Skip to content

docs(examples): cite the #6318 assertion by content, not by line address (objectui#7853) - #7893

Merged
os-sam merged 1 commit into
mainfrom
claude/issue-7853-line-address-citation-rot
Sep 6, 2026
Merged

docs(examples): cite the #6318 assertion by content, not by line address (objectui#7853)#7893
os-sam merged 1 commit into
mainfrom
claude/issue-7853-line-address-citation-rot

Conversation

@claude

@claude claude Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

Fixes #7853

Ruling on the card's A/B/C fork was A — cite by content. This implements A on the one
citation the card names, and reports the one measurement that makes B decidable. No gate is
built here, no script is committed, nothing is added to ci.yml.

The sentence this card is really about

The citation was already stale on main before this PR — and it was made stale by a
change proven to be comment-only.
An edit that changed no behaviour whatsoever falsified a
statement in a different file, and nothing in the repository raised a hand.

That is the whole defect. Not "a number is wrong" — the number was right when it was written.
The defect is that the number became wrong silently, and no instrument in this repo is
capable of noticing.

Fact-check on current main (re-confirmed here, not taken on trust)

Measured at 659235cb6:

reading result
line of the cited assertion in safe-validate-corpus-6318.test.ts 117 (the card measured 98 at 3faaa7d0f)
line of the citing passage in component-fixture-declared-keys.test.ts 835 (unmoved)
instruments that went red because of the drift none — 24 success + 2 skipped, 0 failures

