fix(engine): make .seed_version marker authoritative (no boot refusal) #93

Merged
developer merged 1 commits from feature/dict-seed-marker-wins into development 2026-06-20 18:25:12 +00:00
Owner

What

Follow-up to #92. Make the .seed_version marker authoritative instead of refuse-boot.

Why (incident)

On the test contour the TEST_DICT_VERSION variable was bumped to the active release (v1.2.1) while the volume's flat dir was seeded v1.0.0. The refuse-boot guard from #92 then crash-looped the backend: DICT_VERSION is the seed of a fresh volume, not the active version (which the admin console drives). A natural operator action shouldn't take the contour down.

Change

OpenWithVersions resolves the flat dir's version from .seed_version when present and ignores bootVersion on an already-seeded volume; bootVersion only seeds a fresh volume's marker. So:

  • a bumped build seed on a live volume is a no-op (can't relabel live bytes, can't void games pinned to the prior label), and correctly seeds the next fresh volume;
  • the subdir scan skips the resolved seed, so a version also present as a subdir (e.g. v1.2.1 uploaded via the console while the build seed is v1.2.1) stays loaded rather than shadowed by the flat bytes.

Still a guard against corruption — just by pinning the label to the marker rather than crashing.

Tests

TestOpenWithVersionsMarkerWinsOverBoot, TestOpenWithVersionsBumpedBootKeepsSubdir (the live-contour case). Docs flipped from "refuses to boot" to "marker wins / ignored" (ARCHITECTURE §5, READMEs, compose/.env, PRERELEASE DV).

Verification

Local against v1.2.1: gofmt, build, vet, unit, integration green. This PR's deploy restores the contour (marker v1.0.0 wins over the v1.2.1 build seed → boots flat v1.0.0 + resident v1.1.0/v1.2.1, active v1.2.1). TEST_DICT_VERSION=v1.2.1 can stay — harmless now, correct seed for a future wipe.

## What Follow-up to #92. Make the `.seed_version` marker **authoritative** instead of refuse-boot. ## Why (incident) On the test contour the `TEST_DICT_VERSION` variable was bumped to the active release (`v1.2.1`) while the volume's flat dir was seeded `v1.0.0`. The refuse-boot guard from #92 then crash-looped the backend: `DICT_VERSION` is the **seed** of a fresh volume, not the active version (which the admin console drives). A natural operator action shouldn't take the contour down. ## Change `OpenWithVersions` resolves the flat dir's version from `.seed_version` when present and **ignores** `bootVersion` on an already-seeded volume; `bootVersion` only seeds a fresh volume's marker. So: - a bumped build seed on a live volume is a **no-op** (can't relabel live bytes, can't void games pinned to the prior label), and correctly seeds the **next fresh** volume; - the subdir scan skips the *resolved seed*, so a version also present as a subdir (e.g. `v1.2.1` uploaded via the console while the build seed is `v1.2.1`) stays loaded rather than shadowed by the flat bytes. Still a guard against corruption — just by pinning the label to the marker rather than crashing. ## Tests `TestOpenWithVersionsMarkerWinsOverBoot`, `TestOpenWithVersionsBumpedBootKeepsSubdir` (the live-contour case). Docs flipped from "refuses to boot" to "marker wins / ignored" (ARCHITECTURE §5, READMEs, compose/.env, PRERELEASE DV). ## Verification Local against `v1.2.1`: gofmt, build, vet, unit, integration green. This PR's deploy restores the contour (marker `v1.0.0` wins over the `v1.2.1` build seed → boots flat `v1.0.0` + resident `v1.1.0`/`v1.2.1`, active `v1.2.1`). `TEST_DICT_VERSION=v1.2.1` can stay — harmless now, correct seed for a future wipe.
developer added 1 commit 2026-06-20 18:07:14 +00:00
fix(engine): make .seed_version marker authoritative (no boot refusal)
CI / changes (pull_request) Successful in 1s
CI / unit (pull_request) Successful in 10s
CI / integration (pull_request) Successful in 15s
CI / ui (pull_request) Successful in 53s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m2s
95f5703372
The seed-drift guard shipped as refuse-boot: the backend exited when
BACKEND_DICT_VERSION disagreed with the flat dir's recorded .seed_version. On
the test contour that turned a harmless-in-intent action — bumping the
TEST_DICT_VERSION variable to the active release (v1.2.1) on a volume seeded as
v1.0.0 — into a crash loop, because DICT_VERSION is the *seed* of a fresh
volume, not the active version (which the admin console drives).

Make the marker authoritative instead: OpenWithVersions resolves the flat dir's
version from .seed_version when present and ignores bootVersion on an
already-seeded volume; bootVersion only seeds a fresh volume's marker. So a
bumped build seed on a live volume is a no-op (it can't relabel live bytes and
can't void games pinned to the prior label), and it correctly seeds the next
fresh volume. The subdirectory scan now skips the resolved seed, so a version
also present as a subdir (e.g. v1.2.1 uploaded via the console while the build
seed is bumped to v1.2.1) is still loaded rather than shadowed by the flat bytes.

Tests: marker-wins over a bumped boot version; a bumped boot keeps the matching
subdir resident (the live-contour case). Docs updated (ARCHITECTURE §5, READMEs,
compose/.env, PRERELEASE DV) from "refuses to boot" to "marker wins / ignored".

Verified locally against v1.2.1: gofmt, build, vet, unit, integration green.
owner approved these changes 2026-06-20 18:24:45 +00:00
developer merged commit c72adddb91 into development 2026-06-20 18:25:12 +00:00
developer deleted branch feature/dict-seed-marker-wins 2026-06-20 18:25:12 +00:00
Sign in to join this conversation.
No Reviewers
No Label
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: developer/scrabble-game#93