refactor(mail): Remove bd mail dependency, use bd create/list/show (gt-9xg)

Replace `bd mail send/inbox/read/ack` commands with `bd create/list/show/close`.
This separates the orchestration layer (gt) from the data plane (beads).

Changes:
- router.go: Use `bd create --type=message` instead of `bd mail send`
- mailbox.go: Use `bd list --type=message` and `bd show` for inbox/read
- types.go: Parse metadata from labels (from:, thread:, reply-to:)
- mail.go: Fix findBeadsWorkDir to prefer rig-level beads, fix crew address format

Messages are now stored as beads issues with type=message. Metadata (sender,
thread, reply-to) is stored in labels for retrieval.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Steve Yegge
2025-12-20 17:52:15 -08:00
parent d242239aa1
commit 4c060f4aaa
5 changed files with 114 additions and 52 deletions

View File

@@ -462,16 +462,8 @@ func runMailDelete(cmd *cobra.Command, args []string) error {
// findBeadsWorkDir finds a directory with a .beads database.
// Walks up from CWD looking for .beads/ directory.
func findBeadsWorkDir() (string, error) {
// First try workspace root
townRoot, err := workspace.FindFromCwdOrError()
if err == nil {
// Check if town root has .beads
if _, err := os.Stat(filepath.Join(townRoot, ".beads")); err == nil {
return townRoot, nil
}
}
// Walk up from CWD looking for .beads
// Walk up from CWD looking for .beads - prefer closest one (rig-level)
// This finds the rig's .beads before the town's .beads
cwd, err := os.Getwd()
if err != nil {
return "", err
@@ -490,6 +482,14 @@ func findBeadsWorkDir() (string, error) {
path = parent
}
// Fall back to town root if nothing found walking up
townRoot, err := workspace.FindFromCwdOrError()
if err == nil {
if _, err := os.Stat(filepath.Join(townRoot, ".beads")); err == nil {
return townRoot, nil
}
}
return "", fmt.Errorf("no .beads directory found")
}
@@ -520,14 +520,14 @@ func detectSender() string {
}
}
// If in a rig's crew directory, extract address
// If in a rig's crew directory, extract address (format: rig/crew/name)
if strings.Contains(cwd, "/crew/") {
parts := strings.Split(cwd, "/crew/")
if len(parts) >= 2 {
rigPath := parts[0]
crewName := strings.Split(parts[1], "/")[0]
rigName := filepath.Base(rigPath)
return fmt.Sprintf("%s/%s", rigName, crewName)
return fmt.Sprintf("%s/crew/%s", rigName, crewName)
}
}