PAP-9846 · Triage workbench
Jump to a screen
PAP-9846 · Wireframes · Phase 1

Paperclip Triage — workbench wireframes

Low-fi black-and-white wireframes for the eight surfaces in the approved triage plan. The centerpiece is a two-column item workbench: assistant chat on the center/left, item document and properties on the right. Direct edits and chat-assisted edits target the same item content. Reflection sits over the workbench whenever a transition requires it.

All component references in red callouts are real Paperclip primitives (file:line in the reuse key). Where the spec asks for something new — variable palette, diff renderer — it's flagged as a system change.

8 screens Desktop + mobile Lo-fi · monochrome Click any wireframe to zoom From PAP-9815 plan + PAP-9845 contract
Map

Flow

The main triage loop is the top row (solid arrows). Configuration paths are dashed. The item workbench is the only screen with a bold border — it's the centerpiece. Ingest API is the only entry point for items in v1; there are no source connectors.

flow.svg1280×720
Triage workbench flow diagram
Component reuse

What we borrow from Paperclip core

The plugin SDK and Paperclip core already ship most of what the workbench needs. New surfaces (chat composer pinned to an item, guidance diff renderer, transition-action variable palette) are explicit additions and are called out per-screen.

MarkdownEditorItem content + guidance docs — packages/plugins/sdk/src/ui/components.ts:516
MarkdownBlockRead-only guidance + chat tool output — components.ts:509
AssigneePickerDefault assignee + action template field — components.ts:586
ProjectPickerQueue default project + action template field — components.ts:591
IssuesListLinked work issues column on item list — components.ts:581
IssueChatThreadLean assistant chat surface (hide tool-result toolbar, keep tool-call/result bubbles compact) — ui/src/components/IssueChatThread.tsx:1
usePluginData / usePluginAction / usePluginStreamAll queue/item/guidance reads + chat send — packages/plugins/sdk/src/ui/hooks.ts:43
useHostNavigationOpen linked work issue in host without leaving plugin — hooks.ts:139
LLM Wiki plugin shapeSidebar entry + page route + route sidebar contributions — packages/plugins/plugin-llm-wiki/src/manifest.ts:574 and src/ui/app.tsx:1589 / 2405
shadcn primitives (Button, Card, Tabs, Dialog, Sheet, Badge, Avatar, DropdownMenu, Popover, ScrollArea)All structural chrome — ui/src/components/ui/
Step 1 · entry

1.Queue list

Plugin home. Route sidebar shows queues with state counts and plugin-level links (settings, reconcile, managed agent). Main area is a queue card grid: each card shows state counts as chips, the configured assistant agent, action summary, and an "open workbench" CTA. The "+ create" tile reminds the reader that an unknown queueKey from the ingest API auto-creates the queue with default workflow + guidance.md.

queue-list.svg1280×800 · desktop
Queue list desktop wireframe
mobile375×812
Queue list mobile wireframe

Annotations

  • 1 — Route sidebar mirrors the LLM Wiki routeSidebar slot. Queues appear under QUEUES with state-count badges; plugin links sit under PLUGIN.
  • 2 — State count chips are Badge primitives with the active state filled. Counts read live via usePluginData("queues:listWithCounts").
  • 3 — A dashed create-queue tile educates users that the ingest API creates queues by default — no need to come here first.
  • 4 — Archived queues stay listed but de-emphasised; unarchive without navigation.
  • Mobile — Cards collapse to a single vertical stack; chip row becomes one compact summary line. Bottom tab nav (Queues · Chats · Settings) replaces the sidebar.
Component reuse: Card, Badge, Button, Input from ui/src/components/ui/; route sidebar pattern from plugin-llm-wiki.
Why this shape: the user's first question is "what is there to triage?". Counts by state are the single most actionable summary. We resist a kanban here — items inside one queue are the workbench's job, not the list's.
Step 2 · pick

2.Item list

Items in one queue, grouped by workflow state. The "Start triage (next New)" CTA opens the oldest New item directly in the workbench — keeping the loop friction-free. Each row surfaces title, opaque properties summary, itemKey, age, and any linked work issue.

item-list.svg1280×800 · desktop
Item list desktop wireframe
mobile375×812
Item list mobile wireframe

