Repository navigation
docs(pm-dispatch): one batch cap for every subagent in flight, triage clean-up prepared one group at a time - #20108
Merged
objectstack-fleet[bot] merged 2 commits intoSep 25, 2026
Conversation
… clean-up prepared one group at a time Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0148fenvVvyQV9HYxgVDQ33q
… the batch cap line Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0148fenvVvyQV9HYxgVDQ33q
Contributor
Author
Contract reviewServed-tier: ① Derived judgments
② Semver level
③ Boundary flags
Implemented-by: VERDICT: PASS Rendered in-seat at 2026-09-25T05:24Z on the fetched head (the branch fetched into a seat-owned ref), diff read three-dot against Generated by Claude Code |
This was referenced Sep 25, 2026
objectstack-fleet
Bot
deleted the
claude/issue-20084-subagent-concurrency-cap
branch
September 25, 2026 05:56
akarma-synetal
pushed a commit
to akarma-synetal/framework
that referenced
this pull request
Sep 28, 2026
…ility; same-family findings fold into one class-closure card; triage gates unproven ones to p3 (objectstack-ai#20110) Fixes objectstack-ai#20088 Clause-②: no Every path in this diff is under `.claude/**` (Tier S): the PR stays a draft, is not readied, queued or armed by any seat, and lands only on a contract-tier review of record. It publishes nothing from any package `files[]`, so it carries `skip-changeset`. ## What changed — one rule, four sites, written as shapes The maintainer's ruling on the card (triage seat chat, 2026-09-25, verbatim): the triage seat answered 「立卡时由发现者确认,分诊只把关、不测量」 and the maintainer said 「同意」. The three numbered clauses of the card's 裁决内容 are implemented as written, at the four sites the card names. No card numbers appear in the operational text (`check:pm-skill-id-lint` refuses them there); the two precedents the card asks for are written as shapes. - **`.claude/agents/os-dev.md` rule 3 — the finder.** Every (a)(b)(c) finding carries a `reach:` entry: one measured wrong answer at a public door (HTTP / UI / `os validate` / save), or one named real producer. Read-only inference is listed among what is not a card and goes to `## Acceptance notes` with `carrier:`. The three exceptions still report — possible data exposure, wrong text that a release would freeze, maintainer-directed — with `reach:` naming which. A same-family finding is pointed at the family's class-closure card in the report instead of a second single-site card; the definition lives in the pm-dispatch 报告契约. The report JSON's `out_of_scope_findings` example line gains the `reach:` field (one edited line inside the fence; nothing else in the block moved). - **`.claude/skills/pm-dispatch/SKILL.md` 报告契约 — the seat.** `reach:` is required on every entry; no measurement ⇒ no card, with the exceptions and the definition at 立卡门 ①; the reports of one round are cross-read and a family opens one card. The class-closure card is defined once here: one card covering every site of the family, one pin that enumerates the sites; when none exists, the second occurrence opens it. The four-axis block (:241–:261) is byte-unchanged (md5 `abff5f852c8fd09b79ec0623439aa4f0` before and after). - **`references/triage-duties.md` — the gate.** All three classes owe `reach:`; triage gates and does not measure. Missing evidence and not an exception ⇒ `priority:p3`, folded into the closure or sweep card, never dispatched alone, and triage never takes the card off the board for that reason (关卡归维护者). The old 「同族异缺陷 ⛔ 不并:互链排同批」 sentence is replaced for findings; in-flight cards (assignee / open PR) are still never merged, `Blocked-by:` is still not dispatched, completion still re-checks staleness. - **`references/filing-gate.md` ① — the definition.** A `finding` inside ① is limited to the three classes AND carries `reach:`; the two accepted forms; the three exceptions, whose first execution item is 「先测可达性」; and the two precedents as shapes — a card whose body itself says 未测量 is not filed (Acceptance notes with a carrier); a card recording one measured wrong answer at a public door is filed. Not done, by the card's own terms: no new `check-*` gate; no retroactive re-triage of existing cards; the 过渡期 sentence stays as the card states it (triage already runs clause ③; clauses ① and ② take effect for the other seats when this lands); `.claude/settings.json` untouched. ## Ratchet payment — every file stays at its ceiling, paid inside its own section | file | lines before | lines after | ceiling | |:--|--:|--:|--:| | `.claude/agents/os-dev.md` | 402 | 402 | 402 | | `.claude/skills/pm-dispatch/SKILL.md` | 319 | 319 | 319 | | `.claude/skills/pm-dispatch/references/triage-duties.md` | 120 | 120 | 120 | | `.claude/skills/pm-dispatch/references/filing-gate.md` | 58 | 58 | 58 | Every prose line is at most 120 bytes; no re-wrap was used as payment. What paid, and why it is equal-or-lower value: - os-dev.md — 「(a) 须今天可达,分错误与不完整…示例照抄即失败是 (a),漏列成员不是」 is subsumed by `reach:` (copying the example is a measured wrong answer at the authoring door; a missing member measures nothing) and survives verbatim for the triage seat at triage-duties :44; 风格/nit left the not-a-card list (抛光 covers them) to make room for 只读推断; the pointer line to `rest-channel.md` is deleted (the dev's four writes go through `scripts/pm/` tools that choose the route; the table is the seat's); the two dedupe lines are merged, dropping 「预算外零写」 (it restates the four-write budget beside it) and 「只复核其后增量」 (it contradicted 「dev ⛔ 不查重」). - SKILL.md — the JSON-shape pointer and the `needs_decision` line are merged; the twin-card cross-read line is replaced by the fold rule, which carries 「同轮报告互读」. - triage-duties.md — the instrument line is deleted: it duplicates `instrument-discipline.md` :6 and :8 verbatim, reached through :41's pointer to the filing gate's ⛔ list. - filing-gate.md — 「原为首触即关,今门前即拒」 (history, not a rule) is dropped from the 三类外 line, which now also names the unmeasured `finding`; the 丢卡重建 and sweep-reminder lines are merged; the fleet-identity line is deleted as a verbatim duplicate of SKILL.md :94 (全体座位的不变量). **Re-merge (head `247e355d`, after PR objectstack-ai#20108 landed):** the write-pacing line this branch first paid with had been REPLACED on `main` by objectstack-ai#20108's 「十张一组只备下一组…」 rule, which is kept verbatim; the payment moved to the ⛔-list row 「⛔ 不是卡:仪器误报与门禁假读数(不派 dev 见 `references/instrument-discipline.md`)。」, whose rule lives verbatim at `references/instrument-discipline.md` :6 / :8 and stays reachable from `references/reading-discipline.md` :26. Three-dot diff unchanged: 4 files, +21 / −21; 58 / 58. ## Deviations from the dispatch, measured - 「先测可达性」 as the first execution item is written at the filing gate ① (the seat's definition) and pointed at from SKILL.md, not in os-dev.md: the dev never writes a card body (os-dev.md rule 3, 「dev 不 `POST /issues`」), so the sentence has no reader there. os-dev.md carries the exceptions as the finder's reporting duty (`reach:` names which). - The dispatch named os-dev.md :41–:60 as this card's region; rule 3 runs to :67. Every edit sits inside :45–:60. - The four sites sat exactly where the dispatch cited them on `origin/main` `8d76c2d` (identical to `d624002` for these paths). Same-day churn: nothing landed on the four paths after the branch point; `origin/main` moved once (`aa04ea29`, objectql) with no overlap. ## Verification Gate families derived from the real change set (`node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack`, no paths, three-dot against merge base `8d76c2d`), all run at head `b985bd39`, each exit captured before any pipe; `--ran` reconciliation: 23 derived, 23 run, 0 NOT-MEASURED (a derived zero — every family recorded its exit code). - exit 0: `check-closing-keyword-parity.mjs` (gate and `--self-test`), `check-comment-mask-corpus.mjs` (7156 files, 0 disagree), `check-governed-queue-guard.mjs --self-test` (279 cases), `check-harness-current.mjs --self-test` (26 cases), `check:agent-model-declared`, `check:agent-test-spelling`, `check:commit-card-trailers` (also run by the pre-push hook: 1 commit, no card relation, no model identifier), `check:cross-package-test-inputs`, `check:doc-authoring`, `check:driver-memory-census`, `check:gitlink-declared`, `check:nul-bytes`, `check:pm-expected-skips`, `check:pm-governed-merges`, `check:pm-governed-prose` (2 surfaces name all 6 governed surfaces), `check:pm-half-states` (4912 cases), `check:pm-skill-id-lint` (34 files clean), `check:pm-skill-ratchet` (157 self-test cases; the four files at 402/319/120/58 against ceilings 402/319/120/58), `check:refd-timer-probe`, `check:skill-frame-sync` (one declared copy, coherent), `check:watch-hint-literal`. - exit 0: `pnpm --filter @objectstack/lint run check:doc-formula-expressions` — its prerequisite, the closure `@objectstack/lint...` (spec, formula, sdui-parser, lint), was built under the shared verify lock (`os-verify-lock.sh` VERDICT command-exit 0, held 203s, 4/4 turbo tasks); 22 record-scoped examples across 456 files judged clean. - exit 0, outside the derivation: `check:skill-frame-freshness` (the frame is current with `origin/main`). - Not owed and not run: no package source changed, so no `pnpm test` / `pnpm typecheck` closure; `pnpm lint` is CI's run. ## Acceptance notes No out-of-scope findings. The (a) boundary lesson (示例照抄即失败是 (a),漏列成员不是) now lives only at triage-duties :44; under `reach:` the same question is answered by measurement. ## 维护者速读(草稿) **改了什么** — 四处协议文本改成同一条规则:发现者立卡前先测可达性 —— 公开入口(HTTP、界面、`os validate` 或保存)实测出一次错误结果,或点名一个已存在的真实生产者 —— 写进 `reach:` 一栏;只读代码推断不立卡,进 PR 的 Acceptance notes 并带承接者。三种例外(可能泄露数据、随发版固化的错误文字、维护者直派)未测量也照立,执行要点第一条写「先测可达性」。同族发现并入该族收口卡(一张卡覆盖全部位置、带一个能枚举全部位置的钉子),不再逐点开卡。分诊只把关不测量:缺可达性证据又非例外的定 p3、并入收口卡或清扫卡,不单独派发,也不因此关卡。 **为什么改** — 维护者在分诊席会话的裁决(2026-09-25,逐字):维护者问「理论上的问题建议时分诊时确认还是立卡时确认?」,分诊席答「立卡时由发现者确认,分诊只把关、不测量」,维护者:「同意」。分诊席的读数:一夜 55 张新卡全部来自 dev 报告的顺路发现,大量卡面自注「未测量」,同一缺陷族连环立卡,开放卡数持平 —— 修复速度赶不上顺路发现的速度。 **风险与代价(含回滚)** — 风险:未测量的 (b) 类发现不再成卡,只留在 PR 的 Acceptance notes,若承接者为无则可能被遗忘;三种例外兜住安全、发版固化与直派。代价:四个文件都在行数上限,每条新句都以删掉一条被新规则涵盖或在别处逐字重复的旧句付账(清单在上文 Ratchet payment 节);没有新增门禁、脚本或数据变化。回滚:revert 本 PR 的单个 commit 即可,四个文件回到原样。 **席位意见** — (留空,由席位定稿成评论) **你要做的** — 本 PR 只改 `.claude/**`(Tier S),保持 draft;席内契约复核记录 PASS 后由席位入队落地,不需要维护者的合并点击。维护者只需确认:第 1、2 条从本 PR 落地起对其他席位生效;第 3 条分诊席已按过渡期条款先行执行。 --- _Generated by [Claude Code](https://claude.ai/code/session_0148fenvVvyQV9HYxgVDQ33q)_ Co-authored-by: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #20084
Clause-②: no
Tier S (every path under
.claude/**): this PR stays DRAFT — no ready flip, no enqueue, no auto-merge; it lands on the owning seat's contract-tier review of record.What changed (three lines, three files, net 0 lines everywhere)
Maintainer ruling implemented as written (director seat chat, 2026-09-25, verbatim and untranslated): 「不要同时派发这么多」 · 「小心封号」 · 「同意,让 skills 车道立卡补上这条规则」.
.claude/skills/pm-dispatch/SKILL.md— thebatchrow of the 入口与角色 table (L59), rewritten in place. The 含义 cell now definesbatchas the seat's cap on EVERY subagent in flight, counted perAgentcall and percreate_session— dev, reviewer, census alike — with read-only explicitly not exempt. The 默认 cell (default3, maintainer ceiling5) is unchanged, and thepriority:p0row (L117, 「插队:可超batch」) is untouched and not contradicted..claude/skills/pm-dispatch/references/execution-duties.mdL21, rewritten in place: the same cap in one line — 「batch封顶全部子代理」 (the dev / 复核 / 普查 / 只读 enumeration lives in theSKILL.mdbatchrow every seat reads first) — keeping 「等待不填槽;同批独立按文件面不相交判」 and the tail 「⛔ 不按包、不按 check 名」 verbatim (it has no other home onorigin/main); 120 bytes, at the inclusive cap. Corrected by the seat after the patch round (headc66d03d): the first headcb2d8c4had dropped that tail, and the seat's REWORK put it back..claude/skills/pm-dispatch/references/filing-gate.md— one new line directly beside the groups-of-ten line (L27): the clean-up prepares only the NEXT group; while the current group is not maintainer-confirmed, the one after is not prepared and the batches are not fanned out in advance.Ratchet accounting (headroom 0 on all three files; no ceiling touched)
SKILL.mdbatchrow width 87 B → 191 B, widest-row pin 342 B untouched (widest row is another row, still 342 B)references/execution-duties.mdreferences/filing-gate.mdPayment rationale for filing-gate.md: the deleted line is a verbatim duplicate of
SKILL.mdL94 「写侧恒为objectstack-fleet[bot](AGENTS.md);节奏 ≥3 秒/笔、每账号每小时 ≤40 笔,429 即停写。」, which every seat reads in full before any reference file; the references convention is one rule per line and no rule already stated inSKILL.md, so it was the lowest-value line in the section. Real deletion, not a re-wrap: no two lines were folded. The write pace stays enforced mechanically bywrite-pace.mjsand stated at its single source. L29 (429 ⇒ 停写并记座位贴) keeps its unique half and stays.Gates at
cb2d8c4(derived withnode scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack, no paths; each exit captured before any pipe)All 21 families exit 0:
check-closing-keyword-parity(+--self-test) ·check-comment-mask-corpus·check-governed-queue-guard --self-test·check-harness-current --self-test·check:agent-test-spelling·check:cross-package-test-inputs·check:doc-authoring·check:driver-memory-census·check:gitlink-declared·check:nul-bytes·check:pm-expected-skips·check:pm-governed-merges·check:pm-governed-prose·check:pm-skill-id-lint·check:pm-skill-ratchet·check:refd-timer-probe·check:skill-frame-sync·check:watch-hint-literal·check:skill-frame-freshness(outside the derivation, cheap) ·@objectstack/lint check:doc-formula-expressions(self-test + gate, after the closure build).Ratchet verdict lines quoted from the gate:
SKILL.md is 319 lines (ceiling 319; headroom 0)·widest table row is 342 bytes (pin 342; headroom 0)·execution-duties.md is 183 lines (ceiling 183; headroom 0)·filing-gate.md is 58 lines (ceiling 58; headroom 0).Patch head
c66d03d(one line,execution-duties.mdL21): the same set re-run, every family exit 0 exceptcheck:doc-formula-expressionsNOT MEASURED there (the gate does not scan.claude/**; exit 0 atcb2d8c4; CI runs it). The seat's ACCEPT (card comment 5827273568) and## Contract reviewPASS record (PR comment 5827276360) are recorded forc66d03d.维护者速读(草稿)
改了什么
把「同时在飞的上限」从「只数 dev」改成「数席位起的每一个子代理」:dev、复核、普查、只读全算,默认 3、天花板 5 不变;另加一条:分诊存量清理十张一组时只准备下一组,当前组你没确认之前不准备再下一组、不提前把所有批次都铺开。三处各改一行,文件行数一行没涨。
为什么改
今天总监席一次起了 8 个只读复核子代理加 1 个 dev,9 个同时用一个身份读 GitHub,被你叫停(「不要同时派发这么多」「小心封号」)。原规则写的是「dev 上限」,席位读成「复核不算」;封号警告都围绕写,席位读成「只读安全」。上一次封号之前的负载正是同一身份下的大量读。这三行把口子堵上,并按你的话「让 skills 车道立卡补上这条规则」落地。
风险与代价(含回滚)
纯文本、Tier S,不改任何脚本或门禁,不发布任何包(
skip-changeset)。代价是 filing-gate.md 删了一行写节奏(≥3 秒/笔、每小时 ≤40 笔)——它与 SKILL.md L94 逐字重复,规则仍在 SKILL.md 且由write-pace.mjs机械执行,所以删的是重复不是规则。回滚 = revert 这一个 commit,三文件回到原样。席位意见
(留空)
你要做的
读三行改动是否符合你的意思;若同意,由 skills 席按 Tier S 复核记录落地,不需要你点合并。
Follow-up note (card item ④ — a mechanical guard; NOT built here, and not recommended)
A live count of a seat's in-flight subagents is visible only to the harness (the
Agenttool andcreate_session), not to any repo script: apm:dispatchedcensus would count devs and miss every reviewer/census subagent, which is exactly the class this card closes. No cheap guard exists; the decision frame's default for a new gate is 「不加」, and nothing here recommends one.Acceptance notes / deviations
check:commit-card-trailers) refused it and the repo rule wins, so the unpushed tip was amended to the model-free pair before its first push (no published history rewritten; remote was still at the empty branch).check:doc-formula-expressionsprerequisite: the@objectstack/lintclosure (spec, sdui-parser, formula, lint) was built under the shared verify lock withOS_SKIP_DTS=1(the gate is a node script reading built JS, not.d.ts); held the lock 43 s.SKILL.md报告契约 L278–L285,triage-duties.mdL48/L71,filing-gate.mdL12 and its precedent lines,os-dev.mdrule 3; skills(pm-dispatch): the Claim comment carries the seat's GitHub account (Account: login = the card's assignee) beside the session id — maintainer 2026-09-25 「确认」「而且这个优先派发」 #20103 ownsSKILL.mdL305–L319 andexecution-duties.mdL53–L82. Neither region is touched here; skills(pm-dispatch / os-dev): file a finding only with measured reachability (checked by the finder at filing), fold same-family findings into a class-closure card, triage sends unproven ones to p3 — maintainer 「同意」 #20088 and skills(pm-dispatch): the Claim comment carries the seat's GitHub account (Account: login = the card's assignee) beside the session id — maintainer 2026-09-25 「确认」「而且这个优先派发」 #20103 remain open and are not addressed by this PR. Whichever PR lands later mergesorigin/mainfirst and re-runscheck:pm-skill-ratchet.Generated by Claude Code