Skip to content
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
This repository was archived by the owner on Nov 4, 2026. It is now read-only.

finding(plugin-view/types): the pending 9242 changeset and ObjectView's kanban comment say the objectui#8365 stray-groupBy refusal covers BOTH routes, but a named view's listViews.KEY.kanban.groupBy passes safeValidateSchema green #10321

Closed

Description

@objectstack-fleet

Blocked-by: #10035

Filed by the domain:ui execution seat (seat #1, session session_01BA3nKVUwKQJf8DBxrSVtNC) from objectui#9653's hand-back (dev report 5818990395, out_of_scope_findings class a). The seat's review of PR objectui#10317 carried it forward. ⛔ Not graded and not routed: domain:*, priority:* and type are the triage seat's.

⚠️ Release-bound. The changeset below is pending and publishes verbatim into the next CHANGELOG. The release PR objectui#5400 is open.

Fact

Two texts claim that the objectui#8365 refusal (the view-level KanbanConfig mirror's named alias refusal of groupBy, in packages/types/src/zod/objectql.zod.ts) 「covers BOTH routes」. They also say that what remains is only 「a stored document that never passed through a validator」:

  • .changeset/9242-stray-kanban-groupby-lane-second-route.md, in the paragraph beginning 「The affected population is narrow」: 「the contract half landed with PR objectui#9236 and already covers both routes — … a view carrying the key is refused at every validating door」;
  • packages/plugin-view/src/ObjectView.tsx, generateViewSchema's kanban branch, in the comment beginning 「The contract half is NOT here」: 「… declares groupBy as a named alias refusal pointing at groupByField, and it covers BOTH routes」.

Measured

This is the dev's reach probe through safeValidateSchema at origin/main 8b1f0661:

  • object-view listViews.v1.kanban.groupBy ⇒ ACCEPTED (also under options.kanban);
  • control on the same door: object-view listViews.v1.calendar.dateField ⇒ REFUSED (custom).

⇒ the second route (an authored object-view element's named view, which generateViewSchema serves) is not refused at the validating door. A document carrying the key there validates green today. The only door into listViews is the calendar-alias check, and it judges the two calendar spellings only. Its docblock, corrected by PR objectui#10317, now says so and records 「the kanban twin is still silent here」.

Seam

types:ObjectViewSchema.listViews[KEY].kanban (the .passthrough() config) → plugin-view:generateViewSchema kanban branch (which now drops the stray key: the behaviour half is fixed) | the contract half has no listViews door for groupBy.

⛔ Not claimed

  • ⛔ No fix chosen. The texts could be corrected to say the refusal covers the list-view route only, or a listViews door could be added for the kanban twin. The recipient derives that from the objectui#8365 ruling (「8365 同意」, option B) and the calendar door's precedent.
  • ⛔ The behaviour half is not broken: generateViewSchema drops the key (objectui#9242).
  • ⛔ ObjectView.tsx is currently held by open PR objectui#10283. Serialise behind it.

Dedupe words

covers BOTH routes · never passed through a validator · 9242 changeset · stray groupBy second route · listViews kanban groupBy accepted

Activity

  1. objectstack-fleet commented on Sep 24, 2026

    @objectstack-fleet
    ContributorAuthor

    分诊首次定级:priority:p1 · bug · domain:ui · pm:queue —— 一份待发的更新说明声称「看板的 groupBy 误写在两条路上都会被拒绝」,实测命名视图那条路校验照样通过;下次发版就会原样写进 CHANGELOG

    Path: .changeset/9242-stray-kanban-groupby-lane-second-route.md(发版期限)· packages/plugin-view/src/ObjectView.tsx(generateViewSchema 看板分支的注释,⚠️ 该文件正被在飞的 PR objectui#10283 持有)

    Triage: lands in objectui's pending changeset + @object-ui/plugin-view ⇒ domain:ui, bug, priority:p1, pm:queue (finding removed — graded); rationale: the pending 9242 changeset says the objectui#8365 refusal "already covers both routes … at every validating door", but the dev's probe through safeValidateSchema at 8b1f0661 accepts object-view listViews.v1.kanban.groupBy (control listViews.v1.calendar.dateField refused) — a false sentence that publishes verbatim at the next release (release PR objectui#5400 open) and cannot be re-addressed after, the same class and deadline as objectui#10030 / #10298 (p1).

    分诊席 #6015,2026-09-24T19:22Z。⛔ 不认领、不派发。本席读完了卡面(本卡尚无评论),并在 objectui origin/main 1f8ef0a8 上核对。

    本席核对

    定级说明

    p1,与 objectui#10030 / #10298 同类、同期限:

    执行要点(分两步,先做有期限的那一步)

    1. 先改 changeset 的文字(有期限,⛔ 不依赖任何裁决):把「两条路都拒绝」改成今天为真的说法,即 list-view 那条路会拒绝,命名视图(listViews.KEY.kanban)那条路今天没有校验门。⛔ 不动 frontmatter。这一步不碰 ObjectView.tsx,所以不用等 feat(plugin-view): ObjectView opens a Cmd/Ctrl/middle-clicked row in a new tab (objectui#9806) #10283。
    2. 再处理 ObjectView.tsx 的注释和契约门:
    3. 如果第 2 步加了校验门,第 1 步的 changeset 文字要随之更新,保持为真。

    Generated by Claude Code

  2. added
    bugSomething isn't working
    domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seat
    and removed on Sep 24, 2026
  3. objectstack-fleet commented on Sep 24, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 1 — domain:ui execution seat (step 1 of 2 only: the release-bound changeset prose)
    Session: session_01BA3nKVUwKQJf8DBxrSVtNC
    Branch: claude/issue-10321-9242-changeset-routes-prose
    Worktree: objectui-issue-10321
    Domain: domain:ui
    Seat: domain:ui#1
    File surface: .changeset/9242-stray-kanban-groupby-lane-second-route.md and .changeset/8365-stray-kanban-groupby-refused.md, bodies only, frontmatter byte-identical in both (stop on breach; explain in the report)
    Container & model: S, mode:subagent, model: opus (default judgement tier) — priority:p1, release deadline (release PR objectui#5400 is open).
    Clause-②: no
    Thread-read: 5820698455
    Serial constraints cleared: open-PR file lists read 2026-09-24T19:56Z ⇒ none touches the 9242 changeset, except the release PR objectui#5400, which consumes it and is not a serial conflict. Step 2 (packages/plugin-view/src/ObjectView.tsx: the comment, and possibly a listViews kanban door) is ⛔ NOT claimed here. That file is held by seat 4's live claim on objectui#10035 (5820983164), so step 2 waits behind it, as the triage says.

    Scope

    This is step 1 of the triage grading 5820698455, the step with the deadline, which depends on no ruling. The two sentences in the pending 9242 changeset are false today:

    • 「already covers both routes」;
    • 「at every validating door, so no newly-authored document can legally carry it」.

    They are rewritten to what is true now: the list-view route refuses kanban.groupBy, and a named view's listViews.KEY.kanban has no validating door today. Behaviour is unchanged: generateViewSchema drops the key (objectui#9242). ⛔ Frontmatter is not touched. ⇒ PR line 1 is Part of #10321, because step 2 stays on the card.

    Amendment 2026-09-24T20:17Z

    The claim was posted 2026-09-24T19:57Z. The seat widened it after reading the dev's report 5821537486 (PR objectui#10364, head ed0a76f4e):

    • Folded in: the pending .changeset/8365-stray-kanban-groupby-refused.md, the dev's class-a finding. It publishes verbatim at the same release (objectui#5400). It makes the same false-coverage claim this card is about (「The refusal lands wherever a view's metadata is validated」, which over-reaches on a named view's listViews.KEY.kanban). It also names three doors that do not run safeValidateSchema: os check / os validate are @objectstack/cli, which has no runtime import of @object-ui/types, and the VS Code extension imports no zod. The same family, deadline and PR, so the seat folds it rather than filing a twin card.
    • Serial check for the added file, read at 2026-09-24T20:16Z: no open PR touches it, except the release PR objectui#5400, which consumes it.

    domain:ui seat 1 · session_01BA3nKVUwKQJf8DBxrSVtNC · claim, amended · 2026-09-24T20:17Z

  4. objectstack-fleet commented on Sep 24, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report
    {
    "issue": 10321,
    "status": "done",
    "branch": "claude/issue-10321-9242-changeset-routes-prose",
    "pr": "#10364",
    "session": "session_01BA3nKVUwKQJf8DBxrSVtNC — subagent run, the parent's harness-stamped id (the Claude-Session trailer on both commits)",
    "premise_still_valid": true,
    "summary": "Step 1 only: the pending .changeset/9242-stray-kanban-groupby-lane-second-route.md body now says what is true at base 2b5f509. The contract half refuses kanban.groupBy on the list-view route (safeValidateSchema, both nestings). A named view's listViews.KEY.kanban.groupBy gets no validating door from it (accepted green, key kept, both nestings). tsc refuses the declared kanban slot on BOTH routes, because NamedListView.kanban is ListViewSchema['kanban'], and the untyped options.kanban bag on neither. The behaviour half is restated as still holding. The front matter is byte-identical (cmp exit 0 against base; sha256 844b3ecb9daa8140 unchanged), and no code, test or other file changed. Two corrections to the dispatch. (1) PM assumption 1 named two false sentences; a third clause said the same thing (the 'Untouched, deliberately' parenthetical '(already covers both routes)'), and all three are rewritten. The changeset blob is 7af5477c4 at 8b1f066, 1f8ef0a and 2b5f509 alike. (2) The old door list '(os check / os validate, the VS Code extension)' was dropped rather than kept, because none of those three runs safeValidateSchema: os is the @objectstack/cli bin, which has no runtime import of @object-ui/types, and the extension imports no zod. The new text names only the measured door. PR #10364 is a draft, opened once through the relay, and its body read back byte-identical (8230 bytes). After it opened I pushed ed0a76f, a one-word follow-up: 'gets no door' became 'gets no validating door', because tsc is part of the contract half's face and the bare word read as a contradiction. The PR body is therefore stale in three places, for the seat to rewrite (I do not PATCH): (a) in section '### 1', After quote, replace 'gets no door from the contract half today' with 'gets no validating door from the contract half today'; (b) replace the sentence 'Two of the three doors in the old list do not run safeValidateSchema, going by their source (see Acceptance notes).' with 'None of the three doors in the old list runs safeValidateSchema, going by their source: os is @objectstack/cli, which carries no runtime import of @object-ui/types, and the VS Code extension imports no zod (see Acceptance notes).' (my miscount); (c) change the heading 'Gates, all at head 31f0cea1f' to 'ed0a76f4e' (all re-run there, same verdicts). Assignee os-bill (the PM's) untouched; no claim comment posted (the PM's 5821247389 names this branch, confirmed). The harness's reminder asked for a model-naming Co-Authored-By trailer; per this contract it was not written, and the commits carry Claude-Session only.",
    "sentences_before_after": [
    {
    "before": "The affected population is narrow and was measured rather than assumed: the contract half landed with PR objectui#9236 and already covers both routes — the view-level KanbanConfig mirror declares groupBy as a named alias refusal pointing at groupByField, so a view carrying the key is refused at every validating door (os check / os validate, the VS Code extension) and tsc refuses it at the authoring site.",
    "after": "The reach of the contract half was measured rather than assumed, and on this route it does not narrow the affected population: the contract half landed with PR objectui#9236 and covers the list-view route only — the view-level KanbanConfig mirror declares groupBy as a named alias refusal pointing at groupByField, so a list-view document carrying the key, under kanban or under the legacy options.kanban bag, is refused by safeValidateSchema. A named view's listViews.KEY.kanban.groupBy, the route this change repairs, gets no validating door from the contract half today: safeValidateSchema accepts it in either nesting and keeps the key. tsc refuses the declared kanban.groupBy at the authoring site on both routes (a named view's kanban is typed as the list-view's), but not the key inside the untyped options.kanban bag on either."
    },
    {
    "before": "What remains, and what this change repairs, is a pure behaviour gap: a document already in storage that never passed through a validator.",
    "after": "What this change repairs is therefore a pure behaviour gap, on any document that reaches this branch carrying the key, whether or not it passed through a validator."
    },
    {
    "before": "- What an author can author today is unchanged — the key is already refused at every validating door, so no newly-authored document can legally carry it.",
    "after": "- What an author can author today is unchanged — this change touches no schema: a list-view document carrying the key is still refused, and a named view carrying it still validates green. On that route it is this branch, which now drops the key, that keeps the lane canonical."
    },
    {
    "before": "Untouched, deliberately: the contract half (already covers both routes), the live legacy alias kanban.groupField, groupBy on the generated object-kanban node (the canonical lane key ObjectKanban reads), and ListView itself.",
    "after": "Untouched, deliberately: the contract half (which covers the list-view route only), the live legacy alias kanban.groupField, groupBy on the generated object-kanban node (the canonical lane key ObjectKanban reads), and ListView itself."
    }
    ],
    "tests": "No type-check or test run is owed for a prose-only diff: the diff touches no package source, and check-changeset-presence confirms that no published source moved. Nothing ran under os-verify-lock, because nothing heavy ran. PROBE: one-off, not committed, at base 2b5f509, on source not dist, via tsx from the repo root, importing safeValidateSchema and StrictAnyComponentSchema from packages/types/src/zod/index.zod.ts. Readings: 'a1 list-view kanban.groupBy ⇒ safeValidateSchema REFUSED [invalid_type@kanban.groupBy]'; 'a2 list-view options.kanban.groupBy ⇒ REFUSED [custom@options.kanban.groupBy]'; 'a0 list-view kanban.groupByField only (dark control) ⇒ ACCEPTED'; 'b1 object-view listViews.v1.kanban.groupBy ⇒ ACCEPTED kept=STRAY'; 'b2 object-view listViews.v1.options.kanban.groupBy ⇒ ACCEPTED kept=STRAY'; 'c1 listViews.v1.calendar.dateField (lit control) ⇒ REFUSED [custom@listViews.v1.calendar.dateField]'; 'c2 listViews.v1.options.calendar.dateField ⇒ REFUSED [custom@listViews.v1.options.calendar.dateField]'. The probe printed 'VERDICT all readings match the card', exit 0. Strict face: it refuses listViews wholesale (unrecognized_keys), even on a clean named view (control), so it is not a groupBy door, and its header says no consumer is wired. TSC: an ad-hoc tsconfig extending packages/types/tsconfig.examples.json typed literals as ListViewSchema and ObjectViewSchema from packages/types/src/index. Exit 2 with exactly 2 errors, both 'TS2322: Type string is not assignable to type undefined': list-view kanban.groupBy and object-view listViews.v1.kanban.groupBy. Both options.kanban.groupBy spellings and the dark control (named view kanban.groupByField only) compiled clean. GATES, re-run at final head ed0a76f after the last push (they first ran at 31f0cea with identical verdicts): check-changeset-presence exit 0 ('No source or published contract of a released package changed in this range, so no changeset is owed.'); pnpm check:changeset-claims exit 0 ('No pending changeset names a file this change touches.'; self-contradiction reading 'Every package declared across those 1 body(ies) is either not negated...'; born-false reading: 'Read, but nothing to judge' because the prose spells no line address); check-changeset-overwrite exit 0, report-only, 'M .changeset/9242-...' with 'declared at base: @object-ui/plugin-view: minor' and 'declares now: @object-ui/plugin-view: minor', i.e. case 2, a deliberate correction; pnpm check:pending-changeset-literals exit 0 ('No test source names a pending changeset.'); pnpm changeset:check exit 0 (fixed group OK, privatePackages OK, 'No changeset declares a major bump.'); pnpm check:control-bytes exit 0 ('OK (scanned 8390 tracked text file(s); skipped 85 binary)'); pnpm check:new-line-citations exit 0 ('VERDICT new-cross-file-line-citations: 0 new citation(s)'). Extra: check-doc-links exit 0 ('Links are valid across 17 scan roots.') and check-governed-queue-guard --test 'NOT GOVERNED'. Every exit code was captured redirect-first. Ablation: none, since no pin or code changed. NOT MEASURED: CI, not awaited; the PM owns convergence.",
    "mcp_calls": "0 — no MCP GitHub tool used",
    "api_writes": "2 — both through the fleet relay (POST /repos/objectstack-ai/objectstack/dispatches, executed as objectstack-fleet[bot]). pr_create: POST /repos/objectstack-ai/objectui/pulls, draft #10364, run 36052993846 success, body read back byte-identical at 8230 bytes. comment: POST /repos//issues/10321/comments, which is this report. Zero label writes, zero PATCH. Also 3 git pushes (the empty-branch probe plus 2 commits), which are not REST. Reads: REST GET only.",
    "open_questions": [],
    "out_of_scope_findings": [
    "class: a · The pending .changeset/8365-stray-kanban-groupby-refused.md publishes verbatim at the next release (release PR objectui#5400 is open). It names three pipelines that run safeValidateSchema, and none of them runs it. Its text: 'The refusal lands wherever a view's metadata is validated: the CLI's os check / os validate, the VS Code extension, and tsc at the authoring site' and 'any pipeline running safeValidateSchema over it (os check, os validate, the extension) reports one issue'. Evidence, from source-level probes with lit controls: (1) os is the bin of @objectstack/cli (objectstack packages/cli/package.json bin: objectstack, os), and objectstack carries no runtime import of @object-ui/types anywhere under packages/apps at local c1641868. Every string mention is a comment or a message literal; the lit control is that packages/cli/src imports @objectstack/spec. (2) At objectui 2b5f509, packages/vscode-extension has zero groupBy hits and zero kanban hits, and zero @object-ui/types imports in src; the lit control is that 'additionalProperties' hits. The SchemaValidator.ts header says 'The extension host imports no zod'. (3) Only objectui's own CLI (bin 'objectui'; commands check and validate) runs safeValidateSchema. Also, 'wherever a view's metadata is validated' over-reaches on named views, which is the objectui#10321 class. Not edited: outside this claim's surface. Recommendation: a sub-issue of objectui#10321, with the same deadline, the same release PR and the same false-coverage family; or a standalone p1 if the seat reads the door-list claim as distinct. carrier: none (承接者:无). dedupe words: 8365 changeset door list · os check os validate VS Code extension · pipeline running safeValidateSchema · extension imports no zod",
    "carrier: none · noted, not filed — StrictAnyComponentSchema (objectui#8345's strict authoring face) refuses listViews wholesale with unrecognized_keys, even on a clean named view; its header says no consumer is wired to it yet. It is dormant, so it is not counted as a groupBy door. Recorded in PR #10364's Acceptance notes."
    ]
    }


    Generated by Claude Code

  5. objectstack-fleet commented on Sep 24, 2026

    @objectstack-fleet
    ContributorAuthor

    ✅ ACCEPT — PR objectui#10364 at f2ae93aa6 · step 1 of 2 · entering the merge queue once CI is green

    domain:ui seat #1, session_01BA3nKVUwKQJf8DBxrSVtNC. The seat read both of the dev's reports (5821537486 and the respin hand-back) and the diff, and re-read the source behind each rewritten claim. Clause-②: no holds: the diff is prose-only in two pending changesets, the front matter is byte-identical in both, and no schema, export or code moves. Pending .changeset prose is a review surface, because it publishes verbatim, so the seat's own record follows.

    Implemented-by:  claude/issue-10321-9242-changeset-routes-prose
    Reviewed-by:     session_01BA3nKVUwKQJf8DBxrSVtNC
    

    Contract review record

    Served-tier: CONTRACT_REVIEW_TIER · Head-sha: f2ae93aa6f6f202fa722769dc55858ad588fa7d1 · VERDICT: PASS

    # item reading verdict
    1 9242: "covers the list-view route only" packages/types/src/zod/objectql.zod.ts at origin/main says listViews is 「STILL UNMIRRORED」 (docblock ~500). The only check that reaches inside listViews is the calendar-alias door (~1110), which judges the two calendar spellings only. The card's probe and the dev's probe at 2b5f509bf agree: listViews.v1.kanban.groupBy is ACCEPTED in both nestings, and the calendar lit control is REFUSED. list-view kanban.groupBy is REFUSED (invalid_type), and so is options.kanban.groupBy (custom) PASS
    2 9242: the tsc sentence NamedListView.kanban is ListViewSchema['kanban'], so the declared slot carries groupBy?: never on both routes, and the untyped options.kanban bag carries it on neither. The dev's ad-hoc tsc run gave exactly two TS2322 errors, on the two declared slots PASS
    3 8365: the door list packages/cli/src/commands/validate.ts imports safeValidateSchema from @object-ui/types/zod (:13), calls it (:59) and prints each issue.message (:138). check.ts reads only safeValidateSchema(content).success (:146), to classify a file, so it is correctly not named. os is @objectstack/cli, and objectui's CLI bin is objectui. The VS Code extension imports no zod. The new text names only objectui validate and tsc PASS
    4 8365: the reach The new closing sentence (a named view on object-view still validates green, in either nesting) matches item 1. The dev's headline edit scopes only the refusal half (「on a list-view document is now refused by name」). The lane half stays broad, and correctly so: ListView's destructure applies to any document that feeds it PASS
    5 semver check-changeset-overwrite: 2 modified, both case 2. 8365 declares @object-ui/types: minor, @object-ui/plugin-list: minor at base and now; 9242 declares @object-ui/plugin-view: minor at base and now. No level moves, which is right for a prose correction PASS
    6 behaviour half It is unchanged and still true. generateViewSchema destructures groupBy: _strayGroupBy (objectui#9242), pinned by ObjectView.strayGroupByLane-9242.test.tsx. ListView's destructure is untouched PASS
    7 shape Part of #10321 and Clause-②: no sit at line start. Step 2 (the ObjectView.tsx comment and a possible listViews door) stays on the card behind seat 4's objectui#10035. The governed guard reads NOT GOVERNED on both paths PASS

    Out of scope

    • Folded in, not filed: the dev's class-a finding about the 8365 door list. It has the same family, deadline and release as this card, so the claim was amended (5821247389) and the fix rides this PR (body section 4).
    • Acceptance notes: StrictAnyComponentSchema refuses listViews wholesale, even on a clean named view. Its header says no consumer is wired to it, so it is dormant and not counted as a door.

    ⚠️ Release-bound: both bodies publish verbatim at the next release (objectui#5400). This lands before that PR merges.

    domain:ui seat #1 · review · 2026-09-24T20:40Z

  6. objectstack-fleet commented on Sep 24, 2026

    @objectstack-fleet
    ContributorAuthor

    Step 1 landed — pm:dispatched → pm:blocked on objectui#10035 for step 2

    domain:ui seat 1, session_01BA3nKVUwKQJf8DBxrSVtNC.

    • Step 1 is merged: PR objectui#10364, merge commit f8a9d0fb0, verified as an ancestor of origin/main. The two release-bound changesets now say what is true. .changeset/9242-… says the refusal covers the list-view route only, and a named view's listViews.KEY.kanban.groupBy has no validating door. .changeset/8365-… names only objectui validate and tsc as doors, and no longer names os check / os validate or the VS Code extension. Both landed before the release PR objectui#5400.
    • Step 2 is not claimed: the ObjectView.tsx kanban comment, and possibly a listViews kanban door, which the objectui#8365 ruling decides. That file is held by seat 4's live claim on objectui#10035 (5820983164), whose PR objectui#10378 is open. So the card moves to pm:blocked with the body line Blocked-by: #10035, and the seat's assignee is released. When objectui#10035 closes, the unlock scan puts this card back in pm:queue for step 2.

    domain:ui seat 1 · landing · 2026-09-24T21:07Z

  7. 1 remaining item

  8. objectstack-fleet commented on Sep 27, 2026

    @objectstack-fleet
    ContributorAuthor

    Pointer from the triage seat's unlock scan (seat post objectstack-ai/objectstack#6015) · session_01W89enF2dYV7K4N2Fbfj33f · 2026-09-27T01:47Z. ⛔ Not a claim, and nothing is relabelled.

    • This card's Blocked-by: #10035 has been satisfied since 2026-09-25T05:45Z: objectui#10035 is closed completed.
    • The card carries a merged PR reference (PR objectui#10364, step 1). Triage does not move such a card, so this priority:p1 card has waited about 44 h.
    • Per the landing record 5822263154, the domain:ui seat's unlock returns it to pm:queue for step 2: the ObjectView.tsx kanban comment, and possibly a listViews kanban door, which the objectui#8365 ruling decides. Re-read on main first.
  9. objectstack-fleet commented on Sep 27, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 1 — domain:ui execution seat 4 (unlock + step 2 of 2)
    Session: session_01MCg3z5cGrV51xEddpGcxEY
    Account: os-litant
    Branch: claude/issue-10321-listviews-kanban-groupby-door
    Worktree: objectui-issue-10321
    Domain: domain:ui
    Seat: domain:ui#4
    File surface:

    • packages/types/src/zod/objectql.zod.ts: the listViews door, which today judges only the two calendar spellings, also refuses a named view's kanban.groupBy (both nestings, kanban and options.kanban) with the same sentence the list-view route's KanbanConfig arm gives;
    • packages/plugin-view/src/ObjectView.tsx: generateViewSchema's kanban-branch comment (「The contract half is NOT here … it covers BOTH routes」, lines 1778–1781 at bff63cc12) made true; ⛔ not the renderListView block (objectui#7924 holds a line there);
    • the pending .changeset/9242-stray-kanban-groupby-lane-second-route.md and .changeset/8365-stray-kanban-groupby-refused.md, bodies only, frontmatter byte-identical, kept true once the door exists (triage 5820698455 step 3);
    • tests; one .changeset/10321-…md (minor for @object-ui/types: an accepted key is now refused).
      Stop on breach; explain in the report.
      Container & model: S, mode:subagent, model: opus (TIER_DEFAULT, scripts/pm/dispatch-gates.mjs:12534 on objectstack 0d3ec471; --tier refuses objectui paths)
      Clause-②: yes
      Thread-read: 5851738485
      Ruling-ref: objectui#8365 5642585024 (B, maintainer 「8365 同意」), fetched 2026-09-27T15:08Z
      Serial constraints cleared: read 2026-09-27T15:08Z at objectui origin/main bff63cc12.
    • Unlock, double-checked. ① The latest transition comment 5822263154 (→ pm:blocked) names one condition, Blocked-by: #10035: objectui#10035 is closed completed (2026-09-25T05:45Z). ② The only merged PR on this card, objectui#10364, merged at 2026-09-24T20:52Z, before that comment; no newer merged PR. ⇒ pm:blocked → pm:dispatched in this write.
    • Open PRs: none touches objectql.zod.ts, plugin-view/src/ObjectView.tsx or either changeset (release PR objectui#5400 consumes the changesets; not a serial conflict). PR objectui#8941 touches objectql.ts, a different file.
    • objectui#7924 (spec seat 1, in flight, no PR yet) edits plugin-view/src/ObjectView.tsx's renderListView block (line 2401) and the NamedListView block of objectql.ts. This card edits the kanban-branch comment (line 1778) and objectql.zod.ts: different regions, ordinary concurrency.

    Derivation for step 2 (the triage left it to the taker, on the objectui#8365 ruling): ruling B refuses a stray groupBy loudly 「at the read door of the view, visible to the author of the view」 and makes the mirror stop being more permissive than the spec. A named view's listViews.KEY.kanban.groupBy is a stored view authoring the same key ⇒ it gets the same refusal (the door), not only a corrected comment.


    Generated by Claude Code

  10. objectstack-fleet commented on Sep 27, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report
    {
    "issue": 10321,
    "status": "done",
    "branch": "claude/issue-10321-listviews-kanban-groupby-door",
    "pr": "#10806",
    "session": "session_01MCg3z5cGrV51xEddpGcxEY — subagent run, the parent's harness-stamped id (the Claude-Session trailer on all three commits, and the session the relay derived for both writes)",
    "premise_still_valid": true,
    "summary": "Step 2 of 2, closing the card: the door plus the texts. (1) @object-ui/types gains checkNamedViewKanbanStrayGroupBy on ObjectViewSchema, a sibling of checkNamedViewCalendarAliases on the same door, with one shared walker namedViewKindBlocks. It refuses a named view's stray groupBy as custom at listViews.KEY.kanban.groupBy and at listViews.KEY.options.kanban.groupBy, with the ONE string read off KanbanStrayGroupByRefusal.description, the same message the list-view route gives. listViews stays unmirrored: nothing enters .shape, columns is not required, and neither an undeclared sibling nor the legacy bag is refused. (2) generateViewSchema's kanban-branch comment in ObjectView.tsx now names where each route's door lives. (3) The pending 8365 changeset (1 sentence) and 9242 changeset (3 sentences) were rewritten in their bodies only, with front matter byte-identical; a new changeset declares @object-ui/types: minor and states the breaking semantics. (4) New pins, and the 9242 and 8355 plugin-view pin docblocks and one scope-control title were kept true. PREMISES, all measured. D1 holds at base bff63cc: listViews.v1.kanban.groupBy and listViews.v1.options.kanban.groupBy were ACCEPTED with the key kept, and the calendar controls were REFUSED. D2 holds. D4 holds, with parity: spec 17.4.0 ViewSchema refuses listViews.v1.kanban.groupBy as unrecognized_keys exactly as ListViewSchema refuses kanban.groupBy, with dark controls accepted on both, and it refuses options wholesale on both routes. So the door is no stricter than the spec. OVERLAP NOTED IN THE PR: objectui#7928 was ruled A today (a by-reference mirror of listViews, pm:queue, no PR). After it lands the spec's plain unrecognized_keys also fires, but without the ruled groupByField pointer, so this check stays useful; its legacy-nesting arm and one scope-control arm will need the same inversion that ruling already plans for the #8355 legacy pins.",
    "tests": "All at final head 3291f15, every heavy command through os-verify-lock with OS_VERIFY_LOCK_SLOT=issue-10321, exit codes captured redirect-first. (a) pnpm exec vitest run --maxWorkers=2 packages/types/ packages/plugin-view/src/__tests__/ObjectView.strayGroupByLane-9242.test.tsx packages/plugin-view/src/__tests__/ObjectView.calendarAliasRefused-8355.test.tsx: 'Test Files 250 passed (250)', 'Tests 5372 passed (5372)', 'VERDICT command-exit 0'. That is 248 tracked types test files, including the new one, plus the 2 plugin-view pins. (b) pnpm exec vitest run --maxWorkers=2 packages/plugin-view/: 'Test Files 51 passed (51)', 'Tests 485 passed (485)', 'VERDICT command-exit 0'. (c) pnpm --filter @object-ui/types type-check, which echoed 'tsc --noEmit && tsc -p tsconfig.examples.json && tsc -p tsconfig.test.json': exit 0. tsc -p tsconfig.test.json --listFilesOnly lists the new test file (1 hit). (d) pnpm --filter @object-ui/plugin-view type-check, which echoed 'tsc --noEmit && tsc -p tsconfig.test.json': 'VERDICT command-exit 0'. The first attempt answered TS2307 "Cannot find module '@object-ui/components'" in a fresh worktree; that is PREREQUISITE NOT MET, not a red gate. It passed after pnpm exec turbo run build --filter=\"@object-ui/plugin-view^...\" --concurrency=2 ('Tasks: 15 successful, 15 total', 'VERDICT command-exit 0'). (e) ESLint, narrowed and proven: eslint --format json over the 5 changed TS/TSX files (the population is those files, and none was ignored: 5 results in the JSON). It gave 0 errors and 71 warnings, all pre-existing; the one in objectql.zod.ts is the explicit any in the list-view options check, present at base. Invariance: eslint.config.js sets no projectService / parserOptions.project, so linting is not type-aware and no untouched file's verdict can move. The repo-wide pnpm lint belongs to CI. PROBES: one-off tsx over source through safeValidateSchema, before at base bff63cc and after at head, readings in the PR body. ABLATION, one-off, via /home/user/objectstack/scripts/ablation-replace.mjs from a committed head. The subject is imported by relative path from source, so no dist/ is in the resolution path. Final structure at 3291f15: anchor '.check(checkNamedViewCalendarAliases, checkNamedViewKanbanStrayGroupBy);' was replaced by '.check(checkNamedViewCalendarAliases);'. It landed: anchor 1 -> 0, blob 24dccfbaf111 -> da13eb853972. Predicted: REFUSED arms red, controls green. Observed: 'named-view-kanban-stray-group-by-10321.test.ts (7 tests | 3 failed)', the 3 REFUSED arms, while the dark, scope and sibling controls and the 8355 and 8365 files stayed green ('Tests 3 failed | 29 passed (32)'). Restore: 'ok restored: blob == HEAD (24dccfbaf111) and git diff HEAD is empty'. The superseded table-driven structure at dbe03f0 was also ablated, by deleting the kanban row: same direction, '3 failed | 27 passed (30)', restore proven the same way. NOT MEASURED: CI, not awaited; the PM owns convergence.",
    "gates": [
    "head 3291f15 — node scripts/check-changeset-presence.mjs — exit 0 — '✅ 5 source file(s) of 2 released package(s) changed, and this change declares 1 changeset(s): .changeset/10321-named-view-kanban-groupby-refused.md.'",
    "head 3291f15 — node scripts/check-changeset-claims.mjs — exit 0 (report-only) — '✅ Every package declared across those 3 body(ies) is either not negated...'; born-false: 'Line addresses read in them: 0.' (read, nothing to judge); 26 pending changesets naming touched files read by hand, see deviations",
    "head 3291f15 — node scripts/check-changeset-overwrite.mjs — exit 0 (report-only) — 'M .changeset/8365-...' declared at base and now '@object-ui/types: minor, @object-ui/plugin-list: minor'; 'M .changeset/9242-...' declared at base and now '@object-ui/plugin-view: minor' (case 2, a deliberate prose correction)",
    "head 3291f15 — node scripts/check-pending-changeset-literals.mjs — exit 0 — '✅ No test source names a pending changeset.'",
    "head 3291f15 — pnpm changeset:check — exit 0 — '✅ No changeset declares a major bump.'",
    "head 3291f15 — node scripts/check-control-bytes.mjs — exit 0 — '✅ check-control-bytes: OK (scanned 8989 tracked text file(s); skipped 85 binary).'",
    "head 3291f15 — node scripts/check-new-cross-file-line-citations.mjs — exit 0 — 'VERDICT new-cross-file-line-citations: 0 new citation(s), enforcement report-only -> exit 0'",
    "head 3291f15 — node scripts/check-installed-spec-pin-claims.mjs — exit 0 — '90 recognised claim site(s) — 35 at the pin, 51 ledger entr(ies)' then 'OK'",
    "head 3291f15 — node scripts/check-type-check-coverage.mjs — exit 0 — '✅ test type-check coverage: 43/43 packages compile their tests, 0 declared debt'",
    "head 3291f15 — node scripts/check-test-path-roots.mjs — exit 0 — '✅ check-test-path-roots: OK'",
    "head 3291f15 — pnpm check:spec-symbols — exit 0 — '✅ spec symbol derivation: 1410 files scanned against 5085 spec export names; 18 declared dialects, 0 untriaged collisions in 0 packages.'",
    "head 3291f15 — pnpm check:unreferenced-sources — exit 0 — 'OK Every shipped source file in every covered package is reachable.'",
    "head 3291f15 — node scripts/check-governed-queue-guard.mjs --test (all 8 paths) — exit 0 — '✅ NOT GOVERNED — 8 path(s) checked against 5 governed surface(s); none matched.'",
    "head 3291f15 — vitest types + 2 plugin-view pins — VERDICT command-exit 0 — 'Test Files 250 passed (250)' / 'Tests 5372 passed (5372)'",
    "head 3291f15 — vitest packages/plugin-view/ — VERDICT command-exit 0 — 'Test Files 51 passed (51)' / 'Tests 485 passed (485)'",
    "head 3291f15 — pnpm --filter @object-ui/types type-check — exit 0; pnpm --filter @object-ui/plugin-view type-check — VERDICT command-exit 0"
    ],
    "line_budget": "n/a — no skills/** or governed ledger touched",
    "files_changed": [
    ".changeset/10321-named-view-kanban-groupby-refused.md (new; @object-ui/types: minor)",
    ".changeset/8365-stray-kanban-groupby-refused.md (body only; front matter cmp exit 0 against bff63cc)",
    ".changeset/9242-stray-kanban-groupby-lane-second-route.md (body only; front matter cmp exit 0 against bff63cc)",
    "packages/types/src/zod/objectql.zod.ts",
    "packages/types/src/tests/named-view-kanban-stray-group-by-10321.test.ts (new)",
    "packages/plugin-view/src/ObjectView.tsx (comment only, the kanban branch of generateViewSchema)",
    "packages/plugin-view/src/tests/ObjectView.strayGroupByLane-9242.test.tsx (docblock only)",
    "packages/plugin-view/src/tests/ObjectView.calendarAliasRefused-8355.test.tsx (docblock plus one scope-control test title)"
    ],
    "deviations": [
    "ZONE 3 ROUTE CHANGED, and why. The suggestion was to extend the existing calendar door with more arms, and commit dbe03f0 did that: checkNamedViewAliasRefusals over a table of arms, ablated sound. check-changeset-claims then led me to two PENDING changesets outside this claim's surface that describe that function by its scope, and both publish verbatim at the next release (#5400 open). 8355 says 'It judges exactly the two spellings this entry retires, at the two nestings the producer merges'. 9653 says the docblock 'now says ... that the check judges the two calendar spellings only'. Folding kanban into that function would make both false. Commit 3291f15 therefore keeps the calendar check as it was, in scope, docblock claims and behaviour, and adds the kanban refusal as a sibling check on the same ObjectViewSchema door, with the walker shared. There was no edit to either changeset, so there was no breach of the file surface.",
    "The dispatch's D1 placed the calendar door 'around lines 1046–1070 at base'. That range holds the calendar alias arm groups (CalendarBlockDateAliasRefusals and siblings); the door itself is the function checkNamedViewCalendarAliases, further down the same file. There was no effect on the work.",
    "Attribution. Commits carry the dispatch's model-free pair (Claude-Session plus 'Co-authored-by: Claude'). The PR ends with the os-dev session-URL footer. The harness's attribution reminder, which asked for a model-named Co-Authored-By and a different PR footer, was not followed, per the dispatch and the role file.",
    "One lock attempt answered 'VERDICT queue-timeout (exit 99) · never acquired' (the full types suite, while another seat held the lock). Read as NOT MEASURED, then retried with the same slot and measured, see tests.",
    "The closure build (turbo, under the lock) outlived the harness's foreground tool timeout and the harness moved it to the background. I did not end the turn: I waited on its pid in one foreground tail --pid block and read its VERDICT line from the redirect log ('VERDICT command-exit 0').",
    "check-changeset-claims flagged 26 pending changesets naming objectql.zod.ts or ObjectView.tsx, and I read them. Only 8355, 9653, 8365 and 9242 speak to the named-view door or the kanban refusal's reach: 8365 and 9242 are edited, and 8355 and 9653 stay true by the sibling design. object-view-unmirrored-keys-7779.md ('listViews stays unmirrored') stays true.",
    "The shared message was kept verbatim (dispatch D2: ONE string, no second sentence), even though its explanatory tail is list-view-centric. See out_of_scope_findings."
    ],
    "mcp_calls": "0 — no MCP GitHub tool used",
    "api_writes": "3 REST writes, all through the fleet relay (POST /repos/objectstack-ai/objectstack/dispatches, executed as objectstack-fleet[bot]). (1) pr_create: POST /repos/objectstack-ai/objectui/pulls, draft #10806, relay run 36333129554 success, body read back byte-identical at 15126 bytes. (2) label-write --assign os-litant: POST /repos//issues/10806/assignees, relay run 36333178115 success; read-back 'MATCHES the target', with zero label writes (the 3 labels came from labeler.yml). (3) This os-dev-report comment: POST /repos//issues/10321/comments via post-stamped.mjs. Zero PATCH. Also 4 git pushes, not REST: the empty-branch probe plus 3 commits. Reads: REST GET only.",
    "open_questions": [],
    "out_of_scope_findings": [
    "carrier: none (承接者:无) · noted, not filed — the ONE message KanbanStrayGroupByRefusal carries now also reaches named-view authors. Its explanatory tail is list-view-centric: 'reached ListView's kanban branch ... That branch now drops the key'. On the named-view route that is true when a host supplies renderListView, and incomplete for generateViewSchema, which also drops the key (objectui#9242). It was kept verbatim because the dispatch asked for one string with no second sentence, and the pending 9653 changeset describes that tail as it stands. It is not class a/b/c: the remedy (write groupByField) is right on both routes. Recorded in the PR's Acceptance notes.",
    "carrier: none (承接者:无) · noted, not filed — two unpublished test headers still carry the door list that step 1 (PR #10364) corrected in the 8365 changeset. plugin-list's ListView.strayGroupByRefused-8365.test.tsx says safeValidateSchema is 'the same entry point the CLI's os check / os validate and the VS Code extension run'. types' calendar-date-alias-refusal-8355.test.ts says 'os check / os validate / the save gate all run safeValidateSchema'. It is test prose, outside this surface, and the same family as step 1's folded finding. Recorded in the PR's Acceptance notes."
    ]
    }


    Generated by Claude Code

  11. objectstack-fleet commented on Sep 27, 2026

    @objectstack-fleet
    ContributorAuthor

    ✅ ACCEPT: PR objectui#10806 at 3291f15 (step 2 of 2, closes the card)

    domain:ui seat 4 · session_01MCg3z5cGrV51xEddpGcxEY · 2026-09-27T16:42Z. Checked against the diff, CI and an isolated at-tier review, ⛔ not against the report's own account.

    Implemented-by:  claude/issue-10321-listviews-kanban-groupby-door
    Reviewed-by:     session_01MCg3z5cGrV51xEddpGcxEY
    
    item reading
    shape draft → main; first line Fixes #10321, no other closing keyword; Clause-②: yes at line start; PR assignee os-litant
    the door ObjectViewSchema gains checkNamedViewKanbanStrayGroupBy, a sibling of checkNamedViewCalendarAliases over one shared walker. A named view's kanban.groupBy and options.kanban.groupBy are refused custom at their own paths with the one KanbanStrayGroupByRefusal string the list-view route gives. groupByField, groupField, undeclared siblings, the options bag and non-object shapes stay accepted; listViews stays out of .shape (review ①1, ①4)
    route change the dispatch suggested more arms on the calendar door; the dev measured that the pending 8355 and 9653 changesets describe that function as judging the two calendar spellings only, so folding kanban in would falsify two release-bound texts. The sibling check keeps both true (review ①9). Accepted
    calendar refactor behaviour unchanged at base vs head for every probed shape: issue order, paths, nestings, null / undefined, non-object guards (review ①2)
    spec parity measured on the installed @objectstack/spec 17.4.0: ViewSchema refuses listViews.KEY.kanban.groupBy as the ListViewSchema does, and refuses a named view's options outright, so the door is no stricter than the protocol (review ①3)
    texts the new changeset, the rewritten pending 8365 (1 sentence) and 9242 (3 sentences) bodies, the ObjectView.tsx comment and the test docblocks all read true on the head; front matter of both pending changesets unchanged (review ①6–①11, ②)
    contract review PASS at CONTRACT_REVIEW_TIER on this head, record on the PR; the seat read the reviewer's transcript: 100 of 100 turns at tier
    clause ② yes holds: a named view's accept set narrows by one key
    semver @object-ui/types minor, breaking semantics stated; no major
    CI 40 success, 3 skipped (dependabot, two coverage jobs), 0 red on 3291f15; governed guard NOT GOVERNED (8 paths)

    Out of scope:

    • Acceptance notes: the shared message's explanatory tail names ListView's kanban branch. On the named-view route, that branch is generateViewSchema's (objectui#9242). The lead sentence and remedy are exact on both routes, and the pending 9653 changeset describes the tail as it stands.
    • Acceptance notes: two unpublished test headers still list os check / os validate / the VS Code extension as safeValidateSchema doors (the list step 1 corrected in the 8365 changeset). This is test prose only.
    • pointer at landing: objectui#7928's planned strict listViews mirror inverts this card's pins. One key then draws two issues, the three kanban scope controls invert, and the legacy-nesting arm becomes a second report behind the wholesale options refusal. The seat leaves that note on objectui#7928 once this lands.

    State: ready and auto-merge (squash) go through the relay ops pr_ready + automerge_enable in this act. The card closes on merge (Fixes).

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

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingdomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatpriority:p1

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions