Changelog.

Full development history. Every feature, fix, and architectural decision documented.

Total Entries
99
Date Range
2026-03-27 — 2026-07-13
Source Files
197
Bug Fixes
35+

Highlight Reel.

Major Feature

Query Manager (11 entries) — complete submission management system: Quill researches agents and publishers via web search, auto-populates targets, generates personalized query letters, and tracks submissions. 15th pipeline phase, 6 UI components, dedicated IPC namespace.

Major Feature

WebSearch for all providers (3 entries) — cross-provider web search parity: DuckDuckGo-based WebSearcher for Ollama/llama-server, --enable standalone_web_search for Codex CLI. All providers can now research the web for query targets.

Bug Fix

Codex CLI hardening (11 entries) — silent exits surface real errors, 0.27.0 event envelope unwrapped, tool/file event tracking, file-only success detection, unknown-event diagnostics, model resolution guardrails, bounded stream-failure retry. Codex CLI is now reliable for pipeline use.

Major Feature

Codex CLI provider (8 entries) — OpenAI's Codex CLI as a full AI backend: detection surface, provider client, startup registration, workspace-launch hardening, and add-dir compatibility.

Major Feature

CLI-first Ollama (3 entries) — availability and model discovery routed through the ollama CLI with a built-in agentic tool loop, plus refreshed provider settings copy.

Architecture

250K context ceiling + proactive compaction — MAX_CALL_CONTEXT_TOKENS raised to 250K; Ollama and llama-server agents compact old tool results at 80% of the window instead of breaking at 90%.

Major Feature

Series Bible (7 sessions) — group books into ordered series with shared story bibles. Automatic context injection into all 7 creative agents. File-based storage with reverse-lookup cache.

Major Feature

In-App Helper Agent — floating chat panel with comprehensive user guide knowledge base. Answers questions about features, workflows, and troubleshooting. Persistent across views.

Onboarding

Guided Tours & Tooltips (5 sessions) — three spotlight-based tours, contextual tooltips on 14 components, keyboard navigation, accessibility attributes, and auto-launch after onboarding.

Major Feature

Multi-model provider architecture (7 sessions) — pluggable AI backends with OpenAI-compatible endpoint support, ProviderRegistry, and capability-aware model routing.

Major Feature

Manuscript Import (6 sessions) — import .md/.docx manuscripts with chapter detection, preview editing, and optional multi-agent source document generation.

Major Feature

File Version History (6 sessions) — every file write creates a SQLite snapshot. SHA-256 dedup, visual diff viewer, one-click revert, source tracking.

Architecture

14-prompt architecture refactor — extracted StreamManager, AuditService, PitchRoomService, HotTakeService, AdhocRevisionService from ChatService. Added IChatService/IUsageService interfaces. Database migration system.

Major Feature

Motif Ledger — structured tracking for motif systems, foreshadowing, structural devices, minor characters, flagged phrases, and audit logs. Seven-panel tabbed editor with JSON persistence.

Quality & Stability

Race condition fixes in stream management, EPIPE diagnostic logging, batched stream event persistence, stream listener lifecycle management, and CLI-based motif ledger normalization.

Major Feature

Dashboards & Statistics (7 sessions) — book overview dashboard with pipeline health, word counts, revision tasks, and activity feed. Writing statistics with Recharts-powered charts for token usage, cost tracking, and word count trends.

Feature

Batch Find & Replace — bulk search across all chapter drafts with literal/regex matching, per-chapter preview with inline highlighting, selective application, and automatic version snapshots.

UI Refactor

Sidebar Bookshelf & 5-Tab Files View — BookSelector dropdown replaced with persistent BookPanel. FilesView restructured from 2 tabs to 5 focused category tabs (Source, Chapters, Agents, Explorer, Motif Ledger).

All Entries.

Codex CLI standalone_web_search flag

The Codex CLI's native web_search tool must be explicitly enabled via --enable standalone_web_search on each codex exec spawn. The prior session's Codex web_search work wired up event parsing and tool-name recognition but missed adding the CLI flag, so the tool was never actually offered to the model.

  • src/infrastructure/codex-cli/CodexCliClient.ts — Added '--enable', 'standalone_web_search' to the args array in runCodexAttempt()
WebSearch for all CLIs + Query Manager activity in CLI panel

All model providers (Ollama, llama-server, Codex) now support WebSearch for query-manager research. Previously only Claude CLI had web search capabilities. All Query Manager streaming activity now broadcasts to the CLI Activity panel.

  • src/infrastructure/ollama-cli/WebSearcher.ts — DuckDuckGo HTML-based web search executor
  • src/infrastructure/ollama-cli/tools.ts — Added WebSearch tool definition
  • src/domain/types.ts — Added 'query' to StreamEventSource union
  • src/infrastructure/codex-cli/CodexCliClient.tsextractToolInfo recognizes web_search item types
  • src/infrastructure/claude-cli/StreamSessionTracker.tsinferStage treats WebSearch as a reading-stage tool
  • src/main/ipc/handlers.ts — Query handlers broadcast to both query:onStream and chat:streamEvent
Query Manager auto-populate and per-field AI fill

Quill can now research and auto-populate submission targets in bulk using web search, and any individual field on a target can be AI-filled on demand. This eliminates manual data entry for the Query Manager.

  • src/renderer/components/QueryManager/ResearchPanel.tsx — Streaming research progress panel
  • src/application/QueryService.ts — Added researchTargets() and fillTargetField() methods
  • src/main/ipc/handlers.ts — Added query:researchTargets and query:fillTargetField handlers
  • agents/QUILL.md — Added Phase 7 (target research & field fill)
  • src/infrastructure/claude-cli/ClaudeCodeClient.ts — Added WebSearch to --allowedTools
  • src/renderer/components/QueryManager/TargetCard.tsx — Added per-field AI fill buttons
PipelineSpine integration + pipeline detection for query-agents

Integrated the query-agents phase into the PipelineSpine UI: added it to the SHIP stage, wired the phase click to navigate to the QueryManagerView, and added isPhaseComplete detection via source/query-tracker.md.

  • src/application/PipelineService.ts — Added case 'query-agents' to isPhaseComplete
  • src/renderer/components/PipelineSpine/stages.ts — Added 'query-agents' to SHIP stage
  • src/renderer/components/PipelineSpine/PipelineSpine.tsx — Phase click navigates to query-manager view
QueryManagerView, components, IconRail entry, view routing

Built the full Query Manager UI: 5 React components, added 'query-manager' to ViewId union, added 'mail' icon, added IconRail entry, wired QueryManagerView into AppLayout.

  • src/renderer/components/QueryManager/QueryManagerView.tsx
  • src/renderer/components/QueryManager/TargetCard.tsx
  • src/renderer/components/QueryManager/AddTargetForm.tsx
  • src/renderer/components/QueryManager/LetterPreview.tsx
  • src/renderer/components/QueryManager/FilterBar.tsx
Query Manager renderer store (queryStore)

Created the queryStore Zustand store. Manages tracker/letter state for the active book, calls the preload bridge, and exposes actions for target CRUD, letter generation streaming, and letter file I/O.

  • src/renderer/stores/queryStore.ts — Zustand store with tracker/letters/loading/generating state
Composition root wiring + Quill Phase 6 prompt

Cleaned up the composition root to use a named queryService variable. Added Phase 6 (Personalized Query Letters) to agents/QUILL.md.

  • src/main/index.ts — Named queryService variable, passed to handlers
  • agents/QUILL.md — Added Phase 6: Personalized Query Letters
IPC handlers and preload bridge for query namespace

Wired QueryService into the IPC layer: 9 new channels under query:* namespace, query namespace on the preload bridge with 9 methods.

  • src/main/ipc/handlers.ts — 9 IPC handlers (loadTracker, saveTracker, addTarget, updateTargetStatus, removeTarget, generateLetter, listLetters, readLetter, saveLetter)
  • src/preload/index.ts — Query namespace with 9 methods
QueryService implementation: tracker I/O, CRUD, letter generation

Implemented QueryService in the application layer. Parses/serializes source/query-tracker.md, manages source/query-letters/ directory, and generates personalized query letters via Quill.

  • src/application/QueryService.ts — Full IQueryService implementation
  • src/application/index.ts — Added QueryService barrel export
Query Manager domain types and pipeline phase registration

Added the domain layer foundation for the query management system: new PipelinePhaseId value 'query-agents' (15th phase), six new query types, the IQueryService interface, and two new Quill quick actions.

  • src/domain/types.tsQueryTargetType, QueryStatus, QuerySubmissionMethod, QueryTarget, QueryTracker, QueryLetter types
  • src/domain/interfaces.tsIQueryService interface with 9 methods
  • src/domain/constants.ts'query-agents' in PIPELINE_PHASES and PHASE_OUTPUT_FILES
Codex bounded stream-failure retry

Fully-empty transient Codex stream failures now automatically retry up to 2 times with linear 2s/4s backoff. Exactly one terminal error StreamEvent emitted when the run gives up.

  • src/domain/constants.tsCODEX_STREAM_RETRY_MAX (2) and CODEX_STREAM_RETRY_DELAY_MS (2000)
  • src/infrastructure/codex-cli/CodexCliClient.ts — Extracted runCodexAttempt(), retry loop in sendMessage()
Codex real error surfacing

Transient stream_error events are now distinguished from terminal error events. Terminal errors report Codex CLI reported an error: <real reason> instead of a generic no-output diagnostic dump.

  • src/infrastructure/codex-cli/CodexCliClient.ts — Added extractStreamError(), rewrote extractError(), improved failure summaries
Codex 0.27.0 envelope unwrapping

Codex 0.27.0's {"id":"0","msg":{...}} event envelope is now parsed correctly. Assistant text, status, and usage extracted from nested envelope candidates instead of top-level keys only.

  • src/infrastructure/codex-cli/CodexCliClient.ts — Added unwrapCodexEvent(), rewrote extractText(), extractStatus(), extractUsage()
Codex file-only success detection

Clean Codex exits that update files but emit no assistant text are now classified as successful file-only completions via workspace snapshot diff, instead of surfacing a false error.

  • src/infrastructure/codex-cli/CodexCliClient.ts — Prevents successful Codex file writes from being reported as errors
Codex unknown-event diagnostics

Unknown Codex JSON event shapes now include compact key-shape summaries and bounded unknownJsonTail in exit diagnostics, making parser misses actionable.

  • src/infrastructure/codex-cli/CodexCliClient.ts — Added nested event summary detection, compact unknown shape summaries
Provider model resolution guardrails

Stale model settings now resolve to an available provider model before chat streaming. Startup repairs stale settings.json model/provider pairs, ChatService records the effective model, and Settings shows a warning when the saved primary model is unavailable.

  • src/domain/types.ts — Added ResolvedModelSelection
  • src/domain/interfaces.ts — Added IProviderRegistry.resolveModelSelection()
  • src/infrastructure/providers/ProviderRegistry.ts — Added deterministic model fallback
  • src/renderer/components/Settings/SettingsView.tsx — Shows stale primary-model warning
Codex tool and file event tracking

