Skip to content

fix(spec): re-measure the four #9881/#9972 objectui pin citations at the current pin, and gate the class - #10439

Merged
qq9340100 merged 3 commits into
mainfrom
claude/issue-10274-pin-citation-refresh
Aug 21, 2026
Merged

fix(spec): re-measure the four #9881/#9972 objectui pin citations at the current pin, and gate the class#10439
qq9340100 merged 3 commits into
mainfrom
claude/issue-10274-pin-citation-refresh

Conversation

@qq9340100

@qq9340100qq9340100 commented Aug 20, 2026

Copy link
Copy Markdown
Collaborator

Fixes#10274

The four #9881/#9972 read-point records cited .objectui-sha = 82a94170c. #10137 moved the pin to 9a3daf8d3, so the sentence "the objectui pin this repo builds against" named a pin this repo does not build against. The records did not become wrong — they became unverifiable, which is the exact state they were written to end.

This re-measures all four at the current pin and adds the gate that closes the class, so the next pin bump cannot silently re-rot them.

Note on this body: GitHub's sanitizer strips short angle-bracket fragments even inside backticks and inside fenced blocks, so JSX and sha placeholders below are described in words rather than quoted. The authority is the diff.


1. Re-measurement — not a sha find-and-replace

Each read point was re-derived from the objectui blob at the current pin, not edited in place:

git -C ../objectui show 9a3daf8d37ad973a621e5edd276fe32467f90684:packages/components/src/renderers/layout/containers.tsx
recordcited anchorre-measured at 9a3daf8d3verdict
page:tabs item iconLazyIcon in TabsTriggercontainers.tsx:662-665662-668live; anchor corrected
page:tabs registration items input:721:721live; unchanged
page:accordion item iconLazyIcon in AccordionTriggercontainers.tsx:851-853851-857live; anchor corrected
page:accordion registration items input:898:898live; unchanged

Both read points are alive at the current pin. Neither moved nor died, so no docblock needed more than a citation refresh.

The finding that justifies the "⛔ not a find-and-replace" instruction

The two icon anchors were wrong when they were written, not merely stale. containers.tsx is byte-identical between the old and new pin across the whole read-point region:

$ head -1402 containers.at-oldpin.tsx | sha256sum
d68c0e2aded313b52470c4c90fe3e381f95ff1e0b117a08f89231e4f5071266a
$ head -1402 containers.at-pin.tsx | sha256sum
d68c0e2aded313b52470c4c90fe3e381f95ff1e0b117a08f89231e4f5071266a

(The two pins differ only from line 1403 down, in the unrelated page:headerreadMax region.)

Both cited ranges stop mid-element. Reading the tab trigger line by line at the pin: 662 opens the item.icon guard and its paren; 663 opens the LazyIcon element; 664 is its name prop; 665 its className; 666 its aria-hidden; 667 the self-closing bracket; 668 the guard's closing paren and brace; 669 is the label span. So the element the record points at runs 662-668, and the cited 662-665 cut it off at the className — naming three of its seven lines. 851-853 did the identical thing to the accordion's copy (which runs 851-857), stopping at its name prop.

Both truncations were equally wrong at the old pin, per the hashes above. A sha-only rewrite would have preserved both errors and hidden them behind a fresh-looking sha. This is the #10053 MetricCard near-miss repeating, and it is now written into the gate's failure text and its ledger entry.

Incidentally: the card notes 82a94170c was unreachable in the shallow ../objectui checkout when it was filed. It is reachable now, which is what made the byte-identity comparison possible.

The claims around the anchors were re-verified too, not just the line numbers — the tab icon's mr-1.5 h-3.5 w-3.5 shrink-0 opacity-70 / aria-hidden and its position left of the label span (:669); the accordion icon's grouping with the label inside the trigger's one wrapping span (:850:859); and both registrations' documented items shapes.

2. check:objectui-pin-citations — the class-closing gate

packages/spec/scripts/check-objectui-pin-citations.ts. Prose has no dependency edge to the pin file; this is that edge.

