Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
a1560d4
MS-0MV8BFOVB000HM0W: sync reference pack fixture to 54-column piggyba…
SorraTheOrc Oct 14, 2026
dc4ec0c
MS-0MV8KQQQ90044CM5: sync reference pack fixture to 55-column options…
SorraTheOrc Oct 15, 2026
a1de871
CG-0MVD0IZDR008921Q: engine-sync script + scaffold engine:sync/verify…
Oct 17, 2026
ed801cd
CG-0MVD0IZDR008921Q: document engine-sync/verify in generated game re…
Oct 17, 2026
e4d0e10
CG-0MVD0IZDR008921Q: correct engine-sync.mjs header (submodule-invoke…
Oct 17, 2026
49705fc
CG-0MVFU3JTN00841OR: restore engine dev build/test green
SorraTheOrc Oct 20, 2026
41f8695
CG-0MVFQ6QOZ003FVO4: document The Rising ToneForge SFX in SFX_CONVENT…
SorraTheOrc Oct 20, 2026
5f419f7
MS-0MVFM9YNN008WYZO: generic story-line module in core
SorraTheOrc Oct 20, 2026
c6b1bc8
MS-0MVFMA2XD002Z0A5: Gym storyline demo scene
SorraTheOrc Oct 20, 2026
fab1ce2
MS-0MVFMA9EW001MIQR: document the generic story-line system
SorraTheOrc Oct 20, 2026
2709804
MS-0MV8PDNDT0033TH8: add ToneForge factories for the four income/fanf…
SorraTheOrc Oct 21, 2026
ac502d1
CG-0MVGF2QE9008NA5R: Implementation complete
SorraTheOrc Oct 22, 2026
64063ea
CG-0MVI048QU000UF0F: Implementation complete
SorraTheOrc Oct 22, 2026
b422437
CG-0MVI04A5Z008HVJA: Implementation complete
SorraTheOrc Oct 23, 2026
f8f2610
CG-0MVI04BLE0099ZP9: Implementation complete
SorraTheOrc Oct 23, 2026
8fa2c19
CG-0MVI04D640023PDI: Implementation complete
SorraTheOrc Oct 23, 2026
58d4e12
CG-0MVI04VKX009VPVD: Implementation complete
SorraTheOrc Oct 23, 2026
fc9fa5f
CG-0MVI04WZ8005SD28: Implementation complete
SorraTheOrc Oct 23, 2026
50b545e
CG-0MVKNC9MY006ULES: extract Gym storyline demo pure logic and unit-t…
SorraTheOrc Oct 23, 2026
c331526
MS-0MVLINW3J009RWTO: add shared load-tolerant waitForCondition helper
SorraTheOrc Oct 23, 2026
9cee53c
CG-0MVHZ2KE40011Z0S: generalise the story-line content and authoring …
SorraTheOrc Oct 24, 2026
6d8d73c
CG-0MVHZ2KE40011Z0S: ship committed Gym content/artefacts outside the…
SorraTheOrc Oct 24, 2026
b35f1d0
CG-0MVL21CVM003VK5H: Implementation complete
SorraTheOrc Oct 24, 2026
01d6bcc
CG-0MVHZ2LS3008ATY9: Implementation complete
SorraTheOrc Oct 24, 2026
d907af9
CG-0MVHZ2N2X0082OW7: Implementation complete
SorraTheOrc Oct 24, 2026
da2a4e6
CG-0MVHZ2OEY001S37L: Implementation complete
SorraTheOrc Oct 24, 2026
9ee194e
CG-0MVHZ2PVT0072YYK: Implementation complete
SorraTheOrc Oct 24, 2026
f976266
CG-0MVHZ2RBJ004O0VD: Implementation complete
SorraTheOrc Oct 25, 2026
1c9900a
CG-0MVHZ2SNP001Z5QQ: document the story-line authoring seams and visu…
SorraTheOrc Oct 25, 2026
40f83b9
CG-0MVO268500071BPI: engine:sync writes the pin; verify tells lag fro…
SorraTheOrc Oct 26, 2026
7afa001
CG-0MVPWPWLA008FTDJ: scaffold template emits resolve.dedupe guard
SorraTheOrc Oct 27, 2026
0409c1e
CG-0MVNDK56G007C1U7: Implementation complete
SorraTheOrc Oct 27, 2026
34e0ab6
CG-0MVPXFHBZ004LGEB: illegal-move routine explains rejections with a …
SorraTheOrc Oct 27, 2026
19f30ac
CG-0MVRAT58G002RYRL: Implementation complete
SorraTheOrc Oct 28, 2026
193f947
CG-0MVQQ2M8E003FQMZ: Implementation complete
SorraTheOrc Oct 28, 2026
f5c0a1b
CG-0MVSIB5LH0069LB3: Implementation complete
SorraTheOrc Oct 28, 2026
0cdeac7
CG-0MVGF2QE9008NA5R: Implementation complete
SorraTheOrc Oct 29, 2026
3ac4259
Bump version to v0.1.22
SorraTheOrc Oct 29, 2026
935e8d0
Update CHANGELOG.md for v0.1.22
SorraTheOrc Oct 29, 2026
897d3c3
Merge origin/dev into main (automated)
SorraTheOrc Oct 29, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions .pi/skills_extensions/test/SKILL_PREFIX.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,13 @@ Every typed Vitest command runs through `scripts/vitest-run-with-retry.ts`,
which:

- retries once on Vitest's transient contention-induced failures (worker RPC
timeout / browser WebSocket drop) when either every test file actually
timeout, browser WebSocket drop, or a Vite dev-server module fetch failure)
when either every test file actually
passed **or** the reported failures are attributable solely to the transient
signature (the failed-file variant; CG-0MUIMM28K001W88F);
signature (the failed-file variant; CG-0MUIMM28K001W88F). Acceptance after
both attempts is restricted to the two original signatures: module fetch is
retry-only, so a deterministic module-resolution regression still surfaces
(CG-0MVNDK56G007C1U7);
- bounds each attempt with a wall-clock timeout and exits `124` with a
`[hang-timeout]` diagnostic on a true hang (hangs are never retried); and
- emits a final `[vitest-runner] attempts=N status=S outcome=…` line as the
Expand Down
8 changes: 6 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ npm run preview # Serve production build locally (binds to all interfaces,
npm run setup:distribution -- --dir .. # Clone core + sibling game repos (full distribution)
GAMES_CONFIG=full npm run dev # Run all games + Gym (after setup:distribution)
npm run monte-carlo # Run Main Street Monte Carlo harness via vite-node (JSON + CSV; needs the tce-main-street sibling)
npm run storylines:validate # Validate story-line content through the content adapter (default: Gym)
npm run storylines:graph # Regenerate the committed manifest/Mermaid artefacts (-- --check to guard drift)
npm run storylines:author # Transactional content edits (add-card / update-card; --dry-run supported)
npm run storylines:editor # Story-line editor: viewer + guided editing (local dev tool; -- --content/--adapter)
npm run tf:generate # Generate ToneForge audio artifacts into build/tf-synths/
npm run build:electron # Electron-mode Vite build (relative base, file://-safe) for the desktop launcher
npm run start:electron # Build + launch the Electron desktop app locally
Expand Down Expand Up @@ -111,7 +115,7 @@ Rules of thumb:
2. **Non-tutorial browser tests** (`--project browser`, headless Chromium) — Phaser UI/rendering tests in `tests/**/*.browser.test.ts`. Phaser needs a real browser (WebGL/Canvas) and cannot run under Node/JSDOM.
3. **Tutorial E2E tests** (`scripts/run-tutorial-tests.sh`) — Main Street tutorial flows in `tests/e2e/main-street-tutorial-e2e-part{1-6}.browser.test.ts`, each part in its own browser instance to avoid Phaser 4 canvas/GPU context exhaustion. These are Main Street-owned: in a game-free core checkout (no `tce-main-street` sibling) the runner skips the absent parts and the projects set `passWithNoTests`, so the core suite stays green.

