Files
harness-tools/docs/fast-browser-prototype-validation.md
jb fd63b0ccec
fast-browser scenarios / Offline scenario contract tests (push) Failing after 44s
fast-browser scenarios / Local Chromium headless scenarios (push) Failing after 23s
fast-browser-with-jev
2026-09-20 12:24:08 -04:00

8.0 KiB

Fast Browser prototype validation

This records the original approval-based prototype and demo. Subsequent user requirements and implementation are tracked in the unattended-session plan.

Branch: feat/fast-browser. Validation date: 2026-09-19.

Implemented

  • fast_browser_observe and fast_browser_run Pi tools, lazily loaded config and per-extension serialized browser lane.
  • Bounded click/fill plans (up to 10 steps), exact-name deterministic shortcut, JEV semantic candidate selection, optional registry-backed composition, and per-action UI approval.
  • Literal input bypasses text generation. JEV is lazy: exact-name runs need no Typesafe key.
  • JEV requests contain the task, action, origin and bounded candidate labels, not page URL paths, query strings, fragments, page titles or field values. Control labels still intentionally go to the model and may contain private page-derived information; this is not universal content redaction.
  • Isolated Python worker using the installed, pinned browser-harness==0.1.13 daemon. The worker owns its child process instead of using the harness's detached/retrying/auto-launch path. It attaches to exactly one already-open approved-origin tab, never navigates to choose a tab, and shuts down its own daemon/temporary directories.
  • Only main-frame native text inputs/textareas and supported clickable controls are in scope. No arbitrary model-authored code, screenshots, frame traversal, uploads, downloads, or submit/Enter shortcut API.
  • Every mutation revalidates tab/document/candidate identity and invalidates previous observations. Clicks require a previously unsatisfied URL/text postcondition. Fills verify exact current field value and any optional postcondition. Verification does not prove all internal application state or external side effects.
  • mutationState and actionMayHaveExecuted distinguish an unverified dispatched mutation from a run that never attempted one. Cancellation cannot undo an already dispatched browser action. Unknown outcomes require inspection, not blind retry.

Validation performed

  • Final bun run test passed the complete repository suite, including 56 fast-browser TypeScript tests and 18 Python tests. bun run typecheck and git diff --check also passed.
  • Offline TypeScript tests cover controller budgets, cancellation races, deterministic selection, approval, JEV request/response validation, model routing, config, IPC limits and lifecycle.
  • Python tests cover candidate filtering, stale/changed targets, replay prevention, postconditions, origin changes, helper call contracts, owned daemon startup/shutdown, strict version guard, and non-sensitive protocol errors.
  • A real subprocess smoke check using this host's existing uv interpreter confirmed that installed browser-harness 0.1.8 is rejected before importing browser helpers or connecting to Chrome. No upgrade was performed on that installation.
  • Workspace typecheck passes in the local dependency environment. The lockfile changes only add the new workspace; no dependency-version churn.
  • Package checks verify that runtime Python/TypeScript files, skill and fixture are included and tests/bytecode are excluded.
  • The earlier full repository run passed existing suites but caught a new confirmation-test expectation during a concurrent approval-format edit. That test was corrected to expect safely quoted display values; the final full rerun passed.

Review findings fixed

  • Removed an implicit import from a temporary source checkout.
  • Stopped forwarding the Pi environment and provider API keys into Python/daemon children.
  • Replaced detached daemon startup with explicit process ownership; handled cancellation during startup and waited for worker exit before releasing the lane.
  • Fixed candidate-name/role consistency, main-frame checks, click hit testing, and focused bulk input rather than per-character typing.
  • Rejected preexisting click postconditions, out-of-origin post-action states, and replay through other old snapshots.
  • Tightened probability normalization and rejected a selected JEV option that contradicts the reported winner. Confidence remains a separate provider-reported value with an uncalibrated prototype threshold, not a security boundary.
  • Made streamed model responses abortable and sanitized their failures; bounded direct JEV input calls as well as controller inputs.
  • Limited action evidence to fixed non-sensitive messages and exposed uncertain action outcomes in machine-readable form.

The review's suggestion that the controller must itself understand DOM/frame identity was not adopted: that identity stays private in the real bridge, whose act contract and tests enforce freshness immediately before mutation. Local approval retains the exact escaped URL/payload for informed permission; those confirmation values are not JEV request context.

Not validated / next step

The original prototype validation did not include live mutation/inference. The subsequent demo partially exercised those paths, as recorded below. No comparative task-success or latency benchmark has been run. Initial validation found no Chrome on PATH and an older default harness installation.

Follow-up: live demo preparation

At the user's request, Chrome was subsequently found at /opt/google/chrome/chrome (version150). A separate ignored project-local environment was prepared with browser-harness0.1.13 and a dedicated Chrome profile. The local fixture now includes a Demo greeting textarea for the requested small-model composition demo.

A real read-only bridge smoke test passed: it returned exactly Display name, Demo greeting, and Continue, excluding the password and disabled controls. After bridge shutdown, a CDP tab-list check confirmed that only the original fixture tab remained; the harness-owned blank tab was cleaned up. No API credentials were used and no fields were filled or clicked.

After restarting through .pi/fast-browser-demo/start-pi.sh --resume, the actual Pi tools ran. JEV selected Display name (confidence0.99,433ms); after UI approval, filling Ada was verified in14ms. It next selected Demo greeting (confidence0.89,324ms), but Spark generation failed before any greeting-field mutation. The full partial run took13,240ms, including11,552ms of human approval wait. Continue was not clicked.

A separate tool-free Pi diagnostic confirmed the provider error: gpt-5.3-codex-spark is not supported with this ChatGPT-account authentication. The user selected openai-codex/gpt-5.6-luna with reasoning off instead. The launcher was updated, and Codex auxiliary calls now explicitly send reasoningEffort: none; only the remaining two steps should be resumed after restart. Safe generation errors are now retained in tool results. Latest tests:58 TypeScript+18 Python and workspace typecheck pass.

During this follow-up, one no-key adapter test accidentally inherited the live Typesafe environment and issued a synthetic fixture request. The test helper now clears all fast-browser settings/key before each test, and all adapter tests prohibit HTTP. No actual browser page data or field values were sent by that test. This finding and the remaining environment-only reconfiguration limitation are recorded in docs/todos.md. Preparation/resume state and cleanup resource IDs remain in ignored .pi/fast-browser-demo/README.md.

No speedup or general-browser reliability claim is established by these tests. After the approved live demo, compare identical tasks against a small-model-only baseline.

The origin allowlist controls where this adapter operates; it is not a browser network firewall. A redirect or action may already have caused a network request before the adapter detects it. The JS/DOM checks are not atomic against a malicious page changing between check and input. Use a trusted, dedicated test profile for this prototype.

Tooling failure observed

The browser-bridge subagent failed twice with a provider WebSocket error after writing partial files. The parent resumed once, then completed and tested the implementation directly. Reproduction evidence and a follow-up remain in docs/todos.md.