pog-mcp 0.9.17 → 0.9.18

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.17",
3
+ "version": "0.9.18",
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",
@@ -4959,3 +4959,267 @@ few points, as any change to who presses must.
4959
4959
  original expression cannot be recovered.
4960
4960
 
4961
4961
  5,648,400 matches in about a minute. Whole run: `zp-selector.mts`.
4962
+
4963
+ ## Do the six pog axis candidates move the outcome, and are any of them a decision? (`pog-axes.mts`)
4964
+
4965
+ Six candidates for the pog playbook (issue #809, gate G0): `balance`, `line`,
4966
+ `press`, `build`, `keeper`, `set_piece`. Every one ships as a **selection**
4967
+ preference — abilities stay frozen from creation (F-6) and a playbook only
4968
+ chooses who starts, at which position, and who takes kicks. This probe
4969
+ measures by sweeping 212-point TEMPLATES: the question is whether the engine
4970
+ is sensitive to the profile difference at all; selection realizes it
4971
+ discretely, checked separately in a 17-player-pool companion measurement.
4972
+
4973
+ Five of the six realizations change `squad-lib.mts`'s `build()` inputs;
4974
+ `set_piece` instead reassigns the already-built team's `fkKicker`/`pkKicker`
4975
+ flags directly (`build()` itself hardcodes those flags onto slots 9/10, so
4976
+ this is still a 212-template property, just set via a different code path).
4977
+ `D_*_APPR` (issue #745) is the one axis that patches the engine, via the
4978
+ `appr-role.mts`/#728 exact-match-count-asserted source-replace pattern.
4979
+
4980
+ Eight Codex review rounds (41 findings total, 1 deferred to a follow-up
4981
+ issue rather than fixed inline — see "What Codex found") progressively
4982
+ hardened the isolation guarantees. Highlights load-bearing for the tables
4983
+ below: `balance`/`press` pin the goalkeeper BYTE-IDENTICAL to the base
4984
+ squad, including for `mid`. `line` (round 8) instead clones all 11 existing
4985
+ players byte-for-byte and relabels only the `position` field to the new
4986
+ formation's slot — no attribute rebuild at all, so no GK-pinning pipeline
4987
+ is even needed for this axis. `D_*_APPR`'s focus policies override the
4988
+ argmax player's selection weight to 1,000,000 (not 1024 — see "What Codex
4989
+ found"). `set_piece` ranks FK/PK candidates independently by the actual
4990
+ engine formula: `getPoint`/`takePkShot` show both use `atkSkill + cond/2 +
4991
+ total/3 + roll`, and FK's single `fkKicker` flag triggers a 50/50 mix of a
4992
+ shoot-based and a pass-based branch, so the expected-value-optimal ranking
4993
+ for BOTH roles is `(pass+shoot)/2 + total/3` — with a tie-break that keeps
4994
+ the two roles on different players. This still omits `ofTeamContrib`, a
4995
+ team-aggregate term `getPoint` also adds — round 8's Finding 1, deferred
4996
+ (see "What Codex found").
4997
+
4998
+ ### Method
4999
+
5000
+ Four cores (`flat`, `shaped`, `gkheavy`, `gkmin`). Each axis is a `low`/`mid`/
5001
+ `high` ladder; `low`/`high` change exactly one dimension of `build()`'s
5002
+ inputs (see `docs/pog/02-axes-measurement.md` §2). Opponent grid = the same
5003
+ four cores, both modes, `N=20,000` per cell, seeds keyed on
5004
+ `(axis, myCoreKey, oppCoreKey, mode)`. Bonferroni family size (m=706)
5005
+ computed analytically before any comparison runs. Non-monotone requires BOTH
5006
+ ladder legs to individually clear the bar with opposite signs, on the
5007
+ self-play cell. Opponent-conditional requires a candidate to beat both
5008
+ others at the same bar, for each opponent.
5009
+
5010
+ Adoption is judged on "significant against any of the 4 opponents", which
5011
+ does not always match the displayed self-play row alone — both counts are
5012
+ now reported side by side for reconciliation (see Result below).
5013
+
5014
+ Controls: patch-identity; mirror cells; a `D_*_APPR` policy mirror; a live
5015
+ assertion that no knockout match returns a null winner; every 17-player
5016
+ pool's full 2^17=131,072 possible 11-subsets checked and validated; and the
5017
+ reported grand total checked against a value computed analytically from the
5018
+ loop structure.
5019
+
5020
+ ### Result
5021
+
5022
+ | axis | adopted | sig (self-play only) | sig (any of 4 opp) | max \|Δ\| pp | non-monotone | opponent-conditional |
5023
+ | --- | --- | --- | --- | --- | --- | --- |
5024
+ | `balance` | yes | 7/8 | 8/8 | 33.89 | **0/8** | **0/8** |
5025
+ | `line` | yes | 8/8 | 8/8 | 22.87 | 1/8 | 3/8 |
5026
+ | `press` | yes | 7/8 | 8/8 | 39.88 | 2/8 | **7/8** |
5027
+ | `build` | yes | 7/8 | 8/8 | 12.52 | 1/8 | 0/8 |
5028
+ | `keeper` | yes | 8/8 | 8/8 | 19.02 | **0/8** | **0/8** |
5029
+ | `set_piece` | yes | 8/8 | 8/8 | 11.38 | 4/8 | 0/8 |
5030
+
5031
+ All six adopted (judged on the any-opponent column, matching the code's
5032
+ adoption rule); `line`/`press`/`build`/`set_piece` non-monotone,
5033
+ `balance`/`keeper` cleanly monotone. G0 passes (4 of 6 non-monotone, above
5034
+ the 2-required bar). `press` remains the strongest trade-off: 7 of 8
5035
+ core×mode cells have a supported leader that flips across the 4-opponent
5036
+ grid. `set_piece`'s `flat` core is no longer an exact 0.00pp tie (as in
5037
+ round 4) — it now shows a small but genuinely significant effect
5038
+ (+0.29/+0.33pp) once the ranking criterion includes `total/3`, which makes
5039
+ `slotTotals()`'s rounding-driven total differences the real tiebreaker
5040
+ instead of array order. Round 6 additionally found FK's ranking was missing
5041
+ half its own mechanic (see "What Codex found").
5042
+
5043
+ `D_*_APPR` (#745's three questions): `focus-total` is now restricted to
5044
+ FORWARDS specifically (round 7 — searching all outfielders let a DF win the
5045
+ argmax whenever rounding gave one the squad's top total, e.g. `gkheavy`'s
5046
+ 19-point DF against 18-point forwards, silently testing "focus on whoever
5047
+ has the most points" rather than #745's actual forward-specific claim). The
5048
+ picture sharpened considerably: only `shaped` (STARS weighting, clearly
5049
+ uneven totals with forwards on top) benefits from `focus-total`
5050
+ (+16.65/+19.80pp); the other three cores, where totals are flatter or a
5051
+ forward isn't the max, take a LARGE loss from forcing defensive duty onto a
5052
+ forward (−30 to −46pp) — a much more precise reproduction of #745's own
5053
+ conditional claim ("only works when totals are uneven") than the
5054
+ all-position version showed. The reversal boundary is confirmed in both
5055
+ modes at outfield total-spread 17 (`focus-total` wins, z=36.61 REG / 30.03
5056
+ KO); at every lower spread tested (1, 6, 11) `focus-defense` wins
5057
+ confirmed, now by far larger margins (up to −47.6pp) since the two policies
5058
+ target genuinely different players. Opponent-conditional: 0/8.
5059
+
5060
+ **17-pool realizability (exploratory, not gating)**: same construction as
5061
+ before (three pools of 17, all 2^17 subsets checked). Two limitations now
5062
+ documented, pulling in OPPOSITE directions: (1, round 5) the pool assumes
5063
+ each of the 17 individuals' POSITION and kicker flags are fixed at their
5064
+ build-time template, but `AGENTS.md` states F-6 freezes ABILITY VALUES
5065
+ only, not "pool membership, mutable unminted positions/names, or FK/PK
5066
+ choices" — the real product may allow repositioning or kicker reassignment
5067
+ this check cannot see, understating realizability; (2, round 7) an
5068
+ alternate's total is copied from the slot it replaces, which squad-lib's
5069
+ own `slotTotals()` clamps to [10,29] — wider than the production FA
5070
+ generator's actual reachable range of 16-28 (`AGENTS.md` §3-16). `pool-shaped`/
5071
+ `pool-gkheavy` do produce alternates outside that window (as low as 12, as
5072
+ high as 29 — a keeper on `pool-gkheavy`), i.e. synthetic reserves the real
5073
+ generator could never mint, which OVERSTATES realizability for any verdict
5074
+ depending on one. This exploratory check does not net the two limitations
5075
+ against each other — the true direction is unresolved. Full table and
5076
+ caveats: `docs/pog/02-axes-measurement.md` §6.
5077
+
5078
+ ### What Codex found, and what changed (eight review rounds, 41 findings)
5079
+
5080
+ Rounds 1–4 are summarized in `docs/pog/02-axes-measurement.md` §7 (GK
5081
+ weight-share leaks across three different axes and two different root
5082
+ causes, cross-slot scarcity-repair leaks, unvalidated/undersized/
5083
+ misnamed pool XIs, unsupported opponent-conditional argmax, combined then
5084
+ still-colliding FK/PK selection, proportional instead of concentrated
5085
+ `D_*_APPR` policies, `mid` built through a different algorithm than
5086
+ `low`/`high`, several doc-accuracy corrections).
5087
+
5088
+ **Round 5 (2 P1, 2 P2)** — new defects inside rounds 1–4's fixes:
5089
+
5090
+ - `D_*_APPR`'s focus-weight override of 1024 (round 3's fix) wasn't large
5091
+ enough: in the highest-competition scenes (A0/A1, where up to 4 DF plus
5092
+ the GK each carry ~100 stock weight, summing to ~500), 1024 only bought
5093
+ the focal player 62-72% of the draw rather than near-total concentration
5094
+ (measured on `shaped`/A0). `appr-role.mts`'s 1024 was calibrated for the
5095
+ offence table's much smaller competing sums, not this one. Raised to
5096
+ 1,000,000 — a three-orders-of-magnitude safety margin that guarantees
5097
+ >99.9% share regardless of competing weight.
5098
+ - `set_piece`'s FK/PK ranking (round 4's independent-selection fix) still
5099
+ ranked by the bare `shoot` / `(pass+shoot)/2` stat alone, omitting the
5100
+ `total/3` term `getPoint` and `takePkShot` actually add to the kicker's
5101
+ point. On `flat` (every outfielder has identical `shoot`), ties were
5102
+ broken by JS's stable-sort array order — which happened to correlate with
5103
+ `slotTotals()`'s rounding drift (a couple of slots get one extra total
5104
+ point) — landing the "worst" AND "best" ranking on the same higher-total
5105
+ DF/DMF slot while `mid` uses the FW slots, manufacturing a discontinuity
5106
+ unrelated to kicker quality. Including `total/3` makes ties genuine
5107
+ engine-level ties rather than rounding artifacts wearing a tie's mask.
5108
+ - Two P2s: the 17-pool check doesn't model that unminted players' positions
5109
+ and kicker flags are mutable in the real product (`AGENTS.md`) — documented
5110
+ as a lower-bound limitation rather than modeled (modeling it properly needs
5111
+ a lineup solver, P1-2's job); and the "significant" cell counts didn't
5112
+ match the displayed self-play rows (adoption is judged on "any of 4
5113
+ opponents", which a reader can't verify from the self-play table alone) —
5114
+ now both counts are reported side by side.
5115
+
5116
+ **Round 6 (1 P1)** — a new defect inside round 5's own fix:
5117
+
5118
+ - `set_piece`'s FK ranking (round 5's `total/3` fix) still measured only
5119
+ HALF of the `fkKicker` mechanic. `doFk` sends every free kick through one
5120
+ 50/50 coin flip between `doFkDirect` (`getPoint(..., 'shoot', SCENE.FK1)`)
5121
+ and `doFkCross` (`getPoint(..., 'pass', SCENE.FK2)`) — the same single
5122
+ flag governs both branches. Ranking by `shoot + total/3` alone matched
5123
+ only the direct-kick half in isolation (presumably what
5124
+ `docs/tactics/00-plan.md`'s narrower "FK=shoot" finding itself measured),
5125
+ not the blended mechanic the flag actually controls. Reading `getPoint`
5126
+ directly confirmed both branches use the identical
5127
+ `atkSkill + cond/2 + total/3 + roll` shape with only `atkSkill` swapped
5128
+ between `shoot` and `pass`, so the expected-value-optimal FK ranking is
5129
+ `(shoot+pass)/2 + total/3` — the same formula PK already uses. The two
5130
+ roles now genuinely converge on the same "best all-round kicker" ranking,
5131
+ which is the correct consequence of the engine's real mechanics, not a
5132
+ bug — it just means round 4's "PK falls to the next-best candidate when
5133
+ it ties with FK's pick" tie-break now fires on nearly every ladder cell
5134
+ instead of occasionally.
5135
+
5136
+ **Round 7 (1 P1, 4 P2)** — new defects inside earlier rounds' fixes:
5137
+
5138
+ - `D_*_APPR`'s `focus-total` searched the argmax total across ALL outfield
5139
+ positions, not specifically forwards — #745's own claim names "your
5140
+ biggest FORWARD" explicitly. On `gkheavy` (19-point DF vs 18-point
5141
+ forwards) and the B3 boundary's alpha=0 squad, rounding made a DF the
5142
+ squad-wide max, so `focus-total` was silently testing "focus on whoever
5143
+ has the most points" rather than #745's forward-specific policy.
5144
+ Restricting the search to `position === 'FW'` sharpened the picture
5145
+ considerably (see Result above): only `shaped` (clearly uneven totals,
5146
+ forwards on top) benefits, and the other three cores take a large loss
5147
+ (−30 to −46pp) from forcing defensive duty onto a forward — a much more
5148
+ precise reproduction of #745's conditional claim than the all-position
5149
+ version showed.
5150
+ - Four P2s: both documents still described FK's ranking as `shoot + total/3`
5151
+ even after round 6 corrected the code to `(pass+shoot)/2 + total/3` —
5152
+ fixed to match the committed treatment; the probe's own header comment
5153
+ claimed all six axes are template-input changes via `build()`, when
5154
+ `set_piece` actually reassigns already-built kicker flags directly — now
5155
+ distinguished; the header also still claimed `mid` is "always the bare
5156
+ core", which stopped being true for `balance`/`press`/`line` once round 4
5157
+ rebuilt `mid` through the same pinned pipeline as `low`/`high` (the exact
5158
+ difference round 4 used to find `balance`'s spurious reversal) — corrected
5159
+ to state the real per-axis contract; and the 17-pool's bench alternates can
5160
+ carry totals outside the production FA generator's actual reachable range
5161
+ of 16-28 (`AGENTS.md` §3-16) — as low as 12, as high as 29 for a keeper —
5162
+ documented as a SECOND limitation pulling in the OPPOSITE direction from
5163
+ round 5's position/kicker-flexibility one (this one makes some "가능"/
5164
+ "부분" verdicts optimistic rather than conservative; the two are not
5165
+ netted against each other).
5166
+
5167
+ **Round 8 (2 P1)** — new defects inside earlier rounds' fixes:
5168
+
5169
+ - **[Fixed]** `line`'s realization conflated formation change with attribute
5170
+ reallocation. `AGENTS.md` states F-6 freezes ABILITY VALUES only —
5171
+ unminted players' position labels and FK/PK assignments stay mutable — but
5172
+ the pre-round-8 `line` implementation rebuilt the outfield through
5173
+ `buildGkPinnedVariant` using the new formation's mix ratios, so a position
5174
+ change also dragged along an attribute redistribution the real product
5175
+ doesn't require. Rewritten to clone all 11 existing players (GK included)
5176
+ byte-for-byte and relabel only `position` to the new formation's slot —
5177
+ `buildGkPinnedVariant` is no longer needed for this axis at all, since no
5178
+ attribute is touched. The now-dead `avgOutfieldWeightByPosition()` helper
5179
+ was deleted. Re-measured: `flat` (EVEN weighting, where the old and new
5180
+ approaches coincide by construction) is byte-identical; the other three
5181
+ cores show smaller, more isolated formation-only effects (e.g. `shaped`
5182
+ −8.43→−5.00pp) — the axis's own max \|Δ\| drops from 32.20pp to 22.87pp.
5183
+ Non-monotone/opponent-conditional classification is unchanged (1/8, 3/8) —
5184
+ only the magnitude was wrong, not the qualitative call.
5185
+ - **[Deferred to a follow-up issue]** `set_piece`'s FK/PK ranking
5186
+ (`(shoot+pass)/2 + total/3`, fixed in rounds 5–6) omits `ofTeamContrib`,
5187
+ the team-aggregate term `getPoint`'s full formula also adds:
5188
+ `ofPoint = ofPlayerP + ofTeamContrib`, where `ofTeamContrib =
5189
+ (atkCondSum*atkRate*0.075 + atkAttrSum*atkRate*0.1) * (teamPow/100)`.
5190
+ Codex supplied a concrete counterexample on the `flat` core where including
5191
+ this term could flip the top-ranked candidate. Closing this gap requires
5192
+ extracting the engine's `O_*_RATE` tables and `teamPow` computation — new
5193
+ engine-internals research outside this issue's (#809) measurement scope.
5194
+ Per the coordinator's round-7 scope-management guidance, this was left as a
5195
+ documented "KNOWN LIMITATION" code comment rather than extending the review
5196
+ loop further, and tracked in a separate GitHub issue (linked from PR #840)
5197
+ instead. It does not affect `set_piece`'s own adopted/non-monotone verdict —
5198
+ the current ranking already captures the dominant term of the real
5199
+ mechanism; only a secondary correction term is missing.
5200
+
5201
+ ### What it means
5202
+
5203
+ - **G0 passes.** 6/6 adopted, 4/6 non-monotone. `docs/pog/02-axes-measurement.md`
5204
+ has the full write-up and all eight review rounds' changelogs.
5205
+ - **The realizability column's direction is explicitly unresolved, not
5206
+ presented as a clean lower bound** — round 7 found a second limitation
5207
+ (out-of-range synthetic reserves) pulling the opposite way from round 5's
5208
+ (position/kicker flexibility), and this exploratory check does not net
5209
+ them. Important for W1's planning: some "불가능" verdicts could turn
5210
+ "가능" once P1-2 builds a real fixture, but some "가능" verdicts here
5211
+ could also turn out to be unreachable.
5212
+ - **Every finding across all eight rounds lived inside a FIX, not the
5213
+ original measurement design** — the generalizable lesson: a control that
5214
+ checks the harness is unbiased (mirror, patch-identity) says nothing about
5215
+ whether a specific numeric choice (a weight constant, a ranking formula, an
5216
+ allocator) actually matches the real mechanism it's meant to approximate.
5217
+ Each of those needed independent verification against the actual engine
5218
+ formula or actual competing magnitudes, not just "does the effect look
5219
+ directionally right."
5220
+
5221
+ 14,066,000 matches in 182.5s (N=20,000, round-8 re-run — the loop structure
5222
+ is unchanged so the match count is identical, only wall-clock varies between
5223
+ runs; self-checked against the loop structure). The default `N=6,000`
5224
+ reaches the same G0 PASS verdict in about a third of the time. Whole run:
5225
+ `pog-axes.mts`.