1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
//! pounce#748 — what the default-on μ-strategy retry is allowed to
//! trigger on.
//!
//! #748 turned `mu_strategy_fallback` on by default, to pay for #746's
//! `dirichlet120` casualty. The retry re-runs a solve under the other
//! `mu_strategy` and keeps the second answer only if it reaches
//! `Solve_Succeeded`. Since #138 it had triggered on two statuses:
//! `Maximum_Iterations_Exceeded` and `Solved_To_Acceptable_Level`.
//!
//! Carrying both into the default broke five test targets, all the same
//! way, and the fixture sweep did not see any of it — the sweep runs
//! default options only, and every one of these needs a non-default
//! option to provoke the downgrade the retry then erased:
//!
//! ```text
//! optimize_hs71::hs071_kkt_fidelity_tol_downgrades_succeeded
//! masked_certificate_fuzz::the_earliest_refusal_is_the_one_restored_not_the_strictest
//! issue_616_ls_init_downgrades::the_safeguards_measured_cost_is_now_csfi2_alone
//! issue_250_dual_guard_never_worse::dual_guard_diversion_does_not_return_a_worse_point
//! issue_534_resto_decline_progress::a_lost_deferral_costs_a_bounded_number_of_iterations
//! ```
//!
//! `Solved_To_Acceptable_Level` is not a failure — it is a converged
//! answer at the acceptable tolerance — and retrying it by default is
//! wrong three separate ways:
//!
//! 1. It doubles the cost of a solve that already succeeded. "One extra
//! solve on a run that had already failed" does not describe this.
//! 2. It launders downgrades the caller induced *deliberately* — a tight
//! `kkt_fidelity_tol`, a certificate veto, `least_square_init_primal`
//! — so the signal those options exist to produce never arrives.
//! 3. The retry returns the other run's **point**, not just its status,
//! so it can hand back a different local solution. On
//! `autocorr_bern55-06` with the dual-divergence guard enabled it
//! swapped -2304.0000278 for -2320.0000298.
//!
//! So #748 made the default-on retry trigger on
//! `Maximum_Iterations_Exceeded` alone, and an explicit
//! `mu_strategy_fallback=yes` kept the historical pair. `dirichlet120`
//! stalls at max-iterations, so #748's motivating case is recovered
//! either way.
//!
//! The cost of that narrowing, measured at the time: the three
//! fixture-legs the flip had gained went back to where main had them,
//! and they were the only three that had moved.
//!
//! ```text
//! exact csfi2 SolveSucceeded 21 -> SolvedToAcceptableLevel 35
//! lbfgs eigenb2 SolvedToAcceptableLevel 41 -> SolvedToAcceptableLevel 69
//! lbfgs pooling_rt2stp SolveSucceeded 295 -> SolvedToAcceptableLevel 362
//! ```
//!
//! # pounce#757 supersedes the status-only half of that rule
//!
//! Narrowing by *status* threw out the stock-configuration recoveries to
//! protect the caller-configured ones. Look again at the five broken
//! targets above: every one of them arms a non-default option to provoke
//! the downgrade the retry erased — `kkt_fidelity_tol`, a certificate
//! veto, `dual_diverging_streak`, `resto_decline_deferrals`. Objections 2
//! and 3 are properties of a caller-MODIFIED configuration, not of the
//! exit status, so the condition that actually separates the cases is not
//! "did we end acceptable" but "did the caller tell us what termination
//! means".
//!
//! #757 makes that the rule. The default-on retry now also takes
//! `Solved_To_Acceptable_Level`, but only while the caller has named none
//! of `Application::TERMINATION_POLICY_OPTIONS`. Objection 1 — cost —
//! survives intact and is the accepted price; what it buys is
//! `cho_parmest`, which stalls 5% short of `tol` on the dual term alone
//! with the iterate frozen, and which adaptive certifies in 20 iterations.
//! The three fixture-legs in the table above come back, and the sweep
//! moves nothing else: 3 of 142 lines, both legs, all improvements.
//!
//! What #748 pinned that still holds is below — the opt-in, the
//! `mu_strategy` condition, and the stand-down, which has simply moved
//! from "any acceptable-level exit" to "an acceptable-level exit the
//! caller's own options may have caused". `issue_757_acceptable_retry`
//! owns the positive half.
use PathBuf;
use Command;
use SolveReport;
/// The stand-down, in the form #757 left it: an acceptable-level exit is
/// retried by default, *unless* the caller armed one of the options that
/// decides what termination means. `csfi2` finishes
/// `Solved_To_Acceptable_Level` in 35 iterations and the opposite μ
/// strategy reaches `Solve_Succeeded` in 21 — a genuine improvement the
/// stock configuration is now allowed to take, and a deliberate downgrade
/// the tuned configuration must still be shown.
///
/// If the second half of this test starts reading `SolveSucceeded`, the
/// trigger has widened past `TERMINATION_POLICY_OPTIONS` and every
/// caller-induced downgrade in the suite is being laundered again — see
/// the five targets in this file's header. Status only; the iteration
/// count is the platform-sensitive half.
/// The historical trigger pair is still there for anyone who names it.
/// The retry keeps the second answer only on `Solve_Succeeded`, so asking
/// for it cannot make the status worse — only the wall clock.
/// An explicit `mu_strategy` stands the automatic retry down — #748's
/// condition, pinned end to end rather than at the predicate. Retrying
/// under the other schedule recovers a solve that stalled on a strategy
/// POUNCE chose; it is not licence to override one the caller named, and
/// without this every controlled comparison that pins `mu_strategy` —
/// this repository's own benchmark arms included — would silently run
/// both arms.