Branch Regime Shadow Cutover Checklist
Issue: #1703.
Mode: shadow or pilot only. main remains the accepted everyday agent commit
branch until this checklist records a proceed decision.
This runbook is the proof artifact for the reversible cutover. Fill it out in a
single issue comment or release note before any global prompt, hook, or dispatch
template tells agents to ship normal work to dev.
Entry Criteria
dos.toml [branch_roles]names one development branch, one release branch, one release source, and one public front door.fak release status --jsonreports the same branch-role tuple and no unexplained promotion blockers.fak workflow-audit --write-dochas a clean audit, with every workflow branch filter classified as development, release, tag, legacy, or public-front-door.fak release ship --json --open-prdry-runs from the configured release source and reportssource_branch,source_sha,target_branch,target_sha, andtarget_ancestry.ok=true, plus the exact promotion-PR preview.- The release source SHA has a green source CI witness or the run records a hold decision.
- Forge rulesets for the pilot
devbranch are present and documented. - A named worker cohort is selected. Everyone else remains on
main.
Pilot Cohort Mechanism
The cohort selector is the per-process env opt-in FLEET_BRANCH_PILOT=1
paired with the declared dos.toml [branch_roles].pilot_development_branch.
It breaks the chicken-and-egg this gate recorded (a pilot needs workers on
dev, but splitting [branch_roles] would flip every agent in the shared
tree at once):
- The shared
development_branchnever moves — non-opted workers, hooks, CI, and dispatch keep targeting it, so there is no split-brain. - A worker launched with
FLEET_BRANCH_PILOT=1resolves its development branch to the pilot value everywherebranchrole.Loadis consumed: thefak commitOFF_TRUNK guard expects the pilot branch, thereference-transactionhook allowlists creating it, andfak release statusreportsshadow_cutover.pilot.active=true. - Opting in without a declared pilot branch is a surfaced error and falls back to the shared development branch — a mislaunched pilot worker cannot silently invent a branch.
- The pilot value may never equal the release branch; config parsing refuses it.
fak release status --json shows the lever under shadow_cutover.pilot
(declared branch, opt-in env, whether this process is active).
Execution Steps
-
Record the starting public-front-door SHA:
git ls-remote origin refs/heads/main -
Create or refresh
devfrom that exact SHA only if the branch does not already contain pilot work:git fetch origin main git push origin origin/main:refs/heads/dev -
Capture branch-role status:
fak release status --json --require-ci-green --limit-commits 50 -
Capture workflow role coverage:
fak workflow-audit --write-doc go test ./internal/workflowaudit -count=1 -
Capture release-promotion dry run from the pilot source:
fak release ship --json --open-pr --source-branch dev --trunk main --base origin/dev -
Move only the named pilot cohort to
devby launching each pilot worker withFLEET_BRANCH_PILOT=1(see Pilot Cohort Mechanism above). Record the exact prompt, dispatch packet, or account selector used. -
Require every pilot worker to ship with the usual path-scoped commit witness. Record each commit SHA and
fak commit --previewresult. -
Re-run release status and release-promotion dry run after the pilot commits.
-
Post a final #1703 decision:
proceed,hold, orbackout.
Verification Commands
Use these commands as the minimum proof bundle:
git ls-remote origin refs/heads/main refs/heads/dev
fak release status --json --require-ci-green --limit-commits 50
fak workflow-audit --write-doc
go test ./internal/workflowaudit -count=1
fak release ship --json --open-pr --source-branch dev --trunk main --base origin/dev
fak release prplan --base origin/main --head origin/dev --check
fak release prplan is the promotion-legibility artifact: it folds the
main..dev promotion range into PR units grouped by the (fak <leaf>)
ship-stamp — the “PRs managed in advance” bodies a human operator reads when
dev work ships to main. --check fails if the range holds unstamped
commits, so legibility is a gate, not a hope.
fak release ship --execute --open-pr (issue #2195) turns that fold into a
real GitHub PR at promotion time: it pushes the exact release-cut commit onto
a release-owned promotion branch (fak/release/<tag> by default) and opens or
refreshes that promotion branch -> main with the prplan body. It never uses
live dev as the PR head, so pilot workers can keep landing work on dev
while the release PR is under review. A rerun updates the same promotion branch
with --force-with-lease and refreshes the existing open PR rather than
creating a duplicate. Tag/publish then run in a separate fak release ship
once the PR is reviewed and merged. This is inert until dev and main name
distinct branch roles — the same cutover this checklist gates.
Execute-mode direct dev -> main promotion is refused unless an operator
passes --allow-direct-promotion; the default split-branch promotion path is
the PR flow above.
After merging the promotion PR, run the tag/publish phase against the release
branch itself, for example:
fak release ship --execute --source-branch main --trunk main --base origin/main
That follow-up reuses the merged VERSION/release-note cut when the tag is
missing, so it does not need a second release commit.
The proof bundle is incomplete unless it includes:
- the starting
mainSHA used to create or validatedev; - the current
devSHA; - the pilot worker cohort;
- at least one witnessed pilot commit to
dev, or an explicitholdstating why the cohort did not run; - the release-promotion
--open-prdry-run JSON containing the exactdevsource_shaand promotion PR preview; - a final decision with links to command output or attached artifacts.
Proceed Criteria
Proceed only when all of these are true:
devis protected by the intended development ruleset.- Development CI is green on the exact
devSHA being considered. - Release promotion dry-run can name and validate the exact
devsource SHA. - The pilot cohort shipped to
devwithout split-brain evidence. - No public docs or install links point users at
dev. - The backout commands below still apply without force-pushing.
Hold Criteria
Hold if any of these are true:
- branch-role status is missing, stale, or contradictory;
- workflow audit has unclassified development-path refs;
- release-promotion dry-run cannot prove source CI, target ancestry, or the promoted source range;
- any pilot worker commits ordinary work to
mainafter being moved todev; - any non-pilot worker commits ordinary work to
dev; - forge protections differ from the intended rulesets;
- the proof bundle is unavailable or only verbal.
Backout Steps
- Stop pilot dispatches and prompt changes that target
dev. - Put the pilot cohort back on the current configured development branch.
- Leave
mainuntouched as the public front door. - Do not delete, rewrite, or force-push
dev. - Record the
devSHA and decide whether to promote, merge, or abandon its pilot commits with normal source-SHA evidence. -
Re-run:
fak release status --json --require-ci-green --limit-commits 50 - Post a
backoutdecision on #1703 with the command output and next blocker.
Decision Record Template
Decision: proceed | hold | backout
main start SHA:
dev SHA:
pilot cohort:
pilot commits:
release status artifact:
workflow audit artifact:
release promotion dry-run artifact:
blockers:
next action: