Skip to content

fix(lint): data-model, filter, predicate, search, sort, security and registry findings state each decision in words instead of a tracker number (stage 2) - #21491

Merged
objectstack-fleet[bot] merged 4 commits into
mainfrom
claude/issue-20749-lint-strings-stage2
Oct 3, 2026
Merged

objectstack-fleet[bot] merged 4 commits into
mainfrom
claude/issue-20749-lint-strings-stage2

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Part of #20749
Clause-②: no

Stage 2 of the domain:spec lane's share under the maintainer's A / A ruling (5902360492): the last 51 ledgered tracker-number occurrences in packages/lint, in 18 packages/lint/src files. After this, packages/lint has no row left in scripts/doc-authoring-prose-id.baseline.json. The card stays open for the later stages, so this PR carries no closing keyword. Text only: no rule, condition, code path, rule id, severity or registry field moves (AST skeleton proof below, 18 of 18 SAME).

What this does

These 18 files print findings to authors through os validate, os lint and os build (and, for the rules on the runtime publish gate, through the Studio, REST and MCP publish door). authoring-rules.ts also carries the surfaceReason texts of the exported AUTHORING_RULES registry, and lint-liveness-properties.ts one thrown integrity error. 51 tracker numbers in that text sent the reader to a card for the reason behind it. In form D, as stage 1 (PR #21462) and the sibling lane's stages 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 surface, re-derived from the ledger and from check-doc-authoring.mjs --census on origin/main at 7e7e64b13d (the claim's numbers hold exactly): authoring-rules.ts 9, validate-empty-combinators.ts 6, validate-predicate-path-refs.ts 6, validate-searchable-fields.ts 5, validate-sortable-fields.ts 5, validate-null-guards.ts 4, validate-visibility-predicates.ts 3, data-model-rules.ts 2, validate-security-posture.ts 2, and one each in lint-liveness-properties.ts, validate-component-props.ts, validate-dashboard-action-refs.ts, validate-nav-object-servability.ts, validate-react-page-props.ts, validate-rule-schema-formats.ts, validate-seed-state-machine.ts, validate-view-containers.ts and validate-widget-bindings.ts. They sit in 46 census sites (40 string groups once a + chain is read as one string). By class: 37 occurrences in finding envelopes (a message or hint), 13 in prose (9 in AUTHORING_RULES surfaceReason texts, 4 in the null-guard outcome clauses a finding carries) and 1 thrown. None is logged.

Every cited card (32 objectstack cards, plus objectui#4049, objectui#2348 and objectui#4051, where #5149 was migrated) was read through REST, body and every comment, before its string was rewritten. Where a card closed with no ruling comment, its landing commit was read.

Rewritten in words

Lines are the census lines at 7e7e64b13d.

Where Cited The text now says Decision read from
authoring-rules.ts:440, :1177, :1974, the full-snapshot, capability-reference and sharing-rule surfaceReason texts 4463 "P2 of the runtime publish gate (the Studio, REST and MCP door that runs this registry):" in place of "P2 (#4463):" 5156970572 (the maintainer-delegated ruling: one shared rule core, run at the metadata write boundary so Studio, REST and MCP are all covered), claim 5160065194 (P1 flow first, P2 the full snapshot), ACCEPT 5160403203
authoring-rules.ts:507, the advisory-volume reason 4717, 4716 "each carried back in the save response and rendered by Studio's designer ... The object door opened to the gating object rules alone; crossing an advisory one is a separate UX decision." 4717: maintainer ruling 5237206591 (advisories rides the save response; Studio renders it); 4716: adjudication 5328603673 (the five gating object rules cross, the six advisory-only rules do not ride, advisory UX is separate work)
authoring-rules.ts:1111, the component-types reason 4716 "pending the crossing discipline the gating object rules went through: a measured false-refusal budget, here over stored tenant page rows" 5328603673 (crossing priced on a measured false-refusal budget)
authoring-rules.ts:1976, the sharing-rule reason 9698 "The anchor arm, which refuses a rule anchored on a public-OWD object or a master-detail detail (no share row could widen either), FALSIFIED that" triage promotion 5332890862 (a statically decidable inert sharing declaration is a loud authoring error, as #7503 ruled) and the landing dev report 5338330042
data-model-rules.ts:344, bare declared unique: true 5082 "Protocol 18 rejects this spelling, and stored metadata that still carries it converts to unique: 'global', which builds the same physical index." the card body (ADR-0120 D2 conversion true to 'global', bare true rejected at protocol 18) and the hold records 5225701234 and 5481784294
lint-liveness-properties.ts:288, unrecognised ledger status (thrown) 11384 "An unrecognised status fails loudly here rather than being graded dead." claim 5389729619 and dev report 5390065066 (an unrecognised status throws instead of silently grading dead)
validate-component-props.ts:326, props hint 5068 "props are judged here, at the authoring door, as a warning before they become an error" maintainer ruling 5196404940 (direction A: gate at publish/lint by type, warning first then error; B, reshaping properties, not done)
validate-empty-combinators.ts:231, :235, :271, the $and: [], $or: [] and empty-node messages 5322 "Every backend reduces an empty combinator (an empty node) to its boolean identity, so it ..." maintainer ruling 5185589944 (boolean identity reduction everywhere; the analytics compilers align with the five backends)
validate-empty-combinators.ts:237, $or: [] on a read scope 5134 "(fail-closed by design: an empty disjunction never opens a read scope to the whole table)" the card body and ACCEPT 5178806144 (an empty $or compiles to FALSE; the SQL driver had answered the whole table)
validate-null-guards.ts:597, the fail-closed outcome 4649, 4763 "(a predicate that cannot evaluate refuses the write rather than being skipped)" 4649: PM ruling 5161512629 and ACCEPT 5161923543 (fail closed on a predicate that cannot evaluate); 4763: closing record 5164195111 (the has() shape refused at build/publish)
validate-predicate-path-refs.ts:652, :694; validate-visibility-predicates.ts:1001, :1023, :1126, the fall-open consequence 5149 (and 6254 at :694) "(failing open is the console's settled behaviour)" 5149: ruling 5202273981 (keep fail-open, make it loud, lint at build time) and, on the migrated objectui#4051, the delegated ruling 5235422835 (fail-open kept); 6254: landing 643b7c76bc (a repeater still spells its root data, which the :694 hint already states)
validate-predicate-path-refs.ts:731, dotted right-hand side objectui#4049 "the form evaluator keeps its right-hand side a literal by design, and says why only in a development build" claim and ruling 5251302658 (B: a dev-mode diagnostic, no semantic change; A rejected) and ACCEPT 5251653400
validate-rule-schema-formats.ts:326, format hint 5029 "the one rule-validator.ts registers so that a format is enforced on every write" PM ruling 5175865103 (option 1: register ajv-formats) and ACCEPT 5176328955
validate-security-posture.ts:464, unset OWD objectui#2348 "the leave_request incident, where an object with no sharingModel let an ordinary read/write grant read and edit every other user's records" the PR body (merged) and ADR-0090 §Context and D1, which record the incident
validate-security-posture.ts:526, controlled_by_parent with no relation 7474 "refused with 422 INVALID_METADATA, as a metadata defect rather than a permission denial" maintainer ruling 5248468777 (split the legs by true semantics) and ACCEPT 5248935610
validate-seed-state-machine.ts:146, seed outside the state machine 3433 "(a seed records established facts rather than walking the lifecycle)" landing commit 0c302a7790 (seed writes exempt from state_machine: a curated snapshot of established facts)
validate-view-containers.ts:133, a ViewItem in views: 5320 "The registration loop refuses this entry too: the stack schema, this rule and the loop hold views: to one container-only contract." ruling 5265947108 (tighten the loop to the container-only contract) and fork ruling 5271008099 (the viewItems: home first, then the tighten with lint alignment)
validate-react-page-props.ts:458, absent groupBy 5583 "An ungrouped single-value chart is NOT a supported ObjectChart shape — groupBy stays required, ..." (the ruling stated directly, its citation dropped) landing commit e0f300ba5d (groupBy stays required; the single-value need is served by the object-metric block)

Citation only (the sentence already stated the decision)

  • authoring-rules.ts: :1978 (8309, "objects IS carried by the per-write snapshot"; audit 5279528993); :1982 (7220, "a rule that has never run at a door should not claim it"; maintainer ruling 5237225765).
  • data-model-rules.ts:521 (5030, "SQL UNIQUE is NULL-distinct ... it enforces nothing", the fix naming the NULL-safe organization key part; ADR-0120 and landing record 5178627933).
  • validate-dashboard-action-refs.ts:299 (objectstack#6739, "a modal target names a PAGE, only", with the hint naming actionType: 'form'; maintainer ruling 5229995836).
  • validate-empty-combinators.ts:256 (5330, the hint already says a programmatic producer keeps the runtime identity and only authored metadata is judged; ACCEPT 5226245518); :295 (5297, "which is why the runtime absorbs rather than filters").
  • validate-nav-object-servability.ts:167 (7912, "The server prunes this entry from the served /meta payload"; maintainer ruling 5271014830).
  • validate-null-guards.ts:601 (4811, the clause already describes the skipped requiredWhen; ACCEPT 5169421708).
  • validate-predicate-path-refs.ts:737 (objectui#4049, "it stops working when this surface moves to the real CEL evaluator"); :739 (7696, "this one finding carries BOTH readings"; dev report 5255289068).
  • validate-searchable-fields.ts:356, :419, :443, :476 (4254, "400 INVALID_FIELD"; landing af2a0958c8); :414 (6674, the hint already says the ingress gate now refuses the entry; triage promotion 5230241805 and landing 4ac12ef4cf).
  • validate-sortable-fields.ts:415, :416, :435, :471 (6994 and 7095, "the REST ingress and the engine" refuse a formula sort with 400 INVALID_SORT; landings 9f7a7c25ab and 6908830573, maintainer ruling 5236143229 on 7095).
  • validate-widget-bindings.ts:982 (2501, "The filter is ANDed into this widget's analytics query", the same treatment this file's two neighbouring messages already had).

No occurrence was left in place: no cited decision was unclear, and each fit the string's space.

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

Recomputed with node scripts/check-doc-authoring.mjs --census-ledger (exit 0, no growth refusal) into a scratch file, then copied into place; recomputed again on the merged tree (below), where it is byte-identical to the file in this branch. Against main the diff deletes 71 lines and adds none: exactly the 18 file blocks (36 brace lines and 35 pair lines). A scripted comparison of every other key: 0 moved, 0 added.

before after
the 18 files 51 occurrences, 35 pairs, 18 files 0
packages/lint 51 occurrences, 18 files 0
whole ledger, at the branch point 7e7e64b13d 174 occurrences, 127 pairs, 53 files 123 occurrences, 92 pairs, 35 files
whole ledger, on main at cba4297176 (merged in) 136 occurrences, 97 pairs, 39 files 85 occurrences, 62 pairs, 21 files

pnpm check:doc-authoring at the merged head dfb89505f5: "sibling-package prose ids hold the baseline — 72 pinned site(s) across 21 file(s), 86353 string(s) read in 1253 parsed source(s), no growth, no burn-down unrecorded". No gate is added or loosened; scripts/check-doc-authoring.mjs is untouched.

Ledger serial: while this stage was built, the sibling lane's stage 4 (PR #21472) held the ledger. This PR opened only after it merged (cc0786223b), with origin/main at cba4297176 merged in (a merge commit, no rebase) and the ledger recomputed on that tree; git's text merge of the two deletion-only diffs and the recomputation agree byte for byte. At opening, no open PR touches the ledger or any of the 18 files (every open PR's file list read). PR #21480 (#21457) landed in the same queue run; its edits to validate-predicate-path-refs.test.ts and lazy-deps.test.ts are kept as they landed (both files equal main here), and this PR touches neither.

Quoted elsewhere

  • content/docs/data-modeling/schema-design.mdx:179 quoted the stale-entry hint verbatim, (#4254) included; the quote is updated to the new text in this PR.
  • skills/**: no quote of a changed message.
  • The other docs hits for these numbers are the docs' own prose with their own citations, not quotes of lint text; untouched.

Changeset

.changeset/20749-lint-strings-stage2-state-the-decision.md: patch for @objectstack/lint, carrying Clause-②: no. Measured after building: the new sentences are in packages/lint/dist/index.js, index.cjs, runtime.js and runtime.cjs, and none of the replaced id-bearing fragments is (the two (#6994) / (#5082) hits left in dist are source comments tsup keeps).

Text-only proof

The stage-1 tool, unchanged: a TypeScript-AST skeleton of each changed source in which every string literal and template text is a placeholder, a + chain is flattened and a run of adjacent string operands is one string (only its embedded expressions are kept, in order), identifiers, numbers and regex literals keep their text, every child is visited, and comments are never read. A second leg compares the TEXT of every string group in order: each group that changed must have carried a tracker id before and carry none after, and every other group must be byte-identical. 7e7e64b13d against the head: 18 of 18 SAME on both legs, token counts identical per file, 40 groups changed, all of them id-bearing before and id-free after, parse diagnostics 0/0.

Controls on a scratch copy of validate-empty-combinators.ts (head version), each mutation counted on disk first (1 anchor hit, replacement present, anchor gone): one function renamed reads DIFF; === flipped to !== reads DIFF; one literal re-split into two + operands reads SAME with no extra group changed; a text change in a string that never carried an id reads SAME on the skeleton and VIOLATION on the text leg. No repo file was mutated for the controls.

Pins

Every assertion that found a finding by its tracker number, or by the full old text, now finds it by the words that replaced it, at the same strength (toContain stays toContain, the exact toBe stays exact). No rule-id, severity or path assertion was touched.

  • validate-visibility-predicates.test.ts:968, :1418: "failing open is the console's settled behaviour" for '#5149'.
  • validate-react-page-props.test.ts:1202: "groupBy stays required, and a single number belongs in an object-metric block instead" for '5583'.
  • validate-searchable-fields.test.ts:760: the exact outside-the-declared-set message, now ending "returns 400 INVALID_FIELD."
  • packages/cli/test/data-model-rules.test.ts:622: "on every row whose 'organization_id' is NULL it enforces nothing" for '#5030'.

Tests

All builds and tests through scripts/pm/os-verify-lock.sh, every verdict VERDICT command-exit 0 on the runs quoted. These ran at d5137b469b, the head before main was merged in; the merge brought nine main commits that touch none of this PR's files apart from other rows of the ledger, and the build, the lint suite and the gate union are re-run on the merged head, with their readings in this stage's dev report on #20749.

  • Build: pnpm --workspace-concurrency=2 --filter '@objectstack/lint^...' build (the closure), then pnpm turbo run build --concurrency=2 --filter=./packages/* --filter=./packages/*/* ("Tasks: 71 successful, 71 total") for the dist-reading gates and the CLI test.
  • @objectstack/lint: vitest run --maxWorkers=2: "Test Files 119 passed (119) / Tests 5614 passed | 5 skipped (5619)". The first run, before the re-pins, read 4 failed in 3 files, exactly the four pins listed above. typecheck: tsc --noEmit exit 0 and "check:test-typecheck: OK — @objectstack/lint's test layer compiles ... 2 file(s) / 6 error(s) / 2 pinned signature(s) held".
  • @objectstack/cli, unit layer, test/data-model-rules.test.ts: "Test Files 1 passed (1) / Tests 56 passed (56)". No packages/cli source, bin/ or integration-layer file is touched, so the integration layer is CI's.

Gates

  • node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands (no paths) at d5137b469b: 99 commands, run one at a time from the worktree, each exit code recorded before any pipe. --ran: "99 derived famil(ies) accounted for — 99 run, 0 NOT-MEASURED (a DERIVED zero — all 99 recorded an exit code and none of them is 3)". All 99 exit 0, the dist-reading ones (check:docs-transcript-drift, check:dts-closure, check:dual-build-cjs-loads, check:lean-entry-closure, check:published-files, check:sourcemap-no-sources-content) after the full build. Outside the derived set, also all exit 0: the 11 declared wide-population families and the 11 artifact-roster families whose roster sits under one of this PR's directories (check-changeset-fixed, check-published-list-mirrors and its self-test, check:authz-resolver, check:console-injection, check:engine-double-contract, check:error-code-casing, check:filter-alias-parity, check:i18n-stale-fill, check:published-readme-exports, check-dts-references --self-test).
  • Named by the dispatch: check:doc-authoring (self-test and run) exit 0; check:nul-bytes exit 0; check-adr-0087-registration exit 0 ("this PR adds no declared-breaking changeset (1 non-breaking changeset(s) seen)"); check:empty-changeset exit 0; check-changeset-fixed exit 0 (""fixed" group is in sync with 69 public workspace packages"); check-changeset-no-major exit 0 on the plain run ("This diff introduces no major bump."), and exit 0 when fed this body as a pull_request event (the Clause-②: no line read, patch judged against it). At the merged head dfb89505f5, check:doc-authoring, check:nul-bytes, check-changeset-no-major and check-adr-0087-registration were re-run before opening: all exit 0.
  • check-issue-citations: "no issue citations added against 7e7e64b (18 file(s) read)"; check:partof-closing-keyword on this body: exit 0.
  • Repo-wide pnpm lint is CI's.

Acceptance notes

Noted, not filed:

  • Test titles and test-only strings in these files' tests still cite numbers, outside stage 2: 228 ids in test titles and 21 in other test strings across lint-liveness-properties.test.ts (35 / 4), validate-component-props.test.ts (19 / 0), validate-dashboard-action-refs.test.ts (8 / 0), validate-empty-combinators.test.ts (3 / 1), validate-null-guards.test.ts (3 / 0), validate-predicate-path-refs.test.ts (11 / 1), validate-react-page-props.test.ts (28 / 0), validate-rule-schema-formats.test.ts (4 / 0), validate-searchable-fields.test.ts (13 / 0), validate-security-posture.test.ts (7 / 1) and its .runtime-surface.test.ts (27 / 2), validate-seed-state-machine.test.ts (1 / 0), validate-sortable-fields.test.ts (12 / 0), validate-view-containers.test.ts (2 / 0), validate-visibility-predicates.test.ts (23 / 0), validate-widget-bindings.test.ts (27 / 0), plus authoring-rule-wiring.test.ts (1 / 12) for authoring-rules.ts and reference-integrity-suite.test.ts (4 / 0) for validate-nav-object-servability.ts, which have no same-named test file; data-model-rules' two same-named test files carry none, and packages/cli/test/data-model-rules.test.ts carries 3 in titles. The ledger does not read test files.
  • validate-empty-combinators.test.ts selects its identity cases with (c.note ?? '').includes('#5322') over FILTER_LOGIC_CASES notes in @objectstack/spec: that test-only id is load-bearing (it is a selector, not prose), so the later stage that sweeps test strings cannot just strip it.
  • authoring-rules.ts:1111's reason holds the component-types rule to a budget measured "over stored tenant page rows"; the object-door crossing it cites was adjudicated on a measured lower bound from authored config-file metadata, with a post-launch replay as the audit, because no tenant rows exist yet. The reason's wording is unchanged in substance here; whether that bar still describes the page crossing is the seat's to judge. Carrier: none.
  • The two .mjs gate scripts stage 1 named (packages/lint/scripts/check-doc-formula-expressions.mjs, scripts/check-startup-registry-verdict.mjs) are untouched, as staged.
  • Comments in the 18 files keep their ids: a comment is the sanctioned home for an internal anchor.

Generated by Claude Code

claude added 4 commits October 2, 2026 21:42
…each decision in words instead of a tracker number (stage 2)

Text only: every changed string is a message, hint, thrown error or
registry reason that carried a tracker id; no rule id, severity,
condition or code path moves.

Claude-Session: https://claude.ai/code/session_01YDt3PzwfrkuFzUBF89WPmM
Co-authored-by: Claude <noreply@anthropic.com>
…he replaced tracker numbers

Each assertion keeps its strength: toContain stays toContain on the
words that replaced the number, and the exact-message pin stays exact.

Claude-Session: https://claude.ai/code/session_01YDt3PzwfrkuFzUBF89WPmM
Co-authored-by: Claude <noreply@anthropic.com>
…patch changeset

The ledger is regenerated with check-doc-authoring --census-ledger: the
18 packages/lint file blocks leave it (71 lines deleted, 0 added), and
no other file's row moves.

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

github-actions Bot commented Oct 2, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/lint, touching 21 documentable anchor(s).

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

  • content/docs/deployment/validating-metadata.mdx (via validateRuleSchemaFormats (symbol, a top-level function))
  • content/docs/permissions/authorization.mdx (via validateSecurityPosture (symbol, a top-level function))

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

  • content/docs/releases/v13.mdx (via validateSecurityPosture (symbol, a top-level function))
  • content/docs/releases/v16.mdx (via validateDashboardActionRefs (symbol, a top-level function), validateWidgetBindings (symbol, a top-level function))
  • content/docs/releases/v17/17-1.mdx (via validateWidgetBindings (symbol, a top-level function))

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 — 4 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 cba42971763480ff986dcd6954662bf5fed23f7c → packageMentionDocs.

Which tree this was computed on

This run read content/docs from d074b68d2c8c07d06f7d607991f987ca618670f8 — the merge of head dfb89505f509e1a2c671da17212628a9090ef396 into base cba42971763480ff986dcd6954662bf5fed23f7c, 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 d074b68d2c8c07d06f7d607991f987ca618670f8 && git checkout d074b68d2c8c07d06f7d607991f987ca618670f8
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin cba42971763480ff986dcd6954662bf5fed23f7c dfb89505f509e1a2c671da17212628a9090ef396 && git checkout -B drift-repro cba42971763480ff986dcd6954662bf5fed23f7c && git merge --no-ff dfb89505f509e1a2c671da17212628a9090ef396

node scripts/docs-audit/affected-docs.mjs --json cba42971763480ff986dcd6954662bf5fed23f7c

⚠️ 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 cba42971763480ff986dcd6954662bf5fed23f7c → pass the list as
args.docs, on the commit named under Which tree this was computed on.

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review October 3, 2026 00:10
@objectstack-fleet
objectstack-fleet Bot enabled auto-merge October 3, 2026 00:10
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Oct 3, 2026
Merged via the queue into main with commit 15b29d3 Oct 3, 2026
37 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/issue-20749-lint-strings-stage2 branch October 3, 2026 00:44
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