# Inkhaven 1.3.12 — The background deep refresh

_The world-consistency checks (facts, drift, continuity) are AI passes — a
multi-minute batch. Until now you ran them from the CLI and waited. 1.3.12
brings the whole batch inside the editor, on a background thread, so you never
leave your prose and never freeze the UI. Full plan:
[DEEP-1_PLAN.md](../PROPOSALS/DEEP-1_PLAN.md)._

## `Ctrl+V Shift+F` — refresh in the background

One chord runs `facts check` + `facts scan` + `drift scan` + `continuity
extract` (the `inkhaven world --deep` set, **in the manuscript's language**)
on a background thread. A **`⟳ deep refresh`** chip in the status bar tracks
progress; the editor stays fully responsive — keep writing. When it finishes,
an open story bible (`Ctrl+V Shift+L`) or Editorial Pass (`Ctrl+V Shift+R`)
**rebuilds itself** from the fresh findings and the status shows the new
`inkhaven world` summary. One refresh at a time; needs an LLM provider.

## It's advisory — it never edits your text

The deep refresh **reads** your manuscript and **writes findings** to
`.inkhaven/*.json` sidecars. It does not change a word of your prose — no
paragraphs created, edited, or deleted. The only thing that ever rewrites
prose is the Editorial Pass's `f` / `F`, always user-initiated, snapshotted,
and shown as a diff to accept or reject. The background refresh never touches
that path.

## Stale findings announce themselves

Findings live in their sidecars until you re-run a scan, so a finding can
predate a fix. Each scan now stamps a cheap fingerprint of the manuscript
(every paragraph's `(id, modified_at)` — no content reads); when the prose has
moved since, the world report, the bible banner, and the Editorial Pass show
**`⚠ may be stale`** with a nudge to re-run. It only *warns* — never hides or
deletes a finding.

## How it can run while you write

DuckDB is single-writer, so a second process can't open the project the TUI
holds. Instead the refresh runs in-process on a thread that **shares** a clone
of the editor's connection pool — no second open, no lock. The pool (4
connections by default) is now tunable via **`embeddings.pool_size`** (clamped
to ≥2 so the background read and your foreground edits never contend). Quitting
mid-refresh simply abandons the run: finished sidecars are valid (atomic
writes), an unfinished one is merely stale, never corrupt.

## Under the hood

- Zero new dependencies (`std::thread` + `std::sync::mpsc`; r2d2 already in).
- A reusable **background-job harness** (`start_bg_job` / `pump_bg_job` /
  `BgMsg`) the 1.4 Whole-Book AI Editor will reuse for retrieve-then-reason
  queries.
- The four world-layer scans gained store-injected `*_with` variants (the CLI
  commands are unchanged thin wrappers); `deep_refresh_shared` orchestrates
  them against the shared store, threading `cfg.language` so the deep AI runs
  in the manuscript's language.
- New pure, unit-tested code: `drain_bg_messages`, `world_report::
  manuscript_fingerprint` / `is_stale`.
- Tests 1354 → 1359. New tutorial 72.

## Carryovers (still open)

- **The Whole-Book AI Editor** (general retrieve-then-reason) — the 1.4
  headline; it reuses the background-job harness.
- Cancelling an in-flight job (vs abandon-on-quit); a multi-job queue.
- PDF N-up / booklet presets; CMYK-JPEG grayscale; ePub inline images + popup
  footnotes; sixth supported language.
