Implement StrategyCoordinator and FusionEngine as named facades over
the existing ACMS pipeline components, providing clean public APIs
for parallel strategy execution with proportional budget allocation
and fragment fusion with dedup/conflict resolution/knapsack packing.
Key changes:
- Add StrategyCoordinator with parallel execution and confidence-based budget allocation
- Add FusionEngine with URI+hash dedup, max-depth conflict resolution, greedy knapsack packing
- Add budget overage guard with lowest-relevance fragment dropping
- Add per-strategy max caps enforcement
- Wire into existing ContextAssemblyPipeline
- Add Behave BDD tests, Robot integration tests, ASV benchmarks
- Add docs/reference/acms_fusion.md
ISSUES CLOSED: #192
Implemented lazy container activation for devcontainer-instance resources
with ContainerLifecycleState enum tracking six states (inactive, starting,
active, stopping, stopped, error) with validated transitions. Extended
DevcontainerHandler with devcontainer up CLI integration and JSON output
parsing for container start. Added periodic health checking via
devcontainer exec ping with configurable interval. Added agents resource
stop and agents resource rebuild CLI commands for manual lifecycle
control. Wired session close and plan completion hooks to automatic
container cleanup. Includes lifecycle state persistence in resource
registry with timestamped transitions. Added Behave BDD tests, Robot
integration tests, and ASV activation latency benchmarks.
- Added remoteWorkspaceFolder absolute-path validation
- Aligned spec: handler name, rebuild types, --yes flag on stop/rebuild
- Added registry re-read in stop_container success path for consistency
- Added session_id field to ContainerLifecycleTracker for scoped cleanup
- Scoped stop_all_active_containers to session_id when provided
- Wired _cleanup_devcontainers into fail_apply and fail_execute
- Wired start_health_check into activate_container success path
- Restructured facade session close to always run container cleanup
even without session service (F4)
- Re-read tracker from registry in activate_container success path
- Added evict_terminal_trackers to cap registry growth
- Updated devcontainer_resources.md: health check auto-start, scoped
cleanup hooks, known limitations for eviction and sandbox_strategy
- Wired evict_terminal_trackers into stop_all_active_containers so
terminal-state trackers are actually evicted in production
- Made stop_container idempotent: returns early when container is
already in a terminal state instead of raising ValueError
- Fixed benchmark health check thread leak in TimeActivationLatency
by clearing registry after each timing loop
- Added rebuild pass-through (--reset-container flag to devcontainer up)
- Added host_workspace_path field on ContainerLifecycleTracker so
health probes use the host-side path for devcontainer exec
- Wired lazy activation into DevcontainerHandler.resolve() for
devcontainer-instance resources in non-running states
- Changed _default_strategy from SNAPSHOT to NONE (container
itself provides isolation; SandboxFactory raises NotImplementedError
for snapshot)
- Restricted _STOPPABLE_TYPES to devcontainer-instance only
(container-instance is not directly stoppable via CLI)
ISSUES CLOSED: #514
Add RepoIndexingService with incremental refresh, language detection,
SHA-256 hashing, and policy enforcement. Includes domain models,
DB persistence, DI wiring, Behave/Robot/ASV tests, and reference docs.
ISSUES CLOSED: #195
## Summary
Fix `agents project show` not finding a project immediately after creation. Extends the `session.commit()` fix from #589 to also cover `update()` and `delete()` in `NamespacedProjectRepository`.
## Changes
**Production fix** (`src/cleveragents/infrastructure/database/repositories.py`):
- Add `session.commit()` to `create()`, `update()`, and `delete()` methods
- Add `finally: session.close()` guard to all three methods
- Update class docstring to reflect commit-per-method pattern
**Tests & benchmarks**:
- 3 Behave BDD regression scenarios (`features/project_show_after_create.feature`)
- Robot Framework integration smoke tests with "not found" assertion (`robot/project_show_after_create.robot`)
- ASV benchmarks for create-then-show round-trip (`benchmarks/project_show_after_create_bench.py`)
## Review feedback addressed
- **F1**: Removed unrelated em-dash CHANGELOG edits — wrote clean entry from scratch
- **F2**: Kept Suite Setup/Teardown (required for `${PYTHON}` variable); updated stale docs
- **F3**: Added "not found" string assertion to Robot negative test case
- **F4**: Removed redundant `Base.metadata.create_all()` from `_make_fresh_repo()` helper
- Updated all stale TDD "expected to fail" comments — this PR includes the fix
## Process
- Single squashed commit, rebased onto `master` (no merge commits)
- Prescribed commit message from issue #590 metadata
ISSUES CLOSED: #590
Reviewed-on: cleveragents/cleveragents-core#593
Reviewed-by: Rui Hu <rui.hu@cleverthis.com>
Co-authored-by: Brent E. Edwards <brent.edwards@cleverthis.com>
Co-committed-by: Brent E. Edwards <brent.edwards@cleverthis.com>
## Summary
Fix `agents project create` not persisting projects to the database. `NamespacedProjectRepository.create()` called `session.flush()` but never `session.commit()`, so projects were invisible to subsequent `agents project list` invocations that open a separate session.
## Changes
**Production fix** (`src/cleveragents/infrastructure/database/repositories.py`):
- Replace `session.flush()` with `session.commit()` in `NamespacedProjectRepository.create()`
- Add `finally: session.close()` guard for proper session lifecycle
**Tests & benchmarks**:
- 4 Behave BDD regression scenarios (`features/project_create_persist.feature`)
- Robot Framework integration smoke tests (`robot/project_create_persist.robot`)
- ASV benchmarks for create-then-list round-trip (`benchmarks/project_create_persist_bench.py`)
## Review feedback addressed
- **H3**: Added `finally: session.close()` to `create()` method
- **M1**: Removed redundant `session.flush()` before `session.commit()`
- **M2**: Updated stale TDD "expected to fail" comments — this PR includes the fix
- **M4**: Rewrote CHANGELOG entry to describe the fix, not just tests
- **F1**: Updated Robot documentation (Suite Setup/Teardown kept — needed for `${PYTHON}`)
- **F2**: Fixed bare assertion `"my-app"` to `"local/my-app"` in namespace scenario
- **F3**: Removed redundant `Base.metadata.create_all()` from `_make_fresh_repo()`
## Process
- Single squashed commit, rebased onto `master` (no merge commits)
- Prescribed commit message from issue #589 metadata
ISSUES CLOSED: #589
Reviewed-on: cleveragents/cleveragents-core#591
Reviewed-by: Rui Hu <rui.hu@cleverthis.com>
Co-authored-by: Brent E. Edwards <brent.edwards@cleverthis.com>
Co-committed-by: Brent E. Edwards <brent.edwards@cleverthis.com>
## Summary
Fixes the `plan correct` CLI handler which never passes the decision tree or influence edges to `CorrectionService`, producing single-node impact analysis regardless of the plan's actual decision structure.
Closes#606
## Root Cause
The `correct_decision()` handler in `plan.py` created a bare `CorrectionService()` and called `analyze_impact()` and `execute_correction()` without passing `decision_tree` or `influence_edges`. Both parameters default to `None` -> empty dicts, causing `_compute_affected_subtree()` BFS to return only the single target decision, ignoring all descendants and influence-DAG dependents.
## Changes
### Production Fix (`src/cleveragents/cli/commands/plan.py`)
- Resolve `DecisionService` via `get_container()` (following the pattern used by `plan explain` and `plan tree`)
- Build structural tree adjacency list from `decision_svc.list_decisions(plan_id)` using `parent_decision_id` relationships
- Fetch influence edges from `decision_svc.get_influence_edges(plan_id)`
- Pass both `decision_tree` and `influence_edges` to `svc.analyze_impact()` and `svc.execute_correction()`
### Existing Test Fixups
- Updated 4 step definition files that mock `CorrectionService` to also mock the new `DecisionService` resolution path
### New Tests
- **Behave BDD**: 3 scenarios verifying tree/edge forwarding (dry-run subtree, execution subtree, leaf node)
- **Robot Framework**: 3 integration smoke tests
- **ASV Benchmark**: Tree building and analyze_impact overhead benchmarks
## Quality Gates
- `nox -s lint` — PASSED
- `nox -s typecheck` — 0 errors
- `nox -s unit_tests` — 9,109 scenarios, 0 failures
- `nox -s coverage_report` — 97%
ISSUES CLOSED: #606
Reviewed-on: cleveragents/cleveragents-core#639
Co-authored-by: Jeffrey Phillips Freeman <jeffrey.freeman@cleverthis.com>
Co-committed-by: Jeffrey Phillips Freeman <jeffrey.freeman@cleverthis.com>
Implement spec-mandated pre-flight guardrail checks that validate plan
readiness before entering the Strategize phase:
1. Action schema validation — verifies action exists and is well-formed.
2. Actor availability — confirms all 4 actor roles registered.
3. Skill/tool existence — transitively resolves all tools/skills.
4. Automation policy — verifies profile permits execution.
5. Rollback feasibility — ensures all tools checkpointable if required.
6. Resource accessibility — shallow connectivity check on linked resources.
7. Validation attachment resolution — pre-resolves all applicable validations.
PlanPreflightGuardrail service runs all 7 checks via run_all_checks().
On first failure, raises PreflightRejection with check name and message.
Wired into plan_lifecycle_service before Strategize phase.
Behave BDD: 18 scenarios covering all 7 checks (positive + negative).
Robot Framework: 3 integration smoke tests.
ASV benchmarks: pre-flight check execution time.
ISSUES CLOSED: #582
ToolRegistryRepository.create(), .update(), and .delete() called
session.flush() but never session.commit(). The CLI factory creates a
raw sessionmaker without a UnitOfWork wrapper, so the transaction was
never committed and SQLAlchemy performed an implicit rollback when the
session was garbage-collected.
The same bug existed in ValidationAttachmentRepository.attach() and
.detach().
Changes:
- Add session.commit() after session.flush() in all five mutating
methods across ToolRegistryRepository and
ValidationAttachmentRepository.
- Add finally: session.close() to guarantee session cleanup regardless
of success or failure.
- Update class docstrings to reflect the new commit-on-write semantics.
- Add Behave BDD feature (tool_add_persist.feature) with scenarios for
single-tool round-trip, multi-tool persistence, and duplicate
rejection, using file-based SQLite to reproduce the cross-session
issue.
- Add Robot Framework integration test (tool_add_persist.robot) with
add-then-list and fresh-list-empty scenarios.
- Add ASV benchmark (tool_add_persist_bench.py) with
track_list_after_add_count metric.
Key decisions:
- File-based SQLite (not in-memory) is used in tests because the bug
only manifests when the session/engine is fully disposed between add
and list, simulating separate CLI invocations.
- Step patterns are prefixed with "tool-persist" to avoid AmbiguousStep
collisions with existing tool_registry_steps.py.
- The commit-in-repository approach was chosen over adding a UnitOfWork
to the CLI factory because the CLI commands are simple CRUD operations
that should auto-persist without requiring callers to remember to
commit.
ISSUES CLOSED: #621
Wire SkillService to use SkillRepository for database persistence,
fixing the bug where `agents skill add` stored skills only in an
in-memory OrderedDict that was lost when the CLI process exited.
Changes:
- SkillService now accepts optional skill_repo and session_factory
parameters. When provided, add_skill() persists to the database
and the constructor pre-loads existing skills from DB rows.
- _get_skill_service() in the CLI now creates a DB-backed service
following the same engine/sessionmaker/repository pattern used by
the tool CLI (tool.py).
- _reset_skill_service() now installs a fresh in-memory SkillService
(instead of setting None) to avoid DB side-effects during unit
testing with parallel runners.
- remove_skill() also persists the deletion to the database.
Test coverage:
- Behave BDD: features/skill_add_persist.feature (4 scenarios)
- Robot Framework: robot/skill_add_persist.robot (3 smoke tests)
- ASV benchmark: benchmarks/skill_add_persist_bench.py
ISSUES CLOSED: #620
Add a call to bootstrap_builtin_types() in init_command() (project.py)
immediately after initialize_project() returns. This seeds the built-in
resource types (fs-directory, git-checkout, etc.) into the database so
that "resource add" commands succeed without "Resource type not found"
errors.
The call is idempotent — invoking it multiple times will not create
duplicate types.
Also fix the TDD robot test (resource_type_bootstrap_git.robot) to
initialize a project before running "resource add", and fix a
pre-existing parallel test failure in plan_commands_new_coverage where
unittest.mock.patch could not reliably intercept PlanApplyService under
behave-parallel fork() workers.
ISSUES CLOSED: #523, #524
Add TDD-style failing tests that verify the built-in git-checkout resource
type is available after initialization. Tests assert the correct expected
behavior: after agents init, the git-checkout type should exist in the
registry and 'agents resource add git-checkout' should succeed.
Tests are expected to fail until bug #524 is fixed, because
bootstrap_builtin_types() is never called during initialization. The fix
branch should be based on this branch so the fix commit inherits these tests.
Files added:
- features/resource_type_bootstrap_git.feature (2 Behave scenarios)
- features/steps/resource_type_bootstrap_git_steps.py (step definitions)
- robot/resource_type_bootstrap_git.robot (Robot Framework smoke test)
ISSUES CLOSED: #553
Implemented the remaining ACMS pipeline components and advanced context
strategies:
Pipeline Phase 3:
- FragmentOrdererProtocol + RelevanceCoherenceOrderer: orders fragments
by relevance while maintaining narrative coherence via UKO node prefix
grouping. Groups related fragments together, sorts groups by max
relevance, and within groups orders by relevance desc / depth asc.
- PreambleGeneratorProtocol + ProvenancePreambleGenerator: generates
provenance preamble with strategy contributions (fragment counts and
token percentages), confidence indicators (avg/min/max), tier and
depth distribution, UKO node coverage, and coverage gap detection.
Advanced Strategies:
- ArceStrategy (quality 0.95): adaptive recursive context expansion with
iterative multi-backend refinement and configurable iteration limit
(default 5) to prevent unbounded refinement. Uses composite scoring
(relevance + depth + diversity) with contextual boosting for fragments
related to the current top-ranked anchor set.
- TemporalArchaeologyStrategy (quality 0.5): historical context retrieval
from graph+cold backends. Prioritises cold-tier fragments using a
temporal scoring model (tier bonus + relevance + depth).
- PlanDecisionContextStrategy (quality 0.7): decision history retrieval
from warm/cold backends. Prioritises warm then cold tier fragments
for correction and retry scenarios.
All strategies registered in strategy registry with correct quality scores
and backend requirements. All components implement their respective
Protocol interfaces and can be injected into the ContextAssemblyPipeline
via constructor dependency injection.
Tests:
- 33 BDD scenarios in features/acms_pipeline_phase3.feature
- Robot Framework integration tests in robot/acms_pipeline_phase3.robot
- ASV performance benchmarks in benchmarks/acms_pipeline_phase3_bench.py
ISSUES CLOSED: #545
Add TDD-style Behave BDD tests for the built-in fs-directory resource type
bootstrap (bug #523). Three Gherkin scenarios: one failing TDD test
reproducing the bug (no bootstrap called during init, tagged @wip), and
two regression tests verifying bootstrap_builtin_types() seeds correct
data and resource add fs-directory succeeds after bootstrap. Includes
Robot Framework regression tests.
Review feedback addressed:
- Removed all 21 unnecessary # type: ignore comments (hurui200320 M1)
- Fixed is not True to is False for clarity (Aditya F2)
- Fixed Robot common.resource path to ${CURDIR}/common.resource (hurui200320 L1)
- Squashed all commits into one and rebased onto master (C1, C2)
- Added CHANGELOG entry with correct scenario count
Closes#537
Added minimal LSP server entrypoint supporting initialize/shutdown/exit
handshake over JSON-RPC stdin/stdout transport with Content-Length
framing. Unsupported methods return MethodNotFound error with descriptive
message. Wired LSP requests through ACP facade in local mode. Added
agents lsp serve CLI command with --log-level flag, PID output, and
startup banner. Created reference documentation for the stub server.
Includes Behave BDD tests for protocol handshake, Robot smoke test, and
ASV startup latency benchmark.
ISSUES CLOSED: #203
Core domain types (FragmentProvenance, ContextFragment, ContextBudget,
ContextPayload) now extend their CRP counterparts via Pydantic v2
inheritance, ensuring isinstance compatibility across the model
hierarchy.
Key changes:
- CRP base types made frozen=True (no consumer mutates them)
- CRP AssembledContext fields changed from list to tuple (frozen consistency)
- Core types extend CRP bases: FragmentProvenance(CRPFragmentProvenance),
ContextFragment(CRPContextFragment), ContextBudget(CRPContextBudget),
ContextPayload(CRPAssembledContext)
- Removed duplicate ContextFragment dataclass from skeleton_compressor
- Updated project_context.py to pass tuples to frozen AssembledContext
- Added Behave tests (10 scenarios), Robot integration tests (3 cases),
and ASV benchmarks for the unified hierarchy
- Updated Known Limitations table in docs/reference/acms.md
ISSUES CLOSED: #569
- SPEC-1: Added genuine TDD failing Scenario 1 (@wip) that creates registry
WITHOUT bootstrap and asserts git-checkout exists — reproduces bug #524.
Existing scenarios retained as regression tests (no @wip since they pass).
Added NOTE FOR FIX AUTHOR comment documenting fix-path expectations.
- BUG-1: Removed colliding @when('I run "agents resource add..."') step.
Replaced with uniquely-prefixed bootstrap-git step pattern that invokes
resource_add() directly with mocked DI, avoiding AmbiguousStep collision
with wildcard @when('I run "{command}"') in cli_plan_context_commands_steps.
- BUG-2: Removed duplicate @then('the CLI exit code should be {code:d}').
Replaced with prefixed bootstrap-git assertion steps.
- BUG-3: Removed duplicate @then('the CLI output should not contain...").
Replaced with prefixed bootstrap-git assertion steps.
- TEST-1: Replaced bare MagicMock() with direct service patching via
_PATCH_SERVICE, consistent with PR #567 pattern.
- TEST-2: Updated Robot docs from 'expected to FAIL' to 'regression tests'
since both Robot tests call bootstrap explicitly and pass.
- CODE-1: Simplified hasattr guards on enum fields — removed redundant
hasattr checks, using .value directly since ResourceKind and
SandboxStrategy are always enums.
- TEST-3: Added assertion on bootstrap_builtin_types() return value via
new Then step 'the bootstrap-git registered types should include'.
- Updated CHANGELOG from 'Two scenarios' to 'Three scenarios'.
Refs: #553
Implemented the analyzer plugin framework with AnalyzerProtocol,
AnalyzerRegistry for registration/discovery by file extension,
PythonAnalyzer (AST-based extraction of modules, classes, functions,
imports, docstrings), and MarkdownAnalyzer (section, code block, and
link extraction). Both analyzers produce well-formed UKO triples with
proper URI schemes.
ISSUES CLOSED: #551
Add the Depth/Breadth Projection System and Skeleton Context
Propagation as specified in docs/specification.md §25265-25340
and §43057-43128:
- ProjectionSpec: frozen Pydantic model capturing a projection
request (focus, breadth, depth, gradient, domain)
- ProjectedNode: frozen model for materialized graph nodes with
resolved depth and distance
- DepthBreadthProjector: stateless BFS projector over UKO graph
adjacency with depth gradient (linear reduction by distance)
- PlanContextInheritance: service computing child plan context
from parent assembled context with skeleton injection
- ChildContextResult: frozen result model with request and skeleton
- InheritanceConfig: frozen config for skeleton_ratio (default 0.2)
- Built-in DetailLevelMap presets for code, docs, and database
Includes 27 Behave BDD scenarios, 9 Robot Framework integration
tests, and ASV benchmarks for all components.
ISSUES CLOSED: #544
Add production-grade Phase 2 (Fragment Fusion) components for the ACMS
context assembly pipeline, replacing the no-op defaults:
- ContentHashDeduplicator: Groups fragments by UKO node URI, hashes
content to detect duplicates, retains highest relevance_score.
- MaxDepthResolver: Resolves depth conflicts by keeping the highest
detail depth per UKO node, with relevance tiebreaking.
- WeightedCompositeScorer: Computes composite score from configurable
weighted factors (relevance=0.4, hierarchy=0.3, quality=0.2,
recency=0.1). Stores component breakdown in metadata.
- GreedyKnapsackPacker: Greedy knapsack selection with depth fallback
(tries depths [9,4,2,0] for oversized fragments) and minimum
fragment token threshold (10).
Also adds:
- ScoredFragment frozen Pydantic model (spec §42825) with
composite_score, score_components, and fragment reference
- score_detailed() method on WeightedCompositeScorer returning
ScoredFragment objects for callers needing full breakdowns
- All components implement v1 Protocol signatures from acms_service.py
and can be DI-injected into ACMSPipeline constructor
Testing:
- 31 Behave BDD scenarios in acms_pipeline_phase2.feature covering
deduplication, depth resolution, scoring, packing, depth fallback,
budget constraints, pipeline integration, and ScoredFragment model
- 6 Robot Framework integration smoke tests
- ASV benchmark suites for all 4 components and ScoredFragment
Quality gates: lint, typecheck (0 errors), unit_tests (8555 scenarios),
coverage (97.0%), dead_code — all passing.
ISSUES CLOSED: #540
Add production-quality Phase 1 pipeline components for the ACMS
Context Assembly Pipeline:
- ConfidenceWeightedSelector: strategy selection with preference
boosting and confidence-based ranking
- ProportionalBudgetAllocator: proportional token budget distribution
with min_useful_budget enforcement and largest-remainder rounding
- ParallelStrategyExecutor: concurrent strategy execution via
ThreadPoolExecutor with per-strategy timeouts and circuit breaking
- CircuitBreaker: per-strategy failure tracking with configurable
threshold and explicit reset
- ContextAssemblyPipeline: extends ACMSPipeline with Phase 1
production components and per-stage timing (StageTimings)
Includes 28 Behave BDD scenarios, 9 Robot Framework integration tests,
and ASV benchmarks for all components.
ISSUES CLOSED: #539
Created ScoredFragment frozen model wrapping ContextFragment with
composite_score, score_breakdown, and rank fields. Added pipeline-
specific fragment models in domain/contexts/ with proper equality
based on uko_uri + detail_depth for deduplication support.
ISSUES CLOSED: #538
Implement the first three built-in context strategies for the ACMS v1
context assembly pipeline:
1. SimpleKeywordStrategy (quality 0.3) - Keyword matching on fragment
content with word-density fallback. Universal fallback strategy.
2. SemanticEmbeddingStrategy (quality 0.6) - Jaccard word-overlap
similarity scoring between query and fragment content.
3. BreadthDepthNavigatorStrategy (quality 0.85) - UKO node hierarchy
navigation prioritising fragments near focus nodes with higher
detail depths. Primary strategy for code projects.
All strategies implement the v1 ContextStrategy Protocol from
acms_service.py and can be registered with ACMSPipeline via
register_strategy().
Includes:
- 28 Behave BDD scenarios covering ranking, budget, capabilities,
can_handle confidence, explain, empty input, and pipeline
registration
- 9 Robot Framework integration tests
- ASV benchmarks at 10/100/1000 fragment scales for all 3 strategies
- Vulture whitelist entries for public API symbols
- 100% coverage on context_strategies.py
ISSUES CLOSED: #541
- Add AsyncJob domain model with status state machine and Pydantic validation
- Add AsyncWorker service with configurable concurrency and job store
- Add CancellationToken, WorkerHealthReport, InMemoryJobStore
- Add AsyncJobModel SQLAlchemy model and Alembic migration (m6_003)
- Add 5 async config keys to Settings (worker_id, concurrency, poll_interval, max_retries, timeout)
- Add _check_async_worker_health diagnostic check in system.py
- Add comprehensive Behave BDD tests (~60 scenarios) with full step definitions
- Add Robot Framework integration tests (6 smoke tests)
- Add ASV benchmark suite for async execution
- Add architecture documentation
- Update vulture_whitelist with new public API symbols
- All quality gates pass: lint, typecheck, unit_tests, integration_tests, coverage_report (97%)
1. Wire async job creation into PlanLifecycleService:
- Add optional job_store parameter to __init__
- Add _maybe_enqueue_async_job() helper that checks settings.async_enabled
and job store presence before creating and enqueuing an AsyncJob
- Call helper from execute_plan() (phase="execute") and apply_plan()
(phase="apply") after phase transitions
- When async is disabled or no job store is configured, behaviour is
unchanged (silent no-op)
2. Redact secrets in failed job error messages:
- Apply shared.redaction.redact_value() to the error string before
persisting to AsyncJob.error_message, preventing accidental secret
leakage (e.g. API keys in exception text) into the audit trail
Documentation:
- S1: Added specification reconciliation note (ADR-style) to
async_architecture.md addressing tension between "No Plan Queuing"
clause and the async subsystem authorised by issue #312
ISSUES CLOSED: #312