refactor(spec,skills): gen:react-blocks emits one artifact — the markdown rendering is the single AI-facing output - #15257
Conversation
…down is the single AI-facing rendering The generator wrote the same table twice: a machine-readable JSON rendering (5,352 tokens) and a markdown one (3,153 tokens) — same four blocks, same prop counts, byte-identical `note`. The JSON had zero consumers in this repo beyond the register rows that named it, and zero in objectui. It is retired: the writer is dropped, the file is deleted, `--check` verifies one artifact, and every reference that named the path moves with it — the merge-driver row and its comment, the regeneration orchestrator entry, the governed-merge register's candidate and its self-test fixtures, the skills token ratchet's boundary fixture and pinned exclusion set, ADR-0082, and the one skill-body link. Measured: the published skill bundle drops from 156,787 to 151,426 tokens (-5,361, -3.4%); the generator-owned population goes 11 files to 10 and the published-file population 47 to 46. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01H2oQebDDxYKfWZusyd8GXk
…act-blocks-single-rendering
📓 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): |
|
Seat review: ACCEPT — review of record on #14559 (comment 5537286881), Governed surface ( For the human merger, what to read:
CI on Generated by Claude Code |
Fixes #14559
gen:react-blockswrote the same table twice. It now writes it once:skills/objectstack-ui/references/react-blocks.mdis the single AI-facing rendering, and the machine-readable JSON twin is deleted.The ruling this executes
Maintainer ruling on #14296 item 3 = A (director relay 5507419465, 2026-09-02, 「其他同意」), carried by the seam card: the generator stops emitting
skills/objectstack-ui/contracts/react-blocks.contract.json; the file is deleted;skills/objectstack-ui/references/react-blocks.mdis the single AI-facing output. Not re-decided here. Option C of the same item (movingevals/out of the published tree) is not this PR.Premise, re-verified at the base (
96b4af88)Measured before the first edit, not assumed:
check:react-blocksat base:react-blocks contract: 4 blocks → …contract.json + …react-blocks.mdObjectForm:34 ListView:20 ObjectChart:18 Block:1· markdown table rowsObjectForm:34 ListView:20 ObjectChart:18 Block:1notestringnoteappears byte-identically in the markdown body (md.includes(json.note)→true)truegit grep react-blocks.contract.json= 12 hits, all of them names: the generator, the register rows repaired below, one skill-body link, ADR-0082, and two history files (packages/spec/CHANGELOG.md, an existing changeset). No code reads the file.origin/main24e027e9,git grep react-blocks.contract.jsonis empty; the only neighbour is prose inscripts/check-governed-queue-guard.mjs:106The premise holds in full.
Reverse verification, in the card's order
pnpm --filter @objectstack/spec check:react-blocks✅ 2 generated files in sync with packages/spec+ skills/objectstack-ui/contracts/react-blocks.contract.json (missing — spec adds it)✅ 1 generated files in sync with packages/specStep 2 is the one that matters: the deletion is real, and the sync gate is what sees it. Write mode agrees —
gen:react-blocksprints✅ Generated 1 filesand leaves the tree clean, so the markdown is byte-identical before and after (git statusreports no change to it at any step).The seven moving parts
packages/spec/scripts/build-react-blocks-contract.ts:OUT_JSONand itsemit()are gone, so--checkcompares the markdown alone.versionandsourcewere the JSON envelope's own fields and went with it; the markdown states its provenance in the frontmatterdescriptionit emits. Script names unchanged (gen:react-blocks/check:react-blocks). The header records the retirement so nothing reinstates a second output by habit.check:react-blocksverifies one artifact (reading 3 above). Nothing about the gate's wiring changed; it is the same--checkon the same sink..gitattributes— thecontracts/react-blocks.contract.json merge=os-regenrow is dropped, thereferences/react-blocks.mdrow kept, and the "both halves of the react-blocks contract" comment corrected to name one artifact and one row.pnpm check:merge-driverexit 0.AGENTS.md— no edit; reported rather than invented. The row reads| The react-blocks contract | check:react-blocks | gen:react-blocks |: three cells naming a surface, its gate and its generator, and no artifact path at all — there is no artifact list in it to narrow. The prose above it ("packages/spechas eight checked-in generated artifacts, each with its own CI gate") counts gates, one per table entry, andcheck:react-blocksis still exactly one of the eight. Every cell stays true, so an edit here could only add text to a governed file for no gain.scripts/check-skills-token-ratchet.mjs: thegenContractboundary fixture now points atskills/objectstack-ui/references/react-blocks.md(still a real generator-owned path on this tree, still routing to register rowspec-react-blocks), the pinned excluded set drops the JSON, and both prose comments are corrected. Self-test 64 cases pass; the gate itself is green with the generator-owned population at 10 files, down from 11.spec zod schema ──gen──► react-blocks.md, one rendering, and always has.check:skill-refs/check:skill-docs/check:skill-identifier-liveness— verified, not assumed. Neither reference generator enumerates the JSON (check:skill-refsdeclares 9 outputs, all_index.md;check:skill-docsin sync). The liveness gate's Leg 1 population went 47 published files to 46, matching the one deletion exactly.The four references the card omits — each answered
scripts/regen-artifacts.mjsREGEN_ARTIFACTSentry for the JSON is dropped and the markdown entry kept, soregen-artifactsstill knows this generator by one row. Its "both halves" comment is corrected in the same edit.check:merge-driverreconciles this table against.gitattributes, and both moved together — exit 0.scripts/pm/check-governed-merges.mjsspec-react-blockscandidatealternation loses the JSON branch. Two more sites named the path and would have gone stale silently:REGISTER_SAMPLES(the one real path per row, itself asserted to be matched by its row) and the self-test case that pinned both outputs. The pinning case now asserts the single output, and a new case asserts the retired path is no longer a register member — a candidate that still matched a deleted path would hand it a recompute nothing can satisfy.--self-test246 assertions, exit 0;--teston this PR's eight paths returns exit 3 (GOVERNED, see below).skills/objectstack-ui/rules/pages.md@objectstack/spec" — which is also what the generator actually reads, where the old line implied the markdown was generated from the JSON. Net 0 lines (448 to 448) and −9 tokens (5,501 to 5,492 against a 5,501 ceiling). No other body change.scripts/check-governed-queue-guard.mjs:106origin/main24e027e9the line is prose inside a comment explaining why the register half of the upstream mechanism was not ported: "skills/carries no generator output (noreferences/_index.md, no react-blocks contract)". It is a statement about objectui's own tree, it does not name the JSON path, and it stays true after this change — the react-blocks contract still exists upstream, as one artifact. Nothing in objectui reads the deleted file (git grep react-blocks.contract.jsonthere is empty).Measurements
96b4af88d76ab048rules/pages.mdcheck:react-blocksverifiesToken counts are the ratchet's own
countTokens, applied to the base blobs and the head files, so the two columns are the same instrument.Gates
Derived after the last commit from the real change set —
node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands, no path arguments, atd76ab048: 64 commands, change set exactly the eight paths below. All 64 run, 63 exit 0.The one that did not is
pnpm check:dual-build-cjs-loads, which exited 3 — its own PREREQUISITE-NOT-MET code, printing "this gate reads built output, and some package has no dist/ … ⛔ This is NOT a pass: nothing was measured." Its self-test passed (93 cases) on this tree; only its corpus half is unmeasured, and satisfying it needs a full 102-package build, which is the repo-wide run CI owns. It cannot be moved by this diff: zero of the eight changed paths lie under any package'ssrc/(git diff --name-only merge-base HEAD -- 'packages/*/src/**' 'packages/*/*/src/**'is empty), andpackages/spec/scripts/**is not published or compiled —npm pack --dry-runonpackages/speclists 2,086 files, 0 of them underscripts/. Recorded as NOT MEASURED, never as green.pnpm lint(repo-wideeslint . --no-inline-config, no narrowing) exit 0.node scripts/pm/check-governed-merges.mjs --teston these paths: exit 3,⛔ GOVERNED—docs/adr/**×1 andskills/**×2.Landing
This PR stays DRAFT for a human merge.
AGENTS.mdturned out not to need an edit, so the governed surfaces here aredocs/adr/**andskills/**— two of three, which changes nothing about the route. No seat flips it ready, enqueues it, or arms auto-merge. Review requested fromos-zhuangandhotlong; a human merge is the review record.skip-changeset, and the reason is measured. Nothing this PR touches is published by any package.packages/spec'sfileswhitelist isdist,json-schema,liveness,prompts,llms.txt,README.md,src/**/*.zod.ts,CHANGELOG.md,api-surface,spec-changes.json— noscripts/, confirmed against the real tarball (0 of 2,086 entries underscripts/), andcheck:published-filesstates the whitelist "admits no test, test-harness config or build script".skills/sits in no workspace package and appears in no package'sfiles. So this PR releases nothing and the label is the honest declaration; an empty changeset would be a real input tochangesets/actionand buys nothing the label does not. The existing.changeset/skill-catalog-projected-issue-ids.mdmentions the JSON in prose — that is history and is deliberately untouched.Files
packages/spec/scripts/build-react-blocks-contract.ts·skills/objectstack-ui/contracts/react-blocks.contract.json(deleted) ·.gitattributes·scripts/regen-artifacts.mjs·scripts/pm/check-governed-merges.mjs·scripts/check-skills-token-ratchet.mjs·docs/adr/0082-react-component-contract-governance.md·skills/objectstack-ui/rules/pages.mdGenerated by Claude Code