Commit graph

17 commits

Author SHA1 Message Date
Snider
7a9dbadb57 feat(agent/fleet): core login CODE + fleet connect/poll/heartbeat (#539)
Per RFC §9 Fleet Mode: device pairing + SSE-with-poll-fallback +
heartbeat + status reporting now wired.

Lands:
* pkg/agentic/fleet_login.go — `core login CODE` POSTs /v1/device/pair
  with the 6-digit code; writes {agent_api_key, agent_id, expires_at}
  to ~/.core/agent.key (mode 0600). Errors clean (no panic) on invalid
  code / network fail.
* pkg/agentic/fleet_connect.go — Connect(ctx) opens SSE to
  /v1/fleet/events with Bearer auth; reconnect backoff 1s→2s→4s→8s→
  16s→30s. PollFallback via /v1/fleet/task/next every 30s when SSE
  keeps failing. Heartbeat goroutine POSTs /v1/fleet/heartbeat every
  60s with {agent_id, status}. Persists last-known fleet snapshot to
  ~/.core/fleet.status.json so fleet/status survives restart.
* pkg/agentic/fleet_mode.go — `core fleet` top-level + `fleet/nodes`
  (lists registered nodes) + `fleet/status` (connection state, last
  heartbeat, last task). All exit cleanly on API-unreachable.
* commands.go — registerFleetCommands wired into registerCommands.
* AX-10 tests + CLI Taskfiles for login + nodes (unreachable-API
  asserted clean-exit, no panic).

Sandbox blocked from go test by go.work + private-module-graph
(pre-existing); gofmt clean.

Co-authored-by: Codex <noreply@openai.com>
Closes tasks.lthn.sh/view.php?id=539
2026-04-26 00:13:19 +01:00
Snider
c6415aa53a feat(agent/state): OnStartup queue+registry restore from .core/db.duckdb (#537)
Per RFC §15.3: restart was losing in-flight queue + workspace registry.
"Ghost agents" and "lost queue" pain now fixed.

Lands:
* pkg/agentic/persist.go (NEW):
  - OnStartup(ctx, c): opens .core/db.duckdb via go-store, restores
    registry/queue/concurrency groups
  - Dead-PID detection: registry entries with status=running but
    !pidAlive(PID) → marked failed with question="dead worker on
    restart"; status.json files re-written to disk
  - Orphaned workspace cleanup: walk .core/workspace/, dir-exists +
    registry-says-completed → delete
  - OnShutdown(ctx): flushes in-memory registry + queue back to store
    before close
* pkg/agentic/prep.go — PrepSubsystem.OnStartup/OnShutdown wired
* pkg/agentic/persist_test.go — AX-10 covering queue restore,
  dead-worker reaping, shutdown persistence, invalid-store-payload,
  orphan cleanup
* tests/cli/restart/Taskfile.yaml — extended smoke seeds DuckDB state
  for queued workspace + dead running worker, asserts status.json
  reflects restore correctly

Sandbox blocked from go test by go.work conflicting dappco.re/go/api
replacements (pre-existing); gofmt clean. Supervisor's clean workspace
catches.

Co-authored-by: Codex <noreply@openai.com>
Closes tasks.lthn.sh/view.php?id=537
2026-04-26 00:04:56 +01:00
Snider
2f9ffd5324 feat(agent/pipeline): implement pipeline/budget + pipeline/training (#536)
Replaces the #535 stubs with full impl per RFC.pipeline.md.

Lands:
* pkg/agentic/pipeline_budget.go (extend) — budget/plan reads pool/rate
  config, counts logged dispatches from .core/db.duckdb (JSONL fallback),
  prints per-pool remaining budget. budget/log appends to
  .core/journal/dispatch.jsonl + mirrors to state store.
* pkg/agentic/pipeline_training.go (extend) — training/capture pulls PR
  meta via MetaReader, captures PR diff via Forge PR-diff endpoint with
  `git show` fallback, records structural CodeRabbit-equivalent finding
  counts from review-thread totals, appends to .core/training/journal.jsonl.
  training/stats aggregates totals + zero-finding counts by repo.
  training/export filters to zero-finding entries → .core/training/export.jsonl
  (clean LEM training data).
* pkg/agentic/training_journal.go (NEW) — shared journal helpers
* AX-10 tests replace stubs (pipeline_budget_test.go +
  pipeline_training_test.go)
* tests/cli/pipeline/Taskfile.yaml — end-to-end smoke covers all 5
  subcommands against isolated temp workspace + local Forge stub

LEM training data pipeline now feedable: merged PRs → training/capture
→ journal.jsonl → training/export (zero-finding filter) → ready for next
LEK iteration.

Sandbox blocked from go test by go.work + private-dep resolution;
gofmt clean. Forge PR diff endpoint shape verified against Gitea API
docs (1.19).

Co-authored-by: Codex <noreply@openai.com>
Closes tasks.lthn.sh/view.php?id=536
2026-04-25 23:57:27 +01:00
Snider
23f4be5b85 feat(agent/pipeline): wire branch cleanup into createPR + cmdComplete success paths (#545)
Per RFC §15.5.1: agent branches (agent/*) must be deleted from Forge
after successful push or merge — stale branches pollute workspace prep
and cause clone confusion.

Lands:
* pkg/agentic/branch_cleanup.go (NEW) — cleanupBranch(ctx, repo, branch)
  helper. Refuses main/dev/master regardless of input (defensive).
  Normalises refs/heads/* prefix. Treats missing-remote-branch as
  harmless cleanup-success (idempotent).
* pkg/agentic/branch_cleanup_test.go (NEW) — AX-10 TestCleanupBranch_
  {Good_DeletesAgentBranch, Bad_RefuseProtected, Ugly_DeleteFailsForge}.
* pkg/agentic/pr.go — createPR success-on-push path now calls cleanupBranch.
* pkg/agentic/commands.go — cmdComplete success path also calls cleanupBranch.
* tests/cli/branch/Taskfile.yaml — end-to-end smoke + AX-10 unit hook.

agentic.branch.delete action was already registered in prep.go; this lane
routes the actual delete behaviour through the new helper instead of
editing the registration site.

Sandbox blocked from go test by outer go.work conflicting replacements;
gofmt clean. Supervisor's clean workspace catches.

Co-authored-by: Codex <noreply@openai.com>
Closes tasks.lthn.sh/view.php?id=545
2026-04-25 23:56:34 +01:00
Snider
92b433ad76 feat(agent/sync): WorkspacePushed IPC → go-scm local repo sync (#546)
Per RFC §7 Post-Completion Repo Sync: workspace push → IPC event →
local clone fetch+reset so the supervisor's working tree always
matches Forge.

Lands:
* pkg/agentic/repo_sync.go — registers sync.fetch + sync.reset core
  actions; subscribes to WorkspacePushed IPC; exposes core-agent
  repo/sync --repo <name> [--reset] manual command
* commands.go — wires the subscriber + actions at startup
* pkg/agentic/repo_sync_test.go — AX-10: WorkspacePushed handler,
  branch-switch/reset behaviour, command path
* tests/cli/sync/{Taskfile.yaml,repo/Taskfile.yaml} — end-to-end
  smoke proving local clone matches Forge HEAD after sync

The existing 5min fallback fetch loop in fetch_loop.go is reused
unchanged — this lane fills the event-driven half of the contract.

Sandbox blocked from go test / go build by pre-existing go.work
dappco.re/go/api replacement conflict; supervisor's clean workspace
catches.

Co-authored-by: Codex <noreply@openai.com>
Closes tasks.lthn.sh/view.php?id=546
2026-04-25 23:33:38 +01:00
Snider
53b46c33da feat(agent/pipeline): add core pipeline command tree (#535)
Per RFC.pipeline.md "core pipeline Command Tree": full audit/epic/
monitor/fix/onboard/budget/training subcommand tree wired into
core-agent.

Lands across 18 files:
* pkg/agentic/pipeline_commands.go — registry: audit, epic/create|run|
  status|sync, monitor, fix/reviews|conflicts|format|threads, onboard,
  budget/*, training/*
* pkg/agentic/commands.go — pipeline registration wired in
* pkg/agentic/pipeline_audit.go — audit issue expansion + bug fix:
  audit-created implementation issues no longer carry the 'audit' label,
  so epic + onboard see them as implementation candidates
* pkg/agentic/pipeline_epic.go — epic group/run/sync
* pkg/agentic/pipeline_monitor.go — open-PR watcher
* pkg/agentic/pipeline_fix.go — reviews/conflicts/format/threads helpers
* pkg/agentic/pipeline_onboard.go — chained audit → epic → dispatch
* pkg/agentic/pipeline_budget.go + pipeline_training.go — stubs
  returning blocked-on-sibling pointer (sibling tickets own deep impl)
* pkg/agentic/pipeline_*_test.go — AX-10 per handler
* tests/cli/pipeline/Taskfile.yaml — CLI smoke coverage

go test could not complete in this sandbox due to wider workspace
go.sum/private-module issues outside this ticket; supervisor catches
in clean workspace.

Co-authored-by: Codex <noreply@openai.com>
Closes tasks.lthn.sh/view.php?id=535
2026-04-25 23:25:37 +01:00
Snider
34010f6d35 feat(ax-10): bring agent to v0.8.0-alpha.1 + CLI test scaffold
- Bump dappco.re/go/* deps to v0.8.0-alpha.1 in go.mod (any forge.lthn.ai/core/* paths migrated to canonical dappco.re/go/* form)
- Update Go source imports across 29 .go files
- Add tests/cli/agent/Taskfile.yaml AX-10 scaffold (build/vet/test under default deps), per RFC-CORE-008-AGENT-EXPERIENCE.md §10

Co-Authored-By: Athena <athena@lthn.ai>
2026-04-24 23:48:34 +01:00
Snider
711e2eef72 feat(hermes): add openbrain_context.py ContextEngine plugin
Python plugin implementing Hermes ContextEngine backed by OpenBrain.
compress() does centrality-ranked retrieval over a candidate pool
pulled via brain_recall rather than linear turn truncation. Falls
back to naive head+tail truncation when recall is unavailable so the
caller never sees a raised exception.

Closes tasks.lthn.sh/view.php?id=74
Co-authored-by: Codex <noreply@openai.com>

Co-Authored-By: Virgil <virgil@lethean.io>
2026-04-23 17:29:50 +01:00
Snider
5a851c2f4a feat(hermes): add openbrain_memory.py MemoryProvider plugin
Python plugin implementing Hermes MemoryProvider ABC backed by OpenBrain
(Qdrant + Postgres + PHP BrainService HTTP API). Exposes is_available,
initialize, get_tool_schemas for the four brain_* MCP tools,
handle_tool_call dispatch, sync_turn non-blocking writes, Librarian-stance
system_prompt_block, on_session_end flush.

Closes tasks.lthn.sh/view.php?id=73
Co-authored-by: Codex <noreply@openai.com>

Co-Authored-By: Virgil <virgil@lethean.io>
2026-04-23 17:12:10 +01:00
e58986a3b4 revert fcb9c189e5
revert fix(agentic): harden TODO workspace write

Co-Authored-By: Virgil <virgil@lethean.io>
2026-04-23 12:32:57 +01:00
Codex
cbc262add4 fix(agentic): harden TODO workspace write
Co-Authored-By: Virgil <virgil@lethean.io>
2026-04-23 12:32:57 +01:00
Snider
ccedf536d6 fix(agent-tool-registry): harden rate limiting and api key identifiers
Co-Authored-By: Virgil <virgil@lethean.io>
2026-04-17 20:48:29 +01:00
Snider
b54daae418 fix(reference): harden core reference edge cases
Co-Authored-By: Virgil <virgil@lethean.io>
2026-04-17 20:31:06 +01:00
Snider
716546d0d5 feat(agent): workspace state mirror + ghost reap + sync queue via go-store
- prep.go TrackWorkspace mirrors into queue + concurrency store groups
  (previously only registry); hydrateWorkspaces reaps filesystem ghosts
  (dead PID → failed, persisted back to status.json) so cmdStatus and
  out-of-process consumers see coherent state (RFC §15.3)
- sync.go queue read/write goes through go-store first per RFC §16.5
  ("Queue persists across restarts in db.duckdb"), file remains fallback
  for graceful degradation
- statestore.go stateStoreGet helper for go-store-first reads
- tests/cli/restart — new CLI test for RFC §15.7 "dispatch → kill →
  restart → no ghost agents" dead-PID reap flow
- 4 new statestore tests: queue group mirror, concurrency refresh,
  sync queue persistence, fs ghost reap with disk write-back

Co-Authored-By: Virgil <virgil@lethean.io>
2026-04-14 12:36:44 +01:00
Snider
edfcb1bdfe feat(agent): unblock factory dispatch, runtime-aware containers, RFC gaps
- paths.go: resolve relative workspace_root against $HOME/Code so workspaces
  land in the conventional location regardless of launch cwd (MCP stdio vs CLI)
- dispatch.go: container mounts use /home/agent (matches DEV_USER), plus
  runtime-aware dispatch (apple/docker/podman) with GPU toggle per RFC §15.5
- queue.go / runner/queue.go: DispatchConfig adds Runtime/Image/GPU fields;
  AgentIdentity parsing for the agents: block (RFC §10/§11)
- pr.go / commands_forge.go / actions.go: agentic_delete_branch tool +
  branch/delete CLI (RFC §7)
- brain/tools.go / provider.go: Org + IndexedAt fields on Memory (RFC §4)
- config/agents.yaml: document new dispatch fields, fix identity table
- tests: dispatch_runtime_test.go (21), expanded pr_test.go + queue_test.go,
  new CLI fixtures for branch/delete and pr/list

Co-Authored-By: Virgil <virgil@lethean.io>
2026-04-14 11:45:09 +01:00
Snider
39914fbf14 refactor: AX compliance sweep — replace banned stdlib imports with core primitives
Replaced fmt, strings, sort, os, io, sync, encoding/json, path/filepath,
errors, log, reflect with core.Sprintf, core.E, core.Contains, core.Trim,
core.Split, core.Join, core.JoinPath, slices.Sort, c.Fs(), c.Lock(),
core.JSONMarshal, core.ReadAll and other CoreGO v0.8.0 primitives.

Framework boundary exceptions preserved where stdlib types are required
by external interfaces (Gin, net/http, CGo, Wails, bubbletea).

Co-Authored-By: Virgil <virgil@lethean.io>
2026-04-13 09:32:00 +01:00
Snider
9c6f10902e fix(agent): mcp.Register startup panic + test isolation + CLI test standard
- Replace broken registerMCPService with mcp.Register (fixes nil ServiceRuntime panic)
- Remove dead mcp_service.go, update tests to use mcp.Register directly
- Add setTestWorkspace() helper to clear workspaceRootOverride between tests
- Fix 40+ test files with workspace state poisoning from loadAgentConfig
- Fix forge.lthn.ai → dappco.re in findConsumersList test
- Fix BranchWorkspaceCount test to use isolated temp dir
- Add CLI test standard: 32 tests across 19 subsystems (tests/cli/)
- All 9 packages pass, 0 failures

Co-Authored-By: Virgil <virgil@lethean.io>
2026-04-08 16:15:14 +01:00