Aug-1 Completion SOW — transfer rail, instant sends, needs-review autopilot

Self-contained execution SOW for a fresh session — finish the transfer-rail work, build event-based sends, build the needs-review resolver, launch the three parked agent lanes. All context, ids, and gates included.

Updated 2026-08-01

1 Hard rules — read before anything else

  • NOTHING client-facing sends without Akash's explicit go in that session. Akash issued a hard stop ("DON'T SEND ANYTHING CLIENT FACING") at the end of the Aug-1 session, minutes before 8 backlogged lead texts would have reached Dan. They were pulled in time — zero delivered (ledger 92351). Approval from an earlier turn or session does NOT carry forward.
  • Client-facing = anything that reaches Dan (+12147831312), any homeowner, any client channel. Building infrastructure is fine; firing it is gated.
  • Never resume the organic publisher without flipping sp_organic_config mode to dryrun first — it is currently set enabled=true, mode='live' and would publish to Facebook/Instagram immediately.
  • The three-gates rule (fleet SOW): spend, publish, outbound sends. Everything else runs without asking.
  • All external writes ledgered via brain.log_change(project, action=…, why=…, surface=…, reverse_how=…)public.change_ledger.
  • Plain English in anything Akash reads. Ids only in agent-facing sections.

2 Where the day ended (context for a cold start)

The business now runs on the 3-function frame: marketing (content shipped → leads), sales (conversations started → appointments booked), delivery (tickets resolved → cash flow). Canonical doc: https://stpierre-fleet-sow-docs.pages.dev (v2). Shipped Aug-1 and verified: Telegram HQ group -1004401888570 with topics (alerts 5 · daily_reports 7 · notes 8 · approvals 9 · agent_work 12; registered in vault row telegram/agency/progress_tracker metadata); Hermes on the vaulted Anthropic key with a watchdog (launchd com.stpierre.hermes-heartbeat, alerts ≤45 min); morning brief 7:30 leads with the six numbers; scoreboard collapsed 8 departments → 3 lanes (sp_department_registry.lane_slug, shared metric module .codex/references/sp_lane_metrics.py); tickets instrumented (public.sp_tickets, view v_ticket_resolution_daily, triggers on ops_alerts/ops_anomalies); worker (hermes_runner.py) scope-locked to Linear agent-ready cards, still PAUSED.

Transfer-rail truth (corrected Aug-1, supersedes older memory): the rail WORKS. GHL → bot qualifies → DB trigger sp_enqueue_qualified_lead_transfer seeds one row per enabled destination in sp_client_lead_transfers → n8n drain 6ET0nCwUKY35WBwR (5-min tick) sends via GHL SMS. Destinations (sp_client_delivery_destinations): Dan d251f29c… = real leads; Akash 1f802afa… = test-only. The drain's routing guard rejects real→Akash (akash_route_is_test_only) and test→Dan by design. Iqbal Mahmood + Charles Earls delivered to Dan automatically Aug-1. The false "hand-off FAILING" alerts on guard rejections are fixed (sp_transfer_alert() patched, ledger 92346).

3 Workstream 1 — the 8-lead backlog (GATED on Akash, do first when he says go)

8 real qualified leads (Jul 25–28) never got a Dan transfer row — they qualified before Dan's destination was enabled Jul-31, and the enqueue trigger fires only once at qualification: Twyler Webster, Sam Etoum, Spencer Johnson, Cindie Stewart, Scott Edwards, Mike Yeo, Nathan Green, Esther Williams Pilgrim.

