Split application domains and cache player delivery #43

Merged
kristofferopsahl merged 2 commits from fix/open-issues into main 2026-10-15 22:01:06 +02:00
Collaborator

Repeated player requests rebuilt and serialized the complete projection graph, while API, pipeline and browser behavior lived in large mixed modules. This change introduces domain routers, typed build/cache/player stages and explicit ES modules; caches player shaping by published input version; serves a smaller startup summary with complete details on demand; and makes live refresh reuse fresh data without overwriting newer publications.

CSS consolidation preserves the unchanged computed-style baseline. The default player API is byte-identical on the complete 610-player historical benchmark pool. Warm identity serving fell from 236 ms to 6 ms; JSON bytes fell 26% and retained parsed heap 21%. Cold cost was unchanged. Browser readiness did not improve, and opening full detail became slower because it requires another request; the benchmark records these tradeoffs.

Validation:

Merged main 2184143 passed syntax, 2,144 tests / 145 skipped, and wheel checks in CI run 121. All nine closing references below are closed; #33 is the sole remaining open issue.

  • CI repair merged in #42. Implementation commit 06e1db5 passed remote syntax, tests (2,144 passed / 145 skipped) and wheel checks.
  • Final full-cohort pipeline comparison: 667 players, 60 fixtures, 2,364 rows and 133,237 values exactly equal, excluding only build/code stamps; engine calls and seeds match. Frozen inputs, harnesses and reconstruction instructions are preserved in docs/benchmarks/2026-10-15-pipeline-verification.tar.gz.
  • Full unchanged CSS characterization: 8 passed across five tabs and twelve widths. Golden, CSS and render baselines are unchanged.
  • Frontend source contracts: 409 passed / 30 skipped. Graph/version/parser checks: 24 passed.
  • Final combined browser run: 950 passed / 6 failed. Every failure is inherited and has identical original/current geometry: Record tab overflow at 360px, double-round marks at 360/390px, and compare-label/header overflow at 360/390/1600px. Exact measurements are recorded in the browser/CSS plans and benchmark evidence. All six new lazy-detail regressions pass, including delayed replies, retries, coalescing and stale-generation rejection.
  • Independent API/pipeline/module reviews found no remaining regression. Both live-refresh publication race orders have regression coverage.

The #11 score-bank implementation already existed; this corrects its misleading missing-bank message and provenance documentation. #34's actionable fixes already existed and were independently verified. For #33, the preregistered GW4 confirmation already passed and was not rerun. The new returning-injury audit explicitly reports UNMEASURED because historical point-in-time injury flags are absent; #33 remains open.

Closes #7. Closes #8. Closes #11. Closes #22. Closes #23. Closes #24. Closes #25. Closes #26. Closes #34.

