11---
22name : e2e-loop
33description : Run one manually-triggered, live end-to-end pass of the AutoBroker product
4- as a real car buyer — drive all 17 skills against the real DeepSeek lane through
5- serve-live + a Playwright browser, negotiate for real against resistant LLM dealers,
6- cross-shop several cars at once, and RECORD every blocker / backlog gap / rough edge
7- into an HTML report. The job is to reproduce the real buyer experience and expose its
8- imperfections honestly — NOT to ship a perfect run. Fixing the recorded issues is the
9- companion `e2e-evolve` skill's job (run it in a fresh session). Pass `--light` for a
10- quick read-only sweep. Pass `--provider claude` to drive the WHOLE journey through the
11- Claude OAuth subscription lane (lane B, the official Agent SDK) instead of the default
12- ` --provider deepseek` (the DeepSeek API-key lane). Use to run the live e2e / 全技能巡检 on demand.
4+ as a real car buyer — drive all 17 skills against the run's live LLM lane (default
5+ DeepSeek api-key; `--provider claude` = the Claude OAuth subscription lane, the
6+ official Agent SDK) through serve-live + a Playwright browser, negotiate for real
7+ against resistant LLM dealers, cross-shop several cars at once, and RECORD every
8+ blocker / backlog gap / rough edge into an HTML report. The job is to reproduce the
9+ real buyer experience and expose its imperfections honestly — NOT to ship a perfect
10+ run. Fixing the recorded issues is the companion `e2e-evolve` skill's job (run it in
11+ a fresh session). Pass `--light` for a quick read-only sweep. Use to run the live
12+ e2e / 全技能巡检 on demand.
13+ argument-hint : " [--light] [--provider deepseek|claude]"
1314disable-model-invocation : true
1415---
1516
@@ -44,6 +45,19 @@ ends with a full report; it does **not** need an empty backlog.
4445 write the HTML report ◄── write-back lessons
4546```
4647
48+ ## The three buyer use-cases
49+
50+ - ** UC1 — single-profile pipeline** (every run): one buyer, one search profile, the full
51+ pipeline to a negotiated quote — this IS the pinned spine (steps 2–3).
52+ - ** UC2 — same vehicle, different metro** (one-time boundary evaluation): the product
53+ holds one active profile per (account, make) — a second same-make intake trips
54+ ` ActiveSlotConflict ` with replace/supersede as the product path. Evaluated ONCE (see
55+ ` references/multi-profile-lane.md ` "UC2"), then graduated to the known-correct list;
56+ NOT an every-run probe.
57+ - ** UC3 — same metro, competing models** (portfolio): 3 same-segment different-make
58+ searches in ONE metro, concurrent, one approval inbox, goal = best quote across the
59+ options — this IS step 4 (` references/multi-profile-lane.md ` ).
60+
4761## Modes
4862
4963- ** Provider lane** (` --provider claude|deepseek ` , default ` deepseek ` ): which real LLM
@@ -65,6 +79,7 @@ ends with a full report; it does **not** need an empty backlog.
6579 already-running) serve-live. If its DB is empty, do a minimal intake first to seed one
6680 profile (this also exercises intake live). Light still writes a report; it just
6781 expects fewer findings (a clean read-only sweep may legitimately record zero).
82+ (` --light ` still runs ONE final ui-monitor checkpoint.)
6883- ** Buyer-email probe** (optional, owner-run, separate from serve-live): validates the
6984 REAL Gmail I/O layer — OAuth/refresh, real MIME parse (incl. HTML-only recovery),
7085 attachment download, historyId — that the test-mode journey can never reach. It is a
@@ -88,20 +103,34 @@ ends with a full report; it does **not** need an empty backlog.
88103 for a full run** — pick a big metro + high-volume car) — else fail closed. An empty
89104 metro means a misconfigured ` location_query ` (see the Irvine fallback trap in
90105 ` references/harness-boundaries.md ` ); do not drive a vacuous sweep.
106+ 4 . ** Lane-took-effect verification:** after the FIRST LLM-bearing skill completes, read
107+ ` test_run_records ` in ` <dataDir>/autobroker.db ` and assert the rows match the
108+ requested lane (` --provider claude ` → `provider='anthropic' AND
109+ pricing_source='subscription'` ; ` deepseek` → ` provider='deepseek' AND
110+ pricing_source != 'subscription'` — lane A persists the dated pricing-snapshot
111+ label, or ` 'unavailable' ` on a usage-missing row, never ` 'subscription' ` ).
112+ Mismatch = ** STOP** : a mistyped
113+ ` AUTOBROKER_AGENT_PROVIDER ` value silently resolves to the DeepSeek default (exact
114+ strings ` claude ` /` deepseek ` only), and a whole run on the wrong lane poisons every
115+ cross-lane conclusion.
91116
92117## The journey
93118
94119| step | what you do | how you know it worked | load when you reach it |
95120| ---| ---| ---| ---|
96121| 0 | read the last 1–2 reports, run the safety gate, ` touch .claude/.e2e-loop-active ` | keys/MCP present; listening line seen | this spine |
97- | 1 | (full) fresh worktree off ` origin/main ` + better-sqlite3 rebuild + ` pnpm -r build ` , then start ` pnpm e2e:serve-live ` ; pick a realistic buyer (metro, car, finance mode, persona) | build OK; ` dataDir ` recorded; geosearch ≥1 dealer (≥10 full) | ` references/harness-boundaries.md ` , ` references/brand-picker.md ` |
122+ | 1 | (full) fresh worktree off ` origin/main ` + better-sqlite3 rebuild + ` pnpm -r build ` , then start ` pnpm e2e:serve-live ` ; pick a realistic buyer (metro, car, finance mode, persona) | build OK; ` dataDir ` recorded; geosearch ≥1 dealer (≥10 full) | ` references/harness-boundaries.md ` , ` references/brand-picker.md ` , ` references/ui-monitor.md ` |
98123| 2 | live the journey: drive all 17 skills as the buyer — PASS-A in natural language, PASS-B by ` /slash ` — verifying each skill lands its data AND its UI | terminal skill row + table delta + the right Canvas panel; data-quality coverage (not just a row count) | ` references/skill-pipeline.md ` (+ ` references/ui-lane-personas.md ` ) |
99124| 3 | (full) negotiate for real: deep, multi-thread email negotiation against resistant LLM dealers — ≥10 dealers, front-runners driven to ≥4 rounds, with ghosting and manager escalation | front-runner threads reach ≥4 buyer rounds; ghosts drop after 2 unanswered; revised OTDs extracted | ` references/dealer-brain.md ` |
100125| 4 | (full) cross-shop: run several searches at once (3 different-brand profiles) on the real scheduler — concurrent negotiation, a shared dealer both want, one shared approval inbox | scheduler cap holds; every profile reaches a terminal state; exactly one profile binds each shared dealer, losers voiced + zero send; no budget leak; nothing sent for real | ` references/multi-profile-lane.md ` |
101126| 5 | judge the experience: run ` frontend-taste ` per data tab | a ranked usability findings list | ` references/ui-lane-personas.md ` (→ the ` frontend-taste ` skill by name) |
102127| 6 | record everything: classify each imperfection (blocker / backlog / polish), capture telemetry, fix only safety + one-line blockers, write the HTML report + harvest-register | report sections present; ledger rebuilt | ` references/recording.md ` |
103128| 7 | teardown: kill serve-live, remove the worktree, write the memory pointer, ` rm .claude/.e2e-loop-active ` | marker gone; memory pointer ≤200c | ` references/recording.md ` |
104129
130+ ** UI-monitor checkpoints** (dispatch per ` references/ui-monitor.md ` , driver idle): after
131+ step 2 PASS-A · after step 2 PASS-B · after step 3 · after step 4 · at step 5 ·
132+ pre-teardown final. ` --light ` = exactly ONE final checkpoint.
133+
105134** Step 4 ordering:** the single pinned-brand journey (steps 2 and 3) runs FIRST and
106135reaches a terminal, healthy state before cross-shop (step 4) begins. Never run them
107136concurrently — cross-shop is layered on top of a known-good single-brand pass.
@@ -128,17 +157,22 @@ rows — and a buyer then sees "0 recommendations". For `inventory_site_scan` an
128157` dealer_reply_extract ` the verdict is the ** coverage** from ` /__e2e/dataquality ` , not the
129158row count. (` references/harness-boundaries.md ` has the exact thresholds.)
130159
131- ** Cross-provider isolation — a one-lane failure is not a lane verdict (general rule, both
132- lanes).** When a skill misbehaves on the run's provider lane (a 0-yield scan, a malformed
133- extract, a dropped field), do NOT conclude "this lane is broken" from that one run — * isolate*
134- it first. Re-run that ONE skill on the OTHER provider (` AUTOBROKER_AGENT_PROVIDER ` flipped,
135- fresh dir): the same fault on both lanes = a general / product / environmental cause (fix it
136- provider-agnostically); a fault on only one lane = a genuine lane-specific gap (record it for
137- ` e2e-evolve ` ). For a browser-fed 0-yield, read ` /__e2e/dataquality … rendered_empty_count `
138- FIRST — a blank render is host thrash, provider-independent, and needs no re-run. The browse
139- path has no LLM in it, so it is byte-identical across providers; only the EXTRACTION is the
140- lane. (Full procedure + the decisive controlled-extraction test:
141- ` references/harness-boundaries.md ` .)
160+ ** Cross-lane triage (the four-exit tree — general rule, both lanes).** A one-lane failure is not a lane
161+ verdict. When ANY skill misbehaves on the run's lane, classify before you blame:
162+
163+ 0 . Browser-fed 0-yield? Read /__ e2e/dataquality ` rendered_empty_count ` FIRST —
164+ > 0 = host thrash (environment; browse has no LLM in it), no re-run needed.
165+ 1 . Infra signal (429 / timeout / lane-B subprocess failure / credential)? An
166+ availability fault, not a product fault — re-run ONCE on the SAME lane to confirm.
167+ 2 . Anything else: re-run that ONE skill on the OTHER provider
168+ (` AUTOBROKER_AGENT_PROVIDER ` flipped, fresh dir), AT MOST ONCE, as DIAGNOSIS:
169+ - fails on BOTH lanes → a general product/environment cause — fix provider-agnostically;
170+ - fails on ONE lane only → a genuine lane-specific gap — record it with its lane tag
171+ for ` e2e-evolve ` (which re-verifies its fix on the SAME lane).
172+
173+ Decoupling invariants: the journey NEVER switches lanes mid-run; a missing credential
174+ is a STOP, never a provider swap; the re-run is a diagnostic, never a retry-to-green.
175+ (Procedure detail + the decisive controlled-extraction test: ` references/harness-boundaries.md ` .)
142176
143177## How to classify what you find (three buckets)
144178
@@ -235,8 +269,8 @@ headline.
235269 ` cold ` outcome, never a fabricated quote, never a failure on its own.
236270- ** Worktree needs ` .env ` .** ` .env ` is gitignored, so a fresh worktree has none — copy
237271 the main checkout's ` .env ` into the worktree after ` git worktree add ` (it stays
238- gitignored, never staged), or serve-live reports "add your DeepSeek key" and the
239- router 500s.
272+ gitignored, never staged). Without it the run has no lane credential: lane A reports
273+ "add your DeepSeek key" and the router 500s; lane B fails closed on every call .
240274- ** Self-contained ` YYYY-MM-DD ` HTML report** ; ` MEMORY.md ` pointer ≤200 chars (detail
241275 lives in the topic file).
242276
@@ -251,5 +285,9 @@ headline.
251285 just the row count.
252286- After each of the 3 irreversible sends, you confirmed the ** fake** adapter fired (a
253287 positive check, not just the negative "no real send" counter).
288+ - UI-monitor checkpoints ran (all six on a full run; ONE final on ` --light ` ) and their
289+ findings are folded into the three buckets with a ` monitor ` provenance tag.
290+ - The lane-took-effect check was recorded (provider + pricing_source noted in the
291+ report header).
254292- All cross-session artifacts written: the report, the run-ledger row, the memory pointer.
255293- ` .claude/.e2e-loop-active ` removed (on done AND on any abort).
0 commit comments