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.
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_configmode to dryrun first — it is currently setenabled=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), markerseeded_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 whereprovider_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_transfersINSERT → 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 workflow6ET0nCwUKY35WBwR, 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 whenqc_checked_atis 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_testby design). A test lead exercising the Akash route is allowed; nothing may touch Dan. - 5n8n API access: vault
n8n/agency/rest-api-cowork-claude, basehttps://eyefly.app.n8n.cloud/api/v1. Pagination quirk:?page=Nworks,?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, orqc_failed_needs_reviewon 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(sourceneeds-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_messagesscoring homeowner frustration →ops_alertson 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-pilotHermes cron) + a five-line spend/CPL note posted viabrain.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)
| Gate | Phrase / action |
|---|---|
| Send the 8 backlogged leads to Dan | explicit go in-session (Workstream 1) |
| Resume the worker | "resume the worker" (scope now Linear agent-ready only) |
| Friday reflection rite | his word (paused since Jul-31) |
| Command-center sweep rebuild | decision 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 fold | preview + 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 onclaude -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_handoffsfor 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")