sim: hostlife: a restored database replicates from the TXID it restored to
Rev 7.5's first baseline lost durable writes at 2 / 30,000: after a cold restore the replicator's position stayed at 0, so the next level-0 file claimed [1, TX] while carrying only the pending pages; the planner preferred it and the checksum check refused the restore, correctly. The model's restore now sets the position where litestream's -txid sidecar does. Package doc cites claim rev 6.2.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 files changed,
+9
−5
internal/sim/hostlife/protocol_test.go+7 −3internal/sim/hostlife/world_test.go+2 −2
diff --git a/internal/sim/hostlife/protocol_test.go b/internal/sim/hostlife/protocol_test.go| index 6ee60967c..5a293f31c 100644 |
| --- a/internal/sim/hostlife/protocol_test.go |
| +++ b/internal/sim/hostlife/protocol_test.go |
| @@ -192,7 +192,7 @@ func (w *world) restore(b *box, inc int, loc, gen string) *localDB { |
| } |
| if best != nil { |
| apply(db.State, best.B) |
| - db.TX, db.Key = best.B.Max, best.B.SealKey |
| + db.TX, db.Rep, db.Key = best.B.Max, best.B.Max, best.B.SealKey |
| if best.B.Inc != 0 { |
| db.Inc = best.B.Inc |
| } |
| @@ -242,7 +242,11 @@ func (w *world) restore(b *box, inc int, loc, gen string) *localDB { |
| if last == nil && gen != "" { |
| return nil |
| } |
| - db.TX = cur |
| + // the restored database's replication position is where the restore |
| + // reached: its next LTX file starts at cur+1 (litestream's -txid |
| + // sidecar). Rev 7.5's first run shipped [1, TX] with only the new pages |
| + // after a cold restore; the checksum check refused it, correctly |
| + db.TX, db.Rep = cur, cur |
| return db |
| } |
| @@ -291,7 +295,7 @@ func (w *world) spawn(b *box, c *claim, want string, probe bool) bool { |
| } |
| if newest != nil { |
| apply(b.DB.State, newest.B) |
| - b.DB.TX, b.DB.Key = newest.B.Max, newest.B.SealKey |
| + b.DB.TX, b.DB.Rep, b.DB.Key = newest.B.Max, newest.B.Max, newest.B.SealKey |
| if newest.B.Inc != 0 { |
| b.DB.Inc = newest.B.Inc |
| } |
diff --git a/internal/sim/hostlife/world_test.go b/internal/sim/hostlife/world_test.go| index 7e1299163..372891001 100644 |
| --- a/internal/sim/hostlife/world_test.go |
| +++ b/internal/sim/hostlife/world_test.go |
| @@ -1,7 +1,7 @@ |
| // Package hostlife is a deterministic, randomized model of the host |
| // lifecycle claim (docs/superpowers/specs/2026-10-02-host-lifecycle-claim-design.md, |
| -// rev 6, 3ea3f90c) and Phase 1 of move-any-app |
| -// (docs/superpowers/specs/2026-10-02-move-any-app-design.md, rev 7.4). |
| +// rev 6.2, 30d572c4) and Phase 1 of move-any-app |
| +// (docs/superpowers/specs/2026-10-02-move-any-app-design.md, rev 7.5). |
| // |
| // Since joint round 2 the model encodes what the specs say and nothing |
| // stronger: restore reads the holder's location and the generation the |