Commit graph

100 commits

Author SHA1 Message Date
Virgil
985bc2017f refactor(mcp): align AX DTO defaults and IDE config
Normalize the MCP constructor workspace defaulting to use the actual working directory, and replace the IDE subsystem's functional options with a Config DTO so the codebase stays aligned with AX-style configuration objects.

Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-31 18:02:16 +00:00
Virgil
5177dc391b docs(mcp): refresh AX migration notes and options references 2026-03-30 07:52:58 +00:00
Virgil
ea8478b776 feat(mcp): align channel notifications with AX notifier flow 2026-03-30 05:48:11 +00:00
Snider
014c18e563 fix(mcp): set stdioMode in ServeStdio + use shared locked writer
ServeStdio never set stdioMode=true, so ChannelSend always returned
early. Also switched from StdioTransport to IOTransport with a shared
lockedWriter that both the SDK and ChannelSend write through.

This fixes channel notifications not arriving in Claude Code sessions.

Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-26 12:22:53 +00:00
Snider
c8089fd597 fix(mcp): use shared locked writer for channel notifications
ChannelSend was writing to os.Stdout directly while the SDK's
StdioTransport also writes to os.Stdout — causing interleaved
JSON-RPC messages. Now both use a shared lockedWriter via IOTransport.

Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-26 12:22:53 +00:00
Snider
3ece6656d2 feat(mcp): add ChannelPush IPC message + HandleIPCEvents
Services can now push channel events to Claude Code by sending a
ChannelPush message via Core IPC. The MCP service catches it in
HandleIPCEvents and calls ChannelSend to the stdio transport.

- ChannelPush{Channel, Data} message type in subsystem.go
- HandleIPCEvents on Service catches ChannelPush → ChannelSend
- Enables runner→mcp→Claude Code notification pipeline

Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-26 12:22:53 +00:00
Snider
c68698fc5c deps: bump dappco.re/go/core to v0.8.0-alpha.1
Resolves build failures from using Core primitives (JSONMarshalString,
JSONUnmarshal, ReadAll, ServiceRuntime, etc.) that didn't exist in v0.4.7.

Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-26 12:22:46 +00:00
Snider
63dab254bf fix: ide/bridge.go — remove encoding/json
json.Marshal → core.JSONMarshalString
json.Unmarshal → core.JSONUnmarshal

Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-26 12:22:46 +00:00
Snider
83bcb1e5e1 fix: bridge.go — remove encoding/json entirely
Error classification uses string match on unmarshal errors instead of
stdlib json.SyntaxError/UnmarshalTypeError type assertions. No exceptions.

Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-26 12:22:46 +00:00
Snider
3d3deb1bf5 fix: bridge.go — io.ReadAll → core.ReadAll, errors.As → core.As
encoding/json stays for SyntaxError/UnmarshalTypeError type assertions.
net/http stays — transport boundary.

Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-26 12:22:46 +00:00
Snider
0e38e3a7f0 feat: AX quality gate — eliminate disallowed imports from production code
- mcp.go: os/filepath/strings → core.Env, core.JoinPath, core.PathExt,
  core.PathBase, core.Contains, core.Replace + local helpers
- registry.go: encoding/json/strings → core.JSONUnmarshal, core.Split
- notify.go: encoding/json → core.JSONMarshalString
- tools_metrics.go: fmt/strings → core.Sprintf, core.Trim
- tools_rag.go: fmt → core.Sprintf
- tools_webview.go: fmt → core.Sprintf
- tools_ws.go: fmt → core.Sprintf

Transport files (http/tcp/unix/stdio) retain os/net/http — boundary code.

Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-26 12:22:27 +00:00
Snider
403a15f391 feat: migrate registry.go + notify.go to Core primitives
- registry.go: encoding/json → core.JSONUnmarshal, strings → core.Split
- notify.go: encoding/json → core.JSONMarshalString
- Both files now import dappco.re/go/core instead of stdlib

