keymap.ts lists every key with its context, action and help line.
actions.ts holds what each one does, typed against the table so a key
without an action, or an action without a key, does not compile.
modes.ts stacks the contexts (always > sheet > drawer > workspace >
writing > focused tile > special > global) and writes the two-key
pending logic once. App.svelte's 480-line onkeydown is now one call.
Help, the panel footers (a shared Keys component), the rail's keycaps
and Commands.md all read the table; the wiki gains the card and
scratchpad key tables.
One fix on the way: Ctrl-S in the editor no longer saves twice, which
could make the second save fail as "changed somewhere else".
rust-embed refused to derive without `web/dist`, so on a fresh clone
`cargo check`, `cargo test` and rust-analyzer failed with a derive error that
did not say what was missing. With `allow_missing` the embed is empty until
the frontend is built, and the handler gives the answer it already had for
that case, "frontend not built". The release build is unchanged once
`web/dist` is there, which `make build`, the Dockerfile and CI all see to.
`ci.yml` runs what `make check` runs, in three jobs: format, clippy and the
tests, after building the frontend, because the binary embeds web/dist and does
not compile without it; svelte-check; and the wiki check, so a change to a
command's help that forgets `make wiki` fails before it lands.
`wiki.yml` publishes docs/wiki to the repository's GitHub wiki on every push to
main that touches the pages or a file the generated ones are read from. It
generates the pages afresh rather than trusting the committed ones, lays them
out with `--publish` in a clone of the wiki, and pushes only when something
changed. GitHub makes a wiki's repository only once its first page exists, so
one page has to be saved by hand before the first run; the comment at the top
says so.