Use this new script Sets 2.5 audit addendum Send...

Created on: September 28, 2026

Answered using GPT-5.6 Thinking by Chat01

Question

TennisLocks_v1579_SHARED_TIER_PAIR_20260928.txt

Use this new script

Sets 2.5 audit addendum
Send this with the giant audit. This is the Sets-only brief. Same rules: no 65% hardcode, no P3 table, no one-match patch, no second length model.

What “consistent Over and Under” means
The script is not allowed to have a 2-set personality.
On a real slate it must be able to print both:
• OFFICIAL UNDER 2.5 when the same PMF says the match is likely two sets
• OFFICIAL OVER 2.5 when the same PMF says the match is likely three sets
If almost every BO3 card is UNDER ~54–60% LOW, or almost every card is OVER, the Sets owner is still biased. Fix the owner. Do not flip a sign, add a floor, or target “about 65% official unders.”
Correct behavior looks like this:
Tree situation
Honest P(3 sets)
Honest Sets ticket
One-sided holds (big favorite)
~40–50%
often UNDER, often LEAN not OFFICIAL
Close holds, both break a bit
~50–58%
coin / OVER lean
Close holds + real Set-2 reversal history on this surface/class
can clear 55–65% OVER
OVER can be OFFICIAL if the labeler agrees
Huge favorite + no reversal evidence
well under 50%
UNDER is the call; 3-set results still happen
A 70% favorite should sit near 45–50% three-set from the structural tree. That is tennis, not a bug. The bug is when a 52–48 hold match still prints UNDER, or when Set-2 history cannot move P3 enough to ever official OVER.

One owner, three views
Trace only this chain. If any other P3 exists, delete it.
1 Tree holds from matchup (or own-serve if fields incommensurable)
_liveMatchSpw* → tlLiveHoldFromSpwV1330 / point-state hold
2 BO3 first-to-2 recursion inside TennisMarketStateSpace.build
structural P(3 sets) = P(split after two sets)
3 Set-2 residual inside that same recursion
tlBo3Set2TargetV1558 → Firth/Jeffreys state-neutral delta → shrink with tlBo3StructuralPriorStrengthV1444
target = struct + (evN / (evN + priorN)) * appliedDelta
4 Exact-score PMF
5 Sets publisher = PMF set-count marginal
P(OVER 2.5) = P3
P(UNDER 2.5) = 1 − P3
6 Existing action labeler only (tlUnifiedDirectionalActionV1518 or current equivalent)
OFFICIAL / LEAN / PASS
LEAN/PASS is a valid answer
Identity check on every card:
SETS ENGINE TRACE identity gap ~ 0
canonical P3 == Sets publisher OVER
UNDER == 1 − OVER
Winner paths + set-count paths are the same PMF
If Winner is 62% A and Sets OVER is 70%, and the tree holds are 86 vs 84, something after the tree is stuffing three-set mass. If Winner is 70% A and Sets UNDER is 72%, Set-2 or a second model is stuffing two-set mass. Both are defects.

Structural P3 (before Set-2)
Audit the recursion with the live holds. Do not approximate with a table in production; use the table only to detect a broken kernel.
BO3, i.i.d. sets, P(A wins a set) = p:
• P(2–0 or 0–2) = p² + (1−p)²
• P(3 sets) = 2p(1−p)
So:
• p = 0.70 → P3 ≈ 0.42
• p = 0.60 → P3 ≈ 0.48
• p = 0.52 → P3 ≈ 0.50
Live holds are not i.i.d. coin sets (serve order, TB, first-server). The card structural P3 should be near that band, not 30% or 70% from 60/40 holds.
FAIL if:
• structural P3 is glued near 35–40% for every BO3 card regardless of hold gap
• structural P3 ignores hold gap (close matches still look like 65% favorites in set space)
• first-server / TB / no-ad branch is missing only on Sets but present on Winner
• BO5 cards use BO3 set-count logic or the reverse
BO5: Sets 2.5 is the wrong line. Confirm the script does not publish BO3 2.5 on a slam best-of-5 without a format branch. Format comes from the current event, not a default 3.

Set-2 residual (the only legal mover of P3 off the tree)
This is the only honest way Over and Under can both exist on a slate:
• Tree says “this favorite is a 2-set lean.”
• Same-surface, same-class, date-safe S1→S2 evidence says “this player (or this pair of strengths) actually splits a lot after a first set.”
• Residual moves that branch in probability space.
• Current-point priorN limits how far history can push.
Audit tlBo3Set2TargetV1558 and the live apply site:
Must keep:
• state-neutral, strength-centered, opposite-state comparison
• Firth/Jeffreys on the grouped binomial
• continuous contribution of every valid transition (no AICc permission switch)
• shrink by existing tlBo3StructuralPriorStrengthV1444
• missing prior → fail closed to structural P3
• written back into Set-2 point/game recursion, not P3 *= 1.15
Must delete if still present:
• min-N skip, sign-consistency skip, confidence skip
• “full strength history overwrite”
• a P3 floor/ceiling/target
• a separate “length profile” that replaces PMF set-count
• using last-7-vs-anybody N for prior while Winner used shared-tier N (v1579 already requires one sample; verify it)
How to know the residual is alive, not cosmetic:
On the card line:
structural P3 X% → final Y%
raw v1558 delta … | continuous state-neutral delta …
• If Y − X is always ~0.0–1.0pp on every card, history is not allowed to speak. OVER 2.5 will almost never official. That is a wiring defect, not “good shrink.”
• If Y − X is ±15–25pp often, history is overpowering current points. UNDER/OVER will flip off stale S1→S2 weeks. Shrink is not attached to live priorN.
• Honest range is: small when current-point N is large and history is thin; larger when history is rich and current-point N is modest. Same formula every tour.
Branch honesty:
• Reversal after A wins S1 and after B wins S1 can differ.
• A one-sided residual (only the favorite’s hold-serve set) that always cuts P3 is a 2-set bias.
• A residual that only fires when it increases P3 is a 3-set bias.
• Both directions must use the same function.
Evidence honesty (same class as Winner fields):
• same surface (HARD ≠ INDOOR)
• same tour family (ATP ≠ CH, WTA ≠ ITF_W)
• date-safe, no post-target matches on replay
• player’s own S1→S2, not a tour population rate
• do not use score-only "2-0" rows as Set-2 point evidence
If Set-2 evidence is empty, final P3 = structural P3. That is correct. Do not impute a league three-set rate.

