| name | branch-task-sync |
| description | Detect when the current task does NOT match the current git branch, and recommend the right workspace — stay, switch branch, spawn a worktree, or reuse an existing worktree — before any code is written. Then commit, test, and open a PR. Use whenever you start a new piece of work, whenever the task description and the branch name look unrelated, whenever you realize mid-task "I'm on the wrong branch", whenever the current checkout looks contaminated by another advisor's uncommitted work, or before committing to a branch that wasn't created for THIS task. In this multi-agent repo an advisor regularly inherits a checkout left on an unrelated branch (e.g. on `fix/deploy-retry-hardening` while asked to "add a skill") with 20+ uncommitted files from someone else — committing there mixes unrelated work into another advisor's PR. Trigger at the start of every non-trivial task, and again any time the task's intent shifts. |
Branch ↔ task sync (catch the mismatch before you write)
In this repo (tomyimkc/sophia-agi) an advisor frequently inherits a checkout that is already on an unrelated branch — left there by another advisor, by a prior task, or by a re-checked-out worktree — and frequently contaminated with uncommitted work that isn't theirs. The expensive mistake is to keep coding on that branch: your commits land inside another advisor's PR, the PR title no longer matches its diff, and the human has to untangle the two threads during review.
This skill catches the mismatch before the first edit and recommends the right workspace: stay, switch branch, spawn a new worktree, or reuse an existing worktree. It is the cheap first check that sits in front of the three existing git skills. The workspace selection is grounded in the research archived in references/research.md.
When to run this skill
Run it first, before any of:
- Starting a new piece of work (a feature, a fix, a skill, a doc change)
- Realizing mid-task that the branch was made for something else
- Committing to a branch you did not create yourself this session
It is cheap (one local command, ~0.5 s, no network) and never writes anything by default. Re-run it whenever the task's intent shifts — "while I'm here let me also…" is a classic way an unrelated branch gets contaminated.
The check — run the script
python3 .agents/skills/branch-task-sync/scripts/branch_task_sync.py
With a workspace recommendation (the verdict plus a stay/switch/worktree/reuse
suggestion with exact commands):
python3 .agents/skills/branch-task-sync/scripts/branch_task_sync.py --task "add branch-task-sync skill" --select
Machine-readable, for composing into a larger flow (the recommendation is always
present in JSON as the recommend key, no flag needed):
python3 .agents/skills/branch-task-sync/scripts/branch_task_sync.py --json
python3 .agents/skills/branch-task-sync/scripts/branch_task_sync.py --task "add branch-task-sync skill"
python3 .agents/skills/branch-task-sync/scripts/branch_task_sync.py --task "..." --propose
Exit code is the branch↔task verdict:
| exit | meaning | action |
|---|
| 0 | match / safe | branch name and task agree; safe to write here |
| 1 | mismatch | STOP. Pivot to a correctly-named branch before writing (see below) |
| 2 | on main | never write directly on main; create a feature branch first |
| 3 | error | could not read git state; resolve manually |
The workspace recommendation (stay / switch / new worktree / reuse worktree) rides alongside the verdict in the output and the JSON recommend key — it does not change the exit code. This keeps the contract stable for callers that only care about match/mismatch, while --select surfaces the extra guidance.
The script is dependency-free (Python stdlib + git). It performs only reads.
What it compares
- Branch name tokens — the
/-split, kebab-cased words of the current branch (e.g. fix/deploy-retry-hardening → {fix, deploy, retry, hardening}).
- Task tokens — from (a) an explicit
--task, (b) the most recent user message in the conversation, or (c) the last commit subject on this branch as a fallback.
- Overlap — any token shared (stemmed, case-insensitive). No overlap ⇒ mismatch.
main / master is its own verdict (exit 2).
- Workspace signals (for the recommendation) — the verdict above, plus the list of existing worktrees (
git worktree list --porcelain) and whether the current tree is contaminated (any uncommitted entries from another advisor).
The token-overlap heuristic is deliberately loose: it errs toward "looks related → keep going" so it doesn't force a branch pivot on every loosely-worded task. When it says mismatch, the evidence (branch tokens vs task tokens) is printed so you can judge it.
Selecting the workspace: branch vs. worktree
Once the verdict is known, the script recommends one of four workspaces. The
decision table (research-grounded — see references/research.md
for the full reasoning and sources):
| Signal | → STAY | → SWITCH branch | → NEW worktree | → REUSE worktree |
|---|
| Tokens match & clean tree | ✅ | | | |
| Tokens match but tree contaminated by others' work | | | ✅ | |
| Mismatch, clean tree, no other worktree on this branch | | ✅ | | |
| Mismatch + current tree contaminated | | | ✅ | |
| An existing worktree's branch tokens MATCH the task | | | | ✅ (cd to it) |
| Target branch already checked out in another worktree | | ✗ (collision) | ✅ (different branch) | |
On main/master | | ✅ (never write here) | ✅ | |
| Concurrent/parallel work (long build + review) | | | ✅ | |
The two axes that dominate every row:
- Concurrent vs. serial. Switch branches for short, serial work. Spawn a worktree for concurrent work or to keep a long build alive while you context-switch. Worktrees are the only native git mechanism for two branches checked out at once.
- Contamination. A dirty tree you didn't dirty is the strongest signal to leave the current checkout alone and work in a fresh worktree off
origin/main — git add -A on a contaminated tree is how advisors stage each other's files.
When in doubt, the script biases toward worktree — this repo runs 20+ worktrees at a time and they are the dominant isolation pattern; a worktree can never collide with or contaminate another advisor's checkout the way a branch switch can.
Worktree lifecycle — avoid the footguns
When the script recommends a worktree, two rules are non-negotiable (see
references/research.md §5 for the failure modes):
- Never
rm -rf a worktree. It orphans metadata under .git/worktrees/ and
can "lock" the branch so it can't be checked out elsewhere. Always use
git worktree remove <path> (which fails safely on uncommitted changes) and
git worktree prune to clear stale refs.
- This repo uses git-crypt. A fresh worktree is not unlocked until you
run
git-crypt unlock — until then the smudge filter fails on checkout. The
script's --select output surfaces this as a note: line whenever it
recommends a worktree.
When the script says MISMATCH — pivot
Do this before writing or staging anything. The --select flag tells you
which kind of pivot (switch branch vs. new worktree) and prints the exact
commands; the steps below are the manual version.
1. Stash or leave any uncommitted work where it is
First inspect what's uncommitted. If it belongs to the current (wrong) branch's task, leave it — you'll come back. If it's yours and portable, note it. Never git add -A here: this working tree is frequently contaminated by other advisors' uncommitted changes (see git-operations). Only your own explicitly-listed files should ever move with you.
2. Pivot to the recommended workspace
The script's --select output picks one. If you're doing it by hand:
git fetch origin --prune
git checkout -b <type>/<short-slug> origin/main
git worktree add /private/tmp/<short-slug> origin/main
cd /private/tmp/<short-slug>
git checkout -b <type>/<short-slug>
git-crypt unlock
cd /private/tmp/<that-worktree>
<type> follows the repo convention: feat, fix, chore, docs, codex, claude, etc. <short-slug> is 2–4 kebab-cased words derived from the task. The script's --propose flag prints a suggestion; you still own the final name.
3. Then write, commit, test, and PR — on the right branch
The remaining lifecycle is covered by the sibling skills; this one only owns the pivot:
- After pivoting, write your changes and stage with explicit file paths only (
git add <files> — never -A/.).
- Verify
git branch --show-current and git diff --cached --stat before committing — another advisor's checkout can move under you.
- Test: run the repo's gate (
python3 tools/lint_claims.py here) plus any task-specific check. No overclaiming — never claim a skill is promoted or validated unless the gate says so.
- Push and open a PR targeting
main.
How this skill relates to the other three git skills
Four layered skills; pick by what you're about to do:
branch-task-sync (this one) — the very first check, before any edit. "Am I on the right branch for THIS task, and in the right workspace (branch vs. worktree)?".
git-operations — the situational-awareness snapshot before any git write. "Am I stale? blocked? duplicated?".
multi-agent-merge-preflight — the gate for merges / CI-fixes / "unblock #NNN".
pr-merge-verification — the discipline for reviewing/triaging a PR.
Typical flow for landing work: branch-task-sync (right branch + right workspace?) → git-operations (safe to touch git?) → write on an isolated worktree → (if merging) multi-agent-merge-preflight → (if reviewing) pr-merge-verification.
When NOT to pivot
- The current branch is the task (tokens overlap, or you created it this session for exactly this work) and the tree is clean.
- The human explicitly said "just do it here" / "commit on the current branch." Honor that, but state the branch name back so the choice is visible.
- You're inspecting or reviewing, not writing. Reads don't contaminate; only commits do.
When to stop and ask the human
This skill is about mechanics — am I on the wrong branch? is the tree contaminated? which workspace should I use? — not about any research-integrity claim. Per the repo's no-overclaim discipline: if acting on the recommendation would change what gets claimed (a status, a "validated" verdict, a RESULTS.md entry), stop and ask before acting.
If the mismatch verdict is ambiguous (e.g. the branch name is generic like chore/misc and the task could plausibly belong there), or the recommendation is torn (e.g. a matching branch exists but the tree is heavily contaminated and it's unclear whether the work is yours), surface the specific evidence — the branch tokens, the task tokens, what's uncommitted (git status --porcelain count, not contents), whose commits are already on the branch (git log --oneline -5), and which worktrees exist (git worktree list) — and let the human decide. Asking is cheaper than landing your work on someone else's PR.