Completed Codex tool/file JSON items are now converted to Novel Engine stream activity. file_change events update filesTouched and emit terminal filesChanged, preventing false no-file pipeline runs.

  • src/infrastructure/codex-cli/CodexCliClient.ts — Added tool/file extraction, file-change path normalization, progress inference
Codex final-output fallback and diagnostics

--output-last-message flag passed to codex exec; temporary final-message file read when JSON stdout closes without assistant text. Recovers text that would otherwise be lost.

  • src/infrastructure/codex-cli/CodexCliClient.ts — Recovers assistant text from Codex's final-message file
Surface silent Codex CLI exits as errors

Codex runs that close without assistant text or usage are now treated as failures. Bounded stdout/stderr diagnostics captured, native Codex error JSON forwarded as stream errors.

  • src/infrastructure/codex-cli/CodexCliClient.ts — Prevents silent empty Codex exits from being saved as successful empty responses
Codex silent-exit fix session program

Created a Forge session program for the Codex CLI bug where the process exits in under ten seconds and the UI shows no useful error.

  • prompts/session-program/program-015/ — Session program for Codex silent-exit fix
Created Codex file-only completion program

Created a Forge session program for the Codex CLI auto-draft failure where codex exec --json exits with code 0, writes no final agent message, and Novel Engine reports an error even though the manuscript pane shows file output.

  • prompts/session-program/program-017/ — Session program for Codex file-only completion fix
Increase context ceiling + add compaction for Ollama/llama-server

Large-context models (e.g., kimi-k2.6:cloud with 262K tokens) were hitting the 125K hard MAX_CALL_CONTEXT_TOKENS cap and the 90% context-ceiling in OllamaCodeClient/LlamaServerClient, causing the agent loop to break mid-task. Raised the global cap to 250K, softened the ceiling to 98%, added proactive compaction of old tool results at the 80% threshold, and integrated compactToolHistory from contextCompactor (was never imported) so the loop only stops after compaction fails.

  • src/domain/constants.tsMAX_CALL_CONTEXT_TOKENS raised from 125_000 to 250_000
  • src/infrastructure/ollama-cli/OllamaCodeClient.tscontextCeiling raised from 90% to 98%; added 80% compaction threshold that triggers compactToolHistory before hard-ceiling check
  • src/infrastructure/llama-server/LlamaServerClient.ts — same ceiling/compaction changes as OllamaCodeClient
  • src/infrastructure/ollama-cli/contextCompactor.ts — now imported by both OllamaCodeClient and LlamaServerClient
  • MAX_CALL_CONTEXT_TOKENS increased to 250K to match modern large-context models.
  • Both Ollama and llama-server agents now compact old tool results and assistant messages when context exceeds 80% of window, rather than breaking at 90%.
Deployment Prep: release notes, README update, website rebuild

Executed the full deployment prep pipeline. Generated RELEASE_NOTES.md (v0.6.0) cataloging all changes since v0.5.8 — 25 commits, 132 files changed, 4 new features. Updated README.md with Series Bible, Series Import, In-App Helper, Guided Tours & Tooltips features; corrected file count (136→158), store count (17→20); added new infrastructure/application/component/store entries to the source tree. Rebuilt all 6 GitHub Pages HTML files — updated version to v0.6.0, added 4 feature cards to landing page, updated stats (158 files, 20 stores, ~44K LOC), added 5 new changelog entries to changelog.html, updated architecture.html source tree and dependency graph.

  • RELEASE_NOTES.md — Release notes for v0.6.0 with categorized changes, highlights, and full commit log
  • README.md — Added 4 new Key Features sections (Series Bible, Series Import, In-App Helper, Guided Tours & Tooltips); updated source tree with series/, HelperService, SeriesImportService, 4 new stores, 4 new component directories, tours/; corrected counts (158 files, 20 stores)
  • docs/index.html — Version v0.6.0; added 4 feature cards (Series Bible, Series Import, In-App Helper, Guided Tours & Tooltips)
  • docs/architecture.html — Version v0.6.0; 158 files; added series/ to infra, HelperService + SeriesImportService to app, updated stores (20), hooks (6), component groups (16), added tours/; updated dependency graph
  • docs/changelog.html — Version v0.6.0; 63 entries; added 5 new entries + 3 new highlights
  • docs/press.html — Version v0.6.0; updated stats (158 files, ~44K LOC, 20 stores)
  • docs/contact.html — Version v0.6.0
  • docs/evaluation.html — Version v0.6.0

None — documentation and website assets only, no source code changes.

Small queue intake: 13-session program for 14 feature requests

Processed the full small feature request backlog into a structured 13-session build program at prompts/feature-requests/intake/small-queue/. Each session is a discrete, ordered engineering spec. The program covers UI bugs, sidebar/nav restructure, new views (reading mode, chapter deep dive), and smaller feature additions (saved prompts, about.json rich display, query letter mode). No source code was changed this session — only the program structure and prompt files were created.

  • FORGE-CONFIG.md — First-run program configuration for Novel Engine. Captures stack, module registry, conventions, verification commands, and custom architecture rules. Used by all future Forge runs.
  • prompts/feature-requests/intake/small-queue/MASTER.md — Master loop prompt. Instructs the executing agent to iterate through sessions until all are done.
  • prompts/feature-requests/intake/small-queue/STATE.md — Session state tracker. All 13 sessions start as pending.
  • prompts/feature-requests/intake/small-queue/SESSION-01.md — Bug cluster: revision queue select overflow, sidebar compression, CLI panel scrollbars.
  • prompts/feature-requests/intake/small-queue/SESSION-02.md — Done confirm box (first-draft = celebration modal) + onboarding guide pipeline selector fix.
  • prompts/feature-requests/intake/small-queue/SESSION-03.md — Book dropdown redesign: simplify to books + New Book + Library panel. Hide archived series groups.
  • prompts/feature-requests/intake/small-queue/SESSION-04.md — Sidebar chat expandable: hot take and adhoc revision nested under Chat. Help button relocated to nav bottom.
  • prompts/feature-requests/intake/small-queue/SESSION-05.md — Motif Ledger moved from standalone nav item to a tab inside FilesView.
  • prompts/feature-requests/intake/small-queue/SESSION-06.md — Archive series: single-action UI button in SeriesModal to archive all books in a series.
  • prompts/feature-requests/intake/small-queue/SESSION-07.md — Settings reorganization: four tabs (Writing, Providers, Appearance, Profile).
  • prompts/feature-requests/intake/small-queue/SESSION-08.md — Saved prompt library: SavedPrompt domain type, AppSettings field, Saved tab in Quick Actions.
  • prompts/feature-requests/intake/small-queue/SESSION-09.md — About.json rich display: dynamic key/value card in FilesView when about.json is selected.
  • prompts/feature-requests/intake/small-queue/SESSION-10.md — Query letter / traditional publishing Quick Actions for Quill + HELPER.md improvements + user_guide meta prompt.
  • prompts/feature-requests/intake/small-queue/SESSION-11.md — Chapter deep dive backend: IChatService.deepDive, ChatService implementation, IPC handler, preload bridge.
  • prompts/feature-requests/intake/small-queue/SESSION-12.md — Chapter deep dive UI: Deep Dive button in FilesView chapter toolbar.
  • prompts/feature-requests/intake/small-queue/SESSION-13.md — Reading mode: ManuscriptAssembly type, IFileSystemService.assembleManuscript, IPC, ReadingModeView component, Build view entry point.
  • SESSION-08 (when executed): New type SavedPrompt in src/domain/types.ts; new field savedPrompts in AppSettings; updated DEFAULT_SETTINGS in src/domain/constants.ts
  • SESSION-11 (when executed): New method on IChatService; new IPC channel chat:deepDive; new bridge method window.novelEngine.chat.deepDive
  • SESSION-13 (when executed): New type ManuscriptAssembly in src/domain/types.ts; new method on IFileSystemService; new IPC channel books:assembleManuscript; new view 'reading' in ViewId; new component src/renderer/components/Reading/ReadingModeView.tsx
  • SESSION-05 (when executed): Removes 'motif-ledger' from ViewId; zustand persist migration needed (version bump)
Add Codex CLI detection surface

Added Codex CLI detection beside the existing Claude and Ollama checks. The settings service now probes codex --version non-interactively, persists hasCodexCli, and exposes the result through IPC, preload, and the settings Zustand store for future provider switching UI work.

  • src/domain/interfaces.ts — Added ISettingsService.detectCodexCli().
  • src/infrastructure/settings/SettingsService.ts — Added detectCodexCli() using non-interactive codex --version with a 10s timeout.
  • src/main/ipc/handlers.ts — Added settings:detectCodexCli IPC handler.
  • src/preload/index.ts — Added window.novelEngine.settings.detectCodexCli() bridge method.
  • src/renderer/stores/settingsStore.ts — Added detectCodexCli() action that refreshes settings after probing.
  • docs/architecture/DOMAIN.md — Documented the new settings contract and current Codex/Ollama provider/settings shapes.
  • docs/architecture/INFRASTRUCTURE.md — Documented Codex and Ollama CLI detection behavior in SettingsService.
  • docs/architecture/IPC.md — Documented the new Codex detection channel and preload method.
  • docs/architecture/RENDERER.md — Documented the new settings store detection action.
  • New IPC channel: settings:detectCodexCli
  • New preload bridge method: window.novelEngine.settings.detectCodexCli()
  • Extended settings service contract: ISettingsService.detectCodexCli()
Add Codex CLI provider client

Added the infrastructure provider for Codex CLI. CodexCliClient implements IModelProvider, invokes codex exec --json through a non-interactive stdin prompt, streams JSONL assistant output into Novel Engine stream events, persists stream events in SQLite batches, and supports active-process idle checks and abort cleanup.

  • src/infrastructure/codex-cli/CodexCliClient.ts — Implements the built-in Codex CLI provider with availability checks, prompt construction, JSONL/text streaming, usage handling, event persistence, and SIGTERM/SIGKILL abort support.
  • src/infrastructure/codex-cli/index.ts — Barrel export for the Codex CLI provider.
  • docs/architecture/ARCHITECTURE.md — Added src/infrastructure/codex-cli/ to the source tree and Codex CLI to the technology stack.
  • docs/architecture/INFRASTRUCTURE.md — Added the codex-cli/ module inventory and documented the chosen codex exec --json invocation.
  • New infrastructure module: src/infrastructure/codex-cli/
  • New provider implementation: CodexCliClient implements IModelProvider
  • New runtime dependency path: Codex CLI provider → local codex exec --json
Register Codex provider at startup

Registered Codex CLI as a built-in provider during app startup. The composition root now instantiates CodexCliClient, enables it when codex --version succeeds, persists hasCodexCli, discovers models from ~/.codex/models_cache.json when available, and falls back to a built-in gpt-5.3-codex model.

  • src/main/index.ts — Imports and registers CodexCliClient, adds Codex model discovery, persists Codex CLI availability, and skips Codex in the user-provider loop.
  • src/domain/constants.ts — Adds fallback Codex model gpt-5.3-codex and default model metadata to the built-in Codex provider config.
  • docs/architecture/ARCHITECTURE.md — Updates the service dependency graph for Codex, Ollama, llama-server, and provider registry startup wiring.
  • docs/architecture/DOMAIN.md — Documents the current built-in provider IDs and four built-in provider configs.
  • docs/architecture/INFRASTRUCTURE.md — Documents Codex startup registration and model discovery fallback behavior.
  • New composition root wiring: src/main/index.ts instantiates CodexCliClient(booksDir, db).
  • New startup model discovery path: ~/.codex/models_cache.json → built-in gpt-5.3-codex fallback.
  • Settings persistence: startup updates hasCodexCli based on CodexCliClient.isAvailable().
