Compare commits

...

1 Commits

Author SHA1 Message Date
HAL9000 5ce452b67e docs(spec): document ReconciliationBlockedError and invariant reconciliation failure behavior
CI / lint (pull_request) Successful in 35s
CI / quality (pull_request) Successful in 33s
CI / typecheck (pull_request) Successful in 48s
CI / helm (pull_request) Successful in 23s
CI / push-validation (pull_request) Successful in 19s
CI / security (pull_request) Successful in 1m11s
CI / build (pull_request) Successful in 44s
CI / integration_tests (pull_request) Successful in 4m45s
CI / e2e_tests (pull_request) Successful in 5m5s
CI / unit_tests (pull_request) Successful in 7m19s
CI / docker (pull_request) Successful in 15s
CI / coverage (pull_request) Successful in 15m14s
CI / status-check (pull_request) Successful in 1s
CI / benchmark-publish (pull_request) Has been skipped
CI / benchmark-regression (pull_request) Successful in 58m3s
Adds a new 'Reconciliation failure behavior' subsection to the Invariants
section documenting:

- ReconciliationBlockedError blocks phase transitions when reconciliation fails
- INVARIANT_VIOLATED event emitted on the event bus
- Reconciliation runs at start of Strategize, Execute, and Apply phases
- Post-correction automatic re-reconciliation via CORRECTION_APPLIED event
- builtin/invariant-reconciliation as the fallback actor name

This fills a spec gap identified in proposal #5942 — the implementation
(plan_lifecycle_service.py, actor/reconciliation.py) has this behavior
but it was not documented in the spec.
2026-04-10 20:45:23 +00:00
+14
View File
@@ -19750,6 +19750,20 @@ Each effective invariant is then recorded as an `invariant_enforced` decision in
**Child plan inheritance**: When a top-level plan spawns child plans, the parent's effective invariant view (already reconciled) is passed down to each child plan. Child plans do not re-run reconciliation — they inherit the parent's resolved view.
**Reconciliation failure behavior**: When invariant reconciliation fails at a phase transition, the transition is **blocked** — the plan cannot proceed to the next phase until the invariants are corrected. The system raises a `ReconciliationBlockedError` and emits an `INVARIANT_VIOLATED` event on the event bus. The plan remains in its current phase (e.g., `action` if Strategize was blocked, `strategize` if Execute was blocked).
Reconciliation runs at the start of three phase transitions:
| Phase Transition | When Reconciliation Runs |
|-----------------|--------------------------|
| `start_strategize()` | Before the Strategize phase begins |
| `execute_plan()` | Before the Execute phase begins |
| `apply_plan()` | Before the Apply phase begins |
After a correction is applied via `agents plan correct`, reconciliation automatically re-runs (best-effort) via a `CORRECTION_APPLIED` event subscription. If re-reconciliation succeeds, the plan can proceed to the next phase. If it fails again, the plan remains blocked.
The built-in Invariant Reconciliation Actor is registered as `builtin/invariant-reconciliation`. It is used as the fallback when no actor is configured at the plan, project, or global level.
**Correcting invariants**: The correction mechanism for `invariant_enforced` decisions supports two operations:
* **Remove**: Remove an existing invariant from the plan's decision tree (the invariant remains defined at its scope but is no longer enforced for this plan).
* **Add**: Add a new invariant to the plan. When adding, the user can select from invariants already accessible to the plan (those defined at the plan, action, project, or global scope), or provide free-form text to create a new ad-hoc invariant.