Repeated player requests rebuilt and serialized the complete projection graph, while API, pipeline and browser behavior lived in large mixed modules. This change introduces domain routers, typed build/cache/player stages and explicit ES modules; caches player shaping by published input version; serves a smaller startup summary with complete details on demand; and makes live refresh reuse fresh data without overwriting newer publications. CSS consolidation preserves the unchanged computed-style baseline. The default player API is byte-identical on the complete 610-player historical benchmark pool. Warm identity serving fell from 236 ms to 6 ms; JSON bytes fell 26% and retained parsed heap 21%. Cold cost was unchanged. Browser readiness did not improve, and opening full detail became slower because it requires another request; the benchmark records these tradeoffs. Validation: Merged main `2184143` passed syntax, **2,144 tests / 145 skipped**, and wheel checks in [CI run 121](https://git.kristofferopsahl.com/solvreven/FPL/actions/runs/121). All nine closing references below are closed; #33 is the sole remaining open issue. - CI repair merged in #42. Implementation commit `06e1db5` passed remote syntax, tests (**2,144 passed / 145 skipped**) and wheel checks. - Final full-cohort pipeline comparison: **667 players, 60 fixtures, 2,364 rows and 133,237 values exactly equal**, excluding only build/code stamps; engine calls and seeds match. Frozen inputs, harnesses and reconstruction instructions are preserved in `docs/benchmarks/2026-10-15-pipeline-verification.tar.gz`. - Full unchanged CSS characterization: **8 passed** across five tabs and twelve widths. Golden, CSS and render baselines are unchanged. - Frontend source contracts: **409 passed / 30 skipped**. Graph/version/parser checks: **24 passed**. - Final combined browser run: **950 passed / 6 failed**. Every failure is inherited and has identical original/current geometry: Record tab overflow at 360px, double-round marks at 360/390px, and compare-label/header overflow at 360/390/1600px. Exact measurements are recorded in the browser/CSS plans and benchmark evidence. All six new lazy-detail regressions pass, including delayed replies, retries, coalescing and stale-generation rejection. - Independent API/pipeline/module reviews found no remaining regression. Both live-refresh publication race orders have regression coverage. The #11 score-bank implementation already existed; this corrects its misleading missing-bank message and provenance documentation. #34's actionable fixes already existed and were independently verified. For #33, the preregistered GW4 confirmation already passed and was not rerun. The new returning-injury audit explicitly reports UNMEASURED because historical point-in-time injury flags are absent; #33 remains open. Closes #7. Closes #8. Closes #11. Closes #22. Closes #23. Closes #24. Closes #25. Closes #26. Closes #34.
Split application domains and cache player delivery
All checks were successful
CI / syntax (pull_request) Successful in 9s
CI / tests (pull_request) Successful in 2m25s
CI / wheel (pull_request) Successful in 28s
06e1db5838
Record final browser and exact pipeline verification
All checks were successful
CI / syntax (pull_request) Successful in 8s
CI / tests (pull_request) Successful in 2m24s
CI / wheel (pull_request) Successful in 29s
7530e71db1
Owner

The bonus race is ported onto #43's layout and pushed (aaca006, a merge of origin/main at 790fab1 into the race's branch, now fast-forwarded on main).

The race (item 2 of the calculations audit, #31) went live on this machine the morning after #43 landed, so the two met in the merge. #43 moved most of main.py and pipeline.py into new modules. The race's pieces went where #43 put their neighbours:

  • the bonus-race estimator and the season labels went to player_index.py, re-exported by the pipeline facade;
  • the required field went to projection_cache.py;
  • the archive path went to build_stages.load_inputs;
  • the season's fixtures, which mark a club that plays twice in a round, now reach the override route in routes/admin.py and _live_play_prob in routes/squad.py.

test_player_index_boundary's row is reshaped for the new field. The three wiki conflicts were dates only.

Equivalence. On one frozen set of live inputs, the player index built by 88bb0a1 and by aaca006 was identical for all 667 players, and so were the strengths, fixtures, notes and BPS weights.

Three faults on Windows, none visible under CI's UTF-8 Linux, are fixed in 808feaf:

  • tests/web/test_html_sinks.py hands node its program on stdin with text=True and no encoding. Python encoded it in the locale's cp1252, which has no code for html.js's box-drawing characters. The writer thread died, stdin never closed, and node waited for two hours. It names UTF-8 now, with a 60 s timeout so any other stall fails.
  • tests/web/test_frontend_parses.py read the modules with a bare read_text(). modules/fixtures.js and modules/cards.js do not decode in cp1252, which gave three failures. It now uses UTF-8 both ways, with the same timeout.
  • #42's tests/web/test_operator_status.py built a status cache without the race's figures and ran the load check on it, which gave eight errors. The fixture now carries the figures.

A new guard, tests/test_subprocess_text_names_its_encoding.py, fails on any subprocess text call that does not name its encoding. It reads the syntax tree, because a text search survived a cut.

Checks. 8 hand cuts on the merge and 52 cuts from the race's plan retargeted onto the new modules all went red, each on the test it names, as did 3 for the guard and 1 for the status fixture. The full suite in the live checkout after the go-live: 3,262 passed, 0 skipped, 0 failed at 2474892, which carries the port (2026-10-17).

🤖 Generated with Claude Code

**The bonus race is ported onto #43's layout and pushed** (`aaca006`, a merge of `origin/main` at `790fab1` into the race's branch, now fast-forwarded on `main`). The race (item 2 of the calculations audit, #31) went live on this machine the morning after #43 landed, so the two met in the merge. #43 moved most of `main.py` and `pipeline.py` into new modules. The race's pieces went where #43 put their neighbours: - the bonus-race estimator and the season labels went to `player_index.py`, re-exported by the `pipeline` facade; - the required field went to `projection_cache.py`; - the archive path went to `build_stages.load_inputs`; - the season's fixtures, which mark a club that plays twice in a round, now reach the override route in `routes/admin.py` and `_live_play_prob` in `routes/squad.py`. `test_player_index_boundary`'s row is reshaped for the new field. The three wiki conflicts were dates only. **Equivalence.** On one frozen set of live inputs, the player index built by `88bb0a1` and by `aaca006` was identical for all 667 players, and so were the strengths, fixtures, notes and BPS weights. **Three faults on Windows**, none visible under CI's UTF-8 Linux, are fixed in `808feaf`: - `tests/web/test_html_sinks.py` hands node its program on stdin with `text=True` and no encoding. Python encoded it in the locale's cp1252, which has no code for `html.js`'s box-drawing characters. The writer thread died, stdin never closed, and node waited for two hours. It names UTF-8 now, with a 60 s timeout so any other stall fails. - `tests/web/test_frontend_parses.py` read the modules with a bare `read_text()`. `modules/fixtures.js` and `modules/cards.js` do not decode in cp1252, which gave three failures. It now uses UTF-8 both ways, with the same timeout. - #42's `tests/web/test_operator_status.py` built a status cache without the race's figures and ran the load check on it, which gave eight errors. The fixture now carries the figures. A new guard, `tests/test_subprocess_text_names_its_encoding.py`, fails on any subprocess text call that does not name its encoding. It reads the syntax tree, because a text search survived a cut. **Checks.** 8 hand cuts on the merge and 52 cuts from the race's plan retargeted onto the new modules all went red, each on the test it names, as did 3 for the guard and 1 for the status fixture. The full suite in the live checkout after the go-live: **3,262 passed, 0 skipped, 0 failed** at `2474892`, which carries the port (2026-10-17). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Sign in to join this conversation.
No description provided.