fix(mail): use slash-based identity format for addresses
Changes mail identity format from hyphenated (gastown-Toast) to slash-based (gastown/polecats/Toast) to: - Match directory structure (REST-like) - Distinguish from hyphenated bead IDs (gt-xyz) and molecule names Updated: - addressToIdentity(): preserve slashes instead of replacing with dashes - identityToAddress(): simplified, identity == address now - detectSender(): include /polecats/ in polecat addresses - Tests updated for new format Closes gt-cxtu: shared beads architecture verified working. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -554,14 +554,14 @@ func detectSender() string {
|
||||
return "mayor/"
|
||||
}
|
||||
|
||||
// If in a rig's polecats directory, extract address
|
||||
// If in a rig's polecats directory, extract address (format: rig/polecats/name)
|
||||
if strings.Contains(cwd, "/polecats/") {
|
||||
parts := strings.Split(cwd, "/polecats/")
|
||||
if len(parts) >= 2 {
|
||||
rigPath := parts[0]
|
||||
polecatPath := strings.Split(parts[1], "/")[0]
|
||||
rigName := filepath.Base(rigPath)
|
||||
return fmt.Sprintf("%s/%s", rigName, polecatPath)
|
||||
return fmt.Sprintf("%s/polecats/%s", rigName, polecatPath)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ var (
|
||||
|
||||
// Mailbox manages messages for an identity via beads.
|
||||
type Mailbox struct {
|
||||
identity string // beads identity (e.g., "gastown-Toast")
|
||||
identity string // beads identity (e.g., "gastown/polecats/Toast")
|
||||
workDir string // directory to run bd commands in
|
||||
beadsDir string // explicit .beads directory path (set via BEADS_DIR)
|
||||
path string // for legacy JSONL mode (crew workers)
|
||||
|
||||
@@ -276,16 +276,15 @@ func ParseMessageType(s string) MessageType {
|
||||
|
||||
// addressToIdentity converts a GGT address to a beads identity.
|
||||
//
|
||||
// Examples:
|
||||
// Addresses use slash format matching directory structure:
|
||||
// - "mayor/" → "mayor/"
|
||||
// - "mayor" → "mayor/"
|
||||
// - "deacon/" → "deacon/"
|
||||
// - "deacon" → "deacon/"
|
||||
// - "gastown/Toast" → "gastown-Toast"
|
||||
// - "gastown/refinery" → "gastown-refinery"
|
||||
// - "gastown/polecats/Toast" → "gastown/polecats/Toast"
|
||||
// - "gastown/crew/max" → "gastown/crew/max"
|
||||
// - "gastown/refinery" → "gastown/refinery"
|
||||
// - "gastown/" → "gastown" (rig broadcast)
|
||||
// - "beads/crew/dave" → "beads-dave" (crew/ stripped)
|
||||
// - "beads/polecats/nux" → "beads-nux" (polecats/ stripped)
|
||||
func addressToIdentity(address string) string {
|
||||
// Town-level agents: mayor and deacon keep trailing slash
|
||||
if address == "mayor" || address == "mayor/" {
|
||||
@@ -300,36 +299,20 @@ func addressToIdentity(address string) string {
|
||||
address = address[:len(address)-1]
|
||||
}
|
||||
|
||||
// Normalize worker paths: strip crew/ and polecats/ from path
|
||||
// beads/crew/dave → beads/dave (both resolve to beads-dave)
|
||||
// beads/polecats/nux → beads/nux (both resolve to beads-nux)
|
||||
address = strings.Replace(address, "/crew/", "/", 1)
|
||||
address = strings.Replace(address, "/polecats/", "/", 1)
|
||||
|
||||
// Replace / with - for beads identity
|
||||
// gastown/Toast → gastown-Toast
|
||||
result := ""
|
||||
for _, c := range address {
|
||||
if c == '/' {
|
||||
result += "-"
|
||||
} else {
|
||||
result = result + string(c)
|
||||
}
|
||||
}
|
||||
return result
|
||||
// Keep slashes - addresses map to directory structure
|
||||
return address
|
||||
}
|
||||
|
||||
// identityToAddress converts a beads identity back to a GGT address.
|
||||
//
|
||||
// Examples:
|
||||
// - "mayor" → "mayor/"
|
||||
// Identity format matches address format (slash-based):
|
||||
// - "mayor/" → "mayor/"
|
||||
// - "deacon" → "deacon/"
|
||||
// - "deacon/" → "deacon/"
|
||||
// - "gastown-Toast" → "gastown/Toast"
|
||||
// - "gastown-refinery" → "gastown/refinery"
|
||||
// - "gastown/polecats/Toast" → "gastown/polecats/Toast"
|
||||
// - "gastown/crew/max" → "gastown/crew/max"
|
||||
// - "gastown/refinery" → "gastown/refinery"
|
||||
func identityToAddress(identity string) string {
|
||||
// Town-level agents
|
||||
// Town-level agents ensure trailing slash
|
||||
if identity == "mayor" || identity == "mayor/" {
|
||||
return "mayor/"
|
||||
}
|
||||
@@ -337,14 +320,6 @@ func identityToAddress(identity string) string {
|
||||
return "deacon/"
|
||||
}
|
||||
|
||||
// Find first dash and replace with /
|
||||
// gastown-Toast → gastown/Toast
|
||||
for i, c := range identity {
|
||||
if c == '-' {
|
||||
return identity[:i] + "/" + identity[i+1:]
|
||||
}
|
||||
}
|
||||
|
||||
// No dash found, return as-is with trailing slash
|
||||
return identity + "/"
|
||||
// Identity already in slash format, return as-is
|
||||
return identity
|
||||
}
|
||||
|
||||
@@ -13,10 +13,11 @@ func TestAddressToIdentity(t *testing.T) {
|
||||
{"deacon", "deacon/"},
|
||||
{"deacon/", "deacon/"},
|
||||
|
||||
// Rig-level agents use dash separator
|
||||
{"gastown/Toast", "gastown-Toast"},
|
||||
{"gastown/refinery", "gastown-refinery"},
|
||||
{"gastown/witness", "gastown-witness"},
|
||||
// Rig-level agents: slash format matches directory structure
|
||||
{"gastown/polecats/Toast", "gastown/polecats/Toast"},
|
||||
{"gastown/crew/max", "gastown/crew/max"},
|
||||
{"gastown/refinery", "gastown/refinery"},
|
||||
{"gastown/witness", "gastown/witness"},
|
||||
|
||||
// Rig broadcast (trailing slash removed)
|
||||
{"gastown/", "gastown"},
|
||||
@@ -43,13 +44,14 @@ func TestIdentityToAddress(t *testing.T) {
|
||||
{"deacon", "deacon/"},
|
||||
{"deacon/", "deacon/"},
|
||||
|
||||
// Rig-level agents
|
||||
{"gastown-Toast", "gastown/Toast"},
|
||||
{"gastown-refinery", "gastown/refinery"},
|
||||
{"gastown-witness", "gastown/witness"},
|
||||
// Rig-level agents: identity == address (slash format)
|
||||
{"gastown/polecats/Toast", "gastown/polecats/Toast"},
|
||||
{"gastown/crew/max", "gastown/crew/max"},
|
||||
{"gastown/refinery", "gastown/refinery"},
|
||||
{"gastown/witness", "gastown/witness"},
|
||||
|
||||
// Rig name only (adds trailing slash)
|
||||
{"gastown", "gastown/"},
|
||||
// Rig name only (no transformation)
|
||||
{"gastown", "gastown"},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
|
||||
Reference in New Issue
Block a user