← back to AbramsEgo
lib/spend-reviews/README.md
25 lines
# Spend → Reviews (TK-11433)
AbramsEgo panel that turns Steve's spend into approved, personalized reviews +
thank-you letters — **every post/send is per-item human-gated.**
## Flow
`ingest → resolve (DTD Option B) → draft ($0 local voice) → per-item APPROVE → GATED post/send`
## Files
- `config.js` — paths + HARD RAILS. All executor switches OFF by default; nothing here flips them.
- `store.js` — the `spend_item` record contract + JSONL persistence + merchant normalize/dedupe + place cache + action audit log.
- `adapters/amazon.js` — openclaw real-Chrome scrape of Amazon order history (READ-ONLY). One-time Steve login surfaced as `needsAction:'amazon-login'`.
- `adapters/gmail-receipts.js` — George bridge (:9850) receipt scan (READ-ONLY). Probes for the read route/creds; reports `needsAction` if unwired.
- `adapters/csv.js` — bank/CC statement CSV parser (upload or `data/csv-drop/`). Skips payments/refunds; positive = spend.
- `resolver.js` — **DTD verdict Option B (2026-09-10, 3/3)**: normalize+dedupe cache → keyless Google-Maps search deep-link; place_id captured in-browser at post time. Places API is an OFF-by-default, gated, capped fallback. Amazon resolved from ASIN/seller only — never a bank descriptor.
- `drafts.js` — Steve's genuine positive voice, templated + de-slopped, `$0 (local)`.
- `executors.js` — THE GATED EDGE. `executeTarget` returns the plan (gated) unless the target is per-item APPROVED **and** `{live:true, confirm:<id>}` **and** `SPEND_REVIEW_EXECUTORS_LIVE=1`. No bulk/autonomous path — `draftPendingApprovalMemo` writes to `~/.claude/yolo-queue/pending-approval/` and fires nothing.
- `router.js` — `/api/spend/*` (mounted after Basic-Auth in server.js).
## Activation (what Steve does)
1. **Amazon:** in the openclaw Chrome window, log in once: `openclaw browser open "https://www.amazon.com/gp/css/order-history"` — then click *Ingest Amazon*.
2. **Gmail receipts:** set the correct George read creds/endpoint in AbramsEgo `.env` (`GEORGE_USER`/`GEORGE_PASS`); the adapter reports the exact `needsAction` if unwired.
3. **CSV:** *Upload statement CSV* (or drop files in `data/csv-drop/`).
4. **Go live (gated):** set `SPEND_REVIEW_EXECUTORS_LIVE=1` in `.env` + `pm2 restart abramsego`. Then each *Post/Send* click fires only for that one approved item.