# OpenChrome v1.10.1

Release date: 2026-04-22

## Summary

v1.10.1 is a **patch release** focused on stabilizing the v1.10.0 merge train,
closing CI regressions, and shipping the merged reliability work in a cleaner,
release-ready state.

This release consolidates the post-merge fixes around:

- tenant-aware HTTP session and metric propagation
- explicit cookie-scan partial-result reporting
- listener-failure cleanup and health visibility
- aborted-call accounting for disconnected HTTP clients
- abrupt parent-death cleanup for managed Chrome processes
- CI stability fixes for the new runtime contracts

The primary goal of v1.10.1 is not to introduce a brand-new feature set, but to
ensure the recent lifecycle, tenancy, observability, and shutdown hardening work
is **coherent, merge-safe, and publishable**.

---

## Why this patch release exists

After the v1.10.0 release preparation and the subsequent issue-driven merge
series, the codebase had two important realities:

1. the new fixes materially improved real runtime behavior, and
2. a few CI/test expectations still reflected the pre-fix behavior.

In parallel, additional review surfaced a few follow-up hardening points:

- cookie scan activity ordering still missed some target-indexing paths
- listener-error health retention needed bounded storage
- aborted-call classification needed to propagate into dashboard/activity state
- abrupt-parent-death Chrome cleanup still had a small startup window and a
  PID-file race that needed tightening

v1.10.1 rolls those follow-up fixes together and produces a cleaner release
baseline.

---

## Highlights

### 1. Tenant-aware HTTP execution is now wired through the real runtime path

The HTTP request path now carries bound tenant context deeply enough that:

- tenant-bound HTTP sessions initialize under the correct tenant context
- strict tenant isolation works on ordinary HTTP tool calls for non-default
  tenants
- core tool metrics use the authenticated/bound tenant instead of falling back
  to `unknown`
- `/metrics` now exposes `openchrome_tenant_contexts_active`

This means the recent tenant/isolation work is now reflected not just in helper
functions and partial tests, but in the practical request execution path.

---

### 2. Cookie scanning exposes incomplete work explicitly instead of hiding it

Cookie-source selection no longer needs to collapse all outcomes into a plain
`string | null` model.

New behavior:

- callers can distinguish between complete and partial cookie scans
- partial scans can surface warnings instead of pretending they simply found no
  authenticated page
- cookie-scan ordering now breaks domain-score ties using recent target activity

This makes session-restore behavior easier to reason about and easier to debug
when many tabs or slow targets are involved.

---

### 3. Listener-failure handling is more production-safe and more observable

The listener-failure path now includes:

- explicit zombie-target cleanup/eviction behavior
- listener-error health visibility
- bounded listener-error history retention (minute buckets instead of unbounded
  per-event growth)

This matters both for correctness and for memory stability during error storms:
health reporting now remains bounded in both memory and CPU cost even if many
listener failures happen in a short period.

---

### 4. Disconnected HTTP tool calls are now classified as aborted outcomes

Client disconnects are no longer treated as generic tool failures in the main
accounting path.

v1.10.1 now distinguishes these as true aborted operations across:

- Prometheus metrics
- audit log entries
- dashboard/activity tracking state

This improves operational clarity and prevents disconnect-heavy workloads from
looking like ordinary tool errors.

---

### 5. Abrupt parent death is less likely to leave Chrome behind

Managed Chrome launches now get stronger protection against abrupt parent death
(for example `SIGKILL`, editor/runtime crash, or supervisor kill):

- a detached guardian process watches the parent/child relationship
- the guardian is started earlier in the launch lifecycle
- guardian PID-file cleanup now checks ownership before deleting shared-path
  state
- orphan cleanup uses process-tree semantics instead of killing only the root
  Chrome PID

This reduces the chance of accumulating hidden Chrome, renderer, or utility
processes after abnormal shutdowns.

---

### 6. CI stability is fully restored across the support matrix

The patch release fixes the concrete CI regressions that appeared after the
merge train, and then completes the job so every OS/Node combination in the
matrix (ubuntu, macOS, windows × Node 18, 20, 22) is green for the first time
since the v1.10.x line began landing:

Runtime/test alignment (earlier in the 1.10.1 line):

- tests now understand session-init budget arguments where required
- MCPServer construction remains compatible with lightweight mocks used by tool
  and journal/recording suites
- headed fallback no longer accumulates per-instance process listeners during
  the test matrix
- headed fallback tests no longer confuse guardian process spawning with a
  second Chrome launch

Final CI hotfix wave (PR #643, squash-merged as the last change on the 1.10.1
release line):

- `src/chrome/headed-fallback.ts` no longer trips
  `@typescript-eslint/no-this-alias`. The per-instance cleanup handle that was
  assigned as `activeCleanupTarget = this` has been refactored into a per-
  instance callback (`() => this.shutdown()`) stored as a class property. The
  singleton-style "latest instance owns global cleanup" semantics are
  preserved — identity comparison now runs against the callback, so
  `shutdown()` still self-clears only when it is still the registered owner.
  This was the single blocker that failed the Lint step on every matrix job
  after the v1.10.0 → 1.10.1 merge train and was previously masking every
  downstream test failure on `main`.
