Land staged session/MCP/chrome work + sidebar clear-J fix

This batches the in-flight [Unreleased] block from CHANGELOG.md into a
single commit. Highlights:

- Real MCP protocol layer (initialize / tools/list / tools/call) so
  vendor MCP clients can complete the handshake against the per-PID
  socket. Legacy direct-dispatch preserved for the harness.
- New mcp_injection kinds — cli_override for codex, config_env for
  opencode — joining the existing env-var and config_file paths so
  patterm can slot into more agents without touching their real
  config or auth.
- Ctrl+A/D and Ctrl+W/S focus navigation across tabs and intra-tab
  process lists, recognised in legacy / kitty CSI u / xterm
  modifyOtherKeys encodings.
- Palette macros (sw / k / sp ) and reordering so open sessions
  surface above spawn-new entries.
- Two-row tab bar, sidebar/tabbar/status chrome cache, viewport-wipe
  on agent spawn, CR-terminated orchestrator injections, and split-
  Enter PTY writes so paste-detecting TUIs see Enter as a key event.

Also fixes the bug logged in TODO: claude's Ctrl+O tool-call expansion
emits CSI 0 J, which the viewport renderer was forwarding verbatim —
wiping the sidebar to the right of the cursor and leaving the chrome
cache convinced nothing had changed. CSI 0 J and CSI 1 J are now
translated into per-row ECH sequences clamped to the viewport, same
as CSI 2 J and CSI K already were.

Agent guides (CLAUDE.md / AGENTS.md) now spell out the
TODO->CHANGELOG workflow so completed items land in the changelog
rather than as ticked entries left behind in TODO.
This commit is contained in:
2026-05-14 19:09:35 +01:00
parent 7649587f9a
commit 3622c41fd0
25 changed files with 1951 additions and 163 deletions

View File

@@ -45,16 +45,33 @@ type Preset struct {
ChromeTrimHints []string `json:"chrome_trim_hints,omitempty"`
}
// MCPInjection covers the three strategies SPEC §10 enumerates: a CLI
// flag (claude --mcp-config ...), an external config file we merge into
// (codex ~/.codex/config.toml), or an env var.
// MCPInjection covers the strategies SPEC §10 enumerates plus
// `cli_override` for agents (like codex) that accept inline config
// overrides via repeated CLI flags, and `config_env` for agents (like
// opencode) that read their config from an env var. The fields used
// depend on Kind.
type MCPInjection struct {
Kind string `json:"kind"` // "flag" | "config_file" | "env_var"
Kind string `json:"kind"` // "flag" | "config_file" | "env_var" | "cli_override" | "config_env"
Flag string `json:"flag,omitempty"`
ConfigPath string `json:"config_path,omitempty"`
Path string `json:"path,omitempty"`
MergeKey string `json:"merge_key,omitempty"`
Var string `json:"var,omitempty"`
// config_file fields. patterm reads the file at Path, merges in a
// `patterm` entry under MergeKey, writes the result inside a temp
// directory laid out so HomeVar + HomePath points at the merged
// file, and exports HomeVar to the child. Format is inferred from
// Path's extension (toml or json) when blank.
Path string `json:"path,omitempty"`
MergeKey string `json:"merge_key,omitempty"`
Format string `json:"format,omitempty"`
HomeVar string `json:"home_var,omitempty"`
HomePath string `json:"home_path,omitempty"`
// cli_override fields. patterm emits one `<Flag> <KeyPrefix>.<k>=<v>`
// pair per MCP setting (command, args) so the agent merges them
// into its in-memory config without touching any file on disk. Used
// for codex's `-c key=value`.
KeyPrefix string `json:"key_prefix,omitempty"`
}
// ReadySignal lets a preset override the default 1s-idle heuristic.
@@ -196,7 +213,12 @@ func ensureDefaults(base string) error {
`{
"name": "codex",
"argv": ["codex"],
"mcp_injection": { "kind": "config_file", "path": "~/.codex/config.toml", "merge_key": "mcp_servers" },
"mcp_injection": {
"kind": "cli_override",
"flag": "-c",
"key_prefix": "mcp_servers.patterm",
"format": "toml"
},
"ready_signal": { "idle_ms": 1000 },
"chrome_trim_hints": [
"^OpenAI Codex",
@@ -213,7 +235,13 @@ func ensureDefaults(base string) error {
`{
"name": "opencode",
"argv": ["opencode"],
"mcp_injection": { "kind": "config_file", "path": "~/.config/opencode/opencode.json", "merge_key": "mcp" },
"mcp_injection": {
"kind": "config_env",
"path": "~/.config/opencode/opencode.json",
"merge_key": "mcp",
"format": "json",
"var": "OPENCODE_CONFIG_CONTENT"
},
"ready_signal": { "idle_ms": 1000 },
"chrome_trim_hints": [
"^\\s*█",