Files
cleveragents-core/features/depth_breadth_projection.feature
T
hurui200320 2005b8ef82
CI / push-validation (push) Successful in 18s
CI / build (push) Successful in 19s
CI / helm (push) Successful in 24s
CI / lint (push) Successful in 29s
CI / security (push) Successful in 1m11s
CI / e2e_tests (push) Successful in 2m56s
CI / quality (push) Successful in 3m40s
CI / typecheck (push) Successful in 3m59s
CI / integration_tests (push) Successful in 4m3s
CI / unit_tests (push) Successful in 4m55s
CI / docker (push) Successful in 10s
CI / coverage (push) Successful in 10m44s
CI / status-check (push) Successful in 1s
CI / benchmark-regression (push) Has been skipped
CI / benchmark-publish (push) Successful in 1h13m28s
feat(tests): replace all @skip tags with proper @tdd_expected_fail tags or remove them across the entire codebase (#7221)
## Summary

Replaces all 234 bare `@skip` occurrences across 82 Behave feature files with the correct TDD issue-capture tagging system described in CONTRIBUTING.md § Bug Fix Workflow.

Previously, the noxfile ran Behave with `--tags=not @skip`, silently excluding all `@skip`-tagged scenarios from every CI run. These tests never ran, never inverted results via the `@tdd_expected_fail` mechanism, and never contributed to coverage — defeating the purpose of TDD issue-capture testing. Every `@skip` occurrence had a commented-out hint line immediately above it showing the intended proper tags (e.g., `# @tdd_issue @tdd_issue_4272 @tdd_expected_fail @skip`), confirming they were all intended for conversion.

## Changes

### Mechanical conversion (234 replacements across 82 files)
- Extracted the proper TDD tags from the comment hint above each `@skip` line, removed `@skip` from the tag set, and replaced the `@skip` line with those tags.
- Removed the now-redundant comment hint lines alongside each replacement.

### Bug-fixed scenarios — `@tdd_expected_fail` removed (84 scenarios)
- After conversion, ran `nox -s unit_tests` to identify which newly-enabled `@tdd_expected_fail` scenarios now **pass** (their referenced bugs have already been fixed). Removed `@tdd_expected_fail` from those 84 scenarios and their corresponding feature-level tags, leaving only the permanent `@tdd_issue @tdd_issue_<N>` regression-guard tags.
- Affected features include: `tdd_tool_runner_env_precedence`, `tdd_automation_profile_session_leak`, `tls_certificate_check`, `project_create_persist`, `resource_type_bootstrap_*`, and 18 others.

### Noxfile cleanup
- Removed all four `--tags=not @skip` arguments from `noxfile.py` (unit_tests and coverage sessions). With zero `@skip` tags remaining in the codebase, this filter was dead code and its presence would mislead future maintainers into thinking `@skip` is still a supported escape mechanism.

### Regression guard files
- Split the regression guards into two focused files:
  - `tdd_regression_guards_exec_env.feature` for bug #4281 (exec-env precedence)
  - `tdd_regression_guards_session_list.feature` for bug #4271 (session list summary)
- Each file carries only its own `@tdd_issue` tags at the feature level, avoiding cross-contamination via Behave tag inheritance. The `Background` step (`session-list-summary mock`) only appears in the session-list file where it is actually needed.

### Duplicate tag cleanup
- Removed duplicate `@tdd_issue @tdd_issue_4287` tag lines in `tdd_skill_add_regression.feature` (lines 20 and 29).

### Inline comment for retained `@tdd_expected_fail`
- Added inline comment in `ci_workflow_validation.feature:134` explaining why this specific #4227 scenario retains `@tdd_expected_fail` despite #4227 being closed (CI YAML does not encode threshold as a machine-readable value).

### Known edge cases — `@tdd_expected_fail` retained (closed issues, fix on master, scenarios still fail)
The following issues are **closed** and their fixes **are on master**, but the specific test assertions still fail because the fixes address other aspects of the bugs. The `@tdd_expected_fail` tags are functionally correct and must remain until the specific scenario assertions pass:
- `tdd_exec_env_resolution_precedence.feature` — bug #1080 (closed 2026-03-31). The precedence-level-2-vs-4 scenario still fails.
- `session_list_summary_dedup.feature` — bug #3046 (closed 2026-04-05). The dedup-consistency scenarios still fail.
- `actor_add_update_enforcement.feature` — bug #2609 (closed 2026-04-05). The enforcement scenarios still fail.
- `ci_workflow_validation.feature:134` — #4227 (closed 2026-04-08). The CI YAML threshold assertion still fails.

## Verification

- `grep -r "@skip" features/ --include="*.feature"` → **zero results** ✓
- `grep -n "tags=not @skip" noxfile.py` → **zero results** ✓
- `nox -s unit_tests` → **629 features passed, 0 failed** ✓ (up from ~545 before this PR)
- CI all green (coverage ≥ 97%) ✓
- Integration tests (Robot Framework) do not use `@skip` — confirmed no action needed ✓
- E2E tests (Robot Framework) do not use `@skip` — confirmed no action needed ✓
- `CHANGELOG.md` updated with entry for this change ✓
- `CONTRIBUTORS.md` — Rui Hu already listed ✓

## Issues Addressed

Closes #7025

Co-authored-by: CleverThis <hal9000@cleverthis.com>
Reviewed-on: #7221
Reviewed-by: HAL 9000 <HAL9000@cleverthis.com>
Reviewed-by: HAL9001 <hal9001@cleverthis.com>
Co-authored-by: Rui Hu <rui.hu@cleverthis.com>
Co-committed-by: Rui Hu <rui.hu@cleverthis.com>
2026-04-13 04:56:01 +00:00

277 lines
14 KiB
Gherkin

@phase2 @acms @depth_breadth_projection
Feature: Depth/Breadth Projection System and Skeleton Context Propagation
As a CleverAgents developer
I want a projection system over the UKO graph
So that context can be materialized at varying detail levels
based on distance from focal entities, and child plans can
inherit compressed parent context via skeleton propagation
# ---------------------------------------------------------------------------
# ProjectionSpec model
# ---------------------------------------------------------------------------
@projection @model
Scenario: ProjectionSpec is a frozen Pydantic model
Given the depth/breadth projection modules are available
When I create a ProjectionSpec with focus "class://AuthManager" and breadth 2 and depth 9
Then the projection spec focus should contain "class://AuthManager"
And the projection spec breadth should be 2
And the projection spec depth should be 9
And the projection spec depth_gradient should be True
And the projection spec domain should be "uko-code:"
And the projection spec should be immutable
@projection @model
Scenario: ProjectionSpec rejects empty focus
Given the depth/breadth projection modules are available
When I create a ProjectionSpec with empty focus
Then a projection ValidationError should be raised
@projection @model
Scenario: ProjectionSpec rejects negative integer depth
Given the depth/breadth projection modules are available
When I create a ProjectionSpec with negative depth
Then a projection ValueError should be raised mentioning "non-negative"
@projection @model
Scenario: ProjectionSpec accepts named depth levels
Given the depth/breadth projection modules are available
When I create a ProjectionSpec with focus "module://auth" and named depth "FULL_SOURCE"
Then the projection spec depth should be "FULL_SOURCE"
# ---------------------------------------------------------------------------
# ProjectedNode model
# ---------------------------------------------------------------------------
@projection @model
Scenario: ProjectedNode is a frozen Pydantic model
Given the depth/breadth projection modules are available
When I create a ProjectedNode with uri "class://Foo" and distance 1 and resolved_depth 4
Then the projected node uri should be "class://Foo"
And the projected node distance should be 1
And the projected node resolved_depth should be 4
And the projected node should be immutable
# ---------------------------------------------------------------------------
# DepthBreadthProjector — BFS traversal
# ---------------------------------------------------------------------------
@projection @projector
Scenario: Projector performs BFS from focus with breadth 0
Given the depth/breadth projection modules are available
And a UKO graph with nodes A B C and edges A->B B->C
When I project with focus "A" and breadth 0 and depth 9
Then the projection should contain exactly 1 node
And the projected nodes should include "A" at distance 0
@projection @projector
Scenario: Projector performs BFS from focus with breadth 1
Given the depth/breadth projection modules are available
And a UKO graph with nodes A B C and edges A->B B->C
When I project with focus "A" and breadth 1 and depth 9
Then the projection should contain exactly 2 nodes
And the projected nodes should include "A" at distance 0
And the projected nodes should include "B" at distance 1
@projection @projector
Scenario: Projector performs BFS from focus with breadth 2
Given the depth/breadth projection modules are available
And a UKO graph with nodes A B C and edges A->B B->C
When I project with focus "A" and breadth 2 and depth 9
Then the projection should contain exactly 3 nodes
And the projected nodes should include "A" at distance 0
And the projected nodes should include "B" at distance 1
And the projected nodes should include "C" at distance 2
@projection @projector
Scenario: Projector applies depth gradient
Given the depth/breadth projection modules are available
And a UKO graph with nodes A B C and edges A->B B->C
When I project with focus "A" and breadth 2 and depth 9 and gradient True
Then the projected node "A" should have resolved_depth 9
And the projected node "B" should have resolved_depth greater than 0
And the projected node "B" should have resolved_depth less than 9
And the projected node "C" should have resolved_depth 0
@projection @projector
Scenario: Projector without gradient assigns uniform depth
Given the depth/breadth projection modules are available
And a UKO graph with nodes A B C and edges A->B B->C
When I project with focus "A" and breadth 2 and depth 9 and gradient False
Then the projected node "A" should have resolved_depth 9
And the projected node "B" should have resolved_depth 9
And the projected node "C" should have resolved_depth 9
@projection @projector
Scenario: Projector resolves named depth via DetailLevelMap
Given the depth/breadth projection modules are available
And a code DetailLevelMap is registered for domain "uko-code:"
And a UKO graph with nodes A B and edges A->B
When I project with focus "A" and breadth 1 and named depth "FULL_SOURCE" in domain "uko-code:"
Then the projected node "A" should have resolved_depth 9
And the projected node "B" should have resolved_depth 0
@projection @projector
Scenario: Projector raises error for unresolvable named depth
Given the depth/breadth projection modules are available
And a UKO graph with nodes A and no edges
When I project with focus "A" and breadth 0 and named depth "NONEXISTENT" in domain "unknown:"
Then a projection ValueError should be raised mentioning "no DetailLevelMap"
@projection @projector
Scenario: Projector handles multiple focus nodes
Given the depth/breadth projection modules are available
And a UKO graph with nodes A B C D and edges A->B C->D
When I project with multi-focus "A" and "C" and breadth 1 and depth 5
Then the projection should contain exactly 4 nodes
And the projected nodes should include "A" at distance 0
And the projected nodes should include "C" at distance 0
And the projected nodes should include "B" at distance 1
And the projected nodes should include "D" at distance 1
@projection @projector
Scenario: Projector converts projection to ContextFragments
Given the depth/breadth projection modules are available
And a UKO graph with nodes A B and edges A->B
When I project to fragments with focus "A" and breadth 1 and depth 4
Then the result should contain 2 ContextFragments
And the first fragment uko_node should be "A"
And all fragments should have metadata key "projected" set to True
# ---------------------------------------------------------------------------
# Built-in DetailLevelMap presets
# ---------------------------------------------------------------------------
@projection @presets
Scenario: Code detail level map has correct levels
Given the depth/breadth projection modules are available
When I create the code detail level map preset
Then the code map should resolve "MODULE_LISTING" to 0
And the code map should resolve "SIGNATURES" to 4
And the code map should resolve "FULL_SOURCE" to 9
@projection @presets
Scenario: Docs detail level map has correct levels
Given the depth/breadth projection modules are available
When I create the docs detail level map preset
Then the docs map should resolve "TITLE_ONLY" to 0
And the docs map should resolve "FULL_CONTENT" to 10
@projection @presets
Scenario: Database detail level map has correct levels
Given the depth/breadth projection modules are available
When I create the database detail level map preset
Then the database map should resolve "SCHEMA_LISTING" to 0
And the database map should resolve "TABLE_LISTING" to 1
And the database map should resolve "FULL_CATALOG" to 11
# ---------------------------------------------------------------------------
# PlanContextInheritance — skeleton propagation
# ---------------------------------------------------------------------------
@inheritance @skeleton
Scenario: PlanContextInheritance computes child context request
Given the depth/breadth projection modules are available
And a parent assembled context with 3 fragments at detail_depth 3
And a PlanContextInheritance service with default config
When I compute child context with focus "class://Child" and budget 1000
Then the child result should contain a ContextRequest
And the child request focus should contain "class://Child"
And the child request depth_gradient should be True
And the child result depth_delta should be 1
@inheritance @skeleton
Scenario: PlanContextInheritance increases child detail from parent
Given the depth/breadth projection modules are available
And a parent assembled context with 3 fragments at detail_depth 3
And a PlanContextInheritance service with default config
When I compute child context with focus "class://Child" and budget 1000
Then the child request depth should be greater than 3
@inheritance @skeleton
Scenario: PlanContextInheritance narrows child breadth
Given the depth/breadth projection modules are available
And a parent assembled context with 3 fragments at detail_depth 3
And a PlanContextInheritance service with default config
When I compute child context with focus "class://Child" and budget 1000 at depth_in_tree 0 to 1
Then the child request breadth should be at most 2
@inheritance @skeleton
Scenario: PlanContextInheritance injects skeleton fragments
Given the depth/breadth projection modules are available
And a parent assembled context with 3 fragments at detail_depth 3
And a mock skeleton compressor that returns 2 fragments
And a PlanContextInheritance service with the mock compressor
When I compute child context with focus "class://Child" and budget 1000
Then the child result skeleton_fragments should have 2 entries
@inheritance @skeleton
Scenario: PlanContextInheritance uses DepthReductionCompressor by default
Given the depth/breadth projection modules are available
And a parent assembled context with the following inheritance fragments:
| uko_node | content | tokens | depth | domain | resource_uri |
| project://src/app/main.py | def main(): return runner() | 120 | 7 | uko-py: | project://src/app/main.py |
And a PlanContextInheritance service with default config
When I compute child context with focus "class://Child" and budget 1000
Then the child result skeleton_fragments should have 1 entries
And all child skeleton fragments should have detail depth at most 1
And a child skeleton fragment should contain "[MODULE_GRAPH]: symbols=main"
@inheritance @skeleton @tdd_issue @tdd_issue_4198 @tdd_expected_fail
Scenario: PlanContextInheritance prioritises fragments near the child focus
Given the depth/breadth projection modules are available
And a parent assembled context with the following inheritance fragments:
| uko_node | content | tokens | depth | domain | resource_uri | score |
| project://src/app/main.py | def main(): return run | 120 | 7 | | project://src/app/main.py | 0.2 |
| project://lib/aux.py | def aux(): return slow | 120 | 7 | | project://lib/aux.py | 0.9 |
And a PlanContextInheritance service with default config and min_skeleton_tokens 1
When I compute child context with focus "project://src/app/main.py" and budget 60
Then the child result skeleton_fragments should have 2 entries
And the first child skeleton fragment should contain "main.py"
@inheritance @skeleton
Scenario: PlanContextInheritance skips skeleton when budget too small
Given the depth/breadth projection modules are available
And a parent assembled context with 3 fragments at detail_depth 3
And a mock skeleton compressor that returns 2 fragments
And a PlanContextInheritance service with the mock compressor and min_skeleton_tokens 500
When I compute child context with focus "class://Child" and budget 100
Then the child result skeleton_fragments should have 0 entries
@inheritance @skeleton
Scenario: PlanContextInheritance rejects invalid depth delta
Given the depth/breadth projection modules are available
And a parent assembled context with 3 fragments at detail_depth 3
And a PlanContextInheritance service with default config
When I compute child context with parent_depth 2 and child_depth 1
Then a projection ValueError should be raised mentioning "child_depth_in_tree"
@inheritance @skeleton
Scenario: PlanContextInheritance config uses default skeleton_ratio
Given the depth/breadth projection modules are available
When I create an InheritanceConfig with defaults
Then the inheritance config skeleton_ratio should be 0.15
@inheritance @skeleton
Scenario: PlanContextInheritance extract_child_focus returns parent decisions
Given the depth/breadth projection modules are available
When I extract child focus from decisions "class://A" and "class://B"
Then the child focus should include both "class://A" and "class://B"
@inheritance @skeleton
Scenario: PlanContextInheritance extract_child_focus uses fallback
Given the depth/breadth projection modules are available
When I extract child focus from empty decisions with fallback "class://Default"
Then the child focus should contain "class://Default"
# ---------------------------------------------------------------------------
# ChildContextResult model
# ---------------------------------------------------------------------------
@inheritance @model
Scenario: ChildContextResult is a frozen Pydantic model
Given the depth/breadth projection modules are available
When I create a ChildContextResult with a request and skeleton data
Then the child context result should be immutable
And the child context result should contain the request