UAT: InvariantReconciliationActor implements 4-tier precedence chain (plan > action > project > global) contradicting spec's 3-tier chain (plan > project > global) #3564

Open
opened 2026-04-05 19:46:12 +00:00 by freemo · 1 comment
Owner

Metadata

  • Branch: bugfix/invariant-reconciliation-3-tier-precedence
  • Commit Message: fix(reconciliation): enforce 3-tier invariant precedence chain per spec
  • Milestone: (none — backlog)
  • Parent Epic: #374

Background and Context

The InvariantReconciliationActor in src/cleveragents/actor/reconciliation.py implements a 4-tier precedence chain: plan > action > project > global. However, the specification (docs/specification.md line 92 and lines 19596–19604) explicitly states:

"Action invariants are promoted to plan-level when the action is used, so the runtime precedence chain is three-tier: plan > project > global."

And:

"Note: Action invariants are carried forward as plan-level invariants when the action is used (see Action invariants above), so they participate in precedence at the plan tier — there is no separate action tier in the precedence chain."

The reconciliation actor's conflict resolution therefore produces incorrect results when action-scoped invariants conflict with project-scoped invariants. Per spec, action invariants should already be in the plan's invariant list as InvariantSource.ACTION items (see PlanInvariant.source in plan.py), not stored separately as InvariantScope.ACTION invariants in the InvariantService.

Current Behavior

  • _SCOPE_PRECEDENCE in reconciliation.py defines 4 tiers: PLAN: 0, ACTION: 1, PROJECT: 2, GLOBAL: 3
  • ScopeInvariants has a separate action_invariants field
  • collect_invariants() queries InvariantScope.ACTION separately from plan invariants
  • The reconciliation algorithm treats action-scoped invariants as a distinct tier between plan and project

Code locations:

  • src/cleveragents/actor/reconciliation.py lines 40–47 (_SCOPE_PRECEDENCE)
  • src/cleveragents/actor/reconciliation.py lines 85–100 (ScopeInvariants)
  • src/cleveragents/actor/reconciliation.py lines 270–290 (collect_invariants)

Expected Behavior

  • Action invariants are promoted to plan-level when agents plan use is called
  • The reconciliation actor handles only 3 tiers: plan, project, global
  • There is no separate "action" tier in the reconciliation precedence chain
  • ScopeInvariants does not have a separate action_invariants field for reconciliation purposes

Steps to Reproduce

  1. Add an action-scoped invariant:
    service.add_invariant(text="test", scope=InvariantScope.ACTION, source_name="my-action")
    
  2. Add a project-scoped invariant with the same text:
    service.add_invariant(text="test", scope=InvariantScope.PROJECT, source_name="my-project")
    
  3. Run reconciliation:
    actor.run(plan_id="...", project_name="my-project", action_name="my-action")
    
  4. The action-scoped invariant wins over the project-scoped one (action rank=1 < project rank=2)
  5. Per spec, both should be treated as plan-level (since action invariants are promoted at plan use time), so the conflict resolution should be between plan-level and project-level

Supporting Information

  • What was tested: Code analysis of src/cleveragents/actor/reconciliation.py
  • Spec references: docs/specification.md line 92 and lines 19596–19604
  • Related model: PlanInvariant.source in plan.py (action invariants stored as plan-level with InvariantSource.ACTION)

Backlog note: This issue was discovered during autonomous operation
on milestone v3.2.0. It does not block milestone completion and has been
placed in the backlog for human review and future milestone assignment.

Subtasks

  • Remove action_invariants from ScopeInvariants or treat them as plan-level during reconciliation
  • Update _SCOPE_PRECEDENCE to reflect 3-tier chain (plan > project > global)
  • Update collect_invariants() to not query InvariantScope.ACTION separately
  • Update feature tests in features/invariant_reconciliation_actor.feature to reflect 3-tier behavior
  • Run nox (all default sessions), fix any errors

Definition of Done

This issue is complete when:

  • InvariantReconciliationActor implements 3-tier precedence: plan > project > global
  • Action invariants are treated as plan-level during reconciliation (not as a separate tier)
  • All existing tests updated and passing with the corrected 3-tier behavior
  • All nox stages pass
  • Coverage >= 97%
  • A Git commit is created where the first line of the commit message matches the Commit Message in Metadata exactly, followed by a blank line, then additional lines providing relevant details about the implementation
  • The commit is pushed to the remote on the branch matching the Branch in Metadata exactly
  • The commit is submitted as a pull request to master, reviewed, and merged before this issue is marked done

Automated by CleverAgents Bot
Supervisor: Acting on behalf of: UAT Testing | Agent: ca-new-issue-creator

