Surfaced by local h5 test run (#169 follow-up).
What happened
Task spec said branch_id = fix/foo-typo-receive. After SWE returned, the actual git branch was fix/typo-foo-ts. The MCP tasks.branch_id row stays as fix/foo-typo-receive, so the push gate's tasks.branch_id ↔ git-branch lookup mismatches.
Root cause
`agents/swe.md` line 13:
```
First response: emit two tool calls in parallel — task_get(agent='swe', task_id=N) AND Bash(git worktree add -B .claude/worktrees/ HEAD)
```
The `-B ` flag in `git worktree add` creates or resets the branch. SWE picks the `` placeholder by interpreting the task spec. As a Layer-6-only (prompt-doctrine) constraint, this is unreliable — the LLM compliance ceiling we documented in ENFORCEMENT.md.
The fix
Branch authority belongs to bro. Two options:
Option A — Hook (Layer 2): A PreToolUse hook on Bash that runs before SWE's `git worktree add` call. Reads the task's `branch_id` from MCP, verifies a branch with that name exists at HEAD (creating it if necessary), then lets the call through. Or rewrites the call to drop `-B` and use the spec's branch verbatim.
Option B — Bro creates the branch pre-spawn (Layer 6 with hook backup):
- `tmb_swe-spawn-workflow` skill instructs bro to run `git branch <task.branch_id> HEAD` BEFORE spawning SWE.
- `agents/swe.md` changes the line to `Bash(git worktree add .claude/worktrees/ )` — no `-B`, no creation.
- Optional Layer-2 belt-and-suspenders: PreToolUse hook on Bash that intercepts `git worktree add` and verifies the branch already exists; deny if not.
Option B is cleaner — it makes the constraint structural rather than enforced post-hoc. SWE's tool surface ceases to include branch creation.
Impact
- Push-gate validation fails because git branch ≠ `tasks.branch_id`.
- Audit trail gets confused (the branch the task is "for" doesn't match the branch the commit lives on).
- Users have to manually `git branch -m` to fix, which itself trips the `git-guards.sh` hook (separate bug — see worktree-DB issue).
Surfaced by local h5 test run (#169 follow-up).
What happened
Task spec said
branch_id = fix/foo-typo-receive. After SWE returned, the actual git branch wasfix/typo-foo-ts. The MCPtasks.branch_idrow stays asfix/foo-typo-receive, so the push gate'stasks.branch_id↔ git-branch lookup mismatches.Root cause
`agents/swe.md` line 13:
```
First response: emit two tool calls in parallel — task_get(agent='swe', task_id=N) AND Bash(git worktree add -B .claude/worktrees/ HEAD)
```
The `-B ` flag in `git worktree add` creates or resets the branch. SWE picks the `` placeholder by interpreting the task spec. As a Layer-6-only (prompt-doctrine) constraint, this is unreliable — the LLM compliance ceiling we documented in ENFORCEMENT.md.
The fix
Branch authority belongs to bro. Two options:
Option A — Hook (Layer 2): A PreToolUse hook on Bash that runs before SWE's `git worktree add` call. Reads the task's `branch_id` from MCP, verifies a branch with that name exists at HEAD (creating it if necessary), then lets the call through. Or rewrites the call to drop `-B` and use the spec's branch verbatim.
Option B — Bro creates the branch pre-spawn (Layer 6 with hook backup):
Option B is cleaner — it makes the constraint structural rather than enforced post-hoc. SWE's tool surface ceases to include branch creation.
Impact