805a06197b
Phase 2: Fix flat_config to return typed ProjectContext (FR8 / VC8)
Before: def flat_config(...) -> Metadata (returned dict[str, Any])
After: def flat_config(...) -> ProjectContext (typed fat struct)
Delta: -1 anonymous dict return type; +6 new dataclasses
Per SPEC_CORRECTION_phase_2.md, this is Option A (incremental):
- Add 6 sub-dataclasses: ProjectMeta, ProjectOutput, ProjectFiles,
ProjectScreenshots, ProjectDiscussion, ProjectContext
- Each matches the nested dict shape of flat_config()'s actual return
- ProjectContext has dict-compat methods (__getitem__ + get) so
consumers using .get() / [] continue to work unchanged
- ProjectContext.to_dict() returns the legacy dict shape for migration
- EMPTY_PROJECT_CONTEXT sentinel exported
File locations per spec:
- src/models.py: 6 new dataclasses + EMPTY_PROJECT_CONTEXT sentinel
- src/project_manager.py: flat_config body rewritten to construct
ProjectContext from the proj dict (typed return type)
- tests/test_project_context_20260627.py: NEW regression-guard test file
with 10 tests covering: imports, return type, zero defaults, full
input, dict-compat __getitem__/get, to_dict round-trip, sentinel,
output_dir required field, consumer patterns unchanged
Verification:
- audit_weak_types --strict: OK (96 <= 112 baseline; down from 107)
- generate_type_registry: 23 files regenerated
- 10 test_project_context_20260627 tests PASS
- All existing consumer tests pass (test_context_composition_decoupled: 2,
test_orchestrator_pm: 3, test_orchestration_logic: 8,
test_orchestrator_pm_history + test_context_preview_button: 7,
test_project_manager_tracks: 4, test_track_state_persistence: 1)
VC8 (corrected) verification:
- flat_config returns ProjectContext (typed) ✓
- All 6 sub-dataclasses exist + importable ✓
- Dict-compat methods (ctx["key"], ctx.get("key")) work ✓
- output_dir REQUIRED field defaults to "" (empty, but valid) ✓
- Consumer patterns (ctx.get("output", {}).get("namespace", "project"))
work unchanged via dict-compat ✓
Phase 2 IS COMPLETE.