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:
@@ -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
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user