carlos / platform Public

Clone
git clone https://amadan.net/carlos/platform

Plain git — no account needed to clone.

Download

Download this file

1// approved_run_copy_test.go
2package main
3
4import (
5 "fmt"
6 "os"
7 "path/filepath"
8 "strconv"
9 "strings"
10 "testing"
11)
12
13// The copy gate of the carlos run series (run Plan 1 Task 1). The deck is a
14// markdown table in the moves record's format, read with the moves gate's
15// parser and checked with its helpers, so "applied" means the same thing in
16// both gates:
17//
18// - TestRunCopyRecordIsComplete: the deck names exactly RUN-C1 to RUN-C87;
19// - TestRunBuiltCopyIsApproved: an id in runCopyBuilt is an approved row
20// (a string reaches code only after Paul has approved it);
21// - TestRunBuiltCopyIsApplied: a built row's text is in the file it names;
22// - TestRunCopyHasNoEmDash.
23const runCopyRecordPath = "docs/superpowers/plans/2026-10-08-carlos-run-copy.md"
24
25// runCopyIDs is the deck's inventory: RUN-C1 to RUN-C87, pinned.
26var runCopyIDs = func() []string {
27 ids := make([]string, 0, 87)
28 for i := 1; i <= 87; i++ {
29 ids = append(ids, "RUN-C"+strconv.Itoa(i))
30 }
31 return ids
32}()
33
34// runCopyBuilt is every deck id whose text the code or docs now carry. The
35// task that writes a row's text adds its id here in the same commit.
36var runCopyBuilt = []string{"RUN-C1", "RUN-C2", "RUN-C3", "RUN-C4", "RUN-C5", "RUN-C6", "RUN-C7", "RUN-C8", "RUN-C9", "RUN-C10", "RUN-C11", "RUN-C12", "RUN-C13", "RUN-C14", "RUN-C15", "RUN-C16", "RUN-C17", "RUN-C18", "RUN-C19", "RUN-C20", "RUN-C21", "RUN-C22", "RUN-C23", "RUN-C24", "RUN-C25", "RUN-C26", "RUN-C27", "RUN-C28", "RUN-C29", "RUN-C30", "RUN-C31", "RUN-C32", "RUN-C33", "RUN-C34", "RUN-C35", "RUN-C36", "RUN-C37", "RUN-C38", "RUN-C39", "RUN-C40", "RUN-C41", "RUN-C42", "RUN-C43", "RUN-C44", "RUN-C45", "RUN-C46", "RUN-C47", "RUN-C48", "RUN-C49", "RUN-C50", "RUN-C51", "RUN-C52", "RUN-C53", "RUN-C54", "RUN-C55", "RUN-C56", "RUN-C57", "RUN-C58", "RUN-C59", "RUN-C60", "RUN-C61", "RUN-C62", "RUN-C63", "RUN-C64", "RUN-C65", "RUN-C66", "RUN-C67", "RUN-C68", "RUN-C69", "RUN-C70", "RUN-C71", "RUN-C72", "RUN-C73", "RUN-C74", "RUN-C75", "RUN-C76", "RUN-C77", "RUN-C78", "RUN-C79", "RUN-C80", "RUN-C81", "RUN-C82", "RUN-C83", "RUN-C84", "RUN-C85", "RUN-C86", "RUN-C87"}
37
38func mustParseRunRecord(t *testing.T) []copyRow {
39 t.Helper()
40 rows, err := parseMovesCopyRecord(runCopyRecordPath)
41 if err != nil {
42 t.Fatal(err)
43 }
44 if len(rows) == 0 {
45 t.Fatalf("%s has no rows", runCopyRecordPath)
46 }
47 for _, r := range rows {
48 if !strings.HasPrefix(r.ID, "RUN-C") {
49 t.Fatalf("%s: %s is not a RUN-C id", runCopyRecordPath, r.ID)
50 }
51 }
52 return rows
53}
54
55// checkRunBuilt: every built id is named once, names a row, and that row is
56// approved.
57func checkRunBuilt(rows []copyRow, built []string) []string {
58 byID := map[string]copyRow{}
59 for _, r := range rows {
60 byID[r.ID] = r
61 }
62 var out []string
63 seen := map[string]bool{}
64 for _, id := range built {
65 if seen[id] {
66 out = append(out, fmt.Sprintf("runCopyBuilt names %s twice", id))
67 }
68 seen[id] = true
69 r, ok := byID[id]
70 switch {
71 case !ok:
72 out = append(out, fmt.Sprintf("runCopyBuilt names %s, which the deck has no row for", id))
73 case r.Status != "approved":
74 out = append(out, fmt.Sprintf("%s is built but %s: a string reaches code only after Paul approves it", id, r.Status))
75 }
76 }
77 return out
78}
79
80// builtRows is the rows runCopyBuilt names, in deck order.
81func builtRows(rows []copyRow, built []string) []copyRow {
82 want := map[string]bool{}
83 for _, id := range built {
84 want[id] = true
85 }
86 var out []copyRow
87 for _, r := range rows {
88 if want[r.ID] {
89 out = append(out, r)
90 }
91 }
92 return out
93}
94
95func TestRunCopyRecordIsComplete(t *testing.T) {
96 reportAll(t, checkMovesInventory(mustParseRunRecord(t), runCopyIDs))
97}
98
99func TestRunCopyHasNoEmDash(t *testing.T) {
100 reportAll(t, checkMovesNoEmDash(mustParseRunRecord(t)))
101}
102
103func TestRunBuiltCopyIsApproved(t *testing.T) {
104 reportAll(t, checkRunBuilt(mustParseRunRecord(t), runCopyBuilt))
105}
106
107// runFragment reports whether a row's text is a piece of a larger literal
108// (its file cell says "a fragment"): the top-level usage text, which no
109// whole-expression match can find.
110func runFragment(r copyRow) bool { return strings.Contains(r.File, "(a fragment") }
111
112// checkRunApplied is checkMovesApplied, plus the fragment rows: those must
113// sit inside some string literal of their file (goLiteralMatches,
114// approved_copy_test.go), never only in a comment.
115func checkRunApplied(rows []copyRow, root string) []string {
116 var whole []copyRow
117 var out []string
118 for _, r := range rows {
119 if !runFragment(r) {
120 whole = append(whole, r)
121 continue
122 }
123 if r.Status != "approved" {
124 continue
125 }
126 body, err := os.ReadFile(filepath.Join(root, r.Path()))
127 if err != nil {
128 out = append(out, fmt.Sprintf("%s: %v", r.ID, err))
129 continue
130 }
131 if !goLiteralMatches(body, func(v string) bool { return strings.Contains(v, r.Text) }) {
132 out = append(out, fmt.Sprintf("%s: %s has no string literal holding the approved text %q", r.ID, r.Path(), r.Text))
133 }
134 }
135 return append(checkMovesApplied(whole, root), out...)
136}
137
138func TestRunBuiltCopyIsApplied(t *testing.T) {
139 reportAll(t, checkRunApplied(builtRows(mustParseRunRecord(t), runCopyBuilt), "."))
140}
141
142// Each fixture case is a state the gate must refuse, for the right reason.
143func TestRunCopyGateRefusesTheNegativeFixtures(t *testing.T) {
144 dir := filepath.Join("testdata", "run-copy")
145 rows, err := parseMovesCopyRecord(filepath.Join(dir, "record.md"))
146 if err != nil {
147 t.Fatal(err)
148 }
149 t.Run("a built row still pending", func(t *testing.T) {
150 got := checkRunBuilt(rows, []string{"RUN-C2"})
151 if len(got) != 1 || !strings.Contains(got[0], "RUN-C2 is built but pending") {
152 t.Errorf("problems = %q", got)
153 }
154 })
155 t.Run("a built id with no row", func(t *testing.T) {
156 got := checkRunBuilt(rows, []string{"RUN-C9"})
157 if len(got) != 1 || !strings.Contains(got[0], "no row for") {
158 t.Errorf("problems = %q", got)
159 }
160 })
161 t.Run("a built id named twice", func(t *testing.T) {
162 got := checkRunBuilt(rows, []string{"RUN-C1", "RUN-C1"})
163 if len(got) != 1 || !strings.Contains(got[0], "twice") {
164 t.Errorf("problems = %q", got)
165 }
166 })
167 t.Run("an approved row whose text is only in a comment", func(t *testing.T) {
168 got := checkMovesApplied(builtRows(rows, []string{"RUN-C3"}), dir)
169 if len(got) != 1 || !strings.Contains(got[0], "RUN-C3") {
170 t.Errorf("problems = %q", got)
171 }
172 })
173 t.Run("an approved row that is applied", func(t *testing.T) {
174 if got := checkRunApplied(builtRows(rows, []string{"RUN-C1"}), dir); len(got) != 0 {
175 t.Errorf("problems = %q", got)
176 }
177 })
178 t.Run("a fragment inside a larger literal", func(t *testing.T) {
179 if got := checkRunApplied(builtRows(rows, []string{"RUN-C4"}), dir); len(got) != 0 {
180 t.Errorf("problems = %q", got)
181 }
182 })
183 t.Run("a fragment only in a comment", func(t *testing.T) {
184 got := checkRunApplied(builtRows(rows, []string{"RUN-C5"}), dir)
185 if len(got) != 1 || !strings.Contains(got[0], "RUN-C5") {
186 t.Errorf("problems = %q", got)
187 }
188 })
189}
190
191// The series is done only when every deck row is in the code or the docs.
192func TestRunCopyIsFullyBuilt(t *testing.T) {
193 built := map[string]bool{}
194 for _, id := range runCopyBuilt {
195 built[id] = true
196 }
197 for _, id := range runCopyIDs {
198 if !built[id] {
199 t.Errorf("%s is in the deck but no task built it", id)
200 }
201 }
202}
203