pog-mcp 0.9.14 → 0.9.15
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/reference/measurements.md +188 -5
package/package.json
CHANGED
|
@@ -664,10 +664,11 @@ sets it — there is no `fair:` outside the engine's own tests, and every engine
|
|
|
664
664
|
input is built from an explicit field list — so it is a global constant in
|
|
665
665
|
practice, and setting it on both squads IS the rule change.
|
|
666
666
|
|
|
667
|
-
**Not swept: the zone-press coefficient.**
|
|
668
|
-
candidate weight
|
|
669
|
-
slot" — and a coefficient in front of an undefined selection measures nothing.
|
|
670
|
-
|
|
667
|
+
**Not swept: the zone-press coefficient.** At the time its selector was broken —
|
|
668
|
+
every candidate weight was `0.0`, so `weightedPick` fell back to "the first non-GK
|
|
669
|
+
slot" — and a coefficient in front of an undefined selection measures nothing. The
|
|
670
|
+
selector was fixed in #730 (`zp-selector.mts` below); the coefficient is sweepable
|
|
671
|
+
now but has not been swept.
|
|
671
672
|
|
|
672
673
|
### The statistic, and why not the obvious one
|
|
673
674
|
|
|
@@ -1810,7 +1811,9 @@ another is classified as a `swap` in `FormationPitch`, which calls `handleDrop`
|
|
|
1810
1811
|
so the drop handler wired there never fires. One drag reaches this at team creation; an
|
|
1811
1812
|
existing team cannot be reordered that way.
|
|
1812
1813
|
|
|
1813
|
-
**The mechanism is unidentified, and both candidates are back open.**
|
|
1814
|
+
**The mechanism is unidentified, and both candidates are back open.** *(Superseded:
|
|
1815
|
+
`zp-selector.mts` below identified it — the zone-press fallback, removed by #730. The
|
|
1816
|
+
paragraphs that follow are kept as the record of why the first ablation missed it.)*
|
|
1814
1817
|
|
|
1815
1818
|
| candidate | test | result |
|
|
1816
1819
|
| --- | --- | --- |
|
|
@@ -4279,3 +4282,183 @@ literal early broke one seven times; the last was a markdown table's `` `7036372
|
|
|
4279
4282
|
the edit script itself. No tsconfig includes those. The remedy is asserting the match count on
|
|
4280
4283
|
every replacement, so a broken script dies before it touches the file — which is exactly what
|
|
4281
4284
|
happened. A smoke run is a behavioural check, not the parse gate.
|
|
4285
|
+
|
|
4286
|
+
## Is the slot-order lever the zone-press fallback? (`zp-selector.mts`)
|
|
4287
|
+
|
|
4288
|
+
Yes — on the one core where a lever exists, and a two-line engine change removes
|
|
4289
|
+
it. This settles the question the depth-cap note above left open ("the mechanism
|
|
4290
|
+
is unidentified, and both candidates are back open"): the candidate it withdrew
|
|
4291
|
+
for the wrong reason was the right one.
|
|
4292
|
+
|
|
4293
|
+
### What was broken, exactly
|
|
4294
|
+
|
|
4295
|
+
`tryZonePress` drew the presser with the DEFENSIVE appearance table, whose
|
|
4296
|
+
`SCENE.ZP` column is all-zero for every position (`D_*_APPR[ZP] = 0/0/0/0`), so
|
|
4297
|
+
`weightedPick` had no candidate and fell through to `players[first non-GK]` on
|
|
4298
|
+
every zone press. `getPoint` then drew the possessing side's responder on the
|
|
4299
|
+
same scene with the same table — same fallback, same slot. Both sides of every
|
|
4300
|
+
zone press were therefore the first non-GK slot of their team, a slot the manager
|
|
4301
|
+
chooses freely at team creation. The offence column `O_*_APPR[ZP]` (FW 1.0, OMF
|
|
4302
|
+
0.9, DMF 0.8, DF 0.7) was populated and unreachable.
|
|
4303
|
+
|
|
4304
|
+
The fix draws both with the offence table — the side `getPoint` already scores
|
|
4305
|
+
the presser as (`O_*_RATE[ZP]`). It invents no table; it revives one.
|
|
4306
|
+
|
|
4307
|
+
It also had to define one case the old code left undefined. `getPoint`'s DMF
|
|
4308
|
+
branch carries a ported defect: on the home side it subtracts the ball carrier
|
|
4309
|
+
`this.kiten` rather than the acting player. For a zone press `this.kiten` indexes
|
|
4310
|
+
the POSSESSING team while the calculation is the PRESSING team's, so it names an
|
|
4311
|
+
arbitrary same-numbered player — the keeper included — and makes the press depend
|
|
4312
|
+
on the OPPONENT's slot order. The fallback hid this: the presser was always the
|
|
4313
|
+
first non-GK slot, so a DMF pressed only when a manager happened to put one
|
|
4314
|
+
there. Drawing by weight makes DMF pressers ~19% of presses, so `SCENE.ZP` now
|
|
4315
|
+
takes the acting player, like every other position in that switch. The defect is
|
|
4316
|
+
untouched everywhere it was measured. That this path really was unreachable is
|
|
4317
|
+
now asserted, not assumed: reverting the two selector lines in a source copy
|
|
4318
|
+
reproduces the pre-#725 corpus digest exactly.
|
|
4319
|
+
|
|
4320
|
+
### Method
|
|
4321
|
+
|
|
4322
|
+
Four cores (`flat`, `shaped`, `gkheavy`, `gkmin`), each against a basket of the
|
|
4323
|
+
other three, both modes exposure-weighted (knockout 8.1%). Units are pp of WIN
|
|
4324
|
+
RATE on that mix. Two engines run the same matches from the same seeds: the
|
|
4325
|
+
shipped engine and a copy with the two selector lines patched in a `mkdtemp`
|
|
4326
|
+
directory (the `appr-role.mts` pattern; nothing is written inside the
|
|
4327
|
+
repository). Three readings per core:
|
|
4328
|
+
|
|
4329
|
+
1. **Sweep**: swap each slot j into the first non-GK slot, paired against the
|
|
4330
|
+
base order, on both engines, plus the paired **shipped − fixed contrast** on
|
|
4331
|
+
the same matches. If the lever is the fallback, the shipped column moves and
|
|
4332
|
+
the fixed column does not.
|
|
4333
|
+
2. **Best permutation, selected TWICE — once per engine**: 120 permutations
|
|
4334
|
+
scored at 200 seeds, the winner published at 1500 fresh seeds on both
|
|
4335
|
+
engines (selection column and publication column are different seeds, so the
|
|
4336
|
+
selection optimism is not in the published number). The search runs once
|
|
4337
|
+
against the shipped engine and once, independently, against the fixed one.
|
|
4338
|
+
Optimising only against the shipped engine can show the old exploit is gone;
|
|
4339
|
+
it cannot show the fixed engine has no lever of its own, because a
|
|
4340
|
+
permutation the fixed engine would favour is never tried.
|
|
4341
|
+
3. **Base shift**: fixed − shipped for the base order itself, descriptive only
|
|
4342
|
+
and outside the family, because it answers a different question (does the fix
|
|
4343
|
+
move the level, not the lever).
|
|
4344
|
+
|
|
4345
|
+
Pre-registered family m=132, Bonferroni at α=0.05 → |t| ≥ 3.56 (df 1499). The
|
|
4346
|
+
family is every comparison the run prints with a significance mark — each swap
|
|
4347
|
+
on both engines (72), every swap's own engine contrast (36, not a preselected
|
|
4348
|
+
"widest": nothing picks one and the readings below use several), and the two
|
|
4349
|
+
selected permutations on both engines with their contrasts (16 + 4). Every
|
|
4350
|
+
interval is a paired per-seed t interval.
|
|
4351
|
+
|
|
4352
|
+
Controls, every one of which aborts the run if it fails: the import-rewritten
|
|
4353
|
+
engine with no selector change reproduces 1000 stock matches byte-for-byte
|
|
4354
|
+
(whole `MatchResult`); a fallback census over 400 matches counts 1056 zero-weight
|
|
4355
|
+
fallbacks on the shipped engine (one per zone press) and 0 on the fixed one;
|
|
4356
|
+
mirror cells (true z = 0) read z = 0.3/0.2 shipped and 1.2/1.3 fixed; and the
|
|
4357
|
+
base order replayed reproduces itself exactly on both engines.
|
|
4358
|
+
|
|
4359
|
+
### Result
|
|
4360
|
+
|
|
4361
|
+
| core | shipped-selected perm, on shipped | the same perm, on fixed | shipped − fixed (paired) | **fixed-selected perm, on fixed** | sweep swaps significant, shipped / fixed |
|
|
4362
|
+
| --- | --- | --- | --- | --- | --- |
|
|
4363
|
+
| `shaped` | **+5.20pp** [+0.45, +9.95], t 3.9 | +0.76pp [−3.97, +5.50], t 0.6 | **+4.44pp** [+0.13, +8.74], t 3.7 | **+0.02pp** [−4.60, +4.65], t 0.0 | **4** / 0 |
|
|
4364
|
+
| `flat` | −1.57pp [−4.44, +1.30], t −1.9 | −0.79pp [−3.71, +2.13] | −0.78pp [−3.46, +1.90], t −1.0 | −0.21pp [−3.19, +2.76], t −0.3 | 1 / 0 |
|
|
4365
|
+
| `gkheavy` | +1.10pp [−2.20, +4.41], t 1.2 | +1.18pp [−2.16, +4.52] | −0.08pp [−3.00, +2.84], t −0.1 | +0.82pp [−2.50, +4.13], t 0.9 | 0 / 0 |
|
|
4366
|
+
| `gkmin` | −0.45pp [−3.80, +2.89], t −0.5 | −1.65pp [−5.12, +1.82] | +1.19pp [−1.87, +4.25], t 1.4 | +0.39pp [−3.06, +3.85], t 0.4 | 0 / 0 |
|
|
4367
|
+
|
|
4368
|
+
`shaped` is the only core with a lever on the shipped engine, and the fix is what
|
|
4369
|
+
takes it away — with one honest limit on how far that can be pushed.
|
|
4370
|
+
|
|
4371
|
+
What is RESOLVED: the paired engine contrast. The best permutation's +5.20pp,
|
|
4372
|
+
which put a FW (t28) in the slot a DF (t12) held, reads +0.75pp on the fixed
|
|
4373
|
+
engine, and the shipped−fixed difference over the same permutation and the same
|
|
4374
|
+
matches is **+4.44pp [+0.13, +8.74], t 3.7** — a resolved, corrected difference,
|
|
4375
|
+
so the drop is the fix and not noise. The sweep says the same thing with nine
|
|
4376
|
+
paired swaps instead of one permutation: the four significant ones (slots 7–10,
|
|
4377
|
+
+5.19 to +7.02pp, an OMF or FW into the first slot) read +0.46 to −0.31pp fixed,
|
|
4378
|
+
every one of their contrasts significant (t 4.3 to 6.5), and the range of the
|
|
4379
|
+
whole sweep collapses from 7.02pp to 1.71pp — 0 of 9 significant.
|
|
4380
|
+
|
|
4381
|
+
What that one column does NOT resolve: the residual on the SHIPPED-selected
|
|
4382
|
+
permutation. +0.76pp carries [−3.97, +5.50], whose upper bound still reaches
|
|
4383
|
+
past the 5pp gate, so that reading alone cannot certify the leftover as *below*
|
|
4384
|
+
it — non-significance is not equivalence, and the probe says `UNDECIDED vs the
|
|
4385
|
+
gate` there rather than `REMOVED`.
|
|
4386
|
+
|
|
4387
|
+
What answers the question it was actually asked: give the FIXED engine its own
|
|
4388
|
+
search. A permutation chosen against the shipped engine is not what a manager
|
|
4389
|
+
optimising against the fixed one would ever pick, so the shipped-selected winner
|
|
4390
|
+
cannot speak to whether a lever remains. Under an independent 120-permutation
|
|
4391
|
+
search on the fixed engine, **every core comes in below the gate**: `shaped`
|
|
4392
|
+
+0.02pp [−4.60, +4.65], `flat` −0.21pp, `gkheavy` +0.82pp, `gkmin` +0.39pp, none
|
|
4393
|
+
significant (|t| ≤ 0.9). That is an equivalence result at the gate, on all four
|
|
4394
|
+
cores, for the engine that ships after this fix. The sweep says the same with
|
|
4395
|
+
nine paired swaps: 0 of 9 significant on every core.
|
|
4396
|
+
|
|
4397
|
+
`flat` shows the lever's other face: moving its OMF into slot 1 is a LOSS of
|
|
4398
|
+
3.48pp (t −4.5) on the shipped engine and +0.30pp on the fixed one, contrast
|
|
4399
|
+
−3.78pp (t −4.9). The fallback was hurting managers who put the wrong player
|
|
4400
|
+
first as much as it rewarded the right one.
|
|
4401
|
+
|
|
4402
|
+
The fixed engine does not create a lever on any core: 0 of 36 sweep swaps are
|
|
4403
|
+
significant across the four cores, no fixed-engine gain clears the gate in
|
|
4404
|
+
either direction, and its own independent search finds nothing (above).
|
|
4405
|
+
One isolated contrast stays marked: `gkheavy` slot 10, −2.77pp (t −3.6), with
|
|
4406
|
+
neither engine's own swap significant (−1.49pp t −1.8 shipped, +1.28pp t 1.7
|
|
4407
|
+
fixed) — a resolved difference between two unresolved readings, reported and not
|
|
4408
|
+
read as a lever. `gkmin` slot 5 (−2.27pp, t −3.5) cleared the old m=88 bar and
|
|
4409
|
+
does not clear the m=132 one; it is no longer marked.
|
|
4410
|
+
|
|
4411
|
+
Who presses under the fix, from the revived weights, on a 4-3-3: FW 36%, DMF
|
|
4412
|
+
19%, OMF 11%, DF 34% (on `gkmin`'s 4-4-2: 24/20/22/34). Under the shipped
|
|
4413
|
+
engine: the first slot, a DF in all four cores, 100% of the time.
|
|
4414
|
+
|
|
4415
|
+
Base shift for the record: `shaped` +2.75pp [−0.32, +5.81], `flat` −1.20, `gkheavy`
|
|
4416
|
+
−0.57, `gkmin` −2.64pp [−4.94, −0.34]. The fix moves levels between cores by a
|
|
4417
|
+
few points, as any change to who presses must.
|
|
4418
|
+
|
|
4419
|
+
### What it means
|
|
4420
|
+
|
|
4421
|
+
- **The +5.7pp of the depth-cap note was the fallback.** Its clone ablation
|
|
4422
|
+
withdrew the candidate because it held POSITION fixed and varied only
|
|
4423
|
+
attributes — but what the fallback delivers into the first slot is a player
|
|
4424
|
+
whose `getPoint` branch depends on position, so a same-position swap could
|
|
4425
|
+
not see it. Disabling the path and re-running the same permutations, which
|
|
4426
|
+
that note said was needed, is what this probe did.
|
|
4427
|
+
- **The lever is gone once the fix ships**, so the Skill records nothing about
|
|
4428
|
+
slot order: a lever that no longer exists must not be documented as one.
|
|
4429
|
+
- **Determinism** (P5): completed matches are persisted as events and do not
|
|
4430
|
+
change; the live stream and the replay both read those persisted events, so
|
|
4431
|
+
nothing about a match is observable before it is persisted. Every future
|
|
4432
|
+
match changes — a zone press happens about once a match (1.07 on the test
|
|
4433
|
+
teams, up to 7), and the real draw consumes RNG the fallback did not, so every
|
|
4434
|
+
later draw in that match shifts. The scheduler is one Vercel Cron invocation
|
|
4435
|
+
a minute, not a fleet of replicas: a deploy lands between ticks, and the only
|
|
4436
|
+
match that can straddle it is one whose invocation died mid-tick and whose
|
|
4437
|
+
5-minute lease is then reclaimed by a tick running the new build. That match
|
|
4438
|
+
is simulated once, by the new build, from the stored snapshot and seed — the
|
|
4439
|
+
old build never produced a result for it. Determinism is per build; every
|
|
4440
|
+
engine change (#737, #786, #794 before this one) has made such a boundary, and
|
|
4441
|
+
an engine-replay verification whose window spans a deploy sees it as an
|
|
4442
|
+
ENGINE boundary.
|
|
4443
|
+
- **Workload tally** (F-1/F-2): predicate D — actor plus responder minus
|
|
4444
|
+
zero-weight fallbacks — is unchanged in meaning, and on the shipped engine
|
|
4445
|
+
every fallback was a zone-press engagement, so D excluded zone presses
|
|
4446
|
+
entirely. Now it counts them: on the test teams that is **+0.10 engagements
|
|
4447
|
+
per player-match, +6.1%** of the tally (5.75% of the fixed engine's D). The
|
|
4448
|
+
F-2 curve is `cond = 5 + a − b·L/(L+L₀)` with `b = 0.4914`, `L₀ = 59.03`; a
|
|
4449
|
+
6.1% inflation of the load L moves condition by at most **0.0075** points
|
|
4450
|
+
(at L = L₀; 0.0006 at the neutral load 1.146, 0.0047 at the p95 14.76) — an
|
|
4451
|
+
order of magnitude below the 0.5 band step and far below anything
|
|
4452
|
+
`cond-effect.mts` could detect. `PLAYER_WORKLOAD_VERSION` is therefore NOT
|
|
4453
|
+
bumped: the version is a hard filter in the form store, so a bump erases
|
|
4454
|
+
every accumulated load league-wide — a reset three orders of magnitude larger
|
|
4455
|
+
than the drift it would prevent. The boundary is recorded here instead, and
|
|
4456
|
+
`L_neutral`/`L₀` are re-measured by `engagement-load.mts` on the first
|
|
4457
|
+
production window after the deploy (C-2 follow-up).
|
|
4458
|
+
- **Open sub-decision, recorded**: the responder. The original appears to have
|
|
4459
|
+
skipped the defensive role at ZP entirely (port comment at `game.pl:1924`);
|
|
4460
|
+
drawing it from the same offence column is the smallest change that invents
|
|
4461
|
+
nothing, and "no responder, team term only" was not adopted because the exact
|
|
4462
|
+
original expression cannot be recovered.
|
|
4463
|
+
|
|
4464
|
+
5,648,400 matches in about a minute. Whole run: `zp-selector.mts`.
|