`npm run prepare` runs `npm run build` on install — if `inline-schema` isn't available, installs will fail.
## Local Dependency
`inline-schema` is a **local peer dependency** at `file:../inline-schema` — must exist as a sibling directory before `npm install`. Both vitest and tsup load custom plugins from it (`inline-schema/csv-loader/rollup` and `inline-schema/csv-loader/esbuild`). `yarn-spinner-loader` is also a local dependency at `file:../yarn-spinner-loader` — it can be changed and published if needed. It provides vitest and tsup/esbuild plugins for `.yarnproject` dialogue files.
## Architecture
- **MutableSignal\<T\>**: extends Preact Signal — `.value` to read, `.produce(draft => ...)` to mutate (uses `mutative`). `.produceAsync()` awaits interruption promises first, then mutates.
- **GameModule**: `{ registry?, createInitialState, start }`. `registry` defaults to `createGameCommandRegistry()` if omitted.
- **Command system**: CLI-style parsing with schema validation via `inline-schema`. `CommandRunner.run()` uses `this` bound to a `CommandRunnerContext`.
- **Prompt system**: `game.prompt(def, validator, currentPlayer?)` — validator **throws a string** to reject, **returns a value** to accept. `PromptEvent.tryCommit(Command | string)` returns `null` on success, error string on failure. `promptEnd` event fires after resolve or cancel.
- **Part collections**: `Record<string, Part<TMeta>>` keyed by ID. `Object.values()` for iteration, `Object.keys()` for count/IDs.
- **Region system**: `createRegion()` factory; `partMap` maps position keys to part IDs.
- **Barrel exports**: `src/index.ts` is the single public API surface.
`src/utils/command/` is a directory: types.ts, command-parse.ts, command-registry.ts, command-runner.ts, command-validate.ts, command-apply.ts, schema-parse.ts, index.ts.
## Samples Build
`tsup.samples.config.ts` auto-discovers entries from `src/samples/` (directories → `index.ts`, files → direct `.ts`). It rewrites `@/core/*`, `@/utils/*`, and `@/index` imports to external `boardgame-core`.