Run a Saved Legal Task from a Review Table row

✅ merged · #5 · zgbrenner/gary ← zgbrenner/gary · opened 7d ago by zgbrenner · merged 7d ago by zgbrenner · self · +799-9 across 13 files · ↗ on GitHub

From the PR description

Summary

Makes the Suggested Saved Legal Task column in a Review Table actionable. When Gary suggests a recognized task for a document, a lawyer can launch that task in the assistant - prefilled with the row's context, the task selected, and the document attached. Nothing auto-runs; the lawyer reviews and sends.

Where the action appears

In the cell detail panel (TRSidePanel). A lawyer clicks the Suggested Saved Legal Task cell for a row → the panel opens → a Run Suggested Task button appears.

The button shows only when:

  • the open cell is the Suggested Saved Legal Task column, and
  • that cell has finished generating (status === "done"), and
  • its value resolves to one of the eight recognized tasks.

Rows with None, Unknown, blank, or an unrecognized value show no button.

Task-name mapping

suggestedTask.ts maps the eight recognized task names → built-in Saved Legal Task ids (Contract Review → builtin-contract-review, Discovery Summary → builtin-discovery-summary-assistant, etc.). Matching tolerates whitespace, case, tag-pill brackets ([[Contract Review]]), and trailing punctuation - but is never fuzzy. After normalization the value must exactly equal a canonical name, otherwise it resolves to null. Partial values like "Contract" or "Litigation" never resolve. A test asserts each mapped id is a real assistant-type built-in workflow.

How the task launches - prefill, not auto-run

