Commit Graph
2 Commits
Author SHA1 Message Date
swaits 2d38af60f6 safety(audit): cargo-mutants reaches 98% coverage on the unsafe-touching codegen
The earlier safety-audit run reported 16/53 missed mutants in
compute_transition_paths and concluded the LCA depth-walk wasn't
covered by tests. Wrong diagnosis. cargo-mutants infers the
test-package from the file under mutation, so without an explicit
override it ran only the hsmc-macros per-package test set
(essentially trybuild fixtures). All the asymmetric-depth lateral
coverage in det_lateral.rs et al. is in the hsmc/ workspace tests
and was sitting on the bench.

With `--test-package hsmc --features hsmc/tokio,hsmc/journal`:

  codegen.rs safety fns:  51/53 (14 caught + 37 unviable + 2 missed)
  hsmc/src/lib.rs:        48/48 (45 caught + 3 unviable + 0 missed)
  total:                  99/101 = 98%

The 2 remaining are equivalent mutants — transformations that
provably produce identical __PATH_RANGE / __PATH_DATA output and
so cannot be distinguished by any behavior test:

  1. `da > db` → `da >= db` in the LCA depth-equalizer:
     the mutated loop walks `a` one extra step in the equality case;
     the next loop (`while db > da`) compensates symmetrically.
     parent(root) = None short-circuits any walk past root. Same
     LCA, same paths. Verified by hand on lateral, up-transition,
     and asymmetric-depth (4↔2) inputs.

  2. `from != to && is_strict_ancestor(...)` → `from == to && ...`:
     becomes always-false (a state isn't its own strict ancestor),
     so the up-transition branch is dead code. Up-transitions then
     fall through to the lateral branch, which computes
     lca(from, to) = to (target is ancestor of source), walks
     source up to (exclusive of) to, and produces an empty enter
     path. Same paths.

Both are documented in docs/004 § "The two equivalent mutants".

Updates:
- justfile `just safety`: add the correct flags so future runs
  reproduce 99/101 instead of the misleading 37/53.
- docs/004: corrected mutants section, equivalent-mutant analysis,
  removed the false "asymmetric-depth test gap" claim.
2026-05-04 15:29:24 -06:00
swaits ad2aa6e04d docs(safety): document the unsafe contract end-to-end
After Opt #2 added six bounded `get_unchecked` blocks per chart, the
project's two "no unsafe" claims (README §"At a glance" + spec §11
rule 12) were stale, and there was no single place answering "how
do I know the unsafe is correct?".

This commit closes both gaps:

- New: docs/004. unsafe-safety-contract.md
  Inventories every unsafe site, names the predicate, names what
  establishes it (codegen-time guarantee), and lists the five
  layered checks (const-eval, debug_assert, miri, mutants, Creusot)
  with current status. Documents what's *not* yet covered (the
  16-of-53 missed mutants in the LCA depth walk are behavior, not
  safety; transition() codegen invariants are still Phase-4 for
  Creusot). Includes a maintenance checklist for future unsafe.

- README points at the doc and gives an honest one-paragraph
  summary instead of "no unsafe".

- Spec rule 12 rewritten from "no unsafe in generated code" to
  "bounded unsafe in generated code, none in user code" with a
  pointer to the audit.

- justfile gains `just safety` — runs const-eval (cargo check),
  debug_assert tests, miri, and mutants in one shot. Mirrors the
  doc's audit matrix so the doc never goes stale silently.
2026-05-04 15:29:24 -06:00