README.md
Language Markdown8.4 KB137 lines
# Meridian Outreach VaultThe Obsidian vault and Claude Cowork project behind a print and display shop's quarterlyclient outreach. One linked note per partner client, a machine-readable census over all ofthem, a weekly pipeline that keeps both current from the order system, and a draftingpipeline that turns research into audited emails a person approves before anything is sent.**The company is fictional, and so is every client.** This vault was built for, and runevery week at, a real print and display shop. Here it serves **Meridian Display Co.**, theinvented company behind [meridian-ops-board](https://github.com/mattrguerra/meridian-ops-board),[meridian-crm-mcp](https://github.com/mattrguerra/meridian-crm-mcp),[meridian-orders-mcp](https://github.com/mattrguerra/meridian-orders-mcp) and[meridian-skills](https://github.com/mattrguerra/meridian-skills). The notes, rules, code andhistory are the real ones with the business taken out: staff, clients, programs, products,links and numbers are invented. The one real person is Matt Guerra, who built and ran it.**The client book is a generated sample.** No real client record survived the move. In itsplace, `07-Automation/sample/generate_sample.py` invents 381 order-system accounts,two weeks of orders and two weeks of CRM deals, and `run_sample.py` replays two Monday runsof the real weekly driver against them. Every stub in `03-Clients/`, the census, both weeklyworkbooks and the outreach audit are that driver's own output. On top of that, ten stubs carryhand-written research and eleven sample drafts sit in the email pipeline, all invented. The history notes([LEDGER](LEDGER.md), [DECISIONS](DECISIONS.md), [CHANGELOG](CHANGELOG.md)) describe the system as it ran on the real book,at real scale, with invented numbers.For live numbers, start at [00-Index](00-Index.md). For how Claude works here, see [CLAUDE](CLAUDE.md).## What it does- **Keeps a census of the Partner Program.** Every client whose lifetime spend puts them ina tier (Palladium, Platinum, Iridium, Rhodium) has a stub in `03-Clients/client-stubs/`and a chunk in `03-Clients/partner-client-master-list.xml`, carrying their order-system id,CRM contact id and every outreach funnel they sit in.- **Runs itself weekly.** The [Weekly Partner Client Pipeline](07-Automation/Weekly-Partner-Pipeline-SOP.md)pulls the week's orders from Plinth (the order system), recomputes lifetime value,classifies, refuses to continue if any total shrank, writes and upgrades stubs, refreshesthe census and the roster workbook, reconciles the CRM's deals, proposes who to contactnext, and audits who was actually contacted and when.- **Drafts outreach with a human in the loop.** Emails are drafted in Matt's voice from thestub's sourced research, scored for confidence, audited in three passes (facts, voice,template), and moved stage by stage through `05-Outputs/First Email/` and`05-Outputs/Second Email/`. Nothing is sent, and no CRM record is written, without a person.## Vault map| Folder | What's in it ||---|---|| `01-Tiers/` | Partner tier notes (Palladium / Platinum / Iridium / Rhodium, and Retail) with Dataview rollups of their members. || `02-Outreach/` | Outreach play notes, the approved email templates, call scripts. || `03-Clients/` | `client-stubs/` (one note per client, flat), the XML census, and the folder rules ([CLAUDE-clients](03-Clients/CLAUDE-clients.md)). || `04-Working/` | In-progress review notes. || `05-Outputs/` | The two email pipelines, each weekly run's artifacts (`partner-runs/`), and the outreach audit workbooks. || `06-Resources/` | The drafting prompts. || `07-Automation/` | The weekly driver, its config, SOP, routing rules, runbook, schedule, local data, and the sample generator. || `08-Planning/` | **Human-only** planning space. Claude reads it, never writes to it. |## The weekly pipeline`07-Automation/weekly_partner_pipeline.py` is the entry point of one deterministic program(Python, pyyaml, openpyxl; the code is the `07-Automation/partner_pipeline/` package, onemodule per stage) that never calls an API itself: the scheduled Claude session makes thePlinth and Bitrix calls through their MCP servers and hands the raw responses to it. Thedesign decisions worth reading:- **Incremental by necessity.** Plinth's `orders.fetch` silently truncates large result sets(about 70 orders a response, no "has more" flag) and its offsets overlap. So lifetime valueis never asked of the API: it comes from a local, append-only order history seeded oncefrom the roster workbook, and each week's pull is paged day by day until a page addsnothing new. See [DECISIONS](DECISIONS.md), 2026-07-22.- **The no-shrink guardrail.** Lifetime totals can only grow. If one shrinks, `verify` exits 2and the run stops before anything is written: missing data must never demote a client.- **Relationship over arithmetic.** An approved-merge registry folds one person's duplicateaccounts together, and per-email tier overrides hold a directly-partnered account at itstier whatever each mailbox spent, and keep it out of cold outreach entirely.- **Identity-level exclusion.** Opt-outs and open deals are unioned across every census chunkthat shares an email or a name, so a duplicate record can't route someone who asked not tobe contacted.- **Contact means a send.** The audit counts only stage entries with a real email, call or DMbehind them (`SEND_TOKENS`), keeps retired stages named so old sends still count, collapsessame-minute workflow re-entries, and reuses cached histories for deals that cannot havechanged.- **Human-gated writes.** The driver writes to the vault only. Every CRM change (a deal, astage move) goes through a person.## The drafting pipeline| Stage | Meaning ||---|---|| `01 - Drafted` | Written, not yet audited. || `02 - Audit Result/audit-PASS` | Cleared the three-pass audit (confidence scored as a percentage). || `02 - Audit Result/audit-FAIL` | Failed the audit; needs rework before it can move on. || `03 - Unsent` | Audit passed and approved. Queued to send. || `04 - Sent` | Sent. || `05 - Archive` | Permanently withdrawn: opt-out, or otherwise taken out for good. || `06 - Parked` | Temporary hold for a non-audit issue (vault or routing) pending review. |Drafts use the `matt-guerra-email` skill for voice and follow the rules in[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 thegiveaway vocabulary, and no claim without a source.## Replay the sampleThe replay is the regression check: rebuilt from nothing, the sample must come out thesame. Run it on a scratch copy, because it rewrites the generated state:```bashpip install -r 07-Automation/requirements.txtcp -R . /tmp/vault-replay && cd /tmp/vault-replayrm -rf 03-Clients/client-stubs 03-Clients/partner-client-master-list.xml \05-Outputs/partner-runs 07-Automation/data/order_history.json \07-Automation/data/outreach_touch_cache.jsonpython3 07-Automation/sample/generate_sample.pypython3 07-Automation/sample/run_sample.pydiff -rq -x .git -x '*.xlsx' -x raw -x __pycache__ "$OLDPWD" .```The `diff` should list only the ten stubs with hand-written research: they are examplesadded on top, and the replay does not regenerate them. The workbooks match cell for cellbut not byte for byte, so they are left out of the `diff`. The replay also copies each day'sPlinth pages into `05-Outputs/partner-runs/raw/`, which is not committed; the one committedcopy is `07-Automation/sample/inputs/plinth/`.To browse, open the folder as a vault in [Obsidian](https://obsidian.md) and install the**Dataview** community plugin (enable JavaScript queries). See [SETUP](SETUP.md).## Working hereTwo operators work this vault through separate Cowork projects synced over Obsidian: Mattand Hazel. Every change is logged in [LEDGER](LEDGER.md) with who made it, attributed by sessionemail. Before you build on someone else's synced changes, skim the ledger to see what theytouched.## Reference[00-Index](00-Index.md) · [CLAUDE](CLAUDE.md) · [MEMORY](MEMORY.md) · [HEARTBEAT](HEARTBEAT.md) · [LEDGER](LEDGER.md) · [DECISIONS](DECISIONS.md) ·[CHANGELOG](CHANGELOG.md) · [SETUP](SETUP.md) · [MODEL_GUIDE](MODEL_GUIDE.md) · [SKILLS_REFERENCE](SKILLS_REFERENCE.md) · [CLAUDE-clients](03-Clients/CLAUDE-clients.md) ·[Source-Documents](Source-Documents.md)