Activation-Runbook.md
Language Markdown6.6 KB131 lines
---type: automation-runbookscope: 07-Automationtags: [claude, outreach, automation, runbook]created: 2026-07-23last_modified: 2026-07-23---# Activation Runbook: Weekly Partner Client PipelineThe definitive, in-order procedure to take the pipeline from built (2026-07-22) to live.Every command below was first validated 2026-07-23 against Ines's real roster workbook (notincluded in this repo), where the column mappings auto-detected with **zero** `--map`overrides. In this repo the seed is the sample roster,`07-Automation/sample/inputs/Partner-Clients-Roster_2026-09-07.xlsx` (totals through2026-09-07), which auto-detects the same way. The commands and sanity checks below use it.> The shipped vault is **already seeded and run**: `07-Automation/data/order_history.json`> exists, and the stubs, census and run outputs are the sample replay's. To rehearse this> runbook, start from an unseeded copy (see "The sample" in [[07-Automation/README|07-Automation README]]).Run commands from the **vault root**. Steps 2 and 6 are things you ask Claude to do;everything else is copy-paste.---## Step 0: Dependencies (once per machine)```bashuv venvuv pip install pyyaml openpyxl````uv venv` creates a `.venv` at the vault root; every `uv run` below uses it automatically (run all commands from the vault root). If you'd rather not keep a venv around, skip this step and carry the deps on each command instead, e.g. `uv run --with pyyaml --with openpyxl 07-Automation/weekly_partner_pipeline.py ...`.## Step 1: Seed the baseline (two passes, in this order)**Pass 1: the full customer base** (tab `All Accounts`: every Plinth customer withID/email/LTV/RR; 381 in the sample).This gives *every* Plinth customer a baseline, so future threshold-crossers (someone at$2,400 who orders next week) are detected against real history instead of appearingas unknowns:```bashuv run 07-Automation/weekly_partner_pipeline.py seed-baseline \--sheet "07-Automation/sample/inputs/Partner-Clients-Roster_2026-09-07.xlsx" \--tab "All Accounts" --as-of 2026-09-07```**Pass 2: the partner clients, richer data** (tab `Complete Partner Clients List`: 128clients in the sample, with order counts, dates, company, phone, tier). `--force` isrequired and correct here: it overwrites the thin All Accounts baselines with the richones for these 128; everyone else keeps their pass-1 baseline:```bashuv run 07-Automation/weekly_partner_pipeline.py seed-baseline \--sheet "07-Automation/sample/inputs/Partner-Clients-Roster_2026-09-07.xlsx" \--tab "Complete Partner Clients List" --as-of 2026-09-07 --force```Sanity: pass 1 should report `Seeded baselines for 381 customers`; pass 2 `for 128customers` (compare `05-Outputs/partner-runs/run-log_2026-09-07-seed.txt`). If a mappingever looks wrong, add `--dry-run` to inspect before writing.`--as-of 2026-09-07` is the sheet's cutoff (the "LTV up until Monday" Monday: it's inthe filename and the `Plinth LTV 09/07/26` column header). Orders dated on or before itnever re-count; the weekly delta starts after it.## Step 2: Catch-up pull (as_of → today): ask ClaudeSay: **"Run the catch-up pull per the Activation Runbook."** Claude will, for eachsingle day D from the `as_of` date (2026-09-07) through today:1. `orders.fetch since=D until=D limit=100` (dates as `yyyymmdd`; no status filter,statuses are handled at compute time),2. save the raw page under `05-Outputs/partner-runs/raw/catchup/`,3. `ingest --orders <page>`,4. if the INGEST line shows `added > 0` or the page hit ~50+ rows, pull the same dayagain with a higher `offset` and re-ingest, **until a page reports `added=0`**.Including the `as_of` day itself is deliberate: boundary orders are stored but neverdouble-counted (the compute only adds orders dated *after* `as_of`).## Step 3: Arm itIn [[partner-thresholds]], set the last `TBD`:```min_orders_to_qualify: 1````1` is the recommendation: the program is LTV-based and Ines's rule is "once in theprogram, always in the program": a single $5K trade-show order counts. Your call.## Step 4: First classify + verify + reconcile```uv run 07-Automation/weekly_partner_pipeline.py classifyuv run 07-Automation/weekly_partner_pipeline.py verify```Open `05-Outputs/partner-runs/partner-classification_<today>.xlsx` and check:- **A long-history client adds up.** Pick the partner client with the most orders andconfirm `ltv` = their roster baseline + their counted post-`as_of` orders, nothingmore. In the sample, [[Amara Fenwick]] (Plinth 40114, 53 orders at the seed) reads$112,973.40 on the 2026-09-14 run and $114,720.45 once 2026-09-17 is ingested (twocounted orders that day). If a long-history client ever reads *below* their baseline,something re-introduced a one-shot API pull: stop.- **Tier mismatches:** `store_user_group` vs `assigned_tier`. Expect some. In the sample,[[Lucia Pemberton]] is "Palladium Partner" in Plinth but $10,489.98 LTV is the Platinumband by the math. These go on the Ines/Nora review list, not auto-fixed.- `verify` must print OK. Exit 2 on the *first* run means a seeding problem: stop.- Counting basis is already matched to the roster workbook (grand total with shipping,cancelled 27 + refunded 28 excluded; see [[partner-thresholds]]). If Nora's leadershipcall changes the rules, update `amount_field` / `excluded_order_statuses` and log it inDECISIONS.## Step 5: First manual downstream pass (review between each)```uv run 07-Automation/weekly_partner_pipeline.py write-stubs \--plan 05-Outputs/partner-runs/partner-classification_<today>.plan.jsonuv run 07-Automation/weekly_partner_pipeline.py refresh-xml \--plan 05-Outputs/partner-runs/partner-classification_<today>.plan.json```Then the skills, on the new/changed cohort: `client-enrich` (Apollo credits: itquotes cost first), then `partner-pipeline-push` (Bitrix, always human-gated).Each vault-changing stage = one [[LEDGER]] entry.## Step 6: Enable the schedule: ask ClaudeSay: **"Enable the weekly partner client pipeline."** Claude creates the scheduledtask from [[scheduled-task]] (Mondays 06:00 America/Chicago, `autonomy:spreadsheet_only`: it pulls, ingests, classifies, verifies, exports, notifies you,and touches nothing downstream). Autonomy was widened to `through_vault` the same day.---## After it's live- Monday summaries report tier counts + verify status. **Exit 2 (no-shrink flag) meansstop and look**: data went missing; never demote or route to Winback off that run.- `has_baseline=False` rows are customers newer than the seed: normal for genuinelynew buyers (the sample's 2026-09-21 run has one).- The one spreadsheet Ines ever needs to build by hand again: none. That was the point.