KEEL · YARD v0.10.0

The file footprint

The complete footprint of the solution — every file, and what it is for. Seven Rust crates make the binary, one Django app makes the Yard, and a small tools directory holds the vendored assets. Nothing else is hiding anywhere.

The repo root

C:\ai\workspace\keel\ Cargo.toml the workspace: members, shared deps, THE version (x.y.z single source) Cargo.lock pinned dependency graph CHANGELOG.md the recorded history — shown by keel changelog, the TUI overlay, and /changelog BACKLOG.md decisions, milestones, the owner's kept feature picks docker-compose.yml the Yard + Postgres 16, one `docker compose up` from zero start-keel.ps1 the one-file entry: builds, starts the Yard if needed, opens the sample .gitignore target/, novels/, .keel-home/, python artifacts .dockerignore keeps target/ and git out of the image novels\ your series live here (git-ignored) .keel-home\ credentials/session when launched via the starter (git-ignored) temp\ untracked scratch (screenshots) — not part of the solution

crates/keel-core — the pure domain

Everything Keel knows lives here, with zero I/O: the spine, the ledger, Plank, page geometry, the canonical file forms. Its test suite runs with no fixtures on disk — the design's testability anchor.

crates\keel-core\ Cargo.toml deps: serde, yaml/toml, similar, thiserror — no I/O crates, by rule src\lib.rs module map + re-exports src\id.rs ObjectId + kinds — filename-safe ids, prefix carries the kind src\model.rs BeatCard, statuses, the write-gate functions, entities, frames src\spine.rs SpinePath (position from id), Spine, frontier, synopsis, sparkline src\time.rs StoryTime with era precision; unix formatting; day parts src\calendar.rs the five-era calendar, story-time validation, the total order src\ledger.rs facts, promises, refs, the two clocks, blast radius src\plank.rs the markup: parser events, fmt (bare @end), strip (CommonMark) src\typst.rs Plank → Typst emission for the book pipeline src\context.rs Davy's recipe: pinnable sections S1–T2, token estimates src\geometry.rs trim/margins/face → 62 chars × 34 lines × ~300 words/page src\files.rs canonical parse/serialize for every file form + the seeds src\diff.rs word-level diff (line diffs on prose are unreadable)

crates/keel-store — strict RCS over SQLite

crates\keel-store\ Cargo.toml rusqlite (bundled), zstd, blake3 src\lib.rs module map src\store.rs the Store trait — one schema, Local now, Yard next src\schema.sql objects · revisions · locks · changesets, monotonicity trigger src\local.rs LocalStore: exclusive locks, MAX(rev)+1, loud stale-base, changesets src\error.rs every failure named: Locked, StaleBase, PendingInChangeset…

crates/keel-prose — the Helm, the editor

The hand-built prose widget — the project's flagged biggest risk, fenced to six requirements and finished.

