browser-broker 0.2.0 → 0.4.0
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/.env.example +0 -17
- package/README.md +14 -14
- package/dist/package.json +1 -2
- package/dist/src/adapter/conformance/cases.js +138 -1
- package/dist/src/adapter/conformance/run.js +135 -0
- package/dist/src/browser/fake.js +53 -1
- package/dist/src/browser/real.js +13 -31
- package/dist/src/capture/tiers.js +53 -0
- package/dist/src/cli/commands.js +5 -0
- package/dist/src/cli/reconcile-command.js +68 -17
- package/dist/src/config/environment.js +0 -44
- package/dist/src/service/browser-session.js +81 -8
- package/dist/src/service/comparison.js +23 -5
- package/dist/src/service/operations/pages.js +85 -2
- package/dist/src/tool/session.js +96 -0
- package/dist/src/tool/tools.js +9 -4
- package/package.json +1 -2
- package/RELEASES.md +0 -255
package/RELEASES.md
DELETED
|
@@ -1,255 +0,0 @@
|
|
|
1
|
-
# Release notes
|
|
2
|
-
|
|
3
|
-
**What changes between versions, and specifically what changes *behaviour* on an installation that
|
|
4
|
-
sets nothing.**
|
|
5
|
-
|
|
6
|
-
That second half is the reason this file exists rather than the commit log being enough. A new
|
|
7
|
-
setting with a neutral default is not news: an installation that does not set it behaves exactly as
|
|
8
|
-
before. **A changed default is news**, because it moves an installation that has taken no action and
|
|
9
|
-
made no decision. `docs/plans/DECISIONS.md` §6.3 puts a changed default here rather than in a quiet
|
|
10
|
-
edit for that reason.
|
|
11
|
-
|
|
12
|
-
Entries are newest first. Each names what moved, what an installation has to do about it, and what
|
|
13
|
-
happens if it does nothing.
|
|
14
|
-
|
|
15
|
-
---
|
|
16
|
-
|
|
17
|
-
## 0.2.0
|
|
18
|
-
|
|
19
|
-
### ⚠ Behaviour change: `browser_status` asks whether the browser is still there
|
|
20
|
-
|
|
21
|
-
**What moved.** Liveness was derived from rows and a clock. `browser_status` now asks the operating
|
|
22
|
-
system whether the browser process is still answering, and a session that has died is let go, so the
|
|
23
|
-
next acquisition relaunches rather than handing back a dead one.
|
|
24
|
-
|
|
25
|
-
**Why this is a behaviour change and not a new check.** A lease whose browser had died reported
|
|
26
|
-
`active`, with its expiry advancing, and no sequence of calls from the tool surface could recover it:
|
|
27
|
-
releasing and reclaiming reached the same settled session, because the provider memoised it for the
|
|
28
|
-
life of the process. The lease looked healthy from every angle a caller could see, and every page
|
|
29
|
-
call on it failed.
|
|
30
|
-
|
|
31
|
-
**What an installation has to do.** Nothing.
|
|
32
|
-
|
|
33
|
-
**If it does nothing:** `browser_status` may report a browser gone where it reported `active`. **That
|
|
34
|
-
is the check working, not a new fault appearing** — the browser was already gone, and the report is
|
|
35
|
-
what changed.
|
|
36
|
-
|
|
37
|
-
**The discriminator is load-bearing, and worth knowing about.** A row that says `running` while
|
|
38
|
-
nothing answers is a browser that died; a row that says `stopped` never started. Acquisition is lazy,
|
|
39
|
-
so a freshly granted lease on a machine with no browser installed is the ordinary case, not an error
|
|
40
|
-
— probing without that distinction reports those leases as expired.
|
|
41
|
-
|
|
42
|
-
### A claim says when a browser's tabs are stranded
|
|
43
|
-
|
|
44
|
-
**What moved.** Three reports about tabs stranded mid-close:
|
|
45
|
-
|
|
46
|
-
- **A grant now carries the count**, from the same query and the same instant. A browser holding a
|
|
47
|
-
backlog of tabs left by sessions killed mid-lease can grant a lease that cannot be used: the claim
|
|
48
|
-
succeeds and every navigate on it fails. Five consecutive claims were granted against such a
|
|
49
|
-
backlog before anything said so.
|
|
50
|
-
- **`broker doctor` splits its stranded count per browser** rather than reporting one total, so
|
|
51
|
-
clearing one browser moves the number it is judged by.
|
|
52
|
-
- **`broker reconcile` says when the tab blocking it belongs to the caller's own lease**, given a
|
|
53
|
-
`--session-id` to know it by.
|
|
54
|
-
|
|
55
|
-
**What an installation has to do.** Nothing. The count rides on a grant that is genuinely
|
|
56
|
-
granted — capacity was taken and the lease is active — so this is a note on a successful response
|
|
57
|
-
rather than a refusal, and it is absent rather than zero when there is no backlog.
|
|
58
|
-
|
|
59
|
-
### Command-line help lists the flags a command is refused for omitting, and an unknown flag is refused
|
|
60
|
-
|
|
61
|
-
**What moved.** `broker claim --help` documents `--session-id` and `--purpose`, the two flags a claim
|
|
62
|
-
is refused by name for omitting, and `broker reconcile --help` documents its optional `--session-id`.
|
|
63
|
-
A help text listing three optional flags and neither required one teaches a reader how to call the
|
|
64
|
-
command unsuccessfully.
|
|
65
|
-
|
|
66
|
-
An unknown flag on `snapshot`, `events` or `reconcile` is refused, naming the flag and the accepted
|
|
67
|
-
set, rather than being accepted and discarded.
|
|
68
|
-
|
|
69
|
-
**What an installation has to do.** Nothing. A caller passing correct flags is unaffected.
|
|
70
|
-
|
|
71
|
-
**The refusal's reach is narrower than the help fix, and worth stating plainly:** it covers those
|
|
72
|
-
three commands. `claim` and the other operation commands parse their arguments by a different route,
|
|
73
|
-
so `broker claim --session x` still does not name the typo. The completeness gate covering the
|
|
74
|
-
documented commands is a hand-written list.
|
|
75
|
-
|
|
76
|
-
### `act emulate` says how long its effect lasts
|
|
77
|
-
|
|
78
|
-
**What moved.** An `emulate` result carries `emulationScope`, naming the bound the preference lives
|
|
79
|
-
within and the path that works: emulate and capture within one invocation, or use the tool surface,
|
|
80
|
-
where one connection spans the calls.
|
|
81
|
-
|
|
82
|
-
The preference is scoped to the connection that set it — the tab survives and the emulation binding
|
|
83
|
-
does not — so an emulate driven from a separate invocation than the capture that reads it returns
|
|
84
|
-
`accepted` and changes nothing on the page. A reviewer checking dark mode that way gets a clean
|
|
85
|
-
result and a light screenshot. The harm is the silence rather than the impersistence.
|
|
86
|
-
|
|
87
|
-
**What an installation has to do.** Nothing; the field is additive. `pageDriven` is unchanged and
|
|
88
|
-
still reports `true` here, because a browser genuinely was reached.
|
|
89
|
-
|
|
90
|
-
### `browser_capture` can ask for a higher-resolution tier
|
|
91
|
-
|
|
92
|
-
**What moved.** `browser_capture` takes `tier` — `"detail"` or `"max"` — and `reason` is bounded at 8
|
|
93
|
-
to 200 characters and required alongside `tier="max"`. The default has no name and is what passing
|
|
94
|
-
nothing gives you. A new refusal, `capture.tier_known`, names both accepted words when a tier is not
|
|
95
|
-
one of them.
|
|
96
|
-
|
|
97
|
-
The ladder was built end to end, and the pipeline refuses the top rung without a written reason,
|
|
98
|
-
while no surface could populate either field — so the escalation rollup could only ever read as
|
|
99
|
-
*nobody escalates*, which is a measurement of the surface rather than of any caller.
|
|
100
|
-
|
|
101
|
-
**What an installation has to do.** Nothing. A capture that names no tier gets the default.
|
|
102
|
-
|
|
103
|
-
### ⚠ Behaviour change: `wait_ms` on a navigate is now honoured
|
|
104
|
-
|
|
105
|
-
**What moved.** `browser_navigate` has advertised a `wait_ms` argument for some time, typed,
|
|
106
|
-
documented and accepted without complaint. **Nothing read it.** It now reaches the browser as the
|
|
107
|
-
navigation's timeout, and it is bounded by the lease: a wait longer than the lease can live is
|
|
108
|
-
refused, and the refusal names the accepted range rather than quietly clamping the value.
|
|
109
|
-
|
|
110
|
-
**Why this is a behaviour change and not a new feature.** An installation that has set nothing is
|
|
111
|
-
unaffected — but a *caller* that was already passing `wait_ms`, exactly as the schema invited, was
|
|
112
|
-
having it discarded and now is not. Nothing about that caller's code changes and its behaviour does.
|
|
113
|
-
|
|
114
|
-
**What an installation has to do.** Nothing. A caller passing no wait is unaffected: the argument is
|
|
115
|
-
omitted rather than defaulted, so the browser's own default still applies, and this service does not
|
|
116
|
-
invent a number the browser library owns.
|
|
117
|
-
|
|
118
|
-
**Worth knowing before relying on it:** the wait bounds the **load**, and does not cover work the
|
|
119
|
-
page starts afterwards. A canvas or a lazily-loaded region can still be unfinished when the call
|
|
120
|
-
returns, so two captures differing only in this argument tell you nothing about how long the page
|
|
121
|
-
was given to settle — see `browser_capture` on how to tell. An inert argument is worse than a
|
|
122
|
-
missing one precisely because a caller draws conclusions from it, and that is the conclusion most
|
|
123
|
-
easily drawn here.
|
|
124
|
-
|
|
125
|
-
### Dialog and form-filling become reachable from the command line, and a contradictory answer is refused
|
|
126
|
-
|
|
127
|
-
**What moved.** Two things a command-line caller had no way to do at all:
|
|
128
|
-
|
|
129
|
-
- `act dialog` and `act fill_form` take nested arguments that the flat command-line parser could not
|
|
130
|
-
produce, so **no argument a person could type would ever parse**. They now assemble from ordinary
|
|
131
|
-
flags — `--accept` / `--dismiss`, `--prompt-text`, and a repeatable `--field`.
|
|
132
|
-
- **A contradictory dialog answer is now refused instead of resolved silently.** Asking to accept
|
|
133
|
-
and dismiss the same dialog used to take whichever the code read first. A caller answering a
|
|
134
|
-
destructive `confirm()` deserves a refusal rather than a coin flip, and now gets one.
|
|
135
|
-
|
|
136
|
-
**What an installation has to do.** Nothing. Callers already sending a single, coherent answer — by
|
|
137
|
-
either surface — are unaffected.
|
|
138
|
-
|
|
139
|
-
### Capture responses point at `compare_to`
|
|
140
|
-
|
|
141
|
-
**What moved.** A capture response now carries a hint naming the comparison it could have made. The
|
|
142
|
-
comparison itself already existed and is roughly two orders of magnitude cheaper than reading a
|
|
143
|
-
screenshot back to answer *did this change* — and in all recorded history it had been used once,
|
|
144
|
-
because nothing pointed at it.
|
|
145
|
-
|
|
146
|
-
**What an installation has to do.** Nothing; the hint is additive. It is listed here because the
|
|
147
|
-
cheapest path through this service was, in practice, unreachable, and a caller that never learned
|
|
148
|
-
the verb existed was not making an informed choice.
|
|
149
|
-
|
|
150
|
-
### Closing a tab is recorded, and the doctor counts what was left behind
|
|
151
|
-
|
|
152
|
-
**What moved.** Tab closes now write their outcome, rows nothing could reach are settled, and
|
|
153
|
-
`broker doctor` reports tabs stranded in `closing`. Without that, a released lease can leave its tab
|
|
154
|
-
open with the record stuck mid-close and **nothing anywhere says so** — a state reachable only by
|
|
155
|
-
looking at the browser.
|
|
156
|
-
|
|
157
|
-
**What an installation has to do.** Nothing. **If it does nothing:** `broker doctor` may now report
|
|
158
|
-
stranded tabs that no check could see before. That is the check working, not a new fault appearing.
|
|
159
|
-
|
|
160
|
-
### The package is published, and it ships compiled JavaScript
|
|
161
|
-
|
|
162
|
-
**What moved.** The service is installable from the registry as `browser-broker`, so a caller can
|
|
163
|
-
spawn it without a checkout. The manifest's `bin` entries now name emitted JavaScript under `dist/`
|
|
164
|
-
rather than the TypeScript sources.
|
|
165
|
-
|
|
166
|
-
**Why the build exists**, given that the development path deliberately has none: **Node refuses to
|
|
167
|
-
strip types from any file under a `node_modules` path**, and an installed package is a directory
|
|
168
|
-
under `node_modules`. A manifest whose `bin` named a `.ts` file would install cleanly and then fail
|
|
169
|
-
on the machine of whoever installed it. There is no flag that changes this. The compiler therefore
|
|
170
|
-
runs once per release rather than on every machine that consumes the package, and `erasableSyntaxOnly`
|
|
171
|
-
stays on so the sources still run unbuilt — the two paths execute the same dialect.
|
|
172
|
-
|
|
173
|
-
**What an installation has to do.** Nothing. A checkout is unaffected: `node src/bin/broker.ts` still
|
|
174
|
-
runs the sources with no build. An installation that would rather not track a checkout can point at
|
|
175
|
-
the package instead, and npm revalidates the version on every spawn:
|
|
176
|
-
|
|
177
|
-
```json
|
|
178
|
-
{ "command": "npx", "args": ["-y", "-p", "browser-broker", "broker-tool"] }
|
|
179
|
-
```
|
|
180
|
-
|
|
181
|
-
The `-p` is not decoration: the package ships two executables and neither is named for the package,
|
|
182
|
-
so `npx browser-broker` cannot choose between them and refuses to run at all.
|
|
183
|
-
|
|
184
|
-
**Worth weighing before switching:** `npx` performs a registry round-trip on every spawn, costing
|
|
185
|
-
seconds where a path on disk costs a fraction of one. It buys an upgrade path, not speed.
|
|
186
|
-
|
|
187
|
-
**One surface changes what it reports.** The tool handshake's `serverInfo.version` was the literal
|
|
188
|
-
`0.0.0` while the package was unversioned, and now reads the manifest — so a client logging it sees
|
|
189
|
-
the released version rather than a placeholder.
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
### The default browser engine is named Edge, but resolving it is not built yet
|
|
193
|
-
|
|
194
|
-
**What moved.** `BROKER_REGULAR_BROWSER_ENGINE` and `BROKER_PRIVATE_BROWSER_ENGINE` default to
|
|
195
|
-
**`msedge`** rather than being unset. `DECISIONS.md` §13i chose Edge as the default *name* because it
|
|
196
|
-
is present on every Windows machine, applying §6.1's *"a fresh install runs with nothing set"* to
|
|
197
|
-
which engine a fresh install prefers.
|
|
198
|
-
|
|
199
|
-
**What this does not do: it does not change which binary launches, and it does not remove the browser
|
|
200
|
-
download step.** Resolving an engine name to an executable path is deliberately not built (§13i) —
|
|
201
|
-
`executablePathForEngine` only looks up a path this process was *given* for that engine, and nothing
|
|
202
|
-
in this repository supplies one. So the launch still falls through to `chromium.executablePath()`
|
|
203
|
-
regardless of which engine is named, and a machine that has never fetched a Chromium build still
|
|
204
|
-
needs to, exactly as before this change. The earlier release note claiming this default removed the
|
|
205
|
-
download step was wrong and is corrected here.
|
|
206
|
-
|
|
207
|
-
**What an installation has to do.** Nothing, either way — the engine setting has no observable effect
|
|
208
|
-
yet. Setting it now is preparation for when per-engine resolution is built, not a way to skip the
|
|
209
|
-
browser fetch:
|
|
210
|
-
|
|
211
|
-
```bash
|
|
212
|
-
BROKER_REGULAR_BROWSER_ENGINE=chrome # chrome | brave | msedge — has no effect on which binary launches
|
|
213
|
-
BROKER_PRIVATE_BROWSER_ENGINE=chrome # accepted and validated, and read by nothing — see below
|
|
214
|
-
```
|
|
215
|
-
|
|
216
|
-
Both are parsed and validated, and an unaccepted value is refused at startup and named — that much is
|
|
217
|
-
finished. **The private variable goes one step less far than the regular one:** one driver serves
|
|
218
|
-
every browser in a process, and only the regular engine is handed to it, so the private value is
|
|
219
|
-
validated and then never read by anything at all. It is not merely ineffective downstream; it has no
|
|
220
|
-
downstream.
|
|
221
|
-
|
|
222
|
-
**If it does nothing:** browsers keep launching under whichever Chromium build `playwright-core`
|
|
223
|
-
resolves, same as before this change. **No profile is signed out by setting an engine**, which an
|
|
224
|
-
earlier note claimed would happen: a profile directory is named for its *browser*, not for an engine,
|
|
225
|
-
so there is no engine-keyed profile to move between and nothing to sign in again.
|
|
226
|
-
`setup.profile_never_destroyed` holds, as it did before. The per-engine profile and sign-in
|
|
227
|
-
consequences described in `DECISIONS.md` §13i are what would follow once resolution is wired, and
|
|
228
|
-
describe nothing that happens now.
|
|
229
|
-
|
|
230
|
-
### Browsers are a configured list, and `browser` on a claim is optional
|
|
231
|
-
|
|
232
|
-
**What moved.** Two things, both reversals of recorded decisions — the argument for each is in
|
|
233
|
-
`DECISIONS.md` §13i:
|
|
234
|
-
|
|
235
|
-
- **The fixed pair of browsers becomes a bounded list per kind**, at most three each, named in
|
|
236
|
-
configuration. A name is what a caller claims by and what its profile directory is called.
|
|
237
|
-
- **`browser` on `browser_claim` becomes optional.** Unstated resolves to the first signed-in
|
|
238
|
-
browser; `regular` or `private` resolves to the first of that kind; a configured name resolves to
|
|
239
|
-
that browser exactly.
|
|
240
|
-
|
|
241
|
-
**What an installation has to do.** Nothing. The defaults name one browser of each kind, `regular`
|
|
242
|
-
and `private`, which is the pair that existed before — so an installation that sets nothing has the
|
|
243
|
-
same two browsers under the same two names, and a caller that states `browser` explicitly is
|
|
244
|
-
unaffected.
|
|
245
|
-
|
|
246
|
-
**Worth reading before configuring more than the default two:** the tab budget counts *tabs*, and
|
|
247
|
-
each browser costs a process **before it holds a single tab**. `BROKER_TAB_BUDGET=15` with six
|
|
248
|
-
browsers is six browser processes, plus up to fifteen tabs, plus six keeper tabs that are not
|
|
249
|
-
counted against the budget at all. `.env.example` states this beside the variables.
|
|
250
|
-
|
|
251
|
-
**One schema step.** The store gains a `kind` column on `browsers` and drops the check constraint
|
|
252
|
-
that limited a browser's name to two literals. It is applied on the next spawn, like every step, and
|
|
253
|
-
the two existing rows are backfilled to their own kinds. **A store stepped by this build is not
|
|
254
|
-
readable by an earlier one**, which is the ordinary direction — a build refuses a store newer than
|
|
255
|
-
itself rather than downgrading it.
|