== A. the CAS templates through desktop Giac 1.9 ==
PASS A1 test 1 symbolic: Giac solves (delta - za SE0)/SE1 = zb for n -> ((pvs*pvza+pvs*pvzb)/pvd)^2 = ((za u + zb w)/delta)^2
PASS A1 test 2 symbolic: Giac solves (delta - za SE0)/SE1 = zb for n -> ((sqrt(2)*pvs*pvza+sqrt(2)*pvs*pvzb)/pvd)^2 = ((za u + zb w)/delta)^2
PASS A1 test 3 symbolic: Giac solves (delta - za SE0)/SE1 = zb for n -> ((sqrt(-pvp^2+pvp)*pvza+sqrt(-pvr^2+pvr)*pvzb)/pvd)^2 = ((za u + zb w)/delta)^2
PASS A1 test 4 symbolic: Giac solves (delta - za SE0)/SE1 = zb for n -> ((sqrt(2)*sqrt(-pvm^2+pvm)*pvza+sqrt(-pvp^2+pvp-pvr^2+pvr)*pvzb)/pvd)^2 = ((za u + zb w)/delta)^2
PASS A2 32 numeric templates x 7 alphas x 2 tails (448 values): Giac, evaluated at the plot's z, = PPL closed form   []
PASS A2 the PPL closed form = statsmodels (normal_sample_size_one_tail, NormalIndPower, samplesize_proportions_2indep_onetail), 448 cases (NormalIndPower did not converge in 15, n > 1000: normal_sample_size_one_tail there)   []
PASS A2 no CAS text holds a decimal point (BRIEF_CAS rule 1)   []
PASS A2 defaults, test 1: the CAS with the numbers gives (3*pvza+3*pvzb)^2   (3*pvza+3*pvzb)^2
PASS A2 defaults, test 3: the CAS with the numbers gives (5*pvza+2*sqrt(6)*pvzb)^2   (5*pvza+2*sqrt(6)*pvzb)^2
PASS A2 defaults, test 4: the CAS with the numbers gives (3*sqrt(22)/2*pvza+7*pvzb)^2   (3*sqrt(22)/2*pvza+7*pvzb)^2
PASS A2 defaults, test 2: the CAS with the numbers gives (3*sqrt(2)*pvza+3*sqrt(2)*pvzb)^2   (3*sqrt(2)*pvza+3*sqrt(2)*pvzb)^2
PASS A3 1-sided: ceiling(formula) = brute-force n80 in every case (222)   {(1, 0): 222}
PASS A3 2-sided: n80 is never larger than the ceiling, and smaller only by 1 or 2 (215 off by 0, 5 off by 1, 1 off by 2)
   the differing cases: test 1 2-sided a 0.2: n* 1014.269 -> 1015, n80 1014; test 2 2-sided a 0.2: n* 2028.538 -> 2029, n80 2027; test 2 2-sided a 0.2: n* 507.135 -> 508, n80 507; test 4 2-sided a 0.2: n* 898.425 -> 899, n80 898; test 4 2-sided a 0.2: n* 114.054 -> 115, n80 114; test 4 2-sided a 0.2: n* 205.023 -> 206, n80 205
PASS A3 2-sided means tests: ceil(statsmodels NormalIndPower two-sided, both tails) = brute-force n80 (95 cases; 17 where its solver did not converge, n in the thousands)   []
PASS A4 pv_RatS writes 15 (15), 2.5 (25/10), -5 (-5), 0.55 (55/100) ... exactly   []
PASS A4 pv_RatS gives up beyond 6 decimals (the page then skips the CAS line)
PASS A5 Giac 1.9 factor() of the symbolic one-proportion form is WRONG (-34.49, not 152.47): the program does not use factor
   2.5a test 1, as the Prime prints it: {((pvs*pvza+pvs*pvzb)/pvd)^2}
   2.5a test 2, as the Prime prints it: {((√2*pvs*pvza+√2*pvs*pvzb)/pvd)^2}
   2.5a test 3, as the Prime prints it: {((√(-pvp^2+pvp)*pvza+√(-pvr^2+pvr)*pvzb)/pvd)^2}
   2.5a test 4, as the Prime prints it: {((√2*√(-pvm^2+pvm)*pvza+√(-pvp^2+pvp-pvr^2+pvr)*pvzb)/pvd)^2}
PASS A6 2.5a: every template (4 symbolic, 32 numeric), read as on the calculator, arrives in braces with the root sign, passes pv_CasUse, and has the value of desktop Giac's answer   []

