bug-postmortem

  1. Vanished letters, lingering words

    Two independent PvP bugs on the same day: Norwegian letters missing from what the opponent sees, and a crashed word that refused to leave the screen.

  2. A greedy regex that ate the leading major version digit

    A greedy wildcard in version string extraction stripped leading digits from major version numbers, causing pnpm 11.19.0 to be parsed as 1.19.0.

  3. Breaking a self-referential devcontainer script loop

    Invoking pnpm inside a container startup script re-triggered the pnpm binary wrapper itself. Guarding execution with environment flags broke the infinite loop.

  4. Deriving help text point values from the game engine

    Hardcoded point strings in UI translation dictionaries drifted when fruit values changed. Deriving help copy directly from EDIBLE_POINTS enforced a single source of truth.

  5. Rejected was not final

    A closed draft becomes published after all, exposing one missing transition in the blog registry's state model.

  6. The lock arrived late

    Seventeen blog-registry commits expose the small race between opening a draft and publishing its concurrency lock.

  7. One snake, two renderers

    The live board and canvas share image learn one shared rule for drawing a connected snake without merging a tight coil into a blob.

  8. The fourth status line

    A stale three-tool test turned pnpm support into a devcontainer startup failure, and the repair had to model the new update path properly.

  9. Silence was two different bugs

    One missing leaderboard entry exposed both silent server rejections and a client race that could erase a finished game without making a request.

  10. A directory is not a file type

    Narrowing CI's blog-only skip to blog/** looked complete. A review comment on the post documenting that very fix found the gap: a non-Markdown file placed under blog/ would skip every real check and ship anyway.