docs(qa): FOLLOW-UPS § 7a records the landed subpath repair, not a pending choice - #16909
Conversation
…nding choice `docs/qa/platform-checklist/FOLLOW-UPS.md` § 7a stated in the present tense that `PHASE2_IMPLEMENTATION.md` sections 4 and 5 "still tell readers to `import … from '@objectstack/core/security'`", and that the choice between the two available repairs was "Deliberately left ... not a lane's call". Measured on `origin/main`: that specifier occurs 0 times in `packages/core/PHASE2_IMPLEMENTATION.md` (firing control in the same run: `@objectstack/core` occurs 7 times in the same file), and both section 4 and section 5 now import from the root barrel. PR #16205 (commit e270ebb) repointed them. So both halves were stale: the residue is gone, and the choice was made — the repair taken is the one that does NOT widen the published contract, which is the fact a tracking ledger owes its next reader. `packages/core/package.json` still declares exactly `.` and `./logger`, re-measured here. The "filed separately" half stays and now names its filing, #15931. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ADLdAs2pVcH17h9tZKWMBg
⛔ merge queue 构建失败 — 先分诊,再决定要不要重排队列构建 34250893042 红了。队列跑的是全量套件(PR 侧 CI 只跑 affected 子集), 失败的 job(日志抽取,best effort):
跨 PR 相同签名(24h,按失败测试文件聚合):
历史信号:
分诊清单:
Generated by Claude Code · merge-queue-triage workflow (#4859) |
Part of #16208 — this lands the QA-ledger half only. The second note the card names is
deliberately untouched; What is deliberately left below says why, and names the ruling.
Clause-②: no
1. The premise, verified first — by content on
origin/mainThe card rests on the words "which PR #16205 repaired". That was verified in the tree, never
from a
mergedflag or a commit subject, and with a firing control in the same run:The instrument answers both ways on that one file, so the zero is a reading and not a
pathspec that silently matched nothing. Reading the sections themselves: section 4
(
Permission Manager) at line 161 and section 5 (Sandbox Runtime) at line 219 both now sayfrom '@objectstack/core'. The landing commit, reached by walkingorigin/main's own historyfor that path — so an ancestor by construction, no shallow-clone ancestry test needed:
The repair landed.
premise_still_valid: true.2. Per-note verdicts — each judged on its own reading, not as a package
Note 1 —
docs/qa/platform-checklist/FOLLOW-UPS.md§ 7a: STALE. Rewritten here.Two of its claims are false at head. "sections 4 and 5 still tell readers to
import … from '@objectstack/core/security'" — measured above, 0 occurrences. "Deliberately left: the tworepairs … differ in whether they widen the published contract, which is not a lane's call" —
the choice has since been made. Its remaining claims are true and are kept: the subpath is
still in no
exportsentry (re-measured:packages/core/package.jsondeclares exactly.and
./logger), and the "filed separately" half still holds, so it stays and now names itsfiling, #15931.
Note 2 —
packages/core/src/security/security-scanner-retirement.pin.test.ts:46: STALE too,and deliberately NOT touched here. Its parenthetical "(
PHASE2_IMPLEMENTATION.mdsections4 and 5 still teach it; filed separately, since the two repairs differ …)" is false by the
same measurement. Everything around it was re-measured and is exactly true, so nothing else in
that header is in question:
packages/core/package.jsondeclares exactly.and./logger;PluginSecurityScannerdoes still survive in that document's retired section (line 274) andin the tombstone on
./index.ts(line 80), which is the stated reason the pin is anexport-list assertion rather than a grep.
3. What is deliberately left, and on whose ruling
The card does not grade note 2 — it hands that scope decision away in its own words:
The triage seat took that call on the card and ruled:
— site 1 on its own; site 2 corrected in passing the next time that file is touched for
another reason, its stated cost being that editing a test file's header for one parenthetical
pulls that whole suite into this change's verification surface for zero gain. This PR executes
that ruling rather than reopening it, which is why the first line reads
Part ofand not aclosing keyword: the card should stay open as the record for note 2 until someone touches
that pin test for an unrelated reason. If the maintainer or PM would rather bank it now, the
edit is one comment line and the card can be shut by hand.
Also on the triage seat's instruction — "顺带把做出的选择记下来,那正是这份账本该承载的信息" —
the rewritten paragraph now records which repair was taken (repoint at the root barrel, the
one that does not widen the published contract), which is the fact a tracking ledger owes
its next reader. That is what stops the next person re-opening a settled trade-off.
4. The fossil, read before rewriting
The recorded reason note 1 said what it said is in the note itself, and it does not contradict
the card:
Both named repairs are still the only two, and the delivering PR took the second. So the fossil
is discharged, not overruled — the rewrite says which of its two options was taken.
5. Evidence
Ablation: INAPPLICABLE, not invented. This diff is one Markdown paragraph. It adds no
guard, no assertion and no gate, so there is nothing whose removal could be driven to red.
Per-note absence check, counted on whitespace-flattened text so re-wrapping can neither
mask nor manufacture a count, with a both-ways control in the same run:
HEADstill tell readers to `import … from '@objectstack/core/security'`Deliberately left:which is not a lane's callFiled separately(must survive — triage said keep it)PHASE2_IMPLEMENTATION.mdrepaired in **PR #16205**does **not** widen the published contract was takenThe two CONTROL rows are what make the zeros mean something: the same instrument, on the same
file, in the same run, still answers "present" — so a zero is an absence and not a broken query.
Gates. Derived with
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack, all run, reconciled with--ran. The reconciliation line, verbatim— and it is a statement about COVERAGE, not about verdicts:
Verdicts, stated separately: 12/12 exit 0. One of them needed a second attempt and it is
disclosed rather than quietly re-run —
pnpm --filter @objectstack/lint run check:doc-formula-expressionsfirst came back exit 3,PREREQUISITE NOT MET, which isNOT MEASURED and is not a pass. Its prerequisite build was run under the shared verify lock
(
os-verify-lock: VERDICT command-exit 0), after which the gate itself printed✓ check:doc-formula-expressions: 22 record-scoped formula example(s) across 434 files / 1373 TS blocks judged clean. No verdict here was read while a build was in flight: every gate raneither before that build was started or after it had returned.
The path-matched gate that actually reads the edited file is
pnpm check:platform-checklist,green:
check-platform-checklist: OK — 15 areas, 264 items (264 active).Repo-wide
pnpm lintis CI's run; the narrowing here is measured, not skipped. Threereadings: (1) the checked population comes from ESLint's own config resolution, not a guess —
isPathIgnored('docs/qa/platform-checklist/FOLLOW-UPS.md')returnstrue; (2) the count comesfrom
--format json— 1 result, 0 errors, 1 warning, and that warning is the notice"File ignored because no matching configuration was supplied.", i.e. 0 linted files; (3) theinvariance for untouched files is stated by the config itself at
eslint.config.mjs:326-329—"this repo runs one
eslint.config.mjs, which never enables type-aware linting (noparserOptions.project, no typed@typescript-eslintrules) for ANY file" — so a Markdown-onlydiff cannot move any verdict on any file it did not edit.
Tests/typecheck: none owed. The one edited path belongs to no workspace package (the
nearest
package.jsonabove it is the private root@objectstack/spec-monorepo; thepnpm-workspace.yamlglobs cover onlypackages/**), so no package's suite is implicated.All readings above were taken at
605abe4bon this branch.6. Changeset route — decided on a measurement
Route 2, the
skip-changesetlabel; no.changeset/*.mdentry. The floor sentence, cited withits tree —
AGENTS.md:1036, identical onorigin/mainand in this branch's worktree, which ischeckable because this diff touches exactly one file and
AGENTS.mdis not it:The measurement that puts this diff in the label's half: walking upward from
docs/qa/platform-checklist/FOLLOW-UPS.md, the firstpackage.jsonis the repo root's, whichis
"private": true, andpnpm-workspace.yamlenumerates onlypackages/*and itssubdirectories. The path ships from no released package, so a changeset would publish nothing.
7. 验收备注
description — sections 4 and 5 currently teaching the subpath — exists in exactly the two
places the card names, and nowhere else. Two neighbours were read and are correct as
written, so they are left alone:
packages/spec/src/migrations/entries/semantic/18.plugin-security-scanner-retired.ts:55(and its generated mirror in
registry.ts) says the subpath is one "the package has neverdeclared in its
exportsand which therefore resolved for nobody" — a true statement aboutthe subpath that makes no claim about the document; and
packages/core/src/security/index.ts:10carries
@module @objectstack/core/security, a module tag, not an import instruction. TheCHANGELOG.mdhits are historical release records.docs/adr/** · .claude/** · skills/** · AGENTS.md · CLAUDE.md— and the single edited path isin none of them.
content/docs/releases/**is untouched.packages/metadata-protocol/src/protocol.tsandpackages/spec/src/contracts/scoped-context.tsare not in this diff.negative — no
claude/issue-16208-*branch existed locally or on the remote, andgit status --porcelainin the fresh worktree was empty.🤖 Generated with Claude Code
https://claude.ai/code/session_01ADLdAs2pVcH17h9tZKWMBg
Generated by Claude Code