fix(linear-static-3d-euler-beam): reject CLI option values
This commit is contained in:
@@ -1289,3 +1289,42 @@
|
|||||||
Step 27 can consume only its `physics_evidence` after Step 26 passes.
|
Step 27 can consume only its `physics_evidence` after Step 26 passes.
|
||||||
- concerns: none; no critical implementation, environment, numerical, or
|
- concerns: none; no critical implementation, environment, numerical, or
|
||||||
upstream-contract blocker remains.
|
upstream-contract blocker remains.
|
||||||
|
|
||||||
|
### Step 24 Review Fix Round 1 — option-token output rejection
|
||||||
|
|
||||||
|
- review_trigger: the approved CLI contract classifies repeated `--output`
|
||||||
|
and every unknown option as usage error exit 2. The original three-argument
|
||||||
|
parser treated the value position as an arbitrary nonempty path, so an
|
||||||
|
option token could advance into input analysis instead.
|
||||||
|
- RED-repeated-option: after adding
|
||||||
|
`{missingInput,"--output","--output"}` to the existing exact
|
||||||
|
`LinearStaticCli.ReturnsEveryExactExitCodeAndOrderedDiagnostic` test,
|
||||||
|
`cmake --build .harness/build --config Debug --target
|
||||||
|
fesa_integration_tests` exited 0 and the focused CTest exited 1. Actual exit
|
||||||
|
was 3 and stderr contained no `cli-usage`, rather than expected exit 2.
|
||||||
|
- GREEN-repeated-option: rejecting the literal repeated token made the same
|
||||||
|
focused test pass 1/1.
|
||||||
|
- RED-unknown-option: the reviewer then identified the general unknown-option
|
||||||
|
case. Adding `{missingInput,"--output","--bogus"}` before broadening the
|
||||||
|
production condition again produced build exit 0 and focused CTest exit 1;
|
||||||
|
actual exit was 3 with no `cli-usage`.
|
||||||
|
- production_fix: explicit output form now requires a nonempty third argument
|
||||||
|
that does not begin with `-`. Both a repeated known option and an unknown
|
||||||
|
option token are rejected before any input or output access, while ordinary
|
||||||
|
output paths retain the approved behavior.
|
||||||
|
- GREEN-focused: rebuilding `fesa_integration_tests` exited 0 under `/W4 /WX`;
|
||||||
|
the unchanged exact focused test passed 1/1 with both option cases pinned.
|
||||||
|
- independent_review: Critical 0, unresolved Important 0. The reviewer reran
|
||||||
|
exact Step 24 10/10, discovery 83, full 83/83, comparison 176 rows/16
|
||||||
|
metrics passed, and reference diff/status clean.
|
||||||
|
- remaining_minor: the test-only comparator independently pins float64 result
|
||||||
|
file types but relies on the Step 23 writer self-check/full-suite schema test
|
||||||
|
for exact uint64 endianness and every compound member file dtype/UTF-8. This
|
||||||
|
is defense-in-depth negative coverage, not a reproducible approved-pipeline
|
||||||
|
false pass.
|
||||||
|
- remaining_minor: the inherited diagnostic sorter is not a literal
|
||||||
|
implementation of future multi-source declaration/internal-ID ordering, but
|
||||||
|
no V0 single-input CLI misordering is reproducible.
|
||||||
|
- remaining_minor: the Step 23 `libmmd.dll` guard remains unconditional across
|
||||||
|
alternate HDF5 targets; it is correct for the approved shared-HDF5
|
||||||
|
environment and is an external portability limitation.
|
||||||
|
|||||||
@@ -200,7 +200,7 @@
|
|||||||
"status": "completed",
|
"status": "completed",
|
||||||
"started_at": "2026-08-09T22:13:49+0900",
|
"started_at": "2026-08-09T22:13:49+0900",
|
||||||
"completed_at": "2026-08-09T22:54:33+0900",
|
"completed_at": "2026-08-09T22:54:33+0900",
|
||||||
"summary": "Exact factorize-before-load single-step lifecycle과 argv0-excluded fesa.exe 0/2/3/4/5/6 CLI를 구현하고 read-only legacy B33/HDF5 comparator로 176 rows, 16 metrics, deterministic JSON/physics evidence를 생성해 Step24 10/10 및 전체 83/83을 검증함"
|
"summary": "Exact factorize-before-load single-step lifecycle과 argv0-excluded fesa.exe 0/2/3/4/5/6 CLI를 구현하고 repeated/unknown option token을 usage로 거부하며 read-only legacy B33/HDF5 comparator로 176 rows, 16 metrics, deterministic JSON/physics evidence를 생성해 Step24 10/10 및 전체 83/83을 검증함"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"step": 25,
|
"step": 25,
|
||||||
|
|||||||
@@ -83,7 +83,8 @@ int FesaApplication::run(const std::vector<std::string>& arguments) {
|
|||||||
!arguments[0U].empty() &&
|
!arguments[0U].empty() &&
|
||||||
!startsWithOption(arguments[0U]) &&
|
!startsWithOption(arguments[0U]) &&
|
||||||
arguments[1U] == "--output" &&
|
arguments[1U] == "--output" &&
|
||||||
!arguments[2U].empty();
|
!arguments[2U].empty() &&
|
||||||
|
!startsWithOption(arguments[2U]);
|
||||||
if (!defaultOutputForm && !explicitOutputForm) {
|
if (!defaultOutputForm && !explicitOutputForm) {
|
||||||
writeDiagnostics({usageDiagnostic()});
|
writeDiagnostics({usageDiagnostic()});
|
||||||
return kUsageExitCode;
|
return kUsageExitCode;
|
||||||
|
|||||||
@@ -332,7 +332,10 @@ TEST(LinearStaticCli, ReturnsEveryExactExitCodeAndOrderedDiagnostic) {
|
|||||||
const auto usage = runApplication({});
|
const auto usage = runApplication({});
|
||||||
const auto missingInput = directory.path() / "missing.inp";
|
const auto missingInput = directory.path() / "missing.inp";
|
||||||
const auto input = runApplication({missingInput.string()});
|
const auto input = runApplication({missingInput.string()});
|
||||||
const auto repeatedInput = runApplication({missingInput.string()});
|
const auto repeatedOutput = runApplication(
|
||||||
|
{missingInput.string(), "--output", "--output"});
|
||||||
|
const auto unknownOutputOption = runApplication(
|
||||||
|
{missingInput.string(), "--output", "--bogus"});
|
||||||
const auto model = runApplication(explicitOutputArguments(
|
const auto model = runApplication(explicitOutputArguments(
|
||||||
modelInput, directory.path() / "model-failure.h5"));
|
modelInput, directory.path() / "model-failure.h5"));
|
||||||
const auto solver = runApplication(explicitOutputArguments(
|
const auto solver = runApplication(explicitOutputArguments(
|
||||||
@@ -353,8 +356,14 @@ TEST(LinearStaticCli, ReturnsEveryExactExitCodeAndOrderedDiagnostic) {
|
|||||||
expectDiagnosticFieldOrder(model.standardError);
|
expectDiagnosticFieldOrder(model.standardError);
|
||||||
expectDiagnosticFieldOrder(solver.standardError);
|
expectDiagnosticFieldOrder(solver.standardError);
|
||||||
expectDiagnosticFieldOrder(output.standardError);
|
expectDiagnosticFieldOrder(output.standardError);
|
||||||
EXPECT_EQ(repeatedInput.exitCode, 3);
|
EXPECT_EQ(repeatedOutput.exitCode, 2);
|
||||||
EXPECT_EQ(repeatedInput.standardError, input.standardError);
|
expectDiagnosticFieldOrder(repeatedOutput.standardError);
|
||||||
|
EXPECT_NE(repeatedOutput.standardError.find("code=cli-usage"),
|
||||||
|
std::string::npos);
|
||||||
|
EXPECT_EQ(unknownOutputOption.exitCode, 2);
|
||||||
|
expectDiagnosticFieldOrder(unknownOutputOption.standardError);
|
||||||
|
EXPECT_NE(unknownOutputOption.standardError.find("code=cli-usage"),
|
||||||
|
std::string::npos);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(LinearStaticCli, OutputRequestsDoNotFilterMandatoryResults) {
|
TEST(LinearStaticCli, OutputRequestsDoNotFilterMandatoryResults) {
|
||||||
|
|||||||
Reference in New Issue
Block a user