4 commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
9acd4f8865 |
Queue the browser gates, and let them serve their own tree
Two problems, one change. LOAD. Seven agents each running a wave put 7+ chrome-headless renders on one box; measured today it reached load 47 with 8GB of swap, and a browser gate that is swapping measures the swap, not the product. The wave runner now holds browser steps while 1-min load is at or above LOAD_MAX (12) and takes a coarse flock before each one, so they queue instead of dogpiling. Thresholds, cadence and the 20-minute cap are bundler-3's wait-for-quiet.sh verbatim, and BROWSER_GATE_LOCK selects the rendezvous, so every agent lands on one lock whichever entry point they use. Static gates are untouched: in gates:post that is 38 free, 4 queued. The load wait is taken ONCE per wave, not once per gate. Per-step it multiplied the same hold by the number of browser gates — an hour of a wave doing nothing, which is how a load fix becomes a reason to stop running gates. The flock is what serializes; the wait only decides when to join the queue. Browser steps are identified from the gate FILE (a playwright import), not a hand-kept list that goes stale the first time someone adds a gate — the one missing from such a list is exactly the one that rejoins the dogpile. `verify` is caught too: it imports no playwright itself but spawns three gates that render, and it already marks them browser:true, so that declaration is honoured rather than duplicated. COVERAGE. Yesterday's guard made check:provider-switch and check:packet-browser SKIP in every wave, because their default ports (4173, 4898) belong to other worktrees on this machine. Skipping was honest but a gate that skips every time is a gate nobody runs, so on a mismatch they now start a short-lived server over THIS checkout and measure that instead — the point was never the port, it was being able to prove which build answered. MEASURED: a served tree whose manifest differs by one key but has all the same pages -> "serves a DIFFERENT build", then "serving this checkout on :28384 instead", then a real verdict (16 -> 5 mapbox requests). packet-browser likewise, once it re-navigates to the new origin — a dynamic import across origins is refused by a plain static server, which cost one failed run to learn. gates:post 40/42, the only skips being the two that genuinely have no input (packets-all, zone-census); it was 4 before this. The lock path default is product-named. The shared file several shells export carries an internal code name, and check:no-codename refuses to let a repo we hand over carry one — it caught this commit's first draft. |
||
|
|
6602cd1399 |
Browser gates: prove the server is THIS build before believing it
Five gates took their measurement from whatever answered a default localhost port. On this machine that port belongs to whichever worktree started first: :4173 is wt-packet's server, :4898 is its repo root. Measured today — an hour of probing reported on a build that was not on disk here, and the mistake was only caught because a marker string was in the file and absent from the response. "Answers 200" and "is serving this checkout" are different questions, and only the second one licenses a verdict. _serves-this-tree.mjs already asked it (it exists because the gospel-resources gate hit this and spent three runs reporting on the wrong tree) but only three callers used it. Wired into the five that measure a served page and had no such check: check-provider-switch request tally per host — the wrong tree's tally check-maplibre-layer-drops silent layer drops — invisible by nature check-filter-width-stable width divergence — would accuse untouched CSS check-facet-changes-map data flow on facet change check-packet-browser imports the renderer FROM the server Only a genuine MISMATCH skips. "No manifest to compare" is a different precondition (an unbuilt checkout) that each gate already speaks for, and turning that into a skip would silence these on the builds they should run on. A mismatch exits 0, like the unreachable case, because it is a precondition and not a product finding — but it prints which, so nobody reads it as a pass. CONTROLS, each fired, per gate: correct server -> PASS with a real number (provider-switch 19 -> 5 mapbox requests, drops 17/17, filter-width identical, facet 2107 -> 1209 dots, packet-browser headings match); a served tree whose manifest differs by one key -> SKIP naming "serves a DIFFERENT build"; no server -> the pre-existing unreachable SKIP, unchanged. One correction found by running it rather than by reading it: the first wiring passed the LEAF PAGE URL where the helper wants the ORIGIN, so it looked for the manifest under the page's own path and skipped every run for the wrong reason. node --check cannot see that; only running both controls can. KNOWN COST, not hidden: in a wave with no server of this tree running, check:provider-switch and check:packet-browser now SKIP where they used to report a green about another worktree. That is the honest reading, not a regression, and the runner prints "evaluated nothing" for them. Next increment is to let these gates serve this checkout themselves so they measure again. |
||
|
|
baf691e8cf |
provider-switch gate: run by default, instead of only when someone types a URL
Some checks are pending
build-gate / build (push) Waiting to run
check:provider-switch is a good gate — it counts requests BY HOST rather than reading window globals (which stay defined after a swap), and it allows exactly the api.mapbox.com URLs the generated leaf declares in its own head, so a half-fix at 18 requests cannot pass. It had a package.json entry and was in no wave, because it REQUIRED a URL argument and exited 2 without one. So it only ever ran when somebody typed a URL — the same present-but-never-executed shape check:packets-all had before it was given a fixture. Wiring it as-is would have turned every server-less build red rather than silently green, which is the less common half of that failure. It now defaults to the upg-100 leaf and SKIPs in the form the wave runner recognises, so the skip is counted and named instead of grading as a pass or an error. gates:post 36 -> 37, README re-synced. Verified both ways: 37/37 with a server, and 27/37 passed / 6 SKIPPED on a fresh checkout with none. Found while re-verifying BUG-UPG100-IGNORES-THE-PROVIDER-SWITCH from scratch rather than trusting its done status. The card holds: ?provider=maplibre drops Mapbox traffic 19 -> 5 on the upg-100 leaf, and all 5 are the page's own declared preloads, so zero runtime calls remain. The same run independently reproduced the four residual URLs in BUG-LEAF-PAGES-PRELOAD-MAPBOX-EVEN-UNDER- MAPLIBRE, which stays untaken — its fix is in generate-tree, the tree verb bundler-1 owns. When those preloads go, this gate's allowance drops to 0 and it holds the new floor with no edit. |
||
|
|
e1553df458 |
test(provider): ?provider=maplibre must swap the ENGINE, measured by request host
Some checks are pending
build-gate / build (push) Waiting to run
Gates BUG-UPG100-IGNORES-THE-PROVIDER-SWITCH. my-upg-100-list builds its map RAW with `new gl.Map` instead of going through useMapInstance, so the page-level switch — which resolves inside that composable — could not reach it. The card measured 19 requests to api.mapbox.com at ?provider=maplibre while five sibling leaves swapped cleanly. ★ IT COUNTS NETWORK REQUESTS BY HOST, not globals. `window.mapboxgl` can be present because the leaf page preloads it while the map is actually DRAWN by maplibre, and the reverse is equally possible. What the switch exists for is not loading a proprietary engine and not calling its servers, and only the request log shows that. The allowance is DERIVED from the leaf's own HTML — count the distinct api.mapbox.com urls the generated page declares, plus one for a stylesheet that gets fetched twice — rather than hardcoded. Asserting merely "fewer than the default" would pass a half-fix at 18 of 19; hardcoding 5 would pass a leaf that preloads 4 and leaks 1 runtime call. ★ THE GATE'S OWN FIRST VERSION MEASURED NOTHING AND PASSED. `const URL = process.argv[2]` shadowed the global URL constructor, so every `new URL(request.url())` threw, the host tally stayed empty, and it cheerfully reported "0 mapbox requests" on a page making 19. It now names the variable LEAF, counts what it could not parse, and FAILS if the default run records no requests at all — because a silently empty tally is indistinguishable from success. Passing on three leaves today: upg-100-list 19 -> 5, doxa-simple-map 21 -> 4, countries-map 24 -> 4, with every residual being the page's own <link>/<script> preloads. Confirmed to fail when the allowance is tightened by one. |