diff --git a/CHANGELOG.md b/CHANGELOG.md index 333ddca..f0ecaa2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -108,6 +108,25 @@ loosely follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html). renders the canonical `--flag` form. ### Fixed +- `whoami` and `help("timers")` now advertise the full Solo-parity timer + surface (`timer_set`, `timer_fire_when_idle_any`, + `timer_fire_when_idle_all`, `timer_cancel`, `timer_pause`, + `timer_resume`, `timer_list`) so agents using either tool for + orientation discover them — previously only `timer_wait` was listed. +- Resuming a paused idle-aware timer now re-checks the satisfaction + condition. Previously, if every watched process became idle (or, for + `idle_any`, any non-baseline watcher went idle) while the timer was + paused, the timer stayed pending forever because no further state + transitions were observed. +- Fired and canceled timers are now removed from the timer registry, + so long-running patterm sessions no longer accumulate completed + timer records and message bodies. `timer_list` and the sidebar + indicator already filtered them out; only the in-memory leak is + fixed. +- Per-preset idle-detection config is now installed through `SpawnSpec` + before the child is published to the session, closing a race in + which the classifier goroutine could observe a freshly spawned + process before its preset's classifier strategy was attached. - Opening the command palette while a scratchpad was focused left the palette wedged — typing did nothing and Esc left the palette's top border drawn over the pad until you closed the pad with Ctrl-W and diff --git a/TODO.md b/TODO.md index 9ad5df6..d6e3533 100644 --- a/TODO.md +++ b/TODO.md @@ -1,3 +1,14 @@ +- [ ] Codex seemed to think that it needed to launch patterm itself to get the mcp working +- [ ] I cant click and drag to select text from codex +- [ ] codex uses perl to interact with the socket rather than calling mcp tools + - when it _did_ open a sub claude it opened it as a separate tab rather than a sub-agent. +- [ ] codex rendering is VERY slow + - maybe we need to use diffing rather than rendering the entire viewport for performance +- We should add a --debug and --profile flag, so we can get detailed performance data and full logs of the agent output to be debugged later on. + - I don't mind what format this is in, ideally easy for LLMs to understand +- [ ] Resuming a long claude session takes a couple of seconds for the entire buffer to load in, it looks like it's scrolling down for a couple seconds. + - In raw alacritty this is instant, so there's some sort of performance issue with patterm's terminal emulation. + - [ ] There's a unicode being displayed in opencode [ON HOLD] - Investigated 2026-05-14: patterm passes ghostty grapheme codepoints through unchanged (vt/ghostty.go:452-462), so the `` glyph is diff --git a/internal/app/host.go b/internal/app/host.go index 78985a4..3917431 100644 --- a/internal/app/host.go +++ b/internal/app/host.go @@ -92,9 +92,9 @@ func newToolHost(sess *Session, pads *scratchpad.Store, launcher *Launcher, pres // rather than make it implement the full surface. type timerListenerAdapter struct{ m *timerManager } -func (a timerListenerAdapter) OnChildSpawned(*Child) {} -func (a timerListenerAdapter) OnChildExited(*Child) {} -func (a timerListenerAdapter) OnPTYOut(string, []byte) {} +func (a timerListenerAdapter) OnChildSpawned(*Child) {} +func (a timerListenerAdapter) OnChildExited(*Child) {} +func (a timerListenerAdapter) OnPTYOut(string, []byte) {} func (a timerListenerAdapter) OnChildStateChanged(id string, st IdleState) { a.m.onChildStateChanged(id, st) } @@ -1084,7 +1084,9 @@ func availableToolsForRole(role mcp.CallerRole) []string { "list_processes", "get_process_status", "get_project_status", "get_process_output", "get_process_raw_output", "search_output", "wait_for_pattern", "get_process_ports", - "send_input", "send_message", "request_human_attention", "timer_wait", + "send_input", "send_message", "request_human_attention", + "timer_wait", "timer_set", "timer_fire_when_idle_any", "timer_fire_when_idle_all", + "timer_cancel", "timer_pause", "timer_resume", "timer_list", "scratchpad_list", "scratchpad_read", "scratchpad_write", "scratchpad_append", "whoami", "help", } @@ -1114,8 +1116,8 @@ func helpFor(topic string) mcp.HelpResponse { } case "lifecycle": return mcp.HelpResponse{ - Topic: "lifecycle", - Content: "You own the processes you spawn. When a sub-agent has finished its task (it reports back via send_message, or you've collected what you need from it) call close_process on its process_id to remove the entry and tear down the PTY. Same goes for spawn_process children: command/terminal panes you started are not auto-reclaimed when their work completes. close_process is the normal cleanup path; stop_process(signal) is for sending a signal without removing the entry; start_process re-attaches an exited command preset. Leaving idle sub-agents around wastes vendor tokens and clutters the host — close them as soon as you're done. Sub-agents themselves are reminded (via the [system: …] preface on their first prompt) to clean up anything they created before reporting done.", + Topic: "lifecycle", + Content: "You own the processes you spawn. When a sub-agent has finished its task (it reports back via send_message, or you've collected what you need from it) call close_process on its process_id to remove the entry and tear down the PTY. Same goes for spawn_process children: command/terminal panes you started are not auto-reclaimed when their work completes. close_process is the normal cleanup path; stop_process(signal) is for sending a signal without removing the entry; start_process re-attaches an exited command preset. Leaving idle sub-agents around wastes vendor tokens and clutters the host — close them as soon as you're done. Sub-agents themselves are reminded (via the [system: …] preface on their first prompt) to clean up anything they created before reporting done.", RelatedTools: []string{"close_process", "stop_process", "start_process", "list_processes", "get_process_status"}, } case "inspection": @@ -1144,9 +1146,18 @@ func helpFor(topic string) mcp.HelpResponse { } case "timers": return mcp.HelpResponse{ - Topic: "timers", - Content: "timer_wait returns a timer_id immediately and injects `[system] Your timer [