{"record":{"id":"2934514bd0b6c8e8","repo":"affaan-m/ECC","slug":"completion-requires-the-correct-dispatch-reconciliation","errorCode":null,"errorMessage":"completion requires the correct dispatch/reconciliation state","messagePattern":"completion requires the correct dispatch/reconciliation state","errorType":"validation","errorClass":"ClaimError","httpStatus":null,"severity":"error","filePath":"skills/operator-approval-loop/references/approval_claims.py","lineNumber":143,"sourceCode":"        db.execute(\"UPDATE obligation_delivery_claims SET state='unknown',updated_ts=? WHERE token=?\",\n                   (now, token))\n\n\ndef _finish(db, token, coordinate, now, evidence):\n    if not isinstance(coordinate, str) or not coordinate.strip():\n        raise ClaimError('a confirmed nonempty coordinate is required')\n    with _transaction(db, now):\n        row = _claim_row(db, token)\n        receipt = db.execute('''SELECT * FROM obligation_deliveries\n            WHERE obligation_id=? AND decision_id=?''',\n                             (row['obligation_id'], row['decision_id'])).fetchone()\n        if row['state'] == 'delivered':\n            if receipt is None or receipt['coordinate'] != coordinate or receipt['kind'] != 'draft_sent':\n                raise ClaimError('completion contradicts the existing receipt')\n            return False\n        expected_state = 'dispatching' if evidence is None else 'unknown'\n        if row['state'] != expected_state:\n            raise ClaimError('completion requires the correct dispatch/reconciliation state')\n        _snapshot(db, row['obligation_id'], row['decision_id'])\n        db.execute('''INSERT INTO obligation_deliveries\n            (obligation_id,decision_id,kind,coordinate,delivered_ts) VALUES (?,?,'draft_sent',?,?)''',\n                   (row['obligation_id'], row['decision_id'], coordinate, now))\n        db.execute('''UPDATE obligation_delivery_claims\n            SET state='delivered',updated_ts=?,reconciliation_evidence=? WHERE token=?''',\n                   (now, evidence, token))\n        changed = db.execute(\"UPDATE obligations SET status='sent' WHERE id=? AND status='approved'\",\n                             (row['obligation_id'],)).rowcount\n        if changed != 1:\n            raise ClaimError('obligation completion failed')\n    return True\n\n\ndef complete(db, token, coordinate, *, now):\n    \"\"\"Atomically record a confirmed result; identical duplicate completion is a no-op.\"\"\"\n    return _finish(db, token, coordinate, now, None)\n","sourceCodeStart":125,"sourceCodeEnd":161,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/skills/operator-approval-loop/references/approval_claims.py#L125-L161","documentation":"_finish raises this when the claim's state is neither the expected completion state nor 'delivered'. For complete() (evidence=None) the claim must be 'dispatching'; for reconcile() the claim must be 'unknown'. This guarantees completion is only recorded for an attempt that was actually dispatched, or one whose uncertainty has been reconciled with evidence.","triggerScenarios":"Calling complete() on a claim still in 'claimed' (begin_dispatch never called) or in 'unknown'; calling reconcile() on a claim in 'claimed' or 'dispatching'; calling either on a 'cancelled' claim.","commonSituations":"Skipping begin_dispatch and calling complete directly on a fresh token; calling reconcile before mark_unknown after a failed dispatch; recovery code calling the wrong finisher for the current state.","solutions":["For a normal delivery: call begin_dispatch first, send, then complete().","After an uncertain dispatch: call mark_unknown() first, then reconcile() with trusted evidence.","Select the finisher from the current state: state 'dispatching' -> complete(); state 'unknown' -> reconcile(); anything else -> not completable.","Check state before calling: SELECT state FROM obligation_delivery_claims WHERE token=?."],"exampleFix":"// before: complete without ever dispatching\nclaims.complete(db, token, coordinate, now=ts)  # state 'claimed' -> ClaimError\n\n// after\nclaims.begin_dispatch(db, token, now=ts)\nsend(payload)\nclaims.complete(db, token, coordinate, now=ts)\n# uncertain path:\n# claims.mark_unknown(...); claims.reconcile(db, token, coordinate, evidence, now=ts)","handlingStrategy":"validation","validationCode":"state = db.execute(\"SELECT state FROM obligation_delivery_claims WHERE token=?\", (token,)).fetchone()['state']\nif state == 'dispatching':\n    finisher = lambda: claims.complete(db, token, coordinate, now=ts)\nelif state == 'unknown':\n    finisher = lambda: claims.reconcile(db, token, coordinate, evidence, now=ts)\nelse:\n    raise ValueError(f\"claim not completable in state {state}\")","typeGuard":null,"tryCatchPattern":"try:\n    finisher()\nexcept claims.ClaimError as e:\n    log.error(\"finish refused for %s: %s\", token, e)","preventionTips":["Always begin_dispatch before complete","Always mark_unknown before reconcile","Pick the finisher from the claim's current state, not from the code path you expected"],"tags":["state-machine","api-misuse","recovery","claim-token"],"backgroundTag":"invalid-state-transition","analyzedSha":"8321021c54d670126ce3b2969d5deb880b4b0c2a","analyzedAt":"2026-09-16T10:08:13.343Z","contentChangedAt":"2026-09-16T10:08:13.343Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}