Files
cleveragents-core/features/security_async.feature
T
aditya 50680612d5 feat(estimation): add cost and risk estimation actor
Implemented optional estimation_actor role for cost, risk, and duration
estimation during plan lifecycle. Estimates are persisted to plan metadata
and surfaced in CLI output. Key implementation details:

- EstimationOutput (Pydantic models): CostEstimate with currency, token
  estimates, and confidence ranges; RiskScore with 0-100 scale and factors;
  DurationEstimate with min/expected/max seconds. All include confidence
  levels and validation. EstimationSkipped records when estimation is opted out.

- EstimationService: stateless async service that invokes estimation actor
  (stub implementation for M6). Handles actor output parsing, error recovery,
  and fallback to EstimationSkipped on failure.

- Integration: Plan model gains estimation_output and estimation_skipped fields.
  LifecyclePlanModel adds JSON columns for persistence. PlanLifecycleService
  invokes estimation during use_action unless skip_estimation is true.

- CLI: --no-estimate flag added to 'agents plan use'. plan status displays
  cost (USD with token estimates), risk (score/100 with confidence), and
  duration (seconds with ranges) in rich format.

- Database: Alembic migration m6_003_estimation_metadata adds
  estimation_output_json and estimation_skipped_json columns to v3_plans.

- Tests: 44 BDD scenarios (features/estimation.feature) covering validation,
  lifecycle integration, persistence, CLI display, and edge cases. 18 Robot
  Framework smoke tests. 19 ASV benchmark suites for schema, serialization,
  validation, and plan integration performance.

- Documentation: docs/reference/estimation.md with schema, configuration,
  and examples. plan_cli.md updated with --no-estimate flag usage.

ISSUES CLOSED: #209
2026-03-19 15:07:05 +00:00

121 lines
5.4 KiB
Gherkin

Feature: Async Resource Cleanup and Leak Prevention
As a system operator
I want async resources to be tracked and closed reliably
So that the system does not leak connections, tasks, or subscriptions
Background:
Given I have an async resource tracker
Scenario: Registering an async resource and closing it
Given I have a mock async resource named "db-pool"
When I register the resource with the tracker
And I close all tracked resources
Then the resource "db-pool" should be closed
And the tracker should have zero open resources
Scenario: close_all awaits registered resources with timeout
Given I have 3 mock async resources with varied close times
When I close all tracked resources with a 5 second timeout
Then all 3 resources should be closed
And the tracker should have zero open resources
Scenario: Leaked resources are logged by name in finalizer
Given I have a mock async resource named "leaky-conn"
And I register the resource with the tracker
When the tracker finalizer runs without close_all
Then a warning should be logged mentioning "leaky-conn"
Scenario: Graceful cancellation awaits in-flight tasks before cleanup
Given I have an async task tracked by the bridge
When I request graceful cleanup with a 2 second timeout
Then the task should be cancelled
And the bridge should have no active tasks
Scenario: Time-bounded shutdown warns on forced termination
Given I have an async resource tracker
Given I have a mock async resource named "slow-resource" that takes 5 seconds to close
And I register the resource with the tracker
When I close all tracked resources with a 0.1 second timeout
Then a warning should be logged about forced termination
And the tracker should report the timed-out resource
Scenario: Cancelled async jobs persist cancellation reason
Given I have an async task tracked by the bridge
When I cancel the task with reason "user-requested-shutdown"
Then the cancellation reason should be "user-requested-shutdown"
Scenario: Checkpoint file handles are closed on cleanup
Given I have a state manager with a temporary checkpoint directory
When I save a checkpoint and then close the state manager
Then the checkpoint file should exist and be readable
And the state manager should be marked as closed
Scenario: Subscriptions are disposed on cleanup
Given I have an A2A event queue with 3 active subscriptions
When I close the event queue
Then all subscriptions should be removed
And the subscription count should be zero
Scenario: Tracker rejects duplicate resource names
Given I have a mock async resource named "unique-res"
And I register the resource with the tracker
When I try to register another resource named "unique-res"
Then a ValueError should be raised mentioning "unique-res"
Scenario: Tracker rejects empty resource name
When I try to register a resource with an empty name
Then a ValueError should be raised mentioning "name"
Scenario: Tracker rejects None resource
When I try to register a None resource with name "valid-name"
Then a ValueError should be raised mentioning "resource"
Scenario: Tracker context manager closes resources on exit
Given I have a mock async resource named "ctx-resource"
When I use the tracker as an async context manager and register the resource
Then the resource "ctx-resource" should be closed after exiting the context
Scenario: close_all is idempotent
Given I have a mock async resource named "once-resource"
And I register the resource with the tracker
When I close all tracked resources twice
Then the resource "once-resource" should be closed exactly once
And the tracker should have zero open resources
Scenario: Enhanced bridge cleanup awaits tasks with timeout
Given I have a bridge with 2 slow async tasks
When I run enhanced cleanup with a 2 second timeout
Then the bridge should have no active tasks
And completed tasks should be logged
Scenario: Registering a resource after close_all raises RuntimeError
Given I have a mock async resource named "late-resource"
And I register the resource with the tracker
When I close all tracked resources
And I try to register a resource named "post-close" after close_all
Then a RuntimeError should be raised mentioning "closed"
Scenario: State update after close raises RuntimeError
Given I have a state manager with a temporary checkpoint directory
When I close the state manager
And I try to update state after close
Then a RuntimeError should be raised mentioning "closed"
Scenario: State reset after close raises RuntimeError
Given I have a state manager with a temporary checkpoint directory
When I close the state manager
And I try to reset state after close
Then a RuntimeError should be raised mentioning "closed"
Scenario: Publish after close raises RuntimeError on A2aEventQueue
Given I have an A2A event queue with 1 active subscriptions
When I close the event queue
And I try to publish an event after close
Then a RuntimeError should be raised mentioning "closed"
Scenario: A2aEventQueue exposes is_closed property
Given I have an A2A event queue with 0 active subscriptions
Then the event queue is_closed should be False
When I close the event queue
Then the event queue is_closed should be True