The unit and browser stages run through `scripts/vitest-run-with-retry.ts`, which retries once on Vitest's transient contention-induced failures (worker RPC timeout, browser WebSocket drop) when either every file actually passed **or** the reported failures are attributable solely to the transient signature (the failed-file variant; CG-0MUIMM28K001W88F). It accepts the run as green if the retry is also a pure transient failure (no genuine failure to mask; CG-0MUF0LU4X006IXXU), and bounds every attempt with a wall-clock timeout (exit 124 `[hang-timeout]` diagnostic on a genuine hang — never retried; see CG-0MT08R2QR0070F3N). A `replay-e2e` project (`tests/e2e/replay-*.test.ts`) is also defined for Playwright-driven replay checks. See `docs/DEVELOPER.md#testing` for the full project table, CPU-contention mitigations, and guidance on writing unit and browser tests.
The unit and browser stages run through `scripts/vitest-run-with-retry.ts`, which retries once on Vitest's transient contention-induced failures (worker RPC timeout, browser WebSocket drop, or a Vite dev-server module fetch failure — `Failed to fetch dynamically imported module`) when either every file actually passed **or** the reported failures are attributable solely to the transient signature (the failed-file variant; CG-0MUIMM28K001W88F). It accepts the run as green if the retry is also a pure transient failure of one of the two original signatures (no genuine failure to mask; CG-0MUF0LU4X006IXXU) — the module-fetch signature is deliberately **retry-only**, because a genuine module-resolution regression is deterministic and must surface (CG-0MVNDK56G007C1U7) — and bounds every attempt with a wall-clock timeout (exit 124 `[hang-timeout]` diagnostic on a genuine hang — never retried; see CG-0MT08R2QR0070F3N). Those two stages also opt into the runner's **project-coverage gate** (`--expect-project-coverage`, CG-0MVL21CVM003VK5H): before the run the runner derives the expected test-file set from a collection-only `vitest list --filesOnly --json` over the same project, captures the files each attempt actually executed, and fails the stage if the sets differ — so a run that silently dropped part of the suite can never be accepted as green, and a pre-flight collection failure fails closed (exit 2). `--expected-file <path>` (repeatable) pins an explicit expected set. Smoke/dev/tutorial stages and every `/skill:test --type` command keep the gate **off**. A `replay-e2e` project (`tests/e2e/replay-*.test.ts`) is also defined for Playwright-driven replay checks. See `docs/DEVELOPER.md#testing` for the full project table, CPU-contention mitigations, and guidance on writing unit and browser tests.

