Commit Graph

733 Commits

Author SHA1 Message Date
brent.edwards b99510d016 fix(test): derive decision type count from enum instead of hard-coding 11
Replace hard-coded '11 decision types' with dynamic len(DecisionType) in
the assertion and remove the literal from scenario names, step patterns,
docstrings, and docs so the tests stay correct when new DecisionType
values are added.
2026-02-26 01:19:28 +00:00
brent.edwards 93730067a2 fix(test): address review findings in M3 smoke tests
- Replace dead after_scenario() hook with context.add_cleanup() calls
  so patchers are properly stopped (Behave only runs hooks from
  environment.py)
- Fix invalid ULID constants: pad DECISION/CORRECTION to 26 chars,
  replace invalid 'I' with 'J' in INVARIANT_ULID
- Add temp file cleanup for NamedTemporaryFile(delete=False) via
  context.add_cleanup() in behave steps and try/finally in robot helper
- Remove decision-persistence doc sections from testing.md that belong
  in PR #438, not this PR
2026-02-26 01:13:16 +00:00
brent.edwards ef58883f7a fix(test): harden retry_patterns feature against flaky CI failures
The jitter-spread scenario used millisecond-bucketed wall-clock
timestamps to assert that retried operations did not cluster.  On busy
CI runners — especially when a preceding scenario's time.sleep patch
leaked through a late cleanup — tenacity's retry waits became no-ops
and all five operations landed in the same millisecond bucket, tripping
the max_in_bucket <= 3 assertion.

Three hardening changes:

1. Jitter test: switch from time.time() to time.monotonic_ns() and
   replace the fragile bucket assertion with a unique-timestamp count
   (>= 2 distinct readings among 5 sequential operations).
2. Timeout test: eagerly restore time.sleep in a try/finally block so
   subsequent scenarios never observe the patched no-op, regardless of
   behave's cleanup ordering.
3. Async circuit breaker: lower recovery_timeout from 0.2 s to 0.1 s
   (the sleep step already waits 0.2 s) to give a wider safety margin
   on slow CI machines.
2026-02-26 00:51:11 +00:00
freemo 3a2b134f3c test(coverage): add Behave scenarios for remaining under-tested modules
Added Behave BDD feature files and step definitions targeting coverage
gaps in six modules:

- container.py: exercise get_database_url env-var fallback, AI provider
  None path, cached container singleton, override_providers edge cases
  (lines 66-69, 125-130; branches at 51, 57, 82, 87, 256, 284-288)
- correction_service.py: exercise exception-handling paths in
  execute_revert and execute_append via monkeypatched analyze_impact
  and ULID failures (lines 254-262, 320-328)
- plan_lifecycle_service.py: exercise _persisted UoW commit paths,
  InvalidPhaseTransitionError custom message branch, non-reusable
  action archive, and error_details merge logic (branches at 100,
  216, 237, 327, 461, 570, 576, 607)
- plan.py (CLI): exercise spec-dict optional field branches,
  _print_lifecycle_plan conditional rendering, use_action argument
  parsing, auto-resolve paths, legacy wrappers, and validation
  error branches across 66 scenarios
- skill.py (CLI): exercise singleton cache, timestamp-absent show,
  no-tools MCP, add/remove/list/show format and error branches
  across 26 scenarios
- models.py (DB): exercise to_domain/from_domain None-field branches
  in SkillModel, SessionModel, ToolModel, LifecycleActionModel,
  LifecyclePlanModel, NamespacedProjectModel, and SessionMessageModel
  across 41 scenarios

All 302 features, 6503 scenarios, 28271 steps pass (nox -e unit_tests).

