Add mail gate evaluation in bd gate eval (gt-twjr5.4)
Mail gates check for messages matching the pattern (await_id): - Case-insensitive substring match on message subjects - If waiters specified, only matches messages to those recipients - Closes gate when matching message found Note: Full testing blocked by bd-70c4 (await fields being cleared). The code is correct but gate fields get corrupted by auto-import. Also adds context and storage imports for mail gate function. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
@@ -10,6 +11,7 @@ import (
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/steveyegge/beads/internal/rpc"
|
||||
"github.com/steveyegge/beads/internal/storage"
|
||||
"github.com/steveyegge/beads/internal/storage/sqlite"
|
||||
"github.com/steveyegge/beads/internal/types"
|
||||
"github.com/steveyegge/beads/internal/ui"
|
||||
@@ -770,9 +772,14 @@ This command is idempotent and safe to run repeatedly.`,
|
||||
awaitingHuman = append(awaitingHuman, gate.ID)
|
||||
continue
|
||||
case "mail":
|
||||
// Mail gates will be evaluated when mail gate support is added
|
||||
awaitingMail = append(awaitingMail, gate.ID)
|
||||
continue
|
||||
// Mail gates check for messages matching the pattern
|
||||
if store != nil {
|
||||
shouldClose, reason = evalMailGate(ctx, store, gate)
|
||||
} else {
|
||||
// Daemon mode - can't evaluate mail gates without store access
|
||||
awaitingMail = append(awaitingMail, gate.ID)
|
||||
continue
|
||||
}
|
||||
default:
|
||||
// Unsupported gate type - skip
|
||||
skipped = append(skipped, gate.ID)
|
||||
@@ -943,6 +950,59 @@ func evalGHPRGate(gate *types.Issue) (bool, string) {
|
||||
}
|
||||
}
|
||||
|
||||
// evalMailGate checks if any message matching the pattern exists.
|
||||
// The pattern (await_id) is matched as a case-insensitive substring of message subjects.
|
||||
// If waiters are specified, only messages addressed to those waiters are considered.
|
||||
func evalMailGate(ctx context.Context, store storage.Storage, gate *types.Issue) (bool, string) {
|
||||
pattern := gate.AwaitID
|
||||
if pattern == "" {
|
||||
return false, ""
|
||||
}
|
||||
|
||||
// Search for messages
|
||||
msgType := types.TypeMessage
|
||||
openStatus := types.StatusOpen
|
||||
filter := types.IssueFilter{
|
||||
IssueType: &msgType,
|
||||
Status: &openStatus,
|
||||
}
|
||||
|
||||
messages, err := store.SearchIssues(ctx, "", filter)
|
||||
if err != nil {
|
||||
return false, ""
|
||||
}
|
||||
|
||||
// Convert pattern to lowercase for case-insensitive matching
|
||||
patternLower := strings.ToLower(pattern)
|
||||
|
||||
// Build waiter set for efficient lookup (if waiters specified)
|
||||
waiterSet := make(map[string]bool)
|
||||
for _, w := range gate.Waiters {
|
||||
waiterSet[w] = true
|
||||
}
|
||||
|
||||
// Check each message
|
||||
for _, msg := range messages {
|
||||
// Check subject contains pattern (case-insensitive)
|
||||
if !strings.Contains(strings.ToLower(msg.Title), patternLower) {
|
||||
continue
|
||||
}
|
||||
|
||||
// If waiters specified, check if message is addressed to a waiter
|
||||
// Messages use Assignee field for recipient
|
||||
if len(waiterSet) > 0 {
|
||||
if !waiterSet[msg.Assignee] {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// Found a matching message
|
||||
return true, fmt.Sprintf("Mail received: %s", msg.Title)
|
||||
}
|
||||
|
||||
return false, ""
|
||||
}
|
||||
|
||||
func init() {
|
||||
// Gate eval flags
|
||||
gateEvalCmd.Flags().Bool("dry-run", false, "Show what would be closed without actually closing")
|
||||
|
||||
Reference in New Issue
Block a user