a0275f2401
CI / lint (pull_request) Successful in 21s
CI / typecheck (pull_request) Successful in 58s
CI / security (pull_request) Successful in 1m0s
CI / quality (pull_request) Successful in 35s
CI / build (pull_request) Successful in 24s
CI / helm (pull_request) Successful in 24s
CI / unit_tests (pull_request) Successful in 6m54s
CI / e2e_tests (pull_request) Successful in 19m6s
CI / integration_tests (pull_request) Successful in 22m57s
CI / docker (pull_request) Successful in 1m24s
CI / coverage (pull_request) Successful in 10m53s
CI / status-check (pull_request) Successful in 2s
CI / benchmark-publish (pull_request) Has been skipped
CI / benchmark-regression (pull_request) Successful in 57m5s
Implements the spec-required JSON envelope for `agents plan execute --format json`.
Previously, the command returned the raw plan domain model dict via
`_plan_spec_dict()`, which was missing the sandbox, worker, started,
attempt, strategy_summary, and progress fields required by the spec.
Changes:
- Add `_execute_output_dict(plan, started_at, duration_ms)` function that
builds the spec-required execute output envelope with:
- Top-level envelope: command, status, exit_code, data, timing, messages
- data.sandbox: strategy, path, branch, status (derived from sandbox_refs)
- data.worker: execution_actor or 'local/executor' fallback
- data.started: HH:MM:SS from execute_started_at timestamp
- data.attempt: from plan.identity.attempt
- data.strategy_summary: decisions, invariants, planned_child_plans,
estimated_files, risk (from estimation_result when available)
- data.progress: 4-step list with label/status derived from plan state
- Update `execute_plan()` to track wall-clock start time and use
`_execute_output_dict()` instead of `_plan_spec_dict()` for non-rich output
- Add BDD tests verifying the spec-required envelope structure, sandbox
strategy field, and progress list label/status fields
ISSUES CLOSED: #3435
171 lines
8.0 KiB
Gherkin
171 lines
8.0 KiB
Gherkin
Feature: Plan CLI coverage boost
|
|
As a developer
|
|
I want to exercise uncovered branches in plan.py
|
|
So that code coverage is improved for the plan CLI module
|
|
|
|
# ---- _plan_spec_dict helper ----
|
|
|
|
Scenario: _plan_spec_dict returns error_message when truthy
|
|
Given a v3 Plan with error_message set to "Strategy failed"
|
|
When I call _plan_spec_dict on the plan
|
|
Then the spec dict should contain key "error_message" with value "Strategy failed"
|
|
|
|
Scenario: _plan_spec_dict falls back to legacy format for non-Plan objects
|
|
Given a non-Plan object with string value "legacy plan data"
|
|
When I call _plan_spec_dict on the object
|
|
Then the spec dict should equal {"plan": "legacy plan data"}
|
|
|
|
Scenario: _plan_spec_dict omits error_message when it is None
|
|
Given a v3 Plan with error_message set to None
|
|
When I call _plan_spec_dict on the plan
|
|
Then the spec dict should not contain key "error_message"
|
|
|
|
# ---- _print_lifecycle_plan helper ----
|
|
|
|
Scenario: _print_lifecycle_plan prints all optional timestamps
|
|
Given a v3 Plan with all timestamps populated
|
|
When I call _print_lifecycle_plan on the plan
|
|
Then the printed output should contain "Strategize Started"
|
|
And the printed output should contain "Strategize Completed"
|
|
And the printed output should contain "Execute Started"
|
|
And the printed output should contain "Execute Completed"
|
|
And the printed output should contain "Applied At"
|
|
|
|
Scenario: _print_lifecycle_plan prints estimation_actor when set
|
|
Given a v3 Plan with estimation_actor set to "local/cost-estimator"
|
|
When I call _print_lifecycle_plan on the plan
|
|
Then the printed output should contain "Estimation Actor"
|
|
And the printed output should contain "local/cost-estimator"
|
|
|
|
Scenario: _print_lifecycle_plan prints invariant_actor when set
|
|
Given a v3 Plan with invariant_actor set to "local/invariant-checker"
|
|
When I call _print_lifecycle_plan on the plan
|
|
Then the printed output should contain "Invariant Actor"
|
|
And the printed output should contain "local/invariant-checker"
|
|
|
|
Scenario: _print_lifecycle_plan falls back for non-Plan objects
|
|
Given a non-Plan object with string value "legacy-plan-object"
|
|
When I call _print_lifecycle_plan on the object
|
|
Then the printed output should contain "legacy-plan-object"
|
|
|
|
# ---- execute_plan non-rich format ----
|
|
|
|
Scenario: execute_plan outputs JSON when format is json
|
|
Given a plan lifecycle CLI runner for coverage
|
|
And a mocked lifecycle service for plan coverage commands
|
|
And the service has a complete strategize plan for execute
|
|
When I invoke execute with "--format" "json" and plan id
|
|
Then the plan coverage command should succeed
|
|
And the plan coverage output should contain "plan_id"
|
|
And the plan coverage output should contain "sandbox"
|
|
And the plan coverage output should contain "worker"
|
|
And the plan coverage output should contain "progress"
|
|
And the plan coverage output should contain "strategy_summary"
|
|
And the plan coverage output should contain "command"
|
|
And the plan coverage output should contain "exit_code"
|
|
|
|
Scenario: execute_plan JSON output has spec-required envelope structure
|
|
Given a plan lifecycle CLI runner for coverage
|
|
And a mocked lifecycle service for plan coverage commands
|
|
And the service has a complete strategize plan for execute
|
|
When I invoke execute with "--format" "json" and plan id
|
|
Then the plan coverage command should succeed
|
|
And the execute JSON output has the spec-required envelope fields
|
|
And the execute JSON output data has sandbox with strategy field
|
|
And the execute JSON output data has progress list with label and status
|
|
|
|
# ---- apply_plan non-rich format ----
|
|
|
|
Scenario: apply_plan outputs JSON when format is json
|
|
Given a plan lifecycle CLI runner for coverage
|
|
And a mocked lifecycle service for plan coverage commands
|
|
And the service has a complete execute plan for apply
|
|
When I invoke apply with "--format" "json" and plan id
|
|
Then the plan coverage command should succeed
|
|
And the plan coverage output should contain "plan_id"
|
|
|
|
# ---- list_plans regex and state/processing_state filtering ----
|
|
|
|
Scenario: list_plans filters by regex pattern
|
|
Given a plan lifecycle CLI runner for coverage
|
|
And a mocked lifecycle service for plan coverage commands
|
|
And the service has multiple plans for lifecycle list
|
|
When I invoke list with regex "alpha"
|
|
Then the plan coverage command should succeed
|
|
And the plan coverage output should contain "alpha"
|
|
And the plan coverage output should not contain "beta"
|
|
|
|
Scenario: list_plans filters by state
|
|
Given a plan lifecycle CLI runner for coverage
|
|
And a mocked lifecycle service for plan coverage commands
|
|
And the service has plans in different processing states
|
|
When I invoke list with "--state" "processing"
|
|
Then the plan coverage command should succeed
|
|
|
|
Scenario: list_plans filters by processing_state alias
|
|
Given a plan lifecycle CLI runner for coverage
|
|
And a mocked lifecycle service for plan coverage commands
|
|
And the service has plans in different processing states
|
|
When I invoke list with "--processing-state" "complete"
|
|
Then the plan coverage command should succeed
|
|
|
|
Scenario: list_plans rejects invalid regex
|
|
Given a plan lifecycle CLI runner for coverage
|
|
And a mocked lifecycle service for plan coverage commands
|
|
And the service has multiple plans for lifecycle list
|
|
When I invoke list with regex "[invalid"
|
|
Then the plan coverage command should abort
|
|
And the plan coverage output should contain "Invalid regex"
|
|
|
|
Scenario: list_plans filters by action name
|
|
Given a plan lifecycle CLI runner for coverage
|
|
And a mocked lifecycle service for plan coverage commands
|
|
And the service has multiple plans for lifecycle list
|
|
When I invoke list with "--action" "local/test-action"
|
|
Then the plan coverage command should succeed
|
|
|
|
Scenario: list_plans outputs JSON when format is json
|
|
Given a plan lifecycle CLI runner for coverage
|
|
And a mocked lifecycle service for plan coverage commands
|
|
And the service has multiple plans for lifecycle list
|
|
When I invoke list with "--format" "json"
|
|
Then the plan coverage command should succeed
|
|
And the plan coverage output should contain "plan_id"
|
|
|
|
# ---- cancel_plan ----
|
|
|
|
Scenario: cancel_plan in non-rich format without reason
|
|
Given a plan lifecycle CLI runner for coverage
|
|
And a mocked lifecycle service for plan coverage commands
|
|
And the service can cancel a plan
|
|
When I invoke cancel with "--format" "json" and no reason
|
|
Then the plan coverage command should succeed
|
|
And the plan coverage output should contain "plan_id"
|
|
And the plan coverage output should not contain "cancel_reason"
|
|
|
|
Scenario: cancel_plan in non-rich format with reason
|
|
Given a plan lifecycle CLI runner for coverage
|
|
And a mocked lifecycle service for plan coverage commands
|
|
And the service can cancel a plan
|
|
When I invoke cancel with "--format" "json" and reason "not needed"
|
|
Then the plan coverage command should succeed
|
|
And the plan coverage output should contain "cancel_reason"
|
|
And the plan coverage output should contain "not needed"
|
|
|
|
Scenario: cancel_plan in rich format with reason
|
|
Given a plan lifecycle CLI runner for coverage
|
|
And a mocked lifecycle service for plan coverage commands
|
|
And the service can cancel a plan
|
|
When I invoke cancel in rich format with reason "obsolete"
|
|
Then the plan coverage command should succeed
|
|
And the plan coverage output should contain "Plan cancelled"
|
|
And the plan coverage output should contain "Reason: obsolete"
|
|
|
|
Scenario: cancel_plan in rich format without reason
|
|
Given a plan lifecycle CLI runner for coverage
|
|
And a mocked lifecycle service for plan coverage commands
|
|
And the service can cancel a plan
|
|
When I invoke cancel in rich format without reason
|
|
Then the plan coverage command should succeed
|
|
And the plan coverage output should contain "Plan cancelled"
|