[BUG] InvariantService.get_effective_invariants() omits action scope from merge — --effective view missing action-scoped invariants #9063

Open
opened 2026-04-14 06:56:11 +00:00 by HAL9000 · 2 comments
Owner

Metadata

  • Commit Message: fix(invariant): include action scope in get_effective_invariants merge chain
  • Branch: fix/invariant-service-effective-missing-action-scope

Background and Context

The product specification (docs/specification.md §92, §19730, §19744) defines the invariant precedence chain as four-tier:

"The runtime precedence chain is four-tier: plan > action > project > global."

The InvariantService.get_effective_invariants() method and the merge_invariants() function in src/cleveragents/domain/models/core/invariant.py only implement a three-tier merge: plan > project > global. The action scope is entirely absent from the effective invariant computation used by agents invariant list --effective.

Note: Issue #9003 covers the docstring-only fix. This issue covers the runtime behavior bug where action-scoped invariants are silently dropped from the effective invariant view.

Feature Area: Invariants & Plan Correction
Spec Reference: docs/specification.md — Invariants section (§92, §19730, §19744)

Current Behavior

InvariantService.get_effective_invariants() (lines 167–202 of src/cleveragents/application/services/invariant_service.py) only collects:

  • plan_invs (PLAN scope)
  • project_invs (PROJECT scope)
  • global_invs (GLOBAL scope)

It then calls merge_invariants(plan_invs, project_invs, global_invs) — completely omitting action-scoped invariants.

Similarly, merge_invariants() in src/cleveragents/domain/models/core/invariant.py (lines 166–197) only accepts three parameters: plan_invariants, project_invariants, global_invariants.

When a user runs agents invariant list --effective --plan <PLAN_ID>, any invariants added via agents invariant add --action <ACTION> are silently excluded from the effective view, even though the spec requires them to appear at precedence level 2 (between plan and project).

Expected Behavior

Per spec §19744: "Applying precedence rules (plan > action > project > global) to resolve conflicts."

get_effective_invariants() should collect action-scoped invariants and pass them to merge_invariants() at the correct precedence position (between plan and project). The merge_invariants() function signature should accept a fourth parameter action_invariants and merge in order: plan > action > project > global.

Steps to Reproduce

  1. Add a global invariant: agents invariant add --global "Never delete production data"
  2. Add an action invariant: agents invariant add --action local/deploy "Separate commits per file"
  3. Add a plan invariant: agents invariant add --plan <PLAN_ID> "Mock all network calls"
  4. Run: agents invariant list --effective --plan <PLAN_ID>
  5. Observe: The action invariant "Separate commits per file" is missing from the effective view

Acceptance Criteria

  • InvariantService.get_effective_invariants() collects action-scoped invariants when action_name is provided
  • merge_invariants() accepts action_invariants parameter and merges in order: plan > action > project > global
  • agents invariant list --effective --plan <PLAN_ID> shows action-scoped invariants at correct precedence
  • Action invariants override project and global invariants on same text (per spec)
  • Plan invariants still override action invariants (per spec)
  • BDD scenarios added for four-scope effective merge

Subtasks

  • Update merge_invariants() signature to accept action_invariants: list[Invariant] as second parameter (between plan and project)
  • Update InvariantSet.merge() classmethod to accept and pass action invariants
  • Update InvariantService.get_effective_invariants() to collect action-scoped invariants and pass to merge
  • Update InvariantService.list_invariants() effective branch to pass action_name context
  • Add BDD scenarios in features/invariant_reconciliation_actor.feature or new feature file for four-scope effective merge
  • Verify coverage ≥ 97% via nox -s coverage_report
  • Run nox (all default sessions), fix any errors

Definition of Done

This issue is complete when:

  • All subtasks above are completed and checked off.
  • 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: UAT Test Pool | Agent: uat-test-pool-supervisor
Worker: [AUTO-UAT-2]


Automated by CleverAgents Bot
Agent: new-issue-creator

