fix(patrol): add idempotency check for digest command

Checks if a 'Patrol Report YYYY-MM-DD' bead already exists before
attempting to create a new one. This prevents confusing output when
the patrol digest runs multiple times per day.

Fixes: gt-budqv9

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
max
2026-01-17 03:41:06 -08:00
committed by Steve Yegge
parent 38d3c0c4f1
commit f19a0ab5d6

View File

@@ -103,6 +103,19 @@ func runPatrolDigest(cmd *cobra.Command, args []string) error {
dateStr := targetDate.Format("2006-01-02")
// Idempotency check: see if digest already exists for this date
existingID, err := findExistingPatrolDigest(dateStr)
if err != nil {
// Non-fatal: continue with creation attempt
if patrolDigestVerbose {
fmt.Fprintf(os.Stderr, "[patrol] warning: failed to check existing digest: %v\n", err)
}
} else if existingID != "" {
fmt.Printf("%s Patrol digest already exists for %s (bead: %s)\n",
style.Dim.Render("○"), dateStr, existingID)
return nil
}
// Query ephemeral patrol digest beads for target date
cycles, err := queryPatrolDigests(targetDate)
if err != nil {
@@ -305,6 +318,40 @@ func createPatrolDigestBead(digest PatrolDigest) (string, error) {
return digestID, nil
}
// findExistingPatrolDigest checks if a patrol digest already exists for the given date.
// Returns the bead ID if found, empty string if not found.
func findExistingPatrolDigest(dateStr string) (string, error) {
expectedTitle := fmt.Sprintf("Patrol Report %s", dateStr)
// Query event beads with patrol.digest category
listCmd := exec.Command("bd", "list",
"--type=event",
"--json",
"--limit=50", // Recent events only
)
listOutput, err := listCmd.Output()
if err != nil {
return "", err
}
var events []struct {
ID string `json:"id"`
Title string `json:"title"`
}
if err := json.Unmarshal(listOutput, &events); err != nil {
return "", err
}
for _, evt := range events {
if evt.Title == expectedTitle {
return evt.ID, nil
}
}
return "", nil
}
// deletePatrolDigests deletes ephemeral patrol digest beads for a target date.
func deletePatrolDigests(targetDate time.Time) (int, error) {
// Query patrol digests for the target date