Skip to content

[twarp 07] respec: port deleted Agent Mode UI instead of rebuilding#68

Merged
timomak merged 2 commits into
masterfrom
twarp-07-respec
Jun 2, 2026
Merged

[twarp 07] respec: port deleted Agent Mode UI instead of rebuilding#68
timomak merged 2 commits into
masterfrom
twarp-07-respec

Conversation

@timomak
Copy link
Copy Markdown
Owner

@timomak timomak commented May 29, 2026

Why this re-spec exists

The first implementation attempt, PR #67, rebuilt the Claude Code panel entirely from GPUI primitives (Flex::column(), Container::new(...).with_background_color(...), appearance.ui_builder().span(...)/.link(...)) — zero lines from the deleted Agent Mode rendering layer, directly against the 7a port-and-adapt mandate. The result looks nothing like Warp's Agent Mode:

  • plain-text "tool cards" with no per-tool affordances;
  • a similar unified diff rendered as untinted plain spans (no +/- tinting, no hunk headers — none of feature 05's treatment, despite PRODUCT §33);
  • a static Flex::column with no UniformList and no bottom-stick auto-scroll;
  • plain-text assistant output instead of feature 03's markdown (§18);
  • a WorkspaceAction::ClaudeCodePanel(...) dispatch workaround because direct typed-action dispatch "dropped silently" — symptom-treatment, not the fix.

This PR regresses feature 07 from impl-in-review back to spec-in-review and rewrites the plan as a per-file porting guide an implementer cannot misread. It changes only roadmap/ docs — no code.

Investigation (the main work)

I read every deleted UI file from fea2f7ea (the feature-02 spec commit, predates all deletions) and the kept crates/claude_code driver. Findings:

The original TECH.md table conflated two distinct deleted surfaces that were never composed together:

  • app/src/ai_assistant/ — the simple Warp AI Q&A panel (prompt→answer transcript, markdown + code blocks; coupled to Requests/AIClient/ServerApi/InputSuggestions). No tool cards, thinking, todos, or diffs.
  • app/src/ai/blocklist/Agent Mode (the tool-card / diff / thinking / todo surface that warp.dev/agents/claude-code shows), deeply coupled to AIBlock/AIBlockModel/AIAgentOutputMessageType/BlocklistAIActionModel.

Per-file decision matrix (full version + git show recovery commands in TECH.md):

Source @ fea2f7ea Verdict Why
inline_action/{inline_action_header,requested_action,requested_script,inline_action_icons}.rs Port (clean leaves) Zero crate::ai:: service coupling — take strings + Rc<dyn Fn> callbacks. The reusable card chrome.
ai_assistant/transcript.rs render_message + utils.rs markdown split Port + reparent Markdown prose + code blocks; swap RequestsTranscript::items().
markdown_parser::parse_markdown + FormattedTextElement Reuse on master AI-agnostic; feature 03's live stack (§18).
code_review_view.rs diff renderer / crate::code::inline_diff::InlineDiffView Reuse (feature 05) Themed read-only +/- diff (§30–§33).
block/view_impl/todos.rs Port leaf + bridge Reuse header+icons; swap AIConversation/AIAgentTodo → our TodoItem/TodoStatus.
block/view_impl/{output,common}.rs Extract helpers output::render is a 700-line match over AIAgentOutputMessageType; lift only FormattedTextElement + collapsible/format_elapsed_seconds.
inline_action/code_diff_view.rs (3190 ln) Do NOT port Interactive accept/reject editor; needs AIBlockModel+BlocklistAIActionModel+telemetry+history-revert; delegates real diffing to inline_diff. Wrong target — reuse feature 05.
inline_action/requested_command.rs (1646 ln) Rewrite leaf Stateful View bound to BlocklistAIActionModel/TerminalModel/CodeEditorView; rebuild from the clean chrome.
block/view_impl/header.rs Do NOT port Agent-block chrome tied to TerminalAction/DirectoryContext; our header is net-new.

Dispatch fix (the #67 bug): GlobalSearchView — a working left-panel tab — is itself a TypedActionView that dispatches its own actions directly. So #67's "actions drop unless routed through WorkspaceAction" was a focus-wiring defect, not inherent. The ported panel is a self-dispatching TypedActionView + an on_left_mouse_down focus-grab (the ai_assistant/panel.rs pattern); the WorkspaceAction::ClaudeCodePanel forwarder is deleted.

What survives PR #67 vs what is discarded

  • Keep: the headless crates/claude_code driver crate (lib.rs Transcript/TranscriptEvent/TranscriptItem; driver.rs subprocess + defensive JSONL parser + SIGINT + stdin writer; sessions.rs) — 19 passing tests — and the registration scaffolding (ToolPanelView::ClaudeCode, toolbelt button, render arm, ⌘⌥K via custom_tag_to_keystroke, compute_left_panel_views push). Some pure data helpers (tool_input_summary, diff_for_tool) survive as bridge code.
  • Discard: the entire primitive panel body + the WorkspaceAction::ClaudeCodePanel forwarder.

Doc changes in this PR

  • TECH.md — postmortem + implementer stop-sign; corrected "what 02 deleted" table; per-file decision matrix; git show recovery commands; stub/co-port + TranscriptItem→leaf bridge layers; re-derived port-shaped 7b–7h (7b = "panel shell + ported transcript with a stub event source", visually testable end-to-end with no driver); "visually matches Agent Mode" acceptance gate; risks updated (top risk is now "re-rebuilding from primitives").
  • PRODUCT.md — behavior contract unchanged except making visual consistency with Agent Mode an explicit acceptance gate (Figma note + new smoke step 28). The 62 invariants are otherwise intact.
  • STATUS.md — regression narrative, [twarp 07b] Claude Code panel: resurrect view + event model #67 postmortem, cleared 7b–7h ticks (work shipped against the wrong approach), re-derived sub-phases, dispatch/two-surface decisions recorded.
  • ROADMAP.md — row 07 spec column adds this re-spec PR; impl column cleared.

Relationship to PR #67

This re-spec supersedes #67's approach. #67 should be closed (leaving the kept crates/claude_code driver to be brought into the next impl branch). Per repo convention I'm not closing #67 — that's the owner's call.

Notes

  • Spec-only; no code compiled/changed. Fork CI ending "cancelled" is expected (no matrix runners), not a failure.
  • Implementation is a separate branch + PR in a future chat — this PR is the plan to review first.

🤖 Generated with Claude Code

timomak and others added 2 commits May 29, 2026 11:23
PR #67 rebuilt the Claude Code panel from GPUI primitives (Flex/Container/
Link), ignoring the 7a port-and-adapt mandate: plain-text tool cards,
untinted diffs, no UniformList, plain-text assistant output, and a
WorkspaceAction dispatch workaround. This re-spec regresses 07 from
impl-in-review back to spec-in-review and rewrites the plan as a per-file
porting guide an implementer cannot misread.

Investigation findings (TECH.md):
- The old "what 02 deleted" table conflated two distinct deleted surfaces:
  ai_assistant/ (the simple Warp AI Q&A panel) vs ai/blocklist/ (Agent Mode,
  the tool-card/diff/thinking/todo surface). They were never composed together.
- Per-file decision matrix: the cleanly reusable leaves are the inline_action
  card chrome (HeaderConfig / RenderableAction / status icons, already
  AI-agnostic), the shared markdown stack (parse_markdown -> FormattedTextElement),
  and feature 05's read-only diff renderer. code_diff_view.rs and
  requested_command.rs are deeply service-coupled (interactive editor diff;
  live BlocklistAIActionModel command runner) -> rewrite/reuse, do NOT port.
- Dispatch fix: the panel is a self-dispatching TypedActionView like
  GlobalSearchView + an on_left_mouse_down focus-grab; delete the
  WorkspaceAction::ClaudeCodePanel forwarder #67 added.

Kept from #67: the headless crates/claude_code driver crate (lib/driver/
sessions, 19 passing tests) + the registration scaffolding (ToolPanelView,
toolbelt button, render arm, ⌘⌥K via custom_tag_to_keystroke). Discarded: the
primitive panel body and the WorkspaceAction forwarder.

Doc changes:
- TECH.md: postmortem + stop-sign, corrected table, per-file decision matrix,
  git-show recovery commands, stub/co-port + bridge layers, port-shaped 7b-7h,
  "visually matches Agent Mode" acceptance gate.
- PRODUCT.md: visual-consistency acceptance gate (Figma note + smoke step 28).
- STATUS.md: regression narrative + #67 postmortem + cleared 7b-7h ticks +
  re-derived port-shaped sub-phases.
- ROADMAP.md: row 07 spec column adds the re-spec PR (impl column cleared).

Spec-only change; no code. PR #67 to be closed by the owner.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@timomak timomak merged commit d178c95 into master Jun 2, 2026
5 of 17 checks passed
timomak added a commit that referenced this pull request Jun 2, 2026
Reconcile after re-spec #68 merged: phase spec-in-review -> impl-in-review.
Tick 7b, record the 7b decisions (always-on, no feature flag) and PR #69.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
timomak added a commit that referenced this pull request Jun 2, 2026
* [twarp 07b] Claude Code panel: panel shell + ported transcript

Sub-phase 7b of feature 07. Brings back Warp Agent Mode's rendering layer as
a left-panel tab by PORTING the deleted ai_assistant transcript renderer onto
the thin claude_code::Transcript model, fed by a synthetic event source (no
live driver yet — that lands in 7c).

Rendering layer only: no AI service, LLM client, billing, or cloud sync comes
back (feature 02's removals stay removed). From 7c on, the panel talks solely
to the local `claude` CLI the user already runs.

Kept from #67 (correct, decoupled):
- crates/claude_code driver crate (Transcript/TranscriptEvent/TranscriptItem
  + driver + sessions) — 19 unit tests pass.
- Registration scaffolding: ToolPanelView::ClaudeCode, the toolbelt button,
  render arm, compute_left_panel_views push, and the remappable ⌘⌥K binding
  via custom_tag_to_keystroke (not with_key_binding — the feature-06 lesson).

Discarded from #67:
- The primitive Flex/Container/Link panel body (rebuilt as a port).
- The WorkspaceAction::ClaudeCodePanel forwarder + its handler arm. The panel
  now self-dispatches ClaudeCodePanelAction the GlobalSearchView way (it is a
  TypedActionView with an on_left_mouse_down focus-grab).

The port:
- render_markdown_body ports render_message's markdown body (FormattedTextElement
  for prose, a bordered monospace box for fenced code).
- split_markdown_segments ports the AI-agnostic markdown splitter.
- Reuses feature 03's parse_markdown -> FormattedTextElement stack (§18), so
  assistant text renders as themed markdown, not plain spans.
- Transcript renders in a UniformList; zero state + claude-unavailable state;
  always-on (no feature flag — degrades cleanly when claude is off PATH, §6).

cargo test -p claude_code (19 passed), cargo check -p warp, cargo clippy, and
cargo fmt all clean. Scope is 7b only; 7c–7h follow.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* [twarp 07b] roadmap: advance feature 07 to impl-in-review (7b PR #69)

Reconcile after re-spec #68 merged: phase spec-in-review -> impl-in-review.
Tick 7b, record the 7b decisions (always-on, no feature flag) and PR #69.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <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.

1 participant