Project Path — nothing built yet

Snapshot Fulfillment — Build Path

The route from sale to a personalized, revealed Commercial Electrical Contractors system. Five phases: confirm the foundation, build the product once, prove the thinnest end-to-end path, fill in the rest, then keep it running.

Vertical Commercial Electrical Contractors Source FULFILLMENT-AUTOMATION-MAP.md Status architecture settled · build not started
Executed by API MCP Snapshot Our App Python/JS Human Playwright QA Playwright Priority: Python/JS → API → MCP → Snapshot → Playwright → Human.
The two Playwright tags are not the same risk. Playwright QA only observes — it reads screens, screenshots, and reports. It cannot damage anything. Runs against throwaway locations. Playwright constructs — it builds and mutates real assets through the UI. A bad selector here corrupts an account.
Every constructive Playwright script lives in the Factory (F04, F06, F07) — slow, supervised, run a few times a year, never on a customer's clock. The one exception is A11, which is on the per-sale path — it exists only as a slot for structure-personalizable exceptions, and it should be empty. Every entry that lands in it is a design smell to be pushed back up into the Factory or down into a custom value.
Decided — design settled, not yet built To build Needs a sandbox test first
0

Foundation — decided, not yet verified live

one-time spikes

Every major architectural question has an answer. What's left is confirming each one against a real sandbox before Phase 1 leans on it.

Custom Values have full CRUD — the personalization keystone
Product hidden/revealed via a restricted User role, not sidebar tricks
SMS gated by one custom value (sms_activation_status), never a hard block
SaaS auto-provision yields the location + login + locationId
Snapshot pushes after onboarding, never at purchase
Snapshot installs once — it is never the upgrade mechanism
Snapshot push is API-native: PUT /locations/{id} with snapshot: {id, override}. Agency token, not location token
override: true overwrites a client's personalization. Forbidden in automation — always pass false, explicitly, and lint for it
Content vs. object-name boundary: tokens fill copy, APIs rename things
A2P is an onboarding task tracked in our app, not an API read
API rate limits are a non-issue for provisioning — a few hundred calls against 200k/day per location
The one real volume exposure is bulk contact imports — downstream, not fulfillment
AI agent is fully API-writable: instructions, personality, goal, knowledgeBaseIds[], channels[], mode
mode: off → auto-pilot is the agent's reveal switch; omitting SMS from channels[] is the A2P gate
Custom values interpolate in the agent's prompt fields — the agent ships generic in the snapshot and personalizes itself. Same keystone, one layer up
Knowledge Base container CRUD confirmed — create returns an id that feeds knowledgeBaseIds[]. Max 15 KBs per location
KB taxonomy lives in the industry snapshot — containers are personalized, then created in the location. Never improvised per sale
KB content is fully API-covered — FAQs, rich text, files. No Playwright anywhere in the system
The KB is built from onboarding intake, not a crawl. Onboarding is the knowledge-capture step — every fact is one the client confirmed
Sandbox tokens are tighter than production (25 req/10s vs 100). Build discipline: log every 429, honor Retry-After, don't poll
The LocationCreate webhook carries the new locationId. Agency-level app required — or the signal never arrives
Reconciliation fallback via /saas/locations by Stripe ID. Webhooks get delayed and dropped — build both paths
SaaS plans are read-only via API — build them in the Configurator UI first
Never match a purchase to a location by email alone. A wrong locationId writes one customer's data into another's account
Still to verify — one live test purchase
Does LocationCreate fire reliably — and which verification route actually works?
The signal is known. What's unproven is whether it fires every time in our configuration, and how fast. GHL's own docs disagree on the SaaS subscription-verification route (one is deprecated) — confirm it live, don't hardcode from docs
Token interpolation — field by field, not in general
Custom values are documented in bot goals and action prompts. Likely but unverified in personality, instructions, opening and follow-up messages. Do not assume in knowledge-base content or action parameters. One field resolving does not mean they all do — check each one that matters
The failure path — when the sub-account is never created
SaaS provisioning can fail outright (a known cause: incomplete payment config), and it may do so with no error event at all — Stripe charges, no location appears, silence. That's an assumption, not a documented guarantee — test it. Break the payment config on purpose and record exactly what we receive. The answer decides whether the escalation ladder is a safety net or the only thing there is
1

Product Factory

runs once per release · W-F

Build the Commercial Electrical vertical, once, and get a versioned snapshot out the door. Everything authored token-first — retrofitting tokens later means a rebuild.

F01
Vertical pack authoring
Lexicon, terminology, pipeline labels, calendar questions, compliance notes, the KB taxonomy, and the token-first AI agent template
Python/JS
F02
Core manifest compile
Universal fields, tags, pipelines, workflows, QA rules
Python/JS
F03
Token dictionary generation
Scan every asset, extract every token — becomes the contract for Plane 2
Python/JS
F04
Build-location reset
Wipe/recreate the release-candidate location clean
APIPlaywright
F05
Apply API-supported assets
Custom fields, tags, pipelines, stages, calendars, products
API
F06
Apply UI-only assets
Funnel pages, form/survey schemas, workflow builder construction
Playwright
F07
Snapshot create/refresh
From the build location → vertical-01-vX.Y
SnapshotPlaywright
F08
Release test
Push to a throwaway location, run the full verify suite against it
APIMCP
F09
Promote + version + release notes
Tagged release
Python/JS
F10
Snapshot mutation matrix
Insurance, not a dependency — what a push preserves vs. overwrites, for the day a core revision is ever needed
APIPlaywright QA
A

App Shell — Growth System

parallel track · on the critical path for every customer

