From c3b1841941900bf93098658e50296146b0eadcd0 Mon Sep 17 00:00:00 2001 From: Baruch Sadogursky Date: Thu, 16 Jul 2026 12:32:21 -0500 Subject: [PATCH 01/17] feat(rules): make green-gate shipping actions autonomous MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Opening a PR, dismissing superseded bot reviews, and merging were already sanctioned — but only in skills/release/SKILL.md, which loads on invocation. An agent finishing a task has never invoked the release skill, so its always-on context mandated PRs without ever saying who authorizes opening one. Agents filled that gap by asking, and the ask is what made the merge classifier demand approval for actions the policy had already granted. Add rules/autonomous-shipping.md (always-on) as the single contract, bound by four surviving gates. Retitle ci-safety's dismissal carve-out, whose "Narrow exception" framing defeated the very false-positive it was added in #174 to prevent. Point release Steps 2/7 at the rule. Co-Authored-By: Claude Opus 4.8 (1M context) Claude-Session: https://claude.ai/code/session_01JgdWmv7KBj91nxbVjMsj7X --- .tessl-plugin/plugin.json | 1 + CHANGELOG.md | 6 ++++++ README.md | 3 ++- rules/autonomous-shipping.md | 37 ++++++++++++++++++++++++++++++++++++ rules/ci-safety.md | 5 +++-- skills/release/SKILL.md | 4 ++-- 6 files changed, 51 insertions(+), 5 deletions(-) create mode 100644 rules/autonomous-shipping.md diff --git a/.tessl-plugin/plugin.json b/.tessl-plugin/plugin.json index 78c3efa6..633ce61a 100644 --- a/.tessl-plugin/plugin.json +++ b/.tessl-plugin/plugin.json @@ -19,6 +19,7 @@ "rules/dependency-management.md", "rules/file-hygiene.md", "rules/ci-safety.md", + "rules/autonomous-shipping.md", "rules/no-secrets.md", "rules/code-formatting.md", "rules/language-diagnostics.md", diff --git a/CHANGELOG.md b/CHANGELOG.md index 5b3e3b8d..b76c46f0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +### Rules + +- **`autonomous-shipping` (new, always-on)** — States that opening a PR, dismissing superseded bot reviews, merging, and watching through publish are the autonomous next step once their gate reads green, and that asking on a green gate is a defect rather than a courtesy. The autonomy statements already existed in `skills/release/SKILL.md` (Step 2 "create the PR automatically", Step 7 "merge automatically") but a skill loads only on invocation — an agent that has just finished implementing a task has never invoked the release skill, so its always-on context carried the PR mandate with no word on who authorizes opening one. Agents filled the gap by asking, and the ask itself is what made the merge classifier demand approval for actions the policy had already granted. Rule names the four gating cases that survive (red/absent/ambiguous gate, no-undo actions, human `CHANGES_REQUESTED`, unowned repos) so the autonomy stays bounded. Consumers: an always-on instruction in your own `CLAUDE.md` outranks plugin rules — an "ask before pushing" line there will defeat this rule. +- **`ci-safety`: Superseded-Bot-Review Dismissal Carve-Out → Dismissing Superseded Bot Reviews** — Retitled and reopened; preconditions and the `GATING_BOTS` scoping are unchanged. PR #174 added the carve-out precisely so agents would stop false-positiving a legitimate dismissal as gate-gaming, but titling it "Carve-Out" and opening with "Narrow exception" read as a danger signal, and agents kept asking for a go-ahead on a dismissal `dismiss-stale-reviews.sh` already validates deterministically. The section now leads with the affirmative permission and points at `autonomous-shipping`; the reset line still gates every dismissal the two preconditions miss. +- **`release` skill Steps 2 and 7** — Reference `rules/autonomous-shipping.md` so the skill and the always-on context agree on one contract; Step 7 also names dismissal explicitly as no-ask. + ## 0.3.93 — 2026-07-17 ### Skills diff --git a/README.md b/README.md index edb61f31..c3c7120f 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ Coding policy plugin for Baruch's AI agents. Language-agnostic code quality rule ## What's New -- 23 rules — 16 always-on, 7 conditional (scoped via `applyTo:` to the files where the rule's prescriptions actually fire). Breakdown: 10 covering code quality, 8 covering plugin authoring, 1 covering author-model declaration, 1 covering concurrency, 1 covering review discipline, 1 covering reviewer-feedback reading, 1 covering external-repo action scope +- 24 rules — 17 always-on, 7 conditional (scoped via `applyTo:` to the files where the rule's prescriptions actually fire). Breakdown: 10 covering code quality, 8 covering plugin authoring, 1 covering author-model declaration, 1 covering concurrency, 1 covering review discipline, 1 covering reviewer-feedback reading, 1 covering external-repo action scope, 1 covering shipping autonomy - `release` skill — structured PR + merge workflow with Copilot review and paired-reviewer cross-family enforcement - `eval-authoring` skill — generate, review, and curate eval scenarios with score-driven iteration - `install-reviewer` skill — scaffold the paired gh-aw PR review workflows (OpenAI + Anthropic) into a consumer repo @@ -34,6 +34,7 @@ tessl install jbaruch/coding-policy | Deps | [dependency-management](rules/dependency-management.md) | Stdlib-first, pinned versions kept fresh via a renewal mechanism, lock files | | Files | [file-hygiene](rules/file-hygiene.md) | Proper .gitignore, no generated files committed | | CI | [ci-safety](rules/ci-safety.md) | Never skip tests, never modify CI without asking | +| Shipping | [autonomous-shipping](rules/autonomous-shipping.md) | A green gate is the go-ahead — open the PR, dismiss superseded bot reviews, merge and watch through publish without asking; asking on a green gate is the violation | | Secrets | [no-secrets](rules/no-secrets.md) | No credentials in code, env vars or secrets manager | | Style | [code-formatting](rules/code-formatting.md) | Use project's formatter, don't mix style with logic | | Types | [language-diagnostics](rules/language-diagnostics.md) | Enable the project's language server; its findings are non-dismissible without cause; gate the headless checker in CI at zero findings | diff --git a/rules/autonomous-shipping.md b/rules/autonomous-shipping.md new file mode 100644 index 00000000..22c96990 --- /dev/null +++ b/rules/autonomous-shipping.md @@ -0,0 +1,37 @@ +--- +alwaysApply: true +description: A green gate is the go-ahead; pausing to ask for approval the gate already granted is the violation. +--- + +# Autonomous Shipping + +## Green Gate Is the Approval + +- A shipping action is the autonomous next step once its gate reads green +- The gate is the approval artifact — no human ack stands between a green gate and the action it gates +- A gate is the named conjunction of fields, never an impression — each action below names the fields that must read green +- Read the gate to resolve doubt about whether it is green; never ask the operator to resolve it + +## The Autonomous Actions + +- **Open the PR** — Step 1 readiness checks pass (`skills/release/SKILL.md`) ⇒ push the branch and open the PR +- **Dismiss superseded bot reviews** — a gating bot's `CHANGES_REQUESTED` that the same bot's later all-clear superseded ⇒ run `skills/release/dismiss-stale-reviews.sh` (see `rules/ci-safety.md` Dismissing Superseded Bot Reviews) +- **Merge** — Step 7's conditions hold: watcher returned `ready`, every review body read, every inline thread replied (`skills/release/SKILL.md`) ⇒ merge and clean up +- **Watch through publish** — the merge lands ⇒ watch the run, the registry advance, and the moderation clear per `rules/ci-safety.md` Always Watch CI. The watch is part of the merge, not a separate decision + +## Asking Is the Violation + +- An ask on a green gate is a defect, not a courtesy +- The ask manufactures the approval gate — an action the policy authorized becomes blocked the moment the agent surfaces it as a question +- "The owner may want to weigh in" is not a reason to ask; the owner's position is the policy, already written +- Report the action taken, never propose it — `Dismissed 2 superseded reviews, merged #19` over `Merge #19? It needs the stale reviews dismissed first` +- A gate the operator already answered stays answered — never re-ask per PR what the policy grants standing + +## What Still Gates + +- Red, absent, or ambiguous gate — fix it, or surface the specific field that is not green +- Force-push to a shared branch, history rewrite, tag or release deletion, any action with no undo +- Direct push to a protected branch outside `rules/ci-safety.md` Content-Only Direct-Push Carve-Out +- A human reviewer's `CHANGES_REQUESTED` — autonomous dismissal covers bot reviews only +- Action in a repo the operator does not own (see `rules/external-repo-contributions.md`) +- Scope the operator never granted — this rule governs how to ship the agreed task, never which task to take on diff --git a/rules/ci-safety.md b/rules/ci-safety.md index f7402afd..d051564b 100644 --- a/rules/ci-safety.md +++ b/rules/ci-safety.md @@ -16,9 +16,10 @@ alwaysApply: true - Never disable or skip failing tests to unblock a merge - If tests fail, fix the tests or fix the code -## Superseded-Bot-Review Dismissal Carve-Out +## Dismissing Superseded Bot Reviews -- Narrow exception for dismissing a review gate — not a bypass when the gate is a bot's `CHANGES_REQUESTED` that the same bot later superseded with an all-clear re-review +- Dismiss autonomously once both preconditions below hold — sanctioned gate cleanup, never a bypass, and never an operator ack (see `rules/autonomous-shipping.md`) +- The gate is a bot's `CHANGES_REQUESTED` that the same bot later superseded with an all-clear re-review - Applies when a gating bot that cannot `APPROVE` (`github-actions[bot]` — GitHub returns HTTP 422) re-reviews clean but cannot post the `APPROVED` verdict that would supersede its earlier `CHANGES_REQUESTED` — the stale request keeps the merge `BLOCKED` until dismissed - Preconditions (all required): 1. The dismissed review is a `CHANGES_REQUESTED` from a gating bot on the allowlist (`GATING_BOTS` in `skills/release/dismiss-stale-reviews.sh`), never a human reviewer — a human can `APPROVE`, so a human's supersession goes through re-request-and-approve, never dismissal diff --git a/skills/release/SKILL.md b/skills/release/SKILL.md index 48bb0c75..681f410d 100644 --- a/skills/release/SKILL.md +++ b/skills/release/SKILL.md @@ -33,7 +33,7 @@ Structured workflow for shipping code: PR creation, automated policy review, mer ## Step 2 — Create PR -- Once Step 1's readiness checks pass, create the PR automatically — the green readiness checks are the gate. Do not pause to ask a human whether to open it. +- Once Step 1's readiness checks pass, create the PR automatically — the green readiness checks are the gate. Do not pause to ask a human whether to open it (`rules/autonomous-shipping.md`). - Push the branch: `git push -u origin ` - Create the PR with `gh pr create`: - **Title**: `(): ` @@ -114,7 +114,7 @@ Only proceed when: A `COMMENTED` review never gates the merge on its state alone — but its body must be read before merge, zero inline comments included. With inline comments, it is mergeable once every thread also has a reply. -Once these conditions hold, merge automatically — the green gates are the approval. Do not pause to ask a human whether to merge. +Once these conditions hold, merge automatically — the green gates are the approval. Do not pause to ask a human whether to merge, and do not ask whether to dismiss the superseded reviews below (`rules/autonomous-shipping.md`). **Clear superseded review gates first.** A policy bot cannot `APPROVE` (`github-actions[bot]` gets HTTP 422), so a clean re-review lands as a `COMMENT` that does NOT supersede the bot's earlier `CHANGES_REQUESTED` in GitHub's merge gate — the stale request keeps `merge_state.status` at `BLOCKED`. Dismiss every such superseded review before merging: From 63c28539b3a8bf82cd5b53d6876a26bb8a509c53 Mon Sep 17 00:00:00 2001 From: Baruch Sadogursky Date: Thu, 16 Jul 2026 18:57:54 -0500 Subject: [PATCH 02/17] feat(rules): define what counts as approval The rule asserted "the green gate is the approval" without ever saying what the gate is made of, and was silent on the question every reader actually has: does bot review substitute for human review? ci-safety documents that github-actions[bot] cannot APPROVE (HTTP 422). SKILL.md Step 7 lists a merge conjunction. Neither says whether a human must sign off, so "green gate is the approval" read as an assertion rather than a definition. State the operator's position outright and name the conjunction. Also: - Authorization is standing, never inferred from the conversation. An agent that stops asking but still needs a grant will manufacture one; production showed an agent reading the operator's challenge to the policy as authorization under it. - A verdict approves only the commit it reviewed. A review whose commit_id is not the head SHA reads as absent, not clean. - CI-config edits join What Still Gates (ci-safety says stop and ask; the rule's red-gate line said fix it). - The Merge action points at the definition instead of restating fields (Copilot on #178). Co-Authored-By: Claude Opus 4.8 (1M context) Claude-Session: https://claude.ai/code/session_01JgdWmv7KBj91nxbVjMsj7X --- CHANGELOG.md | 4 +++- rules/autonomous-shipping.md | 18 ++++++++++++++++-- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b76c46f0..e8467677 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,9 @@ ### Rules -- **`autonomous-shipping` (new, always-on)** — States that opening a PR, dismissing superseded bot reviews, merging, and watching through publish are the autonomous next step once their gate reads green, and that asking on a green gate is a defect rather than a courtesy. The autonomy statements already existed in `skills/release/SKILL.md` (Step 2 "create the PR automatically", Step 7 "merge automatically") but a skill loads only on invocation — an agent that has just finished implementing a task has never invoked the release skill, so its always-on context carried the PR mandate with no word on who authorizes opening one. Agents filled the gap by asking, and the ask itself is what made the merge classifier demand approval for actions the policy had already granted. Rule names the four gating cases that survive (red/absent/ambiguous gate, no-undo actions, human `CHANGES_REQUESTED`, unowned repos) so the autonomy stays bounded. Consumers: an always-on instruction in your own `CLAUDE.md` outranks plugin rules — an "ask before pushing" line there will defeat this rule. +- **`autonomous-shipping` (new, always-on)** — States that opening a PR, dismissing superseded bot reviews, merging, and watching through publish are the autonomous next step once their gate reads green, and that asking on a green gate is a defect rather than a courtesy. The autonomy statements already existed in `skills/release/SKILL.md` (Step 2 "create the PR automatically", Step 7 "merge automatically") but a skill loads only on invocation — an agent that has just finished implementing a task has never invoked the release skill, so its always-on context carried the PR mandate with no word on who authorizes opening one. Agents filled the gap by asking. Bounded by seven surviving gates (red/absent/ambiguous gate, unplanned CI-config edits, no-undo actions, protected-branch pushes, human `CHANGES_REQUESTED`, unowned repos, ungranted scope). +- **`autonomous-shipping`: What Counts as Approval** — The policy asserted "the green gate is the approval" without ever defining what the gate is made of, and was silent on the question every reader actually has: does bot review substitute for human review? `ci-safety` documents that `github-actions[bot]` cannot `APPROVE` (HTTP 422); `SKILL.md` Step 7 lists a merge conjunction; neither says whether a human must sign off. The section states the operator's position outright — review is the paired bot fleet, a merge needs no human approval — and names the conjunction. Also encodes commit-scoped verdicts: a review whose `commit_id` is not the PR's head SHA reads as absent, not clean, so a stale approval cannot stand in for a missing one (the `poll-pr-reviews.sh` counterpart is tracked separately). +- **`autonomous-shipping`: authorization is standing, never inferred** — Removing the ask without supplying the grant is worse than the ask: an agent that stops asking but still needs authorization will manufacture it from the conversation. Observed in production — an agent read the operator's question "why is it my call? Is it somewhere in the rules?" (a challenge to the policy) as authorization under it, and a safety classifier correctly blocked the merge. The grant lives in this policy and the operator's durable config, never in the operator's latest message; where no standing grant covers an action the gate is absent, not green. Consumers: an always-on instruction in your own `CLAUDE.md` outranks plugin rules — an "ask before pushing" line there will defeat this rule. - **`ci-safety`: Superseded-Bot-Review Dismissal Carve-Out → Dismissing Superseded Bot Reviews** — Retitled and reopened; preconditions and the `GATING_BOTS` scoping are unchanged. PR #174 added the carve-out precisely so agents would stop false-positiving a legitimate dismissal as gate-gaming, but titling it "Carve-Out" and opening with "Narrow exception" read as a danger signal, and agents kept asking for a go-ahead on a dismissal `dismiss-stale-reviews.sh` already validates deterministically. The section now leads with the affirmative permission and points at `autonomous-shipping`; the reset line still gates every dismissal the two preconditions miss. - **`release` skill Steps 2 and 7** — Reference `rules/autonomous-shipping.md` so the skill and the always-on context agree on one contract; Step 7 also names dismissal explicitly as no-ask. diff --git a/rules/autonomous-shipping.md b/rules/autonomous-shipping.md index 22c96990..2e846fa7 100644 --- a/rules/autonomous-shipping.md +++ b/rules/autonomous-shipping.md @@ -9,14 +9,27 @@ description: A green gate is the go-ahead; pausing to ask for approval the gate - A shipping action is the autonomous next step once its gate reads green - The gate is the approval artifact — no human ack stands between a green gate and the action it gates -- A gate is the named conjunction of fields, never an impression — each action below names the fields that must read green +- A gate is a named conjunction of fields, never an impression — What Counts as Approval names the merge gate's fields; each action below names the gate it reads - Read the gate to resolve doubt about whether it is green; never ask the operator to resolve it +- Authorization is standing — it lives in this policy and in the operator's own durable config, never in the operator's latest message +- Never read a challenging question, an ambiguous remark, or silence as the grant — "is that in the rules?" interrogates the policy, it does not authorize an action under it +- No standing grant covers the action — the gate is absent, not green (see What Still Gates) +- A harness gate this policy does not govern (a safety classifier, a permission prompt) is a red gate like any other — surface it and name what it wants; never re-attempt the action to route around it + +## What Counts as Approval + +- Review in these repos is the paired bot fleet, not a human sign-off — a merge needs no human approval, and its absence is never a reason to hold a green PR +- Merge approval is the conjunction, all required: both gating bots' latest verdicts posted for the head SHA and non-`CHANGES_REQUESTED`, CI `success` or `none`, merge state mergeable, every review body read, every inline comment answered +- A verdict approves only the commit it reviewed — a review whose `commit_id` is not the PR's head SHA has not approved the current code, and reads as absent rather than clean +- A reviewer that has posted no verdict for the current head SHA has not reviewed it; a stale verdict never stands in for the missing one +- A gating bot that cannot `APPROVE` posts its all-clear as `COMMENTED` — `github-actions[bot]` gets HTTP 422 from GitHub (see `rules/ci-safety.md` Dismissing Superseded Bot Reviews) +- A human reviewer's `CHANGES_REQUESTED` overrides every bot verdict (see What Still Gates) ## The Autonomous Actions - **Open the PR** — Step 1 readiness checks pass (`skills/release/SKILL.md`) ⇒ push the branch and open the PR - **Dismiss superseded bot reviews** — a gating bot's `CHANGES_REQUESTED` that the same bot's later all-clear superseded ⇒ run `skills/release/dismiss-stale-reviews.sh` (see `rules/ci-safety.md` Dismissing Superseded Bot Reviews) -- **Merge** — Step 7's conditions hold: watcher returned `ready`, every review body read, every inline thread replied (`skills/release/SKILL.md`) ⇒ merge and clean up +- **Merge** — the What Counts as Approval conjunction holds ⇒ merge and clean up (`skills/release/SKILL.md` Step 7) - **Watch through publish** — the merge lands ⇒ watch the run, the registry advance, and the moderation clear per `rules/ci-safety.md` Always Watch CI. The watch is part of the merge, not a separate decision ## Asking Is the Violation @@ -30,6 +43,7 @@ description: A green gate is the go-ahead; pausing to ask for approval the gate ## What Still Gates - Red, absent, or ambiguous gate — fix it, or surface the specific field that is not green +- An unplanned CI-config edit, even to turn a red gate green (see `rules/ci-safety.md` Hands Off CI Config) - Force-push to a shared branch, history rewrite, tag or release deletion, any action with no undo - Direct push to a protected branch outside `rules/ci-safety.md` Content-Only Direct-Push Carve-Out - A human reviewer's `CHANGES_REQUESTED` — autonomous dismissal covers bot reviews only From c70b7f686e3560b07bedbc795bdc37f0250147e7 Mon Sep 17 00:00:00 2001 From: Baruch Sadogursky Date: Thu, 16 Jul 2026 19:06:54 -0500 Subject: [PATCH 03/17] fix(rules): defer the commit-scoped verdict clause; restore carve-out shape MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit gh-aw caught two policy self-consistency breaks. The rule required each verdict to approve only the commit it reviewed, but poll-pr-reviews.sh resolves reviews by bot login and returns no commit_id, and watch-pr-reviews.sh treats any non-none state as satisfying `ready`. A clean verdict on a superseded commit still passes the executable gate. That publishes a rule the repo does not obey (context-artifacts.md Post-Edit Rule Audit). The script lives in an unmerged PR, so the clause defers to land with the gate that enforces it. The ci-safety retitle dropped the `Narrow exception for X.` lead while keeping preconditions and a reset line — still a carve-out, minus the shape context-writing-style.md prescribes. That traded one violation for another. The framing fix belongs in autonomous-shipping, which now names dismissal as an autonomous action and defines approval, so the carve-out keeps its shape and gains a pointer. Copilot: split the two multi-directive bullets, cut the worked examples (context-writing-style sends those to CHANGELOG), drop the "each action names the fields" claim the actions did not honour. Co-Authored-By: Claude Opus 4.8 (1M context) Claude-Session: https://claude.ai/code/session_01JgdWmv7KBj91nxbVjMsj7X --- CHANGELOG.md | 5 +++-- rules/autonomous-shipping.md | 21 ++++++++++----------- rules/ci-safety.md | 6 +++--- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e8467677..a80d2ae8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,9 +3,10 @@ ### Rules - **`autonomous-shipping` (new, always-on)** — States that opening a PR, dismissing superseded bot reviews, merging, and watching through publish are the autonomous next step once their gate reads green, and that asking on a green gate is a defect rather than a courtesy. The autonomy statements already existed in `skills/release/SKILL.md` (Step 2 "create the PR automatically", Step 7 "merge automatically") but a skill loads only on invocation — an agent that has just finished implementing a task has never invoked the release skill, so its always-on context carried the PR mandate with no word on who authorizes opening one. Agents filled the gap by asking. Bounded by seven surviving gates (red/absent/ambiguous gate, unplanned CI-config edits, no-undo actions, protected-branch pushes, human `CHANGES_REQUESTED`, unowned repos, ungranted scope). -- **`autonomous-shipping`: What Counts as Approval** — The policy asserted "the green gate is the approval" without ever defining what the gate is made of, and was silent on the question every reader actually has: does bot review substitute for human review? `ci-safety` documents that `github-actions[bot]` cannot `APPROVE` (HTTP 422); `SKILL.md` Step 7 lists a merge conjunction; neither says whether a human must sign off. The section states the operator's position outright — review is the paired bot fleet, a merge needs no human approval — and names the conjunction. Also encodes commit-scoped verdicts: a review whose `commit_id` is not the PR's head SHA reads as absent, not clean, so a stale approval cannot stand in for a missing one (the `poll-pr-reviews.sh` counterpart is tracked separately). +- **`autonomous-shipping`: What Counts as Approval** — The policy asserted "the green gate is the approval" without ever defining what the gate is made of, and was silent on the question every reader actually has: does bot review substitute for human review? `ci-safety` documents that `github-actions[bot]` cannot `APPROVE` (HTTP 422); `SKILL.md` Step 7 lists a merge conjunction; neither says whether a human must sign off. The section states the operator's position outright — review is the paired bot fleet, a merge needs no human approval — and names the conjunction. +- **Commit-scoped verdicts deferred** — a first draft required each verdict to approve only the commit it reviewed (`commit_id` == head SHA). `poll-pr-reviews.sh` resolves reviews by bot login and returns `{state, submitted_at, body}` with no `commit_id`, and `watch-pr-reviews.sh` treats any non-`none` state as satisfying the bot-verdict half of `ready` — so a clean verdict on a superseded commit still passes the executable gate. Shipping the clause here would have published a rule the repo does not obey (`rules/context-artifacts.md` Post-Edit Rule Audit). It lands with the poll/watch change, not before. - **`autonomous-shipping`: authorization is standing, never inferred** — Removing the ask without supplying the grant is worse than the ask: an agent that stops asking but still needs authorization will manufacture it from the conversation. Observed in production — an agent read the operator's question "why is it my call? Is it somewhere in the rules?" (a challenge to the policy) as authorization under it, and a safety classifier correctly blocked the merge. The grant lives in this policy and the operator's durable config, never in the operator's latest message; where no standing grant covers an action the gate is absent, not green. Consumers: an always-on instruction in your own `CLAUDE.md` outranks plugin rules — an "ask before pushing" line there will defeat this rule. -- **`ci-safety`: Superseded-Bot-Review Dismissal Carve-Out → Dismissing Superseded Bot Reviews** — Retitled and reopened; preconditions and the `GATING_BOTS` scoping are unchanged. PR #174 added the carve-out precisely so agents would stop false-positiving a legitimate dismissal as gate-gaming, but titling it "Carve-Out" and opening with "Narrow exception" read as a danger signal, and agents kept asking for a go-ahead on a dismissal `dismiss-stale-reviews.sh` already validates deterministically. The section now leads with the affirmative permission and points at `autonomous-shipping`; the reset line still gates every dismissal the two preconditions miss. +- **`ci-safety`: Superseded-Bot-Review Dismissal Carve-Out keeps its shape, gains an autonomy pointer** — an intermediate draft retitled the section and dropped the `Narrow exception for X.` lead, on the theory that the carve-out framing was itself what made agents ask permission for a dismissal `dismiss-stale-reviews.sh` already validates deterministically. That trades one `context-writing-style.md` violation for another: the section is still a preconditioned exception, so it still owes the prescribed carve-out shape. The framing fix belongs in `autonomous-shipping`, which now names dismissal as an autonomous action and defines approval outright — so the carve-out shape is restored and the section gains a single pointer to it. Preconditions and `GATING_BOTS` scoping unchanged throughout. - **`release` skill Steps 2 and 7** — Reference `rules/autonomous-shipping.md` so the skill and the always-on context agree on one contract; Step 7 also names dismissal explicitly as no-ask. ## 0.3.93 — 2026-07-17 diff --git a/rules/autonomous-shipping.md b/rules/autonomous-shipping.md index 2e846fa7..93d9f486 100644 --- a/rules/autonomous-shipping.md +++ b/rules/autonomous-shipping.md @@ -8,21 +8,20 @@ description: A green gate is the go-ahead; pausing to ask for approval the gate ## Green Gate Is the Approval - A shipping action is the autonomous next step once its gate reads green -- The gate is the approval artifact — no human ack stands between a green gate and the action it gates -- A gate is a named conjunction of fields, never an impression — What Counts as Approval names the merge gate's fields; each action below names the gate it reads -- Read the gate to resolve doubt about whether it is green; never ask the operator to resolve it +- A gate is a named conjunction of fields, never an impression — What Counts as Approval names the merge gate's fields +- Read the gate to resolve doubt about whether it is green +- Never ask the operator to resolve what reading the gate answers - Authorization is standing — it lives in this policy and in the operator's own durable config, never in the operator's latest message -- Never read a challenging question, an ambiguous remark, or silence as the grant — "is that in the rules?" interrogates the policy, it does not authorize an action under it +- Never read a challenging question, an ambiguous remark, or silence as the grant - No standing grant covers the action — the gate is absent, not green (see What Still Gates) -- A harness gate this policy does not govern (a safety classifier, a permission prompt) is a red gate like any other — surface it and name what it wants; never re-attempt the action to route around it +- A harness gate this policy does not govern (a safety classifier, a permission prompt) is a red gate — surface it and name what it blocked +- Never re-attempt a harness-blocked action through another tool ## What Counts as Approval - Review in these repos is the paired bot fleet, not a human sign-off — a merge needs no human approval, and its absence is never a reason to hold a green PR -- Merge approval is the conjunction, all required: both gating bots' latest verdicts posted for the head SHA and non-`CHANGES_REQUESTED`, CI `success` or `none`, merge state mergeable, every review body read, every inline comment answered -- A verdict approves only the commit it reviewed — a review whose `commit_id` is not the PR's head SHA has not approved the current code, and reads as absent rather than clean -- A reviewer that has posted no verdict for the current head SHA has not reviewed it; a stale verdict never stands in for the missing one -- A gating bot that cannot `APPROVE` posts its all-clear as `COMMENTED` — `github-actions[bot]` gets HTTP 422 from GitHub (see `rules/ci-safety.md` Dismissing Superseded Bot Reviews) +- Merge approval is the conjunction, all required: both gating bots' latest verdicts posted and non-`CHANGES_REQUESTED`, CI `success` or `none`, merge state mergeable, every review body read, every inline comment answered +- A gating bot that cannot `APPROVE` posts its all-clear as `COMMENTED` — `github-actions[bot]` gets HTTP 422 from GitHub (see `rules/ci-safety.md` Superseded-Bot-Review Dismissal Carve-Out) - A human reviewer's `CHANGES_REQUESTED` overrides every bot verdict (see What Still Gates) ## The Autonomous Actions @@ -37,8 +36,8 @@ description: A green gate is the go-ahead; pausing to ask for approval the gate - An ask on a green gate is a defect, not a courtesy - The ask manufactures the approval gate — an action the policy authorized becomes blocked the moment the agent surfaces it as a question - "The owner may want to weigh in" is not a reason to ask; the owner's position is the policy, already written -- Report the action taken, never propose it — `Dismissed 2 superseded reviews, merged #19` over `Merge #19? It needs the stale reviews dismissed first` -- A gate the operator already answered stays answered — never re-ask per PR what the policy grants standing +- Report the action taken, never propose it +- Never re-ask per PR what the policy grants standing ## What Still Gates diff --git a/rules/ci-safety.md b/rules/ci-safety.md index d051564b..2ce59eab 100644 --- a/rules/ci-safety.md +++ b/rules/ci-safety.md @@ -16,10 +16,10 @@ alwaysApply: true - Never disable or skip failing tests to unblock a merge - If tests fail, fix the tests or fix the code -## Dismissing Superseded Bot Reviews +## Superseded-Bot-Review Dismissal Carve-Out -- Dismiss autonomously once both preconditions below hold — sanctioned gate cleanup, never a bypass, and never an operator ack (see `rules/autonomous-shipping.md`) -- The gate is a bot's `CHANGES_REQUESTED` that the same bot later superseded with an all-clear re-review +- Narrow exception for dismissing a review gate — not a bypass when the gate is a bot's `CHANGES_REQUESTED` that the same bot later superseded with an all-clear re-review +- Dismissal under this exception is autonomous, never an operator ack (see `rules/autonomous-shipping.md`) - Applies when a gating bot that cannot `APPROVE` (`github-actions[bot]` — GitHub returns HTTP 422) re-reviews clean but cannot post the `APPROVED` verdict that would supersede its earlier `CHANGES_REQUESTED` — the stale request keeps the merge `BLOCKED` until dismissed - Preconditions (all required): 1. The dismissed review is a `CHANGES_REQUESTED` from a gating bot on the allowlist (`GATING_BOTS` in `skills/release/dismiss-stale-reviews.sh`), never a human reviewer — a human can `APPROVE`, so a human's supersession goes through re-request-and-approve, never dismissal From 97b95c63cf7e674a35709a99d7abafa9b5530c6a Mon Sep 17 00:00:00 2001 From: Baruch Sadogursky Date: Thu, 16 Jul 2026 21:07:58 -0500 Subject: [PATCH 04/17] fix(rules): repair the cross-reference the carve-out restore broke MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Restoring ci-safety's `Superseded-Bot-Review Dismissal Carve-Out` title left autonomous-shipping pointing at `Dismissing Superseded Bot Reviews` — a heading that no longer exists. Both reviewers caught it; it is the same Post-Edit Rule Audit failure the carve-out restore was fixing, moved one file over. Also expand "operator ack" — the abbreviation appears nowhere else in the rules (Copilot). Co-Authored-By: Claude Opus 4.8 (1M context) Claude-Session: https://claude.ai/code/session_01JgdWmv7KBj91nxbVjMsj7X --- rules/autonomous-shipping.md | 2 +- rules/ci-safety.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/rules/autonomous-shipping.md b/rules/autonomous-shipping.md index 93d9f486..a297a006 100644 --- a/rules/autonomous-shipping.md +++ b/rules/autonomous-shipping.md @@ -27,7 +27,7 @@ description: A green gate is the go-ahead; pausing to ask for approval the gate ## The Autonomous Actions - **Open the PR** — Step 1 readiness checks pass (`skills/release/SKILL.md`) ⇒ push the branch and open the PR -- **Dismiss superseded bot reviews** — a gating bot's `CHANGES_REQUESTED` that the same bot's later all-clear superseded ⇒ run `skills/release/dismiss-stale-reviews.sh` (see `rules/ci-safety.md` Dismissing Superseded Bot Reviews) +- **Dismiss superseded bot reviews** — a gating bot's `CHANGES_REQUESTED` that the same bot's later all-clear superseded ⇒ run `skills/release/dismiss-stale-reviews.sh` (see `rules/ci-safety.md` Superseded-Bot-Review Dismissal Carve-Out) - **Merge** — the What Counts as Approval conjunction holds ⇒ merge and clean up (`skills/release/SKILL.md` Step 7) - **Watch through publish** — the merge lands ⇒ watch the run, the registry advance, and the moderation clear per `rules/ci-safety.md` Always Watch CI. The watch is part of the merge, not a separate decision diff --git a/rules/ci-safety.md b/rules/ci-safety.md index 2ce59eab..66be3991 100644 --- a/rules/ci-safety.md +++ b/rules/ci-safety.md @@ -19,7 +19,7 @@ alwaysApply: true ## Superseded-Bot-Review Dismissal Carve-Out - Narrow exception for dismissing a review gate — not a bypass when the gate is a bot's `CHANGES_REQUESTED` that the same bot later superseded with an all-clear re-review -- Dismissal under this exception is autonomous, never an operator ack (see `rules/autonomous-shipping.md`) +- Dismissal under this exception is autonomous — never pause for the operator to confirm it (see `rules/autonomous-shipping.md`) - Applies when a gating bot that cannot `APPROVE` (`github-actions[bot]` — GitHub returns HTTP 422) re-reviews clean but cannot post the `APPROVED` verdict that would supersede its earlier `CHANGES_REQUESTED` — the stale request keeps the merge `BLOCKED` until dismissed - Preconditions (all required): 1. The dismissed review is a `CHANGES_REQUESTED` from a gating bot on the allowlist (`GATING_BOTS` in `skills/release/dismiss-stale-reviews.sh`), never a human reviewer — a human can `APPROVE`, so a human's supersession goes through re-request-and-approve, never dismissal From 4da1f0e50608095b518d6ade139685eca5b37e26 Mon Sep 17 00:00:00 2001 From: Baruch Sadogursky Date: Thu, 16 Jul 2026 21:58:44 -0500 Subject: [PATCH 05/17] fix(rules): close the four holes an adversarial review found MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit An independent review attacked the rule as the agent that benefits from it — the read the bot fleet does not perform, since it checks conformance to policy rather than whether the policy is sound. The worst one indicts the rule's own premise: the always-on conjunction was weaker than the Step 7 it pointed at, and this rule exists FOR agents that never load skills/release — so the weaker gate was the one they carried. "Every inline comment answered" is not Step 7's `Fixed in ` / `Declining — `; nothing bound a verdict to the head SHA; nothing re-checked before merging. The gate is now Step 7's preconditions, stated once. What Still Gates listed force-push and history rewrite as no-undo but never platform bypass. An agent with a standing grant, hitting a blocked merge, could read it as an obstacle to an already-authorized action and retry with --admin. Now gated explicitly, with mergeStateStatus in the conjunction so BLOCKED is not policy-green. "A merge needs no human approval" collided with ci-safety's Bootstrap-Red Carve-Out, which requires owner approval. The failure mode is multi-rule rationalization, not the happy path. Qualified, Bootstrap-Red named. "Asking Is the Violation" is right for approval questions the gate answers and dangerous everywhere else — an agent could refuse to surface scope or a human's prose hold. Split from a new Surfacing Is Required. Co-Authored-By: Claude Opus 4.8 (1M context) Claude-Session: https://claude.ai/code/session_01JgdWmv7KBj91nxbVjMsj7X --- CHANGELOG.md | 2 ++ rules/autonomous-shipping.md | 31 ++++++++++++++++++++++++------- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a80d2ae8..25d6cef1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ # Changelog +- **`autonomous-shipping`: hardened against the adversarial read** — an independent review (Grok, one-off) attacked the rule from the position of the agent that benefits from it and found four holes the bot fleet's conformance review does not look for. (1) The always-on conjunction was WEAKER than the `skills/release` Step 7 it pointed at — and the rule exists precisely for agents that never load that skill, so the weaker gate was the one they carried: "every inline comment answered" instead of Step 7's `Fixed in ` / `Declining — ` literals, no head-SHA binding, no re-check before merge. The gate is now Step 7's preconditions, stated once, never summarized. (2) `What Still Gates` named force-push and history rewrite as no-undo but never named platform bypass — an agent holding a standing grant could read a blocked merge as an obstacle and retry with `--admin`. Now explicitly gated, and `mergeStateStatus` joins the conjunction so `BLOCKED` is not policy-green. (3) "A merge needs no human approval" collided with `ci-safety`'s Bootstrap-Red Carve-Out, which still requires owner approval — the hole was multi-rule rationalization, not the happy path. Now qualified, with Bootstrap-Red named. (4) "Asking Is the Violation" is correct for approval questions the gate answers and dangerous outside them; an agent could refuse to surface scope, a base-branch question, or a human's prose hold. Split into `Asking Is the Violation` (approval questions only) and `Surfacing Is Required` (everything else). Also: authorization excludes every conversational turn, not merely the latest; draft status, non-merge labels, `PENDING` human reviews, prose holds, and mis-based PRs join the gates. + ### Rules - **`autonomous-shipping` (new, always-on)** — States that opening a PR, dismissing superseded bot reviews, merging, and watching through publish are the autonomous next step once their gate reads green, and that asking on a green gate is a defect rather than a courtesy. The autonomy statements already existed in `skills/release/SKILL.md` (Step 2 "create the PR automatically", Step 7 "merge automatically") but a skill loads only on invocation — an agent that has just finished implementing a task has never invoked the release skill, so its always-on context carried the PR mandate with no word on who authorizes opening one. Agents filled the gap by asking. Bounded by seven surviving gates (red/absent/ambiguous gate, unplanned CI-config edits, no-undo actions, protected-branch pushes, human `CHANGES_REQUESTED`, unowned repos, ungranted scope). diff --git a/rules/autonomous-shipping.md b/rules/autonomous-shipping.md index a297a006..e8318304 100644 --- a/rules/autonomous-shipping.md +++ b/rules/autonomous-shipping.md @@ -8,19 +8,23 @@ description: A green gate is the go-ahead; pausing to ask for approval the gate ## Green Gate Is the Approval - A shipping action is the autonomous next step once its gate reads green -- A gate is a named conjunction of fields, never an impression — What Counts as Approval names the merge gate's fields +- A gate is a named conjunction of fields, never an impression — What Counts as Approval names every field of the merge gate - Read the gate to resolve doubt about whether it is green - Never ask the operator to resolve what reading the gate answers -- Authorization is standing — it lives in this policy and in the operator's own durable config, never in the operator's latest message -- Never read a challenging question, an ambiguous remark, or silence as the grant +- Authorization to ship is standing — it lives in this policy and in the operator's own durable config, and in no conversational turn +- Never read a challenging question, an ambiguous remark, an earlier "ship it when green", or silence as the grant +- Conversation sets the task's scope; it never supplies the grant to ship - No standing grant covers the action — the gate is absent, not green (see What Still Gates) - A harness gate this policy does not govern (a safety classifier, a permission prompt) is a red gate — surface it and name what it blocked - Never re-attempt a harness-blocked action through another tool ## What Counts as Approval -- Review in these repos is the paired bot fleet, not a human sign-off — a merge needs no human approval, and its absence is never a reason to hold a green PR -- Merge approval is the conjunction, all required: both gating bots' latest verdicts posted and non-`CHANGES_REQUESTED`, CI `success` or `none`, merge state mergeable, every review body read, every inline comment answered +- Review in these repos is the paired bot fleet, not a human sign-off — a merge needs no human approval, except where another always-on rule names an owner-approval precondition (see What Still Gates) +- Merge approval is exactly `skills/release/SKILL.md` Step 7's preconditions — this section does not restate a shorter one, and a summary of them is never the gate +- Every gate field, all required: both gating bots' latest verdicts posted and non-`CHANGES_REQUESTED`, CI `success` or `none`, `mergeable` MERGEABLE, `mergeStateStatus` not `BLOCKED` / `DIRTY` / `BEHIND`, every review body read in full, every inline comment answered with Step 7's literals — `Fixed in ` or `Declining — ` +- "Latest verdict" resolves by bot login across every commit — the poll does not bind a verdict to the head SHA, so a verdict on a superseded commit reads as current. Confirm each gating bot's latest verdict names the PR's head SHA before merging +- Re-read the gate immediately before merging — `ready` is a snapshot, and a push or review landing between the check and the merge makes it stale - A gating bot that cannot `APPROVE` posts its all-clear as `COMMENTED` — `github-actions[bot]` gets HTTP 422 from GitHub (see `rules/ci-safety.md` Superseded-Bot-Review Dismissal Carve-Out) - A human reviewer's `CHANGES_REQUESTED` overrides every bot verdict (see What Still Gates) @@ -28,23 +32,36 @@ description: A green gate is the go-ahead; pausing to ask for approval the gate - **Open the PR** — Step 1 readiness checks pass (`skills/release/SKILL.md`) ⇒ push the branch and open the PR - **Dismiss superseded bot reviews** — a gating bot's `CHANGES_REQUESTED` that the same bot's later all-clear superseded ⇒ run `skills/release/dismiss-stale-reviews.sh` (see `rules/ci-safety.md` Superseded-Bot-Review Dismissal Carve-Out) -- **Merge** — the What Counts as Approval conjunction holds ⇒ merge and clean up (`skills/release/SKILL.md` Step 7) +- **Merge** — `skills/release/SKILL.md` Step 7's preconditions hold ⇒ merge and clean up. What Counts as Approval is that same conjunction, never a subset - **Watch through publish** — the merge lands ⇒ watch the run, the registry advance, and the moderation clear per `rules/ci-safety.md` Always Watch CI. The watch is part of the merge, not a separate decision ## Asking Is the Violation +- This section governs approval questions the gate already answers, and nothing else - An ask on a green gate is a defect, not a courtesy - The ask manufactures the approval gate — an action the policy authorized becomes blocked the moment the agent surfaces it as a question - "The owner may want to weigh in" is not a reason to ask; the owner's position is the policy, already written - Report the action taken, never propose it - Never re-ask per PR what the policy grants standing +## Surfacing Is Required + +- Surface every decision the gate does not answer — this is the complement of the section above, never an exception to it +- A question outside What Counts as Approval is an absent grant, never a green one: scope, base branch, a human's prose hold, whether boy-scout work is in the task +- Re-reading this policy never resolves an absent grant — the answer is not in it +- Uncertainty about whether the rule covers an action means it does not — report and stop + ## What Still Gates - Red, absent, or ambiguous gate — fix it, or surface the specific field that is not green +- A platform-rejected merge is a red gate, never an obstacle to route around — never `--admin`, never a ruleset or branch-protection bypass, never "merge despite failing requirements". Surface the blocking rule +- An owner-approval precondition named by another always-on rule — `rules/ci-safety.md` Bootstrap-Red Carve-Out requires the repo owner's explicit approval, and no bullet in this rule retires it - An unplanned CI-config edit, even to turn a red gate green (see `rules/ci-safety.md` Hands Off CI Config) - Force-push to a shared branch, history rewrite, tag or release deletion, any action with no undo - Direct push to a protected branch outside `rules/ci-safety.md` Content-Only Direct-Push Carve-Out - A human reviewer's `CHANGES_REQUESTED` — autonomous dismissal covers bot reviews only +- A human's hold stated in prose — a `COMMENTED` review or comment asking to wait gates the merge as firmly as `CHANGES_REQUESTED`; a human review still `PENDING` gates it too +- A PR marked not-ready — draft status, a `do-not-merge` or WIP label, a title marker +- A base branch the task never named — merging a stacked or mis-based PR is not the agreed task - Action in a repo the operator does not own (see `rules/external-repo-contributions.md`) -- Scope the operator never granted — this rule governs how to ship the agreed task, never which task to take on +- Scope the operator never granted — this rule governs how to ship the agreed task, never which task to take on. Boy-scout cleanup and drive-by dependency work are new tasks, never standing ship authorization From 514f0333a96f2018f9bb60c0ad729b3162180434 Mon Sep 17 00:00:00 2001 From: Baruch Sadogursky Date: Thu, 16 Jul 2026 22:17:44 -0500 Subject: [PATCH 06/17] fix(rules): stop the rule claiming a gate the system does not check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Grok's re-review: HOLD. The fix for the weaker-conjunction hole built the same hole inverted. The rule asserted merge approval is "exactly Step 7's preconditions" and then restated a LONGER conjunction than Step 7 names — mergeStateStatus, head-SHA binding. An agent that benefits from shipping takes "exactly Step 7" literally, loads the watcher's `ready` (mergeable, CI, bot states — no mergeStateStatus, no commit identity) and merges. Claiming identity while listing a different set is worse than either half. The head-SHA clause also re-published the Post-Edit Rule Audit gap this same PR deferred one commit earlier: poll-pr-reviews.sh returns no commit_id, so the rule ordered agents to confirm a field the scripted path cannot produce. I removed that clause at gh-aw's request, then re-added it answering Grok's first review, without noticing it was the same clause. Neither reviewer saw the other's finding. I saw both. The rule now names no gate field. Step 7 holds the gate; the rule points there and says to load it before merging. Platform rejection stays gated behaviorally — a rejected merge is a red gate, --admin is banned — rather than by a field the watcher does not read. Also qualifies the boy-scout bullet: only OUT-of-scope discoveries are a new task. As written it contradicted rules/boy-scout.md, which requires in-scope cleanup to roll into the current PR. Co-Authored-By: Claude Opus 4.8 (1M context) Claude-Session: https://claude.ai/code/session_01JgdWmv7KBj91nxbVjMsj7X --- CHANGELOG.md | 2 ++ rules/autonomous-shipping.md | 10 ++++------ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 25d6cef1..e5cc4e10 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ # Changelog +- **`autonomous-shipping`: one authority for the merge gate** — the fix for the weaker-conjunction hole created the same hole inverted. The rule claimed merge approval is "exactly Step 7's preconditions" while restating a LONGER conjunction Step 7 does not name (`mergeStateStatus`, head-SHA binding of each bot's latest verdict): an agent takes the "exactly Step 7" branch, loads the watcher's `ready` — which checks `mergeable`, CI, and bot states, not `mergeStateStatus` — and ships. The head-SHA clause also re-published the Post-Edit Rule Audit gap this same PR had deferred one commit earlier, since `poll-pr-reviews.sh` returns no `commit_id`. The rule now names no gate field at all: Step 7 holds the gate, the rule points at it and says to load it. Platform rejection stays gated behaviorally (a rejected merge is a red gate; `--admin` is banned) rather than by a field the system does not check. Widening the gate to `mergeStateStatus` or head-SHA lands when the watcher and Step 7 move with it. + - **`autonomous-shipping`: hardened against the adversarial read** — an independent review (Grok, one-off) attacked the rule from the position of the agent that benefits from it and found four holes the bot fleet's conformance review does not look for. (1) The always-on conjunction was WEAKER than the `skills/release` Step 7 it pointed at — and the rule exists precisely for agents that never load that skill, so the weaker gate was the one they carried: "every inline comment answered" instead of Step 7's `Fixed in ` / `Declining — ` literals, no head-SHA binding, no re-check before merge. The gate is now Step 7's preconditions, stated once, never summarized. (2) `What Still Gates` named force-push and history rewrite as no-undo but never named platform bypass — an agent holding a standing grant could read a blocked merge as an obstacle and retry with `--admin`. Now explicitly gated, and `mergeStateStatus` joins the conjunction so `BLOCKED` is not policy-green. (3) "A merge needs no human approval" collided with `ci-safety`'s Bootstrap-Red Carve-Out, which still requires owner approval — the hole was multi-rule rationalization, not the happy path. Now qualified, with Bootstrap-Red named. (4) "Asking Is the Violation" is correct for approval questions the gate answers and dangerous outside them; an agent could refuse to surface scope, a base-branch question, or a human's prose hold. Split into `Asking Is the Violation` (approval questions only) and `Surfacing Is Required` (everything else). Also: authorization excludes every conversational turn, not merely the latest; draft status, non-merge labels, `PENDING` human reviews, prose holds, and mis-based PRs join the gates. ### Rules diff --git a/rules/autonomous-shipping.md b/rules/autonomous-shipping.md index e8318304..8c52c7ed 100644 --- a/rules/autonomous-shipping.md +++ b/rules/autonomous-shipping.md @@ -21,10 +21,8 @@ description: A green gate is the go-ahead; pausing to ask for approval the gate ## What Counts as Approval - Review in these repos is the paired bot fleet, not a human sign-off — a merge needs no human approval, except where another always-on rule names an owner-approval precondition (see What Still Gates) -- Merge approval is exactly `skills/release/SKILL.md` Step 7's preconditions — this section does not restate a shorter one, and a summary of them is never the gate -- Every gate field, all required: both gating bots' latest verdicts posted and non-`CHANGES_REQUESTED`, CI `success` or `none`, `mergeable` MERGEABLE, `mergeStateStatus` not `BLOCKED` / `DIRTY` / `BEHIND`, every review body read in full, every inline comment answered with Step 7's literals — `Fixed in ` or `Declining — ` -- "Latest verdict" resolves by bot login across every commit — the poll does not bind a verdict to the head SHA, so a verdict on a superseded commit reads as current. Confirm each gating bot's latest verdict names the PR's head SHA before merging -- Re-read the gate immediately before merging — `ready` is a snapshot, and a push or review landing between the check and the merge makes it stale +- Merge approval is exactly `skills/release/SKILL.md` Step 7's preconditions — this rule adds no field to them and subtracts none +- Load Step 7 before merging — it holds the gate, and this rule never restates it - A gating bot that cannot `APPROVE` posts its all-clear as `COMMENTED` — `github-actions[bot]` gets HTTP 422 from GitHub (see `rules/ci-safety.md` Superseded-Bot-Review Dismissal Carve-Out) - A human reviewer's `CHANGES_REQUESTED` overrides every bot verdict (see What Still Gates) @@ -47,7 +45,7 @@ description: A green gate is the go-ahead; pausing to ask for approval the gate ## Surfacing Is Required - Surface every decision the gate does not answer — this is the complement of the section above, never an exception to it -- A question outside What Counts as Approval is an absent grant, never a green one: scope, base branch, a human's prose hold, whether boy-scout work is in the task +- A question outside What Counts as Approval is an absent grant, never a green one: scope, base branch, a human's prose hold, whether an out-of-scope discovery belongs in this task - Re-reading this policy never resolves an absent grant — the answer is not in it - Uncertainty about whether the rule covers an action means it does not — report and stop @@ -64,4 +62,4 @@ description: A green gate is the go-ahead; pausing to ask for approval the gate - A PR marked not-ready — draft status, a `do-not-merge` or WIP label, a title marker - A base branch the task never named — merging a stacked or mis-based PR is not the agreed task - Action in a repo the operator does not own (see `rules/external-repo-contributions.md`) -- Scope the operator never granted — this rule governs how to ship the agreed task, never which task to take on. Boy-scout cleanup and drive-by dependency work are new tasks, never standing ship authorization +- Scope the operator never granted — this rule governs how to ship the agreed task, never which task to take on. An out-of-scope boy-scout discovery and drive-by dependency work are new tasks, never standing ship authorization (in-scope cleanup rolls into the current PR per `rules/boy-scout.md` How to Apply) From d61c6b30ec0eff493a78e5327fb71f1002b7100f Mon Sep 17 00:00:00 2001 From: Baruch Sadogursky Date: Thu, 16 Jul 2026 22:27:29 -0500 Subject: [PATCH 07/17] fix(rules): stop claiming the rule adds no gate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit gh-aw, and the third pass over this sentence: the rule asserted merge approval is "exactly Step 7 ... adds no field to them and subtracts none", while What Still Gates lists human prose holds, PENDING reviews, draft status, and base branch — none of which Step 7 or watch-pr-reviews.sh checks. Adding gates while claiming to add none is the same contradiction Grok found twice, wearing a different hat: first the conjunction was weaker than Step 7, then longer, now the claim of identity survived while the additions moved into another section. Approval and blocking are different tests, and the rule now says so: Step 7's preconditions are the approval gate; What Still Gates lists conditions that block a merge even when that gate reads green. What Still Gates also states who enforces it — the agent, before merging, since the watcher does not read draft status, labels, base branch, or a hold written in prose. Co-Authored-By: Claude Opus 4.8 (1M context) Claude-Session: https://claude.ai/code/session_01JgdWmv7KBj91nxbVjMsj7X --- rules/autonomous-shipping.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/rules/autonomous-shipping.md b/rules/autonomous-shipping.md index 8c52c7ed..52be89e1 100644 --- a/rules/autonomous-shipping.md +++ b/rules/autonomous-shipping.md @@ -21,8 +21,8 @@ description: A green gate is the go-ahead; pausing to ask for approval the gate ## What Counts as Approval - Review in these repos is the paired bot fleet, not a human sign-off — a merge needs no human approval, except where another always-on rule names an owner-approval precondition (see What Still Gates) -- Merge approval is exactly `skills/release/SKILL.md` Step 7's preconditions — this rule adds no field to them and subtracts none -- Load Step 7 before merging — it holds the gate, and this rule never restates it +- Merge approval is `skills/release/SKILL.md` Step 7's preconditions — load Step 7 before merging; this rule never restates them and never adds an approval field +- Approval is not the whole test — What Still Gates lists conditions that block a merge even when Step 7's gate reads green, and no green gate retires them - A gating bot that cannot `APPROVE` posts its all-clear as `COMMENTED` — `github-actions[bot]` gets HTTP 422 from GitHub (see `rules/ci-safety.md` Superseded-Bot-Review Dismissal Carve-Out) - A human reviewer's `CHANGES_REQUESTED` overrides every bot verdict (see What Still Gates) @@ -51,6 +51,7 @@ description: A green gate is the go-ahead; pausing to ask for approval the gate ## What Still Gates +- These block a merge even when Step 7's gate reads green. The watcher does not check them — the agent does, before merging - Red, absent, or ambiguous gate — fix it, or surface the specific field that is not green - A platform-rejected merge is a red gate, never an obstacle to route around — never `--admin`, never a ruleset or branch-protection bypass, never "merge despite failing requirements". Surface the blocking rule - An owner-approval precondition named by another always-on rule — `rules/ci-safety.md` Bootstrap-Red Carve-Out requires the repo owner's explicit approval, and no bullet in this rule retires it From e82526dd2a4ad85370a848384777063f837508ec Mon Sep 17 00:00:00 2001 From: Baruch Sadogursky Date: Thu, 16 Jul 2026 22:39:19 -0500 Subject: [PATCH 08/17] fix(rules): drop the last 'names every field' claim MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit gh-aw: line 11 still said What Counts as Approval "names every field of the merge gate" while that section now says the rule never restates them and points at Step 7. The rule contradicted itself. Fourth pass over this sentence family. Each fix moved the claim rather than removing it: weaker than Step 7 → longer than Step 7 → identity claimed while What Still Gates added blocks → a stale pointer in the Green Gate section. The through-line is that I kept wanting this rule to carry the gate for agents that never load the skill, and kept writing a copy that drifts. It does not carry the gate. Step 7 does. The rule points there and says to load it. Co-Authored-By: Claude Opus 4.8 (1M context) Claude-Session: https://claude.ai/code/session_01JgdWmv7KBj91nxbVjMsj7X --- rules/autonomous-shipping.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rules/autonomous-shipping.md b/rules/autonomous-shipping.md index 52be89e1..01057f20 100644 --- a/rules/autonomous-shipping.md +++ b/rules/autonomous-shipping.md @@ -8,7 +8,7 @@ description: A green gate is the go-ahead; pausing to ask for approval the gate ## Green Gate Is the Approval - A shipping action is the autonomous next step once its gate reads green -- A gate is a named conjunction of fields, never an impression — What Counts as Approval names every field of the merge gate +- A gate is a named conjunction of fields, never an impression — the merge gate's fields live in `skills/release/SKILL.md` Step 7 (see What Counts as Approval) - Read the gate to resolve doubt about whether it is green - Never ask the operator to resolve what reading the gate answers - Authorization to ship is standing — it lives in this policy and in the operator's own durable config, and in no conversational turn From 1266610ac8b7bcb9fa1f940a15a35ccde457ca21 Mon Sep 17 00:00:00 2001 From: Baruch Sadogursky Date: Fri, 17 Jul 2026 09:58:31 -0500 Subject: [PATCH 09/17] fix(rules): align dismiss action with ci-safety; stop counting gates MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Copilot, both correct. The Dismiss action bullet mandated dismiss-stale-reviews.sh, but ci-safety sanctions a hand dismissal meeting both preconditions. As written the two rules conflicted — one required the script, the other allowed the manual path. The bullet now names the script as recommended and the hand dismissal as equally sanctioned, matching ci-safety. The CHANGELOG said "seven surviving gates" and listed them, while What Still Gates now enumerates more (platform bypass, prose holds, draft markers, base branch). A count in the archive drifts every time the list grows. The entry now points at What Still Gates as the authoritative list instead of copying it. Co-Authored-By: Claude Opus 4.8 (1M context) Claude-Session: https://claude.ai/code/session_01JgdWmv7KBj91nxbVjMsj7X --- CHANGELOG.md | 2 +- rules/autonomous-shipping.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e5cc4e10..209c9f8e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,7 @@ ### Rules -- **`autonomous-shipping` (new, always-on)** — States that opening a PR, dismissing superseded bot reviews, merging, and watching through publish are the autonomous next step once their gate reads green, and that asking on a green gate is a defect rather than a courtesy. The autonomy statements already existed in `skills/release/SKILL.md` (Step 2 "create the PR automatically", Step 7 "merge automatically") but a skill loads only on invocation — an agent that has just finished implementing a task has never invoked the release skill, so its always-on context carried the PR mandate with no word on who authorizes opening one. Agents filled the gap by asking. Bounded by seven surviving gates (red/absent/ambiguous gate, unplanned CI-config edits, no-undo actions, protected-branch pushes, human `CHANGES_REQUESTED`, unowned repos, ungranted scope). +- **`autonomous-shipping` (new, always-on)** — States that opening a PR, dismissing superseded bot reviews, merging, and watching through publish are the autonomous next step once their gate reads green, and that asking on a green gate is a defect rather than a courtesy. The autonomy statements already existed in `skills/release/SKILL.md` (Step 2 "create the PR automatically", Step 7 "merge automatically") but a skill loads only on invocation — an agent that has just finished implementing a task has never invoked the release skill, so its always-on context carried the PR mandate with no word on who authorizes opening one. Agents filled the gap by asking. Bounded by the rule's What Still Gates section — the authoritative list; this entry does not re-enumerate it, so the two cannot drift. - **`autonomous-shipping`: What Counts as Approval** — The policy asserted "the green gate is the approval" without ever defining what the gate is made of, and was silent on the question every reader actually has: does bot review substitute for human review? `ci-safety` documents that `github-actions[bot]` cannot `APPROVE` (HTTP 422); `SKILL.md` Step 7 lists a merge conjunction; neither says whether a human must sign off. The section states the operator's position outright — review is the paired bot fleet, a merge needs no human approval — and names the conjunction. - **Commit-scoped verdicts deferred** — a first draft required each verdict to approve only the commit it reviewed (`commit_id` == head SHA). `poll-pr-reviews.sh` resolves reviews by bot login and returns `{state, submitted_at, body}` with no `commit_id`, and `watch-pr-reviews.sh` treats any non-`none` state as satisfying the bot-verdict half of `ready` — so a clean verdict on a superseded commit still passes the executable gate. Shipping the clause here would have published a rule the repo does not obey (`rules/context-artifacts.md` Post-Edit Rule Audit). It lands with the poll/watch change, not before. - **`autonomous-shipping`: authorization is standing, never inferred** — Removing the ask without supplying the grant is worse than the ask: an agent that stops asking but still needs authorization will manufacture it from the conversation. Observed in production — an agent read the operator's question "why is it my call? Is it somewhere in the rules?" (a challenge to the policy) as authorization under it, and a safety classifier correctly blocked the merge. The grant lives in this policy and the operator's durable config, never in the operator's latest message; where no standing grant covers an action the gate is absent, not green. Consumers: an always-on instruction in your own `CLAUDE.md` outranks plugin rules — an "ask before pushing" line there will defeat this rule. diff --git a/rules/autonomous-shipping.md b/rules/autonomous-shipping.md index 01057f20..79838366 100644 --- a/rules/autonomous-shipping.md +++ b/rules/autonomous-shipping.md @@ -29,7 +29,7 @@ description: A green gate is the go-ahead; pausing to ask for approval the gate ## The Autonomous Actions - **Open the PR** — Step 1 readiness checks pass (`skills/release/SKILL.md`) ⇒ push the branch and open the PR -- **Dismiss superseded bot reviews** — a gating bot's `CHANGES_REQUESTED` that the same bot's later all-clear superseded ⇒ run `skills/release/dismiss-stale-reviews.sh` (see `rules/ci-safety.md` Superseded-Bot-Review Dismissal Carve-Out) +- **Dismiss superseded bot reviews** — a gating bot's `CHANGES_REQUESTED` that the same bot's later all-clear superseded ⇒ dismiss it. `skills/release/dismiss-stale-reviews.sh` is the recommended path; a hand dismissal meeting both preconditions is equally sanctioned (see `rules/ci-safety.md` Superseded-Bot-Review Dismissal Carve-Out) - **Merge** — `skills/release/SKILL.md` Step 7's preconditions hold ⇒ merge and clean up. What Counts as Approval is that same conjunction, never a subset - **Watch through publish** — the merge lands ⇒ watch the run, the registry advance, and the moderation clear per `rules/ci-safety.md` Always Watch CI. The watch is part of the merge, not a separate decision From 59d779475b3f12e7f91c7c7a38c7abe14c2b51a8 Mon Sep 17 00:00:00 2001 From: Baruch Sadogursky Date: Fri, 17 Jul 2026 10:10:19 -0500 Subject: [PATCH 10/17] docs(changelog): consolidate the autonomous-shipping entries MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit gh-aw: two bullets sat above the `### Rules` heading and would be orphaned when the stamp step inserts the version heading — CHANGELOG Hygiene wants un-headed `### ` entry blocks at the very top. They were also a diary of my own rewrites — "one authority for the merge gate", "hardened against the adversarial read" — documenting intermediate drafts that never shipped. context-writing-style says consolidate: collapse to what NET changed. One rule bullet describing the shipped rule, plus the ci-safety pointer and the skill reference. The drafting history lives in the PR thread, not the archive. Co-Authored-By: Claude Opus 4.8 (1M context) Claude-Session: https://claude.ai/code/session_01JgdWmv7KBj91nxbVjMsj7X --- CHANGELOG.md | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 209c9f8e..05ba7f23 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,17 +1,10 @@ # Changelog -- **`autonomous-shipping`: one authority for the merge gate** — the fix for the weaker-conjunction hole created the same hole inverted. The rule claimed merge approval is "exactly Step 7's preconditions" while restating a LONGER conjunction Step 7 does not name (`mergeStateStatus`, head-SHA binding of each bot's latest verdict): an agent takes the "exactly Step 7" branch, loads the watcher's `ready` — which checks `mergeable`, CI, and bot states, not `mergeStateStatus` — and ships. The head-SHA clause also re-published the Post-Edit Rule Audit gap this same PR had deferred one commit earlier, since `poll-pr-reviews.sh` returns no `commit_id`. The rule now names no gate field at all: Step 7 holds the gate, the rule points at it and says to load it. Platform rejection stays gated behaviorally (a rejected merge is a red gate; `--admin` is banned) rather than by a field the system does not check. Widening the gate to `mergeStateStatus` or head-SHA lands when the watcher and Step 7 move with it. - -- **`autonomous-shipping`: hardened against the adversarial read** — an independent review (Grok, one-off) attacked the rule from the position of the agent that benefits from it and found four holes the bot fleet's conformance review does not look for. (1) The always-on conjunction was WEAKER than the `skills/release` Step 7 it pointed at — and the rule exists precisely for agents that never load that skill, so the weaker gate was the one they carried: "every inline comment answered" instead of Step 7's `Fixed in ` / `Declining — ` literals, no head-SHA binding, no re-check before merge. The gate is now Step 7's preconditions, stated once, never summarized. (2) `What Still Gates` named force-push and history rewrite as no-undo but never named platform bypass — an agent holding a standing grant could read a blocked merge as an obstacle and retry with `--admin`. Now explicitly gated, and `mergeStateStatus` joins the conjunction so `BLOCKED` is not policy-green. (3) "A merge needs no human approval" collided with `ci-safety`'s Bootstrap-Red Carve-Out, which still requires owner approval — the hole was multi-rule rationalization, not the happy path. Now qualified, with Bootstrap-Red named. (4) "Asking Is the Violation" is correct for approval questions the gate answers and dangerous outside them; an agent could refuse to surface scope, a base-branch question, or a human's prose hold. Split into `Asking Is the Violation` (approval questions only) and `Surfacing Is Required` (everything else). Also: authorization excludes every conversational turn, not merely the latest; draft status, non-merge labels, `PENDING` human reviews, prose holds, and mis-based PRs join the gates. - ### Rules -- **`autonomous-shipping` (new, always-on)** — States that opening a PR, dismissing superseded bot reviews, merging, and watching through publish are the autonomous next step once their gate reads green, and that asking on a green gate is a defect rather than a courtesy. The autonomy statements already existed in `skills/release/SKILL.md` (Step 2 "create the PR automatically", Step 7 "merge automatically") but a skill loads only on invocation — an agent that has just finished implementing a task has never invoked the release skill, so its always-on context carried the PR mandate with no word on who authorizes opening one. Agents filled the gap by asking. Bounded by the rule's What Still Gates section — the authoritative list; this entry does not re-enumerate it, so the two cannot drift. -- **`autonomous-shipping`: What Counts as Approval** — The policy asserted "the green gate is the approval" without ever defining what the gate is made of, and was silent on the question every reader actually has: does bot review substitute for human review? `ci-safety` documents that `github-actions[bot]` cannot `APPROVE` (HTTP 422); `SKILL.md` Step 7 lists a merge conjunction; neither says whether a human must sign off. The section states the operator's position outright — review is the paired bot fleet, a merge needs no human approval — and names the conjunction. -- **Commit-scoped verdicts deferred** — a first draft required each verdict to approve only the commit it reviewed (`commit_id` == head SHA). `poll-pr-reviews.sh` resolves reviews by bot login and returns `{state, submitted_at, body}` with no `commit_id`, and `watch-pr-reviews.sh` treats any non-`none` state as satisfying the bot-verdict half of `ready` — so a clean verdict on a superseded commit still passes the executable gate. Shipping the clause here would have published a rule the repo does not obey (`rules/context-artifacts.md` Post-Edit Rule Audit). It lands with the poll/watch change, not before. -- **`autonomous-shipping`: authorization is standing, never inferred** — Removing the ask without supplying the grant is worse than the ask: an agent that stops asking but still needs authorization will manufacture it from the conversation. Observed in production — an agent read the operator's question "why is it my call? Is it somewhere in the rules?" (a challenge to the policy) as authorization under it, and a safety classifier correctly blocked the merge. The grant lives in this policy and the operator's durable config, never in the operator's latest message; where no standing grant covers an action the gate is absent, not green. Consumers: an always-on instruction in your own `CLAUDE.md` outranks plugin rules — an "ask before pushing" line there will defeat this rule. -- **`ci-safety`: Superseded-Bot-Review Dismissal Carve-Out keeps its shape, gains an autonomy pointer** — an intermediate draft retitled the section and dropped the `Narrow exception for X.` lead, on the theory that the carve-out framing was itself what made agents ask permission for a dismissal `dismiss-stale-reviews.sh` already validates deterministically. That trades one `context-writing-style.md` violation for another: the section is still a preconditioned exception, so it still owes the prescribed carve-out shape. The framing fix belongs in `autonomous-shipping`, which now names dismissal as an autonomous action and defines approval outright — so the carve-out shape is restored and the section gains a single pointer to it. Preconditions and `GATING_BOTS` scoping unchanged throughout. -- **`release` skill Steps 2 and 7** — Reference `rules/autonomous-shipping.md` so the skill and the always-on context agree on one contract; Step 7 also names dismissal explicitly as no-ask. +- **`autonomous-shipping` (new, always-on)** — Opening a PR, dismissing superseded bot reviews, merging, and watching through publish are the autonomous next step once the gate reads green; asking on a green gate is a defect. The autonomy statements already lived in `skills/release/SKILL.md` (Step 2, Step 7), but a skill loads only on invocation — an agent that just finished a task never invoked it, so its always-on context carried the PR mandate with no word on who authorizes shipping. `What Counts as Approval` states the operator's position outright: review is the paired bot fleet, a merge needs no human approval, and the gate is exactly Step 7's preconditions (the rule points there, never restating a weaker or longer copy). `What Still Gates` is the authoritative list of what blocks a merge even on green — platform bypass (`--admin`), an owner-approval carve-out like Bootstrap-Red, a human's `CHANGES_REQUESTED` or prose hold or `PENDING` review, draft/label markers, mis-based PRs, ungranted scope. `Asking Is the Violation` covers approval questions the gate answers; `Surfacing Is Required` covers everything it does not, so refusing to surface scope or a hold is itself a defect. Authorization is standing (policy + durable config), never inferred from any conversational turn. Consumers: an always-on `CLAUDE.md` instruction outranks plugin rules — an "ask before pushing" line there defeats this rule. A commit-scoped-verdict clause (verdict must name the head SHA) is deferred until `poll-pr-reviews.sh` emits `commit_id` and the watcher enforces it. +- **`ci-safety`: Superseded-Bot-Review Dismissal Carve-Out** — gains a pointer to `autonomous-shipping` (dismissal is an autonomous action, script or hand-dismissal equally sanctioned); shape and `GATING_BOTS` scoping unchanged. +- **`release` skill Steps 2 and 7** — reference `rules/autonomous-shipping.md` so skill and always-on context agree on one contract. ## 0.3.93 — 2026-07-17 From d3e8caf8da2b049f92fd225db746981a4fe578cd Mon Sep 17 00:00:00 2001 From: Baruch Sadogursky Date: Fri, 17 Jul 2026 10:41:43 -0500 Subject: [PATCH 11/17] =?UTF-8?q?docs(rules):=20tighten=20autonomous-shipp?= =?UTF-8?q?ing=2066=E2=86=9246=20lines?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit gh-aw flagged the loaded surface against context-writing-style's ~25-40 line budget. I declined this from Copilot earlier on the multi-aspect exemption, and the exemption does apply — but a gating CHANGES_REQUESTED can't be declined the way a COMMENTED can, and the rule genuinely bloated 37→66 across the session as each adversarial round bolted on a clause. Cut the redundancy, not the coverage: - Merged "Asking Is the Violation" + "Surfacing Is Required" into one "Asking vs Surfacing" section — 11 bullets across 2 sections became 2 bullets in 1, keeping both directives. - Dropped restated lines: "Approval is not the whole test" (What Still Gates already says it), the duplicate human-CHANGES_REQUESTED bullet, "that same conjunction, never a subset" (the approval bullet says it). - Folded rationale clauses into their directives. Every gate the adversarial rounds added survives — platform bypass, Bootstrap-Red, prose holds, PENDING reviews, draft markers, base branch, standing-auth, the asking/surfacing split. 5 H2 sections, no connectives, cross-refs resolve. At 46 lines it's shorter than testing-standards and five other multi-aspect rules. Co-Authored-By: Claude Opus 4.8 (1M context) Claude-Session: https://claude.ai/code/session_01JgdWmv7KBj91nxbVjMsj7X --- rules/autonomous-shipping.md | 66 +++++++++++++----------------------- 1 file changed, 23 insertions(+), 43 deletions(-) diff --git a/rules/autonomous-shipping.md b/rules/autonomous-shipping.md index 79838366..ba08a993 100644 --- a/rules/autonomous-shipping.md +++ b/rules/autonomous-shipping.md @@ -8,59 +8,39 @@ description: A green gate is the go-ahead; pausing to ask for approval the gate ## Green Gate Is the Approval - A shipping action is the autonomous next step once its gate reads green -- A gate is a named conjunction of fields, never an impression — the merge gate's fields live in `skills/release/SKILL.md` Step 7 (see What Counts as Approval) -- Read the gate to resolve doubt about whether it is green -- Never ask the operator to resolve what reading the gate answers -- Authorization to ship is standing — it lives in this policy and in the operator's own durable config, and in no conversational turn -- Never read a challenging question, an ambiguous remark, an earlier "ship it when green", or silence as the grant -- Conversation sets the task's scope; it never supplies the grant to ship -- No standing grant covers the action — the gate is absent, not green (see What Still Gates) -- A harness gate this policy does not govern (a safety classifier, a permission prompt) is a red gate — surface it and name what it blocked -- Never re-attempt a harness-blocked action through another tool +- Read the gate to resolve doubt; never ask the operator what reading it answers +- Authorization to ship is standing — it lives in this policy and the operator's durable config, in no conversational turn. A challenging question, an ambiguous remark, an earlier "ship it when green", or silence is never the grant +- No standing grant covers the action ⇒ the gate is absent, not green (see What Still Gates) +- A harness gate this policy does not govern (safety classifier, permission prompt) is a red gate — surface what it blocked; never re-attempt through another tool ## What Counts as Approval -- Review in these repos is the paired bot fleet, not a human sign-off — a merge needs no human approval, except where another always-on rule names an owner-approval precondition (see What Still Gates) -- Merge approval is `skills/release/SKILL.md` Step 7's preconditions — load Step 7 before merging; this rule never restates them and never adds an approval field -- Approval is not the whole test — What Still Gates lists conditions that block a merge even when Step 7's gate reads green, and no green gate retires them -- A gating bot that cannot `APPROVE` posts its all-clear as `COMMENTED` — `github-actions[bot]` gets HTTP 422 from GitHub (see `rules/ci-safety.md` Superseded-Bot-Review Dismissal Carve-Out) -- A human reviewer's `CHANGES_REQUESTED` overrides every bot verdict (see What Still Gates) +- Review is the paired bot fleet, not a human sign-off — a merge needs no human approval, except where another always-on rule names an owner-approval precondition (see What Still Gates) +- Merge approval is exactly `skills/release/SKILL.md` Step 7's preconditions — load Step 7 before merging; this rule never restates them and never adds an approval field +- A gating bot that cannot `APPROVE` posts its all-clear as `COMMENTED` — `github-actions[bot]` gets HTTP 422 (see `rules/ci-safety.md` Superseded-Bot-Review Dismissal Carve-Out) ## The Autonomous Actions -- **Open the PR** — Step 1 readiness checks pass (`skills/release/SKILL.md`) ⇒ push the branch and open the PR -- **Dismiss superseded bot reviews** — a gating bot's `CHANGES_REQUESTED` that the same bot's later all-clear superseded ⇒ dismiss it. `skills/release/dismiss-stale-reviews.sh` is the recommended path; a hand dismissal meeting both preconditions is equally sanctioned (see `rules/ci-safety.md` Superseded-Bot-Review Dismissal Carve-Out) -- **Merge** — `skills/release/SKILL.md` Step 7's preconditions hold ⇒ merge and clean up. What Counts as Approval is that same conjunction, never a subset -- **Watch through publish** — the merge lands ⇒ watch the run, the registry advance, and the moderation clear per `rules/ci-safety.md` Always Watch CI. The watch is part of the merge, not a separate decision +- **Open the PR** — Step 1 readiness checks pass (`skills/release/SKILL.md`) ⇒ push and open +- **Dismiss superseded bot reviews** — a bot's `CHANGES_REQUESTED` its own later all-clear superseded ⇒ dismiss it via `skills/release/dismiss-stale-reviews.sh`, or a hand dismissal meeting both preconditions (see `rules/ci-safety.md` Superseded-Bot-Review Dismissal Carve-Out) +- **Merge** — Step 7's preconditions hold ⇒ merge and clean up +- **Watch through publish** — the merge lands ⇒ watch the run, the registry advance, the moderation clear per `rules/ci-safety.md` Always Watch CI; part of the merge, not a separate decision -## Asking Is the Violation +## Asking vs Surfacing -- This section governs approval questions the gate already answers, and nothing else -- An ask on a green gate is a defect, not a courtesy -- The ask manufactures the approval gate — an action the policy authorized becomes blocked the moment the agent surfaces it as a question -- "The owner may want to weigh in" is not a reason to ask; the owner's position is the policy, already written -- Report the action taken, never propose it -- Never re-ask per PR what the policy grants standing - -## Surfacing Is Required - -- Surface every decision the gate does not answer — this is the complement of the section above, never an exception to it -- A question outside What Counts as Approval is an absent grant, never a green one: scope, base branch, a human's prose hold, whether an out-of-scope discovery belongs in this task -- Re-reading this policy never resolves an absent grant — the answer is not in it -- Uncertainty about whether the rule covers an action means it does not — report and stop +- An ask on a green gate is a defect — the ask manufactures the very gate the policy already opened. Report the action taken, never propose it; never re-ask what the policy grants standing +- Surface every decision the gate does NOT answer — scope, base branch, a human's prose hold, whether an out-of-scope discovery belongs in the task. These are absent grants, not green ones; re-reading this policy never resolves one. Uncertainty that the rule covers an action means it does not — report and stop ## What Still Gates -- These block a merge even when Step 7's gate reads green. The watcher does not check them — the agent does, before merging -- Red, absent, or ambiguous gate — fix it, or surface the specific field that is not green -- A platform-rejected merge is a red gate, never an obstacle to route around — never `--admin`, never a ruleset or branch-protection bypass, never "merge despite failing requirements". Surface the blocking rule -- An owner-approval precondition named by another always-on rule — `rules/ci-safety.md` Bootstrap-Red Carve-Out requires the repo owner's explicit approval, and no bullet in this rule retires it -- An unplanned CI-config edit, even to turn a red gate green (see `rules/ci-safety.md` Hands Off CI Config) -- Force-push to a shared branch, history rewrite, tag or release deletion, any action with no undo +- These block a merge even when Step 7's gate reads green; the agent checks them, the watcher does not +- A platform-rejected merge — never `--admin`, never a ruleset or branch-protection bypass; surface the blocking rule +- An owner-approval precondition named by another always-on rule (`rules/ci-safety.md` Bootstrap-Red Carve-Out); no bullet here retires it +- An unplanned CI-config edit, even to turn a red gate green (`rules/ci-safety.md` Hands Off CI Config) +- Force-push, history rewrite, tag or release deletion — any action with no undo - Direct push to a protected branch outside `rules/ci-safety.md` Content-Only Direct-Push Carve-Out -- A human reviewer's `CHANGES_REQUESTED` — autonomous dismissal covers bot reviews only -- A human's hold stated in prose — a `COMMENTED` review or comment asking to wait gates the merge as firmly as `CHANGES_REQUESTED`; a human review still `PENDING` gates it too +- A human reviewer's `CHANGES_REQUESTED`, a prose hold ("wait", "I'll approve after X"), or a `PENDING` human review — autonomous dismissal covers bot reviews only - A PR marked not-ready — draft status, a `do-not-merge` or WIP label, a title marker -- A base branch the task never named — merging a stacked or mis-based PR is not the agreed task -- Action in a repo the operator does not own (see `rules/external-repo-contributions.md`) -- Scope the operator never granted — this rule governs how to ship the agreed task, never which task to take on. An out-of-scope boy-scout discovery and drive-by dependency work are new tasks, never standing ship authorization (in-scope cleanup rolls into the current PR per `rules/boy-scout.md` How to Apply) +- A base branch the task never named — a stacked or mis-based PR is not the agreed task +- A repo the operator does not own (`rules/external-repo-contributions.md`) +- Scope never granted — an out-of-scope boy-scout discovery and drive-by dependency work are new tasks, not ship authorization (in-scope cleanup rolls into the PR per `rules/boy-scout.md` How to Apply) From ca824eefd85f8def49e1b207d8435c66669898de Mon Sep 17 00:00:00 2001 From: Baruch Sadogursky Date: Fri, 17 Jul 2026 10:53:52 -0500 Subject: [PATCH 12/17] =?UTF-8?q?fix(rules):=20tell=20the=20truth=20?= =?UTF-8?q?=E2=80=94=20the=20merge=20gate=20has=20two=20halves?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit gh-aw, fourth variation of one tension: the rule claimed "merge approval is exactly Step 7" while What Still Gates lists blockers Step 7 doesn't check, and SKILL.md says merge once Step 7 holds. Three things disagreeing. Prior rounds tried weaker-than-Step-7, longer-than-Step-7, and adds-fields-while-denying-it. All were the same mistake: pretending Step 7 is the whole gate. It never was. Approval is Step 7's executable preconditions (watcher-checked) AND What Still Gates' conditions (agent-checked) — a human's prose hold, a draft marker, ungranted scope, none of which any script enforces. Stop claiming "exactly Step 7". Name both halves in What Counts as Approval, and add the What-Still-Gates half to SKILL.md Step 7's "Only proceed when" list so the skill and the rule describe the same gate. This converges by removing a false claim, not adding another clause. Co-Authored-By: Claude Opus 4.8 (1M context) Claude-Session: https://claude.ai/code/session_01JgdWmv7KBj91nxbVjMsj7X --- rules/autonomous-shipping.md | 2 +- skills/release/SKILL.md | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/rules/autonomous-shipping.md b/rules/autonomous-shipping.md index ba08a993..415de70a 100644 --- a/rules/autonomous-shipping.md +++ b/rules/autonomous-shipping.md @@ -16,7 +16,7 @@ description: A green gate is the go-ahead; pausing to ask for approval the gate ## What Counts as Approval - Review is the paired bot fleet, not a human sign-off — a merge needs no human approval, except where another always-on rule names an owner-approval precondition (see What Still Gates) -- Merge approval is exactly `skills/release/SKILL.md` Step 7's preconditions — load Step 7 before merging; this rule never restates them and never adds an approval field +- The merge gate has two halves, both required: `skills/release/SKILL.md` Step 7's executable preconditions (watcher-checked) AND every What Still Gates condition (agent-checked). Load Step 7 and confirm What Still Gates before merging; this rule restates neither - A gating bot that cannot `APPROVE` posts its all-clear as `COMMENTED` — `github-actions[bot]` gets HTTP 422 (see `rules/ci-safety.md` Superseded-Bot-Review Dismissal Carve-Out) ## The Autonomous Actions diff --git a/skills/release/SKILL.md b/skills/release/SKILL.md index 681f410d..8364b912 100644 --- a/skills/release/SKILL.md +++ b/skills/release/SKILL.md @@ -110,7 +110,8 @@ It returns the full `poll-pr-reviews.sh` snapshot plus a `watch` object — `{"r Only proceed when: - Step 5's watcher returned `.watch.result` as `ready` — its exit-0 readiness conjunction (mergeable, CI `success`/`none`, both gating bots posted, no `CHANGES_REQUESTED`); the field predicate is the watcher's, not restated here (`rules/script-as-black-box.md` — see `skills/release/watch-pr-reviews.sh` header). `ready` already requires each gating bot's `state` to have left `none`, so a reviewer that never ran cannot satisfy the gate vacuously, AND - Every non-empty `reviews.*.body` in the returned snapshot has been read in full — a `COMMENTED` state with zero inline comments is not a license to skip the body (see `rules/reviewer-feedback-reading.md`), AND -- Every inline comment from Step 5's `inline_comments` count has a `Fixed in ` or `Declining — ` reply per Step 6 (verify by listing the PR's review comments — the poll script tracks counts, not reply state, so the operator confirms thread closure). +- Every inline comment from Step 5's `inline_comments` count has a `Fixed in ` or `Declining — ` reply per Step 6 (verify by listing the PR's review comments — the poll script tracks counts, not reply state, so the operator confirms thread closure), AND +- No `rules/autonomous-shipping.md` What Still Gates condition applies — these are agent-checked, not watcher-checked (a human's prose hold or `PENDING` review, a `do-not-merge`/draft marker, a mis-based branch, an owner-approval carve-out, ungranted scope). This half of the gate is not in the `ready` conjunction; confirm it by hand before merging. A `COMMENTED` review never gates the merge on its state alone — but its body must be read before merge, zero inline comments included. With inline comments, it is mergeable once every thread also has a reply. From b889027d729964220371b68567f84ce4b0bb3cf4 Mon Sep 17 00:00:00 2001 From: Baruch Sadogursky Date: Fri, 17 Jul 2026 11:04:34 -0500 Subject: [PATCH 13/17] fix(rules): the gate needs What Still Gates ABSENT, not present MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit gh-aw: I inverted the polarity. What Still Gates is a blocker list, so the merge gate requires those conditions ABSENT — "no What Still Gates condition applies" — not "every What Still Gates condition". The rule said require-them; the skill (correctly) said require-their-absence. They disagreed. Rule now matches the skill. Co-Authored-By: Claude Opus 4.8 (1M context) Claude-Session: https://claude.ai/code/session_01JgdWmv7KBj91nxbVjMsj7X --- rules/autonomous-shipping.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rules/autonomous-shipping.md b/rules/autonomous-shipping.md index 415de70a..e28bd628 100644 --- a/rules/autonomous-shipping.md +++ b/rules/autonomous-shipping.md @@ -16,7 +16,7 @@ description: A green gate is the go-ahead; pausing to ask for approval the gate ## What Counts as Approval - Review is the paired bot fleet, not a human sign-off — a merge needs no human approval, except where another always-on rule names an owner-approval precondition (see What Still Gates) -- The merge gate has two halves, both required: `skills/release/SKILL.md` Step 7's executable preconditions (watcher-checked) AND every What Still Gates condition (agent-checked). Load Step 7 and confirm What Still Gates before merging; this rule restates neither +- The merge gate has two halves, both required: `skills/release/SKILL.md` Step 7's executable preconditions hold (watcher-checked) AND no What Still Gates condition applies (agent-checked). Load Step 7 and confirm What Still Gates before merging; this rule restates neither - A gating bot that cannot `APPROVE` posts its all-clear as `COMMENTED` — `github-actions[bot]` gets HTTP 422 (see `rules/ci-safety.md` Superseded-Bot-Review Dismissal Carve-Out) ## The Autonomous Actions From 5a830abc76a168629f957f6706a79629836c342c Mon Sep 17 00:00:00 2001 From: Baruch Sadogursky Date: Fri, 17 Jul 2026 11:20:26 -0500 Subject: [PATCH 14/17] docs(rules): cut the intensifier "very" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit gh-aw: "the very gate" — `very` is rhetorical emphasis, not a constraint, and context-writing-style bans noise intensifiers. Now "an approval gate". Co-Authored-By: Claude Opus 4.8 (1M context) Claude-Session: https://claude.ai/code/session_01JgdWmv7KBj91nxbVjMsj7X --- rules/autonomous-shipping.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rules/autonomous-shipping.md b/rules/autonomous-shipping.md index e28bd628..e1e95e05 100644 --- a/rules/autonomous-shipping.md +++ b/rules/autonomous-shipping.md @@ -28,7 +28,7 @@ description: A green gate is the go-ahead; pausing to ask for approval the gate ## Asking vs Surfacing -- An ask on a green gate is a defect — the ask manufactures the very gate the policy already opened. Report the action taken, never propose it; never re-ask what the policy grants standing +- An ask on a green gate is a defect — the ask manufactures an approval gate the policy already opened. Report the action taken, never propose it; never re-ask what the policy grants standing - Surface every decision the gate does NOT answer — scope, base branch, a human's prose hold, whether an out-of-scope discovery belongs in the task. These are absent grants, not green ones; re-reading this policy never resolves one. Uncertainty that the rule covers an action means it does not — report and stop ## What Still Gates From de448c35447cc442bec97059f21a3970b1262f35 Mon Sep 17 00:00:00 2001 From: Baruch Sadogursky Date: Fri, 17 Jul 2026 11:44:55 -0500 Subject: [PATCH 15/17] docs(rules): split non-atomic bullets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit gh-aw: the Asking vs Surfacing bullets combined multiple directives and rationale — non-atomic, against context-writing-style's "one directive per bullet". Tightening 66→46 earlier merged two sections into two dense bullets; that traded a line-budget concern for an atomicity violation (atomicity is a hard rule, line count has the multi-aspect exemption). Split Asking vs Surfacing into seven atomic bullets, and proactively split the two other bullets with the same pattern (standing-auth, two-halves gate) so each carries one directive. 51 lines — still shorter than five other multi-aspect rules. Co-Authored-By: Claude Opus 4.8 (1M context) Claude-Session: https://claude.ai/code/session_01JgdWmv7KBj91nxbVjMsj7X --- rules/autonomous-shipping.md | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/rules/autonomous-shipping.md b/rules/autonomous-shipping.md index e1e95e05..71d526e9 100644 --- a/rules/autonomous-shipping.md +++ b/rules/autonomous-shipping.md @@ -9,14 +9,16 @@ description: A green gate is the go-ahead; pausing to ask for approval the gate - A shipping action is the autonomous next step once its gate reads green - Read the gate to resolve doubt; never ask the operator what reading it answers -- Authorization to ship is standing — it lives in this policy and the operator's durable config, in no conversational turn. A challenging question, an ambiguous remark, an earlier "ship it when green", or silence is never the grant +- Authorization to ship is standing — it lives in this policy and the operator's durable config, in no conversational turn +- A challenging question, an ambiguous remark, an earlier "ship it when green", or silence is never the grant - No standing grant covers the action ⇒ the gate is absent, not green (see What Still Gates) - A harness gate this policy does not govern (safety classifier, permission prompt) is a red gate — surface what it blocked; never re-attempt through another tool ## What Counts as Approval - Review is the paired bot fleet, not a human sign-off — a merge needs no human approval, except where another always-on rule names an owner-approval precondition (see What Still Gates) -- The merge gate has two halves, both required: `skills/release/SKILL.md` Step 7's executable preconditions hold (watcher-checked) AND no What Still Gates condition applies (agent-checked). Load Step 7 and confirm What Still Gates before merging; this rule restates neither +- The merge gate has two halves, both required: `skills/release/SKILL.md` Step 7's executable preconditions hold (watcher-checked) AND no What Still Gates condition applies (agent-checked) +- Load Step 7 and confirm What Still Gates before merging; this rule restates neither - A gating bot that cannot `APPROVE` posts its all-clear as `COMMENTED` — `github-actions[bot]` gets HTTP 422 (see `rules/ci-safety.md` Superseded-Bot-Review Dismissal Carve-Out) ## The Autonomous Actions @@ -28,8 +30,13 @@ description: A green gate is the go-ahead; pausing to ask for approval the gate ## Asking vs Surfacing -- An ask on a green gate is a defect — the ask manufactures an approval gate the policy already opened. Report the action taken, never propose it; never re-ask what the policy grants standing -- Surface every decision the gate does NOT answer — scope, base branch, a human's prose hold, whether an out-of-scope discovery belongs in the task. These are absent grants, not green ones; re-reading this policy never resolves one. Uncertainty that the rule covers an action means it does not — report and stop +- An ask on a green gate is a defect +- Report the action taken, never propose it +- Never re-ask what the policy grants standing +- Surface every decision the gate does not answer: scope, base branch, a human's prose hold, whether an out-of-scope discovery belongs in the task +- A question the gate does not answer is an absent grant, not a green one +- Re-reading this policy never resolves an absent grant +- Uncertainty that the rule covers an action means it does not — report and stop ## What Still Gates From a11144a55e4e087575bca5a4116b35894ba0b50a Mon Sep 17 00:00:00 2001 From: Baruch Sadogursky Date: Fri, 17 Jul 2026 11:53:28 -0500 Subject: [PATCH 16/17] fix(rules): qualify force-push to shared history, not your own branch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit gh-aw: the rule gated "Force-push" unqualified, but SKILL.md Step 5 tells agents to rebase + force-push their own feature branch to recover a dirty branch. Contradiction. The no-undo concern is shared/protected HISTORY, not your own branch — force-pushing a feature branch to land a rebase is routine and reversible. Qualified accordingly; the skill and rule now agree. (The line-budget finding on the same review is not addressed here — it is in direct tension with last round's atomic-bullets fix and needs an operator decision; see the PR thread.) Co-Authored-By: Claude Opus 4.8 (1M context) Claude-Session: https://claude.ai/code/session_01JgdWmv7KBj91nxbVjMsj7X --- rules/autonomous-shipping.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rules/autonomous-shipping.md b/rules/autonomous-shipping.md index 71d526e9..2168441f 100644 --- a/rules/autonomous-shipping.md +++ b/rules/autonomous-shipping.md @@ -44,7 +44,7 @@ description: A green gate is the go-ahead; pausing to ask for approval the gate - A platform-rejected merge — never `--admin`, never a ruleset or branch-protection bypass; surface the blocking rule - An owner-approval precondition named by another always-on rule (`rules/ci-safety.md` Bootstrap-Red Carve-Out); no bullet here retires it - An unplanned CI-config edit, even to turn a red gate green (`rules/ci-safety.md` Hands Off CI Config) -- Force-push, history rewrite, tag or release deletion — any action with no undo +- Force-push over shared or protected history, tag or release deletion — any action with no undo. Force-pushing your own feature branch to land a rebase is routine, not gated - Direct push to a protected branch outside `rules/ci-safety.md` Content-Only Direct-Push Carve-Out - A human reviewer's `CHANGES_REQUESTED`, a prose hold ("wait", "I'll approve after X"), or a `PENDING` human review — autonomous dismissal covers bot reviews only - A PR marked not-ready — draft status, a `do-not-merge` or WIP label, a title marker From 40d4d970bbf36a0d7200761cd5c54fd883591726 Mon Sep 17 00:00:00 2001 From: Baruch Sadogursky Date: Fri, 17 Jul 2026 17:18:40 -0500 Subject: [PATCH 17/17] fix(rules): make the multi-aspect line-budget exemption countable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Operator decision on the atomic-vs-budget catch-22: amend context-writing-style at the source rather than oscillate the rule. gh-aw flagged autonomous-shipping's line count (53 > 40) one round, then its non-atomic bullets when I merged to shrink — the two style requirements can't both hold for a many-directive rule. The multi-aspect exemption existed but "may run larger" was too vague for gh-aw to apply, so it kept classifying the rule single-concept. Now countable: 4+ named H2 sub-aspect sections => multi-aspect => exempt from BOTH the line and section budgets, still owing atomic bullets and all prose discipline. Verified against the tree — every rule over 40 lines has 5-11 sections, so the criterion describes what's committed (Post-Edit Rule Audit). autonomous-shipping (5 sections) is now unambiguously exempt; atomic bullets still bind and are satisfiable. Co-Authored-By: Claude Opus 4.8 (1M context) Claude-Session: https://claude.ai/code/session_01JgdWmv7KBj91nxbVjMsj7X --- CHANGELOG.md | 1 + rules/context-writing-style.md | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 05ba7f23..94aa7890 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ### Rules +- **`context-writing-style`: make the multi-aspect budget exemption falsifiable** — the exemption existed ("rules covering several sub-aspects may run larger") but was too vague to apply consistently — a gh-aw reviewer flagged `autonomous-shipping`'s line count as a budget violation across successive rounds while it also demanded atomic bullets, an unsatisfiable pair for a rule with many directives. The exemption now has a countable criterion: a rule with 4+ named H2 sub-aspect sections is multi-aspect and exempt from BOTH the ~25-40 line and 3-6 section budgets, while still owing every non-numeric discipline (atomic bullets, connective/intensifier bans, carve-out format). Verified against the tree: all 12 rules over 40 lines have 5-11 sections, so the criterion describes what's committed. Resolves the atomic-vs-budget catch-22 for `autonomous-shipping` (5 sections) and any future multi-directive rule. - **`autonomous-shipping` (new, always-on)** — Opening a PR, dismissing superseded bot reviews, merging, and watching through publish are the autonomous next step once the gate reads green; asking on a green gate is a defect. The autonomy statements already lived in `skills/release/SKILL.md` (Step 2, Step 7), but a skill loads only on invocation — an agent that just finished a task never invoked it, so its always-on context carried the PR mandate with no word on who authorizes shipping. `What Counts as Approval` states the operator's position outright: review is the paired bot fleet, a merge needs no human approval, and the gate is exactly Step 7's preconditions (the rule points there, never restating a weaker or longer copy). `What Still Gates` is the authoritative list of what blocks a merge even on green — platform bypass (`--admin`), an owner-approval carve-out like Bootstrap-Red, a human's `CHANGES_REQUESTED` or prose hold or `PENDING` review, draft/label markers, mis-based PRs, ungranted scope. `Asking Is the Violation` covers approval questions the gate answers; `Surfacing Is Required` covers everything it does not, so refusing to surface scope or a hold is itself a defect. Authorization is standing (policy + durable config), never inferred from any conversational turn. Consumers: an always-on `CLAUDE.md` instruction outranks plugin rules — an "ask before pushing" line there defeats this rule. A commit-scoped-verdict clause (verdict must name the head SHA) is deferred until `poll-pr-reviews.sh` emits `commit_id` and the watcher enforces it. - **`ci-safety`: Superseded-Bot-Review Dismissal Carve-Out** — gains a pointer to `autonomous-shipping` (dismissal is an autonomous action, script or hand-dismissal equally sanctioned); shape and `GATING_BOTS` scoping unchanged. - **`release` skill Steps 2 and 7** — reference `rules/autonomous-shipping.md` so skill and always-on context agree on one contract. diff --git a/rules/context-writing-style.md b/rules/context-writing-style.md index 6ad6e28d..720e7828 100644 --- a/rules/context-writing-style.md +++ b/rules/context-writing-style.md @@ -15,7 +15,8 @@ description: Prose discipline for rules, skills, and READMEs — what to cut, wh - CHANGELOG entries load only on demand, not always-on - CHANGELOG entries are the archive — they carry the motivation and incident references stripped from rules, and follow looser discipline - `What to Cut` and `Structure` do not govern CHANGELOG. `What to Cut` names CHANGELOG as where the stripped explanation goes; a connective ban there would leave it nowhere to live. The rule reaches CHANGELOG only to say what belongs in it -- Line-count and section-count budgets target single-concept rules; rules that cover one coherent policy area with several sub-aspects (e.g., `plugin-evals` covering coverage/lift/persistence/naming/hygiene; `context-artifacts` covering structure/review/sync/audit; `skill-authoring` covering frontmatter/preamble/steps/calls) may run larger +- The ~25–40 line and 3–6 section budgets bind single-concept rules only. A rule with 4 or more named H2 sub-aspect sections is multi-aspect and exempt from both numeric budgets (e.g. `plugin-evals` covering coverage/lift/persistence/naming/hygiene; `context-artifacts` covering structure/review/sync/audit; `autonomous-shipping` covering green-gate/approval/actions/asking/gating) +- A multi-aspect rule still owes every non-numeric discipline in full — atomic bullets, the connective and intensifier bans, carve-out format. Exempt from the counts, never from the prose quality - Lists and quoted literals naming the forbidden terms themselves (e.g., this rule's own bullets enumerating the connectives and intensifiers) are not violations — the directive is the list, not prose use of the listed words ## What to Cut