From 096519b978a17ec5821921e556702f08cc78fe91 Mon Sep 17 00:00:00 2001 From: mika kuns Date: Fri, 5 Jun 2026 08:21:33 +0200 Subject: [PATCH] docs(review): add implementation plan for terminal-style review controls Co-Authored-By: Claude Opus 4.7 --- .../plans/2026-06-05-terminal-review.md | 522 ++++++++++++++++++ 1 file changed, 522 insertions(+) create mode 100644 docs/superpowers/plans/2026-06-05-terminal-review.md diff --git a/docs/superpowers/plans/2026-06-05-terminal-review.md b/docs/superpowers/plans/2026-06-05-terminal-review.md new file mode 100644 index 0000000..c624c5b --- /dev/null +++ b/docs/superpowers/plans/2026-06-05-terminal-review.md @@ -0,0 +1,522 @@ +# Terminal-style Review Controls Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Move review feedback into the Output (terminal) tab as a prompt-style input with `[Retry]`/`[Reset]` actions, and relocate Approve + all merge/worktree controls to a new **Git** tab. + +**Architecture:** Pure UI-layer change in `ClaudeDo.Ui`. Add an `IsGitTab` computed flag to `DetailsIslandViewModel`, re-home existing XAML blocks across three tabs (Output · Git · Session) in `WorkConsole.axaml`, add a bottom-docked review footer to the Output tab, and intercept Enter in `WorkConsole.axaml.cs`. No worker-side or `IWorkerClient` changes; no ViewModel command renames. + +**Tech Stack:** .NET 8, Avalonia 12 (Fluent), CommunityToolkit.Mvvm, xUnit (ClaudeDo.Ui.Tests). + +**Reference spec:** `docs/superpowers/specs/2026-06-05-terminal-review-design.md` + +**Build/test note (from CLAUDE.md):** A running Worker locks `Debug` output — build UI in `-c Release`: +`dotnet build src/ClaudeDo.App/ClaudeDo.App.csproj -c Release` +`dotnet test tests/ClaudeDo.Ui.Tests/ClaudeDo.Ui.Tests.csproj -c Release` + +--- + +## File Structure + +- Modify: `src/ClaudeDo.Ui/ViewModels/Islands/DetailsIslandViewModel.cs` — add `IsGitTab`, wire notifications. +- Modify: `src/ClaudeDo.Ui/Views/Islands/Detail/WorkConsole.axaml` — add Git tab button; split tab bodies; add Output-tab review footer; update Session empty-state text. +- Modify: `src/ClaudeDo.Ui/Views/Islands/Detail/WorkConsole.axaml.cs` — Enter-to-Retry key handling. +- Test: `tests/ClaudeDo.Ui.Tests/ViewModels/DetailsIslandTabsTests.cs` (create) — `IsGitTab` behavior. + +--- + +### Task 1: Add `IsGitTab` tab flag to the ViewModel + +**Files:** +- Modify: `src/ClaudeDo.Ui/ViewModels/Islands/DetailsIslandViewModel.cs:139-147` +- Test: `tests/ClaudeDo.Ui.Tests/ViewModels/DetailsIslandTabsTests.cs` (create) + +- [ ] **Step 1: Write the failing test** + +Create `tests/ClaudeDo.Ui.Tests/ViewModels/DetailsIslandTabsTests.cs`. Mirror the +construction pattern from `DetailsIslandPrepModeTests.cs` (temp SQLite db, +`TestDbFactory`, `StubWorkerClient`, `NullServiceProvider`, `StubNotesApi`). + +```csharp +using ClaudeDo.Data; +using ClaudeDo.Ui.Services; +using ClaudeDo.Ui.ViewModels.Islands; +using Microsoft.EntityFrameworkCore; + +namespace ClaudeDo.Ui.Tests.ViewModels; + +public class DetailsIslandTabsTests : IDisposable +{ + private readonly string _dbPath; + + public DetailsIslandTabsTests() + { + _dbPath = Path.Combine(Path.GetTempPath(), $"claudedo_tabs_test_{Guid.NewGuid():N}.db"); + using var ctx = NewContext(); + ctx.Database.EnsureCreated(); + } + + public void Dispose() + { + try { File.Delete(_dbPath); } catch { } + try { File.Delete(_dbPath + "-wal"); } catch { } + try { File.Delete(_dbPath + "-shm"); } catch { } + } + + private ClaudeDoDbContext NewContext() + { + var opts = new DbContextOptionsBuilder() + .UseSqlite($"Data Source={_dbPath}") + .Options; + return new ClaudeDoDbContext(opts); + } + + private sealed class TestDbFactory : IDbContextFactory + { + private readonly Func _create; + public TestDbFactory(Func create) => _create = create; + public ClaudeDoDbContext CreateDbContext() => _create(); + } + + private sealed class StubNotesApi : ClaudeDo.Ui.Services.Interfaces.INotesApi + { + public Task> ListAsync(DateOnly day) => Task.FromResult(new List()); + public Task AddAsync(DateOnly day, string text) => Task.FromResult(null); + public Task UpdateAsync(string id, string text) => Task.CompletedTask; + public Task DeleteAsync(string id) => Task.CompletedTask; + } + + private sealed class NullServiceProvider : IServiceProvider + { + public object? GetService(Type serviceType) => null; + } + + // StubWorkerClient is abstract — use a concrete no-op subclass (same pattern as DetailsIslandPrepModeTests). + private sealed class DefaultStub : StubWorkerClient { } + + private DetailsIslandViewModel NewVm() + { + var factory = new TestDbFactory(NewContext); + return new DetailsIslandViewModel(factory, new DefaultStub(), new NullServiceProvider(), new StubNotesApi()); + } + + [Fact] + public void SelectTab_git_sets_IsGitTab_and_clears_others() + { + var vm = NewVm(); + + vm.SelectTabCommand.Execute("git"); + + Assert.True(vm.IsGitTab); + Assert.False(vm.IsOutputTab); + Assert.False(vm.IsSessionTab); + } + + [Fact] + public void Default_tab_is_output_not_git() + { + var vm = NewVm(); + + Assert.True(vm.IsOutputTab); + Assert.False(vm.IsGitTab); + } +} +``` + +- [ ] **Step 2: Run test to verify it fails** + +Run: `dotnet test tests/ClaudeDo.Ui.Tests/ClaudeDo.Ui.Tests.csproj -c Release --filter DetailsIslandTabsTests` +Expected: FAIL — compile error, `DetailsIslandViewModel` has no `IsGitTab`. + +- [ ] **Step 3: Add `IsGitTab` to the ViewModel** + +In `DetailsIslandViewModel.cs`, find the `SelectedTab` property notifications and the +tab getters (around lines 139-147). Add the `IsGitTab` notification and getter: + +```csharp + [NotifyPropertyChangedFor(nameof(IsOutputTab))] + [NotifyPropertyChangedFor(nameof(IsSessionTab))] + [NotifyPropertyChangedFor(nameof(IsGitTab))] +``` + +```csharp + public bool IsOutputTab => SelectedTab == "output"; + public bool IsGitTab => SelectedTab == "git"; + public bool IsSessionTab => SelectedTab == "session"; +``` + +(Leave `SelectTab` unchanged — it already accepts any string and defaults to `"output"`.) + +- [ ] **Step 4: Run test to verify it passes** + +Run: `dotnet test tests/ClaudeDo.Ui.Tests/ClaudeDo.Ui.Tests.csproj -c Release --filter DetailsIslandTabsTests` +Expected: PASS (2 tests). + +- [ ] **Step 5: Commit** + +```bash +git add src/ClaudeDo.Ui/ViewModels/Islands/DetailsIslandViewModel.cs tests/ClaudeDo.Ui.Tests/ViewModels/DetailsIslandTabsTests.cs +git commit -m "feat(ui): add IsGitTab flag to work console view model" +``` + +--- + +### Task 2: Add the Git tab button and move the merge/worktree block onto it + +**Files:** +- Modify: `src/ClaudeDo.Ui/Views/Islands/Detail/WorkConsole.axaml:124-135` (tab strip) +- Modify: `src/ClaudeDo.Ui/Views/Islands/Detail/WorkConsole.axaml:164-273` (tab body) + +- [ ] **Step 1: Add the Git tab button** + +In the tab strip `StackPanel` (lines 124-135), insert a Git button between the Output +and Session buttons: + +```xml + + +