Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
9cb42a3
Fix terminal dimensions error after switching sessions
Sep 13, 2026
f4bfa6d
Fix Claude and Codex live status detection
Sep 13, 2026
7950ded
Prioritize explicit agent status over redraw activity
Sep 13, 2026
218adf0
Guard terminal lifetimes and publish consistent teardown status
Sep 13, 2026
0aa0c02
Scope Claude blockers to live prompt regions
Sep 13, 2026
1308cb3
Discard initial input callbacks from replaced terminals
Sep 13, 2026
4fd6b4d
Retain real startup work across transient redraws
Sep 13, 2026
5a75f82
Reconcile renderer statuses on attach and reconnect
Sep 13, 2026
f25b5db
Keep terminal startup unknown until status detection is meaningful
Sep 13, 2026
3960aa9
Do not announce terminal teardown as agent completion
Sep 13, 2026
b2b4618
Drain terminal snapshots before asynchronous teardown
Sep 13, 2026
1871401
Recognize all Claude circle spinner title frames
Sep 13, 2026
73cb19e
Cover delayed tool startup and document drained teardown
Sep 13, 2026
8c02376
Skip terminal snapshot persistence before panel deletion
Sep 13, 2026
64c3dad
Preserve natural exit details during terminal teardown
Sep 13, 2026
cd52002
Keep shell terminals docked and share the empty pane launcher
Sep 13, 2026
52af9ee
Clear inherited startup titles and guarantee terminal teardown cleanup
Sep 13, 2026
ca7ca2e
Add fresh pane launcher screenshot for review
Sep 13, 2026
4cdcdf7
Merge upstream main v2.4.105 into terminal refresh branch
Sep 14, 2026
acd94ce
Merge upstream main v2.4.106 into terminal refresh branch
Sep 15, 2026
48134e5
Fix remote terminal input ordering
Sep 16, 2026
09da513
Merge upstream main v2.4.115 into terminal refresh branch
Sep 23, 2026
b68ff50
Preserve Escape boundaries and handle discarded terminal input
Sep 24, 2026
b51e7fa
Merge upstream v2.4.125 and preserve terminal lifecycle fixes
Sep 24, 2026
12e94a0
Merge upstream v2.4.129 and align browser regression fixtures
Sep 25, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,12 @@ All notable changes to Pane will be documented in this file.
### Changed
- Custom-command keyboard shortcuts moved from `mod+alt+5..9` to `mod+alt+6..9` to make room for the Cursor slot.
- Cursor Agent is now available inside WSL repositories.
- Repository main panes now show the default shell in the bottom dock. The dock defaults to expanded in both main and worktree panes, while preserving saved collapse preferences.
- `runpane watch` defaults are unchanged and stay responsive: no settle, no batching, all event kinds, IDLE every 10 minutes, HEARTBEAT every 60 seconds under `--follow`.
- The Pane Chat orchestrator's Liveness Contract now arms the cadence flags above, filters HEARTBEAT out of its monitor, and judges a dead watch by a non-zero exit or a `WATCH ERROR` line rather than by silence.

### Fixed
- Agent terminals remain in working tabs after deleting the default shell and switching panes. Closing the dock also repairs tab selection when another shell takes its place.
- Pane Chat has its skills again. Pane synced its agents' skills from the skills repository, which moved them on 2026-08-13; every sync since then failed, and new installs had none. Pane now ships 37 skills: Agent Farm's current raw-profile skills and their helpers, general-purpose primitives such as `verify-app`, `options`, `brief`, and `orchestrate-sessions`, and three Pane-specific ones (`pane-orchestrator`, `runpane`, `pane-work`). It also installs four helper subagents (explorer, cold-reader, qa-and-verify, reviewer) for Claude and Codex Sessions. The skill sync is removed, and Pane deletes its old sync folders.
- `runpane panels submit` now submits prompts to Claude panes instead of leaving them in the composer. Pane waits for Claude's composer, types the prompt, and presses Enter separately once the text shows, so a pane created with `--wait-ready` and submitted to right away starts the turn. `verifiedSubmitted` is true only when Claude's composer is seen empty afterwards.
- `runpane panels screen` reports `composer.hasUndeliveredText` for Claude panes. It used to read false for every Claude pane, even with a prompt sitting in the composer. Claude's dim placeholder suggestion does not count.
Expand Down
5 changes: 4 additions & 1 deletion docs/ADDING_NEW_CLI_TOOLS.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,10 @@ add a ready detector like `createCursorReadyDetector` and gate `signalCliReady`
fixtures and register it in `MANIFESTS_BY_AGENT`. Unknown agents fall back to
`GENERIC_MANIFEST` (works, less precise). Keep blocker rules narrow and live-region
gated so answered prompts in scrollback don't stick. Record the CLI version the
fixtures came from.
fixtures came from. Set `visibleIdle` only for reliable idle/completion evidence;
composers that remain visible mid-turn must not set it. The monitor prioritizes
blockers and working chrome, then reliable idle evidence, with byte activity as
a fallback. Unclassified boot output is ignored during the startup grace window.

