diff --git a/PLAN.md b/PLAN.md index ad17894..8560e29 100644 --- a/PLAN.md +++ b/PLAN.md @@ -21,7 +21,7 @@ - [ ] **State:** In progress — the package-native capped xtask entry point is reachable, rejects unknown packages, propagates mutest failure, and mutation-tests `hemx-axum`, `hemx-core`, `hemx-js`, and the full `hemx-test` package cleanly; full package closure remains. - **User value:** maintainers can run one bounded repository command and trust that meaningful Rust logic across every mutation-applicable library is either killed or explicitly justified. - **Build:** add a capped `hemx-xtask` mutation command that invokes `/opt/repositories/mutest`/`mutest` through package-native test targets rather than the broken workspace-wide example path; enumerate only current mutation-applicable library/proc-macro packages; finish adversarial tests or simplify code until every survivor is classified; keep equivalent, invariant-only, and infrastructure-inapplicable classifications inspectable and minimal; document the exact local release command in the existing readiness surface. -- **Blocked by:** none; broad survivors currently remain in `hemx-build`, `hemx-derive`, and `hemx-lsp` outside already-clean focused contracts. The current `hemx-build` frontier now adversarially proves static convention diagnostics; public file/source diagnostics and context facts; and mutation-clean generated-artifact create, no-op, and stale-output refresh behavior through `AppBuilder::run`; remaining resource-extraction and internal diagnostic survivors remain. The complete 470-mutant `hemx-axum` package gate now passes with 262 caught and 208 unviable after public page/form/multipart/registry/response/runtime proofs and narrow classification of infallible header parsing and streamed multipart unwrap-equivalent mutants. +- **Blocked by:** none; broad survivors currently remain in `hemx-build`, `hemx-derive`, and `hemx-lsp` outside already-clean focused contracts. The current `hemx-build` frontier now adversarially proves static convention diagnostics; public file/source diagnostics and context facts; mutation-clean generated-artifact create, no-op, and stale-output refresh behavior; and exact fail-closed invalid client-handler diagnostics through `AppBuilder::run`; remaining class/event/slot/atom/handle/form extraction and internal diagnostic survivors remain. The complete 470-mutant `hemx-axum` package gate now passes with 262 caught and 208 unviable after public page/form/multipart/registry/response/runtime proofs and narrow classification of infallible header parsing and streamed multipart unwrap-equivalent mutants. - **Proof:** the new xtask mutation command exits zero within its documented bound, covers each applicable package, emits no unexplained missed mutant, and a deliberate adjacent mutation makes it fail. `cargo run -p hemx-xtask -- test` remains green. req: test/020 req: test/021 ## 3. Elect and enforce the release license policy diff --git a/hemx-build/src/lib.rs b/hemx-build/src/lib.rs index b639904..7134438 100644 --- a/hemx-build/src/lib.rs +++ b/hemx-build/src/lib.rs @@ -2512,7 +2512,7 @@ mod tests { } #[test] - fn app_builder_returns_output_errors_instead_of_panicking() { + fn app_builder_propagates_output_and_client_contract_errors_without_panicking() { let root = std::env::temp_dir().join(format!( "hemx-build-error-{}-{}", std::process::id(), @@ -2552,8 +2552,29 @@ mod tests { result.unwrap().unwrap_err().to_string(), "client-local handlers require one data-hemx-client-module on a hemx root" ); + + let invalid_handler = templates.join("invalid_handler.heml"); + std::fs::write( + &invalid_handler, + r#"
"#, + ) + .unwrap(); + std::fs::remove_file(templates.join("client.heml")).unwrap(); + let error = app() + .template_dir(&templates) + .out_dir(&invalid_out) + .run() + .unwrap_err(); + assert_eq!(error.kind(), io::ErrorKind::InvalidData); + assert_eq!( + error.to_string(), + format!( + "{}: invalid data-hemx-client value `save-item`; expected a Rust handler identifier", + invalid_handler.display() + ) + ); let _ = std::fs::remove_dir_all(root); - // test req: build/004 + // test req: build/004 req: client_local/011 req: diagnostics/004 } #[test]