Not greenfield — an existing Node.js app on AWS, already wired to intake, provisioned server-side from the payment payload. This is an embed + entitlement adaptation, but Onboarding lives inside it, so it has to be ready before Phase 2 can run end to end.

APP
HighLevel Custom Page embed
Allow iframe embedding; set frame-ancestors for HighLevel domains
Our App
APP
Entitlements store
Drives which submenu items and modules a given customer sees
Our App
APP
Onboarding intake UI
Renders inside the app, feeds the compile layer (W-O01)
Our App
APP
Bump & Priority Launch delivery surfaces
Personalized Lead Gen Strategy; 3-appointment booking form — both entitlement-gated, both post-intake
Our App
2

The Spine

thinnest possible end-to-end path

One vertical, one test client, zero exceptions: a purchase produces a provisioned, locked, intaken, compiled, personalized, verified, revealed location. Everything else in Phase 3 is elaboration on this.

Provision
P00
Correlation record
Written before checkout: provisioning ID, order, Stripe customer/subscription, plan. Everything else resolves against this
Python/JS
P01
Purchase event capture
Webhook → attach to correlation record, resolve entitlements
API
P02
locationId resolution
Primary: the LocationCreate webhook. Fallback: reconcile via /saas/locations by Stripe ID. Correlate, verify the subscription, bind. Staged escalation — 10 min internal alert, 20–30 min manual ticket. The customer is never told it "failed"
API
P03
Token exchange
Agency token → location-scoped token. Plane 2 can now write
API
P04
Restricted user creation
Customer created as a User — Contacts/CRM + Growth System only
API
P05
Member access grant
Credentials / magic link
API
Onboard
O02
Intake capture
Also the knowledge-capture step — services, hours, scope, escalation rules. This is what the AI agent will know
Our App
O03
Intake normalize + validate
Python/JS
O05
Authorization task list
Fires A2P immediately — the longest pole, start it first
Python/JSHuman
O06
Build manifest generation
Python/JS
Compile — zero GHL writes
C01
Token resolution
Every token gets a value or compile fails — no silent blanks
Python/JS
C04
Knowledge base compile
Turn confirmed intake into KB content — services, hours, scope boundaries, escalation rules, FAQs. Intake only. No crawl
Python/JS
C06
Dry-run diff
Nothing is applied until this passes
Python/JS
Apply, verify, reveal
A00
Snapshot push
PUT /locations/{id} with snapshot: {id, override: false}. First write of the apply phase, post-onboarding. Agency token
SnapshotAPI
A01
Custom Values upsert
The keystone. Idempotent by construction
API
Q02
Token leak scan
No unresolved {{...}} anywhere — the single most valuable assertion in the system
API
R01
Product reveal
Expose the full module set via user permissions, and flip the AI agent off → auto-pilot
API
3

Full Apply + QA

fill in everything the spine skipped

Every remaining write and every remaining assertion. This is where real human minutes per activation get measured — the number that decides whether the business scales.

Apply — the rest
A02
Custom fields + tags
API
A03
Pipelines + stage labels
API
A04
Calendars
Names, questions, availability, buffers
API
A05
Media + brand assets
API
A06
AI agent configuration
Create at mode: off, attach actions, set follow-up. Omit SMS from channels until A2P clears
API
A07
Knowledge Base provisioning
Create KB containers → write intake-sourced FAQs/rich text/files → assign to agent → confirm indexed
API
A08
Chat widget config
Snapshot
A09
Trigger links + attribution/UTM
API
A10
Products/prices
Only if the client sells through GHL
API
A11
Structure-personalizable exceptions
Audit and eliminate ruthlessly — every entry here is expensive
Playwright
Verify — the rest
Q01
Asset inventory
APIMCP
Q03
Dependency graph
Every referenced field, tag, calendar, pipeline actually exists
APIMCP
Q04
Live smoke test
Test contact through form → workflow → calendar → opportunity
APIMCP
Q05
AI agent retrieval test
Ask questions only the client's KB can answer. A 201 on KB creation is not a pass — retrieval is the assertion
MCP
Q06
Authorization status
Which Bucket E items are outstanding
API
Q08
Test-data teardown
Never hand over a dirty account
API
Reveal — the rest
R02
Entitlement unlock
LMS, KB, Demand Gen, Demand Gen AI Agent — our app, not GHL automation
Our App
R03
Delivery notification
Includes the channel-readiness panel
API
R05
Bump delivery
Personalized Lead Gen Strategy, entitlement-gated
Our App
R06
Priority Launch delivery
3-appointment booking form, paid in full — no deposit gate
Our AppAPI
4

Operate

runs continuously · W-X

Drift, entitlement upgrades, churn, and the two things that quietly decide whether this scales: chasing pending channels and watching the Priority Launch calendar against ad spend.

X01
Feature/entitlement upgrade
Reveal + apply only new assets — never a snapshot re-push
API
X02
Drift detection
Live location vs. expected manifest
APIMCP
X03
Churn / deprovision
DELETE /locations/{id}?deleteTwilioAccount=. Deleting the Twilio account is irreversible — they lose their phone number. An explicit decision, never a default
API
X04
Authorization chase
On A2P approval: flip sms_activation_status and add SMS to the agent's channels — one workflow releases both gates
API
X05
Failure triage
The human's only routine job
Python/JSHuman
X06
Audit log
Every write to every location, forever
Python/JS
X07
Priority Launch capacity monitor
10/month counter, plus an early warning on Abe's calendar before it forces ad spend down
API
X08
Knowledge update
Let the client revise their own facts — prices, services, hours — from the app; recompile the KB. Correct at launch; goes stale only as their business changes
API
Snapshot Fulfillment — Tier1 Marketing · visual companion to FULFILLMENT-AUTOMATION-MAP.md