## 5. Restart/auto-resume

Expand Down
6 changes: 6 additions & 0 deletions docs/remote-daemon-lifecycle.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,9 @@ This is the implementation checklist for Remote Pane setup, teardown, and runtim
- Connected remote clients are runtime state, not saved client records.
- Current Pane Data hosting is live only while that Pane app is running.
- Isolated daemon data can install a background service; Current Pane Data should not.

## Terminal Input

Desktop and browser clients send at most one terminal input request per panel at a time. Keys typed while a request is pending are combined into the next request, preserving their order without a separate round trip for every buffered key. A bare Escape always ends a combined request, because terminal apps read Escape followed by another key in the same write as an Alt shortcut. Different panels and other remote commands remain independent.

Input requests are not retried. On failure, disconnect, or a ten-second input timeout, queued input is discarded and outstanding callers are rejected. An interrupted request may already have reached the host, so its input must not be replayed after reconnecting. This uses the existing HTTP API and requires no host protocol upgrade.
34 changes: 3 additions & 31 deletions frontend/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import { DISCORD_INVITE_URL } from './components/DiscordIcon';
import { ResumeSessionsDialog } from './components/ResumeSessionsDialog';
import { useErrorStore } from './stores/errorStore';
import { useSessionStore } from './stores/sessionStore';
import { rollupSessionAgentState } from './utils/agentStatus';
import { subscribePanelStatus } from './services/panelStatusSync';
import { useConfigStore } from './stores/configStore';
import { usePanelStore } from './stores/panelStore';
import { API } from './utils/api';
Expand Down Expand Up @@ -150,36 +150,8 @@ function App() {
useIPCEvents();
const { showNotification } = useNotifications();

// Global panel activity status listener
useEffect(() => {
const unsubscribe = window.electronAPI?.events?.onPanelActivityStatus?.((data) => {
usePanelStore.getState().setActivityStatus(data.panelId, data.status, data.lastActivityAt);
});
return () => unsubscribe?.();
}, []);

// Global agent status listener (blocked / working / done) for terminal panels.
useEffect(() => {
const unsubscribe = window.electronAPI?.events?.onPanelAgentStatus?.((data) => {
const store = usePanelStore.getState();
const prevState = store.agentStatus[data.panelId];
store.setAgentStatus(data.panelId, data.sessionId, data.state);

// A background agent finishing should read as done (blue) right away —
// mark unseen completion from the unified working -> idle transition
// instead of waiting for the legacy 30s activity flip.
if (prevState === 'working' && data.state === 'idle') {
const next = usePanelStore.getState();
const activeSessionId = useSessionStore.getState().activeSessionId;
const sessionSettled =
rollupSessionAgentState(next.agentStatus, next.agentStatusSession, data.sessionId) === 'idle';
if (sessionSettled && activeSessionId !== data.sessionId) {
next.markUnviewedCompletedActivity(data.sessionId);
}
}
});
return () => unsubscribe?.();
}, []);
// Subscribe to live statuses and reconcile the daemon baseline on attach/reconnect.
useEffect(() => subscribePanelStatus(), []);

useEffect(() => {
const clearViewedCompletedActivity = (event: Event) => {
Expand Down
Loading
Loading