Uh oh!
There was an error while loading. Please reload this page.
fix(docs-audit): give declinedIn the type-declaration discriminator - #11500
Merged
Conversation
…#10901) `declinedIn` was the last `route:`/`client:` scan in `affected-docs.mjs` still deciding "is this in code position?" for itself. #10793 taught the row recognizer and the first term of its denominator to read through both of #10500's exact discriminators; its complement did not move, so a literal-union `route:` TYPE member written in either of the two quotes the recognizer declines was billed as a value the parse FAILED to read — a named entry, a PARTIAL-read verdict and exit 1, on a ledger that is completely accurate. The region list now arrives as a required parameter from the one caller that already computes it, with no default: a call site that forgot the discriminator would silently reintroduce exactly the second opinion this closes. `offset` makes the returned index absolute, so the in-window slice's coordinate translation happens once inside the function instead of at one of the two call sites. Both call sites were reachable and both are covered: a leading entry interface arrives through the file-wide `route:` sweep, a trailing one lands inside a row window and reached the in-window `client:` sweep (measured before the fix: `clientsDeclared` 2 on a file declaring one client, exit 1). ⛔ The other discriminator is deliberately NOT applied. This still reads raw bytes, so a declined spelling quoted in a COMMENT is still billed as an unread row — that is #10794, closed `not planned`, and not this change's to reverse. The boundary is pinned in `--self-test` so whichever card eventually takes on #10794 moves the pin rather than finding none. Self-test: 339 -> 366 cases. 15 of the new cases fail against the previous `declinedIn` and pass after. Live delta is zero and predicted so in advance: 0 quoted `route:`/`client:` leads inside any type declaration across all seven ledgers, and `--bridge-coverage` is byte-identical before and after (268 of 268 route / 222 of 222 client / 177 unreachable, exit 0). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015ahemw8RcTgqtxrj15PEZx
Contributor
📓 Docs Drift CheckNothing in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 0 changed package(s)), so this run has no opinion about the docs. |
os-steve
marked this pull request as ready for review
August 24, 2026 01:34
Uh oh!
There was an error while loading. Please reload this page.
This was referenced Aug 24, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes#10901
declinedInwas the lastroute:/client:scan inscripts/docs-audit/affected-docs.mjsstill deciding "is this in code position?" for itself. #10793 taught the row recognizer — and the first term of its denominator — to read through both of #10500's exact discriminators. Its complement did not move, so a literal-unionroute:TYPE member written in either of the two quotes the recognizer declines was billed as a value the parse failed to read: a named entry, a PARTIAL-read verdict, and exit 1, on a ledger that is completely accurate. That is the false red the type-declaration exclusion exists to prevent.Route taken: (2), the narrow one — chosen on measurement, not on adjective
Triage ruled (2) and left (3) available "if it turns out equally cheap". It is not. I built (3) as a working probe (fold
declinedInintodeclarationsInas its missing third filter, with the one declaration list computed once per file so the in-window call cannot mis-lex a slice) and ran the differential againstorigin/mainon five shapes. (3) passes the existing 339 self-test cases, so the measurement had to be behavioural rather than a pass/fail:origin/mainroute:type member, double-quoteddeclined 1, exit 1declined 0declined 0declined 1, exit 1declined 0declined 0declined 1, exit 1declined 0declined 1, exit 1declined 2,routesDeclared 3declined 1, value unnameddeclined 2,routesDeclared 3client:uniondeclined 1, exit 1declined 0declined 0(3) changes four populations, two of them uninvited:
declinedInstill reads raw text, so aroute:quoted in a comment in ANY other spelling is billed as an unread row — a PARTIAL-read verdict on an accurate ledger #10794, closednot planned("the loud direction… polish without a puller"). Folding intodeclarationsInappliescodeOnlyas a rider and silently reverses that closure. Not this card's to reverse.declarationsInmatches[ \t]*after the colon wheredeclinedInmatches\s*, so under (3) the declaration stops being named (route:with an empty value) while still being counted. "Produces nothing a reader can act on" is the silence this file exists to break.So (2) it is: it changes exactly the population this card is about, in both quote spellings, at both call sites. D is pre-existing and byte-identical on
origin/mainand on this branch — filed unassigned as #11494.What changed
The region list arrives as a required parameter from the one caller that already computes it, with no default — a call site that forgot the discriminator would silently reintroduce exactly the second opinion this closes.
offsetmakes the returnedindexabsolute, so the in-window slice's coordinate translation happens once inside the function instead of at one of the two call sites.Both call sites were reachable and both are covered:
route:sweep;client:sweep. Measured before the fix on that shape:clientsDeclared2 on a file declaring one client, one named declined entry, exit 1.⛔ The other discriminator is deliberately not applied. This still reads raw bytes, so a declined spelling quoted in a comment is still billed as an unread row (#10794). Applying
codeOnlyhere is also not free of its own accord: it blanks string contents, and this scan's whole job is to quote the unread spelling back at the reader, so a masked window would nameroute: ""for every entry. The boundary is pinned in--self-testso whichever card eventually takes on #10794moves that pin rather than finding none.Evidence
All figures below are from this branch at
c2fc7771.The non-vacuity proof is synthetic, and it has to be. The live delta is zero, so a green live run proves nothing about this change — stated as a prediction before running, then checked.
Fail-before / pass-after, identical case text, run against
origin/main'sdeclinedInand against this one:Both quote spellings are pinned apart, not assumed. They come out of one regex alternation and one code path and were measured behaving identically — which is the reason to pin them separately rather than to trust one for both.
Live safety check — predicted NO CHANGE, and it held.
--bridge-coveragebefore and after is byte-identical (md5 201a2b4850f62b5f9f0133547d0e907fboth runs), exit 0 both:The claimed live-zero was verified here rather than inherited, with a positive control. Across all seven ledgers: 0 quoted
route:/client:leads inside any type declaration, out of 490 quoted code leads. The same scan finds the lead in the fixture (1 per spelling), so the zero is a measurement and not a broken scan.The exclusion is still load-bearing — measured, not assumed. Ablating
typeDeclRegionsto return[](mutation proven on disk by anchored grep; restored by anEXIT INT TERMtrap;affected-docs.mjsis executed directly by node, so the edited bytes are the bytes that run):That is today's tree's form of the note the file records (
259 of 266): seven ledgers, oneroute: string;member each,268 + 7 = 275.--bridge-coverage's consumer is unaffected..github/workflows/docs-drift-check.ymlreads onlybridge.measured,bridge.reachable,bridge.clientRowsandbridge.unreachablefrom the--jsonarm. This change does not touchrows, so none of those four can move; the header's shape is unchanged.Gates
Derived with
node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack(change set taken from the script's own merge-base derivation, re-derived after the final commit — the set was unchanged), and run atc2fc7771. All green, each quoted from the gate's own verdict line:pnpm check:docs-audit-scope—✓ affected-docs self-test: 366 cases pass./✓ check-audit-scope self-test: 24 cases pass.pnpm check:entry-guard—✓ check:entry-guard: 139 scripts/ file(s) — every entry guard goes through invoked-as.mjspnpm check:parse-guard—✓ check:parse-guard: 138 scripts/ file(s) — every TypeScript parse goes through ts-parse.mjs.pnpm check:cross-package-test-inputs/node scripts/check-cross-package-test-inputs.mjs—OK: 14 package(s) read outside themselves, all declaredpnpm check:pnpm-filter-targets—✓ check:pnpm-filter-targets: 120/148 --filter occurrence(s) … resolvepnpm check:pm-governed-merges—✓ check-governed-merges --self-test: 129 assertionsnode scripts/check-ci-filter-parity.mjs—OK: all 89 declared cross-package glob(s) … are coverednode scripts/docs-audit/check-affected-docs.mjs—✓ affected-docs self-test: 366 cases pass.pnpm check:nul-bytes—check-nul-bytes: OK (scanned 6448 text file(s) … no raw ASCII control bytes).No narrowing to declare:
pnpm lint(eslint . --no-inline-config, repo-wide) was run in full under the shared verify lock — exit 0 in 68s.No changeset: this touches one CI/tooling script under
scripts/and publishes nothing, so the PR carriesskip-changeset.Closing-reference hygiene, and one measurement that changed how I report it
An earlier revision of this work carried a closing keyword before a reference to #10794 in both the PR
body and the commit message. #10794 was closed
not plannedby a human on 2026-08-21 and this changeexplicitly does not act on it, so either would have recorded that decision as undone by an unrelated PR.
Both are gone here: the body was reworded, and this branch was re-landed from
origin/mainwith thecommit message reworded too, since a pushed commit message cannot be corrected without a force-push.
The predecessor is #11495, closed as superseded; its diff and this one are byte-identical (same blob
cac567a9, same patch md5f99e1da7e5c3c5df6e19aaaa54a90808, same+184 / -14).resolve/resolves/resolvedis itself a closing keyword, alongsideclose/closes/closedand
fix/fixes/fixed— rewording one into another is not a fix. The wording here (takes on) usesnone of them, and both body and message were rescanned for keyword+
#nand keyword+URL forms.closed_by_pull_requestsREST field is not usable as proof of this, in either direction.After the fix it reads
total=0on #10794 — but it also readstotal=0on #10901, whose intendedclosing line is intact at the top of this body, and a control over four other OPEN PRs in this repo carrying
Fixes #n(#11469, #11466, #11406, #11393, draft and non-draft alike) shows
total=0on all four target issues.So its zero says nothing about any particular PR. The discriminating evidence is the source text that the
merge-time parser actually reads — the stored body and the commit message, both rescanned above — not the
field. (
closingIssuesReferencesvia GraphQL would have been the direct check; it returns HTTP 403 forthis token.)
Generated by Claude Code