Skip to content

Add a plan section to the work-context pane - #1094

Merged
alexeyzimarev merged 4 commits into
mainfrom
capacitor/agent-4da9e05532834e
Sep 21, 2026
Merged

alexeyzimarev merged 4 commits into
mainfrom
capacitor/agent-4da9e05532834e

Conversation

@alexeyzimarev

@alexeyzimarev alexeyzimarev commented Sep 21, 2026 •

Copy link
Copy Markdown
Member

Closes #1075 — AI-3035

What & why

The work-context pane gains a PLAN section between the pull request and SUBAGENTS: the documents the session declared, then its tasks, marked the way subagent rows are. Its header reads "2 of 6 done" while open and, folded, counts settled and open tasks beside their marks. The server pushes nothing when a plan changes, so the section re-reads GET /api/sessions/{id}/plans when a kcap-plans write settles in the local transcript, once more two seconds later because the read model can trail the write, and on the pane's 30 s tick for every other writer. The push itself is kurrent-io/kcap-server#1978.

Where to look

  • PlanToolNames.IsWrite matches a tool by its own name as a suffix: Codex records an MCP tool bare, so matching the kcap-plans server name would miss every Codex session.
  • PlanActivity.Apply takes a whole transcript read, because the chat applies its projection line by line and a replayed history has to cost one server read.

Verification

Check Result
dotnet build Capacitor.slnx 16 projects, 0 errors, 0 warnings
dotnet publish src/Capacitor.Cli -c Release, grep for IL[23] no matches
Capacitor.App.Tests.Unit 2795 / 2795
SessionPlansClientTests, PlanToolNamesTests, McpPlansServerTests 14, 13, 38 — all passed
Pane rendered with Skia, expanded and folded marks, counts and order as described

Not run: the app against a live server. A kcap-plans update from a running Claude and a running Codex session is the check still owed.

🤖 Generated with Claude Code

alexeyzimarev and others added 2 commits September 21, 2026 15:38
The server pushes nothing when a plan changes, so the section re-reads when a
plan write settles in the local transcript. Plan tools are matched by their
own names: Codex records an MCP tool bare, so the server name would miss it.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Merges main. The plan sits directly above SUBAGENTS, and its rows and folded
counts draw their marks from one template so the two cannot drift apart.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 21, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-21T14:39:28.295562Z 7d34381 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Add live plan progress to the work-context pane

✨ Enhancement 🧪 Tests 📝 Documentation 🕐 40+ Minutes

Grey Divider

AI Description

• Adds an expandable PLAN section showing declared documents, tasks, states, notes, and progress.
• Refreshes plans after transcript writes, projection settling, periodic ticks, and authentication
 changes.
• Introduces authenticated plan API models with comprehensive view-model, client, and rendering
 tests.
Diagram

sequenceDiagram
    participant T as Transcript
    participant C as Chat Tab
    participant A as Plan Activity
    participant W as Work Context
    participant P as Plan Section
    participant S as Plan Source
    participant API as Plans API
    participant V as PLAN View
    T->>C: Project tool events
    C->>A: Apply complete read
    A-->>P: Successful write settled
    W->>P: Session or tick refresh
    P->>S: Read session plans
    S->>API: GET session plans
    API-->>S: Documents and tasks
    S-->>P: Totalized result
    P-->>V: Reactive rows and counts
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Server-pushed plan updates
  • ➕ Eliminates transcript inference and periodic polling
  • ➕ Delivers consistent updates from every writer
  • ➕ Avoids the delayed second read after projection lag
  • ➖ Requires a new server event contract and client subscription lifecycle
  • ➖ Depends on server work outside this PR
  • ➖ Still needs initial and reconnect reads
2. Include plans in work-context reads
  • ➕ Uses the pane's existing refresh and session lease
  • ➕ Reduces the number of independent client abstractions
  • ➖ Couples plan latency and failures to work-item rendering
  • ➖ Prevents independent plan refreshes after transcript writes
  • ➖ Makes frequent plan polling fetch unrelated work-context data

Recommendation: Keep the independent plan source and transcript-assisted polling implemented here. It isolates plan latency from the existing work-context read and provides near-real-time local updates without requiring unavailable server push support; migrate the refresh trigger to server-pushed events if that capability is later exposed.

Files changed (35) +1565 / -30

Enhancement (20) +601 / -17
App.axaml.csRegister the authenticated plan source +3/-2

Register the authenticated plan source

• Creates ServerPlanSource, adds it to shared server-client cleanup, and injects it into the workspace graph.

src/Capacitor.App/App.axaml.cs

IPlanSource.csDefine the session-plan source contract +8/-0

Define the session-plan source contract

• Adds an abstraction for cancellation-aware reads of plans associated with a session.

src/Capacitor.App/Services/IPlanSource.cs

