Replace CliRunner + unittest.mock.patch with subprocess.run for all
21 CLI-facing test functions across the M1-M6 E2E verification helpers.
Application code fixes:
- action.py: _get_lifecycle_service() uses container.plan_lifecycle_service()
- plan.py: _get_lifecycle_service() uses container.plan_lifecycle_service()
- plan.py: three container.resolve(DecisionService) → container.decision_service()
Test infrastructure:
- New robot/helper_e2e_common.py with shared subprocess utilities
(run_cli, setup_workspace with DB migrations, cleanup_workspace)
- M1-M4, M6 helpers refactored to use run_cli() with real SQLite DB
- M5 unchanged (0 CLI tests, all domain-level)
- TDD detection updated to recognise run_cli() as subprocess invocation
- Remove @tdd_expected_fail from TDD feature + robot tags
- Update 8 Behave step files that mocked container.resolve() to use
container.decision_service() / container.plan_lifecycle_service()
Core domain types (FragmentProvenance, ContextFragment, ContextBudget,
ContextPayload) now extend their CRP counterparts via Pydantic v2
inheritance, ensuring isinstance compatibility across the model
hierarchy.
Key changes:
- CRP base types made frozen=True (no consumer mutates them)
- CRP AssembledContext fields changed from list to tuple (frozen consistency)
- Core types extend CRP bases: FragmentProvenance(CRPFragmentProvenance),
ContextFragment(CRPContextFragment), ContextBudget(CRPContextBudget),
ContextPayload(CRPAssembledContext)
- Removed duplicate ContextFragment dataclass from skeleton_compressor
- Updated project_context.py to pass tuples to frozen AssembledContext
- Added Behave tests (10 scenarios), Robot integration tests (3 cases),
and ASV benchmarks for the unified hierarchy
- Updated Known Limitations table in docs/reference/acms.md
ISSUES CLOSED: #569