Skip to content

fix(polecat): refuse to stamp worktree-setup persistent branch on submit#8

Open
eric-jones wants to merge 1 commit into
mainfrom
topic/polecat-refuse-stamp-setup-branch
Open

fix(polecat): refuse to stamp worktree-setup persistent branch on submit#8
eric-jones wants to merge 1 commit into
mainfrom
topic/polecat-refuse-stamp-setup-branch

Conversation

@eric-jones
Copy link
Copy Markdown
Owner

Fork-PR for review. Upstream: gastownhall#1959 WITHDRAWN 2026-05-20 (Q3 lifecycle-hook). Paired with topic/polecat-release-pool-slot. Retained on fork.

@eric-jones eric-jones force-pushed the topic/polecat-refuse-stamp-setup-branch branch from 4f21000 to 9fdfd1d Compare May 20, 2026 16:07
@eric-jones eric-jones force-pushed the topic/polecat-refuse-stamp-setup-branch branch 2 times, most recently from 57c9847 to 6c5a2b0 Compare May 22, 2026 07:32
The polecat prompt's FINAL REMINDER done sequence stamped
`branch=$(git branch --show-current)` directly into the work bead's
metadata. When the agent skipped the formula's workspace-setup step
(which would create a fresh `polecat/<issue>` feature branch), `git
branch --show-current` returned the per-slot persistent branch that
`assets/scripts/worktree-setup.sh` creates — `gc-<agent>-<hash>`,
where `<agent>` is the polecat slot name (e.g. `furiosa`) and `<hash>`
is the worktree path's git hash-object value.

That branch is shared across every polecat session that reuses the
slot. So stamping it on a work bead points the refinery at a branch
the next polecat in the slot will reuse for an unrelated bead —
producing the failure where two work beads sit in the refinery queue
pointing at the same branch, the refinery merges one (fast-forward),
the other becomes stuck-conflicted, and no polecat ever picks it up
because the slot's `git worktree list` view conflicts.

## What changed

`examples/gastown/packs/gastown/agents/polecat/prompt.template.md` —
FINAL REMINDER captures `CURRENT_BRANCH=$(git branch --show-current)`,
runs a `case "$CURRENT_BRANCH" in gc-*) ... exit 1 ;;` guard, and
stamps `--set-metadata branch="$CURRENT_BRANCH"` only after the guard
passes. The error message names the formula step that creates the
correct feature branch so the agent knows the next action.

`examples/gastown/gastown_test.go` — new
TestPolecatPromptRejectsWorktreeSetupBranchOnSubmit asserts the
chained shape (capture, case-statement guard, exit 1, then stamp from
the captured variable) and explicitly rejects the prior
`--set-metadata branch=$(git branch --show-current)` shape so
reverting the fix fails the test.

## Surface

Pack-prompt edit only (no gascity Go code touched). The bug class is
agent-behavior — instruction-shape per the maintenance-fixer
solution-shape preference. The deeper architectural shape (
worktree-setup's persistent branch surviving across pool slot reuses)
is left untouched: that branch is correct as a stable per-slot
checkout target; the bug is the polecat prompt trusting `git branch
--show-current` for bead metadata without validating it's a feature
branch.

## Out of scope

- Polecat formula `mol-polecat-work.toml` already creates the correct
  `polecat/<issue>` feature branch in workspace-setup; this PR does
  NOT modify that step. The guard catches the case where the agent
  goes straight to the prompt's done sequence without running
  workspace-setup.
- gascity#1925 (open) adds the `git branch -D "$BRANCH"` cleanup
  that runs against the same `git branch --show-current` value —
  this guard layers cleanly on top: if `$BRANCH` matched `gc-*`, the
  guard exits before cleanup, surfacing the issue rather than
  silently deleting the persistent worktree branch.
- The worktree-setup `branch_name()` function and its `gc-<agent>-<hash>`
  naming scheme are unchanged — that's the canonical worktree-branch
  contract; the fix just teaches the polecat to recognize it and
  refuse to stamp it as a feature branch.

## Testing

- `go test ./examples/gastown/...` — full scoped suite passes (146s).
- `TestPolecatPromptRejectsWorktreeSetupBranchOnSubmit` fails when
  the prompt is reverted (verified via stash + run).
- Forensic evidence: `cities/validate-l5-20260510-v3/.gc/events.jsonl`
  shows two work beads (`vl2vr-73h`, `vl2vr-gcw`) both stamped with
  `branch=gc-furiosa-14808603229f` across two polecat sessions
  (`polecat-vl2v-e1b`, `polecat-vl2v-037k`) in the same `furiosa`
  slot. The hash `14808603229f` exactly matches
  `printf '%s' '<worktree-path>' | git hash-object --stdin | cut -c1-12`
  — i.e. `worktree-setup.sh`'s `branch_name()` output for that path.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

Upstream-PR: gastownhall#1959
@eric-jones eric-jones force-pushed the topic/polecat-refuse-stamp-setup-branch branch from 6c5a2b0 to c9d81af Compare May 22, 2026 08:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant