name: wc-fixture-progression
description: Rates fixture difficulty (separately for an attacking and a defending fantasy asset, 1-5 each way, from opponent xGA/xG), computes team progression probabilities (group qualification odds from the mini-table; round-by-round knockout survival down the bracket) by reference-class forecasting updated Bayesianly on observed form and group state, detects weak-group/mismatch fixtures (powerhouse-vs-minnow -> captain candidates and clean-sheet locks), and builds a multi-round swing calendar of where each team's difficulty flips so transfers can be planned ahead. Emits the fixture signal. Use when called by wc-fixture-analyst, by the strategists in the populate stage, and by wc-fitness-eval for its progression_carry term — and never re-derive these once the signal exists.
wc-fixture-progression — difficulty, progression odds, mismatches, swings
The engine behind wc-fixture-analyst and the source of the p_advance figures wc-fitness-eval discounts in its progression_carry term. It does four jobs the rest of the system reads off rather than recomputing: rate each fixture's difficulty in both directions, put a calibrated probability on each team advancing each round, flag the lopsided fixtures where points come cheapest, and lay out a forward calendar of difficulty swings so transfers land ahead of the field's lag (game-theory-meta.md §4).
The probability work is deliberately two-stage: an outside view first (reference-class advance rates by seed/ranking — reference-class-forecasting), then a Bayesian update on what we actually observe (form, goal difference, group state — bayesian-reasoning-calibration). A favourite is never priced as a certainty; the reference class always carries an upset rate, and the dead-rubber rotation flag fires the moment a team has clinched.
Inputs
- The round id, phase, and bracket from
tournament-state.md(group mini-tables, who plays whom, current standings). - Per-team attacking and defensive strength: team xG-for and xGA per match (web-searched, cited; manager-provided where a model exists). Seed/pot and world ranking at the draw for the reference class.
- Observed results to date this tournament (goals, goal difference, xG over/under-performance) for the Bayesian update.
- Confirmed kickoff order within the round (from
wc-matchday-timingif already emitted) for the swing calendar's day-tagging — optional, fixture difficulty does not need it.
Read the round's clean-sheet and scout signals if present, but do not re-derive them — this skill supplies the fixture-strength scalars those skills consume, not the other way round.
Workflow
- [ ] 1. FIXTURE DIFFICULTY — rate every fixture 1-5 for an attacker AND 1-5 for a defender (opponent xGA -> attack ease; opponent xG -> clean-sheet ease)
- [ ] 2. PROGRESSION ODDS — outside-view base rate by seed (reference class), then Bayesian update on form + group state; groups via the mini-table, knockouts round-by-round down the bracket
- [ ] 3. WEAK-GROUP / MISMATCH — flag powerhouse-vs-minnow fixtures; tag attackers as captain candidates, defenders as clean-sheet locks
- [ ] 4. FIXTURE SWINGS — find the rounds where a team's difficulty flips (easy->hard or hard->easy); build the swing calendar to plan transfers ahead
- [ ] 5. DEAD-RUBBER CHECK — flag any fixture where a team has already qualified/is already out (rotation risk on that fixture's assets)
- [ ] 6. Emit the `fixture` signal (both-direction difficulty grid, p_advance per round, weak_group_flags, mismatch_list, swing_calendar) via wc-signal-emitter
Method
1. Fixture difficulty — two directions, never one number
A fixture is not equally hard for the attacker you own and the defender you own. A goalkeeper against a toothless attack and a striker against a porous defence can sit in the same match with opposite difficulty. So rate every fixture twice on a 1-5 scale (1 = easiest for that asset, 5 = hardest):
Attacking ease (
fd_att) — driven by the opponent's defensive concession rate. Read the opponent's xGA-per-match and convert to a band. The easier the defence leaks, the lower (better) the score for your forwards/attacking mids:opponent xGA/match fd_attmeaning for your attacker ≥ 1.8 1 shooting gallery — captain/ceiling territory 1.4 – 1.8 2 soft 1.0 – 1.4 3 neutral 0.7 – 1.0 4 stingy < 0.7 5 elite back line — fade your attackers Clean-sheet / defensive ease (
fd_def) — driven by the opponent's attacking output. Read the opponent's xG-for-per-match. The blunter their attack, the lower (better) the score for your GK/defenders:opponent xG/match fd_defmeaning for your defence < 0.7 1 clean-sheet lock — stack candidate 0.7 – 1.0 2 strong CS odds 1.0 – 1.4 3 neutral 1.4 – 1.8 4 leaky game likely ≥ 1.8 5 shootout — avoid the defensive stack here
Adjust each band by ±1 for home/away (host or strong-home-support nations defend better and attack more freely at home — nudge fd_def down and fd_att down at home, up away) and clamp to [1,5]. These are the scalars wc-player-ev multiplies xG/xA by and wc-clean-sheet-model reads for P(clean sheet | fixture) — emit them, do not let those skills re-estimate opponent strength independently.
The two directions can disagree sharply and that is the point: a 1/5 split (
fd_att=1,fd_def=5) is a high-scoring-game signal — load attackers, avoid the back line; a 5/1 split is a low-event game — your GK is a lock, your striker is a trap.wc-fixture-analystreads both columns, never an averaged "FDR".
2. Progression odds — reference class, then Bayes
The probability a team advances is a forecast, so build it the disciplined way: outside view, then update.
(a) Outside view — the reference class (reference-class-forecasting). Anchor on the historical advance rate for a team of this seed/pot/ranking before looking at the current team's narrative. Starting base rates (World Cup historical seed-advance frequencies; refine against the cited source, mark provisional until confirmed):
- Group stage — P(advance from group) by pot: Pot 1 ≈ 0.80, Pot 2 ≈ 0.60, Pot 3 ≈ 0.40, Pot 4 ≈ 0.20 (these sum to ~2 per group of four, i.e. two qualifiers — sanity-check that each group's four priors total ≈ 2.0 and renormalise if not).
- Knockout single tie — P(win the tie) from the seed gap: roughly even (≈0.50) between peers, ≈0.62 for a one-tier favourite, ≈0.72 for a two-tier favourite, ≈0.82 for a three-tier-plus gulf. Never 1.0 — the highest a single-match World Cup favourite earns is ~0.85; the residual is the upset rate the reference class exists to preserve.
(b) Bayesian update on observed reality (bayesian-reasoning-calibration). Treat the base rate as the prior and update on what this tournament has actually shown:
prior_odds = p_base / (1 - p_base)
posterior_odds = prior_odds × Π_i LR_i
p_advance = posterior_odds / (1 + posterior_odds)
Evidence likelihood ratios LR_i (multiply the ones that apply; keep each bounded so no single signal swamps the prior):
| evidence | LR direction | rough magnitude |
|---|---|---|
| won MD1 / positive goal difference | > 1 | 1.3 – 1.7 |
| lost MD1 / negative GD | < 1 | 0.6 – 0.8 |
| xG strongly out-performing (over-performing finish — regress) | slightly < 1 | 0.85 – 0.95 |
| xG strongly under-performing (unlucky — expect mean-reversion up) | slightly > 1 | 1.05 – 1.20 |
key player injured/suspended for the decisive match (cite scout) |
< 1 | 0.5 – 0.8 |
| favourable remaining group draw vs unfavourable | > 1 / < 1 | 0.8 – 1.25 |
Cap the total swing so a single MD1 result can't move a Pot-1 side from 0.80 to a near-certainty — calibration over reactivity. After MD2/MD3, the group mini-table arithmetic dominates the prior: compute qualification combinatorially.
(c) Groups — qualification odds from the mini-table. Once games are played, enumerate the remaining-results space rather than trusting the seed prior:
- With one round to go, list the realistic remaining scorelines, find which combinations qualify the team (including the tie-breakers in order: points → goal difference → goals scored → head-to-head per the official rule, confirm in
league-config.md/competition rules), and weight each combination by the per-match win/draw/loss probabilities implied by the two sides'fd/strength.p_advance_group = Σ P(qualifying combinations). - 2026 best-thirds path (do not use top-two-only math): the top two per group plus the 8 best third-placed teams (of 12) advance. So
p_advance_group = P(top two) + P(3rd) × P(3rd-place points/GD ranks in the best 8 | the cross-group thirds table). The cross-group comparison means a "likely 3rd" team is often ~50–70% alive, not out — and qualification can stay undecided until other groups finish. Track the live thirds table once MD2 results land. - Surface clinched (
p_advance = 1.0, but tag dead-rubber — see step 5) and eliminated (p_advance = 0.0) explicitly; these flip the whole asset calculus.
(d) Knockouts — round-by-round survival down the bracket. A team's value horizon is the product of surviving each successive tie:
p_reach(round R) = Π_{r = current..R} p_win_tie(r)
where each p_win_tie(r) is the seed-gap base rate updated by form, against the likeliest opponent at that node (use the bracket; if the next opponent is itself unresolved, average over that opponent's own p_reach to this node). Emit the full ladder p_advance[round] for r32, r16, qf, sf, final — this is exactly the per-round survival curve wc-fitness-eval multiplies into progression_carry (Σ_r P(team alive at r) × discount^r). A team that is 0.72 to win the R16 but only 0.30 to reach the QF tells the carry term to value its assets for ~1.7 more rounds, not the whole bracket.
3. Weak-group / mismatch detection
Points come from mismatches (the A4 Fixture Exploiter thesis). Flag a fixture as a mismatch when the strength gulf is large enough that returns become cheap and near-deterministic:
- Powerhouse-vs-minnow trigger: strength delta ≥ ~2 difficulty bands and one of {
fd_att≤ 2 for the favourite's attackers,fd_def≤ 2 for the favourite's defence}. Concretely: favourite'sfd_att= 1-2 → its attackers are captain candidates (ceiling + safety together — the chalk-captain and differential-captain logic both start here); favourite'sfd_def= 1-2 vs a sub-0.7-xG attack → its defenders/GK are clean-sheet locks and a natural BB2 stack + Clean Sheet Shield target. - Weak-group flag: a whole group containing a clearly dominant side and ≥2 weak attacks — it will generate multiple cheap clean sheets and goal hauls across the group across all three matchdays; flag the group so the strategists know to mine it, not just the single fixture.
- For each mismatch, name the direction(s) (attack, defence, or both) and the asset type unlocked, so the board can route it: A1 captains the favourite's premium attacker, A4 stacks the favourite's defence, A2 looks for the low-owned member of the same mismatch (the third-choice striker who'll still feast).
Mismatches are where ownership concentrates and where the field is quickest to converge — so a mismatch flag is also an instruction to wc-ownership-analyst to expect chalk, and to the differential hunters to find the under-owned way into the same game.
4. Fixture swings — the forward calendar
The field is slow to react to fixture turns (ownership lags reality by ~a round). Identify, per team, the rounds where its difficulty flips so transfers land before the field moves:
- For each team build the difficulty path across the next
Hrounds (group: the remaining matchdays; knockout: the bracket path weighted byp_reach). A swing is a flip of ≥2 bands in either direction:- Easy→hard swing (sell signal): a team enjoying a 1-2 stretch hits a 4-5 fixture in round t+k → plan to transfer its attackers out before round t+k, and (if KO) note whether its elimination-risk round arrives first (don't pay a transfer to dodge a fixture in a team that may be gone anyway — coordinate with
tournament-state.mdelimination horizons). - Hard→easy swing (buy signal): a team coming off tough fixtures into a 1-2 run → get there a round early, before ownership rises, to bank the value the lagging field hasn't priced.
- Easy→hard swing (sell signal): a team enjoying a 1-2 stretch hits a 4-5 fixture in round t+k → plan to transfer its attackers out before round t+k, and (if KO) note whether its elimination-risk round arrives first (don't pay a transfer to dodge a fixture in a team that may be gone anyway — coordinate with
- Annotate each swing with the round id, the direction, the asset class affected (attack vs defence — a swing can be one-directional, e.g. the opponent is leaky but also dangerous:
fd_attimproves whilefd_defworsens), and a plan-ahead lead (how many rounds before the swing the transfer should fire to beat the field). Feed this straight towc-transfer-planner.
5. Dead-rubber / rotation guard
The moment a team has clinched (or been eliminated from) qualification, its final group fixture becomes a rotation risk: managers rest starters, the clean-sheet and minutes assumptions break, and an owned asset's xEV can collapse without any injury. For every such fixture:
- Tag the fixture
dead_rubber: trueand drop arotation_risk: highnote keyed to that team's assets, sowc-scoutandwc-player-evdiscount minutes andwc-fitness-evaldoesn't carry phantom progression value on a benched starter. - A clinched team still shows
p_advance = 1.0for progression, but its next-fixture difficulty and minutes carry the dead-rubber caveat — keep the two separate so the carry term isn't double-penalised. - 2026 caveat — third place is usually alive, so true dead rubbers are rarer than top-two math suggests. A team sitting 3rd on MD3 typically still has a live best-thirds path (above), and even a clinched team may play its starters to win the group (a kinder R32 bracket slot) or to protect goal difference for the thirds tie-breaker its rivals need. Only tag
dead_rubber: truewhen the team's qualification and seeding/GD incentives are both settled — otherwise tagrotation_risk: mediumwith the reason, and letwc-scoutconfirm the team-news reality near lock.
Output — the fixture signal
---
type: fixture
round: <round id, e.g. 2026-grp-md2>
date: <YYYY-MM-DD>
emitted_by: wc-fixture-progression
confidence: <0.00-1.00> # cap at 0.35 for any load-bearing strength/odds fact web-search couldn't confirm
source_urls:
- <url for team xG/xGA>
- <url for results/standings>
- <url for seeds/ranking> # or "manager-provided"
---
fixture_difficulty: # both directions, 1 (easy) .. 5 (hard), per team per round
- team: <nation>
round: <round id>
opponent: <nation>
home_away: H|A|N
fd_att: <1-5> # from opponent xGA — ease for YOUR attackers
fd_def: <1-5> # from opponent xG — ease for YOUR defence/GK
opp_xGA_per_match: <n>
opp_xG_per_match: <n>
note: <e.g. "1/5 split — high-scoring game, load attack, fade the back line">
p_advance: # the per-round survival ladder fitness-eval discounts
- team: <nation>
p_advance_this_round: <0.00-1.00>
method: reference-class+bayes | group-mini-table | clinched | eliminated
base_rate: <0.00-1.00> # the outside-view prior (seed/pot/seed-gap) BEFORE update
by_round: { r32: <p>, r16: <p>, qf: <p>, sf: <p>, final: <p> } # p_reach = Π survival
upset_rate: <1 - p_win_tie> # explicit — a favourite is never 1.0
drivers: [ "won MD1 +2 GD (LR 1.5)", "xG over-performing, regress (LR 0.9)" ]
weak_group_flags:
- group: <id>
dominant: <nation>
weak_attacks: [<nation>, <nation>]
note: "multiple cheap CS + goal hauls available across all three MDs"
mismatch_list:
- fixture: <FAV vs MINNOW> (<round id>)
strength_delta_bands: <n>
favourite: <nation>
unlocks: [ captain_candidate (attack), clean_sheet_lock (defence) ]
differential_angle: <e.g. "FAV's 2nd-choice striker — same feast, sub-8% owned">
swing_calendar:
- team: <nation>
swing_round: <round id>
direction: easy_to_hard | hard_to_easy
axis: attack | defence | both
delta_bands: <n>
plan_ahead_lead: <rounds before the swing to transfer to beat the field>
action: "sell attackers before <round>" | "buy a round early, pre-ownership-rise"
elimination_caveat: <e.g. "team's R16 elim-risk precedes this swing — may be moot">
dead_rubber_flags:
- team: <nation>
fixture_round: <round id>
status: clinched | eliminated
rotation_risk: high|medium
note: "discount minutes/CS for this team's assets this fixture"
Every numeric field declares its range so the emitter can range-check it (signal-framework.md). Downstream agents read these columns; they must not re-estimate opponent strength or advance odds for the same round.
Guardrails
- Never price a favourite as a certainty. Every
p_advancecarries itsbase_rateand an explicitupset_ratefrom the reference class; the single-match ceiling is ~0.85. If you've written 1.0 for anything other than a mathematically clinched group position, the Bayesian update has over-fit to a small sample — pull it back to the reference class. - Reference class before narrative. Anchor on the seed/pot/ranking base rate first (
reference-class-forecasting), then update on form (bayesian-reasoning-calibration). Do not let a single MD1 scoreline or a hot-form story set the prior; bound each likelihood ratio so no one signal swamps the base rate. - Two directions, always. Never collapse
fd_attandfd_definto one "difficulty" number — a fixture that is easy for attackers can be hard for the defence and vice-versa, and conflating them is the most common fantasy fixture error. Emit both columns. - Dead-rubber rotation is a hard flag, not a footnote. Once a team has qualified or is out, its remaining group asset minutes are unreliable — tag it so the EV and fitness skills discount it. A clinched team's progression is 1.0 but its next-fixture value is not.
- Swings must respect the elimination clock. Don't recommend a transfer to dodge a future hard fixture in a knockout team whose elimination-risk round arrives first (
tournament-state.md) — coordinate the swing calendar with each asset's horizon, or the move is wasted. - Confirm the strength inputs or cap confidence. Team xG/xGA, seeds, and standings are load-bearing; web-search and cite each, or mark manager-provided. Any unconfirmed load-bearing fact caps the whole signal's
confidenceat 0.35 and gets a "confirm before lock" note for the board (signal-framework.md). - Emit; don't re-derive. If a
fixturesignal already exists for this round, read it. This skill is the single source of fixture-strength scalars and progression odds for the round — downstream skills consume it rather than recomputing opponent strength.