ISSUES CLOSED: #446
2026-02-25 19:38:43 -05:00
brent.edwards c80cda2590 Merge feature/m4-correction-subplan-smoke into develop-brent-5 2026-02-25 22:11:33 +00:00
brent.edwards 5a212481e1 Merge branch 'feature/m4-decision-tests' into develop-brent-5 2026-02-25 22:10:38 +00:00
brent.edwards 917c2bc546 test(e2e): add M4 correction + subplan suites 2026-02-25 21:51:26 +00:00
brent.edwards ace7311de4 test(e2e): add M3 decision + validation suites 2026-02-25 21:26:19 +00:00
brent.edwards f4c4884d03 test(persistence): add decision persistence suites
Add comprehensive persistence test suites for the Decision domain model
covering serialization round-trips (model_dump/model_validate, JSON),
context-snapshot persistence, correction-chain reconstruction, and
decision-tree reconstruction from serialized data.

Deliverables:
- Behave: 21 scenarios in features/decision_persistence.feature
- Robot Framework: 7 integration tests in robot/decision_persistence.robot
- ASV benchmarks: 4 suites (17 benchmarks) in benchmarks/decision_persistence_bench.py
- Documentation: Updated docs/development/testing.md

ISSUES CLOSED: #180
2026-02-25 21:19:57 +00:00
brent.edwards d055b59d7c Merge branch 'master' into develop-brent-4 2026-02-25 20:05:18 +00:00
brent.edwards 3b58432ecc docs(merge): merge new docs into branch 2026-02-25 19:41:56 +00:00
freemo c4f71e930d feat(concurrency): add plan resume
Implement step-level progress persistence and plan resume with graceful
shutdown handling.

- Add ResumeCheckpoint, ResumeMetadata, ResumeEligibility, ResumeSummary
  domain models (resume.py)
- Add PlanResumeService with validate_eligibility(), build_resume_summary(),
  resume_plan(dry_run), record_step_checkpoint(), record_shutdown()
- Add last_completed_step and last_checkpoint_id fields to Plan model
- Add 'plan resume' CLI command with --dry-run flag
- Update plan lifecycle docs (ADR-006) with resume behavior section
- Add Behave tests (24 scenarios in plan_resume.feature)
- Add Robot Framework integration tests (10 tests)
- Add ASV benchmarks for resume overhead

Closes #328
2026-02-25 14:00:04 -05:00
freemo 134dce896a feat(provider): add cost controls and fallback
Add token/cost tracking, budget enforcement (per-plan and per-day),
provider fallback selection with capability filtering, and cost
metadata for plan models.

New modules:
- providers/cost_table.py: CostEntry + ProviderCostTable with default
  pricing for OpenAI, Anthropic, Google, Groq, Together, Cohere, Mock
- providers/cost_tracker.py: BudgetStatus enum, BudgetCheckResult,
  CostTracker with warn-at-90%/block-at-100% enforcement
- providers/fallback_selector.py: FallbackSelector with capability
  filtering (tool_calls, streaming, vision, json_mode) and budget
- domain/models/core/cost_metadata.py: CostMetadata + BudgetExhaustionEvent

Modified:
- config/settings.py: budget_per_plan, budget_per_day, fallback_providers
- domain/models/core/plan.py: cost_metadata field + CLI dict surfacing
- providers/__init__.py: public exports for new classes

Testing:
- 71 Behave scenarios in features/cost_controls.feature (all pass)
- 6 Robot Framework integration tests (all pass)
- ASV benchmarks in benchmarks/cost_controls_bench.py
- nox lint, typecheck, format, docs, build, dead_code, security_scan pass

Closes #324
2026-02-25 12:08:01 -05:00
freemo 7a298ede6e feat(concurrency): add plan and project locks
Implemented plan-level and project-level locking with configurable timeouts.
Added locks table via Alembic migration storing owner_id, resource_type,
resource_id, acquired_at, and expires_at. Locks enforced in
PlanLifecycleService transitions. Support for re-entrant acquisition,
lock renewal, graceful shutdown release, and startup cleanup of expired
locks. Added diagnostics check for stale lock reporting.

