Imported CostMetadata into fallback_selector.py to access per-plan budget data.
Extended FallbackSelector.__init__ with cost_metadata: CostMetadata | None = None and stored it in self._cost_metadata.
Implemented per-plan budget check in FallbackSelector.select() immediately after the daily budget validation to enforce per-plan limits during selection.
Added two new TDD scenarios to features/cost_controls.feature to exercise per-plan budget behavior, tagged @tdd_issue @tdd_issue_10471.
Added new test steps at features/steps/tdd_fallback_plan_budget_steps.py to support the new scenarios.
ISSUES CLOSED: #10485
Implemented TDD scaffolding for issue #10500:
- Added a new Behave feature: features/tdd_persona_state_set_active_persona_reset.feature
- Contains two scenarios tagged @tdd_issue @tdd_issue_10500 @tdd_expected_fail
- Verifies that PersonaState.set_active_persona() resets the preset to "default" when switching personas
- Tests are intentionally failing to demonstrate TDD; the @tdd_expected_fail tag inverts results so CI passes
- Added step definitions: features/steps/tdd_persona_state_set_active_persona_reset_steps.py
- Implements the steps required by the feature to exercise set_active_persona() and preset handling
- Rationale: The bug is that set_active_persona() only initializes the preset to "default" when there is no preset; if a non-default preset exists (e.g., "turbo"), switching personas leaves the preset unchanged instead of resetting to "default"
Files added provide the failing test scenarios and their wiring, guiding the eventual fix for resetting presets on persona switches.
Added import threading to src/cleveragents/providers/registry.py to enable a module-level lock.
Defined _registry_lock: threading.Lock = threading.Lock() at module scope.
Wrapped get_provider_registry() body with with _registry_lock: to ensure thread-safety.
Wrapped reset_provider_registry() body with with _registry_lock: to ensure thread-safety.
Added TDD support: features/tdd_registry_thread_safety.feature with @tdd_issue @tdd_issue_10409 @mock_only.
Added step definitions: features/steps/tdd_registry_thread_safety_steps.py.
ISSUES CLOSED: #10478
The feature file cli_version_info_diagnostics_showcase.feature was added
without corresponding Behave step definitions, causing unit_tests CI to fail
with AmbiguousStep errors. This commit adds the step definitions file and
updates the feature file step text to avoid conflicts with existing steps
in execution_environment_steps.py.
Created comprehensive showcase documentation for CLI version, info, and diagnostics commands
Documented fast-path vs regular command behavior
Included verified outputs and machine-readable JSON/YAML examples
Registered the showcase entry in docs/showcase/examples.json
Added BDD tests for the showcase documentation
Closes#7592
Three issues causing CI failures in advanced-context-strategies tests:
1. AmbiguousStep: `@then("the strategy should be {strategy_type}")` in
advanced_context_strategies_steps.py conflicted with the existing
`@then('the strategy should be "{expected_strategy}"')` in
plan_merge_strategy_steps.py:122. Renamed to
`@then("the loaded strategy type should be {strategy_type}")` and
updated all four matching lines in the feature file.
2. Wrong fragment count assertion: scenario "Semantic search strategy
ranks by embedding similarity" expected 3 fragments but
SemanticEmbeddingStrategy (word-overlap Jaccard, min_similarity=0.05)
correctly filters "File input output handler" (0 overlap with
"database connection"). Fixed assertion from 3 to 2.
3. Robot helper import failure: `features.mocks` is not importable when
Robot Framework imports the library because it adds robot/ to
sys.path but not the project root. Added explicit project-root
sys.path.insert before the features.mocks import (same pattern as
helper_lsp_stub.py), with # noqa: E402 on the post-path imports.
ISSUES CLOSED: #7574
- Extract FakeEmbeddings, RelevanceScoringStrategy, AdaptiveContextSelector,
ContextFusionStrategy, and _pack_budget from features/steps/ into new
features/mocks/advanced_context_strategies_mocks.py per mock-placement rules
- Remove sys.path manipulation from robot/helper_advanced_context_strategies.py;
import directly from features.mocks instead of features/steps
- Add None guard before selected.assemble() in step_assemble_context_query
- Add explicit ValueError for unknown strategy types in step_load_yaml_strategy
and load_strategy_from_yaml_impl
ISSUES CLOSED: #7574
- Add Behave feature file with 30+ scenarios for semantic search, relevance scoring, adaptive selection, and context fusion strategies
- Implement step definitions for all advanced context strategy tests
- Add FakeEmbeddings mock for deterministic testing without real API calls
- Create Robot Framework integration tests for E2E validation
- Implement helper functions for Robot Framework test execution
- All tests use proper type annotations and follow CONTRIBUTING.md guidelines
- Tests verify strategy selection, budget handling, deduplication, and YAML configuration
- Integration tests validate ContextAssembler compatibility and strategy priority handling
Add a Behave scenario that adds an fs-directory resource at a seeded
directory via the CLI. This exercises the if-children branch in
resource_add (lines 857-887 of resource.py), including _short_resource_id,
_format_child_status, and the Rich child table rendering — all previously
uncovered because no existing scenario produced auto-discovered children
through the resource add command path.
ISSUES CLOSED: #6464
The previous attempt wrapped `register_resource` in `with session.begin():`
to guarantee parent + auto-discovered children commit atomically. That
pattern raises `sqlalchemy.exc.InvalidRequestError: A transaction is
already begun on this Session.` whenever a caller (e.g. the WF05
integration helper at `robot/helper_int_wf05_db_migration.py`) reuses a
single Session across multiple service calls — autobegin has already
opened the implicit transaction by the time `register_resource` runs.
This rewrites the flow to keep the simpler `session.commit()` pattern
that worked with shared sessions, but moves the commit to AFTER
`auto_discover_children` so any failure between `session.add(parent)`
and `session.commit()` rolls the whole transaction back via the
existing `except`/`session.rollback()` handlers. Atomicity is
preserved (parent is never persisted on an auto-discovery failure) and
shared-session callers no longer get the `InvalidRequestError`.
Also stabilises the `Service get_children returns auto-discovered
children for directory` scenario in `features/resource_cli_tree.feature`
by adding an explicit `Given a seeded directory exists at "/tmp/gcl"`
step that creates the directory and writes a sentinel file. Without
this seed the scenario depended on whatever happened to exist at
`/tmp/gcl` in the CI environment.
ISSUES CLOSED: #6464
- Always rollback session unconditionally in auto_discover_children
except blocks (both ResourceNotFoundRepoError and OperationalError/
SQLAlchemyDatabaseError), regardless of commit/own_session flags.
This ensures @database_retry retries with a clean session and callers
continue to see the original DatabaseError instead of
sqlalchemy.exc.PendingRollbackError.
- Remove unused 'auto_exc' binding in register_resource's auto-discovery
exception handler (use bare 'except Exception:' instead).
- Move all 'from datetime import UTC, datetime' imports from inside
function bodies to module-level in
resource_registry_service_coverage_steps.py.
ISSUES CLOSED: #6464
Rename the step decorator in showcase_repl_actor_run_steps.py from
'the JSON should be valid' to 'the examples JSON content is valid'
to avoid collision with the identical step already defined in
aimodelsproviders_steps.py (which uses a different context variable).
Update the matching step text in showcase_repl_actor_run.feature.
ISSUES CLOSED: #7552
The BDD test step_commands_include checks for exact list membership.
"agents actor run" was missing from the commands list, causing the
"Showcase commands list is not empty" scenario to fail with:
AssertionError: Command 'agents actor run' not found in commands list
- Remove unused import os from showcase_repl_actor_run_steps.py
- Fix import order (given, then, when) per ruff I001
- Remove unnecessary "r" mode argument from open() calls (UP015)
- Fix step_check_repl_entry to actually find the REPL entry in examples.json
(was a no-op pass that left context.repl_entry unset, causing test failures)
- Register REPL and actor run showcase in examples.json
- Add BDD tests for showcase documentation structure
- Verify markdown file exists and is properly formatted
- Validate JSON metadata for showcase entry
- Test documented commands and content sections
Closes#7552
The _create_provider_instance method had two ProviderType.OPENROUTER
branches. The first (lines 574-598) ran first, returning without
sanitizing numeric header keys. The second (correct) branch at lines
627-652 — which coerces all header keys/values to str — was dead code
and never reached.
Fix: remove the first (broken) branch so the sanitizing branch executes.
Also add _create_provider_llm as a thin wrapper around
_create_provider_instance. Three scenarios in
openrouter_provider_registry.feature called this method and received
AttributeError because it did not exist.
Fixes: features/openrouter_provider_registry.feature:19,27,35 (errored)
features/provider_registry_coverage_boost.feature:48 (failed)
The openrouter_provider_registry_steps.py file called use_step_matcher("re")
at module level without restoring the default "parse" matcher at the end.
This caused all step files loaded alphabetically after it (provider_registry_*,
resource_*, session_*, etc.) to use the regex matcher instead of the parse
matcher, breaking their {value}-style step patterns and causing unit_tests CI
failures.
Add use_step_matcher("parse") at the end of the file to restore the default
matcher after the openrouter step definitions are registered.
Added handling for ProviderType.OPENROUTER in _create_provider_llm in src/cleveragents/providers/registry.py to resolve ValueError: Unsupported provider type when using OpenRouter via create_llm.
Created features/openrouter_provider_registry.feature with 11 scenarios validating OpenRouter provider behavior in ProviderRegistry.
Created features/steps/openrouter_provider_registry_steps.py with step definitions for the new feature file.
Created docs/reference/providers.md with comprehensive documentation including the OpenRouter configuration guide.
ISSUES CLOSED: #8907
The actor_compute_impact_error_handling.feature file references the
'Given an actor CLI runner' step in its Background section, but the
step definition was missing from the step file. This caused the tests
to fail with an undefined step error.
Added the missing step definition that initializes a CliRunner context
for testing. Also removed the unused noqa comment from the CliRunner
import since the import is now used in the step definition.
Replace three bare 'except Exception: pass' blocks in _compute_actor_impact()
with proper exception handling that logs at WARNING level with exception type
and message for diagnostics. The function still returns (0, 0, 0) on failure
(graceful degradation) but failures are now visible in logs.
Also adds BDD scenarios covering the error paths (DB unavailable -> warning
logged, counts return 0) and removes the pragma: no cover annotations from
the exception handlers.
ISSUES CLOSED: #8434
- Added comprehensive documentation about actor removal impact handling, outlining potential effects on dependencies, data integrity, and service continuity. Includes a clear, step-by-step checklist for evaluating impact prior to removal and guidance on planning mitigations.
- Documented the --unsafe flag and when it's required, with explicit warnings, usage criteria, and recommended safeguards, rollback steps, and testing considerations.
- Added non-zero impact scenarios and best practices for safe removal, including concrete examples of edge cases, guidance on graceful shutdown, data migration considerations, and rollback planning to minimize disruption.
- Updated the actor management workflow showcase with new guidance, aligning demonstrations and diagrams with the updated removal process and decision points.
Closes#7540
- What was implemented
- Added _resolve_resource_names() helper in src/cleveragents/cli/commands/project.py that queries the Resource Registry to map resource ULIDs to their namespaced names, with graceful fallback to None when the registry is unavailable or a resource has no name
- Updated _project_spec_dict() to accept an optional resource_names dict parameter and include resource_name alongside resource_id in JSON/YAML output formats
- Updated show command to resolve resource names before display, showing human-readable names (e.g. local/my-git-repo) instead of raw ULIDs, falling back to ULID when name is unavailable
- Added BDD feature file features/project_show_resource_name.feature with 6 regression scenarios
- Added step definitions features/steps/project_show_resource_name_steps.py
- Key design decisions
- Graceful degradation: if the Resource Registry is unavailable, the show command still works and falls back to displaying the raw ULID
- Resources without names (auto-discovered) also fall back to ULID display
- JSON/YAML output includes both resource_id and resource_name for completeness
- The fix is minimal and non-breaking: _project_spec_dict() only includes resource_name when resource_names dict is explicitly passed
- Rationale and implementation notes
- _resolve_resource_names() provides a bounded, resilient means to enrich output with human-readable names without breaking on registry failures
- The show command uses resolved names for display while preserving IDs as the underlying data source
- Outputs (JSON/YAML) expose both IDs and names when available, ensuring downstream consumers have full context
- Modules/Components Affected
- src/cleveragents/cli/commands/project.py
- tests/BDD: features/project_show_resource_name.feature
- tests/BDD steps: features/steps/project_show_resource_name_steps.py
- Backwards compatibility
- Non-breaking: if resource_names is not provided or the registry is unavailable, behavior remains compatible by falling back to ULIDs
- Testing
- Added regression scenarios via the new feature file and step definitions to validate name resolution and fallback behavior
ISSUES CLOSED: #2943
Fixes multiple bugs in the Behave step definitions for RelevanceScoringStrategy:
- Use context.strategy_fragments and context.strategy_budget (not context.fragments/context.budget)
- Store assemble result in context.strategy_result (not context.result_fragments)
- Store can_handle result in context.confidence (not context.strategy_confidence)
- Fix step pattern for can_handle with query to use quoted string "{query}"
- Fix step pattern for explain to use quoted string "{text}"
- Fix register_strategy call to pass name and strategy (not just strategy)
- Add RelevanceScoringStrategy to top-level imports
- Add proper type annotations to all new step functions