== B. the program in the harness (ppl_run_v3e; 2.5b) ==
PASS B1 test 1, 1-sided: panel "n₈₀ = 56 (55.6)", inside the panel, clear of the SE line   [('SE₀ = σ/√n = 15/√30 = 2.74', 8.0), ('n₈₀ = 56 (55.6)', 228.0)]
PASS B2 test 1, 1-sided formula page: CAS solve, CAS numbers, PPL n = 55.64, round up = 56 = n80, the right explanation, layout
PASS B2 2.5a: every CAS text asks for string(...), every answer arrives quoted; no CAS variable assigned, no CAS call of a variable   [('string(solve((pvd-pvza*pvs/sqrt(pvn))/(pvs/sqrt(pvn))=pvzb,pvn))', '"{((pvs*pvza+pvs*pvzb)/pvd)^2}"', 208.5855007171631)]
PASS B2 test 1 page shows "(μ₁−μ₀ − zα×SE₀)/SE₁ = zβ,  SE₀ = SE₁ = σ/√n"
PASS B2 test 1 page shows "n = ((σ×zα+σ×zβ)/(μ₁−μ₀))^2"
PASS B2 test 1 page shows "CAS, with σ = 15, |μ₁−μ₀| = 5 (z kept exact):"
PASS B2 test 1 page shows "n = (3×zα+3×zβ)^2"
PASS B2 test 1 page shows "n = ((15×1.645 + 15×0.842)/5)^2 = 55.64"
PASS B1 test 1, 2-sided: panel "n₈₀ = 71 (70.6)", inside the panel, clear of the SE line   [('SE₀ = σ/√n = 15/√30 = 2.74', 8.0), ('n₈₀ = 71 (70.6)', 228.0)]
PASS B2 test 1, 2-sided formula page: CAS solve, CAS numbers, PPL n = 70.64, round up = 71 = n80, the right explanation, layout
PASS B1 test 2, 1-sided: panel "n₈₀ = 112 (111.3)", inside the panel, clear of the SE line   [('SE₀ = σ√(2/n) = 15√(2/30) = 3.87', 8.0), ('n₈₀ = 112 (111.3)', 221.0)]
PASS B2 test 2, 1-sided formula page: CAS solve, CAS numbers, PPL n = 111.29, round up = 112 = n80, the right explanation, layout
PASS B1 test 2, 2-sided: panel "n₈₀ = 142 (141.3)", inside the panel, clear of the SE line   [('SE₀ = σ√(2/n) = 15√(2/30) = 3.87', 8.0), ('n₈₀ = 142 (141.3)', 221.0)]
PASS B2 test 2, 2-sided formula page: CAS solve, CAS numbers, PPL n = 141.28, round up = 142 = n80, the right explanation, layout
PASS B1 test 3, 1-sided: panel "n₈₀ = 153 (152.5)", inside the panel, clear of the SE line   [('SE₀ = √(0.5×0.5/100) = 0.0500', 8.0), ('n₈₀ = 153 (152.5)', 221.0)]
PASS B2 test 3, 1-sided formula page: CAS solve, CAS numbers, PPL n = 152.46, round up = 153 = n80, the right explanation, layout
PASS B2 2.5a test 3: the CAS lines carry the Prime's root sign, shown as it is, and no "sqrt"   ["critical line, which is zα SE₀ past H₀'s centre:", '  (p₁−p₀ − zα×SE₀)/SE₁ = zβ,', '  SE₀ = √(p₀(1−p₀)/n),  SE₁ = √(p₁(1−p₁)/n)', 'CAS, solved for n:', '  n = ((√(-p₀^2+p₀)×zα+√(-p₁^2+p₁)×zβ)/(p₁−p₀))^2', 'CAS, with p₀ = 0.5, p₁ = 0.6 (z kept exact):']
PASS B1 test 3, 2-sided: panel "n₈₀ = 194 (193.8)", inside the panel, clear of the SE line   [('SE₀ = √(0.5×0.5/100) = 0.0500', 8.0), ('n₈₀ = 194 (193.8)', 221.0)]
PASS B2 test 3, 2-sided formula page: CAS solve, CAS numbers, PPL n = 193.85, round up = 194 = n80, the right explanation, layout
PASS B1 test 4, 1-sided: panel "n₈₀ = 305 (304.99)", inside the panel, clear of the SE line   [('SE₀ = √(2×0.55×0.45/100) = 0.0704', 8.0), ('n₈₀ = 305 (304.99)', 215.0)]
PASS B2 test 4, 1-sided formula page: CAS solve, CAS numbers, PPL n = 304.99, round up = 305 = n80, the right explanation, layout
PASS B1 test 4, 2-sided: panel "n₈₀ = 388 (387.3)", inside the panel, clear of the SE line   [('SE₀ = √(2×0.55×0.45/100) = 0.0704', 8.0), ('n₈₀ = 388 (387.3)', 221.0)]
PASS B2 test 4, 2-sided formula page: CAS solve, CAS numbers, PPL n = 387.34, round up = 388 = n80, the right explanation, layout
PASS B3 five openings of the page: CAS calls 2 + 0 + 0 + 0 + 1 = 3 (symbolic once; numbers again only when mu1 changed; n and alpha never, because z stays a symbol)   3 calls: ['string(solve((pvd-pvza*pvs/sqrt(pvn))/(p', 'string(solve((((105)-(100))-pvza*(15)/sq', 'string(solve((((106)-(100))-pvza*(15)/sq']
PASS B3 after Right (mu1 106) the CAS line reads n = (15/6×zα+15/6×zβ)^2 in some exact form   ['CAS, solved for n:', '  n = ((σ×zα+σ×zβ)/(μ₁−μ₀))^2', 'CAS, with σ = 15, |μ₁−μ₀| = 6 (z kept exact):']
PASS B3 after alpha+ (0.10) the PPL line uses z(0.9) = 1.282
PASS B4 an H1 drag, an n drag, arrows and soft keys: no CAS call at all   0
PASS B4 the panel's formula n follows the drag (PPL): final "(7.0)"
PASS B5 cas=fail: no error; the page says "decimal", gives the textbook form, keeps the PPL numbers   ['Where n comes from', 'decimal', "Power = 0.80 when H₁'s centre is zβ SE₁ past the", "critical line, which is zα SE₀ past H₀'s centre:", '  (p₁−p₀ − zα×SE₀)/SE₁ = zβ,', '  SE₀ = √(p₀(1−p₀)/n),  SE₁ = √(p₁(1−p₁)/n)', '(no CAS: the formula as textbooks print it)', '  n = ((zα√(p₀(1−p₀)) + zβ√(p₁(1−p₁)))/(p₁−p₀))^2', '(no CAS line with p₀ = 0.5, p₁ = 0.6)']
PASS B5 cas=fail: the panel is the same as with the CAS ("n₈₀ = 153 (152.5)")
PASS B6 2-sided, alpha 0.20, mu1 101: n* = 1014.27 -> 1015, n80 = 1014; the page says n80 stops 1 sooner   ['2-sided: the formula drops the far tail, whose', 'tiny extra power lets n₈₀ stop 1 sooner.', 'any key or tap = back   (CAS: 1 ms)']
PASS B6 panel "n₈₀ = 1014 (1014.27)"
PASS B7 no effect (mu1 = mu0): the panel has no bracket, the page says no n is enough, one CAS call   ['Where n comes from', 'exact (CAS)', "Power = 0.80 when H₁'s centre is zβ SE₁ past the", "critical line, which is zα SE₀ past H₀'s centre:", '  (μ₁−μ₀ − zα×SE₀)/SE₁ = zβ,  SE₀ = SE₁ = σ/√n', 'CAS, solved for n:', '  n = ((σ×zα+σ×zβ)/(μ₁−μ₀))^2', 'No effect (σ = 15, |μ₁−μ₀| = 0): no n is enough.', 'any key or tap = back   (CAS: 1 ms)']
PASS B8 Menu has 9 items and "Sample-size formula" opens the page   ['Edit values', 'Toggle 1/2-sided', 'Set α', 'Power vs n curve', 'Power vs effect size', 'Sample-size formula', 'Change test', 'Help', 'Return to plot']
PASS B8 help: three pages, page 3 is the n formula, all text inside x 318
PASS B9 Pow-n view: "formula: 55.6 → 56" in magenta under the green n80 label
PASS B10 answers wrapped in quotes: stripped by the kit, the page is exact
PASS B10 an approximate-mode answer (decimals) is refused: badge "decimal", no CAS number line
PASS B11 stale-key mode: the menu's Enter does not skip the formula page   []

