UAT: Action invariants stored as InvariantSource.ACTION instead of being promoted to PLAN scope at plan use time — spec requires three-tier precedence #4000

Open
opened 2026-04-06 08:26:55 +00:00 by freemo · 0 comments
Owner

Metadata

  • Branch: fix/backlog-invariant-action-promotion-to-plan-scope
  • Commit Message: fix(invariant): promote action invariants to PLAN scope at plan use time
  • Milestone: None (Backlog)
  • Parent Epic: #3370

Summary

The specification states: "Action invariants are promoted to plan-level when the action is used, so the runtime precedence chain is three-tier: plan > project > global." However, the implementation stores action invariants with InvariantSource.ACTION (a separate fourth tier) rather than promoting them to InvariantSource.PLAN scope at plan use time.

The InvariantReconciliationActor uses a four-tier precedence (PLAN > ACTION > PROJECT > GLOBAL) instead of the spec-required three-tier chain (plan > project > global).

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

Current Behavior

In src/cleveragents/application/services/plan_lifecycle_service.py, the use_action() method (lines 1021-1025) adds action invariants with InvariantSource.ACTION:

# Build merged invariants: plan > action > (project/global added later)
merged_invariants: list[PlanInvariant] = list(invariants or [])
for inv_text in action.invariants:
    merged_invariants.append(
        PlanInvariant(text=inv_text, source=InvariantSource.ACTION)
    )

The InvariantReconciliationActor in src/cleveragents/actor/reconciliation.py uses a four-tier precedence:

_SCOPE_PRECEDENCE: dict[InvariantScope, int] = {
    InvariantScope.PLAN: 0,
    InvariantScope.ACTION: 1,
    InvariantScope.PROJECT: 2,
    InvariantScope.GLOBAL: 3,
}

This creates a four-tier system (PLAN > ACTION > PROJECT > GLOBAL) instead of the spec-required three-tier system (plan > project > global).

Expected Behavior

Per spec (Glossary, Invariant definition): "Action invariants are promoted to plan-level when the action is used, so the runtime precedence chain is three-tier: plan > project > global."

When agents plan use <action> <project> is called:

  1. Action invariants should be stored with InvariantSource.PLAN (not InvariantSource.ACTION)
  2. The runtime precedence chain should be three-tier: plan > project > global
  3. The InvariantReconciliationActor should not need a separate ACTION tier

Steps to Reproduce

  1. Create an action with invariants: agents action create --config action.yaml (where action.yaml includes invariants)
  2. Use the action: agents plan use local/my-action local/my-project
  3. Check the plan's invariants: agents plan status <PLAN_ID> --format json
  4. Observe: Invariants show "source": "action" instead of "source": "plan"
  5. Expected: Invariants show "source": "plan" (promoted at use time)

Code Locations

  • File: src/cleveragents/application/services/plan_lifecycle_service.py

    • Function: use_action() (lines 1021-1025)
    • Fix: Change InvariantSource.ACTION to InvariantSource.PLAN when adding action invariants to the plan
  • File: src/cleveragents/actor/reconciliation.py

    • Variable: _SCOPE_PRECEDENCE (lines 43-48)
    • Fix: Remove InvariantScope.ACTION from the precedence dict (or keep it as equal to PLAN for backward compatibility)
  • File: src/cleveragents/domain/models/core/plan.py

    • Class: InvariantSource (lines 176-183)
    • Note: The ACTION value may need to be kept for provenance tracking but should not affect runtime precedence

Subtasks

  • Update use_action() to store action invariants with InvariantSource.PLAN (or a new InvariantSource.ACTION_PROMOTED value)
  • Update InvariantReconciliationActor._SCOPE_PRECEDENCE to use three-tier precedence
  • Update merge_invariants() in src/cleveragents/domain/models/core/invariant.py to reflect three-tier semantics
  • Add Behave BDD test verifying action invariants are promoted to plan scope at plan use time
  • Verify existing reconciliation tests still pass

Definition of Done

  • Action invariants stored with PLAN scope (or equivalent) after plan use
  • Runtime precedence chain is three-tier: plan > project > global
  • InvariantReconciliationActor correctly handles the three-tier chain
  • Unit tests verify promotion behavior
  • Code passes nox -e typecheck and nox -e unit_tests
  • All nox stages pass
  • Coverage >= 97%

Automated by CleverAgents Bot
Supervisor: UAT Testing | Agent: ca-uat-tester


Automated by CleverAgents Bot
Supervisor: UAT Testing | Agent: ca-new-issue-creator

