# Intake Question Set — v1.2 (hand-off to ghl-command-mcp)

STATUS: FINAL for v1.2, 2026-08-26 (question-set version `0.2`). Owner: atlas (wording/labels) → ghl-command-mcp (builds the form-template installer from this). Jerry approves the final set. **v1.1 added 3 keys** (`team_size`, `monthly_lead_volume`, `business_hours`) per Jerry's 2026-06-15 ruling. **v1.2 adds 7 keys in three new sections** — G "Your team", H "Calendars and phone", I "Your voice" — after the owner inspected a real build (2026-08-26): *"Our intake is not sufficient and missing pieces that prevent a good build. The better we do upfront, the less we have to go in and modify later."* See "Tier 1 v2 additions" at the bottom.

This is the canonical list of questions the installed intake form asks. It is the **built-in fallback brief source** (schema §2A path B) — the path taken when no partner OS (Agency OS) is detected or the subscriber declines it. It is the FLOOR: the form is installed regardless, because it is the only path when no partner OS is present.

**Contract rule honored:** the 25 original `key`s below are unchanged from schema §3 (changing a key is a contract change). Only wording/labels/options/help text are finalized here. **3 keys were ADDED** (`team_size`, `monthly_lead_volume`, `business_hours`) per Jerry's 2026-06-15 ruling and **7 more on 2026-08-26** (`staff_members`, `notify_name`, `calls_name`, `booking_calendars`, `has_phone_number`, `brand_voice`, `signature_line`) — coordinated contract changes: command-center folds them into schema §3 + §6, ghl-command-mcp adds them to the installer. Every earlier key and label is unchanged, so a form installed from v1.1 still maps; only the new answers are missing from it.

**Form display order** (sections are contiguous so each gets one header): Contact → A Business basics → **G Your team** → B Offer → C Audience → D Goal → **H Calendars and phone** → E Channels → F Assets → **I Your voice**.

Each question maps 1:1 to a Brief field (schema §4) via its `key`. The mapping column is authoritative for the normalizer.

---

## How the installer should read this

- The form is **account-agnostic**: installed into whatever `get_current_location` returns, zero hardcoded IDs.
- The form needs the **standard GHL contact fields** too (first name, last name, email, phone) — these carry the submitter/contact identity and are not business-profile `key`s. They are not in the table below; add them as the form's standard contact block. The business-profile answers below populate the Brief.
- `required: true` questions are the minimum to generate a usable plan. Everything else is optional; the skill omits unknowns (never emits `null`) and notes safe defaults.
- Field types use GHL form field types. Where a question offers fixed choices, the options are listed verbatim; the installer should use these exact option labels (the normalizer matches on them).
- Sections A–F are display groupings (use as form sections/page breaks); they are not part of the contract.

---

## Section A — Business basics

| # | Label (client sees) | `key` | Type | Required | Options / help |
|---|---|---|---|---|---|
| A1 | Business name | `business_name` | text | yes | Your business or brand name, as you want it to appear. |
| A2 | What kind of business is this? | `business_type` | dropdown | yes | Options: `Med spa`, `Clinic / practice`, `Coach / consultant`, `Ecommerce`, `Local service`, `Agency`, `Other`. *(Drives preset selection.)* |
| A3 | Website | `website` | url | no | If you have one. Leave blank if not. |
| A4 | Primary location | `primary_location` | text | no | City, State/Country. Used for tone + scheduling. |
| A5 | Time zone | `timezone` | dropdown | yes | Standard IANA time-zone list (e.g. `America/Phoenix`). Drives appointment hours and send windows. |
| A6 | How many people work your leads? | `team_size` | dropdown | no | Options: `Just me`, `2-5`, `6+`. Sizes how much human follow-up vs automation we build (and opportunity assignment / round-robin). |
| A7 | Roughly how many new leads per month? | `monthly_lead_volume` | dropdown | no | Options: `Under 100`, `100-500`, `500-1000`, `1000+`. Sizes SMS phone numbers (~1 per 500/mo) and send volume. Leave blank if unsure. |
| A8 | Your business hours | `business_hours` | textarea | no | e.g. "Mon-Fri 9-6, Sat 10-2". Sets your calendar's default booking hours. Leave blank for Mon-Fri 9-5. |

## Section G — Your team *(v1.2)*

| # | Label (client sees) | `key` | Type | Required | Options / help |
|---|---|---|---|---|---|
| G1 | Staff members to set up (one per line: Name, email, role, mobile) | `staff_members` | textarea | no | Placeholder shows the exact line format: `Jane Smith, jane@yourclinic.com, Front desk, 555-123-4567`. Every person becomes a plan `users[]` entry; every notification / task / calendar points at one. Empty → the build still ships, with those steps marked *waiting for a staff member*. |
| G2 | Who should be notified about new leads? | `notify_name` | text | no | A name from the list above, or "the owner". |
| G3 | Who takes booking calls / follow-up calls? | `calls_name` | text | no | A name from the list above, or "the owner". |