- `tests/cli/admin-keys.test.ts` now extracts the `oc_live_*` plaintext via a
  regex rather than asserting `stdout` starts with the token. The in-process
  harness monkey-patches `process.stdout.write`, which is the same hook used
  by Jest's console-capture layer when it renders a captured `console.error`
  block; a leaked `CDPClient.setHeartbeatMode` interval from a prior test in
  the same worker would prepend that decorated block and cause
  `/^oc_live_/` to miss on macOS Node 20/22. The CLI's own token emission is
  unique, so the regex lookup is robust to such capture-noise and does not
  weaken any security assertion.
- `tests/transports/http-abort-on-disconnect.test.ts` raises its inner race
  timeout from 2s to 8s (with a per-test jest timeout of 15s) so the abort
  propagation path (socket close → `req.on('close')` → controller abort) has
  enough headroom on loaded macOS Actions runners. The test still fails fast
  if the propagation genuinely never occurs.
- `tests/utils/process-guardian.test.ts` raises `waitForDead`'s default
  timeout from 4s to 15s, with each test given a 20s jest timeout. Windows
  CI spends several seconds on detached Node cold-start for the guardian
  plus the `taskkill /T /F /PID` round-trip before the child actually exits,
  which deterministically blew past the old budget on all three Node
  versions.
- `tests/transports/http-streamable.test.ts` adds
  `jest.retryTimes(2, { logErrorsBeforeRetry: true })` to absorb the rare
  "socket hang up" observed on ubuntu-20 when the very first SSE request
  lands in the narrow server `listen()` vs. client `connect()` window. A
  true regression still fails all three attempts.

After those fixes the post-merge CI state on `main` went from "all 9 jobs
failing at the Lint step" to "all 9 jobs green from Lint through Run tests".

In short: the runtime behavior, the test expectations, and the cross-platform
CI matrix are now back in alignment end-to-end.

---

## Detailed change areas

### Runtime / lifecycle
- tightened abrupt-parent-death cleanup for managed Chrome
- improved process-tree orphan termination
- guarded PID-file cleanup against stale guardian races

### Multi-tenant HTTP behavior
- propagated request-bound tenant context into real session creation
- ensured tenant-aware metric emission on the actual tool execution path
- exported active tenant BrowserContext gauge via health/metrics

### Cookie/session restore behavior
- introduced structured cookie-scan results
- improved partial-scan diagnostics
- completed recent-activity tracking for additional target-indexing paths

### Observability
- added/solidified aborted-call metrics and audit metadata
- bounded listener health retention with fixed time buckets
- aligned dashboard/activity views with aborted-call classification

### CI / testability
- updated CI-sensitive tests to match current runtime contracts
- removed false assumptions around mock session manager capabilities
- stabilized headed fallback lifecycle tests around the new guardian model
- refactored `HeadedFallbackManager` global-cleanup registration to avoid a
  `no-this-alias` lint error without changing runtime behavior
- hardened admin-keys, abort-on-disconnect, process-guardian, and SSE
  streamable HTTP test files against CI-specific timing and console-capture
  flakes, so every OS/Node combination on the CI matrix is green

---

## Verification performed for v1.10.1

The release line was validated with fresh local verification after the CI fixes.

### Build
- `npm run build`

### CI-targeted regression coverage
- `npx jest --config jest.ci.config.js --runInBand tests/mcp-server.test.ts tests/tools/recording.test.ts tests/tools/journal.test.ts tests/headed/headed-fallback-manager.test.ts`

### Targeted functional/regression suites
- tenant/session/metrics/auth suites
- cookie scan explicit-result suites
- listener cleanup / health reporting suites
- abort accounting / audit suites
- guardian / PID cleanup suites

### High-level final release verification
- recent issue-driven PR train merged into `develop`
- `develop` merged into `main`
- final release state built again from `main`
- post-merge CI hotfix PR #643 squash-merged into `main` (commit `5d54ec1`),
  taking the cross-platform CI matrix from red to green in one shot
- `main` CI run `24781397898` recorded as the first all-green build on the
  1.10.x line (9/9 jobs passing Lint and Run tests)

---

## Operator-impact summary

If you are upgrading from v1.10.0 to v1.10.1, the most important practical
improvements are:

- better safety around orphaned Chrome after abnormal shutdowns
- more trustworthy tenant-aware metrics for authenticated HTTP calls
- clearer cookie-restore behavior when scans are incomplete
- cleaner distinction between true tool failures and client disconnect aborts
- better bounded health telemetry during listener error storms

---

## Compatibility notes

v1.10.1 is intended as a backward-compatible patch release.

Notable compatibility posture:

- legacy wrapper APIs such as `findAuthenticatedPageTargetId()` remain in place
- the newer structured cookie-scan API is additive
- tenant-aware behavior is improved in the real HTTP path without removing
  single-user/local compatibility paths
- dashboard/activity semantics now expose aborted operations more accurately,
  which may slightly change how disconnect-heavy sessions appear operationally

---

## Known limits / follow-up candidates

v1.10.1 improves the main failure modes discussed above, but it does not claim
that all long-running resource issues are permanently solved.

Areas still worth deeper follow-up include:

- long-duration soak tests for memory growth under real interactive workloads
- deeper per-tool abort cleanup coverage beyond the currently hardened hot paths
- broader headed fallback live-environment validation on every supported OS
- production-like stress testing for tenant-heavy and tab-heavy scenarios

---

## Upgrade recommendation

**Recommended upgrade:** yes.

If you are already on the recent v1.10.x line, v1.10.1 is the safer release to
run because it packages the post-merge fixes, closes the discovered CI gaps, and
ships the merged reliability work in a more stable release state.
