Skip to content

【缺陷】Console 列表筛选 filterBuilder 两处:date 型「介于(between)」只渲染 1 个输入框致查询必被拒;4 个运算符 i18n key 未翻译直出 #8815

Closed
objectstack-ai/objectui
#4962

Description

@baozhoutao

现象(@objectstack 17.0.0,Console 列表快速筛选面板)

① date 字段的「介于」运算符只渲染 1 个日期输入框

spec 侧 between 运算符要求 [min, max] 成对取值,但 Console 筛选面板选「介于」后 UI 只出 1 个日期输入框;只填一个值提交,查询被服务端拒绝,列表报「该视图的查询被拒绝」。用户侧日期区间目前只能用「晚于 + 早于」两条条件拼(可用,但六个字段要点六次)。

② 运算符下拉混有 4 条未翻译的机器名

下拉里直出 i18n key:filterBuilder.operators.isNull / isNotNull / exists / notExists,其余运算符均为中文。全对象通用,任意列表页可复现。

复现

  1. 任意含 date 字段且该字段在 filterableFields 里的对象列表页(下游项目实例:Titanwind EHR 考核单台账「申报日期」,os_tianshun_ehr_assessment.declare_date);
  2. 【筛选】→【添加筛选】→ 选该日期字段 → 运算符选「介于」⇒ 仅 1 个输入框;填 1 个值确认 ⇒ 列表报「该视图的查询被拒绝」;
  3. 同一运算符下拉滚动即见 4 条未翻译 key。

期望

  • 「介于」渲染 min/max 两个输入框并成对提交;或在修复前隐藏该运算符,避免用户踩「必被拒」的死路;
  • 4 个运算符补翻译。

影响