Remaining: mcp.go has os/strings/filepath (transport boundary),
tests need forge.lthn.ai → dappco.re module path migration.

Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-26 12:22:27 +00:00
Snider
66527165d0 feat: add ServiceRuntime to MCP Service + use s.Core()
MCP Service now embeds *core.ServiceRuntime[McpOptions] like all v0.8.0
services. OnStartup uses s.Core() instead of casting coreRef.

Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-26 12:22:27 +00:00
Snider
96f46e53cb fix: OnStartup/OnShutdown return core.Result (v0.8.0 Startable interface)
Was returning error — Core didn't recognise it as Startable so mcp/serve
commands were never registered. One-line fix per method.

Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-26 12:22:27 +00:00
d02853cb6c Merge pull request 'feat: mcp.Register + module path dappco.re/go/mcp' (#15) from feat/core-service-pattern into dev 2026-03-24 22:10:00 +00:00
Snider
3d62d2f531 feat: migrate module path forge.lthn.ai/core/mcp → dappco.re/go/mcp
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-24 21:39:52 +00:00
Snider
4ae003e6d8 feat: MCP registers mcp/serve commands in OnStartup
Service stores Core ref, registers transport commands during lifecycle.
Commands use Service methods directly — no external wiring.

Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-24 21:24:15 +00:00
Snider
7957013500 feat: mcp.Register for core.WithService — auto-discovers subsystems from Core
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-24 21:16:10 +00:00
18ccaec720 Merge pull request 'Update MCP SDK migration plan' (#13) from agent/update-the-migration-plan-at-docs-plans into dev
Reviewed-on: #13
2026-03-24 11:43:22 +00:00
Snider
f15d2cb6ce Merge origin/dev into agent/update-the-migration-plan-at-docs-plans
Resolve conflicts:
- docs/plans/2026-03-21-mcp-sdk-migration.md: keep PR version (AX conventions + notifications plan)
- pkg/mcp/tools_process_ci_test.go: keep dappco.re/go/core import + new Core API

Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-24 11:42:10 +00:00
35f6a12639 Merge pull request 'Fix Codex review findings' (#12) from agent/fix-the-following-codex-review-findings into dev
Reviewed-on: #12
2026-03-24 11:37:44 +00:00
2e4608e6b5 Merge branch 'dev' into agent/fix-the-following-codex-review-findings 2026-03-24 11:37:34 +00:00
87b98b0c44 Merge pull request 'Create MCP SDK migration plan' (#14) from agent/create-a-migration-plan-to-replace-the-m into dev
Reviewed-on: #14
2026-03-24 11:37:19 +00:00
ef8ab58d2e Merge pull request '[agent/codex:gpt-5.3-codex-spark] Fix ALL findings from issue #6. Read CLAUDE.md. MCP transpor...' (#10) from agent/full-audit-per-issue--6--read-claude-md into dev 2026-03-23 14:33:54 +00:00
Virgil
d3c7210433 fix(mcp): harden transport auth and workspace prep path validation
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-23 14:33:35 +00:00
Snider
2992f872f0 revert(agentic): remove pipeline chaining from dispatch
MCP SDK doesn't support nested struct slices in schema generation.
Pipeline orchestration will be handled at a higher level.

Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 07:56:28 +00:00
Snider
1d46159340 feat(agentic): pipeline chaining — review→fix→verify in one dispatch
DispatchInput now accepts Pipeline []PipelineStep for follow-up steps.
On agent completion, the next step auto-dispatches with {{.Findings}}
replaced by the previous agent's output. Enables:

  dispatch(review) → auto(fix with findings) → auto(verify)

WorkspaceStatus stores NextSteps for the completion handler.

Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 07:46:44 +00:00
Snider
517afe627f revert(agentic): remove hardcoded copyReference — use embedded templates
Reference files are now embedded in core-agent's workspace template
(pkg/lib/workspace/default/.core/reference/). No hardcoded paths needed.

Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 07:00:03 +00:00
Snider
2bbc8063cf feat(agentic): auto-copy AX spec + Core source into agent workspaces
prepWorkspace now copies RFC-025-AGENT-EXPERIENCE.md and all Core .go
files into .core/reference/ in every dispatched workspace. Agents can
read the AX conventions and Core API without network access.

Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 06:47:04 +00:00
Snider
4329bd7f27 fix(agentic): write status before spawn to prevent concurrency race
writeStatus("running") was after cmd.Start(), so rapid sequential
dispatches all saw 0 running. Now writes status immediately after
the concurrency check passes, before spawning. Updates with PID
after start. Reverts to "failed" if spawn fails.

Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 02:32:17 +00:00
Snider
72ba11b481 fix(agentic): config path is ~/Code/.core/agents.yaml only
All .core/ config lives at codePath/.core/ — not in individual repos.

Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 02:28:05 +00:00
Snider
5d749af517 fix(mcp): resolve codex review findings — spelling, imports, tests, assertions
- UK English in transport_e2e_test.go comments and error strings
- Replace fmt.Printf with coreerr.Error/Warn in brain-seed for errors/skips
- Alias stdlib io as goio in transport_tcp, brain/direct, agentic/prep, bridge, brain-seed
- Add var _ Notifier = (*Service)(nil) compile-time assertion
- Add TestRegisterProcessTools_Bad_NilService for nil-service error path
- Add webview handler tests beyond nil-guard (disconnect success, validation paths)
- Guard tools_process_ci_test.go with //go:build ci (pre-existing build failure)
- Document circular-import exception in EXCEPTIONS.md

Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 02:14:33 +00:00
Snider
94cc1b9ed5 fix(agentic): scan nested workspace dirs for concurrency + status
listWorkspaceDirs() now recurses one level into subdirectories
(e.g. workspace/core/go-io-123/) so countRunningByAgent and
agentic_status find workspaces regardless of directory structure.

Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 02:11:59 +00:00
Snider
90bb784e79 fix(agentic): workspace root is ~/Code/.core/ not ~/Code/host-uk/core/.core/
The hardcoded host-uk/core path doesn't exist on the homelab,
causing countRunningByAgent to always return 0 (no concurrency limiting)
and agentic_status to miss workspaces.

Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 01:57:12 +00:00
Snider
907d62a545 fix(mcp): resolve 17 code review findings + php route('login') fix
Some checks failed
CI / test (push) Failing after 2s
Go (17 findings from Codex sweep):
- CRITICAL: bare type assertion panic in tools_metrics.go
- CRITICAL: webviewInstance data race — added webviewMu mutex
- CRITICAL: swallowed Glob error in agentic/ingest.go
- HIGH: 9 nil-pointer dereferences on resp.StatusCode across agentic/
- HIGH: swallowed os.Open/os.Create errors in dispatch, queue, resume
- HIGH: hardcoded ~/Code/host-uk/core paths replaced with s.workspaceRoot()
- HIGH: wsServer/wsAddr data race — added wsMu to Service struct
- MEDIUM: ChannelSend stdout guard for non-stdio transports
- MEDIUM: readPlan discarded underlying error
- MEDIUM: TCP session IDs now unique per connection (RemoteAddr)
- LOW: SPDX typo in brain/provider.go

PHP (route('login') fix):
- Replace route('login') with url('/login') in 4 MCP files
- route('login') fails on mcp.* subdomains where no login route exists
- url('/login') resolves correctly on any domain

Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-21 23:13:03 +00:00
Snider
8e84a06b82 fix(mcp): send channel events via notifications/claude/channel
Some checks failed
CI / test (push) Failing after 3s
ChannelSend now writes raw JSON-RPC notifications with method
notifications/claude/channel directly to stdout, bypassing the
SDK's Log() method which uses notifications/message/log.

The official Go SDK doesn't expose a way to send custom
notification methods, so we write the JSON-RPC notification
directly to the stdio transport. This is the format Claude Code
channels expect for --channels to surface events in session.

Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-21 18:57:36 +00:00
Snider
c815b9f1b1 fix(test): use port 0 instead of hardcoded 9101 in TCP warning test
Some checks failed
CI / test (push) Failing after 3s
Port 9101 conflicts with running core-agent serve. OS-assigned
port avoids the conflict and still tests the 0.0.0.0 warning.

Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-21 17:48:48 +00:00
Snider
1d44728dcd fix(brain): default list limit to 50 instead of 0
Some checks failed
CI / test (push) Failing after 2s
Backend clamps 0 to 1, returning only one memory. Default to 50
for a sensible batch when callers omit the limit field.

Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-21 17:45:36 +00:00
Snider
1ac4ff731d feat(mcp): emit channel events for brain recall/remember
Some checks failed
CI / test (push) Failing after 3s
DirectSubsystem pushes brain.recall.complete and brain.remember.complete
events via OnChannel callback. Avoids circular import by using func-based
wiring instead of interface-based SubsystemWithNotifier.

New() auto-detects subsystems with OnChannel() and wires them to
ChannelSend via closure.

Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-21 15:16:34 +00:00
Snider
bc3c7184e9 feat(mcp): emit channel events for process start/stop/kill
Some checks failed
CI / test (push) Failing after 3s
process.start on successful spawn, process.exit on stop/kill.
Events include process ID, PID, command, and signal type.

Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-21 15:10:01 +00:00
Snider
4775f2c2d3 refactor(mcp): TCP/Unix transports use shared server sessions
Some checks failed
CI / test (push) Failing after 3s
Connections now register on the shared server via Server.Connect()
instead of creating per-connection servers. All sessions (stdio,
HTTP, TCP, Unix) are now visible to Sessions() and notification
broadcasting.

Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-21 15:08:34 +00:00
Snider
7e24efaa85 docs: update CLAUDE.md for Options{} API + add CI workflow
Some checks failed
CI / test (push) Failing after 3s
CLAUDE.md reflects new Options{} constructor, notification
broadcasting, and channel events. CI runs tests with Codecov.

Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-21 13:53:49 +00:00
Snider
3c0cd0c238 docs(mcp): add usage-example comments to all public types
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-21 13:51:14 +00:00
Snider
8021475bf5 refactor(mcp): Options{} struct + notification broadcasting + claude/channel
Phase 1: Replace functional options (WithWorkspaceRoot, WithSubsystem,
WithProcessService, WithWSHub) with Options{} struct. Breaking change
for consumers (agent, ide).

Phase 2: Add notification broadcasting and claude/channel capability.
- SendNotificationToAllClients: broadcasts to all MCP sessions
- ChannelSend: push named events (agent.complete, build.failed, etc.)
- ChannelSendToSession: push to a specific session
- Notifier interface for sub-packages to avoid circular imports
- claude/channel registered as experimental MCP capability

Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-21 13:51:14 +00:00
Snider
04ef80cd06 refactor: migrate core import to dappco.re/go/core
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-21 13:51:14 +00:00
Snider
40e43773a7 chore: sync dependencies for v0.3.4
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-21 13:51:14 +00:00
Snider
6a6dfe5217 chore: sync dependencies for v0.3.3
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-21 13:51:14 +00:00
Snider
ea81084058 docs(mcp): add SDK migration plan for AX conventions + notifications
5-phase plan covering:
- Options{} struct replacing functional options (breaking)
- SendNotificationToAllClients + claude/channel capability
- Usage-example comments on all public types
- Notifier interface for subsystem event broadcasting
- Consumer migration guide for agent/ide modules

Evaluated mark3labs/mcp-go vs official SDK; recommends staying on
official SDK with Server.Sessions() wrapper for notifications.

Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-21 12:34:14 +00:00
Snider
4c6c9d7709 refactor: migrate core import to dappco.re/go/core
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-21 12:13:52 +00:00
Snider
6fa6c79b86 docs(mcp): add migration plan for official SDK to mcp-go
Maps all 27 source files and 55 tool registrations from
github.com/modelcontextprotocol/go-sdk to github.com/mark3labs/mcp-go.
Covers handler signature adapter, transport strategy, subsystem interface
changes, and consumer impact. Key motivation: unlock SendNotificationToClient
for claude/channel event push.

Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-21 11:59:04 +00:00