Commit Graph

730 Commits

Author SHA1 Message Date
brent.edwards bc6a41deb6 tdd(cli): prevent actor list from triggering database updates (#1151)
CI / build (push) Successful in 25s
CI / helm (push) Successful in 29s
CI / lint (push) Successful in 3m20s
CI / quality (push) Successful in 3m45s
CI / typecheck (push) Successful in 4m7s
CI / benchmark-regression (push) Has been skipped
CI / security (push) Successful in 4m8s
CI / integration_tests (push) Successful in 9m17s
CI / unit_tests (push) Successful in 9m34s
CI / docker (push) Successful in 1m31s
CI / e2e_tests (push) Successful in 13m53s
CI / coverage (push) Successful in 11m30s
CI / status-check (push) Successful in 1s
CI / benchmark-publish (push) Successful in 26m47s
## Summary

- Fix bug #797: `agents actor list` no longer triggers database writes (`upsert_actor`, `set_default_actor`) by removing `ensure_built_in_actors()` from `ActorRegistry.list()` and `ActorRegistry.list_actors()`
- Include TDD regression tests from #841 with `@tdd_expected_fail` removed per Bug Fix Workflow
- Update three existing test suites that relied on the old behavior to call `ensure_built_in_actors()` explicitly

## Root Cause

`ActorRegistry.list_actors()` and `ActorRegistry.list()` both unconditionally called `self.ensure_built_in_actors()` before delegating to the actor service. `ensure_built_in_actors()` iterates all configured providers and calls `_actor_service.upsert_actor()` for each — a database WRITE operation. It may also call `_actor_service.set_default_actor()` if no default exists — another WRITE. This means every read-only `agents actor list` command triggered database writes and could prompt for pending migrations on fresh checkouts.

## Changes

### Bug Fix
- **`src/cleveragents/actor/registry.py`** — Removed `self.ensure_built_in_actors()` from `list()` and `list_actors()`. Both methods now delegate directly to the service layer without triggering writes. All write-heavy methods (`add`, `upsert_actor`, `get`, `get_actor`, `remove`, `remove_actor`, `set_default_actor`, `get_default_actor`) still call `ensure_built_in_actors()`.

### TDD Tests (from #841, `@tdd_expected_fail` removed)
- **`features/tdd_actor_list_no_db_update.feature`** — 2 Behave scenarios verifying `upsert_actor` and `set_default_actor` are not called during `actor list`
- **`features/steps/tdd_actor_list_no_db_update_steps.py`** — Step definitions
- **`robot/tdd_actor_list_no_db_update.robot`** — 2 Robot Framework integration tests
- **`robot/helper_tdd_actor_list_no_db_update.py`** — Robot helper script

### Test Adjustments
Three existing test suites relied on the old (buggy) behavior where `list_actors()` called `ensure_built_in_actors()`:
1. **`features/consolidated_actor.feature`** — Scenario updated to explicitly call `ensure_built_in_actors()` before `list_actors()`
2. **`features/steps/tdd_actor_list_validation_steps.py`** + **`robot/helper_tdd_actor_list_validation.py`** (bug #592) — Updated to call `ensure_built_in_actors()` explicitly before CLI invocation
3. **`features/steps/actor_list_empty_steps.py`** (bug #592) — Updated with explicit `ensure_built_in_actors()` call and capturing upsert pattern

## Quality Gates

| Gate | Result |
|------|--------|
| `nox -e lint` |  Pass |
| `nox -e typecheck` |  Pass (0 errors) |
| `nox -e unit_tests` |  Pass (468 features, 12367 scenarios, 0 failures) |
| `nox -e integration_tests` | ⚠️ 6 pre-existing failures (timeouts/OOM) |
| `nox -e coverage_report` |  98% (>= 97% threshold) |

The 6 integration test failures are pre-existing infrastructure issues (SIGTERM/SIGKILL timeouts) unrelated to this change: Container Resolve Crash (3), M3 E2E Verification (2), Resource CLI (1).

Closes #797

Reviewed-on: #1151
Reviewed-by: Jeffrey Phillips Freeman <jeffrey.freeman@cleverthis.com>
Co-authored-by: Brent E. Edwards <brent.edwards@cleverthis.com>
Co-committed-by: Brent E. Edwards <brent.edwards@cleverthis.com>
2026-03-28 05:27:14 +00:00
brent.edwards b59100cc6c test: add TDD bug-capture test for #1141 — session create persistence (#1144)
CI / build (push) Successful in 16s
CI / helm (push) Successful in 28s
CI / lint (push) Successful in 3m20s
CI / quality (push) Successful in 3m53s
CI / security (push) Successful in 4m9s
CI / typecheck (push) Successful in 4m15s
CI / benchmark-regression (push) Has been skipped
CI / integration_tests (push) Successful in 6m57s
CI / unit_tests (push) Successful in 7m3s
CI / docker (push) Successful in 1m30s
CI / e2e_tests (push) Successful in 11m37s
CI / coverage (push) Successful in 11m27s
CI / status-check (push) Successful in 1s
CI / benchmark-publish (push) Successful in 27m7s
## Summary

Adds TDD bug-capture coverage for bug #1141 (`session create` -> `session list` lifecycle) on metadata branch `tdd/m3-session-create-persist`.

### What changed

- Added Behave bug-capture feature: `features/tdd_session_create_persist.feature`
  - Required tags: `@tdd_bug @tdd_bug_1141 @tdd_expected_fail`
  - Scenario path: `init --force --yes` -> `session list --format json` -> `session create` -> `session list --format json`
- Added Behave step definitions: `features/steps/tdd_session_create_persist_steps.py`
  - Uses root CLI app (`cleveragents.cli.main:app`) for realistic command routing
  - Asserts expected list totals; underlying assertion intentionally fails while bug is present
- Added Robot E2E bug-capture test: `robot/e2e/e2e_session_create_persist.robot`
  - Required tags: `E2E`, `tdd_expected_fail`, `tdd_bug`, `tdd_bug_1141`
  - Includes explicit in-file note to remove `tdd_expected_fail` when #1141 is fixed
- Updated changelog (`CHANGELOG.md`, Unreleased)

### Notes

- The issue subtask referenced `robot/e2e/e2e_session_lifecycle.robot`, which is not present on current `master`; equivalent E2E coverage is implemented in `robot/e2e/e2e_session_create_persist.robot`.
- The branch was force-updated to remove stale merge-based history and keep an atomic, rebase-clean commit for this issue.

## Quality gates

| Gate | Result |
|---|---|
| `nox -s lint` |  pass |
| `nox -s typecheck` |  pass |
| `nox -s unit_tests -- features/tdd_session_create_persist.feature` |  pass (TDD inversion active; underlying assert fails) |
| `nox -s integration_tests -- robot/e2e/e2e_session_create_persist.robot` |  pass |
| `nox -s e2e_tests` |  pass |
| `nox -s coverage_report` |  pass (97.66173849218832%) |
| `nox` (full default suite) |  pass |

## Related issue

Closes #1142

Reviewed-on: #1144
Reviewed-by: Jeffrey Phillips Freeman <jeffrey.freeman@cleverthis.com>
Co-authored-by: Brent Edwards <brent.edwards@cleverthis.com>
Co-committed-by: Brent Edwards <brent.edwards@cleverthis.com>
2026-03-28 04:34:47 +00:00
brent.edwards 26632f79e9 test: add TDD bug-capture test for #1079 — project context set missing flag (#1130)
CI / build (push) Successful in 18s
CI / helm (push) Successful in 21s
CI / lint (push) Successful in 3m17s
CI / quality (push) Successful in 3m41s
CI / typecheck (push) Successful in 4m3s
CI / security (push) Successful in 4m4s
CI / benchmark-regression (push) Has been skipped
CI / integration_tests (push) Successful in 7m7s
CI / unit_tests (push) Successful in 7m15s
CI / docker (push) Successful in 1m31s
CI / e2e_tests (push) Successful in 12m39s
CI / coverage (push) Successful in 11m32s
CI / status-check (push) Successful in 1s
CI / benchmark-publish (push) Successful in 29m36s
## Summary

This PR adds TDD bug-capture tests for bug #1079 (`project context set` missing `--execution-env-priority` flag). Per the Bug Fix Workflow in CONTRIBUTING.md, the first step in fixing any bug is to write a test that proves the bug exists.

### What was done

- **Behave unit tests** (6 scenarios in `features/project_context_set_exec_env_priority.feature`):
  - `project context set --execution-env-priority override` with `--execution-environment` should succeed and persist
  - `project context set --execution-env-priority fallback` with `--execution-environment` should succeed and persist
  - `--execution-env-priority` without `--execution-environment` should be rejected
  - Default to `fallback` when only `--execution-environment` is specified
  - Invalid `--execution-env-priority` value should be rejected
  - `project context show` should reflect persisted `execution_env_priority` in JSON output

- **Robot integration tests** (3 test cases in `robot/project_context_set_exec_env_priority.robot`):
  - Override acceptance with persistence verification
  - Fallback acceptance with persistence verification
  - Full round-trip persistence check

All tests are tagged `@tdd_bug @tdd_bug_1079 @tdd_expected_fail`. The underlying assertions fail (confirming the bug exists — `--execution-env-priority` is "No such option"), and the `@tdd_expected_fail` tag inverts the result so CI passes.

### Bug confirmed

The `context_set()` function in `cleveragents.cli.commands.project_context` does not accept `execution_env_priority` as a parameter. The specification (§Execution Environment Routing, precedence table) requires this flag at precedence level 2 for project-level execution environment priority control.

### Quality gates

| Gate | Result |
|------|--------|
| `nox -s lint` | PASS |
| `nox -s typecheck` | PASS (0 errors) |
| `nox -s unit_tests` | PASS (12236 scenarios, 0 failed) |
| `nox -s integration_tests` | My 3 tests pass (13 pre-existing failures) |
| `nox -s coverage_report` | PASS (98%, threshold 97%) |

Closes #1100

Reviewed-on: #1130
Reviewed-by: Jeffrey Phillips Freeman <jeffrey.freeman@cleverthis.com>
Co-authored-by: Brent E. Edwards <brent.edwards@cleverthis.com>
Co-committed-by: Brent E. Edwards <brent.edwards@cleverthis.com>
2026-03-28 02:14:55 +00:00
brent.edwards b46a0e6102 feat(plan): implement real revert-mode re-execution from decision point (#1153)
CI / status-check (push) Blocked by required conditions
CI / build (push) Successful in 18s
CI / helm (push) Successful in 31s
CI / lint (push) Successful in 3m29s
CI / typecheck (push) Successful in 3m56s
CI / benchmark-regression (push) Has been skipped
CI / quality (push) Successful in 3m41s
CI / unit_tests (push) Successful in 4m11s
CI / integration_tests (push) Failing after 4m12s
CI / security (push) Successful in 4m38s
CI / docker (push) Successful in 1m32s
CI / coverage (push) Successful in 11m33s
CI / e2e_tests (push) Failing after 23m17s
CI / benchmark-publish (push) Failing after 38m50s
## Summary

Implements the full revert-mode re-execution pipeline from the specification (§ Correction Flow, Revert Mode), enabling `agents plan correct --mode=revert` to truly re-execute from the targeted decision point rather than only logically marking decisions as superseded.

### Changes

- **Resource rollback**: `CorrectionService.execute_revert` now delegates to `CheckpointService.rollback_to_checkpoint` when a decision-aligned checkpoint exists, performing real `git reset --hard` in the sandbox. Gracefully degrades when checkpointing is unavailable.
- **Reasoning rollback**: Extracts `actor_state_ref` from the target decision's `ContextSnapshot` for downstream LangGraph actor restoration.
- **Guidance injection**: Generates a `user_intervention` decision ID for callers to record correction guidance in the decision tree.
- **Phase transition**: Signals that the plan should re-enter Strategize via `phase_transition_target="strategize"` on the result.
- **Model extension**: Added `checkpoint_restored`, `actor_state_ref`, `user_intervention_decision_id`, and `phase_transition_target` fields to `CorrectionResult` with backward-compatible defaults.
- **Dispatch update**: `execute_correction` now accepts and forwards a `decisions` parameter.

### Design Approach

Uses a signal-based architecture: rather than having `CorrectionService` directly manipulate plan state or LangGraph actors, the enhanced `execute_revert` returns signal fields on `CorrectionResult` that downstream consumers use for the full pipeline. This preserves separation of concerns.

### Tests

- **Behave**: 16 new BDD scenarios in `features/revert_re_execution.feature`
- **Robot**: 7 integration tests in `robot/revert_re_execution.robot`
- **Coverage**: 98% (above 97% threshold)

### Quality Gates

| Gate | Status |
|------|--------|
| `nox -s lint` | Pass |
| `nox -s typecheck` | Pass (0 errors) |
| `nox -s unit_tests` | Pass (12376 scenarios, 0 failed) |
| `nox -s integration_tests` | Pass (1631 passed, 3 pre-existing failures #647) |
| `nox -s e2e_tests` | Pass (37 passed) |
| `nox -s coverage_report` | Pass (98%) |

Closes #844

Reviewed-on: #1153
Co-authored-by: Brent E. Edwards <brent.edwards@cleverthis.com>
Co-committed-by: Brent E. Edwards <brent.edwards@cleverthis.com>
2026-03-28 00:57:51 +00:00
brent.edwards efacfd61c3 test: add TDD bug-capture test for #1023 — implicit init requirement (#1113)
CI / build (push) Successful in 17s
CI / helm (push) Successful in 21s
CI / lint (push) Successful in 3m19s
CI / quality (push) Successful in 3m44s
CI / typecheck (push) Successful in 3m56s
CI / benchmark-regression (push) Has been skipped
CI / integration_tests (push) Failing after 3m56s
CI / security (push) Successful in 4m7s
CI / unit_tests (push) Successful in 6m59s
CI / docker (push) Successful in 1m32s
CI / e2e_tests (push) Successful in 12m56s
CI / coverage (push) Successful in 11m39s
CI / status-check (push) Failing after 1s
CI / benchmark-publish (push) Has been cancelled
## Summary

Adds TDD bug-capture tests proving that CLI commands (`resource add`, `project create`) fail in a fresh environment without explicit `agents init`, even when `CLEVERAGENTS_AUTO_APPLY_MIGRATIONS=true` is set.

Bug #1023 reports that `CLEVERAGENTS_AUTO_APPLY_MIGRATIONS=true` triggers schema migrations on an existing database but does NOT create the database file or its parent directory structure, causing `sqlite3.OperationalError: unable to open database file`.

## Changes

### Behave Tests
- `features/tdd_e2e_implicit_init.feature` — Two scenarios tagged `@tdd_expected_fail @tdd_bug @tdd_bug_1023`:
  - `resource add` in a fresh environment without prior init
  - `project create` in a fresh environment without prior init
  - Both scenarios include output content assertions
- `features/steps/tdd_e2e_implicit_init_steps.py` — Step definitions using Typer's CliRunner with real CLI invocation in a pristine temp directory.
  - Env isolation: saves/removes `CLEVERAGENTS_AUTO_APPLY_MIGRATIONS`, `CLEVERAGENTS_DATABASE_URL`, `CLEVERAGENTS_TEST_DATABASE_URL`, `CLEVERAGENTS_HOME`, `BEHAVE_TESTING`, `CLEVERAGENTS_TEMPLATE_DB`, `CLEVERAGENTS_TESTING_USE_MOCK_AI`
  - CliRunner invoked without `catch_exceptions=False` to ensure proper `@tdd_expected_fail` inversion

### Robot Tests
- `robot/tdd_e2e_implicit_init.robot` — Two test cases tagged `tdd_bug tdd_bug_1023 tdd_expected_fail` (listener inverts results while bug is unfixed).
- `robot/helper_tdd_e2e_implicit_init.py` — Helper script exercising CLI in a fresh environment.
  - Env isolation includes `ROBOT_TESTING`, `CLEVERAGENTS_TEMPLATE_DB`, `CLEVERAGENTS_TESTING_USE_MOCK_AI`
  - Env restoration in `finally` block ensures cleanup even on exceptions
  - CliRunner invoked without `catch_exceptions=False` for correct inversion

### Changelog
- Updated `CHANGELOG.md` with entry for this TDD test addition.

## Quality Gates

| Gate | Result |
|------|--------|
| `nox -s lint` | PASS |
| `nox -s typecheck` | PASS (0 errors) |
| `nox -s unit_tests` | PASS (462 features, 12232 scenarios, 0 failed) |
| `nox -s integration_tests` | PASS (pre-existing failures only; our suite correct) |
| `nox -s e2e_tests` | N/A (TDD test only, no E2E suite changes) |
| `nox -s coverage_report` | PASS (98% coverage, threshold 97%) |

Closes #1033

Reviewed-on: #1113
Reviewed-by: Jeffrey Phillips Freeman <jeffrey.freeman@cleverthis.com>
Co-authored-by: Brent Edwards <brent.edwards@cleverthis.com>
Co-committed-by: Brent Edwards <brent.edwards@cleverthis.com>
2026-03-28 00:30:26 +00:00
brent.edwards b51df2ee0f feat(server): add Kubernetes Helm chart for server deployment (#1085)
CI / docker (push) Blocked by required conditions
CI / status-check (push) Blocked by required conditions
CI / build (push) Successful in 20s
CI / helm (push) Successful in 23s
CI / lint (push) Successful in 3m19s
CI / typecheck (push) Successful in 3m57s
CI / benchmark-regression (push) Has been skipped
CI / security (push) Successful in 4m5s
CI / integration_tests (push) Successful in 7m25s
CI / unit_tests (push) Failing after 13m18s
CI / quality (push) Failing after 13m19s
CI / e2e_tests (push) Failing after 18m16s
CI / coverage (push) Failing after 19m20s
CI / benchmark-publish (push) Failing after 28m16s
## Summary

This PR adds Kubernetes Helm deployment support for the CleverAgents server.

Closes #928

### What this PR includes

- Helm chart under `k8s/` with Deployment, Service, optional Ingress, ConfigMap,
  ServiceAccount, Secrets, NOTES, and optional Redis subchart configuration.
- Multi-stage `Dockerfile.server` for server runtime deployment.
- Deployment-focused docs in `k8s/README.md`.
- Behave + Robot + benchmark coverage for chart/deployment wiring.

### Review fixes applied (cycle 11 — hurui200320 review #2687)

**Critical fix:**

1. **CI SHA256 checksum verification fixed** — All 3 Helm install blocks (`unit_tests`, `integration_tests`, `helm` jobs) now save the tarball using its original filename (`helm-v3.16.4-linux-amd64.tar.gz`) instead of `helm.tgz`, so the `.sha256sum` file can correctly locate and verify it. This was causing all 3 CI Helm jobs to fail with "No such file or directory".

**Major fixes (test coverage gaps):**

2. **405 Allow header now tested** — The existing "POST to known path returns method not allowed" scenario now asserts that the `Allow: GET` header is present. Added a second 405 scenario testing `POST /live` for broader `_KNOWN_PATHS` coverage (review item #11).
3. **Security-hardening headers now tested** — New scenario "HTTP responses include security-hardening headers" verifies `content-length`, `x-content-type-options: nosniff`, and `cache-control: no-store` headers are present on HTTP responses.
4. **Lifespan warning logging now tested** — New scenario "Unrecognised lifespan message type logs warning and continues" queues `lifespan.startup` → `lifespan.bogus` → `lifespan.shutdown` and verifies: (a) the app completes the lifespan cycle cleanly, (b) a warning is logged mentioning the unrecognised type.

### Review fixes applied (cycle 10)

**Critical/Major fixes (from hurui200320's prior REQUEST_CHANGES):**

1. **Rebased branch onto master** — Removed merge commit per CONTRIBUTING.md rebase-only policy. Clean linear history restored.
2. **Fixed commit message body** — Replaced literal `\n` sequences with actual newlines. `ISSUES CLOSED: #928` footer is now on its own line after a blank separator.
3. **Moved uvicorn import to module top level** — `from uvicorn import run as uvicorn_run` is now at the top of `src/cleveragents/cli/commands/server.py` per Import Guidelines. Updated test mock target from `uvicorn.run` to `cleveragents.cli.commands.server.uvicorn_run`.
4. **Added SHA256 checksum verification** — All three Helm CLI install blocks in `.forgejo/workflows/ci.yml` now download and verify `helm.sha256sum` before extracting the binary.

**Minor fixes:**

5. **Added `Dockerfile.server` build to CI** — New "Build Docker image (Server)" step in the `docker` job validates the server Dockerfile.
6. **ASGI 405 Method Not Allowed** — Known paths (`/`, `/live`, `/ready`, `/health`) now return 405 with `Allow: GET` header for non-GET methods, per RFC 9110 §15.5.6. Added `_KNOWN_PATHS` frozenset.
7. **WebSocket close protocol fix** — App now calls `await receive()` to consume the `websocket.connect` event before closing. Changed close code from 1000 (Normal Closure) to 1008 (Policy Violation).
8. **Lifespan handler logging** — Unrecognised lifespan message types are now logged as warnings instead of silently consumed.
9. **Security-hardening headers** — `_send_response` now includes `content-length`, `x-content-type-options: nosniff`, and `cache-control: no-store` on all HTTP responses.
10. **`.dockerignore` credential patterns** — Added `*.pem`, `*.key`, `*.p12`, `*.pfx`, `credentials*.json`.
11. **`--log-level` validation** — Constrained to `click.Choice(["critical", "error", "warning", "info", "debug", "trace"])` for clean CLI validation errors.
12. **Reverted unrelated semgrep pre-commit change** — `pass_filenames` and `entry` restored to original values per atomic commit hygiene.
13. **Removed unused `ReceiveCallable` type alias** and `Callable`/`Awaitable` imports from `asgi_app_steps.py`.
14. **Fixed redundant `shutil.which("helm")` check** — `_skip_if_helm_missing` now returns `bool` to eliminate the duplicate check in `_render_chart`.
15. **Improved test deque error handling** — Lifespan test receive mock now raises descriptive `AssertionError` instead of opaque `IndexError`.
16. **Scope type dispatch** — Changed `if/if/if` to `if/elif/elif` for mutually exclusive ASGI scope types.
17. **Dockerfile.server base image** — Standardised to `python:3.13-slim` (floating minor) consistent with CLI Dockerfile.
18. **Dockerfile layer caching** — Split `uv pip install build` and `python -m build` into separate `RUN` instructions.
19. **Removed extraneous double blank line** in Dockerfile.server.

### Deferred items (acknowledged, not in scope)

- PodDisruptionBudget, HorizontalPodAutoscaler, NetworkPolicy — Follow-up for production hardening.
- `appVersion: "1.0.0"` placeholder — Needs tracking issue for release versioning alignment.
- Readiness probe with downstream dependency checks — Documented limitation.
- Cross-system test for probe paths matching ASGI routes — Test enhancement.
- Improved benchmarks (helm template timing vs PyYAML parsing) — Benchmark quality improvement.
- CI DRY violation (Helm install 3×) — Code quality improvement, consider composite action.
- File length limits exceeded (`k8s_helm_chart_steps.py` 551 lines, `helper_k8s_helm_chart.py` 678 lines) — Non-blocking, can be split in follow-up.
- `runAsGroup: 1000` in pod security context — Defense-in-depth improvement.
- HEAD method support on known paths — RFC compliance, does not affect K8s probes.
- `click.Choice` log-level validation via CLI runner test — Test gap.

### Scope note: status-check CI gate

The `status-check` job now includes `integration_tests`, `e2e_tests`, and `helm` in its `needs` list. The `helm` job is new in this PR. The `integration_tests` and `e2e_tests` additions fix previously-missing gate checks — included here since this PR modifies both of those jobs to install Helm.

### Quality gates

- `nox -e lint` 
- `nox -e typecheck` 
- `nox -e unit_tests`  (12,321 scenarios passed, 4 skipped)
- `nox -e integration_tests` — 3 pre-existing failures in unrelated areas (plan correction, resource types)
- `nox -e e2e_tests` — pre-existing failures (LLM API keys not available in local env)
- `nox -e coverage_report`  (**97.7%**)

Reviewed-on: #1085
Reviewed-by: Jeffrey Phillips Freeman <jeffrey.freeman@cleverthis.com>
Co-authored-by: Brent E. Edwards <brent.edwards@cleverthis.com>
Co-committed-by: Brent E. Edwards <brent.edwards@cleverthis.com>
2026-03-27 23:53:22 +00:00
brent.edwards 8b8942817c feat(wf03): add plan prompt test coverage and confidence-threshold pausing verification
CI / benchmark-publish (pull_request) Has been skipped
CI / build (pull_request) Successful in 44s
CI / docker (pull_request) Successful in 1m12s
CI / status-check (pull_request) Successful in 9s
CI / lint (pull_request) Successful in 3m17s
CI / typecheck (pull_request) Successful in 3m54s
CI / quality (pull_request) Successful in 4m6s
CI / security (pull_request) Successful in 4m29s
CI / unit_tests (pull_request) Successful in 6m58s
CI / integration_tests (pull_request) Successful in 7m30s
CI / e2e_tests (pull_request) Successful in 11m39s
CI / coverage (pull_request) Successful in 11m52s
CI / build (push) Successful in 17s
CI / lint (push) Successful in 3m18s
CI / quality (push) Successful in 3m51s
CI / typecheck (push) Successful in 3m55s
CI / benchmark-regression (push) Has been skipped
CI / security (push) Successful in 4m2s
CI / integration_tests (push) Successful in 8m57s
CI / unit_tests (push) Successful in 9m9s
CI / docker (push) Successful in 1m7s
CI / e2e_tests (push) Successful in 11m24s
CI / coverage (push) Successful in 11m41s
CI / status-check (push) Successful in 1s
CI / benchmark-publish (push) Successful in 27m28s
CI / benchmark-regression (pull_request) Successful in 59m17s
2026-03-27 13:35:17 -07:00
hamza.khyari 0569aaa51c test(integration): workflow example 4 — multi-project dependency update (supervised profile)
CI / benchmark-publish (pull_request) Has been skipped
CI / build (pull_request) Successful in 17s
CI / lint (pull_request) Successful in 3m18s
CI / typecheck (pull_request) Successful in 3m55s
CI / quality (pull_request) Successful in 4m2s
CI / security (pull_request) Successful in 4m16s
CI / integration_tests (pull_request) Successful in 9m11s
CI / unit_tests (pull_request) Successful in 9m30s
CI / docker (pull_request) Successful in 1m23s
CI / e2e_tests (pull_request) Successful in 13m30s
CI / coverage (pull_request) Successful in 11m29s
CI / status-check (pull_request) Successful in 1s
CI / benchmark-regression (pull_request) Successful in 53m38s
Robot Framework integration test suite for Specification Workflow Example 4:
Multi-Project Dependency Update.  Exercises the supervised automation profile
with 4 projects (common-lib + 3 microservices), child plan spawning,
dependency-ordered execution, and coordinated apply.

- 8 test cases covering: project registration, action creation, plan use
  with supervised profile, strategize with DEPENDENCY_ORDERED config,
  child plan spawning (4 children), dependency-ordered execution
  (common-lib first), coordinated apply, and full end-to-end lifecycle
- Multi-project scope initialization, changeset recording, and
  cross-project validation via MultiProjectService
- Shared validation (local/pytest-mypy) registered and attached to all
  4 projects per spec §Workflow Example 4
- Uses mocked LLM providers (CLEVERAGENTS_TESTING_USE_MOCK_AI=true)
- All Run Process calls have timeout=60s on_timeout=kill
  (120s for full lifecycle)
- _NoClose wrapper calls rollback() to match established _SafeSession
  pattern; child IDs generated via ULID() instead of hardcoded

ISSUES CLOSED: #768
2026-03-27 14:50:11 +00:00
hamza.khyari 7bb77aee5c feat(resource): implement ResourceHandler sandbox and checkpoint methods
CI / build (pull_request) Successful in 14s
CI / lint (pull_request) Successful in 4m3s
CI / quality (pull_request) Successful in 4m1s
CI / typecheck (pull_request) Successful in 4m30s
CI / security (pull_request) Successful in 5m12s
CI / unit_tests (pull_request) Successful in 8m45s
CI / integration_tests (pull_request) Successful in 8m43s
CI / docker (pull_request) Successful in 1m13s
CI / e2e_tests (pull_request) Successful in 13m7s
CI / coverage (pull_request) Successful in 12m43s
CI / status-check (pull_request) Successful in 1s
CI / benchmark-publish (pull_request) Has been skipped
CI / benchmark-regression (pull_request) Successful in 1h9m12s
Extend the ResourceHandler protocol with four sandbox/lifecycle methods:
create_sandbox (idempotent), create_checkpoint, rollback_to, project_access.

Fixes from self-review:
- Instance-level checkpoint dict instead of ClassVar (no shared state)
- Git rollback uses 'git reset --hard' + 'git clean -fd' (not just checkout)
- FsDirectory rollback skips .git to preserve git metadata
- project_access separates ImportError (local mode) from ValueError (reject)
- Added discard_checkpoints() cleanup method
- Git rollback test verifies file content restored

ISSUES CLOSED: #836
2026-03-27 10:50:15 +00:00
hurui200320 1878998b7a refactor(testing): rename tdd_bug/tdd_bug_N tags to tdd_issue/tdd_issue_N
CI / benchmark-publish (pull_request) Has been skipped
CI / build (pull_request) Successful in 25s
CI / lint (pull_request) Successful in 3m19s
CI / typecheck (pull_request) Successful in 3m56s
CI / security (pull_request) Successful in 4m6s
CI / quality (pull_request) Successful in 4m10s
CI / integration_tests (pull_request) Successful in 7m20s
CI / unit_tests (pull_request) Successful in 7m44s
CI / docker (pull_request) Successful in 1m8s
CI / e2e_tests (pull_request) Successful in 13m1s
CI / coverage (pull_request) Successful in 12m25s
CI / status-check (pull_request) Successful in 1s
CI / build (push) Successful in 26s
CI / lint (push) Successful in 3m31s
CI / quality (push) Successful in 3m40s
CI / typecheck (push) Successful in 3m57s
CI / benchmark-regression (push) Has been skipped
CI / security (push) Successful in 4m1s
CI / integration_tests (push) Successful in 8m55s
CI / unit_tests (push) Successful in 9m14s
CI / docker (push) Successful in 9s
CI / e2e_tests (push) Successful in 11m42s
CI / coverage (push) Successful in 11m37s
CI / status-check (push) Successful in 4s
CI / benchmark-publish (push) Successful in 29m25s
CI / benchmark-regression (pull_request) Successful in 54m8s
Rename the TDD tag system from tdd_bug/tdd_bug_<N> to tdd_issue/tdd_issue_<N>
across the entire codebase. The tdd_expected_fail tag is unchanged.

The TDD expected-failure workflow is not limited to bug fixes — it applies
equally to any issue type (features, tasks, refactors). The _bug suffix was
misleading and narrowed the perceived scope. The new _issue suffix accurately
reflects that the TDD tagging system applies to any Forgejo issue.

Changes span 92 files:
- features/environment.py: validate_tdd_tags(), should_invert_result(), and
  apply_tdd_inversion() updated — regex, variables, error messages
- robot/tdd_expected_fail_listener.py: _validate_tdd_tags(), _should_invert_result(),
  start_test(), end_test() updated consistently
- 33 Behave .feature files: all @tdd_bug/@tdd_bug_<N> tags renamed
- 29 Robot .robot files: all tdd_bug/tdd_bug_<N> tags renamed
- 3 Robot fixture files renamed (tdd_bug_alone, tdd_missing_tdd_bug,
  tdd_expected_fail_missing_bug_n) with content and references updated
- Tag validation tests and helpers updated (function names, command dispatch
  keys, output strings, fixture references)
- CONTRIBUTING.md: section renamed from 'TDD Bug Test Tags' to
  'TDD Issue Test Tags', all tag references and examples updated
- noxfile.py: comment references updated
- Step definition files, mock helpers, and benchmark files: docstring
  references updated

ISSUES CLOSED: #965
2026-03-27 05:58:35 +00:00
Luis Mendes d196e90779 test(integration): workflow example 14 — server mode team collaboration (supervised profile)
CI / benchmark-publish (pull_request) Has been skipped
CI / build (pull_request) Successful in 25s
CI / lint (pull_request) Successful in 3m20s
CI / typecheck (pull_request) Successful in 3m55s
CI / security (pull_request) Successful in 4m3s
CI / quality (pull_request) Successful in 4m10s
CI / integration_tests (pull_request) Successful in 7m23s
CI / unit_tests (pull_request) Successful in 7m41s
CI / docker (pull_request) Successful in 1m9s
CI / e2e_tests (pull_request) Successful in 12m39s
CI / coverage (pull_request) Successful in 11m17s
CI / status-check (pull_request) Successful in 1s
CI / build (push) Successful in 21s
CI / lint (push) Successful in 3m17s
CI / quality (push) Successful in 3m46s
CI / typecheck (push) Successful in 3m53s
CI / benchmark-regression (push) Has been skipped
CI / security (push) Successful in 4m1s
CI / unit_tests (push) Successful in 7m13s
CI / docker (push) Successful in 1m8s
CI / e2e_tests (push) Failing after 16m44s
CI / integration_tests (push) Failing after 16m44s
CI / coverage (push) Failing after 17m50s
CI / benchmark-publish (push) Successful in 34m0s
CI / status-check (push) Failing after 1s
CI / benchmark-regression (pull_request) Successful in 59m37s
Implemented Robot Framework integration test suite validating the server
mode team collaboration workflow (Specification Example 14) with mocked
LLM providers and in-memory domain services. Tests cover server mode
configuration, config-registry diagnostics, namespace management, action
publishing to team namespaces with namespaced actor references, shared
action consumption via use_action(), and namespace-filtered plan monitoring
across namespaces. Uses standard integration test infrastructure with
mock AI.

Post-review fixes applied:
- F1: plan_namespace() now creates actions, calls use_action() to instantiate
  plans, and verifies namespace-filtered listing with non-empty results
- F2: Renamed actor_namespace() to action_actor_refs() with accurate
  docstring (tests action actor field references, not ActorService)
- F3: Added use_shared_action() subcommand covering spec Step 3 (use a
  shared action to create a plan and verify namespace inheritance)
- F5: Updated diagnostics() docstring to accurately describe scope (config
  registry verification, not full diagnostic operations)
- F7: Fixed _COMMANDS type from dict[str, object] to dict[str, Callable]
  removing type: ignore suppression
- F9: Extracted _make_config_service() factory to remove duplicated tempdir
  creation pattern
- F10: Added [Tags] to all Robot test cases for filtering support
- F11: Added automation_profile="supervised" to all create_action() calls
  for spec consistency
- M1: Fixed CHANGELOG wording from "mocked server backend" to "in-memory
  domain services" to accurately describe the test approach
- M5: Added symmetric phase and action_name assertions for beta plan in
  plan_namespace() to match alpha plan verification depth
- M6: Added strategy_actor and review_actor assertions after get_action()
  in action_actor_refs() for complete actor field persistence verification
- M8: Added core.namespace default value verification ("local") in
  diagnostics() subcommand
- L2: Added total unfiltered action count verification in shared_actions()
- L3: Added distinguishing tags (publish/shared) to disambiguate Robot
  test cases with previously identical tag sets
- L4: Added ActionState.AVAILABLE assertion for all actions in
  shared_actions() for consistency with action_namespace()

ISSUES CLOSED: #778
2026-03-26 22:33:19 +00:00
CoreRasurae 80f1664a0d test(integration): workflow example 7 — CI/CD integration, automated PR review and fix (ci profile)
CI / benchmark-publish (pull_request) Has been skipped
CI / build (pull_request) Successful in 23s
CI / lint (pull_request) Successful in 3m20s
CI / typecheck (pull_request) Successful in 3m54s
CI / security (pull_request) Successful in 4m13s
CI / quality (pull_request) Successful in 4m17s
CI / integration_tests (pull_request) Successful in 9m21s
CI / unit_tests (pull_request) Successful in 9m42s
CI / docker (pull_request) Successful in 14s
CI / e2e_tests (pull_request) Successful in 12m1s
CI / coverage (pull_request) Successful in 11m41s
CI / status-check (pull_request) Successful in 1s
CI / build (push) Successful in 26s
CI / lint (push) Successful in 3m19s
CI / quality (push) Successful in 3m41s
CI / typecheck (push) Successful in 3m56s
CI / benchmark-regression (push) Has been skipped
CI / security (push) Successful in 4m2s
CI / integration_tests (push) Successful in 9m3s
CI / unit_tests (push) Successful in 9m24s
CI / docker (push) Successful in 1m9s
CI / e2e_tests (push) Successful in 13m51s
CI / coverage (push) Successful in 11m25s
CI / status-check (push) Successful in 1s
CI / benchmark-publish (push) Failing after 24m52s
CI / benchmark-regression (pull_request) Failing after 37m6s
Implemented Robot Framework integration test suite validating the CI/CD
workflow (Specification Example 7). Tests cover ci-profile configuration
(automation-profile, format, log level), idempotent resource and project
registration with duplicate-detection assertions, three validation tools
(ci-lint, ci-typecheck, ci-tests) registration and resource attachment
via ToolRegistryService, action creation with typed arguments and
invariants per spec Step 2, plan lifecycle with phase-by-phase completion
through all phases (strategize, execute, apply) until terminal applied
state, and JSON output structure verification including plan_id, phase,
state, action, projects, and arguments fields.

Post-review fixes applied (round 1):
- H1: Fix truncated invariant #2 text to match spec line 39051
- H2: Fix definition_of_done to match spec's 5-bullet-point format
- M1: Register all 3 spec validations (ci-lint, ci-typecheck, ci-tests)
- M3: Add branch property to resource registration per spec Step 3
- M4: Replace phantom resource_id with real registered resource
- M5: Add projects and arguments field assertions to JSON output test
- M7: Replace 'polling-based' with 'phase-by-phase' in docs/comments
- L1: Use timezone-aware datetime (timezone.utc)
- L2: Use tempfile for resource path instead of hardcoded /tmp
- L3: Clarify json_output() docstring to reflect as_cli_dict() scope
- L4: Tighten attachment count assertion from >= 1 to == 1 (now == 3)

Post-review fixes applied (round 2):
- M2: Use Setup Test Environment With Database Isolation for pabot safety
- L1: Replace remaining hardcoded /tmp paths with tempfile (validation_attach,
  resource_idempotent duplicate registration)
- L2: Fix stale 'Polling-based' comment missed in round 1
- L5: Align action description with spec line 39027
- M1/L3/L6: Document automation_profile propagation gap in use_action()
  with TODO for when production code wires the field onto Plan
- L4: Add comment explaining local actor name deviation from spec

Includes CHANGELOG update describing the integration test scope.

ISSUES CLOSED: #771
2026-03-26 21:42:37 +00:00
CoreRasurae d2c70bd489 test(e2e): workflow example 14 — server mode team collaboration (supervised profile)
CI / benchmark-publish (pull_request) Has been skipped
CI / build (pull_request) Successful in 29s
CI / quality (pull_request) Successful in 33s
CI / security (pull_request) Successful in 59s
CI / lint (pull_request) Successful in 3m40s
CI / typecheck (pull_request) Successful in 3m57s
CI / unit_tests (pull_request) Successful in 5m55s
CI / docker (pull_request) Successful in 1m11s
CI / integration_tests (pull_request) Successful in 7m21s
CI / coverage (pull_request) Successful in 11m34s
CI / status-check (pull_request) Successful in 1s
CI / e2e_tests (pull_request) Successful in 11m30s
CI / build (push) Successful in 24s
CI / lint (push) Successful in 3m18s
CI / quality (push) Successful in 3m41s
CI / typecheck (push) Successful in 4m16s
CI / benchmark-regression (push) Has been skipped
CI / security (push) Successful in 4m25s
CI / unit_tests (push) Successful in 7m15s
CI / integration_tests (push) Successful in 7m22s
CI / docker (push) Successful in 1m16s
CI / e2e_tests (push) Successful in 12m3s
CI / coverage (push) Successful in 12m2s
CI / status-check (push) Successful in 1s
CI / benchmark-publish (push) Failing after 22m16s
CI / benchmark-regression (pull_request) Successful in 51m52s
Implemented Robot Framework E2E test suite validating Specification
Workflow Example 14 (Server Mode Team Collaboration). Tests exercise
the real CleverAgents CLI with zero mocking, covering server mode
configuration (server.url, server.token, core.namespace), diagnostics,
action publishing to team namespace with namespace-scoped listing,
actor registration, plan list graceful handling, and supervised
automation profile verification.

Review fixes applied:
- Added WF14 Suite Setup with agents init and uuid4 suffix generation
- Added WF14 Suite Teardown to reset config state (server.url,
  server.token, core.namespace)
- Added server.token config round-trip per spec Example 14 Step 1
- Changed action name to myteam/ namespace prefix per spec Step 2
- Added action list --namespace myteam test per issue AC
- Replaced epoch-based name uniqueness with uuid4 for CI safety
- Updated diagnostics test documentation (no server connectivity check)
- Changed to Force Tags E2E at suite level for consistency
- Added description field to actor YAML configuration
- Updated plan list test documentation to reflect actual behavior
- Reverted unrelated cls->klass rename from strategy_registry.py
  (CONTRIBUTING.md: do not mix cosmetic changes with functional changes)
- Updated CHANGELOG to accurately reflect test coverage

ISSUES CLOSED: #760
2026-03-26 18:56:16 +00:00
CoreRasurae cefbca73c2 test(e2e): workflow example 7 — CI/CD integration, automated PR review and fix (ci profile)
CI / lint (pull_request) Successful in 3m18s
CI / build (pull_request) Successful in 45s
CI / typecheck (pull_request) Successful in 3m49s
CI / security (pull_request) Successful in 4m7s
CI / quality (pull_request) Successful in 4m9s
CI / benchmark-publish (pull_request) Has been skipped
CI / integration_tests (pull_request) Successful in 7m11s
CI / unit_tests (pull_request) Successful in 7m53s
CI / docker (pull_request) Successful in 1m2s
CI / e2e_tests (pull_request) Successful in 12m13s
CI / coverage (pull_request) Successful in 11m54s
CI / status-check (pull_request) Successful in 1s
CI / build (push) Successful in 20s
CI / lint (push) Successful in 3m15s
CI / quality (push) Successful in 3m39s
CI / typecheck (push) Successful in 3m56s
CI / benchmark-regression (push) Has been skipped
CI / security (push) Successful in 4m24s
CI / unit_tests (push) Successful in 6m7s
CI / integration_tests (push) Successful in 6m53s
CI / docker (push) Successful in 1m49s
CI / e2e_tests (push) Successful in 12m4s
CI / coverage (push) Successful in 10m14s
CI / status-check (push) Successful in 3s
CI / benchmark-publish (push) Successful in 28m31s
CI / benchmark-regression (pull_request) Successful in 53m11s
Implemented Robot Framework E2E test suite validating Specification
Workflow Example 7 (CI/CD Integration).  Tests exercise the real
CleverAgents CLI with zero mocking, covering:

- ci-profile configuration with JSON output format and WARN log level
  (spec Step 1)
- Idempotent resource and project registration with resource linking,
  verified via strict occurrence-count assertions
- Three-validation registration (lint, typecheck, tests) with project
  attachment and tool-list verification
- CI plan launch with action args (pr_branch, base_branch), explicit
  plan execute for lifecycle progression, and terminal-state assertion
- JSON output verification via json.loads() with raw_decode fallback
  for mixed log/JSON CLI output
- Graceful degradation via Skip If No LLM Keys when API keys are
  unavailable

Resource/project naming follows spec convention (local/ci-workspace
project, local/ci-main resource).  Entity creation commands tolerate
"already exists" for CI re-runnability.  Config assertions use
stdout-only matching and exact equality.  Validation naming aligned
with spec (local/ci-lint per §Example 7, line 39130).

Added robot/common_vars.py module placeholder for shared Robot
Framework variables.

ISSUES CLOSED: #753
2026-03-26 18:10:14 +00:00
CoreRasurae e4c01492d5 refactor(cli): align actor run signature with spec positional args
CI / benchmark-publish (pull_request) Has been skipped
CI / build (pull_request) Successful in 15s
CI / lint (pull_request) Successful in 3m18s
CI / quality (pull_request) Successful in 3m47s
CI / typecheck (pull_request) Successful in 3m52s
CI / security (pull_request) Successful in 4m1s
CI / integration_tests (pull_request) Successful in 6m53s
CI / unit_tests (pull_request) Successful in 7m9s
CI / docker (pull_request) Successful in 1m9s
CI / e2e_tests (pull_request) Successful in 11m5s
CI / coverage (pull_request) Successful in 11m15s
CI / status-check (pull_request) Successful in 1s
CI / lint (push) Successful in 3m16s
CI / build (push) Successful in 31s
CI / typecheck (push) Successful in 4m0s
CI / security (push) Successful in 4m1s
CI / benchmark-regression (push) Has been skipped
CI / quality (push) Successful in 4m8s
CI / integration_tests (push) Successful in 6m10s
CI / unit_tests (push) Successful in 7m35s
CI / docker (push) Successful in 1m9s
CI / e2e_tests (push) Successful in 9m58s
CI / coverage (push) Successful in 11m7s
CI / status-check (push) Successful in 1s
CI / benchmark-publish (push) Failing after 17m22s
CI / benchmark-regression (pull_request) Successful in 56m7s
Aligned the `agents actor run` command signature with the
specification by introducing positional NAME and PROMPT arguments.
The --config/-c option is preserved as an optional fallback for
direct YAML invocation. When NAME is provided without --config,
the actor is resolved from the Actor Registry.

Updated both actor_run.py and actor.py run commands. Added backward
compatibility: if --config is provided, it takes precedence over
name-based resolution.

Review fixes applied (code review round 1):
- P1-1: Narrowed bare `except Exception` to `except NotFoundError`
  in _resolve_config_files to avoid masking infrastructure errors.
- P1-2: Moved _resolve_config_files call inside the try block in
  run() so container/registry init errors get user-friendly messages.
  Added `except click.exceptions.Exit: raise` to let typer.Exit
  propagate through the broadened try scope.
- P1-3: Added atexit.register cleanup for temp files created by
  _resolve_config_files (resource leak fix).
- P1-4: Added CHANGELOG.md entry for the breaking CLI change.
- P2-1: Extracted duplicated _resolve_config_files to shared module
  `_resolve_actor.py`; both actor.py and actor_run.py now import it.
- P2-2: Added guard for actors with no configuration data
  (config_blob=None) to produce a clear error instead of invalid YAML.
- P2-3/P2-4: Added 5 BDD scenarios exercising the real
  resolve_config_files function (registry path, yaml_text path,
  config_blob fallback, no-config-data error, not-found error).
- P2-5: Added @coverage tags to all new BDD scenarios.
- P3-1: Added timeout=120s and on_timeout=kill to Robot tests.
- Fixed rxpy_route_validation.robot tests that used the removed
  --prompt/-p option (replaced with positional NAME + PROMPT args).

Review fixes applied (code review round 2):
- P2-1: Aligned actor_run.py exception handler from
  `CleverAgentsException` to `CleverAgentsError`, matching actor.py
  so infrastructure errors from registry resolution get user-friendly
  messages instead of falling through to the generic handler.
- P2-2: Changed `yaml.dump` to `yaml.safe_dump` in _resolve_actor.py
  for fail-fast behavior on unexpected types, consistent with the
  codebase's dominant pattern.
- P3-6: Replaced defensive `getattr(actor, ...)` calls with direct
  Pydantic model attribute access (`actor.yaml_text`, `actor.config_blob`)
  for type-checker coverage.
- P3-1: Switched BDD temp file cleanup from post-assertion
  `unlink()` to `context.add_cleanup()` for leak-proof teardown.
- P2-3/P3-2/P3-3/P3-4: Added 3 BDD edge-case scenarios
  (empty config_blob dict, infrastructure error propagation, empty
  string name) and 1 Robot test case (actor_app registry resolution).

Review fixes applied (code review round 3):
- P1-1: Migrated 48 remaining `-p` invocations across 9 Robot test
  files to the new positional `NAME PROMPT` pattern (context_delete_all_yes,
  load_context_test, scientific_paper_e2e_test, routing_prefix_stripping,
  scientific_paper_basic, scientific_paper_writer_test,
  context_management_test, initial_next_command_test,
  system_prompt_template_rendering).
- P2-1: Documented `--config/-c` as a spec deviation in
  `_resolve_actor.py` module docstring (spec lines 4562-4566 define
  `actor run` with no --config option; issue #901 AC accepts keeping
  it as optional).
- P2-2: Corrected `--config` help text from "fallback" to "overrides
  registry-based name resolution" — the option takes precedence, not
  the other way around.
- P3-1: Added `.strip()` to `yaml_text` emptiness check in
  `_resolve_actor.py` to handle whitespace-only values that would
  otherwise bypass the `config_blob` fallback.
- P3-2: Added `from None` to the no-configuration-data
  `typer.Exit(code=2)` for consistency with the not-found path.
- P3-3: Added BDD scenario testing `--config` precedence for
  `actor_run_app` (was only tested for `actor_app`).
- P3-4: Strengthened config_blob BDD scenario to verify generated
  YAML is parseable via `yaml.safe_load` round-trip.
- P3-7: Replaced hardcoded `/tmp/dummy.yaml` with
  `tempfile.gettempdir()` for portability.
- P3-8: Moved 5 inline imports to module level per CONTRIBUTING.md
  §1292-1294 (3x `import click`, 1x InfrastructureError in steps;
  1x `import typer` in robot helper).
- P3-9: Added `encoding="utf-8"` to `_write_yaml` in Robot helper
  for consistency with production code.

Review fixes applied (code review round 4):
- P2-1: Wrapped `yaml.safe_dump` in `_resolve_actor.py` with
  `try/except yaml.YAMLError` so non-serialisable config_blob values
  produce a user-friendly error message instead of a raw traceback.
- P2-2: Moved remaining inline `import yaml` to module level in
  `actor_run_signature_steps.py` per CONTRIBUTING.md §1292-1294.
- P2-3: Replaced 3 bare `assert` statements in Robot helper
  `helper_actor_run_signature.py` with diagnostic `if/print/sys.exit`
  pattern matching the rest of the file, improving failure diagnostics.

Review fixes applied (code review round 5):
- P3-4: Replaced per-call `atexit.register(lambda)` in
  `_resolve_actor.py` with a module-level `_temp_files` set and a
  single `atexit` handler (`_cleanup_temp_files`) to prevent
  unbounded handler accumulation in same-process usage (e.g. test
  suites running multiple CliRunner invocations).
- P3-1/P3-2/P3-3: Added 4 BDD scenarios: whitespace-only
  `yaml_text` fallback to config_blob, config-precedence
  registry-not-consulted assertion for both `actor_app` and
  `actor_run_app`, multiple `--config` files with positional NAME.
- P4-1: Strengthened error-path BDD assertions to verify error
  message content (not-found, no-config-data, serialisation-error)
  alongside exit codes via captured stderr.
- P4-2: Added Robot test case for `actor_app` unknown-name error
  path and corresponding helper function.

ISSUES CLOSED: #901
2026-03-26 13:41:31 +00:00
CoreRasurae 00881a3e5f feat(observability): implement Event System Domain Event Taxonomy (full EventType enum + DomainEvent model)
CI / benchmark-publish (pull_request) Has been skipped
CI / lint (pull_request) Successful in 3m26s
CI / build (pull_request) Successful in 14s
CI / typecheck (pull_request) Successful in 4m2s
CI / quality (pull_request) Successful in 4m2s
CI / security (pull_request) Successful in 4m23s
CI / integration_tests (pull_request) Successful in 9m35s
CI / unit_tests (pull_request) Successful in 9m39s
CI / docker (pull_request) Successful in 2m15s
CI / e2e_tests (pull_request) Successful in 12m32s
CI / coverage (pull_request) Successful in 11m41s
CI / status-check (pull_request) Successful in 1s
CI / build (push) Successful in 23s
CI / lint (push) Successful in 3m17s
CI / typecheck (push) Successful in 4m11s
CI / quality (push) Successful in 4m11s
CI / security (push) Successful in 4m28s
CI / benchmark-regression (push) Has been skipped
CI / integration_tests (push) Successful in 9m13s
CI / unit_tests (push) Successful in 9m26s
CI / e2e_tests (push) Successful in 10m20s
CI / docker (push) Successful in 1m16s
CI / coverage (push) Successful in 12m2s
CI / status-check (push) Successful in 1s
CI / benchmark-publish (push) Successful in 33m17s
CI / benchmark-regression (pull_request) Successful in 57m23s
Verified and completed the Event System Domain Event Taxonomy implementation.

Gap analysis:
- EventType enum (38 types across 12 domains): ALREADY EXISTED, verified complete
- DomainEvent Pydantic model (all 9 fields): ALREADY EXISTED, verified complete
- EventBus Protocol (emit + subscribe): ALREADY EXISTED, verified complete
- ReactiveEventBus (RxPY Subject, stream property): ALREADY EXISTED, verified
- LoggingEventBus (structlog-based): ALREADY EXISTED, verified complete

Added:
- In-memory audit_log on ReactiveEventBus (list[DomainEvent] with defensive copy)
- Emit ordering aligned with specification: RxPY stream push, then audit append,
  then handler dispatch (§Event System)
- Clarified audit_log docstring: volatile in-memory log, not durable SQLite
  persistence (durable persistence wired separately via audit service layer)
- Behave feature: features/observability/event_system_taxonomy.feature (36 scenarios)
- Step definitions: features/steps/event_system_taxonomy_steps.py
- Robot integration test: robot/event_system_taxonomy_integration.robot (13 test cases)
- Robot helper: robot/helper_event_system_taxonomy.py (13 subcommands)
- ASV benchmark: benchmarks/bench_event_bus.py (5 benchmark suites)
- vulture_whitelist.py: added audit_log property

Code review fixes applied:
- Reordered emit() to match spec: on_next → audit_log → handlers (was: audit → on_next → handlers)
- Clarified audit_log docstring to distinguish volatile in-memory log from spec SQLite table
- Fixed benchmark TaxonomyAuditLogSuite: parameterized setup instead of inline construction
- Added teardown to TaxonomyLoggingEmitSuite to restore logging.disable(NOTSET)
- Clear _received list between benchmark iterations to reduce noise
- Catch specific pydantic.ValidationError in frozen model mutation tests
- Consolidated duplicate singular/plural step definitions
- Tightened EventType count threshold from >=30 to >=38

Quality gates:
- lint: PASSED
- typecheck: PASSED (0 errors)
- unit_tests: 36/36 new scenarios PASSED (pre-existing 12 flaky failures unchanged)
- integration_tests: 1483/1483 PASSED
- security_scan: PASSED
- dead_code: PASSED

ISSUES CLOSED: #587
2026-03-26 11:52:52 +00:00
hurui200320 414abb1396 fix(cli): add missing --yes flag to plan apply command (#1127)
CI / benchmark-publish (push) Waiting to run
CI / lint (push) Successful in 19s
CI / build (push) Successful in 20s
CI / quality (push) Successful in 3m49s
CI / typecheck (push) Successful in 3m58s
CI / benchmark-regression (push) Waiting to run
CI / security (push) Successful in 4m7s
CI / integration_tests (push) Successful in 6m48s
CI / unit_tests (push) Successful in 7m30s
CI / docker (push) Successful in 1m12s
CI / e2e_tests (push) Successful in 10m1s
CI / coverage (push) Successful in 11m48s
CI / status-check (push) Successful in 1s
## Summary

Adds the `--yes`/`-y` flag to the `lifecycle-apply` CLI command as required by the specification (`agents plan apply [--yes|-y] <PLAN_ID>`). Without `--yes`, a confirmation prompt now displays before proceeding with the destructive Apply phase. With `--yes`, the apply proceeds immediately without prompting.

Closes #932

## Changes

### Source Code
- **`src/cleveragents/cli/commands/plan.py`**: Added `yes: Annotated[bool, typer.Option("--yes", "-y", help="Skip confirmation prompt")] = False` parameter to `lifecycle_apply_plan`. Added `typer.confirm()` prompt before the apply operation, consistent with the pattern used by `rollback_plan`, `correct_plan`, and other destructive commands.
  - Confirmation prompt text matches spec exactly: `"Apply changes for plan {plan_id}?"` producing `Apply changes for plan <ID>? [y/N]:`.
  - Fixed redundant plan ID display when `pre_plan` is `None` — now shows `"Apply changes for plan X?"` instead of `"Apply plan X (X)?"`.
  - Added `except ValueError` handler consistent with sibling commands `lifecycle_execute_plan` and `_lifecycle_apply_with_id`.
  - Added `except Exception` catch-all handler with `isinstance(e, (typer.Abort, typer.Exit))` re-raise guard, consistent with `lifecycle_execute_plan`.
  - Moved `PlanPhase` and `ProcessingState` imports to module level per CONTRIBUTING.md §Import Guidelines.

### TDD Tag Removal (Bug Fix Workflow)
- **`features/tdd_plan_apply_yes_flag.feature`**: Removed `@tdd_expected_fail` tag (leaving `@tdd_bug` and `@tdd_bug_932` as permanent regression guards).
- **`robot/tdd_plan_apply_yes_flag.robot`**: Removed `tdd_expected_fail` tag (leaving `tdd_bug` and `tdd_bug_932`).

### Test Updates
Updated all existing `lifecycle-apply` invocations across 17 test/benchmark files to pass `--yes`, since the new confirmation prompt would otherwise abort in non-interactive test environments:
- 9 Behave step definition files
- 3 Robot Framework helper scripts
- 2 Robot Framework e2e acceptance tests
- 3 ASV benchmark files (4 invocations: `cli_robot_flow_bench.py` ×2, `m1_sourcecode_smoke_bench.py` ×1, `plan_cli_smoke_bench.py` ×1)

### Confirmation Prompt Tests (New + Strengthened)
- **`features/tdd_plan_apply_yes_flag.feature`**: 5 scenarios total:
  - `lifecycle-apply recognises the --yes long flag` — verifies flag acceptance, prompt suppression, exit code 0, and `apply_plan` was called
  - `lifecycle-apply recognises the -y short flag` — same as above for short flag
  - `lifecycle-apply without --yes prompts for confirmation and user declines` — verifies `"Apply cancelled."` message, `exit_code == 0`, and `apply_plan` was NOT called
  - `lifecycle-apply without --yes prompts for confirmation and user accepts` — verifies prompt appears, `exit_code == 0`, and `apply_plan` was called
  - `lifecycle-apply catches unexpected exceptions cleanly` — verifies `"Unexpected error"` output, no traceback leak, non-zero exit code (exercises the `except Exception` catch-all)
- **`features/steps/tdd_plan_apply_yes_flag_steps.py`**: Refactored step definitions:
  - `_make_mock_plan` uses `PlanPhase` and `ProcessingState` enum types instead of raw strings
  - `_make_mock_plan` uses `datetime.now(tz=UTC)` instead of timezone-naive `datetime.now()`
  - Unified prompt suppression step handles both `--yes` and `-y` via parameterised step pattern
  - Added `When` step for unexpected error scenario with `RuntimeError` side_effect
  - Added `Then` step for non-zero exit code assertion
- **Feature/Robot documentation**: Updated stale descriptions that said "implementation does not accept --yes" to reflect the flag is now implemented.

### Documentation
- **`docs/reference/plan_cli.md`**: Updated `lifecycle-apply` section with:
  - `### Synopsis` heading with code block
  - `### Options` table listing `--yes/-y` and `--format/-f` flags
  - `### Arguments` table listing `PLAN_ID`
  - Matches the style used by other command sections in the same file

## Review Fixes (Cycle 3 — Luis's review)

| ID | Severity | Issue | Resolution |
|----|----------|-------|------------|
| M1 | Medium | `typer.Abort()` on user decline produces exit code 1 and redundant "Aborted." | Changed to `raise typer.Exit(0)` — consistent with `correct_decision` and legacy `apply` |
| M2 | Medium | Missing exit code assertion on decline scenario | Added `And the lifecycle-apply exit code should be 0` to the decline scenario |
| M3 | Medium | Spec compliance: "summary of pending changes" not implemented | Deferred — spec example shows summary *after* confirmation, not before; implementation matches spec. Ticket-vs-spec ambiguity noted. |
| L1 | Low | Missing `except Exception` catch-all handler | Added catch-all matching `lifecycle_execute_plan` pattern; re-raises `typer.Abort`/`typer.Exit` |
| L2 | Low | Documentation description not updated | Expanded description in `plan_cli.md` to explain confirmation prompt and `--yes` |
| L3 | Low | Dead code `is not None` guards | Removed both guards — `get_plan()` raises `NotFoundError`, never returns `None` |
| I1 | Info | Duplicate `PlanPhase` import | Hoisted import to top of `try` block, eliminating duplicate at old line 2087 |
| I2 | Info | `typer.confirm` without explicit `default=False` | Added `default=False` for consistency with sibling commands |
| L4 | Low | No test for `--yes` after positional arg | Not addressed — Typer/Click handles both orderings; low risk |
| L5 | Low | No test for auto-select + interactive prompt | Not addressed — separate concern outside ticket scope |
| I3 | Info | Robot helper only tests flag recognition | By design — noted as informational |

## Review Fixes (Cycle 4 — Self-QA)

| ID | Severity | Issue | Resolution |
|----|----------|-------|------------|
| Major-1 | Major | No test for `except Exception` catch-all handler | Added new scenario `"lifecycle-apply catches unexpected exceptions cleanly"` with `RuntimeError` side_effect; asserts `"Unexpected error"` output, no traceback, non-zero exit |
| Minor-2 | Minor | Missing `ValueError` handler inconsistent with siblings | Added `except ValueError as e:` with `"[red]Execution Error:[/red]"` before catch-all, matching `lifecycle_execute_plan` and `_lifecycle_apply_with_id` |
| Minor-3 | Minor | Flag scenarios don't verify `apply_plan` called | Added `And the lifecycle-apply should have called apply` to both `--yes` and `-y` scenarios |
| Minor-4 | Minor | Stale docstring in Robot helper references `tdd_expected_fail` inversion | Updated to reflect bug is fixed and tests serve as regression guards |
| Minor-5 | Minor | `plan_cli.md` lacks Options table for `lifecycle-apply` | Added Synopsis, Options, and Arguments sections matching sibling command style |
| Nit-6 | Nit | Duplicated step defs for `--yes` vs `-y` prompt suppression | Unified into single parameterised step `"the lifecycle-apply {flag} output should not contain the confirmation prompt"` |
| Nit-7 | Nit | `datetime.now()` timezone-naive | Changed to `datetime.now(tz=UTC)` |
| Nit-8 | Nit | `_make_mock_plan` params use `str` instead of enum types | Changed to `PlanPhase` and `ProcessingState` enum types |

## Review Fixes (Cycle 5 — Jeff's approval note)

| ID | Severity | Issue | Resolution |
|----|----------|-------|------------|
| Import-1 | Minor | `PlanPhase`/`ProcessingState` imports inside function body instead of module level | Moved to module-level import per CONTRIBUTING.md §Import Guidelines |

## Known Limitations / Deferred Items

- **M3: Ticket AC mentions "summary of pending changes"** but the spec example only shows `"Apply changes for plan <ID>? [y/N]: y"` without a change summary. The implementation shows plan ID only (matching the spec), not a change summary. This is a ticket-vs-spec ambiguity; recommend discussing with ticket author.
- **Legacy `apply` command** accepts `--yes` but does not pass it to `_lifecycle_apply_with_id()`. This is a pre-existing issue outside the scope of this ticket.
- **`pre_plan is None` branch** has no explicit test. Pre-existing architectural issue; no action taken.

## Quality Gates

| Gate | Result |
|------|--------|
| `nox -s lint` |  passed |
| `nox -s typecheck` |  passed (0 errors) |
| `nox -s unit_tests` |  passed (471 features, 12,424 scenarios, 0 failures) |
| `nox -s integration_tests` |  passed (1,727 tests, 0 failures) |
| `nox -s e2e_tests` |  passed (41 tests, 0 failures) |
| `nox -s coverage_report` |  passed (≥97% coverage) |

Reviewed-on: #1127
Reviewed-by: Jeffrey Phillips Freeman <jeffrey.freeman@cleverthis.com>
Co-authored-by: Rui Hu <rui.hu@cleverthis.com>
Co-committed-by: Rui Hu <rui.hu@cleverthis.com>
2026-03-26 07:50:09 +00:00
aditya d8d08facde feat(acms): budget enforcement with max_file_size and max_total_size constraints
CI / build (pull_request) Successful in 22s
CI / lint (pull_request) Successful in 3m20s
CI / quality (pull_request) Successful in 3m55s
CI / security (pull_request) Successful in 4m2s
CI / typecheck (pull_request) Successful in 4m13s
CI / integration_tests (pull_request) Successful in 6m50s
CI / unit_tests (pull_request) Successful in 7m19s
CI / docker (pull_request) Successful in 1m8s
CI / e2e_tests (pull_request) Successful in 9m53s
CI / coverage (pull_request) Successful in 11m28s
CI / status-check (pull_request) Successful in 1s
CI / benchmark-publish (pull_request) Has been skipped
CI / benchmark-regression (pull_request) Successful in 1h9m52s
Implements byte-size budget enforcement for the ACMS context assembly
pipeline.  enforce_size_budget() filters context fragments against
max_file_size (per-fragment) and max_total_size (cumulative) limits
defined in a ContextView.  New domain models BudgetViolation and
BudgetEnforcementResult provide structured violation reporting.

Pipeline integration in ACMSPipeline.assemble() applies enforcement
as a pre-filter when a context_view is provided.

Review feedback addressed:
- Fixed PR milestone to v3.4.0 (matching ticket #847)
- Rebased branch onto latest master
- Added CHANGELOG.md entry
- Extracted duplicated enforcement logic into _apply_budget_enforcement()
  shared method on ACMSPipeline, called by both parent and subclass
- Fixed _make_fragment return type from object to ContextFragment
- Moved all imports to top of files (acms_pipeline.py, steps file)
- Added errors="replace" to encode("utf-8") for surrogate safety
- Documented thread-safety caveat on last_enforcement_result property
- Added short-circuit early return when both limits are None
- Added multi-byte Unicode content test scenario
- Added total_size assertions to key scenarios
- Added violation type verification to mixed limits scenario
- Merged duplicate singular/plural step definitions
- Added edge case scenarios (empty list, all exceed, exact boundary)
- Fixed misleading docstring in ContextAssemblyPipeline.assemble()
- Re-exported VALID_PHASES through core __init__.py public API

ISSUES CLOSED: #847
2026-03-26 07:14:43 +00:00
aditya 968f33c17d test(cli): TDD failing tests for actor list database update (bug #797)
CI / build (pull_request) Successful in 17s
CI / lint (pull_request) Successful in 3m20s
CI / quality (pull_request) Successful in 3m41s
CI / typecheck (pull_request) Successful in 3m57s
CI / security (pull_request) Successful in 4m3s
CI / integration_tests (pull_request) Successful in 7m30s
CI / unit_tests (pull_request) Successful in 8m26s
CI / docker (pull_request) Successful in 1m7s
CI / e2e_tests (pull_request) Successful in 9m52s
CI / coverage (pull_request) Successful in 11m26s
CI / status-check (pull_request) Successful in 3s
CI / benchmark-publish (pull_request) Has been skipped
CI / benchmark-regression (pull_request) Successful in 1h2m29s
Add TDD tests that prove bug #797 exists: the read-only `agents actor list`
command triggers database writes via `ActorRegistry.list_actors()` calling
`ensure_built_in_actors()`, which invokes `upsert_actor()` and potentially
`set_default_actor()` on every invocation.

Behave scenarios (features/tdd_actor_list_no_db_update.feature):
- Assert upsert_actor is not called during actor list (fails: bug present)
- Assert set_default_actor is not called during actor list (fails: bug present)

Robot Framework tests (robot/tdd_actor_list_no_db_update.robot):
- Integration smoke tests via helper script with same assertions
- Both test cases fail as expected, inverted by tdd_expected_fail_listener

All tests tagged @tdd_expected_fail @tdd_bug @tdd_bug_797 per the mandatory
TDD bug-fix workflow. The inversion mechanism converts the expected failures
to passes in CI. When bug #797 is fixed, the @tdd_expected_fail tag will be
removed and the tests will run normally.

Quality gates: lint pass, typecheck pass, coverage 98.22% (>97%).

ISSUES CLOSED: #841
2026-03-26 06:45:11 +00:00
aditya 42a32c2709 fix(acms): align budget allocation formula and protocol signatures with spec
CI / build (pull_request) Successful in 18s
CI / lint (pull_request) Successful in 3m19s
CI / quality (pull_request) Successful in 3m42s
CI / security (pull_request) Successful in 4m6s
CI / typecheck (pull_request) Successful in 4m11s
CI / integration_tests (pull_request) Successful in 5m56s
CI / unit_tests (pull_request) Successful in 7m20s
CI / docker (pull_request) Successful in 50s
CI / e2e_tests (pull_request) Successful in 10m0s
CI / coverage (pull_request) Successful in 11m13s
CI / status-check (pull_request) Successful in 4s
CI / benchmark-publish (pull_request) Has been skipped
CI / benchmark-regression (pull_request) Has been cancelled
Align ACMS pipeline protocol signatures and allocation formula with the
specification (docs/specification.md §42630-42937):

- BudgetAllocator.allocate() now accepts optional request: ContextRequest
  parameter per BudgetAllocatorProtocol spec (§44754-44766), enabling
  future request-aware allocation strategies.

- Allocation formula changed from proportional to confidence alone to
  proportional to confidence * quality_score per spec §45003. Both
  DefaultBudgetAllocator and ProportionalBudgetAllocator use the new
  weighted formula. With default quality_score=1.0, behavior is backward-
  compatible.

- DetailDepthResolver.resolve() now accepts budget: int parameter per
  DetailDepthResolverProtocol spec (§44803-44814), enabling future
  budget-aware depth resolution decisions.

- Default packer changed from no-op DefaultBudgetPacker to production
  GreedyKnapsackPacker per spec §45013. ACMSPipeline uses lazy import
  to avoid circular dependency; ContextAssemblyPipeline imports directly.

- Added quality_score field to service-layer StrategyCapabilities
  (already present in domain model).

- Updated 5 feature scenarios and 1 Robot helper where GreedyKnapsackPacker
  relevance-based ordering changed fragment output order vs. the old no-op
  packer. Fixed by adjusting test fragment relevance scores to preserve
  expected ordering.

ISSUES CLOSED: #924
2026-03-26 06:19:14 +00:00
brent.edwards 8ccda647a8 Merge remote-tracking branch 'origin/master' into merge-master-tmp
CI / benchmark-publish (pull_request) Has been skipped
CI / build (pull_request) Successful in 18s
CI / lint (pull_request) Successful in 4m34s
CI / quality (pull_request) Successful in 4m54s
CI / typecheck (pull_request) Successful in 5m33s
CI / security (pull_request) Successful in 5m48s
CI / integration_tests (pull_request) Successful in 7m50s
CI / unit_tests (pull_request) Successful in 9m37s
CI / docker (pull_request) Successful in 1m11s
CI / e2e_tests (pull_request) Successful in 10m44s
CI / coverage (pull_request) Successful in 11m39s
CI / status-check (pull_request) Successful in 1s
CI / benchmark-regression (pull_request) Has been cancelled
2026-03-26 02:09:54 +00:00
brent.edwards 0e407f7f19 test: add TDD bug-capture test for #1022 — InvariantService persistence (#1109)
CI / build (push) Successful in 27s
CI / lint (push) Successful in 3m20s
CI / quality (push) Successful in 3m54s
CI / typecheck (push) Successful in 4m6s
CI / benchmark-regression (push) Has been skipped
CI / integration_tests (push) Successful in 6m55s
CI / unit_tests (push) Successful in 7m6s
CI / security (push) Successful in 8m4s
CI / e2e_tests (push) Successful in 10m47s
CI / docker (push) Successful in 1m9s
CI / coverage (push) Successful in 14m37s
CI / status-check (push) Successful in 1s
CI / benchmark-publish (push) Failing after 24m9s
## Summary

Add Behave BDD and Robot Framework integration tests that capture bug #1022 — `InvariantService` stores invariants in an in-memory dict only, losing them across CLI process invocations.

### Motivation

Per the project's TDD Bug Fix Workflow (CONTRIBUTING.md), every bug must first have a test written that captures the buggy behavior before the fix is implemented. This PR fulfills the TDD counterpart issue #1032 for bug #1022.

### What was done

**Behave tests** (`features/tdd_invariant_persistence.feature`): Four scenarios tagged `@tdd_expected_fail @tdd_bug @tdd_bug_1022 @mock_only` that simulate separate CLI invocations via fresh `InvariantService` instances and assert cross-instance data visibility:

1. Project invariant persistence across service instances
2. Global invariant persistence across service instances
3. CLI add/list across separate invocations
4. Cross-instance soft-delete by invariant ID

Step definitions in `features/steps/tdd_invariant_persistence_steps.py`.

**Robot integration tests** (`robot/tdd_invariant_persistence.robot`): Three integration test cases with a helper script (`robot/helper_tdd_invariant_persistence.py`) that exercises add-then-list and add-then-remove across fresh service instances.

### How it passes CI

All tests carry `@tdd_expected_fail`, which inverts the test result via the environment hooks (Behave) and listener (Robot). The underlying assertions fail (proving the bug exists), but are reported as passed to CI. The `@tdd_expected_fail` tag will be removed when bug #1022 is fixed, at which point the tests will run normally and must pass.

### Review fixes applied

- **M1**: Moved `InvariantScope` import from function body in `robot/helper_tdd_invariant_persistence.py` to module-level top imports.
- **m1**: Added `@mock_only` tag to `features/tdd_invariant_persistence.feature` — these tests use purely in-memory services and never touch the database.
- **m2**: Added `exit_code == 0` assertion to `step_invoke_list_cli` in `features/steps/tdd_invariant_persistence_steps.py`, matching the pattern used in `step_invoke_add_cli`.
- **m3**: Changed all `context: Any` parameter types to `context: Context` (from `behave.runner`), following the project-wide convention used in 335+ step files.
- **m4**: Narrowed `except Exception` to `except NotFoundError` in `robot/helper_tdd_invariant_persistence.py`, matching the specific error being tested.
- **n3**: Branch rebased onto latest `master`.

### Quality Gates

- **lint**:  passed
- **typecheck**:  passed (Pyright, 0 errors)
- **unit_tests**:  1 feature, 4 scenarios, 16 steps — all passed via `@tdd_expected_fail`
- **coverage**: ≥ 97% (test-only changes, no source modifications)

Closes #1032

Co-authored-by: Jeffrey Phillips Freeman <the@jeffreyfreeman.me>
Reviewed-on: #1109
Reviewed-by: Jeffrey Phillips Freeman <jeffrey.freeman@cleverthis.com>
Co-authored-by: Brent E. Edwards <brent.edwards@cleverthis.com>
Co-committed-by: Brent E. Edwards <brent.edwards@cleverthis.com>
2026-03-26 02:06:28 +00:00
brent.edwards 822f999ebb fix(test): increase container resolve regression timeouts to 120s
CI / build (pull_request) Successful in 32s
CI / lint (pull_request) Successful in 3m22s
CI / quality (pull_request) Successful in 3m42s
CI / typecheck (pull_request) Successful in 3m55s
CI / security (pull_request) Successful in 4m2s
CI / integration_tests (pull_request) Successful in 6m42s
CI / unit_tests (pull_request) Successful in 7m4s
CI / docker (pull_request) Successful in 1m10s
CI / e2e_tests (pull_request) Successful in 9m49s
CI / benchmark-publish (pull_request) Has been skipped
CI / benchmark-regression (pull_request) Has been cancelled
CI / coverage (pull_request) Has been cancelled
CI / status-check (pull_request) Has been cancelled
2026-03-26 01:44:00 +00:00
Luis Mendes 34c2acc354 fix(acms): implement context tier runtime promotion/demotion/eviction
CI / benchmark-publish (pull_request) Has been skipped
CI / lint (pull_request) Successful in 3m18s
CI / typecheck (pull_request) Successful in 4m3s
CI / security (pull_request) Successful in 4m13s
CI / build (pull_request) Successful in 21s
CI / quality (pull_request) Successful in 3m42s
CI / integration_tests (pull_request) Successful in 8m50s
CI / unit_tests (pull_request) Successful in 9m14s
CI / e2e_tests (pull_request) Successful in 9m28s
CI / docker (pull_request) Successful in 1m9s
CI / coverage (pull_request) Successful in 10m24s
CI / status-check (pull_request) Successful in 3s
CI / benchmark-regression (pull_request) Successful in 48m36s
CI / build (push) Successful in 22s
CI / lint (push) Successful in 3m43s
CI / typecheck (push) Successful in 4m19s
CI / benchmark-regression (push) Has been skipped
CI / security (push) Successful in 4m28s
CI / quality (push) Successful in 4m21s
CI / integration_tests (push) Successful in 9m12s
CI / e2e_tests (push) Successful in 9m29s
CI / unit_tests (push) Successful in 9m36s
CI / docker (push) Successful in 1m8s
CI / coverage (push) Successful in 10m33s
CI / status-check (push) Successful in 1s
CI / benchmark-publish (push) Successful in 25m40s
Implement the missing runtime logic for the ACMS context tier service.
Previously only data models and manual promote()/demote()/evict_lru()
methods existed. This commit adds:

- Auto-promotion on access: get() now promotes fragments one tier up
  when access_count reaches the configurable promotion_threshold
  (default: 5 accesses).  The access counter resets after each
  successful promotion so fragments must accumulate fresh accesses
  before the next tier transition.
- Staleness enforcement: new enforce_staleness() method demotes hot
  fragments older than hot_ttl (default: 24h) to warm, and warm
  fragments older than warm_ttl to cold. A snapshot of existing
  warm-tier IDs prevents double-demotion in a single pass.
- Budget enforcement on store and promote: store() and promote()
  now enforce TierBudget.max_tokens_hot by evicting LRU hot-tier
  fragments until the token budget is met.  The eviction loop uses
  incremental token tracking to avoid recomputing the sum.
- Event emission: Added TIER_PROMOTED, TIER_DEMOTED, TIER_EVICTED
  event types to EventType enum. All tier transitions emit
  DomainEvent instances through the optional EventBus.
- Configuration: Added context_tier_promotion_threshold,
  context_tier_hot_ttl_hours, context_tier_warm_ttl_hours settings.
  The warm TTL setting also accepts the spec-defined env var
  CLEVERAGENTS_CTX_WARM_HOURS as an alias.
- DI wiring: container.py now injects event_bus into
  context_tier_service.

Review fixes applied (code review on PR #1150):
- C1: Reset access_count to 0 after each auto-promotion to prevent
  chain promotion that bypassed the warm tier.
- C2: Call _enforce_hot_budget() inside promote() warm-to-hot path
  so auto-promoted fragments respect the token budget.
- H1: Corrected _enforce_hot_budget() docstring: actual complexity
  is O(n + n*k) not O(n), since min() scans remaining entries on
  each eviction.
- M1: Added CLEVERAGENTS_CTX_WARM_HOURS as an additional env var
  alias for context_tier_warm_ttl_hours per specification line 30555.

Review fixes applied (second code review on PR #1150):
- B-CRIT-1: Fixed data loss in promote() warm-to-hot: emit
  TIER_PROMOTED before _enforce_hot_budget(), and if the promoted
  fragment is evicted by budget, restore it to the warm tier instead
  of silently losing it.
- B-HIGH-1: Fixed self-eviction on store(): fragments whose
  token_count exceeds the entire hot-tier budget are now redirected
  to the warm tier with a warning log.
- B-MED-1: Wrapped _emit_tier_event() in try/except so a failing
  event bus does not break tier operations (best-effort emission).
- B-MED-2: Fixed event ordering so TIER_PROMOTED fires before any
  budget-triggered TIER_EVICTED events.
- D-LOW-1: Fixed type hint in Robot helper (dict[str, Callable]).
- D-LOW-2: Added __all__ export to context_tiers.py.
- S-LOW-1: Added thread-safety docstring note to ContextTierService.

Review fixes applied (third code review on PR #1150):
- B-MED-1: Added TIER_DEMOTED event emission for oversized fragment
  redirect in store(), closing the observability gap where the only
  tier transition without event emission was the hot-to-warm redirect
  for fragments exceeding the entire hot-tier budget.
- S-LOW-1: Added CLEVERAGENTS_CTX_HOT_HOURS as an additional env var
  alias for context_tier_hot_ttl_hours, for consistency with the
  warm-tier alias CLEVERAGENTS_CTX_WARM_HOURS.
- S-LOW-2: Added docstring note to enforce_staleness() reconciling
  the hot-tier TTL with the specification statement that hot-tier
  retention is "Until resource removed" (TTL controls tier placement,
  not data retention).

Review fixes applied (fourth code review on PR #1150):
- B-HIGH-1: Reset access_count to 0 on demotion so that demoted
  fragments must accumulate fresh accesses before re-promotion.
  Without this reset, a previously popular fragment whose
  access_count already exceeded the promotion threshold would be
  re-promoted on the very next get() call, making staleness
  enforcement ineffective.

Review fixes applied (freemo APPROVED review on PR #1150):
- #1: Removed all # type: ignore annotations from test files.
  Fixed _EventCollector, _FailingBus, and _NullBus subscribe()
  signatures to use Callable[[DomainEvent], None] matching the
  EventBus protocol.  Replaced dict-spread TieredFragment construction
  with explicit keyword arguments and post-construction assignment.
- #2: Extracted runtime policy logic (enforce_staleness,
  _maybe_auto_promote, _re_fetch_after_promotion, _enforce_hot_budget,
  _emit_tier_event) into TierRuntimeMixin in tier_runtime.py to
  reduce context_tiers.py toward the 500-line guideline.
- #3: Added fragment_id non-empty validation guard to promote() and
  demote() per CONTRIBUTING.md argument validation policy.
- #8: Renamed _resolve to _re_fetch_after_promotion for clarity.

Removed @tdd_expected_fail from TDD tests (Behave + Robot) as the
bug is now fixed. All 3 TDD scenarios pass normally.

Tests: 27 Behave scenarios (24 feature + 3 TDD), 4 Robot integration
tests, 4 ASV benchmark suites.

ISSUES CLOSED: #821
2026-03-25 17:49:06 +00:00
freemo 06130212ed test(e2e): workflow example 5 — database schema migration with safety nets (review profile) (#816)
CI / build (push) Successful in 17s
CI / security (push) Successful in 1m7s
CI / lint (push) Successful in 3m18s
CI / quality (push) Successful in 3m40s
CI / typecheck (push) Successful in 3m48s
CI / benchmark-regression (push) Has been skipped
CI / unit_tests (push) Has started running
CI / docker (push) Blocked by required conditions
CI / status-check (push) Blocked by required conditions
CI / integration_tests (push) Has started running
CI / e2e_tests (push) Has started running
CI / coverage (push) Has started running
CI / benchmark-publish (push) Has started running
## Summary

E2E test for Workflow Example 5 — database schema migration with safety nets using the **review** automation profile. Exercises the full spec-aligned workflow:

- **Custom resource type registration** via `resource type add --config` (postgres-db type with `transaction_rollback` sandbox strategy, `--host`, `--port`, `--database`, `--schema` CLI args with flat `type`/`default` fields per `ResourceTypeArgument` schema)
- **Custom resource instantiation** — attempts `resource add` with the custom type to exercise mixed resource types, followed by `project link-resource` to link DB resource to the project
- **Custom skill creation** with spec-aligned database tools: `local/query_db` (read-only), `local/execute_migration` (writes, checkpointable), `local/backfill_column` (writes, checkpointable) — registered via `skill add --config`, with namespaced tool reference names per `SkillToolRefSchema` validation
- **Action creation** with `automation_profile: review`, `reusable: true`, `state: available`, spec invariants, and typed `arguments` section (`table_name`, `column_name`, `column_type`, `backfill_source` — all required per spec, using `arguments` field per `ActionConfigSchema`)
- **Plan use** with `--arg` flags exercising parameterized action invocation including `backfill_source=audit_log`, plus **explicit `--automation-profile review`** flag (action-to-plan profile propagation is not yet wired in `PlanLifecycleService.use_action`)
- **Phased child plan verification** via `plan tree --format json` with `decision_count >= 2` hard assertion on framework decisions plus WARN tiers for LLM decomposition quality (`< 3`, `< 5`)
- **Plan phase assertion** — hard assertion that phase is populated after execute
- **Checkpoint-based rollback** with hard assertions: `rc=0` on rollback success, `rc!=0` on fake checkpoint, None guard for JSON null checkpoint IDs, re-execute with Traceback/INTERNAL checks on success and explanatory comment on failure path
- **Plan diff** with hard `rc=0` assertion and content-signal verification
- **Migration content verification** — baseline SHA saved before apply, diff against baseline (not `HEAD~1`), WARN-level check on migration keywords (`last_login`, `schema`, `migration`, `column`, `alter`) — flexible per LLM non-determinism
- **Commit count** assertion `>= 2` (fixture baseline: Create Temp Git Repo + DB fixture commit), WARN if no additional commits from lifecycle-apply
- **Backfill evidence** WARN-level check in plan tree/execution output (`backfill`, `batch`, `populate`, `last_login`) with explanatory comment noting tree covers decomposition plan
- **Combined AC #6 gate** — if *both* migration content *and* backfill evidence are absent, explicit WARN visibility for CI debugging
- **Terminal state assertion** after `lifecycle-apply` — `plan status` call verifies phase/processing_state reflects terminal or apply-progress outcome
- **Automation profile fallback verification** — if `plan use` output omits `automation_profile`, falls back to `plan status` for secondary verification (hard assertion always runs)
- **Traceback and INTERNAL checks** on all CLI commands (resource add, project create, resource type add, skill add, action create, plan use, strategize, execute, plan tree, plan status, plan diff, plan rollback, re-execute after rollback, lifecycle-apply) including custom resource error paths
- **Dynamic actor selection** — detects available API keys (Anthropic/OpenAI) at suite setup
- **Skip If No LLM Keys** guard for graceful CI degradation
- **Test-level teardown** with diagnostic logging for both plan status and plan tree on failure
- **30-minute timeout** covering worst-case rollback+re-execute path
- **Force Tags** for consistency with `m6_acceptance.robot`
- **Timeout parameters** (`timeout=60s on_timeout=kill`) on all local `Run Process` git commands
- **Sequential section numbering** (1 through 15) for readability

Closes #751

ISSUES CLOSED: #751

## Approach

Follows the patterns established by `m6_acceptance.robot` and `m2_acceptance.robot`:
- `WF05 Suite Setup` initialises the workspace, generates a unique run suffix, and detects available LLM API keys
- `Safe Parse Json Field` from `common_e2e.resource` for JSON field extraction with None guards for JSON null values
- All CLI commands use `--format json` for predictable, parseable output
- `expected_rc=None` with explicit `Should Be Equal As Integers` for detailed failure messages
- Hard assertions on infrastructure/framework behavior (CLI commands, phase transitions, tool registration)
- WARN-level assertions on LLM-dependent output (decision decomposition, migration content, backfill evidence, commit count) — per ticket requirement "output validation is flexible"
- Traceback and INTERNAL checks on all CLI commands following `m2_acceptance.robot` pattern
- Baseline SHA approach for post-apply diff verification eliminates false positives from fixture commits

## Bug Fix: LifecyclePlanRepository.update() UNIQUE Constraint Violation

**Root cause**: `LifecyclePlanRepository.update()` called `clear()` on child relationship collections (project_links, arguments, invariants) followed by `append()` with new items, but only flushed at the end. SQLAlchemy's default operation ordering can emit INSERTs before DELETEs within the same flush, causing `UNIQUE constraint failed: plan_arguments.plan_id, plan_arguments.name` when plans have arguments.

**Fix**: Group all three `clear()` calls together and flush them before appending new rows. This ensures the DELETEs are committed before any INSERTs, preventing the UNIQUE constraint violation.

**Impact**: This was a latent bug affecting ALL plans with arguments when `update()` is called. Previously undetected because existing E2E tests (M1, M2, M5, M6) create plans without `--arg` flags.

## Review Fixes (addressing medium findings from @CoreRasurae review)

| # | Finding | Fix |
|---|---------|-----|
| **BUG-1** | No regression test for UNIQUE constraint fix | Added targeted BDD scenario in `repositories_coverage_boost.feature` — creates plan with argument `x=v1`, updates to `x=v2`, asserts no `IntegrityError` |
| **TEST-1** | AC #4 weakened — fragile string counting | Replaced raw `count('"decision_id"')` with proper JSON parsing via `json.loads()`, recursive tree walking for decision counting, structural `children_key_count` and `child_link_count` verification |
| **TEST-2** | AC #5 conditionally tested | Added explicit WARN log when no checkpoint_id is present ("AC #5 visibility"); fake checkpoint test now runs unconditionally (moved outside IF/ELSE) with Traceback/INTERNAL checks |
| **TEST-3** | No terminal state assertion after lifecycle-apply | Added `plan status` call after apply with phase/processing_state extraction; hard assertion on terminal state or apply-phase progress |
| **TEST-4** | AC #6 migration/backfill WARN-only | Added combined gate (`has_ac6_evidence`): if *both* migration and backfill evidence are absent, explicit WARN for CI visibility. WARN-only is intentional per ticket AC "output validation is flexible" |
| **TEST-5** | Automation profile silently skipped | Added fallback to `plan status --format json` when `plan use` output omits `automation_profile`; hard assertion (`Should Be Equal As Strings review`) now always executes |
| **TEST-8** | Missing Traceback/INTERNAL on custom resource error paths | Added Traceback/INTERNAL checks inside both `resource add` and `project link-resource` ELSE branches with `NoSuchOption` guard |

## Quality Gates

- `nox -e lint` 
- `nox -e typecheck`  (0 errors)
- `nox -e unit_tests`  (471 features, 12,422 scenarios, 0 failures)
- `nox -e integration_tests`  (1,727 tests, 0 failures)
- `nox -e e2e_tests`  (42 tests, 42 passed, 0 failed)
- `nox -e coverage_report`  (98%, meets threshold)

## Manual Verification

### Prerequisites
- `OPENAI_API_KEY` or `ANTHROPIC_API_KEY` environment variable set

### Commands

```bash
nox -e e2e_tests
# Or run just this suite:
python -m robot --outputdir build/reports/robot --include E2E robot/e2e/wf05_db_migration.robot
```

Reviewed-on: #816
Reviewed-by: Luis Mendes <luis.mendes@cleverthis.com>
Co-authored-by: Jeffrey Phillips Freeman <the@jeffreyfreeman.me>
Co-committed-by: Jeffrey Phillips Freeman <the@jeffreyfreeman.me>
2026-03-25 13:05:04 +00:00
aditya 2aa2bb6a43 fix(e2e): disable git commit signing in temp test repos
CI / benchmark-publish (pull_request) Has been skipped
CI / build (pull_request) Successful in 24s
CI / lint (pull_request) Successful in 3m30s
CI / typecheck (pull_request) Successful in 4m0s
CI / quality (pull_request) Successful in 3m37s
CI / security (pull_request) Successful in 4m22s
CI / integration_tests (pull_request) Successful in 7m14s
CI / e2e_tests (pull_request) Successful in 10m12s
CI / coverage (pull_request) Successful in 10m11s
CI / unit_tests (pull_request) Successful in 5m51s
CI / docker (pull_request) Successful in 1m7s
CI / status-check (pull_request) Successful in 1s
CI / benchmark-regression (pull_request) Has been cancelled
2026-03-25 12:05:40 +00:00
hurui200320 83c22b8391 test(e2e): TDD behavioral test proving ACMS indexing pipeline is not wired into CLI (bug #1028) (#1124)
CI / build (push) Successful in 19s
CI / lint (push) Successful in 3m18s
CI / typecheck (push) Successful in 3m47s
CI / quality (push) Successful in 3m58s
CI / benchmark-regression (push) Has been skipped
CI / security (push) Successful in 4m17s
CI / integration_tests (push) Successful in 6m44s
CI / unit_tests (push) Successful in 6m53s
CI / docker (push) Successful in 56s
CI / e2e_tests (push) Successful in 9m4s
CI / coverage (push) Successful in 10m43s
CI / status-check (push) Successful in 2s
CI / benchmark-publish (push) Successful in 26m37s
## Summary

This PR adds a Robot Framework E2E test suite (`robot/e2e/tdd_acms_behavioral_validation.robot`) that proves bug #1028 exists — the ACMS indexing pipeline is not wired into the CLI, so `ContextTierService` starts empty on every invocation.

### Changes

- **New file**: `robot/e2e/tdd_acms_behavioral_validation.robot` — 4 E2E test cases tagged `tdd_expected_fail`, `tdd_bug`, `tdd_bug_1028`, `E2E`
- **Modified**: `robot/e2e/common_e2e.resource` — Extracted shared keywords (`Run CLI`, `Extract JSON From Stdout`, `Link Resource To Project`, `Create Synthetic Codebase`) from both `m5_acceptance.robot` and `tdd_acms_behavioral_validation.robot` to eliminate ~97 lines of duplication. `Create Synthetic Codebase` is parameterized with `project_label`.
- **Modified**: `robot/e2e/m5_acceptance.robot` — Removed duplicated keywords now provided by `common_e2e.resource`.
- **CHANGELOG.md**: Added entry under `## Unreleased` documenting the TDD tests for #1029.

### Test Cases

- **Test 1**: Context Simulate Returns Non-Empty Tier Data — asserts `fragment_count > 0` (fails, proving bug)
- **Test 2**: Context Inspect Shows Indexed Resources — asserts tier metrics total > 0 (fails, proving bug)
- **Test 3**: Budget Enforcement Excludes Oversized Files — asserts `fragment_count > 0` with `max_file_size` policy (fails, proving bug). Includes TODO comment for post-fix exclusion assertion.
- **Test 4**: Large Project Indexes Without Timeout — generates 10K+ files, asserts `fragment_count > 0` (fails, proving bug). Includes explicit developer responsibility note about git-tracking of generated files.

All tests pass CI through result inversion by the `tdd_expected_fail_listener.py` — failing assertions (bug confirmed) are inverted to PASS.

### Documentation & Robustness Improvements

- Suite-level documentation expanded with **known limitation** section explaining `tdd_expected_fail` result inversion scope.
- Suite setup error messages include `(rc=${var.rc}). Check DEBUG logs above.` for debugging consistency with `m5_acceptance.robot`.
- Redundant exit code assertions after `Run CLI` calls removed (Run CLI already validates rc internally).
- `Run CLI` keyword documentation includes API key security notes.
- Budget enforcement test (Test 3) includes `TODO(bugfix/...)` comment for the bug-fix developer.
- Large project test (Test 4) includes explicit NOTE assigning responsibility to the bug-fix developer to evaluate filesystem vs. git-tracked content indexing.

### Review Fix Round

Addressed all findings from Luis's review (review #2691):
- **C1 (CRITICAL)**: Restored the #845 `CorrectionService` changelog entry (50 lines) accidentally deleted during merge conflict resolution.
- **L1 (LOW)**: Extracted ~97 lines of duplicated keywords into `common_e2e.resource` (parameterized `Create Synthetic Codebase`, shared `Run CLI`, `Extract JSON From Stdout`, `Link Resource To Project`).
- **M1 (MEDIUM)**: Strengthened NOTE comment about 10K files not being git-committed — explicit developer MUST responsibility.
- **L3 (LOW)**: Made suite setup error messages verbose with `(rc=...). Check DEBUG logs above.`
- **L2 (LOW)**: Removed redundant exit code assertions after `Run CLI` calls.
- **M2 (MEDIUM)**: Acknowledged — partial assertion is acceptable for TDD capture phase (TODO documents the gap).
- **I1 (INFO)**: Acknowledged — `tdd_expected_fail` masking is documented and mitigated.

### Motivation

Per the Bug Fix Workflow in CONTRIBUTING.md, this TDD issue (#1029) is the prerequisite for bug fix #1028. The tests capture the buggy behavior so that when the fix is implemented, removing the `tdd_expected_fail` tag will cause the tests to pass normally.

### Quality Gates

| Gate | Result |
|------|--------|
| lint | PASS |
| typecheck | PASS |
| unit_tests | PASS |
| integration_tests | PASS |
| e2e_tests | PASS (41 tests, 4 TDD) |
| coverage_report | PASS (>=97%) |

Closes #1029

Reviewed-on: #1124
Reviewed-by: Jeffrey Phillips Freeman <jeffrey.freeman@cleverthis.com>
Co-authored-by: Rui Hu <rui.hu@cleverthis.com>
Co-committed-by: Rui Hu <rui.hu@cleverthis.com>
2026-03-25 11:13:37 +00:00
Luis Mendes 3cf3f1f69e feat(validation): implement Fix-then-Revalidate orchestration loop for required validations
CI / benchmark-publish (pull_request) Has been skipped
CI / build (pull_request) Successful in 15s
CI / lint (pull_request) Successful in 3m40s
CI / quality (pull_request) Successful in 4m13s
CI / security (pull_request) Successful in 4m16s
CI / typecheck (pull_request) Successful in 4m16s
CI / integration_tests (pull_request) Successful in 9m11s
CI / unit_tests (pull_request) Successful in 9m23s
CI / docker (pull_request) Successful in 1m18s
CI / coverage (pull_request) Successful in 11m48s
CI / status-check (pull_request) Successful in 7s
CI / e2e_tests (pull_request) Successful in 8m24s
CI / lint (push) Successful in 3m18s
CI / build (push) Failing after 13s
CI / typecheck (push) Successful in 3m54s
CI / benchmark-regression (push) Has been skipped
CI / quality (push) Successful in 4m15s
CI / security (push) Successful in 4m39s
CI / integration_tests (push) Successful in 7m21s
CI / unit_tests (push) Successful in 7m44s
CI / docker (push) Successful in 1m9s
CI / e2e_tests (push) Successful in 11m9s
CI / coverage (push) Successful in 13m41s
CI / status-check (push) Successful in 2s
CI / benchmark-regression (pull_request) Successful in 48m49s
CI / benchmark-publish (push) Successful in 26m25s
Implemented FixThenRevalidateOrchestrator with full diagnosis → self-fix →
re-validation → retry limit → strategy revision → user escalation → terminal
failure flow. Added retry counting per validation per plan, configurable retry
limit (default 3), auto_strategy_revision flag support, and validation_fix_history
recording in plan execution metadata.

Review fixes applied (round 1):
- Added try/except around fix_callback and revalidate_callback (spec: validation
  errors treated as required failure regardless of mode)
- Wired optional EventBus for VALIDATION_FIX_ATTEMPTED/SUCCEEDED/EXHAUSTED events
- Fixed total_attempts derivation from fix_history length instead of cumulative
  retry counts
- Updated module docstring to reflect implemented vs caller-responsible steps
- Added exhausted-retry logging on re-invocation
- Replaced bare assert in Robot helper with explicit _check() function
- Added 10 new Behave scenarios covering exception paths, multi-failure, reset,
  field validation, boundary values, event_bus property, and exhausted re-invocation

Review fixes applied (round 2 — PR #711):
- B1+B7: Fixed TOCTOU race in _fix_single_validation; atomic claim-per-iteration
  under RLock; eliminated defaultdict auto-vivification with .get() reads
- B2: Added validation_name mismatch check on revalidate_callback return
- B3: Added fix_description truncation to 2000 chars before FixAttemptRecord
- T1: Switched threading.Lock to threading.RLock for defensive reentrancy
- A1: Added model_validator preventing escalated+terminal_failure both True
- R1: Added max_length=255 to FixAttemptRecord.validation_name
- S7: Fixed misleading docstring about automation_profile integration
- D4: Fixed timestamp field description to specify UTC
- D1: Renamed misleading benchmark time_fix_after_two_retries
- Added 5 new Behave scenarios for truncation, model constraints, name mismatch

ISSUES CLOSED: #583
2026-03-24 22:01:48 +00:00
freemo e52c79e958 test: add TDD bug-capture test for #1024 — SQLite DB URL CWD resolution
CI / benchmark-publish (pull_request) Has been skipped
CI / build (pull_request) Successful in 23s
CI / lint (pull_request) Successful in 3m19s
CI / typecheck (pull_request) Successful in 4m3s
CI / quality (pull_request) Successful in 4m3s
CI / security (pull_request) Successful in 4m3s
CI / integration_tests (pull_request) Successful in 6m26s
CI / unit_tests (pull_request) Successful in 7m57s
CI / e2e_tests (pull_request) Successful in 8m23s
CI / docker (pull_request) Successful in 1m8s
CI / coverage (pull_request) Successful in 11m22s
CI / status-check (pull_request) Successful in 1s
CI / build (push) Successful in 19s
CI / lint (push) Successful in 3m17s
CI / quality (push) Successful in 3m44s
CI / typecheck (push) Successful in 3m53s
CI / security (push) Successful in 3m54s
CI / benchmark-regression (push) Has been skipped
CI / integration_tests (push) Successful in 5m53s
CI / unit_tests (push) Successful in 6m59s
CI / docker (push) Successful in 1m2s
CI / e2e_tests (push) Successful in 8m42s
CI / coverage (push) Successful in 9m53s
CI / status-check (push) Successful in 3s
CI / benchmark-publish (push) Successful in 26m34s
CI / benchmark-regression (pull_request) Successful in 55m26s
Add Behave BDD scenarios (tagged @tdd_bug @tdd_bug_1024 @tdd_expected_fail)
that verify the default database_url resolves inside CLEVERAGENTS_HOME rather
than the current working directory.  Two scenarios exercise both the container
get_database_url() helper and the Settings model default.

Add Robot Framework integration tests with a helper script exercising the same
resolution paths via subprocess, verifying database URL resolution and CLI
database file placement relative to CLEVERAGENTS_HOME.

The tests currently fail as expected because the bug in #1024 is still present:
the relative SQLite path sqlite:///cleveragents.db resolves against CWD.  The
@tdd_expected_fail tag inverts the result so CI passes.

ISSUES CLOSED: #1034
2026-03-24 20:29:49 +00:00
freemo 93da31e80f fix(skill): resolve skill add persistence regression after PR #640
CI / build (pull_request) Successful in 25s
CI / benchmark-publish (pull_request) Has been skipped
CI / lint (pull_request) Successful in 3m46s
CI / quality (pull_request) Successful in 4m9s
CI / security (pull_request) Successful in 4m13s
CI / typecheck (pull_request) Successful in 4m23s
CI / unit_tests (pull_request) Successful in 6m31s
CI / integration_tests (pull_request) Successful in 7m8s
CI / docker (pull_request) Successful in 1m14s
CI / e2e_tests (pull_request) Successful in 8m28s
CI / coverage (pull_request) Successful in 10m19s
CI / status-check (pull_request) Successful in 1s
CI / build (push) Successful in 24s
CI / lint (push) Successful in 3m36s
CI / quality (push) Successful in 3m41s
CI / typecheck (push) Successful in 3m56s
CI / benchmark-regression (push) Has been skipped
CI / security (push) Successful in 4m4s
CI / integration_tests (push) Successful in 7m1s
CI / coverage (push) Failing after 12m22s
CI / e2e_tests (push) Failing after 16m19s
CI / unit_tests (push) Successful in 18m40s
CI / docker (push) Successful in 57s
CI / status-check (push) Failing after 3s
CI / benchmark-publish (push) Successful in 28m38s
CI / benchmark-regression (pull_request) Successful in 52m22s
Root cause: _build_skill_service in container.py created a SkillRepository
pointing at the database but did not ensure the skills/skill_items tables
existed. When the tables were missing, SkillRepository.list_all() and
create() failed silently (caught by SkillService._load_from_db and
_persist_skill exception handlers), causing the service to operate in
in-memory-only mode. Skills added in one CLI process were lost when a
new process created a fresh SkillService.

Additionally, SkillRepository lacked auto_commit support. Each call to
session_factory() returned a new session, so the flush in create/update/
delete operated on a different session than the commit in
SkillService._commit(), meaning data was never actually persisted even
when the tables existed.

Fix:
1. Add targeted table creation in _build_skill_service (following the
   pattern in _build_session_service) — checks for missing skills and
   skill_items tables and creates them via Base.metadata.create_all.
2. Add auto_commit parameter to SkillRepository (following the pattern
   in SessionRepository) so each mutating method commits and closes its
   own session.
3. Pass auto_commit=True from the container builder.
4. Remove @tdd_expected_fail from TDD test (leaving @tdd_bug and
   @tdd_bug_980 as permanent regression guards).

ISSUES CLOSED: #980
2026-03-24 17:08:22 +00:00
freemo a6e2bc7842 test: add TDD bug-capture test for #980 — skill add cross-process persistence
Write cross-process Behave and Robot tests capturing skill add
persistence regression. Tests use subprocess invocations to verify
skills persist across CLI process boundaries.

The existing persistence tests (skill_add_persist.feature) verify
round-trip within the same Python process by creating two SkillService
instances sharing the same in-memory database. This approach cannot
detect the cross-process regression where _build_skill_service falls
back to in-memory storage because the skills table does not exist in
the database created by agents init.

Behave: features/tdd_skill_add_regression.feature
Robot:  robot/tdd_skill_add_regression.robot

Tags: @tdd_bug, @tdd_bug_980, @tdd_expected_fail

ISSUES CLOSED: #981
2026-03-24 17:08:22 +00:00
hamza.khyari 90e5bbb99c feat(resource): implement ResourceHandler CRUD and discovery methods
CI / benchmark-publish (pull_request) Has been skipped
CI / build (pull_request) Successful in 17s
CI / lint (pull_request) Successful in 3m17s
CI / unit_tests (pull_request) Successful in 3m38s
CI / quality (pull_request) Successful in 3m42s
CI / typecheck (pull_request) Successful in 3m54s
CI / security (pull_request) Successful in 4m2s
CI / docker (pull_request) Successful in 50s
CI / e2e_tests (pull_request) Successful in 8m32s
CI / integration_tests (pull_request) Successful in 6m54s
CI / coverage (pull_request) Successful in 14m10s
CI / status-check (pull_request) Successful in 1s
CI / benchmark-regression (pull_request) Successful in 59m15s
Extend the ResourceHandler protocol with six content operations (read,
write, delete, list_children, diff, discover_children) and four frozen
dataclass result types (Content, WriteResult, DeleteResult, DiffResult).

Handler implementations:
- GitCheckoutHandler: read via git show (binary-safe), write/delete via
  filesystem ops, list via git ls-tree, diff via git diff --no-index
  with locale-safe shortstat parsing, discover via git ls-tree -d
- FsDirectoryHandler: full CRUD via pathlib/os/difflib/shutil
- DevcontainerHandler: read/write/discover via devcontainer exec
- CloudResourceHandler: NotImplementedError stubs for protocol compliance
- DatabaseResourceHandler: inherits base NotImplementedError stubs

Security:
- Path traversal guard (_safe_resolve) on all read/write/delete ops
  using os.sep-suffixed startswith check to prevent prefix collisions
- Empty-path deletion rejected with PermissionError

Tests:
- 22 Behave scenarios (115 steps): CRUD for FsDirectory and GitCheckout,
  path traversal rejection (3 scenarios), NotImplementedError defaults
- 2 Robot integration tests: read -> write -> diff cycle on real temp
  directories and git repos

ISSUES CLOSED: #827
2026-03-24 13:53:41 +00:00
hamza.khyari 65a2e4db76 feat(resource): add LSP resource types
CI / benchmark-publish (pull_request) Has been skipped
CI / build (pull_request) Successful in 21s
CI / lint (pull_request) Successful in 3m18s
CI / quality (pull_request) Successful in 3m46s
CI / typecheck (pull_request) Successful in 3m54s
CI / security (pull_request) Successful in 4m3s
CI / unit_tests (pull_request) Successful in 5m57s
CI / integration_tests (pull_request) Successful in 6m45s
CI / docker (pull_request) Successful in 56s
CI / e2e_tests (pull_request) Successful in 8m29s
CI / coverage (pull_request) Successful in 11m12s
CI / status-check (pull_request) Successful in 1s
CI / benchmark-regression (pull_request) Failing after 52m33s
Add 4 LSP-related built-in resource types to the resource registry:

- executable: system binary/interpreter/LSP server binary with
  auto-discovery from container-exec-env and fs-directory (lazy)
- lsp-server: LSP server definition with command, language-ids,
  transport, args, port, initialization-options config;
  children: lsp-workspace
- lsp-workspace: workspace root tracked by LSP server, auto-discovered
  from lsp-server; children: lsp-document; not user-addable
- lsp-document: text document tracked by LSP server, auto-discovered
  from lsp-workspace; read+write capabilities; not user-addable

Type definitions extracted to _resource_registry_lsp.py for consistency
with existing type modules. Parent/child hierarchy: lsp-server ->
lsp-workspace -> lsp-document. YAML configs with ADR references
(ADR-039, ADR-040). All 7 lsp-server CLI args per ADR-040.

Behave tests (21 scenarios): YAML loading, user-addable flags,
capabilities, parent/child hierarchy, auto-discovery for all 3
discoverable types, BUILTIN_NAMES, DB bootstrap roundtrip, negative
tests for manual registration rejection.

Robot tests (6 tests): import, BUILTIN_NAMES, DB roundtrip, hierarchy,
auto-discovery, user-addable guard.

ISSUES CLOSED: #832
2026-03-24 13:21:12 +00:00
hamza.khyari 4ff075e0da feat(lsp): implement functional LSP runtime
CI / benchmark-publish (pull_request) Has been skipped
CI / build (pull_request) Successful in 18s
CI / quality (pull_request) Successful in 32s
CI / typecheck (pull_request) Successful in 56s
CI / security (pull_request) Successful in 57s
CI / lint (pull_request) Successful in 3m19s
CI / integration_tests (pull_request) Successful in 3m44s
CI / unit_tests (pull_request) Successful in 6m39s
CI / docker (pull_request) Successful in 1m9s
CI / e2e_tests (pull_request) Successful in 9m38s
CI / coverage (pull_request) Successful in 11m19s
CI / status-check (pull_request) Successful in 1s
CI / benchmark-regression (pull_request) Failing after 1h13m38s
Replace local-mode stubs with real LSP protocol support:

- StdioTransport: subprocess management with JSON-RPC framing
- LspClient: LSP protocol (initialize/shutdown/diagnostics/completions)
- LspLifecycleManager: reference-counted instances, health checks, crash restart
- LspRuntime: registry-based server lookup, auto-restart on crash
- LspToolAdapter: runtime-delegating handlers with local-mode fallback
- LanguageDiscovery: 4-layer detection (extension, shebang, UKO, project)
- activate_bindings/deactivate_bindings: actor compiler LSP binding wiring

Tests: 27 Behave scenarios, 6 Robot integration tests, 250 existing pass.

ISSUES CLOSED: #826
2026-03-24 13:01:12 +00:00
aditya 36c36bc0ee test(cli): add regression-guard tests for Container.resolve() crash
CI / benchmark-publish (pull_request) Has been skipped
CI / build (pull_request) Successful in 18s
CI / lint (pull_request) Successful in 3m19s
CI / quality (pull_request) Successful in 3m41s
CI / typecheck (pull_request) Successful in 3m54s
CI / security (pull_request) Successful in 4m2s
CI / integration_tests (pull_request) Successful in 6m41s
CI / unit_tests (pull_request) Successful in 6m49s
CI / docker (pull_request) Successful in 1m9s
CI / e2e_tests (pull_request) Successful in 9m19s
CI / coverage (pull_request) Successful in 11m17s
CI / status-check (pull_request) Successful in 1s
CI / benchmark-regression (pull_request) Successful in 50m38s
Add Behave and Robot Framework regression tests for bug #647, where
plan tree, plan explain, and plan correct CLI commands crashed with
AttributeError when resolving DecisionService from the DI container.

Tests use a real DI container with seeded decisions (not MagicMock)
to catch the exact class of bug that existing M3 tests missed.
Assertions verify successful execution and command-specific output
content. Includes Settings.reset() classmethod for robust singleton
cleanup in test teardown.

Review feedback addressed (hurui200320 Round 5):
- Fixed Behave step engine leak by capturing UoW in cleanup closure
- Removed dead @then decorator; renamed to private _assert_command_succeeded
- Strengthened plan correct assertions with revert/dry-run content checks
- Updated misleading get_container() comment to reflect singleton warming
- Added test-only warning to Settings.reset() docstring
- Added type annotations to 4 settings step functions
- Fixed CONTRIBUTORS.md alphabetical ordering and removed duplicate entry
- Replaced glob.glob with pathlib suffix iteration in Robot helper
- Fixed feature description line break for readability
- Removed redundant TYPE_CHECKING import for Decision

ISSUES CLOSED: #648
2026-03-24 08:46:58 +00:00
Luis Mendes 9e316b1a3e fix(domain): align plan lifecycle model validation with specification
CI / build (pull_request) Successful in 22s
CI / typecheck (pull_request) Successful in 47s
CI / lint (pull_request) Successful in 3m17s
CI / quality (pull_request) Successful in 3m33s
CI / security (pull_request) Successful in 3m59s
CI / unit_tests (pull_request) Successful in 5m31s
CI / docker (pull_request) Successful in 57s
CI / coverage (pull_request) Successful in 12m32s
CI / status-check (pull_request) Successful in 1s
CI / integration_tests (pull_request) Successful in 2m25s
CI / e2e_tests (pull_request) Successful in 7m9s
CI / benchmark-publish (pull_request) Has been skipped
CI / build (push) Successful in 26s
CI / lint (push) Successful in 3m18s
CI / typecheck (push) Successful in 3m54s
CI / security (push) Successful in 4m2s
CI / quality (push) Successful in 3m33s
CI / integration_tests (push) Successful in 5m47s
CI / unit_tests (push) Successful in 7m6s
CI / docker (push) Successful in 39s
CI / benchmark-regression (pull_request) Failing after 21m11s
CI / coverage (push) Failing after 19m3s
CI / benchmark-regression (push) Has been skipped
CI / e2e_tests (push) Failing after 21m14s
CI / status-check (push) Failing after 1s
CI / benchmark-publish (push) Failing after 18m51s
Aligned the plan lifecycle model with the specification:

1. ERRORED is now treated as terminal in is_terminal property,
   matching the spec table where errored is marked "Terminal? Yes"
   for all processing phases.

2. Added per-phase state validation via model_validator: APPLIED
   and CONSTRAINED are only valid in APPLY phase; COMPLETE is only
   valid in STRATEGIZE or EXECUTE phases. Invalid combinations
   now raise ValueError at construction time.

3. Updated ProcessingState.COMPLETE docstring to clarify phase-level
   terminality semantics.

4. Fixed assignment ordering in execute_plan() to set
   processing_state before phase, consistent with the state-first
   pattern used in apply_plan() and _perform_reversion().

5. Added defensive coercion in LifecyclePlanModel.to_domain() to
   handle legacy DB rows with invalid phase/state combinations
   (e.g. APPLY/COMPLETE -> APPLY/APPLIED) with warning-level
   logging for observability.

6. Updated module docstrings: ERRORED description now reflects
   terminal semantics, terminal outcomes location clarified for
   all phases, can_revert_to docstring notes ERRORED/CONSTRAINED
   are terminal but revertable, is_terminal docstring explains
   the distinction between terminal and permanently irrecoverable
   and documents why COMPLETE is not plan-terminal despite the
   spec marking it "Terminal? Yes" (phase-level vs plan-level).

7. Updated PlanResumeService.validate_eligibility() docstring to
   reflect that ERRORED is now terminal but still eligible for
   resume.

8. Added CHANGELOG entry.

ISSUES CLOSED: #918
2026-03-23 23:33:33 +00:00
Luis Mendes 1ffb0fddbe feat(plan): decision correction recomputes only affected subtree
CI / benchmark-publish (pull_request) Has been skipped
CI / build (pull_request) Successful in 21s
CI / lint (pull_request) Successful in 3m18s
CI / typecheck (pull_request) Successful in 4m11s
CI / security (pull_request) Successful in 4m13s
CI / integration_tests (pull_request) Successful in 5m56s
CI / coverage (pull_request) Successful in 10m2s
CI / quality (pull_request) Successful in 3m40s
CI / unit_tests (pull_request) Successful in 6m6s
CI / docker (pull_request) Successful in 1m2s
CI / status-check (pull_request) Successful in 1s
CI / e2e_tests (pull_request) Successful in 8m19s
CI / build (push) Successful in 14s
CI / lint (push) Successful in 3m35s
CI / typecheck (push) Successful in 3m53s
CI / benchmark-regression (push) Has been skipped
CI / integration_tests (push) Successful in 5m54s
CI / unit_tests (push) Successful in 7m17s
CI / e2e_tests (push) Successful in 9m39s
CI / coverage (push) Successful in 11m22s
CI / benchmark-regression (pull_request) Successful in 58m8s
CI / benchmark-publish (push) Successful in 32m8s
CI / quality (push) Successful in 3m29s
CI / security (push) Successful in 3m40s
CI / docker (push) Successful in 51s
CI / status-check (push) Successful in 1s
Enhanced the CorrectionService to properly isolate correction scope:

1. analyze_impact() now populates excluded_decisions by computing
   the set difference between all plan decisions and the affected
   subtree, ensuring root and sibling decisions are tracked.

2. Added rollback_tier computation that counts parent hops from
   the target decision to the root, enabling depth-aware rollback
   strategies (tier 0 = root targeted, tier N = N levels deep).

3. Enhanced dry-run report with excluded decisions list, rollback
   tier, and tier-0 warning when entire tree is affected.

4. Added subtree isolation validation confirming root exclusion
   and sibling non-contamination for non-root corrections.

5. Fixed status state-machine regression in execute_revert() where
   analyze_impact() overwrote status back to ANALYZING from EXECUTING.
   Guard now only transitions to ANALYZING when status is PENDING.
   execute_revert() now transitions through ANALYZING before EXECUTING
   for correct lifecycle ordering.

6. Fixed validate_subtree_isolation() to use structural-only BFS for
   the sibling invariant check, so that influence-DAG-caused sibling
   reachability is not misreported as an isolation violation (per spec
   § Affected Subtree Computation).

7. Fixed false-positive cycle-detection warnings from convergent
   (diamond) topologies by replacing per-node seen_this_round with a
   global enqueued set in BFS, preventing duplicate queue insertions
   from different parents.

8. Added dry_run enforcement guard in _assert_executable() to prevent
   execution of dry-run-only corrections per spec (§ plan correct
   --dry-run: "Show impact without executing").

9. Fixed generate_dry_run_report() to preserve request status so that
   generating a preview does not advance the correction lifecycle
   (dry-run is non-mutating per spec).  Status restoration now uses
   try/finally to guarantee recovery even when analyze_impact() raises
   after transitioning the status.

10. Improved cycle-detection log message accuracy to cover both
    structural tree and influence DAG sources.

11. Extracted cost/time estimation constants (_COST_PER_DECISION,
    _RECOMPUTE_SECONDS_PER_DECISION) from magic numbers.

12. Added terminal-state guard in analyze_impact() to reject
    re-analysis after execution (APPLIED/FAILED/CANCELLED/REJECTED),
    preventing audit-data corruption.  Promoted terminal-status set
    to a module-level _TERMINAL_STATUSES frozenset constant.

13. Added mode validation in execute_revert()/execute_append() to
    prevent mode-mismatched execution (e.g. calling execute_revert
    on an APPEND correction).

14. Fixed _collect_all_decisions() to always include the target
    decision in the universe, preventing broken partition invariant
    for isolated single-node plans.

15. Fixed tier-0 dry-run warning to only trigger when the target
    is genuinely in the structural tree (avoiding false warnings for
    nodes not present in the tree).

16. Removed duplicate as_cli_dict regression scenarios in
    resource_type_deferred_physical.feature.

ISSUES CLOSED: #845
2026-03-23 18:41:53 +00:00
brent.edwards 34c6972a05 feat(tool): implement BuiltinAdapter class and MCP automatic resource slot creation (#964)
CI / build (push) Successful in 18s
CI / lint (push) Successful in 3m20s
CI / typecheck (push) Successful in 3m56s
CI / benchmark-regression (push) Has been skipped
CI / security (push) Successful in 4m1s
CI / quality (push) Successful in 4m8s
CI / unit_tests (push) Successful in 6m40s
CI / integration_tests (push) Successful in 6m40s
CI / docker (push) Successful in 1m19s
CI / e2e_tests (push) Failing after 17m17s
CI / coverage (push) Failing after 18m20s
CI / benchmark-publish (push) Successful in 31m37s
CI / status-check (push) Failing after 1s
## Summary

Implement `BuiltinAdapter` class and MCP automatic resource slot creation. Two main changes:

### 1. BuiltinAdapter Class (`tool/builtins/adapter.py`)
Formal adapter implementing the tool adapter lifecycle pattern for built-in tools:
- `discover()` — returns all built-in tool descriptors (file, git, subplan tools)
- `register(registry)` — registers all tools in a ToolRegistry, returns registered names
- `activate()`/`deactivate()` — no-ops (built-in tools are always available)
- Wraps existing `ALL_FILE_TOOLS`, `ALL_GIT_TOOLS`, `ALL_SUBPLAN_TOOLS` lists
- Backward compatible — existing registration functions still work

### 2. MCP Resource Slot Inference (`mcp/adapter.py`)
New `infer_resource_slots()` static method on `MCPToolAdapter`:
- Scans MCP tool parameter schemas for file/directory/repo patterns
- Creates `ResourceSlot` objects with appropriate type, access mode, binding mode
- Mapping: `file_path`→file(rw), `directory`→directory(ro), `repo_path`→git-checkout(rw)
- Slots stored in `source_metadata["resource_slots"]` on registered `ToolSpec` objects

### Quality Gates

| Session | Result |
|---|---|
| `nox -s lint` | PASS |
| `nox -s typecheck` | PASS (0 errors) |
| `nox -s unit_tests` | PASS (10,817 scenarios) |
| `nox -s integration_tests` | PASS (6 new tests) |
| `nox -s coverage_report` | 97% (>= 97%) |

Closes #882

Reviewed-on: #964
Co-authored-by: Brent E. Edwards <brent.edwards@cleverthis.com>
Co-committed-by: Brent E. Edwards <brent.edwards@cleverthis.com>
2026-03-21 05:30:01 +00:00
brent.edwards b88bc0ec1b feat(perf): large project scaling tests (#984)
CI / build (push) Successful in 19s
CI / lint (push) Successful in 3m19s
CI / quality (push) Successful in 3m43s
CI / typecheck (push) Successful in 3m55s
CI / security (push) Successful in 4m2s
CI / unit_tests (push) Successful in 6m39s
CI / integration_tests (push) Successful in 6m48s
CI / docker (push) Successful in 1m7s
CI / e2e_tests (push) Successful in 9m7s
CI / benchmark-regression (push) Has been skipped
CI / coverage (push) Failing after 16m36s
CI / benchmark-publish (push) Successful in 25m51s
CI / status-check (push) Failing after 4s
## Summary

Add large project scaling benchmarks and tests at production scale (10K–100K files).

### New ASV Benchmarks

**IndexingScalingSuite** (`large_project_scaling_bench.py`):
- `time_walk_and_index` at 1K/10K/50K/100K files
- `time_incremental_refresh` (1% modified files)
- `track_indexed_file_count`, `track_tokens_per_second`

**ContextAssemblyScalingSuite** (`context_assembly_scaling_bench.py`):
- `time_full_pipeline` at 100/1K/5K/10K fragments
- `time_tiered_strategy`, `time_recency_strategy`
- `track_assembled_tokens`, `track_fragments_per_second`

**ExecutionThroughputSuite** (`execution_throughput_bench.py`):
- `time_sequential_plans` at 10/50/100 plans
- `time_executor_construction`, `time_decision_tree_scaling`

### Scale Fixture Updates

- Added `xlarge` (50K files) and `xxlarge` (100K files) profiles to `scale_metadata.json`
- Added 50K/100K thresholds to `baseline_thresholds.json`
- Added `context_assembly` and `execution_throughput` threshold sections

### Tests & Documentation

- 15 Behave scenarios validating profiles, thresholds, monotonicity, memory budgets
- 6 Robot integration tests including live 1K-file indexing throughput check
- `docs/reference/scaling_baselines.md` documenting all baseline metrics

### Quality Gates

| Session | Result |
|---|---|
| `nox -s lint` | PASS |
| `nox -s typecheck` | PASS (0 errors) |
| `nox -s unit_tests` | PASS (10,910 scenarios) |
| `nox -s integration_tests` | PASS (1,526 tests) |
| `nox -s coverage_report` | 97% (>= 97%) |

Closes #859

Reviewed-on: #984
Co-authored-by: Brent E. Edwards <brent.edwards@cleverthis.com>
Co-committed-by: Brent E. Edwards <brent.edwards@cleverthis.com>
2026-03-21 04:46:45 +00:00
brent.edwards 8a87262f86 feat(sandbox): implement overlay filesystem sandbox strategy (#994)
CI / build (push) Successful in 17s
CI / lint (push) Successful in 3m41s
CI / quality (push) Successful in 3m47s
CI / unit_tests (push) Successful in 3m58s
CI / typecheck (push) Successful in 4m17s
CI / benchmark-regression (push) Has been skipped
CI / security (push) Successful in 4m22s
CI / docker (push) Successful in 1m22s
CI / e2e_tests (push) Successful in 8m57s
CI / coverage (push) Successful in 11m16s
CI / status-check (push) Successful in 3s
CI / benchmark-publish (push) Successful in 19m45s
CI / integration_tests (push) Failing after 20m53s
## Summary

Implement the overlay filesystem sandbox strategy with OverlayFS support and userspace fallback.

### Implementation

**`OverlaySandbox`** (`infrastructure/sandbox/overlay.py`, 497 lines):
- Detects OverlayFS availability at runtime via `/proc/filesystems` + `os.geteuid() == 0` check
- **Real OverlayFS mode** (requires root): creates upper/work/merged dirs, mounts overlay filesystem, captures writes in upper layer
- **Userspace fallback** (default in CI/containers): `shutil.copytree` the original into merged dir, tracks changes via `filecmp` diff on commit
- `create()`: sets up directory structure, mounts if available
- `commit()`: copies changed/added files from overlay to original, removes deleted files
- `rollback()`: unmounts (or removes) merged, recreates from scratch
- `cleanup()`: unmounts, removes all temp dirs, idempotent

### Domain Model Updates
- Added `OVERLAY = "overlay"` to `SandboxStrategy` enum in both `resource_type.py` and `resource.py`
- Added `STRATEGY_OVERLAY` to `SandboxFactory`, registered for `fs-mount`, `fs-directory`, `fs-file` resources

### Tests
- **22 Behave scenarios**: full lifecycle (create/commit/rollback/cleanup), status transitions, path traversal guard, fallback detection, error handling
- **6 Robot integration tests**: end-to-end overlay sandbox operations

### Quality Gates

| Session | Result |
|---|---|
| `nox -s lint` | PASS |
| `nox -s typecheck` | PASS (0 errors) |
| `nox -s unit_tests` | PASS (10,917 scenarios) |
| `nox -s coverage_report` | 97% (>= 97%) |

Closes #880

Reviewed-on: #994
Co-authored-by: Brent Edwards <brent.edwards@cleverthis.com>
Co-committed-by: Brent Edwards <brent.edwards@cleverthis.com>
2026-03-21 03:14:40 +00:00
brent.edwards 6531440431 feat(actor): implement estimation actor type (#962)
CI / build (push) Successful in 24s
CI / lint (push) Successful in 3m16s
CI / quality (push) Successful in 3m45s
CI / typecheck (push) Successful in 3m52s
CI / benchmark-regression (push) Has been skipped
CI / security (push) Successful in 4m1s
CI / unit_tests (push) Successful in 7m8s
CI / integration_tests (push) Successful in 7m1s
CI / docker (push) Successful in 1m6s
CI / e2e_tests (push) Successful in 9m49s
CI / coverage (push) Successful in 12m22s
CI / status-check (push) Successful in 1s
CI / benchmark-publish (push) Successful in 19m34s
## Summary

Implement the estimation actor as a functional actor type. The estimation actor provides cost, time, and resource estimates for plan operations, running after Strategize completes (before Execute). Estimation is informational only and optional — plans work without an estimation actor configured.

### Changes

**New files:**
- `src/cleveragents/domain/models/core/estimation.py` — `EstimationResult` frozen Pydantic model with fields for cost (USD), tokens, steps, child plans, time, risk level/factors, summary
- `features/estimation_actor.feature` — 12 Behave test scenarios (model validation, serialization, stub actor, plan integration, optional behavior)
- `features/steps/estimation_actor_steps.py` — Step definitions
- `robot/estimation_actor.robot` — 6 Robot integration tests
- `robot/helper_estimation_actor.py` — Robot test helper

**Modified files:**
- `domain/models/acms/tiers.py` — Added `ESTIMATOR` to `ActorRole` enum
- `domain/models/core/plan.py` — Added `estimation_result: EstimationResult | None` field, estimation data in `as_cli_dict()`
- `application/services/plan_executor.py` — Added `EstimationStubActor` class
- `application/services/plan_lifecycle_service.py` — Added `_run_estimation()` method, invoked in `execute_plan()`
- `cli/commands/plan.py` — Display estimation results in plan status
- `vulture_whitelist.py` — Added 12 new public symbols

### Quality Gates

| Session | Result |
|---|---|
| `nox -s lint` | PASS |
| `nox -s typecheck` | PASS (0 errors) |
| `nox -s unit_tests` | PASS (10,818 scenarios) |
| `nox -s integration_tests` | PASS (1,512 tests) |
| `nox -s coverage_report` | 98% (>= 97%) |

Closes #890

Reviewed-on: #962
Co-authored-by: Brent Edwards <brent.edwards@cleverthis.com>
Co-committed-by: Brent Edwards <brent.edwards@cleverthis.com>
2026-03-21 01:40:58 +00:00
brent.edwards 95d3e09925 feat(cli): final CLI polish and UX consistency pass (#1018)
CI / build (push) Successful in 19s
CI / lint (push) Successful in 3m21s
CI / quality (push) Successful in 3m43s
CI / typecheck (push) Successful in 4m13s
CI / benchmark-regression (push) Has been skipped
CI / security (push) Successful in 4m17s
CI / unit_tests (push) Successful in 5m45s
CI / docker (push) Successful in 1m3s
CI / integration_tests (push) Successful in 6m49s
CI / e2e_tests (push) Successful in 9m8s
CI / coverage (push) Failing after 13m47s
CI / benchmark-publish (push) Successful in 19m43s
CI / status-check (push) Failing after 1s
## Summary

Final CLI polish and UX consistency pass: shared constants, centralized error formatting, shell completion, and standardized help text.

### New Modules

- **`cli/constants.py`** (70 lines): Exit codes (`EXIT_SUCCESS`=0 through `EXIT_CONFLICT`=4), format defaults (`FORMAT_TEXT`, `FORMAT_JSON`, `FORMAT_TABLE`)
- **`cli/errors.py`** (105 lines): `cli_error()` with hint support, `cli_warning()`, `cli_not_found()` with resource-type-aware hint

### CLI Changes

- Shell `completion` command generating scripts for bash/zsh/fish/powershell
- Standardized help text across command modules
- Error functions exported from `cli/__init__.py`

### Tests

- **17 Behave scenarios**: Exit codes, error formatting, cli_not_found, format constants, help text, completion
- **15 Robot integration tests**: All subcommands respond to --help, invalid commands return non-zero, completion generation works

### Quality Gates

| Session | Result |
|---|---|
| `nox -s lint` | PASS |
| `nox -s typecheck` | PASS (0 errors) |
| `nox -s unit_tests` | PASS (10,912 scenarios) |
| `nox -s coverage_report` | 97% (>= 97%) |

Closes #861

Reviewed-on: #1018
Co-authored-by: Brent E. Edwards <brent.edwards@cleverthis.com>
Co-committed-by: Brent E. Edwards <brent.edwards@cleverthis.com>
2026-03-21 01:14:18 +00:00
brent.edwards 00897be24a feat(ci): CI/CD pipeline definitions (#983)
CI / build (push) Successful in 21s
CI / lint (push) Successful in 3m30s
CI / typecheck (push) Successful in 3m55s
CI / benchmark-regression (push) Has been skipped
CI / security (push) Successful in 3m57s
CI / quality (push) Successful in 3m59s
CI / integration_tests (push) Successful in 5m52s
CI / e2e_tests (push) Successful in 8m15s
CI / coverage (push) Failing after 13m33s
CI / unit_tests (push) Failing after 17m29s
CI / benchmark-publish (push) Successful in 19m11s
CI / docker (push) Has been skipped
CI / status-check (push) Failing after 3s
## Summary

Complete CI/CD pipeline definitions: release workflow, caching, status-check consolidation, and documentation.

### Changes

**New: Release pipeline** (`.forgejo/workflows/release.yml`):
- Triggered on `v*` tags
- 3 jobs: `build-wheel` → `build-docker` → `create-release`
- Builds wheel via `nox -s build`, Docker image via multi-stage Dockerfile
- Creates Forgejo release via API with wheel artifact attached
- Configurable registry push via `REGISTRY_*` secrets

**Updated: CI pipeline** (`.forgejo/workflows/ci.yml`):
- Added `actions/cache@v3` for `~/.cache/uv` on all 8 primary jobs (keyed on `pyproject.toml` hash)
- Added `status-check` consolidation job depending on all required checks — single gate for branch protection

**Updated: CONTRIBUTING.md**:
- New CI/CD section: pipeline overview, job table, required merge checks, release process, secrets documentation

**Tests**:
- 13 new Behave scenarios validating workflow YAML structure, tag triggers, job definitions, dependencies
- 9 new Robot tests validating file existence, content, nox session references

### Quality Gates

| Session | Result |
|---|---|
| `nox -s lint` | PASS |
| `nox -s typecheck` | PASS (0 errors) |
| `nox -s unit_tests` | PASS (10,819 scenarios) |
| `nox -s coverage_report` | 97.9% (>= 97%) |

Closes #858

Reviewed-on: #983
Co-authored-by: Brent E. Edwards <brent.edwards@cleverthis.com>
Co-committed-by: Brent E. Edwards <brent.edwards@cleverthis.com>
2026-03-21 00:29:49 +00:00
brent.edwards fa3f2d6365 test: add TDD bug-capture test for #932 — plan apply missing --yes flag (#958)
CI / lint (push) Successful in 26s
CI / quality (push) Successful in 39s
CI / build (push) Successful in 40s
CI / typecheck (push) Successful in 52s
CI / security (push) Successful in 53s
CI / benchmark-regression (push) Has been skipped
CI / unit_tests (push) Successful in 3m3s
CI / integration_tests (push) Successful in 3m7s
CI / docker (push) Successful in 1m7s
CI / e2e_tests (push) Successful in 5m30s
CI / coverage (push) Successful in 9m32s
CI / benchmark-publish (push) Has been cancelled
## Summary

TDD expected-fail tests proving bug #932 exists: the `plan apply` (`lifecycle-apply`) command does not accept the `--yes`/`-y` flag required by the specification. The flag should skip the confirmation prompt before applying plan changes.

### Tests Added

**Behave scenarios** (`features/tdd_plan_apply_yes_flag.feature`):
- `lifecycle-apply --yes` should be accepted (tests `--yes` long flag)
- `lifecycle-apply -y` should be accepted (tests `-y` short flag)

Tags: `@tdd_expected_fail @tdd_bug @tdd_bug_932`

**Robot Framework tests** (`robot/tdd_plan_apply_yes_flag.robot`):
- `check-yes-long` — invokes CLI with `--yes`, asserts no "No such option" error
- `check-yes-short` — invokes CLI with `-y`, asserts no "No such option" error

### How the Bug Is Proven

The `lifecycle_apply_plan` function (`cleveragents.cli.commands.plan`) defines only `plan_id` and `--format` parameters — no `--yes`/`-y`. When tests invoke `lifecycle-apply --yes`, Typer/Click rejects it with `"No such option: --yes"` and exit code 2. The assertion that this error is absent **fails**, confirming bug #932. The `@tdd_expected_fail` tag inverts this to a pass.

### Quality Gates

| Session | Result |
|---|---|
| `nox -s lint` | PASS |
| `nox -s typecheck` | PASS (0 errors) |
| `nox -s unit_tests` | PASS (10,808 scenarios) |
| `nox -s integration_tests` | PASS (1,508 tests) |
| `nox -s coverage_report` | 98% (>= 97%) |

Closes #950

Reviewed-on: #958
Co-authored-by: Brent E. Edwards <brent.edwards@cleverthis.com>
Co-committed-by: Brent E. Edwards <brent.edwards@cleverthis.com>
2026-03-21 00:13:17 +00:00
brent.edwards 8d108cb5d1 feat(tool): add tool-level execution environment preferences (#970)
CI / lint (push) Successful in 21s
CI / build (push) Successful in 27s
CI / quality (push) Successful in 30s
CI / typecheck (push) Successful in 40s
CI / benchmark-regression (push) Has been skipped
CI / security (push) Successful in 54s
CI / integration_tests (push) Successful in 3m57s
CI / e2e_tests (push) Successful in 4m51s
CI / unit_tests (push) Successful in 5m23s
CI / docker (push) Successful in 1m2s
CI / coverage (push) Successful in 6m57s
CI / benchmark-publish (push) Successful in 19m29s
## Summary

Add tool-level execution environment preferences with four modes: `required`, `preferred`, `specific`, and `none`.

### Changes

**New model** (`domain/models/core/execution_environment_preference.py`):
- `EnvironmentPreferenceMode` enum: REQUIRED, PREFERRED, SPECIFIC, NONE
- `ExecutionEnvironmentPreference` frozen Pydantic model with `mode` and `target_resource` fields
- Model validator ensures `target_resource` required iff mode is SPECIFIC

**ToolSpec & Tool model updates:**
- Added `execution_environment: ExecutionEnvironmentPreference` field to both `ToolSpec` (runtime) and `Tool` (domain)
- `Tool.from_config()` parses `execution_environment` from YAML config dicts

**ToolRunner integration** (`tool/runner.py`):
- Before calling `_env_resolver.resolve()`, checks `spec.execution_environment.mode`:
  - REQUIRED: raises `ContainerUnavailableError` if resolved env is not CONTAINER
  - PREFERRED: tries container, gracefully falls back to host
  - SPECIFIC: overrides `tool_env` with `target_resource`
  - NONE: current behavior (caller-supplied tool_env)

### Tests

- **27 Behave scenarios** covering model validation, serialization, preference routing, YAML parsing, error cases
- **12 Robot integration tests** covering CLI tool preference display and end-to-end routing

### Quality Gates

| Session | Result |
|---|---|
| `nox -s lint` | PASS |
| `nox -s typecheck` | PASS (0 errors) |
| `nox -s unit_tests` | PASS (10,833 scenarios) |
| `nox -s integration_tests` | PASS (12 new tests) |

Closes #879

Reviewed-on: #970
Co-authored-by: Brent Edwards <brent.edwards@cleverthis.com>
Co-committed-by: Brent Edwards <brent.edwards@cleverthis.com>
2026-03-20 23:51:46 +00:00
brent.edwards 4f950a1600 feat(cli): repo indexing CLI functional (#982)
CI / lint (push) Successful in 24s
CI / build (push) Successful in 16s
CI / typecheck (push) Successful in 38s
CI / quality (push) Successful in 43s
CI / security (push) Successful in 53s
CI / benchmark-regression (push) Has been skipped
CI / integration_tests (push) Successful in 2m39s
CI / unit_tests (push) Successful in 3m58s
CI / docker (push) Successful in 1m8s
CI / e2e_tests (push) Successful in 5m21s
CI / coverage (push) Successful in 6m31s
CI / benchmark-publish (push) Successful in 19m39s
## Summary

Add `agents repo index` and `agents repo status` CLI commands, wiring the existing `RepoIndexingService` backend to the CLI layer.

### Commands

- **`agents repo index <resource_name>`** — Triggers full or incremental indexing of a repository resource. Options: `--full` (force full re-index), `--format text|json`
- **`agents repo status <resource_name>`** — Displays indexing metadata: status, file count, token estimate, primary language, last indexed timestamp. Options: `--format text|json`

### Implementation

- New CLI module `src/cleveragents/cli/commands/repo.py` (238 lines)
- Registered as `repo` subcommand group in `cli/main.py`
- Resolves resource by name via `ResourceRegistryService`
- Calls `RepoIndexingService.index_resource()` / `refresh_index()` / `get_index_status()`
- Both text (Rich panel) and JSON output formats

### Quality Gates

| Session | Result |
|---|---|
| `nox -s lint` | PASS |
| `nox -s typecheck` | PASS (0 errors) |
| `nox -s unit_tests` | PASS (10,819 scenarios) |
| `nox -s coverage_report` | 98% (>= 97%) |
| Integration tests | 5/5 PASS |

Closes #856

Reviewed-on: #982
Co-authored-by: Brent Edwards <brent.edwards@cleverthis.com>
Co-committed-by: Brent Edwards <brent.edwards@cleverthis.com>
2026-03-20 22:28:32 +00:00
freemo 051ee7c290 test(coverage): add Behave BDD tests to improve coverage across 52 source files
CI / benchmark-publish (pull_request) Has been skipped
CI / lint (pull_request) Successful in 21s
CI / quality (pull_request) Successful in 31s
CI / typecheck (pull_request) Successful in 47s
CI / security (pull_request) Successful in 52s
CI / build (pull_request) Successful in 56s
CI / e2e_tests (pull_request) Successful in 5m1s
CI / integration_tests (pull_request) Successful in 5m30s
CI / unit_tests (pull_request) Successful in 5m42s
CI / docker (pull_request) Successful in 58s
CI / coverage (pull_request) Successful in 7m35s
CI / build (push) Successful in 21s
CI / docker (push) Has been skipped
CI / benchmark-regression (pull_request) Failing after 49m24s
CI / lint (push) Successful in 22s
CI / quality (push) Successful in 39s
CI / security (push) Successful in 48s
CI / typecheck (push) Successful in 1m26s
CI / benchmark-regression (push) Has been skipped
CI / e2e_tests (push) Successful in 5m53s
CI / coverage (push) Successful in 9m4s
CI / benchmark-publish (push) Successful in 19m10s
CI / integration_tests (push) Failing after 19m18s
CI / unit_tests (push) Failing after 19m20s
Added 52 new .feature files and corresponding _steps.py files targeting
previously uncovered code paths in the following areas:

- TUI layer: app, commands, persona (state/schema/registry), widgets,
  input (shell_exec, reference_parser)
- Application services: plan lifecycle/service/executor, session,
  project, repo indexing, correction, checkpoint, actor, llm_actors,
  strategy coordinator, resource file watcher, service retry wiring
- CLI commands: session, resource, repl, plan, db, automation_profile
- Domain models: retry_policy, resource_type, cost_budget,
  docker_compose_analyzer, detail_level, _sql_string_aware,
  _postgresql_helpers
- Core: circuit_breaker, retry_service_patterns
- Infrastructure: repositories, transaction_sandbox, strategy_registry,
  plugins/loader, container
- Config: settings
- Agents: plan_generation, context_analysis, auto_debug
- A2A: facade

All new tests follow the Behave/Gherkin BDD standard. Resolved step
definition collisions with unique prefixes. Fixed Alembic fileConfig
logger disabling issue (disable_existing_loggers=False).

ISSUES CLOSED: #1068
2026-03-20 21:22:10 +00:00
brent.edwards 202c9bfe75 test(acms): TDD failing tests for context tier runtime logic (bug #821) (#1058)
CI / lint (push) Successful in 13s
CI / e2e_tests (push) Has started running
CI / quality (push) Successful in 23s
CI / benchmark-publish (push) Has started running
CI / typecheck (push) Successful in 43s
CI / benchmark-regression (push) Has been skipped
CI / build (push) Successful in 22s
CI / security (push) Successful in 59s
CI / integration_tests (push) Successful in 2m49s
CI / unit_tests (push) Successful in 4m1s
CI / docker (push) Successful in 1m26s
CI / coverage (push) Successful in 9m14s
## Summary

TDD expected-fail tests proving bug #821 exists: `ContextTierService` has data models for hot/warm/cold tiers but **no runtime logic** for automatic promotion, demotion, or eviction.

- **Promotion on access**: Accessing a cold-tier fragment repeatedly via `get()` does NOT auto-promote it — `get()` updates `access_count`/`last_accessed` but never calls `promote()`
- **Demotion on staleness**: No staleness enforcement method exists — tried `enforce_staleness()`, `apply_tier_policy()`, `tick()`, etc. — none are implemented
- **Eviction on budget overflow**: `store()` does NOT enforce `TierBudget.max_tokens_hot` — the hot tier grows without bound

### Files Added
| File | Purpose |
|------|---------|
| `features/tdd_context_tier_runtime.feature` | 3 Behave scenarios tagged `@tdd_expected_fail @tdd_bug @tdd_bug_821 @mock_only` |
| `features/steps/tdd_context_tier_runtime_steps.py` | Type-annotated step definitions exercising real `ContextTierService` |
| `robot/tdd_context_tier_runtime.robot` | 3 Robot Framework integration tests tagged `tdd_expected_fail` |
| `robot/helper_tdd_context_tier_runtime.py` | Helper script for Robot tests with 3 subcommands |

### Verification
- `nox -s lint` — passed
- `nox -s typecheck` — passed (0 errors)
- `nox -s unit_tests -- features/tdd_context_tier_runtime.feature` — **3 scenarios passed** (all assertions fail as expected, `@tdd_expected_fail` inverts to CI pass)

ISSUES CLOSED: #840

Reviewed-on: #1058
Co-authored-by: Brent Edwards <brent.edwards@cleverthis.com>
Co-committed-by: Brent Edwards <brent.edwards@cleverthis.com>
2026-03-19 22:24:41 +00:00
brent.edwards 60af2cae0c fix(cli): make plan explain accept plan_id for plan-level explanation (#1057)
CI / lint (push) Successful in 14s
CI / typecheck (push) Successful in 25s
CI / build (push) Successful in 21s
CI / security (push) Successful in 58s
CI / benchmark-regression (push) Has been skipped
CI / quality (push) Successful in 47s
CI / integration_tests (push) Successful in 2m51s
CI / e2e_tests (push) Successful in 4m17s
CI / unit_tests (push) Successful in 4m19s
CI / coverage (push) Successful in 4m32s
CI / docker (push) Successful in 1m50s
CI / benchmark-publish (push) Has been cancelled
## Summary

Fixes `plan explain` to accept both decision IDs and plan IDs as the positional argument, matching the M3 acceptance test usage pattern `plan explain <plan_id>`.

### Problem
`explain_decision_cmd` only accepted a decision ULID. When the M3 acceptance test passed a plan ID, `svc.get_decision(plan_id)` returned `None`, causing "Decision not found" error with exit code 1.

### Fix
1. Renamed parameter `decision_id` → `identifier`
2. Tries `svc.get_decision(identifier)` first (backward compat)
3. Falls back to `svc.list_decisions(identifier)` treating it as a plan_id, explaining the root decision
4. Clear error if neither resolves

### Quality Gates
| Session | Result |
|---------|--------|
| `nox -s lint` | PASS |
| `nox -s typecheck` | PASS (0 errors) |
| `nox -s unit_tests` (explain features) | 46/46 PASS |

Closes #968

Reviewed-on: #1057
Co-authored-by: Brent Edwards <brent.edwards@cleverthis.com>
Co-committed-by: Brent Edwards <brent.edwards@cleverthis.com>
2026-03-19 22:10:23 +00:00
hamza.khyari e2f90ffcd5 feat(resource): add deferred physical resource types
CI / benchmark-publish (pull_request) Has been skipped
CI / lint (pull_request) Successful in 19s
CI / build (pull_request) Successful in 28s
CI / quality (pull_request) Successful in 29s
CI / typecheck (pull_request) Successful in 42s
CI / security (pull_request) Successful in 52s
CI / unit_tests (pull_request) Successful in 3m23s
CI / integration_tests (pull_request) Successful in 3m37s
CI / docker (pull_request) Successful in 1m8s
CI / e2e_tests (pull_request) Successful in 5m26s
CI / coverage (pull_request) Successful in 8m7s
CI / benchmark-regression (pull_request) Successful in 38m7s
Add 11 deferred physical resource types covering the git object taxonomy
(git, git-remote, git-branch, git-tag, git-commit, git-tree, git-tree-entry,
git-stash, git-submodule) and filesystem link types (fs-symlink, fs-hardlink).

- YAML configs under examples/resource-types/
- Bootstrap registration via _resource_registry_physical.py module
- Auto-discovery rules with bounded scan_depth (1-2) for git object graph
- fs-directory scan_depth=1 (immediate children only)
- git-branch scan_depth=1 (single HEAD), git-tree scan_depth=2 (capped)
- Updated fs-directory child_types/parent_types/auto_discovery
- Updated git-checkout child_types to include git
- Fixed git-tag child_types to include git-commit (DAG consistency)
- Behave tests, Robot tests, ASV benchmarks
- Documentation in docs/reference/resource_types_builtin.md

ISSUES CLOSED: #330
2026-03-19 14:03:17 +00:00