Repository navigation
Commit 9a56630
docs(pm-dispatch): three write-side lines of the REST channel table, and the pipeline trap in post-stamped (#18391)
Fixes #18337
Fixes #18339
Fixes #18360
Three write-side lines of
`.claude/skills/pm-dispatch/references/rest-channel.md` — the table a
seat opens before hand-rolling a REST write — plus the same pipeline
trap in the header of `scripts/pm/post-stamped.mjs`, which is the file
opened before that idiom is typed. One commit per card.
The file sits at its ratchet ceiling with zero headroom (82 / 82), so
the two added rules are paid for by two retired rows, each declared
below with the surviving home of every clause it carried. **82 lines
before, 82 lines after.** No re-wrap was used as currency, and
`references/platform-readings.md` is untouched.
## Per card
### #18337 — the pipeline-exit trap, beside the two tools it names
**Landing point (by content):** the write-side block, immediately after
the `label-write.mjs` row.
**Before:** no such line; the trap was written down only in one lane's
private Routine prompt.
**After (verbatim):**
```
- ⛔ `post-stamped`/`label-write` 永不接进管道再 `&&`:拒收读成 0;看尾先落文件或 `set -o pipefail`。
```
**Second half — the tool's own header.** `scripts/pm/post-stamped.mjs`
gains one section, `## ⛔ Never pipe this tool, then && the write that
follows`, which names the half-state shape (refused audit comment, label
landed anyway, card graded with nothing saying why), the
redirect-then-capture spelling, and `set -o pipefail`. It states the
shape rather than citing a card number, and it does not restate the
generic mechanism: that reading keeps its single home in
`references/platform-readings.md`.
**How this card reads independently:** both places carry the trap — the
write-side block (grep the table for `pipefail`: was 0, is 1) and the
tool header a seat opens before typing the idiom (`grep -c 'set -o
pipefail' scripts/pm/post-stamped.mjs`).
**Paid by:** retiring the write-side row
```
- 入队读 timeline `added_to_merge_queue`,落地读 `git rev-list --parents`;⛔ `auto_merge` 与回显都不作数。
```
Every clause of it survives, twice over: `added_to_merge_queue` is
already a judgment row in this same file's queue-routing block; `git
rev-list --parents` is a spelling this file's own 第三桶 block declares to
live in `platform-readings.md`, where it is written with its `-n1`; and
the auto_merge / echo-back unreliability is in `platform-readings.md`
twice plus this file's own queue-routing rule that the answer comes from
the attempted action and not from the attribute field. It is the row
this file's own line 「本表只指路,⛔ 不在两处各存一份」 refuses to keep.
### #18339 — the mandatory header, on the table seats consult
**Landing point (by content):** the write-side block, immediately after
the request-body line 「请求体走文件…或引号定界 heredoc」, which is the hook the card
names.
**Before:** the block carried zero mentions and zero cross-references of
the header (`content-type`, case-insensitive, over the whole table: 0
hits, with `GET` at 12 hits as the firing control).
**After (verbatim):**
```
- 每个写请求必带 `Content-Type: application/json`;缺头的 415 与判别式见配额段。
```
**How this card reads independently:** the reader path from the
write-side block to the rule is now **0 hops** — the rule is in the
block — and the reading it is measured from (the 415, and the
discriminator that tells a proxy refusal from a GitHub one) is **1
hop**, named rather than copied. Was ∞. The two `platform-readings.md`
rows are not copied and not edited; the pointer uses this table's
existing spelling for that section, which its own opening line and its
不可迁移 heading already use.
**Paid by:** retiring the reading beside it,
```
- 双引号内 shell 先展开反引号、`$(...)`、`$VAR`,请求尚未成形;只标题坏而正文完好即此形。
```
Both of its facts are in `platform-readings.md` verbatim: the backtick
expansion with the broken-title-intact-body symptom, and the
quoted-delimiter rule whose general form is 「请求体永不过会展开的 shell 上下文」,
which is what covers `$(...)` and `$VAR`. The prescription those bytes
explained — body via file or quoted heredoc, never an inline
double-quoted string, with both spellings — stays untouched on the line
above.
### #18360 — the direct-merge actor follows the token class, not the
session
**Landing point (by content):** the write-side block's direct-merge row.
**Before (verbatim):**
```
- 直合仓 `PUT .../pulls/{n}/merge`;actor 记通道令牌:REST 按会话为 `claude[bot]` 或用户,MCP 恒用户。
```
**After (verbatim):**
```
- 直合仓 `PUT .../pulls/{n}/merge`;actor 记令牌类,按账号非会话、逐写回读;见配额段,MCP 恒用户。
```
**How this card reads independently:** `grep -c '按会话' ` on the file is 0
(was 1, that row); the row now says the actor is the token class, bound
to the account and read back on each write; the fact-table rows landed
by #18359 are pointed at, not copied; `MCP 恒用户` stays, because it is
this table's own fact and has no other home. In place, 120 bytes, at the
cap the ratchet sets.
## Line budget
| | lines |
|:---|---:|
| `rest-channel.md` before | 82 |
| `rest-channel.md` after | 82 |
| ceiling | 82 |
Added 2 rules, retired 2 rows, re-keyed 1 row in place.
`scripts/pm/post-stamped.mjs` carries no ceiling (it is not in the
ratchet's CEILINGS map — checked, not assumed). Every touched line is
within the 120-byte cap; the two new rules measure 119 B and 98 B, the
re-keyed row 120 B.
## Gates
All 39 commands derived by `node scripts/pm/dispatch-gates.mjs
--commands --repo objectstack-ai/objectstack` against this branch's real
change set were run, exit code captured before any pipe. 38 of 39 are
green, including `pnpm check:pm-skill-ratchet` (its own verdict line:
`rest-channel.md is 82 lines (ceiling 82; headroom 0)`), `pnpm
check:pm-post-stamped` (233 cases), `pnpm check:nul-bytes`, `pnpm
check:doc-authoring`, `pnpm check:pm-governed-merges` and `pnpm
check:pm-skill-id-lint`. `pnpm --filter @objectstack/lint run
check:doc-formula-expressions` first exited 3, PREREQUISITE NOT MET
(unbuilt workspace packages, nothing measured); after `turbo run build
--filter=@objectstack/formula --filter=@objectstack/lint` it exits 0.
The remaining command, `pnpm check:pm-dispatch-gates` (a 430–450 s
battery), was still running when this PR was opened; its verdict is in
the dev report on #18337.
`node scripts/pm/check-governed-merges.mjs --test
.claude/skills/pm-dispatch/references/rest-channel.md` exits 3 —
GOVERNED, `.claude/**`. ⛔ No seat flips this ready, enqueues it or arms
auto-merge; it lands after the skills seat's contract-tier review.
## Acceptance notes
- Noted, not filed: nothing else in the write-side block was touched.
The `-d @file` flag and the quoted-heredoc delimiter spelling, the
shell-expansion prescription, and every ✓ channel row are unchanged.
- To file (out of scope here, `scripts/pm/check-half-states.mjs`): H64's
header quotes this same retired premise as its rationale — 「REST 按会话为
`claude[bot]` 或用户,MCP 恒用户」, sourced to `rest-channel.md`, with the
surrounding prose reading "the write identity follows the CHANNEL rather
than the account" and, further down, "the token class is handed to a
session at start rather than chosen at write time". The landed fact
table says the opposite in as many words: 「类按 Claude Code 账号定,⛔ 不按会话定」
and 「一会话内两次写之间可无席位动作地翻转」. The row's runtime message text carries the
same sourcing. Prose only, no enforcement change; this PR's claim names
`rest-channel.md` and `post-stamped.mjs` and nothing else, so it is
reported rather than fixed here. Dedup words: `H64 按会话` ·
`check-half-states token class` · `write identity follows the channel` ·
`session-handed token`.
## 维护者速读(草稿)
**改了什么** —— pm-dispatch 的 REST
通道对照表(席位手搓写请求前查的那张表)的写侧段,加了两条规则、改写了一条、退役了两条重复行;另外给
`scripts/pm/post-stamped.mjs` 的文件头加了一段管道陷阱说明。表的总行数没变(82 行,正好在棘轮天花板上)。
**为什么改** —— 三张 p3 卡,同一个形状:规则存在,但不在读者动手时会看的那张表上。① 把写脚本接进管道再
`&&`,管道退出码取末端,于是审计评论被拒、标签照落,卡上留下「改了标、没理由」;这条陷阱原先只写在某条车道的私有唤醒提示词里。② REST
写必带 `Content-Type: application/json`,缺了代理回 415、一个字节都不写 ——
规则写在事实表里,写侧段零提及,一个班次内六次独立踩中、四个端点,而失败长得像「别人并发把我的标签冲掉了」,会把一个加一个头就能修的问题误诊成分布式竞态。③
直合的 actor 那行还写着「按会话」,而事实表已经改成「按 Claude Code 账号」,并记录了一个会话内无人操作就翻转两次的实测。
**风险与代价(含回滚)** —— 纯文本面,无代码行为改动,无 changeset(`.claude/**` 与
`scripts/pm/**` 不发布)。代价是退役了两行:每一行的每个子句都在别处有家(逐条列在上面的 Paid by
里),这是天花板零余量下唯一合法的付账方式 —— 删内容,不是折行。若判定某条退役行不该退,回滚是一次 revert:三个 commit
逐卡独立,可以只回其中一个。
**席位意见** ——
**你要做的** —— 复核两处:① 两行退役是否同意(它们的存续副本是否真的够用);② 三条新/改写的行文字是否准确 —— 尤其 #18360
那行为了压进 120 字节,把「按 Claude Code
账号」压成「按账号」,完整拼写留在它指向的配额段。这是受管面(`.claude/**`),⛔ 不会有任何席位把它 ready 或入队。
---
_Generated by [Claude
Code](https://claude.ai/code/session_01Bz6hxDBqK62NP2W1LATvnt)_
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent 37af653 commit 9a56630
2 files changed
Lines changed: 21 additions & 3 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
36 | 36 | | |
37 | 37 | | |
38 | 38 | | |
| 39 | + | |
39 | 40 | | |
40 | 41 | | |
41 | 42 | | |
42 | | - | |
| 43 | + | |
43 | 44 | | |
44 | 45 | | |
45 | 46 | | |
| |||
49 | 50 | | |
50 | 51 | | |
51 | 52 | | |
52 | | - | |
53 | 53 | | |
54 | | - | |
| 54 | + | |
55 | 55 | | |
56 | 56 | | |
57 | 57 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
62 | 62 | | |
63 | 63 | | |
64 | 64 | | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
65 | 83 | | |
66 | 84 | | |
67 | 85 | | |
| |||
0 commit comments