From 9d7b76339bf4f8ecfac41dd96b0f078d136f3bf0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20F=C3=B6rtsch?= Date: Wed, 15 Apr 2026 06:43:52 +0200 Subject: [PATCH] spec: drop verify/checkmarks, merge jobs view into item details Co-Authored-By: Claude Opus 4.6 (1M context) --- ...-04-15-drop-verify-and-jobs-page-design.md | 114 ++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 docs/superpowers/specs/2026-04-15-drop-verify-and-jobs-page-design.md diff --git a/docs/superpowers/specs/2026-04-15-drop-verify-and-jobs-page-design.md b/docs/superpowers/specs/2026-04-15-drop-verify-and-jobs-page-design.md new file mode 100644 index 0000000..3eda245 --- /dev/null +++ b/docs/superpowers/specs/2026-04-15-drop-verify-and-jobs-page-design.md @@ -0,0 +1,114 @@ +# Drop verify/checkmarks, merge jobs view into item details + +Date: 2026-04-15 + +## Summary + +Remove the post-job Jellyfin verification path and its associated `verified` flag entirely. Delete the standalone `/execute` jobs page. Surface per-item job info (status, command, log, run/cancel actions) on the item details page instead. Batch queue controls (Run all / Clear) move into the Pipeline column headers. + +Rescan becomes the sole source of truth for "is this file still done?" — if a file drifts off-noop, the next scan flips its plan back to pending and the card reappears in Review. + +## Motivation + +The verify feature tried to promote done cards from ✓ to ✓✓ after ffprobe/Jellyfin cross-checked the on-disk file. In practice the Jellyfin refresh path is fragile (times out silently), the ✓/✓✓ distinction adds UI noise without user value, and rescan already catches drift. The separate Jobs page duplicates info that belongs on the item details page and forces users to jump between views to answer "what happened to this file?". + +## Backend changes + +### Remove verification path +- Delete `handOffToJellyfin()` in `server/api/execute.ts` (≈lines 38–98) and both callers at `:492` and `:609`. Post-job handling is now just the existing `jobs.status` update. +- Delete `emitPlanUpdate()` and the `plan_update` SSE event emission. +- Delete `POST /api/execute/verify-unverified` (≈lines 357–389). + +### Drop `verified` column +- Add idempotent migration in `server/db/index.ts` following the existing try/catch `alter()` pattern: + ```ts + alter("ALTER TABLE review_plans DROP COLUMN verified"); + ``` + Supported on Bun's bundled SQLite (≥3.35). +- Remove `verified` from `server/db/schema.ts:77` in the `review_plans` CREATE TABLE. +- In `server/services/rescan.ts`, remove `verified` from the INSERT column list and the `verified = CASE ...` branch in the ON CONFLICT DO UPDATE clause. +- In `server/api/review.ts`: + - Remove `rp.verified` from the pipeline SELECT (≈line 330). + - Remove `verified = 0` from the unapprove UPDATE (≈line 773). + +### Remove jobs-list endpoint +- Delete `GET /api/execute` (the filtered list used only by the Execute page). +- Keep: `/start`, `/clear`, `/clear-completed`, `/job/:id/run`, `/job/:id/cancel`, `/stop`, `/events`, SSE events `job_update`, `job_progress`, `queue_status`. + +### Enrich item details endpoint +- Extend `GET /api/review/:id` to include the latest job row for this item (if any): + ```ts + job: { + id: number; + status: Job["status"]; + job_type: "copy" | "transcode"; + command: string | null; + output: string | null; + exit_code: number | null; + started_at: string | null; + completed_at: string | null; + } | null + ``` +- "Latest" = most recent by `jobs.created_at DESC LIMIT 1` for the item. A single additional prepared statement. + +## Frontend changes + +### Deletions +- `src/features/execute/ExecutePage.tsx` +- `src/routes/execute.tsx` +- Nav link to `/execute` in `src/routes/__root.tsx` +- `plan_update` SSE listener in `src/features/pipeline/PipelinePage.tsx:70-72` +- Verify button, `verifyUnverified()`, `unverifiedCount`, and the `✓`/`✓✓` glyph span in `src/features/pipeline/DoneColumn.tsx` +- The `verified` field on `PipelineJobItem` in `src/shared/lib/types.ts:161` + +### DoneColumn simplification +Each card keeps its title link, `← Back to review` hover button, and status `` (`done` or `error`). The mark glyph and its `title` attribute go away. Column actions stay: `Clear` when items exist. + +### Pipeline column headers (batch controls) +`ColumnShell` already accepts an `actions: ColumnAction[]` array. Move existing batch controls off the `/execute` page into the headers: +- **Queued column** — `Run all` (primary, when at least one pending) + `Clear queue` (when items exist) +- **Done column** — `Clear` (existing) +- **Processing column** — no batch controls + +Wire these to the existing endpoints: `/api/execute/start`, `/api/execute/clear`, `/api/execute/clear-completed`. + +### AudioDetailPage job section +New section rendered only when `data.job` is non-null. Placement: between the FFmpeg command textarea and the Approve/Skip button row. + +Contents: +- Header row: status ``, job-type badge (`Audio Remux`/`Audio Transcode`), started/completed timestamps, exit code badge (only when non-zero) +- `Cmd` toggle button — reveals the job's recorded command (the `jobs.command` column) +- `Log` toggle button — reveals `jobs.output`; auto-expanded when `status === "error"` +- Action buttons based on `job.status`: + - `pending` → `▶ Run` (calls `POST /api/execute/job/:id/run`), `✕ Cancel` (calls `POST /api/execute/job/:id/cancel`) + - `running` → `✕ Stop` (calls `POST /api/execute/stop`) + - `done` / `error` → no actions + +### Live updates on details page +The details page gets its own scoped `EventSource` subscription to `/api/execute/events`, filtering for events where `id === data.job?.id`: +- `job_update` → merge into local state, re-fetch details on terminal (`done`/`error`) to pick up the refreshed `jobs` row +- `job_progress` → update a progress bar for the active job +- Close on unmount + +## Data flow after the change + +1. User approves plan in Review → plan.status = approved +2. User clicks `Run all` in Queued column header → queued jobs start +3. Processing column shows the running job with live progress (unchanged) +4. Job finishes → `jobs.status = done`, `review_plans.status = done`. No Jellyfin refresh, no verified flip. +5. Card lands in Done column with a `done` badge. No ✓/✓✓ glyph. +6. Next scan (automatic or manual) re-analyzes the file. If still `is_noop = 1`, plan stays `done`; if not, plan returns to `pending` and the card reappears in Review. + +## Testing + +- Delete `server/services/__tests__/webhook.test.ts:186-240` — the "webhook_verified flag" describe block. The remaining webhook tests (status transitions, upserts) stay. +- No new tests required: this spec removes features, does not add behavior. + +## Guided Gates + +- **GG-1:** After deploy, confirm the Done column shows cards with only a `done`/`error` badge — no ✓ or ✓✓ glyph. +- **GG-2:** Click an item in Done → details page shows the job section below the FFmpeg command box, with `Cmd` and `Log` toggles. +- **GG-3:** Click an item in Queued → details page shows a pending job with working `▶ Run` and `✕ Cancel` buttons; running the job updates the badge live. +- **GG-4:** `/execute` in the browser returns a 404 (route is gone). +- **GG-5:** `Run all` and `Clear queue` buttons appear in the Queued column header; `Clear` stays in the Done column header. +- **GG-6:** `PRAGMA table_info(review_plans);` in the SQLite DB no longer lists a `verified` column.