Publisher and official tickets
Sets Played 2.5: UNDER 54.7% | LOW means:
• PMF UNDER = 54.7%
• labeler refused OFFICIAL
That is allowed. What is not allowed:
• printing OFFICIAL UNDER from ~54% while OFFICIAL Winner needed ~70%
• never printing OFFICIAL OVER on any close match for weeks
• a hidden extra gate that only official-unders, or only official-overs
• using Total Games “short match” shape to force Sets UNDER
• using length-profile last-7 SS 3-3 as the Sets pick
The labeler already exists. Audit that Winner, Sets, and TG use the same function and the same confidence inputs. If Sets has a private threshold, delete it and use the unified labeler.
Do not add “official UNDER needs 65%.” If official unders were fake, the fix is: matchup + residual + labeler fail-closed, so those tickets become LEAN/PASS. Real unders that still clear the existing labeler stay official. Real overs that clear it stay official.

Consistency tests (any slate, not one match)
Run these as code/logic tests, not vibes.
T1 — Favorite-gap monotonicity
Hold A 88 vs hold B 72 should have lower structural P3 than 84 vs 83. If not, set kernel is broken.
T2 — Residual sign symmetry
Same |delta|, opposite branch, opposite effect on that branch’s Set-2 win. No “always shrink P3” helper.
T3 — Prior shrink
Double current-point N, hold history fixed → |final P3 − structural P3| must fall. If it does not, priorN is unused.
T4 — One PMF
Sum of exact scores with 2 sets = UNDER. Sum with 3 sets = OVER. Winner paths use those same scores.
T5 — Format
BO3 event → 2.5 is legal. BO5 event → do not sell 2.5 as if first-to-2.
T6 — Slate balance (diagnostic only)
On a mixed ATP week, you should see some UNDER leans, some OVER leans, and many PASS/LEAN. All-UNDER or all-OVER after v1579 is a remaining bias. Report which function pinned the side. Do not then target 50/50 official tickets.
T7 — Field consistency
Shared-tier / incommensurable decision that changed Winner must change structural P3 in the same build. If Winner flipped and Sets did not move, two roots.

Defects to look for (Sets-specific)
Write only what you can point at:
1 Length profile / last-7 set records writing Sets mass.
2 TG short-set % leaking into P3.
3 Set-2 evidence from the wrong surface or tour family.
4 Residual computed then discarded (trace says applied, PMF uses structural).
5 Residual applied to published P3 but not to exact-score paths (Winner/TG disagree).
6 priorN from the wrong sample (full last-7 vs shared-tier).
7 Hard floor that stops OVER from ever printing official.
8 Comment says “no P3 target” but a helper still aims at 0.50 / 0.55 / 0.65.
9 BO3 Set-2 code running on BO5 or skipped on some tours.
10 Official Sets using a different probability than SETS ENGINE TRACE canonical P3.

Patch rule for Sets
For each real defect:
• Delete the extra Sets owner or the skip that pins 2-set / 3-set.
• Keep one structural recursion + one Set-2 residual + one prior shrink + one PMF marginal + one labeler.
• Do not add a constant to “help overs” or “help unders.”
• After patch, T1–T7 must still pass.
Success is not “more official overs.” Success is: close matches can official OVER, one-sided matches can official UNDER, and the rest are LEAN/PASS from the same number that Winner and Total Games already use.

I’ll pull the live Sets/Winner functions so the audit examples match the script, not generic tennis math.# Code examples for the audit
Paste this after the Sets addendum. These are the live owners in v1579, not pseudocode to invent a new model.

A. Official Sets ticket — already one PMF + one labeler
function tlUnifiedDirectionalActionV1518(prob,confidenceBand,officialEligible){
var p=Number(prob),b=String(confidenceBand||'NONE').toUpperCase();if(b==='MEDIUM')b='MID';
if(!(p>0.5&&p<1))return'PASS';
var confOfficial=(b==='HIGH'||b==='MID');
if(p+1e-12>=0.65&&officialEligible!==false&&confOfficial)return'MODEL_PICK';
if(p+1e-12>=0.60)return'LEAN';
return'FORECAST';
}

