Pulse/cmd/agent-probe/main_test.go
rcourtman 956646a5c1 Add cmd/agent-probe — worked example consuming the agent substrate
The substrate's read and write surfaces are end-to-end-tested
internally; this slice answers the harder question — "is the
substrate actually usable from the outside?" — by writing the
smallest standalone program that consumes it. agent-probe walks
the discovery → triage → depth → push flow against a running
Pulse instance using only the Go standard library, so it doubles
as a reference implementation for anyone building MCP servers,
Claude Code integrations, or custom agents on top of Pulse.

It resolves every path from the manifest rather than hardcoding
them — if discovery moves a path, the probe follows
automatically — and branches on the stable error envelope's
"error" code field, never on human-readable messages. The focus
rule (severity-lex-ordered) is intentionally simple so a reader
can predict what the probe will pick; real agents will have
richer policies.

This is documentation as code: the program is short enough to
read top-to-bottom and reads like the agent's own narration of
what it's doing. The unit test pins the focus rule's lex
ordering so a refactor that swaps it for a weighted score (which
allowed many warnings to outrank one critical) cannot regress
silently.
2026-05-09 22:28:00 +01:00

83 lines
2 KiB
Go

package main
import (
"testing"
)
// TestPickFocus_PrefersCriticalThenWarningThenInfo pins the focus
// rule the probe uses for "where do I look first?". The unit test
// is here rather than against the substrate because the rule is a
// probe-side triage convention, not a contract Pulse owns; agents
// building on the substrate can implement their own ordering.
func TestPickFocus_PrefersCriticalThenWarningThenInfo(t *testing.T) {
mk := func(id string, c, w, i, p int) fleetResource {
r := fleetResource{CanonicalID: id, PendingApprovalCount: p}
r.Findings.Critical = c
r.Findings.Warning = w
r.Findings.Info = i
r.Findings.Total = c + w + i
return r
}
cases := []struct {
name string
resources []fleetResource
want string
}{
{
name: "single critical beats many warnings",
resources: []fleetResource{
mk("vm:noisy", 0, 50, 0, 0),
mk("vm:critical", 1, 0, 0, 0),
mk("vm:quiet", 0, 0, 0, 0),
},
want: "vm:critical",
},
{
name: "tie on severity broken by count",
resources: []fleetResource{
mk("vm:warm", 0, 1, 0, 0),
mk("vm:warmer", 0, 3, 0, 0),
},
want: "vm:warmer",
},
{
name: "no findings — pending approvals as tiebreaker",
resources: []fleetResource{
mk("vm:idle", 0, 0, 0, 0),
mk("vm:waiting", 0, 0, 0, 2),
},
want: "vm:waiting",
},
{
name: "no findings or approvals — first wins so depth step still runs",
resources: []fleetResource{
mk("vm:first", 0, 0, 0, 0),
mk("vm:second", 0, 0, 0, 0),
},
want: "vm:first",
},
{
name: "empty fleet returns nil",
resources: nil,
want: "",
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
got := pickFocus(tc.resources)
if tc.want == "" {
if got != nil {
t.Fatalf("expected nil for empty fleet; got %+v", got)
}
return
}
if got == nil {
t.Fatalf("expected %q; got nil", tc.want)
}
if got.CanonicalID != tc.want {
t.Errorf("focus = %q; want %q", got.CanonicalID, tc.want)
}
})
}
}