# Inkhaven 1.4.14 — Dialogue quality & attribution

_Dialogue is the most technically demanding prose mode: readers must always know who is speaking,
said-bookisms (`he ejaculated`) degrade the page, and an unbroken run of talking heads loses the
physical scene. Inkhaven's Inner Socrates flagged unattributed dialogue in passing; nothing measured
dialogue as a **mode** with its own properties. DIALOG-1 does — **deterministically, with no LLM, no
parser, and no external dependency** — in five languages (EN/RU/DE/FR/ES) across three structurally
distinct quotation conventions. It **measures; it never prescribes.** **No new runtime crates.**_

_Plan: [DIALOG-1_PLAN.md](../PROPOSALS/DIALOG-1_PLAN.md)_

## Scan a book

```sh
inkhaven dialogue scan
```

```
Dialogue scan — `The Sunken Throne` [en]
──────────────────────────────────────────────────────────────────
  dialogue spans detected   34
  zero attribution          3
  talking-head sequences    1
──────────────────────────────────────────────────────────────────
  [ch.12 · 7f1a…] unattributed speech — no tag or character name within range
  …
──────────────────────────────────────────────────────────────────
```

`scan` **exits non-zero** when any zero-attribution span is found, so it doubles as a pre-submission
gate (`inkhaven dialogue scan --findings zero-attribution || …`). Three deterministic findings:

- **Zero-attribution** — a speech span with no tag or nearby character name. An established
  two-speaker exchange is allowed to alternate untagged for a run (default 8 turns) before it fires.
- **Said-bookism density** — a chapter whose non-neutral tag verbs (`whispered`, `growled`) run above
  the book's own baseline by more than a threshold.
- **Talking heads** — a run of dialogue-only paragraphs with no action beat (a ≥ 8-word line of
  narration) to ground the scene.

## Three quotation conventions

Detection is **not** uniform across languages — that's the heart of DIALOG-1:

- **EN, DE** — paired quotation marks (`"…"`, `„…"`, `»…«`).
- **FR, RU** — guillemets `«…»` and em-dash openers (`— …`); the French inline *incise*
  (`, dit-il,`, with the euphonic `-t-`) is stripped from the speech before it's measured.
- **ES** — all three, detected additively and de-duplicated.

Said-bookism and neutral tag-verb lists are embedded for all five languages in their dominant
narrative tense (EN past · RU perfective gender pairs · DE Präteritum · FR passé simple · ES
pretérito); EN adds a stem fallback so `whispering` matches `whispered`.

## Per-character fingerprints

```sh
inkhaven dialogue profile
```

```
Character    Utts  Avg words  MATTR  Questions  Excl.  Hedging
Mara           47      11.3   0.74      0.31    0.08    0.019
Aldric         83      11.8   0.69      0.12    0.22    0.041
```

Each character gets a six-metric voice signature — utterance count, average length, vocabulary
diversity (MATTR), question / exclamation ratios, hedge density — built **only** from confidently
(`Certain`) attributed lines, reusing NARR-1's MATTR and modal word list. In the editor,
**`Ctrl+V Shift+Q`** opens the fingerprint view for the nearest character (one named in the open
paragraph, else the most-speaking) as ASCII bars with a compare line.

## In the editor

The dialogue check rides the **unified review pass** — **`Ctrl+B Shift+C`** runs it alongside the
fact / Socratic / timeline checkers; the findings land in the **Output pane** (navigable to the
flagged paragraph). Zero-AI and content-hash lazy, so only the chapter you just edited re-detects.
There's also a new Inner Socrates persona, **`theatergoer`** (`Ctrl+B J → S` to cycle to it): it
reads a dialogue scene as if the narrator's private glosses were invisible, and asks whether the
subtext is legible from the words and visible action alone.

## Notes

- **One implementation, four surfaces.** The pipeline, CLI, Bund, and TUI all run on the same
  detection / attribution / `dialogue.duckdb` core. Findings stay informational; profiles live in
  `.inkhaven/dialogue.duckdb`, invalidated by a content hash.
- **`dialogue:` config** tunes the windows / thresholds and — importantly for SF/fantasy — lets you
  mark genre speech verbs neutral (`extra_neutral_verbs: ["transmitted", "sent"]`) so telepathy
  isn't counted as a said-bookism.
- **Scripting** — read-only `ink.dialogue.{stats,fingerprint,violations,spans,refresh}` (refresh
  writes only the derived cache, so it stays `store_read`, like `ink.prose.refresh`).
- **No new runtime crates; no new system books; no new `NodeKind`.** One new
  `.inkhaven/dialogue.duckdb`, one new Inner Socrates persona (15 total), one new chord. Imports
  NARR-1's `ProseLanguage` + modal lists. New tutorial 97.
- Tests 2005 → 2039 (the engine is unit-tested across detection / attribution / store / pipeline /
  fingerprints; the CLI / Bund / TUI surfaces were validated end-to-end on real projects).
