docs-audit: state where every emitted anchor came from - #13738
Merged
Conversation
Each row of the docs-drift advisory now names the declaration that minted its anchor, so a reader can judge the row instead of guessing: organizationId (symbol, a field of interface MetaOverlayCacheKey) userActions (symbol, a field of const object ObjectSchemaBase) Those two are the same syntactic form — `name:` inside an object or interface — and that is the finding this implements: one is the noisiest anchor the tool mints, the other the most valuable, and no syntactic or per-package test separates them. The declaring container does, and no row printed it before. Publication only. No guard, no threshold and no bridge hop reads the new field; the emitted anchor set is byte-identical before and after, with only the rendering differing. `--self-test` pins the provenance key set as exactly the anchor set in both directions, so a later change cannot start deciding with it without going red. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Pk26oZ12t5N1hwGW1m1MgC
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. 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): |
os-project-manager
marked this pull request as ready for review
August 31, 2026 09:15
This was referenced Aug 31, 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 free
to 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 #12824
Implements option C of the maintainer's ruling of 2026-08-31 (verbatim 「同意」), and only C: every row the docs-drift advisory emits now states where its anchor came from — the member and the declaration enclosing it — so a reader can judge the row instead of guessing.
Those last two are the same syntactic form —
name:inside an object or interface — and that is the whole finding. One is a field of an internal cache struct that lands 10 pages documenting an unrelatedorganizationId; the other is the canonical authorable key whose row is the best this tool produces. The card's three disproven discriminators (syntactic form, declaring package, property name against the authorable registry) all fail to separate them. The declaring container separates them, and no row printed it before.Scope — what this deliberately is not
OVERBROAD_ANCHOR_SHARE,MAX_ROUTES_PER_SYMBOLanddocumentableDeclarationsAt's selection are byte-identical.Proof that the anchor set is unchanged — measured, not asserted
Both arms of
affected-docs.mjs(origin/mainand this branch) were run against the same tree at the same commit over 100 consecutivemaincommits touchingpackages/, comparing the full--jsonoutput:Compared per commit: the anchor set as
kind+token; thedocslist; and the entire JSON document once the two additive fields (anchors[].from, and the clause appended inside eachdetail[].viastring) are removed. All three byte-identical on every commit. Harness and per-commit records are in the dev report on #12824.The same property is pinned in
--self-testrather than left to this one measurement: the provenance key set is asserted to be exactly the anchor set, in both directions — never a superset (a name nothing minted) and never a subset (an anchor with no clause). A future change cannot start deciding withfromwithout going red.The ruling's own example, end to end
Driven through the real pipeline by committing a one-line widening at each declaration site and running both arms at
HEAD^:organizationId?: stringonMetaOverlayCacheKeyorganizationId (symbol)organizationId (symbol, a field of interface MetaOverlayCacheKey)userActionsonObjectSchemaBaseuserActions (symbol)userActions (symbol, a field of const object ObjectSchemaBase)content/docs/data-modeling/objects.mdx— the true positive option B drops — is present in both arms, unchanged.Every anchor kind names its origin
symbolis the card's subject, but the card also records the bridge amplification it feeds (publishItem (sdk)and/:type/:name/publish (route)on a diff touching no state machine), and that is only judgeable when the row names the hop it rode. From a real run on this tree:Measured cost
The advisory comment gets longer, which the ruling accepted implicitly (C "does not reduce the row count"). Quantified on the worst run in the 100-commit population: the rendered row block grows 1265 → 2312 bytes (x1.8) at the 15-row display cap. That worst case is
commandanchors, whose clause was first drafted asthe CLI command id ID, read off FILE— a restatement of the token — and is now justread off FILE, which took the worst single row from 2201 to 1549 chars. Median row is 76 chars, p90 222.⛔ The display-cut problem itself is not addressed here and survives, exactly as the card says of option C.
Verification
node scripts/docs-audit/affected-docs.mjs --self-test— 503 cases pass (487 before; +16 pins for the provenance derivation, the member-form classifier including its degraded answer, and the key-set invariant).node scripts/docs-audit/check-affected-docs.mjs— exit 0 (self-test +--bridge-coverage; discovered population unchanged).node scripts/docs-audit/check-drift-comment.mjs— 56 cases pass across 5 fixture diffs. This runs the workflow's real comment script against real mapper output, so it is also the check that the added clause does not break the renderer.pnpm lint(repo-wide,eslint . --no-inline-config) — exit 0.node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack), all exit 0:check:nul-bytes,check:docs-audit-scope,check:watch-hint-literal,check:agent-test-spelling,check:entry-guard,check:parse-guard,check:cli-command-ids,check:pnpm-filter-targets,check:bash32-floor,check:pm-governed-merges,check:cross-package-test-inputs,check-self-test-wired,check-ci-filter-parity,check-shard-attestation.check-test-completeness.mjs— NOT MEASURED (PREREQUISITE NOT MET, exit 3): it grades a savedturbo run testlog and the family names it with no argument. Not a red.memberFormOn's verdict reds 8 pins; withholding the provenance write reds the 4 key-set invariant pins. Restored blob56b1f118…matchesHEADandgit diff HEADis empty in both cases.All of the above ran at
8087897a7, the branch head.No changeset: this edits a CI-internal tooling script and its README and publishes nothing from any package — the
skip-changesetcase the workflow prescribes.Generated by Claude Code