Skip to content

.claude: allow the relay's landing strokes in settings.json; landing-operations names the direct invocation - #23442

Merged
objectstack-fleet[bot] merged 2 commits into
mainfrom
claude/issue-23432-relay-landing-allow-rule
Oct 14, 2026
Merged

objectstack-fleet[bot] merged 2 commits into
mainfrom
claude/issue-23432-relay-landing-allow-rule

Conversation

@objectstack-fleet

@objectstack-fleet objectstack-fleet Bot commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #23432
Clause-②: no

Adds the fleet-write relay's entry point to the repository's Claude Code permission allow-list, so a seat runs the Tier S landing strokes (pr_ready + automerge_enable) without a permission prompt. The landing reference now names the direct invocation. The card closes on landing (ruling 6164613078 returned it to pm:dispatched; the seat records the post-landing live proof on the closed card).

The two allow entries

.claude/settings.json, permissions.allow. Both lines go directly after "Bash(node scripts/pm/label-write.mjs *)", plain first and then --use-env-proxy, the pair order the close-cards / issue-create / issue-transfer pairs already use. Nothing else in the file moves (+2/-0, JSON parses).

"Bash(node scripts/pm/fleet-write/dispatch.mjs *)",
"Bash(node --use-env-proxy scripts/pm/fleet-write/dispatch.mjs *)",

The reference line, before and after

.claude/skills/pm-dispatch/references/landing-operations.md has ratchet ceiling 101 and is 101 lines both before and after (+2/-2).

Before (line 51):

- 绿即经中继 op `pr_ready` + `automerge_enable` 落地,拼写见 `rest-channel.md`;未绿按阶梯重挂定点。

After (line 51 unchanged; lines 52-53 new, 119 and 95 bytes):

- 绿即经中继 op `pr_ready` + `automerge_enable` 落地,拼写见 `rest-channel.md`;未绿按阶梯重挂定点。
- 直敲 `node scripts/pm/fleet-write/dispatch.mjs --repo OWNER/NAME --actions-file F`,⛔ 套壳:许可逐字匹配。
- 写节流拒(exit 10) ⇒ 待 `node scripts/pm/write-pace.mjs --status` 现空槽再重试。

The two command spans alone are 118 bytes, so the sentence cannot fit one 120-byte line. Two restatements are deleted to pay for the two new lines, so the ceiling is not raised:

- 卡以 completed 关闭且带 `Adopts:` 行 ⇒ 同一动作在所指 fork PR 贴致谢与落地链接并关闭它。      (was line 69)
- auto-merge 由 PM 挂,dev 永不碰。                                                              (was line 96)
  • Line 69 restates external-contributions.md:14, which states the same close in the same act, with the same thanks and landing link. Line 7 of this file already routes every fork PR to that reference, and that reference's back-pointer names line 7, not line 69.
  • Line 96 restates line 95 (the PM arms auto-merge), plus the dev agent's own rule 4 in os-dev.md (the dev never merges). Its dev-facing half addresses a reader who never opens this seat-only file.
  • No gate pins either line: a git grep over scripts/ and .github/ finds no hit.

Why the invocation must be direct

A Bash(...) allow rule matches the command as typed: the literal prefix before the rule's glob. rest-channel.md:38 states the same for the curl rules, and rest-channel.md:13 records that assignment and cd ... && prefixes fall to the classifier. Any wrapper in front makes the typed command start with something other than node scripts/pm/fleet-write/dispatch.mjs: a bash -c shell, with-fleet.sh --, or a scratchpad pacing script. The rule then never matches, and the stroke goes back to the classifier that refused these strokes as "Self-Approval" and "Merge Without Review".

The write-pace refusal is exit 10: EXIT_WRITE_PACE_REFUSED in write-pace.mjs, which dispatch.mjs reports as "throttle refused". It is the one refusal the seat retries itself, once write-pace.mjs --status shows a free slot, instead of wrapping the call in its own pacing loop.