Polish provider switching UI

Updated Settings and onboarding copy so Codex CLI is presented as a first-class built-in backend alongside Claude CLI, Ollama, and llama-server. Provider cards now show clear labels, active-provider state, active switching, and local CLI checks for Claude/Codex without exposing endpoint fields for Codex.

  • src/renderer/components/Settings/ProviderSection.tsx — Added Codex/Ollama type labels, active badges, active-provider switching, provider-neutral copy, and kept endpoint editing scoped to Ollama/llama-server.
  • src/renderer/components/Settings/SettingsView.tsx — Replaced Claude-only status copy with Claude/Codex built-in CLI checks and clarified model selection switches the active provider.
  • src/renderer/components/Onboarding/OnboardingWizard.tsx — Updated onboarding setup and ready summary to accept Claude CLI or Codex CLI as local built-in backends.
  • src/renderer/stores/providerStore.ts — Reloads settings after setDefault() so active provider state refreshes cleanly.
  • docs/architecture/RENDERER.md — Documented provider switching UI, provider store refresh behavior, and Codex-aware onboarding.
  • Renderer state flow: providerStore.setDefault() now reloads settingsStore after providers:setDefault.
  • No new IPC channels — existing providers:setDefault, settings:detectClaudeCli, and settings:detectCodexCli are reused.
Unify Settings model pickers

Primary and Secondary Model selection now render from the same available-provider model list exposed by models.getAvailable(). Secondary model selection is provider-neutral, persists only secondaryModel, and chapter audits now resolve that secondary model through the provider registry before falling back to the primary model.

  • src/renderer/components/Settings/SettingsView.tsx — Removed Claude-only secondary filtering, reused grouped available-provider model buttons for both pickers, added empty-list guidance, and clarified secondary model copy.
  • src/application/AuditService.ts — Resolves AppSettings.secondaryModel through IProviderRegistry for chapter audits before falling back to the primary model.
  • docs/architecture/RENDERER.md — Documented that both Settings model pickers use the same available-provider groups and only primary changes switch the active provider.
  • docs/architecture/APPLICATION.md — Documented provider-registry secondary model resolution for AuditService.auditChapter().
  • Application behavior change: AuditService.auditChapter() can route secondaryModel to any registered available provider through IProviderRegistry.
  • Renderer behavior change: SettingsView.tsx uses one grouped model list for primary and secondary pickers.
  • No new IPC channels or preload bridge methods.
Codex add-dir compatibility session program

Created a Forge session program for fixing the Codex provider runtime failure where codex exec rejects --add-dir. The program captures the screenshot bug report, scopes the fix to CodexCliClient, and requires infrastructure documentation plus changelog updates during implementation.

  • prompts/session-program/program-006/input-files/bug-report.md — Captures the screenshot symptoms, initial code pointers, and expected outcome.
  • prompts/session-program/program-006/SESSION-01.md — Defines the implementation session for conditional Codex CLI --add-dir support.
  • prompts/session-program/program-006/STATE.md — Tracks session status, scope, design decisions, and handoff notes.
  • prompts/session-program/program-006/MASTER.md — Defines the execution protocol, recovery steps, and final report requirements.

None — prompt program only, no source wiring changes.

Codex add-dir compatibility fix

src/infrastructure/codex-cli/CodexCliClient.ts now detects whether the installed Codex CLI supports --add-dir before spawning codex exec. Compatible installs keep the broader books-directory workspace, while older installs fall back to --cd-scoped access with a main-process warning instead of failing immediately.

  • src/infrastructure/codex-cli/CodexCliClient.ts — Added cached codex exec --help detection for --add-dir, conditional argument construction, and cache invalidation.
  • docs/architecture/INFRASTRUCTURE.md — Documented conditional Codex CLI --add-dir support and fallback behavior.
  • src/infrastructure/codex-cli/CodexCliClient.ts — Prevents chat requests from hard-failing on Codex CLI installations that reject --add-dir.
  • CLI invocation behavior: CodexCliClient now branches on local codex exec --help output before adding --add-dir <booksDir>.
  • No domain contracts, IPC channels, renderer stores, or schema changes.
Harden Codex CLI workspace fallback

./src/infrastructure/codex-cli/CodexCliClient.ts now validates the Codex CLI working directory before launch and reports the non---add-dir fallback as a stream status event instead of only writing a console warning.

  • ./src/infrastructure/codex-cli/CodexCliClient.ts — Added explicit workspace planning for Codex CLI launches, active-book fallback mode, and spawn logging that includes the selected workspace mode.
  • ./docs/architecture/INFRASTRUCTURE.md — Documented Codex CLI workspace planning, early directory validation, and fallback status diagnostics.
  • ./src/infrastructure/codex-cli/CodexCliClient.ts — Emits a clear error before spawn when the planned working directory is missing and emits an observable status event when older Codex CLI installs run with active-book-only workspace access.
  • None — no new dependencies, IPC channels, stores, or schema changes.
Ollama CLI runner

./src/infrastructure/ollama-cli/OllamaCliRunner.ts adds a focused wrapper around the local ollama command so later sessions can make local Ollama detection, model discovery, service startup, and smoke tests CLI-first without adding command parsing to the chat client.

  • ./src/infrastructure/ollama-cli/OllamaCliRunner.ts — Wraps ollama --version, ollama list, ollama show, ollama serve, and ollama run smoke tests with timeout-safe boolean/empty-list fallbacks.
  • ./src/infrastructure/ollama-cli/index.ts — Exports OllamaCliRunner and OllamaCliModel.
  • ./docs/architecture/INFRASTRUCTURE.md — Documents the Ollama CLI/API hybrid module and runner behavior.
  • ./docs/architecture/ARCHITECTURE.md — Lists ollama-cli, llama-server, and provider infrastructure files in the source tree and technology stack.
  • New infrastructure utility: OllamaCliRunner centralizes local ollama command invocation for future Ollama provider routing.
  • No new domain contracts, IPC channels, renderer stores, database schema changes, or composition-root wiring.
CLI-first Ollama provider routing

./src/infrastructure/ollama-cli/OllamaCodeClient.ts now treats local Ollama as a CLI-first provider for availability while preserving /api/chat for structured streaming and tool-use. Startup model discovery in ./src/main/index.ts uses OllamaCliRunner for local models and context windows, with HTTP discovery retained for remote Ollama endpoints.

  • ./src/infrastructure/ollama-cli/OllamaCodeClient.ts — Injects OllamaCliRunner, checks local CLI availability before API reachability, attempts ollama serve, and verifies the local API before chat streaming.
  • ./src/main/index.ts — Instantiates one OllamaCliRunner, passes it into OllamaCodeClient, uses CLI-backed model discovery for local Ollama, and keeps HTTP discovery for remote hosts.
  • ./docs/architecture/INFRASTRUCTURE.md — Documents local CLI-first availability, local API readiness before chat, and remote HTTP behavior.
  • ./docs/architecture/ARCHITECTURE.md — Updates the composition root dependency graph for OllamaCliRunner injection.
  • New dependency wiring: OllamaCodeClient receives OllamaCliRunner from ./src/main/index.ts.
  • Provider behavior change: local Ollama availability is based on CLI detection and model listing before API-only failure; remote Ollama remains HTTP-based.
  • No new IPC channels, renderer stores, database schema changes, or domain contracts.
CLI-first Ollama settings copy

Settings now presents Ollama as a local CLI-first provider. The Providers tab shows Ollama CLI status alongside Claude and Codex, explains that local models come from ollama pull model-name and ollama list, and keeps the endpoint field as an advanced override for remote Ollama hosts.

  • ./src/renderer/components/Settings/SettingsView.tsx — Added Ollama CLI to built-in CLI status, updated provider guidance, and clarified empty-model copy for local Ollama pulls.
  • ./src/renderer/components/Settings/ProviderSection.tsx — Renamed Ollama endpoint copy to an advanced override, added CLI discovery help, and labeled the provider badge as Ollama CLI.
  • ./docs/architecture/RENDERER.md — Documented Settings and ProviderSection CLI-first Ollama behavior.
  • Renderer behavior change: Settings now calls the existing settings:detectOllamaCli bridge from the built-in CLI status section.
  • No new IPC channels, preload methods, stores, database schema changes, or domain contracts.
Dashboards, Statistics, & Revision Queue Modal (7 sessions)

Full dashboard and statistics feature suite. Book overview dashboard shows pipeline progress, word counts per chapter, revision task completion, recent file activity, and project health. Writing statistics view powered by Recharts with token usage trends, per-agent/per-phase breakdowns, word count history, and cost estimates. Revision queue refactored from full-page view to a slide-over modal accessible from any view. New domain types, services, IPC channels, preload bridge endpoints, and Zustand stores.

  • src/domain/types.ts — BookDashboardData, BookStatistics, RecentFile, RevisionTaskItem, UsageTimePoint, AgentUsageBreakdown, PhaseUsageBreakdown, WordCountSnapshot types
  • src/domain/interfaces.ts — IDashboardService, IStatisticsService interfaces
  • src/application/DashboardService.ts — Book overview data aggregation
  • src/application/StatisticsService.ts — Usage trends, cost estimates
  • src/infrastructure/database/DatabaseService.ts — Dashboard & statistics queries
  • src/renderer/components/Dashboard/DashboardView.tsx — Book overview dashboard
  • src/renderer/components/Statistics/StatisticsView.tsx — Writing statistics with charts
  • src/renderer/components/RevisionQueue/RevisionQueueModal.tsx — Slide-over revision queue
  • src/renderer/stores/dashboardStore.ts, statisticsStore.ts, rightPanelStore.ts — New Zustand stores
  • src/main/index.ts — Instantiates DashboardService, StatisticsService
  • src/main/ipc/handlers.ts — Added dashboard:getData, statistics:get, statistics:recordSnapshot handlers
  • src/preload/index.ts — Added dashboard, statistics namespaces
  • src/renderer/components/Layout/AppLayout.tsx — Dashboard and statistics views in routing
  • src/renderer/stores/viewStore.ts — Added 'dashboard' and 'statistics' view types
Sidebar Bookshelf & 5-Tab FilesView

Restructured the UI: (1) FilesView from 2 tabs (Files | Motif Ledger) to 5 category tabs (Source, Chapters, Agents, Explorer, Motif Ledger), each rendering its panel directly. (2) Sidebar's BookSelector dropdown replaced with a permanently visible BookPanel with icon toolbar and scrollable book cards. New ImportChoiceModal for single-book vs. series import selection.

  • src/renderer/components/Sidebar/BookPanel.tsx — Persistent bookshelf with icon toolbar
  • src/renderer/components/Sidebar/ImportChoiceModal.tsx — Import type selection modal
  • src/renderer/components/Files/FilesView.tsx — 2-tab → 5-tab layout
  • src/renderer/components/Layout/Sidebar.tsx — BookSelector → BookPanel
  • src/renderer/components/Files/StructuredBrowser.tsx
  • src/renderer/components/Files/CollapsibleSection.tsx
  • src/renderer/components/Sidebar/FileTree.tsx
  • src/renderer/components/Sidebar/BookSelector.tsx
