Add BDD/Behave test scenarios for the existing --format/-f flag on `agents session tell`,
and update CHANGELOG.md and CONTRIBUTORS.md.
The implementation of --format on session tell exists in the codebase (commit 87a7ce35d),
but lacks dedicated BDD test coverage. This PR adds:
- 6 new Behave scenarios in features/session_cli.feature testing JSON, YAML, plain, table,
short flag (-f), and Rich output regression paths
- 6 corresponding step definitions in features/steps/session_cli_steps.py verifying
spec-compliant JSON envelopes, valid YAML/JSON output, ASCII table output, and Rich console
content preservation
- CHANGELOG.md entry under [Unreleased] documenting the --format flag feature
- CONTRIBUTORS.md entry crediting Jeffrey Phillips Freeman
Quality gates: lint ✓, typecheck ✓ (only pre-existing warnings about optional provider imports)
ISSUES CLOSED: #10466
Removed unconditional session.rollback() calls within exception handlers in:
- ProjectRepository.create()
- NamespacedProjectRepository.create() (IntegrityError handler)
- NamespacedProjectRepository.create() (OperationalError handler)
- NamespacedProjectRepository.update()
- NamespacedProjectRepository.delete()
The Unit of Work pattern already handles transaction rollback at the outer layer
via its except Exception: session.rollback() handler, making these inner rollbacks
redundant. SQLAlchemy automatically invalidates the transaction state when exceptions
occur after flush(), preventing partial data from being committed.
Removing the redundant rollbacks improves clarity, eliminates potential issues related
to exception chaining across retry boundary layers, and aligns repository implementations
with explicit transaction boundaries.
ISSUES CLOSED: #8179
Issue references corrected from #264 to #691 throughout all documentation.
The A2A stdio transport feature is tracked by issue #691, not #264 (which was
about resource registry tables in v3.0.0).
CHANGELOG.md: Updated issue reference and added .py path routing fix entry under
BDD tests: Added command construction assertions for all three connect scenarios
(module, .py script, executable) to verify subprocess.Popen receives correct args:
- Module paths (cleveragents.X): [python, -m, module]
- .py file paths: [python, file.py]
- Executable paths: [executable_path]
The connect() method in A2aStdioTransport incorrectly routed literal .py
script paths (e.g. "agent.py") through `python -m` which expects Python
module names. Fixed to use `python agent_path` for direct script execution
while keeping module paths (cleveragents.*) via `-m` and executables unchanged.
Also resolved merge conflict markers in CONTRIBUTORS.md and added changelog
entry for the A2A stdio transport feature under [Unreleased]. Added BDD
test coverage entry.
ISSUES CLOSED: #264
Replaced insecure str.startswith(root + "/") path containment checks in
tool/path_mapper.py (_is_under) and application/services/llm_actors.py
(_write_to_sandbox) with semantic os.path.relpath comparisons to prevent
sibling-directory prefix-collision path traversal attacks.
The string-prefix approach was vulnerable: a sandbox root of /tmp/sandbox
would incorrectly allow access to /tmp/sandboxmalicious/file.txt because
"/tmp/sandboxmalicious/file" starts with "/tmp/sandbox".
Security specification mandates all path containment checks use
Path.is_relative_to() or equivalent semantic comparison.
Added BDD test coverage in features/path_containment_security.feature
with @tdd_issue_7478 tags for the prefix-collision attack scenarios.
ISSUES CLOSED: #7478
CHANGELOG.md and CONTRIBUTORS.md both referenced #10590, which is an
open PR not an issue. The correct issue is #8616. Also removed the
duplicate ### Added heading in CHANGELOG.md that preceded the entry.
CONTRIBUTORS.md now references PR #11106 / issue #8616.
ISSUES CLOSED: #8616
Implement the ContextStrategy Protocol for pluggable context assembly strategies
in the ACMS pipeline. Includes six built-in strategies, a StrategyRegistry service
with plugin discovery support, thread-safe operations, and comprehensive BDD tests.
ISSUES CLOSED: #10590
ACMSExecutePhaseContextAssembler previously instantiated the plain
ACMSPipeline when no pipeline was explicitly provided, missing production
Phase 1 optimizations including confidence-weighted strategy selection,
proportional budget allocation with min-budget enforcement, parallel
strategy execution with circuit breaking, and per-stage timing instrumentation.
The default is now ContextAssemblyPipeline which provides all of these
capabilities while remaining a drop-in replacement for ACMSPipeline.
ISSUES CLOSED: #10027
Epic #8477: added ExecutePhaseDecisionHook as the Execute-phase mirror of
StrategizeDecisionHook. Provides six recording methods for implementation
choices, tool invocations, error recovery, validation responses, subplan
spawn, and resource selection during execution contexts. Captures full
context snapshots with SHA-256 hashes and persists decisions atomically
via DecisionService. Includes comprehensive Behave test coverage.
ISSUES CLOSED: #8477
This PR implements the Invariant data model and database schema for the
v3.2.0 milestone. The Invariant feature enables the system to define, store,
and manage invariant rules that can be evaluated against system state.
- Alembic migration m3_001_invariants_table creates the invariants table
with columns: id (UUID), description (text), created_at (timestamp),
is_active (bool, default True), with index on is_active for efficiency
- SQLAlchemy ORM InvariantModel in
cleveragents.infrastructure.database.models.InvariantModel
- M3 merge migration to resolve Alembic head conflict
- BDD Behave scenarios (10 test cases) in features/invariant_model.feature
- Robot Framework integration tests in robot/invariant_model.robot
- Updated CHANGELOG.md and CONTRIBUTORS.md
- Restored status-check CI aggregation job
ISSUES CLOSED: #8524
When subprocess.Popen() fails during LSP server initialization (e.g.
FileNotFoundError for missing command or general OSError), partially-allocated
pipe resources and internal file descriptors could be left in an inconsistent
state. This was caused by _process potentially containing a stale reference if
an exception occurred between pipe allocation and the Popen object being fully
returned.
Fix: Add explicit self._process = None resets in three places:
1) Before subprocess.Popen() — ensures clean initial state even across retries
2) In FileNotFoundError handler — guards against intermediate error states
3) In OSError handler — general safety net for all subprocess failures
This prevents:
- Orphaned child processes never terminated (zombie processes)
- File descriptor leaks from partially-allocated pipes
- Transports stuck in ambiguous 'started but not live' state
Tests added: Two new Behave scenarios verify _process is None after both
FileNotFoundError and OSError during start().
ISSUES CLOSED: #10597
Implemented cache invalidation for CleanupService to fix stale sandbox paths
being reported after purge() completes. The _sandbox_dirs_cache is now
invalidated after _purge_sandboxes() so subsequent scan() calls re-read the
filesystem instead of returning already-deleted paths.
Changes:
- Added self._sandbox_dirs_cache = None at end of _purge_sandboxes()
- Updated docstring to document cache invalidation behavior
- Created comprehensive BDD test coverage with 5 scenarios under new
features/cleanup_service_cache_invalidation.feature and step definitions
- Updated CHANGELOG.md with bug fix entry
- Updated CONTRIBUTORS.md with PR #8257
ISSUES CLOSED: #7527
- Move Gherkin scenario tags from inline to separate lines before Scenario keywords in feature spec
- Remove HAL 9000 prose contribution entry from name list in CONTRIBUTORS.md per project conventions
- Add commit footer: ISSUES CLOSED: #7112
ISSUES CLOSED: #7112
Adds SandboxDirsCache to track filesystem paths of sandbox-created directories indexed by plan_id. Cache is purged in cleanup_all(), cleanup_abandoned(), clear_sandbox_dirs_cache(), and the at-exit handler matching the existing clear_boundary_cache() invalidation.
Add _state == McpClientState.STARTING guard inside the threading.RLock in
start() and _ensure_started() so that concurrent callers see the in-progress
state and return immediately, preventing double initialisation of the MCP
server connection.
- Move _CountingTransport test double from inline step file to dedicated
features/mocks/counting_mcp_transport.py per CONTRIBUTING.md mock placement rules
- Updated step definitions to import CountingMCPTransport from new location
- Added Race condition entry to CHANGELOG under [Unreleased] -> Fixed
- Added contributor credit for McpClient race condition fix
ISSUES CLOSED: #10438
Align the resource and skill management showcase with review feedback: consistent resource type counts (101), explicit save-to-disk instructions before each skill registration command, metadata callouts for non-obvious behaviors (Config: unknown, capability summary zeros, local/linear-tracker 0-tool count), and README framing to acknowledge platform feature walkthroughs.
Remove obsolete tdd_issue tags from coverage threshold Robot tests now that the noxfile enforces COVERAGE_THRESHOLD = 97.
Harden the Skip If No LLM Keys E2E helper with per-key regex validation and log-level suppression to prevent credential leakage in CI logs. Restore the Resolve LLM Actor keyword that was inadvertently removed from common_e2e.resource.
Update CHANGELOG.md and CONTRIBUTORS.md per project requirements.
ISSUES CLOSED: #4470
- Remove duplicate @then decorator on step_verify_peak_concurrency_limit
(caused AmbiguousStep error crashing all 8 unit test feature files)
- Rename "the subplans should have been executed in order" to
"the subplans should have been executed in sequential order" to
avoid conflict with pre-existing step in subplan_execution_steps.py
- Remove 13 additional @then step definitions that duplicated steps in
subplan_execution_steps.py; alias context.exec_result and
context.validation_error in @when steps so pre-existing steps work
- Replace two # type: ignore comments (lines 438, 453) with typed
Any variables per zero-tolerance policy
- Apply ruff format to fix formatting (long import wrapping, list comps)
- Add CHANGELOG entry and CONTRIBUTORS entry for #9555
ISSUES CLOSED: #9609
Applied ruff format fix to tui_permissions_screen_steps.py and corrected the step text mismatch in execution_environment.feature where 'it should not contain' was not updated to 'the container types should not contain' when the step definition was renamed.
ISSUES CLOSED: #10488
- 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
Implemented spec-compliant JSON, YAML, plain, and rich outputs for `agents project context set`. Added BDD coverage verifying the new output structure across formats.\n\nISSUES CLOSED: #6319
The CHANGELOG.md and CONTRIBUTORS.md entries from db048dd2 claimed this
PR adds `features/pure_graph_coverage.feature`. That standalone file
was intentionally not added (and an earlier draft was removed) because
the PureGraph scenarios already live in
`features/consolidated_langgraph.feature` — adding a standalone file
would have created duplicate Behave scenarios against the same step
definitions and broken `unit_tests` CI.
Reword both entries to accurately describe what this PR delivers:
- the previously orphaned `features/steps/pure_graph_coverage_steps.py`
is now driven through the existing consolidated feature file
- Robot Framework integration tests in `robot/langgraph/pure_graph.robot`
backed by `robot/langgraph/pure_graph_lib.py`
- ASV benchmarks in `benchmarks/pure_graph_bench.py`
ISSUES CLOSED: #9531
Update the PR compliance checklist items that were missing from the original
PR creation by pr-creator:
- Added ### Tests section to CHANGELOG.md documenting the PureGraph BDD,
Robot Framework integration tests, and ASV benchmark additions
- Updated CONTRIBUTORS.md with contribution details for the PureGraph test
coverage suite (PR #9601 / issue #9531)
This completes items [1] and [2] of the mandatory 8-item PR Compliance Checklist.
ISSUES CLOSED: #9531
- Rewrote production CLI to use real ContextTierService (get_scoped_view, get_all_fragments, evict_lru) instead of non-existent ACMSService
- Removed unused imports (Path, Panel, ScopedView) from production code
- Fixed all lint issues: trailing whitespace, import ordering, nested with statements
- Replaced typer.Abort() with typer.Exit(code=1) for error exits
- Added input validation for empty/whitespace view parameter
- Fixed error handling to use str(e) instead of e.message
- Added guards against negative budget values in _format_budget_utilization
- Added warning when clearing context with no filters (clear ALL)
- Removed module-level console side effect
- Moved mocks to features/mocks/acms_context_mocks.py per CONTRIBUTING.md
- Fixed test assertions to capture real CLI output (not placeholder)
- Fixed duplicate step definitions (AmbiguousStep errors)
- Fixed feature file step mismatch for tier count parameter
- Added Robot Framework integration tests in robot/acms_context_cli.robot
- Added performance benchmarks in benchmarks/acms_context_cli_bench.py
- Updated CHANGELOG.md with ACMS context CLI feature entry
- Updated CONTRIBUTORS.md with ACMS context CLI contribution
ISSUES CLOSED: #9586
- Add changelog entry under [Unreleased]/Fixed for plan artifacts JSON completeness (#9084)
- Add contributors detail for validation_summary and apply_summary fix work.
ISSUES CLOSED: #9084
Fix the failing unit tests in agent_task_memory_leak_fix.feature by
replacing the broken event loop management with a persistent background
asyncio event loop running in a daemon thread. The original implementation
called asyncio.create_task() from synchronous Behave step code, which
requires a running event loop — causing RuntimeError: no running event loop.
The fix introduces a _BackgroundLoop class that keeps a dedicated asyncio
event loop alive in a background thread. All agent instantiation and
message sending now happens via asyncio.run_coroutine_threadsafe(), ensuring
the event loop is always running when asyncio.create_task() is called.
Also adds the missing step definition for 'I send {count:d} messages to
the agent' (without 'in rapid succession') to match the feature file.
Updates CONTRIBUTORS.md with the agent task memory leak fix contribution.
ISSUES CLOSED: #9044
Adds Context Tier Hydration subsection to the ACMS Architecture section of
the specification, documenting the context_tier_hydrator module's public
interface (hydrate_tiers_for_plan, hydrate_tiers_from_project), file listing
strategy (git ls-files for git-checkout resources, os.walk fallback), budget
limits (256 KB per file, 10 MB total per project), and fragment structure
(TieredFragment with ContextTier.HOT placement, metadata keys path/detail_depth/relevance_score).
Also updates CHANGELOG.md under [Unreleased] > Documentation and adds
contribution entry to CONTRIBUTORS.md.
ISSUES CLOSED: #6175
author CleverThis <hal9000@cleverthis.com> 1776170939 +0000
committer CleverThis <hal9000@cleverthis.com> 1776170939 +0000
refactor(agent): replace hardcoded dependency and context file limits with configurable parameters
Implemented configurable limits for the agent and graph components:
- ContextAnalysisAgent now accepts max_dependencies: int = 10 with validation (ValueError if <= 0)
- _parse_dependencies uses self.max_dependencies instead of a hard-coded 10
- PlanGenerationGraph now accepts max_context_files: int = 5 with validation (ValueError if <= 0)
- _format_context_summary uses self.max_context_files instead of a hard-coded 5
- Updated class docstrings to reflect new parameters
- Added Behave feature file at features/agent_configurable_limits.feature with 12 scenarios
- Added step definitions at features/steps/agent_configurable_limits_steps.py
ISSUES CLOSED: #9050
- Remove committed build artifacts (test_reports/summary.txt,
test_reports/test_results.json) and add test_reports/ to .gitignore
- Fix CLI resource.py: update lifecycle state condition and warning
banner from 'detected (not built)' to 'discovered (not built)' and
'Devcontainer detected' to 'Devcontainer discovered' to align with
ContainerLifecycleState.DISCOVERED rename
- Fix BDD feature file: update resource_list_lifecycle_state.feature
scenario title and assertion from 'Devcontainer detected' to
'Devcontainer discovered'
- Fix robot/helper_devcontainer_lifecycle.py: update enum value check
from 'detected' to 'discovered' in cmd_enum_values()
- Fix robot/helper_devcontainer_handler.py: update strategy check
assertion from 'none' to 'snapshot' to match PR #8304 change
- Update CONTRIBUTORS.md with HAL 9000 feature contribution entry
Closes#7555 (via PR #8304)
Fixes: CI unit_tests and integration_tests failures from PR #8304
Add comprehensive Subplan System specification defining module boundaries,
data models (Subplan, SubplanResult, SubplanTree), PostgreSQL schema with
indexes, the 8-step spawning algorithm, concurrency control via per-plan
semaphores, and error handling.
Implement invariant loading and enforcement in Strategize phase:
- Add InvariantViolationError exception class
- Add load_active_invariants() and check_invariants() methods to InvariantService
- Add _is_violation heuristic for action/invariant matching
- Add BDD tests with @load_invariants, @check_invariants, etc. tags
ISSUES CLOSED: #8725
This TDD scenario documents the gap in Spec Requirement #7: the current
implementation of 'agents plan tree' does not visually distinguish corrected
nodes (decisions with is_correction=True).
The scenario creates a plan with a corrected decision and asserts that the
tree output contains a visual marker such as [corrected] or ✎. The scenario
is tagged @tdd_expected_fail to allow CI to pass while the bug exists.
The Rich tree renderer in tree_decisions_cmd builds node labels without
checking decision.is_correction, proving the gap exists.
- Revert production code change: remove label key and [corrected] marker
from _node_dict in build_decision_tree (the TDD scenario must prove the
bug exists, not fix it; the fix belongs in a separate PR)
- Update CONTRIBUTORS.md with TDD scenario contribution entry
- Add CHANGELOG.md entry for TDD scenario (#8576)
- Remove dead _make_decision() helper (was already removed by prior attempt)
- Remove # type: ignore[import-untyped] (was already removed by prior attempt)
ISSUES CLOSED: #8576
The step_tree_json_valid BDD step was asserting a raw list from
format_output, but the function wraps all machine-readable output in
a spec-required envelope dict ({"data": [...]}). This PR fixes the
step to correctly validate the envelope structure (dict with data key)
and removes @tdd_expected_fail from the @tdd_issue_4254 scenario so
it runs as a permanent regression guard.
The code producing decision_id in tree nodes was already correct; only
the test assertion needed fixing.
ISSUES CLOSED: #9096
- Add _sanitize_user_input() helper that catches PromptInjectionDetected and falls back to wrap_user_content() instead of crashing the agent
- Remove dead code (_bs, _be variables) from all three agent methods
- Use wrap_user_content() for error_analysis (internal LLM output) in _generate_fix() to avoid crashing on the agent's own output
- Add @security @prompt-injection BDD tags to feature file and all scenarios
- Add missing @then("the boundary markers should be present") step definition
- Add Robot Framework integration tests (auto_debug_agent_prompt_injection.robot)
- Update CHANGELOG.md and CONTRIBUTORS.md
ISSUES CLOSED: #9110
Add domain-scenario Gherkin tags to all A2A, session, and CLI feature
files (30 files) so tests can be filtered individually via behave.
- 8 A2A feature files: @a2a tag
- 7 session feature files: @session tag
- 15 CLI feature files: @cli tag
ISSUES CLOSED: #9124
- Fix error suppression in validate_all_commands: log at DEBUG level instead of silently swallowing exceptions
- Fix multi-word command name parsing bug: use command_token_count to skip the full command prefix when extracting positional values
- Add @cli tag to features/cli_docstring_example_validation.feature
- Update CONTRIBUTING.md with CLI docstring example style guide
- Update CHANGELOG.md with entry for automated docstring validation
- Update CONTRIBUTORS.md with contribution entry
- Fix test design flaws: separate Given/When/Then steps per scenario
- Add validate_all_commands test coverage via new Behave scenario
- Fix _extract_positional_args to only count required positional args
The plan correct --format json output already nests correction fields
under data.correction and sets command to "plan correct" via
format_output, so the three BDD scenarios now pass against the current
implementation. Remove the @tdd_expected_fail inversion tag so CI
reports them as passing, not as unexpected-pass failures.
Updated CHANGELOG.md and CONTRIBUTORS.md.
ISSUES CLOSED: #8584
Add MEMORY_ENGINES_LOCK to engine_cache.py and wrap the check-and-set
in UnitOfWork.engine with it to prevent concurrent threads from creating
duplicate in-memory SQLite engines. Also fix cache-hit bug where
self._engine was never assigned on a cache hit.
Closes#7566
Before transitioning to the Apply phase, PlanLifecycleService.apply_plan
now evaluates the plan's definition_of_done criteria using DoDEvaluator
(TextMatchEvaluator). If any required criteria fail, a DoDGatingError is
raised and the plan remains in Execute/COMPLETE state. The evaluation
result is stored in plan.validation_summary with dod_evaluated=True and
dod_all_passed reflecting the outcome. Plans with no DoD text skip
evaluation and proceed normally.
Adds DoDGatingError exception class and _evaluate_dod() helper method.
Adds BDD feature file and step definitions for DoD gating scenarios.
ISSUES CLOSED: #7927
Fixes a race condition (TOCTOU) in ActorLoader.list_actors() where the namespace
filter was applied outside the threading lock, creating a window for concurrent
dictionary modifications. Moving the filter inside the with self._lock: block
ensures atomic reads and filtering.
- Move namespace filtering inside the RLock in list_actors()
- Add concurrency BDD test (threading.Barrier) for list_actors + clear race condition
- Update CHANGELOG.md with fix entry (closes#8588)
- Update CONTRIBUTORS.md with contribution details
ISSUES CLOSED: #8588
Wrapped the `fileConfig()` call in `src/cleveragents/infrastructure/database/migrations/env.py`
with a `try/except` block that catches malformed INI logging configuration and emits
a clear, user-actionable error message to stderr before exiting with code 1.
Includes:
- Error handling guard around fileConfig() in env.py (fileConfig can raise
configparser.Error, KeyError, ValueError on malformed logging config)
- BDD/Behave feature file with 4 scenarios under `features/`
- Step definitions in `features/steps/` for isolated test coverage
- CHANGELOG.md entry under [Unreleased] Fixed section
- CONTRIBUTORS.md update for HAL 9000
ISSUES CLOSED: #7874
Signed-off-by: CleverThis <hal9000@cleverthis.com>