diff --git a/docs/escalation.md b/docs/escalation.md index 2944ca4e..54a17ad4 100644 --- a/docs/escalation.md +++ b/docs/escalation.md @@ -225,7 +225,7 @@ EOF gt escalate --type decision --issue $ISSUE "Caching approach needs decision" # 3. Exit cleanly -gt done --exit ESCALATED +gt done --status ESCALATED ``` ## Mayor Startup Check diff --git a/internal/cmd/done.go b/internal/cmd/done.go index 5bfd7c9d..a44724e7 100644 --- a/internal/cmd/done.go +++ b/internal/cmd/done.go @@ -24,24 +24,27 @@ This is a convenience command for polecats that: 1. Submits the current branch to the merge queue 2. Auto-detects issue ID from branch name 3. Notifies the Witness with the exit outcome +4. Optionally exits the Claude session (--exit flag) -Exit types: +Exit statuses: COMPLETED - Work done, MR submitted (default) ESCALATED - Hit blocker, needs human intervention DEFERRED - Work paused, issue still open Examples: - gt done # Submit branch, notify COMPLETED - gt done --issue gt-abc # Explicit issue ID - gt done --exit ESCALATED # Signal blocker, skip MR - gt done --exit DEFERRED # Pause work, skip MR`, + gt done # Submit branch, notify COMPLETED + gt done --exit # Submit and exit Claude session + gt done --issue gt-abc # Explicit issue ID + gt done --status ESCALATED # Signal blocker, skip MR + gt done --status DEFERRED # Pause work, skip MR`, RunE: runDone, } var ( doneIssue string donePriority int - doneExit string + doneStatus string + doneExit bool ) // Valid exit types for gt done @@ -54,16 +57,17 @@ const ( func init() { doneCmd.Flags().StringVar(&doneIssue, "issue", "", "Source issue ID (default: parse from branch name)") doneCmd.Flags().IntVarP(&donePriority, "priority", "p", -1, "Override priority (0-4, default: inherit from issue)") - doneCmd.Flags().StringVar(&doneExit, "exit", ExitCompleted, "Exit type: COMPLETED, ESCALATED, or DEFERRED") + doneCmd.Flags().StringVar(&doneStatus, "status", ExitCompleted, "Exit status: COMPLETED, ESCALATED, or DEFERRED") + doneCmd.Flags().BoolVar(&doneExit, "exit", false, "Exit Claude session after MR submission (self-terminate)") rootCmd.AddCommand(doneCmd) } func runDone(cmd *cobra.Command, args []string) error { - // Validate exit type - exitType := strings.ToUpper(doneExit) + // Validate exit status + exitType := strings.ToUpper(doneStatus) if exitType != ExitCompleted && exitType != ExitEscalated && exitType != ExitDeferred { - return fmt.Errorf("invalid exit type '%s': must be COMPLETED, ESCALATED, or DEFERRED", doneExit) + return fmt.Errorf("invalid exit status '%s': must be COMPLETED, ESCALATED, or DEFERRED", doneStatus) } // Find workspace @@ -277,6 +281,15 @@ func runDone(cmd *cobra.Command, args []string) error { // Update agent bead state (ZFC: self-report completion) updateAgentStateOnDone(cwd, townRoot, exitType, issueID) + // Handle session self-termination if requested + if doneExit { + fmt.Println() + fmt.Printf("%s Session self-terminating (--exit flag)\n", style.Bold.Render("→")) + fmt.Printf(" Witness will handle worktree cleanup.\n") + fmt.Printf(" Goodbye!\n") + os.Exit(0) + } + return nil } diff --git a/internal/cmd/handoff.go b/internal/cmd/handoff.go index b1597dbf..bc67e507 100644 --- a/internal/cmd/handoff.go +++ b/internal/cmd/handoff.go @@ -25,7 +25,7 @@ var handoffCmd = &cobra.Command{ This is the canonical way to end any agent session. It handles all roles: - Mayor, Crew, Witness, Refinery, Deacon: Respawns with fresh Claude instance - - Polecats: Calls 'gt done --exit DEFERRED' (Witness handles lifecycle) + - Polecats: Calls 'gt done --status DEFERRED' (Witness handles lifecycle) When run without arguments, hands off the current session. When given a bead ID (gt-xxx, hq-xxx), hooks that work first, then restarts.