Skip to content

MEIO V4 Worked Numbers — Every Figure, Traced

Status: Companion walkthrough for the implemented MEIO V4 release (Aug 2026). Every number below is exact arithmetic on the stated inputs, computed by the same formulas the optimizer runs (files/meio_network_topology.py, files/meio_runner.py::_attach_v4_network, files/MEIO_v3/src/marginal.rs).

How to read this page: first the toy network, then every input with its master-data source, then the numbered computations. Each computation says what, why, and where it shows up (Network Diagnostics panel, MEIO results). Nothing here is approximated — reproduce it on a calculator and you get the optimizer's numbers.

1. The toy network (in gps_1 geography)

A small version of the crates network — the same site names you see in gps_1, with round numbers for easy checking. One returnable crate (item 7, the "GPS Standard Crate"):

flowchart LR
    WH["Bremen Supplier (100)"] -->|"TRANSFER 6 wk (standard)"| S1["Frankfurt DC (81)"]
    S2["Rotterdam DC (80)"] -->|"BALANCING 0.25 wk (rescue)"| S1
    S3["Continental Hannover (84)"] -->|"RETURN 1 wk (dirty crates)"| F["Rotterdam Wash (facility)"]
    F -->|"REPAIR 3 wk, yield 0.8, quota 1"| S1
    F -->|"REPAIR 3 wk, yield 0.8, quota 3"| S2
  • The GPS Europe zone contains Frankfurt (81) and Rotterdam (80) for item 7 (config_zone_parameter), so the BALANCING route between them classifies as a rescue edge — exactly like the real routes 7/11 in gps_1.
  • Bremen Supplier → Frankfurt is a TRANSFER route: standard hierarchy replenishment.
  • Continental → Rotterdam Wash is the only dirty-crate inflow of the facility (a RETURN route) — the tyre plant does not get its own crates back.
  • Rotterdam Wash sends repaired good units to Frankfurt and Rotterdam — not back to Continental. This is the pooled repair model: whatever arrives at the facility repairs whoever the output quotas say.

2. All inputs, with their master-data source

# Input Value Comes from
I1 Item 7 ("GPS Standard Crate") every route's item_id
I2 Zone membership item 7, zone "GPS Europe", members {81 Frankfurt, 80 Rotterdam}, participation 1 config_zone_parameter
I3 Demand at Frankfurt λ = 4 units/week master.demand_actuals → SKU total_demand_rate
I4 Demand at Rotterdam λ = 4 units/week same
I5 Demand at Continental λ = 6 units/week same
I6 TRANSFER Bremen→Frankfurt lead time 6 weeks, network_role empty master.route (LT days / 7)
I7 BALANCING Rotterdam→Frankfurt lead time 0.25 weeks, network_role empty master.route. 0.25 wk ≈ 1.75 days
I8 RETURN Continental→Rotterdam Wash return_rate 0, push_quota 0.5, return_wash_rate 0.2, LT 1 week master.route
I9 REPAIR Wash→Frankfurt repair_yield 0.8, shop LT 3 weeks, wip_qty 6, capacity resource 42 (3 units/week), push_quota 1.0 master.route + route_resource/capacity_id → {schema}.pipe_supply_capacity
I10 REPAIR Wash→Rotterdam repair_yield 0.8, push_quota 3.0 same
I11 Fill-rate TARGET 0.95 for the zone/segment group segment MEIO parameter set (config_meio_parameter_set) — this is the goal you configure (your 95%/98% values in gps_1)
I12 Rotterdam leg lead time 1 week route blend → SKU leg_lead_time
I13 Frankfurt leg lead time 1 week same

network_role empty everywhere on purpose: the whole classification comes from route type + zone membership — the default the customer sees without touching the Routes grid.

Optimizer state — NOT inputs (used in the arithmetic below)

Two values in the computations that follow look like inputs but are mid-run optimizer state, not master data or configuration:

State value Toy value Where it comes from
Bremen Supplier current fill rate FR = 0.90 The fill rate the supplier's currently committed buffer produces at the moment the optimizer evaluates the next investment step. It starts low (little or no buffer) and is recomputed after every committed step as the buffer grows toward the target.
Frankfurt current fill rate FR = 0.60 Same for Frankfurt — a snapshot from partway through the greedy loop, not a setting.

Do not confuse these with the target (I11): the target is what you configure (0.95/0.98 in gps_1); the current FR is what the optimizer has achieved so far. The formulas need the current value because the marginal questions are state-dependent:

  • hierarchy wait (N2): parent_wait = LT × (1 − FR_supplier_current) — the more stocked the supplier already is, the less the child suffers;
  • shortage claim (N5): (1 − FR_Frankfurt_current) × λ × horizon — the remaining gap the rescue could cover, which shrinks as Frankfurt's own buffer grows.

In the toy arithmetic the values 0.90 and 0.60 were picked as convenient mid-run snapshots; in a live run they move at every iteration.

What leg_lead_time actually is (I12–I13)

leg_lead_time is not something you type anywhere — it is computed by the engine from your routes:

leg_lead_time(item, site) = Σ(coverage_pct_i × LT_i) / Σ(coverage_pct_i)
                            over every BUY / TRANSFER / MAKE route arriving at (item, site)
  • Per route, the lead time is the route's total days converted to weeks: (lead_time + transit_time + pick_pack_time) / 7 from master.route.
  • The blend (route_lt_blend in meio_runner.py): when several replenishment routes serve the same SKU at the same site, the leg is the coverage-weighted average of their lead times — the route that physically supplies 60% of the flow contributes 60% of the leg. If no route carries a coverage_pct, they split equally.
  • Meaning: the deterministic time between "I order from my standard supplier(s)" and "stock is on my shelf" — before any parent wait. Your full horizon is leg + wait: the leg is your route's fault, the wait is your upstream parent's fault (N2).
  • Zone scenarios (enable_zone_pass) deliberately swap this for an all-route blend (every arriving route type, not just BUY/TRANSFER/MAKE), so warehouses replenished by REPAIR/BALANCING loops still get a real lead time for the pooled zone pass.

Toy values are round (1 week for both warehouses) to keep the arithmetic clean. For reference, the gps_1 live runs produced: Rotterdam 0.0 wk (its replenishment is the on-site wash line — no transit), Frankfurt 10.0 wk, Memphis 9.0 wk, Detroit 0.0 wk, and the producers ≈ 0.4–0.6 wk (their crate supply is local).

3. Edge classification (N1)

Classification precedence: explicit network_role → zone-aware default → standard.

Route Type Co-zonal for item 7? Classified as Why
Bremen→Frankfurt TRANSFER n/a Standard replenishment TRANSFER is always the hierarchy (forward), never rescue, unless the planner sets network_role='rescue'.
Rotterdam→Frankfurt BALANCING yes (both in the GPS Europe zone for item 7) Lateral rescue intra-zone balancing = the default rescue lane.
Continental→Rotterdam Wash RETURN n/a Repair pool inflow RETURN never serves demand; it replenishes the facility's bad pool.
Wash→Frankfurt, Wash→Rotterdam REPAIR n/a Repair pool outputs good output of the shared facility pool, split by push_quota.

The Network Diagnostics panel lists exactly these four edge groups for the scenario.

4. Hierarchy wait — the standard branch (N2)

The Bremen supplier replenishes Frankfurt. The hierarchy wait Frankfurt suffers when the supplier is stocked out:

parent_wait = LT_supplier × (1 − FR_supplier) = 6 × (1 − 0.90) = 0.6 weeks

That 0.6 weeks is Frankfurt's base wait (stored as current_base_wait_time — the pre-rescue hierarchy wait the optimizer can always recover).

Frankfurt's standard resupply horizon (no rescue, no repair):

H_Frankfurt = leg_LT + base_wait = 1 + 0.6 = 1.6 weeks

5. Rescue: how much stock can Rotterdam actually lend? (N3–N7)

N3 — Rotterdam's protected stock (a source never sacrifices itself)

Rotterdam's own pipeline requirement (demand over its own effective lead time):

protected_Rotterdam = λ × (leg_LT + wait) = 4 × (1 + 0) = 4 units

Rotterdam has no configured min floor (sku_min_sl_qty = 0), so the protection is this pipeline baseline. (With an ASL floor configured, the protection would be that floor instead.)

N4 — Rotterdam's free (shareable) stock

free_Rotterdam = max(0, rop − protected) = max(0, 6 − 4) = 2 units

Fill rate is not availability: Rotterdam's FR is 0.92, but only 2 units are lendable — 4 units are busy covering its own demand. This is the number the old proposal's FR × dilution formula could not produce.

N5 — Frankfurt's shortage claim

shortage_Frankfurt = (1 − FR) × λ × H
                   = (1 − 0.60) × 4 × 1.6
                   = 0.40 × 4 × 1.6
                   = 2.56 units

N6 — Allocation of Rotterdam's free stock

Frankfurt is Rotterdam's only claimant (one-hop rescue edge). The BALANCING route has no capacity resource, so the lane is uncapped:

alloc_Rotterdam→Frankfurt = min(shortage, free) = min(2.56, 2) = 2 units

Arrival probability: the rescue lead time (0.25 wk) beats the standard horizon (1.6 wk) with certainty, and there is no configured lead-time variability on this route:

P(arrival ≤ H_Frankfurt) = 1.0   (0.25 ≤ 1.6, deterministic)
useful                   = alloc × reliability × P(arrival) = 2 × 1.0 × 1.0 = 2 units

N7 — Rescued fraction and the blended wait

rescued_fraction = min(useful, shortage) / shortage
                 = min(2, 2.56) / 2.56
                 = 0.78125

Frankfurt's effective wait blends the fast rescue arrival with the slow hierarchy wait:

wait_Frankfurt = (1 − 0.78125) × 0.6 + 0.78125 × 0.25
        = 0.21875 × 0.6 + 0.1953
        = 0.13125 + 0.1953
        = 0.327 weeks     (was 0.6 without rescue)

New effective horizon:

H'_Frankfurt = leg_LT + wait = 1 + 0.327 = 1.327 weeks   (was 1.6)

Every unit the optimizer adds at Rotterdam is priced with this horizon reduction for Frankfurt — the source's buffer helps its peer by exactly the allocated quantity, not by a diluted fill rate.

6. Repair as a pooled, timed supply process (N8–N12)

N8 — The wash facility's inflow pool

The RETURN route carries return_rate = 0, so the dual-convention rule uses the bad_forecast formula:

fraction = push_quota × (1 − return_wash_rate)
         = 0.5 × (1 − 0.2)
         = 0.40 of Continental's demand returning as dirty crates
pool_inflow = 0.40 × λ_Continental = 0.40 × 6 = 2.4 units/week

(The other convention — a return_rate > 0 on the RETURN route — would win over this formula when set. Both are explicit master data; nothing is guessed.)

The pool-inlet lead time is the fraction-weighted mean of the facility's RETURN routes. Only one route exists:

return_LT = (0.40 × 1) / 0.40 = 1 week

N9 — Capacity and output split

The wash line allows 3 units/week; inflow is 2.4:

pool_available = min(inflow, capacity) = min(2.4, 3) = 2.4 units/week

The facility's two REPAIR outputs split by push_quota (source-side outflow policy):

quota_Frankfurt : quota_Rotterdam = 1 : 3   →   share 0.25 / 0.75

(If all quotas at a facility were NULL/0, the split would be equal — the same normalization the indirect-demand rollup uses for coverage.)

pool_to_Frankfurt = 2.4 × 0.25 = 0.6 units/week
pool_to_Rotterdam = 2.4 × 0.75 = 1.8 units/week

N10 — Yield and the wire values sent to the optimizer (Frankfurt)

good_units_Frankfurt = pool_to_Frankfurt × repair_yield = 0.6 × 0.8 = 0.48 units/week

The Python pre-pass writes, on Frankfurt's repair process edge:

Wire field Value Meaning
return_rate 0.48 / 4 = 0.12 allocated good units as a fraction of Frankfurt's demand
repair_yield 1.0 yield already applied once — the Rust side must not re-apply it
capacity_per_week 0.48 allocated good units; the engine's min(inflow, cap) stays harmless
current_wip_qty 6 × 0.8 = 4.8 WIP pre-multiplied by yield for exactly the same reason
total_cycle_weeks return 1 + shop 3 = 4 weeks the repair branch's own lead time

N11 — Net demand after timed repair (Rust side)

bad_inflow  = λ_Frankfurt × return_rate = 4 × 0.12 = 0.48 units/week
throughput  = min(bad_inflow, capacity) = min(0.48, 0.48) = 0.48
good_out    = throughput × repair_yield = 0.48 × 1.0 = 0.48
net_demand  = max(0, λ − good_out) = 4 − 0.48 = 3.52 units/week

Legacy V3 netting would have computed the same net demand here — the difference comes next.

N12 — WIP phased by horizon, and the horizon blend

Legacy netting credited all WIP×yield immediately (4.8 units as if on the shelf). V4 only credits what can finish inside Frankfurt's own resupply horizon:

cycle        = 4 weeks
horizon      = H'_Frankfurt = 1.327 weeks (from N7)
phase        = min(1, horizon / cycle) = min(1, 1.327 / 4) = 0.3318
WIP_credit   = 4.8 × 0.3318 = 1.59 units    (legacy: 4.8 — three times as much)

And the demand covered by repair accrues over the repair cycle, not over the procurement horizon (the horizon blend):

procurement-side demand over horizon = net_demand × H'_Frankfurt
                                     = 3.52 × 1.327 = 4.671 units
repair-side demand over cycle        = good_out × cycle
                                     = 0.48 × 4 = 1.92 units
effective demand-over-lead-time      = 4.671 + 1.92 = 6.59 units

If the wash facility takes 8 weeks instead of 4, the second term doubles to 3.84 and the total becomes 8.51 — a longer repair lead time genuinely raises Frankfurt's stock requirement, which the legacy netting could not express at all.

Sanity table — legacy V3 vs V4 for Frankfurt

Quantity Legacy netting (V3 mode) Timed repair (V4 mode)
Net weekly demand 3.52 3.52
Demand over effective LT 3.52 × 1.6* = 5.63 4.671 + 1.92 = 6.59
WIP credit 4.8 (immediate) 1.59 (phased)
Repair lead time invisible explicit driver of stock

* V3 also had no rescue, so its horizon is the un-blended 1.6 weeks (leg + hierarchy wait). V4 mixes both effects into one effective requirement — this is the full picture of what changed.

7. Two claimants, one pool — the allocation policy (N13)

Independent second example. Suppose Rotterdam had two rescue claimants: Frankfurt (criticality 2, shortage 3.2) and Detroit DC (criticality 1, shortage 1.6), and Rotterdam's free stock were 3 units.

Priority-then-proportional (locked policy): criticality tiers are served first; equal tiers split proportionally to their claims.

Tier crit=2: claims 3.2, pool 3 → pool exhausted within the tier
  Frankfurt gets min(3.2, 3) = 3 units   (proportional split inside one-claimant tier)
Tier crit=1: claims 1.6, pool left 0
  Detroit gets 0 units

If Rotterdam's free stock were 4.6 instead:

Tier crit=2: 3.2 ≤ 4.6 → Frankfurt gets its full 3.2; pool left = 1.4
Tier crit=1: Detroit gets min(1.6, 1.4) = 1.4

The allocation is source-conserving in every case: the sums never exceed the free pool, so one unit of backup can never be credited to two destinations at once.

8. Where each number shows up

Number Surface
Edge classes (N1) Network Diagnostics panel — Rescue / Standard/edge tables
Base wait (N2) internal (current_base_wait_time); diagnostics show the hierarchy edges
Free stock (N3–N4) not displayed directly; drives the rescue-credit computation
Allocation & rescued fraction (N6–N7) changes Frankfurt's effective wait → MEIO results wait time column
Pool inflow/split (N8–N9) Network Diagnostics — Timed repair processes table (inflow via facility row, quota per output)
Wire values (N10) internal; the table above is exactly the payload
Net demand, WIP, horizon blend (N11–N12) internal; reflected in Frankfurt's committed buffer (MEIO results Committed buffer)

9. One-paragraph version for the customer

Rotterdam DC carries six crates of stock. Four are busy feeding its own demand, so two are lendable. Its sister depot Frankfurt, in the same GPS Europe zone, has an expected gap of 2.56 crates over its six-week supplier resupply, so it takes those two — its effective wait drops from 0.6 to 0.33 weeks. Meanwhile the Rotterdam wash line receives 2.4 dirty crates per week from Continental Hannover, keeps them under its 3-per-week line, repairs eight out of ten, and sends a quarter of the output to Frankfurt: 0.48 good crates per week arriving four weeks after the crates got dirty. That stream covers part of Frankfurt's demand, but only 1.6 of the 4.8 WIP units count as available today — because the rest cannot finish inside Frankfurt's 1.3-week window. The optimizer sizes Frankfurt's buffer on 6.59 crates of demand-over-lead-time instead of 5.63, because repaired supply is supply with a lead time of its own, and sibling stock only counts when it is actually free, allocated, and close enough to matter.

Appendix — full arithmetic in one column

parent_wait (Bremen)   = 6 × (1−0.90)                          = 0.600 wk
protected_Rotterdam    = 4 × (1+0)                             = 4.000 units
free_Rotterdam         = max(0, 6 − 4)                         = 2.000 units
H_Frankfurt            = 1 + 0.6                               = 1.600 wk
shortage_Frankfurt     = 0.40 × 4 × 1.6                        = 2.560 units
alloc_Rot→Fra          = min(2.56, 2)                          = 2.000 units
useful                 = 2 × 1.0 × 1.0                         = 2.000 units
rescued_fraction       = 2 / 2.56                              = 0.78125
wait_Frankfurt         = 0.21875×0.6 + 0.78125×0.25            = 0.327 wk
H'_Frankfurt           = 1 + 0.327                             = 1.327 wk
return fraction        = 0.5 × (1−0.2)                         = 0.400
pool_inflow (Continental) = 0.4 × 6                            = 2.400 units/wk
pool_available         = min(2.4, 3)                           = 2.400 units/wk
quota split            = 1:(1+3), 3:(1+3)                      = 0.25 / 0.75
pool_to_Frankfurt      = 2.4 × 0.25                            = 0.600 units/wk
good_units_Frankfurt   = 0.6 × 0.8                             = 0.480 units/wk
wire return_rate       = 0.48 / 4                              = 0.120
net_demand             = 4 − 0.48                              = 3.520 units/wk
wire WIP               = 6 × 0.8                               = 4.800 units
cycle                  = 1 + 3                                 = 4.000 wk
WIP phase              = min(1, 1.327/4)                       = 0.3318
WIP_credit             = 4.8 × 0.3318                          = 1.590 units
demand over LT         = 3.52×1.327 + 0.48×4                   = 6.590 units

Case study — gps_1 crates network (live data, Aug 2026)

Same formulas, real tenant. Scenario "V4 Network Rescue" (id 3) bound to pipelines 2 (MRP) and 3 (LP); item 7 "GPS Standard Crate" (unit cost 5.0).

Classification produced 21 edges

Class Count Which
Lateral rescue 4 BALANCING pairs 80↔81 (Rotterdam↔Frankfurt) and 85↔86 (Memphis↔Detroit), τ = 2 days = 0.286 wk — intra-zone in config_zone_parameter
Forward replenishment 12 TRANSFER/inter-zone routes
Use (consumption) 5 USE routes to the tyre plants
Repair process 2 facility 80 (Rotterdam wash) and facility 85 (Memphis wash)

Repair pool arithmetic (exact, from the engine's own batch demand rates)

Facility 80 — Rotterdam wash. Only RETURN inflow: route 56, Continental Hannover (84) → 80, return_rate=0.8, LT 4 days = 0.571 wk. Only REPAIR output: route 12, 80 → 80, shop LT 7 days = 1.0 wk, yield 0.92, WASH resource cap 400 units/wk, quota 1.0 (sole output → share 1.0).

λ(item7 @ Continental 84)   = 808.3482 units/wk        (batch demand signal)
pool inflow                 = 0.8 × 808.3482           = 646.679 units/wk
pool available              = min(646.679, 400)        = 400.000 units/wk   ← capacity caps
good units to Rotterdam     = 400 × 0.92               = 368.000 units/wk
wire return_rate            = 368 / 703.5683           = 0.523048
λ(item7 @ Rotterdam 80)     = 703.5683 units/wk
net demand after repair     = 703.5683 − 368           = 335.568 units/wk   (−52.3%)
repair cycle                = 0.571 + 1.0              = 1.571 wk

Facility 85 — Memphis wash. RETURN route 22 from Cooper Tire Findlay (88), return_rate=0.8, LT 3 days = 0.429 wk. REPAIR route 21, 85 → 85, yield 0.92, cap 100 units/wk.

λ(item7 @ Cooper 88)        = 230.7305 units/wk
pool inflow                 = 0.8 × 230.7305           = 184.584 units/wk
pool available              = min(184.584, 100)        = 100.000 units/wk   ← capacity caps
good units to Memphis       = 100 × 0.92               = 92.000 units/wk
wire return_rate            = 92 / 291.5685            = 0.315535
net demand at Memphis       = 291.5685 − 92            = 199.569 units/wk   (−31.6%)
repair cycle                = 0.429 + 1.0              = 1.429 wk

Rescue arithmetic (why the effect is tiny on this network)

Route 7, Rotterdam(80) → Frankfurt(81): the source's protection is its own demand over its own horizon — Rotterdam's leg is 0 weeks, so:

protected_80 = net_rate × (leg + wait) = 335.568 × (0 + 0) = 0
free_80      = committed ROP − 0 = 1 − 0                 = 1 unit only
shortage_81  = (1 − 0.0000) × 376.5935 × (10 + 0)        = 3765.9 units
alloc        = min(3765.9, 1)                            = 1 unit
rescued_fraction = 1 / 3765.9                            = 0.00027
blended horizon  = (1−0.00027)×10 + 0.00027×0.286        = 9.997 wk (from 10)

Route 20, Detroit(86) → Memphis(85): Detroit also holds 1 unit → rescued_fraction ≈ 0.0018, horizon 9 → 8.984 wk. The optimizer's answer on this data: rescue lanes exist but the sources hold no surplus, so almost nothing flows — and it does not pay to stock Rotterdam/Detroit just to feed their sisters. That is a legitimate planning conclusion, visible for the first time, not a model failure.

Results written (pipeline 2, archive 2026-07-27, scenario 3)

Site rop safety stock fill rate wait leg Note
80 Rotterdam 1.0 1.0 1.0000 0.0 0.0 zero lead time + 52% repair coverage → floor buffer
81 Frankfurt 250.0 0.0 0.0000 0.0 10.0 indirect-only demand under direct scope (identical in V3)
82 Michelin 16650.0 16417.9 0.7500 0.0 0.43 direct demand 541.6/wk
83 Bridgestone 9950.0 9759.6 0.7917 0.0 0.57 direct demand 333.3/wk
85 Memphis 2651.0 26.9 0.6976 0.0 9.0 net demand 199.6/wk after repair
86 Detroit 1.0 1.0 1.0000 0.0 0.0 floor buffer
87 Goodyear 12700.0 12506.8 0.8333 0.0 0.49 direct demand 397.8/wk

All waits are 0.0000 because no parent imposes one: every TRANSFER-free network edge is USE/REPAIR/BALANCING, and the hierarchy propagation only follows TRANSFER routes. Rescue therefore acts on the horizon (leg-shortening), not on a parent wait — the V4 runs moved Memphis from 2687 → 2651 units (−36 × €5 = −€180) when the horizon-blend correction landed.

Why Frankfurt shows zero safety stock and Memphis does not (the two real blockers)

Both sites are indirect-only warehouses — but neither outcome is caused by the demand scope. The debug trace of the same run proves it:

Frankfurt (81) is clamped by its depot storage cap. The ASL floor (sku_min_fill_rate = 0.7 from the catch-all parameter set) computed its ideal buffer:

ASL buffer (Frankfurt) ≈ 3766 units   (λ 376.59/wk × 10-wk horizon + safety → fr 0.697)
location cap (Frankfurt DC) = 250 units        ← master.site.max_capacity_qty
committed buffer          = min(3798, 250)     = 250
fill rate at 250 vs demand-over-LT 3765.9      ≈ 0.0000   ← the displayed 0.0000

Memphis (85) is parked by the max fill-rate ceiling. ASL pushed it to buffer 2651 (fr 0.6976); the greedy loop's next step would take it from 0.6976 to 1.0000, which exceeds the catch-all parameter set's sku_max_fill_rate = 0.999 → below_max=false → the SKU is exhausted and receives no further investment. It stays at 0.6976 — above its 0.7 floor region, below the 0.95 target, blocked by the ceiling.

Consequence for configuration: switching demand_scope to total changes nothing on these two sites because they are constraint-limited, not reward-limited. Total scope pays off when the greedy loop's reward decides the investment (e.g. uncapped indirect warehouses without a max-fill collision). To move these two: raise Frankfurt's max_capacity_qty (master data, via import.site) if 250 is a placeholder, and/or raise the segment's sku_max_fill_rate toward 1.0 if parking at 0.6976 is undesired.

The leg blend in gps_1, decomposed per site

Only Goodyear Akron actually exercises the weighted average — every other site has exactly one replenishment route (or none):

Site Route Type Source LT (days) coverage_pct Weight share LT×share
Frankfurt DC (81) 35 BUY external supplier 70 NULL → 1.0 1.000 10.000 wk
Michelin Clermont-Ferrand (82) 57 TRANSFER Rotterdam DC 3 1.0 1.000 0.429 wk
Bridgestone Béthune (83) 50 TRANSFER Frankfurt DC 4 1.0 1.000 0.571 wk
Memphis DC (85) 49 BUY external supplier 63 NULL → 1.0 1.000 9.000 wk
Goodyear Akron (87) 5 TRANSFER Memphis DC 3 0.6 0.600 0.257 wk
〃 6 TRANSFER Detroit DC 4 0.4 0.400 0.229 wk
〃 blend Σ = 1.0 0.486 wk

Goodyear's leg: 0.6 × (3/7) + 0.4 × (4/7) = 0.257 + 0.229 = 0.486 wk. Rotterdam (80) and Detroit (86) have no BUY/TRANSFER/MAKE route arriving — their replenishment is the on-site REPAIR wash loop, which the standard blend deliberately excludes — so their leg is 0.0 wk (their supply timing comes from the repair process edges, N8–N12, not from the leg blend).

Install-base direct demand (Aug 2026 addition)

The producers (Michelin Clermont-Ferrand 82, Bridgestone Béthune 83, Goodyear Akron 87) are flagged is_install_base — their demand is direct customer demand for the GPS depots. The first-hop TRANSFER rollup now tags those good_replenishment rows is_install_base_direct = 1 and MEIO counts them as direct demand at the receiving depot:

Rotterdam (80) ← Michelin (82):    29,140 units tagged direct → ddr = 135.2/wk
Frankfurt (81) ← Bridgestone (83): 17,641 units tagged direct → ddr =  89.1/wk
Memphis   (85) ← Goodyear (87):    13,607 units tagged direct → ddr =  62.8/wk
Detroit   (86) ← Goodyear (87):     9,071 units tagged direct → ddr =  41.5/wk

All four depots now carry is_direct_demand = 1 in PIPE_meio_results — they earn group reward and are sized as customer-facing stocking points, while their total sizing signal is unchanged (the split moves attribution, not volume).

How to check every number yourself

  1. Edge classification: MEIO Scenarios → edit "V4 Network Rescue" → Network Diagnostics (V4) panel — 4 rescue edges, 12 standard, 2 repair processes, each with LT/cap/yield.
  2. Route inputs: Settings → Master Data → Routes — routes 7/11/16/20 (BALANCING, 2-day lead), 56/22 (RETURN, return_rate 0.8), 12/21 (REPAIR, yield 0.92). Net Role column empty → default classification.
  3. Pool inputs: the inflow fractions and quotas in SQL —
SELECT r.id, r.item_id, r.site_id, r.source_site_id, rt.planning_type,
       r.return_rate, r.push_quota, r.repair_yield
FROM master.route r JOIN master.route_type rt ON rt.id = r.type_id
WHERE rt.planning_type IN ('RETURN','REPAIR');
  1. Capacity: SELECT * FROM gps_1.pipe_supply_capacity WHERE resource_type='WASH' AND scenario_id IS NULL → 400/wk (80), 100/wk (85).
  2. Results: in ClickHouse —
SELECT site_id, rop, safety_stock, fill_rate, wait_time, leg_lead_time, direct_demand_rate
FROM gps_1.PIPE_meio_results
WHERE pipeline_id = 2 AND scenario_id = 3 AND item_id = 7
  AND archive_date = (SELECT max(archive_date) FROM gps_1.PIPE_meio_results WHERE pipeline_id = 2)
ORDER BY site_id;
  1. Recompute the pools by hand with the formulas in §6 and this page's appendix — every figure matches the engine's wire values exactly (verified against _load_sku_records + _allocate_repair_capacity output).