| 1 | // approved_db_forward_copy_test.go |
| 2 | package main |
| 3 | |
| 4 | import ( |
| 5 | "fmt" |
| 6 | "os" |
| 7 | "regexp" |
| 8 | "strconv" |
| 9 | "strings" |
| 10 | "testing" |
| 11 | ) |
| 12 | |
| 13 | // The copy gate of the db region forward plans (spec 2026-10-22 §10), the |
| 14 | // region HA 2b gate over this record: |
| 15 | // |
| 16 | // - TestDBForwardCopyRecordIsComplete: the record names exactly |
| 17 | // dbForwardCopyIDs; |
| 18 | // - TestDBForwardCopyHasNoEmDash; |
| 19 | // - TestDBForwardBuiltCopyIsApproved: an id in dbForwardCopyBuilt is an |
| 20 | // approved row. No pending string reaches code or docs; |
| 21 | // - TestDBForwardBuiltCopyIsApplied: a built row's text is in the file it |
| 22 | // names. |
| 23 | const dbForwardCopyRecordPath = "docs/superpowers/plans/2026-10-22-db-region-forward-copy.md" |
| 24 | |
| 25 | var dbForwardCopyIDPattern = regexp.MustCompile(`^DBF-[0-9]+$`) |
| 26 | |
| 27 | // dbForwardCopyIDs is the record's inventory, pinned: DBF-1 to DBF-20, |
| 28 | // DBF-23 and DBF-24 (plan 3's pull rows among them), then DBF-21, DBF-22, |
| 29 | // DBF-30, DBF-31 and DBF-32. |
| 30 | var dbForwardCopyIDs = func() []string { |
| 31 | ids := make([]string, 0, 27) |
| 32 | for i := 1; i <= 24; i++ { |
| 33 | if i == 21 || i == 22 { |
| 34 | continue // appended below, in the record's order |
| 35 | } |
| 36 | ids = append(ids, "DBF-"+strconv.Itoa(i)) |
| 37 | } |
| 38 | return append(ids, "DBF-21", "DBF-22", "DBF-30", "DBF-31", "DBF-32") |
| 39 | }() |
| 40 | |
| 41 | // dbForwardCopyBuilt is every id whose text the code or docs carry. The task |
| 42 | // that writes a row's text adds its id here in the same commit, once Paul has |
| 43 | // approved the row. |
| 44 | var dbForwardCopyBuilt = []string{ |
| 45 | "DBF-1", "DBF-2", "DBF-14", "DBF-9", "DBF-10", "DBF-21", "DBF-22", // the console |
| 46 | "DBF-3", "DBF-4", "DBF-5", "DBF-6", "DBF-7", "DBF-8", "DBF-11", "DBF-12", "DBF-13", "DBF-15", "DBF-16", "DBF-32", // the CLI |
| 47 | "DBF-19", "DBF-20", // the console's pull audit details (plan 3) |
| 48 | "DBF-17", "DBF-18", "DBF-24", // the CLI's pull sentences (plan 3) |
| 49 | "DBF-23", "DBF-31", // docs/site/cli.md (DBF-23 replaced DBF-30 there) |
| 50 | } |
| 51 | |
| 52 | // dbForwardCopyWired is every id whose PENDING text the code already |
| 53 | // carries, behind the console's CARLOS_DB_FORWARD switch, which is off |
| 54 | // unless a deployment sets it (plan 2's build, ruling R1: Paul asked for the |
| 55 | // feature to work first, and the copy review comes separately). This is the |
| 56 | // moves record's D13 rule, a pending sentence only behind a switch that is |
| 57 | // off by default, in list form: every DBF sentence in code is reached only |
| 58 | // from a console that forwards, so none reaches a person on a deployment |
| 59 | // that has not turned forwarding on. The copy review moves each id from here |
| 60 | // to dbForwardCopyBuilt, applying Paul's edits in the same commit. Docs rows |
| 61 | // are public the moment the site syncs, so they are never wired. Luna |
| 62 | // approved every plan 2 row and every plan 3 pull row on 2026-10-23, so the |
| 63 | // list is empty and every row is built. |
| 64 | var dbForwardCopyWired = []string{} |
| 65 | |
| 66 | func mustParseDBForwardRecord(t *testing.T) []copyRow { |
| 67 | t.Helper() |
| 68 | raw, err := os.ReadFile(dbForwardCopyRecordPath) |
| 69 | if err != nil { |
| 70 | t.Fatal(err) |
| 71 | } |
| 72 | rows, err := parseCopyTable(string(raw), dbForwardCopyRecordPath, dbForwardCopyIDPattern, "a DBF-<n>") |
| 73 | if err != nil { |
| 74 | t.Fatal(err) |
| 75 | } |
| 76 | return rows |
| 77 | } |
| 78 | |
| 79 | func TestDBForwardCopyRecordIsComplete(t *testing.T) { |
| 80 | reportAll(t, checkMovesInventory(mustParseDBForwardRecord(t), dbForwardCopyIDs)) |
| 81 | } |
| 82 | |
| 83 | func TestDBForwardCopyHasNoEmDash(t *testing.T) { |
| 84 | reportAll(t, checkMovesNoEmDash(mustParseDBForwardRecord(t))) |
| 85 | } |
| 86 | |
| 87 | func TestDBForwardBuiltCopyIsApproved(t *testing.T) { |
| 88 | reportAll(t, checkRunBuilt(mustParseDBForwardRecord(t), dbForwardCopyBuilt)) |
| 89 | } |
| 90 | |
| 91 | func TestDBForwardBuiltCopyIsApplied(t *testing.T) { |
| 92 | rows := builtRows(mustParseDBForwardRecord(t), dbForwardCopyBuilt) |
| 93 | for i := range rows { |
| 94 | rows[i].Text = strings.ReplaceAll(rows[i].Text, `\n`, "\n") |
| 95 | } |
| 96 | reportAll(t, checkRunApplied(rows, ".")) |
| 97 | } |
| 98 | |
| 99 | // checkDBForwardWired: a wired id is a pending row the record has, named |
| 100 | // once, not built as well, not a docs row, and its text is in the file it |
| 101 | // names (so the review's edits must reach the code). |
| 102 | func checkDBForwardWired(rows []copyRow, wired, built []string) []string { |
| 103 | byID := map[string]copyRow{} |
| 104 | for _, r := range rows { |
| 105 | byID[r.ID] = r |
| 106 | } |
| 107 | isBuilt := map[string]bool{} |
| 108 | for _, id := range built { |
| 109 | isBuilt[id] = true |
| 110 | } |
| 111 | var out []string |
| 112 | var apply []copyRow |
| 113 | seen := map[string]bool{} |
| 114 | for _, id := range wired { |
| 115 | if seen[id] { |
| 116 | out = append(out, fmt.Sprintf("dbForwardCopyWired names %s twice", id)) |
| 117 | } |
| 118 | seen[id] = true |
| 119 | r, ok := byID[id] |
| 120 | switch { |
| 121 | case !ok: |
| 122 | out = append(out, fmt.Sprintf("dbForwardCopyWired names %s, which the record has no row for", id)) |
| 123 | continue |
| 124 | case isBuilt[id]: |
| 125 | out = append(out, fmt.Sprintf("%s is both wired and built: an approved row moves to dbForwardCopyBuilt", id)) |
| 126 | case r.Status != "pending": |
| 127 | out = append(out, fmt.Sprintf("%s is %s: an approved row moves from dbForwardCopyWired to dbForwardCopyBuilt", id, r.Status)) |
| 128 | case strings.HasPrefix(r.Path(), "docs/"): |
| 129 | out = append(out, fmt.Sprintf("%s is a docs row: pending docs text is never wired", id)) |
| 130 | } |
| 131 | r.Status = "approved" // checkMovesApplied reads approved rows only |
| 132 | apply = append(apply, r) |
| 133 | } |
| 134 | return append(out, checkMovesApplied(apply, ".")...) |
| 135 | } |
| 136 | |
| 137 | func TestDBForwardWiredCopyIsPendingAndApplied(t *testing.T) { |
| 138 | rows := mustParseDBForwardRecord(t) |
| 139 | for i := range rows { |
| 140 | rows[i].Text = strings.ReplaceAll(rows[i].Text, `\n`, "\n") |
| 141 | } |
| 142 | reportAll(t, checkDBForwardWired(rows, dbForwardCopyWired, dbForwardCopyBuilt)) |
| 143 | } |
| 144 | |
| 145 | // The gate bites: a wired row whose text is not in its file, an approved |
| 146 | // row left wired, and a docs row wired are each refused. |
| 147 | func TestDBForwardWiredGateRefuses(t *testing.T) { |
| 148 | rows := []copyRow{ |
| 149 | {"DBF-1", "internal/console/apidbforward.go", "nothing like this sentence is in the file.", "pending"}, |
| 150 | {"DBF-2", "internal/console/apidbforward.go", "x", "approved"}, |
| 151 | {"DBF-30", "docs/site/cli.md", "x", "pending"}, |
| 152 | } |
| 153 | got := checkDBForwardWired(rows, []string{"DBF-1", "DBF-2", "DBF-30"}, nil) |
| 154 | for _, want := range []string{"does not contain the approved text", "DBF-2 is approved", "DBF-30 is a docs row"} { |
| 155 | found := false |
| 156 | for _, g := range got { |
| 157 | found = found || strings.Contains(g, want) |
| 158 | } |
| 159 | if !found { |
| 160 | t.Errorf("no problem saying %q in %q", want, got) |
| 161 | } |
| 162 | } |
| 163 | } |
| 164 | |