Skip to content

fix(docs-audit): state the rule-carrying pairing the drift advisory can never reach - #11853

Merged
os-steve merged 1 commit into
mainfrom
claude/issue-11434-drift-rule-carrying-gap
Aug 24, 2026
Merged

os-steve merged 1 commit into
mainfrom
claude/issue-11434-drift-rule-carrying-gap

Conversation

@claude

@claude claude Bot commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

Fixes #11434 — the narrowed deliverable triage set at 20:22Z: one static line in the drift advisory's "What this run could not see" block naming the class. No population sweep, no anchoring-mechanism change. #11817 remains open and owns both of those.

The gap

The advisory's fold names five limits, and every one of them is a report about the run: files that yielded no anchor, cross-cutting symbols, over-broad anchors, weak names, and the sdk bridge's unreachable ledger rows. None covers the pair #11434 recorded — a page that states a rule by the rule's inputs while the diff touches its emitter. They share no identifier, so precision-first anchoring (#9192) has nothing to join them with, and the reader gets silence where the advisory's presence invites "not listed" to be read as "not affected".

Falsified before writing the sentence

The recorded instance still reproduces, re-run through today's mapper (post-#11778, post-#11828) against the tree at the code-only commit of #11430 (d980b939a, base 122ef3860):

derived 9 anchors — SqlDriver, createColumn, keyableTextLength, MAX_KEYABLE_VARCHAR_CHARS, …
listed 7 pages — the six the card names, plus content/docs/releases/v17.mdx
not listed content/docs/protocol/objectql/types.mdxthe page that diff falsified, in four places

Still real on today's tree. An emitter-only change (MAX_KEYABLE_VARCHAR_CHARS = 768767, mutation confirmed on disk: anchor hits 1 → 0, injected 1) derives 1 anchor, lists 0 pages, and leaves anchorlessChanges, crossCuttingSymbols, overbroadAnchors and weakAnchorsDropped all empty — so no existing limit line fires and the run reads as narrow rather than blind. The coarse fallback misses it too: the page never mentions the changed package. Zero of the nine recorded anchors appear anywhere in today's types.mdx.

Positive control, same page and same tree — so the zero-hit above is a structural miss, not a dead instrument: a change to FieldSchema, which that page does name, lists it, via FieldSchema (symbol).

Triage's 20:22Z reading re-verified on origin/main: the fold's existing limit lines do not name this class, by reading (limits.push × 5) and by the measurement above.

What changed

One limits.push, unconditional, plus the comment block explaining why it is not a report, plus the README section and the pin.

Before (same probe, origin/main):

<details><summary>What this run could not see</summary>

Coarse fallback — **9** page(s) merely *mention* a changed package …
</details>

After:

<details><summary>What this run could not see</summary>

- 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.

Coarse fallback — **9** page(s) merely *mention* a changed package …
</details>

Unconditional on purpose, and that is the one thing this file usually forbids. check-drift-comment.mjs exists because unconditional text "is not a report at all" — but that reasoning is about reports. This is a boundary of the anchor model: the absence of a shared identifier is the defect, and an absence anchors nothing, so there is no per-run signal to compute. Same posture as the sdk bridge line. The headline stays conditional; this stays in the fold.

Anchor derivation is untouched. No file under scripts/docs-audit/ changes behaviour; the mapper is byte-identical.

Pinned, and reverse-verified in both directions

check-drift-comment.mjs now pins the sentence byte-exact on every one of the five fixture cases, in the fold and asserted absent from the headline. For a statement whose contract is that it is always true, "renders everywhere" is the only meaningful pin — so both ways of breaking it go red:

ablation expected observed
drop the limits.push red on all 5 cases 5 of 56 failed
gate it on anchorless.length red only where anchorless is empty 3 of 56 failedanchored-source, docs-listed, no-package-change; the two README cases stayed green, which is the vacuity this pin closes

Both mutations were confirmed on disk before each run (anchor hit counts printed, git diff --stat non-empty), and restore ran from an EXIT INT TERM trap; the gate is back at 56/56 on a clean tree. No build is involved — the gate reads the workflow YAML from disk and runs the shipped script, so there is no dist/ for a stale artefact to hide in.

Verification

All at 370c50fe4, after the final commit.

  • node scripts/docs-audit/check-drift-comment.mjs✓ 56 cases pass across 5 fixture diff(s) (was 46 before this PR).
  • Gate union re-derived with node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack (no paths passed): 19 path-matched families. All exit 0 across 29 invocations, including the workflow-reading ones that parse the edited YAML with the real yaml library — check-step-collectors (331 run: steps across 26 workflows), check:workflow-status-functions (26 workflows, 49 jobs), check-aggregator-roster, check:required-contexts, check:shard-attestation. Plus check:nul-bytes (6598 files) and check:docs-audit-scope by convention.
  • pnpm lint — full repo, eslint . --no-inline-configexit 0 (53s). No narrowing claimed.
  • Nine gates first reported PREREQUISITE NOT MET — the dependency yaml is not installed on the fresh worktree; they were re-run after pnpm install and are counted only from that second run.

skip-changeset: nothing published changes — the diff is a workflow, a gate and its README. Same file set and same label as #11798 and #11828.

Not done, deliberately

Generated by Claude Code


Generated by Claude Code

The advisory's "What this run could not see" fold names five limits, all of
them reports about the run: files that yielded no anchor, cross-cutting
symbols, over-broad anchors, weak names, and the sdk bridge's unreachable
ledger rows. None of them covers the pair recorded in #11434 -- a page that
states a rule by the rule's INPUTS while the diff touches its EMITTER.

Measured on the recorded specimen (#11430 / #11374), 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, nor by the coarse fallback. On today's
tree an emitter-only change derives 1 anchor, lists 0 pages, and leaves every
existing limit set EMPTY, so the run reads as narrow rather than blind.
Positive control on the same page and tree: a change to FieldSchema, which
that page does name, lists it via `FieldSchema (symbol)`.

So the fold states it. Unconditionally, because the absence of a shared
identifier IS the defect and an absence anchors nothing -- there is no
per-run signal to compute, which is the same posture as the sdk bridge line.
check-drift-comment.mjs pins the sentence byte-exact on every fixture case,
in the fold and never in the headline: for a statement whose contract is that
it is always true, "renders everywhere" is the only meaningful pin.

Nothing in anchor derivation changes; this states the gap and does not close
it. The routes that would buy coverage are the open question in #11817, and
the population question is deliberately not measured here -- the sentence's
truth does not depend on the count.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015ahemw8RcTgqtxrj15PEZx
@claude claude Bot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Aug 24, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

Nothing 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
  • 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 fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys 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.

Coarse fallback — 0 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json 0a2f63afcdbe73024cc2cf919e057407b8250379packageMentionDocs.

@github-actions github-actions Bot added size/m ci/cd documentation Improvements or additions to documentation labels Aug 24, 2026
Merged via the queue into main with commit 4019e16 Aug 24, 2026
36 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci/cd documentation Improvements or additions to documentation size/m skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

1 participant