You set the rule tonight that a release candidate is a PR — assignee obotclaw[bot], reviewer @jwildfire, review formally requested — and that only RCs reach your queue. obot.agent cannot satisfy it: its integration branch is main, so work merges straight there and nothing is left to propose. The v0.4.0 draft release is the framework's own documented workaround for that, and you are right that it is not an RC.
R2 accepted — obot.agent gets a release branch, so a release there is a real pull request with a diff, a reviewer and a merge gate, like every other repo we own.
He set the governing principle alongside it: repos that run the program are operational and merge on their own lane, while anything clinical stays behind his review. Implemented the same night — the stable branch was cut at v0.3.0, the merge policy learned it, the framework doc was corrected, and v0.4.0 shipped as a real release pull request. His words are on the thread; this entry is a summary of them, not a quotation.
R2 accepted by @jwildfire — decision record in Q&A #155, alongside the operational-vs-clinical governing principle.
Implemented the same night: stable cut at v0.3.0, policy.json gains "release": ["stable"], rc-framework.md corrected, and v0.4.0 proposed as a real main → stable RC PR.
Every other releasing repo we own has two branches — work lands on dev, releases are proposed to main — so a release is naturally a PR with a diff, a reviewer and a merge gate. obot.agent and obot.roadmap have one branch each: policy.json records both as {"integration": "main", "release": []}, meaning no branch holds the release role at all. With nothing to merge into, a release there can only be a GitHub draft release, which has no assignee, no reviewer, no review request and no diff — none of the five things that make an RC reviewable.
A release PR's diff is "everything since the last tag." For that to exist, the PR's base must be a branch sitting at the last release.
obot.agent has no such branch. That is the whole problem, and it is one branch wide — not a repo-model problem, unless we choose to make it one.
docs/rc-framework.md (merged tonight as oa#83) already anticipated this and answered it:
### Repos where integration *is* the release branch obot.agent, obot.roadmap and demo-301 have no `dev`. There, the RC is a **draft GitHub release** — same notes, same demo link, same ask — proposed against the accumulated `main`, rather than a `dev -> main` PR.
The v0.4.0 draft therefore follows the written framework exactly. What changed is the roles rule, set after that paragraph was written: an RC carries obotclaw[bot] as assignee and you as requested reviewer, the way sv#124 did. A draft release cannot carry either. Two documents merged on the same night now contradict each other, and this artifact exists to pick which one gives way.
Aside, same doc: line 26 lists demo-301's release branch as site, while line 80 lists demo-301 among the repos that have none. Whichever option you pick, that line needs correcting.
Ordered cheapest first. Every one of them needs your sign-off regardless, because scripts/policy.json sits inside its own carve-out.
Amend the roles rule so that a draft GitHub release is an accepted RC vehicle for single-branch repos, and give it the closest available substitutes: a hub issue standing in for the review request, and the wrapup's 🚦 list as the queue.
reviews-queue, obot-merge, the RC roles memory — must handle two shapes forever, and each new consumer is a chance to handle only one.rc-framework.md.main → stableCreate stable once, at the commit tagged v0.3.0. Work keeps landing on main exactly as it does today. Each release is a main → stable PR whose diff is precisely the release window; it takes the RC roles, merges on the attested lane, and the tag lands on stable. policy.json already supports this shape — it is demo-301's shape (integration: main, release: ["site"]) — so the change is one array in one file.
stable lags main between releases, which is the point but is a second thing to look at.main keeps its name, its role, its default status and its URLs. R3 remains available later if the two-branch bookkeeping ever earns its keep.stable, head main, diff = the 21 merged PRs, body = the NEWS.md section, demo page linked, roles applied. Then tag v0.4.0 on stable."release": ["stable"] to obot.agent's policy.json entry, open the PR, fix the rc-framework.md paragraph.dev, make it defaultBranch dev from main, switch the repository's default branch to it, repoint policy.json to {"integration": "dev", "release": ["main"]}, and protect main. Releases become dev → main PRs, identical in shape to safety.viz.
obot.agent/blob/main links across 40 files in this repo and the hub silently change meaning from "current" to "last released"; 21 existing feature branches are based on main; the installer, the AGENTS.md worktree recipe (origin/{base}) and the spawn docs all name branches. There is no CI in this repo at all — no workflows, no package.json — so nothing catches a stale reference.obot.agent/skills/, so the branch this clone sits on is the code every session in the workspace actually runs. That is survivable either way, but it means the choice of default branch is also a choice about which code your sessions execute.release/vX.Y.Z base per releaseSame mechanic as R2, but instead of one permanent stable, cut a fresh release/v0.4.0 at the previous tag for each release, PR main into it, tag, and delete it.
policy.json release array that must either be edited per release or hold a pattern the file does not currently support.release/v0.4.0 from main and PR-ing it back to main — produces an empty diff, because the branch and its base are the same commit. Whichever way it is arranged, the base has to be a branch that lags. That is R2.Create stable at v0.3.0 and release by main → stable PR.
It is the only option that satisfies the rule you set without changing anything about how obot.agent is worked on today. It needs one array edited in one file, it reuses a shape policy.json already models and demo-301 already runs, it leaves all 47 blob/main links meaning what they mean now, and it strands none of the 21 live branches. R3 buys symmetry with safety.viz and nothing else that R2 does not already give you — and it is the option that costs a day and a reference sweep in a repo with no CI to catch what the sweep misses.
| Answer | Next action, immediately | v0.4.0 reaches you as |
|---|---|---|
| R2 | Create stable, one-line policy.json edit, open the RC PR, correct rc-framework.md | A PR you review and approve, tonight |
| R1 | Amend the roles rule in rc-framework.md | The draft release, unchanged — publish when ready |
| R3 | Branch, switch default, repoint policy, protect main, sweep references | A PR, after the migration lands |
| R4 | As R2, with a per-release branch name | A PR you review and approve, tonight |
Until you answer, v0.4.0 stays an unpublished draft. Its notes, its demo page and its diff are all ready — NEWS.md is written and the demo page is live and covers all five areas. Only the vehicle is undecided. Handing it to you as "an RC" before that is settled would repeat exactly the mistake you corrected tonight.