== B12. v2.4's verify_PowerViz.py run against v2.5b (harness v3d) ==
   64 PASS, 1 FAIL
   FAIL soft key Menu -> Help: two drawn pages
   SCI-LIST []
PASS B12 v2.4's verification runs to the end on v2.5: 64 PASS, the only FAIL is the intended help-page count   []

== G. 2.5a: v2.5 in harness v3b, and v2.5a against v2.5 ==
PASS G v2.5 in v3b: its pv_Cas hands back its own text, so the page shows the textbook form and "decimal"

G. v2.5a: v2.5 in harness v3b, and v2.5a against v2.5
PASS v2.5a: routines that differ from v2.5: ['pv_Cas'] (want pv_Cas)
PASS v2.5a: outside those routines only comments differ
PASS v2.5a: the #PYTHON blocks are unchanged
  routines that differ from v2.5: pv_Cas; everything else differs only in comments

== R. 2.5b: the round-2 string fixes (harness v3d) ==
PASS R1 2.5b: a failed CAS call -> pv_Cas returns "" with no error
PASS R1 v2.5a in v3d: the same call stops the program   INSTRING: Invalid input (the first argument is an empty stri
PASS R1 2.5b: an empty CAS string -> "", undef -> "", {7/2} kept
PASS R2 2.5b cas=fail, test 1, 1-sided: the formula page opens with "decimal" and the textbook form, no error
PASS R2 v2.5a in v3d, cas=fail, test 1, 1-sided: stops   INSTRING: Invalid input (the first argument 
PASS R2 2.5b cas=fail, test 2, 1-sided: the formula page opens with "decimal" and the textbook form, no error
PASS R2 v2.5a in v3d, cas=fail, test 2, 1-sided: stops   INSTRING: Invalid input (the first argument 
PASS R2 2.5b cas=fail, test 3, 1-sided: the formula page opens with "decimal" and the textbook form, no error
PASS R2 v2.5a in v3d, cas=fail, test 3, 1-sided: stops   INSTRING: Invalid input (the first argument 
PASS R2 2.5b cas=fail, test 4, 1-sided: the formula page opens with "decimal" and the textbook form, no error
PASS R2 v2.5a in v3d, cas=fail, test 4, 1-sided: stops   INSTRING: Invalid input (the first argument 
PASS R2 2.5b cas=fail, test 2, 2-sided: the formula page opens with "decimal" and the textbook form, no error
PASS R2 v2.5a in v3d, cas=fail, test 2, 2-sided: stops   INSTRING: Invalid input (the first argument 
PASS R2 2.5b cas=fail, test 4, menu route: the formula page opens with "decimal" and the textbook form, no error
PASS R2 v2.5a in v3d, cas=fail, test 4, menu route: stops   INSTRING: Invalid input (the first argument 
PASS R2 2.5b cas=fail, no effect: the formula page opens with "decimal" and the textbook form, no error
PASS R2 v2.5a in v3d, cas=fail, no effect: stops   INSTRING: Invalid input (the first argument 
PASS R3 pv_Rep('pvza+pvzb', 'pvzb', 'zβ') = 'pvza+zβ'
PASS R3 pv_Rep('pvza+pvzb', 'pvza', 'zα') = 'zα+pvzb'
PASS R3 pv_Rep('pvd', 'pvd', 'δ') = 'δ'
PASS R3 pv_Rep('3*pvs*pvs', 'pvs', 'σ') = '3*σ*σ'
PASS R3 pv_Rep('a*b', '', 'x') = 'a*b'
PASS R3 pv_Rep('', 'pvd', 'δ') = ''
PASS R3 pv_Rep('', '', 'x') = ''
PASS R3 pv_Rep('abc', 'pvd', 'δ') = 'abc'
PASS R3 pv_Rep('2*3*', '*', '×') = '2×3×'
PASS R3 pv_Rep('**', '*', '') = ''
PASS R3 pv_Strip('') = ''
PASS R3 pv_Strip('{}') = ''
PASS R3 pv_Strip('list[(3*pvza)^2]') = '(3*pvza)^2'
PASS R3 pv_Strip('{((pvs*pvza+pvs*pvzb)/pvd)^2}') = '((pvs*pvza+pvs*pvzb)/pvd)^2'
PASS R3 pv_Strip('list') = ''
PASS R3 v2.5a in v3d: pv_Rep with the pattern at the end stops   INSTRING: Invalid input (the first argument 
PASS R3 2.5b: CAS answers ending in pvzb: the page opens "exact (CAS)" and shows them   ["critical line, which is zα SE₀ past H₀'s centre:", '  (μ₁−μ₀ − zα×SE₀)/SE₁ = zβ,  SE₀ = SE₁ = σ/√n', 'CAS, solved for n:', '  n = (zα+zβ)^2×σ^2/(μ₁−μ₀)^2×zβ/zβ', 'CAS, with σ = 15, |μ₁−μ₀| = 5 (z kept exact):']
PASS R3 v2.5a in v3d, the same canned answers: stops in pv_Rep   INSTRING: Invalid input (the first argument 
PASS R4 pv_FMT rounds first: ['0.00', '0.01', '0.1', '0.0', '1.645', '55.64']
PASS R4 pv_NumS(0.0004) = "0.000", pv_NumS(2.5) = "2.5", pv_NumD(0.00004) = "0.0000", pv_NumD(0.0005) = "0.0005"
PASS R4 v2.5a in v3d: pv_FMT(0.0033, 2) = '3.30ᴇ-3', pv_NumS(0.0004) = '4.000ᴇ-4' (the finding)
PASS R4 2.5b mu1 = 100.001 (d = 0.0000667): ['at d = 0.00: power = 0.050, key or tap = back'], summary ['effect = 0.0010   d = 0.000']; sigma 0.0004: ['SE₀ = σ/√n = 0.000/√30 = 0.0000730']; no scientific text
PASS R4 v2.5a in v3d, the same inputs: ['at d = 6.67ᴇ-5: power = 0.050, key or tap = back'], ['effect = 0.0010   d = 6.667ᴇ-5'], ['SE₀ = σ/√n = 4.000ᴇ-4/√30 = 0.0000730']
PASS R5 2.5b (and 2.5c: + POWERVIZ, pv_BetaS, pv_Draw, pv_PCDraw, pv_Rel, pv_Tails): routines that differ from v2.5a: ['POWERVIZ', 'pv_BetaS', 'pv_Cas', 'pv_Draw', 'pv_FMT', 'pv_FMTP', 'pv_Formula', 'pv_NCF', 'pv_NumD', 'pv_NumS', 'pv_PCDraw', 'pv_Rel', 'pv_Rep', 'pv_ShowHelp', 'pv_Strip', 'pv_Tails']
PASS R5 2.5b: outside those routines only comments differ
PASS R5 2.5b: 49 of the 49 untouched routines are byte-identical, comments included
  INSTRING sites in v2.5b: 502, 540, 545, 560, 565, 579, 580, 581, 732, 733
  harness runs: 34 of v2.5c here, plus B12's subprocess; 14 of v2.5 / v2.5a / v2.5b
  h.sci_strings, v2.5b: []
  h.sci_strings, B12 (v2.4's script on v2.5b): []
  h.sci_strings, v2.5 / v2.5a (for comparison): [(6.6666667e-05, 2, '6.67ᴇ-5'), (6.6666667e-05, 3, '6.667ᴇ-5'), (0.0004, 3, '4.000ᴇ-4'), (0.0033, 2, '3.30ᴇ-3')]
PASS R6 2.5b: no scientific STRING(x, 2, d) result in any of the 34 v2.5b runs, nor in B12

== T. 2.5c: no "=" before a relation; beta of its own (harness v3e) ==
   T1 typed alpha 0.0001, d 0.033: v2.5b (['α = < 0.001', 'β = 1.000'], 'n = 30/group  α = < 0.001  1-sided', 'POWER = 0.0002   (β = 0.9998)')  ->  v2.5c (['α < 0.001', 'β > 0.999'], 'n = 30/group  α < 0.001  1-sided', 'POWER = 0.0002   (β = 0.9998)')
PASS T1 typed alpha 0.0001, d 0.033: v2.5b (['α = < 0.001', 'β = 1.000'], 'n = 30/group  α = < 0.001  1-sided', 'POWER = 0.0002   (β = 0.9998)')
PASS T1 typed alpha 0.0001, d 0.033: v2.5c (['α < 0.001', 'β > 0.999'], 'n = 30/group  α < 0.001  1-sided', 'POWER = 0.0002   (β = 0.9998)')
   T1 typed alpha 0.00001, no effect: v2.5b (['α = < 0.001', 'β = 1.000'], 'n = 30/group  α = < 0.001  1-sided', 'POWER = < 0.0001   (β = 1.0000)')  ->  v2.5c (['α < 0.001', 'β > 0.999'], 'n = 30/group  α < 0.001  1-sided', 'POWER < 0.0001   (β > 0.9999)')
PASS T1 typed alpha 0.00001, no effect: v2.5b (['α = < 0.001', 'β = 1.000'], 'n = 30/group  α = < 0.001  1-sided', 'POWER = < 0.0001   (β = 1.0000)')
PASS T1 typed alpha 0.00001, no effect: v2.5c (['α < 0.001', 'β > 0.999'], 'n = 30/group  α < 0.001  1-sided', 'POWER < 0.0001   (β > 0.9999)')
   T1 n 200, d 0.67: v2.5b (['α = 0.050', 'β = < 0.001'], 'n = 200/group  α = 0.050  1-sided', 'POWER = 1.0000   (β = < 0.0001)')  ->  v2.5c (['α = 0.050', 'β < 0.001'], 'n = 200/group  α = 0.050  1-sided', 'POWER > 0.9999   (β < 0.0001)')
PASS T1 n 200, d 0.67: v2.5b (['α = 0.050', 'β = < 0.001'], 'n = 200/group  α = 0.050  1-sided', 'POWER = 1.0000   (β = < 0.0001)')
PASS T1 n 200, d 0.67: v2.5c (['α = 0.050', 'β < 0.001'], 'n = 200/group  α = 0.050  1-sided', 'POWER > 0.9999   (β < 0.0001)')
   T1 n 5000, d 0.67: v2.5b (['α = 0.050', 'β = 0.000'], 'n = 5000/group  α = 0.050  1-sided', 'POWER = 1.0000   (β = 0.0000)')  ->  v2.5c (['α = 0.050', 'β < 0.001'], 'n = 5000/group  α = 0.050  1-sided', 'POWER > 0.9999   (β < 0.0001)')
PASS T1 n 5000, d 0.67: v2.5b (['α = 0.050', 'β = 0.000'], 'n = 5000/group  α = 0.050  1-sided', 'POWER = 1.0000   (β = 0.0000)')
PASS T1 n 5000, d 0.67: v2.5c (['α = 0.050', 'β < 0.001'], 'n = 5000/group  α = 0.050  1-sided', 'POWER > 0.9999   (β < 0.0001)')
   T1 defaults: v2.5b (['α = 0.050', 'β = 0.428'], 'n = 30/group  α = 0.050  1-sided', 'POWER = 0.5718   (β = 0.4282)')  ->  v2.5c (['α = 0.050', 'β = 0.428'], 'n = 30/group  α = 0.050  1-sided', 'POWER = 0.5718   (β = 0.4282)')
PASS T1 defaults: v2.5b (['α = 0.050', 'β = 0.428'], 'n = 30/group  α = 0.050  1-sided', 'POWER = 0.5718   (β = 0.4282)')
PASS T1 defaults: an ordinary panel and exit box are the same in v2.5c: (['α = 0.050', 'β = 0.428'], 'n = 30/group  α = 0.050  1-sided', 'POWER = 0.5718   (β = 0.4282)')
   T1 2-sided, typed alpha 0.0001: v2.5b (['α = < 0.001', 'β = 1.000'], 'n = 30/group  α = < 0.001  2-sided', 'POWER = 0.0002   (β = 0.9998)')  ->  v2.5c (['α < 0.001', 'β > 0.999'], 'n = 30/group  α < 0.001  2-sided', 'POWER = 0.0002   (β = 0.9998)')
PASS T1 2-sided, typed alpha 0.0001: v2.5b (['α = < 0.001', 'β = 1.000'], 'n = 30/group  α = < 0.001  2-sided', 'POWER = 0.0002   (β = 0.9998)')
PASS T1 2-sided, typed alpha 0.0001: v2.5c (['α < 0.001', 'β > 0.999'], 'n = 30/group  α < 0.001  2-sided', 'POWER = 0.0002   (β = 0.9998)')
PASS T1 the tails hint, typed alpha 0.0001: v2.5b ['2-sided: α = < 0.001 is split, < 0.0001 in each tail,'] -> v2.5c ['2-sided: α < 0.001 is split, < 0.0001 in each tail,']
PASS T1 curve view 1, typed alpha 0.0001: v2.5b ['μ₁ = 100.50, d = 0.03, tiny, α = < 0.001, 1-sided', 'at n = 30: power = < 0.001, touch = pick n, key = back'] -> v2.5c ['μ₁ = 100.50, d = 0.03, tiny, α < 0.001, 1-sided', 'at n = 30: power < 0.001, touch = pick n, key = back']
PASS T1 curve view 2, typed alpha 0.0001: v2.5b ['n = 30/grp, α = < 0.001, 1-sided', 'at d = 0.03: power = < 0.001, key or tap = back'] -> v2.5c ['n = 30/grp, α < 0.001, 1-sided', 'at d = 0.03: power < 0.001, key or tap = back']
PASS T1 curve view 1, defaults: the same in v2.5b and v2.5c: ['μ₁ = 105, d = 0.33, small, α = 0.050, 1-sided', 'at n = 30: power = 0.572, touch = pick n, key = back']
PASS T2 pv_BetaS over 1152 states (4 tests, 2 tails, 4 alphas, n 2-5000, 6 effects; 3 and 4 decimals): the text v2.5b printed for 1 - PW wherever 1 - PW still had its digits, else the floor where SciPy's beta is below it (2304 / 2304)
PASS T2 the beta pv_BetaS computes is SciPy's P(XCL < X < XCU) to 3.4e-13 relative, down to 1E-290
PASS T3 pv_Rel: "< 0.001" -> " < 0.001", "> -0.001" -> " > -0.001", "0.050" -> " = 0.050", "" -> " = ": [' < 0.001', ' > -0.001', ' = 0.050', ' = ']
PASS T4 the drag clamps alpha to 0.001-0.5 (so the drag and snap hints never reach the floor), unchanged
PASS T4 the plot's beta and power labels (2 decimals) are never drawn below 0.01 (120 states; v2.5b's 960-state sweep found none either): []
PASS T5 routines that differ from v2.5b: ['POWERVIZ', 'pv_BetaS', 'pv_Draw', 'pv_PCDraw', 'pv_Rel', 'pv_Tails'] (pv_BetaS, pv_Rel new)
PASS T5 the code lines that changed are exactly the 11 listed (and the two new routines): -[] +[]
PASS T5 the new names pv_Rel, pv_BetaS, rlS, bsD, bsV are not built-ins (case ignored) and carry the pv_ tag
PASS T5 version strings (2.5d: v2.5d's): the banner, the tested-on lines, the v2.5d paragraph above v2.5c's
PASS T5 no // comment inside an open bracket: []
PASS T5 INSTRING: the same guarded lines as v2.5b (2.5d: in v2.5d too); pv_Rel reads LEFT(rlS, 1) only inside IF DIM(rlS) > 0
PASS T6 no scientific STRING(x, 2, d) result in any of the 165 v2.5c runs (section T included)

== U. 2.5d: P1, the top floor, the disclaimer (harness v3e) ==
PASS U1 P1 test 1, {'MM1': 107.5, 'AL': 0.999}, CAS giac: v2.5c NCF 20.225, "Round UP (whole people)" -> v2.5d NCF -1, no value, "no root", "Power is above 0.80 at every n", and why   ['  n = ((15×-3.090 + 15×0.842)/7.5)^2', '    no root: the bracket is 0 or less, and √n > 0', 'Power is above 0.80 at every n;  trying n: n₈₀ = 2', '1-sided α above 0.5: the test rejects H₀ more', 'often than not even when there is no effect.', 'any key or tap = back   (CAS: 1 ms)']
PASS U1 P1 test 1, {'MM1': 107.5, 'AL': 0.999}, CAS fail: v2.5c NCF 20.225, "Round UP (whole people)" -> v2.5d NCF -1, no value, "no root", "Power is above 0.80 at every n", and why   ['  n = ((15×-3.090 + 15×0.842)/7.5)^2', '    no root: the bracket is 0 or less, and √n > 0', 'Power is above 0.80 at every n;  trying n: n₈₀ = 2', '1-sided α above 0.5: the test rejects H₀ more', 'often than not even when there is no effect.', 'any key or tap = back   (CAS: 1 ms)']
PASS U1 P1 test 1: the panel's n80 line: v2.5c 'n₈₀ = 2 (20.2)' -> v2.5d 'n₈₀ = 2' (no bracket)
PASS U1 P1 test 2, {'AL': 0.9}, CAS giac: v2.5c NCF 3.484, "Round UP (whole people)" -> v2.5d NCF -1, no value, "no root", "Power is above 0.80 at every n", and why   ['  n = ((15√2×-1.282 + 15√2×0.842)/5)^2', '    no root: the bracket is 0 or less, and √n > 0', 'Power is above 0.80 at every n;  trying n: n₈₀ = 2', '1-sided α above 0.5: the test rejects H₀ more', 'often than not even when there is no effect.', 'any key or tap = back   (CAS: 1 ms)']
PASS U1 P1 test 2, {'AL': 0.9}, CAS fail: v2.5c NCF 3.484, "Round UP (whole people)" -> v2.5d NCF -1, no value, "no root", "Power is above 0.80 at every n", and why   ['  n = ((15√2×-1.282 + 15√2×0.842)/5)^2', '    no root: the bracket is 0 or less, and √n > 0', 'Power is above 0.80 at every n;  trying n: n₈₀ = 2', '1-sided α above 0.5: the test rejects H₀ more', 'often than not even when there is no effect.', 'any key or tap = back   (CAS: 1 ms)']
PASS U1 P1 test 2: the panel's n80 line: v2.5c 'n₈₀ = 2 (3.5)' -> v2.5d 'n₈₀ = 2' (no bracket)
PASS U1 P1 test 3, {'AL': 0.95}, CAS giac: v2.5c NCF 16.820, "Round UP (whole people)" -> v2.5d NCF -1, no value, "no root", "Power is above 0.80 at every n", and why   ['  n = ((√(0.25)×-1.645 + √(0.24)×0.842)/0.1)^2', '    no root: the bracket is 0 or less, and √n > 0', 'Power is above 0.80 at every n;  trying n: n₈₀ = 2', '1-sided α above 0.5: the test rejects H₀ more', 'often than not even when there is no effect.', 'any key or tap = back   (CAS: 1 ms)']
PASS U1 P1 test 3, {'AL': 0.95}, CAS fail: v2.5c NCF 16.820, "Round UP (whole people)" -> v2.5d NCF -1, no value, "no root", "Power is above 0.80 at every n", and why   ['  n = ((√(0.25)×-1.645 + √(0.24)×0.842)/0.1)^2', '    no root: the bracket is 0 or less, and √n > 0', 'Power is above 0.80 at every n;  trying n: n₈₀ = 2', '1-sided α above 0.5: the test rejects H₀ more', 'often than not even when there is no effect.', 'any key or tap = back   (CAS: 1 ms)']
PASS U1 P1 test 3: the panel's n80 line: v2.5c 'n₈₀ = 2 (16.8)' -> v2.5d 'n₈₀ = 2' (no bracket)
PASS U1 P1 test 4, {'AL': 0.99}, CAS giac: v2.5c NCF 109.746, "Round UP (whole people)" -> v2.5d NCF -1, no value, "no root", "Power is above 0.80 at every n", and why   ['  n = ((√(0.495)×-2.326 + √(0.49)×0.842)/0.1)^2', '    no root: the bracket is 0 or less, and √n > 0', 'Power is above 0.80 at every n;  trying n: n₈₀ = 2', '1-sided α above 0.5: the test rejects H₀ more', 'often than not even when there is no effect.', 'any key or tap = back   (CAS: 1 ms)']
PASS U1 P1 test 4, {'AL': 0.99}, CAS fail: v2.5c NCF 109.746, "Round UP (whole people)" -> v2.5d NCF -1, no value, "no root", "Power is above 0.80 at every n", and why   ['  n = ((√(0.495)×-2.326 + √(0.49)×0.842)/0.1)^2', '    no root: the bracket is 0 or less, and √n > 0', 'Power is above 0.80 at every n;  trying n: n₈₀ = 2', '1-sided α above 0.5: the test rejects H₀ more', 'often than not even when there is no effect.', 'any key or tap = back   (CAS: 1 ms)']
PASS U1 P1 test 4: the panel's n80 line: v2.5c 'n₈₀ = 2 (109.7)' -> v2.5d 'n₈₀ = 2' (no bracket)
PASS U1 P1 Pow-n view, v2.5c: "['formula: 20.2 → 21']"
PASS U1 P1 Pow-n view, v2.5d: no "formula:" label ([])
PASS U1 ordinary: test 1, defaults: NCF 55.643, n80 56, the panel's n80 line and the whole formula page are v2.5c's
PASS U1 ordinary: test 1, {'MM1': 107.5, 'AL': 0.5}: NCF 2.833, n80 3, the panel's n80 line and the whole formula page are v2.5c's
PASS U1 ordinary: test 1, {'MM1': 107.5, 'AL': 0.6}: NCF 1.384, n80 2, the panel's n80 line and the whole formula page are v2.5c's
PASS U1 ordinary: test 3, defaults: NCF 152.457, n80 153, the panel's n80 line and the whole formula page are v2.5c's
PASS U1 ordinary: test 4, {'AL': 0.2}: NCF 139.539, n80 140, the panel's n80 line and the whole formula page are v2.5c's
PASS U1 ordinary: test 2, {'AL': 0.05}: NCF 111.286, n80 112, the panel's n80 line and the whole formula page are v2.5c's
PASS U1 sweep, 4 tests x 2 tails x 10 alphas x 4 effects: pv_NCF = the closed form wherever the bracket is positive; in the 80 states where it is not, pv_NCF is -1, the test is 1-sided with alpha above 0.5, and power at n = 2 is already above 0.80 (so "above 0.80 at every n" holds) []
PASS U2 pv_FMTP: v2.5d ['> 0.999', '> 0.999', '0.999', '> 0.9999', '0.9999', '> 0.99', '0.500', '< 0.001', '0.000', '0.050'] (v2.5c ['1.000', '1.000', '0.999', '1.0000', '0.9999', '1.00', '0.500', '< 0.001', '0.000', '0.050'])
PASS U2 pv_Rel on the floor: " > 0.999"
PASS U2 the big POWER readout, {'MM1': 107.5, 'NN': 100}: v2.5c "1.000" -> v2.5d "> 0.999" (font 5 from x 222: ends near 288 < 317); exit box "POWER = 0.9996   (β = 0.0004)"
PASS U2 the big POWER readout, {'MM1': 110, 'NN': 5000}: v2.5c "1.000" -> v2.5d "> 0.999" (font 5 from x 222: ends near 288 < 317); exit box "POWER > 0.9999   (β < 0.0001)"
PASS U2 the big POWER readout, {'MM1': 107.5, 'AL': 0.999}: v2.5c "1.000" -> v2.5d "> 0.999" (font 5 from x 222: ends near 288 < 317); exit box "POWER > 0.9999   (β < 0.0001)"
PASS U2 the big POWER readout, defaults: v2.5c "0.572" -> v2.5d "0.572" (font 5 from x 222: ends near 269 < 317); exit box "POWER = 0.5718   (β = 0.4282)"
PASS U2 plot label, {'MM1': 107.5, 'AL': 0.5}: v2.5c ['power = 1.00'] -> v2.5d ['power > 0.99']
PASS U2 plot label, {'MM1': 100.5, 'AL': 0.0001}: v2.5c ['β = 1.00'] -> v2.5d ['β > 0.99']
PASS U2 plot labels, an ordinary scene (d 0.67, power 0.978): the same in v2.5c and v2.5d: ['power = 0.98']
PASS U2 Pow-n readout at n 200, d 0.67: v2.5c ['at n = 200: power = 1.000, touch = pick n, key = back'] -> v2.5d ['at n = 200: power > 0.999, touch = pick n, key = back']
PASS U2 sweep, 4 tests x 2 tails x 5 scenes (alpha 0.001-0.999, n 2-5000): no POWER 1.000, no "= >" / "= <" []
PASS U3 the header carries the disclaimer word for word (v2.5c: no); the old "For academic use only ... not been rigorously verified" lines stay (D17)
PASS U3 help page 1 shows "Teaching aid; not for clinical or legal use." (font 1, red, y 208: above the footer at 222; 44 characters, ends near x 298 < 317); every other line of the three pages is v2.5c's
   review check_PowerViz.py on v2.5c: 1 failed ['12 probe scenes through main view, Tails, Pow-n, Pow-effect, formula page a']
   review check_PowerViz.py on v2.5d: 1 failed ['12 probe scenes through main view, Tails, Pow-n, Pow-effect, formula page a']
PASS U4 the review's check_PowerViz.py: its one failure on v2.5c (the Pow-n subtitle at sigma = 1E-6, absurd input the review left "as a FAIL in the log for the record"; not on the fix list) is the only one on v2.5d too
PASS U5 routines that differ from v2.5c: ['pv_Draw', 'pv_FMTP', 'pv_Formula', 'pv_NCF', 'pv_ShowHelp']
PASS U5 outside them only comments differ
   code lines removed 2, added 18 (the formula page's 2-sided/1-sided block is re-indented inside an ELSE)
PASS U5 the changed code lines: the guard, the floor, the two labels, the formula page's new branch and the disclaimer line; every other removed line comes back unchanged (re-indented) [] []
PASS U5 no new names (the routines and LOCALs are v2.5c's); no MAKELIST with K added
   h.sci_strings over the 231 v2.5d runs: []
PASS U6 no scientific STRING(x, 2, d) result in any of the 231 v2.5d runs (sections A-U)

174 PASS, 0 FAIL
