Snider
53db749738
fix(runner): reserve slot on approval to prevent TOCTOU race
...
Runner now creates a reservation entry (PID=-1) in the workspace Registry
immediately when approving a dispatch. This prevents parallel requests
from all seeing count < limit before any spawn completes.
Reservations are counted by countRunningByAgent/ByModel (PID < 0 = always
count). Agentic overwrites with real PID via TrackWorkspace after spawn.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-26 11:23:04 +00:00
Snider
8911dc5f42
fix(agentic): delegate runner/shutdown/poke to runner service
...
StartRunner and Poke are now no-ops — runner.Service owns the queue.
Shutdown MCP tools delegate to runner.start/stop/kill Actions via IPC.
Updated 18 tests to verify delegation instead of direct state mutation.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-26 11:19:45 +00:00
Snider
0fc6eeb4cc
feat(runner): extract dispatch runner into independent Core service
...
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>
2026-03-26 11:00:47 +00:00
Snider
e5b7b4f7d7
fix: only clone direct deps, skip indirect
...
parseCoreDeps now skips // indirect lines from go.mod.
Reduces cloned repos from 17 to 10 — only what the repo directly imports.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-26 07:43:02 +00:00
Snider
ba281a2a2d
feat: clone workspace dependencies + Docker cleanup
...
- 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>
2026-03-26 07:37:43 +00:00
Snider
19d849aa75
fix: use Core PerformAsync for agent monitoring — app stays alive
...
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>
2026-03-26 07:16:48 +00:00
Snider
b57be6eb91
fix: spawnAgent uses ServiceFor instead of global process.Default()
...
The global process.StartWithOptions() requires process.SetDefault() which
was never called. Use core.ServiceFor[*process.Service] to get the registered
service instance directly — same code path, proper Core wiring.
Fixes: dispatch failing with "failed to spawn codex" on CLI dispatch.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-26 06:47:44 +00:00
Snider
537226bd4d
feat: AX v0.8.0 upgrade — Core features + quality gates
...
AX Quality Gates (RFC-025):
- Eliminate os/exec from all test + production code (12+ files)
- Eliminate encoding/json from all test files (15 files, 66 occurrences)
- Eliminate os from all test files except TestMain (Go runtime contract)
- Eliminate path/filepath, net/url from all files
- String concat: 39 violations replaced with core.Concat()
- Test naming AX-7: 264 test functions renamed across all 6 packages
- Example test 1:1 coverage complete
Core Features Adopted:
- Task Composition: agent.completion pipeline (QA → PR → Verify → Ingest → Poke)
- PerformAsync: completion pipeline runs with WaitGroup + progress tracking
- Config: agents.yaml loaded once, feature flags (auto-qa/pr/merge/ingest)
- Named Locks: c.Lock("drain") for queue serialisation
- Registry: workspace state with cross-package QUERY access
- QUERY: c.QUERY(WorkspaceQuery{Status: "running"}) for cross-service queries
- Action descriptions: 25+ Actions self-documenting
- Data mounts: prompts/tasks/flows/personas/workspaces via c.Data()
- Content Actions: agentic.prompt/task/flow/persona callable via IPC
- Drive endpoints: forge + brain registered with tokens
- Drive REST helpers: DriveGet/DrivePost/DriveDo for Drive-aware HTTP
- HandleIPCEvents: auto-discovered by WithService (no manual wiring)
- Entitlement: frozen-queue gate on write Actions
- CLI dispatch: workspace dispatch wired to real dispatch method
- CLI: --quiet/-q and --debug/-d global flags
- CLI: banner, version, check (with service/action/command counts), env
- main.go: minimal — 5 services + c.Run(), no os import
- cmd tests: 84.2% coverage (was 0%)
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-26 06:38:02 +00:00
Snider
e46c1f66fa
fix: dogfood review_queue_extra_test — eliminate os + encoding/json
...
os.MkdirAll→fs.EnsureDir, os.WriteFile→fs.Write, os.ReadFile→fs.Read,
os.Remove→fs.Delete, json.Marshal→core.JSONMarshalString.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-26 02:16:44 +00:00
Snider
316dbf6018
fix: dogfood queue_extra_test — eliminate encoding/json, reduce os
...
45 os/json calls replaced with Core primitives. os remains only for
os.Getpid() (no Core equivalent for PID as int).
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-26 02:12:03 +00:00
Snider
12588e8b4e
fix: dogfood auto_pr_test + status_logic_test — eliminate os + encoding/json
...
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-26 02:07:31 +00:00
Snider
76b167a874
fix: dogfood watch_test + resume_test — eliminate os + encoding/json
...
os.MkdirAll→fs.EnsureDir, os.WriteFile→fs.Write, os.ReadFile→fs.Read,
json.Marshal→core.JSONMarshalString. Both files now clean.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-26 02:03:08 +00:00
Snider
68b55572f1
fix: dogfood status_test.go — eliminate encoding/json
...
json.MarshalIndent→core.JSONMarshalString, json.Unmarshal→core.JSONUnmarshalString.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-26 01:58:36 +00:00
Snider
7be229d40d
fix: dogfood handlers_test + commands_workspace_test
...
os.MkdirAll→fs.EnsureDir, os.WriteFile→fs.Write,
json.Marshal→core.JSONMarshalString, os.Stat→fs.Exists/fs.IsDir.
Both files now free of os + encoding/json.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-26 01:55:57 +00:00
Snider
56981772c7
fix: dogfood dispatch_test.go — eliminate os + json.Marshal
...
os.WriteFile→fs.Write, os.MkdirAll→fs.EnsureDir, os.ReadFile→fs.Read,
os.Stat+os.IsNotExist→fs.Exists, json.Marshal→core.JSONMarshalString.
Only json.NewEncoder remains (httptest handler — legitimate).
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-26 01:51:03 +00:00
Snider
b3ed21b6a3
wip: test dogfooding — dispatch_test.go json.Marshal→core.JSONMarshalString
...
Partial migration of dispatch_test.go: 5 of 9 json.Marshal+os.WriteFile
pairs replaced with fs.Write+core.JSONMarshalString. Pattern established
for remaining 74 calls across 30 test files.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-26 01:46:25 +00:00
Snider
23bb62a116
fix: eliminate path/filepath from all test files
...
29 test files migrated: filepath.Join→core.JoinPath,
filepath.Dir→core.PathDir, filepath.Base→core.PathBase,
filepath.IsAbs→core.PathIsAbs. Test dogfooding complete for filepath.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-26 01:39:41 +00:00
Snider
aafa63818f
fix: remove dead client field from PrepSubsystem + test literals
...
client *http.Client removed — all HTTP routes through transport.go.
75 test struct literals cleaned, 3 test assertions updated.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-26 01:32:17 +00:00
Snider
f83c753277
feat(v0.8.0): full AX migration — ServiceRuntime, Actions, quality gates, transport
...
go-process:
- Register factory, Result lifecycle, 5 named Action handlers
- Start/Run/StartWithOptions/RunWithOptions all return core.Result
- core.ID() replaces fmt.Sprintf, core.As replaces errors.As
core/agent:
- PrepSubsystem + monitor.Subsystem + setup.Service embed ServiceRuntime[T]
- 22 named Actions + agent.completion Task pipeline in OnStartup
- ChannelNotifier removed — all IPC via c.ACTION(messages.X{})
- proc.go: all methods via s.Core().Process(), returns core.Result
- status.go: WriteAtomic + JSONMarshalString
- paths.go: Fs.NewUnrestricted() replaces unsafe.Pointer
- transport.go: ONE net/http file — HTTPGet/HTTPPost/HTTPDo/MCP transport
- All disallowed imports eliminated from source files (13 quality gates)
- String concat eliminated — core.Concat() throughout
- 1:1 _test.go + _example_test.go for every source file
- Reference docs synced from core/go v0.8.0
- RFC-025 updated with net/http, net/url, io/fs quality gates
- lib.go: io/fs eliminated via Data.ListNames, Array[T].Deduplicate
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-26 01:27:46 +00:00
Snider
3522a3bea5
test: RegisterTools GBU + buildPrompt git log — 840 tests, 79.9% coverage
...
- RegisterTools: exercises all 12 register*Tool functions via mcp.NewServer (+1.4pp)
- buildPrompt: test with real git repo for RECENT CHANGES path
- AX-7: 92% categories filled
0.1pp from 80%. Remaining gap is process-dependent functions
awaiting go-process v0.7.0 update.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-25 10:28:30 +00:00
Snider
d67336c761
test: batch 5 — proc.go GBU + getGitLog + runGoTests + prepWorkspace — 836 tests
...
New: proc_test.go with 28 tests for all proc.go helpers (runCmd, gitCmd,
gitOutput, processIsRunning, processKill, ensureProcess).
Plus: getGitLog GBU, runGoTests GBU, prepWorkspace Good,
listLocalRepos Ugly, loadRateLimitState Bad, runLoop skips.
AX-7: 501/543 filled (92%), 167/181 functions complete
Coverage: 78.5%, 836 tests
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-25 10:20:50 +00:00
Snider
4eb1111faa
refactor: clean up proc.go — ensureProcess bridge, processIsRunning/processKill helpers
...
- proc.go: ensureProcess() as temporary bridge until go-process gets v0.7.0 update
- processIsRunning/processKill: use go-process ProcessID when available, fall back to PID
- WorkspaceStatus: add ProcessID field for go-process managed lookup
- dispatch.go: simplified spawnAgent goroutine — uses proc.Done() instead of syscall poll
- Removed syscall import from dispatch.go
Next: update go-process to v0.7.0 Core contract, then replace
syscall.Kill calls in queue.go, shutdown.go, status.go, dispatch_sync.go
with processIsRunning/processKill.
Coverage: 78.1%, 802 tests
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-25 10:10:17 +00:00
Snider
8521a55907
refactor: eliminate os/exec from all source files → go-process
...
Replace ALL exec.Command calls with proc.go helpers backed by go-process:
- runCmd/runCmdEnv/runCmdOK — general command execution
- gitCmd/gitCmdOK/gitOutput — git-specific helpers
- ensureProcess() — lazy default service init
Refactored files (0 source files import os/exec now):
- verify.go: runGoTests, runPHPTests, runNodeTests, rebaseBranch
- dispatch.go: runQA (3 exec.Command chains → runCmdOK)
- prep.go: getGitLog, prepWorkspace clone/branch
- pr.go: createPR branch detection + push
- auto_pr.go: commit counting + push
- mirror.go: all git ops + gh CLI calls
- review_queue.go: pushAndMerge, buildReviewCommand (returns string+args now)
- paths.go: DefaultBranch
Coverage: 77.2% → 78.4% (+1.2pp from testable process paths)
802 tests
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-25 09:51:57 +00:00
Snider
c0bc7675a1
test: batch 4 — fill 36 testable gaps, 802 tests, AX-7 89%
...
- commands.go: factory wrapper Good/Bad/Ugly
- dispatch.go: containerCommand Bad
- queue.go: UnmarshalYAML/loadAgentsConfig Good/Bad/Ugly
- remote.go: resolveHost/remoteToken Bad/Ugly
- remote_client.go: setHeaders Bad
- prep.go: TestPrepWorkspace/TestBuildPrompt public API GBU
- prep.go: sanitise Good tests (collapseRepeatedRune, sanitisePlanSlug, trimRuneEdges)
- ingest.go: ingestFindings/createIssueViaAPI Ugly
- scan.go: scan Good
- runner.go: Poke Ugly, StartRunner Bad/Ugly
- process_register.go: ProcessRegister Good/Bad/Ugly
AX-7: 462/516 filled (89%), 152/172 functions complete
Coverage: 77.2%, 802 tests
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-25 09:31:38 +00:00
Snider
eeaed52256
test: batch 3 — add 73 Good/Bad/Ugly tests across 9 files
...
Fill missing categories for:
- prep.go: 25 lifecycle/detect/env tests
- prep_extra.go: pullWikiContent/renderPlan/brainRecall/findConsumers Ugly
- pr.go: buildPRBody/commentOnIssue/createPR/listPRs/listRepoPRs GBU
- epic.go: createEpic/createIssue/resolveLabelIDs/createLabel Ugly
- scan.go: scan/listOrgRepos/listRepoIssues GBU
- events (logic_test.go): emitStartEvent/emitCompletionEvent GBU
- review_queue_extra.go: buildReviewCommand/countFindings/parseRetryAfter/store/save/load
- watch.go: findActiveWorkspaces/resolveWorkspaceDir Bad/Ugly
- paths.go: newFs/parseInt Good
- plan_crud.go: generatePlanID/planList/writePlan Bad/Ugly
AX-7 scorecard: 425/516 categories filled (82%)
Gap: 166 → 91 missing categories
Tests: 690 → 765 (+75)
Coverage: 76.0% → 76.8%
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-25 09:19:05 +00:00
Snider
9002b7ca8a
test: batch 2 — add 44 Bad/Ugly tests for commands, verify, queue, remote_client
...
Fill missing categories for:
- commands.go: CmdExtract/Orchestrator/Prep/Prompt/RunTask/Status Bad/Ugly
- commands_workspace.go: List/Clean/Dispatch/ExtractField Bad/Ugly
- verify.go: EnsureLabel/GetLabelID/ForgeMergePR/FileExists/FlagForReview/RunVerification Ugly
- queue.go: CanDispatchAgent/CountRunning/DelayForAgent/DrainOne/DrainQueue Bad/Ugly
- remote_client.go: McpInitialize/McpCall/ReadSSEData/SetHeaders/DrainSSE Ugly
Gap: 208 → 166 missing categories (-42)
Tests: 646 → 690 (+44)
Coverage: 74.4% → 76.0%
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-25 08:53:28 +00:00
Snider
a5afad870c
test: batch 1 — add 80 Bad/Ugly tests for paths, plan, status, shutdown, forge cmds
...
Fill missing Good/Bad/Ugly categories for:
- paths.go: LocalFs, WorkspaceRoot, CoreRoot, PlansRoot, AgentName, GitHubOrg, parseInt, DefaultBranch
- plan.go: planCreate/Read/Update/Delete/List Ugly, planPath Ugly, validPlanStatus Ugly
- status.go: writeStatus Bad, status Good/Bad
- shutdown.go: dispatchStart/shutdownGraceful Bad/Ugly, shutdownNow Ugly
- commands_forge.go: all 9 cmd* functions Ugly (with httptest mocks)
- sanitise.go: Bad/Ugly for all 5 functions
- prep.go: various lifecycle Bad/Ugly
Gap: 260 → 208 missing categories
Tests: 566 → 646 (+80)
Coverage: 74.4%
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-25 08:43:35 +00:00
Snider
97d06c1e90
refactor(test): bulk rename 478 tests to TestFile_Function_{Good,Bad,Ugly}
...
Mechanical rename of all test functions to follow the convention:
TestFilename_FunctionName_{Good,Bad,Ugly}
Examples:
TestForgeMergePR_Good_Success → TestVerify_ForgeMergePR_Good_Success
TestAgentCommand_Good_Gemini → TestDispatch_AgentCommand_Good_Gemini
TestReadStatus_Bad_NoFile → TestStatus_ReadStatus_Bad_NoFile
Gap analysis now works: 137 functions still need 260 missing categories.
566 tests, agentic 74.3% — naming is now the tooling.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-25 08:32:08 +00:00
Snider
8b46e15d24
test: add Ugly tests for queue, shutdown, verify, status, review_queue
...
- TestQueue_CanDispatchAgent_Ugly — Core.Config concurrency path
- TestQueue_DrainQueue_Ugly — Core lock path
- TestShutdown_ShutdownNow_Ugly — deep layout
- TestVerify_AutoVerifyAndMerge_Ugly — invalid PR URL
- TestVerify_AttemptVerifyAndMerge_Ugly — build failure
- TestVerify_ExtractPRNumber_Ugly — edge cases
- TestStatus_WriteStatus_Ugly — full roundtrip
- TestReviewQueue_LoadRateLimitState_Ugly — corrupt JSON
agentic 74.3%, 566 tests
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-25 08:26:15 +00:00
Snider
acae0d804f
test: add Good/Bad/Ugly for status, paths, auto_pr, prep — agentic 74.0%
...
New properly named tests:
- TestStatus_Status_Ugly — dead PID detection (blocked/completed/failed)
- TestPaths_DefaultBranch_{Good,Bad,Ugly} — main/master/non-git
- TestAutoPR_AutoCreatePR_{Good,Bad,Ugly} — early returns + no commits
- TestPrep_BuildPrompt_{Good,Bad,Ugly} — basic/empty/persona+issue
558 agentic tests, 74.0% coverage
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-25 08:16:53 +00:00
Snider
3c894e8101
refactor(test): proper naming — resume, remote, remote_status
...
Rewrite tests with TestFile_Function_{Good,Bad,Ugly} convention.
Split remote_dispatch_test.go → remote.go tests + remote_status_test.go.
Resume tests consolidated with all 3 test categories.
agentic 73.2% (recovering after catch-all deletion)
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-25 08:11:39 +00:00
Snider
52f6031822
refactor(test): delete catch-all test files, rewrite dispatch_test.go
...
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>
2026-03-25 08:08:36 +00:00
Snider
18eac65b70
test: coverage push — status dead PID, PR branches, DefaultBranch — agentic 75.5%
...
822 total tests across all packages. Exercises:
- statusRemote error/call-fail paths
- loadRateLimitState corrupt JSON
- shutdownNow deep layout
- findReviewCandidates no github remote
- prepWorkspace path traversal
- dispatch dry run
- DefaultBranch master fallback
- attemptVerifyAndMerge test failure
- resume completed workspace
- buildPRBody, runQA node, extractPRNumber edges
Coverage: agentic 74.8% → 75.5% (+0.7pp)
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-25 01:24:08 +00:00
Snider
ccf8e3bc7d
test: edge cases for status, createPR, autoCreatePR, buildPrompt — agentic 74.8%
...
- status: dead PID detection (blocked/completed/failed paths)
- createPR: no status file, branch detection from git, default title
- autoCreatePR: no status, empty branch/repo, no commits
- DefaultBranch: git repo + non-git fallback
- cmdPrep: issue/pr/branch/tag parsing paths
- cmdRunTask: defaults + issue parsing
- canDispatchAgent: Core config path
- buildPrompt: persona + plan template branches
- writeStatus: timestamp + field preservation
Coverage: agentic 72.3% → 74.8% (+2.5pp)
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-25 01:20:08 +00:00
Snider
e0a6b33729
test: issue tracking + broadcast with Forge mocks — agentic 72.3%
...
Add httptest mocks for startIssueTracking/stopIssueTracking with Forge,
broadcastStart/broadcastComplete with Core IPC.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-25 01:15:19 +00:00
Snider
d30b07e34f
test: renderPlan + dispatchRemote + statusRemote — agentic 71.5%, 559 tests
...
- renderPlan: test with real embedded templates (bug-fix, new-feature)
- dispatchRemote: full MCP roundtrip with httptest mock
- statusRemote: validation + unreachable + full roundtrip
Coverage: agentic 67.8% → 71.5% (+3.7pp)
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-25 01:13:35 +00:00
Snider
1e12b062dd
refactor: decompose spawnAgent monolith — agentic 67.8%, 546 tests
...
Extract 7 functions from 150-line spawnAgent goroutine:
- detectFinalStatus: BLOCKED.md + exit code → status/question
- trackFailureRate: fast-failure detection + backoff
- startIssueTracking/stopIssueTracking: Forge stopwatch
- broadcastStart/broadcastComplete: IPC + audit events
- onAgentComplete: orchestrates all post-completion steps
- agentOutputFile: log path helper
spawnAgent is now: build command → start process → broadcast → monitor.
All extracted functions are independently testable.
Coverage: agentic 66.4% → 67.8% (+1.4pp)
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-25 01:11:04 +00:00
Snider
cf68371421
test: command method edge cases — agentic 66.4%, 524 tests
...
Add error path tests for all forge commands (API errors, missing args),
PR with body, issue create with labels/milestones, workspace clean filters.
Coverage: agentic 65.1% → 66.4% (+1.3pp)
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-25 00:56:19 +00:00
Snider
3d7adb91eb
refactor: extract commands.go closures into methods — agentic 65.1%
...
Extract run/task, orchestrator, prep, status, prompt, extract closures
into standalone methods on PrepSubsystem. Extract shared parseIntStr helper.
Coverage: agentic 61.4% → 65.1% (+3.7pp)
Total: 512 agentic tests
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-25 00:54:07 +00:00
Snider
b5cb294b25
refactor: extract command closures into named methods — agentic 61.4%
...
Move all command closure bodies from registerForgeCommands,
registerWorkspaceCommands into standalone methods (cmd*) on PrepSubsystem.
This makes them directly testable without CLI integration.
New: 9 forge command methods (cmdIssueGet, cmdIssueList, cmdIssueComment,
cmdIssueCreate, cmdPRGet, cmdPRList, cmdPRMerge, cmdRepoGet, cmdRepoList)
+ 3 workspace methods (cmdWorkspaceList, cmdWorkspaceClean, cmdWorkspaceDispatch)
Coverage: agentic 54.3% → 61.4% (+7.1pp)
Total: 501 agentic tests, 727 across all packages
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-25 00:52:00 +00:00
Snider
277510ee16
test: 413 new tests — agentic 54.3%, setup 75.8%, all packages passing
...
Coverage: agentic 40.1% → 54.3%, setup 71.5% → 75.8%
Total: 695 passing tests across all packages (was ~357)
New test files (15):
- commands_forge_test.go — parseForgeArgs, fmtIndex
- commands_workspace_test.go — extractField (9 cases)
- commands_test.go — command registration + Core integration
- handlers_test.go — RegisterHandlers, IPC pipeline, lifecycle
- plan_crud_test.go — full CRUD via MCP handlers (23 tests)
- prep_extra_test.go — buildPrompt, findConsumersList, pullWikiContent, getIssueBody
- queue_extra_test.go — ConcurrencyLimit YAML, delayForAgent, drainOne
- remote_client_test.go — mcpInitialize, mcpCall, readSSEData, setHeaders
- remote_test.go — resolveHost, remoteToken
- resume_test.go — resume dry run, agent override, validation
- review_queue_test.go — countFindings, parseRetryAfter, buildAutoPRBody
- review_queue_extra_test.go — buildReviewCommand, rateLimitState, reviewQueue
- verify_extra_test.go — attemptVerifyAndMerge, autoVerifyAndMerge pipeline
- watch_test.go — findActiveWorkspaces, resolveWorkspaceDir
- setup/setup_extra_test.go — defaultBuildCommand, defaultTestCommand all branches
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-25 00:44:17 +00:00
Snider
04f91ed6a0
feat: all commands in services — cmd/ has only main.go (97 lines) + update.go (24 lines)
...
- forge.go moved to pkg/agentic/commands_forge.go
- Uses s.forge directly (no newForgeClient())
- registerForgeCommands called in OnStartup
- main.go: 97 lines, zero command registration
- cmd/ total: 121 lines (was 650+)
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-25 00:06:46 +00:00
Snider
72387dde91
feat: move workspace + process commands into services — main.go 98 lines
...
- ProcessRegister: proper factory in pkg/agentic
- Workspace commands (list/clean/dispatch): moved to agentic.registerWorkspaceCommands
- workspace.go deleted from cmd/
- main.go: 98 lines, just core.New + app commands + c.Run()
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-25 00:03:22 +00:00
Snider
4359b3d8d4
test(agentic): add status_extra_test.go — status, shutdown, brain, and lifecycle tests
...
Tests status tool (empty/mixed/deep/corrupt workspaces), shutdown tools
(start/graceful/now with queued cleanup), brainRecall (success/empty/error),
prepWorkspace validation, listPRs, Poke, OnShutdown, drainQueue.
23 tests pushing coverage from 39.4% to 44.1%.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-24 23:31:28 +00:00
Snider
27032d980f
test(agentic): add pr_test.go — PR creation and listing tests
...
Tests forgeCreatePR, createPR (validation, dry-run, custom title),
listPRs validation, commentOnIssue via mock Forge API.
9 tests covering the PR creation pipeline.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-24 23:31:21 +00:00
Snider
64f3f3b060
test(agentic): add dispatch_test.go — dispatch validation, runQA, workspace tests
...
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>
2026-03-24 23:31:14 +00:00
Snider
507bf55eb5
test(agentic): add scan_test.go — Forge issue scanning with mock API
...
Tests scan tool with mockScanServer (org repos, issue listing, dedup),
listRepoIssues (assignee extraction, URL rewriting, error handling).
11 tests covering filtering, limits, labels, and deduplication.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-24 23:31:07 +00:00
Snider
0008e269e4
test(agentic): add ingest_test.go — findings ingestion and issue creation tests
...
Tests ingestFindings pipeline (completed/not-completed/no-log/quota-exhausted),
createIssueViaAPI with mock Brain API, and security-specific countFileRefs cases.
13 tests covering the full ingest flow and edge cases.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-24 23:30:58 +00:00
Snider
ce682e42fe
test(agentic): add verify_test.go — PR merge, labels, and verification tests
...
Tests forgeMergePR, ensureLabel, getLabelID, runVerification, flagForReview,
autoVerifyAndMerge, fileExists, truncate via mock Forge API.
33 tests covering merge success/conflict/error, label CRUD, and project detection.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-24 23:30:50 +00:00
Snider
805be3bf32
test(agentic): add epic_test.go — Forge API integration tests with httptest
...
Tests createIssue, resolveLabelIDs, createLabel, createEpic via mock Forge.
Shared mockForgeServer and newTestSubsystem helpers for reuse.
19 tests covering success, validation, and error paths.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-24 23:30:44 +00:00