Skip to content

feat(spec)!: the page parse refuses a component data prop naming the retired view-level api source, at every door that parses a page - #23419

Merged
objectstack-fleet[bot] merged 8 commits into
mainfrom
claude/issue-23357-page-component-api-data
Oct 14, 2026
Merged

objectstack-fleet[bot] merged 8 commits into
mainfrom
claude/issue-23357-page-component-api-data

Conversation

@objectstack-fleet

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

Copy link
Copy Markdown
Contributor

Fixes #23357

Clause-②: yes (narrowing)

The seat amended the claim to yes (narrowing) at ACCEPT because of the one published export, checkPageComponentViewData.

What changes

The page parse now refuses a page component's data prop that names the retired view-level api data source, as a view's own data is refused. That is triage's runtime half of this card (grade 6159116611): the narrow judge for ViewDataSchema at a component's data, enforced at every door that parses a page. It is not the component-props gate's runtime rollout, which stays as decided.

  • packages/spec/src/ui/page.zod.ts: a fifth PageSchema object-level check, checkPageComponentViewData, attached by identifier like its four siblings. For a component of a type whose data is a view data source (object-grid, object-map, object-gantt, object-tree) whose properties.data names the retired provider, it raises the prescription ViewDataSchema's own parse raises, located at the component's properties.data.provider (code custom, the code of every object-level check on this schema). The prescription is read off ViewDataSchema's issue, not copied. It walks every component under regions and slots at any depth, a component nested in a page:tabs item or a container included.
  • packages/spec/src/conversions/refused-shapes.ts: the stored listing's fate for such a component now says what happens: the parse refuses the page; it still loads and is served, registered under [metadata_spec_invalid] with the refusal in every read's _diagnostics; its next save is refused with 422.
  • packages/spec/src/migrations/entries/semantic/18.view-data-api-provider-retired.ts: the acceptance criteria name the page parse, at every door that parses a page, beside the component-props gate.
  • view.zod.ts: a comment pointing from the retirement's prescription to the page check. Generated: api-surface/ui.json, export-origins/ui.json (the one new export).

The renderer half is objectstack-ai/objectui#12325, which remains open: until objectui deletes its reader of the retired arm, a page already stored with such a component keeps sending the request.

Measured (mechanism hypotheses)

  • H1, half falsified. view.zod.ts refuses the arm through the discriminated union's error map: invalid_union at provider, message VIEW_DATA_API_PROVIDER_RETIRED. page.zod.ts does NOT parse a component's data: properties is z.record(z.string(), z.unknown()), and on origin/main PageSchema.safeParse of an app page whose object-grid binds the retired provider answered success: true.
  • H2, holds. The save door's schema is getMetadataTypeSchema('page'), which is PageSchema by identity (resolveOverlaySchema, protocol.ts). Measured through the real saveMetaItem in protocol.save-union-issues.test.ts: 422 INVALID_METADATA, nothing persisted, issue at regions.0.components.0.properties.data.provider, code custom, the prescription. metadata-protocol/src/protocol.ts is untouched.
  • H3, the four, and only by declaration. Derived from ComponentPropsMap by def identity, the rows whose data member is ViewDataSchema are exactly object-grid, object-map, object-gantt, object-tree (59 rows; object-kanban, object-calendar, object-timeline take a row array). The page check cannot derive that set itself: component.zod.ts imports page.zod.ts, packages/spec/src has zero import cycles (measured: 1383 modules, 0 strongly connected components), and moving ElementDataSourceSchema / RETIRED_PAGE_COMPONENT_TYPES out of page.zod.ts would change the published skill's generated references. So the set is declared in page.zod.ts (the PRINT_REFUSED_PAGE_COMPONENT_TYPES precedent) and pinned equal to the derivation in both directions (page-component-view-data.test.ts: for every props row, the page parse refuses the binding exactly when the row's data is ViewDataSchema). The same cycle keeps pageComponentSlotPositions() out of reach, so the walk descends every object under regions and slots, a superset of every slot position: it reaches no less than os migrate meta --stored lists or the props gate judges, and what it judges at a node stays the one retired binding on those four types.
  • H4, stored pages load and are listed; their next save is refused. Boot hydration (loadMetaFromDb, measured with a throwaway probe over a stub engine, not committed): two stored pages, one bound to the retired provider: {"loaded":2,"errors":0,"invalid":1}, both registered, one [metadata_spec_invalid] warning naming page/partner_page and the prescription. Read path (getMetaItem, pinned): served, with _diagnostics.valid: false and the prescription at the component's position. The fate text states exactly that.

