# 1. Winner-probability stack (inputs to `MATCH_PR...

Creato il: 28 marzo 2026

Risposto usando GPT-5.4 Thinking da Chat01

Domanda

TennisLocks_v22_FIXED.gs.txt

1. Winner-probability stack (inputs to MATCH_PREVIEW)

To fix the core win probability, we must locate and correct exactly how probabilities from simulation, stats, and Elo are blended, how the market anchor is applied, and how opponent-quality adjustments are capped. Follow these steps in the script:

  • Find the blending function (winner probability): In your code (likely in MATCH_PICK or a similar decision helper), locate the block where pFinal is first set to 0.5 and then weighted by model/stats/Elo (you’ll see THRESHOLDS.BLEND_W_MODEL, BLEND_W_STATS, BLEND_W_ELO used). It typically starts like:

    js
    var pFinal = 0.5; var _hasElo = (Number.isFinite(pElo) && pElo > 0 && pElo < 1); if (_hasElo) { var _wM = THRESHOLDS.BLEND_W_MODEL; var _wS = THRESHOLDS.BLEND_W_STATS; var _wE = THRESHOLDS.BLEND_W_ELO; // final blend happens here }

    Within this if (_hasElo) block, replace the existing blend logic with the exact weighted-average pattern:

    js
    var wM = THRESHOLDS.BLEND_W_MODEL; // 0.42 var wS = THRESHOLDS.BLEND_W_STATS; // 0.42 var wE = THRESHOLDS.BLEND_W_ELO; // 0.16 var wSum = wM + wS + wE; if (wSum <= 0) { wM = 0.5; wS = 0.5; wE = 0; wSum = 1; } var pBlendA = (wM * pSimA + wS * pKernelA + wE * pEloA) / wSum; pBlendA = clamp01(pBlendA);

    Here pSimA is the simulation-based win-prob, pKernelA is the stats/kernel-based win-prob, and pEloA is the Elo-based prob. Use these variables (or their equivalents in your code) in place of your current computation. This enforces the 0.42/0.42/0.16 weights and clamps the result between 0 and 1.

  • Remove any alternative overrides: After blending, make sure no other assignment overrides this probability. Search for any later lines like pFinal = pMarkovA, pFinal = pEloA, or similar. These should be removed or treated as logging only. The final win probability (pFinal or whatever your script uses) must come only from the weighted blend (and subsequent anchor/damp steps), not replaced by a single source.

  • Verify clamp and defaults: Ensure after blending you do pBlendA = clamp01(pBlendA). If your code uses clamp01 or similar, keep it. Also check the “zero-weight” fallback: if for some reason wM+wS+wE is zero, you must set them to .5/.5/0 as above to avoid NaN.

1.2. Market anchor (pull toward odds)

In the same decision function, find the market anchor block. It usually follows the blend, and will have variables like marketDivergence_pick, pull_pick, etc. For example, you might see code that computes an implied market probability (often from devigOdds) and then applies a “pull” to the blend.

  • Swap the divergence sign: The current code may compute marketDivergence = pMktA - pBlendA. Invert this so that diff = pBlendA - pMktA (model minus market). In other words, wherever you see something like

    js
    marketDivergence_pick = pMktA - pBlendA;

    change it to

    js
    var diff = pBlendA - pMktA;

    Then compute sign based on that (sign = (diff>0)?1:(diff<0)?-1:0).

  • Apply capped pull in correct direction: Use a hard cap (8% = 0.08) on the pull and move toward the market without crossing it. The exact replacement code should be:

    js
    var maxPull = 0.08; var pull = Math.min(Math.abs(diff), maxPull); var anchored = pBlendA - pull * sign; // Prevent crossing: if it crosses, set to market prob if ((pBlendA > pMktA && anchored < pMktA) || (pBlendA < pMktA && anchored > pMktA)) { anchored = pMktA; } pFinal = clamp01(anchored);

    In summary: pull = min(|model–market|, 0.08), then subtract that amount (in the sign direction) from the model probability. This ensures favorites are not pulled past fair odds.

  • Check for existing pull logic: If your code uses something like _dir_pull_pick or other constructs, ensure that its logic matches the pattern above. For example, if you see code doing pFinal = clamp01(pFinal + pull * dir), verify that dir is computed as (pBlendA > pMktA ? -1 : +1) or similar. The key is that a positive diff (model > market) should cause a negative pull (pushing down toward the market).

  • Audit any anchor flags: Some code may set flags like marketAnchorApplied. These can remain (they may be for auditing), but make sure they reflect the new logic. The important fix is the sign and clamp logic above.

1.3 Opponent-quality adjustment caps

Find the function that applies opponent-quality boosts to stats, usually named _adjustStatsByOppQuality_ (or similar). This function will adjust hold %, serve/return points, etc., based on how weak the opponent is. We need to cap how much those stats can shift (in logit space) so that beating weak foes doesn’t inflate win-prob too much.

Inside _adjustStatsByOppQuality_, after it computes an adjusted stat (e.g. adjHold, adjSPW, adjRPW or similar) from the raw stat, do the following for each rate: hold %, SPW, RPW, etc. Instead of directly assigning the adjusted value, do:

js
// Example for a single adjusted rate var rawRate = /* original stat from stats object */; var adjRate = /* the computed adjusted stat before capping */; var logRaw = _logit_(rawRate); var logAdj = _logit_(adjRate); var delta = logAdj - logRaw; var maxShift = 0.35; // corresponding to about ±8–10 percentage points if (delta > maxShift) delta = maxShift; if (delta < -maxShift) delta = -maxShift; var finalRate = _sigmoid_(logRaw + delta); // Now overwrite the stat with finalRate stats.hold = finalRate; // or stats.SPWin = finalRate, etc.

In practice, locate where the code says something like stats.hold = someValue; (or sets SPW, RPW). Replace that assignment with the logit-based cap. In each case use _logit_ and _sigmoid_ functions (which should be defined in the script) to translate to log-odds, cap the change (delta), and convert back. This ensures no stat jumps more than ~9–10% up or down from the raw value.

2. Bimodal/decider stack (totals & sets)

This part fixes how the script handles 3-set matches (“deciders”) and ensures consistency between totals, sets, and coinflip language.

2.1 Single canonical P(decider)

In _computeFullBimodal_(…), the code calculates a “decider probability” (pDeciderAuth or pDeciderDisplay). We must use that one value everywhere instead of recomputing or blending it again later.

  • In _computeFullBimodal_, ensure you return a single field named something like pDeciderAuth (often already there or as pDeciderDisplay) as part of the result object. For example, append:

    js
    return { // … existing fields … pDeciderAuth: pDeciderValue, // … other fields … };

    (Replace pDeciderValue with whatever your code currently uses as the authoritative decider prob.)

  • In _computeDeciderSetProb_(sim, 3), instead of recomputing from setScores or holds, use the bimodal result if available. For example, if that function has access to the bimodal object, have it return bimodal.pDeciderAuth (clamped between any min/max if needed). If not easily possible, at least avoid blending p2 vs p3 there. The goal is to rely on the already-calculated decider.

  • In _buildSetsMarketEngine_(ctx), find where it sets up BO3 config. Locate the lines where p3Raw is defined. Change it to use the bimodal auth value. For example:

    js
    // Before: maybe compute from DISP/RAW/HOLD, etc. var p3Raw = bimodal.pDeciderAuth; // use the canonical decider

    Then clamp it into empirical tour bounds:

    js
    var tourK = tourInfo.tour; // e.g. 'ATP','WTA','CH','ITF' var cfgT = SETS_MARKET_CFG.TOUR[tourK] || SETS_MARKET_CFG.TOUR.DEFAULT; var p3 = _clamp_(p3Raw, cfgT.minP3, cfgT.maxP3); var p2 = 1 - p3;

    This ensures the same decider probability drives all decisions (total points language, coinflip mentions, sets pick).

2.2 Use 32k calibration for thresholds

In the BO3 section of _buildSetsMarketEngine_, after you load the 32k-match calibration (var cal = get32kCalibration(tourK); giving cal.mvtDecHigh, .mvtDecMid, .mvtDecLow), set the pick thresholds from it. For example, right after retrieving cal32k, insert:

js
// Using 32k calibration to set BO3 pick thresholds cfg.p3BetThr = Math.max(cfgT.maxP3 - 0.02, cal.mvtDecHigh - 0.02); cfg.p3LeanThr = Math.max(cfgT.baseP3 + 0.06, cal.mvtDecMid); cfg.minDeciderThr = cal.mvtDecLow - 0.03; cfg.p2LeanThr = 1 - cfg.p3LeanThr; cfg.p2BetThr = 1 - cfg.p3LeanThr + 0.04;

This replaces any hard-coded 0.60/0.54/0.44/0.38 thresholds. After this, make sure the logic uses cfg.p3BetThr, cfg.p3LeanThr, cfg.p2BetThr, cfg.p2LeanThr for deciding bets/leans. In the decision rules (like where you compute can2Bet, can2Lean, can3Bet, can3Lean), it should now look like:

js
var can2Bet = !deciderVeto2 && (p2Final >= cfg.p2BetThr + riskPenalty2) && sup2Count >= 2 && (agreementLevel!=='DISAGREE' || p2Final>=0.66); var can2Lean = !deciderVeto2 && (p2Final >= cfg.p2LeanThr + riskPenalty2) && sup2Count >= 1; var can3Bet = !hardSweep3Kill && !minDecider3Kill && (p3Final >= cfg.p3BetThr + riskPenalty3) && sup3Count >= 2 && (agreementLevel!=='DISAGREE' || p3Final>=0.66); var can3Lean = !hardSweep3Kill && !minDecider3Kill && (p3Final >= cfg.p3LeanThr + riskPenalty3) && sup3Count >= 1;

(Here riskPenaltyN are your penalties for risk, already in code.) The key is use the cfg thresholds instead of any fixed constants (SETS_MARKET_CFG.READ_*). This integrates the calibration.

2.3 Built-in veto for bimodal/fragile matches

To prevent low-confidence “BET 2 SETS” picks on matches that are mixed or fragile, add a veto flag.

  • In _computeFullBimodal_: before returning its result, add:
    js
    var vetoSets = false; // Veto if the match is BIMODAL or FRAGILE with a moderate decider probability if ((shape === 'BIMODAL' || hookFlag === 'FRAGILE') && pDeciderAuth > 0.30 && pDeciderAuth < 0.45) { vetoSets = true; } // Return this in the object return { // ...existing fields..., vetoSets: vetoSets };
  • In _buildSetsMarketEngine_: after you determine the final pick and conf for the sets market (2-sets vs 3-sets), add:
    js
    if (bimodal.vetoSets && conf !== 'HIGH') { pick = ''; conf = 'NONE'; }
    This means if vetoSets is true (i.e. a mixed match) and our confidence isn’t very high, cancel the sets pick. Now “BET 2 SETS” won’t appear on fragile/mismatched decider probabilities.

3. Confidence mapping and universal no-bet guard

Finally, clean up how confidence labels (“HIGH”, “MID”, “LOW”) are assigned, and add a final guard against weak edges.

3.1 Winner confidence from edge

Find where you assign a confidence string based on the winner edge (often using something like riskScore * 0.025). Replace that with a function of the actual probability edge:

Define a helper function, e.g. near the top of your script or in a utils area:

js
function confFromEdge(edge, riskPenalty) { var effEdge = Math.max(0, edge - riskPenalty); if (effEdge >= 0.10) return 'HIGH'; if (effEdge >= 0.06) return 'MID'; if (effEdge >= 0.03) return 'LOW'; return 'NONE'; }

Then use it consistently:

  • For the winner market, edge is (model_prob – market_prob) or similar. Compute winnerEdge = Math.abs(pModelA - impliedMarketProbA). Then do winnerConf = confFromEdge(winnerEdge, riskScore * 0.025).
  • For totals, do the same with edge = |pOver - 0.5| (distance from 50%).
  • For sets, use edge = Math.abs(p3Final - 0.5) (for 3-set bet) or similarly for 2-set. Then setsConf = confFromEdge(setsEdge, riskPenalty).

Remove any hard-coded “if edge > X then HIGH” logic. Now all confidences come from this unified mapping.

3.2 No-bet guard in MATCH_PREVIEW

At the very end of your MATCH_PREVIEW function (just before assembling the output text), insert a universal guard. Define a function:

js
function _guardPick(pSide, edge, confLabel) { if (!pSide) return ''; if (!Number.isFinite(edge) || edge < THRESHOLDS.MIN_PICK_CONF) return ''; if (confLabel === 'NONE') return ''; return pSide; }

Then apply it before printing each pick. For example, replace direct usage of winnerPick, totalsPick, setsPick with guarded versions:

js
var finalWinnerPick = _guardPick(winnerSide, winnerEdge, winnerConf); var finalTotalsPick = _guardPick(totalsSide, totalsEdge, totalsConf); var finalSetsPick = _guardPick(setsSide, setsEdge, setsConf);

And in the preview output, use finalWinnerPick etc. If _guardPick returns '', it means omit the “BET” line for that market entirely (leave just neutral commentary). This ensures no weak edges (below MIN_PICK_CONF) slip through on any tour or market.

4. Step-by-step fix order

To systematically apply these changes, do them in this sequence:

  1. Market anchor block (Sec 1.2): Find the market-anchor code in your pick function, swap the diff sign and implement the capped-pull logic as shown.
  2. Decider veto (Sec 2.3): In _computeFullBimodal_, add the vetoSets flag at the end; in _buildSetsMarketEngine_, insert the veto check after picks are chosen.
  3. BO3 engine fixes (Secs 2.1–2.2): In _buildSetsMarketEngine_ (BO3 path only):
    • Replace any local P(3-set) calculation with var p3Raw = bimodal.pDeciderAuth; and clamp it as shown.
    • Right after cal32k = get32kCalibration(tourK), assign cfg.p3BetThr, cfg.p3LeanThr, cfg.minDeciderThr, cfg.p2LeanThr, cfg.p2BetThr using the formulas above.
    • Ensure the can2Bet/can3Bet/etc. logic uses these cfg thresholds (with risk penalties), not old constants.
    • Apply the vetoSets logic to clear the pick if needed (as in step 2).
  4. Add no-bet guard (Sec 3.2): At the end of MATCH_PREVIEW, before printing picks, define _guardPick and wrap each market’s pick. Replace any direct output of winnerSide/totalsSide/setsSide with the guarded result.

After these fixes, your preview text will align with the corrected probabilities and thresholds. Each change above should be done by directly editing the specified functions in your script. Double-check each section for typos, and test on a known example (like the Altmaier–Guerrieri match) to ensure “BET 2 SETS” no longer appears erroneously.

Update my script then send it as a downloadable txt do not write new code on old code else the old code will work u gotta replace old code

Pensiero

bash -lc cat > /mnt/data/patch_tennislocks.py <<'PY' from pathlib import Path import re

path = Path('/mnt/data/TennisLocks_v22_FIXED.gs.txt') text = path.read_text(encoding='utf-8') orig = text

def must_replace(old, new, count=1): global text n = text.count(old) if n != count: raise RuntimeError(f'Expected {count} occurrence(s) for exact replace, found {n} for snippet starting: {old[:80]!r}') text = text.replace(old, new)

def must_sub(pattern, repl, count=1, flags=0): global text new_text, n = re.subn(pattern, repl, text, count=count, flags=flags) if n != count: raise RuntimeError(f'Expected {count} regex replacement(s), found {n} for pattern: {pattern}') text = new_text

1) Add unified confidence + guard helpers near totals confidence scale.

helper_anchor = "var _V20_CONF_PENALTY_SCALE = 0.025;\n" helper_insert = """var _V20_CONF_PENALTY_SCALE = 0.025;\n\nfunction confFromEdge(edge, riskPenalty) {\n var e = Number(edge);\n var rp = Number(riskPenalty);\n if (!Number.isFinite(e)) return 'NONE';\n if (!Number.isFinite(rp)) rp = 0;\n var effEdge = Math.max(0, e - rp);\n if (effEdge >= 0.10) return 'HIGH';\n if (effEdge >= 0.06) return 'MID';\n if (effEdge >= 0.03) return 'LOW';\n return 'NONE';\n}\n\nfunction _guardPick(pSide, edge, confLabel) {\n if (!pSide) return '';\n var e = Number(edge);\n if (!Number.isFinite(e) || e < THRESHOLDS.MIN_PICK_CONF) return '';\n if (String(confLabel || '').toUpperCase() === 'NONE') return '';\n return pSide;\n}\n""" must_replace(helper_anchor, helper_insert, count=1)

2) Replace MATCH_PICK winner blend with strict weighted average and keep pBlendA for anchor.

