carlos / platform Public

cli: region copy, as approved

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
claude agent, operated by paul@keymail.dev edffc4fd9506824262431d5b49de9a56be1623b6 parent ac1e7d4
2 files changed, +166 −0
  • region_copy.go +82 −0
  • region_copy_test.go +84 −0
diff --git a/region_copy.go b/region_copy.go
new file mode 100644
index 000000000..b770924e7
--- /dev/null
+++ b/region_copy.go
@@ -0,0 +1,82 @@
+package main
+
+import "fmt"
+
+// The nearest-region CLI strings (spec §19 and this plan's additions), as
+// approved in the nearest-region copy record. Change none of them without a
+// new copy review.
+
+// regionCreatedLine is C9 to C12, by source word; anything else reads as the
+// default.
+func regionCreatedLine(place, source string) string {
+ switch source {
+ case "timezone":
+ return fmt.Sprintf("Region: %s (from your timezone). Use --region to choose another.", place)
+ case "ip":
+ return fmt.Sprintf("Region: %s (from your network location). Use --region to choose another.", place)
+ case "chosen":
+ return fmt.Sprintf("Region: %s.", place)
+ }
+ return fmt.Sprintf("Region: %s (the platform default). Use --region to choose another.", place)
+}
+
+// regionNotRecordedOldConsole is C13a.
+const regionNotRecordedOldConsole = "This console does not record an app region yet, so --region was not applied."
+
+// regionNotAppliedSwitchOff is C13b.
+func regionNotAppliedSwitchOff(place string) string {
+ return fmt.Sprintf("This console is not assigning app regions yet, so --region was not applied. This app's instances start in %s.", place)
+}
+
+// instanceCreatedSuffix is C14: the parenthesis content of
+// "created instance {host} (...)".
+func instanceCreatedSuffix(channel, place string) string {
+ return fmt.Sprintf("channel %s, %s", channel, place)
+}
+
+// deployRegionMismatch is C15.
+func deployRegionMismatch(app, place string) string {
+ return fmt.Sprintf("%s already runs in %s. --region only applies when deploy creates an app. To place one instance elsewhere, use carlos instances create --region.", app, place)
+}
+
+// deployRegionUnreadable is C15b: deploy stops when it cannot read the app's
+// region.
+func deployRegionUnreadable(app string, err error) string {
+ return fmt.Sprintf("could not read %s's region (%v), so deploy stopped before shipping anything. Try again, or run without --region.", app, err)
+}
+
+// deployRegionUnknown is C15c: the console answered, but could not read the
+// app's region.
+func deployRegionUnknown(app string) string {
+ return fmt.Sprintf("the console could not read %s's region, so deploy stopped before shipping anything. Try again, or run without --region.", app)
+}
+
+// canaryRegionMismatch is C25.
+func canaryRegionMismatch(host, place string) string {
+ return fmt.Sprintf("canary %s already runs in %s. --region applies only when canary creates the host. Run carlos canary rm first to start it somewhere else.", host, place)
+}
+
+// canaryRegionOnFleet is C30.
+func canaryRegionOnFleet(app, fleet string) string {
+ return fmt.Sprintf("%s runs on your fleet %s, which decides where every instance runs, so --region does not apply. Run the command without --region.", app, fleet)
+}
+
+// canaryFleetUnknown is C30b: an older console cannot say whether a fleet
+// governs.
+func canaryFleetUnknown(app string) string {
+ return fmt.Sprintf("this console can't say where %s's instances run, so --region can't be checked. Update the console, or run the command without --region.", app)
+}
+
+// canaryRegionUnconfirmed is C30c: the canary's own record could not be read,
+// so whether it already runs elsewhere is unknown.
+func canaryRegionUnconfirmed(name string) string {
+ return fmt.Sprintf("could not confirm where canary %s runs, so nothing was changed. Try again, or run the command without --region.", name)
+}
+
+// C22a to C22d: flag help.
+const (
+ flagRegionAppsCreate = "region this app's instances start in (default: the region nearest you)"
+ flagRegionDeploy = "region for the app this deploy creates (default: the region nearest you)"
+ flagRegionCanary = "region for the canary instance (default: the app's region)"
+ flagRegionInstancesCreate = "region for this instance (default: the app's region, subject to the manifest's allow-list)"
+)
diff --git a/region_copy_test.go b/region_copy_test.go
new file mode 100644
index 000000000..632567784
--- /dev/null
+++ b/region_copy_test.go
@@ -0,0 +1,84 @@
+package main
+
+import (
+ "encoding/json"
+ "errors"
+ "os"
+ "sort"
+ "strconv"
+ "strings"
+ "testing"
+)
+
+func TestRegionCLICopy(t *testing.T) {
+ lines := map[string]string{}
+ for _, src := range []string{"timezone", "ip", "default", "chosen"} {
+ lines[src] = regionCreatedLine("P", src)
+ }
+ if len(map[string]bool{lines["timezone"]: true, lines["ip"]: true, lines["default"]: true, lines["chosen"]: true}) != 4 {
+ t.Fatalf("each source needs its own line: %v", lines)
+ }
+ if regionCreatedLine("P", "") != lines["default"] {
+ t.Fatal("an unknown source must read as the default")
+ }
+ all := []string{
+ regionNotRecordedOldConsole, regionNotAppliedSwitchOff("P"),
+ instanceCreatedSuffix("stable", "P"), deployRegionMismatch("blog", "P"),
+ deployRegionUnreadable("blog", errors.New("timeout")), deployRegionUnknown("blog"),
+ canaryRegionMismatch("c.go.tito.io", "P"), canaryRegionOnFleet("blog", "acme"),
+ canaryFleetUnknown("blog"), canaryRegionUnconfirmed("c"),
+ flagRegionAppsCreate, flagRegionDeploy, flagRegionCanary, flagRegionInstancesCreate,
+ }
+ for _, s := range append(all, lines["timezone"], lines["ip"], lines["default"], lines["chosen"]) {
+ if s == "" || strings.Contains(s, "—") || strings.Contains(s, "%!") {
+ t.Errorf("bad copy %q", s)
+ }
+ }
+}
+
+// TestRegionCLICopyMatchesTheApprovedRecord holds region_copy.go to the copy
+// record: every record entry filed under region_copy.go must appear in the
+// source as its exact quoted Go literal. A substring of a longer string, or
+// of an identifier, does not count.
+func TestRegionCLICopyMatchesTheApprovedRecord(t *testing.T) {
+ raw, err := os.ReadFile("docs/superpowers/plans/2026-10-02-nearest-region-copy.json")
+ if err != nil {
+ t.Fatal(err)
+ }
+ var rec struct {
+ Entries []struct {
+ ID string `json:"id"`
+ File string `json:"file"`
+ Text string `json:"text"`
+ } `json:"entries"`
+ }
+ if err := json.Unmarshal(raw, &rec); err != nil {
+ t.Fatal(err)
+ }
+ src, err := os.ReadFile("region_copy.go")
+ if err != nil {
+ t.Fatal(err)
+ }
+ want := []string{"C9", "C10", "C11", "C12", "C13a", "C13b", "C14", "C15", "C15b", "C15c",
+ "C22a", "C22b", "C22c", "C22d", "C25", "C30", "C30b", "C30c"}
+ var got []string
+ for _, e := range rec.Entries {
+ if e.File != "region_copy.go" {
+ continue
+ }
+ got = append(got, e.ID)
+ if e.Text == "" {
+ t.Errorf("%s: empty record text", e.ID)
+ continue
+ }
+ if !strings.Contains(string(src), strconv.Quote(e.Text)) {
+ t.Errorf("%s: region_copy.go has no literal %s", e.ID, strconv.Quote(e.Text))
+ }
+ }
+ // A record entry dropped or re-filed must not shrink this check silently.
+ sort.Strings(got)
+ sort.Strings(want)
+ if strings.Join(got, ",") != strings.Join(want, ",") {
+ t.Errorf("record entries for region_copy.go = %v, want %v", got, want)
+ }
+}