Repository navigation
docs(pm-dispatch): name objectstack-fleet[bot] as the write identity - #19890
Merged
Merged
Conversation
SKILL.md and references/filing-gate.md still told a seat to write as claude[bot], the REST-proxy installation identity. AGENTS.md is the authority: every GitHub write leaves through scripts/pm/ as objectstack-fleet[bot], behind the shared write gate. Both lines now say so, in place, keeping each file's line count and each line under the ratchet's 120-byte cap. The pacing half of the SKILL.md line is unchanged. Claude-Session: https://claude.ai/code/session_01X7HwfPLpQtCixDMrRGkSbe Co-authored-by: Claude <noreply@anthropic.com>
This was referenced Sep 23, 2026
os-zhuang
approved these changes
Sep 24, 2026
os-zhuang
marked this pull request as ready for review
September 24, 2026 15:12
os-zhuang
enabled auto-merge
September 24, 2026 15:13
akarma-synetal
pushed a commit
to akarma-synetal/framework
that referenced
this pull request
Sep 28, 2026
…s card (objectstack-ai#19895) Fixes objectstack-ai#19883 Clause-②: no ## 维护者速读(草稿) **改了什么**:三份 PM 协议细则文件,共 +5 / −3 行。① 采纳了 fork PR 的卡,正文恒带一行行首 `Adopts: #M`(M = 那个 fork PR 的号),立卡那一笔就写;② 落地收口清单(确认 MERGED、给卡收口的那一笔)加一行:卡带这一行,就在同一动作里给 fork PR 贴致谢 + 落地链接并关闭它;需求被拒(卡关 not_planned)时,关卡那一笔同样贴致谢与谢绝理由并关闭;③ 分诊席每次读的职责文件加一行:每次 fire 扫开着的 fork PR,没卡就立卡,卡已关而 fork PR 还开着就补关。两份有行数上限的文件各加一行、各退一行同文件里已原样写着的重复内容,上限不动。 **为什么改**:维护者原话「这种pr应该写个评论直接关闭。」「"这种 PR"都应该这样处理,开一个 skills 卡片」。外部贡献者的 PR 在需求已由内部 PR 落地后被晾了两天没人关:这条规则只写在一份落地时没有席位会读的文件里,落地收口清单里没有这一步,卡上指向 fork PR 的只是一段散文。另外核实发现,「分诊每次 fire 扫 fork PR」这一步本身也不在分诊席每次读的职责文件里,只在那份没人读的文件里。 **风险与代价(含回滚)**:纯文本改动:不加门禁、不加脚本、不加巡查行、不动行数上限。代价是分诊每次 fire 多一次「列出开着的 PR」的读取(当前 23 个开放 PR,0 个 fork),以及卡正文多一种行首拼写 `Adopts:`。退掉的两行,其每一句在同一文件里都还在(逐条对照见下文表格)。回滚 = revert 这一个 squash commit。 **席位意见**: **你要做的**:无需点击。本 PR 只碰 `.claude/**`,属 Tier S,由 skills 席在席内契约复核 PASS 后走队列落地。若不希望分诊每次 fire 都扫 fork PR(只保留落地那一笔),在本 PR 评论一句即可,删掉 triage 那一行。 ## What this PR does Three files under `.claude/skills/pm-dispatch/references/`, +5 / −3. 1. **`external-contributions.md`** (the fork-PR playbook) - Step ①: the card behind a fork PR always carries a line-start `Adopts: #M` (M = the fork PR's number). It is written in the stroke that files the card, or that attaches the fork PR to a card that already exists. The landing closeout and the triage catch-up read only this line. - Step ③: the line "after the internal PR lands, close the fork PR with thanks and the landing link" becomes: the stroke that closes the card also closes the fork PR its `Adopts:` line names. On `completed` the closing comment carries thanks and the landing link. On `not_planned` it carries thanks and the reason the need was declined. The declined case had no text before. - The sentence that limits a seat's comments on a fork PR is rewritten, not worked around. It used to say "only these two kinds" after naming review comments and the close. It now names them: apart from step ①'s fixed comment, a seat writes review comments and the closing comment, and nothing else. The declined form is the closing comment's second form, not a third kind. 2. **`landing-operations.md` §B, the MERGED closeout**, the home of "the landing stroke": one line directly after the `Part of` / `Fixes` closeout line. A card closing `completed` with an `Adopts:` line means the same action posts thanks and the landing link on that fork PR and closes it. 3. **`triage-duties.md`**: one line at the end of the backlog-sweep block. Every fire also scans open fork PRs. No card: file one per step ①. Card already closed: close the fork PR per step ③. ## Why this shape — the four axes The card offers two candidates, A (at the landing step) and B (in the triage sweep), and leaves the shape to the seat. `SKILL.md`'s order for a failure fix is: remove the construct that allows the error, make the right form the only spelling, and only then add a check. - **Remove the construct.** The miss was allowed because the close was a separate, later act. It was written only in `external-contributions.md`, and no seat reads that file at MERGED. The landing seat reads `landing-operations.md`, whose closeout list had no fork-PR item. The card named its fork PR only in free prose: an "Adoption of PR" section and a promise to close it "in the landing stroke". Shape A removes the construct: the close is now an item of the closeout list itself, in the same action that closes the card. - **One spelling.** `Adopts: #M`, line-start and undecorated, the same form as `Blocked-by:`. It has three named readers: the landing closeout, the triage catch-up, and step ①'s "does this fork PR already have a card". Measured on the one case: the fork PR's timeline carries **10** cross-references from other issues and PRs, one of them its card. The line is what picks the card out of the ten. - **Check.** None is added: no gate, no half-state row, no ratchet. Neither ruling sentence names one, and a new gate defaults to no. B is one prose duty line on a scan the triage seat already owes by step ①. It is not a patrol row. - **Why B at all, with A in place.** The declined case has no other reader. A `not_planned` close happens in several seats' flows: a triage first-touch close, a decision-box answer, a falsified premise. The one file every seat reads is `SKILL.md`, which sits at 319 / 319 and is held by PR objectstack-ai#19890. The triage fire is the one reader that sees every closed card's fork PR, and it is also the backstop if a landing stroke misses one. - **Real business need (measured).** Fork PRs are rare: 1 among the 500 most recent closed PRs (created 2026-09-17T18:37Z .. 2026-09-23T14:41Z). That one is the fork PR that was missed. 0 of 23 open PRs are forks at 2026-09-23T15:29:57Z. The maintainer's word covers every such PR, and the one miss cost an outside contributor two days of silence. - **Startup focus.** +2 lines net across the corpus. Both ceilinged files stay at their ceilings: `landing-operations.md` 101 / 101, `triage-duties.md` 120 / 120. `external-contributions.md` goes 16 → 18; that file is not in the ceiling map. - **Rejected alternative.** Teach `scripts/pm/close-cards.mjs` to read `Adopts:` and refuse a card close that does not also close the fork PR. That is structurally the strongest shape, but it is a new mechanical check that no maintainer word names, and it is outside this card's claimed file surface. ## Premise check, on `origin/main` at `dabf8d7` - **Confirmed.** The rule's only carrier was `external-contributions.md` (the old line 13), as prose. Fork PR objectstack-ai#19342 stayed open from the internal landing to 2026-09-23T14:42:37Z. Card objectstack-ai#19489 is `closed` / `completed` (2026-09-21T10:32:18Z). PR objectstack-ai#19534 merged 2026-09-21T10:32:16Z as `2aac821a8c`. - **Correction to one reading in the dispatch.** `triage-duties.md` had **no** fork-PR scan line. `git grep -c -i fork dabf8d7 -- …/triage-duties.md` exits 1 (zero hits). The control on the same tree and term, `…/external-contributions.md`, hits 8 and exits 0. Step ①'s scan lived only in `external-contributions.md`, and `SKILL.md`'s phase-file index names no reader for that file. The pre-relocation `SKILL.md` (`f151ef2^`) pointed at it only from the enqueue-and-landing section. So candidate B's premise, "step ① already scans open PRs on every fire", held on paper only. The new triage line is what gives step ① a reader. - The dispatch was cut at `e9eb2244d5`; this worktree starts at `dabf8d7`. `git diff --stat e9eb224 dabf8d7 -- .claude/skills/pm-dispatch/` is empty. ## Retired lines: every clause is still stated in the same file | retired | where each clause still stands | |---|---| | `landing-operations.md` old :19, "follow to MERGED; after enqueue the watch belongs to the lane PM's landing window: every round read the queue branch and `origin/main`" | §B heading 「跟到 MERGED 为止;入队后的看护归车道 PM 落地窗口」 and §B 「确认 MERGED 要两个读数:每轮同时读队列分支与 `origin/main`。」 | | `triage-duties.md` old :8, "the tool-loading discipline binds only the triage fresh session's opening; execution seats and devs are not bound" | line 3: the file is the triage seat's alone. Line 6 「fire 开局只按名加载…判定本轮有活才加载其余」 and line 7 「⛔ 分诊 fresh session 开局不做泛关键词 ToolSearch」 are both scoped to the opening already. | Neither retired line is quoted anywhere else in the tree (`git grep` over both texts: the only hits are the lines themselves). ## Gates, on `4a3242c` `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` derives 18 families from the 3 changed paths, merge base `dabf8d795`. All 18 were run, each exit captured before any pipe. `--ran` verdict: `✓ dispatch-gates --ran: 18 derived famil(ies) accounted for — 18 run, 0 NOT-MEASURED (a DERIVED zero — all 18 recorded an exit code and none of them is 3).` - `pnpm check:pm-skill-ratchet`: exit 0. `landing-operations.md is 101 lines (ceiling 101; headroom 0)`; `triage-duties.md is 120 lines (ceiling 120; headroom 0)`. Every changed line is 120 bytes or less. - `pnpm check:pm-skill-id-lint`: exit 0, `34 file(s) clean (pattern /#[0-9]{3,}/g)`. No rule line cites a tracker number. - `pnpm check:pm-governed-prose` (named by the dispatch, outside the derivation): exit 0. - `pnpm check:nul-bytes`: exit 0, `no raw ASCII control bytes`. - `pnpm check:skill-frame-sync`: exit 0. - `pnpm check:pm-half-states`: exit 0, `4912 cases pass`. - `pnpm check:pm-governed-merges`: exit 0. - `pnpm --filter @objectstack/lint run check:doc-formula-expressions`: the first run exited 3 (PREREQUISITE NOT MET, `@objectstack/formula` and `@objectstack/lint` not built). After `turbo run build` for those two packages under the verify lock (VERDICT command-exit 0), the re-run exited 0. - The other 10 derived families (closing-keyword parity ×2, comment-mask corpus, harness-current, agent-test spelling, cross-package test inputs, doc authoring, driver-memory census, gitlink, refd-timer probe, watch-hint literal): exit 0. No package is touched, so there is no build closure and no package test to run. Nothing here is published (`.claude/**`), so this PR carries `skip-changeset`. ## Acceptance notes - `SKILL.md`'s phase-file index names no reader for `references/external-contributions.md`. After this PR both executing seats' files point at it (`landing-operations.md` line 7, `triage-duties.md`), so no index row is owed. Carrier: none. - `references/external-contributions.md` is not in the line ratchet's ceiling map, while the other `pm-dispatch` reference files are. Stated as a fact, not a gap. Carrier: none. - A fork-PR card that closes as `duplicate` is not covered: its `Adopts:` line would need to move to the surviving card. There are 0 instances. Carrier: none. - `check-half-states.mjs`'s H65 message quotes `triage-duties.md` as 「选层按 fire 时刻,⛔ 不用计数器;简报写明本轮跑的层」, but the file says 「选层按 fire 时刻 ⛔ 不用计数器,简报写明层」. This is report-only message text. Carrier: none. --- _Generated by [Claude Code](https://claude.ai/code/session_01A22sUB3mUWs6M36VgfijBq)_ 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 #19881
Clause-②: no
What changed
Two lines of the pm-dispatch skill still named
claude[bot]as the write identity.claude[bot]is the REST-proxy installation identity, and it has been superseded.AGENTS.mdis the authority: "Every GitHub write leaves throughscripts/pm/, asobjectstack-fleet[bot], behind the shared write gate." Both lines now say that, edited in place:Ruling (verbatim, untranslated):
Why the lines read the way they do
check-skill-line-ratchetholds both files at zero line headroom: SKILL.md is at 319 of 319 lines and filing-gate.md is at 58 of 58. It also caps every line at 120 bytes. The old SKILL.md:94 was 119 bytes, andobjectstack-fleet[bot]is 11 bytes longer thanclaude[bot].scripts/pm/doors (issue-create,label-write,post-stamped,close-cards,with-fleet.sh), because they would not fit under the cap either. The AGENTS.md pointer names them, and filing-gate.md:31 namesscripts/pm/.claude(bot). It is untouched. The optional one-line note under it was not added: the file has zero line headroom, and line 31, now 119 bytes, has no room to carry the note.Lines re-read and left unchanged
references/platform-readings.md:130and:132are dated measurements of the container's REST-proxy token classes. They are not a write rule.references/platform-readings.md:136tells a seat not to assume a write is signed asclaude[bot]. That agrees with the new identity. It is not an instruction to write asclaude[bot].references/filing-gate.md:32-33say to read backuser.typeon a fire's first write, and to stop filing if it readsUser. A write through the doors reads backBot, so aUserreadback still flags a write that went around them. These lines are not an instruction to write asclaude[bot].At
1be1a7d, the acceptance grepgit grep -n 'claude\[bot\]' -- .claude/skills/pm-dispatchhits exactly three lines:platform-readings.md:130,:132and:136. That is the list above, and none of them prescribes a write identity.Verification (all at
1be1a7d).claude/skills/pm-dispatch/SKILL.md.claude/skills/pm-dispatch/references/filing-gate.mdpnpm check:pm-skill-ratchetexited 0. Its readings:SKILL.md is 319 lines (ceiling 319; headroom 0)andfiling-gate.md is 58 lines (ceiling 58; headroom 0). The 120-byte line rule passed.pnpm check:pm-governed-proseexited 0:2 instruction surface(s) name all 6 registered governed surfaces.pnpm check:pm-skill-id-lintexited 0:34 file(s) clean.pnpm check:nul-bytesexited 0:no raw ASCII control bytes.node scripts/pm/dispatch-gates.mjs --commands(with no paths passed) derived 20 commands. All 20 exited 0.pnpm --filter @objectstack/lint run check:doc-formula-expressionsfirst exited 3 because a prerequisite was not built. It exited 0 afterturbo run build --filter=@objectstack/formula --filter=@objectstack/lint.--ranreconciliation reported20 derived famil(ies) accounted for — 20 run, 0 NOT-MEASURED (a DERIVED zero).pnpm check:pm-settings-deny-rosteralso exited 0. The derivation flagged its roster as living under.claude/.check:commit-card-trailerspassed.Acceptance notes
.claude/**-only diff, which is the fast lane and publishes nothing, so no changeset is written.Check Changesetstays red until theskip-changesetlabel is on this PR. This dispatch's write budget has no label write, so the label is not applied here and is owed by the seat.GOVERNED_SURFACESinscripts/pm/check-governed-merges.mjs) rows.claude/**as Tier S. The PR stays draft either way.维护者速读(草稿)
改了什么:pm-dispatch 技能里有两行把 GitHub 写身份写成
claude[bot],现在都改成objectstack-fleet[bot],并注明以 AGENTS.md 为准。两行是SKILL.md:94和references/filing-gate.md:31。只改这两行,两个文件的行数都不变。为什么改:AGENTS.md 规定,所有 GitHub 写都经
scripts/pm/以objectstack-fleet[bot]身份发出。技能文档还写着旧身份,只读技能的席位会被引向错误身份。这既与 AGENTS.md 矛盾,也与同一技能的rest-channel.md矛盾。本卡按您的原话裁决直派。风险与代价(含回滚):
SKILL.md:94删去了“⛔ 不走用户令牌”半句。这个意思在同文件第 92 行已经有了,filing-gate.md:31也仍然保留,规则没有丢。席位意见:
你要做的:
.claude/**属 Tier S,由席位的达档复核 PASS 记录放行落地,不需要您点批准。skip-changeset标签由席位补挂。Generated by Claude Code