tg-bot-ts/.claude/MERGE_CHECKLIST.md
Nuno Duque Nunes 7d66ab7319 fix: result posting bugs, tg-history shape, and stat-input parser hardening
- Result.post() now returns { ok, reason } instead of void — it used to
  silently no-op (unconfigured channel, or zero rows built) while
  /tg-admin result post always reported success regardless
- Fixed a crash when a TGScore's class is missing and the character it
  names is gone from CharacterRegistry (orphaned history) — Emoji.class()
  and Emoji.nation() now degrade to a placeholder instead of throwing
- Fixed tg-history files being written with only a scores array, missing
  date/confirmed/nationKD — Score.submit's loadHistory now fills in the
  full TGResult shape on every read; scripts/migrate-history-shape.py
  backfills existing files (50 fixed in dev, run on prod too — this
  script is gitignored like the other migration scripts, copy manually)
- ATK/DEF/Heal shorthand parser: accepts comma as a decimal separator
  (3,4M == 3.4M), and rejects implausibly large values (150.0M, or an
  already-full number with a redundant M) via a configurable ceiling
  (Config.tg.maxStatValue, default 50,000,000, /tg-config tg
  set-max-stat-value) instead of silently producing multi-billion junk
- data/updates v0.10.1 (result posting fixes) and v0.10.2 (parser
  refinements) — sequenced after the already-deployed v0.10 rather than
  backfilling v0.9.x, since posting order in #updates is what matters
- new announcement (002) explaining the shorthand input change to players
- doc updates: REFERENCE.md and MERGE_CHECKLIST.md cover all of the above
2026-07-31 02:59:26 +01:00

3.6 KiB

TG Bot — Merge & Deployment Checklist

Follow these steps IN ORDER every time we're ready to merge dev → prod. Never skip steps, never edit prod directly.


Step 1 — Commit on dev

cd /opt/docker/tg-bot-ts-dev
git add -A
git commit -m "<message>"
git push origin dev

Commit message conventions:

  • feature: short description — new player-facing feature
  • fix: short description — bug fix
  • housekeeping: short description — internal/admin-only addition, refactor, maintenance
  • For multi-topic commits, use a body:
    fix: unify score submission, fix TGScore type drift, fix playedBy semantics
    
    - Score.submit/score/set.ts/score-inject.ts now share one code path
    - TGScore consolidated to single canonical type
    - playedBy now correctly identifies the actual player on borrowed characters
    - Attendance.allSubmitted matches against playedBy (borrower) not just userKey
    

Step 2 — Merge to prod

cd /opt/docker/tg-bot-ts
git fetch origin
git merge origin/dev
docker compose up -d --build
docker compose restart

Step 3 — Run maintenance scripts (ALWAYS after merge)

python3 scripts/migrate-stats-shape.py /opt/docker/tg-bot-ts/data
python3 scripts/fix-class-keys.py /opt/docker/tg-bot-ts/data
python3 scripts/migrate-history-shape.py /opt/docker/tg-bot-ts/data

These are safe to re-run (idempotent). The class-key script is especially important — see the Known Bug note below. migrate-history-shape.py (added 2026-07-31) backfills tg-history/*.json files that only have a scores array — caused by Score.submit not writing the full result shape on a file's first write; the code path is now fixed, this just repairs files created before the fix. Found 50 affected files in dev alone, so prod almost certainly needs this run too.


Step 4 — Verify prod is healthy

docker logs tg-bot-ts --tail 50 2>&1
# or via alias:
tg-prod-logs

Look for: no TypeScript compile errors, no unhandled exceptions on startup, "Bot ready." in the logs, poll state restored correctly if a poll was active.


Step 5 — Post changelog and announcements (if applicable)

/tg-admin updates post version:vX.X.X
/tg-admin announcement post id:XXX-announcement-id

Only post what's new since the last prod deploy — don't re-post already-posted versions.


Known Bug — Class object serialization (recurring, must run fix-class-keys.py every merge)

Files are still being written with the UNSERIALIZED CharacterClass object shape instead of the plain ClassKey string. Example of the broken shape:

"characterClass": {
  "key": "DM",
  "name": "Dark Mage",
  "shortName": "DM"
}

Expected shape (everywhere in wrank.json and tg-history/*.json):

"class": "DM"

This causes class emojis to silently disappear from Leaderboard/Result embeds. scripts/fix-class-keys.py normalizes these on every run — run it after EVERY merge until the systemic fix (a proper serializeCharacter/hydrateCharacter pair at every read/write boundary) is implemented.

The systemic fix is tracked in REFERENCE.md under PENDING items.


Quick reference — shell aliases (both stacks, defined in ~/.bashrc)

tg-dev-logs          # docker logs tg-bot-ts-dev --follow
tg-prod-logs         # docker logs tg-bot-ts --follow
tg-dev-restart       # docker compose restart (dev)
tg-prod-deploy       # fetch + merge + build + restart (prod)
tg-dev-register      # register slash commands on dev
tg-prod-register     # register slash commands on prod
tg-dev-upload-emojis
tg-prod-upload-emojis
tg-dev-split-emojis