# Inkhaven 1.1

The 1.1 line picks up the full editing-to-PDF pipeline. Where 1.0
gave you a TUI editor with semantic search and a single-shot AI
pane, 1.1 lets you assemble the manuscript into a typst-compilable
tree, compile it from the TUI, route compile errors through an
AI-error-analysis chat, embed first-class images, drive document
status through a workflow ring, switch between six LLM providers,
and so on. There's also a substantial documentation refresh.

This file is the upgrade guide and a tour of the new surface.
Released `v1.1.0` (with release candidates `rc1` through `rc4`
preceding the stable tag).

---

## Highlights

| Area | What changed |
| ---- | ------------ |
| **Images** | First-class `NodeKind::Image` alongside Paragraph. F3 imports PNG/JPG/GIF/WebP/SVG. Book assembly emits per-level `wrap_image_book/chapter/subchapter` calls. Enter on an Image row pops a ratatui-image preview (kitty / sixel / iterm2 / half-block fallback). `Ctrl+B P` inside `#image("…")` opens a sibling picker. |
| **Assembly pipeline** | `Ctrl+B A` writes the manuscript out as a typst tree under `<artefacts>/<book>/`. `Ctrl+B B` runs `typst compile` with a spinner splash; on failure the captured stderr opens a fresh AI chat with a typst-aware system prompt. `Ctrl+B O` builds and copies the PDF to the launch cwd as `<book-slug>-YYYYDDMM-HHMM.pdf`. |
| **HJSON-driven typst settings** | New `typst_page` / `typst_fonts` / `typst_layout` stanzas synthesise the `#set page / text / par / heading` header in the assembled `settings.typ`. User-supplied free-form code in the Typst-book `settings.typ` paragraph is appended below as an override layer. |
| **HJSON-driven wrap templates** | The four prose wraps (`wrap_book / wrap_chapter / wrap_subchapter / wrap_paragraph`) and four image wraps are all configurable via `typst_templates.*` in HJSON. Empty falls back to a baked-in default. |
| **LLM providers** | Six bundled stanzas — Gemini, Claude, OpenAI, DeepSeek, Grok, Ollama. `Ctrl+B L` opens a floating switcher that rewrites only `llm.default` in place, preserving the rest of the file. |
| **AI full-screen layout** | `Ctrl+B K` toggles a three-pane layout — AI pane left, chat history right (scrollable, markdown-rendered), AI prompt at the bottom. Chat history persists to `<project>/.inkhaven-chat.json` between sessions. `Ctrl+F` searches inside the history (substring highlight, current match centred, `Ctrl+X` advances to older). `Ctrl+C` enters a turn-selection mode with `c` (clipboard) and `t` (insert into editor) actions. |
| **Typewriter mode** | `Ctrl+B W` hides every pane except the editor. Mutually exclusive with the AI full-screen layout. |
| **Document status** | New `status` metadata field on paragraphs, cycled by `Ctrl+B R` through `None → Napkin → First → Second → Third → Final → Ready → None`. Editor header shows a colour-coded badge; tree pane gains a one-character gutter column. `Ctrl+B 1..7` opens a scoped status-filter modal (scoped to the tree cursor's enclosing branch) with `r` / `-` in-modal status cycling. |
| **HJSON data nodes** | Paragraphs can now hold HJSON in addition to Typst — F3 detects `.hjson` files and creates a Paragraph with `content_type = "hjson"`. The editor switches to a hand-rolled HJSON highlighter; on-disk filename uses `.hjson`. |
| **Editor smarts** | Ctrl+B F opens a Typst function picker (≈80 baked-in built-ins) with tree-sitter-typst-driven smart `#` prepending. Auto-close pairs for `()` `[]` `{}` `""` `''` with step-over and Enter-expand-to-indented-block. CRLF normalisation on import and load. Search-match centring in the editor pane. |
| **Snapshot picker** | F6 picker shows local-time timestamps; `D` / `Del` deletes a snapshot. |
| **Tree-pane import** | F3 directory imports show a progress splash with the current file path. |
| **Help corpus** | `inkhaven import-typst-help` seeds the Help book with a curated 33-section Typst reference. F1 RAG answers typst questions from grounded context. |
| **System books** | New **Artefacts** book between Characters and Typst; new **Typst** book seeded with per-user-book skeletons (`index.typ`, `settings.typ`, `globals.typ`). Existing projects auto-pick up both on next open; a self-healing pass fixes any order collisions from pre-rc3 seeders. |
| **Backups / artefacts location** | Defaults moved to **sibling-of-project** directories: `<parent>/inkhaven-backups/<project>/` and `<parent>/inkhaven-artefacts/<project>/`. Visible in any file manager, easy to copy off to external storage. CLI `inkhaven backup` no longer requires `--out`. |
| **Sound effects** | `Ctrl+B E` toggles synthesised typewriter SFX (Enter click, focus-out rattle). All synthesised at runtime via `rodio` — no audio assets shipped. Disabled by default. |
| **Polish** | Editor header shows live word count, reading-time estimate (250 wpm), and `edited X ago` next to L/C cursor. Snapshot list now shows local-time timestamps. Status filter modal navigation. `Ctrl+B I` floating book-info panel. `Ctrl+B V` credits panel. Many quickref / META hint updates. |

---

## New chords (global meta `Ctrl+B …`)

| Chord    | Action |
| -------- | ------ |
| `Ctrl+B I` | Current book info — paths, structural counts, reading-time, PDF status. |
| `Ctrl+B L` | LLM provider switcher (writes `llm.default` to inkhaven.hjson in place). |
| `Ctrl+B E` | Toggle typewriter SFX (writes `sound.enabled` to inkhaven.hjson). |
| `Ctrl+B A` | Book assembly — emit typst tree under `<artefacts>/<book>/`. |
| `Ctrl+B B` | Build the book (assembly + `typst compile`). |
| `Ctrl+B O` | Take the book — build + copy PDF to launch cwd. |
| `Ctrl+B R` | Cycle the open paragraph's status. *(Previously: snapshot history — F6 still works.)* |
| `Ctrl+B 1..7` | Scoped status filter modal (1=Ready, 2=Final, … 7=None). |
| `Ctrl+B W` | Toggle full-screen typewriter mode. |
| `Ctrl+B K` | Toggle full-screen AI mode (AI pane + chat history + AI prompt). |
| `Ctrl+B G` | Notes RAG inference (selection → Notes book → AI pane). |
| `Ctrl+B Y` | Artefacts RAG inference (selection → Artefacts book → AI pane). |
| `Ctrl+B F` | Typst function picker (was: a duplicate of F4 split-edit — F4 still works). |
| `Ctrl+B P` | Inside `#image("…")` → sibling-image picker; otherwise Places RAG. |

In AI full-screen mode (Ctrl+B K) only:

| Chord    | Action |
| -------- | ------ |
| `Ctrl+F` | Chat-history search prompt (substring; starts at newest match). |
| `Ctrl+X` | Advance to next-older chat-search match. |
| `Ctrl+C` | Toggle chat selection mode (`c` = clipboard, `t` = insert into editor). |
| `↑` / `↓` | Scroll chat history one line. |
| `PageUp` / `PageDown` | Scroll chat history by 10 lines. |

---

## New CLI subcommands

```bash
# Seed the Help book with a curated Typst reference (~33 sections).
# Re-run after any inkhaven upgrade to refresh.
$ inkhaven --project <path> import-typst-help
```

`inkhaven backup` no longer requires `--out`; absence falls back
to the new default location (`<parent>/inkhaven-backups/<project>/`).

---

## New HJSON stanzas

Added to a fresh `inkhaven init`. Existing projects pick up the
defaults via `#[serde(default)]` on the next open.

```hjson
typst_page: {
  paper: "us-letter"
  margin_top: "2.5cm"
  margin_bottom: "2.5cm"
  margin_inside: "3cm"
  margin_outside: "2cm"
  page_numbering: "1"
  columns: 1
}

typst_fonts: {
  body: "EB Garamond"
  body_size: "11pt"
  monospace: "JetBrains Mono"
  language: "en"
}

typst_layout: {
  justify: true
  leading: "0.7em"
  paragraph_indent: ""
  heading_numbering: ""
}

typst_templates: {
  wrap_book: ""           // four prose wraps
  wrap_chapter: ""
  wrap_subchapter: ""
  wrap_paragraph: ""
  wrap_image_book: ""     // four image wraps (book-art, chapter-art, …)
  wrap_image_chapter: ""
  wrap_image_subchapter: ""
  wrap_image_inline: ""
}

typst_compile: {
  // System prompt used when typst compile errors are routed into a
  // fresh AI chat. Empty = baked-in default that explains inkhaven's
  // file layout to the LLM.
  error_system_prompt: ""
}

images: {
  preview_enabled: true
  allowed_extensions: ["png", "jpg", "jpeg", "gif", "webp", "svg"]
  max_size_bytes: 33554432
}

sound: {
  enabled: false        // typewriter SFX (Ctrl+B E to toggle)
  volume: 0.6
}

editor: {
  // …existing fields…
  auto_close_pairs: true
}
```

Existing `llm.providers` block expanded with `claude`, `openai`,
`grok`. The `default_project.hjson` template now ships the full
six-provider set with comments explaining the model-name routing.

---

## File-layout changes

Three new on-disk locations:

| Path | Purpose |
| ---- | ------- |
| `<parent>/inkhaven-backups/<project>/` | Default backup target (replaces in-project `backups/`). Sibling of project dir, easy to copy off. |
| `<parent>/inkhaven-artefacts/<project>/` | Assembled typst tree + built PDF for each user book. Wiped clean on every Ctrl+B A. |
| `<project>/.inkhaven-chat.json` | Persisted AI chat history (used by Ctrl+B K). Removed when history is cleared. |

Projects from 1.0 keep working without intervention. The first
launch on 1.1 silently:

- Seeds the new **Artefacts** system book between Characters and
  Typst (a self-healing pass restamps system-book orders if a
  pre-rc3 seeder left collisions).
- Seeds the **Typst** book.
- Adds the new HJSON config blocks to every config read.

---

## Breaking / behaviour changes

### `Ctrl+B R` no longer opens snapshot history

`Ctrl+B R` now cycles paragraph status. **F6 still opens the
snapshot picker** — that's the canonical chord and was the chord
F6 mapped to even in 1.0. Muscle memory for the meta chord needs
to relearn one chord; the F-key path is unchanged.

### `Ctrl+B P` is context-sensitive

Outside an `#image("…")` call, `Ctrl+B P` still opens Places RAG.
Inside, it opens the sibling-image picker. The detector is line-
local (looks backward from the cursor for `#image(` without a
matching `)` and exactly one `"`); multi-line `#image(...)` calls
fall through to Places RAG.

### CRLF / bare-CR line endings

Imported files (RFC dumps, Word-exported text, old-Mac dumps)
previously kept their `\r` bytes on disk and rendered as visible
control glyphs in the editor. 1.1 normalises `\r\n` → `\n` (and
bare `\r` → `\n`) at both import and load time. Re-saving an
existing file rewrites it with LF endings.

### Snapshot picker timestamps are local

The F6 / Ctrl+B R-then-F6 snapshot picker now shows
`2026-05-19 18:41:29 -0600` instead of `2026-05-19 18:41:29` UTC.
The on-disk timestamp is still UTC (RFC-3339); only the
display converts.

### `inkhaven backup --out` is optional

If omitted, defaults to the new sibling-of-project location. Pass
`--out <dir>` to override; absolute paths are used as-is, relative
paths resolve against the project root.

---

## Tutorials added

| # | Tutorial |
| - | -------- |
| 12 | [`Tutorials/12-configuring-ai-providers.md`](../Tutorials/12-configuring-ai-providers.md) — the six bundled provider stanzas + Ctrl+B L workflow. |
| 13 | [`Tutorials/13-ai-full-screen-mode.md`](../Tutorials/13-ai-full-screen-mode.md) — Ctrl+B K layout, persistent chat, search, selection mode. |
| 14 | [`Tutorials/14-document-status.md`](../Tutorials/14-document-status.md) — workflow ring, badges, scoped filter modal. |

---

## Migration checklist

For a 1.0.x project:

1. **Set the new env vars** for the providers you want — at minimum,
   keep the one you used in 1.0. Optionally add `ANTHROPIC_API_KEY`,
   `OPENAI_API_KEY`, `XAI_API_KEY`.
2. **Run `inkhaven import-typst-help`** once per project to seed the
   Help book with the Typst reference (so `F1` answers typst
   questions).
3. **Note the new chord meanings** — if `Ctrl+B R` was muscle memory
   for snapshot history, retrain to F6.
4. **Optionally tune `typst_page` / `typst_fonts` / `typst_layout`**
   instead of hand-editing `settings.typ`. The auto-generated header
   is regenerated each `Ctrl+B A` from these stanzas.
5. **Backups + artefacts moved.** Existing `<project>/backups/`
   keeps working if your `backup.out_dir` still points there. New
   projects default to the sibling-of-project location.

No data migration is required. `.typ` files are unchanged. bdslib
schema is backwards-compatible.

