← back to Delivery Address Fix

SKILL.md

132 lines

---
name: delivery-address-fix
description: Pluggable, provider-adapter skill that fixes/saves a delivery address on a food-delivery account (UberEats, DoorDash, Instacart) by driving a REAL headed Chrome through the provider's own site UI, with human-in-the-loop 2FA relayed over email. Use when Steve (or any authorized user) says "change my delivery address on <provider>", "my order is going to the wrong address", "save this address on ubereats/doordash/instacart", "/delivery-address-fix", or replies to an in-flight address-fix thread with a 2FA code, card digits, or an address. Born from the 2026-08-02 UberEats session (TK-10140); generalized per Steve's directive ("The system must work for all users. Allow user to plugin this skill for ubereats or Instacart and door dash", 2026-08-02, TK-10145).
---

# delivery-address-fix — pluggable delivery-address fixer

One engine, N provider adapters. The engine owns the browser session, the
human-in-the-loop (HITL) email relay, and the hard rails. Each adapter
(`references/<provider>.md`) owns the provider-specific selectors and flow.

## Architecture

```
user email/request
      │
      ▼
 ENGINE (this file)          ADAPTERS (references/)
 - session lifecycle    ──►  ubereats.md   (PROVEN 2026-08-02)
 - HITL email relay          doordash.md   (scaffold — verify on first run)
 - hard rails                instacart.md  (scaffold — verify on first run)
 - screenshots/audit
```

## Engine: session lifecycle

1. **Workdir per run**: `~/delivery-address-fix/<provider>-<yyyymmdd>/`
   (screenshots, step scripts, HANDOFF.md). Keep a HANDOFF.md updated after
   EVERY state change so any later session can resume cold.
2. **Browser**: long-lived headed REAL Chrome via Playwright persistent
   context — launcher template in `scripts/browser-server.js` (edit profile
   dir, CDP port, start URL per provider; one port per provider, 9223+).
   Headless gets bot-walled; headed real Chrome is the proven path.
3. **Connect for each step over CDP** (`http://127.0.0.1:<port>`) with short
   scripts — never restart the browser between steps; the parked session IS
   the state.
4. **⚠️ Select the target tab by URL substring** (e.g. `uber.com`), NEVER
   `pages()[0]` — other tasks open tabs in the same browser (proven failure
   2026-08-02: a Tesla auth tab became index 0).

## Engine: HITL email relay (2FA, card gates, address)

The user is remote; codes and card digits arrive by email reply, gated by the
sender allowlist + secret phrase (per the mailbox's standing rules).

- **Code gates (SMS/call/email) EXPIRE FAST** — Uber sessions died in well
  under 30 min. Enter codes the moment they land. If expired: restart the
  auth flow (adapter has the script pattern), tell the user the NEWEST code
  wins, and that any resend INVALIDATES prior codes. Never resend
  speculatively — only when the user says the code didn't arrive.
- **Static gates (card-digit verification) do NOT expire** — park and wait.
  NEVER guess digits, NEVER submit blank (risks killing the session). If the
  reply contains no digits, re-ask specifying exactly which digits.
- **Email-code self-read**: if the provider offers an email code and the
  user's inbox is George-readable, read it yourself (strip `<style>` blocks;
  beware numbers in the provider's footer address masquerading as codes).
- Every ask to the user states: what's needed, the exact reply format
  ("1234 <secret-phrase>"), and that sooner is safer.

## HARD RAILS (engine-level, all providers)

1. **VERBATIM ADDRESS ONLY.** Save exactly the address the user typed —
   street, city, zip, verbatim. NEVER infer an address from location data,
   map readings, charger positions, or context. (2026-08-02 lesson: an
   inferred "668 S Alameda St" from a Supercharger reading was WRONG —
   "I have never been at alameda!!". If the user hasn't stated the address,
   ask for it.)
2. **Never place, cancel, or modify orders** without an explicit per-action
   go. Address save ≠ order authority.
3. **Surface before deleting**: list any existing saved addresses that look
   wrong to the user before removing anything.
4. **Live-order first**: after login, check for an active order; if it shows
   a wrong address, use the provider's order-Help change-address path (if
   offered) before touching the address book.
5. **Screenshot every step** into the workdir; update HANDOFF.md.
6. **Credentials**: only from the secrets master (`~/Projects/secrets-manager/.env`)
   or the user's explicit reply. Never echo full card numbers/codes back —
   last-4 only.
7. **Ticket everything** (`tk`); cost line on every report ($0 local browser).

## Multi-user plugin model (Kickback.ai direction)

Per-user config object — everything user-specific is parameterized, nothing
hardcoded:

```json
{
  "user_id": "steve",
  "provider": "ubereats | doordash | instacart",
  "login_email": "…",
  "email_reader": "george:steve-personal | none",
  "reply_gate": { "allowlist": ["…"], "secret": "…" },
  "address": { "street": "…", "city": "…", "zip": "…", "nickname": "…" },
  "cdp_port": 9223
}
```

The engine + adapters read ONLY from this config. A hosted/product version
(Kickback.ai) swaps the email relay for an in-app prompt but keeps the same
adapter contract: `login() → passGates() → liveOrderCheck() → saveAddress()`.

## Adding a provider

Copy `references/_adapter-template.md`, fill in: auth URL, login selectors,
2FA gate types observed, address-book path, order-help path, quirks. Mark
UNVERIFIED until a real run proves each step; promote to PROVEN with dates.

## Runnable scripts (merged from TK-10144, 2026-08-02)

Generic, parameterized — nothing user-specific hardcoded. All take
`--platform <ubereats|doordash|instacart> --user <email> --port <cdp> --match <url-substring>`;
per-user persistent Chrome profiles live under `profiles/<user>-<platform>/`
(gitignored) so a completed login survives restarts.

- `scripts/launch.js` — headed real Chrome (Playwright persistent context,
  `channel: 'chrome'`), CDP exposed, navigates to the provider's auth URL.
  Supersedes the per-run `browser-server.js` template (kept for reference).
- `scripts/state.js` — screenshot + page text of the target tab (selected by
  `--match`, never `pages()[0]`).
- `scripts/enter-code.js` — types a 2FA code / card digits into the parked gate.
- `scripts/restart-login.js` — restarts an expired auth flow (auto-fires a
  fresh code; remind the user the NEWEST code wins).
- `scripts/lib.js` — shared CDP attach + tab-select helpers.

Per-user setup: `config.example.json` → `config.json` (gitignored).
Extra flow notes and failure modes: `references/platform-notes.md`.

> Consolidation note: this skill absorbed `~/Projects/delivery-address-skill`
> (TK-10144) on 2026-08-02 per Steve's "work with the other terminal" email —
> two parallel sessions had built the same generalization. This repo is
> CANONICAL; the other is deprecated with a pointer.