Detect and clean stale POLECAT_DONE messages (#913)

* fix(witness): detect and ignore stale POLECAT_DONE messages

Add timestamp validation to prevent witness from nuking newly spawned
polecat sessions when processing stale POLECAT_DONE messages from
previous sessions.

- Add isStalePolecatDone() to compare message timestamp vs session created time
- If message timestamp < session created time, message is stale and ignored
- Add unit tests for timestamp parsing and stale detection logic

Fixes #909

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat(mail): add --stale flag to gt mail archive

Add ability to archive stale messages (sent before current session started).
This prevents old messages from cycling forever in patrol inbox.

Changes:
- Add --stale and --dry-run flags to gt mail archive
- Move stale detection helpers to internal/session/stale.go for reuse
- Add ParseAddress to parse mail addresses into AgentIdentity
- Add SessionCreatedAt to get tmux session start time

Usage:
  gt mail archive --stale           # Archive all stale messages
  gt mail archive --stale --dry-run # Preview what would be archived

Co-Authored-By: GPT-5.2 Codex <noreply@openai.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: GPT-5.2 Codex <noreply@openai.com>
This commit is contained in:
Artem Bambalov
2026-01-25 07:47:59 +02:00
committed by GitHub
parent f635555f93
commit 533caf8e4b
8 changed files with 392 additions and 4 deletions
+18 -4
View File
@@ -42,6 +42,10 @@ var (
// Clear flags
mailClearAll bool
// Archive flags
mailArchiveStale bool
mailArchiveDryRun bool
)
var mailCmd = &cobra.Command{
@@ -196,16 +200,22 @@ Examples:
}
var mailArchiveCmd = &cobra.Command{
Use: "archive <message-id> [message-id...]",
Use: "archive [message-id...]",
Short: "Archive messages",
Long: `Archive one or more messages.
Removes the messages from your inbox by closing them in beads.
Use --stale to archive messages sent before your current session started.
Examples:
gt mail archive hq-abc123
gt mail archive hq-abc123 hq-def456 hq-ghi789`,
Args: cobra.MinimumNArgs(1),
gt mail archive hq-abc123
gt mail archive hq-abc123 hq-def456 hq-ghi789
gt mail archive --stale
gt mail archive --stale --dry-run`,
Args: func(cmd *cobra.Command, args []string) error {
return nil
},
RunE: runMailArchive,
}
@@ -487,6 +497,10 @@ func init() {
// Clear flags
mailClearCmd.Flags().BoolVar(&mailClearAll, "all", false, "Clear all messages (default behavior)")
// Archive flags
mailArchiveCmd.Flags().BoolVar(&mailArchiveStale, "stale", false, "Archive messages sent before session start")
mailArchiveCmd.Flags().BoolVarP(&mailArchiveDryRun, "dry-run", "n", false, "Show what would be archived without archiving")
// Add subcommands
mailCmd.AddCommand(mailSendCmd)
mailCmd.AddCommand(mailInboxCmd)