v0.53.1

feder-cr/invisible_dotsv0.53.1Sep 14, 2026by github-actions[bot]

Upgrading?

AI Summary

This release fixes a critical bug where externally killed browser processes were incorrectly reported as running, resulting in stale UI states. It refines logic for handling dead targets across `Work.gone()`, `listing`, and `StealthSession` to accurately reflect process status.

Key Highlights

  • Fixed incorrect reporting of dead browsers where processes killed externally were still listed as running.
  • Renamed `StealthSession.is_alive` to `is_usable` to accurately reflect its local limitations.
  • Updated `Work.gone(role)` and its callers (`session`, `acting`, `status`) to correctly handle `TargetClosedError`.
  • Improved `swallow()` logic to distinguish between mid-navigation failures and closed target errors.
  • Added engine tests to verify process death handling and the order of events.

Breaking Changes

  • Renamed `StealthSession.is_alive` to `is_usable`.

Full Release Notes

Writing the engine test that 0.53.0 was missing - kill Firefox under the
server and check the sentence a model acts on - found that half of it was
not true. Measured against firefox-30, with the process ended from
outside: `is_connected()` answers true for at least six seconds, and
`page.url` answers from cache the whole time. Nothing local can see a
process that is gone. What sees it is the first round trip, which raises
TargetClosedError since wrapper 0.15.0 - `page.title()` and
`context.new_page()` both.

So a browser whose engine had been killed answered `browser_status` with
the identity and the page, as though somebody were browsing, and
`browser_list` listed it as running. The live panes draw that listing:
a pane over a browser that no longer exists is the frozen picture of
[B202], one layer up.

Fixed where the fact is one:

- `swallow(why, unless=...)` names the failures a silence is not for.
  `describe_pages` swallows a title a page mid-navigation will not give
  and lets a closed target out, because that is the browser being gone.
  The comment beside it says which of the two fields is cached and which
  is the round trip.
- `Work.gone(role)` is the one place that forgets the browser and
  composes the sentence. Three callers notice: `session` locally,
  `acting` under an action, `status` under the question.
- `listing` drops a browser whose round trip says it is gone instead of
  reporting it as running; `status` answers the sentence instead of the
  identity it still holds in memory.
- `StealthSession.is_alive` is `is_usable`, with the measurement in its
  docstring: the old name promised what no local question can answer,
  and it is what made me write a known-bad that does not happen.

Two engine tests, one per path, because a killed process reaches them in
a definite order: an action raises the closed target (the aliveness check
does not fire first), and the status is what holds the other path. They
kill only the pids born after their own launch.

Six mutations, six killed: acting re-raising; the round trip swallowed
again; the status answering anyway; the local check dropped; the listing
keeping the row; the status reporting the identity.

Related Repositories