Skip to content

Commit 5b31fb9

Browse files
governance(AGENTS.md PD15): carve the fleet-write relay's refresh stroke out of the release.yml dispatch prohibition (#23436)
Fixes #23393 Clause-②: no Executes ruling **A** on #23193: ruling record `6160857949`, the maintainer's word verbatim 「23209 A」, on the options put in `6141962120`. #23193 remains open for PR #23209. #23177 remains open. **Governed, Tier H** (`AGENTS.md`). This PR stays a draft until an at-tier contract review and an authorized approval. Landing order per the ruling: this PR first, then PR #23209 merges `main`, is re-checked and lands. Only after that is ruling B item 5 on #23177 (`6139629628`) executable. Patch round 1 (`session_01B7mrh59UAGffd7s9asUfoY`, head `9b68a60e` to `e7712a44`) adds edit 2 below. That is the seat's answer B (card comment `6164269656`) to the report's open question. ## What changes Two edits to `AGENTS.md` Prime Directive 15. Nothing else in the file changes. **1. The reserved-act clause.** This is the shape option A put to the maintainer: "the reserved act becomes dispatching `release.yml` in any lane except the relay's ... refresh stroke (... `refresh_version_pr: true` alone)". - Before: ⛔ `workflow_dispatch`-ing `release.yml` or any other publish-capable workflow, - After: ⛔ `workflow_dispatch`-ing `release.yml` in any lane but the fleet-write relay's refresh stroke (`refresh_version_pr: true` alone), or any other publish-capable workflow, **2. The bold lead.** This aligns the lead with the amended list. - Before: no AI seat publishes, tags, cuts a Release, or triggers a release workflow, and none merges the Version Packages PR. - After: no AI seat publishes, tags, cuts a Release, or triggers a release, and none merges the Version Packages PR. - Why: ruling A adopts the rationale in `6141962120`, "one rule text that matches one mechanism". With only the clause amended, the lead still forbade what the amended list admits, because the relay's refresh stroke does trigger `release.yml`, which is a release workflow. That is the same contradiction that held PR #23209. The seat's answer (`6164269656`) treats aligning the lead as executing the ruling as given, not as a new decision. - Bound: the reserved-act list stays the definition. Every other `release.yml` lane and every other publish-capable workflow stays reserved there by name. **Proof that nothing else moved.** Against merge base `4f81f31526`, `git diff -w --word-diff` shows exactly two changes: - the lead's `release workflow,` becomes `release,`, so one word (`workflow`) is removed; - the clause `in any lane but the fleet-write relay's refresh stroke (refresh_version_pr: true alone),` is inserted. A whitespace-normalised whole-file comparison of `AGENTS.md` at base and at head `e7712a44` equals base with exactly those two edits applied. It answers `true`. Control: the same edits without the clause's trailing comma answer `false`. Lines 307-315 of the hunk are the forced re-flow of the paragraph at its own typeset width (118 B). The lead edit shortens line 302 in place and re-flows nothing. Every other reserved act stays word for word: - `changeset publish` / `pnpm run release`; - the version tag, the GitHub Release and the runtime image; - any other `release.yml` dispatch or input combination, and any other publish-capable workflow; - the `release` environment approval; - merging, queueing or arming the Version Packages PR. ## True on the `main` it merges into (dependence on PR #23209) - `WORKFLOW_DISPATCH_INPUTS` is not on `main`: `git grep -c WORKFLOW_DISPATCH_INPUTS origin/main` answers nothing (exit 1) at `4f81f31526`. PR #23209 (head `961ec7100a`) adds it in `scripts/pm/fleet-write/ops.mjs` as `'release.yml': { refresh_version_pr: true }`. So the clause states the rule (the relay's stroke, with that one input alone) and names no constant. - On `main` the relay's `WORKFLOW_DISPATCH_ALLOWLIST` is `['shard-timings-refresh.yml']`. `validate.mjs --self-test` pins that a `release.yml` dispatch is refused, and the refusal names that list. So between this landing and PR #23209's, the relay refuses the admitted stroke with zero writes. The rule lands before its mechanism, and it fails closed. - **This carve-out can be used only once PR #23209 lands.** Nothing here edits `release.yml`, `scripts/pm/fleet-write/**` or PR #23209, and nothing was dispatched. ## Why the stroke cannot publish: `release.yml` jobs on `main` (`4f81f31526`) - `version-pr` (`Version PR maintenance`) runs on `schedule`, or on a dispatch with `inputs.refresh_version_pr` true. It is the only job the stroke starts. - `release-integrity` (`Release integrity (audit + no-mint backfill)`) and `stale-prompts` (`Cancel publish prompts for versions already on npm`) carry `!inputs.refresh_version_pr` in their own `if:` for a dispatch. - `full-battery` (`Full battery green at the version commit`) and `publish` (`Publish ... to npm (awaiting approval)`) need `release-integrity`, so a skipped audit makes `success()` false. Their `force` branch also carries `!inputs.refresh_version_pr`. - `docker` (`Docker image`) has no input guard. It runs only on a `published` output from `release-integrity` or `publish`, and the stroke leaves both unset. So the card's "the publish lanes require `!inputs.refresh_version_pr`" holds literally for two jobs and on the `force` branch for two more, and `docker` is covered through its dependency. The two dispatches recorded in `6141962120` (runs `38351525685` and `38357219168`) ran `Version PR maintenance` and skipped the other five jobs. ## Line budget: why the ruling's clause and not a three-part sentence - `AGENTS.md` has a line ceiling of 1116 in `scripts/pm/check-skill-line-ratchet.mjs`, at headroom 0 on base. Raising it takes a maintainer ruling quoted in the raising PR. Ruling A ruled the text and named no line budget. - I measured with that gate's own `wrapLine` at the paragraph's typeset width (118 B). The base paragraph greedy-wraps to its current 15 lines, so it has no lossless re-wrap headroom, and its last line has 99 B of slack. With both edits (+91 B clause, -9 B lead) the paragraph is still 15 lines, with 12 B of slack on its last line. `AGENTS.md` stays at 1116 lines on head `e7712a44`. - The three-part sentence the card sketched (the admitted dispatch, the by-job warrant, and every other act unchanged; 367 B) measures **+3 lines (1116 to 1119)**. It would need its own ruling. The ratchet's header refuses re-wrapping existing text to pay for it. - The warrant above is recorded here, not in the rule. PD15's own second paragraph holds that "the YAML is not a barrier that holds against you". So the carve-out's authority is the ruling, and the job guards are only the reason it is safe. ## Reviewer points 1. The bold lead is aligned in patch round 1, per the seat's answer B (`6164269656`); see edit 2. 2. Mirror check: no file restates PD15's reserved-act list, so nothing moves in step. The queries are listed under Acceptance notes. 3. Prime Directive 13: no ADR reserves the refresh stroke. ADR-0125 line 95 (PD15's "prohibitions stand as written") is the record of 2026-08-20, and it predates `refresh_version_pr`. Nothing is superseded. ## Acceptance notes - Mirror search over `.claude/**`, `skills/**`, `scripts/**` and `docs/**`, with git grep -F at `9b68a60e`. Control: `publish-capable workflow` in `AGENTS.md` = 1 hit. - 0 hits in all four trees for each list phrase: `publish-capable workflow`, `publish-capable`, `workflow_dispatch`-ing, `release act itself`, `triggers a release workflow`, `PD15` and pending `release` environment. - `Prime Directive 15`: `scripts/release-github-releases.mjs` (2 hits; it cites PD15 for not deleting Releases). - `Prime Directive #15`: `scripts/pm/check-skill-line-ratchet.mjs` (1, a historical ceiling comment), plus `docs/adr/0125-…` and `docs/adr/0082-…` (7 in total, all citations). - `refresh_version_pr`: `scripts/pm/check-expected-skips.mjs` (2) and `docs/releases-maintenance.md` (3, the maintainer's runbook). - `.claude/skills/pm-dispatch/SKILL.md:34` is a pointer ("发布动作的完整清单以 AGENTS.md 为权威"). - Pointers do not move, and there is no Tier S hunk. - The card cites PD15 at `:300-312`. On base it is `:301-321`. The lead edit is at `:302`, and the amended clause is at `:307-308`. ## Gates (head `e7712a44`) Derived with `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` (no paths; 1 path vs merge base `4f81f3152`, +10 / -10). This is the same 15-command list as on `9b68a60e`. All 15 exited 0, with exit codes captured before any pipe: - `check-closing-keyword-parity` and its `--self-test` - `check-comment-mask-corpus` - `check:agent-test-spelling` - `check:docs-audit-scope` - `check:driver-memory-census` - `check:gitlink-declared` - `check:nul-bytes` ("no raw ASCII control bytes") - `check:pm-governed-merges` - `check:pm-governed-prose` - `check:pm-skill-id-lint` ("87 file(s) clean") - `check:pm-skill-ratchet` ("AGENTS.md is 1116 lines (ceiling 1116; headroom 0)") - `check:refd-timer-probe` - `check:required-contexts` - `check:watch-hint-literal` Also run, outside the derivation: `check-published-list-mirrors` ("1 published list mirror(s) match"), exit 0. Reconciliation with `--ran`: "15 derived, 15 run, 0 NOT-MEASURED, 0 UNRUN", a derived zero. Not measured: - `scripts/check-required-contexts.mjs --verify-required-set`, which takes a value from the workflow. - No package build or test: no package is touched. No changeset: `AGENTS.md` ships in no package's `files[]` (`skip-changeset`). GitHub reports the PR mergeable, so `main` was not merged in. ## 维护者速读(草稿) ### 改了什么 AGENTS.md 第 15 条改了两处: 1. 保留动作清单。手动派发 `release.yml` 仍由维护者保留,只有一种例外:经 fleet-write 中继、只带 `refresh_version_pr: true` 的刷新,它只重生成 Version Packages PR。 2. 加粗首句。「triggers a release workflow」改成「triggers a release」,和清单对齐。 其余保留动作一字未改,包括发布、打 tag、Release、镜像、`release` 环境审批,以及合并或排队 Version Packages PR。 ### 为什么改 执行 #23193 的裁决 A(「23209 A」)。裁决 B 第 5 条要求席位在修复合入后立刻刷新 Version PR,但原文禁止任何 `release.yml` 派发,规则和机制互相矛盾,PR #23209 因此一直搁置。只改清单的话,首句仍会禁止清单已经允许的刷新,矛盾还在。所以按裁决 A 的理由「一条规则文本对应一种机制」,首句一并对齐。这是席位对报告问题的答复(B)。 ### 风险与代价(含回滚) 这次刷新不会发布:它只跑 `Version PR maintenance`,审计、发布、镜像任务都跳过,两次实跑可以作证。首句改短以后,其余发布类派发仍由清单逐项点名保留。PR #23209 合入之前,中继会直接拒绝 `release.yml`,例外暂时用不上,失败方向是关闭。行数仍是 1116,不需要抬上限。回滚方法:revert 本 PR 合入的 commit。 ### 席位意见 ### 你要做的 批准本 PR(Tier H)。 --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 863213a commit 5b31fb9

