# Inkhaven 1.3.27 — The world, mapped (and a deeper checker)

_1.3.25 built a world; 1.3.26 read your prose against it. 1.3.27 **draws** the
world and makes the checker **deeper**. Your compiled world now renders to an
actual map (via [plakat](https://crates.io/crates/plakat)); the fact-checker
gains a slow LLM track, a cross-paragraph **coherence** pass, scope chords,
multilingual place-name matching, and graceful degradation when it isn't sure
what language you're writing in. The world definition grows real **geography /
hydrology / economy** blocks, and the repo ships a complete, ready-to-compile
**Earth**. This rounds out RFC WORLD-4 toward its P7 polish._

_Reference: [WORLD-4_PLAN.md](../PROPOSALS/WORLD-4_PLAN.md) · Tutorials
[76 — Building a world](../Tutorials/76-building-a-world-realworld.md),
[77 — World maps and the fact-checker](../Tutorials/77-world-maps-and-fact-checking.md)_

## Maps — `inkhaven realworld map`

Your compiled world now renders to a map. Inkhaven emits a **MapSpec v2** from the
geology / climate / hydrology / demographics layers and hands it to the `plakat`
binary, which draws it — `plakat map --map-spec` loads our spec and skips its own
LLM entirely, so the cartography stays a pure function of your world and seed.

```
$ inkhaven realworld map
map · Aldoria (160×120 grid) · plakat 1.10.0
  features: assets/maps/world.features.png
  geojson:  assets/maps/world.geojson
  20 landmark(s) resolved, 20 Place coordinate(s) refined
```

Three artifacts land under `assets/maps/`: the **MapSpec** JSON, a rendered
**features PNG**, and a **GeoJSON** (coast, rivers, roads, landmarks). Mountain
ranges come from clustering the heightfield's high cells; rivers run their real
D8 watercourse (mouth from hydrology, source traced upstream); landmarks are your
largest settlements, coastal cities becoming ports. plakat's resolved landmark
positions are read back to **refine each accepted Place's coordinates**.

- **`--spec-only`** writes the MapSpec without invoking plakat.
- **`--no-ingest`** renders without touching Place coordinates.
- TUI: **`Ctrl+B W` → `M`**.
- plakat is **optional** — a missing binary degrades to a notice, never a
  failure. Install with `cargo install plakat`.

## A deeper fact-checker

### The slow track — `fact-check --slow`

Where the fast track is deterministic patterns, the **slow track** asks the
configured LLM for the subtle contradictions patterns miss. It's opt-in and
cost-controlled: a **cost preflight** prints the estimated tokens and the day's
tally before each call, a per-call **soft cap** (`--max-cost`, default 6000;
`--force` overrides) refuses an oversized call, a daily ceiling holds, and
transient errors (rate limits, timeouts, 5xx) **retry with backoff**. A missing
provider or a reached cap degrades to a notice.

### Coherence — `realworld coherence <node>`

A new pass checks a *run* of paragraphs **against each other** — a character in
two places without the travel between, a fact asserted then reversed, a timeline
that doesn't add up. Give it a book or chapter node id; it gathers the paragraphs
in document order and runs one cost-capped call, citing the `¶` numbers involved.

### Scope chords — `Ctrl+B W` → `F` → `P` / `B` / `R`

`F` now arms a scope picker: check the open **p**aragraph, the whole enclosing
**b**ook, or the 12 most **r**ecently edited paragraphs. Each pass replaces those
paragraphs' prior Output findings and flips you there with a summary.

### Idle auto slow-check — `Ctrl+B W` → `S`

An opt-in toggle (off by default — it spends tokens). With it on, ~45 s of quiet
on a changed paragraph runs the slow track **in the background**; the editor stays
responsive and findings land in Output when ready.

### An economy category

The fast track gains a fifth category — a metal mined or worked in the prose that
the world's geology doesn't yield, scoped to a clear extraction context so a
silver ring doesn't imply local silver.

## Multilingual matching & graceful degradation

- **Grammatical variants** — place names now resolve in their inflected forms.
  The win is Russian declension (`в Москве` / `к северу от Москвы` both match
  `Москва`); German adds its genitive `-s`.
- **Never-fail detection** — language detection reports a **confidence**; when it
  isn't sure, the checker renders the warning in English rather than asserting a
  guessed language. It never panics on any input.
- **Honest backend** — the optional enhanced parser (a UD model) is *never
  required*; an absent or unreadable asset silently degrades to the built-in
  heuristic, and the fact-check footer names the active backend (`INKHAVEN_LANG_MODEL`
  points at an enhanced one).

## Author-declared setting blocks

The world definition gains three optional blocks — and expanded geology — that
let you name your world's real features. They materialize into a **Setting**
chapter of the World book, and two of them feed the checker directly:

```hjson
geography: { landmarks: [ { name: "Cairo", kind: "city", climate_zone: "hot_desert", population: 9500000 } ] }
economy:   { tech_level: "industrial", resources: [ "iron", "copper", "petroleum" ] }
hydrology: { rainfall: "temperate", rivers: [ { name: "Nile" } ] }
geology:   { generated: { volcanism: "moderate", mineral_richness: "rich", notable_minerals: [ "iron", "gold" ] } }
```

- A **landmark** with a `climate_zone` becomes a gazetteer entry the checker
  resolves by name — *before* you compile and accept procedural Places. "Snow
  fell on Cairo" flags against its declared `hot_desert` zone.
- `economy.resources` + `geology.notable_minerals` join the checker's known
  goods, so trading your world's ores isn't flagged.

## Start from Earth

The repo ships [`examples/realworld/Earth.hjson`](../../examples/realworld/Earth.hjson)
— a complete, heavily-commented real Sun/Earth/Moon definition: exact astronomy,
the Gregorian calendar, Earth-tuned procedural geology, and populated
geography / hydrology / economy (the Sahara, Cairo, the Nile, an industrial
economy, Earth's ores). Copy it in as `world.hjson` and compile to start in a
recognisable world.

## The World overview, corrected

The `Ctrl+B W` panel no longer claims the geology / climate / hydrology /
demographics layers are "not yet implemented" — it shows each layer's real status
(DEM vs generated, materialized ✓ or pending) and a key legend
(`C`/`P`/`F`→`P`/`B`/`R`/`M`/`S`).

## Dependencies & compatibility

**Zero new dependencies.** The map emitter mirrors plakat's MapSpec schema with
`serde_json` rather than importing it; the GeoJSON readback is plain `serde_json`;
plakat is an optional external binary, not a crate. The slow track and coherence
pass reuse the existing AI client and the background-job harness. Non-breaking and
opt-in throughout — maps need plakat, the slow track and coherence need an LLM
provider, and everything still only runs when a project has a `world.hjson`.

Tests 1625 → 1658. Two new tutorials (76, 77).