ServerClients.csManage plan-source authentication and disposal +8/-5

Manage plan-source authentication and disposal

• Adds the plan source to authentication invalidation and guarded server-client cleanup ordering.

src/Capacitor.App/Services/ServerClients.cs

ServerPlanSource.csAdd authenticated server-backed plan reads +22/-0

Add authenticated server-backed plan reads

• Wraps SessionPlansClient with shared authenticated-read behavior, fallback outcomes, invalidation, and async disposal.

src/Capacitor.App/Services/ServerPlanSource.cs

ChatTabViewModel.csForward transcript plan activity to the pane +9/-3

Forward transcript plan activity to the pane

• Applies full transcript reads to PlanActivity, propagates session completion, and clears in-flight plan calls when feeds change.

src/Capacitor.App/ViewModels/ChatTabViewModel.cs

PlanActivity.csDetect settled plan writes in transcripts +46/-0

Detect settled plan writes in transcripts

• Correlates plan tool calls with successful results, emits one refresh signal per transcript read, and tracks whether the session ended.

src/Capacitor.App/ViewModels/PlanActivity.cs

PlanDocumentRow.csModel declared plan documents for display +7/-0

Model declared plan documents for display

• Represents document kind and path while deriving a cross-platform filename for the pane.

src/Capacitor.App/ViewModels/PlanDocumentRow.cs

PlanSectionViewModel.csCoordinate plan reads, refreshes, and progress rows +207/-0

Coordinate plan reads, refreshes, and progress rows

• Adds session-scoped read leases, stale-result protection, write-triggered rereads, projection-settle delay, plan selection, reactive counts, and teardown. It preserves visible plans during outages and updates stable task rows in place.

src/Capacitor.App/ViewModels/PlanSectionViewModel.cs

PlanTaskRow.csPresent mutable plan-task state +56/-0

Present mutable plan-task state

• Maps server statuses to display states, exposes settled and active flags, and updates row content without replacing UI containers.

src/Capacitor.App/ViewModels/PlanTaskRow.cs

PlanTaskState.csDefine display states for plan tasks +3/-0

Define display states for plan tasks

• Adds pending, in-progress, completed, and skipped task states for binding and templates.

src/Capacitor.App/ViewModels/PlanTaskState.cs

WorkContextViewModel.csIntegrate plan lifecycle with work context +15/-4

Integrate plan lifecycle with work context

• Owns the plan section and refreshes it on session changes, pane ticks, manual refreshes, and sign-in completion. Teardown now awaits plan cleanup.

src/Capacitor.App/ViewModels/WorkContextViewModel.cs

WorkspaceViewModel.csShare plan activity between chat and work context +5/-3

Share plan activity between chat and work context

• Creates one PlanActivity per workspace and injects it into the chat and work-context view models alongside the plan source.

src/Capacitor.App/ViewModels/WorkspaceViewModel.cs

WorkContextView.axamlRender expandable plan documents and tasks +121/-0

Render expandable plan documents and tasks

• Adds the PLAN section between pull requests and subagents, including shared state marks, active-task animation, notes, document labels, expanded progress text, and folded counts.

src/Capacitor.App/Views/WorkContextView.axaml

Models.csRegister session-plan JSON serialization +1/-0

Register session-plan JSON serialization

• Adds source-generated serialization metadata for lists of session plans.

src/Capacitor.Cli.Core/Models.cs

PlanDocumentDto.csModel plan document summaries +11/-0

Model plan document summaries

• Defines the document key, kind, and repository-relative path returned by the session-plans endpoint.

src/Capacitor.Cli.Core/Plans/PlanDocumentDto.cs

PlanToolNames.csCentralize and recognize plan tool names +20/-0

Centralize and recognize plan tool names

• Defines shared MCP tool constants and detects write tools by suffix across bare Codex and prefixed Claude spellings while rejecting partial matches.

src/Capacitor.Cli.Core/Plans/PlanToolNames.cs

SessionPlanDto.csModel plans returned for a session +12/-0

Model plans returned for a session

• Defines plan identity, current-plan selection, declared documents, and ordered task data.

src/Capacitor.Cli.Core/Plans/SessionPlanDto.cs

SessionPlansClient.csRead plans from the session plans API +36/-0

Read plans from the session plans API

• Adds canonical session-ID handling, authenticated GET requests, JSON parsing, status normalization, transient failure handling, and cancellation propagation.

src/Capacitor.Cli.Core/Plans/SessionPlansClient.cs

SessionPlansRead.csRepresent totalized session-plan reads +6/-0

Represent totalized session-plan reads

• Pairs a normalized outcome with the plans returned by the server and provides empty-result construction.

src/Capacitor.Cli.Core/Plans/SessionPlansRead.cs

