Commit Graph
879 Commits
Author SHA1 Message Date
mika kuns bb92dc279f feat(lists): assign a colour to a sidebar folder
Tints the folder name and its guide line; picked from a swatch row in the folder settings.
2026-09-30 10:12:41 +02:00
mika kuns 8a31a67c74 feat(report): write weekly report as short bullets with haiku 2026-09-30 10:05:24 +02:00
mika kuns f2ff865dca feat(ui): searchable Material Design icon library for lists and folders 2026-09-30 09:52:34 +02:00
mika kuns 27d2b1d8ef fix(tickets): convert ticket HTML to markdown on import 2026-09-30 08:39:17 +02:00
mika kuns 75b78cb2c0 feat(ui): make sidebar folder hierarchy readable
Lists default to the Text icon instead of the folder icon, rows align
across depths with a guide line per open folder, folder names are
semibold, folder counts only show while collapsed and zero counts hide.
2026-09-30 08:21:34 +02:00
mika kuns 52ba538339 test(worker): cover WorktreeUpdated broadcast on interactive review submission 2026-09-30 08:14:26 +02:00
mika kuns 81dcaebfba Merge branch 'claudedo/f518b71f990643cfaf73174e8617b2b5'
Drop the unused deferredUntil parameter the branch added to HandoffRequested: the worker still sends three args, so the four-arg client handler would never bind. The reset time already arrives via HandlerHandoffDeferred.
2026-09-29 08:54:14 +02:00
Mika KunsandClaude Sonnet 5 0dac047c46 feat(lists): allow nested sidebar folders via drag and drop
Folders can now contain other folders, to arbitrary depth, via a
self-referencing parent_folder_id (ON DELETE SET NULL, same pattern as
lists.folder_id). Nesting/un-nesting is drag-and-drop only: dropping a
folder onto another folder's header middle moves it in, the outer
quarters or any top-level/in-folder drop insert it beside a target.
Dropping a folder into itself or one of its own subfolders is silently
ignored. Deleting a folder releases its lists and subfolders back to
the top level, unchanged from the existing list behavior.

ListFolderNavItemViewModel.Lists became Children (object, mixing lists
and subfolders, mirroring TopLevel) so the existing implicit, type-matched
DataTemplates render nested folders recursively without new XAML, and each
nesting level gets its indent for free from the folder template's own
margin. Folders/RootLists/ContainerOf/PersistOrderAsync/RecomputeFolderCounts
now walk the tree instead of assuming one level.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-28 13:31:26 +02:00
mika kuns 352aaa525b fix(worker): DeleteTask aus der UI schlug immer mit generischem Serverfehler fehl
Der CancellationToken-Parameter auf der nicht-streamenden Hub-Methode liess SignalR jede Invocation vor dem Methodenrumpf abbrechen. Die Tests riefen den Hub direkt auf und sahen das nicht; neuer Reflection-Guard verbietet CancellationToken auf allen nicht-streamenden Hub-Methoden.
2026-09-28 13:02:47 +02:00
Mika Kuns d3db4455fa feat(ui): Mission Control Recent Sessions mit verschachtelten Handoffs
Neue Tabelle mission_control_sessions (Migration AddMissionControlSessions), befuellt vom
InteractiveLaunchSpecService bei Task-, Ad-hoc- und Handoff-Kacheln. Flyout im Mission-Control-Header
listet die letzten 14 Tage / 50 Sessions, Handoffs eingerueckt unter ihrer Ursprungs-Session, mit
Fortsetzen (--resume im gespeicherten cwd) und Brief anzeigen.
2026-09-28 12:11:21 +02:00
Mika Kuns 08d1797ead chore(claude-do): Mission Control: allgemeiner Session-Handoff an eine frische
## Ziel

Jede Mission-Control-Session (Ad-hoc UND Task-Session) soll ihre Arbeit an eine frische Session
uebergeben koennen: "gib das ab an eine neue Session". Die alte Kachel wird geschlossen, an
derselben Position oeffnet eine frische Session im selben cwd, die mit einem Brief startet, den
die abgebende Session selbst geschrieben hat.

Motivation: eine lange Session mit vollem/verrottetem Kontex

