Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions .github/workflows/docs-drift-check.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -260,6 +260,45 @@ jobs:
if (overbroad.length) limits.push(`**${overbroad.length}** anchor(s) matched too much of the corpus to be a work list: \`${overbroad.join('`, `')}\``);
if (weak.length) limits.push(`**${weak.length}** name(s) were too generic to anchor anything (single lowercase words)`);
if (bridge && bridge.measured && bridge.unreachable > 0) limits.push(`the SDK route bridge reached **${bridge.reachable}** of **${bridge.clientRows}** client-bound route-ledger rows — the other **${bridge.unreachable}** have no registrar \`path:\` tail to select them, so pages documenting THEIR client methods cannot appear above, on this or any run: \`node scripts/docs-audit/affected-docs.mjs --bridge-coverage\``);
// ── THE RULE-CARRYING PAGE AN EMITTER DIFF CANNOT REACH (#11434) ──────
//
// Every line above is a REPORT about this run: a count this run produced, a
// set this run derived. This one is not — it is a BOUNDARY of the anchor
// model, and it is why it is pushed unconditionally.
//
// The pair it describes: a page states a rule by the rule's INPUTS, and the
// code that carries the rule is its EMITTER. They share no identifier, so
// precision-first anchoring (#9192) has nothing to join them with, and no
// per-run signal can be computed — the absence of a shared token is the whole
// defect, and an absence anchors nothing. Reported here rather than detected
// because there is nothing to detect on.
//
// Measured, twice, on the specimen from #11434. On the recorded diff (#11430,
// `sql-driver.ts` `createColumn`, re-run through today's mapper): 9 anchors
// derived, 7 pages listed, and `content/docs/protocol/objectql/types.mdx` —
// the page that diff falsified in four places — listed by none of them. Not
// by the coarse fallback either: the page never names the changed package. On
// today's tree an emitter-only change to `MAX_KEYABLE_VARCHAR_CHARS` derives
// 1 anchor, lists 0 pages, and leaves `anchorlessChanges`, `crossCuttingSymbols`,
// `overbroadAnchors` and `weakAnchorsDropped` all EMPTY — so no line above
// fires, and the run reads as narrow rather than blind. Positive control on
// the same tree and the same page: a change to `FieldSchema`, which that page
// does name, lists it via `FieldSchema (symbol)`. The page is reachable; this
// pairing is not.
//
// ⛔ NOT a detector, and must not grow into one here. The routes that would
// buy real coverage — a curated code↔page ledger, a per-type anchor
// vocabulary, authored enumeration marks — are the open question escalated as
// #11817, and deciding the cheap half of it by implementation would pre-empt
// that ruling. This says the gap exists; it does not close it.
//
// ⛔ And it is deliberately NOT the `notCovered` headline's posture. That
// sentence is conditional because it reports what THIS diff left unanchored,
// and unconditional text there would report nothing (see
// `scripts/docs-audit/check-drift-comment.mjs`). This one is true on every
// run by construction, exactly like the SDK bridge line above, and stating it
// only sometimes would be the lie.
limits.push('a page that states a rule by its **inputs** shares no identifier with the **emitter** that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on #11430: `content/docs/protocol/objectql/types.mdx` documents the text-family column mapping by the ObjectQL type names it maps FROM (`text` / `textarea` / `html`) while the diff changed `createColumn`; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.');
// A broken scan is not a coverage number and must not read like one — see
// `bridgeCoverageFrom`. Rendered outside the collapsed section below, because
// "the bridge could not read the ledgers" is not a limit of this run, it is a
Expand All@@ -277,6 +316,11 @@ jobs:
// say is "the wide net exists and holds N pages". A short list is the right
// answer here, but a reader must be able to tell a short list from a blind one
// without leaving the PR.
//
// Since #11434 `limits` is never empty — the rule-carrying line above holds on
// every run — so this fold now renders on every run too. The guard stays: it is
// what keeps the fold from rendering empty if that line is ever moved out, and
// an empty "what this run could not see" is the reading it exists to refuse.
const limitsBlock = (limits.length || coarse.length)
? ['', '<details><summary>What this run could not see</summary>', '', ...limits.map(l => `- ${l}`), ...(limits.length ? [''] : []), `Coarse fallback — **${coarse.length}** page(s) merely *mention* a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): \`${rederive}\` → \`packageMentionDocs\`.`, '</details>']
: [];
Expand Down
50 changes: 46 additions & 4 deletions scripts/docs-audit/README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -450,10 +450,52 @@ to re-verify.