## Section B — Offer and pricing

| # | Label | `key` | Type | Required | Options / help |
|---|---|---|---|---|---|
| B1 | What do you sell? | `core_offer` | textarea | yes | One or two sentences. The main thing a customer buys from you. |
| B2 | Your main offers and prices | `price_points` | textarea | no | List your key offers with prices, one per line (e.g. "New client consult — $19"). |
| B3 | Free offer / lead magnet | `lead_magnet` | text | no | A free thing you give to capture a lead (assessment, guide, trial). Leave blank if none. |
| B4 | Average sale value | `avg_deal_value` | text | no | Roughly what a new customer is worth on the first purchase. |

## Section C — Audience

| # | Label | `key` | Type | Required | Options / help |
|---|---|---|---|---|---|
| C1 | Who is your ideal customer? | `ideal_customer` | textarea | yes | Who you serve best. Be specific (age, situation, what they want). |
| C2 | What problems do they come to you with? | `top_pain_points` | textarea | no | The top pains/frustrations that bring them in. One per line is fine. |
| C3 | Why do prospects hesitate? | `objections` | textarea | no | The objections you hear most (price, trust, timing, fear). |

## Section D — Goal and sales process

| # | Label | `key` | Type | Required | Options / help |
|---|---|---|---|---|---|
| D1 | What should this account do first and best? | `primary_goal` | dropdown | yes | Options: `Book appointments`, `Capture + nurture leads`, `Direct sales`, `Re-engage past clients`, `Other`. *(Drives the workflow + pipeline spine.)* |
| D2 | The steps a lead moves through, from new to won | `sales_stages` | textarea | no | Name the stages in order (e.g. "new lead → contacted → consult booked → showed → sold → repeat"). If blank, we use a sensible default for your business type. *(Drives pipeline stages.)* |
| D3 | Do customers book appointments with you? | `booking_needed` | radio (yes/no) | yes | Yes if you take consults/appointments. *(Drives whether a calendar is built.)* |
| D4 | Follow-up style | `follow_up_style` | dropdown | no | Options: `High-touch / multi-step`, `Light`, `Single confirmation`. How aggressively to follow up. |

## Section H — Calendars and phone *(v1.2)*

| # | Label (client sees) | `key` | Type | Required | Options / help |
|---|---|---|---|---|---|
| H1 | How many booking calendars do you need, and what is each one for? | `booking_calendars` | textarea | no | Placeholder shows the format: `Calendar name, type: one-on-one / round-robin / class, who is on it, how long` — e.g. `New Patient Consult, round-robin, Jane Smith + Dr. Mark Lee, 45 minutes`. One line per calendar. *(Drives how many calendars are built, who is on each, and the slot length — "15 minutes" becomes `slotDuration: 15`; without it GoHighLevel builds 30-minute slots.)* |
| H2 | Do you already have a phone number in GoHighLevel? | `has_phone_number` | dropdown | no | Options: `Yes`, `No`, `Not sure`. (No "email" in any dropdown label — browser autofill, see E1.) *(With SMS wanted, No / Not sure flags `phone_number_needed`.)* |

## Section E — Channels and tech

| # | Label | `key` | Type | Required | Options / help |
|---|---|---|---|---|---|
| E1 | Is your sending domain set up? | `email_ready` | radio (yes/no) | no | Yes if you have a sending domain / mailbox connected in GHL. (Label carries no "email" on purpose: browsers autofill saved addresses into it otherwise.) |
| E2 | Do you want to send text messages (SMS)? | `sms_desired` | radio (yes/no) | no | Yes flags the A2P registration step you'll need to complete. |
| E3 | A2P / SMS registration status | `a2p_status` | dropdown | no | Options: `Not started`, `In progress`, `Approved`, `Not needed`. |
| E4 | Payment processing | `payment_processor` | dropdown | no | Options: `Stripe connected`, `Stripe not connected`, `Other`, `None`. *(Flags the Stripe handoff if you sell on a page.)* |
| E5 | Is your calendar connected? | `calendar_connected` | radio (yes/no) | no | Yes if your Google/Outlook calendar is already authorized in GHL. *(Flags the OAuth handoff if booking is needed and this is no.)* |
| E6 | Which channels do you post on? | `social_channels` | multiselect | no | Options: `Instagram`, `Facebook`, `TikTok`, `YouTube`, `LinkedIn`, `Google Business`, `None`. |

## Section F — Assets on hand

