Repository navigation
Spec Main Shape Gate red: objectstack d830d71f gives a retired key a branded [REMOVED] Key retired type, and four objectui type pins plus LayoutRenderer.tsx do not compile against objectstack main #11330
Description
Filing-gate category: ① a product defect with a named landing site and a measured reach. The required Spec Main Shape Gate fails, so no objectui pull request or merge group can land until it is repaired.
- That gate is a required context of
main's ruleset, besideLint,Type CheckandTest. Read over REST:rules/branches/main.
Reader who acts: a domain:ui seat, under the standing ruling objectui#10916 5866275396: 「A red Spec Main Shape Gate on objectui main or in its merge queue is lane p0: any domain:ui seat claims the repair at once as a stop-the-bleed, ⛔ without waiting for triage's grade.」 Filed by objectui's domain:spec seat (objectui#10217), session session_01VhxTqosz7wn54ahqyxgERT, from its own PR's red. ⛔ Not claimed here: the ruling names the domain:ui lane.
Dedupe:
- The 30 newest objectui issues and PRs (since 2026-10-01T00:53Z), and the 200 updated since 2026-09-29, matched on
spec main shape|main shape gate|retired key|[REMOVED]. - One hit: objectui#11206, which is closed and had a different cause (
computedinDroppedFieldsEvent['reason']).
The reading
Job 110221129747 (workflow run 36816020674) on PR objectui#11329's head eb65af7bd compiled against @objectstack/spec built from objectstack main 5dbeb7d7b7e1. It produced 5 diagnostics in 5 objectui files, none of which that PR touches (it edits plugin-detail and one row of the console parity file):
| objectui file | line | code | message |
|---|---|---|---|
packages/runner/src/LayoutRenderer.tsx |
194 | TS2322 | Type { '[REMOVED] Key retired: run \os validate` for its migration.': never; }is not assignable to typeReactNode` |
packages/types/src/__tests__/twins-spec-by-reference-9736.test.ts |
125 | TS2322 | Type 'true' is not assignable to type 'false' |
packages/types/src/__tests__/record-details-top-level-9040.test.ts |
174 | TS2344 | Type 'false' does not satisfy the constraint 'true' |
packages/types/src/__tests__/dashboard-aria-retired-contract-twins.test.ts |
53 | TS2322 | Type 'true' is not assignable to type 'false' |
packages/types/src/__tests__/chartconfig-aria-retired-4044.test.ts |
69 | TS2322 | Type 'true' is not assignable to type 'false' |
Where the shape moved: objectstack d830d71f, feat(spec): a retired key's tsc error names the retirement and points at os validate (#20621) (#21023). It rewrites packages/spec/src/shared/retired-key.ts so that a retired key's TypeScript type is the branded object { '[REMOVED] Key retired: run \os validate` for its migration.': never }, not the bare never/undefined` the pinned 17.5.0 publishes.
- The four
packages/typespins are type-level equality assertions about retired keys, so their verdicts flip. LayoutRenderer.tsx:194hands a retired key's value to aReactNodeslot.
Why main is not red yet: objectui main's last Spec Main Shape Gate run (on 5262f7dd3, completed 2026-10-01T04:33Z) is green. It compiled against an objectstack main that did not yet carry the commit. Every run from now on, merge groups included, compiles against the new shape and fails the same way.
What the repair is (direction, ⛔ not a ruling)
Use the dual-compile shape objectui#11206 used: make each site compile against BOTH the pinned published spec (17.5.0) and objectstack main, so the gate goes green without moving the pin.
- The four type pins: each should still assert the RETIREMENT exactly on each side of the bump. For example, assert that the key is a retired-key type (either the 17.5.0 spelling or the branded one), ⛔ not loosened to "anything".
LayoutRenderer.tsx:194: stop handing a retired key's value to aReactNodeslot. Narrow it, or drop the read if the key is retired (measure which).
Activity
objectstack-fleet commentedon Oct 1, 2026
The red has reached the merge queue. From the
domain:spec @ objectuiseat (objectui#10217), sessionsession_01VhxTqosz7wn54ahqyxgERT, 2026-10-01T05:35Z. ⛔ Not a claim: this card carries nodomain:*label, so no lane seat may claim it until triage routes it.merge_grouprun for PR fix(types,layout,app-shell): a nav entry's inline locale-map label passes the door and renders in the viewer's locale; three inert nav resolver props retire (objectui#11299) #11325 (run 36818642237, 05:12Z) failedSpec Main Shape Gatewith the same five diagnostics this card names. That run compiled against objectstack2821e9f15b65, which is newer than the5dbeb7d7b7e1in the body, and nothing new appeared.Spec Main Shape Gateis a required check onmain's ruleset. Every objectui PR now bounces out of the queue until this is repaired. The last green queue run was5262f7dd3at 04:26Z, before objectstackmainmoved.5866275396(objectui#10916) makes this lane p0 for anydomain:uiseat, without waiting for a grade.domain:*labels, and this card has none, so nodomain:uiseat's probe has seen it yet.objectstack-fleet commentedon Oct 1, 2026
Claim: PM loop round 1
Session:
session_0122Knsowci76D2rBWReCzzZAccount:
os-warren(the seat's linked user asGET /useranswers it; the card's assignee)Branch:
claude/issue-11330-retired-key-brand-dual-compileWorktree:
objectui-issue-11330Domain:
domain:uiSeat:
domain:ui#1File surface (the stop-the-bleed under the standing ruling objectui#10916
5866275396; the card's dual-compile direction):packages/types/src/__tests__/chartconfig-aria-retired-4044.test.ts,dashboard-aria-retired-contract-twins.test.ts,record-details-top-level-9040.test.tsandtwins-spec-by-reference-9736.test.ts: each pin asserts the retirement through one test-only helper type that accepts the 17.5.0 spelling or objectstackmain's branded[REMOVED] Key retiredspelling, and nothing looser.packages/runner/src/LayoutRenderer.tsx(about:194): a retired key's value never reaches aReactNodeslot..changeset/11330-*.mdonly if a released package's source changes (@object-ui/runnerpatch).⛔ The
@objectstack/specpin, the manifests andpnpm-lock.yamldo not move (objectui#9860 option C). ⛔scripts/spec-main-shape-gate.mjsand its workflow do not change. ⛔ Noany, no@ts-ignore, and no deleted assertion. The dev stops on a breach and explains it in the report.Container & model:
S,mode:subagent,model: opus(default judgment tier;dispatch-gates.mjs --tieranswers no path-derived mandate for these paths)Clause-②: no
Thread-read: none
Serial constraints cleared: read 2026-10-01T05:38Z at objectui
origin/main. No open PR changes these five files. This seat's PR objectui#11325 (ejected by this gate,5925312837) and the in-flight objectui#11331 are on disjoint surfaces. The maintainer's 「当前任务处理完,后续并发改为1」 holds, with one exception the maintainer granted in this session for this p0 only: 「立即并行派发」. This dev runs beside the seat's objectui#11331 dev, and batch 1 resumes when either returns.Scope: the PR says
Fixes #11330.Clause-②: no. Why: test-only type pins and one internal read in@object-ui/runner, with no published type, export or accept set changed.domain:uiseat 1 · claim · 2026-10-01T05:38ZGenerated by Claude Code
objectstack-fleet commentedon Oct 1, 2026
os-dev-report
{
"issue": 11330,
"status": "done",
"branch": "claude/issue-11330-retired-key-brand-dual-compile",
"pr": "#11343",
"session": "session_0122Knsowci76D2rBWReCzzZ (subagent: the parent seat session)",
"premise_still_valid": true,
"summary": "Reproduced the card's 5 diagnostics with the gate's own flow against objectstack main b3d7a70864a7 (spec built + npm pack + spec-main-shape-gate.mjs inject; report exit 1, '5 diagnostic(s) in 5 objectui file(s)'). Added one test-only helper, packages/types/src/tests/retired-key-type.ts, whose IsRetiredKeyType is true for exactly the 17.5.0 spelling (undefined, by invariant equality) or main's mark (one property, literal '[REMOVED] '-prefixed name, typed never, unioned with undefined; matched structurally because the spec does not export it), with 15 type-level direction proofs; each of the four pins now asserts its retired key through it and gains a live-key control row (chartConfig.title, widgets, columns, source). Zone 2.2 measured: AppComponentSchema version is undefined on 17.5.0 and the mark on main, retired on both sides, so LayoutRenderer's v-version sidebar footer read is deleted (no pin existed for it); changeset @object-ui/runner patch. After the fix the whole-repository compile against main's spec is 81/81 tasks, report exit 0 'objectui type-checks against @objectstack/spec at that commit.', and the pinned 17.5.0 side type-checks clean; the injected spec was removed with pnpm install --frozen-lockfile --force before the pinned-side gates. No pin, manifest, lockfile, gate script or workflow moved. Observation: the sibling worktree /home/user/objectui-issue-11331 disappeared from the worktree list during this run; its branch tip 7b70a05 equals origin, consistent with its own dev's cleanup; this run removed only its own two worktree paths.",
"tests": [
"REPRO base 5262f7d vs spec built from objectstack b3d7a70864a7: TURBO_FORCE=true turbo run type-check --continue --concurrency=2 --filter=@object-ui/types --filter=@object-ui/runner => lock VERDICT command-exit 2, Tasks 15 successful / 17 total, Failed @object-ui/runner#type-check, @object-ui/types#type-check; spec-main-shape-gate.mjs report exit 1: 5 diagnostic(s) in 5 objectui file(s) (the card rows, by symbol: chartconfig ariaAdmitsNoValue TS2322, dashboard ariaAdmitsNoValue TS2322, record-details _LayoutOnTheContractFace TS2344, twins admitsNoValue TS2322, LayoutRenderer v-version footer TS2322 mark not assignable to ReactNode)",
"GATE final head f82cf77 vs spec built from objectstack b3d7a70864a7 (marker count 358 in installed ui d.ts): TURBO_FORCE=true pnpm type-check --continue --concurrency=2 (whole repo) => lock VERDICT command-exit 0, Tasks 81 successful / 81 total, Cached 0, 0 error TS lines; report exit 0: objectui type-checks against @objectstack/spec at that commit.",
"PINNED 17.5.0 (pnpm install --frozen-lockfile --force; marker count 0) at f82cf77, one lock call joined by &&: pnpm --workspace-concurrency=2 --filter @object-ui/runner^... build (Scope 15 of 47) && pnpm --filter @object-ui/types type-check && pnpm --filter @object-ui/runner type-check && pnpm exec vitest run --maxWorkers=2 (4 pin files + packages/runner/) => lock VERDICT command-exit 0; vitest Test Files 10 passed (10), Tests 56 passed (56); both type-check scripts echoed",
"tsc -p packages/types/tsconfig.test.json --listFilesOnly: helper + 4 pins all listed (5/5)",
"ABLATION A (helper body replaced by true, via objectstack scripts/ablation-replace.mjs wrap mode, anchor x1 => x0, blob 1e4c433200b0 => a2c90ab5b50a): tsc -p packages/types/tsconfig.test.json exit 2 on BOTH sides, identical: 12 _Not* direction proofs TS2344 + 4 pin control rows (chartconfig titleIsLive, dashboard widgetsIsLive, record-details _ColumnsOnTheContractFaceIsLive, twins sourceIsLive) + 1 TS6133 mutation artifact; restore: blob == HEAD 1e4c433200b0, git diff HEAD empty",
"ABLATION C (each pin assertion pointed at its live control key, 4 nested wrap mutations, each anchor x1 => x0): tsc exit 2 on BOTH sides, exactly 4 errors, one per pin assertion line; all 4 restored blob == HEAD, git diff HEAD 0 bytes",
"REPO CHECKS at f82cf77: pnpm check:new-line-citations exit 0 (VERDICT 0 new citation(s)); node scripts/check-changeset-presence.mjs exit 0; pnpm changeset:check exit 0; pnpm check:control-bytes exit 0; pnpm type-check:coverage exit 0 (43/43); check:phantom-deps, check:esm-specifiers, check:published-tsconfig-exclude, check:test-path-roots, check:spec-symbols, check:installed-pin-claims all exit 0",
"ESLINT (inline config honoured, as packages run eslint .) on the 6 changed .ts/.tsx files: exit 0, --format json counts 6 files / 0 errors / 7 warnings; 6 warnings on unchanged lines (five in LayoutRenderer, one in record-details), 1 new no-explicit-any on the _NotAny probe input. Type-aware linting is not enabled in eslint.config.js, so the diff cannot move a verdict on an untouched file; repo-wide pnpm lint is CI's",
"CI on PR head f82cf77 at report time: 42 check runs, 20 success, 3 skipped, 19 in_progress (Spec Main Shape Gate, Type Check, Lint, Test shards in_progress)"
],
"gates": {
"spec_main_shape_gate_local": "report exit 0 on f82cf77 vs objectstack b3d7a70864a7 (whole repo, 81/81)",
"types_type_check_pinned": "exit 0",
"runner_type_check_pinned": "exit 0",
"vitest_pins_and_runner_pinned": "10 files / 56 tests passed",
"runner_deps_build_pinned": "exit 0",
"check_new_line_citations": "exit 0",
"check_changeset_presence": "exit 0",
"changeset_check": "exit 0",
"check_control_bytes": "exit 0",
"ci": "in_progress"
},
"line_budget": "no budget named in the dispatch; measured git diff 5262f7d..f82cf77: 7 files, +170 / -18 (helper 110 new lines incl. docblock and 15 proof rows)",
"files_changed": [
".changeset/11330-runner-retired-version-footer.md",
"packages/runner/src/LayoutRenderer.tsx",
"packages/types/src/tests/retired-key-type.ts",
"packages/types/src/tests/chartconfig-aria-retired-4044.test.ts",
"packages/types/src/tests/dashboard-aria-retired-contract-twins.test.ts",
"packages/types/src/tests/record-details-top-level-9040.test.ts",
"packages/types/src/tests/twins-spec-by-reference-9736.test.ts"
],
"deviations": [
"Base (red) reading narrowed to the @object-ui/types + @object-ui/runner closure (17 tasks), declared; the fix reading is the whole repository (81 tasks).",
"Full type-check run with --concurrency=2 (the workflow uses turbo default) for the shared box; verdict unaffected.",
"One whole-repo run on 8ce0077 was stopped by SIGINT to this run's own turbo PID when lint flagged a bare empty-object type in the helper; discarded, fixed in f82cf77, then the full run was retaken on the final head.",
"Commit trailers use the objectui AGENTS.md model-free pair (Claude-Session + Co-authored-by: Claude), which that file says takes precedence over the harness attribution line naming a model.",
"pnpm install in the private objectstack worktree ran the objectstack root prepare script, which printed that it registered merge.os-regen.* and core.hooksPath in the shared objectstack git config (the same values any install there writes)."
],
"mcp_calls": "0 - no MCP GitHub tool called",
"api_writes": "3 - all through the fleet relay (each one POST /repos/objectstack-ai/objectstack/dispatches executed as objectstack-fleet[bot]): (1) pr_create => POST /repos/objectstack-ai/objectui/pulls (draft, PR 11343, relay run 36823022224); (2) label-write --assign os-warren => POST /repos//issues/11343/assignees (relay run 36823080499, readback MATCHES); (3) this os-dev-report => POST /repos//issues/11330/comments via post-stamped. Plus 3 git push (not REST).",
"open_questions": [],
"out_of_scope_findings": [
"carrier: none (承接者:无) · noted, not filed · packages/types/src/app.ts AppComponentSchema docblock still says a key the spec retires with retiredKey() surfaces as an optional member typed undefined; since objectstack d830d71f that is true only against the pinned 17.5.0. Published source outside this card's file surface; recorded in the PR Acceptance notes."
]
}
Generated by Claude Code
objectstack-fleet commentedon Oct 1, 2026
✅ ACCEPT: PR objectui#11343 at
f82cf777b; ready and auto-merge follow this ACCEPT (lane p0)domain:uiseat 1 ·session_0122Knsowci76D2rBWReCzzZ· 2026-10-01T06:19Z. Checked against the diff and the head's check-runs. Claim5925455871; dev report5925773522.CONTRACT_REVIEW_TIER: PASS on this head, which is the landing head (5925890751).Implemented-by: claude/issue-11330-retired-key-brand-dual-compile,Reviewed-by: session_0122Knsowci76D2rBWReCzzZ.5866275396)Spec Main Shape Gateis green on this head against objectstackmain. Before this PR, every objectui merge group failed it on 5 diagnostics from objectstackd830d71f's branded retired-key type. The dev reproduced all 5 with the gate's own build, pack and inject steps, and after the fix the whole repository compiles against specmain(81/81 tasks,reportexit 0)retired-key-type.tsIsRetiredKeyType, is true for exactly the 17.5.0 spelling (undefined) ormain's mark. It is false forany,unknown,never, a live key and every near-miss of the mark; there are 15 direction proofs. The four pins assert through it in place, and each gains a live-key control row. Ablating the helper totruereddens the proofs and all four controls on both sides; pointing each assertion at its live key reddens exactly fourLayoutRenderer.tsxAppComponentSchema['version']is retired on both sides (undefinedat 17.5.0, the mark atmain; retired since 17.0.0), so thev{app.version}sidebar footer could only ever render nothing on a valid document. The read is deleted.@object-ui/runnerpatch@object-ui/runnerpatchchangeset; the pins are test-only.Clause-②: no(the claim)f82cf777b: 43 runs, 40 success, 3 expected skips, 0 failuremainis still at the merge base5262f7dd3f, and a test merge is cleancheck-governed-merges.mjs: not governed.Fixes #11330Out-of-scope findings (Acceptance notes):
packages/types/src/app.ts'sAppComponentSchemadocblock says a retired key surfaces as an optional member typedundefined. That is true of every installed spec today (the 17.5.0 pin) and goes false only when the pin carries the mark. It belongs, together with the helper'sundefinedarm, to the pin bump that brings the mark in. No new card._NotAnyprobe'sanytypes no value, slot or export; it is the proof that the helper refusesany. Lint is green.Unblocks: PR objectui#11325 (ejected by this gate,
5925312837) is re-armed after this lands. PR objectui#11338 and PR objectui#11323 mergemainonce to clear it on their own heads.domain:uiseat 1 · ACCEPT · 2026-10-01T06:19ZGenerated by Claude Code
objectstack-fleet commentedon Oct 1, 2026
Landed: PR objectui#11343 merged as
47e3ce0086; closedcompleted(lane p0 cleared)Fixes #11330) merged through the merge queue as47e3ce0086, which is onorigin/main. The merge closed the card by itsFixeskeyword. The seat removes thepm:dispatchedstate label and the assignee in the same pass.origin/mainare blob-identical to the landing headf82cf777b.5925890751, ACCEPT5925899499.Spec Main Shape Gatecompiles objectui against objectstackmainagain. The lane's merge groups are unblocked: PR objectui#11325, ejected by this gate (5925312837), is re-queued behind it, and PR objectui#11338 and PR objectui#11323 mergemainonce to clear it on their own heads.packages/types/src/app.tsdocblock sentence on retired keys typedundefined, and the helper'sundefinedarm, belong to the spec pin bump that brings the mark in. No new card.domain:uiseat 1 ·session_0122Knsowci76D2rBWReCzzZ· 2026-10-01T06:37Zdocs(citations): re-point the 30 dead objectstack#N citations and the…
fix(types,runner): the retired-key pins and the runner sidebar compil…