## Metadata - **Branch**: `fix/backlog-invariant-action-promotion-to-plan-scope` - **Commit Message**: `fix(invariant): promote action invariants to PLAN scope at plan use time` - **Milestone**: None (Backlog) - **Parent Epic**: #3370 ## Summary The specification states: "Action invariants are promoted to plan-level when the action is used, so the runtime precedence chain is three-tier: **plan > project > global**." However, the implementation stores action invariants with `InvariantSource.ACTION` (a separate fourth tier) rather than promoting them to `InvariantSource.PLAN` scope at `plan use` time. The `InvariantReconciliationActor` uses a four-tier precedence (PLAN > ACTION > PROJECT > GLOBAL) instead of the spec-required three-tier chain (plan > project > global). > **Backlog note:** This issue was discovered during autonomous UAT operation. It does not block milestone completion and has been placed in the backlog for human review and future milestone assignment. ## Current Behavior In `src/cleveragents/application/services/plan_lifecycle_service.py`, the `use_action()` method (lines 1021-1025) adds action invariants with `InvariantSource.ACTION`: ```python # Build merged invariants: plan > action > (project/global added later) merged_invariants: list[PlanInvariant] = list(invariants or []) for inv_text in action.invariants: merged_invariants.append( PlanInvariant(text=inv_text, source=InvariantSource.ACTION) ) ``` The `InvariantReconciliationActor` in `src/cleveragents/actor/reconciliation.py` uses a four-tier precedence: ```python _SCOPE_PRECEDENCE: dict[InvariantScope, int] = { InvariantScope.PLAN: 0, InvariantScope.ACTION: 1, InvariantScope.PROJECT: 2, InvariantScope.GLOBAL: 3, } ``` This creates a four-tier system (PLAN > ACTION > PROJECT > GLOBAL) instead of the spec-required three-tier system (plan > project > global). ## Expected Behavior Per spec (Glossary, Invariant definition): "Action invariants are promoted to plan-level when the action is used, so the runtime precedence chain is three-tier: plan > project > global." When `agents plan use <action> <project>` is called: 1. Action invariants should be stored with `InvariantSource.PLAN` (not `InvariantSource.ACTION`) 2. The runtime precedence chain should be three-tier: plan > project > global 3. The `InvariantReconciliationActor` should not need a separate ACTION tier ## Steps to Reproduce 1. Create an action with invariants: `agents action create --config action.yaml` (where action.yaml includes invariants) 2. Use the action: `agents plan use local/my-action local/my-project` 3. Check the plan's invariants: `agents plan status <PLAN_ID> --format json` 4. Observe: Invariants show `"source": "action"` instead of `"source": "plan"` 5. Expected: Invariants show `"source": "plan"` (promoted at use time) ## Code Locations - **File**: `src/cleveragents/application/services/plan_lifecycle_service.py` - **Function**: `use_action()` (lines 1021-1025) - **Fix**: Change `InvariantSource.ACTION` to `InvariantSource.PLAN` when adding action invariants to the plan - **File**: `src/cleveragents/actor/reconciliation.py` - **Variable**: `_SCOPE_PRECEDENCE` (lines 43-48) - **Fix**: Remove `InvariantScope.ACTION` from the precedence dict (or keep it as equal to PLAN for backward compatibility) - **File**: `src/cleveragents/domain/models/core/plan.py` - **Class**: `InvariantSource` (lines 176-183) - **Note**: The `ACTION` value may need to be kept for provenance tracking but should not affect runtime precedence ## Subtasks - [ ] Update `use_action()` to store action invariants with `InvariantSource.PLAN` (or a new `InvariantSource.ACTION_PROMOTED` value) - [ ] Update `InvariantReconciliationActor._SCOPE_PRECEDENCE` to use three-tier precedence - [ ] Update `merge_invariants()` in `src/cleveragents/domain/models/core/invariant.py` to reflect three-tier semantics - [ ] Add Behave BDD test verifying action invariants are promoted to plan scope at `plan use` time - [ ] Verify existing reconciliation tests still pass ## Definition of Done - [ ] Action invariants stored with PLAN scope (or equivalent) after `plan use` - [ ] Runtime precedence chain is three-tier: plan > project > global - [ ] `InvariantReconciliationActor` correctly handles the three-tier chain - [ ] Unit tests verify promotion behavior - [ ] Code passes `nox -e typecheck` and `nox -e unit_tests` - [ ] All nox stages pass - [ ] Coverage >= 97% --- **Automated by CleverAgents Bot** Supervisor: UAT Testing | Agent: ca-uat-tester --- **Automated by CleverAgents Bot** Supervisor: UAT Testing | Agent: ca-new-issue-creator
HAL9000 added this to the v3.5.0 milestone 2026-04-09 03:12:11 +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#4000
No description provided.