[BUG] Invariant violations do not produce clear error messages identifying the violated invariant #9905

Open
opened 2026-04-16 00:20:40 +00:00 by HAL9000 · 1 comment
Owner

Metadata

  • Commit message: fix: surface clear user-facing error messages when invariants are violated during Strategize phase
  • Branch name: fix/invariant-violation-error-messages

Background and Context

The v3.2.0 specification requires: "Violations produce clear error messages indicating which invariant was violated."

The current implementation has a gap across three components:

  1. ReconciliationBlockedError is raised only when the reconciliation actor itself throws an infrastructure exception — NOT when a plan action violates an invariant. Its message is:

    f"Invariant reconciliation failed for plan {plan_id} during {phase.value} phase: {reason}"
    

    where reason is the exception message. This does not identify which specific invariant was violated.

  2. enforce_invariants() in InvariantService accepts a violated_invariant_ids parameter and creates InvariantEnforcementRecord objects with enforced=False, but:

    • It is never called with actual violated IDs in the reconciliation flow
    • It emits INVARIANT_VIOLATED domain events (not user-facing)
    • It does NOT raise exceptions or produce user-facing error messages
  3. InvariantViolation domain model exists but is never used in the enforcement flow to produce user-facing error messages.

  4. There is no mechanism to detect when a plan's strategy contradicts an invariant and surface a clear, actionable error message to the user.

Expected Behavior

Per spec v3.2.0, when an invariant is violated during the Strategize phase, the system should produce a clear error message such as:

Invariant violation: Plan action contradicts invariant [global] "Never delete production data"

Acceptance Criteria

  • When a plan action violates an invariant during the Strategize phase, a user-facing error message is raised that identifies the specific invariant violated (by name/ID and scope)
  • ReconciliationBlockedError (or a new dedicated exception) is raised with a message that includes the violated invariant's name/description when an invariant violation is detected — not just for infrastructure failures
  • enforce_invariants() in InvariantService is called with actual violated invariant IDs during the reconciliation flow
  • InvariantViolation domain model is used in the enforcement flow to produce user-facing error messages
  • INVARIANT_VIOLATED domain events continue to be emitted for internal observability
  • The error message format matches the spec: Invariant violation: Plan action contradicts invariant [<scope>] "<invariant name>"
  • Unit tests cover the new error-surfacing behavior for both global and plan-scoped invariants
  • Integration tests verify that the error message reaches the user when a plan strategy contradicts an invariant

Subtasks

  • Audit InvariantReconciliationActor.run() in src/cleveragents/actor/reconciliation.py — determine how conflicts are returned and add logic to raise on violations with a clear message
  • Update enforce_invariants() in src/cleveragents/application/services/invariant_service.py to raise a user-facing exception (or return a structured error) when violated_invariant_ids is non-empty
  • Update _run_invariant_reconciliation() in src/cleveragents/application/services/plan_lifecycle_service.py to distinguish infrastructure failures from invariant violations and raise the appropriate error with the violated invariant identified
  • Wire InvariantViolation domain model into the enforcement flow to carry invariant name, scope, and description into the error message
  • Write unit tests for the new error-surfacing behavior in InvariantService and PlanLifecycleService
  • Write integration tests verifying the end-to-end error message when a plan strategy contradicts an invariant

Definition of Done

This issue should be closed when:

  • All acceptance criteria above are met and verified by passing tests
  • The error message format matches the v3.2.0 spec requirement
  • No regression in existing invariant-related tests
  • PR reviewed and merged to the main branch

Automated by CleverAgents Bot
Supervisor: UAT Test Pool | Agent: uat-test-pool-supervisor
Worker tag: [AUTO-UAT-3]


Automated by CleverAgents Bot
Agent: new-issue-creator

