fix(cli): require at least one scope flag for invariant add per spec
CI / lint (pull_request) Successful in 34s
CI / security (pull_request) Successful in 51s
CI / typecheck (pull_request) Successful in 54s
CI / quality (pull_request) Successful in 28s
CI / build (pull_request) Successful in 27s
CI / helm (pull_request) Successful in 36s
CI / push-validation (pull_request) Successful in 23s
CI / integration_tests (pull_request) Successful in 4m25s
CI / e2e_tests (pull_request) Successful in 4m22s
CI / unit_tests (pull_request) Successful in 5m32s
CI / docker (pull_request) Successful in 1m19s
CI / coverage (pull_request) Successful in 11m20s
CI / status-check (pull_request) Successful in 1s
CI / lint (pull_request) Successful in 34s
CI / security (pull_request) Successful in 51s
CI / typecheck (pull_request) Successful in 54s
CI / quality (pull_request) Successful in 28s
CI / build (pull_request) Successful in 27s
CI / helm (pull_request) Successful in 36s
CI / push-validation (pull_request) Successful in 23s
CI / integration_tests (pull_request) Successful in 4m25s
CI / e2e_tests (pull_request) Successful in 4m22s
CI / unit_tests (pull_request) Successful in 5m32s
CI / docker (pull_request) Successful in 1m19s
CI / coverage (pull_request) Successful in 11m20s
CI / status-check (pull_request) Successful in 1s
The invariant add command was silently defaulting to global scope when no scope flag was provided, violating the specification which requires at least one scope flag (--global, --project, --plan, or --action). This fix: - Updates _resolve_scope() to raise typer.BadParameter when no flags are set - Updates the docstring to reflect the requirement - Adds a new BDD scenario to test the missing scope flag error - Updates the existing scenario that expected default to global behavior
This commit is contained in:
@@ -25,10 +25,9 @@ Feature: Invariant CLI commands coverage
|
||||
Then the resolved invariant scope should be "action"
|
||||
And the resolved invariant source name should be "deploy-service"
|
||||
|
||||
Scenario: Resolve scope with no flags defaults to GLOBAL
|
||||
Scenario: Resolve scope with no flags raises BadParameter
|
||||
When I resolve invariant scope with no flags
|
||||
Then the resolved invariant scope should be "global"
|
||||
And the resolved invariant source name should be "system"
|
||||
Then a BadParameter error should be raised for invariant scope
|
||||
|
||||
Scenario: Resolve scope with conflicting flags raises BadParameter
|
||||
When I resolve invariant scope with global and project flags
|
||||
@@ -71,6 +70,12 @@ Feature: Invariant CLI commands coverage
|
||||
Then the invariant CLI exit code should be 0
|
||||
And the invariant CLI output should contain "JSON constraint"
|
||||
|
||||
Scenario: Add invariant without scope flag raises error
|
||||
Given a mocked InvariantService for invariant CLI add
|
||||
When I invoke invariant add with no scope flags and text "Missing scope"
|
||||
Then the invariant CLI exit code should be non-zero
|
||||
And the invariant CLI output should contain "At least one scope flag is required"
|
||||
|
||||
Scenario: Add invariant handles CleverAgentsError
|
||||
Given a mocked InvariantService that raises CleverAgentsError on add
|
||||
When I invoke invariant add with "--global" and text "will fail"
|
||||
|
||||
@@ -91,9 +91,13 @@ def step_resolve_scope_action(context, action):
|
||||
|
||||
@when("I resolve invariant scope with no flags")
|
||||
def step_resolve_scope_default(context):
|
||||
context.resolved_scope, context.resolved_source = _resolve_scope(
|
||||
is_global=False, project=None, plan=None, action=None
|
||||
)
|
||||
context.inv_bad_parameter_raised = False
|
||||
try:
|
||||
context.resolved_scope, context.resolved_source = _resolve_scope(
|
||||
is_global=False, project=None, plan=None, action=None
|
||||
)
|
||||
except typer.BadParameter:
|
||||
context.inv_bad_parameter_raised = True
|
||||
|
||||
|
||||
@when("I resolve invariant scope with global and project flags")
|
||||
@@ -214,6 +218,12 @@ def step_run_add(context, flags, text):
|
||||
context.inv_result = _runner.invoke(app, args)
|
||||
|
||||
|
||||
@when('I invoke invariant add with no scope flags and text "{text}"')
|
||||
def step_run_add_no_scope(context, text):
|
||||
args = ["add", text]
|
||||
context.inv_result = _runner.invoke(app, args)
|
||||
|
||||
|
||||
@then("the invariant CLI exit code should be 0")
|
||||
def step_check_exit_zero(context):
|
||||
assert context.inv_result.exit_code == 0, (
|
||||
|
||||
@@ -20,7 +20,7 @@ Each invariant belongs to exactly one scope. Pass the matching flag:
|
||||
- ``--action ACTION``: Action-template invariant
|
||||
- ``--plan PLAN_ID``: Plan-specific invariant
|
||||
|
||||
If no scope flag is given, ``--global`` is assumed.
|
||||
At least one scope flag must be provided.
|
||||
|
||||
## Examples
|
||||
|
||||
@@ -86,6 +86,12 @@ def _resolve_scope(
|
||||
"Specify at most one scope flag: --global, --project, --plan, or --action"
|
||||
)
|
||||
|
||||
if flags_set == 0:
|
||||
raise typer.BadParameter(
|
||||
"At least one scope flag is required: --global, --project, --plan, "
|
||||
"or --action"
|
||||
)
|
||||
|
||||
if project is not None:
|
||||
return InvariantScope.PROJECT, project
|
||||
if plan is not None:
|
||||
@@ -93,7 +99,6 @@ def _resolve_scope(
|
||||
if action is not None:
|
||||
return InvariantScope.ACTION, action
|
||||
|
||||
# Default to global
|
||||
return InvariantScope.GLOBAL, "system"
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user