Files
CharacterGardenStack/thoughts.md

6.5 KiB

thoughts.md

Current Status

  • Scaffold complete: charactergarden/ folder structure created per spec section 9
  • Core contracts defined in app/src/types.ts: Entity, Action, Verb, ValidationResult, StateChange, GameEvent, Turn, Belief, Fact, Affordance, Summary
  • docker-compose.yml created; ollama service gated behind --profile llm (not required for MVP)
  • .env / .env.example / .gitignore in place
  • Container-first runtime files added: app/frontend Dockerfiles and .dockerignores
  • Truth Engine implemented in app/src/truthEngine.ts — pure function, no I/O, no LLM
    • validate(actions, worldState) → ValidationResult
    • applyChanges(worldState, changes) → new WorldState (immutable)
    • All 8 verbs handled with explicit rejection reasons
  • move now supports a built-in offscene room convention via createOffsceneRoom()
  • latentEntities.ts can promote plausible personal items from belief to fact when the actor has carrying context
  • db.ts added with SQLite schema + persistence helpers for entities, events, turns, beliefs, and summaries
  • Minimal Fastify server + app pipeline added with seeded world state and fallback parser
  • Minimal Vite React inspector added for visual boot testing and state inspection

Current Architecture Decisions

  • App: Node.js + Fastify + TypeScript
  • Frontend: React + Vite + TypeScript
  • Database: better-sqlite3 (synchronous, no ORM)
  • Ollama is optional; system must work without it (per section 14)
  • Event type renamed GameEvent in code to avoid collision with the DOM Event global
  • Latent personal items are gated by facts-derived affordances, not accepted directly from beliefs
  • The offscene room is represented as a normal room entity with id offscene
  • App and frontend should be run and validated through Docker Compose rather than host-installed Node

MVP Readiness (2026-04-23)

  • Estimated completion: ~90%
  • Completed against spec:
    • Turn pipeline implemented end-to-end (input -> parse -> validate -> apply -> events -> narration)
    • Truth Engine is authoritative for state mutation
    • SQLite persistence for entities/events/turns/beliefs/summaries
    • Dockerized app + frontend stack, with optional Ollama profile
    • Minimal inspector UI for state/events/turns
    • MVP world bounded to 2 rooms and <=3 characters
  • Remaining to call MVP done:
    • Run one clean boot smoke pass from current branch and record expected outputs in this file
    • Add a short "MVP acceptance checklist" section and mark each contract as pass/fail
    • Tighten fallback parser behavior for known starter prompts and ensure no regression on latent-item turns

MVP Acceptance Checklist

  • PASS: Core contracts implemented (Entity, Action, ValidationResult, StateChange, GameEvent)
  • PASS: Truth Engine is sole authority for state mutation
  • PASS: Invalid actions produce explicit rejection reasons
  • PASS: Turn flow wired end-to-end in app service
  • PASS: SQLite tables for entities/events/turns/beliefs/summaries
  • PASS: Dockerized app + frontend, no host Node dependency required
  • PASS: MVP scope bounds respected (2 rooms, <=3 characters, limited verb set)
  • PASS: Frontend inspector can submit turns and inspect state/events
  • PASS: Latent personal-item flow works in runtime (pull out my phone => promoted + accepted)
  • PASS: Parser now fails gracefully with explicit rephrase guidance for unknown/underspecified input

Next Steps

  1. Execute and capture a final Docker boot smoke check (/health, /api/state, /api/turn happy path + latent-item turn)
  2. Add explicit MVP acceptance checklist results here (contracts, scope limits, runtime constraints)
  3. Do a small parser-hardening pass for prompt coverage, then freeze MVP scope
  4. Defer non-MVP work (container-entity plausibility, richer narration, full LLM adapter)

Open Questions

  • None currently blocking MVP implementation.

Resolved Decisions (2026-04-23)

  • Room/location model: keep location as an entity attribute that points to another entity id. Rooms remain normal entities (type: room) and inventory uses inventory:<actor_id>.
  • MVP initial world: lock to 2 rooms (garden, shed) and 2 characters (player, groundskeeper), plus static scene objects (gate, bench) and built-in offscene room.
  • Latent personal-item plausibility: use actor attributes as the MVP source of truth (clothed, pocket_count, has_bag, searched_empty).
  • Container/worn-item entities: defer to post-MVP. Add this as a planned extension, not a current gate for plausibility.

Follow-up Implications

  1. Keep truth rules keyed to entity attributes.location and avoid introducing a separate room-graph subsystem yet.
  2. Keep fallback parser and truth engine behavior tuned to the locked MVP world and verb set.
  3. Add a backlog item for container-aware plausibility (worn, container, nested inventory checks) after MVP boot/test milestone.

Turn Contract (Higher Stack)

  • End-user turn response should always include:
    • narration (what happened)
    • parser_feedback when intent is unclear or underspecified
    • accepted/rejected action detail for debugger/inspector views
  • UX rule: when parser_feedback is present, UI should explicitly surface it and encourage rephrasing.

LLM Prompting Contract (In-Environment)

  • Added prompt builder in app/src/llmAdapter.ts (buildActionExtractionPrompt) to enforce world-grounded extraction.
  • Prompt constraints:
    • only allowed verbs
    • only known entity ids from current world snapshot
    • strict JSON output shape (actions, optional parser_feedback)
    • no freeform world mutation outside truth-engine validation

Session Notes

  • 2026-04-23: Project started. Scaffold, type contracts, .gitignore, and .env.example created.
  • 2026-04-23: Truth Engine implemented. Pure validation with per-verb handlers and immutable applyChanges helper.
  • 2026-04-23: Added facts/affordances + latent entity resolver for improv-style personal items, plus offscene room support.
  • 2026-04-23: Added SQLite schema module. Host npm install is blocked by better-sqlite3 on Windows Node 25, so runtime validation should happen inside Docker on an LTS Node image instead.
  • 2026-04-23: Added minimal backend/frontend boot slice so the project can be tested visually through Docker.
  • 2026-04-23: Runtime smoke check passed with live services (/health ok, state returned, look around accepted, pull out my phone accepted with zero rejections).
  • 2026-04-23: Fallback parser hardened to return human-readable guidance on unclear input (e.g., unknown intent, missing take target, missing move destination) and suggest concrete rephrasing examples.