Skip to content
This repository was archived by the owner on Aug 17, 2026. It is now read-only.
This repository was archived by the owner on Aug 17, 2026. It is now read-only.

Dashboard renders write xd://propose (and other xd devices) as file writes — no plan-approval UI #117

Description

@joeshull

Summary

Dashboard treats OMP 17 write xd://… device dispatches as ordinary file writes. TUI does not.

Worst case is plan mode: write xd://propose is the only way to submit a plan for approval. TUI pops handlePlanApproval({ planFilePath, title, planExists }). Dashboard renders a Write xd://propose card with the slug as file content and never opens an approval UI.

Same unwrap gap hits every other xd:// device (resolve, reject, MCP, github, canvas, …) plus a long tail of TUI-specialized tools that fall through to GenericToolRenderer (raw JSON args).

Not a dup of #95 (Ask collapse), #56 (xd:// excluded from change summaries only), or #115 (prompt-bus re-entry crash).

Observed

Live session ~/.omp/agent/sessions/-code-zge-workspace/2026-07-16T22-34-50-732Z_019f6d11-7dec-7000-b12d-b062e35737a2.jsonl:

toolName: write
args.path: "xd://propose"
args.content: "omp-ci-debt-repair/CI debt repair + …"
result.text: "Plan ready for approval."
details.xdev: {
  tool: "propose",
  mode: "execute",
  args: { title: "omp-ci-debt-repair/…" },
  inner: { planFilePath: "local://omp-ci-debt-repair-plan.md", title, planExists }
}

TUI (event-controller.ts ~1197–1217): writeDeviceDispatchhandlePlanApproval.
Dashboard: WriteToolRenderer prints path + syntax-highlighted content. No details.xdev read anywhere under packages/client.

Expected

Surface TUI Dashboard today Dashboard should
write xd://propose Propose status + plan-approval popup Write card of slug text Plan-approval card (title, local://…-plan.md, Approve/Reject)
write xd://resolve / xd://reject Inverse Accept/Discard banner Write card of reason text Same Accept/Discard banner
Other write xd://<device> Delegates to mounted renderer Write card of JSON/text payload Unwrap details.xdev.tool and render that tool
eval / browser / task / hub / todo / lsp / ast_edit / ast_grep / grep / glob / web_search / debug / github Dedicated denser + full bodies Generic JSON dump (or Write if xd-mounted) Dedicated cards matching TUI density

Grounded cause

OMP 17 removed the hidden resolve tool. Staged actions + plan submit ride plain-text writes to xd://resolve / xd://reject / xd://propose. Write results carry details.xdev (WriteToolDetails.xdev). TUI write renderer delegates; dashboard never unwraps.

Dashboard lookup is name-only:

  • getToolRenderer(toolName) in packages/client/src/components/tool-renderers/registry.ts — mapped: read, edit, write, bash, Agent, ask/ask_user, ctx_*. Else Generic.
  • getSummary / toolIcons in packages/client/src/lib/tool-summary.ts — same small set + grep/glob/find/ls/git/kb_search. Unknown → bare tool name.
  • toolCallPrefKey buckets every unmapped name as generic (hidable).
  • isInputNeededTool is only ask / ask_user. Plan approval is not input-needed, so bursts can collapse it.
  • lineDelta.ts already drops xd:// paths from file summaries (Exclude xd:// tool calls from per-turn file change summaries #56) — render path was never updated.

ProposeDialog.tsx is OpenSpec /skill:openspec-propose, not this device.

Zero matches in dashboard source for xd://propose, writeDeviceDispatch, handlePlanApproval, planFilePath, details.xdev.

Catalog (TUI renderer vs dashboard)

TUI toolRenderers (@oh-my-pi/pi-coding-agent/src/tools/renderers.ts):

TUI key Dashboard
ask AskUserToolRenderer
bash BashToolRenderer
edit / apply_patch EditToolRenderer (no staged-preview / ⟨proposed⟩ badge)
write WriteToolRenderer (no xd unwrap)
read ReadToolRenderer
resolve / reject missing (arrive as write)
eval (+ js/python/notebook aliases) Generic
browser / puppeteer Generic
task Generic (Agent renderer is a different tool)
hub / irc / job / await / poll Generic
todo Generic
lsp Generic
ast_edit / ast_grep Generic
grep / glob / find summary one-liner only; body Generic
web_search / fetch Generic
debug Generic
github Generic
goal / think / retain / recall / reflect Generic
inspect_image / generate_image / computer Generic
vibe_* Generic
ctx_* CtxToolRenderer (dashboard-only; good)

OMP collab-web already ships React views for most of the TUI set (export/html/tool-views.generated.js). Dashboard does not reuse them.

Suggested fix (do not implement here)

  1. P0 — unwrap write + details.xdev. If args.path is xd://<name> or toolDetails.xdev is set, look up renderer by device name (not "write"). Header/summary/icon follow the device.
  2. P0 — plan approval. xdev.tool === "propose" + inner.planFilePath → interactive card (title, plan path, Approve/Reject). Treat as input-needed so bursts cannot collapse it. Wire a respond path equivalent to TUI handlePlanApproval.
  3. P0 — resolve/reject. Dedicated Accept/Discard banner; do not syntax-highlight the reason as a file.
  4. P1 — high-frequency TUI tools. Dedicated cards for eval, browser, task, hub, todo, lsp, ast_edit/ast_grep, grep/glob, web_search, debug, github. Prefer adapting OMP collab-web views over a second visual language.
  5. P1 — staged edit preview. Surface PREVIEW_PENDING_NOTICE / ⟨proposed⟩ so a staged ast_edit/edit does not look applied.
  6. Keep Exclude xd:// tool calls from per-turn file change summaries #56: xd:// writes stay out of per-turn file change summaries.

Acceptance

  • Plan-mode write xd://propose with details.xdev.inner.planExists opens a dashboard approval card; Approve/Reject unblocks the agent the same way TUI does.
  • write xd://resolve / xd://reject render as Accept/Discard, not Write.
  • write xd://mcp__… (and other mounted devices) render as that tool, not a file write of the JSON args.
  • eval / browser / task / hub / todo cards are readable without expanding raw JSON.
  • ask / ask_user stay non-collapsible (bug: "Ask" tool UI broken — buttons truncated, unclickable, tool collapsed, context hidden #95).
  • Real filesystem writes still use WriteToolRenderer.

Pointers

  • TUI dispatch: dev-tools/omp-tool-ui-collapse/overlay/files/src/modes/controllers/event-controller.ts ~1197
  • TUI write unwrap: @oh-my-pi/pi-coding-agent/src/tools/write.ts writeToolRenderer + WriteToolDetails.xdev
  • Devices: @oh-my-pi/pi-coding-agent/src/tools/resolve.ts (PROPOSE_DEVICE_PATH, writeDeviceDispatch, isProposeToolCall)
  • Plan mode: interactive-mode.ts #enterPlanMode (write required so agent can submit)
  • Dashboard: packages/client/src/components/tool-renderers/{registry,WriteToolRenderer,GenericToolRenderer}.tsx, packages/client/src/lib/tool-summary.ts, packages/shared/src/{display-prefs,input-needed-tools}.ts

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions