Skip to content

Commit 56f2675

Browse files
NagyViktNagyVikt
andauthored
fix(guardex): auto-stash dirty primary on branch-switch (#417)
Previously the post-checkout guard only reverted a primary-tree switch back to the protected branch when the working tree was clean. A dirty tree caused the guard to print "auto-revert skipped" and silently leave the primary checkout on the agent branch - the exact symptom that flips local main to an agent/* worktree branch. - templates/githooks/post-checkout: stash dirty worktree as `guardex-auto-revert <ts> <prev>-><new>` (include untracked) before reverting; primary always ends up back on the protected branch in an agent session. Fallback message only fires when stash itself fails. - AGENTS.md + templates/AGENTS.multiagent-safety.md: promote the primary-tree lock to an explicit blocking rule enumerating every disallowed command (git checkout/switch/checkout -b/switch -c/worktree add onto an existing agent branch) and add a dirty-tree rule that points at the new auto-stash safety net without making it a workflow. Co-authored-by: NagyVikt <nagy.viktordp@gmail.com>
1 parent 0e9131b commit 56f2675

3 files changed

Lines changed: 18 additions & 4 deletions

File tree

AGENTS.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -382,10 +382,14 @@ Default: less word, same proof.
382382
- Auto-clarity wins: switch back to `lite` or normal wording for security warnings, irreversible actions, privacy/compliance notes, ordered instructions where fragments may confuse, or when the user is confused and needs more detail.
383383
- Boundaries stay normal/exact for code, commits, PR text, specs, logs, and blocker evidence.
384384

385-
**Isolation.** Every task runs on a dedicated `agent/*` branch + worktree. Start with `gx branch start "<task>" "<agent-name>"`. Treat the base branch (`main`/`dev`) as read-only while an agent branch is active. Never `git checkout <branch>` on a primary working tree (including nested repos); use `git worktree add` instead. The `.githooks/post-checkout` hook auto-reverts primary-branch switches during agent sessions - bypass only with `GUARDEX_ALLOW_PRIMARY_BRANCH_SWITCH=1`.
385+
**Isolation.** Every task runs on a dedicated `agent/*` branch + worktree. Start with `gx branch start "<task>" "<agent-name>"`. Treat the base branch (`main`/`dev`) as read-only while an agent branch is active. The `.githooks/post-checkout` hook auto-reverts primary-branch switches during agent sessions and auto-stashes a dirty tree before reverting - bypass only with `GUARDEX_ALLOW_PRIMARY_BRANCH_SWITCH=1`.
386386
For every new task, including follow-up work in the same chat/session, if an assigned agent sub-branch/worktree is already open, continue in that sub-branch instead of creating a fresh lane unless the user explicitly redirects scope.
387387
Never implement directly on the local/base branch checkout; keep it unchanged and perform all edits in the agent sub-branch/worktree.
388388

389+
**Primary-tree lock (blocking).** On the primary checkout, do NOT run any of: `git checkout <ref>`, `git switch <ref>`, `git switch -c ...`, `git checkout -b ...`, or `git worktree add <path> <existing-agent-branch>`. The only branch-changing commands allowed on primary are `git fetch` and `git pull --ff-only` against the protected branch itself. To work on any `agent/*` branch, run `gx branch start ...` first, then `cd` into the printed `.omc/agent-worktrees/...` path and run every subsequent git command from inside that worktree. If you find yourself typing `git checkout agent/...` or `git switch agent/...` from the primary cwd, stop - that is the mistake that flips primary onto an agent branch.
390+
391+
**Dirty-tree rule.** Finish or stash edits inside the worktree they belong to before any branch switch on primary. The post-checkout guard auto-stashes a dirty primary tree as `guardex-auto-revert <ts> <prev>-><new>` before reverting, but that is a safety net, not a workflow; do not rely on it routinely. Recover stashed changes with `git stash list | grep 'guardex-auto-revert'`.
392+
389393
**Ownership.** Before editing, claim files: `gx locks claim --branch "<agent-branch>" <file...>`. Before deleting, confirm the path is in your claim. Don't edit outside your scope unless reassigned.
390394

391395
**Handoff gate.** Post a one-line handoff note (plan/change, owned scope, intended action) before editing. Re-read the latest handoffs before replacing others' code.

templates/AGENTS.multiagent-safety.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,14 @@ Default: less word, same proof.
3636
- Auto-clarity wins: switch back to `lite` or normal wording for security warnings, irreversible actions, privacy/compliance notes, ordered instructions where fragments may confuse, or when the user is confused and needs more detail.
3737
- Boundaries stay normal/exact for code, commits, PR text, specs, logs, and blocker evidence.
3838

39-
**Isolation.** Every task runs on a dedicated `agent/*` branch + worktree. Start with `gx branch start "<task>" "<agent-name>"`. Treat the base branch (`main`/`dev`) as read-only while an agent branch is active. Never `git checkout <branch>` on a primary working tree (including nested repos); use `git worktree add` instead. The `.githooks/post-checkout` hook auto-reverts primary-branch switches during agent sessions - bypass only with `GUARDEX_ALLOW_PRIMARY_BRANCH_SWITCH=1`.
39+
**Isolation.** Every task runs on a dedicated `agent/*` branch + worktree. Start with `gx branch start "<task>" "<agent-name>"`. Treat the base branch (`main`/`dev`) as read-only while an agent branch is active. The `.githooks/post-checkout` hook auto-reverts primary-branch switches during agent sessions and auto-stashes a dirty tree before reverting - bypass only with `GUARDEX_ALLOW_PRIMARY_BRANCH_SWITCH=1`.
4040
For every new task, including follow-up work in the same chat/session, if an assigned agent sub-branch/worktree is already open, continue in that sub-branch instead of creating a fresh lane unless the user explicitly redirects scope.
4141
Never implement directly on the local/base branch checkout; keep it unchanged and perform all edits in the agent sub-branch/worktree.
4242

43+
**Primary-tree lock (blocking).** On the primary checkout, do NOT run any of: `git checkout <ref>`, `git switch <ref>`, `git switch -c ...`, `git checkout -b ...`, or `git worktree add <path> <existing-agent-branch>`. The only branch-changing commands allowed on primary are `git fetch` and `git pull --ff-only` against the protected branch itself. To work on any `agent/*` branch, run `gx branch start ...` first, then `cd` into the printed `.omc/agent-worktrees/...` path and run every subsequent git command from inside that worktree. If you find yourself typing `git checkout agent/...` or `git switch agent/...` from the primary cwd, stop - that is the mistake that flips primary onto an agent branch.
44+
45+
**Dirty-tree rule.** Finish or stash edits inside the worktree they belong to before any branch switch on primary. The post-checkout guard auto-stashes a dirty primary tree as `guardex-auto-revert <ts> <prev>-><new>` before reverting, but that is a safety net, not a workflow; do not rely on it routinely. Recover stashed changes with `git stash list | grep 'guardex-auto-revert'`.
46+
4347
**Ownership.** Before editing, claim files: `gx locks claim --branch "<agent-branch>" <file...>`. Before deleting, confirm the path is in your claim. Don't edit outside your scope unless reassigned.
4448

4549
**Handoff gate.** Post a one-line handoff note (plan/change, owned scope, intended action) before editing. Re-read the latest handoffs before replacing others' code.

templates/githooks/post-checkout

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,14 @@ if [[ "$is_agent" == "1" ]]; then
7373
GUARDEX_ALLOW_PRIMARY_BRANCH_SWITCH=1 git checkout "$prev_branch" >/dev/null 2>&1 || true
7474
echo "[agent-primary-branch-guard] Reverted to '$prev_branch'." >&2
7575
else
76-
echo "[agent-primary-branch-guard] Working tree dirty — auto-revert skipped." >&2
77-
echo "[agent-primary-branch-guard] Fix manually: git stash && git checkout $prev_branch" >&2
76+
stash_msg="guardex-auto-revert $(date +%s) ${prev_branch}->${new_branch}"
77+
if git stash push --include-untracked -m "$stash_msg" >/dev/null 2>&1; then
78+
GUARDEX_ALLOW_PRIMARY_BRANCH_SWITCH=1 git checkout "$prev_branch" >/dev/null 2>&1 || true
79+
echo "[agent-primary-branch-guard] Dirty tree auto-stashed as '$stash_msg'; primary reverted to '$prev_branch'." >&2
80+
echo "[agent-primary-branch-guard] Restore later with: git stash list | grep 'guardex-auto-revert'" >&2
81+
else
82+
echo "[agent-primary-branch-guard] Auto-stash failed; working tree left on '$new_branch'. Fix manually: git stash -u && git checkout $prev_branch" >&2
83+
fi
7884
fi
7985
else
8086
echo "[agent-primary-branch-guard] Bypass with GUARDEX_ALLOW_PRIMARY_BRANCH_SWITCH=1 if intentional." >&2

0 commit comments

Comments
 (0)