From 3ebb1118d3baf9b384609797226b554015097107 Mon Sep 17 00:00:00 2001 From: gastown/crew/max Date: Thu, 15 Jan 2026 19:24:03 -0800 Subject: [PATCH] fix(mail): use workspace.Find for consistent town root detection detectTownRoot() was only checking for mayor/town.json, but some workspaces only have the mayor/ directory without town.json. This caused mail routing to fail silently - messages showed success but werent persisted because townRoot was empty. Now uses workspace.Find() which supports both primary marker (mayor/town.json) and secondary marker (mayor/ directory). Fixes: gt-6v7z89 Co-Authored-By: Claude Opus 4.5 --- internal/mail/router.go | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/internal/mail/router.go b/internal/mail/router.go index c5d1bedd..35279206 100644 --- a/internal/mail/router.go +++ b/internal/mail/router.go @@ -4,7 +4,6 @@ import ( "encoding/json" "errors" "fmt" - "os" "path/filepath" "strings" @@ -12,6 +11,7 @@ import ( "github.com/steveyegge/gastown/internal/config" "github.com/steveyegge/gastown/internal/session" "github.com/steveyegge/gastown/internal/tmux" + "github.com/steveyegge/gastown/internal/workspace" ) // ErrUnknownList indicates a mailing list name was not found in configuration. @@ -161,24 +161,15 @@ func (r *Router) expandAnnounce(announceName string) (*config.AnnounceConfig, er }, ErrUnknownAnnounce) } -// detectTownRoot finds the town root by looking for mayor/town.json. +// detectTownRoot finds the town root using workspace.Find. +// This ensures consistent detection with the rest of the codebase, +// supporting both primary (mayor/town.json) and secondary (mayor/) markers. func detectTownRoot(startDir string) string { - dir := startDir - for { - // Check for primary marker (mayor/town.json) - markerPath := filepath.Join(dir, "mayor", "town.json") - if _, err := os.Stat(markerPath); err == nil { - return dir - } - - // Move up - parent := filepath.Dir(dir) - if parent == dir { - break - } - dir = parent + townRoot, err := workspace.Find(startDir) + if err != nil { + return "" } - return "" + return townRoot } // resolveBeadsDir returns the correct .beads directory for the given address.