sim: hostlife: an empty dead generation still gets its park-generation chore
Found by the rev 7.12 30,000-seed baseline (seeds 15273 and 20810): the previous commit queued no chore for a dead generation holding nothing in the publishing region, and a dead writer's late upload or certificate then landed in it with no chore owing it. The chore is queued for every dead generation of this region, empty or not; only one whose objects are another region's is left to that region's publication.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
1 file changed,
+6
−3
internal/sim/hostlife/protocol_test.go+6 −3
diff --git a/internal/sim/hostlife/protocol_test.go b/internal/sim/hostlife/protocol_test.go| index 8c9cc3713..df2e4e835 100644 |
| --- a/internal/sim/hostlife/protocol_test.go |
| +++ b/internal/sim/hostlife/protocol_test.go |
| @@ -944,7 +944,7 @@ func (w *world) publishGeneration(b *box, c *claim, observedOpID, observedPhase |
| // stays uncovered for that region's next PublishGeneration: a |
| // chore queued there from here would park a generation the |
| // rollback may still need (seeds 33646, 40148, 1296 / rev 7.12) |
| - if e.Predecessor.Gen == published || !w.hasFilesAnywhere(n.Holder.Location, e.Predecessor.Gen) || hasStr(dead, e.Predecessor.Gen) && w.hasFilesIn(region, n.Holder.Location, e.Predecessor.Gen) { |
| + if e.Predecessor.Gen == published || hasStr(dead, e.Predecessor.Gen) && (w.hasFilesIn(region, n.Holder.Location, e.Predecessor.Gen) || !w.hasFilesAnywhere(n.Holder.Location, e.Predecessor.Gen)) { |
| e.Covered = true |
| } |
| } |
| @@ -962,9 +962,12 @@ func (w *world) publishGeneration(b *box, c *claim, observedOpID, observedPhase |
| } |
| n.Holder.Admissions = keep |
| for _, retire := range dead { |
| - if retire == published || !w.hasFilesIn(region, n.Holder.Location, retire) { |
| - continue // nothing of it here: an empty generation, or one whose objects are another region's |
| + if retire == published || !w.hasFilesIn(region, n.Holder.Location, retire) && w.hasFilesAnywhere(n.Holder.Location, retire) { |
| + continue // its objects are another region's: that region's publication retires it |
| } |
| + // an empty dead generation still gets its chore: a dead writer's |
| + // late upload or certificate may land in it within the chore's |
| + // horizon (seeds 15273 and 20810 / 30,000) |
| ret := retire |
| if ret == "" { |
| ret = "@root" // the sentinel for the origin generation (claim rev 6.10) |