Skip to content

fix(security): runtime strings state each decision in words instead of a tracker number (stage 5) - #21518

Merged
objectstack-fleet[bot] merged 6 commits into
mainfrom
claude/issue-20751-services-strings-stage5
Oct 3, 2026
Merged

objectstack-fleet[bot] merged 6 commits into
mainfrom
claude/issue-20751-services-strings-stage5

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Part of #20751
Clause-②: no

Stage 5 of the domain:services lane under the maintainer's A / A ruling (5902360492): the plugin-security strings. The card stays open for the later stages, so this PR carries no closing keyword. Text only: no status, error code, field, route, export or control flow moves (the AST skeleton reads SAME for 17 of 17 changed sources, below).

What this does

Some of the security plugin's strings sent the reader to a tracker number for the reason behind them: refusals, explain details, boot warnings, log lines, and the managed_by field help on sys_permission_set / sys_position (with their es-ES, ja-JP and zh-CN variants). In form D, as stages 1 to 4 applied it, the number goes. Where the sentence already said what was decided, only the citation goes. Where it leaned on the number, it now says the decision in words.

The stage covers all 43 ledgered occurrences in plugin-security (claim 5960178324). They were re-derived from the ledger on origin/main at 94a8761a8, and again on the merged tree at cb919dc03 (with origin/main f9a8eb889 merged in): 43 occurrences, 27 (file, id) pairs and 11 files, in 38 string sites. The card's table reads 43, so it matches. None of them sits in the excluded share-link-tenant-wall.test.ts (a test file, which the ledger does not read), and that file is not touched. The two PRs that landed in plugin-security/src/ after this branch was cut (21488 and 21503) add no tracker-number string: the census of the merged tree finds 0 sites in the package.

Rewritten in words

Author- and administrator-visible text first, log lines last. Line numbers are at the head.

