"""q02_judgments.py: every judgment and setting the Phase 3 plan fixes before any confirmatory statistic exists.

Each entry is a choice, not a measurement. It is registered once here, with its reason, and the plan, the
Phase 4 analysis and the Phase 4 check read it by name. Settings reused unchanged from Phase 2 are not
registered again: the plan names them directly (s1_folds, s1_repeats, boot_b, ci_level,
min_runs_interpretable, d5_comb_bins, d5_band_lo_hz, d5_band_hi_hz, d5_min_rpm, d9_threshold).
"""
import sys

sys.path.insert(0, "/home/claude/mill/code")
from vals import Values

P3 = "/home/claude/mill/phase3"
V = Values(path=f"{P3}/outputs/values3.json", script="q02_judgments.py")


def J(name, value, unit, reason):
    V.set(name, value, unit, {"population": "analyst judgment", "filter": "Phase 3 plan", "statistic": reason}, kind="judgment")


# ---------------------------------------------------------------- decision rules of the four predictions
J("alpha_family", 0.05, "probability", "family-wise error rate over the confirmatory predictions, controlled by the Holm procedure")
J("thr_auc_drop", 0.05, "AUC", "smallest fall in pooled AUC from run-held-out to tool-family-held-out evaluation that counts as a practical loss (H1, H2)")
J("thr_kappa_frac", 0.5, "fraction", "position of the H3 threshold on the way from the kappa expected under independence within spindle-speed classes to the largest kappa the per-class shares allow")
J("speed_class_edge_rpm", 9000, "r/min", "edge between the H3 spindle-speed classes among label 1 paths; each class then holds label 1 paths of more than one tool family and more than min_pos_testable paths (checked in q03_population.py)")
J("max_nonfinite_share", 0.01, "fraction", "largest share of bootstrap draws that may be undefined before a prediction is NOT_TESTED")
J("rel_speed_tol", 0.005, "fraction", "spindle speed error covered by the relative comb of variant V6c: each harmonic zone widens to this share of the harmonic frequency when that exceeds d5_comb_bins; no measurement of the actual speed exists in the dataset")
J("freq_match_tol_hz", 12.5, "Hz", "largest difference between the Acc0 and Sound2 off-harmonic line frequencies that counts as the same line in E9 (two bins of the Acc0 spectrum)")
J("min_pos_testable", 30, "paths", "fewest label 1 paths in any training set, comparison group or family for a statistic to be computed")
# ---------------------------------------------------------------- model and resampling settings
J("lr_c", 1.0, "inverse penalty", "inverse regularisation strength of the logistic model (the scikit-learn default used by the Phase 2 screen)")
J("rf_trees", 500, "trees", "trees in the random forest of variant V3")
J("rf_min_leaf", 5, "paths", "smallest leaf of the random forest of variant V3")
J("winsor_q", 0.01, "fraction", "tail share clipped on each side of every feature in variant V5, with limits fitted on the training fold only")
J("comb_bins_v6a", 1, "bins", "narrower comb of variant V6a: bins treated as harmonic on each side of a spindle harmonic")
J("comb_bins_v6b", 3, "bins", "wider comb of variant V6b: bins treated as harmonic on each side of a spindle harmonic")
J("band_hi_v7_hz", 5000.0, "Hz", "upper edge of the searched band in variant V7")
J("seed_analysis", 20260922, "seed", "seed of every random split and resample in Phases 3 and 4 (the Phase 2 seed)")
V.set("auc_chance", 0.5, "AUC", {"population": "definition", "filter": "none", "statistic": "AUC of a score unrelated to the label"})
V.set("kappa_independent", 0.0, "kappa", {"population": "definition", "filter": "none", "statistic": "kappa of two indicators that are independent"})
# ---------------------------------------------------------------- figures (venue limits are v_* values from q01_venue.py)
J("fig_font_pt", 8, "pt", "lettering size of every figure at final size")
J("fig_line_pt", 0.5, "pt", "thinnest line in any figure at final size")
J("fig1_height_mm", 60.0, "mm", "height of Fig. 1 at final size")
J("fig2_height_mm", 60.0, "mm", "height of Fig. 2 at final size")
J("fig3_height_mm", 100.0, "mm", "height of Fig. 3 at final size")
J("fig4_height_mm", 70.0, "mm", "height of Fig. 4 at final size")
J("fig5_height_mm", 70.0, "mm", "height of Fig. 5 at final size")
J("words_main_max", 8000, "words", "self-imposed ceiling on the main text (title to conclusions, without references, tables, captions and declarations); the guidelines state no limit for original articles")
J("keywords_planned", 5, "keywords", "keywords planned for the title page")
J("structure_levels_planned", 2, "levels", "deepest heading level planned for the manuscript (section and subsection)")
# ---------------------------------------------------------------- calibration of the plan's risks
J("p_fail_tool", 0.30, "probability", "probability that the tool analysis (H1, H2) is judged a property of this one design and cannot support a general recommendation")
J("p_fail_indicator", 0.25, "probability", "probability that the spectral indicator is judged unvalidated, so the chatter part of the paper cannot stand")
J("p_fail_null", 0.20, "probability", "probability that no prediction is confirmed and robust, leaving only findings already seen in Phase 2")
J("conf_plan", 0.60, "probability", "confidence that executing this plan yields a manuscript that passes the IJAMT desk")
J("conf_plan_target", 0.70, "probability", "confidence level below which the plan must state what evidence would raise it")
V.save()
print("q02_judgments: registered", len([k for k in V.v if V.v[k]["source"] == "q02_judgments.py"]), "values")
