feat(control): make the controller generation the repository's; a cold resume opens a placement generation - #35
Merged
Conversation
…d resume opens a placement generation The controller lease lived in a map inside AttachmentService, so a controld restart handed session authority out again from zero and two replicas over one store could grant the same generation twice. SessionRepository now owns it: NextControllerGeneration advances a session's controller generation atomically and returns it, Session carries ControllerGeneration, and the service keeps none of its own — a viewer attaches under the row's value, a controller asks the repository for the next. The port docs pin the generation semantics the stores must implement, so the hosted cell and the self-hosted stores cannot drift: Transition advances PlacementGeneration whenever its RunnerID option names a runner, UpsertRunner is ErrStale below the stored runner generation, SetEnvironmentSnapshot is ErrStale on a moved setup hash and ErrNotFound on an absent environment. That rule makes a cold resume a placement, per the hosted PRD §9: it starts a new sandbox, so it names the session's own runner again and opens a new generation, while a warm resume unpauses the sandbox it has and names none. The self-hosted adapter answers NextControllerGeneration from a process-local table on the host's side of the port, after confirming the row exists in the store. Making it durable is Task 2 of the workspace-scope plan. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GiKRhqhzgJ1UDaLBynMyj3
Merged
5 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Task 1 of
docs/superpowers/plans/2026-08-30-workspace-scope-and-generations.md— the plan's one coordinatedcontrolchange, additive and non-behavioral on the wire (the #31 pattern).control.Session.ControllerGenerationandcontrol.SessionRepository.NextControllerGeneration: the controller lease is the repository's.AttachmentServicedrops its in-memory lease map; a viewer attaches under the row's value, a controller asks the repository for the next. The self-hosted adapter answers from a process-local table for now (Task 2 persists it).TransitionadvancesPlacementGenerationwhen itsRunnerIDoption names a runner;UpsertRunnerisErrStalebelow the stored generation;SetEnvironmentSnapshotisErrStaleon a moved hash andErrNotFoundon an absent environment.ResumeSession's cold branch names the session's own runner so the repository opens a new generation for the new sandbox; a warm resume names none.Test plan
TestControllerGenerationIsTheRepositorys(viewer 4 from the row, controller 5 from one repository call) andTestColdResumeOpensANewPlacementGeneration(cold → 2, warm → 1), both seen failing before the changegofmt,go vet,go test ./control ./controlapp -race,go test ./internal/controld/... -race,scripts/check-public-control.sh(inventory unchanged, no new duplicate),make verify,git diff --check— run by the worker and rerun independently by the reviewer🤖 Generated with Claude Code
https://claude.ai/code/session_01GiKRhqhzgJ1UDaLBynMyj3