# CHUNK #4 — Characters & World-Building **Duration:** ~2 days · **Prereqs:** CHUNK #2 (entity storage), CHUNK #3 (editor for mentions) · **Follows:** CHUNK #3 · **Unblocks:** CHUNK #5 (plot links entities), #9 (AI context pulls from entities) **Purpose:** Make the story's moving parts first-class: character sheets with typed relationships, flexible world items, fast fuzzy search, backlinks, and `@mention` links from prose to entities. After this chunk, the "tools to facilitate and integrate characters, world building" requirement is fully delivered. --- ## Steps ### 1. Entity engine (`apps/web/src/features/entities/`) 1. **Generic field renderer** (`EntityFields.tsx`) — driven entirely by `ENTITY_FIELDS` from `packages/core/src/schema.ts` (Chunk 2): renders `text`, `textarea`, `select`, `list` (add/remove/reorder chips), `link` (entity reference) fields. Adding a field to the registry = it appears in the UI. No per-entity UI code. 2. **Entity panel** (`EntitiesView.tsx`) — tabbed: **Characters · World · Notes**. Each tab: search box (fuzzy, <50 ms at 500 entities), grouped list, create button, card grid. 3. **Entity editor** (`EntityEditor.tsx`) — right-rail drawer: fields from the registry, plus: - **Relationships editor** (characters): add `{ target: character, kind: 'ally'|'rival'|'family'|'mentor'|'romantic'|'custom', note }`; render as a list with the linked character's chip. - **Backlinks** tab: "Appears in" — chapters containing a mention of this entity, plus entities that reference it. - Duplicate, delete (with confirm + backlink warning), "pin to context rail". 4. **World kinds** — `location`, `faction`, `item`, `glossary`, `system` — each with its field set from the registry (e.g. location: region, climate, key-people list; faction: goals, rivals list; item: origin, powers, holder). 5. **Relationship map** (`RelationshipMap.tsx`) — a small force/graph view (reuse React Flow with a static layout) of the selected character's web; click a node → open that character. ### 2. Mentions & linking 1. **Autocomplete** (`packages/editor/src/mention.ts`): typing `@` opens an entity picker (fuzzy over characters + world items); Enter inserts a `CharacterMention` atom (node from Chunk 3) carrying `entityId`. 2. **Mention chip** — styled, hover → mini popover (name + one-line bio + "Open sheet"); click → opens the entity editor. 3. **Backlink computation** (`packages/core/src/backlinks.ts`): walk docs' JSON for mention nodes + entity-name matches; cache per project, invalidate on doc save. Power the "Appears in" tab and the context rail. 4. **Consistency check** (small win, big value): `findInconsistencies(project)` — e.g. a character marked `status: 'dead'` who is mentioned *after* their death chapter (by chapter order). Surface as a warnings list in the Characters tab. ### 3. Search & navigation 1. Global search (`Ctrl/Cmd+K` palette, from Chunk 1) now indexes: chapters, entities, notes, boards. Grouped results, jump-to with context snippet. 2. Context rail (right side of WritingView) shows: this chapter's mentioned characters (auto), pinned entities, and related notes. ### 4. Data & seed 1. Extend `server/src/seed.ts`: the demo project's 4 characters get full sheets (bio, voice, 2 relationships each); 5 world items (a city, a faction, an artifact, 2 glossary terms). 2. `docs/DATA_MODEL.md` — the entity registry table (kind → fields) as the human reference. ### 5. Tests 1. Unit: field renderer per type; fuzzy search (500 entities < 50 ms); backlink computation (property test: insert mention → backlink appears; remove → disappears). 2. Contract: entity CRUD + `?q=` search through both adapters (add to Chunk 2's suite). 3. E2E: create character → `@mention` it in a chapter → backlinks tab lists the chapter → open sheet from the chip. --- ## Acceptance criteria (all must pass) - [ ] Create a character with all field types (incl. list + link) via the generic renderer — no custom code added. - [ ] Fuzzy search over 500 seeded entities returns in < 50 ms (measured in test). - [ ] `@` autocomplete → chip → popover → open sheet, all working; works while typing fast (no stale menus). - [ ] Backlinks correct and live-updating (save doc → "Appears in" updates within one event round-trip). - [ ] Consistency check flags the seeded dead-character-after-death case. - [ ] Relationship map renders and navigates. - [ ] Global palette finds a chapter, a character, and a note from one box. - [ ] Contract suite still green on both adapters. ## Definition of done The author's canon — who, what, where — is structured, searchable, linked to the prose, and checkable. This is the data the AI roles will reason from in Chunk 9. ## Risks & fallbacks - **Fuzzy search quality** → use a small, well-tested scorer (e.g. `fuse.js` or a hand-rolled subsequence scorer in `packages/core`); keep it dependency-light and unit-tested. - **Backlink cost on huge docs** → compute incrementally on save (diff the doc), not full re-scan; cache in the DB (`mentions(entity_id, chapter_id)` table). - **Mention vs. plain text ambiguity** → only explicit `@`-inserted atoms are links; name-matching is *suggested*, never auto-applied.