Batch Find & Replace

Bulk search-and-replace across all chapter draft files. Literal or regex patterns, per-chapter match preview with inline highlighting, selective file application, and automatic version snapshots for safe revert. Three-phase modal: input → preview → result.

  • src/domain/types.ts — FindReplaceOptions, FindReplaceMatchLocation, FindReplacePreviewItem, FindReplacePreviewResult, FindReplaceApplyResult types
  • src/domain/interfaces.ts — IFindReplaceService interface
  • src/application/FindReplaceService.ts — Preview + apply with version snapshots
  • src/renderer/components/Files/FindReplaceModal.tsx — Three-phase modal UI
  • src/main/ipc/handlers.ts — Added findReplace:preview, findReplace:apply handlers
  • src/preload/index.ts — Added findReplace namespace
  • src/renderer/components/Files/FilesHeader.tsx — Added Find & Replace button
Reading Mode, About.json Editor, Pipeline Panel, and misc improvements

Added ReadingModeView for distraction-free manuscript reading, AboutJsonViewer for editing book metadata in-app, PipelinePanel as a detachable right-side pipeline visualization, expanded QuickActions, improved Settings layout, enhanced Chat store streaming, and various UI polish across Build, CLI Activity, and Series components.

  • src/renderer/components/Reading/ReadingModeView.tsx
  • src/renderer/components/Files/AboutJsonViewer.tsx
  • src/renderer/components/RightPanel/PipelinePanel.tsx
  • src/renderer/stores/autoDraftStore.ts
Architecture Engine meta-prompt

New meta-prompt system for structured, multi-session codebase modifications. Includes full workflow documentation, configuration file (FORGE-CONFIG.md), and test runs across Opus 4.6 and Sonnet 4.6 with varying complexity levels.

  • prompts/meta/architecture-engine/architecture-engine.md — Full architecture engine prompt
  • prompts/meta/architecture-engine/readme.md — Explainer document
  • FORGE-CONFIG.md — Project-level Forge configuration
Add in-app Helper agent (floating help chat)

Added a non-creative Helper agent accessible via a floating chat bubble in the bottom-right corner of the app. The helper uses a comprehensive user guide as its knowledge base and answers questions about Novel Engine features, workflows, agents, troubleshooting, and more. The helper conversation persists across book switches and view navigation.

  • agents/HELPER.md — Helper agent system prompt
  • docs/USER_GUIDE.md — Comprehensive 16-section user guide
  • src/application/HelperService.ts — Implements IHelperService
  • src/renderer/stores/helperStore.ts — Zustand store for helper panel state
  • src/renderer/components/Helper/HelperButton.tsx — Floating help button
  • src/renderer/components/Helper/HelperPanel.tsx — Slide-up chat panel
  • src/renderer/components/Helper/HelperMessageList.tsx — Message list with streaming support
  • src/domain/types.ts — Added 'Helper' to AgentName, 'helper' to ConversationPurpose
  • src/domain/constants.ts — Added Helper to AGENT_REGISTRY
  • src/domain/interfaces.ts — Added IHelperService interface
  • src/main/index.ts — Instantiates HelperService
  • src/main/ipc/handlers.ts — Added 5 helper:* IPC channels
  • src/preload/index.ts — Added helper namespace to preload bridge
Onboarding Guide & Tooltips (5 sessions)

Added interactive guided tours and contextual tooltips. Three spotlight-based tours (Welcome, First Book, Pipeline Intro) with CSS clip-path cutouts, keyboard navigation, and auto-launch after onboarding. Tooltips on 14 components (sidebar buttons, pipeline phases, chat controls, window controls). Tour-aware tooltip suppression, accessibility attributes, and a help button in the sidebar.

  • src/renderer/components/common/Tooltip.tsx — Portal-based tooltip with arrow and animation
  • src/renderer/components/common/GuidedTourOverlay.tsx — Spotlight overlay with clip-path
  • src/renderer/hooks/useTooltip.ts — Positioning hook with viewport clamping
  • src/renderer/tours/tourDefinitions.ts — 3 tour definitions (16 total steps)
  • src/renderer/stores/tourStore.ts — Tour lifecycle management
  • src/domain/types.ts — Added TourId, TourStep, TourStepPlacement, TourState types; completedTours to AppSettings
  • 14 components gained tooltips and data-tour attributes
  • src/renderer/components/Settings/SettingsView.tsx — Added Guided Tours section with replay buttons
Series Import feature (4 sessions)

Added batch manuscript import with series grouping. Select multiple files, preview as ordered volumes, edit titles, reorder, skip individual volumes, and commit to a new or existing series. Composes existing ManuscriptImportService and SeriesService through a new SeriesImportService.

  • src/application/SeriesImportService.ts — Batch preview + sequential commit
  • src/renderer/stores/seriesImportStore.ts — Wizard state management
  • src/renderer/components/Import/ImportSeriesWizard.tsx — Full wizard modal
  • src/renderer/components/Import/VolumePreviewList.tsx — Volume list with editing
  • src/domain/types.ts — Added SeriesImportVolume, SeriesImportPreview, SeriesImportCommitConfig, SeriesImportResult types
  • src/domain/interfaces.ts — Added ISeriesImportService interface
  • src/main/ipc/handlers.ts — Added 3 import:series* handlers
  • src/preload/index.ts — Added seriesImport namespace
Series Bible feature (7 sessions)

Added series support — group multiple books into ordered series with a shared story bible. Series are file-based (JSON manifest + markdown bible), stored in {userData}/series/{slug}/. A reverse-lookup cache enables O(1) book→series resolution. The ContextBuilder injects the series bible path into agent system prompts. All 7 creative agents have series-bible.md in their readIfRelevant guidance.

  • src/infrastructure/series/SeriesService.ts — Full ISeriesService implementation
  • src/renderer/stores/seriesStore.ts — Zustand store with full CRUD
  • src/renderer/components/Series/SeriesModal.tsx — Series management modal
  • src/renderer/components/Series/SeriesForm.tsx — Create/edit form
  • src/renderer/components/Series/VolumeList.tsx — Volume ordering
  • src/renderer/components/Series/SeriesBibleEditor.tsx — Markdown editor
  • src/renderer/components/Sidebar/SeriesGroup.tsx — Collapsible sidebar group
  • src/domain/types.ts — Added SeriesVolume, SeriesMeta, SeriesSummary types
  • src/domain/interfaces.ts — Added ISeriesService interface (12 methods)
  • src/domain/constants.ts — Added seriesBible to FILE_MANIFEST_KEYS and read guidance
  • src/application/ChatService.ts — Added ISeriesService dependency
  • src/application/ContextBuilder.ts — Series bible path injection
  • src/main/ipc/handlers.ts — Added 11 series:* IPC handlers
  • src/preload/index.ts — Added series namespace (11 methods)
Full rebuild of GitHub Pages website (6 pages)

Rebuilt the complete 6-page GitHub Pages site in docs/. Landing page with hero, 7 agent cards, 14-phase pipeline, feature cards, getting started, published books. Architecture page with 5-layer diagram, tech stack, dependency graph, schema overview. Changelog page with all entries. Press page with pitch, differentiators, stats, quotes. Contact page with contribution guide. All pages share design tokens, sticky nav, responsive breakpoints.

README deep update from source code analysis

Comprehensive rewrite of `README.md` based on a full audit of every source file across all five architecture layers. Every feature, type, service, pipeline phase, agent, and IPC channel was verified against actual code. New features added: Manuscript Import, Source Generation, CLI Activity Monitor, Modal Chat, File Version History, File Watchers, O...

  • README.md — Full rewrite. Verified all 7 agents against constants.ts. Verified all 14 pipeline phases against PipelineService.ts. Verified all npm scripts against package.json. Verified tech stack versions. Updated src/ tree to include import/ChapterDetector.ts, ManuscriptImportService.ts, SourceGenerationService.ts, Import/ components, importStore.ts. Added 8 new Key Features sections (Manuscript Import, CLI Activity Monitor, Modal Chat, File Version History, File Watchers, OS Notifications, Book Management, Multi-Model Provider Support, Chapter Validation). Corrected store count to 17. Corrected application service listing. Preserved Dedication, Book list, and Testers Needed sections verbatim.
CLI-based motif ledger schema normalization

Replaced the hardcoded field-mapping normalizers in `MotifLedgerService` with a CLI-based normalization step. When `load()` detects a non-canonical JSON shape (agent-written fields like `associatedCharacters`, object-typed `firstAppearance`, `plant`/`payoff` foreshadow objects, etc.), it sends the raw JSON to a Sonnet CLI call with a structured pro...

  • src/application/MotifLedgerService.ts — Added IProviderRegistry dependency. Replaced per-type normalizer functions with isCanonicalShape() shape detection + normalizeViaCli() CLI call. Added parseLedgerFromCanonical() as best-effort fallback. Added setNormalizationCallback() for progress events. load() now saves normalized data back to disk.
  • src/main/index.ts — Passes providerRegistry to MotifLedgerService constructor. Registers normalization callback that broadcasts motifLedger:normalizing events to all renderer windows.
  • src/preload/index.ts — Added onNormalizing() event listener to motifLedger namespace.
  • src/renderer/stores/motifLedgerStore.ts — Added isNormalizing state and setNormalizing() action.
  • src/renderer/components/MotifLedger/MotifLedgerView.tsx — Subscribes to motifLedger:normalizing push events. Shows animated spinner with "Normalizing ledger format via AI..." message during CLI normalization.
Manuscript Import feature (6 sessions)

Added the ability to import an existing manuscript (.md, .markdown, .txt, or .docx) into Novel Engine. The import wizard detects chapter boundaries via pattern matching, lets the user review/rename/merge chapters, then creates the full book directory structure with status set to `first-draft`. After import, the user can optionally trigger multi-age...

  • src/domain/types.ts — Added ImportSourceFormat, DetectedChapter, ImportPreview, ImportCommitConfig, ImportResult, SourceGenerationStep, SourceGenerationEvent types
  • src/domain/interfaces.ts — Added IManuscriptImportService and ISourceGenerationService interfaces
  • src/application/import/ChapterDetector.ts — Pure utility: detects chapter boundaries by heading patterns, "Chapter N" patterns, or fallback single-chapter. Includes ambiguity detection for uneven splits and short documents.
  • src/application/ManuscriptImportService.ts — Implements IManuscriptImportService. Reads files, converts DOCX via Pandoc, runs chapter detection, commits by creating book structure.
  • src/application/SourceGenerationService.ts — Implements ISourceGenerationService. Runs 4 sequential agent calls (Spark pitch, Verity outline+bible, Verity voice, Verity motif) with per-step progress events.
  • src/renderer/stores/importStore.ts — Zustand store managing the multi-step import wizard state machine (idle → loading → preview → importing → success → generating → generated).
  • src/renderer/components/Import/ImportWizard.tsx — Modal wizard with step-based rendering: file analysis, chapter preview with editing, import progress, success, source generation progress.
  • src/renderer/components/Import/ChapterPreviewList.tsx — Scrollable chapter list with inline rename, merge, and remove controls.
  • src/main/index.ts — Instantiates ManuscriptImportService and SourceGenerationService, passes to registerIpcHandlers
  • src/main/ipc/handlers.ts — Added import:selectFile, import:preview, import:commit, import:generateSources handlers
  • src/preload/index.ts — Added window.novelEngine.import namespace with selectFile, preview, commit, generateSources, onGenerationProgress
  • src/renderer/components/Sidebar/BookSelector.tsx — Replaced single "New Book" button with "New Book" + "Import" side-by-side. Renders ImportWizard modal.
