Skip to content

docs(pm): batch default back to 3 on the maintainer's ruling — ceiling 5 unchanged (#18125) - #18128

Merged
os-zhuang merged 1 commit into
mainfrom
claude/issue-18125-batch-default-3
Sep 14, 2026
Merged

os-zhuang merged 1 commit into
mainfrom
claude/issue-18125-batch-default-3

Conversation

@claude

@claude claude Bot commented Sep 14, 2026

Copy link
Copy Markdown
Contributor

Fixes #18125

Ruling

The maintainer, in the skills seat's chat at 2026-09-14T03:45Z, verbatim and untranslated: 「并发2 还是太慢了,默认恢复3吧」. It supersedes lock 3's default (PR #18072, commit 7ef05f997, 「batch 默认 2」). The maintainer ceiling 5 stays. Ruling C (#17971, 「C. approve 后不管后续改动都由席位落地:」) governs the landing: this PR stays a DRAFT; the seat does the four-piece; nothing here is readied, queued, armed or approved by the dev.

Change — one line

.claude/skills/pm-dispatch/SKILL.md line 60, the batch:N row of the 〈入口与角色〉 argument table:

  • before: | batch:N | 同时在飞的 dev 上限 | 默认 2;N 的维护者天花板 5 |
  • after: | batch:N | 同时在飞的 dev 上限 | 默认 3;N 的维护者天花板 5 |

(The row is quoted with N standing in for the angle-bracket placeholder the file uses, so the body survives the sanitizer; the file itself is unchanged in that respect.)

Equal-line and byte-neutral: 812 lines before and after (ceiling 812, scripts/pm/check-skill-line-ratchet.mjs:320), 73524 bytes before and after, one insertion / one deletion in git diff --stat ca7886047 06c10152b. Nothing else moves: write-identity locks 1, 2, 4, 5, LOCK_DEPTH_HOLD, the same-file serial rule and the ceiling 5 are untouched. The seats' Routine prompts are the seats' own to update on landing (card body).

Premise readings (all against origin/main = ca7886047, worktree created 2026-09-14T03:50:37Z)

  • P1 holds (read 2026-09-14T03:51Z): SKILL.md line 60 read 默认 2; git grep -n for the literal 默认 followed by a backticked 2, over .claude AGENTS.md CLAUDE.md, returned exactly one hit, .claude/skills/pm-dispatch/SKILL.md:60.
  • P2 holds (read 2026-09-14T03:51Z): references/core-rules.md is 151 lines and states no batch DEFAULT. grep -n batch hits: line 11 「并行度以 batch 封顶,验证锁到达深度 ≥ LOCK_DEPTH_HOLD(2)即等;同批按构造文件面不相交。」 (the verify-lock depth, a different number) and line 37 「插队标签可超 batch 立即派发,⛔ 不豁免同文件串行、深度等待与认领协议。」. grep -n 默认 hits lines 7, 17, 18, 52, 77, 139, 140 — none is about batch. So there is no mirror line, and core-rules.md is untouched (151/151); the card body's "core-rules mirror line likewise" is superseded by the claim comment's reading, which this grep confirms.
  • P3 holds (read 2026-09-14T03:51Z): SKILL.md is 812 lines at ceiling 812; sed -n '733,754p' SKILL.md | md5sum = 3327d02c56f8a0eca88569dad2270f32. Same two readings on HEAD 06c10152b after the edit: 812 lines, md5 3327d02c56f8a0eca88569dad2270f32.
  • P4 holds (read 2026-09-14T03:52:44Z–03:53:16Z): git ls-remote --heads origin listed 1106 heads; the 6 claude/issue-18xxx heads were compared to main through REST GET .../compare/main...BRANCH and all 9 open PRs through REST GET .../pulls/N/files (page count 9, fewer than 100, so the listing is complete): zero hits on pm-dispatch/SKILL.md or core-rules.md in any of them. Scope declared: open PRs plus this wave's issue-18xxx heads; the 62 older keyword-matched heads (seat session branches pm-dispatch-*, old issue branches) were listed but not compared.

Gates (run on the working tree at HEAD 06c10152b, 2026-09-14T03:55Z–04:01Z; every exit captured by redirect-then-$?)

Derived with node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack (no paths; change set from the merge base ca7886047; the --repo assertion held): 16 commands — 9 matched by path, 7 whole-tree. All 16 exit 0:

  • pnpm check:pm-skill-ratchet — exit 0 (ratchet green; widest-table-row pins and ceilings unchanged)
  • pnpm check:skill-frame-sync — exit 0 (「the one declared copy of the decision frame is internally coherent … 74 markdown files scanned for undeclared copies」)
  • pnpm check:pm-governed-prose — exit 0 (「2 instruction surface(s) name all 5 registered governed surfaces … and claim no others」)
  • pnpm check:pm-skill-id-lint — exit 0 (27 files clean)
  • pnpm check:pm-governed-merges — exit 0
  • pnpm check:nul-bytes — exit 0 (8643 text files, no raw control bytes)
  • node scripts/pm/check-governed-queue-guard.mjs --self-test — exit 0 (233 cases)
  • pnpm check:agent-test-spelling — exit 0
  • node scripts/check-closing-keyword-parity.mjs and its --self-test — exit 0 / 0
  • node scripts/check-comment-mask-corpus.mjs — exit 0 (6747 files, 0 disagree)
  • pnpm --filter @objectstack/lint run check:doc-formula-expressions — first run exit 3 「PREREQUISITE NOT MET — @objectstack/formula is not built」 (not a measurement); after pnpm exec turbo run build --filter=@objectstack/formula --filter=@objectstack/lint under os-verify-lock.sh (「VERDICT command-exit 0 · held the lock 167s」), rerun exit 0 (「22 record-scoped formula example(s) across 438 files … judged clean」)
  • pnpm check:doc-authoring, pnpm check:driver-memory-census, pnpm check:refd-timer-probe, pnpm check:watch-hint-literal — exit 0 each

Reconciliation (--ran with COMMAND :: exit CODE lines, 2026-09-14T04:01:47Z): 「✓ dispatch-gates --ran: 16 derived famil(ies) accounted for — 16 run, 0 NOT-MEASURED (a DERIVED zero — all 16 recorded an exit code and none of them is 3).」

Tied family not on the derived list, run anyway: node scripts/check-skill-frame-freshness.mjs (--self-test exit 0, scan exit 0: 「the decision frame in this tree is current with origin/main」). CI-measured only, not runnable here: check-governed-queue-guard.mjs on the event payload.

Lint, narrowed and declared: eslint --no-inline-config --format json .claude/skills/pm-dispatch/SKILL.md — exit 0, 1 file, 0 errors, 1 warning 「File ignored because no matching configuration was supplied」. Population read from eslint.config.mjs: every files: block matches only **/*.{ts,tsx,mts,cts,js,jsx,mjs,cjs} (six blocks; COMMENT_SWALLOW_FILES is the same glob), so a .md file is outside the linted population. Invariance: the config never enables type-aware linting (its own line 328: no parserOptions.project, no typed rules), so a one-line edit to an unlinted file cannot move the verdict of any linted file; the repo-wide pnpm lint is CI's run.

dispatch-gates --tier was read for the claim; its model line is not reproduced here (model-free rule).

Changeset

None owed. The Check Changeset job (.github/workflows/pr-automation.yml, job changeset-check) reads exactly two exemptions — the skip-changeset label and the changesets release PR pinned by branch and author — and no path exemption, so the label is the declaration. The diff publishes nothing: .claude/** is in no released package's files[] (fast-lane class per the dev definition). The label is applied with the additive POST .../issues/N/labels and read back; the read-back is recorded in the report comment on #18125.

维护者速读(草稿)

改了什么:PM 派发技能 SKILL.mdbatch 参数默认值从 2 改回 3;上限 5 不变;只此一行。

为什么改:维护者裁决「并发2 还是太慢了,默认恢复3吧」;lock 3 落地的默认 2 由此被取代。core-rules.md 本就没写默认值,故无需同改。

风险与代价(含回滚):并发默认回到 3 意味着同一时刻多一个 dev 在飞,共享容器的验证锁排队会略长;其余四把写身份锁、验证锁深度等待、同文件串行规则均不动。回滚 = 把该行的 3 改回 2,一行、零副作用。

席位意见:(留空,席位定稿成评论)

你要做的:确认后由授权账号 approve,席位按裁决 C 落地;各席位自行更新自己的 Routine 提示词。

Acceptance notes

  • Dispatch vs dev definition: the dispatch asked for a two-line 维护者速读; the dev definition sets five paragraphs, and the definition wins on conflict, so the five-paragraph form is used with the two-line business content inside it. Noted, no card.
  • noted, not filed: the card body says the core-rules mirror line changes "likewise"; the tree says there is no such line (P2 above). The claim comment already carries the correction. 承接者:无 (nothing to land).
  • noted, not filed: the first check:doc-formula-expressions run exited 3 on a fresh worktree because @objectstack/formula and @objectstack/lint are not built by pnpm install; the gate's own text says so and prescribes the build. Behaviour by design (Absence must be loud), not a defect. 承接者:无.
  • Out-of-scope findings of the three filing classes: none.
  • Clause-②: no

Generated by Claude Code

…g 5 unchanged

One line in `.claude/skills/pm-dispatch/SKILL.md` 〈入口与角色〉: the
`batch:<n>` table row's default moves 2 → 3 on the maintainer's ruling
「并发2 还是太慢了,默认恢复3吧」. The maintainer ceiling 5, the write-identity
locks, `LOCK_DEPTH_HOLD` and the same-file serial rule are untouched;
`references/core-rules.md` states no batch default, so it has no mirror line.
Equal-line and byte-neutral: 812/812 lines, 73524 bytes before and after,
frame block (lines 733–754) md5 unchanged.

Claude-Session: https://claude.ai/code/session_01DAcomhvR9kKizeYgg89Vo8
Co-authored-by: Claude <noreply@anthropic.com>
@claude claude Bot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Sep 14, 2026
@github-actions github-actions Bot added the documentation Improvements or additions to documentation label Sep 14, 2026
@claude

claude Bot commented Sep 14, 2026

Copy link
Copy Markdown
Contributor Author
  • Served-tier: 1957/1957 CONTRACT_REVIEW_TIER — harness model stamp counted over this seat's own transcript (non-sidechain assistant messages a model served; <synthetic> harness notices excluded) at 2026-09-14T04:07Z and compared to the constant's value outside the repository; get_session external_metadata.last_served_model read equal to the constant at 2026-09-14T00:20Z.

Contract review

Head: 06c10152 (PR #18128, card #18125 — the maintainer's direct order) — reviewed at 2026-09-14T04:07Z by the skills seat at the contract-review tier. GOVERNED rules layer (SKILL.md) ⇒ this record is the seat's ACCEPT, not the landing: the draft stays until an authorized APPROVED review (os-zhuang / hotlong, not dismissed) exists; then this seat lands it under ruling C.

① derived judgments (seat-measured on the fetched head, ⛔ not taken from the report):

  1. The one line, exactly as ruled: SKILL.md line 60 「| batch:<n> | 同时在飞的 dev 上限 | 默认 3;n 的维护者天花板 5 |」 — 默认 23, the ceiling 5 unchanged; the maintainer's words of 2026-09-14T03:45Z, verbatim 「并发2 还是太慢了,默认恢复3吧」, are the ruling this line restates. Nothing else moves: locks 1, 2, 4, 5, LOCK_DEPTH_HOLD and the same-file serial rule stay.
  2. Ceilings and frame: 812/812, byte-neutral (73524 bytes before and after), widest row 342 B, frame block 733–754 md5 3327d02c56f8a0eca88569dad2270f32 unchanged; check-skill-line-ratchet and check-skill-frame-sync exit 0 on the head (seat-run in a full worktree).
  3. No mirror owed: references/core-rules.md states no batch default (its batch hits are the lock-depth line and the 插队 line) — the card's 「core-rules mirror」 sentence corrected by the claim and by the dev's P2 grep; 151/151 untouched.
  4. Gates: 16 derived / 16 run / 0 NOT-MEASURED / 0 UNRUN with --repo asserted; check:pm-governed-prose 「2 instruction surface(s) name all 5 registered governed surfaces」; one exit-3 prerequisite built under the verify lock and re-run to 0. Checks on the head at 2026-09-14T04:07Z: 0 red at read time.
  5. Scope held: one file, one line; skip-changeset is the declaration; Clause-②: no holds — no contract path; --pair 18128 on origin/main's reader → exit 0 at 2026-09-14T04:07Z before this record.

② semver: unchanged — nothing published.

③ boundary flags: the domain:services seat's Routine carries the maintainer's earlier 2026-09-13 word 「当前任务处理完,后续并发降到2」; this ruling supersedes the default — that seat updates its own prompt on the landed text (the skills seat knocks on #6021 at landing). Nothing else.

Implemented-by: claude/issue-18125-batch-default-3
Reviewed-by: session_01DAcomhvR9kKizeYgg89Vo8

Verdict: PASS — awaiting an authorized approval; ⛔ never ready / enqueue / auto-merge before it; the seat lands after.

维护者速读(终稿)

按你 03:45Z 的话「并发2 还是太慢了,默认恢复3吧」:SKILL.md 那张参数表里 batch 的默认值从 2 改回 3,上限 5 不动,其余四道锁和验证锁深度规则都不动,只此一行、字节数不变。需要你一条 APPROVED review,之后本席落地。落地后 services 席按新默认自行更新它的 Routine。


Generated by Claude Code

@claude
claude Bot requested review from hotlong and os-zhuang September 14, 2026 04:07
@os-zhuang
os-zhuang marked this pull request as ready for review September 14, 2026 10:47
@os-zhuang
os-zhuang added this pull request to the merge queue Sep 14, 2026
@claude

claude Bot commented Sep 14, 2026

Copy link
Copy Markdown
Contributor Author

Landing under ruling Cdomain:skills seat, 2026-09-14T10:48Z. An authorized APPROVED review exists: 5196699813 by os-zhuang (GOVERNED_APPROVERS), submitted 2026-09-14T10:46Z on the reviewed head 06c10152b, not dismissed. The review of record naming that head is 5658865058 (**VERDICT: PASS**, ACCEPT 5658864898 on #18125); check-clause2-carriers --pair 18128 re-read exit 0 at 2026-09-14T10:47Z; CI on the head 18 success / 16 skipped with the Governed Surface Queue Guard re-running on the merge-group leg. The approver flipped the PR ready and enqueued it (queue ref gh-readonly-queue/main/pr-18128-689d60 present at the seat's read), so the seat leaves the queue entry as set, clears needs-user-decision in this act, and reads the landing by content on origin/main (SKILL.md :60 默认 3, 812/812). On landing the SKILL.md chain behind this PR (#18119#18044#17800#17497) becomes dispatchable and the services seat (#6021) gets its knock.


Generated by Claude Code

Merged via the queue into main with commit fffe3e5 Sep 14, 2026
39 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-18125-batch-default-3 branch September 14, 2026 11:11
akarma-synetal pushed a commit to akarma-synetal/framework that referenced this pull request Sep 17, 2026
…s still exists (objectstack-ai#18149)

Fixes objectstack-ai#17966

`os-verify-lock.sh` already knew, for its own grant logic, whether the
process behind the holder record and behind every queued ticket still
exists — it keys tickets on pid **plus** the `/proc` start time. Both
paths that decide it (`holder_line`, `queue_live`) then **delete** the
record and print nothing about it. That is correct for ordering — a dead
ticket must not wedge the queue — and it is exactly why the reading a
seat needs was never on the page: by the time `--status` prints, the
evidence that a run died holding this lock has been reaped silently, and
the surface reads `state: lock is free` / `queue: empty`, which a reader
takes as *"nothing is blocked"* rather than *"the thing you think is
blocked already died"*.

This PR is the card's **shape 1**: a liveness reading a seat can take in
one command.

## What changed

`--status` now prints, after every pre-existing line:

- one `instrument:` line proving the prober itself works, then
- one verdict line per holder and per queued ticket — the pid, whether
it exists, whether it is still the **same** process by the recorded
start time, and how long ago the record was written.

The snapshot of the records is taken **before** `holder_line` and
`queue_live` run, because those two reap what they judge. Nothing in the
new path prunes, grants or decides; it reads and it reports.

**`--status` was extended rather than given a new flag, and the output
contract was measured before deciding.** `git grep -n -- '--status' --
scripts .claude .github` finds two consumers outside the script:

- `.claude/agents/os-dev.md:103` — prose, "prints the holder and the
queue".
- `.claude/skills/pm-dispatch/SKILL.md:436` — arrival depth = the count
of `queue N:` lines plus 1, with `state:` holder lines and `parked`
lines explicitly **not** counted.

Neither pins the shape beyond those spellings, so lines may be added and
none may be reshaped. A case in the suite asserts those two spellings
still appear, and every new line carries a prefix (`instrument:`,
`liveness `, `refusing:`) that no existing reader counts.

## The reading carries its own control

A prober broken in the **alive** direction reports every corpse as
running — an instrument answering confidently, wrongly, and in the
reassuring direction, which is the shape this card is about. Both
directions are therefore proved in the same output, against pids whose
answer is known before the test runs: this process must read **alive**,
and a child this call started and **reaped** must read **dead** (a pid
can be reused between the reap and the check, so the dead leg retries
before concluding).

If either leg fails, `--status` prints **no reading at all** — not a
reading with a caveat, and not merely no verdicts. Every holder, waiter
and parked line it prints is decided by that same `pid_alive`, so an
unlit prober invalidates the whole listing; the command refuses with
**exit 3**, names the leg that failed, and prints nothing else.

`OS_VERIFY_LOCK_SIM_LIVENESS=alive|dead` exists solely so the suite can
drive both failure directions — the one failure this control is built to
catch cannot be produced by arranging real processes, and a control
nothing has ever been seen to fail is not a control. It is documented at
`pid_alive`, and every invocation announces it on stderr so it cannot be
set quietly.

## Acceptance

**A free lock — the control line, and no verdicts because there is
nothing to judge.** ⚠ The absence is printed, not left to be inferred:
that is the exact shape the card measured (harness "running", lock free,
queue empty, process already dead).

```
state: lock is free
queue: empty (entry-point waiters only — a free-hand flock waiter takes no ticket)
ledger: ... (no records yet)
boots: ... (1 recorded) — `--report` reads them back with their controls
instrument: lit — own pid 6537 reads ALIVE, a child this call started and reaped (pid 6542) reads DEAD, and start times are readable here, so a reused pid is told apart from the original.
liveness: no records to judge — this lock has no holder and no tickets.
          ⚠ That is NOT evidence that whatever you are waiting on is alive. A
          process that never reached this lock leaves nothing here to judge,
          which is the exact shape objectstack-ai#17966 measured: the harness said running,
          this command said free and empty, and the process was already dead.
          Read the process table next to a pid you KNOW is alive before you
          conclude anything about a run that left no record here.
```

**A fixture with a live holder, a live waiter, a dead waiter, a reused
pid and a parked slot** — every pre-existing line unchanged, the reading
appended:

```
state: holder pid 8283, held 95s — pnpm --filter core test
queue 1: pid 8283 waiting 40s — live-waiter
parked 1: slot skills, place kept 300s (blocks nobody) — skills-slot
...
instrument: lit — own pid 8396 reads ALIVE, a child this call started and reaped (pid 8399) reads DEAD, and start times are readable here, so a reused pid is told apart from the original.
liveness holder: pid 8283 ALIVE and still the same process (start time matches the record) — holding 95s (1m35s), since 2026-09-14T06:21:48Z — pnpm --filter core test
liveness waiter ticket 00000000000000000001-8283: pid 8283 ALIVE and still the same process (start time matches the record) — waiting 40s, since 2026-09-14T06:22:43Z — live-waiter
liveness waiter ticket 00000000000000000002-999999: pid 999999 DOES NOT EXIST — nothing is waiting behind this ticket; the record was written 70s (1m10s) ago, at 2026-09-14T06:22:13Z, and the next queue scan prunes it, so this is the one reading you get — dead-waiter
liveness waiter ticket 00000000000000000003-r8283: pid 8283 EXISTS BUT IS NOT THE RECORDED PROCESS (start time 472121 recorded, 472114 now) — nothing is waiting behind this ticket and its pid has been reused; the next queue scan prunes it, so this is the one reading you get — reused-waiter
liveness parked 00000000000000000004-sskills: pid 0 — BY DESIGN no process to judge; a place kept, not a waiter, taken 300s (5m00s) ago, at 2026-09-14T06:18:23Z — skills-slot
```

**Byte-identity of the pre-existing lines.** The pre-change script (`git
show origin/main:scripts/pm/os-verify-lock.sh`) and this one were run
against the **same** fixture state, both outputs truncated at the new
block (`sed '/^instrument: /,$d'`), and diffed:

- free lock, empty queue: `diff` empty, **exit 0**, no normalisation at
all.
- the rich fixture above: `diff` empty, **exit 0**, with one declared
normalisation — `held|waiting|kept N s` durations, which differ between
two runs taken seconds apart by construction and are not affected by
this diff.

**`git diff --stat` against the merge base names only the script** (its
self-test lives in the same file):

```
 scripts/pm/os-verify-lock.sh | 341 +++++++++++++++++++++++++++++++++-
 1 file changed, 338 insertions(+), 3 deletions(-)
```

## Tests

`bash scripts/pm/os-verify-lock.sh --self-test` — **exit 0, 243 cases
pass, 0 fail** (the CI step `Verify-lock entry-point self-test` in
`lint.yml` runs exactly this command). 14 new cases, written in the
suite's existing shape and driving `--status` as a **child process**
against a private lock of their own, because what is owed is the surface
a seat runs — cases that called the helpers in-process would pin the
predicates and leave the output unpinned, which is the state this card
is about.

```
  ✓ a lit liveness reading exits 0
  ✓ and says it is lit, on its own line, before any verdict
  ✓ a waiter whose process is really there reads ALIVE
  ✓ a holder whose process is gone reads DOES NOT EXIST — the one-line reading that was owed
  ✓ and a live pid that is NOT the recorded process is neither alive nor gone
  ✓ and the lines existing readers count are untouched
  ✓ a prober that reads every pid ALIVE refuses instead of reporting
  ✓ and names its instrument as not lit
  ✓ and prints no verdict at all — not one carrying a caveat
  ✓ and withholds the holder, queue and parked lines that same probe decides
  ✓ and the other direction — every pid reading DEAD — refuses too
  ✓ with nothing recorded it says there is nothing to judge
  ✓ and refuses to let that absence read as an all-clear
  ✓ and prints no verdict line, because there is nothing to judge
```

### Ablation — both new claims proved able to fail

Run from the committed fix, each mutation proved on disk
(injected-marker count plus a `git hash-object` blob change against the
`HEAD` blob), each restore leg `git checkout HEAD --
scripts/pm/os-verify-lock.sh` proved by an empty `git diff HEAD`, under
a `trap ... EXIT INT TERM` with absolute paths. Both legs restored
clean; the working tree is at `HEAD`.

**A — the snapshot is taken before the pruning paths.** Moved
`liveness_snapshot` to the foot of `mode_status`. Suite exit 1, **2
cases red**, exactly the ones about records that are reaped as they are
judged:

```
  ✗ a holder whose process is gone reads DOES NOT EXIST — the one-line reading that was owed
      want: 1 / got: 0
  ✗ and a live pid that is NOT the recorded process is neither alive nor gone
      want: 1 / got: 0
```

**B — a failed control refuses.** Made the dead leg's failure return
success instead. Suite exit 1, **3 cases red**:

```
  ✗ a prober that reads every pid ALIVE refuses instead of reporting   want: 3 / got: 0
  ✗ and prints no verdict at all — not one carrying a caveat           want: 0 / got: 1
  ✗ and withholds the holder, queue and parked lines that same probe decides   want: 0 / got: 2
```

⚠ Worth recording from B: `and names its instrument as not lit` stayed
**green** under the mutation — the `instrument: NOT LIT` line was still
printed, beside a full set of verdicts. The line is not the mechanism;
the refusal is. A suite that asserted only the wording would have passed
the broken build.

### Gates

`node scripts/pm/dispatch-gates.mjs --commands --repo
objectstack-ai/objectstack` (no paths) derived **26** families. All 26
run in the foreground, each exit code captured before any pipe, all
**exit 0**; reconciled with `--ran`:

```
✓ dispatch-gates --ran: 26 derived famil(ies) accounted for — 26 run,
  0 NOT-MEASURED (a DERIVED zero — all 26 recorded an exit code and none of them is 3).
```

The list was re-derived after a fresh `git fetch origin main` (base
moved `a90a9f267` to `739ab526d`; no upstream commit touched this file)
and came back identical. Eight artifact-roster families whose roster
sits in a directory this path is in were also run. Six exit 0:
`check-published-list-mirrors`, `check-published-list-mirrors
--self-test`, `check:console-injection`, `check:dts-closure` excepted,
`check:engine-double-contract`, `check:i18n-stale-fill`,
`check:pm-label-desc-cap`.

⛔ **NOT MEASURED:** `check:dts-closure` and
`check:published-readme-exports` both exit **3** (PREREQUISITE NOT MET —
they need a full `pnpm build`'s dist closure). That is not a pass and
not a finding. Neither gate reads a `.sh` file at all and neither roster
names this script, so nothing in this diff can move them; they are left
to CI, which builds.

## Deliberately not in this PR

The card's **shapes 2 and 3** — the rule line in `SKILL.md` and dispatch
briefs, and a seat-side sweep over in-flight dispatches — are a later
PR. `SKILL.md` is serial behind PR objectstack-ai#18128, and it is a different layer
(rules prose, four-piece) from this one (a script with its own
self-test). Splitting them keeps this one landable now and keeps the
prose half from queueing behind a script review. The lock's
mutual-exclusion semantics, ticket ordering, ledger format and boots
format are untouched: this is a **reading** only.

## Acceptance notes

Observed while working here, out of scope, **not filed** (each would
need a carrier that will actually touch the file):

- `noted, not filed:` the CI step comment in
`.github/workflows/lint.yml` describing this suite says "48 cases"; the
suite ran 228 before this PR and 243 after. Pre-existing prose drift, no
mechanism reads the number. Carrier: the next PR that edits the
`Verify-lock entry-point self-test` step.
- `noted, not filed:` the reaping that hid this reading is also
invisible to the waiter's progress output and to `--report` — only
`--status` gained the disclosure. Carrier: none identified; the
seat-facing surface is `--status`, which is where the card asked for it.
- `noted, not filed:` `skip-changeset` applies — `scripts/pm/**`
publishes nothing (no package `files[]` ships it, it is repo tooling).
The label is applied on this PR.

_Generated by [Claude
Code](https://claude.ai/code/session_01DAcomhvR9kKizeYgg89Vo8)_

---
_Generated by [Claude
Code](https://claude.ai/code/session_01DAcomhvR9kKizeYgg89Vo8)_

Co-authored-by: Claude <noreply@anthropic.com>
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/xs skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

1 participant