Scope: the glob admits every op in the relay's closed table (fleet-write/ops.mjs), not only the two landing ops. The director seat's reading on the card (comment 6164270805) chose the carded glob. validate.mjs, the write pace and the queue's governed-surface guard stay the gates, the same shape that already covers post-stamped, label-write, close-cards, issue-create and issue-transfer.

维护者速读(草稿)

改了什么: .claude/settings.json 的许可清单加两条规则(普通写法与 --use-env-proxy 写法各一),允许席位会话不经弹窗直接运行舰队写中继 scripts/pm/fleet-write/dispatch.mjs。landing-operations.md 写明两件事:落地笔直接敲这条命令、前面不套壳;写节流拒(exit 10)后等 --status 显示有空槽再重试。为守住该文件 101 行上限,同时删掉两条在别处已有的重复规则。

为什么改: Tier S 落地(pr_ready + automerge_enable)要经这条中继命令,而会话权限分类器曾把它拒为 "Self-Approval" 与 "Merge Without Review",席位无法按登记册自己落地。这是你在卡上要求的改动。本 PR 由 dev 在你明确授权后编写:第一轮 dev 遇分类器以 Self-Modification 拒绝,随即停手并回退未提交的改动;之后你在席位会话中授权,原话(经席位转述):「我去掉了 auto,你现在可以改吗」。dev 据此重做了同一份已备好的 diff。

风险与代价(含回滚): 规则用 * 通配,放行的是中继闭合 op 表里的全部操作(开 PR、改卡、转卡、白名单内的 workflow_dispatch 等),不只落地两步。把关的仍是三道:中继自己的 validate.mjs、写节流 write-pace、合并队列的受管面守卫。没有达档复核记录或你的批准,受管面 PR 仍进不了队列。回滚:revert 本 PR 即删掉两条规则,落地回到每次弹窗。

席位意见(留空):

你要做的: 本 PR 自己的落地需要你 Approve 一次,规则落地后 Tier S 由席位按登记册落地。

Acceptance notes