Update GitHub Pages website with all latest features

Rebuilt all 6 GitHub Pages HTML files to reflect the current state of the codebase. Added multi-model provider support, file version history, and catalog export to landing page feature cards. Updated architecture page with `providers/` infrastructure module, `file_versions` and `schema_version` tables (7 total), 130 source files, 16 stores, and com...

  • docs/index.html — Added Key Features section (9 cards: Pitch Room, Voice Profile, Auto-Draft, Verity Audit, Motif Ledger, Revision Queue, Version History, Multi-Model, Build & Export). Updated subtitle to mention multi-model. Updated export description for catalog export.
  • docs/architecture.html — Added providers/ to infrastructure modules. Added file_versions and schema_version to schema table. Updated file count to 130, store count to 16. Added ProviderRegistry and VersionService to dependency graph. Added multi-model and version history to design decisions. Updated source tree with all current files.
  • docs/changelog.html — Full rebuild with all 39 entries (was 21). Updated stats: entries 21→39. Added all 2026-03-28 entries (18 new). Expanded highlight reel with version history and multi-model features.
  • docs/press.html — Updated stats: 130 files, 16 stores, 7 tables, 80+ IPC channels. Added "Multi-model support" differentiator card. Updated source file count in "Open source" card.
  • docs/contact.html — Updated architecture rules to include barrel export requirement. Minor copy refinements.
Comprehensive README rewrite

Rewrote `README.md` to accurately reflect the current state of the codebase. Updated file count from 121 to 130. Added documentation for three features missing from the previous README: File Version History (VersionService, VersionHistoryPanel, DiffViewer, versionStore), Multi-Model Provider Support (ProviderRegistry, OpenAiCompatibleProvider, Prov...

  • README.md — Full rewrite per prompts/meta/readme-deep-update.md spec. All sections verified against source code.
Multi-model providers: renderer UI (SESSION-07)

Added provider management UI to Settings. New `providerStore` (Zustand) manages provider state. New `ProviderSection` component shows provider cards with status indicators, test connectivity, add/remove/toggle. Updated `ModelSelectionSection` to group models by provider with "Text only" badges for non-tool-use models. Selecting a model from a diffe...

  • src/renderer/stores/providerStore.ts — Zustand store for provider CRUD, status checking
  • src/renderer/components/Settings/ProviderSection.tsx — Provider management: cards, status dots, add form, enable/disable/remove
  • src/renderer/components/Settings/SettingsView.tsx — Added ProviderSection between CLI status and model selection. Rewrote ModelSelectionSection to group models by provider, show "Text only" badge, and update activeProviderId on cross-provider model selection.
Multi-model providers: IPC channels & preload bridge (SESSION-06)

Exposed provider management to the renderer through 7 new `providers:*` IPC channels and a `window.novelEngine.providers` preload namespace. Updated `settings:getAvailableModels` to return `ModelInfo[]` from the registry instead of the deprecated static `AVAILABLE_MODELS` array.

  • src/main/ipc/handlers.ts — Added 7 providers:* handlers (list, getConfig, add, update, remove, checkStatus, setDefault). Updated settings:getAvailableModels to use providerRegistry.listAllModels(). Added providerRegistry to services param.
  • src/preload/index.ts — Added providers namespace with 7 bridge methods. Updated models.getAvailable return type to ModelInfo[].
  • src/main/index.ts — Added providerRegistry to registerIpcHandlers call.
Multi-model providers: service migration + composition root (SESSION-05)

Migrated all 6 application services from `IClaudeClient` to `IProviderRegistry`. Rewired the composition root to instantiate `ProviderRegistry`, register the built-in Claude CLI provider, and initialize any user-configured OpenAI-compatible providers from settings. No behavioral changes — all services use the same `sendMessage`/`abortStream` interf...

  • src/application/ChatService.tsIClaudeClientIProviderRegistry, this.claudethis.providers, isAvailable() routes through getDefaultProvider()
  • src/application/HotTakeService.tsIClaudeClientIProviderRegistry
  • src/application/PitchRoomService.tsIClaudeClientIProviderRegistry
  • src/application/AdhocRevisionService.tsIClaudeClientIProviderRegistry
  • src/application/AuditService.tsIClaudeClientIProviderRegistry
  • src/application/RevisionQueueService.tsIClaudeClientIProviderRegistry
  • src/main/index.ts — Added ProviderRegistry + OpenAiCompatibleProvider setup between infra and service instantiation. Removed redundant settings.load() call.
Multi-model providers: OpenAI-compatible provider (SESSION-04)

Created `OpenAiCompatibleProvider` — the universal BYOK/self-hosted provider. Implements `IModelProvider` using built-in `fetch` + SSE streaming. Works with any OpenAI Chat Completions-compatible endpoint. No tool-use — text completion + streaming only. Token counts estimated at 4 chars/token.

  • src/infrastructure/providers/OpenAiCompatibleProvider.ts — SSE streaming, AbortController cancellation, runtime API key/URL update, /v1/models health check
  • src/infrastructure/providers/index.ts — Added OpenAiCompatibleProvider export
Multi-model providers: ProviderRegistry infrastructure (SESSION-03)

Created `ProviderRegistry` — the central hub that manages all model providers, routes model requests to the correct provider, and persists configurations. Implements `IProviderRegistry` from domain. Uses a reverse model index for O(1) model→provider lookups. Protects built-in providers from deletion and immutable config fields from mutation.

  • src/infrastructure/providers/ProviderRegistry.ts — Implements IProviderRegistry. Model routing, provider CRUD, config persistence to settings.
  • src/infrastructure/providers/index.ts — Barrel export
Multi-model providers: ClaudeCodeClient implements IModelProvider (SESSION-02)

Made `ClaudeCodeClient` implement `IModelProvider` in addition to `IClaudeClient`. Added `providerId` (`'claude-cli'`) and `capabilities` (`['text-completion', 'tool-use', 'thinking', 'streaming']`) readonly properties. No behavioral changes — purely additive interface conformance.

  • src/infrastructure/claude-cli/ClaudeCodeClient.ts — Now implements both IClaudeClient and IModelProvider. Added providerId and capabilities properties.
Multi-model providers: domain types, interfaces, constants (SESSION-01)

Foundation for pluggable AI provider architecture. Added provider-related types (`ProviderId`, `ProviderType`, `ProviderCapability`, `ProviderConfig`, `ModelInfo`, `ProviderStatus`), new interfaces (`IModelProvider`, `IProviderRegistry`), and built-in provider constants. `AppSettings` extended with `providers` and `activeProviderId`. `IClaudeClient...

  • src/domain/types.ts — Added 6 provider types (ProviderId, ProviderType, ProviderCapability, ProviderStatus, ProviderConfig, ModelInfo). Extended AppSettings with providers: ProviderConfig[] and activeProviderId: ProviderId.
  • src/domain/interfaces.ts — Added IModelProvider interface (same shape as IClaudeClient plus providerId and capabilities). Added IProviderRegistry interface (router + CRUD + convenience delegates). Deprecated IClaudeClient with JSDoc.
  • src/domain/constants.ts — Added CLAUDE_CLI_PROVIDER_ID, OPENCODE_CLI_PROVIDER_ID, BUILT_IN_PROVIDER_CONFIGS. Deprecated AVAILABLE_MODELS with JSDoc. Updated DEFAULT_SETTINGS with provider fields. Reordered declarations to avoid forward-reference errors.
Add catalog export (ZIP all books)

Added the ability to export the entire book catalog as a single ZIP archive from the Settings view. A new `catalog:exportZip` IPC channel zips the full `books/` directory using `archiver` (already a dependency), and a new `CatalogExportSection` component in SettingsView provides the trigger button with success feedback.

  • src/main/ipc/handlers.ts — Added catalog:exportZip handler between build and usage sections. Zips paths.booksDir into a user-chosen location with default filename novel-engine-catalog-YYYY-MM-DD.zip.
  • src/preload/index.ts — Added catalog namespace with exportZip() bridge method.
  • src/renderer/components/Settings/SettingsView.tsx — Added CatalogExportSection component between UsageSection and AuthorProfileSection. Shows export button, disabled state during export, and clickable "Saved to:" path on success.
Integrate version history into all file views

Integrated the `VersionHistoryPanel` into every place files are surfaced in the UI. FileEditor and FilesView reader mode now have a "History" toggle button that opens a split-panel with the version timeline on the right. SourcePanel, ChaptersPanel, and AgentOutputPanel show clock icon buttons on hover that navigate to the file's reader view for his...

Add VersionHistoryPanel component

Created the `VersionHistoryPanel` — a slide-over panel that displays a file's version history as a timeline with source badges (user/agent/revert), relative timestamps, and byte sizes. Clicking a version computes and displays the diff. Each version entry has a "Revert to this version" button with inline confirmation. Supports paginated loading for ...

  • src/renderer/components/Files/VersionHistoryPanel.tsx — Full version history UI: timeline with VersionEntry sub-component, integrated DiffViewer, revert with confirmation, pagination, error handling, empty states.
Add version store and DiffViewer component

Created `versionStore` Zustand store with paginated history loading, version selection with auto-diff computation, revert, and error handling. Created `DiffViewer` component that renders `FileDiff` as color-coded unified diff with dual line numbers, hunk headers, and addition/deletion summary bar.

  • src/renderer/stores/versionStore.ts — Zustand store with 6 actions: loadHistory, loadMoreHistory, selectVersion, clearSelection, revertToVersion, reset. Paginated at 30 items per page.
  • src/renderer/components/Files/DiffViewer.tsx — Renders FileDiff with green (additions), red (deletions), neutral (context) line coloring. Sub-components: HunkHeader, DiffLineRow, DiffSummary.
Wire VersionService into IPC, preload bridge, and composition root

Connected `VersionService` to the Electron app. Instantiated in composition root, exposed through 6 new IPC channels (`versions:*`), and added to the preload bridge as `window.novelEngine.versions`. Auto-snapshot hooks added at 5 capture points: `files:write` (user edits), `chat:send` (pipeline agent writes), `hot-take:start`, `adhoc-revision:start...

  • src/main/index.ts — Import and instantiate VersionService. Add startup pruning loop. Add fallback snapshot to BookWatcher callback. Pass version to registerIpcHandlers.
  • src/main/ipc/handlers.ts — Add IVersionService to services param. Add snapshotChangedFiles helper. Add 6 versions:* IPC handlers. Modify files:write to auto-snapshot. Add snapshot hooks to chat:send, hot-take:start, adhoc-revision:start, and revision queue event forwarding.
  • src/preload/index.ts — Add versions namespace with 6 methods: getHistory, getVersion, getDiff, revert, getCount, snapshot. Add type imports for FileDiff, FileVersion, FileVersionSource, FileVersionSummary.
Add VersionService implementation with diff computation

Created `VersionService` in the application layer, implementing all 8 methods of `IVersionService`. Installed `diff` npm package for structured diff computation using `structuredPatch()`. The service handles snapshot dedup via SHA-256 hashing, file extension filtering (`.md`/`.json` only), structured diff output with line numbers, and version pruni...

  • src/application/VersionService.ts — Implements IVersionService. Depends on IDatabaseService and IFileSystemService via DI. Uses node:crypto for hashing and diff package for structured patches.
Add database migration and version repository for content version control

Added SQLite migration v2 creating the `file_versions` table with composite indexes, and extended `IDatabaseService` and `DatabaseService` with 7 new methods for version CRUD: insert, get, list, count, delete-beyond-limit, and get-versioned-paths. All queries use parameterized prepared statements with explicit snake_case→camelCase mapping.

  • src/domain/interfaces.ts — Extended IDatabaseService with 7 new methods in a // File Versions section: insertFileVersion, getFileVersion, getLatestFileVersion, listFileVersions, countFileVersions, deleteFileVersionsBeyondLimit, getVersionedFilePaths
  • src/infrastructure/database/migrations.ts — Added migration v2: creates file_versions table with idx_file_versions_lookup and idx_file_versions_hash indexes
  • src/infrastructure/database/DatabaseService.ts — Implemented all 7 new IDatabaseService methods. Added 6 prepared statements and 2 private row mappers (mapFileVersion, mapFileVersionSummary). Added FileVersion, FileVersionSource, FileVersionSummary type imports.
Add domain types and interface for content version control

Added version control domain types (`FileVersion`, `FileVersionSummary`, `DiffHunk`, `DiffLine`, `FileDiff`, `FileVersionSource`, `DiffLineType`) and the `IVersionService` interface to `src/domain/`. This is the foundation for the content-version-control feature — snapshot-per-write model with SHA-256 dedup, structured diffs, and revert capability.

  • src/domain/types.ts — Added 7 version control types after the File System section: FileVersionSource, FileVersion, FileVersionSummary, DiffLineType, DiffLine, DiffHunk, FileDiff
  • src/domain/interfaces.ts — Added IVersionService interface with 8 methods: snapshotFile, snapshotContent, getHistory, getVersion, getDiff, revertToVersion, getVersionCount, pruneVersions. Added 4 new type imports.
Add intake meta-prompt for document-to-session decomposition

Created `prompts/meta/intake.md` — a generic meta-prompt that takes any number of attached documents (feature specs, research, design docs, bug reports, RFCs, raw ideas), analyzes them against the current codebase, and decomposes the work into ordered session prompts under `prompts/feature/{feature-name}/`. Generates a complete build-out directory ...

  • prompts/meta/intake.md — Document intake and feature decomposition prompt. Parses attached documents, researches current codebase, decomposes into layered sessions, generates MASTER/STATE/SESSION files.
Fix MotifLedgerService data loss: remove auto-writeback, harden JSON repair

The initial JSON repair implementation (2026-03-27) auto-wrote repaired data back to disk on load. The `repairJson()` regex matched `}{` patterns inside string values (not just between array elements), corrupting the parsed structure. The writeback then overwrote the 133KB original with an empty/corrupt version — total data loss. Fixed by: (1) remo...

  • src/application/MotifLedgerService.ts — Removed auto-writeback of repaired JSON on load. Rewrote repairJson() from global regex to line-by-line structural repair (only matches lines that are purely } or ]). Simplified safeParse() return type (removed repaired flag).
