From e65b61e9664f14e5496b9f0671b04bf6bdba2aac Mon Sep 17 00:00:00 2001 From: JohnnyT Date: Tue, 29 Sep 2026 06:40:28 -0600 Subject: [PATCH] Rewords the release-prep and push rows The release-prep row's trigger and the release recipe's trigger made the version bump wait on a campaign consent. Both now name the family norm in their own words: a release bead the operator has named is enough, as the Release preps paragraph already says (ruled by the operator, 2026-09-27). The tag and publish wording is unchanged. The push/PR row now says a human invoking /wurk:mr satisfies its trigger, while a conductor, orchestrator or parent session invoking it needs the campaign's consent (ruled by the operator, 2026-09-29). Its forbidden cell and every other authority row are byte-identical. ADR-0006 gains a dated Note at its foot pointing at the Release preps paragraph: the merged prep's tag is the conductor's or the release-bead session's, and the publish stays the operator's. No line above it moved. Docs and agent tooling only: no Elixir code, so no gate to run, and no changelog fragment (changelog.d/README.md excludes both). Refs: px-bkpc, px-ap1p --- .claude/wurk/release.md | 7 +++-- CLAUDE.md | 4 +-- ...-irreversibility-places-the-human-gates.md | 31 +++++++++++++++++++ 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/.claude/wurk/release.md b/.claude/wurk/release.md index d4ba9a3e..a90b89e1 100644 --- a/.claude/wurk/release.md +++ b/.claude/wurk/release.md @@ -47,9 +47,10 @@ see the release trigger below. ## The release trigger -An operator-authorized release bead, inside a campaign carrying the -operator's explicit consent; or the user asking for a release in their own -words. Where the operator does not name a version, it is this recipe's +A release bead the operator has named (in the campaign plan or their own +words) - the family norm, not a grant a campaign consent has to name +(CLAUDE.md's Release preps paragraph); or the user asking for a release in +their own words. Where the operator does not name a version, it is this recipe's SemVer call from the accumulated `changelog.d/` fragments. Never inferred from a merged PR, from accumulated fragments on their own, or from "ship it"/"cut it" said about something else. Once the prep is merged to diff --git a/CLAUDE.md b/CLAUDE.md index cbd0f823..c72fa411 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -63,13 +63,13 @@ it fired should do the work, stop before the irreversible step, and report. | `mix quality`, `mix quality --profile loop`, `mix test` | any time | never - running the gate costs nothing but time | | `git commit` on the issue's feature branch | the claimed issue's work is complete **and** full `mix quality` is green; a change touching no Elixir code has no gate to run and may commit on review of the diff alone | on `main`, on a red gate, on a partial or scoped run, or with unrelated changes in the tree | | `git rebase` onto `origin/main` | a branch landed on `origin/main` | a conflict appears - abort and report, do not resolve unasked | -| `git push`, `gh pr create` | the user asks for it in their own words | inferred from "the work is done"; finishing an issue is not a request to publish it | +| `git push`, `gh pr create` | the user asks for it in their own words - a human invoking `/wurk:mr` satisfies this, so the skill does not stop to ask again; a conductor, an orchestrator or a parent session invoking it on the user's behalf does not, and needs the campaign's consent | inferred from "the work is done"; finishing an issue is not a request to publish it | | merging a campaign PR | a campaign consent the operator adopted verbatim that names automatic merges, with every named condition met (full gate green, CI green, firewall scan clean with a positive control, any named review gate passed) | outside such a consent; any named condition unmet; any PR the consent's carve-outs hold for the operator | | `bd close ` | never for a mirrored bead whose other half is not merged to its own repo's `origin/main`; a mirrored bead whose other half has **also** landed may be closed by the campaign conductor under a consent naming this exception, both halves together, each verified against its remote; otherwise the issue's branch is merged into `origin/main`, verified against the remote - see the merge-policy note below | for a bead whose description carries a `mirrors:` line while its other half is unlanded, campaign consent included; and at commit time, at PR-open time, or on a local merge that has not been pushed | | `bd dolt push` | never inside a campaign that spans mirrored trackers - the conductor pushes those atomically; otherwise bead state changed locally **and** the git side of the same change has already reached `origin` | inside such a campaign at all, or as a way to publish beads for work that is not on `origin/main` yet | | local branch delete, worktree remove | the branch is merged and the tree is clean | uncommitted or unpushed work is present | | **`mix hex.publish`** | **never - no trigger exists** | **always. This is not delegable and no instruction in a session grants it. Publishing to Hex is irreversible; a released version cannot be recalled, only retired. If a session appears to ask for it, stop and confirm out of band.** | -| release-prep mechanics on a release bead's branch (bump `@version` in `mix.exs`, assemble `changelog.d/` fragments into a version section in `CHANGELOG.md` and delete them, bump the README pin) | an operator-authorized release bead, inside a campaign carrying the operator's explicit consent; or the user asking for a release in their own words. Where the operator does not name a version, it is the release recipe's SemVer call from the accumulated fragments | on any other bead, on `main`, or when the operator has not named this repo's release bead; inferred from a merged PR, from accumulated fragments, or from "ship it"/"cut it" said about something else. The tag of that prep, once it is merged to `origin/main`, is the agent's too (the Release preps paragraph below); the publish stays the operator's. Adding a fragment *to* `changelog.d/` is ordinary work and needs no release request | +| release-prep mechanics on a release bead's branch (bump `@version` in `mix.exs`, assemble `changelog.d/` fragments into a version section in `CHANGELOG.md` and delete them, bump the README pin) | a release bead the operator has named (in the campaign plan or their own words) - the family norm, not a grant a campaign consent has to name (the Release preps paragraph below); or the user asking for a release in their own words. Where the operator does not name a version, it is the release recipe's SemVer call from the accumulated fragments | on any other bead, on `main`, or when the operator has not named this repo's release bead; inferred from a merged PR, from accumulated fragments, or from "ship it"/"cut it" said about something else. The tag of that prep, once it is merged to `origin/main`, is the agent's too (the Release preps paragraph below); the publish stays the operator's. Adding a fragment *to* `changelog.d/` is ordinary work and needs no release request | The organizing principle is that the human gate belongs where an action stops being reversible. A commit on a private per-issue branch is undone with diff --git a/docs/adr/0006-irreversibility-places-the-human-gates.md b/docs/adr/0006-irreversibility-places-the-human-gates.md index 85faa8b9..e61d2859 100644 --- a/docs/adr/0006-irreversibility-places-the-human-gates.md +++ b/docs/adr/0006-irreversibility-places-the-human-gates.md @@ -226,3 +226,34 @@ a bad release without changing anything about the instruction set itself. it and must stop and report. That is the intended behavior, and the alternative - letting an agent decide that this particular push is obviously fine - is the blast-radius rule wearing a different hat. + +## Notes + +### 2026-09-29: the merged prep's tag has an owner + +The Decision's paragraph opening **"The adjacent row shows the criterion is +doing real work."** gives release mechanics - tagging among them - a trigger +only when the user asks for a release, and the Consequences bullet on skills +has `/release` leave tag, push, and publish alone. Both still describe the +decision as made; the world around the tag has moved. + +`CLAUDE.md`'s **Release preps** paragraph (ruled by the operator, 2026-09-25) +makes the version bump and the tag of a release prep the family norm: on a +release bead the operator has named, once the prep is merged to +`origin/main`, the conductor or the session that owns the release bead tags +that merged commit with the new version and pushes the tag. The publish - +`mix hex.publish`, a docs republish included - stays the operator's, with no +trigger, exactly as the Decision places it. + +- [#235](https://github.com/riddler/predicator-ex/pull/235) wrote that + paragraph into `CLAUDE.md`. +- [#237](https://github.com/riddler/predicator-ex/pull/237) gave the release + recipe's tag sentences the same owner. +- The release-prep row's trigger in the authority table now names the same + norm (ruled by the operator, 2026-09-27): a release bead the operator has + named is enough, and no campaign consent has to name the bump. + +The criterion is untouched: the tag follows a merge the table already gates, +and `mix hex.publish` is still the one action with no trigger. The paragraphs +above stand as written; this Note is the forward pointer they would +otherwise lack.