old_blend_pick = """ var pFinal = 0.5;\n var _hasElo = (Number.isFinite(pElo) && pElo > 0 && pElo < 1);\n if (_hasElo) {\n var _wM = THRESHOLDS.BLEND_W_MODEL;\n var _wS = THRESHOLDS.BLEND_W_STATS;\n var _wE = THRESHOLDS.BLEND_W_ELO;\n var _blTourK = 'ATP';\n try { _blTourK = taperTourKey(tourLabel); } catch(e) { _blTourK = 'ATP'; }\n var _blIsWta = (_blTourK === 'WTA');\n var _blIsCh = (_blTourK === 'CH');\n var _blTrustGate = _blIsWta ? 0.96 : _blIsCh ? 0.955 : 0.95;\n var _blEloCap = _blIsWta ? 0.18 : _blIsCh ? 0.19 : 0.22;\n var _blEloScale = _blIsWta ? 1.8 : _blIsCh ? 1.9 : 2.0;\n var _blNeutBand = _blIsWta ? 0.04 : _blIsCh ? 0.035 : (THRESHOLDS.MODEL_NEUTRAL_BAND || 0.03);\n var _oqA_bl2 = (statsA && statsA.oppQuality) ? statsA.oppQuality : null;\n var _oqB_bl2 = (statsB && statsB.oppQuality) ? statsB.oppQuality : null;\n var _tA_bl2 = (_oqA_bl2 && Number.isFinite(_oqA_bl2.trust)) ? Number(_oqA_bl2.trust) : 1.0;\n var _tB_bl2 = (_oqB_bl2 && Number.isFinite(_oqB_bl2.trust)) ? Number(_oqB_bl2.trust) : 1.0;\n var _trustMin_bl2 = Math.min(_tA_bl2, _tB_bl2);\n if (_trustMin_bl2 < _blTrustGate) {\n var _eloBoost2 = Math.min(_blEloCap, (_blTrustGate - _trustMin_bl2) * _blEloScale);\n _wE += _eloBoost2;\n _wM = Math.max(0.15, _wM - _eloBoost2 * 0.5);\n _wS = Math.max(0.10, _wS - _eloBoost2 * 0.5);\n }\n if (Math.abs(pModelA_raw - 0.50) < _blNeutBand ) {\n var _targetE = Math.min(_wE, 0.03);\n var _deltaE = _wE - _targetE;\n if (_deltaE > 0) {\n _wE = _targetE;\n _wM += _deltaE / 2;\n _wS += _deltaE / 2;\n }\n }\n _wF_mp = Math.max(0, Math.min(0.48, _wF_mp));\n var _baseSum = _wM + _wS + _wE;\n var _scale = (_baseSum > 0) ? ((1 - _wF_mp) / _baseSum) : 0;\n _wM *= _scale; _wS *= _scale; _wE *= _scale;\n _wE = Math.min(_wE, 0.22);\n var _wF_mp_raw = _wF_mp; // preserve for downstream engine call\n var _wSum = _wM + _wS + _wE + _wF_mp;\n if (_wSum > 0) { _wM /= _wSum; _wS /= _wSum; _wE /= _wSum; _wF_mp /= _wSum; }\n pFinal = _wM * pModelA + _wS * pStats + _wE * pElo + _wF_mp * _pFormA_mp;\n _wF_mp = _wF_mp_raw; // restore for downstream cap usage\n } else {\n _wF_mp = Math.max(0, Math.min(0.48, _wF_mp));\n var _wM0 = 0.50 * (1 - _wF_mp);\n var _wS0 = 0.50 * (1 - _wF_mp);\n var _wSum2 = _wM0 + _wS0 + _wF_mp;\n pFinal = (_wM0 * pModelA + _wS0 * pStats + _wF_mp * _pFormA_mp) / _wSum2;\n }\n pFinal = clamp01(pFinal);\n""" new_blend_pick = """ var pFinal = 0.5;\n var pBlendA = NaN;\n var _hasElo = (Number.isFinite(pElo) && pElo > 0 && pElo < 1);\n if (_hasElo) {\n var wM = THRESHOLDS.BLEND_W_MODEL;\n var wS = THRESHOLDS.BLEND_W_STATS;\n var wE = THRESHOLDS.BLEND_W_ELO;\n var wSum = wM + wS + wE;\n if (wSum <= 0) { wM = 0.5; wS = 0.5; wE = 0; wSum = 1; }\n pBlendA = (wM * pModelA + wS * pStats + wE * pElo) / wSum;\n pBlendA = clamp01(pBlendA);\n pFinal = pBlendA;\n } else {\n var wM0 = 0.5;\n var wS0 = 0.5;\n var wSum0 = wM0 + wS0;\n if (wSum0 <= 0) { wM0 = 0.5; wS0 = 0.5; wSum0 = 1; }\n pBlendA = (wM0 * pModelA + wS0 * pStats) / wSum0;\n pBlendA = clamp01(pBlendA);\n pFinal = pBlendA;\n }\n pFinal = clamp01(pFinal);\n""" must_replace(old_blend_pick, new_blend_pick, count=1)

3) Replace MATCH_PICK market anchor with capped move toward market using pBlendA.

old_anchor_pick = """ if (Number.isFinite(impliedProbA_pick) && impliedProbA_pick > 0 && !isTrapScenario_pick) {\n marketDivergence_pick = pFinal - impliedProbA_pick;\n var diff_pick = Math.abs(marketDivergence_pick);\n var pull_pick = 0;\n if (diff_pick > _maDivThr_p) {\n pull_pick = _maPullBase_p;\n try {\n var _oqA_p = (statsA && statsA.oppQuality) ? statsA.oppQuality : null;\n var _oqB_p = (statsB && statsB.oppQuality) ? statsB.oppQuality : null;\n var _fd_p = (_formLayer_mp && Number.isFinite(_formLayer_mp.delta)) ? Number(_formLayer_mp.delta) : 0;\n var _trustMinP = 1.0;\n if (_oqA_p && Number.isFinite(_oqA_p.trust)) _trustMinP = Math.min(_trustMinP, Number(_oqA_p.trust));\n if (_oqB_p && Number.isFinite(_oqB_p.trust)) _trustMinP = Math.min(_trustMinP, Number(_oqB_p.trust));\n if (Math.abs(_fd_p) > 0.03 && _trustMinP >= _maFormTrust_p) {\n var _modelDirAnchor = pFinal > 0.5 ? 1 : -1;\n var _formSupports = (Number.isFinite(_fd_p) && (_fd_p > 0) === (_modelDirAnchor > 0));\n if (!_formSupports && !_pickIsDog_p) pull_pick = Math.min(_maPullBig_p, pull_pick + _maPullForm_p);\n if (!_formSupports && _pickIsDog_p) pull_pick = Math.min(_maPullBase_p, pull_pick);\n anchorReason_pick = 'Divergence ' + Math.round(diff_pick * 100) + 'pp, Form Supports Model';\n } else if (_trustMinP < _maLowTrust_p) {\n pull_pick = Math.min(_maPullLowT_p, pull_pick);\n anchorReason_pick = 'Divergence ' + Math.round(diff_pick * 100) + 'pp, Low Schedule Trust';\n } else {\n anchorReason_pick = 'Divergence ' + Math.round(diff_pick * 100) + 'pp';\n }\n } catch(_eMAP) {\n anchorReason_pick = 'Divergence ' + Math.round(diff_pick * 100) + 'pp';\n }\n if (pull_pick > 0) {\n var _dir_pull_pick = (marketDivergence_pick > 0 ? 1 : -1);\n pFinal = clamp01(pFinal - pull_pick * _dir_pull_pick);\n anchorWeightUsed_pick = pull_pick;\n marketAnchorApplied_pick = true;\n }\n } else {\n anchorWeightUsed_pick = _maSoftW_p;\n anchorReason_pick = 'Soft Alignment';\n }\n } else if (isTrapScenario_pick) {\n""" new_anchor_pick = """ if (Number.isFinite(impliedProbA_pick) && impliedProbA_pick > 0 && !isTrapScenario_pick) {\n var _anchorSource_pick = Number.isFinite(pBlendA) ? pBlendA : pFinal;\n var diff_pick = _anchorSource_pick - impliedProbA_pick;\n marketDivergence_pick = diff_pick;\n var sign_pick = (diff_pick > 0) ? 1 : ((diff_pick < 0) ? -1 : 0);\n var maxPull_pick = 0.08;\n var pull_pick = Math.min(Math.abs(diff_pick), maxPull_pick);\n var anchored_pick = _anchorSource_pick - pull_pick * sign_pick;\n if ((_anchorSource_pick > impliedProbA_pick && anchored_pick < impliedProbA_pick) ||\n (_anchorSource_pick < impliedProbA_pick && anchored_pick > impliedProbA_pick)) {\n anchored_pick = impliedProbA_pick;\n }\n pFinal = clamp01(anchored_pick);\n if (pull_pick > 0) {\n anchorWeightUsed_pick = pull_pick;\n marketAnchorApplied_pick = true;\n anchorReason_pick = 'Divergence ' + Math.round(Math.abs(diff_pick) * 100) + 'pp';\n } else {\n anchorWeightUsed_pick = 0.0;\n anchorReason_pick = 'Soft Alignment';\n }\n } else if (isTrapScenario_pick) {\n""" must_replace(old_anchor_pick, new_anchor_pick, count=1)

