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

README.md

Language Markdown8.4 KB137 lines

README.md

  1. # Meridian Outreach Vault
  2. The Obsidian vault and Claude Cowork project behind a print and display shop's quarterly
  3. client outreach. One linked note per partner client, a machine-readable census over all of
  4. them, a weekly pipeline that keeps both current from the order system, and a drafting
  5. pipeline that turns research into audited emails a person approves before anything is sent.
  6. **The company is fictional, and so is every client.** This vault was built for, and run
  7. every week at, a real print and display shop. Here it serves **Meridian Display Co.**, the
  8. invented company behind [meridian-ops-board](https://github.com/mattrguerra/meridian-ops-board),
  9. [meridian-crm-mcp](https://github.com/mattrguerra/meridian-crm-mcp),
  10. [meridian-orders-mcp](https://github.com/mattrguerra/meridian-orders-mcp) and
  11. [meridian-skills](https://github.com/mattrguerra/meridian-skills). The notes, rules, code and
  12. history are the real ones with the business taken out: staff, clients, programs, products,
  13. links and numbers are invented. The one real person is Matt Guerra, who built and ran it.
  14. **The client book is a generated sample.** No real client record survived the move. In its
  15. place, `07-Automation/sample/generate_sample.py` invents 381 order-system accounts,
  16. two weeks of orders and two weeks of CRM deals, and `run_sample.py` replays two Monday runs
  17. of the real weekly driver against them. Every stub in `03-Clients/`, the census, both weekly
  18. workbooks and the outreach audit are that driver's own output. On top of that, ten stubs carry
  19. hand-written research and eleven sample drafts sit in the email pipeline, all invented. The history notes
  20. ([LEDGER](LEDGER.md), [DECISIONS](DECISIONS.md), [CHANGELOG](CHANGELOG.md)) describe the system as it ran on the real book,
  21. at real scale, with invented numbers.
  22. For live numbers, start at [00-Index](00-Index.md). For how Claude works here, see [CLAUDE](CLAUDE.md).
  23. ## What it does
  24. - **Keeps a census of the Partner Program.** Every client whose lifetime spend puts them in
  25. a tier (Palladium, Platinum, Iridium, Rhodium) has a stub in `03-Clients/client-stubs/`
  26. and a chunk in `03-Clients/partner-client-master-list.xml`, carrying their order-system id,
  27. CRM contact id and every outreach funnel they sit in.
  28. - **Runs itself weekly.** The [Weekly Partner Client Pipeline](07-Automation/Weekly-Partner-Pipeline-SOP.md)
  29. pulls the week's orders from Plinth (the order system), recomputes lifetime value,
  30. classifies, refuses to continue if any total shrank, writes and upgrades stubs, refreshes
  31. the census and the roster workbook, reconciles the CRM's deals, proposes who to contact
  32. next, and audits who was actually contacted and when.
  33. - **Drafts outreach with a human in the loop.** Emails are drafted in Matt's voice from the
  34. stub's sourced research, scored for confidence, audited in three passes (facts, voice,
  35. template), and moved stage by stage through `05-Outputs/First Email/` and
  36. `05-Outputs/Second Email/`. Nothing is sent, and no CRM record is written, without a person.
  37. ## Vault map
  38. | Folder | What's in it |
  39. |---|---|
  40. | `01-Tiers/` | Partner tier notes (Palladium / Platinum / Iridium / Rhodium, and Retail) with Dataview rollups of their members. |
  41. | `02-Outreach/` | Outreach play notes, the approved email templates, call scripts. |
  42. | `03-Clients/` | `client-stubs/` (one note per client, flat), the XML census, and the folder rules ([CLAUDE-clients](03-Clients/CLAUDE-clients.md)). |
  43. | `04-Working/` | In-progress review notes. |
  44. | `05-Outputs/` | The two email pipelines, each weekly run's artifacts (`partner-runs/`), and the outreach audit workbooks. |
  45. | `06-Resources/` | The drafting prompts. |
  46. | `07-Automation/` | The weekly driver, its config, SOP, routing rules, runbook, schedule, local data, and the sample generator. |
  47. | `08-Planning/` | **Human-only** planning space. Claude reads it, never writes to it. |
  48. ## The weekly pipeline
  49. `07-Automation/weekly_partner_pipeline.py` is the entry point of one deterministic program
  50. (Python, pyyaml, openpyxl; the code is the `07-Automation/partner_pipeline/` package, one
  51. module per stage) that never calls an API itself: the scheduled Claude session makes the
  52. Plinth and Bitrix calls through their MCP servers and hands the raw responses to it. The
  53. design decisions worth reading:
  54. - **Incremental by necessity.** Plinth's `orders.fetch` silently truncates large result sets
  55. (about 70 orders a response, no "has more" flag) and its offsets overlap. So lifetime value
  56. is never asked of the API: it comes from a local, append-only order history seeded once
  57. from the roster workbook, and each week's pull is paged day by day until a page adds
  58. nothing new. See [DECISIONS](DECISIONS.md), 2026-07-22.
  59. - **The no-shrink guardrail.** Lifetime totals can only grow. If one shrinks, `verify` exits 2
  60. and the run stops before anything is written: missing data must never demote a client.
  61. - **Relationship over arithmetic.** An approved-merge registry folds one person's duplicate
  62. accounts together, and per-email tier overrides hold a directly-partnered account at its
  63. tier whatever each mailbox spent, and keep it out of cold outreach entirely.
  64. - **Identity-level exclusion.** Opt-outs and open deals are unioned across every census chunk
  65. that shares an email or a name, so a duplicate record can't route someone who asked not to
  66. be contacted.
  67. - **Contact means a send.** The audit counts only stage entries with a real email, call or DM
  68. behind them (`SEND_TOKENS`), keeps retired stages named so old sends still count, collapses
  69. same-minute workflow re-entries, and reuses cached histories for deals that cannot have
  70. changed.
  71. - **Human-gated writes.** The driver writes to the vault only. Every CRM change (a deal, a
  72. stage move) goes through a person.
  73. ## The drafting pipeline
  74. | Stage | Meaning |
  75. |---|---|
  76. | `01 - Drafted` | Written, not yet audited. |
  77. | `02 - Audit Result/audit-PASS` | Cleared the three-pass audit (confidence scored as a percentage). |
  78. | `02 - Audit Result/audit-FAIL` | Failed the audit; needs rework before it can move on. |
  79. | `03 - Unsent` | Audit passed and approved. Queued to send. |
  80. | `04 - Sent` | Sent. |
  81. | `05 - Archive` | Permanently withdrawn: opt-out, or otherwise taken out for good. |
  82. | `06 - Parked` | Temporary hold for a non-audit issue (vault or routing) pending review. |
  83. Drafts use the `matt-guerra-email` skill for voice and follow the rules in
  84. [Email-1-Drafting-Prompt](06-Resources/Email-1-Drafting-Prompt.md) and [Email-2-Drafting-Prompt](06-Resources/Email-2-Drafting-Prompt.md): no em dashes, none of the
  85. giveaway vocabulary, and no claim without a source.
  86. ## Replay the sample
  87. The replay is the regression check: rebuilt from nothing, the sample must come out the
  88. same. Run it on a scratch copy, because it rewrites the generated state:
  89. ```bash
  90. pip install -r 07-Automation/requirements.txt
  91. cp -R . /tmp/vault-replay && cd /tmp/vault-replay
  92. rm -rf 03-Clients/client-stubs 03-Clients/partner-client-master-list.xml \
  93. 05-Outputs/partner-runs 07-Automation/data/order_history.json \
  94. 07-Automation/data/outreach_touch_cache.json
  95. python3 07-Automation/sample/generate_sample.py
  96. python3 07-Automation/sample/run_sample.py
  97. diff -rq -x .git -x '*.xlsx' -x raw -x __pycache__ "$OLDPWD" .
  98. ```
  99. The `diff` should list only the ten stubs with hand-written research: they are examples
  100. added on top, and the replay does not regenerate them. The workbooks match cell for cell
  101. but not byte for byte, so they are left out of the `diff`. The replay also copies each day's
  102. Plinth pages into `05-Outputs/partner-runs/raw/`, which is not committed; the one committed
  103. copy is `07-Automation/sample/inputs/plinth/`.
  104. To browse, open the folder as a vault in [Obsidian](https://obsidian.md) and install the
  105. **Dataview** community plugin (enable JavaScript queries). See [SETUP](SETUP.md).
  106. ## Working here
  107. Two operators work this vault through separate Cowork projects synced over Obsidian: Matt
  108. and Hazel. Every change is logged in [LEDGER](LEDGER.md) with who made it, attributed by session
  109. email. Before you build on someone else's synced changes, skim the ledger to see what they
  110. touched.
  111. ## Reference
  112. [00-Index](00-Index.md) · [CLAUDE](CLAUDE.md) · [MEMORY](MEMORY.md) · [HEARTBEAT](HEARTBEAT.md) · [LEDGER](LEDGER.md) · [DECISIONS](DECISIONS.md) ·
  113. [CHANGELOG](CHANGELOG.md) · [SETUP](SETUP.md) · [MODEL_GUIDE](MODEL_GUIDE.md) · [SKILLS_REFERENCE](SKILLS_REFERENCE.md) · [CLAUDE-clients](03-Clients/CLAUDE-clients.md) ·
  114. [Source-Documents](Source-Documents.md)