Two stages, one arc, no protocol change. Stage 1 makes the terminal
configurable (profiles, scrollback, escape key) and binds the opening
command; Stage 2 adds copy mode and search over scrollback. They are
independently releasable and get separate branches and PRs.
Three scouted facts shaped the design, two of them ruling out the
obvious plan.
Profiles cannot be a config-registry setting: ConfigValue is four
scalars and there is no table kind, so profiles join pmacs.lsp.config
and pmacs.pair.sets as a raw Lua table while the registry holds only
scalars.
Search cannot reuse isearch in place: SearchStore addresses matches as
byte ranges into a buffer's rope, and a terminal identity buffer is
empty by construction.
An in-place copy mode would be the seventh dispatch shadow, which
COHERENCE section 6 grades weak and growing by one island per modal
feature, with no transient-keymap mechanism to migrate to.
Copy mode therefore materializes the retained rows into an ordinary
read-only buffer. isearch, motion, selection and the kill ring work
with no new substrate; the "keys must not reach the child" problem
dissolves because the snapshot is not a terminal; and describe-key
stays truthful because the bindings are buffer-local. The cost, stated
in the doc, is that the snapshot is point-in-time rather than a live
freeze.
Four review rounds produced the load-bearing parts: the escape-key
cache is owned by TerminalSession so its lifecycle is the terminal's,
with three acceptance pins that each fail a different wrong cache; the
snapshot needs set_round_trip_input because a Lua intercept does not
set Buffer::read_only and an optimistic CrdtOp would mutate both the
daemon buffer and the mirror; the double-escape must encode the
configured chord rather than a hardcoded ETX; and the two open-time
settings resolve through the global chain because they are read before
the terminal buffer exists.
No code changes in this commit.