From ba5fd040259a2e1c076c1843b91988f4ad49d1a3 Mon Sep 17 00:00:00 2001 From: Levi Neely Date: Sun, 1 Mar 2026 00:47:13 +0100 Subject: [PATCH] fix: make beads mount work with lazy initialization - Changed NewServer to accept *BeadsFS instead of bd.Storage - BeadsFS is always created but with no initial mounts - Each mount opens its own store on-demand - Added nil check in supervisor to handle missing beads gracefully --- cmd/anvilsrv/main.go | 5 +++-- internal/backend/tmux/session.go | 9 --------- internal/backend/tmux/tmux.go | 9 --------- internal/p9/server.go | 9 +-------- internal/supervisor/supervisor.go | 5 +++++ 5 files changed, 9 insertions(+), 28 deletions(-) diff --git a/cmd/anvilsrv/main.go b/cmd/anvilsrv/main.go index 4f7d7b7..308ed67 100644 --- a/cmd/anvilsrv/main.go +++ b/cmd/anvilsrv/main.go @@ -211,8 +211,9 @@ func start(daemonize bool) { } }() - // Start 9P server - srv, err := p9.NewServer(mgr, nil) + // Start 9P server with empty beads filesystem (mounts created on-demand) + beadsFS := p9.NewBeadsFS(nil, context.Background()) + srv, err := p9.NewServer(mgr, beadsFS) if err != nil { logging.Logger().Fatal("failed to start 9P server", zap.Error(err)) } diff --git a/internal/backend/tmux/session.go b/internal/backend/tmux/session.go index 5117389..974da51 100644 --- a/internal/backend/tmux/session.go +++ b/internal/backend/tmux/session.go @@ -670,7 +670,6 @@ func (s *Session) Restart(ctx context.Context) error { backendName := s.backendName backendCommand := s.backendCommand role := s.role - tasks := s.tasks hadCrash := s.hadCrash model := s.model modelResolver := s.modelResolver @@ -720,14 +719,6 @@ func (s *Session) Restart(ctx context.Context) error { } layers = append(layers, roleLayer) - for _, taskName := range tasks { - taskLayer, err := sandbox.LoadTask(taskName) - if err != nil { - return fmt.Errorf("failed to load task %q: %w", taskName, err) - } - layers = append(layers, taskLayer) - } - general := sandbox.GeneralConfig{BestEffort: false, LogLevel: "error"} advanced := sandbox.AdvancedConfig{LDD: false, AddExec: true} sandboxCfg := sandbox.Merge(general, advanced, layers...) diff --git a/internal/backend/tmux/tmux.go b/internal/backend/tmux/tmux.go index 17fd601..0b9c9be 100644 --- a/internal/backend/tmux/tmux.go +++ b/internal/backend/tmux/tmux.go @@ -159,15 +159,6 @@ func (b *Backend) CreateSession(ctx context.Context, opts backend.SessionOptions } layers = append(layers, roleLayer) - // Add task layers - for _, taskName := range opts.Tasks { - taskLayer, err := sandbox.LoadTask(taskName) - if err != nil { - return nil, fmt.Errorf("failed to load task %q: %w", taskName, err) - } - layers = append(layers, taskLayer) - } - // Merge layers into final config general := sandbox.GeneralConfig{ BestEffort: false, diff --git a/internal/p9/server.go b/internal/p9/server.go index 1cfbb51..7a17292 100644 --- a/internal/p9/server.go +++ b/internal/p9/server.go @@ -24,7 +24,6 @@ import ( "sync" "github.com/google/uuid" - bd "github.com/steveyegge/beads" "go.uber.org/zap" "9fans.net/go/plan9" @@ -150,7 +149,7 @@ type fid struct { } // NewServer creates and starts the 9P server. -func NewServer(mgr *session.Manager, beadsStore bd.Storage) (*Server, error) { +func NewServer(mgr *session.Manager, beadsFS *BeadsFS) (*Server, error) { ns := client.Namespace() if ns == "" { return nil, fmt.Errorf("no namespace") @@ -173,12 +172,6 @@ func NewServer(mgr *session.Manager, beadsStore bd.Storage) (*Server, error) { return nil, err } - // Create BeadsFS (shared across all namespaces) - var beadsFS *BeadsFS - if beadsStore != nil { - beadsFS = NewBeadsFS(beadsStore, context.Background()) - } - // Load tools from anvilmcp tools := loadMCPTools() toolsFS := NewToolsFS(tools) diff --git a/internal/supervisor/supervisor.go b/internal/supervisor/supervisor.go index c95b7e1..822c45f 100644 --- a/internal/supervisor/supervisor.go +++ b/internal/supervisor/supervisor.go @@ -27,6 +27,11 @@ func New(s *session.Manager, b *p9.BeadsFS, m *mailbox.Manager, e *eventbus.Bus) } func (s *Supervisor) assignWork() { + // Skip if beads not available + if s.beads == nil { + return + } + // Get all claimable tasks from all projects ready, err := s.beads.Read("ready") if err != nil || len(ready) == 0 {