moves: T3 rejects a target-only layout variable off the flat layout; test diagnostics name keys, never values (Task 9 fix round 1)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
3 files changed,
+31
−11
internal/activator/backend_exec_test.go+8 −6internal/moves/envreport.go+6 −0internal/moves/envreport_test.go+17 −5
diff --git a/internal/activator/backend_exec_test.go b/internal/activator/backend_exec_test.go| index a3602a38c..7bba0776c 100644 |
| --- a/internal/activator/backend_exec_test.go |
| +++ b/internal/activator/backend_exec_test.go |
| @@ -336,27 +336,29 @@ func TestLaunchEnvironmentComposesTheSpawnEnvironment(t *testing.T) { |
| t.Fatal(err) |
| } |
| if len(shadowed) != 1 || shadowed[0] != "MINE" || env["FROM_CONFIG"] != "c" { |
| - t.Fatalf("shadowed %v (env values withheld: the agent's own environment is in it)", shadowed) |
| + t.Fatalf("shadowed names %v, want [MINE]; FROM_CONFIG: want set from the config file, got set=%v", shadowed, env["FROM_CONFIG"] != "") |
| } |
| if env["MINE"] != "1" || env["UNRELATED"] != "yes" || env["CARLOS_SECRETS_KEY"] != "" || env["CARLOS_ADMIN_TOKEN"] != "t" { |
| - t.Fatalf("launch env: MINE=%q SECRETS_KEY set=%v UNRELATED=%q", env["MINE"], env["CARLOS_SECRETS_KEY"] != "", env["UNRELATED"]) |
| + t.Fatalf("launch env: MINE matches the own file: %v; UNRELATED passed through: %v; CARLOS_SECRETS_KEY: want unset, got set=%v; CARLOS_ADMIN_TOKEN matches the own file: %v", |
| + env["MINE"] == "1", env["UNRELATED"] == "yes", env["CARLOS_SECRETS_KEY"] != "", env["CARLOS_ADMIN_TOKEN"] == "t") |
| } |
| // The agent-owned layer, exactly as agentOwnedVars composes it: the |
| // tenant's region and purge values are overridden or removed. |
| if env["CARLOS_REGION"] != "ie" || env["CARLOS_CONTROL_SOCKET"] != rt.Socket+".control" { |
| - t.Fatalf("agent-owned vars: region %q control %q", env["CARLOS_REGION"], env["CARLOS_CONTROL_SOCKET"]) |
| + t.Fatalf("agent-owned vars: CARLOS_REGION is the backend's: %v; CARLOS_CONTROL_SOCKET is the route's control path: %v", |
| + env["CARLOS_REGION"] == "ie", env["CARLOS_CONTROL_SOCKET"] == rt.Socket+".control") |
| } |
| if _, ok := env["CARLOS_PURGE"]; ok { |
| t.Fatal("CARLOS_PURGE survived on a box without a cache") |
| } |
| b.Cache = edge.NewCache(16, 1<<20) |
| if env, _, _ = b.LaunchEnvironment(rt); env["CARLOS_PURGE"] != "header" { |
| - t.Fatalf("CARLOS_PURGE on a box with a cache: %q", env["CARLOS_PURGE"]) |
| + t.Fatalf("CARLOS_PURGE on a box with a cache: want header, got set=%v", env["CARLOS_PURGE"] != "") |
| } |
| // A box with no region strips the tenant's value rather than keeping it. |
| b.Region = "" |
| if env, _, _ = b.LaunchEnvironment(rt); env["CARLOS_REGION"] != "" { |
| - t.Fatalf("CARLOS_REGION survived on a box with no region: %q", env["CARLOS_REGION"]) |
| + t.Fatal("CARLOS_REGION: want unset on a box with no region, got set") |
| } |
| } |
| @@ -367,6 +369,6 @@ func TestLaunchEnvironmentNoFiles(t *testing.T) { |
| rt := registry.Route{Host: "b.go.example.com", Socket: filepath.Join(b.DataDir, "b.sock")} |
| env, shadowed, err := b.LaunchEnvironment(rt) |
| if err != nil || len(shadowed) != 0 || env["CARLOS_REGION"] != "ie" { |
| - t.Fatalf("region %q shadowed %v err %v", env["CARLOS_REGION"], shadowed, err) |
| + t.Fatalf("CARLOS_REGION is the backend's: %v; shadowed %v; err %v", env["CARLOS_REGION"] == "ie", shadowed, err) |
| } |
| } |
diff --git a/internal/moves/envreport.go b/internal/moves/envreport.go| index 6837fb41c..24ea7a4e8 100644 |
| --- a/internal/moves/envreport.go |
| +++ b/internal/moves/envreport.go |
| @@ -156,6 +156,12 @@ func CompareEnv(source, target EnvReport, flatLayout bool) []EnvDiff { |
| diffs = append(diffs, EnvDiff{name, "extra"}) |
| case "advisory": |
| diffs = append(diffs, EnvDiff{name, "advisory-differs"}) |
| + case "layout": |
| + // present iff the flat layout provides it: a target-only |
| + // layout variable is wrong on a non-flat landing |
| + if !flatLayout { |
| + diffs = append(diffs, EnvDiff{name, "layout-present"}) |
| + } |
| } |
| } |
| // layout names absent from BOTH reports are still checked: a flat |
diff --git a/internal/moves/envreport_test.go b/internal/moves/envreport_test.go| index bf6ffd09a..f5739830f 100644 |
| --- a/internal/moves/envreport_test.go |
| +++ b/internal/moves/envreport_test.go |
| @@ -83,17 +83,29 @@ func TestCompareEnvNestedLayout(t *testing.T) { |
| key := []byte("0123456789abcdef0123456789abcdef") |
| src := ReportEnv(key, map[string]string{"A": "1", "CARLOS_REGION": "ie"}) |
| tgt := ReportEnv(key, map[string]string{"A": "1", "CARLOS_REGION": "uk", "CARLOS_CONTROL_SOCKET": "/run/y"}) |
| - diffs := CompareEnv(src, tgt, false) |
| - // a layout name only the target carries is not "extra": the not-flat |
| - // rule (layout-present) fires only for a name in the source report, so |
| - // the target-only case is pinned here as the current behaviour. |
| - if len(diffs) != 0 { |
| + // T3's "present iff the flat layout provides it": a layout variable |
| + // only the target carries is a diff on a non-flat landing, and |
| + // nothing on a flat one. |
| + if diffs := CompareEnv(src, tgt, false); len(diffs) != 1 || diffs[0].Name != "CARLOS_CONTROL_SOCKET" || diffs[0].Kind != "layout-present" { |
| t.Fatalf("target-only layout var, non-flat: %v", diffs) |
| } |
| + if diffs := CompareEnv(src, tgt, true); len(diffs) != 0 { |
| + t.Fatalf("target-only layout var, flat: %v", diffs) |
| + } |
| src2 := ReportEnv(key, map[string]string{"A": "1", "CARLOS_REGION": "ie", "CARLOS_CONTROL_SOCKET": "/run/x"}) |
| if diffs := CompareEnv(src2, tgt, false); len(diffs) != 1 || diffs[0].Kind != "layout-present" { |
| t.Fatalf("layout-present: %v", diffs) |
| } |
| + // neither side carries it, non-flat: clean |
| + none := ReportEnv(key, map[string]string{"A": "1", "CARLOS_REGION": "uk"}) |
| + if diffs := CompareEnv(src, none, false); len(diffs) != 0 { |
| + t.Fatalf("no layout var anywhere, non-flat: %v", diffs) |
| + } |
| + // the advisory exception holds: a target-only CARLOS_PURGE is a note |
| + purge := ReportEnv(key, map[string]string{"A": "1", "CARLOS_REGION": "uk", "CARLOS_PURGE": "header"}) |
| + if diffs := CompareEnv(src, purge, false); len(diffs) != 1 || !diffs[0].Note() { |
| + t.Fatalf("target-only purge, non-flat: %v", diffs) |
| + } |
| } |
| func TestReportEnvIsDeterministicAndDigestCoversNamesAndValues(t *testing.T) { |