SessionPlansReadKind.csClassify session-plan read outcomes +5/-0

Classify session-plan read outcomes

• Distinguishes successful, unavailable, signed-out, and unreachable responses so callers can retain or clear state appropriately.

src/Capacitor.Cli.Core/Plans/SessionPlansReadKind.cs

Refactor (1) +10 / -9
McpPlansServer.csReuse shared plan MCP tool constants +10/-9

Reuse shared plan MCP tool constants

• Replaces duplicated string literals in dispatch and tool registration with PlanToolNames constants.

src/Capacitor.Cli/Commands/McpPlansServer.cs

Tests (11) +913 / -3
ChatTabViewModelTests.csTest chat-driven plan write notifications +39/-1

Test chat-driven plan write notifications

• Verifies successful transcript writes notify PlanActivity only after their results and that feed changes discard old in-flight calls.

test/Capacitor.App.Tests.Unit/ChatTabViewModelTests.cs

FakePlanSource.csAdd a scripted plan-source test double +32/-0

Add a scripted plan-source test double

• Provides queued and gated plan responses while recording requested session IDs for deterministic lifecycle tests.

test/Capacitor.App.Tests.Unit/FakePlanSource.cs

PlanActivityTests.csTest plan transcript activity folding +101/-0

Test plan transcript activity folding

• Covers call/result correlation, deduplication, replay batching, errors, unrelated tools, subscriber failures, and clearing.

test/Capacitor.App.Tests.Unit/PlanActivityTests.cs

PlanSectionViewModelTests.csTest plan-section state and read lifecycle +334/-0

Test plan-section state and read lifecycle

• Covers plan selection, ordering, counts, documents, unknown statuses, stale reads, refresh coalescing, settle rereads, outages, row identity, session completion, toggling, and teardown.

test/Capacitor.App.Tests.Unit/PlanSectionViewModelTests.cs

ServerClientsTests.csTest plan-source cleanup ordering +10/-0

Test plan-source cleanup ordering

• Verifies the plan source is disposed after launch, work-context, and pull-request clients.

test/Capacitor.App.Tests.Unit/ServerClientsTests.cs

ServerPlanSourceTests.csTest authenticated plan-source behavior +64/-0

Test authenticated plan-source behavior

• Verifies signed-out fallback behavior and authenticated-client retirement and recreation after unauthorized responses.

test/Capacitor.App.Tests.Unit/ServerPlanSourceTests.cs

WorkContextViewModelTests.csTest plan integration with pane refreshes +73/-1

Test plan integration with pane refreshes

• Verifies session, timer, manual, and sign-in refreshes reach the plan source, session changes replace plan state, and teardown stops reads.

test/Capacitor.App.Tests.Unit/WorkContextViewModelTests.cs

WorkContextViewSmokeTests.csSmoke-test PLAN section rendering +105/-1

Smoke-test PLAN section rendering

• Validates placement, document and task content, state styling, active animation, expanded progress, folded counts, document-only plans, and hidden empty state.

test/Capacitor.App.Tests.Unit/WorkContextViewSmokeTests.cs

WorkspaceViewSmokeTests.csRegister PLAN controls in workspace smoke tests +1/-0

Register PLAN controls in workspace smoke tests

• Ensures every new named PLAN section control resolves in the assembled workspace view.

test/Capacitor.App.Tests.Unit/WorkspaceViewSmokeTests.cs

PlanToolNamesTests.csTest cross-vendor plan tool matching +28/-0

Test cross-vendor plan tool matching

• Covers bare and prefixed write names while rejecting reads, unrelated names, nulls, and misleading suffix extensions.

test/Capacitor.Cli.Core.Tests.Unit/Plans/PlanToolNamesTests.cs

SessionPlansClientTests.csTest the session-plans HTTP client +126/-0

Test the session-plans HTTP client

• Covers ID canonicalization and containment, DTO parsing, empty plans, HTTP outcome mapping, malformed payloads, transport failures, and caller cancellation.

test/Capacitor.Cli.Core.Tests.Unit/Plans/SessionPlansClientTests.cs

Documentation (3) +41 / -1
README.mdDocument the work-context PLAN section +2/-0

Document the work-context PLAN section

• Explains plan documents, task states, progress counts, refresh timing, placement, and non-clickable rows.

README.md

CHANGES.mdRecord plan-pane behavior and design decisions +37/-0

Record plan-pane behavior and design decisions

• Documents rendering semantics, plan selection, API choice, transcript-driven refreshes, polling, lease isolation, error handling, and stable row identity.

docs/CHANGES.md

PlanLedgerTaskDto.csClarify extensible plan task values +2/-1

Clarify extensible plan task values

• Updates contract documentation to require fallback handling for server-defined status or source values.

src/Capacitor.Cli.Core/Plans/PlanLedgerTaskDto.cs

