diff --git a/pkg/agentic/dispatch.go b/pkg/agentic/dispatch.go index 8666d2b..5018614 100644 --- a/pkg/agentic/dispatch.go +++ b/pkg/agentic/dispatch.go @@ -383,11 +383,16 @@ func (s *PrepSubsystem) spawnAgent(agent, prompt, wsDir string) (int, string, er s.broadcastStart(agent, wsDir) s.startIssueTracking(wsDir) - go func() { + // Register a one-shot Action that monitors this agent, then run it via PerformAsync. + // PerformAsync tracks it in Core's WaitGroup — ServiceShutdown waits for it. + monitorAction := core.Concat("agentic.monitor.", core.PathBase(wsDir)) + s.Core().Action(monitorAction, func(_ context.Context, _ core.Options) core.Result { <-proc.Done() s.onAgentComplete(agent, wsDir, outputFile, proc.Info().ExitCode, string(proc.Info().Status), proc.Output()) - }() + return core.Result{OK: true} + }) + s.Core().PerformAsync(monitorAction, core.NewOptions()) return pid, outputFile, nil } diff --git a/pkg/agentic/prep.go b/pkg/agentic/prep.go index c800388..6d14f13 100644 --- a/pkg/agentic/prep.go +++ b/pkg/agentic/prep.go @@ -105,7 +105,10 @@ func (s *PrepSubsystem) OnStartup(ctx context.Context) core.Result { if !core.HasPrefix(action, "agentic.") { return core.Entitlement{Allowed: true, Unlimited: true} } - // Read-only actions always allowed + // Read-only + internal actions always allowed + if core.HasPrefix(action, "agentic.monitor.") || core.HasPrefix(action, "agentic.complete") { + return core.Entitlement{Allowed: true, Unlimited: true} + } switch action { case "agentic.status", "agentic.scan", "agentic.watch", "agentic.issue.get", "agentic.issue.list", "agentic.pr.get", "agentic.pr.list",