It keys on two canonical spellings, because two different things get said about a sha and only one of them can rot:

spelling (in words)claimchecked against .objectui-sha
the token .objectui-sha in backticks, then =, then the sha in backticksthis IS the pin we build againstyes
the token .objectui-sha in backticks, then the word pin, then the sha in backticksmeasured AT that pin — a dated recordno

Forcing historical records forward (#5010 absorbed at 09987b68, a renderer's branch semantics measured at 665661ab0932) would demand re-measuring settled history on every bump, and rewriting their shas without re-measuring would be a lie the gate manufactured.

An unrecognised spelling FAILS rather than being skipped. A source scan sees only the spellings it knows, and an unrecognised one produces no flag — silently, the failure mode AGENTS.md records for check:cross-package-test-inputs. A .objectui-sha mention naming a sha-shaped token in neither form is a hard failure asking the author to pick one. Mentions naming no sha are skipped (they make no falsifiable claim), and that boundary is stated in the header rather than left implicit.

Discovered population on the merged tree — 971 spec sources, 12 citations, no allowlist anywhere:

asserting 9a3daf8d3 current packages/spec/src/data/api-methods-batch-conformance.test.ts:64
asserting 9a3daf8d3 current packages/spec/src/ui/component.test.ts:281
asserting 9a3daf8d3 current packages/spec/src/ui/component.test.ts:364
asserting 9a3daf8d3 current packages/spec/src/ui/component.test.ts:1950
asserting 9a3daf8d3 current packages/spec/src/ui/component.zod.ts:638
asserting 9a3daf8d3 current packages/spec/src/ui/component.zod.ts:1501
asserting 9a3daf8d3 current packages/spec/src/ui/component.zod.ts:1675
asserting 9a3daf8d3 current packages/spec/src/ui/component.zod.ts:2150
historical 09987b68 historical packages/spec/src/conversions/registry.ts:2586
historical 09987b68 historical packages/spec/src/conversions/registry.ts:5980
historical 665661ab0932 historical packages/spec/src/conversions/registry.ts:6601
historical 82a9417 historical packages/spec/src/ui/expression-bindable-text-keys.zod.ts:49

8 asserting / 4 historical.component.zod.ts:1675 and :2150 are the two records #10270 added; they were already correct and are untouched. The batch-conformance site is asserting because #10521 (issue #10435) re-measured it and landed on main — see section 3.

Deliberately no gen:. The obvious automation — rewrite every cited sha to the pin — is the one thing this gate must never offer, for the reason section 1 measured: the sha is not the record, the anchors are. Classified NO_GENERATOR in the check:generated ledger for check:browser-reachable-entries' reason exactly (a gen: would grant by command the one thing that has to be earned by measurement). Ledger reconciles on the merged tree: 25 check: + 17 gen: scripts, all classified (… 9 source audits …).

Why it scans raw text and not scripts/js-comment-mask.mjs: that helper answers "comment or code?", and this gate does not have the question — a pin citation is a citation wherever it is written, and nothing is stripped, so there is no private stripComments to drift. Wrapped prose is handled generally: comment decoration is peeled and lines joined before matching, with a per-character map back to the original line so failures name a line a reader can open.

3. Spelling normalizations (declared — beyond the card's four sites)

The gate can only find citations spelled findably, so these sites were normalized. Token-level only; not one word of any claim changed.

4. Generated-docs propagation (commit 2) — and a correction to this body

The second expression-bindable-text-keys.zod.ts docblock is a gen:docs input: it is rendered verbatim into content/docs/references/ui/expression-bindable-text-keys.mdx. An earlier revision of this body claimed the diff "moves no generated artifact" — that was wrong, and CI is what falsified it (check:docs: "content/docs/references/ is out of date with packages/spec"). Recording the correction rather than quietly overwriting it, since a claim like that is exactly the kind a later reader would trust without re-checking.

Fixed by regeneration, never by hand-editing the mdx:

pnpm --filter @objectstack/spec gen:schema && pnpm --filter @objectstack/spec gen:docs

The result is a 2-line change carrying only the reworded citation — no other content moved. Nothing under content/docs/releases/ is touched.

5. Merge with main (commit 3)

git merge origin/main — merge commit, no rebase, no force-push. Three conflicts, all resolved and re-verified:

fileconflictresolution
api-methods-batch-conformance.test.tsthis branch's historical spelling vs #10521's re-measured asserting formmain wins (pre-adjudicated; section 3)
packages/spec/package.jsonboth sides added a check: script at the same insertion pointboth keptcheck:browser-reachable-entries (#10398) and check:objectui-pin-citations are independent gates
.github/workflows/lint.ymlmain split TypeScript Type Check into 4 lanes; this branch inserted a step in the pre-build source-audit groupboth kept — the step stays in that group (which main preserves), main's new lane jobs follow intact

The last two were additive collisions, not supersessions, and the workflow gates confirm main's restructure survived: check:workflow-status-functions now sees 49 jobs (was 45) and check:node-version32 setup-node steps (was 29).

Verification

Measured on the merged head 67e0ad6c1.

Reverse-verification, both legs, mutation proven on disk each time (run on 9a62304b3; the gate's logic is untouched by the merge). This gate reads source, not dist, so no rebuild is involved — the ablation's validity rests on the file the scanner opens.

  1. Citation goes stale — reverted component.zod.ts:638 to 82a94170c (on-disk: 82a94170c 0→1 occurrence, 9a3daf8d3 4→3 lines). Gate exit 1, naming component.zod.ts:638 cites 82a94170c. Restored; on-disk absence confirmed.
  2. The pin bumps — the class this actually closes. Replaced .objectui-sha with a fake sha (on-disk: fake present 1, real absent 0). Gate exit 1 listing all asserting citations as stale, and none of the historical ones. Restored; on-disk absence confirmed.

Both legs failed in the expected direction (red), and leg 2 confirms the gate fires on the pin move rather than only on an edited citation.

gate (on the merged head)verdict line
check:objectui-pin-citations✅ 8 asserting objectui pin citation(s) match .objectui-sha (9a3daf8d3), 4 historical citation(s) recorded and not checked, across 971 spec source(s).
check:objectui-pin-citations --self-test✅ self-test: asserting citations are checked against the pin and historical ones are not; …
check:generated --reconcile-only✓ … 25 check: + 17 gen: scripts, all classified (14 gated, 9 source audits, …)
check:docs✅ 229 generated files in sync with packages/spec (after gen:schemajson-schema/ is a gitignored artifact a fresh worktree lacks, and the gate hard-refuses rather than reporting from a tree it never read)
check:nul-bytesOK (scanned 6177 text file(s) … no raw ASCII control bytes)
check:workflow-status-functionsOK (scanned 26 workflow file(s), 49 job(s), 24 job-level if: expression(s))
check:node-versionOK (32 setup-node step(s) across 26 workflow(s), all on Node 22)
check:required-contexts / check:shard-attestationboth OK

Pre-merge head 9a62304b3 additionally ran green: spec suite Test Files 415 passed (415) / Tests 11071 passed (11071); check:authorable-surface; check:scripts-typecheck + spec typecheck; check:cross-package-test-inputs; check:engine-double-contract; check:where-matcher; check:query-options-erasure; check:slot-lookup; check:spec-parsed-alias; check:type-check-coverage; check:type-source-resolution; check:merge-driver; check:doc-anchors; check:docs-redirects; check:docs-audit-scope; check:role-word; check:quick-reference-counts; check:published-readme-links; check:doc-authoring; check:docs-image-tagnone new on every ratchet.

Changeset

None — skip-changeset. The packages/spec/src diff is comment lines only: zero .describe(), zero schema, zero export, zero runtime behaviour, and check:authorable-surface leaves the JSON Schema tree clean. The one generated artifact that moves is a docs-site reference page (section 4), which publishes no package. So this PR releases nothing and takes the label route. An empty-frontmatter changeset is the wrong instrument here and check:empty-changeset rejects newly added ones — its header records why (an empty changeset is a real input to changesets/action and can take the hasChangesets && !hasNonEmptyChangesets branch that silently stalled 17.0.0-rc.2, which the label cannot do).

Scope

Per the card's fences: prose + a new observing gate, no acceptance change anywhere. check:objectui-pin-citations only observes; it relaxes nothing. #10270's two records are untouched.


Generated by Claude Code

@github-actions

github-actionsBot commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/spec, touching 2 documentable anchor(s).

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

  • content/docs/releases/v15.mdx(via PageTabsProps (symbol))

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
  • 1 changed file(s) yielded no anchor (packages/spec/src/ui/expression-bindable-text-keys.zod.ts) — pages documenting those are invisible to this run

Coarse fallback — 122 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 359f5956d7910aed7ae9f8fccc9fbb988b3e4882packageMentionDocs.

Which tree this was computed on

This run read content/docs from 23a73edb6780ca1580d5b55061b78201a41afa7b — the merge of head 67e0ad6c1ac3a467a9130a85701e94ca3602deed into base 359f5956d7910aed7ae9f8fccc9fbb988b3e4882, 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 23a73edb6780ca1580d5b55061b78201a41afa7b && git checkout 23a73edb6780ca1580d5b55061b78201a41afa7b
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 359f5956d7910aed7ae9f8fccc9fbb988b3e4882 67e0ad6c1ac3a467a9130a85701e94ca3602deed && git checkout -B drift-repro 359f5956d7910aed7ae9f8fccc9fbb988b3e4882 && git merge --no-ff 67e0ad6c1ac3a467a9130a85701e94ca3602deed
node scripts/docs-audit/affected-docs.mjs --json 359f5956d7910aed7ae9f8fccc9fbb988b3e4882

⚠️ 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 359f5956d7910aed7ae9f8fccc9fbb988b3e4882 → pass the list as
args.docs, on the commit named under Which tree this was computed on.

@qq9340100qq9340100 added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Aug 20, 2026 — with Claude
…r the normalized pin citation
The module docblock feeds content/docs/references/ via gen:docs, so the
citation-spelling normalization propagates. Generated, not hand-edited:
pnpm --filter @objectstack/spec gen:schema && ... gen:docs
@github-actionsgithub-actionsBot added the documentation Improvements or additions to documentation label Aug 20, 2026
@qq9340100
qq9340100 marked this pull request as ready for review August 21, 2026 00:56
@qq9340100
qq9340100 enabled auto-merge August 21, 2026 00:56
qq9340100 pushed a commit that referenced this pull request Aug 21, 2026
…e current objectui pin and promote the citation to the asserting spelling (#10435)
The SINGLE_RECORD_WRITE_ONLY entry for sys_api_key justified itself with a
present-tense claim ("the console build this release pins") while citing
.objectui-sha 6314e87f2 — but the release pins 9a3daf8d37ad. Re-measured all
three claims at 9a3daf8d3 (they hold, see PR body) and promoted the citation
to the asserting spelling so check:objectui-pin-citations (#10274/PR #10439)
re-checks this site on every future pin bump.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016gcKVsiywU9CcS96S5t9qD
…n-citation-refresh
# Conflicts:
#	.github/workflows/lint.yml
#	packages/spec/package.json
#	packages/spec/src/data/api-methods-batch-conformance.test.ts
@qq9340100
qq9340100 added this pull request to the merge queueAug 21, 2026
Merged via the queue into main with commit d1ba685Aug 21, 2026
37 checks passed
@qq9340100
qq9340100 deleted the claude/issue-10274-pin-citation-refresh branch August 21, 2026 03:27
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci/cddependenciesPull requests that update a dependency filedocumentationImprovements or additions to documentationprotocol:dataprotocol:uisize/lskip-changesetPR has no user-facing published change; bypasses the changeset gateteststooling

Projects

None yet

2 participants

@qq9340100@claude