ClaudeDo-Task: 8b846deb-ad10-4243-9272-9aea2a01ec93
2026-09-28 11:57:37 +02:00
mika kuns e0a1448f44 feat(ui): Mission-Control-Kacheln behalten Position und Identitaetsfarbe ueber Handoffs
Ein Handoff schloss die alte Pane und haengte die neue hinten an -- die Kachel
sprang ans Ende und das ganze Grid ordnete sich neu. Die neue Pane wird jetzt am
Index der alten eingesetzt.

Dazu bekommt jede Kachel eine aus IdentityKey (Default: TaskId) abgeleitete Farbe:
3px-Streifen links am Tile, Punkt im Focus-Mode-Tab. Kein State, keine Persistenz --
derselbe Task faerbt nach App-Neustart gleich, und ein Handoff erbt die Farbe, weil
er dieselbe TaskId behaelt. Nur kuehle Hues, damit nichts als Status gelesen wird.
2026-09-28 08:56:50 +02:00
Mika Kuns 09bcd696dd feat(ui): dirty Ziel-Verzeichnis beim Oeffnen des Merge-Dialogs melden statt nach dem Fehlschlag
MergeTargetsDto/MergeTargets bekommen TargetDirty (via HasChangesAsync,
includeUntracked: false). Das Merge-Modal zeigt Warnung + Stash-Retry
sofort in InitializeAsync statt erst nach dem dirty_target-Fehlschlag;
der REVIEW-Block in der Detail-Pane zeigt denselben Hinweis neben
Approve. Der dirty_target-Rueckgabepfad bleibt als Absicherung bestehen.

Behebt Befund F6 aus docs/test-session-2026-09-16.md.
2026-09-16 15:43:39 +02:00
Mika Kuns 86cc309ba9 fix(ui): duplizierter Confirm-Dialog mit "Delete"-Knopf – zusammenfuehren und lokalisieren
F4: DetailsIslandView/TasksIslandView hatten je eine view-lokale Confirm/Error-Dialog-Kopie,
teils mit hartkodiertem "Delete"-Knopf fuer jede Aktion (inkl. der Stash+Merge-Bestaetigung,
die nichts loescht). Beide Kopien entfernt; DetailsIslandViewModel/TasksIslandViewModel routen
Confirm/Error jetzt durch den geteilten Dialogs-Seam (IDialogService, propagiert vom Shell wie
schon bei Lists/Tasks) statt ueber eine vom Code-behind gesetzte Func-Property.

IDialogService.ConfirmAsync bekommt einen optionalen confirmLabel-Parameter (Default: lokalisiertes
"Confirm"); nur die echten Delete-Aktionen (Task loeschen, abgeschlossene Tasks leeren) uebergeben
das lokalisierte "Delete"-Label.

F5: "Cancel"/"Confirm"/"Delete"/"OK" und die Titel "Confirm"/"Error" durch Loc.T mit neuen Keys
unter "dialog.*" ersetzt (en.json + de.json). Mission Controls eigene Dialog-Kopie bleibt bestehen
(eigenes Fenster, WindowDialogService ist an den Haupt-Owner gebunden) — nur ihre Labels wurden
lokalisiert.

