rugnux: record what the two-pass completeness arm can decide, and what three stand-ins could not

Only under -S does the arm read a completeness with headroom. De novo the search merge is in P1 and
does not count its possible reflections, so there is no number and CC1/2 is the only live term.
Three ways to give the arm one back were measured on 28 rotation crystals and none lands, so say so
at the guard rather than leave the next reader to rediscover them:

* Count the possible reflections on the search merge too. It is affordable - 5.2 ms against a 38 s
  run - but a healthy crystal reads 27-43% of the P1 hemisphere, so the 100.5% bound is never
  approached and no decision changes. It would only add a figure to the user's report that reads as
  the dataset's completeness while being a fraction of a different group's asymmetric unit.
* Observation count. The two search merges are built in the same terms, so pass 2 retaining under 90%
  of pass 1's observations looks like the signal the completeness ratio stood in for. It never fires -
  bit-identical on all 28, including the crystal whose pass 2 predicted 44% fewer partials. Predicted
  partials and observations that survive into the merge are not the same population.
* Completeness ratio. Same idea one level up, and it does fire - on the wrong crystals. This merge is
  deliberately never resolution-cut, so the possible list grows with whatever range the pass reached
  and a pass that predicts FINER scores as one that lost the sweep. At a 0.90 bound it reverted two
  crystals indexing at 100%, taking one of them from 0.07% to 0.29% cell deviation and ISa 19.5 to
  17.1, and rescued nothing.

Bringing the wrong-cell detector back for de-novo data means putting it on the final merge or
retiring the arm and saying so; neither is done here.

No test covers the decision line: Rugnux_Rotation does not reach this guard - the two passes in its
log are the indexer's, not RunAllPasses' - and there is no fixture for building a RotationScaleMerge,
so an assertion placed there would never execute.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EFEJG6WBQv8th4UJFNe53N
This commit is contained in:
2026-09-01 09:48:39 +02:00
co-authored by Claude Opus 5
parent 8935a59721
commit 04d823135e
+12
View File
@@ -1604,6 +1604,18 @@ ProcessResult Rugnux::RunAllPasses(RugnuxObserver *observer) {
// wrong), or its CC1/2 collapses relative to pass 1. Both bounds are set where only a failure
// reaches them, so a normal run - where pass 2 is a little better - keeps pass 2.
//
// The completeness arm only bites when the search merge is in a fixed group (-S). De novo that
// merge is in P1 and does not count its possible reflections at all, so there is no
// completeness and CC1/2 decides alone. Counting them there was measured and not taken: it
// costs 5.2 ms, but a merge that fills its own asymmetric unit reads 27-43% of the P1
// hemisphere over 28 rotation crystals, so the 100.5% bound is never approached and no
// decision changes - it would only put a figure into the report that reads as the dataset's
// completeness and is not one. Two cheaper stand-ins were measured on that corpus and failed:
// pass 2's search-merge OBSERVATION count never drops below 90% of pass 1's even when pass 2
// predicts 44% fewer partials, and pass 2's search-merge COMPLETENESS relative to pass 1's
// fires only on passes that reached FINER, because this merge is never resolution-cut and the
// possible list grows with the range - it reverted two healthy crystals and rescued none.
//
// The comparison is made on each pass's SEARCH merge, not on the final one. Each pass
// determines its own space group, so the two final merges can be in different groups, and
// completeness and CC1/2 in different groups are not the same measurement. The search merge is