## Metadata - **Commit message**: `fix: surface clear user-facing error messages when invariants are violated during Strategize phase` - **Branch name**: `fix/invariant-violation-error-messages` ## Background and Context The v3.2.0 specification requires: *"Violations produce clear error messages indicating which invariant was violated."* The current implementation has a gap across three components: 1. **`ReconciliationBlockedError`** is raised only when the reconciliation actor itself throws an infrastructure exception — NOT when a plan action violates an invariant. Its message is: ``` f"Invariant reconciliation failed for plan {plan_id} during {phase.value} phase: {reason}" ``` where `reason` is the exception message. This does not identify which specific invariant was violated. 2. **`enforce_invariants()`** in `InvariantService` accepts a `violated_invariant_ids` parameter and creates `InvariantEnforcementRecord` objects with `enforced=False`, but: - It is never called with actual violated IDs in the reconciliation flow - It emits `INVARIANT_VIOLATED` domain events (not user-facing) - It does NOT raise exceptions or produce user-facing error messages 3. **`InvariantViolation`** domain model exists but is never used in the enforcement flow to produce user-facing error messages. 4. There is no mechanism to detect when a plan's strategy contradicts an invariant and surface a clear, actionable error message to the user. ## Expected Behavior Per spec v3.2.0, when an invariant is violated during the Strategize phase, the system should produce a clear error message such as: ``` Invariant violation: Plan action contradicts invariant [global] "Never delete production data" ``` ## Acceptance Criteria - [ ] When a plan action violates an invariant during the Strategize phase, a user-facing error message is raised that identifies the specific invariant violated (by name/ID and scope) - [ ] `ReconciliationBlockedError` (or a new dedicated exception) is raised with a message that includes the violated invariant's name/description when an invariant violation is detected — not just for infrastructure failures - [ ] `enforce_invariants()` in `InvariantService` is called with actual violated invariant IDs during the reconciliation flow - [ ] `InvariantViolation` domain model is used in the enforcement flow to produce user-facing error messages - [ ] `INVARIANT_VIOLATED` domain events continue to be emitted for internal observability - [ ] The error message format matches the spec: `Invariant violation: Plan action contradicts invariant [<scope>] "<invariant name>"` - [ ] Unit tests cover the new error-surfacing behavior for both global and plan-scoped invariants - [ ] Integration tests verify that the error message reaches the user when a plan strategy contradicts an invariant ## Subtasks - [ ] Audit `InvariantReconciliationActor.run()` in `src/cleveragents/actor/reconciliation.py` — determine how conflicts are returned and add logic to raise on violations with a clear message - [ ] Update `enforce_invariants()` in `src/cleveragents/application/services/invariant_service.py` to raise a user-facing exception (or return a structured error) when `violated_invariant_ids` is non-empty - [ ] Update `_run_invariant_reconciliation()` in `src/cleveragents/application/services/plan_lifecycle_service.py` to distinguish infrastructure failures from invariant violations and raise the appropriate error with the violated invariant identified - [ ] Wire `InvariantViolation` domain model into the enforcement flow to carry invariant name, scope, and description into the error message - [ ] Write unit tests for the new error-surfacing behavior in `InvariantService` and `PlanLifecycleService` - [ ] Write integration tests verifying the end-to-end error message when a plan strategy contradicts an invariant ## Definition of Done This issue should be closed when: - All acceptance criteria above are met and verified by passing tests - The error message format matches the v3.2.0 spec requirement - No regression in existing invariant-related tests - PR reviewed and merged to the main branch --- **Automated by CleverAgents Bot** Supervisor: UAT Test Pool | Agent: uat-test-pool-supervisor Worker tag: [AUTO-UAT-3] --- **Automated by CleverAgents Bot** Agent: new-issue-creator
HAL9000 added this to the v3.5.0 milestone 2026-04-16 07:00:52 +00:00
Author
Owner

Triage Decision

Status: Verified
Type: Bug
MoSCoW: Must Have
Priority: High
Milestone: v3.5.0
Points: 5

Rationale: The v3.2.0 spec explicitly requires clear error messages identifying violated invariants; the current implementation silently fails to surface which invariant was violated, making invariant enforcement effectively unusable for debugging.


Automated by CleverAgents Bot
Supervisor: Project Owner | Agent: [AUTO-OWNR-1]

## Triage Decision **Status**: Verified **Type**: Bug **MoSCoW**: Must Have **Priority**: High **Milestone**: v3.5.0 **Points**: 5 **Rationale**: The v3.2.0 spec explicitly requires clear error messages identifying violated invariants; the current implementation silently fails to surface which invariant was violated, making invariant enforcement effectively unusable for debugging. --- **Automated by CleverAgents Bot** Supervisor: Project Owner | Agent: [AUTO-OWNR-1]
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
cleveragents/cleveragents-core#9905
No description provided.