Uh oh!
There was an error while loading. Please reload this page.
fix(spec): re-measure the element:button icon record at objectui 9602dc820 — the describe named a normaliser the renderer no longer has - #13029
Conversation
…dc820 The `.describe()` on `ElementButtonPropsSchema.icon` told authors the renderer resolved the name "using its own PascalCase normaliser and rename map". That clause went false when objectui#5993 deleted `button.tsx`'s file-local `toPascalCase` + `iconNameMap` + `icons` index and routed the button through the shared `resolveIcon` every `action:*` site already used — the duplicate was itself the defect, since a rename added to `resolve-icon.ts` to absorb a lucide retirement reached every action site and silently missed `ui:button`. Correct the shipped prose, re-point both read-point records' anchors at the new pin (the resolution anchor now hops into `renderers/action/resolve-icon.ts`), and move exactly those two citations to `.objectui-sha` = `9602dc820`. Nothing an author may write changed: the key is still read, still rendered per `iconPosition`, still suppressed while `loading`, and an unknown name still resolves to nothing rather than a fallback glyph. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LpRNHxWZgSUgVnFT9mQQo4
📓 Docs Drift Check1 anchor(s) derived from 1 changed package(s); no hand-written page names any of them, so this run has nothing to list — not a clean bill of health. This check sees only pages that NAME a derived anchor: one that documents this change in prose, or enumerates it in an authoring dialect, names none and stays invisible to it on every run. What this run could not see
Coarse fallback — 126 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 07cd6864a94f7c2a11b31cdf9e0ad09e13d4b329 && git checkout 07cd6864a94f7c2a11b31cdf9e0ad09e13d4b329
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 0da7cd2c1114649755b7f9f45a7dbbe34985ac6e 5593b54e3680285b20e02d89348ba647e1d0dfae && git checkout -B drift-repro 0da7cd2c1114649755b7f9f45a7dbbe34985ac6e && git merge --no-ff 5593b54e3680285b20e02d89348ba647e1d0dfae
node scripts/docs-audit/affected-docs.mjs --json 0da7cd2c1114649755b7f9f45a7dbbe34985ac6e |
os-trump
commented
Aug 29, 2026
Closing as superseded — plan A executed. This PR's entire content (head #12968's closure now rides #12955's landing: the seat closes it with a pointer when #12955 merges (kept out of #12955's body to avoid a double-claim window against this PR while it was open, and recorded here instead). Generated by Claude Code |
Fixes#12968
The
.describe()onElementButtonPropsSchema.iconshipped a clause that had gone false: it told authors the renderer resolves the name "using its own PascalCase normaliser and rename map". objectui#5993 deletedbutton.tsx's file-localtoPascalCase+iconNameMap+iconsindex and routed the button through the sharedresolveIconeveryaction:*site already used. The duplicate had been the defect in its own right — a rename added toresolve-icon.tsto absorb a lucide retirement reached every action site and silently missedui:button.Three steps, one edit, exactly as the card ruled: correct the prose, re-point both read-point records' anchors, and move exactly those two citations to
`.objectui-sha` = `9602dc820`.⛔ MUST READ FIRST — this PR cannot land on its own
Measured, not predicted.
check-objectui-pin-citationsclassifies a citation asassertingand then requirespin.startsWith(citedSha). With this tree's.objectui-shastill at190fbd01d0615e2e168faf9e08b8ad7844bc039d, the two moved citations do not prefix-match, so the gate reds. Its own verdict line, run on this branch:That step runs in job
typecheck-source-gates, which is a member of theTypeScript Type Checkaggregator (OS_AGGREGATOR_MEMBERSinlint.yml) — a required context. So the merge queue will not land this PR by itself, and ⛔ auto-merge must not be armed on it.The deadlock is mutual, and the resolution is coordination
.objectui-shamaintoday190fbd01d190fbd01d190fbd01d9602dc8209602dc820190fbd01d9602dc8209602dc820Neither PR is green in isolation; only the joint tree is. Two ways out, for the PM / maintainer to pick:
automation:packaged#12955 merges this branch into its own (or the reverse), so a single PR carries both the bump and the re-measured records. That tree is green, needs no override, andmainis never red. The split ruling that created this card was about who authors and authorises the contract prose, not about which merge commit it rides in — that authorship has happened here, on this card, underdomain:spec, so combining afterwards re-litigates nothing.automation:packaged#12955 first, this PR second.chore(console): bump the objectui pin 190fbd01 → 9602dc82 so a stock console build resolvesautomation:packaged#12955 lands carrying the red the card already declares accepted (an admin merge, since the queue will refuse it); the moment.objectui-shamoves to9602dc820, this PR is green and rides the queue normally. Exactly one override, and it is spent on the red that already has a ruling behind it.⛔ The mirror-image order — this PR first — is available but strictly worse: it manufactures a second accepted-red that nobody has ruled on, and during the window
mainwould tell authors about a shared resolver while the console it actually ships is built at190fbd01d, where the button still carries its private copy.I have flipped nothing and armed nothing. The review chain owns enqueue.
What was re-measured, and against what
Every anchor was re-derived by reading the objectui tree at
9602dc820450(git show 9602dc820450:...), not carried over from the card:190fbd01d9602dc820— confirmedbutton.tsx:44-47button.tsx:36—const Icon = resolveIcon(schema.icon);, and it now hops into a second filebutton.tsx:14-27resolve-icon.ts:14-24(toPascalCaseat:14-19,iconNameMapat:21-24) and:30-35(resolveIcon).button.tsx:14-27is now imports plus theforwardRefopeningbutton.tsx:69/:71button.tsx:57/:59—mr-2 h-4 w-4/ml-2 h-4 w-4, unchangedbutton.tsx:82-98button.tsx:70-87(label,variant,size,className; noicon),:88-92is nowdefaultPropsOne substantive correction beyond line numbers: the old prose said an unknown name resolves to
undefined.resolveIconendsreturn (icons as Record)[mapped] ?? null, so the record now saysnull. The author-visible outcome is the same — no glyph, no diagnostic — and theLazyIconcontrast survives intact (lazy-icon.tsxis byte-identical across the move;getLazyIconstill degrades an unknown name to theDatabaseglyph).The card's four "what did NOT break" facts were taken as given and not re-established, per the ruling.
Two-pin coexistence is intentional and holds
Exactly the two ruled records moved. The other citations in these files stay where they are: blanket-updating them would fabricate reviews that never happened. The gate's
--liston this branch confirms the population — the six otherassertingcitations still naming190fbd01dremaincurrent, and thehistoricalspelling is not checked at all. No record other than the two moved ones reds, so there is no fork to report on the card.The one addition beyond the card's three steps
The
#10053pin block asserted only that the describe nameslucide-reactandLazyIcon. Both survived the clause going false — which is how it shipped false. Added one assertion,toContain('resolveIcon'), so the corrected claim is pinned by the block that exists to pin it.Ablated to prove it can fail rather than assuming it: reverted the describe to the stale wording, confirmed the mutation landed on disk by occurrence count (injected clause 1, removed clause 0) and by blob hash (
e86ff735…to88aaef5a…), then re-ran:Exactly the new assertion, nothing else. The restore leg was proven too, not assumed:
git checkout HEAD -- ...(absolute path,trap-guarded), restored blobe86ff735c569aa73738dad72b8efbd624103267fequal to the HEAD blob,git diff HEADempty,git status --porcelaincarrying noMM.Changeset: measured, not guessed
check:generatedproved exactly one artifact stale —content/docs/references/**— andgen:docsmoved one line ofcontent/docs/references/ui/component.mdx, the customer-facing docs projection of this describe. A reader-visible artifact moves, so this is not askip-changesetdiff: patch on@objectstack/spec, text face. Regenerated by repo tooling only (check:generated --fix, which regenerated only the one it proved stale).Gates
All runs below are on
5593b54e3, the pushed head (the ratchet-relevant families were re-run on it after the final amend; that amend touched the commit message only —git diff a080d453a 5593b54e3is empty, so the earlier full sweep and this one read the same tree). Exit codes captured before any pipe, and each verdict quoted from the gate's own output rather than from a bare shell status. Union derived at this tree bynode scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack(which reads its own change set from the merge base — 4 paths).Green (49):
check:doc-authoring("13306 customer-facing string(s) across 672 spec sources clean — no internal issue-id references (message 778 · strictObject 3282 · tombstone 751 · describe 8495)" — the widened Rule 3 holds for the new prose),check:generated(14/14 after thegen:docsregeneration),check:docs,check:authorable-surface,check:skill-examples,check:skill-refs,check:liveness,check:empty-state,check:strictness-ledger,check:variant-docs,check:doc-anchors,check:doc-formula-expressions,check:doc-security-posture,check:docs-audit-scope,check:docs-redirects,check:docs-single-h1,check:quick-reference-counts,check:role-word,check:published-readme-links,check:published-files,check:react-page-adapter-contract,check:spec-parsed-alias,check:slot-lookup,check:page-declaration-shape,check:test-source-alias,check:type-source-resolution,check:merge-driver,check:cross-package-test-inputs,check:objectql-double-limit,check:engine-double-contract,check:where-matcher,check:query-options-erasure,check:nul-bytes,check:changeset-gate-self-tests,check:objectui-changeset,check:pm-half-states, and thenode scripts/…families (doc-frontmatter,doc-route-spelling,docs-section-name,section-landing-index,comment-mask-adoption,keyed-text-bounds,plugin-teardown-shape,undeclared-dep-imports,ci-filter-parity,adr-0087-registration,changeset-no-major,empty-changeset,release-rehearsal-clone --self-test,docs-audit/check-affected-docs,docs-audit/check-drift-comment).Tests and types:
Both edited files confirmed inside that tsc program rather than assumed —
tsc -p tsconfig.test.json --listFileslistssrc/ui/component.test.tsandsrc/ui/component.zod.tsonce each, so "typecheck green" really covers this diff.Red — one, and it is the subject of this PR:
check:objectui-pin-citations— red by design until the pin bump lands. See the deadlock section above.Not measured (reported as such, never as green or red):
node scripts/pm/check-half-states.mjs— exit 3, its own PREREQUISITE-NOT-MET path: the container'sGITHUB_TOKENis a proxy placeholder, so "no issue was listed, no predicate (H1–H16) ran … it is no reading at all". A PM board sweep, unrelated to this diff.node scripts/check-dev-prereqs.mjs— refuses on 66 of 67 workspace packages having no builtdist/in this worktree; a local-environment prerequisite, not a finding.Repo-wide
pnpm lintwas not run locally and is left to CI, which runs the farm regardless.Generated by Claude Code