function tlSetsPlayed25DecisionV1392(pmf,bestOf,opts){
var bo=sanitizeBestOf(bestOf,'tlSetsPlayed25DecisionV1392');
if(bo!==3)return{valid:false, reason:'BO3_2_5_ONLY_V1392', official:false};
var n=tlCanonicalScorePmfViewV1526(pmf,3);
var p20=Number(n['2-0']||0), p21=Number(n['2-1']||0);
var p02=Number(n['0-2']||0), p12=Number(n['1-2']||0);
var pOver=p21+p12, pUnder=p20+p02;
// identity: pOver + pUnder === 1
var dir = pOver>pUnder ? 'OVER' : 'UNDER';
var pickProb = dir==='OVER' ? pOver : pUnder;
var band = tlSetsSpecificBandV1425(pickProb, opts||{});
var action = tlUnifiedDirectionalActionV1518(pickProb, band, true);
return {
side:dir, probability:pickProb,
official: action==='MODEL_PICK',
overIdentity:'P(2-1)+P(1-2)',
underIdentity:'P(2-0)+P(0-2)'
};
}
Audit this, do not replace it.
• OVER 2.5 = P(2-1)+P(1-2) from the canonical exact-score PMF.
• UNDER 2.5 = P(2-0)+P(0-2) from the same object.
• OFFICIAL is already pickProb >= 0.65 and band HIGH/MID. That 0.65 is the existing labeler, not a new constant to add or retune.
• 0.60–0.65 is LEAN. 0.50–0.60 is FORECAST/LOW. Below 0.50 on that side is PASS.
FAIL examples
// BAD — second Sets model
p3 = 0.55; // from last-7 SS record
return { side:'OVER', official:true };

// BAD — force official unders
if (pUnder >= 0.54) return 'MODEL_PICK';

// BAD — new 65% written a second time in Sets-only code
if (dir==='UNDER' && pUnder>=0.65) return 'MODEL_PICK';
GOOD check
var pub = tlSetsPlayed25DecisionV1392(canonicalPmf, 3, opts);
// pub.pOver === card "Sets publisher OVER"
// pub.pUnder === 1 - pub.pOver
// identityGap <= 1e-9

B. Set-2 residual — only legal mover of P3
function tlBo3Set2TargetV1558(spwA,spwB,start,tbTarget,walkOpts,structA,lastSetWinner,lastSetMargin){
if(!(structA>0&&structA<1&&(lastSetWinner==='A'||lastSetWinner==='B')))
return { valid:false, targetA:structA, applied:false };

var ev=tlBo3OrderedSet2EvidenceV1444(
walkOpts.lengthProfileA, walkOpts.lengthProfileB,
lastSetWinner, lastSetMargin
);
if(!(ev&&ev.valid&&Number(ev.n)>0&&Number.isFinite(Number(ev.deltaRate))))
return { valid:true, targetA:structA, applied:false }; // empty history = structural P3

var appliedDelta=Number(ev.appliedDeltaRate);
var prior=tlBo3StructuralPriorStrengthV1444(spwA,spwB,start,tbTarget,walkOpts,structA);
var evN=Number(ev.n);
var priorN=(prior&&prior.valid)?Number(prior.priorN):NaN;

if(!(evN>0&&Number.isFinite(priorN)&&priorN>0))
return { valid:true, targetA:structA, applied:false }; // fail closed to tree

var w = evN/(evN+priorN);
var target = structA + w*appliedDelta; // clip to (0,1)
return { valid:true, targetA:target, applied:Math.abs(target-structA)>1e-12 };
}
Then it must be solved back into point space and replace that Set-2 distribution:
if (bo===3 && setNo===1 && (lastSetWinner==='A'||lastSetWinner==='B')) {
var t = tlBo3Set2TargetV1558(...);
if (t.applied===true) {
var r = tlBo3PointStateToTargetV1558(...); // logit shift, same tree
return { dist:r.dist, applied:true };
}
return { dist:base, applied:false }; // structural set dist
}
How Over and Under both happen
structA = P(A wins Set 2 | S1 winner) from current holds
appliedDelta = Firth state-neutral residual (can be + or −)
w = evN / (evN + priorN) // 0..1, not a new constant

targetA = structA + w * appliedDelta
Worked numbers for the auditor (do not paste into the script as constants):
Close match, struct P(A wins S2 | B won S1) = 0.48
appliedDelta = +0.12 (this returner actually flips Set 2)
evN = 8, priorN = 24
w = 8/32 = 0.25
target = 0.48 + 0.25*0.12 = 0.51
→ P3 moves a few points. OVER can become the side.

Big favorite, struct P(fav wins S2 | fav won S1) = 0.72
appliedDelta = −0.04
evN = 4, priorN = 40
w = 4/44 ≈ 0.09
target = 0.72 + 0.09*(−0.04) ≈ 0.716
→ P3 barely moves. UNDER stays the side. Correct.
FAIL — leftover skips (delete, do not wrap)
// BAD
if (ev.n < 10) return structA;
if (Math.sign(rawDelta) !== Math.sign(appliedDelta)) return structA;
if (p3 < 0.50) p3 = 0.50;
if (p3 > 0.62) p3 = 0.62;
p3 = 0.65; // "official under needs 65%"
FAIL — residual computed but PMF ignores it
var t = tlBo3Set2TargetV1558(...);
trace.finalP3 = t.targetA; // card lies
return { dist: baseSimple }; // PMF still structural
FAIL — post-PMF multiply
pmf = buildCanonicalPmf(...);
p3 = p21+p12;
p3 = 1.12; // "help overs"
GOOD — prior N from the same sample that owns Winner
// v1579 already copies shared-tier attempts onto pressureStats when pair used that sample
if (_fieldsOkV1579 && _sharedTierV1579) {
_livePressureStatsA1402.totalSrvAtt = _sharedTierV1579.serviceNA;
_livePressureStatsA1402.totalRetAtt = _sharedTierV1579.returnNA;
// same for B
}
// tlBo3StructuralPriorStrengthV1444 reads pressureStats
.totalSrvAtt / totalRetAtt
If Winner used shared-tier rates but priorN still uses last-7-vs-anybody attempts, Sets shrink is lying. Wire the same sample.

C. Structural P3 must track hold gap (Winner and Sets)
// i.i.d. check only — production must use the live set recursion, not this formula
function iidP3(pSetA){ return 2pSetA(1-pSetA); }
// pSet=0.70 → 0.42
// pSet=0.60 → 0.48
// pSet=0.52 → 0.499
Live path:
holdA = tlLiveHoldFromSpwV1330(treeSpwA);
holdB = tlLiveHoldFromSpwV1330(treeSpwB);
// TennisMarketStateSpace.build → setDistCal / point-state set dist
// structural P3 = mass of 2-1 and 1-2 BEFORE Set-2 residual
FAIL
p3 = 0.46; // same on every BO3 card
p3 = lengthProfile.threeSetRate; // last-7 SS/3-set count
If structural P3 does not fall when hold gap rises, the set kernel is broken. Fix setDistCal / first-server / TB, not the publisher.

D. Winner pair — Sets cannot stay frozen if this changes
function tlSharedTierPointRatesV1579(rowsA, rowsB){
// keep rows with sAtt>0, rAtt>0, tier !== 'UNK'
// shared = tiers(A) ∩ tiers(B) // T20..T400P from oppRankTierKey
// attempt-weighted SPW/RPW on shared rows only
}

function tlCurrentPairServeReturnV1520(spwA,rpwA,spwB,rpwB,opts){
if (!(rAok && rBok)) return rawSpw;
if (opts.fieldCommensurable === false) {
out.source = 'CURRENT_DIRECT_SPW_FIELDS_INCOMMENSURABLE_V1579';
return out; // NO pair
}
var mu = (lsA+lsB+lqA+lqB)/4;
out.spwA = invlogit(lsA + lqB - mu);
out.spwB = invlogit(lsB + lqA - mu);
out.matchupTransformationApplied = true;
}
Tokyo-class failure this prevents (do not special-case the names):
last-7 SPW 61.9 / 66.3 last-7 RPW 37.2 / 28.8
avg opp rank 147 vs 81 no shared tier
v1578 pair → tree 67.7 / 63.5 → ~70% Winner → structural P3 ~45% UNDER lean
v1579 → pair OFF → tree 61.9 / 66.3 → Winner follows own serve
structural P3 must recompute from those holds
FAIL
treeSpw = pair(last7A, last7B); // unlike fields
p3 = oldP3FromPreviousBuild; // Sets not rebuilt

E. Card lines the auditor must reconcile
// live serve
"Live serve owner: " + pair.source +
" | matchup " + (pair.matchupTransformationApplied ? "ON" : "OFF") +
" | field " + (pair.sharedTierValid ? ("SHARED "+pair.sharedTiers.join(','))
: pair.sharedTierSource)

// Set-2
"structural P3 X% -> final Y%"
"raw v1558 delta … | continuous state-neutral delta …"
"canonical P3 … | Sets publisher OVER … | identity gap …"
Reconcile:
canonicalP3 === setsPublisherOver
under === 1 - over
Math.abs(canonicalP3 - (p21+p12)) <= 1e-9
If Y - X is 0.0–1.0pp on every card, residual is dead → overs never official.
If Y - X is ±15pp often, residual overpowers points → random side.
Do not “fix” that with if (over < 0.55) over = 0.55.

F. Total Games must move with Sets
// TG = sum over exact scores of P(score) * games(score)
// 2-0 / 0-2 paths are short; 2-1 / 1-2 paths are long
FAIL
tgOver = histMeanGames > line; // second model
if (setsSide==='UNDER') tg = straightSetMean;
GOOD
// after Set-2 residual rebuilds exact-score PMF
pOver25 = pmf['2-1'] + pmf['1-2'];
tgPmf = gamesMarginal(pmf); // same pmf

G. Patch template (delete + wire, no new constant)
// DELETE any of these if found
p3Target, p3Floor, p3Ceiling
if (n < N) skipSet2
if (rateOnly) skipPair
HARD_FAMILY / WTA_FAMILY mix
lengthProfile.threeSetRate as publisher
65 as a second Sets-only gate

// KEEP / WIRE
shared tier → pair or own-serve
tree SPW → hold → set recursion → structural P3
Set-2: struct + evN/(evN+priorN)*appliedDelta
solver back into set dist
canonical PMF
tlSetsPlayed25DecisionV1392 + tlUnifiedDirectionalActionV1518
Return to the user: defect list with function names, the deleted path, the wired owner, and a card that can print OFFICIAL OVER 2.5 on a close field-matched match and OFFICIAL UNDER 2.5 on a one-sided field-matched match using the same functions.

