Tabular column management: hide, reprocess per-column, delete with confirm
nwhitehouse added the column-level actions that become necessary once a tabular review has more than a handful of columns: per-column reprocess, delete with a confirmation modal that names the column and counts cells, and per-device localStorage-backed column visibility. Three commits, with two of them relocating the manage-columns UI after user feedback.
POST /tabular-review/:reviewId/reprocess-column wipes the target column's cells back to pending and creates a new tabular_jobs run via the existing worker pool. The worker's "skip done cells" filter naturally picks up the freshly wiped rows without any new worker logic. The endpoint returns 409 if a job is already in flight on the review, which prevents the worker pool from racing against cells being wiped mid-run.
DELETE /tabular-review/:reviewId/columns/:columnIndex removes the column from columns_config and deletes its tabular_cells rows. Hard delete, no undo. The response includes the updated columns_config so the frontend can rerender without a follow-up fetch. Both endpoints reuse ensureReviewAccess and the existing document-filter helpers.
On the frontend, hidden column state lives in localStorage keyed by (review, device). This is the right default for an ephemeral view setting - no server round-trip, resets cleanly if the user switches devices. The ColumnVisibilityMenu component (sliders icon, Show all / Hide all bulk actions, per-column eye toggle + format pill + trash icon) landed in the table header in the first commit, then moved to the main toolbar in the second after user feedback that the header was the wrong place. Two-commit thrash, but the final position makes sense and matches the workflow-toolbar pattern elsewhere in the UI.
One dependency: this feature can't land without the bug-007 job/worker infrastructure first. The reprocess endpoint creates a job via createGenerateJob(); without the worker pool running, the wiped cells just sit there.
Spotted something wrong? Or know the PR text has fresher detail than the writeup above?