Commit Graph

1050 Commits

Author SHA1 Message Date
brent.edwards f2e44b2cf1 Merge remote-tracking branch 'origin/master' into feature/m3-fix-actor-list-empty
# Conflicts:
#	features/mocks/fake_provider.py
2026-03-11 03:40:37 +00:00
brent.edwards 5b9f0554c0 Merge pull request 'test(actor): add TDD failing tests for actor list empty validation error' (#655) from tdd/actor-list-validation into master
Reviewed-on: cleveragents/cleveragents-core#655
Reviewed-by: Hamza Khyari <hamza.khyari@cleverthis.com>
2026-03-11 03:37:23 +00:00
brent.edwards 1a1d0a7fbb fix(test): remove self-inversion from actor list Robot helper
The helper was written before the tdd_expected_fail_listener existed and
inverted pass/fail internally.  After merging master the listener is now
active, causing a double inversion that made all three tdd_bug_592 Robot
tests fail with 'bug appears to be fixed — remove the tag'.

Switch to the real-outcome convention: exit 0 + sentinel when the bug is
fixed, exit 1 when the bug is still present, and let the listener handle
inversion.

ISSUES CLOSED: #634
2026-03-11 03:21:50 +00:00
brent.edwards 205e94eb52 Merge remote-tracking branch 'origin/master' into feature/m3-fix-actor-list-empty
# Conflicts:
#	CHANGELOG.md
#	noxfile.py
2026-03-11 03:12:52 +00:00
brent.edwards 5c5de082f2 Merge remote-tracking branch 'origin/master' into tdd/actor-list-validation
# Conflicts:
#	benchmarks/tdd_session_create_di_bench.py
#	features/steps/tdd_session_create_di_steps.py
#	robot/helper_tdd_session_create_di.py
#	robot/tdd_session_create_di.robot
2026-03-11 03:07:42 +00:00
brent.edwards 70da5572a6 Merge pull request 'test(session): add TDD failing tests for session create DI error' (#654) from tdd/session-create-di-error into master
Reviewed-on: cleveragents/cleveragents-core#654
2026-03-11 02:50:22 +00:00
brent.edwards aa5d5eeaf5 test(session): add TDD failing tests for session create DI error
Implement TDD bug-capture tests for bug #570 where `agents session create`
fails because `_get_session_service()` calls `container.db()` which does
not exist on the DI Container class (AttributeError). Same root cause as
bug #554.

Behave BDD scenarios tagged @tdd_bug @tdd_bug_570 @tdd_expected_fail
exercise the real DI path (no mocks). Includes Robot Framework integration
smoke tests with self-inverting helper and ASV benchmark baseline.

ISSUES CLOSED: #631
2026-03-11 02:42:13 +00:00
hamza.khyari afaae615f2 Merge pull request 'feat(acms): implement Temporal Data Model (Revision-Aware RDF) with 3 storage tiers' (#615) from feature/m6-temporal-data-model-revision-aware-rdf into master
Reviewed-on: cleveragents/cleveragents-core#615
Reviewed-by: Brent Edwards <brent.edwards@cleverthis.com>
2026-03-11 01:43:38 +00:00
hamza.khyari d5f7f15215 feat(acms): implement Temporal Data Model (Revision-Aware RDF) with 3 storage tiers
Temporal metadata fields (validFrom, validUntil, isCurrent, isRevisionOf)
on UKO InformationUnit nodes enable revision chain tracking: when code
changes, old nodes are marked historical and new revision nodes are
created with back-links. Three storage tiers (hot/warm/cold) filter
nodes by temporal scope (current/recent/all) with configurable retention
(warm_retention_hours default 24h, cold_retention_days default 90d).

Includes TemporalMetadata, TemporalNode, RevisionChain, TierQueryResult,
TierRetentionConfig frozen domain models, TemporalBackend protocol,
InMemoryTemporalBackend stub, TemporalService with structlog and DI,
BackendSet.temporal typing upgrade from object|None to TemporalBackend|None.
67 Behave scenarios, 8 Robot Framework tests, ASV benchmarks, and
reference documentation.

ISSUES CLOSED: #577
2026-03-11 01:36:06 +00:00
hamza.khyari 95808fdf77 Merge pull request 'feat(acms): implement Real-time Index Sync / UKOIndexer with pluggable analyzers' (#612) from feature/m5-realtime-index-sync-ukoindexer into master
Reviewed-on: cleveragents/cleveragents-core#612
Reviewed-by: Brent Edwards <brent.edwards@cleverthis.com>
2026-03-11 01:33:38 +00:00
hamza.khyari 12b026e100 Merge remote-tracking branch 'origin/master' into feature/m5-realtime-index-sync-ukoindexer 2026-03-11 01:26:26 +00:00
brent.edwards 0a7892b030 Merge pull request 'test(session): add TDD failing tests for session list DI error' (#653) from tdd/session-list-di-error into master
Reviewed-on: cleveragents/cleveragents-core#653
Reviewed-by: Aditya Chhabra <aditya.chhabra@cleverthis.com>
2026-03-11 00:49:26 +00:00
Brent E. Edwards bed7072dde fix(tdd): restore tdd_expected_fail tags and fix Robot helper inversion
Bug #554 is NOT yet fixed — the DI container still lacks a db provider.
The previous commit incorrectly removed tdd_expected_fail tags, exposing
the real failures in Behave unit tests (13 scenarios).

Root cause: the Robot helper had its own pass/fail inversion (a workaround
from before tdd_expected_fail_listener existed).  The master merge brought
in the listener, causing double inversion that made Robot tests appear to
pass.  This commit:

- Rewrites the helper to report real outcomes (exit 0 = bug fixed)
- Restores tdd_expected_fail on all 16 Robot + Behave scenarios
- Lets the listener (Robot) and environment.py (Behave) handle inversion
2026-03-11 00:40:35 +00:00
hamza.khyari 1e606553d4 feat(acms): implement Real-time Index Sync / UKOIndexer with pluggable analyzers
Implement the UKOIndexer service that produces UKO triples from resources
using pluggable domain-specific analyzers, wraps each triple with provenance
metadata, and simultaneously indexes into text, vector, and graph backends.

Key design decisions and components:

- UKOIndexer orchestrates the full index lifecycle: add_resource,
  update_resource (remove-then-add), remove_resource, and maintenance
  triggers. Each operation fires lifecycle hooks (on_indexed, on_removed,
  on_error) so callers can observe progress.

- Analyzer selection is pluggable via ContentAnalyzer protocol. The indexer
  accepts a registry mapping resource types to analyzers. PythonAnalyzer
  and MarkdownAnalyzer are provided as built-in implementations.

- LocationContentReader protocol abstracts file I/O with a base_dir
  parameter for path-traversal prevention (post-resolve validation rejects
  paths escaping the base directory and non-regular files).

- UKOTriple model includes a @model_validator ensuring at least one of
  object_uri or object_value is populated, preventing empty triples at
  construction time.

- Triple removal uses scoped deletion via uko:sourceResource predicate to
  avoid shared-subject collision — only triples originating from the
  specific resource are removed, not all triples for a shared subject.

- _resource_subjects.pop is deferred until after all backend removal
  operations succeed, preventing inconsistent state on partial failure.

- analyzer.analyze() is wrapped in try/except so that analyzer errors
  produce an IndexResult with error details rather than propagating
  exceptions to callers.

- All lifecycle hook calls are guarded via _fire_on_indexed,
  _fire_on_removed, and _fire_on_error helpers that catch and log hook
  exceptions without disrupting the indexing pipeline.

- max_triples parameter (default 50,000) bounds analyzer output size to
  prevent runaway resource consumption.

- ResourceFileWatcher monitors filesystem paths via watchdog and triggers
  re-indexing callbacks on file changes with configurable debouncing.
  Emits RESOURCE_MODIFIED domain events via EventBus when file changes
  are detected. Debounce timers coalesce rapid edits into a single
  callback invocation. Thread-safe design with daemon threads for clean
  shutdown.

- SearchResult.__post_init__ validates score is in [0.0, 1.0], correctly
  rejecting NaN values.

- Placeholder embedding uses [1.0] instead of [float(len(content))] to
  avoid leaking content size information.

- isinstance check on graph_backend ensures GraphIndexBackend protocol
  compliance at runtime.

- Test doubles extracted to features/mocks/uko_indexer_mocks.py for reuse
  across BDD steps and Robot helpers.

Spec reference: Architecture > ACMS > Real-time Index Synchronization
(specification.md lines ~43205-43300).

ISSUES CLOSED: #578
2026-03-11 00:40:07 +00:00
Brent E. Edwards 3c7915099f fix(tdd): remove tdd_expected_fail tags — bug #554 is fixed
The merge from master brought in the DI container fix for bug #554.
All 16 session-list TDD tests now pass, so the tdd_expected_fail
tags are removed per the TDD listener protocol.
2026-03-11 00:07:07 +00:00
Brent E. Edwards 6bce5479f3 Merge branch 'master' into tdd/session-list-di-error
# Conflicts:
#	features/environment.py
#	noxfile.py
2026-03-10 23:34:36 +00:00
brent.edwards 72c7574e10 Merge pull request 'test(cli): add failing tests for session list DI container error (#554)' (#596) from feature/m3-fix-session-list-error into master
Reviewed-on: cleveragents/cleveragents-core#596
Reviewed-by: Rui Hu <rui.hu@cleverthis.com>
2026-03-10 23:30:07 +00:00
brent.edwards de379d4a33 Merge remote-tracking branch 'origin/master' into feature/m3-fix-session-list-error
# Conflicts:
#	CHANGELOG.md
2026-03-10 23:12:20 +00:00
Brent E. Edwards 73d5552467 fix(actor): handle empty actor list without validation error
ActorRegistry._actor_name() built names via f"{provider}/{model}", which
produced names with multiple slashes when providers included models
containing "/" (e.g. OpenRouter's "anthropic/claude-sonnet-4-20250514").
The resulting name violated the spec pattern ^[a-z0-9_-]+/[a-z0-9_-]+$
and triggered a ValidationError during actor upsert.

Now sanitises both provider and model components by replacing "/" with "-"
and lowercasing, so multi-slash provider models no longer break actor
listing.

Includes 6 Behave BDD regression scenarios (covering zero-provider,
multi-slash, consecutive-slash, leading-slash, and name-validation
cases), Robot Framework integration smoke tests, and ASV benchmarks.

ISSUES CLOSED: #592
2026-03-10 23:11:22 +00:00
brent.edwards 832b8a8b5a Merge pull request 'test(cli): add failing tests for session create DI container error (#570)' (#595) from feature/m3-fix-session-create-error into master
Reviewed-on: cleveragents/cleveragents-core#595
Reviewed-by: Rui Hu <rui.hu@cleverthis.com>
2026-03-10 23:08:20 +00:00
brent.edwards 8d235c97fc Merge branch 'tdd/session-create-di-error' into tdd/actor-list-validation 2026-03-10 22:57:24 +00:00
brent.edwards 142895e34d Merge remote-tracking branch 'origin/master' into feature/m3-fix-session-create-error
# Conflicts:
#	CHANGELOG.md
2026-03-10 22:56:43 +00:00
brent.edwards 2365f9a355 test(actor): add TDD failing tests for actor list empty validation error
Behave BDD scenarios (3) tagged @tdd_bug @tdd_bug_592 @tdd_expected_fail
exercise the real ActorRegistry._actor_name() code path with a provider
whose default model contains '/' separators. The tests assert correct
behaviour (exit 0, single-slash names, valid JSON) and fail while the
bug is present; the @tdd_expected_fail handler inverts results so CI
stays green.

Includes Robot Framework integration smoke tests (3), ASV benchmarks (3),
and a shared FakeProviderInfo/FakeProviderRegistry mock in
features/mocks/fake_provider.py.

ISSUES CLOSED: #634
2026-03-10 22:40:15 +00:00
brent.edwards 4fff7f67c5 fix(test): use scoped_session to prevent GC-induced data loss in r2cov
SQLite in-memory engines use SingletonThreadPool, giving every Session
the same underlying connection.  Repository methods create a new
Session via the factory, flush, then return — letting the Session go
out of scope.  Under high memory pressure (e.g. 32 parallel behave
workers) Python's garbage collector closes these orphaned Sessions,
issuing an implicit ROLLBACK on the shared connection and wiping
flushed-but-uncommitted rows written by other Sessions.

Replace the plain sessionmaker with scoped_session in the r2cov
Background step so that every factory() call returns the same Session
instance.  A single long-lived Session per scenario eliminates the
premature close/rollback window entirely.

Verified: 3 consecutive green runs with --processes 32 (10 099
scenarios, 0 failures each).

Refs: #570
2026-03-10 22:27:37 +00:00
Brent E. Edwards 1e116e3fec Merge branch 'master' into tdd/session-list-di-error 2026-03-10 22:22:25 +00:00
Brent E. Edwards 1be8dd9cb9 Merge branch 'master' into feature/m3-fix-session-list-error 2026-03-10 22:22:01 +00:00
Brent E. Edwards d0689573e0 test(cli): add failing tests for session create DI container error
Add TDD regression tests for bug #570 where `_get_session_service()`
calls `container.db()` but the DI `Container` class has no `db`
provider, raising `AttributeError`.  Same root cause as bug #554.

Includes 4 Behave BDD scenarios tagged `@tdd_bug @tdd_bug_570
@tdd_expected_fail`, Robot Framework integration smoke tests with
`--format plain`, and ASV service-layer benchmarks.  Tests exercise the
real DI path by resetting `_service = None` and using a file-based
SQLite database.

Implements the `@tdd_expected_fail` inversion infrastructure:
- Behave: `after_scenario` hook in `features/environment.py` inverts
  pass/fail for scenarios tagged `@tdd_expected_fail`
- Robot: `robot/tdd_expected_fail_listener.py` listener (API v3)
  performs the same inversion for Robot test cases
- `noxfile.py`: registers the listener via `--listener` in both the
  `integration_tests` and `slow_integration_tests` sessions

Migrates 18 existing TDD scenarios across 5 feature files from the old
`@tdd @bugNNN` convention to the standardised `@tdd_bug @tdd_bug_NNN`
tags per CONTRIBUTING.md § TDD Bug Test Tags.

Refs: #570
2026-03-10 21:39:31 +00:00
Brent E. Edwards 4c5589da4e test(cli): add failing TDD tests for session list DI container error
Add 10 Behave BDD scenarios (@tdd_bug @tdd_bug_554 @tdd_expected_fail)
for the session list DI wiring bug where _get_session_service() calls
container.db() but the Container has no db provider (AttributeError).
Scenarios cover empty list, format validation (JSON/YAML/plain/rich),
init-then-list lifecycle, and post-create list paths.

Implement @tdd_expected_fail infrastructure: Behave after_scenario hook
inverts FAIL→PASS (expected) and PASS→FAIL (unexpected fix), plus Robot
Framework listener (Listener API v3) with identical semantics registered
via --listener in both integration_tests and slow_integration_tests nox
sessions.

Migrate 18 existing TDD scenarios across 5 feature files from legacy
@tdd @bugNNN convention to @tdd_bug @tdd_bug_NNN per CONTRIBUTING.md
§ TDD Bug Test Tags.

Includes Robot Framework integration smoke tests and ASV service-layer
benchmarks.

Refs: #554
2026-03-10 21:24:42 +00:00
brent.edwards 471426f5b6 Merge branch 'master' into tdd/session-create-di-error 2026-03-10 21:08:17 +00:00
freemo c054675167 feat(resource): add database resources
Implement database resource types (postgres, mysql, sqlite, duckdb)
with connection args, auth handling, and transaction-based sandbox
strategy using BEGIN/ROLLBACK/COMMIT wrappers.

Key changes:
- Add DatabaseResourceHandler with 4 database type definitions
- Implement TransactionSandbox for transaction_rollback strategy
- Wire TransactionSandbox into SandboxFactory
- Register database types in bootstrap_builtin_types
- Add connection validation with credential masking
- Add Behave BDD tests, Robot integration tests, ASV benchmarks

ISSUES CLOSED: #342
2026-03-10 19:29:27 +00:00
brent.edwards 9ee4c4aa2d Merge pull request 'fix(test): resolve race condition in M4 validation integration test' (#619) from fix/m4-validation-race-condition into master
Reviewed-on: cleveragents/cleveragents-core#619
Reviewed-by: Rui Hu <rui.hu@cleverthis.com>
2026-03-10 19:13:22 +00:00
brent.edwards b80a9232fa test(session): add TDD failing tests for session create DI error
Implement TDD bug-capture tests for bug #570 where `agents session create`
fails because `_get_session_service()` calls `container.db()` which does
not exist on the DI Container class (AttributeError). Same root cause as
bug #554.

Behave BDD scenarios tagged @tdd_bug @tdd_bug_570 @tdd_expected_fail
exercise the real DI path (no mocks). Includes Robot Framework integration
smoke tests with self-inverting helper and ASV benchmark baseline.

ISSUES CLOSED: #631
2026-03-10 19:05:18 +00:00
brent.edwards 06bbe48a9c test(session): add TDD failing tests for session list DI error
Implement TDD bug-capture tests for bug #554 where `agents session list`
fails because `_get_session_service()` calls `container.db()` which does
not exist on the DI Container class (AttributeError).

Behave BDD scenarios tagged @tdd_bug @tdd_bug_554 @tdd_expected_fail
exercise the real DI path (no mocks) and assert correct behavior. The
@tdd_expected_fail handler in environment.py inverts failed→passed while
the bug is present, keeping CI green.

Also adds:
- @tdd_expected_fail infrastructure in features/environment.py
  (tag validation + status inversion in after_scenario hook)
- behave-parallel exit logic fix to use summary-based failure
  detection (compatible with TDD status inversion)
- Robot Framework integration smoke tests with self-inverting helper
- ASV benchmark baseline for session list command throughput

ISSUES CLOSED: #630
2026-03-10 19:05:12 +00:00
Brent E. Edwards d88dad94f6 fix(test): resolve race condition in M4 validation integration test
Three-pronged fix for intermittent pabot-parallel race condition in
M4 validation integration tests:

1. Composable Setup Database Isolation keyword in common.resource
   gives each suite a unique CLEVERAGENTS_DATABASE_URL so concurrent
   pabot workers never contend on the same SQLite file.

2. Per-suite CLEVERAGENTS_HOME directories prevent shared temp
   directory cleanup from racing between workers.

3. Centralised reset_global_state() in robot/helpers_common.py clears
   Settings singleton, DI container, provider registry, and engine
   cache between chained CLI invocations in helper processes.

Also:
- Setup Test Environment now accepts optional mock_ai and
  auto_apply_migrations arguments (default TRUE) for backward
  compatibility while allowing suites to opt out.
- Added Suite Teardown to cli_plan_context_commands.robot.
- Fixed _COMMANDS typing in two helpers to eliminate type: ignore.
- Updated docs/development/testing.md to reflect helpers_common
  delegation pattern.
- Added timeout=30s to all Run Process calls in
  m4_e2e_verification.robot.

Fixes: #563
2026-03-10 19:04:57 +00:00
freemo 876217d0ca feat(guardrails): implement Per-Session and Per-Org Cost Budgets
Implements Forgejo issue #584: three-tier budget hierarchy
(per-plan -> per-session -> per-org) with tightest limit winning.

Domain models:
- BudgetLevel enum (PLAN, SESSION, ORG)
- BudgetCheckResult (frozen Pydantic model with exceeded_level, warning)
- SessionCostBudget (tracks per-session accumulated cost)
- OrgCostAccumulator (tracks per-org accumulated cost)
- ThreadSafeOrgCostAccumulator (thread-safe wrapper with snapshot)

Application services:
- CostBudgetService: manages budget state, enforces hierarchy,
  emits BUDGET_WARNING (once per session) and BUDGET_EXCEEDED events
- AutonomyGuardrailService: extended with associate_plan_with_session,
  check_budget_hierarchy, record_plan_cost_to_session methods

Configuration:
- Settings: session_max_cost_usd, org_max_cost_usd, budget_warning_threshold

Integration:
- Session model: cost_budget field, as_cli_dict includes budget data
- DI container: CostBudgetService registered as Singleton
- CLI session show: cost budget panel display

Tests:
- 54 Behave scenarios (features/cost_budgets.feature)
- 11 Robot Framework integration tests (robot/cost_budgets.robot)
- ASV benchmarks (benchmarks/bench_budget_check.py)

All nox stages pass: lint, typecheck, unit_tests, coverage_report (98%).

CLOSES #584
2026-03-10 14:18:04 -04:00
freemo 958eb0c060 feat(observability): implement Metrics Collection Framework (14 metric types with Histogram/Counter/Gauge)
Implement the structured metrics collection framework covering 14
operational metric types with proper Histogram, Counter, and Gauge
semantics per the spec (Architecture > Observability > Metrics
Collection, lines ~43805-43825).

Domain layer:
- Add MetricType enum (HISTOGRAM, COUNTER, GAUGE) to metrics.py
- Add MetricDefinition model and METRIC_DEFINITIONS registry mapping
  all 14 OperationalMetricKey values to their metric types
- Extend MetricCollector with typed factory methods (histogram, counter,
  gauge) and 14 convenience methods (plan_duration, plan_cost,
  plan_decision_count, subplan_count, actor_invocation_count,
  actor_latency, tool_invocation_count, tool_error_rate,
  context_build_time, context_token_count, llm_call_count,
  llm_total_tokens, llm_total_cost, llm_avg_latency)
- Extend MetricEntry with optional metric_type field that auto-resolves
  from METRIC_DEFINITIONS via MetricCollector.record()

Infrastructure layer:
- Add MetricsEmitter (infrastructure/observability/metrics_emitter.py)
  with emit(), emit_batch(), from_settings(), and enabled/disabled
  support for structured log emission in local mode
- Add metrics_log_processor (config/metrics_processor.py) for structlog
  integration

Configuration:
- Add metrics_enabled and metrics_export_prometheus settings
- Register MetricsEmitter as DI Singleton in application container

Instrumentation:
- Add best-effort metric emission in PlanExecutor for plan_duration
  (both runtime and stub execute paths) and plan_decision_count
  (strategize path) via _try_emit_metric helper that tolerates invalid
  plan IDs in test fixtures

Testing:
- 34 Behave BDD scenarios (features/observability/metrics_collection.feature)
- 8 Robot Framework integration tests (robot/metrics_collection.robot)
- ASV benchmark suite (benchmarks/bench_metrics_collection.py)

Closes #579
2026-03-10 17:23:05 +00:00
freemo c2db74ba81 Docs: Restyled ADR pages 2026-03-10 12:38:35 -04:00
freemo 01a2a03e2e Docs: Improved the navigation seperating out ToC from top nac bar 2026-03-10 12:38:35 -04:00
freemo a41fc02f11 feat(acms): add strategy coordinator and fusion engine
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
2026-03-10 15:09:03 +00:00
freemo 521a552e56 feat(extensibility): implement Plugin Architecture Framework with module:ClassName resolution
Implement plugin architecture framework enabling custom implementations
of tools, strategies, sandbox strategies, index backends, and pipeline
components through module:ClassName resolution and entry point discovery.

Key changes:
- Add infrastructure/plugins/ package with PluginLoader, PluginManager, types, exceptions
- Implement dynamic import via module:ClassName with security prefix allowlist
- Add entry point discovery via importlib.metadata
- Add Protocol validation for loaded plugin classes
- Add plugin lifecycle management (discover/activate/deactivate)
- Add config-driven registration (custom_module + custom_class + custom_options)
- Register PluginManager in DI container
- Add comprehensive Behave BDD tests, Robot integration tests, ASV benchmarks

ISSUES CLOSED: #585
2026-03-10 14:51:39 +00:00
CoreRasurae cf67ba0a86 feat(devcontainer): add lazy activation and lifecycle management
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
2026-03-10 12:17:51 +00:00
hamza.khyari 1b4e021659 Merge pull request 'feat(resource): add resource type inheritance and polymorphic tool matching' (#618) from feature/m6-resource-type-inheritance into master
Reviewed-on: cleveragents/cleveragents-core#618
Reviewed-by: Brent Edwards <brent.edwards@cleverthis.com>
2026-03-10 04:16:36 +00:00
hamza.khyari 45c15bcc1a fix(migration): chain m6_004 after m7_001_repo_indexing_tables to resolve multiple heads
m6_004_resource_type_inherits and m7_001_repo_indexing_tables both had
down_revision='m6_003_async_jobs_table', creating two Alembic heads.
Chain m6_004 after m7_001 so the migration graph is linear.
2026-03-10 04:10:58 +00:00
hamza.khyari 135481f9a6 fix(resource): address PR #618 review findings (round 1)
- P2-1: Add field_validator('inherits') on ResourceTypeSpec
- P2-2: Remove 'properties' from _COLLECTION_FIELDS (scalar override)
- P2-3: Add behave scenarios for exception rollback paths
- P2-4: Add ordering comment to BUILTIN_TYPES
- P2-5: Define RegistryHost Protocol, remove type:ignore on mixins
- P2-6: Add if_not_exists=True on migration index creation
- P3-1: Use deque.popleft() in get_ancestors for O(1) BFS
- P3-2: Filter private attrs in _to_dict vars() fallback
- P3-3: Replace _handler_cache import with clear_handler_cache()
- P3-4: Add migration downgrade test for m6_004
- P3-5: Extract ResourceDagMixin to _resource_registry_dag.py

All files remain under 500-line CONTRIBUTING limit.
Lint, typecheck, and 85 behave scenarios pass.
2026-03-10 04:06:02 +00:00
hamza.khyari ab4da7804d test(resource): add diff-coverage BDD scenarios for inheritance service and resolver
Add 21 scenarios covering uncovered paths in:
- resource_registry_service.py: register_type inherits validation,
  remove_type guards, resolve_chain, is_subtype_of (76% -> 95%)
- resolver.py: import error, instantiation, protocol check,
  polymorphic chain walk (77% -> 98%)
- _resource_registry_ops.py: exact filter, child type mismatch,
  tree type_filter (95% -> 98%)
- inheritance.py: _merge_dict, resolve_fields gap (96% -> 99%)

Overall project coverage holds at 97%.
2026-03-10 03:39:32 +00:00
hamza.khyari bebe91e0a7 fix(resource): add defensive copies for capabilities/auto_discovery/equivalence in as_cli_dict
Complete F24 fix: capabilities, auto_discovery, and equivalence dicts
were returned as direct references. Now wrapped with dict() to
prevent callers from mutating internal state.
2026-03-10 03:39:32 +00:00
hamza.khyari ce1536c4c4 refactor(resource): split resource_registry_service into 3 modules (<500 LOC each)
Extract data helpers (_resource_registry_data.py, 389 lines) and
operation mixins (_resource_registry_ops.py, 497 lines) from the
1247-line resource_registry_service.py, reducing it to 467 lines.

All three modules stay under the 500-line CONTRIBUTING limit.
Backward-compat aliases (_spec_to_db, _db_to_spec) are re-exported
from the main module so existing test imports continue to work.

Addresses review finding F8 for PR #618.
2026-03-10 03:39:32 +00:00
hamza.khyari 23d8a53f6a fix(resource): address review findings for resource type inheritance
Fix 25 of 27 review findings from PR #618 code review:

P1 (Must Fix):
- F3: Fix silent data corruption in _merge_collection for properties
  dict fields (was falling through to string list merge)
- F1: Split 1023-line step file into 3 files + helper module (all <500)
- F4: Add SELECT FOR UPDATE lock on parent type in register_type to
  prevent TOCTOU race in concurrent registrations
- F6: Fix docs claiming exceptions inherit from CleverAgentsError
  (they inherit from ValueError)
- F7: Fix docs incorrectly describing validate_chain return type

P2 (Should Fix):
- F9: Replace dict[str, Any] with TypeRegistryMap type alias
- F10: Replace import logging with structlog in inheritance.py
- F11: Add __all__ to inheritance.py
- F13: Fix _load_type_registry to derive built_in from namespace column
- F14: Add warning log for unregistered types in resolve_inheritance_chain
- F15: Return defensive copies from resolve_fields
- F16: Add chain validation to bootstrap_builtin_types
- F17: Narrow except Exception to specific types in step files
- F18: Add side-effect verification scenarios after error cases
- F19: Always include inherits key in JSON output for consistent schema
- F20: Log actual exception instead of hardcoded string in CLI

P3 (Nit):
- F21: Reject whitespace-only inherits values in validate_chain
- F23: Wrap chain errors in HandlerResolutionError in resolver
- F24: Return defensive copies from as_cli_dict
- F25: Replace tautological assertion with ResourceHandler isinstance
- F26: Add whitespace inherits test scenario
- F27: Fix find_subtypes docstring to note it excludes ancestor_name

Deferred:
- F2: type: ignore in step files — pyright only checks src/, matches
  existing project pattern (91 occurrences in resource_dag_steps.py)
- F5: CLI integration tests require full DI container setup
- F8: resource_registry_service.py size is pre-existing (971 on master)
- F12: Coverage boost file changes are test adaptations, not scope creep
- F22: FK constraint intentionally omitted per docs (SQLite compat)
2026-03-10 03:39:32 +00:00
hamza.khyari bb8175aa11 feat(resource): add resource type inheritance and polymorphic tool matching
Implement ADR-042 single-inheritance for resource types with polymorphic
tool and handler resolution.

Core changes:
- Add `inherits` field to ResourceTypeConfigSchema, ResourceTypeSpec, and
  ResourceTypeModel with chain depth validation (max 5), circular
  inheritance detection, and built-in-from-custom guard
- New inheritance.py module (390 lines): resolve_inheritance_chain(),
  validate_chain(), is_subtype_of(), resolve_fields(), find_subtypes()
- Wire inheritance into ResourceRegistryService: chain validation on
  register_type(), resolve_type_inheritance_chain(), is_subtype_of()
- Add find_tools_for_resource() to ToolRegistry with polymorphic matching
  that walks the inheritance chain
- Add resolve_handler_polymorphic() to handler resolver
- Alembic migration m6_004_resource_type_inherits adds inherits column
  and index to resource_types table

CLI changes:
- `agents resource type list` shows Inherits column
- `agents resource type show` displays inheritance chain

Tests:
- 30 BDD scenarios in resource_type_inheritance.feature (all pass)
- 18 Robot Framework test cases
- 14 ASV benchmark timing methods across 4 suites

Docs:
- docs/reference/resource_type_inheritance.md (full reference)
- Updated docs/schema/resource_type.schema.yaml
- CHANGELOG entry for #513

ISSUES CLOSED: #513
2026-03-10 03:39:32 +00:00
hamza.khyari fcdf80f342 Merge pull request 'feat(context): add repo indexing service' (#610) from feature/m4-context-indexing into master
Reviewed-on: cleveragents/cleveragents-core#610
Reviewed-by: Brent Edwards <brent.edwards@cleverthis.com>
2026-03-10 00:02:19 +00:00