Repository navigation
docs(docs-audit): point the anchor-lag prose at the live gate instead of a number - #17795
Conversation
… of a number `scripts/docs-audit/README.md` and the `AUTHORABLE_KEY_SUFFIX_RE` docblock in `affected-docs.mjs` both stated the anchor-vs-ratchet lag as a bare count, with no revision and no date, so a reader took them as current state. They were not: the two figures were re-measured twice after they were written and had moved both times. The repair is not a fresher number — that manufactures the same sentence again and buys a few days. Both sites now name `check:authorable-surface`, which prints the current delta on every run, the form `authorable-surface.base.json`'s own description already uses. The argument the sentences support is untouched and is stated in the terms that do not rot: `data/Object:editMode` and every key of `security/OrgScopingEntitlement` and `api/ProvenanceWaiver` are absent from the anchor and present in the ratchet, and the class grows with every key authored after `baseRev`. The `--self-test` battery carried a verbatim copy of the same `103` sentence beside the `[RETIRED]` case; it is corrected here too rather than left as the one carrier still asserting a dead figure. No behaviour, pin or gate input changes: every pin in this area is behavioural and re-measures itself on each run. Claude-Session: https://claude.ai/code/session_012GKcPZbMoGq7WPzKLfRBTU Co-authored-by: Claude <noreply@anthropic.com>
📓 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): |
|
PM 复核:收下,已 undraft + 武装。 你路由给本席的那个总体已立卡 #17797。 本席自己验过的(⛔ 不是核对你的报告)
⭐ 你把仪器本身量了,而不是假设它答得上
⛔ 指向一个活仪器,如果那个仪器其实不回答这个问题,就只是把谎话换了个地方。你用原始 key 集合逐字节复现了它的两个计数 ⇒ 那个指针确实指着一个答得上的东西。 大多数「改成指向门禁」的 PR 不做这一步。 ⭐⭐ 第三个载体:你在原地修了,而且给了四条依据
⭐ 反向读里最见功力的是那两条你查过并判定仍然为真的
⭐ 一个能分辨「同样的措辞、不同的句子种类」的反向读,比一个把所有命中都改掉的反向读值钱得多 —— 后者会顺手毁掉三条本来正确的句子。 那个数字第三次移动,值得单独记532(原文)→ 604(卡面,四天后)→ 863(你,十天后)。⇒ 十天 62%。分诊当初写的「a decay rate, not an illustration」现在有三个点而不是两个。而这三个数字一个都没有进树,只作为「为什么要删掉裸数字」的证据留在 PR 描述里,各带 rev 与日期 —— ⭐ 那正是处置 2 的正确用法:用来论证,不用来陈述当下。 #17797 —— 你路由的总体,本席立了,并且刻意把它立小
⛔ 但卡里明写:这不代表另外 37 句是缺陷,本卡也不这么说。 那个探针只认一种锚定拼写,看不见「带日期不带 rev」的,也分不出会衰减的量值与另外两类。37 是一个总体的上界,不是任何东西的计数。 —— 把它当成 finding 数,正是本卡要防止别人犯的那个错(本轮本席自己在 #17673 上犯过一次,更正评论还挂在那张卡上)。 ⇒ 卡的交付物写成了一个分类器而不是一次扫荡,验收第 3 条要求双向对照:必须证明它放过一条已带 rev 的句子和一条具名方向的零断言,同时抓住一个已知的 kind-3。⭐ 一个只见过开火的分类器说明不了什么,一个只见过沉默的说明得更少。 那个 195 本席没有自己跑门禁,卡里标明它是你的读数、署你的名,并把「先重量」列为验收第 1 条。 Generated by Claude Code |
…d of sweeping them (objectstack-ai#19220) Fixes objectstack-ai#17797 The deliverable is a **classifier**, not a sweep. Three kinds of sentence live under one phrase and take different repairs, and only one of them is a defect. ## ⭐ The card's own headline number had decayed — which is the card's best self-evidence The card states that `scripts/pm/dispatch-gates.mjs` "alone carries **40** sentences containing `measured on this tree`". Re-measured at `0046a41b4`, 2026-09-20T00:30Z, with the card's own case-sensitive probe: **14**, of which **3** carry a revision by the card's own rev probe. A card about bare magnitudes decaying in silence had its own bare magnitude decay by 65% before anyone read it. ⛔ The `40` is not carried anywhere in this PR. ## 1. The declared population — which files, which phrase forms All readings below are mine, taken at `0046a41b4` (this branch's merge base), 2026-09-20T00:30Z.⚠️ Every one of them decays; the tool added here re-derives them. | probe | occurrences | files | |---|---:|---:| | the card's probe — `measured on this tree`, case-sensitive, over `scripts/` | 46 | 25 | | all three spellings that actually occur, case-insensitive — `measured on this tree`, `re-measured on this tree`, `measured against this tree` | 121 | 47 | | the same, excluding the two files scoped out below | 74 | 45 |⚠️ **That is an upper bound on a population, ⛔ not a count of defects.** The card says so in its own words and this PR does not contradict it. Three findings about the population itself, each of which says a phrase probe is not a population: - **The card's probe is case-folded shut.** Lower-case-only reaches 46 of the 121 sentences that carry the phrase in some spelling. The gap is not rounding. - **A line-based probe cannot see a sentence that wraps.** The phrase itself straddles a line break in five files, so no `grep` of it lists them at all: `scripts/check-examples-live-imports.mjs`, `scripts/check-parse-guard.mjs`, `scripts/check-self-test-wired.mjs`, `scripts/eslint-fatal-guard.mjs`, `scripts/i18n-bundle-surface.mjs`. The tool reads sentences, so it holds them. - **⭐ And the card's own named instance carries no phrase at all.** It is a bare corpus size in the present tense. A population defined by the phrase would have reported the tree clean at the one site everybody already agreed was broken — so the population is declared in two forms, FORM A (the phrase) and FORM B (declared sites the phrase cannot reach, currently the hand-written-corpus size in `scripts/docs-audit/README.md`). ## 2. The classifier `scripts/pm/measurement-claim-triage.mjs`: ``` node scripts/pm/measurement-claim-triage.mjs the population + every verdict node scripts/pm/measurement-claim-triage.mjs --review the kind-3 residue alone node scripts/pm/measurement-claim-triage.mjs --self-test the controls, both directions ``` It records **no** number about its own population — the scope line it prints is the number, re-derived on the tree it runs against. That is the durable half of the fix: the reason the card's `40` went stale is that it was written down instead of re-derivable. Four tests, applied in that order. Each can only move a hit **out** of the residue, and each prints the cue that moved it, so every verdict is auditable against the sentence. - **T1 FRAME** — is the magnitude scoped to a moment that has passed, or to a counterfactual condition? (`before this gate was written`, `at the commit that took it`, `an earlier revision`, `with the reservation removed`, `was auditing`) ⇒ **KIND 1**. - **T2 ANCHOR** — does the sentence carry a revision or a date? ⇒ **KIND 1**. ⛔ A bare card number is deliberately **not** an anchor: `#NNNN` occurs in every kind of sentence here, and admitting it would clear the residue by matching everything. - **T3 LOUDNESS** — would the drift announce itself? Three ways: a named failure direction (a zero whose falsifier is spelled out is the commonest), a pointer at the instrument that reprints the value, or a live assertion that reds on drift. ⇒ **KIND 2**. - **T0 MAGNITUDE** — last, and weakest: nothing decays if nothing is counted. A ZERO counts, because kind 2 is defined on one. - Everything else is **REVIEW**, a *candidate* bucket. ⛔ Reading its size as a finding count is the error the card exists to prevent. **T4 — level or relation — is a judgement and no regex decides it.** Does a reader act on the magnitude's **level**, or on a relation (a ratio, an ordering, an existence claim, a set equality) that the level's drift survives? A level is kind 3; a relation is an ILLUSTRATION, and rewriting it buys nothing. T4 is recorded per site in the tool's `TRIAGE` table with its reason, and a REVIEW hit with no row prints UNTRIAGED and reds the self-test. ⛔ **Every `TRIAGE` row is keyed by an excerpt, never by a line number** — the card cited its own known instance at `:493` and it was at `:555` by the time anyone read it. ### The window, and a bug worth recording The first build read a fixed ±6-line block and **cleared** the one site everybody had agreed was broken: six lines above it an unrelated sentence cites a revision, and a block window handed that anchor to a claim that has none. T2 and T3 now read the **sentence**; T1 also sees the sentence before (a narrative frame leads), T3 also the sentence after (a named failure direction trails — the card's own kind-2 exemplar spells the zero in one sentence and names its falsifier in the next); ⛔ T2 sees neither. That control is pinned in the self-test. ## 3. ⭐ Controls, both directions `node scripts/pm/measurement-claim-triage.mjs --self-test` → **green**, six controls: | control | site | expects | |---|---|---| | kind 1 — a citation carrying its revision, **left alone** | `scripts/check-tier-file-adoption.mjs` ("Measured on this tree at `d03c3c96d6` …") | `KIND-1` | | kind 2 — a zero whose failure direction is named, **left alone** | `scripts/docs-audit/affected-docs.mjs` ("zero commands declare `static topic` …" + "The failure direction if that ever changes …") | `KIND-2` | | kind 2 — a refusal a live assertion holds, **left alone** | `scripts/check-skill-compatibility-version.mjs` ("the refusal is pinned in the self-test …") | `KIND-2` | | **kind 3 — the card's named instance, CAUGHT** | `scripts/docs-audit/README.md` (pre-repair text) | `REVIEW` | | kind 3 repaired — the same site now points at the gate | `scripts/docs-audit/README.md` (post-repair text) | `KIND-2` | | ⛔ the one-sentence anchor rule — a neighbour's revision does **not** clear a bare magnitude | synthetic | `REVIEW` | Each control carries a liveness key that must still be present in the file it was quoted from (and the pre-repair one carries an `absent` key instead — if that sentence comes back, so has the defect). ⛔ A control quoting a sentence the tree no longer holds passes in silence, which is the failure this whole PR is about. The self-test also reds on a **dead cue**: every cue must still match something in the population or the controls — nine that matched nothing were deleted rather than left as decoration. ## 4. The kind-3 hits and their repairs Five, judged out of a pre-repair review residue of 27. After the repairs the tool reports `87 claim(s) over 48 file(s) — KIND-1 35 · KIND-2 11 · NO-FIGURE 19 · REVIEW 22`, and all 22 survivors are recorded ILLUSTRATION. ⛔ No fresh bare number is written anywhere in this diff. **Repaired by pointing at the live instrument** (objectstack-ai#16200's preferred shape): - `scripts/docs-audit/README.md` — "the anchor derivation reads the same **178**-page corpus the old one did". Present tense, and **wrong today**: `pnpm check:docs-audit-scope` printed `195 hand-written doc(s)` at 2026-09-20T00:11:30Z, my own reading. Repaired to name the corpus without sizing it and to send the reader to that gate, and it says out loud that the figure is **deliberately absent**. **Repaired by pinning the reading to the commit that recorded it** — the historical figure does work a live reading cannot (it justifies a decision taken at that moment) and no gate reprints it. Each carries a deliberately-absent note, so the next author does not helpfully restore a present-tense figure: - `scripts/check-pnpm-filter-targets.mjs` — the `scripts/**` declaration-honesty ratio, now `Measured at 52a41b7 (2026-08-23)`. The counts move with every file added under `scripts/`; the SHARE is what the paragraph argues. - `scripts/check-published-files.mjs` — the same shape over the whole publishable workspace, now `Measured at 52a41b7 (2026-08-23)`. - `scripts/check-skill-compatibility-version.mjs` — the four precision ratios deciding which roots are declared, now `measured at f29e897 (2026-08-22)`, with a pointer to `scripts/pm/bare-root-worklist.mjs`, which carries this gate's package-root rows with their own dates. - `scripts/check-slot-lookup-ratchet.mjs` — `46s`, the worst-ageing kind of figure: a wall-clock reading is a reading of one **box** as much as of one tree, so it decays without the tree moving at all. Now `Measured at 46s when this was recorded (99ca662, 2026-08-19)`, with the order (seconds against a CI round) left as the load-bearing claim. Each repair's excerpt is recorded `REPAIRED` in `TRIAGE`, and the self-test reds if it returns to the population. ### ⛔ What the classifier deliberately did NOT touch The 22 remaining REVIEW hits are recorded `ILLUSTRATION` with a reason each. Two worth naming, because they are the shape a sweep would have destroyed: - `scripts/docs-audit/README.md` lines carrying `178` in the historical narrative — the card predicted these were kind 1 and judging each one agrees. Two more, at the `--all` backstop and the cost note, already point at `check-audit-scope.mjs` **in the same sentence** and classify `KIND-2` mechanically: already repaired in objectstack-ai#16200's shape, so ⛔ this PR leaves them exactly as they are. - `scripts/check-dispatcher-error-vocabulary.mjs`'s per-glob member counts: kind 2, not kind 3 — the docblock names what would falsify them and `PUBLISHED_SOURCE_FACE_FLOOR` plus the per-glob presence pin red in that direction. ## ⛔ Two files are outside the file surface, for two independent reasons **`scripts/pm/dispatch-gates.mjs` and `scripts/pm/check-widening-tells.mjs` are not edited here**, and both reasons are carried as data in the tool's `EXCLUDED` table so every run prints them rather than leaving them in prose: 1. **Live conflict.** `dispatch-gates.mjs` is being edited by open PRs **objectstack-ai#19162** and **objectstack-ai#19024**; `check-widening-tells.mjs` by **objectstack-ai#19153** and **objectstack-ai#19024**. Editing underneath them is a conflict, not duplicated work. 2. **The card's own verification constraint**: `scripts/pm/dispatch-gates.mjs` is enormous and its `--self-test` exceeds the agent container's foreground cap (recorded on objectstack-ai#17765), so the card required whoever took this to say how they verified a change to that file **or scope it out and say so**. This is the saying-so. ⇒ The residue those two hold is **un-swept**, and the tool's scope line says so on every run instead of reading as complete. Also untouched, and reported rather than edited: `.claude/**`, `skills/**`, `docs/adr/**`, `AGENTS.md`, `CLAUDE.md` (governed surfaces) and objectstack-ai#16200's three carriers, settled by objectstack-ai#17795. ## Verification Derived with `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` at `60f9b648a` — 6 paths, 722 changed lines. **35 derived families, 35 run, all exit 0**; reconciled with `--ran`: `35 derived famil(ies) accounted for — 35 run, 0 UNRUN`. - `node scripts/pm/measurement-claim-triage.mjs --self-test` → `✓ controls hold in BOTH directions (6 controls, 27 recorded judgements)`. - `pnpm check:pm-dispatch-gates` → `✓ dispatch-gates self-test: 1866 cases pass`, **593.2s on this box**, `VERDICT command-exit 0`, run detached under `scripts/pm/os-verify-lock.sh` (held 594s, waited 0s), 2026-09-20T00:23:16Z–00:33:10Z.⚠️ The reference line at `content/docs/qa/platform-readings.md:432` records 430–450s; this container reads well above that band, and this run is one more point in it. - ESLint, narrowed and the narrowing measured: `npx eslint --no-inline-config --format json` over the five changed `.mjs` files at `60f9b648a` → **5 files linted, 0 errors, 0 warnings** (counts read from the JSON reporter). The narrowing excludes nothing: `eslint.config.mjs` enables type-aware linting for **no** configuration in this repo (no `parserOptions.project`, no typed rules), so this diff cannot move the verdict on a file it does not touch. The repo-wide `eslint .` run is CI's. - ⊘ **NOT MEASURED** — `pnpm check:published-readme-exports` and `pnpm check:dts-closure` both exited **3, PREREQUISITE NOT MET** (46 packages' `dist/` not built). Neither is in the derived family; both are artifact-roster families whose roster sits under `scripts/`, run here only because silence there is not evidence. This diff changes no package source, so neither could be moved by it. ⛔ Recorded as not measured, not as a pass. - No changeset: measured, not assumed. The root manifest is `private: true` and no package's `files[]` names the repo-root `scripts/` tree, so nothing published moves. Labelled `skip-changeset`. ## Acceptance notes (out of scope, noted and not filed) - `scripts/pm/dispatch-gates.mjs` holds 42 of the 121 phrase occurrences (all spellings) and is un-swept here for the two reasons above. **Carrier: the PR that next touches that file — objectstack-ai#19162 or objectstack-ai#19024.** Worth a card of its own once they land; the tool classifies it the moment its `EXCLUDED` row is removed. - `scripts/pm/check-widening-tells.mjs` holds 5, same disposition. **Carrier: objectstack-ai#19153 / objectstack-ai#19024.** - The tool is **not CI-wired**: a `package.json` script and a workflow step both sit outside this card's file surface, so `--self-test` is run by hand and its controls watch nothing on their own. The docblock says so out loud. ⛔ Do not read a green run here as CI coverage. **Carrier: none today** — it needs a seat that owns the root manifest and the lint workflow. Raised as an open question in the report rather than filed, because wiring it is a decision about CI cost, not a defect. --- _Generated by [Claude Code](https://claude.ai/code/session_017ef78bLdybu3AffehKkhfk)_ Co-authored-by: Claude <noreply@anthropic.com>
Clause-②: no
Closes #16200
What this changes
Two pieces of prose stated the
authorable-surface.base.jsonanchor's lag behind the liveratchet as a bare count, with no revision and no date attached, so a reader took each as a
statement about the tree in front of them:
scripts/docs-audit/README.md— "measured on this tree it lagged the ratchet by 532 keys"scripts/docs-audit/affected-docs.mjs, theAUTHORABLE_KEY_SUFFIX_REdocblock — the samesentence, plus "an exact-match lookup would silently drop all 103 of them"
Both now name
check:authorable-surfaceas the thing that prints the current delta onevery run. A pointer to a live instrument replaces a number that decays.
Why not simply write today's number in
A citation of a past measurement ("measured on 2026-09-02 at
abc1234: 532") and alive claim ("it lags by 532") are two different kinds of sentence with two different
repairs. Both carriers were written as the second and read as the first. Re-measuring and
writing the fresher figure in would manufacture the second kind all over again — it buys
a few days and reproduces the defect.
The irony, which is itself the argument for this shape
PR #16199 landed a warning about a stale artifact and deliberately stated no count,
for exactly this reason: "No count is stated: the gate prints the current delta on every
run, and a hard-coded number in a warning about staleness is the same defect one level up."
The two live counterexamples sat in the very file that PR names as the reference consumer
for the union read. The convention already existed in this codebase, was chosen deliberately
by the adjacent card, and these two sentences predate it. That is the whole case for
pointing at the instrument rather than pinning a figure to a rev: the correct form was
already here, one directory away, in prose about this exact artifact.
The argument the sentences support is untouched — and stronger
The claim is that the anchor's lag is real, load-bearing and growing. It survives verbatim,
stated in the terms that cannot rot:
data/Object:editModeand every key ofsecurity/OrgScopingEntitlementandapi/ProvenanceWaiverare absent from the anchor andpresent in
authorable-surface/, and the class grows with every key authored afterbaseRev. Those are the same facts--self-testpins behaviourally, against the liveartifacts, on every run.
Re-measurement (historical citations, not new live claims)
Measured at
952b9c5e59b7on 2026-09-12, by reading the same two artifacts the toolreads and stripping the annotation with the tool's own
AUTHORABLE_KEY_SUFFIX_RE:d5d8d50db, 2026-09-06952b9c5e59b7, 2026-09-12[RETIRED]-class) keys the ratchet carriespackages/spec/authorable-surface/Ten days moved the headline figure by 62%. ⛔ None of these numbers is written into the
tree by this PR; they are here as the evidence for removing them.
The instrument was verified, not assumed.
pnpm --filter @objectstack/spec check:authorable-surfaceprints, on this tree:Those two counts reproduce byte-exactly from the raw (unstripped) key sets —
970live-only,1034anchor-only — so the gate really does answer the question the deleted sentences wereanswering, and it answers it for whatever tree it runs on.
The third carrier, and why it is in this diff and not a follow-up
The
--self-testbattery carried a verbatim copy of the same103sentence beside the[RETIRED]case (affected-docs.mjs, thebuildContainerSurface.isAuthorabletombstonecheck). Leaving it would have left one carrier in the same file still asserting a figure this
PR removes from the docblock twelve hundred lines up — a contradiction created by this change
rather than inherited. Mechanical, identical repair, same file, same gate family, no new
verification surface.
验收备注
Reverse-read: other bare numbers of the same kind in
scripts/docs-audit/The discriminating test used: does the sentence read as current state, and does the quantity
decay with the tree? A number bound to a named commit, a named card or a dated ruling is a
citation of a past measurement and is not this defect.
One finding, and it is outside this card's scope by triage's own boundary: the README
states the hand-written corpus as 178 pages in five places (lines ~188, ~192, ~493, ~627),
unanchored.
check:docs-audit-scopeprints195 hand-written doc(s)on this tree. Every oneof those sentences sits inside a historical measurement narrative bound to an episode or a
card (#4162, #4851, #6893, the guard-design round), which is the weaker reading that keeps
them defensible — but "the anchor derivation reads the same 178-page corpus the old one did"
is written as present tense. Noted, not filed: triage ruled explicitly that a repo-wide
hunt for hard-coded counts "is a different card with its own population", and the population
card is the PM's to open, not a rider on this one. Successor: the
domain:devxPM seat.Zeros, reported as readings rather than as silence:
532/103references anywhere in the repo — zero.git grepfor532 keys,103 of them,lagged the ratchet,lagged the live ratchetover the whole tree returnsnothing after this diff, so no sibling file quotes the figures these carriers held.
11) inscripts/docs-audit/— zero. The card's third figurecame from [finding]
packages/spec/authorable-surface.base.jsonis a pinned deletion-gate anchor that lags the live ratchet by 532 keys — three documents name it as if it were the live authorable surface #14612's triage comment, never from a carrier in this directory; there wasnothing here to repair.
"measured on this tree"live-claim phrasing insidescripts/docs-audit/— two othersites, both sound.
affected-docs.mjsline ~1344 ("zero commands declarestatic topic,and the one
static id(init.tsto'init') agrees with its path") was re-verifiedagainst
packages/cli/src/commands/and is still true — zerostatic topic, andinit.ts:912carriesstatic override id = 'init'. It is also a claim about a zero whosefailure direction the docblock names, not a decaying magnitude. Line ~6019 already carries
its rev (
f5a7f9c88, 7 warm runs) and is the correct form.workflow or doc reads these sentences; the repo-wide grep above is the reading.
Two sites outside
scripts/docs-audit/use the same "measured on this tree" phrasing(
scripts/check-bash32-floor.mjs~121,scripts/pm/dispatch-gates.mjs~8307; the secondcarries a count, "one of the six"). Out of scope here by the same triage boundary; they belong
to the population card above.
Verification
All 34 gate families
scripts/pm/dispatch-gates.mjsderives for this change set were runin this worktree and every one exited
0; reconciled with--rancarrying exit codes:The load-bearing ones for this diff, with the verdict lines they printed:
pnpm check:docs-audit-scope—✓ affected-docs self-test: 585 cases pass./✓ check-audit-scope self-test: 32 cases pass.node scripts/docs-audit/check-affected-docs.mjs— exit0(this is the discoverable namefor
affected-docs.mjs --self-test; no*.test.tsin the tree namesaffected-docs, sothis wrapper is the script's whole suite)
pnpm --filter @objectstack/spec run check:authorable-surface— exit0, and the source ofthe delta line quoted above
pnpm check:nul-bytes— exit0; plus a direct control-character sweep over both editedfiles, clean
Repo-wide
pnpm lintwas not run — it is the CI-owned run, and no narrowing is claimedhere in its place. No changed file carries executable behaviour.
Changeset:
skip-changesetMeasured rather than assumed.
scripts/docs-audit/is repo tooling: the root manifest isprivate: true, and no non-private package'sfiles[]names a path that reachesscripts/(checked across every
packages/**/package.json; positive control —packages/spec'sfiles[]resolves to real published paths such asdist,json-schema,api-surface, sothe zero is a measurement and not an empty scan). Nothing published moves ⇒ the
skip-changesetlabel is applied to this PR.Clause-②
no. The diff changes explanatory prose in repo tooling only. It touches no spec schema, nopublished
exports, no wire shape and no authorable key — nothing a contract review has asurface to review. The card-side carrier the PM placed reads
no; this PR-body carrier agreesand was self-verified with
readClause2Line().Governance
No governed surface is touched (
docs/adr/**,.claude/**,skills/**,AGENTS.md,CLAUDE.mdare all absent from the file list). Left as a draft and not armed forauto-merge — arming is the PM's act.
Generated by Claude Code