# Step 7: results-containers ## 읽어야 할 파일 먼저 아래 파일들을 읽고 프로젝트의 아키텍처와 이전 step 산출물을 파악하라: - `/AGENTS.md` - `/docs/PRD.md` - `/docs/ARCHITECTURE.md` - `/docs/ADR.md` - `/src/fesa/analysis/analysis_state.hpp` - `/src/fesa/analysis/analysis.hpp` - `/tests/unit/analysis_flow_template_test.cpp` 이전 step에서 만들어진 AnalysisState와 Analysis flow를 꼼꼼히 읽고, 결과 container가 HDF5 API에 직접 의존하지 않도록 유지하라. ## 작업 HDF5 writer 구현 전 단계의 results data model skeleton을 `/src/fesa/results/`에 구현한다. 필수 파일: - `/src/fesa/results/results.hpp` - `/tests/unit/results_containers_test.cpp` 필수 interface: ```cpp namespace fesa::results { enum class FieldLocation { nodal, element, integration_point }; struct FieldOutput { std::string name; FieldLocation location; std::vector components; std::vector entity_ids; std::vector values; }; struct HistoryOutput { std::string name; std::vector time; std::vector values; }; class ResultFrame { public: ResultFrame(int frame_id, double time); int frame_id() const; double time() const; void add_field_output(FieldOutput output); void add_history_output(HistoryOutput output); const std::vector& field_outputs() const; const std::vector& history_outputs() const; }; class ResultStep { public: explicit ResultStep(std::string name); const std::string& name() const; ResultFrame& add_frame(int frame_id, double time); const std::vector& frames() const; }; } // namespace fesa::results ``` 구현 규칙: - Result hierarchy는 `ResultStep -> ResultFrame -> FieldOutput/HistoryOutput` 구조를 따른다. - Field output은 row identity를 위해 `entity_ids`를 보존한다. - Field output values layout은 skeleton 단계에서 row-major flat vector로 둔다. - HDF5 file/dataset, schema writer, CSV export는 구현하지 않는다. - validation은 크기 consistency만 최소로 확인한다: - `components`가 비어 있으면 `std::invalid_argument` - `entity_ids.size() * components.size() == values.size()`가 아니면 `std::invalid_argument` ## Tests To Write First - `/tests/unit/results_containers_test.cpp` - ResultStep이 이름과 frame 목록을 보존한다. - ResultFrame이 frame id/time을 보존한다. - nodal displacement FieldOutput을 추가하면 components/entity ids/values가 보존된다. - invalid FieldOutput shape가 `std::invalid_argument`를 던진다. - HistoryOutput이 time/value series를 보존한다. RED 확인: 1. 테스트 파일을 먼저 작성한다. 2. targeted CTest를 실행해 missing `results.hpp`로 실패함을 확인한다. 3. 그 뒤 production header를 작성한다. ## Acceptance Criteria ```powershell python -m unittest discover -s scripts -p "test_*.py" python scripts/validate_workspace.py ctest --test-dir build/msvc-debug --output-on-failure -C Debug -R results_containers_test ``` ## 검증 절차 1. 위 AC 커맨드를 실행한다. 2. 아키텍처 체크리스트를 확인한다: - Results hierarchy가 ARCHITECTURE.md와 일치하는가? - HDF5 API가 results container에 직접 노출되지 않는가? - reference comparison을 위한 entity row identity가 보존되는가? 3. 결과에 따라 `phases/solver-core-skeleton/index.json`의 step 7을 업데이트한다: - 성공: `"status": "completed"`, `"summary": "ResultStep, ResultFrame, FieldOutput, and HistoryOutput containers added"` - 3회 수정 시도 후 실패: `"status": "error"`, `"error_message": "구체적 에러 내용"` - 사용자 개입 필요: `"status": "blocked"`, `"blocked_reason": "구체적 사유"` 후 중단 ## 금지사항 - HDF5 writer/reader를 구현하지 마라. - deterministic CSV export를 구현하지 마라. - JavaScript/TypeScript/npm fallback을 추가하지 마라.