RFC-012: Artifact Lifecycle Protocol (ALP) — 8. Compensation
AIGP Specification › RFC-012: Artifact Lifecycle Protocol (ALP) › 8. Compensation
← 7. Approval Rules · Section index · 9. Storage →
8. Compensation
Every executable artifact MUST have a paired compensation (rollback) artifact. Compensation is the mechanism that ensures failed executions can be reversed.
8.1 Compensation Rules
- A compensation artifact MUST be created at the same time as its primary artifact (in the CREATE message).
- A compensation artifact follows the same lifecycle as its primary when the primary is promoted, the compensation is promoted alongside it.
- A compensation artifact MUST be reviewed and approved as part of the primary’s approval.
- Compensation is triggered automatically when an artifact transitions to
FAILED. - Compensation execution is itself an ALP-governed operation it produces its own execution record and provenance.
8.2 Compensation Schema
{ "artifact_id": "art-20260504-001-rollback", "artifact_type": "PYTHON_SCRIPT", "name": "rollback-remediate-prisma-gaps.py", "is_compensation": true, "compensates_for": "art-20260504-001", "state": "APPROVED", "content_ref": { "s3_bucket": "run-prj-artifacts", "s3_key": "artifacts/art-20260504-001/v1/rollback-remediate-prisma-gaps.py", "content_hash": "sha256:f6g7h8i9j0k1..." }}8.3 Compensation Execution Flow
Primary artifact FAILS
Orchestrator evaluates failure
Is compensation artifact available and APPROVED? YES Execute compensation artifact NO Alert human operator, halt
Compensation artifact executes
COMPLETED Primary marked FAILED (compensated)
FAILED CRITICAL ALERT manual intervention required8.4 Compensation Execution
async def handle_execution_failure(orchestrator, primary_artifact: dict, failure: dict) -> dict: """Handle a failed artifact execution by triggering compensation.""" comp_id = primary_artifact["compensation_ref"]["artifact_id"] comp_artifact = await orchestrator.get_artifact(comp_id)
if comp_artifact["state"] != "APPROVED": await orchestrator.alert( severity="CRITICAL", message=f"Compensation artifact {comp_id} not in APPROVED state", primary_artifact_id=primary_artifact["artifact_id"], ) return {"compensation": "UNAVAILABLE", "requires_manual_intervention": True}
result = await orchestrator.execute_artifact(comp_artifact, context={ "compensating_for": primary_artifact["artifact_id"], "failure_reason": failure["error"], "run_id": failure["run_id"], })
if result["state"] == "COMPLETED": return {"compensation": "SUCCEEDED", "rollback_run_id": result["run_id"]}
await orchestrator.alert( severity="CRITICAL", message=f"Compensation FAILED for {primary_artifact['artifact_id']}", requires_manual_intervention=True, ) return {"compensation": "FAILED", "requires_manual_intervention": True}