feat(runs): per-run base branch — composer picker, PRs target the starting branch, afk_base_branch #131
Labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Cloonar/coding-lab#131
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What to build
Record the branch a run forked from and make the whole branch lifecycle honor it. Today the base is hard-coded to
repo.DefaultBranchat four points — worktree fork (internal/instance/launch.go:98), PR-create base (internal/agentapi/handlers.go:627), merge target, and the teardown merged-check (internal/gitx/worktree.go:98) — and the run row never records what it started from.End-to-end behavior:
runs.base_branchcolumn (migration), snapshotted at spawn viaLaunchSpec/instance.Launch. Existing rows without a value are treated asrepo.DefaultBranch.GET /api/v1/repos/{id}/branchesdoes a best-effort fetch on the bare mirror, then lists origin branches (default branch first).web/src/routes/NewRun.tsx): base-branch selection lives in the…popover, offering all remote branches (managedlab//afk/branches included — stacking on an unmerged agent branch is supported), default branch preselected. A non-default choice is promoted to a removable chip in the composer row. The selection is never sticky: it resets on composer load and on repo switch.StartParamsgains the base field;AddWorktree's fail-loud fetch oforigin/<base>remains the final validator.labctl pr createuses the run'sbase_branchinstead ofrepo.DefaultBranch; merges then land on the starting branch automatically since forge and builtin both merge into the PR/CR's stored base.origin/<base>no longer exists at PR-create or merged-check time (e.g. a stacked parent was merged with delete-on-merge), fall back torepo.DefaultBranchand note the retarget in the PR body. Merged-checks in teardown/reaper/sweep consult the recorded base with the same fallback.afk_base_branchrepo setting (empty =DefaultBranch), edited in RepoSettings beside the AFK branch pattern; AFK launches record it as the run's base.DefaultBranchkeeps meaning "the forge's real default" — it stays the delete-safety guard and the vanished-base fallback.Verification item (do first, document the result in this issue): confirm on the pinned Forgejo version what happens to an already-open PR whose base branch is deleted (Gitea-lineage forges retarget child PRs to the deleted branch's own base) — this decides whether the post-create vanish case needs any code beyond the PR-create fallback.
Out of scope: per-issue base overrides for AFK; pre-biasing the composer picker from
afk_base_branch.Acceptance criteria
runs.base_branchrecorded at spawn for manual and AFK runs; absent value falls back torepo.DefaultBrancheverywhereGET /repos/{id}/brancheslists remote branches after a best-effort fetch…popover; non-default base shows as a removable chip; selection resets per load and on repo switchorigin/<selected base>; spawn fails loud if the branch vanishedlabctl pr createtargets the recorded base; vanished base → default branch with a note in the PR bodyafk_base_branchrepo setting surfaced in RepoSettings; AFK runs fork from and target itBlocked by
None - can start immediately (interacts with #130 only at the vanished-base fallback, which is safe to build regardless)