Where (head line) Cited The text now says Decision read from
security-plugin.ts:7056, the curated capability-name refusal (403 PERMISSION_DENIED) 8552 "A curated name is refused at authoring so that no admin-authored row can collide with the row the platform seeds for it." The maintainer ruling on the card: option 4 (Setup can no longer create a sys_capability row with a name in PLATFORM_CAPABILITY_NAMES, or rename one to it), plus option 1 for installations that already collide.
delegated-admin-gate.ts:624, :625, the two delegation-anchor refusals cloud 830 "because the anchor roots the delegate's business-unit visibility and may only narrow yours" / "a delegation may only narrow visibility, never widen it, because the anchor roots the delegate's business-unit visibility" Not read. objectstack-ai/cloud answers 403 to this session, and add_repo was refused. The text states the behaviour the code enforces and what its own docblock records (delegated-admin-gate.ts:600: that card made business_unit_id the read-scope depth anchor, so "anchoring only narrows, never widens").
objects/sys-permission-set.object.ts:336, objects/sys-position.object.ts:288, the managed_by field help, and the generated en leaves 2920 (item A4) "Record provenance, on the one platform / package / admin vocabulary that capabilities, permission sets and positions all share" Item A4 of the tracking card: the three RBAC catalogs' managed_by is unified on sys_capability's select tri-state, and legacy values are mapped (system to platform, config to package, user to admin).
bootstrap-system-capabilities.ts:758, the derived-capability boot warning 5876 "left as their author wrote them (the derivation refreshes them only on a row it can prove is the platform's own)" The card's fix as accepted: the derived pass guards its label/description refresh by managed_by, and a row that is "not provably ours" is left alone.
bootstrap-system-capabilities.ts:749, :753, the two remediation tails of that warning 8552 "when a row the seeder cannot prove is its own already holds the name, the seeder declines rather than adopting that row or backfilling a stamp" / "the seeder does not adopt a row it cannot prove is its own, and does not backfill provenance on the operator's behalf" The same ruling rejected options 2 (adopt) and 3 (backfill). Adopting would reverse "not provably ours, leave it alone"; backfilling would decide provenance on the operator's behalf.
security-plugin.ts:2216, the public-form strip warning 3022 "stripped: an anonymous form submission cannot set ownership, tenancy or audit columns" The card's expectation, as landed: a public form has no transfer authority, so a supplied owner_id, organization_id or audit column is stripped at the data layer.
security-plugin.ts:5148, :8279, the controlled_by_parent write-gate and master read-scope failures 5386 "a child is writable only where its master is, so a master check that cannot be resolved refuses" / "a child is readable only where its master is, so a master scope that cannot be resolved admits no child" The card's acceptance: a controlled_by_parent child follows its master's ownership and share grants, on both reads and writes, and a sharing failure denies on both.
security-plugin.ts:8252, :8261, the two chain guards 11082 "a chain the derivation cannot resolve admits no child rather than leaving it unrestricted" The triage direction the fix implemented: compose across the chain, with cycle and depth guards that fail closed, and never a blanket deny for every chain. The card's issue endpoint answers 404 today; its comments were read through the timeline.
security-plugin.ts:5248, the row-level write gate's sharing-verdict failure 5492 "only a resolved sharing allow, from Modify All Data or an edit-level share, may replace that floor" The maintainer ruling: enforce both declared write wideners. The gate composes the sharing verdict, so allow replaces only the platform's own ownership floor.
security-plugin.ts:5448, the authored-policy verdict failure 5493 "a verdict that cannot be resolved never lifts the sharing refusal" The maintainer ruling Q1 = A: admit only when an app-authored policy matches, and abstain in every other case, a throw included.
security-plugin.ts:5506, the getReadFilter sharing-scope failure 4467 "a path that bypasses the engine middleware never runs without the owner and share scope a direct read applies" The card's expectation, as landed: the analytics read scope carries owner scope and share grants, and fails closed when it cannot resolve them.
security-plugin.ts:5544, the on-behalf-of read-scope refusal 2852 "a delegated read is never scoped wider than its delegator's own" The card's remaining scope (Gap 1): this path has no delegator intersection yet, so a delegated read denies rather than returning the agent's wider scope.
security-plugin.ts:7672, the platform-owner wall-bypass audit line 12974 "crossed the Layer 0 organization wall on a read ... (only the declared platform owner's reads cross it; writes stay walled for everyone)" The card has no comments. The ruling is quoted verbatim in the code at that site: READS only, for the verified OS_PLATFORM_OWNER_EMAIL account; writes keep the ADR-0123 D2 refusal.
cleanup-package-permissions.ts:195, the uninstall line 2747 "removed by package_id, so no grant outlives the package (ADR-0090 D5)" The card's expectation (delete by package_id so authorization lapses at once), and ADR-0090 D5's "No ghost grants".
unresolved-posture.ts:229, :233, :242, the three fail-closed log lines 3545, 10401, 10424 "fail-closed: an unreadable posture never defaults to public or uncontracted" 3545's second assessment: an unresolvable posture fails closed, and the exposure gate stays fail-open. Each line already stated the draft and outage halves (10401, 10424) in its own words.
normalize-managed-by.ts:190, the normalizer line 2920 (item A4) "normalized to platform/package/admin, the one vocabulary every RBAC catalog shares" As for the field help above.

Citation only (the sentence already stated the decision)

  • explain-engine.ts:1409, :1868, :1874 (4647): "the same bypass the write path consults", "the write path consults this SAME bypass", "a write bypass requires Modify All Data (modifyAllRecords), so ownership and sharing still decide". These already say what 4647 ruled (option A: explain and the write path share one bypass predicate, and View All Data alone never bypasses a write).
  • unresolved-posture.ts:197, :202, :207 (3545): each already says the access "fails CLOSED rather than defaulting to public/uncontracted".
  • security-plugin.ts:1037, :1641, :1648, the org-scoping entitlement refusal and the two arming lines (12699). The refusal's problem text already says the key is refused and resolves to "never declared" (fail closed). The arming lines already say "Layer 0 does not wall them on THIS deployment" and "membership-driven grants hand out organization_admin_no_bypass". Their [security/ + number prefix becomes [security].
  • security-plugin.ts:8915, the invalid maskingRule warning (8993): it already says "applying a full mask (fail-closed)" and names the closed preset set and {keepHead, keepTail}. The prefix changes as above.
  • security-plugin.ts:2104, the "registered security service" line (3544, 3547, 5493, 7616): the method list in the same line names what each card added (canExport, getReadableFields, checkAuthoredRowWrite, resolvePermissionSetsForContext). The ADR references stay.
  • permission-evaluator.ts:511, :558 (2565): "falling back to bootstrap/db sources" and "unresolved sets grant nothing this request" are the card's fix (warn, and stay fail-closed).

