# Step 1: core-primitives ## 읽어야 할 파일 먼저 아래 파일들을 읽고 프로젝트의 아키텍처와 이전 step 산출물을 파악하라: - `/AGENTS.md` - `/docs/PRD.md` - `/docs/ARCHITECTURE.md` - `/docs/ADR.md` - `/CMakeLists.txt` - `/tests/unit/CMakeLists.txt` 이전 step에서 만들어진 CMake/CTest 구성을 꼼꼼히 읽고, 새 unit test가 자동 등록되는 방식과 일관성을 유지하라. ## 작업 solver skeleton의 공통 primitive를 `/src/fesa/core/` 아래 header-only로 구현한다. 필수 파일: - `/src/fesa/core/ids.hpp` - `/src/fesa/core/diagnostic.hpp` - `/src/fesa/core/status.hpp` - `/tests/unit/core_primitives_test.cpp` 필수 interface: ```cpp namespace fesa::core { struct NodeId { int value; }; struct ElementId { int value; }; struct MaterialId { int value; }; struct PropertyId { int value; }; struct StepId { int value; }; enum class Severity { info, warning, error }; struct Diagnostic { Severity severity; std::string code; std::string message; }; class Status { public: static Status ok(); static Status failure(Diagnostic diagnostic); bool is_ok() const; const std::vector& diagnostics() const; void add(Diagnostic diagnostic); }; } // namespace fesa::core ``` 구현 규칙: - 모든 ID type은 strong typedef 역할을 하며 서로 암시적으로 대체되지 않아야 한다. - ID에는 equation id 또는 DOF numbering 정보를 넣지 않는다. - `Status::ok()`는 diagnostics가 비어 있고 `is_ok() == true`여야 한다. - `Status::failure(...)`는 최소 하나의 diagnostic을 포함하고 `is_ok() == false`여야 한다. - 외부 라이브러리에 의존하지 않는다. ## Tests To Write First - `/tests/unit/core_primitives_test.cpp` - `NodeId{1}`과 `ElementId{1}`이 서로 다른 타입임을 compile-time으로 확인한다. - `Status::ok().is_ok()`가 true임을 확인한다. - `Status::failure(...)`가 false이고 diagnostic code/message를 보존함을 확인한다. - `Status::add(...)`로 warning을 추가해도 diagnostic 순서가 보존됨을 확인한다. RED 확인: 1. 테스트 파일을 먼저 작성한다. 2. `python scripts/validate_workspace.py` 또는 targeted CTest를 실행해 `fesa/core/ids.hpp` 등 missing include로 실패함을 확인한다. 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 core_primitives_test ``` ## 검증 절차 1. 위 AC 커맨드를 실행한다. 2. 아키텍처 체크리스트를 확인한다: - `core`가 외부 라이브러리에 의존하지 않는가? - ID type에 equation numbering을 저장하지 않는가? - C++ production header 변경에 대응하는 test file이 있는가? 3. 결과에 따라 `phases/solver-core-skeleton/index.json`의 step 1을 업데이트한다: - 성공: `"status": "completed"`, `"summary": "Core ID, diagnostic, and status primitives added with tests"` - 3회 수정 시도 후 실패: `"status": "error"`, `"error_message": "구체적 에러 내용"` - 사용자 개입 필요: `"status": "blocked"`, `"blocked_reason": "구체적 사유"` 후 중단 ## 금지사항 - Node, Element, Domain 같은 model class를 이 step에서 만들지 마라. - MKL, TBB, HDF5 API를 include하지 마라. - JavaScript/TypeScript/npm fallback을 추가하지 마라.