fix: resolve final AX audit findings
- cmd/main.go: keyed core.Result literals (go vet clean) - pkg/brain/direct.go: compile-time mcp.Subsystem assertion - pkg/monitor/monitor.go: compile-time Subsystem + CompletionNotifier assertions - pkg/agentic/prep.go: alias stdlib io as goio - pkg/agentic/remote_client.go: UK English (initialise/initialised) - pkg/monitor/monitor_test.go: updated inbox tests for current contract AX audit now returns 0 convention findings. Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
parent
7873e0ebf7
commit
4f66eb4cca
6 changed files with 42 additions and 32 deletions
10
cmd/main.go
10
cmd/main.go
|
|
@ -57,11 +57,11 @@ func main() {
|
|||
Action: func(opts core.Options) core.Result {
|
||||
mcpSvc, mon, err := initServices()
|
||||
if err != nil {
|
||||
return core.Result{err, false}
|
||||
return core.Result{Value: err, OK: false}
|
||||
}
|
||||
mon.Start(ctx)
|
||||
if err := mcpSvc.Run(ctx); err != nil {
|
||||
return core.Result{err, false}
|
||||
return core.Result{Value: err, OK: false}
|
||||
}
|
||||
return core.Result{OK: true}
|
||||
},
|
||||
|
|
@ -73,7 +73,7 @@ func main() {
|
|||
Action: func(opts core.Options) core.Result {
|
||||
mcpSvc, mon, err := initServices()
|
||||
if err != nil {
|
||||
return core.Result{err, false}
|
||||
return core.Result{Value: err, OK: false}
|
||||
}
|
||||
|
||||
addr := os.Getenv("MCP_HTTP_ADDR")
|
||||
|
|
@ -102,7 +102,7 @@ func main() {
|
|||
})
|
||||
|
||||
if err := daemon.Start(); err != nil {
|
||||
return core.Result{core.E("main", "daemon start", err), false}
|
||||
return core.Result{Value: core.E("main", "daemon start", err), OK: false}
|
||||
}
|
||||
|
||||
mon.Start(ctx)
|
||||
|
|
@ -112,7 +112,7 @@ func main() {
|
|||
os.Setenv("MCP_HTTP_ADDR", addr)
|
||||
|
||||
if err := mcpSvc.Run(ctx); err != nil {
|
||||
return core.Result{err, false}
|
||||
return core.Result{Value: err, OK: false}
|
||||
}
|
||||
return core.Result{OK: true}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import (
|
|||
"context"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"io"
|
||||
goio "io"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
|
|
@ -19,6 +19,7 @@ import (
|
|||
|
||||
"dappco.re/go/agent/pkg/lib"
|
||||
core "dappco.re/go/core"
|
||||
coremcp "forge.lthn.ai/core/mcp/pkg/mcp"
|
||||
"github.com/modelcontextprotocol/go-sdk/mcp"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
|
@ -47,6 +48,8 @@ type PrepSubsystem struct {
|
|||
drainMu sync.Mutex // protects drainQueue from concurrent execution
|
||||
}
|
||||
|
||||
var _ coremcp.Subsystem = (*PrepSubsystem)(nil)
|
||||
|
||||
// NewPrep creates an agentic subsystem.
|
||||
//
|
||||
// sub := agentic.NewPrep()
|
||||
|
|
@ -516,7 +519,7 @@ func (s *PrepSubsystem) generateContext(ctx context.Context, repo, wsDir string)
|
|||
return 0
|
||||
}
|
||||
|
||||
respData, _ := io.ReadAll(resp.Body)
|
||||
respData, _ := goio.ReadAll(resp.Body)
|
||||
var result struct {
|
||||
Memories []map[string]any `json:"memories"`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import (
|
|||
core "dappco.re/go/core"
|
||||
)
|
||||
|
||||
// mcpInitialize performs the MCP initialize handshake over Streamable HTTP.
|
||||
// mcpInitialize performs the MCP initialise handshake over Streamable HTTP.
|
||||
// Returns the session ID from the Mcp-Session-Id header.
|
||||
func mcpInitialize(ctx context.Context, client *http.Client, url, token string) (string, error) {
|
||||
initReq := map[string]any{
|
||||
|
|
@ -49,10 +49,10 @@ func mcpInitialize(ctx context.Context, client *http.Client, url, token string)
|
|||
|
||||
sessionID := resp.Header.Get("Mcp-Session-Id")
|
||||
|
||||
// Drain the SSE response (we don't need the initialize result)
|
||||
// Drain the SSE response (we don't need the initialise result)
|
||||
drainSSE(resp)
|
||||
|
||||
// Send initialized notification
|
||||
// Send initialised notification
|
||||
notif := map[string]any{
|
||||
"jsonrpc": "2.0",
|
||||
"method": "notifications/initialized",
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import (
|
|||
|
||||
"dappco.re/go/agent/pkg/agentic"
|
||||
core "dappco.re/go/core"
|
||||
coremcp "forge.lthn.ai/core/mcp/pkg/mcp"
|
||||
"github.com/modelcontextprotocol/go-sdk/mcp"
|
||||
)
|
||||
|
||||
|
|
@ -25,6 +26,8 @@ type DirectSubsystem struct {
|
|||
client *http.Client
|
||||
}
|
||||
|
||||
var _ coremcp.Subsystem = (*DirectSubsystem)(nil)
|
||||
|
||||
// NewDirect creates a direct HTTP brain subsystem.
|
||||
//
|
||||
// sub := brain.NewDirect()
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import (
|
|||
|
||||
"dappco.re/go/agent/pkg/agentic"
|
||||
core "dappco.re/go/core"
|
||||
coremcp "forge.lthn.ai/core/mcp/pkg/mcp"
|
||||
"github.com/modelcontextprotocol/go-sdk/mcp"
|
||||
)
|
||||
|
||||
|
|
@ -82,6 +83,9 @@ type Subsystem struct {
|
|||
poke chan struct{}
|
||||
}
|
||||
|
||||
var _ coremcp.Subsystem = (*Subsystem)(nil)
|
||||
var _ agentic.CompletionNotifier = (*Subsystem)(nil)
|
||||
|
||||
// SetNotifier wires up channel event broadcasting.
|
||||
//
|
||||
// mon.SetNotifier(notifier)
|
||||
|
|
@ -393,7 +397,6 @@ func (m *Subsystem) checkInbox() string {
|
|||
// Find max ID, count unread, collect new messages
|
||||
maxID := 0
|
||||
unread := 0
|
||||
senders := make(map[string]int)
|
||||
|
||||
m.mu.Lock()
|
||||
prevMaxID := m.lastInboxMaxID
|
||||
|
|
@ -414,9 +417,6 @@ func (m *Subsystem) checkInbox() string {
|
|||
}
|
||||
if !msg.Read {
|
||||
unread++
|
||||
if msg.From != "" {
|
||||
senders[msg.From]++
|
||||
}
|
||||
}
|
||||
// Collect messages newer than what we've seen
|
||||
if msg.ID > prevMaxID {
|
||||
|
|
|
|||
|
|
@ -241,9 +241,9 @@ func TestCheckInbox_Good_UnreadMessages(t *testing.T) {
|
|||
|
||||
resp := map[string]any{
|
||||
"data": []map[string]any{
|
||||
{"read": false, "from_agent": "clotho", "subject": "task done"},
|
||||
{"read": false, "from_agent": "gemini", "subject": "review ready"},
|
||||
{"read": true, "from_agent": "clotho", "subject": "old msg"},
|
||||
{"id": 3, "read": false, "from": "clotho", "subject": "task done"},
|
||||
{"id": 2, "read": false, "from": "gemini", "subject": "review ready"},
|
||||
{"id": 1, "read": true, "from": "clotho", "subject": "old msg"},
|
||||
},
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
|
@ -256,6 +256,7 @@ func TestCheckInbox_Good_UnreadMessages(t *testing.T) {
|
|||
t.Setenv("AGENT_NAME", "test-agent")
|
||||
|
||||
mon := New()
|
||||
mon.inboxSeeded = true
|
||||
notifier := &mockNotifier{}
|
||||
mon.SetNotifier(notifier)
|
||||
|
||||
|
|
@ -266,16 +267,19 @@ func TestCheckInbox_Good_UnreadMessages(t *testing.T) {
|
|||
require.Len(t, events, 1)
|
||||
assert.Equal(t, "inbox.message", events[0].channel)
|
||||
eventData := events[0].data.(map[string]any)
|
||||
assert.Equal(t, 2, eventData["new"])
|
||||
assert.Equal(t, 3, eventData["new"])
|
||||
assert.Equal(t, 2, eventData["total"])
|
||||
assert.Equal(t, "task done", eventData["subject"])
|
||||
payload, err := json.Marshal(eventData["messages"])
|
||||
require.NoError(t, err)
|
||||
assert.Contains(t, string(payload), "\"subject\":\"task done\"")
|
||||
assert.Contains(t, string(payload), "\"subject\":\"review ready\"")
|
||||
}
|
||||
|
||||
func TestCheckInbox_Good_NoUnread(t *testing.T) {
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
resp := map[string]any{
|
||||
"data": []map[string]any{
|
||||
{"read": true, "from_agent": "clotho", "subject": "old"},
|
||||
{"id": 1, "read": true, "from": "clotho", "subject": "old"},
|
||||
},
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
|
@ -294,7 +298,7 @@ func TestCheckInbox_Good_SameCountNoRepeat(t *testing.T) {
|
|||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
resp := map[string]any{
|
||||
"data": []map[string]any{
|
||||
{"read": false, "from_agent": "clotho", "subject": "msg"},
|
||||
{"id": 1, "read": false, "from": "clotho", "subject": "msg"},
|
||||
},
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
|
@ -351,9 +355,9 @@ func TestCheckInbox_Good_MultipleSameSender(t *testing.T) {
|
|||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
resp := map[string]any{
|
||||
"data": []map[string]any{
|
||||
{"read": false, "from_agent": "clotho", "subject": "msg1"},
|
||||
{"read": false, "from_agent": "clotho", "subject": "msg2"},
|
||||
{"read": false, "from_agent": "gemini", "subject": "msg3"},
|
||||
{"id": 3, "read": false, "from": "clotho", "subject": "msg1"},
|
||||
{"id": 2, "read": false, "from": "clotho", "subject": "msg2"},
|
||||
{"id": 1, "read": false, "from": "gemini", "subject": "msg3"},
|
||||
},
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
|
@ -364,6 +368,7 @@ func TestCheckInbox_Good_MultipleSameSender(t *testing.T) {
|
|||
setupAPIEnv(t, srv.URL)
|
||||
|
||||
mon := New()
|
||||
mon.inboxSeeded = true
|
||||
notifier := &mockNotifier{}
|
||||
mon.SetNotifier(notifier)
|
||||
|
||||
|
|
@ -373,14 +378,13 @@ func TestCheckInbox_Good_MultipleSameSender(t *testing.T) {
|
|||
events := notifier.Events()
|
||||
require.Len(t, events, 1)
|
||||
eventData := events[0].data.(map[string]any)
|
||||
senders := eventData["senders"].([]string)
|
||||
found := false
|
||||
for _, s := range senders {
|
||||
if s == "clotho (2)" {
|
||||
found = true
|
||||
}
|
||||
}
|
||||
assert.True(t, found, "expected clotho (2) in senders, got %v", senders)
|
||||
assert.Equal(t, 3, eventData["new"])
|
||||
assert.Equal(t, 3, eventData["total"])
|
||||
payload, err := json.Marshal(eventData["messages"])
|
||||
require.NoError(t, err)
|
||||
assert.Contains(t, string(payload), "\"from\":\"clotho\"")
|
||||
assert.Contains(t, string(payload), "\"subject\":\"msg1\"")
|
||||
assert.Contains(t, string(payload), "\"subject\":\"msg2\"")
|
||||
}
|
||||
|
||||
// --- check (integration of sub-checks) ---
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue