Decision artifact2026-08-14Goal #73 · autonomy

obot.agent has no branch to open a release PR from

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.

Blocks obot.agent v0.4.0 Also affects obot.roadmap Options R1–R4 Recommendation R2 Needs a policy.json edit — carve-out, your sign-off Answer in Q&A #155

Decisions

@jwildfire · 2026-08-15 · recorded on Q&A #155

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.

Decided 2026-08-15

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.

The situation

Three sentences

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.

The precise gap

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.

What the framework currently says, and why it is now wrong

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.

The options

Four ways to close it

Ordered cheapest first. Every one of them needs your sign-off regardless, because scripts/policy.json sits inside its own carve-out.

R1 — Change the rule, not the repo

Do nothing

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.

Costs
"An RC is a PR" stops being an invariant and becomes a per-repo case. Every consumer — the wrapup's two headlines, reviews-queue, obot-merge, the RC roles memory — must handle two shapes forever, and each new consumer is a chance to handle only one.
Forecloses
Diff-level review of a release. You would keep approving obot.agent releases by reading notes, never by reading what actually changed.
v0.4.0
Ships tonight. Publish the draft as it stands.
Effort
One paragraph in rc-framework.md.

R2 — Add one lagging release branch: mainstable

Recommended

Create 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.

Costs
One extra branch and one extra merge per release. stable lags main between releases, which is the point but is a second thing to look at.
Forecloses
Nothing. It is a strict superset of today: 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.
v0.4.0
Ships as a real RC PR tonight — base 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.
Effort
~15 minutes: create the branch, add "release": ["stable"] to obot.agent's policy.json entry, open the PR, fix the rc-framework.md paragraph.
Same fix for
obot.roadmap, if and when it wants releases. Not required now.

R3 — The full safety.viz model: create dev, make it default

Bigger

Branch 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.

Costs
A default-branch switch touches things that are only findable by breaking them: 47 hard-coded 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.
Also
Twelve workspace skills are symlinks into 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.
Forecloses
Nothing permanently, but it is the option that is hardest to walk back.
v0.4.0
Same PR diff as R2, with the branch-model migration bundled in front of it — so it ships a day later, not tonight.
Effort
A half-session, plus a sweep for stale references with no test suite to back it up.

R4 — A throwaway release/vX.Y.Z base per release

Variant of R2

Same 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.

Costs
Identical review experience to R2 with more moving parts: a branch to create and delete every time, a name that changes every release, and a policy.json release array that must either be edited per release or hold a pattern the file does not currently support.
Worth stating
The intuitive form of this — cutting 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.
v0.4.0
Same as R2.
Effort
Same as R2 tonight, more every release after.
Recommendation

R2 — one branch, no migration

Recommended

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.

What unblocks on each answer

AnswerNext action, immediatelyv0.4.0 reaches you as
R2Create stable, one-line policy.json edit, open the RC PR, correct rc-framework.mdA PR you review and approve, tonight
R1Amend the roles rule in rc-framework.mdThe draft release, unchanged — publish when ready
R3Branch, switch default, repoint policy, protect main, sweep referencesA PR, after the migration lands
R4As R2, with a per-release branch nameA 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.

What this does not decide