Skip to content

[finding] Nothing holds the isSystem census page's anchors to the code — 101 of 111 had rotted in 19 days, and no anchor shape can catch the 2 sites that were deleted #12962

Description

@os-elon

Filed from the re-census done for #12802. That card corrected the anchors; it deliberately did not build the enforcement, because a new CI gate needs .github/workflows/lint.yml and the root package.json, both held by open PR #12942. This card is the enforcement half, with the measurement that should size it.

What was measured

content/docs/permissions/system-context.mdx declares itself "the authority" and "built by census over the whole repo, not by recall". Its census was written in ece8730 (2026-08-09). Re-measured against origin/main at c94be6291 (2026-08-28), 19 days later:

Anchor reconciliation — all 111 anchors of the previous edition (not 64: a grep -c counts lines carrying an anchor; continuation anchors like the backticked :1409 form and range ends bring the real population to 111):

BucketCount
matched-and-correct — line still names the construct10
matched-and-moved — construct exists, line number rotted101
unmatched-on-page — anchor's construct gone from the code0
unmatched-in-code — read site in the code with no row on the page32

Site population, independently measured at both commits (TypeScript AST, not grep — a regex pass silently lost 6 real sites in report-service.ts to a quoting desync):

at ece8730at c94be6291
reads of ExecutionContext.isSystem in non-test sources83109
packages containing at least one1820

Split of the 83 sites that existed when the census was written: 81 survived (75 of them at a different line), 2 were deleted, and 28 arrived.

Why this matters for the anchor shape

The two deletions are the load-bearing part of this card. They are:

  • packages/services/service-storage/src/attachment-access-hooks.ts:79 — the callerContext() helper's isSystem: exec.isSystem propagation
  • packages/plugins/plugin-audit/src/comment-access-hooks.ts:192 — the same helper, same shape

Both helpers still exist under the same names. Only the isSystem read inside them is gone. A symbol-name anchor pointed at callerContext would still resolve, and would still be green — so the "cheaper shape" from #12802's own fork does not, on this page, catch the failure that matters most: a site that vanished from the code while its row survives on the page. This page's entire value is that it enumerates all elevated write sites for someone deciding whether elevation is safe; a row describing a protection that no longer exists is worse than a rotted line number, because a rotted line number is visibly wrong the moment a reader follows it.

(Both deleted sites happened to be propagation-only, and neither was on the page. That is luck, not a property of the shape.)

What the triage grading on #12802 ruled, and what the measurement adds

The grading comment ruled that the two shapes compose: symbol-name anchors to stop the rot, then a gate that resolves each symbol and fails when it is absent, and explicitly said not to ship the first alone without filing the second with a reason. This is that filing.

The measurement adds one thing to that ruling: the gate has to check the population, not only the anchors. Resolving every anchor on the page would have passed at c94be6291 under a symbol scheme, while the page was 32 sites short and carried a headline count that was 29 too low. A gate that only resolves what the page already says can never find what the page omits.

Suggested shape, for the implementer to price

  1. Census script, committed rather than throwaway: enumerate ExecutionContext.isSystem reads by AST. Regexes are not adequate here and this is measured, not asserted — see above.
  2. Gate A — resolution: every anchor on the page resolves to a real file and a real line, and to a line the census also identifies as a read site (or to an explicitly allow-listed non-read anchor, of which the corrected page has 11).
  3. Gate B — population: the census's site count, package count and per-section counts match the numbers the page states. This is the half that catches deletions and arrivals, and it is cheap once step 1 exists.
  4. Anchor spelling: the corrected page already spells an ambiguous basename far enough to be unique (objectql/src/engine.ts, not engine.ts). 41 of the previous edition's 111 anchors named a basename matching two files and could not be resolved without reading the row's Package column — worth keeping mechanical.

A working prototype of Gate A already exists as a throwaway from #12802's PR and is quoted in that PR body; it parses the page's inline-code spans (including continuation and range-end anchors), resolves each against git ls-files, and exits non-zero on any failure. It reported resolved 146 failures 0 on the corrected page and resolved 70 failures 41 on the previous edition.

Not prescribing where the gate is wired

lint.yml and the root package.json were held by #12942 when this was filed. If a cheaper host exists (folding the check into an existing docs gate rather than adding a check:* entry), that is likely better than a new farm member for one page — but note the mechanism generalises: any docs page carrying file:line anchors has this defect, and there are others.

Metadata

Metadata

Assignees

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions