# Step 11: reference-comparison-gate ## 읽어야 할 파일 - `AGENTS.md` - `docs/TOLERANCE.md` - `docs/nonlinear-static-newton-raphson/reference-model.md` - `docs/nonlinear-static-newton-raphson/io.md` - `docs/nonlinear-static-newton-raphson/numerical-review.md` - `tests/reference/reference_tolerance_policy.h` - `tests/reference/reference_tolerance_policy.cpp` - `tests/reference/reference_comparison.h` - `tests/reference/reference_comparison.cpp` - `tests/reference/mitc4_reference_comparison.h` - `tests/reference/mitc4_reference_comparison.cpp` - Step 9 files: `include/fesa/results/nonlinear_results_writer.h`, `include/fesa/io/hdf5/nonlinear_hdf5_results_writer.h` - Step 10 files: `include/fesa/analysis/prepared_analysis.h`, `src/fesa/app/fesa_application.cpp` ## 이전 Step 전제 Step 10 runs copied input files through FESA and writes authoritative HDF5 outputs after log close. ## 소유 파일 - Create: `tests/reference/nonlinear_static_reference_comparison.h` - Create: `tests/reference/nonlinear_static_reference_comparison.cpp` - Create: `tests/reference/nonlinear_static_reference_cases_test.cpp` - Modify: `tests/CMakeLists.txt` ## 인터페이스 ```cpp namespace fesa::test { struct NonlinearReferenceCase { std::string case_id; std::filesystem::path original_input_path; std::filesystem::path displacement_csv_path; std::filesystem::path reaction_csv_path; std::filesystem::path stress_inventory_path; std::filesystem::path execution_directory; }; struct ArtifactSnapshot { std::filesystem::path path; std::string sha256; std::uintmax_t byte_size; std::filesystem::file_time_type last_write_time; }; enum class NonlinearReferenceDisposition { kBlocking, kWarningOnly, kExcluded }; struct NonlinearReferenceRowKey { std::string case_id; std::string accepted_state; std::string instance_name; std::int64_t source_node_label; std::string component; }; struct NonlinearReferenceFamilyReport { std::string family_identity; std::vector components; NonlinearReferenceDisposition disposition; std::size_t row_count; ReferenceToleranceFamilyDecision tolerance; }; struct GeneratedRunArtifacts { std::filesystem::path copied_input_path; std::filesystem::path generated_results_hdf5; std::filesystem::path generated_log_path; }; struct NonlinearReferenceComparisonReport { std::string case_id; std::filesystem::path original_input_path; std::filesystem::path copied_input_path; std::filesystem::path generated_results_hdf5; std::filesystem::path generated_log_path; std::vector pre_run_artifacts; std::vector post_run_artifacts; std::vector families; bool blocking_passed; }; enum class NonlinearReferenceClassification { kPassed, kFailed, kWarningOnlyDifferences }; Result> ArtifactCheck( const NonlinearReferenceCase& reference_case); Result CopyInputToExecutionDirectory( const NonlinearReferenceCase& reference_case); Result RunFesaApplicationOnCopiedInput( const NonlinearReferenceCase& reference_case, const std::filesystem::path& copied_input_path); Result CompareHdf5ToReferenceCsv( const NonlinearReferenceCase& reference_case, const std::filesystem::path& hdf5_results_path); NonlinearReferenceClassification ClassifyReferenceComparison( const NonlinearReferenceComparisonReport& report); NonlinearReferenceComparisonReport BuildReferenceComparisonReport( const NonlinearReferenceCase& reference_case, const std::filesystem::path& hdf5_results_path); } // namespace fesa::test ``` ## RED Add tests first. - `NSNR-REF-001`: artifact check verifies exact pre-run SHA-256 for every declared input/CSV path. - `NSNR-REF-002`: original `reference/shellNL/shellNL.inp` bytes are copied unchanged into a unique build-local temp case directory and only the copied `.inp` is passed to `FesaApplication`. - `NSNR-REF-003`: original `reference/shell/shell.inp` bytes are copied unchanged into a unique build-local temp case directory and only the copied `.inp` is passed to `FesaApplication`. - `NSNR-REF-004`: copied shellNL run produces copied-sibling `shellNL_results.h5` and `shellNL_log.txt`; copied shell run produces copied-sibling `shell_results.h5` and `shell_log.txt`. - `NSNR-REF-005`: HDF5 source path identity matches the copied user-addressed input path, and source content identity matches the approved original input hash. - `NSNR-REF-006`: exact post-run SHA-256, byte size, timestamp, and inventory for all original declared reference artifacts match pre-run snapshots. - `NSNR-REF-007`: shellNL displacement/reaction rows require exact `Frame` value `Increment 10: Step Time = 1.000`. - `NSNR-REF-008`: required CSV wide rows expand to unique `(case_id, accepted_state, instance, source_node_label, component)` keys. - `NSNR-REF-009`: HDF5 rows and CSV rows reject missing, extra, duplicate, and nonfinite required rows before tolerance. - `NSNR-REF-010`: `linear.translation` has 147 blocking rows. - `NSNR-REF-011`: `linear.rotation` has 147 warning-only rows. - `NSNR-REF-012`: `nonlinear.translation` has 147 blocking rows. - `NSNR-REF-013`: `nonlinear.rotation` has 147 warning-only rows. - `NSNR-REF-014`: shellNL constrained nodes select only labels `1,3,4,5,6,7,8,9,14,15,16,17,22,23,24,25,26,27,28,29,30,31,32,33`. - `NSNR-REF-015`: `RF1/RF2` has 48 blocking rows, `RF3` has 24 blocking rows, and `RM1/RM2` has 48 blocking rows. - `NSNR-REF-016`: `RM3` and stress quantities create no numeric comparison family. - `NSNR-REF-017`: docs/TOLERANCE.md family policy is applied exactly and warning-only failures do not change blocking verdict. - `NSNR-REF-018`: stress CSV files are hash-audited as nonblocking inventory artifacts and their schema/order is not a blocking verdict. Run: ```powershell cmake --build .harness/build --config Debug ctest --test-dir .harness/build -C Debug -R "NonlinearStaticReference|ReferenceTolerance|Mitc4Reference" --output-on-failure ``` Expected: new tests fail. Unexpected pass stops. ## GREEN Implement `ARTIFACT CHECK -> COPY -> RUN -> COMPARE -> CLASSIFY -> REPORT` while preserving the required public gate wording `ARTIFACT CHECK -> COMPARE -> CLASSIFY -> REPORT` in reports. The runner never passes the original reference input path to `FesaApplication`; it copies input bytes unchanged into a unique build-local temp case directory, runs the copied `.inp`, consumes copied-sibling `_results.h5` and `_log.txt`, and compares HDF5 data to original read-only CSVs. Use exact declared paths and hashes: | path | rows | SHA-256 | | --- | ---: | --- | | `reference/shellNL/shellNL.inp` | input | `4BF3ECB0F7F1E8462C573E993DBC97AC5D920C91CF6F23AD4C6891D77FFBADA2` | | `reference/shellNL/shellNL displacements.csv` | 49 | `4E0F99CA9372B1ADF7FAF102F43BC0B887DC743FDEDA378E4342D2CF8E0C0786` | | `reference/shellNL/shellNL reactions.csv` | 49 | `001CB1541A9E94424E5E650509D46BC8724970DF4DE47184D9DB09C7938AB069` | | `reference/shellNL/shellNL stresses.csv` | 288 | `5500E5114B1C44887528E30CEC054A1EB0F68BE3F4B8CE81FA59FC74A881483F` | | `reference/shell/shell.inp` | input | `4005851E1AB22FD3A16AC17A8D5DA3E051233F69F37419079F3553AD134ECFCF` | | `reference/shell/shell displacements.csv` | 49 | `C81D94E0B4A849F87AA0F79C83A79B94D5661AC79E44ED826919AB432C87746B` | | `reference/shell/shell reactions.csv` | 49 | `0E34EEC27E700C3C0C744C1DAFD8A3B95EFEF34B8616FE96665876586FE82D41` | | `reference/shell/shell stresses.csv` | 288 | `2B75A5B0DEB045A283C9BB7E9B1153B79F7537FF487214BF4A23316B59B660A7` | Use docs/TOLERANCE.md exactly: family scale `S=max(abs(reference))`, near-zero band `0.01*S`, non-near relative error `<=0.05`, family `RMS(error)/S<=0.01`, zero-scale exact zero only. Original reference directory inventory, bytes, timestamps, and hashes must be unchanged after the run. ## VERIFY ```powershell cmake --fresh -S . -B .harness/build -G "Visual Studio 18 2026" -A x64 ` "-DFESA_GTEST_SOURCE_DIR=$gtestSource" ` "-DMKL_DIR=$mklDir" ` "-DTBB_DIR=$tbbDir" ` "-DHDF5_DIR=$hdf5Dir" cmake --build .harness/build --config Debug ctest --test-dir .harness/build -C Debug -R "NonlinearStaticReference|ReferenceTolerance|Mitc4Reference" --output-on-failure ctest --test-dir .harness/build -C Debug --show-only=json-v1 ctest --test-dir .harness/build -C Debug --output-on-failure ``` Recheck `.harness/config.json` before default commands. ## 상태 기록 Update only Step 11 status and one-line payload. Executor owns timestamps, commits, retry, and advancement. ## 금지사항 - Do not rewrite, rename, normalize, or repair `.inp` or CSV artifacts. 이유: reference artifacts are immutable external evidence. - Do not run `FesaApplication` on original `reference/shellNL/shellNL.inp` or `reference/shell/shell.inp`. 이유: CLI derives sibling outputs and would mutate the reference directory. - Do not compare `RM3`. 이유: approved contract excludes stabilization-dependent drilling reaction. - Do not numerically compare stress CSV data. 이유: stress artifacts are nonblocking inventory only in this feature. - Do not average, omit, synthesize, or row-order match reference rows. 이유: source/component identity prechecks are mandatory.