Skip to content

docs(pm-dispatch): name objectstack-fleet[bot] as the write identity - #19890

Merged
os-zhuang merged 1 commit into
mainfrom
claude/lucid-turing-izrwob
Sep 24, 2026
Merged

os-zhuang merged 1 commit into
mainfrom
claude/lucid-turing-izrwob

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

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.md is the authority: "Every GitHub write leaves through scripts/pm/, as objectstack-fleet[bot], behind the shared write gate." Both lines now say that, edited in place:

 .claude/skills/pm-dispatch/SKILL.md:94
-- 写侧恒走 `claude[bot]` ⛔ 不走用户令牌;节奏 ≥3 秒/笔、每账号每小时 ≤40 笔,429 即停写。
+- 写侧恒为 `objectstack-fleet[bot]`(AGENTS.md);节奏 ≥3 秒/笔、每账号每小时 ≤40 笔,429 即停写。

 .claude/skills/pm-dispatch/references/filing-gate.md:31
-- 立卡、开 PR 与评论恒走 App 安装身份(`claude[bot]`),⛔ 不走席位用户令牌。
+- 立卡、开 PR 与评论恒经 `scripts/pm/` 为 `objectstack-fleet[bot]`(AGENTS.md),⛔ 不走席位用户令牌。

Ruling (verbatim, untranslated):

另外注意 pm-dispatch 技能文档里有一处过时:SKILL.md:94 和 references/filing-gate.md:31 还写着"写侧恒走 claude[bot]" 这个是错的,立卡修改
你可以直接派发修改

Why the lines read the way they do

  • check-skill-line-ratchet holds 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, and objectstack-fleet[bot] is 11 bytes longer than claude[bot].
  • The pacing half of SKILL.md:94 is 67 bytes and is kept byte-identical. With it in place, the identity, the user-token clause and an authority pointer cannot all fit: the shortest line that holds all three is 127 bytes.
  • So the new SKILL.md:94 keeps the identity and the AGENTS.md pointer, and drops the user-token clause. Nothing is lost:
    • SKILL.md:92 already says user accounts have exactly three uses, and none of them is a write.
    • filing-gate.md:31 still carries its own user-token prohibition for filing cards, opening PRs and commenting.
  • SKILL.md:94 does not list the 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 names scripts/pm/.
  • filing-gate.md:9 is a verbatim maintainer quote that names 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:130 and :132 are dated measurements of the container's REST-proxy token classes. They are not a write rule.
  • references/platform-readings.md:136 tells a seat not to assume a write is signed as claude[bot]. That agrees with the new identity. It is not an instruction to write as claude[bot].
  • references/filing-gate.md:32-33 say to read back user.type on a fire's first write, and to stop filing if it reads User. A write through the doors reads back Bot, so a User readback still flags a write that went around them. These lines are not an instruction to write as claude[bot].

At 1be1a7d, the acceptance grep git grep -n 'claude\[bot\]' -- .claude/skills/pm-dispatch hits exactly three lines: platform-readings.md:130, :132 and :136. That is the list above, and none of them prescribes a write identity.

Verification (all at 1be1a7d)

file lines before / after / ceiling edited line bytes before / after / cap
.claude/skills/pm-dispatch/SKILL.md 319 / 319 / 319 119 / 118 / 120
.claude/skills/pm-dispatch/references/filing-gate.md 58 / 58 / 58 97 / 119 / 120
  • pnpm check:pm-skill-ratchet exited 0. Its readings: SKILL.md is 319 lines (ceiling 319; headroom 0) and filing-gate.md is 58 lines (ceiling 58; headroom 0). The 120-byte line rule passed.
  • pnpm check:pm-governed-prose exited 0: 2 instruction surface(s) name all 6 registered governed surfaces.
  • pnpm check:pm-skill-id-lint exited 0: 34 file(s) clean.
  • pnpm check:nul-bytes exited 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-expressions first exited 3 because a prerequisite was not built. It exited 0 after turbo run build --filter=@objectstack/formula --filter=@objectstack/lint.
  • --ran reconciliation reported 20 derived famil(ies) accounted for — 20 run, 0 NOT-MEASURED (a DERIVED zero).
  • pnpm check:pm-settings-deny-roster also exited 0. The derivation flagged its roster as living under .claude/.
  • The pre-push check:commit-card-trailers passed.

Acceptance notes

  • Changeset: this is a .claude/**-only diff, which is the fast lane and publishes nothing, so no changeset is written. Check Changeset stays red until the skip-changeset label 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.
  • Landing tier: the dispatch described this diff as Tier H. The register (GOVERNED_SURFACES in scripts/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 矛盾。本卡按您的原话裁决直派。

风险与代价(含回滚):

  • 纯内部文档改动,不发布,不影响运行时。
  • 行棘轮规定每行不超过 120 字节,所以 SKILL.md:94 删去了“⛔ 不走用户令牌”半句。这个意思在同文件第 92 行已经有了,filing-gate.md:31 也仍然保留,规则没有丢。
  • 回滚就是 revert 本 PR 的单个提交。

席位意见:

你要做的:

  • 按登记册,.claude/** 属 Tier S,由席位的达档复核 PASS 记录放行落地,不需要您点批准。
  • 按派发,已请 os-zhuang、hotlong 复审;如果您想按 Tier H 处理,需要其中一人批准一次。
  • skip-changeset 标签由席位补挂。

Generated by Claude Code

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>
@github-actions github-actions Bot added size/xs documentation Improvements or additions to documentation labels Sep 23, 2026
@objectstack-fleet objectstack-fleet Bot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Sep 23, 2026
This was referenced Sep 23, 2026
@os-zhuang
os-zhuang marked this pull request as ready for review September 24, 2026 15:12
@os-zhuang
os-zhuang enabled auto-merge September 24, 2026 15:13
@os-zhuang
os-zhuang added this pull request to the merge queue Sep 24, 2026
Merged via the queue into main with commit ad6e234 Sep 24, 2026
31 of 32 checks passed
@os-zhuang
os-zhuang deleted the claude/lucid-turing-izrwob branch September 24, 2026 15:54
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>
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

2 participants