The comment also carries a collapsed **"What this run could not see"** section:
anchorless files, cross-cutting symbols, over-broad anchors, the coarse package-mention
count, and the `sdk` bridge's reach over the client-bound ledger rows (#9572). That is
the point-of-use half of #9192 — every one of the three derived-list failures in that
shift was caught only because a dev widened the probe past what the tool offered, never
because the tool signalled its own limits where it was read.
count, the `sdk` bridge's reach over the client-bound ledger rows (#9572), and the
rule-carrying pairing no run can reach (#11434, below). That is the point-of-use half of
#9192 — every one of the three derived-list failures in that shift was caught only because
a dev widened the probe past what the tool offered, never because the tool signalled its
own limits where it was read.

### The rule stated by its inputs, the diff touching its emitter (#11434)

Every other entry in that fold is a **report about the run** — a count it produced, a set
it derived. One is not, and renders on every run:

> a page that states a rule by its **inputs** shares no identifier with the **emitter**
> that implements the rule, so an emitter-only diff cannot list it — not on this run and
> not on any run.

A page can document a rule in the rule's own **vocabulary** — the values it maps *from* —
while the code carrying the rule is named for what it *does*. The two share no token, so
precision-first anchoring has nothing to join them with. This is not a tuning miss with a
threshold behind it: the absence of a shared identifier **is** the defect, and an absence
anchors nothing, so no per-run signal exists to compute. It is reported because it cannot
be detected — the same posture as the `sdk` bridge line above.

Measured on the specimen (#11434, from PR #11430 / card #11374), re-run through today's
mapper:

| | |
|---|---|
| the diff | `packages/drivers/driver-sql/src/sql-driver.ts` — `createColumn`, the text family's column mapping |
| derived | 9 anchors (`SqlDriver`, `createColumn`, `keyableTextLength`, …) |
| listed | 7 pages, every one via a `SqlDriver`-family symbol it merely mentions |
| **not listed** | `content/docs/protocol/objectql/types.mdx` — **the page that diff falsified, in four places** |
| coarse fallback | misses it too: the page never mentions the changed package |
| existing limit lines | all silent — `anchorlessChanges`, `crossCuttingSymbols`, `overbroadAnchors`, `weakAnchorsDropped` all empty |

The last row is the reason this is stated rather than left to the reader: with every limit
line silent, the run reads as *narrow*, not *blind*. Positive control on the same page and
the same tree — a change to `FieldSchema`, which the page **does** name, lists it via
`FieldSchema (symbol)`. The page is reachable; that pairing is not.

⛔ **This states the gap; it does not close it.** Buying real coverage would take a curated
code↔page ledger, a per-type anchor vocabulary, or authored enumeration marks — the open
question escalated as **#11817**, whose ruling also owns the population question (how wide
this class is is deliberately **not measured here**; the sentence's truth does not depend
on the count). `check-drift-comment.mjs` pins the line byte-exact on **every** fixture
case, which is the only meaningful pin for a statement whose contract is that it is always
true — making it conditional, moving it to the headline, or dropping it all go red.

### The headline says what the run did not cover (#11357)

Expand Down
38 changes: 38 additions & 0 deletions scripts/docs-audit/check-drift-comment.mjs
Original file line numberDiff line numberDiff line change
Expand Up@@ -31,6 +31,14 @@
* UNCONDITIONALLY, which is not a report at all. A blind-spot notice that renders on every
* run says nothing about any run.
*
* ⚠️ That reasoning is about REPORTS, and since #11434 the fold also carries one line that
* is not one: a BOUNDARY of the anchor model, true on every run by construction, because
* the pair it names (a page stating a rule by its INPUTS, a diff touching the rule's
* EMITTER) shares no identifier for any per-run signal to be computed from. Its
* unconditionality is the contract, so it is pinned the only way that is meaningful — on
* EVERY case, byte-exact, and in the fold rather than the headline. Removing it, making it
* conditional, or promoting it to the headline all go red. See `RULE_CARRYING_BLIND_SPOT`.
*
* So both directions are measured end to end, from a git diff:
*
* diff → the real affected-docs.mjs → its real --json → the real comment script → bytes
Expand DownExpand Up@@ -201,6 +209,27 @@ const ANCHORS_DERIVED_NONE_NAMED =
/** The phrase that tells that verdict apart from every neighbouring one. */
const NARROWED_PHRASE = 'nothing to list';

/**
* The #11434 boundary line, byte-exact — the one fold entry that is not a report about the
* run, and the only one asserted on every case.
*
* The class: `content/docs/protocol/objectql/types.mdx` documents the text-family column
* mapping by the ObjectQL type names it maps FROM, `sql-driver.ts` carries the mapping in
* `createColumn`, and the two share no token — so the advisory listed seven other pages on
* #11430 and not the one that diff falsified in four places. Nothing in the anchor model
* can join that pair (the routes that could are escalated as #11817), so the run says so
* instead of implying coverage by silence.
*/
const RULE_CARRYING_BLIND_SPOT =
'a page that states a rule by its **inputs** shares no identifier with the **emitter**'
+ ' that implements the rule, so an emitter-only diff cannot list it — not on this run and'
+ ' not on any run. Measured on #11430: `content/docs/protocol/objectql/types.mdx`'
+ ' documents the text-family column mapping by the ObjectQL type names it maps FROM'
+ ' (`text` / `textarea` / `html`) while the diff changed `createColumn`; it went unlisted,'
+ ' and it was the page that diff falsified, in four places. No shared token exists to'
+ ' detect this on, so a rule your change carries has to be re-read by hand in the pages'
+ ' that restate it.';

/**
* `want` is the mapper contract each case rides on — asserted before any text is, so a
* case that silently stopped exercising its branch fails here instead of passing there.
Expand DownExpand Up@@ -310,6 +339,15 @@ try {
if (typeof c.narrowed !== 'boolean') throw new Error(`case ${c.id} does not declare \`narrowed\``);
check(c.id, `the #11356 narrowed verdict ${c.narrowed ? 'renders here' : 'does NOT render here'}`,
c.narrowed, headline.includes(NARROWED_PHRASE));
// #11434 — the opposite pin to every other one in this file, and deliberately so. A
// model boundary that renders only sometimes is false on the runs it skips, so the
// assertion is "on every case", which is what fails if someone makes it conditional.
// It belongs in the fold: the headline is where a run says what IT did not cover, and
// a sentence true of all runs would dilute exactly that (#11357).
check(c.id, 'the rule-carrying blind spot is stated in the fold, byte-exact',
true, body.includes(`- ${RULE_CARRYING_BLIND_SPOT}`));
check(c.id, 'and it stays out of the headline, which reports this run only',
false, headline.includes('shares no identifier with the **emitter**'));
c.expect(headline, body);
}
} finally {
Expand Down
Loading