ISSUES CLOSED: #327
2026-02-25 10:48:05 -05:00
aditya 2f9707cfdf refactor(mcp): fix mock placement, type annotation, and constructor validation
- Extract MockMCPTransport to features/mocks/mock_mcp_transport.py
- Use ToolRegistry type with TYPE_CHECKING in register_tools()
- Move transport config validation into __init__ via _validate_config()
2026-02-25 14:17:34 +00:00
aditya ee82d6101e feat(skill): add MCP adapter for external tools
Implement MCPToolAdapter to connect to external MCP servers, enumerate
tools, and register them in ToolRegistry with source="mcp". Includes
connect/reconnect/disconnect lifecycle with timeout enforcement, input
validation on invoke, capability inference, Behave/Robot/ASV tests, and
docs/reference/mcp_adapter.md.

ISSUES CLOSED: #159
2026-02-25 13:17:26 +00:00
aditya 913fd31e07 Merge branch 'master' into feature/m2-actor-yaml 2026-02-25 10:31:07 +00:00
aditya e476d2de0e feat(actor): extend hierarchical actor YAML schema and loader
Extend actor YAML schema to support hierarchical graphs with explicit
node types (agent, tool, conditional, subgraph), per-node LSP bindings
(lsp_binding with server, languages, auto, capabilities), and tool-source
references (skills, mcp_servers, agent_skills).

Add schema validation for namespaced actor references, duplicate node IDs,
edge target existence, and graph reachability — all nodes must be reachable
from entry_node via explicit edges or conditional node routing targets.

Update loader to report YAML parse errors with precise line/column positions
and schema validation errors with dotted field paths and remediation hints
pointing to docs/reference/actor_config.md.

Add docs/reference/actor_config.md as the practical configuration reference
covering hierarchical graph examples, node type table, topology rules, and
common error cases with fix guidance.

Refresh examples/actors/graph_workflow.yaml to replace deprecated actor_path
with actor_ref. Add benchmarks/actor_yaml_bench.py for schema load overhead.

Tests: 95 Behave scenarios, 10 Robot smoke tests (including hierarchical
loader smoke test), security scan clean, coverage 99% (threshold 97%).

ISSUES CLOSED: #157
2026-02-25 10:30:42 +00:00
CoreRasurae f5e4771e78 test(unit): fix failing unit tests 2026-02-25 10:07:09 +00:00
CoreRasurae d6c58344d1 test(coverage): add 32 BDD scenarios to boost coverage from 97.0% to 97.2%
Add coverage boost tests targeting low-coverage modules:
- skills/registry.py: validate_skill error paths
- cli/formatting.py: format_output_session, _format_table branches
- cli/commands/system.py: health check functions
- cli/commands/session.py: CRUD command edge cases
- cli/commands/cleanup.py: error handling paths
- cli/commands/audit.py: audit service creation
- application/container.py: container init/reset

All 32 new scenarios pass alongside existing 29 security template
scenarios. Full nox -s coverage_report confirmed at 97.2%.
2026-02-25 10:06:59 +00:00
CoreRasurae a7dc917021 fix(security): harden template rendering
ISSUES CLOSED: #319
2026-02-25 10:06:27 +00:00
CoreRasurae 8604bc66b6 fix(security): enforce explicit exception handling
ISSUES CLOSED: #320
2026-02-25 10:05:57 +00:00
CoreRasurae d70a5d84ae feat(plan): add error recovery patterns and CLI hints
ISSUES CLOSED: #186
2026-02-25 10:05:10 +00:00
CoreRasurae fe69d132f1 feat(dod): enforce definition-of-done gating
ISSUES CLOSED: #178
2026-02-25 10:04:31 +00:00
CoreRasurae 4874f2ad6f feat(validation): add validation pipeline and results model
ISSUES CLOSED: #175
2026-02-25 10:03:57 +00:00
CoreRasurae 57fcc880c3 feat(apply): run validation attachments
ISSUES CLOSED: #176
2026-02-25 10:03:21 +00:00
CoreRasurae 95b6ed57c2 feat(change): add diff review artifacts
ISSUES CLOSED: #303
2026-02-25 10:02:38 +00:00
CoreRasurae ab6a3fd732 feat(apply): add validation-gated apply pipeline
ISSUES CLOSED: #155
2026-02-25 10:01:57 +00:00
brent.edwards e230700857 Merge feature/m1-e2e-sourcecode into develop-brent-4 2026-02-25 06:36:45 +00:00
brent.edwards dbc9be9fc0 Merge feature/m2-actor-tool-smoke into develop-brent-4 2026-02-25 06:35:44 +00:00
brent.edwards 0397a00eb6 test(e2e): add M1 source-code plan lifecycle suite 2026-02-25 04:50:43 +00:00
brent.edwards 9bf87a20d9 chore(pr): address code review feedback for PR #421
- Added CHANGELOG.md entry for M2 E2E test suite (CONTRIBUTING.md §6)
- Added Brent E. Edwards to CONTRIBUTORS.md (CONTRIBUTING.md §8)
- Fixed docs/development/testing.md: corrected M2 Behave scenario count
  from 11 to 10 to match actual feature file
