fix(invariant): InvariantSet.merge() missing action-scope parameter — only handles 3-tier instead of 4-tier precedence #3066

Open
opened 2026-04-05 04:51:37 +00:00 by freemo · 7 comments
Owner

Bug: InvariantSet.merge() Missing Action Scope

Description

The InvariantSet.merge() class method in src/cleveragents/domain/models/core/invariant.py (lines 130–155) only accepts three parameters — plan_invariants, project_invariants, global_invariants — and implements a 3-tier merge (plan > project > global). It is missing the action_invariants parameter.

This contradicts:

  1. ADR-016 which defines a 4-tier precedence chain: plan > action > project > global
  2. The InvariantReconciliationActor in actor/reconciliation.py which correctly handles all 4 scopes
  3. The InvariantScope enum which includes ACTION = "action" as a distinct scope

Current Code

# domain/models/core/invariant.py lines 130-155
@classmethod
def merge(
    cls,
    plan_invariants: list[Invariant],
    project_invariants: list[Invariant],
    global_invariants: list[Invariant],  # ← missing action_invariants!
) -> InvariantSet:
    """Merge invariants respecting plan > project > global precedence."""
    ...

Expected Fix

@classmethod
def merge(
    cls,
    plan_invariants: list[Invariant],
    action_invariants: list[Invariant],
    project_invariants: list[Invariant],
    global_invariants: list[Invariant],
) -> InvariantSet:
    """Merge invariants respecting plan > action > project > global precedence."""
    ...

The merge_invariants() standalone function (lines 160–191) has the same issue — it only accepts 3 parameters.

Impact

Any code calling InvariantSet.merge() directly (rather than using InvariantReconciliationActor) will silently drop action-scoped invariants from the effective invariant set. This is a correctness bug.

Spec Reference

  • ADR-016 (Invariant System), line 71: "Invariant precedence (plan > action > project > global) is fixed and cannot be overridden."
  • Spec line 18977: "The plan's automation profile is resolved (plan > action > project > global precedence)"

Definition of Done

  • InvariantSet.merge() accepts action_invariants parameter in the correct position (between plan and project)
  • merge_invariants() standalone function updated to match
  • All callers of InvariantSet.merge() and merge_invariants() updated
  • BDD scenarios updated to cover 4-tier merge
  • Docstrings corrected to say plan > action > project > global
  • PR merged and CI green

Automated by CleverAgents Bot
Supervisor: Spec Evolution | Agent: ca-spec-updater

## Bug: `InvariantSet.merge()` Missing Action Scope ### Description The `InvariantSet.merge()` class method in `src/cleveragents/domain/models/core/invariant.py` (lines 130–155) only accepts three parameters — `plan_invariants`, `project_invariants`, `global_invariants` — and implements a 3-tier merge (`plan > project > global`). It is missing the `action_invariants` parameter. This contradicts: 1. **ADR-016** which defines a 4-tier precedence chain: `plan > action > project > global` 2. **The `InvariantReconciliationActor`** in `actor/reconciliation.py` which correctly handles all 4 scopes 3. **The `InvariantScope` enum** which includes `ACTION = "action"` as a distinct scope ### Current Code ```python # domain/models/core/invariant.py lines 130-155 @classmethod def merge( cls, plan_invariants: list[Invariant], project_invariants: list[Invariant], global_invariants: list[Invariant], # ← missing action_invariants! ) -> InvariantSet: """Merge invariants respecting plan > project > global precedence.""" ... ``` ### Expected Fix ```python @classmethod def merge( cls, plan_invariants: list[Invariant], action_invariants: list[Invariant], project_invariants: list[Invariant], global_invariants: list[Invariant], ) -> InvariantSet: """Merge invariants respecting plan > action > project > global precedence.""" ... ``` The `merge_invariants()` standalone function (lines 160–191) has the same issue — it only accepts 3 parameters. ### Impact Any code calling `InvariantSet.merge()` directly (rather than using `InvariantReconciliationActor`) will silently drop action-scoped invariants from the effective invariant set. This is a correctness bug. ### Spec Reference - ADR-016 (Invariant System), line 71: "Invariant precedence (plan > action > project > global) is fixed and cannot be overridden." - Spec line 18977: "The plan's automation profile is resolved (plan > action > project > global precedence)" ### Definition of Done - [x] `InvariantSet.merge()` accepts `action_invariants` parameter in the correct position (between plan and project) - [x] `merge_invariants()` standalone function updated to match - [x] All callers of `InvariantSet.merge()` and `merge_invariants()` updated - [x] BDD scenarios updated to cover 4-tier merge - [x] Docstrings corrected to say `plan > action > project > global` - [ ] PR merged and CI green --- **Automated by CleverAgents Bot** Supervisor: Spec Evolution | Agent: ca-spec-updater
Author
Owner

