From 3dbb256796cf3c99e687c4622c255f9dca7f8f96 Mon Sep 17 00:00:00 2001 From: Andrei Vershinin Date: Sat, 17 Oct 2026 14:08:13 +0000 Subject: [PATCH] docs(browse): /health liveness vs active-tab responsiveness (#3247) BROWSER.md's busy-vs-dead lifecycle note, ARCHITECTURE.md's daemon model and the REMOTE_BROWSER_ACCESS /health reference now say that `status` is daemon liveness, that `activeTab` reports the active tab separately, and which commands keep working while a tab is busy. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01Wb6Wntntmwau19fSuSbuaL --- ARCHITECTURE.md | 2 +- BROWSER.md | 8 ++++++++ docs/REMOTE_BROWSER_ACCESS.md | 4 +++- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 4ff86a04f..d9e8082cd 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -91,7 +91,7 @@ The server writes `.gstack/browse.json` (atomic write via tmp + rename, mode 0o6 { "pid": 12345, "port": 34567, "token": "uuid-v4", "startedAt": "...", "binaryVersion": "abc123" } ``` -The CLI reads this file to find the server. If the file is missing or the daemon process is dead, the CLI spawns a new server. A process that is alive but not answering `/health` is busy, not dead: the CLI probes for a bounded ~8s, then reports busy with a nonzero exit — only an explicit `--force-restart` kills a live daemon. Process liveness uses signal-0 (`isProcessAlive`, EPERM counts as alive) on every platform, with the health check (GET /health) as the responsiveness signal. Daemon stdout/stderr persists to `/.gstack/browse-daemon.log`. +The CLI reads this file to find the server. If the file is missing or the daemon process is dead, the CLI spawns a new server. A process that is alive but not answering `/health` is busy, not dead: the CLI probes for a bounded ~8s, then reports busy with a nonzero exit — only an explicit `--force-restart` kills a live daemon. Process liveness uses signal-0 (`isProcessAlive`, EPERM counts as alive) on every platform, with the health check (GET /health) as the responsiveness signal. Its `status` covers the daemon and its Chromium connection only; the active tab's main thread is reported separately (`activeTab.responsive`, a probe bounded to 1s), so one page stuck in a long script never makes the CLI refuse commands. Daemon stdout/stderr persists to `/.gstack/browse-daemon.log`. ### Port selection diff --git a/BROWSER.md b/BROWSER.md index 75cd99b9e..8fffd5910 100644 --- a/BROWSER.md +++ b/BROWSER.md @@ -626,6 +626,14 @@ Storage stays intact by default. With explicit approval on a Chromium target, `- | `tab-each [args...]` | Fan out a command across every open tab; returns JSON | | `frame ` | Switch to iframe context (or back to main); clears refs | +**A busy tab is not a busy daemon.** `/health` `status` is daemon liveness +(Chromium connected); the active tab's main thread is reported separately as +`activeTab: { id, responsive }`, probed for at most 1s. While one page is stuck +in a long script, `status`, `tabs`, `tab `, `newtab`, `closetab`, +`state save` and `stop` keep working, and `status` and `tabs` mark the tab as +not responding. A command that needs the stuck tab times out after 30s and +names it, so you can switch away or close it without `--force-restart`. + ### Extraction | Command | Description | diff --git a/docs/REMOTE_BROWSER_ACCESS.md b/docs/REMOTE_BROWSER_ACCESS.md index c5565ba0e..902df6efb 100644 --- a/docs/REMOTE_BROWSER_ACCESS.md +++ b/docs/REMOTE_BROWSER_ACCESS.md @@ -81,7 +81,9 @@ Response: (plain text result of the command) ``` #### GET /health -Server status. No auth required. Returns status, tabs, mode, uptime. +Server status. No auth required. Returns status, activeTab, tabs, mode, uptime. +`status` is daemon liveness; `activeTab` (`{ id, responsive }`, or null with no +page) says whether the active tab's main thread answered within 1s. Never carries a token — extension token bootstrap is `POST /extension-token` (local listener only, validates the pinned `chrome-extension://` Origin and a loopback Host; 403 otherwise). Not reachable over the tunnel (404).