Skip to content

docs: cite landing commits where pending changesets and source comments name 41 objectui issues that answer 404 (objectui#10803, batch 5) - #10892

Merged
objectstack-fleet[bot] merged 3 commits into
mainfrom
claude/issue-10803-dead-citations-fifth-batch
Sep 28, 2026
Merged

objectstack-fleet[bot] merged 3 commits into
mainfrom
claude/issue-10803-dead-citations-fifth-batch

Conversation

@objectstack-fleet

@objectstack-fleet objectstack-fleet Bot commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor

Part of #10803
Clause-②: no

Dispatched implementation of the domain:ui seat 2 claim (comment 5862515185) on objectui#10803, batch 5, session https://claude.ai/code/session_014mXUNuFomfj24w7s1pZzhN. Citations only: no sentence's claim moves, and every edited pending changeset's frontmatter is byte-identical. The runtime text that moves loses its dead pointer and nothing else, all in @object-ui/types: the six ChatbotSchema tombstone guidance strings open RETIRED (ADR-0049) — (rulings 5861129870 and 5861311219), the page node's actions refusal, an ADR-0049 tombstone too, cites (ADR-0049) in place of its dead card (ruling 5861129870, as measured in patch round 1), and the ChartDataSeriesSchema.variant description drops its pointer (amendment 5860244997, Q1 = A). Two tests that pin changed text follow it, anchor only (ruling 5861900779, route a).

Patch round 1 answers the contract review's one FAIL item on afed8aa6b: Special cases 7 had read the actions refusal as not ADR-0049 from a proxy (the breadcrumbs changeset, which only says the 2026-09-09 RULING is not borrowed). Measured from the retirement itself, it is an ADR-0049 tombstone, so under the seat's option (a) its string now reads "never was (ADR-0049): no renderer reads it". The runtime-strings changeset follows, and the sweep changeset notes that @object-ui/types' runtime text is declared separately. One text-only commit, 8255f14f4; no merge, no force-push.

Why Part of, not a closing line

The card stays open for the other 23 numbers of the family remainder (seat amendment 5860244997, Q2 = A), listed in Acceptance notes 1, and for the bare sister-repo numbers the C0 census below lists.

Premise, re-measured

  • REST GET /repos/objectstack-ai/objectui/issues/N for each of the 41: all 41 answer 404, and a second read of each answers 404 again (41 of 41). GET .../pulls/N answers 404 for all 41 too. Lit controls: objectui#10533 and objectui#7714 answer 200. No number was dropped from the batch.
  • The same 41 in objectstack all answer 200. Three of them are the sites' real subject, read not guessed, and are re-qualified (Zone 1 item 5):
    • objectstack#3720 "列表行级 edit/delete 与批量删除未接入服务端 effective 操作集": the five [#3720] sites in ObjectGrid.tsx, rowCrudAffordances.ts and ListView.tsx describe that gate, and their landing ba4514511 is titled "gate list row Edit/Delete and bulk delete on the effective operation set (objectstack#3720)".
    • objectstack#5506, the "five more hardcoded English chrome strings" card: useDetailTranslation.ts wrote "the SAME key Studio metadata forms: no errors before input, translated help text, and a publish button clear of the toast #5506 gave NavigationOverlay's identical handle", and nine sibling in-scope lines already cite objectstack#5506 for those strings.
    • objectstack#6936, the metadata-admin predicate fail-CLOSED card: predicate.ts wrote "fix(types): one authority for ActionSchema and the Breadcrumb pair #6936's true verdict" one line below "objectstack#6936's unresolved-path ruling".
    • Every other site names an objectui card or pull request, confirmed by its landing commit below (for example objectstack#7853 is a driver-memory finding, while objectui#7853 is the cite-by-content ruling AGENTS.md [WIP] Update documentation for project #11 names).
  • Every edited changeset is pending: it is present in .changeset/ on main.
  • Branch point: b2683a2c0. main is now 4f8b7f86a; its census still reads 215, and the merge of this head with it reads 0. Not a shallow checkout.

C0: the bare-number remainder (measurement only)

The instrument of PR objectui#10875, at the branch point:

git grep -hoP '(?:^|(?<=[^\w#&/.\-]))#\d+(?![0-9A-Za-z_])' b2683a2c0 -- '.changeset/*.md' 'packages/*/src/**' ':!**/__tests__/**' ':!**/*.test.*' ':!**/*.spec.*' ':!**/test/**' ':!**/tests/**' | sort -u | wc -l

Census (the enumeration pin for this batch)

The instrument PR objectui#10854 printed and PRs objectui#10869 / #10875 reused, with this batch's 41 numbers substituted (REF = a commit or tree):

git grep -nE '(objectui#|#|issues/)(7091|7097|7108|7177|7612|7620|7623|7658|7666|7667|7669|7678|7681|7682|7703|7704|7708|7804|7844|7853|7869|7874|7877|7926|7959|7967|7979|7980|8058|8060|3720|5420|5503|5506|5737|6467|6936|6945|7622|7662|7684)([^0-9]|$)' REF -- '.changeset/*.md' 'packages/*/src/**' ':!**/__tests__/**' ':!**/*.test.*' ':!**/*.spec.*' ':!**/test/**' ':!**/tests/**' | grep -v 'objectstack#' | wc -l
  • REF = b2683a2c0 (branch point, and main now): 215 lines, 74 changeset lines in 55 files and 141 src lines in 47 files.
  • REF = 8255f14f4 (this head): 0. Round 0's head afed8aa6b also read 0.
  • This head merged with a fresh main (4f8b7f86a, git merge-tree --write-tree, clean, tree 08f80168a): 0. REF = 4f8b7f86a alone: 215.
  • The filter hid nothing this time. The 18 branch-point lines the grep -v 'objectstack#' drops name only objectstack#6936 or objectstack#5506; with those tokens deleted, none of them matches the instrument (0). Unfiltered, this head reads 26, all live objectstack# lines: the 18, the seven re-qualified here, and the same spelling in the new sweep changeset.
  • Lit control, the same printed instrument over live objectui#7714 at this head: 17 lines. Hex-colour false positives (a number followed by a hex letter) at the branch point: 0.
  • Out of scope, as it stands (the instrument with the 41 numbers, unfiltered, whole tree at this head): 367 test lines in 98 files, 23 scripts lines in 5 files, 0 .github, 5 governed lines in 4 files (AGENTS.md and three skills/objectui files), and 51 other lines in 18 files: published CHANGELOG.md history (21 lines in 8 files), content/docs (11 in 4), apps/console (7 in 3), eslint-rules (8 in 2) and eslint.config.js (4). See Acceptance notes 4.

Citation form

Mapping (number to resolution)

Lines / files are the branch-point census for that number. "Method" is how the landing was found. The last column is why that commit carries what the sentence cites it for.

dead number resolution method lines / files why the commit carries it
#7091 (a pull request) 969ba84f4 git log --grep: its squash subject ends "(#7091)" 1 / 1 it registers the console app:launcher renderer, which is what made the "not a page" clause false
#7097 3cab5703b; own-card pointer dropped changeset's adding commit 3 / 3 it adds the 2xl read arm and the literal GRID_COLS_2XL class map, the value-level fix both sentences name
#7108 1267508ea; own-card pointer dropped changeset's adding commit 3 / 2 it tombstones a deleted record reference in the approvals inbox, the platform-flagged class the sentences name
#7177 own-card pointer dropped (landing ebc05b4d6) changeset's adding commit 1 / 1 the only site is its own changeset's pointer
#7612 "the 2026-09-20 ruling"; the card by role git log --grep finds only 2ca238075, the objectui#10150 record of the ruling; the switch, PR objectui#10054, closed unmerged 3 / 2 nothing landed: the ruling was "no". See Special cases 3 and 4
#7620 c15d7eca6; "ruling A behind c15d7eca6" where the sentence cites the ruling; own-card pointer dropped changeset's adding commit, git log -S 13 / 10 it moves data-table's date-only fallback onto formatDate's default face, and its message records the two-faces fact pattern the sentences cite
#7623 5d0876c5c; own-card pointer dropped changeset's adding commit 3 / 3 it retires the inert dashboard-root title declaration
#7658 90c6d090d; own-card pointer dropped changeset's adding commit 2 / 2 it keeps code-span content out of extractToc's HTML strip
#7666 nothing answers: the card by role ("already-filed defect") git log -S finds only a472b0716, which records it as an already-filed defect 1 / 1 see Special cases 3
#7667 a472b0716; own-card pointer dropped changeset's adding commit 2 / 2 it gives extractToc's emphasis rules the flanking rule that keeps SCREAMING_SNAKE underscores
#7669 (a pull request) a3eb5d07a git log --grep: its squash subject ends "(#7669)" 2 / 2 it retires FloatingChatbotConfig.triggerIcon as the tombstone both sentences name
#7678 5f8190c8c ("in its amended form"); own-card pointers dropped changeset's adding commit; its body opens "Part of #7678" 21 / 14 it brings every statement of the retire-vs-remove discriminator to the amended form, the surviving-carrier precondition included. See Special cases 6
#7681 01c27c431; own-card pointer dropped changeset's adding commit 6 / 4 it routes a dataKey-shaped series through normalizeSeries, removing the fast path, so its type override is honoured
#7682 nothing answers: "a separate card"; runtime pointer dropped git log -S finds only 8fe8e5c16, which defers that decision to it 3 / 3 see Special cases 3
#7703 a4611b3e2; runtime text RETIRED (ADR-0049) —; own-card pointer dropped changeset's adding commit 15 / 3 it retires the six dark ChatbotSchema keys as ADR-0049 tombstones
#7704 20316bac3; "the card behind 20316bac3" for the scope note; own-card pointer dropped changeset's adding commit 3 / 2 it adds chatbot-enhanced and chatbot-floating to SchemaRegistry
#7708 d3499b315; PR #8077 kept where it stands beside the dead card; "the card behind d3499b315" for the ruling; own-card and runtime pointers dropped changeset's adding commit, git log --grep 13 / 6 it fences chatbot-floating's raw props spread through toDomProps at the head of the element
#7804 (the handler-key parent) per slice, by git blame: 75fca9669 (data-table), 7ca6ddd4b (detail), f1cd29032 (list-view), 5a41ce733 (object-kanban), 8d50bc2bf (objectql.ts), 604476d97 (tree-view); own-card pointers dropped; "the handler-key parent card" where the sentence means the open parent each slice changeset's adding commit, and git blame per line 49 / 17 each commit declares exactly the handler keys the site's arm or face names
#7844 nothing answers: "their own card" git log -S finds only c4a1d39fe, which leaves both sub-shapes dark 1 / 1 see Special cases 3
#7853 "the card behind fa7d66c45" AGENTS.md #11 names fa7d66c45 as its landing 3 / 3 the ruling lived on the card; fa7d66c45 is its one-site landing
#7869 "the finding objectui#8344 discharged" / "the finding this card discharges" (landing 841dd2b7e) 841dd2b7e's message; the live objectui#8344's body, "Discharges the finding #7869" 2 / 2 the measurement lived on the dead finding, and the live card that discharged it restates it
#7874 d9580f464; PR #7887 kept beside the dead card; own-card pointer dropped changeset's adding commit 3 / 3 it retires the five dead timeline.relative.* rows
#7877 7dcda9cd4 git log -S on the heading 1 / 1 it moves the hand-rolled-table data into hand-rolled-tables.json, the heading's subject
#7926 12b599219; "the 2026-09-09 ruling"; "the actions refusal" by role beside PR #8870; runtime text (ADR-0049); own-card pointer dropped changeset's adding commit 15 / 6 it refuses actions by name on the page node, measures breadcrumbs at 1 site and leaves it parsing, and pins that
#7959 36fc74629; "the card behind 36fc74629" for its scope restraint the tests it added are headed "objectui#7959" 8 / 6 it adds readEnvelopeFailureText, the userMessage-first rule on PackagesPage, and the load-failure testid
#7967 own-card pointer dropped (landing 0544ae958) changeset's adding commit 1 / 1 the only site is its own changeset's pointer
#7979 own-card pointer dropped (landing bfa4fe728) changeset's adding commit 1 / 1 the only site is its own changeset's pointer
#7980 a810bb2ae; "the card behind a810bb2ae" for its surface and its comment; own-card pointer dropped changeset's adding commit 4 / 3 it publishes readEnvelopeFailureText from the package entry
#8058 3f4b45886 git log -S storedRelationshipTarget 5 / 2 it adds storedRelationshipTarget, the read door under both spellings, and rewrites the "costs nothing" claim
#8060 7dc31bb8d; "step 1 of the card behind 7dc31bb8d" git log --grep: its subject names "(#8060)" 8 / 3 it carries a stored type the designer cannot author through verbatim (partitionStoredFields) instead of flattening it to text
#3720 (C0) re-qualified objectstack#3720 ba4514511's subject; objectstack#3720's subject 5 / 3 see Premise
#5420 (C0) own-card pointer dropped (landing b470e9150) the adding commit's subject names "(#5420)" 1 / 1 the only site is its own changeset's heading
#5503 (C0, a pull request) 6f017e99c its squash subject ends "(#5503)" 1 / 1 it puts the chart min-height floor on the element Recharts measures
#5506 (C0) re-qualified objectstack#5506 nine sibling in-scope lines already cite it for the same strings 1 / 1 see Premise
#5737 (C0, "PR #5737") d1ab06f0f its squash subject ends "(#5737)" 4 / 4 it declares record.* the row-predicate canon and warns on the two deprecated spellings, which is Phase 1
#6467 (C0) own-card pointer dropped (landing 5ad0641e0) its subject names "(#6467)" before its own "(#7332)" 1 / 1 the only site is its own changeset's pointer
#6936 (C0) re-qualified objectstack#6936 the line above already cites it 1 / 1 see Premise
#6945 (C0, "PR #6945") 2c45966ff its squash subject ends "(#6945)" 1 / 1 it declares the 13 renderer-read keys the sentence says objectui#6150 declared first
#7622 (C0, "PR #7622") 1cca678ba its squash subject ends "(#7622)" 1 / 1 it retires the dashboard-root title read on all five surfaces
#7662 (C0, "PR #7662") bc640ec56 its squash subject ends "(#7662)" 1 / 1 it is the change to SchemaRegistry's kanban entry the sentence ascribes to objectui#7645
#7684 (C0, "PR #7684") "the contract review of 8fe8e5c16's pull request" its squash subject ends "(#7684)" 2 / 2 the review lived on the dead pull request; the sha only locates it

Special cases (the judgement calls)

  1. A dead card beside its own live landing.
  2. The sister-repo numbers. [#3720] becomes [objectstack#3720] at five sites; "Studio metadata forms: no errors before input, translated help text, and a publish button clear of the toast #5506" and "fix(types): one authority for ActionSchema and the Breadcrumb pair #6936's" become objectstack#5506 and objectstack#6936's. See Premise.
  3. The card named by role.
  4. Rulings by date.
  5. Own-card pointers that needed a word.
    • 7097-grid-2xl-breakpoint.md: the pointer sat on its own line, so the period moved up with it.
    • 7678-tombstone-discriminator-agreement.md: "the site objectui#7678 was filed about" becomes "the site this card was filed about", the file's own wording two lines earlier.
    • 7804-object-kanban-handler-keys-judged.md: "its KNOWN_UNDECLARED_READS row naming objectui#7804, which stays open and stays the parent" becomes "its KNOWN_UNDECLARED_READS row, which names the parent card".
    • The six 7804-* slice changesets keep "(the … slice)" once the pointer goes, as batch 4 kept "(slice 2)".
  6. The discriminator form (types: the triggerIcon tombstone's rationale contradicts mobile.ts's own retire-vs-remove discriminator, and its tripwire comment overclaims #7678). "in the form objectui#7678 amended it to" becomes "in its amended form (5f8190c8c)" at every site; "as amended by objectui#7678" and "amended by objectui#7678" take the same wording; a bare "types: the triggerIcon tombstone's rationale contradicts mobile.ts's own retire-vs-remove discriminator, and its tripwire comment overclaims #7678" in a precedent list becomes 5f8190c8c. mobile.ts's "without the precondition objectui#7678 added" becomes "without the precondition the amendment added", whose antecedent is the preamble's "amended form" two sentences up. 9684-discriminator-cited-once.md: "objectui#7678's amendment had to be applied by hand" becomes "the amendment (5f8190c8c) had to be applied by hand", which is what that commit did.
  7. The runtime strings. Only the listed text moves in each.
file member before after
types/src/zod/complex.zod.ts ChatbotSchema.loading, .showAvatars, .userAvatar, .assistantAvatar, .markdown, .height (tombstones) "RETIRED (objectui#7703, ADR-0049) — …" "RETIRED (ADR-0049) — …"
types/src/zod/complex.zod.ts ChatbotSchema.showAvatars (tombstone) "… unfiltered props spread — was fenced by objectui#7708. Delete the key: …" "… unfiltered props spread — was fenced. Delete the key: …"
types/src/zod/layout.zod.ts PageNodeSchema.actions refusal "actions is not a key of the page node and never was (objectui#7926): no renderer reads it, …" "actions is not a key of the page node and never was (ADR-0049): no renderer reads it, …"
types/src/zod/data-display.zod.ts ChartDataSeriesSchema.variant .describe() "… the renderer-internal current spelling is not a member (objectui#7682)" "… the renderer-internal current spelling is not a member"

The ADR-0049 condition, measured from the retirement itself (Zone 1 item 4): the six tombstones already cited ADR-0049 beside the dead card; the zod comment above them opens "ADR-0049 retirement tombstones"; their landing a4611b3e2 is titled "retire six dark ChatbotSchema keys as ADR-0049 tombstones"; and the pending 7703-chatbot-dark-keys-retired.md says "ADR-0049 retirement tombstones". The actions refusal is an ADR-0049 tombstone too, measured the same way: its arm is retirementTombstone(PAGE_ACTIONS_REFUSAL), its landing 12b599219 calls it "an ADR-0049 retirementTombstone arm", and 7926-page-node-refuses-actions.md calls it "an ADR-0049 refusal arm". Its string has no RETIRED opener, so its own parenthetical becomes (ADR-0049), the spelling its breadcrumbs sibling already uses. The TypeScript twins in complex.ts read "ADR-0049 RETIREMENT TOMBSTONE — loading (a4611b3e2)", the comment form.
8. What follows the text, and nothing else in it (ruling 5861900779, route a; ruling 5861129870).

  • chatbot-dark-keys-retired-7703.test.ts pins the six guidance strings as full literals. Their openings follow to RETIRED (ADR-0049) — , the showAvatars literal follows "was fenced.", its prescriptive anchor 'was fenced by objectui#7708' becomes 'was fenced.', and toContain('RETIRED (objectui#7703') becomes toContain('RETIRED (ADR-0049) —'). Its test names and @ts-expect-error comments still read "RETIRED (objectui#7703)"; they describe the ?: never TypeScript face and are out of class (Acceptance notes 6).
  • clientValidation.authorShapeRuling-10150.test.ts pins that the AUTHOR_SHAPE_ONLY_TYPES header names the ruling and extractDraftBody. Its subject 'objectui#7612' becomes 'the 2026-09-20 ruling'; its message and title are unchanged.
  • No test, doc or changeset quotes the actions refusal or the variant description verbatim: a whole-tree search for the old strings returns only the source lines.
  1. The anchor sweep (PR objectui#10875 Special cases 10 shape).
    • Instrument: every string, template, numeric and regex literal in all 3822 test and script files under packages/ and scripts/, enumerated with git ls-tree at head and parsed with TypeScript (113091 distinct literals).
    • Test applied to each literal: does its occurrence count DROP between b2683a2c0 and head in any file this PR changes, in raw text or in a comment-flattened form?
    • Run 1, on 8c267051f (the sweep commit, before any test moved): 336 distinct literals drop. Read against the files they sit in, the specific anchors are the two pins in item 8 (the six literals, the prescriptive anchor and the toContain in the first; 'objectui#7612' in the second). Also listed and read: the 'objectui#7804' values of check-handler-key-read-sites's KNOWN_UNDECLARED_READS ledger and its test, which assert over the script's own data and never read a changed file, and tombstone-discriminator-agreement-9684's /RETIRED \(objectui#/, which it applies to mobile.ts alone, untouched here.
    • Everything else is a generic token (whitespace, punctuation, single letters and digits, objectui#, character-class regexes of whole-tree scanners), none an assertion over text this PR changed.
    • Run 2, on round 0's head afed8aa6b: 327 distinct literals; the nine literals the two pins moved are gone from the drop set, nothing new appears, and the only one left naming a batch number is that ledger value.
    • Run 3, patch round 1, over the delta afed8aa6b..8255f14f4: 18 (literal, file) drops, every one a generic token (' is', 'dropped', a /(\w+):/g scanner); no test pins the changed refusal text.

Held

By the serial rule: nothing. Patch round 1 re-read: 8 open besides this PR (objectui#10896, #10891, #10890, #10889, #10888, #10777, #10278 and the release PR #5400; #10886 and #10714 have left the open list). New since round 0, objectui#10896 shares plugin-grid/src/ObjectGrid.tsx and plugin-list/src/ListView.tsx; trial merges of this head with every open head are clean except #10278 (conflicts identical against main alone) and the release PR #5400, which regenerates. The round's one source edit, in layout.zod.ts, is held by no open PR.

Round 0, re-read before its push: 11 open besides this PR. They are objectui#10890, #10889, #10888, #10886, #10884, #10852, #10780, #10777, #10714, #10278 and the release PR #5400.

Changesets

  • .changeset/10803-dead-citation-sweep-fifth-batch.md, EMPTY frontmatter: the comment-only edits in 15 released packages and the private @object-ui/test-support. No published behaviour changes through them. It marks @object-ui/types as the package "whose runtime text is declared separately below" (patch round 1) and points at the second file for it.
  • .changeset/10803-fifth-batch-runtime-strings.md, '@object-ui/types': patch: the six tombstones open RETIRED (ADR-0049) — with everything after the dash unchanged except the showAvatars pointer; the actions tombstone cites ADR-0049 in place of its dead card; and the variant description loses its pointer. No key, path, issue code, accept set, refusal or severity moves.

Proof of prose-only (C4), against b2683a2c0, on this head 8255f14f4

  • Source. Each of the 49 touched .ts / .tsx files (47 non-test sources and the two pins) was parsed at b2683a2c0 and at this head with TypeScript's createSourceFile and re-printed by createPrinter({ removeComments: true }).
    • 44 of 49 prints are identical.
    • The other 5 are equal once exactly the 19 listed substitutions are applied to the base print, each matched once: complex.zod.ts 7 (six openings and the fence pointer), layout.zod.ts 1 (the pointer becomes (ADR-0049)), data-display.zod.ts 1, chatbot-dark-keys-retired-7703.test.ts 9 (the same seven, the prescriptive anchor and the toContain anchor), clientValidation.authorShapeRuling-10150.test.ts 1.
    • 0 parse diagnostics.
    • Lit controls on the same instrument: dropping "(ADR-0049)" from the loading string moves the print; re-spacing the "ADR-0049 retirement tombstones" comment does not.
  • Changesets. The frontmatter block of every one of the 55 edited changesets is byte-identical at b2683a2c0 and this head (55 of 55, by md5). The overwrite gate below agrees.
  • Scope of the diff: 106 files: 55 edited and 2 new changesets, 47 non-test source files, and 2 tests.

Gates, on this head 8255f14f4

Each line is the gate's own verdict and exit code, captured by redirect-then-$?.

  • node scripts/check-changeset-presence.mjs, exit 0: "48 source file(s) of 15 released package(s) changed, and this change declares 2 changeset(s): .changeset/10803-dead-citation-sweep-fifth-batch.md, .changeset/10803-fifth-batch-runtime-strings.md." (48 = the 46 released sources and the 2 tests under released packages' src/; test-support is under a package changesets ignores.)
  • pnpm changeset:check, exit 0: "All workspace packages are in the changeset fixed group." / "No changeset declares a major bump."
  • node scripts/check-changeset-overwrite.mjs (report-only), exit 0: "2 changeset(s) added, 55 modified, 0 deleted". declared at base equals declares now for 55 of 55.
  • pnpm check:changeset-claims (report-only), exit 0:
    • born-false: "Every one of those 2 address(es) either names the tree it was read from, or points at a line this change does not move";
    • self-contradiction: "Every package declared across those 45 body(ies) is either not negated in its own prose, or negated only in an ASPECT of it that may legitimately hold still";
    • the standing notice "103 pending changeset(s) describe a file this change touches".
    • Read against the diff: a pending changeset quoting a replaced pointer would itself carry the dead number and so sit in the census, which reads 0. No pending changeset quotes a changed runtime string.
  • pnpm check:control-bytes, exit 0: "check-control-bytes: OK (scanned 9145 tracked text file(s); skipped 85 binary)."
  • pnpm check:new-line-citations, exit 0: "VERDICT new-cross-file-line-citations: 0 new citation(s), enforcement report-only -> exit 0".
  • Also run: pnpm check:pending-changeset-literals, exit 0: "No test source names a pending changeset."; the governed-surface predicate over the 106 paths, exit 0: "NOT GOVERNED — 106 path(s) checked against 5 governed surface(s); none matched." (lit control AGENTS.md: exit 3).

Tests, through the shared verify lock.

  • Red, reproduced first. The branch-point copies of the two pins were written over the committed sweep tree and run: Test Files 2 failed (2), Tests 13 failed | 29 passed (42), for example "expected 'RETIRED (ADR-0049) — never read: chat…' to contain 'RETIRED (objectui#7703'". Both files were then restored with git checkout HEAD --, each checked by blob hash against HEAD, and git diff HEAD came back empty.
  • Patch round 1, on this head 8255f14f4: page-actions-refusal-7926 (it pins the message's remedy words actions, children and page:header and that it is not zod's generic text, never the pointer; verified by reading it), page-breadcrumbs-refusal-8871, guide-layout-page-buttons-7926, zod-mirror-parity, chatbot-dark-keys-retired-7703, clientValidation.authorShapeRuling-10150 and tombstone-discriminator-agreement-9684 give Test Files 7 passed (7), Tests 134 passed (134), under VERDICT command-exit 0. A whole-tree search for "never was: no renderer" finds no test or doc quoting it (only the source line and the runtime-strings changeset, both updated); an anchor sweep over the round's delta finds only generic tokens.
  • Green, round 0, on afed8aa6b: chatbot-dark-keys-retired-7703, clientValidation.authorShapeRuling-10150, tombstone-discriminator-agreement-9684, page-actions-refusal-7926, page-breadcrumbs-refusal-8871, chart-series-keys-7546, zod-mirror-parity, chatbot-display-mode-retired and schema-registry-chatbot-keys-7704 give Test Files 9 passed (9), Tests 173 passed (173), under VERDICT command-exit 0.

Declared narrowing (per the dispatch: the named checks, not wider sweeps). NOT MEASURED locally: the full suites and type-check of the 15 touched packages, and eslint. Reason: the comment-stripped syntax tree of 44 of the 49 touched files is identical to main, and the other 5 differ only by the listed literal edits. Every test that anchors on a changed string or comment was found by the anchor sweep (Special cases 9) and run above. CI runs the full farm.

Acceptance notes

  1. The remainder rides this card, unchanged (seat amendment 5860244997, Q2 = A). Of the 53 numbers PR objectui#10875's Acceptance notes 1 lists, this PR carries the first 30 in ascending order, plus the 11 C0 404s of its Acceptance notes 2. The other 23 are: finding(types): InputSchema.wrapperClass is declared on the TS face and absent from its zod mirror — the one schema.wrapperClass reader still ledgered in UnmirroredDeclared #8072 A spec-valid type: 'page' view silently renders as a grid — ViewType in packages/types/src/views.ts never gained page, so six total maps over it compile green while being incomplete #8127 Decision: registry-inputs-spec-parity fails on the 17.3.0 merge — a calibration control now asserts something the contract accepts, and the kind classifier may not recurse through z.union #8137 console: registry-inputs-spec-parity's refusesKind reads a union branch's [invalid_type, too_small] pair as a CONTENT refusal, so an array probe the contract refuses enters the accepted-kind set #8204 finding(components): flex.tsx's own registration declares defaultProps.align: 'center' while its renderer falls back to 'start' #8229 finding(types): objectui#8222's exclusion message still calls the seed decomposition a LIVE figure, which objectui#8243 made historical #8248 plugin-kanban: the lane header count is col.cards.length — it counts the fetched window, not the group, so a board over more than limit rows reports plausible-looking wrong totals #8307 [finding] Public form page /f/:slug renders the object API name as its <h1>: the fallback chain reads form.label, a key FormViewSchema rejects, while the config carries title — and description is never rendered #8408 Studio: the "Create app" dialog's confirm control shares an accessible name with the toolbar button that opens it — a mis-click silently leaves the app uncreated #9231 ci.yml's type-check and e2e decide steps have no markdown stage, and the only thing holding that up is an ASSERTED claim — "type-check reads no document, and no e2e spec does" was never traced #9241 pickSpanClass emits a col-span class for ONE breakpoint tier only, so span: 'full' under-spans at every intermediate tier — and the correct per-tier implementation already exists in plugin-detail #9244 finding(types,components): docblocks assert bridgeListView writes these slots in the PRESENT TENSE — the whole spec-bridge was retired by #6366, and one of them is the stated factual basis of ruling #4580 #9365 bug(plugin-list): ListView's record-detail overlay heading renders [object Object] Detail for an inline-locale-map label — the t() options sink no compiler can name #9373 finding(types): base.ts's vocabulary docblock says the two i18n label shapes "each accept the other's shape vacuously" — an instrument now in the tree refutes it, on the reference face #9375 finding(core/app-shell): ResultDialogSpec hand-copies the contract's resultDialog block and has drifted — title / description / acknowledge are string here and I18nLabel in the contract #9542 finding(docs): AGENTS.md documents a BaseSchema.events key that no schema declares and no renderer reads — BaseSchemaCore is passthrough, so a node authored from the instruction file is silently discarded #9553 measurement only: does the zod refusal gate the collapsible RENDER path, or only validate? — the binary precondition every route on objectui#8236 depends on #9585 [repo:objectui] page:header crashes with React #31 when the record's name field is empty — the title fallback picks a lookup field and renders its expanded record object as a JSX child #10117 App nav item visible (CEL) is served to the client but never evaluated — a silently inert gate (17.2.0) #10119 [repo:objectui] Record edit form posts every displayed field, so a user with field-level editable:false on any form field gets 403 「您没有权限保存这条记录」 even when editing only an allowed field — inline grid sends the dirty cell and succeeds #10120 An action's params dialog renders a field-backed lookup as a bare text input — 0 options, no request on the wire, so the action cannot be launched from the UI at all #10129 console: #7804's GlobalFilterSchema.object is never read, and ChartAxisSchema.title bypasses a locale resolver in its own bundle — two dashboard i18n surfaces declared translatable and not resolved #10132 #14026. None of them occurs in any hunk of this diff.
  2. The C0 bare numbers above 10900, for later batches (sites at b2683a2c0, lines / files). Each answers 404 as an objectui issue, and none is an objectui citation, so the fix is a re-qualification to objectstack, not a landing sha:
  3. A live-but-wrong bare number beside a re-qualified one. rowCrudAffordances.ts cites "(/me/permissions apiOperations, [console] 记录详情页头的 api 动作:target URL 的 {field} 占位符从不插值——record_header 执行器不提供 params._rowRecord,literal {id} 被原样发出 #3391)" at the two sites that now read [objectstack#3720]. objectui#3391 answers 200 with an unrelated subject (a record-header api action placeholder), while objectstack#3391 is the apiMethods whitelist contract card that objectstack#3720's own title names. It is not a 404, so it is outside the family pin and was not touched. Carrier: none.
  4. Published or shipped text outside the two in-scope classes still names some of these numbers (counts in Census). It is untouched by scope, as another class the triage split did not scope here: published CHANGELOG.md history (never re-addressed), content/docs (for example the chatbot and layout guides), apps/console (the approvals inbox and the agent-connect section), eslint-rules and eslint.config.js, three skills/objectui files and AGENTS.md (governed). Carrier: none.
  5. Filenames are not citations. Pending changeset and test FILENAMES carry several of these numbers. They stay, as in PRs objectui#10707, docs: cite landing commits where pending changesets and source docblocks name ten objectui issues that answer 404 (objectui#10771) #10797, docs: cite landing commits where pending changesets and source comments name fourteen objectui issues that answer 404 (objectui#10803) #10854, docs: cite landing commits where pending changesets and source comments name 32 objectui issues that answer 404 (objectui#10803, batch 3) #10869 and docs: cite landing commits where pending changesets and source comments name 30 objectui issues that answer 404 (objectui#10803, batch 4) #10875.
  6. Test comments left as they are. chatbot-dark-keys-retired-7703.test.ts's test names and @ts-expect-error comments still read "RETIRED (objectui#7703)", and clientValidation.authorShapeRuling-10150.test.ts's header, title and message still name objectui#7612. Only anchors moved (ruling 5861900779).

Generated by Claude Code

…ts name 41 objectui issues that answer 404 (objectui#10803, batch 5)

Re-points every in-scope citation of the batch's 30 family numbers and the
11 bare-number 404s the batch 4 census found: pending `.changeset/*.md`
prose and non-test `packages/*/src` comments cite the 9-character sha that
landed what the sentence rests on, a ruling by its date, a live pointer the
sentence already named, or the card by role. A changeset's pointer to its
own card is dropped. Three bare numbers that were sister-repo cards are
re-qualified to objectstack.

Runtime text drops its dead pointer and nothing else: six ChatbotSchema
tombstones open `RETIRED (ADR-0049) —`, the page `actions` refusal and the
ChartDataSeriesSchema.variant description lose theirs
(`@object-ui/types: patch`). Every edited changeset's frontmatter is
byte-identical.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014mXUNuFomfj24w7s1pZzhN
`chatbot-dark-keys-retired-7703` pins the six ChatbotSchema tombstone
strings as full literals; their openings follow the runtime strings to
`RETIRED (ADR-0049) —`, and the `showAvatars` prescriptive anchor follows
"was fenced." The `AUTHOR_SHAPE_ONLY_TYPES` header pin in
`clientValidation.authorShapeRuling-10150` now requires the header to name
the 2026-09-20 ruling, the citation that replaced the dead card. Anchors
only: titles, messages and comments in both files are unchanged.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014mXUNuFomfj24w7s1pZzhN
@github-actions

github-actions Bot commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor

changeset-claim-re-read

⚠️ 103 pending changeset(s) describe a file this change touches

Their bodies publish verbatim into the CHANGELOG at the next release, so this is a request to re-read them against your diff — addressed here because you are the one seat that can answer it without re-deriving anything.

⛔ Nothing here blocks, and nothing here is a verdict on your change. This gate exits 0, is not a required context, and judges name resolution, never meaning: it asked whether a pending body names a file you touched. "Is this sentence still true?" is the one question it will not answer, and the one you are being asked to answer.

.changeset/4730-retire-dead-locale-key-batch.md

  • names ObjectGrid.tsx → packages/plugin-grid/src/ObjectGrid.tsx — edited by this change

    • Superseded twin vocabularies. cellRender.* and rowAction.* duplicated a grid.* vocabulary that won. RowActionMenu.tsx is fully i18n-wired and reads grid.openMenu / grid.edit / grid.delete; ObjectGrid.tsx reads grid.empty / grid.yes / grid.no / grid.systemFields. The twins had no reader on either side. - Labels that outlived their control. calendar.agenda labelled a view mode b55a34647 retired from CalendarViewMode (now 'month' | 'week' | 'day'). home.quickActions.createApp*, layout.systemNav.createApp, actionDialog.defaultActionTitle / .ok and grid.bulk.selectPlaceholder sit in namespaces whose consumers are live and wired but demonstrably read other siblings. - Surfaces that left the product. map.* is the strongest form: @object-ui/plugin-map declares no @object-ui/i18n dependency and contains no t() call at all, so it cannot consume a locale string. home.stats.* and recordDetail.viewersTooltip name surfaces nothing renders.

.changeset/4895-retire-block-schema-family.md

  • names packages/types/src/layout.ts → packages/types/src/layout.ts — edited by this change

    ⚠️ Not this family, and not touched. The live slotted record-page vocabulary — PageNodeSchema.kind === 'slotted' with slots?: PageSlotMap (packages/types/src/layout.ts), rendered by usePageAssignment / PageBlockCanvas / PageBlockInspector in @object-ui/app-shell — shares the words "block" and "slot" with the retired family and shares no declaration, type or file with it. Neither is the type: 'component' NAVIGATION item kind ({ type: 'component', componentRef }, NavigationItemSchema in zod/app.zod.ts), a different declaration in a different module.

.changeset/5453-retire-grid-column-wrap-forward.md

  • names data-table.tsx → packages/components/src/renderers/complex/data-table.tsx — edited by this change

    generateColumns() copied a per-column wrap onto every column object handed to data-table, and packages/components' data-table.tsx never read it. Measured on the current ref rather than inherited from the card, with comments stripped so prose mentions cannot be counted as reads: a column-level wrap scores 0, against accessorKey 34, align 5, header 4, className 4, width 8 and fitContent 2 in the same query shape. Those sibling counts are the positive control — the search style does find the keys that are genuinely consumed, so the zero is a measurement and not a mis-aimed grep. The raw string wrap does occur in that file; every occurrence is flex-wrap, whitespace-nowrap, or a variable named wrapper.

.changeset/5632-svg-host-dom-passthrough.md

  • names packages/types/src/layout.ts → packages/types/src/layout.ts — edited by this change

    Both renderers forwarded their whole prop bag to the SVG they render, so every authored SDUI key on the node became an attribute — 14 per target, and icon="check" on all 71 icon nodes in the schema catalog. The two nodes declare different keys, and each renderer consumes its own node's keys by name: IconSchema (packages/types/src/layout.ts) against the pass-through docblock in renderers/basic/icon.tsx, and SpinnerSchema (packages/types/src/feedback.ts) against the one in renderers/feedback/spinner.tsx. icon and color are IconSchema's alone — SpinnerSchema declares neither. Read those two declarations for what they carry; this paragraph deliberately copies no member list. So the SDUI pass-through list withholds nothing they need.

.changeset/5853-tablecolumn-type-canonical-union.md

  • names data-table.tsx → packages/components/src/renderers/complex/data-table.tsx — edited by this change

    @object-ui/types exports TABLE_COLUMN_TYPES (the canonical tuple — the single declaration the zod mirror builds its enum from, so the two cannot drift), the TableColumnType union, and normalizeTableColumnType() for producers. The as any cast in data-table.tsx is deleted and the read is typed, so re-introducing an undeclared spelling is a tsc error rather than a silent widening.

.changeset/5903-objectgantt-declared-keys.md

  • names packages/types/src/objectql.ts → packages/types/src/objectql.ts — edited by this change

    Both halves move together. The TS declaration (packages/types/src/objectql.ts) and its zod mirror (src/zod/objectql.zod.ts) gain the same ten keys at the same requiredness — all optional — and no KnownDrift entry is added. navigation is taken from @objectstack/spec's NavigationConfigSchema by reference rather than restated, matching ObjectGridSchema.navigation.

  • names src/zod/objectql.zod.ts → packages/types/src/zod/objectql.zod.ts — edited by this change

    Both halves move together. The TS declaration (packages/types/src/objectql.ts) and its zod mirror (src/zod/objectql.zod.ts) gain the same ten keys at the same requiredness — all optional — and no KnownDrift entry is added. navigation is taken from @objectstack/spec's NavigationConfigSchema by reference rather than restated, matching ObjectGridSchema.navigation.

.changeset/5905-componentinput-inputtype-tombstone.md

  • names zod/base.zod.ts → packages/types/src/zod/base.zod.ts — edited by this change

    Stale wording corrected in the same pass, because this change falsifies it: base.ts and zod/base.zod.ts both said the fork was "recorded for a ruling; until then this stays a live, writable key", and widget.ts called it "the open fork". All three now record the ruling. A reader who greps the source instead of the card thread was meeting an open fork that no longer existed.

.changeset/5905-componentinput-retire-constraint-keys.md

  • names packages/types/src/zod/base.zod.ts → packages/types/src/zod/base.zod.ts — edited by this change

    The retirement kit: ?: never on the interface (packages/types/src/base.ts), so authoring one is a tsc error at the registration site; retirementTombstone() on the Zod mirror (packages/types/src/zod/base.zod.ts), so an authored value is REFUSED at parse time with code: 'invalid_type', the key named in the issue path, and the migration note as the message. Deleting the members outright was the option NOT taken: ComponentInputSchema is a non-strict z.object, which strips an undeclared key silently — one silent no-op traded for another. Pinned in packages/types/src/__tests__/component-input-retired-constraint-keys.test.ts.

.changeset/5926-empty-action-visible-when.md

  • names data-display.zod.ts → packages/types/src/zod/data-display.zod.ts — edited by this change

    emptyAction was the one authored-node exception in the tree. The empty-state CTA slot resolved the registry directly — ComponentRegistry.get(node.type) — and mounted the result itself, so the node never passed through SchemaRenderer and its visibleWhen was never evaluated. @objectstack/spec accepts the key (SchemaNodeSchema carries visibleWhen, and data-display.zod.ts types emptyAction as a SchemaNode), so an author wrote a gate, the platform took it, and nothing enforced it — declared-not-enforced, the same class c86185eb5 closed for record:alert, one level down.

  • names data-table.tsx → packages/components/src/renderers/complex/data-table.tsx — edited by this change

    The fix is a route, not a new check: no visibleWhen test was added to data-table.tsx. A local check on this slot would have been a fourth evaluator, which is the drift page:tabs' item-level predicate already records on this card. The slot now mounts its authored node exactly the way the empty renderer's action slot always has.

.changeset/5993-button-shared-icon-resolver.md

.changeset/6169-chatbot-authoring-face-type.md

  • names packages/plugin-chatbot/src/renderer.tsx → packages/plugin-chatbot/src/renderer.tsx — edited by this change

    ChatbotSchema (@object-ui/types) now declares ten keys that previously existed ONLY inside an anonymous inline intersection local to packages/plugin-chatbot/src/renderer.tsx's chatbot registration, invisible to anything outside that one file:

.changeset/6175-column-state-persistence.md

  • names data-table.tsx → packages/components/src/renderers/complex/data-table.tsx — edited by this change

    • @object-ui/components — DataTableSchema has declared onColumnResize?: (columnKey, width) => void all along, and data-table.tsx invoked it nowhere: the resize drag updated the table's local columnWidths state and stopped there. It now reports the settled width once, at mouseup. Once, deliberately — the host turns this callback into a write to shared view config, so a per-mousemove callback would be a write storm. - @object-ui/plugin-grid — ObjectGrid emitted onColumnReorder (singular) while the renderer invokes the near-duplicate onColumnsReorder (with the s), a different declared key with a different signature. The producer now emits the spelling the renderer actually invokes, mapping the reported TableColumn[] to the accessorKey order columnState stores.

.changeset/6238-object-payload-enabled.md

  • names packages/app-shell/src/index.ts → packages/app-shell/src/index.ts — edited by this change

    No published type changed. ObjectMetadataPayload is exported from its module but that module is not re-exported by packages/app-shell/src/index.ts, the package's only entry, so the removed enabled?: boolean was never on the published surface and no **/src/index.ts is touched. What consumers can observe is behaviour: MetadataService is reachable through the published useMetadataService() hook, both method signatures are unchanged (PromiseANGLE-BRACKETS(void)), and the HTTP request they issue changes from a PUT with a body to a DELETE.

.changeset/6349-types-internal-name-collisions-batch-1.md

  • names crud.ts → packages/types/src/crud.ts — edited by this change

    ActionSchema — renamed, because the two shapes are unrelated. crud.ts and ui-action.ts both declared it. Measured member-by-member they share 9 keys out of 28 each: crud.ts extends BaseSchema and pins type: 'action' (a UI node — a button in a component tree), ui-action.ts extends nothing and types type as ActionType (a spec-v2 action definition, with name, locations, params, target). Re-pointing either at the other would silently hand a consumer a different type, so this took the rename branch (objectui#5044 is the precedent for choosing the surviving name). ui-action.ts's declaration is now spelled UIActionSchema — the name src/index.ts has always PUBLISHED it under, via export type { ActionSchema as UIActionSchema }, which is now a plain re-export. The package's public surface is unchanged: ActionSchema still means crud.ts's legacy shape and UIActionSchema still means ui-action.ts's, exactly as before. Nothing outside ui-action.ts imported the old spelling — there is no ./ui-action subpath in exports, so the old name was never reachable from outside the package.

  • names data-display.ts → packages/types/src/data-display.ts — edited by this change

    BreadcrumbItem / BreadcrumbSchema — re-pointed, because one copy was stale. Both were declared in data-display.ts and in navigation.ts. The data-display pair was not a second dialect but a strict SUBSET: no key declared differently on either side, and missing BreadcrumbItem.icon / onClick / siblings and BreadcrumbSchema.maxItems. Everything that reads a breadcrumb was already on the navigation declaration — registry.ts maps the 'breadcrumb' component type to it, src/index.ts re-exports it under the bare names, zod/navigation.zod.ts mirrors it (icon, onClick, siblings, maxItems included), the ui:breadcrumb renderer consumes it, and the component's own documentation page documents icon and maxItems. data-display.ts now re-exports the one authority.

.changeset/6373-datatable-emit-boundary.md

  • names data-table.tsx → packages/components/src/renderers/complex/data-table.tsx — edited by this change

    The measured read set of the consumer (data-table.tsx, comments stripped) contains none of the six, so all six retire from the emit rather than being declared — declaring a key nothing reads is the same declared != enforced defect facing the other way. Rendering is unchanged because none of those keys was the live path for its own value: the FieldMeta the cell closure captures is what this widget's type-aware rendering has always read, and it is untouched. Authored spellings still pass through, so a column the author wrote as { format: '$0,0' } keeps its format exactly as before.

.changeset/6424-tablecolumn-declares-headericon.md

  • names data-table.tsx → packages/components/src/renderers/complex/data-table.tsx — edited by this change

    Scope of the enforcement claim, measured: the declaration, the parse road, and the renderer's behaviour now agree; the renderer's internal column reads remain any-mediated (the col: any normalization in data-table.tsx) — a standing instrument gap, not closed here.

.changeset/6519-retired-field-key-strip.md

  • names plugin-designer/src/MetadataFieldsPage.tsx → packages/plugin-designer/src/MetadataFieldsPage.tsx — edited by this change

    Unifying the three retired-key lists on this seam is deliberately not part of this change: it spans plugin-designer/src/MetadataFieldsPage.tsx, which objectui#6489 owns in flight.

.changeset/6559-expression-user-input-contract.md

  • names packages/app-shell/src/index.ts → packages/app-shell/src/index.ts — edited by this change

    WHAT BREAKS, AND FOR WHOM. This tightens a signature published from the package entry (packages/app-shell/src/index.ts), so an external caller that passes an unchecked or under-declared value stops compiling on upgrade. That is accepted (maintainer ruling 2026-08-27, option A): the only calls it refuses are calls that were never conformant with the contract the module already declared. It ships as minor, not major — objectui's major tracks @objectstack's, so its own breaking changes ship as a minor with the break written down (scripts/check-changeset-no-major.mjs). ⛔ Keeping unknown and ⛔ adding a second, wider entry point were both declined.

.changeset/6597-retire-fieldmeta-referenceto.md

  • names plugin-grid/src/ObjectGrid.tsx → packages/plugin-grid/src/ObjectGrid.tsx — edited by this change

    No authoring story survived the search either. ObjectGrid's own relational-meta pass-through (applyRelationalMeta, plugin-grid/src/ObjectGrid.tsx) copies reference_to / reference / display_field / etc. from the SCHEMA field def only, at all three of its call sites — never from an authored column override. No doc, example, or fixture in this repo shows a table column pinning a lookup's target away from what its schema field already says. Under the maintainer's standing startup-stage rule (2026-08-27: deprecated/alias spellings retire immediately, no transition windows), no measured demand selects withdraw.

.changeset/6625-retire-fieldmeta-decimals.md

  • names GridField.tsx → packages/fields/src/widgets/GridField.tsx — edited by this change

    buildFieldMeta computed decimals: overrides.decimals ?? meta?.decimals ?? meta?.scale on every call and the value reached nothing. Re-measured on this branch's base (efdc6c62): zero .decimals member reads across @object-ui/fields, @object-ui/i18n, @object-ui/components, @object-ui/core and plugin-dashboard itself — the only non-comment occurrence was the write being removed here. The positive control in the same query shape fires: .scale member reads hit NumberField.tsx, GridField.tsx and fields/src/index.tsx. So the zero is a finding, not a broken query. The overrides.decimals ?? head of that chain had already lost its only feeder when objectui#6425's ruling removed the authored read from ObjectDataTable.enrich(); RecordDetailDrawer, the only other buildFieldMeta caller, passes no overrides at all. Both halves retire together, so the key leaves in one move.

.changeset/6687-chatbot-surface-authorable.md

  • names packages/types/src/complex.ts → packages/types/src/complex.ts — edited by this change

    Measured on both declaration faces before the fix, each with a control that had to hit: schema.surface appeared 0 times in renderer.tsx against schema.placeholder at 3 (one per registration) and schema.processVisibility at 1; and ChatbotSchema (packages/types/src/complex.ts) declared 34 keys, not this one. Two faces agreeing is what made the zero a reading rather than a bad query.

.changeset/6881-retire-data-table-toolbar.md

  • names data-display.ts → packages/types/src/data-display.ts — edited by this change

    What was measured. The key was declared on both published faces — data-display.ts (toolbar?: SchemaNode[], "Table toolbar actions/content") and the Zod mirror (SchemaNode | SchemaNode[]) — documented, mirrored, and read by NOTHING: data-table.tsx, the registered renderer for type: 'data-table', contains the word only in two prose comments and never reads schema.toolbar. The sibling emptyAction slot on the same interface IS mounted through SchemaRenderer, so the census zero is a reading, not a blind query. An author who wrote a toolbar got a green document and a blank result, with no signal anywhere that said so — the declared-vs-enforced failure mode that is worst for AI-authored metadata, which has nothing but the declaration to go on.

  • names data-table.tsx → packages/components/src/renderers/complex/data-table.tsx — edited by this change

    What was measured. The key was declared on both published faces — data-display.ts (toolbar?: SchemaNode[], "Table toolbar actions/content") and the Zod mirror (SchemaNode | SchemaNode[]) — documented, mirrored, and read by NOTHING: data-table.tsx, the registered renderer for type: 'data-table', contains the word only in two prose comments and never reads schema.toolbar. The sibling emptyAction slot on the same interface IS mounted through SchemaRenderer, so the census zero is a reading, not a blind query. An author who wrote a toolbar got a green document and a blank result, with no signal anywhere that said so — the declared-vs-enforced failure mode that is worst for AI-authored metadata, which has nothing but the declaration to go on.

.changeset/6882-datatable-declare-render-cell-editor-and-cell-classname.md

  • names data-table.tsx → packages/components/src/renderers/complex/data-table.tsx — edited by this change

    data-table has read both keys on its production path all along — renderCellEditor through a (schema as any) cast, cellClassName by destructuring it into the class of its three utility cells (the selection checkbox, the row number, the row actions). Neither was declared, so authoring either one was unchecked: a misspelling produced no error and no widget, and no editor completion offered them. DataTableSchema now declares both, and the cast in data-table.tsx is gone rather than replaced.

.changeset/6909-fieldeditwidget-dom-pass-through.md

  • names data-table.tsx → packages/components/src/renderers/complex/data-table.tsx — edited by this change

    Also corrects a comment in @object-ui/components' data-table.tsx that this change falsifies. It justified the injected editor's document-level pointerdown listener partly with "FieldEditWidget forwards autoFocus and nothing else out of the DOM block, so a host handler could not reach the control through it even if one were passed" — no longer true. The listener is still load-bearing for the other half of that reason, which is untouched: the renderCellEditor context object has nowhere to put an onBlur in the first place. Comment only; no behaviour change in that package.

.changeset/6939-kanban-column-cards.md

  • names complex.ts → packages/types/src/complex.ts — edited by this change

    Breaking, deliberately. KanbanColumn declared its card list as items in complex.ts and in the zod mirror complex.zod.ts. Every board reads cards. Measured on origin/main 78a3cc238: KanbanImpl.tsx reads .cards on 12 lines, KanbanEnhanced.tsx on 8, and bucketCardsIntoColumns twice more as col.cards || []; .items had zero read sites in either board (a same-shaped .title control on the same two files returns 8 and 3, so those zeros are readings and not a mis-shaped probe). Both catalog entries, the plugin docs and content/docs/api/schema-reference.md all author cards.

  • names complex.zod.ts → packages/types/src/zod/complex.zod.ts — edited by this change

    Breaking, deliberately. KanbanColumn declared its card list as items in complex.ts and in the zod mirror complex.zod.ts. Every board reads cards. Measured on origin/main 78a3cc238: KanbanImpl.tsx reads .cards on 12 lines, KanbanEnhanced.tsx on 8, and bucketCardsIntoColumns twice more as col.cards || []; .items had zero read sites in either board (a same-shaped .title control on the same two files returns 8 and 3, so those zeros are readings and not a mis-shaped probe). Both catalog entries, the plugin docs and content/docs/api/schema-reference.md all author cards.

.changeset/6940-rowactions-boolean-mirror.md

  • names zod/data-display.zod.ts → packages/types/src/zod/data-display.zod.ts — edited by this change

    The hand-written zod mirror in zod/data-display.zod.ts declared rowActions: z.array(z.any()).optional(). Every other face of the same key says boolean: the TS declaration it mirrors (rowActions?: boolean), the renderer's destructuring default (rowActions = false), its two truthiness gates and two colSpan arithmetic sites, the registered authoring input ({ type: 'boolean', label: 'Show Row Actions' }), defaultProps: { rowActions: true }, and the renderer's own docblock example, which authors "rowActions": true. The mirror was the single outlier — and the published one, so safeValidateSchema refused the exact spelling the component's documentation, defaults and authoring UI all teach. Two shipped examples/schema-catalog entries (user-table.json, full-featured-table.json) failed validation for this and no other reason; both now validate unchanged.

  • names zod/objectql.zod.ts → packages/types/src/zod/objectql.zod.ts — edited by this change

    The list view's same-named rowActions in zod/objectql.zod.ts — z.array(z.string()), the legacy bare-name action list on ObjectGridSchema — is a different key that is correct as it stands, is in parity with its own TS twin (rowActions?: string[]), and is not touched.

.changeset/6951-text-value-retired.md

  • names layout.ts → packages/types/src/layout.ts — edited by this change

    Two published faces, one retirement. The TypeScript interface TextSchema (@object-ui/types, layout.ts) declares value?: never; the Zod mirror TextSchema (@object-ui/types/zod, layout.zod.ts) declares value as a retirementTombstone(), so the key stays DECLARED and is refused BY NAME — a plain deletion would have let an authored value ride BaseSchema's .passthrough() into a silent blank, which is worse than the tolerated fallback it replaces. The value?: string members of TextSpanSchema and TabsSchema in the same file are other schemas' contracts and are unchanged.

  • names layout.zod.ts → packages/types/src/zod/layout.zod.ts — edited by this change

    Two published faces, one retirement. The TypeScript interface TextSchema (@object-ui/types, layout.ts) declares value?: never; the Zod mirror TextSchema (@object-ui/types/zod, layout.zod.ts) declares value as a retirementTombstone(), so the key stays DECLARED and is refused BY NAME — a plain deletion would have let an authored value ride BaseSchema's .passthrough() into a silent blank, which is worse than the tolerated fallback it replaces. The value?: string members of TextSpanSchema and TabsSchema in the same file are other schemas' contracts and are unchanged.

.changeset/6951-tree-view-data-retired.md

  • names data-display.ts → packages/types/src/data-display.ts — edited by this change

    Two published faces, one retirement — and why a tombstone, not a deletion. The TypeScript interface TreeViewSchema (@object-ui/types, data-display.ts) declares data?: never; the Zod mirror TreeViewSchema (@object-ui/types/zod, data-display.zod.ts) declares data as a retirementTombstone(). BaseSchema already declares data?: any (z.any().optional() on the mirror), so DELETING the member would not have refused the key — it would have ADMITTED it, unvalidated, through the base member, and the renderer would have drawn an empty tree. The tombstone on the extended schema shadows the base member on both faces; the pin measures the base accepting the very document the extended schema refuses.

  • names data-display.zod.ts → packages/types/src/zod/data-display.zod.ts — edited by this change

    Two published faces, one retirement — and why a tombstone, not a deletion. The TypeScript interface TreeViewSchema (@object-ui/types, data-display.ts) declares data?: never; the Zod mirror TreeViewSchema (@object-ui/types/zod, data-display.zod.ts) declares data as a retirementTombstone(). BaseSchema already declares data?: any (z.any().optional() on the mirror), so DELETING the member would not have refused the key — it would have ADMITTED it, unvalidated, through the base member, and the renderer would have drawn an empty tree. The tombstone on the extended schema shadows the base member on both faces; the pin measures the base accepting the very document the extended schema refuses.

.changeset/6972-markdown-inert-keys-retired.md

  • names data-display.ts → packages/types/src/data-display.ts — edited by this change

    What was measured, on this branch's base. sanitize was declared ?: boolean with @default true on both published faces — data-display.ts and the Zod mirror — documented, and read by NOTHING. Worse than an ordinary inert key, it implied a switch that does not exist: sanitization is unconditional. rehypePlugins in plugin-markdown/src/MarkdownImpl.tsx is a module-level const array whose last link is [rehypeSanitize, sanitizeSchema], handed to ReactMarkdown as-is — no ternary, no if, no runtime assembly. MarkdownRenderer forwards exactly content and className, and MarkdownImplProps accepts only those two. A repo-wide grep for schema.sanitize over packages/ and apps/ returns nothing, against a control of 20 .tsx files reading schema.content in the same query shape, so the zero is a reading, not a blind query. An author writing sanitize: false believed they turned XSS filtering off; one writing sanitize: true believed they turned it on. Neither was true.

.changeset/7070-no-invented-gantt-date-fields.md

  • names plugin-list/src/ListView.tsx → packages/plugin-list/src/ListView.tsx — edited by this change

    • app-shell/src/views/ObjectView.tsx — the console object page. The inline branch becomes ganttViewOptions, the sibling of calendarViewOptions and timelineViewOptions: the declared block spread whole, title floored at 'name', no date field invented. - plugin-list/src/ListView.tsx — the render branch AND the capability gate. - plugin-view/src/ObjectView.tsx — generateViewSchema, the authored object-view element route, which bypasses ListView entirely.

.changeset/7081-overlay-trigger-union.md

  • names zod/overlay.zod.ts → packages/types/src/zod/overlay.zod.ts — edited by this change

    This is a widening, not a replacement: every singular trigger keeps type-checking unchanged. The Zod mirror is untouched — zod/overlay.zod.ts already spelled every one of these keys z.union([SchemaNodeSchema, z.array(SchemaNodeSchema)]) — and so is the runtime: every overlay renderer hands schema.trigger to renderChildren, whose Array.isArray branch has served the array form all along, and every registration's defaultProps.trigger ships as an array. What changes is that the TypeScript face stops under-reporting an accept set that already ships: copying a renderer's own default into a typed document is no longer a type error against the type that shipped it. The seven docs pages' trigger rows follow the declaration.

.changeset/7087-disabled-twin-symmetry.md

  • names base.zod.ts → packages/types/src/zod/base.zod.ts — edited by this change

    Those 18 redeclarations are removed, on both faces. The interfaces inherit BaseSchema.disabled the way they always inherited visible; the zod mirrors inherit base.zod.ts's z.union([z.boolean(), z.string()]) through .extend()'s merged .shape, so there is no second spelling of the union to drift from — the route ChatbotSchema took in objectui#6169.

.changeset/7113-chart-data-model.md

  • names objectql.zod.ts → packages/types/src/zod/objectql.zod.ts — edited by this change

    .extend() with a NEW key still works and preserves the fold and the refinement; .optional(), z.discriminatedUnion, z.toJSONSchema and safeValidateSchema are all unaffected. Nothing in this repository calls the throwing combinators on either const, and the published surface already ships refined mirrors (objectql.zod.ts, complex.zod.ts, form.zod.ts, app.zod.ts), so the class is not new — but it is a real behaviour change on a published export and it belongs in the release note rather than in a reviewer's file.

  • names complex.zod.ts → packages/types/src/zod/complex.zod.ts — edited by this change

    .extend() with a NEW key still works and preserves the fold and the refinement; .optional(), z.discriminatedUnion, z.toJSONSchema and safeValidateSchema are all unaffected. Nothing in this repository calls the throwing combinators on either const, and the published surface already ships refined mirrors (objectql.zod.ts, complex.zod.ts, form.zod.ts, app.zod.ts), so the class is not new — but it is a real behaviour change on a published export and it belongs in the release note rather than in a reviewer's file.

.changeset/7200-object-form-section-style-keys-undeclared.md

  • names zod/objectql.zod.ts → packages/types/src/zod/objectql.zod.ts — edited by this change

    The authored-metadata type now agrees with @objectstack/spec, whose FormSectionSchema is a strict object declaring neither key, and with the ruling's rationale (maintainer 2026-09-01, verbatim): "retire the reads … Declaring the keys was weighed and not adopted: it would formally invite free Tailwind strings into authored metadata, the exact class the boundary exists to keep out." A ?: never tombstone was not used: ObjectFormSection has no zod mirror (ObjectFormSchema in zod/objectql.zod.ts does not declare sections), so there is no parse door to refuse at, and a tombstone is still a declaration in completion and in the published .d.ts.

.changeset/7265-types-user-filter-field-derives.md

  • names zod/objectql.zod.ts → packages/types/src/zod/objectql.zod.ts — edited by this change

    zod/objectql.zod.ts declared two schemas under names @objectstack/spec/ui already exports. They were triaged separately, by reading their sites, and went different ways.

.changeset/7295-chat-message-avatar-keys.md

  • names packages/types/src/complex.ts → packages/types/src/complex.ts — edited by this change

    packages/plugin-chatbot/src/index.tsx:173–178 reads message.avatar || userAvatarUrl and message.avatarFallback || userAvatarFallback (and the assistant twins), the authoring-to-runtime seam spreads every unlisted key through (chatMessageAdapter.ts, ...passthrough), and the SDUI renderer feeds the authored messages[] straight in — a per-message avatar override renders, is documented, and no authoring-facing type declared it. ChatMessage in packages/types/src/complex.ts has no index signature (objectui#5155, deliberately — none is added here), so an author annotating ChatbotSchema.messages was told a value that renders is an error (TS2353); the zod mirror ChatMessageSchema is a plain strip-mode z.object, so the value parsed green and was silently DROPPED from the parsed output.

.changeset/7322-object-kanban-group-by-limit.md

  • names objectql.ts → packages/types/src/objectql.ts — edited by this change

    Breaking for authored metadata: ObjectKanbanSchema.groupField is RETIRED (objectui#7322, ADR-0049 enforce-or-remove), and the two keys the object-kanban renderer actually reads — groupBy and limit — are now DECLARED and validated on both published faces: the TypeScript interface in objectql.ts and the Zod mirror in zod/objectql.zod.ts.

  • names zod/objectql.zod.ts → packages/types/src/zod/objectql.zod.ts — edited by this change

    Breaking for authored metadata: ObjectKanbanSchema.groupField is RETIRED (objectui#7322, ADR-0049 enforce-or-remove), and the two keys the object-kanban renderer actually reads — groupBy and limit — are now DECLARED and validated on both published faces: the TypeScript interface in objectql.ts and the Zod mirror in zod/objectql.zod.ts.

.changeset/7344-handler-string-any-mirrors.md

.changeset/7352-drill-down-config-mirror.md

  • names zod/data-display.zod.ts → packages/types/src/zod/data-display.zod.ts — edited by this change

    DrillDownConfigSchema is the zod mirror of DrillDownConfig, and both declarations that carry drillDown reference it — ChartSchema (zod/data-display.zod.ts) and ObjectDataTableSchema (zod/objectql.zod.ts) — so the published validator under @object-ui/types/zod reads the key for the first time (objectui#7352).

  • names zod/objectql.zod.ts → packages/types/src/zod/objectql.zod.ts — edited by this change

    DrillDownConfigSchema is the zod mirror of DrillDownConfig, and both declarations that carry drillDown reference it — ChartSchema (zod/data-display.zod.ts) and ObjectDataTableSchema (zod/objectql.zod.ts) — so the published validator under @object-ui/types/zod reads the key for the first time (objectui#7352).

.changeset/7363-objectql-union-arms.md

  • names objectql.ts → packages/types/src/objectql.ts — edited by this change

    ObjectGallerySchema and ObjectDataTableSchema are members of ObjectQLComponentSchema on both faces — the TS union in objectql.ts and the zod union in zod/objectql.zod.ts — so AnyComponentSchema, and with it validateSchema / safeValidateSchema / objectui validate, has an arm for object-gallery and object-data-table nodes (objectui#7363).

  • names zod/objectql.zod.ts → packages/types/src/zod/objectql.zod.ts — edited by this change

    ObjectGallerySchema and ObjectDataTableSchema are members of ObjectQLComponentSchema on both faces — the TS union in objectql.ts and the zod union in zod/objectql.zod.ts — so AnyComponentSchema, and with it validateSchema / safeValidateSchema / objectui validate, has an arm for object-gallery and object-data-table nodes (objectui#7363).

.changeset/7493-componentinput-retire-label-defaultvalue-advanced.md

  • names packages/types/src/zod/base.zod.ts → packages/types/src/zod/base.zod.ts — edited by this change

    The retirement kit: ?: never on ComponentInput (packages/types/src/base.ts), so authoring one is a tsc error at the registration site; retirementTombstone() on ComponentInputSchema (packages/types/src/zod/base.zod.ts), so an authored value is REFUSED at parse time with code: 'invalid_type', the key named in the issue path, and the migration note as the message (one string, both channels). Pinned in packages/types/src/__tests__/component-input-retired-keys-7493.test.ts, which also holds a tree-scoped absence census over every inputs: array under packages/** and apps/**.

.changeset/7499-gantt-non-axis-floors-omitted.md

  • names plugin-list/src/ListView.tsx → packages/plugin-list/src/ListView.tsx — edited by this change

    • plugin-list/src/ListView.tsx — the object-gantt render branch. - plugin-view/src/ObjectView.tsx — generateViewSchema, the authored object-view element route, which bypasses ListView entirely.

.changeset/7530-predicate-envelope-declared.md

  • names base.zod.ts → packages/types/src/zod/base.zod.ts — edited by this change

    • ExpressionWire (type, main entry) — the TypeScript wire union, in packages/types/src/expression.ts. - ExpressionWireSchema (@object-ui/types/zod) — its runtime twin, hoisted out of zod/form.zod.ts (where it was module-private) into zod/expression.zod.ts and imported by both base.zod.ts and form.zod.ts. One envelope type, reused by reference; no second spelling.

.changeset/7580-responsive-vocabulary-rehome.md

  • names mobile.ts → packages/types/src/mobile.ts — edited by this change

    • BreakpointName (xs…2xl) is now declared in @object-ui/types (mobile.ts) instead of re-exported from the spec. No consumer change: same name, same six members, same export sites on @object-ui/types and @object-ui/mobile. Only its provenance moved. - BreakpointColumnMap is now declared in @object-ui/layout (ResponsiveGrid.tsx), verbatim from the retired $strict schema: six optional column counts, no index signature. responsive-grid's columns input and its resolver are unchanged.

.changeset/7632-shared-record-source-config.md

  • names packages/types/src/objectql.ts → packages/types/src/objectql.ts — edited by this change

    That ladder is published contract on both faces — packages/types/src/objectql.ts and its zod mirror both ship .describe() strings naming getDataConfig's order (77cb489b4, maintainer ruling 2026-09-02), pinned by objectql-record-source-refinement-6939.test.ts — and it was hand-copied into five plugin components with no gate holding them together. A change to the ruled order had five edit sites and nothing that noticed a missed one; that is the AGENTS.md #0.1 drift class.

.changeset/7654-floating-chatbot-trigger-icon-tombstone.md

  • names packages/plugin-chatbot/src/renderer.tsx → packages/plugin-chatbot/src/renderer.tsx — edited by this change

    It is also absent from the chatbot-floating registration's inputs AND from its defaultProps (packages/plugin-chatbot/src/renderer.tsx), both re-confirmed here. No designer control ever offered it and no designer-created node carries it, so TypeScript was the only way to reach the key. That is what makes this half of objectui#7654 an ordinary retirement; the card's other key, displayMode, is seeded into defaultProps and is NOT touched here.

.changeset/7694-chart-series-chart-type-alias-refusal.md

  • names zod/data-display.zod.ts → packages/types/src/zod/data-display.zod.ts — edited by this change

    • Before: series: [{ name: 'revenue', chartType: 'line' }] validated green through @object-ui/types/zod (safeValidateSchema, objectui check / objectui validate, any pipeline that keeps parse()'s output) — and the key was gone from the output, so a consumer of the parse result drew that series in the chart's own family, precisely what the author was overriding. On the TypeScript face the key was merely an excess property on a fresh literal; a widened object carrying it assigned structurally. - After: the same document REFUSES at series[i].chartType (issue code invalid_type) with one message on both channels — the parse-time issue and the .describe() metadata: Unrecognized key(s) on this chart series: \chartType`. Did you mean `chartType` → `type`? …followed by the reason and the remedy. Writetype: 'bar' | 'line' | 'area'. On the TypeScript face ChartDataSeries.chartTypeis a?: nevertombstone, so both the fresh literal and the widened assignment aretsc errors. - **Both written** ({ type: 'bar', chartType: 'line' }) is refused at chartTypealone — the key is not folded ontotypeand no precedence is minted between the two spellings. - **Which documents to scan.** The narrowing does not stop atChartDataSeriesSchema; it reaches every document through the parents that embed it — ChartSchema.series (zod/data-display.zod.ts, z.array(ChartDataSeriesSchema)) and, one level further out, ReportSectionSchema.chart (zod/reports.zod.ts, ChartSchema.optional()). Authors meet it through safeValidateSchema() (zod/index.zod.ts, which parses AnyComponentSchema) and through the CLI's objectui validate command (packages/cli/src/cli.ts). In practice: every chartnode'sseries[], and every report section whose chart` carries one.

.changeset/7722-wrapper-class-five-more.md

  • names data-display.ts → packages/types/src/data-display.ts — edited by this change

    Each of renderers/form/switch.tsx, textarea.tsx, date-picker.tsx, select.tsx and renderers/data-display/list.tsx reads schema.wrapperClass onto its wrapper element, and neither the TypeScript interface (form.ts, data-display.ts) nor the zod mirror (zod/form.zod.ts, zod/data-display.zod.ts) declared the key. The reads compiled through BaseSchema's index signature (objectui#5155) and the values parsed through .passthrough(), admitted unexamined. The same key, on the same class of read, is declared on CheckboxSchema (b74a8598d), FileUploadSchema and FilterBuilderSchema (objectui#6150); these five were left out only because their doc pages never listed it.

  • names zod/data-display.zod.ts → packages/types/src/zod/data-display.zod.ts — edited by this change

    Each of renderers/form/switch.tsx, textarea.tsx, date-picker.tsx, select.tsx and renderers/data-display/list.tsx reads schema.wrapperClass onto its wrapper element, and neither the TypeScript interface (form.ts, data-display.ts) nor the zod mirror (zod/form.zod.ts, zod/data-display.zod.ts) declared the key. The reads compiled through BaseSchema's index signature (objectui#5155) and the values parsed through .passthrough(), admitted unexamined. The same key, on the same class of read, is declared on CheckboxSchema (b74a8598d), FileUploadSchema and FilterBuilderSchema (objectui#6150); these five were left out only because their doc pages never listed it.

.changeset/7735-zod-mirrors-stop-authoring-defaults.md

  • names layout.zod.ts → packages/types/src/zod/layout.zod.ts — edited by this change

    What changed. All 41 .default() call sites under packages/types/src/zod/ are removed — layout.zod.ts 22, crud.zod.ts 11, form.zod.ts 5, views.zod.ts 2, app.zod.ts 1. @object-ui/components reconciles the third face objectui#8229 found: flex's registration defaultProps.align seeded 'center', the value its own renderer never applies, so a designer-made node laid out differently from a hand-authored one; it now seeds 'start'.

  • names crud.zod.ts → packages/types/src/zod/crud.zod.ts — edited by this change

    What changed. All 41 .default() call sites under packages/types/src/zod/ are removed — layout.zod.ts 22, crud.zod.ts 11, form.zod.ts 5, views.zod.ts 2, app.zod.ts 1. @object-ui/components reconciles the third face objectui#8229 found: flex's registration defaultProps.align seeded 'center', the value its own renderer never applies, so a designer-made node laid out differently from a hand-authored one; it now seeds 'start'.

  • names views.zod.ts → packages/types/src/zod/views.zod.ts — edited by this change

    What changed. All 41 .default() call sites under packages/types/src/zod/ are removed — layout.zod.ts 22, crud.zod.ts 11, form.zod.ts 5, views.zod.ts 2, app.zod.ts 1. @object-ui/components reconciles the third face objectui#8229 found: flex's registration defaultProps.align seeded 'center', the value its own renderer never applies, so a designer-made node laid out differently from a hand-authored one; it now seeds 'start'.

.changeset/7762-object-grid-export-options-bare-array-refusal.md

  • names ObjectGrid.tsx → packages/plugin-grid/src/ObjectGrid.tsx — edited by this change

    What was measured, on this branch's base. The mirror declared NO exportOptions member at all, and BaseSchema is .passthrough(), so ObjectGridSchema.safeParse({ type: 'object-grid', objectName: 'accounts', exportOptions: ['csv', 'xlsx'] }) returned success: true with the array back VERBATIM — as did { formats: ['csv', 'pdf'], compression: 'gzip' }. Nothing on the render path parses, and ObjectGrid.tsx reads schema.exportOptions?.formats and only that, so the authored array then lost SILENTLY to the ['csv', 'json'] default: the useEffect that warns about dropped formats reads .formats too and returns early when it is absent, while !!schema.exportOptions kept the export button on screen. An author declared ['csv', 'xlsx'] and got csv/json with no error, no warning and no console line. The two authoring faces disagreed in the direction opposite to objectui#6956's: the TypeScript interface already declared the object form only, so TS refused what zod admitted.

.changeset/7773-kanban-adapter-groupfield-write.md

  • names ListView.tsx → packages/plugin-list/src/ListView.tsx — edited by this change

    Who is NOT affected — the boundary is node-local. Every VIEW-LEVEL groupField read is untouched and still live: it is a legacy alias of the spec's groupByField on the kanban view config, mapped by normalize-list-view.ts, and both adapters still resolve lanes through it (ObjectView.tsx's kanbanCfg.groupField ||, ListView.tsx's groupByField || groupField). Authoring options.kanban.groupField on a list-view or object-view keeps working exactly as documented in packages/plugin-list/README.md. groupField is dead only on the generated object-kanban NODE.

.changeset/7780-object-kanban-record-source.md

.changeset/7917-export-breadcrumb-object-tree-zod-schemas.md

  • names objectql.zod.ts → packages/types/src/zod/objectql.zod.ts — edited by this change

    AnyComponentSchema declares 107 node component types. 105 of them could be named on the ./zod barrel — ButtonSchema.safeParse(node), which is what a designer, a form builder or a targeted test needs. The arms declaring type: 'breadcrumb' (navigation.zod.ts) and type: 'object-tree' (objectql.zod.ts) could not: both were already export const in their own module, but index.zod.ts — the package's only zod entry point — did not re-export them, so the schemas existed, were maintained, and were applied by the union while no consumer could name them.

.changeset/7918-zod-lazy-getter-identity.md

  • names base.zod.ts → packages/types/src/zod/base.zod.ts — edited by this change

    The card that found this did not claim the ten were wrong. It asked whether the spelling was buying a temporal-dead-zone dodge, and that check is what shipped. Each of the ten was rewritten in place to const inner = ANGLE-BRACKETS(body); z.lazy(() => inner), the package rebuilt, and the built barrel imported in a fresh process. Eight refuse to load. Seven name the very const being declared (children: z.array(TreeNodeSchema) sits inside TreeNodeSchema's own initialiser); SchemaNodeSchema names BaseSchemaCore, which base.zod.ts declares below it. For those eight the z.lazy is load-bearing, so ActionSchema, AppMenuItemSchema, FilterGroupSchema, MenuItemSchema, NavLinkSchema, NavigationMenuItemSchema, SchemaNodeSchema and TreeNodeSchema keep the spelling they have. The two that loaded clean are memoised: FilterBuilderConditionSchema is not recursive at all, and NavigationItemSchema already defers its self-reference through an inner z.lazy(() => NavigationItemSchema) on children.

  • names overlay.zod.ts → packages/types/src/zod/overlay.zod.ts — edited by this change

    ⚠️ Also settled while locating the ten: AppMenuItemSchema has no declaration of its own — it is the barrel alias of app.zod.ts's MenuItemSchema, while the barrel's own MenuItemSchema is overlay.zod.ts's. Two different schemas, so the list really is ten entries and not nine.

.changeset/7963-alert-dialog-footer-keys-retired.md

  • names objectql.ts → packages/types/src/objectql.ts — edited by this change

    Nothing else moves. These spellings are overloaded across the tree and every other owner is a live key on a different declaration — FormSchema.cancelLabel, objectql.ts's confirmLabel, plugin-designer's ConfirmDialog React props, plugin-grid's def.confirmLabel, and plugin-form's ModalForm / DrawerForm, which build a local cancelLabel from schema.cancelText. None is an AlertDialogSchema; none is touched, and a pin asserts it. No fixture, catalog schema, example app or doc fence authored any of the three on an alert-dialog node, so no shipped document is stranded.

.changeset/8166-record-scope-data-root.md

  • names views/metadata-admin/predicate.ts → packages/app-shell/src/views/metadata-admin/predicate.ts — edited by this change

    Migration. Rewrite data.foo as record.foo on any runtime record surface — the canonical spelling since 83fe6e741, and the only one that reaches the row. The metadata-admin designer is unaffected: its data is the DRAFT under edit (ADR-0089 D3, CANONICAL_ROOT_BY_LAYER = { runtime: 'record', metadata: 'data' }), bound by views/metadata-admin/predicate.ts through its own builder, which takes only the identity roots from this bag and assigns its own data last.

.changeset/8167-conditionbuilder-mount-scope.md

  • names rowPredicateCanon.ts → packages/core/src/evaluator/rowPredicateCanon.ts — edited by this change

    • scope?: 'record' | 'flattened' is now an optional prop, forwarded verbatim to CelPredicateField. Omitting it forwards undefined, so the engine hint is exactly what it was and every mount that passes nothing is unchanged. It deliberately does not derive the scope from subjects.fieldPrefix — that would silently decide the mounts whose tier is still an open question. - An action's Visible when and Disabled when (ActionDefaultInspector) declare scope="record". Conformance: the row-predicate canon in @object-ui/core (rowPredicateCanon.ts) names visible / disabled on an action renderer as a row surface in its own words. - An object validation rule's condition (ObjectValidationsPanel) declares scope="record". The authority there is the server: objectql's rule validator evaluates a script / cross_field condition with { record, previous } and nothing else, and since objectstack#4649 an unevaluable predicate is fail-CLOSED — so a bare reference authored here did not merely fail to match, it rejected every write to the object while the editor linted it green.

.changeset/8331-data-table-empty-action-primitive-node.md

  • names packages/types/src/data-display.ts → packages/types/src/data-display.ts — edited by this change

    Behaviour change on a published surface, deliberately. DataTableSchema.emptyAction is declared SchemaNode on both published faces — packages/types/src/data-display.ts and its Zod twin in packages/types/src/zod/data-display.zod.ts — and SchemaNode is BaseSchema | string | number | boolean | null | undefined. The empty-state render path additionally required typeof … === 'object', so an authored emptyAction: 'Create the first record' rendered nothing and reported nothing: declared wider than enforced, failing in the direction that loses the author's content without a diagnostic. A node that renders nothing today therefore starts rendering.

  • names packages/types/src/zod/data-display.zod.ts → packages/types/src/zod/data-display.zod.ts — edited by this change

    Behaviour change on a published surface, deliberately. DataTableSchema.emptyAction is declared SchemaNode on both published faces — packages/types/src/data-display.ts and its Zod twin in packages/types/src/zod/data-display.zod.ts — and SchemaNode is BaseSchema | string | number | boolean | null | undefined. The empty-state render path additionally required typeof … === 'object', so an authored emptyAction: 'Create the first record' rendered nothing and reported nothing: declared wider than enforced, failing in the direction that loses the author's content without a diagnostic. A node that renders nothing today therefore starts rendering.

.changeset/8415-filter-builder-condition-id.md

  • names complex.ts → packages/types/src/complex.ts — edited by this change

    Breaking for authored metadata: a filter-builder CONDITION must now declare id (objectui#8415). It is declared on both published faces — the TypeScript interface FilterBuilderCondition in complex.ts and the Zod mirror FilterBuilderConditionSchema in zod/complex.zod.ts — so a key the renderer has always required is finally validated instead of silently discarded.

  • names zod/complex.zod.ts → packages/types/src/zod/complex.zod.ts — edited by this change

    Breaking for authored metadata: a filter-builder CONDITION must now declare id (objectui#8415). It is declared on both published faces — the TypeScript interface FilterBuilderCondition in complex.ts and the Zod mirror FilterBuilderConditionSchema in zod/complex.zod.ts — so a key the renderer has always required is finally validated instead of silently discarded.

.changeset/8478-describe-line-addresses.md

.changeset/8478-zod-pins-complex.md

.changeset/8478-zod-pins-form-layout.md

.changeset/8499-node-slot-registered-arms.md

  • names zod/layout.zod.ts → packages/types/src/zod/layout.zod.ts — edited by this change

    • SemanticElementSchema (zod/layout.zod.ts) — the seven HTML sectioning tags renderers/layout/semantic.tsx registers: aside main header nav footer section article. - HtmlElementSchema (zod/layout.zod.ts) — the 37 safe flow/inline tags renderers/basic/html-elements.tsx registers (h1…h6, p, a, ul, img, …), plus the per-tag keys that module forwards to the DOM (href, target, rel, title, src, alt, width, height, dateTime, cite). ⚠️ Dated note, 2026-09-27 — that set has since gained code — objectui#10756. At this change TAGS and this arm both named 37 tags; both now name 38, and the parity pin counts 38. The rest of this entry is kept as the reading of this change. - InputShorthandSchema (zod/form.zod.ts) — email / password, the two aliases renderers/form/input.tsx registers onto the input renderer with inputType pinned. inputType is deliberately NOT declared on this arm: the wrapper spreads its own value last, so an authored one is overwritten. - UiCalendarSchema (zod/form.zod.ts) — ui:calendar, the date-picker primitive renderers/form/calendar.tsx registers under exactly that key (skipFallback, because bare calendar belongs to the plugin-calendar view).

.changeset/8516-8556-mirror-partial-record-narrowing.md

  • names zod/layout.zod.ts → packages/types/src/zod/layout.zod.ts — edited by this change

    | key | mirror was | mirror is | | :-- | :--------- | :-------- | | GridSchema.columns (zod/layout.zod.ts) | z.record(z.string(), z.number()) | a PARTIAL record over the six breakpoints | | ReportComponentSchema.exportConfigs (zod/reports.zod.ts) | z.record(z.string(), ReportExportConfigSchema) | a PARTIAL record over ReportExportFormat |

.changeset/8735-objectql-mirror-docblocks-not-defaulted.md

  • names zod/objectql.zod.ts → packages/types/src/zod/objectql.zod.ts — edited by this change

    Correct four zod/objectql.zod.ts docblocks that described the behaviour objectui#8317 removed. Since that change the zod mirrors strip imported @objectstack/spec defaults at this package's import boundary, but the docblocks on HttpRequestSchema, ListColumnSchema, SelectionConfigSchema and PaginationConfigSchema still said, in the present tense, that method, prefix.type, type and pageSize are defaulted on parse — the opposite of what each export does. Each now says the key is declared and accepted but NOT defaulted on parse.

.changeset/8767-object-grid-refuses-string-sort.md

  • names packages/types/src/objectql.ts → packages/types/src/objectql.ts — edited by this change

    Migration. Write the array: sort: [{ field: 'name', order: 'desc' }]. Both keys are required. SortConfig.order carries no ? in @object-ui/types (packages/types/src/objectql.ts) and no .optional() in its zod mirror, and the protocol's own reusable SortItemSchema requires order as well — measured: that schema refuses [{ field: 'name' }] with invalid_value at 0.order. Do not omit it: this block's array arm interpolates whatever is present, so an omitted order lowers to $orderby: 'name undefined' today. That is pre-existing behaviour on the arm this change does not touch, and it is filed as a successor card rather than widened into here.

.changeset/8800-retire-ai-insights.md

  • names ai.ts → packages/types/src/ai.ts — edited by this change

    The retirement's tombstones are the comment standing where the interface was in ai.ts and the comment standing where the barrel re-export was in index.ts; the executable half, including the tree-wide census with its controls, is packages/types/src/__tests__/ai-insights-retired-8800.test.ts. The objectui#8178 exclusion pin that deliberately held AIInsightsSchema.objectName out of that retirement was rewritten by this ruling, which is the only thing that was ever allowed to rewrite it.

.changeset/8801-object-kanban-allow-collapse-retired.md

  • names packages/types/src/objectql.ts → packages/types/src/objectql.ts — edited by this change

    • the declarations retired here — packages/types/src/objectql.ts and its mirror packages/types/src/zod/objectql.zod.ts; - the pins that assert the retirement — object-kanban-allow-collapse-retired-8801.test.ts and bare-kanban-node-key-retired-8802.test.ts; - a comment in packages/types/src/zod/complex.zod.ts, recording that the deleted retiredZeroReadKanbanKey helper once carried this spelling on the SIBLING arm; - one row of content/docs/api/schema-reference.md; - the .changeset/ release notes that discuss it — this one, the two historical entries covering the sibling arm's own spelling, and objectui#9629's note recording the correction to this paragraph.
  • names packages/types/src/zod/objectql.zod.ts → packages/types/src/zod/objectql.zod.ts — edited by this change

    • the declarations retired here — packages/types/src/objectql.ts and its mirror packages/types/src/zod/objectql.zod.ts; - the pins that assert the retirement — object-kanban-allow-collapse-retired-8801.test.ts and bare-kanban-node-key-retired-8802.test.ts; - a comment in packages/types/src/zod/complex.zod.ts, recording that the deleted retiredZeroReadKanbanKey helper once carried this spelling on the SIBLING arm; - one row of content/docs/api/schema-reference.md; - the .changeset/ release notes that discuss it — this one, the two historical entries covering the sibling arm's own spelling, and objectui#9629's note recording the correction to this paragraph.
  • names packages/types/src/zod/complex.zod.ts → packages/types/src/zod/complex.zod.ts — edited by this change

    • the declarations retired here — packages/types/src/objectql.ts and its mirror packages/types/src/zod/objectql.zod.ts; - the pins that assert the retirement — object-kanban-allow-collapse-retired-8801.test.ts and bare-kanban-node-key-retired-8802.test.ts; - a comment in packages/types/src/zod/complex.zod.ts, recording that the deleted retiredZeroReadKanbanKey helper once carried this spelling on the SIBLING arm; - one row of content/docs/api/schema-reference.md; - the .changeset/ release notes that discuss it — this one, the two historical entries covering the sibling arm's own spelling, and objectui#9629's note recording the correction to this paragraph.

.changeset/8802-8257-8008-kanban-gantt-family-retirement.md

  • names complex.ts → packages/types/src/complex.ts — edited by this change

    What each retirement was, measured. Three of the four were registration-only: no schema face in @object-ui/types ever declared kanban-ui, kanban-enhanced or gantt as a component node type, so unregistering is the whole retirement. The bare kanban key was the exception — it had a declared arm on both faces (KanbanSchema in complex.ts and its Zod mirror), and a plain deletion there would have been the objectui#7664 failure: BaseSchema is .passthrough(), so a document naming a dropped key validates green and renders nothing. It therefore retires as a named refusal: the Zod union keeps an arm claiming the literal and answers a { "type": "kanban" } document with a message naming object-kanban as the remedy, while the TypeScript half is the absence of the arm from ComplexSchema and of the key from SchemaRegistry, so tsc refuses it at the authoring site.

.changeset/8854-app-shell-readme-flow-draft.md

  • names clientValidation.ts → packages/app-shell/src/views/metadata-admin/clientValidation.ts — edited by this change

    Which door was measured. Not the server, and not the node and edge schemas one at a time: the app-shell metadata admin validates a flow draft client-side by handing the whole draft to the spec's FlowSchema — clientValidation.ts's LOADERS.flow resolves it and ResourceEditPage calls validateMetadataDraft(type, draft) with the editor's entire body. Graded per node and per edge, this block would have reported green while still being refused on save; that is how the identity keys stayed invisible to two previous cards against this same fence.

.changeset/8885-object-chart-drilldown-title-compareto.md

  • names packages/types/src/objectql.ts → packages/types/src/objectql.ts — edited by this change

    ObjectChart.tsx reads all three off schema, and until now neither published copy declared any of them: not the TS interface (packages/types/src/objectql.ts) and not the zod mirror (packages/types/src/zod/objectql.zod.ts). They rode BaseSchema's index signature / .passthrough() and arrived unvalidated. drillDown was the sharpest case — this component's registry inputs advertise it to the designer palette, and @objectstack/spec publishes ChartDrillDownSchema for exactly this carrier, so an author was offered a key that neither published shape mentioned.

  • names packages/types/src/zod/objectql.zod.ts → packages/types/src/zod/objectql.zod.ts — edited by this change

    ObjectChart.tsx reads all three off schema, and until now neither published copy declared any of them: not the TS interface (packages/types/src/objectql.ts) and not the zod mirror (packages/types/src/zod/objectql.zod.ts). They rode BaseSchema's index signature / .passthrough() and arrived unvalidated. drillDown was the sharpest case — this component's registry inputs advertise it to the designer palette, and @objectstack/spec publishes ChartDrillDownSchema for exactly this carrier, so an author was offered a key that neither published shape mentioned.

.changeset/8913-object-kanban-columns-declared.md

  • names objectql.ts → packages/types/src/objectql.ts — edited by this change

    What moved. ObjectKanbanSchema gains columns on both halves that move together — the TypeScript interface (objectql.ts) and its Zod mirror (zod/objectql.zod.ts). Retiring the bare kanban node type key (objectui#8802) removed the only face that judged a lane, and object-kanban had never declared the key, so it rode BaseSchema's [key: string]: any / .passthrough(): read by the renderer at three sites, named by no published face.

  • names zod/objectql.zod.ts → packages/types/src/zod/objectql.zod.ts — edited by this change

    What moved. ObjectKanbanSchema gains columns on both halves that move together — the TypeScript interface (objectql.ts) and its Zod mirror (zod/objectql.zod.ts). Retiring the bare kanban node type key (objectui#8802) removed the only face that judged a lane, and object-kanban had never declared the key, so it rode BaseSchema's [key: string]: any / .passthrough(): read by the renderer at three sites, named by no published face.

.changeset/8990-object-kanban-groupby-optional.md

  • names packages/types/src/objectql.ts → packages/types/src/objectql.ts — edited by this change

    @objectstack/spec declares the key optional — groupBy: z.string().optional() on ObjectKanbanPropsSchema — while this package required it on the TypeScript declaration (packages/types/src/objectql.ts) and on the Zod mirror (packages/types/src/zod/objectql.zod.ts). objectui was therefore narrower than the protocol on a published key: ObjectKanbanSchema.safeParse and safeValidateSchema refused an object-kanban node the protocol accepts, and such a node could not be annotated with its own type.

  • names packages/types/src/zod/objectql.zod.ts → packages/types/src/zod/objectql.zod.ts — edited by this change

    @objectstack/spec declares the key optional — groupBy: z.string().optional() on ObjectKanbanPropsSchema — while this package required it on the TypeScript declaration (packages/types/src/objectql.ts) and on the Zod mirror (packages/types/src/zod/objectql.zod.ts). objectui was therefore narrower than the protocol on a published key: ObjectKanbanSchema.safeParse and safeValidateSchema refused an object-kanban node the protocol accepts, and such a node could not be annotated with its own type.

  • names packages/plugin-list/src/ListView.tsx → packages/plugin-list/src/ListView.tsx — edited by this change

    • packages/plugin-list/src/ListView.tsx generates the node as groupBy: laneField. objectDef loads asynchronously, so laneField is undefined on every load until it lands, and stays undefined whenever the object offers no stageField hint and none of status / stage / state / phase. The renderer serves that node; both published faces refused it. - content/docs/utilities/data-objectstack.mdx documents an object-kanban node that is exactly { type, dataSource }, with no groupBy. ⚠️ This one is weaker and is cited for what it is: that fragment is still refused after this change, at RECORD_SOURCE_REQUIRED, because dataSource is not a rung of the record-source ladder. It shows a lane-less board is a documented authoring; it is not a document this change admits.

.changeset/8992-user-actions-collapse-and-docblock.md

  • names objectql.zod.ts → packages/types/src/zod/objectql.zod.ts — edited by this change

    objectql.zod.ts's UserActionsSchema read stripImportedDefaults(Spec).extend({ group, hideFields, rowColor }), an extension that existed only because @objectstack/spec did not declare those three keys while normalizeListViewSchema folded objectui's legacy showGroup / showHideFields / showColor onto them. The protocol adopted all three in 17.3.0 (objectui#5435's ruling), so the extension is now a second local copy of a protocol declaration — the shape two faces start drifting from — and it collapses into the plain by-reference re-export its own note always said it would become.

.changeset/9092-inline-locale-declared-face.md

  • names objectql.ts → packages/types/src/objectql.ts — edited by this change

    • AppComponentSchema.label (app.ts) - ObjectGridSchema.label and .description (objectql.ts) - PageNodeSchema.aria.ariaLabel (layout.ts)
  • names layout.ts → packages/types/src/layout.ts — edited by this change

    • AppComponentSchema.label (app.ts) - ObjectGridSchema.label and .description (objectql.ts) - PageNodeSchema.aria.ariaLabel (layout.ts)

.changeset/9162-node-slot-guard-class-closure.md

  • names packages/types/src/zod/base.zod.ts → packages/types/src/zod/base.zod.ts — edited by this change

    What leaked. {schema.footer && ANGLE-BRACKETS(CardFooter)…ANGLE-BRACKETS(/CardFooter)} does not evaluate to false when the slot is falsy — it evaluates to the slot, and React renders numbers. A node slot's published zod face carries a z.number() arm (nodeUnionOptions, packages/types/src/zod/base.zod.ts), so footer: 0 is legal authored input, and it painted a stray 0 into the DOM. NaN painted three characters. The && also short-circuits, so renderChildren's own if (!children) return null first leg was never reached — which is why the objectui#8908 bridge repair could not cover any of these sites.

.changeset/9256-list-timeline-content-channels.md

  • names packages/types/src/data-display.ts → packages/types/src/data-display.ts — edited by this change

    These two were held out of the previous family-D slice for a SERIAL constraint on packages/types/src/data-display.ts and never for a verdict. Readership was re-derived for both rather than inherited: a TypeScript compiler-API sweep files every .body / .children read under the declared type of its receiver and answers zero for ListSchema and TimelineSchema while its live controls fire. timeline's bare-key owner is any-typed, so it was attributed directly as well — packages/plugin-timeline contains no channel read of any kind.

.changeset/9309-object-gallery-filter-destination-typed.md

  • names objectql.ts → packages/types/src/objectql.ts — edited by this change

    ObjectGallerySchema.filter is typed as the destination its own docblock names — QueryParams['$filter'] — on both faces, the TS interface in objectql.ts and the zod mirror in zod/objectql.zod.ts (objectui#9309).

  • names zod/objectql.zod.ts → packages/types/src/zod/objectql.zod.ts — edited by this change

    ObjectGallerySchema.filter is typed as the destination its own docblock names — QueryParams['$filter'] — on both faces, the TS interface in objectql.ts and the zod mirror in zod/objectql.zod.ts (objectui#9309).

.changeset/9511-record-id-is-a-string.md

  • names objectql.ts → packages/types/src/objectql.ts — edited by this change

    The three authorable keys, each on BOTH faces. ObjectFormSchema.recordId (objectql.ts + zod/objectql.zod.ts), DetailViewSchema.resourceId (views.ts + zod/views.zod.ts) and DetailSchema.resourceId (crud.ts + zod/crud.zod.ts). ⚠️ The crud pair is DetailSchema, not DetailViewSchema, and it reaches the same renderer — not by symbol but by data flow: plugin-detail registers the 'detail' node type onto DetailView. A read that follows TypeScript symbols alone finds two keys and is incomplete.

  • names zod/objectql.zod.ts → packages/types/src/zod/objectql.zod.ts — edited by this change

    The three authorable keys, each on BOTH faces. ObjectFormSchema.recordId (objectql.ts + zod/objectql.zod.ts), DetailViewSchema.resourceId (views.ts + zod/views.zod.ts) and DetailSchema.resourceId (crud.ts + zod/crud.zod.ts). ⚠️ The crud pair is DetailSchema, not DetailViewSchema, and it reaches the same renderer — not by symbol but by data flow: plugin-detail registers the 'detail' node type onto DetailView. A read that follows TypeScript symbols alone finds two keys and is incomplete.

  • names zod/views.zod.ts → packages/types/src/zod/views.zod.ts — edited by this change

    The three authorable keys, each on BOTH faces. ObjectFormSchema.recordId (objectql.ts + zod/objectql.zod.ts), DetailViewSchema.resourceId (views.ts + zod/views.zod.ts) and DetailSchema.resourceId (crud.ts + zod/crud.zod.ts). ⚠️ The crud pair is DetailSchema, not DetailViewSchema, and it reaches the same renderer — not by symbol but by data flow: plugin-detail registers the 'detail' node type onto DetailView. A read that follows TypeScript symbols alone finds two keys and is incomplete.

  • names crud.ts → packages/types/src/crud.ts — edited by this change

    The three authorable keys, each on BOTH faces. ObjectFormSchema.recordId (objectql.ts + zod/objectql.zod.ts), DetailViewSchema.resourceId (views.ts + zod/views.zod.ts) and DetailSchema.resourceId (crud.ts + zod/crud.zod.ts). ⚠️ The crud pair is DetailSchema, not DetailViewSchema, and it reaches the same renderer — not by symbol but by data flow: plugin-detail registers the 'detail' node type onto DetailView. A read that follows TypeScript symbols alone finds two keys and is incomplete.

  • names zod/crud.zod.ts → packages/types/src/zod/crud.zod.ts — edited by this change

    The three authorable keys, each on BOTH faces. ObjectFormSchema.recordId (objectql.ts + zod/objectql.zod.ts), DetailViewSchema.resourceId (views.ts + zod/views.zod.ts) and DetailSchema.resourceId (crud.ts + zod/crud.zod.ts). ⚠️ The crud pair is DetailSchema, not DetailViewSchema, and it reaches the same renderer — not by symbol but by data flow: plugin-detail registers the 'detail' node type onto DetailView. A read that follows TypeScript symbols alone finds two keys and is incomplete.

.changeset/9549-tree-filter-declared.md

  • names objectql.ts → packages/types/src/objectql.ts — edited by this change

    ObjectTreeSchema.filter is declared on both faces, in the shape objectui#9309 settled for ObjectGallerySchema.filter: QueryParams['$filter'] by indexed access on the TS interface in objectql.ts, and the same two-arm union (array first) on the zod mirror in zod/objectql.zod.ts (objectui#9549).

  • names zod/objectql.zod.ts → packages/types/src/zod/objectql.zod.ts — edited by this change

    ObjectTreeSchema.filter is declared on both faces, in the shape objectui#9309 settled for ObjectGallerySchema.filter: QueryParams['$filter'] by indexed access on the TS interface in objectql.ts, and the same two-arm union (array first) on the zod mirror in zod/objectql.zod.ts (objectui#9549).

.changeset/9550-object-tree-root-barrel.md

  • names objectql.ts → packages/types/src/objectql.ts — edited by this change

    ObjectQLComponentSchema declares the node types an ObjectQL block may be. Every one of its arms was a named export of this package's root barrel except ObjectTreeSchema, which was declared in objectql.ts, applied by the union, and re-exported by the ./zod barrel (objectui#7917) — while no TypeScript consumer could name it. There is no ./objectql subpath to reach around the barrel: the package's exports map is pinned by packages/types/src/__tests__/package-exports-manifest.test.ts, and the root barrel was the only route to this type.

.changeset/9606-object-kanban-card-title.md

  • names zod/objectql.zod.ts → packages/types/src/zod/objectql.zod.ts — edited by this change

    Both published faces of the object-kanban arm now name the key: the zod mirror ObjectKanbanSchema in zod/objectql.zod.ts and its TypeScript twin, the ObjectKanbanSchema interface in objectql.ts. Both declare it OPTIONAL, at the same requiredness the other face uses, so the two faces accept and refuse the same documents. (Located and cited by SYMBOL: line addresses in zod/objectql.zod.ts have drifted before, and this change is itself about a drifted mirror.)

  • names objectql.ts → packages/types/src/objectql.ts — edited by this change

    Both published faces of the object-kanban arm now name the key: the zod mirror ObjectKanbanSchema in zod/objectql.zod.ts and its TypeScript twin, the ObjectKanbanSchema interface in objectql.ts. Both declare it OPTIONAL, at the same requiredness the other face uses, so the two faces accept and refuse the same documents. (Located and cited by SYMBOL: line addresses in zod/objectql.zod.ts have drifted before, and this change is itself about a drifted mirror.)

.changeset/9628-kanban-column-collapsed-honoured.md

  • names objectql.ts → packages/types/src/objectql.ts — edited by this change

    The key was declared on both published faces of the object-kanban arm — the lane element of ObjectKanbanSchema (objectql.ts and its Zod mirror) and the runtime lane KanbanColumn (complex.ts and its mirror) — and read by KanbanEnhanced alone, a module no production source imports. An authored { "id": "todo", "title": "To Do", "collapsed": true } therefore parsed green on both faces and reached a board that did nothing with it: KanbanImpl's only collapse is the SWIMLANE row's, held in viewer state under objectui:kanban-collapsed:ANGLE-BRACKETS(swimlaneField) and never keyed to a lane's declared value. That is the ADR-0049 declared-but-unhonoured shape.

  • names complex.ts → packages/types/src/complex.ts — edited by this change

    The key was declared on both published faces of the object-kanban arm — the lane element of ObjectKanbanSchema (objectql.ts and its Zod mirror) and the runtime lane KanbanColumn (complex.ts and its mirror) — and read by KanbanEnhanced alone, a module no production source imports. An authored { "id": "todo", "title": "To Do", "collapsed": true } therefore parsed green on both faces and reached a board that did nothing with it: KanbanImpl's only collapse is the SWIMLANE row's, held in viewer state under objectui:kanban-collapsed:ANGLE-BRACKETS(swimlaneField) and never keyed to a lane's declared value. That is the ADR-0049 declared-but-unhonoured shape.

.changeset/9659-node-recursion-point-inert-clause.md

.changeset/9722-bulk-executor-datasource-face.md

  • names ObjectGrid.tsx → packages/plugin-grid/src/ObjectGrid.tsx — edited by this change

    • ObjectGrid.tsx → RecordDetailPanel: removing it type-checks GREEN. It was paying for nothing — both sides already declare the same DataSource | undefined from @object-ui/types. Removed outright. - ObjectGrid.tsx → BulkActionDialog: removing it reddens, and it was paying for TWO things at once — the optional-vs-required arm (the grid declares dataSource?: DataSource, the dialog demands one) AND the bulk-door contravariance. Only the first still needs erasing, so it is now a non-null assertion: today's runtime behaviour is preserved exactly, and any future drift of the face reddens at that site instead of passing silently.

.changeset/9853-grid-non-positive-page-size.md

  • names ObjectGrid.tsx → packages/plugin-grid/src/ObjectGrid.tsx — edited by this change

    Refuse a non-positive pageSize at all three of ObjectGrid.tsx's read points, instead of giving two different answers for one authored value (objectui#9853).

.changeset/action-callback-retired-7068.md

  • names crud.ts → packages/types/src/crud.ts — edited by this change

    What was measured, on this branch's base (900f8d99). ActionCallback ({ type: 'toast' | 'message' | 'redirect' | 'reload' | 'custom' | 'ajax' | 'dialog', message?, url?, api?, method?, dialog?, handler? }) was declared in crud.ts, mirrored in zod/crud.zod.ts, re-exported by both barrels, and carried on the legacy ActionSchema as onSuccess? / onFailure?. Producers: the package's own phase2-schemas.test.ts fixture and three ts fences in content/docs/core/enhanced-actions.mdx — nothing else (git grep -l ActionCallback over packages content skills hit the five packages/types files; positive control SchemaNodeSchema hit 22). Runtime readers: none — ActionRunner imports UIActionSchema, never this interface, and its own ActionDef.onFailure is a different (runner-native) meaning. It was the THIRD meaning of one key: objectui#5934 had already retired the runner's callback meaning of onSuccess and converged it on the spec's block.

  • names zod/crud.zod.ts → packages/types/src/zod/crud.zod.ts — edited by this change

    What was measured, on this branch's base (900f8d99). ActionCallback ({ type: 'toast' | 'message' | 'redirect' | 'reload' | 'custom' | 'ajax' | 'dialog', message?, url?, api?, method?, dialog?, handler? }) was declared in crud.ts, mirrored in zod/crud.zod.ts, re-exported by both barrels, and carried on the legacy ActionSchema as onSuccess? / onFailure?. Producers: the package's own phase2-schemas.test.ts fixture and three ts fences in content/docs/core/enhanced-actions.mdx — nothing else (git grep -l ActionCallback over packages content skills hit the five packages/types files; positive control SchemaNodeSchema hit 22). Runtime readers: none — ActionRunner imports UIActionSchema, never this interface, and its own ActionDef.onFailure is a different (runner-native) meaning. It was the THIRD meaning of one key: objectui#5934 had already retired the runner's callback meaning of onSuccess and converged it on the spec's block.

.changeset/calendar-readme-schema-keys-5045.md

  • names packages/types/src/complex.ts → packages/types/src/complex.ts — edited by this change

    README.md's "Schema API / CalendarView" block described a CalendarViewSchema that does not exist. Measured against the interface itself (packages/types/src/complex.ts) and its zod mirror: events — the schema's only required key besides type — was published as events?, so a reader following the README omits it and TypeScript rejects the node; defaultDate was string where the schema says string | Date; and onDateClick was listed as a schema key when it is a CalendarViewProps component prop, sending readers to a different package's surface for a key calendar-view does not have (the schema's key is onDateChange). The block also listed 6 of the schema's 13 keys with nothing saying it was a summary (objectui#5045).

.changeset/component-meta-converge-and-deprecate-alias-5893.md

  • names zod/base.zod.ts → packages/types/src/zod/base.zod.ts — edited by this change

    Either side had already moved. base.ts declared eleven keys; the plugin-scoped copy declared nine — the same nine, minus tags and description. So a plugin author typing against the plugin-facing declaration could not write two keys the main surface advertises, and which the runtime validator already accepted: ComponentMetaSchema in zod/base.zod.ts declares all eleven, so two of the three authorities agreed and the plugin-facing one did not. resizeConstraints' six members were identical in both, so the delta was exactly those two keys.

.changeset/dashboard-stable-empty-rows-4629.md

  • names data-table.tsx → packages/components/src/renderers/complex/data-table.tsx — edited by this change

    Nothing rendered wrong before or after; this is wasted work in the empty window, plus the live react-hooks/exhaustive-deps warning the conditional raised. It is the same module-scope frozen empty data-table.tsx adopted for its own EMPTY_ROWS (objectui#4618), applied to the provider: 'object' siblings.

.changeset/grid-dom-attribute-whitelist-4787.md

  • names grid.tsx → packages/components/src/renderers/layout/grid.tsx — edited by this change

    grid.tsx ended in a bare {...gridProps} spread that removed only data-obj-* and style, so everything else SchemaRenderer hands a registered component reached the element. Measured on a canary node, eight attributes leaked: columns="4", gap="4", mdcolumns="2", smcolumns="2", name="grid_node", props="[object Object]", colorvariant="x" (the flattened props container) and an unknown authored zzcanary="leak". A responsive columns object rendered as columns="[object Object]". Layout was unaffected, so every catalog grid example rendered with them — the reason this went unnoticed.

.changeset/issue-5373-retire-crud-schema.md

  • names packages/types/src/crud.ts → packages/types/src/crud.ts — edited by this change

    crud had four declaration faces and no registered renderer, for the whole life of the key: the TS interface (packages/types/src/crud.ts), the zod mirror (packages/types/src/zod/crud.zod.ts), a dedicated branch in validateSchema that affirmatively PASSED it, and CRUDBuilder in @object-ui/core. A node spelling it painted the OBJUI-001 "Unknown component type" panel, and content/docs/api/schema-reference.md published it as reference material — so a reader (or an AI author) who copied the page got a red panel.

  • names packages/types/src/zod/crud.zod.ts → packages/types/src/zod/crud.zod.ts — edited by this change

    crud had four declaration faces and no registered renderer, for the whole life of the key: the TS interface (packages/types/src/crud.ts), the zod mirror (packages/types/src/zod/crud.zod.ts), a dedicated branch in validateSchema that affirmatively PASSED it, and CRUDBuilder in @object-ui/core. A node spelling it painted the OBJUI-001 "Unknown component type" panel, and content/docs/api/schema-reference.md published it as reference material — so a reader (or an AI author) who copied the page got a red panel.

.changeset/issue-9819-operations-ceiling.md

  • names packages/plugin-grid/src/rowCrudAffordances.ts → packages/plugin-grid/src/rowCrudAffordances.ts — edited by this change

    Maintainer ruling of 2026-09-18, ruling batch Complete component documentation coverage for all 76 platform components #162 item 1, letter A, on objectui#9819. rowActions' other ruled power — narrowing INSIDE the ceiling, so naming only edit would withhold an allowed Delete — is NOT part of this change; the section headed "operations is the ceiling" in packages/plugin-grid/src/rowCrudAffordances.ts records what blocks it.

.changeset/layout-default-jsdoc-7361.md

  • names layout.ts → packages/types/src/layout.ts — edited by this change

    The published @default documentation on two layout.ts members now matches the value the renderer actually applies. ContainerSchema.maxWidth documented 'lg' while container.tsx applies schema.maxWidth ?? 'xl', and the shared FlexLayoutProps.align documented 'center' while flex.tsx applies schema.align || 'start' and stack.tsx applies schema.align || 'stretch'. The renderers are unchanged — they are the authority for what runs — so only the docblocks moved; align now states both consumers in prose instead of carrying a single @default, because one member shared by two deliberately divergent component types cannot have one correct default.

.changeset/list-user-actions-collision-5398.md

  • names ListView.tsx → packages/plugin-list/src/ListView.tsx — edited by this change

    The harvest now reads the object block only. Both userActions read sites in ListView.tsx carry a comment naming the collision, and __tests__/ListView.userActionsCollision.test.tsx pins each clause of it: the two shapes, a producer that manufactures the view one, the harvest's blindness to it, and the projection that must keep the object's operand with a toolbar block — or an empty block — present on the view.

.changeset/listview-comment-pair-4559.md

  • names ListView.tsx → packages/plugin-list/src/ListView.tsx — edited by this change

    Two comment corrections in ListView.tsx (objectui#4559, objectui#4966). No runtime behaviour changes and the emitted bundle is byte-identical; the published .d.ts does change, which is why this is a patch rather than an empty frontmatter.

.changeset/lookup-dropdown-cell-renderer-5492.md

  • names widgets/lookupColumnDisplay.tsx → packages/fields/src/widgets/lookupColumnDisplay.tsx — edited by this change

    Both surfaces now call one shared module — widgets/lookupColumnDisplay.tsx, which owns column normalisation, the field-descriptor enrichment from the referenced object's schema, and the render itself. The picker's own renderCellContent and columnFieldDescriptors are now thin calls into it, so there is a single renderer left to drift from. The dropdown's extra columns are rendered into the option row itself; the row's title keeps the full option label, which is what a truncated label needs, instead of a raw-value dump.

.changeset/param-dialog-title-fallback-4282.md

  • names crud.ts → packages/types/src/crud.ts — edited by this change

    title is declared on no action surface in the ecosystem: it is absent from @objectstack/spec's ActionSchema (44 keys walked at spec 17.0.0), from @object-ui/core's ActionDef and its pinned ACTION_DEF_KEYS / SPEC_ACTION_KEYS inventories, and from @object-ui/types' renderer view (ui-action.ts) and crud.ts ActionSchema / BaseSchema. None of the four action renderers — action:button, action:icon, action:group, action:menu — forwards it either. So the right-hand side of that || could not be reached by authored metadata: a fallback that cannot fire, which is the "declared is not enforced" shape objectstack#4075 exists to reduce. Nothing a user hits changes; the line now reads exactly one key, matching the description line directly below it.

.changeset/plugin-detail-8937-parent-scope-residue.md

  • names RelatedList.tsx → packages/plugin-detail/src/RelatedList.tsx — edited by this change

    • packages/plugin-detail/README.md (it is in files[], so it ships). It said the node's filter is AND-combined with { [relationshipField]: parentId }, full stop. Since objectui#7299 the parent condition is compiled to match the relationship field's arity, so a multi-valued relationship gets { [relationshipField]: { $contains: parentId } } instead. The paragraph now states both spellings and names the arbiter (@objectstack/spec/data's isMultiValueField). - The claim that the SQL driver decides arity on that same predicate. It does not: driver-sql gates the equality family on its own storage question, which reads multiple as truthy on ANY type. The two rules therefore disagree for a type outside MULTI_CAPABLE_TYPES carrying multiple: true. objectui#9184 moved the arity compiler into @object-ui/core's parent-scope seam and carried the claim with it, so the correction is recorded there — the seam now states the driver's measured rule, records the divergence as a divergence, and points at the upstream card that owns which of the two rules is right (objectstack#17469). RelatedList.tsx's pointer comment and the objectui#7299 test header carried the same sentence and are corrected to match.

.changeset/record-detail-param-dialog-title-5610.md

  • names crud.ts → packages/types/src/crud.ts — edited by this change

    title is declared on no action surface in the ecosystem: it is absent from @objectstack/spec's ActionSchema (44 keys walked at spec 17.0.0), from @object-ui/core's ActionDef and its pinned ACTION_DEF_KEYS / SPEC_ACTION_KEYS inventories, and from @object-ui/types' renderer view (ui-action.ts) and crud.ts ActionSchema / BaseSchema. None of the four action renderers — action:button, action:icon, action:group, action:menu — forwards it either. So the right-hand side of that || could not be reached by authored metadata: a fallback that cannot fire, which is the "declared is not enforced" shape objectstack#4075 exists to reduce. Nothing a user hits changes; the line now reads exactly one key, matching the description line directly below it.

.changeset/row-predicate-record-canon-5330.md

  • names evaluator/rowPredicateCanon.ts → packages/core/src/evaluator/rowPredicateCanon.ts — edited by this change

    • @object-ui/core exports detectNonCanonicalRowSpelling, warnNonCanonicalRowSpelling, resetRowPredicateCanonWarnings and ROW_PREDICATE_CANONICAL_ROOT from a new evaluator/rowPredicateCanon.ts, which carries the canon statement and the measurement. - Both evaluation tiers report once, in dev: evalRowPredicate (core) and useCondition (react, for bags bound by usePredicateRecordContext). - Detection reuses the server's own oracles (collectCelRootIdentifiers, firstUndeclaredReference) rather than a regex, so no second dialect judgement is invented client-side.

.changeset/table-renderer-declared-column-contract-5350.md

  • names packages/types/src/data-display.ts → packages/types/src/data-display.ts — edited by this change

    renderers/complex/table.tsx resolved a heading as col.header || col.label and a cell as row[col.accessorKey || col.name]. Neither label nor name is declared on TableColumn, which declares header and accessorKey — both required (packages/types/src/data-display.ts). This was the fourth site of the column-alias family, after data-table, ObjectDataTable and ObjectGrid (objectui#5350).

.changeset/theme-clientvalidation-dead-entry-5715.md

  • names clientValidation.ts → packages/app-shell/src/views/metadata-admin/clientValidation.ts — edited by this change

    Removed the dead theme: entry from clientValidation.ts's LOADERS table, which read ThemeSchema off @objectstack/spec/ui — a symbol the spec retired upstream (objectstack#10485 / PR objectstack#10695, which deleted the whole ui/theme.zod.ts module). theme was never a registered metadata type, so metadata-admin never asked for it (objectui#5715).

Read the paragraph, not the line: both false halves of the objectui#8617 claim sat in one paragraph, and correcting either alone would have left it asserting the same wrong thing.

If a claim did go false, correct the body. That is precedented and prose-only, frontmatter untouched; check-changeset-overwrite.mjs will report the correction as its own case 2 ("correcting a declaration on purpose … legitimate"), which is the intended shape — one gate asks for the read, the other records the write.

Not covered, stated so nobody reads this as more: a born-false claim that spells no line address at all (objectui#9495 coordinated one by ORDINAL — "a grep finds that member first" — and deciding that means reading what the sentence means), a claim spelled as a symbol or a package rather than a backticked file name, and a file named ambiguously.

Angle-bracketed names in the quoted prose above are rewritten as ANGLE-BRACKETS(name): GitHub deletes tag-shaped fragments from a stored body, and a quote that silently loses the identifier it is about is worse than a visible repair.

Compared the checked-out tree with 35d68c4ce (merge-base with origin/main): 49 file(s) changed outside .changeset/, read against 1615 pending declaration(s) that publish a body (2197 pending in total). · run

@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 329 chunks) 3095.4 KB 3104.5 KB
Main entry chunk (gzip) 148.4 KB 350 KB
Entry file index-BDtbBmOu.js —
Status PASS —

The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it.


📦 Bundle Size Report

Package Size Gzipped
app-shell (consoleActionDispatch.js) 0.20KB 0.19KB
app-shell (index.js) 16.58KB 6.17KB
app-shell (runtime-config.js) 20.68KB 7.36KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 10.06KB 3.86KB
auth (ActiveOrganizationStorage.js) 27.95KB 10.04KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 2.07KB 1.00KB
auth (AuthProvider.js) 40.17KB 10.58KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 18.15KB 5.39KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.65KB 2.22KB
auth (SocialSignInButtons.js) 9.61KB 3.89KB
auth (UserMenu.js) 3.39KB 1.21KB
auth (auth-gate-events.js) 1.29KB 0.66KB
auth (authStyles.js) 5.04KB 1.72KB
auth (createAuthClient.js) 40.21KB 10.80KB
auth (createAuthenticatedFetch.js) 8.52KB 3.45KB
auth (index.js) 3.63KB 1.64KB
auth (invitation-status.js) 1.22KB 0.70KB
auth (org-roles.js) 6.66KB 2.78KB
auth (phone-identifier.js) 1.11KB 0.66KB
auth (types.js) 0.59KB 0.35KB
auth (useAuth.js) 5.30KB 1.02KB
auth (useWorkspaceAdminStatus.js) 11.08KB 4.58KB
collaboration (CommentThread.js) 27.13KB 7.95KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 6.49KB 2.64KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (index.js) 1.68KB 0.73KB
collaboration (useCollaborationTranslation.js) 6.05KB 2.52KB
collaboration (useCommentSearch.js) 1.98KB 0.88KB
collaboration (useConflictResolution.js) 7.75KB 1.86KB
collaboration (useMentionNotifications.js) 1.81KB 0.68KB
collaboration (usePresence.js) 6.33KB 1.84KB
collaboration (useRealtimeSubscription.js) 7.91KB 2.01KB
components (index.js) 557.61KB 133.61KB
core (index.js) 9.93KB 3.94KB
create-plugin (index.js) 27.94KB 9.51KB
data-objectstack (index.js) 226.44KB 63.00KB
fields (index.js) 261.01KB 66.28KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
i18n (builtinAggregateLabels.js) 0.86KB 0.49KB
i18n (currency.js) 2.59KB 1.22KB
i18n (fallbackInterpolation.js) 6.25KB 2.77KB
i18n (i18n.js) 8.87KB 3.64KB
i18n (index.js) 5.24KB 2.27KB
i18n (pickLocalized.js) 9.86KB 3.95KB
i18n (provider.js) 39.40KB 12.91KB
i18n (translateFn.js) 0.20KB 0.18KB
i18n (useDisplayLocale.js) 3.52KB 1.76KB
i18n (useObjectLabel.js) 34.34KB 9.17KB
i18n (useSafeTranslation.js) 5.60KB 2.33KB
layout (index.js) 39.28KB 11.09KB
mobile (MobileProvider.js) 0.92KB 0.49KB
mobile (ResponsiveContainer.js) 0.94KB 0.38KB
mobile (breakpoints.js) 1.51KB 0.70KB
mobile (createOfflineDataSource.js) 5.61KB 1.75KB
mobile (index.js) 1.99KB 0.87KB
mobile (offlineQueue.js) 3.91KB 1.35KB
mobile (pwa.js) 0.97KB 0.49KB
mobile (serviceWorker.js) 1.48KB 0.62KB
mobile (serviceWorkerSource.js) 3.41KB 1.48KB
mobile (useBreakpoint.js) 1.54KB 0.65KB
mobile (useGesture.js) 6.96KB 1.98KB
mobile (useOfflineSync.js) 1.99KB 0.72KB
mobile (usePullToRefresh.js) 6.62KB 2.45KB
mobile (useResponsive.js) 0.72KB 0.42KB
mobile (useSpecGesture.js) 5.52KB 2.10KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 13.52KB 4.88KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 6.24KB 2.16KB
permissions (discardProofCache.js) 1.04KB 0.55KB
permissions (evaluator.js) 8.33KB 3.07KB
permissions (index.js) 0.93KB 0.41KB
permissions (store.js) 0.91KB 0.42KB
permissions (useFieldPermissions.js) 1.28KB 0.53KB
permissions (usePermissions.js) 4.83KB 2.27KB
plugin-ai (index.js) 16.01KB 3.93KB
plugin-calendar (index.js) 51.73KB 14.72KB
plugin-charts (index.js) 83.99KB 22.86KB
plugin-chatbot (index.js) 197.67KB 46.90KB
plugin-dashboard (index.js) 136.82KB 36.44KB
plugin-designer (index.js) 216.42KB 44.47KB
plugin-detail (index.js) 233.48KB 61.79KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 161.21KB 41.41KB
plugin-gantt (index.js) 169.83KB 41.99KB
plugin-grid (index.js) 228.11KB 62.72KB
plugin-kanban (index.js) 48.43KB 15.11KB
plugin-list (index.js) 115.01KB 28.49KB
plugin-map (index.js) 22.90KB 7.62KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 44.17KB 12.20KB
plugin-timeline (index.js) 31.00KB 9.09KB
plugin-tree (index.js) 11.21KB 3.89KB
plugin-view (index.js) 87.90KB 22.06KB
providers (DataSourceProvider.js) 0.75KB 0.39KB
providers (MetadataProvider.js) 1.37KB 0.59KB
providers (ThemeProvider.js) 1.90KB 0.85KB
providers (UploadProvider.js) 11.81KB 3.58KB
providers (index.js) 0.45KB 0.23KB
providers (types.js) 0.01KB 0.04KB
react-runtime (index.js) 5.62KB 2.34KB
react (LazyPluginLoader.js) 4.47KB 1.63KB
react (SchemaRenderer.js) 119.16KB 39.05KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.03KB 1.86KB
react (schema-input.js) 4.25KB 2.04KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (body-dialect.js) 4.78KB 2.09KB
sdui-parser (codegen.js) 7.50KB 3.05KB
sdui-parser (dashboard-widget-options.js) 3.08KB 1.30KB
sdui-parser (index.js) 6.16KB 2.71KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (kanban-quick-add.js) 3.89KB 1.87KB
sdui-parser (parse.js) 25.28KB 7.80KB
sdui-parser (provenance.js) 3.84KB 1.90KB
sdui-parser (types.js) 0.28KB 0.23KB
sdui-parser (validate.js) 18.27KB 6.22KB
types (ai.js) 4.11KB 2.06KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 3.52KB 1.36KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (complex.js) 2.93KB 1.49KB
types (crud.js) 0.20KB 0.18KB
types (dashboard-filter-alias.js) 6.23KB 2.74KB
types (data-display.js) 3.75KB 1.85KB
types (data-protocol.js) 0.20KB 0.19KB
types (data.js) 0.20KB 0.18KB
types (designer.js) 1.85KB 0.85KB
types (disclosure.js) 0.20KB 0.18KB
types (error-code.js) 1.54KB 0.88KB
types (expression.js) 0.20KB 0.18KB
types (feedback.js) 0.20KB 0.18KB
types (field-types.js) 0.20KB 0.18KB
types (form.js) 0.20KB 0.18KB
types (http-inflight.js) 8.87KB 3.73KB
types (http-retry.js) 4.32KB 2.02KB
types (icon-key-migration.js) 4.26KB 1.63KB
types (index.js) 4.74KB 2.26KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 5.00KB 2.39KB
types (navigation.js) 0.20KB 0.18KB
types (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 2.52KB 1.31KB
types (plugin-scope.js) 0.20KB 0.18KB
types (record-components.js) 0.20KB 0.19KB
types (record-semantics.js) 1.28KB 0.67KB
types (registry.js) 0.20KB 0.18KB
types (reports.js) 0.20KB 0.18KB
types (select-option.js) 0.20KB 0.19KB
types (spec-report.js) 5.05KB 1.93KB
types (spec-ui-namespace.js) 0.20KB 0.19KB
types (strict-authoring-face.js) 17.15KB 6.32KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 6.27KB 2.87KB
types (ui-action.js) 8.11KB 3.32KB
types (views.js) 0.20KB 0.18KB
types (widget.js) 0.20KB 0.18KB

Size Limits

  • ✅ Core packages should be < 50KB gzipped
  • ✅ Component packages should be < 100KB gzipped
  • ⚠️ Plugin packages should be < 150KB gzipped

…s dead card (objectui#10803, batch 5)

The `actions` refusal on the `page` node is an ADR-0049 tombstone, measured
from the retirement itself: its arm is `retirementTombstone(PAGE_ACTIONS_REFUSAL)`,
its landing `12b599219` calls it an ADR-0049 `retirementTombstone` arm, and
`7926-page-node-refuses-actions.md` calls it an ADR-0049 refusal arm. Its
string has no `RETIRED` opener, so its own parenthetical takes the reference:
"never was (ADR-0049): no renderer reads it", the spelling its `breadcrumbs`
sibling already uses. The runtime-strings changeset says so, and the sweep
changeset notes that `@object-ui/types`' runtime text is declared separately.
Frontmatter of both changesets is byte-identical.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014mXUNuFomfj24w7s1pZzhN
@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 329 chunks) 3095.5 KB 3104.5 KB
Main entry chunk (gzip) 148.5 KB 350 KB
Entry file index-C9mJOteQ.js —
Status PASS —

The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it.


📦 Bundle Size Report

Package Size Gzipped
app-shell (consoleActionDispatch.js) 0.20KB 0.19KB
app-shell (index.js) 16.58KB 6.17KB
app-shell (runtime-config.js) 20.68KB 7.36KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 10.06KB 3.86KB
auth (ActiveOrganizationStorage.js) 27.95KB 10.04KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 2.07KB 1.00KB
auth (AuthProvider.js) 40.17KB 10.58KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 18.15KB 5.39KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.65KB 2.22KB
auth (SocialSignInButtons.js) 9.61KB 3.89KB
auth (UserMenu.js) 3.39KB 1.21KB
auth (auth-gate-events.js) 1.29KB 0.66KB
auth (authStyles.js) 5.04KB 1.72KB
auth (createAuthClient.js) 40.21KB 10.80KB
auth (createAuthenticatedFetch.js) 8.52KB 3.45KB
auth (index.js) 3.63KB 1.64KB
auth (invitation-status.js) 1.22KB 0.70KB
auth (org-roles.js) 6.66KB 2.78KB
auth (phone-identifier.js) 1.11KB 0.66KB
auth (types.js) 0.59KB 0.35KB
auth (useAuth.js) 5.30KB 1.02KB
auth (useWorkspaceAdminStatus.js) 11.08KB 4.58KB
collaboration (CommentThread.js) 27.13KB 7.95KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 6.49KB 2.64KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (index.js) 1.68KB 0.73KB
collaboration (useCollaborationTranslation.js) 6.05KB 2.52KB
collaboration (useCommentSearch.js) 1.98KB 0.88KB
collaboration (useConflictResolution.js) 7.75KB 1.86KB
collaboration (useMentionNotifications.js) 1.81KB 0.68KB
collaboration (usePresence.js) 6.33KB 1.84KB
collaboration (useRealtimeSubscription.js) 7.91KB 2.01KB
components (index.js) 557.59KB 133.60KB
core (index.js) 9.93KB 3.94KB
create-plugin (index.js) 27.94KB 9.51KB
data-objectstack (index.js) 226.44KB 63.00KB
fields (index.js) 261.01KB 66.28KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
i18n (builtinAggregateLabels.js) 0.86KB 0.49KB
i18n (currency.js) 2.59KB 1.22KB
i18n (fallbackInterpolation.js) 6.25KB 2.77KB
i18n (i18n.js) 8.87KB 3.64KB
i18n (index.js) 5.24KB 2.27KB
i18n (pickLocalized.js) 9.86KB 3.95KB
i18n (provider.js) 39.40KB 12.91KB
i18n (translateFn.js) 0.20KB 0.18KB
i18n (useDisplayLocale.js) 3.52KB 1.76KB
i18n (useObjectLabel.js) 34.34KB 9.17KB
i18n (useSafeTranslation.js) 5.60KB 2.33KB
layout (index.js) 39.28KB 11.09KB
mobile (MobileProvider.js) 0.92KB 0.49KB
mobile (ResponsiveContainer.js) 0.94KB 0.38KB
mobile (breakpoints.js) 1.51KB 0.70KB
mobile (createOfflineDataSource.js) 5.61KB 1.75KB
mobile (index.js) 1.99KB 0.87KB
mobile (offlineQueue.js) 3.91KB 1.35KB
mobile (pwa.js) 0.97KB 0.49KB
mobile (serviceWorker.js) 1.48KB 0.62KB
mobile (serviceWorkerSource.js) 3.41KB 1.48KB
mobile (useBreakpoint.js) 1.54KB 0.65KB
mobile (useGesture.js) 6.96KB 1.98KB
mobile (useOfflineSync.js) 1.99KB 0.72KB
mobile (usePullToRefresh.js) 6.62KB 2.45KB
mobile (useResponsive.js) 0.72KB 0.42KB
mobile (useSpecGesture.js) 5.52KB 2.10KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 13.52KB 4.88KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 6.24KB 2.16KB
permissions (discardProofCache.js) 1.04KB 0.55KB
permissions (evaluator.js) 8.33KB 3.07KB
permissions (index.js) 0.93KB 0.41KB
permissions (store.js) 0.91KB 0.42KB
permissions (useFieldPermissions.js) 1.28KB 0.53KB
permissions (usePermissions.js) 4.83KB 2.27KB
plugin-ai (index.js) 16.01KB 3.93KB
plugin-calendar (index.js) 51.96KB 14.83KB
plugin-charts (index.js) 83.99KB 22.86KB
plugin-chatbot (index.js) 197.67KB 46.90KB
plugin-dashboard (index.js) 136.82KB 36.44KB
plugin-designer (index.js) 216.42KB 44.47KB
plugin-detail (index.js) 233.48KB 61.79KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 161.21KB 41.41KB
plugin-gantt (index.js) 170.35KB 42.19KB
plugin-grid (index.js) 228.11KB 62.72KB
plugin-kanban (index.js) 48.43KB 15.11KB
plugin-list (index.js) 115.01KB 28.49KB
plugin-map (index.js) 22.90KB 7.62KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 44.17KB 12.20KB
plugin-timeline (index.js) 31.00KB 9.09KB
plugin-tree (index.js) 11.21KB 3.89KB
plugin-view (index.js) 88.42KB 22.18KB
providers (DataSourceProvider.js) 0.75KB 0.39KB
providers (MetadataProvider.js) 1.37KB 0.59KB
providers (ThemeProvider.js) 1.90KB 0.85KB
providers (UploadProvider.js) 11.81KB 3.58KB
providers (index.js) 0.45KB 0.23KB
providers (types.js) 0.01KB 0.04KB
react-runtime (index.js) 5.62KB 2.34KB
react (LazyPluginLoader.js) 4.47KB 1.63KB
react (SchemaRenderer.js) 119.16KB 39.05KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.03KB 1.86KB
react (schema-input.js) 4.25KB 2.04KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (body-dialect.js) 4.78KB 2.09KB
sdui-parser (codegen.js) 7.50KB 3.05KB
sdui-parser (dashboard-widget-options.js) 3.08KB 1.30KB
sdui-parser (index.js) 6.16KB 2.71KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (kanban-quick-add.js) 3.89KB 1.87KB
sdui-parser (parse.js) 25.28KB 7.80KB
sdui-parser (provenance.js) 3.84KB 1.90KB
sdui-parser (types.js) 0.28KB 0.23KB
sdui-parser (validate.js) 18.27KB 6.22KB
types (ai.js) 4.11KB 2.06KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 3.52KB 1.36KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (complex.js) 2.93KB 1.49KB
types (crud.js) 0.20KB 0.18KB
types (dashboard-filter-alias.js) 6.23KB 2.74KB
types (data-display.js) 3.75KB 1.85KB
types (data-protocol.js) 0.20KB 0.19KB
types (data.js) 0.20KB 0.18KB
types (designer.js) 1.85KB 0.85KB
types (disclosure.js) 0.20KB 0.18KB
types (error-code.js) 1.54KB 0.88KB
types (expression.js) 0.20KB 0.18KB
types (feedback.js) 0.20KB 0.18KB
types (field-types.js) 0.20KB 0.18KB
types (form.js) 0.20KB 0.18KB
types (http-inflight.js) 8.87KB 3.73KB
types (http-retry.js) 4.32KB 2.02KB
types (icon-key-migration.js) 4.26KB 1.63KB
types (index.js) 4.74KB 2.26KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 5.00KB 2.39KB
types (navigation.js) 0.20KB 0.18KB
types (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 2.52KB 1.31KB
types (plugin-scope.js) 0.20KB 0.18KB
types (record-components.js) 0.20KB 0.19KB
types (record-semantics.js) 1.28KB 0.67KB
types (registry.js) 0.20KB 0.18KB
types (reports.js) 0.20KB 0.18KB
types (select-option.js) 0.20KB 0.19KB
types (spec-report.js) 5.05KB 1.93KB
types (spec-ui-namespace.js) 0.20KB 0.19KB
types (strict-authoring-face.js) 17.15KB 6.32KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 6.27KB 2.87KB
types (ui-action.js) 8.11KB 3.32KB
types (views.js) 0.20KB 0.18KB
types (widget.js) 0.20KB 0.18KB

Size Limits

  • ✅ Core packages should be < 50KB gzipped
  • ✅ Component packages should be < 100KB gzipped
  • ⚠️ Plugin packages should be < 150KB gzipped

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: afed8aa6b48cc2111c2c1f9adb539d5fb779753a

① Derived judgments

② Semver level

patch for @object-ui/types: only message and description text moves. Clause-②: no stands; the sweep changeset is empty. ⛔ Not major.

③ Boundary flags

  • CI on head: 40 success, 3 skipped, 0 failure; final.
  • git merge-tree against main 4f38f3928: clean.
  • Open PRs:
    • trial merges with objectui#10890, objectui#10888, objectui#10886 and objectui#10891 are clean;
    • objectui#10278's conflicts are the same region as against main alone, outside this diff's lines.
  • check-governed-merges --pr was refused with HTTP 403 on page 2 of the file list (as in batch 3). The same predicate via --test over the 106 paths: NOT GOVERNED, with a lit control.
  • Draft, assigned to os-elon-musk.
  • The commit trailers carry no model identifier.

Implemented-by: claude/issue-10803-dead-citations-fifth-batch
Reviewed-by: session_014mXUNuFomfj24w7s1pZzhN

VERDICT: FAIL

The actions refusal takes (ADR-0049) (the seat rules option (a)), with the runtime changeset and the PR body's Special cases 7 following. The optional package-list nit rides the same commit.

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 8255f14f475331b51951f23e46a3641aab316f7b

This is an in-seat delta review of fix round 1 (afed8aa6b to 8255f14f4, one text-only commit), against record 5863489805 (FAIL, one item).

① Derived judgments

  • The actions refusal: fixed, as the seat ruled (option a). PAGE_ACTIONS_REFUSAL in layout.zod.ts now reads "never was (ADR-0049): no renderer reads it", the spelling its breadcrumbs sibling already uses. It is measured from the retirement itself:
    • the retirementTombstone arm;
    • the landing 12b599219;
    • 7926-page-node-refuses-actions.md.
  • .changeset/10803-fifth-batch-runtime-strings.md carries the ruling's exact wording in both sentences: "the six tombstones keep ADR-0049 … the actions tombstone cites ADR-0049 in its place, and the one description simply drops its pointer", and the actions bullet. The frontmatter md5 is unchanged.
  • The optional package-list nit: taken. @object-ui/types is marked "(whose runtime text is declared separately below)", with frontmatter unchanged.
  • Nothing else moved: 3 files, 9 insertions and 6 deletions.
    • page-actions-refusal-7926 pins only remedy words ('actions', 'children', 'page:header'), and the dev read it rather than assuming. No test or doc quotes "never was: no renderer".
    • The seven related pin files pass (134 tests).
    • C4 still reads 44 identical plus 5 equal after 19 listed substitutions.
    • The census is 0 at head and 0 merged with current main.
  • The PR body r2 (applied with this landing) carries Special cases 7 in the seat's text, the table's "after" cell with (ADR-0049), and a re-read census and Held section. Line 1 is Part of #10803, and there is no closing keyword.

② Semver level

patch for @object-ui/types (message text only), and an empty sweep changeset. Clause-②: no. ⛔ Not major.

③ Boundary flags

  • CI: the landing waits for every check-run on this head to be final and green, and re-runs git merge-tree against current main first.
  • Open PRs: trial merges are clean with every one except objectui#10278, whose conflicts are the same region as against main alone. New objectui#10896 shares ObjectGrid.tsx and ListView.tsx and merges clean. No open PR holds layout.zod.ts.
  • NOT GOVERNED (--test over the 106 paths).
  • Draft, assigned to os-elon-musk.

Implemented-by: claude/issue-10803-dead-citations-fifth-batch
Reviewed-by: session_014mXUNuFomfj24w7s1pZzhN

VERDICT: PASS

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review September 28, 2026 04:45
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Sep 28, 2026
Merged via the queue into main with commit b8e0941 Sep 28, 2026
45 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/issue-10803-dead-citations-fifth-batch branch September 28, 2026 04:59
akarma-synetal pushed a commit to akarma-synetal/objectui that referenced this pull request Sep 28, 2026
…bject views, detail-view, email, password) and repair the shorthand Omit erasure (objectui#9256) (objectstack-ai#10897)

Part of objectstack-ai#9256
Clause-②: yes

**Clause-② `yes`, as the claim declared:** twelve published arms stop
accepting an authored `children`, and two published TypeScript faces
stop erasing the members they inherit. Both narrow an accept set; a
contract review is owed before landing.

The E3 residual that the maintainer's ruling on objectui#8284 (comment
`5861449497`, Q2 A) moved onto this card: keys with a published arm
whose renderer reads **neither** content channel. It also carries the
ruling's execution parameter 3, the `InputShorthandSchema` /
`UiCalendarSchema` TypeScript `Omit` erasure. objectui#9256 stays open
for the rest of family D.

## What changed

- **Narrowed (12 keys):** `object-grid`, `object-form`, `object-kanban`,
`object-map`, `object-tree`, `object-view`, `object-gantt`,
`object-calendar`, `object-chart`, `detail-view`, `email`, `password`.
- TypeScript face: `body?: never` and `children?: never`, each with a
docblock naming what the node renders instead.
- zod mirror: `body` and `children` are two `retirementTombstone`
members fed ONE string from the new `neitherContentChannelGuidance`
builder in `zod/tombstone.zod.ts`. Both stay MEMBERS, so
`zod-mirror-parity`'s key sets stay equal.
- `body` was already refused on these arms (by `BaseSchema`,
objectui#6771), except on the `email` / `password` TypeScript face,
which the `Omit` erased. It is restated because `BaseSchema`'s refusal
names `children` as the remedy, and `children` is dead here too.
- **`Omit` erasure repaired:** `InputShorthandSchema` and
`UiCalendarSchema` now inherit through `OmitDeclared` (`form.ts`, not
exported). It is a key-remapping mapped type: it drops exactly the named
keys and keeps every other named member and the index signature.
- `ui:calendar` gains no refusal of its own. Its face now re-exposes
what `CalendarSchema` declares, so the published TypeScript face refuses
`body`, `children` and a `mode` outside the declared enum, which the
erased face accepted. Its mirror (a `.extend()` of that one) already
refused them.
- I measured the `ui:calendar` renderer anyway
(`renderers/form/calendar.tsx`, typed `CalendarSchema`). It reads
`defaultValue`, `mode` and `value`, and no channel.
- **Held (3 keys): `br`, `hr`, `img`.** See "Held, and the question it
leaves" below.

## Per-key measurement, taken on `origin/main` `0c50f1863` before any
edit

**Instrument.** The TypeScript compiler API, ⛔ not grep. It builds one
program per workspace package from that package's own `tsconfig.json`:
40 programs over 1573 source files, on a BUILT tree (turbo build 42/42
first), with `@object-ui/types` resolving to `packages/types/dist`. It
files every `.body` / `.children` read (property access, string element
access, object destructuring) under the declared type of its receiver.

- 547 channel reads were filed.
- **Lit controls fire:** `ButtonSchema` 1, `DivSchema` 1, `CardSchema`
1, `ContainerSchema` 1 (each `children`).
- **Receiver-reachability control:** the same program sees every
narrowed declaration as a receiver of the keys its renderer reads. The
zeros below are readings, not blindness.

| key | registration(s) claiming it | registration hop → reader, and the
type it reads the node as | `body` / `children` reads under that type |
receiver reads (reachability) | arm, TS face: before → after | arm, zod
face: before → after | disposition |
|---|---|---|---|---|---|---|---|
| `object-grid` | `plugin-grid:object-grid` (+ console `registerLazy` of
the same plugin) | `ObjectGridRenderer` (`any`) → `ObjectGrid` ·
`ObjectGridSchema` | 0 / 0 | 158 reads, 38 keys | body refused
(BaseSchema), children accepted → both refused | same → both refused by
name | narrowed |
| `object-form` | `plugin-form:object-form` | `ObjectFormRenderer`
(`any`) → `ObjectForm` · `ObjectFormSchema` | 0 / 0 | 200 / 44 | same |
same | narrowed |
| `object-kanban` | `plugin-kanban:object-kanban` (+ lazy) |
`ObjectKanbanRenderer` (`any`) → `ObjectKanban` · `ObjectKanbanSchema` |
0 / 0 | 67 / 13 | same | same | narrowed |
| `object-map` | `plugin-map:object-map` (+ lazy) | `ObjectMapRenderer`
(`any`) → `ObjectMap` · `ObjectMapSchema` | 0 / 0 | 30 / 16 | same |
same | narrowed |
| `object-tree` | `plugin-tree:object-tree` (+ lazy) |
`ObjectTreeRenderer` (`any`) → `ObjectTree` · `ObjectTreeSchema` | 0 / 0
| 13 / 8 | same | same | narrowed |
| `object-view` | `plugin-view:object-view` (and the `view` alias) |
`ObjectViewRenderer` (`any`) → `ObjectView` · `ObjectViewSchema` | 0 / 0
| 112 / 19 | same | same | narrowed |
| `object-gantt` | `plugin-gantt:object-gantt` (+ lazy) |
`ObjectGanttRenderer` (`any`) → `ObjectGantt` · `ObjectGanttSchema` | 0
/ 0 | 61 / 48 | same | same | narrowed |
| `object-calendar` | `plugin-calendar:object-calendar` (+ lazy) |
`ObjectCalendarRenderer` (`any`) → `ObjectCalendar` ·
`ObjectCalendarSchema` | 0 / 0 | 40 / 12 | same | same | narrowed |
| `object-chart` | `plugin-charts:object-chart` (+ lazy) |
`ObjectChartBlock` (`any`) → `ObjectChart` · `ObjectChartSchema` | 0 / 0
| 123 / 15 | same | same | narrowed |
| `detail-view` | `plugin-detail:detail-view` | `DetailViewRenderer`
(`any`) → `DetailView` · `DetailViewSchema` | 0 / 0 | 195 / 31 | same |
same | narrowed |
| `email` | `ui:email` (`field:email` stands down) | `any` wrapper
spreads the node into `InputRenderer` · `InputSchema` | 0 / 0 | 23 / 17
| BOTH accepted (erased `Omit`) → both refused | body refused, children
accepted → both refused by name | narrowed |
| `password` | `ui:password` (`field:password` stands down) | same as
`email` | 0 / 0 | 23 / 17 | same as `email` | same as `email` | narrowed
|
| `br` | `ui:br` | html-elements factory (`any`), void tag: passes
`undefined` as the child | reads neither (the one `schema?.children`
read is behind the void-tag guard) | n/a (`any`) | body refused,
children accepted (family arm) → unchanged | same → unchanged | **held**
|
| `hr` | `ui:hr` | same | same | n/a | same | same | **held** |
| `img` | `ui:img` | same | same | n/a | same | same | **held** |

The residual count stays 15: no key reads `children` today. 12 are
narrowed and 3 are held.

**`any`-typed receivers, attributed rather than assumed.**

- Every hop above is `any`-typed. Each hop body was read: none contains
a channel read.
- The any-typed reads in the eleven hosting files and packages were
attributed one by one:
- React `children` destructured off internal components' own props
(`SchemaRenderer` passes no node child as a React child);
  - `document.body` and `err.body`;
  - `TreeNode.children` on the record hierarchy `ObjectTree` builds;
  - `FeedItem.body`;
  - `record:alert`'s own `props.body`, which is another registration.
- The html factory's `schema?.children` read sits behind `isVoid ?
undefined : …`.

**Delegation hosts, checked for pass-through.** Every `SchemaRenderer`
call in the ten object/detail packages was traced. The node it renders
is built one of three ways:

- key by key — `ObjectForm` / `ModalForm` / `DrawerForm` / `TabbedForm`
/ `SplitForm` / `WizardForm` all build their `form` node that way, and
the `form` renderer DOES draw `children`, which is why this was checked;
- from a sub-key — `DetailView`'s `header` / `footer` / tab `content`,
`ObjectChart`'s drill-down table;
- or from a generated `object-*` node — `ObjectView` assembles
`object-kanban`, `object-calendar`, `object-gallery`, `object-timeline`,
`object-gantt`, `object-map`, `object-tree` and `object-chart` from
named keys, and every one of those reads neither channel (for gallery
and timeline: `packages/plugin-list` and `packages/plugin-timeline` hold
no node-channel read).

No host spreads its own node into a node that reads `children`.

**Generic traversers** (`validateChildren` in core, `sdui-parser`
`validateTree`, the metadata-admin preview canvases, the vscode
validator) walk children to validate or preview. They render nothing and
are node-agnostic, as for every row family D already holds.

**objectui#9910 cross-check.** None of the 12 narrowed registrations
declares a `children` slot input: a grep over their registration files
finds 0 hits, and the lit control is `html-elements.tsx` / `div.tsx`,
which do.

**Producers.** `pnpm census:body-dialect --keys` over the 15, plus
`ui:calendar` and `input`, with `div` / `card` / `page` / `button` / `p`
/ `h1` as lit controls in the same pass: 8981 files, 2744 candidate
nodes.

- **0** nodes author `children` on any of the 15.
- 1 node authors `body` on `ui:calendar`: it was the family-D TRIPWIRE
test line (test bucket), moved by this change.
- The controls read `div` 170 / `card` 183 / `page` 47 `children`.
- Producers derived: none. Nothing was migrated.

## The `Omit` repair — measured on the BUILT d.ts

A probe program under `packages/components` resolved `@object-ui/types`
to `packages/types/dist/index.d.ts` (`--traceResolution`). It carried 15
`@ts-expect-error` pins (the 10 object/detail `children`, `email`
`children`, `password` `body`, `email` `label: 42`, and the
`ui:calendar` `children` and `mode: 'default'`), a lit control (`const
n: number = 'x'`), and 12 channel-free controls.

- **On this branch:** exit 0 — every directive used, every control
compiles, the lit control fires.
- **On the base dist:** exit 2 with 15 × TS2578, and the lit control is
still used.
- The emitted `dist/form.d.ts` declares `OmitDeclared` locally and both
heritage clauses use it.

## Red on base, then green — one-shot, the restore proven by state

The predictions were written to a file BEFORE the mutation. The mutation
was `git checkout 0c50f18 -- THE-SEVEN-DECLARATION-FILES`, with every
test file at HEAD. It was proven by 7/7 blob hashes equal to BASE plus
anchor counts (`neitherContentChannel` 0, `OmitDeclared` 0). The run sat
under `trap … EXIT INT TERM` with absolute paths.

| reader | mutated (BASE arms) | restored (HEAD `14fd13c51`) |
|---|---|---|
| vitest, the new pin file | **RED** exit 1 — 73 failed / 90 passed;
exactly the predicted 12 × 5 `children` families + 12 `body`-message
rows + 1 nested row | **GREEN** 163 / 163 |
| `tsc -p packages/types/tsconfig.test.json` | **RED** exit 2 — 18 ×
TS2578 and 3 × TS2322 (the `Eq` pins) in the new file, plus 3 in
`zod-mirror-parity` naming the two re-collapsed pairs and the stale
`KnownDrift` row; 0 elsewhere | **GREEN** exit 0 |
| built-d.ts probe (types rebuilt; dist markers 0 → 29 / 6) | **RED**
exit 2, 15 × TS2578 | **GREEN** exit 0 |

The restore was proven by 7/7 blob hashes equal to HEAD, `git diff HEAD`
empty and `git status` clean, both after the restore and at the end.

⚠️ **The `body` rows on the ten object/detail arms are GREEN on base, by
design:** `BaseSchema` already refused `body` there. Only their MESSAGE
changes, and the message rows are the ones that turn red. `?: never` is
erased before vitest runs, so the TypeScript half is read by `tsc`
alone. The vitest run cannot see it.

## Serial constraints

- **Mapped at branch time (`0c50f1863`).** PRs objectui#10714, objectstack-ai#10883
and objectstack-ai#10884 were open then; all three have since merged, and PR
objectui#10875 was the base.
- `layout.ts` (TabItem) and `layout.zod.ts` (TabItemSchema): untouched,
because `br` / `hr` / `img` are held and neither file is edited.
- `content-channel-family-d-9256.test.ts`: the only edits are forced
ones, clear of PR objectui#10714's hunks, which sit in the ListItem and
Tabs sections:
- The file's own `ui:calendar` TRIPWIRE said "when the collapse is
repaired this line goes RED … turn it back into a `@ts-expect-error`
pair". The repair fired it.
- The pair moved to the new file. That file lost the tripwire line, its
`uiCalendarBody` array entry (32 → 31) and the now-unused
`UiCalendarSchema` type import.
    - No pin was added there.
- `objectql.ts`: the insertion after `ObjectViewSchema`'s last member is
clear of PR objectui#10883's `NamedListView` docblock edit.
- `object-view-unmirrored-keys-7779.test.ts` (PR objectui#10884):
untouched.
- **Open PRs the branch-time map missed** (re-mapped by contract review
`5863631182`):
- PR objectui#10890 rewrote the same two `KnownDrift` header figures in
`zod-mirror-parity.test.ts` and landed first (`c30c8dd4c`). This branch
merged `main` at that commit (merge commit `31bb63bcb`, no rebase, no
force-push) and recounted the figures from the merged table; see "Merge
round" under Gates.
- PRs objectui#10888, objectstack-ai#10889 and objectstack-ai#10892 are textually disjoint, and all
three have since merged. `git merge-tree` of the merge head against
`main` at `6a7f24e92`, which carries all of them, reports no conflict.
- ⛔ `zod/index.zod.ts` and the `packages/cli` ratchet (objectui#10872)
are untouched.

## Collateral that the repair and narrowing made true or false — each
measured, none widened

- **`zod-mirror-parity.test.ts`:**
- The two `Omit` COLLAPSE rows (32 + 26 keys) leave
`MirroredUndeclared`. Its figures move from 4 / 60 to 2 / 2, and the
class note records the emptying.
- Restoring the named members NARROWED those faces: a collapsed face
accepted every key at `any`. So this is not the "declare the keys"
remedy that ledger refuses.
- The repaired shorthand face now carries `InputSchema`'s `onChange`
runtime slot. It enters `KnownDrift` as inherited drift: one entry, one
key. After the merge with PR objectui#10890 (which took
`ai.zod.ts#AIFormAssistSchema` out, one entry and two keys), the table
holds 49 entries / 88 keys, and both header sites say so.
- The union-arm non-vacuity leg had no multi-arm entry left in this
ledger. It now takes the same reader's arm-walking on `KnownDrift` and
re-arms here when a multi-arm entry lands.
- **`object-view-spec-parity.test.ts`:** `body` / `children` are
redeclared envelope keys on `object-view` now. They are triaged into
`SANCTIONED_LOCAL` as refusal-only surface, like `viewTabBar`, and the
declared-surface figure moves 24 → 26.
- **`CalendarSchema`'s texts on both faces said the TypeScript `Omit`
"collapses … and carries no member".** That became false; they are
corrected.
- **Two comments** that spelled the old plain-`Omit` heritage
(`index.ts`, `form-barrel-mirror-9406.test.ts`) are corrected.
- **`scripts/check-handler-key-read-sites.mjs`** caught my first
spelling. It was a computed spread (`...helper(…)`) that the gate cannot
resolve, so it stopped judging all eleven arms and its `detail-view`
`onTabChange` waiver read stale. The fix, the second commit, declares
both members explicitly. Now 49 / 49 reads are judged and 0 are left
unjudged.

## Held, and the question it leaves

`br` / `hr` / `img` read neither channel, but their only published arm
is `HtmlElementSchema`: ONE object over 38 tags, whose renderer draws
`children` for the other 35 (`p`, `h1`, …). Refusing the key on three
tags means splitting that family arm, or refining it per tag. Both
change a published contract's shape.

- The option the ruling adopted (option A in measurement `5859897857`)
reads: "leaving the three void tags to the tier because their arm is the
shared HtmlElementSchema family whose per-tag split was ruled out
(objectui#9067)".
- The parser tier already names them: the registration declares no
`children` slot on a void tag, so `validateTree` reports
`not-a-container`.
- A HELD control in the new pin file records the shared-arm fact, so the
hold is visible.

That the brief listed them among the keys to narrow is recorded as a
conflict in the report, ⛔ not resolved here by guessing.

## Gates (at HEAD `14fd13c51`, exit codes captured by
redirect-then-capture; heavy runs through the shared verify lock)

| gate | result |
|---|---|
| `@object-ui/types` build (tsc + vite + dist completeness) | exit 0 —
132 emitted files verified |
| `@object-ui/types` `type-check` (`tsc --noEmit` + examples +
`tsconfig.test.json`) | exit 0 |
| `pnpm exec vitest run packages/types/` (parity, node-slot, arm,
mirror, family-D and the new pins) | 259 files / 5670 tests, exit 0 |
| `pnpm exec vitest run scripts/` | 177 passed + 2 skipped of 179 files
/ 5317 tests, exit 0 |
| consumer type-check — every package naming a narrowed type (28
packages: the ten object plugins, app-shell, components, core, fields,
cli, react, runner, console, schema-catalog, vscode-extension …) | exit
0, 28 × `type-check: Done` |
| `pnpm --filter @object-ui/types lint` | 0 errors; 0 findings on any
added line (eslint JSON over the 13 touched files) |
| `check:control-bytes` · `check:new-line-citations` (0 new) ·
`changeset:check` · `check-changeset-presence` ·
`check:changeset-claims` · `check:pending-changeset-literals` | exit 0
each |
| `check:doc-types` · `check:doc-snippets` · `check:doc-examples` ·
`check:skill-examples` · `check:doc-fences` · `check:doc-example-ids`
(against the built types) | exit 0 each |
| `check:handler-key-reads` · `check:component-surface-parity` ·
`check:prompt-keys` · `check:registry-bare-names` · `check:spec-symbols`
· `check:readme-exports` · `pnpm check` (CLI self-check) | exit 0 each |
| governed guard `--test` over the 14 paths | NOT GOVERNED |

NOT MEASURED:

- `check:sdui-registration-pins` exits 2 without a console build. The
diff touches no registration and no `sideEffects` array. Left to CI.
- The 4-way `pnpm test` shards beyond `packages/types` and `scripts/`,
plus `test:dist` and E2E: left to CI.

### Merge round — head `31bb63bcb` (merges `main` at `c30c8dd4c`)

The one conflict was the two `KnownDrift` header figures in
`zod-mirror-parity.test.ts`. It was resolved by RECOUNTING the merged
table with the test's own AST reader, not by picking a side:

| tree | `KnownDrift` |
|---|---|
| base `0c50f1863` | 49 entries / 89 keys |
| PR objectui#10890 removes `ai.zod.ts#AIFormAssistSchema` | −1 entry /
−2 keys (48 / 87 on `c30c8dd4c`) |
| this branch adds `form.zod.ts#InputShorthandSchema` | +1 entry / +1
key (50 / 90 on `14fd13c51`) |
| merged `31bb63bcb` | **49 entries / 88 keys** |

The population bullet and the KNOWN_DRIFT restatement both read 49 / 88,
and the bullet keeps both histories in landing order. The other ledgers
read the same as before: `MirroredUndeclared` 2 / 2,
`UnmirroredDeclared` 12 / 84, `RuntimeOnlyDeclared` 3 / 7,
`WiderThanDeclared` 6 / 7. The merge head differs from `main` by exactly
this PR's 14 files.

| gate at `31bb63bcb` | result |
|---|---|
| `zod-mirror-parity` + `content-channel-e3-residual-9256` | 2 files /
200 tests, exit 0 |
| `@object-ui/types` build · `type-check` (incl. `tsconfig.test.json`) |
exit 0 · exit 0 |
| `pnpm exec vitest run packages/types/` (incl. PR objectui#10890's
`ai-zod-arms-10859` / `ai-node-faces-agree-10874` and the family-D file
PR objectui#10714 edited) | 261 files / 5696 tests, exit 0 |
| `pnpm exec vitest run scripts/` | 177 passed + 2 skipped of 179 files
/ 5322 tests, exit 0 |
| `check:control-bytes` · `check:new-line-citations` · `changeset:check`
· `check-changeset-presence` · `check:changeset-claims` ·
`check:pending-changeset-literals` · `check:handler-key-reads` | exit 0
each |

## Acceptance notes — out of scope, not fixed here

- **`input` reads neither channel as well.** `InputSchema`: 0 channel
reads, 17 keys read; the registration declares no `children` slot.
- It is this card's remaining family-D name, and it was not in this
claim.
- Its old hold-out ground ("a TS `Omit` carries nothing") is gone with
this repair: a tombstone on `InputSchema` now propagates on both faces.
  - Carrier: the next objectui#9256 slice.
- **`PartialSchema`'s docblock in `index.ts`** says every generic
re-spelling of its `Omit` collapses for the same `keyof T` reason.
`OmitDeclared` is a generic spelling that does not: this PR measures it
on two faces.
- Carrier: the next objectui#9256 slice, which touches the same `Omit`
subject. objectui#6397, that alias's card, is closed.
  - Noted, not filed.
- **The family-D test header** still records `InputSchema` as "family E,
frozen" and `DetailViewSchema` as unattributable. Both readings are
superseded by this change.
  - Carrier: the next objectui#9256 slice.
- Noted, not edited: PR objectui#10714 held that file while this PR was
written. It has since merged, so the next slice edits the header freely.

---
_Generated by [Claude
Code](https://claude.ai/code/session_01DuWo5bdP9SdVebamn99GGk)_

---------

Co-authored-by: Claude <noreply@anthropic.com>
akarma-synetal pushed a commit to akarma-synetal/objectui that referenced this pull request Sep 28, 2026
…ts name 23 objectui issues that answer 404, and re-qualify 19 bare objectstack numbers (objectui#10803, batch 6) (objectstack-ai#10914)

Part of objectstack-ai#10803
Clause-②: no

Dispatched implementation of the `domain:ui` seat objectstack-ai#1 claim (comment
`5864334310`) on objectui#10803, batch 6, session
`https://claude.ai/code/session_01DuWo5bdP9SdVebamn99GGk`. Citations
only: no sentence's claim moves, and every edited pending changeset's
frontmatter is byte-identical. The one runtime string that moves is
`InputSchema.wrapperClass`'s zod `.describe()` text in
`@object-ui/types`, which loses its dead pointer and nothing else
(amendment `5860244997`, Q1 = A; `patch` changeset). No test pins any
changed text: the literal-anchor sweep below finds no specific anchor,
so no test file is edited.

This batch carries the release note `5863776648`'s three lists:
- the last **23 family numbers**;
- the **18 bare objectstack numbers above 10900** from PR
objectui#10892's C0 census, plus **#13086**, a 404 the C0 instrument
cannot see because it shares a token with #13337 (**Premise**);
- the live-but-wrong bare `objectstack-ai#3391` at the two `rowCrudAffordances.ts`
sites beside `objectstack#3720`.

## Why `Part of`, not a closing line

The order says `Part of`. With this PR the family list (all 115 numbers
of amendment `5860244997` Q2) and the C0 above-10900 list both read 0.
Whether the card now closes, or carries the dead `objectstack#N` class
measured in **Acceptance notes** 1, is the seat's call.

## Premise, re-measured on `origin/main` `9f0c84a44` (the branch point)

- **The 23 family numbers.** REST `GET
/repos/objectstack-ai/objectui/issues/N`: 23 of 23 answer 404, and a
second read of each answers 404 again. `GET .../pulls/N` answers 404 for
all 23. Lit controls: objectui#10533 and objectui#7714 answer 200.
- **No new family member.** The distinct `objectui#N` citations in the
two in-scope classes at the branch point, less those at batch 1's head
`6c3ad7c80`, are 24 numbers. Each was read once: 24 of 24 answer 200. So
the family list is still batch 5's 23.
- **#14026 was a sister-repo card written as objectui's.**
objectui#14026 answers 404 as an issue and as a pull. objectstack#14026
answers 301 to objectui#10102, the card it was transferred to. That
card's measurement-round claim (branch
`claude/issue-14026-import-mapping-selector-probe`) is the session of
`ecf14190e`, the commit that added `14026-list-import-mappings-pin.md`,
and six sibling in-scope lines already write `objectstack#14026` for the
same card.
- **C0, the bare-number census** (the instrument of PRs objectui#10875
and objectstack-ai#10892, at the branch point):

```
git grep -hoP '(?:^|(?<=[^\w#&/.\-]))#\d+(?![0-9A-Za-z_])' 9f0c84a -- '.changeset/*.md' 'packages/*/src/**' ':!**/__tests__/**' ':!**/*.test.*' ':!**/*.spec.*' ':!**/test/**' ':!**/tests/**' | sort -u | wc -l
```

- 984 distinct at `9f0c84a44`, against 998 at batch 5's `b2683a2c0`. The
14 that batch 5 re-pointed are gone, and none is new.
- Above 10900 there are 23: the same 5 CSS colours and the same 18
numbers. Each of the 18 answers 404 as an objectui issue and as an
objectui pull on two reads.
- In objectstack, 16 of the 18 answer 200 with the sentence's own
subject (the **C0 mapping** below). #13033 and #13413 answer 404 there
too, as issues and as pulls. Their squash commits exist in objectstack's
history (a full, not shallow, clone): `c459da6bc` "narrow the per-option
`default` key out of the form-view options vocabulary … (#13033)" and
`89448a52b` "remove the inert AUTH_SSO_PROVIDER_SCHEMA export (#13413)".
Both are ancestors of objectstack `main` (`git merge-base
--is-ancestor`, exit 0).
- **The C0 instrument's blind spot.** Its lookbehind refuses a `#`
preceded by `/`, `-`, `.` or `&`. That form (`#A/#B`, `-#N`) carries 109
distinct numbers at the branch point. The 17 that no earlier batch read
were each read once. 16 answer 200. **#13086 answers 404**, as an issue
and as a pull, in objectui and in objectstack. It sits in
`6985-wizard-card-r-alignment.md` as "the #13337/#13086 fence", in the
same token as #13337, so it rides here. objectstack's
`check-yaml-examples.ts` header, at its landing `2ebfe7e9f` (PR
objectstack#13267, which answers 200), reads "Check YAML Examples
(anti-drift for the AUTHORING format, #13086)" and "Ruled 2026-08-29
(#13086)".
- **objectstack-ai#3391.** objectui#3391 answers 200 with an unrelated subject (a
record-header api action placeholder). objectstack#3391 answers 200 as
the apiMethods whitelist contract card ("跟踪:UI 操作按钮与 apiMethods
白名单一致性契约落地"), and objectstack#3720's own title calls itself "objectstack-ai#3391
遗漏的第四个面".
- Every edited changeset is pending: it is present in `.changeset/` on
`main`. The checkout is not shallow.

## Census (the enumeration pin for this batch)

The instrument PR objectui#10854 printed and PRs objectui#10869 / objectstack-ai#10875
/ objectstack-ai#10892 reused, with this batch's 23 numbers substituted (REF = a
commit or tree):

```
git grep -nE '(objectui#|#|issues/)(8072|8127|8137|8204|8229|8248|8307|8408|9231|9241|9244|9365|9373|9375|9542|9553|9585|10117|10119|10120|10129|10132|14026)([^0-9]|$)' REF -- '.changeset/*.md' 'packages/*/src/**' ':!**/__tests__/**' ':!**/*.test.*' ':!**/*.spec.*' ':!**/test/**' ':!**/tests/**' | grep -v 'objectstack#' | wc -l
```

- REF = `9f0c84a44` (branch point): **104** lines.
- One more line is hidden by the `grep -v 'objectstack#'` filter:
`9943-viewtype-totals-page-row-retired.md` names objectui#8127 beside an
`objectstack#` citation.
- So the true population is **105** lines: 28 changeset lines in 26
files, and 77 src lines in 42 files.
- Unfiltered, REF reads 111. The other 6 lines are live
`objectstack#14026` lines.
- REF = `2b3d2061a` (this head): **0**. Unfiltered it reads 7, all live:
the six `objectstack#14026` lines and the re-qualified one.
- This head merged with a fresh `main` (`8522396c0`, `git merge-tree
--write-tree`, clean, tree `f19d17884`): **0**. REF = `8522396c0` alone:
104.
- **C0**, the 19 numbers, bare and not `objectstack#`-qualified: 28
lines in 23 files at the branch point; 0 at this head. At this head C0
reads 966 distinct numbers, and above 10900 only the five CSS colours
are left.
- Lit control, the printed instrument over live objectui#7714 at this
head: 17 lines. Hex-colour false positives (a number followed by a hex
letter) at the branch point: 0.
- **Out of scope, as it stands** (the 23 numbers, filtered, whole tree
at this head):
  - 94 test lines in 36 files;
  - 5 `.github` lines in 1 file (`ci.yml`, objectui#9241);
  - 2 `apps/console` lines in 1 file (`FormPage.tsx`, objectui#8408);
  - 1 line of the root `vitest.config.mts`;
  - 0 scripts, 0 governed, 0 `CHANGELOG.md`.
- For the 19 C0 numbers: 13 test lines in 10 files, and 1 line of
`packages/plugin-tree/README.md`.

## Citation form

- **Landing shas.** The 9-character backticked sha of the commit on
`main` that landed the change the sentence rests on, as in the earlier
batches. All 15 distinct objectui shas below are ancestors of `main`:
`git merge-base --is-ancestor`, exit 0 each. Control legs in the same
checkout: the head of PR objectui#10902 (`496c63c06`) answers exit 1,
and the known ancestor `5f789538d` answers exit 0. `git rev-parse
--short=9` returns the same 9 characters for each.
- **Own-card pointers** in a changeset are dropped, not replaced. The
configured changelog generator (`@changesets/cli/changelog`, per
`.changeset/config.json`) prefixes each released entry with the hash of
the commit that added the file, which is that landing.
- **The claim lived only on the card.** Where the sentence rests on
something that lived only on the dead card, the sha only locates it:
"the card behind SHA".
- **Nothing answers.** The pointer is dropped and the sentence names the
card by role (objectstack-ai#9553 only).
- **Sister-repo numbers.**
- A bare sister-repo number becomes `objectstack#N` after reading it
there.
- "objectstack PR #N" becomes "PR objectstack#N", since the qualifier
now carries the repository. "framework #N", "upstream #N" and "spec #N"
keep their word, as batch 4 kept "framework PR objectstack#6942".
- Where the objectstack pull request itself answers 404, the sentence
cites its commit in that repository as objectstack `SHA`, the spelling
the tree already uses for an objectstack commit ("Measured on
objectstack `9bd4344e4`").
- **Runtime text** carries no sha: see **Special cases** 6.

## Mapping, the 23 family numbers

Lines / files are the branch-point census for that number. "Method" is
how the landing was found; for every source site, `git log -S
'objectui#N' -- FILE` names the commit that wrote the citation, and it
is the landing below unless the row says otherwise.

| dead number | resolution | method | lines / files | why the commit
carries it |
|:--|:--|:--|:--|:--|
| objectstack-ai#8072 | `c974edf14`; own-card pointer dropped; runtime pointer dropped
| changeset's adding commit, subject "(objectui#8072)" | 5 / 3 | it
mirrors `wrapperClass` on `InputSchema`, which is what both comments and
the `7722` changeset say happened |
| objectstack-ai#8127 | `ca3942729`; "the card behind `ca3942729`" twice (**Special
cases** 2) | `git log -S` names `ca3942729` for the first citation in
all 10 source files; `05a49f2ee` (objectui#9880) and `8a7e09fa1` (the
`9943` changeset's landing) wrote three later sentences that cite the
same fix | 17 / 11 | it derives `ViewType` from `@objectstack/spec`
instead of re-declaring it, and its message records the
`page`-degrades-like-a-typo measurement the sentences cite |
| objectstack-ai#8137 | own-card pointer dropped (landing `0fa7a9c83`) | changeset's
adding commit | 1 / 1 | the only site is its own changeset's pointer |
| objectstack-ai#8204 | own-card pointer dropped (landing `580b0fdf4`) | changeset's
adding commit | 1 / 1 | the pointer opened a paragraph as its own
sentence |
| objectstack-ai#8229 | "a separate finding" (changeset); "the finding `8b7ea3945`
reconciled" (`flex.tsx`) | `8b7ea3945`'s message: "Reconciles the third
face objectui#8229 found" | 2 / 2 | the finding lived on the dead card;
`8b7ea3945` is the commit that reconciled it, and it is the `7735`
changeset's own landing |
| objectstack-ai#8248 | own-card label dropped from the second list item (landing
`d02942b0e`) | changeset's adding commit; its message covers
objectui#8458 and objectui#8248 | 1 / 1 | the changeset lists the two
cards its one landing closed |
| objectstack-ai#8307 | `5591f03bd`; own-card pointer dropped | changeset's adding
commit | 11 / 4 | it makes a lane header over a windowed fetch say
`77+`, and it wrote every comment that cites the card |
| objectstack-ai#8408 | own-card pointer dropped; "seam 2 of the card behind
`8241a4400`" | changeset's adding commit; `8241a4400`'s message names no
seams | 2 / 2 | the seam list lived on the dead card |
| objectstack-ai#9231 | `383502b23`; own-card pointer dropped | changeset's adding
commit | 3 / 2 | it gives the create dialog's confirm control its own
accessible name, the rule both `i18n.ts` comments state |
| objectstack-ai#9241 | own-card pointer dropped (landing `250429c8f`) | changeset's
adding commit | 1 / 1 | the only site is its own changeset's heading |
| objectstack-ai#9244 | `bd0995738` | `git log --grep`: its message names the card; it
wrote all three comments | 3 / 2 | it emits one col-span class per
breakpoint tier, not one for the widest |
| objectstack-ai#9365 | own-card pointer dropped (landing `0970a0e00`) | changeset's
adding commit | 1 / 1 | the only site is its own changeset's pointer |
| objectstack-ai#9373 | `c1006ed8e`; own-card pointer dropped | changeset's adding
commit | 2 / 2 | it resolves the inline locale map before the
interpolation options, the `ListView` comment's subject |
| objectstack-ai#9375 | own-card pointer dropped (landing `e427e9c00`) | changeset's
adding commit | 1 / 1 | the only site is its own changeset's pointer |
| objectstack-ai#9542 | `43c0d1710`; own-card pointer dropped; "filed as a separate
card" (**Special cases** 3) | changeset's adding commit; `git log -S`
names it for the `action-button` / `action-icon` comments too | 9 / 6 |
it accepts and resolves an inline `I18nLabel` on `resultDialog` and
makes `ResultDialogSpec` derive its label members |
| objectstack-ai#9553 | nothing answers: "a separate card carried that census" | `git
log --grep` finds only `40f34b4ba`, which points at the card; no commit
lands it | 1 / 1 | see **Special cases** 4 |
| objectstack-ai#9585 | "`ee70287e4`'s pin measures it NOT GATED"; in its own
changeset, "a pin in this change measures it" | no commit names it;
`ee70287e4` adds the test "NOT GATED: the renderer paints the very node
the mirror refuses, without parsing it" | 2 / 2 | see **Special cases**
5 |
| objectstack-ai#10117 | `4c6f549ef`; own-card pointer dropped | changeset's adding
commit | 3 / 2 | it resolves a lookup title candidate in `page:header`
and adds the record-key safety net both comments describe |
| objectstack-ai#10119 | `73a3c89af`; own-card pointer dropped | changeset's adding
commit | 4 / 2 | it makes a nav ancestor's gates reach its subtree and
stops a group outliving its children |
| objectstack-ai#10120 | `80c54122e`; own-card pointer dropped | changeset's adding
commit; for each file `git log -S` names it, or a later commit that
cites its gate: `e0f820246` (objectui#10563) or `b809375ac`
(objectui#10163) | 16 / 13 | it makes a form neither submit nor offer a
field the caller may read but not edit, the FLS half every site names |
| objectstack-ai#10129 | `6cc910b6d`; own-card pointer dropped | changeset's adding
commit | 10 / 5 | it routes a field-backed action param to its record
picker and refuses an unreadable one |
| objectstack-ai#10132 | `061f5e829`; own-card pointer dropped | changeset's adding
commit | 8 / 4 | it makes the two declared-translatable dashboard
surfaces resolve, including the axis `title` forward |
| #14026 | re-qualified `objectstack#14026` | see **Premise** | 1 / 1 |
it is the card the pin's measurement answered |

## Mapping, the 19 bare sister-repo numbers

| number | resolution | what objectstack says | lines / files |
|:--|:--|:--|:--|
| objectstack-ai#11289 | `objectstack#11289` ("upstream") | "record:details sections
cannot survive an empty record: `hideEmpty` / `collapsible` /
`showBorder` are honoured by the renderer but undeclared" | 2 / 2 |
| #11662 | PR `objectstack#11662` | "feat(spec): declare hideEmpty /
collapsible / showBorder on record:details sections" | 1 / 1 |
| #12616 | PR `objectstack#12616` | "feat(spec): declare record:details
section headerColor as a closed six-token enum" | 1 / 1 |
| #12718 | PR `objectstack#12718` | "feat(spec): retire preview mode —
the RuntimeMode 'preview' value and the whole PreviewModeConfig block" |
1 / 1 |
| #13033 | objectstack `c459da6bc` | the pull request answers 404; its
squash commit narrows the per-option `default` key out of the form-view
options vocabulary, the ruling `form-spec.ts` says was executed upstream
| 1 / 1 |
| #13337 | `objectstack#13337` | "docs(objectui): layout-dsl teaches
only shapes the live schemas accept" | 1 / 1 |
| #13086 | `objectstack#13267` | the card answers 404; PR
objectstack#13267 landed its ruled YAML-examples gate (see **Premise**)
| the same line |
| #13413 | objectstack `89448a52b` | the pull request answers 404; its
squash commit removes an inert schema export and leaves a note recording
the absence as a choice, the shape the `base.zod.ts` note cites as
precedent | 1 / 1 |
| #13632 | `objectstack#13632` | "[spec] `FieldSchema` accepts a
`lookup`/`master_detail` with no `reference` target …", the card
17.3.0's refinement answered | 3 / 3 |
| #13733 | PR `objectstack#13733` | "feat(spec): wizard view v1 —
declaration-and-refusal tightening of FormViewSchema type:'wizard' (Card
S)" | 1 / 1 |
| #13855 | `objectstack#13855` | the field-grouping decision card whose
option B is a section `group` reference, landed by `39404f3d9` (#13897)
"a layout section can reference a declared field group" | 1 / 1 |
| #13906 | `objectstack#13906` ("framework") | "two more
`computeExecCtx` seams read "failed" and "not wired" as one value …" | 6
/ 3 |
| #14274 | PR `objectstack#14274` | "fix(sdui-parser): refuse an
authored `type` attribute on the html tier …" | 1 / 1 |
| #14945 | `objectstack#14945` | "A flow cannot REFUSE with per-record
text …", honoured by `cca699149` "the flow `end` node honours `outcome:
'refused'`" | 1 / 1 |
| #15469 | `objectstack#15469` ("spec") | "`GanttConfigSchema` is
`strictObject(...).passthrough()` …", landed as `9c270bba0` "close the
gantt/tree config .passthrough() windows … (#15469)" | 2 / 2 |
| #15948 | `objectstack#15948` | "fix(plugin-auth)!: session payload
`positions[]` is the security axis, not the better-auth role scalar" | 1
/ 1 |
| #17493 | `objectstack#17493` | "three residues of #17322's node-door
refusal …", landed as `2c1011b01` "refuse a blank string in a flow
node's predicate slot" | 1 / 1 |
| #20051 | `objectstack#20051` | "judge a flattened view overlay's
top-level `options.KIND` …", whose door half is `6a4aec71d` | 1 / 1 |
| #20160 | PR `objectstack#20160` | "fix(spec): a joined report refuses
a top-level dataset / rows / columns / values, pointing each onto
blocks[]" | 2 / 2 |

The live-but-wrong number: "(`/me/permissions` `apiOperations`, objectstack-ai#3391)"
becomes "… `apiOperations`, objectstack#3391)" at the two
`rowCrudAffordances.ts` sites.

## Special cases (the judgement calls)

1. **#14026 is re-qualified, not dropped as an own-card pointer.** The
card behind `14026-list-import-mappings-pin.md` was never an objectui
card: it was objectstack#14026, now objectui#10102. Dropping the pointer
would lose which hypothesis the pin refuted. Re-qualifying it matches
the six sibling lines.
2. **objectstack-ai#8127, the card by role twice.**
- `CreateViewDialog.tsx`: "one of the sites the card records as
"drifted, …"" becomes "one of the sites the card behind `ca3942729`
records as …". That record lived on the card.
- `plugin-list` `ViewSwitcher.tsx`: "objectui#8127 was filed against the
two in `@object-ui/types`, and the maps below were described there as
total …" becomes "the card behind `ca3942729` was filed against …".
- `normalize-list-view.ts`: "The bug objectui#8127 records" becomes "The
bug `ca3942729` records". That commit's message carries the measurement:
`page` resolved "to exactly what it resolved a typo to".
3. **objectstack-ai#9542 in `8648-ui-action-four-undeclared-keys.md`.**
- The superseded paragraph keeps its pre-landing voice: "so it is filed
as a separate card and ⛔ not guessed at here".
- The superseding paragraph reads "`43c0d1710` landed the derivation".
- "(Noted here by the objectui#9542 seat, …)" becomes "(Noted here by
the seat that landed `43c0d1710`, …)".
4. **objectstack-ai#9553, nothing answers.** `base.zod.ts` said "No count of authored
`events` keys is stated here — objectui#9553 carries that census." No
commit landed that card. `40f34b4ba` only points at it, and the
`AGENTS.md` fix `7550728a6` names a different card. So the sentence now
reads "— a separate card carried that census". The census is not
restated, per AGENTS.md objectstack-ai#9.
5. **objectstack-ai#9585, the measurement's instrument.** The card measured the render
path NOT GATED, and no commit names it. But the commit that wrote both
citing sentences, `ee70287e4`, adds a pin that re-measures exactly that:
"NOT GATED: the renderer paints the very node the mirror refuses,
without parsing it".
- `disclosure.ts` now reads "(`ee70287e4`'s pin measures it NOT GATED)".
- Its own changeset, `8236-collapsible-open-intercept-retire.md`, whose
landing is `ee70287e4`, reads "(a pin in this change measures it NOT
GATED)".
6. **The runtime string.** Only the listed text moves.

| file | member | before | after |
|:--|:--|:--|:--|
| `types/src/zod/form.zod.ts` | `InputSchema.wrapperClass` `.describe()`
| "Classes on the wrapper div around the input and its label
(objectui#8072)" | "Classes on the wrapper div around the input and its
label" |

No test, doc or changeset quotes it: a whole-tree search for the old
string returns only the source line.
7. **objectstack-ai#8229 in `flex.tsx`.** "(objectui#8229, folded into objectui#7735's
ruling)" becomes "(the finding `8b7ea3945` reconciled, folded into
objectui#7735's ruling)". objectui#7735 answers 200 and stays.
8. **#13413's sentence.** "Precedent of the same shape:
objectstack#12009 / PR #13413." becomes "… objectstack#12009 /
objectstack `89448a52b`." objectstack#12009 answers 404 too, but it is a
qualified sister-repo number outside this batch's lists, so it is left
and listed (**Acceptance notes** 1).
9. **#20160 across a line break.** In
`10746-joined-report-clears-binding.md`, "(objectstack PR" ends one line
and "#20160: …" opens the next. They become "(PR" and
"objectstack#20160: …".

## The literal-anchor sweep (both test-pin classes, ruling `5861900779`)

- **Instrument.** Every string, template, numeric and regex literal in
all 4068 tracked test and script files (119016 distinct literals),
parsed with TypeScript.
- **Candidate filter.** A literal is a candidate only if it matches the
diff's removed lines with two lines of context, raw or
comment-flattened. That leaves 2839.
- **Test applied to each candidate.** Does its occurrence count DROP
between `9f0c84a44` and `2b3d2061a` in any of the 92 files this PR
changes, in raw text or in a comment-flattened form? 229 distinct
literals drop.
- **Every one is a generic token.** Digits and short numbers,
punctuation, single letters, `objectui#`, `objectui#1`, and whole-tree
scanners such as `/#\d+/` and `/objectui#\d+/`. The three `objectui#\d+`
matchers (`ActionRunner.disabledGate`, `registry-inputs-spec-parity`,
`catalog-gallery-render`) assert over their own test data and read no
changed file.
- **No specific anchor.** None is a batch number, a changed phrase, or
the changed `.describe()` string. So no test pins changed runtime text
(class one), and no source-reading test pins a changed comment or
docblock citation (class two).
- Test titles and comments that name these numbers are out of the card's
classes and stay (**Census**, out of scope).

## Held

**By the serial rule: nothing.** Re-mapped before the push, on 9 open
PRs: objectui#10910, objectstack-ai#10908, objectstack-ai#10907, objectstack-ai#10906, objectstack-ai#10901, objectstack-ai#10891, objectstack-ai#10777,
objectstack-ai#10278 and the release PR objectstack-ai#5400 (objectstack-ai#10902 and objectstack-ai#10904 had merged since the
claim).

Two of them share files with this PR. Their hunks were read against
their merge-bases; each file is identical at its merge-base and at
`9f0c84a44`, so the lines map directly.
- **objectui#10907, `types/src/zod/form.zod.ts`.** It inserts a refusal
constant before `InputSchema`, two tombstone members further down
`InputSchema`, and a comment in the `InputShorthandSchema` arm. This
PR's three edited lines (the `wrapperClass` comment and description, and
the arm's "shrank that row" comment) sit outside every one of its hunks
and their 3-line context.
- **objectui#10906, `metadata-admin/i18n.ts` and
`previews/ViewPreview.tsx`.** Its `i18n.ts` insertions are far from the
two `createDraft` comments, and its `ViewPreview.tsx` hunks are far from
the `options` fold docblock.

Trial merges with this head (`git merge-tree --write-tree`):
- clean for objectstack-ai#10910, objectstack-ai#10908, objectstack-ai#10907, objectstack-ai#10906, objectstack-ai#10901, objectstack-ai#10891 and objectstack-ai#10777;
- objectstack-ai#10278 (`eab4c8e52`) conflicts in `ObjectGrid.tsx`,
`plugin-grid/README.md` and `content/docs/plugins/plugin-grid.mdx`, and
conflicts identically against `9f0c84a44` alone;
- objectstack-ai#5400 (Version Packages) regenerates and is not a hold.

objectui#10891 shares no file with this PR.

## Changesets

- `.changeset/10803-dead-citation-sweep-sixth-batch.md`, EMPTY
frontmatter. It covers the comment-only edits in 15 released packages;
no published behaviour changes through them. It points at the second
file for `@object-ui/types`' runtime text.
- `.changeset/10803-sixth-batch-runtime-strings.md`,
`'@object-ui/types': patch`: the `wrapperClass` description loses its
pointer. No key, path, issue code, accept set, refusal or severity
moves.

## Proof of prose-only (C4), against `9f0c84a44`, on this head
`2b3d2061a`

- **Source.** Each of the 53 touched `.ts` / `.tsx` files was parsed at
`9f0c84a44` and at this head with TypeScript 6.0.3's `createSourceFile`,
and re-printed by `createPrinter({ removeComments: true })`.
  - 52 of 53 prints are identical.
- `form.zod.ts` is equal once the one listed substitution (**Special
cases** 6) is applied to the base print, matched once.
  - 0 parse diagnostics.
- Lit controls on the same instrument: editing a string literal moves
the print; re-spacing a comment does not.
- **Changesets.** The frontmatter block of every one of the 37 edited
changesets is byte-identical at `9f0c84a44` and this head (37 of 37, by
md5). The overwrite gate below agrees.
- **Scope of the diff:** 92 files, +175 / −140. That is 37 edited and 2
new changesets, and 53 non-test source files in 15 released packages. No
test file.

## Gates, on this head `2b3d2061a`

Each line is the gate's own verdict and exit code, captured by
redirect-then-`$?`.

- `node scripts/check-changeset-presence.mjs`, exit 0: "53 source
file(s) of 15 released package(s) changed, and this change declares 2
changeset(s): .changeset/10803-dead-citation-sweep-sixth-batch.md,
.changeset/10803-sixth-batch-runtime-strings.md."
- `pnpm changeset:check`, exit 0: "All workspace packages are in the
changeset fixed group." / "No changeset declares a `major` bump."
- `node scripts/check-changeset-overwrite.mjs` (report-only), exit 0: "2
changeset(s) added, 37 modified, 0 deleted". `declared at base` equals
`declares now` for 37 of 37.
- `pnpm check:changeset-claims` (report-only), exit 0:
- "Every one of those 1 address(es) either names the tree it was read
from, or points at a line this change does not move";
- "Every package declared across those 31 body(ies) is either not
negated …";
- the standing notice "75 pending changeset(s) describe a file this
change touches".
- Read against the diff: a pending changeset quoting a replaced pointer
would itself carry the dead number and sit in the census, which reads 0.
No pending changeset quotes the changed description.
- `pnpm check:control-bytes`, exit 0: "check-control-bytes: OK (scanned
9178 tracked text file(s); skipped 85 binary)."
- `pnpm check:new-line-citations`, exit 0: "VERDICT
new-cross-file-line-citations: 0 new citation(s), enforcement
report-only -> exit 0".
- `pnpm check:pending-changeset-literals`, exit 0: "No test source names
a pending changeset."
- Also run over the touched comments:
  - `pnpm check:installed-pin-claims`, exit 0 ("OK");
- `pnpm check:comment-mask-corpus`, exit 0 (1 disagreeing file, within
the ceiling objectui#7882 holds open);
- `pnpm check:handler-key-reads`, exit 0 ("every judged read is a
declared member of it").
- The governed-surface predicate over the 92 paths, exit 0: "NOT
GOVERNED — 92 path(s) checked against 5 governed surface(s); none
matched." Lit control `AGENTS.md`: exit 3.

**Tests**, through the shared verify lock, on `2b3d2061a`. Each is
`VERDICT command-exit 0`.
- `scripts/__tests__/`, the whole directory, whose whole-tree scanners
read the touched files: `Test Files 177 passed | 2 skipped (179)`,
`Tests 5322 passed | 2 skipped (5324)`. The two skipped files are the
network-escape fixtures that run only as a child.
- `packages/types/`, the whole package, whose runtime text moved: `Test
Files 264 passed (264)`, `Tests 5854 passed (5854)`. `pnpm --filter
@object-ui/types type-check`, exit 0.
- **The pins nearest the re-pointed text:**
- in `types`: `input-wrapper-class-mirrored-8072`, `zod-mirror-parity`,
`wrapper-class-declared-7722`, `zod-mirror-authors-no-defaults-7735`,
`collapsible-open-refusal-8236`, `tree-view-config-readers-8253` and
`layout-default-jsdoc-7361`;
- in `components`: `collapsible-open-intercept-8236`,
`registration-defaults-match-renderer-8229` and
`action-undeclared-keys-8648`;
- in `plugin-view`: `ViewSwitcher` and
`ViewSwitcher.viewTypeTotalsBothLegs-9943`;
  - in `plugin-kanban`: `laneCountHonesty-8307`;
  - in `plugin-grid`: `rowCrudAffordances` and `rowCrudEffectiveOps`.
  - Result: `Test Files  15 passed (15)`, `Tests  381 passed (381)`.
- No red leg: the sweep found no anchor to move, so there is no pin
whose old copy should fail.

**Declared narrowing.** NOT MEASURED locally:
- the full suites and type-check of the 14 other touched packages, and
eslint.
- Reason: the comment-stripped syntax tree of 52 of 53 touched source
files is identical to `main`, and the 53rd differs only by the listed
literal.
- CI runs the full farm.

## Acceptance notes

1. **A sister-repo class of the same defect: 30 `objectstack#N`
citations answer 404 in objectstack.**
- **Measurement.** Every distinct `objectstack#N` in the two in-scope
classes at the branch point is 359 numbers. Each was read once: 328
answer 200, 1 answers 301 (objectstack#14026 to objectui#10102), and 30
answer 404, each confirmed by a second read.
- **The 30:** objectstack-ai#5970 objectstack-ai#5976 objectstack-ai#6038 objectstack-ai#6124 objectstack-ai#6281 objectstack-ai#6331 objectstack-ai#6450 objectstack-ai#6483 objectstack-ai#6515
objectstack-ai#9933 objectstack-ai#9934 objectstack-ai#10354 objectstack-ai#10485 objectstack-ai#10695 objectstack-ai#11330 #11507 #11513 #11658 #11703
#11753 #11846 #12009 #12868 #13117 #13670 #16126 #17147 #17762 #17987
#18012.
- **Sites at this head:** 82 lines in 63 files, 26 of them changeset
lines.
- **Three of them sit in sentences this PR edits, and are left as they
are:**
- objectstack#11846, "(objectstack#11846, landed as PR
objectstack#12718)" in `6748-preview-mode-provenance-ratchet.md`;
     - objectstack#12009, in `base.zod.ts`'s precedent line;
- objectstack#12868, in `form-spec.ts`'s "RULED 2026-08-28
(objectui#6263 / objectstack#12868, …)".
- **Why left.** They were not in this batch's lists, and the class is
the seat's to scope. objectstack's own card for dead tracker citations
in its tree is objectstack#19123, whose landing `66e266c93` counts
#12868 among the dead numbers it measured. Triage item 3 would put a
dead number in these classes on this card. The fix shape measured here
for such a number is the objectstack commit, as with `c459da6bc`.
2. **The rest of the bare `objectstack-ai#3391` population.** Only the two sites the
claim names were re-qualified. 28 more in-scope lines in 10 files write
the apiMethods whitelist card as a bare `objectstack-ai#3391`, which resolves to the
unrelated objectui#3391:
   - `ObjectDataPage.tsx`, `ObjectView.tsx` (app-shell);
   - `managedBy.ts`;
- `MePermissionsProvider.tsx`, `PermissionContext.ts`,
`PermissionProvider.tsx`;
   - `fieldWriteGate.ts`;
   - `ImportWizard.tsx`, `ObjectGrid.tsx`;
   - `ListView.tsx`.

It is live, not a 404, so it is outside the family pin. Two of those
lines pair it with a bare 3546 that means objectstack#3546 ("detail/form
面的 edit/delete 按钮接入服务端 effective 操作集"), while objectui#3546 is an
unrelated i18n card. Carrier: none.
3. **A stale claim beside a re-pointed sentence.** The same
`base.zod.ts` paragraph says "AGENTS.md's abridged protocol sketch shows
`events?: Record…` and its action-system commandment authors one".
`7550728a6` removed both from `AGENTS.md`, so that sentence is now
false. It is not a citation, and this PR does not touch it. Carrier:
none.
4. **The C0 blind spot, for any later census.** The bare-number
instrument's lookbehind hides a number written after `/`, `-`, `.` or
`&` (`#13337/#13086`, `-objectstack-ai#2231`). This batch read the 17 such numbers no
batch had read, and #13086 was the only 404. A later census can narrow
the lookbehind to refuse only a word character, `#` or `&` before the
`#`, and drop URL fragments by hand.
5. **Filenames are not citations.** Pending changeset and test FILENAMES
carry several of these numbers. They stay, as in PRs objectui#10707,
objectstack-ai#10797, objectstack-ai#10854, objectstack-ai#10869, objectstack-ai#10875 and objectstack-ai#10892.

---
_Generated by [Claude
Code](https://claude.ai/code/session_01DuWo5bdP9SdVebamn99GGk)_

Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants