[DEPRECATED] Chip Fetcher → adom-chip-fetcher
Public Made by Adomby adom
DEPRECATED — use adom/adom-chip-fetcher. No longer maintained.
Dashboard flow — chip-fetcher's UI is the user's home base (HARD RULE)
Read this first. chip-fetcher is not just a CLI that scrapes the web — it's a dashboard that the user keeps open as their home base while the agent does the scraping in a separate window. The dashboard is the single place the user looks to understand what's planned, what's in flight, and what's done. The skill below is mandatory for every batch fetch.
The hard rule
Two separate surfaces. The dashboard is user-preference; the scraping window is always pup.
| Surface | Where it lives | User-preferred? | Why |
|---|---|---|---|
| Dashboard (home base) | EITHER pup sessionId: "chip-fetcher-dashboard" OR Hydrogen webview tab named "chip-fetcher" |
YES — ask the user (or check user-profile memory) | Just renders HTML + polls /api/activity. No automation needed. |
| Scraping window | pup sessionId: "chip-fetcher" |
NO — always pup | Needs browser_input_dispatch for trusted clicks, captcha solving, vendor-login cookies on the chip-fetcher profile, download capture from ~/Downloads. None of that works in a Hydrogen webview. |
Dashboard placement — figure out the user's preference
Adom users split based on screen real estate:
- Laptop-screen users (e.g. John) prefer pup as the dashboard — the pup window can be moved to a second monitor, alt-tabbed, or sized to taste outside VS Code's chrome.
- Big-monitor users (e.g. Colby) prefer Hydrogen webview — keeps everything inside VS Code, splits cleanly alongside the editor in a workspace pane.
Be smart about this detail:
- Check
~/.claude/projects/-home-adom-project/memory/user_profile.mdfor achip_fetcher_dashboard_surfacepreference (puporwebview) - If absent, ASK the user once: "Where do you want the chip-fetcher dashboard — pup window or Hydrogen webview tab?" and save the answer for future sessions
- Default fallback if you can't ask: pup, since it works on any screen size
Either way, the scraping work always runs in pup — the dashboard surface is decoupled from the automation surface.
How to open the dashboard in either surface
Pup version:
DASHBOARD_URL="${VSCODE_PROXY_URI/\{\{port\}\}/8786}"
adom-desktop browser_open_window "{
\"sessionId\":\"chip-fetcher-dashboard\",
\"profile\":\"chip-fetcher\",
\"url\":\"$DASHBOARD_URL\"
}"
adom-desktop browser_raise_os_window '{"sessionId":"chip-fetcher-dashboard"}'
Hydrogen webview version:
# Find a non-VS-Code pane (per the "never cover VS Code" memory rule)
# Then split + add a webview tab
VSCODE_PANEL=$(adom-cli hydrogen workspace tabs | jq -r '.tabs[] | select(.name=="Visual Studio Code") | .panelId')
WEBVIEW_TYPE="adom/c1d2e3f4-aaaa-4000-a000-00000000000f"
DASHBOARD_URL="http://127.0.0.1:8786/"
adom-cli hydrogen workspace split \
--panel-id "$VSCODE_PANEL" \
--direction horizontal \
--panel-type "$WEBVIEW_TYPE" \
--display-name "chip-fetcher" \
--position after \
--ratio 0.4 \
--initial-state "{\"url\":\"$DASHBOARD_URL\",\"displayName\":\"chip-fetcher\"}"
Both surfaces poll the same /api/activity endpoint, so heartbeats reach the user regardless of which surface they picked.
Why two distinct things:
- The user can always glance at the dashboard while the agent navigates. They don't lose context when the agent visits SnapMagic or solves a captcha.
- The dashboard surface NEVER gets navigated away from. It stays on the chip-fetcher viewer URL. The scraping window does the work.
- If the agent gets stuck, the dashboard surfaces it on the relevant chip's card — the user knows which chip needs help without reading chat.
The canonical batch flow
User asks: "fetch these 6 LEDs"
↓
Stage 0: PLAN
├ Tell user the MPN list as a numbered plan
├ chip-fetcher plan <MPN1> <MPN2> ... (seeds dashboard with planned-state stub cards)
└ Open dashboard in chip-fetcher-dashboard session if not already open
↓
Stage 1: PROBE manufacturer site (per chip, in chip-fetcher session)
├ post_act <MPN> "probing <vendor>.com"
├ Walk product page for CAD/Documentation/Tools links
└ post_act <MPN> "found UL deep-link" OR "no mfr-direct CAD"
↓
Stage 2: FETCH (per chip, in chip-fetcher session)
├ post_act <MPN> "downloading <format>"
├ Drive UL form / SnapEDA modal / Mouser CSE Library Loader
└ post_act <MPN> "captcha — user help needed" if stuck
↓
Stage 3: PULL + IMPORT (per chip)
├ post_act <MPN> "pulling from desktop"
├ chip-fetcher pull <path> --mpn <MPN>
└ post_act <MPN> "imported"
↓
Stage 4: CLEAR
└ post_act <MPN> "" (or DELETE) to clear the live activity badge
The activity-heartbeat protocol
Always use the CLI: chip-fetcher heartbeat <MPN> "<stage>" — it does five things on every call so the AI doesn't have to remember them:
- POSTs the heartbeat to
/api/activityso the dashboard renders the live stage. - Auto-creates a stub
library/<MPN>/info.jsonthe first time a new MPN heartbeats — the dashboard renders an empty placeholder card so the user has something to scroll to even before any files land. - Auto-scrolls the dashboard pup window so the active MPN's card is centered in view with a brief outline highlight (
#5cf). No more "I'm working on this chip but the user is parked on a different row of the grid." - Prints the canonical sourcing-ladder HINT on the very first heartbeat per MPN (Mfr → SnapMagic → Mouser → DigiKey → Arrow → CSE/UL → LCSC). The AI sees this on stdout instead of having to re-read the skill.
- Prints a card-completeness
WARN:on every heartbeat listing what files the active card is still missing (PDF / STEP /.kicad_sym/.kicad_mod), plus a library-wideWARN: N/Total cards still incompletecount. The AI cannot quietly walk away from a half-finished batch — the count is in stdout on every heartbeat.
The legacy raw-curl flow still works as a fallback for shell scripts that don't have the binary on PATH:
ACTIVITY="http://127.0.0.1:8786/api/activity"
post_act() {
curl -s -X POST "$ACTIVITY" -H 'Content-Type: application/json' \
-d "{\"mpn\":\"$MPN\",\"stage\":\"$1\"}" >/dev/null
}
…but it does NOT trigger any of the above side-effects. Always prefer the CLI.
The dashboard polls /api/activity and renders the latest stage on the chip's card. The user's card shows: live stage, history of recent stages, and any "stuck" flag.
The completion gate — chip-fetcher gate
Before reporting "X of Y done" or "batch complete" or shipping anything based on the library, run chip-fetcher gate. It walks every chip and exits 1 if ANY card lacks PDF + STEP + .kicad_sym + .kicad_mod (default mode) or also Altium + Fusion (--strict). For each incomplete card it prints HINT: lines naming the exact missing artifacts. The deterministic check replaces "did I remember to check completeness?" — the binary remembers for you.
Datasheet-only cards count as incomplete stubs, not done. If the ladder is genuinely exhausted (no STEP exists anywhere on Mfr / SnapMagic / Mouser / DigiKey / Arrow / CSE), record that in info.json.fetched_via_chain so the gate sees it as a documented dead-end — but ONLY after walking the full ladder, not as a shortcut.
Heartbeat MUST fire on:
- Every page navigation in the scraping session (
navigating <vendor>.com) - Every form-fill / button-click that's part of a multi-step flow (
pre-setting form,clicking reCAPTCHA,polling Downloads) - Every state change that affects "is this chip done yet?" (
downloading kicad zip,pulling from desktop,imported) - Every stuck state (
captcha — user help needed,mfr lacks CAD — needs SnapEDA approval)
Heartbeat must NOT lie about state. "imported" means the file is in library/<MPN>/. "downloading" means the download fired and we're polling Downloads. Don't post "imported" before the file has actually landed — the user trusts the dashboard to be ground truth.
Canonical stage labels
Use these exact strings so the dashboard can color/group consistently:
| Stage label | When | Color |
|---|---|---|
planned |
Initial state when chip-fetcher plan seeds the card |
grey |
probing <vendor>.com |
Scraping window navigated to manufacturer page | blue |
found UL deep-link / found mfr STEP / found CSE link |
mfr-direct CAD path identified | blue |
no mfr-direct CAD — falling back to <source> |
manufacturer doesn't host; await user approval | amber |
downloading <format> |
Format selected, click fired | blue |
captcha — user help needed |
Captcha escalated; pup raised to user | amber |
polling Downloads |
Watching ~/Downloads for the zip to land | blue |
pulling from desktop |
adom-desktop pull_file in flight |
blue |
importing |
chip-fetcher import running |
blue |
imported |
Files in library/<MPN>/, ready to verify |
green |
done — verified |
step + sym + mod + pdf all present in library | green |
stuck — <one-line reason> |
Genuine blocker; user needs to step in | red |
Opening the dashboard pup window
# 1. Make sure the viewer is running
ps aux | grep "[c]hip-fetcher serve" >/dev/null || \
nohup /usr/local/bin/chip-fetcher serve --port 8786 > /tmp/cf-serve.log 2>&1 & disown
# 2. Get the public URL for pup (proxy through the container's adom.cloud slug)
DASHBOARD_URL="${VSCODE_PROXY_URI/\{\{port\}\}/8786}" # env var inside the container
# 3. Open in pup session "chip-fetcher-dashboard" (NEVER navigate this session away)
adom-desktop browser_open_window "{
\"sessionId\":\"chip-fetcher-dashboard\",
\"profile\":\"chip-fetcher\",
\"url\":\"$DASHBOARD_URL\"
}"
# 4. Raise it so the user can see
adom-desktop browser_raise_os_window '{"sessionId":"chip-fetcher-dashboard"}'
The scraping session
# Use sessionId "chip-fetcher" (NOT "chip-fetcher-dashboard") for all scraping.
# Navigate, login, click, captcha — all in this window.
adom-desktop browser_navigate '{"sessionId":"chip-fetcher","url":"https://www.vishay.com/..."}'
adom-desktop browser_eval '{"sessionId":"chip-fetcher","expr":"..."}'
Never call browser_navigate against chip-fetcher-dashboard. That window stays on the dashboard URL for the entire batch. If the user does navigate it (clicks a link in the viewer), let them — but don't drive it programmatically.
Plan-loading (current state of code)
⚠ Code gap (as of chip-fetcher 0.1.2): there is no chip-fetcher plan <MPN>... command yet. The viewer auto-discovers chips by scanning library/<MPN>/ directories at server start, so a chip doesn't appear on the dashboard until it has at least one file imported.
Until that command lands, the canonical flow is:
- List the planned MPNs to the user textually as a numbered batch (so they see the queue before any scraping fires)
- Start the heartbeat the moment the chip moves into
probing <vendor>.com(this auto-creates the chip's card via the activity API's side-effect of writing tolibrary/<MPN>/.activityor similar) - Do not pretend "planned" cards exist on the dashboard if they don't yet
Code work to add proper plan-loading is tracked separately in chip-fetcher's TODO; keep this playbook authoritative for what the flow SHOULD look like once that lands.
When the dashboard window dies / closes
If the user accidentally closes the dashboard window:
- Don't reopen it silently — that's confusing if they meant to close it.
- Surface it: "I noticed the chip-fetcher dashboard window closed. Want me to reopen it so you can see batch progress?" and wait for yes.
- If they say yes, reopen with
chip-fetcher-dashboardsession and resume heartbeats.
The activity history is server-side (in chip-fetcher serve memory) so reopening shows current state instantly.
Common antipatterns (don't do these)
| Antipattern | Why it's wrong |
|---|---|
Single sessionId: "chip-fetcher" for both dashboard AND scraping |
Navigating to vishay.com covers the dashboard; user loses context |
| Heartbeats only on stuck/done | User can't see live progress mid-flow; they think the agent froze |
| Navigating the dashboard window mid-batch | Dashboard is the user's anchor; never overwrite it |
Posting imported before the file actually lands in library/<MPN>/ |
Lies on the dashboard erode user trust |
| Skipping plan-listing because "I'll just fetch and they'll see results" | User doesn't know what's coming or how long it'll take |
| Using a different profile for the dashboard session | Cookies / vendor logins won't be shared |
Cross-references
manufacturer-direct.md— every stage in the per-vendor flow should heartbeatultra-librarian.md—cf-ul-fetch.shalready implements this protocol; reference implementationsnapmagic.md— heartbeat the format-cycling stages (kicad → altium → fusion)mouser-cse.md— heartbeat the slide-CAPTCHA escalationhandoff-and-watching.md— when a stage hits "user help needed", post the heartbeat AND raise the scraping window
# Dashboard flow — chip-fetcher's UI is the user's home base (HARD RULE)
**Read this first.** chip-fetcher is not just a CLI that scrapes the web — it's a dashboard that the user keeps open as their home base while the agent does the scraping in a separate window. The dashboard is the single place the user looks to understand what's planned, what's in flight, and what's done. The skill below is mandatory for every batch fetch.
## The hard rule
**Two separate surfaces. The dashboard is user-preference; the scraping window is always pup.**
| Surface | Where it lives | User-preferred? | Why |
|---------|----------------|-----------------|-----|
| **Dashboard** (home base) | EITHER pup `sessionId: "chip-fetcher-dashboard"` OR Hydrogen webview tab named "chip-fetcher" | **YES — ask the user (or check user-profile memory)** | Just renders HTML + polls `/api/activity`. No automation needed. |
| **Scraping window** | pup `sessionId: "chip-fetcher"` | **NO — always pup** | Needs `browser_input_dispatch` for trusted clicks, captcha solving, vendor-login cookies on the `chip-fetcher` profile, download capture from `~/Downloads`. None of that works in a Hydrogen webview. |
### Dashboard placement — figure out the user's preference
Adom users split based on screen real estate:
- **Laptop-screen users (e.g. John)** prefer pup as the dashboard — the pup window can be moved to a second monitor, alt-tabbed, or sized to taste outside VS Code's chrome.
- **Big-monitor users (e.g. Colby)** prefer Hydrogen webview — keeps everything inside VS Code, splits cleanly alongside the editor in a workspace pane.
**Be smart about this detail:**
1. Check `~/.claude/projects/-home-adom-project/memory/user_profile.md` for a `chip_fetcher_dashboard_surface` preference (`pup` or `webview`)
2. If absent, ASK the user once: *"Where do you want the chip-fetcher dashboard — pup window or Hydrogen webview tab?"* and save the answer for future sessions
3. Default fallback if you can't ask: pup, since it works on any screen size
Either way, the **scraping work always runs in pup** — the dashboard surface is decoupled from the automation surface.
### How to open the dashboard in either surface
**Pup version:**
```bash
DASHBOARD_URL="${VSCODE_PROXY_URI/\{\{port\}\}/8786}"
adom-desktop browser_open_window "{
\"sessionId\":\"chip-fetcher-dashboard\",
\"profile\":\"chip-fetcher\",
\"url\":\"$DASHBOARD_URL\"
}"
adom-desktop browser_raise_os_window '{"sessionId":"chip-fetcher-dashboard"}'
```
**Hydrogen webview version:**
```bash
# Find a non-VS-Code pane (per the "never cover VS Code" memory rule)
# Then split + add a webview tab
VSCODE_PANEL=$(adom-cli hydrogen workspace tabs | jq -r '.tabs[] | select(.name=="Visual Studio Code") | .panelId')
WEBVIEW_TYPE="adom/c1d2e3f4-aaaa-4000-a000-00000000000f"
DASHBOARD_URL="http://127.0.0.1:8786/"
adom-cli hydrogen workspace split \
--panel-id "$VSCODE_PANEL" \
--direction horizontal \
--panel-type "$WEBVIEW_TYPE" \
--display-name "chip-fetcher" \
--position after \
--ratio 0.4 \
--initial-state "{\"url\":\"$DASHBOARD_URL\",\"displayName\":\"chip-fetcher\"}"
```
Both surfaces poll the same `/api/activity` endpoint, so heartbeats reach the user regardless of which surface they picked.
**Why two distinct things:**
- The user can always glance at the dashboard while the agent navigates. They don't lose context when the agent visits SnapMagic or solves a captcha.
- The dashboard surface NEVER gets navigated away from. It stays on the chip-fetcher viewer URL. The scraping window does the work.
- If the agent gets stuck, the dashboard surfaces it on the relevant chip's card — the user knows which chip needs help without reading chat.
## The canonical batch flow
```
User asks: "fetch these 6 LEDs"
↓
Stage 0: PLAN
├ Tell user the MPN list as a numbered plan
├ chip-fetcher plan <MPN1> <MPN2> ... (seeds dashboard with planned-state stub cards)
└ Open dashboard in chip-fetcher-dashboard session if not already open
↓
Stage 1: PROBE manufacturer site (per chip, in chip-fetcher session)
├ post_act <MPN> "probing <vendor>.com"
├ Walk product page for CAD/Documentation/Tools links
└ post_act <MPN> "found UL deep-link" OR "no mfr-direct CAD"
↓
Stage 2: FETCH (per chip, in chip-fetcher session)
├ post_act <MPN> "downloading <format>"
├ Drive UL form / SnapEDA modal / Mouser CSE Library Loader
└ post_act <MPN> "captcha — user help needed" if stuck
↓
Stage 3: PULL + IMPORT (per chip)
├ post_act <MPN> "pulling from desktop"
├ chip-fetcher pull <path> --mpn <MPN>
└ post_act <MPN> "imported"
↓
Stage 4: CLEAR
└ post_act <MPN> "" (or DELETE) to clear the live activity badge
```
## The activity-heartbeat protocol
**Always use the CLI: `chip-fetcher heartbeat <MPN> "<stage>"`** — it does five things on every call so the AI doesn't have to remember them:
1. POSTs the heartbeat to `/api/activity` so the dashboard renders the live stage.
2. **Auto-creates a stub `library/<MPN>/info.json`** the first time a new MPN heartbeats — the dashboard renders an empty placeholder card so the user has something to scroll to even before any files land.
3. **Auto-scrolls the dashboard pup window** so the active MPN's card is centered in view with a brief outline highlight (`#5cf`). No more "I'm working on this chip but the user is parked on a different row of the grid."
4. **Prints the canonical sourcing-ladder HINT on the very first heartbeat per MPN** (Mfr → SnapMagic → Mouser → DigiKey → Arrow → CSE/UL → LCSC). The AI sees this on stdout instead of having to re-read the skill.
5. **Prints a card-completeness `WARN:` on every heartbeat** listing what files the active card is still missing (PDF / STEP / `.kicad_sym` / `.kicad_mod`), plus a library-wide `WARN: N/Total cards still incomplete` count. The AI cannot quietly walk away from a half-finished batch — the count is in stdout on every heartbeat.
The legacy raw-curl flow still works as a fallback for shell scripts that don't have the binary on PATH:
```bash
ACTIVITY="http://127.0.0.1:8786/api/activity"
post_act() {
curl -s -X POST "$ACTIVITY" -H 'Content-Type: application/json' \
-d "{\"mpn\":\"$MPN\",\"stage\":\"$1\"}" >/dev/null
}
```
…but it does NOT trigger any of the above side-effects. Always prefer the CLI.
The dashboard polls `/api/activity` and renders the latest stage on the chip's card. The user's card shows: live stage, history of recent stages, and any "stuck" flag.
## The completion gate — `chip-fetcher gate`
Before reporting "X of Y done" or "batch complete" or shipping anything based on the library, run `chip-fetcher gate`. It walks every chip and exits 1 if ANY card lacks PDF + STEP + `.kicad_sym` + `.kicad_mod` (default mode) or also Altium + Fusion (`--strict`). For each incomplete card it prints `HINT:` lines naming the exact missing artifacts. The deterministic check replaces "did I remember to check completeness?" — the binary remembers for you.
Datasheet-only cards count as **incomplete stubs**, not done. If the ladder is genuinely exhausted (no STEP exists anywhere on Mfr / SnapMagic / Mouser / DigiKey / Arrow / CSE), record that in `info.json.fetched_via_chain` so the gate sees it as a documented dead-end — but ONLY after walking the full ladder, not as a shortcut.
**Heartbeat MUST fire on:**
- Every page navigation in the scraping session (`navigating <vendor>.com`)
- Every form-fill / button-click that's part of a multi-step flow (`pre-setting form`, `clicking reCAPTCHA`, `polling Downloads`)
- Every state change that affects "is this chip done yet?" (`downloading kicad zip`, `pulling from desktop`, `imported`)
- Every stuck state (`captcha — user help needed`, `mfr lacks CAD — needs SnapEDA approval`)
**Heartbeat must NOT lie about state.** "imported" means the file is in `library/<MPN>/`. "downloading" means the download fired and we're polling Downloads. Don't post "imported" before the file has actually landed — the user trusts the dashboard to be ground truth.
## Canonical stage labels
Use these exact strings so the dashboard can color/group consistently:
| Stage label | When | Color |
|-------------|------|-------|
| `planned` | Initial state when `chip-fetcher plan` seeds the card | grey |
| `probing <vendor>.com` | Scraping window navigated to manufacturer page | blue |
| `found UL deep-link` / `found mfr STEP` / `found CSE link` | mfr-direct CAD path identified | blue |
| `no mfr-direct CAD — falling back to <source>` | manufacturer doesn't host; await user approval | amber |
| `downloading <format>` | Format selected, click fired | blue |
| `captcha — user help needed` | Captcha escalated; pup raised to user | amber |
| `polling Downloads` | Watching ~/Downloads for the zip to land | blue |
| `pulling from desktop` | `adom-desktop pull_file` in flight | blue |
| `importing` | `chip-fetcher import` running | blue |
| `imported` | Files in `library/<MPN>/`, ready to verify | green |
| `done — verified` | step + sym + mod + pdf all present in library | green |
| `stuck — <one-line reason>` | Genuine blocker; user needs to step in | red |
## Opening the dashboard pup window
```bash
# 1. Make sure the viewer is running
ps aux | grep "[c]hip-fetcher serve" >/dev/null || \
nohup /usr/local/bin/chip-fetcher serve --port 8786 > /tmp/cf-serve.log 2>&1 & disown
# 2. Get the public URL for pup (proxy through the container's adom.cloud slug)
DASHBOARD_URL="${VSCODE_PROXY_URI/\{\{port\}\}/8786}" # env var inside the container
# 3. Open in pup session "chip-fetcher-dashboard" (NEVER navigate this session away)
adom-desktop browser_open_window "{
\"sessionId\":\"chip-fetcher-dashboard\",
\"profile\":\"chip-fetcher\",
\"url\":\"$DASHBOARD_URL\"
}"
# 4. Raise it so the user can see
adom-desktop browser_raise_os_window '{"sessionId":"chip-fetcher-dashboard"}'
```
## The scraping session
```bash
# Use sessionId "chip-fetcher" (NOT "chip-fetcher-dashboard") for all scraping.
# Navigate, login, click, captcha — all in this window.
adom-desktop browser_navigate '{"sessionId":"chip-fetcher","url":"https://www.vishay.com/..."}'
adom-desktop browser_eval '{"sessionId":"chip-fetcher","expr":"..."}'
```
**Never** call `browser_navigate` against `chip-fetcher-dashboard`. That window stays on the dashboard URL for the entire batch. If the user does navigate it (clicks a link in the viewer), let them — but don't drive it programmatically.
## Plan-loading (current state of code)
⚠ **Code gap (as of chip-fetcher 0.1.2):** there is no `chip-fetcher plan <MPN>...` command yet. The viewer auto-discovers chips by scanning `library/<MPN>/` directories at server start, so a chip doesn't appear on the dashboard until it has at least one file imported.
**Until that command lands**, the canonical flow is:
1. List the planned MPNs to the user textually as a numbered batch (so they see the queue before any scraping fires)
2. Start the heartbeat the moment the chip moves into `probing <vendor>.com` (this auto-creates the chip's card via the activity API's side-effect of writing to `library/<MPN>/.activity` or similar)
3. Do not pretend "planned" cards exist on the dashboard if they don't yet
Code work to add proper plan-loading is tracked separately in chip-fetcher's TODO; keep this playbook authoritative for what the flow SHOULD look like once that lands.
## When the dashboard window dies / closes
If the user accidentally closes the dashboard window:
1. Don't reopen it silently — that's confusing if they meant to close it.
2. Surface it: *"I noticed the chip-fetcher dashboard window closed. Want me to reopen it so you can see batch progress?"* and wait for yes.
3. If they say yes, reopen with `chip-fetcher-dashboard` session and resume heartbeats.
The activity history is server-side (in `chip-fetcher serve` memory) so reopening shows current state instantly.
## Common antipatterns (don't do these)
| Antipattern | Why it's wrong |
|-------------|----------------|
| Single `sessionId: "chip-fetcher"` for both dashboard AND scraping | Navigating to vishay.com covers the dashboard; user loses context |
| Heartbeats only on stuck/done | User can't see live progress mid-flow; they think the agent froze |
| Navigating the dashboard window mid-batch | Dashboard is the user's anchor; never overwrite it |
| Posting `imported` before the file actually lands in `library/<MPN>/` | Lies on the dashboard erode user trust |
| Skipping plan-listing because "I'll just fetch and they'll see results" | User doesn't know what's coming or how long it'll take |
| Using a different profile for the dashboard session | Cookies / vendor logins won't be shared |
## Cross-references
- [`manufacturer-direct.md`](manufacturer-direct.md) — every stage in the per-vendor flow should heartbeat
- [`ultra-librarian.md`](ultra-librarian.md) — `cf-ul-fetch.sh` already implements this protocol; reference implementation
- [`snapmagic.md`](snapmagic.md) — heartbeat the format-cycling stages (kicad → altium → fusion)
- [`mouser-cse.md`](mouser-cse.md) — heartbeat the slide-CAPTCHA escalation
- [`handoff-and-watching.md`](handoff-and-watching.md) — when a stage hits "user help needed", post the heartbeat AND raise the scraping window