Commit Graph
224 Commits
Author SHA1 Message Date
ciregenzandClaude Opus 5 a982e3361f [eric] browser: an approval nobody can answer declines now instead of parking a turn for 5 minutes
The wait was a bare `timeout=300.0` at the call site: invisible, unchangeable, and
longer than WALL_BUDGET_S (180s) itself, so a single prompt could outlive the whole
run's budget.

Measured 2026-08-08. deepl bot-detected the browser profile, the agent correctly
refused to solve the challenge ("handing to the user, not solving it") and asked for
help via RequestHumanIntervention. Headless, nobody answered, so it burned the full
306s and then denied -- the identical verdict it can reach instantly. That single
wait consumed the entire 420s task budget and was the whole of what looked like a
"249s spawn stall" while profiling. Cron runs, scheduled agents, CI and benchmarks
all sit in exactly this position.

Two changes, neither of which weakens the gate:
- ws_manager.has_listener(session_id) reports whether ANY socket would receive the
  session's events, reading the same two lists send_to_session broadcasts to so it
  cannot drift from where messages actually go.
- p_request_browser_approval checks it BEFORE building a request, and declines with
  an honest reason when no UI is attached. The decision is unchanged (deny); only
  the five minutes of waiting for it are gone.

The timeout is now P_APPROVAL_TIMEOUT_S, overridable via OSW_APPROVAL_TIMEOUT_S for
automation contexts that want a different budget.

A human at the keyboard sees no change: with a socket attached the request is sent
and awaited exactly as before.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-08 09:28:53 -07:00
ciregenzandClaude Opus 5 3c50359146 [eric] browser-v3: fix the instrument first, then the two composer bugs it could finally see
Six of the eleven defects here were in the MEASUREMENT, not the product, and they
were wrong in both directions.

Harness, all of which silently produced wrong numbers:
- coverage.py preflight refused every sweep on a box holding exactly one backend:
  stack.sh's supervisor is a `bash -c` quoting the whole uvicorn line, so it carries
  both "-m uvicorn backend.main" AND the venv python path. Discriminate on POSITION.
- stack.sh status reported 2 backends over 1 and 0 webpack over a live dev server
  (webpack retitles its process). A status check whose job is preventing a second
  stack, failing in the direction that lets one land.
- c7_run.sh/c8_run.sh slice r6_be.log while stack.sh names logs by TAG: a stack under
  any other tag hands every trial an empty slice and the sweep reports a confident
  0/108. Now refuses loudly; it caught this exact mistake on first use.
- "Browser command timed out" was bucketed infra. It is ONE command blowing its own
  budget, not a dead webview: all 4 such rows were BrowserFindComposer at exactly its
  30s cap, every run completed after, zero card-gone markers in the whole log. Filed
  as infra it read as 11.8% flake AND lifted holdout reach 70% -> 84%.
- api_retry / rate_limit_error now grade as infra. A provider 429 storm turned clean
  15-21s exclusions into 188s product_no_composer rows.
- bench.py prints reach BOTH ways when a row is UNVERIFIED. An exclusion resting on
  the agent's own word quietly flatters the score, and coverage.py's own instruction
  to confirm it by hand goes unread (I quoted a 100% that excluded onlinegdb).

Timing was measuring 0.2% of the run: prestage completes BEFORE metrics_started_at,
so other_ms was 25ms of a 12700ms median while prestage (4146ms, ~61%) sat in no
bucket at all. prestage_ms/task_ms are now recorded; total_ms is deliberately NOT
redefined, which would invalidate every before/after already taken against it.

Product:
- find_composer rejected ACE/CodeMirror-5/Monaco composers. Their input is a ~1x1
  offscreen textarea that paints into a sibling div, so it can never pass a size
  gate. Accept it when a VISIBLE ancestor is composer-sized; honeypots stay out
  because the input itself must not be display:none/visibility:hidden/opacity:0.
  anon reach 80% -> 100%, holdout 89% -> 90%, p95 38.6s -> 9.7s.
- the composer poll slept a blind 0+1.2+1.4 = 2.6s whenever prestage staged nothing,
  which is nearly every run, and it was the whole of other_ms's suspicious constancy
  (2610-2613ms regardless of tools_ms). Stop when two reads are identical, the rule
  the opener poll 40 lines below already applies. other_ms -53.7%, tools_ms flat.
