4efa71515e
Data layer: - Fuzzy scorer (packages/core/src/fuzzy.ts) with index recovery + unit tests - Backlink computation (packages/core/src/backlinks.ts) incl. entity-level backlinks - Consistency checker (packages/core/src/consistency.ts) incl. reciprocity/scope + unit tests - StorageAdapter contract extended with listEntities/searchEntities/saveEntity/deleteEntity; implemented in Local (Dexie) and Server adapters; contract tests cover entity CRUD + ?q= search - WorldItem.fields now supports list values (keyPeople, rivals); expanded RelationshipKind - @mention autocomplete extension + picker in the editor package Entity UI (apps/web/src/features/entities/): - Generic field renderer (EntityFields) driven by ENTITY_FIELDS/FieldDef - Tabbed directory with fuzzy search + entity cards (EntitiesView) - Create/edit/delete drawer (EntityEditor) reusing shared fields - Relationship editor + force-directed SVG relationship map - Entity engine stylesheet; wired into nav Store: project-store entity methods (load/create/update/delete) over the StorageAdapter contract. CI-green: typecheck, lint, 65 tests, and web build all pass.
69 lines
6.2 KiB
Markdown
69 lines
6.2 KiB
Markdown
# 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.
|
|
|
|
**Status (updated 2026-10-25):** 🟡 In progress. Data layer and entity UI layer complete and CI-green (`pnpm typecheck`, `pnpm test`, `pnpm lint`, `pnpm build` all pass; 65 tests green across the workspace). See "Remaining" below.
|
|
|
|
---
|
|
|
|
## 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. Generic renderer done for `text`/`textarea`/`checkbox`/`tags` (list); `link` field type pending.
|
|
- [x] 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). Autocomplete + chip + open sheet done; hover popover pending.
|
|
- [x] 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. Logic in `packages/core/src/consistency.ts` done; UI wiring + seeded case pending.
|
|
- [x] Relationship map renders and navigates.
|
|
- [ ] Global palette finds a chapter, a character, and a note from one box.
|
|
- [x] Contract suite still green on both adapters.
|
|
|
|
## Remaining work
|
|
- Wire `findInconsistencies()` into the Characters tab as a warnings list (Chunk 3.2).
|
|
- Index entities in the global `Ctrl/Cmd+K` palette (Chunk 3.1).
|
|
- Context rail (right side of WritingView): this chapter's mentioned characters, pinned entities, related notes (Chunk 3.2).
|
|
- Extend `server/src/seed.ts`: full character sheets (bio, voice, 2 relationships each) + 5 world items (Chunk 4.1).
|
|
- `docs/DATA_MODEL.md`: the entity registry table (kind → fields) as the human reference (Chunk 4.2).
|
|
- E2E: create character → `@mention` it in a chapter → backlinks tab lists the chapter → open sheet from the chip (Chunk 5.3).
|
|
|
|
## 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.
|