Skip to content

spec(ui): the ComponentPropsMap rows still type renderer-read members as z.unknown() — navigation on object-map / object-gantt / object-tree and conditionalFormatting on object-kanban accept 42 — the family close-out after #21445 #21464

Description

@objectstack-fleet

Filing gate: ① a defect with a measured reach:, finding class (c). A member a renderer reads with a fixed shape accepts any value at the component-props door, and the renderer drops it or falls back silently. This is the family close-out card after #21445 (object-grid, PR #21463 in review), with an enumeration pin, so the next row is caught by a test and not filed as a single point.

reach: the published @objectstack/spec@17.6.0 (npm latest), with ComponentPropsMap[TYPE].safeParse(...), the schema os validate's component-props gate parses through:

  • object-map { navigation: 42 }: ACCEPT. Same for object-gantt and object-tree.
  • object-kanban { conditionalFormatting: 42 }: ACCEPT.
  • Control: object-kanban { navigation: 42 }: REFUSE navigation:invalid_type. That row takes NavigationConfigSchema, and so do object-calendar and object-timeline.

Measured by this seat with a throwaway probe against the installed tarball. Nothing in this repository was run. Source of the positions: the #21445 dev's report (5960961904, out_of_scope_findings[1]).

Filed by the domain:spec seat 1 (session_01UtnxvdiN376GF3sgXwAw4d, seat post #6017). ⛔ Filed bare: routing and grading are triage's. ⛔ Not a claim.

The family on main 9b7a0ef3fa

packages/spec/src/ui/component.zod.ts carries 40 z.unknown() members.

Direction (for triage, not a ruling)

Dedupe

mcp__github__search_issues, repo-scoped, open and closed, 「ComponentPropsMap z.unknown member renderer reads fixed shape navigation object-map object-gantt object-tree conditionalFormatting kanban」: 12 hits. #21445 (open) is the object-grid row. #20831 (closed) is the object-kanban grouping. #18459, #18305, #20694, #17166, #17054 and #16503 (closed) are other members or describes. None covers the remaining z.unknown() members.

Dedupe words: ComponentPropsMap z.unknown family · navigation z.unknown object-map gantt tree · kanban conditionalFormatting z.unknown

Activity

  1. objectstack-fleet commented on Oct 2, 2026

    @objectstack-fleet
    ContributorAuthor

    Triage: first grade — bug · priority:p2 · domain:spec · area:records · pm:queue. Every z.unknown() in ComponentPropsMap is typed, or carries its reason; one enumeration pin holds the family

    Triage seat (objectstack-wide, seat post #6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-02T20:52Z. ⛔ Not a claim, ⛔ not a dispatch.

    Why p2. It matches #21445 (p2), the family's object-grid row. It is class (c), measured on the published 17.6.0: renderer-read members accept any value, and the renderer drops or substitutes them.

    Routing. packages/spec/src/ui/component.zod.ts is domain:spec.

    Direction: the card's, accepted as the family close-out.

    Serial: after PR #21463 (#21445) lands, in the same file.


    Generated by Claude Code

  2. objectstack-fleet commented on Oct 2, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 1
    Session: session_01YDt3PzwfrkuFzUBF89WPmM
    Account: os-tesla (the seat's linked user as GET /user answers it; the card's assignee)
    Branch: claude/issue-21464-component-props-unknown-closeout
    Worktree: objectstack-issue-21464
    Domain: domain:spec
    Seat: domain:spec#2
    File surface (at aa4632235b): packages/spec/src/ui/component.zod.ts, every z.unknown() member across ComponentPropsMap, per triage 5961300594:

    • A member a renderer reads with a fixed shape is typed: by reference where a schema already declares it (for example NavigationConfigSchema on object-map, object-gantt and object-tree, and the list view's conditionalFormatting on object-kanban), and otherwise to the renderer's read at the .objectui-sha pin, as PR feat(spec)!: an object-grid page block types the seven members the grid reads, and resizableColumns retires for resizable (#21445) #21463 did for object-grid.
    • A member forwarded verbatim to a runner keeps z.unknown(), with its reason in the .describe().
    • A census of authored writers at the pin precedes each narrowing. A narrowing that would refuse a measured writer is reported, not shipped.
    • One enumeration pin: every z.unknown() member is typed or listed with its recorded reason, so a new one fails until it carries one.
    • Plus the regenerated artifacts (authorable-surface, the references page, the strictness counts), the ADR-0087 semantic entry for the narrowing, and one changeset.
    • ⛔ No objectui edit, and no renderer change.
    • Size: if the family cannot land as one reviewable PR, the dev stops after the census and returns a staging proposal before building past the first group.
    • Stop on breach and explain in the report.

    Container & model: L, mode:subagent, model: opus (dispatch-gates --tier at aa4632235b: no path-derived mandate; floor sonnet · default opus · ceiling CONTRACT_REVIEW_TIER). packages/spec/src/**, so the at-tier contract review runs as a separate isolated subagent after the PR opens.
    Clause-②: yes (narrowing)
    Thread-read: 5961300594
    Serial constraints cleared:

    Seat terms: p2, ordered ahead of this seat's p3 work under the maintainer's terms (「只处理 p0 p1 p2」, widened by 5952442849), batch 3. The PR is Fixes objectstack-ai/objectstack#21464, unless the dev stages it.


    Generated by Claude Code

  3. objectstack-fleet commented on Oct 3, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report
    {
    "issue": 21464,
    "status": "done",
    "branch": "claude/issue-21464-component-props-unknown-closeout",
    "pr": "#21502",
    "session": "session_01YDt3PzwfrkuFzUBF89WPmM — the parent session (mode:subagent), from the Claude-Session line this run commits under",
    "premise_still_valid": true,
    "summary": "Stage 1 of the ComponentPropsMap z.unknown() close-out, delivered as Part of #21464 under the size rule (A7). The census holds 107 z.unknown() members over 56 rows, 31 of them renderer-read; at the precedent PR #21463 rate (about 140 non-generated lines per member) the 28 still untyped project to about 3,900 lines, over the 2,500 ceiling. This PR types navigation on object-map, object-gantt and object-tree as the list view NavigationConfigSchema by reference, with no measured writer refused (36 of 36 authored literals parse). It adds one enumeration pin that lists every other z.unknown() member with a recorded reason (28 staged with a reader at the pin and a named stage, one of them held for a ruling) and fails on a new or a stale one. The rest of the kit: the ADR-0087 D3 entry, the step-18 rationale fragment, the regenerated references page and a minor BREAKING changeset. The staging proposal and two A2/A3 decisions are in open_questions.",
    "resume": {
    "found_done": [
    "c7bb62ae6f: navigation typed by reference on the three rows; the enumeration pin (427 lines) with its ledger, STAGES table and §1-§4",
    "527957de24 (wip): D3 entry 18.ui-object-map-gantt-tree-navigation-typed, rationale fragment order 64, changeset; content complete except as finished below",
    "9a8037abbe: regenerated content/docs/references/ui/component.mdx",
    "the lost run had already chosen A7 staging: the pin header and STAGES say so, and 28 staged lines each cite a reader"
    ],
    "finished_here": [
    "settled the open question: staging holds — 31 renderer-read members is over A7 (about 30), and the projected lines are over 2,500; every staged reader citation was re-read at 89cad75d55 and holds",
    "merged origin/main 100c394 through scripts/pm/os-regen-merge.sh (merge commit 58b235e): check:generated reported all 15 artifacts current, so no regeneration was owed; sibling entries (agent-lifecycle-retired, ui-object-grid-row-members-typed) intact",
    "re-measured the navigation writer census on the merged head and the kanban refusal (A3)",
    "d3431deed3: finished the changeset (measured section re-anchored to the merged head with controls; summary now matches the ledger, 27 staged plus 1 held) and corrected two STAGES reasons that named a wrong or incomplete candidate (object-metric: chart aggregate/drillDown and dashboard compareTo, trend none; objectui-held: UIActionSchema is an objectui interface)",
    "every gate rerun on d3431de; the lost run readings were discarded as not measured on the final head",
    "opened draft PR #21502, assigned os-tesla, removed the worktree"
    ]
    },
    "tests": "All on d3431de, under scripts/pm/os-verify-lock.sh, with exit codes written to disk first. (1) pnpm --filter @objectstack/spec test: Test Files 602 passed, 1 skipped (603); Tests 17832 passed. (2) pnpm --filter @objectstack/spec typecheck: exit 0, with check:test-typecheck: OK — the test layer compiles under packages/spec/tsconfig.test.json (tsconfig.json excludes /*.test.ts, so this is what covers the pin). (3) The pin by name (--project local): Tests 51 passed (51). (4) scripts/step18-rationale-merge.test.ts (--project repo): Tests 9 passed (9). (5) Ablation via node scripts/ablation-replace.mjs in WRAP mode: object-map navigation reverted to z.unknown() with no ledger line. It landed: anchor x1 to x0, replace x0 to x1, blob 58b6e27fbc to 7e3b411604. The run went red: Tests 8 failed, 43 passed (51); §1 received ["object-map navigation"]; census expected 108 to be 107; six object-map §4 cases failed. Restore: blob after restore 58b6e27fbc == blob at HEAD, git diff HEAD empty. Green rerun: Tests 51 passed (51). The pin imports ./component.zod from source, so no build sits between mutation and run. (6) A narrowed eslint run over the 4 changed TS files: 4 files, 0 errors, 0 warnings. The population is from eslint itself (each resolves a config with --print-config); the count is from --format json; invariance holds because eslint.config.mjs never enables type-aware linting (lines 326-328). The full pnpm lint is CI's.",
    "gates": {
    "derivation": "node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands (no paths): 114 commands, merge base 100c394, 6 changed paths, 649 changed lines (under the 5000 threshold)",
    "reconcile": "node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --ran r-ran.list: exit 0 — Run reconciliation: 114 derived, 114 run, 0 NOT-MEASURED, 0 UNRUN",
    "all_114": "exit 0. Six spec gates (check:api-surface, check:browser-reachable-entries, check:dual-source-exports, check:entry-nameability, check:exported-any, check:skill-examples) first answered PREREQUISITE NOT MET (exit 3), because dist predated the final pin edit. After pnpm --filter @objectstack/spec build at d3431de they and the whole spec family (#44-#67) were rerun: exit 0. The exit-3 lines are kept apart, not counted.",
    "named": [
    "pnpm --filter @objectstack/spec build :: exit 0",
    "pnpm --filter @objectstack/spec run check:generated :: exit 0 — ✓ All 15 generated artifacts are up to date",
    "pnpm --filter @objectstack/spec run check:liveness :: exit 0 — ✓ packages/spec/liveness/state-counts/ is current",
    "pnpm --filter @objectstack/spec run check:migration-registry :: exit 0 — ✓ src/migrations/registry.ts is current (353 semantic, 246 retired-key, 217 retired-def)",
    "pnpm --filter @objectstack/spec run check:strictness-ledger :: exit 0 — counts current, unmoved",
    "pnpm --filter @objectstack/spec run check:authorable-surface :: exit 0 — authorable-surface/ui.json unmoved",
    "pnpm --filter @objectstack/spec test :: exit 0; pnpm --filter @objectstack/spec typecheck :: exit 0",
    "node scripts/check-adr-0087-registration.mjs --base origin/main :: exit 0 — ✓ 1 declared-breaking changeset(s), each carrying an ADR-0087 disposition (registered ui-object-map-gantt-tree-navigation-typed)",
    "node scripts/check-changeset-no-major.mjs --base 100c394 --event event.json (the PR body as the payload) :: exit 0 — ✓ LEVEL AXIS: this PR declares clause-② yes (narrowing), and no package whose packages/
    /src/** it moves is graded patch · direction arm: narrowing — a BREAKING change; during the launch window it ships minor",
    "node scripts/check-empty-changeset.mjs --base origin/main :: exit 0",
    "pnpm check:doc-authoring :: exit 0 — ✓ doc authoring guard: 17287 customer-facing string(s) across 1247 spec sources clean",
    "pnpm check:nul-bytes :: exit 0 — check-nul-bytes: OK (scanned 9839 text file(s), no raw ASCII control bytes)",
    "pnpm check:dual-build-cjs-loads :: exit 0 — 105 published require entry point(s) across 66 package(s) load (the lost run got PREREQUISITE NOT MET here; this run found every dist present)"
    ],
    "not_measured": "NOT MEASURED: the Console Pin Gate, Dogfood and the full pnpm lint, reason: CI-owned. NOT MEASURED: the derivation against origin/main 5555047, reason: --ran printed STALE TREE — one family input, scripts/engine-double-contract.pinned.json, changed on main after the merge base; the diff touches none of its subjects, and the only other overlap since is a comment-only edit in ui/view.zod.ts"
    },
    "line_budget": "649 changed lines (+637/-12, 6 files) vs merge base 100c394. Before generated files: 573 (component.zod.ts +50/-9, pin +427, D3 entry +41, rationale fragment +13, changeset +33). Generated: component.mdx +36/-3 and registry.ts generated region +37. The A7 ceiling is about 2,500; the remaining 28 members project to about 3,900.",
    "files_changed": [
    "packages/spec/src/ui/component.zod.ts",
    "packages/spec/src/ui/component-props-unknown-members.pin.test.ts",
    "packages/spec/src/migrations/entries/semantic/18.ui-object-map-gantt-tree-navigation-typed.ts",
    "packages/spec/src/migrations/registry.ts (rationale fragment hand-written; semantic region generated)",
    "content/docs/references/ui/component.mdx (generated)",
    ".changeset/21464-component-props-navigation-typed.md"
    ],
    "semver": "@objectstack/spec minor, BREAKING banner, Clause-②: yes (narrowing), ADR-0087 marker registered ui-object-map-gantt-tree-navigation-typed; judged by the level-axis and adr-0087 lines quoted in gates.named",
    "census": {
    "scope": "107 z.unknown() members over 56 rows on the merged head (unchanged from aa46322 minus the 3 typed). Readers: objectui at 89cad75d55, every citation re-read. Writers are file co-mentions (type plus authored KEY:) with a control key, written os N/M (ctl) | ou N/M (ctl). os was counted by the lost run on its aa46322-based tree, except navigation, which was re-measured on the merged head.",
    "renderer_read": [
    "object-map/gantt/tree · navigation · ObjectMap.tsx:1189, ObjectGantt.tsx:1960/2025, ObjectTree.tsx:1054, hook useNavigationOverlay.ts:364 · NavigationConfigSchema · os 0 on the row (ctl objectName 4/5) | ou 88/98/59 files (ctl 55/70/40), 36/36 literals parse · TYPED (this PR)",
    "object-metric · aggregate · ObjectMetricWidget.tsx:250, :404 · chart aggregate (chart.zod.ts:644) · os 7/8 (7) | ou 17/36 (20) · staged object-metric",
    "object-metric · trend · ObjectMetricWidget.tsx:254 (:176) · none · os 0/8 | ou 1/36 · staged object-metric",
    "object-metric · drillDown · ObjectMetricWidget.tsx:265 (:218) · chart drillDown (chart.zod.ts:663) · os 0/8 | ou 7/36 · staged object-metric",
    "object-metric · compareTo · ObjectMetricWidget.tsx:267 (:241) · dashboard widget compareTo (dashboard.zod.ts:1205) · os 1/8 | ou 4/36 · staged object-metric",
    "object-form · fields[] · ObjectForm.tsx:961 · none · os 11/14 (12) | ou 178/210 (188) · staged object-form",
    "object-form · customFields · ObjectForm.tsx:755, :1180 · none · os 0/14 | ou 21/210 · staged object-form",
    "object-form · sections[] · ObjectForm.tsx:364, :1518 · FormViewSchema.sections · os 3/14 | ou 78/210 · staged object-form",
    "object-form · contentLayout · ModalForm.tsx:854 (:151) · none · os 0/14 | ou 7/210 · staged object-form",
    "object-form · submitBehavior · ObjectForm.tsx:1312-1313 · FormViewSchema.submitBehavior · os 2/14 | ou 12/210 · staged object-form",
    "object-form · navigateOnSuccess · ObjectForm.tsx:1373, :1412 · none · os 0/14 | ou 5/210 · staged object-form",
    "object-form · mobile · ObjectForm.tsx:1857 · none · os 0/14 | ou 7/210 · staged object-form",
    "object-master-detail-form · sections[], fields[] · MasterDetailForm.tsx:1692-1693 · as object-form · os 2/4, 4/4 (4) | ou 9/29, 18/29 (21) · staged object-form",
    "object-grid · columns[] · ObjectGrid.tsx:2158 · ListViewSchema.columns · os 7/21 (16) | ou 198/292 (248) · staged list-family",
    "object-grid · fields[] · ObjectGrid.tsx:1946 · none · os 7/21 | ou 191/292 · staged list-family",
    "object-grid · selection · ObjectGrid.tsx:4799-4810 · ListViewSchema.selection · os 1/21 | ou 19/292 · staged list-family",
    "object-grid · selectable · ObjectGrid.tsx:4813-4815 · none · os 0/21 | ou 7/292 · staged list-family",
    "object-grid · rowActions[] · ObjectGrid.tsx:1834-1835 · ListViewSchema.rowActions · os 1/21 | ou 19/292 · staged list-family",
    "object-grid · bulkActions[], batchActions[] · ObjectGrid.tsx:4763 · ListViewSchema.bulkActions · os 2/21, 0/21 | ou 27/292, 7/292 · staged list-family",
    "object-kanban · columns[] · KanbanBoardCore.tsx:95 · none · os 4/12 (9) | ou 87/152 (99) · staged list-family",
    "object-calendar · calendar · ObjectCalendar.tsx:296-297 · ListViewSchema.calendar · os 1/6 (6) | ou 50/83 (62) · staged list-family",
    "object-gantt · markers[] · ObjectGantt.tsx:2497 (GanttMarker) · none in spec · os 0/5 (4) | ou 6/98 (70) · staged objectui-held",
    "object-timeline · items[] · ObjectTimeline.tsx:587 · none in spec · os 3/3 (3) | ou 12/45 (34) · staged objectui-held",
    "object-timeline · mapping · ObjectTimeline.tsx:551, :576-579 (TimelineMappingSchema) · none in spec · os 2/3 | ou 2/45 · staged objectui-held",
    "action:group · actions[]{} · action-group.tsx:303 (UIActionSchema, objectui interface) · none in spec · os 2/3 (label 3) | ou 23/36 (26) · staged objectui-held",
    "action:menu · actions[]{} · action-menu.tsx:339 · none in spec · os 2/4 (3) | ou 23/38 (28) · staged objectui-held",
    "object-kanban · conditionalFormatting · KanbanBoardCore.tsx:114, KanbanImpl.tsx:179 · ListViewSchema.conditionalFormatting · os 1/12 | ou 9/152 · HELD for a ruling (A3, open_questions[1])"
    ],
    "recorded_reason": [
    "slot (7) · page:tabs/page:accordion items[].children[], page:card children[]/footer[], page:footer/page:sidebar/page:section children[] · declared slot positions, judged at their own node (§2 checks)",
    "runner (16) · action:button and action:icon params, bodyExtra, bodyShape, operation, patch, toast, resultDialog, onSuccess · forwarded verbatim to the action runner; each .describe() says so (§2 checks)",
    "records (18) · staticData[] (grid/map/gantt/tree), data[] (kanban/timeline/calendar), calendar staticData[], data.items[] (grid/map/gantt/tree), initialValues{}/initialData{} (form/master-detail), grid bulkActionDefs[].patch{} and params[].default · record rows and field values shaped by the bound object",
    "shared (35) · expression AST .ast beside every source (14) · HttpRequestSchema params{}/body on data.read/data.write (16) · inline JSON Schema data.schema{} (4) · bulk-action option entry params[].options[].* (1) · owned and judged by another file",
    "any-value (1) · element:definition-list items[].description · shown as-is, data-list.tsx:68 toText",
    "open-bag (1) · object-grid pagination.* · z.looseObject on purpose, named members typed",
    "no-reader (1) · ai:chat_window context{} · objectui registers no ai:chat_window renderer (placeholders.tsx:109-113) — A2 open question, open_questions[2]"
    ]
    },
    "a2_decisions": "Typed: 3 (navigation x3, by reference). Runner-forwarded and kept z.unknown() with the reason in .describe(): 16. Recorded non-renderer reasons: 76 (slot 7, records 18, shared 35, runner 16). Plus one each of any-value, open-bag and no-reader. Staged: 27 renderer-read members, each with its reader at the pin and a named stage. Held: 1 (kanban conditionalFormatting, A3). Not guessed: ai:chat_window context{} has no reader and is listed as an open question, not a verdict.",
    "a3": "navigation: no measured writer refused — objectstack 0 writers on the three rows; objectui 77 navigation lines in 190 files, 36/36 distinct authored literals parse on all three rows; the refused values are probes that already expect refusal (both-faces parity anything, a @ts-expect-error drawer, mode sideways). kanban conditionalFormatting: the by-reference shape refuses objectui fixtures — native rule: unrecognized_keys plus invalid_type@style; flat CEL rule: invalid_type@style plus unrecognized_keys[backgroundColor] — so it was NOT shipped.",
    "a4_red_then_green": "Red: one member reverted (object-map navigation to z.unknown(), no ledger line), Tests 8 failed, 43 passed (51), §1 names exactly object-map navigation. Green: Tests 51 passed (51) before the ablation and again after the blob-proven restore. Both directions of §1 are live: an unlisted member reds, and a ledger line outliving its member reds.",
    "a8": "No open PR touches ui/component.zod.ts, component.mdx, migrations/registry.ts, authorable-surface/ui.json or the pin (8 open PRs read via REST at 2026-10-03; #21352, the bot Version Packages PR, was read only to page 1 because the proxy refused its pagination link).",
    "deviations": [
    "Merged origin/main 100c394 into the branch (58b235e) through os-regen-merge.sh, per AGENTS.md multi-agent §10, before opening the PR; not named in the dispatch.",
    "The wip commit 527957d keeps its wip subject in history; it was finished by d3431de instead of a history rewrite (no force-push). Squash landing collapses it.",
    "The PR footer and commit trailers follow AGENTS.md (session-URL footer; model-free trailer pair), not the harness reminder that names a model and a different footer.",
    "dispatch-gates --ran printed STALE TREE against origin/main 5555047 (one family input changed after the merge base); not re-derived, declared under gates.not_measured."
    ],
    "mcp_calls": "0 — no MCP GitHub tool called",
    "api_writes": "3 — each through the fleet-write relay as one repository_dispatch (POST /repos/objectstack-ai/objectstack/dispatches, 204), executed as objectstack-fleet[bot]: (1) pr_create, POST /repos/objectstack-ai/objectstack/pulls, draft #21502 (body read back byte-identical, 15559 bytes); (2) the label-write assign op on #21502, assignee os-tesla (read back matches); (3) this os-dev-report comment via post-stamped.mjs --comment=21464. Plus 2 git pushes (58b235e, d3431de), which are not REST.",
    "open_questions": [
    {
    "question": "Staging proposal (A7): how do the 28 untyped renderer-read members land? The pin names four stages plus one held item.",
    "options": [
    "A — Four stages under #21464, each a Part-of PR that runs its own value census first: S-list (9: grid columns, fields, selection, selectable, rowActions, bulkActions, batchActions; kanban columns; calendar calendar — 5 by reference to ListViewSchema); S-form (9: form fields, customFields, sections, contentLayout, submitBehavior, navigateOnSuccess, mobile; master-detail sections, fields — FormViewSchema sections and submitBehavior by reference); S-metric (4: aggregate and drillDown by reference to the chart, compareTo to the dashboard widget, trend to the renderer read); S-objectui-held (5: gantt markers, timeline items and mapping, action:group and action:menu actions — the spec declares each contract first). The last stage carries the closing line once the held item is ruled.",
    "B — Same four groups, filed as sub-issues of #21464 so separate seats can take them in parallel.",
    "C — One PR for all of them: about 3,900 lines at the precedent rate, over A7."
    ],
    "recommendation": "A, in the order S-list, S-form, S-metric, S-objectui-held. Business need, measured: the list and form rows carry the largest authored populations (objectui grid columns in 198 of 292 files, form fields in 178 of 210), so that is where an off-shape value is most likely to be authored. Long-term soundness: each stage types by reference where the spec already declares the shape, and the objectui-held contracts get declared in the spec first, contract-first, before any row takes them. Preventing AI authoring errors: every stage is a loud narrowing, and the pin keeps the remaining debt visible and shrink-only, so no new silent member can enter. Startup focus: staging answers size only; it keeps no alias or dual spelling and adds no gate beyond the pin triage named. B is equally sound if the PM wants parallel seats; C fails A7."
    },
    {
    "question": "object-kanban conditionalFormatting (A3): the list view shape (the grid shape since PR #21463) refuses two rule dialects that objectui authors in its own fixtures and asserts in its own kanban schema test. How should it be typed?",
    "options": [
    "A — Narrow to ListViewSchema.conditionalFormatting, and pair it with an objectui change: respell its fixtures from the native rule to { condition: CEL, style: { backgroundColor } }, and retire the native dialect from objectui ObjectKanbanSchema in the same landing, with the pin bump (AGENTS.md Post-Task 4).",
    "B — Widen the spec: the list view conditionalFormatting also accepts the native { field, operator, value, backgroundColor } rule, on every list carrier.",
    "C — Keep z.unknown() with a recorded two-dialect reason."
    ],
    "recommendation": "A. Business need: the measured writers are objectui test fixtures (9 of 152 files at the pin), not authored apps, and the grid already ships the single CEL dialect. Long-term soundness: one strict contract beats two dialects, and B widens every list carrier to tolerate a legacy spelling. Preventing AI authoring errors: one dialect is the one an AI cannot write wrong, while B and C keep a second spelling and C keeps the silent accept. Startup focus: retire the alias dialect at once, with no staged window. Cost: an objectui-side change outside this card (no objectui edit was allowed here), so it is its own card."
    },
    {
    "question": "ai:chat_window (A2): the row has no renderer at the pin. objectui omits it on purpose, a referencing page gets a loud Unknown component type, and its palette excludes it. So context{} has no reader. Should the row retire?",
    "options": [
    "A — Retire ai:chat_window from ComponentPropsMap and the page component type list (page.zod.ts:164) under ADR-0049 enforce-or-remove, with the retirement kit (tombstone, D3 entry, changeset).",
    "B — Keep the row and have objectui implement an inline renderer.",
    "C — Keep it as is, with context{} recorded as no-reader (today’s pin line)."
    ],
    "recommendation": "A, as its own card. Business need: zero authored writers in either repository; the objectstack hits are spec tests and type lists, and the objectui hits are tests asserting the absence, a palette exclusion and a tombstone list in check-prompt-component-keys. Long-term soundness: a declared component nothing renders is declared but not enforced, and the floating chat overlay is objectui canonical entry. Preventing AI authoring errors: today the spec accepts a block the console refuses to draw, and retiring makes the refusal loud at authoring. Startup focus: a zero-pull declared surface retires now, with no sunk-cost exemption."
    }
    ],
    "out_of_scope_findings": [
    "carrier: open_questions[2] (PM) · ai:chat_window is declared in ComponentPropsMap and page.zod.ts:164, but objectui registers no renderer (placeholders.tsx:109-113) and zero writers author it in either repository · noted, not filed (no public-door reach measured in this run) · dedupe words: ai:chat_window renderer retire · chat_window ComponentPropsMap no reader · page component type no renderer",
    "carrier: open_questions[1] (PM) · object-kanban conditionalFormatting is held under A3; objectui fixtures author two dialects the list view refuses · noted, not filed · dedupe words: kanban conditionalFormatting dialect · ListViewSchema conditionalFormatting native rule · kanban field operator value backgroundColor"
    ],
    "cleanup": "Removed the worktree /home/user/objectstack-issue-21464 with git worktree remove, no --force, after confirming HEAD d3431de equals the remote branch and the tree was clean; root node_modules was removed first. No dev server, monitor or background process was started."
    }


    Generated by Claude Code

  4. 99 remaining items

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

Metadata

Metadata

Assignees

Labels

area:recordsBusiness objects, records, the views that show data, usable forms, searchbugSomething isn't workingdomain:specpriority:p2Medium: important, M3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions