documentation: the browser guard, and ask the repo rather than grepping
Follow-up to the doc landing in 49, which was written before the guard existed. Adds the guard: every browser gate reaches Playwright through internal/lib/playwright-guarded.mjs and refuses unless browser-slot.sh exported DOXA_BROWSER_SLOT; an unslotted run exits 75 with the command to use, quoted verbatim. And says the slot is a COUNTING SEMAPHORE, not a mutex, with the reason from its own header -- a single lock queued 10-19 deep for hours because the real constraint is memory, ~300-500MB per chrome, not exclusivity. Replaces the grep advice with `bun run browser-gates`. The grep still works and is fine for a quick look, but it is a heuristic over file text: my own count from grepping internal/check-*.mjs said 87 browser gates; the repo's own detector says 97, because browser gates also live in plugin-designs/*/scripts/. Corrected. The authoritative list cannot drift from what is enforced, because check:browser-gates-guarded uses the same detector. One line the guard's header earns and this doc had not stated: being able to launch is not the same as it being yours to launch. The guard stops the accident; it does not hand a newcomer the seat. Testing whether the guard refuses is itself a browser launch. Does NOT claim path-into-node_modules detection: studio has that in landing 50, and it is not in this tree, so the doc does not describe it yet.
This commit is contained in:
parent
a9dfe29200
commit
f2e2509167
1 changed files with 41 additions and 7 deletions
|
|
@ -1,6 +1,6 @@
|
|||
# Which gates need a browser
|
||||
|
||||
There are **238** checks in this repo. **148 run anywhere. 87 need a real browser.** If you are not
|
||||
There are **238** checks in this repo. **97 need a real browser**; the rest run anywhere. If you are not
|
||||
the person who owns the browser seat, that second group is not yours to run — and knowing which is
|
||||
which saves you from a whole class of wrong answer.
|
||||
|
||||
|
|
@ -12,14 +12,16 @@ which saves you from a whole class of wrong answer.
|
|||
|
||||
## Telling them apart
|
||||
|
||||
Open the gate's file and look for one import:
|
||||
**Ask the repo, don't grep:**
|
||||
|
||||
```bash
|
||||
grep -l 'playwright\|chromium' internal/check-*.mjs
|
||||
bun run browser-gates # lists every script that launches a browser
|
||||
```
|
||||
|
||||
If it imports `playwright` or launches `chromium`, it needs a browser. That is the whole test — the
|
||||
name does not tell you. `check:packet-render` sounds like a file check and drives a browser;
|
||||
That is the authoritative answer — the same detector `check:browser-gates-guarded` uses, so it
|
||||
cannot drift from what is enforced. A grep for `playwright|chromium` also works today and is fine
|
||||
for a quick look, but it is a heuristic: it finds files that *mention* the word, and it would miss a
|
||||
file that reached the package by path. The name tells you nothing either. `check:packet-render` sounds like a file check and drives a browser;
|
||||
`check:composites-mount` sounds like it needs one and does not (it mounts every composite through
|
||||
Vite's SSR loader, no browser at all).
|
||||
|
||||
|
|
@ -27,8 +29,8 @@ Vite's SSR loader, no browser at all).
|
|||
|
||||
| | Count |
|
||||
|---|---:|
|
||||
| headless — run these yourself | **148** |
|
||||
| **browser — not yours unless you own the seat** | **87** |
|
||||
| headless — run these yourself | the remainder |
|
||||
| **browser — not yours unless you own the seat** | **97** |
|
||||
| neither (shells out to `bun`/`php`) | 3 — `check:mobile`, `check:wp-embed`, `smoke:playground` |
|
||||
|
||||
The browser group is, broadly: everything that renders a map (`check:map-paints`,
|
||||
|
|
@ -60,6 +62,38 @@ and confusing them is the most common way to report something false:
|
|||
|
||||
---
|
||||
|
||||
## The guard: you cannot launch a browser by accident any more
|
||||
|
||||
The rule above used to be remembered. It is now **enforced**. Every browser gate reaches Playwright
|
||||
through `internal/lib/playwright-guarded.mjs`, which refuses to launch unless
|
||||
`internal/browser-slot.sh` has exported `DOXA_BROWSER_SLOT`:
|
||||
|
||||
```bash
|
||||
internal/browser-slot.sh bun run check:packet-render # the only way to run one
|
||||
```
|
||||
|
||||
Run a browser gate outside the slot and it does not fail — **it exits 75 and tells you the command**:
|
||||
|
||||
```
|
||||
this gate launches a browser. Browsers run only on the browser seat, inside the slot:
|
||||
internal/browser-slot.sh bun run <script> (it exports DOXA_BROWSER_SLOT)
|
||||
NOT MEASURED (exit 75).
|
||||
```
|
||||
|
||||
`check:browser-gates-guarded` fails any repo file that reaches Playwright directly instead of
|
||||
through the guard.
|
||||
|
||||
**The slot is a counting semaphore, not a mutex.** A single lock made every agent's browser proof
|
||||
queue behind one chrome — measured 2026-09-25, the queue sat 10–19 deep for hours. The real
|
||||
constraint is memory (~300–500 MB per headless chrome), not exclusivity, so the slot admits as many
|
||||
browsers as the box can hold and refuses when free memory is below the floor. A slot that is free
|
||||
while the box is out of memory is an invitation to be OOM-killed mid-measurement, which reads as a
|
||||
flaky gate rather than as what it is.
|
||||
|
||||
> **If you are not the browser seat, none of this is your invitation.** The guard stops the accident;
|
||||
> it does not make the run yours to take. Send the command to whoever owns the seat. Testing whether
|
||||
> the guard refuses *is itself a browser launch* — that one has been learned the hard way.
|
||||
|
||||
## ★ Exit 75 means NOT MEASURED. It is not a pass and it is not a failure.
|
||||
|
||||
This is the one that bites hardest, because it looks like success.
|
||||
|
|
|
|||
Loading…
Reference in a new issue