# CHUNK #9 — AI Roles & Suggestions **Status:** In progress. Core AI session storage layer implemented and tested. ## Progress - [x] **AI session storage layer** (`packages/ai/src/`) - [x] `agent.ts` — AgentController: streaming orchestration + token budget enforcement - [x] `suggestions.ts` — SuggestionBuilder: AI suggestions across brainstorm/outline/expand/tighten/continue/research/dialogue/worldbuilding - [x] `notes.ts` — NoteBuilder: note builders for writing assistance - [x] `ai-session.ts` — AIStore: IndexedDB session persistence via Dexie (sessions, messages, suggestions, notes) - [x] `suggestion-mutation.ts` — SuggestionMutation: apply/insert/replace/delete logic - [x] `index.ts` — package exports - [x] `dexie` dependency added to `packages/ai/package.json` ## Bug fixes - [x] **`listSessions` sort tiebreaker flaky in full suite** — `packages/core/src/ids.ts` `createUlid` used the non-monotonic `ulid` function, so ULIDs weren't monotonic. The `listSessions` sort uses ULID comparison as a tiebreaker when `updatedAt` timestamps are equal; non-monotonic ULIDs caused the test to pass in isolation but fail in the full suite. Fixed by switching `createUlid` to `monotonicFactory` from the `ulid` package. - [x] **`mergeNotes` test used wrong note id** — test used `note2.notes[0]!.id` (same as note1's id) instead of `note2.notes[1]!.id`, causing the merge to combine note1 with itself. Fixed the test. - [x] **`outline` system prompt missing context** — test "includes the context in the system prompt" expected the outline prompt to include `setting` and `characters`, but the outline prompt only included `chapterTitle` and `previous`. Added setting and characters to the outline prompt. - [x] **Lint errors** — removed unused imports: `createInMemoryPersistence`, `NoteKind`, `AINote`, `AISuggestion`. ## Test results - packages/core: 47 tests - packages/ui: 5 tests - packages/editor: 30 tests - packages/ai: 71 tests - packages/exporters: 22 tests - apps/web: 13 tests - **Total: 188 tests passing** ## Key facts - Chunk #9 builds `packages/ai` as a self-contained SSE-based provider layer (NOT the Vercel AI SDK). The SDK moved v5→v4 and `@ai-sdk/openrouter` doesn't exist (404); a hand-rolled SSE client directly exercises the real deliverable (streaming orchestration, thinking-param mapping, usage tracking, 429 retry) in the mocked integration test that is the CI gate. - The Vercel AI SDK remains the intended transport for Chunk #11 (tools). - `packages/core/src/tokens.ts` provides `countTokens`/`allocateBudget`/`DEFAULT_BUDGET` (re-exported by `packages/ai/budget.ts`). - `packages/ai` re-exports core's token-budget types as `Budget` (NOT `TokenBudget`). - `packages/ai` uses Dexie for IndexedDB AI session persistence, coordinating `AIStore`, `SuggestionBuilder`, `NoteBuilder`, and `AgentController`. ## Remaining (per CHUNK#9.md) - Base role prompts (`packages/ai/src/roles/`): editor/reader/publisher/co-author - Context builder (`packages/ai/src/context.ts`) - Tools (`packages/ai/src/tools/`): applySuggestion, updateEntity, addNote, draftChapter, queryProject - Suggestion protocol: structured output + inline rendering in editor decorations - Session UI (`apps/web/src/features/ai/`): AiPanel, AiSessionsView, feedback loop