4) Replace FINAL_BET_SUMMARY/secondary winner blend with strict weighted average.

old_blend_summary = """ var wModel = THRESHOLDS.BLEND_W_MODEL;\n var wStats = THRESHOLDS.BLEND_W_STATS;\n var wElo = THRESHOLDS.BLEND_W_ELO;\n var eloConf = Math.abs((Number.isFinite(pElo) ? pElo : 0.5) - 0.5);\n var modelConf = Math.abs(pMatchModelA - 0.5);\n if (eloConf > 0.10 && modelConf < 0.05) {\n wElo = 0.20; wModel = 0.40; wStats = 0.40;\n }\n if (Number.isFinite(pElo)) {\n if (pElo > 0.60 && pMatchModelA < 0.50) {\n wElo = 0.08; wModel = 0.40; wStats = 0.40;\n } else if (pElo < 0.40 && pMatchModelA > 0.50) {\n wElo = 0.08; wModel = 0.40; wStats = 0.40;\n }\n }\n var statsConf = Math.abs(pStatsA - 0.5);\n if (Number.isFinite(pElo) && eloConf > 0.06) {\n var eloDir = (pElo > 0.5) ? 1 : -1;\n var modelDir = (pMatchModelA > 0.5) ? 1 : -1;\n var statsDir = (pStatsA > 0.5) ? 1 : -1;\n // Elo + Model agree, Stats disagrees\n if (eloDir === modelDir && eloDir !== statsDir && modelConf > 0.04) {\n wElo = 0.22; wModel = 0.50; wStats = 0.28;\n }\n // Elo + Stats agree, Model disagrees\n else if (eloDir === statsDir && eloDir !== modelDir && statsConf > 0.04) {\n wElo = 0.22; wStats = 0.50; wModel = 0.28;\n }\n }\n var wSum = wModel + wStats + wElo;\n wModel /= wSum; wStats /= wSum; wElo /= wSum;\n var pFinalA = clamp01(\n wModel * clamp01(pMatchModelA) +\n wStats * clamp01(pStatsA) +\n wElo * (Number.isFinite(pElo) ? clamp01(pElo) : clamp01(pMatchModelA))\n );\n var msDenom2 = (wModel + wStats);\n if (msDenom2 > 0) {\n if (pFinalA > 0.50 && pMatchModelA < 0.50 && pStatsA < 0.50) {\n var pMSOnly = (wModel * pMatchModelA + wStats * pStatsA) / msDenom2;\n pFinalA = clamp01(pMSOnly);\n } else if (pFinalA < 0.50 && pMatchModelA > 0.50 && pStatsA > 0.50) {\n var pMSOnly2 = (wModel * pMatchModelA + wStats * pStatsA) / msDenom2;\n pFinalA = clamp01(pMSOnly2);\n }\n }\n""" new_blend_summary = """ var wModel = THRESHOLDS.BLEND_W_MODEL;\n var wStats = THRESHOLDS.BLEND_W_STATS;\n var wElo = THRESHOLDS.BLEND_W_ELO;\n var wSum = wModel + wStats + wElo;\n if (wSum <= 0) { wModel = 0.5; wStats = 0.5; wElo = 0; wSum = 1; }\n var pFinalA = clamp01((\n wModel * clamp01(pMatchModelA) +\n wStats * clamp01(pStatsA) +\n wElo * (Number.isFinite(pElo) ? clamp01(pElo) : clamp01(pMatchModelA))\n ) / wSum);\n""" must_replace(old_blend_summary, new_blend_summary, count=1)

5) Replace MATCH_PREVIEW winner blend with strict weighted average and pBlendA_pv.

old_blend_preview = """ var pFinalA = 0.5;\n var hasElo = (Number.isFinite(pElo) && pElo > 0 && pElo < 1);\n if (hasElo) {\n var _wM_pv = THRESHOLDS.BLEND_W_MODEL;\n var _wS_pv = THRESHOLDS.BLEND_W_STATS;\n var _wE_pv = THRESHOLDS.BLEND_W_ELO;\n var _oqA_blend = (statsA && statsA.oppQuality) ? statsA.oppQuality : null;\n var _oqB_blend = (statsB && statsB.oppQuality) ? statsB.oppQuality : null;\n var _tA_blend = (_oqA_blend && Number.isFinite(_oqA_blend.trust)) ? Number(_oqA_blend.trust) : 1.0;\n var _tB_blend = (_oqB_blend && Number.isFinite(_oqB_blend.trust)) ? Number(_oqB_blend.trust) : 1.0;\n var _trustMin_blend = Math.min(_tA_blend, _tB_blend);\n var _blTourK_pv = 'ATP';\n try { _blTourK_pv = taperTourKey(tourLabel); } catch(e) { _blTourK_pv = 'ATP'; }\n var _blIsWta_pv = (_blTourK_pv === 'WTA');\n var _blIsCh_pv = (_blTourK_pv === 'CH');\n var _blTrustGate_pv = _blIsWta_pv ? 0.96 : _blIsCh_pv ? 0.955 : 0.95;\n var _blEloCap_pv = _blIsWta_pv ? 0.20 : _blIsCh_pv ? 0.22 : 0.25;\n var _blEloScale_pv = _blIsWta_pv ? 1.8 : _blIsCh_pv ? 1.9 : 2.0;\n var _blNeutBand_pv = _blIsWta_pv ? 0.04 : _blIsCh_pv ? 0.035 : (THRESHOLDS.MODEL_NEUTRAL_BAND || 0.03);\n if (_trustMin_blend < _blTrustGate_pv) {\n var _eloBoost = Math.min(_blEloCap_pv, (_blTrustGate_pv - _trustMin_blend) * _blEloScale_pv);\n _wE_pv += _eloBoost;\n _wM_pv = Math.max(0.15, _wM_pv - _eloBoost * 0.5);\n _wS_pv = Math.max(0.10, _wS_pv - _eloBoost * 0.5);\n }\n if (Math.abs(pModelA - 0.50) < _blNeutBand_pv) {\n var _targetE_pv = Math.min(_wE_pv, 0.05);\n var _deltaE_pv = _wE_pv - _targetE_pv;\n if (_deltaE_pv > 0) {\n _wE_pv = _targetE_pv;\n _wM_pv += _deltaE_pv / 2;\n _wS_pv += _deltaE_pv / 2;\n }\n }\n _wF_pv = Math.max(0, Math.min(0.48, _wF_pv));\n var _baseSum_pv = _wM_pv + _wS_pv + _wE_pv;\n var _scale_pv = (_baseSum_pv > 0) ? ((1 - _wF_pv) / _baseSum_pv) : 0;\n _wM_pv *= _scale_pv; _wS_pv *= _scale_pv; _wE_pv *= _scale_pv;\n var _wSum_pv = _wM_pv + _wS_pv + _wE_pv + _wF_pv;\n pFinalA = (_wM_pv * pModelA + _wS_pv * pStats + _wE_pv * pElo + _wF_pv * _pFormA_pv) / _wSum_pv;\n } else {\n _wF_pv = Math.max(0, Math.min(0.48, _wF_pv));\n var _wM0_pv = 0.50 * (1 - _wF_pv);\n var _wS0_pv = 0.50 * (1 - _wF_pv);\n var _wSum2_pv = _wM0_pv + _wS0_pv + _wF_pv;\n pFinalA = (_wM0_pv * pModelA + _wS0_pv * pStats + _wF_pv * _pFormA_pv) / _wSum2_pv;\n }\n pFinalA = clamp01(pFinalA);\n""" new_blend_preview = """ var pFinalA = 0.5;\n var pBlendA_pv = NaN;\n var hasElo = (Number.isFinite(pElo) && pElo > 0 && pElo < 1);\n if (hasElo) {\n var _wM_pv = THRESHOLDS.BLEND_W_MODEL;\n var _wS_pv = THRESHOLDS.BLEND_W_STATS;\n var _wE_pv = THRESHOLDS.BLEND_W_ELO;\n var _wSum_pv = _wM_pv + _wS_pv + _wE_pv;\n if (_wSum_pv <= 0) { _wM_pv = 0.5; _wS_pv = 0.5; _wE_pv = 0; _wSum_pv = 1; }\n pBlendA_pv = (_wM_pv * pModelA + _wS_pv * pStats + _wE_pv * pElo) / _wSum_pv;\n pBlendA_pv = clamp01(pBlendA_pv);\n pFinalA = pBlendA_pv;\n } else {\n var _wM0_pv = 0.5;\n var _wS0_pv = 0.5;\n var _wSum2_pv = _wM0_pv + _wS0_pv;\n if (_wSum2_pv <= 0) { _wM0_pv = 0.5; _wS0_pv = 0.5; _wSum2_pv = 1; }\n pBlendA_pv = (_wM0_pv * pModelA + _wS0_pv * pStats) / _wSum2_pv;\n pBlendA_pv = clamp01(pBlendA_pv);\n pFinalA = pBlendA_pv;\n }\n pFinalA = clamp01(pFinalA);\n""" must_replace(old_blend_preview, new_blend_preview, count=1)

6) Replace MATCH_PREVIEW market anchor.

old_anchor_preview = """ if (Number.isFinite(impliedProbA) && !isTrapScenario) {\n marketDivergence = (pFinalA - impliedProbA);\n var diff = Math.abs(marketDivergence);\n var pull = 0;\n if (diff > _maDivThr) {\n pull = _maPullBase;\n try {\n var _oqA_a = oqA || (statsA && statsA.oppQuality ? statsA.oppQuality : null);\n var _oqB_a = oqB || (statsB && statsB.oppQuality ? statsB.oppQuality : null);\n var _formL = _formLayer_pv;\n var _fd = (_formL && Number.isFinite(_formL.delta)) ? Number(_formL.delta) : 0;\n var _trustMinA = 1.0;\n if (_oqA_a && Number.isFinite(_oqA_a.trust)) _trustMinA = Math.min(_trustMinA, Number(_oqA_a.trust));\n if (_oqB_a && Number.isFinite(_oqB_a.trust)) _trustMinA = Math.min(_trustMinA, Number(_oqB_a.trust));\n if (Math.abs(_fd) > 0.03 && _trustMinA >= _maFormTrust) {\n pull = Math.min(_maPullBig, pull + _maPullForm);\n anchorReason = 'Divergence ' + Math.round(diff * 100) + 'pp, Form Supports Model';\n } else if (_trustMinA < _maLowTrust) {\n pull = Math.min(_maPullLowT, pull);\n anchorReason = 'Divergence ' + Math.round(diff * 100) + 'pp, Low Schedule Trust';\n } else {\n anchorReason = 'Divergence ' + Math.round(diff * 100) + 'pp';\n }\n } catch(_eMA) {\n anchorReason = 'Divergence ' + Math.round(diff * 100) + 'pp';\n }\n if (pull > 0) {\n var _dir_pull = (marketDivergence > 0 ? 1 : -1);\n pFinalA = clamp01(pFinalA - pull * _dir_pull);\n anchorWeightUsed = pull;\n marketAnchorApplied = true;\n }\n } else {\n var _maAgreeDir = (pFinalA > 0.5) ? 1 : -1;\n var _maMarketDir = (impliedProbA > 0.5) ? 1 : -1;\n if (_maAgreeDir === _maMarketDir && diff < (_maDivThr * 0.50)) {\n var _maReinforce = Math.min(0.008, diff * 0.15);\n pFinalA = clamp01(pFinalA + _maAgreeDir * _maReinforce);\n anchorWeightUsed = _maReinforce;\n anchorReason = 'Market Confirms (' + Math.round(diff * 100) + 'pp)';\n } else {\n anchorWeightUsed = _maSoftW;\n anchorReason = 'Soft Alignment';\n }\n }\n } else if (isTrapScenario) {\n""" new_anchor_preview = """ if (Number.isFinite(impliedProbA) && !isTrapScenario) {\n var _anchorSource_pv = Number.isFinite(pBlendA_pv) ? pBlendA_pv : pFinalA;\n var diff = _anchorSource_pv - impliedProbA;\n marketDivergence = diff;\n var sign = (diff > 0) ? 1 : ((diff < 0) ? -1 : 0);\n var maxPull = 0.08;\n var pull = Math.min(Math.abs(diff), maxPull);\n var anchored = _anchorSource_pv - pull * sign;\n if ((_anchorSource_pv > impliedProbA && anchored < impliedProbA) ||\n (_anchorSource_pv < impliedProbA && anchored > impliedProbA)) {\n anchored = impliedProbA;\n }\n pFinalA = clamp01(anchored);\n if (pull > 0) {\n anchorWeightUsed = pull;\n marketAnchorApplied = true;\n anchorReason = 'Divergence ' + Math.round(Math.abs(diff) * 100) + 'pp';\n } else {\n anchorWeightUsed = 0.0;\n anchorReason = 'Soft Alignment';\n }\n } else if (isTrapScenario) {\n""" must_replace(old_anchor_preview, new_anchor_preview, count=1)

7) Cap opponent-quality adjustments in logit space directly inside _apply.

old_apply_return = """ return clamp01(adj);\n }\n""" new_apply_return = """ var rawRate = raw;\n var adjRate = clamp01(adj);\n var logRaw = logit(rawRate);\n var logAdj = logit(adjRate);\n var delta = logAdj - logRaw;\n var maxShift = 0.35;\n if (delta > maxShift) delta = maxShift;\n if (delta < -maxShift) delta = -maxShift;\n var finalRate = sigmoid(logRaw + delta);\n return clamp01(finalRate);\n }\n"""

occurs in the target function twice due exact helper duplicate in file snapshot? replace both.

must_replace(old_apply_return, new_apply_return, count=2)

8) Canonical decider in computeDeciderSetProb.

old_decider_func = """function computeDeciderSetProb(sim, bestOf) {\n try {\n if (!sim || !sim.totalRuns || !sim.setScores) return NaN;\n if (bestOf === 5) {\n return ((sim.setScores["3-2"] || 0) + (sim.setScores["2-3"] || 0)) / sim.totalRuns;\n }\n // default Bo3\n return ((sim.setScores["2-1"] || 0) + (sim.setScores["1-2"] || 0)) / sim.totalRuns;\n } catch(e) { return NaN; }\n}\n""" new_decider_func = """function computeDeciderSetProb(sim, bestOf) {\n try {\n if (!sim) return NaN;\n if (bestOf === 3) {\n if (sim._fullBimodal && Number.isFinite(sim._fullBimodal.pDeciderAuth)) {\n return clamp01(sim._fullBimodal.pDeciderAuth);\n }\n if (Number.isFinite(sim.pDeciderAuth)) {\n return clamp01(sim.pDeciderAuth);\n }\n }\n if (!sim.totalRuns || !sim.setScores) return NaN;\n if (bestOf === 5) {\n return ((sim.setScores["3-2"] || 0) + (sim.setScores["2-3"] || 0)) / sim.totalRuns;\n }\n return ((sim.setScores["2-1"] || 0) + (sim.setScores["1-2"] || 0)) / sim.totalRuns;\n } catch(e) { return NaN; }\n}\n""" must_replace(old_decider_func, new_decider_func, count=1)

9) Add pDeciderAuth and vetoSets to computeFullBimodal.

must_replace( """ mcDist: null\n };\n""", """ mcDist: null,\n pDeciderAuth: NaN,\n vetoSets: false\n };\n""", count=1)

must_replace( """ var biResult = _computeBimodalScore(\n p3, splitGap, med2, med3, modeAdj,\n valleyCentralMass, leftTail, rightTail,\n lmp, tourK, p3Raw\n );\n var finalIsSplitGap = (biResult.label === 'BIMODAL' || biResult.label === 'SOFT');\n""", """ var biResult = _computeBimodalScore(\n p3, splitGap, med2, med3, modeAdj,\n valleyCentralMass, leftTail, rightTail,\n lmp, tourK, p3Raw\n );\n var pDeciderAuth = Number.isFinite(p3) ? clamp01(p3) : (Number.isFinite(p3Raw) ? clamp01(p3Raw) : NaN);\n var vetoSets = false;\n if ((biResult.label === 'BIMODAL' || biResult.label === 'FRAGILE') &&\n Number.isFinite(pDeciderAuth) && pDeciderAuth > 0.30 && pDeciderAuth < 0.45) {\n vetoSets = true;\n }\n var finalIsSplitGap = (biResult.label === 'BIMODAL' || biResult.label === 'SOFT');\n""", count=1)

must_replace( """ mcDist: mcDist\n };\n}\n""", """ mcDist: mcDist,\n pDeciderAuth: pDeciderAuth,\n vetoSets: vetoSets\n };\n}\n""", count=1)

10) Store canonical decider back on sim after full bimodal build.

must_replace( """ var _fullBi = computeFullBimodal(sim, marketLine, tourLabel, bo);\n sim._fullBimodal = _fullBi;\n""", """ var _fullBi = computeFullBimodal(sim, marketLine, tourLabel, bo);\n sim._fullBimodal = _fullBi;\n if (_fullBi && Number.isFinite(_fullBi.pDeciderAuth)) sim.pDeciderAuth = _fullBi.pDeciderAuth;\n""", count=1)

11) Build sets engine config with canonical p3 and 32k thresholds.

must_replace( """ var tourK = 'ATP';\n try { tourK = taperTourKey(ctx.tourLabel); } catch (_eTK) { tourK = 'ATP'; }\n var tourCfg = setsMarketTourCfg(ctx.tourLabel); // baseP3, maxP3, holdLo/Hi, …\n var cal32k = get32kCalibration(tourK); // mvtDecHigh, mvtDecMid, mvtDecLow\n var cfg = {\n""", """ var tourK = 'ATP';\n try { tourK = taperTourKey(ctx.tourLabel); } catch (_eTK) { tourK = 'ATP'; }\n var tourCfg = setsMarketTourCfg(ctx.tourLabel); // baseP3, maxP3, holdLo/Hi, …\n var cal32k = get32kCalibration(tourK); // mvtDecHigh, mvtDecMid, mvtDecLow\n var bimodal = (ctx && ctx.bimodal) ? ctx.bimodal : ((ctx && ctx._fullBimodal) ? ctx._fullBimodal : null);\n var cfg = {\n""", count=1)