- prestage no longer navigates to the page it is already on, nor sleeps 0.35s before
  its first settle probe.
- is_replay_boundary reasoned from the NAME alone, so x.com's composer textbox named
  "Post text" was ruled an irreversible send and truncated its replay to a bare
  navigate. Excluded by ROLE; first_unsafe_step now passes role through at all.

Measured on this box: reach 100% (83% if onlinegdb's unverified exclusion is bogus),
0 false successes in ~155 runs, prestage tier-0/1 2702ms, other_ms -53.7%, infra
flake 0/158, holdout 18/20. Criteria 2/4/9 need live writes and are untouched.
Full evidence, including what did NOT work, in e2e/browser-v3/RESULTS_2026-08-06.md.

Also drops the tracked electron/node_modules symlink pointing at another machine's
Downloads folder; it is dangling on every other checkout and re-breaks the install on
any stash or checkout.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-06 23:21:05 -07:00
ciregenz af68dcd06d [eric] send: when the task names a field, write into that field (reddit's title) 2026-08-05 08:28:38 -07:00
ciregenz 438a96eb42 [eric] skills: name the send-script's clicks so a completed write can be recorded at all 2026-08-05 07:47:01 -07:00
ciregenz 83649f5b17 Revert "[eric] browser: prove a send by the payload appearing twice, when the composer never clears"
This reverts commit 7fcce1e2f3.
2026-08-05 00:48:16 -07:00
ciregenz 7fcce1e2f3 [eric] browser: prove a send by the payload appearing twice, when the composer never clears 2026-08-05 00:45:38 -07:00
ciregenz 6e3ef0e40a [eric] browser: nudge a lazy feed once before deciding it has no posts 2026-08-04 23:32:14 -07:00
ciregenz 324639e217 [eric] browser: open the first post by its own link, instead of hunting a feed 2026-08-04 23:26:37 -07:00
ciregenz ac6dbb119f [eric] browser: catch a wrong-surface landing while there are still steps to fix it 2026-08-04 23:12:49 -07:00
ciregenz 8298d3f604 [eric] browser: let the model name the message, so the fast lane stops needing quotes 2026-08-04 22:03:50 -07:00
ciregenz 1eaa23b9c1 [eric] browser: say 'I never typed it' when nothing was typed, not 'check the page' 2026-08-04 21:53:58 -07:00
ciregenz 25bfe12da4 [eric] browser: a page that loaded content is settled, even with nothing to compare against 2026-08-04 21:16:27 -07:00
ciregenz 5abf06b54f [eric] browser: a click that reveals the composer ends the stage, no second model call 2026-08-04 20:59:44 -07:00
ciregenz e445ca3eeb [eric] browser: fill the one field a disabled submit is waiting on, then re-ask the page 2026-08-04 20:14:50 -07:00
ciregenz 7dc5f58651 [eric] browser: a composer already on the page needs no model to confirm it 2026-08-04 19:44:44 -07:00
ciregenz 3b10b409a8 [eric] browser: an unproven send still blocks a resend, so nothing gets posted twice 2026-08-04 18:32:51 -07:00
ciregenz 310fa1619a Revert "[eric] browser: prove a send by the posted content, not only by an emptied box"
This reverts commit 5035520629.
2026-08-04 17:49:23 -07:00
ciregenz 5035520629 [eric] browser: prove a send by the posted content, not only by an emptied box 2026-08-04 17:40:39 -07:00
ciregenz 3787123468 [eric] browser: wait longer for a slow composer to clear, so a real send stops reading as unverified 2026-08-04 17:23:57 -07:00
ciregenz ccccf9fc4c [eric] browser: probe before sleeping, so a ready page stops paying the slow page's wait 2026-08-04 16:50:44 -07:00
ciregenz bd24d0bf6c [eric] browser: a comment task must not click Create-new-post 2026-08-04 16:11:51 -07:00
ciregenz b62a29357e [eric] browser: a comment meant for a post must not land on a story 2026-08-04 15:57:30 -07:00
ciregenz 57d5a6fed7 [eric] browser: hand a bot-detection challenge to the user instead of guessing at it 2026-08-04 15:33:35 -07:00
ciregenz a6e63815e7 [eric] browser: record the navigation prefix instead of discarding the whole run 2026-08-03 16:28:57 -07:00
ciregenz aa07ff0728 [eric] browser: tell a user their DELETION was unconfirmed, not their send 2026-08-03 15:48:33 -07:00
ciregenz 116e44255e [eric] browser: a delete task can no longer report a send it never made 2026-08-03 15:23:50 -07:00
ciregenz ab89896443 [eric] browser: reach an opener whose label is a sentence, without reaching an upsell 2026-08-02 17:55:23 -07:00
ciregenz 8a6be84a4c [eric] browser: a send task is not staged until there is somewhere to write 2026-08-02 17:48:00 -07:00
ciregenz d67df490f8 [eric] browser: a header sign-in widget no longer walls off the composer beside it 2026-08-02 16:23:46 -07:00
ciregenz fb3ec15105 [eric] merge: bring eric/dev onto the browser v3 branch (7 conflicts resolved, gates green) 2026-08-02 16:14:53 -07:00
ciregenz 1508e03c5f [eric] browser: half an emoji in page text no longer kills the whole prestage 2026-08-02 15:30:17 -07:00
ciregenz 2489cc3971 [eric] browser: persist the wall/llm/tools/ours latency split, so a speed claim has evidence 2026-08-01 00:35:11 -07:00
ciregenz 5799b3b62a [eric] browser: log the page a send filled on; correct the inflated composer-reach claim 2026-08-01 00:32:51 -07:00
ciregenz 39dbbd0a39 [eric] browser: a post or comment task can never land in a DM box, at composer or opener 2026-07-31 22:50:17 -07:00
ciregenz c826d2b614 [eric] browser: a slow command reports whether the wait was before its handler or inside it 2026-07-31 18:43:20 -07:00
ciregenz 7761d716b1 [eric] browser: a read-only directive can never be a publish task, so probes stop reporting failure 2026-07-31 17:16:50 -07:00
ciregenz ec4a044b0b [eric] browser: strip the click-by-index element rows from anything a human reads 2026-07-31 15:58:49 -07:00
ciregenz a9da551425 [eric] browser: show a failed step as failed in the live overlay, with per-step timestamps 2026-07-31 14:33:16 -07:00
ciregenz dcaf655b14 [eric] browser: measure browser time where the commands actually run, not from 18 self-reports 2026-07-31 14:00:19 -07:00
ciregenz c9c25542b9 [eric] browser: never click a disabled submit, and turn the structural composer finder on 2026-07-31 13:03:59 -07:00
ciregenz 2c63367ae0 [eric] browser: a signed-in page is not a login wall just because it says sign in 2026-07-31 13:03:58 -07:00
ciregenz 0cf7d111c2 [eric] browser: rank a submit control instead of exact-matching a closed label set 2026-07-31 13:03:58 -07:00
ciregenz 5d8bf4102e [eric] browser: only a verified delivery teaches a write skill, not a resend guard 2026-07-31 02:44:34 -07:00
ciregenz a1c6c710eb [eric] browser: reddit clears its composer without posting, so treat it as a ghost-drop host 2026-07-31 02:37:07 -07:00
ciregenz b4074c3665 [eric] browser: never report a post as sent when no send was ever confirmed 2026-07-31 02:23:36 -07:00
ciregenz 013bf663ef [eric] browser: a post that never confirmed is not a skill worth learning 2026-07-31 01:27:55 -07:00
ciregenz 17ab446945 [eric] browser: read script looks cheap first and only a decline buys the whole page 2026-07-31 00:51:54 -07:00
ciregenz 4f4d5e8d55 [eric] browser: the read script asks for the whole page, not the model loop's smaller default 2026-07-31 00:02:57 -07:00
ciregenz e989517c6c [eric] lint: de-private the wall budget, trim error_classify under cap, drop stray ws_manager 2026-07-30 20:58:16 -07:00
ciregenz f6ad6cfb91 [eric] browser: a run out of wall time delivers what it has instead of nothing 2026-07-30 20:50:37 -07:00