How to drop new practice files so they get built and deployed automatically
The automation runs every weekday at 09:00 Mountain. It dispatches by file extension: raw CSVs go to Phase 1 (prospect-list scan for Amy → PRD review); PRD-approved xlsx files go to Phase 2 (build the HTML engine + deploy to sga-growth.dev/growth-engine/).
What the automation does — and what it needs from you
One scheduled run every weekday morning:
- Weekdays 09:00 (Mountain) — the sweep pulls new files from both Drive folders (Input + Output) and dispatches by what it finds in each file:
.csvin the Input folder without aKeep? (Y/N)column → Phase 1. Amy runs a prospect scan and drops the resulting Excel back for PRD review..csvin the Input folder with aKeep? (Y/N)column → approved-CSV bridge. The sweep enriches the Keep=Y rows via Google Places (address, phone, website, drive-time), converts them into a Phase 2-shaped xlsx, and builds the engine in the same run..xlsxin the Input folder → Phase 2. Automation reads the approved xlsx directly, builds the HTML engine, and publishes tosga-growth.dev/growth-engine/.
Three things the automation needs to do its job:
- The file in the correct drop folder (Input folder for both raw scans and PRD-approved lists)
- The filename starts with the practice's Paylocity code
- The matching referrer roster CSV (any file in the same folder starting with the same Paylocity code that doesn't have
_approved_in the name) is present so the engine can populate the Referrers tab
Keep? (Y/N) and treats it as PRD-approved. It enriches the Y-rows via Google Places, writes a per-practice xlsx under docs/specialty/referring-docs/referring-doc-output/<slug>_prospect-list_approved_YYYY-MM-DD.xlsx, then runs build_engine.py against it — all in one sweep. Column I Keep? (Y/N) = Y is the ingest signal. Toggle off with SGA_REFERRAL_SWEEP_SKIP_APPROVED=1 or force skeletal (no Places $) with SGA_REFERRAL_SWEEP_SKIP_ENRICH=1.
1 · The Drive drop zone
One folder for everything
Referral Growth Engine · Google Drive
Every CSV — for a prospect-list build, an engine-only build, or a PRD-approved rebuild — goes in this folder. Drop files any day of the week; the automation checks them at the next scheduled run (Monday for untagged, Friday for tagged).
2 · Filename convention
Paylocity code + practice name + tag before .csv
The automation reads the leading token in the filename to look up the practice in Scott's master crosswalk. It reads the tag before .csv to decide which lane the file is in.
JAXDSPFLPP_Jacksonville_Dental_Specialists_Provider_List.csvALPTTAGAPP_Alpharetta_Perio_Provider_List_engine-only.csvBEACHESLGA_Beaches_Perio_Provider_List_approved.csvJacksonville Dental Specialists Provider List.csvalpharetta_perio_referrers.csvJAX_Dental_Specialists.csvAAS-SC). If you can't find one, ping Amy before dropping the file.
3 · The three lanes
The tag before .csv tells the automation what you want
Three lanes. Pick one when you drop the file — you can always retag later.
_Provider_List.csv_approved and Friday builds the full engine.
_Provider_List_engine-only.csv<slug>_prospect-list_approved_YYYY-MM-DD.xlsx- Sheet 1 · Prospects — every candidate row with full data (name, address, phone, website, tier, drive-time to home location, strategy note).
- Sheet 3 · PRD QA Checklist — one row per prospect with
name,Keep?(Y/N),Override tier,PRD notes. Only rows where Keep? = Y are ingested into the engine's Prospects tab. Column I of Jayme's roster CSVs (Keep? (Y/N)) is the authoritative approval signal; Y or Yes = build into the engine.
AAS-SC Aiken Oral Surgery + AAG-GA Augusta Oral Surgery), you have two options: (a) split the approved prospect list by whichever office each prospect is closer to (drive-time) and produce two xlsx files — one keyed on each Paylocity code — the single-location build_engine.py then produces two engines under sga-growth.dev/growth-engine/<slug>_referral_growth_engine.html; or (b) if one PRD manages both offices as one territory, consolidate into a single master engine with both locations declared. Reference build (option b): aiken-augusta oral & facial surgery — master, built 2026-08-07 from Jayme's AAS-SC_aiken-augusta-prospect-list_approved_2026-07-24.csv + AIKEN_aikenaugusta_PartnerProviders_2026-07-16.csv.
4 · CSV column format
Two supported schemas — the automation auto-detects
The automation reads the CSV header row and picks the matching parser. Both schemas produce the same engine output; the differences are what data each carries and how tiering is derived.
Preferred · Referral-Lab Export
What Jayme's most recent Jacksonville drop uses. Doctor-level rows with rank and specialty; the automation groups rows by practice address, picks the top-ranked doctor as the card lead, and lists other doctors in the notes.
Legacy · Office Manager Roster
The original format from Q2. Practice-level rows with office manager contact info. Still supported for older data pulls; tiering is driven by a suffix on the Practice column (see section 5).
Referral-Lab Export columns
| Column header | Notes |
|---|---|
| Overall_Rank | Integer rank (1 = top referrer). Drives tier — see section 5. |
| First_Name | Doctor first name |
| Last_Name | Doctor last name |
| Nickname | Optional |
| IsInternal | True / False. True → Green Internal tier. |
| AffiliatedPartner | Optional |
| Specialty | General Dentist, Endodontist, Oral Surgeon, Orthodontist, Pediatric Dentist, etc. |
| Mobile_Phone | Doctor mobile (optional) |
| Email_Address | Doctor email (optional) |
| Practice | Practice / office name |
| Address, Address2, City, State, Zipcode | Practice address (used to dedupe doctors at same office) |
| Phone_Number, Fax_Number | Practice main lines |
| Study_Club_Name, Birthday_Date, Graduated_Year | Optional — surfaced in notes when present |
| Last_Note, Next_Task, Last_Referral | Optional — surfaced on the card |
Legacy Office-Manager columns
| Column header | Notes |
|---|---|
| Practice | Practice name. Suffix rules drive tier — see section 5. |
| Address, Address2, City, State, Zipcode | Practice address |
| Phone_Number, Fax_Number, Email_Address | Practice contact |
| Office_Manager_First_Name, _Last_Name, _Email_Address | Office manager contact |
| Hours_of_Operation | Free-text (optional) |
Overall_Rank column and separate First_Name / Last_Name for the doctor, it's the Referral-Lab Export (preferred). If it has Office_Manager_First_Name and no rank column, it's the legacy Office-Manager Roster. Both work.
5 · How tiering works
Green / Yellow / NeedsReview — driven by whichever schema you dropped
Referral-Lab Export → Rank drives tier
Legacy Office-Manager → Suffix on Practice column drives tier
-INTERNAL REFERRALS (no space after dash) and - New Ref Outreach (space after dash) are what the parser looks for. Anything else falls into the "no suffix" bucket.
6 · What the automation does
Every weekday 09:00 (Mountain) — one sweep, two phases
The daily sweep (tools/referral-engine/run_daily_sweep.sh, LaunchAgent com.sga.referral-engine-daily-sweep) runs one dispatch loop over all new files:
Phase 1 · .csv in Input folder
- For each untagged raw CSV it hasn't seen, the sweep queues that practice for a Phase 1 prospect scan.
- Amy gets a ticket in sga3p listing every practice waiting for Phase 1, plus the run-log path.
- Amy runs Phase 1 for each, delivers the resulting Excel to the assigned PRD, and rolls approvals back into the Input folder as an
.xlsx(with the two required sheets — see section 3).
Phase 2 · .xlsx in Input folder
- For each PRD-approved xlsx, the sweep looks up the practice in Scott's crosswalk by the leading Paylocity code.
- Inspects the xlsx: reads the
Prospectssheet, countsKeep? = Yrows on thePRD QA Checklist, checks for multi-locationdriveMin_*columns. - Builds the HTML engine — referring-doctor tab from the referrer CSV, Prospects tab from the Keep=Y subset with tier overrides applied.
- Auto-bumps version (v1, v2, v3…) so previous builds stay reachable at dated URLs.
- Publishes to
sga-growth.dev/growth-engine/<slug>_referral_growth_engine.htmlvia a singlewrangler pages deployat the end of the sweep. - Posts a summary ticket to sga3p listing every build, waiting file, and skip.
Published dashboards live at sga-growth.dev/growth-engine/ (SGA SSO required).
driveMin_<LocationName> column, the sweep pauses that file and tickets Amy for a manual split into per-office xlsx files (one per Paylocity code). See the multi-location callout in section 3.
7 · When a file gets skipped
Reasons a file can get skipped or wait
- No Paylocity code prefix. The filename doesn't start with uppercase letters +
_. → Rename and re-drop. - Paylocity code not in the crosswalk. Typo, or Scott hasn't added the practice yet. Common trap: composite/fake codes like
AIKENAUGSCDDfor a two-office network — use the real per-office codes (AAS-SC,AAG-GA). → Fix the code or add to crosswalk; next run picks it up. - Missing or corrupt CSV/xlsx data. Practice column empty on every row, unparseable file, xlsx missing the
ProspectsorPRD QA Checklistsheet. → Reissue the export. - Approved CSV with no matching referrer roster. The bridge finds the approved CSV (Keep column present) and builds the xlsx, but Phase 2 can't locate a companion referrer roster (any
<code>_*.csvwithout_approved_in the name). → Drop the referrer roster CSV in the same folder with the matching Paylocity code prefix. - Multi-location xlsx (two or more
driveMin_*columns). The sweep blocks and tickets Amy to split into per-office xlsx files. → Wait for Amy's manual split. - Untagged CSV (waiting). Not an error — the file is queued for Phase 1. Nothing to fix on your end unless you meant engine-only or already-approved (see section 3).
Skips and waits get logged to the daily sweep summary at data/output/referral-engine-daily-sweep-YYYY-MM-DD.md and a ticket lands in sga3p. Fix the underlying issue and the file processes on the next weekday run — no need to re-drop it.
Questions?
Email Amy McNeill. Drops made any weekday get picked up at the next 09:00 (Mountain) sweep. If it's urgent and needs to go out the same day, drop by 08:30 Mountain.