Fix Motif Ledger Audit Log crash from agent-written data shape mismatch

The Audit Log tab in the Motif Ledger crashed with a `TypeError` when clicking it. Root cause: the MOTIF-AUDIT agent writes audit log records with fields `{ chapter, date, findings }`, but the UI expects `{ id, chapterSlug, auditedAt, entriesAdded, entriesUpdated, notes }`. The sort on line 33 of `AuditLogTab.tsx` called `.localeCompare()` on `unde...

  • src/application/MotifLedgerService.ts — Added normalizeAuditRecord() to map agent field names (chapterchapterSlug, dateauditedAt, findingsnotes) and fill missing fields (id, entriesAdded, entriesUpdated). Also added normalizeSystem() (fills missing components array) and normalizeEntry() (fills missing phrase field). Added safeArray() helper to guard against non-array values.
  • src/renderer/components/MotifLedger/AuditLogTab.tsx — Sort comparison now uses (b.auditedAt ?? '').localeCompare(a.auditedAt ?? '') as a defensive fallback.
Fix Hot Take button not appearing after chapters are created mid-session

`HotTakeButton` only re-checked for chapters when `activeSlug` changed, not when files were created on disk. After auto-drafting chapters, the button stayed hidden until app restart. Fixed by subscribing to `fileChangeStore.revision` — the same pattern `AdhocRevisionButton` already used.

  • src/renderer/components/Sidebar/HotTakeButton.tsx — Added fileRevision from useFileChangeStore to the useEffect dependency array so the chapter existence check re-runs when files change on disk.
Update GitHub Pages website with latest changelog entries

Updated `docs/changelog.html` with 3 new entries added since the last website build: r003 race condition/stream architecture fixes, MotifLedgerView crash fix, and BookSelector/SystemsTab crash fix. Updated stats (18 → 21 entries, added bug fix count), expanded the Quality & Stability highlight reel section. All other pages remain current — no new f...

  • docs/changelog.html — Added 3 new entries at top (r003 fixes, MotifLedgerView crash, BookSelector/SystemsTab crash). Updated stats: entries 18→21, replaced "Architecture Changes" stat with "Bug Fixes: 20+". Added r003 and MotifLedger crash fixes to Quality & Stability highlights.
Fix nested button DOM warning and SystemsTab crash on undefined components

Fixed three console errors: (1) React `validateDOMNesting` warning from a `<button>` nested inside a `<button>` in BookSelector — the outer dropdown trigger is now a `<div role="button">` with keyboard support; (2) `TypeError` crash in SystemsTab when `sys.components` is `undefined` from partially-populated ledger JSON on disk — added `?? []` fallb...

  • src/renderer/components/Sidebar/BookSelector.tsx — Changed outer dropdown trigger from <button> to <div role="button"> with tabIndex and onKeyDown, eliminating the nested-button DOM warning.
  • src/renderer/components/MotifLedger/SystemsTab.tsx — Guarded sys.components with ?? [] in startEdit() (line 42), render loop (line 165), and iteration (line 167) to prevent crash when ledger JSON has systems with missing components field.
Fix crash on startup: MotifLedgerView tab count reads undefined array

Fixed a `TypeError: Cannot read properties of undefined (reading 'length')` crash on production app startup. The `MotifLedgerView` tab-count computation assumed all ledger array keys exist when the ledger object is truthy, but partial/empty ledger JSON files leave some keys undefined. Since all views are rendered simultaneously (hidden with CSS), t...

  • src/renderer/components/MotifLedger/MotifLedgerView.tsx — Tab count computation now guards against undefined ledger arrays with optional chaining (arr?.length ?? 0) instead of casting to unknown[] and accessing .length directly.
Issue fixes r003: Race conditions, error handling, stream architecture

Executed 8 fix prompts from the r003 evaluation. Fixed critical race conditions in concurrent stream management (book switching kills background streams, singleton diagnostics/changedFiles overwritten by concurrent calls), improved error handling in auto-draft audit failures, added proper stream listener lifecycle to pitchRoomStore, enhanced EPIPE ...

  • src/renderer/stores/chatStore.ts — Added _streamOrigin discriminator ('self'|'external'|null). switchBook() only aborts 'self' streams, preserving background auto-draft/hot-take/revision streams.
  • src/renderer/stores/autoDraftStore.ts — Added skippedAudits: string[] to AutoDraftSession. Audit/fix catch block now pauses the loop instead of silently continuing. Logs skipped audits on session completion.
  • src/application/ChatService.ts — Replaced lastDiagnostics singleton with diagnosticsMap: Map<string, ContextDiagnostics> keyed by conversationId (max 20 entries). getLastDiagnostics() accepts optional conversationId. sendMessage() now returns { changedFiles: string[] }. Removed resetChangedFiles() call and getLastChangedFiles() method.
  • src/application/StreamManager.ts — Removed lastChangedFiles singleton, resetChangedFiles(), and getLastChangedFiles(). Each stream tracks its own changedFiles via closure. startStream() returns getChangedFiles() getter.
  • src/domain/interfaces.ts — Updated IChatService.sendMessage return type to Promise<{ changedFiles: string[] }>. Updated getLastDiagnostics to accept optional conversationId. Removed getLastChangedFiles(). Added persistStreamEventBatch() to IDatabaseService.
  • src/domain/types.ts — Added StreamEventSource type union for event origin discrimination.
  • src/main/ipc/handlers.tschat:send reads changedFiles from sendMessage() return. adhoc-revision:start captures changedFiles from stream events. All broadcast sites inject source: StreamEventSource. context:getLastDiagnostics passes conversationId. Verity broadcastVerityEvent now accepts source parameter.
  • src/preload/index.tscontext.getLastDiagnostics accepts optional conversationId.
  • ...and 7 more
Build multi-page GitHub Pages website

Built a full 6-page GitHub Pages website in `docs/`. Migrated the existing 10-book evaluation from `docs/index.html` to `docs/evaluation.html` (content preserved verbatim) and replaced `docs/index.html` with a new landing page. Created 4 additional pages: architecture (technical docs for developers), changelog (formatted project history), press kit...

  • docs/index.html — Landing page: hero, 7 agent cards, 14-phase pipeline visualization, getting started guide, screenshots, published books grid
  • docs/evaluation.html — 10-book dual AI evaluation (migrated from old index.html with nav/footer added)
  • docs/architecture.html — Technical architecture: 5-layer diagram, tech stack, service dependency graph, design decisions, database schema, source tree, contributing guide
  • docs/changelog.html — Formatted changelog with summary stats, highlight reel, collapsible entries for all 18 changelog entries
  • docs/press.html — Press kit: quotable pitch, 7 differentiator cards, published works, by-the-numbers stats, quotable lines, asset links
  • docs/contact.html — Contact info, contribution guide with architecture rules, bug reporting template, testers-wanted callout with platform badges
  • docs/index.html — Replaced single-page evaluation site with full landing page (evaluation content moved to evaluation.html)
README deep update: comprehensive rewrite from codebase analysis

Rewrote `README.md` from a full analysis of every source file. Updated file count (102 → 121), corrected agent thinking budgets (Spark 4K not 8K), added Verity Audit Pipeline and Motif Ledger as documented features, updated source tree to reflect `streamHandler.ts` (renamed from `streamRouter.ts`), `migrations.ts`, `statusMessages.ts`, `MotifLedger...

  • README.md — Full rewrite. Updated source tree, file count, feature descriptions, agent registry, custom-agents directory listing. Added Verity Audit Pipeline, Motif Ledger, and phase-aware Verity prompt sections. Corrected Spark thinking budget from 8K to 4K. Updated store count to 14. Added all missing component groups and application services.