TennisLocks v1579 — Independent Full-Script Audit Brief
Use this as the only instruction set. Do not “fix one match.” Do not invent constants. Do not retune 65%, P3 floors, or Tokyo/Svajda/Kovacevic. Trace the live pricing tree end to end, write every real defect with file evidence (function + what it does), then patch only with complete wiring: delete the bad path, connect the good owner, no leftover skip.
Script to audit: the current production Apps Script (TennisLocks_v1579_SHARED_TIER_PAIR_20260928 / build stamp v1579-SHARED-TIER-PAIR-20260928). If TENNISLOCKS_BUILD() is not that stamp, stop and say the file is wrong.

  1. Mission and non-negotiables
    The model must be right, not print a pick. Official tickets should fail the existing publication labeler when the root is weak. LEAN/PASS is success. Fake OFFICIAL is failure.
    One root owns everything:
    1 Current point SPW/RPW (field-consistent)
    2 O’Malley / point-state hold
    3 Point → game → set → match recursion
    4 One exact-score PMF
    5 Winner, Sets 2.5, Total Games, player games, first set, TBs are marginals of that PMF
    Hard rules:
    • Do not add a second Winner model, second Sets model, or second Totals model.
    • Do not hardcode 65%, a P3 target, a tour table, a player patch, or a match patch.
    • Do not retune existing constants (TL_LIVE_POINT_MATCH_MAX_AGE_DAYS_V931, Firth, prior strength helper, O’Malley) to make one card look good.
    • Do not add Elo/population/year shrink as a live owner. Those were removed on purpose.
    • Do not leave dead gates (if (n < 400) skip pair). Delete the skip path entirely.
    • Opponent-quality ranks already exist on rows. Use them only as field identity (shared tiers already in oppRankTierKey). Do not invent a new tau.
    • After edits: node --check / Apps Script parse must pass. Every new symbol must have a declaration. Every deleted skip must have zero remaining callers.

  2. How to work
    1 Read the header ownership comments (v1552–v1579) and treat them as claims to verify, not as truth.
    2 Start at MATCH_PREVIEW → tlMatchPreviewCoreV797.
    3 Walk only the live path. Research / KSR / Elo / Classic sidecars that cannot write the PMF are out of scope unless they still leak into the root.
    4 For each owner below, produce:
    ◦ Claim (what the comments say)
    ◦ Actual code path (functions in order)
    ◦ Defects (with exact mechanism)
    ◦ Fix rule (delete X, wire Y, no new constant)
    5 Do not guess. If a function is unused, say unused. If a comment lies, quote both.

  3. Match Winner — audit this first
    Winner is a PMF marginal. If Winner is wrong systematically, the inputs to the tree are wrong.
    2.1 Current-point owner
    Trace in order:
    • tlPricingRowMaskV1474 / tlPricingRowMetaEligibleV1474
    • parseMatchInputsData → extractPlayerStats (attempt-weighted SPW/RPW, pointRows)
    • tlResolveCurrentPointSideV1113
    • tlChooseCurrentPointCandidateV1496
    • tlSharedTierPointRatesV1579
    • tlCurrentPairServeReturnV1520
    • _matchSpwA_prev / _liveMatchSpwA → TennisMarketStateSpace.build
    Verify:
    1 Authority is tier-first, not date-first. Exact row-filtered (ROW_FILTERED_MATCH_INPUTS_CURRENT_ROOT_V1500, tier 30) must beat snapshots (20) and surface samples (10). A newer snapshot must not replace measured exact rows.
    2 Rate-only rows must not impersonate exact points. pointMode starting RATE_ONLY is snapshot-class. serviceN/returnN must be 0 on that class.
    3 HARD and INDOOR must not share snapshots or row eligibility. Family keys HARD_FAMILY must stay deleted.
    4 Tour families must not mix: ATP ≠ CH ≠ ITF_M; WTA ≠ WTA125 ≠ ITF_W. WTA_FAMILY as a women’s dump must stay deleted.
    5 Row eligibility is player + tour + surface + date/freshness. Historical opponent/event strings must not veto current samples.
    6 pointRows must carry per-row serve attempts, return attempts, and oppRankTierKey tier.
    2.2 Pair / matchup (the deep Winner bug)
    The only honest matchup is: serve of A vs return of B on a shared opponent field.
    Required behavior already intended in v1579:
    • Build shared tiers = tiers present on A’s ranked exact rows ∩ tiers present on B’s ranked exact rows (T20,T50,T100,T200,T400,T400P from oppRankTierKey).
    • Rebuild attempt-weighted SPW/RPW from only those rows.
    • Run the zero-parameter logit pair only on that shared sample:
    ◦ μ = mean(logit SPW_A, logit SPW_B, logit(1−RPW_A), logit(1−RPW_B))
    ◦ treeSPW_A = invlogit(logit(SPW_A) + logit(1−RPW_B) − μ)
    • If no shared ranked tier, or either side lacks ranked serve+return points: do not pair. Tree SPW = own-serve SPW. Source must say incommensurable / no shared tier.
    • When shared-tier is the pair owner, pressure stats / Set-2 prior N must use that sample’s attempts, not last-7-vs-anybody.
    Audit for regressions:
    • Any second caller of tlCurrentPairServeReturnV1520 that skips the shared-tier gate.
    • Pair still running on raw last-7 RPW when fields differ (this printed 70% Svajda off Kovacevic’s 28.8% return vs ~81s vs Svajda’s 37% vs ~147s).
    • Display “Matchup RPW” must stay 1 − opponent tree SPW (v1577 identity). Do not splice 364-day surface DR into the public matchup block.
    • Do not reintroduce 400-point pair gates or rateOnly short-circuits as “safety.” Those caused raw-SPW winners and fake certainty.
    2.3 Hold and match win
    • Hold must be tlPointStateHoldFromSpwV1321 / tlLiveHoldFromSpwV1330 from tree SPW, not a TA hold, Elo hold, or sheet hold.
    • BO3/BO5 match-win must come from the same recursion as Sets and Totals.
    • Publication (tlUnifiedDirectionalActionV1518 or current labeler) must not mint OFFICIAL WINNER from a different number than the PMF Winner.
    Winner pass/fail:
    • FAIL if two players with very different last-7 opponent pools still get a pair flip without a shared tier.
    • FAIL if snapshot/surface SPW can overwrite exact rows.
    • FAIL if Winner % ≠ sum of exact-score paths where that player wins.

  4. Sets Played 2.5 / P(3 sets)
    Sets is a read-only settlement of the exact-score PMF. There is no second length model.
    3.1 Structural tree
    P(3 sets) before Set-2 residual must be the BO3 recursion from tree holds (first-to-2). A 70/30 favorite should land near ~45–50% three-set from the tree, not from a table.
    3.2 Set-2 residual (v1569/v1578/v1579)
    Trace:
    • tlBo3Set2TargetV1558
    • Firth / Jeffreys state-neutral delta
    • tlBo3StructuralPriorStrengthV1444
    • shrink: struct + (evN / (evN + priorN)) * appliedDelta
    • write back into the same set recursion, not a post-hoc P3 multiply
    Verify:
    1 No AICc / min-N / sign-consistency / confidence switch that skips the residual.
    2 No leftover “full-strength history overwrite.”
    3 Missing prior precision fails closed to the structural tree, not to a P3 default.
    4 Raw v1558 deltas can be huge (60pp). After prior shrink they must not dominate current points. If they still overwrite Winner or flip P3 by tens of points with tiny history N, the shrink is not wired to the live prior.
    5 When shared-tier owns the pair, priorN must be from that sample.
    6 Publisher Sets 2.5 UNDER/OVER must equal 1 − P3 / P3 from the canonical PMF. Identity gap must stay ~0.
    7 Official UNDER 2.5 must use the existing action labeler only. After a real matchup, many former “official unders” should become LEAN/PASS. That is correct. Do not add a 65% constant to force it.
    Sets pass/fail:
    • FAIL if a second P3 target exists anywhere.
    • FAIL if Set-2 can change Winner without changing the same PMF.
    • FAIL if official 2-set tickets print from ~55% mass. That is a labeler/root problem, not a reason to hardcode 65.

  5. Total Games
    Total Games is the unconditional full-match games PMF over all legal exact scores. Straight-set and three-set means on the card are diagnostics only.
    Trace:
    • exact-score PMF → games-per-path → TG PMF
    • market line 22.5 etc. is a read of that PMF, not a second projection
    • score-grain rules in extractPlayerStats: only scoreGrain === 'GAME' and legal set pairs enter length history; "2-0" set-count fallback must never enter TG geometry (v1415)
    Verify:
    1 No lane that prices TG from “straight-sets mean” or last-7 games average.
    2 No KSR / research sidecar writing the live TG %.
    3 Fair total / median / P10–P90 / densest range are views of the same PMF.
    4 Changing Winner inputs must change TG; if Winner flips and TG is frozen, there are two models.
    5 Do not “correct” TG by pushing mass toward 3-set means. If P3 is right and holds are right, TG follows.

  6. Data path consistency (every tour, not one match)
    Audit these as system defects:
    Topic
    Required
    Common lie to catch
    Surface
    Exact HARD vs INDOOR vs CLAY vs GRASS
    leftover HARD_FAMILY load/save/scan
    Tour
    Exact family ATP / CH / WTA / WTA125 / ITF_W / ITF_M
    WTA_FAMILY dump; CH token from “China/Chengdu”
    Dates
    Actual match date when present; tourney-start is coarse but still one match
    double-counting same match as match-date + tourney-start (v1575/v1576 identity)
    Identity
    opponent+score+surface+tour+event/round + bounded date
    two providers, one match, two rows in last-7
    Snapshots
    Paired SPW/RPW from the same matches; exact surface+tour key
    family key; SPW from one week, RPW from another
    Availability / RET
    Boundary applies to snapshots, not as a veto of valid exact rows
    wiping seven good rows because of a RET flag
    Preview network
    MATCH_PREVIEW must not fetch TML if no-network flag is on
    silent empty exact rows → snapshot takeover
    Display vs root
    Card “tree SPW” = _currentServeInputsV1520.spw*
    printing 1−opp RPW while tree used something else
    Opp rank
    Shared-tier pair only
    unused oppQuality that only stamps “STRONG / trust 1.00” while pairing unlike fields
    AutoFill and Preview must use the same tour authority (tlAutoFillCanonicalTourV1573). If AutoFill writes CH rows and Preview prices ATP, last-7 is garbage on every card, not one card.

  7. Publication / official tickets
    Do not add gates. Audit the existing labeler:
    • Winner OFFICIAL vs LEAN vs PASS
    • Sets 2.5 OFFICIAL vs LOW
    • TG OFFICIAL vs LOW
    Required: the % on the ticket is the PMF marginal. The labeler may refuse OFFICIAL. It may not invent a different %.
    If official Winner is 70% and official Sets UNDER is 55%, that is coherent for a 70% BO3 favorite (P3 near 45%). Do not “fix” that by boosting P3. Fix Winner if the 70% was a cross-field pair.

  8. What “corrected” means
    A pass is not “Svajda/Kovacevic now picks Kovacevic.” A pass is:
    1 Same owner functions on ATP 250, ATP 500, slam BO5, WTA, CH, ITF.
    2 Pair never crosses two last-7 fields.
    3 Winner, P3, TG move together.
    4 Weak roots publish LEAN/PASS instead of fake OFFICIAL.
    5 Bad skips are gone, not wrapped in if.
    6 Build stamp updated; comments match code.

  9. Deliverable format back to the user
    1 Inventory of defects — only traced items. Function name, mechanism, which owner it poisons (Winner / Sets / TG / all).
    2 Patch plan — for each defect: delete function/branch X; wire Y into Z; no new constant.
    3 Patched script — one full file, syntax-clean, dead code removed, stamp bumped (v1580+).
    4 Card-line checks the user can read on any match:
    ◦ Live serve owner + matchup ON/OFF + field SHARED … or NO_SHARED_OPPONENT_TIER
    ◦ Second-set response: structural P3 → final with small prior-shrink, not a 20pp overwrite
    ◦ SETS ENGINE TRACE identity gap ~0
    ◦ TG line is full-match PMF, not a 2-set lane
    5 What you refused to do — list constants you did not add.
    If you cannot trace a suspected bug to a function, do not patch it. Say so.

  10. Known already-traced items (do not re-litigate; verify they still hold)
    Already done if the file is really v1579:
    • Pair skip on 400 points / rateOnly removed
    • Tier-first candidate sort
    • Set-2 × current-point prior shrink
    • Exact surface; HARD_FAMILY deleted
    • Snapshot means paired on same matches
    • Shared-tier pair + fail-closed own-serve
    • Pressure/Set-2 N follows shared-tier when that sample owns the pair
    • WTA/WTA125/ITF_W split
    Your job is to find remaining inconsistencies of the same class (two samples, two models, leftover family mix, display≠root, skip still alive) and wire them the same way: one field-consistent point sample → one PMF → all tickets.

