7 Commits

Author SHA1 Message Date
freemo 7fb3fc76c8 fix(plan-lifecycle): add rollback_plan method to PlanLifecycleService
- What was implemented
  - Added PLAN_ROLLED_BACK event type to the EventType enum at src/cleveragents/infrastructure/events/types.py to properly represent successful rollbacks in the domain model.
  - Implemented rollback_plan(plan_id: str, checkpoint_id: str) -> RollbackResult in PlanLifecycleService (src/cleveragents/application/services/plan_lifecycle_service.py) with:
    - Plan state validation: rejects rollback when the plan is in terminal APPLIED or CANCELLED states.
    - Delegation to CheckpointService.selective_rollback() to perform the actual rollback logic and obtain a RollbackResult.
    - Emission of PLAN_ROLLED_BACK as a domain event to reflect the completed rollback.
    - checkpoint_service is accepted as an optional constructor parameter; if not provided, a PlanError is raised to preserve backward compatibility.
  - Updated CLI behavior in src/cleveragents/cli/commands/plan.py so agents plan rollback routes through PlanLifecycleService.rollback_plan() rather than calling CheckpointService.selective_rollback() directly.
  - Updated PlanLifecycleService module docstring to include rollback_plan in the documented API.
  - Added Behave feature file features/plan_lifecycle_rollback.feature with 11 scenarios covering state validation, domain events, and delegation.
  - Added step implementations in features/steps/plan_lifecycle_rollback_steps.py to support the new scenarios.

- Key design decisions
  - rollback_plan returns RollbackResult (the same result type produced by CheckpointService.selective_rollback) so the CLI can display rollback details consistently.
  - Terminal states APPLIED and CANCELLED are disallowed for rollback to prevent inconsistent or invalid state transitions.
  - checkpoint_service is optional in the PlanLifecycleService constructor; when omitted (None), a PlanError is raised to retain backward compatibility while signaling explicit dependency requirements.
  - CLI UI remains powered by CheckpointService for metadata enrichment (e.g., confirmation prompts), but the actual rollback action is performed via PlanLifecycleService to ensure proper domain workflow and event emission.

- Technical implications
  - All rollback logic now flows through the domain service layer (PlanLifecycleService) to preserve invariants and emit domain events, rather than allowing ad-hoc UI routes to bypass service validation.
  - The UI can still retrieve checkpoint metadata for user confirmation, but the operation that modifies state uses the new rollback_plan pathway.
  - Tests and behavior coverage were expanded via the new Behave feature and step implementations to validate state handling, events, and delegation.

- Affected modules/components
  - src/cleveragents/infrastructure/events/types.py
  - src/cleveragents/application/services/plan_lifecycle_service.py
  - src/cleveragents/cli/commands/plan.py
  - PlanLifecycleService module docstring
  - features/plan_lifecycle_rollback.feature
  - features/steps/plan_lifecycle_rollback_steps.py

ISSUES CLOSED: #3677
2026-06-03 03:22:59 -04:00
HAL9000 a726b96d26 fix(cli): address reviewer feedback on format_output rich/color fix
- Move function-level imports to module top level in formatting.py:
  * Remove redundant OutputSession import inside _format_rich()
  * Remove redundant OutputSession import inside _format_color()
  * Move `import sys` from inside format_output() to module level

- Fix robot/helper_cli_formats.py:
  * Remove redundant `import json as _json` inside format_output_rich();
    use the top-level `json` module directly
  * Replace non-deterministic datetime.now() calls in _mock_action() and
    _mock_plan() with fixed datetime(2025, 1, 15, 10, 0, 0)

- Split cli_output_formats_steps.py to comply with 500-line limit:
  * Extract all @then step definitions into new file
    features/steps/cli_output_format_validation_steps.py
  * Behave auto-discovers steps from any .py file in steps/

ISSUES CLOSED: #2921
2026-05-30 11:09:06 -04:00
freemo 6e47abbd63 fix(cli): fix format_output() to use rich and color renderers instead of JSON fallback
The format_output() function in src/cleveragents/cli/formatting.py had two
routing bugs that caused incorrect output for the 'rich' and 'color' formats:

1. The 'rich' format had no explicit dispatch branch and silently fell through
   to the final JSON fallback, returning raw JSON instead of styled terminal
   output. Since 'rich' is the default CLI format (per ADR-021), this meant
   all commands using format_output() (version, info, diagnostics) produced
   JSON by default.

2. The 'color' format was incorrectly routed to _format_plain() instead of a
   color-aware renderer, producing plain text with no ANSI color codes.

Fix:
- Added _format_rich() helper that delegates to RichMaterializer via
  OutputSession, producing ANSI-styled terminal output consistent with
  format_output_session().
- Added _format_color() helper that delegates to ColorMaterializer via
  OutputSession, producing ANSI-colored terminal output.
- Added explicit OutputFormat.RICH dispatch in format_output() routing.
- Fixed OutputFormat.COLOR dispatch to use _format_color() instead of
  _format_plain().