Issue fixes r002: 9 bug fixes from repo evaluation

Executed all 9 fix prompts from `prompts/arch/r002/` addressing findings from the repo evaluation. Fixed error path cleanup (stale `_activeCallId` + orphan temp messages), revision event forwarding missing `conversationId`, missing `callStart` events for Verity audit/fix calls, duplicate polling intervals in cliActivityStore recovery, silent error ...

  • src/renderer/stores/streamHandler.ts — Shared createStreamHandler() factory encapsulating guard logic and event dispatch for chatStore, modalChatStore, pitchRoomStore
  • src/renderer/stores/chatStore.ts — Error catch clears _activeCallId and filters temp message; _handleStreamEvent delegates to shared handler; switchBook() aborts active stream before clearing state
  • src/renderer/stores/modalChatStore.ts — Error catch clears _activeCallId and filters temp message; _handleStreamEvent delegates to shared handler; added _closeRequested flag for close-on-stream-end UX
  • src/renderer/stores/pitchRoomStore.ts — Error catch clears _activeCallId and filters temp message; _handleStreamEvent delegates to shared handler
  • src/renderer/stores/cliActivityStore.ts — Recovery polling uses module-level timer refs to prevent duplicate intervals
  • src/domain/types.tsRevisionQueueEvent session:streamEvent variant now includes optional conversationId
  • src/application/RevisionQueueService.ts — Includes conversationId when emitting session:streamEvent
  • src/main/ipc/handlers.ts — Forwards conversationId in revision event bridge; added emitVerityCallStart() helper + 4 call sites for Verity audit/fix/motif-audit
  • src/infrastructure/claude-cli/ClaudeCodeClient.ts — EPIPE logged with console.warn; DB persistence errors logged on first failure per session; 500KB system prompt size guard before spawn
Repo evaluation: comprehensive audit of chat bleed, activity monitor, and code quality

Executed `prompts/standard/repo-eval.md` — a full audit of stream event isolation, CLI activity monitor coverage, and latent bugs. Traced event flows end-to-end across all 10+ surfaces that spawn CLI calls. Found no critical chat bleed issues; the callId-per-send pattern is robust. Identified 12 findings across medium/low severity: missing `_active...

  • issues.md — Full repo evaluation report with 12 findings, coverage matrix, and positive observations
Add update-website standard prompt (multi-page)

Created `prompts/standard/update-website.md` — a meta-prompt that reads the changelog, architecture docs, README, and existing GitHub Pages site assets, then builds a full multi-page GitHub Pages website in `docs/`. Produces 6 HTML pages: landing (index), 10-book evaluation (migrated from old index.html), architecture, changelog, press kit, and con...

  • prompts/standard/update-website.md — 8-step prompt: collect source material → define site map (6 pages) → spec each page → design system tokens → content tone rules → screenshot strategy → build all pages → verify 16-point checklist
Add address-issues standard prompt

Created `prompts/standard/address-issues.md` — a meta-prompt that reads `issues.md` (output of `repo-eval.md`), decomposes findings into numbered `FIX-NN.md` prompts in the next available `prompts/arch/r###/` revision, and generates `MASTER.md` + `STATE.md` for loop execution.

  • prompts/standard/address-issues.md — 7-step prompt: parse issues → group by affinity → order by severity → generate fix prompts → generate STATE.md → generate MASTER.md → summary report
ARCH-12: Audit and fix silent error swallowing

Audited all 115 bare `catch {}` blocks across the codebase. Added explanatory comments to 12 uncommented catches in priority files (SettingsService, FileSystemService, MotifLedgerService, RevisionQueueService, bootstrap, handlers). Found that 82 catches already had comments, and the remaining 33 are clearly ENOENT-expected patterns or already log w...

  • src/infrastructure/settings/SettingsService.ts — Added comments to 2 catches (settings load, CLI detection)
  • src/infrastructure/filesystem/FileSystemService.ts — Added comments to 2 catches (books dir, active book)
  • src/application/MotifLedgerService.ts — Added comments to 2 catches (load, getUnauditedChapters)
  • src/application/RevisionQueueService.ts — Added comments to 2 catches (readCache, readState)
  • src/main/bootstrap.ts — Added comment to 1 catch (needsBootstrap)
  • src/main/ipc/handlers.ts — Added comment to 1 catch (author profile load)
ARCH-09: Slim ChatService to router

Final cleanup of ChatService after all extractions. Removed unused `IAuditService` and `IUsageService` dependencies (StreamManager handles usage recording). ChatService is now a clean router at 403 lines (down from 1,218 — 67% reduction).

  • src/application/ChatService.ts — Removed audit: IAuditService and usage: IUsageService constructor params (no longer directly needed). Final line count: 403.
  • src/main/index.ts — Updated ChatService constructor call.
ARCH-07 & ARCH-08: Extract HotTakeService and AdhocRevisionService

Extracted `handleHotTake()` into HotTakeService and `handleAdhocRevision()` into AdhocRevisionService. Both implement domain interfaces. ChatService now delegates all three special-purpose conversation flows (pitch-room, hot-take, adhoc-revision) to their own services.

  • src/application/HotTakeService.tsHotTakeService implementing IHotTakeService (98 lines)
  • src/application/AdhocRevisionService.tsAdhocRevisionService implementing IAdhocRevisionService (105 lines)
  • src/domain/interfaces.tsIHotTakeService, IAdhocRevisionService interfaces
  • src/application/ChatService.ts — Removed handleHotTake() and handleAdhocRevision(). Added hotTake: IHotTakeService and adhocRevision: IAdhocRevisionService constructor params. ChatService: 559→407 lines.
  • src/main/index.ts — Instantiate HotTakeService and AdhocRevisionService, inject into ChatService.
ARCH-06: Extract PitchRoomService from ChatService

Extracted `handlePitchRoomMessage()` from ChatService into a new `PitchRoomService` behind an `IPitchRoomService` interface. StreamManager is now instantiated externally in main/index.ts and shared between ChatService and PitchRoomService (required for correct active-stream tracking).

  • src/application/PitchRoomService.tsPitchRoomService class implementing IPitchRoomService (109 lines)
  • src/domain/interfaces.tsIPitchRoomService interface (handleMessage)
  • src/application/ChatService.ts — Removed handlePitchRoomMessage(). Added pitchRoom: IPitchRoomService and streamManager: StreamManager constructor params. StreamManager no longer created internally. ChatService: 637→559 lines.
  • src/main/index.ts — StreamManager created externally and injected into both ChatService and PitchRoomService. PitchRoomService instantiated and passed to ChatService.
ARCH-05: Extract AuditService from ChatService

Extracted `auditChapter()`, `fixChapter()`, and `runMotifAudit()` from ChatService into a new `AuditService` behind an `IAuditService` interface. These three methods form a cohesive audit-and-fix subsystem. ChatService's `handleAdhocRevision` now delegates to `this.audit.runMotifAudit()`. IPC handlers route audit channels directly to the audit serv...

  • src/application/AuditService.tsAuditService class implementing IAuditService (350 lines)
  • src/domain/interfaces.tsIAuditService interface (auditChapter, fixChapter, runMotifAudit)
  • src/application/ChatService.ts — Removed 3 method implementations (~320 lines). Added audit: IAuditService constructor param. ChatService reduced from 1,121→637 lines.
  • src/domain/interfaces.ts — Moved audit methods from IChatService to new IAuditService
  • src/main/ipc/handlers.ts — Added audit: IAuditService to services param. Routed verity:auditChapter, verity:fixChapter, verity:fixChapterWithAudit, verity:runMotifAudit to services.audit
  • src/main/index.ts — Instantiate AuditService, inject into ChatService and registerIpcHandlers
ARCH-04: Extract StreamManager from ChatService

