Tabular review cells get version history and a multi-model comparison panel

Three commits turn tabular-review cells from overwrite-only into a versioned artefact that records which model and prompt produced each result. A history modal lets you compare prior outputs side by side - and run the same cell against a different model without leaving the UI.

contract-reviewdiscovery

ce6e9c2 adds migration 001_tabular_cell_versions.sql. Four new columns on tabular_cells - model, system_prompt, column_prompt, updated_at - capture what produced the current value. A new tabular_cell_versions table archives prior state before each overwrite, with the same four provenance fields plus content, status, and citations. The generate endpoint gains a document_ids parameter to force-rerun a subset of rows, surfaced as a "Run selected (N)" header button. GET /tabular-review/:id/cells/:cellId/versions returns the history.

Existing cells aren't backfilled - model and system_prompt will be null until the next overwrite. The migration is additive-only, so deploying without a backfill is safe; just expect gaps in history for older cells.

c2471472 adds CellHistoryModal.tsx (~210 LOC), opened from a history icon on each cell. The modal has a three-column layout: a version list on the left (showing model name and timestamp for each archived entry plus the current state), and two panels on the right showing the selected version's summary and the system/column prompts that produced it.

1f3d4cb makes the modal actionable. A row of "Run on..." pills - one per model in the MODELS registry (Claude, Gemini, Grok at the time of writing) - calls /regenerate-cell with an explicit model override in the request body. The backend change is two lines: read model from the request, fall back to tabular_model if absent. Each run archives the current cell first, so clicking through multiple models builds a history you can compare without losing prior results.

So what Solid pull for any team running tabular reviews with multiple models or iterating on prompts. The data model is minimal - one table, four columns - and backwards-compatible. The model-override path on `/regenerate-cell` is clean enough to pull in isolation if you don't want the full UI. Remember: the migration must run before deploy, and cells that existed before the migration will have null provenance until next overwrite.

View this fork on GitHub →

Spotted something wrong? Or know the PR text has fresher detail than the writeup above?

Commits in this thread

3 commits from Custos/legalos, oldest first. Source extracted verbatim from the harvested git log.

SHA Subject Author Date
ce6e9c27 Tabular: run on selected rows + version history with model & prompts Custos 2026-05-04 ↗ GitHub
commit body
- New tabular_cell_versions table archives prior cell state (content, model,
  system_prompt, column_prompt) on every overwrite.
- tabular_cells gains model/system_prompt/column_prompt/updated_at columns
  capturing what produced the current content.
- POST /tabular-review/:id/generate accepts optional document_ids; when
  provided, those rows force-rerun and prior values are archived.
- POST /tabular-review/:id/regenerate-cell archives prior content first.
- New GET /tabular-review/:id/cells/:cellId/versions returns history.
- Frontend: 'Run selected (N)' button appears in the header when rows are
  checked, posts document_ids to the streaming endpoint.
- .env.example: add XAI_API_KEY and R2_REGION.
c2471472 Tabular: cell history modal - view archived versions, models, prompts Custos 2026-05-04 ↗ GitHub
1f3d4cb9 Multi-model comparison from cell history modal Custos 2026-05-04 ↗ GitHub
commit body
- /regenerate-cell now accepts an optional model param that overrides the
  user's tabular_model for that one run; the new content is saved with
  that model id, prior content archived as usual.
- regenerateTabularCell(reviewId, docId, colIdx, model?) on the client.
- Cell history modal: a 'Run on ...' row of model pills in the header lets
  you re-run the same cell against any other supported model (Claude,
  Gemini, Grok). Each run appears as a new history entry, so you can
  click between versions to compare. The current model is disabled.

Capture this thread into my fork

Download a single Markdown prompt that tells Claude how to port every commit above into your working tree — adapting paths and structure to match your repo. Run it via claude -p < capture-thread-47.md from inside the repo you want the changes in.

⬇ Download capture-thread-47.md