- **During implementation** — prefer targeted runs for fast feedback (seconds, not minutes):
- Unit: `npx vitest run --project unit tests/<game>/` or `npx vitest run --project unit tests/<game>/<name>.test.ts`
Expand Down Expand Up @@ -341,7 +345,7 @@ Use `SaveLoadStore`, `serializeWithVersion()`, and `deserializeWithVersion()` fr

### 8. Event-Driven Audio and Visual Feedback

**Requirement:** Every player **and** AI action that uses a core engine animation/feedback helper — `dealCard`, `discardCard`, `flipCard`, `placeCard`, `moveGameObject`, `shakeIllegalMove`, `popTextOrIcon`, and any future helpers — **must** be rendered with the corresponding animation and wired with a sound effect (SFX), so the action is both animated and audible. Satisfy both via each helper's `soundManager` + `sfx` (`start`/`move`/`end`) parameters, or an equivalent event-driven `GameEventEmitter`/`SoundManager` mapping. SFX keys must follow the shared convention — `COMMON_SFX_KEYS` from `src/core-engine/SoundManager.ts` with the `sfx-` prefix per `docs/SFX_CONVENTION.md`; no game-scoped string literals. (`shakeIllegalMove` plays `COMMON_SFX_KEYS.ILLEGAL_MOVE` automatically; `popTextOrIcon()` is the lightweight score/notification popup.)
**Requirement:** Every player **and** AI action that uses a core engine animation/feedback helper — `dealCard`, `discardCard`, `flipCard`, `placeCard`, `moveGameObject`, `shakeIllegalMove`, `popTextOrIcon`, and any future helpers — **must** be rendered with the corresponding animation and wired with a sound effect (SFX), so the action is both animated and audible. Satisfy both via each helper's `soundManager` + `sfx` (`start`/`move`/`end`) parameters, or an equivalent event-driven `GameEventEmitter`/`SoundManager` mapping. SFX keys must follow the shared convention — `COMMON_SFX_KEYS` from `src/core-engine/SoundManager.ts` with the `sfx-` prefix per `docs/SFX_CONVENTION.md`; no game-scoped string literals. (`shakeIllegalMove` plays `COMMON_SFX_KEYS.ILLEGAL_MOVE` automatically and, when passed a `reason` — normally the rules layer's `LegalityResult.reason` — also renders the shared transient reason toast, so a refused move is explained as well as animated (`docs/ui-animations.md` → shakeIllegalMove); `popTextOrIcon()` is the lightweight score/notification popup.)

