Skip to content

docs(pm-dispatch): the detach reading names where its pid comes from - #18405

Merged
os-elon-musk merged 2 commits into
mainfrom
claude/issue-18362-platform-readings-detach-pid-source
Sep 16, 2026
Merged

os-elon-musk merged 2 commits into
mainfrom
claude/issue-18362-platform-readings-detach-pid-source

Conversation

@os-elon-musk

Copy link
Copy Markdown
Collaborator

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 namepgrep -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 runPREREQUISITE 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

维护者速读(草稿)

改了什么 —— 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:534guard-process-kill.sh 文件头已经各写了一遍。回滚 = revert 本 PR 的单行 diff,无后续依赖。

席位意见 ——

你要做的 —— 这是受管面(.claude/**),合并权不在任何 agent 席位手里。按 references 层的分级,它走 skills 席的 contract-tier 复核后由本席落地;若你想自己看一眼,只需看上面 before/after 那两行,和「要不要为 pgrep 那句话删掉 单机」这一个取舍。


Generated by Claude Code

The `check:pm-dispatch-gates` reading prescribed "detach + `tail --pid`" but
never said where the pid comes from; re-deriving it with `pgrep -f` matches the
asking shell's own command line, so the monitor waits on itself. The recipe now
carries the pid source in its own copyable spelling, `tail --pid=$!`.

Re-keyed in place: 466 / 466 lines, the row 119 -> 113 bytes.

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

Copy link
Copy Markdown
Collaborator Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 7674f7ce7f7a6bc9b5b9bbc765696ad78ee4af32

① Derived judgments

  • Accept set / public surface: none — references/platform-readings.md only (this skill's fact layer); no runtime code, no published package.
  • Diff read whole by this seat (merge-base → head, +1 / −1, one file, 466 → 466): the detach row now reads detach 加 \tail --pid=$!` — the pid's source is in the prescription in the spelling a reader copies; the card's three protected parts (430–450 秒, detach, 超时非读数) are byte-identical on the head; the byte paid is 调用方 (贴调用方容器上限贴容器上限), the route this seat's claim named. grep -c 'tail --pid'= 1 onorigin/mainand 1 on the head;git diff origin/main..head --stat` = 1 file, 1 insertion, 1 deletion.
  • Item 2 of the card (⭐ 「若要写得更稳」 — explain the pgrep -f self-match) is optional by its own wording and is declined here with the dev's byte table: every spelling that fits the 120-byte cap deletes 单机 and/or 容器 from the measured half, and the rule already lives at AGENTS.md:534 (read on origin/main by this seat: 「wait only on one, never a name — pgrep -f matches the asking shell」) and in guard-process-kill.sh's header. A reader who copies =$! has no pid left to re-derive. Adopted.
  • Re-run by this seat on the head in a detached worktree: check-skill-line-ratchet.mjs exit 0 — 466 lines, ceiling 466, headroom 0; the row 113 B (cap 120); check-clause2-carriers.mjs --pair 18405 exit 0; path face GOVERNED, wholly under references/ (fact layer ⇒ in-seat landing).

② Semver level

skip-changeset — nothing published moves.

③ Boundary flags

Implemented-by: claude/issue-18362-platform-readings-detach-pid-source
Reviewed-by: session_01Bz6hxDBqK62NP2W1LATvnt

VERDICT: PASS


Generated by Claude Code

@os-elon-musk
os-elon-musk marked this pull request as ready for review September 16, 2026 09:41
@os-elon-musk
os-elon-musk added this pull request to the merge queue Sep 16, 2026
Merged via the queue into main with commit 90b23ab Sep 16, 2026
32 checks passed
@os-elon-musk
os-elon-musk deleted the claude/issue-18362-platform-readings-detach-pid-source branch September 16, 2026 10:01
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

Development

Successfully merging this pull request may close these issues.

platform-readings 的 detach 处方没说 pid 从哪来 —— 用 pgrep -f 重新推导会自匹配到包装器自己,监视器永远等自己

2 participants