# Step 1: Domain Validation

## 읽어야 할 파일

- `/AGENTS.md`
- `/docs/PRD.md`
- `/docs/ARCHITECTURE.md`
- `/docs/ADR.md`
- `/docs/superpowers/plans/2026-07-29-fesa-phase-1.md`
- `/include/fesa/model/`
- `/tests/unit/model/`

이전 step의 타입 이름과 필드를 변경하지 말고 builder validation을 추가하라.

## 작업

`DomainBuilder`가 모든 semantic entity를 검증한 뒤 불변 `Domain` 하나를 생성하게
한다.

```cpp
struct DomainBuildResult final {
    std::optional<Domain> domain;
    std::vector<Diagnostic> diagnostics;
};

class DomainBuilder final {
public:
    void add_node(Node);
    void add_material(IsotropicElastic);
    void add_section(BeamSection);
    void add_beam_element(BeamElement);
    void add_node_set(NodeSet);
    void add_element_set(ElementSet);
    void set_step(StepDefinition);
    [[nodiscard]] DomainBuildResult build() &&;
};
```

- 중복 internal ID, 중복 origin, missing reference, invalid \(E,\nu,A,I,J,A_s\),
  nonfinite 값, zero-length element, invalid orientation, section/material 누락,
  충돌 BC를 각각 실패 테스트로 먼저 작성한다.
- 내부 dense lookup과 origin lookup을 만들되 public mutable access는 제공하지 않는다.

## Acceptance Criteria

```powershell
cmake --build --preset windows-debug
ctest --preset windows-debug -R "DomainBuilder|DomainValidation" --output-on-failure
ctest --preset windows-debug --output-on-failure
```

## 검증 절차

1. 각 거부 조건의 실패 테스트를 먼저 확인한다.
2. 하나의 오류가 다른 오류를 숨기지 않도록 가능한 진단을 수집한다.
3. valid Domain test와 전체 CTest를 실행한다.
4. index summary에 검증 규칙과 생성 파일을 기록한다.

## 금지사항

- 잘못된 입력값을 자동 보정하지 마라. 이유: explicit diagnostic 계약을 위반한다.
- solver 또는 parser validation을 이 builder에 넣지 마라. 이유: 모듈 책임이 다르다.
- mutable Domain accessor를 추가하지 마라. 이유: 해석 중 모델 불변성을 깨뜨린다.
