docs(spec): correct the expired browser-only manifest premise in two prose sites (#17735 item 4) - #18608
Conversation
…-only manifest claim `check-generated.ts`'s EXTERNAL_INPUT_REQUIRED `why` string asserted that the registry "exists only after objectui is built at .objectui-sha and enumerated in a real browser" and that "nothing in this repo can hand it one". Both halves are false: `scripts/gen-sdui-manifest-node.mjs` enumerates the registry under plain Node, and the artefact it writes has been tracked at the repo root since #13446, where lint.yml feeds it to the gate on every PR. The classification is unchanged — the aggregate genuinely passes no MANIFEST — only the stated reason is made true. The gate's own header carried the same expired premise ("its only producer is objectui's dump-public-manifest.mjs ... nothing enumerates it from Node") and is corrected alongside it, with what the two producers actually read. Claude-Session: https://claude.ai/code/session_01LvwGppdonww4zGLWZo5rho Co-authored-by: Claude <noreply@anthropic.com>
…ssue-17735-sdui-manifest-producer-parity
…ssue-17735-sdui-manifest-producer-parity
📓 Docs Drift CheckNothing in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 0 changed package(s)), so this run has no opinion about the docs. What this run could not see
Coarse fallback — 0 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): |
Contract reviewServed-tier: ① Derived judgments
② Semver level
③ Boundary flags
Implemented-by: VERDICT: PASS Generated by Claude Code |
Seat verdict: REWORK — the contract review passed, and that is not the same questionSeat
⭐ The review earned this by reproducing the load-bearing claim independently rather than accepting it: it npm-installed the 17 published What must change — three items, all inside the two files already in the diff
What is NOT owed and must not be re-opened
Note for the seat's own recordThe review's ① also flags that the header's retained 「NOTHING HERE PRODUCES one」 (line 98) is scoped by its next sentence to the console-build half, whose sub-claims remain true — so it is ⛔ not a fourth item. Recorded so a later reader does not "fix" a sentence that is correct. Generated by Claude Code |
… build objectui
Rework of the prose this branch already corrected: the replacement text
re-asserted two things that are themselves false, and one bucket definition
still contradicted the corrected reason one line below it.
1. "builds objectui at .objectui-sha" (check-generated.ts `why`) and "it builds
objectui from the SOURCE at `.objectui-sha`" (parity-gate header). Measured:
scripts/gen-sdui-manifest.sh computes BUILD_ROOT=.cache/objectui-<sha12> (507)
and exits 1 unless that directory already exists (512-516), printing "Run
'pnpm objectui:build' first to vendor the console at the pinned SHA". It then
serves that vendored tree with a vite dev server (sdui_dev_server_cmd, 373-376;
pushd 545), drives objectui's dumper against it (654-655) and runs the ADR-0082
ratchet on the result (684-688). It requires a build; it performs none.
2. The citation `objectui#6741`, carried in both files. It resolves to nothing:
404 for both the issue and the PR at that number, while objectui 6739 / 6742 /
6743 answer 200 as controls. The fact it was cited for -- the registry
enumerates under plain Node -- is reproduced and stays; the number is dropped
and the parity header carries a tombstone so nobody restores it.
3. The same-class sentences that survived the first pass, all in
check-generated.ts: the EXTERNAL_INPUT_REQUIRED doc comment ("the input they
compare against does not exist here and cannot be produced here"), the print
line ("source audit(s) whose input this repo cannot produce") with its
rationale comment, and the ledger's classification prompt for the same bucket.
All four said the input cannot be produced here; the corrected `why` one line
away says it is tracked here and CI feeds it to the gate on every PR. The
bucket, its membership, `runBy` and every verdict are untouched -- only the
stated reason moves, which is the ruling's item 4.
Claude-Session: https://claude.ai/code/session_01LvwGppdonww4zGLWZo5rho
Co-authored-by: Claude <noreply@anthropic.com>
…ui-manifest-producer-parity
Contract reviewServed-tier: ① Derived judgments
② Semver level
③ Boundary flags
Implemented-by: VERDICT: PASS Generated by Claude Code |
Seat verdict: ACCEPT — and the one survival the review found is filed, ⛔ not waved throughSeat The three REWORK items are discharged, and the review proved it by executionIt did not read the code and reason about it — it ⭐ Two things make this review trustworthy rather than agreeable:
The corrected clause is true of the tree, line by line: The one survival, and why it is filed rather than sent backParity header line 118 still reads 「 Seat-verified before deciding: the sentence is present at head and at ⇒ ACCEPT, for a trade stated plainly rather than assumed: a third dev round moves the head again and voids a review that cost a full offline install and two built trees, buying one pre-existing sentence. The lane also caps patch rounds at two. ⛔ The sentence does not get dropped for that convenience — it is filed with its measurement so it cannot rot. Filed rather than folded
Landing
Generated by Claude Code |
Part of #17735 — this PR discharges ruling item 4 only. Items 1 and 2 are not implemented, because item 1's stated premise measured false and item 3's escape clause fires. The evidence is below;
#17735remains open for the seat to route the mechanism question.What landed
Prose-only. Every sentence in two dev-only gate scripts that asserted the expired browser-only manifest claim, or that mis-described what
pnpm sdui:manifestdoes, is corrected. No behaviour, no classification, no verdict set, no baseline moves.packages/spec/scripts/check-generated.ts— theEXTERNAL_INPUT_REQUIREDwhystring (ruling item 4), plus the three other sentences in the same file that stated the same retired reason. The bucket, its membership andrunByare untouched; only the stated reason moves.packages/spec/scripts/check-react-blocks-declaration-parity.ts— the gate's own header carried the identical stale premise. It is on this card's declared file surface and is the first thing the next reader of this card will read, so it is corrected in the same PR and named here rather than left to rot.Every sentence corrected, and what it was measured against
check-generated.tswhyscripts/gen-sdui-manifest-node.mjsenumerates it under plain Node — no browser, no objectui buildcheck-generated.tswhylint.ymlfeeds it to the gate on every PRcheck-generated.tswhydump-public-manifest.mjs"check-generated.tswhypnpm sdui:manifest"builds objectui at.objectui-sha"check-generated.tsEXTERNAL_INPUT_REQUIREDdoc commentcheck-generated.tsprint line + its rationale commentMANIFEST; a reader can run the gate by hand, and CI doescheck-generated.tsledger classification promptpnpm sdui:manifest"builds objectui from the SOURCE at.objectui-sha"objectui#6741Two of those rows — the "builds objectui" clause and the
objectui#6741citation — were re-asserted by this PR's own first pass, inherited from the text it replaced. They are listed here rather than quietly dropped, because a PR that exists to correct false prose shipping new false prose is exactly the failure this card is about."builds objectui" — what
scripts/gen-sdui-manifest.shactually doesRead on this head, by line:
BUILD_ROOT="${FRAMEWORK_ROOT}/.cache/objectui-${PINNED_SHA:0:12}"— derived from.objectui-sha.if [[ ! -d "$BUILD_ROOT" ]]→ prints✗ objectui build tree not found at …andRun 'pnpm objectui:build' first to vendor the console at the pinned SHA, thenexit 1.ℹ … nothing to doandexit 0.pushdes into that tree and spawnspnpm --filter @object-ui/console exec vite dev --port … --strictPort— a dev server over the already-vendored checkout.BASE_URL=http://localhost:PORT OUT=… node scripts/dump-public-manifest.mjs.--strictagainst what it dumped.So it requires a build (
pnpm objectui:build=scripts/build-console.sh) and performs none: it dumps, then ratchets. The script's own comment at 534-538 says the same thing from the other side — "this script drives a vite DEV server over.cache/objectui-SHA".objectui#6741— dropped, with a tombstoneThe number resolves to nothing in
objectstack-ai/objectui: 404 for both the issue and the PR at that number. This is a zero-hit reading with same-subject controls that hit — objectui#6739,#6742and#6743all answer 200 on the identical endpoint, so the 404 is the number, not the endpoint or the token.objectstack#6741is an unrelated ADR-governance ruling, and neitherpackages/spec/CHANGELOG.mdnor the #13446 commit body carries the objectui number.The fact it was cited for — the registry enumerates under plain Node — is independently reproduced (byte-identical regeneration, below), so the fact stays and the citation goes. The parity header keeps a one-sentence tombstone saying the old citation resolved to nothing, carrying no number, so the next author neither follows a dead link nor "restores" one.
No dead reference is left in either file:
git grep -c '6741'is 0 in both, with the node producer's header hitting 1 as the control. That third occurrence is not in this PR's file surface; it is reported for the seat to file.Why ruling item 1 is not implemented — its premise is false
Item 1 reads: "Where the node generator omits what the runtime registry declares … the node generator is fixed to emit it."
The node generator omits nothing. Measured at every layer it could hide in:
scripts/gen-sdui-manifest-node.mjs, read in full (194 lines): it imports the 16 registry modules, callsComponentRegistry.getPublicConfigs(), and passes the result tomanifestFromConfigs. There is no filter, no allowlist, no key removal anywhere in it.manifestFromConfigs(packages/sdui-parser/src/index.ts) copiesconfig.inputsfield-for-field. The node generator passes neitheronlynorpublicOnly.@object-ui/core@17.6.0contains nowithElementDataSourceInput/ELEMENT_DATA_SOURCE_INPUT(control:getPublicConfigshits in the same dist).Byte-level proof that the tracked artefact is exactly that registry — regenerating it reproduces the committed file with no diff at all:
This was reproduced independently in contract review of this PR, from a fresh npm install of the 17 published
@object-ui@17.6.0packages and an esbuild bundle ofsdui-parser, reaching the samesha256 49211fee7792/git hash-object 78f870e42fe9and a cleancmp. So the artefact is not stale relative to its own input, and there is no omission to remove. "Fix the node generator to emitdataSource" would mean hard-coding a key the registry it reads does not declare.The actual cause, key by key
The two producers read two different registries:
gen-sdui-manifest-node.mjs) installs the npm-published@object-ui/*at the version named inscripts/sdui-manifest.record.json—17.6.0, published 2026-08-24.gen-sdui-manifest.sh) dumps the registry of the source at.objectui-sha—53ded82b, authored 2026-09-05 — from a checkoutpnpm objectui:buildhas already vendored.Every diverging key landed in objectui source inside that 12-day window:
dataSourceon 15 blockswithElementDataSourceInputinRegistry.register(), which is not in the published 17.6.0 distvariant/alignonui:textui:textregistration after 17.6.0. Noteelement:textalready declares all three in bothtypevsactionTypeon the two action blockstypeactionTypetypeand reads `d.actionTypeThe root defect is one false equivalence, and it is in this repo's own prose and procedure:
.objectui-shaships a commit; the@object-uiversion read off that commit'spackages/core/package.jsonnames a published tarball built from an earlier commit, because objectui bumpsversiononly at release. Every commit between two releases carries the previous release's version number, so the version string cannot distinguish them.Nothing detects it:
scripts/check-sdui-manifest.mjsverifies shape,sha256(artefact) == record.sha256, andrecord.objectuiSha == .objectui-sha. It readsobjectuiPackagesVersiononly as a required-field presence check — it never verifies that the version installed corresponds to the pinned commit.Why item 2 is not implemented — item 3's escape fires
A producer-parity test pinning the two outputs equal would be red today, by construction, and landing a knowingly-red required gate is not an option:
17.6.0is the newest published@object-ui/core(npmtime: nothing after 2026-08-24).Per ruling item 3 this is reported, and nothing is retired. A candidate mechanism that would reach parity without retiring anything — pointing the node producer at the pin's built tree via its existing
--modules-rootflag, whichbuild-console.shalready materialises at.cache/objectui-SHA— is unverified: no built objectui tree exists in this container. It is an open question on the card, not shipped here. Choosing among the candidate mechanisms is the maintainer's, and the decision box on #17735 holds it.Premise checks
"dataSource"in the tracked artefact = 0 (control"name"= 339); the falsewhystring = 1 (controlEXTERNAL_INPUT_REQUIRED= 12).align,variantontext» is about theui:textkey. The artefact does carryelement:textwith["content","variant","align"]; it istext(namespaceui) that carries only["content"]. Both keys exist in both producers — onlyui:textdiverges.docs/releases-maintenance.md. Line 118 is a closing code fence; the sentence is at 120-121: "Read that version from the objectui checkout'spackages/core/package.json— the bump already required that checkout." It is mechanically accurate and substantively misleading: following it is what manufactures the skew above.#17736is closed as completed, so it landed without this card's answer. The file isdomain:devxand is not edited here — reported for the seat to route, since the correct sentence depends on the producer ruling.object-tree. Regenerating from the registry does not produce it, in either producer.object-treeis registered byplugin-treein published 17.6.0 and at the pin, but it is absent fromPUBLIC_BLOCKSin both (control:object-gridpresent), andplugin-treedeclares notier: 'public'opt-in at the pin — sogetPublicConfigs()excludes it either way. That is a different defect, living in objectui's public-tier curation. [finding] the trackedsdui.manifest.jsonhas noobject-treeentry althoughplugin-treeregisters the renderer — the newobject-treespec row gets no parity comparison at all #18407 is not addressed here and is not subsumed by this PR.Rework round — what the seat's REWORK verdict asked for, item by item
The contract review of record (
CONTRACT_REVIEW_TIER, PASS) and the seat's REWORK answer different questions: the review asks whether this moves an accept set or a public surface (it does not, proven hard); the seat asks whether the PR discharges ruling item 4, whose whole content is 「reason made true」. The review measured the new reason false in two places. Those, and only those, are what this round changes.gen-sdui-manifest.sh(above). The script requires a vendored checkout and refuses without one; it dumps and ratchets.objectui#6741, carried twice — dropped from both files. The fact stays, the citation goes, and a tombstone carrying no number stops the next author restoring it. No real reference was findable: objectui's numbering covers that range (newest is well above it) but the number itself answers 404 for both the issue and the PR, and the GitHub search API is not reachable from this session, so the fact is stated without a number as the verdict permits.One correction beyond the two the seat named, in the same file and the same sentence class, declared here rather than left:
check-generated.ts's ledger classification prompt ("or audit source against an input this repo cannot produce") stated the selection criterion for the very bucket whose definition this round corrects. Leaving it would have left the file defining one bucket two ways — the same defect at a smaller scale. It is a problem-message string, pinned by no test (control: the ledger test's fourtoContainpins are1 needing an external input,cannot run here: check:react-declaration-parity,MANIFEST,scripts/gen-sdui-manifest.sh, all unchanged and all still green).Not re-opened, per the verdict: ruling items 1 and 2 stay unimplemented (item 1's premise measured false by two independent parties); the mechanism question M1/M2/M3 stays in the decision box on #17735 and is the maintainer's; #18407 stays open and is not subsumed; the
check:cross-package-test-inputsred is pre-existing and diff-invariant. The parity header's retained "NOTHING HERE PRODUCES one" (line 98) is scoped by its next sentence to the console-build half, whose sub-claims remain true — it is correct and is deliberately untouched.Verification
Head
ae7e4c916d, merged withorigin/mainat21b7c12b4fbefore measuring. Change set derived from git: exactly the two files, three-dot semantics.Gates. 54 families derived on this head with
node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands; all 54 run; reconciled with--ranat exit 0 — "54 derived famil(ies) accounted for — 54 run". Exit codes captured with redirect-then-$?, never through a pipe. 50 green, 4 non-zero and every one of them known:check:react-declaration-parity(bare)MANIFEST=; the CI-shaped run is green, belowcheck:cross-package-test-inputspackages/spec/dist/exists)check:dual-build-cjs-loadscheck:lean-entry-closureThe two exit-3 readings are NOT MEASURED, not red: they need a full
pnpm build, which CI does.Targeted runs on this head:
pnpm --filter @objectstack/spec build:: exit 0 (34/34 declaration files present) — run first, because two of the gates below read the builtdist/pnpm --filter @objectstack/spec run check:generated:: exit 0 — "All 15 generated artifacts are up to date", and the corrected print line readsNeeds an input this aggregate does not pass (1 source audit(s)):MANIFEST="$PWD/sdui.manifest.json" pnpm --filter @objectstack/spec check:react-declaration-parity --baseline react-declaration-parity.baseline.json --strict:: exit 0 — "no new DECLARATION divergence vs accepted baseline"vitest run --project repo scripts/check-generated-ledger.test.ts:: exit 0 — 8 passedvitest run --project local scripts/check-react-blocks-declaration-parity.test.ts:: exit 0 — 30 passedpnpm check:pm-dispatch-gates:: exit 0 — "dispatch-gates self-test: 1746 cases pass", 815.6 s (run detached: it exceeds this container's foreground cap, which is a cap, not a red)pnpm lint(eslint . --no-inline-config, the repo-wide population, no narrowing) :: exit 0No changeset (
skip-changeset):packages/spec'sfiles[]does not includescripts/, and nothing undersrc/imports either edited file (control: 26 hits for a script thatsrc/does import). Nothing published moves.Clause-②: no.🤖 Generated with Claude Code
https://claude.ai/code/session_01LvwGppdonww4zGLWZo5rho
Generated by Claude Code