Approval flow (Akash's standing rule, set Aug-1): copy/paste the exact packet text to him FIRST, per lead, and send only the ones he names. The full approval pack (all 8 packets verbatim) was posted to the HQ Approvals topic on Aug-1 and is reproduced in the session transcript. Only 5 are sendable — Cindie Stewart, Scott Edwards, Spencer Johnson, Sam Etoum, Nathan Green. Three have NO phone number (Twyler Webster, Mike Yeo, Esther Williams Pilgrim) → they go to Workstream 3, not to Dan.

  • 1Get his verdict on the 5 (he may name a subset; Nathan Green is thin — phone only, no location).
  • 2On explicit go: re-run the seed INSERT from ledger row 92345 (public.change_ledger) for exactly the approved leads — it is idempotent (ON CONFLICT (lead_id, channel, recipient_last4) DO NOTHING), marker seeded_by='manual_backfill_2026_08_01_akash_go'.
  • 3Know the timing trap that burned the last session twice: the drain's claim SQL has a 10-minute QC backstop keyed on the transfer row's created_at — fresh rows are invisible to the drain for 10 minutes, then the next 5-min tick sends. Verify with: rows where provider_message_id IS NOT NULL.
  • 4NOT ready, do not send: the needs-review pile (10 leads incl. Jeff Loiacono, John Krebs) — that's Workstream 3's job.

4 Workstream 2 — event-based sends (Akash approved the build: "5 min is way too slow")

Goal: a qualified lead reaches Dan in seconds, not up to 15 minutes (5-min tick + 10-min backstop).

  • 1Build: Postgres trigger on sp_client_lead_transfers INSERT → n8n webhook that immediately runs the same claim+send logic. n8n hosting is the approved first choice; new n8n workflows are pre-approved (hosting-hierarchy memory). Reuse the drain's nodes — clone workflow 6ET0nCwUKY35WBwR, swap the schedule trigger for a webhook trigger, keep EVERY guard (routing, QC gate, kill switch, retries).
  • 2Decide the QC backstop: instant send can't wait 10 min for qc_checked_at. Options: (a) trigger fires only when qc_checked_at is already set (QC runs at qualification — verify), (b) keep 10-min path as fallback for unchecked rows. Do NOT silently drop the QC gate.
  • 3Keep the 5-min drain as the reconciliation backstop (event-based > loop-based; loops = thin reconciliation).
  • 4Test with a self-test lead ONLY (Jean = text the 626 line; Jordan lane = DM the DFW page from a NON-admin FB account; Akash's +14143085477 is is_test by design). A test lead exercising the Akash route is allowed; nothing may touch Dan.
  • 5n8n API access: vault n8n/agency/rest-api-cowork-claude, base https://eyefly.app.n8n.cloud/api/v1. Pagination quirk: ?page=N works, ?per_page= errors.

5 Workstream 3 — needs-review autopilot (Akash: "why can't you review, fix and send yourself?")

Today needs-review leads rot invisibly (John McLaughlin sat 8 days). Akash's standing answers: he reviews in Telegram Approvals topic + stpierre-unblock-queue.pages.dev (interim), and the real fix is AI-first resolution.

  • 1Inventory why each of the ~10 needs-review leads failed QC: sp_client_leads.qualification_state='needs_review' + metadata (usually missing phone/ZIP, or qc_failed_needs_review on the transfer). A DB trigger from Jul-31 already re-extracts late phone/ZIP from new inbound messages and re-fires — check why it didn't clear these (memory: qualification-fires-before-contact-info).
  • 2Build the resolver (nightly + on-event): re-read the full conversation, re-extract missing fields, auto-fix what's provable (write to the lead row, ledgered), flip back to qualified → transfer seeds normally (send still respects Workstream 1's gate until Akash's standing go exists).
  • 3What it may NOT do alone: message the homeowner to re-ask for missing info (client-facing → per-lead approval in Approvals topic, with the drafted re-ask attached), or judge ambiguous intent/anger (→ ticket to Akash with a recommendation and a ★ default).
  • 4Every unresolved case = a ticket in sp_tickets (source needs-review-lead) so delivery's time-to-resolution number sees it. The escalator already texts new criticals to the HQ Alerts topic.

6 Workstream 4 — the three parked agent lanes (approved for Opus subagents, never launched)

Launch as parallel subagents; all are internal builds, no client sends:

  • 1Alex booking wire — GHL Conversation AI agent R6mqKPSx0Lcv2kCe0Mru (staged, suggestive, SMS-only, empty actions array so step 4 BOOK dead-ends). Wire the calendar handoff via the Conversation AI API (the one GHL write path that's allowed; UI builds are Akash-only). If the calendar id is ambiguous, stop and name it.
  • 2Jordan templating + frustration monitor — snapshot Level King's live config (prompt, extraction CVs, workflows *1/*2/*5/⭐, n8n bridge params) into a versioned per-niche template JSON; build a nightly classifier over sp_client_messages scoring homeowner frustration → ops_alerts on threshold. Propose the schedule, don't self-schedule.
  • 3Morgan consolidation — one daily cadence over the existing creative machinery: the 07:45 pack (sp-daily-pack-pilot Hermes cron) + a five-line spend/CPL note posted via brain.telegram_hq_send('daily_reports', …). Meta activation stays behind the spend gate, always.

7 Workstream 5 — verify the scoreboard-page collapse

A separate session is running task "Collapse team scoreboard page to 3 functions" (build_scoreboard.py / render_control_room.py still draw 8 department cards). Verify it landed; it's a deployed page, so preview + Akash approval before deploy (preview-before-deploy memory).

8 Open gates on Akash (say-the-word list)

GatePhrase / action
Send the 8 backlogged leads to Danexplicit go in-session (Workstream 1)
Resume the worker"resume the worker" (scope now Linear agent-ready only)
Friday reflection ritehis word (paused since Jul-31)
Command-center sweep rebuilddecision task 3ac667bb — ★ default: rebuild as Hermes job
Casey Phase 0 (~30 min)pay $40.01 on act_3289323034532141 · one real 3rd-party DM to m.me/1308868515634109 · 4 GHL clicks
Own-ads batch (STP-37)approval waiting since Jul-31 17:47
North-star page reframe + income-dashboard foldpreview + approval

9 Context pack (agent-facing)

  • Brain: sys.path.insert(0,'/Users/akash/Documents/Claude/.codex/references'); import brain. Vault reads: brain.get_credential(service, scope=…, label=…). Telegram: brain.telegram_hq_send(topic, text).
  • Aug-1 ledger rows (all in public.change_ledger, each with reverse_how): 92336 fleet-SOW v2 · 92337/92338 scoreboard lanes+metrics · 92339/92340 tickets schema+backfill · 92341/92342 brief prompt+feed · 92343 lane files · 92345 backlog seed (retracted) · 92346 alert patch · 92351 retraction.
  • Key files: 01-Projects/CommandCenter/watchdog/{escalate.py, hermes_heartbeat.py} · 01-Projects/St_Pierre_Digital/agent-board-rail/hermes_runner.py · 01-Projects/CommandCenter/tickets/{schema.sql, backfill.py, README.md} · 01-Projects/StPierre-GTM/loop-engine/{loop_engine.py, nightly_actuals.py} · .codex/references/sp_lane_metrics.py · ~/.hermes/scripts/sam_morning_brief_data.py · ~/.hermes/cron/jobs.json.
  • Docs: fleet SOW https://stpierre-fleet-sow-docs.pages.dev · pages cheatsheet https://stpierre-deployed-pages-docs.pages.dev (Rev 3, 72 cards) · decision cockpit https://stpierre-unblock-queue.pages.dev.
  • Hermes: gateway launchd ai.hermes.gateway; venv has no pip (use uv) and no psycopg2 (cron .py scripts must exec system python); never rebuild on claude -p; never call setWebhook/deleteWebhook (gateway long-polls getUpdates and owns inbound).
  • Session handoff: this session's work is also captured in Postgres handoffs (search session_handoffs for 2026-08-01).

10 Done-when checklist

- [ ] Backlog decision made by Akash; if go → 8/8 provider_message_id set, alerts clean

- [ ] Qualified→Dan latency under 60s on a self-test lead, all guards proven intact, drain still passing as backstop

- [ ] Needs-review pile ≤ judgment-only; every remaining case is a ticket with a drafted next step in Approvals

- [ ] Alex books a test call end-to-end; Jordan template JSON exists + frustration classifier proposed; Morgan's daily note lands in Daily Reports

- [ ] Scoreboard page shows 3 functions (after preview approval)

- [ ] All changes ledgered; fleet SOW updated if any state flips ("update the fleet SOW")