Skip to content

feat(spec): ComponentPropsMap gains a 'list-view' row — a page-embedded list view is judged as a list view; stored objectName / viewType convert to data / type (#22444) - #24217

Merged
objectstack-fleet[bot] merged 10 commits into
mainfrom
claude/issue-22444-list-view-component-props-row-c
Oct 18, 2026
Merged

objectstack-fleet[bot] merged 10 commits into
mainfrom
claude/issue-22444-list-view-component-props-row-c

Conversation

@objectstack-fleet

@objectstack-fleet objectstack-fleet Bot commented Oct 17, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #22444

Clause-②: yes

Ruling C on #22444 (record 6100463199, the maintainer's 「同意」), its spec half: a list view embedded on a page is judged as a list view, and the page carrier's own spelling objectName / viewType is refused by name and carried forward on stored nodes by an ADR-0087 D2 conversion. Dev session: session_01Q5DmD3Wg7eTiagmd5p9rqf (cloud dispatch from the domain:spec#1 seat, claim 6238503560).

What changed

  • ComponentPropsMap['list-view'] (packages/spec/src/ui/component.zod.ts, ListViewPageProps). Every member is ListViewSchema.shape's own schema object, and both of the list view's object-level checks are attached (checkListViewCalendarVisualization, checkListViewChartBinding). The two members the list overlay member declares instead, and nothing else:
    • columns optional: the overlay member's own spelling, ListViewSchema.shape.columns.optional();
    • options judged per kind: the overlay member's own bag by reference, VIEW_METADATA_MEMBERS.listOverlay.shape.options. Each options.KIND is judged by that kind's block, and options.grid gets its existing guidance.
    • objectName / viewType are undeclared, and the row's guidance answers them by name. The guidance quotes the react tier's note for the same alias verbatim.
    • The row is not exported, for the reason ListViewShapeSchema is not: a top-level export would mint a def and duplicate every ui/ListView key in authorable-surface/. check:authorable-surface, check:api-surface and check:docs are unchanged.
  • One prescription for both tiers. REACT_RETIRED_OVERLAY_PROPS.ListView's two entries moved, byte for byte, to a leaf module outside the ui barrel (ui/list-view-retired-aliases.ts). react-blocks.ts reads it there, and so does the row. The row cannot import react-blocks.ts, which reads ComponentPropsMap at module load. The published value of REACT_RETIRED_OVERLAY_PROPS is unchanged (check:react-blocks and check:export-origins are green).
  • D2 conversion page-list-view-object-name-view-type-to-data-type (conversions/registry.ts, order 68, retiredFromLoadPath: true, retiredAfter: '17.7.0'). On every page component of type list-view that mapPageComponents reaches:
    • objectName: 'x' becomes data: { provider: 'object', object: 'x' };
    • viewType becomes type;
    • a redundant twin is deleted;
    • a conflict is left byte-identical and reported as a TODO: an alias beside a data source or a dataSource.object naming another object, a viewType beside a different type, or a non-string alias.
  • D3 entry page-list-view-object-name-view-type-retired (conversionIds joins it to the conversion), plus its step-18 rationale fragment in registry.ts.template (order 101).
  • Census pins the new row trips, each classified instead of skipped:
    • page.zod.ts: PRINT_REFUSED_PAGE_COMPONENT_TYPES gains list-view (it pages its rows, the object-grid reason). Before this, the type was refused in a print page as unknown vocabulary, so the accept set does not move.
    • The view-API-source refusal (refused-shapes.ts and the D3 entry view-data-api-provider-retired) now names list-view among the components whose data prop takes a view data source. The detector reads each row's data member, so it reaches a page list-view node for the first time with this row (contract review 6240571802, ① item 8). The strings now name it.
    • The z.unknown() member ledger, the requiredPermissions census and the retired-prescription join each gained their list-view lines.
  • The strictness ledger counts were regenerated (gen:strictness-ledger: ui/ gains 1 strict site).

Accept set, before → after

door before (d9a749bae) after (this head)
PageSchema / PageComponentSchema accepts a list-view node with any properties unchanged: accepts (the carrier stays an open record, maintainer ruling 2026-08-05)
component-props rule (os validate / os build / os lint, page save door) list-view skipped as unregistered: 0 findings judged by the row: kanban.groupField, options.grid, properties.objectName, properties.viewType are component-props-unknown-key, each naming the key
stored page row / artifact / installed package (data at rest) loads as stored the D2 conversion moves objectName / viewType to data / type on read
authoring funnel (defineStack) n/a does not replay the conversion (retired from the load path), so an author meets the refusal

Measured against a real producer

The external corpus objectstack-ai/hotcrm 4.0.1 (the published-pages fixture packages/objectql/src/__fixtures__/hotcrm-4.0.1-published-pages.artifact.json, 7 pages in package 2) carries 4 page list-view nodes in the old spelling:

  • without the conversion, the props rule reports 8 findings (each node's objectName and viewType);
  • the conversion emits 8 OS_METADATA_CONVERTED notices and 0 TODOs;
  • after the conversion, the rule reports 0 findings on those nodes. The row has no false positive on the converted real nodes (their rule-array filter, { field, order } sort and string columns all pass).

In-repo producers of page list-view nodes: 0 in packages/** and examples/** outside test fixtures (control: the same grep hits react-blocks.ts:292).

Tests

All at head 945584a6 unless noted.

  • pnpm --filter @objectstack/spec test: 693 files, 20989 passed, 1 todo, exit 0.
  • pnpm --filter @objectstack/spec typecheck: exit 0.
  • pnpm --filter @objectstack/lint test: 143 files, 6821 passed, 5 skipped. typecheck: exit 0.
  • Consumers whose fixtures carry page list-view nodes, after a closure build: @objectstack/objectql registry-installed-package-retired-page-declarations.test.ts (8 passed), @objectstack/service-package (8 files, 119 passed), @objectstack/cloud-connection (50 files, 602 passed). All exit 0.
  • New pins:
    • spec/src/ui/component-list-view-row.test.ts: the ruling's list, by-reference identity, the checks attached, one prescription for both tiers, PageSchema unmoved;
    • spec/src/conversions/page-list-view-object-name-view-type-to-data-type.test.ts: stored row → accepted by the row, notices, TODOs on conflict, not on the authoring funnel, idempotent, copy-on-write;
    • lint/src/validate-component-props-list-view-22444.test.ts: the findings at the gate, and through runAuthoringRules.
  • Ablation (one shot, not kept): the map key was renamed to list-view-ablated through scripts/ablation-replace.mjs, then spec was rebuilt. The marker was present in dist/ (proved by the run turning red). The lint pin went 5 failed / 3 passed: every flag case red, and the three contract-only cases still green, as expected with no row. Restore leg: git checkout HEAD --, blob a5e4dbed97 equal to HEAD, rebuild, ablation-dist-preflight --absent exit 0, then the pin went 8/8 green.

Gates

node scripts/pm/dispatch-gates.mjs --commands (90 derived families, change set vs merge base d9a749bae), run at 945584a6:

  • 89 exited 0;
  • pnpm check:dual-build-cjs-loads exited 3, PREREQUISITE NOT MET (needs every package built), so it is NOT MEASURED locally and left to CI;
  • node scripts/check-plugin-teardown-shape.mjs --self-test first exited 3 because its pinned fixture commit was outside the shallow clone. After fetching that one commit it exited 0.

The --ran reconciliation reports 90 accounted, 89 run, 1 NOT-MEASURED. check-adr-0087-registration: "this PR adds no declared-breaking changeset". Separately, pnpm --filter @objectstack/spec check:generated reported 14/14 up to date after gen:strictness-ledger, and check:dev-prereqs exited 0. origin/main moved to 8259ea03 after this branch was cut. Those commits touch none of this PR's files, so no merge was taken.

Patch round 1 (e55aa1bf)

Acceptance notes

  • The gate's tier is now error, not the "warning" the ruling text names. Ruling item (1) says the row is lint-tier, "as every ComponentPropsMap row has been since spec: record:reference_rail has no ComponentPropsMap row — an entry filter parses, typechecks, validates, ships, and silently does nothing #8691", with no new gate. Measured: validate-component-props emits error for every finding since lint: the rest of the component-props gate's recorded plan — every component-props-invalid class and component-props-unknown-key go to error, after an external-corpus inventory #23147, at os validate / os build / os lint and at the runtime page save door (ruling record 6161173492). This PR adds no gate and changes no tier: the row takes the rule's tier, as every row does. So in practice an authored page source carrying properties.objectName / viewType on a list-view fails os validate, and a Studio, REST or MCP save of such a page is refused until it is rewritten. Stored rows load converted. The Clause-② arm follows the ruling (yes (widening), minor). The seat may want the arm re-read on this fact (see the report's open question).

  • columns is optional whatever the binding. The seat's note reads "optional under a dataSource.view binding". The row judges properties only and cannot see the node's dataSource. The overlay member's own difference is unconditional, and the list renderer draws a column-less list.

  • Differences from objectui's ListViewPropsBag (@object-ui/types at the .objectui-sha pin 5e15928b46), read as a reference only:

    • objectui makes the kanban block's columns optional and adds named refusals on its kanban / calendar / gallery / timeline blocks; this row keeps ListViewSchema's blocks as declared;
    • objectui keeps its local toolbar flags and a passthrough tolerant face;
    • objectui attaches its own dataset-chart filter check.

    So a page kanban with a kanban block that omits columns passes objectui's face and draws kanban.columns required here.

  • .objectui-sha, objectui, PageSchema's accept set and validate-component-props.ts were not touched: the rule dispatches on map rows, and no dispatch change was needed.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Q5DmD3Wg7eTiagmd5p9rqf


Generated by Claude Code

…n to its prescriptions

Claude-Session: https://claude.ai/code/session_01Q5DmD3Wg7eTiagmd5p9rqf
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions

github-actions Bot commented Oct 17, 2026 •

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/spec, touching 16 documentable anchor(s). ⚠️ 2 changed file(s) yielded no anchor (packages/spec/src/migrations/registry.ts.template, packages/spec/src/ui/react-blocks.ts), so the pages documenting them are NOT COVERED by this run — this is not a clean bill of health for those files.

4 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:

  • content/docs/deployment/validating-metadata.mdx (via ComponentPropsMap (symbol, a top-level const object))
  • content/docs/protocol/objectui/concept.mdx (via viewType (symbol, a field of const object LIST_VIEW_PAGE_ALIAS_GUIDANCE; a field of const object LIST_VIEW_RETIRED_ALIASES), viewType (literal, a string literal in LIST_VIEW_PAGE_ALIAS_GUIDANCE; a string literal in LIST_VIEW_RETIRED_ALIASES; a string literal in apply))
  • content/docs/protocol/objectui/layout-dsl.mdx (via ComponentPropsMap (symbol, a top-level const object))
  • content/docs/ui/pages.mdx (via open_deals (literal, a string literal in fixture), sales_home (literal, a string literal in fixture))

⛔ 5 release-owned page(s) also name something this change touched. These are read-only:

  • content/docs/releases/v17/17-1.mdx (via ComponentPropsMap (symbol, a top-level const object))
  • content/docs/releases/v17/17-3.mdx (via ComponentPropsMap (symbol, a top-level const object))
  • content/docs/releases/v17/17-4.mdx (via ComponentPropsMap (symbol, a top-level const object), viewType (symbol, a field of const object LIST_VIEW_PAGE_ALIAS_GUIDANCE; a field of const object LIST_VIEW_RETIRED_ALIASES), viewType (literal, a string literal in LIST_VIEW_PAGE_ALIAS_GUIDANCE; a string literal in LIST_VIEW_RETIRED_ALIASES; a string literal in apply))
  • content/docs/releases/v17/17-5.mdx (via ComponentPropsMap (symbol, a top-level const object), retiredAfter (symbol, a field of const object pageListViewObjectNameViewTypeToDataType), retiredFromLoadPath (symbol, a field of const object pageListViewObjectNameViewTypeToDataType))
  • content/docs/releases/v17/17-7.mdx (via ComponentPropsMap (symbol, a top-level const object))

content/docs/releases/ is RELEASE-OWNED (AGENTS.md "Documentation Guardrails"): release
notes are written centrally at release time, and a code PR that edits them is the exact PR
that guardrail exists to stop. They are still audited — read-only. If one of them is actually
wrong, file an issue or open a dedicated docs-only PR; do not edit it here.

What this run could not see
  • 2 changed file(s) yielded no anchor (packages/spec/src/migrations/registry.ts.template, packages/spec/src/ui/react-blocks.ts) — pages documenting those are invisible to this run
  • 2 anchor(s) matched too much of the corpus to be a work list: objectName (symbol, 39 pages), objectName (literal, 39 pages)
  • 6 name(s) were too generic to anchor anything (single lowercase words)
  • the SDK route bridge reached 54 of 206 client-bound route-ledger rows — the other 152 have no registrar path: tail to select them, so pages documenting THEIR client methods cannot appear above, on this or any run. Of those 152: 0 are remediable by widening that discovery convention (an in-repo file declares the path; the convention did not scan it); 55 are structural — on a ledger where NOT ONE row is declared in-repo, so no discovery change reaches them at any price; 97 are undecided (no in-repo declaration, on a ledger that has other in-repo registrars — absence and an unreadable spelling are not distinguishable here). The rows themselves: node scripts/docs-audit/affected-docs.mjs --bridge-coverage
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.
  • a key NAME is not a key, so the hand re-read the line above prescribes can land on the wrong schema. The same spelling is authorable on one governed type and a [REMOVED] tombstone on another for each of active, aria, joins, objects, template, tools and version (censused on [finding] tools is a key on BOTH AgentSchema (tombstoned, dead) and SkillSchema (live, cloud-attested), so a name-based search attributes skill examples to the agent key — it produced a false stop-the-line alarm on PR #19059 #19093 over the liveness ledger's governed types, top-level keys); nothing in a search result distinguishes the two, so a grep hit on a LIVE example reads as evidence about the DEAD key. Measured on fix(spec): the agent.tools liveness row says dead — it claimed live on a key the schema tombstoned #19059: content/docs/ai/agents.mdx was reported as contradicting the agent.tools tombstone over its tools: example at :161, which is inside the defineSkill({ block opened at :155 — the page was already correct. Settle ownership by PARSING the value against both schemas, never by the name: that literal PASSES SkillSchema, and as an AgentSchema it FAILS at tools with the tombstone prescription. ⛔ These names are not the whole class — a key retired through a .strict() guidance map leaves no tombstone in the walked shape and none of them here (tool.category, live as AIToolDefinition.category).

Coarse fallback — 143 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json 6ec0e1222812996230b312da753a592026eaf6d9 → packageMentionDocs.

Which tree this was computed on

This run read content/docs from dce94ca12a2cbf606945c90389c70800196ea7ca — the merge of head e55aa1bfce055fae9fd16db9a9413f34d4084021 into base 6ec0e1222812996230b312da753a592026eaf6d9, which is what actions/checkout gives a pull_request run. Not the PR head.

A worktree cut from an older main holds a different content/docs, so re-deriving there can legitimately return a different list — that is a different tree, not a wrong row. To answer on the same tree:

# while this PR is open — GitHub drops the merge commit once it closes
git fetch origin dce94ca12a2cbf606945c90389c70800196ea7ca && git checkout dce94ca12a2cbf606945c90389c70800196ea7ca
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 6ec0e1222812996230b312da753a592026eaf6d9 e55aa1bfce055fae9fd16db9a9413f34d4084021 && git checkout -B drift-repro 6ec0e1222812996230b312da753a592026eaf6d9 && git merge --no-ff e55aa1bfce055fae9fd16db9a9413f34d4084021

node scripts/docs-audit/affected-docs.mjs --json 6ec0e1222812996230b312da753a592026eaf6d9

⚠️ That checkout carried uncommitted changes, so the commit above does not fully identify what was read.

Advisory only, and a precision-first one (#9192): a page is listed because it names a
symbol, wire route or SDK method this diff touched — not because it mentions a changed
package. Each row says which anchor put it there, so a wrong row is reportable rather than
merely annoying. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs 6ec0e1222812996230b312da753a592026eaf6d9 → pass the list as
args.docs, on the commit named under Which tree this was computed on.

…meta sentence whole

Claude-Session: https://claude.ai/code/session_01Q5DmD3Wg7eTiagmd5p9rqf
Co-authored-by: Claude <noreply@anthropic.com>
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 86c001e7c286788d5078b854bcf36147aa0910b7
Local-runs: none
Scope: packages/spec/src/conversions/refused-shapes.ts, packages/spec/src/conversions/registry.ts, packages/spec/src/migrations/entries/semantic/18.page-list-view-object-name-view-type-retired.ts, packages/spec/src/migrations/entries/semantic/18.view-data-api-provider-retired.ts, packages/spec/src/migrations/registry.ts.template, packages/spec/src/ui/component.zod.ts, packages/spec/src/ui/list-view-retired-aliases.ts, packages/spec/src/ui/page.zod.ts, packages/spec/src/ui/react-blocks.ts + packages/spec/src/ui/view.zod.ts (ListViewShapeSchema, ListViewOverlayWireSchema, ListViewOverlayOptionsSchema, listOverlayPatchFields), packages/spec/src/conversions/walk.ts (mapPageComponents, renameKey), packages/spec/src/conversions/types.ts (retiredAfter), packages/spec/src/ui/component-type-vocabulary.ts, packages/lint/src/validate-component-props.ts, packages/lint/src/authoring-rules.ts (the validateComponentProps entry), packages/lint/src/validate-component-types.ts, packages/lint/src/validate-print-page-blocks.ts, .changeset/22444-list-view-component-props-row.md, packages/spec/src/ui/component-list-view-row.test.ts, packages/spec/src/conversions/page-list-view-object-name-view-type-to-data-type.test.ts, packages/lint/src/validate-component-props-list-view-22444.test.ts, packages/objectql/src/fixtures/hotcrm-4.0.1-published-pages.artifact.json, objectui packages/plugin-list/src/index.tsx at the pin 5e15928b46. The remainder of the diff (the regenerated strictness counts, the three census test ledgers, retired-key-removal-version.pin.test.ts, refused-shapes.test.ts) is the lane seat's ACCEPT at TIER_DEFAULT.

Reviewed as a read of the net diff against main (merge base d9a749bae; origin/main has since moved to b7f29ddfe, and none of its intervening commits touch a file of this PR), the card's body and all 13 comments, PR #24217's body and file list, #24219, and the check-runs on this head. Head unchanged at the time of writing.

① Derived judgments

  1. ComponentPropsMap gains the key 'list-view' (exported from @objectstack/spec/ui): the published key set widens, ComponentProps of 'list-view' now resolves. Right. api-surface/ui.json records the const by name only; check:api-surface runs in Type Check · consumer gates (see the gate line below).
  2. The row's accept set is ListViewSchema.shape by reference (strict, every member the authoring list view declares; name / label optional, so an empty bag passes), columns made optional (shape.columns.optional()), options taken by reference from VIEW_METADATA_MEMBERS.listOverlay.shape.options (the per-kind judged bag; options.grid refused with its existing guidance), and both object-level checks attached (checkListViewCalendarVisualization, checkListViewChartBinding). Verified against main's ListViewOverlayWireSchema: these are the overlay member's two differences the ruling named, and the overlay's third (type without its default plus checkListOverlayTypeNeedsColumns) is correctly NOT taken, since a column-less page node naming a kind is a shape the ruling says passes. Right, and exactly the dispatch shape of 6238503560.
  3. objectName / viewType undeclared, answered by name through the row's guidance, quoting LIST_VIEW_RETIRED_ALIASES notes verbatim. Right: one prescription for both tiers, as ruled.
  4. The props gate narrows for type: 'list-view' nodes. validateComponentProps dispatches on map rows (PROPS_SCHEMAS[type], skip when absent): before this head a page list-view node drew 0 findings whatever its bag; after it, every key outside the row and every value verdict is severity: 'error', and the rule is tier: 'gating', commands: ALL, on the runtime page door (authoring-rules.ts, ruling 6161173492). So os validate / os build / os lint refuse, and a Studio / REST / MCP page save carrying objectName, viewType, kanban.groupField or options.grid on a list-view is refused until rewritten. Right as a mechanism (no dispatch, tier or door change in the diff) and this is the accept-set narrowing ② must carry.
  5. PageSchema / PageComponentSchema accept set unchanged (open properties record, the 2026-08-05 ruling), pinned in component-list-view-row.test.ts. Right.
  6. The type door is unmoved. validateComponentTypes judges only reserved-namespace types (hasReservedComponentNamespace guard); list-view has no colon prefix and rode the open arm before and after. The row neither widens nor narrows component-type-unknown. Right.
  7. PRINT_REFUSED_PAGE_COMPONENT_TYPES gains list-view with the object-grid reason. The print census pin (every vocabulary member is printable or refused, never both) trips on a new map key; before, list-view in a print page was refused by the generic "not in the printable block subset" clause, now by its own reason. Print accept set unchanged. Right.
  8. The refused-stored-shape detector view-data-api-provider-retired now reaches page list-view nodes. componentApiBindingRefusal reads ComponentPropsMap[type].shape.data, so with no row it returned undefined: a stored list-view node binding the retired api provider was NOT listed before and IS listed now. New reach in the right direction, and the surface strings (refused-shapes.ts, the D3 entry) now name it. Right; the PR body's "it reported the node anyway" overstates, the widening is this PR's.
  9. REACT_RETIRED_OVERLAY_PROPS.ListView published value unchanged: the two entries moved byte-identical to ui/list-view-retired-aliases.ts, a leaf outside the ui barrel (the list-view-export-options.ts precedent); react-blocks.ts reads ComponentPropsMap at module load for RECORD_CONTEXT_BLOCK_TAGS, so the row cannot import it. Identity pinned with toBe. check:react-blocks ran in Type Check · source gates, success. Right.
  10. RECORD_CONTEXT_BLOCK_TAGS derives from Object.keys(ComponentPropsMap) filtered to record:*; list-view is not one, so the react publish gate is unmoved. Right.
  11. D2 conversion page-list-view-object-name-view-type-to-data-type (toMajor 18, order 68, retiredFromLoadPath: true, retiredAfter: '17.7.0', the value 30 sibling step-18 entries carry; spec at 18.0.0-next.3). Reach is mapPageComponents (regions, slots, nested containers, source-authored pages). objectName (non-empty string) moves to data: { provider: 'object', object } when data is absent; a twin naming the same object through the object provider is deleted; a non-string or empty alias, a disagreeing dataSource.object, or a disagreeing data is left byte-identical and reported as a TODO. viewType goes through renameKey (deep-equal twin deleted; disagreement returns null, reported as a TODO). Copy-on-write and idempotent, pinned in the new test and the fixture pair (expectedNotices: 4). Consumer at the pin 5e15928b46: plugin-list/src/index.tsx registers list-view with data / type inputs and defaultProps.data, and states objectName / viewType are neither published nor read, so the conversion's target spelling is what the pinned console reads. Right; the ruling's mapping, with the conflict guard the ruling did not spell out but ADR-0087 requires.
  12. D3 entry and step-18 fragment (conversionIds join; fragment order 101, unique; duplicate orders already exist on main, so uniqueness is not an invariant), plus the retired-key-removal-version.pin.test.ts JOIN gaining the two refusals. Right. check:spec-changes / check:upgrade-guide are in-memory projections, nothing to commit.
  13. Not exported: ListViewPageProps mints no def, so authorable-surface/, json-schema/ and the docs are unchanged; check:authorable-surface and check:docs ran in Type Check · source gates, success. Right.
  14. Census pins classified rather than skipped (the z.unknown() member ledger mirroring object-grid's expression, records and bulk-option slots; the requiredPermissions census; strictness counts +1 strict site). Right.
  15. Hold-offs respected: .objectui-sha, objectui, PageSchema's accept set and validate-component-props.ts untouched. Runtime strings carry no tracker number (Lint · docs & code guards, success). Commit trailers are the model-free pair on all 9 commits.

Real-producer reading accepted as stated: the hotcrm 4.0.1 fixture carries 4 page list-view nodes in the old spelling (4 viewType keys on 4 list-view nodes, counted on main), 8 findings unconverted, 8 notices, 0 TODOs, 0 findings converted.

② Semver level

Does not match what the diff publishes. The changeset is @objectstack/spec: minor, Clause-②: yes (widening), a plain feat(spec): summary, no BREAKING line and no ADR-0087 disposition marker. What the diff publishes (judgment 4) is an accept-set narrowing at two error-tier doors: an authored page list-view node that passed os validate / os build / os lint and the Studio / REST / MCP page save at d9a749bae is refused at this head, with one named external producer (hotcrm 4.0.1, 4 nodes) and 0 in-repo producers. Under AGENTS.md Post-Task Checklist 3 the arm is (narrowing), (narrowing) is BREAKING, and a breaking changeset carries its migration (the FROM → TO text is already in the body) and exactly one disposition marker. The three same-class page-row narrowings landed since the error tier each declared it: #23331 (1623fafc3), #23425 (775ed65e2), #23494 (ad5a7d7c3), all ! summary, BREAKING line, registered marker, minor under the launch-window convention. check-adr-0087-registration is green on this head only because the changeset declares nothing breaking; its own header says silence is the one thing it cannot see.

Why the ruling's letter does not settle it on this head: ruling 6100463199 item (2) rests on item (1), "a warning at os validate, build and lint; nothing refused at save", which was true on 2026-10-10 and was moved by two later rulings before this branch was cut (#23244, every component-props finding an error; #23388 ruling 6161173492, the rule on the runtime page door). The dev's report (6239842134, open_questions[0]), the PR's first acceptance note and #24219 all say so. The item is the maintainer's to re-open, and #24219 (needs-user-decision) already carries it with my reading as its recommendation B.

What lifts this section: one changeset patch round on this PR, about three lines in .changeset/22444-list-view-component-props-row.md: Clause-②: yes (narrowing) (yes stays, the exported map widens), a feat(spec)!: summary, one BREAKING line naming the save-door narrowing, and the HTML-comment marker adr-0087: registered page-list-view-object-name-view-type-to-data-type (the conversion this PR already ships); bump stays minor; pnpm check:adr-0087-registration must then be green on the new head, which takes a new record. If the maintainer instead answers A on #24219, that answer is the ruling of record for this item and a record re-rendered on this head carries it as the ② basis.

Clause-②: line on the PR body: yes (no arm), well-formed; the changeset carries the arm, and that arm is what is wrong.

③ Boundary flags

  • Dev deviation 1 (surface widened to page.zod.ts, refused-shapes.ts, the view-data-api-provider-retired D3 entry, three test ledgers, the strictness counts): each is a census pin tripped by the new map key and each is classified, not skipped (judgments 7, 8, 14). Accepted.
  • Dev deviation 2 (react-blocks.ts edited; leaf module): the TDZ reason holds (judgment 9), the published value is identical, the claim allowed the edit for exactly this case. Accepted.
  • Dev deviation 3, open_questions[0], acceptance note 1 (error tier and save door, not the ruling's "warning"): this is ②. Escalated; [Decision] #22444's page list-view row refuses the old objectName / viewType spelling at os validate and the page save door, but ruling C declared it yes (widening) on a warning-tier premise: declare the narrowing? #24219 carries it. Answer from this review: B.
  • Dev deviations 4, 5, 6 (no PR-activity subscription; worktree cut from the primary checkout with BASE pinned at d9a749bae; model-free trailer pair): process notes, verified where verifiable (trailers on all 9 commits). Accepted.
  • open_questions[1], acceptance note 2 (columns optional whatever the binding): answered A. The row judges the bag and cannot see the node's dataSource; the overlay member's own difference is unconditional (listOverlayPatchFields); a binding-aware rule is a lint dispatch change the ruled shape excludes and would refuse column-less nodes the renderer draws. The claim's "under a dataSource.view binding" was the reason, not a condition.
  • out_of_scope_findings[0], acceptance note 3 (objectui ListViewPropsBag at the pin makes the kanban block's columns optional; the spec row keeps ListViewSchema's kanban block): a page kanban whose block omits columns passes objectui's face and is refused error at the spec's save door. Two ends of one internal contract disagreeing on one authored shape is a metadata-authoring trap under Prime Directive chore: version packages #10, not a note: it needs a card (objectui converges its bag on the spec row, or the spec decides the page kanban block's columns). Escalated to the lane seat to file; this review's write budget is one comment. Not a FAIL item for this PR, which does not move the kanban block.
  • out_of_scope_findings[1] (check:dual-build-cjs-loads not measured locally): hosted by ci.yml Build Core, which concluded success on this head.
  • Acceptance note 4 (hold-offs): confirmed (judgment 15).
  • Check-runs on this head at the second reading (their conclusions are the gate verdicts): 32 of 39 complete, every one success or skipped, among them Lint & Repo Gates, Governed Surface Queue Guard, Build Core, Check Changeset, Spec property liveness, Type Check · source gates, Type Check · consumer gates (check:api-surface) and Type Check · debt ledger; still in_progress: Test Core 1-6 and Type Check · workspace, so the required TypeScript Type Check aggregate has not reported yet. Not waited on. The spec and lint test files this review relies on (the row test, the conversion test, the lint pin, the fixture pair in conversions.test.ts) are therefore the dev's local run (6239842134) until Test Core concludes.

Implemented-by: claude/issue-22444-list-view-component-props-row-c
Reviewed-by: session_01TyRhWbVbbQpQJTDbW8VahJ

VERDICT: FAIL

Scope of the FAIL: section ② only. Sections ① and ③ hold; the implementation is ruling C's spec half as ruled and as measured. The fix is one changeset patch round (or the maintainer's letter on #24219), then a new record on the head that carries it.


Generated by Claude Code

…lias prescription, in one literal

Claude-Session: https://claude.ai/code/session_01Q5DmD3Wg7eTiagmd5p9rqf
Co-authored-by: Claude <noreply@anthropic.com>
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Pointer — #24219 ruled A. From the director seat, summon #44 (session_01MVLumUXJ6mkcQv27o7LR1V), 2026-10-18T00:04Z.

Ruling 6243467550, the maintainer's 「24217 A」, keeps this PR's changeset as shipped: Clause-②: yes (widening), minor, no BREAKING line, no ADR-0087 marker. It answers ② of contract review 6240571802, so the next record on this head takes the ruling as its ② basis. The landing seat (domain:spec seat 1) re-renders that record and lands the PR once CI is green. This seat serves below CONTRACT_REVIEW_TIER in this summon and writes no record.

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: e55aa1bfce055fae9fd16db9a9413f34d4084021
Local-runs: none
Scope: packages/spec/src/conversions/refused-shapes.ts, packages/spec/src/conversions/registry.ts, packages/spec/src/migrations/entries/semantic/18.page-list-view-object-name-view-type-retired.ts, packages/spec/src/migrations/entries/semantic/18.view-data-api-provider-retired.ts, packages/spec/src/migrations/registry.ts.template, packages/spec/src/ui/component.zod.ts, packages/spec/src/ui/list-view-retired-aliases.ts, packages/spec/src/ui/page.zod.ts, packages/spec/src/ui/react-blocks.ts + packages/spec/src/ui/view.zod.ts (ListViewShapeSchema, ListViewSchema, ListViewOverlayOptionsSchema, listOverlayPatchFields, ListViewOverlayWireSchema, VIEW_METADATA_MEMBERS), packages/spec/src/shared/strict-object.ts and packages/spec/src/shared/suggestions.zod.ts (guidance / guidanceSets to the unknown-key message), packages/spec/src/shared/lazy-schema.ts, packages/spec/src/conversions/walk.ts (mapPageComponents, renameKey), packages/spec/src/conversions/types.ts (retiredAfter), packages/spec/src/conversions/stored.ts, packages/spec/src/migrations/types.ts (SemanticMigration.conversionIds), packages/spec/src/ui/component-type-vocabulary.ts (KNOWN_COMPONENT_TYPES), packages/spec/src/ui/page-print.test.ts (the print census pin), packages/lint/src/validate-component-props.ts, packages/lint/src/authoring-rules.ts (the validateComponentProps entry), packages/lint/src/validate-component-types.ts, packages/lint/src/validate-print-page-blocks.ts, scripts/check-adr-0087-registration.mjs (header), packages/spec/api-surface/ui.json (ComponentPropsMap, KNOWN_COMPONENT_TYPES), .changeset/22444-list-view-component-props-row.md, packages/spec/src/ui/component-list-view-row.test.ts, packages/spec/src/conversions/page-list-view-object-name-view-type-to-data-type.test.ts, packages/lint/src/validate-component-props-list-view-22444.test.ts, packages/objectql/src/fixtures/hotcrm-4.0.1-published-pages.artifact.json. The remainder of the diff (the regenerated strictness counts under docs/audits/, the three census ledgers component-props-unknown-members.pin.test.ts, component-record-block-field-security.test.ts, retired-key-removal-version.pin.test.ts, and refused-shapes.test.ts) is the lane seat's ACCEPT at TIER_DEFAULT.

Re-rendered record. It supersedes 6240571802 (same reviewer, head 86c001e7c), whose ② FAIL named one item; that item is now ruled by the maintainer (6243467550 on #24219, 「24217 A」), and this record takes the ruling as its ② basis. Read: the card's body and all 15 comments, #24219's body and all 3 comments, PR #24217's body, file list (18 files, +849 −28) and net diff against main (merge base d9a749bae), the director's pointer 6243498936, and the check-runs on this head. origin/main stood at 6e43b7bc3f at the time of reading, 22 commits past the merge base, none of them touching a file of this PR; mergeable_state: clean. Head unchanged while this was written. The delta from 86c001e7c to this head is one commit: the react-tier note in each alias prescription moved one sentence earlier so the house os migrate meta sentence closes the literal, plus one word in the conversion's docblock.

① Derived judgments

  1. ComponentPropsMap gains the key 'list-view' (an exported const of @objectstack/spec/ui). The published key set and ComponentProps of 'list-view' widen. api-surface/ui.json:120 records the const by name only, so the snapshot is unchanged; check:api-surface ran in Type Check · consumer gates, success. Right.
  2. The row's accept set is ListViewShapeSchema's members by reference (every member the same schema object, pinned with toBe), columns the same member made optional, and options the list overlay member's own judged bag by reference (ListViewOverlayOptionsSchema.optional() through VIEW_METADATA_MEMBERS.listOverlay.shape.options: per-kind blocks, options.grid refused with its existing guidance). Both object-level checks are attached, so a chart with no dataset binding is refused with the authoring door's own issues (pinned). The overlay member's third difference, type without its default plus checkListOverlayTypeNeedsColumns and the default overwrite, is correctly NOT taken: a column-less page node naming a kind is a shape the ruling says passes. guidanceSets carries the visibility set only, not COMPONENT_LEVEL_GUIDANCE: the second set there names responsive, which ListViewShapeSchema declares, and the alias-integrity audit refuses a pattern set whose key the row declares (the record:alert precedent). Right, and exactly the dispatch shape of claim 6238503560.
  3. objectName / viewType undeclared, answered by name through the row's guidance, which strictUnknownKeyError turns into the unknown-key issue's message. Each prescription quotes LIST_VIEW_RETIRED_ALIASES[alias].note verbatim and closes with the house os migrate meta sentence in one literal (the patch round; retired-key-migrate-sentence.test.ts runs under Test Core, success on this head). One prescription for both tiers, as ruled. Right.
  4. The component-props gate narrows for type: 'list-view' nodes. validateComponentProps dispatches on PROPS_SCHEMAS[type] and skips an absent row; every finding it emits is severity: 'error'; its authoring-rules.ts entry is tier: 'gating', commands: ALL, on the runtime page door by ruling 6161173492. So an authored page list-view node that drew 0 findings whatever its bag now meets an error for every undeclared key and every value verdict at os validate / os build / os lint and at the Studio / REST / MCP page save. The diff changes no dispatch, tier or door; the narrowing is the row meeting the rule as it stands on main. Right as a mechanism, and the fact ② carries to the ruling.
  5. PageSchema / PageComponentSchema accept set unchanged: the carrier stays an open record (the 2026-08-05 ruling), pinned in component-list-view-row.test.ts. Right.
  6. The type door is unmoved. validateComponentTypes judges reserved-namespace types only (hasReservedComponentNamespace at :202); list-view has no colon. KNOWN_COMPONENT_TYPES (exported, derived from Object.keys(ComponentPropsMap)) now holds list-view, so the exported isKnownComponentType answers true for it: a widening in the right direction (the pinned console registers the type), and nothing outside the vocabulary module and its tests reads the predicate. Right.
  7. PRINT_REFUSED_PAGE_COMPONENT_TYPES gains list-view. page-print.test.ts:187 requires every live known type to be printable or refused; the new key tripped it. Before, validatePrintPageBlocks refused list-view in a print page through the generic "not in the printable block subset" clause; now through its own reason, worded to the pin. The print accept set does not move. Right.
  8. The view-data-api-provider-retired detector reaches page list-view nodes for the first time. componentApiBindingRefusal reads ComponentPropsMap[type].shape.data and answers undefined with no row, so a stored page list-view node binding the retired api provider was not listed before this head and is listed now; the surface strings in refused-shapes.ts and the D3 entry name it, and the test fixture rightly omits objectName on a list-view. New reach, right direction. Right. (The dev report's "the detector already reported it" is the one overstatement in the thread; the PR body corrects it.)
  9. REACT_RETIRED_OVERLAY_PROPS.ListView published value unchanged: the two entries moved byte-identical to ui/list-view-retired-aliases.ts, a leaf the ui barrel does not export (the list-view-export-options.ts precedent); react-blocks.ts reads ComponentPropsMap at module load for RECORD_CONTEXT_BLOCK_TAGS, so the row cannot import it. Identity pinned with toBe; check:react-blocks ran in Type Check · source gates, success. Right.
  10. RECORD_CONTEXT_BLOCK_TAGS filters the map's keys to record:*; list-view is not one, so the react publish gate is unmoved. Right.
  11. D2 conversion page-list-view-object-name-view-type-to-data-type (toMajor 18, order 68 under inApplicationOrder, where duplicate orders already exist on main so uniqueness is not an invariant; retiredFromLoadPath: true; retiredAfter: '17.7.0', the value 31 sibling step-18 entries carry, read by the artifact-ingestion door and pinned by retired-after.census.test.ts). Reach is mapPageComponents: regions, slots, nested containers. objectName moves to data: { provider: 'object', object } when it is a non-empty string, no node-level dataSource.object names a different object, and data is absent; a same-object object-provider twin is deleted; any other case is left byte-identical and reported as a TODO. viewType goes through renameKey: type absent means rename, a deep-equal twin is deleted, a disagreement returns null and is reported as a TODO. Copy-on-write and idempotent, pinned in the new test and in the fixture pair (expectedNotices: 4); the authoring funnel never replays it (pinned); applyConversionsToStoredItem replays it with includeRetired: true. The one case the walker resolves on its own, an alias beside an agreeing dataSource.object with data absent, writes a second consistent binding rather than deleting the alias; two agreeing answers, not a conflict. Right: the ruling's mapping with the conflict guard ADR-0087 requires.
  12. D3 entry and step-18 fragment. The entry carries the five required fields, surface without backticks or pipes, and conversionIds joining the D2 (the type's own doc admits an id only when the entry judges that conversion's output; the TODO judgment is that). The template fragment (order 101, unique at this head; joinRationale consumes it) names the entry id. check:spec-changes / check:upgrade-guide are in-memory projections, nothing to commit, green. Right.
  13. Not exported. ListViewPageProps is a module-local const, so no def is minted and authorable-surface/, json-schema/ and the docs are unchanged; check:authorable-surface and check:docs ran in Type Check · source gates, success. Right.
  14. Census pins classified rather than skipped: the z.unknown() member ledger (list-view beside object-grid for the expression, record and bulk-option slots it shares by reference), the requiredPermissions census (the row carries ListViewShapeSchema.requiredPermissions), the retired-prescription JOIN, and the strictness counts (+1 strict site in component.zod.ts, a file that already has its hand row, so check:strictness-ledger under check:generated needs no hand edit). Right.
  15. Changeset coverage. @objectstack/spec: minor is the only released package the diff changes; the packages/lint change is a test file. Check Changeset success.
  16. Hold-offs and house rules. .objectui-sha, objectui, PageSchema's accept set and validate-component-props.ts untouched. Runtime strings (the guidance, the TODO reason, the D3 prose, the conversion summary) carry no tracker number. All 10 commits carry the model-free trailer pair. Right.
  17. Real-producer reading, re-counted on this head's fixture: the hotcrm 4.0.1 artifact holds 4 page list-view nodes, each columns / filter / sort / objectName / viewType: 'grid' with no node-level dataSource, three of them nested in page:tabs items. Consistent with 8 findings unconverted, 8 notices, 0 TODOs, 0 findings converted.

② Semver level

Matches, against the ruling of record. What the diff publishes is two things at once: the exported ComponentPropsMap key set widens (judgment 1), and the accept set at two error-tier doors narrows for authored page list-view nodes (judgment 4), with one named external producer and 0 in-repo producers. On AGENTS.md Post-Task Checklist 3 alone, the previous record read the second as (narrowing) and FAILed this section; the item was the maintainer's to re-open, because ruling C item (2) had settled yes (widening) on a premise two later rulings moved, and #24219 carried it. The maintainer ruled it: 6243467550, 「24217 A」, against the seat's recommendation B. Under A the changeset stays as shipped, Clause-②: yes (widening), minor, no !, no BREAKING line, no ADR-0087 marker; ruling C item (2) stands with the error tier and the page save door as they are on main. A maintainer ruling outranks AGENTS.md for the item it rules, and this one does.

Against that ruling the changeset is well-formed and complete: yes (the published map widens; yes takes at least minor, and the bump is minor); (widening) is the ruled arm and the one arm present; the body states the FROM → TO mapping and the house os migrate meta --from 17 --write sentence anyway, so an upgrading author who greps the CHANGELOG entry for objectName or viewType still lands on the fix; check-adr-0087-registration reads only a declared-breaking changeset and has nothing to read here, green. The Clause-②: line on the PR body is yes, no arm, well-formed and consistent with the changeset's arm.

What this section records so the ledger of the review stays honest: the narrowing at the save door is real (judgment 4), it is not announced as BREAKING by the maintainer's choice, and under A the hotcrm card the ruling orders at landing (③) is that producer's only notice.

③ Boundary flags

  • Dev deviation 1 (surface widened to page.zod.ts, refused-shapes.ts, the view-data-api-provider-retired D3 entry, three test ledgers, the strictness counts): each is a census pin tripped by the new map key and each is classified rather than skipped (judgments 7, 8, 14). Accepted.
  • Dev deviation 2 (react-blocks.ts edited; the leaf module): the module-load reason holds and the published value is identical (judgment 9); the claim allowed the edit for exactly this case. Accepted.
  • Dev deviation 3, open_questions[0], acceptance note 1 (error tier and save door, not the ruling's "warning"): escalated on [Decision] #22444's page list-view row refuses the old objectName / viewType spelling at os validate and the page save door, but ruling C declared it yes (widening) on a warning-tier premise: declare the narrowing? #24219, ruled A (6243467550). Closed by the ruling; it is this record's ② basis.
  • Dev deviations 4, 5, 6 (no PR-activity subscription; worktree cut from the primary checkout with BASE pinned at d9a749bae; the model-free trailer pair): process notes, verified where verifiable (trailers on all 10 commits). Accepted.
  • Patch-round deviations (6241238026: the react-tier note moved before the house sentence; 86c001e7c pushed red and e55aa1bfc fixed it, no history rewritten): the note is still quoted verbatim (pinned with toContain in both the spec and the lint tests), and Test Core concluded success on this head. Accepted.
  • open_questions[1], acceptance note 2 (columns optional whatever the binding): answered A. The row judges properties and cannot see the node's dataSource; listOverlayPatchFields makes the overlay member's columns optional unconditionally; the dispatch shape's "under a dataSource.view binding" was the reason, not a condition; a binding-aware rule is a lint dispatch change the ruled shape excludes and would refuse column-less nodes the renderer draws.
  • out_of_scope_findings[0], acceptance note 3 (objectui's ListViewPropsBag at the pin makes the kanban block's columns optional; the spec row keeps ListViewSchema's kanban block, so a page kanban whose block omits columns passes objectui's face and is refused error at the spec's save door): two ends of one internal contract disagreeing on one authored shape is a metadata-authoring trap under Prime Directive chore: version packages #10. Stays escalated to the lane seat to file as a card (objectui converges its bag on the spec row, or the spec decides the page kanban block's columns); this review's write budget is one comment. Not a FAIL item for this PR, which does not move the kanban block.
  • out_of_scope_findings[1] (check:dual-build-cjs-loads not measured in round 1): the patch round re-ran it locally at exit 0, and Build Core concluded success on this head.
  • Ruling term carried to landing (6243467550, and the director's pointers 6243490831 / 6243498936): at landing the domain:spec seat files the hotcrm card (src/sales/pages/home.page.ts, helper embeddedListView, 4 nodes meeting 8 errors at os validate on the spec release carrying this PR; rewrite to data: { provider: 'object', object } and type: 'grid', or run os migrate meta --from 17 --write), or names the existing pin-bump card. Flagged here so the obligation travels with the landing; it does not gate the verdict.
  • Governance and size: no governed surface in the file list; head repo equals base repo; 877 changed lines; a Clause-②: yes on a published packages/spec/src/** schema is why the review is at this tier. The landing is the lane seat's, on this record plus green.
  • Check-runs on this head (their conclusions are the gate verdicts): 48 check-runs, all completed, none in_progress, none failure. The five required contexts Lint & Repo Gates, TypeScript Type Check, Test Core, Build Core and Governed Surface Queue Guard each concluded success, as did Check Changeset, Spec property liveness, Test Core (1/6) to (6/6), Type Check · source gates / consumer gates / debt ledger / workspace, every Lint · lane, and Dogfood Regression Gate. The skipped set is path-filtered or opt-in on a PR run (Build Docs, Console Pin Gate, Temporal Conformance, Dogfood Verify CLI, the dogfood shards, Packed-tarball smoke) plus the re-triggered duplicates of Auto Label and Check PR Size.

Implemented-by: claude/issue-22444-list-view-component-props-row-c
Reviewed-by: session_01TyRhWbVbbQpQJTDbW8VahJ

VERDICT: PASS

Sections ① and ③ hold as in 6240571802; ② now matches the changeset against the ruling of record. The implementation is ruling C's spec half as ruled and as measured, and the PR can land through the queue once the lane seat arms it.


Generated by Claude Code

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

席位核对 · ACCEPT · PR #24217 @ e55aa1bfce (#22444) · domain:spec seat 1 · os-project-manager · session session_01TyRhWbVbbQpQJTDbW8VahJ · 2026-10-18T00:17Z

Reviewer of record. Every item below was checked against GitHub and the code, not against the reports (6239842134 and 6241238026 on #22444).

  • Shape: draft, base main. The first line is Fixes #22444, the body's only closing keyword, then Clause-②: yes, matching claim 6238503560. 18 files, +849/−28, assignee os-project-manager. Not governed: check-governed-merges.mjs --pr 24217 reads 0 of 18 paths on the register, 877 lines (under 3000). origin/main is 22 commits past the merge base d9a749bae, and none of those commits touches a file of this PR.
  • What it lands (ruling C's spec half, 6100463199):
    • The list-view row in ComponentPropsMap: ListViewSchema's members by reference, plus the list overlay member's two differences (columns optional; options judged per kind, with options.grid refused). Both object-level checks are attached.
    • objectName / viewType are refused by name, with the react tier's prescription. That prescription is now declared once, in a leaf module, and REACT_RETIRED_OVERLAY_PROPS's published value is unchanged.
    • The ADR-0087 D2 conversion page-list-view-object-name-view-type-to-data-type (retired from the load path), its D3 entry and its step-18 fragment.
    • Census pins, each classified rather than skipped, and a minor changeset.
  • Clause-② arm: the dev measured the ruling's "a warning" premise as false: feat(lint)!: every component-props finding is an error at os validate, os build and os lint #23244 made every component-props finding an error, and feat(lint)!: the two page component rules run on the runtime publish door (ruling B) #23418 put the rule on the page save door. That conflict was filed as [Decision] #22444's page list-view row refuses the old objectName / viewType spelling at os validate and the page save door, but ruling C declared it yes (widening) on a warning-tier premise: declare the narrowing? #24219, and the PR stayed unarmed. The maintainer ruled A (6243467550, 「24217 A」): the changeset stays Clause-②: yes (widening), minor, with no BREAKING line.
  • Contract review: PASS 6243628562 on this head (CONTRACT_REVIEW_TIER), re-rendered with that ruling as its ② basis. It supersedes 6240571802, whose only FAIL was that item; ① and ③ held then and hold now.
  • Patch round 1: fixed this PR's own Test Core red: the test:repo house-sentence pin, which vitest --project local did not run. The reorder deviation is accepted: the scanner requires the house sentence to close the merged literal. The PR body records the round, and the seat corrected one overstated sentence in it (review ① item 8).
  • Gates: 48 check-runs on e55aa1bfce, all completed: 40 success, 8 skipped (all in check-expected-skips.mjs's roster, matched by name). The five required contexts are success. Mergeable, state clean.
  • Open questions: Q1 was ruled A, as above. Q2 is A (columns optional whatever the binding; both review records agree).
  • Review ③, the kanban columns divergence (objectui's ListViewPropsBag takes it optional, while the spec row requires it): no card, below the filing gate. It has no reach:: 0 page list-view kanban producers were measured, and the one objectui writer of { groupByField } alone, CreateViewDialog, writes the view door, not a page node. It is recorded on the seat post as a pointer for this lane.
  • Ruling term, carried to landing: hotcrm's live source (src/sales/pages/home.page.ts, embeddedListView, 4 nodes) writes the old spelling. The seat confirmed it in a read-only clone at hotcrm 4f82b81. At landing the seat files the hotcrm upgrade card, or names the existing pin-bump card.

The PR goes to the merge queue in this act. The cloud dev session is archived.


Generated by Claude Code

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review October 18, 2026 00:19
@objectstack-fleet
objectstack-fleet Bot enabled auto-merge October 18, 2026 00:19
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Oct 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation protocol:ui size/l tests tooling

Projects

None yet

2 participants