Out of scope (siehe Task-Beschreibung): die Nachrichtentexte der Dialoge bleiben unlokalisiert.
2026-09-16 15:43:38 +02:00
Mika KunsandClaude Sonnet 5 684b0115e5 feat(worker): preview_merge_set flags removed symbols and locale-key overlaps
Overlap detection was file-name-only: 9/15 tasks touching en.json/de.json in
run #316 all got flagged even though only one pair actually collided on a
key, and a removed method with no textual file conflict (#297 vs #286) went
unflagged entirely.

- removedSymbols per task entry: a line-pattern scan of `-` diff lines for
  C# method/property/field/type/event declarations (skips .axaml/.json).
- symbolWarnings at the set level: cross-references those names against
  every other task's `+` lines, catching same-symbol collisions across
  files that overlaps/subsets (both purely file-based) can't see.
- overlaps narrows to key-path level for .json files (base commit vs. task
  branch head, both sides parsed and flattened) so two tasks adding
  different locale keys to the same file no longer collide; unparsable
  JSON on either side falls back to the old file-level check.
- GitService.ShowFileAsync: `git show ref:path`, used to read a task
  branch's json content at its base/head commit.

Out of scope per the task: no Roslyn/parser, no AXAML analysis, and the
merge-helper prompt in PromptFiles.cs doesn't mention the new fields yet.

Build: dotnet build src/ClaudeDo.App (pulls in Ui+Data) + src/ClaudeDo.Worker, both clean.
Tests: dotnet test tests/ClaudeDo.Worker.Tests --filter "FullyQualifiedName~MergeMcpTools|FullyQualifiedName~ExternalMcpToolSchema" -- 51 passed, 0 failed.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-16 15:43:38 +02:00
Mika Kuns 1325ab9438 fix(ui): Worktrees-Uebersicht zeigt Task-Nummern, DIFF-Spalte trimmt statt abzuschneiden
Befund F7 aus der Sichtpruefung 2026-09-16. TaskNumber war bereits im
WorktreeMaintenanceService-Join und in WorktreeOverviewRow vorhanden, fehlte
aber im Wire-DTO und in der UI-Kette; jetzt bis zur Row-/Conflict-Anzeige
durchgereicht (#<number> dimmed vor dem Titel, ausgeblendet bei 0). DIFF-Spalte
bekommt CharacterEllipsis-Trimming + Tooltip statt hartem Cut, Spalte von 80
auf 110px verbreitert (Header und Row synchron).
2026-09-16 15:43:38 +02:00
Mika Kuns 56161e4e9b feat(ui): Bilder aus der Zwischenablage ins interaktive Terminal einfuegen
Ctrl+V mit einem Bild in der Zwischenablage schreibt es als temporaeres
PNG unter ~/.claudeDo/tmp/ und fuegt den Pfad in den Composer ein, genau
wie ein Datei-Drop -- Claude liest die Datei selbst. Text-Paste laeuft
unveraendert ueber den bestehenden bracketed-paste-Pfad.

Avalonia 12.0.4 liest Clipboard-Bitmaps bereits selbst (IClipboard.
TryGetDataAsync + AsyncDataTransferExtensions.TryGetBitmapAsync), kein
Win32-P/Invoke noetig. Alte Tmp-Dateien (>24h) werden beim App-Start
aufgeraeumt (ClaudeDo.App/Program.cs), keine eigene Aufraeum-Infrastruktur.
2026-09-16 15:43:38 +02:00
Mika Kuns 5cdfb14ff1 fix(ui): Ordner-Toggle in der Sidebar schluckt schnelle Klicks
ToggleFolderAsync war ein async [RelayCommand]; AsyncRelayCommand sperrt
sich waehrend des DB-Writes selbst, schnelle Klicks gingen verloren
(Befund F1, docs/test-session-2026-09-16.md).

Variante A: Toggle ist jetzt synchron (reiner UI-State), Persistierung
fire-and-forget mit einem CancellationTokenSource pro Ordner, damit ein
zweiter Klick vor dem ersten Schreibvorgang diesen abbricht - die DB
landet immer beim zuletzt sichtbaren Zustand, nie bei einem veralteten.
Gleiches Muster wie SaveTitleAsync/SaveDescriptionAsync in
DetailsIslandViewModel.

Gegenprueft: RemoveFromFolderAsync/CreateListAsync haben denselben
async-RelayCommand-Schnitt, sind aber Einzelklick-Aktionen (Kontextmenue/
Button), kein Rapid-Click-Ziel wie der Ordner-Toggle - bewusst nicht
umgebaut. Die Modal-oeffnenden Commands sind unkritisch, ein Modal
blockiert ohnehin.
2026-09-16 15:43:37 +02:00
Mika KunsandClaude Sonnet 5 7452f6cfe4 fix(worker): preview_merge braucht einen runVerify-Parameter wie preview_merge_set
preview_merge baute bisher immer, sobald die Liste ein Verify-Kommando
konfiguriert hatte -- anders als das Geschwister-Tool preview_merge_set,
dessen runVerify-Parameter per Default false ist. Ein einzelnes preview_merge
im Merge-Helper-Recheck stiess dadurch einen ungewollten Scratch-Build an.

runVerify (Default false) jetzt symmetrisch bei preview_merge ergaenzt,
Description-Text und die Merge-Helper-Prompt-Doku angepasst.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-16 15:43:37 +02:00
Mika KunsandClaude Opus 5 c874bf7e52 fix(worker): depends_on-Nachfolger schon beim gelandeten Merge freigeben
Der Queue-Picker gatete eine task_dependencies-Kante auf status='done'.
review_task(skipVerify) laesst einen erfolgreich gemergten Task aber
bewusst auf WaitingForReview stehen, bis verify_merges einmal zentral
laeuft -- damit blockierte jeder Nachfolger ueber den gesamten Batch plus
Full-Suite-Verify hinweg, bei freien Slots.

Eine Kante gilt jetzt als erfuellt, wenn der Vorgaenger 'done' ist ODER
sein Merge gelandet ist (worktrees.state = 'merged'). TaskBlocking
(get_task/list_tasks/wait_for_task_change) und der UI-Wartehinweis folgen
derselben Regel, damit "blocked" nicht meldet, was der Picker claimt.

Abgeleitet: revert_merge/abort_merge setzen den Worktree auf Active und
blockieren wieder; reject_rerun/reject_park haben nie gemergt und bleiben
unerfuellt; ein Task ohne Worktree wird nur ueber 'done' erfuellt; ein
fehlgeschlagener verify_merges gibt Nachfolger frei, weil der Code so
oder so auf main liegt.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-16 15:43:37 +02:00
mika kuns 251b70ce83 feat(merge): Stash-Option fuer uncommittete Aenderungen im Ziel-Tree
Changelog / changelog (push) Successful in 2s
Release / release (push) Successful in 43s
Ein dirty Ziel-Arbeitsverzeichnis gibt jetzt den eigenen Status
dirty_target zurueck statt blocked. Die UI bietet daraufhin einen
Retry an, der per git merge --autostash stasht, merged und die
Aenderungen danach wiederherstellt - opt-in pro Merge:

- Approve & Merge: Bestaetigungsdialog
- Merge-Modal: Button "Aenderungen stashen und mergen"
- MCP (merge_task/review_task) wirft weiterhin, kein autostash dort
2026-09-11 11:43:28 +02:00
mika kuns bfb1c6523c feat(ui): Listen und Ordner in einer gemischten Sidebar-Reihenfolge
Die oberste Sidebar-Ebene ist jetzt eine gemischte TopLevel-Collection, so
dass eine Liste auch oberhalb eines Ordners stehen kann. DropAsync deckt
alle vier Quelle/Ziel-Kombinationen ab, ReorderSidebarAsync numeriert die
gesamte sichtbare Reihenfolge ueber lists und list_folders hinweg.
2026-09-10 15:40:10 +02:00
mika kuns 1770b67713 fix(tickets): Import broadcastet TaskUpdated fuer neue Tasks
ImportTickets sendete nur ListUpdated. Die UI liest das als Aenderung der
Listen-Metadaten und patcht nur bestehende Zeilen, also tauchten die
importierten Tasks erst nach Schliessen und Neuoeffnen der Liste auf.
TicketImportResult liefert jetzt die angelegten Task-Ids, der Hub
broadcastet pro Id ein TaskUpdated - derselbe Pfad, den jeder andere
out-of-band Creator nutzt.
2026-09-10 15:39:58 +02:00
mika kuns 73e038edd9 fix(claude-do): merge GitService stderr matches are English-only, same locale bug
ClaudeDo-Task: 66b7ad7b-ffc4-4ebd-8b21-54bba28e5b04
2026-09-10 13:56:14 +02:00
mika kuns 9d22c775f2 fix(claude-do): merge fix(ui,worker): Diff-Zähler locale-fest machen und toten Par
ClaudeDo-Task: 1085277d-ba7e-4e58-b06d-751e1b99b96f
2026-09-10 13:56:11 +02:00
mika kuns 5ecf6f750a fix(data): force English git output for locale-fragile stderr matches
RevParseHeadAsync and CommitAsync's identity-error detection match
English-only substrings against git stderr. Under a non-English OS/git
locale these silently fail to match, falling through to a generic
error. Force LC_ALL=C and LANGUAGE=C on the git ProcessStartInfo so
git always emits English output regardless of ambient locale.
2026-09-10 13:54:14 +02:00
mika kuns eb62371430 feat(ui): confirm before closing a running ConPTY session
The tile's own X killed a live Claude session with no confirmation, unlike
the semantically similar Abandon-run action. Gate the close behind the same
ConfirmAsync mechanism, but only when Terminal.IsRunning -- a dead session
(StartError or exited-after-startup) still closes immediately since the X
there is pure cleanup.
2026-09-10 13:52:36 +02:00
mika kuns 29ea18c427 fix(ui): make diff-stat parsing locale-safe and dedupe the two parsers
TaskRowViewModel had its own ParseDiffStat expecting "+12"/"-3" tokens that
`git diff --stat` never emits, so the row badge always showed 0/0. Meanwhile
DetailsIslandViewModel's parser matched only the English words
"insertion"/"deletion", so it broke on a localized git (e.g. German Windows:
"Einfügung(en)"/"Löschung(en)").

Row and detail badge now share one parser, anchored on git's untranslated
(+)/(-) suffix instead of the language-dependent word before it, so it reads
correctly in any locale. Also corrected the Worker CLAUDE.md's branch-name
claim (`claudedo/{taskId[:8]}`) to match the actual full-GUID branch name.
2026-09-10 13:50:35 +02:00
mika kuns 1bdf20272d feat(ui): worker-menu Shutdown ends worker + app after confirm
Adds a Shutdown entry after the Worker menu's Restart/Update Claude CLI
items. Confirms via IDialogService.ConfirmAsync, then kills this
installation's ClaudeDo.Worker process(es) (shared kill loop, extracted
from RestartWorkerService) and force-closes the window through the same
_forceClose path MainWindow already uses for the Mission-Control close
confirm, so no second confirmation dialog shows.
2026-09-10 13:48:50 +02:00
mika kuns d2648f965c feat(worker): chain a normal parent's children on WaitingForChildren
A standalone parent (PlanningPhase.None) with existing Idle/Queued children
now runs itself first, then sequences its children instead of flat-enqueuing
all of them at once: SubmitForChildrenAsync calls
PlanningChainCoordinator.SetupChainAsync(enqueue: true) right after the
Running -> WaitingForChildren transition, mirroring the planning path but
firing immediately instead of waiting for an explicit "Queue plan". Planning
parents are left untouched (they queue via QueuePlanAsync), and a child
already Running makes SetupChainAsync throw, which is now caught and logged
so it can't fail the parent's own transition.
2026-09-10 13:36:08 +02:00
mika kuns 897f287ee1 chore(claude-do): merge chore(ui): IWorkerClient.MergeProgressEvent-Forwarder entfer
ClaudeDo-Task: 2feaa8b5-0484-4b11-9519-6627f0bb95a3
2026-09-10 13:35:54 +02:00
mika kuns 1a5728749b fix(claude-do): merge fix(worker): max_turns-Fehlertext nicht fest deutsch — konsi
ClaudeDo-Task: 6549e3b5-cee3-4aa4-ba3a-6240bab952e6
2026-09-10 13:35:45 +02:00
mika kuns 0cec0a77ee fix(ui): report failed paste/drop in the interactive terminal
PasteAsync silently swallowed every exception and returned void, so a
package update renaming Iciclecreek's private write seam would break
Ctrl+V/drop with zero user-visible signal. PasteAsync/SendTextAsync now
return bool (mirroring SendLineAsync), and the view checks the result,
routing a failure through InteractiveTerminalViewModel.ErrorReported ->
ConPtyPaneViewModel.ErrorReported -> the existing footer error strip.
2026-09-10 13:35:16 +02:00
mika kuns b4b6225432 fix(ui): surface worker connect/restart failures instead of no-opting
WorkerConnectionModalViewModel's StartWorker/RerunInstaller swallowed
missing-exe and Process.Start failures behind an empty catch and closed
the dialog anyway, looking like success. Now both show an inline error
and keep the dialog open; only a real launch closes it.

IslandsShellViewModel.RestartWorkerAsync never checked whether the
relaunched worker actually stayed up, and its status property was never
bound in any view. RestartWorkerService now fails if the new process
exits within a short survival window, and the outcome routes through
the footer error/success strip instead of the dead RestartWorkerStatus.

InstallArtifactLocator.Find() is now virtual and its two subclasses
unsealed so tests can fake exe resolution without touching the real
filesystem/registry.
2026-09-10 13:34:32 +02:00
mika kuns 46a0a27620 fix(claude-do): merge fix(ui): Settings-Politur — PowerUse-Zeitfenster validieren,
ClaudeDo-Task: f3f0a355-936c-4933-8236-d41c21fb73dc
2026-09-10 13:34:29 +02:00
mika kuns 423d39e9fb fix(claude-do): merge fix(worker): WeekReportService durch PermissionModeResolver
ClaudeDo-Task: b4198327-6045-451c-abf1-dbabad88e91a
2026-09-10 13:34:20 +02:00
mika kuns 951c2fe92a fix(ui): validate PowerUse window, explain effort and Prime Claude in Settings
Three usability-audit findings in Settings:
- An unparseable PowerUse window (e.g. "9:0") used to save silently as null
  (= round the clock), the opposite of what the typo implied. Validate() now
  rejects an unparseable start/end unless blank; the worker-side read-time
  tolerance is unchanged.
- "Effort" column header gets a tooltip explaining it's the model's reasoning
  effort (cost/depth tradeoff).
- The "Prime Claude" tab gets a tooltip explaining scheduled Claude runs
  (Ping / Fill My Day / custom prompt).

New locale keys added to en+de. Updated the PowerUse round-trip test that
asserted the old silent-normalize behavior.
2026-09-10 13:34:06 +02:00
mika kuns 6f1fbe5b93 fix(claude-do): merge fix(ui): Working-Dir beim Speichern der Listen-Settings als
ClaudeDo-Task: e8986885-add7-43b4-94bf-f12be5712848
2026-09-10 13:34:03 +02:00
mika kuns cfda3e9044 chore(ui): remove IWorkerClient.MergeProgressEvent forwarder
Group C of the operation-feedback batch is fully merged; the two consumers
(DetailsIslandViewModel.ApproveReviewAsync, MergeModalViewModel) now handle
the verifying phase from the generic OperationProgressEvent handler instead
of a separate forwarder event.
2026-09-10 13:33:57 +02:00
mika kuns 451c01848c fix(worker): start_list_handler ehrlich machen, wenn keine App verbunden ist
ConnectedClientTracker zaehlt verbundene UI-Clients (WorkerHub.OnConnectedAsync/
OnDisconnectedAsync). StartListHandler prueft ihn vor dem Broadcast und liefert
bei 0 verbundenen Clients Requested=false plus Reason statt unbedingtem true.
Tool-Beschreibung und external-mcp.md an das reale Verhalten angepasst.
2026-09-10 13:33:30 +02:00
mika kuns 0235b43bad fix(claude-do): merge fix(worker): Port-Konflikt beim Start laut melden statt stil
ClaudeDo-Task: 1eb4cfcd-a31e-4216-8c05-88cd662a211b
2026-09-10 13:33:28 +02:00
mika kuns 3348736e9d fix(ui): warn and block save when a list's working dir isn't a git repo
Reuses RepoScanner.IsRepo (now public) to validate WorkingDir whenever it
changes in ListSettingsModalViewModel — Browse or typing. A missing folder
or a non-repo folder shows an inline warning and gates Save via the same
CanExecute pattern the load-failure gate already uses; an empty WorkingDir
is untouched. Previously this only surfaced as a Failed task deep in
WorktreeManager on first run.

Also localizes the two hardcoded EN strings in the same file (delete
confirm, planning-sessions block) into vm.listSettings.* keys.
2026-09-10 13:32:52 +02:00
mika kuns 4cf601e423 feat(ui): surface depends_on blocking in status chip, chain label, and detail pane
Usability-Audit 2026-09-10 found three gaps versus the dependency-chain-display
spec: a Queued task blocked on an unmet task_dependencies edge rendered the same
chip as one about to run, a cross-list predecessor silently dropped the
"after #N" chip, and the detail pane showed nothing about a wait at all.

- TaskRowViewModel gains IsBlockedByDependency/DependencyWaitLabel (extrinsic,
  assigned by TasksIslandViewModel like the existing chain fields); IsQueued/
  IsWaiting/StatusChipClass/StatusLabel/StatusChipTooltip now account for it
  alongside the existing BlockedByTaskId planning-chain link.
- TasksIslandViewModel.ApplyDependencyWaitState computes the blocked flag and
  wait label per row; a new RefreshExternalDependencyCacheAsync backfills
  Number/Title/Status for predecessors not loaded into the current list's
  Items (reusing the already-open DbContext, no new hub method), so
  BuildAfterLabel/blocking both resolve a listenfremder Vorgänger correctly.
- New "waiting" chip style (IslandStyles.axaml) and locale keys (en+de);
  TaskHeaderBar shows a "Waiting on #N" line bound straight to the same row.

Tests: TasksIslandChainTests (blocked/unblocked chip, cross-list predecessor),
DetailsIslandDependencyWaitTests (new), TaskRowViewModelNotificationsTests
updated for the new notification set.
2026-09-10 13:32:36 +02:00
mika kuns 256bea5ffa fix(ui): show a banner when a ConPTY session dies after startup
InteractiveTerminalViewModel.HasExitedAfterStartup now covers every
post-startup death that ExitedAfterStartup alone missed (crash, clean
exit, quiet exit inside the grace window) -- previously the tile just
stayed looking alive/thinking with zero signal. ConPtyPaneView binds a
new banner to it (message + Retry + Close); CanRetry simplifies to
"any HasExited state" since the same descriptor factory can relaunch
either kind of death. HandlerRestartCoordinator's worker-side
auto-restart path is untouched.
2026-09-10 13:32:19 +02:00
mika kuns 741f66fe14 fix(localization): merge duplicate top-level "checks" block in en/de.json
en.json and de.json each defined the checks object twice; JSON silently
kept the second block's values, so the first block's friendlier titles/hints
(e.g. "Permission Mode" over the raw "--permission-mode auto support" flag)
were dead text. Merged into one block per key, keeping the friendlier title
and the more actionable hint.

Added a Utf8JsonReader-based duplicate-top-level-key test, since
JsonDocument accepts duplicates without error and the existing parity test
can't see this failure mode either.
2026-09-10 13:31:01 +02:00
mika kuns 0fcfe7c524 fix(worker): translate max_turns failure text to English
TaskRunner.BuildFailureMarkdown returned a hardcoded German string for
TerminalReason == "max_turns", the only worker-generated string not in
English. Surfaced as the outcome/roadblock card for one of the most likely
first failures, looking broken to non-German users.
2026-09-10 13:22:30 +02:00
mika kuns 5be972564a feat(ui): mission-control pane title shows usage limit reset time
When a list-handler handoff is deferred waiting for the 5h usage limit to
reset, the Mission Control pane title is augmented with ⏳ waiting for
limit reset (HH:mm) so the wait is visible at a glance. Extends
HubBroadcaster.HandoffRequested with an optional deferredUntil DateTime
parameter, wired through SignalR to MissionControlViewModel, which formats
it into the pane title via Loc.T(missionControl.waitingForLimitReset).
2026-09-10 13:18:09 +02:00
mika kuns 1c76852957 fix(worker): route WeekReportService permission-mode through PermissionModeResolver
Closes the last unrouted --permission-mode call site: haiku default models were
hardcoding raw "auto", which the CLI silently downgrades to interactive "default"
and hangs the report generation. Also drops the author's personal C:\Private
default exclude in favor of an empty default (config stays via ReportExcludedPaths).
2026-09-10 13:13:16 +02:00
mika kuns c9d4823f06 fix(worker): report startup port conflicts instead of crashing silently
Mutex was Local\ (per Windows session), so a second RDP/fast-user-switching
session bypassed the single-instance guard. A Kestrel bind failure on top of
that had no try/catch, so a second worker (or any process on 47821/47822)
died as an unhandled crash with nothing in the log to explain why the UI
never connects. Mutex is now Global\, bind failures and any last-resort
unhandled exception log a Fatal line and exit(1) instead of crashing raw.
2026-09-10 13:12:25 +02:00
mika kuns dbee4a0de9 feat(ui): Worker-Menü "Update Claude CLI" führt claude update aus
Neuer Eintrag im Worker-Menü der Titelleiste, der die Claude CLI über
das konfigurierte claude_bin (ExecutableResolver, inkl. Shim-Handling)
mit `claude update` aktualisiert. Ausgabe/Fehler landen im Footer-Strip
(FlashFooterSuccess/FlashFooterError), Menüpunkt ist während des Laufs
deaktiviert. 5-Minuten-Timeout tötet den Prozessbaum.
2026-09-10 13:10:30 +02:00