Skip to content

Commit 90b23ab

Browse files
os-elon-muskclaude
andauthored
docs(pm-dispatch): the detach reading names where its pid comes from (#18405)
Fixes #18362 One row of `.claude/skills/pm-dispatch/references/platform-readings.md`, re-keyed in place. No other row is touched. ## The row, before and after before — 119 bytes: ``` - `check:pm-dispatch-gates` 单机 430–450 秒贴调用方容器上限 ⇒ detach 加 `tail --pid`;超时非读数。 ``` after — 113 bytes: ``` - `check:pm-dispatch-gates` 单机 430–450 秒贴容器上限 ⇒ detach 加 `tail --pid=$!`;超时非读数。 ``` The pid's source is now IN the prescription, in the spelling a reader copies: `tail --pid=$!`. The three parts the card protects are byte-identical — `430–450 秒`, `detach`, `超时非读数`. The one word paid to the byte cap is `调用方` in `贴调用方容器上限`; `容器上限` still names what the seconds bump against. That trim is the route the dispatching seat proposed, and it is what buys the `=$!`. Located by content, never by line number (the card's own correction, comment 5692424694): `grep -n 'tail --pid'` matched exactly one row on `origin/main` at `9a566305e` before the edit and matches exactly one after. ## Line budget — the whole edit had to fit an existing line `pnpm check:pm-skill-ratchet` holds this file at **466 / 466 lines, headroom 0**, and caps every line at **120 bytes** (`scripts/pm/check-skill-line-ratchet.mjs`, section "Why 120 bytes"). So the edit is an in-place re-key: **466 → 466 lines**, the row **119 → 113 bytes**, 7 bytes under the cap. Nothing was re-wrapped to buy room, and no line was added. ## Acceptance item 2 (the starred half) is NOT written here — the measurement, then the reason The card's item 1 (name the pid source) is a hard requirement and is landed. Item 2 (⭐ explain why `pgrep -f` self-matches) is starred, and every spelling of it was measured against the 120-byte cap: | candidate row | bytes | verdict | |---|---|---| | landed, item 1 only | 113 | fits | | item 1 + `⛔ pgrep 自匹配`, qualifiers kept | 133 | 13 over | | item 1 + `⛔ 不用 pgrep`, qualifiers kept | 130 | 10 over | | item 1 + `⛔ pgrep 自匹配`, minus `单机` | 126 | 6 over | | item 1 + `⛔ pgrep 自匹配`, minus `单机` and `容器` | 120 | fits, zero margin | | item 1 + terse `⛔ 非 pgrep`, minus `单机` | 120 | fits, zero margin | So both items fit on one row only by deleting measured qualifiers out of the half the card forbids disturbing (`单机` says the 430–450 seconds is a single-box reading, `容器` says which limit it bumps against), and the two that do fit sit exactly at the cap with no margin for the next author. Against that, the starred half is already written down twice in this repo, both times with more room than a 120-byte row has: - `AGENTS.md:534` (Multi-agent discipline §8) — "⛔ One process table per container: **kill only a PID you recorded, and wait only on one, never a name** — `pgrep -f` matches the asking shell (`guard-process-kill.sh`)." - `.claude/hooks/guard-process-kill.sh` header, lines 72–76 — the measured mechanism itself, including the deadlock it produced on this container. And the re-derivation the card names as the natural wrong completion has no occasion left: a reader who copies `tail --pid=$!` has the pid already. Trading a measured qualifier for a duplicate of a rule two other files carry is the trade this PR declines; the seat can overturn it with one number from the table above. ## Verification Gate families derived from the real change set, not from a hand-written list — `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` (1 path vs merge base `f04be62aa`), then reconciled with `--ran`: ``` Run reconciliation — 16 derived, 16 run, 0 NOT-MEASURED, 0 UNRUN. ✓ 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). ``` All 16 exited 0 on the merged head `7674f7ce7`: `check:pm-skill-ratchet` · `check:pm-skill-id-lint` · `check:skill-frame-sync` · `check:required-contexts` · `check-governed-queue-guard.mjs --self-test` · `check-closing-keyword-parity.mjs` (+ `--self-test`) · `check-comment-mask-corpus.mjs` · `@objectstack/lint check:doc-formula-expressions` · `check:agent-test-spelling` · `check:doc-authoring` · `check:driver-memory-census` · `check:nul-bytes` · `check:pm-governed-merges` · `check:refd-timer-probe` · `check:watch-hint-literal`. The ratchet's own verdict line for this file: ``` ✓ check-skill-line-ratchet: .claude/skills/pm-dispatch/references/platform-readings.md is 466 lines (ceiling 466; headroom 0). ``` `check:doc-formula-expressions` exited **3 on its first run** — `PREREQUISITE NOT MET`, `@objectstack/formula` and `@objectstack/lint` not built — which is not a finding and not a measurement. Cleared by the fix the gate itself prints (`turbo run build --filter=@objectstack/formula --filter=@objectstack/lint`, run through `scripts/pm/os-verify-lock.sh`), then re-run to exit 0. Three gates run beyond the derived 16, each for a stated reason: - `pnpm check:pm-settings-deny-roster` — exit 0. The derivation flags its roster as living under `.claude/`, where one of my paths is, so its silence is evidence in neither direction and it was read rather than assumed. - `node scripts/pm/check-governed-merges.mjs --test .claude/skills/pm-dispatch/references/platform-readings.md` — exit **3, GOVERNED**, as expected: `.claude/** ×1`. This PR stays draft; no seat flips it ready, enqueues it or arms auto-merge. - `node scripts/check-skills-token-ratchet.mjs` — exit 0. It ratchets the published `skills/` catalog, which this diff does not touch; run to prove that, not because it covers this file. **Repo-wide lint is CI's, and the local narrowing is declared with its three readings.** ① The population comes from eslint's own config, not a guess: every `files:` glob in `eslint.config.mjs` is `**/*.{ts,tsx,mts,cts,js,jsx,mjs,cjs}` or a TypeScript subset of it — markdown is in no configured population. ② Counted from `--format json`: eslint over the one changed file returns `errorCount: 0` with `"File ignored because no matching configuration was supplied."`, i.e. 0 linted files in this diff. ③ Invariance: there is no `parserOptions.project` and no typed `@typescript-eslint` rule anywhere in that config, so nothing in this diff can move the verdict of a file it does not contain — and this diff contains no JS or TS at all. Not run and not owed: no workspace package is in the change set, so there is no dependency closure to build and no package test or typecheck to run. `@objectstack/formula` and `@objectstack/lint` were built only as the named prerequisite above. ## Acceptance notes - `.claude/agents/os-dev.md:342` also names `tail --pid` without a pid source — noted, not filed, and deliberately not edited: it is one hop from `AGENTS.md:534`, which bans the `pgrep -f` derivation by name, and the card's item 4 keeps a sweep of other prescriptions out of this PR as a separate card with its own evidence. Successor: whoever files that sweep. - Region-parallel on this file with PR #18396 — that PR's three rows are a different card's and are untouched here; #18396 is not addressed by this PR. `git merge origin/main` was run once before opening this PR; `origin/main` at `f04be62aa` did not carry #18396 yet, and the merge touched no `.claude/` path. - `skip-changeset`: the diff publishes nothing. `.claude/**` ships in no package's `files[]` — it is repo-internal agent instruction text. ## 维护者速读(草稿) **改了什么** —— `platform-readings.md` 里那条讲 `check:pm-dispatch-gates` 太慢要 detach 的读数,原来只说了「detach 加 `tail --pid`」,没说这个 pid 从哪来。现在它自己带上了可照抄的写法 `tail --pid=$!`。全文只动这一行,行数 466 → 466。 **为什么改** —— 处方缺了一半,而最自然的补法是错的:用 `pgrep -f 模式` 反推 pid 时,跑 pgrep 的那层 shell 自己的命令行里就带着那个模式,于是监视器等的是它自己,永远等不到。代价量过:一个 dev 在一张卡上踩了三次,每次都把一次干净跑完、exit 0、日志完整的测量,报成了挂死的后台任务。 **风险与代价(含回滚)** —— 风险极低:改的是给 agent 读的一行说明文字,不进任何产物、不发布、无 changeset。代价是一个词:`调用方容器上限` 压成 `容器上限`,为 `=$!` 腾出字节(该文件行数上限 466 已零余量,每行上限 120 字节)。卡面 ⭐ 的第二件(解释 `pgrep -f` 为什么自匹配)没写进这一行 —— 量过:要写下它,就得删掉 `单机` 或 `容器` 这些量过的限定词,而这条规则 `AGENTS.md:534` 与 `guard-process-kill.sh` 文件头已经各写了一遍。回滚 = revert 本 PR 的单行 diff,无后续依赖。 **席位意见** —— **你要做的** —— 这是受管面(`.claude/**`),合并权不在任何 agent 席位手里。按 references 层的分级,它走 skills 席的 contract-tier 复核后由本席落地;若你想自己看一眼,只需看上面 before/after 那两行,和「要不要为 `pgrep` 那句话删掉 `单机`」这一个取舍。 --- _Generated by [Claude Code](https://claude.ai/code/session_01Bz6hxDBqK62NP2W1LATvnt)_ Co-authored-by: Claude <noreply@anthropic.com>
1 parent 588475c commit 90b23ab

1 file changed

Lines changed: 1 addition & 1 deletion

File tree

‎.claude/skills/pm-dispatch/references/platform-readings.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -424,7 +424,7 @@
424424
- `check-governed-merges` 浅克隆上拒答而非少报,并报未审计仓数;补救 `git fetch --shallow-since=`。
425425
- ⛔ 不越过该拒答自行枚举:短清单读作合规;加深日期取窗口起点之前,不猜深度。
426426
- 前台 `sleep` 被 harness 拒 ⇒ 等待写成带 until 条件的前台阻塞等待,⛔ 不写 sleep 轮询循环。
427-
- `check:pm-dispatch-gates` 单机 430–450 秒贴调用方容器上限 ⇒ detach 加 `tail --pid`;超时非读数。
427+
- `check:pm-dispatch-gates` 单机 430–450 秒贴容器上限 ⇒ detach 加 `tail --pid=$!`;超时非读数。
428428
- `check-half-states.mjs` 连 `--help` 都跑整仓 I/O ⇒ 早读到的输出文件是空的,不是干净的。
429429
- 后台工具调用里再 `nohup … &` 会让包装器报假 `exit 0`,而真活还在跑。
430430
- 分支删除被拒有第二形态:代理回 403,与既有 send-pack 断连同处置 ⇒ 不可删,⛔ 不重试。

0 commit comments

Comments
 (0)