Planning start/resume opened an external Windows Terminal (wt) window.
Route them through the embedded ConPTY Command Center pane instead, matching
the existing interactive-session UX (no external window).
- Extract bare planning arg builders (BuildPlanningStartArgs/ResumeArgs) from
WindowsTerminalLauncher; the wt path still uses them (kept, not removed).
- InteractiveLaunchSpecService.BuildPlanningStart/Resume map a planning
context into a LaunchSpec (planning args + env: MAX_THINKING_TOKENS,
CLAUDEDO_PLANNING_TOKEN). Hub GetPlanningStart/ResumeLaunchSpec run
StartAsync/ResumeAsync then return the spec.
- UI: OpenPlanningSession + the resume branch raise OpenPlanningConPtyRequested;
the shell opens Mission Control and hosts a planning ConPTY pane.
Env is process-global by design (sequential human-paced sessions). wt planning
code retained. Tests added for the arg/env mapping.
THe update notification should be in the Bottom Rught hand corner as a Small Popup card. IT should have the Update and Dismiss Butotns. It should only show when there is a new Update available, not if everything is up to date
ClaudeDo-Task: c14606f009e44e4ba04bfe5bcbc884ad
A planning parent stays Status=Idle while its session is Active (or
Finalized-but-not-queued), so the lifecycle chip read "Idle"/"Parked"
next to the PLANNING/PLANNED badge. Hide the chip in that case; the badge
already conveys the state.
A --json-schema run can echo the structured {"summary":...} JSON as the
result text, which then landed verbatim in task.Result and rendered raw in
the OUTCOME card. Unwrap the summary in StreamAnalyzer when the result text
is itself such a JSON object (a plain markdown result is kept as-is), and
add a UI safety net in ApplyOutcome for rows already persisted as raw JSON.
Finalize/Discard broadcast only the parent's TaskUpdated; the delta path
updated the parent row but never recomputed child-derived flags or dropped
discarded children, so subtasks stayed "Draft" after finalize and deleted
rows lingered after discard until a manual reload. Reconcile the whole
list when the updated task is (or owns) a planning subtree.
Opening the dropped IStorageFile stream ran outside the try, so a
first-drop failure escaped the async-void handler as an unobserved fault
(generic "An error occurred"). Wrap the stream-open loop and surface the
exception type via DropStatus; include the exception type in the generic
add-file failure too, so the intermittent case is analyzable.
ResumePlanningSessionAsync wrapped everything in an empty catch, so a
failed resume vanished silently. Report it via the footer error channel
with a dedicated planningResumeFailed message.
Continue was already gated on CanContinue (all files resolved); surface a
footer hint counting the still-unresolved conflicts/files so the disabled
state is explained, not just for binary files.
Show an explanatory empty-state under the install row when no skills are
installed. Rename the unified-parent status/labels from "Improvements" to
neutral "Subtasks" (waitingForChildren, agentStatus.children,
childOutcomesLabel) since WaitingForChildren now covers planning too.
diff --git headers pack two paths on one space-delimited line, which broke
for unquoted paths containing spaces and for git's C-style octal-quoted
paths (non-ASCII filenames). Add quote-aware header splitting plus a git
unquote helper, and prefer the unambiguous "--- a/"/"+++ b/" lines to
correct the file's identity when present.
The embedded ConPTY terminal replaced the in-app streaming interactive session, so
delete the dead stack: StreamingClaudeSession, InteractiveSessionService,
ProcessClaudeStreamTransport, IClaudeStreamTransport, ILiveSession, LiveSessionRegistry,
IdleSessionReaper (+ WorkerConfig.InteractiveIdleTimeoutMinutes), the WorkerHub
interactive methods + HubBroadcaster events, IWorkerClient interactive members, the
TaskMonitorViewModel composer + SessionTerminalView composer markup, and the old
'Run interactively' entry. AskUser/PendingQuestionRegistry, the autonomous path,
planning, ResumeTaskInTerminal, and all ConPTY code are kept. Localization pruned.
Adds a 'New session' header button in Mission Control that opens a folder picker
and starts a task-less embedded ConPTY session in the chosen directory. ConPtyPaneViewModel
TaskId is now nullable (ad-hoc panes have no task and are never deduped) with a
CreateAdHoc factory; the view does the picking, the VM stays picker-agnostic.
Adds an 'Open ConPTY session' entry that fetches a task's launch spec and hosts
an embedded ConPTY terminal as a Mission Control pane, coexisting with the
streamed-log monitor panes (streaming stack untouched). Introduces IMissionControlPane
+ ConPtyPaneViewModel, a non-destructive Panes mirror (Monitors prefix + ConPtySessions
suffix) so unrelated monitor churn never tears down a live terminal, and a grid<->tabs
layout toggle. Launch failures surface via the footer error strip.
Adds a self-contained terminal host: PtyTerminalSession drives a Porta.Pty child
directly (custom env) and pumps it through Iciclecreek's XTerm.NET renderer via
TerminalControl.Terminal, bypassing LaunchProcess() so a fully-populated
environment can be passed. InteractiveTerminalView/ViewModel host it with an
order-independent attach/start. Adds Iciclecreek.Avalonia.Terminal 2.0.3.
Sets Process="" to suppress the control's auto-launch of a stray shell.
Queued rows are now QueuedMessageViewModel (Text + RemoveCommand); each shows a
✕ (Icon.WinClose) that calls RemoveQueuedInteractiveMessageAsync(taskId, text).
The worker re-broadcasts the queue, rebuilding the strip without the removed
message. Adds session.composer.unqueue (en/de).
A queued message now appears in a pending strip above the input box (driven by
InteractiveQueueChanged), not optimistically in the transcript. The transcript
user line is added on delivery via InteractiveMessageSent. SessionTerminalView
gains QueuedMessages/HasQueuedMessages styled props (Mission Control); WorkConsole
binds Monitor.* (task detail). Adds session.composer.queued (en/de).
LogKindForegroundConverter drives the log message foreground via a local
binding (beats the dim local value), so user messages render in the accent
color instead of vanishing into the transcript. Adds a small stop (Icon.Stop)
button next to Send in both composers (SessionTerminalView + WorkConsole) wired
to InterruptInteractiveCommand → InterruptInteractiveSessionAsync. Adds
session.composer.interrupt (en/de).
TaskMonitorViewModel gains IsInteractiveLive + ComposerDraft + SubmitComposer
(optimistic LogKind.User echo, then SendInteractiveMessageAsync) + StopInteractive,
driven by the InteractiveSessionStarted/Ended events. Since DetailsIslandViewModel
embeds this monitor, both task detail and Mission Control get the composer. Mission
Control auto-creates a monitor on InteractiveSessionStarted. Adds LogKind.User.
TaskMonitorViewModel surfaces a pending AskUser question (TaskQuestionAsked /
TaskQuestionResolved events) with an AnswerDraft + SubmitAnswerCommand that calls
the new IWorkerClient.AnswerTaskQuestionAsync; MonitorPaneView shows an accent
question banner with an input box above the terminal. Pending question is cleared
on answer/resolve/finish and re-hydrated on attach via GetPendingQuestionAsync.
en/de localization for missionControl.question.*; test fakes updated.
Add the borderless, transparent, topmost, click-through DragGhostWindow that
hosts a tilted (~-6deg) translucent snapshot of the dragged row, a
TaskDragController that owns its lifecycle (snapshot -> show -> follow -> close),
and a pure DPI-aware DragHitTest helper (unit-tested) for the cross-window
screen hit test. Adds the TaskRowViewModel.IsDragging flag and the
'grabbed' Border.task-row.dragging style (lift + scale + lower opacity +
shadow). Not yet wired into the drag source.
The state badge in the worktrees overview used bright off-palette Material colors
with hardcoded near-black text (via WorktreeStateColorConverter), which was hard
to read. Switch to the existing chip pattern (subtle tint background + matching
border + colored text): active=blue, merged=green, kept=amber, discarded=gray.
Drop the now-unused WorktreeStateColorConverter.
Replace the static DETAILS label and its dead space with a segment switcher; the card body now shows one section at a time. Step/file counts sit in the tab labels, the edit/preview toggle is scoped to Description, and drag-and-drop or add jumps to the Files tab. Tab labels localized (en/de).
Drop a file anywhere on the detail pane to attach it: pane-wide drop target
with a 'Drop to attach' hover overlay (Copy cursor, gated on an idle selected
task), an explicit lingering confirmation/error line, plus an Attachments list
with size, remove, and an Add file… picker in the DETAILS card. ComposedPreview
now shows the reference files too. en/de keys added.
The RequestConflictResolution Func was declared on 5 VMs and hand-threaded shell->details->merge-section->diff->merge-modal. Replaced with a DI-singleton IMergeCoordinator (MergeCoordinator holder; shell wires its Handler at composition, breaking the shell<->island cycle). Invokers (MergeModal, DetailsIsland, WorktreesOverview) depend on the interface; the two pass-through VMs (DiffModal, MergeSection) drop the seam entirely. No behavior change; conflict-seam + batch tests rewired to assert via the coordinator.
Collapses the ~10 per-modal Show*Modal Func callbacks (wired separately on the shell and the lists island) into one IDialogService + WindowDialogService impl. Removes the RepoImport/WorktreesOverview dialog construction duplicated across MainWindow and ListsIslandView, plus the Confirm/Error dialogs duplicated in both code-behinds. Shell/lists Open* commands now route through an injected Dialogs handle (propagated shell->lists); the per-list worktrees overview also wires conflict resolution now, matching the global one. No VM ctor changes (Dialogs is a settable seam), so no test-fake impact.
Drops the append-SortOrder query duplicated inline in TasksIslandViewModel.AddAsync; the repository (already used by MCP AddTask) is now the single home for the create+SortOrder invariant. Sets Status=Idle explicitly for parity.
Code-review follow-ups before push:
- MergeFile.ResultText/Compose() fell back to Ours for unresolved conflicts while
the editor seeds them empty — align both on empty so the public model matches the
pane and Continue can't silently auto-accept Ours.
- Bound the gutter re-layout retry (was an unbounded Background re-post when the
editor isn't laid out, e.g. minimized).
- Pluralize the readout ('1 conflict' not '1 conflicts'). Tests updated. Ui 128 green.