must_replace( """ // Compute derived thresholds\n cfg.p3BetThr = Math.max(cfg.maxP3 * 0.83, cfg.calHigh + 0.02);\n cfg.p3LeanThr = Math.max(cfg.maxP3 * 0.60, cfg.baseP3, cfg.calMid);\n // ===========================================================================\n // SECTION 2 — SOURCE EXTRACTION\n var p2Raw = clamp01(a20 + b20);\n var p3Raw = clamp01(a21 + b21);\n // Primary source: calibrated display p3\n var p3Primary;\n if (Number.isFinite(ctx.deciderDisplay)) {\n p3Primary = clamp01(ctx.deciderDisplay);\n } else if (Number.isFinite(ctx.deciderAdj)) {\n p3Primary = clamp01(ctx.deciderAdj);\n } else if (Number.isFinite(ctx.deciderRaw)) {\n p3Primary = clamp01(ctx.deciderRaw);\n try {\n var _fbDisp = clusterDisplayP3({\n tourLabel: ctx.tourLabel,\n pDecider: p3Primary,\n pDeciderRaw: p3Primary,\n pDeciderAdj: p3Primary,\n holdA: ctx.holdA,\n holdB: ctx.holdB\n });\n if (Number.isFinite(_fbDisp)) p3Primary = clamp01(_fbDisp);\n } catch (_eFBD) { }\n } else {\n p3Primary = p3Raw;\n }\n""", """ // Compute derived thresholds\n cfg.p3BetThr = Math.max(cfg.maxP3 - 0.02, cfg.calHigh - 0.02);\n cfg.p3LeanThr = Math.max(cfg.baseP3 + 0.06, cfg.calMid);\n cfg.minDeciderThr = cfg.calLow - 0.03;\n cfg.p2LeanThr = 1 - cfg.p3LeanThr;\n cfg.p2BetThr = 1 - cfg.p3LeanThr + 0.04;\n // ===========================================================================\n // SECTION 2 — SOURCE EXTRACTION\n var p3Raw = NaN;\n if (bimodal && Number.isFinite(bimodal.pDeciderAuth)) {\n p3Raw = clamp01(bimodal.pDeciderAuth);\n } else if (Number.isFinite(ctx.deciderDisplay)) {\n p3Raw = clamp01(ctx.deciderDisplay);\n } else if (Number.isFinite(ctx.deciderAdj)) {\n p3Raw = clamp01(ctx.deciderAdj);\n } else if (Number.isFinite(ctx.deciderRaw)) {\n p3Raw = clamp01(ctx.deciderRaw);\n } else {\n p3Raw = clamp01(a21 + b21);\n }\n p3Raw = clamp(p3Raw, tourCfg.minP3, tourCfg.maxP3);\n var p2Raw = clamp01(1 - p3Raw);\n var p3Primary = p3Raw;\n""", count=1)

12) Tune sets can3Bet formula and veto after decision.

must_replace( """ var can3Bet = !hardSweep3Kill && !minDecider3Kill\n && (p3Final >= cfg.p3BetThr + riskPenalty3)\n && (sup3Count >= 2)\n && (agreementLevel !== 'DISAGREE');\n""", """ var can3Bet = !hardSweep3Kill && !minDecider3Kill\n && (p3Final >= cfg.p3BetThr + riskPenalty3)\n && (sup3Count >= 2)\n && (agreementLevel !== 'DISAGREE' || p3Final >= 0.66);\n""", count=1)

must_replace( """ out.setsPick = setsPick;\n out.setsConfidence = capConfByRead(setsConfidence, displayConf);\n""", """ if (bimodal && bimodal.vetoSets && setsConfidence !== 'HIGH') {\n setsPick = 'PASS';\n setsConfidence = 'NONE';\n }\n out.setsPick = setsPick;\n out.setsConfidence = (setsConfidence === 'NONE') ? 'NONE' : capConfByRead(setsConfidence, displayConf);\n""", count=1)

13) Prefer canonical bimodal decider when available in the lightweight sets O/U helper.

must_replace( """ if (!sim || !sim.totalRuns || !sim.setScores) return '';\n var mk = buildSetsMarketEngine({\n""", """ if (!sim || !sim.totalRuns || !sim.setScores) return '';\n try {\n if (!sim._fullBimodal || !Number.isFinite(sim._fullBimodal.pDeciderAuth)) {\n sim._fullBimodal = computeFullBimodal(sim, NaN, tourLabel, bo);\n }\n if (sim._fullBimodal && Number.isFinite(sim._fullBimodal.pDeciderAuth)) sim.pDeciderAuth = sim._fullBimodal.pDeciderAuth;\n } catch(_eMkBi) {}\n var mk = buildSetsMarketEngine({\n""", count=1)

must_replace( """ deciderAdj: (bo === 3 && Number.isFinite(sim.pDeciderAdj)) ? Number(sim.pDeciderAdj) : NaN,\n""", """ deciderAdj: (bo === 3 && Number.isFinite(sim.pDeciderAdj)) ? Number(sim.pDeciderAdj) : NaN,\n deciderDisplay: (bo === 3 && sim._fullBimodal && Number.isFinite(sim._fullBimodal.pDeciderAuth)) ? Number(sim._fullBimodal.pDeciderAuth) : NaN,\n bimodal: sim._fullBimodal || null,\n""", count=1)

14) Prefer canonical bimodal decider in preview sets header and sets preview.

must_replace( """ var _pvCoinflipHdr = !!(_pvDecision && _pvDecision.classification === "PASS" && _pvThinWinner && (_pvDecision.structuralCoinFlip || _pvDecision.weakDataPolicy || _pvDecision.edgeAbs <= 0.05));\n""", """ var winnerEdgePreview = Math.abs(Number.isFinite(_pvDecision && _pvDecision.marketEdge) ? Number(_pvDecision.marketEdge) : (edge !== null ? edge / 100 : pickConfidence));\n var winnerRiskPenalty = (Number.isFinite(matchVolatility) ? clamp01(matchVolatility) : 0) * 0.025;\n var winnerConf = confFromEdge(winnerEdgePreview, winnerRiskPenalty);\n var finalWinnerPick = _guardPick((_pvDecision && _pvDecision.classification !== "PASS") ? String(_pvDecision.pickSide || '') : '', winnerEdgePreview, winnerConf);\n if (!finalWinnerPick && _pvDecision && _pvDecision.classification !== "PASS") {\n _pvDecision.classification = "PASS";\n _pvDecision.pickLabel = "PASS";\n }\n var _pvCoinflipHdr = !!(_pvDecision && _pvDecision.classification === "PASS" && _pvThinWinner && (_pvDecision.structuralCoinFlip || _pvDecision.weakDataPolicy || _pvDecision.edgeAbs <= 0.05));\n""", count=1)

must_replace( """ var _pvConfStr = (_pvDecision.classification === "PRIMARY") ? "HIGH" :\n (_pvDecision.classification === "LEAN") ? (_pvDecision.fragileFavorite ? "LOW" : "MID") :\n (_pvDecision.classification === "LIVE_DOG") ? "HIGH" : confStr;\n""", """ var _pvConfStr = (winnerConf && winnerConf !== 'NONE') ? winnerConf : 'LOW';\n""", count=1)

