# Release notes

Per-release write-ups for every published Inkhaven version. Each
file walks through what changed at user-facing granularity — new
chords, new modals, new config knobs, new CLI subcommands — plus
migration notes when the on-disk shape moved.

The point of these is **continuity**: a writer coming back to the
TUI after a few months should be able to read one or two notes and
see what they missed without trawling the git log.

| Version  | Released   | Notes                                | Highlights |
| -------- | ---------- | ------------------------------------ | ---------- |
| **1.5.0** | 2026-06   | [`1.5.0.md`](1.5.0.md)           | **Research Assistant (RESRCH-1).**  A separate full-screen TUI — `inkhaven research [--thread <name>]` — for AI-assisted research that transfers **verified** findings into the **Facts** / **Notes** corpus, with a confirmation step on every insertion.  Three panes: **Facts tree** (navigate / pin / edit) · **streaming RAG chat** grounded by your Facts book (reuses the book-scoped retriever; `F10` cycles Facts+Full / Facts only / Full only; `Ctrl+P` pins up to 3) · a `/command` query prompt.  **`/fact "…" [→ path]`** distils the last response into one titled fact (in the project language) → an **editable confirmation overlay** (`Ctrl+S` insert, `Esc` discard); inserts re-embed immediately so they reach `/diff`, the writing RAG, and every Facts consumer with no rebuild.  **`/note`** → Notes (speculative); **`n`** types one by hand.  **`/diff`** similar facts · **`/verify`** claim-confidence · **`/factcheck`** whole-corpus accuracy + mutual-contradiction audit (multi-call) · **`/chain a → b → c`** · `/goto /rag /clear /save`.  Facts tree edits on par with the editor + Outline (`R` rename, `c`/`s` chapter/subchapter, `-`/`D` delete, `K`/`J` move, `y`/`x`/`p` copy/cut/paste).  Named, resumable **threads** (`.inkhaven/research-threads/<slug>.json`); `--list-threads` / `--export-thread` (table/json/md).  `Ctrl+B h` quick reference; themed from `theme:`; arrow-editable prompt; wrapped-row chat scroll.  **Audit-corrected** RFC: **no `facts.duckdb`** (facts are Facts-book paragraphs in the shared vector store), synchronous crossterm loop + `spawn_chat_stream` (not `tokio::select`), `create_node` + `update_paragraph_content`, `find_by_path`, reuse `book_rag::retrieval`.  **No new runtime crates / system books / `NodeKind`.**  New tutorial 103; `research:` config.  Tests 2146 → 2177. |
| **1.4.19** | 2026-06   | [`1.4.19.md`](1.4.19.md)         | **Mythological & Symbolic Pattern Library (MYTH-1).**  A home for the book's symbolic layer — but tracking only what the author **declares** in the new **Mythology** system book: never discovers, never interprets, never edits prose.  Three declaration paragraphs: **symbols** (`para:myth-symbol`, `⊛` — vocabulary + meaning + valence + traditions; the vocab highlights lavender in the editor), **motifs** (`para:myth-motif`, `∿`), **archetypes** (`para:myth-archetype`, `⍟` — a character mapped to one of Vogler's eight roles or a custom one).  **Deterministic** (zero-AI): archetype vacant / absent, motif absent from the final act — Output **`myth`** category, folded into `Ctrl+B Shift+C`.  **LLM** (explicit, `inkhaven myth check`): symbol consistency / motif completeness / archetype role fulfilment — given only declarations + concrete excerpts, in the project language.  **`Ctrl+V Shift+M`** renders the symbol-density / motif-presence / archetype-presence **heatmap** into the Thoughts pane + jumps to the nearest declared symbol.  A 16th Inner Socrates persona **The Myth-Reader**; declared traditions ground **Inner Theologian** (Source 4), declared motifs ground the **utopian-architect**.  CLI `inkhaven myth scan / check [--kind] / profile / refresh / suppress`; Bund `ink.myth.{symbols,motifs,archetypes,density,findings}` (read) + `ink.myth.suppress` (write); `myth:` config; `.inkhaven/myth.duckdb`.  **No new runtime crates / `NodeKind`.**  New tutorial 102.  Tests 2131 → 2146. |
| **1.4.18** | 2026-06   | [`1.4.18.md`](1.4.18.md)         | **Inner Theologian + the Thoughts pane (INNER-THEOLOGIAN-1, THOUGHTS-1).**  The third Inner-family reader after Socrates (logic) and Editor (craft): **moral & theological seriousness**.  A **tradition-neutral comparativist** reading any manuscript through **eleven lenses** (Catholic / Protestant / Orthodox / Gnostic / LDS / Islam / Judaism / Hinduism / Buddhism / Confucianism / secular philosophy) — never to judge by any, only to ask what each *sees*.  Belongs to no tradition, **never a verdict**, never edits prose.  **Fast track** (deterministic, zero-AI, 5 langs): three `info` signals — moral invisibility / consequence gap / sacred levity — in the Output **`theologian`** category (`⚖`), folded into `Ctrl+B Shift+C`.  **Slow track** **`Ctrl+B J→T`**: a **two-pass** flow — a *discovery* call picks the 2–4 of all eleven lenses that genuinely illuminate the passage (+ tellingly **silent** ones), an *analysis* call poses questions through them, in the book's language.  Six categories; grounded by WORLD-6 theological findings + CHAR-1 belief arcs + in-scope signals (all degrade).  CLI `inkhaven theologian scan / session [--chapter N --category 1-6 --lens <code>] / suppress`; Bund `ink.theologian.{signals,suppress}`; `theologian:` config; `.inkhaven/inner_theologian.db`.  **THOUGHTS-1:** a new read-only, scrollable, Markdown-rendered **Thoughts** right-side pane (the slow-track's home).  `Ctrl+B Tab` cycles Output → AI → Thoughts; plain `Tab` → Tree/Editor/current pane; auto-show without stealing focus; **`Ctrl+Z f`** fullscreens Output/Thoughts; pane remembered across restarts.  **Audit-corrected** from the RFC: own store (not a `kind` column on inner_socrates.db), `⚖` (✦ went to HAIKU-1), English corpus + in-language directive, no session resume.  **No new runtime crates / system books / `NodeKind`.**  New tutorial 101.  Tests 2106 → 2131. |
| **1.4.17** | 2026-06   | [`1.4.17.md`](1.4.17.md)         | **The startup haiku (HAIKU-1).**  A writer-delight feature: a hand-curated haiku in the Output pane at three moments — **startup**, when a new **manuscript paragraph** is created and opened to write (user books only — not system books / seeded / structural paragraphs), and on demand via **`Ctrl+Z p`**.  **Zero-AI, zero-network, zero new crates** — all 25 poems (5 languages EN/RU/DE/FR/ES × 5) are `&'static str` baked into the binary, present even airgapped before the DB journal replays.  The poem is in the book's language (`editor.language`, English fallback); a clock-seeded per-process rotation advances on each trigger (Tier-A manuscript themes first, Tier-B atmosphere later).  Renders as a `✦ haiku` row with three indented lines; only the most recent ever lives in the pane (prior ones are dismissed on emit, so they never pile up).  Toggle the automatic moments with **`editor.startup_haiku`** (default true); the chord works regardless.  The Output pane's first piece of good news.  **No new crates / DB / system books / `NodeKind`.**  New tutorial 100.  Tests 2103 → 2106. |
| **1.4.16** | 2026-06   | [`1.4.16.md`](1.4.16.md)         | **Character arc tracking (CHAR-1).**  The third axis after the continuity bible (facts) and DIALOG-1 (speech): **change over time**.  Per named character — a chapter-ordered **observable-state chain**, a **deterministic agency score**, and completeness checks against a **declared arc**.  Declare it in a Characters-book paragraph's **`character_arc`** HJSON block (`arc_type` ∈ positive_change / flat / corruption / fall / disillusionment + aliases; `desired_state_start` / optional `desired_midpoint_state` / `desired_state_end`).  **Agency** is zero-AI — `active/(active+passive)` presence via a windowed name↔action-verb heuristic gated by NARR-1 passive detection, five languages EN/RU/DE/FR/ES; **state extraction** is the only LLM pass (sliding-window, content-hash lazy, enriched with DIALOG-1 utterance/hedge + NARR-1 interiority).  **`inkhaven character refresh`** (agency + extraction), **`check`** (start/midpoint/end alignment + **arc-earned** + a deterministic **stall** check — exits **2** if the ending/earned fails, **1** on any other gap/stall — CI gate), **`plan`** (Planning-Board coverage gaps: no scene card / first-half-only / no final act — exit 1), **`arc <name>`** (full report).  **`Ctrl+V Shift+N`** opens the read-only arc view (declaration · ✦ state chain w/ agency · checks · gaps) for the nearest character; the **`Ctrl+B Shift+C`** review pass folds in the deterministic layers + cached arc problems (Output **`character`** category, zero-cost — LLM stays CLI-explicit).  Read-only `ink.char.{arc,stalls,checks,plan,refresh}` Bund; `char:` config (stall threshold / agency windows / min chapters / enrichment toggles / `extra_action_verbs`); `.inkhaven/char.duckdb`.  **It never edits prose.**  **No new runtime crates / system books / `NodeKind`.**  New tutorial 99.  Tests 2069 → 2103. |
| **1.4.15** | 2026-06   | [`1.4.15.md`](1.4.15.md)         | **Utopian/dystopian coherence checker (WORLD-6).**  Checks the **logical coherence of a declared social premise** (premise → mechanism → consequence + elimination inventory) that WORLD-4/5's physical/temporal facts don't.  Declare the premise in the **World** book as paragraphs tagged **`para:utopia-{premise,mechanism,consequence,elimination}`** (glyphs ⊢ ⚙ ⇒ ∅; add via `Ctrl+B ]`); consecutive tagged paragraphs form a premise group (a gap breaks it; `// world:group:<name>` names one).  Three LLM stages reading **only what you declare**, judging **logical/systemic** structure only (never morality): **Stage 1** extraction, **Stage 2** pairing → CHAIN BREAK / CONSEQUENCE GAP / INTERNAL CONFLICT (explicit-only, O(pairs)), **Stage 3** per-chapter entailment scan → ENTAILMENT VIOLATIONs vs the elimination inventory.  Plus a deterministic **Facts-book cross-reference**.  **`inkhaven world utopia-check [--stage 1\|2\|3\|all]`** (exits 1 on chain finding, 2 on entailment — CI gate); **`utopia-model`** prints the extracted claims; **`utopia-suppress`** / magic-ledger `deliberate_tension` covering `utopia_coherence` mutes deliberate ironies; **`utopia-refresh`**.  Grounds the **`utopian-architect`** Inner Socrates persona's opening; cached findings surface in the **`Ctrl+B Shift+C`** review pass (Output `utopia` category, read-only — stages run only via CLI).  Bund `ink.utopia.{model,findings,violations,suppress}`; `utopia:` config; `.inkhaven/utopia.duckdb`.  **`inkhaven world` restructured into subcommands** (the bare `world` snapshot unchanged).  Schema reserves `theological` domain + `research` hooks for future features.  **No new runtime crates / system books / `NodeKind`.**  New tutorial 98.  Tests 2039 → 2069. |
| **1.4.14** | 2026-06   | [`1.4.14.md`](1.4.14.md)         | **Dialogue quality & attribution (DIALOG-1).**  Dialogue measured as a *mode* — **deterministic, zero-AI, no parser, no external dependency, no new crates** — in five languages (EN/RU/DE/FR/ES) across **three quotation conventions** (paired quotes EN/DE · guillemets + em-dash FR/RU, with the French inline `, dit-il,` *incise* stripped · Spanish hybrid).  **`inkhaven dialogue scan`** flags three findings — **zero-attribution** (no tag / character name, with a two-speaker run-clearing heuristic), **said-bookism density** (chapter `whispered`/`growled` rate vs the book baseline), **talking-head sequences** (dialogue-only runs with no ≥8-word action beat) — and **exits non-zero** on any zero-attribution (CI gate).  **`dialogue profile`** builds a six-metric per-character fingerprint (utterances / avg words / **MATTR** / question / exclamation / hedge) from confidently-attributed lines, reusing NARR-1's MATTR + modal list; **`Ctrl+V Shift+Q`** opens the fingerprint view for the nearest character.  The check rides the **`Ctrl+B Shift+C`** review pass into the Output pane (zero-AI, content-hash lazy).  New Inner Socrates **`theatergoer`** persona (15th) reads a scene as if the narrator's glosses were invisible.  Read-only `ink.dialogue.{stats,fingerprint,violations,spans,refresh}` Bund; `dialogue:` config (windows / thresholds + **`extra_neutral_verbs`** so SF/fantasy speech verbs aren't said-bookisms); `.inkhaven/dialogue.duckdb`.  CLI `scan`/`profile`/`refresh`/`suggest`.  **No new runtime crates; no new system books / `NodeKind`.**  New tutorial 97.  Tests 2005 → 2039. |
| **1.4.13** | 2026-06   | [`1.4.13.md`](1.4.13.md)         | **The manuscript Outline (OUTLINE-1).**  The side Tree pane navigates but doesn't restructure comfortably.  A new **full-screen, foldable Outline** of the whole book — **`Ctrl+2`** (backup **`Ctrl+B Shift+O`**; `Ctrl+T` now focuses the side Tree pane).  View state (folds / cursor / filter) persists per project to `.inkhaven/outline-state.json`; opens with Books + Chapters expanded; a right-hand **detail panel** shows the cursor node's breadcrumb / status / words-vs-target / tags / modified.  Navigate `j`/`k`/`g`/`G`, fold `Enter`/`l`/`h`/`Space`.  **Restructure:** `Shift+J`/`Shift+K` reorder siblings, **`<`/`>`** promote/demote one nesting level (childless nodes; placement-rule violations are no-ops).  **Cross-parent paragraph copy/move** via a clipboard shared with the Tree pane — **`y`** copy · **`m`** move · **`f`** affix (INTO a branch / alongside a paragraph); copy duplicates (fresh uuid, prose metadata carried, **no** timeline event) and stays held for repeat pastes.  **`/`** filters to the path-to-match tree (case-insensitive, Unicode-aware); staged `Esc`.  CLI parity: **`inkhaven outline [--filter]`**, **`inkhaven paragraph copy\|move <src> <dest>`** (slug paths).  Bund: `ink.outline.{print, paragraph_copy, paragraph_move}` (mutators need `store_write`).  The pane, the Tree clipboard, the CLI, and Bund all share one set of **filesystem-aware store primitives** (`move_node_to_parent` / `copy_paragraph_to_parent` / `swap_siblings`).  **No new runtime crates; no new `NodeKind` / `ChildRef` / DB tables.**  New tutorial 96.  Tests 1996 → 2005. |
| **1.4.12** | 2026-06   | [`1.4.12.md`](1.4.12.md)         | **Narrative voice profiling (NARR-1).**  Does chapter 40 read like the person who wrote chapter 1?  **`inkhaven prose`** measures voice as a statistical property of the whole book — **deterministically, with no LLM, no parser, and no external dependency**: sentence-rhythm (**CV** / burstiness / **MATTR**), epistemic-hedging **modal density**, free-indirect-discourse **interiority** (+ German *erlebte Rede* particles), and a `--deep` tier (**sensory channel balance** + per-language **active/passive ratio**).  **Five first-class languages** (EN/RU/DE/FR/ES, each with curated word lists; an unsupported language still gets the full rhythm tier + a note).  **`prose profile`** prints the book aggregate; **`prose drift [--mode baseline\|rolling] [--reference <project>]`** shows per-chapter deltas + threshold crossings; **`prose suggest`** explains the metrics.  In the editor **`Ctrl+V V`** (Voice) runs the check in the **background** — content-hash lazy (only edited chapters recompute), **zero-AI / zero-cost** — and drops threshold crossings into the **Output pane** as informational, navigable `prose` findings; **`Ctrl+V Shift+V`** toggles ambient (off, 90s cooldown).  Profiles live in a new `.inkhaven/prose.duckdb`; `prose:` config block (thresholds, `extra_modal_tokens`, …); read-only `ink.prose.{profile,drift,violations,refresh}` Bund.  **It measures, never prescribes.**  **No new runtime crates.**  Also: Output pane `Home`/`End`/`PageUp`/`PageDown`.  New tutorial 95.  Tests 1952 → 1996. |
| **1.4.11** | 2026-06   | [`1.4.11.md`](1.4.11.md)         | **Structural paragraphs & deletion hardening (STRUCT-2).**  Technical chapters mix prose with code / admonitions / math / procedures / tables.  **(Part A)** **`i`** in the Tree pane opens a picker of those subtypes and creates a `.typ` paragraph tagged **`para:*`** with the matching Typst boilerplate seeded — a **tag, not a content type**, so it's addable/removable via **`Ctrl+B ]`** without a morph.  Structural paragraphs get a type-specific tree glyph (`⌨ ⚠ ∫ ≡ ⊞`), are **skipped by the Inner Editor / Inner Socrates** (except `para:procedure`, which is prose), and are **excluded from prose word counts** — Book Info (`Ctrl+B I`) shows a separate `structural: N` line.  **(Part B — deletion hardening)** the delete confirmation now shows the **word count** about to be lost (`… and 12 descendants (15,342 words)?`); **branch deletes stash every paragraph leaf** into the kill-ring (**`Ctrl+B U`** restores them one at a time, in order, with word counts; **`Ctrl+V Shift+U`** picker); and a **pre-delete snapshot** of every paragraph (`pre-delete: <title> · <date>`) lets you recover any of them from the **`F6`** picker long after the kill-ring cycles.  **Purely additive — no new content type / NodeKind / ChildRef / DB tables; no new dependencies.**  New tutorial 94.  Tests 1949 → 1952. |
| **1.4.10** | 2026-06   | [`1.4.10.md`](1.4.10.md)         | **Jinja template paragraphs (STRUCT-1).**  Some content is *structured* and *data-driven*, not free prose.  A paragraph with `content_type: "jinja"` is a [minijinja](https://docs.rs/minijinja) template the assembler renders to **Typst** before `typst compile` — two layers, strictly sequential, never nested.  **`e`** in the Tree pane creates one (under a user book → a data-driven manuscript template; under the **Snippets** book → a reusable `{% include %}` fragment); plain **`t`/`T`** cycles an existing leaf's type through the new `jinja` rung (`typst → hjson → jinja → bund`).  The render context exposes `title` / `book` / `chapter` / `language` / `genre` and **`linked["<slug>"].<field>`** — HJSON data from paragraphs linked with **`Ctrl+V a`**.  Snippet `.jinja` paragraphs register as named templates (`snippets/<path>.jinja`) so manuscript templates `{% include %}` them; everything is registered before any rendering, so includes always resolve.  Tree glyph **`⟡`**, editor badge **`[jinja]`**, Jinja syntax highlighting; Jinja paragraphs are skipped by Inner Editor / Socrates / fact-check (markup, not prose).  A render error **aborts assembly** by default (CI-safe); `jinja.continue_on_error: true` writes a visible error block and continues.  Also: the REUSE-1 `#include` validator now catches a typo'd snippets directory and verifies generic Typst includes against the assembled output.  **Self-gating; one new crate (`minijinja`); no new `NodeKind` / `ChildRef` / DB tables.**  New tutorial 93.  Tests 1936 → 1949. |
| **1.4.9** | 2026-06   | [`1.4.9.md`](1.4.9.md)            | **Reusable content blocks (REUSE-1).**  Write a warning / procedure / admonition **once** and reference it from many places.  Reusable prose lives as Typst paragraphs in a new **Snippets** system book; elsewhere you reference it with a standard Typst **`#include "…/snippets/<slug>.typ"`**.  At Book assembly inkhaven copies every snippet to a `snippets/` sidecar next to the assembled book, so the include resolves at `typst compile` — **no new Typst syntax, no new content type**.  **`Ctrl+V x`** fuzzy-picks a snippet and inserts a depth-correct `#include` (the `../…/snippets/` prefix is computed from the paragraph's place in the tree); with the cursor inside an existing snippet include it **replaces** the path in place.  **`Ctrl+V Shift+X`** is the overview — every snippet + its project-wide reference count, Enter jumps to source.  A **save-time validator** flags any `#include` pointing at an undefined snippet (status / F8 / `Ctrl+V N`), validated against the live Snippets book so it works *before* assembly.  **`inkhaven snippets check [--book] [--json]`** validates the whole project (exit 1 on a missing reference; orphaned snippets are warnings); `snippets list` lists them + ref counts.  Read-only `ink.snippets.{list,get,check}` Bund words.  **Self-gating** — no Snippets book, no cost.  **No new content type / NodeKind / DB tables; no external or runtime crates.**  New tutorial 92.  Tests 1926 → 1936. |
| **1.4.8** | 2026-06   | [`1.4.8.md`](1.4.8.md)            | **Terminology governance (TERMS-1).**  Tackles terminology drift in long nonfiction/technical writing.  A new **Glossary** system book holds canonical terms + **banned synonyms** as HJSON entries; the editor **red-underlines** the synonyms in prose (so "auth token" is flagged while the canonical "access token" is clean — the inverse of a normal highlight), with a footer hint `"auth token" → use "access token"`.  Multi-word (1–3-gram) + Unicode-aware matching.  **`Ctrl+V z`** toggles the overlay; **`Ctrl+V Shift+Z`** declares the term under the cursor a **deliberate variant** (intent-ledger suppression).  **`inkhaven terms check [--book] [--json]`** scans the whole project (exits non-zero — CI-ready); **`inkhaven terms suggest [--book] [--auto-create]`** clusters multi-form terms and proposes Glossary entries via the LLM.  Read-only `ink.terms.{list,get,check}` + `declare_intent` Bund words; Glossary terms appear in the story bible.  **Self-gating** — an empty Glossary flags nothing, so projects that don't use it pay zero.  Built on the existing style-warning + intent-ledger machinery — **no external deps; no new runtime crates; no new DB tables** (one additive system book + one `IntentKind`).  New tutorial 91.  Tests 1910 → 1926. |
| **1.4.7** | 2026-06   | [`1.4.7.md`](1.4.7.md)            | **More readers, and two adversaries (AUDIENCE-1.1).**  Inner Socrates grows from nine bundled personas to **fourteen**.  **(Ideas readers)** three for work that's neither plain fiction nor empirical nonfiction — `philosophical-reader` (the Dialectician — argument structure), `theological-reader` (**non-empiricist** — coherence/fidelity/scope, never "show evidence"), `utopian-architect` (**hybrid** — argument-weighted but keeps the narrative live); matching `philosophy` / `theology` / `utopian` genres reframe both companions.  **(Verdict personas)** two deliberately one-sided adversaries — `defender` (**only praise**) and `prosecutor` (**only concern**), a steelman/devil's-advocate pair that break the questions-only spine on purpose; LLM-only + bilingual; a persona file can opt in with `stance: praise|concern`.  The neutral `inner-socrates` and every other persona are **untouched** (byte-for-byte, by test).  **(Slow pass in the editor)** **`Ctrl+B J → E`** (Engage) runs the LLM deep-questions / verdict over the open paragraph in the **background** → Output (mirrors `Ctrl+V O → E`; CLI `check` and engage now share one path).  **(Easier targeting)** `inkhaven list` prints full copy-pasteable slug paths; **`inner-socrates check --path <slug-path>`** takes them (no UUID lookup).  **Purely additive** — no genre + no non-default persona = exactly the prior behaviour.  **No new deps; no new DB tables** (one `stance` field).  Tutorial 90 expanded.  Tests 1904 → 1910. |
| **1.4.6** | 2026-06   | [`1.4.6.md`](1.4.6.md)            | **Nonfiction reader personas (AUDIENCE-1).**  Inner Socrates' five bundled personas all read for *fiction*, so on a manual or a paper its questions were coherent but miscalibrated.  This adds **four nonfiction readers** — `skeptical-practitioner` (IT/technical), `domain-newcomer` (general nonfiction), `expert-reviewer` (academic/peer-review), `end-user` (documentation) — bringing the bundled set to **nine**.  Each mutes the narrative-only categories (dramatization gap / temporal density / unattributed dialogue) and leans on assumption-surfacing, framing, and significance.  Activate per session (`inner-socrates persona activate <id>` / **`Ctrl+B J → S`** cycles all nine) or set a project default with **`inner_socrates_default_persona`** in `inkhaven.hjson` (consulted only when no persona is explicitly set; explicit activation always wins; overview flags `(project default from config)`).  Declaring a nonfiction **`genre`** (`technical` / `documentation` / `academic` / `science` / `business`) also reframes the *system prompt* of both Inner Socrates (procedures as reproduction attempts) and Inner Editor (clarity/completeness as the craft).  **Purely additive** — with no genre and no default set, fiction authors see exactly the prior behaviour (an unknown genre also falls back to fiction).  The five fiction personas, the Category enum, the Fast track, the wizard, and the `Ctrl+B J` chords are unchanged.  **No external app/binary deps; no new runtime crates; no new DB tables** (one `Option<String>` config field).  New tutorial 90.  Tests 1897 → 1904. |
| **1.4.5** | 2026-06   | [`1.4.5.md`](1.4.5.md)            | **Bibliography & citations (SOURCES-1).**  inkhaven compiles to Typst, which has a real bibliography engine — this wires the two together.  References live as structured **HJSON entries** in a new **Sources** system book (one chapter per user book, auto-seeded with the schema); cite in prose with Typst's **`@key`** syntax.  At Book assembly (`Ctrl+B A` / `inkhaven build`) inkhaven compiles the entries to **`sources.bib`** and appends **`#bibliography("sources.bib", style: …)`**, so `typst compile` renders the reference list and resolves every citation (status reports `N citation(s) -> sources.bib`).  **(Authoring)** press **`P`** under the Sources book (title becomes the cite key, body pre-seeded) or bulk-import BibTeX — **`inkhaven sources import <file.bib>`** (dependency-free reader: braced/quoted/bare values, nested braces, `@comment`/`@string`/`@preamble` skipped, biblatex `date→year`).  **(Insert)** **`Ctrl+V @`** opens a fuzzy **cite picker** (filter by key/author/title, Enter inserts `@key`; e-mails aren't mistaken for cites).  **(Validate)** **`inkhaven sources check`** scans prose `@key` tokens against defined entries — reads what assembly compiles, **exits non-zero** on undefined keys (CI-ready); `--json`/`--book-name`; `sources list` lists entries.  **(Scope)** `sources.all` toggles one-shared vs per-book bibliographies; `bibliography_style` (CSL) + `auto_bibliography` knobs.  **(Scripting)** four read-only `ink.sources.{list,get,check,bibtex}` Bund words.  Built on the existing `.typ` + DuckDB + serde-hjson stack — **no external app/binary deps; no new runtime crates.**  New tutorial 89.  Tests 1882 → 1897. |
| **1.4.4** | 2026-06   | [`1.4.4.md`](1.4.4.md)            | **Unify the companions (COMPANIONS-1).**  Makes the examined-authorship triad (World / Inner Socrates / Inner Editor) feel like one system.  **(Editor in the review pass)** `Ctrl+B Shift+C` now includes Inner Editor — spawned in the **background** on the open paragraph (it's LLM-only) so the instant fact/socrates/timeline pass stays instant; its ✎ observations arrive in Output + re-badge the tree (badges were already kind-agnostic).  **(Intent loop closes)** dismiss a category enough and the Editor nudges you to declare it deliberate — `inkhaven inner-editor suggestions list/promote/dismiss`; `promote` writes the **shared intent ledger** Socrates also consults.  Also repaired a latent bug where Socrates' own promotion nudge was clobbered by the generic "dismissed".  **(One view)** a `companions` stop in the Output `f` filter shows all four examined-authorship sources at once; **`inkhaven companions`** is a terminal cockpit — open findings per companion, the shared ledger + pending promotions, and today's per-companion LLM cost.  **(Scripting)** new `ink.inner_editor.suggestions` Bund word.  Deferred: `inner-editor config set` (the HJSON splice can't safely write deeply-nested keys — would corrupt config; use `inkhaven config` for now).  **No new dependencies.**  Tests 1879 → 1882. |
| **1.4.3** | 2026-06   | [`1.4.3.md`](1.4.3.md)            | **The Inner Editor — Part B (INNER_EDITOR-1 complete).**  Makes the Editor **conversational** and **teachable**.  **(Two fixes first)** background AI jobs no longer crash the TUI (the job runner now inherits the Tokio runtime — the panic Inner Editor's engage hit; also a latent WORLD-4 crash), and `collect_blocking`'s per-token `.` progress ticks are suppressed in the TUI (they were splattering the editor pane).  **(Conversation)** `Ctrl+V O → C` (or F9 → **Editor** scope) discusses the Editor's observations in the AI pane, non-prescriptive.  **(Record-as-intent)** press **`i`** on a finding, or `inkhaven inner-editor intent <category> [--chapter] [--description]`, to declare a craft choice deliberate → suppressed via the **shared intent ledger** (new additive kinds: `deliberate_repetition` / `voice_instability_intentional` / `prose_belief_intentional_distance` / …); findings record the paragraph snapshot id for cross-draft `findings history`.  **(Scripting)** seven `ink.inner_editor.*` Bund words (`findings.list`/`usage.today`/`config`/`categories`/`system_prompt` read-only, `intent.declare` store-write, `engage` ai-write).  **(Cost)** `inkhaven cost` / `Ctrl+B $` now surface the `inner editor · editor_engagement` budget (informative).  New tutorial 88 + `inner_editor` CONFIGURATION block.  **No new dependencies.**  Tests 1875 → 1879. |
| **1.4.2** | 2026-06   | [`1.4.2.md`](1.4.2.md)            | **The Inner Editor — Part A (INNER_EDITOR-1).**  The second **Inner-family** member: where Inner Socrates interrogates structure, **Inner Editor** observes *literacy and style* through a single configurable persona — brief, grounded, **non-prescriptive** observations across eight categories (richness / tautology / style / style-instability / vocabulary / belief-stance / craft-praise / suggestions), graded **Praise / Note / Concern**.  Structural discipline: never commands ("should"/"must" forbidden), **praise must be earned**, silence is fine.  LLM-only, paragraph scope (¶ + preceding window); consults the shared **intent ledger**; **multilingual** EN/RU/ES/FR/DE.  **`Ctrl+V O`** (Observe) opens the overview → `E` engage / `A` opt-in ambient paragraph-pause auto-engage (cooldown so it never fires mid-edit) / `F` jump to findings; Output rows carry a **✎** glyph + warm-earth palette, coexisting with Inner Socrates' purple.  CLI **`inkhaven inner-editor engage / findings / config / usage`**; new `inner_editor:` config block + project `genre`; `inner_editor` cost budget (informative).  **Part A** — conversation mode, snapshot history, `ink.inner_editor.*` Bund words land in 1.4.3.  Also: **Book-RAG polish** — Book-scope chat renders inline as a transcript; citations are readable `[chapter/scene]` paths, not UUIDs.  **No new dependencies.**  Tests 1855 → 1875. |
| **1.4.1** | 2026-06   | [`1.4.1.md`](1.4.1.md)            | **Chat with your book (BOOK_RAG-1).**  The AI pane's **Book** scope is now **retrieval-augmented** — instead of shipping the whole manuscript with every question, it retrieves the paragraphs that bear on the question, grounds the answer in them, and makes the model **cite** them (`[label](#id)`; invented citations flagged inline; honest "doesn't address that" when the book is silent).  **Always on for Book scope; the other scopes (Selection / Paragraph / Subchapter / Chapter) are unchanged.**  Press **`p`** for the *Retrieved passages* transparency panel; retrieval runs **once per chat session** (clear history to re-ground); a curated set of system books (Notes / Research / Places / Characters / Artefacts / World / Language) joins the manuscript in scope.  **From the terminal:** **`inkhaven book-rag retrieve <query>`** inspects what chat would ground on, no LLM call (`--book-name` / `--top-k` / `--context`).  **From a script:** eight read-only **`ink.book_rag.*`** Bund words (`retrieve` / `context` / `scope` / `config` / `system_prompt` / `estimate_tokens` / `cited_ids` / `validate_citations`) — pane, CLI, and Bund share one retrieval core.  Tuned by the new `book_rag:` config block; grounding prompt localized EN/RU/ES/FR/DE; `book_rag`-category cost is informative only.  Built entirely on the existing `.typ` + DuckDB + Fastembed + vecstore stack — **no external app/binary deps; no new runtime crates.**  New tutorial 87.  Tests 1850 → 1855. |
| **1.4.0** | 2026-06   | [`1.4.0.md`](1.4.0.md)            | **Consolidation & hardening — the milestone.**  Bundles the whole 1.3.32 → 1.3.37 cycle.  **(1) The marquee: EPUB import** — **`inkhaven import-epub <file.epub>`** reads an EPUB (container → OPF → spine) into a Book → Chapters → paragraphs of converted prose (headings / `*strong*` / `_emph_` / lists), images to a sidecar; the inverse of `inkhaven epub`; `--book-name` / `--dry-run`; built on in-tree `zip`+`quick-xml`.  **(2) Surfacing the analytics** — project doctor scan (`inkhaven doctor --scan`), the unified review pass (`Ctrl+B Shift+C` / `inkhaven check`), the AI cost dashboard (`Ctrl+B $` / `inkhaven cost`), the command palette (`Ctrl+V Space`), Output-pane filters, `inkhaven goals` + lifetime-best streaks + the in-app goals editor, and the project-wide snapshot browser (`Ctrl+F6`).  **(3) Completing the config** — 13 hardcoded behaviours became opt-in HJSON (`cost:`, `project_lock:`, `goals.day_boundary` utc\|local, five `editor` knobs, `backup.keep_last`), every default preserving behaviour.  **(4) Hardening** — a pre-1.4.0 audit + 16 verified fixes (focused-pane save, hook panic isolation, typst pipe-deadlock, crash-safe store ordering, schema versioning, …), fuzz coverage for every untrusted parser, and the advisory project lock.  **No external app/binary deps; no new runtime crates across the whole milestone.**  New tutorials 82–86. |
| **1.3.36** | 2026-06   | [`1.3.36.md`](1.3.36.md)          | **Every snapshot, and a lock on the door.**  Snapshot browser + the first slice of the road-to-1.4.0 hardening sweep.  **(1) Project-wide snapshot browser** — **`Ctrl+F6`** lists every snapshot across *all* paragraphs (not just the open one's `F6` history), newest first, one row each (timestamp · words · paragraph · annotation): `/` filters by title or annotation, `V` diffs the selection against its paragraph's current text (same diff modal `F6` uses), `Enter` opens that paragraph + its `F6` picker.  Built on a new `Store::list_all_snapshots()` + the proven `compute_line_diff`.  **(2) Parser fuzzing** — never-panic proptests for the three importers that read untrusted files: Scrivener **RTF**, **Typst** syntax check, and the Scrivener **`.scrivx`** binder XML (7 tests, ~256 cases each; no panics surfaced).  **(3) Advisory project lock** — an OS advisory lock (`flock` via the existing `fs2`) on `<project>/.inkhaven.lock` so two sessions don't corrupt `metadata.db`/`.session.json`; the kernel releases it on crash so there's no stale-lock cleanup.  Per the permissive principle it **informs, never blocks**: on conflict you get a warning + "Open anyway? [y/N]", and unsupported filesystems just proceed.  Plus **goals-editor fixes** from 1.3.35 (Backspace now deletes across terminal encodings; `0` fields seed empty; the heatmap opens the editor on `e`).  **No external app/binary deps; no new runtime crates.**  Tests 1813 → 1825. |
| **1.3.35** | 2026-06   | [`1.3.35.md`](1.3.35.md)          | **Keeping count.**  Writing goals were already ~90% built (streak engine, per-book pacing, daily targets, status-ladder, active-time, the `Ctrl+V g` modal); this release surfaces, extends, and makes them editable.  **(1) `inkhaven goals`** — the missing terminal surface, reusing the *exact* `build_snapshot` engine: project + per-book totals, today vs `goals.daily_words` (bar), current streak **and lifetime best**, per-book pace + deadline, weekly status-ladder, active time, 30-day sparkline.  Read-only.  **(2) Lifetime best streak + milestones** — the streak now knows its **all-time best** (full history, same grace rule), shown as `· best Nd` in the CLI + modal; new **`hook.on_streak_milestone ( days -- )`** fires once when the streak crosses **7 / 30 / 100 / 365** upward — informative, never blocking, no re-fire on reopen.  **(3) In-app goals editor** — press **`e`** in the `Ctrl+V g` modal to edit `daily_words` / `active_minutes_daily` / `streak_grace_per_week`; commit writes the changed keys back to `inkhaven.hjson` through the **comment-preserving surgical-splice** pipeline (versioned backup in `.config-backups/`, atomic write) — every comment + unrelated stanza survives, applied live without restart.  Plus: dropped two dead symbols to clear build warnings.  **No external app/binary deps; no new runtime crates.**  Tests 1804 → 1813. |
| **1.3.34** | 2026-06   | [`1.3.34.md`](1.3.34.md)          | **The review pass, and where the money goes.**  Two road-to-1.4.0 consolidation features.  **(1) Unified review pass** — **`Ctrl+B Shift+C`** (or `inkhaven check`) runs *every* fast, deterministic checker at once: the world fact-checker + Inner Socrates over the **open paragraph**, plus the timeline critique over the **project**, all into the **Output pane** (where 1.3.33's `f`/`S`/`t` filtering slices the combined findings) with a `fact N · socrates N · timeline N` summary — instant and LLM-free.  The tree shows a per-node **report-card badge** (`⊗`/`⚠`/`●` + count) aggregated up from the source paragraphs, so you see *where* attention is needed.  **(2) AI cost dashboard** — **`Ctrl+B $`** (or `inkhaven cost`): today's LLM usage in one view — capped **daily budgets** (slow tracks) with usage bars, plus **other AI calls today by category** (chat / grammar / explain / critique / continuation / translation / …, now tracked at the one inference chokepoint — the whole picture, not just the capped tracks), and the total.  Counts are per UTC day (reset 00:00 UTC); extensible to new analytical threads.  Per Inkhaven's permissive principle, **cost control informs, it doesn't gate** — past a daily budget the slow tracks **warn and continue**, the author decides.  Both self-list in the palette + quick reference; KEYBINDING §1.1 "Any pane" table.  **No external app/binary deps; no new runtime crates.**  Tests 1795 → 1804. |
| **1.3.33** | 2026-06   | [`1.3.33.md`](1.3.33.md)          | **Command palette + a filterable Output pane.**  Two road-to-1.4.0 QoL features, both about finding things fast.  **(1) Command palette** — **`Ctrl+V Space`** opens a fuzzy finder over *every* command (type to filter by name / chord / description, `↑↓` select, `Enter` run); it's a projection of the live keybinding registry so it reflects your actual bindings and self-lists, and it's surfaced in the Quick reference (`Ctrl+B H`, plus `?` from the Tree pane).  Bound to `Ctrl+V Space` — a two-key chord with no `Ctrl+Shift+<letter>` terminal ambiguity (`Ctrl+P` stays editor-paste).  **(2) Output pane filtering** — the pane now collects findings from 5+ subsystems, so narrow it: **`f`** by **source** (fact-check / socrates / timeline-critique / world / translation / lexicon / variety / ai / bund / other, via a kind→source classifier), **`S`** by **minimum severity**, **`t`** to **this paragraph only**, **`c`** clears; the title shows `shown/total · <filter>` and the filter **persists** in `.session.json`.  Also documents the Output pane's keys for the first time (KEYBINDING §4.1) + an opt-in `INKHAVEN_KEYLOG` tracer.  **No external app/binary deps; no new runtime crates** (both are read-side views over the existing registry + message store).  Tests 1771 → 1795. |
| **1.3.32** | 2026-06   | [`1.3.32.md`](1.3.32.md)          | **Project doctor.**  Opens the road to **1.4.0** (a consolidation & hardening milestone — see [`ROADMAP-1.4.0.md`](../PROPOSALS/ROADMAP-1.4.0.md)) with the stability bookend.  `inkhaven doctor --scan` learns **referential integrity** — five new classes over the in-memory hierarchy catching the dangling UUIDs that rot from deletes / partial restores / hand-edits: **`broken-parent-ref`** (Critical — a `parent_id` pointing at a non-existent node, so the node is detached/unreachable), **`dangling-paragraph-link`** (a `linked_paragraphs` target was deleted), **`dangling-event-ref`** (an event references a deleted character/place), **`sibling-slug-collision`** (two children share a slug → their files collide), and **`duplicate-system-book`** (two Books share a `system_tag` → ambiguous lookup).  They run in the default scan (CI exit 2 on ≥ Warning), gate by `--class`, and emit to `--json`; detection-only this release.  Also stands up the **property-test spine**: a `proptest` dev-dep, perf budgets as ordinary `cargo test` assertions (referential scans @1k nodes < 500ms — O(n²) guard), and a never-panic sweep over the three panic-prone parsers (calendar parse/format/round-trip, HJSON config on arbitrary + brace-soup input, language detection on arbitrary unicode / emoji / 100k chars).  **No external app/binary deps** (one pure-Rust dev-crate, test-only).  Tests 1725 → 1771. |
| **1.3.31** | 2026-06   | [`1.3.31.md`](1.3.31.md)          | **The timeline critique, pruned.**  RFC TIMELINE-2-INTEGRATION closes the timeline-aware trilogy by refactoring the legacy timeline AI critique (1.2.6+).  Four of its five audit items now have better homes — travel-time + co-location → the world fact-checker (`travel_time` / `co_location`), date mismatches → `date_coherence`, pacing → INNER_SOCRATES `temporal_density` — so they're removed here.  What stays is the genuinely **timeline-internal** specialty no other system understands: **orphan events** (`⊘`, graded by **significance × staleness** — a detailed long-orphaned event is a contradiction, a fresh stub a note) and **fuzzy-precision overlaps** (`⧉`, `season`/`month` windows colliding suspiciously, with multi-event **clusters**).  The `y`/`Y`/`Ctrl+Y`/`F12` chords now emit **structured findings to the Output pane** (not streaming AI prose), localized to five languages, with optional cost-capped LLM **elaboration**.  New CLI `inkhaven event critique` (`--track`/`--book-name`; `--migration-check` / `--diff` map the move; `--legacy` keeps the old audit behind a deprecation warning); a `timeline.critique` config block; five read-only `ink.event.critique.*` Bund words.  Timeline **data**, the `event` CLI, the calendar, the `Ctrl+V e` picker, the swim-lane view, and `ink.event.*` are all unchanged.  **Zero new deps.**  Tests 1725 → 1752.  One new tutorial (81); 31 updated. |
| **1.3.30** | 2026-06   | [`1.3.30.md`](1.3.30.md)          | **The fact-checker learns *when*.**  RFC WORLD-5 — the world fact-checker (1.3.25–1.3.27) knew *what* your world looks like but not *when* each scene happens; 1.3.30 connects it to your [timeline](../Tutorials/31-story-timeline.md), so a paragraph linked to an event is checked against ground truth instead of prose inference.  Four timeline gains, automatic (`Ctrl+B W → F` / ambient), five languages, magic-ledger-respecting: **calendar-grounded season** (snow in a summer-dated scene → contradiction), **event-derived travel time** (prose "three days" vs a 35-day event gap — the flagship), a new **`date_coherence`** category (a *midsummer feast* in a winter-dated scene), and a new **`co_location`** category (a character in two places at overlapping times — whole-timeline check via `inkhaven realworld co-location`).  Timeline-derived findings carry a **📅** marker in the Output pane.  CLI gates with `fact-check --timeline-aware auto\|on\|off` / `--timeline-only`; five read-only `ink.world.fact_check.timeline.*` Bund words (`events_near` / `events_for_character` / `events_for_place` / `season_for` / `effective_date`).  The legacy timeline AI critique (1.2.6+) runs unchanged alongside during the interim.  **Purely additive** to WORLD-4 (compiler, plakat, every existing check, CLI/TUI surface, and schema all unchanged; projects without a timeline get exactly 1.3.27).  Also ships a tutorial for the Inner Socrates conversation (79).  **Zero new deps.**  Tests 1713 → 1725.  Two new tutorials (79, 80). |
| **1.3.29** | 2026-06   | [`1.3.29.md`](1.3.29.md)          | **Inner Socrates, in conversation.**  A focused follow-on to 1.3.28 — the Socratic interrogator (RFC INNER_SOCRATES-1; reference [`INNER_SOCRATES.md`](../INNER_SOCRATES.md)) becomes **interactive**.  The AI pane's **F9** scope cycle gains **Socrates** (after Facts): a sticky **conversation** scope that seeds the chat with the active Reader Persona's voice + the open paragraph's questions, then hands you the prompt (the persona discusses; it never drafts your prose) — the same conversation `Ctrl+B J → C` opens, now in the standard scope cycle, with the scope shown in the AI header.  **Per-finding outcomes** on a Socratic question in the **Output pane**: **`i`** record-as-intent (declare the category a deliberate choice, chapter-scoped — writes an intent-ledger entry that stops the question here), **`m`** make-note (a **Socratic Notes** entry quoting the question + the passage with room for your response), **`x`** mark-addressed, **`d`** dismiss (still feeds the promotion mechanism); each dismisses the message once handled, and the Output footer advertises them.  Completes INNER_SOCRATES-1's interactive layer.  **Zero new deps.**  Tests 1713 (stable). |
| **1.3.28** | 2026-06   | [`1.3.28.md`](1.3.28.md)          | **Inner Socrates.**  A third examined-authorship pillar (RFC INNER_SOCRATES-1; reference [`INNER_SOCRATES.md`](../INNER_SOCRATES.md)) — the ConLang Suite examines your languages and the world simulator your world; **Inner Socrates examines your prose**, surfacing **questions** (never corrections) about the assumptions it treats as given, the framings it presupposes, the tensions inside it, what each scene does for the work.  Two tracks like the world fact-checker: a **Fast track** (deterministic, instant, no LLM — 7 categories: asserted necessity / hedging / structural patterns / unattributed dialogue / sentence length / tense shifts / pronoun ambiguity, five languages, ambient on a writing pause or `Ctrl+B J → F`) and a **Slow track** (the configured LLM, cost-capped — 5 prose categories: hidden assumptions / internal tensions / framings / significance / echoes, plus 3 that read the prose against the project **timeline**: dramatization gaps / implications / temporal density).  Three severities — **Notice** (hidden by default) / **Inquiry** / **Probe** — onto the Output pane.  **Five Reader Personas** (Inner Socrates, the Careful Editor, the Skeptical Reader, the First-Time Reader, the Slow Reader), each calibrated to read differently; author your own (`persona new`, or `Ctrl+B J → N` AI wizard), stored at `~/.config/inkhaven/personas/` or the new **Intent** system book (the 13th).  The **intent ledger** — the prose sibling of WORLD-4's magic ledger, same vocabulary — suppresses what you declared deliberate; a **promotion mechanism** builds it from repeated dismissals, and **`.isl` bundles** carry series-level intentions to the next book.  A **conversation** mode (`Ctrl+B J → C`) seeds the AI pane with the persona's voice + the paragraph's questions to talk it through (it discusses, never rewrites).  Full CLI (`inner-socrates check / timeline / persona / suggestions / bundle / findings`) + read-only `ink.inner_socrates.*` Bund words.  Also ships **WORLDBUILDING.md**, the WORLD-4 reference.  **Zero new deps** (all inherited from PANE-1 + WORLD-4).  Tests 1658 → 1713.  One new tutorial (78). |
| **1.3.27** | 2026-06   | [`1.3.27.md`](1.3.27.md)          | **The world, mapped (and a deeper checker).**  1.3.25 built a world and 1.3.26 read your prose against it; 1.3.27 **draws** the world and deepens the checker (RFC WORLD-4, toward P7; plan [`WORLD-4_PLAN.md`](../PROPOSALS/WORLD-4_PLAN.md)).  **Maps** — **`inkhaven realworld map`** emits a **MapSpec v2** from the compiled geology / climate / hydrology / demographics layers and renders it with [**plakat**](https://crates.io/crates/plakat) (`plakat map --map-spec` loads our spec and skips its own LLM): a **features PNG** + a **GeoJSON** under `assets/maps/`, mountain ranges clustered from the heightfield, rivers tracing their real D8 course, settlements as landmarks (coastal cities → ports), and the resolved positions read back to **refine each accepted Place's coordinates** (`--spec-only` / `--no-ingest`; `Ctrl+B W → M`; plakat optional — a missing binary degrades to a notice).  **A deeper fact-checker** — a **slow track** (`fact-check --slow`) asks the LLM for the subtle contradictions patterns miss, with a **cost preflight** (estimated tokens + daily tally), a per-call soft cap (`--max-cost` / `--force`), a daily ceiling, and **retry-with-backoff**; a **coherence pass** (`realworld coherence <node>`) checks a run of paragraphs **against each other** citing the `¶` numbers; **scope chords** (`Ctrl+B W → F →` `P` paragraph / `B` book / `R` recent); an opt-in **idle auto slow-check** (`Ctrl+B W → S`); and a fifth fast category, **economy** (a metal worked that the geology doesn't yield).  **Multilingual & never-fail** — place names resolve in their **grammatical cases** (`в Москве` matches `Москва`; German genitive), detection reports a **confidence** and degrades to English rather than guessing, the optional enhanced parser (`INKHAVEN_LANG_MODEL`) is never required, and detection never panics.  **Author-declared setting** — optional `geography` / `hydrology` / `economy` blocks + expanded `geology` materialize into a **Setting** chapter; **declared landmarks** become gazetteer entries resolved by name and **declared resources** join the checker's known goods.  Ships a complete [`examples/realworld/Earth.hjson`](../../examples/realworld/Earth.hjson) and fixes the stale World overview panel.  **Zero new deps** (plakat is an optional external binary; the MapSpec + GeoJSON use `serde_json`).  Tests 1625 → 1658.  Two new tutorials (76, 77). |
| **1.3.26** | 2026-06   | [`1.3.26.md`](1.3.26.md)          | **The World Fact-Checker.**  The other half of the world simulation (RFC WORLD-4 Branch B, fast track; plan [`WORLD-4_PLAN.md`](../PROPOSALS/WORLD-4_PLAN.md)) — 1.3.25 built a world; 1.3.26 reads your prose and flags claims that don't fit it, **as you write**.  A **magic ledger** (`magic:` block in `world.hjson`) declares your world's exceptions to physics — each rule names a `kind`, the categories it `covers`, and who/where it applies to; the checker consults it **lazily** (only after a candidate warning) and suppresses covered, applicable findings with a note instead of nagging.  The **fast-track fact-checker** is deterministic + instant (no LLM), four categories: **travel time** (distance + duration → implausible pace, pure prose), **climate** (weather contradicting a place's climate zone), **demographics** (a population far from the modeled figure), **astronomy** (a moon count vs the world's sky).  Climate + demographics resolve place names through a **gazetteer** built from the Place↔World cross-references — closing the loop (compile → accept cities → write → check).  **Real-time**: when a project has a world, pausing on a paragraph runs the check and the findings appear in the **Output pane** (no chord, no focus stolen; a re-check replaces the paragraph's prior findings).  Explicit forms: **`Ctrl+B W` → `F`** (open paragraph) and headless `inkhaven fact-check --text "…"`.  The `Ctrl+B W` hub gains `F` alongside `C` (compile) and `P` (proposals).  **Zero new deps** (reuses `regex` + the DuckDB stores + the Output pane).  Non-breaking + opt-in (only runs with a `world.hjson`).  Tests 1613 → 1625. |
| **1.3.25** | 2026-06   | [`1.3.25.md`](1.3.25.md)          | **World Simulation.**  Inkhaven gains an actual simulated world — a new **`inkhaven realworld`** compiler turns a structured `world.hjson` into a coherent, physically-grounded world materialized into a new **World** system book (first slice of RFC WORLD-4, the compiler half; plan [`WORLD-4_PLAN.md`](../PROPOSALS/WORLD-4_PLAN.md)).  Five **deterministic** layers, each a pure function of `(definition, seed)`: **astronomy** (Kepler year, insolation, lunar synodic periods, tides, calendar-divergence flag), **geology** (seed → tectonic plates → procedural heightmap → continents / mountains / minerals, or **DEM import**), **climate** (zonal model — stellar-flux mean, latitude profile, elevation lapse, rainfall belts + orographic rain shadows → Köppen biomes + winds), **hydrology** (D8 flow → rivers with Strahler order → lakes → watersheds → settlement priors), **demographics** (biome carrying-capacity → a Rank-Size hierarchy of cities / towns / villages).  Each **materializes** into the World book (10th, after Artefacts) + a heightmap PNG; idempotent.  A **proposal queue** turns settlements into named **Place** records you accept/reject (`realworld propose` / `proposals …`), recording a **Place↔World cross-reference** on accept; re-running never re-proposes a resolved site.  **`Ctrl+B W`** is the World overview hub — **`C`** compiles + materializes + seeds the queue, **`P`** reviews proposals.  Also **completes RFC PANE-1**: per-kind `Enter`, `e` edit+remember, `ai_task_complete` notices, bare-`print` mirror, Output as the default launch pane; new **`Ctrl+B D`** deterministic translation + lexicon/variety routing (focus mode → `Ctrl+B Shift+W`).  Two pure-Rust deps (`noise` + `delaunator`, geology only); else zero new deps.  Non-breaking.  Tests 1582 → 1613. |
| **1.3.24** | 2026-06   | [`1.3.24.md`](1.3.24.md)          | **The Output Pane.**  A new right-side **Output** pane for structured one-way notifications from every subsystem — the first slice of RFC PANE-1, the planned TUI rearchitecture (plan [`PANE-1_PLAN.md`](../PROPOSALS/PANE-1_PLAN.md)).  The AI pane stays a conversation; Output absorbs everything Inkhaven *tells* you.  **Zero new deps** (reuses DuckDB / ratatui / Bund VM / chords).  **`Ctrl+B Tab` / `Shift+Tab`** cycle the right region between Output and AI (default AI; launch view unchanged); messages carry a severity icon (`●`/`⚠`/`⊗`/`↻`) + kind + summary, pinned on top, with per-message `o` expand (a translation's per-word trace renders inline) · `d` dismiss · `p` pin · `r` **remember** (commit a translation to memory) · `a` **ask the AI** (carries the message's full detail into the conversation by reference, not value).  Persisted in a per-project DuckDB store; headless CLI `inkhaven output show|emit|dismiss|clear`.  **Translation (LANG-3)** routes into Output (`translation_result` + a `⚠` uncovered-word report); new **Bund `ink.io.*`** stdlib (print/log/notify/message.*) gives script output a home in the TUI.  Non-breaking; the shell CLI is unaffected.  Tests 1576 → 1582. |
| **1.3.23** | 2026-06   | [`1.3.23.md`](1.3.23.md)          | **Local Translation: the ConLang Suite learns to translate.**  A constructed language can now be **translated** — English↔conlang and conlang→conlang — fully offline, deterministically, improving as you correct it (core of RFC LANG-3; reference [`CONLANG.md`](../CONLANG.md)).  **Python-free, training-free, zero new deps.**  **Tier 1 (rule-based)** — **`language translate`** maps each English word to a headword by its lexicon gloss and hands the clause to the LANG-1 syntax engine, so it reorders + inflects for free (*the bird sees the stone* → `kira nami pata` SVO / `kira pata nami` SOV); lexicon-aware parsing (verb by meaning, adjective agreement, number); **`reverse`** (conlang→English) and **`cross`** (conlang→conlang via an English pivot), each with a per-word confidence + trace.  **Tier 2 (retrieval, not a trained model — Amendment A1)** — the corpus *is* the knowledge, so it's retrieved via the in-binary `fastembed` + vector store: **`remember`** confirms a translation reused immediately (no retraining; exact overrides with the rule-based kept as an alternative, near matches are **semantic**), **`corpus`** seeds from a bundled English pool, **`eval`** scores quality reference-free (round-trip + coverage), **`export-translation`** ships the system as a portable `.itm` pack.  Full Bund surface (`lang.translate`/`reverse`/`cross`/`remember`/`memory`/`corpus`/`eval`/`export`).  Tests 1548 → 1576. |
| **1.3.22** | 2026-06   | [`1.3.22.md`](1.3.22.md)          | **The ConLang Suite: Sociolinguistics & Contact.**  A whole new pillar (RFC LANG-2) — a constructed language stops being uniform and lives among its speakers and neighbours (reference [`CONLANG.md`](../CONLANG.md)).  The insight: a **dialect is a sound-change chain applied synchronically** and a **loanword is a phonotactic repair**, so the features mostly orchestrate the LANG-1 engines.  **Variation** (`varieties` block) — a variety is a delta of ordered `sound_changes` + suppletive overrides; **`language varieties`** / **`lect`** (render in a dialect, `kata` → `kada`) / **`dialects`** (the dialectology table).  **Borrowing** (`loan_phonology` block) — **`language borrow`** adapts a donor word by perceive (nearest native sound) + repair (epenthesis/deletion), `tras` → `tulasu`.  **Areal features / Sprachbund** (`contact` block) — **`language areal`** overlays convergence (✓ / → / +); `family-tree` gains horizontal contact edges.  **Speech communities** — places carry a `--variety`, characters a `--native-variety`; **`language ecology`** (+`--svg` atlas) and **`language idiolect`** render a character's own dialect.  **Grammar book** gains Variation + Contact sections.  **Advisory AI** — `propose-dialect` / `propose-loans` / `areal-check` (the AI proposes, the engine validates, `--yes`-gated).  Developer's guide gains Part VI (*A Language in a World*) and Part XI (*Scripting Your Language* — a gentle Bund intro + full API reference).  Deterministic core, advisory AI, zero new deps.  Tests 1533 → 1548. |
| **1.3.21** | 2026-06   | [`1.3.21.md`](1.3.21.md)          | **Scripting the ConLang Suite from Bund.**  Opens the whole ConLang Suite to Bund, Inkhaven's scripting layer — one script can define, inspect, generate, AI-author, and typeset an entire constructed language, interchangeable with the JSON/CLI path (reference [`CONLANG.md`](../CONLANG.md)).  New **`ink.lang.*`** tree (~37 words, also `lang.X`): **define a whole language** (`init`/`add_word`/`define` write the same HJSON blocks the book stores); **inspect every layer** (generate_word/syllabify/ipa/stress/tone/transliterate/gloss/paradigm/derive/agree/sentence/relative/complement/coordinate/stats/audit/query/gaps/sound_change/cognates/family_tree/names/prose/poem — results as native Bund dicts/lists); **mutate** (remove_word/derive_add/grammar_set/idiom_add/metaphor_add); **AI generation** (compose/reconstruct/realism_check/generate_lexicon — advisory); **produce files** (dictionary/grammar_book/font_build/glyph_lint/glyph_draft).  Native `lang.dict` builder aliased to `word`/`rule`/`phoneme`.  Classified into the scripting policy (store_read allowed; store_write/ai_write/fs_write default-denied); AI words advisory; sandboxed paths.  Book gains a *Scripting (Bund)* section + pastel-green "What you learned" recaps.  Zero new deps.  Tests 1531 → 1533. |
| **1.3.20** | 2026-06   | [`1.3.20.md`](1.3.20.md)          | **Complement clauses, and a deeper developer's guide.**  A focused follow-on to 1.3.19's syntax engine (reference [`CONLANG.md`](../CONLANG.md)).  **Complement clauses** (**`language complement`**) build a sentence whose object is a whole clause ("I know *that the bird sees the stone*") — the matrix subject/verb wrap an embedded clause via an optional complementizer; since the complement fills the matrix object slot, word order places it (post-verbal in SVO, pre-verbal in a verb-final language) and the embedded clause still case-marks its object.  Completes the syntax-depth set (sentence → negation → questions → relative → coordination → complement).  **Book** — new dedicated *interchange* chapter (Standard Format / Toolbox / FieldWorks / Lexique Pro, PolyGlot, ConWorkShop, CAT tools / XLIFF, Anki, linguex, with a CSV round-trip), plus a whole-book depth pass (20 new glossary terms; worked circumfix/ablaut/reduplication, sonority, tone-output, and family-tree examples; stale notes fixed), and a typographic fix keeping section headings off the bottom of a page.  Deterministic core, backward compatible.  Zero new deps.  Tests 1529 → 1531. |
| **1.3.19** | 2026-06   | [`1.3.19.md`](1.3.19.md)          | **The ConLang Suite: syntax, interchange & creative text.**  Makes a constructed language *speak* and lets it *travel* (reference [`CONLANG.md`](../CONLANG.md)).  **Syntax engine** — **`language sentence`** assembles a clause from subject/verb/object, ordering by `word_order`, case-marking by `alignment`, inflecting each noun, and running agreement, with an interlinear gloss (and the grammar book now prints a worked example from the lexicon).  **Negation + polar questions** (`--negate`/`--question`) realize per the `negation`/`question` typology (particle/affix; particle/inversion/morphology), never inventing a word.  **Relative clauses** (**`language relative`**) build "the bird that sees the stone" — the embedded clause case-marks and agrees, pre- or postnominal per `relative_clause`.  **Coordination** (**`language coordinate`**) joins nouns or clauses with a conjunction.  **Interchange** — `export` gains **xliff** (CAT-tool translation memory), **linguex** (LaTeX glossed examples), **ipa-chart**; **`language import`** reads **Toolbox / MDF / Lexique Pro** SFM and **PolyGlot** (`.pgd` zip + xml), previewing until `--yes`.  **Semantic-gap finder** (**`language gaps`**) diffs the lexicon against the bundled **Swadesh-100** (every working language) or a custom concept list.  **Creative text** (**`language compose`**) generates names, grammatical prose, metered verse, and lexicon-constrained AI blessings/curses.  Deterministic core, advisory AI, backward compatible.  Zero new deps.  Tests 1490 → 1529. |
| **1.3.18** | 2026-06   | [`1.3.18.md`](1.3.18.md)          | **The ConLang Suite: morphology depth & a developer's guide.**  Deepens morphology after LANG-1 completed, and ships a beginner's book (reference [`CONLANG.md`](../CONLANG.md)).  **Non-concatenative morphology** — a morpheme can be an **infix** (`sulat` → `s-um-ulat`), a **circumfix** (`form: "ge_t"`), an **ablaut** process (SPE `rules` swapping a stem sound), or **reduplication** (`full` / `initial_cv` / …); all used in paradigm cells like affixes, with allophony at every seam.  **Affix precedence** — `precedence` orders stacked affixes by closeness to the root.  **Agreement (concord)** — an `agreement` block + **`language agree`** inflects a dependent to match its head's features (`mira` → `mirai`, *bright-PL*).  **Grammar book** now groups affixes by `category`/`value` and shows each one's kind, with an agreement section.  **New book** — *Developing a Constructed Language with Inkhaven* (`Book/CONLANG_DEVELOPMENT/`), a ~120-page guide teaching the whole suite from zero for readers new to linguistics *and* Inkhaven.  Backward compatible; deterministic core.  Zero new deps.  Tests 1490 → 1498. |
| **1.3.17** | 2026-06   | [`1.3.17.md`](1.3.17.md)          | **The ConLang Suite (Part 4: the books) — LANG-1 complete.**  Turns a constructed language into typeset books (reference [`CONLANG.md`](../CONLANG.md)).  **Grammar book** (`grammar-book --format md\|typ`) — a reference grammar from the language's data (phonology / morphology / typology / idioms / sample texts), the companion to the 1.3.16 dictionary.  **Learner's textbook** (`tutorial --format md\|typ --provider …`) — **AI-written**: the model authors a complete graded course (introduction, pronunciation guide, lessons that *explain* the grammar with worked examples, a reading, exercises), constrained to the language's actual data — the prose is generated, never hardcoded.  **Study guide** (`grammar-book --study`) — an AI-written companion that defines + explains every linguistic term the grammar uses (case, allophony, SOV, nominative–accusative alignment, …); the reference itself stays deterministic.  **A book design** — dictionary, grammar, and tutorial share a manual-style B5 layout (title page, contents, callout boxes), embed the conscript font, and compile to PDF.  **A complete worked example** (`examples/conlang/build-sample-language.sh` + checked-in `sample-output/`) builds a whole language end to end with an AI-drawn font.  AI writes Markdown, a deterministic Markdown→Typst converter + scaffold makes it always compile.  Completes RFC LANG-1 (P1–P7).  Zero new deps.  Tests 1479 → 1490. |
| **1.3.16** | 2026-06   | [`1.3.16.md`](1.3.16.md)          | **The ConLang Suite (Part 3: writing systems, fonts & output).**  A constructed script goes from hand artwork or an AI description to a real TrueType font, a Typst layout, and a typed input method — fully in-process, no external tool (reference [`CONLANG.md`](../CONLANG.md)).  **Writing systems + fonts** — **glyph preflight** (`glyph-lint`; filled-paths-only, plus a counter-mistake warning on near-white fills); **SVG → UFO → TrueType** (`font-build --format ufo\|ttf\|both`; the TTF assembles a full OpenType table set with `write-fonts`, cubics quadified, passes a fontTools round-trip); **config-driven font block** (`font-import-glyph` binds a glyph to a phoneme + codepoint, `font-build --language` compiles the script from the book); **AI text-to-SVG glyph draft** (`glyph-draft`, advisory, preflight-gated, prompts reverse-wound counters — *validated live against DeepSeek*); **spatial templates** — one engine, two binding times: `font-compose` bakes a precomposed block (Hangul square / quadrat), `spatial-typst` arranges at layout time; **input method** (`transliterate`, greedy longest-key romanized → script).  **Analysis** — `stats` (inventory balance, phoneme frequency, syllable distribution, onset/coda usage, POS spread).  **Dictionary output** — `dictionary --format md\|typ`; the Typst path is a paginated two-column A5 book embedding the conscript font with native-script headwords.  Deterministic core, thin AI layer, advisory.  **One new dependency** (`norad`; `write-fonts`/`kurbo` reuse crates already in the tree, `fontc` deliberately avoided).  Tests 1439 → 1479. |
| **1.3.15** | 2026-06   | [`1.3.15.md`](1.3.15.md)          | **The ConLang Suite (Part 2: morphology & diachronics).**  Builds two whole pillars on the 1.3.14 substrate, each reusing the engines already in place (reference [`CONLANG.md`](../CONLANG.md)).  **Morphology completed** — **auto-gloss** (`language gloss` aligned Leipzig interlinear, recognising inflected + allophony-altered forms by generating paradigms forward and matching); **derived-form proposals** (`language derive` coins new lexemes — agent nouns, diminutives — with allophony); **grammar questionnaire** (`language grammar`, a WALS-aligned catalog of 16 typological features, `--set` validated); **idioms + metaphors** (`idiom-add` / `metaphor-add` / `idioms`).  **Diachronics** — a sound change *is* an ordered context rewrite, so the engine **reuses the allophony rewrite engine**: `language sound-change` (`tap > taf`), `derive-lexicon` (evolve a proto's whole dictionary through a daughter's chain), `family-tree` + `cognates` (a proto-form's reflex in every daughter), and the AI `reconstruct` (proto-form from cognates) + `realism-check` (chain plausibility).  Everything deterministic except the two AI checks + translation; AI advisory; extend-in-place (no new chapters).  Zero new dependencies.  Tests 1428 → 1439. |
| **1.3.14** | 2026-06   | [`1.3.14.md`](1.3.14.md)          | **The ConLang Suite (Part 1: phonology, lexicon, morphology).**  Inkhaven becomes the first constructed-language workbench *inside* the writing tool (RFC LANG-1; reference [`CONLANG.md`](../CONLANG.md)), layered on the existing 1.2.13 `Language` book.  **Phonology engine** — inventory / classes / templates / syllable-aware phonotactics → **allophony** (SPE rules `k > tʃ / _ i`) → **stress** (fixed or weight-sensitive Latin) → **bidirectional multi-scheme romanization** (contextual digraph disambiguation) → **tone sandhi**; deterministic word generator; six CLI inspectors (`generate-word` / `syllabify` / `ipa` / `stress` / `romanize` / `tone`).  **Lexicon + AI generation** — **`language generate-lexicon`** with a **complete dedup gate** (forms from the deterministic generator so they always obey the phonotactics; the AI assigns meanings in the working language; rejects illegal / homophone / duplicate-meaning / `--semantic` near-synonym via embeddings); plus `audit`, rich-field `query`, `scan-manuscript` (undefined words), and Places/Characters language links (sidecar).  **Morphology** — `language paradigm` applies a paradigm's morphemes to a root and runs allophony across the affix boundaries (`kata`+DAT → `katat`).  **In the editor** — `Ctrl+B X` ConLang hub overview + `:lang:` inline lexicon insertion.  Forms obey the language, meanings come from the AI, nothing duplicates; AI is advisory.  Flagship-in-progress (P3–P7 continue across 1.3.x).  Zero new dependencies.  Tests 1369 → 1428. |
| **1.3.13** | 2026-06   | [`1.3.13.md`](1.3.13.md)          | **Breadth: every language, cancellable jobs, print & ebook polish.**  Goes *wide* after the deep world-layer cycle.  **Cancel a deep refresh** — re-press `Ctrl+V Shift+F` and each scan honours a shared cancel flag between chapters/entities, stopping in seconds (finished scans keep their sidecars).  **Full multilingual** — the detector word lists no longer masquerade as English for an uncurated language (empty + honest); **`inkhaven lang status`** prints a coverage matrix and **`inkhaven lang bootstrap <lang>`** has the LLM lexicographer produce the full detector vocabulary (lemma form) for **any** language, `--yes`-patching `inkhaven.hjson` safely; all four world-check prompts are **localized** (en/ru/fr/de/es, English-with-warning fallback, 3-tier override) and force findings into the project language; detector config moved to per-language **maps** with worked Arabic / Hungarian examples.  **Print** — **`inkhaven pdf booklet`** is a zero-config saddle-stitch booklet auto-fitting the sheet to 2× the page (any trim), and the **`a5_book`** profile imposes a proper perfect-bound A5 codex from A4 sheets.  **Ebook** — EPUB export now embeds **inline images** (`<figure>` + OPF manifest) and **popup footnotes** (EPUB3 noteref/aside).  Zero new dependencies.  Tests 1359 → 1369.  One new tutorial (73). |
| **1.3.12** | 2026-06   | [`1.3.12.md`](1.3.12.md)          | **The background deep refresh.**  **`Ctrl+V Shift+F`** runs the whole world-layer AI batch (facts check + facts scan + drift + continuity, the `inkhaven world --deep` set, **in the manuscript's language**) on a **background thread** — the editor stays fully responsive, a `⟳ deep refresh` chip tracks progress, and the open story bible / Editorial Pass rebuilds itself from the fresh findings when it lands.  It runs in-process on a **clone of the editor's DuckDB connection pool** (single-writer lock means no second open; the pool is now tunable via `embeddings.pool_size`, clamped ≥2).  **Advisory** — reads your manuscript and writes findings to `.inkhaven/*.json` sidecars only; never edits your prose (rewrites stay manual via the Editorial Pass `f`/`F`, snapshot-gated + diff-reviewed).  **Stale findings announce themselves** — each scan stamps a cheap manuscript fingerprint, and the world report / bible / `edit` show `⚠ may be stale` (warn, never hide) when the prose has moved since.  Built on a reusable background-job harness the 1.4 AI Editor will reuse.  Zero new dependencies.  Tests 1354 → 1359. |
| **1.3.11** | 2026-06   | [`1.3.11.md`](1.3.11.md)          | **Drift depth + the world report.**  Rounds out world consistency (1.3.8 hard facts, 1.3.10 soft drift).  **Drift reads pronouns** — coreference-lite recovers pronoun-only descriptions ("Mara crossed the yard. She was taller…") via a precision-favouring recency anchor (single named entity per kind; ambiguity clears it; never crosses a chapter), with **multilingual** built-in pronoun sets (en/ru/fr/de/es) keyed by the project language and a Unicode-aware word-boundary check.  **`inkhaven world`** — one consolidated consistency snapshot (established facts + internal/prose contradictions + drift + continuity coverage + named anachronisms + a health summary); complements `edit` (walkable worklist) as a world-layer snapshot; `--json` gates CI, `--deep` refreshes the AI scans, `--entity <name>` zooms in.  The same health line banners the `Ctrl+V Shift+L` story bible.  **Coverage** flags entities defined in the books but never named in the prose (a dangling cast) — also an `info` `coverage` finding in `edit`, jumping to the bible definition.  `world` also names each anachronism + chapter; `drift list --entity` scopes the preview.  Zero new dependencies.  Tests 1346 → 1354. |
| **1.3.10** | 2026-06   | [`1.3.10.md`](1.3.10.md)          | **Semantic drift.**  The *soft*-consistency counterpart to 1.3.8: two descriptions of the same entity that diverge across the manuscript without a hard fact clash (a tavern "cramped and smoky" in ch.2, "airy and bright" in ch.20).  **Embeddings retrieve, the AI adjudicates** — cosine similarity finds same-topic descriptions but can't tell contradiction from relatedness, so drift reuses the **existing on-save vector index** to pull each entity's description paragraphs (keeping only the ones that name it), then asks the model which contradict.  No new index.  **`inkhaven drift scan`** writes `.inkhaven/drift.json` (`--json` gate); **`drift list`** previews the retrieval deterministically.  Surfaces in `inkhaven edit` + the `Ctrl+V Shift+R` cockpit as the `drift` category (Warn, **jump-only** to the divergent passage); `edit --deep` runs it.  The **`Ctrl+V Shift+L`** story bible shows a ⚠ drift badge + the chapter-ordered description trail under each flagged entity (persisted in the sidecar — no embedding load in the TUI).  Tunable via the `drift` config block.  This is the 1.4 Whole-Book AI Editor bridge — it builds the retrieve-then-reason loop.  Zero new dependencies.  Tests 1339 → 1346. |
| **1.3.9** | 2026-06   | [`1.3.9.md`](1.3.9.md)              | **Finish the Editorial Pass.**  Closes the four deferrals from the 1.3.6–1.3.7 cuts, taking the cockpit to its final 1.3 form.  **Span-scoped rewrite:** `f` on a localized finding now rewrites *only* the flagged phrase and splices it back (show-don't-tell / filter-word), leaving the surrounding prose alone; echo / pacing still rewrite the whole paragraph; the diff shows the full paragraph for context.  Pure char-indexed `splice_span` + `extract_phrase`, the span category marks the phrase between `« »` and asks for just its replacement.  **Filter-words join the worklist** — the last live-overlay detector not yet in `inkhaven edit`, surfaced as `filter` findings at `info` severity (sort last, never bury sharper findings), span-`f`-rewritable.  **Anachronism underlines live** in the editor (its own amber-orange `theme.style_warning_anachronism_fg`), self-gating on the setting `year` + the master style toggle.  **`F` batch fix-all:** walks every rewritable finding in the current filter through the *same* per-item diff review — never blind-applied; `a` accept+advance, `r` skip, `Esc` stop; progress + `N applied, M skipped` summary.  Quick-help / chord descriptions / Tutorial 68 refreshed.  Zero new dependencies.  Tests 1333 → 1339. |
| **1.3.8** | 2026-06   | [`1.3.8.md`](1.3.8.md)              | **World consistency.**  A long book builds a world (climate, geography, a cast with fixed attributes, a setting in time); the tools to keep it consistent were scattered.  1.3.8 fills the four remaining gaps.  **`inkhaven facts check`** runs an AI pass over the *whole* Facts book for contradictions between the facts themselves ("winters are mild" ⟷ "the harbor freezes each January"), cached + `--json`-gateable, also surfaced in `inkhaven edit` (category `world`).  **Anachronism detection:** set `editor.style_warnings.anachronism.year` and terms postdating it (a ~35-term built-in lexicon + your additive `terms`) flag in `edit` (category `anachronism`), jumpable to the word; off until a year is set.  **The story bible** — **`Ctrl+V Shift+L`** (L for Lore) — one consolidated, navigable view: every Character with the attributes `continuity extract` tracked across chapters beneath it, plus Places / Artefacts / Facts; `Enter` jumps to source.  **Series-shared facts:** point `facts.shared_path` at a directory of one-file-per-fact text files and a series shares one canon — `facts check` layers it (local wins), `facts import` snapshots it in.  Zero new dependencies.  Tests 1328 → 1333.  One new tutorial (69). |
| **1.3.7** | 2026-06   | [`1.3.7.md`](1.3.7.md)              | **Close the loop: AI rewrite-in-place.**  The Editorial Pass (1.3.6) *found* every problem and jumped you to it; 1.3.7 lets the AI *fix* the prose-level ones.  In the **`Ctrl+V Shift+R`** cockpit, a `✎` marks the rewritable findings — **echo** (vary the over-repeated word), **pacing** (tighten an overlong paragraph), **show-don't-tell** (rewrite telling to showing) — and **`f`** opens the finding's paragraph, streams a category-specific rewrite, and pops the diff-review (`a` accept snapshot-first, `r` reject), reusing the 1.2.11 rewrite→diff→snapshot machinery.  The rewrite prompt is 3-tier-tunable (`editorial-fix-<category>`).  Judgment findings (structure / continuity / fact / weak-scene) stay jump-only.  **Show-don't-tell** also joins the worklist as a finding (the editor overlay's regex, surfaced per paragraph with a char-range location).  Zero new dependencies.  Tests 1326 → 1328. |
| **1.3.6** | 2026-06   | [`1.3.6.md`](1.3.6.md)              | **The Editorial Pass.**  The 1.3 capstone (the "editorial-pass cycle" flagged back in 1.2.22): unify every detector into one ranked, walkable revision worklist.  **`inkhaven edit`** collapses the editorial `doctor` classes (echo / pacing / continuity / naming / dropped-character / …) + `plan check`'s structural findings + the Facts-scan sidecar into one list, errors first; deterministic (reads computed sidecars, no live AI), so `--json` gates a CI build and `--only` narrows it.  **`Ctrl+V Shift+R`** is the cockpit: `↑↓` navigate, `[`/`]` filter, **`Enter` jumps to the finding's chapter/paragraph** (the new capability — location resolution from a path / chapter title → node id), `s` skips, `d` defers (persisted, fingerprinted by text so it resurfaces only when the prose changes), `D` clears.  **`edit --deep`** re-runs the AI scans (Facts / tension / continuity) then aggregates.  `edit` is *manuscript readiness*; `doctor` stays *project integrity*.  Zero new dependencies.  Tests 1321 → 1326.  One new tutorial (68). |
| **1.3.5** | 2026-06   | [`1.3.5.md`](1.3.5.md)              | **Scene craft: scaffold, sequel, second opinion.**  Deepens the scene grain 1.3.4 opened.  **Scene scaffold:** `inkhaven plan scene scaffold --chapter <slug>` (or `--all`) reads the chapter prose and proposes the goal/conflict/disaster; in the `Ctrl+V Shift+K` scene board, `g` regenerates the selected card (proposal streams to the AI pane, `L` files it).  **Sequel cards:** `inkhaven plan sequel add\|list\|set\|remove` — the reactive counterpart (reaction → dilemma → decision); one unified card model (`Scene` gains `kind`, old cards load unchanged), weak-check flips by kind (scene = no turn, sequel = no decision), plus a two-scenes-in-a-row "unprocessed disaster" hint.  **Tension second opinion:** `inkhaven plan tension rate` AI-rates each chapter's felt intensity 0–100 (cached), adding an `ai` column to `plan check` and a third sparkline to the overlay beside expected + actual — two independent readings of where the middle sags.  Zero new dependencies.  Tests 1316 → 1321. |
| **1.3.4** | 2026-06   | [`1.3.4.md`](1.3.4.md)              | **The Planning Board — the shape of the rise and fall.**  Finishes pillar B (structure).  1.3.2 diagnosed where each beat *lands*; 1.3.4 adds what the Board couldn't see — **intensity** and **scene craft**.  **Tension curve:** every beat carries an *expected* intensity (the framework's authored dramatic shape) vs an *actual* one derived deterministically from open narrative obligations (the `inkhaven tension scan` ledger + open Threads), so a sagging middle is an objective finding ("Midpoint 33% where the framework wants 65%").  `plan check` prints a TENSION section; the **`Ctrl+V Shift+K`** outline draws expected/actual `▁`..`█` sparklines under the bars.  **Scene cards:** `inkhaven plan scene add\|list\|set\|remove` — each scene's goal → conflict → disaster, with a deterministic weak-scene (no-turn) check, folded into `plan check`, the `v` scene board, and `plan analyze`.  **Outline finished:** the deferred `t` (thread-link), `Enter` (jump-to-chapter), `v` (scenes) keys.  Zero new dependencies.  Tests 1307 → 1316. |
| **1.3.3** | 2026-06   | [`1.3.3.md`](1.3.3.md)              | **The Planning Board, fluent & complete.**  Finishes the Board opened in 1.3.2.  **Fluent:** `inkhaven plan map <beat> --chapter <slug> [--threads …]` / `plan unmap` write a beat's Planning-book HJSON in place, and `plan check` now prints the **CHAPTER SLUGS** / **THREAD SLUGS** to use — no slug-hunting.  The **`Ctrl+V Shift+K`** outline is editable: `m` maps a beat from a chapter picker, `s` cycles status, `a` streams the AI analysis (`L` in the AI pane files it into Planning).  **Complete (plan-first):** `plan scaffold --premise "<logline>"` writes a concrete intention into every framework beat; `--chapters` materializes back-linked chapter shells (opt-in, guarded).  **PDF-1 follow-ups:** three new imposition profiles (`us_perfect` / `us_chapbook` / `thick`), aspect-preserving cover art (`--fit cover\|fit\|stretch`) + spine-text auto-fit, JPEG (DCTDecode) grayscale, and preflight press-hazard reporting (overprint / transparency / spot colours).  **Polish:** CLI Prompts-book prompt tier, `stale-submission` doctor scan, `I`-lift of a streamed draft, `actions/checkout@v5`.  Zero new dependencies.  Tests 1294 → 1307. |
| **1.3.2** | 2026-06   | [`1.3.2.md`](1.3.2.md)              | **The Planning Board.**  Opens pillar B — *structure*, the third axis (Timeline = *when*, Threads = *arc payoff*, Planning = the skeleton).  Leads with **diagnosis, not card-shuffling**.  `inkhaven plan init --framework save_the_cat\|three_act\|story_circle\|hero_journey\|seven_point` scaffolds a framework's beats into a new **Planning** system book (HJSON paragraphs; map a beat with `mapped_chapter` + `threads`).  **`inkhaven plan check`** is the deterministic finding — coverage gaps, per-beat **position drift** (Midpoint at 64% vs target 50%), and **act word-share pacing** ("Act 1 is 30% — long"); no AI.  **`Ctrl+V Shift+K`** renders it as a position bar per beat.  **`inkhaven plan analyze`** (and `a` in the outline) maps beats→chapters + names the sag over the 1.3.1 digest.  Thread-links surfaced + validated.  Zero new dependencies.  Tests 1286 → 1294.  One new tutorial (67). |
| **1.3.1** | 2026-06   | [`1.3.1.md`](1.3.1.md)              | **Submission track.**  Pillar A's second half — getting a finished manuscript to an agent or editor, pure-Rust with no new dependencies.  **`.docx`**: `inkhaven docx` emits a hand-rolled Shunn-format Word document (the audit rejected `docx-rs` for hard-pulling a duplicate `zip` major version); `docx` is a `Ctrl+B O` book-take.  **Package (AI)**: `inkhaven submission digest` caches a compact whole-book context (per-chapter one-line summaries + Characters/Threads), then `submission query \| synopsis [--long] \| comps \| logline` draft into a new **Submissions** system book — synopses spoil the ending, comps are Local-pinned labelled suggestions.  `Ctrl+V q` picks a generator and streams it into the AI pane (3-tier prompt resolution).  **Tracker**: `inkhaven submissions add\|list\|status\|add-note\|remove` (the `.inkhaven/submissions.json` log) + the `Ctrl+V u` modal; `add-note` is a timestamped event trail.  Five `ink.export.*` Bund words (`fs_write`-gated).  Tests 1270 → 1286.  One new tutorial (66). |
| **1.3.0** | 2026-06   | [`1.3.0.md`](1.3.0.md)              | **Print production (PDF-1).**  The first minor since the 1.2 line — a complete, self-contained **PDF production subsystem** for taking a built book to a print shop or hand-binding bench, over a pure-Rust core (`lopdf` + `barcoders`, no external apps).  **Imposition** (the marquee): `inkhaven pdf impose` reorders a book into folding signatures — perfect-bound / saddle-stitch / side-stab, creep/shingling from the paper caliper, crop/fold/registration/spine/sig# marks, configurable through HJSON `imposition:` profiles (`--dry-run` plan, `Ctrl+B Q` TUI preview, `imposed_pdf` book-take).  **Cover + spine + barcode**: `pdf cover --pages N` computes the spine from page count + paper stock, with front art, back blurb, and a validated EAN-13 `--isbn` barcode (`cover_pdf` book-take; standalone `pdf barcode`).  **Preflight**: `pdf preflight` catches print-only problems — effective image DPI via CTM tracking (the screenshot-blown-up-to-full-page case), font embedding, page-size consistency, blanks.  **Page ops**: info / extract / delete / rotate / reorder / split / merge / metadata / outline.  **Finishing**: grayscale / optimize / watermark / sample.  All mirrored across CLI (`inkhaven pdf …`), the `ink.pdf.*` Bund stdlib, config (`imposition:` / `cover:` / `preflight:`), and `Ctrl+B O` book-takes.  Two new runtime deps (`lopdf`, `barcoders` — audited, pure-Rust, the first in several cycles).  One new tutorial (65).  Tests 1190 → 1270. |
| **1.2.23** | 2026-06  | [`1.2.23.md`](1.2.23.md)            | **Stability & fixes** — the last 1.2 before the 1.3 editorial-pass cycle.  Broken-pipe on stdout (`inkhaven … \| head`) no longer writes a spurious crash report (panic-hook Step 0, no SIGPIPE reset → TUI untouched).  Whole-tree **panic-surface re-audit**: fixed three UTF-8 byte-boundary slice panics (theme-colour parse, fact-check cursor jump, doctor naming scan — all reachable on multilingual / malformed input) and routed four `store` writes through `io_atomic`.  **SQL hardening**: the JSON/blob + progress stores now bind parameters instead of string-interpolating (both `sql_escape` copies removed; adversarial round-trip test).  **Find & replace polish**: `w`/`i`/`x` toggle whole-word / ignore-case / regex inside the review modal.  **D.8**: three copies of the manuscript walk collapsed into `Hierarchy::user_book_chapters()`.  Tests 1186 → 1190.  Zero new deps. |
| **1.2.22** | 2026-06  | [`1.2.22.md`](1.2.22.md)            | **Project-wide find & replace.**  The cross-book edit Inkhaven couldn't do — rename a character / term over the whole manuscript, safely.  Lexical (literal / whole-word / opt-in regex, *not* semantic) over a linear scan; no FTS index (the `regex` crate already in-tree → zero new deps).  In the editor: `Ctrl+R` → `Ctrl+B` toggles whole-book scope → a **review modal** shows every match in context, `Space` skips individual ones, `Enter` applies the kept ones — **snapshotting each touched paragraph first** (`F6` undo).  CLI: `inkhaven replace <pat> <repl>` with `--dry-run` preview + `--yes` apply (refuses to write otherwise), `--regex` / `--substring` / `--ignore-case` / `--book` / `--include-system`.  Whole-word + user-books-only by default (no `Will`/`will` footgun, won't touch Notes/Facts).  The review-gated apply machinery is the substrate for the 1.3 editorial-pass cycle.  Also: three consolidation-audit items closed as intentional non-duplicates (documented divergence, no merge).  Tests 1169 → 1186.  Zero new deps.  One new tutorial (64). |
| **1.2.21** | 2026-06  | [`1.2.21.md`](1.2.21.md)            | **The Facts book.**  A dedicated **Facts** system book for a world's invariants (climate, geography, seasons, distances, chronology) — free-form prose like Notes — and the AI plumbing to write against them.  **Facts AI scope** (`F9`) seeds a sticky, always-Local fact-analysis chat from the whole Facts book (refreshes when it changes).  **Fact-check chord** (`Ctrl+B Shift+X`) checks the open paragraph against the facts (scope locked to local), emits `claim \| fact \| detail`, and **`Ctrl+B Shift+J`** cycles the findings jumping the cursor to each flagged claim.  **Facts search** (`Ctrl+B Shift+S`) — a semantic-search modal to ground a chat in just the relevant facts (scalable for a big book).  **`inkhaven facts scan`** sweeps every chapter for contradictions (RAG-filtered, `--json` for CI); **`facts extract`** proposes world-facts from the draft for interactive accept (cold-start solver, deduped); **`facts init [--genre]`** scaffolds the starter categories (genre-aware).  Facts join the wiki-link system (provenance → Notes/Research; dependents via `Ctrl+V K`); opt-in `⚑N` status chip.  Multilingual throughout (en/ru/de/fr/es).  Tests 1160 → 1169.  Zero new Rust deps.  One new tutorial (63). |
| **1.2.20** | 2026-06  | [`1.2.20.md`](1.2.20.md)            | **Consolidation, hardening & global themes.**  Pays down the duplication audit the 1.2.19 cycle left behind, then spends the headroom on user-facing polish.  **Live echo overlay** (`Ctrl+B Shift+K`) — the inline companion to the `echo-repetition` scan underlines, in the open paragraph, words echoing across nearby paragraphs of the chapter (open paragraph read live, no per-keystroke I/O), in its own colour (`theme.style_warning_echo_fg`).  **EPUB cover images** — drop a `cover.png`/`.jpg` next to `inkhaven.hjson` and `inkhaven epub` embeds it as the EPUB 3 `cover-image` thumbnail + opening page (zero-config).  **User-global config cascade** — `~/.config/inkhaven/config.hjson` + `conf/*.hjson` layer over each project's `inkhaven.hjson` (global wins; partial overrides; honours `$XDG_CONFIG_HOME`) so one personal theme/keybind set applies everywhere; ships `color_styles/` with 15 popular classic/dark/light schemes (Dracula, Nord, Gruvbox, Solarized, Tokyo Night, Monokai, One Dark, Material Ocean, Catppuccin, GitHub Light, Ayu Light, …).  **Hardening:** `paragraph-too-long` doctor class (read-time threshold), low-disk pre-flight warning, uncommitted-changes quit guard.  **Bug:** Russian `ё`→`е` fold added to three older stem surfaces (concordance / style-warnings / name highlighter) so `пошёл`/`пошла` group.  **Internal:** six duplication categories consolidated into shared helpers (`text::normalize_stem`, `cli::resolve_user_book`, `cli::book_walk`, `ai::stream::collect_blocking`, `typst_prose`, `is_scene_break`).  Two new tutorials (61, 62).  Tests 1121 → 1160.  One new Rust dep (`fs2`). |
| **1.2.19** | 2026-06  | [`1.2.19.md`](1.2.19.md)            | **Revision & continuity (multilingual).**  The draft-3-to-final layer — four detectors + a submission export, built multilingual across a three-tier model (AI prompts / Snowball stemmer / per-language quantity lexicons).  `echo-repetition` flags a distinctive word reused close together (stem + window; all 18 Snowball languages).  `numeric-contradiction` flags reversed directions + mismatched durations via per-language quantity lexicons (`200 leagues north` … `200 leagues south`; `three day` … `a week`) — en/fr/es bundled, others skip cleanly.  `continuity-drift` (the headline): `inkhaven continuity extract` runs an AI pass building a character-fact bible (`.inkhaven/continuity.json`), the scan flags attributes that change across chapters (eyes green→brown), stemmer-normalised so inflection doesn't false-flag.  `unresolved-tension` (opt-in): `inkhaven tension scan` tags introduced/resolved tensions, the scan flags the ones never paid off.  `inkhaven manuscript` exports a submission-ready Shunn standard manuscript format typst doc (monospace double-spaced, title page + rounded word count + running header, scene breaks as `#`).  Config: `editor.echo_*`.  Closes the deferred A.5.b + A.6.b.  Tests 1053 → 1121.  Zero new Rust deps — reuses the existing stemmer / stop-word / whatlang / AI / typst stack.  A real multilingual lesson: the Russian Snowball stemmer needed a `ё`→`е` fold + is a stemmer not a lemmatiser (noun cases collapse, some verb forms don't). |
| **1.2.18** | 2026-06  | [`1.2.18.md`](1.2.18.md)            | **Performance pass + reader experience.**  Two themes.  **I.1 perf:** a deterministic fixture generator (`inkhaven gen-fixture`), a criterion bench harness (`benches/`), timing-instrumented hotspot analysis that overturned the plan's guesses, two algorithmic wins — **lazy embedding-engine init** (cold start 507 ms → 36 ms; the fastembed model no longer loads eagerly on every `Store::open`) and a **parent→children index** that takes `Hierarchy::flatten` from O(n²) to O(n) (31.98 ms → 0.05 ms at 2k) — and a CI regression gate (`inkhaven _bench-report` + `.github/workflows/bench.yml`, fail on >20%).  **Reader experience:** `inkhaven epub` builds a standards-compliant EPUB 3 directly (in-tree `zip` + in-house typst→XHTML, no pandoc); `inkhaven audiobook` synthesises a chapter-marked `.m4b` via the TTS engine + ffmpeg; a status-bar reading-time chip (`📖 remaining / total` at `editor.reading_wpm`); and a reader-pace preview teleprompter (`Ctrl+B Shift+E`) that advances a word-by-word highlight at reading speed.  Two new HJSON knobs (`editor.reading_time_chip`, `editor.reading_wpm`).  Tests 962 → 1053.  Zero new Rust deps in the reader-experience work (`criterion` is a dev-dep; ffmpeg is a documented required external for the audiobook mux). |
| **1.2.17** | 2026-06  | [`1.2.17.md`](1.2.17.md)            | **TTS Piper transition.**  Cross-platform neural TTS replacing the 1.2.9 macOS-only `say` integration.  `editor.tts.engine: "auto"` prefers Piper if resolvable + falls back to System otherwise — macOS users see no regression.  Voices auto-download into `<project>/.inkhaven/voices/` (per-project for language-coverage isolation), Piper binary into `~/.cache/inkhaven/piper-<plat>/` (user-scoped since it's identical across projects).  Voice picker modal on `Ctrl+B Shift+V` with catalog browsing + on-the-fly filter + Enter-to-download.  Headless `inkhaven tts` CLI surface: `engine` / `binary status\|download` / `voice list\|download\|remove` / `catalog refresh` / `test "<phrase>"`.  11 new HJSON knobs (`engine`, `voices_dir`, `auto_download`, `catalog_url`, `catalog_ttl_hours`, `binary_path`, `auto_download_binary`, `cache_max_voices`, `play_command`, `sample_rate_hz`, `auto_gitignore`).  LRU eviction caps the project voice cache at 5 by default.  Idempotent `.gitignore` append on first download.  Stale-catalog + offline fallbacks so synthesis with already-downloaded voices keeps working when the network goes away.  Zero new Rust deps (curl + tar subprocess pattern matches `tui::say`).  Tests 758 → 955 (+197).  Apple Silicon limitation documented: upstream Piper ships x86_64 code in the `aarch64` tarball — mac arm64 users stay on `engine: "system"` for now.  Single-feature cycle. |
| **1.2.16** | 2026-06  | [`1.2.16.md`](1.2.16.md)            | **Author intelligence + polish.**  Headline: manuscript intelligence dashboard (`Ctrl+V Shift+J`) — synthesis pane unifying word count + structure + threads + comments into one view, `e` exports atomic snapshot to `<project>/journal-<UTC>.md`.  Narrative-audit detectors in `inkhaven doctor --scan`: `dropped-character`, `pacing-collapse`, `stalled-thread`, `naming-inconsistency` (Levenshtein over canonical multi-word names).  Worldbuilding glossary chip (`<N>C·<N>P·<N>A`) in status bar (toggle: `editor.show_glossary_chip`).  Carryovers landed: snippet picker placeholders (`{char_lookup}` / `{place_lookup}` / `{artefact_lookup}`) + `bund:` prefix; language CLI exports (`grammar`, `phrasebook`, `csv` round-trip) + `language define-rule` with `$EDITOR`; Bund stdlib expansion (`ink.review.list/add_comment/resolve`, `ink.thread.list`); DB-side health checks (`PRAGMA integrity_check` + HNSW parity + tree-integrity).  Amber backup chip (`backup.amber_threshold`) so users see freshness drift before the warn fires.  Tantivy references purged from active docs (search has been HNSW-only since the in-tree storage migration).  Tests grew across all phases; zero new dependencies. |
| **1.2.15** | 2026-06  | [`1.2.15.md`](1.2.15.md)            | **Stability + self-healing + security hardening.**  Panic-survivability layer: custom panic hook flushes every dirty buffer to `<path>.inkhaven-rescue` atomically + writes `inkhaven-crash-<UTC>.hjson` with panic context + project state + recent action ring; `inkhaven recover` walks the manifest with y/N/diff per buffer.  Stability sweep across `src/tui`, `src/store`, `src/cli`, helper modules + every user-data save path upgraded to atomic via the new `crate::io_atomic` helper — 62 panic sites neutralised; 5 critical-data writes made atomic; lock-poisoning recovery on every shared mutex.  Background health monitor (tokio task) with project-root / backup-freshness / rescue-orphan checks at independent cadences, status-bar chip (`✓ ✎ ⚠ ✗`), per-class auto-repair opt-in, `.inkhaven/health.log` audit trail with size rotation.  Project doctor: `inkhaven doctor --scan/--autofix/--json/--class`, kebab-case scan classes including the new `bdslib-only` (recoverable disk drift), TUI panel on `Ctrl+B Shift+0`.  Security hardening from a full audit: path-traversal patches in recover CLI + HJSON config; `ink.fs.*` sandboxed to project root; Bund script auto-load gated by `<project>/.inkhaven/trust` + `scripting.trust_decision`.  New `Documentation/SECURITY_WARNING.md` discloses known + unknown risks and limitation of liability.  Tests 565 → 695 (+130).  Zero new dependencies. |
| **1.2.14** | 2026-05  | [`1.2.14.md`](1.2.14.md)            | **Plot intelligence + inline comments + quick wins.**  New `Threads` system book (`Ctrl+V Shift+H` picker + swim-lane weave view, `Ctrl+V Shift+A` AI audit, `Ctrl+V Shift+D` deterministic thread doctor modal, `inkhaven thread add/list/doctor/export` CLI).  Inline comments with sidecar JSON storage (`Ctrl+V c` add — span-anchored with char-offset UTF-8 safety, `Ctrl+V Shift+C` project-wide panel with `(N/M in ¶)` dense indicator + `a` AI digest, `inkhaven comments list/resolve/reopen/delete/export` CLI).  Project templates (`inkhaven init --template <name>` + `inkhaven template list`) — 14 scaffolds total including 5 Russian (novel / long-story / scifi / lore / utopia) + 3 international (epic-fantasy / mystery / french-novel).  HJSON-driven snippet expansion with `{date}`/`{slug}`/`{author}`/`{cursor}` placeholders on Space-trigger.  AI continuation drafting (`Ctrl+V d`) + inline footnote (`Ctrl+V f`).  Project word-count goal modal (`Ctrl+V Shift+G`) with 30-day projection.  Style-transfer rewrite (`Ctrl+V y`) from a recent-paragraph picker. |
| **1.2.13** | 2026-05  | [`1.2.13.md`](1.2.13.md)            | **The Language book — a first-class invented-language workbench.**  New `Language` system book with `Meta` / `Dictionary` / `Grammar` / `Phonology` / `Sample texts` chapters; tree-pane scaffolders (`b` on Language scaffolds the 5-chapter shell, `+` under each chapter seeds the right schema-aware HJSON template).  Lexicon overlay + cursor-footer chip in the manuscript editor (`theme.language_word_fg`).  AI translation flow: `Ctrl+B Q` translates the open paragraph INTO an invented language (envelope composes Meta + Grammar + Phonology + RAG-filtered Dictionary + Sample-texts register anchors); `Ctrl+B Shift+Q` reverses direction for roundtrip-drift testing.  Full CLI surface: `inkhaven language init / add-word / import / remove-word / list / doctor / export` with `--format json|anki|dictionary-twocol`.  CSV bulk-import with pre-flight alphabet + phonology validation.  Two tutorials (49 end-to-end + 50 CSV deep-dive) + sample CSV. |
| **1.2.12** | 2026-05  | [`1.2.12.md`](1.2.12.md)            | **Fullscreen split view.**  Four-phase rework that gave two paragraphs full editor chrome side by side.  Universal `Shift+Enter` pin (any pane), `Ctrl+V Shift+B` sibling-book lookup (`manuscript-en/03-rain` → `manuscript-ru/03-rain`), `F12` critique-compare across panes, snapshot-as-secondary draft-vs-current workflow.  Plus the concordance export CLI, HJSON-editor inline LLM review (`Ctrl+R` inside `Ctrl+B 0`), per-detector style-warning underline overrides, and the doc-extractor polish that made every config field show its source comments. |
| **1.2.11** | 2026-05  | [`1.2.11.md`](1.2.11.md)            | **Multilingual prompts.**  Three-phase resolver work (string → directory → per-language prompt fragments) so the AI prompts adapt to the project's working language.  AI sentence-rhythm rewrite (`Ctrl+B Shift+M`) pairs with the rhythm gauge.  Concordance Enter-jump (concordance modal now jumps the editor cursor to the selected paragraph).  AI-diff modal wrapping for long diffs.  Two bootstrap CLIs: `inkhaven bootstrap-sdt` (per-language stop-word + filter-word seeds) and `inkhaven bootstrap-prompts` (per-language prompt seeds).  Config-TUI polish trio: `F3` file picker for path fields, expanded enum widget set, HSL slider with live preview. |
| **1.2.10** | 2026-05  | [`1.2.10.md`](1.2.10.md)            | **Standalone editors for `inkhaven.hjson` and `prompts.hjson`.**  `inkhaven config` — schema-aware TUI editor: auto-derived schema from `Config::default()`, build-time `///` doc-comment extraction so every field has docs, comment-preserving surgical save, `.config-backups/` rollback, per-field annotations (Ctrl+A) + comment inspector (Ctrl+I), map-entry add/delete for `llm.providers`, typed widgets (bool / int / float / string / colour with live preview / path / enum / list).  `inkhaven prompts-editor` — four-pane workbench (list + editor + AI response + AI prompt input) where the LLM acts as a prompt-engineering reviewer; Ctrl+B G lifts the response into the editor; Ctrl+R rollback to `.prompts-backups/`.  Both editors auto-populate from embedded defaults on first launch.  Two new tutorials (44 prompts-editor, 45 config-tui). |
| **1.2.9** | 2026-05   | [`1.2.9.md`](1.2.9.md)              | **Prose-craft tools for novelists.** Inline style-warning overlays (filter words, repeated phrases, show-don't-tell — all multilingual + Snowball-stemmed) under one `Ctrl+B Shift+F` toggle. New modals: project-wide concordance (`Ctrl+B Shift+L`), sentence-rhythm gauge (`Ctrl+B Shift+H`), writing-streak heatmap (`Ctrl+B Shift+G`). New status-bar POV / character chip (`Ctrl+B Shift+P`). Scene-break navigation (`Ctrl+B <` / `>`). TTS read-aloud (`Ctrl+B S`) + save-as-audio file (`Ctrl+B Shift+R`) on macOS. AI-driven show-don't-tell scan (`Ctrl+B Shift+T`). `inkhaven doctor` gains `--voices`, `--tts-test`, `--filter-words-snippet`. Six new tutorials (38-43). |
| **1.2.8** | 2026-05   | [`1.2.8.md`](1.2.8.md)              | **Shell, config editor, and the surface gets sharper.** Embedded nushell pane (`Ctrl+Z o`) running in-process. HJSON config editor (`Ctrl+B 0`) with syntax highlight + restart-required banner. Help book renders as markdown via pulldown-cmark. `inkhaven export-timeline` CLI (SVG / PNG / Typst). Scrivener `<CustomMeta>` date import. Mouse wheel everywhere. Ctrl+Q opt-in confirm. Multi-slot kill-ring + Shift-letter chord-matcher fix. |
| **1.2.7** | 2026-05    | [`1.2.7.md`](1.2.7.md)               | **Polish + plumbing.** Timeline gains two-level Tab/Enter navigation, Space track collapse, span-aware ↑/↓ event select, grid stripes, F12 full critique, per-book session persistence, book-slug prefix, and selection-aware `Ctrl+V Shift+E`. Around it: `Ctrl+B U` paragraph undelete (single-slot kill-ring), `Alt+←`/`Alt+→` visited-paragraph back/forward, `Ctrl+V Shift+P` recent-¶ picker, `Ctrl+Shift+M` mouse-capture toggle for native terminal copy, passive external-change auto-reload, snapshot dedupe, status-bar today widget gets colour, F8 from any pane. Internally: `src/tui/app.rs` refactor 26,605 → 13,939 LOC across 21 new sibling/child modules (zero behavioural delta). Fixes: Ctrl+S no longer jumps the cursor home; clippy clean. 4 new tutorials (32-34) plus 1.2.7 polish section on 31. |
| **1.2.6** | 2026-05   | [`1.2.6.md`](1.2.6.md)               | **Tools for the working novelist.** Tag triad (project-wide picker, rename, `export --tag`, tree pips, `ink.tag.*`, Scrivener keyword import). Diagnostic UX (gutter `●`, F8 list, Ctrl+V N/Shift+N, Ctrl+F12 AI explain, `hook.on_diagnostic`). AI as a partner (F12 critique, per-paragraph memory, diff modal). Snapshot annotations (F5 prompt, F6 picker `✎` rendering). Story view split (Ctrl+V w paragraph mini + Ctrl+V Shift+W book). Render preview live zoom. **Story timeline (1.2.6)** — calendar-aware events; `Ctrl+V e` picker; `Ctrl+V Shift+E` new event from any pane; `Ctrl+V Shift+T` swim lanes with auto-fit on open, scope nav, and Up/Down event-step navigation; `Ctrl+V Shift+I` edit timing; y/Y/Ctrl+Y AI critique; seven `ink.event.*` Bund words + 2 hooks. F11 → Ctrl+F12 (macOS workaround). Seven new tutorials (25 — 31). New **Book of Inkhaven** companion volume. |
| **1.2.5** | 2026-05   | [`1.2.5.md`](1.2.5.md)               | **Typst goes in-process** — `typst_compile.engine = "inprocess"` runs `typst::compile + typst-pdf` inside inkhaven (no shell-out, bundled fonts, `@preview` package fetch). Phase-1 `typst-syntax` parse diagnostics on save/idle; opt-in semantic diagnostics via full compile. `Ctrl+V R` renders the open paragraph to a floating PNG preview with page navigation (←/→) + save-current (S) + save-all (A). `Ctrl+V N` jumps the cursor to the next diagnostic. Esc cancels in-flight compiles; autosave fires before Ctrl+B A/B/O. New `inkhaven doctor` CLI. Embedded logo banners the credits pane. |
| **1.2.4** | 2026-05   | [`1.2.4.md`](1.2.4.md)               | Wiki-links + backlinks (Ctrl+V A/I/L/K), navigation pack (Ctrl+V P/B/M, AI Up history), snapshot diff (F6 V) + pre-restore safety snapshot, per-paragraph word targets + auto-promote, active-time tracking, per-book bar chart, `inkhaven export --status`, `inkhaven stats`, Scrivener importer, tree multi-select + bulk T/O, save-as picker, theme persistence, Bund stdlib gaps closed (`ink.fs.*`, `ink.editor.replace_all`, `ink.search.load`, `ink.ai.poll`, `ink.ai.send_blocking`), F-keys in keybind table, startup splash, Windows CI re-enabled. |
| **1.2.3** | 2026-05   | [`1.2.3.md`](1.2.3.md)               | Multi-format export (markdown / TeX via tylax / EPUB) + `--book-name`, writing-progress subsystem (Ctrl+V G modal, status-bar widget), similar-paragraph side-by-side mode (Ctrl+V S), Bund output pane + Ctrl+Z ? script picker + `ink.input`, dynamic Quick Help. |
| **1.2.1** | 2026-05   | [`1.2.1.md`](1.2.1.md)               | bdslib + tree-sitter-typst absorbed in-tree (crates.io-publishable), Bund scripting (`ink.*` stdlib, hook points, `.bund` Script nodes, Scripts system book), data-driven keymap with HJSON + Bund rebinding, `Ctrl+B M` cycle-type, dirty-flag sync. |
| **1.1**  | 2026-05    | [`1.1.md`](1.1.md)                   | Images first-class, Book assembly / build / take, HJSON-driven `settings.typ`, six LLM providers, AI full-screen + typewriter layouts, document-status workflow, HJSON data nodes, 1000+ commits of polish. |
| **1.0.3** | 2026-04    | (tag-only — see GitHub Releases)     | First public binary release: Linux x86_64 + macOS aarch64. |
| 1.0.2 / 1.0.1 / 1.0.0 | 2026-04 | (tag-only — release-pipeline iteration) | Build / matrix-shaping commits, no user-facing change between them. |

## Reading order

If you're upgrading from an earlier version, read the notes for
every version between the one you came from and the one you're on,
in order. Each release-notes file is self-contained but assumes
you've read the previous one's "Breaking changes" section, if any.

## What we *don't* put here

- Per-commit changelogs — `git log` is canonical for that.
- Internal refactors with no user-visible effect.
- Bugfixes that simply restore advertised behaviour (those land in
  point releases without notes; major behavioural changes get
  notes regardless of size).
