Independent CODE review — nox Hemera no_std feature boundary
Verdict: APPROVE — scoped two-file source repair, decision label, owner-gated merge, benchmark gate carried as an explicit RED/UNVERIFIED, no version/tag/publication. No blockers. Several findings below are mandatory-to-state-in-the-PR rather than merge blockers; one is a near-blocker I weighed carefully (§ "Closest call").
What I verified from the supplied material
The diff is exactly the approved delta, no more. §5's patch touches two files. rs/Cargo.toml: std = [] → std = ["hemera/std"] and , default-features = false appended to the hemera line. Nothing else — nebu, cyber-lens-core, cyber-lens-brakedown, acpu, criterion, bench, [lib], version 0.2.0, license-file, keywords all unchanged. §6's full final manifest corroborates the patch line by line; I reconstructed it from the §5 hunks against the implied parent and found no third change. The CLAUDE.md hunk appends after the existing "do not touch zones" tail at line 570+, and §7's full final file confirms it lands at the very end, with the pre-existing two bullets intact above it. §33 independently reports production_files: 2, owning_rust_count: 48, all_source_before_after_equal: true, and that the worktree diff equals the frozen patch hash 387f9cce… — which matches §5's declared sha256. That is a closed loop on "only the two intended files changed."
The causal claim is proven by raw compiler output, not narrative. §44 (record 38, parent) fails with E0463: can't find crate for std at hemera/rs/src/lib.rs:55 extern crate std; while compiling cyber-hemera v0.3.1, before nox is reached. §12 shows line-level context: #![no_std], extern crate alloc, then #[cfg(feature = "std")] extern crate std;. §11 shows Hemera's default = ["std"]. So the parent's nox edge unified hemera/std on and killed thumb codegen. §35 (record 72, candidate) is the same command, same target, exit 0, Finished dev profile, with cyber-hemera v0.3.1 compiling cleanly. §45/§41 repeat the identical before/after in the normalized package epoch, where Hemera comes from the registry path (/tmp/nox-no-std-registry/cyber-hemera-0.3.1/src/lib.rs:55) rather than the sibling checkout. Two independent dependency domains, same fix, same result. This is build, not check, so monomorphization and codegen are exercised.
The feature-tree inverse is a real artifact, not a claim. §37 (record 90, --no-default-features) prints exactly two lines: hemera and nox, with no cyber-hemera feature "std" node. §39 (record 91, --features std) prints the same tree plus └── cyber-hemera feature "std" ← cyber-nox feature "std". That is the invariant the patch is supposed to establish, shown as a diff of two stdout bodies, with receipts (§36/§38) confirming both ran under CARGO_TARGET_DIR=/tmp/nox-no-std-candidate-target, CARGO_BUILD_JOBS=2, CARGO_INCREMENTAL=0, toolchain-bin PATH first, and the same manifest. §26 records 92/93/94 cover parallel/brakedown/wgpu on the candidate — the one place under-forwarding could hide — and §27 pairs each against parent records 69/70/71. The forwarding closure is sound from §6: each of those three features lists "std", and std now lists "hemera/std".
Behavior preservation is paired, not asserted. §27 is the load-bearing document and it holds up: 161/161 owning tests debug (40↔74), release (41↔75), std (42↔76); 164/164 parallel (43↔77) and brakedown (44↔78); H264 4/4 debug and release in both sibling (16↔84, 50↔85) and package (98/99) domains; CLI build/test, wgpu check identical. Every row carries both receipt hashes and distinct parent_target/candidate_target paths, so these are not shared-target artifacts. §34's receipt shows the environment pinning the plan demanded (RUSTC/RUSTDOC absolute, PATH toolchain-bin first, offline, isolated CARGO_HOME).
The retained reds are labeled honestly, with one correctly-flagged imperfection. fmt 58↔79 both exit 1, normalized_stdout_equal: true. Docs 47↔81: 25 error headings, listed in full, identical set and order. honeycrisp 56↔89: same two E0425 missing-acpu symbols — and critically, this is the corrected story, not the obsolete "cache unavailable" claim the plan explicitly ordered preserving. Clippy 57↔80: same needless_borrow source diagnostic, but same_error_headings: false because Cargo's wrapper line differs (bin "nox" vs bin "nox" test). §3 and §27 both say so rather than smoothing it, and §49 shows the raw candidate tail. I checked whether that wrapper difference could hide a real new lint: the candidate's is the strictly broader target set (--all-targets compiling the bin's test harness too), the source diagnostic is byte-identical at cli/main.rs:247:52, and normalized_stdout_equal: true. Not a regression.
API comparison is isolated and its limits are stated. §42's receipt shows record 101 consuming /tmp/nox-no-std-api-candidate-target/doc/nox.json against a separately-recorded baseline; §32 gives both files' byte counts and distinct sha256 and distinct compiler targets (…api-candidate-target vs …api-parent-baseline-target). §43 is the actual tail: 229 checks: 229 pass, 31 skip, no semver update required. The brief, §3 and §9 all refuse to extend this to dependency-feature inheritance, which is correct: cargo-semver-checks models the default surface and would not see Hash::to_hex vanishing from a downstream's view. The shared-target diagnostics 60/61 are named and refused.
Unreachability of the two lost APIs is source-proven. §13 shows to_hex gated, with Display/Debug unconditional and emitting the same hex. §14 shows impl std::io::Read for OutputReader gated with OutputReader::fill unconditional — the gated impl is a two-line delegation to fill. §17 is the decisive witness for nox: data/hash.rs uses only hemera::tree::hash_leaf, hash_node, Hash::from_bytes, Hash::as_bytes. §18's benchmark uses hash_leaf/hash_node/as_bytes. §8's lib.rs re-exports no Hemera type. No to_hex, no Read.
Arithmetic/backend independence from std is verified against complete files, not a scan summary. I read §15 (arith.rs, 12016 B) and §16 (backend.rs, 6726 B) end to end: zero occurrences of feature = "std"; every cfg is all(target_arch = "aarch64", not(hemera_portable)) or its negation. Fast/Ct selection in §16 is static trait dispatch with no feature or runtime CPU detection. §10's 18-site inventory is consistent with both. So the no_std switch cannot change the hash kernel — which is why the benchmark results below are anomalous rather than explanatory.
Ring/label is right. §20 is the canonical text: a ring-0 PR merges without the owner only when every gate is green, blast radius is the repository, and no spec changed. Gates are not all green (fmt, clippy, docs, honeycrisp, exact-tag, benchmark), and §19 shows reverse Cargo edges into soft3/zheng/mudra/bbg/trident. decision + owner acceptance is the correct disposition, and §3 claims no new authorization. §21 opens the exact-tag red as its own task with a blocks edge and explicitly declines to modify any historical tag or lock — the right handling of record 64's cannot update the lock file … --locked was passed.
Closest call: the benchmark gate
I considered blocking on this. §20's self-verification clause requires "benchmark — no regressions vs baselines," and §28/§29 show measured slower cases. I am not blocking, for these reasons, and I want the reasoning on record because it is the one place a future reader could mistake this APPROVE for a performance clearance.
The data does not describe a code change; it describes an uncontrolled host. §47 (parent repeat) reports pattern/add -19%, mul -18%, hash -27%, hash_chain_64 -47%, encode/tree_64 -54%, encode/particle_atom -53% against the parent's own earlier run of identical source. The parent moved by up to 54% with zero bytes changed. That is the noise floor of this host, and it is larger than every candidate-vs-parent delta in §29 except encode_tree_64 (+89.6%). §28 and §29 also disagree in direction on add (+23.7% then −36.4%), mul (+12.0% then −10.1%), jet_merkle_verify (+16.9% then −2.0%), encode_particle_atom (−4.8% then +43.1%) — sign-flipping is the signature of environmental variance, not of a feature flag. §29's own 95% intervals are internally unstable: parent pattern/inv spans 64.9–75.2 µs in §29 but §47's raw Criterion prints [72.314 µs 106.20 µs 162.79 µs] for the same run, a >2× spread.
Crucially, the execution note does not make the argument I just made. §3 says "cause is unestablished," "not explained away as noise," "the shared host was not a controlled benchmark lab," "no further repeat or source tuning is hidden," and §30 says equal 3028144-byte sizes with unequal whole-file hashes "does not localize a performance cause." §29's disposition field says "remains red/unverified." That restraint is exactly what the plan's step 5 demanded and what makes the record trustworthy. Approving a disclosed red is a different act from approving a waived one, and the owner — not I — holds the disposition. I am approving the source repair with the gate red and stated; I am not certifying performance.
Blockers
None.
Required PR-body content (not blockers, but must not be dropped)
- Verbatim: "Kadek still resolves unchanged registry nox 0.2.0."
- The two affected dependency APIs by name:
Hash::to_hexandimpl std::io::Read for OutputReaderdisappear for any downstream relying on nox's default edge to enablehemera/std. §19 shows no current consumer does; the sentence belongs in the durable record anyway. - The benchmark gate is RED/UNVERIFIED with cause unestablished — nine-case pair with five breaches, one paired repeat with six, shared non-lab host. No speedup, equivalence or noise claim.
- The exact-tag locked API baseline (record 64) is unmet, with §21's follow-up linked by a
blocksedge. - Inherited reds carried unchanged: fmt, CLI
needless_borrow, strict docs, honeycrisp missing-acpu, Trident clap prerequisite. - Future release floor includes the component graph and the inherited dependency-feature contract, beyond cargo-semver-checks' default-surface result.
Advice (non-blocking)
- Capture the parent's self-variance as a first-class artifact. §47's parent-vs-parent deltas are the single most informative number in the benchmark material and currently exist only inside a raw stdout body. A
parent-self-variance.jsonbeside §28/§29 would let the next reviewer bound the noise floor without reconstructing it, and would support a future controlled measurement rather than retroactively excusing this one. - Pin Criterion's
--save-baseline/--baselineinstead of relying on its implicitchange:lines. §47 and §48 both printchange:against whatever happened to be in each target's Criterion state, which is why §47 shows the parent "improving" against itself. Explicit named baselines would make the comparison semantics unambiguous. - Add the
rustup target add thumbv7em-none-eabiline as a non-executing note in the §7 CLAUDE section. §3 deliberately omitted it to keep the delta exact, which I accept; but a contributor hitting the red prerequisite will read it as a broken repository. Fold it in at the next CLAUDE edit. - Record the two std-only APIs in Hemera's own docs/CHANGELOG, not only in nox's PR. The feature contract that just became load-bearing lives in Hemera; nox's PR body will be hard to find from there.
- At the publication unit, re-run the inverse feature tree against the registry Hemera, not the sibling path. §41 shows the package epoch builds, but §31's normalized manifest carries
default-features = falseon a version requirement — the forwarding behavior there deserves its own receipt before a bump. - Consider a CI matrix entry for
--no-default-featureson the host too. §26 record 73 passes and is cheap; the named gate is thumb-only, and a host no-default build would catchalloc-vs-stdslips without requiring the cross target.
The repair is two values, the diagnosis is raw compiler output in two dependency epochs, the feature invariant is shown as a two-stdout diff, 48 Rust files and all locks are byte-identical, the behavioral pairs are complete with distinct compiler roots, the inherited reds are preserved rather than laundered, and the one gate that is genuinely unexplained is labeled unexplained. Approved for an owner-gated decision merge with the reds carried forward.