| # | Label | `key` | Type | Required | Options / help |
|---|---|---|---|---|---|
| F1 | Do you already have a pipeline built? | `existing_pipeline` | radio (yes/no) + textarea | no | If yes, describe it briefly so we don't duplicate it. |
| F2 | Anything already built we should not touch? | `existing_workflows` | textarea | no | List workflows/automations already live that we must leave alone. *(Becomes the do-not-clobber guardrail for the executor.)* |
| F3 | Brand assets | `brand_assets` | text | no | Logo, colors, domain available — whatever you have. |
| F4 | Anything else we should know? | `anything_else` | textarea | no | Constraints, compliance limits, preferences, context. |

## Section I — Your voice *(v1.2)*

| # | Label (client sees) | `key` | Type | Required | Options / help |
|---|---|---|---|---|---|
| I1 | Brand voice in three words | `brand_voice` | text | no | e.g. "warm, direct, unhurried". The copywriter's tone brief. |
| I2 | A line you always say to new clients (your voice) | `signature_line` | textarea | no | Word for word; it is reused in the welcome email / first text so the messages sound like the client. |

---

## Key → Brief field map (authoritative for the normalizer)

| `key` | Brief field (§4) |
|---|---|
| `business_name` | `business.name` |
| `business_type` | `business.type` + `preset` (selection) |
| `website` | `business.website` |
| `primary_location` | `business.location` |
| `timezone` | `business.timezone` |
| `team_size` | `business.teamSize` (enum) |
| `monthly_lead_volume` | `business.monthlyLeadVolume` (enum) |
| `business_hours` | `business.hours` |
| `core_offer` | `offer.summary` |
| `price_points` | `offer.pricePoints` (parse `[{name, price}]` per line) |
| `lead_magnet` | `offer.leadMagnet` |
| `avg_deal_value` | `offer.avgDealValue` |
| `ideal_customer` | `audience.ideal` |
| `top_pain_points` | `audience.painPoints` (split lines → array) |
| `objections` | `audience.objections` (split lines → array) |
| `primary_goal` | `goal.primary` |
| `sales_stages` | `goal.salesStages` (split → array of stage names) |
| `booking_needed` | `goal.bookingNeeded` (bool) |
| `follow_up_style` | `goal.followUpStyle` |
| `email_ready` | `channels.email` (bool) |
| `sms_desired` | `channels.sms` (bool) |
| `a2p_status` | `channels.a2pStatus` |
| `payment_processor` | `channels.payment` |
| `calendar_connected` | `channels.calendarConnected` (bool) |
| `social_channels` | `channels.social` (array) |
| `existing_pipeline` | `assets.existingPipeline` |
| `existing_workflows` | `assets.existingWorkflows` |
| `brand_assets` | `assets.brand` |
| `anything_else` | `assets.notes` |
| `staff_members` | `team.staff` (parse lines → `[{name, email, role?, mobile?}]`; an unreadable line → `warnings[]`) |
| `notify_name` | `team.notifyName` |
| `calls_name` | `team.callsName` |
| `booking_calendars` | `calendars` (parse lines → `[{name, type, staffNames}]`, type ∈ `one_on_one` / `round_robin` / `class`) |
| `has_phone_number` | `channels.hasPhoneNumber` (`yes` / `no` / `unsure`) |
| `brand_voice` | `voice.threeWords` |
| `signature_line` | `voice.signatureLine` |

### Derived `flags` (normalizer computes, not asked)
- `needs_a2p` ← `sms_desired == yes` AND `a2p_status != approved`
- `stripe_not_connected` ← `payment_processor == "Stripe not connected"`
- `calendar_oauth_needed` ← `booking_needed == yes` AND `calendar_connected == no`
- `email_domain_needed` ← `email_ready == no`
- `phone_number_needed` ← `sms_desired == yes` AND `has_phone_number` answered anything but `Yes` *(v1.2)*

### `validate_brief` warnings (v1.2 — the gaps a schema-valid brief can still carry)
Returned as `warnings[]` next to `errors[]`; never fatal. The plan-gen skill reads them and either asks or marks the step as waiting.
- **No staff listed** → "notifications will be marked as waiting for a staff member" (`user.__pending__` in the plan).
- **A calendar named without staff** → it cannot take bookings until someone is put on it.
- **A calendar lists a name not in the staff list** / **notify or calls name not in the staff list** ("the owner" is always accepted).
- **Booking wanted but no calendar described** → the plan would have to assume one.
- Plus every parse-time note the normalizer left in `brief.warnings` (e.g. `Staff line 2 ("Bob") was skipped: no email address found`).

---

## Ratified additions — folded in 2026-06-15 (Jerry)

