carlos / platform Public

run: the carlos run copy gate (Plan 1 Task 1)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
claude agent, operated by paul@keymail.dev cd1dc93853d20c5aee06df42b96b07e3945f7c79 parent 4d84f27
4 files changed, +209 −2
  • approved_moves_copy_test.go +2 −2
  • approved_run_copy_test.go +189 −0
  • testdata/run-copy/applied.go +11 −0
  • testdata/run-copy/record.md +7 −0

CI passed — run details

diff --git a/approved_moves_copy_test.go b/approved_moves_copy_test.go
index bb7ec9b31..3374e69d6 100644
--- a/approved_moves_copy_test.go
+++ b/approved_moves_copy_test.go
@@ -88,7 +88,7 @@ func (r copyRow) Path() string {
return r.File
}
-var movesCopyIDPattern = regexp.MustCompile(`^(M-C|MV-N|HC5-N)[0-9]+$`)
+var movesCopyIDPattern = regexp.MustCompile(`^(M-C|MV-N|HC5-N|RUN-C)[0-9]+$`)
// parseMovesCopyRecord reads the record's tables. A data row is a line that
// follows a `| id | file | text | status |` header; the separator line is
@@ -145,7 +145,7 @@ func parseMovesCopyTable(src, name string) ([]copyRow, error) {
Status: cells[last],
}
if !movesCopyIDPattern.MatchString(r.ID) {
- return nil, fmt.Errorf("%s: %q is not an M-C<n>, MV-N<n> or HC5-N<n> id", at, r.ID)
+ return nil, fmt.Errorf("%s: %q is not an M-C<n>, MV-N<n>, HC5-N<n> or RUN-C<n> id", at, r.ID)
}
if r.File == "" || r.Text == "" {
return nil, fmt.Errorf("%s: %s has an empty file or text cell", at, r.ID)
diff --git a/approved_run_copy_test.go b/approved_run_copy_test.go
new file mode 100644
index 000000000..89bc87cd6
--- /dev/null
+++ b/approved_run_copy_test.go
@@ -0,0 +1,189 @@
+// approved_run_copy_test.go
+package main
+
+import (
+ "fmt"
+ "os"
+ "path/filepath"
+ "strconv"
+ "strings"
+ "testing"
+)
+
+// The copy gate of the carlos run series (run Plan 1 Task 1). The deck is a
+// markdown table in the moves record's format, read with the moves gate's
+// parser and checked with its helpers, so "applied" means the same thing in
+// both gates:
+//
+// - TestRunCopyRecordIsComplete: the deck names exactly RUN-C1 to RUN-C83;
+// - TestRunBuiltCopyIsApproved: an id in runCopyBuilt is an approved row
+// (a string reaches code only after Paul has approved it);
+// - TestRunBuiltCopyIsApplied: a built row's text is in the file it names;
+// - TestRunCopyHasNoEmDash.
+const runCopyRecordPath = "docs/superpowers/plans/2026-10-08-carlos-run-copy.md"
+
+// runCopyIDs is the deck's inventory: RUN-C1 to RUN-C83, pinned.
+var runCopyIDs = func() []string {
+ ids := make([]string, 0, 83)
+ for i := 1; i <= 83; i++ {
+ ids = append(ids, "RUN-C"+strconv.Itoa(i))
+ }
+ return ids
+}()
+
+// runCopyBuilt is every deck id whose text the code or docs now carry. The
+// task that writes a row's text adds its id here in the same commit.
+var runCopyBuilt = []string{}
+
+func mustParseRunRecord(t *testing.T) []copyRow {
+ t.Helper()
+ rows, err := parseMovesCopyRecord(runCopyRecordPath)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(rows) == 0 {
+ t.Fatalf("%s has no rows", runCopyRecordPath)
+ }
+ for _, r := range rows {
+ if !strings.HasPrefix(r.ID, "RUN-C") {
+ t.Fatalf("%s: %s is not a RUN-C id", runCopyRecordPath, r.ID)
+ }
+ }
+ return rows
+}
+
+// checkRunBuilt: every built id is named once, names a row, and that row is
+// approved.
+func checkRunBuilt(rows []copyRow, built []string) []string {
+ byID := map[string]copyRow{}
+ for _, r := range rows {
+ byID[r.ID] = r
+ }
+ var out []string
+ seen := map[string]bool{}
+ for _, id := range built {
+ if seen[id] {
+ out = append(out, fmt.Sprintf("runCopyBuilt names %s twice", id))
+ }
+ seen[id] = true
+ r, ok := byID[id]
+ switch {
+ case !ok:
+ out = append(out, fmt.Sprintf("runCopyBuilt names %s, which the deck has no row for", id))
+ case r.Status != "approved":
+ out = append(out, fmt.Sprintf("%s is built but %s: a string reaches code only after Paul approves it", id, r.Status))
+ }
+ }
+ return out
+}
+
+// builtRows is the rows runCopyBuilt names, in deck order.
+func builtRows(rows []copyRow, built []string) []copyRow {
+ want := map[string]bool{}
+ for _, id := range built {
+ want[id] = true
+ }
+ var out []copyRow
+ for _, r := range rows {
+ if want[r.ID] {
+ out = append(out, r)
+ }
+ }
+ return out
+}
+
+func TestRunCopyRecordIsComplete(t *testing.T) {
+ reportAll(t, checkMovesInventory(mustParseRunRecord(t), runCopyIDs))
+}
+
+func TestRunCopyHasNoEmDash(t *testing.T) {
+ reportAll(t, checkMovesNoEmDash(mustParseRunRecord(t)))
+}
+
+func TestRunBuiltCopyIsApproved(t *testing.T) {
+ reportAll(t, checkRunBuilt(mustParseRunRecord(t), runCopyBuilt))
+}
+
+// runFragment reports whether a row's text is a piece of a larger literal
+// (its file cell says "a fragment"): the top-level usage text, which no
+// whole-expression match can find.
+func runFragment(r copyRow) bool { return strings.Contains(r.File, "(a fragment") }
+
+// checkRunApplied is checkMovesApplied, plus the fragment rows: those must
+// sit inside some string literal of their file (goLiteralMatches,
+// approved_copy_test.go), never only in a comment.
+func checkRunApplied(rows []copyRow, root string) []string {
+ var whole []copyRow
+ var out []string
+ for _, r := range rows {
+ if !runFragment(r) {
+ whole = append(whole, r)
+ continue
+ }
+ if r.Status != "approved" {
+ continue
+ }
+ body, err := os.ReadFile(filepath.Join(root, r.Path()))
+ if err != nil {
+ out = append(out, fmt.Sprintf("%s: %v", r.ID, err))
+ continue
+ }
+ if !goLiteralMatches(body, func(v string) bool { return strings.Contains(v, r.Text) }) {
+ out = append(out, fmt.Sprintf("%s: %s has no string literal holding the approved text %q", r.ID, r.Path(), r.Text))
+ }
+ }
+ return append(checkMovesApplied(whole, root), out...)
+}
+
+func TestRunBuiltCopyIsApplied(t *testing.T) {
+ reportAll(t, checkRunApplied(builtRows(mustParseRunRecord(t), runCopyBuilt), "."))
+}
+
+// Each fixture case is a state the gate must refuse, for the right reason.
+func TestRunCopyGateRefusesTheNegativeFixtures(t *testing.T) {
+ dir := filepath.Join("testdata", "run-copy")
+ rows, err := parseMovesCopyRecord(filepath.Join(dir, "record.md"))
+ if err != nil {
+ t.Fatal(err)
+ }
+ t.Run("a built row still pending", func(t *testing.T) {
+ got := checkRunBuilt(rows, []string{"RUN-C2"})
+ if len(got) != 1 || !strings.Contains(got[0], "RUN-C2 is built but pending") {
+ t.Errorf("problems = %q", got)
+ }
+ })
+ t.Run("a built id with no row", func(t *testing.T) {
+ got := checkRunBuilt(rows, []string{"RUN-C9"})
+ if len(got) != 1 || !strings.Contains(got[0], "no row for") {
+ t.Errorf("problems = %q", got)
+ }
+ })
+ t.Run("a built id named twice", func(t *testing.T) {
+ got := checkRunBuilt(rows, []string{"RUN-C1", "RUN-C1"})
+ if len(got) != 1 || !strings.Contains(got[0], "twice") {
+ t.Errorf("problems = %q", got)
+ }
+ })
+ t.Run("an approved row whose text is only in a comment", func(t *testing.T) {
+ got := checkMovesApplied(builtRows(rows, []string{"RUN-C3"}), dir)
+ if len(got) != 1 || !strings.Contains(got[0], "RUN-C3") {
+ t.Errorf("problems = %q", got)
+ }
+ })
+ t.Run("an approved row that is applied", func(t *testing.T) {
+ if got := checkRunApplied(builtRows(rows, []string{"RUN-C1"}), dir); len(got) != 0 {
+ t.Errorf("problems = %q", got)
+ }
+ })
+ t.Run("a fragment inside a larger literal", func(t *testing.T) {
+ if got := checkRunApplied(builtRows(rows, []string{"RUN-C4"}), dir); len(got) != 0 {
+ t.Errorf("problems = %q", got)
+ }
+ })
+ t.Run("a fragment only in a comment", func(t *testing.T) {
+ got := checkRunApplied(builtRows(rows, []string{"RUN-C5"}), dir)
+ if len(got) != 1 || !strings.Contains(got[0], "RUN-C5") {
+ t.Errorf("problems = %q", got)
+ }
+ })
+}
diff --git a/testdata/run-copy/applied.go b/testdata/run-copy/applied.go
new file mode 100644
index 000000000..5173b543e
--- /dev/null
+++ b/testdata/run-copy/applied.go
@@ -0,0 +1,11 @@
+package fixture
+
+import "fmt"
+
+func say(host, id string) string { return fmt.Sprintf("%s has no run %s", host, id) }
+
+const usage = `usage: x
+ run run one command, somewhere`
+
+// the box's agent stopped: in this comment only, which never counts.
+// only in a comment
diff --git a/testdata/run-copy/record.md b/testdata/run-copy/record.md
new file mode 100644
index 000000000..2ea72df34
--- /dev/null
+++ b/testdata/run-copy/record.md
@@ -0,0 +1,7 @@
+| id | file | text | status |
+|---|---|---|---|
+| RUN-C1 | applied.go | <host> has no run <id> | approved |
+| RUN-C2 | applied.go | the instance hibernated | pending |
+| RUN-C3 | applied.go | the box's agent stopped | approved |
+| RUN-C4 | applied.go (a fragment of the usage text) | run one command | approved |
+| RUN-C5 | applied.go (a fragment of the usage text) | only in a comment | approved |