pog-mcp 0.8.1 → 0.8.2
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 +1 -1
- package/skill/SKILL.md +104 -18
- package/skill/reference/measurements.md +382 -41
package/package.json
CHANGED
package/skill/SKILL.md
CHANGED
|
@@ -332,25 +332,101 @@ player is the worst thing you can build — it lost to every differentiated squa
|
|
|
332
332
|
tested, most by 3:1. Defenders want defense, forwards want shoot. This is the
|
|
333
333
|
single largest effect measured, and it is what a naive even split gets wrong.
|
|
334
334
|
|
|
335
|
-
**
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
335
|
+
**The goalkeeper slot reads exactly one attribute when defending.** Every save
|
|
336
|
+
a keeper ever makes scores `defense + cond/2 + total/3`, at three sites: the 1v1
|
|
337
|
+
chance, an in-match penalty (a regulation-time event too — roughly an eighth of
|
|
338
|
+
all goals are penalties), and a shootout kick. Its pass, dribble and shoot are
|
|
339
|
+
read by no *defensive* code path.
|
|
340
|
+
They are read in exactly two offensive cases: if you nominate the keeper as a
|
|
341
|
+
kick taker (measured worst of every option — do not), and in a long shootout,
|
|
342
|
+
where the kicking order covers all eleven players and can eventually reach the
|
|
343
|
+
keeper, scoring `(pass + shoot) / 2 + cond / 2 + total / 3` — the same
|
|
344
|
+
`takePkShot` roll as any taker. Neither changes the advice: whatever total
|
|
345
|
+
your keeper ends up with, put it in defense.
|
|
346
|
+
|
|
347
|
+
**How much total to give it is NOT settled, and you should distrust anyone who
|
|
348
|
+
tells you it is** — including earlier versions of this file. Four separate
|
|
349
|
+
measurements over one day gave four different answers, each overturned by
|
|
350
|
+
controlling something the previous one had left free. What survived:
|
|
351
|
+
|
|
352
|
+
- A smaller keeper total is better in league matches (draws allowed). This held
|
|
353
|
+
under every construction tried.
|
|
354
|
+
- In knockout matches the best total **depends on shootout exposure — how
|
|
355
|
+
often YOUR matches end level, which both sides' attacks set together.** The
|
|
356
|
+
keeper's `total/3` is in every save it makes — regulation 1v1s included — but
|
|
357
|
+
a shootout multiplies how many keeper rolls a match contains. Measured across
|
|
358
|
+
three same-profile pairings (shootout reach ~13% to ~75%): at the
|
|
359
|
+
starved-attack extreme the ranking REVERSES and a total-29 keeper beats a
|
|
360
|
+
total-13 one outright; in ordinary pairings the small total stays best. Your
|
|
361
|
+
own attack is the half of that exposure you control.
|
|
362
|
+
|
|
363
|
+
So treat the keeper total as a squad-level question, not a lookup.
|
|
364
|
+
|
|
365
|
+
**There is a second budget, and this file's own advice competes for it.** Beyond
|
|
366
|
+
the 212 points, the whole TEAM may hold at most three attributes of value 10 and
|
|
367
|
+
five of value 8–9 (`validator.ts`). "Forwards want shoot", "give the kicks to
|
|
368
|
+
your best shooter", and a maximal keeper defense cannot all be satisfied — three
|
|
369
|
+
forwards at 10 plus a keeper at 10 is four, and the validator rejects it. Decide
|
|
370
|
+
where the scarce values go on purpose.
|
|
371
|
+
|
|
372
|
+
Measured head to head, 20,000 matches each, squads identical except for where a
|
|
373
|
+
single 10 sits:
|
|
374
|
+
|
|
375
|
+
| A single 10 given to… | League | Knockout |
|
|
376
|
+
| --- | --- | --- |
|
|
377
|
+
| the set-piece taker's `shoot` | **1st** | 2nd |
|
|
378
|
+
| an ordinary forward's `shoot` | 2nd | 3rd |
|
|
379
|
+
| the keeper's `defense` | 3rd | **1st** |
|
|
380
|
+
|
|
381
|
+
The keeper and the ordinary forward swap ends. The set-piece taker is first or
|
|
382
|
+
second in both — the only allocation measured that was never wrong. (This too was
|
|
383
|
+
measured on one outfield template; read it as a strong hint, not a law.)
|
|
384
|
+
|
|
385
|
+
**One thing about kickers that is easy to get wrong.** Your `isFkKicker` and
|
|
386
|
+
`isPkKicker` choices decide who takes free kicks and in-match penalties —
|
|
387
|
+
together roughly a third to a half of all goals, with the exact share depending
|
|
388
|
+
on squad construction. **They do not apply to a shootout.** That order is computed
|
|
389
|
+
from `shoot + pass` across the whole squad, so a shootout is decided by your best
|
|
390
|
+
shooters whether you nominated them or not.
|
|
391
|
+
|
|
392
|
+
Budget in ranges, not in single points: a one-point change is below what even
|
|
393
|
+
thousands of matches can distinguish.
|
|
341
394
|
|
|
342
395
|
**Spreading beats star-building.** Concentrating points into a few 26–29 players
|
|
343
396
|
and starving the rest conceded roughly three times as many goals as an even
|
|
344
397
|
outfield spread, and lost overall despite scoring more.
|
|
345
398
|
|
|
346
|
-
**Solidity beats aggression
|
|
347
|
-
|
|
399
|
+
**Solidity beats aggression — in matches that can end level.** With identical
|
|
400
|
+
formations and budgets, the defense-leaning 4-3-3 beat the attack-leaning one
|
|
401
|
+
56.5% of the time in league play, and in knockout rounds the same pairing
|
|
402
|
+
flips: the attack-leaning side wins 53.6%. Both directions are significant at
|
|
403
|
+
4,000 matches. A 0-0 is worth a point in the league — and in a cup GROUP
|
|
404
|
+
match too, which is regulation-only and can end level just like a league
|
|
405
|
+
round. Only in a cup KNOCKOUT round does a 0-0 proceed to a tiebreaker, and
|
|
406
|
+
that tiebreaker is anything but a coin flip — the shootout is decided by your
|
|
407
|
+
best shooters' `shoot + pass` against the keeper's `defense`/total (see the
|
|
408
|
+
keeper section above), so the draw-heavy defensive shape hands the decision to
|
|
409
|
+
exactly the attributes it skimped on. Scoring is low — well under one goal per team per match, and about half of
|
|
348
410
|
all matches end level — so conceding one fewer is worth more than scoring one
|
|
349
411
|
more.
|
|
350
412
|
|
|
351
|
-
**
|
|
352
|
-
|
|
353
|
-
and
|
|
413
|
+
**The two set-piece roles split — measured separately, one flag moved at a
|
|
414
|
+
time (`pk-taker.mts`).** A free kick goes direct half the time (scored by the
|
|
415
|
+
kicker's `shoot`) and crossed half the time (gated by the kicker's `pass`, then
|
|
416
|
+
a DIFFERENT receiver shoots). Even with that pass gate, the shoot-heavy taker
|
|
417
|
+
wins the FK slot: a shoot-10/pass-4 striker out-converts a 9/9 passer-shooter
|
|
418
|
+
34.4% → 47.9% and out-scores him by ~330 points over 4,000 matches. (Caveat:
|
|
419
|
+
the crossed half's payoff runs through your receivers' `shoot` — this fixture's
|
|
420
|
+
receivers are flat, which favours the direct half.) The in-match penalty flips:
|
|
421
|
+
`takePkShot` rolls `(pass + shoot) / 2 + cond / 2 + total / 3 + rand`, and with
|
|
422
|
+
totals and condition held equal the 9/9 converts 83.9% vs 69.8% for the 10/4.
|
|
423
|
+
Both branches roll through `getPoint`, which adds `total / 3` (and
|
|
424
|
+
condition) to the selected skill — the probe held totals and condition equal
|
|
425
|
+
to isolate the attribute terms. So between candidates with DIFFERENT totals
|
|
426
|
+
compare full expressions, not attributes alone: `isFkKicker` by `shoot +
|
|
427
|
+
total / 3`, `isPkKicker` by `(pass + shoot) / 2 + total / 3`. One player may
|
|
428
|
+
hold both roles if he wins both criteria. (Neither nomination applies to a shootout — that order is computed
|
|
429
|
+
from `shoot + pass` across the whole squad.)
|
|
354
430
|
|
|
355
431
|
**There is no home advantage.** Identical squads win equally often from either
|
|
356
432
|
side. Never explain a result by which side you were on.
|
|
@@ -362,11 +438,21 @@ worthless as evidence, and this is the mistake to avoid:
|
|
|
362
438
|
|
|
363
439
|
| Friendlies played | Chance the better squad looks better |
|
|
364
440
|
| --- | --- |
|
|
365
|
-
| 1 |
|
|
366
|
-
| 5 |
|
|
367
|
-
| 10 |
|
|
368
|
-
| 30 |
|
|
369
|
-
| 50 |
|
|
441
|
+
| 1 | 34% |
|
|
442
|
+
| 5 | 58% |
|
|
443
|
+
| 10 | 70% |
|
|
444
|
+
| 30 | 88% |
|
|
445
|
+
| 50 | 94% |
|
|
446
|
+
|
|
447
|
+
(Measured on ONE specific gap — a keeper-10 squad against a keeper-24 squad,
|
|
448
|
+
re-validated with independent seeding. A smaller true gap needs MORE matches
|
|
449
|
+
than this table says, a larger one fewer; read it as orders of magnitude, not
|
|
450
|
+
as thresholds. **Measured with `allowDraw: true` (`gameFlg 0`) — a default
|
|
451
|
+
friendly resolves level scores through ET and a shootout, so these draw-heavy
|
|
452
|
+
rows do not describe it.** Worse than that: in default-friendly mode the SAME
|
|
453
|
+
two squads' true ordering FLIPS — the keeper-10 squad loses 48.5/51.5 over
|
|
454
|
+
20,000 matches, because keeper weight itself is mode-dependent (see the keeper
|
|
455
|
+
section). Measure in the mode you intend to play.)
|
|
370
456
|
|
|
371
457
|
At one match the most likely outcome is not a wrong answer — it is **no answer**:
|
|
372
458
|
roughly half of all friendlies end level.
|
|
@@ -378,8 +464,8 @@ are a coin flip:
|
|
|
378
464
|
| Friendlies | Identical squads showing a 2+ win gap | …that a significance test would call real |
|
|
379
465
|
| --- | --- | --- |
|
|
380
466
|
| 10 | 51% | 1% |
|
|
381
|
-
| 30 |
|
|
382
|
-
| 100 |
|
|
467
|
+
| 30 | 72% | 3% |
|
|
468
|
+
| 100 | 84% | 4% |
|
|
383
469
|
|
|
384
470
|
Read the two columns together. "One squad is clearly ahead" is the normal state
|
|
385
471
|
between squads that are exactly the same, and it gets MORE common with more
|
|
@@ -9,6 +9,13 @@ from an installed copy of this package.
|
|
|
9
9
|
Re-run them after any engine change. **A rebalance invalidates this file, and
|
|
10
10
|
`SKILL.md` with it.**
|
|
11
11
|
|
|
12
|
+
**The probes are repo-only, deliberately.** They import the workspace engine by
|
|
13
|
+
a relative path, so from an installed npm package they are module-not-found —
|
|
14
|
+
that exact breakage shipped once and is now pinned by `packaging.test.ts`. To
|
|
15
|
+
reproduce any table here, run from a checkout of
|
|
16
|
+
`github.com/1XP-AI/solana-world-soccer-2026` under
|
|
17
|
+
`packages/mcp/skill/reference/probes/`.
|
|
18
|
+
|
|
12
19
|
## Method
|
|
13
20
|
|
|
14
21
|
Candidate squads are built to exactly 212 points and passed through
|
|
@@ -16,12 +23,42 @@ Candidate squads are built to exactly 212 points and passed through
|
|
|
16
23
|
actually field. Squads then play each other over many seeds; only the seed
|
|
17
24
|
varies between repetitions of a fixture.
|
|
18
25
|
|
|
19
|
-
**
|
|
20
|
-
engine defaults it to 1, which sends a level score
|
|
21
|
-
a golden-goal winner. An earlier version of every
|
|
22
|
-
way, so it described a mixture of regulation and
|
|
23
|
-
Skill tells agents to compare squads with draws
|
|
24
|
-
the correction; the magnitudes did not, and draws
|
|
26
|
+
**Tables run with `gameFlg: 0` — regulation only, draws allowed — unless a
|
|
27
|
+
section says otherwise.** The engine defaults it to 1, which sends a level score
|
|
28
|
+
to extra time and can produce a golden-goal winner. An earlier version of every
|
|
29
|
+
table here was measured that way, so it described a mixture of regulation and
|
|
30
|
+
knockout outcomes while the Skill tells agents to compare squads with draws
|
|
31
|
+
enabled. The rankings survived the correction; the magnitudes did not, and draws
|
|
32
|
+
roughly doubled.
|
|
33
|
+
|
|
34
|
+
**That correction then created a blind spot of its own, found 2026-08-19.**
|
|
35
|
+
Measuring only with draws allowed describes the ladder and cup group stage — but
|
|
36
|
+
cup knockout rounds and default friendlies are played with `gameFlg: 1`, and at
|
|
37
|
+
least one conclusion REVERSES between the two. A table measured in one mode is
|
|
38
|
+
evidence about that mode only. Where a result depends on the mode, both are now
|
|
39
|
+
published side by side.
|
|
40
|
+
|
|
41
|
+
**Probe seeding matters more than it looks.** Until 2026-08-20 every probe here
|
|
42
|
+
derived seeds with a hand-rolled FNV-style nibble walk, and the engine reads
|
|
43
|
+
only the first 32 hex chars of a seed. An adversarial re-measurement showed that
|
|
44
|
+
similar tag strings can produce CORRELATED seed families — phantom |z| up to ~7
|
|
45
|
+
on cells whose true value is zero, and a true ~12 measured as ~1.7, depending on
|
|
46
|
+
tag-string luck. `budget-allocation.mts`, `gk-split.mts`, `pk-taker.mts` and
|
|
47
|
+
`cycle-probe.mts` now seed with SHA-256 and carry a standing mirror cell (same
|
|
48
|
+
team vs itself; it must stay near z 0 or the seeding, not the game, is what got
|
|
49
|
+
measured) — the cycle probe additionally applies a Bonferroni-corrected
|
|
50
|
+
threshold, and its re-run is recorded in "Strategy round-robin in BOTH modes"
|
|
51
|
+
below. `sample-size.mts` was re-validated the same day (SHA-256; both tables below
|
|
52
|
+
updated — shape unchanged, rows a touch weaker; its identical-squads section is
|
|
53
|
+
its own true-zero control). Still queued: `strategy-probe.mts`,
|
|
54
|
+
`skill-value.mts`, `gk-sweep.mts`, and any published verdict resting on
|
|
55
|
+
|z| < 10 from the old seeder.
|
|
56
|
+
|
|
57
|
+
**A probe that scores by comparing `homeScore` to `awayScore` is wrong under
|
|
58
|
+
`gameFlg: 1`** and silently reports decided matches as draws. `MatchResult` has
|
|
59
|
+
no `penaltyWinner` field — read `winner`, which carries the engine's verdict
|
|
60
|
+
after every tiebreaker. This mistake was made and caught here; the note is left
|
|
61
|
+
so it is not made again.
|
|
25
62
|
|
|
26
63
|
One earlier version of this harness repaired the point total globally after
|
|
27
64
|
shaping each player, which quietly flattened all eleven candidates into the same
|
|
@@ -71,8 +108,16 @@ the ten outfield players. Every squad plays the same fixed opponent (a keeper of
|
|
|
71
108
|
| 23 | 1.144 | 0.47 |
|
|
72
109
|
| 29 | 0.991 | 0.51 |
|
|
73
110
|
|
|
74
|
-
|
|
75
|
-
|
|
111
|
+
The trend falls across the whole range, but **adjacent totals do not separate**.
|
|
112
|
+
Re-running the sweep, the order reverses at five of the twenty values — 13, 15,
|
|
113
|
+
17, 19 and 28 each score above the total directly below them. Three thousand
|
|
114
|
+
matches cannot split a one-point difference in keeper budget. What it does split
|
|
115
|
+
is the range: the ~0.4 pt/match gap between the low teens and the high twenties
|
|
116
|
+
is far larger than any reversal. Read this table as "the low end beats the high
|
|
117
|
+
end", never as "19 beats 20".
|
|
118
|
+
|
|
119
|
+
Note the second column: a *better* keeper concedes *more*, because the points
|
|
120
|
+
came out of the ten players in front of it.
|
|
76
121
|
|
|
77
122
|
**Mechanism** (`packages/engine/src/engine.ts`): the goalkeeper is selected as
|
|
78
123
|
defender only in scene `A0`, the 1v1 chance — its weight is 0 in every other
|
|
@@ -83,8 +128,178 @@ through the rate tables. The keeper's stats also decide penalty shootouts
|
|
|
83
128
|
(`takePkShot`).
|
|
84
129
|
|
|
85
130
|
This is faithful to the original sgsoccer engine, not a defect introduced here.
|
|
86
|
-
|
|
87
|
-
|
|
131
|
+
|
|
132
|
+
### …and the "reversal" it seemed to show was an artefact
|
|
133
|
+
|
|
134
|
+
An earlier version of this section reported that the keeper budget REVERSES in
|
|
135
|
+
knockout matches — cheap best in regulation, expensive best in knockouts. That
|
|
136
|
+
was wrong, and the way it was wrong is worth keeping.
|
|
137
|
+
|
|
138
|
+
**The sweep above is not a single-variable sweep.** `gk-sweep.mts` builds the
|
|
139
|
+
keeper from a fixed ratio, `a(1, 1, 1, 3)`, so the total and the keeper's
|
|
140
|
+
`defense` move together and cannot be told apart. Worse, `defense` hits its cap
|
|
141
|
+
of 10 at around total 20, so below that a "smaller budget" also means "a worse
|
|
142
|
+
keeper" while above it the total grows with defense already pinned. The knockout
|
|
143
|
+
column's apparent peak in the high teens is those two effects crossing, not a
|
|
144
|
+
budget optimum.
|
|
145
|
+
|
|
146
|
+
Separating them — total held while defense varies, then defense held while the
|
|
147
|
+
total varies; 4,000 matches per cell; opponent fixed at total 20 / defense 10:
|
|
148
|
+
|
|
149
|
+
**Defense pinned at 10, total varied**
|
|
150
|
+
|
|
151
|
+
| GK total | Regulation | Knockout |
|
|
152
|
+
| --- | --- | --- |
|
|
153
|
+
| 13 | **1.492** | **1.613** |
|
|
154
|
+
| 16 | 1.375 | 1.615 |
|
|
155
|
+
| 20 | 1.244 | 1.505 |
|
|
156
|
+
| 24 | 1.075 | 1.380 |
|
|
157
|
+
| 29 | 0.945 | 1.253 |
|
|
158
|
+
|
|
159
|
+
**Total pinned at 20, defense varied** (outfield byte-identical across rows)
|
|
160
|
+
|
|
161
|
+
| GK defense | Regulation | Knockout |
|
|
162
|
+
| --- | --- | --- |
|
|
163
|
+
| 2 | 1.271 | 1.090 |
|
|
164
|
+
| 4 | 1.240 | 1.158 |
|
|
165
|
+
| 6 | 1.250 | 1.224 |
|
|
166
|
+
| 8 | 1.301 | 1.364 |
|
|
167
|
+
| 10 | 1.280 | **1.492** |
|
|
168
|
+
|
|
169
|
+
**Neither axis reverses ON THIS OUTFIELD** — and that qualifier turned out to
|
|
170
|
+
matter. A smaller total is better in both modes here; more defense is better in
|
|
171
|
+
both modes, weakly in regulation and strongly in knockouts.
|
|
172
|
+
|
|
173
|
+
> ⚠️ **The knockout half of that is outfield-conditional.** Reproducible from
|
|
174
|
+
> this repo — `gk-split.mts` section ④ holds the keeper at defense 10, swaps
|
|
175
|
+
> only the outfield across three legal fixtures (opponent = same-outfield
|
|
176
|
+
> total 20 / defense 10), and prints the shootout-reach rate that drives it:
|
|
177
|
+
>
|
|
178
|
+
> | Outfield (shoot profile) | Shootout reach | Knockout: total 13 vs 29 |
|
|
179
|
+
> | --- | --- | --- |
|
|
180
|
+
> | weak (shoot starved to 1) | ~75% | **REVERSED — 29 wins by ~0.85 pt/m** (1.202 vs 2.050) |
|
|
181
|
+
> | low (even spread, no 10s) | ~23% | monotone, 13 best (1.662 vs 1.298) |
|
|
182
|
+
> | high (two forwards at shoot 10) | ~13% | monotone, 13 best (1.661 vs 1.352) |
|
|
183
|
+
>
|
|
184
|
+
> `total/3` is in every save (regulation 1v1 included); a shootout multiplies
|
|
185
|
+
> those rolls, so the keeper's total is worth more the more often the match ends
|
|
186
|
+
> level. **The best keeper total is a function of SHOOTOUT EXPOSURE — a property
|
|
187
|
+
> of the pairing (both attacks together), not of the keeper and not of one squad
|
|
188
|
+
> alone.** The reach column is the mediator itself. Construction matters and bit
|
|
189
|
+
> us once: against a FIXED opponent the reversal disappears (exposure stops
|
|
190
|
+
> varying between arms) — the fixture pairs same-profile outfields precisely so
|
|
191
|
+
> exposure varies, and that also means the table demonstrates a pairing effect;
|
|
192
|
+
> your own attack is the half of it you control. The flip was first seen in an
|
|
193
|
+
> adversarial scratch run (z≈24); section ④ replaces that citation with
|
|
194
|
+
> something a checkout can re-run. The regulation column stayed monotone under
|
|
195
|
+
> every construction tried.
|
|
196
|
+
|
|
197
|
+
**Mechanism**: every save a keeper makes scores the same way —
|
|
198
|
+
`defense + cond/2 + total/3` against the attacker — at three sites: the 1v1
|
|
199
|
+
(`engine.ts:1385` via `getPoint`), the in-match penalty, and the shootout kick
|
|
200
|
+
(both through `takePkShot`, `engine.ts:1251`; `handlePk` calls it in regulation
|
|
201
|
+
too, so keeper defense pays on ~an eighth of goals even in league play). Nothing
|
|
202
|
+
else on the keeper is read by any defensive path, so its pass, dribble and shoot
|
|
203
|
+
are dead points there. The penalty/shootout roll weighs harder because its
|
|
204
|
+
random range is `rand(5)` against the taker's `rand(16)`.
|
|
205
|
+
|
|
206
|
+
**A related trap in the set-piece tables**: `isFkKicker` and `isPkKicker` decide
|
|
207
|
+
free kicks (`engine.ts:785`) and in-match penalties (`engine.ts:1214`), but
|
|
208
|
+
`runPkShootout` ignores both — it sorts the whole squad by `shoot + pass`
|
|
209
|
+
(`engine.ts:1062`). Any set-piece conclusion measured with `gameFlg: 0` therefore
|
|
210
|
+
says nothing about shootouts, and the shootout cannot be steered by nomination at
|
|
211
|
+
all.
|
|
212
|
+
|
|
213
|
+
**That is still not the whole answer**, and the first version of this section
|
|
214
|
+
claimed it was ("defense 10, everything else at 1, total 13 — best in both
|
|
215
|
+
modes"). That claim came from a sweep in which the points freed from the keeper
|
|
216
|
+
were spread evenly over the outfield — nobody lost anything, so no trade-off
|
|
217
|
+
could appear. A sweep has no opportunity cost built in.
|
|
218
|
+
|
|
219
|
+
Give those points a REAL competing use and the ranking changes. The squad has a
|
|
220
|
+
second budget beyond 212: **at most three attributes of value 10 and five of 8–9
|
|
221
|
+
across the whole team** (`validator.ts` `TEN_MAX` / `EIGHT_MAX` — team-wide, not
|
|
222
|
+
per player). Where one of those three 10s goes, measured head to head at 20,000
|
|
223
|
+
matches per pairing on otherwise byte-identical squads:
|
|
224
|
+
|
|
225
|
+
| A single 10 given to… | League | Knockout |
|
|
226
|
+
| --- | --- | --- |
|
|
227
|
+
| the set-piece taker's `shoot` | **1st** | 2nd |
|
|
228
|
+
| an ordinary forward's `shoot` | 2nd | 3rd |
|
|
229
|
+
| the keeper's `defense` | **3rd** | **1st** |
|
|
230
|
+
|
|
231
|
+
| Pairing | League | Knockout |
|
|
232
|
+
| --- | --- | --- |
|
|
233
|
+
| keeper-10 vs taker-10 | 45.1% (z −18.5) | 52.8% (z +7.9) |
|
|
234
|
+
| taker-10 vs forward-10 | 51.9% (z +6.9) | 53.7% (z +10.4) |
|
|
235
|
+
| forward-10 vs keeper-10 | 50.9% (z +3.5) | 43.3% (z −19.1) |
|
|
236
|
+
|
|
237
|
+
*Re-measured 2026-08-20 with SHA-256 seeding: ranking and signs unchanged
|
|
238
|
+
(z −15.5 / +11.0 / +5.5 regulation, +5.4 / +12.2 / −19.1 knockout; mirror
|
|
239
|
+
control z −0.09).*
|
|
240
|
+
|
|
241
|
+
The keeper and the ordinary forward swap ends completely. The set-piece taker is
|
|
242
|
+
first or second in both — the only allocation measured that is never wrong.
|
|
243
|
+
|
|
244
|
+
**Two lessons for this file, learned the hard way on the same day:**
|
|
245
|
+
|
|
246
|
+
1. A sweep that varies one *named* quantity is not a single-variable sweep if the
|
|
247
|
+
construction ties other quantities to it (the keeper's ratio tied `defense` to
|
|
248
|
+
the total). State the construction, or measure the axes apart.
|
|
249
|
+
2. **Separating the axes is not enough.** A sweep measures a quantity against
|
|
250
|
+
nothing, so it cannot rank allocations. Any claim of the form "X is optimal"
|
|
251
|
+
needs a control that spends the same budget somewhere else.
|
|
252
|
+
|
|
253
|
+
**Which matches are which** (`packages/api/src`) — still worth knowing, because
|
|
254
|
+
the SIZE of the defense effect differs by an order of magnitude between them:
|
|
255
|
+
|
|
256
|
+
| Match type | `gameFlg` |
|
|
257
|
+
| --- | --- |
|
|
258
|
+
| Ladder (`routes/playoff.ts`) | 0 |
|
|
259
|
+
| Cup group stage (`scheduler/daemon.ts`) | 0 |
|
|
260
|
+
| Cup knockout (`scheduler/daemon.ts`) | 1 |
|
|
261
|
+
| Friendly, default (`routes/matches.ts`) | 1 |
|
|
262
|
+
|
|
263
|
+
## Strategy round-robin in BOTH modes (`cycle-probe.mts`)
|
|
264
|
+
|
|
265
|
+
Recorded 2026-08-20 — the founding "no cycles" claim had circulated without a
|
|
266
|
+
home in this file. Construction: the SAME squads as the round-robin above (the
|
|
267
|
+
builders are shared code in `squad-lib.mts`, not a copy — an earlier hand-copied
|
|
268
|
+
variant repaired the scarcity caps in a different order and silently built
|
|
269
|
+
different squads from identical slot totals), SHA-256 seeding, mirror control
|
|
270
|
+
z 0.89, eight candidates, 4,000 matches per pairing per mode.
|
|
271
|
+
|
|
272
|
+
Significance is Bonferroni-corrected across all 56 pairings (two modes ×
|
|
273
|
+
28): |z| >= 3.32 rather than a naive 1.96, which over 56 comparisons all but
|
|
274
|
+
guarantees a few false edges — and one false edge can create or erase a
|
|
275
|
+
dominance or cycle verdict.
|
|
276
|
+
|
|
277
|
+
| | Regulation (draws) | Knockout (ET + shootout) |
|
|
278
|
+
| --- | --- | --- |
|
|
279
|
+
| Significant pairings | 25/28 | 24/28 |
|
|
280
|
+
| 3-cycles (A>B>C>A) | **0** | **0** |
|
|
281
|
+
| Dominant strategy | none | **`role-433`** beats all seven |
|
|
282
|
+
|
|
283
|
+
Mode reversals that survived this re-measurement:
|
|
284
|
+
|
|
285
|
+
- **Attack vs defense lean** (same formation, same budgets): `def-433` beats
|
|
286
|
+
`role-433` 56.5% in regulation; the SAME pairing flips to 53.6% for the
|
|
287
|
+
attack lean in knockouts. Both significant — the cleanest reversal measured.
|
|
288
|
+
- **Formation**: `def-532` beats `bal-442` 73.9% in regulation and loses 56.6%
|
|
289
|
+
in knockouts.
|
|
290
|
+
- **Cheap keeper**: `gkmin-433` collapses in knockouts (27~42% against the
|
|
291
|
+
other top squads). Its regulation edge over the top group did NOT survive the
|
|
292
|
+
corrected builders (50.8% vs `def-433`, 47.4% vs `def-532` — not significant);
|
|
293
|
+
what remains significant in regulation is its edge over `role-433` (57.0%)
|
|
294
|
+
and everything below the top group.
|
|
295
|
+
|
|
296
|
+
Monotone in both modes, still: role differentiation (`flat-433` last
|
|
297
|
+
everywhere) and spreading over star-concentration (`stars-433` next-to-last).
|
|
298
|
+
|
|
299
|
+
Scope: all squads tenure=0, as everywhere in this file. Production applies
|
|
300
|
+
`applyMatchGrowth()` before the engine, raising effective totals — these
|
|
301
|
+
dominance/reversal claims are about zero-buff squads until the buff-0/max
|
|
302
|
+
control runs (docs/tactics/01, track 0.1).
|
|
88
303
|
|
|
89
304
|
## Home advantage: none
|
|
90
305
|
|
|
@@ -103,34 +318,89 @@ Same squad, only the kicker slots move. Opponent fixed, 3,000 matches each.
|
|
|
103
318
|
| DF / DF | 20.4 | 1.149 |
|
|
104
319
|
| GK / GK | 17.4 | 1.066 |
|
|
105
320
|
|
|
106
|
-
Conversion tracks the taker's shooting
|
|
107
|
-
|
|
321
|
+
Conversion tracks the taker's shooting — for FREE kicks. This table moved both
|
|
322
|
+
roles together and never crossed the two criteria, so it says nothing about the
|
|
323
|
+
PK slot on its own. `pk-taker.mts` crosses them: one squad held byte-identical,
|
|
324
|
+
only `pkKicker` moved between a 9-pass/9-shoot midfielder (the PK formula's
|
|
325
|
+
pick — `takePkShot` scores the taker as `(pass + shoot) / 2 + …`) and a
|
|
326
|
+
10-shoot/4-pass striker (the FK criterion's pick). Opponent fixed, regulation,
|
|
327
|
+
4,000 matches per arm, mirror z −0.62:
|
|
328
|
+
|
|
329
|
+
| pkKicker | (pass+shoot)/2 | PK attempts | Conversion |
|
|
330
|
+
| --- | --- | --- | --- |
|
|
331
|
+
| mid 9/9 | 9 | 299 | **83.9%** |
|
|
332
|
+
| fw 10/4 | 7 | 301 | 69.8% |
|
|
333
|
+
|
|
334
|
+
+14.2pp, two-proportion z 4.12. In-match penalties are rare (~0.07 attempts
|
|
335
|
+
per match here), so the points axis is underpowered — the verdict is the
|
|
336
|
+
conversion rate.
|
|
337
|
+
|
|
338
|
+
The FK half is measured the same way (section ② of the probe): only
|
|
339
|
+
`fkKicker` moves, `pkKicker` pinned. A direct FK (half of `doFk`) scores by
|
|
340
|
+
the kicker's `shoot`; a crossed FK gates on the kicker's `pass` and then a
|
|
341
|
+
different receiver shoots. Attempt counts include foul-site direct FKs taken
|
|
342
|
+
by the fouled ball-carrier — those ignore the flag and are identically
|
|
343
|
+
distributed across both arms, so the BETWEEN-ARM gap is attributable to the
|
|
344
|
+
designated-kicker FKs alone (and the per-attempt gap is an underestimate).
|
|
345
|
+
|
|
346
|
+
| fkKicker | shoot | pass | FK attempts | Team FK goals | Per attempt | W-D-L |
|
|
347
|
+
| --- | --- | --- | --- | --- | --- | --- |
|
|
348
|
+
| mid 9/9 | 9 | 9 | 2,307 | 793 | 34.4% | 1289-1532-1179 |
|
|
349
|
+
| fw 10/4 | 10 | 4 | 2,311 | 1,107 | **47.9%** | 1420-1470-1110 |
|
|
350
|
+
|
|
351
|
+
−13.5pp, two-proportion z −9.34; points 5,399 vs 5,730. Even with the pass
|
|
352
|
+
gate, the shoot-heavy taker wins the FK slot — in THIS fixture, whose
|
|
353
|
+
receivers are flat: the crossed half's payoff runs through the receivers'
|
|
354
|
+
`shoot`, so a squad with strong secondary attackers shifts value back toward
|
|
355
|
+
the crossing taker. Both set pieces roll through `getPoint`/`takePkShot`,
|
|
356
|
+
which add `total/3` (and condition) to the attribute term — the probe held
|
|
357
|
+
totals and condition equal to isolate that term. So: free kicks to the best
|
|
358
|
+
`shoot + total/3`, the penalty to the best `(pass+shoot)/2 + total/3`; with
|
|
359
|
+
unequal condition include `cond/2` too; one player may hold both roles when
|
|
360
|
+
he wins both criteria.
|
|
108
361
|
|
|
109
362
|
## How many friendlies a conclusion needs
|
|
110
363
|
|
|
111
364
|
Two squads with a known true gap, resampled 20,000 times at each sample size.
|
|
112
365
|
|
|
366
|
+
Re-measured 2026-08-20 with SHA-256 seeding (the original numbers came from the
|
|
367
|
+
correlated FNV seeder; shape unchanged, every row a touch weaker). Scope: this
|
|
368
|
+
is ONE matchup — a keeper-10 squad against a keeper-24 squad, ratio-locked
|
|
369
|
+
construction — so the true gap is that specific ~1.8-win-in-ten one. A smaller
|
|
370
|
+
true gap needs more matches than the row says; a larger one, fewer.
|
|
371
|
+
|
|
372
|
+
Scope, part two (Codex P2, #688): **everything below is `gameFlg 0` —
|
|
373
|
+
regulation, draws allowed** (`allowDraw: true` on a friendly), which is what
|
|
374
|
+
`sample-size.mts` simulates. A DEFAULT friendly is `gameFlg 1`. Running the
|
|
375
|
+
probe with `GAME_FLG=1` does not merely shrink the tie column: the same two
|
|
376
|
+
squads' true ordering FLIPS — the keeper-10 squad, the better side in
|
|
377
|
+
regulation, loses 48.5/51.5 over 20,000 default-mode matches, consistent with
|
|
378
|
+
the keeper section's mode dependence (ET and a shootout multiply keeper
|
|
379
|
+
rolls). A "which squad is better" verdict is mode-specific twice over: the
|
|
380
|
+
sample sizes below apply only to draw-allowed friendlies, and the ANSWER can
|
|
381
|
+
change when the mode does. Measure in the mode you intend to play.
|
|
382
|
+
|
|
113
383
|
| Friendlies | Correct conclusion | Wrong conclusion | Tied |
|
|
114
384
|
| --- | --- | --- | --- |
|
|
115
|
-
| 1 |
|
|
116
|
-
| 3 |
|
|
117
|
-
| 5 |
|
|
118
|
-
| 10 |
|
|
119
|
-
| 20 |
|
|
120
|
-
| 30 |
|
|
121
|
-
| 50 |
|
|
122
|
-
| 100 |
|
|
385
|
+
| 1 | 33.6% | 17.2% | 49.2% |
|
|
386
|
+
| 3 | 50.2% | 20.4% | 29.3% |
|
|
387
|
+
| 5 | 58.3% | 19.7% | 22.0% |
|
|
388
|
+
| 10 | 69.7% | 16.6% | 13.7% |
|
|
389
|
+
| 20 | 81.5% | 11.1% | 7.4% |
|
|
390
|
+
| 30 | 88.0% | 7.5% | 4.5% |
|
|
391
|
+
| 50 | 94.1% | 3.9% | 1.9% |
|
|
392
|
+
| 100 | 98.9% | 0.7% | 0.4% |
|
|
123
393
|
|
|
124
394
|
And the false-positive side — **identical** squads, by three different
|
|
125
395
|
definitions of "one side looks better":
|
|
126
396
|
|
|
127
397
|
| Friendlies | Record not exactly level | Win-loss gap ≥ 2 | Significant (sign test, p<0.05) |
|
|
128
398
|
| --- | --- | --- | --- |
|
|
129
|
-
| 1 |
|
|
130
|
-
| 5 | 75.
|
|
131
|
-
| 10 | 82.
|
|
132
|
-
| 30 |
|
|
133
|
-
| 100 |
|
|
399
|
+
| 1 | 51.4% | 0.0% | 0.0% |
|
|
400
|
+
| 5 | 75.8% | 35.0% | 0.0% |
|
|
401
|
+
| 10 | 82.8% | 50.9% | 1.0% |
|
|
402
|
+
| 30 | 90.6% | 72.3% | 2.9% |
|
|
403
|
+
| 100 | 94.6% | 83.9% | 3.5% |
|
|
134
404
|
|
|
135
405
|
**The first column is a trap and was published on its own in an earlier version
|
|
136
406
|
of this file.** "Not exactly level" approaches 100% for any pair of squads simply
|
|
@@ -174,19 +444,90 @@ rest drawn.
|
|
|
174
444
|
|
|
175
445
|
## Note for the maintainers
|
|
176
446
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
the
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
447
|
+
> **2026-08-19: this note was rewritten twice in one day.** First it said the
|
|
448
|
+
> cheap keeper was "monotonically better across the whole range". Then it said
|
|
449
|
+
> the direction reverses in knockouts. Both were readings of a sweep that could
|
|
450
|
+
> not separate the keeper's total from its defense. The section above has the
|
|
451
|
+
> separated measurement; this note now describes that.
|
|
452
|
+
|
|
453
|
+
The keeper slot reads exactly one attribute — `defense` — at exactly three
|
|
454
|
+
sites: the 1v1, the in-match penalty (a regulation event too, ~an eighth of all
|
|
455
|
+
goals), and the shootout kick. Everything else parked there is dead weight. So there
|
|
456
|
+
are two independent facts, and conflating them produced both earlier errors:
|
|
457
|
+
|
|
458
|
+
- **Total: smaller is better in matches that allow draws** — that held under
|
|
459
|
+
every construction tried. In knockouts it is OUTFIELD-CONDITIONAL (see the
|
|
460
|
+
warning above): a low-scoring squad reaches shootouts often enough that a
|
|
461
|
+
bigger keeper total pays there.
|
|
462
|
+
- **Defense: higher is better on its own slot, in both modes** — weakly in
|
|
463
|
+
regulation, strongly in knockouts. But a 10 there is one of only three the
|
|
464
|
+
whole team may hold, and in the scarce-10 comparison above the keeper's 10
|
|
465
|
+
ranked LAST in league play.
|
|
466
|
+
|
|
467
|
+
So even the two facts do not compose into one recommended shape. What survives
|
|
468
|
+
is the negative advice: never leave points in the keeper's pass/dribble/shoot,
|
|
469
|
+
and never scale a balanced keeper down.
|
|
470
|
+
|
|
471
|
+
Keep it in proportion. Against a naive squad, role shaping alone wins 43.6% and
|
|
472
|
+
adding a cheap keeper takes that to 52.1%. Role differentiation still decides
|
|
473
|
+
more matches than the keeper does.
|
|
474
|
+
|
|
475
|
+
`SKILL.md` states the two facts separately and warns against scaling a balanced
|
|
476
|
+
keeper down, because that drags defense along with the total. If the keeper is
|
|
477
|
+
ever given team contribution or a budget floor, re-run these probes in BOTH
|
|
478
|
+
modes AND with the two axes separated — the ratio-locked sweep alone will not
|
|
479
|
+
show it.
|
|
480
|
+
|
|
481
|
+
### The decision, and what would reopen it
|
|
482
|
+
|
|
483
|
+
Issue #604 settled on **leaving the engine faithful to sgsoccer** — and made
|
|
484
|
+
that settlement *conditional* on the meta not collapsing onto one answer. The
|
|
485
|
+
separated measurement makes that risk concrete again: defense 10 is the single
|
|
486
|
+
best keeper defense everywhere measured, and under ordinary shootout exposure —
|
|
487
|
+
regulation, and knockout pairings that reach shootouts at typical rates — the
|
|
488
|
+
best shape is defense 10, total 13. The one measured exception is the pairing
|
|
489
|
+
block above: against shoot-starved pairings reaching shootouts ~75% of the
|
|
490
|
+
time, the optimum climbs the total axis (total 29 beat total 13 by ~0.85 ppm)
|
|
491
|
+
while defense stays at 10. So what a converging population would collapse onto
|
|
492
|
+
is per-context on the total axis but single-valued on the defense axis. The
|
|
493
|
+
earlier hope that "the meta has nowhere to collapse to" rested on a reversal
|
|
494
|
+
that turned out to be an artefact.
|
|
495
|
+
|
|
496
|
+
What is worth watching therefore returns to the original question, with one
|
|
497
|
+
correction: **watch the keeper's `defense`, not its total.** A population
|
|
498
|
+
converging on total 13 while keeping defense at 10 has found the optimum; a
|
|
499
|
+
population converging on a low total with a scaled-down defense has been misled
|
|
500
|
+
and is playing worse. Those two look identical to a total-only metric.
|
|
501
|
+
|
|
502
|
+
Read-only from production on 2026-08-18 (32 human squads, seeded AI bots
|
|
503
|
+
excluded): median keeper total **19**, mean 17.6, **nobody** above 24, and only
|
|
504
|
+
two squads (6%) at the minimum. So the direction the probes predict is visible —
|
|
505
|
+
heavy keepers are unbought — but the meta has NOT converged. Two thirds sit at
|
|
506
|
+
19–20, which is the default left untouched rather than a choice.
|
|
507
|
+
|
|
508
|
+
That reading is limited by sample, not by engine design: in that season only two
|
|
509
|
+
human teams had played more than three matches, so no comparison *by result* was
|
|
510
|
+
possible. The re-review triggers therefore key on sample first:
|
|
511
|
+
|
|
512
|
+
| # | Trigger | Threshold |
|
|
513
|
+
| --- | --- | --- |
|
|
514
|
+
| 1 | Human teams with enough matches to compare by result — AND a contrast: two keeper-total cohorts of >= 3 qualified teams each. UNDECIDABLE (reported, never firing) until matches record the squad they were played with: cohorts group season records by the CURRENT keeper, and FA-market trading makes mid-season keeper edits routine, so a cohort can be fabricated | >= 10 teams, >= 2 cohorts, per-match squad snapshots |
|
|
515
|
+
| 2 | Share of human squads on the MONITORED allocation — total <= 13 (the legal minimum with defense 10 is 1+1+1+10) AND defense >= 9. Cheap-but-weak squads are the opposite event (stale-advice damage) and are reported separately as `misled`, never firing this trigger. Undecidable below 10 human squads — a share over fewer reads one manager's choice as a meta | > 40% of >= 10 squads |
|
|
516
|
+
| 3 | Median keeper total of the top 10 ranked human teams, each with >= 10 matches (a one-match post-rollover ranking stays null). UNDECIDABLE (reported, never firing) until per-match squad snapshots exist — rank is season-long, the keeper total is current, and leaders swapping keepers after earning their records would fire it over zero matches at the new total | <= 14, plus squad snapshots |
|
|
517
|
+
|
|
518
|
+
These live as code, not as prose here — prose does not get re-read:
|
|
519
|
+
|
|
520
|
+
```bash
|
|
521
|
+
DATABASE_URL=postgres://… pnpm --filter @sws26/api exec tsx scripts/gk-budget-watch.ts
|
|
522
|
+
```
|
|
523
|
+
|
|
524
|
+
It prints the current distribution, the record grouped by keeper total, and
|
|
525
|
+
whether any trigger has fired. `packages/api/src/lib/gk-budget-watch.ts` holds
|
|
526
|
+
the thresholds; the CLI reads squads through `TeamStore` rather than the
|
|
527
|
+
`players` table, because a sold keeper leaves `roster_slots` without rewriting
|
|
528
|
+
the legacy row.
|
|
529
|
+
|
|
530
|
+
If a trigger fires, re-run the probes above BEFORE touching anything, then
|
|
531
|
+
decide between the options in #604. Whatever is chosen, the engine change and
|
|
532
|
+
both documents move in the SAME change — `SKILL.md` is what agents believe, and
|
|
533
|
+
a stale sentence there makes them exclude squads that are perfectly legal.
|