Every cited card that could be read was read through REST, body and every comment, before its string was rewritten. That is 22 cards: 8552, 5876, 2747, 4647, 2920, 2565, 12699, 3544, 3547, 5493, 7616, 3022, 5386, 5492, 4467, 2852, 12974, 11082, 8993, 3545, 10401 and 10424. 11082's issue endpoint answers 404 today, so its comments were read from the timeline endpoint. cloud 830 could not be read (see the table).

Translations

  • managed_by help on both objects: the es-ES, ja-JP and zh-CN leaves are hand-written translations that never carried the number or the decision (they translate the value list only). Each now carries the same decision, using each locale's own object labels: "en el único vocabulario platform / package / admin que comparten capacidades, conjuntos de permisos y puestos", "ケイパビリティ・権限セット・ポジションで共通の platform / package / admin の語彙" and "能力、权限集与岗位共用同一套 platform / package / admin 取值". No key was added or dropped.
  • node scripts/check-i18n-bundles.mjs --write --filter=plugin-security rewrote the two en leaves from the object source. No en leaf and no source-hash digest was hand-edited. The four managed_by locale leaves have no digest entry (they are legacy-trusted), and the merge kept every hand-written value.
  • Tracker numbers left in the package's locale bundles: 0.

Tests

Four assertions in three test files held the old text. Each now holds the new substance, and no code or status assertion is touched.

  • metadata-outage-unresolved-cause.test.ts: the assertion that the outage explain detail contains the 3545 citation now asserts toContain('rather than defaulting to public/uncontracted'). The assertion that all three log lines contain the fail-closed suffix with the 3545 citation now asserts toContain('fail-closed: an unreadable posture never defaults to public').
  • default-report-sink.test.ts: the assertion on the fail-closed suffix with the 2852 citation now asserts the new delegated-read clause.
  • deployment-platform-global-exemption.test.ts: the "nothing to refuse means nothing to warn about" filter matched the number in the refusal warn's prefix. It now matches 'org-scoping entitlement key', the refusal warn's own words. The junk-declaration cases in the same file are its positive control.

Reverse check at the committed head: both sources were put back to origin/main, then restored with git checkout HEAD; the restore was proven by blob hash and an empty git diff HEAD. I predicted 3 red and measured 2: the log-line pin and the delegated-read pin. The outage explain-detail pin stayed green because that sentence's substance was already there; only its citation went.

At the merged head cb919dc03, through scripts/pm/os-verify-lock.sh after a full build (turbo build, 71/71):

  • pnpm --filter @objectstack/plugin-security test: Test Files 164 passed (164), Tests 3527 passed | 45 skipped (3572), exit 0.
  • pnpm --filter @objectstack/plugin-security typecheck: exit 0. This includes check:test-typecheck: OK over tsconfig.test.json, so the re-pinned test files are compiled.

In the published surface, dist/index.js and dist/index.mjs carry the new sentences. No dist file carries the old 3545 fail-closed suffix, the 12699 log prefix or the cloud 830 anchoring parenthesis.

Ledger (scripts/doc-authoring-prose-id.baseline.json)

  • This PR opened after stage 4's PR 21472 merged (cc0786223). origin/main (f9a8eb889) was merged in, with no rebase. Only this file conflicted, and the conflict was resolved by taking main's copy and regenerating it, never by hand.
  • The ledger was recomputed with node scripts/check-doc-authoring.mjs --census-ledger on the merged tree. Against main's copy: 49 lines deleted, 0 added. The 11 plugin-security files leave the ledger (43 occurrences, 27 pairs), and no other entry moves.
  • Totals: 85 → 42 occurrences, 62 → 35 pairs, 21 → 10 files. --census-ledger refuses growth, and it refused nothing.
  • check:doc-authoring: "sibling-package prose ids hold the baseline — 34 pinned site(s) across 10 file(s), 86188 string(s) read in 1252 parsed source(s), no growth, no burn-down unrecorded".

Text only

The AST skeleton compares origin/main (f9a8eb889) with the head. Strings become placeholders, a + chain of strings counts as one string, template expressions are kept, identifiers and numbers are kept, and comments are not read. It reads SAME for all 17 changed .ts files. Controls on a scratch copy of security-plugin.ts, with each mutation counted once on disk: an identifier rename reads DIFF, a text-only change SAME, and a template re-split SAME. The changed lines are byte-identical before and after the merge (the -U0 +/- line sets against 94a8761a8 and against f9a8eb889 are equal).

