Effort: standard
scidex/forge/forge_tools.py:43 register_tool adds entries to the skills
table; today there's no reverse audit asking "of the registered tools, which
have not been invoked in 90 days?". The result is tools.py accreting dead
weight: tools written for one debate, never used again, still showing up in
agent prompt manifests and confusing model selection. Build a periodic
detector that flags zero-usage tools, classifies why (broken? superseded?
niche?), and emits Senate decisions for each: deprecate, retire, or rewrite.
scidex/forge/deprecated_tool_detector.py::scan(window_days=90) returns rows where times_used = 0 in window OR success_rate_in_window < 0.3.never_invoked, chronic_failure (success_rate < 0.3), superseded (LLM check: are there tools with overlapping signature with success_rate > 0.7?), niche (used <5 times but successful).tool_deprecation_candidates(tool_id PK, classification, evidence_json, scanned_at, decision, decided_at, decided_by) — created inline via ensure_table().effort=standard): given (deprecated_tool_signature, candidate_supersessor_signatures), returns boolean + rationale.scidex/senate/scheduled_tasks.py; emits a tool_deprecation_review Senate proposal grouping all candidates by classification./forge/tools/deprecation page lists candidates with classification badges and "decide" buttons (delegates to apply_decision).GET /api/forge/tools/deprecation returns the candidate list.retire, skills.retired_at is set and the candidate row is marked retired_at (PR auto-comment deferred to review workflow).scidex/forge/forge_tools.py:67 log_tool_call to learn the success/duration schema.scidex/forge/tools.py not from string-matching.scripts/orchestra_pr.py if present; else use subprocess + gh pr create (see CLAUDE.md "Creating pull requests" pattern).scanned_at row.q-tools-cost-benchmark — supplies success-rate and ROI signals.scidex/forge/forge_tools.py (skills table source).scidex/senate/governance.py:159 create_proposal — proposal channel.Files created/modified:
scidex/forge/deprecated_tool_detector.py — new module: ensure_table(), scan(window_days=90, force=False), emit_senate_proposal(), apply_decision(), get_candidates(), _check_supersession() (LLM-graded), _get_tool_signatures_from_ast() (AST-based), _upsert_candidate() (isolated per-row commits to avoid TX poisoning)scidex/senate/scheduled_tasks.py — added DeprecatedToolDetectorTask with weekly 10080-min cronapi.py — added GET /api/forge/tools/deprecation (JSON), POST /api/forge/tools/deprecation/{tool_id}/decide, GET /forge/tools/deprecation (HTML page with classification badges and decide buttons)tests/test_deprecated_tool_detector.py — test harness for the 3-tool seed scenariodocs/planning/specs/q-tools-deprecated-detector_spec.md — this filenever_invoked, B (5/20 = 25%) → chronic_failure, C (3/3, 3 uses) → nicheemit_senate_proposal creates tool_deprecation_review proposal with all 3 test tools in metadata.tool_ids_upsert_candidate prevent PostgreSQL TX abort from propagating across the scan loop