isolated exec: plan 3 pre-flight rulings (SocketDir in LayoutInputs, prepare returns the env)
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YZ1ZvWj7naf73GjTX8MBv5
1 file changed,
+22
−6
docs/superpowers/plans/2026-09-11-isolated-exec-3-activator.md+22 −6
diff --git a/docs/superpowers/plans/2026-09-11-isolated-exec-3-activator.md b/docs/superpowers/plans/2026-09-11-isolated-exec-3-activator.md| index c47bc4806..bc00d9855 100644 |
| --- a/docs/superpowers/plans/2026-09-11-isolated-exec-3-activator.md |
| +++ b/docs/superpowers/plans/2026-09-11-isolated-exec-3-activator.md |
| @@ -604,13 +604,28 @@ const ( |
| // tests without a box want. |
| type LayoutInputs struct { |
| DataDir string |
| - Journal func(host string) bool |
| - Peers func() ([]registry.Route, error) |
| + // SocketDir is where flat sockets live and under which the nested |
| + // instances directory sits. Empty means provision.SocketDir; a test |
| + // points it at a temp dir so a route can classify as nested without |
| + // writing to /run/carlos. |
| + SocketDir string |
| + Journal func(host string) bool |
| + Peers func() ([]registry.Route, error) |
| // SameID reports whether two hosts share an instance identifier. Nil |
| // means provision.InstanceID equality; tests inject a collision. |
| SameID func(a, b string) bool |
| } |
| +// sockets returns the flat and nested socket paths for host under the |
| +// configured socket directory. |
| +func (in LayoutInputs) sockets(host string) (flat, nested string) { |
| + dir := in.SocketDir |
| + if dir == "" { |
| + dir = provision.SocketDir |
| + } |
| + return filepath.Join(dir, host+".sock"), filepath.Join(dir, "instances", provision.InstanceID(host), "app.sock") |
| +} |
| + |
| // ActivatorManaged is the activator's own predicate for a route it owns |
| // (activator.go's per-host gate and edge.go's proxy decision): an instance |
| // route, hibernate-flagged, with a socket, not unit-backed, not |
| @@ -640,10 +655,11 @@ func Classify(rt registry.Route, in LayoutInputs) (Layout, string) { |
| } |
| } |
| } |
| + flatSock, nestedSock := in.sockets(rt.Host) |
| switch { |
| - case rt.DBPath == provision.DefaultDBPath(in.DataDir, rt.Host) && rt.Socket == provision.DefaultSocket(rt.Host): |
| + case rt.DBPath == provision.DefaultDBPath(in.DataDir, rt.Host) && rt.Socket == flatSock: |
| return LayoutFlat, "" |
| - case rt.DBPath == provision.NestedDBPath(in.DataDir, rt.Host) && rt.Socket == provision.NestedSocket(rt.Host): |
| + case rt.DBPath == provision.NestedDBPath(in.DataDir, rt.Host) && rt.Socket == nestedSock: |
| return LayoutNested, "" |
| } |
| return LayoutForeign, fmt.Sprintf("db %q socket %q are neither the flat nor the nested defaults", rt.DBPath, rt.Socket) |
| @@ -1100,7 +1116,7 @@ git commit -m "activator: deduplicated child env, the Control seam, the per-role |
| type unitProc struct { host string; role instancectl.Role; unit, slice, invocation string; ctl *edge.ControlListener; logs *logListener; exited atomic.Bool; done chan struct{}; stopRequested atomic.Bool } |
| func (p *unitProc) Stop(ctx context.Context) error |
| func (p *unitProc) Exited() bool |
| - func (b *ExecBackend) prepare(rt registry.Route, role instancectl.Role, extraEnv map[string]string) (paths instancePaths, ctl *edge.ControlListener, logs *logListener, err error) |
| + func (b *ExecBackend) prepare(rt registry.Route, role instancectl.Role) (paths instancePaths, ctl *edge.ControlListener, logs *logListener, fileEnv map[string]string, err error) |
| func (b *ExecBackend) writeLaunch(paths instancePaths, role instancectl.Role, host string, argv, env []string) error |
| func (b *ExecBackend) startUnit(ctx context.Context, rt registry.Route) (Proc, string, error) |
| func (b *ExecBackend) seedUnit(ctx context.Context, rt registry.Route) error |
| @@ -1217,7 +1233,7 @@ func nestedBackend(t *testing.T, ctl *fakeControl, unit *fakeUnit) (*ExecBackend |
| } |
| ``` |
| -`RunDirOverride` is a test-only field: `pathsFor` uses it as the socket dir when non-empty (so a test can point `/run/carlos` at a temp dir); `Classify` compares `rt.Socket` against `provision.NestedSocket(host)` and would call this row foreign, so `pathsFor` passes a `LayoutInputs` whose `SocketDir` overrides `provision.SocketDir`: add `SocketDir string` to `LayoutInputs` (empty = `provision.SocketDir`) and use it in `Classify`'s two socket comparisons and in `pathsFor`. Update Task 2's `Classify` accordingly (flat: `filepath.Join(sockDir, host+".sock")`; nested: `filepath.Join(sockDir, "instances", provision.InstanceID(host), "app.sock")`); the Task 2 tests keep passing with an empty `SocketDir`. |
| +`RunDirOverride` is a test-only field on `ExecBackend`: when non-empty, `layoutInputs()` sets `LayoutInputs.SocketDir` to it and `pathsFor` uses it in place of `provision.SocketDir` for `runDir` (nested: `<RunDirOverride>/instances/<iid>`), so a test can point `/run/carlos` at a temp dir and the row still classifies as nested through Task 2's `sockets` helper. |
| ```go |
| func TestStartUnitWritesTheLaunchFileAndReturnsAUnitProc(t *testing.T) { |