Gates

  • node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands at cb919dc03 derives 74 commands. All 74 were run one at a time from the worktree, with exit codes recorded before any pipe, and all 74 exit 0.
  • --ran: "✓ dispatch-gates --ran: 74 derived famil(ies) accounted for — 74 run, 0 NOT-MEASURED (a DERIVED zero — all 74 recorded an exit code and none of them is 3)."
  • Among them: check:i18n ("all bundles in sync, no undeclared authoring keys"), check:i18n-stale-fill ("no new stale fills, 0 baselined"), check:nul-bytes, check:published-files, check:dts-closure (169/169), and check:dual-build-cjs-loads (106 require entry points across 66 packages load).
  • Lint, narrowed as a measurement: eslint --no-inline-config --format json over the 17 changed .ts files at cb919dc03 reports 17 files linted (none ignored), 0 errors and 0 warnings. eslint.config.mjs enables no type-aware linting (no parserOptions.project), so this diff cannot change the verdict on any untouched file. The repo-wide pnpm lint is CI's.

Acceptance notes

  • cloud 830 cannot be read from this session (403). The two anchor refusals state the behaviour the code enforces, not a reading of that card.
  • The issue endpoint for 11082 answers 404, while its timeline is readable.
  • plugin-sharing's sharing-service.ts carries the same 5493 citation in its own abstain line. That is the plugin-sharing stage of this card, and this PR leaves it alone.
  • Test titles in this package still name card numbers. Those are test files, outside the ledger and the ruling's runtime scope, and this PR leaves them alone.
  • The locale managed_by leaves changed although they never carried the number, so that each locale carries the same decision as en.

Generated by Claude Code

claude added 6 commits October 2, 2026 19:58
…f a tracker number (stage 5, wip)

Rewrites the plugin-security refusals, explain details, field help and
log lines that cited a tracker number so each one says what was decided.
Text only.

Claude-Session: https://claude.ai/code/session_01DiCSbmJrkzNhuEAier4VoJ
Co-authored-by: Claude <noreply@anthropic.com>
… help carries the shared-vocabulary decision (stage 5, wip)

Claude-Session: https://claude.ai/code/session_01DiCSbmJrkzNhuEAier4VoJ
Co-authored-by: Claude <noreply@anthropic.com>
…ld help (stage 5, wip)

Written by node scripts/check-i18n-bundles.mjs --write --filter=plugin-security.

Claude-Session: https://claude.ai/code/session_01DiCSbmJrkzNhuEAier4VoJ
Co-authored-by: Claude <noreply@anthropic.com>
…s (stage 5, wip)

Claude-Session: https://claude.ai/code/session_01DiCSbmJrkzNhuEAier4VoJ
Co-authored-by: Claude <noreply@anthropic.com>
…ger; plugin-security goes to zero (stage 5, wip)

Shrink only: 49 lines deleted, 0 added; no other entry moves.

Claude-Session: https://claude.ai/code/session_01DiCSbmJrkzNhuEAier4VoJ
Co-authored-by: Claude <noreply@anthropic.com>
Brings in stage 4 of the services lane and the plugin-security changes
landed since the branch was cut. Only the prose-id ledger conflicted; it is
recomputed with --census-ledger on the merged tree (shrink only: the
plugin-security entries go to zero, no other entry moves).

Claude-Session: https://claude.ai/code/session_01DiCSbmJrkzNhuEAier4VoJ
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions github-actions Bot added the size/m label Oct 3, 2026
@github-actions github-actions Bot added documentation Improvements or additions to documentation tests tooling labels Oct 3, 2026
@github-actions

github-actions Bot commented Oct 3, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/plugin-security, touching 22 documentable anchor(s).