Tests

Every run went through scripts/pm/os-verify-lock.sh. Final verdicts are at 63e1e4800, the branch merged with origin/main c857a93ee. The newest head, dce543307, adds only the changeset's Clause-② line.

  • @objectstack/spec, vitest run --project local: 675 files, 20507 passed, 1 todo, exit 0.
  • @objectstack/spec, --project repo: 59 files, 1011 passed, exit 0. This project holds the tree-scoped absence pin.
  • @objectstack/metadata-protocol: 235 files passed, 3 skipped; 28377 tests passed, exit 0.
  • @objectstack/cli, --project unit: 287 files, 4307 tests passed, exit 0.
  • @objectstack/lint: 138 files, 6699 tests passed, exit 0, at 7309ef08c. The later merge touched nothing in packages/lint.
  • typecheck of spec and of metadata-protocol: exit 0 each.
  • pnpm --filter @objectstack/spec check:generated: all 14 artifacts up to date.

New pins:

  • packages/spec/src/ui/page-component-view-data.test.ts:
    • each of the four types is refused at regions.0.components.0.properties.data.provider with the retirement's exact message;
    • a nested component, a container's grandchild and a slot are each refused at their own position;
    • definePage, getMetadataTypeSchema('page') and the stack parse all refuse;
    • controls: object, value, schema, no data, another provider, object-kanban, a custom type and the element dataSource binding are accepted;
    • a derivation pin over all 59 ComponentPropsMap rows.
  • object-refinement-check-exports.test.ts: the fifth export's parity, count, attachment and barrel legs.
  • refused-shapes.test.ts: the new fate text, and the page parse refuses exactly the positions the listing lists.
  • protocol.save-union-issues.test.ts:
    • 422 INVALID_METADATA with nothing persisted, top-level and nested;
    • control saves with object and value (one row each);
    • the read path serves a stored page with _diagnostics.valid: false and the prescription.

Not run locally, and declared to CI:

  • the cli integration layer: the diff touches no integration file and no spawn entry;
  • the full turbo ls --affected closure, 83 packages. That set comes from the package dependency graph and is blind to tests that read another package's source from disk. The root package's own suites are not on the graph.

Ablation (negative control)

Run on 7309ef08c through scripts/ablation-replace.mjs, which mutates and restores and proves both on disk, and scripts/ablation-dist-preflight.mjs.

  1. Pristine. The dist marker superRefine(checkPageComponentViewData)) is present in 18 built JS files, and the tree is clean.
  2. Mutate. The attachment .superRefine(checkPageComponentViewData)); is replaced by an inert comment. The anchor count goes 1 to 0, and the blob goes ed11df9efb60 to b310419cea20.
    • The spec source suites go red: 3 files, 17 failed, 268 passed. They are the four type pins, nested/slot, doors, self-reference, the derivation pin, the export parity/count/attachment legs, and the two refused-shapes parity pins.
    • After the spec rebuild, the preflight reads the marker absent from all 232 built files.
    • protocol.save-union-issues.test.ts goes red: 3 failed, 26 passed. They are the two 422 pins and the read path. The control save stays green.
  3. Restore. The blob equals HEAD, git diff HEAD is empty and the whole-tree status is clean. After the spec rebuild, the marker is present in 18 files and the tree is clean. Spec runs 285/285 and metadata-protocol 29/29.

The expected direction: the pins turn red.

Two earlier attempts carry no reading:

  • The first was a no-op. The tool refused it because the replacement ); already occurred in the file, so the mutation never landed.
  • The second used a dist marker that the .d.ts docblock also carries, so its dist reading was void. It was re-run as above, with a marker only the runtime JS carries.

Gates

node scripts/pm/dispatch-gates.mjs --ran on 7309ef08c reports 90 derived families, all accounted for. 88 exited 0, including check:adr-0087-registration --base origin/main, check:api-surface, check:generated (all 14 artifacts up to date), check:skill-refs, check:doc-authoring, check:engine-double-contract, check:nul-bytes, check:lean-entry-closure and check:cross-package-test-inputs.