**AI actions:** AI turns must be animated with a brief delay so the player can see and hear what the AI did (e.g. card placement / row take). Coloretto is the in-repo precedent — `../tce-coloretto/src/scenes/ColorettoScene.ts` runs AI turns via `time.delayedCall` (750ms, 150ms under reduced motion) then executes the AI's action through the same animated/sounded path as a human turn.

Expand Down
23 changes: 23 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,28 @@
# Changelog

## v0.1.22 (2026-10-29)
> **Release focus:** This release focuses on strengthening the shared engine and tooling behind the games, with more reliable CI testing, automatic engine syncing, consistent card actions, and custom event logging. It also expands branching story choices with coin and reputation requirements, adds on-screen reasons for rejected moves, and gives each game its own version number.
### Features
- CI test runs now fail loudly if any test files are silently skipped, so broken code can't slip through as a false pass. (CG-0MVL21CVM003VK5H)
- Branching story choices are now powered by a shared system, paving the way for richer narratives. (CG-0MVH2H67H002M27B)
- Engine updates now stay in sync automatically, so releases no longer fail or need manual fixes. (CG-0MVO268500071BPI)
- Card actions now behave more consistently across all games, reducing bugs and glitches. (CG-0MTXDWHDT009Q2IU)
- Games can now add their own custom events, and every event is automatically logged for debugging. (CG-0MVRAT58G002RYRL)
- Rejected moves now show a brief on-screen reason so you know why a move was refused. (CG-0MVPXFHBZ004LGEB)
- Game updates now stay in sync with engine improvements for a smoother experience. (CG-0MVD0IZDR008921Q)
- The Rising's face-off sounds are now documented so future games can reuse them consistently. (CG-0MVFQ6QOZ003FVO4)
- Browser tests now retry once when a loaded machine drops a module fetch, so test gates reflect your code, not CPU load. (CG-0MVNDK56G007C1U7)
- New game repos now keep a single copy of Phaser and Tone, preventing mysterious startup crashes. (CG-0MVPWPWLA008FTDJ)
- Story choices can now require coins or reputation, show extra effects, and branch based on your status. (CG-0MVI013DU000KEAB)
### Bug Fixes
- New game projects now save transcripts correctly, and dev consoles no longer spam warnings. (CG-0MVSIB5LH0069LB3)
- Illegal-move toasts no longer break game tests, so your suite runs clean again. (CG-0MVQQ2M8E003FQMZ)
- Fixed internal build and test issues so future game updates can ship smoothly. (CG-0MVFU3JTN00841OR)
- Each game now shows its own version number, separate from the engine's. (CG-0MVGF2QE9008NA5R)
### Other
- Storylines work exactly as before, with the Gym demo and all Main Street arcs verified. (CG-0MVHY82PQ004Q3B9)
> [Play the alpha release](https://thewizardscode.github.io/Tableau-Card-Engine/). Provide feedback in [Discord](https://discord.gg/gUKQTFkzQ4)

## v0.1.21 (2026-10-15)
> **Release focus:** This release introduces a new Irish history card game while overhauling how card packs work, letting third-party packs carry their own artwork and be added as unlockable DLC. It also improves audio defaults, publishing automation, and developer tooling, including a more reliable dev server and a single up-to-date guide for creating new games.
### Features
Expand Down
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,18 @@ into the game's `./core` submodule via `CORE_ROOT`. There is no `src` symlink:
the aliases replace the F4 compatibility symlinks. See the
[layout decision record](docs/dev/per-game-src-layout-decision.md).

#### Per-game version policy

A game repo owns its own version — it is never the engine's version. The
scaffold seeds a brand-new game repo at `0.1.0`, **preserves** the `version`
already in an existing repo's `package.json` when re-scaffolding (so an existing
game is never renumbered), accepts an explicit `--version <semver>` override,
and never copies the core's `version`. A release cut inside `tce-<game>` bumps
only that game's `package.json`, so game and engine releases proceed at
independent cadences and the version label on game screens follows the game
build. See
[Per-game version policy](docs/dev/creating-a-new-game.md#per-game-version-policy).

### Repository layout (this checkout)

```
Expand Down
Loading
Loading