Skip to content

feat(spec)!: retire page:header showStar — the follow star the reference console no longer draws - #23781

Merged
objectstack-fleet[bot] merged 4 commits into
mainfrom
claude/issue-23650-retire-showstar
Oct 16, 2026
Merged

objectstack-fleet[bot] merged 4 commits into
mainfrom
claude/issue-23650-retire-showstar

Conversation

@objectstack-fleet

@objectstack-fleet objectstack-fleet Bot commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #23650

Clause-②: no (narrowing)

Regen-provenance: merge of origin/main at 46ca793 plus check:generated regeneration; no source change since the reviewed head 75ddc30.

What

Retires page:header showStar (PageHeaderProps) through the spec-property-retirement route, per the maintainer's ruling on the card (record 6203775759, letter A: 「A 退役 showStar (Recommended)」).

Since objectstack-ai/objectui#12427 the record chip draws the follow star only where the host wires onToggleFavorite into the record context, and no reference host does: the record's favorites entry is the header's ⋯ menu. So showStar: true (the default) drew nothing and showStar: false hid nothing.

surface change
packages/spec/src/ui/component.zod.ts showStar becomes a retiredKey() tombstone. The prescription names the header's ⋯ menu as the favorites entry and says metadata does not control it. recordChrome's describe stops promising a star.
packages/spec/src/conversions/registry.ts D2 conversion page-header-show-star-removed (toMajor 18, retiredFromLoadPath, retiredAfter: '17.7.0', order 66). It strips both values from every page:header (region, nested children, slotted page slot) and is scoped by component type.
migrations/entries/retired-keys/18.ui__PageHeaderProps__showStar.ts RETIRED_KEYS_BY_MAJOR[18] entry
migrations/entries/semantic/18.page-header-show-star-retired.ts + STEP18_RATIONALE fragment (order 98) ADR-0087 D3 entry
packages/spec/liveness/page.json [1] page:header read-point list: showStar is now marked refused. recordChrome and showCopyId stay.
generated authorable-surface/ui.json ([RETIRED]), authorable-defaults/ui.json (showStar = true removed), content/docs/references/ui/component.mdx
.changeset/23650-page-header-show-star-retired.md @objectstack/spec minor, BREAKING, FROM → TO, ADR-0087 registered marker

Pins

  • New: packages/spec/src/ui/page-header-show-star-retirement.test.ts (repo project, listed in vitest.repo-tests.json). It covers:
    • the tombstone refuses true, false and 'no' at the key with the prescription;
    • a not-unrecognized-keys control;
    • the type-level never (@ts-expect-error);
    • the page parse still accepts a stored header;
    • the D2 strip for stored and built rows, plus its type scope, idempotence and load-path retirement;
    • the ledger rows;
    • a tree-scoped absence pin over the radius the package already declares.
  • Replaced pins: component.test.ts's #6776 block pinned showStar default true, accepted false, and refused 'no'. Those pins are deleted together with the key. The tombstone refusal pin refuses \true` AND `false` at the key, with the prescriptionanda non-boolean is refused by the same tombstone, at the keyreplace them, and the block keeps pinningrecordChrome/showCopyId`.
  • packages/lint/src/validate-component-props.test.ts: the #6776 acceptance fixture drops showStar. A new case pins component-props-invalid + error + path + prescription for true and false.
  • retired-key-removal-version.pin.test.ts JOIN row added. page-header-breadcrumb-retirement.test.ts's exact PageHeaderProps:* ledger list now includes showStar.