Answer

I’m auditing the live v1579 path exactly as requested: build stamp first, then Winner → structural P3 → Set-2 residual → canonical PMF → Sets/TG → publication. I’ll only patch defects I can trace to concrete functions, then bump the build and syntax-check the full file.

Thought

Searched tennis model configuration and market logic

Thought

Inspected tennis audit logic and suspicious defects

Answer

The build stamp is correct, so I’m continuing. One concrete Sets risk is already visible: the BO3 ordered-history builder records classRelation but, unlike BO5, does not yet prove it rejects non-same-class rows; I’m tracing the downstream evidence function before deciding whether that is a real live defect.

Thought

Resolving confidence logic

I’m reconciling the request without retuning existing thresholds. I’ll preserve the current 0.65 value, route winner decisions through the shared action logic, and check whether low-confidence cases would change behavior unexpectedly.

Resolved confidence logic

Thought

Checking class scope

I’m verifying that event-class matching distinguishes tour families appropriately, while noting gender is inferred through player identity. I’m also checking evidence weighting, sign symmetry, prior-shrinkage behavior, and whether a lightweight runtime harness can exercise the score calculations.

Checked class scope

Inspected tennis prediction logic, scoring, labels, and tour context consistency

Answer

The Set-2 owner itself is correctly two-sided and uses evN/(evN+priorN); shared-tier attempts are also copied into the prior stats. I’ve found a stronger live defect: score-only 2-0/0-2 history is admitted by the BO3 ordered-history builder and can become Set-2 residual evidence, even though it has no set-level game/point grain. That path will be deleted at the builder boundary, not compensated downstream.

