mattrguerra/meridian-outreach-vaultmainPrivate on GitHub, published here in full

README.md

Language Markdown8.4 KB124 lines

07-Automation/README.md

  1. ---
  2. type: automation-index
  3. scope: 07-Automation
  4. tags: [claude, outreach, automation]
  5. created: 2026-07-22
  6. last_modified: 2026-09-21
  7. ---
  8. # 07-Automation: Weekly Partner Client Pipeline
  9. The **live** Cowork automation that turns live Plinth order data into a partner client
  10. classification each week, maintains the partner stubs and the XML census, and (on your
  11. approval) continues to enrichment and Bitrix. Everything here is plain files you can
  12. edit in VS Code and re-upload.
  13. ## The files
  14. - **[[partner-thresholds]]**: config + the activation checklist. Tier bands are live
  15. program values; `min_orders_to_qualify: TBD` is the arming switch. Single source of
  16. truth; the driver parses the ` ```yaml ` block out of it.
  17. - **[[Weekly-Partner-Pipeline-SOP]]**: the full A0→H procedure and the guardrails,
  18. including **"Why incremental"**, the Plinth truncation bug that dictates the whole
  19. architecture. Read that section before touching Stage A.
  20. - **`weekly_partner_pipeline.py`**: the deterministic engine, v2 incremental:
  21. `seed-baseline` → `ingest` (dedupe by `order_ref`) → `classify` (from local history)
  22. → `verify` (no-shrink) → guarded stub/XML/workbook writes, then the read-only Bitrix
  23. stages (`reconcile-deals`, `route`, `outreach-pull-list`, `outreach-audit`). Does not
  24. call Plinth or Bitrix; Claude feeds it the raw page dumps and deal pulls. The file is
  25. the command-line entry point; the code is in **`partner_pipeline/`**, one module per
  26. stage (`stages.py` holds the funnel, stage-name and send-token tables).
  27. - **`requirements.txt`**: pyyaml and openpyxl for the driver, freezegun for the replay.
  28. - **`data/order_history.json`**: the local order history (created at seed time). This,
  29. not the API, is the source of truth for lifetime value.
  30. - **[[scheduled-task]]**: the live weekly schedule + the exact prompt (ENABLED
  31. 2026-07-23).
  32. - **[[pipeline-routing-rules]]**: the entry rules `route` implements, and the four-funnel
  33. audit scope.
  34. - **`sample/`**: the generator and replay that produced every client file in this repo
  35. (see "The sample" below).
  36. ## Current state (2026-07-24)
  37. 1. **LIVE.** Seeded from Ines's roster workbook (baseline as_of 2026-07-20), armed
  38. (`min_orders_to_qualify: 1`), and scheduled: Mondays 06:00 America/Chicago,
  39. autonomy `through_vault`. First run completed 2026-07-23: verify OK, stubs + XML census
  40. refreshed for the whole partner base. (The shipped sample's first run, 2026-09-14:
  41. 128 partner clients, Palladium 85 · Platinum 28 · Iridium 8 · Rhodium 7.)
  42. 2. `refresh-xml` maintains the XML map as a **complete partner census** (adds
  43. empty-pipeline `pl-` chunks for anyone missing; idempotent).
  44. 3. Enrichment (Stage G) and Bitrix push (Stage H) remain **manual and human-gated**;
  45. nobody is routed into an outreach/watch pipeline until those entry rules are decided.
  46. ## Activating it
  47. Follow **[[Activation-Runbook]]**: the definitive step-by-step, with commands
  48. validated against the roster workbook (in this repo, the sample roster in
  49. `sample/inputs/`). Short version: two-pass seed (All Accounts then the Complete list),
  50. catch-up pull, set `min_orders_to_qualify`, classify + verify + reconcile, one manual E to H
  51. pass, enable the schedule.
  52. ## The sample
  53. Meridian Display Co. and every client in this vault are fictional. The client data is not
  54. hand-written: two scripts in `sample/` invent a client book and then run the real driver
  55. over it.
  56. - **`sample/generate_sample.py`** invents the book: 381 Plinth accounts with a
  57. roster workbook (`sample/inputs/Partner-Clients-Roster_2026-09-07.xlsx`, tabs
  58. "2026 Partner Working List", "Complete Partner Clients List" and "All Accounts", totals
  59. through 2026-09-07), two weeks of Plinth `orders.fetch` page dumps, and two weekly
  60. Bitrix deal enumerations with their stage histories and contacts. It is seeded, so every
  61. run produces the same world. The world is built to exercise the parts of the driver that
  62. matter: a Plinth day (2026-09-17) that truncates silently at 50 rows with overlapping
  63. offsets; cancelled (27) and refunded (28) orders; clients crossing a tier band mid-week
  64. and a brand-new customer who qualifies on a first order (`has_baseline=False`); an
  65. approved merge; the directly-partnered Harlow Ridge Homes mailboxes (Rhodium by
  66. override, never cold-emailed) and a staff mailbox on our own domain; an identity twin
  67. where only one twin carries the Not Interested closure; a shared company mailbox; a
  68. role-named account and a messy shipping-label name; retired Bitrix stages, same-minute
  69. workflow re-entries, and a cart that moved into production funnels after converting.
  70. - **`sample/run_sample.py`** replays two Monday runs (2026-09-14 and 2026-09-21) of
  71. `weekly_partner_pipeline.py` against those inputs, doing what the scheduled session does
  72. with the MCP calls stood in for by files: seed the baseline in two passes and copy the
  73. roster as the first Drive-swap base; then per run, pull and ingest each day of the
  74. window until a page adds nothing, `classify`, `verify`, `write-stubs`, `refresh-xml`,
  75. `refresh-workbook`, `reconcile-deals`, `route`, `outreach-pull-list` (attaching stage
  76. histories and contacts only for the deals it asks for), and `outreach-audit`. The clock
  77. is pinned to each run date with freezegun, because the driver dates its outputs by
  78. today's date; that is the only thing it changes. Each run's console output is saved as
  79. `05-Outputs/partner-runs/run-log_<date>.txt`.
  80. **Regenerating.** The replay refuses to run if `07-Automation/data/order_history.json`
  81. exists, so run it on a scratch copy with the generated state removed. The root
  82. [[README]] ("Replay the sample") has the exact commands and the `diff` that checks the
  83. result: only the ten hand-researched stubs differ, because the replay does not regenerate
  84. them. The replay copies each day's Plinth pages into `05-Outputs/partner-runs/raw/`, which
  85. is not committed (the committed copy is `sample/inputs/plinth/`).
  86. **What came from the replay.** Every stub in `03-Clients/client-stubs/`, the census
  87. `03-Clients/partner-client-master-list.xml`, everything in `05-Outputs/partner-runs/` (plus
  88. the two `Bitrix_Pipeline_Outreach_Audit_*.xlsx` workbooks in `05-Outputs/`), and everything
  89. in `07-Automation/data/` (the merge registry and suppression list are copied in from
  90. `sample/inputs/`). State after the 2026-09-21 run: 381 Plinth accounts in history; 130
  91. partner clients (Palladium 86, Platinum 29, Iridium 8, Rhodium 7), 130 stubs and 130 census
  92. chunks, 43 of them with pipeline placement; 54 deals across the four audited funnels, 28
  93. with a verified touch; route: Winback 50, cat 24 first-touch 31, Dormant queue 4, excluded 45.
  94. **What was added by hand on top.** Ten stubs carry invented research under `## Research` (written the way `client-enrich` writes it, with sources on `.example` hosts), a few carry Human Notes and Outreach Log rows that match their Bitrix history, `05-Outputs/First Email/` and `05-Outputs/Second Email/` hold eleven sample drafts spread across the six stages, and `04-Working/dual-active-pipelines_2026-09-21.md` is a review note built from the 09-21 census. A fresh replay does not recreate these.
  95. ## Design decisions worth knowing
  96. - **Incremental by necessity.** Plinth `orders.fetch` truncates at roughly 70 orders per
  97. response with no signal and unreliable offsets (verified on one long-standing account,
  98. 2026-07-22; see [[DECISIONS]]). Lifetime totals therefore come from the local history
  99. store, never from a single API call. The `verify` no-shrink guardrail is the tripwire.
  100. - **Two existing skills do the last two stages**: `client-enrich` (enrichment) and
  101. `partner-pipeline-push` (Bitrix). This template chains them; it does not duplicate them.
  102. - **Modification date is new.** Neither stubs nor the XML map carried one. The driver adds
  103. `last_modified` (frontmatter) and `<last_modified>` (XML), deliberately named apart from
  104. the historical `updated` key the enrichment writeback avoids.
  105. - **Human Notes and Research are never written** by the classifier. Research is only ever
  106. touched by `client-enrich`. This is the [[CLAUDE-clients]] scraping-dump contract.
  107. - **Bitrix is always human-gated.** Even at full autonomy the SOP holds the push for a person.
  108. - **Shared vault:** every write stage appends one [[LEDGER]] entry.
  109. ## Dependencies
  110. `pip install -r 07-Automation/requirements.txt` (openpyxl optional for the driver, which
  111. falls back to CSV; freezegun is only for replaying the sample). Plinth MCP must be connected for the pull;
  112. Apollo/Apify for enrichment; Bitrix for the push.