These three keys came up while reconciling against the CLL 49-field form and Module 0 prereqs. **Jerry ratified adding all three on 2026-06-15** (`outbox/2026-06-15-to-atlas-intake-decisions.md`, decision #1, overriding the earlier "ship without"). They are now in the installed set above (Section A: A6–A8) and the Key → Brief map. Adding them is a coordinated contract change: **command-center** folds the keys into schema §3 + §6; **ghl-command-mcp** adds them to the form-template installer. All three are **optional** (the required floor is unchanged), so the skill still degrades gracefully when a subscriber leaves them blank.

atlas-owned wording decisions — the dataType + brief path proposed for cc (§3/§6 fold-in) and mcp (installer):

| `key` | Form type | GHL `dataType` | Brief path (§4) | Brief type | Option labels | Drives in plan |
|---|---|---|---|---|---|---|
| `team_size` | dropdown | `SINGLE_OPTIONS` | `business.teamSize` | enum | `Just me`, `2-5`, `6+` | speed-to-lead human-follow-up sizing + opportunity assignment / round-robin; calendar staff hint |
| `monthly_lead_volume` | dropdown | `SINGLE_OPTIONS` | `business.monthlyLeadVolume` | enum | `Under 100`, `100-500`, `500-1000`, `1000+` | SMS phone-number count for the clinic_launch_a2p preset (~1 per 500/mo) + send-volume sizing |
| `business_hours` | textarea | `LARGE_TEXT` | `business.hours` | string | — (free text) | calendar `openHours` defaults (replaces the generic Mon-Fri 9-5); parsed + operator-editable |

Fold-in notes:
- **`monthly_lead_volume` refined from the original "(text)" proposal → dropdown buckets (`SINGLE_OPTIONS`).** Free text ("a few hundred?") is unparseable for the 1-number-per-500 math; fixed buckets map cleanly to a phone-number count. Flagging the type change explicitly so the installer builds a dropdown, not a text field.
- All three land under the Brief's `business.*` namespace (new sub-keys `teamSize`, `monthlyLeadVolume`, `hours`) — purely additive, no existing field changes, so `schemaVersion` stays `0.1`.
- No new derived `flags`. `monthly_lead_volume` is read directly by the clinic_launch_a2p preset at phone-provisioning time; absent → the preset keeps its current ask-at-handoff default. `business_hours` absent → skill keeps the Mon-Fri 9-5 default + operator-edit flag. `team_size` absent → skill keeps "automate first touch, human follow-up light."

---

## Tier 1 v2 additions — folded in 2026-08-26 (question-set 0.2)

The owner inspected a real build and found it had created **one** user and **one** calendar — because the intake never asked. His words: *"Staff: if we are going to create one, why wouldn't we ask for the info on all staff members who should be included?"* and *"Calendar: are we sure we only need one calendar? Did we even ask?"* Seven keys, all optional (the required floor is unchanged):

| `key` | Form type | GHL `dataType` | Brief path (§4) | Brief type | Drives in plan |
|---|---|---|---|---|---|
| `staff_members` | textarea | `LARGE_TEXT` | `team.staff` | `[{name, email, role?, mobile?}]` | `users[]` (one per line) + every `userRef` on notifications, tasks, assignments, calendars |
| `notify_name` | text | `TEXT` | `team.notifyName` | string | which `user.*` the new-lead `internal_notification` points at (or `user.__pending__`) |
| `calls_name` | text | `TEXT` | `team.callsName` | string | task assignee / `assign_user` on the speed-to-lead |
| `booking_calendars` | textarea | `LARGE_TEXT` | `calendars` | `[{name, type, staffNames}]` | how many `calendars[]` are built, their `calendarType` and `teamMemberRefs` |
| `has_phone_number` | dropdown | `SINGLE_OPTIONS` | `channels.hasPhoneNumber` | `yes` / `no` / `unsure` | the phone-number handoff (with SMS wanted) |
| `brand_voice` | text | `TEXT` | `voice.threeWords` | string | tone of every email / SMS template |
| `signature_line` | textarea | `LARGE_TEXT` | `voice.signatureLine` | string | reused verbatim in the welcome email / first text |

Parse rules (normalizer, pure, never throws):
- **Staff lines**: fields split on `,` `|` `;` or tab; order is not trusted — the email is whichever field looks like one, the mobile whichever looks like a phone number, the name the first remaining field, the role the rest. No name or no email → the line is **skipped and reported** in `warnings[]`, never silently dropped.
- **Calendar lines**: first field is the name; the type is whichever field reads like `one-on-one` / `1:1`, `round-robin`, or `class` / `group` (a `type:` prefix is fine); everything else is people, split on `+`, `&`, `and`, `/`. No recognizable type → assumed one-on-one **and reported**.
- The derived fieldKeys for these seven are produced by the same rule as the rest (`contact.intake_<slug>`) and are **derived, not yet live-captured**; the installer's verify-after step confirms the real key on first install.
