Files
L'électron rare afcab32aa7 feat(atelier): migrate simulation into atelier
Phase 4 of the V3 fusion plan. The atelier app now embeds
the real R3F 3D simulation in its right pane. P6 also
absorbed (apps/simulation removed, desktop bundle updated).

Migrated from apps/simulation/src (via git mv to preserve
history):
- scene/{Room, RoomScene, PuzzleStation, PuzzleStations,
  RtcPhone, NpcBubble} (6 files)
- puzzles/{P1Sound, P5Morse, P6Symbols, P7Coffre}
- modes/{Sandbox, Demo, Test}Mode (Tailwind classes
  replaced with inline styles since Tailwind was never
  configured in V3)
- store/simStore.ts -> stores/simStore.ts (matches
  atelier's plural convention)

Atelier wiring:
- StagePane: lazy(R3F Canvas + RoomScene) + lazy mode HUD
  selected by simStore.mode. Stale badge still consumed
  from runtimeStore.isStale (P5 will trigger).
- ConsolePane: switched mode binding from runtimeStore to
  simStore (mode is a sim concern, not editor↔stage sync).
- runtimeStore: dropped `mode` field (now in simStore).
  Kept currentIr/pendingIr/isStale/setPendingIr/
  commitPendingIr for the live-diff flow (P5).
- atelier tsconfig: types: ["@react-three/fiber"] for JSX
  intrinsics.
- @types/three added to atelier devDeps.

scenario-engine bug fixes (the 3 tests skipped in P0):
- yaml-parser now converts puzzles dict (YAML format) to
  array (TS contract) at parse time. The YAML keeps puzzles
  as a keyed dict for human readability; consumers expect
  PuzzleConfig[]. This fixes 2 tests that called
  scenario.puzzles.find/.reduce.
- getScore test realigned with engine implementation:
  fast-completion bonus applies continuously when elapsed
  is below 80% of target, so total at t=0 is base + bonus
  = 1200, not just base = 1000. The test name + body now
  documents this behaviour. (Whether engine should only
  apply the bonus on game end is a separate question for
  future engine refactor.)

Decommission (early P6 for simulation):
- git rm -r apps/simulation/
- desktop/scripts/build-frontends.sh: now iterates over
  [atelier, dashboard] and uses pnpm instead of npm
- frontend-v3/CLAUDE.md: now describes 2 apps + 3 packages
- root CLAUDE.md: Authoring line lists atelier + dashboard

Acceptance:
- pnpm typecheck: 8/8 green
- pnpm test: 9/9 (atelier:0, dashboard:5, scenario-engine:9
  ALL passing including the 3 previously skipped)
- pnpm build: 5/5 green
- Atelier production chunks: shell 76 kB, blockly 698 kB
  (lazy), three 1.25 MB (lazy), R3F scene 10 kB, mode HUDs
  ~1 kB each (lazy)

Phase 6 scope reduced to: nothing left. The "decommission +
propagation" work was absorbed into P3 (editor) and P4
(simulation + desktop bundle + CLAUDE.md). Phase 5 (live-
diff wiring) is the only remaining phase.
2026-05-02 23:54:54 +02:00

1.5 KiB

Frontend V3 (Monorepo)

pnpm + turbo monorepo. Two apps + three shared packages. Node ≥20, pnpm ≥9.

Layout

apps/
  dashboard/         # Live game-master dashboard (analytics, control)
  atelier/           # Scratch-like authoring studio (Blockly editor + 3D stage)
packages/
  scenario-engine/   # Runtime 3 IR + execution (shared core)
  shared/            # Cross-app utilities, types, constants
  ui/                # Shared component library

Commands

pnpm install            # Bootstrap workspace
pnpm dev                # turbo run dev (all apps)
pnpm --filter dashboard dev   # Single app
pnpm build              # turbo run build
pnpm test               # turbo run test
pnpm typecheck          # turbo run typecheck
pnpm lint               # turbo run lint

Patterns

  • scenario-engine is the canonical TS Runtime 3 implementation. New apps consume it; do not fork the IR.
  • All cross-app types live in packages/shared — never copy-paste types between apps.
  • Components shared across ≥2 apps move to packages/ui. Keep app-local components in apps/<app>/src/components.
  • Turbo cache keys: ensure inputs in turbo.json cover all source paths; missing globs cause stale cache.

Anti-Patterns

  • Adding deps to root package.json (use the relevant app/package)
  • Bypassing turbo with manual tsc invocations — breaks cache invalidation
  • Circular dependencies between packages (turbo will warn; fix immediately)
  • Publishing packages/* to npm — they're internal workspace-only