feat(nonlinear-static-newton-raphson): step 11 - equilibrium-projection-and-reference-gate

This commit is contained in:
KOKO\Mimi
2026-08-28 09:22:33 +09:00
parent 65b56b1755
commit 6dbf1b2bcf
30 changed files with 13122 additions and 728 deletions
@@ -134,6 +134,10 @@ Add tests first.
- `NSNR-PROC-017`: failed nonlinear run preserves prior final HDF5 according to output lifecycle.
- `NSNR-PROC-018`: deterministic repeat produces same sparse structure, nodal source-identity order, result row order, diagnostics, and log line ordering.
### USER-DECISION-003 option-1 revision addendum
Step 10의 completed status, summary, timestamps와 commits는 보존한다. Existing procedure는 same-trial free residual/internal/external vectors를 force와 moment channel별로 분리하여 `EvaluateNewtonConvergence`에 전달하고 fresh same-iteration correction을 별도로 전달한다. 따라서 option 1의 production correction은 Step 11의 `nonlinear_static_control.cpp`에 한정하며 `nonlinear_static_procedure.cpp`, prepared-analysis API와 log writer production 변경은 예상하지 않는다. Step 11의 shellNL copied-input run과 log assertions이 unloaded rotational external channel의 exact-zero branch, loaded force channel의 retained relative branch, four-channel AND 및 intended factors `0.1..1.0`을 integration 수준에서 검증한다.
Run:
```powershell
@@ -171,3 +175,4 @@ Update only Step 10 status and one-line payload. Executor owns timestamps, commi
- Do not insert nonlinear branches into `LinearStaticAnalysis` private lifecycle. 이유: new procedure owns its own lifecycle.
- Do not replace final HDF5 on failed analysis, log failure, or HDF5 failure. 이유: asymmetric preservation contract requires prior valid final preservation.
- Do not construct MKL/TBB/HDF5 backends inside procedure executors. 이유: dependencies are injected so tests can observe lifecycle and no backend type crosses analysis/core public boundaries.
- Do not duplicate the option-1 selector in the procedure or log writer. 이유: the existing procedure already transports the three residual vectors separately and convergence ownership remains in `nonlinear_static_control`.
+334 -116
View File
@@ -1,79 +1,143 @@
# Step 11: reference-comparison-gate
# Step 11: equilibrium-projection-and-reference-gate
## 목적
USER-DECISION-004 option 1과 `AUDIT-001`을 구현·검증한다. 같은 accepted factor-one state에서
accepted free residual, constrained reaction resultant, global applied-plus-reaction balance error를
서로 다른 quantity로 재구성하고, 기존 schema-v1 `/global/equilibrium`에는 balance error만 저장한다.
Fine nonlinear case는 primary, coarse nonlinear case는 companion으로 검증한다. Local nodal
`RF1/RF2/RF3`와 physical spatial `RM1/RM2`는 deterministic review-only evidence이고 blocking
verdict를 바꾸지 않는다. Global force와 moment balance는 각각 fixed normalized `<=1e-8`
comparator gate를 사용하며 runtime configuration 또는 product solver acceptance로 노출하지 않는다.
## 읽어야 할 파일
- `AGENTS.md`
- `docs/PRD.md`
- `docs/ARCHITECTURE.md`
- `docs/ADR.md`
- `docs/CODINGSTYLE.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`
- `docs/nonlinear-static-newton-raphson/requirements.md`
- `docs/nonlinear-static-newton-raphson/research.md`
- `docs/nonlinear-static-newton-raphson/formulation.md` §§11.4, 13.1, 13.4, 14.1
- `docs/nonlinear-static-newton-raphson/numerical-review.md` §§3.2, 6.2, 6.3
- `docs/nonlinear-static-newton-raphson/reference-model.md` §§3–6
- `docs/nonlinear-static-newton-raphson/io.md` §§7.3–7.5.1, 8.1–8.7
- `docs/nonlinear-static-newton-raphson/implementation-plan.md`
- `docs/nonlinear-static-newton-raphson/corrections.md` §13
- `phases/nonlinear-static-newton-raphson/index.json`
- `include/fesa/analysis/nonlinear_analysis_state.h`
- `include/fesa/analysis/nonlinear_static_procedure.h`
- `include/fesa/analysis/nonlinear_static_control.h`
- `src/fesa/analysis/nonlinear_static_procedure.cpp`
- `src/fesa/analysis/nonlinear_static_control.cpp`
- `include/fesa/results/nonlinear_results_writer.h`
- `include/fesa/io/hdf5/nonlinear_hdf5_results_writer.h`
- `src/fesa/io/hdf5/nonlinear_hdf5_results_writer.cpp`
- `tests/integration/analysis/nonlinear_static_procedure_test.cpp`
- `tests/unit/io/hdf5/nonlinear_hdf5_results_writer_test.cpp`
- `tests/unit/analysis/nonlinear_static_control_test.cpp`
- `tests/unit/analysis/newton_iteration_log_test.cpp`
- `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`
- `tests/reference/nonlinear_static_reference_comparison.h`
- `tests/reference/nonlinear_static_reference_comparison.cpp`
- `tests/reference/nonlinear_static_reference_cases_test.cpp`
- `tests/CMakeLists.txt`
- `.harness/config.json`
- `CMakePresets.json`
## 이전 Step 전제
## 이전 Step과 보존 전제
Step 10 runs copied input files through FESA and writes authoritative HDF5 outputs after log close.
- Steps 0–10은 completed다. 그 status, summary, timestamp, commit 또는 구현을 replay, amend,
reset하거나 다시 작성하지 않는다.
- 현재 worktree의 `NSNR-CTRL-018..021`, `NSNR-LOG-012`, `NSNR-PROC-019`,
`NSNR-HDF5-014`, residual-selector GREEN과 `NSNR-REF-001..023` comparator/CMake 작업은
이전 blocked Step 11에서 생성된 보존 대상이다. 삭제·재생성·reset하지 말고 현재 내용에서
계속한다.
- 현재 comparator의 shared `<=1e-10` global force/moment gate는 이전 blocker를 재현하는
보존된 implementation state다. 새 RED가 approved between-threshold metric을 거부하는 것을
증명한 뒤 comparator 내부 gate만 `<=1e-8`로 변경한다.
- Selector RED는 이미 과거 실행 evidence에 속한다. 이 재실행에서 selector RED를 fabricate하거나
다시 실패시키지 않는다. 기존 테스트가 계속 green인지 focused VERIFY에서 확인한다.
- Step 12는 pending이며 이 Step에서 시작하지 않는다.
## 소유 파일
- 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`
RED test를 먼저 추가한 뒤 필요한 production file만 최소 수정한다.
## 인터페이스
- Modify test first: `tests/integration/analysis/nonlinear_static_procedure_test.cpp`
- Modify test first: `tests/unit/io/hdf5/nonlinear_hdf5_results_writer_test.cpp`
- Preserve and extend test-private comparator: `tests/reference/nonlinear_static_reference_comparison.h`
- Preserve and extend test-private comparator: `tests/reference/nonlinear_static_reference_comparison.cpp`
- Preserve and extend tests: `tests/reference/nonlinear_static_reference_cases_test.cpp`
- Preserve existing registration; edit only if the current sources are not registered:
`tests/CMakeLists.txt`
- Minimal GREEN: `src/fesa/analysis/nonlinear_static_procedure.cpp`
- Minimal GREEN: `src/fesa/io/hdf5/nonlinear_hdf5_results_writer.cpp`
- Preserve existing partial GREEN/tests without redesign:
`src/fesa/analysis/nonlinear_static_control.cpp`,
`tests/unit/analysis/nonlinear_static_control_test.cpp`,
`tests/unit/analysis/newton_iteration_log_test.cpp`
No public header, new CMake target, new HDF5 dataset, schema-version change or reference artifact is
owned by this Step.
## Authoritative HDF5 입력과 test-private report 경계
Comparator는 아래 existing schema-v1 paths만 읽는다.
```text
/model/nodes [node_count]
/model/nodal_constraint_mask [node_count,6]
/steps/Step-1/accepted_frames unique factor-one row
/steps/Step-1/frames/<frame>/nodal/displacement [node_count,6]
/steps/Step-1/frames/<frame>/nodal/generalized_internal_force [node_count,6]
/steps/Step-1/frames/<frame>/nodal/generalized_external_force [node_count,6]
/steps/Step-1/frames/<frame>/nodal/generalized_residual [node_count,6]
/steps/Step-1/frames/<frame>/nodal/reaction [node_count,6]
/steps/Step-1/frames/<frame>/global/equilibrium [6]
```
`/global/equilibrium` component order is
`FORCE_1,FORCE_2,FORCE_3,MOMENT_1,MOMENT_2,MOMENT_3` and its required
`location` is `global-balance-error`.
Preserve the current test-private types and make only the extensions needed by the approved
dispositions and distinct internal evidence. Add the required standard `<array>` and `<optional>`
includes to the test-private header. Candidate signature-level shape:
```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
kReviewOnly,
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 {
struct NonlinearReferencePrecheckFinding {
std::string family_identity;
std::vector<std::string> components;
NonlinearReferenceDisposition disposition;
std::size_t row_count;
ReferenceToleranceFamilyDecision tolerance;
std::string diagnostic_code;
std::vector<NonlinearReferenceRowKey> affected_keys;
};
struct GeneratedRunArtifacts {
std::filesystem::path copied_input_path;
std::filesystem::path generated_results_hdf5;
std::filesystem::path generated_log_path;
struct NonlinearInternalEquilibriumReport {
std::string family_identity;
std::size_t row_count;
double numerator;
double scale;
std::optional<double> normalized_metric;
bool passed;
std::string diagnostic_code;
};
struct ConstrainedReactionResultantReport {
std::array<double, 3> force;
std::array<double, 3> moment;
};
struct NonlinearReferenceComparisonReport {
@@ -85,103 +149,257 @@ struct NonlinearReferenceComparisonReport {
std::vector<ArtifactSnapshot> pre_run_artifacts;
std::vector<ArtifactSnapshot> post_run_artifacts;
std::vector<NonlinearReferenceFamilyReport> families;
std::vector<NonlinearReferencePrecheckFinding> precheck_findings;
std::vector<NonlinearInternalEquilibriumReport> internal_equilibrium;
ConstrainedReactionResultantReport constrained_reaction_resultant;
bool external_blocking_passed;
bool internal_blocking_passed;
bool blocking_passed;
};
enum class NonlinearReferenceClassification {
kPassed,
kFailed,
kWarningOnlyDifferences
};
Result<std::vector<ArtifactSnapshot>> ArtifactCheck(
const NonlinearReferenceCase& reference_case);
Result<std::filesystem::path> CopyInputToExecutionDirectory(
const NonlinearReferenceCase& reference_case);
Result<GeneratedRunArtifacts> RunFesaApplicationOnCopiedInput(
const NonlinearReferenceCase& reference_case,
const std::filesystem::path& copied_input_path);
Result<NonlinearReferenceComparisonReport> 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
```
These are test-support interfaces only. Match the existing aggregate/data style and avoid a public
solver API. For an exact-zero internal scale, leave `normalized_metric` empty and use
`diagnostic_code` plus the exact-zero numerator/pass rule instead of writing NaN or Inf.
## Required physical algorithm
For each node in stable Domain order at the accepted state:
1. Read `X` from Domain/model identity and `u, phi` from the accepted state. Set `x=X+u`.
2. Read generalized applied force/covector from `generalized_external_force`.
3. Build constrained generalized reaction by applying the exact component mask to
`generalized_residual` before any rotational conversion.
4. Convert applied and constrained-reaction rotational covectors independently with
`InverseTransposeLeftJacobianSO3(phi)`. Do not convert their sum as a shortcut and do not mix
free generalized residual into reaction.
5. Accumulate, about global origin `[0,0,0]`:
```text
F_applied += applied spatial force
M_applied += x cross F_applied_node + applied spatial physical moment
F_reaction += constrained reaction spatial force
M_reaction += x cross F_reaction_node + reaction spatial physical moment
global balance error = [F_applied + F_reaction,
M_applied + M_reaction]
```
Store only the six-component balance error in the existing accepted-frame
`global_equilibrium` and existing `/global/equilibrium` dataset. Reconstruct the constrained
reaction resultant and accepted free residual separately in the comparator; do not add summary
datasets or a public header.
For internal blocking gates:
- Force scale is `max(sum(||F_applied_node||2), sum(||F_reaction_node||2))`.
- Moment scale is
`max(sum(||x cross F_applied_node + M_applied_node||2),
sum(||x cross F_reaction_node + M_reaction_node||2))`.
- Force and moment use separate `||balance_error||2/scale <= 1e-8` gates. If scale is exact zero,
only exact-zero balance passes. No floor, `max(1,scale)` or clamp is allowed.
- Accepted free translation-force and rotation-moment rows use the exact free mask and reproduce
NSNR-069: nonzero matching external scale uses
`||residual||inf/max(||internal||inf,||external||inf) <= 1e-2`; exact-zero external scale uses
typed absolute `<=1e-3`. Finite checks occur first.
- `docs/TOLERANCE.md` is not used for these internal gates.
## RED
Add tests first.
기존 dirty `NSNR-PROC-019`, `NSNR-HDF5-014`, `NSNR-REF-020..023`은 재작성하지 않는다.
먼저 existing `NSNR-REF-022`를 실행해 old shared gate failure를 다시 관찰·기록한 뒤,
`NSNR-REF-024..025`를 comparator threshold 변경 전에 test-first로 추가한다. Procedure/HDF5
behavior는 threshold rework를 위해 추가 변경하지 않는다.
- `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.
- Approved draft label `NSNR-PROC-011` collides with completed Step 10's historical
`NSNR-PROC-011` increment-loop identity. Preserve that history and use collision-resolved test ID
`NSNR-PROC-019` with exact GTest symbol
`NonlinearStaticProcedure.NonzeroPrescribedMotionWritesCurrentArmSpatialAppliedPlusReactionBalance`.
Use a supported nonlinear shell input with nonzero prescribed translation and rotation plus a
resolved fixed-global load. Independently reconstruct the six balance components from accepted
`X,u,phi`, external force and masked residual. Expected RED: the current helper uses initial
coordinates, raw full-residual summation and raw rotational residual, so the current-arm/spatial
expected vector or distinct constrained/free projection assertion fails.
- `NSNR-HDF5-014`
`NonlinearHdf5ResultsWriter.WritesSchemaV1GlobalBalanceErrorLocation` checks existing path/shape,
exact component names, schema version 1 and `location=global-balance-error`. Expected RED: current
writer emits `location=global-origin`.
- `NSNR-REF-020`
`NonlinearStaticReference.AuditsFinePrimaryAndCoarseCompanionArtifacts` checks all exact fine,
coarse and linear input/CSV hashes, fine/coarse independent execution directories and case roles.
Expected RED: current case inventory supports only coarse nonlinear and linear cases.
- `NSNR-REF-021`
`NonlinearStaticReference.ReviewOnlyLocalReactionsCannotChangeBlockingVerdict` injects or observes
failing local RF/RM row/RMS decisions while U and internal blocking families pass. It requires
deterministic local error/precheck reporting and an unchanged blocking pass. Expected RED:
current local RF/RM dispositions are `kBlocking`.
- `NSNR-REF-022`
`NonlinearStaticReference.BlocksOnGlobalBalanceAndAcceptedFreeResidual` fails each coarse/fine
global-force, global-moment, free-force-residual and free-moment-residual family one at a time,
then passes all. It also asserts the constrained reaction resultant is a distinct review summary.
Expected RED for this re-execution: the preserved comparator applies the old shared `<=1e-10`
gate, so the approved coarse metric `1.413750912531167e-10` and fine metric
`2.7454660159924086e-10` are rejected even though both are below `1e-8`.
- `NSNR-REF-023`
`NonlinearStaticReference.RejectsMissingExtraDuplicateAndNonfiniteRowsBeforeToleranceAndRecordsReviewOnlyFindings`
covers blocking, warning-only and review-only families. Blocking precheck failure changes the
blocking verdict; warning/review failures remain ordered findings. Expected RED: the current
comparator cannot retain review-only precheck findings independently of the blocking verdict.
- `NSNR-REF-024`
`NonlinearStaticReference.GlobalForceAndMomentBalanceUseApprovedInclusiveOneEighthGate` uses a
test-private balance evaluator for distinct force and moment family identities. It requires an
approved between-threshold metric such as `5e-9` and exact `1e-8` to pass, and
`nextafter(1e-8,+infinity)` to fail for both identities. Expected decisive RED: the preserved
shared `<=1e-10` comparison rejects `5e-9` and `1e-8`.
- `NSNR-REF-025`
`NonlinearStaticReference.GlobalForceAndMomentExactZeroScaleRequiresExactZeroBalance` exercises
force and moment identities independently and requires exact-zero scale plus exact-zero numerator
to pass while any nonzero numerator fails without NaN/Inf or a fabricated normalized metric. This
is an unchanged-contract regression and may already pass in the RED batch; it must be present
before GREEN.
Run:
Run and record the observed failures:
```powershell
cmake --build --preset windows-msvc-ninja-debug
ctest --preset windows-msvc-ninja-debug -R "NonlinearStaticReference|ReferenceTolerance|Mitc4Reference" --output-on-failure
ctest --preset windows-msvc-ninja-debug -R "^(NonlinearStaticProcedure|NonlinearHdf5ResultsWriter|NonlinearStaticReference)\." --output-on-failure
```
Expected: new tests fail. Unexpected pass stops.
The new tests must fail for the stated reasons. A compile failure caused only by the test-first
enum/report extension is valid RED when the diagnostic identifies the missing planned production/
test-support behavior. An unexpected pass or unrelated failure stops the Step for classification.
## GREEN
## Minimal 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:
1. Replace the private raw-residual/initial-coordinate global helper in
`src/fesa/analysis/nonlinear_static_procedure.cpp` with the Required physical algorithm above.
Keep stable node order, mask-before-conversion, independent applied/reaction conversion and
finite failure behavior. Do not change the public procedure header or accepted-state layout.
2. In `src/fesa/io/hdf5/nonlinear_hdf5_results_writer.cpp`, preserve the path, shape, component
names and schema version; change the exact `/global/equilibrium` location attribute to
`global-balance-error` and keep writer validation finite/fail-closed.
3. Extend the existing comparator without deleting its partial work:
- add fine primary inventory and keep coarse companion/linear control independent;
- add `kReviewOnly` and keep local RF/RM key/schema/inventory/finite/row/RMS evidence;
- reconstruct the constrained reaction resultant and accepted free residual from the exact HDF5
paths/mask; never use `/nodal/reaction` or `/global/equilibrium` as a substitute for all three;
- apply internal gates exactly as specified above, using one test-private/internal shared
`1.0e-8` constant for both distinct force and moment families;
- keep U blocking, UR warning-only, local RF/RM review-only, RM3/stress excluded;
- reject blocking missing/extra/duplicate/nonfinite rows before tolerance and retain ordered
nonblocking findings;
- set overall blocking verdict from blocking external U families AND all internal global/free
families only.
4. Preserve existing `NSNR-CTRL-018..021`, `NSNR-LOG-012`, Full Newton, fixed factors, iteration
limit, 39-field log schema and the already corrected residual selector unchanged.
5. Do not change production solver/configuration behavior for the balance threshold. No `fesa.env`,
environment variable, CLI option, public API or HDF5 schema change is part of this GREEN.
| 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` |
## Exact read-only artifact inventory
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.
| case | exact path | rows | SHA-256 |
| --- | --- | ---: | --- |
| fine primary | `reference/shellNL-meshfine/shellNL-meshfine.inp` | input | `40DF1CE77311C8D799564A21A60F3BDEBB8148D52CAE22B7292FDFAD32018220` |
| fine primary | `reference/shellNL-meshfine/shellNL-meshfine displacements.csv` | 729 | `740819FF8AED0E279961581F7CDBFA12784CFBA3A488C35A652E80103F64433F` |
| fine primary | `reference/shellNL-meshfine/shellNL-meshfine reactions.csv` | 729 | `AEB01C98C596792B0E5F2B86A81945CAB0BEB0C6969CFC6738C6F81DF1F94363` |
| fine optional | `reference/shellNL-meshfine/shellNL-meshfine stresses.csv` | 5,408 | `6D6213AB5DB9D6B1F5FBD641367D08BACC805967B6C5A95BCE0E1A5395377782` |
| coarse companion | `reference/shellNL/shellNL.inp` | input | `4BF3ECB0F7F1E8462C573E993DBC97AC5D920C91CF6F23AD4C6891D77FFBADA2` |
| coarse companion | `reference/shellNL/shellNL displacements.csv` | 49 | `4E0F99CA9372B1ADF7FAF102F43BC0B887DC743FDEDA378E4342D2CF8E0C0786` |
| coarse companion | `reference/shellNL/shellNL reactions.csv` | 49 | `001CB1541A9E94424E5E650509D46BC8724970DF4DE47184D9DB09C7938AB069` |
| coarse optional | `reference/shellNL/shellNL stresses.csv` | 288 | `5500E5114B1C44887528E30CEC054A1EB0F68BE3F4B8CE81FA59FC74A881483F` |
| linear control | `reference/shell/shell.inp` | input | `4005851E1AB22FD3A16AC17A8D5DA3E051233F69F37419079F3553AD134ECFCF` |
| linear control | `reference/shell/shell displacements.csv` | 49 | `C81D94E0B4A849F87AA0F79C83A79B94D5661AC79E44ED826919AB432C87746B` |
| linear optional | `reference/shell/shell reactions.csv` | 49 | `0E34EEC27E700C3C0C744C1DAFD8A3B95EFEF34B8616FE96665876586FE82D41` |
| linear optional | `reference/shell/shell stresses.csv` | 288 | `2B75A5B0DEB045A283C9BB7E9B1153B79F7537FF487214BF4A23316B59B660A7` |
## VERIFY
For every case, snapshot original inventory, bytes, SHA-256, size and timestamp; copy only the `.inp`
bytes to a unique build-local directory; run only the copy; consume copied-sibling `_results.h5` and
`_log.txt`; compare against original read-only CSVs; then prove the original inventory is unchanged.
## External comparison and classification
- Fine and coarse `U1/U2/U3` are separate blocking families.
- Linear `U1/U2/U3` is a blocking regression family.
- All `UR1/UR2/UR3` families are warning-only.
- Fine/coarse local `RF1/RF2`, `RF3`, spatial `RM1/RM2` are separate review-only families with exact
mask-derived keys and complete common-policy error reports.
- `RM3` and all stress values have no numerical family. Stress files remain hash-audited optional
inventory; the known fine malformed optional stress key is not repaired.
- External families use exactly `docs/TOLERANCE.md`: reference-only `S=max(abs(reference))`,
`B=0.01*S`, near-zero row `abs(error)<=B`, other-row relative `<=0.05`, family
`RMS(error)/S<=0.01`, exact-zero family exact-zero FESA only. No absolute floor, averaging,
collapse, row-order identity, clamp or tolerance relaxation.
The final gate order is literally:
```text
ARTIFACT CHECK -> COMPARE -> CLASSIFY -> REPORT
```
## Focused and full VERIFY
After minimal GREEN, run in this order and retain command, exit code, duration and output tail for
Step 12:
```powershell
cmake --preset windows-msvc-ninja-debug
cmake --build --preset windows-msvc-ninja-debug
ctest --preset windows-msvc-ninja-debug -R "NonlinearStaticReference|ReferenceTolerance|Mitc4Reference" --output-on-failure
ctest --preset windows-msvc-ninja-debug -R "^(NonlinearConvergence|NewtonIterationLog)\." --output-on-failure
ctest --preset windows-msvc-ninja-debug -R "^(NonlinearStaticProcedure|NonlinearHdf5ResultsWriter)\." --output-on-failure
ctest --preset windows-msvc-ninja-debug -R "^NonlinearStaticReference\." --output-on-failure
ctest --preset windows-msvc-ninja-debug -R "^(NonlinearStaticReference|ReferenceTolerance|Mitc4Reference)\." --output-on-failure
ctest --preset windows-msvc-ninja-debug --show-only=json-v1
ctest --preset windows-msvc-ninja-debug --output-on-failure
```
Use the ignored `.harness/config.json` preset contract. The Harness process must inherit VsDevCmd x64 and `FESA_GTEST_SOURCE_DIR`, `MKL_DIR`, `TBB_DIR`, and `HDF5_DIR` from its parent launch environment.
The Harness launch environment must be VsDevCmd x64 and inherit `FESA_GTEST_SOURCE_DIR`, `MKL_DIR`,
`TBB_DIR`, and `HDF5_DIR`. Do not substitute the solution-only MSBuild path.
## Acceptance Criteria
- New RED tests fail first for their declared current behavior, then pass after minimal GREEN.
- `/global/equilibrium` remains schema v1 `[6]` with the same component names and stores only the
current-arm/spatial-moment applied-plus-reaction balance error with
`location=global-balance-error`.
- Fine/coarse global force and moment normalized metrics are each `<=1e-8`; exact-zero scale follows
the exact-zero rule.
- Fine/coarse accepted free force and moment residual gates pass NSNR-069 independently.
- Fine/coarse U blocking and linear U regression pass `docs/TOLERANCE.md`.
- UR differences remain warning-only. Local RF/RM findings remain review-only and cannot fail the
blocking verdict. RM3/stress remain excluded.
- Missing/extra/duplicate/nonfinite blocking rows fail before tolerance; warning/review findings are
deterministic and nonblocking.
- Original reference artifact content, inventory, size, timestamp and hash are unchanged.
- Focused tests, test discovery and full CTest pass without new compiler warnings.
## 상태 기록
Update only Step 11 status and one-line payload. Executor owns timestamps, commits, retry, and advancement.
On success, update only Step 11 to `completed` and add one concise `summary`. On an implementation,
build, test or reference-comparison failure, classify it and update only the Executor-selected Step's
allowed payload. Executor owns retry, timestamps, commits, advancement and top-level status. Do not
start Step 12.
## 금지사항
- 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.
- Do not edit any reference artifact. 이유: exact stored files are immutable external evidence.
- Do not run FESA on an original reference `.inp`. 이유: derived sibling outputs would mutate the
reference directory.
- Do not add HDF5 datasets, change schema version/path/shape/components or add public headers. 이유:
Stage 5 requires reconstruction from existing schema-v1 datasets.
- Do not use initial coordinates or raw rotational covectors for global physical moment. 이유:
`AUDIT-001` requires accepted current arms and spatial moment conversion.
- Do not apply the constraint mask after spatial conversion. 이유: partial rotational constraints
would mix free residual into reaction.
- Do not use `/global/equilibrium`, local `/nodal/reaction` or a raw full-residual sum as a substitute
for all three equilibrium quantities. 이유: their physical identities differ.
- Do not make local reaction rows blocking or omit their review evidence. 이유: USER-DECISION-004
fixes review-only with deterministic findings.
- Do not compare `RM3` or stress values, average/collapse rows, match by row order, clamp zero values,
add `max(1,S)`, relax tolerance or repair CSVs. 이유: approved identity/tolerance contracts forbid it.
- Do not add `fesa.env`, runtime configuration, product solver acceptance, CLI or public API behavior
for the `1e-8` gate. 이유: this fixed threshold belongs only to comparator-owned internal verification.
- Do not replay or fabricate selector RED, delete partial Step 11 work, reset history, commit, push,
run a reference solver, start Step 12, or claim Physics/Release readiness.
- Stop and return a classified blocker if the required behavior needs an upstream contract, public
API, HDF5 schema, tolerance or reference-artifact change.
+191 -51
View File
@@ -1,5 +1,11 @@
# Step 12: execution-closure-and-evidence-docs
## 목적
Step 11이 실제로 통과한 뒤에만 fresh MSVC/CTest와 reference gate evidence를 수집하고 Stage 6
canonical reports를 actual output으로 작성한다. 직접 superseded된 PRD/ARCHITECTURE/ADR 문장만
최소 동기화한다. 이 Step은 solver 동작을 새로 구현하지 않는다.
## 읽어야 할 파일
- `AGENTS.md`
@@ -8,85 +14,219 @@
- `docs/ADR.md`
- `docs/CODINGSTYLE.md`
- `docs/TOLERANCE.md`
- `docs/nonlinear-static-newton-raphson/implementation-plan.md`
- `docs/SOLVER_AGENT_DESIGN.md`
- `docs/HARNESS.md`
- `docs/HARNESS_WORKFLOW.md`
- `docs/nonlinear-static-newton-raphson/requirements.md`
- `docs/nonlinear-static-newton-raphson/numerical-review.md`
- `docs/nonlinear-static-newton-raphson/reference-model.md`
- `docs/nonlinear-static-newton-raphson/io.md`
- `docs/nonlinear-static-newton-raphson/formulation.md` §§11.4, 13.1, 13.4, 14.1
- `docs/nonlinear-static-newton-raphson/numerical-review.md` §§3.2, 6.2, 6.3
- `docs/nonlinear-static-newton-raphson/reference-model.md` §§3–6
- `docs/nonlinear-static-newton-raphson/io.md` §§7.5.1, 8.1–8.7
- `docs/nonlinear-static-newton-raphson/implementation-plan.md`
- `docs/nonlinear-static-newton-raphson/corrections.md` §13
- `phases/nonlinear-static-newton-raphson/index.json`
- Step 0-11 modified source/test/CMake files
- `phases/nonlinear-static-newton-raphson/step11.md`
- All source/test/CMake files actually changed by Steps 0–11
- `.harness/config.json`
- `CMakePresets.json`
## 이전 Step 전제
## 시작 전 hard gate
Steps 0-11 have implemented and verified CLI lifecycle, Domain contract, nonlinear MITC4, controls, tangent solver, log, state, HDF5 schema v1, full prepared procedure, and reference comparison tests.
- Steps 0–10의 completed history를 그대로 유지한다.
- Step 11 must be `completed` with an actual summary and passing RED/GREEN/VERIFY evidence.
- If Step 11 is not completed, stop without creating/updating evidence docs or global docs.
- Do not infer Step 11 success from a prior blocked run, diagnostic spike or translation-only report.
## 소유 파일
- Modify: `docs/PRD.md`
- Modify: `docs/ARCHITECTURE.md`
- Modify: `docs/ADR.md`
- Create: `docs/nonlinear-static-newton-raphson/implementation-report.md`
- Create: `docs/nonlinear-static-newton-raphson/build-test.md`
- Create: `docs/nonlinear-static-newton-raphson/reference-comparison.md`
- Modify only directly superseded statements: `docs/PRD.md`
- Modify only directly superseded statements: `docs/ARCHITECTURE.md`
- Modify only directly superseded decisions or add the minimum accepted decision record:
`docs/ADR.md`
- Create from actual outputs: `docs/nonlinear-static-newton-raphson/implementation-report.md`
- Create from actual outputs: `docs/nonlinear-static-newton-raphson/build-test.md`
- Create from actual outputs: `docs/nonlinear-static-newton-raphson/reference-comparison.md`
No C++ production file is owned by this Step.
No C++ production, public header, test, CMake, Harness, reference or tolerance file is owned by this
Step.
## 인터페이스
## RED: evidence freshness audit
Evidence documents must record actual observed outputs:
Perform this audit before writing reports. The expected initial result is failure because the three
canonical reports are missing or do not contain this Step's fresh evidence.
```text
implementation-report.md: RED/GREEN/VERIFY command log, Step summaries, diagnostics, implementation-owned decisions.
build-test.md: fresh configure/build/discovery/full CTest commands, exit codes, duration, stdout/stderr tail, warning audit, failure classification.
reference-comparison.md: exact artifact inventory, HDF5 paths, projection, row prechecks, tolerance, per-family decisions, classification, no-change assertion.
```
- `NSNR-EVID-001`: `implementation-report.md` is missing or stale unless it records every Step 11 new
RED test, the observed reason, minimal GREEN diff, focused/full VERIFY and preserved
`NSNR-CTRL-018..021`/`NSNR-LOG-012` evidence.
- `NSNR-EVID-002`: `build-test.md` is missing or stale unless it records fresh configure, build,
discovery, focused/full CTest commands with exit code, duration, output tail, MSVC x64 Debug
environment, warning audit and failure classification.
- `NSNR-EVID-003`: `reference-comparison.md` is missing or stale unless it records the literal
`ARTIFACT CHECK -> COMPARE -> CLASSIFY -> REPORT` run with exact paths/hashes, generated HDF5/log
paths, projection, row decisions, metrics, classification and no-change evidence.
- `NSNR-EVID-004`: evidence or global docs are stale if they still classify local RF/RM as blocking,
omit review-only findings, identify coarse shellNL as the only nonlinear case, or describe
`/global/equilibrium` as raw full-residual/initial-arm evidence.
- `NSNR-EVID-005`: reference evidence is stale if it lacks fine-primary/coarse-companion/linear-control
inventory, separate U/UR/local reaction families, four coarse and four fine internal blocking
equilibrium families, the inclusive `1e-8` force/moment boundary and exact-zero-scale regressions,
and the distinct constrained-reaction summary.
- `NSNR-EVID-006`: implementation evidence is stale unless it closes `AUDIT-001` with actual tests for
nonzero prescribed translation/rotation, `x=X+u`, mask-before-conversion, independent
`InverseTransposeLeftJacobianSO3(phi)` conversion, and `location=global-balance-error`.
- `NSNR-EVID-007`: command evidence is stale if copied from an earlier run, omits artifact pre/post
immutability, lacks command output/exit/duration, changes the required stage order, or claims a
verdict before CLASSIFY.
## RED
Record this expected failing freshness audit in `implementation-report.md` only after fresh evidence
has been collected. If the audit unexpectedly passes before this Step's commands, stop and report the
evidence provenance conflict.
Before writing evidence docs, run an evidence freshness audit by checking that the three evidence docs do not already contain current command outputs from this final Step.
## GREEN: fresh evidence execution
- `NSNR-EVID-001`: missing or stale `implementation-report.md` is a failing precondition.
- `NSNR-EVID-002`: missing or stale `build-test.md` is a failing precondition.
- `NSNR-EVID-003`: missing or stale `reference-comparison.md` is a failing precondition.
- `NSNR-EVID-004`: PRD/ARCHITECTURE/ADR still contain directly superseded global CLI/procedure/output statements.
- `NSNR-EVID-005`: reference artifact pre-run SHA inventory must match Step 11 values.
Use the ignored `.harness/config.json` and tracked `windows-msvc-ninja-debug` preset. The parent
environment must be VsDevCmd x64 and contain `FESA_GTEST_SOURCE_DIR`, `MKL_DIR`, `TBB_DIR`, and
`HDF5_DIR`.
Expected: evidence freshness audit fails before this Step writes docs. If it unexpectedly passes with current evidence already present, stop and report to Coordinator.
## GREEN
- Run fresh MSVC x64 Debug configure/build/discovery/full CTest.
- Run focused nonlinear reference comparison repeat.
- Run deterministic repeat/reference checks required by Step 11.
- Run warning audit from build output.
- Run `git diff --check` and `git status --short`.
- Run reference artifact post-run SHA audit and compare to pre-run values.
- Update only directly superseded PRD/ARCHITECTURE/ADR statements for CLI removal, prepared linear/nonlinear procedure boundary, output naming, log lifecycle, and nonlinear HDF5 schema.
- Create the three Stage 6 evidence docs from actual command outputs only.
## VERIFY
Use the ignored `.harness/config.json` preset contract. The Harness process must inherit VsDevCmd x64 and `FESA_GTEST_SOURCE_DIR`, `MKL_DIR`, `TBB_DIR`, and `HDF5_DIR` from its parent launch environment. Run:
### 1. Fresh build and regression evidence
```powershell
cmake --preset windows-msvc-ninja-debug
cmake --build --preset windows-msvc-ninja-debug
ctest --preset windows-msvc-ninja-debug --show-only=json-v1
ctest --preset windows-msvc-ninja-debug -R "^(NonlinearConvergence|NewtonIterationLog)\." --output-on-failure
ctest --preset windows-msvc-ninja-debug -R "^(NonlinearStaticProcedure|NonlinearHdf5ResultsWriter)\." --output-on-failure
ctest --preset windows-msvc-ninja-debug --output-on-failure
ctest --preset windows-msvc-ninja-debug -R "NonlinearStaticReference" --output-on-failure
```
Record command, working directory, exit code, duration, stdout/stderr tail and failed-test inventory.
Audit new compiler warnings. Stop at the first decisive failure and classify it as
`configure | compile | link | test | reference-comparison | harness | environment | upstream-contract`.
### 2. Final reference gate in literal order
#### ARTIFACT CHECK
- Verify every exact fine/coarse/linear input/CSV path and SHA-256 from `reference-model.md` and
`step11.md`.
- Verify readable headers, exact nonlinear factor-one Frame, source node/component inventories,
uniqueness and finite required values.
- Snapshot original inventory, size, timestamps and hashes before any copied-input run.
- Verify generated results will be written only under unique build-local copied-input directories.
#### COMPARE
```powershell
ctest --preset windows-msvc-ninja-debug -R "^NonlinearStaticReference\." --output-on-failure
ctest --preset windows-msvc-ninja-debug -R "^(NonlinearStaticReference|ReferenceTolerance|Mitc4Reference)\." --output-on-failure
```
Compare by `(case_id, accepted_state, canonical_instance_name, source_node_label, component)`, never
by row order. Apply `docs/TOLERANCE.md` only to external U/UR/local-review families. Apply internal
`1e-8` force/moment balance and NSNR-069 free-residual gates separately. Preserve the exact
blocking/warning/review/excluded dispositions.
#### CLASSIFY
- Blocking pass requires fine/coarse U families, linear U regression and all eight fine/coarse
internal equilibrium families to pass.
- UR failure is warning-only.
- Local RF/RM precheck/row/RMS failure is a deterministic review finding and cannot change blocking
pass/fail.
- RM3/stress values are excluded.
- Any blocking missing/extra/duplicate/nonfinite row fails before tolerance.
- Classify actual failures without relaxing tolerance, changing artifacts or claiming external solver
internal equivalence.
#### REPORT
Only after CLASSIFY, write the three canonical reports from actual outputs.
## Report contracts
### `implementation-report.md`
Record metadata, approved upstream hashes, Steps 0–10 preserved summaries, Step 11 RED failures,
minimal GREEN file/symbol changes, focused/full VERIFY commands and results, `AUDIT-001` closure,
requirement/test traceability, no-change assertion, classification and open issues. Do not invent
unobserved output.
### `build-test.md`
Use `owner_agent: implementation-agent`. Record execution environment, exact commands, working
directories, exit codes, durations, output tails, discovered test inventory, focused/full results,
new-warning audit, failure classification, failed tests, handoff recommendation, no-change assertion
and open issues.
### `reference-comparison.md`
Record exact input/CSV SHA inventory, copied input and generated HDF5/log paths, accepted factor-one
frame, every HDF5 projection/path/component, stable source-key matching, row prechecks, external
common tolerance, internal gates, per-family/per-row decisions, max absolute error, applicable
relative error, RMS/scale metric, constrained-reaction summary, warnings/review findings, final
classification, original artifact post-run identity, no-change assertion and open issues.
The report must explicitly state that FESA HDF5 is authoritative, CSV is external comparison
evidence, and numerical agreement does not imply Abaqus S4 internal formulation equivalence.
## Minimal PRD/ARCHITECTURE/ADR sync
After actual passing evidence exists, update only statements directly superseded by the implemented
feature:
- repository-wide derived result/log names and removal of `--output`;
- prepared parse-once linear/nonlinear procedure boundary and separate nonlinear state/solver/writer;
- nonlinear HDF5 schema v1 accepted-frame meaning;
- `/global/equilibrium` as current-arm/spatial-moment applied-plus-reaction balance error;
- distinct accepted free residual and constrained reaction resultant projections;
- fine primary/coarse companion, U blocking, UR warning-only, local RF/RM review-only and RM3/stress
exclusion.
Do not rewrite unrelated V0 history, refactor architecture prose or add future scope.
## Final validation
```powershell
git diff --check
git status --short
```
Record command, exit code, duration, stdout/stderr tail, and failure classification for every command in the evidence docs.
Confirm the original reference pre/post hashes, sizes, timestamps and inventory are equal. Confirm
that every required report statement is backed by a command or deterministic artifact observation.
Harness Python validation is not required because this Step does not change Harness Python, hooks or
agent configuration.
## Acceptance Criteria
- Evidence freshness audit initially fails for the declared stale/missing reason and is recorded.
- Fresh configure/build/discovery/focused/full CTest all pass with MSVC x64 Debug and no new warnings.
- Final gate executes in exact order `ARTIFACT CHECK -> COMPARE -> CLASSIFY -> REPORT`.
- All blocking external and internal families pass; warnings and review findings remain
nonblocking and are fully reported.
- `AUDIT-001`, fine/coarse roles and reaction disposition have direct test/output evidence.
- Three canonical Stage 6 reports contain reproducible commands, metrics, classifications and
no-change assertions.
- PRD/ARCHITECTURE/ADR edits are limited to directly superseded statements.
- `git diff --check` passes and reference artifacts remain byte-for-byte unchanged.
## 상태 기록
Update only Step 12 status and one-line payload. Executor owns timestamps, commits, retry, top-level phase completion, and advancement.
On success, update only Step 12 to `completed` and add one concise `summary`. Executor owns
timestamps, commits, top-level completion and advancement. A passing Step 12 returns Stage 6 evidence
to Coordinator; it does not itself dispatch Physics or Release.
## 금지사항
- Do not claim success before the commands above actually pass. 이유: Stage 6 evidence docs must be output-backed.
- Do not broadly rewrite global docs. 이유: Step 12 only synchronizes directly superseded CLI/procedure/output statements.
- Do not change reference artifact content. 이유: SHA pre/post immutability is part of the acceptance evidence.
- Do not run `scripts/execute.py` from this Step. 이유: Executor already owns Harness execution.
- Do not create or update evidence reports before actual fresh output exists. 이유: Stage 6 reports
are execution evidence, not predictions.
- Do not change C++ code, tests, CMake, Harness configuration, tolerance or reference artifacts.
이유: Step 12 is evidence closure only.
- Do not run `scripts/execute.py` from this Step. 이유: Executor already owns the active Step session.
- Do not reorder or collapse `ARTIFACT CHECK -> COMPARE -> CLASSIFY -> REPORT`. 이유: schema and
identity failures must precede tolerance and verdict.
- Do not make local RF/RM blocking, omit their errors, or compare RM3/stress. 이유:
USER-DECISION-004 fixes the disposition.
- Do not use Abaqus CSV/tolerance for internal balance/free-residual gates or claim Abaqus internal
equivalence. 이유: external comparison and internal physics evidence are distinct.
- Do not broadly rewrite PRD/ARCHITECTURE/ADR, alter Steps 0–11 history, commit, push, run a reference
solver, or claim Physics/Release readiness.
@@ -136,6 +136,15 @@ Add tests first.
- `NSNR-CTRL-016`: empty free channels evaluate with `numerator_norm=0`, `denominator_scale=0`, branch `kZeroScale`, exact zero-scale threshold/unit, and pass.
- `NSNR-CTRL-017`: iteration numbering remains `1..100` with no iteration `101`.
### USER-DECISION-003 option-1 revision addendum
Step 5의 completed status, summary, timestamps와 commits는 보존한다. 다음 correction tests와 minimal GREEN은 재실행된 Step 5가 아니라 Executor-selected Step 11 안에서 수행한다.
- `NSNR-CTRL-018`: force와 force-length residual channel 각각에서 matching external vector가 finite exact zero이고 internal/residual이 nonzero여도 `kZeroScale`을 선택한다. Numerator exact `1.0e-3`은 pass, `std::nextafter(1.0e-3, +infinity)`는 fail이며 decision denominator는 exact `0`, threshold unit은 각각 `kForce`, `kForceLength`다. Empty free channel pass도 유지한다.
- `NSNR-CTRL-019`: matching external scale이 nonzero이면 internal-dominant와 external-dominant case 모두 denominator `max(||f_int||inf,||f_ext||inf)`를 쓴다. Ratio exact `1.0e-2`는 pass, 바로 위는 fail이다. Numerator가 typed `1.0e-3`보다 작아도 relative ratio가 실패하는 case를 포함하여 absolute/relative OR가 없음을 증명한다.
- `NSNR-CTRL-020`: residual/internal/external vector 또는 derived norm의 NaN/Inf는 branch/tolerance acceptance 전에 fail하고 combined pass를 만들지 않는다. `std::nextafter(0.0,+infinity)`인 matching external scale은 tolerance band, zero clamp, `max(1,...)` 없이 nonzero relative branch를 선택한다.
- `NSNR-CTRL-021`: force residual, moment residual, translation correction, rotation correction을 하나씩 실패시키는 truth table과 네 channel 모두 pass하는 case로 logical AND를 고정한다. NSNR-070 correction selector, denominators, thresholds와 units는 변경하지 않는다.
Run:
```powershell
@@ -147,7 +156,7 @@ Expected: new tests fail. Unexpected pass stops.
## GREEN
Implement factor sequence derivation, load/BC scaling, global-once fixed-load external vector `f_ext` and external tangent `K_ext` assembly, moment admissibility, and typed convergence-channel evaluation. Residual denominator scale is derived from the provided free internal/external channel values, correction denominator scale from the provided current increment channel values, and zero-scale branches use only `kZeroScale`. Thresholds and threshold units are not caller inputs; `EvaluateNewtonConvergence` assigns the exact branch/channel constants from `requirements.md` and `io.md`. Return structured diagnostics for invalid nonlinear static data, unsupported drilling load, nonfinite Newton data, and nonconvergence readiness.
Implement factor sequence derivation, load/BC scaling, global-once fixed-load external vector `f_ext` and external tangent `K_ext` assembly, moment admissibility, and typed convergence-channel evaluation. For the USER-DECISION-003 correction, validate the residual/internal/external values and norms first, select a residual branch from the matching external scale itself, emit denominator exact `0` and typed absolute `1.0e-3` when that scale is exact zero, and otherwise emit retained `max(internal,external)` with relative `1.0e-2`. Correction denominator selection remains derived from current increment values. Thresholds and threshold units are not caller inputs; `EvaluateNewtonConvergence` assigns the exact branch/channel constants from `requirements.md` and `io.md`. Return structured diagnostics for invalid nonlinear static data, unsupported drilling load, nonfinite Newton data, and nonconvergence readiness.
## VERIFY
@@ -173,3 +182,4 @@ Update only Step 5 status and one-line payload. Executor owns timestamps, commit
- Do not distribute full source-node CLOAD into every incident element. 이유: this would multiply loads by incident element count and violate formulation §11.2.
- Do not emit convergence branch labels outside `relative` and `zero-scale`. 이유: io.md exposes exactly those two branches.
- Do not accept per-call convergence thresholds or units. 이유: NSNR-069/070 fix branch thresholds and typed units globally.
- Do not use internal scale, tolerance bands, clamps, `max(1,...)`, or absolute/relative OR to select a residual branch. 이유: revised NSNR-069 selects only from the finite matching external scale's exact-zero identity.
@@ -91,6 +91,12 @@ Add tests first.
- `NSNR-LOG-010`: write/flush/close failure returns `log-output-failure` and prevents success classification.
- `NSNR-LOG-011`: non-Newton controlled failure path can leave a zero-byte log owned by app lifecycle.
### USER-DECISION-003 option-1 revision addendum
Step 7의 completed status, summary, timestamps와 commits는 보존한다. Executor-selected Step 11에서 `tests/unit/analysis/newton_iteration_log_test.cpp`에 다음 RED assertion을 추가한다.
- `NSNR-LOG-012`: synthetic `NewtonChannelDecision`이 아니라 `EvaluateNewtonConvergence`가 만든 residual decisions를 record에 넣는다. Exact-zero matching external channel은 denominator exact `0`, branch `zero-scale`, threshold `1.0e-3`, force 또는 force-length unit으로 직렬화하고, nonzero matching external channel은 retained denominator, branch `relative`, threshold `1.0e-2`, unit `1`로 직렬화한다. 같은 line이 기존 39 labels/order, TAB separation, LF termination을 그대로 유지해야 하므로 기존 selector에서는 RED가 된다.
Run:
```powershell
@@ -102,7 +108,7 @@ Expected: new tests fail. Unexpected pass stops.
## GREEN
Implement a small log writer with explicit open/write/flush/close state, serializer-owned 39-field order, deterministic escaping, finite numeric formatting, `relative`/`zero-scale` convergence branch mapping, typed `not-evaluated(reason)` substitution, and structured `Status` failures.
Implement a small log writer with explicit open/write/flush/close state, serializer-owned 39-field order, deterministic escaping, finite numeric formatting, `relative`/`zero-scale` convergence branch mapping, typed `not-evaluated(reason)` substitution, and structured `Status` failures. USER-DECISION-003는 evaluator-produced decision semantics만 바꾸므로 log writer production 또는 `nsnr-log-v1` schema 변경은 예상하지 않는다.
## VERIFY
@@ -126,3 +132,4 @@ Update only Step 7 status and one-line payload. Executor owns timestamps, commit
- Do not accept arbitrary caller-provided field vectors. 이유: io.md requires an exact fixed schema and order.
- Do not write HDF5 trial history. 이유: log is diagnostic and HDF5 stores accepted frames only.
- Do not continue after log write/flush/close failure. 이유: log failure blocks result commit.
- Do not add, remove, rename, reorder, or re-delimit any `nsnr-log-v1` field. 이유: option 1 changes only residual decision values, not the approved 39-field external log contract.