@mock_only Feature: Execute-phase context assembler coverage Comprehensive tests for ACMSExecutePhaseContextAssembler covering _resolve_execute_view, _path_matches, _resource_matches, _to_context_fragment, and the full assemble() method with all filtering branches. # ---- Protocol ---- Scenario: epcov protocol assemble method is abstract Given epcov a class implementing the ExecutePhaseContextAssembler protocol When epcov I call assemble on the protocol stub Then epcov the result should be None # ---- _resolve_execute_view ---- Scenario: epcov resolve execute view success Given epcov an assembler with a project repository returning a custom policy When epcov I resolve the execute view for "proj-alpha" Then epcov the resolved view should have the custom include_resources Scenario: epcov resolve execute view falls back on exception Given epcov an assembler with a project repository that raises an exception When epcov I resolve the execute view for "proj-broken" Then epcov the resolved view should be the default empty ContextView # ---- _path_matches static method ---- Scenario: epcov path matches with no rules passes all When epcov I check path matching for "src/foo.py" with no include or exclude Then epcov the path should match Scenario: epcov path matches with include rule matching When epcov I check path matching for "src/foo.py" with include "src/**/*.py" Then epcov the path should match Scenario: epcov path matches with include rule not matching When epcov I check path matching for "docs/readme.md" with include "src/**/*.py" Then epcov the path should not match Scenario: epcov path matches with exclude rule matching When epcov I check path matching for "src/secret.py" with exclude "src/secret*" Then epcov the path should not match Scenario: epcov path matches with exclude rule not matching When epcov I check path matching for "src/foo.py" with exclude "src/secret*" Then epcov the path should match # ---- Absolute path matching with relative globs (issue #10972) ---- @tdd_issue @tdd_issue_10972 Scenario: epcov path matches absolute path against relative include glob When epcov I check path matching for "/app/.opencode/skills/SKILL.md" with include ".opencode/**" Then epcov the path should match @tdd_issue @tdd_issue_10972 Scenario: epcov path matches absolute path against relative exclude glob When epcov I check path matching for "/app/.opencode/skills/SKILL.md" with exclude ".opencode/**" Then epcov the path should not match @tdd_issue @tdd_issue_10972 Scenario: epcov path matches absolute path against relative include glob with wildcard When epcov I check path matching for "/app/docs/readme.md" with include "docs/*" Then epcov the path should match @tdd_issue @tdd_issue_10972 Scenario: epcov path matches absolute path not matching relative include glob When epcov I check path matching for "/app/src/main.py" with include "docs/*" Then epcov the path should not match @tdd_issue @tdd_issue_10972 Scenario: epcov relative path is excluded by trailing ** glob When epcov I check path matching for "build/debug/output.log" with exclude "build/**" Then epcov the path should not match @tdd_issue @tdd_issue_10972 Scenario: epcov absolute path matched against relative exclude glob When epcov I check path matching for "/app/.opencode/skills/secret.md" with exclude ".opencode/**" Then epcov the path should not match @tdd_issue @tdd_issue_10972 Scenario: epcov absolute path deep subdirectory matches relative glob When epcov I check path matching for "/app/docs/api/endpoint.md" with include "docs/**" Then epcov the path should match @tdd_issue @tdd_issue_10972 Scenario: epcov absolute path excluded by nested relative glob When epcov I check path matching for "/app/vendor/lib/external.py" with exclude "vendor/**" Then epcov the path should not match @tdd_issue @tdd_issue_10972 Scenario: epcov absolute pattern (anchored with /) passed through unchanged When epcov I check path matching for "/src/main.py" with include "/src/**" Then epcov the path should match # ---- _resource_matches static method ---- Scenario: epcov resource matches with no rules passes all When epcov I check resource matching for "res:abc" with no include or exclude Then epcov the resource should match Scenario: epcov resource matches with include rule matching When epcov I check resource matching for "res:abc" with include "res:*" Then epcov the resource should match Scenario: epcov resource matches with include rule not matching When epcov I check resource matching for "other:xyz" with include "res:*" Then epcov the resource should not match Scenario: epcov resource matches with exclude rule matching When epcov I check resource matching for "res:secret" with exclude "res:secret" Then epcov the resource should not match Scenario: epcov resource matches with exclude rule not matching When epcov I check resource matching for "res:abc" with exclude "res:secret" Then epcov the resource should match # ---- _to_context_fragment ---- Scenario: epcov converts tiered fragment with full metadata Given epcov an assembler instance When epcov I convert a tiered fragment with detail_depth 3 and relevance 0.8 Then epcov the core fragment should have detail_depth 3 and relevance 0.8 Scenario: epcov converts tiered fragment with missing metadata defaults Given epcov an assembler instance When epcov I convert a tiered fragment with no detail_depth or relevance Then epcov the core fragment should have detail_depth 1 and relevance 0.5 Scenario: epcov converts tiered fragment with non-int detail_depth Given epcov an assembler instance When epcov I convert a tiered fragment with detail_depth "high" and relevance "bad" Then epcov the core fragment should have detail_depth 1 and relevance 0.5 Scenario: epcov converts tiered fragment clamps relevance to bounds Given epcov an assembler instance When epcov I convert a tiered fragment with relevance 1.5 Then epcov the core fragment should have clamped relevance 1.0 Scenario: epcov converts tiered fragment with negative relevance Given epcov an assembler instance When epcov I convert a tiered fragment with relevance -0.3 Then epcov the core fragment should have clamped relevance 0.0 Scenario: epcov converts tiered fragment with no resource_id uses uko fallback Given epcov an assembler instance When epcov I convert a tiered fragment with empty resource_id Then epcov the core fragment uko_node should start with "uko:" Scenario: epcov converts tiered fragment with path metadata Given epcov an assembler instance When epcov I convert a tiered fragment with path "src/main.py" in metadata Then epcov the core fragment provenance location should be "src/main.py" Scenario: epcov converts tiered fragment with non-string path metadata Given epcov an assembler instance When epcov I convert a tiered fragment with non-string path in metadata Then epcov the core fragment provenance location should be empty # ---- assemble: no project links ---- Scenario: epcov assemble returns None when plan has no project links Given epcov an assembler instance And epcov a plan with no project links When epcov I call assemble on the plan Then epcov the assembled result should be None # ---- assemble: empty scoped view ---- Scenario: epcov assemble returns None when scoped view is empty Given epcov an assembler with scoped view returning empty list And epcov a plan with project links When epcov I call assemble on the plan Then epcov the assembled result should be None # ---- assemble: fragment excluded by missing view ---- Scenario: epcov assemble excludes fragment whose project has no view Given epcov an assembler with views only for "proj-alpha" And epcov a plan with project links for "proj-alpha" and "proj-beta" And epcov scoped fragments for "proj-alpha" and "proj-beta" When epcov I call assemble on the plan Then epcov the assembled result should include only proj-alpha fragments # ---- assemble: resource filtering ---- Scenario: epcov assemble excludes fragment by resource include rules Given epcov an assembler with resource include rule "allowed:*" And epcov a plan with project links And epcov scoped fragments with resource ids "allowed:file" and "denied:file" When epcov I call assemble on the plan Then epcov the assembled result should include only the allowed resource fragment Scenario: epcov assemble excludes fragment by resource exclude rules Given epcov an assembler with resource exclude rule "secret:*" And epcov a plan with project links And epcov scoped fragments with resource ids "public:file" and "secret:file" When epcov I call assemble on the plan Then epcov the assembled result should include only the public resource fragment # ---- assemble: path filtering ---- Scenario: epcov assemble excludes fragment by path include rules Given epcov an assembler with path include rule "src/**" And epcov a plan with project links And epcov scoped fragments with paths "src/main.py" and "docs/readme.md" When epcov I call assemble on the plan Then epcov the assembled result should include only the src fragment Scenario: epcov assemble excludes fragment by path exclude rules Given epcov an assembler with path exclude rule "vendor/**" And epcov a plan with project links And epcov scoped fragments with paths "src/main.py" and "vendor/lib.py" When epcov I call assemble on the plan Then epcov the assembled result should include only the non-vendor fragment Scenario: epcov assemble excludes fragment with no path when include_paths set Given epcov an assembler with path include rule "src/**" And epcov a plan with project links And epcov a scoped fragment with no path metadata When epcov I call assemble on the plan Then epcov the assembled result should be None # ---- assemble: max_file_size filtering ---- Scenario: epcov assemble excludes fragment exceeding max_file_size Given epcov an assembler with max_file_size of 10 bytes And epcov a plan with project links And epcov a scoped fragment with content exceeding 10 bytes When epcov I call assemble on the plan Then epcov the assembled result should be None # ---- assemble: max_total_size filtering ---- Scenario: epcov assemble excludes fragment exceeding max_total_size Given epcov an assembler with max_total_size of 20 bytes And epcov a plan with project links And epcov two scoped fragments each with 15 byte content When epcov I call assemble on the plan Then epcov the assembled result should include only the first fragment # ---- assemble: all filtered out ---- Scenario: epcov assemble returns None when all fragments are filtered out Given epcov an assembler with resource include rule "nonexistent:*" And epcov a plan with project links And epcov scoped fragments with resource ids "other:a" and "other:b" When epcov I call assemble on the plan Then epcov the assembled result should be None # ---- assemble: successful full pipeline ---- Scenario: epcov assemble returns full AssembledContext on success Given epcov an assembler with default policy and pipeline And epcov a plan with project links And epcov scoped fragments that pass all filters When epcov I call assemble on the plan Then epcov the assembled result should be an AssembledContext And epcov the assembled result should have fragments and metadata # ---- _resolve_hot_max_tokens: reads context_policy_json from DB ---- @tdd_issue @tdd_issue_11035 Scenario: epcov assemble uses project-level hot_max_tokens from context_policy_json Given epcov an assembler with context_policy_json hot_max_tokens 32000 And epcov a plan with project links And epcov scoped fragments that pass all filters When epcov I call assemble on the plan Then epcov the pipeline received budget max_tokens of 32000 @tdd_issue @tdd_issue_11035 Scenario: epcov assemble falls back to global hot_max_tokens when context_policy_json has no override Given epcov an assembler with no hot_max_tokens in context_policy_json And epcov a plan with project links And epcov scoped fragments that pass all filters When epcov I call assemble on the plan Then epcov the pipeline received budget max_tokens of 4096 # ---- Default pipeline type ---- Scenario: epcov default pipeline is ContextAssemblyPipeline when none provided Given epcov an assembler with no explicit pipeline argument Then epcov the internal pipeline should be a ContextAssemblyPipeline Scenario: epcov explicit pipeline overrides default ContextAssemblyPipeline Given epcov an assembler with an explicitly passed ACMSPipeline mock Then epcov the internal pipeline should be the explicitly passed mock