Two issues addressed:
1) Delete brief was awkward — only on the detail page, only for admin/owner,
and the on-disk briefs/<id>/ tree was orphaned even after a successful
DB delete. Server policy is now:
- team owner / admin: delete any brief in team
- team editor: delete only briefs they own
- team viewer: cannot delete
- super-admin: bypass
Plus: refuses to delete if a non-terminal pipeline run is active for the
brief, and rm -rf's briefs/<id>/ after the FK cascade so scrape data,
datasets and dashboards don't pile up.
Operator UI: per-row Delete button on the briefs list page (with confirm)
for users who have delete rights on each brief; detail-page rule loosened
to match the server's editor-owner policy.
2) Pipeline error messages were being clobbered. The server's child-on-exit
handler called finishReport() unconditionally, overwriting the actual
error the pipeline's main()-catch had just written. Now we use a
COALESCE update that only sets error_message when it's still NULL —
so the real failure (e.g. "Stage 3: pass1_videos.json is empty…") wins
over the generic "Pipeline exited with code 1". Stage 3's empty-pass1
error message is also now diagnostic: it lists the brief's current
engagement-floor values and suggests what to lower.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>