feat(spawn): Replace tmux injection with persistent mail-based work assignment (ga-yp3)
- gt spawn now sends work assignment to polecat inbox instead of tmux injection - Add --identity flag to gt mail inbox and gt mail check - Add --force flag to gt spawn to override existing unread mail - Update polecat template with startup protocol for reading inbox - Fix pre-existing lint issue in start.go The new flow is more reliable: 1. Spawn sends work assignment mail to polecat inbox 2. Polecat starts and runs gt prime 3. gt prime automatically runs gt mail check --inject 4. Polecat reads work assignment from inbox Benefits: - Persistence across session restarts - No racing against Claude initialization - Audit trail in beads - Edge case handling for existing unread mail 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -26,8 +26,10 @@ var (
|
||||
mailInboxJSON bool
|
||||
mailReadJSON bool
|
||||
mailInboxUnread bool
|
||||
mailInboxIdentity string
|
||||
mailCheckInject bool
|
||||
mailCheckJSON bool
|
||||
mailCheckIdentity string
|
||||
mailThreadJSON bool
|
||||
mailReplySubject string
|
||||
mailReplyMessage string
|
||||
@@ -78,11 +80,13 @@ var mailInboxCmd = &cobra.Command{
|
||||
Long: `Check messages in an inbox.
|
||||
|
||||
If no address is specified, shows the current context's inbox.
|
||||
Use --identity for polecats to explicitly specify their identity.
|
||||
|
||||
Examples:
|
||||
gt mail inbox # Current context
|
||||
gt mail inbox mayor/ # Mayor's inbox
|
||||
gt mail inbox gastown/Toast # Polecat's inbox`,
|
||||
gt mail inbox # Current context (auto-detected)
|
||||
gt mail inbox mayor/ # Mayor's inbox
|
||||
gt mail inbox gastown/Toast # Polecat's inbox
|
||||
gt mail inbox --identity gastown/Toast # Explicit polecat identity`,
|
||||
Args: cobra.MaximumNArgs(1),
|
||||
RunE: runMailInbox,
|
||||
}
|
||||
@@ -120,9 +124,12 @@ Exit codes (--inject mode):
|
||||
0 - Always (hooks should never block)
|
||||
Output: system-reminder if mail exists, silent if no mail
|
||||
|
||||
Use --identity for polecats to explicitly specify their identity.
|
||||
|
||||
Examples:
|
||||
gt mail check # Simple check
|
||||
gt mail check --inject # For hooks`,
|
||||
gt mail check # Simple check (auto-detect identity)
|
||||
gt mail check --inject # For hooks
|
||||
gt mail check --identity gastown/Toast # Explicit polecat identity`,
|
||||
RunE: runMailCheck,
|
||||
}
|
||||
|
||||
@@ -169,6 +176,7 @@ func init() {
|
||||
// Inbox flags
|
||||
mailInboxCmd.Flags().BoolVar(&mailInboxJSON, "json", false, "Output as JSON")
|
||||
mailInboxCmd.Flags().BoolVarP(&mailInboxUnread, "unread", "u", false, "Show only unread messages")
|
||||
mailInboxCmd.Flags().StringVar(&mailInboxIdentity, "identity", "", "Explicit identity for inbox (e.g., gastown/Toast)")
|
||||
|
||||
// Read flags
|
||||
mailReadCmd.Flags().BoolVar(&mailReadJSON, "json", false, "Output as JSON")
|
||||
@@ -176,6 +184,7 @@ func init() {
|
||||
// Check flags
|
||||
mailCheckCmd.Flags().BoolVar(&mailCheckInject, "inject", false, "Output format for Claude Code hooks")
|
||||
mailCheckCmd.Flags().BoolVar(&mailCheckJSON, "json", false, "Output as JSON")
|
||||
mailCheckCmd.Flags().StringVar(&mailCheckIdentity, "identity", "", "Explicit identity for inbox (e.g., gastown/Toast)")
|
||||
|
||||
// Thread flags
|
||||
mailThreadCmd.Flags().BoolVar(&mailThreadJSON, "json", false, "Output as JSON")
|
||||
@@ -270,9 +279,11 @@ func runMailInbox(cmd *cobra.Command, args []string) error {
|
||||
return fmt.Errorf("not in a Gas Town workspace: %w", err)
|
||||
}
|
||||
|
||||
// Determine which inbox to check
|
||||
// Determine which inbox to check (priority: --identity flag, positional arg, auto-detect)
|
||||
address := ""
|
||||
if len(args) > 0 {
|
||||
if mailInboxIdentity != "" {
|
||||
address = mailInboxIdentity
|
||||
} else if len(args) > 0 {
|
||||
address = args[0]
|
||||
} else {
|
||||
address = detectSender()
|
||||
@@ -519,8 +530,13 @@ func runMailCheck(cmd *cobra.Command, args []string) error {
|
||||
return fmt.Errorf("not in a Gas Town workspace: %w", err)
|
||||
}
|
||||
|
||||
// Determine which inbox
|
||||
address := detectSender()
|
||||
// Determine which inbox (priority: --identity flag, auto-detect)
|
||||
address := ""
|
||||
if mailCheckIdentity != "" {
|
||||
address = mailCheckIdentity
|
||||
} else {
|
||||
address = detectSender()
|
||||
}
|
||||
|
||||
// Get mailbox
|
||||
router := mail.NewRouter(workDir)
|
||||
|
||||
Reference in New Issue
Block a user