The lowest-friction history-acquisition path so far. Customer scans one fresh QR, waits for WhatsApp Multi-Device sync, then `bootstrap.sh` pulls the resulting .txt files directly from PulseAgent. Zero device backup, zero password, zero USB.
What changed
Added
- `scripts/fetch-from-pa.py` — Client-side downloader that calls PulseAgent's `/whatsapp/export-history` endpoint and unpacks the ZIP into `exports/`. Returns exit code 2 on 404 ("no history imported yet") so wrapper scripts can fall back to backup extraction.
- `bootstrap.sh` — Path B/C now offers a three-way choice: Path D / Auto (v0.4 backup extractor) / Manual. The Path D prompt prints an explicit 6-step prerequisite checklist including the unavoidable "wait 30 min – 6 hours" expectation so no client feels stalled mid-process.
- `docs/UPSTREAM-POLICY.md` — Frozen policy. PulseAgent has zero source-level coupling with upstream openclaw; cherry-pick rules only become necessary if that ever changes. Documents what the OpenClaw Release Routine is allowed to touch (marketing docs only, never customer-running code).
- `docs/CUSTOMER-DELIVERY-GUIDE.md` — Decision tree extended with Q2.5 (Path D eligibility check: SYNC_HISTORY=1, downtime tolerance, fresh-QR willingness, Device History setting).
Backend dependency
Path D requires a PulseAgent deployment with the companion PR merged (iPythoning/PulseAgent#135):
- `whatsapp_history_imports` table
- `POST /v1/relay/history-batch` (Bearer bridge token, idempotent via `UniqueConstraint`)
- `GET /whatsapp/export-history` (Bearer user token, ZIP response)
- whatsapp-relay must run with `SYNC_HISTORY=1`
Why Path D isn't the only path
WhatsApp Multi-Device sync only fires on a fresh QR scan. An already-linked device cannot retroactively backfill history even after `syncFullHistory: true` is set on the relay. So Path D = tear down + re-link = hours of downtime for any tenant whose AI is already running on WhatsApp.
Backup extraction (v0.4) stays the default for tenants who need zero-downtime onboarding. Path D shines for greenfield customers who haven't yet linked their account.
Decision matrix (when to use which)
| Scenario | Recommended path |
|---|---|
| Greenfield customer, comfortable with "wait several hours" | Path D |
| Tenant already running AI on WhatsApp (zero downtime required) | Path B/C (v0.4 backup) |
| Customer's iPhone has "Device History: Last 90 days" set | Path B/C (v0.4) — Path D won't pull more |
| Large account (10k+ messages) | Path B/C (v0.4) — Multi-Device sync is slow/flaky at scale |
| Small/medium account, no time pressure | Either works |
Test plan (before first paid Path D delivery)
- Stand up a tenant relay with `SYNC_HISTORY=1`
- `POST /qr-refresh`, scan QR with a test WhatsApp account
- Verify rows accumulating in `whatsapp_history_imports`
- Pull via `fetch-from-pa.py`, verify .txt format matches what `whatsapp-export-parser.py` expects
- Run end-to-end through profile extractor → miner → KB upload
- Tenant isolation test: confirm tenant A's export doesn't see tenant B's rows
Compatibility
Drop-in extension of v0.4. All prior paths (A/B/C + Auto/Manual) preserved. `fetch-from-pa.py` output is byte-compatible with v0.4 device-backup extractors so the downstream pipeline (parser → profile extractor → miner → upload) is unchanged regardless of source.
See `CHANGELOG.md` → 2026-05-22 v0.5 entry for full details.