A game you come back to has not begun

Reported by Jesse, 2026-08-30: "when you are continuing the saved game
out of that screen, do not post a message that says 'The game has
begun.' … it needs to say 'The game has resumed.'"

A restored game draws exactly like a dealt one — mid-Day, mid-phase,
with a log already several turns deep — and solitaire said nothing at
all to tell the two apart. It flashes "The game has resumed — Day 3,
Stage 7" now, on both ways back in: the setup screen's Continue saved
game, and a bare reload that restores the save.

THE SAME LINE WAS WRONG ON THE MULTIPLAYER SIDE, IN THE OTHER
DIRECTION. noteFirstFrame guards on firstFrameSeen, which is per
page-load — so re-entering a game this browser already held a seat in,
by reloading mid-game or picking it out of the lobby's list, announced
that the game had BEGUN to somebody who had been playing it for an
hour. beginRemote carries whether this is a rejoin now, and the line
reads "resumed" when it is.

Both halves are pinned, including that a brand-new game does not claim
to be a resume — an announcement that fires either way says nothing.

Stays in the unshipped v0.7.9. 878 tests pass, eleven new.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AdG46Ja2PEDBkpqiDazMoX
This commit is contained in:
Jesse.Markowitz
2026-08-30 16:10:17 -04:00
co-authored by Claude Sonnet 5
parent 788e5f2eec
commit bb1b661211
3 changed files with 79 additions and 8 deletions
+24
View File
@@ -4348,6 +4348,30 @@ describe('the solitaire setup screen', () => {
assert.match(n.search, /coltotal=0/, 'unticking the total-collision condition did not switch it off');
});
it('says the game has RESUMED, not begun, when you come back to one', async () => {
/**
* REPORTED BY JESSE 2026-08-30: "when you are continuing the saved game out of that screen, do
* not post a message that says 'The game has begun.' … it needs to say 'The game has resumed.'"
*
* A restored game draws exactly like a dealt one — mid-Day, mid-phase, log already deep — so
* nothing distinguished the two. Checked in both directions here: the wording itself, and that
* the multiplayer line which DOES say "begun" cannot be said to somebody rejoining.
*/
const save = JSON.stringify({ seed: 12345, history: [] });
const { els } = await load('', { 'station-master.save.v1': save });
assert.match(String(els.get('announce')!['textContent']), /has resumed/, 'a restored game said nothing');
assert.doesNotMatch(String(els.get('announce')!['textContent']), /has begun/, 'a restored game claimed to be new');
// A freshly dealt game must NOT claim to be resumed — the announcement has to mean something.
const fresh = await load('?hand=sixRandom');
assert.doesNotMatch(String(fresh.els.get('announce')?.['textContent'] ?? ''), /resumed/,
'a brand new game announced itself as a resume');
// And the multiplayer first-frame line is conditional now rather than always "begun".
const src = readFileSync(join(root, 'src/web/main.ts'), 'utf8');
assert.match(src, /rejoining \? 'resumed' : 'begun'/, 'rejoining a table still says the game has begun');
});
it('backing out deals nothing and puts the same game back on screen', async () => {
/**
* WHAT CANCEL USED TO BE. The dialog had a Cancel button and an Esc key, and this pinned that