Add opt-in current-checkout mode for autonomous runs#2
Conversation
|
Added a follow-up UX layer on top of the current-checkout controller mode. New slash-command skills:
Existing Validation run:
The remaining controller failure is |
quaat
left a comment
There was a problem hiding this comment.
Reviewed the current-checkout mode. Clean, well-tested, and fail-closed — approving in spirit. Three minor inline notes below; only the detached-HEAD one affects the main guard's reliability.
| worktree_mode = getattr(args, "worktree_mode", "isolated") | ||
| dirty = git(repo.canonical_root, "status", "--short", check=False).splitlines() | ||
| if worktree_mode == "current": | ||
| if repo.branch in {"main", "master"} and not getattr(args, "allow_main", False): |
There was a problem hiding this comment.
Detached HEAD bypasses this guard. repo.branch comes from git branch --show-current, which returns an empty string on a detached HEAD. So if the user is in detached-HEAD state (even sitting exactly on the tip of main), repo.branch in {"main", "master"} is False and current-checkout mode proceeds without --allow-main. Consider also refusing an empty branch name here (or explicitly documenting detached HEAD as out of scope).
| ctx_text, encoding="utf-8" | ||
| ) | ||
| worktree_mode = getattr(args, "worktree_mode", "isolated") | ||
| dirty = git(repo.canonical_root, "status", "--short", check=False).splitlines() |
There was a problem hiding this comment.
git status --short reports untracked files (??) too, so a tree that is clean except for benign untracked files will be refused below as 'not a clean working tree'. That matches the intended fail-closed posture, but the error message may surprise users who only have untracked files — worth a word in the message or docs. (Also note the docs/skills say git status --porcelain; equivalent for emptiness, just flagging the wording mismatch.)
| worktree_mode = getattr(args, "worktree_mode", "isolated") | ||
| dirty = git(repo.canonical_root, "status", "--short", check=False).splitlines() | ||
| if worktree_mode == "current": | ||
| if repo.branch in {"main", "master"} and not getattr(args, "allow_main", False): |
There was a problem hiding this comment.
Separately: --allow-main is silently ignored when --worktree-mode is isolated (no validation ties the two together). Harmless, but a no-op flag can mislead — consider warning if --allow-main is passed without --worktree-mode current.
Summary
Adds an explicit opt-in current-checkout execution mode for autonomous runs.
The existing isolated-worktree workflow remains the default. This adds a second mode for users who already created their own feature branch and want the autonomous run to operate directly in that checkout, so normal
git diff, local testing, and manual commit flow still work.What changed
controller.py init --worktree-mode isolated|currentisolatedremains the default behavior.currentuses the current project root as the run worktree.--allow-mainguard override for current-checkout mode.main/masterunless--allow-mainis passedisolatedmode.Why
The existing isolated worktree model is safe and should remain the default, but it is awkward when the user already has a prepared branch and wants to watch normal local diffs, run project-specific manual tests, and commit manually.
This mode is meant for that manual-branch workflow without weakening the default safety model.
Safety behavior
Current-checkout mode is deliberately opt-in.
It does not create
.claude/worktrees/*orworktree-*branches.It fails closed on risky starting states:
main/masterbranch unless explicitly overriddenTests
Ran:
./.venv/bin/python -m unittest tests.test_state ./.venv/bin/python -m unittest tests.test_project_layout PATH="$PWD/.venv/bin:$PATH" ./.venv/bin/python -m unittest tests.test_controllerAll passed.
Also smoke-tested current-checkout mode manually in a throwaway repository:
--worktree-mode current.claude/worktrees/*worktree was createdHEADstayed unchanged until manual commit--allow-main