fix(qa): derive the authz matrix docblock's ledger figures instead of hand-typing them - #17719
Conversation
… hand-typing them `authz-conformance.matrix.ts` stated the REST route ledger holds "94 rows / 19 families" in the present tense and undated. Measured today the table holds 91 rows / 19 families: the families count was right, the row count was not. The cause was NOT the route-guarding move (`cc837dbfec`) whose own stale figures sat seven lines below it in the same docblock — guarding a route never changes its ledger disposition. It moved when #14503 took the three REST package read/delete rows out of the ledger (94 -> 91, `sdk` 84 -> 81; families unmoved at 19 because all three departing rows carried `family: packages`, which survives on the publish row). Two stale figures in one docblock with two entirely different causes; attributing this one to the neighbour teaches the wrong lesson, so the docblock now records the attribution. Correcting the constant alone would leave the mechanism intact, so all four figures in that sentence — both ledgers' rows and their families/domains — are now DERIVED and pinned in the companion test against a scoped read of the ledger each one names. The pin reads the PROSE rather than an exported constant: the defect is a sentence that went false, and lifting the number into a symbol would leave the sentence free to rot while the symbol stayed green. No symbol is exported from `packages/rest` or `packages/runtime` for it — both ledgers are only read, through the scoping rule `probeSource` already used, now extracted as `scopedSource` so there is one rule rather than two. The pin folds `//` continuations before matching, which is load-bearing rather than tidying: every figure in that docblock wraps mid-phrase, so a line-at-a-time literal search for the row/family phrase reads ZERO against the very file that carries it. A control case pins that failure, because a zero from an instrument blind to the shape is not a reading of absence. Five more cases prove the pin bites — stale rows, stale groups, a deleted figure, a second unpinned copy, and that the anchor is the ledger PATH so the dated "94 -> 91" attribution is not mistaken for a present-tense claim — each doctored from the measured value so no case hand-types a count of its own. The runtime ledger's "82 rows / 21 domains" in the same sentence measured CORRECT today and is pinned unchanged. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TSf4DV7ziu4V5j73e46b7c
📓 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. What this run could not see
Coarse fallback — 0 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): |
Review of record — ACCEPTHead reviewed: Reviewed-by:
Gates on this head, exit codes captured before any pipe
CI
⭐ All FOUR corrected figures re-measured by this seat, independently of the pinThe card was about one stale count. The PR corrects it and pins all four figures in that sentence. Both ledgers read off
⇒ every figure the docblock now states is what the tree holds, and
What makes this a pin rather than a corrected constant — and each property checked against the diffTriage asked for derivation over a retyped number, and this delivers the stronger thing:
The cause is recorded, and it is the half triage ranked firstThe docblock now states that the drift came from #14503 taking three REST package read/delete rows out of the ledger (94 → 91, The two sites it did NOT touch, each with a stated reason
The open question was ruled before this review, not past itThe dev raised the PR-body footer divergence. Answered on the card ( VerdictACCEPT. Two files, Generated by Claude Code |
Fixes #17111
authz-conformance.matrix.tsstated the REST route ledger holds "94 rows / 19 families" in the present tense and undated. The families count was right; the row count was not. This PR corrects it, records the real cause, and — because triage asked for the derivation rather than the constant — pins all four figures in that sentence to the ledgers they name, so the next drift is red instead of silent.Today's figure, derived (not taken from the card)
The card's reading was dated 2026-09-09 and the PM seat recorded the row count as NOT MEASURED, so it was re-derived from the ledger's own structure. Two independent derivations, chosen to share no failure mode:
route:/family:/domain:), scoped to the exported tableBoth agree. The brace-depth leg also returns to depth 0, which is the control on the scope itself: a slice truncated at a premature
\n];would end unbalanced.route:andfamily:occurrences are equal at 91 (androute:anddomain:equal at 82), which is the control on prose leaking into the scope — both fields are one-per-row.⇒ The REST row count is 91 today. The runtime figures in the same sentence measured CORRECT and are unchanged.
The PM seat's failed attempt (
grep -c "path:", which returned 1) missed because the ledger spells a rowroute:, notpath:.The cause is #14503, not the gate move next to it
Re-derived rather than inherited, by measuring the ledger at four refs through the contents API:
83863b2dfe— parent of #1450373709893f1— #14503 itselff6b7c53db7— the card's 2026-09-09 reading7173d7d1— this PR's base, todayThe three rows that left, and nothing arrived:
73709893f1is titled "fix(rest): the dispatcher's /packages domain is the one implementation of the package read and delete routes (#14503)". Families stayed at 19 because all three carriedfamily: packages, which survives onPOST /api/v1/packages/publish.⭐ So the drift was not the route-guarding move (
cc837dbfec) whose own stale figures sat seven lines below it in the same docblock: guarding a route never changes its ledger disposition. Two stale figures, one docblock, two entirely different causes. The docblock now carries that attribution, because a reader who corrects the number without it learns the wrong lesson.Pinned, not dated — and why
Triage: "this is the sixth card in this round on a hand-typed count that went stale. If a pin is cheap here, that is the better deliverable." It is cheap, so the figure is pinned, not dated.
The companion test already read both ledger files as source text through
probeSource, scoped to the exported table. That scoping is now extracted asscopedSourceand reused, so there is one scoping rule rather than two — two copies would let a rename widen one while the other stayed correct, and the wider one would still mint plausible numbers.Three deliberate choices:
//continuations before matching, and that fold is the instrument. Every figure in that docblock wraps mid-phrase, so a line-at-a-time literal search for the row/family phrase reads zero against the very file that carries it. A control case pins that failure.packages/restorpackages/runtimefor this. Both ledgers are only read, through the same mechanism already in place.Clause-②: nostill holds, as declared on the card. Hold #13776's two trigger files were read and not touched.The pin bites — measured both ways
Eight cases, each doctored from the measured value so no case hand-types a count of its own:
Reverse verification on the real file, from the committed state, with the mutation proved on disk before the run and the restore proved byte-identical after:
Six of the eight fired; the two CONTROL cases stayed green, which is what makes them controls. Both legs ran under a
trap ... EXIT INT TERMwith an absolute path, and the restore is proved by content, not by an exit code.The third site, and the dated sibling
⭐
authz-probe-blind-spot.census.ts:151is a non-carrier and is left untouched: under aRE-MEASURED 2026-09-09heading it writes "sdk84 -> 81 when #14503 took the three REST package read/delete rows out of the ledger (94 rows -> 91, already recorded ...)" — a dated transition record that names 91 as the current value and #14503 as the cause, so it asserts no stale present-tense figure and already teaches exactly the lesson this card exists to teach.authz-ledger-population.baseline.ts:61is left untouched too, per the fence's requirement to state a reason either way: its figure sits under an explicitMEASURED 2026-08-31, and the measurement re-derived above confirms it was true as written on that date (94 rows at83863b2dfe, pre-#14503). A dated reading of a past state is materially different from a false present-tense claim, and its own arithmetic is unmoved.The card's executable criterion
⇒ Zero undated present-tense statements in that directory claim a ledger row count the ledger does not hold, and the ones that remain can no longer go stale unnoticed, because the pin now holds every present-tense figure equal to its ledger.
Verification
Full derived gate union from
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack(51 commands), run at75ddfd7e, each exit code captured before any pipe:pnpm check:dual-build-cjs-loadsexits 3 =PREREQUISITE NOT MET— it reads built output and eight unrelated packages have nodist/. Its own text: "This is NOT a pass: nothing was measured." NOT MEASURED, unrelated to this diff, left to CI.pnpm --filter @objectstack/dogfood typecheck— exit 0.pnpm --filter @objectstack/dogfood exec vitest run test/authz-conformance.test.ts— exit 0,Tests 55 passed (55)(47 onorigin/main, so all 8 new cases ran).pnpm --filter '@objectstack/dogfood^...' build— exit 0.pnpm lint— the whole repo, exactly as the repo spells it (eslint . --no-inline-config): exit 0. No narrowing was needed, so no narrowing is claimed.pnpm check:cross-package-test-inputsexits 0: the new ledger reads reuse the existingreadFileSync(join(REPO_ROOT, ...))seam, which the gate already recognises.Not run locally: the sharded
Dogfood Regression GateandTest Corejobs, which boot example apps — declared to CI. The matrix-file half of this diff is comment-only, so the only executable change is inauthz-conformance.test.ts.Changeset
skip-changeset.@objectstack/dogfoodisprivate: truewith nofiles[], so it publishes nothing; both changed files are test-layer, and the matrix change is entirely inside//comments. No released package's shipped contents move. ⛔ No behaviour change is claimed.Acceptance notes
Noted, not filed:
22 of 29/76%/population 80. All three measured correct today and are the post-docs(qa): re-measure the two route-census figures #16955 left behind, and split the two moves inside one sentence #17110 corrected values — deliberately untouched, and the card is explicit that the population is still 80.scopedSourcetakes the first\n];after the export, so a ledger array containing a nested array terminated at column 0 would truncate the scope silently. Not reachable today (both tables end balanced, asserted by the new CONTROL case) and not this card's subject. Successor: none currently in flight; whoever next adds a probe withwithinwould be the one to meet it.🤖 Generated with Claude Code
https://claude.ai/code/session_01TSf4DV7ziu4V5j73e46b7c
Generated by Claude Code