Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
c8649c7
CG-0MS0J0Y6G009WXMF: Buy business card goes to hand instead of direct…
Jul 29, 2026
08ea22c
CG-0MS0J0Y6G009WXMF: Fix T9 tutorial step, update E2E tests, add plac…
Jul 29, 2026
814c273
CG-0MS0J0Y6G009WXMF: Fix hand card off-screen and action buttons hidd…
Jul 29, 2026
aa141cf
CG-0MS0J0Y6G009WXMF: Fix animation jump, add placing-from-hand button…
Jul 29, 2026
d2a1135
CG-0MS0J0Y6G009WXMF: Fix empty street slots not interactive during pl…
Jul 29, 2026
4cfb2ca
Revert "CG-0MS0J0Y6G009WXMF: Fix empty street slots not interactive d…
Jul 29, 2026
c8947be
CG-0MS0J0Y6G009WXMF: Fix empty street slots not interactive during pl…
Jul 30, 2026
add35e5
CG-0MS0J0Y6G009WXMF: Migrate business hand cards to core HandView wit…
Jul 30, 2026
8b9f2a9
CG-0MS7EP4S0007F7M1: Fix hand cards scrolling off left side with 2 cards
Jul 30, 2026
df4e78c
CG-0MRF170G70080OSN: Round score display to nearest whole number
Jul 30, 2026
3a6f1eb
CG-0MS7EPE0I001R6PI: Main Street: Hand cards not clickable in market …
Jul 30, 2026
58d1eef
CG-0MRF13LRL004UB9J: Save card setup with save games
Jul 30, 2026
b9d1eea
CG-0MROYZ9G1004LZNZ: Add SLL layout requirement to Example Games section
Jul 30, 2026
ec20feb
CG-0MROYZ9G1004LZNZ: Add SLL layout requirement to Example Games section
Jul 30, 2026
86406b1
CG-0MRPE1D1B003JHAF: Add Game Architecture Best Practices section to …
Jul 30, 2026
d59696d
CG-0MRGW6RQQ005NJHG: Fix missing card selection and illegal highlight…
Jul 31, 2026
6015555
CG-0MRI9EPGM005NPL8: Integrate CardMemoryTracker into Lost Cities AI
Jul 31, 2026
4dfdc38
fix(gym): multi-bar registry in GymSceneBase keeps all button bars (C…
Jul 31, 2026
ef28501
docs(gym): document multi-bar initButtonBar contract in GymSceneBase …
Jul 31, 2026
6edf35d
test: align stale browser tests with intentional Main Street / Settin…
Jul 31, 2026
19c3fa2
CG-0MRGW6RQQ005NJHG: Address audit gaps — rotated tint overlays, drag…
Jul 31, 2026
0647980
CG-0MRGW6RQQ005NJHG: Address audit gaps (rotated tint overlays, drag …
Jul 31, 2026
62e2702
fix(ui): persist card style preference to localStorage (CG-0MS83ES5U0…
Jul 31, 2026
f2a8207
fix(gym): consolidate GymHandPileScene buttons into two rows (CG-0MRG…
Jul 31, 2026
aa10e13
feat(gym): selected card raises along its rotation with adjustable di…
Jul 31, 2026
a7406ab
fix(gym): selection highlight raises with the card; raise slider max …
Jul 31, 2026
151f4c5
CG-0MRF170G70080OSN: Round coin balance displays to nearest whole number
Jul 31, 2026
7221902
fix(gym): Cancel Move returns card to base hand position, not raised …
Jul 31, 2026
6bccf2e
chore(tests): remove 32 low-value test files and strip dead assertion…
Jul 31, 2026
0b194b4
chore(docs): add SLL layout requirement to AGENTS.md (CG-0MROYZ9G1004…
Jul 31, 2026
6d050c6
Bump version to v0.1.9
Jul 31, 2026
85e0955
Update CHANGELOG.md for v0.1.9
Jul 31, 2026
13361d1
Merge origin/dev into main (automated)
Jul 31, 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
193 changes: 192 additions & 1 deletion AGENTS.md

Large diffs are not rendered by default.

47 changes: 47 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,52 @@
# Changelog

## v0.1.9 (2026-07-31)
### Features
- When buying a business card that card should go into the hand (CG-0MS0J0Y6G009WXMF)
- Main Street: Hand cards not clickable in market phase (CG-0MS7EPE0I001R6PI)
- Implement: Interactive hit area in handBusinessView.renderCard (CG-0MS7MLCD40005JF8)
- Implement: onHandBusinessCardClick handler + scene wiring (CG-0MS7MLKTA008WYF3)
- Multi-bar registry in GymSceneBase (CG-0MS8TISJM00596PH)
- Save card setup with save games (CG-0MRF13LRL004UB9J)
- Integrate CardMemoryTracker into Lost Cities AI (CG-0MRI9EPGM005NPL8)
- Fix missing card selection and illegal highlights in Gym Hand and Pile Interactions scene (CG-0MRGW6RQQ005NJHG)
- Gym Hand & Pile: selected card raises along its rotation with adjustable distance slider (CG-0MS934XSL00453HF)
- Gym Hand & Pile: selection highlight raises with the card; raise slider max 180 / default 60 (CG-0MS98MXQP007OGFU)
- Gym Hand & Pile: selection highlight renders over cards to the right of the selected card (CG-0MS937FT9006273E)
### Bug Fixes
- Score should be rounded to nearest whole number (CG-0MRF170G70080OSN)
- [test-failure] gym-handpile-cancel.browser.test.ts — failing test (CG-0MS99JZBK001ZIBM)
- Hand cards scroll off left side of screen with two cards (CG-0MS7EP4S0007F7M1)
- Gym Hand & Pile: setup/interaction buttons no longer visible (CG-0MS8T34T8004ZVEM)
- [test-failure] tests/ui/SettingsPanelTooltips.browser.test.ts — failing test (CG-0MS8V1L3H003LYIX)
- [test-failure] tests/main-street/MainStreetScene.browser.test.ts :: only materializes purchased cards at destination after transfer animation completes — failing test (CG-0MS8V1TRB007IE1B)
- [test-failure] tests/main-street/MainStreetZOrder.browser.test.ts :: gameplay containers use default depth (0) — failing test (CG-0MS8V1UEX008X8YR)
- [test-failure] tests/main-street/TutorialOverlayManager.browser.test.ts :: investmentsRow highlight (T9) — failing test (CG-0MS8V1V300080WPA)
- Card style preference is not persisted (CG-0MRO5W3CL000CNGO)
- [test-failure] GymHandPileScene Cancel Move after completed move also returns card to hand — failing test (CG-0MS8UILM40076ISR)
- [test-failure] GymHandPileScene Card can be moved again after cancelling previous move — failing test (CG-0MS8UIMCA008MI7P)
- [test-failure] MainStreetScene only materializes purchased cards at destination after transfer animation completes (desktop + narrow viewports) — failing test (CG-0MS8UIOL9002KVTH)
- [test-failure] Main Street container z-order gameplay containers use default depth (0) — failing test (CG-0MS8UIPER008BI6Q)
- [test-failure] TutorialOverlayManager investmentsRow highlight (T9) covers the investments row for upgrade concept — failing test (CG-0MS8UIQ56000AWGC)
- [test-failure] SettingsPanel tooltips toggle conditional display when hasTooltips is false still displays the Reduced Motion label — failing test (CG-0MS8UJGJW001IOL3)
- [test-failure] SettingsPanel tooltips toggle conditional display when hasTooltips is false still displays the End Turn Key label — failing test (CG-0MS8UJHAR009KBBR)
- [test-failure] SettingsPanel tooltips toggle conditional display when hasTooltips is omitted (defaults to true) displays the Tooltips label by default — failing test (CG-0MS8UJJGT008AQ53)
- Fix getCardDesign() default parameter bug causing persistence failure (CG-0MS83ES5U00853Y4)
- [test-failure] GymHandPileScene Cancel Move returns moved card to original hand position — failing test (CG-0MS8UH8G8009JUW0)
### Other
- Test: Hand business card interactivity in market phase (CG-0MS7ML1W7002DZKB)
- Update GymSceneBase button-bar contract test (CG-0MS8TIRWC006JOX5)
- Button-visibility regression browser test (5 scenes) (CG-0MS8TIS7G0050ILQ)
- Update button-bar docs for multi-bar semantics (CG-0MS8TISUZ006D443)
- Embed CSV data in serialized state (CG-0MS7NH2E50063LAP)
- CSV mismatch resolution and legacy save handling (CG-0MS7NHCTZ009U12O)
- Preserve market state on checkpoint resume (CG-0MS7NHLRT008LYMI)
- Documentation updates and final verification (CG-0MS7NHU1H0014Z81)
- Integrate CardMemoryTracker into game AI systems (CG-0MRI8T1WO003GL9W)
- Update AGENTS.md with game architecture best practices drawn from Gym scenes (CG-0MRPE1D1B003JHAF)
- Add browser-level card design persistence test (CG-0MS83F3K4004JZ0U)
- Update documentation for card design persistence fix (CG-0MS83FDWP005UENP)

## v0.1.8 (2026-07-29)
### Features
- E-1: Add per-run card ownership tracking to MonteCarloRunSummary (CG-0MRYZT4ID008PFFT)
Expand Down
20 changes: 13 additions & 7 deletions docs/DEVELOPER.md
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ example-games/
│ ├── GymRouterScene.ts Landing page with navigation cards
│ ├── GymSceneBase.ts Shared base class for all Gym scenes
│ ├── GymDeckRngScene.ts Deck lifecycle & seeded RNG demo
│ ├── GymHandPileScene.ts Hand/pile interaction demo (bottom-anchored hand arc + live radius slider)
│ ├── GymHandPileScene.ts Hand/pile interaction demo (bottom-anchored hand arc + live arc/spacing/rotation/raise sliders)
│ ├── GymOverlayUiScene.ts Overlay & UI configuration demo
│ ├── GymUndoRedoScene.ts Undo/redo workflow demo
│ ├── GymTranscriptScene.ts Transcript recording demo
Expand Down Expand Up @@ -364,7 +364,6 @@ public/assets/
└── CREDITS.md Asset attribution

tests/
├── smoke.test.ts Toolchain smoke test
├── fixtures/transcripts/ Fixture transcripts for replay tests (one per game)
├── ai/ AiPlayer, pickRandom, pickBest, barrel export tests
├── card-system/ Card, Deck, Pile unit tests
Expand Down Expand Up @@ -2002,15 +2001,22 @@ bar.addButton('[ Custom ]', () => { /* ... */ }, {

#### Integration with GymSceneBase

Gym scenes call `initButtonBar()` to create a `GymButtonBar` instance and store it as `this.buttonBar`:
Gym scenes call `initButtonBar()` once per button row/section. Each call creates a **new** `GymButtonBar` at the given Y position and appends it to an internal registry — previously created bars are **kept** (no destroy-and-recreate). `this.buttonBar` always points at the most recently created bar:

```typescript
protected initButtonBar(y?: number): void {
this.buttonBar = new GymButtonBar(this, { y: y ?? 60 });
}
// Controls row 1
this.initButtonBar(60);
this.buttonBar!.addButton('[ Draw ]', () => this.drawToHand(), { zone: 'center' });
this.buttonBar!.addButton('[ Discard ]', () => this.discardSelected(), { zone: 'center' });

// Controls row 2 — a SECOND bar; row 1 is NOT destroyed
this.initButtonBar(112);
this.buttonBar!.addButton('[ Disable Drag ]', () => this.toggleDrag(), { zone: 'center' });
```

Scenes with buttons at multiple Y positions create multiple `GymButtonBar` instances at different Y values.
`initButtonBar(y, opts?)` returns the created bar (also exposed as `this.buttonBar`), and accepts the same `GymButtonBarConfig` overrides as the `GymButtonBar` constructor (e.g. `{ zone: 'left' }`, `{ rowSpacing: 30 }`).

All registered bars are destroyed automatically when the scene shuts down or is destroyed, so scene restarts are leak-free. `GymSceneBase` wires this cleanup to the Phaser scene `shutdown`/`destroy` events on the first `initButtonBar()` call.

The `GymButtonBar` is exported from the UI barrel (`src/ui/index.ts`) and can be used by any scene, not just Gym scenes.

Expand Down
6 changes: 3 additions & 3 deletions docs/gym/GYM_INDEX.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,13 @@ npx vitest run --project browser tests/gym/*.browser.test.ts

| Scene | Key | Core APIs | Source | Tests |
|---|---|---|---|---|
| Deck & Seeded RNG | `GymDeckRngScene` | `createStandardDeck`, `shuffleArray`, `createSeededRng` | [`scenes/GymDeckRngScene.ts`](../../example-games/gym/scenes/GymDeckRngScene.ts) | [`GymDeckRng.test.ts`](../../tests/gym/GymDeckRng.test.ts) |
| Hand & Pile Interactions | `GymHandPileScene` | `Pile`, `createStandardDeck`, `createSeededRng`, `HandView.setMaxRotationDegrees` | [`scenes/GymHandPileScene.ts`](../../example-games/gym/scenes/GymHandPileScene.ts) | [`GymRegistry.test.ts`](../../tests/gym/GymRegistry.test.ts), [`GymHandPileRotation.test.ts`](../../tests/gym/GymHandPileRotation.test.ts) |
| Deck & Seeded RNG | `GymDeckRngScene` | `createStandardDeck`, `shuffleArray`, `createSeededRng` | [`scenes/GymDeckRngScene.ts`](../../example-games/gym/scenes/GymDeckRngScene.ts) | [`GymDeckRngGrid.smoke.browser.test.ts`](../../tests/gym/GymDeckRngGrid.smoke.browser.test.ts), [`GymHeadlessDeterminism.test.ts`](../../tests/gym/GymHeadlessDeterminism.test.ts) |
| Hand & Pile Interactions | `GymHandPileScene` | `Pile`, `createStandardDeck`, `createSeededRng`, `HandView.setMaxRotationDegrees`, `HandView.setSelectionLift` | [`scenes/GymHandPileScene.ts`](../../example-games/gym/scenes/GymHandPileScene.ts) | [`GymRegistry.test.ts`](../../tests/gym/GymRegistry.test.ts), [`GymHandPile.test.ts`](../../tests/gym/GymHandPile.test.ts), [`handPileScene.animation.test.ts`](../../tests/gym/handPileScene.animation.test.ts) |
| Overlay & UI Config | `GymOverlayUiScene` | `createOverlayBackground`, `dismissOverlay` | [`scenes/GymOverlayUiScene.ts`](../../example-games/gym/scenes/GymOverlayUiScene.ts) | [`GymSceneSmoke.browser.test.ts`](../../tests/gym/GymSceneSmoke.browser.test.ts) |
| Undo / Redo | `GymUndoRedoScene` | `UndoRedoManager`, `CompoundCommand` | [`scenes/GymUndoRedoScene.ts`](../../example-games/gym/scenes/GymUndoRedoScene.ts) | [`GymUndoRedo.test.ts`](../../tests/gym/GymUndoRedo.test.ts) |
| Transcript Recording | `GymTranscriptScene` | `TranscriptRecorderBase`, `createSeededRng` | [`scenes/GymTranscriptScene.ts`](../../example-games/gym/scenes/GymTranscriptScene.ts) | [`GymTranscript.test.ts`](../../tests/gym/GymTranscript.test.ts) |
| Save / Load State | `GymSaveLoadScene` | `SaveLoadStore`, `serializeWithVersion`, `deserializeWithVersion`, `RenderTexture.saveTexture()`, `RenderTexture.snapshot()`, snapshot persistence via base64 data URL | [`scenes/GymSaveLoadScene.ts`](../../example-games/gym/scenes/GymSaveLoadScene.ts) | [`GymSaveLoad.test.ts`](../../tests/gym/GymSaveLoad.test.ts) |
| Audio & Feedback Config | `GymAudioFeedbackScene` | `SoundManager`, `GameEventEmitter`, `EventSoundMapping` | [`scenes/GymAudioFeedbackScene.ts`](../../example-games/gym/scenes/GymAudioFeedbackScene.ts) | [`GymAudioFeedback.test.ts`](../../tests/gym/GymAudioFeedback.test.ts) |
| Audio & Feedback Config | `GymAudioFeedbackScene` | `SoundManager`, `GameEventEmitter`, `EventSoundMapping` | [`scenes/GymAudioFeedbackScene.ts`](../../example-games/gym/scenes/GymAudioFeedbackScene.ts) | [`GymHeadlessDeterminism.test.ts`](../../tests/gym/GymHeadlessDeterminism.test.ts) |
| Shader & Blend Spike | `GymGraphicsShaderSpikeScene` | Sprite tinting, blend modes, shader feasibility | [`scenes/GymGraphicsShaderSpikeScene.ts`](../../example-games/gym/scenes/GymGraphicsShaderSpikeScene.ts) | [`GymSceneSmoke.browser.test.ts`](../../tests/gym/GymSceneSmoke.browser.test.ts) |
| Lighting Spike | `GymGraphicsLightingSpikeScene` | Point light, shadow evaluation, WebGL fallback | [`scenes/GymGraphicsLightingSpikeScene.ts`](../../example-games/gym/scenes/GymGraphicsLightingSpikeScene.ts) | [`GymSceneSmoke.browser.test.ts`](../../tests/gym/GymSceneSmoke.browser.test.ts) |
| Screen Layout Language (SLL) | `GymSllScene` | `validateScreenLayoutDocument`, `parseScreenLayoutDocument`, `normalizedToPixels`, `getZoneRect`, `anchorPoint` | [`scenes/GymSllScene.ts`](../../example-games/gym/scenes/GymSllScene.ts) | [`GymSllLayout.test.ts`](../../tests/gym/GymSllLayout.test.ts), [`GymSllScene.browser.test.ts`](../../tests/gym/GymSllScene.browser.test.ts) |
Expand Down
2 changes: 1 addition & 1 deletion docs/main-street/prd-multi-use-card-economy.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ totalHandSynergy = Σ perBusinessBonus for each (handCard, tableauBusiness) syne

| Action | Cost/Value | Destination |
|--------|-----------|-------------|
| Place from hand to tableau | 80% of purchase cost (coins deducted) | Tableau slot |
| Place from hand to tableau | Free (no coin deduction) | Tableau slot |
| Sell from hand | 75% of purchase value (coins credited) | Discard pile |
| Sell from tableau | 75% of purchase value (coins credited) | Discard pile (slot freed) |

Expand Down
2 changes: 1 addition & 1 deletion example-games/gym/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Open `http://localhost:3000` and select **Gym** from the game selector. From the
| Scene | Key | What it Demonstrates |
|---|---|---|
| Deck & Seeded RNG | `GymDeckRngScene` | Create/shuffle/draw with deterministic seeded randomness; flip and deal animations |
| Hand & Pile Interactions | `GymHandPileScene` | Move cards with deal/place/discard/move/shake animations; bottom-anchored arc hand layout with live radius and per-card rotation sliders; drop-zone highlights; flip support |
| Hand & Pile Interactions | `GymHandPileScene` | Move cards with deal/place/discard/move/shake animations; bottom-anchored arc hand layout with live radius, per-card rotation, and selection-raise sliders; drop-zone highlights; flip support |
| Overlay & UI Config | `GymOverlayUiScene` | Open/close overlays; toggle feedback intensity; GeometryMask scrollable content |
| Undo / Redo | `GymUndoRedoScene` | Execute, undo, and redo actions; pop text feedback on undo/redo |
| Transcript Recording | `GymTranscriptScene` | Record game events, inspect transcripts; pop text feedback |
Expand Down
Loading
Loading