The 2026-04-24 recurring-block incident
(project_orchestra_recurring_block_incident) showed 165 tasks burning
slots with zero output. aa8c3204_2746's "Wasted Resources" section
flags individual high-cost-low-impact tasks but doesn't act. Build a
detector that, when a task has been picked up by 3+ slots without a
landed commit (no task_runs.commit_sha row), automatically archives
it with a waste_archived status, refunds the bidder's wallet, and
emits a Senate proposal asking a human to spec-rewrite or kill it.
scidex/senate/waste_detector.py::scan() -> list[WasteCandidate] with fields (task_id, attempt_count, total_tokens_burned, last_failure_reason).count(task_runs WHERE task_id = T AND finished_at IS NOT NULL AND commit_sha IS NULL) >= 3 AND no successful run in last 14 days.waste_archived, write a row to waste_archive_log with full attempt history, refund wallet via token_ledger.refund_task_cost(task_id).waste_review enumerates the candidates and links to the spec file for human-readable triage.WASTE_DETECTOR_DRY_RUN=1) defaults to 0 only after a 7-day shadow period (logged decisions but no archive)./senate adds "Waste Archive" tab listing last 90 days of auto-archives with un-archive button.open.archive lifecycle code paths in orchestra/services.py to ensure we don't break audit trails.task_runs.commit_sha IS NULL AND finished_at IS NOT NULL as the abandonment signal — avoids racing with in-flight runs.cost_ledger.cost_usd for the task's runs and credit the spawning quest's wallet.waste_archive_log.id so the human can see the full history without 3 SQL hops.2147d16ef177 (wallets) for refund.task_runs table from Orchestra (existing).Files created/modified:
scidex/senate/waste_detector.py — core module with scan(), archive_waste(),unarchive_task(), run_once(), get_archive_log(); WasteCandidate dataclass;ensure_tables() for waste_archive_log.
tests/test_waste_detector.py — 10 tests covering scan, archive, dry-run, unarchive,api_routes/senate.py — added POST /api/senate/waste-detector/run,GET /api/senate/waste-archive, POST /api/senate/waste-archive/{task_id}/unarchive.
scidex/senate/scheduled_tasks.py — registered senate.waste_detector as a dailyapi.py — added GET /senate/waste-archive page route with un-archive buttons;Implementation notes:
waste_archived; used archived insteadwaste_archive_log (SciDEX PostgreSQL).
task_runs.ended_at IS NOT NULL AND task_runs.last_commit_shaquality_gate proposal type (only valid type that fits).WASTE_DETECTOR_DRY_RUN defaults to "1" (shadow period); set to "0" to activate.token_ledger; no-op when billing is disabled.