Phase 1: v1 single-bot roleplay engine #1
Reference in New Issue
Block a user
Delete Branch "phase-1"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Phase 1 of the Roleplay Engine, end-to-end. 38 commits, 168 tests passing, schema version 7.
The single-bot core loop is functional: bot authoring with kickoff parse-and-confirm, streaming turns over SSE with multi-tab sync, drawer rendering with edit affordances, scene-close detection with per-POV summary rewrites, edge updates per turn, FTS5 retrieval with witness filter + ranking boosts, periodic snapshots + nightly backups, rewind/regenerate/reset, first-run navigation, friendly 404/500 pages.
What's in this PR
append_and_apply, per-turn memory writes, async significance pass + auto-pin, ranked retrieval.365dacc):*.egg-info/gitignored,pip install -e .packaging fix, Phase 1.5 backlog documented in CLAUDE.md.Design references
Test plan
.venv/bin/pytest— 168 passed.venv/bin/pip install -e .— succeeds (post-cleanup)data/config.example.toml→data/config.tomlwith real Featherless key,uvicorn chat.app:app --reload, walk through first-run (settings → bot author → kickoff confirm → chat), play 5 turns, open drawer, edit affinity, close scene, rewind, regenerate, multi-tab sync.Phase 1.5 cleanup backlog
Documented in CLAUDE.md. None blocking. Track via that file rather than separate issues.
Out of scope (Phase 2+)
Idempotent seeder for three sample bots (Maya — coworker slow-burn, Eli — live-in partner, Sam — bartender / new connection). Each is a distinct relational archetype to exercise the system from different angles. Run from repo root: .venv/bin/python scripts/seed_sample_bots.py Re-running skips ids that already exist. After seeding, walk each bot through kickoff parse-and-confirm at /bots/<id>/kickoff.The kickoff parse-and-confirm route was 500-ing intermittently because Hermes-3 + Featherless's response_format={"type":"json_object"} only guarantees JSON output, NOT a particular schema. The model was inventing its own field names (sceneTime, entities, settingDetails) instead of the KickoffParse fields, causing Pydantic validation to fail on both classify() retries. Three changes: 1. Include the Pydantic JSON schema in the system prompt so the model knows exactly which keys to produce. Affects every classify() call (kickoff parse, turn parse, scene-close detect, significance, state-update, scene summarize). Strip ```json fences if the model wraps its output. Bump retries 2 → 3 (model is stochastic; one extra attempt closes most of the remaining gap). 2. parse_kickoff() now passes a default empty KickoffParse so the route degrades to a fillable form instead of 500 when the classifier ultimately fails. The confirm form is the human-in-the-loop; an empty form is strictly better UX than a stack trace. 3. Tests updated: bumped canned-failure arrays from 2 → 3 entries to match the new attempt count; renamed kickoff test from "raises_when_classifier_fails_twice" to "falls_back_to_empty_when_classifier_fails" reflecting the new degraded-but-usable behavior. Verified live with all 3 sample bots (maya/eli/sam) — kickoff route returns 200 across multiple attempts. Full suite: 168 passed.13 tasks across 6 waves (1, 2, 3, 4a, 4b, 5). Designed for parallel subagent execution where file-disjointness allows. Waves 1, 2, 4a, and 5 each contain 2-3 tasks that touch disjoint files and can be dispatched concurrently via the Agent tool with isolation: "worktree". Waves 3 (drawer guest support) and 4b (multi- entity turn flow) are single-task because they touch hot files (_drawer.html, turns.py) that cannot be safely co-modified. Plan covers: - T36: group_node schema + handlers (new migration 0008) - T37: guest_added / guest_removed event handlers (modifies world.py) - T38: relationship-seed service ("have they met?") - T39: interjection classifier service - T40: multi-entity state-update coordinator (6 directed pairs) - T41: multi-witness memory write helper - T42: drawer guest add/remove UI + render - T43: multi-entity prompt assembly (extends T18) - T44: multi-entity turn flow (rewrites post_turn) - T45: multi-entity per-POV summaries on scene close - T46: witness filter cross-coverage tests - T47: bot_reset cascades to guest references - T48: Phase 2 documentation update Plan also documents: - Worktree-per-subagent dispatch pattern using Agent isolation flag - Merge ordering per wave (file-disjointness = conflict-free merges) - Failure recovery (cancel failed parallel task, re-dispatch as solo) - Conflict prevention checklist (verify Files sections disjoint per wave) Tasks file (.tasks.json) carries dependency DAG with `blockedBy` and `parallelGroup` so a future executing-plans run can dispatch correctly. NOT EXECUTING. Plan only.