crates\keel-prose\ Cargo.toml ropey, ratatui, unicode-width src\lib.rs the pinned public surface src\view.rs the Helm state: rope, cursor, selection, decorations, focus src\wrap.rs soft wrap at display columns, per-line cache src\keys.rs vim-lite modal keys (normal/insert/visual, the fenced set) src\journal.rs flat undo/redo with same-word coalescing src\render.rs typewriter offset, decoration merge, cursor cell tests\the Helm.rs the public-API suite: motions, undo, search, wrap, dimming tests\markup_api.rs selection wrap + block insertion (the ^m palette's hooks)

crates/keel-tui — the C shell

crates\keel-tui\ Cargo.toml ratatui, crossterm, spellbook, keel-prose, keel-client src\lib.rs AppData assembly from the store; run_at / run_standalone src\app.rs the pure reducer: views, lenses, palettes, overlays — all testable src\event.rs the blocking loop: key routing, DAVY drain, F5 render, refresh src\session.rs WriteSession: checkout/resume/read-only, save, spell tick, ✎% src\login.rs the centered editor login (F2 dev mode, Esc quit) src\picker.rs the series picker for a bare keel.exe outside any workspace src\console.rs the : command console — any keel command, run in place src\DAVY.rs recipe gathering + the live stream state + provenance src\spell.rs spellbook + the project dictionary → misspelling ranges src\editor.rs $EDITOR handoff (suspend, spawn, reload) src\term.rs TerminalGuard: restore on exit AND on panic src\ui\mod.rs layout: bordered head/rail/content/foot, panels, overlays src\ui\head.rs breadcrumb, mode badge, the beat contract line, ◉ editor src\ui\rail.rs lens tabs + per-lens content + the split detail box src\ui\foot.rs words · rev · lock · flags · key hints src\ui\views.rs per-view centers: map preview, codex, ledger, review, write src\ui\worldline.rs the era-segmented timeline, both modes, scroll math src\ui\DAVY.rs the ^g panel: instruct/inspect/stream/review src\ui\markup.rs the ^m contextual markup palette with preview src\ui\palette.rs the ^p command palette src\ui\console.rs the console output overlay src\ui\help.rs the ? help — the manual inside the tool src\ui\changelog.rs the changelog overlay (embedded at build time)

crates/keel-client — AI and the Yard, over the wire

crates\keel-client\ Cargo.toml tokio, reqwest, eventsource-stream — async lives HERE only src\lib.rs module map src\provider.rs the AiProvider contract: stream events over a sync channel src\direct.rs the raw Messages API: JSON + SSE, cache_control, no SDK src\mock.rs the offline provider (KEEL_AI_MOCK) — every test runs without a key src\usage.rs model routing per agent + the cost meter's math and log src\creds.rs stored Yard credentials (shared by login and the TUI screen) src\yard.rs Yard HTTP: token login, session validation src\context_cache.rs small pure helpers (day boundaries for the meter) tests\mock_stream.rs byte-exact mock streaming + provider selection

crates/keel-index — derived data, rebuildable

crates\keel-index\ Cargo.toml rusqlite src\lib.rs deterministic rebuild: docs + FTS5 + refs; search; dict.txt tests\determinism.rs byte-identical rebuilds — the discipline test tests\search.rs bm25 hits, snippets, query wrapping tests\dict.rs sorted dictionary generation from the loft

crates/keel — the binary

crates\keel\ Cargo.toml clap + every crate above src\main.rs entry: color-eyre, dispatch, exit codes src\cli.rs the whole command surface (see the CLI reference) src\exit.rs error → exit-code mapping (3 locks, 4 integrity) src\workspace.rs workspace discovery, working-file paths, identity src\spine_load.rs store → Spine, loudly src\ledger_io.rs ledger load/save under locks, next-id, narrative positions src\commands\ one file per verb: init.rs co.rs ci.rs log.rs diff.rs status.rs the RCS lifecycle new.rs synopsis.rs frames.rs the spine proofread.rs plank.rs the writing chain fact.rs promise.rs extract.rs the ledger amend.rs blast radius · land · abandon · list render.rs export.rs snapshot.rs stats.rs the book and its numbers search.rs index.rs geometry.rs derived data ai.rs voice.rs Davy from the CLI login.rs changelog.rs auto_novel.rs session · history · the sample tests\ end-to-end against the real binary: cli_roundtrip.rs index_determinism.rs M0 acceptance m1_loft.rs m2_spine.rs m3_plank.rs per-milestone suites m5_ai.rs m6_ledger.rs m7_launch.rs m7_proofread.rs m8_login.rs m8_auto_novel.rs typst_geometry.rs 62×34 vs real renders (ignored by default)

yard/ — the web admin

yard\ Dockerfile python-slim image: migrate, seed admin, serve manage.py Django entry requirements.txt django, django-ninja, psycopg, blake3, zstandard, pytest-django pytest.ini test config (sqlite for speed) yard\settings.py DATABASE_URL or sqlite; version parsed from Cargo.toml yard\urls.py admin · api · docs · changelog · preview routes yard\asgi.py wsgi.py servers' entries core\apps.py the app config core\models.py Series, KeelObject, Revision, Lock, Changeset, Token, PreviewPdf core\store.py the semantics engine — mirrors local.rs checkin exactly core\api.py django-ninja endpoints with machine-readable error codes core\admin.py KEEL-branded Django admin registrations core\views.py docs sections, changelog page, preview serving core\context_processors.py the version into every template core\management\commands\seed_admin.py the idempotent MVP login core\migrations\ 0001 the schema · 0002 preview PDFs core\tests\test_api.py parity + auth + preview (pytest) templates\base.html the site shell: palette, favicon, header, version templates\changelog.html the rendered changelog templates\docs.html superseded placeholder (pre-docs-shell; unused) templates\docs\ THIS documentation: base_docs.html + one file per chapter templates\admin\base_site.html admin branding + palette templates\admin\login.html the login page: home link + the test credentials

tools/ and docs/ — assets and the founding papers

tools\ typst\book.typ the book template: B-format, running heads, the 13.6pt grid typst\geometry-check.typ the acceptance harness that pins 62×34 against real renders fonts\EBGaramond\ the book face, vendored (OFL license alongside) dictionaries\en\ hunspell en dictionary powering spellcheck (index.aff/.dic) docs\ keel-spec.html the design spec, rev 0.7 — where all of this was decided keel-surfaces.html the three surface mocks the UI was built to calendar-draft.yaml the settled world-calendar structure verification-m0.md the M0 acceptance walkthrough
Reading order for the curious: keel-core/src/model.rs for the shape of the thing, keel-store/src/local.rs for how nothing is ever lost, then keel-tui/src/app.rs for how it all drives. The spec in docs/ is the long answer to every "why".