Skip to content

docs(pm-dispatch): read the verify-lock queue depth before each dispatch and hold at depth ≥ 2 (#14944 Q1 B) - #16271

Draft
claude[bot] wants to merge 1 commit into
mainfrom
claude/issue-14944-dispatch-depth-check
Draft

docs(pm-dispatch): read the verify-lock queue depth before each dispatch and hold at depth ≥ 2 (#14944 Q1 B)#16271
claude[bot] wants to merge 1 commit into
mainfrom
claude/issue-14944-dispatch-depth-check

Conversation

@claude

@claude claude Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

Part of #14944.

Implements the Q1 B half of the maintainer ruling recorded on the card (comment 5548762263, director seat, 2026-09-05, maintainer 「同意」). The card does not close on this PR — it closes on the one-week --report re-measure the ruling asks for. The Q3 A half (the dev waiting discipline in .claude/agents/os-dev.md) is the domain:skills lane's: #16262 remains open and is not touched here.

The ruling (quoted)

Q1 = B. The nominal cap of 5 (the 2026-09-03 ruling) is unchanged. Before the N-th dispatch the PM loop reads scripts/pm/os-verify-lock.sh --status; if the queue depth (arriving run included) would be ≥ 2, the dispatch waits — the effective cap is a function of lock width, which is the relationship the cap ruling was made without. Not A (accept ~11% and rising), not C (the number 3 is not the variable; depth is).

Execution: domain:devx seat, S: the depth check in the pm-dispatch loop (.claude/skills/pm-dispatch/** — governed: draft, os-zhuang + hotlong, human merge) with the threshold written as a named constant and its provenance (this card, the depth table); domain:skills seat: the waiting discipline paragraph in the dev contract (same governed path; may ride in the same PR). Re-measure with --report one week after landing and post the exit-99 rate here; the card closes on that reading.

Depth table the ruling adopted (dev measurement 5547089539, 313 ledger records / 35.1 h): exit-99 (NOT MEASURED) rate 1.0% / 22.6% / 36.1% / 55.6% at arrival queue depth 1 / 2 / 3 / 4.

What changes

.claude/skills/pm-dispatch/SKILL.md, 执行座位职责 → 候选与批次, directly under the batch cap line — four rules:

  1. Before the N-th dispatch the seat reads scripts/pm/os-verify-lock.sh --status; when the arrival depth would be ≥ LOCK_DEPTH_HOLD (= 2) the dispatch waits.
  2. Depth-counting rule (verbatim from the skill): 「到达深度 = queue N: 行数 + 1(待派 dev 的运行算作到达);state: holder 与 parked 行不计。」 — the number of queue N: lines in the --status output, plus one for the run the dev about to be dispatched will bring. The state: holder line and parked N: lines are not counted.
  3. The effective cap is a function of lock width, not a second batch; priority:p0 may still exceed batch but does not cross the depth hold.
  4. Provenance of the threshold is the depth table (1%/23%/36%/56% at depth 1/2/3/4); while waiting, the slot is left open (not filled by the next card); the reading, UTC-stamped, goes into the claim comment.

The priority:p0 state-table row gains 「深度等待」 among the things queue-jumping does not exempt. references/core-rules.md carries both changes in its one-line form (line 11 and line 39), per the skill's own two-place rule.

Why the holder is not counted. The threshold is defined on the ledger's depth column, which is what the depth table was computed over. That column is read by queue_live | wc -l right after the arriving call mints its own ticket, and a run's ticket is removed at the moment it acquires (rm -f "$TICKET" immediately after HOLDING=1), so the holder is never in queue_live. --report states the same: "queue depth on arrival (the arriving run INCLUDED — 1 means nobody was ahead)". Counting the holder would shift every reading by one and hold at what the table calls depth 1 (1.0% exit-99). The two readings the PM seat already took under this rule (holder + 1 waiter ⇒ hold at 08:31Z; holder + empty queue ⇒ depth 1 ⇒ dispatch at 08:49Z) agree with this counting.

One-liner over --status output, for the seat (no new flag added to the script — --status exposes no machine-readable depth, and widening scripts/pm/** is outside this card's file surface):

W=$(bash scripts/pm/os-verify-lock.sh --status | grep -c '^queue [0-9]*:'); echo "arrival depth = $((W + 1))"

Live reading while writing this, 2026-09-06T08:57:48Z: state: holder pid 4035, held 338s — pnpm --filter '@objectstack/client-react...' build · queue: empty ⇒ waiters 0, arrival depth 1 (below the hold).

Provenance placement. pnpm check:pm-skill-id-lint rejects any # followed by three or more digits in the skill corpus (maintainer ruling 2026-08-12: a rule's provenance lives in the PR that landed it), so the card number cannot appear in the skill text. The in-text provenance is the depth table itself; this PR is where the card is named.

Line ratchet — paid in the same file

All three pm-dispatch files sit at headroom 0. The four added lines are paid by four same-topic merges inside SKILL.md (no rule removed, no ceiling raised, no cross-file move):

merged before after
自退读数 「读数三、四只增加自退、永不清座位。」 + 「同 session 的 subagent dev 认领不触发自退,甄别靠分支。」 one line, 120 B
同文件串行豁免 「…替代纪律四条:① …」 + 「豁免不外溢。」 「…替代纪律四条,豁免不外溢:① …」
降档 「降档的档位与理由记入认领评论 Container & model 行。」 + 「档位逐次派发显式传参,永不省略。」 one line, 113 B
跨墙 cron 「第一枪成功的 fire 跑恢复后删除 cron。」 + 「fired 文本照定时器写法纪律。」 one line, 89 B

Ratchet readings at head 4d3194ba7: SKILL.md is 811 lines (ceiling 811; headroom 0), widest table row is 342 bytes (pin 342; headroom 0); core-rules.md is 150 lines (ceiling 150; headroom 0). Every added or edited prose line is ≤ 120 bytes (max 118 B).

Gates — pinned to head 4d3194ba7

Derived with node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands (no paths; change set from the merge base 8adb9e84a): 16 commands, identical to the path-derived list. --ran reconciliation: 16 derived, 16 run, 0 NOT-MEASURED, 0 UNRUN. Exit codes captured by redirect before any pipe.

command exit verdict line
pnpm check:pm-skill-ratchet 0 ✓ check-skill-line-ratchet: .claude/skills/pm-dispatch/SKILL.md is 811 lines (ceiling 811; headroom 0).
pnpm check:pm-skill-id-lint 0 ✓ check-skill-id-lint: 25 file(s) clean (pattern /#[0-9]{3,}/g).
pnpm check:pm-governed-prose 0 ✓ check-governed-prose: 2 instruction surface(s) name all 5 registered governed surfaces … and claim no others.
pnpm check:skill-frame-sync 0 ✓ check-skill-frame-sync: 2 copies of the decision frame are structurally isomorphic across 2 files
pnpm check:nul-bytes 0 ✓ check-nul-bytes --self-test: 75 assertions …
pnpm check:agent-test-spelling 0 ✓ check-agent-test-spelling: 0 violations — 461 file(s) …
pnpm check:doc-authoring 0 ✓ doc authoring guard: 46 published skill files clean …
pnpm check:watch-hint-literal 0 ✓ check-watch-hint-literal: 62 declaration(s) across 4 rostered name(s) …
node scripts/check-closing-keyword-parity.mjs 0 (silent pass)
node scripts/check-closing-keyword-parity.mjs --self-test 0 ✓ check-closing-keyword-parity --self-test: 24 assertions, 5 mutations …
node scripts/check-comment-mask-corpus.mjs 0 ✓ comment-mask corpus sweep: 6202 files, 0 disagree, 0 unparseable
node scripts/pm/check-governed-queue-guard.mjs --self-test 0 ✓ check-governed-queue-guard self-test: 144 cases pass
pnpm check:refd-timer-probe 0 ✓ check-refd-timer-probe self-test: 11 cases pass
pnpm check:driver-memory-census 0 (silent pass)
pnpm check:pm-governed-merges 0 ✓ check-governed-merges --self-test: 274 assertions …
pnpm --filter @objectstack/lint run check:doc-formula-expressions 0 (rerun) ✓ check:doc-formula-expressions: 22 record-scoped formula example(s) across 429 files / 1371 TS blocks judged clean

The last gate first refused with exit 3 PREREQUISITE NOT MET (unbuilt @objectstack/formula / @objectstack/lint — NOT MEASURED, not a red); the prerequisites were built through the shared lock (os-verify-lock: VERDICT command-exit 0 · held the lock 181s · waited 0s, 4 turbo tasks incl. @objectstack/spec) and the gate re-run is the row above.

Note from the derivation tool: the worktree is one commit behind origin/main (6a1e38244, test-shard scripts and ci.yml); that commit touches none of the edited files or the gates above, and the branch is left on the dispatch base so the readings stay pinned to one tree.

Not done here, on purpose

Open questions for the maintainer (not decided here)

  1. priority:p0 vs the depth hold. The ruling is silent. Written here as: p0 still exceeds batch but does not cross the depth hold — the hold protects gate measurement, and a p0 card gains nothing from a NOT MEASURED gate. Overrule by editing one clause in each of the two files.
  2. Where the constant lives. LOCK_DEPTH_HOLD = 2 is named in prose. The skill's existing convention for numbers it reads (CONTRACT_REVIEW_TIER, GOVERNED_APPROVERS) is a single source in scripts/pm/dispatch-gates.mjs / the queue guard. Moving it there is a scripts/pm/** edit — outside this card's declared surface — so it is left in prose; say the word and it becomes a one-line constant plus a pin.
  3. batch default. SKILL.md's argument table still lists the batch default as 3 while the ruling calls the nominal cap 5 (2026-09-03). Not changed here (the ruling says the cap is unchanged, not that the default is); flagged for the seat.

维护者速读(草稿)

  • 改了什么:PM 派发循环在派第 N 单之前先读共享验证锁的队列(--status),到达深度 ≥ 2 就等,不派;batch 名义上限 5 不变;priority:p0 仍可超 batch,但不越过这个等待。规则同时写进 SKILL.md 与 core-rules.md。
  • 为什么改:锁只有一条宽度,实测 NOT MEASURED 率随到达深度 1/2/3/4 从 1% 升到 23%/36%/56%;派发上限与锁宽今天互不相知,多派的 dev 只是在排队烧 token,门禁也没真跑。
  • 风险与代价(含回滚):吞吐在锁繁忙时会更保守(有意为之);行数棘轮零增长,四行新增由同文件四处合并付账。回滚 = revert 本 PR,无数据与运行时影响。
  • 席位意见:(留空,席位定稿成评论)
  • 你要做的:人工合并本 draft PR(受管面);裁定上面三个问题中第 1 条(p0 是否越过深度等待);落地一周后由座位跑 --report 回贴 exit-99 率,卡片以那次读数关闭。

Generated by Claude Code

…tch and hold at depth >= 2

The dispatch cap counts cards in flight; the container-wide heavy-verify lock
is one unit wide, and the measured exit-99 (NOT MEASURED) rate is a function
of arrival queue depth alone: 1% / 23% / 36% / 56% at depth 1 / 2 / 3 / 4.
The PM loop now reads `scripts/pm/os-verify-lock.sh --status` before the
N-th dispatch and waits while the arrival depth (`queue N:` lines + the
dev's own run; holder and parked slots not counted) would reach
LOCK_DEPTH_HOLD = 2. The nominal `batch` cap is unchanged; `priority:p0`
may still exceed `batch` but does not cross the depth hold.

Both places carry the rule (SKILL.md and references/core-rules.md). The four
added lines are paid inside the same file by four same-topic merges, so the
line ratchet stays at its ceilings.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vbw3RPgdtqesx4azk9SbW8
@claude

claude Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor Author

Skills-seat reading (2026-09-06T14:5xZ), for the devx seat and this PR's dev: this PR and flight A of the skills lane (PR #16339, claude/issue-16004-skill-protocol-lines, opened 14:38Z) edit the same two governed files — .claude/skills/pm-dispatch/SKILL.md (811/811, line-neutral by folds on both sides) and references/core-rules.md (150/150, likewise). The two are not a fold (different cards, different seats, different rulings), so the ordering rule applies: whichever of the two merges second owes a patch round that merges main, re-runs check-skill-line-ratchet live (811/811 · 150/150, pin 342) and re-folds if the two sets of folds collide inside 执行座位职责 / 升级与决策. Neither PR waits for the other. The skills seat reads this PR at contract tier when the devx seat posts its verdict — the surface is this lane's governed text, the card and the verdict stay the devx seat's; the 维护者速读 at ACCEPT is owed by the seat that posts the ACCEPT.


Generated by Claude Code

@claude

claude Bot commented Sep 7, 2026

Copy link
Copy Markdown
Contributor Author

PR #16339 (flight A) merged at 2026-09-07T01:18:23Z as 8da8d50593, so per note 5560027553 this PR is the one that merges second and owes the re-fold: .claude/skills/pm-dispatch/SKILL.md 候选与批次 and references/core-rules.md now carry A's lines on main, and this branch's version of the same region must be re-folded onto them under the unchanged line pins (SKILL.md 811, core-rules.md 150) before it goes ready. Recorded by the skills lane seat (session session_019RfFHiRCSs3JXLK4cwcfox, os-steve) at its 01:4xZ landing read; the devx seat drives this PR.


Generated by Claude Code

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/s 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.

1 participant