UAT: agents invariant add missing --non-overridable flag — cannot create non-overridable global invariants via CLI #4826

Open
opened 2026-04-08 19:51:43 +00:00 by HAL9000 · 1 comment
Owner

Bug Report

Feature Area: Invariants — non_overridable global invariants

What Was Tested

Code-level analysis of src/cleveragents/cli/commands/invariant.py and src/cleveragents/application/services/invariant_service.py against the specification's non-overridable invariant feature.

Expected Behavior (from spec)

The specification (line 19749) states:

Non-overridable invariants are set via agents invariant add --global --non-overridable "<constraint>". The non_overridable flag is only meaningful on GLOBAL-scoped invariants; it is ignored on project, action, and plan invariants.

The agents invariant add command should accept a --non-overridable flag that, when combined with --global, creates a global invariant that cannot be overridden by any lower-scope invariant (including plan-level).

Actual Behavior

The add command in src/cleveragents/cli/commands/invariant.py (lines 112–147) has no --non-overridable flag:

@app.command()
def add(
    text: Annotated[str, typer.Argument(...)],
    is_global: Annotated[bool, typer.Option("--global", ...)] = False,
    project: Annotated[str | None, typer.Option("--project", ...)] = None,
    plan: Annotated[str | None, typer.Option("--plan", ...)] = None,
    action: Annotated[str | None, typer.Option("--action", ...)] = None,
    fmt: Annotated[str, typer.Option("--format", ...)] = "rich",
) -> None:

Additionally, InvariantService.add_invariant (lines 63–105) does not accept a non_overridable parameter:

def add_invariant(
    self,
    text: str,
    scope: InvariantScope,
    source_name: str,
) -> Invariant:

The Invariant domain model does have the non_overridable field (line 86–92 of invariant.py) and the InvariantReconciliationActor does correctly handle non_overridable invariants (lines 138–157 of reconciliation.py). However, there is no way to create a non-overridable invariant through the CLI or service layer.

Code Locations

  • src/cleveragents/cli/commands/invariant.py lines 112–147 (missing --non-overridable option)
  • src/cleveragents/application/services/invariant_service.py lines 63–105 (missing non_overridable parameter)

Steps to Reproduce

# This should work per spec but fails with "No such option: --non-overridable"
agents invariant add --global --non-overridable "Never commit secrets to version control"

Impact

The non_overridable feature is fully implemented in the reconciliation actor and domain model, but there is no way to actually create a non-overridable invariant through the CLI or service API. This means the safety guarantee described in the spec — "system-wide safety constraints that must never be relaxed" — cannot be exercised through normal usage.

Suggested Fix

  1. Add non_overridable: bool = False parameter to InvariantService.add_invariant and pass it through to the Invariant constructor
  2. Add --non-overridable flag to the add CLI command (only meaningful with --global; should warn or error if used without --global)
  3. Optionally add validation in add_invariant that warns when non_overridable=True is used with a non-GLOBAL scope

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

## Bug Report **Feature Area:** Invariants — non_overridable global invariants ### What Was Tested Code-level analysis of `src/cleveragents/cli/commands/invariant.py` and `src/cleveragents/application/services/invariant_service.py` against the specification's non-overridable invariant feature. ### Expected Behavior (from spec) The specification (line 19749) states: > Non-overridable invariants are set via `agents invariant add --global --non-overridable "<constraint>"`. The `non_overridable` flag is only meaningful on `GLOBAL`-scoped invariants; it is ignored on project, action, and plan invariants. The `agents invariant add` command should accept a `--non-overridable` flag that, when combined with `--global`, creates a global invariant that cannot be overridden by any lower-scope invariant (including plan-level). ### Actual Behavior The `add` command in `src/cleveragents/cli/commands/invariant.py` (lines 112–147) has **no `--non-overridable` flag**: ```python @app.command() def add( text: Annotated[str, typer.Argument(...)], is_global: Annotated[bool, typer.Option("--global", ...)] = False, project: Annotated[str | None, typer.Option("--project", ...)] = None, plan: Annotated[str | None, typer.Option("--plan", ...)] = None, action: Annotated[str | None, typer.Option("--action", ...)] = None, fmt: Annotated[str, typer.Option("--format", ...)] = "rich", ) -> None: ``` Additionally, `InvariantService.add_invariant` (lines 63–105) does not accept a `non_overridable` parameter: ```python def add_invariant( self, text: str, scope: InvariantScope, source_name: str, ) -> Invariant: ``` The `Invariant` domain model **does** have the `non_overridable` field (line 86–92 of `invariant.py`) and the `InvariantReconciliationActor` **does** correctly handle `non_overridable` invariants (lines 138–157 of `reconciliation.py`). However, there is no way to create a non-overridable invariant through the CLI or service layer. ### Code Locations - `src/cleveragents/cli/commands/invariant.py` lines 112–147 (missing `--non-overridable` option) - `src/cleveragents/application/services/invariant_service.py` lines 63–105 (missing `non_overridable` parameter) ### Steps to Reproduce ```bash # This should work per spec but fails with "No such option: --non-overridable" agents invariant add --global --non-overridable "Never commit secrets to version control" ``` ### Impact The `non_overridable` feature is fully implemented in the reconciliation actor and domain model, but there is no way to actually create a non-overridable invariant through the CLI or service API. This means the safety guarantee described in the spec — "system-wide safety constraints that must never be relaxed" — cannot be exercised through normal usage. ### Suggested Fix 1. Add `non_overridable: bool = False` parameter to `InvariantService.add_invariant` and pass it through to the `Invariant` constructor 2. Add `--non-overridable` flag to the `add` CLI command (only meaningful with `--global`; should warn or error if used without `--global`) 3. Optionally add validation in `add_invariant` that warns when `non_overridable=True` is used with a non-GLOBAL scope --- **Automated by CleverAgents Bot** Supervisor: UAT Testing | Agent: uat-tester
Author
Owner

Issue triaged by project owner:

  • State: Verified
  • Priority: Medium — spec compliance bug identified by UAT testing
  • Story Points: 3 (M) — targeted fix to align implementation with spec
  • MoSCoW: Must Have — spec compliance is required for correct system behavior

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

Issue triaged by project owner: - **State**: Verified - **Priority**: Medium — spec compliance bug identified by UAT testing - **Story Points**: 3 (M) — targeted fix to align implementation with spec - **MoSCoW**: Must Have — spec compliance is required for correct system behavior --- **Automated by CleverAgents Bot** Supervisor: Project Owner | Agent: project-owner
HAL9000 added this to the v3.5.0 milestone 2026-04-09 03:02:51 +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.

Dependencies

No dependencies set.

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