0033. Retire the batch execution path (FR-17 Slice 6b-iii)
Date: 2026-07-19 Status: accepted
Context
The agentic retest console (ADR-0025 → ADR-0032) now covers the whole retest lifecycle end to end: a user-owned goal (ADR-0032) drives a Pydantic AI agent that runs gated commands in an egress-locked sandbox, concludes a verdict (ADR-0030) backed by flexible command-output evidence (ADR-0031), and leaves a replayable transcript for the FR-10 audit and the FR-12 export.
That makes the original batch execution path fully redundant. The batch path
was: an LLM-proposed, deterministically-gated retest plan of typed HTTP Probes
(ADR-0011), a server-side plan-approval gate (ADR-0012), an independent execution
sanity checker (ADR-0014), an optional browser-driven probe executor (ADR-0018),
and a kind-keyed technique registry (ADR-0019). Every one of those now has an
agentic equivalent, and keeping both means two verdict producers, two evidence
shapes, and a polymorphic VerdictRecord (ADR-0030's source discriminator)
whose batch branch is never written in an agentic-only world.
Two paths to the same outcome differ only in cost. Álvaro chose full deletion (clean end-state) over a soft-deprecate: dead code is the project's #1 development pathology (CLAUDE.md), and a never-filled batch branch invites bit-rot in exactly the audit/export surface the thesis leans on for reproducibility.
Decision
Delete the batch execution path outright and collapse every shape it left polymorphic down to the single agentic one.
- Delete the batch modules and their demos/tests:
approval.py,retest.py,sanity.py,browser.py(withtest_approval*,test_retest,test_sanity,test_browser,test_techniques,test_db_plan, the batch API/pipeline tests, and thedemo-plan/approval/sanity/techniques/browser-xss/walking-skeletondemos + Makefile targets). - Remove the batch REST surface from
app.py(plan generate/edit/approve/ reject/revise/list and theretestendpoints). KeepGET /verdictsandGET /audit, now served agentic-only. - Strip
plan.pyto goal-only — keep the repurposedgenerate_goal(FR-04, ADR-0032); dropgenerate_plan,Probegating, and the allowlist coupling. - Collapse the domain: remove
Probe,RetestPlan,PlanStatus,Verdict, andEvidence; keepAgenticEvidenceandVerdictStatus. - Collapse persistence: drop
PlanRecord;VerdictRecordbecomes agentic-only — thesourcediscriminator and the batch-only columns (plan_id,plan_version,probe_kind) go, leaving the singleagentic()shape. This realizes ADR-0030's polymorphism as one concrete shape. - Narrow the FR-12 export: drop
PlanExportand theplansmetric;VerdictExportis agentic-only; schema 1.3 → 1.4 (published schema regenerated, drift test enforces it). - Collapse the FR-10 audit to agentic-only transcript re-derivation
(
_rederive_agentic); the batch evidence-rederivation branch is removed. - Drop FR-14 (browser-driven probes) entirely.
- FR-06 unchanged, one mechanism. Egress control now lives solely in the
sandbox's Docker
--internalnetwork membership (ADR-0025) — strictly stronger than the deleted HTTP-transport allowlist, which only ever guarded batchProbes.allowlist.pyis thereby orphaned; it is kept this slice (a tracked cleanup follow-up) rather than deleted, to avoid expanding a batch-retirement slice onto the FR-06 module.lab_base_url()(the one helper the system test still used fromretest.py) moves tosandbox.py.
Implementation split. 6b-iii-a is the backend deletion (this ADR's realization). 6b-iii-b reshapes the SPA finding flow to Extract → Goal → Agentic retest → Verdict.
Alternatives considered
- Soft-deprecate — keep the batch modules dead behind a flag. Rejected: dead
code is the #1 pathology here, and a
VerdictRecord.sourcebranch that is never written rots silently in the audit/export path. - Keep the batch path as a non-interactive fallback. Rejected: free-launch mode (ADR-0029) already runs the agentic console unattended, so a second verdict producer buys nothing and doubles the FR-10/FR-12 surface to keep correct.
- Delete
allowlist.pyin this slice too. Rejected (deferred): it is an FR-06 module, not part of the batch execution path proper; the CI gate does not force it (vulture is advisory,--min-confidence 80 || true), so its removal is a separate, safely-deferrable cleanup rather than scope creep here. - A soft schema bump (additive-only). Rejected: the batch fields are gone, not
optional; a clean
1.4that matches the emitted document beats a schema carrying fields nothing writes.
Consequences
- Good: one verdict producer (agentic), one evidence shape
(
AgenticEvidence), one audit path, one export shape. Nine source/test/demo modules deleted;VerdictRecord,VerdictExport, and the audit collapse from polymorphic to a single concrete shape. - Requirements: FR-04/05/07/08 move implemented → superseded by FR-17; FR-14 is dropped; FR-06 stays satisfied (network isolation); FR-09/10/12 now have exactly one implementation. ADR-0025 becomes ratifiable — its "supersedes FR-04/05/07-09 over time" is now realized — and ADRs 0011/0012/0014/0015/0018/ 0019/0022/0023 are superseded by this one.
- Breaking export change (1.4): consumers lose
plansand the batch verdict fields. The only consumer, the FR-15 eval harness, already reads the agentic shape, so no migration is needed. - Accepted debt:
allowlist.pyis orphaned pending a cleanup follow-up. The SPA still calls the removed batch endpoints until 6b-iii-b — they 404 harmlessly and the SPA build/tests mock the client, so the frontend is unaffected by this backend deletion.
References
- Design spec:
docs/superpowers/specs/2026-07-19-agentic-retest-console-slice-6b-iii-design.md - Plan:
docs/superpowers/plans/2026-07-19-agentic-retest-console-slice-6b-iii-a.md - Supersedes ADR-0011, ADR-0012, ADR-0014, ADR-0015, ADR-0018, ADR-0019, ADR-0022, ADR-0023. Realizes ADR-0025; builds on ADR-0030/0031/0032. Epic #87, issue #110.