- Added standard explanatory comments to benchmark sys.path setup
  for consistency with project convention (advisory)
- Replaced untyped lambda handler with typed _m2_noop_handler function
  in step definitions (advisory)

All nox stages pass: lint, typecheck, format, unit_tests (280 features /
5846 scenarios / 0 failures), integration_tests (682 passed),
coverage_report (97.2%).

ISSUES CLOSED: #169
2026-02-25 04:13:55 +00:00
brent.edwards a2a91c3d9c Merge branch 'master' into feature/m2-actor-tool-smoke 2026-02-24 21:59:58 +00:00
brent.edwards c8434e21f3 Merge branch 'master' into feature/m4-cli-extension-tests 2026-02-24 21:56:43 +00:00
brent.edwards 093a74953f test(e2e): add M2 actor + tool source smoke suite
Add comprehensive E2E test suite for M2 (Actor Graphs + Tool Sources) epic:

- Behave BDD: 10 scenarios covering actor YAML loading, skill registry,
  tool lifecycle (discover/activate/execute/deactivate), and MCP stub
- Robot Framework: 6 integration tests via CLI helper script
- ASV benchmarks: 12 benchmarks for actor loading, skill registry,
  tool lifecycle, and MCP stub performance baselines
- MCP stub server mock: in-process fake with 3 tools (search/fetch/transform)
- Fixtures: hierarchical graph actor YAML + skill pack with tool refs and
  inline tools
- Docs: updated testing.md with M2 smoke suite section

Closes #169
2026-02-24 21:55:24 +00:00
brent.edwards 2c21611ad5 test(cli): cover action and plan extensions
Added comprehensive test coverage for CLI extension features from #325:
- Behave scenarios for automation_profile resolution, invariant ordering,
  and actor override error cases
- Output snapshot assertions for JSON/YAML/table formats
- Robot integration test for action show with optional actors/invariants
- ASV benchmark for extended CLI scenario runtime baseline
- Updated testing.md with CLI extension test fixture documentation

ISSUES CLOSED: #326
2026-02-24 20:11:42 +00:00
freemo 25c571541f feat(skill): integrate agent skills discovery
Add agent skills discovery system that scans configurable filesystem
paths for Agent Skills Standard folders (containing SKILL.md with YAML
front-matter) and registers them as tools in ToolRegistry.

Core implementation:
- New skills/discovery.py module with path parsing, directory scanning,
  SKILL.md front-matter parsing, ToolSpec building, and registration
  with configurable conflict handling (skip/error/replace strategies)
- Config key skills.agent_skills_paths for comma-separated discovery paths
- ToolSpec extended with source and source_metadata fields for provenance
- ToolRegistry.list_tools() gains source filter parameter
- SkillRegistryService rewritten with discover_and_register() and
  refresh_agent_skills() hooks for on-demand re-scanning
- CLI "agents skill tools" command updated with --refresh flag and
  source metadata in JSON output

