feat: AX v0.8.0 upgrade — Core features + quality gates #21

Closed
Virgil wants to merge 0 commits from feat/ax-v080-upgrade into dev
Member

Summary

  • 79 files changed, 1477 insertions, 1338 deletions
  • AX quality gates clean: 0 disallowed imports, 0 naming violations, 0 string concat
  • 12 Core features adopted: Task composition, PerformAsync, Config, Registry, QUERY, HandleIPCEvents, Entitlement, Data mounts, Action descriptions, Drive REST helpers, content Actions, feature flags
  • CLI dispatch wired, --quiet/--debug flags, banner, cmd tests at 84.2%
  • main.go: 5 services + c.Run() — no os import

Test plan

  • go test ./... — all pass
  • go build ./cmd/core-agent/ — compiles
  • CLI functional test: version, check, env, status, workspace list/clean, issue/pr/repo list, prompt, extract
  • AX verification: all 4 checks clean
  • Codex review pass

🤖 Generated with Claude Code
Co-Authored-By: Virgil virgil@lethean.io

## Summary - **79 files changed**, 1477 insertions, 1338 deletions - AX quality gates clean: 0 disallowed imports, 0 naming violations, 0 string concat - 12 Core features adopted: Task composition, PerformAsync, Config, Registry, QUERY, HandleIPCEvents, Entitlement, Data mounts, Action descriptions, Drive REST helpers, content Actions, feature flags - CLI dispatch wired, --quiet/--debug flags, banner, cmd tests at 84.2% - main.go: 5 services + c.Run() — no os import ## Test plan - [x] `go test ./...` — all pass - [x] `go build ./cmd/core-agent/` — compiles - [x] CLI functional test: version, check, env, status, workspace list/clean, issue/pr/repo list, prompt, extract - [x] AX verification: all 4 checks clean - [ ] Codex review pass 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Virgil <virgil@lethean.io>
Virgil added 18 commits 2026-03-26 06:39:09 +00:00
Was: "current state → target state" migration narrative
Now: "this is what core/agent v0.8.0 IS" API contract

14 sections covering: registration, actions, pipeline, process,
status, filesystem, validation, entitlements, MCP aggregator,
remote dispatch, JSON, testing, quality gates.

Written with full core/go domain context — every example uses
the implemented v0.8.0 primitives.

Co-Authored-By: Virgil <virgil@lethean.io>
- Section 14: String operations — Println, Sprintf, Concat, Path, Contains, Split, Trim
- Section 15: AX Principle 2 — every exported function needs usage-example comment
- Section 16: Example tests — one {source}_example_test.go per source file
- Section 17: Quality gates — all 10 disallowed imports + string concat check

The next session agent loads this RFC and knows exactly what v0.8.0 looks like.

Co-Authored-By: Virgil <virgil@lethean.io>
Complete coverage of every core/go primitive:
- Section 14: Error handling (core.E, Wrap, Root) + Logging (Info, Warn, Security)
- Section 15: Configuration (Config.Set/Get/String/Int, feature flags)
- Section 16: Registry[T] (workspace tracking, cross-cutting queries)
- Section 17: Stream helpers (ReadAll, WriteAll, CloseStream)
- Section 18: Data (embedded assets) + Drive (transport config)

22 sections total. Every core/go primitive mapped to core/agent usage.
Next session loads this + core/go RFC → complete domain context.

Co-Authored-By: Virgil <virgil@lethean.io>
- Depends on: go-process v0.7.0 → v0.8.0
- Section 6: readStatus uses JSONUnmarshalString + Fs.Read (dogfood)
- Section 22: quality gate grep uses generic paths not pkg/**
- Fixed double blank line in Section 19

Co-Authored-By: Virgil <virgil@lethean.io>
- Current State: lists every file that needs migration with specific action
- File Layout: annotated tree showing DELETE/REWRITE/MIGRATE per file
- MCP closure capture bug fixed (re-resolve action at call time)
- Message types location documented (pkg/messages/)

Future session reads this and knows exactly what to touch.

Co-Authored-By: Virgil <virgil@lethean.io>
Step-by-step: load 3 RFCs, verify understanding, work migration,
follow session cadence. Lists what NOT to do (10 disallowed imports,
no string concat, no anonymous closures, no nested ACTION).

Co-Authored-By: Virgil <virgil@lethean.io>
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>
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>
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>
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>
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>
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>
json.MarshalIndent→core.JSONMarshalString, json.Unmarshal→core.JSONUnmarshalString.

Co-Authored-By: Virgil <virgil@lethean.io>
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>
Co-Authored-By: Virgil <virgil@lethean.io>
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>
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>
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>
Virgil added 1 commit 2026-03-26 06:47:46 +00:00
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>
Virgil added 1 commit 2026-03-26 07:16:50 +00:00
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>
Virgil added 1 commit 2026-03-26 07:18:36 +00:00
Found by Codex review dispatched from core-agent CLI.

Co-Authored-By: Virgil <virgil@lethean.io>
Virgil added 1 commit 2026-03-26 07:37:45 +00:00
- 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>
Virgil added 1 commit 2026-03-26 07:43:05 +00:00
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>
Virgil added 1 commit 2026-03-26 09:37:03 +00:00
Co-Authored-By: Virgil <virgil@lethean.io>
Virgil added 1 commit 2026-03-26 11:01:21 +00:00
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>
Virgil added 1 commit 2026-03-26 11:19:53 +00:00
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>
Virgil added 1 commit 2026-03-26 11:23:06 +00:00
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>
Virgil added 1 commit 2026-03-26 11:30:41 +00:00
ConfigGet type assertion fails across package boundaries —
agentic stores map[string]agentic.ConcurrencyLimit but runner
tries to retrieve map[string]runner.ConcurrencyLimit.

Use Core's c.Config().Get() → Result → type assert instead.
This is why concurrency limits were never enforced.

Co-Authored-By: Virgil <virgil@lethean.io>
Virgil added 1 commit 2026-03-26 11:55:46 +00:00
Runner HandleIPCEvents now catches AgentStarted in addition to
AgentCompleted, sending ChannelPush to MCP for both lifecycle events.

Co-Authored-By: Virgil <virgil@lethean.io>
Snider closed this pull request 2026-03-29 20:32:39 +00:00

Pull request closed

Sign in to join this conversation.
No description provided.