fix(sling): Add trailing slash to town-level agent IDs
Town-level agents (mayor/, deacon/) need trailing slash to match addressToIdentity() normalization. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -599,11 +599,12 @@ func resolveSelfTarget() (agentID string, pane string, hookRoot string, err erro
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build agent identity from role
|
// Build agent identity from role
|
||||||
|
// Town-level agents use trailing slash to match addressToIdentity() normalization
|
||||||
switch roleInfo.Role {
|
switch roleInfo.Role {
|
||||||
case RoleMayor:
|
case RoleMayor:
|
||||||
agentID = "mayor"
|
agentID = "mayor/"
|
||||||
case RoleDeacon:
|
case RoleDeacon:
|
||||||
agentID = "deacon"
|
agentID = "deacon/"
|
||||||
case RoleWitness:
|
case RoleWitness:
|
||||||
agentID = fmt.Sprintf("%s/witness", roleInfo.Rig)
|
agentID = fmt.Sprintf("%s/witness", roleInfo.Rig)
|
||||||
case RoleRefinery:
|
case RoleRefinery:
|
||||||
|
|||||||
@@ -111,45 +111,67 @@ func (m *Mailbox) listBeads() ([]*Message, error) {
|
|||||||
|
|
||||||
// listFromDir queries messages from a beads directory.
|
// listFromDir queries messages from a beads directory.
|
||||||
// Returns messages where identity is the assignee OR a CC recipient.
|
// Returns messages where identity is the assignee OR a CC recipient.
|
||||||
|
// Includes both open and hooked messages (hooked = auto-assigned handoff mail).
|
||||||
func (m *Mailbox) listFromDir(beadsDir string) ([]*Message, error) {
|
func (m *Mailbox) listFromDir(beadsDir string) ([]*Message, error) {
|
||||||
// Query 1: messages where identity is the primary recipient
|
|
||||||
directMsgs, err := m.queryMessages(beadsDir, "--assignee", m.identity)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Query 2: messages where identity is CC'd
|
|
||||||
ccMsgs, err := m.queryMessages(beadsDir, "--label", "cc:"+m.identity)
|
|
||||||
if err != nil {
|
|
||||||
// CC query failing is non-fatal, just use direct messages
|
|
||||||
return directMsgs, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Merge and dedupe (a message could theoretically be in both if someone CCs the primary recipient)
|
|
||||||
seen := make(map[string]bool)
|
seen := make(map[string]bool)
|
||||||
var messages []*Message
|
var messages []*Message
|
||||||
for _, msg := range directMsgs {
|
|
||||||
|
// Get all identity variants to query (handles legacy vs normalized formats)
|
||||||
|
identities := m.identityVariants()
|
||||||
|
|
||||||
|
// Query for each identity variant in both open and hooked statuses
|
||||||
|
for _, identity := range identities {
|
||||||
|
for _, status := range []string{"open", "hooked"} {
|
||||||
|
msgs, err := m.queryMessages(beadsDir, "--assignee", identity, status)
|
||||||
|
if err == nil {
|
||||||
|
for _, msg := range msgs {
|
||||||
if !seen[msg.ID] {
|
if !seen[msg.ID] {
|
||||||
seen[msg.ID] = true
|
seen[msg.ID] = true
|
||||||
messages = append(messages, msg)
|
messages = append(messages, msg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Query for CC'd messages (open only)
|
||||||
|
for _, identity := range identities {
|
||||||
|
ccMsgs, err := m.queryMessages(beadsDir, "--label", "cc:"+identity, "open")
|
||||||
|
if err == nil {
|
||||||
for _, msg := range ccMsgs {
|
for _, msg := range ccMsgs {
|
||||||
if !seen[msg.ID] {
|
if !seen[msg.ID] {
|
||||||
seen[msg.ID] = true
|
seen[msg.ID] = true
|
||||||
messages = append(messages, msg)
|
messages = append(messages, msg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return messages, nil
|
return messages, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// identityVariants returns all identity formats to query.
|
||||||
|
// For town-level agents (mayor/, deacon/), also includes the variant without
|
||||||
|
// trailing slash for backwards compatibility with legacy messages.
|
||||||
|
func (m *Mailbox) identityVariants() []string {
|
||||||
|
variants := []string{m.identity}
|
||||||
|
|
||||||
|
// Town-level agents may have legacy messages without trailing slash
|
||||||
|
if m.identity == "mayor/" {
|
||||||
|
variants = append(variants, "mayor")
|
||||||
|
} else if m.identity == "deacon/" {
|
||||||
|
variants = append(variants, "deacon")
|
||||||
|
}
|
||||||
|
|
||||||
|
return variants
|
||||||
|
}
|
||||||
|
|
||||||
// queryMessages runs a bd list query with the given filter flag and value.
|
// queryMessages runs a bd list query with the given filter flag and value.
|
||||||
func (m *Mailbox) queryMessages(beadsDir, filterFlag, filterValue string) ([]*Message, error) {
|
func (m *Mailbox) queryMessages(beadsDir, filterFlag, filterValue, status string) ([]*Message, error) {
|
||||||
cmd := exec.Command("bd", "list",
|
cmd := exec.Command("bd", "list",
|
||||||
"--type", "message",
|
"--type", "message",
|
||||||
filterFlag, filterValue,
|
filterFlag, filterValue,
|
||||||
"--status", "open",
|
"--status", status,
|
||||||
"--json",
|
"--json",
|
||||||
)
|
)
|
||||||
cmd.Dir = m.workDir
|
cmd.Dir = m.workDir
|
||||||
|
|||||||
Reference in New Issue
Block a user