When a workspace already exists (resumed=true), checkout main and
pull origin before creating the feature branch. Prevents agents
from working on stale code after previous runs merged.
Co-Authored-By: Virgil <virgil@lethean.io>
Workspace prep now detects repo language and copies the right CODEX.md:
- Go repos get CODEX.md.tmpl (existing — Core primitives, banned imports)
- PHP repos get CODEX-PHP.md.tmpl (CorePHP patterns, lifecycle events,
Actions, BelongsToWorkspace, Flux Pro, FA Pro, UK English)
Added lib.WorkspaceFile() helper for reading individual template files.
Co-Authored-By: Virgil <virgil@lethean.io>
Agents now get the full ecosystem docs (core.help) at
.core/reference/docs/ in their workspace. 349 markdown files
covering architecture, guides, specs — not just the RFC.
Co-Authored-By: Virgil <virgil@lethean.io>
Moves concurrency, queue drain, workspace lifecycle, and frozen state
from agentic/prep into pkg/runner/ — a standalone Core service that
communicates via IPC Actions only.
- runner.Register wires Actions: dispatch, status, start, stop, kill, poke
- runner.HandleIPCEvents catches AgentCompleted → ChannelPush + queue poke
- Agentic dispatch asks runner for permission via c.Action("runner.dispatch")
- Dispatch mutex moved to struct-level sync.Mutex (fixes core.Lock init race)
- Registry-based concurrency counting replaces disk scanning
- TrackWorkspace called on both queued and running status writes
- SpawnQueued message added for runner→agentic spawn requests
- ChannelPush message in core/mcp enables any service to push channel events
- 51 new tests covering runner service, queue, and config parsing
Co-Authored-By: Virgil <virgil@lethean.io>
- cloneWorkspaceDeps: reads go.mod, clones Core ecosystem modules from Forge
into workspace alongside ./repo, rebuilds go.work with all use directives
- Deduplicates deps (dappco.re + forge.lthn.ai map to same repos)
- Container chmod: workspace files made writable before exit so host can clean up
- GONOSUMCHECK for local workspace modules (bypass checksum for dev branches)
- Removed stale OLLAMA_HOST env from container
Co-Authored-By: Virgil <virgil@lethean.io>
The monitoring goroutine that waits for agent completion was a raw `go func()`
that Core didn't know about. ServiceShutdown killed it immediately on CLI exit.
Now uses PerformAsync which registers with Core's WaitGroup:
- ServiceShutdown waits for all async tasks to drain
- `core-agent workspace dispatch` blocks until agent completes
- Agent lifecycle properly tracked by the framework
Also whitelist agentic.monitor.* and agentic.complete in entitlement checker.
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>
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>
- 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>
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>
Replace raw http.Client calls with go-forge typed API:
- prep.go: getIssueBody via forge.Issues.Get, pullWikiContent
via forge.Wiki.ListPages/GetPage
- pr.go: forgeCreatePR via forge.Pulls.Create, commentOnIssue
via forge.Issues.CreateComment, listRepoPRs via forge.Pulls.ListAll
- scan.go: listOrgRepos via forge.Repos.ListOrgRepos
Eliminates manual JSON marshalling, auth headers, pagination loops,
and anonymous struct declarations. One Forge client, one auth,
type-safe responses.
Co-Authored-By: Virgil <virgil@lethean.io>
Major simplification of the dispatch model:
- Workspace dir: .core/workspace/{org}/{repo}/{pr|task|branch|tag}/
- Clone into repo/ (not src/), metadata in .meta/
- One of issue, pr, branch, or tag required for dispatch
- All context (brain, consumers, git log, wiki, plan) assembled
into prompt string — no TODO.md, PROMPT.md, CONTEXT.md files
- Resume detection: skip clone if repo/.git exists
- Default agent changed to codex
- spawnAgent drops srcDir param, runs from repo/
- No --skip-git-repo-check (repo/ IS a git repo)
- All downstream files: srcDir → repoDir
Track PRs, not workspace iterations.
Co-Authored-By: Virgil <virgil@lethean.io>
Replace all os.UserHomeDir/os.Getenv/os.Hostname with core.Env().
Replace all filepath.Base/Dir/Glob/IsAbs with core.PathBase/PathDir/
PathGlob/PathIsAbs.
10 files migrated: paths, prep, review_queue, remote, dispatch,
ingest, mirror, plan, verify, watch.
Imports eliminated: 5x os, 7x filepath. All file I/O and path
construction now routes through Core primitives.
Bumps dappco.re/go/core to v0.6.0.
Co-Authored-By: Virgil <virgil@lethean.io>
Replace separate go-io (coreio) and go-log (coreerr) packages with
Core's built-in Fs and error/logging functions. This is the reference
implementation for how all Core ecosystem packages should migrate.
Changes:
- coreio.Local.Read/Write/EnsureDir/Delete/IsFile → core.Fs methods
- coreerr.E() → core.E(), coreerr.Info/Warn/Error → core.Info/Warn/Error
- (value, error) return pattern → core.Result pattern (r.OK, r.Value)
- go-io and go-log moved from direct to indirect deps in go.mod
- Added AX usage-example comments on key public types
- Added newFs("/") helper for unrestricted filesystem access
Co-Authored-By: Virgil <virgil@lethean.io>
High/Security: sanitise input.Repo via filepath.Base to prevent
path traversal in workspace prep (../escape from CODE_PATH).
High/Security: sanitise repo.Repo from API response in syncRepos
to prevent path traversal via crafted checkin responses.
Medium: dispatchFixFromQueue now returns error, review_queue checks
success before recording fix_dispatched.
Known issues updated with async bridge provider findings.
Co-Authored-By: Virgil <virgil@lethean.io>
High: workspace names use UnixNano to prevent same-second collisions
High: sync only pulls the branch the server reported (was pulling current)
Medium: drainQueue serialised via mutex to prevent concurrent over-dispatch
Medium: remote_status checks JSON-RPC error field before reporting success
Medium: dead agent PIDs without output log marked failed, not completed
Low: detectLanguage uses ordered slice instead of map for deterministic results
Also: URL-encoded agent names in messaging, monitor inbox, and sync endpoints.
Co-Authored-By: Virgil <virgil@lethean.io>
High: harvest no longer hardcodes 'main' — detects default branch
via symbolic-ref/rev-parse fallback. Repos with master/other
default branches are now harvested correctly.
High: empty task no longer produces invalid 'agent/' branch name.
Falls back to issue-N or work-timestamp. Branch creation errors
are now surfaced instead of silently ignored.
High: PHP verification no longer returns passed:true when no test
runner exists. Untested PHP repos correctly fail verification.
(brain/direct.go findings 5-6 verified as false positives — API
returns top-level keys, not {data: ...} envelope)
Co-Authored-By: Virgil <virgil@lethean.io>
- Module path: dappco.re/go/agent
- Core import: dappco.re/go/core v0.4.7
- Process service re-enabled with new Core API
- Plugin bumped to v0.11.0
- Directory flattened from go/ to root
Co-Authored-By: Virgil <virgil@lethean.io>
Extract 4 hardcoded templates from prep.go raw strings into
pkg/prompts/lib/templates/ as markdown files:
- coding.md — main coding template with closeout sequence
- conventions.md — convention audit (report only)
- security.md — security review
- verify.md — PR verification
- default.md — fallback
prep.go now calls prompts.Template("coding") instead of
maintaining 120 lines of raw Go string literals.
Backticks now work properly in templates — no more
concatenation hacks for inline code formatting.
Co-Authored-By: Virgil <virgil@lethean.io>