Go 74 lines
package cockpit
import (
"encoding/json"
"os"
"path/filepath"
"testing"
)
// loadAllSources reads every shipped playbook JSON source directly (no
// internal/playbooks import → no cycle), so the cockpit package can assert the
// safety invariant against the real library.
func loadAllSources(t *testing.T) []Playbook {
t.Helper()
dir := filepath.Join("..", "playbooks", "data")
entries, err := os.ReadDir(dir)
if err != nil {
t.Fatalf("read playbook data dir: %v", err)
}
var out []Playbook
for _, e := range entries {
if e.IsDir() || filepath.Ext(e.Name()) != ".json" {
continue
}
b, err := os.ReadFile(filepath.Join(dir, e.Name()))
if err != nil {
t.Fatalf("read %s: %v", e.Name(), err)
}
var pb Playbook
if err := json.Unmarshal(b, &pb); err != nil {
t.Fatalf("parse %s: %v", e.Name(), err)
}
out = append(out, pb)
}
if len(out) == 0 {
t.Fatal("no playbook sources found")
}
return out
}
// TestAllSources_NoWriteGitVerb is the S1 trap-door test: every shipped
// playbook's composed allowlist must hold the safety invariant (zero
// write-git verbs), so a `git tag` slipping into a capability fails at test
// time, not at emit time.
func TestAllSources_NoWriteGitVerb(t *testing.T) {
for _, pb := range loadAllSources(t) {
if hits := ScanAllowlistForWriteGitVerbs(composeAllowedTools(pb), pb.Intent.forbiddenVerbs()); len(hits) > 0 {
t.Errorf("playbook %q grants forbidden write-git verb(s): %v", pb.Name, hits)
}
}
}
// TestAllSources_RenderOnEveryTarget: every shipped playbook renders without
// error on the per-playbook targets, and the whole set renders on the
// aggregate targets.
func TestAllSources_RenderOnEveryTarget(t *testing.T) {
set := loadAllSources(t)
for _, target := range []string{"claude", "cursor"} {
r, _ := rendererFor(target)
for _, pb := range set {
if _, err := r.Render(pb); err != nil {
t.Errorf("%s render of %q: %v", target, pb.Name, err)
}
}
}
for _, target := range []string{"agents", "gemini"} {
r, _ := rendererFor(target)
agg, _ := isAggregate(r)
if _, err := agg.RenderAll(set); err != nil {
t.Errorf("%s RenderAll: %v", target, err)
}
}
}