# thoughts.md ## Current Status (clean-break) - Backend is running the new contract-native API shape: - `GET /api/state` -> `{ worldState, turns }` - `POST /api/turn` -> `{ rawText, actions, validation, worldState }` - Runtime blocker is resolved: - old SQLite schema conflict (`turns.raw_text`) was fixed by wiping old DB state - stale legacy files removed from backend source tree: - `app/src/types.ts` - `app/src/latentEntities.ts` - `app/src/llmAdapter.ts` - Door/key MVP smoke checks pass: - `open door` before key -> `locked_requires_key` - `take key` -> success - `open door` after key -> success - Scene-entry support added: - `introduce` is now a first-class action - rooms can declare `is_joinable` - characters can declare `is_social` - successful introduction moves a character from offstage into the actor's current room - `introduce` can also create a new social character when the named target does not already exist ## Architecture Now - Core contracts in `app/src/contracts/`: - `action.ts` - `validation.ts` - `turn.ts` - `entity.ts` - `world.ts` - Deterministic truth engine: - `app/src/truthEngine.ts` with `validateActions(actions, worldState)` - Ordered turn pipeline: - `app/src/turns/processTurn.ts` parse -> validate -> apply -> persist - World mutation: - `app/src/world/applyActions.ts` - Persistence: - `app/src/db.ts` with tables `turns`, `actions`, `validation_results`, `entities`, `world_states` - App seed domain: - `app/src/app.ts` door/key world (`room_start`, `room_exit`, `room_offstage`, `player`, `groundskeeper`, `door_1`, `key_1`) ## Scene Entry Rules - `introduce` validates against deterministic affordances: - target must exist - target must be a character - target must have `is_social: true` - actor must be in a valid room - room must have `is_joinable: true` - target must not already be in that room - If no existing target entity is resolved but a character name is present, `introduce` may create a new character directly into the current room. ## Character Description (NEW) - `describe` action adds traits to characters: - Syntax: `"describe the merchant as shrewd and quick"` - Traits are stored in `character.attributes.traits[]` - Multi-sentence support: `"introduce a merchant. describe the merchant as shrewd and quick."` - Validation rules: - target character must exist (or will be created by introduce in same turn) - actor and target must be in same room (for existing targets) - supports forward-reference to entities created in the same turn - Multi-action parsing: - Sentences split on `/[.!?]+/` - Each sentence becomes a separate action - Validation accounts for entities created by introduce actions in the same turn - On success: - target location becomes the actor's location - `in_scene` is set to `true` - `last_introduced_by` is recorded - newly created characters default to `type: character`, `is_social: true`, `in_scene: true` ## New Endpoint - Added `POST /api/reset` in `app/src/index.ts` - App-level reset implementation in `app/src/app.ts` - DB wipe support in `app/src/db.ts` - Verified reset behavior: - returns `{ worldState, turns }` - `turns` is empty after reset - `player` and `key_1` return to `room_start` ## Frontend Migration Notes - `frontend/src/App.tsx` migrated to consume new backend contracts. - Removed dependencies on old fields (`narration`, `events`, `beliefs`, `summaries`, `parser_feedback`). - Turn submit flow now refreshes snapshot via `GET /api/state` after `POST /api/turn`. - Reset call now sends JSON body/content-type to satisfy Fastify media-type validation. ## Remaining Checks 1. Frontend build pass completed in container (`docker compose exec frontend npm run build`). 2. Validate inspector UX manually against the door/key plus introduce flow. 3. Expand parser coverage only within current clean MVP domain.