@qodo-code-review

qodo-code-review Bot commented Sep 21, 2026 •

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Grey Divider


Remediation recommended

1. Failed plan writes trigger extra reads ✗ Dismissed 🐞 Bug ➹ Performance
Description
PlanActivity.Apply emits PlanWritten for any matched result whose ToolIsError value is false,
but the Codex projection never populates that flag. When a Codex plan tool returns an error, the
pane performs both the immediate and delayed server reads even though no plan changed.
Code

src/Capacitor.App/ViewModels/PlanActivity.cs[R32-33]

+                if (envelope.Kind == AcpEventKind.ToolCall && PlanToolNames.IsWrite(envelope.ToolName)) _writes.Add(callId);
+                else if (envelope.Kind == AcpEventKind.ToolResult && _writes.Remove(callId) && !envelope.ToolIsError) written = true;
Relevance

●●● Strong

Codex error metadata is omitted, causing failed writes to trigger unnecessary refresh reads; similar
Codex robustness fixes were accepted.

PR-#515
PR-#648

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The new activity tracker requires ToolIsError to suppress refreshes. Codex maps both
function-output variants to ToolResultReceived using only the call ID and output text, after which
the common envelope conversion leaves ToolIsError at its false default; Claude explicitly maps its
vendor error metadata, demonstrating the missing Codex path.

src/Capacitor.App/ViewModels/PlanActivity.cs[27-34]
src/Capacitor.Models.Transcripts/Harness/Codex/CodexRolloutEvents.cs[40-45]
src/Capacitor.Cli.Core/TranscriptEnvelopes.cs[30-33]
src/Capacitor.Cli.Core/Harness/Claude/ClaudeChatRules.cs[43-47]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Failed Codex plan-tool results are projected without `ToolIsError`, so `PlanActivity` treats them as successful writes and schedules two unnecessary plan reads.

## Fix Focus Areas
- src/Capacitor.Models.Transcripts/Harness/Codex/CodexRolloutEvents.cs[40-45]
- src/Capacitor.Cli.Core/Harness/Codex/CodexChatRules.cs[14-18]
- src/Capacitor.App/ViewModels/PlanActivity.cs[27-34]

## Recommended Fix
Preserve the error state exposed by Codex tool output when projecting a tool result and map it to `AcpEventEnvelope.ToolIsError`. Add coverage proving that a failed Codex plan result does not emit `PlanWritten`, while a successful result still does.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Plan markup has a redundant comment ✓ Resolved 📘 Rule violation ⚙ Maintainability
Description
The comment above PlanSection merely narrates the documents, tasks, expanded progress text, and
folded counts expressed by the immediately following bindings. When the markup changes, this
duplicate description can become stale without preserving any invariant, workaround, or
behavior-critical rationale.
Code

src/Capacitor.App/Views/WorkContextView.axaml[R510-511]

+                <!-- Plan: the documents and tasks the session declared, read from the server. Expanded,
+                     the header says how far along it is; folded, it carries a count per mark. -->
Relevance

●●● Strong

Recent precedent accepts removing comments that merely restate immediately following XAML bindings.

PR-#1068

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Compliance rule 2762993 permits comments only for non-obvious, behavior-critical constraints. The
cited comment describes behavior directly represented by PlanSection, PlanHeaderText, and
PlanCounts in the following markup.

Rule 2762993: Restrict comments to documenting non-obvious, behavior‑critical constraints
src/Capacitor.App/Views/WorkContextView.axaml[510-511]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The comment above the PLAN section restates behavior already clear from the surrounding controls and bindings, rather than documenting a non-obvious constraint.

## Fix Focus Areas
- src/Capacitor.App/Views/WorkContextView.axaml[510-511]

## Recommended Fix
Remove the two-line comment. If an undocumented behavior-critical constraint exists, replace it with a concise comment explaining that rationale rather than narrating the visible markup.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Context sources
✅ Compliance rules (platform): 64 rules
✅ Cross-repo context — repo relationships
  Explored: repo: kurrent-io/kcap-server (sha: 7f7d7c40)
Review mode: 🧠 Deep: This is a broad, behavior-heavy feature spanning UI, asynchronous refresh/lease lifecycle, transcript projection, HTTP/auth clients, serialization, and many independent code paths, creating a high density of subtle defects.

Grey Divider

Tip of the day
💡 Did you know, you can add REVIEW.md to your repo root and Qodo follows it on every PR

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread src/Capacitor.App/Views/WorkContextView.axaml Outdated
Comment thread src/Capacitor.App/ViewModels/PlanActivity.cs
alexeyzimarev and others added 2 commits September 21, 2026 16:44
Merges main. The pane's name pin carries the plan section's names next to the
pull request and issue sections it sits under.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add plan sidebar widget to the app

1 participant