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

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.
This commit is contained in:
Ilia Denisov
2026-06-20 19:26:32 +02:00
parent c739f12d3d
commit a5db10c46e
12 changed files with 164 additions and 24 deletions
+8 -4
View File
@@ -66,7 +66,9 @@ services:
context: ..
dockerfile: backend/Dockerfile
args:
DICT_VERSION: ${DICT_VERSION:-v1.0.0}
# Seed dictionary for a FRESH volume; the per-contour value comes from the
# deploy env (Gitea TEST_/PROD_DICT_VERSION). See the volume note below.
DICT_VERSION: ${DICT_VERSION:-v1.2.1}
restart: unless-stopped
logging: *default-logging
depends_on:
@@ -94,9 +96,11 @@ services:
# (the image's /opt/dawg is owned by the nonroot UID, which the fresh volume
# inherits). The admin console writes new version subdirectories here, and the
# volume preserves them — and the versions in-progress games pin — across
# redeploys. Once seeded the volume is not re-seeded, so bumping DICT_VERSION on a
# later deploy has no effect on an existing contour; update via the console
# instead (docs/ARCHITECTURE.md §5).
# redeploys. Once seeded the volume is not re-seeded: DICT_VERSION is the seed for
# a FRESH volume only. On a live volume the backend refuses to start if DICT_VERSION
# no longer matches the recorded seed (the seed-drift guard), so a running contour's
# dictionary is changed through the admin console, never by bumping the seed
# (docs/ARCHITECTURE.md §5).
volumes:
- dawg-data:/opt/dawg
# No container healthcheck: the distroless image has no shell/wget. Readiness