ajhahn.de
← eeco
Go 89 lines
package cockpit

import (
	"strings"
	"testing"
)

// synthPlaybook builds a minimal read-only playbook for aggregate-render
// tests, with a distinct name so set ordering is observable.
func synthPlaybook(name string) Playbook {
	return Playbook{
		Name:        name,
		Description: "synthetic " + name + " playbook for tests",
		Intent: Intent{
			Guarantee: "reads and reports only",
			Forbidden: []string{"git commit", "edit any tracked file"},
		},
		Capabilities: []Capability{
			{Kind: "tool", Name: "Read"},
			{Kind: "bash", Verb: "git status", Scope: "*"},
		},
		Steps: []Step{
			{Index: 0, Title: "look", Body: "inspect the tree"},
			{Index: 1, Title: "report", Body: "print findings"},
		},
		OutputFormat: "a short report",
	}
}

func twoPlaybooks(t *testing.T) []Playbook {
	t.Helper()
	return []Playbook{loadHandover(t), synthPlaybook("zeta")}
}

func TestAgentsRender_Structure(t *testing.T) {
	out, err := agentsRenderer{}.RenderAll(twoPlaybooks(t))
	if err != nil {
		t.Fatalf("RenderAll: %v", err)
	}
	got := string(out)

	if strings.HasPrefix(got, "---") {
		t.Error("AGENTS.md must not carry YAML frontmatter")
	}
	for _, want := range []string{"# AGENTS.md", advisoryBanner, "## Fidelity report", "### " + headingForbidden, "### " + headingAllowed} {
		if !strings.Contains(got, want) {
			t.Errorf("AGENTS.md missing %q", want)
		}
	}
	// Both playbooks' sections present (sorted by Name → handover before zeta).
	hIdx := strings.Index(got, "## Handover")
	zIdx := strings.Index(got, "## Zeta")
	if hIdx < 0 || zIdx < 0 {
		t.Fatalf("missing a playbook section: handover@%d zeta@%d", hIdx, zIdx)
	}
	if hIdx > zIdx {
		t.Error("sections not sorted by Name (handover should precede zeta)")
	}
}

func TestAgentsRender_SetOrderStable(t *testing.T) {
	a, err := agentsRenderer{}.RenderAll([]Playbook{loadHandover(t), synthPlaybook("zeta")})
	if err != nil {
		t.Fatal(err)
	}
	b, err := agentsRenderer{}.RenderAll([]Playbook{synthPlaybook("zeta"), loadHandover(t)})
	if err != nil {
		t.Fatal(err)
	}
	if string(a) != string(b) {
		t.Error("aggregate render not stable under input reordering")
	}
}

func TestAgentsAggRelPath(t *testing.T) {
	if got := (agentsRenderer{}).AggRelPath(); got != "AGENTS.md" {
		t.Errorf("AggRelPath = %q, want AGENTS.md", got)
	}
	if !IsAggregateTarget("agents") {
		t.Error("agents should be an aggregate target")
	}
}

func TestAgentsEnforcement(t *testing.T) {
	if got := (agentsRenderer{}).Enforcement(); got != EnforcementAdvisory {
		t.Errorf("agents enforcement = %v, want advisory", got)
	}
}