## Metadata - **Branch**: `bugfix/invariant-reconciliation-3-tier-precedence` - **Commit Message**: `fix(reconciliation): enforce 3-tier invariant precedence chain per spec` - **Milestone**: *(none — backlog)* - **Parent Epic**: #374 ## Background and Context The `InvariantReconciliationActor` in `src/cleveragents/actor/reconciliation.py` implements a **4-tier** precedence chain: `plan > action > project > global`. However, the specification (`docs/specification.md` line 92 and lines 19596–19604) explicitly states: > "Action invariants are promoted to plan-level when the action is used, so the runtime precedence chain is three-tier: plan > project > global." And: > "Note: Action invariants are carried forward as plan-level invariants when the action is used (see Action invariants above), so they participate in precedence at the plan tier — there is no separate action tier in the precedence chain." The reconciliation actor's conflict resolution therefore produces incorrect results when action-scoped invariants conflict with project-scoped invariants. Per spec, action invariants should already be in the plan's invariant list as `InvariantSource.ACTION` items (see `PlanInvariant.source` in `plan.py`), not stored separately as `InvariantScope.ACTION` invariants in the `InvariantService`. ## Current Behavior - `_SCOPE_PRECEDENCE` in `reconciliation.py` defines 4 tiers: `PLAN: 0, ACTION: 1, PROJECT: 2, GLOBAL: 3` - `ScopeInvariants` has a separate `action_invariants` field - `collect_invariants()` queries `InvariantScope.ACTION` separately from plan invariants - The reconciliation algorithm treats action-scoped invariants as a distinct tier between plan and project **Code locations:** - `src/cleveragents/actor/reconciliation.py` lines 40–47 (`_SCOPE_PRECEDENCE`) - `src/cleveragents/actor/reconciliation.py` lines 85–100 (`ScopeInvariants`) - `src/cleveragents/actor/reconciliation.py` lines 270–290 (`collect_invariants`) ## Expected Behavior - Action invariants are promoted to plan-level when `agents plan use` is called - The reconciliation actor handles only 3 tiers: plan, project, global - There is **no** separate "action" tier in the reconciliation precedence chain - `ScopeInvariants` does not have a separate `action_invariants` field for reconciliation purposes ## Steps to Reproduce 1. Add an action-scoped invariant: ```python service.add_invariant(text="test", scope=InvariantScope.ACTION, source_name="my-action") ``` 2. Add a project-scoped invariant with the same text: ```python service.add_invariant(text="test", scope=InvariantScope.PROJECT, source_name="my-project") ``` 3. Run reconciliation: ```python actor.run(plan_id="...", project_name="my-project", action_name="my-action") ``` 4. The action-scoped invariant wins over the project-scoped one (action rank=1 < project rank=2) 5. **Per spec**, both should be treated as plan-level (since action invariants are promoted at `plan use` time), so the conflict resolution should be between plan-level and project-level ## Supporting Information - **What was tested**: Code analysis of `src/cleveragents/actor/reconciliation.py` - **Spec references**: `docs/specification.md` line 92 and lines 19596–19604 - **Related model**: `PlanInvariant.source` in `plan.py` (action invariants stored as plan-level with `InvariantSource.ACTION`) > **Backlog note:** This issue was discovered during autonomous operation > on milestone v3.2.0. It does not block milestone completion and has been > placed in the backlog for human review and future milestone assignment. ## Subtasks - [ ] Remove `action_invariants` from `ScopeInvariants` or treat them as plan-level during reconciliation - [ ] Update `_SCOPE_PRECEDENCE` to reflect 3-tier chain (plan > project > global) - [ ] Update `collect_invariants()` to not query `InvariantScope.ACTION` separately - [ ] Update feature tests in `features/invariant_reconciliation_actor.feature` to reflect 3-tier behavior - [ ] Run `nox` (all default sessions), fix any errors ## Definition of Done This issue is complete when: - [ ] `InvariantReconciliationActor` implements 3-tier precedence: plan > project > global - [ ] Action invariants are treated as plan-level during reconciliation (not as a separate tier) - [ ] All existing tests updated and passing with the corrected 3-tier behavior - [ ] All nox stages pass - [ ] Coverage >= 97% - [ ] A Git commit is created where the **first line** of the commit message matches the Commit Message in Metadata exactly, followed by a blank line, then additional lines providing relevant details about the implementation - [ ] The commit is pushed to the remote on the branch matching the **Branch** in Metadata exactly - [ ] The commit is submitted as a **pull request** to `master`, reviewed, and **merged** before this issue is marked done --- **Automated by CleverAgents Bot** Supervisor: Acting on behalf of: UAT Testing | Agent: ca-new-issue-creator
freemo added this to the v3.3.0 milestone 2026-04-05 20:04:17 +00:00
Author
Owner

Issue triaged by project owner:

  • State: Verified
  • Priority: Medium — The reconciliation actor implements a 4-tier precedence chain (plan > action > project > global) but the spec explicitly states a 3-tier chain (plan > project > global). Action invariants should be promoted to plan-level at plan use time. This causes incorrect conflict resolution when action-scoped and project-scoped invariants conflict.
  • Milestone: v3.3.0
  • Story Points: 3 — M — Requires restructuring the precedence chain, removing the action tier from ScopeInvariants, updating collect_invariants(), and updating feature tests.
  • MoSCoW: Should Have — Spec compliance for invariant reconciliation is important. The spec is explicit (lines 19596–19604) that there is no separate action tier. However, this only manifests when action and project invariants conflict on the same text, which may not be a common scenario in current usage.
  • Parent Epic: #374 (dependency link already exists)

Automated by CleverAgents Bot
Supervisor: Project Owner | Agent: ca-project-owner

Issue triaged by project owner: - **State**: Verified - **Priority**: Medium — The reconciliation actor implements a 4-tier precedence chain (plan > action > project > global) but the spec explicitly states a 3-tier chain (plan > project > global). Action invariants should be promoted to plan-level at `plan use` time. This causes incorrect conflict resolution when action-scoped and project-scoped invariants conflict. - **Milestone**: v3.3.0 - **Story Points**: 3 — M — Requires restructuring the precedence chain, removing the action tier from `ScopeInvariants`, updating `collect_invariants()`, and updating feature tests. - **MoSCoW**: Should Have — Spec compliance for invariant reconciliation is important. The spec is explicit (lines 19596–19604) that there is no separate action tier. However, this only manifests when action and project invariants conflict on the same text, which may not be a common scenario in current usage. - **Parent Epic**: #374 (dependency link already exists) --- **Automated by CleverAgents Bot** Supervisor: Project Owner | Agent: ca-project-owner
freemo removed this from the v3.3.0 milestone 2026-04-06 23:38:35 +00:00
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.

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