browser-broker 0.2.0 → 0.3.1

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/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.