[object Object]

← back to Cli Printing Press

feat(skills): browser-capture fallback options (chrome-MCP, computer-use) (#529)

f2450385474ae29e9a47d79abf3abb315f869504 · 2026-05-03 09:48:38 -0700 · Matt Van Horn

* feat(skills): browser-capture fallback options (chrome-MCP, computer-use)

Extend the browser-sniff capture workflow so that when the primary
backends (browser-use, agent-browser) get blocked or fail, the skill
detects and offers two additional capture options the runtime already
has access to: the Claude chrome-MCP (mcp__claude-in-chrome__*) and
computer-use (mcp__computer-use__*).

Motivated by an airbnb-vrbo printing-press session where agent-browser
got hard-blocked by Akamai on VRBO and the existing recovery menu
offered only "try cleared-browser again / manual HAR / pivot scope" —
the user had to manually inject "you have MCP chrome extension" to
redirect the agent. The chrome-MCP captured the data successfully once
pointed at it, but the skill never offered it as an option.

Changes:

- references/browser-sniff-capture.md Step 1 — agent-prose detection
  block for the two MCP fallbacks; sets CHROME_MCP_AVAILABLE and
  COMPUTER_USE_AVAILABLE flags via reasoning (not bash, since shell
  blocks can't read the agent's own tool registry). Probe is cheap
  inspection only; ToolSearch schema load is deferred until the user
  picks the option.
- references/browser-sniff-capture.md Step 2e (new) — chrome-MCP
  capture playbook. Covers prerequisites, mandatory tab-scope rule
  (always tabs_create_mcp, never reuse the user's existing tabs),
  mandatory body-capture interceptor (read_network_requests omits
  response bodies; install fetch/XHR shadow before navigation),
  output to the existing EnrichedCapture JSON shape, mandatory
  write-time credential strip, pacing scope (only operations the
  agent initiates pace), multi-trigger failure detection (HTTP status
  + body markers + page sentinel), and replayability check.
- references/browser-sniff-capture.md Step 2c.5 — recovery menu
  rewritten as availability-aware composition table (4 rows, one per
  flag combination, capped at 4 menu options). Recommended-badge
  fires on chrome-MCP whenever it's in the menu and the trigger was
  an anti-bot block. Question stem teaches the chrome-MCP mechanic
  on first encounter. Session-scoped tracking of failed backends so
  the menu re-fires with failed options removed.
- references/browser-sniff-capture.md Step 1d HAR-export expansion —
  refreshed for Chrome 147+ DevTools layout (download-arrow icon path,
  since "Save all as HAR with content" was removed from the right-
  click menu). Computer-use visual-feedback-loop spec when available:
  collapse-pane-before-screenshot to keep credentials out of PNGs,
  inline display + agent interpretation (not silent storage),
  Phase 5.5 PNG cleanup so manuscripts don't archive credential pixels.
- references/browser-sniff-capture.md cardinal rule 1 — fallback set
  extended to enumerate chrome-MCP and computer-use alongside the
  existing browser-use / agent-browser / manual-HAR set.
- SKILL.md Phase 1.7 — disclosure language extended to enumerate the
  full fallback set including chrome-MCP's authenticated-session use
  and computer-use's screenshot guidance, so user pre-approval at
  Phase 1.7 covers the recovery-menu fallback selection without a
  per-invocation re-consent.
- SKILL.md Phase 1.7 Banned Skip Reasons — new entry preventing
  silent pivot when chrome-MCP is available and the previous backend
  failed against an anti-bot gate. Routes to Step 2c.5 menu instead.
- printing-press-polish/SKILL.md Phase 1 baseline — one-paragraph
  pointer at the shared playbook so polish runs that need re-discovery
  know the chrome-MCP/computer-use options exist.

Defaults stay defaults — browser-use primary, agent-browser secondary.
The new options enter only on Step 2c.5 failure-recovery or as opt-in
choices in the install/initial menus. No Go code changes; pure SKILL
prose. Marker file schema unchanged (reason field absorbs new content).

Plan: docs/plans/2026-05-03-001-feat-browser-capture-fallback-options-plan.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(plans): browser-capture fallback options plan

Plan document for the feat(skills) commit on this branch. Captures
the problem frame (airbnb-vrbo session blocked by Akamai with no
chrome-MCP option offered), 11 active requirements, 6 implementation
units (U1-U6), key technical decisions including tier roles and
artifact contract preservation, scope boundaries, and 8 deferred
items in Open Questions for follow-up resolution.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

Files touched

Diff

commit f2450385474ae29e9a47d79abf3abb315f869504
Author: Matt Van Horn <mvanhorn@users.noreply.github.com>
Date:   Sun May 3 09:48:38 2026 -0700

    feat(skills): browser-capture fallback options (chrome-MCP, computer-use) (#529)
    
    * feat(skills): browser-capture fallback options (chrome-MCP, computer-use)
    
    Extend the browser-sniff capture workflow so that when the primary
    backends (browser-use, agent-browser) get blocked or fail, the skill
    detects and offers two additional capture options the runtime already
    has access to: the Claude chrome-MCP (mcp__claude-in-chrome__*) and
    computer-use (mcp__computer-use__*).
    
    Motivated by an airbnb-vrbo printing-press session where agent-browser
    got hard-blocked by Akamai on VRBO and the existing recovery menu
    offered only "try cleared-browser again / manual HAR / pivot scope" —
    the user had to manually inject "you have MCP chrome extension" to
    redirect the agent. The chrome-MCP captured the data successfully once
    pointed at it, but the skill never offered it as an option.
    
    Changes:
    
    - references/browser-sniff-capture.md Step 1 — agent-prose detection
      block for the two MCP fallbacks; sets CHROME_MCP_AVAILABLE and
      COMPUTER_USE_AVAILABLE flags via reasoning (not bash, since shell
      blocks can't read the agent's own tool registry). Probe is cheap
      inspection only; ToolSearch schema load is deferred until the user
      picks the option.
    - references/browser-sniff-capture.md Step 2e (new) — chrome-MCP
      capture playbook. Covers prerequisites, mandatory tab-scope rule
      (always tabs_create_mcp, never reuse the user's existing tabs),
      mandatory body-capture interceptor (read_network_requests omits
      response bodies; install fetch/XHR shadow before navigation),
      output to the existing EnrichedCapture JSON shape, mandatory
      write-time credential strip, pacing scope (only operations the
      agent initiates pace), multi-trigger failure detection (HTTP status
      + body markers + page sentinel), and replayability check.
    - references/browser-sniff-capture.md Step 2c.5 — recovery menu
      rewritten as availability-aware composition table (4 rows, one per
      flag combination, capped at 4 menu options). Recommended-badge
      fires on chrome-MCP whenever it's in the menu and the trigger was
      an anti-bot block. Question stem teaches the chrome-MCP mechanic
      on first encounter. Session-scoped tracking of failed backends so
      the menu re-fires with failed options removed.
    - references/browser-sniff-capture.md Step 1d HAR-export expansion —
      refreshed for Chrome 147+ DevTools layout (download-arrow icon path,
      since "Save all as HAR with content" was removed from the right-
      click menu). Computer-use visual-feedback-loop spec when available:
      collapse-pane-before-screenshot to keep credentials out of PNGs,
      inline display + agent interpretation (not silent storage),
      Phase 5.5 PNG cleanup so manuscripts don't archive credential pixels.
    - references/browser-sniff-capture.md cardinal rule 1 — fallback set
      extended to enumerate chrome-MCP and computer-use alongside the
      existing browser-use / agent-browser / manual-HAR set.
    - SKILL.md Phase 1.7 — disclosure language extended to enumerate the
      full fallback set including chrome-MCP's authenticated-session use
      and computer-use's screenshot guidance, so user pre-approval at
      Phase 1.7 covers the recovery-menu fallback selection without a
      per-invocation re-consent.
    - SKILL.md Phase 1.7 Banned Skip Reasons — new entry preventing
      silent pivot when chrome-MCP is available and the previous backend
      failed against an anti-bot gate. Routes to Step 2c.5 menu instead.
    - printing-press-polish/SKILL.md Phase 1 baseline — one-paragraph
      pointer at the shared playbook so polish runs that need re-discovery
      know the chrome-MCP/computer-use options exist.
    
    Defaults stay defaults — browser-use primary, agent-browser secondary.
    The new options enter only on Step 2c.5 failure-recovery or as opt-in
    choices in the install/initial menus. No Go code changes; pure SKILL
    prose. Marker file schema unchanged (reason field absorbs new content).
    
    Plan: docs/plans/2026-05-03-001-feat-browser-capture-fallback-options-plan.md
    
    Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
    
    * docs(plans): browser-capture fallback options plan
    
    Plan document for the feat(skills) commit on this branch. Captures
    the problem frame (airbnb-vrbo session blocked by Akamai with no
    chrome-MCP option offered), 11 active requirements, 6 implementation
    units (U1-U6), key technical decisions including tier roles and
    artifact contract preservation, scope boundaries, and 8 deferred
    items in Open Questions for follow-up resolution.
    
    Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
    
    ---------
    
    Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
    Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---
 ...1-feat-browser-capture-fallback-options-plan.md | 391 +++++++++++++++++++++
 skills/printing-press-polish/SKILL.md              |   2 +
 skills/printing-press/SKILL.md                     |   9 +-
 .../references/browser-sniff-capture.md            | 189 +++++++++-
 4 files changed, 581 insertions(+), 10 deletions(-)

diff --git a/docs/plans/2026-05-03-001-feat-browser-capture-fallback-options-plan.md b/docs/plans/2026-05-03-001-feat-browser-capture-fallback-options-plan.md
new file mode 100644
index 00000000..8be1ab40
--- /dev/null
+++ b/docs/plans/2026-05-03-001-feat-browser-capture-fallback-options-plan.md
@@ -0,0 +1,391 @@
+---
+title: "feat: Browser-capture fallback options (chrome-MCP, computer-use) for browser-sniff"
+type: feat
+status: active
+date: 2026-05-03
+---
+
+# feat: Browser-capture fallback options for browser-sniff
+
+## Summary
+
+Extend the `printing-press` browser-sniff capture workflow so that when the primary backends (`browser-use`, `agent-browser`) get blocked or fail, the skill detects and offers two additional capture options the runtime already has access to: the Claude chrome-MCP (`mcp__claude-in-chrome__*`) and computer-use (`mcp__computer-use__*`). The fix lives in three files: the shared `browser-sniff-capture.md` reference (capture playbook, recovery menu, manual-HAR refresh), `printing-press/SKILL.md` (Phase 1.7 disclosure + Banned Skip Reasons entry), and `printing-press-polish/SKILL.md` (one-paragraph routing pointer). No Go code changes, no new artifact format.
+
+---
+
+## Problem Frame
+
+The `airbnb-vrbo` printing-press session on 2026-05-02 surfaced a recurring failure mode. When `agent-browser` got hard-blocked by Akamai on VRBO, the skill's recovery menu (Step 2c.5 in `skills/printing-press/references/browser-sniff-capture.md`) offered exactly three options: try cleared-browser again (which would hit the same block), provide a HAR manually from DevTools, or pivot scope. The first option was useless against a hard block. The second option failed because Chrome 147's DevTools moved the HAR-export button and the text-only instructions sent the user through three dead-end menus before they gave up. The third option meant abandoning the killer feature.
+
+The skill never offered the Claude chrome-MCP or computer-use, even though both were loaded into the same runtime. The user had to manually inject "you have MCP chrome extension you can use my computer" to redirect the agent. Once redirected, chrome-MCP captured both Airbnb listing-detail SSR shape and VRBO SSR rendering in one session — exactly the data the failed `agent-browser` run was supposed to produce.
+
+The gap is that the skill's tool-detection block (Step 1) and recovery menu (Step 2c.5) hard-code awareness of `browser-use` and `agent-browser` only. Adding two more capture backends as first-class options closes the loop without changing the underlying capture-artifact contract or the marker-file gate.
+
+---
+
+## Requirements
+
+- R1. The skill detects whether `mcp__claude-in-chrome__*` tools are loadable in the current runtime (deferred-tool list or already-loaded), and sets a `CHROME_MCP_AVAILABLE` flag.
+- R2. The skill detects whether `mcp__computer-use__*` tools are loadable, and sets a `COMPUTER_USE_AVAILABLE` flag.
+- R3. When the primary capture backend (`browser-use` or `agent-browser`) fails by the criteria already documented in Step 2c.5 (challenge-only HTML, hard block, login-redirect loop, ≥3 consecutive 429s), the recovery menu surfaces chrome-MCP as an option when `CHROME_MCP_AVAILABLE=true`.
+- R4. The recovery menu surfaces computer-use as a visual-aid for the manual-HAR option when `COMPUTER_USE_AVAILABLE=true`. Computer-use is NOT offered as a peer browser-driver — its tier-"read" restriction on browsers makes it unable to click or type into Chrome.
+- R5. A new chrome-MCP capture playbook section in `browser-sniff-capture.md` describes how to drive the chrome-MCP for capture: tabs context → navigate → interact → read page text → read network requests, with output written to the same `$DISCOVERY_DIR/browser-sniff-capture.json` enriched-capture path the existing pipeline already consumes.
+- R6. The chrome-MCP backend inherits the existing adaptive-pacing posture (start at 1s, double on 429, pause 30s after 3 consecutive 429s) so the WAF that blocked the primary backend doesn't get hammered by the fallback.
+- R7. The manual-HAR instructions in Step 1d and Step 2c.5 are refreshed for Chrome 147+ DevTools layout (the download-arrow icon at the top of the Network panel, since "Save all as HAR with content" was removed from the right-click menu).
+- R8. The Phase 1.7 marker file (`browser-browser-sniff-gate.json`) records which backend was actually used in its existing free-form `reason` field — no schema change.
+- R9. The `browser-sniff-capture.md` cardinal rules section (rule 1) is updated to name chrome-MCP and computer-use as valid fallbacks alongside the existing `browser-use` / `agent-browser` / manual-HAR set.
+- R10. SKILL.md Phase 1.7 "Banned skip reasons" gains an entry that prevents silent skip-to-pivot when chrome-MCP is available and the previous backend failed against an anti-bot gate. The gate is "ask before giving up," not "auto-pivot when blocked."
+- R11. The polish skill (`skills/printing-press-polish/SKILL.md`) gains a brief pointer in its Phase 1 baseline section noting that if discovery rework requires browser capture, the chrome-MCP and computer-use are available via the shared reference. No duplication of the capture playbook.
+
+(R12 was a non-regression invariant; moved to System-Wide Impact > Unchanged invariants for clarity.)
+
+---
+
+## Scope Boundaries
+
+- Not implementing chrome-MCP or computer-use as a runtime transport for the printed CLI. Browser-sniff is generation-time discovery only; the cardinal rule against resident-browser sidecar transport is unchanged.
+- Not refactoring the existing `browser-use` or `agent-browser` Step 2a / Step 2b capture flows. Additive only.
+- Not adding a new artifact format. chrome-MCP writes to the existing `$DISCOVERY_DIR/browser-sniff-capture.json` enriched-capture shape so `printing-press browser-sniff --har <path>` (which accepts both HAR and enriched-JSON) consumes it unchanged.
+- Not building anti-bot prediction. The new menu fires on observed failure, not predicted failure. The existing `probe-reachability` classification stays the gatekeeper for transport-tier selection.
+- Not auto-retrying a backend that just failed. If `agent-browser` got blocked, the menu offers different backends; it does not silently re-run `agent-browser`.
+- Not auth-failure or network-failure handling. Those have separate paths in Step 1d and stay unchanged.
+- Not extending tool detection to other speculative MCPs (`browse`, `gstack`, etc.) — only the two the user named and the runtime makes available today.
+
+### Deferred to Follow-Up Work
+
+- A `/ce-compound` writeup of the WAF-fallback escalation pattern + MCP-availability detection convention. The `learnings-researcher` pass confirmed no prior docs exist on either; this plan creates the precedent worth capturing back. Separate task after the plan ships.
+
+---
+
+## Context & Research
+
+### Relevant Code and Patterns
+
+- `skills/printing-press/references/browser-sniff-capture.md` — the shared capture reference. Step 1 (lines 56-80) does tool detection. Step 1b (lines 82-125) is the install-picker `AskUserQuestion`. Step 2c.5 (lines 703-723) is the failure-recovery menu the user hit. All edits land here.
+- `skills/printing-press/SKILL.md` — Phase 1.7 (lines 781-1012). The marker file contract (lines 789-820) and the "Banned skip reasons" list (lines 822-834). Disclosure language about which backends the skill will offer lives in the AskUserQuestion blocks at lines 949-953 and 957-970.
+- `skills/printing-press-polish/SKILL.md` — Phase 1 baseline diagnostics (line 192). One pointer line gets added; no playbook duplication.
+- `internal/cli/browser_sniff.go` (lines 17-44) — the Cobra `browser-sniff` command. Inputs are `--har` or `--auth-from`. Accepts both HAR files and the enriched-capture JSON shape. The new chrome-MCP backend produces the enriched-JSON shape; this Go code is untouched.
+- `internal/browsersniff/parser.go`, `fixtures.go` — HAR + enriched-capture parsers. Untouched.
+- AskUserQuestion shape precedent: 3-option menus with "(Recommended)" badge on option 1, manual-HAR always last. Step 1b (lines 86-91), Step 1d Chrome-running (lines 192-196), Step 2c.5 (lines 715-719). The recovery menu may need to grow to 4 options when both chrome-MCP and computer-use are available; this is permitted by the AskUserQuestion 4-option cap.
+
+### Institutional Learnings
+
+- `docs/solutions/best-practices/sniff-and-crowd-sniff-complementary-discovery-2026-03-30.md` — discovery sources are complementary, not replacing. New backends should slot into the same "more sources = better coverage" mental model and produce the same artifact shape so the existing `mergeSpecs()` collision-handling works unchanged.
+- `docs/solutions/best-practices/adaptive-rate-limiting-sniffed-apis.md` — sites guarded by Akamai/DataDome 429 aggressively. The new chrome-MCP backend must inherit the existing pacing posture so the WAF that blocked the primary doesn't get hit at full speed by the fallback. R6 carries this forward.
+- `docs/solutions/best-practices/multi-source-api-discovery-design-2026-03-30.md` — each source is optional and independent; failure of one (missing tool, denied access) yields warn-then-empty, never aborts siblings. Maps directly to "chrome-MCP not loaded" and "computer-use access not granted" cases — both should warn and continue, not block the whole capture.
+- `docs/solutions/security-issues/filepath-join-traversal-with-user-input-2026-03-29.md` — tangential. Only relevant if the new playbook accepts user-supplied paths. The existing `$DISCOVERY_DIR` convention sidesteps this; flagged only if the chrome-MCP playbook ends up taking a user path arg.
+
+### Prior Plan Precedent
+
+The five prior browser-sniff plans (`2026-04-02-001-feat-browser-auth-cookie-runtime`, `2026-04-03-001-fix-sniff-auth-graphql-naming`, `2026-04-11-001-fix-sniff-gate-enforcement`, `2026-04-18-002-refactor-rename-sniff-to-browser-sniff`, `2026-04-21-001-feat-browser-sniff-traffic-analysis`) all extend the capture flow by inserting new Step subsections (`Step 2a.1.5`, `Step 2a.2.5`, etc.) inside the existing structure rather than restructuring it. This plan follows the same precedent: a new `Step 2e` for chrome-MCP, an inline expansion of Step 2c.5 for the recovery menu, and a refresh of Step 1 for detection.
+
+---
+
+## Key Technical Decisions
+
+- **Tier roles:** `browser-use` stays primary, `agent-browser` stays secondary. chrome-MCP is a third-tier fallback that enters only on failure recovery or when the user picks it explicitly from the install/initial menu. Computer-use is positioned as a visual-aid for manual HAR, not as a peer browser-driver. Rationale: chrome-MCP requires the user's existing browser session (good for auth-gated flows but tied to one tab at a time); computer-use cannot drive browsers due to its tier-"read" restriction on browser apps; the existing tools handle the unblocked-site case better.
+- **Detection mechanism:** check the runtime's deferred-tool list for substring matches on `mcp__claude-in-chrome__` and `mcp__computer-use__`. Loading the schemas via `ToolSearch` is deferred until the user actually picks the option, so detection is cheap. Falls back gracefully on platforms where the deferred-tool list is not exposed (treat as "not available").
+- **Artifact contract preserved:** chrome-MCP writes the enriched-capture JSON shape (`$DISCOVERY_DIR/browser-sniff-capture.json`) that `internal/browsersniff` already parses. Computer-use does not produce a primary artifact — it augments manual-HAR with screenshots saved to `$DISCOVERY_DIR/devtools-help-*.png` for the user's reference, plus on-screen verification of DevTools state.
+- **Marker file unchanged:** the `browser-browser-sniff-gate.json` marker keeps its current schema. The `reason` field (already free-form) records which backend was used (`reason: "chrome-mcp captured 142 requests; SSR enriched"`), giving Phase 1.5 and downstream readers the audit trail without a schema migration.
+- **Pacing posture:** chrome-MCP inherits the same 1s→0.3s ramp-down, double-on-429, 30s-pause-after-3-consecutive-429s rules already documented in Step 1b "Browser-Sniff Pacing." The playbook references the existing rules rather than restating them.
+- **Menu shape on recovery:** Step 2c.5's 3-option menu grows to up to 5 options when both chrome-MCP and computer-use are available (try-cleared-browser, try chrome-MCP, manual-HAR, manual-HAR-with-computer-use-screenshots, alternate scope). Per the AskUserQuestion 4-option cap, the implementation collapses computer-use into the manual-HAR option as a sub-flow ("manual HAR — I'll guide you with screenshots") rather than a separate top-level option, keeping the menu at 4 options max.
+- **Default-flow preservation:** when no failure occurs and both default backends are available and working, the new options never surface. Defaults stay defaults. The new options enter only on (a) Step 2c.5 failure recovery, or (b) Step 1b install-picker as opt-in choices when the user wants them up-front.
+
+---
+
+## Open Questions
+
+### Resolved During Planning
+
+- Should computer-use be a peer browser-driver to chrome-MCP? Resolved: no — computer-use's tier-"read" restriction on browsers blocks clicks/typing. Computer-use is positioned as a visual-aid for manual-HAR (screenshot verification, step-by-step guidance with `screenshot` tool) instead.
+- Does this fix also need polish-skill duplication? Resolved: no — polish does not call browser-sniff today (`grep` confirmed zero references). One pointer line in polish's baseline section is enough so future polish runs that need capture know where the playbook lives.
+- Does the marker file schema need migration? Resolved: no — the existing `reason` free-form field absorbs the new content.
+
+### Deferred to Implementation
+
+- Exact wording and option labels for the expanded Step 2c.5 menu. The implementer should follow the existing label conventions (3-5 word bold labels, "Recommended" badge on option 1 only when one is unambiguously preferred, manual-HAR last) and pick wording at edit time.
+- Whether the chrome-MCP playbook should explicitly list common interaction patterns (`tabs_context_mcp` first, `navigate`, `read_page`, `read_network_requests`, `javascript_tool` for `__APOLLO_STATE__`-style introspection) or stay at a higher level pointing readers at the MCP tool index. Implementer to pick during the edit based on how dense the existing Step 2a playbook is.
+- Whether DevTools-instruction screenshots (computer-use augmentation) should be saved as a static set in `assets/` or generated per-session. Static is simpler; per-session reflects the user's actual Chrome version. Defer to implementation.
+
+### Deferred from doc review (2026-05-03)
+
+These items surfaced in document review but require their own design discussion or scope decision before this plan ships. None are blockers for U1-U6 as currently scoped, but each warrants resolution before implementation begins.
+
+- **U6 polish pointer is too thin to fix the observed improvisation failure** (scope-guardian + adversarial). The pointer is found only by an agent that already concluded re-discovery is needed — not the failure mode the user experienced. Decide: keep the lightweight pointer (current), add a Phase 1 trigger in polish that fires the browser-capture playbook when sparse-capture or extraction-broken signals appear, or some hybrid. May warrant a follow-up plan rather than scope expansion of U6.
+- **Banned Skip Reasons is enforcement by prose only** (adversarial). The existing 5 banned reasons already failed to prevent the silent pivot in the user's session — adding a 6th treats the symptom, not the failure mode. Decide: keep U5 as prose enforcement (current), extend the marker-file gate with a `recovery_menu_shown` field that Phase 1.5 enforces, or some hybrid. The marker-file option also needs a small Go change to Phase 1.5.
+- **Menu re-fire state machine for failed backends unspecified** (design-lens). U3 edge case 4 introduces a new pattern (re-fire with chrome-MCP option removed) but doesn't say where the tried-backends state lives, whether the re-fired menu is the same Step 2c.5 or a distinct state, or how it interacts with the existing two-consecutive-failure logic. Decide: session-scoped (agent reasons about what it just tried) vs run-scoped (marker file tracks tried-and-failed across runs).
+- **Flag-11 silently drops plain manual-HAR option** (design-lens). When both flags are true, manual-HAR-without-screenshots is replaced by manual-HAR-with-screenshots. A user who doesn't want computer-use watching their screen has no escape. Decide: forced substitution (current implication), opt-in within the manual-HAR option (sub-question or "screenshots: yes/no" suffix), or two top-level options collapsed elsewhere.
+- **chrome-MCP consent surface omitted from Phase 1.7 disclosure analysis** (design-lens). chrome-MCP accesses the user's authenticated Chrome session — meaningfully different consent than browser-use's profile load. Decide: Phase 1.7 pre-approval with rich disclosure, per-invocation re-consent at Step 2c.5 menu, or explicit enumeration in disclosure language.
+- **chrome-MCP-also-blocked recovery has no real exit** (adversarial). Plan acknowledges the WAF could block chrome-MCP but doesn't specify failure-detection criteria for chrome-MCP — `read_network_requests` returning 142 challenge-page entries would be misrecorded as success. Decide: HTTP status pattern matching, response body markers (`cf_chl_opt`, `Just a moment`, Akamai sensors), Apollo/SSR introspection failures, or some combination; and at what threshold to re-fire the recovery menu vs accept partial capture.
+- **Question stem teaching for first-time chrome-MCP mechanic unresolved** (design-lens). Step 2c.5 fires when the user is mid-failure and has never seen chrome-MCP-as-fallback. Decide: stem includes a one-line explainer when chrome-MCP is in the menu, stem stays generic and option body carries the explainer, or agent decides at edit time based on session context.
+- **Computer-use only path (flag 01) complexity unjustified** (scope-guardian). Conditional menu composition for the 01 state delivers thin uplift (screenshot verification only). Decide: keep the 01 specialization (current), drop it (treat as flag 00 when chrome-MCP unavailable, reducing 4 conditional states to 3), or keep with stronger justification.
+
+---
+
+## Implementation Units
+
+**Recommended implementation order:** U1 → U2 → U3 → U4 → U5 → U6. The unit dependencies encode the partial order, but U3 + U4 both edit Step 2c.5 of `browser-sniff-capture.md` and U5 references the new Step 2e from U2 — sequential traversal in the listed order avoids edit conflicts on shared sections.
+
+- U1. **Detect chrome-MCP and computer-use availability**
+
+**Goal:** Extend the tool-detection block in `browser-sniff-capture.md` Step 1 so the skill knows whether the new backends are reachable, and sets flags the downstream menus consume.
+
+**Requirements:** R1, R2
+
+**Dependencies:** None
+
+**Files:**
+- Modify: `skills/printing-press/references/browser-sniff-capture.md` (Step 1: Detect capture tools, lines 56-80)
+
+**Approach:**
+- Detection is agent-prose, not shell-probe. The existing `command -v browser-use` / `command -v agent-browser` blocks remain (those are real binaries on PATH). For MCP tools, append a prose block to Step 1 instructing the agent to inspect its own tools list (visible in system reminders and the deferred-tool block) and assert flags inline in its reasoning: "If `mcp__claude-in-chrome__*` tools appear in your available or deferred tool list, set `CHROME_MCP_AVAILABLE=true`. If `mcp__computer-use__*` tools appear, set `COMPUTER_USE_AVAILABLE=true`. Otherwise both default to false." The flags live in the agent's reasoning across the same conversation turn, not as shell env vars — downstream menus read them from the same context.
+- Extend the "Using **<tool>**..." status report to additionally mention which fallback MCPs the agent detected (e.g., "Fallbacks available: chrome-MCP, computer-use")
+- The probe is intentionally cheap — actual schema loading via `ToolSearch` is deferred until the user picks the option
+- Falls back gracefully on platforms where the deferred-tool list is not exposed (the agent observes neither MCP, both flags default to false, downstream behavior unchanged from today's)
+
+**Patterns to follow:**
+- Existing detection block at Step 1 lines 56-80 (BROWSER_USE_HAS_LLM env-var probe is the closest analogue)
+- AGENTS.md "Default to machine changes" — the detection helper is conditional and additive
+
+**Test scenarios:**
+- Happy path: both MCPs available -> `CHROME_MCP_AVAILABLE=true`, `COMPUTER_USE_AVAILABLE=true`, status line names both
+- Edge case: chrome-MCP available, computer-use absent -> only chrome-MCP flag is true
+- Edge case: neither MCP available -> both flags false, status line unchanged from today
+- Edge case: runtime does not expose deferred-tool list (non-Claude-Code platforms) -> both flags default to false; existing flow unaffected
+- Integration: detection runs even when user has not yet approved any backend, so Step 2c.5 can render the right menu later
+
+**Verification:**
+- Re-running the user's `airbnb-vrbo` session shows the status line listing chrome-MCP as a detected fallback before any backend is chosen
+
+---
+
+- U2. **Add chrome-MCP capture playbook (new Step 2e)**
+
+**Goal:** Document how to drive the chrome-MCP for capture, with output written to the existing enriched-capture JSON path so the downstream pipeline consumes it unchanged.
+
+**Requirements:** R5, R6
+
+**Dependencies:** U1
+
+**Files:**
+- Modify: `skills/printing-press/references/browser-sniff-capture.md` (insert new section after Step 2b, before Step 2c)
+
+**Approach:**
+- New `#### Step 2e: Claude chrome-MCP capture (failure-recovery fallback)` section
+- **Tab scope rule (mandatory):** always create a fresh tab via `tabs_create_mcp` for capture, even if a tab matching the target site appears in `tabs_context_mcp`. Close the capture tab when done. Never `navigate` an existing tab — that could redirect work the user has open. The `tabs_context_mcp` call is for awareness only, not for tab selection.
+- **Body-capture step (mandatory before navigation):** chrome-MCP's `read_network_requests` returns request metadata only — no response bodies. Before navigation, install a `fetch`/`XHR` interceptor via `javascript_tool` so response bodies are captured at original-request time. Mirrors the agent-browser enrichment pattern at lines 672-682 of the same file. The interceptor approach (vs re-fetching after the fact) avoids re-firing requests against a WAF that's already wary of the session.
+- Order of MCP calls: `tabs_context_mcp` (awareness) → `tabs_create_mcp` (fresh capture tab) → `javascript_tool` (install fetch/XHR interceptor) → `navigate` (open target) → interaction loop using `find` / `left_click` / `read_page` / `javascript_tool` → `read_network_requests` (request metadata) → merge with interceptor-captured response bodies → optional `get_page_text` for SSR shape → `tabs_close_mcp` (capture tab cleanup)
+- **Write-time credential strip (mandatory):** before writing to `$DISCOVERY_DIR/browser-sniff-capture.json`, scrub `Authorization`, `Cookie`, `Set-Cookie`, and any header matching `/^x-.*-(token|key|auth|session)$/i` from each entry's `request_headers` and `response_headers`. Cross-reference `secret-protection.md` for the canonical scrub list so the rules stay in one place.
+- **Artifact shape:** `EnrichedCapture` in `internal/browsersniff/types.go` (top-level: `target_url`, `captured_at`, `interaction_rounds`, `auth`, `entries[]`; per-entry: `method`, `url`, `request_headers`, `response_headers`, `request_body`, `response_body`, `response_status`, `response_content_type`, `classification`, `is_noise`). Write to `$DISCOVERY_DIR/browser-sniff-capture.json`.
+- **Pacing scope:** when the playbook drives navigation loops or fires `javascript_tool`-initiated fetch/XHR requests, those operations inherit the existing adaptive-pacing posture (start at 1s, double on 429, 30s pause after 3 consecutive 429s) at lines 36-46 of the same file. `read_network_requests` is observational and does not pace.
+- Cross-reference the existing replayability check at the cardinal-rules section
+- Note the constraint that chrome-MCP requires a visible Chrome window with the extension installed; user-side setup link or `/pair-agent` reference if applicable
+- Note the auth advantage: chrome-MCP uses the user's already-logged-in Chrome session by default — no cookie transfer step needed, unlike Step 1d
+
+**Patterns to follow:**
+- Existing Step 2a (browser-use) and Step 2b (agent-browser) section structure: capture commands → enrichment → output path → replayability check
+- Adaptive-pacing reference, not restatement
+- AGENTS.md prose-placeholder rule: use `<api>`, `<site>`, "the target site" — concrete names only in `Example:` paragraphs
+
+**Test scenarios:**
+- Happy path: agent invokes chrome-MCP capture against a non-blocked site, produces `browser-sniff-capture.json` with at least 5 unique endpoints, and `printing-press browser-sniff --har <path>` (which accepts the enriched-JSON shape) generates a spec without error
+- Edge case: chrome-MCP returns empty network requests (page didn't fire XHRs) -> playbook instructs scroll/click before re-reading network requests
+- Edge case: chrome-MCP captures a page behind a CAPTCHA -> the user's Chrome session has the cleared cookies; capture proceeds; replayability check still applies to the captured surface
+- Error path: `tabs_context_mcp` returns no tabs -> playbook instructs creating one via `tabs_create_mcp`
+- Error path: chrome-MCP extension not connected -> playbook instructs the connection prompt and falls through to the next menu option without aborting capture
+- Integration: the captured artifact at `$DISCOVERY_DIR/browser-sniff-capture.json` flows through `internal/browsersniff/parser.go` ParseEnriched without modification
+
+**Verification:**
+- Manual test: drive the chrome-MCP playbook against `vrbo.com` (the site that hard-blocked `agent-browser` in the user's session), verify capture produces a usable enriched-JSON. The `vrbo.com` reference appears only in this plan's verification step, not in the resulting SKILL.md edit — Step 2e prose MUST use placeholders (`<api>`, `<site>`, "the target site") per AGENTS.md.
+
+---
+
+- U3. **Expand Step 2c.5 failure-recovery menu**
+
+**Goal:** Replace the current 3-option recovery menu with an availability-aware menu that includes chrome-MCP when detected, and threads computer-use into the manual-HAR option as a visual-aid sub-flow.
+
+**Requirements:** R3, R4
+
+**Dependencies:** U1, U2 (the new Step 2e the menu links to)
+
+**Files:**
+- Modify: `skills/printing-press/references/browser-sniff-capture.md` (Step 2c.5: Challenge-only capture safety check, lines 703-723)
+
+**Approach:**
+- Replace the static 3-option `AskUserQuestion` block with an availability-aware variant per the composition table below.
+
+**Menu composition table** (one row per flag combination):
+
+| Chrome-MCP | Computer-use | Menu options (in order) |
+|---|---|---|
+| no | no | Try cleared-browser, Manual HAR, Alternate scope (3 options, current behavior unchanged) |
+| no | yes | Try cleared-browser, Manual HAR with screenshot guidance, Alternate scope (3 options) |
+| yes | no | Try cleared-browser, Try chrome-MCP (Recommended on anti-bot trigger), Manual HAR, Alternate scope (4 options) |
+| yes | yes | Try cleared-browser, Try chrome-MCP (Recommended on anti-bot trigger), Manual HAR with screenshot guidance, Alternate scope (4 options) |
+
+**Recommended badge rule (explicit):** When an anti-bot block triggered the recovery menu, chrome-MCP carries the Recommended badge whenever it is present in the menu, regardless of whether computer-use is also detected. In other failure modes (thin results, time-budget bailout), no option carries the Recommended badge — the user picks based on context.
+
+**Patterns to follow:**
+- Existing Step 2c.5 menu (lines 715-719) for label/body shape
+- Existing AskUserQuestion 4-option cap convention
+- "Recommended" badge convention (only when one option is unambiguously preferred for the situation)
+
+**Test scenarios:**
+- Happy path: anti-bot block detected, both flags true -> menu shows 4 options with chrome-MCP recommended; user picks chrome-MCP and Step 2e runs
+- Happy path: anti-bot block detected, only chrome-MCP available -> menu shows 4 options (computer-use sub-flow absent), chrome-MCP recommended
+- Happy path: anti-bot block detected, only computer-use available -> menu shows the existing 3 options with manual-HAR body augmented
+- Edge case: anti-bot block detected, neither flag true -> menu identical to today's (zero behavior change, no new entries)
+- Edge case: user picks chrome-MCP and chrome-MCP also fails -> menu re-fires with chrome-MCP option removed (cannot pick a backend that just failed); fall through to manual-HAR
+- Integration: the chosen backend's reason ("chrome-mcp", "manual-har-with-computer-use-screenshots", etc.) is recorded in the marker file's `reason` field
+
+**Verification:**
+- Replaying the `airbnb-vrbo` session against the updated reference: the menu offers chrome-MCP as the recommended option after `agent-browser` is blocked, and the user can pick it without manual intervention
+
+---
+
+- U4. **Refresh manual-HAR instructions with optional computer-use visual aid**
+
+**Goal:** Bring the DevTools HAR-export instructions up to Chrome 147+ layout (where "Save all as HAR with content" was removed from the right-click menu and the download-arrow icon is now the export path), and document the optional computer-use augmentation for visual verification.
+
+**Requirements:** R4, R7
+
+**Dependencies:** U1, U3 (U3 expands Step 2c.5; U4's manual-HAR body augmentation must layer on top of U3's expanded menu structure)
+
+**Files:**
+- Modify: `skills/printing-press/references/browser-sniff-capture.md` (Step 1d manual-HAR expansion at line 262, and the manual-HAR body in Step 2c.5 at line 717)
+
+**Approach:**
+- Update the DevTools click path: Network panel → top-left download-arrow icon (between the upload arrow and the record button) → Save dialog → save as `.har`
+- Note the legacy right-click "Save all as HAR with content" path no longer exists in Chrome 147+; the download-arrow icon is the only stable path
+- Add troubleshooting for common stuck states the user hit: wrong tab open, Recorder tab confused for Network tab, ">> overflow arrow" hiding the Network tab when DevTools is narrow
+- When `COMPUTER_USE_AVAILABLE=true`, add a visual-feedback-loop flow (NOT silent verification — the agent must close the loop with the user):
+  - **Before screenshotting:** instruct the user to collapse the Network panel detail pane (only the request list visible, not header/body detail). This reduces credential exposure surface in the captured PNG.
+  - Use computer-use `screenshot` to capture the user's Chrome window at each instruction checkpoint
+  - **After each screenshot:** the agent MUST display the image inline by Read'ing the PNG path AND describe what it sees in 1-2 sentences (e.g., "I see your DevTools is on the Recorder tab, not Network — click >> in the tab strip to switch"). The screenshot is part of the agent's reasoning + user-facing feedback, not a silent storage artifact.
+  - Save screenshots to `$DISCOVERY_DIR/devtools-help-*.png` for the agent's display loop and the user's reference
+  - **Phase 5.5 cleanup:** explicitly delete `$DISCOVERY_DIR/devtools-help-*.png` at archive time (PNGs are not archived). Computer-use augmentation produces ephemeral debug aids, not durable artifacts.
+- Cardinal-rule call-out: computer-use cannot click or type into Chrome (tier-"read" on browsers); it is visual-feedback-only — the agent describes what it sees back to the user, who clicks themselves
+
+**Patterns to follow:**
+- Existing Step 1d Chrome-running and Chrome-not-running branches (lines 184-262) for sub-path structure
+- Existing manual-HAR body in Step 2c.5 (line 717) for option-body wording
+
+**Test scenarios:**
+- Happy path: user follows refreshed instructions on Chrome 147, reaches the download-arrow icon on first attempt, exports HAR, returns the path
+- Edge case: user is on Chrome 146 or older where the right-click "Save all as HAR with content" still exists -> instructions still work because the download-arrow icon predates the right-click removal
+- Edge case: user is in dark-mode Chrome where the download-arrow icon contrast is reduced -> instructions name the icon position relative to the upload-arrow and record button
+- Edge case: computer-use available but user is on a non-macOS platform -> screenshot fallback degrades gracefully (instructions remain text-only, no error)
+- Integration: a HAR file produced via the refreshed flow flows through `internal/browsersniff/parser.go` LoadCapture without modification
+
+**Verification:**
+- Manual test on the user's Chrome 147 setup: user follows the refreshed text-only instructions, then re-runs with computer-use augmentation, verifies the export step succeeds in both modes
+
+---
+
+- U5. **Update SKILL.md Phase 1.7 disclosure language and Banned Skip Reasons**
+
+**Goal:** Mention the new backends in the Phase 1.7 AskUserQuestion disclosure language so users know what they are agreeing to, and add a Banned Skip Reasons entry preventing silent pivot when chrome-MCP is available.
+
+**Requirements:** R8, R9, R10
+
+**Dependencies:** U1, U2, U3
+
+**Files:**
+- Modify: `skills/printing-press/SKILL.md` (Phase 1.7 section at lines 781-1012; specifically the AskUserQuestion disclosure block around lines 949-970 and the Banned Skip Reasons list at lines 822-834)
+- Modify: `skills/printing-press/references/browser-sniff-capture.md` (cardinal rule 1 at line 12)
+
+**Approach:**
+- Cardinal rule 1 in `browser-sniff-capture.md`: extend the valid-fallbacks list to name chrome-MCP and computer-use alongside `browser-use` / `agent-browser` / manual-HAR
+- Phase 1.7 AskUserQuestion disclosure (SKILL.md ~line 949-970): when listing what the skill might do during browser-sniff, add a sentence noting that the chrome-MCP and computer-use may be offered as fallbacks if available
+- Add a new entry to the Banned Skip Reasons list (SKILL.md ~line 822-834): "**'The site is blocked by a WAF and our default browser-use/agent-browser hit a hard block'** — this is exactly when chrome-MCP and computer-use options enter. Do NOT pivot scope or fall back to RSS/docs without first asking the user via the recovery menu in Step 2c.5."
+- Note the marker-file `reason` field convention: when a backend other than `browser-use` or `agent-browser` is chosen, the reason should name it explicitly (e.g., `reason: "chrome-mcp captured 142 requests; SSR enriched after Akamai block"`)
+
+**Patterns to follow:**
+- Existing Banned Skip Reasons format (SKILL.md lines 824-830): bold quote of the rationale, dash, explanation
+- Existing disclosure-language convention in Phase 1.7 AskUserQuestion blocks
+- AGENTS.md "Default to machine changes" — the disclosure update is additive, doesn't break existing menu shapes
+
+**Test scenarios:**
+- Happy path: anti-bot block fires, agent reads Banned Skip Reasons, sees the new entry, fires Step 2c.5 menu instead of pivoting
+- Edge case: chrome-MCP unavailable -> Banned Skip Reasons new entry still applies (the menu still fires; it just has fewer options); pivot is still gated through the menu, not silent
+- Integration: marker file written for a chrome-MCP-recovered run names "chrome-mcp" in the reason field; downstream readers (Phase 1.5 pre-flight, future audit) can identify which backend was actually used
+
+**Verification:**
+- Replay the `airbnb-vrbo` session: at the moment `agent-browser` is hard-blocked, the agent does NOT pivot to manual-HAR-only; instead it fires the expanded Step 2c.5 menu and the marker file's `reason` field names the chosen backend
+
+---
+
+- U6. **Add browser-capture pointer to polish skill**
+
+**Goal:** When polish discovers it needs browser capture (rare but real, as in the user's airbnb-vrbo session), point the implementer at the shared playbook so the chrome-MCP and computer-use options are visible.
+
+**Requirements:** R11
+
+**Dependencies:** U2, U3 (the playbook and menu the pointer references)
+
+**Files:**
+- Modify: `skills/printing-press-polish/SKILL.md` (Phase 1 baseline diagnostics, around line 192)
+
+**Approach:**
+- One short paragraph or bullet noting that polish does not normally do browser capture, but if Phase 1 baseline reveals the underlying CLI needs re-discovery (broken extraction, sparse capture, etc.), the shared playbook at `skills/printing-press/references/browser-sniff-capture.md` covers all available capture backends including the chrome-MCP and computer-use
+- No duplication of the playbook itself
+- No new menus added to polish; this is a routing pointer only
+
+**Patterns to follow:**
+- Existing polish SKILL.md routing-pointer convention (e.g., references to `tools-polish.md`, `printing-press-output-review`)
+- AGENTS.md skill-authoring note: cross-skill shared content stays in one reference, with pointers from consumers
+
+**Test scenarios:**
+- Happy path: polish run hits a discovery-rework need, reads the new pointer, navigates to the shared playbook, finds chrome-MCP option
+- Edge case: polish run never needs browser capture -> pointer is invisible noise but not actively harmful
+- Test expectation: none for this unit -- pure documentation pointer with no behavioral logic
+
+**Verification:**
+- Read the polish SKILL.md after the edit and confirm the pointer is discoverable from Phase 1 baseline without disrupting the existing baseline-diagnostics flow
+
+---
+
+## System-Wide Impact
+
+- **Interaction graph:** the new chrome-MCP backend integrates with the runtime via the platform's deferred-tool loading mechanism (`ToolSearch`), shared by every Claude Code skill. No new global state.
+- **Error propagation:** a missing or unavailable MCP yields warn-then-empty per the multi-source-discovery doctrine; never aborts the surrounding capture flow. Failure inside a chosen backend (e.g., chrome-MCP also gets blocked) re-fires the recovery menu with the failed option removed.
+- **State lifecycle risks:** none. The new backend writes to the same `$DISCOVERY_DIR` path the existing pipeline already cleans up at run end. No new persistent state.
+- **API surface parity:** the marker-file schema is unchanged. Phase 1.5's pre-flight read of `browser-browser-sniff-gate.json` works without modification. Downstream audit tooling that parses `reason` strings continues to work because `reason` was already free-form.
+- **Integration coverage:** unit tests of `internal/browsersniff/parser.go` already cover the enriched-capture JSON shape that chrome-MCP will produce. No new Go tests required unless the playbook reveals a new edge case in the artifact shape.
+- **Unchanged invariants:** browser-sniff remains generation-time only; resident-browser sidecar transport stays banned (cardinal rule 5). Phase 1.7 marker file remains a hard gate. Default backend ordering (`browser-use` primary, `agent-browser` secondary) is preserved. Existing `browser-use` and `agent-browser` flows are unchanged when no failure occurs — defaults stay defaults; the new options enter only on failure-recovery (Step 2c.5) or as opt-in choices in the install/initial menus (Step 1b). [formerly R12, moved here as a non-regression invariant]
+
+---
+
+## Risks & Dependencies
+
+| Risk | Mitigation |
+|------|------------|
+| chrome-MCP capture produces a different shape than `internal/browsersniff` parses, breaking Phase 2 silently | U2 verification step: drive the playbook end-to-end and confirm `printing-press browser-sniff --har <path>` accepts the artifact unchanged. If parsing fails, the playbook instructions get tightened to match the existing shape, NOT the parser changed (avoids touching Go) |
+| Detection probe for `mcp__claude-in-chrome__*` returns false negatives on platforms where the deferred-tool list is not exposed (non-Claude-Code targets running the skill via plugin install) | Detection defaults to false on detection failure; behavior degrades to today's flow (no new options offered). Documented in U1 edge-case test |
+| The 4-option AskUserQuestion cap is hit when both new flags are true and we want all options visible | Computer-use folds into the manual-HAR option as a sub-flow rather than a separate top-level option. U3 approach already accounts for this |
+| User picks chrome-MCP and the Chrome extension is installed but disconnected | Playbook instructs the connection prompt; capture proceeds after connection. If user declines, the menu re-fires with chrome-MCP removed |
+| WAF that hard-blocked agent-browser also blocks chrome-MCP (Akamai may detect Chrome-extension automation) | Adaptive pacing carries forward (R6); replayability check still applies; user can fall through to manual-HAR. The new option isn't a guaranteed fix; it just exposes another path the runtime supports today |
+| Future Chrome version moves the DevTools download-arrow icon again | U4 troubleshooting section names common stuck states; the icon's position is described relative to fixed elements (record button, upload arrow). Computer-use augmentation provides visual verification when text instructions go stale |
+
+---
+
+## Documentation / Operational Notes
+
+- README.md and ONBOARDING.md make no claims about which capture backends are supported. No update needed.
+- CHANGELOG.md will get an entry on release per the standard `feat(skills):` line. release-please owns the version bump per `AGENTS.md` rules — do not manually bump.
+- After this plan ships, run `/ce-compound` on the WAF-fallback escalation pattern + MCP-availability detection convention. The learnings-researcher pass confirmed no prior docs exist on either; this plan creates the precedent worth capturing back into `docs/solutions/`.
+- No golden-output regeneration needed — pure SKILL.md and reference-file prose changes. `scripts/golden.sh verify` is for Go-side parser changes.
+
+---
+
+## Sources & References
+
+- User session transcript (2026-05-02 to 2026-05-03): `airbnb-vrbo` printing-press run that surfaced the gap, including manual chrome-MCP intervention
+- `skills/printing-press/references/browser-sniff-capture.md`
+- `skills/printing-press/SKILL.md` (Phase 1.7)
+- `skills/printing-press-polish/SKILL.md`
+- `internal/cli/browser_sniff.go`, `internal/browsersniff/parser.go`
+- `docs/solutions/best-practices/sniff-and-crowd-sniff-complementary-discovery-2026-03-30.md`
+- `docs/solutions/best-practices/adaptive-rate-limiting-sniffed-apis.md`
+- `docs/solutions/best-practices/multi-source-api-discovery-design-2026-03-30.md`
+- Prior plan precedent: `docs/plans/2026-04-11-001-fix-sniff-gate-enforcement-plan.md`, `docs/plans/2026-04-03-001-fix-sniff-auth-graphql-naming-plan.md`, `docs/plans/2026-04-21-001-feat-browser-sniff-traffic-analysis-plan.md`
diff --git a/skills/printing-press-polish/SKILL.md b/skills/printing-press-polish/SKILL.md
index 360aae08..93c4c049 100644
--- a/skills/printing-press-polish/SKILL.md
+++ b/skills/printing-press-polish/SKILL.md
@@ -216,6 +216,8 @@ go vet ./... 2>&1
 
 verify-skill and workflow-verify run alongside dogfood/verify/scorecard so polish catches the same class of failures the public-library CI catches. Polish hard-gates `ship` on `verify-skill` exit 0 (see ship logic at the end).
 
+**If Phase 1 baseline reveals the underlying CLI needs re-discovery** — broken HTML/SSR extraction, sparse capture (fewer than 5 unique endpoints in the source manuscript), wrong endpoint shapes, missing GraphQL operation hashes, or any signal that the CLI was generated from incomplete capture — polish does not normally do browser capture itself, but the shared playbook at `skills/printing-press/references/browser-sniff-capture.md` covers all available capture backends including the Claude chrome-MCP (`mcp__claude-in-chrome__*`) and computer-use (`mcp__computer-use__*`) when the runtime exposes them. Read Step 1 (tool detection), Step 2c.5 (failure-recovery menu), and Step 2e (chrome-MCP capture playbook) of that reference before improvising. Re-discovery from polish is rare but real; when it happens, use the shared backends — do not invent a new capture flow.
+
 Parse findings into categories:
 
 | Category | Source | What to look for |
diff --git a/skills/printing-press/SKILL.md b/skills/printing-press/SKILL.md
index 1e11724a..5422cb42 100644
--- a/skills/printing-press/SKILL.md
+++ b/skills/printing-press/SKILL.md
@@ -782,9 +782,13 @@ Set `AUTH_SESSION_AVAILABLE=true` if the user selects option 1 or 2. The Browser
 
 After Phase 1 research, evaluate whether browser-sniffing the live site would improve the spec. This phase MUST produce a decision marker file for every source named in the briefing before Phase 1.5 can proceed.
 
-**Browser discovery is temporary discovery, not a printed-CLI runtime.** Use browser-use, agent-browser, or a manual HAR to learn the hidden web contract: URLs, methods, persisted GraphQL hashes, BFF envelopes, response shapes, cookies, CSRF/header construction, HTML/SSR/RSS/JSON-LD surfaces, and whether replay is viable. The final printed CLI must use replayable HTTP, Surf/browser-compatible HTTP, browser-clearance cookie import plus replay, or structured HTML/SSR/RSS extraction. If the only working path requires live page-context execution, HOLD or pivot scope — do not generate a resident browser sidecar transport.
+**Browser discovery is temporary discovery, not a printed-CLI runtime.** Use browser-use, agent-browser, the Claude chrome-MCP (`mcp__claude-in-chrome__*`, when the runtime exposes it), or a manual HAR (optionally augmented with computer-use screenshots for visual guidance, when `mcp__computer-use__*` is exposed) to learn the hidden web contract: URLs, methods, persisted GraphQL hashes, BFF envelopes, response shapes, cookies, CSRF/header construction, HTML/SSR/RSS/JSON-LD surfaces, and whether replay is viable. The final printed CLI must use replayable HTTP, Surf/browser-compatible HTTP, browser-clearance cookie import plus replay, or structured HTML/SSR/RSS extraction. If the only working path requires live page-context execution, HOLD or pivot scope — do not generate a resident browser sidecar transport.
 
-**Automatic offer, explicit consent.** The Printing Press decides when browser discovery should be offered, but opening Chrome, attaching to a browser session, installing browser-use/agent-browser, or asking the user to solve a challenge requires explicit user approval through the Phase 0 website choice or the Phase 1.7 `AskUserQuestion` prompt.
+**Automatic offer, explicit consent.** The Printing Press decides when browser discovery should be offered, but opening Chrome, attaching to a browser session, installing browser-use/agent-browser, asking the user to solve a challenge, or driving the user's logged-in Chrome via the chrome-MCP requires explicit user approval through the Phase 0 website choice or the Phase 1.7 `AskUserQuestion` prompt. **Approval at Phase 1.7 covers the full fallback set** including chrome-MCP and computer-use when Step 2c.5's recovery menu later offers them — picking chrome-MCP at the recovery menu is a refinement of the Phase 1.7 consent, not a new consent surface. The disclosure language used at the Phase 1.7 prompt MUST enumerate these possibilities so the user understands what they are approving:
+
+> "Approving browser-sniff means the agent may run browser-use, agent-browser, ask you for a manual DevTools HAR export, or — if the default backends get blocked by an anti-bot gate and your runtime exposes them — drive your already-running Chrome via the chrome-MCP browser extension, or take read-only screenshots of your DevTools window via computer-use to guide you through the HAR export. Capture artifacts are written to `$DISCOVERY_DIR/` and credential headers are stripped at write time. The chrome-MCP option uses your real logged-in Chrome session in a fresh capture tab; the agent never navigates your existing tabs."
+
+If chrome-MCP picks up later in Step 2c.5's recovery menu, do NOT re-fire a per-invocation consent prompt — Phase 1.7's pre-approval covers it. The recovery menu lists chrome-MCP as one of the fallback options the user already pre-approved; the user's selection in the menu is a backend choice, not a new consent step.
 
 ### Enforcement: the browser-browser-sniff-gate.json marker file
 
@@ -830,6 +834,7 @@ The following rationales are NOT valid reasons to skip the browser-sniff gate. I
 - **"Installing browser-use or agent-browser is friction"** — the browser-sniff capture reference already documents the install path. Tooling friction is not a valid skip reason. Ask.
 - **"The documentation looks thorough enough"** — the decision matrix already handles this case explicitly. If research found that competitors or community projects reference more endpoints than the spec covers, that IS a gap and you MUST ask.
 - **"The user said 'let's go' earlier and implicitly approved everything"** — "let's go" at the briefing stage is consent to proceed with research, not standing approval for every future decision. Ask each gate individually.
+- **"The default browser-use / agent-browser path got hard-blocked by a WAF, so the only remaining option is to pivot scope or fall back to RSS/docs"** — this is exactly when the chrome-MCP and computer-use fallback options enter, when the runtime exposes them. Step 1 of `references/browser-sniff-capture.md` detects which fallback MCPs are available; Step 2c.5 composes the recovery menu including those fallbacks; the gate is "ask before giving up," not "auto-pivot when blocked." Do NOT skip the Step 2c.5 menu. Do NOT pivot scope or substitute an alternate target without first asking the user via that menu.
 
 These banned reasons all fired at once in a past combo-CLI run and caused a user-critical source to be silently swapped out. The marker file exists so this cannot happen again. If you find yourself writing a phrase like "skipping browser-sniff because X" where X is one of the above, stop and call `AskUserQuestion`.
 
diff --git a/skills/printing-press/references/browser-sniff-capture.md b/skills/printing-press/references/browser-sniff-capture.md
index 52f88646..8f3c3cee 100644
--- a/skills/printing-press/references/browser-sniff-capture.md
+++ b/skills/printing-press/references/browser-sniff-capture.md
@@ -9,7 +9,7 @@
 
 ### Cardinal Rules
 
-1. **Prefer browser-use CLI mode for capture, but keep valid fallbacks.** Use browser-use CLI mode when available because it gives stable open/eval/scroll control and response interception without an LLM key. If browser-use is unavailable or incompatible, use agent-browser only when it can produce equivalent network capture artifacts, or ask the user for a manual DevTools HAR. Do NOT substitute curl probing, JS bundle grepping, or agent-browser auto-connect alone for an approved browser capture.
+1. **Prefer browser-use CLI mode for capture, but keep valid fallbacks.** Use browser-use CLI mode when available because it gives stable open/eval/scroll control and response interception without an LLM key. If browser-use is unavailable or incompatible, the valid fallback set is: `agent-browser` (when it can produce equivalent network capture artifacts), the Claude chrome-MCP (`mcp__claude-in-chrome__*` — drives the user's existing Chrome session via the browser extension; see Step 2e), computer-use as a visual-feedback aid for the manual-HAR flow (`mcp__computer-use__*` — read-only on browsers, used to take screenshots and guide the user; see Step 1d's manual-HAR expansion), or asking the user for a manual DevTools HAR. Do NOT substitute curl probing, JS bundle grepping, or agent-browser auto-connect alone for an approved browser capture. Detection of which fallbacks are actually available happens in Step 1; menu composition for failure-recovery selection is in Step 2c.5. Rule 5 (replayability) applies to all of these — fallback shape does not relax the success criterion.
 
 2. **Do NOT skip auth discovery when the session expires.** *(Only applies when `AUTH_SESSION_AVAILABLE=true` — the user confirmed they're logged in.)* If a Chrome profile loads but the session has expired (login page visible instead of account page), offer headed login as a fallback. Never proceed without auth just because the profile session was stale. For anonymous sniffs (no auth context), this rule does not apply.
 
@@ -79,6 +79,19 @@ If a tool is found, report: "Using **<tool>** for temporary traffic capture duri
 
 **Important:** browser-use has two modes: autonomous Agent mode (requires an LLM API key like ANTHROPIC_API_KEY) and CLI mode (open/eval/scroll — no key needed). **Always use CLI mode for browser-sniff.** It is more reliable, version-stable, and does not require the user to provide an additional API key. Do NOT attempt to use browser-use's Python `Agent` class — it requires an LLM key that may not be available.
 
+**Also detect: optional MCP-driven fallback backends.** Two additional capture options exist when the runtime exposes them — they enter only on failure-recovery in Step 2c.5 or as opt-in choices in Step 1b's install picker, never as defaults. Detection is **agent-prose, not shell-probe** — the agent inspects its own available and deferred tool lists (visible in system reminders / the deferred-tool block / `ToolSearch` catalog) and asserts the flags inline in its reasoning. Bash blocks cannot read the agent's own tool registry; do not write `command -v mcp__claude-in-chrome__` style probes.
+
+> **Inspect your tool catalog now and assert these flags in your reasoning, not as shell vars.** They are read by Step 2c.5 (recovery menu composition) and Step 2e (chrome-MCP capture playbook) later in this same conversation turn.
+>
+> - If `mcp__claude-in-chrome__*` tools appear in your available or deferred tool list, set `CHROME_MCP_AVAILABLE=true`. Otherwise `false`.
+> - If `mcp__computer-use__*` tools appear in your available or deferred tool list, set `COMPUTER_USE_AVAILABLE=true`. Otherwise `false`.
+> - The probe is intentionally cheap — actual schema loading via `ToolSearch` is deferred until the user picks the option from a menu.
+> - On platforms that don't expose a deferred-tool list (non-Claude-Code targets running this skill via plugin install), the agent observes neither MCP and both flags default to `false`. Downstream behavior is unchanged from today's.
+
+If either MCP flag is true, extend the status report:
+
+> "Using **<tool>** for traffic capture. Fallbacks available: chrome-MCP, computer-use." (list whichever flags are true)
+
 #### Step 1b: Install capture tool (if none found)
 
 If neither tool is installed, offer to install via `AskUserQuestion`. Do not install automatically:
@@ -259,7 +272,28 @@ agent-browser state save "$DISCOVERY_DIR/session-state.json"
 ```
 Close the headed browser and restart headless with the saved state.
 
-**For HAR export (option 3):** Guide the user through DevTools > Network > Save all as HAR. Then use `--har` path. Make clear that a HAR is discovery input, not a promise that every captured HTML/XHR route becomes a printed CLI command. After analyzing the HAR, keep only surfaces that replay through lightweight HTTP/Surf/browser-compatible HTTP, browser-clearance cookie import plus replay, or structured HTML/SSR/RSS extraction. If the HAR only proves live page-context execution works, HOLD or pivot scope.
+**For HAR export (option 3):** Guide the user through the DevTools HAR-export flow. Make clear that a HAR is discovery input, not a promise that every captured HTML/XHR route becomes a printed CLI command. After analyzing the HAR, keep only surfaces that replay through lightweight HTTP/Surf/browser-compatible HTTP, browser-clearance cookie import plus replay, or structured HTML/SSR/RSS extraction. If the HAR only proves live page-context execution works, HOLD or pivot scope.
+
+**Chrome 147+ DevTools HAR export — concrete instructions.** Recent Chrome versions (147+) removed "Save all as HAR with content" from the right-click menu in the Network panel. The download-arrow icon at the top of the Network panel is now the only stable export path. Walk the user through these steps in order — they are the steps a user got stuck on in a recent session, so the language is deliberately literal:
+
+1. **Open DevTools.** `Cmd+Option+I` (macOS) or `Ctrl+Shift+I` (Windows/Linux). If DevTools is already open but on the wrong tab, the next step covers it.
+2. **Switch to the Network panel.** It is in the top tab strip alongside Elements, Console, Sources, Performance. If DevTools is narrow, the Network tab may be hidden behind a `>>` overflow chevron at the right end of the tab strip — click `>>` and pick **Network**. Do not pick "Recorder" — that is a different panel.
+3. **Confirm recording is on.** A red dot at the top-left of the Network panel means recording is on. If it is gray/black, click it once to enable.
+4. **Check "Preserve log" and "Disable cache"** — both are checkboxes in the Network panel toolbar. Preserve log keeps records across navigations; disable cache forces fresh requests so the HAR contains real network activity.
+5. **Clear any prior requests.** Click the 🚫 (clear / no-entry) icon in the toolbar to start with an empty log.
+6. **Reproduce the user flow on the target site** — navigate, click into the section the printed CLI needs, scroll, interact. Wait for network activity to settle between actions.
+7. **Export the HAR.** Click the **download-arrow icon** at the top-left of the Network panel toolbar (between the upload-arrow icon `↑` and the record/clear icons — it looks like a `↓` arrow with a horizontal bar underneath). A macOS/Windows save dialog opens. Save as `<api>-capture.har` somewhere accessible like `~/Downloads/`.
+8. **Tell the agent the path.** The agent runs `printing-press browser-sniff --har <path>` next.
+
+**Computer-use visual-feedback-loop (only when `COMPUTER_USE_AVAILABLE=true`).** Computer-use cannot click or type into Chrome (browsers are tier-"read" — visible in screenshots, but input is blocked). Its value here is closing the loop with the user when text instructions get them stuck. Pattern:
+
+1. **Before screenshotting, instruct the user to collapse the Network panel detail pane** so only the request list is visible. The detail pane shows full request and response headers including `Authorization` and `Cookie`; collapsing it before each screenshot keeps credentials out of the captured PNG. (Click the `×` on any open request detail, or click in the request list to deselect.)
+2. **Take a screenshot via `mcp__computer-use__screenshot`** at each instruction checkpoint (after step 1, after step 2, after step 7).
+3. **Display the screenshot inline AND describe what the agent sees in 1-2 sentences.** This is mandatory — silent storage helps no one. Pattern: `Read` the saved PNG path so the image shows in the response, then say something like "I see your DevTools is on the Recorder tab, not Network — click `>>` in the tab strip and pick Network." The screenshot becomes part of the agent's reasoning AND the user-facing feedback.
+4. **Save screenshots to `$DISCOVERY_DIR/devtools-help-*.png`** during the session so they're available for inline display and so manuscripts archiving can clean them up.
+5. **Phase 5.5 cleanup:** the archive-time cleanup must explicitly delete `$DISCOVERY_DIR/devtools-help-*.png` — these are ephemeral debug aids, not durable artifacts, and the text-based credential scrubber in `secret-protection.md` cannot redact PNG contents. Make sure the `cleanup` block in the run wrap-up includes `rm -f "$DISCOVERY_DIR"/devtools-help-*.png 2>/dev/null` or equivalent.
+
+If `COMPUTER_USE_AVAILABLE=false`, the text-only instructions above stand on their own. Do not skip them just because computer-use isn't available — the click path itself is the load-bearing fix.
 
 **After any session transfer method**, verify cookies transferred before proceeding:
 
@@ -686,6 +720,111 @@ If browser-use is not available, use agent-browser with Claude driving the explo
    agent-browser network har stop "$DISCOVERY_DIR/browser-sniff-capture.har"
    ```
 
+#### Step 2e: Claude chrome-MCP capture (failure-recovery fallback)
+
+Use this backend when (a) the user picks chrome-MCP from the Step 2c.5 recovery menu after `browser-use` or `agent-browser` was hard-blocked by an anti-bot gate, or (b) the user opted into chrome-MCP up-front from the Step 1b install picker. Detection is set in Step 1 (`CHROME_MCP_AVAILABLE`). Skip this section entirely if `CHROME_MCP_AVAILABLE=false`.
+
+**Why chrome-MCP exists as a fallback.** chrome-MCP drives the user's already-running Chrome via a browser extension, so capture happens inside the user's logged-in session — no cookie transfer step (unlike Step 1d), and the WAF sees a real Chrome instance with the user's normal fingerprint. This is exactly what unblocks targets that hard-blocked headless Chromium-based capture (browser-use, agent-browser) under Akamai / DataDome / sophisticated bot detection.
+
+**Auth surface caveat.** chrome-MCP captures every request the user's tab fires, including ones carrying `Authorization` headers, session cookies, OAuth tokens, and JWTs from the live session. The credential strip rules below are mandatory, not advisory.
+
+**Prerequisites.**
+
+- The Chrome browser extension for chrome-MCP must be installed and connected. If `tabs_context_mcp` returns an error indicating the extension isn't connected, instruct the user via `AskUserQuestion` to connect the extension and retry. If they decline, fall back to the Step 2c.5 recovery menu with chrome-MCP removed (the menu re-fires per the menu re-fire rule in Step 2c.5).
+- Chrome must be visible and unminimized (chrome-MCP cannot drive a hidden window).
+- For authenticated discovery: the user should already be logged in to `<site>` in their Chrome session. No separate cookie transfer step.
+
+**Tab scope rule (mandatory — not optional).**
+
+Always create a fresh capture tab via `mcp__claude-in-chrome__tabs_create_mcp`, even if `tabs_context_mcp` shows a tab already open at `<site>`. Reasons:
+
+- The user's existing tab may have unsaved work (a draft message, a partially-filled form, a search the user is mid-way through). Navigating it away is data loss.
+- Other open tabs may be sensitive (banking, internal tools, personal email). The agent has no way to classify them; the safe default is to never touch them.
+- A fresh tab gives the agent a clean DOM and clean network log scoped to the discovery target.
+
+`tabs_context_mcp` is called for awareness only — to confirm the extension is connected and to log how many tabs the user has open. **Never `navigate` an existing tab.** Always `tabs_create_mcp` → `navigate` in the new tab. After capture, close the capture tab via `mcp__claude-in-chrome__tabs_close_mcp` so the user's tab strip returns to its original state.
+
+**Body-capture interceptor (mandatory — install BEFORE navigation).**
+
+`mcp__claude-in-chrome__read_network_requests` returns request metadata (URL, method, request headers, response status) but **does not include response bodies**. The downstream `internal/browsersniff/parser.go` consumer requires `response_body` populated per entry, so an extra step is mandatory.
+
+Two viable approaches:
+
+1. **Recommended: in-page interceptor installed before navigation.** Use `mcp__claude-in-chrome__javascript_tool` to install a `fetch` and `XMLHttpRequest` interceptor in the new tab BEFORE navigating to `<site>`. The interceptor pushes each completed request's body into `window.__capture_bodies` keyed by URL+method. After capture, `javascript_tool` reads `window.__capture_bodies` back. This avoids re-firing requests against a wary WAF.
+
+2. **Fallback: `javascript_tool` re-fetches each captured URL after the fact.** Mirrors the `agent-browser network request <id> --json` enrichment loop in Step 2b. Use this only when option 1 fails (e.g., the page wraps `fetch` itself and the interceptor can't shadow it). Re-fetching may trip rate limits — apply the pacing rules below.
+
+The interceptor sketch (illustrative, adapt to the page's actual fetch shape):
+
+```javascript
+// Run via mcp__claude-in-chrome__javascript_tool BEFORE mcp__claude-in-chrome__navigate
+window.__capture_bodies = {};
+const _origFetch = window.fetch;
+window.fetch = async function(...args) {
+  const resp = await _origFetch.apply(this, args);
+  const cloned = resp.clone();
+  const url = typeof args[0] === 'string' ? args[0] : args[0].url;
+  const method = (args[1] && args[1].method) || 'GET';
+  cloned.text().then(body => {
+    window.__capture_bodies[`${method} ${url}`] = body;
+  }).catch(() => {});
+  return resp;
+};
+// XHR interceptor analogous; install both
+```
+
+**Capture flow (full sequence).**
+
+1. `mcp__claude-in-chrome__tabs_context_mcp` — awareness only; confirm extension is connected
+2. `mcp__claude-in-chrome__tabs_create_mcp` — fresh capture tab
+3. `mcp__claude-in-chrome__javascript_tool` — install fetch + XHR body interceptor in the new tab
+4. `mcp__claude-in-chrome__navigate` — open the discovery target URL
+5. Interaction loop (per the same "click + scroll + interact" guidance the browser-use flow uses):
+   - `mcp__claude-in-chrome__read_page` to find interactive elements
+   - `mcp__claude-in-chrome__find` + `mcp__claude-in-chrome__left_click` (or `form_input` for forms) to interact
+   - For SPAs that hydrate via JS without a fresh navigation, do at least 3 meaningful interactions before reading the network log
+6. `mcp__claude-in-chrome__read_network_requests` — pull request metadata
+7. `mcp__claude-in-chrome__javascript_tool` — read back `window.__capture_bodies`
+8. Optional: `mcp__claude-in-chrome__get_page_text` for SSR-rendered content
+9. Merge metadata + bodies into the enriched-capture JSON shape (next subsection)
+10. `mcp__claude-in-chrome__tabs_close_mcp` — clean up the capture tab
+
+**Output format.**
+
+Write to `$DISCOVERY_DIR/browser-sniff-capture.json` using the `EnrichedCapture` shape from `internal/browsersniff/types.go`:
+
+- Top-level: `target_url`, `captured_at` (RFC3339), `interaction_rounds` (count of meaningful interactions), `auth` (object describing how auth flows for this capture; `{"type": "chrome_mcp_session", "site": "<site>"}` is fine), `entries[]`
+- Per-entry: `method`, `url`, `request_headers` (object), `response_headers` (object), `request_body` (string, may be empty), `response_body` (string, populated from interceptor), `response_status` (int), `response_content_type` (string), `classification` (leave empty; analyzer fills), `is_noise` (leave false; analyzer fills)
+
+This is the same shape `agent-browser`'s enriched-capture JSON uses (Step 2b lines 685-695), so downstream parsing is unchanged.
+
+**Write-time credential strip (mandatory — not optional).**
+
+Before writing the entry to `$DISCOVERY_DIR/browser-sniff-capture.json`, scrub credentials from `request_headers` and `response_headers`:
+
+- Remove headers with names matching (case-insensitive): `Authorization`, `Cookie`, `Set-Cookie`, `Proxy-Authorization`, `X-Api-Key`, `X-Auth-Token`, `X-Session-Id`, and any header matching the regex `/^x-.*-(token|key|auth|session|secret)$/i`.
+- For URLs containing query parameters that look like tokens (`access_token=`, `api_key=`, `token=`, `key=`, `signature=`, `auth=`, `password=`), redact the value to `REDACTED` in the stored URL.
+
+Cross-reference `secret-protection.md` for the canonical scrub list — when the canonical list updates, this section must update too. The strip happens at write time so the artifact never sits on disk with live credentials, even briefly. Phase 5.5 archive-time strip is a defense-in-depth backstop, not the primary control for chrome-MCP captures.
+
+**Pacing scope.**
+
+The adaptive-pacing rules at the top of "If user approves browser-sniff" (start at 1s, ramp down on success, double on 429, hard-stop after 3 consecutive 429s) apply to operations the agent initiates: `navigate` between pages, `javascript_tool`-fired `fetch()` calls, and any re-fetch loop in the fallback body-capture approach. They do **not** apply to `read_network_requests` itself — that's observational and reads what the page already fired. Apply pacing where the agent is the request source, not the observer.
+
+**Failure detection (multi-trigger).**
+
+A chrome-MCP capture has not succeeded just because `read_network_requests` returned 142 entries — the entries may all be challenge-page noise. Before reporting success, check all three triggers; any one means "WAF is also blocking chrome-MCP, treat as capture failure":
+
+1. **HTTP status pattern.** Count entries by status. If fewer than 30% returned 2xx, OR more than 30% returned 403/429, the capture is failing.
+2. **Body markers.** Scan response bodies for known challenge sentinels: `Just a moment` (Cloudflare), `cf_chl_opt` (Cloudflare), `_abck` references in HTML (Akamai), `<title>Access Denied</title>` (Akamai/F5), `Pardon Our Interruption` (PerimeterX), `<title>Bot or Not?</title>` (Akamai). Any sentinel in any body triggers detection.
+3. **Page sentinel.** `mcp__claude-in-chrome__get_page_text` after the interaction loop — if the visible page contains "verifying you are human", "checking your browser", "captcha" (case-insensitive), or "access denied", treat as challenge.
+
+When any trigger fires, do NOT write the artifact. Re-fire the Step 2c.5 recovery menu with chrome-MCP removed from the option list (per the menu re-fire rule in Step 2c.5). Record the failure in the marker file's `reason` field: `chrome-mcp captured N requests but failure detection triggered: <which trigger fired>`.
+
+**Replayability check.**
+
+Even when failure detection passes, the same replayability constraint from cardinal rule 5 applies: the captured surface must round-trip through Surf with the same Chrome TLS fingerprint the printed CLI will ship, or the captured URLs are unusable in production. Do not skip this check just because the user's authenticated browser session worked — the printed CLI does not have the user's authenticated browser session.
+
 #### Step 2c: Thin-results safety check
 
 After completing the primary user flow capture (browser-use or agent-browser), count unique API endpoints discovered. If fewer than 5 unique endpoints:
@@ -710,15 +849,49 @@ Treat the capture as failed when all or nearly all captured target-site response
 - only login redirects/pages when the user expected an authenticated capture
 - no API-looking requests, no SSR embedded data, no structured HTML/feed data, and no page-context fetch evidence
 
-When this happens, do not continue to Phase 2 with a challenge-page spec. Present via `AskUserQuestion`:
+When this happens, do not continue to Phase 2 with a challenge-page spec. Compose the recovery menu **per the availability of the MCP fallback flags set in Step 1** — the menu shape changes based on what's reachable in this runtime. Use the table below to pick the option set, then present via `AskUserQuestion`.
+
+**Menu composition table.** Always read `CHROME_MCP_AVAILABLE` and `COMPUTER_USE_AVAILABLE` from your reasoning (set in Step 1). Pick the row matching the flag combination:
+
+| `CHROME_MCP_AVAILABLE` | `COMPUTER_USE_AVAILABLE` | Menu options (in order) |
+|---|---|---|
+| false | false | (1) Try cleared-browser capture again, (2) I'll provide a HAR from DevTools, (3) Discuss alternate CLI scope — current behavior, no change |
+| false | true | (1) Try cleared-browser capture again, (2) I'll provide a HAR from DevTools — I'll guide you with screenshots of your DevTools window, (3) Discuss alternate CLI scope |
+| true | false | (1) Try cleared-browser capture again, (2) **Try chrome-MCP** — recommended on anti-bot trigger, (3) I'll provide a HAR from DevTools, (4) Discuss alternate CLI scope |
+| true | true | (1) Try cleared-browser capture again, (2) **Try chrome-MCP** — recommended on anti-bot trigger, (3) I'll provide a HAR from DevTools — I'll guide you with screenshots of your DevTools window, (4) Discuss alternate CLI scope |
+
+**Recommended-badge rule.** When the menu fires because of an anti-bot block (the trigger criteria above: 403/429 with WAF markers, "Just a moment", challenge titles, login-redirect-only when authenticated capture was expected), chrome-MCP carries the **(Recommended)** badge whenever it is present in the menu, regardless of whether computer-use is also detected — chrome-MCP is the highest-leverage path against an anti-bot block because it uses the user's real Chrome session. In other failure modes (thin results from the Step 2c check, time-budget bailout), no option carries the Recommended badge — let the user pick based on context.
+
+**Question stem (teach the chrome-MCP mechanic when present).** When chrome-MCP is in the menu and the user has not seen this menu before in the current session, the question stem must teach the mechanic in one line. The user is mid-failure and may have never encountered chrome-MCP-as-fallback.
+
+When chrome-MCP IS in the menu:
+
+> "The browser capture only saw challenge or login pages, so it did not discover the real website data/API surface. The Chrome-extension MCP can capture from your existing Chrome window — pick this if your Chrome is open and you're already logged in to the target site. What should we do next?"
+
+When chrome-MCP is NOT in the menu (current 3-option case, unchanged):
 
 > "The browser capture only saw challenge or login pages, so it did not discover the real website data/API surface. What should we do next?"
->
-> 1. **Try cleared-browser capture again** — "Open/attach Chrome, solve the challenge, then repeat the browser-sniff."
-> 2. **I'll provide a HAR from DevTools** — "You browse the target site in Chrome and export the HAR. I analyze it for discovery, then keep only routes that pass replayability checks."
-> 3. **Discuss alternate CLI scope** — "Only now consider RSS/docs/official API/browser-backed command scope."
 
-Only option 3 may lead to an RSS-first, official API, docs-only, or narrower-scope proposal. Record the failed capture in `$DISCOVERY_DIR/browser-sniff-report.md` if a report is written.
+**Fixed option labels and bodies.** Use these exact strings as the `AskUserQuestion` option labels and descriptions — the implementer should not paraphrase. Labels are short (4-7 words), self-contained (some harnesses render labels without descriptions), and front-load the differentiator. Composition is per the table above; pick the option set for the flag combination, then mark Recommended where the rule above says.
+
+- **"Try cleared-browser capture again"** — "Open/attach Chrome, solve the challenge, then repeat the browser-sniff with the previous backend."
+- **"Try chrome-MCP"** — "Capture from your already-running Chrome window via the Chrome extension MCP. Uses your logged-in session, no cookie transfer. The agent will create a fresh tab and close it when done."
+- **"I'll provide a HAR from DevTools"** — "You browse the target site in your Chrome and export a HAR. The agent analyzes it for discovery, then keeps only routes that pass replayability checks."
+- **"I'll provide a HAR from DevTools — I'll guide you with screenshots of your DevTools window"** — "Same as 'I'll provide a HAR from DevTools', plus the agent uses computer-use to take screenshots of your Chrome window at each step and tells you what it sees so you don't get stuck on the export flow."
+- **"Discuss alternate CLI scope"** — "Step away from this discovery target and consider RSS/docs/official API/narrower-scope proposals. Only pick this when the other options have been tried."
+
+**Routing on selection.**
+
+- "Try cleared-browser capture again" → re-run the previously-attempted backend (browser-use or agent-browser) per the existing capture flow. If it fails again with the same trigger, re-fire this menu with this option's body amended to "(this option already failed once; consider another path)" — the option stays in the menu but loses any badge.
+- "Try chrome-MCP" → load the chrome-MCP MCP tools via `ToolSearch` (`select:mcp__claude-in-chrome__*`), then proceed to **Step 2e** for the capture playbook.
+- "I'll provide a HAR from DevTools" (either variant) → proceed to the manual-HAR flow at Step 1d (the existing branch). When the user picks the augmented variant, the manual-HAR body augmentation in Step 1d kicks in — see Step 1d for the computer-use visual-feedback-loop.
+- "Discuss alternate CLI scope" → leave this flow and return to upstream scope discussion. Record `decision: alternate_scope` in the marker file.
+
+**Menu re-fire on backend failure (session-scoped state).** When the user picks a backend from this menu and that backend ALSO fails (per the Step 2c.5 trigger criteria for browser-use/agent-browser/manual-HAR, or per the Step 2e multi-trigger failure detection for chrome-MCP), re-fire this exact menu with the failed option removed. Track which backends have been tried in your reasoning across this same recovery session — this is a session-scoped tracking concern, not a marker-file field. Stop re-firing when only "Discuss alternate CLI scope" remains in the menu, or when the user picks "Discuss alternate CLI scope" themselves.
+
+**Marker file `reason` field convention.** When recording the chosen backend in the `browser-browser-sniff-gate.json` marker, name it explicitly so future audit can identify which backend produced the capture. Examples: `reason: "chrome-mcp captured 142 requests; SSR enriched after Akamai block on agent-browser"`, `reason: "manual-HAR with computer-use guidance after browser-use blocked"`. The `reason` field is free-form per the existing schema; no migration needed.
+
+Only the "Discuss alternate CLI scope" option may lead to an RSS-first, official API, docs-only, or narrower-scope proposal. Record the failed capture in `$DISCOVERY_DIR/browser-sniff-report.md` if a report is written.
 
 If direct HTTP is blocked but the page does not require live page-context execution, try the lightweight replay path before proposing a resident browser runtime: Surf/Chrome-compatible HTTP with modern TLS/UA headers, uTLS-style Chrome ClientHello where available, browser-clearance cookie import plus replay, or structured HTML/SSR/RSS extraction. These are discovery and replayability aids, not permission to ship a browser sidecar transport.
 

← 7364324a chore(main): release 3.8.0 (#527)  ·  back to Cli Printing Press  ·  feat(skills): brainstorm novel features via Task subagent (# 13995da7 →