# Step 6: analysis-template-flow ## 읽어야 할 파일 먼저 아래 파일들을 읽고 프로젝트의 아키텍처와 이전 step 산출물을 파악하라: - `/AGENTS.md` - `/docs/PRD.md` - `/docs/ARCHITECTURE.md` - `/docs/ADR.md` - `/src/fesa/analysis/analysis_model.hpp` - `/src/fesa/analysis/analysis_state.hpp` - `/src/fesa/fem/dof_manager.hpp` - `/tests/unit/analysis_state_vectors_test.cpp` 이전 step에서 만들어진 AnalysisModel, DofManager, AnalysisState를 꼼꼼히 읽고, ARCHITECTURE.md의 Template Method 실행 흐름과 일관성을 유지하라. ## 작업 공통 해석 실행 흐름을 고정하는 `Analysis` base class와 선형 정적 해석 skeleton을 `/src/fesa/analysis/`에 구현한다. 필수 파일: - `/src/fesa/analysis/analysis.hpp` - `/src/fesa/analysis/linear_static_analysis.hpp` - `/tests/unit/analysis_flow_template_test.cpp` 필수 interface: ```cpp namespace fesa::analysis { class Analysis { public: virtual ~Analysis() = default; void run(); protected: virtual void initialize() {} virtual void build_analysis_model() {} virtual void build_dof_map() {} virtual void build_sparse_pattern() {} virtual void assemble() {} virtual void apply_boundary_conditions() {} virtual void solve() {} virtual void update_state() {} virtual void write_results() {} }; class LinearStaticAnalysis : public Analysis { public: LinearStaticAnalysis(const model::Domain& domain, core::StepId step_id); const AnalysisModel* analysis_model() const; const AnalysisState* state() const; protected: void build_analysis_model() override; void build_dof_map() override; void update_state() override; }; } // namespace fesa::analysis ``` 구현 규칙: - `Analysis::run()`은 반드시 다음 순서로 hook을 호출한다: `initialize -> build_analysis_model -> build_dof_map -> build_sparse_pattern -> assemble -> apply_boundary_conditions -> solve -> update_state -> write_results` - `LinearStaticAnalysis`는 skeleton 단계에서 실제 stiffness assembly나 solve를 하지 않는다. - `LinearStaticAnalysis::build_analysis_model()`은 `AnalysisModel`을 생성한다. - `LinearStaticAnalysis::build_dof_map()`은 active element connectivity에서 등장한 node에 `ux`, `uy`, `uz`를 정의하고 active BC를 적용한 뒤 equation numbering을 수행한다. - `LinearStaticAnalysis::update_state()`는 total DOF count 크기의 `AnalysisState`를 준비한다. - MKL, TBB, HDF5 adapter는 만들지 않는다. ## Tests To Write First - `/tests/unit/analysis_flow_template_test.cpp` - test-only derived `RecordingAnalysis`가 hook 호출 순서를 vector에 기록한다. - `run()` 호출 후 ARCHITECTURE.md 순서와 정확히 일치하는지 확인한다. - 최소 Domain과 Step으로 `LinearStaticAnalysis`를 실행하면 `analysis_model()`과 `state()`가 null이 아니게 되는지 확인한다. - `LinearStaticAnalysis`가 실제 solver 결과를 계산한다고 주장하지 않음을 테스트 이름과 assertion 범위에 반영한다. RED 확인: 1. 테스트 파일을 먼저 작성한다. 2. targeted CTest를 실행해 missing `analysis.hpp` 또는 `linear_static_analysis.hpp`로 실패함을 확인한다. 3. 그 뒤 production headers를 작성한다. ## 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 analysis_flow_template_test ``` ## 검증 절차 1. 위 AC 커맨드를 실행한다. 2. 아키텍처 체크리스트를 확인한다: - Analysis::run()이 Template Method 흐름을 고정하는가? - LinearStaticAnalysis가 skeleton 범위를 넘어 solver backend를 구현하지 않는가? - 외부 라이브러리 API가 solver core에 노출되지 않는가? 3. 결과에 따라 `phases/solver-core-skeleton/index.json`의 step 6을 업데이트한다: - 성공: `"status": "completed"`, `"summary": "Analysis template method and LinearStaticAnalysis skeleton added"` - 3회 수정 시도 후 실패: `"status": "error"`, `"error_message": "구체적 에러 내용"` - 사용자 개입 필요: `"status": "blocked"`, `"blocked_reason": "구체적 사유"` 후 중단 ## 금지사항 - 실제 stiffness matrix assembly, linear solve, MKL PARDISO adapter를 구현하지 마라. - HDF5 writer를 구현하지 마라. - JavaScript/TypeScript/npm fallback을 추가하지 마라.