Repository navigation
Commit d13df0c
docs(skills): os-dev.md names check:pm-dispatch-gates as a detached, unlocked check:* gate; its duration reading corrected (#21798)
Fixes #21786
Clause-②: no
Maintainer-direct card (the order is quoted verbatim in the card body).
It carries the remedy measured on #21719,
which is closed; nothing here acts on that card.
## What changed: two in-place edits, two files, net 0 lines
### 1. `.claude/agents/os-dev.md`, 〈资源纪律〉 item 1: one added sub-line
After (new line 83, 120 bytes), directly under the unchanged `check:*`
sub-line (line 82, 104 bytes):
```text
- 它不保证机器空闲:`check:*` 门禁、install、dev server 不走它,与持锁同核并跑。
- 测试电池 `pnpm check:pm-dispatch-gates` 亦属 `check:*`:不走锁,`nohup … > LOG 2>&1 &` 后 `tail --pid`。
```
Before: no line in the file named the battery. `git grep -n
'pm-dispatch-gates' e83c9f6 -- .claude/agents/os-dev.md` exits 1; the
control word `os-verify-lock` in the same file answers 2 hits, exit 0.
Item 1's first sentence 「每次 build/test 都从这里走」 is what sent a
`check:*`-named test battery into the lock. The new line follows the
"Run --self-test DETACHED on an agent container" section of the
`scripts/pm/dispatch-gates.mjs` header (about :28 to :50).
**Why a new line rather than a rewrite of line 82 (dispatch route a).**
Route (a) does not fit. Adding only the gate name to the existing
sub-line, as 「(含 `pnpm check:pm-dispatch-gates`)」, measures 140 bytes
before any detach prescription, which is over the 120-byte cap. So the
line is new, and it is paid for by deleting a restated line from the
same file (route b):
| deleted line (old line 203, 〈标准条款住在这里〉, 73 bytes) | owning copy that
stays on the reading path |
|---|---|
| `- `origin/main` 是共享指针,别的 agent 一次 fetch 就推进它。` | `AGENTS.md`,
Multi-agent working discipline, lines 343 to 344 at `e83c9f615`:
"**`refs/remotes/*` is shared** — a sibling's fetch advances **your**
`origin/main`" |
The same fact also stays in os-dev.md itself, one line above the
deletion (line 200, unchanged): 「共享的含 refs(含 `refs/remotes/*`)、stash
栈、config、hooks;配方不点名共享态才 worktree-safe。」 The line that followed the
deleted one (`git reset --soft origin/main` …) still reads correctly
after it.
### 2. `.claude/skills/pm-dispatch/references/platform-readings.md`,
line 432: edited in place
```text
before (113 bytes): - `check:pm-dispatch-gates` 单机 430–450 秒贴容器上限 ⇒ detach 加 `tail --pid=$!`;超时非读数。
after (118 bytes): - `check:pm-dispatch-gates` 1216–1246 秒超容器上限 ⇒ 不走锁,detach 加 `tail --pid=$!`;超时非读数。
```
Provenance of the number: these are the holds the lock printed on its
own `VERDICT` line for five dev runs in one shift on 2026-10-04. They
ran on an agent container through `os-verify-lock.sh -c`: 1239, 1246,
1224, 1216 and about 1222 s, with the battery itself at 1222 to 1245 s
over 1976 cases (#21719 body). This PR did not
re-measure them, because the battery takes about 20 minutes. The detach
plus `tail --pid=$!` prescription and 「超时非读数」 are kept. 「不走锁」 points the
same way as edit 1. A per-run unit 「秒/次」 measured 122 bytes, so it was
left out; the comparison with the per-command cap already reads as a
per-run figure.
### Declared deviation from the dispatch wording
The dispatch spelled the os-dev prescription "tail 日志", after the
header's "tail the log file until it stops growing". The line says `tail
--pid` instead, for three reasons. The platform-readings row already
uses that prescription (`tail --pid=$!`). It is also the only waiting
shape os-dev.md 〈干净收尾〉 item 4 allows: 「前台跑完,或 `tail --pid` 等它退出」. A bare
"tail the log" can be read as polling, which the same file forbids. The
line comes to exactly 120 bytes.
## Not changed
- `scripts/pm/os-verify-lock.sh` and `scripts/pm/dispatch-gates.mjs` are
untouched. The dedicated-slot, run-length-class and self-test-batching
routes were rejected at triage, and the latter file is frozen under
ruling 208.
- No gate, patrol row or script was added. No file other than the two
above changed.
## Line budget
| file | lines before → after | ceiling | edited / added / deleted lines
|
|---|---|---|---|
| `.claude/agents/os-dev.md` | 402 → 402 | 402 (unchanged) | +1 (line
83, 120 B) / −1 (old line 203, 73 B) |
| `.claude/skills/pm-dispatch/references/platform-readings.md` | 469 →
469 | 469 (unchanged) | 1 edited in place (line 432, 113 B → 118 B) |
No ceiling was raised, and no lines were gained by re-wrapping.
## Gates, run on HEAD `2ea131a3e` (the only commit on this branch)
Every `check:*` gate ran outside the verify lock. The only locked run
was the build that one gate's prerequisite needed. Exit codes were
captured before any pipe.
| command | exit | verdict line (abridged) |
|---|---|---|
| `pnpm check:pm-skill-ratchet` | 0 | `os-dev.md is 402 lines (ceiling
402; headroom 0)` · `platform-readings.md is 469 lines (ceiling 469;
headroom 0)` · self-test 157 cases pass |
| `pnpm check:agent-model-declared` | 0 | `1 agent definition(s) under
.claude/agents/ all declare a model` (`os-dev.md → opus`) |
| `pnpm check:pm-skill-id-lint` | 0 | `34 file(s) clean (pattern
/#[0-9]{3,}/g)` |
| `pnpm check:skill-frame-sync` | 0 | `the one declared copy of the
decision frame is internally coherent` |
| `pnpm check:nul-bytes` | 0 | `scanned 10150 text file(s) … no raw
ASCII control bytes` |
| `pnpm check:pm-governed-merges` · `check:pm-half-states` ·
`check:commit-card-trailers` · `check:doc-authoring` ·
`check:agent-test-spelling` · `check:cross-package-test-inputs` ·
`check:driver-memory-census` · `check:gitlink-declared` ·
`check:refd-timer-probe` · `check:required-contexts` ·
`check:watch-hint-literal` | 0 each | each gate's own pass line |
| `node scripts/check-closing-keyword-parity.mjs` (+ `--self-test`) ·
`check-comment-mask-corpus.mjs` · `pm/check-governed-queue-guard.mjs
--self-test` · `pm/check-harness-current.mjs --self-test` | 0 each |
each gate's own pass line |
| `pnpm --filter @objectstack/lint run check:doc-formula-expressions` |
3, then 0 | The first run printed `PREREQUISITE NOT MET` (formula and
lint not built). That run measured nothing and is not a finding. After
the build `os-verify-lock.sh -c 'pnpm exec turbo run build
--filter=@objectstack/formula --filter=@objectstack/lint'` (`VERDICT
command-exit 0 · held the lock 71s`), the rerun printed `22
record-scoped formula example(s) … judged clean` |
| beyond the derivation: `check:pm-settings-deny-roster` ·
`check-published-list-mirrors.mjs` · `check-skills-token-ratchet.mjs` ·
`check:pm-governed-prose` | 0 each | the roster under `.claude` checked,
the mirrors match, and the governed prose names all 6 surfaces |
Reconciliation: `node scripts/pm/dispatch-gates.mjs --repo
objectstack-ai/objectstack --ran FILE` printed `22 derived famil(ies)
accounted for — 22 run, 0 NOT-MEASURED (a DERIVED zero — all 22 recorded
an exit code and none of them is 3)`. The derivation names its tree as
`objectstack-ai/objectstack` at commit `2ea131a3e`, with a change set of
2 paths against merge base `e83c9f615`.
NOT MEASURED locally:
- The two CI-only families: `check-required-contexts
--verify-required-set` and `check-half-states --provenance`.
- The four type-check lanes. The diff touches no TypeScript.
- `pnpm check:pm-dispatch-gates`. It is not derived for this diff and
was deliberately not run.
## Acceptance notes
- The card's acceptance, "The next shift's PM-tool dev reports record no
locked `check:pm-dispatch-gates` hold", is a future reading that this PR
cannot prove. What the PR does prove: both texts landed, and the
ratchet, agent-model, id-lint and frame-sync gates are green.
- The card body says "each line is paid in place by tightening a
neighbouring line". `os-dev.md` bars re-wrapping as a way to gain lines,
so the os-dev line is paid for by deleting a restated line instead
(table above).
- The 1216 to 1246 s figure is a shared-box reading: unlocked sibling
`check:*` work ran beside the holder. On a quiet container the header
says the battery fits inside the cap. The 120-byte row has no room to
state that condition, so it is recorded here.
## 维护者速读(草稿)
**改了什么**:开发 agent 手册「资源纪律」第 1 条新增一行,写明 `pnpm check:pm-dispatch-gates`
这条约 20 分钟的自测电池属于 `check:*` 门禁:不走共享验证锁,用 nohup 放到后台跑,再用 `tail --pid`
等它结束。为保持行数不变,同文件删掉了一条与 AGENTS.md 重复的行(「origin/main
是共享指针」)。平台读数表里这条电池的耗时也从过时的 430–450 秒改为实测的 1216–1246 秒,并写明不走锁。
**为什么改**:手册原话「每次 build/test 都从这里走」,让开发 agent 把这条以 `check:*`
命名的测试电池当作测试送进了锁。一班里出现五次,每次占锁约 20 分钟;同期其他 agent 排队超时(exit
99),只好绕开锁运行。锁本来就不接收 `check:*` 门禁,问题出在说明书写得含糊,而不在锁或脚本。
**风险与代价(含回滚)**:只改两行说明文字,不动任何脚本、门禁或锁策略,两个文件的行数上限都不变。代价是被删的那行不再出现在
os-dev.md 里,但 AGENTS.md 的原句和同文件上一行(refs/remotes 共享)仍在阅读路径上。回滚方式:revert 本
PR 的唯一一个 commit。
**席位意见**:
**你要做的**:本 PR 属 Tier S(只改 `.claude/**`),席位完成达档复核并留下 PASS
记录后经合并队列落地,不需要你批准。只有当你认为这条规则方向不对时才需要提出。效果要看下一班 PM 工具卡的开发报告,是否不再出现
`check:pm-dispatch-gates` 占锁。
---
_Generated by [Claude
Code](https://claude.ai/code/session_011SekRJwTRqXSmsP6xTSci4)_
Co-authored-by: Claude <noreply@anthropic.com>1 parent 26d710e commit d13df0c
2 files changed
Lines changed: 2 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
80 | 80 | | |
81 | 81 | | |
82 | 82 | | |
| 83 | + | |
83 | 84 | | |
84 | 85 | | |
85 | 86 | | |
| |||
200 | 201 | | |
201 | 202 | | |
202 | 203 | | |
203 | | - | |
204 | 204 | | |
205 | 205 | | |
206 | 206 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
429 | 429 | | |
430 | 430 | | |
431 | 431 | | |
432 | | - | |
| 432 | + | |
433 | 433 | | |
434 | 434 | | |
435 | 435 | | |
| |||
0 commit comments