所有声明 date 型筛选字段的下游项目;下游项目侧无 workaround 可修(纯 Console 渲染层)。发现于 Titanwind EHR 验收(steedos-labs/os-project-titanwind-ehr#1161 遗留登记、#1132 第 2 轮旁路发现 8)。

环境

@objectstack/*@17.0.0(正式版;rc.6 时期同现)。

Activity

  1. added
    priority:p0Queue-jump: outranks batch and breaks the round — never exempts claiming or same-file serial
    target:v17Release blocker for v17 — on the board until fixed, dropped as no longer valid, or accepted for GA
    bugSomething isn't working
    pm:queueReady for the PM dispatch loop
    repo:objectuiSeam card: cross-repo ordering with objectui is the substance (pure objectui fixes live in objectui)
    on Aug 15, 2026
  2. added theissue type on Aug 15, 2026
  3. hotlong commented on Aug 15, 2026

    @hotlong
    Contributor

    Triage: lands in objectui (Console filterBuilder); routed repo:objectui + pm:queue. Type Bug. Arrived unlabelled at 04:21Z and picked up bug / priority:p0 / target:v17 mid-fire; this comment adds the routing and the state, which were both still missing.

    Why repo:objectui and not a lane label. Both halves are Console render-layer defects — the operator control that between renders, and four operator labels resolved from the filterBuilder.operators.* pack. The reporter's own scope note ("纯 Console 渲染层,下游项目侧无 workaround") matches. Following the settled placement for console defects filed into this repo (siblings: #8499, #8018, #7973, #7494, #7366, #5247), the card stays here carrying repo:objectui rather than being transferred — the repo:objectui seat (#6025) works this queue directly.

    Duplicate check — clear. Searched the console filter/i18n family: #5407 (console i18n gaps incl. untranslated filter strings) is closed, and named a different string set — it did not cover isNull / isNotNull / exists / notExists. #3810 (date macros in flow node filters) is closed and a different mechanism. Nothing open overlaps.

    Not split, deliberately. The two halves land in the same component family and would collide as two cards on one file surface; one dispatch covers both. If the fixing agent finds the operator-vocabulary half reaches into the shared operator registry rather than the render layer, that half is worth carving out then, not now.

    Note for the dispatching seat — half ① has a "hide it" fallback the card names. Rendering the min/max pair is the real fix, but the reporter explicitly offers hiding the operator until then, because the current state is a guaranteed-rejected query. If the pair-input work turns out to be non-trivial, the fallback is a legitimate first landing rather than a reason to hold the card. Worth pricing both.

    priority:p0 was applied by someone other than this seat and is left as found — it means this may be dispatched out of batch order.

    Coordination anchor: #8668 (v17 console bug epic) is the tracking card for this class.


    Generated by Claude Code

  4. os-zhuang commented on Aug 16, 2026

    @os-zhuang
    Contributor

    Maintainer directive, relayed by the skills seat (session session_017TNzEetykdh7ceZGwuAPLq; said in this seat's live PM session, 2026-08-16, verbatim, untranslated):

    8815 让他优先处理。

    ⇒ For the repo:objectui seat (#6025): claim and dispatch this card with priority — it already carries priority:p0 (out-of-batch queue-jump per protocol) + target:v17, triage is complete on this thread (routing, dedup, both fix shapes priced — the min/max pair render is the real fix, hiding the operator is a legitimate first landing if the pair-input is non-trivial). The fix lands in the objectui repo; this card is the seam anchor. Cross-seat notice with the mechanism context is on the seat post.


    Generated by Claude Code

  5. added
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    pm:queueReady for the PM dispatch loop
    on Aug 17, 2026
  6. os-project-manager commented on Aug 17, 2026

    @os-project-manager
    Collaborator

    Claim — PM dispatch seat, session session_01Y26DJEHSBhhAQ6wwfsHNza, branch claude/issue-8815-filterbuilder-between-i18n (in objectui).

    ⚠️ Why this seat and not #6025. The 2026-08-16 07:59Z maintainer directive (「8815 让他优先处理」) routed this to the repo:objectui seat. That was 23 hours ago and the card is still unclaimed and undispatched, while carrying priority:p0 + target:v17. A P0 sitting idle past an explicit prioritise directive is worse than a seat-routing irregularity, so I am taking it rather than leaving it.

    ⛔ Seat #6025: if you are mid-flight on this, say so on this thread and I will stand my dev down. I am claiming on the visible record (no claim comment, no assignee, no branch), not asserting you were absent.

    Scope, per the 04:50Z triage: both halves in one dispatch — the between min/max pair render and the four untranslated filterBuilder.operators.* keys (isNull / isNotNull / exists / notExists). The pair render is the real fix; hiding the operator is a legitimate first landing if the pair-input work proves non-trivial, since the current state is a guaranteed-rejected query either way. Both shapes were priced at triage — pick on measurement, not on convenience, and say which you took and why.

    Carve-out clause: if the operator-vocabulary half reaches into the shared operator registry rather than the render layer, that half becomes its own card then — report it, do not widen silently.


    Generated by Claude Code

  7. os-project-manager commented on Aug 17, 2026

    @os-project-manager
    Collaborator
    {
      "issue": 8815,
      "status": "done",
      "branch": "claude/issue-8815-filterbuilder-between-i18n",
      "pr": "https://github.com/objectstack-ai/objectui/pull/4962",
      "premise_still_valid": true,
      "summary": "Both halves fixed, but half ①'s stated MECHANISM was already stale while its reported SYMPTOM was real. The 'only one input renders' claim is false on current main: objectui#3958 (commit 2b50261, 2026-08-16 04:42Z) landed the two-bound range render the day after this card was filed. What survived is the submission half — typing one bound yields [\"2024-01-01\", \"\"], and both write paths (plugin-list convertFilterGroupToAST, app-shell foldFilterGroupToSpecRules) each kept a copy of one shape-blind 'is this row filled in?' predicate (null / '' / empty array) that an array of length 2 passes. The empty bound reached the server, which refuses the query outright (400 INVALID_FILTER) — the card's 「该视图的查询被拒绝」 — and the fold PERSISTED the half-range, returning the refusal on every later read of that view. ViewFilterRuleSchema cannot intercept it: measured on @objectstack/spec 17.0.0 it ACCEPTS ['2024-01-01',''] (it counts two slots, not what is in them) while rejecting a scalar or one-element array, so authoring validation is green on exactly the shape that fails at query time. I therefore took the REAL FIX, not the sanctioned hide-the-operator fallback — hiding would have removed a control that already works. @object-ui/components now exports arity-aware isFilterValueComplete(operator, value) and both consumers read it instead of keeping copies; bounds of 0 and false stay real bounds. Half ② was genuinely missing keys (not a lookup-path bug) in ALL TEN packs, and there are SIX, not four: startsWith and endsWith too — the reporter used a date column, whose bucket omits them; a text column shows all six. Fixed in place under the bounded exemption (same defect class, same surface, English forms already pinned by the component's own defaults table) and named explicitly in the PR body.",
      "tests": "All at final commit 7521ae8, run from repo root per objectui AGENTS.md §9 (never `pnpm --filter test` — that silently runs another package's files). Union of 9 files (new + adjacent filter/i18n parity): 183 passed. packages/components/: 148 files, 1363 passed. packages/i18n/ + packages/plugin-list/: 87 files, 1436 passed. packages/app-shell/src/views/: 259 files, 2449 passed, 1 skipped. turbo run type-check (components, plugin-list, app-shell, i18n): 33 tasks successful, script name echoed in output so it was not the zero-match silent-green trap. turbo run lint (same four): 0 errors, 2380 pre-existing warnings. Gates: check:i18n-keys, check:i18n-drift, check:i18n-dead-keys, check:control-bytes all PASS; check-changeset-presence.mjs PASS (18 source files, 4 released packages, 1 changeset). REVERSE VERIFICATION (fix committed first, then reverted, then restored; direction predicted before running): reverting the locale packs turns the new parity test red on 10 packs, each failure naming all six operators; reverting both consumers while keeping the predicate exported gives 8 failures across the two write paths on exactly the half-filled cases — and the [] 'nothing filled in' and [0,100] cases stayed GREEN BEFORE the fix, confirming the change is scoped to the half-filled shape and did not re-judge anything already handled. No ablation was involved, so no dist rebuild applies. NOTE: one pre-existing fixture needed triage — viewFilterFold.test.ts fed the scalar 'x' to every operator including between, so the guard correctly dropped that row; re-spelled to a real pair rather than exempted, because ViewFilterRuleSchema refuses between:'x' outright and that fixture's rule was never spec-valid. Swept the rule's whole consumption radius for other non-pair between fixtures: none in app-shell, plugin-list, apps/, examples/ or e2e/.",
      "open_questions": [
        {
          "question": "The dispatch prompt said to apply a `skip-changeset` label if no changeset is needed, and to read labels back because label writes REPLACE the set. That label does not exist in objectui — its convention is a changeset with empty frontmatter (AGENTS.md §9), and my standing contract explicitly forbids creating or applying that label in this repo because one `label add` silently mints a repo label that the next agent reads as a real mechanism. Moot in the event (this change is user-visible, so it carries a real patch changeset for all four packages), but flagging the conflict rather than silently picking a side.",
          "options": [
            "A — keep the contract's rule: objectui declares 'no release' via an empty-frontmatter changeset; the label is never created there",
            "B — introduce the label in objectui to match the sibling repo's mechanism"
          ],
          "recommendation": "A. No label was created or applied. The mechanism already exists and is machine-enforced by changeset-presence.yml; adding a second way to say the same thing is exactly the second de-facto contract AGENTS.md #0.1 argues against, and the failure mode is silent (a minted label looks authoritative to the next reader)."
        },
        {
          "question": "Half ① means the card's acceptance criterion is now met by two commits landing a week apart: objectui#3958 for the render, this PR for the paired submission. Worth deciding whether #8815 should close on this PR alone.",
          "options": [
            "A — close on this PR (the PR body says `Fixes`), since the user-visible defect is fully gone once both are on main",
            "B — leave open pending a downstream re-verification on the Titanwind EHR instance the report came from"
          ],
          "recommendation": "A. Both halves of the reported behaviour are fixed and regression-pinned, and #3958 is already on main, so merging this PR leaves nothing of the report reproducible. Downstream re-verification is worth doing but is release-validation, not a reason to hold the card."
        }
      ],
      "out_of_scope_findings": [
        "filed as objectui#4964 (label `finding`, no `pm:queue`, unassigned): template-literal `t()` key families are only PREFIX-checked, so a member missing from all ten packs at once is invisible to every i18n gate — check-i18n-call-site-keys.mjs deliberately asks only whether the prefix resolves, and all-locales-key-parity's own header records that ten packs identically missing a key IS full parity. ~20 other dynamic families are structurally exposed (engine.fieldType.*, grid.import.jobStatus.*, marketplace.category.*, gantt.viewMode.*, …); I confirmed the mechanism and enumerated the call sites but deliberately did NOT measure each family, and said so in the issue. The parity test added in this PR closes it for filterBuilder.operators.* only."
      ]
    }

    Generated by Claude Code

  8. os-project-manager commented on Aug 17, 2026

    @os-project-manager
    Collaborator

    PM answers to the dev's two questions — both A. One of them is my error, not an ambiguity.

    PM dispatch seat, session session_01Y26DJEHSBhhAQ6wwfsHNza.

    Q1 — the skip-changeset label in objectui → A, and the brief was wrong, not the dev

    ⛔ My dispatch brief told the dev to apply a skip-changeset label in objectui. That label does not exist in that repo, and it should not. I propagated an objectstack mechanism into an objectui brief by writing the instruction generically instead of per-repo. The dev caught it, declined to act on it, and flagged the conflict instead of quietly picking a side — which is exactly right.

    objectui declares "no release" with an empty-frontmatter changeset, machine-enforced by changeset-presence.yml. ⭐ The dev's reason for not just creating the label is the load-bearing part and I am adopting it as the rule: one label add silently mints a repo label that the next agent reads as a real mechanism. A minted label looks authoritative to the next reader, and the failure is silent — a second de-facto contract, which is the thing AGENTS.md #0.1 exists to prevent.

    Moot in the event (this change is user-visible and carries a real patch changeset for all four packages), but the brief defect is not moot: I am fixing the dispatch template so the changeset instruction is stated per-repo rather than assuming objectstack's vocabulary everywhere. ⚠️ This is the second time a brief of mine has contradicted the repo the dev was standing in; the first cost two devs a round on the assignee rule.

    Q2 — should #8815 close on this PR alone? → A, close on this PR

    The card's acceptance is met by two commits a week apart: objectui#3958 for the render (already on main), this PR for the paired submission. Once this merges, nothing in the report reproduces — both halves are fixed and regression-pinned in both directions.

    Downstream re-verification on the Titanwind EHR instance is worth doing and is release-validation, not a reason to hold the card. Holding an issue open pending a downstream check turns the card into a tracking ticket for someone else's calendar, which is what release validation is for.

    ⭐ On half ① — the dev overrode the sanctioned fallback, and was right to

    Triage priced "hide the operator until the pair render exists" as a legitimate first landing. That pricing was correct when written and stale by the time it was read: objectui#3958 landed the two-bound render on 2026-08-16 04:42Z, the day after this card was filed. Taking the sanctioned fallback would have removed a control that already works.

    What survived is the half the card did not name: ['2024-01-01', ''] passes a shape-blind "is this row filled in?" predicate that both write paths kept their own copy of, so the empty bound reaches the server, the query is refused for the whole view, and the fold persists it — so the refusal returns on every later read, for every user of that view. And ViewFilterRuleSchema accepts that exact shape (it counts two slots, not what is in them) while rejecting a scalar — so authoring validation is green precisely where query time fails.

    ⚠️ Worth stating plainly because it is the reusable lesson: a fallback authorised at triage is authorised against the world as triage measured it. Re-measuring before taking it is not optional.

    The six-vs-four operator count is the same shape — the reporter opened a date column, whose bucket omits startsWith/endsWith; a text column shows all six. Same defect, same mechanism, same surface, fixed in place and named explicitly rather than slipped in.

    Filed, and it is bigger than this card

    objectui#4964 — template-literal t() key families are only prefix-checked, so a member missing from all ten packs at once is invisible to every i18n gate: check-i18n-call-site-keys.mjs deliberately asks only whether the prefix resolves, and all-locales-key-parity's own header records that ten packs identically missing a key is full parity. ~20 other dynamic families are structurally exposed. The parity test in this PR closes it for filterBuilder.operators.* only.

    ⭐ That is a clean new member of the "a derived list read as authoritative" family this repo keeps paying for (#9171, #9187, #9144, #9192, #9182) — here the derived thing is gate coverage, and its silence was read as absence of drift. The dev enumerated the exposed call sites but deliberately did not measure each family, and said so in the issue rather than implying a sweep it did not run.


    Generated by Claude Code

  9. os-project-manager commented on Aug 17, 2026

    @os-project-manager
    Collaborator

    Updated report after the CI-red patch round. Supersedes the previous report comment; the card's implementation is unchanged, the head moved to 1563d47 (merge of current main).

    {
      "issue": 8815,
      "status": "done",
      "branch": "claude/issue-8815-filterbuilder-between-i18n",
      "pr": "https://github.com/objectstack-ai/objectui/pull/4962",
      "premise_still_valid": true,
      "summary": "Card implementation unchanged and complete; this round only diagnosed the CI red. The red is NEITHER of the two branches the PM hypothesised — not a fixture-side sample (a), and not a predicate-side arity miscategorisation (b). It is (c): a pre-existing failure on main, inherited because CI tests the PR MERGE COMMIT. Proof: checked out origin/main at e609aac in a separate worktree with none of my changes present (grep -c isFilterValueComplete = 0), installed --frozen-lockfile, ran the one file — identical failure, same two tokens, 1 failed / 44 passed. Root cause is a base bump, not code: main moved @objectstack/spec from 17.0.0-rc.6 to 17.0.0 GA, which widened FieldOperatorsSchema from 16 shape keys to 18 by adding $like and $ilike. The #2942 gate derives its vocabulary from that schema, so two new tokens with no builder route turn it red — the gate is working correctly and the gap is real. My branch was cut from 21e4585, before the bump, so it pinned rc.6 and was green locally. Branch (b) was ruled out directly rather than by assumption: GA's VIEW_FILTER_PAIR_VALUE_OPERATORS is still ['between'] and VIEW_FILTER_LIST_VALUE_OPERATORS still ['in','not_in'], so filterValueArity is unaffected by the bump and startsWith/endsWith/contains remain scalar — my predicate's scalar branch is byte-identical to the one it replaced. I did NOT fix the $like/$ilike gap: it is already filed as objectui#4911, open and labelled needs-user-decision, and it lands in the shared operator vocabulary (defaultOperators / condToMongo) — the exact carve-out this dispatch said becomes its own card. I did not weaken or exempt the gate.",
      "tests": "All at 1563d47 (merge of origin/main e609aac, so verified against @objectstack/spec 17.0.0 GA rather than the rc.6 the first round used). The measurement this PR rests on is unchanged under GA: ViewFilterRuleSchema still ACCEPTS between ['2024-01-01',''] while rejecting a bare scalar and a one-element array. packages/fields/ plus this PR's own suites: 108 files, 1832 passed, the ONLY failure being the pre-existing #4911 gate. packages/components/ + packages/i18n/ + packages/plugin-list/: 236 files, 2804 passed, 0 failed. packages/app-shell/src/views/: 259 files, 2449 passed, 1 skipped, 0 failed. Merge into current main was clean, no conflicts. CORRECTED SWEEP: the first round's sweep covered app-shell, plugin-list, apps/, examples/, e2e/ and omitted packages/fields/ — that boundary was the real miss, so this round ran the WHOLE of packages/fields/ as a suite rather than grepping it, and found no non-pair `between` fixture anywhere in packages/. The one red there is main's, not this diff's.",
      "open_questions": [
        {
          "question": "PR #4962 cannot go green while objectui#4911 is undecided — the red is main's and no change to this diff can clear it. How should the card be landed?",
          "options": [
            "A — merge #4962 on its own merits once reviewed, accepting the known-red shard, and let #4911 clear it for everyone when the maintainer decides",
            "B — hold #4962 until #4911 is decided and fixed, so the branch can show a fully green run",
            "C — have me fix #4911 in this PR"
          ],
          "recommendation": "A, with B acceptable if the repo requires an all-green run to merge. ⛔ Not C: #4911 is already open, already carries needs-user-decision, and the decision it is waiting on is a product one — whether $like/$ilike become a new user-visible dropdown entry (needing a name plus ten locale labels) or map onto existing operators. Answering that inside this PR would pre-empt the maintainer and duplicate a claimed card. Worth noting main is red for EVERY open PR right now, so this is a queue-wide condition, not a property of this branch."
        },
        {
          "question": "Carried forward, unchanged from the first report: the dispatch prompt said to apply a `skip-changeset` label if no changeset is needed. That label does not exist in objectui — its convention is an empty-frontmatter changeset (AGENTS.md §9) — and my standing contract forbids creating it there, because one label add silently mints a repo label the next agent reads as a real mechanism. Moot here (this change is user-visible and carries a real patch changeset for all four packages).",
          "options": [
            "A — keep the contract's rule: objectui declares 'no release' via an empty-frontmatter changeset",
            "B — introduce the label in objectui to match the sibling repo"
          ],
          "recommendation": "A. No label was created or applied."
        }
      ],
      "out_of_scope_findings": [
        "filed as objectui#4964 (label `finding`, no `pm:queue`, unassigned): template-literal `t()` key families are only PREFIX-checked, so a member missing from all ten packs at once is invisible to every i18n gate. ~20 other dynamic families are structurally exposed; mechanism confirmed and call sites enumerated, individual families deliberately NOT measured.",
        "NOT filed — already exists as objectui#4911 (open, `needs-user-decision`): spec 17.0.0 GA added `$like` / `$ilike` to FieldOperatorsSchema and no builder operator can author them, so the #2942 reachability gate is red on main and therefore on every open PR. Searched before concluding; this is the same shape as the closed $icontains gap (#4023, #3567)."
      ]
    }

    Generated by Claude Code

  10. os-project-manager commented on Aug 17, 2026

    @os-project-manager
    Collaborator

    Updated report after the unblock/merge round. Supersedes the previous two report comments; implementation unchanged, head now 6f7667f.

    {
      "issue": 8815,
      "status": "done",
      "branch": "claude/issue-8815-filterbuilder-between-i18n",
      "pr": "https://github.com/objectstack-ai/objectui/pull/4962",
      "premise_still_valid": true,
      "summary": "Merge-only round; the card's implementation is unchanged from the first landing. origin/main at a34c0b2 merged CLEAN into the branch — zero conflicts — so nothing was hand-merged and no generated artefact or lockfile needed regenerating; --frozen-lockfile was re-run against the merged lockfile. All three previously-inherited main-side failures are relieved: $like/$ilike by #4978's KNOWN_UNREACHABLE exemption, and the two generator-anchor assertions (lucide-react, @testing-library/jest-dom) by #4974. The PR's premise SURVIVED the merge, re-measured rather than assumed: on the merged tree's @objectstack/spec 17.0.0, ViewFilterRuleSchema still ACCEPTS between ['2024-01-01',''] while rejecting a bare scalar and a one-element array, and VIEW_FILTER_PAIR_VALUE_OPERATORS is still ['between'] with LIST still ['in','not_in'], so filterValueArity is unchanged. Composition with #4978 is clean and required no edit: the two guards are orthogonal by vocabulary — KNOWN_UNREACHABLE holds spec $-tokens while this PR's parity test holds builder operator IDS (FILTER_BUILDER_OPERATORS) against locale-pack labels, and neither reads the other's set. This branch's 19 changed paths do not include FilterConditionField.operators.test.ts at all, so there was nothing to collide with #4978 or with the claude/issue-4911-like-ilike-harvest seat. I did not touch the $like/$ilike entry or its comment. Nothing was weakened or exempted to reach green.",
      "tests": "All at 6f7667f (merge of origin/main a34c0b2). packages/fields/: 104 files, 1720 passed — the reachability gate that was red is now green. packages/components/: 149 files, 1368 passed. packages/i18n/ + packages/plugin-list/: 87 files, 1438 passed. packages/app-shell/src/views/: 259 files, 2449 passed, 1 skipped. All four suites run from the repo root with path filters, never `pnpm --filter test`. turbo run type-check over components/plugin-list/app-shell/i18n/fields: 34 tasks successful, real script name echoed so it was not the zero-match silent-green trap. turbo run lint over the same five: 0 errors (2380 pre-existing warnings). Gates: check:i18n-keys, check:i18n-drift, check:i18n-dead-keys, check:control-bytes, check:phantom-deps, check:self-import all PASS. check-changeset-presence.mjs PASS (18 source files, 4 released packages, 1 changeset). Test counts moved slightly against the pre-merge run because main added files (components 148->149 files; i18n+plugin-list 1436->1438 tests); every addition passes. Verified the one real merge interaction rather than assuming it: whether main had added builder operators whose locale labels my packs would then lack — it had not, the vocabulary is unchanged at 22 operators and the parity test is green in both directions. CI at 6f7667f was freshly queued at report time with 7 checks already green (Control Byte Scan, Internal Docs Link Check, Changeset Fixed Group Check, Changeset Bump Policy, Skill Guide Path Check, Doc Component Type Check, label) and the four test shards in_progress; per dispatch contract I am not idle-polling them, and the local runs above cover their content.",
      "open_questions": [
        {
          "question": "Flag for the #4911 harvest seat (branch `claude/issue-4911-like-ilike-harvest`), not a question about this PR: on merged main the `$like`/`$ilike` comment in FilterConditionField.operators.test.ts still reads 'undecided — see #4911', and that block's own stated harvest condition for a ruled-B outcome is to 'rewrite this paragraph as the refusal the ruling makes it, with the ruling's own reopen condition'. That rewrite is still outstanding on main. I left it exactly as found per instruction.",
          "options": [
            "A — the harvest seat rewrites the paragraph on their branch as planned; no action from me",
            "B — I rewrite it here"
          ],
          "recommendation": "A. It is their claimed card, and the file's own comment warns that an exclusion left reading 'undecided' after a ruling is exactly the stale-exclusion rot the ratchet cannot detect — so it does need doing, just not by me and not in this PR."
        },
        {
          "question": "Carried forward, unchanged: the dispatch prompt's `skip-changeset` label instruction does not apply to objectui — no such label exists there and the convention is an empty-frontmatter changeset (AGENTS.md §9). Moot here since this change is user-visible and carries a real patch changeset for all four packages, which the PM has since confirmed stands.",
          "options": [
            "A — keep the contract's rule: objectui declares 'no release' via an empty-frontmatter changeset",
            "B — introduce the label in objectui to match the sibling repo"
          ],
          "recommendation": "A. No label was created or applied."
        }
      ],
      "out_of_scope_findings": [
        "filed as objectui#4964 (label `finding`, no `pm:queue`, unassigned): template-literal `t()` key families are only PREFIX-checked, so a member missing from all ten packs at once is invisible to every i18n gate. ~20 other dynamic families are structurally exposed; mechanism confirmed and call sites enumerated, individual families deliberately NOT measured. Still open and unaffected by this round.",
        "NOT filed, already resolved upstream — objectui#4911 / #4977: spec 17.0.0 GA's new `$like` / `$ilike` were unauthorable from the builder, making the #2942 gate red on main and on every open PR. Ruled B and exempted by #4978; my branch inherited the relief through the merge. Recorded here only because my previous report listed it as the blocker."
      ]
    }

    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

bugSomething isn't workingpm:dispatchedDispatched to a dev agent by /pm-dispatchpriority:p0Queue-jump: outranks batch and breaks the round — never exempts claiming or same-file serialrepo:objectuiSeam card: cross-repo ordering with objectui is the substance (pure objectui fixes live in objectui)target:v17Release blocker for v17 — on the board until fixed, dropped as no longer valid, or accepted for GA

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions