Delete edge_case_test.go, coverage_push_test.go, dispatch_extra_test.go.
Rewrite dispatch_test.go with proper naming: TestDispatch_Function_{Good,Bad,Ugly}.
Every function in dispatch.go now has Good/Bad/Ugly test groups.
Tests for non-dispatch functions will be restored to their correct files.
agentic 72.6% (temporary regression — tests being redistributed)
Co-Authored-By: Virgil <virgil@lethean.io>
Add httptest mocks for startIssueTracking/stopIssueTracking with Forge,
broadcastStart/broadcastComplete with Core IPC.
Co-Authored-By: Virgil <virgil@lethean.io>
Tests dispatch input validation, DryRun flow with real git clone,
runQA with valid/broken Go projects, workspaceDir path resolution,
buildPRBody formatting, and canDispatchAgent concurrency checks.
17 tests covering the dispatch pipeline without Docker.
Co-Authored-By: Virgil <virgil@lethean.io>
- core.New() includes mcp.Register — auto-discovers subsystems
- mcp/serve commands use c.Service("mcp") for typed retrieval
- ServiceStartup called once before Cli().Run()
- run/task and run/orchestrator registered by agentic.OnStartup
- Removed ServiceFor generics — c.Service() returns instances directly
Co-Authored-By: Virgil <virgil@lethean.io>
Services are now registered during Core construction:
core.New(
core.WithService(agentic.Register),
core.WithService(monitor.Register),
core.WithService(brain.Register),
)
- Remove initServices() closure — services created once in conclave
- Commands use c.ServiceStartup()/c.ServiceShutdown() for lifecycle
- Service instances retrieved via c.Config() for MCP tool registration
- run/orchestrator reduced to ServiceStartup + block + ServiceShutdown
- run/task uses conclave's agentic instance
Co-Authored-By: Virgil <virgil@lethean.io>
Phase 3 of Core DI migration:
- Remove CompletionNotifier interface from pkg/agentic
- dispatch.go emits messages.AgentStarted/AgentCompleted via c.ACTION()
- monitor registers IPC handlers in SetCore() — handleAgentStarted/handleAgentCompleted
- Remove circular callback wiring (SetCompletionNotifier) from main.go
- Export ReadStatus for cross-package use
- Update run/orchestrator to use SetCore() instead of SetCompletionNotifier()
Services now communicate through typed messages, not direct references.
Co-Authored-By: Virgil <virgil@lethean.io>
Phase 2 of Core DI migration:
- Add *core.Core field + SetCore() to PrepSubsystem and monitor.Subsystem
- Register agentic/monitor/brain as Core services with lifecycle hooks
- Mark SetCompletionNotifier and SetNotifier as deprecated (removed in Phase 3)
- Fix monitor test to match actual event names
- initServices() now wires Core refs before legacy callbacks
Co-Authored-By: Virgil <virgil@lethean.io>
- Export ReadStatus (was readStatus) for cross-package use
- AgentCompleted now emits agent.completed with repo/agent/workspace/status
for every finished task, not just failures
- queue.drained only fires when genuinely empty — verified by checking
PIDs are alive via kill(0), not just trusting stale status files
- Fix Docker mount paths: /root/ → /home/dev/ for non-root container
- Update all callers and tests
Co-Authored-By: Virgil <virgil@lethean.io>
- Add background queue runner (runner.go) — 30s tick + poke on completion
- drainQueue now loops to fill all slots per tick
- Add run orchestrator command — standalone queue runner without MCP
- Slim agentic_status — stats only, blocked workspaces listed
- Docker containerised dispatch — all agents run in core-dev container
- Forge stopwatch start/stop on issue when agent starts/completes
- issue create supports --milestone, --assignee, --ref
- Auto-PR targets dev branch (not main)
- PR body includes Closes #N for issue-linked work
- CLI usage strings use spaces not slashes
- Review agent uses exec with sandbox bypass (not codex review subcommand)
- Local model support via codex --oss with socat Ollama proxy
Co-Authored-By: Virgil <virgil@lethean.io>
CompletionNotifier interface now has AgentStarted() and
AgentCompleted() instead of Poke(). Dispatch pushes notifications
directly to monitor with agent/repo/status data. Monitor pushes
MCP channel events immediately — no scanning, no dedup maps,
no filesystem polling latency.
Events.jsonl kept as audit log only, not notification mechanism.
Timer-based scan kept for startup seeding and stale detection.
Co-Authored-By: Virgil <virgil@lethean.io>
filepath.Base gave just "main" — every branch-based workspace
collided in seenCompleted map. Now uses relative path like
"core/go/main" for unique deduplication.
Co-Authored-By: Virgil <virgil@lethean.io>
Status MCP tool only scanned one level deep (*/status.json).
New workspaces at */*/*/status.json were invisible. Now scans
both layouts. Also removed unused os/filepath imports.
Co-Authored-By: Virgil <virgil@lethean.io>
monitorAPIURL, monitorBrainKey, monitorHomeDir, monitorPath were
added by Codex on remote dev but lost when we force-pushed after
rebase conflict. Restored with simplified Core.Env() usage.
Co-Authored-By: Virgil <virgil@lethean.io>
countRunningByAgent only scanned one level deep (*/status.json)
but new workspaces are at */*/*/status.json. Concurrency limits
weren't enforced — all agents dispatched as running instead of
queuing. Now scans both old and new layouts.
Co-Authored-By: Virgil <virgil@lethean.io>
QA gate failed because cloned repos weren't in a Go workspace.
Extract default template (including go.work with use ./repo)
into workspace dir before cloning. Fixes go test isolation.
Co-Authored-By: Virgil <virgil@lethean.io>
- emitStartEvent fires when agent spawns (dispatch.go)
- Monitor detects new "running" workspaces and pushes agent.started
channel notification with repo and agent info
- agent.complete already included blocked/failed status — no change
- Both old and new workspace layouts supported
Co-Authored-By: Virgil <virgil@lethean.io>
workspaceStatusPaths scans both old (*/status.json) and new
(*/*/*/status.json) workspace layouts. Fixes agent.complete
channel notifications not firing for org/repo/identifier paths.
Replaces filepath.Glob with core.PathGlob in harvest.go.
Co-Authored-By: Virgil <virgil@lethean.io>
When model variant was specified, the splice inserted --model
between -o and its value, making Codex see -o with no file path.
Fixed by appending --model and prompt sequentially instead of
splicing into the middle of the args slice.
Co-Authored-By: Virgil <virgil@lethean.io>