The drift-causing commit is 7e6de4b05 (squash of #7860, landed 2026-09-06T01:12:55Z), and it
really is comment-only: it touches exactly one file, +24 / -5, and 0 of its 29 diff lines
are non-comment lines
. Net +19; 98 + 19 = 117. Its check-runs: 24 success, 2 skipped,
zero failures.

⚠️ Worth stating plainly, because it is worse than "off by 19": line 98 of that file today is
not a near-miss. It is a comment line inside a different it(...), in a different
describe(...) block
, about a different subject. A reader who followed the old address
landed somewhere that reads plausibly and says nothing about the claim.

What changed

One docblock passage in examples/schema-catalog/test/component-fixture-declared-keys.test.ts.
The citation now names the assertion's content and the enclosing it(...) title, and
carries no line number. The file name is kept — that part is a stable pointer, and dropping it
(option C) was rejected.

The argument the passage makes, and the pin below it, are untouched; the card says that block
reads soundly and this PR does not reopen it. The cited file itself is not touched.

I also left a short note in the docblock saying the missing line number is deliberate, with the
reason. Without it the next reader "helpfully" restores an address, and we file this card again.

The quote-length trade-off, decided by measurement

The quote has to be long enough to be unique and short enough to be stable. I picked the
boundary by counting rather than by taste — occurrences across packages/** and examples/**:

candidate quote occurrences verdict
'type' in o 2 ⛔ not unique — and the second hit is this very file's own sweep code below, so a reader searching it lands on the wrong file
options.some((o) => 'type' in o) 1 chosen — shortest span that is already unique tree-wide
expect(options.some((o) => 'type' in o)).toBe(false); 1 ⛔ no uniqueness gained, and it buys two extra ways to rot falsely

So the chosen quote is the shortest unique span. Everything longer is pure cost: the
expect(...) / .toBe(false) wrapper is assertion style, and restyling it to .toBeFalsy()
would break the quote without changing the claim the passage leans on — a false alarm, which is
the one failure mode that would make people distrust loud rot. Everything shorter is ambiguous.

Naming the enclosing it(...) title is the second, independent handle: titles are prose a
human rewrites deliberately, so it survives mechanical edits that would move any line number.

This change is itself comment-only, proven the same two ways the card used

  • every one of its 33 diff lines is a comment line (0 non-comment)
  • esbuild@0.28.2 transform of both revisions is byte-identical:
    e95598747f099988e3c69b32b33269ae6498f08fe4a183991b2f03dbd08a20bc, 21710 bytes each

Effect on the citation class: the population goes 491 to 490 — exactly one address retired,
and I verified my own added prose introduces no new path.ext:line token.

The measurement that makes B decidable

⛔ A reading only. No gate, no committed script, no ci.yml change. Throwaway script, run once
on 659235cb6.

Population: 491, reproducing the card's grep verbatim
([A-Za-z0-9_.-]+\.(ts|tsx):[0-9]+ over packages/** examples/**) — the card's number
still holds exactly on current main.

1. In comments vs in code

bucket count
in a comment 353
in code, inside a string literal 69
in bare code 0
in a non-JS file (all .md: CHANGELOGs and READMEs) 69

Containing files: 224 .ts, 198 .tsx, 69 .md. Comment-vs-code is decided by this repo's own
scripts/js-comment-mask.mjs — the single answer to that question, whose self-test I ran green
(35 cases) — not by a hand-rolled regex.

The 69 in-code ones are the "probably a different thing" the card predicted: they are source
locations as test data (flow fixtures asserted by ConditionBuilder / FlowNodeConfigField
tests), not prose pointers. 0 citations sit in bare code.

2. Does the cited path resolve?

bucket count
resolves to a tracked file 381
does not resolve 58
ambiguous (basename matches more than one tracked file) 52

Resolution runs against git ls-files, so node_modules and build output are excluded by
construction
, not by a filter I wrote. This matters for the PM's reliability warning: the
false-positive sources named there do not silently mis-resolve, they land in the
unresolvable bucket where I can see them — citations into dist/, into .d.ts build output,
and cross-repo citations into the service-ai backend are all there. The 52 ambiguous ones are
honestly ambiguous (e.g. index.tsx:271, 21 candidate files) and are excluded from item 3
rather than guessed at.

3. Cited line beyond the file's line count — a LOWER BOUND on "definitely stale"

Among the 381 resolvable citations: 0.

⚠️ This is a lower bound, not a stale total, and it is a very weak one. It counts only
citations whose line number exceeds the file's length. It says nothing about whether a cited
line still contains what the citing text claims — that would mean opening 491 addresses, which
the card did not do and neither did I.

A zero needs a control before it can be reported, so I ran one. The detector fires correctly on
a known out-of-range citation and stays quiet on in-range ones, including at the exact
off-by-one boundary (:149 on a 148-line file flags; :148 does not). Headroom on the real
population: max citedLine / fileLength is 0.978, median 0.436, and only 5 of 381 sit
within 10 lines of EOF. So the zero is a property, not a near-miss.

⭐ What that zero actually tells you about B

The cheap criterion does not catch this card's own defect. The citation this PR is fixing —
known stale, demonstrably stale — cites line 98 of a 148-line file. In range. The control
confirms it: the out-of-range test returns false for it.

So the honest read for the B decision is:

  • a line-existence gate would have found 0 stale citations today, and would have been blind
    to the one defect that caused this card to be filed;
  • the useful version of B is therefore the stronger one the card names second — check that
    the cited line still contains the quoted text — which is a much larger build, needs the
    citation to carry a quote in the first place, and still faces the 52 ambiguous and 58
    unresolvable paths measured above;
  • 353 of the 491 are in comments, so the population a comment-scoped gate would govern is 353,
    not 491.

I am not recommending for or against B — that is the PM's or the director's call. This is the
number they asked for.

Checks

All run on the final commit 814c1a9d0, with git diff HEAD empty.

check result
pnpm lint (full repo, eslint . --no-inline-config) exit 0 — 47/47 tasks, 0 errors (2886 pre-existing warnings, unchanged)
examples/schema-catalog type-check exit 0
component-fixture-declared-keys.test.ts 43 passed / 43
check:control-bytes ✅ check-control-bytes: OK (scanned 6386 tracked text file(s); skipped 85 binary).
check:vi-mock-specifiers exit 0 ✅
check:vi-mock-inherit exit 0 ✅
check:shell-escape-residue exit 0 ✅
check:unreferenced-sources OK Every shipped source file in every covered package is reachable.

The type-check genuinely reads the edited file — tsc -p tsconfig.test.json --listFiles lists
it, so "type-check clean" is a measurement about this file rather than a vacuous pass.

⚠️ 93 local failures, none of them caused by this PR, and main is not broken. Running the
whole package suite locally, 93 tests fail in catalog-gallery-render.test.tsx (92) and
plugin-dashboard-gallery-render.test.tsx (1). Three readings place them:

  • on the pristine tree — the edited file reverted to its origin/main blob, hash-verified
    identical — those same two files fail with 93, the identical count;
  • the transpile of this change is byte-identical, so it cannot be causal either way;
  • on 659235cb6 CI's four Test (shard N/4) runs are all green.

So this is a local build-state artifact of my container (I built only this package's dependency
closure, and those two suites reach for docs-gallery host artifacts that a full build produces),
not a defect on main. Recording it because it cost a measurement, not as a finding against
the tree. Session: https://claude.ai/code/session_01KbJQ1y1J12nZxYzFWhP8Q3

Changeset — the checker's verdict, quoted verbatim, not guessed:

Compared the working tree with 659235c (merge-base with origin/main): 1 file(s) changed, 0
of them published source of a package the release covers, 0 of them a manifest whose published
contract moved, 0 under a package changesets ignores, 0 changeset(s) added.
✅ No source or published contract of a released package changed in this range, so no
changeset is owed.

So no changeset is owed at all — not even the empty-frontmatter form. examples/** is not a
released package. The dispatch's guess was the empty-frontmatter form; the checker overrides it,
and I obeyed the checker.

Governed surface — verdict quoted verbatim:

✅ NOT GOVERNED — 1 path(s) checked against 5 governed surface(s); none matched.
An ordinary pull request: the normal review and merge-queue route applies.

Left as draft regardless: the PM seat runs the pre-landing checks and drives the queue.

🤖 Generated with Claude Code


Generated by Claude Code

…ess (objectui#7853)

The citing docblock addressed `safe-validate-corpus-6318.test.ts` by line
number. A comment-only edit to that file -- every diff line a comment, both
revisions transpiling byte-identically -- moved the cited assertion from line
98 to line 117, making the address false. Nothing in the repository went red.

Cite the assertion's content and name the enclosing `it(...)` title instead,
and drop the line number. A quoted assertion rots too if someone rewrites the
assertion, but it rots LOUDLY: the quote stops matching anything, and one
`git grep -F` says so.

The quote is the shortest span that is unique tree-wide (1 occurrence); the
shorter `'type' in o` matches 2 sites, and the longer form only adds an
`expect(...).toBe(false)` wrapper that can be restyled without changing the
claim.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KbJQ1y1J12nZxYzFWhP8Q3
@os-sam
os-sam marked this pull request as ready for review September 6, 2026 02:07
@os-sam
os-sam added this pull request to the merge queue Sep 6, 2026
Merged via the queue into main with commit fa7d66c Sep 6, 2026
31 checks passed
@os-sam
os-sam deleted the claude/issue-7853-line-address-citation-rot branch September 6, 2026 02:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

2 participants