Repository navigation
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 |
…jectui citation (objectstack-ai#18864) Fixes objectstack-ai#18627 Clause-②: no `scripts/gen-sdui-manifest-node.mjs` was the last site still citing the dead objectui number for the 2026-08-29 "the browser-only manifest claim is expired" measurement. PR objectstack-ai#18608 had already dropped that citation from the two sibling gate scripts and left a number-free tombstone in each; this header was the survivor — and it is the header both corrected sites now send readers to for the readings, so a reader following the corrected trail landed on the one uncorrected number. ## What changed Prose only: one docblock paragraph in one dev-only script. No behaviour, no export, no generated artefact. - **The fact stays.** Plain Node enumerates the registry: measured false 2026-08-29, re-measured 2026-08-30 against published `@object-ui/*` 17.6.0, 57 configs, 0 lazy stubs, no Playwright, no objectui build. - **The number goes, and the readings replace it.** The paragraph now carries the independent reproduction from the review of PR objectstack-ai#18608 — the 17 published `@object-ui/*` 17.6.0 packages installed from npm, `sdui-parser` bundled, this generator run under plain Node, `sha256 49211fee7792` / `git hash-object 78f870e`, `cmp` byte-identical to the tracked artefact. - **A number-free tombstone**, in the form PR objectstack-ai#18608 established in the sibling file: do not put an objectui issue number back on that measurement — the citation this paragraph carried answers 404 on both the issue and the PR endpoint, while seven neighbouring objectui numbers answer 200 as controls on the same endpoint and token, so the zero is that number, not the channel — and the readings above stand without one. `git grep 'objectui#6741'` over the whole tree: **0** hits. The remaining `objectstack-ai#6741` hits are objectstack#6741, the live ADR-governance ruling — a different repository's number, untouched. ## DARK reading: the generator's behaviour is untouched (must read 0, and does) Both runs enumerate the same npm install (the second reuses the first via `--modules-root`), so the header is the only variable. | run | artefact `sha256` | `git hash-object` | bytes / components | |---|---|---|---| | pre-edit, at this branch's base `be7aeb8275` | `49211fee7792cf51…` | `78f870e42fe9fec1…` | 66910 / 57 | | post-edit, at `49be1bcc90` | `49211fee7792cf51…` | `78f870e42fe9fec1…` | 66910 / 57 | | tracked `sdui.manifest.json` | `49211fee7792cf51…` | `78f870e42fe9fec1…` | 66910 / 57 | `cmp` pre-edit vs post-edit :: exit 0. `cmp` post-edit vs tracked :: exit 0. `node scripts/check-sdui-manifest.mjs` :: exit 0 (artefact, record and pin still agree). The only tracked file either run moved is `scripts/sdui-manifest.record.json`, and only its `generatedAt` stamp (`2026-09-08` → the run's own date). It was restored with `git checkout HEAD -- …` and the restoration is proven by an empty `git diff HEAD`, so this PR does not touch it. ## Gates - `node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --ran …` :: **26 derived families, 26 run, 0 NOT-MEASURED, 0 UNRUN** — every one recorded as `command :: exit 0`, each exit code captured before any pipe. One run beyond the derived union: `node scripts/check-sdui-manifest.mjs`. - Repo-wide lint, **not narrowed**: `node --stack-size=4000 node_modules/eslint/bin/eslint.js . --no-inline-config --format json` :: exit 0 in 68s — **6847 files linted, 0 errors, 0 warnings**, this file among them. Taken at `49be1bcc90`, the final commit. - No package is in the diff, so there is no dependency-closure build and no package `test` / `typecheck` owed here. The file is a repo-root dev script that ships in no package's `files[]`. - `skip-changeset`: nothing published moves — a comment paragraph in a repo-root dev script, in no package tarball. ## Acceptance notes - **The other citation in this same header, `objectstack-ai#12924`, also answers 404** — objectstack `issues/12924` and `pulls/12924` both 404, with 10 of the 20 neighbouring numbers 12915–12935 answering 200 on the same endpoint and token, so the zero is that number. ⛔ Deliberately not touched: the card fences this round to the objectui citation. It is also already a known, patrolled case — the H40 row in `scripts/pm/check-half-states.mjs` records `objectstack-ai#13398 objectstack-ai#13399 objectstack-ai#13178 objectstack-ai#12924 objectstack-ai#13456 — HTTP 404 — do not resolve` as suppressed cards — and `objectstack-ai#12924` is cited well beyond this file (`.github/workflows/lint.yml`, `.github/workflows/ci.yml`, `packages/lint/src/sdui-jsx-baseline.json`, `packages/lint/src/validate-jsx-pages.production-witness.test.ts`). Named here for the filing seat; devs do not POST issues. - The mechanism question on this file's producer — card objectstack-ai#17735, M1 point at the pin's built tree / M2 retire in favour of the browser dump / M3 keep the skew and add a detector — is untouched and stays open; nothing here anticipates it, because the citation is dead whichever mechanism wins. objectstack-ai#17735 is not addressed by this PR. --- _Generated by [Claude Code](https://claude.ai/code/session_01JbZnqu8bt6YqfJsr9vaFb3)_ Co-authored-by: Claude <noreply@anthropic.com>
…he declaration-parity ratchet and the browser dump (objectstack-ai#19921) Fixes objectstack-ai#17735 Clause-②: no Executes maintainer ruling **丙** on objectstack-ai#17735 (ruling record `5724940904`, batch objectstack-ai#151 item 2; verification record `5717306177`; maintainer re-affirmation `5791879338` over ruling objectstack-ai#197 A's PR objectstack-ai#19270 path). The fence notes `5756239563` and `5786373289` are cleared: PR objectstack-ai#19270 was closed unmerged by the re-affirmation, and the census in claim `5800589054` found every path clear. PR objectstack-ai#18608 (squash `681ebe4246`) already discharged the earlier ruling's item 4 (the `check-generated.ts` `why` string). This PR does steps 1–3 of 丙 and leaves step 4's list in place. The witness ledger is the one exception, shrunk by three rows (see Deviations).⚠️ **Governed surfaces:** `AGENTS.md` and `docs/adr/**` (Tier H), plus `.claude/hooks/**` (Tier S, comments only). This PR stays **draft** and lands by the maintainer's hand. ## Step 3 first: the byte comparison decided the shape of this PR Both producers were run once over one built tree, `.cache/objectui-62597c588072` (objectui at pin `62597c588072636e9c30ea35b3d89b1e46fd765d`, built by `pnpm objectui:build`, `VERDICT command-exit 0`): ```text $ node scripts/gen-sdui-manifest-node.mjs # the new built-tree producer (this PR) ✓ wrote sdui.manifest.json (59 components, 85726 bytes, sha256 22c83c9ec701…) $ PLAYWRIGHT_BROWSERS_PATH=SCRATCH/pw bash scripts/gen-sdui-manifest.sh # the browser dump, as on main ✓ wrote 59 public blocks → packages/console/dist/sdui.manifest.json $ cmp packages/console/dist/sdui.manifest.json sdui.manifest.json; echo CMP_EXIT=$? CMP_EXIT=0 $ sha256sum packages/console/dist/sdui.manifest.json sdui.manifest.json 22c83c9ec70163559c2bd8f7b1613174d8660ad9949d15ed483a4189b7857c9a packages/console/dist/sdui.manifest.json 22c83c9ec70163559c2bd8f7b1613174d8660ad9949d15ed483a4189b7857c9a sdui.manifest.json ``` The outputs are **identical**, so the ruling's copy branch applies. `build-console.sh` now copies the tracked `sdui.manifest.json` into `packages/console/dist/`. `scripts/gen-sdui-manifest.sh`, `pnpm sdui:manifest` and cut-rc's Playwright install step are retired. The dump ran against the container's chromium 1194, exposed under the revision name that playwright 1.62.1 asks for through a scratch `PLAYWRIGHT_BROWSERS_PATH`. Nothing was installed. The dump script's trailing ratchet did not run: it is guarded on the baseline file, which this branch had already deleted, and that guard sits after the dump wrote its file. ## Step 1: M1 is the standing producer - **`scripts/gen-sdui-manifest-node.mjs`** takes no arguments. - It derives the modules root `.cache/objectui-SHA12/apps/console` from `.objectui-sha`. - It refuses to run, with `pnpm objectui:build` as the remedy, when the tree is missing, when the tree's HEAD is not the pin, or when the tree is not built (`apps/console/node_modules/@object-ui/core/dist/index.js` absent). It also refuses any argument, so the retired `--objectui-version` and `--modules-root` fail loudly instead of being ignored. - The temp-npm-install default is deleted. - The runner file is written to its own `mkdtemp` dir and removed afterwards. A resolve hook re-anchors bare specifiers to the modules root, so module resolution is unchanged and nothing lands in the build tree. Measured: 0 runner files in `apps/console`, 0 leftover temp dirs. - Output is deterministic: two runs, `cmp` identical. - **`scripts/sdui-manifest.record.json`** now records `source: built-tree`, `modulesRoot` and `objectuiWorkspaceVersion` (read from the built `@object-ui/core/package.json`), and its `//` block is rewritten. - **`scripts/check-sdui-manifest.mjs`** is re-keyed. - The presence check now requires `source` (it must equal `built-tree`), `modulesRoot` and `objectuiWorkspaceVersion`. - Check 4 compares `objectuiWorkspaceVersion`, and the header prose and every remedy line name `pnpm objectui:build && node scripts/gen-sdui-manifest-node.mjs`. - The self-test seed writes the new keys. One new row, `a record from the retired npm-install route is RED`, raises the floor to 12. - **npm-route prose rewritten** in: the generator header (the dead-citation fact of objectstack-ai#18627 is restated without a number), the record's `//` block, `build-console.sh`'s trailing reminder, the `AGENTS.md` pin-move paragraph (located by content), `docs/releases-maintenance.md` (the "After the pin moves" section, the pin-policy step 4 and the rc-cut step 2), `scripts/bump-objectui.sh` (header, NEXT STEP text and the not-on-main warning) and the `lint.yml` comment on the `check-sdui-manifest` step. - **Artefact regenerated at the pin:** 57 → **59** components (`box` and `object-tree` added), 66,910 → **85,726** bytes, sha256 `49211fee7792…` → `22c83c9ec701…`. - 19 components differ in their input-name set: 38 names appear only in the new artefact and 3 only in the old. - `dataSource` is now on 15 components (it was on 0). - `actionType` replaces `type` on `action:button` and `action:icon`. - `flex.isContainer` is now `true`. - `dashboard.refreshInterval` became `refreshIntervalSeconds`. - The rest are `object-kanban`/`object-calendar` inputs, plus `text.align` and `text.variant`. ## Step 2: the parity ratchet retires Removed: `packages/spec/scripts/check-react-blocks-declaration-parity.ts`, its test, `packages/spec/react-declaration-parity.baseline.json`, the gate's only helper `packages/spec/scripts/manifest-prescription.ts` (the two deleted files were its only importers), the `check:react-declaration-parity` script, the `lint.yml` step, and the cut-rc steps `Install a Playwright browser for the manifest dump` and `Declaration-parity ratchet at the committed pin (ADR-0082 D4)`. ADR-0082 decision 4 gains exactly one status line: 「retired 2026-09-18 by maintainer ruling on objectstack-ai#17735; the artefact stays for the CLI witness and the freshness gate」. That is an amendment, not a rewrite. Knock-on edits: - `check:generated`'s `EXTERNAL_INPUT_REQUIRED` bucket is now empty. The bucket and its reconciliation are kept, and the ledger test asserts `0 needing an external input`. - `published-projection-choke-point.test.ts` loses the deleted file's allowance row. - `gen-sdui-manifest.sh` goes with its three tests (`gen-sdui-manifest-cleanup`, `-collision` and `-write-target`), which are also removed from `vitest.repo-tests.json`. - `pnpm check:cross-package-test-inputs` reported two dispositions after the deletion, and both are applied. It reported `scripts/gen-sdui-manifest.sh` as an unheld glob for `create-objectstack`, so it comes out of the declaration and `turbo.json`. It reported that `check-generated-ledger.test.ts` no longer reads outside its package, so it comes out of the spec repo-tests list. ## Folded cards (ruling step 5) objectstack-ai#18627 (dead citation in the generator header), objectstack-ai#18633 (`releases-maintenance.md` clause and the instruction that caused the version skew) and objectstack-ai#18632 (the parity header's 「dumped from」 sentence) are folded here. All three are already closed as not planned, each with a pointer to this card, so there is nothing further to close. objectstack-ai#18407 stays open, and it is not addressed here. **objectstack-ai#14490 re-measure reading:** the regenerated artefact has `actionType` on `action:button` and `action:icon`, and neither block has an input named `type`. The artefact also contains `object-tree` now. ## Changesets - `skip-changeset` is the ruling's route for the scripts and the ADR line. - Because step 3's copy landed, this PR adds `.changeset/sdui-manifest-one-producer.md` (`@objectstack/console: patch`). - Which labels to apply is the seat's call. I wrote none.⚠️ **Premise correction for the changeset.** Ruling step 6 describes the dist as gaining 「a file it already shipped from the browser dump」. Measured, that is false. The published `@objectstack/console` 17.0.0, 17.3.0 and 17.4.0 tarballs contain **0** `sdui.manifest.json` (control: `package/dist/index.html` 1 each). `pnpm run release` re-runs `build-console.sh`, which recreates `dist/` from scratch, so the RC cut's copy never reached a tarball. The changeset states that. It also states that the console's `exports` map (`./package.json` only) keeps the file unreachable through `exports` for now. ## Deviations, and why 1. **`packages/lint/src/sdui-jsx-baseline.json` is shrunk by 3 rows**, although the dispatch listed it as untouched. With the regenerated manifest, `flex` declares `isContainer`, so the 32 `jsx-not-a-container` warnings no longer fire. The witness test (unedited) fails with 「STALE ledger rows … delete these rows … in this same PR」. The rows were deleted, none was added, and no count was raised, which is the ledger's own shrink-only rule. The ruling's step 1 regeneration forces this. 2. **Comment-only edits outside the claimed file surface**, made because the dispatch asked for no dangling reference: - `.claude/hooks/guard-process-kill.sh` and its selftest said `pgrep -s` teardown is "live in two tracked scripts", one of which this PR deletes. - `scripts/pm/os-verify-lock.sh`, `scripts/publish-smoke.sh`, `scripts/check-sdui-lockstep.mjs`, `scripts/check-pnpm-filter-targets.mjs` and `scripts/pnpm-filter-targets.mjs` (the `FOREIGN_SCOPES` reason string). - `packages/spec/src/ui/react-blocks.ts` (a line comment naming the deleted baseline). - `docs/audits/2026-06-react-blocks-conformance.md` (a retirement note above its run instructions). 3. `scripts/objectui-changeset-digest.mjs`'s self-test asserted that the bump prints `pnpm sdui:manifest`. It now asserts the bump prints `node scripts/gen-sdui-manifest-node.mjs`, `pnpm objectui:build` and `NEXT STEP`. ## References kept on purpose (history, not pointers) - `packages/spec/CHANGELOG.md` (release-owned). - ADR-0082's body and addenda (amendment only). - `docs/protocol-upgrade-guide.md`, and the `packages/spec/src` narratives in `component.zod.ts` (×3), `conversions/registry.ts`, `migrations/registry.ts` and `retired-keys/17.ui__RecordDetailsProps__layout.ts`. These explain why a past gate stayed green. - `docs/audits/...` (dated record). - Past-tense comments in `publish-smoke.sh`, `publish-smoke-port-collision.test.ts`, `scaffold-e2e-boot-probe.test.ts` and `lib/docs-import-surface.ts`. - Fixture strings in `scripts/check-agent-test-spelling.mjs` and `scripts/pm/ci-failure.mjs`. ## Acceptance notes - `component.zod.ts` still has one forward-looking sentence: the `check:react-declaration-parity` gate 「carries the spec↔objectui parity burden going forward」. It is TSDoc on published spec source, so it was left for the spec seat. - The witness test's title still says 「57-component public tier」. The test is unedited per the dispatch, and its assertion reads `length > 0`. ## Local verification All results below were taken on head `b7d0b3693a`, the final commit, after `git rev-parse --short HEAD`. - **Gate union:** - `node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands` derived 155 families. - All 155 were run, each with its exit code recorded before any pipe, and **all 155 exited 0**. That includes `check:pm-dispatch-gates` (1905 cases, run detached because it exceeds the foreground cap), plus `check:dual-build-cjs-loads`, `check:lean-entry-closure` and `check:type-check-debt` after a full `turbo run build --filter='./packages/*' --filter='./packages/*/*'` (72/72 tasks). - Reconciliation with `--ran` exited 0: 「155 derived, 155 run, 0 NOT-MEASURED, 0 UNRUN」. - NOT MEASURED, as the derivation prints them: the 10 workflow-valued families, the six CI jobs scheduled by these paths (Test Core, Temporal Conformance, Dogfood Regression Gate, Dogfood Verify CLI, Build Core, Console Pin Gate), and the workspace, examples and downstream type-check programs. These belong to CI. - **Lint:** eslint narrowed to the 12 changed lintable files, `--no-inline-config --format json`. - The JSON reports 12 files, 0 errors and 0 warnings. - This narrowing is safe because `eslint.config.mjs` enables no type-aware linting (no `parserOptions.project`), and nothing imports a deleted file. So no untouched file's verdict can move. The repo-wide `pnpm lint` belongs to CI. - Tests: - `@objectstack/lint` full `vitest run`: 108 files, 4121 tests passed. - spec targeted run (`check-generated-ledger`, `published-projection-choke-point`, `publish-smoke-port-collision`, `publish-smoke-boot-failure`): 4 files, 38 tests passed. - `@objectstack/vitest-filter-preflight` `config-wiring-sweep.test.ts`: 65 passed. - `@objectstack/spec typecheck` (src, scripts and test layer): exit 0. - Self-tests: `bump-objectui.selftest.sh` 20/20, `guard-process-kill.selftest.sh` 69/69, `os-verify-lock.sh --self-test` pass, `check-sdui-manifest.mjs --self-test` 12 cases. - Gate at the pin, with the objectui oracle: `node scripts/check-sdui-manifest.mjs --require-objectui` exit 0, reporting 「@object-ui 17.6.0 is the version objectui 62597c588072… declares」. - Ablation (one-shot, restored byte-exact by `scripts/ablation-replace.mjs`): with the re-key reverted to `['objectuiSha', 'sha256', 'components']`, the self-test reds on exactly the new row (「a record from the retired npm-install route is RED — expected RED, got GREEN」, exit 1). The restore leaves the blob equal to HEAD `b6484613ce99` and `git diff HEAD` empty. - Generator refusals, probed on a scratch copy (each exit 1, nothing written): an argument, no tree, a tree at the wrong HEAD, and a tree at the pin but not built. - `build-console.sh`'s new block was exercised on fixtures: fresh (copied, ✓ line), stale record pin (copied, ⚠ with the regeneration step) and missing artefact (exit 1). A full `pnpm objectui:build` on this branch's first commit also passed; that run's ending came before the copy block existed. ## 维护者速读(草稿) **改了什么** —— `sdui.manifest.json` 只剩一个生产者:`gen-sdui-manifest-node.mjs` 直接读 pin 上已构建好的 objectui 树,不再从 npm 装旧包。声明对齐门禁(ADR-0082 D4)和浏览器 dump 一起退役。console 构建把这份受跟踪的 manifest 原样拷进 dist。 **为什么改** —— 裁决 丙。实测两个生产者在同一棵已构建树上逐字节相同(`cmp` 退出码 0),所以浏览器那一路没有存在的必要。manifest 重新生成后,缺的 `dataSource`、`actionType` 等 38 个输入全部回来了。 **风险与代价(含回滚)** —— 以后升 pin 要先 `pnpm objectui:build`(约 10 分钟),再跑生成器。每个 PR 的门禁照旧离线,不变。console 包会第一次真的带上这个文件:此前发布的 17.0.0、17.3.0、17.4.0 都没有。但包的 `exports` 只导出 `./package.json`,CLI 现在还读不到它,所以对用户没有行为变化。回滚就是 revert 这个 PR。 **席位意见** —— **你要做的** —— 审阅后亲手合并(治理面:AGENTS.md、ADR)。 --- _Generated by [Claude Code](https://claude.ai/code/session_013RDBh5DqXd2xnLwvHLgLFr)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
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