Tests:
- Updated existing BDD scenario that was validating the buggy behavior
  (expected JSON for rich format) to now assert correct styled output.
- Added new BDD scenarios: 'rich format produces styled terminal output not
  JSON' and 'color format produces ANSI-colored output not plain text'.
- Added Robot Framework integration tests in cli_formats.robot and
  helper_cli_formats.py verifying end-to-end styled output for both formats.

All nox sessions pass: lint, typecheck, unit_tests, security_scan.

ISSUES CLOSED: #2921
2026-05-30 11:09:06 -04:00
freemo 4d31f0ed02 fix(cli): promote --format to global CLI callback option per spec
CI / lint (pull_request) Successful in 21s
CI / quality (pull_request) Successful in 34s
CI / typecheck (pull_request) Successful in 51s
CI / security (pull_request) Successful in 1m0s
CI / build (pull_request) Successful in 19s
CI / helm (pull_request) Successful in 24s
CI / unit_tests (pull_request) Failing after 7m5s
CI / docker (pull_request) Has been skipped
CI / e2e_tests (pull_request) Successful in 16m51s
CI / integration_tests (pull_request) Successful in 23m16s
CI / coverage (pull_request) Successful in 10m39s
CI / status-check (pull_request) Failing after 1s
CI / benchmark-publish (pull_request) Has been skipped
CI / benchmark-regression (pull_request) Successful in 56m46s
Add `fmt: OutputFormat` parameter to `main_callback()` in
`src/cleveragents/cli/main.py` and store the selected format in
`ctx.obj["format"]` so all subcommands can read it without needing
their own per-command `--format` flag.

Remove per-command `--format` / `fmt` parameters from `version()`,
`info()`, and `diagnostics()` commands. These commands now read the
format from `ctx.obj.get("format", OutputFormat.RICH.value)`.

The specification states: "The framework supports six distinct output
formats, selectable via the global `--format` flag." This change
aligns the implementation with the spec by making `--format` a global
option on the root `agents` command (via the Typer callback).

All six formats (json, yaml, plain, rich, table, color) are supported
via the global flag and the `-f` shorthand.

Add Behave BDD scenarios covering global `--format` flag propagation
to subcommands for all six formats. Update Robot Framework integration
tests to exercise the global `--format` flag. Update existing tests
that used per-command `--format` for version/info/diagnostics to use
the global flag instead.

ISSUES CLOSED: #2908
2026-04-05 08:39:14 +00:00
freemo 48cff5cfe0 refactor(cli): rename plan lifecycle-list and lifecycle-apply to match specification
CI / build (push) Successful in 18s
CI / lint (push) Failing after 31s
CI / helm (push) Successful in 33s
CI / typecheck (push) Successful in 50s
CI / security (push) Failing after 51s
CI / coverage (push) Has been skipped
CI / benchmark-regression (push) Has been skipped
CI / unit_tests (push) Failing after 1m50s
CI / docker (push) Has been skipped
CI / quality (push) Successful in 3m43s
CI / integration_tests (push) Has been cancelled
CI / e2e_tests (push) Has been cancelled
CI / benchmark-publish (push) Has been cancelled
CI / status-check (push) Has been cancelled
Renames `plan lifecycle-list` to `plan list` and `plan lifecycle-apply` to `plan apply` to align with the specification's canonical command names. Removes legacy V2 plan commands that occupied those names.

- Renamed CLI command registrations from lifecycle-list/lifecycle-apply to list/apply
- Removed legacy V2 apply and list commands (~200 lines)
- Updated apply shortcut in main.py to delegate to v3 lifecycle
- Added defensive null check for plan existence in apply command
- Updated 63+ test, doc, and benchmark files for consistency

Closes #881

Co-authored-by: Jeffrey Phillips Freeman <the@jeffreyfreeman.me>
Co-committed-by: Jeffrey Phillips Freeman <the@jeffreyfreeman.me>
2026-04-02 19:09:04 +00:00
freemo 174e117d8e refactor(automation): remove automation_level legacy fields 2026-02-20 15:57:21 +00:00
Jeff (CTO) 156e3ffde9 feat(cli): stabilize action/plan output formats
CI / quality (push) Waiting to run
CI / unit_tests (push) Waiting to run
CI / integration_tests (push) Waiting to run
CI / lint (push) Waiting to run
CI / typecheck (push) Waiting to run
CI / security (push) Waiting to run
CI / coverage (push) Blocked by required conditions
CI / build (push) Waiting to run
CI / docker (push) Blocked by required conditions
CI / lint (pull_request) Successful in 13s
CI / typecheck (pull_request) Successful in 27s
CI / security (pull_request) Successful in 21s
CI / quality (pull_request) Successful in 15s
CI / integration_tests (pull_request) Successful in 4m38s
CI / build (pull_request) Successful in 16s
CI / unit_tests (pull_request) Successful in 9m35s
CI / docker (pull_request) Successful in 37s
CI / coverage (pull_request) Successful in 6m57s
2026-02-14 13:51:12 -05:00