11 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:

  • content/docs/api/error-catalog.mdx (via sys_permission_set (symbol, a field of const object enObjects; a field of const object esESObjects; a field of const object jaJPObjects; a field of const object zhCNObjects))
  • content/docs/concepts/metadata-lifecycle.mdx (via sys_permission_set (symbol, a field of const object enObjects; a field of const object esESObjects; a field of const object jaJPObjects; a field of const object zhCNObjects))
  • content/docs/deployment/environment-variables.mdx (via sys_permission_set (symbol, a field of const object enObjects; a field of const object esESObjects; a field of const object jaJPObjects; a field of const object zhCNObjects), sys_position (symbol, a field of const object enObjects; a field of const object esESObjects; a field of const object jaJPObjects; a field of const object zhCNObjects))
  • content/docs/permissions/authorization.mdx (via sys_permission_set (symbol, a field of const object enObjects; a field of const object esESObjects; a field of const object jaJPObjects; a field of const object zhCNObjects), sys_position (symbol, a field of const object enObjects; a field of const object esESObjects; a field of const object jaJPObjects; a field of const object zhCNObjects))
  • content/docs/permissions/delegated-administration.mdx (via sys_permission_set (symbol, a field of const object enObjects; a field of const object esESObjects; a field of const object jaJPObjects; a field of const object zhCNObjects), sys_position (symbol, a field of const object enObjects; a field of const object esESObjects; a field of const object jaJPObjects; a field of const object zhCNObjects))
  • content/docs/permissions/permission-sets.mdx (via sys_permission_set (symbol, a field of const object enObjects; a field of const object esESObjects; a field of const object jaJPObjects; a field of const object zhCNObjects))
  • content/docs/permissions/permissions-matrix.mdx (via computeLayeredRlsFilter (symbol, a method of class SecurityPlugin))
  • content/docs/permissions/positions.mdx (via sys_position (symbol, a field of const object enObjects; a field of const object esESObjects; a field of const object jaJPObjects; a field of const object zhCNObjects))
  • content/docs/permissions/sharing-rules.mdx (via computeLayeredRlsFilter (symbol, a method of class SecurityPlugin), getReadFilter (symbol, a method of class SecurityPlugin))
  • content/docs/permissions/system-context.mdx (via getReadFilter (symbol, a method of class SecurityPlugin), sys_position (symbol, a field of const object enObjects; a field of const object esESObjects; a field of const object jaJPObjects; a field of const object zhCNObjects))
  • content/docs/protocol/backward-compatibility.mdx (via sys_position (symbol, a field of const object enObjects; a field of const object esESObjects; a field of const object jaJPObjects; a field of const object zhCNObjects))

⛔ 10 release-owned page(s) also name something this change touched. These are read-only:

  • content/docs/releases/index.mdx (via sys_position (symbol, a field of const object enObjects; a field of const object esESObjects; a field of const object jaJPObjects; a field of const object zhCNObjects))
  • content/docs/releases/v12.mdx (via sys_permission_set (symbol, a field of const object enObjects; a field of const object esESObjects; a field of const object jaJPObjects; a field of const object zhCNObjects))
  • content/docs/releases/v13.mdx (via SysPosition (symbol, a top-level const object), sys_permission_set (symbol, a field of const object enObjects; a field of const object esESObjects; a field of const object jaJPObjects; a field of const object zhCNObjects), sys_position (symbol, a field of const object enObjects; a field of const object esESObjects; a field of const object jaJPObjects; a field of const object zhCNObjects))
  • content/docs/releases/v14.mdx (via sys_position (symbol, a field of const object enObjects; a field of const object esESObjects; a field of const object jaJPObjects; a field of const object zhCNObjects))
  • content/docs/releases/v15.mdx (via getReadFilter (symbol, a method of class SecurityPlugin), sys_permission_set (symbol, a field of const object enObjects; a field of const object esESObjects; a field of const object jaJPObjects; a field of const object zhCNObjects), sys_position (symbol, a field of const object enObjects; a field of const object esESObjects; a field of const object jaJPObjects; a field of const object zhCNObjects))
  • content/docs/releases/v17/17-0.mdx (via sys_permission_set (symbol, a field of const object enObjects; a field of const object esESObjects; a field of const object jaJPObjects; a field of const object zhCNObjects))
  • content/docs/releases/v17/17-1.mdx (via sys_permission_set (symbol, a field of const object enObjects; a field of const object esESObjects; a field of const object jaJPObjects; a field of const object zhCNObjects), sys_position (symbol, a field of const object enObjects; a field of const object esESObjects; a field of const object jaJPObjects; a field of const object zhCNObjects))
  • content/docs/releases/v17/17-2.mdx (via sys_position (symbol, a field of const object enObjects; a field of const object esESObjects; a field of const object jaJPObjects; a field of const object zhCNObjects))
  • content/docs/releases/v17/17-5.mdx (via sys_permission_set (symbol, a field of const object enObjects; a field of const object esESObjects; a field of const object jaJPObjects; a field of const object zhCNObjects))
  • content/docs/releases/v17/17-6.mdx (via getReadFilter (symbol, a method of class SecurityPlugin), sys_permission_set (symbol, a field of const object enObjects; a field of const object esESObjects; a field of const object jaJPObjects; a field of const object zhCNObjects))