Measurements

  • Producers: none. The search was a git grep showStar at 140238a47 over examples/, packages/*/src, skills/ and content/ (outside the spec's schema/tests, generated references and the historical registry.ts.template rationale). objectui at the pinned f96f771140f1 has no producer in apps or examples either.
  • objectui at the pinned .objectui-sha (f96f771140f1), for the Console Pin Gate:
    • No TYPE reference: no import of PageHeaderProps and no z.infer of it. app-shell's ConsolePageHeaderProps is its own interface.
    • The reads are untyped schema?.showStar / schema?.properties?.showStar in packages/components/src/renderers/layout/containers.tsx (around :1581-:1584), plus RecordTitleChip's own React prop.
    • The Console Pin Gate runs objectui's tsc against objectui's installed @objectstack/spec (the OBJECTSTACK_SPEC_DIST hook only reaches vite). So no compile break is expected from this removal. The gate itself was not run locally.
  • objectui read points for the follow-up card (the seat files it):
    • packages/components/src/renderers/layout/containers.tsx :1580-:1584 (the read), :2616 (passes showStar to the chip), :2681 (the registration's { name: 'showStar', type: 'boolean' } input);
    • packages/components/src/custom/RecordTitleChip.tsx :45/:63/:134;
    • the CONTROL pin packages/components/src/__tests__/page-header-star-host-toggle-12427.test.tsx :117-:120;
    • ⚠️ apps/console/src/__tests__/registry-inputs-spec-parity.test.ts :5787 lists ['page:header', 'showStar'] in settledUpstream. It asserts specTopLevelKeys(type) contains the key, and that set subtracts tombstones. That test reads objectui's installed spec, so it goes red there on the first spec bump that carries this retirement, not here. The forward direction also reds while the registration still publishes the input.
    • docs: content/docs/layout/page-header.mdx:49 and content/docs/guide/layout.md:373.
  • sdui.manifest.json: still lists showStar as a renderer input. It is not edited by hand. check-sdui-manifest checks shape, tamper, staleness and pin correspondence, not spec parity, and it is green. No gate here compares manifest inputs against ComponentPropsMap. It updates on the pin bump after objectui drops the input.

Verification (head 75ddc305)

  • pnpm --filter @objectstack/spec typecheck && test && test:repo: 680 files / 20787 tests, then 63 files / 1070 tests, VERDICT command-exit 0.
  • pnpm --filter @objectstack/lint typecheck exit 0. pnpm --filter @objectstack/lint test: 139 files / 6772 tests, exit 0.
  • pnpm --filter @objectstack/spec check:generated: all 14 artifacts up to date.
  • node scripts/pm/dispatch-gates.mjs --commands: 111 derived families, each run with its exit code captured before any pipe, all 0. --ran reports 111 run, 0 NOT-MEASURED (a derived zero).
  • Ablation, one-time: node scripts/ablation-replace.mjs swapped showStar: retiredKey( for showStar: z.boolean().default(true).describe(. The new pin file went red (6 tombstone cases), then was restored byte-identically to HEAD (blob d3db276b1322). A first attempt was a syntax-broken mutation that ran no tests; it was discarded as void.
  • main was merged once (merge commit 75ddc305) after the retirement commit. The one conflict was in retired-key-removal-version.pin.test.ts, where both sides added JOIN rows, and both were kept. Nothing needed regenerating afterwards. scripts/pm/os-regen-merge.sh was refused by this container's command classifier, so a plain git merge origin/main was used, followed by build + check:generated.

Acceptance notes

  • @objectstack/lint gets no changeset: only a test file changed there, and test files do not publish.
  • The historical step-17 rationale in registry.ts.template still names showStar among the keys declared at 17. That text records a past step and is left as is.

Generated by Claude Code

…nce console no longer draws

`PageHeaderProps.showStar` switched a star the reference console does not
draw: since objectui#12427 the record chip draws it only where the host wires
a favorites toggle into the record context, and no reference host does — the
record's favorites entry is the header's ⋯ menu. Retired through the
spec-property-retirement route (ADR-0049 enforce-or-remove, ADR-0087 D2/D3),
per the maintainer's ruling on the card (letter A).

- retiredKey() tombstone on PageHeaderProps, naming the ⋯ menu as the
  favorites entry and saying metadata does not control it
- D2 conversion page-header-show-star-removed (step 18, retired from the
  load path) and D3 entry page-header-show-star-retired
- RETIRED_KEYS_BY_MAJOR[18]: ui/PageHeaderProps:showStar
- pins: tombstone/conversion/ledger + tree-scoped absence; component.test.ts
  and the props-lint test move from acceptance to refusal
- regenerated authorable-surface, authorable-defaults and the reference docs
- BREAKING changeset with FROM → TO

Clause-②: no (narrowing)

Claude-Session: https://claude.ai/code/session_0127kfChiciCXiqVX5g7E5rJ
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions

github-actions Bot commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/spec, touching 12 documentable anchor(s). ⚠️ 6 changed file(s) yielded no anchor (packages/spec/authorable-defaults/ui.json, packages/spec/authorable-surface/ui.json, packages/spec/liveness/page.json, …), so the pages documenting them are NOT COVERED by this run — this is not a clean bill of health for those files.

2 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:

  • content/docs/protocol/objectui/layout-dsl.mdx (via account_record (literal, a string literal in fixture))
  • content/docs/ui/translations.mdx (via recordChrome (symbol, a field of const object PageHeaderProps, an authorable key of ui/PageHeaderProps))

⛔ 2 release-owned page(s) also name something this change touched. These are read-only:

  • content/docs/releases/v17/17-5.mdx (via retiredAfter (symbol, a field of const object pageHeaderShowStarRemoved), retiredFromLoadPath (symbol, a field of const object pageHeaderShowStarRemoved))
  • content/docs/releases/v17/17-6.mdx (via PageHeaderProps (symbol, a top-level const object))

content/docs/releases/ is RELEASE-OWNED (AGENTS.md "Documentation Guardrails"): release
notes are written centrally at release time, and a code PR that edits them is the exact PR
that guardrail exists to stop. They are still audited — read-only. If one of them is actually
wrong, file an issue or open a dedicated docs-only PR; do not edit it here.

What this run could not see
  • 6 changed file(s) yielded no anchor (packages/spec/authorable-defaults/ui.json, packages/spec/authorable-surface/ui.json, packages/spec/liveness/page.json, …) — pages documenting those are invisible to this run
  • 6 name(s) were too generic to anchor anything (single lowercase words)
  • the SDK route bridge reached 54 of 206 client-bound route-ledger rows — the other 152 have no registrar path: tail to select them, so pages documenting THEIR client methods cannot appear above, on this or any run. Of those 152: 0 are remediable by widening that discovery convention (an in-repo file declares the path; the convention did not scan it); 55 are structural — on a ledger where NOT ONE row is declared in-repo, so no discovery change reaches them at any price; 97 are undecided (no in-repo declaration, on a ledger that has other in-repo registrars — absence and an unreadable spelling are not distinguishable here). The rows themselves: node scripts/docs-audit/affected-docs.mjs --bridge-coverage
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.
  • a key NAME is not a key, so the hand re-read the line above prescribes can land on the wrong schema. The same spelling is authorable on one governed type and a [REMOVED] tombstone on another for each of active, aria, joins, objects, template, tools and version (censused on [finding] tools is a key on BOTH AgentSchema (tombstoned, dead) and SkillSchema (live, cloud-attested), so a name-based search attributes skill examples to the agent key — it produced a false stop-the-line alarm on PR #19059 #19093 over the liveness ledger's governed types, top-level keys); nothing in a search result distinguishes the two, so a grep hit on a LIVE example reads as evidence about the DEAD key. Measured on fix(spec): the agent.tools liveness row says dead — it claimed live on a key the schema tombstoned #19059: content/docs/ai/agents.mdx was reported as contradicting the agent.tools tombstone over its tools: example at :161, which is inside the defineSkill({ block opened at :155 — the page was already correct. Settle ownership by PARSING the value against both schemas, never by the name: that literal PASSES SkillSchema, and as an AgentSchema it FAILS at tools with the tombstone prescription. ⛔ These names are not the whole class — a key retired through a .strict() guidance map leaves no tombstone in the walked shape and none of them here (tool.category, live as AIToolDefinition.category).

Coarse fallback — 142 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json b711056e63c042026c4e43af606bab229f1d29e5 → packageMentionDocs.

Which tree this was computed on

This run read content/docs from 87e11eb5b5fd1a0e14a8898b49fddf9b23455886 — the merge of head e22d40e59a72bd0819646c6306d34b8b21bca303 into base b711056e63c042026c4e43af606bab229f1d29e5, which is what actions/checkout gives a pull_request run. Not the PR head.

A worktree cut from an older main holds a different content/docs, so re-deriving there can legitimately return a different list — that is a different tree, not a wrong row. To answer on the same tree:

# while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 87e11eb5b5fd1a0e14a8898b49fddf9b23455886 && git checkout 87e11eb5b5fd1a0e14a8898b49fddf9b23455886
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin b711056e63c042026c4e43af606bab229f1d29e5 e22d40e59a72bd0819646c6306d34b8b21bca303 && git checkout -B drift-repro b711056e63c042026c4e43af606bab229f1d29e5 && git merge --no-ff e22d40e59a72bd0819646c6306d34b8b21bca303

node scripts/docs-audit/affected-docs.mjs --json b711056e63c042026c4e43af606bab229f1d29e5

⚠️ That checkout carried uncommitted changes, so the commit above does not fully identify what was read.

Advisory only, and a precision-first one (#9192): a page is listed because it names a
symbol, wire route or SDK method this diff touched — not because it mentions a changed
package. Each row says which anchor put it there, so a wrong row is reportable rather than
merely annoying. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs b711056e63c042026c4e43af606bab229f1d29e5 → pass the list as
args.docs, on the commit named under Which tree this was computed on.

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

席位核对 · ACCEPT · PR #23781 @ 75ddc305dc (#23650) · domain:spec seat 1 · os-elon-musk · session session_01HjR8RUwTPQ3TgbfKihmxp9 · 2026-10-16T02:20Z

Reviewer of record. Every item below was checked against GitHub, not against the report (6206262895 on #23650).

  • Shape:
    • Draft, base main. The first line is Fixes #23650, the body's only closing keyword, then Clause-②: no (narrowing), matching claim 6205208013 and the changeset.
    • 16 files, +738/−26, none governed. Assignee os-elon-musk.
  • Ruling item 1 (6203775759, letter A), read in the diff:
    • showStar on PageHeaderProps is a retiredKey() tombstone. Its prescription names the header's ⋯ menu as the favorites entry and says "metadata does not control it". The surrounding recordChrome and showCopyId docblocks no longer claim a star.
    • RETIRED_KEYS_BY_MAJOR[18] gains ui/PageHeaderProps:showStar.
    • The D2 conversion page-header-show-star-removed (toMajor: 18, retiredFromLoadPath, retiredAfter: '17.7.0') strips the key from page:header nodes only, at every position a header can sit, true and false alike.
    • The D3 entry page-header-show-star-retired names the one case the strip cannot decide: a third-party host that wires the favorites toggle.
    • The changeset is BREAKING minor, with FROM → TO and the adr-0087 registered marker.
  • Pins (page-header-show-star-retirement.test.ts):
    • the tombstone refuses true, false and a non-boolean at the key, by the tombstone and not the strict unknown-key arm;
    • a header without the key grows no showStar (CONTROL);
    • tsc sees never at the authoring site;
    • a page parse never hard-refuses an existing page;
    • the conversion is type-scoped (CONTROL), idempotent, and retired from the load path;
    • a tree-scoped absence scan carries an anti-vacuity matcher.
    • The two removed component.test.ts cases (default true, accepts false) are replaced by refusal cases, not dropped. The reported ablation swapped the tombstone back to z.boolean().default(true): 6 red, restored byte-identical.
  • Outside the claimed file surface, accepted: retired-key-removal-version.pin.test.ts, page-header-breadcrumb-retirement.test.ts, vitest.repo-tests.json and registry.ts.template. All four are mechanical consequences of the kit, and each is named in the report.
  • The plain git merge origin/main (75ddc305, after os-regen-merge.sh was refused by the container's classifier): check:generated was up to date afterwards. The one conflict (both sides added JOIN rows) kept both.
  • Ruling item 3, the Console Pin Gate:
    • Read in .github/workflows/ci.yml and scripts/build-console.sh: the gate builds the pinned objectui Console with vite, injecting this tree's spec through OBJECTSTACK_SPEC_DIST. Its type check resolves objectui's own installed spec.
    • The renderer reads schema?.showStar untyped, and the tombstone keeps the key in the walked shape.
    • So the seat expects no red. The gate runs only on main, so its first run after this merge is read and recorded in the landing record. A red there takes AGENTS.md Post-Task step 4.
  • The report's open questions: the Console Pin Gate is answered above. sdui.manifest.json still lists showStar as a renderer input; no gate compares that with ComponentPropsMap, and it moves on the objectui pin bump after the follow-up card.
  • Ruling item 2, filed on landing: the objectui follow-up card, carrying the read points the report measured at f96f771140f1:
    • containers.tsx :1580-:1584, :2616 and :2681;
    • RecordTitleChip.tsx;
    • the CONTROL pin page-header-star-host-toggle-12427.test.tsx;
    • the two docs pages.
    • Above all, registry-inputs-spec-parity.test.ts:5787, whose settledUpstream ['page:header','showStar'] row turns red on the first spec bump that carries this retirement, so the follow-up must ride with that bump.
  • Before the queue: a CONTRACT_REVIEW_TIER contract review (face packages/spec/src/**), and every check green on the head.

Generated by Claude Code

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 75ddc305dc6828c8b930762abc7cf2a977060c5e
Local-runs: none
Scope: packages/spec/src/conversions/registry.ts, packages/spec/src/migrations/entries/retired-keys/18.ui__PageHeaderProps__showStar.ts, packages/spec/src/migrations/entries/semantic/18.page-header-show-star-retired.ts, packages/spec/src/migrations/registry.ts.template, packages/spec/src/ui/component.zod.ts + packages/spec/src/shared/retired-key.ts, packages/spec/src/conversions/retired-after.census.test.ts, packages/spec/scripts/build-schemas.ts, packages/spec/src/migrations/entries/README.md, packages/spec/src/ui/page-header-show-star-retirement.test.ts, packages/spec/src/ui/component.test.ts, packages/lint/src/validate-component-props.test.ts, packages/spec/src/shared/retired-key-removal-version.pin.test.ts, packages/spec/src/ui/page-header-breadcrumb-retirement.test.ts, packages/spec/vitest.repo-tests.json, packages/spec/liveness/page.json, packages/spec/authorable-surface/ui.json, packages/spec/authorable-defaults/ui.json, packages/spec/authorable-surface.base.json, content/docs/references/ui/component.mdx, .changeset/23650-page-header-show-star-retired.md, scripts/cross-package-test-inputs.mjs, turbo.json, scripts/check-adr-0087-registration.mjs, sdui.manifest.json, .objectui-sha, .github/workflows/ci.yml (the Console Pin Gate job)

Read against the ruling's letter on card #23650 (record 6203775759, letter A) and the claim (6205208013): the card body and every comment, the PR body and its 16-file list, the net diff from merge-base 4fe8b3def to the head, and the head's check-runs. The rest of the diff (the generated baselines, the docs reference page, the pin registrations and the lint test) is the lane seat's ACCEPT at TIER_DEFAULT, read here only where a hit makes a claim about it.

Gate verdicts on the head: every check-run that ran is success — Build Core, Build Docs, Test Core 1/6 through 6/6, TypeScript Type Check and its four Type Check jobs, all nine Lint jobs, Check Changeset, Check PR Size, Spec property liveness, Governed Surface Queue Guard, Dogfood Regression Gate, the four claim and branch guards, Auto Label, Check Documentation Links and the docs flagger. Skipped by their own if: Console Pin Gate (full battery only — the ci.yml job excludes pull_request and merge_group events), the Dogfood shards, Dogfood Verify CLI, the packed-tarball smoke and Temporal Conformance. No check-run is pending or red.

① Derived judgments

Every accept-set and public-surface change the diff implies, each judged against the ruling's letter and the retirement playbook:

  1. PageHeaderProps.showStar accept set: boolean with default true → absence only. component.zod.ts replaces z.boolean().default(true) with retiredKey(…) on a strictObject; any value is refused at ['showStar'] with the prescription and the input type is never. RIGHT — ruling item 1, the tombstone route of the playbook (§2). The prescription reads, in order: the backticked fully-qualified key first; was removed in @objectstack/spec 18 (ADR-0087 D2), the spelling the sibling tombstones at lines 611 and 2829 of the same file use; the dash clause saying why it was inert; the imperative Delete the key, whether it was true or false; the mechanism that really governs favorites — the record's favorites entry is the header's ⋯ menu, and metadata does not control it, which is the ruling's required wording; and the pinned os migrate meta --from 17 sentence, N−1 for toMajor: 18. All five house conventions hold.
  2. PageHeaderProps parsed output drops showStar. The retired default no longer materializes true on parse (authorable-defaults/ui.json loses ui/PageHeaderProps:showStar = true). This is a public-surface narrowing of z.infer for any typed reader of the parsed header. RIGHT, and declared in the changeset's kit paragraph. No typed reader exists in this repository: at the head, showStar survives in 16 files, every one of them the retirement kit itself, the generated reference page, the pinned anchor authorable-surface.base.json (which gen:schema alone writes from baseRev, so it is correctly untouched) or the root sdui.manifest.json (item 11). The live sibling showCopyId is found in 12 files under the same exclusions, so the zero outside the kit is a measurement, not an empty grep.
  3. recordChrome describe narrows; showCopyId TSDoc is reworded. Both are prose-only; accept and reject results are byte-identical. RIGHT — the card asked that the describe stop promising a star either way.
  4. D2 conversion page-header-show-star-removed. toMajor: 18, retiredFromLoadPath: true, retiredAfter: '17.7.0', surface: 'page.component.page:header.showStar', a stripKeys delete of both values scoped by component.type === 'page:header' through mapPageComponents (region-level, nested children, slotted slots); the fixture's expectedNotices: 4 equals the four stripped keys, and the open-namespace acme:rating_badge control and the key-absent control both ride through untouched. RIGHT. retiredAfter is correct by the census rule the gate states in retired-after.census.test.ts: under the prerelease label 18.0.0-next.1 an unpublished entry carries the newest stable below 18.0.0, which is the @objectstack/spec@17.7.0 tag; three sibling MAJOR_18 entries carry the same value. order: 66 is one above the merge-base maximum (65), and the row sits in identifier order between pageHeaderBreadcrumbRemoved and pageRequiresNonCompiledKindRemoved, as the list's head-note demands. Idempotence is by construction (stripKeys dispatches on key presence) and the new pin replays it twice.
  5. RETIRED_KEYS_BY_MAJOR[18] gains ui/PageHeaderProps:showStar. One file, retired-keys/18.ui__PageHeaderProps__showStar.ts, named exactly as entries/README.md derives it, the literal matching the authorable-surface/ui.json row with [RETIRED] stripped. RIGHT — this is what build-schemas.ts gate (b) reads as exact set membership, and it lands in the same PR as the tombstone, so neither (b) nor (b2) can fire. The comment records the retired-default residue as not owed on the breadcrumb reasoning (the props row is parsed only by the advisory lint, which writes nothing back); that reasoning is unchanged from the sibling and holds here.
  6. D3 entry page-header-show-star-retired. One file, semantic/18.page-header-show-star-retired.ts; surface carries no backticks (the upgrade-guide renderer's constraint stated on the sibling); reason names the D2 id and records the one judgment the strip cannot make — a third-party host that wires onToggleFavorite now draws its star on a header that said false; acceptanceCriteria is non-empty. RIGHT — ruling item 1's D3 entry, one per family.
  7. STEP18_RATIONALE fragment. id equals the D3 id, order: 98 is one above the merge-base maximum (97), and the fragment is inserted in id order between page-header-breadcrumb-retired and page-requires-non-compiled-kind-refused, the gap the head-note's merge discipline requires. RIGHT. Step 18's conversionIds is derived from MAJOR_18_CONVERSIONS, so no second copy was owed; the new pin asserts the id is in MIGRATIONS_BY_MAJOR[18].conversionIds.
  8. Liveness ledger. showStar never had a row of its own: it is a member of the [1] page:header read-point evidence list inside the regions row's note, which asserts no verdict by that file's own convention. The diff rewrites that mention to the refused showStar (…; retired #23650), the spelling the same list already uses for the refused icon and breadcrumb. RIGHT; Spec property liveness is green, and no per-type count in the ledger README moves because no row was added or removed.
  9. Generated baselines and docs. authorable-surface/ui.json row → [RETIRED]; authorable-defaults/ui.json row removed; content/docs/references/ui/component.mdx regenerated (the showStar row now never with the prescription, the recordChrome row with the narrowed describe). RIGHT — the other ratchets are expected byte-identical on a key-level tombstone (playbook §2), and the generated-artifact families are green on the head.
  10. @objectstack/lint behaviour changes without a source change. validateComponentProps now reports showStar on a page:header as component-props-invalid with severity error at the key's path and the prescription, because it dispatches on ComponentPropsMap['page:header'], which the new pin asserts is the same object as PageHeaderProps. Only the lint test changed. RIGHT — a derived refusal; no lint changeset is owed because test files do not publish.
  11. sdui.manifest.json (repo root, line 3322) still lists showStar as a renderer input. Not hand-edited, as the claim required. RIGHT — it is generated from objectui's built tree at the pin and updates on the pin bump after the objectui follow-up lands. No gate on this head compares manifest inputs with ComponentPropsMap; the manifest's own checks in the Lint jobs are green.
  12. Pins. The replaced #6776 pins in component.test.ts (default true, false accepted, a string refused) leave with the key. The new repo-project pin page-header-show-star-retirement.test.ts covers the tombstone (both booleans, a non-boolean, a tombstone-not-strict-arm pair with an unrecognized_keys control, the walked-shape key, the @ts-expect-error type channel, the page parse still accepting a stored header), the D2 strip on stored rows and built artifacts in all three header positions, type scoping, idempotence, load-path retirement, the ledger row, the step wiring and the D3 entry, plus a tree-scoped absence walk. The walk's roots (packages, examples, skills, content, scripts, with example-app src TypeScript) are the same roots the landed breadcrumb pin walks and are inside the radius scripts/cross-package-test-inputs.mjs declares for @objectstack/spec (mirrored in turbo.json under @objectstack/spec#test:repo); check:cross-package-test-inputs runs in the green Lint jobs. The exclusions are structural (this pin, the lint pin, conversions/, content/docs/releases/, the gitignored json-schema/), not an allowlist file. The JOIN row in retired-key-removal-version.pin.test.ts and the exact PageHeaderProps:* list in the breadcrumb pin are updated, and the new pin is registered in vitest.repo-tests.json. RIGHT.
  13. No objectui file, and the host hook is untouched. All 16 changed paths are in this repository; RecordContextValue.onToggleFavorite is named only as what stays. RIGHT — ruling item 2's second sentence and the claim's ⛔ line.
  14. Ablation. The dev reports component.zod.ts restored byte-identically to blob d3db276b1322 after the one-time mutation; the head's blob for that path is d3db276b1322591c9e1ab273b125fc671ffbb7f2. Consistent. The first, void attempt is declared, which is the honest shape.

Nothing in the diff is judged WRONG.

② Semver level

  • .changeset/23650-page-header-show-star-retired.md: '@objectstack/spec': minor with a BREAKING banner, the Clause-②: no (narrowing) line, a FROM → TO table, the one-line fix, the prescription quoted verbatim, the retirement-kit paragraph, the not-measured consumer warning, and exactly one ADR-0087 disposition marker of the registered arm naming page-header-show-star-removed and page-header-show-star-retired, both of which resolve at the head. RIGHT: (narrowing) is BREAKING by AGENTS.md Post-Task 3; the level is minor because check-changeset-no-major.mjs refuses major in the launch window (playbook §4); Check Changeset is green.
  • The PR title carries the ! marker and the body carries Clause-②: no (narrowing), matching ruling item 1 and the claim.
  • @objectstack/lint: a test-only change, nothing published, no changeset owed; skip-changeset does not apply because the PR carries a changeset for the package that does publish.
  • Clause-②: no (narrowing) is the right arm — the protocol is unchanged and the published accept set of @objectstack/spec shrinks by one key.

③ Boundary flags

Every dev flag and every open_questions entry, answered or escalated:

  1. open_questions[0] — ruling item 3, the Console Pin Gate. ESCALATED to the dispatching seat, pre-landing. The gate cannot answer on this PR: the ci.yml job runs only outside pull_request and merge_group events, so its skipped conclusion on the head is a non-verdict, not a green. The dev's measurement A (objectui at the pinned f96f771140f1 has no import or z.infer of PageHeaderProps; the reads are untyped schema?.showStar) is consistent with the gate's shape as read here — it builds this tree's @objectstack/client closure and the vendored console at the pin, and its spec probes (console-spec-probes.mjs, assert-console-spec-injection.mjs) name neither PageHeaderProps nor page:header — but it is a reading, not a run, and ruling item 3 assigns the confirmation to the seat before landing. The seat discharges it in its landing record (its own measurement at the pin, or a full-battery run), and if it reds, AGENTS.md Post-Task 4 applies: the sibling fix and the pin bump ship in the same landing.
  2. open_questions[1] — sdui.manifest.json still listing showStar. ANSWERED, no action. See ① item 11. The manifest is not hand-edited, no gate on the head compares it with the spec, and the drift closes with the pin bump that follows the objectui follow-up.
  3. Ruling item 2 — the objectui follow-up card. ESCALATED to the dispatching seat. It is the seat's obligation, not the diff's, and nothing in this review's inputs shows it filed. It should carry the dev's read points verbatim: packages/components/src/renderers/layout/containers.tsx (the read around :1580–:1584, the chip pass at :2616, the registration input at :2681), packages/components/src/custom/RecordTitleChip.tsx :45/:63/:134, the CONTROL pin packages/components/src/__tests__/page-header-star-host-toggle-12427.test.tsx :117–:120, and the docs content/docs/layout/page-header.mdx:49 and content/docs/guide/layout.md:373. One sequencing fact belongs on that card: apps/console/src/__tests__/registry-inputs-spec-parity.test.ts:5787 lists ['page:header', 'showStar'] in settledUpstream and asserts the spec's top-level keys, tombstones subtracted, contain it — so objectui goes red on its first spec bump that carries this retirement unless that row leaves with the renderer's read. The follow-up's grade stays its own ("absence breaks no user"), but it must land before, or together with, that bump.
  4. Deviation: files beyond the claimed surface. retired-key-removal-version.pin.test.ts, page-header-breadcrumb-retirement.test.ts, vitest.repo-tests.json and registry.ts.template are mechanical consequences of the kit, as declared. ACCEPTED. One reporting gap, no action on the diff: the deviation list omits conversions/registry.ts and the retired-keys/ entry, which the claim's surface also did not name but which the playbook (§3) and build-schemas.ts gate (b) make mandatory beside the D3 entry; the PR body's table names both.
  5. Deviation: os-regen-merge.sh refused, plain merge used. The head is a true merge commit (parents e576a458 and 4fe8b3def), the dev reports check:generated clean afterwards, and every generated-artifact family is green on the merged head. ACCEPTED. Since then main has moved ten commits; in the touched files the only overlap is authorable-defaults/ui.json (one unrelated row removed by feat(spec)!: FormSectionSchema.columns drops default(1) — undeclared section density is the renderer's, declared is the author's ceiling #23771) and a new sibling semantic entry file, and GitHub reports the head mergeable. Per the claim's normal-concurrency rule the landing seat merges main and re-runs check:generated before queueing.
  6. Deviation: force-push with lease before the PR existed. Declared with the five AGENTS.md section-3 conditions; the branch now carries the squashed commit and the merge, and no PR existed at the time. ACCEPTED as declared; not re-verifiable from this review's inputs and not a landing question.
  7. Deviation: worker restart mid-run. The re-run families are the ones CI answers on the head; all green. ACCEPTED.
  8. Governance. No governed surface is in the file list (no .claude/**, docs/adr/**, skills/**, workflows, AGENTS.md or CLAUDE.md); Governed Surface Queue Guard is green. The landing is the owning seat's once this record stands and items 1 and 3 above are discharged.

Implemented-by: claude/issue-23650-retire-showstar
Reviewed-by: session_01HjR8RUwTPQ3TgbfKihmxp9

VERDICT: PASS


Generated by Claude Code

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review October 16, 2026 04:01
@objectstack-fleet
objectstack-fleet Bot enabled auto-merge October 16, 2026 04:01
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Oct 16, 2026
Merged via the queue into main with commit ae0ca66 Oct 16, 2026
49 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/issue-23650-retire-showstar branch October 16, 2026 04:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation protocol:ui size/l tests tooling

Projects

None yet

2 participants