Files
FESADev/phases/nonlinear-static-newton-raphson/step0.md
T

136 lines
6.1 KiB
Markdown

# Step 0: cli-output-lease-and-derived-names
> 과거 개발 계획이다. 아래 작업·상태·예시는 현재 실행 지시가 아니다.
> 현재 구현과 검증 한계는 [기능 요약](../../docs/nonlinear-static-newton-raphson/README.md)을 따른다.
## 읽어야 할 파일
- `AGENTS.md`
- `../../docs/solver-core/README.md`
- `../../docs/solver-core/README.md`
- `../../docs/solver-core/README.md`
- `.codex/hooks.json`
- `../../docs/nonlinear-static-newton-raphson/README.md`
- `../../docs/nonlinear-static-newton-raphson/README.md`
- `../../docs/nonlinear-static-newton-raphson/README.md`
- `src/fesa/app/fesa_application.cpp`
- `include/fesa/app/fesa_application.h`
- `include/fesa/analysis/analysis.h`
- `tests/integration/app/fesa_application_test.cpp`
- `src/fesa/CMakeLists.txt`
- `tests/CMakeLists.txt`
## 이전 Step 전제
없음. 이 Step은 app/CLI output lifecycle의 첫 변경이다.
## 소유 파일
- Create: `include/fesa/app/output_paths.h`
- Create: `src/fesa/app/output_paths.cpp`
- Create: `tests/unit/app/output_paths_test.cpp`
- Modify: `include/fesa/analysis/analysis.h`
- Modify: `include/fesa/app/fesa_application.h`
- Modify: `src/fesa/app/fesa_application.cpp`
- Modify: `src/fesa/CMakeLists.txt`
- Modify: `tests/CMakeLists.txt`
- Test: `tests/integration/app/fesa_application_test.cpp`
## 인터페이스
```cpp
namespace fesa {
struct DerivedOutputPaths {
std::filesystem::path input_path;
std::filesystem::path results_path;
std::filesystem::path log_path;
};
class OutputWriteLease {
public:
OutputWriteLease(const OutputWriteLease&) = delete;
OutputWriteLease& operator=(const OutputWriteLease&) = delete;
OutputWriteLease(OutputWriteLease&&) noexcept;
OutputWriteLease& operator=(OutputWriteLease&&) noexcept;
~OutputWriteLease();
private:
class Impl;
friend Result<OutputWriteLease> AcquireOutputWriteLease(
const DerivedOutputPaths& paths);
explicit OutputWriteLease(std::unique_ptr<Impl> impl) noexcept;
std::unique_ptr<Impl> impl_;
};
Result<DerivedOutputPaths> DeriveSingleInputOutputPaths(
const std::vector<std::string>& arguments,
const std::filesystem::path& invocation_cwd);
Result<OutputWriteLease> AcquireOutputWriteLease(
const DerivedOutputPaths& paths);
struct AnalysisRequest {
std::filesystem::path input_path;
std::filesystem::path output_path;
std::filesystem::path log_path;
};
} // namespace fesa
```
`OutputWriteLease`는 acquisition-only private constructor와 private pimpl storage로 lock lifetime을 보존한다. Win32 handle, file handle, 또는 platform lock 표현은 `Impl` 안에만 둔다. `FesaApplication`은 lease를 log close와 HDF5 finalization이 끝날 때까지 보관한다.
## RED
테스트를 먼저 추가한다.
- `NSNR-CLI-001`: argv의 모든 token을 왼쪽에서 오른쪽으로 검사하고, case-sensitive substring `--output`을 포함한 첫 token에서 exit code `2`와 diagnostic code `cli-usage`가 하나만 출력된다.
- `NSNR-CLI-002`: `abc--outputdef`, `--output-path`, `--output=foo`, `--output` 모두 input path resolution 전에 실패한다.
- `NSNR-CLI-003`: `--output` 실패는 parser, Analysis construction, lease acquisition, log create/truncate, HDF5 candidate creation을 호출하지 않는다.
- `NSNR-CLI-004`: relative `.inp` path는 invocation CWD 기준으로 lexical normalization만 하고 `<stem>_results.h5`, `<stem>_log.txt`를 같은 directory에 만든다.
- `NSNR-CLI-005`: final extension `.inp`는 case-insensitive이고 stem은 마지막 extension만 제거하며 basename case와 preceding dots를 보존한다.
- `NSNR-CLI-006`: output-busy lease collision은 exit code `6`이며 log와 HDF5를 만들거나 바꾸지 않는다.
- `NSNR-CLI-007`: previous result/log files가 있는 상태에서 `--output` 실패 후 bytes와 timestamps가 변하지 않는다.
- `NSNR-CLI-008`: existing default `fesa.exe <model.inp>` invocation은 더 이상 cwd `results.h5`를 기본값으로 쓰지 않는다.
- `NSNR-CLI-009`: `AnalysisRequest`가 `input_path`, `output_path`, `log_path`를 함께 전달한다.
실행:
```powershell
cmake --build --preset windows-msvc-ninja-debug
ctest --preset windows-msvc-ninja-debug -R "FesaApplication|OutputPath" --output-on-failure
```
기대: 새 테스트가 컴파일 실패 또는 assertion 실패로 실패한다. 새 테스트가 예상 없이 통과하면 구현을 중단하고 Coordinator에게 보고한다.
## GREEN
- `output_paths` module에 argv 검사, lexical path derivation, input extension validation, lease acquisition을 구현한다.
- `FesaApplication`은 `DeriveSingleInputOutputPaths` 성공 뒤 `AcquireOutputWriteLease`를 호출한다.
- 이 Step에서는 nonlinear procedure를 만들지 않는다.
- `LinearStaticAnalysis` 호출은 기존 방식대로 유지하되 `AnalysisRequest::output_path`가 `<stem>_results.h5`를 가리키게 한다.
## VERIFY
Use the ignored 과거 검증 자료(정리됨) 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:
```powershell
cmake --preset windows-msvc-ninja-debug
cmake --build --preset windows-msvc-ninja-debug
ctest --preset windows-msvc-ninja-debug -R "FesaApplication|OutputPath" --output-on-failure
ctest --preset windows-msvc-ninja-debug --show-only=json-v1
ctest --preset windows-msvc-ninja-debug --output-on-failure
```
## 상태 기록
Executor가 선택한 current Step 0만 `completed`, `error`, `blocked` 중 하나로 갱신한다. 성공 시 summary 한 줄만 기록한다. timestamp, retry, commit, advancement는 Executor 소유다.
## 금지사항
- `--output` alias 또는 deprecation path를 남기지 마라. 이유: 승인된 public compatibility가 fail-closed removal이다.
- path를 symlink, junction, short-name, case-normalized realpath로 resolve하지 마라. 이유: io.md가 lexical user-addressed identity를 요구한다.
- log/HDF5 작업이 끝나기 전에 `OutputWriteLease`를 파기하지 마라. 이유: exclusive ownership 보장이 깨진다.
- nonlinear analysis 분기를 `LinearStaticAnalysis` private lifecycle에 넣지 마라. 이유: Step 10의 별도 prepared flow가 소유한다.