Annotations

  • 1 — State tabs are driven by the queue workflow definition. Counts live-update from the worker.
  • 2 — Row is a list-row primitive; clicking opens the item workbench. Properties shown as a free-form, opaque summary (sourceKind, priority, stats).
  • 3 — Primary CTA always opens the next actionable item. Keeps the triage loop fast.
  • 4 — Linked work issue, when present, links into Paperclip's regular issue view via useHostNavigation.
  • Mobile — Rows become full-width cards; state tabs scroll horizontally. The "open #142 in workbench" CTA is sticky at the bottom.
Component reuse: shadcn Tabs, Badge, Table-style list row; IssuesList for the linked-work-issue column on the right.
Why a table on desktop, cards on mobile: properties matter — a table puts itemKey, properties, and age in one scan line. On mobile, cards keep titles legible without horizontal scroll.
Step 3 · the centerpiece

3.Item workbench — two columns, locked

The approved two-column work area: assistant chat on the center/left, item document and properties on the right. Both columns target the same item content — edits made directly in the markdown editor and edits made through a chat tool call are equivalent. Allowed transitions sit in the workbench bar; the route sidebar holds queue/item nav so the two columns stay the mental model.

item-workbench.svg1280×800 · desktop
Item workbench desktop wireframe
mobile375×812
Item workbench mobile wireframe

Annotations

  • 1 · chat column — IssueChatThread, rendered against the queue's hidden chat issue, with assistant tool-call bubbles slimmed down (no comment toolbar, no reactions). Chat history dropdown + "new chat" pin to the column header.
  • 2 · document column — Title input + MarkdownEditor + properties editor + linked-work-issue card. This is the "edit directly" path.
  • 3 · pinned item card — Always visible in the chat. Pins the current item into assistant context (queue, item, state, allowed transitions, guidance files) — see composer footer for the full context strip.
  • 4 — Title is editable inline.
  • 5 · chat-assisted edit — Same content, different path. The assistant's update_item_content tool call produces a small diff card inside the chat bubble; the right-column editor updates in place. Saves count for reflection just like manual edits.
  • 6 · free-form properties — Key/value editor. No schema enforcement in v1; the contract is explicit about that.
  • 7 · composer — Single-line composer with shift+enter for multi-line. Footer surfaces the full assistant context so the user trusts the agent's view of the world.
  • 8 · linked work issue card — Dashed when none exists, with a preview of what the configured transition action will do.
  • 9 · transition controls — Allowed transitions only, rendered as Buttons in the workbench bar. Disabled with a tooltip when reflection is required and not yet resolved.
  • Mobile — The two columns become a top tab switch (Chat / Document). State strip + transitions become a sticky bottom action bar. The pinned-item card stays visible above the chat. Sheet/drawer (Sheet) holds route navigation.
Component reuse: IssueChatThread (slim variant), MarkdownEditor, Tabs, Button, Sheet for mobile drawer, Badge for state pill, ScrollArea for both columns.
Why a fixed two-column split, not collapsible: the mental model the plan locks in is "chat on the center/left, document on the right". Collapse the right column and we lose the "draft together, see the artifact live" experience the user described. Mobile is the one place we tab — there's no room — and we pay the cost there only.
System change requested: a slim variant of IssueChatThread that suppresses comment toolbar / reactions and renders tool-call bubbles compactly. Proposed as a prop on the existing component, not a fork.
Step 4 · the learning loop

4.Reflection diff

Sits over the workbench when a transition requires reflection (default: new.approve and new.reject). The assistant compares the original item, edits, chat, and current guidance, then proposes a diff to one or more guidance documents. The user accepts, rejects, edits inline, or asks for a revision. Acceptance bumps the doc revision and unblocks the transition.

reflection-diff.svg1280×800 · desktop
Reflection diff desktop wireframe
mobile375×812
Reflection diff mobile wireframe

Annotations

  • 1 · summary — The assistant's one-line take on what changed. Citable.
  • 2 · doc selector — Folder-style list of guidance docs with change counts; "+ propose new file" supports growth beyond guidance.md.
  • 3 · diff body — Unified diff in markdown. Inline edit converts the panel into a MarkdownEditor over the proposed body.
  • 4 · revise / reject / edit — All three soft paths. Revise sends a chat turn ("revise because…"); reject keeps the proposal in history for audit.
  • 5 · accept — Creates a new guidance revision and unblocks the transition. Status note explains the linkage so the user understands why this is required.
  • Mobile — Reflection becomes a full-screen sheet. Doc selector becomes scrollable tab chips. Actions sit in a sticky bottom bar with an "Edit ›" link to drop into the editor on a separate screen.
