docs(browser,rules): the js op is NOT auto-woken, the agent cannot SEE, and a squash merge is never an ancestor - #294
Merged
Conversation
…E, and a squash merge is never an ancestor
Three durable findings from the civitai #3539 /apps store-UX arc.
1. spa-wake.md — a `js` MEASUREMENT is the unprotected case. The agent's
deterministic auto-wake is AUTO_WAKE_OPS = Object.freeze(["text","html"])
(opencode/tools/browser_tool_impl.mjs, pinned by tests/auto_wake.test.mjs).
The wire op `eval` — for which `js` is a CLI-only alias — is deliberately
not in that set, so a layout/geometry/overflow measurement can be taken on a
throttled, hidden, never-rendered tab and return plausible numbers with no
error. Rule: assert a non-zero content count in the same expression.
Measured 2026-08-02: a bare `js` on a freshly-opened tab returns
visibilityState "hidden".
`visibilityState` is NOT a "did wake work" check — the flip is scoped to the
wake window because WAKE_CDP_TEARDOWN (extension/protocol.js) explicitly
reverts focus emulation before detaching, rather than leaving it to detach.
This file's existing measured table ("one wake fires visibilitychange
TWICE") already establishes that, so the note now points at it instead of
re-deriving it from a second measurement.
2. agent.md — the browser agent is BLIND, and that guarantee is CODE-ENFORCED
rather than model-dependent: summarizeResult() returns only
{ok, screenshot:true, bytes, note} for op === "screenshot", so the base64
dataUrl never reaches the model's context. The configured deepseek-v4-*
models are text-only as well, but swapping in a vision model would NOT make
the agent sighted — the tool would have to be changed to emit the image.
Grounding the claim on the code keeps this page true across a model swap.
3. RULES.md — a squash merge never makes the branch head an ancestor of the
base, so `merge-base --is-ancestor` is false forever after one and reads as
"not merged". Verify a squash by CONTENT, not ancestry.
Byte gates, measured on the REBASED (merged) tree:
claude/RULES.md 33,562 B — headroom 938 (min 900), ceiling 34,500
scripts/browser-bridge/SKILL.md 12,034 B — headroom 254 (min 250), ceiling 12,288
Both gates were watched RED first: the pre-fix merged SKILL.md was 12,053 B and
failed with "RECLAIM: 15 bytes". SKILL.md's addition is paid for by evicting
"SEE the page → drive.", which the new BLIND clause and the existing
`diagnostic` bullet now state twice over.
Corrections against the first version of this branch:
- `--wake` on `open` against an `about:blank` tab fails
`cdp_attach_refused:about:`, NOT `<no-scheme>`. cdpSchemeOf returns
`new URL(url).protocol`, so `about:blank` yields `about:`; `<no-scheme>` is
only the case where URL parsing throws (url absent/uncommitted). The old
wording also contradicted reference/errors.md, which already documented
`about:` for exactly this tab state.
- the blindness claim is regrounded on the tool layer (see 2), so it no longer
silently becomes false if the agent model changes.
ZacxDev
force-pushed
the
zach/browser-skill-js-wake-and-blind-agent
branch
from
August 6, 2026 01:14
c0e1330 to
a653d9c
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Three durable findings from the civitai #3539
/appsstore-UX arc. Docs only — no code, no behaviour change.1.
reference/spa-wake.md— ajsMEASUREMENT is the unprotected caseThe
browser agent's deterministic auto-wake isAUTO_WAKE_OPS = ["text","html"];eval/jsis deliberately not in it. So a layout / geometry / overflow measurement can be taken on a throttled, hidden, never-rendered tab and come back as plausible numbers with no error. It cost a "no horizontal overflow, no wide elements" verdict measured on a page whose SPA content had never loaded — every number real, and about an empty document.Rule added: assert a non-zero content count in the same expression as the measurement.
Measured, not asserted (2026-08-02,
workinstance, own isolated tab, closed after):json a freshly-opened tab →visibilityState: "hidden".wakeitself →{"woke":true,"visibilityState":"visible"}, while the very next separatejsread on that same tab →"hidden"again.That second pair resolves a real ambiguity in this file. Both readings are correct — the flip is scoped to the wake window and
wakereverts focus emulation on detach — so the doc now says which one you get when, and thatvisibilityStateis not a "did wake work" check. Also recorded:--wakeonopencan failcdp_attach_refused:<no-scheme>when the tab is stillabout:blank, i.e. navigation had not completed.2.
reference/agent.md— the agent is BLINDEvery
deepseek-v4-*model on OpenRouter isinput_modalities: ['text'](flash,flash-latest,flash-0731,pro— verified 2026-08-02 against the OpenRouter models API). Thebrowser agenttherefore structurally cannot judge a screenshot, a layout, or a visual regression. This is the mechanism behindSKILL.md's existing "diagnostic → drive" routing, now stated as a capability boundary rather than a preference, with the routing consequence spelled out.3.
claude/RULES.md— a squash merge is never an ancestorgit merge-base --is-ancestor <head> origin/mainreturns false after every squash merge, forever. It reads as "not merged / don't delete the branch". Verify a squash landed by content, not ancestry.Byte budget
SKILL.mdgets only the two sharpenings that must live in the core (the agent is blind; auto-wake never coversjs). It is 11,910 B against the 12,038 B enforced budget → 378 B headroom (min 250), andtest_skill_size.pypasses 4/4. No eviction needed.🤖 Generated with Claude Code