NOT MEASURED:

  • check:dual-build-cjs-loads: exit 3, PREREQUISITE NOT MET. 9 packages outside this card's build closure have no dist/.
  • check:type-check-debt: its re-measure re-runs tsc over every DEBT-ledger package repo-wide, which CI owns. The touched packages' own typecheck runs are green.

Repo-wide pnpm lint was not run locally. CI owns it.

Acceptance notes

  • One published export added (checkPageComponentViewData), required by object-refinement-check-exports.test.ts for every object-level PageSchema check so a .shape mirror can re-attach it; see the Clause-② note at the top.
  • The page check's issue code is custom, not the view's invalid_union: the object-level-check pin reads custom as the code of every check on the schema. The message is the retirement's, byte for byte.
  • ADR-0087: not-required (already-registered view-data-api-provider-retired); check-adr-0087-registration accepts it.
  • Consumer sweep: examples/** holds no provider: 'api' (0 hits; control provider: 'object' hits in examples/app-crm/src/views); the tree-scoped absence pin (view-data-api-provider-retirement.test.ts) is green, and every fixture here spells the provider through a constant.

Generated by Claude Code

…e retired view-level api provider

A page component whose `data` prop is a view data source (object-grid,
object-map, object-gantt, object-tree) is judged by `PageSchema` through
the retirement's own judge, `ViewDataSchema`: the `invalid_union` issue it
raises at `provider` is raised unchanged at the component's
`properties.data.provider`, at any depth under `regions` and `slots`.

Claude-Session: https://claude.ai/code/session_01YRp5z4kK6vgYkrdH97ztsy
Co-authored-by: Claude <noreply@anthropic.com>
…tored page's fate

The listing's fate for a page component bound to the retired view-level
api source now says the parse refuses the page: it still loads and is
served under [metadata_spec_invalid], reads carry the refusal in
_diagnostics, and its next save is refused with 422. The step-18 entry's
acceptance criteria name the page parse beside the component-props gate.

Claude-Session: https://claude.ai/code/session_01YRp5z4kK6vgYkrdH97ztsy
Co-authored-by: Claude <noreply@anthropic.com>
…w-level api source is refused at the save door

Claude-Session: https://claude.ai/code/session_01YRp5z4kK6vgYkrdH97ztsy
Co-authored-by: Claude <noreply@anthropic.com>
…evel api data binding

Claude-Session: https://claude.ai/code/session_01YRp5z4kK6vgYkrdH97ztsy
Co-authored-by: Claude <noreply@anthropic.com>
…omponentViewData

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

github-actions Bot commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/spec, touching 5 documentable anchor(s). ⚠️ 3 changed file(s) yielded no anchor (packages/spec/api-surface/ui.json, packages/spec/export-origins/ui.json, packages/spec/src/ui/view.zod.ts), so the pages documenting them are NOT COVERED by this run — this is not a clean bill of health for those files.

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

  • content/docs/protocol/objectui/layout-dsl.mdx (via PageSchema (symbol, a top-level const))
What this run could not see
  • 3 changed file(s) yielded no anchor (packages/spec/api-surface/ui.json, packages/spec/export-origins/ui.json, packages/spec/src/ui/view.zod.ts) — pages documenting those are invisible to this run
  • 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 — 142 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 a7a135dc267f0d154aca453f098c49ce8aac550c → packageMentionDocs.

Which tree this was computed on

This run read content/docs from 543d9f315c7e97cc8526f20a83f5ef662c7d126a — the merge of head dce5433072dcd82b591b3fc3831927cf1cbc0007 into base a7a135dc267f0d154aca453f098c49ce8aac550c, 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 543d9f315c7e97cc8526f20a83f5ef662c7d126a && git checkout 543d9f315c7e97cc8526f20a83f5ef662c7d126a
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin a7a135dc267f0d154aca453f098c49ce8aac550c dce5433072dcd82b591b3fc3831927cf1cbc0007 && git checkout -B drift-repro a7a135dc267f0d154aca453f098c49ce8aac550c && git merge --no-ff dce5433072dcd82b591b3fc3831927cf1cbc0007

node scripts/docs-audit/affected-docs.mjs --json a7a135dc267f0d154aca453f098c49ce8aac550c

⚠️ 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 a7a135dc267f0d154aca453f098c49ce8aac550c → pass the list as
args.docs, on the commit named under Which tree this was computed on.

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: dce5433072dcd82b591b3fc3831927cf1cbc0007
Local-runs: none

Inputs: card #23357 (body; comments 6159116611 triage, 6160762995 claim amended in place, 6163363165 seat-3 pointer, 6164084655 regrade, 6164488810 os-dev-report, 6164621776 ACCEPT); PR #23419 body, its 11-file list and the net diff against the merge-base c857a93ee (+493/-17); the check-runs on dce543307 and on the prior head 63e1e4800 (differs by one changeset line, the Clause-② arm); the committed source on origin/claude/issue-23357-page-component-api-data and origin/main. Nothing was built, run or re-run.

① Derived judgments

(a) The narrowing — right. checkPageComponentViewData (page.zod.ts, the fifth PageSchema object-level check) fires only when a node's type is one of object-grid / object-map / object-gantt / object-tree, its properties is a non-array object, and properties.data is an object whose provider is strictly 'api'. It then runs ViewDataSchema.safeParse(data) and raises the issue found at path provider. Three things judged:

  • Exactly the retired spelling, nothing else in the bag. The === 'api' gate means another provider (object, value, schema, an unknown rest), a missing data, a bare-array data, a row-array type carrying the binding (object-kanban), a type with no props row (custom:partner-widget) and the component's own governed dataSource: { provider: 'api', read: { url } } (ElementApiDataSourceSchema, outside properties) are all untouched; each is a pinned control in page-component-view-data.test.ts and the parity fixtures. The view's union error map (view.zod.ts:277-285) returns the prescription only when input.provider === 'api', so an uppercase or other misspelling meets zod's default report in both places, consistently.
  • Read, not copied. VIEW_DATA_API_PROVIDER_RETIRED is a module-private const in view.zod.ts, so page.zod.ts cannot import it; the check raises retirement.message off the view's own issue, and if the view ever re-admits the arm (verdict.success) the page check falls silent with it. The PRESCRIPTION in the pins is likewise read off ViewDataSchema with an anti-vacuity assertion.
  • Path. [...path, 'properties', 'data', 'provider'], pinned at a region component, a page:tabs item child, a container grandchild, slots.header.0 and slots.details; the save door reports the same string path (regions.0.components.0.properties.data.provider).
  • Issue code. custom, not the view's invalid_union: the parity harness (runParse) treats any non-custom issue as "fixture not shape-valid" and throws, so custom is the only code an object-level check on PageSchema may raise. Message byte-identical. Right.

(b) The reach — right. definePage is PageSchema.parse (page.zod.ts:1855) and is pinned to throw. defineStack parses through ObjectStackDefinitionSchema.safeParse (stack.zod.ts), whose pages is z.array(PageSchema) (:496) and which ObjectStackSchema aliases by identity (:1888); the pin is on ObjectStackSchema.safeParse({ pages }), which is the same schema object, so defineStack is covered transitively though not called by name in a pin. The page metadata type's schema is PageSchema by identity (metadata-type-schemas.ts:113), which resolveOverlaySchema resolves for the save door (protocol.ts:813-815); protocol.save-union-issues.test.ts pins 422 INVALID_METADATA, nothing persisted, the located custom issue, top-level and page:tabs-nested, with object and value controls that persist one row. The stored-page consequence: loadMetaFromDb is "Diagnose, never drop … STILL registered" with the [metadata_spec_invalid] warning (protocol.ts:28973-28984, :29104); the read path is pinned for a page (_diagnostics.valid false, prescription at the path). The register-anyway rule is pinned on an object row (protocol.stored-conversions.test.ts:286-293, loaded 1 / invalid 1 / registered); the page-specific boot count loaded 2 / invalid 1 was measured with a deleted probe only. The fate text is right on the protocol's one type-agnostic rule; a page row in that boot pin would close the last gap (follow-up, not a blocker).

(c) The hand-declared set — holds over the map's domain; one direction has a blind spot. VIEW_DATA_SOURCE_COMPONENT_TYPES is a module-private set of the four; the import-cycle reason is measured (component.zod.ts:89 imports ElementDataSourceSchema and RETIRED_PAGE_COMPONENT_TYPES from page.zod.ts). The derivation pin compares _zod.def identity of each row's unwrapped data member to ViewDataSchema's (the lazySchema proxy inherits the real def, so identity is sound) and asserts exactly the four with an anti-vacuity floor of 40 rows; the behavioural pin asserts, for every ComponentPropsMap key, refused-at-position if and only if the row takes ViewDataSchema. So set ∩ map-keys equals the derivation in both directions. What neither pin can see: a name added to the hand set that is not a ComponentPropsMap key at all (a custom or registered block). The set is private, so no pin enumerates it; the guard is review of page.zod.ts. At this head the set is the four, so the contract is right. Precision note on the "both directions" claim, not a defect.

(d) The generic walk — it can refuse one contrived non-component shape. The walk descends every object and array under regions and slots, including the whole of a component's open properties: data.items (the value arm's z.array(z.unknown())), staticData, read.headers. A static row or any open-record value that itself spells type in the four and properties.data.provider: 'api' is refused at its own path, though it is data, not a component. The listing (mapPageComponents, walk.ts:304-330) descends only pageComponentSlotPositions() keys, and the props row's items is z.unknown(), so neither would refuse that site: in that corner the page parse is strictly narrower than both. Reachable only by authoring a row that is itself a retired component spelling; the refusal when it fires is the correct prescription at a located path, never a silent change; and the refused-shapes.test.ts "exactly the listed positions" pin bounds the walk only for its fixture. Superset claim confirmed: every slot position (children, items[].children, the retired container spellings) is a plain descent, so nothing the listing lists is missed. The seen identity set ends a self-referencing hand-built stack (pinned). No PageComponentSchema alias exists for properties, so an unparsed nested child cannot hide behind one. Residual recorded; not a FAIL.

(e) The new published export — right. export function checkPageComponentViewData in page.zod.ts, attached once by identifier after checkPageSlotPair; the ui barrel re-exports page.zod (index.ts:53); api-surface/ui.json and export-origins/ui.json each gain exactly the one alphabetically placed line; object-refinement-check-exports.test.ts pins declaration count 1, attachment count 1, the barrel's reference identity, and the (value, ctx) arity. check:api-surface, check:export-origins, check:generated (14 artifacts) exit 0 in the report; the Lint jobs that host them are green on both heads.

② Semver level

  • Changeset 23357-page-component-view-data-api-refused.md: @objectstack/spec: minor, **BREAKING**, FROM → TO table, the one-line fix, the door list (definePage, defineStack({ pages }), os validate, PUT /api/v1/meta/page/:name 422), the stored-page sentence, exactly one adr-0087 marker. AGENTS.md: yes takes at least minor, (narrowing) is BREAKING, and check-changeset-no-major admits major only for a PROTOCOL_VERSION move, so minor is the admissible level and matches what the diff publishes (one new export beside a narrowed accept set). Sibling [Decision] Does a view's api data source adopt the page-element rule — a same-origin url and no headers written in metadata? #23082's changeset is minor with the same shape. Right.
  • ADR-0087 disposition not-required (already-registered view-data-api-provider-retired): the step-18 entry's surface already names "the data prop of each page component that takes a view data source (object-grid, object-map, object-gantt, object-tree)" and its reason says such a component has no mechanical move. The scope was registered at [Decision] Does a view's api data source adopt the page-element rule — a same-origin url and no headers written in metadata? #23082; this diff moves enforcement onto the page parse and updates acceptanceCriteria to name every door that parses a page, the save door's 422 included. No new entry owed. The gate runs in Check Changeset ("Require an ADR-0087 disposition on a declared-breaking changeset", pr-automation.yml), success twice on dce543307; exit 0 locally per the report. Right.
  • Clause-②: yes (narrowing) reads identically in the claim (6160762995, amended in place 08:48Z), the PR body's line 3, and the changeset at dce543307 (the one-line delta from 63e1e4800). One arm, as the rule requires: yes for the export, (narrowing) for the accept set. Right.

③ Boundary flags

Dev report 6164488810: open_questions: [], out_of_scope_findings: []. Its seven deviations, each against the ACCEPT:

  1. Hand-declared set — accepted; the cycle reason is measured and the precedent (PRINT_REFUSED_PAGE_COMPONENT_TYPES) is real. Judged in ①(c) with the out-of-map residual. Acceptance right.
  2. Clause-② amended to yes — accepted and carried through all three carriers. Right.
  3. custom vs invalid_union — accepted; the harness's own rule. Right.
  4. PR body written while runs were in flight — the body now states final verdicts at 63e1e4800 and names dce543307 as the one-line delta: restated. Right.
  5. verify-lock timeouts — process only; no contract effect.
  6. H4 boot measured with a deleted probe — accepted; the read path is pinned and the protocol's register-anyway rule is pinned on an object row. Escalated as a follow-up: add a page row to the boot pin so the fate text's [metadata_spec_invalid] sentence rests on a committed test for this type.
  7. Commit trailers model-free — AGENTS.md's pair (Claude-Session + Co-authored-by: Claude); not a contract matter.

Gates: check:dual-build-cjs-loads exit 3 is PREREQUISITE NOT MET by the script's own contract (no dist/; scripts/check-dual-build-cjs-loads.mjs:203, :1116). It is a Build Core step ("Every published require entry point actually loads", ci.yml:2642-2643); Build Core is success on 63e1e4800 and in progress on dce543307, whose delta is changeset text. check:type-check-debt NOT-MEASURED: Type Check · debt ledger success on 63e1e4800, in progress on the head. Both acceptances right.

Seat-3 pointer 6163363165 (not in the dev's deviations, not in the ACCEPT): PR #23418 (ruling B, moves validateComponentProps onto the runtime door) is open, draft and unmerged at this read (head ba20e780e), so nothing from ruling item 6 is due yet, and the dev followed the order rule (merged origin/main c857a93ee). Carried forward for the seat: the day #23418 lands, (i) this judge overlaps the general rule and is deleted per item 6, in a follow-up since this PR will have landed; (ii) the sentence "the component-props gate runs at the CLI doors only", now written in page.zod.ts's new docblock, refused-shapes.ts's docblock, the changeset body and the step-18 acceptanceCriteria beside lint:111-116, becomes false and is rewritten in the same act. True at this head; packages/lint is untouched here.

Renderer half objectstack-ai/objectui#12325: open (pm:dispatched, domain:ui). The PR body's only closing keyword is Fixes #23357 (line 1); objectui#12325 is named as "which remains open" with no keyword; "Part-of PR must not also close its card" and "The card this PR closes must claim this branch" are success on both heads; check-closing-keyword-parity exit 0. Correctly left out and not closed.

Check-runs as found. dce543307 (46): success — Auto Label, Check Changeset ×2, Check Documentation Links, Check PR Size, Dogfood Regression Gate, Flag docs affected, Governed Surface Queue Guard, Lint · CI/release/engine, Lint · ESLint, Lint · PM dispatch-gates, Lint · docs and code guards, Lint · repo and tooling, Lint · scoped ×3, No other open PR may claim the same issue ×2, same single-writer path ×2, Part-of ×2, Spec property liveness, The card this PR closes ×2, Type Check · source gates, filter; skipped — Auto Label, Build Docs, Check PR Size, Console Pin Gate, Dogfood matrix, Dogfood Verify CLI, Packed-tarball smoke, Temporal Conformance; in progress — Build Core, Test Core 1/6 to 6/6, Type Check · consumer gates, · debt ledger, · workspace; queued — Lint and Repo Gates; failures 0. 63e1e4800 (41): all completed, 35 success (Build Core, Test Core ×6 plus aggregate, Type Check ×4 plus aggregate, Lint and Repo Gates included), 6 skipped, 0 failures. The queue waits for the head's green on its own; the verdict below is on the contract.

Implemented-by: claude/issue-23357-page-component-api-data
Reviewed-by: session_01YRp5z4kK6vgYkrdH97ztsy

VERDICT: PASS


Generated by Claude Code

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review October 14, 2026 09:21
@objectstack-fleet
objectstack-fleet Bot enabled auto-merge October 14, 2026 09:21
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Oct 14, 2026
Merged via the queue into main with commit 05ab9ef Oct 14, 2026
49 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/issue-23357-page-component-api-data branch October 14, 2026 09:52
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