Component reuse: Dialog for the desktop overlay; Sheet for mobile; MarkdownBlock + custom diff renderer for the body.
System change requested: a small markdown-diff renderer (added/removed line markers, hunk grouping) — does not exist in core today. Lives inside the plugin until two callers want it.
Why blocking-by-default for reflection-required transitions: the contract makes requiresReflection a hard gate. Surfacing this as an overlay (not a separate screen) keeps the user in their item's context.
Step 5 · queue memory

5.Guidance editor

Queue guidance lives as a folder of plugin documents, not one oversized blob. Every queue starts with guidance.md; more files (style.md, examples.md, rubric.md) can be added as the queue's voice matures. Pending reflection proposals surface in the file tree so the user can see "this doc has open work" without jumping through the chat.

guidance-editor.svg1280×800 · desktop
Guidance editor desktop wireframe
mobile375×812
Guidance editor mobile wireframe

Annotations

  • 1 · file tree — Documents listed with revision tag and one-line purpose. Active doc highlighted. "+ new document" is permissive (path-like keys per the plan).
  • 2 · editor — Same MarkdownEditor the workbench uses. History link opens the revision drawer.
  • 3 · header — Last update attribution, revision count, save shortcut.
  • 4 · revision history strip — Recent revisions inline. Each entry is clickable and notes whether the revision came from an accepted reflection (with item link) or a manual edit.
  • Mobile — File list becomes horizontal scroll chips. Pending-proposal banner appears at the top of the active doc. Add-doc + save are sticky at the bottom.
Component reuse: MarkdownEditor, Tabs (mobile chips), Sheet for revision history drawer, Badge for proposal counts.
Why a folder, not one file: the user explicitly called out that "agents.md" patterns outgrow single files. Putting style.md/examples.md/rubric.md on the same screen normalises the practice early so reflection proposals can target the right doc without the user thinking about it.
Step 6 · queue rules

6.Workflow editor

Per the contract, v1 ships a small internal validator — no state-machine library, no drag-and-drop builder. The editor is two tables (states, transitions) plus a read-only graph preview rendered from the records. This keeps invariants honest (terminal states have no outgoing transitions, every transition references real states) without leaking visual-editor complexity.

workflow-editor.svg1280×800 · desktop
Workflow editor desktop wireframe
mobile375×812
Workflow editor mobile wireframe

Annotations

  • 1 · preview — Auto-generated from the records below. Terminal state has the thicker border (used as a consistent terminal marker across all screens).
  • 2 · states table — All fields from the contract: stateKey, label, terminal, visibility, sort order.
  • 3 · transitions table — From/to, label, reflection required, attached action template. Inline row actions edit per-row; bulk add via "+ Add transition".
  • 4 · action template chip — Tappable pill that opens the transition action editor (next screen) with the right transition pre-selected.
  • Mobile — Preview collapses to an accordion. States and transitions become stacked cards. Add buttons sit below the list — no FAB.
Component reuse: shadcn Table, Badge, Button, Collapsible for the mobile preview.
Why no drag-and-drop builder: the contract explicitly chose a small internal validator over a state-machine library, and the plan flags YAML editors / visual builders as later work. A table with a generated preview is the smallest thing that makes invariants visible without inviting users to build state spaghetti.
Step 7 · hand off to Paperclip

7.Transition action template

v1's only allowed action: create_or_update_issue. The template is a constrained form — string interpolation only, fields locked to the contract's allowlist (title, description, comment, projectId, goalId, assigneeAgentId/UserId, priority, status). The variable palette + live preview against a real item make the template legible without inviting users to drop in arbitrary expressions.

transition-action.svg1280×800 · desktop
Transition action template desktop wireframe
mobile375×812
Transition action template mobile wireframe

