Files
executus/run/progress_test.go
T
steve ca243a2d50
executus CI / test (push) Failing after 24s
P0: stand up executus harness module above majordomo
Batteries-included agent-harness base, extracted from mort's agent layer.
This first cut establishes the module + the zero-coupling core primitives:

- lane, dispatchguard, pendingattach, run/progress.go: moved verbatim from mort
- config: host config Source seam + env-var default (nil-safe helpers)
- deliver: output-egress seam + Discard/Stdout defaults
- identity: AdminPolicy + MemberResolver seams (nil-safe)
- fanout: programmatic N×M swarm (bounded global + per-key concurrency)
- README/CLAUDE.md with the vibe-coded banner; CI with Go gates +
  the "core stays majordomo+stdlib only" invariant

Core builds with stdlib only today; majordomo enters at P1 (model/structured).
go build/vet/test -race all green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-26 19:18:37 -04:00

124 lines
4.1 KiB
Go

package run
import (
"context"
"testing"
)
// ProgressSinkFrom on a bare context returns nil (nothing wired).
func TestProgressSinkFrom_Empty(t *testing.T) {
if got := ProgressSinkFrom(context.Background()); got != nil {
t.Fatalf("expected nil sink on bare context, got non-nil")
}
}
// WithProgressSink round-trips a sink through the context.
func TestWithProgressSink_RoundTrip(t *testing.T) {
var got string
ctx := WithProgressSink(context.Background(), func(n string) { got = n })
sink := ProgressSinkFrom(ctx)
if sink == nil {
t.Fatal("expected non-nil sink")
}
sink("hello")
if got != "hello" {
t.Fatalf("sink did not deliver note; got %q", got)
}
}
// InstallProgressBridge with no parent and a report only feeds the report,
// and notifyAncestors is nil (there are no ancestors to notify).
func TestInstallProgressBridge_NoParent(t *testing.T) {
var reported []string
childCtx, notify := InstallProgressBridge(context.Background(), func(n string) {
reported = append(reported, n)
})
if notify != nil {
t.Fatal("expected nil notifyAncestors when there is no parent")
}
// A child installed under childCtx should reach our report.
child := ProgressSinkFrom(childCtx)
if child == nil {
t.Fatal("expected a child sink installed")
}
child("from-child")
if len(reported) != 1 || reported[0] != "from-child" {
t.Fatalf("report did not receive child note; got %v", reported)
}
}
// InstallProgressBridge with a nil report and an existing parent must pass the
// parent through unchanged (no needless wrapper layer) — this is the skill
// case: a skill run has no recorder of its own but must forward its progress
// to the ancestor agent's critic.
func TestInstallProgressBridge_NilReportPassesParentThrough(t *testing.T) {
var ancestor []string
base := WithProgressSink(context.Background(), func(n string) { ancestor = append(ancestor, n) })
childCtx, notify := InstallProgressBridge(base, nil)
// This run's own steps must notify the ancestor.
if notify == nil {
t.Fatal("expected non-nil notifyAncestors when a parent exists")
}
notify("my-step")
// And a descendant under childCtx must also reach the ancestor.
ProgressSinkFrom(childCtx)("grandchild-step")
if len(ancestor) != 2 || ancestor[0] != "my-step" || ancestor[1] != "grandchild-step" {
t.Fatalf("ancestor did not receive both notes; got %v", ancestor)
}
}
// The full three-level chain: grandchild progress must bump BOTH the child's
// own report and the root ancestor — this is the depth>=2 case (agent ->
// sub-agent -> sub-sub-agent) where every blocked ancestor must stay alive.
func TestInstallProgressBridge_ThreeLevelChain(t *testing.T) {
var root, mid []string
// Level 0 (root agent): has a recorder (report), no parent.
rootCtx, rootNotify := InstallProgressBridge(context.Background(),
func(n string) { root = append(root, n) })
if rootNotify != nil {
t.Fatal("root should have no ancestors")
}
// Level 1 (child agent): has its own recorder, parent = root.
midCtx, midNotify := InstallProgressBridge(rootCtx,
func(n string) { mid = append(mid, n) })
if midNotify == nil {
t.Fatal("mid should notify root")
}
// Level 1's own step notifies root only (its own recorder is fed by its
// own step observer, not via notifyAncestors).
midNotify("mid-step")
if len(root) != 1 || root[0] != "mid-step" {
t.Fatalf("root missed mid-step; root=%v", root)
}
// Level 2 (grandchild): no recorder, parent = mid.
gcCtx, gcNotify := InstallProgressBridge(midCtx, nil)
if gcNotify == nil {
t.Fatal("grandchild should notify its ancestors")
}
// Grandchild's own step must bump BOTH mid (its parent's recorder) and
// root (mid forwards upward).
gcNotify("gc-step")
if len(mid) != 1 || mid[0] != "gc-step" {
t.Fatalf("mid missed gc-step; mid=%v", mid)
}
if len(root) != 2 || root[1] != "gc-step" {
t.Fatalf("root missed forwarded gc-step; root=%v", root)
}
// A descendant installed under gcCtx still reaches mid + root.
ProgressSinkFrom(gcCtx)("ggc-step")
if len(mid) != 2 || mid[1] != "ggc-step" {
t.Fatalf("mid missed ggc-step; mid=%v", mid)
}
if len(root) != 3 || root[2] != "ggc-step" {
t.Fatalf("root missed ggc-step; root=%v", root)
}
}