Extracted `StreamManager` and `resolveThinkingBudget()` from ChatService. StreamManager owns the active-streams map and the repetitive register → accumulate → save → record usage → cleanup lifecycle. All four manual stream patterns in ChatService (`sendMessage`, `handleHotTake`, `handleAdhocRevision`, `handlePitchRoomMessage`) now delegate to `Stre...

  • src/application/StreamManager.tsStreamManager class: startStream(), resetChangedFiles(), getActiveStream(), getActiveStreamForBook(), getLastChangedFiles(), cleanupAbortedStream(), cleanupErroredStream()
  • src/application/thinkingBudget.tsresolveThinkingBudget() pure function (per-message override → global override → per-agent default → undefined)
  • src/application/ChatService.ts — Removed private activeStreams and private lastChangedFiles fields. Added private streamManager: StreamManager. All four stream handler methods now use streamManager.startStream() instead of manual buffer/cleanup patterns. Replaced inline resolveThinkingBudget with import from ./thinkingBudget.
ARCH-03: Add IChatService and IUsageService interfaces

Added `IChatService` (14 methods) and `IUsageService` (3 methods) interfaces to the domain layer. The IPC handlers now depend on these abstractions instead of concrete application classes. ChatService's constructor now takes `IUsageService` instead of `UsageService`. Both concrete classes have `implements` clauses.

  • src/domain/interfaces.tsIChatService interface (sendMessage, createConversation, getConversations, getMessages, abortStream, getActiveStream, getActiveStreamForBook, getLastDiagnostics, getLastChangedFiles, isCliIdle, recoverOrphanedSessions, getRecoveredOrphans, auditChapter, fixChapter, runMotifAudit)
  • src/domain/interfaces.tsIUsageService interface (recordUsage, getSummary, getByConversation)
  • src/domain/interfaces.ts — Added imports: ActiveStreamInfo, AuditResult, ContextDiagnostics, ConversationPurpose
  • src/application/ChatService.tsimplements IChatService. Constructor param usage: UsageServiceusage: IUsageService. Removed concrete UsageService import.
  • src/application/UsageService.tsimplements IUsageService
  • src/main/ipc/handlers.ts — Replaced import type { ChatService } and import type { UsageService } with IChatService and IUsageService from @domain/interfaces. Updated registerIpcHandlers signature.
ARCH-13: Add database migration system

Added a forward-only SQLite migration system. Migrations are defined as sequential versioned entries in `migrations.ts`, each running in its own transaction. The system tracks applied versions in a `schema_version` table. Converted the existing ad hoc ALTER TABLE check (conversations.purpose column) into a proper v1 migration.

  • src/infrastructure/database/migrations.tsMigration type, MIGRATIONS array (v0 baseline + v1 purpose column), runMigrations() function
  • src/infrastructure/database/schema.ts — Replaced ad hoc ALTER TABLE check with runMigrations(db) call. Added import of runMigrations.
ARCH-14: Standardize agent filenames

Standardized all agent prompt filenames to `UPPER-CASE.md` convention. Renamed `FORGE.MD` → `FORGE.md` (extension casing) and `Quill.md` → `QUILL.md` (name casing). Added a rename migration in `bootstrap.ts` so existing user installations get their files renamed automatically on next startup.

  • agents/FORGE.MDagents/FORGE.md — Extension casing standardized
  • agents/Quill.mdagents/QUILL.md — Name casing standardized
  • src/domain/constants.tsAGENT_REGISTRY.Forge.filename: 'FORGE.MD''FORGE.md', .Quill.filename: 'Quill.md''QUILL.md'
  • src/main/bootstrap.ts — Added agent rename migration step in ensureAgents() (runs before file copy)
  • docs/architecture/DOMAIN.md — Agent registry table updated with correct filenames
ARCH-11: Clean up Wrangler vestige

Updated the Wrangler agent's role from 'Context Planner' to 'Revision Plan Parser' to accurately reflect its actual usage. The Wrangler is only used by `RevisionQueueService` for parsing Forge's revision plan output — the two-call context planning pattern was never implemented.

  • src/domain/constants.tsAGENT_REGISTRY.Wrangler.role: 'Context Planner''Revision Plan Parser'
  • docs/architecture/DOMAIN.md — Updated Wrangler role in Agent Registry table
ARCH-10: Document renderer value imports exception

Documented the formal exception that allows the renderer layer to import pure data constants and pure functions from `@domain/constants` and `@domain/statusMessages`. These are statically defined values with zero Node.js dependencies — routing them through the IPC bridge would add complexity for no safety benefit.

  • src/domain/constants.ts — Added header comment noting the renderer value import exception
  • docs/architecture/ARCHITECTURE.md — Added "Renderer Value Import Exception" section with criteria, allowed imports list, and exclusions
  • docs/architecture/RENDERER.md — Added callout noting the exception with link to ARCHITECTURE.md
ARCH-02: Extract status messages from constants.ts

Moved ~190 lines of status message arrays and helper functions from `src/domain/constants.ts` into a new `src/domain/statusMessages.ts` file. The new file has zero imports — pure functions over static data. constants.ts is now 273 lines (from 466 after ARCH-01, originally 755).

  • src/domain/statusMessages.ts — STATUS_PREPARING, STATUS_WAITING, STATUS_RESPONDING, PITCH_ROOM_FLAVOR arrays and their public accessor functions
  • src/domain/constants.ts — Removed all status message arrays and functions (~190 lines)
  • src/domain/index.ts — Added export * from './statusMessages' to barrel export
  • src/application/ChatService.ts — Import randomPreparingStatus, randomWaitingStatus from @domain/statusMessages
  • src/renderer/hooks/useRotatingStatus.ts — Import randomRespondingStatus from @domain/statusMessages
  • src/renderer/stores/chatStore.ts — Import randomRespondingStatus from @domain/statusMessages
  • src/renderer/stores/modalChatStore.ts — Import randomRespondingStatus from @domain/statusMessages
  • src/renderer/stores/pitchRoomStore.ts — Split import: PITCH_ROOM_SLUG from constants, randomRespondingStatus from statusMessages
  • src/renderer/components/PitchRoom/PitchRoomView.tsx — Split import: AGENT_REGISTRY from constants, randomPitchRoomFlavor from statusMessages
ARCH-01: Extract prompt templates from constants.ts

Moved 9 long-form prompt template strings out of `src/domain/constants.ts` into standalone `.md` files in the `agents/` directory. These are now loaded at runtime via `AgentService.loadRaw()`. Reduces constants.ts from 755 lines to 466 lines. The domain layer no longer contains natural language prompt text — only pure configuration data.

  • agents/VOICE-SETUP.md — Voice profile setup instructions (was VOICE_SETUP_INSTRUCTIONS)
  • agents/AUTHOR-PROFILE.md — Author profile setup instructions (was AUTHOR_PROFILE_INSTRUCTIONS)
  • agents/PITCH-ROOM.md — Pitch room brainstorming instructions with {{BOOKS_PATH}} placeholder (was buildPitchRoomInstructions())
  • agents/HOT-TAKE.md — Hot take assessment instructions (was HOT_TAKE_INSTRUCTIONS)
  • agents/MOTIF-AUDIT.md — Scoped phrase & motif audit instructions (was MOTIF_AUDIT_INSTRUCTIONS)
  • agents/ADHOC-REVISION.md — Direct feedback mode instructions (was ADHOC_REVISION_INSTRUCTIONS)
  • agents/REVISION-VERIFICATION.md — Post-revision verification prompt (was REVISION_VERIFICATION_PROMPT)
  • agents/VERITY-FIX.md — Audit fix mode instructions (was VERITY_FIX_INSTRUCTIONS)
  • ...and 1 more
  • src/domain/constants.ts — Removed 9 exported prompt constants/functions (~289 lines). Updated MOTIF_AUDIT_CADENCE comment to reference agent file instead of deleted constant.
  • src/application/ChatService.ts — Replaced all 8 prompt constant references with await this.agents.loadRaw() calls. buildPitchRoomInstructions() replaced with template load + {{BOOKS_PATH}} regex replace.
  • src/application/RevisionQueueService.ts — Replaced WRANGLER_SESSION_PARSE_PROMPT with await this.agents.loadRaw('WRANGLER-PARSE.md').
Architecture refactor prompt suite

Created a complete set of 14 encapsulated refactoring prompts to address the architectural issues documented in `issues.md`. Includes a state tracker for cross-context handoffs, a dependency graph, and a master loop prompt that drives execution through all prompts in order. No production code changes — this is the planning and orchestration layer f...

  • prompts/arch/STATE.md — State tracker with prompt status, dependency graph, and handoff notes
  • prompts/arch/MASTER.md — Master loop prompt that reads state, picks next prompt, executes, and loops
  • prompts/arch/ARCH-01.md — Extract prompt templates from constants.ts to agent .md files
  • prompts/arch/ARCH-02.md — Extract status messages from constants.ts to statusMessages.ts
  • prompts/arch/ARCH-03.md — Add IChatService and IUsageService interfaces
  • prompts/arch/ARCH-04.md — Extract StreamManager from ChatService
  • prompts/arch/ARCH-05.md — Extract AuditService from ChatService
  • prompts/arch/ARCH-06.md — Extract PitchRoomService from ChatService
  • ...and 8 more
Remove phrase ledger, consolidate into motif ledger

Eliminated the standalone phrase ledger (`source/phrase-ledger.md`) as a separate artifact. All phrase/repetition tracking now lives exclusively in the `flaggedPhrases` section of `source/motif-ledger.json`. The motif ledger already had this section — the phrase ledger was a legacy Markdown format that duplicated its function. Lumen's Lens 8 audit ...

  • src/domain/types.ts — Renamed AuditViolationType variant 'phrase-ledger-hit''flagged-phrase'
  • src/domain/constants.ts — Removed source/phrase-ledger.md from AGENT_READ_GUIDANCE (Verity, Lumen). Removed phraseLedger from FILE_MANIFEST_KEYS. Renamed PHRASE_AUDIT_INSTRUCTIONSMOTIF_AUDIT_INSTRUCTIONS (now writes to motif-ledger.json). Renamed PHRASE_AUDIT_CADENCEMOTIF_AUDIT_CADENCE. Updated VERITY_FIX_INSTRUCTIONS to use flagged-phrase violation type.
  • src/application/ChatService.ts — Renamed runPhraseAudit()runMotifAudit(). Audit chapter now loads flaggedPhrases from motif-ledger.json instead of reading phrase-ledger.md. Updated ad hoc revision pre-step.
  • src/main/ipc/handlers.ts — Renamed IPC channel verity:runPhraseAuditverity:runMotifAudit
  • src/preload/index.ts — Renamed bridge method runPhraseAuditrunMotifAudit
  • src/renderer/stores/autoDraftStore.ts — Renamed PHRASE_AUDIT_CADENCEMOTIF_AUDIT_CADENCE, updated periodic audit labels and method calls
  • agents/LUMEN.md — Lens 8 now writes flaggedPhrases to motif-ledger.json instead of phrase-ledger.md. Updated file ownership table.
  • agents/VERITY-AUDIT.md — Renamed violation type, updated input description and flagging rules
  • ...and 5 more
  • source/phrase-ledger.md concept — no longer produced or consumed by any agent or service
  • phraseLedger key from FILE_MANIFEST_KEYS
Create full architecture documentation from scratch

Created all six architecture documentation files by reading every source file in the codebase and documenting the actual state. Covers all 5 layers: domain types/interfaces/constants, infrastructure modules and database schema, application services and orchestration logic, IPC channels and preload bridge shape, and renderer stores/components/views....

  • docs/architecture/ARCHITECTURE.md — Master overview: layer diagram, source tree, service dependency graph, conventions, tech stack
  • docs/architecture/DOMAIN.md — All types (60+ types cataloged), all interfaces (11 interfaces with full method tables), all constants
  • docs/architecture/INFRASTRUCTURE.md — 6 infrastructure modules, 5 database tables with column details, CLI integration protocol, file watcher docs
  • docs/architecture/APPLICATION.md — 8 application services with method tables, context assembly strategy, conversation compaction rules
  • docs/architecture/IPC.md — 80+ IPC channels across 17 namespaces, 7 push events, full window.novelEngine preload bridge type shape
  • docs/architecture/RENDERER.md — 13 Zustand stores, 8 views, 12 component groups (50+ components), 5 hooks
Move architecture docs to docs/architecture/ subfolder

Relocated all architecture documentation references from `docs/` to `docs/architecture/`. The `docs/` root already contained a landing page (`index.html`, `og-image.png`), so architecture docs now live in their own subfolder to avoid mixing concerns. Created the `docs/architecture/` directory and updated every reference in `AGENTS.md`.

  • docs/architecture/ — New directory for all architecture documentation files
  • AGENTS.md — Updated all 20+ references from docs/*.md to docs/architecture/*.md (Rule section, section headers, Workflow mappings, Edge Cases)
Motif Ledger: full-stack feature from domain to UI

Added the Motif Ledger — a structured JSON-backed system for tracking motif systems, character entries, structural devices, foreshadow threads, minor characters, flagged phrases, and audit logs per book. The domain types and application service were already built in a prior session; this session completed the IPC wiring, preload bridge, Zustand sto...

  • src/main/ipc/handlers.ts — Added motifLedger:load, motifLedger:save, motifLedger:getUnauditedChapters IPC handlers
  • src/preload/index.ts — Added motifLedger namespace to the contextBridge API
  • src/renderer/stores/motifLedgerStore.ts — Zustand store with full CRUD for all 7 ledger sections, dirty tracking, save/load
  • src/renderer/components/MotifLedger/MotifLedgerView.tsx — Main view with 7-tab navigation, save button, Cmd+S shortcut
  • src/renderer/components/MotifLedger/SystemsTab.tsx — Motif systems CRUD
  • src/renderer/components/MotifLedger/EntriesTab.tsx — Character motif entries CRUD with filtering
  • src/renderer/components/MotifLedger/StructuralTab.tsx — Structural devices CRUD
  • src/renderer/components/MotifLedger/ForeshadowTab.tsx — Foreshadow registry with status grouping
  • ...and 3 more
  • src/main/ipc/handlers.ts — Added IMotifLedgerService to services type, MotifLedger to type imports
  • src/preload/index.ts — Added MotifLedger type import
  • src/renderer/stores/viewStore.ts — Added 'motif-ledger' to ViewId
  • src/renderer/components/Layout/AppLayout.tsx — Added MotifLedgerView to ViewContent
  • src/renderer/components/Layout/Sidebar.tsx — Added motif-ledger nav item