must_replace( """ var _setsPreview = buildSetsMarketEngine({\n""", """ try {\n if (_totSim && (!_totSim._fullBimodal || !Number.isFinite(_totSim._fullBimodal.pDeciderAuth))) {\n _totSim._fullBimodal = computeFullBimodal(_totSim, marketLine, tourLabel, bo);\n }\n if (_totSim && _totSim._fullBimodal && Number.isFinite(_totSim._fullBimodal.pDeciderAuth)) {\n _totSim.pDeciderAuth = _totSim._fullBimodal.pDeciderAuth;\n }\n } catch(_eTotBiPreview) {}\n var _setsPreview = buildSetsMarketEngine({\n""", count=1)

must_replace( """ deciderDisplay: (bo === 3) ? clusterDisplayP3({ tourLabel: tourLabel, pDecider: deciderPct, pDeciderRaw: deciderPct, pDeciderAdj: _p3setAdj, holdA: hA, holdB: hB }) : NaN,\n""", """ deciderDisplay: (bo === 3 && _totSim && _totSim._fullBimodal && Number.isFinite(_totSim._fullBimodal.pDeciderAuth)) ? _totSim._fullBimodal.pDeciderAuth : ((bo === 3) ? clusterDisplayP3({ tourLabel: tourLabel, pDecider: deciderPct, pDeciderRaw: deciderPct, pDeciderAdj: _p3setAdj, holdA: hA, holdB: hB }) : NaN),\n bimodal: (_totSim && _totSim._fullBimodal) ? _totSim._fullBimodal : null,\n""", count=1)

must_replace( """ appendSetsMarketBlock(lines, eDice + " Sets Market:", _setsPreview);\n""", """ var setsSide = '';\n if (_setsPreview && _setsPreview.available && _setsPreview.setsPick) {\n var _setsPickUpper = String(_setsPreview.setsPick).toUpperCase();\n if (_setsPickUpper.indexOf('3 SETS') >= 0) setsSide = '3 SETS';\n else if (_setsPickUpper.indexOf('2 SETS') >= 0) setsSide = '2 SETS';\n }\n var setsProb = NaN;\n if (setsSide === '3 SETS') setsProb = Number(_setsPreview && _setsPreview.p3);\n else if (setsSide === '2 SETS') setsProb = Number(_setsPreview && _setsPreview.p2);\n var setsEdge = Number.isFinite(setsProb) ? Math.abs(setsProb - 0.5) : NaN;\n var setsRiskPenalty = (_setsPreview && String(_setsPreview.riskTag || '').toUpperCase() === 'POLICY_RISK') ? 0.02 : 0;\n var setsConf = confFromEdge(setsEdge, setsRiskPenalty);\n var finalSetsPick = _guardPick(setsSide, setsEdge, setsConf);\n if (!finalSetsPick && _setsPreview) {\n _setsPreview.setsPick = 'PASS';\n _setsPreview.setsConfidence = 'NONE';\n } else if (_setsPreview) {\n _setsPreview.setsConfidence = setsConf;\n }\n appendSetsMarketBlock(lines, eDice + " Sets Market:", _setsPreview);\n""", count=1)

15) Apply totals guard just before totals display meta is built.

must_replace( """var _totReasonNice = prettyTotalsReason(_totReason);\nvar _totDisplayMeta = buildTotalsDisplayMeta(totDecision);\n""", """var _totReasonNice = prettyTotalsReason(_totReason);\nvar totalsSide = (String(totDecision).indexOf('UNDER') >= 0) ? 'UNDER' : ((String(totDecision).indexOf('OVER') >= 0) ? 'OVER' : '');\nvar totalsEdge = Math.abs((Number.isFinite(totConfProb) ? Number(totConfProb) : (Number.isFinite(_pOverEvalForConf) ? Number(_pOverEvalForConf) : 0.5)) - 0.5);\nvar totalsRiskPenalty = (_totCtx && Number.isFinite(_totCtx.totalsConfPenalty)) ? Number(_totCtx.totalsConfPenalty) : 0;\nvar totalsConfUnified = confFromEdge(totalsEdge, totalsRiskPenalty);\nvar finalTotalsPick = _guardPick(totalsSide, totalsEdge, totalsConfUnified);\nif (!finalTotalsPick) {\n totDecision = 'PASS';\n totConf = 'NONE';\n} else {\n totConf = totalsConfUnified;\n}\nvar _totDisplayMeta = buildTotalsDisplayMeta(totDecision);\n""", count=1)

16) Ensure preview sets header also gets canonical bimodal when possible.

must_replace( """ var _pvSetsHdr = buildSetsMarketEngine({\n""", """ try {\n if (_totSim && (!_totSim._fullBimodal || !Number.isFinite(_totSim._fullBimodal.pDeciderAuth))) {\n _totSim._fullBimodal = computeFullBimodal(_totSim, marketLine, tourLabel, bo);\n }\n if (_totSim && _totSim._fullBimodal && Number.isFinite(_totSim._fullBimodal.pDeciderAuth)) {\n _totSim.pDeciderAuth = _totSim._fullBimodal.pDeciderAuth;\n }\n } catch(_ePvBiHdr) {}\n var _pvSetsHdr = buildSetsMarketEngine({\n""", count=1)

must_replace( """ deciderAdj: (bo === 3) ? _p3setAdj : NaN,\n""", """ deciderAdj: (bo === 3) ? _p3setAdj : NaN,\n deciderDisplay: (bo === 3 && _totSim && _totSim._fullBimodal && Number.isFinite(_totSim._fullBimodal.pDeciderAuth)) ? _totSim._fullBimodal.pDeciderAuth : NaN,\n bimodal: (_totSim && _totSim._fullBimodal) ? _totSim._fullBimodal : null,\n""", count=1)

17) Also wire canonical bimodal into secondary sets market block in FINAL_BET_SUMMARY.

must_replace( """ deciderAdj: (bo === 3 && sim && Number.isFinite(sim.pDeciderAdj)) ? Number(sim.pDeciderAdj) : NaN,\n""", """ deciderAdj: (bo === 3 && sim && Number.isFinite(sim.pDeciderAdj)) ? Number(sim.pDeciderAdj) : NaN,\n deciderDisplay: (bo === 3 && sim && sim._fullBimodal && Number.isFinite(sim._fullBimodal.pDeciderAuth)) ? Number(sim._fullBimodal.pDeciderAuth) : NaN,\n bimodal: (sim && sim._fullBimodal) ? sim._fullBimodal : null,\n""", count=1)

if text == orig: raise RuntimeError('No changes made')

path.write_text(text, encoding='utf-8') print('Patched successfully') PY python3 /mnt/data/patch_tennislocks.py

Thought for 10m 10s

Pensiero

bash -lc cp /mnt/data/TennisLocks_v22_FIXED.gs.txt /mnt/data/TennisLocks_v22_FIXED_UPDATED.txt && ls -l /mnt/data/TennisLocks_v22_FIXED_UPDATED.txt

Thought for 13m 50s

Risposta

Done — I replaced the old logic in the uploaded script and exported the patched .txt version here: Download the updated script (TennisLocks_v22_FIXED.gs.txt)

I replaced the winner blend, market anchor, opponent-quality cap behavior, canonical decider usage, BO3 threshold logic, veto handling, and the preview no-bet guards directly in the script so the old paths are no longer the ones driving output.

Condividi questa Q&A