// approved_seeded_copy_test.go package main import ( "os" "path/filepath" "regexp" "strconv" "strings" "testing" ) // The copy gate of the seeded-instances series (#260, #261). The deck is // reviewed BEFORE any code speaks a sentence (the reverse of the moves // record, where code came first), so the gate has two lists: // // - seededCopyIDs: every row the deck holds, pinned both ways; // - seededWiredIDs: the rows code already speaks. Each plan's wiring task // appends the ids it wired, and the gate checks each one's text is in // the file its row names. const seededCopyRecordPath = "docs/superpowers/plans/2026-10-08-seeded-instances-copy.md" var seededCopyIDPattern = regexp.MustCompile(`^SD-N[0-9]+$`) var seededCopyIDs = func() []string { ids := make([]string, 0, 140) for n := 1; n <= 140; n++ { ids = append(ids, "SD-N"+strconv.Itoa(n)) } return ids }() // seededWiredIDs grows as the plans wire rows. Plan 1 wires none; Plan 3 // Task 3 wires SD-N1, Task 5 SD-N2 to SD-N8 and SD-N113, Task 6 SD-N9 to SD-N13, // SD-N111 and SD-N112; Plan 4 Task 3 SD-N14 to SD-N19; Plan 5 Task 3 SD-N27 to SD-N29, // Task 5 SD-N20 to SD-N26, SD-N30 to SD-N39 and SD-N41; Plan 5 Task 6 SD-N40, SD-N42 to SD-N47, SD-N83 to SD-N88 and SD-N114; // Plan 6 Task 1 SD-N48 to SD-N50, SD-N62 and SD-N67; Plan 6 Task 2 SD-N51 to SD-N53, SD-N59, SD-N61 and SD-N63; // Plan 6 Task 3 SD-N54, SD-N55, SD-N60, SD-N64, SD-N65 and SD-N115; Plan 6 Task 5 SD-N56 to SD-N58 and SD-N66; // Plan 6 Task 6 SD-N68 to SD-N82, SD-N89 and SD-N90; Plan 7 Task 3 SD-N91 to SD-N98; Plan 7 Task 6 SD-N99; // Plan 8 Task 3 SD-N100 and SD-N101; Plan 8 Task 5 SD-N102 to SD-N110 and SD-N116; // the 2026-10-10 copy review (round 2) SD-N117 to SD-N136, with SD-N110's last sentence replaced. var seededWiredIDs = []string{"SD-N1", "SD-N2", "SD-N3", "SD-N4", "SD-N5", "SD-N6", "SD-N7", "SD-N8", "SD-N113", "SD-N9", "SD-N10", "SD-N11", "SD-N12", "SD-N13", "SD-N111", "SD-N112", "SD-N14", "SD-N15", "SD-N16", "SD-N17", "SD-N18", "SD-N19", "SD-N27", "SD-N28", "SD-N29", "SD-N20", "SD-N21", "SD-N22", "SD-N23", "SD-N24", "SD-N25", "SD-N26", "SD-N30", "SD-N31", "SD-N32", "SD-N33", "SD-N34", "SD-N35", "SD-N36", "SD-N37", "SD-N38", "SD-N39", "SD-N41", "SD-N40", "SD-N42", "SD-N43", "SD-N44", "SD-N45", "SD-N46", "SD-N47", "SD-N114", "SD-N83", "SD-N84", "SD-N85", "SD-N86", "SD-N87", "SD-N88", "SD-N48", "SD-N49", "SD-N50", "SD-N62", "SD-N67", "SD-N51", "SD-N52", "SD-N53", "SD-N59", "SD-N61", "SD-N63", "SD-N54", "SD-N55", "SD-N60", "SD-N64", "SD-N65", "SD-N115", "SD-N56", "SD-N57", "SD-N58", "SD-N66", "SD-N68", "SD-N69", "SD-N70", "SD-N71", "SD-N72", "SD-N73", "SD-N74", "SD-N75", "SD-N76", "SD-N77", "SD-N78", "SD-N79", "SD-N80", "SD-N81", "SD-N82", "SD-N89", "SD-N90", "SD-N91", "SD-N92", "SD-N93", "SD-N94", "SD-N95", "SD-N96", "SD-N97", "SD-N98", "SD-N99", "SD-N100", "SD-N101", "SD-N102", "SD-N103", "SD-N104", "SD-N105", "SD-N106", "SD-N107", "SD-N108", "SD-N109", "SD-N110", "SD-N116", "SD-N117", "SD-N118", "SD-N119", "SD-N120", "SD-N121", "SD-N122", "SD-N123", "SD-N124", "SD-N125", "SD-N126", "SD-N127", "SD-N128", "SD-N129", "SD-N130", "SD-N131", "SD-N132", "SD-N133", "SD-N134", "SD-N135", "SD-N136", // the claim-activation refusals over seed state, approved 2026-10-13. "SD-N137", "SD-N138", "SD-N139", "SD-N140"} func mustParseSeededRecord(t *testing.T) []copyRow { t.Helper() rows, err := parseSeededCopyRecord(seededCopyRecordPath) if err != nil { t.Fatal(err) } if len(rows) == 0 { t.Fatalf("%s has no rows", seededCopyRecordPath) } return rows } func TestSeededCopyRecordIsComplete(t *testing.T) { reportAll(t, checkMovesInventory(mustParseSeededRecord(t), seededCopyIDs)) } func TestSeededCopyHasNoEmDash(t *testing.T) { reportAll(t, checkMovesNoEmDash(mustParseSeededRecord(t))) } func TestSeededWiredCopyIsApplied(t *testing.T) { reportAll(t, checkSeededWired(mustParseSeededRecord(t), seededWiredIDs, ".")) } func TestParseSeededCopyTableKeepsPipes(t *testing.T) { src := "| id | file | text | status |\n|---|---|---|---|\n" + "| SD-N1 | a.go | one | two | pending |\n" rows, err := parseCopyTable(src, "x.md", seededCopyIDPattern, "an SD-N") if err != nil { t.Fatal(err) } if len(rows) != 1 || rows[0].Text != "one | two" { t.Fatalf("rows = %+v", rows) } if _, err := parseCopyTable(strings.Replace(src, "SD-N1", "MV-N1", 1), "x.md", seededCopyIDPattern, "an SD-N"); err == nil || !strings.Contains(err.Error(), "is not an SD-N id") { t.Fatalf("a moves id in the seeded deck: err = %v", err) } } func TestSeededCopyInventoryBitesBothWays(t *testing.T) { rows := []copyRow{{"SD-N1", "a.go", "x", "pending"}, {"SD-N3", "a.go", "y", "pending"}} got := checkMovesInventory(rows, []string{"SD-N1", "SD-N2"}) if len(got) != 2 { t.Fatalf("problems = %q, want a missing SD-N2 and an extra SD-N3", got) } } func TestSeededWiredCheckBites(t *testing.T) { dir := t.TempDir() writeFile(t, dir, "a.go", "package a\n\nvar s = \"hello there\"\n") rows := []copyRow{ {"SD-N1", "a.go", "hello there", "approved"}, {"SD-N2", "a.go", "goodbye", "approved"}, {"SD-N3", "a.go", "hello there", "pending"}, } if got := checkSeededWired(rows, []string{"SD-N1"}, dir); len(got) != 0 { t.Errorf("a wired, applied row: problems = %q", got) } if got := checkSeededWired(rows, []string{"SD-N2"}, dir); len(got) != 1 || !strings.Contains(got[0], "SD-N2") { t.Errorf("a wired row whose text is missing: problems = %q", got) } if got := checkSeededWired(rows, []string{"SD-N3"}, dir); len(got) != 1 || !strings.Contains(got[0], "pending") { t.Errorf("a wired pending row: problems = %q", got) } if got := checkSeededWired(rows, []string{"SD-N9"}, dir); len(got) != 1 || !strings.Contains(got[0], "no row") { t.Errorf("a wired id with no row: problems = %q", got) } } func parseSeededCopyRecord(path string) ([]copyRow, error) { raw, err := os.ReadFile(path) if err != nil { return nil, err } return parseCopyTable(string(raw), path, seededCopyIDPattern, "an SD-N") } // checkSeededWired checks every wired id: it has a row, the row is // approved, and its text is in the file the row names (the moves gate's own // matcher, so a Go file must carry it as one literal, concatenation or // format, and any other file raw). func checkSeededWired(rows []copyRow, wired []string, root string) []string { byID := map[string]copyRow{} for _, r := range rows { byID[r.ID] = r } var out []string var applyRows []copyRow for _, id := range wired { r, ok := byID[id] switch { case !ok: out = append(out, id+": wired, but the deck has no row for it") case r.Status != "approved": out = append(out, id+": wired, but its row is "+r.Status+": only approved text may reach code") default: applyRows = append(applyRows, r) } } return append(out, checkMovesApplied(applyRows, root)...) } // checkSeededApproved fails on any row that is not approved. Plan 1 Task 2 // adds the test that calls it, once Paul's review has landed. func checkSeededApproved(rows []copyRow) []string { var out []string for _, r := range rows { if r.Status != "approved" { out = append(out, r.ID+" is "+r.Status+": the deck is reviewed before any plan wires a string") } } return out } func writeFile(t *testing.T, dir, name, body string) { t.Helper() if err := os.WriteFile(filepath.Join(dir, name), []byte(body), 0o644); err != nil { t.Fatal(err) } } // Every row is reviewed before any plan of the series wires one (Plan 1 // Task 2). A row added later is reviewed before the plan that adds it // merges, and this test holds that line. func TestSeededCopyIsApproved(t *testing.T) { reportAll(t, checkSeededApproved(mustParseSeededRecord(t))) } // TestEverySeededRowIsWired holds the series' end state: every approved // deck row is spoken by the code that owns it (Plan 8 Task 6). func TestEverySeededRowIsWired(t *testing.T) { wired := map[string]bool{} for _, id := range seededWiredIDs { wired[id] = true } for _, id := range seededCopyIDs { if !wired[id] { t.Errorf("%s is approved and never wired", id) } } }