All readings below are at head 8e5999ccd, on base origin/main 04a314873.

  • node -e "JSON.parse(require('fs').readFileSync('.claude/settings.json','utf8'))": exit 0. git diff origin/main --stat: settings +2/-0; the reference 4 lines changed, +2/-2, 101 lines.
  • pnpm -s check:pm-skill-ratchet: exit 0. Its reading: landing-operations.md is 101 lines (ceiling 101; headroom 0).
  • pnpm -s check:pm-skill-id-lint: exit 0, 87 file(s) clean.
  • pnpm -s check:pm-governed-prose: exit 0.
  • pnpm -s check:nul-bytes: exit 0, no raw ASCII control bytes.
  • pnpm -s check:skill-frame-sync: exit 0.
  • node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack derived 18 families. All were run, and the record carries exit codes. --ran reports: 18 derived, 18 run, 0 NOT-MEASURED, 0 UNRUN (a DERIVED zero). One family, @objectstack/lint check:doc-formula-expressions, first exited 3 with PREREQUISITE NOT MET (formula and lint not built, nothing measured). After turbo run build --filter=@objectstack/formula --filter=@objectstack/lint under the verify lock (VERDICT command-exit 0), it exited 0.
  • node scripts/pm/check-governed-merges.mjs --test .claude/settings.json .claude/skills/pm-dispatch/references/landing-operations.md: exit 3, which is the GOVERNED verdict on --test. Both paths fall under .claude/**, so the PR is Tier S, governed whole. It stays a draft, and the dev never readies, queues, arms or approves it.
  • Changeset: no package ships .claude/**, so skip-changeset is owed. The dev applies no labels in this order, so Check Changeset is expected red until the seat applies the label.
  • Deviation: the first line is Part of, not Fixes. The card carries needs-user-decision, and the dev protocol never writes a closing keyword against a card in the decision box. The card's live-proof acceptance item also stays open after merge. Once the ruling act clears the label, the seat may edit the first line to Fixes.
  • Deviation: the PR has no assignee. The card's assignee is empty since the seat's Release (comment 6164270805), and the PR's assignee mirrors the card's.
  • Out of scope, noted and not filed (no carrier): landing-operations.md:59 says 落地前检三条, while contract-review.md:32 says 落地前检两条.

Generated by Claude Code

…the direct invocation

settings.json permissions.allow gains the fleet-write relay entry point
(plain and --use-env-proxy), beside the other scripts/pm write tools, so a
seat can run the pr_ready + automerge_enable landing strokes without a
prompt. landing-operations.md names the direct invocation (no wrapper in
front: the allow rule matches the command as typed) and the write-pace
retry; two restatements (the Adopts close, already in
external-contributions.md, and the D-section auto-merge line, already in the
line above it) pay for the two lines, so the file stays at its ceiling.

Claude-Session: https://claude.ai/code/session_01LqNgdPZB2Jnr5HpGbaqLeB
Co-authored-by: Claude <noreply@anthropic.com>
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

维护者速读(终稿)· PR #23442 · 席位已对照 diff 逐行校正,2026-10-14T08:57Z

改了什么:.claude/settings.json 的 permissions.allow 加两条,紧跟 label-write 那对之后:Bash(node scripts/pm/fleet-write/dispatch.mjs *) 和它的 --use-env-proxy 变体(+2/−0,JSON 可解析,别处不动)。landing-operations.md(101 行顶格,净零)第 51 行后加两行:落地笔画直敲 node scripts/pm/fleet-write/dispatch.mjs --repo … --actions-file …,前面不套壳(许可按命令原样逐字匹配);写入限速拒绝(exit 10)等 write-pace --status 有空槽再重试。删两处重述:旧 69 行(Adopts: 关卡致谢,external-contributions.md:14 已有,第 7 行已指过去)和旧 96 行(「auto-merge 由 PM 挂,dev 永不碰」,重述 95 行与 os-dev 自己的规则 4)。2 文件 +4/−2。

为什么改:你的话:「给 Bash 加一条许可规则,允许 scripts/pm/fleet-write/dispatch.mjs 的落地写入(pr_ready / automerge_enable),以后 Tier S 的 PR 我就能按登记册自己落地」「这个你应该派卡开发」。本会话的 auto 分类器先后以「Self-Approval」「Merge Without Review」拒了 #23417、#23389 的中继落地笔画,又以「Self-Modification」拒了 agent 自改许可清单;你关掉 auto 并授权(「我去掉了 auto,你现在可以改吗」「我授权你执行相关所有的高风险修改」)后,开发按备好的 diff 逐字重跑,权限层放行。

风险与代价(含回滚):这条许可匹配整个中继脚本,覆盖它封闭 op 表里的全部写入(评论、标签、建卡、开 PR、入队、转移、限定的 workflow_dispatch),和现有 post-stamped / label-write / close-cards / issue-create 规则同一形状;闸门仍是中继自己的 op 校验、expected_head_sha、写入限速,以及合并队列上的受管守卫(受管 PR 仍需同档记录或你的 Approve)。不进 CI。回滚:revert 本 PR。本 PR 自己是第一张按新规则落地的:规则随合并生效,席位用中继直接入队。

席位意见:建议落地。两轮都在认领面内;18 个派生门禁族全跑全绿,五个具名检查绿,受管预检读 Tier S。一处面外小漂移(landing-operations.md:59 写「检三条」而 contract-review.md:32 写「两条」)记在卡上,未立卡。

你要做的:无。

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: d56ad594dd95e592bb6609bcf796fca8a9799f76
Local-runs: none

PR #23442, card #23432 (ruling 6164613078, letter A on both questions, the maintainer's authorisation quoted there). Governed by path: .claude/settings.json and .claude/skills/pm-dispatch/references/landing-operations.md (the rules face), so the review is owed at the contract tier and is served in-seat by the director seat (summon #37), which also dispatched the card, 2026-10-14T09:01Z. The head is d56ad594dd: 8e5999ccd (the change) with main a7a135dc2 merged by the relay (clean, disjoint files). The PR's own diff is 2 files, +4/−2. Read: the whole diff, the card, the ruling and the seat's reading 6164270805, the two dev reports (6164237929, the round-2 report), the claim 6164671367, the 终稿 6164705535, the ACCEPT 6164711824, the current .claude/settings.json on main, and the head's check-runs.

① Derived judgments

  1. The two allow entries. "Bash(node scripts/pm/fleet-write/dispatch.mjs *)" and "Bash(node --use-env-proxy scripts/pm/fleet-write/dispatch.mjs *)", inserted directly after "Bash(node scripts/pm/label-write.mjs *)", the plain-then-proxy order the close-cards / issue-create / issue-transfer pairs use; valid JSON; nothing else in the file moves. The shape is the one the file already grants to the fleet's other write tools (post-stamped, label-write, close-cards, issue-create, issue-transfer) and to the curl ccr/ready_for_review and ccr/auto_merge endpoints, so the entry closes a gap rather than opening a new class of write: every stroke still goes through fleet-write/validate.mjs (closed op table, expected_head_sha on pr_update_branch), write-pace.mjs, and the merge queue's check-governed-queue-guard for a governed PR. The glob admits every op of that table (the dev's scope question), which the ruling kept knowingly. Correct.
  2. The reference lines. Line 51 unchanged; lines 52–53 new: 直敲 the relay with no wrapper in front (a Bash(...) rule matches the command as typed, which rest-channel.md:13 and :38 already record for the curl rules), and the exit-10 write-pace refusal retried after write-pace.mjs --status shows a slot (EXIT_WRITE_PACE_REFUSED in write-pace.mjs, the one refusal a seat retries itself). 119 and 95 bytes, no issue number. Net zero at the 101-line ceiling paid by deleting old line 69 (the Adopts: close, stated in full at external-contributions.md:14, to which line 7 routes every fork PR) and old line 96 (the PM arms auto-merge and the dev never does: line 95 says the first; os-dev.md says the second twice, at :41 「回退他人的操作(尤其 ready 翻转)永不轮到你」 and at :61, where the dev's four writes are git push, pr_create as a draft, label-write and the report, no landing stroke among them). I read external-contributions.md:14 and os-dev.md on main: both rules survive. Correct.
  3. The authorship question. Round 1 stopped at the session's self-modification refusal, reverted, routed around nothing; the maintainer switched the auto-mode classifier off and authorised the change in their own words (quoted in the ruling); round 2 re-ran the prepared diff byte-exact and the permission layer allowed it. The authorisation is the maintainer's, recorded on the card, not an agent's. Correct.
  4. Gates on the head: 41 completed: 29 success, 12 skipped (Auto Label, Build Core, Build Docs, Check Changeset, Check PR Size, Console Pin Gate, Dogfood Regression Gate (N/3), Dogfood Verify CLI, Packed-tarball smoke (opt-in), Temporal Conformance (live PG + MySQL), Test Core (N/6)), 0 red, none running; Check Changeset (with skip-changeset), Governed Surface Queue Guard, Lint · PM dispatch-gates, Lint · repo & tooling gates, Type Check · workspace and TypeScript Type Check among the green. The PR body records, on 8e5999ccd: JSON parse exit 0; ratchet 101/101, id-lint, governed-prose, nul-bytes, frame-sync exit 0; the derived union 18/18 with --ran reconciled; check-governed-merges --test → GOVERNED Tier S. Not re-run here. The red Check Changeset on 8e5999ccd ran before skip-changeset was hung and is green on this head.
  5. The 速读 (终稿 6164705535) is true of this head.

② Semver level

No package's files[] ships .claude/**; skip-changeset is hung. Clause-②: no is right: no published schema and no public door moves; the review is owed by the rules face alone.

③ Boundary flags

The dev raised two open questions in round 1 (authorship; the glob's scope), both ruled A (6164613078); round 2 raised none. Deviations accepted in the ACCEPT (Part of → Fixes by the seat; no assignee on the PR; round 2 run on the seat's message before the ruling act was on the card). Out of scope, noted on the card, carrier none: landing-operations.md:59 「检三条」 vs contract-review.md:32 「检两条」. No repository, app/platform or published-contract boundary is crossed. NOT MEASURED locally: nothing; the record is read-only.

Implemented-by: claude/issue-23432-relay-landing-allow-rule
Reviewed-by: session_01LqNgdPZB2Jnr5HpGbaqLeB

VERDICT: PASS

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review October 14, 2026 09:02
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Oct 14, 2026
@github-actions

Copy link
Copy Markdown
Contributor

⛔ merge queue 构建失败 — 先分诊,再决定要不要重排

队列构建 38539409668 红了。队列跑的是全量套件(PR 侧 CI 只跑 affected 子集),
所以失败的测试可能在本 PR 没碰过的包里 —— 那不是重排能修的。每次盲目重排都会让排在后面的所有 PR 重建一轮。

分类:failure —— 按下面的日志分诊。

失败的 job(日志抽取,best effort):

  • Build Core — 失败步骤: Build packages (excluding docs)(日志不可读,点进 job 看)

↳ 失败原因 是判读的关键:超时(Test timed out in … / Hook timed out in …)多半是负载/时序,不是本 PR 的回归;
断言(AssertionError: …)才指向真实的行为改变。两者的 FAIL 行长得一模一样,只有这一行能区分。

⚠️ 断言这一侧有一类例外,判据是断言在测什么,不是它是不是 AssertionError。 断言的对象是产品行为(一个值、一个形状、一次拒收)⇒ 照上面读:真实的行为改变,去查,⛔ 不要重排掉;
断言的对象是这次实验自身的有效性前提(跑完的耗时、负载下的先后、任何只在时间预算内才成立的条件)⇒ 它跟超时是同一类,同样对负载敏感,重排一次是合法的判别手段。
识别是机械的:断言的消息或它比较的值本身点名了一段时长、一个时间戳、一个耗时计数。实测过的一对 —— AssertionError: SecurityPlugin.init() ran: expected false to be true 测的是产品行为(真回归);
AssertionError: this run took over a second, so second-precision stamps could have differed too: expected 1006 to be less than 1000 测的是实验前提:它守护的那条不变式当时是绿的,同一个 head 原样重排一次即成功。
穿着 AssertionError 外衣的时间测量,仍然是时间测量。(⛔ 这只改「怎么读一次红」,不改「哪些测试可以重排」——后者由别处管。)

跨 PR 相同签名(24h,按失败测试文件聚合):

  • ⚠️ 本次没有可用的聚合签名(日志里没有能解析出测试文件名的 FAIL 行)—— 这不是「没有同签名的其他 PR」,是这一轮没测到。跨 PR 聚合本次不可用,请手工比对其他 PR 的同类评论。
  • ⚠️ 24h 评论账本没读完(超过 5 页仍未读到窗口尽头),所以上面的「不同 PR 数」是下界,不是全量。

历史信号:

  • 本 PR 过去 24h 无队列失败记录(首次)。
  • 过去 24h 队列共有 4 个失败构建(不含本次)。

分诊清单:

  1. 失败测试在本 PR 改动的包里 → 真回归,修 PR。
  2. 失败测试与本 PR 无关 → 看上面的「跨 PR 相同签名」;已有汇总 issue ⇒ flaky/环境问题实锤,去那张 issue 上谈,修好前重排只会再烧一轮全队列。
  3. 两者都不是 → 可能与同组 PR 语义冲突;等前面的 PR 落地或失败出队后再重排一次即可,不要连续重排。

Generated by Claude Code · merge-queue-triage workflow (#4859)

Merged via the queue into main with commit 61b1258 Oct 14, 2026
42 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/issue-23432-relay-landing-allow-rule branch October 14, 2026 09:22
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

1 participant