Rebuild from scratch: new POST /api/jobs/{id}/rebuild-full forces every
pipeline stage to rerun unconditionally (reuses the existing force_from
mechanism, pinned to the first stage), for cases where an unchanged
resubmission would otherwise replay every stage as "cached, skipping" even
when output_dir is empty.
Delete: new DELETE /api/jobs/{id} removes a song's work/output
directories and drops it from the job list, gated the same way other
mutating endpoints are (409 while queued/running).
Cross-restart persistence: the worker now writes a work_dir/<slug>/input.json
sidecar right after the slug is resolved (ordered to avoid racing relocate_work's collision check), and a new _discover_jobs startup scan
reconstructs done/failed jobs from those sidecars before the worker
thread starts, so songs survive a server restart instead of disappearing
from the UI.
Frontend: "REBUILD FROM SCRATCH" and "DELETE" buttons wired up next to the
existing rerun/edit actions, plus a clearDetail() fix so the review panel
resets correctly when no job is selected (e.g. after deleting the last song).
Built via superpowers subagent-driven-development: 5 planned tasks, each with
its own task-scoped review, followed by a whole-branch final review that
caught and fixed 3 Important issues before merge (see below).
Notable fixes from final review
DELETE now checks for any other job sharing the same slug that's still
queued/running (e.g. a rebuild-from-scratch child) and returns 409 instead
of deleting the directories out from under it.
_discover_jobs no longer crashes the whole server on startup if one
song's sidecar/notes file was left corrupt/torn by an interrupted process
— it skips that entry and continues.
Two minor items were identified and deliberately deferred (not blocking):
DELETE doesn't clean up a failed job's retained video upload directory, and rebuildFullJob/rerunJob share near-identical fetch/error-handling code in
the frontend that could be factored out later.
Test plan
Full suite green: pytest -q → 251 passed, 1 skipped
Each of the 5 implementation tasks individually reviewed (spec +
quality) with clean verdicts
Whole-branch final review, findings fixed, scoped re-review clean
Manual smoke test in a browser (rebuild-from-scratch, delete, and a
server-restart reload) — not yet done by a human
**Summary generated by LLM agent**
## Summary
Three related fixes to the webui's job handling:
- **Rebuild from scratch**: new `POST /api/jobs/{id}/rebuild-full` forces every
pipeline stage to rerun unconditionally (reuses the existing `force_from`
mechanism, pinned to the first stage), for cases where an unchanged
resubmission would otherwise replay every stage as "cached, skipping" even
when `output_dir` is empty.
- **Delete**: new `DELETE /api/jobs/{id}` removes a song's work/output
directories and drops it from the job list, gated the same way other
mutating endpoints are (409 while queued/running).
- **Cross-restart persistence**: the worker now writes a `work_dir/<slug>/input.json`
sidecar right after the slug is resolved (ordered to avoid racing
`relocate_work`'s collision check), and a new `_discover_jobs` startup scan
reconstructs `done`/`failed` jobs from those sidecars before the worker
thread starts, so songs survive a server restart instead of disappearing
from the UI.
- Frontend: "REBUILD FROM SCRATCH" and "DELETE" buttons wired up next to the
existing rerun/edit actions, plus a `clearDetail()` fix so the review panel
resets correctly when no job is selected (e.g. after deleting the last song).
Built via superpowers subagent-driven-development: 5 planned tasks, each with
its own task-scoped review, followed by a whole-branch final review that
caught and fixed 3 Important issues before merge (see below).
## Notable fixes from final review
- `DELETE` now checks for any *other* job sharing the same slug that's still
queued/running (e.g. a rebuild-from-scratch child) and returns 409 instead
of deleting the directories out from under it.
- `_discover_jobs` no longer crashes the whole server on startup if one
song's sidecar/notes file was left corrupt/torn by an interrupted process
— it skips that entry and continues.
Two minor items were identified and deliberately deferred (not blocking):
DELETE doesn't clean up a failed job's retained video upload directory, and
`rebuildFullJob`/`rerunJob` share near-identical fetch/error-handling code in
the frontend that could be factored out later.
## Test plan
- [x] Full suite green: `pytest -q` → 251 passed, 1 skipped
- [x] Each of the 5 implementation tasks individually reviewed (spec +
quality) with clean verdicts
- [x] Whole-branch final review, findings fixed, scoped re-review clean
- [ ] Manual smoke test in a browser (rebuild-from-scratch, delete, and a
server-restart reload) — not yet done by a human
- DELETE now checks under the shared lock whether another job with the
same slug is queued/running before removing the job entry, so
deleting a done parent can no longer rmtree a rebuild's active
work/output directories.
- _discover_jobs now wraps the iterdir/stat/read_warnings calls in the
same try/except as the JSON parse, so one corrupt or torn sidecar
file (e.g. from a killed mid-write) no longer crashes the whole app
at boot.
- Fixed test_delete_tolerates_a_work_dir_that_is_already_gone, which
had become vacuous since _write_sidecar now eagerly creates the work
dir; it now removes the dir before asserting DELETE tolerates its
absence.
- Added a regression test covering the DELETE slug-collision race.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Summary generated by LLM agent
Summary
Three related fixes to the webui's job handling:
POST /api/jobs/{id}/rebuild-fullforces everypipeline stage to rerun unconditionally (reuses the existing
force_frommechanism, pinned to the first stage), for cases where an unchanged
resubmission would otherwise replay every stage as "cached, skipping" even
when
output_diris empty.DELETE /api/jobs/{id}removes a song's work/outputdirectories and drops it from the job list, gated the same way other
mutating endpoints are (409 while queued/running).
work_dir/<slug>/input.jsonsidecar right after the slug is resolved (ordered to avoid racing
relocate_work's collision check), and a new_discover_jobsstartup scanreconstructs
done/failedjobs from those sidecars before the workerthread starts, so songs survive a server restart instead of disappearing
from the UI.
existing rerun/edit actions, plus a
clearDetail()fix so the review panelresets correctly when no job is selected (e.g. after deleting the last song).
Built via superpowers subagent-driven-development: 5 planned tasks, each with
its own task-scoped review, followed by a whole-branch final review that
caught and fixed 3 Important issues before merge (see below).
Notable fixes from final review
DELETEnow checks for any other job sharing the same slug that's stillqueued/running (e.g. a rebuild-from-scratch child) and returns 409 instead
of deleting the directories out from under it.
_discover_jobsno longer crashes the whole server on startup if onesong's sidecar/notes file was left corrupt/torn by an interrupted process
— it skips that entry and continues.
Two minor items were identified and deliberately deferred (not blocking):
DELETE doesn't clean up a failed job's retained video upload directory, and
rebuildFullJob/rerunJobshare near-identical fetch/error-handling code inthe frontend that could be factored out later.
Test plan
pytest -q→ 251 passed, 1 skippedquality) with clean verdicts
server-restart reload) — not yet done by a human