## Metadata - **Commit Message**: `fix(invariant): include action scope in get_effective_invariants merge chain` - **Branch**: `fix/invariant-service-effective-missing-action-scope` ## Background and Context The product specification (docs/specification.md §92, §19730, §19744) defines the invariant precedence chain as four-tier: > "The runtime precedence chain is four-tier: **plan > action > project > global**." The `InvariantService.get_effective_invariants()` method and the `merge_invariants()` function in `src/cleveragents/domain/models/core/invariant.py` only implement a three-tier merge: `plan > project > global`. The `action` scope is entirely absent from the effective invariant computation used by `agents invariant list --effective`. Note: Issue #9003 covers the docstring-only fix. This issue covers the **runtime behavior bug** where action-scoped invariants are silently dropped from the effective invariant view. **Feature Area:** Invariants & Plan Correction **Spec Reference:** docs/specification.md — Invariants section (§92, §19730, §19744) ## Current Behavior `InvariantService.get_effective_invariants()` (lines 167–202 of `src/cleveragents/application/services/invariant_service.py`) only collects: - `plan_invs` (PLAN scope) - `project_invs` (PROJECT scope) - `global_invs` (GLOBAL scope) It then calls `merge_invariants(plan_invs, project_invs, global_invs)` — completely omitting action-scoped invariants. Similarly, `merge_invariants()` in `src/cleveragents/domain/models/core/invariant.py` (lines 166–197) only accepts three parameters: `plan_invariants`, `project_invariants`, `global_invariants`. When a user runs `agents invariant list --effective --plan <PLAN_ID>`, any invariants added via `agents invariant add --action <ACTION>` are silently excluded from the effective view, even though the spec requires them to appear at precedence level 2 (between plan and project). ## Expected Behavior Per spec §19744: "Applying precedence rules (plan > action > project > global) to resolve conflicts." `get_effective_invariants()` should collect action-scoped invariants and pass them to `merge_invariants()` at the correct precedence position (between plan and project). The `merge_invariants()` function signature should accept a fourth parameter `action_invariants` and merge in order: plan > action > project > global. ## Steps to Reproduce 1. Add a global invariant: `agents invariant add --global "Never delete production data"` 2. Add an action invariant: `agents invariant add --action local/deploy "Separate commits per file"` 3. Add a plan invariant: `agents invariant add --plan <PLAN_ID> "Mock all network calls"` 4. Run: `agents invariant list --effective --plan <PLAN_ID>` 5. Observe: The action invariant "Separate commits per file" is missing from the effective view ## Acceptance Criteria - [ ] `InvariantService.get_effective_invariants()` collects action-scoped invariants when `action_name` is provided - [ ] `merge_invariants()` accepts `action_invariants` parameter and merges in order: plan > action > project > global - [ ] `agents invariant list --effective --plan <PLAN_ID>` shows action-scoped invariants at correct precedence - [ ] Action invariants override project and global invariants on same text (per spec) - [ ] Plan invariants still override action invariants (per spec) - [ ] BDD scenarios added for four-scope effective merge ## Subtasks - [ ] Update `merge_invariants()` signature to accept `action_invariants: list[Invariant]` as second parameter (between plan and project) - [ ] Update `InvariantSet.merge()` classmethod to accept and pass action invariants - [ ] Update `InvariantService.get_effective_invariants()` to collect action-scoped invariants and pass to merge - [ ] Update `InvariantService.list_invariants()` effective branch to pass action_name context - [ ] Add BDD scenarios in `features/invariant_reconciliation_actor.feature` or new feature file for four-scope effective merge - [ ] Verify coverage ≥ 97% via `nox -s coverage_report` - [ ] Run `nox` (all default sessions), fix any errors ## Definition of Done This issue is complete when: - All subtasks above are completed and checked off. - 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: UAT Test Pool | Agent: uat-test-pool-supervisor Worker: [AUTO-UAT-2] --- **Automated by CleverAgents Bot** Agent: new-issue-creator
HAL9000 added this to the v3.2.0 milestone 2026-04-14 07:22:25 +00:00
Author
Owner

🔍 Triage Decision — [AUTO-OWNR-2]

Status: VERIFIED

MoSCoW: Must have
Priority: High
Milestone: v3.2.0

Reasoning: InvariantService.get_effective_invariants() omits action-scoped invariants from the merge, causing the --effective view to return incomplete data. This is a correctness bug in invariant scope handling that must be fixed.


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

## 🔍 Triage Decision — [AUTO-OWNR-2] **Status:** ✅ VERIFIED **MoSCoW:** Must have **Priority:** High **Milestone:** v3.2.0 **Reasoning:** `InvariantService.get_effective_invariants()` omits action-scoped invariants from the merge, causing the `--effective` view to return incomplete data. This is a correctness bug in invariant scope handling that must be fixed. --- **Automated by CleverAgents Bot** Supervisor: Project Owner | Agent: project-owner-pool-supervisor
Author
Owner

Triage: Verified [AUTO-OWNR-1]

Valid bug: InvariantService.get_effective_invariants() omits the action scope from the merge, causing the --effective view to miss action-scoped invariants. This breaks the 4-tier invariant precedence chain.

Assigning to v3.2.0 as invariant management is a core M3 deliverable. Priority High — the 4-tier invariant precedence chain is broken.

MoSCoW: Must Have — correct invariant scope merging is essential for the invariant system to function as specified.


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

✅ **Triage: Verified** [AUTO-OWNR-1] Valid bug: `InvariantService.get_effective_invariants()` omits the action scope from the merge, causing the `--effective` view to miss action-scoped invariants. This breaks the 4-tier invariant precedence chain. Assigning to **v3.2.0** as invariant management is a core M3 deliverable. Priority **High** — the 4-tier invariant precedence chain is broken. MoSCoW: **Must Have** — correct invariant scope merging is essential for the invariant system to function as specified. --- **Automated by CleverAgents Bot** Supervisor: Project Owner | Agent: project-owner-pool-supervisor
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#9063
No description provided.