Summary
When complete-task.ts fails during disk render, the rollback path resets task status to "pending" but does not clean up verification_evidence rows inserted in the same transaction.
Impact
After a disk-render failure and rollback:
- Task status is
pending (correct)
- Verification evidence rows exist pointing to a
pending task (incorrect — from a rolled-back completion attempt)
- On retry,
insertVerificationEvidence INSERTs additional rows (no ON CONFLICT deduplication), so evidence accumulates across attempts
Root Cause
complete-task.ts:246-263 — The rollback at lines 251-260 runs a raw UPDATE tasks SET status = 'pending' but does not DELETE FROM verification_evidence for the same task.
The original transaction (lines 155-208) calls both insertTask() and insertVerificationEvidence() — both succeed and commit. The "rollback" is actually a compensating write after commit, not a true rollback. It compensates the task status but forgets the evidence.
Fix
Option A: Add DELETE FROM verification_evidence WHERE milestone_id = :mid AND slice_id = :sid AND task_id = :tid to the rollback path.
Option B (better): Use a SQLite savepoint or restructure so disk render happens inside the transaction, allowing a real rollback on failure.
Option C: Make insertVerificationEvidence use INSERT OR REPLACE keyed on (milestone_id, slice_id, task_id, command) so retries are idempotent.
Files
src/resources/extensions/gsd/tools/complete-task.ts — lines 155-208 (transaction), 246-263 (rollback)
Confidence
83%
Summary
When
complete-task.tsfails during disk render, the rollback path resets task status to"pending"but does not clean upverification_evidencerows inserted in the same transaction.Impact
After a disk-render failure and rollback:
pending(correct)pendingtask (incorrect — from a rolled-back completion attempt)insertVerificationEvidenceINSERTs additional rows (noON CONFLICTdeduplication), so evidence accumulates across attemptsRoot Cause
complete-task.ts:246-263— The rollback at lines 251-260 runs a rawUPDATE tasks SET status = 'pending'but does notDELETE FROM verification_evidencefor the same task.The original transaction (lines 155-208) calls both
insertTask()andinsertVerificationEvidence()— both succeed and commit. The "rollback" is actually a compensating write after commit, not a true rollback. It compensates the task status but forgets the evidence.Fix
Option A: Add
DELETE FROM verification_evidence WHERE milestone_id = :mid AND slice_id = :sid AND task_id = :tidto the rollback path.Option B (better): Use a SQLite savepoint or restructure so disk render happens inside the transaction, allowing a real rollback on failure.
Option C: Make
insertVerificationEvidenceuseINSERT OR REPLACEkeyed on(milestone_id, slice_id, task_id, command)so retries are idempotent.Files
src/resources/extensions/gsd/tools/complete-task.ts— lines 155-208 (transaction), 246-263 (rollback)Confidence
83%