1. What the cascade measures (and what it does not)

The projection cascade produces a per-player season-long fantasy-point projection plus its supporting decomposition. For every active MLB player the cascade outputs:

Note on population scope

The cascade operates on the active MLB roster - which includes rookies (first-year MLB players who still retain rookie eligibility), MLB-active young players (recently graduated former prospects), and established veterans. It does NOT operate on minor-league prospects who have not yet appeared in MLB; those records are handled by the prospect-shadow model instead.

Per MLB's operational definition, "prospect" status is determined by retained rookie eligibility - a player loses prospect status once they exceed any one of these thresholds:

Source: MLB rookie eligibility rules.

A player on the eligibility cusp may appear in BOTH the cascade and the shadow pipelines during their transition season - this is operationally correct (different model layers serving different scopes), not a duplication bug.

Honest data-coverage disclosure: the cascade does not currently track per-player MLB at-bats, MLB innings pitched, or active-roster service days as first-class fields. Cascade-vs-shadow routing is therefore based on whether the record has cascade-shape data (projectionAudit populated) rather than on a strict rookie-eligibility check. Five distinct concepts - prospect status, rookie eligibility, developmental stage, organizational value, fantasy relevance - are not enforced as separate fields in the cascade. See shadow methodology §1 for the detailed five-concept distinction.

What the cascade does NOT measure

Plainly listed here so any reader citing cascade output can interpret it correctly. These are real model gaps, not roadmap promises:

2. Pipeline overview - two parallel branches

The cascade is invoked from render() at line 16353. It splits into two parallel branches that share the same general stage pattern but differ in the specific functions and rate categories:

render()                                                ← line 16353
  │
  ├─ Pitcher branch
  │     groupByPlayer(pitchRows)
  │     computePitcherProjection(rows, year, popModels)   ← line 13253
  │       │
  │       ├─ Anchor + projAge + careerIP + pitchQualified  (13254-13302)
  │       ├─ Rate projection + shrinkage + age adjust      (13336-13448)
  │       ├─ Workload (IP tier + durability + ramp)        (13450-13515)
  │       ├─ Role retention probability                    (13548-13562)
  │       ├─ Fantasy-points synthesis (K, ERA, H, BB,…)    (13564-13776)
  │       └─ projectionAudit assembly (~53 fields)         (13851-13923)
  │
  ├─ Batter branch
  │     groupByPlayer(batterRows)
  │     computeBatterProjection(rows, year, popModels)     ← line 14183
  │       │
  │       ├─ Anchor + projAge + position resolution        (14184-14220)
  │       ├─ Rate projection + shrinkage + bounds          (14228-14353)
  │       ├─ Workload (PA tier + rookie ramp + slot)       (14381-14441)
  │       ├─ Context multipliers (lineup, park, prot.)     (14379-14413)
  │       ├─ Statcast compression                          (14457-14599)
  │       ├─ Fantasy-points synthesis (R, TB, RBI, BB,…)   (14586-14610)
  │       └─ projectionAudit assembly (~30+ fields)        (14626-14683)
  │
  │   Both branches converge:
  ├─ applyAvailabilityAndRiskToProjection(proj, currentYear)  ← line 12604
  │     (injury / role / callup penalties on top of cascade output)
  │
  ├─ attachFantasyValueMetrics(proj)                          ← line 5773
  │     (master confidence, talent tier, fantasy value)
  │
  ├─ runMonteCarlo(proj, …)                                   ← line 4594
  │     (~10,000 simulations per player; produces percentiles,
  │      floorPoints, upsidePoints, pctBust, pctElite)
  │
  └─ state.lastProjectionAuditRows = filtered.slice()         ← line 16534
        (downstream surfaces, including the Player Explainer,
         read from this array.)

The cascade is not phase-numbered like the shadow model (P0-P5). It is organized by archetype (pitcher vs batter) and within each archetype by stage (anchor → rates → workload → context → fantasy points → audit). The shadow model's phase numbering reflects its incremental build history; the cascade's stage organization reflects the data dependencies between the steps.

3. Anchor & role determination

The first stage of each branch establishes a baseline "anchor" - the player's best recent career season - and resolves their projected age plus role.

3.1 Pitcher anchor (lines 13254-13302)

Identifies the best career year by composite score (innings pitched, rate quality, recency). Resolves projAge from birthdate plus current season. Determines whether the player qualifies for full rate projection (pitchQualified) versus reduced shrinkage (low-sample players). Pulls role state from role_overrides: rotation lock, closer lock, swingman flag, callup probability, injury status.

3.2 Batter anchor & position (lines 14184-14220)

Same pattern. Anchor selected from best recent career year. Position resolved with explicit override-precedence: role-override file > platform position > Statcast-derived position. The resolved positionsLabel drives downstream workload tier assignment (different PA defaults for catchers vs middle infielders vs corner outfielders).

4. Rate projection - shrinkage toward population models

The cascade projects each stat category as a per-PA or per-IP rate, then multiplies by projected workload to get totals. Rate projection is the core empirical-Bayesian layer of the cascade.

4.1 Pitcher rates (lines 13336-13448)

For each rate (K%, BB%, hit-rate, ER-rate, HR-proxy):

Outputs: projK_rate, projER_rate, projH_rate, projBB_rate, projHRproxy_rate, kpctProj, stuffScore.

4.2 Batter rates (lines 14228-14353)

Same pattern, different categories: R, TB, RBI, BB, K, SB. Each rate is shrunk toward a position-bucketed population mean (catchers have different population means than middle infielders, etc.). Additional defensive steps:

Outputs: projR_rate, projTB_rate, projRBI_rate, projBB_rate, projK_rate, projSB_rate.

5. Workload modeling - IP (pitcher) / PA (batter)

5.1 Pitcher workload (lines 13450-13515)

Assigns the pitcher to a workload tier based on role, injury history, archetype, and recent IP. The tier label is exposed as workloadTierLabel in the audit block; common values include workhorse, mid-rotation, back-end, swingman, closer, setup, middle relief.

The tier determines:

5.2 Pitcher role retention (lines 13548-13562)

A separate roleRetentionProbability multiplier representing the probability the pitcher stays in their assigned role through the season. Reads rotation locks, closer locks, depth-chart rank, injury risk, prior-season starts. A 0.8 retention probability scales final IP by 0.8 (the model expects 20% of innings to be lost to role change).

5.3 Batter workload (lines 14381-14441)

Assigns the batter to a PA tier from a defined set: full_time, regular, part_time, platoon, backup, injury_replacement. The tier sets workloadPA as the base projection.

Rookie ramp adjusts PA downward for first-year players based on pedigree (rookieRampMult). Lineup slot is either taken from explicit override or guessed from position and tier (slotGuess). The guessed slot influences R/RBI multipliers (heart-of-order produces more runs and RBI per PA).

6. Context multipliers - park, lineup slot, lineup protection

Once base rates and workload are projected, context multipliers adjust the totals. Lines 14379-14413 (batter side; pitcher side has analogous park adjustments in the fantasy-point synthesis layer).

These multipliers are applied multiplicatively. They are NOT position-adjusted in any sophisticated way (e.g., the lineup-slot multiplier is the same for catchers and outfielders) - see §16.

7. Statcast compression layer (batters)

Lines 14457-14599. For batters, Statcast-derived features compress into multipliers applied to power and contact projections:

The Statcast layer is the batter cascade's most empirically-rich component. For pitchers, the analogous layer is the stuffScore nudge inside rate projection (§4.1) plus xERA blending inside fantasy-point synthesis (§8); the pitcher cascade does not have a dedicated Statcast compression block.

8. Fantasy-point synthesis

The synthesis stage converts projected rates × workload into per-category totals, then weights them by the league's scoring system into the headline projPoints.

8.1 Pitcher synthesis (lines 13564-13776)

For each scoring category:

The cascade applies a final sanity cap: if rawProjPts exceeds an archetype-specific ceiling, the result is hard-capped and the difference is recorded as spikeRisk (so the audit shows the model was constrained).

8.2 Batter synthesis (lines 14586-14610)

For each category (R, TB, RBI, BB, K, SB), totals are computed as rate × PA × context_multiplier. Aging effects and talent-ceiling clamps are applied as final modulators. talentCeiling is a per-tier maximum that prevents low-tier batters from projecting elite output even with favorable contextual factors.

The synthesis stage emits projPoints, rawProjPts, projPointsFloor, and projPointsCeiling. The Floor and Ceiling are first-pass estimates that are refined by the Monte Carlo layer (§9).

9. Monte Carlo simulation

runMonteCarlo() at line 4594. After the deterministic cascade produces a point estimate, ~10,000 simulations (configurable via MC_SIMS_FINAL or MC_SIMS_QUICK) are run per player to produce the full outcome distribution.

9.1 State-based simulation

Each simulation first draws a role state before drawing per-category outcomes:

Breakout and collapse probabilities are age-conditional: young players carry ~12% breakout / 6% collapse priors; older players carry ~6% breakout / 24% collapse priors.

9.2 Per-category draws

Within each simulation, per-category rates are drawn from distributions centered at the projected rates with variance set by stabilization confidence. Categories are drawn independently (e.g., BB and K rates are not correlated through chase rate) - see §16.

9.3 Outputs

The MC layer is the cascade's most computationally expensive stage. Quick mode (MC_SIMS_QUICK) is used for live UI; final mode (MC_SIMS_FINAL) is used when the user explicitly requests full recomputation.

10. Talent-tier classification

computeTrueTalentTier() at line 15173. Assigns each player to one of five tiers:

TierLabelPitcher gate (example)Batter gate (example)
1superstarK% > 0.30 + IP > 180, or stuff score > 0.55peak TB rate top 0.5% + sustained PA
2eliteK% > 0.28 + IP > 150, or stuff > 0.40peak TB top 2% + multiple seasons
3quality starter / regularK% > 0.22 + IP > 120solid current-form + adequate sample
4role / platoonlower IP or marginal rateslimited PA tier or weak hitter grade
5fringeminimal MLB sample, no rate stabilityfringe-roster signal

Tier assignment is multi-gate and conservative. A player needs to meet either current-form criteria OR peak-evidence criteria to qualify for tiers 1-2; meeting both produces high-confidence assignment.

11. Master confidence - six-component composite

computeMasterConfidence() at line 5729. Multiplicative composite:

masterConfidence = rosterConf
                 × roleConf
                 × sampleConf
                 × marketConf
                 × √survivorship
                 × √realPlayerProb
                 × spikeRiskMult

Component definitions:

The composite is multiplicative, so a single very-low component significantly reduces confidence. This is intentional: a player with great rate confidence but no role lock should not be projected with high overall confidence.

12. Bust risk + elite-season probability

Both come from the Monte Carlo distribution (§9), not from separate computations.

The 8% elite threshold is a construction choice. The cascade uses it as a consistent yardstick for the upper tail; users should not read it as "8% chance this player is elite" without qualification.

13. Audit assembly - what projectionAudit contains

The projectionAudit block (assembled at lines 13851-13923 for pitchers, 14626-14683 for batters) is the cascade's transparency surface. It is attached to each player record as rec.projectionAudit and is the primary data source for the Player Explainer's cascade-projection sections.

Field categories:

CategoryFields
Workload workloadTierLabel, workloadIP, workloadPA, ipLo/ipHi, paFloorApplied
Talent talentTier, talentCeiling, projAge, breakoutMult
Confidence masterConfidence, rosterConfidence, roleConfidence, sampleConfidence2, marketConfidence, orgTrust
Rates (batter) projTBrate, projRrate, projSBrate, projBBrate, projKrate, peakTBrate
Rates (pitcher) kpctProj, stuffScore, workloadOuts
Risk callupRisk, platoonRisk, roleRetentionProbability, durabilityMult, archetypeDispersionMult, spikeRisk
Role pCloser (probability of closer role), workloadRampCap (IL ramp)

The audit block is read directly by the Explainer's _renderHeadline, _renderWhy, _renderSensitivity, and other render functions. Every number a user sees in those sections corresponds to a field in this block.

14. Required inputs

The cascade reads broadly from both per-player record fields and global state.

14.1 Batter rec fields

player_id, player_name, pa, year, r_run, b_total_bases, b_rbi, walk, strikeout, r_total_stolen_base, b_game, plus Statcast: xwoba, woba, barrel_batted_rate, hard_hit_percent, avg_best_speed, sprint_speed, whiff_percent, out_zone_swing_percent, avg_swing_speed.

14.2 Pitcher rec fields

player_id, player_name, p_out, year, p_strikeout, p_earned_run, p_total_hits, p_walk, p_win, p_loss, p_save, p_blown_save, p_starting_p, p_game_in_relief, plus Statcast: xera, p_era, k_percent, bb_percent, whiff_percent, barrel_batted_rate, hard_hit_percent.

14.3 Global state reads

15. Version status

As of the latest methodology revision, the projection cascade carries a methodology version stamp on every output: projectionAudit.methodologyVersion = 'cascade-v1.0'. This closes the gap previously documented in this section.

Both pitcher and batter cascade audit objects (constructed in app.js at the two projectionAudit assignment sites) include the field. Cascade-derived numbers in the Player Explainer, the research-snapshot export, and the Operations workspace now all carry the version reference.

15.1 Version history

15.2 Version-bump policy

Future methodology changes that alter cascade computations should be paired with a version bump here AND in the projectionAudit.methodologyVersion string. Documentation drift between this page and the audit-block stamp should be treated as a real bug, not a cosmetic inconsistency.

16. Limitations

Known limits of the cascade as it operates today. Each is a real model property, not an apology:

17. Related methodology

The three model layers (cascade, prospect-shadow, FYPD) are intentionally separated. Each has its own input scope, its own methodology, and its own output surface. Composing them into a single ranking is a downstream concern, not a model-layer concern.

17.1 Cross-surface vocabulary notes

Two words appear with structurally different meanings across the platform's model layers: "confidence" (used in masterConfidence here in the cascade, but also in shadow's confidenceBucket, identity-graph join confidence, injury reports, position attribution, and the disagreement signal) and "archetype" (used in the cascade's workload, aging, and volatility classifications, and separately in the shadow model's prospect-archetype buckets and the Operations portfolio archetypes). Each usage is correct within its own context; the overloading is at the platform level.

The cross-surface translation tables are documented in shadow methodology §16.4. Refer there before comparing "confidence" or "archetype" values across different surfaces.

18. How to cite

When citing cascade output in analytical writing:

Example: Per managr Projection Cascade v1.0 (computed 2026-05-17), Player X projects to 425 fantasy points (P10 280, P90 560) with master confidence 0.72 and talent tier 2.