test(build): lock canonical generated contracts

Hash complete generated Rust, global exports, and symbol manifests across component, keyed, collision, duplicate-class/event, form, and parameter branches; simplify root component exports and remove impossible target-fallback bookkeeping.

req: codegen/005

req: codegen/006

req: build/009

req: test/021
This commit is contained in:
slhx agent
2026-07-17 04:50:36 +02:00
parent 72bce73e52
commit 2ba0be4d24
2 changed files with 89 additions and 18 deletions
+1 -1
View File
@@ -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 all class/form/event/slot/atom/handle extraction, field/parameter metadata, invalid-name, collision, deduplication, and keyed-upgrade behavior through `AppBuilder::run`; resource extraction is mutation-clean, leaving only internal diagnostic/code-generation survivors before the full package gate. 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 mutation-proves resource extraction plus canonical generated Rust/global exports/symbol manifests across keyed/component/collision/deduplication branches; the full 1,368-mutant package gate was runnable but exceeded 30 minutes after exposing 187 remaining survivors, led by `AppBuilder::run`, collection/error propagation, stylesheet parsing, and template-context diagnostics. 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
+88 -17
View File
@@ -548,7 +548,7 @@ impl Resources {
let root_indent = usize::default();
if global_exports {
self.push_component_refs(&mut out, root_indent);
self.push_component_refs(&mut out);
self.push_resource_modules(&mut out, &component_names, None, root_indent);
}
self.push_lowering_api(&mut out, None, root_indent);
@@ -567,19 +567,15 @@ impl Resources {
out
}
fn push_component_refs(&self, out: &mut String, indent: usize) {
let pad = " ".repeat(indent);
let inner = " ".repeat(indent + 1);
out.push_str(&format!(
"{pad}#[allow(non_upper_case_globals)]\n{pad}pub mod components {{\n"
));
fn push_component_refs(&self, out: &mut String) {
out.push_str("#[allow(non_upper_case_globals)]\npub mod components {\n");
for component in self.component_names() {
out.push_str(&format!(
"{inner}pub const {component}: ::hemx::ComponentRef = ::hemx::ComponentRef::new({});\n",
" pub const {component}: ::hemx::ComponentRef = ::hemx::ComponentRef::new({});\n",
rust_str(&component)
));
}
out.push_str(&format!("{pad}}}\n"));
out.push_str("}\n");
}
fn push_resource_modules(
@@ -752,14 +748,8 @@ impl Resources {
.values()
.filter(|res| component_matches(res, component))
{
push_root_export(
out,
&pad,
"targets",
&mut root_exports,
&res.ident,
"target",
);
root_exports.insert(res.ident.clone());
out.push_str(&format!("{pad}pub use self::targets::{};\n", res.ident));
}
out.push('\n');
@@ -2453,6 +2443,87 @@ mod tests {
assert!(generated_with_globals.contains("pub mod advanced {"));
assert!(generated_with_globals.contains("pub mod slots {"));
let mut row_slot = resource("row", "row", 21);
row_slot.keyed = true;
resources.slots.insert("row".into(), row_slot);
resources
.handles
.insert("edit".into(), resource("edit", "row", 22));
resources
.atoms
.insert("selection".into(), resource("selection", "row", 23));
resources
.slots
.insert("child".into(), resource("child", "page", 24));
resources
.handles
.insert("child_handle".into(), resource("child_handle", "child", 25));
resources
.slots
.insert("shared".into(), resource("shared", "page", 26));
resources
.handles
.insert("shared".into(), resource("shared", "page", 27));
resources.forms.insert(
"shared".into(),
FormResource {
resource: resource("shared", "page", 28),
controls: Vec::new(),
},
);
for (symbol, ident, component, token) in [
("a::card", "card", "page", "card"),
("b::card", "card", "row", "card"),
("z::last", "last", "page", "last"),
] {
resources.classes.insert(
symbol.into(),
ClassToken {
symbol: symbol.into(),
ident: ident.into(),
component: component.into(),
token: token.into(),
},
);
}
for (component, name) in [("page", "click"), ("row", "click"), ("z", "submit")] {
resources.events.insert(
format!("{component}::{name}"),
EventToken {
symbol: format!("{component}::{name}"),
ident: name.into(),
component: component.into(),
name: name.into(),
},
);
}
resources
.handle_forms
.insert("save".into(), "profile".into());
resources
.handle_params
.entry("save".into())
.or_default()
.insert("item_id".into());
let canonical_generated = resources.generated_rs(false);
let canonical_globals = resources.generated_rs(true);
let canonical_syms = resources.syms();
assert_eq!(
stable_id("generated-rs", &canonical_generated),
3_748_714_336,
"canonical generated Rust changed"
);
assert_eq!(
stable_id("generated-rs-global", &canonical_globals),
2_783_766_475,
"canonical global-export Rust changed"
);
assert_eq!(
stable_id("generated-syms", &canonical_syms),
984_222_700,
"canonical symbol manifest changed"
);
assert_eq!(Resources::default().client_bootstrap().unwrap(), "");
resources
.client_handlers