Testing:
- 27 Behave scenarios covering config key, path parsing, discovery,
  ToolSpec building, registration, conflict handling, refresh, edge
  cases (invalid YAML, empty front-matter, non-dict YAML, empty
  descriptions, noop handler), and source metadata
- 10 Robot Framework integration tests for end-to-end discovery flow
- ASV benchmarks for discovery scan performance overhead

Documentation:
- docs/reference/skill_registry.md updated with Agent Skills Discovery
  section covering config, algorithm, SKILL.md format, conflict
  handling, refresh hook, CLI output, and service API

ISSUES CLOSED: #161
2026-02-24 19:41:29 +00:00
freemo f7993d7309 feat(cli): align actor commands to YAML
Align actor add/remove/list/show commands to YAML-first configs,
namespaced names, and --format json|yaml|plain output support.

Changes:
- Add --format option to list, show, add, and update commands
- Add --update flag to add command for updating existing actors
- Add _actor_spec_dict helper for structured output serialization
- Update _print_actor to support format_output rendering
- Add Behave feature tests for CLI format scenarios (11 scenarios)
- Add Robot Framework integration test for show output fields
- Add ASV benchmark for actor CLI parsing overhead
- Add CLI reference documentation for actor commands

ISSUES CLOSED: #288
2026-02-24 19:12:01 +00:00
brent.edwards aa06b7aa37 Merge branch 'master' into fix/database-parallelism 2026-02-24 18:33:45 +00:00
freemo c47e6445d0 feat(actor): compile hierarchical actor configs to LangGraph
Add ActorCompiler module that translates GRAPH-type ActorConfigSchema
definitions into LangGraph NodeConfig/Edge structures with LSP binding
metadata. Includes subgraph resolution with cross-actor cycle detection,
entry/exit validation, and CompilationMetadata for diagnostics.

New files:
- src/cleveragents/actor/compiler.py: Core compiler with compile_actor()
- features/actor_compiler.feature: 13 Behave scenarios
- features/steps/actor_compiler_steps.py: Step definitions
- robot/actor_compiler.robot: 4 Robot smoke tests
- benchmarks/actor_compiler_bench.py: ASV performance benchmarks
- docs/reference/actor_compiler.md: Compilation pipeline reference

Modified:
- src/cleveragents/actor/__init__.py: Export compiler types
- vulture_whitelist.py: Whitelist new public API

ISSUES CLOSED: #158
2026-02-24 17:57:18 +00:00
freemo 55aee7cf22 fix(test): commit after each add_skill to prevent session GC rollback, and improved coverage.
The step_register_skills_table step called add_skill in a loop but only
committed once at the end. Because SkillRepository.create() obtains a
new session per call and only flushes (never commits), the intermediate
sessions could be garbage-collected before the final commit, rolling
back their transactions on the shared SQLite :memory: connection. Moving
_commit_pending inside the loop ensures each skill is durably committed
before the next session is created.

ISSUES CLOSED: #418
2026-02-24 12:19:04 -05:00
brent.edwards c402e6402b Merge branch 'master' into fix/database-parallelism 2026-02-24 16:02:53 +00:00
freemo aa008ba5d7 feat(cli): add action and plan CLI extensions
Add extended CLI flags and output rendering for plan and action
commands in the v3 plan lifecycle.

Plan use command:
- --automation-profile flag validates against BUILTIN_PROFILES and
  persists to plan metadata with PLAN provenance
- --invariant flag (repeatable) passes PlanInvariant objects with
  InvariantSource.PLAN to PlanLifecycleService.use_action()
- --strategy-actor, --execution-actor, --estimation-actor, and
  --invariant-actor flags validate namespace/name format via
  validate_namespaced_actor() before setting on the plan

Plan status/list output:
- Profile and Invariants columns added to plan status summary table
- Profile and Invariants columns added to lifecycle-list table
- _plan_spec_dict includes estimation_actor, invariant_actor, and
  invariants fields in all output formats (json, yaml, plain, table)
- _print_lifecycle_plan rich panel displays invariants with source
  provenance tags

