20 KiB
Fast-browser live validation (milestone 1)
extensions/fast-browser/live-validation.ts is an opt-in, local-only integration harness. It starts an HTTP fixture on a random loopback port, creates a unique temporary profile root and CDP lease root, and uses only the typed BrowserSessionManager, BrowserBridge, and runSteps APIs. It never loads normal user profiles, reads existing manual sessions, contacts JEV/provider APIs, or uses external accounts. Literal accessible names are required; the injected decider throws if a semantic decision is attempted.
The fixture's /setup response sets a synthetic, run-unique persistent cookie (Max-Age=3600). Its page makes a bounded /ready?case=setup request; the server resolves readiness only after receiving that cookie, so this is evidence that Chromium processed the seed response—not a manual credential login. The visible setup launch is asserted to have no CDP or headless flags. Automation, when unblocked, reopens the same named profile and verifies retention with a visible postcondition after a literal fill and click. Headless launch, two concurrent isolated named profiles, same-profile contention, closing one while the other remains alive, and cleanup are covered independently.
Integration command
From the repository root, with the existing pinned environment:
node --experimental-strip-types extensions/fast-browser/live-validation.ts
The focused test is opt-in and does not start a browser during ordinary test runs. It currently fails honestly on the visible-close blocker above until the production lifecycle fix lands:
FAST_BROWSER_LIVE=1 node --test --experimental-strip-types \
extensions/fast-browser/live-validation.test.ts
The harness requires /usr/bin/chromium and .pi/fast-browser-demo/venv/bin/python with browser-harness==0.1.13. It uses finite startup, action, readiness, worker, and close deadlines. Cleanup reports owned process/root leftovers rather than terminating anything it did not own.
Validation evidence (2026-09-19)
Runtime versions: Chromium 152.0.7977.75 Arch Linux; Python 3.12.13; browser-harness 0.1.13; Node v22.23.2.
- Blocked: visible manual setup seeded the cookie and
/readyproved it.manager.close()returned, establishing that the manager's tracked Chromium root had exited, but owned GPU descendant PID2870508still carried the temporary profile--user-data-dir;SingletonLockwas still present and the nextmanager.open()rejected the profile. Visible automation was skipped rather than bypassing the lock. The PID is from this disposable test profile only. - Passed: headless launch with bounded literal fill/click and verified visible postcondition.
- Passed: two different headless named profiles concurrently, server-verified cookie/state isolation, same-profile contention rejection, and profile B remaining alive after profile A closed.
- Passed: final owned cleanup; no test processes or temporary root remained.
This is a production lifecycle blocker, not a fixture workaround. The minimal proposed fix is for the session manager to own/wait for the complete Chromium process tree (including GPU/renderer descendants) and confirm the profile lock is gone before releasing a named-profile lease, within its existing bounded close deadline. No production module or package manifest was changed in this milestone.
Controlled Linux rerun (2026-09-20)
The Linux-only PID review was cleared for this controlled run. Preflight used the real /usr/bin/chromium and a real positive version-check PID 3222628 (parent 3222621, not the validator process); the pinned environment remained Python 3.12.13 with browser-harness 0.1.13. No fake process or PID seam, user profile, or external origin was used.
The original M1 command was bounded with timeout -k 5s 180s. Cookie seed/readiness reached the visible setup close boundary, but close failed closed with browser process-group ownership could not be confirmed; preserving session state; automation reuse was skipped. Headless bounded fill/click and concurrent profile isolation/contention passed. Cleanup correctly preserved the uncertain owned root /tmp/fast-browser-live-validation-5HvmBr rather than deleting it. Ten owned Chromium processes remained at capture: 3222696, 3222709, 3222710, 3222712, 3222738, 3222740, 3222752, 3222761, 3222770, 3222771; the root process was 3222696 and GPU descendant 3222738. This run exited 124 from the finite timeout and is evidence for the lifecycle blocker, not a release claim.
The canonical development validator then ran with a bounded 240s timeout. All six cases passed: input-safe read/assert/navigation/reload, popup/no-auto-switch/targeted-read selection, A→B evidence isolation, narrowed peer-origin filtering with base restoration, private PNG+diagnostics capture, and honest provenance handling (Evidence provenance unavailable: false). Its private artifacts lived under a unique /tmp/fast-browser-runtime-live-* root and were removed after owned cleanup; no canonical-run process/root remained. The report artifact is this document; non-Linux/global release clearance remains pending.
Isolated managed-CLI batch (2026-09-20, no rerun after this evidence)
After the independent broker/provenance review cleared, a single sequential native-Linux batch ran with /usr/bin/chromium 152.0.7977.75, Python 3.12.13, browser-harness 0.1.13, and Node v22.23.2. HOME, PI_CODING_AGENT_DIR, XDG config/data/cache/state/runtime roots, TMPDIR, cwd, scenario JSON copies, and report roots were unique and owned. The four loopback ports were unique and all managed servers were started only by scenario-cli; no active harness-test profile, provider key, JEV call, or external origin was used. Synthetic FAST_BROWSER_TEST_PASSWORD=demo-password was local-only and did not appear in reports, stdout, or diagnostics.
The M1 validator reported: manual setup reached cookie readiness and manager.close() returned, but its stale tombstone assertion expected /Unknown browser session/; the manager intentionally returned Browser session is no longer available: session closed. Headless launch and the two-profile case then failed closed on process-group ownership, and the finite command exited 124. The validator assertion is now corrected; the fixture now sends Max-Age=3600, but no post-change browser rerun has been made.
The preserved setup profile from that batch was inspected without launching a browser. The fixture source used at capture time had only Path=/; SameSite=Lax and no Expires or Max-Age, so it created a session cookie rather than a persistent cookie. HTTP receipt is nevertheless proven: /ready?case=setup only resolves after the server sees the exact cookie value, and the M1 run reached that readiness. After the setup close, Default/Cookies was SQLite journal_mode=delete with zero rows, Cookies-journal was zero bytes, no Cookies-wal existed, and SingletonLock was absent; no pending WAL/checkpoint explains the absence. The tracked root had closed and no live process for the named profile remained. Therefore this batch does not prove profile-cookie reuse: the zero row is explained by the old validator fixture's session-cookie attribute, while the independent root-exit-before-first-census lifecycle blocker still prevented the automation phase.
The three managed examples ran from disposable JSON copies. local-form and local-login completed all browser operations, but their reports were failed because owned browser cleanup did not complete before the bounded outer timeout (124). The corrected-port local-popup navigation passed, then its click failed because the example's postcondition (Scenario fixture ready) already held before the click; the worker correctly refused to treat that as proof of a mutation. The intentional failed-assert scenario reached assertion timed_out after a credential fill, retained a real PNG and diagnostics JSON, and produced a nonzero failed report. Its report was mode 0600 in an owned mode-0755 directory; artifact files were 0600 under mode-0700 roots; diagnostics contained password=[redacted] and the synthetic secret was absent.
Every browser and crashpad group left by the timed-out commands was later cleaned only after verifying current PID/start-time/UID/executable/argv/ancestry/PGID/SID ownership against the unique batch roots. All managed ports were closed and no batch-owned Chromium or crashpad process remained. The M1 cleanup proof is retained at /tmp/fast-browser-next-validation-uqoyor/m1-cleanup.json; per-scenario cleanup proofs and the complete summary are under /tmp/fast-browser-next-validation-uqoyor/ (batch-summary.json). Disposable profile and retained-evidence roots remain preserved for diagnosis. This batch is validation evidence, not release clearance.
Follow-up M1 gate rerun (2026-09-20, Linux; CLI batch intentionally not started)
A final ownership review cleared another single native-Linux run with fresh roots, /usr/bin/chromium, the pinned Python environment, isolated HOME/XDG/TMPDIR/cwd/config, and no provider or active user-profile state. The original M1 ran first and was not a full pass: visible manual setup seeded the synthetic cookie and closed cleanly, but visible automation failed its retained-session click with Postcondition not verified; action was not retried. Headless bounded fill/click and the two named-profile isolation/contention cases passed. The validator reported owned cleanup passed and exited 1 solely for the automation case.
Because M1 did not pass, the gate correctly stopped before launching any managed CLI examples or intentional-failure scenario. A post-run /proc census found no Chromium or crashpad process carrying the fresh batch roots, and no subsequent CLI ports existed. The batch root is /tmp/fast-browser-final-validation-ewubUW; its bounded M1 output is m1.stdout. Chromium left only disposable org.chromium.Chromium.* socket directories under the isolated TMPDIR; these contain no live owned process and were preserved rather than removed blindly.
The stale recent-exit tombstone assertion and validator cookie are now corrected in live-validation.ts: closed-session lookup expects session closed, and /setup sends Max-Age=3600. This rerun therefore does not reproduce the earlier session-cookie explanation, but it also does not prove profile-cookie reuse: the named profile was removed after owned cleanup and no retained profile database remained for inspection. The remaining failure is separate from the validator assertion and broker census fixes: Chromium processed the seed request, yet the post-close automation session did not reach the retained postcondition. No production spec was changed and no release or cookie-reuse claim is made.
Independent managed-CLI rerun after the M1 gate (2026-09-20)
The M1 cleanup gate passed even though retained-session automation did not, so the independent CLI proof was run separately with fresh isolated state at /tmp/fast-browser-cli-final-OqHfA6. The environment again used only /usr/bin/chromium, the pinned Python environment, unique loopback ports, isolated HOME/XDG/TMPDIR/cwd/config roots, synthetic local credentials, and no provider keys or user profiles.
Successful managed examples:
local-form: exit0; all two operations passed; cleanup passed.local-login: exit0; all three operations passed using the synthetic environment credential; cleanup passed.local-popup: the original immediate-popup copy reached the click but timed out inwaitPopup(exit1, cleanup passed). The failure is retained as a production target-inventory race finding: the click postcondition passed, but the popup was not discovered by the opener-bound wait. A disposable diagnostic copy with a 100 mswindow.opendelay then passed navigation, click, popup discovery, and read with exit0; that delay is diagnostic evidence only, not popup clearance. The source fixture was restored to immediate popup behavior with its status-change fix preserved.
The intentional failed-assert scenario was changed to wait: "none" so the expected assertion failure remains non-aborted and evidence capture can complete. It exited 1 promptly (~506 ms), reported assertion not_satisfied, retained a real PNG and diagnostics JSON, and cleaned owned browser/fixture resources. The report is 0600 in the owned 0755 reports directory; artifact files are 0600 under 0700 roots. Diagnostics contain password=[redacted]; the synthetic credential is absent from report and stdout. Final census found no batch-owned Chromium/crashpad processes and no open managed ports.
The immediate-popup failure produced no retained evidence because the runtime operation aborted before the CLI's failure capture could run; cleanup still passed and the CLI removed its disposable profile. This is reported as a production/runtime evidence-retention finding, not hidden by treating cleanup success as scenario success. The validator now preserves failed M1 roots even when process cleanup succeeds and records automation cookie/outcome evidence for any future rerun.
Diagnostic retained-profile rerun (2026-09-20)
With process cleanup verified and no popup workaround retained, only the retained-profile prerequisite and automation case were run from a fresh isolated root /tmp/fast-browser-retained-run-gizlJ0. No headless, isolation, popup, or managed-CLI case was launched.
- Setup readiness passed, named setup closed, the profile remained, and no profile process remained.
- Setup persistence metadata was directly inspected at
.../Default/Cookies: 20,480-byte database, zero rows, zero journal bytes, zero WAL bytes. The final post-automation metadata was identical. There was therefore no persisted Chromium cookie row to reuse; no cookie value or token was logged. - Automation readiness passed, but server telemetry recorded
cookieHeaderPresent: false,cookieReceived: false, andretained: false. - The exact fill of
Milestoneverified. The exact click dispatched once withmutationState: unknown/actionMayHaveExecuted: true; it was never retried. Expected text wasRetained session verified; the fixture's actual bounded outcome wasFixture action did not meet its bounded condition, and the controller returnedPostcondition not verified; action was not retried. - Cleanup passed with no remaining owned processes. The failed diagnostic root was deliberately preserved mode
0700, with summary mode0600at/tmp/fast-browser-retained-run-gizlJ0/tmp/fast-browser-retained-diagnostic-0Rkywk/retained-diagnostic-summary.json.
This proves the retained-session failure is an actual missing-cookie condition in this isolated run, not merely an unrecorded postcondition mismatch. It does not establish cross-platform or global release clearance.
Immediate-popup managed rerun (2026-09-20)
The restored immediate-popup fixture was run alone from fresh isolated state at /tmp/fast-browser-popup-final-8qElTH, using native Linux /usr/bin/chromium, the pinned Python environment, an explicit unique loopback port, and isolated HOME/XDG/TMPDIR/cwd/config roots. The disposable scenario verified the full sequence click → waitPopup → selectTab → read without exposing tab IDs to the model.
The managed CLI exited 0 in 530 ms. Navigate, click (Popup opened postcondition), waitPopup, explicit selectTab, and popup read all passed; cleanup passed. Final ownership census found no batch-owned Chromium/crashpad processes and no open managed port. No popup delay workaround was used, and no timeout-metadata clearance claim is made.
Controlled persistent-cookie M1 comparison (2026-09-20)
The current leader-first implementation was tested once on a fresh isolated Linux profile at /tmp/fast-browser-persist-run-9J6jRV/tmp/fast-browser-persistent-cookie-m1-NKPozp. It used /usr/bin/chromium, the pinned Python environment, a disposable loopback fixture, and the explicit Max-Age=3600; Path=/; SameSite=Lax cookie. Setup was visible and no-CDP: its process argv had no --headless or remote-debugging flag.
- Setup readiness and close passed; the server received the synthetic cookie and the named profile survived with no remaining browser process.
- Post-close SQLite metadata showed one persistent row for the loopback host,
hasExpires: true,isPersistent: true,expiresUtcpopulated, and encrypted value storage; raw cookie values were not recorded. - Same-profile automation received the cookie (
cookieHeaderPresent: true,cookieReceived: true,retained: true). Fill and retained-session click both verified; actual outcome wasRetained session verified; no action retry occurred. - Final metadata still showed the one persistent row. Cleanup passed with no owned Chromium/crashpad processes; the failed-case-safe root was preserved mode
0700and the summary is mode0600.
Conclusion: root-first fixes persistent-cookie reuse in this controlled current Linux run. This is scoped evidence only; it is not global or non-Linux release clearance.
Final live integration pass (2026-09-20)
The current tree was validated with fresh isolated Linux roots and no user profiles, providers, or fixture timing workaround.
- Full original M1: exit
0; visible setup persistence, retained-session automation, headless bounded action, and two-profile isolation/contention all passed. Cleanup passed. - Canonical development matrix: exit
0; all six cases passed withEvidence provenance unavailable: false. - Managed
local-form: exit0; cleanup passed. - Managed
local-login: exit0; cleanup passed. - Managed immediate
local-popup: exit0in 531 ms; navigate, click,waitPopup, explicitselectTab, and read passed; cleanup passed. - Intentional assertion failure: exit
1in 558 ms withassertion not_satisfied,retry: never; private PNG and diagnostics were retained. Report mode was0600in a0755report directory, artifacts were0600under0700roots, and diagnostics retainedpassword=[redacted]only.
The real overall-deadline case used a no-popup waitPopup with a 3,000 ms scenario budget, below the operation's bounded wait. It exited nonzero (1) naturally in 3,066 ms; navigation passed and waitPopup aborted with mutationState: not_attempted, retry: never. Evidence was explicitly represented as private unavailable evidence (status: failed, error browser session is unavailable). The exact report is /tmp/fast-browser-final-batch-boijm3/reports/overall-deadline-no-popup.json; its scenario cleanup is { status: "failed", detail: "browser session cleanup failed" }, and the top-level cleanup is { status: "failed", detail: "one or more owned resources failed cleanup" }. This is the handoff finding for the CLI owner. Validation stopped immediately as required. No force-kill or mutation retry was used. A final ownership census still found no batch-owned Chromium/crashpad processes and no open managed ports, but this does not convert the reported cleanup failure into a pass.
The failed batch root remains preserved at /tmp/fast-browser-final-batch-boijm3; the complete summary is /tmp/fast-browser-final-batch-boijm3/final-validation-summary.json. No production or validation-source changes were needed for this pass.
Deadline cleanup-race rerun after manager fix (2026-09-20)
After the manager/CLI cleanup-race fix, only the real overall-deadline/no-popup case was rerun from fresh native-Linux isolated state at /tmp/fast-browser-deadline-rerun-iaE8de; the earlier failure report was not overwritten. The no-popup fixture used a 3,000 ms scenario budget below the bounded popup wait.
The new report is /tmp/fast-browser-deadline-rerun-iaE8de/reports/overall-deadline-no-popup-rerun.json. It exited 1 naturally in 3,090 ms: navigation passed, waitPopup aborted, and the report preserved retry: never, mutationState: not_attempted, and private unavailable evidence (browser session is unavailable). Cleanup now passed with owned runtime, artifacts, browser session, and fixture resources cleaned. Final census found no rerun-owned Chromium/crashpad process and no open port. The rerun root remains preserved mode 0700, and the report is mode 0600.