feat(engine,deploy): seed-drift guard + track current dictionary release (v1.2.1) #92

Merged
developer merged 1 commits from feature/dict-version-track-release into development 2026-06-20 17:39:02 +00:00
Owner

What

Track the current dictionary release (v1.2.1) and add a seed-drift guard so a bumped build seed can never silently corrupt a live contour.

Why

The dictionary release moved to v1.2.1 while DICT_VERSION stayed pinned at v1.0.0 in CI and the image/compose seed. Beyond stale CI, the real hazard: the dawg-data volume is seeded once and never re-seeded, and the flat DAWGs carry no embedded version — so bumping the seed on a live volume relabels the already-seeded bytes, voiding games pinned to the prior label and serving the wrong dictionary to new ones, undetectably.

Changes

  • Seed-drift guard (engine.OpenWithVersions + seedmarker.go): records the flat dir's version in a .seed_version marker on first boot; refuses to start when a later BACKEND_DICT_VERSION disagrees. DICT_VERSION is now the seed for a fresh volume only; a live contour migrates through the admin console (prior versions stay resident, in-progress games keep replaying).
  • Track the release: CI DICT_VERSION centralised to one workflow-level env (v1.2.1); image / compose / .env.example seed defaults → v1.2.1. The deploy job still reads the per-contour vars.TEST_DICT_VERSION.
  • Docs: ARCHITECTURE §5 (decision record), backend/deploy READMEs, PRERELEASE DV row.

Verification

Local against the real v1.2.1 artifact: gofmt, build, vet, unit and integration (-tags=integration) all green. Two new engine tests cover the marker record + drift refusal.

Rollout (test contour — already done pre-PR)

The existing contour holds v1.0.0 (flat) + v1.1.0 (resident subdir), active v1.0.0. To keep the first guarded deploy safe:

  • Pre-armed .seed_version=v1.0.0 on scrabble_dawg-data (matches the real bytes).
  • Set Gitea TEST_DICT_VERSION=v1.0.0 (so this deploy boots v1.0.0, marker matches).

After merge + deploy, the contour is moved to v1.2.1 via the admin console (keeps v1.0.0 + v1.1.0 resident). At the next contour wipe, bump TEST_DICT_VERSION to v1.2.1.

## What Track the current dictionary release (`v1.2.1`) and add a **seed-drift guard** so a bumped build seed can never silently corrupt a live contour. ### Why The dictionary release moved to `v1.2.1` while `DICT_VERSION` stayed pinned at `v1.0.0` in CI and the image/compose seed. Beyond stale CI, the real hazard: the `dawg-data` volume is seeded once and never re-seeded, and the flat DAWGs carry **no embedded version** — so bumping the seed on a live volume relabels the already-seeded bytes, voiding games pinned to the prior label and serving the wrong dictionary to new ones, undetectably. ### Changes - **Seed-drift guard** (`engine.OpenWithVersions` + `seedmarker.go`): records the flat dir's version in a `.seed_version` marker on first boot; **refuses to start** when a later `BACKEND_DICT_VERSION` disagrees. `DICT_VERSION` is now the seed for a **fresh volume only**; a live contour migrates through the admin console (prior versions stay resident, in-progress games keep replaying). - **Track the release**: CI `DICT_VERSION` centralised to one workflow-level `env` (`v1.2.1`); image / compose / `.env.example` seed defaults → `v1.2.1`. The deploy job still reads the per-contour `vars.TEST_DICT_VERSION`. - **Docs**: ARCHITECTURE §5 (decision record), backend/deploy READMEs, PRERELEASE `DV` row. ### Verification Local against the real `v1.2.1` artifact: `gofmt`, `build`, `vet`, unit and integration (`-tags=integration`) all green. Two new engine tests cover the marker record + drift refusal. ### Rollout (test contour — already done pre-PR) The existing contour holds `v1.0.0` (flat) + `v1.1.0` (resident subdir), active `v1.0.0`. To keep the first guarded deploy safe: - Pre-armed `.seed_version=v1.0.0` on `scrabble_dawg-data` (matches the real bytes). - Set Gitea `TEST_DICT_VERSION=v1.0.0` (so this deploy boots `v1.0.0`, marker matches). After merge + deploy, the contour is moved to `v1.2.1` via the admin console (keeps `v1.0.0` + `v1.1.0` resident). At the next contour wipe, bump `TEST_DICT_VERSION` to `v1.2.1`.
developer added 1 commit 2026-06-20 17:28:44 +00:00
feat(engine,deploy): seed-drift guard + track current dictionary release
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Successful in 10s
CI / integration (pull_request) Successful in 14s
CI / ui (pull_request) Successful in 54s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m12s
a5db10c46e
The dictionary release moved to v1.2.1 while DICT_VERSION stayed pinned at
v1.0.0 in CI and the image/compose seed defaults. Two problems:

1. CI validated against a stale dictionary.
2. The contour seed could be bumped on a live volume, which silently relabels
   the already-seeded bytes — voiding games pinned to the prior label and
   serving the wrong dictionary for new ones. The flat DAWGs carry no embedded
   version, so this drift was undetectable.

Changes:

- Seed-drift guard: OpenWithVersions records the flat dir's version in a
  .seed_version marker on first boot and refuses to start when a later
  BACKEND_DICT_VERSION disagrees. DICT_VERSION is now the seed for a *fresh*
  volume only; a live contour migrates through the admin console (old versions
  stay resident, in-progress games keep replaying).
- Track the current release: CI's DICT_VERSION centralised to one workflow-level
  env (v1.2.1); image/compose/.env seed defaults bumped to v1.2.1. The deploy
  job keeps reading the per-contour vars.TEST_DICT_VERSION.
- Docs: ARCHITECTURE §5 (decision record), backend/deploy READMEs, PRERELEASE
  tracker (DV row).

Verified locally against the v1.2.1 artifact: gofmt, build, vet, unit and
integration (-tags=integration) all green.
owner approved these changes 2026-06-20 17:38:20 +00:00
developer merged commit d40fe1edec into development 2026-06-20 17:39:02 +00:00
developer deleted branch feature/dict-version-track-release 2026-06-20 17:39:02 +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#92