fix(done): get issue ID from agent hook and detect integration branches (#411) (#453)

Branch names like "polecat/furiosa-mkb0vq9f" don't contain the actual
issue ID, causing gt done to incorrectly parse "furiosa-mkb0vq9f" as the
issue. This broke integration branch auto-detection since the wrong issue
was used for parent epic lookup.

Changes:
- After parsing branch name, check the agent's hook_bead field which
  contains the actual issue ID (e.g., "gt-845.1")
- Fix parseBranchName to not extract fake issue IDs from modern polecat branches
- Fix detectIntegrationBranch to traverse full parent chain (molecule → bug → epic)
- Include issue ID in polecat branch names when HookBead is set

Added tests covering:
- Agent hook returns correct issue ID
- Modern polecat branch format parsing
- Integration branch detection through parent chain

Fixes #411

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Julian Knutsen
2026-01-16 19:40:18 +00:00
committed by GitHub
parent 8332a719ab
commit e5aea04fa1
5 changed files with 220 additions and 51 deletions

View File

@@ -215,6 +215,16 @@ func runDone(cmd *cobra.Command, args []string) error {
agentBeadID = getAgentBeadID(ctx)
}
// If issue ID not set by flag or branch name, try agent's hook_bead.
// This handles cases where branch name doesn't contain issue ID
// (e.g., "polecat/furiosa-mkb0vq9f" doesn't have the actual issue).
if issueID == "" && agentBeadID != "" {
bd := beads.New(beads.ResolveBeadsDir(cwd))
if hookIssue := getIssueFromAgentHook(bd, agentBeadID); hookIssue != "" {
issueID = hookIssue
}
}
// Get configured default branch for this rig
defaultBranch := "main" // fallback
if rigCfg, err := rig.LoadRigConfig(filepath.Join(townRoot, rigName)); err == nil && rigCfg.DefaultBranch != "" {
@@ -617,6 +627,21 @@ func updateAgentStateOnDone(cwd, townRoot, exitType, _ string) { // issueID unus
}
}
// getIssueFromAgentHook retrieves the issue ID from an agent's hook_bead field.
// This is the authoritative source for what work a polecat is doing, since branch
// names may not contain the issue ID (e.g., "polecat/furiosa-mkb0vq9f").
// Returns empty string if agent doesn't exist or has no hook.
func getIssueFromAgentHook(bd *beads.Beads, agentBeadID string) string {
if agentBeadID == "" {
return ""
}
agentBead, err := bd.Show(agentBeadID)
if err != nil {
return ""
}
return agentBead.HookBead
}
// getDispatcherFromBead retrieves the dispatcher agent ID from the bead's attachment fields.
// Returns empty string if no dispatcher is recorded.
func getDispatcherFromBead(cwd, issueID string) string {