From 38d3c0c4f1ec6e34b64ff77bf668572e173ee4d4 Mon Sep 17 00:00:00 2001 From: jack Date: Sat, 17 Jan 2026 03:40:24 -0800 Subject: [PATCH] fix(mail): resolve beads-native queues/channels by name resolveByName() only checked config-based queues/channels, missing beads-native ones (gt:queue, gt:channel). Added lookup for both. Also added LookupQueueByName to beads package for parity with LookupChannelByName. Fixes: gt-l5qbi3 Co-Authored-By: Claude Opus 4.5 --- internal/beads/beads_queue.go | 31 +++++++++++++++++++++++++++++++ internal/mail/resolve.go | 24 +++++++++++++++++++++++- 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/internal/beads/beads_queue.go b/internal/beads/beads_queue.go index 37abe08e..8df740a0 100644 --- a/internal/beads/beads_queue.go +++ b/internal/beads/beads_queue.go @@ -292,6 +292,37 @@ func (b *Beads) DeleteQueueBead(id string) error { return err } +// LookupQueueByName finds a queue by its name field (not by ID). +// This is used for address resolution where we may not know the full bead ID. +func (b *Beads) LookupQueueByName(name string) (*Issue, *QueueFields, error) { + // First try direct lookup by standard ID formats (town and rig level) + for _, isTownLevel := range []bool{true, false} { + id := QueueBeadID(name, isTownLevel) + issue, fields, err := b.GetQueueBead(id) + if err != nil { + return nil, nil, err + } + if issue != nil { + return issue, fields, nil + } + } + + // If not found by ID, search all queues by name field + queues, err := b.ListQueueBeads() + if err != nil { + return nil, nil, err + } + + for _, issue := range queues { + fields := ParseQueueFields(issue.Description) + if fields.Name == name { + return issue, fields, nil + } + } + + return nil, nil, nil // Not found +} + // MatchClaimPattern checks if an identity matches a claim pattern. // Patterns support: // - "*" matches anyone diff --git a/internal/mail/resolve.go b/internal/mail/resolve.go index 61894516..c1177844 100644 --- a/internal/mail/resolve.go +++ b/internal/mail/resolve.go @@ -171,7 +171,29 @@ func (r *Resolver) resolveByName(name string) ([]Recipient, error) { } } - // Check for queue in config + // Check for beads-native queue + if r.beads != nil { + _, queueFields, err := r.beads.LookupQueueByName(name) + if err != nil { + return nil, err + } + if queueFields != nil { + foundQueue = true + } + } + + // Check for beads-native channel + if r.beads != nil { + _, channelFields, err := r.beads.LookupChannelByName(name) + if err != nil { + return nil, err + } + if channelFields != nil { + foundChannel = true + } + } + + // Check for queue/channel in config (legacy) if r.townRoot != "" { cfg, err := config.LoadMessagingConfig(config.MessagingConfigPath(r.townRoot)) if err == nil && cfg != nil {