On confirm, Gary:

  1. creates a chat (in the review's matter if it has one, else standalone),
  2. sets a new newChatDraft channel on ChatHistoryContext carrying { content, workflow, documents },
  3. opens the assistant chat.

ChatInput seeds its initial state from the draft - the prompt text, the task as a workflow chip, and the document as an attachment chip. The lawyer reviews/edits and clicks send manually. The existing newChatMessages auto-send path is not used. ChatView was taught to render an empty-with-draft chat (instead of the loading skeleton). The confirmation modal (RunSuggestedTaskModal) is the explicit user gate: "Run Saved Legal Task?" with a prompt preview and Open in Assistant / Cancel.

Document attachment - implemented

The row already corresponds to a MikeDocument. The document is attached through the existing chat file mechanism (documents on the draft → ChatInput attachment chip → files on send). The document_id rides in the attachment, never in the visible prompt text.

Safety guardrails

The prefilled prompt (built by buildRowContextPrompt) contains:

  • "Treat extracted values as draft and unverified. Use the uploaded document content where available. Do not invent facts, dates, legal authorities, deadlines, or parties. Flag uncertainty."
  • an Instructions block: "Verify against the underlying document. Do not invent missing facts, legal authorities, deadlines, or parties."
  • the matter name and extracted fields (Document Type, Date, People / Parties, Short Summary, Key Issues, Needs Attorney Review), with missing values rendered as Unknown.
  • no raw internal identifiers - document id, review id, cell id, column index never appear in the text.

The modal and the side-panel block both restate that the row is draft context to review before sending.

Files changed (13)

  • frontend/src/app/components/tabular/suggestedTask.ts (new) - mapping + row-context prompt builder.
  • frontend/src/app/components/tabular/suggestedTask.test.ts (new) - 10 focused tests.
  • frontend/src/app/components/tabular/RunSuggestedTaskModal.tsx (new) - confirmation modal.
  • frontend/src/app/components/tabular/TRSidePanel.tsx - optional "Run Suggested Task" action block.
  • frontend/src/app/components/tabular/TabularReviewView.tsx - resolves the row's task, builds the prompt, owns the modal + launch flow.
  • frontend/src/app/components/shared/types.ts - NewChatDraft type.
  • frontend/src/app/contexts/ChatHistoryContext.tsx - newChatDraft / setNewChatDraft.
  • frontend/src/app/components/assistant/ChatInput.tsx - initialDraft prop seeds input/workflow/attachments.
  • frontend/src/app/components/assistant/ChatView.tsx - forwards initialDraft; renders empty-with-draft state.
  • frontend/src/app/(pages)/assistant/chat/[id]/page.tsx and .../projects/[id]/assistant/chat/[chatId]/page.tsx - capture + pass the draft; skip the empty-chat redirect for a draft chat.
  • docs/US_LAWYER_SETUP_GUIDE.md, docs/US_TERMINOLOGY_MAP.md.

Tests

suggestedTask.test.ts (10 tests, all pass): eight-task mapping; every mapped id is a real assistant built-in; match tolerance (whitespace/case/brackets/punctuation); the no-fuzzy-match guarantee; blank/Unknown/None/null → null; prompt names the task + matter + document; prompt carries the attorney-review safety language; missing fields render Unknown; no raw internal identifiers in the prompt; no legacy Workflow Template / Tabular Review wording. Existing test suites still pass.

Validation

  • Backend bun run build - clean.
  • Frontend bun run build - TypeScript compiles successfully (Compiled successfully, Finished TypeScript). The static prerender of /account/models fails with the documented Missing NEXT_PUBLIC_SUPABASE_URL codespace error (no Supabase env vars here) - unrelated to this change.
  • Frontend bun run lint - 112 total issues vs 113 on the base branch (one fewer; no new errors or warnings introduced).

Notes / deferred

  • The action lives in the cell detail panel rather than as an always-visible row button - this keeps TRTable generic (no row-action framework, per the brief). Surfacing it inline on the row is a possible follow-up.
  • Confirming creates the chat up front; if a lawyer opens the draft and never sends, an empty "Untitled" chat remains in history (it can be deleted). Mirrors the existing workflow-launch pattern.

Recommended next PR

  • Surface "Run Suggested Task" directly on the table row for one-click discovery.
  • Let the lawyer pick a different task than the suggested one before launching.

Test plan

  • Open a Matter Document Review table, generate it, click a Suggested Saved Legal Task cell with a recognized value → Run Suggested Task appears.
  • Click it → confirmation modal shows the prompt preview → Open in Assistant.
  • Assistant opens with the prompt prefilled, the task chip set, and the document attached; nothing is sent until you click send.
  • A cell with None/Unknown/blank shows no button.
  • Works for both a matter-scoped review and a standalone review.

https://claude.ai/code/session_01LNzU9cGoR4SsYXon8H7aJZ


Generated by Claude Code

Our analysis

Make suggested legal task in Review Table launch the assistant — read the full analysis →

Think the analysis missed something the PR description covers?

Commits in this PR (1)

SHA Subject Author Date
b01092b7 feat: run a Saved Legal Task from a Review Table row Claude 2026-05-20 ↗ GitHub
commit body
Make the "Suggested Saved Legal Task" column actionable. When Gary
suggests a recognized task for a document, a lawyer can launch that
task in the assistant prefilled with the row's context.

- suggestedTask.ts: maps the eight recognized task names to built-in
  Saved Legal Task ids. Matching tolerates whitespace, case, tag
  brackets, and trailing punctuation but is never fuzzy - an
  unrecognized value resolves to null rather than guessing. Also
  builds the row-context prompt (task name, matter, document name,
  extracted fields, and attorney-review safety language).
- RunSuggestedTaskModal.tsx: a simple "Run Saved Legal Task?"
  confirmation with a prompt preview and Open in Assistant / Cancel.
- TRSidePanel: shows a "Run Suggested Task" action - only on the
  Suggested Saved Legal Task column's cell, and only when the value
  resolves to a recognized task and the cell has finished generating.
- TabularReviewView: resolves the row's suggested task, builds the
  row-context prompt from the row's other cells, and on confirm
  creates a chat, prefills an assistant draft, and opens it.
- Prefill, not auto-run: a new newChatDraft channel on
  ChatHistoryContext carries a draft (content + workflow + attached
  document) that ChatInput seeds its initial state from. The lawyer
  reviews and sends manually - nothing is auto-submitted. ChatView
  renders an empty-with-draft chat instead of the loading skeleton.
- The row's document is attached via the existing chat file
  mechanism; the document_id rides in the attachment, never in the
  visible prompt text. No raw internal ids appear in the prompt.
- Safety: the prompt instructs Gary to treat the row as draft and
  unverified, use the uploaded document, not invent facts / dates /
  legal authorities / deadlines / parties, and flag uncertainty.
- Docs: add "Running a Saved Legal Task from a Review Table" to the
  U.S. lawyer guide; add a terminology-map entry.
- Tests: suggestedTask.test.ts covers the eight-task mapping (and
  that each id is a real assistant built-in), match tolerance, the
  no-fuzzy-match guarantee, blank/Unknown/None handling, the prompt's
  attorney-review language, Unknown fallbacks, and the absence of raw
  internal ids and legacy terminology.

Capture this PR into my fork

Download a Markdown prompt that tells Claude how to port every commit in this PR into your working tree. Run it via claude -p < capture-pull-5.md from inside the repo you want the changes in.

⬇ Download capture-pull-5.md