Files
cleveragents-core/features/plan_apply_json_envelope.feature
HAL9000 bbe8d830d5 fix(cli): correct _apply_output_dict data fields to match spec
Fix the spec-required data structure for `agents plan apply --format json`:
- artifacts: [] -> 0 (integer count per spec)
- changes: [] -> {"insertions": 0, "deletions": 0} (dict per spec)
- validation: rename "test" -> "tests" with nested dict structure, restructure
  "lint" and "type_check" as nested dicts, rename "duration" -> "duration_s" (float)
- lifecycle.child_plans: [] -> 0 (integer count per spec)
- timing.applied_at key renamed to timing.started per spec

Update BDD tests to match corrected implementation:
- plan_apply_json_envelope.feature: check "tests" not "test" in validation
- plan_cli_coverage_boost.feature: remove non-spec "namespaced_name" assertion
- plan_cli_coverage_boost_steps.py: check flat string messages per spec,
  not {"level", "text"} objects

ISSUES CLOSED: #9449
2026-06-17 06:49:43 -04:00

105 lines
6.1 KiB
Gherkin

Feature: plan apply --format json returns spec-required JSON envelope
As a programmatic consumer of the CleverAgents CLI
I want ``agents plan apply --format json`` to return a spec-compliant JSON envelope
So that tooling and scripts can reliably parse the apply output
Background:
Given a plan CLI runner for the apply JSON envelope test
# ── Envelope field presence ──────────────────────────────────────────────
Scenario: apply JSON output includes all required top-level envelope fields
When I invoke plan apply with --format json and a mocked service
Then the apply JSON envelope should contain field "command"
And the apply JSON envelope should contain field "status"
And the apply JSON envelope should contain field "exit_code"
And the apply JSON envelope should contain field "data"
And the apply JSON envelope should contain field "timing"
And the apply JSON envelope should contain field "messages"
Scenario: apply JSON envelope command field is "plan apply"
When I invoke plan apply with --format json and a mocked service
Then the apply JSON envelope command should be "plan apply"
Scenario: apply JSON envelope status field is "ok"
When I invoke plan apply with --format json and a mocked service
Then the apply JSON envelope status should be "ok"
Scenario: apply JSON envelope exit_code field is 0
When I invoke plan apply with --format json and a mocked service
Then the apply JSON envelope exit_code should be 0
Scenario: apply JSON envelope messages is a non-empty list
When I invoke plan apply with --format json and a mocked service
Then the apply JSON envelope messages should be a non-empty list
# ── Data field structure ─────────────────────────────────────────────────
Scenario: apply JSON envelope data field contains required sub-fields
When I invoke plan apply with --format json and a mocked service
Then the apply JSON data should contain field "artifacts"
And the apply JSON data should contain field "changes"
And the apply JSON data should contain field "project"
And the apply JSON data should contain field "applied_at"
And the apply JSON data should contain field "validation"
And the apply JSON data should contain field "sandbox_cleanup"
And the apply JSON data should contain field "lifecycle"
Scenario: apply JSON data validation field contains test lint and type_check
When I invoke plan apply with --format json and a mocked service
Then the apply JSON data validation should contain field "tests"
And the apply JSON data validation should contain field "lint"
And the apply JSON data validation should contain field "type_check"
Scenario: apply JSON data lifecycle field contains required sub-fields
When I invoke plan apply with --format json and a mocked service
Then the apply JSON data lifecycle should contain field "phase"
And the apply JSON data lifecycle should contain field "state"
And the apply JSON data lifecycle should contain field "total_duration"
And the apply JSON data lifecycle should contain field "total_cost"
And the apply JSON data lifecycle should contain field "decisions_made"
And the apply JSON data lifecycle should contain field "child_plans"
Scenario: apply JSON data sandbox_cleanup field contains worktree branch checkpoint
When I invoke plan apply with --format json and a mocked service
Then the apply JSON data sandbox_cleanup should contain field "worktree"
And the apply JSON data sandbox_cleanup should contain field "branch"
And the apply JSON data sandbox_cleanup should contain field "checkpoint"
# ── sandbox_cleanup derives from actual plan state ───────────────────────
Scenario: sandbox_cleanup shows removed state for terminal apply plan
When I invoke plan apply with --format json and a terminal apply plan
Then the apply JSON data sandbox_cleanup worktree should be "removed"
And the apply JSON data sandbox_cleanup branch should be "merged to main"
And the apply JSON data sandbox_cleanup checkpoint should be "archived"
Scenario: sandbox_cleanup shows active state for non-terminal plan
When I invoke plan apply with --format json and a non-terminal plan
Then the apply JSON data sandbox_cleanup worktree should be "active"
And the apply JSON data sandbox_cleanup branch should be "open"
And the apply JSON data sandbox_cleanup checkpoint should be "pending"
# ── Command isolation ────────────────────────────────────────────────────
Scenario: plan status --format json does not emit plan apply command field
When I invoke plan status with --format json and a mocked service
Then the plan status JSON output should not have command "plan apply"
Scenario: plan cancel --format json does not emit plan apply command field
When I invoke plan cancel with --format json and a mocked service
Then the plan cancel JSON output should not have command "plan apply"
# ── Legacy plan fallback ─────────────────────────────────────────────────
Scenario: apply JSON envelope handles legacy plan object gracefully
When I invoke the apply output dict with a legacy plan object
Then the legacy apply JSON envelope command should be "plan apply"
And the legacy apply JSON envelope data should contain field "plan"
# ── total_cost from cost_metadata ────────────────────────────────────────
Scenario: apply JSON data lifecycle total_cost reflects plan cost_metadata
When I invoke plan apply with --format json and a plan with cost metadata
Then the apply JSON data lifecycle total_cost should start with "$"