seeds: raise the protocol to 1 (Plan 8 Task 6)
ProtocolVersion is 1: this build places, swaps and rolls back a seed,
refuses moves of an unplaced or uncommitted one, and its console sweeps
and assigns. The pre-raise checks (preflight §8) all held: the sweep and
assign door with M2 to M9; seedMoveRefusal in MoveRequest,
MoveStartTransition and SetRecordRegion; the movesPass skip and the
ReadyProbe gate; seedRegionReady's protocol check before the floor's
release, pinned by TestSeedRegionReadyFailsClosedOnTheEdgesFile ("an
unreadable local floor"); the box's seed wiring; no test pinning 0; every
deck row wired.
The floor test becomes TestProtocolMeetsWhatTheConsoleRequires, and the
index names Plan 8 as the plan that raises it.
Release note: publish the seeds floor with min_release at or above the
first release that speaks protocol 1, never lower. A carlos.prev built
from Plans 2 to 7 (protocol 0, no move refusal) must read as below the
floor. The raise opens nothing by itself: a door opens only when an
operator publishes the floor (spec §10 step 2), which is Paul's step.
Rollout gates for Paul. These gate publishing the floor (spec §10 step 2),
not this raise:
- a held rollback has no exit except a hand 'DELETE FROM import_journal';
- a kept old replica can be restored by the next seed's first wake;
- versioned buckets keep deleted snapshots as noncurrent versions, with
no noncurrent-version expiry;
- the console and box roles need the S3 permissions in the ledgers
(seeds/* Put/Delete/List, instances/* List/Delete/GetObject lock.json,
the legacy-route-owners file);
- SD-N39 says 'Try again', but a finish can take up to about 5 minutes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
3 files changed,
+22
−20
docs/superpowers/plans/2026-10-08-seeded-instances-0-index.md+3 −2internal/seeds/floor.go+12 −10internal/seeds/floor_test.go+7 −8
diff --git a/docs/superpowers/plans/2026-10-08-seeded-instances-0-index.md b/docs/superpowers/plans/2026-10-08-seeded-instances-0-index.md| index f2d6ae92a..a4ceba593 100644 |
| --- a/docs/superpowers/plans/2026-10-08-seeded-instances-0-index.md |
| +++ b/docs/superpowers/plans/2026-10-08-seeded-instances-0-index.md |
| @@ -31,8 +31,9 @@ There is no feature flag. The seeds floor (spec §3.3) is the switch: |
| seed-capable, the nested layout and no claim control (Plan 3 Task 5); the |
| import door also requires a one-box region (a deviation, Plan 3 Task 5); |
| - a box reports `seeds_protocol` from `seeds.ProtocolVersion`, which Plan 3 |
| - introduces at **0** and Plan 7's last task raises to **1**, once the box |
| - can place, swap and roll back; |
| + introduces at **0** and Plan 8's Task 6 raises to **1**, once the box |
| + can place, swap and roll back, refuses moves of an unplaced or |
| + uncommitted seed, and the console sweeps and assigns; |
| - the console requires `seeds_protocol >= 1` from every box. |
| So Plans 2 to 6 merge dark: no box running their builds can claim to be |
diff --git a/internal/seeds/floor.go b/internal/seeds/floor.go| index 00158620b..8798041d9 100644 |
| --- a/internal/seeds/floor.go |
| +++ b/internal/seeds/floor.go |
| @@ -12,17 +12,19 @@ import ( |
| ) |
| // ProtocolVersion is the seeds protocol this build speaks. A box that |
| -// reports 0 can never satisfy the console's RequiredProtocol, so every |
| -// seed door stays shut. |
| +// reports 0 (Plans 3 to 7, and any older build) can never satisfy the |
| +// console's RequiredProtocol, so every seed door stays shut for it. |
| // |
| -// It stays 0 through Plan 7, although this build places, swaps and rolls |
| -// back a seed (Plans 4 and 7): spec §5.8's move refusals, the seeds sweep |
| -// and the legacy-routes assign door must exist before any door opens |
| -// (preflight M9). Plan 8's last task raises it to 1, with the comment |
| -// "1: this build places, swaps and rolls back a seed", and rewrites |
| -// floor_test.go's TestProtocolStartsBelowWhatTheConsoleRequires as |
| -// TestProtocolMeetsWhatTheConsoleRequires. |
| -const ProtocolVersion = 0 |
| +// 1: this build places, swaps and rolls back a seed, refuses moves of an |
| +// unplaced or uncommitted one, and its console sweeps and assigns. |
| +// |
| +// It stayed 0 through Plan 7, although that build placed, swapped and |
| +// rolled back a seed (Plans 4 and 7): spec §5.8's move refusals, the |
| +// seeds sweep and the legacy-routes assign door had to exist before any |
| +// door opens (preflight M9). Plan 8 built them, and its Task 6 raised it |
| +// to 1. Raising it opens nothing alone: a door opens only once an |
| +// operator publishes the seeds floor (spec §10 step 2). |
| +const ProtocolVersion = 1 |
| // RequiredProtocol is what the console requires every box in the region to |
| // report before it writes any seed state (spec §3.3). |
diff --git a/internal/seeds/floor_test.go b/internal/seeds/floor_test.go| index 111be296c..28231e217 100644 |
| --- a/internal/seeds/floor_test.go |
| +++ b/internal/seeds/floor_test.go |
| @@ -108,14 +108,13 @@ func TestReleaseAtOrAbove(t *testing.T) { |
| } |
| } |
| -func TestProtocolStartsBelowWhatTheConsoleRequires(t *testing.T) { |
| - // The floor ships dark: no box built from it can satisfy the console's |
| - // check. Plan 7 builds the swap and the rollback but leaves the switch |
| - // off (preflight M9): spec §5.8's move refusals, the seeds sweep and |
| - // the legacy-routes assign door must exist before any door opens. Plan |
| - // 8's last task raises ProtocolVersion and rewrites this test as |
| - // TestProtocolMeetsWhatTheConsoleRequires. |
| - if ProtocolVersion >= RequiredProtocol { |
| +func TestProtocolMeetsWhatTheConsoleRequires(t *testing.T) { |
| + // The floor shipped dark through Plan 7 (preflight M9): spec §5.8's |
| + // move refusals, the seeds sweep and the legacy-routes assign door had |
| + // to exist before any door opens. Plan 8 built them, and its Task 6 |
| + // raised ProtocolVersion, so a box built from here can satisfy the |
| + // console's check once an operator publishes the seeds floor. |
| + if ProtocolVersion < RequiredProtocol { |
| t.Fatalf("ProtocolVersion = %d, RequiredProtocol = %d", ProtocolVersion, RequiredProtocol) |
| } |
| } |