Annotations

  • 1 · action type chip — Locked to create_or_update_issue in v1. Surfaced as a chip so the constraint is visible, not hidden in a disabled dropdown.
  • 2 · mode segmented control — Three contract-locked modes; the body description below explains the selected mode in plain language.
  • 3 · transitions side rail — All transitions for this queue. Each shows whether it has an action so the user can tour them.
  • 4 · variable palette — Click-to-insert tokens from the four contract variable roots (queue.*, item.*, transition.*, actor.*). No JavaScript, no helpers — the palette is the entire surface area.
  • 5 · live preview — Renders the template against the most recent New item so the user can spot a missing variable or weird formatting before saving. Templating errors fail closed before any side effect runs.
  • Status restriction — The status dropdown only contains backlog / todo / in_review, matching the contract's allowlist. Disabled options aren't shown.
  • Mobile — Side rail moves into a dropdown above the form. Variable palette becomes a popover triggered by "Insert variable…". Preview lives in a compact card at the bottom.
Component reuse: Input, Textarea, Select, Popover, Tabs, ProjectPicker, AssigneePicker.
System change requested: a small string-interpolation preview helper (renders {{var}} against a context object, flags missing keys). Lives in the plugin; trivial to lift if a second caller appears.
Why a constrained form, not a code editor: the contract explicitly bans dynamic evaluation. A form (not a YAML pane) keeps users inside the allowlist and lets the preview catch typos before runtime audit rows surface them as failures.
Step 8 · queue identity

8.Queue settings

Per-queue identity, defaults, and lifecycle. queueKey is immutable (it's the ingest API contract). Defaults wire the assistant agent and the project transition actions use. The strict-ingest toggle controls the contract's requireExistingQueue behaviour for this queue. Other concerns (workflow, transition actions, guidance, chat history, danger zone) are tab destinations to keep this screen scannable.

queue-settings.svg1280×800 · desktop
Queue settings desktop wireframe
mobile375×812
Queue settings mobile wireframe

Annotations

  • 1 · immutable queueKey — Shown disabled with explicit "immutable" caption. Avoids the trap of breaking the external ingest API contract by renaming.
  • 2 · default assistant agent — Picker. Default is the managed Triage Assistant; teams can swap in a specialised agent per queue (per the plan's "executive assistant learning agent" framing).
  • 3 · default state — Constrained to the queue's workflow states.
  • 4 · ingest fallback toggle — Maps directly to requireExistingQueue in the ingest API. "Auto-create queue on unknown key" reads better to a human than the API field name.
  • Sticky save bar — Discard / Save with unsaved-changes indicator. Save bar pattern echoes the rest of the Paperclip UI to feel native, not plugin-y.
  • Mobile — Same fields, single column. Tabs scroll horizontally. Danger zone is its own card below the main form.
Component reuse: Tabs, Input, Textarea, Select, Switch, AssigneePicker, ProjectPicker, the standard Paperclip sticky-save-bar pattern.
Why settings sit alongside workflow / actions tabs (not buried in a separate page): creating a new queue is a configuration burst — the user will likely set defaults, define states, and attach an action in one sitting. Tabs keep all of it within one URL.
For reviewer

Open questions for CTO/product

  • Q1 · Chat history surface — Should the queue's chat history live inside the route sidebar (compact list, click to re-pin items) or inside a dedicated "Chat history" tab on the queue settings? Wireframes lean toward a "Chat history" tab plus a "+ new chat" / "history ▾" pair in the chat column header. Confirm.
  • Q2 · Reflection scope — On a transition like new.approve, the assistant may want to propose changes across multiple guidance docs (e.g. guidance.md + examples.md). The reflection screen supports that today via the file selector. Should we ship that in v1 or restrict v1 to single-doc proposals for simplicity?
  • Q3 · "Edit before accept" — Goes from the diff view into a full MarkdownEditor over the proposed body. Open: do we preserve the unaccepted diff badge once edited, or treat the edited version as a fresh manual edit (no longer "from the assistant")? Wireframes currently imply the latter.
  • Q4 · Mobile two-column posture — Mobile tabs Chat / Document instead of stacking. Stacking would preserve the "see both at once" intent but force scrolling. Confirm tabbing on phones is acceptable given that the desktop two-column is the locked invariant.
  • Q5 · Transition action preview "sample item" — Wireframes show the preview pinned to the most recent New item. Alternative: let the user pick which item to preview against. Adds power; complicates first-use. Confirm we ship the default-only version in v1.
  • Q6 · Status restriction labelling — The contract bans in_progress/done/blocked/cancelled as template statuses. Show them disabled (educational) or omit them (cleaner)? Wireframes currently omit.

Questions are also posted as a request_confirmation interaction on PAP-9846 so acceptance can wake the right agent.