Transition plan executed:

  • Precondition checks: none required (current state: State/Unverified; no Blocked/Paused blocker present).
  • Remove old state labels: removing all existing State/* labels (found: State/Unverified).
  • Add new state label: State/Verified.

Notes:

  • This transition follows the 4-tier precedence (plan > action > project > global) per ADR-016 as the action scope will be introduced to the invariant merge logic.
  • If there are any blockers or preconditions fail in the future, I will stop and report accordingly.

Automated by CleverAgents Bot
Supervisor: Implementation | Agent: ca-issue-state-updater

Transition plan executed: - Precondition checks: none required (current state: State/Unverified; no Blocked/Paused blocker present). - Remove old state labels: removing all existing State/* labels (found: State/Unverified). - Add new state label: State/Verified. Notes: - This transition follows the 4-tier precedence (plan > action > project > global) per ADR-016 as the action scope will be introduced to the invariant merge logic. - If there are any blockers or preconditions fail in the future, I will stop and report accordingly. --- **Automated by CleverAgents Bot** Supervisor: Implementation | Agent: ca-issue-state-updater
freemo added this to the v3.5.0 milestone 2026-04-05 06:18:03 +00:00
Author
Owner

Issue triaged by project owner:

  • State: Verified
  • Priority: High — correctness bug violating ADR-016's mandatory 4-tier invariant precedence chain (plan > action > project > global)
  • Milestone: v3.5.0 (Autonomy Hardening)
  • MoSCoW: Must Have — the specification (ADR-016, line 71) states "Invariant precedence (plan > action > project > global) is fixed and cannot be overridden." This is a MUST requirement. The current 3-tier implementation silently drops action-scoped invariants, which is a correctness violation.
  • Parent Epic: #394 (Decision Framework)

Spec references:

  • ADR-016 (Invariant System), line 71: 4-tier precedence is mandatory
  • Spec line 18977: "The plan's automation profile is resolved (plan > action > project > global precedence)"
  • v3.5.0 acceptance criteria: "Automation profile resolution precedence correct (plan > action > global)"

This issue is closely related to #3064 (spec update proposal for the same inconsistency). The code fix here should land first, then the spec update.


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

Issue triaged by project owner: - **State**: Verified - **Priority**: High — correctness bug violating ADR-016's mandatory 4-tier invariant precedence chain (`plan > action > project > global`) - **Milestone**: v3.5.0 (Autonomy Hardening) - **MoSCoW**: Must Have — the specification (ADR-016, line 71) states "Invariant precedence (plan > action > project > global) is fixed and cannot be overridden." This is a MUST requirement. The current 3-tier implementation silently drops action-scoped invariants, which is a correctness violation. - **Parent Epic**: #394 (Decision Framework) **Spec references:** - ADR-016 (Invariant System), line 71: 4-tier precedence is mandatory - Spec line 18977: "The plan's automation profile is resolved (plan > action > project > global precedence)" - v3.5.0 acceptance criteria: "Automation profile resolution precedence correct (plan > action > global)" This issue is closely related to #3064 (spec update proposal for the same inconsistency). The code fix here should land first, then the spec update. --- **Automated by CleverAgents Bot** Supervisor: Project Owner | Agent: ca-project-owner
Author
Owner

Transition Forgejo issue #3066: State transition to In Progress.

Precondition check:

  • Issue is not paused or blocked. No blocker handling required.

Actions:

  • Removed old state label: State/Verified
  • Added new state label: State/In Progress

Status: Transition completed per the requested target state.

If any automatic label removal encountered transient errors, please retry the operation.


Automated by CleverAgents Bot
Supervisor: Implementation | Agent: ca-issue-state-updater

Transition Forgejo issue #3066: State transition to In Progress. Precondition check: - Issue is not paused or blocked. No blocker handling required. Actions: - Removed old state label: State/Verified - Added new state label: State/In Progress Status: Transition completed per the requested target state. If any automatic label removal encountered transient errors, please retry the operation. --- **Automated by CleverAgents Bot** Supervisor: Implementation | Agent: ca-issue-state-updater
Author
Owner

Starting implementation on branch fix/invariant-set-merge-action-scope.

Analysis complete:

  • Bug confirmed: InvariantSet.merge() and merge_invariants() in src/cleveragents/domain/models/core/invariant.py only handle 3-tier precedence (plan > project > global), missing the action tier
  • 4-tier order: plan > action > project > global per ADR-016
  • Callers to update: invariant_service.py (get_effective_invariants), invariant_models_steps.py (BDD steps), invariant_merge_bench.py (benchmarks)
  • BDD scenarios: Need new scenarios for 4-tier merge coverage

Difficulty assessment: Low → starting at sonnet tier.


Automated by CleverAgents Bot
Supervisor: Implementation | Agent: ca-issue-worker

Starting implementation on branch `fix/invariant-set-merge-action-scope`. Analysis complete: - **Bug confirmed**: `InvariantSet.merge()` and `merge_invariants()` in `src/cleveragents/domain/models/core/invariant.py` only handle 3-tier precedence (`plan > project > global`), missing the `action` tier - **4-tier order**: `plan > action > project > global` per ADR-016 - **Callers to update**: `invariant_service.py` (get_effective_invariants), `invariant_models_steps.py` (BDD steps), `invariant_merge_bench.py` (benchmarks) - **BDD scenarios**: Need new scenarios for 4-tier merge coverage Difficulty assessment: Low → starting at sonnet tier. --- **Automated by CleverAgents Bot** Supervisor: Implementation | Agent: ca-issue-worker
Author
Owner

All subtasks complete. Quality gates passed. PR #3269 created on branch fix/invariant-set-merge-action-scope.

Implementation summary:

  • InvariantSet.merge() now accepts action_invariants parameter in the correct position (between plan and project)
  • merge_invariants() standalone function updated to match
  • All callers updated: InvariantService.get_effective_invariants(), BDD steps, benchmarks, robot E2E helper
  • BDD scenarios updated to cover 4-tier merge (3 new scenarios added)
  • Docstrings corrected to say plan > action > project > global
  • Lint (ruff): pass | Typecheck (pyright): 0 errors | Security scan: pass | Dead code: pass

PR review and merge handled by continuous review stream.


Automated by CleverAgents Bot
Supervisor: Implementation | Agent: ca-issue-worker

All subtasks complete. Quality gates passed. PR #3269 created on branch `fix/invariant-set-merge-action-scope`. **Implementation summary:** - ✅ `InvariantSet.merge()` now accepts `action_invariants` parameter in the correct position (between plan and project) - ✅ `merge_invariants()` standalone function updated to match - ✅ All callers updated: `InvariantService.get_effective_invariants()`, BDD steps, benchmarks, robot E2E helper - ✅ BDD scenarios updated to cover 4-tier merge (3 new scenarios added) - ✅ Docstrings corrected to say `plan > action > project > global` - ✅ Lint (ruff): pass | Typecheck (pyright): 0 errors | Security scan: pass | Dead code: pass PR review and merge handled by continuous review stream. --- **Automated by CleverAgents Bot** Supervisor: Implementation | Agent: ca-issue-worker
Author
Owner

Label compliance fix applied:

  • Added missing labels: Type/Bug, Priority/Backlog
  • Reason: Issue had State/In Review but was missing required Type/* and Priority/* labels per CONTRIBUTING.md

Automated by CleverAgents Bot
Supervisor: Backlog Grooming | Agent: ca-backlog-groomer

Label compliance fix applied: - Added missing labels: `Type/Bug`, `Priority/Backlog` - Reason: Issue had `State/In Review` but was missing required `Type/*` and `Priority/*` labels per CONTRIBUTING.md --- **Automated by CleverAgents Bot** Supervisor: Backlog Grooming | Agent: ca-backlog-groomer
freemo removed this from the v3.5.0 milestone 2026-04-06 22:41:04 +00:00
Author
Owner

This issue has been moved to the backlog as part of an aggressive grooming of the v3.5.0 milestone. It has been deemed non-critical for the minimal viability of the milestone and will be addressed in a future release.

This issue has been moved to the backlog as part of an aggressive grooming of the v3.5.0 milestone. It has been deemed non-critical for the minimal viability of the milestone and will be addressed in a future release.
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.

Blocks
#394 Epic: Decision Framework
cleveragents/cleveragents-core
Reference
cleveragents/cleveragents-core#3066
No description provided.