content/docs/releases/ is RELEASE-OWNED (AGENTS.md "Documentation Guardrails"): release
notes are written centrally at release time, and a code PR that edits them is the exact PR
that guardrail exists to stop. They are still audited — read-only. If one of them is actually
wrong, file an issue or open a dedicated docs-only PR; do not edit it here.

What this run could not see
  • 1 name(s) were too generic to anchor anything (single lowercase words)
  • the SDK route bridge reached 54 of 206 client-bound route-ledger rows — the other 152 have no registrar path: tail to select them, so pages documenting THEIR client methods cannot appear above, on this or any run. Of those 152: 0 are remediable by widening that discovery convention (an in-repo file declares the path; the convention did not scan it); 55 are structural — on a ledger where NOT ONE row is declared in-repo, so no discovery change reaches them at any price; 97 are undecided (no in-repo declaration, on a ledger that has other in-repo registrars — absence and an unreadable spelling are not distinguishable here). The rows themselves: node scripts/docs-audit/affected-docs.mjs --bridge-coverage
  • 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.
  • a key NAME is not a key, so the hand re-read the line above prescribes can land on the wrong schema. The same spelling is authorable on one governed type and a [REMOVED] tombstone on another for each of active, aria, joins, objects, template, tools and version (censused on [finding] tools is a key on BOTH AgentSchema (tombstoned, dead) and SkillSchema (live, cloud-attested), so a name-based search attributes skill examples to the agent key — it produced a false stop-the-line alarm on PR #19059 #19093 over the liveness ledger's governed types, top-level keys); nothing in a search result distinguishes the two, so a grep hit on a LIVE example reads as evidence about the DEAD key. Measured on fix(spec): the agent.tools liveness row says dead — it claimed live on a key the schema tombstoned #19059: content/docs/ai/agents.mdx was reported as contradicting the agent.tools tombstone over its tools: example at :161, which is inside the defineSkill({ block opened at :155 — the page was already correct. Settle ownership by PARSING the value against both schemas, never by the name: that literal PASSES SkillSchema, and as an AgentSchema it FAILS at tools with the tombstone prescription. ⛔ These names are not the whole class — a key retired through a .strict() guidance map leaves no tombstone in the walked shape and none of them here (tool.category, live as AIToolDefinition.category).

Coarse fallback — 16 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 529d9711fb1403221c2d5d641b018dda21aec5e1 → packageMentionDocs.

Which tree this was computed on

This run read content/docs from 7ed7a07f92edeaacbd12aa74ed2c203f06128ee4 — the merge of head cb919dc030a456c96986cfb0cb72f59dfbeb5bc3 into base 529d9711fb1403221c2d5d641b018dda21aec5e1, which is what actions/checkout gives a pull_request run. Not the PR head.

A worktree cut from an older main holds a different content/docs, so re-deriving there can legitimately return a different list — that is a different tree, not a wrong row. To answer on the same tree:

# while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 7ed7a07f92edeaacbd12aa74ed2c203f06128ee4 && git checkout 7ed7a07f92edeaacbd12aa74ed2c203f06128ee4
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 529d9711fb1403221c2d5d641b018dda21aec5e1 cb919dc030a456c96986cfb0cb72f59dfbeb5bc3 && git checkout -B drift-repro 529d9711fb1403221c2d5d641b018dda21aec5e1 && git merge --no-ff cb919dc030a456c96986cfb0cb72f59dfbeb5bc3

node scripts/docs-audit/affected-docs.mjs --json 529d9711fb1403221c2d5d641b018dda21aec5e1

⚠️ That checkout carried uncommitted changes, so the commit above does not fully identify what was read.

Advisory only, and a precision-first one (#9192): a page is listed because it names a
symbol, wire route or SDK method this diff touched — not because it mentions a changed
package. Each row says which anchor put it there, so a wrong row is reportable rather than
merely annoying. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs 529d9711fb1403221c2d5d641b018dda21aec5e1 → pass the list as
args.docs, on the commit named under Which tree this was computed on.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/m tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants