pog-mcp 0.9.6 → 0.9.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pog-mcp",
3
- "version": "0.9.6",
3
+ "version": "0.9.8",
4
4
  "type": "module",
5
5
  "description": "MCP server that lets an AI agent play Proof of Goal — wallet, sign-in, squad building, and matches as typed tools.",
6
6
  "license": "MIT",
@@ -2544,17 +2544,52 @@ that was an artefact of an unattainable +4 buff and is withdrawn.
2544
2544
  the short side drops by the same Δ. A real fatigued squad is uneven.
2545
2545
 
2546
2546
 
2547
- ## What growth-neutral load would a player accrue? (`engagement-load.mts` + `c2-team-load.ts`)
2548
-
2549
- **This section does NOT close C-2.** An earlier version said it did; that was wrong. `τ` was
2550
- never measured the probe's 24h default was simply used — and the neutral point was left
2551
- unchosen between its two branches. An F-1 implementer following that decision would have made
2552
- a probe default the production recovery rate. And `τ` cannot be measured from this data: F-1
2553
- does not exist, so production has no fatigue and there is no observed recovery curve to fit.
2554
- What measurement CAN do is price the choices, which is what the τ sweep does. A third product
2555
- choice sits beside τ and the neutral point: F-1 has not selected predicate C versus D. The
2556
- published values are conditional on C; switching to D moves τ=24h median/p95 `L` by
2557
- −5.3%/−10.4%. That measures the price of the choice, not which workload meaning the product wants.
2547
+ ## What growth-neutral load would a player accrue? measurement and product decision
2548
+
2549
+ The first #783/#784 measurement did **not** close C-2. `τ` was not measurable the probe's 24h
2550
+ default had merely been used — and the neutral point was left between two branches. Production
2551
+ had no fatigue curve to fit before F-1; measurement could price the choices but could not make the
2552
+ product choice. Predicate C versus D was also open at publication and F-1 subsequently persisted
2553
+ **D** on 2026-09-04. The C-conditioned tables and correction trail below remain historical evidence;
2554
+ they are not relabelled as D.
2555
+
2556
+ **Product decision, 2026-09-06 F-2 reference curve.** Re-integrating the same owner-only export
2557
+ and stored seed column under D, then independently validating only the selected 4× curve, chooses
2558
+ **`τ=24h`**, active-appearance neutral load **`L_neutral=8.076776`**,
2559
+ **`L₀=90.717176`** (4× D p95 `22.679294`), **`b=0.5399`**, and therefore
2560
+ **`a=b·L_neutral/(L_neutral+L₀)=0.044139`**. The versioned equation is
2561
+ `cond=5+a−bL/(L+L₀)`. This does not activate fatigue: F-2 first lands behind a default-OFF flag,
2562
+ and G-3 can flip only after the maximum legal role×condition interaction, 8–11-match cup depletion,
2563
+ the launch-amplitude prize/cost ordering, H ceiling, and I-c CAP clear against this same curve.
2564
+ The D product rerun is recorded below; the older C run remains the audit trail.
2565
+
2566
+ ### F-1 implementation status — predicate D is now durable
2567
+
2568
+ F-1 persists version `f1-d-growth-neutral-v1`: actor plus responder selections minus only the
2569
+ actor/responder selections produced by a zero-weight `weightedPick` fallback. Legitimate direct
2570
+ defender selections, fixed set-piece/post-play actors, and penalty keepers remain counted. This
2571
+ keeps the measured defensive participation while preventing the known all-zero ZP table from
2572
+ turning the first non-GK slot into a fatigue lever.
2573
+
2574
+ The engine instrumentation is opt-in and consumes no RNG. The existing growth-buffed simulation
2575
+ still decides the real result; one separate engine instance projects `total` back to the public
2576
+ attribute sum and emits only unsigned slot counters. Scheduled processing claims the complete due
2577
+ batch before either real or shadow simulation, freezes one external batch epoch into
2578
+ `MatchInputSnapshot v3.capturedAt`, and reuses it on retries. A first locked transaction commits the
2579
+ snapshot and durable per-player reservation; a second commits the real result, replay events,
2580
+ `match_workloads` root, 11/22 `player_workload_events`, and reservation release. Interactive ladder
2581
+ play holds the same player locks from snapshot through both simulations and the durable write.
2582
+
2583
+ Cup classification is structural (`tournament_id IS NOT NULL`) and credits both sides. Ladder
2584
+ credits home, plus away only when the shared `isAI || isSystemOwnedWallet` rule identifies a bot;
2585
+ human away produces no workload rows. Durable players retain `playerId`; daily cup fill-bots use a
2586
+ separate salt over cup date, team and slot. Listing, fixed purchase, auction settlement, custody
2587
+ activation/delivery finalization, and shared ownership transfer all participate in the same lock
2588
+ and reservation fence. Recovery discovers exactly
2589
+ `(tournament_id IS NOT NULL OR match_type='playoff') AND status='complete' AND completed_at > cursor`,
2590
+ never filters on kickoff, and records explicit legacy exemptions. Friendly, paid trial and sandbox
2591
+ write no workload and pin both route-local engine copies to `cond=5`. EWMA decay, neutral point and
2592
+ actual condition derivation remain F-2; F-1 alone changes no competitive input.
2558
2593
 
2559
2594
  ### Growth-leak gate: use a zero-growth shadow, not the real action trace
2560
2595
 
@@ -2578,7 +2613,7 @@ stored seed and `gameFlg`. F-1 consumes unsigned engagement counters only from t
2578
2613
  The real result still uses the growth-buffed input; the shadow cannot change its score, events,
2579
2614
  ratings or growth. It is therefore a **zero-growth counterfactual workload**, never the action
2580
2615
  record of the match that happened. Runtime cost is one extra pure simulation per competitive match;
2581
- F-1 still has to persist its counters atomically with completion. The workload timestamp must be
2616
+ F-1 persists its counters atomically with the computed result. The workload timestamp must be
2582
2617
  growth-invariant too: fix every due match's first-condition-snapshot (claim-start) time before ANY
2583
2618
  real or shadow engine in that scheduler batch runs, then use that match's one stored value for both.
2584
2619
  A sequential loop that timestamps match B only after simulating match A would carry A's
@@ -2604,8 +2639,8 @@ projection to the synthetic variations above and got byte-identical candidate-F-
2604
2639
  **1,201/1,201 matches and all 2,402 sides**. Unit tests pin erasure, preservation, non-mutation and
2605
2640
  idempotence; `match-growth.test.ts` pins that the real `applyMatchGrowth` producer projects exactly
2606
2641
  back to its innate team, and the existing squad-hash test independently pins that `total` is outside
2607
- the hash. This closes only the §3-5 prerequisite, not F-1/F-3/G-1/F-4's own implementation and
2608
- exposure contracts.
2642
+ the hash. That closed the §3-5 prerequisite; F-1 now uses it and G-1 is complete, while F-3 and F-4
2643
+ retain their own implementation and exposure contracts.
2609
2644
 
2610
2645
  **The gate is not a per-mode ceiling — it is defined on the exposure-weighted mix.**
2611
2646
  `band-worstcase.mts` holds the canonical statement (`01-engine-expansion.md:319-329` puts
@@ -2765,7 +2800,8 @@ counts; on expected rates it is 14%. Within-match noise had been read as between
2765
2800
  structure. The argument survives in a different form.
2766
2801
 
2767
2802
  The keeper still accrues almost nothing — it enters a contest only at the A0 one-on-one and
2768
- at penalties so no rule here makes one tired, and F-1 has to fill that blank deliberately.
2803
+ at penalties. F-1 deliberately accepted that limitation when it selected D rather than adding a
2804
+ separate goalkeeper source; whether it yields usable rotation belongs to F-2.
2769
2805
 
2770
2806
  Predicate D now subtracts fallbacks on BOTH sides of the contest: zone press picks its ACTOR
2771
2807
  through the fallback too, and an earlier version recorded only the responder's, so "C without
@@ -3007,8 +3043,9 @@ conversion.
3007
3043
 
3008
3044
  ### τ cannot be measured — only priced
3009
3045
 
3010
- `τ` is the recovery rate §6 C-2 asks for. F-1 does not exist, so production has no fatigue
3011
- and there is no observed curve to fit: `τ` is a DESIGN choice, not a measurement. What
3046
+ `τ` is the recovery rate §6 C-2 asks for. This measurement window predates F-1 and fatigue,
3047
+ so there is no observed curve to fit. The later F-1 ledger still does not derive condition;
3048
+ `τ` remains a DESIGN choice, not a measurement. What
3012
3049
  measurement can do is re-run everything at each candidate and report what follows. Each row
3013
3050
  below re-integrates the timeline, re-runs that τ's full cell set, and re-searches for the safe
3014
3051
  amplitude (one run, one snapshot).
@@ -3126,7 +3163,7 @@ it leaves open — does an opponent outside the basket exceed? — is asked sepa
3126
3163
  only **62 distinct XIs**. The old pool held 95 objects, of which only **47** were distinct
3127
3164
  lineups — 48 were duplicates. And **35 of the 95 teams fielded more than one XI** inside the
3128
3165
  window, every later one discarded. The new pool CONTAINS the old one and adds 15 lineups.
3129
- (Snapshot `cond` is 5 for everyone in this window — F-1 does not exist yet — so "fielded XI"
3166
+ (Snapshot `cond` is 5 for everyone in this historical window — it predates F-1 — so "fielded XI"
3130
3167
  is squad identity here, not condition.)
3131
3168
 
3132
3169
  **Taking only the top three was arbitrary — all 13 teams that played are measured.** Two
@@ -3387,14 +3424,64 @@ rule-of-three bound was bolted on for it. Under empirical Bernstein the range te
3387
3424
  `3R ln(3/δ)/n` survives at SD = 0, so the interval never collapses in the first place: no
3388
3425
  guard, no special case, and one fewer argument resting on its own iid assumption.
3389
3426
 
3427
+ ### Post-F-1 product rerun — certify only the selected D · 4× curve
3428
+
3429
+ Results 6 through the safe-amplitude section above preserve the historical predicate-C run and
3430
+ its joint 1×/2×/4× candidate family. The product values were not obtained by scaling that table.
3431
+ All four τ values were re-integrated and tested from scratch with
3432
+ **`LOAD_PRED=D L0_SWEEP=4`**, using the same stored seed column and the same owner-only export,
3433
+ SHA-256 `1c7335ba9fa11388363de57628207ecc4820dc9bb02285066bda849adf571b6f`.
3434
+ Letting discarded 1×/2× curves choose the worst cell or enlarge the family would charge the
3435
+ shipped curve for hypotheses the product does not ship. The 4× choice was fixed from input-load
3436
+ geometry, not outcome seeds, before the result bounds; its family is
3437
+ `(26+26+26+24)×6 opponents = 612`.
3438
+
3439
+ | τ(h) | D `L` median | D `L` p95 | 0.2-derived `b` (4×) | one match (pp)\* | cells over | **product-curve safe `b`** | worst upper at low end |
3440
+ | --- | --- | --- | --- | --- | --- | --- | --- |
3441
+ | 6 | 2.51 | 10.52 | 3.548 | 0.2948 | **14/16** | 0.4296–0.4331 | 3.74pp |
3442
+ | 12 | 4.07 | 14.29 | 3.009 | 0.1876 | **7/16** | 0.4672–0.4701 | 3.44pp |
3443
+ | **24** | **8.08** | **22.68** | **2.446** | **0.0980** | **0/18** | **0.5399–0.5423** | **3.69pp** |
3444
+ | 48 | 16.69 | 40.03 | 2.119 | 0.0488 | **0/17** | 0.5546–0.5567 | 3.70pp |
3445
+
3446
+ \* “One match” is the secant conversion at each row's `b` derived from E's 0.2 median spread,
3447
+ kept only for comparison. It is not the one-match cost at the selected safe `b`. The safe range
3448
+ is not a confidence interval either: its left endpoint is the largest grid point independently
3449
+ established below for every actual cell, while the right endpoint is the smallest grid point not
3450
+ established below. No row established a lower bound above 5pp, so none gets an upper threshold.
3451
+
3452
+ The product choices are:
3453
+
3454
+ - **`τ=24h`.** The 6h and 12h 0.2-derived curves put 14 and 7 cells over; 24h is the first with
3455
+ zero. 48h is also zero but halves the one-match secant again, 0.0980→0.0488pp. This is a product
3456
+ compromise between daily rotation and fairness, not a recovery estimate fitted to observations.
3457
+ - **`L₀=90.717176`.** This is 4× the D/τ24 pre-appearance p95 `22.679294`, and 2.12× the observed
3458
+ maximum `42.87`. At that maximum the marginal slope retained relative to zero load is
3459
+ 12.0%/26.4%/46.1% for 1×/2×/4×. Only 4× meaningfully follows §3-1's prescription to keep the
3460
+ curvature scale above the realistic range so marginal cost does not die early.
3461
+ - **Neutral `L=8.076776`, `b=0.5399`, `a=0.044139`.** The median active appearance maps to
3462
+ condition 5. Zero load maps to 5.044, D p95 to 4.936, this window's observed maximum to 4.871,
3463
+ and the asymptote to 4.504. At `b=0.5399`, the independent worst upper bound is 3.69pp across
3464
+ all 18 actual cells.
3465
+ - **Prize versus cost remains unresolved.** At the safe amplitude's maximum recoverable deficit
3466
+ 0.173, the prize is 0.19pp [−0.07, 0.45], the selected cheapest one-point replacement costs
3467
+ 0.16pp, and paired cost−prize is −0.03pp [−0.50, 0.43]. Together with the unmeasured legal
3468
+ role×condition and cup extremes, that keeps F-2 default OFF until the follow-up gates and G-3.
3469
+
3470
+ The canonical constants are therefore `τ=24h` and
3471
+ `cond = 5 + 0.044139 − 0.5399·L/(L + 90.717176)`. Implementation derives `a` from the other
3472
+ three constants so documentation rounding cannot move the exact neutral point.
3473
+
3390
3474
  ### Stage 3 — a multi-wallet feeder is exempt, not merely advantaged
3391
3475
 
3392
3476
  F-1's side rule writes nothing for a ladder away side that is human; `playoff-finalize.ts`
3393
3477
  calls `applyResult` for both; `selectOpponentByStrength` draws from the five strength-nearest
3394
3478
  in-division; the cooldown is initiator-only. Observed at-appearance `L` reaches 55 for an
3395
3479
  honest player while a team taking the same match count as the away side accumulates zero. That
3396
- is exemption, not a ratio — bounded only by what bounds the feature, since the prize is 0.59pp at g=0.4 (0.16pp at the τ=24h safe amplitude)
3397
- and the team-level gap is 3.43pp at the safe amplitude, under the gate.
3480
+ is exemption, not a ratio — bounded only by what bounds the feature. The historical `g=0.4`
3481
+ single-player prize is 0.59pp [0.25, 0.93]; at the selected D product amplitude the maximum
3482
+ recoverable deficit gives 0.19pp [−0.07, 0.45], and the independently certified team-level worst
3483
+ upper bound is 3.69pp across the 18 observed cells. The unmeasured legal role×condition extreme
3484
+ is why that bound is not yet an activation verdict.
3398
3485
 
3399
3486
  ### What this does not settle
3400
3487
 
@@ -3428,10 +3515,10 @@ states while `allCells` did not. A deficit of exactly zero is not evidence of cl
3428
3515
  gate either, so such teams are excluded outright and the output says how many. None occur in
3429
3516
  this window.
3430
3517
 
3431
- The prize-versus-cost ordering AT THE AMPLITUDE THAT WOULD SHIP it splits at `g=0.4`
3432
- (−0.43pp [−0.76, 0.10]) but not at the safe amplitude's own deficit (0.133; prize 0.16pp
3433
- [−0.09, 0.40], cheapest cost 0.16pp, paired difference 0.00pp [−0.47, 0.47]), and that second
3434
- one is the decision. The neutral-point fork. Maximum LEGAL role concentration (the
3518
+ The prize-versus-cost ordering at the D product amplitude remains unresolved: at its maximum
3519
+ recoverable deficit 0.173, prize is 0.19pp [−0.07, 0.45], cheapest selected cost is 0.16pp, and
3520
+ paired cost−prize is −0.03pp [−0.50, 0.43]. The neutral-point fork is now closed at the D active-appearance median;
3521
+ what remains is maximum LEGAL role concentration (the
3435
3522
  replay is what happened, not what the rules permit). Player identity is the snapshot's `actorIds` playerId, keyed GLOBALLY rather than per team —
3436
3523
  a minted player sold mid-window would otherwise get two chains starting from zero, understating
3437
3524
  the buyer's vector. A missing actor map or even one player that fails to join is rejected by the
@@ -3455,9 +3542,15 @@ itself. The cost is that nothing with a period longer than 11 days is visible.
3455
3542
  C2_ENV_FILE=<main checkout>/.env.deploy DAYS=30 WINDOW_END=2026-09-01 \
3456
3543
  EXPORT_SNAPSHOTS=/tmp/prod-tl.json \
3457
3544
  pnpm --filter @sws26/api exec tsx scripts/c2-team-load.ts
3545
+ # Post-F-1 product curve: predicate D, testing only the selected L₀=4×p95
3546
+ MATCHES=3000 SNAPSHOTS=/tmp/prod-tl.json REPLAYS=5 TAU_SWEEP=6,12,24,48 \
3547
+ LOAD_PRED=D L0_SWEEP=4 LAMBDA_MED=6 LAMBDA_MAX=21 \
3548
+ pnpm --filter pog-mcp exec tsx skill/reference/probes/engagement-load.mts
3549
+
3550
+ # Historical C-conditioned 1×/2×/4× table only
3458
3551
  MATCHES=3000 SNAPSHOTS=/tmp/prod-tl.json REPLAYS=5 TAU_SWEEP=6,12,24,48 \
3459
- LAMBDA_MED=6 LAMBDA_MAX=21 \
3460
- npx tsx packages/mcp/skill/reference/probes/engagement-load.mts
3552
+ LOAD_PRED=C L0_SWEEP=1,2,4 LAMBDA_MED=6 LAMBDA_MAX=21 \
3553
+ pnpm --filter pog-mcp exec tsx skill/reference/probes/engagement-load.mts
3461
3554
  ```
3462
3555
 
3463
3556
  **The window's end is now stated explicitly, so these figures can be rebuilt.** The default is
@@ -3536,9 +3629,12 @@ from an artificially low `L` and `Lmed`, the gate vectors and the safe amplitude
3536
3629
  understated. Engine changes are input-dependent, so interspersed failures are a normal
3537
3630
  possibility rather than a clean release boundary.
3538
3631
 
3539
- `LOAD_PRED` selects the integration predicate (default `C`). C is published, and the probe also
3540
- integrates at D at every τ and prints the difference — F-1 has not chosen, so the calibration
3541
- has to carry which predicate it is conditional on.
3632
+ `LOAD_PRED` selects the integration predicate (default `D`). D is the F-1 product predicate, and
3633
+ the probe also integrates the opposite predicate C at every τ and prints the difference. Set
3634
+ `LOAD_PRED=C` explicitly to reproduce the historical C-conditioned figures: calibration must
3635
+ always carry the predicate it used. `L0_SWEEP` selects the p95 multiples under test. Its default
3636
+ `1,2,4` preserves the historical comparison; the product amplitude is certified separately with
3637
+ `L0_SWEEP=4`, so an unselected curve neither enlarges the family nor chooses the worst cell.
3542
3638
 
3543
3639
  Without `TAU_SWEEP` only `TAU_H` runs. **Calling a single-τ run a "decision" makes a probe
3544
3640
  default the production recovery rate** — that is why the sweep exists.