5.9 KiB
CHUNK #9 — AI Roles & Suggestions
Duration: ~3 days · Prereqs: CHUNK #8 (providers, token budget), CHUNK #4 (entities), CHUNK #3 (editor edit API) · Follows: CHUNK #8 · Unblocks: CHUNK #11 (parity: AI works in web + desktop identically)
Purpose: Bring the four agentic roles (Editor, Reader, Publisher, Co-Author) to life with robust base prompts, a context builder that pulls from the author's own data, AI SDK tool-calls, and — the signature feature — the suggestion protocol that renders AI feedback as inline, adoptable/rejectable/pinnable edits anchored to exact passages.
Steps
1. Base role prompts (packages/ai/src/roles/)
- Role type (
packages/ai/src/roles/types.ts):Role = 'editor' | 'reader' | 'publisher' | 'co-author'. Each has asystemPrompt,temperaturedefault, andtools[]. - Editor (line editor): tighten prose, kill filter words, sharpen dialogue tags, fix pacing, flag weak openings/closings, check consistency against character/world data. Emits targeted structured edits with rationale. Respects the author's voice.
- Reader (honest first-time reader): what was confusing, where attention dropped, what was telegraphed too early, what paid off. Reports as a reader, not in craft jargon.
- Publisher (market & packaging): comps, hook, pacing vs. genre, title/cover/blurb ideas, series potential, format decisions.
- Co-Author (collaborator with full project knowledge): drafts scenes/chapters in the author's voice, proposes plot turns, writes dialogue, expands world-building — always as suggestions the author accepts or rejects, never silently rewriting canon.
- Prompts live in
docs/ROLE_PROMPTS.mdas the human reference;packages/ai/src/roles/prompts.tsimports them.
2. Context builder (packages/ai/src/context.ts)
buildContext(project, { targetDoc, role, maxTokens }):- Pull relevant characters (mentioned in target doc + top entities), world items, linked plot beats, prior chapter summaries.
- Pack in priority order until the context budget (Chunk 8) is reached.
- Return
{ system, contextText, sources: {entityId, title}[] }—sourcespowers the "what I used" panel.
- History: last N messages from the
AISession, truncated to the history budget.
3. Tools (packages/ai/src/tools/)
AI SDK tool-calls so a role acts on the workspace:
applySuggestion({ target, before, after, rationale, kind })— registers a suggestion (Chunk 5 model).updateEntity({ id, fields })— edits a character/world field (pending author approval in UI).addNote({ body, linkedTo })— creates a note.draftChapter({ title, outline })— seeds a chapter doc.queryProject({ q })— search entities/chapters (returns snippets for the role).
4. Suggestion protocol (the signature feature)
- Structured output: roles emit JSON
{ target: {docId, range|nodePath}, before, after, rationale, kind: 'replace'|'insert'|'delete'|'entity-update'|'draft', status: 'pending' }. Enforce with the provider's JSON-mode + a local zod schema validator (retry on parse failure). - Inline rendering (
packages/editor/src/decorations/suggestions.ts): render each pending suggestion as an inline decoration over the exact passage — green for insert, yellow for replace, red for delete. Range is a node anchor, not a raw offset (re-resolved on every transaction — prevents drift, Chunk 3 risk). - Actions: hover a decoration → Accept (applies the edit via
applyEdit), Reject (removes it), Pin (copies it into a pinned note for later). Panel lists all pending suggestions with rationale + "what I used" sources. - Co-Author drafts: render as a side-by-side diff view (original vs. draft) with accept/reject per paragraph.
5. Session UI (apps/web/src/features/ai/)
- AI panel (
AiPanel.tsx): role selector, provider/model picker, temperature/thinking/context sliders, "Ask" button, streaming response view, pending suggestions counter. - Sessions (
AiSessionsView.tsx): list past sessions (fromAISession), reopen to continue, export session transcript. - Feedback loop: after accepting/rejecting, log the choice → future context can deprioritize rejected styles (v1: simple counter, not ML).
6. Tests
- Unit:
buildContextpacks the right entities within budget;sourcespopulated. - Unit: zod schema rejects malformed suggestion JSON.
- Unit: node-anchor resolution survives a doc edit (insert before range → range shifts correctly).
- E2E: start an Editor session → suggestion appears inline → Accept → text changes → suggestion cleared; Pin → note created.
- E2E: Co-Author draft → diff view → Reject → original intact.
Acceptance criteria (all must pass)
- All four roles respond with role-appropriate output; base prompts enforced.
- Suggestions render inline over the exact passage; accept/reject/pin all work.
- Accepting applies the edit; rejecting removes it; Pin creates a note.
- "What I used" lists the entities/context the role drew from.
- Node-anchored ranges stay correct across typing (no drift).
- Co-Author draft shows a paragraph-level diff; accept/reject work.
- Sessions persist; reopen continues the conversation.
- Contract suite still green on both adapters.
Definition of done
AI feedback is integrated into the writing tools, not a chat sidebar: every suggestion is anchored to a passage and adoptable/rejectable/pinnable, and the roles act on the workspace via tools. This is the signature PubScript feature.
Risks & fallbacks
- Range drift over live editing → node anchors, not raw offsets; re-resolve on every transaction (built into Chunk 3's decoration pipeline).
- Scope creep in roles → roles are prompt + tools, not new UI surfaces; the suggestion protocol is the single integration point.
- LLM JSON reliability → strict zod validation + retry; fall back to a structured template if the model refuses JSON.