Action show output:
- _print_action displays estimation_actor, invariant_actor,
  invariants list, inputs_schema, and automation_profile when present
- _action_spec_dict conditionally includes estimation_actor,
  invariant_actor, and inputs_schema fields

Documentation:
- docs/reference/plan_cli.md documents all extended flags, actor
  override validation, and usage examples
- docs/reference/action_cli.md documents extended output fields and
  YAML configuration options

Tests:
- 29 Behave scenarios in features/cli_extensions.feature covering
  automation profile, invariant flags, actor override validation,
  plan status/list rendering, and action show extended fields
- 5 Robot Framework integration tests in robot/cli_extensions.robot
  for plan use with invariants, profiles, and actor validation
- 6 ASV benchmark suites in benchmarks/cli_extensions_bench.py
  measuring parsing overhead for all new flags and rendering paths

ISSUES CLOSED: #325
2026-02-24 13:41:11 +00:00
brent.edwards dd963daeaa Merge branch 'master' into fix/database-parallelism 2026-02-24 00:45:01 +00:00
brent.edwards f2b9ccfde4 fix(test): isolate parallel behave subprocesses with per-scenario temp databases
Each behave-parallel worker previously resolved to the same file-based
SQLite database (cleveragents.db or .cleveragents/db.sqlite) because
before_scenario removed the CLEVERAGENTS_DATABASE_URL env var and the
fallback paths are shared across processes.  Under parallel execution
this caused intermittent 'database is locked' and duplicate-project
errors—most visibly in the coverage_report nox session.

Replace the env-var removal in before_scenario with unique temp database
paths via tempfile.mktemp(), giving every scenario its own isolated
database file.  Temp files are cleaned up in after_scenario.

Also fix cli_streaming_steps.py where a Background + duplicate Given
sequence triggered a duplicate project name collision, and update
coverage_boost_steps.py so Settings-default assertions explicitly clear
the env vars before testing pydantic defaults.
2026-02-24 00:41:01 +00:00
khyari hamza 2c46a0be5a revert(test): remove StaticPool from skill registry in-memory db
Reverts the StaticPool fix (68bc068) as it is no longer needed on
develop-hamza-2. Restores the original SingletonThreadPool default
for sqlite:///:memory: engine creation.
2026-02-23 22:20:44 +00:00
khyari hamza 1eb028402c fix(test): use StaticPool for skill registry in-memory db
The default SingletonThreadPool for sqlite:///:memory: can
non-deterministically lose flushed data when multiple sessions are
created without closing (as in the bulk-register table step).
Under CI with coverage --parallel-mode and behave-parallel --processes 32,
this caused list_all() to return 2 skills instead of 3.

StaticPool guarantees all sessions share the exact same DBAPI connection,
which is the SQLAlchemy-recommended pattern for :memory: test databases.
2026-02-23 22:20:44 +00:00
khyari hamza 1a0a501f66 refactor(resource): address PR review feedback for handler runtime
- extract BaseResourceHandler to eliminate ~90% duplication between
  GitCheckoutHandler and FsDirectoryHandler
- raise RuntimeError when sandbox.context is None instead of silent
  empty string fallback
- add threading.Lock to resolver handler cache for thread safety
- type resource_lookup/type_lookup as Callable instead of Any
- log original HandlerResolutionError at DEBUG before fallback
- use behave.runner.Context in step definitions per repo convention
2026-02-23 22:20:44 +00:00
khyari hamza bfc6ab0fb1 feat(resource): add handler runtime for git-checkout and fs-directory 2026-02-23 22:20:44 +00:00
khyari hamza 229dbc8925 refactor(decision): address PR review feedback
- add with_superseded_by() helper for frozen model mutation
- document frozen model + superseded_by interaction in docstring
- clarify sequence_number uniqueness is a persistence concern
- add scenario for invalid corrects_decision_id ULID validation
- add scenario for with_superseded_by copy behavior
- type step helper dict as dict[str, Any]
2026-02-23 22:20:03 +00:00