From c24400333903a9d6efec24b6315095c634edfda8 Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Tue, 22 Sep 2026 20:52:20 +0200 Subject: [PATCH] Record the Stryker triage: a dozen live survivors on this cut's own rules The triage landed on the fifth attempt. Most of the 85 survivors are message strings; about a dozen are real, and they sit on the rules the cut exists to enforce: the alias-numeric refusal degrades to "only if every schema agrees", a half-blank cites.target stops being refused, the index-alias role naming is untested at all four sites, the row tiebreak and EdgesFor's ordering are pinned by nothing, and ComputeDigest's hop branches have no coverage at all. The equivalent mutants are named so nobody chases them twice. R-AA's triage half is done; what it now owes is a behavioural test per live survivor. Soul also withdrew its own claim that C#'s cursor digest does not sort its lists. It does, at CultNetSelectionEvaluator.cs:637. Co-Authored-By: Claude Opus 5 --- docs/cultnet-selection-cut.md | 47 +++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/docs/cultnet-selection-cut.md b/docs/cultnet-selection-cut.md index e18e1fc0..5b5561cc 100644 --- a/docs/cultnet-selection-cut.md +++ b/docs/cultnet-selection-cut.md @@ -747,6 +747,46 @@ merge.** `dotnet-stryker --project GameCult.Networking.csproj --mutate "**/CultNetSelection*.cs" --reporter json --reporter progress --concurrency 4`. **Read the HTML report Stryker writes beside the JSON**, rather than parsing JSON in the container. +- **The triage landed on the fifth attempt, 2026-09-22, and it sharpens S-5 + rather than softening it.** Most of the 85 are message-string mutations and + are not worth chasing; roughly a dozen are real, and they sit on the rules + this cut exists to enforce: + - `CultNetSelection.cs:439`, `Any()` → `All()` survived. §2's "a comparison + on an alias any reachable schema declares non-numeric is refused" degrades + to "refused only if every reachable schema declares it non-numeric". No + fixture has an alias numeric on one reachable leaf and a string on + another — the exact case the rule exists for. + - `CultNetSelection.cs:387`, `||` → `&&` survived. A `cites.target` with a + schemaId and a blank recordKey, or the reverse, stops being refused. + - `member.IndexAlias ?? member.MemberName` → `member.MemberName` survived at + all four sites (`CultNetSelectionEvaluator.cs:352,384,404` and + `CultNetSelection.cs:445`). §2's role-naming rule for the hop is untested + everywhere it is implemented. + - `CultNetSelectionEvaluator.cs:203,204`, `ThenBy` ↔ `ThenByDescending` + survived on both paths: the `(ordinal, schemaId, recordKey)` tiebreak is + pinned by nothing. + - `CultNetSelectionEvaluator.cs:290-297`, five order flips in `EdgesFor`, all + survived. **R-B's "page-row order, then `(from, role, to)` in code-point + order" has no test pinning a single component**, though R-B exists because + that ordering was wrong once already. + - `CultNetSelectionEvaluator.cs:590-605` has no coverage at all: + `ComputeDigest`'s `cites` and `cited` branches, plus the number-presence + flag at `:584-585`. R-H's collision-freedom rests on a reading, not a test. + - `:673,678` survived: `Cursor.Parse`'s length-prefix bounds checks, on + attacker-supplied base64. `:307,322` survived: cursor positioning under + `descending`, and `ComparePosition`'s schema-vs-key tiebreak. `:710,715,729` + survived: the code-point comparator's surrogate path, despite R-C having a + vector for it. + - **Equivalent, not to be chased:** `Selection.cs:103` `<=`, `:118` `>=`, + `:121` `dot <= 0` are guarded upstream and unreachable for canonical input; + `:103,107` turn `sign * x` into `sign / x` with `x` in {-1,1}; `:109` + Max→Min is a no-op because `PadRight` to a shorter length does nothing; + `:80` is a `RegexOptions` flag; `Evaluator:272` is equivalent because + `full.Edges` is empty without a hop. +- **Soul withdrew a finding of its own in the same pass.** It had reported that + C#'s cursor digest does not sort its lists while Rust's does, offered as a + low-severity intra-runtime difference. `CultNetSelectionEvaluator.cs:637` + sorts by code point, same as Rust. The remark belongs in no fix list. - **cargo-mutants cannot run on `cultnet-rs` at all.** `schema_discovery.rs` uses `include_str!("../../../contracts/…")`, which escapes the package, so the tool's copied tree fails its baseline build. **There is no mutation @@ -781,6 +821,13 @@ merge.** - **R-AA (S-5).** Triage all 85 survivors by name. The 75 uncovered mutants mean whole regions have no test; write behavioural tests for them. A survivor that is genuinely equivalent gets a one-line reason in the report. + **The triage half is done** (see the list under S-5, 2026-09-22). What is + owed is a behavioural test for each named live survivor: the alias + disagreement across reachable schemas, the half-blank `cites.target`, the + four index-alias role sites, the row tiebreak, `EdgesFor`'s ordering, + `ComputeDigest`'s hop branches, `Cursor.Parse`'s bounds, descending cursor + positioning, and the surrogate comparator. The equivalent mutants are + recorded and are not to be chased. - **R-AB. Make `cultnet-rs` self-contained enough to mutate.** Replace the escaping `include_str!` with a build script that stages the contracts into `OUT_DIR`, or another route that keeps every source path inside the package.