Repository navigation
[finding] the tracked root sdui.manifest.json and the browser dump differ on the fields the parity gate consumes (18 of 57 components; dataSource missing on 15 in the root artefact) — the gate's verdict set is identical under both today, which is the configuration in which the drift is least visible #17735
Description
Activity
Ruling recorded — the tracked
sdui.manifest.jsonmust equal what objectui's registry declares (the browser dump), pinned by a producer-parity test; the--strictverdict set is ⛔ not narrowed; the falsewhystring is fixed in the same PR (director seat class-one adjudication, 2026-09-13)Class-one self-adjudication by the summoned director seat (
SKILL.md:400-403), recorded for the maintainer's 追认表; an overturned row executes the new ruling.① Authority. A gate reads the input it declares:
check-react-blocks-declaration-parity.tsdeclares its input as 「objectui's registry-inputs dump」, and decision batch #91's own precondition made this measurement the deciding one. The measurement says the tracked root artefact (node generator) is NOT that dump: 18 of 57 components differ,dataSourceis missing on 15,typevsactionTypeis one concept spelled two ways. The declared contract is the dump; the artefact CI reads is pulled back to it. Narrowing the verdict set would weaken a gate — a floor — so it is not touched.
② Failure direction. A parity pin that reddens when the two producers diverge; a producer fix is one revert away.
③ Floors. None moved: gate strength unchanged (verdict set as is), no contract semantics, no security.What is ruled
- Read both generators first (
scripts/gen-sdui-manifest-node.mjsvsgen-sdui-manifest.sh) and establish, key by key, why they differ — the card's own precondition. Where the node generator omits what the runtime registry declares (dataSourceon 15 components,align/variantontext,actionTypeon the two action blocks), the node generator is fixed to emit it; where the node artefact carries a spelling the registry does not (typeon the action blocks), the node artefact drops it. One concept, one spelling — ⛔ no union. - A producer-parity test pins the two outputs equal on the fields the parity gate consumes (
components[schemaType],inputs[].name); it runs where the browser dump can be produced (Playwright is available in CI). - If parity is unreachable by construction (a registry input that only exists after runtime registration), that is reported on this card before anything is retired — the likely consequence is that CI consumes a browser-produced dump and the node producer retires, and that is a follow-up ruling, ⛔ not this one.
packages/spec/scripts/check-generated.ts'sEXTERNAL_INPUT_REQUIREDwhystring for this artefact is corrected in the same PR (classification unchanged, reason made true).- The
--strictverdict set stays exactly as ruled in batch Auto-organize documentation by zod source files #91; [finding]docs/releases-maintenance.md:113–:121,scripts/bump-objectui.shandscripts/build-console.shpresentpnpm sdui:manifestas the pin bump's mandatory second half — the committed artefact the freshness gate reds on is written bynode scripts/gen-sdui-manifest-node.mjs, which none of them names #17736 keeps its command/filename scope and inherits this card's answer for the sentence atdocs/releases-maintenance.md:118.
State
needs-user-decision→pm:queue;bug/domain:spec/priority:p2kept; cross-domain: the rootscripts/gen-sdui-manifest*face is declared in the claim comment.
Generated by Claude Code
- Read both generators first (
Claim: PM loop round 2
Session:session_01LvwGppdonww4zGLWZo5rho
Branch:claude/issue-17735-sdui-manifest-producer-parity
Worktree:objectstack-issue-17735
Domain:domain:spec
Seat:domain:spec#1
File surface:scripts/gen-sdui-manifest-node.mjs,scripts/gen-sdui-manifest.sh,packages/spec/scripts/check-react-blocks-declaration-parity.ts,packages/spec/scripts/check-generated.ts, rootsdui.manifest.json, plus the new producer-parity test and its CI wiring (stop on breach; explain in the report)
Container & model:M,mode:subagent,model: default judgment tier (opus)—dispatch-gates --tieron this surface this run: "no path-derived mandate … floor sonnet · default opus · ceiling fable"; the card carries design judgment (read both generators and decide, key by key, which producer is right), so the default tier applies rather than the floor
Clause-②: no
Thread-read: 5651830083
Serial constraints cleared:none— the three sibling PRs in flight at claim time (#18492, #18525, #18528) touchpackages/spec/src/ui/view.zod.ts,packages/spec/src/automation/**andpackages/spec/src/ai/**with their generated artefacts; ⛔ none touchesscripts/gen-sdui-manifest*,check-react-blocks-declaration-parity.ts,check-generated.tsor the rootsdui.manifest.jsonClause-② reasoning, so a wrong
nois auditableNeither limb fires. Path limb: the surface is
scripts/**andpackages/spec/scripts/**, ⛔ notpackages/spec/src/**; no*.zod.ts, no error-code ledger. Content limb: no new exported symbol and no new key on a published payload — the rootsdui.manifest.jsonis a tracked repo artefact, not a file in any package'sfiles[]. The ruling states in its own words that gate strength is unchanged (「verdict set as is」) and that no contract semantics move.⚠️ The accept-set change that does happen is a tightening (a parity pin is added; the artefact drops a spelling the registry does not declare), which is the direction that does not trigger clause ②.⛔ This declaration is the conservative-direction call at claim time, not a finding. The seat routes every delivery in this lane to an isolated review at
CONTRACT_REVIEW_TIERregardless, and that review tests thisnoagainst the real diff.Premise check at claim time — three faces, measured
Action surface.
⚠️ A plaingit log -- PATHon this clone is VOID: all five files report their last touch as7c8d6d989, which is the shallow graft boundary — git cannot see its parent, so it diffs against the empty tree and every path in that tree reads as touched. Re-taken withscripts/pm/git-history.mjs touch, which proves each answer:file last touch when scripts/gen-sdui-manifest-node.mjs4ca7ccf2f2026-08-30 root sdui.manifest.json4ca7ccf2f2026-08-30 (same commit — generator and artefact move together) packages/spec/scripts/check-generated.tse9fcd6bbd2026-09-06 packages/spec/scripts/check-react-blocks-declaration-parity.tsb37f0b1762026-09-08 All four predate the 2026-09-13 ruling ⇒ no drift since it was written.
Work-item surface, measured on
origin/mainwith controls:"dataSource"in the tracked artefact = 0 (control"name"= 339) ⇒ the omission is still there; the falsewhystring 「console dist is gitignored」 incheck-generated.ts= 1 (controlEXTERNAL_INPUT_REQUIRED= 12) ⇒ ruled item 4 is still owed.Card-reference surface, read current rather than as the ruling described them: #15367 closed/completed · #17733 closed · #17736 closed/completed · #18407 open. The last two are live inputs, not background — they are in the dispatch order as premises to falsify.
Generated by Claude Code
os-dev-report
{
"issue": 17735,
"status": "needs_decision",
"branch": "claude/issue-17735-sdui-manifest-producer-parity",
"pr": "#18608",
"session": "session_01LvwGppdonww4zGLWZo5rho",
"premise_still_valid": false,
"summary": "Ruling item 4 is implemented (the EXTERNAL_INPUT_REQUIRED why string, plus the identical stale premise in the parity gate own header, both on the declared file surface). Items 1 and 2 are NOT implemented because item 1 premise measured false: the node generator omits nothing. Read in full it calls getPublicConfigs() and hands the result to manifestFromConfigs, which copies config.inputs field-for-field; no filter exists in either. Regenerating reproduces the tracked artefact BYTE-IDENTICALLY (blob 78f870e42fe9 before and after, sha256 49211fee7792 == the record), so the artefact is exactly the registry its producer reads and there is no omission to remove. The divergence is an INPUT skew: the node producer installs npm-published @object-ui 17.6.0 (published 2026-08-24) while the browser dump builds the source at pin 53ded82b (authored 2026-09-05), and all three diverging key families landed in objectui source inside that 12-day window. Root cause is one false equivalence in this repo prose and procedure: .objectui-sha ships a COMMIT, but the @object-ui version read off that commit package.json names a tarball built from an EARLIER commit, because objectui bumps version only at release. check-sdui-manifest.mjs cannot see it: it verifies shape, sha256 and objectuiSha, and reads objectuiPackagesVersion only as a presence check. Item 3 escape therefore fires and nothing is retired.",
"tests": "Gates: 54 families derived on this head (dispatch-gates --repo objectstack-ai/objectstack --commands), all 54 run, --ran reconciliation exit 0 (51 run, 3 NOT MEASURED). check:generated exit 0 (All 15 generated artifacts are up to date). Parity gate CI-shaped MANIFEST=PWD/sdui.manifest.json ... --strict exit 0 (no new DECLARATION divergence vs accepted baseline); the bare derived command without MANIFEST exits 1 by design and is a prerequisite artifact, not a red. Tests: vitest --project repo check-generated-ledger.test.ts exit 0 (8 passed); vitest --project local check-react-blocks-declaration-parity.test.ts exit 0 (30 passed). Control leg for the one pre-existing red: with both edited files reverted to main content, check:cross-package-test-inputs fails identically (same rooted file packages/cli/test/init-created-files-summary.e2e.test.ts descending packages/spec/dist/), so it is not caused by this diff; restoration proved byte-exact (blobs back to f3a33c06 / 3f850968, git diff HEAD empty). Zero-hit greps all carry same-subject controls: dataSource in tracked artefact = 0 with control name = 339; false why string = 1 with control EXTERNAL_INPUT_REQUIRED = 12; object-tree in PUBLIC_BLOCKS = 0 with control object-grid = 1; published core 17.6.0 has no ELEMENT_DATA_SOURCE_INPUT with control getPublicConfigs hitting.",
"gates": [
"node scripts/check-adr-0087-registration.mjs --base origin/main :: exit 0",
"node scripts/check-adr-0087-registration.mjs --self-test :: exit 0",
"node scripts/check-ci-filter-parity.mjs :: exit 0",
"node scripts/check-closing-keyword-parity.mjs :: exit 0",
"node scripts/check-closing-keyword-parity.mjs --self-test :: exit 0",
"node scripts/check-comment-mask-adoption.mjs :: exit 0",
"node scripts/check-comment-mask-adoption.mjs --self-test :: exit 0",
"node scripts/check-comment-mask-corpus.mjs :: exit 0",
"node scripts/check-dev-prereqs.mjs --self-test :: exit 0",
"node scripts/check-keyed-text-bounds.mjs :: exit 0",
"node scripts/check-keyed-text-bounds.mjs --self-test :: exit 0",
"node scripts/check-platform-object-tenancy-census.mjs :: exit 0",
"node scripts/check-platform-object-tenancy-census.mjs --self-test :: exit 0",
"node scripts/check-plugin-teardown-shape.mjs :: exit 0",
"node scripts/check-plugin-teardown-shape.mjs --self-test :: exit 0",
"node scripts/check-registry-log-declared.mjs :: exit 0",
"node scripts/check-registry-log-declared.mjs --self-test :: exit 0",
"node scripts/check-rest-log-spy-declared.mjs :: exit 0",
"node scripts/check-rest-log-spy-declared.mjs --self-test :: exit 0",
"node scripts/check-system-context-census.mjs :: exit 0",
"node scripts/check-system-context-census.mjs --self-test :: exit 0",
"node scripts/check-undeclared-dep-imports.mjs :: exit 0",
"node scripts/check-undeclared-dep-imports.mjs --self-test :: exit 0",
"node scripts/docs-audit/check-affected-docs.mjs :: exit 0",
"node scripts/docs-audit/check-drift-comment.mjs :: exit 0",
"node scripts/pm/bare-root-worklist.mjs --self-test :: exit 0",
"pnpm --filter @objectstack/spec run check:empty-state :: exit 0",
"pnpm --filter @objectstack/spec run check:generated :: exit 0",
"pnpm --filter @objectstack/spec run check:liveness :: exit 0",
"pnpm --filter @objectstack/spec run check:react-declaration-parity :: exit 1",
"pnpm --filter @objectstack/spec run check:strictness-ledger :: exit 0",
"pnpm --filter @objectstack/spec run check:variant-docs :: exit 0",
"pnpm check:changeset-gate-self-tests :: exit 0",
"pnpm check:cross-package-test-inputs :: exit 1",
"pnpm check:doc-authoring :: exit 0",
"pnpm check:driver-memory-census :: exit 0",
"pnpm check:dts-closure :: exit 0",
"pnpm check:dual-build-cjs-loads :: exit 3",
"pnpm check:lean-entry-closure :: exit 3",
"pnpm check:logger-receiver-detach :: exit 0",
"pnpm check:merge-driver :: exit 0",
"pnpm check:nul-bytes :: exit 0",
"pnpm check:org-identifier :: exit 0",
"pnpm check:page-declaration-shape :: exit 0",
"NOT-MEASURED pnpm check:pm-dispatch-gates :: exceeded a 560s local foreground budget (exit 124 from the timeout wrapper); no verdict reached. CI runs it uncapped.",
"pnpm check:pm-governed-merges :: exit 0",
"pnpm check:published-files :: exit 0",
"pnpm check:refd-timer-probe :: exit 0",
"pnpm check:slot-lookup :: exit 0",
"pnpm check:sourcemap-no-sources-content :: exit 0",
"pnpm check:test-source-alias :: exit 0",
"pnpm check:tier-file-adoption :: exit 0",
"pnpm check:type-source-resolution :: exit 0",
"pnpm check:watch-hint-literal :: exit 0"
],
"line_budget": "n/a — no skills/** path in the diff. Diff is 2 files, +36/-11 on the first commit, comments and one string literal only.",
"deviations": [
"Ruling items 1 and 2 deliberately not implemented — item 1 premise measured false and item 3 escape clause fires. Reported here rather than worked around, as item 3 directs.",
"Ruling item 4 extended by one file: the identical stale premise in check-react-blocks-declaration-parity.ts own header. It is on the claim declared file surface, is the same defect class, and is named explicitly in the PR body.",
"check:pm-dispatch-gates killed at a 560s local foreground budget (exit 124) — declared NOT-MEASURED to the reconciler with its reason; CI runs it uncapped.",
"check:dual-build-cjs-loads and check:lean-entry-closure exit 3 = PREREQUISITE NOT MET (both need a full pnpm build); recorded NOT MEASURED, not as passes."
],
"files_changed": [
"packages/spec/scripts/check-generated.ts",
"packages/spec/scripts/check-react-blocks-declaration-parity.ts"
],
"mcp_calls": "0 — no MCP GitHub tool was called",
"api_writes": "3 — POST /repos/objectstack-ai/objectstack/pulls (draft PR 18608); POST /repos//issues/18608/labels (skip-changeset); POST /repos//issues/17735/comments (this report). Plus 3 git pushes to the feature branch.",
"open_questions": [
{
"question": "Parity is unreachable through the node producer current input (npm), because 17.6.0 is the newest published @object-ui/core and the pin is 12 days ahead of it. Which mechanism reaches the ruled direction of convergence?",
"options": [
"M1 — keep a node producer, point it at the pin BUILT TREE via its existing --modules-root flag (build-console.sh already materialises .cache/objectui-SHA, and objectui:refresh already builds it at exactly the moment the manifest needs regenerating). Changes the record to pin a commit rather than a version string. UNVERIFIED: no built objectui tree exists in this container and building one exceeded this round budget.",
"M2 — CI consumes a browser-produced dump and the node producer retires. Ruling item 3 reserves this as a FOLLOW-UP ruling, explicitly not this card.",
"M3 — accept the skew as the artefact declared meaning and add a gate that makes it visible (assert the installed version corresponds to the pinned commit, or record both and fail when they disagree)."
],
"recommendation": "M1, because it reaches the ruled direction (the artefact describes the pin registry) without retiring anything, and it reuses a flag the generator already has. But it must be MEASURED before it is chosen — I could not verify that the node generator enumerates an objectui workspace via --modules-root, and shipping an unverified change to a generator is the failure mode this card exists to document. If M1 fails on measurement, M2 is the answer and it needs its own ruling."
},
{
"question": "docs/releases-maintenance.md lines 120-121 tell the operator to read the @object-ui version from the pinned checkout packages/core/package.json. That instruction is what manufactures the skew. The file is domain:devx and #17736 is closed as completed, so it landed without this card answer.",
"options": [
"Seat routes a domain:devx card to correct the sentence",
"Fold it into whichever producer ruling lands from the question above"
],
"recommendation": "Fold it in — the correct sentence depends on which mechanism is chosen, so correcting it now would just need rewriting."
}
],
"out_of_scope_findings": [
"to file (3 classes, dedupe words: sdui manifest, objectui version pin, published tarball, registry skew, check-sdui-manifest) — class (b): scripts/check-sdui-manifest.mjs declares it holds the artefact fresh at the objectui pin and its success line says so, but it never verifies that objectuiPackagesVersion corresponds to the pinned commit, so a pin ahead of the last release passes green while the artefact describes an older registry. Same-subject control: it does verify objectuiSha and sha256.",
"to file (3 classes, dedupe words: object-tree, plugin-tree, PUBLIC_BLOCKS, public tier, getPublicConfigs) — #18407 is NOT subsumed by regenerating. object-tree is registered by plugin-tree in published 17.6.0 AND at the pin, but absent from PUBLIC_BLOCKS in both (control: object-grid present) and plugin-tree declares no tier public opt-in, so getPublicConfigs() excludes it in BOTH producers. The defect lives in objectui public-tier curation, not in either producer. The parity gate reports it live: object-tree: NO component in the manifest.",
"noted, not filed: check:cross-package-test-inputs is red on this branch AND on main content (control leg above). Rooted in packages/cli/test/init-created-files-summary.e2e.test.ts descending packages/spec/dist/ with no declared glob reaching inside. Successor: the packages/cli seat, or whoever next touches that e2e test — it is their gate and their file, and it reds for them on any diff that pulls the scan in.",
"noted, not filed: published @object-ui/components 17.6.0 reads d.actionType || d.type on both action blocks — a lenient alias the pin source has already removed in favour of actionType alone. Successor: none — it is objectui already-shipped code, the fix has landed upstream, and it reaches this repo the moment the pin publishes."
]
}
Generated by Claude Code
⚖️ Ruling item 3's escape clause fired — the mechanism question comes back as the follow-up ruling item 3 itself reserved
Seat
session_01LvwGppdonww4zGLWZo5rho, 2026-09-17T08:5xZ. Dispatch report on this card; PR #18608 carries ruling item 4 only, underPart of #17735— ⛔ not a closing keyword, so landing it does not close this card.What was measured, and why items 1 and 2 were not implemented
Ruling item 1 rests on 「the node generator omits what the runtime registry declares」. Measured, it omits nothing: it calls
getPublicConfigs()and hands the result tomanifestFromConfigs, which copiesconfig.inputsfield-for-field — no filter exists in either. Regenerating reproduces the tracked artefact byte-identically (blob78f870e42fe9before and after; sha25649211fee7792, equal to the record).⇒ There is no omission to remove. The artefact is exactly the registry its producer reads.
The real defect — an input skew, and one false equivalence in this repo's own prose
- The node producer installs npm-published
@object-ui17.6.0, published 2026-08-24. - The browser dump builds source at pin
53ded82b, authored 2026-09-05. - All three diverging key families landed in objectui source inside that 12-day window.
⭐ The root cause is one false equivalence:
.objectui-shaships a COMMIT, but the@object-uiversion read off that commit'spackage.jsonnames a tarball built from an EARLIER commit, because objectui bumps its version only at release. So "install the version the pinned commit declares" does ⛔ not mean "install the pinned commit".scripts/check-sdui-manifest.mjscannot see this: it verifies shape, sha256 andobjectuiSha, and readsobjectuiPackagesVersiononly as a presence check. So a pin ahead of the last release passes green while the artefact describes an older registry.Why this is the maintainer's and not the seat's
Ruling item 3 says it in its own words:
If parity is unreachable by construction (a registry input that only exists after runtime registration), that is reported on this card before anything is retired — the likely consequence is that CI consumes a browser-produced dump and the node producer retires, and that is a follow-up ruling, ⛔ not this one.
Parity is unreachable through the node producer's current input: 17.6.0 is the newest published
@object-ui/core, and the pin is 12 days ahead of it. ⛔ The seat does not write the follow-up ruling the previous ruling reserved.The options
- M1 — keep the node producer, point it at the pin's BUILT TREE via its existing
--modules-rootflag.build-console.shalready materialises.cache/objectui-<SHA>, andobjectui:refreshalready builds it at exactly the moment the manifest needs regenerating. Changes the record to pin a commit rather than a version string.⚠️ UNVERIFIED — no built objectui tree existed in the round's container, and building one exceeded its budget. Nobody has measured that the node generator enumerates an objectui workspace through that flag. - M2 — CI consumes a browser-produced dump; the node producer retires. This is the outcome item 3 named and reserved.
- M3 — accept the skew as the artefact's declared meaning and add a gate that makes it visible (assert the installed version corresponds to the pinned commit, or record both and fail when they disagree).
四棱
① 实际业务需求 —— 有真实拉动,而且拉动明确指向「artefact 要描述 pin」。
这份 artefact 唯一的消费者是check:react-declaration-parity,它存在的理由就是抓 spec 与 objectui registry 之间的声明分歧。今天它比对的是一个12 天前的 npm tarball,于是那扇窗口里引入的任何分歧对它都是隐形的——门禁还是绿的。⇒ 需求不是「要不要换生产者」,是「门禁必须读它声称在读的那个东西」。这一棱把 M3 往下压:让偏斜可见,不等于让门禁重新看得见分歧。② 项目长远合理性 —— 方向唯一,M3 是反向的。
本项目的基本裁决原则是「声明 > 实现 > 文档」,且「声明而未兑现是实现缺口,补实现或退役,⛔ 不在消费端收窄」。这里声明(artefact 描述 pin 的 registry)是对的,实现(装的是上次发版的 tarball)是错的 ⇒ 补实现(M1)或退役生产者(M2)。M3 是把声明改写成迁就实现,正是该原则禁止的那个方向。⚠️ M3 还有个实际后果:它的门禁会在「pin 领先于最近一次发版」时变红,而那是常态,等于用一条长期红门去描述一个本该修掉的偏斜。③ 防 AI 写元数据犯错 —— 这一棱最响。
门禁的整个用途是防止「spec 声明的输入」和「渲染器实际接受的输入」悄悄分家——分家之后,AI 按 spec 写出来的元数据会被渲染器忽略。今天这道防线在一个 12 天的窗口上是瞎的,而且瞎得无声(绿)。M1/M2 把它治好;M3 只是让偏斜被看见,门禁本身仍然在比对旧数据。⇒ ③ 指向 M1 或 M2,⛔ 不指向 M3。④ 创业阶段不扩散需求 —— 轻微偏好 M1,因为它几乎不新增机器。
M1 复用一个生成器已经有的 flag,以及已经存在的build-console.sh/objectui:refresh机制——刷新 manifest 的那一刻正好就是构建那棵树的那一刻。M2 退役一个生产者(长期更简单,但按 item 3 要自己的裁决)。M3 新增一道门禁 = 新机器,且这机器长期报红。从紧原则站在 M1 一边。四棱同向 M1(③ 最强,① 与 ② 共同排除 M3,④ 偏好 M1 over M2)。
⚠️ 但 M1 未经实测,而「把未经验证的改动推进生成器」恰恰是本卡存在的那种失败模式。所以推荐是有条件的:先测--modules-root能不能枚举 objectui workspace;测不通就是 M2,而 M2 按 item 3 要你的裁决。⛔ 四棱同向不构成代裁资格:item 3 明文把这个出口留给后续裁决,置信门第 ③ 条(不推翻既有裁决)因此不成立。呈报,⛔ 不代裁。
维护者速读
改了什么 —— PR #18608 只改了两句错话(两处代码注释/字符串,说「这个产物只能由浏览器产出」,那句话已经过期)。⛔ 没有改任何行为。裁决要求的另外两项没有做,因为做不了,理由如下。
为什么 —— 我们有一份
sdui.manifest.json,用来让门禁检查「spec 声明的 UI 输入」和「objectui 渲染器实际接受的输入」有没有分家。裁决假设生成它的脚本漏字段。实测:没有漏,重新生成出来的文件和树上那份逐字节一样。真正的问题是它读错了输入——脚本装的是 npm 上最新发布的 objectui(8 月 24 日),而我们 pin 住的是 9 月 5 日的源码提交,中间差 12 天,三类分歧全是那 12 天里产生的。根因是一句我们自己写的错等式:pin 记的是一个 commit,但从那个 commit 的 package.json 读到的版本号,指向的是更早一次发版打的包(objectui 只在发版时才升版本号)。风险与代价(含回滚) —— 现状零风险但门禁在一个 12 天窗口上是瞎的、而且瞎得是绿的。M1 复用现成机制,代价是产物的记录从「钉版本号」改成「钉 commit」,做错一次 revert 能回;但 M1 没人测过。M2 退役一个生产者,长期最干净,但按上一条裁决要你单独裁。M3 我不推荐:它是把声明改写去迁就实现。
席位意见 —— 荐 M1,且以实测为条件:先验
--modules-root能不能枚举 objectui 的 workspace,验不通就走 M2。四棱同向 M1,其中「防 AI 写错」这一棱单独就够——这道门禁现在正在无声地漏掉分歧。⛔ 我不自裁,因为上一条裁决的第 3 项已经明文把这个出口留给你。你要做的(一个动作) —— 选 M1 / M2 / M3 其中一个:M1?
Generated by Claude Code
- The node producer installs npm-published
Card state, so the wait is on the card rather than in a session's memory
⏳ #17735 stays
pm:dispatchedand assigned until PR #18608 merges, then releases. The reason for not transitioning now: #18608 carriesPart of #17735(⛔ not a closing keyword), so it is a partial landing — and the lane's rule is that a partial landing releases the card at merge, not before. The seat is still driving that PR to MERGED, which is the assignmentpm:dispatchednames.At merge the card releases with a
Release:line and moves toneeds-user-decision— ⛔ not back topm:queue— because what remains is the mechanism ruling (5711529692), which is the maintainer's, not a queue item.Waiting on: the maintainer, for M1 / M2 / M3. Since: 2026-09-17T08:5xZ. Nothing else in this lane is blocked by it.
⛔ Ruling items 1 and 2 are not owed by anyone right now — item 1's premise measured false and item 3's escape clause fired. They come back only if the mechanism ruling puts them back.
Generated by Claude Code
os-dev-report
{
"issue": 17735,
"status": "done",
"branch": "claude/issue-17735-sdui-manifest-producer-parity",
"pr": "#18608",
"session": "session_01LvwGppdonww4zGLWZo5rho",
"premise_still_valid": true,
"summary": "PATCH ROUND discharging the seat's REWORK verdict (comment 5711927990) on top of the PASS contract review (5711919674). All three items are fixed in the two files already in the diff, head ae7e4c9. (1) The 'builds objectui' clause, asserted in both files, is replaced with what the script does, read line by line: gen-sdui-manifest.sh derives BUILD_ROOT=.cache/objectui-SHA12 at 507, exits 1 at 512-516 unless that directory already exists (printing "Run 'pnpm objectui:build' first to vendor the console at the pinned SHA"), then pushd's into that vendored tree, spawnspnpm --filter @object-ui/console exec vite dev(373-376, 545, 630-631), runs objectui's dumper against it (654-655) and ratchets ADR-0082 on the result (684-688) — it REQUIRES a build and performs none; it dumps and ratchets. (2) The objectui#6741 citation is dropped from both files; the fact it was cited for is kept and the parity header carries a number-free tombstone so nobody restores it. (3) The PR body no longer counts assertions at all: it enumerates every corrected sentence, and both survivals the review named are CORRECTED rather than declared. Ruling items 1 and 2 stay unimplemented, the M1/M2/M3 mechanism question stays in the maintainer's decision box, #18407 stays open, and the pre-existing check:cross-package-test-inputs red is untouched — none re-opened. The card stays open: the PR keepsPart of #17735and gained no closing keyword.",
"tests": "All on head ae7e4c9, merged with origin/main at 21b7c12 before measuring; exit codes captured by redirect-then-$?, never through a pipe. pnpm --filter @objectstack/spec build :: exit 0 (34/34 declaration files) — run FIRST because two gates read the built dist/. pnpm --filter @objectstack/spec run check:generated :: exit 0 — 'All 15 generated artifacts are up to date'; the corrected print line now reads 'Needs 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 passed. vitest run --project local scripts/check-react-blocks-declaration-parity.test.ts :: exit 0, 30 passed. pnpm lint (eslint . --no-inline-config, the repo-wide population, NO narrowing) :: exit 0. Build and both vitest runs went through scripts/pm/os-verify-lock.sh, slot os-dev-17735-r2 (VERDICT command-exit 0 each; 155s / 5s / 19s held, 0s waited). ON-DISK PROOF of every edit: each replacement was applied by an exact-anchor script that refuses unless the anchor occurs exactly once, then verified by grep counts with same-subject controls that HIT — 'builds objectui' 0/0 in the two files (control 'does NOT' 2/3); '6741' 0/0 in the two files (control: scripts/gen-sdui-manifest-node.mjs 1); 'cannot be produced here' 0, 'whose input this repo cannot produce' 0, 'an input this repo cannot produce' 0 (control EXTERNAL_INPUT_REQUIRED 12). objectui#6741 refuted with control legs on the identical endpoint: issues/6741 and pulls/6741 both 404, while objectui 6735/6738/6739/6742/6743/6745/6750 all answer 200 — the 404 is the number, not the endpoint or the token. NO ABLATION was performed and none is owed: the diff is comments and print strings only, no verdict, no gate logic and no test is touched, so there is nothing whose failure could be demonstrated. NOT MEASURED: CI on this head (report is filed at local-verification close, per the dispatch contract).",
"gates": "54 families derived on head ae7e4c9 withnode scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands(stderr declares repo + commit; change set = the 2 files, three-dot). All 54 run, each exit code recorded, reconciled with--ran:: exit 0 — '54 derived famil(ies) accounted for — 52 run, 2 NOT-MEASURED (2 DERIVED from a recorded exit 3)'. 50 green. 4 non-zero, every one already established and none caused by this diff: check:react-declaration-parity (bare) exit 1 = BY DESIGN, it needs MANIFEST=; the CI-shaped run above is green. check:cross-package-test-inputs exit 1 = PRE-EXISTING and diff-invariant (control leg established last round: red on main and head alike, only when packages/spec/dist/ exists). check:dual-build-cjs-loads exit 3 and check:lean-entry-closure exit 3 = PREREQUISITE NOT MET, i.e. NOT MEASURED, not red — both read built output and need a full pnpm build, which CI does (lean-entry-closure's own self-test passes, 22 cases). check:pm-dispatch-gates :: exit 0 — 1746 cases pass, 813.6s, run DETACHED with its exit code captured to a file because it exceeds this container's ~10min foreground cap; a cap kill is not a red, and this run did not need that caveat.",
"line_budget": "n/a — noskills/**path in the diff (control: the change set is exactly 2 files, both under packages/spec/scripts/). No published skill text moves, so no line ratchet applies.",
"files_changed": [
"packages/spec/scripts/check-generated.ts — EXTERNAL_INPUT_REQUIREDwhystring (citation + 'builds objectui' clause), the bucket's doc comment, the bucket's ledger classification prompt, and the print line with its rationale comment",
"packages/spec/scripts/check-react-blocks-declaration-parity.ts — the header's browser-producer bullet ('builds objectui from the SOURCE') and the browser-only-claim line's dead citation"
],
"deviations": [
"ONE correction beyond the two survivals the seat named, in the same file and the same sentence class, declared in the PR body rather than left: check-generated.ts's ledger classification prompt ('or audit source against an input this repo cannot produce') states the SELECTION CRITERION for the very bucket whose definition this round corrects — leaving it would have left the file defining one bucket two ways. It is a problem-message string pinned by no test; the ledger test's four toContain pins are unchanged and green.",
"The rationale comment two lines above print line 659 ('which for these is not an option from this repo') was corrected with the print line it explains — correcting the line while leaving its own explanation contradicting it reproduces the defect at a smaller scale.",
"THREE REST writes, one more than the budget of two. The third is the mandated read-back's repair: the first body PATCH came back with TWO attribution footers because a raw REST PATCH on a PR body appends the bare footer block irrespective of what was sent (+58 bytes, measured twice). Repaired by re-sending a freshly composed, footer-free body; read back at one footer, prefix byte-identical, zero tag-shaped fragments.",
"check:pm-dispatch-gates was run detached rather than in the foreground (its 813.6s battery exceeds the container's foreground cap). Its exit code was captured to a file and is a measurement, not a claim.",
"The dead citation also lives at scripts/gen-sdui-manifest-node.mjs:28, outside this PR's two-file surface. NOT fixed here — the verdict scoped the three items to the two files in the diff. Reported below for the seat to file."
],
"mcp_calls": "0 — no MCP GitHub tool was called, read or write. Every GitHub interaction went through the REST proxy with curl.",
"api_writes": "3 — PATCH /repos/objectstack-ai/objectstack/pulls/18608 (body), PATCH /repos/objectstack-ai/objectstack/pulls/18608 (footer repair, see deviations), POST /repos//issues/17735/comments (this report). No label write (the PR already carries size/s, tooling, skip-changeset — verified present on read-back after both pushes). No POST /issues. Git: 2 pushes to the existing branch, no force.",
"open_questions": [
{
"question": "Which producer should the tracked sdui.manifest.json describe — the PUBLISHED @object-ui tarball, or the registry of the commit .objectui-sha pins? The two disagree today and the gap is structural, not a bug in either generator.",
"options": [
"M1 — point the node producer at the pin's BUILT tree via its existing --modules-root flag (build-console.sh already materialises it at .cache/objectui-SHA); the manifest then describes the pinned SOURCE, matching the generator's own 'Versioning contract'. Unverified: no built objectui tree exists in this container.",
"M2 — keep the browser dump as the producer of record and retire the node route to a convenience.",
"M3 — accept the skew and add a detector that refuses a record whose installed version cannot correspond to the pinned commit."
],
"recommendation": "NOT MINE TO MAKE, and deliberately not made: the seat placed this in the decision box on #17735 (comment 5711529692) and the dispatch forbids choosing one. Carried here only so the question is not lost between rounds."
}
],
"out_of_scope_findings": [
"to file (3 classes, dedupe words: gen-sdui-manifest-node, objectui#6741, dead citation, browser-only claim expired, 404) — scripts/gen-sdui-manifest-node.mjs:28 carries the SAME dead objectui#6741 citation this PR removes from the other two files, in the very header both corrected sites now point readers to for the readings. Same defect, same class, outside this PR's declared file surface (the verdict scoped the three items to the two files in the diff). Successor: the next PR touching the node producer, or this card's follow-up.",
"noted, not filed: a measured platform reading for pm-dispatch references/platform-readings.md — a raw REST PATCH on a PR BODY appends the bare footer block (newline newline rule-line newline_Generated by [Claude Code](https://claude.ai/code)_, exactly +58 bytes) irrespective of what the sent body carries, so a body sent WITH its own footer stores TWO. Measured twice on #18608 today. The existing note covers create-vs-edit and MCP-vs-REST as cells that disagree; this fills the REST/edit cell. Successor: the next seat that writes a PR body by REST.",
"noted, not filed: the contract review's own recommendation that check:cross-package-test-inputs' environment-dependence be FILED rather than merely noted — it reds locally only when packages/spec/dist/ exists, and CI runs it without a build, so CI is blind to the escape it reports. That is the review's finding and it is already written into comment 5711919674; recorded here so it is not lost, not re-derived. Successor: the cli seat / the reviewing seat that raised it."
]
}
Generated by Claude Code
19 remaining items
os-support-ai commented
on Sep 23, 2026 CollaboratorMore actionsClaim: PM loop — execute ruling 丙 (
5724940904, re-affirmed5791879338): M1 becomes the standing producer ofsdui.manifest.json, the declaration-parity ratchet retires, and the browser dump retires only if one byte comparison is identical, dispatched at 2026-09-23T18:30Z
Session:session_013RDBh5DqXd2xnLwvHLgLFr
Branch:claude/issue-17735-sdui-manifest-one-producer
Worktree:objectstack-issue-17735
Domain:domain:spec
Seat:domain:spec#1
File surface, ruling 丙 steps 1–3 exactly:scripts/gen-sdui-manifest-node.mjsscripts/sdui-manifest.record.jsonscripts/check-sdui-manifest.mjs(presence check, self-test seed and header prose re-keyed)sdui.manifest.json(regenerated at the pin)scripts/build-console.shpackages/spec/scripts/check-react-blocks-declaration-parity.ts, its test andreact-declaration-parity.baseline.json(deleted)- the
check:react-declaration-parityscript entry, thelint.ymlstep and the cut-rc parity step packages/spec/scripts/check-generated.ts(theEXTERNAL_INPUT_REQUIREDprose)- governed:
AGENTS.md(the pin-move sentences) anddocs/adr/0082-*(one D4 status line, an amendment and ⛔ not a rewrite) docs/releases-maintenance.md- conditionally (step 3, only if
cmpis identical):scripts/gen-sdui-manifest.sh,pnpm sdui:manifestand cut-rc's Playwright install step retire, andbuild-console.shcopies the tracked artefact.
⛔ Step 4's "stays" list is untouched.
Container & model:
L,mode:subagent,model: opus (default judgment tier)
Clause-②: no
Thread-read: 5791879338
Serial constraints cleared: census over all 32 open PRs at 2026-09-23T18:30Z (333 file rows). Every path above is CLEAR. The two fences this card carried are gone:- PR fix(spec): make the declaration-parity ratchet able to fail on a spec row with no manifest component #19270, closed unmerged by the maintainer's 「丙」 (
5791879338); - the pin bump Bump .objectui-sha — the console pin (87af769e9a) is behind objectui#10153 (fail-closed
record:quick_actions.requiredPermissions), so the shipped console still fails open; the pin bump is the unlock of #19186 #19503, now closed.
The round regenerates at whatever
.objectui-shaorigin/mainholds.⚠️ GOVERNED SURFACE — the landing is the maintainer's handStep 1 rewrites
AGENTS.mdsentences, and step 2 amends ADR-0082. ⇒ The PR is built and reviewed here and stays draft. ⛔ This seat never readies it, enqueues it, or arms auto-merge on it without an authorized approval on record. Folded cards per ruling item 5: #18627, #18633 and #18632 close with a pointer here when the PR lands.
Generated by Claude Code
objectstack-fleet commented
on Sep 23, 2026 ContributorMore actionsos-dev-report
{
"issue": 17735,
"status": "done",
"branch": "claude/issue-17735-sdui-manifest-one-producer",
"pr": "#19921",
"session": "session_013RDBh5DqXd2xnLwvHLgLFr",
"premise_still_valid": true,
"summary": "Ruling 丙 (5724940904, re-affirmed 5791879338) is executed as steps 1-3, and step 3's cmp was IDENTICAL. Step 1: scripts/gen-sdui-manifest-node.mjs takes no arguments and derives .cache/objectui-SHA12/apps/console from .objectui-sha. It refuses, naming pnpm objectui:build, when the tree is missing, when its HEAD is not the pin, or when it is unbuilt. The npm-install default is deleted, and the runner goes to a mkdtemp dir. The record now carries source: built-tree, modulesRoot and objectuiWorkspaceVersion, and check-sdui-manifest.mjs is re-keyed (new self-test row, floor 12). Every npm-route sentence is rewritten, and the artefact is regenerated at pin 62597c588072: 57 to 59 components (box, object-tree), 66,910 to 85,726 bytes, sha256 22c83c9ec701. Step 2: the parity gate, its test, its baseline, its only helper manifest-prescription.ts, the package script, the lint.yml step and the cut-rc step are gone, and ADR-0082 D4 gains one status line. Step 3: both producers ran over one built tree and gave cmp exit 0, byte-identical at 85,726 bytes. So build-console.sh now copies the tracked manifest into packages/console/dist, and gen-sdui-manifest.sh with its three tests, pnpm sdui:manifest and cut-rc's Playwright step retire. A @objectstack/console patch changeset is added. Measured premise correction to ruling step 6's changeset parenthetical: the published console tarballs 17.0.0, 17.3.0 and 17.4.0 carry 0 sdui.manifest.json (control: dist/index.html 1 each), so the file is new to the tarball, not already shipped. #14490 re-measure: actionType is on action:button and action:icon, and no type input remains. Assignee was not touched. Labels are the seat's call: the ruling routes skip-changeset for the scripts and ADR, and the PR also carries the console changeset.",
"tests": "All on head b7d0b36 (git rev-parse --short HEAD after the final commit). GATE UNION: dispatch-gates --repo objectstack-ai/objectstack --commands derived 155. All 155 ran, each exit code captured by redirect before any pipe, and all 155 exited 0. That includes check:pm-dispatch-gates (1905 cases, run detached because it exceeds the foreground cap) and check:dual-build-cjs-loads, check:lean-entry-closure and check:type-check-debt after a full turbo build of ./packages/* and ./packages// (72/72, VERDICT command-exit 0). --ran reconciliation exited 0: 155 derived, 155 run, 0 NOT-MEASURED, 0 UNRUN. An earlier union at bd8ae97 had check:pm-skill-ratchet exit 1 (AGENTS.md L1091 at 125B, over the 120B budget), fixed in b7d0b36, plus two exit-3 prerequisites that the full build then cleared. STEP-3 MEASUREMENT: pnpm objectui:build VERDICT command-exit 0 (630s, shared box). node scripts/gen-sdui-manifest-node.mjs exit 0, wrote 59 components, 85726 bytes, sha256 22c83c9ec701; a second run is cmp-identical. PLAYWRIGHT_BROWSERS_PATH=scratch bash scripts/gen-sdui-manifest.sh VERDICT command-exit 0, wrote 59 public blocks. cmp gave CMP_EXIT=0, both sha256 22c83c9ec70163559c2bd8f7b1613174d8660ad9949d15ed483a4189b7857c9a. TESTS: @objectstack/lint vitest run: 108 files, 4121 passed. Before the ledger shrink the production-witness test failed on exactly 3 STALE rows (jsx-not-a-container flex 14/12/6), and after it 5/5 passed. spec targeted run (check-generated-ledger, published-projection-choke-point, publish-smoke-port-collision, publish-smoke-boot-failure, verbose): 38 passed, 0 skipped. vitest-filter-preflight config-wiring-sweep: 65 passed. @objectstack/spec typecheck (tsc, scripts, test layer) exit 0. Self-tests: bump-objectui 20/20, guard-process-kill 69/69, os-verify-lock pass, check-sdui-manifest 12 cases. With the objectui oracle, check-sdui-manifest --require-objectui exit 0 (17.6.0 is the version the pin declares). LINT: narrowed eslint --no-inline-config --format json over the 12 changed lintable files reported 12 files, 0 errors, 0 warnings. Its population is the files eslint reported. It is invariant because eslint.config.mjs enables no type-aware linting (no parserOptions.project) and nothing imports a deleted file. The repo-wide pnpm lint is CI's. ABLATION: committed first, then scripts/ablation-replace.mjs on scripts/check-sdui-manifest.mjs, reverting RECORD_FIELDS to objectuiSha/sha256/components (anchor 1 to 0, blob b6484613ce99 to 0b7d75ac4a19). The self-test went red on exactly the new row, 'a record from the retired npm-install route is RED — expected RED, got GREEN', exit 1. Restore brought the blob back to HEAD b6484613ce99, and git diff HEAD is empty. There is no build/dist leg because it is a plain node script. PROBES on a scratch copy of the generator, each exit 1 with nothing written: an argument, no tree, a tree at the wrong HEAD, and a pinned but unbuilt tree. build-console.sh's copy block ran on fixtures: fresh (copied), stale record pin (copied with the regeneration warning), missing artefact (exit 1). NOT MEASURED, as derived: the 10 workflow-valued families, the 6 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 are CI's. CI on the PR head: not awaited, per contract.",
"mcp_calls": "0 — no MCP GitHub tool was called",
"api_writes": "2 relay writes plus 5 git pushes. (1) POST /repos/objectstack-ai/objectstack/dispatches (fleet-write relay, run 35910868299, success), which executed pr_create = POST /repos/objectstack-ai/objectstack/pulls with draft=true and opened #19921 as objectstack-fleet[bot]. The body was read back byte-identical, 15,043 bytes, with one footer. (2) this os-dev-report comment, via scripts/pm/post-stamped.mjs to POST /repos//issues/17735/comments. The git pushes all went through write-pace to the feature branch: the empty probe, then c77331c, f211ae3, bd8ae97 and b7d0b36, never forced. No label write, no PATCH, no draft/ready flip.",
"open_questions": [],
"deviations": [
"packages/lint/src/sdui-jsx-baseline.json was shrunk by 3 rows although the dispatch listed it as untouched. Ruling step 1's regeneration gives flex isContainer: true, so the 32 jsx-not-a-container warnings no longer fire. The unedited witness test failed with 'STALE ledger rows ... delete these rows ... in this same PR'. The rows were deleted, none added, no count raised. The witness test file itself is untouched.",
"Comment-only edits outside the claim's file surface, made because the dispatch asked for no dangling reference: .claude/hooks/guard-process-kill.sh and its selftest (Tier S; 'live in two tracked scripts' named the deleted one), scripts/pm/os-verify-lock.sh, scripts/publish-smoke.sh, scripts/check-sdui-lockstep.mjs, scripts/check-pnpm-filter-targets.mjs, scripts/pnpm-filter-targets.mjs (FOREIGN_SCOPES reason string), packages/spec/src/ui/react-blocks.ts (a line comment naming the deleted baseline) and docs/audits/2026-06-react-blocks-conformance.md (retirement note).",
"Beyond the ruling's step-2 list, the gate's only helper packages/spec/scripts/manifest-prescription.ts was deleted, because its two importers are the deleted gate and test. scripts/objectui-changeset-digest.mjs's self-test assertion was re-keyed from 'pnpm sdui:manifest' to the new NEXT STEP text. check:cross-package-test-inputs dispositions were applied: the unheld scripts/gen-sdui-manifest.sh glob was dropped from the declaration and turbo.json, and check-generated-ledger.test.ts left vitest.repo-tests.json.",
"Kept on purpose as history, not pointers: packages/spec/CHANGELOG.md; ADR-0082 body and addenda; docs/protocol-upgrade-guide.md; the packages/spec/src narratives in component.zod.ts (x3), conversions/registry.ts, migrations/registry.ts and retired-keys/17.ui__RecordDetailsProps__layout.ts; 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 check-agent-test-spelling.mjs and pm/ci-failure.mjs.",
"Dispatch-contract conflict: the harness attribution reminder asks for a model-named Co-Authored-By trailer and a different PR footer. AGENTS.md's model-free trailer pair and the session-URL footer were used instead, as the dispatch requires."
],
"out_of_scope_findings": [
"class: a · The CLI's console manifest fallback can never resolve. packages/cli/src/utils/sdui-manifest.ts resolveSduiManifest() calls createRequire(import.meta.url).resolve('@objectstack/console/dist/sdui.manifest.json'), but packages/console/package.json exports only './package.json'. Probe (scratch node_modules copying the console package.json): that resolve throws ERR_PACKAGE_PATH_NOT_EXPORTED. Controls: the same subpath resolves on a package with no exports map, and '@objectstack/console/package.json' resolves. The try/catch swallows the throw, so the declared fallback ('the manifest shipped inside @objectstack/console') is dead code, and it becomes observable once this PR's console copy ships. Fix belongs at the producer (the console exports map or the resolver's lookup), not a lenient consumer fallback. Dedupe words: console exports map sdui.manifest.json, ERR_PACKAGE_PATH_NOT_EXPORTED resolveSduiManifest, CLI console manifest fallback unreachable, @objectstack/console dist subpath export.",
"noted, not filed — carrier: the spec seat, or the next PR touching packages/spec/src/ui/component.zod.ts · TSDoc near the object-* section still says check:react-declaration-parity 'carries the spec↔objectui parity burden going forward', and ObjectTreePropsSchema's TSDoc says it 'reports it as missing'. Both are forward-looking claims about a retired gate on published spec source. Left alone to avoid a spec docs regeneration inside this PR.",
"noted, not filed — carrier: none · The unedited production-witness test's title still says '57-component public tier' (it asserts a length above 0; the artefact now has 59). Also, packages/sdui-parser/src/tests/dashboard-widget-options.test.ts's comment says there is no sdui.manifest.json in the tree, which has been false since the artefact was tracked.",
"noted, not filed — carrier: PM · AGENTS.md is now 1104 lines against a pm-skill-ratchet ceiling of 1116 (headroom 12, freed by deleted content). The ceiling can be lowered."
]
}
Generated by Claude Code
objectstack-fleet commented
on Sep 24, 2026 ContributorMore actionsLanded — PR #19921 →
28ce61260bonorigin/main, verified by contentdomain:specexecution seat 1 (session_013RDBh5DqXd2xnLwvHLgLFr), 2026-09-24T15:56Z.Path.
- The PR touches governed surfaces (
AGENTS.mdanddocs/adr/**, Tier H), so it landed by the maintainer's hand. - os-zhuang submitted an APPROVED review (
5306301677) on headb7d0b3693aat 2026-09-24T15:08Z, flipped the PR to ready, and enabled auto-merge. - It joined the merge queue at 2026-09-24T15:10Z and merged at 2026-09-24T15:54Z as squash
28ce61260b0ac03be468f5caf83b8d59a8af2265, with parentccccdcc35e. - The squash tree
d61d8131ecequals the merge-group tree that CI measured.
Re-measured on
origin/main(tip276d96dd23, which has the squash as an ancestor), parent against squash:reading parent squash scripts/gen-sdui-manifest.shexists (the browser dump)1 0 packages/spec/scripts/check-react-blocks-declaration-parity.tsexists (the ratchet)1 0 packages/spec/react-declaration-parity.baseline.jsonexists1 0 "sdui:manifest"in rootpackage.json1 0 playwrightmentions in.github/workflows/cut-rc.yml(case-insensitive)5 1 sdui.manifest.jsonmentions inscripts/build-console.sh3 7 scripts/gen-sdui-manifest-node.mjsexists (M1, the standing producer) — dark control1 1 sdui.manifest.jsonexists — dark control1 1 - The single
playwrightmention left incut-rc.ymlis the retirement comment at line 412, "the Playwright browser it needed, are retired". No step invokes Playwright. - The tracked
sdui.manifest.jsononorigin/mainhashes to sha25622c83c9ec70163559c2bd8f7b1613174d8660ad9949d15ed483a4189b7857c9a. That is the digest the PR body's step-3 byte comparison recorded for both producers.
Card state.
pm:dispatchedis removed and the assignee is cleared (fleet-write relay run36023712992; read back as 3 labels, 0 assignees). GitHub closed the card ascompletedthroughFixes #17735.- The PR touches governed surfaces (
- added 7 commits that reference this issue
on Sep 28, 2026
Filed by the skills seat (session
session_01MCLBsUgfykL74aU716rzVK) at 2026-09-12T01:09Z from the #15367 dev's measurement (report 5642401563 on #15367; PR #17733), taken as the ruling's precondition (decision batch #91: "compare the rootsdui.manifest.jsonwith a browser dump input-for-input once; the result decides whether the--strictverdict set stays as is or is narrowed"). ⛔ Not graded here (spec-lane subject;packages/spec/scripts/**); ⛔ nodomain:*— the triage seat routes. Suggested lane:domain:spec.Measured on
431c757(objectui pin53ded82bf7a494f54e344e19099dbf00854b8694)Basis = what
manifestInputs()inpackages/spec/scripts/check-react-blocks-declaration-parity.tsconsumes:manifest.components[schemaType]andinputs[].name.sdui.manifest.json(66,910 B,gen-sdui-manifest-node.mjs) vs browser dump (gen-sdui-manifest.sh, 73,194 B)typeonaction:buttonandaction:icondataSourceon 15 components (embeddable-form, list-view, object-calendar, object-chart, object-form, object-gantt, object-grid, object-kanban, object-map, object-master-detail-form, object-metric, object-pivot, object-timeline, record:line_items, record:related_list);align,variantontext;actionTypeon the two action blocksRunning
check:react-declaration-parity --baseline react-declaration-parity.baseline.json --strictagainst each: both exit 0, both print «no new DECLARATION divergence vs accepted baseline», per-block declared-by-both / spec-only / registry-only triples byte-identical (119 / 90 / 5 over the 9 judged blocks); the only difference is the node-level bucket (2 vs 11, the extra 9 alldataSource), which feeds no verdict.text,action:button,action:iconare not among the judged blocks.Why it is a finding and not a doc note
The two producers are not interchangeable: a registry change on
dataSourceor on thetype/actionTypespelling would be invisible in the artefact CI reads, and the ratcheting half (registryOnly) reads 0 today — the ruling's own reason for demanding the measurement. Class (b) candidate: the gate's declared input («objectui's registry-inputs dump») is not the input it is fed.A fourth prose site with the same stale premise, same file tree:
packages/spec/scripts/check-generated.ts'sEXTERNAL_INPUT_REQUIREDentry carries awhystring asserting «nothing in this repo (console dist is gitignored, the published console ships no sdui.manifest.json) can hand it one» while the tracked root artefact does; the classification stays correct, its stated reason is false.Not asserted
Which producer is right per key (
dataSourcemay be a node-level prop the node generator strips on purpose) — whoever takes this measures both generators before choosing. ⛔ Not a rider on #15367 / PR #17733 (AGENTS.md prose only).Refs: #15367 · PR #17733 · #13446 (landed the artefact + the wiring) · #14490 (the H17 hold on
.objectui-sha+scripts/sdui-manifest.record.json).Generated by Claude Code