import InfoBox from '../components/InfoBox.astro';
import Figure from '../components/Figure.astro';

An end-to-end test verifying best-of-day leaderboard deduplication failed deterministically on a fresh database, expecting a score of 22 and receiving 34. The test was written to ensure that when a player submits multiple attempts under the same day-scoped token, the server preserves their highest score while discarding the lower one. When the test was originally constructed, candidate Norwegian words had been posted against a local development server to find sequences with the right score relationship ([proving a score instead of guessing it](/posts/persisted-but-never-shown#proving-a-score-instead-of-guessing-it)), and those observed totals were committed as literal expectations. But running the suite against a clean database produced a persistent mismatch: the test expected 22 for the word list, but the server calculated 34.

## The path without turns

The initial suspicion pointed toward the calendar date, wondering whether the daily challenge seed had rolled over between test runs. Digging into the replay mechanics revealed a more subtle divergence. The test used short Norwegian words: `bil` (car), `bok` (book), `hus` (house), and `kake` (cake). In Norwegian, the snake's controls map cardinal directions to specific letters, and none of those words contain any direction letters. As a result, the snake makes zero turns while spelling them out, advancing across the board in an unswerving straight line from its starting spawn point.

<InfoBox title="Straight-line word paths" variant="note">
When a word contains no direction-changing characters, the snake moves in a continuous straight line. The final score depends not only on the base letter values, but on whether that fixed trajectory happens to collide with an active bonus fruit on the board.
</InfoBox>

Whether that straight-line path picks up bonus fruit depends on where and when fruits appear on the grid. The daily challenge board layout, including its fruit spawn sequence, is generated deterministically by seeding a pseudo-random number generator with the challenge date, the language, and a server-side seed secret. By design, that server secret differs between the local devcontainer and the continuous integration pipeline, ensuring test runs do not depend on production credentials. Because the seed secrets differed, the two environments generated entirely different fruit queues for the exact same calendar day.

<Figure caption="Identical words walk different fruit queues when the server seed secret changes between dev and CI.">

```mermaid
flowchart TD
  accTitle: Environment seed divergence affecting fruit spawns
  accDescr: The challenge date and language combine with an environment seed secret. A devcontainer secret spawns fruits that miss the straight-line snake path, producing a score of 22. The CI secret spawns an early bonus fruit on the path, raising the score to 34.

  A["Challenge date + language"] --> B{"Server seed secret"}
  B -->|Local dev secret| C["Dev fruit queue<br/>(path misses fruit)"]
  B -->|CI pipeline secret| D["CI fruit queue<br/>(path hits fruit)"]
  C --> E["Score: 22<br/>(base letters only)"]
  D --> F["Score: 34<br/>(base letters + fruit)"]

  class E muted
  class F accent
```

</Figure>

In the local devcontainer, the straight-line walk of `['bil', 'bok']` never crossed a bonus fruit, yielding 22 points based purely on letter rarity. In continuous integration, the alternate seed placed an early bonus fruit directly in the snake's path, boosting the authoritative replay score to 34. Neither number was wrong; both were the legitimate, deterministic result of running the game engine against that environment's configured seed. Hardcoding 22 had coupled the test's assertions to the arbitrary secret of one developer machine.

## Discovering the score at runtime

The fix replaced the hardcoded literals with runtime score discovery. Before asserting on deduplication behavior, the test now submits each candidate word sequence once under a disposable player identity to observe the authoritative score in whichever environment is running:

```typescript
const { score: husScore } = await getScoreForWordHistory(request, seed, ['hus']);
const { score: bilBokScore } = await getScoreForWordHistory(request, seed, ['bil', 'bok']);

// ... submit both under the same daily token ...

expect(matching).toHaveLength(1);
expect(matching[0].score).toBe(Math.max(husScore, bilBokScore));
```

The test's core requirement was never that `['bil', 'bok']` equal 22, but that deduplication always keeps `Math.max(attemptA, attemptB)`. Querying the server for the ground truth allows the suite to verify the deduplication logic cleanly, regardless of which secret seeded the board or whether the fruit queue spawned an apple along the way. With environment-specific literals removed, the suite runs predictably across both local devcontainers and CI runners.