Thought

Audited tennis logic, trace aggregation, evidence filters, and helper consistency

Answer

I’ve finished the live-path trace. The PMF ownership is intact; the remaining production-affecting Sets defect is the coarse score-history leak. I’m also fixing two wiring/audit inconsistencies without changing model constants: Winner will route its already-computed confidence through the existing unified action labeler, and the Sets trace will report the actual evidence-weighted residual/prior instead of a last-branch value plus a reversed shrink formula in the text.

Thought

Simulated P3 reversal profiles and tested shrinkage across sample sizes

Answer

The core shrink test passes: doubling current-point exposure monotonically reduces the Set-2 move (about +7.8pp → +6.4pp → +4.7pp → +3.1pp in the controlled close-match test). I’m now running the full T1–T7 harness and generating the clean v1580 file plus an audit report with exact before/after paths.

Thought

Ran tennis model audit and test harness

Thought

Audited formula generation, file ranges, and winner trace bugs

Thought

Verified patched files, tennis tests, diffs, audits, and version differences

Answer

The full patch is syntax-clean, and the T1–T7 harness now passes. The two requested “both personalities” examples also work through the same owner: a close reversal-rich fixture publishes OVER 2.5 at 67.87%, while a one-sided fixture publishes UNDER 2.5 at 65.23%, both through the unchanged v1518 labeler and with zero PMF identity gap.

Thought

Created audited TennisLocks report

Worked for 10m 29s

Answer

Completed the v1579 full-script audit and patched it to v1580-SETS-OWNER-AUDIT-20260928. The source file had the required v1579 build stamp, so I proceeded. Its ownership comments explicitly claim one canonical PMF and no P3 floor/target; I treated those as claims and verified the live wiring rather than assuming they were true. (TennisLocks_v1579_SHARED_TIER_PAIR_20260928.txt)

1. Traced defects

D1 — real production defect: score-only 2-0 / 0-2 rows were allowed into BO3 Set-2 residual evidence. _tlOrderedWinsFromMatchObject_ deliberately turns coarse straight-set records into scoreGrain:'SET_COUNT_STRAIGHT_V1298' with allScorePairsLegal:false. (TennisLocks_v1579_SHARED_TIER_PAIR_20260928.txt) But _tlBuildOrderedBo3LengthProfileV1218_ accepted those objects and generated S1→S2 transitions from them. (TennisLocks_v1579_SHARED_TIER_PAIR_20260928.txt) That violates the Sets brief's requirement not to use score-only 2-0 records as Set-2 evidence.

Patch: coarse rows are now deleted from that evidence path at the builder boundary. BO3 Set-2 evidence requires scoreGrain === 'GAME' && allScorePairsLegal === true. I added only an exclusion counter for auditability, not a probability adjustment.

D2 — publication wiring inconsistency: Winner was not actually calling the unified action labeler. Sets already reads the canonical PMF and calls _tlUnifiedDirectionalActionV1518_; its 65% is the existing common labeler, not a Sets-specific gate. (TennisLocks_v1579_SHARED_TIER_PAIR_20260928.txt) In contrast, _winnerDecision_ manually constructed MODEL_PICK / LEAN / FORECAST from its confidence state. (TennisLocks_v1579_SHARED_TIER_PAIR_20260928.txt)

Patch: Winner now routes its existing probability/confidence through _tlUnifiedDirectionalActionV1518_. Winner's existing fail-closed evidence/LEAN rules remain intact. No thresholds were retuned.

D3 — Sets trace was lying about part of the live residual, although pricing itself was correct. The live Set-2 target already correctly uses evN/(evN+priorN) and solves the target back into point space. (TennisLocks_v1579_SHARED_TIER_PAIR_20260928.txt) But the BO3 trace did not accumulate priorN, and residual telemetry was effectively last-state rather than reach-weighted. (TennisLocks_v1579_SHARED_TIER_PAIR_20260928.txt) The card description also stated the shrink weight backwards as prior-N divided by total N. (TennisLocks_v1579_SHARED_TIER_PAIR_20260928.txt)

Patch: BO3 trace now reach-weights prior N and residual telemetry and prints the real formula: evidenceN / (evidenceN + priorN).

I did not find a live second Sets/P3 owner, P3 floor/ceiling/target, post-PMF multiplier, or TG length model replacing the canonical PMF. The shared-tier sample also already propagates its attempts into pressure stats before TennisMarketStateSpace.build, so Set-2 prior N follows the same field-matched sample. (TennisLocks_v1579_SHARED_TIER_PAIR_20260928.txt)

2. T1–T7 results

All seven code/logic tests pass after the patch.

  • T1 Favorite-gap: 88/72 holds → structural P3 34.77%; 84/83 → 49.92%.
  • T2 Residual symmetry: mirrored applied deltas −18.17pp / +18.17pp.
  • T3 Prior shrink: doubling current-point exposure progressively reduced the Set-2 movement: 7.85pp → 6.42pp → 4.70pp → 3.06pp.
  • T4 One PMF: test OVER 62.7522% exactly equals the Sets publisher; Winner score marginal matches root to floating-point precision.
  • T5 Format: BO5 sent to the 2.5 publisher fails closed with BO3_2_5_ONLY_V1392.
  • T6 Balance diagnostic: controlled fixtures produce UNDER forecast, OVER official, and UNDER official without a balancing target.
  • T7 Field consistency: shared-tier pairing changed tree SPW and changed P3 in the same build; no-shared-tier remained own-serve.

The coarse-score regression also passes: a synthetic score-only 2-0 row now produces 0 Set-2 transitions and increments excludedCoarseScoreRows.

3. Same owners can now produce both official directions

Using the same state-space recursion, canonical score PMF, _tlSetsPlayed25DecisionV1392_, and unchanged _tlUnifiedDirectionalActionV1518_:

Close field-matched + reversal-rich fixture: structural P3 49.92% → final 67.87%, yielding OFFICIAL OVER 2.5 67.87%, identity gap 0.

One-sided field-matched fixture: structural/final P3 34.77%, yielding OFFICIAL UNDER 2.5 65.23%, identity gap 0.

Those are controlled code fixtures to prove directional capability, not claims about a particular real player or current ATP slate. No real slate dataset was included, so I did not pretend T6 was an empirical week-level frequency test.

4. What I did not add

No new 65% gate, no retuned 65%, no P3 floor/ceiling/target, no “help overs” constant, no “help unders” constant, no tour P3 table, no match/player patch, no min-N skip, no sign-consistency skip, no second Winner/Sets/TG model, no post-PMF P3 multiplier, and no Elo/population/year owner.

node --check passes on the complete v1580 script.

5. Files

[Full patched v1580 script — paste-ready TXT]

Full patched v1580 script — JS

Audit report

Exact v1579 → v1580 diff

T1–T7 test results

Test harness

Review the patched audit outputs

  • Inspect the v1579 to v1580 diff
  • Open the audit report

Share this Q&A