Credibility pass: one conflict check, one hostile list, one set of chrome

Duplicated logic and styling that had drifted apart is unified: the
gesture-sharing check, the hostile spell list, the enchanted test, the
plan limits, and the shared button, link, field and disabled styles.
Dead plumbing is gone: the always-true implemented flag, the unread
cast length, an unreachable guard, an impossible time-stop condition,
the unused sequence formatter and utility class, the template
placeholder. The counter-spell tests now put a counter-spell in front
of a spell, the test helpers live in one file, and the resolver's
sections are numbered in order. The deploy script's cache headers now
do what its comment says, and the README describes the screen rather
than listing features in the order they arrived.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Eric WagonerandClaude Fable 5.1 committed 2026-09-22 16:37:54 -04:00
1 parent 527820ee95
commit 5de352db43
22 files changed
+415 -485

No files matched your search

+3 -25
View File
@@ -1,10 +1,8 @@
import { describe, expect, it } from 'vitest';
import { Duel } from './duel.svelte';
import { resolveTurn } from './resolve';
import { createGame, type GameState, type TurnInput } from './state';
import { createGame, type GameState } from './state';
import type { Gesture } from './spells';
const noop = (): TurnInput => ({ left: '-', right: '-', casts: [] });
import { play } from './test-helpers';
/** A is one gesture from a lightning bolt and has just been struck by amnesia. */
function amnesiaBeforeLightning(): GameState {
@@ -12,10 +10,7 @@ function amnesiaBeforeLightning(): GameState {
const left = 'DFFD';
const foe = '-DPP';
for (let i = 0; i < 4; i++) {
s = resolveTurn(s, {
A: { ...noop(), left: left[i] as Gesture },
B: { ...noop(), left: foe[i] as Gesture, casts: i === 3 ? [{ hand: 'left', spellId: 'amnesia' }] : [] }
});
s = play(s, { left: left[i] as Gesture }, { left: foe[i] as Gesture, casts: i === 3 ? [{ hand: 'left', spellId: 'amnesia' }] : [] });
}
expect(s.wizards.A.constraints.amnesia).toBe(true);
return s;
@@ -31,21 +26,4 @@ describe('the duel store', () => {
duel.reveal();
expect(duel.foe.hp).toBe(10);
});
it('chooses a default cast at the start of the next turn as well', () => {
let s = createGame({ A: 'You', B: 'Foe' }, 1);
// A's left hand made D-F-F-D; B's amnesia lands as A makes the fourth gesture.
const left = 'DFFD';
const foe = '-DPP';
for (let i = 0; i < 3; i++) {
s = resolveTurn(s, { A: { ...noop(), left: left[i] as Gesture }, B: { ...noop(), left: foe[i] as Gesture } });
}
const duel = new Duel(s);
duel.choose('main', 'left', 'D');
duel.choose('main', 'right', '-');
// The bot is replaced by a scripted foe for this test: resolve directly, then hand the store the result.
const next = resolveTurn(s, { A: { ...noop(), left: 'D' }, B: { ...noop(), left: 'P', casts: [{ hand: 'left', spellId: 'amnesia' }] } });
const fresh = new Duel(next);
expect(fresh.sets.main.left.spellId).toBe('lightning_bolt');
});
});