fix(cli): preserve no-flag list_invariants "all scopes" semantics
CI / load-versions (pull_request) Successful in 31s
CI / push-validation (pull_request) Successful in 37s
CI / lint (pull_request) Successful in 44s
CI / typecheck (pull_request) Successful in 1m10s
CI / security (pull_request) Successful in 1m24s
CI / build (pull_request) Successful in 36s
CI / quality (pull_request) Successful in 1m22s
CI / helm (pull_request) Successful in 2m7s
CI / unit_tests (pull_request) Successful in 7m55s
CI / docker (pull_request) Successful in 2m54s
CI / integration_tests (pull_request) Successful in 12m23s
CI / coverage (pull_request) Successful in 14m4s
CI / status-check (pull_request) Successful in 3s

The previous refactor routed list_invariants through _resolve_scope,
which silently changed the no-flags behavior: _resolve_scope returns
(GLOBAL, "system") when no flag is given (the `add` default), so
`agents invariant list` filtered to only global+system invariants
instead of returning every active invariant.

InvariantService.list_invariants documents scope=None / source_name=None
as "all scopes" / "all sources"; the listing CLI must preserve that
contract. Inline the mutual-exclusion check in list_invariants and
restore the if/elif chain that leaves scope/source_name=None when no
flag is set, while keeping `agents invariant add` defaulting to global.

Tests added:
- "List invariants with no flags passes no scope filter" verifies the
  service is called with scope=None, source_name=None.
- "List invariants with conflicting scope flags rejected" covers the
  new BadParameter raise path.

ISSUES CLOSED: #11049
This commit is contained in:
2026-06-18 01:13:39 -04:00
committed by Forgejo
parent 875dce304e
commit c7a20eccd0
3 changed files with 49 additions and 2 deletions
@@ -146,6 +146,17 @@ Feature: Invariant CLI commands coverage
Then the invariant CLI exit code should be 0
And the invariant CLI output should contain "Never delete prod"
Scenario: List invariants with no flags passes no scope filter
Given a mocked InvariantService that returns two invariants for list
When I invoke invariant list with no filters
Then the invariant CLI exit code should be 0
And the invariant service list was called with no scope filter
Scenario: List invariants with conflicting scope flags rejected
Given a mocked InvariantService that returns two invariants for list
When I invoke invariant list with flags "--global --project myapp"
Then the invariant CLI exit code should be non-zero
# === invariant remove command ===
Scenario: Remove invariant with --yes flag
@@ -332,6 +332,19 @@ def step_check_list_effective(context):
assert kwargs.get("effective") is True
@then("the invariant service list was called with no scope filter")
def step_check_list_no_scope(context):
call_kwargs = context.inv_mock_svc.list_invariants.call_args
assert call_kwargs is not None, "list_invariants was never called"
kwargs = call_kwargs[1] if call_kwargs[1] else {}
assert kwargs.get("scope") is None, (
f"Expected scope=None (all scopes), got {kwargs.get('scope')!r}"
)
assert kwargs.get("source_name") is None, (
f"Expected source_name=None, got {kwargs.get('source_name')!r}"
)
# ================================================================
# invariant remove command steps
# ================================================================