1 file changed

Lines changed: 10 additions & 10 deletions

File tree

‎AGENTS.md‎

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -299,20 +299,20 @@ localStorage / auth gotchas.
299299
approval, or a Tier S merge without a PASS record is a seat violation, filed and rolled back. No seat judges this.
300300

301301
15. **⛔ A version release is performed by the maintainer, by hand — no AI seat publishes, tags, cuts a Release, or
302-
triggers a release workflow, and none merges the Version Packages PR.** A rule that binds every seat lives here,
302+
triggers a release, and none merges the Version Packages PR.** A rule that binds every seat lives here,
303303
not only in a lane-specific skill file. **Release-adjacent work stays open to every seat**: the release board,
304304
`.objectui-sha` pin bumps, version reconciliation, writing changesets, compiling release notes when asked, and
305305
*verifying* release state (`npm view`, `git ls-remote --tags`) are ordinary tasks. What is reserved is the
306306
**release act itself**: ⛔ running `changeset publish` / `pnpm run release`, ⛔ pushing a version tag, ⛔
307-
cutting a GitHub Release, ⛔ pushing a runtime image, ⛔ `workflow_dispatch`-ing `release.yml` or any other
308-
publish-capable workflow, ⛔ **approving a pending `release` environment deployment** (ADR-0125: that click IS
309-
the publish authorisation, and a deployment waiting for hours is the system working, not a state you clear), and
310-
⛔ merging — or queueing, or arming auto-merge on — the **Version Packages** PR (`chore: version packages`).
311-
That PR is bot-authored and standing-open by design: it is regenerated six-hourly by `release.yml`'s `version-pr`
312-
job — never on a push to `main`; push drives the publish lane — so "green, current, and nobody has objected"
313-
is its permanent resting state, not a signal that it is due. When you find a publish nobody ordered — a tag or
314-
an npm version that simply appeared — ⛔ do not "repair" it with a counter-publish: file it as an incident for
315-
the maintainer.
307+
cutting a GitHub Release, ⛔ pushing a runtime image, ⛔ `workflow_dispatch`-ing `release.yml` in any lane but
308+
the fleet-write relay's refresh stroke (`refresh_version_pr: true` alone), or any other publish-capable workflow,
309+
⛔ **approving a pending `release` environment deployment** (ADR-0125: that click IS the publish authorisation,
310+
and a deployment waiting for hours is the system working, not a state you clear), and ⛔ merging — or queueing,
311+
or arming auto-merge on — the **Version Packages** PR (`chore: version packages`). That PR is bot-authored and
312+
standing-open by design: it is regenerated six-hourly by `release.yml`'s `version-pr` job — never on a push to
313+
`main`; push drives the publish lane — so "green, current, and nobody has objected" is its permanent resting
314+
state, not a signal that it is due. When you find a publish nobody ordered — a tag or an npm version that simply
315+
appeared — ⛔ do not "repair" it with a counter-publish: file it as an incident for the maintainer.
316316

317317
**The existence of a path to a release is not authorization to walk it, and the YAML is not a barrier that
318318
holds against you.** The publish job is triggered by the **push that lands the Version Packages PR** and held at

0 commit comments

Comments
 (0)