# SM-CAMPAIGNS-01 R2 — Data & Interaction Specification

**Date:** 2026-11-03  
**Scope:** Shared across Y1 / Y2 / Y3  
**Authority:** D1–D21 + AC-1…AC-12; Muse V-findings as evidence

---

## 1. Canonical vocabulary (excerpt)

| Name | Meaning / behavior |
|------|-------------------|
| Home | Lifecycle primary pane |
| Sequence | Unified initial + follow-ups |
| Schedule | Timezone, days, working hours, daily cap |
| Start Campaign | Opens launch recap when ready |
| Confirm Start | Only launch commit |
| Keep editing | Dialog dismiss (never “Cancel”) |
| Cancel Campaign | Destructive lifecycle action |
| Save Sequence | Single authoritative explicit save (AC-6) |
| Insert Variable | Picker → insert at caret |
| Apply Template | Picker → replace active step subject/body |
| Fallbacks | One modal for variable fallbacks |
| Preview | One surface; Step \| Full Sequence; shared recipient |

Full map: `shared/vocabulary.js`.

---

## 2. Save model (V-04 / C-3 disposition)

**Implemented:** Explicit whole-Sequence save **and** independent Schedule save.  
**Authority:** AC-6 + D2 — **not** reopened as a product decision.  
Muse flagged “owner decision”; that is incorrect relative to the approved constraint register.

Rules (R2.1):

- **Sequence dirty domain:** steps + fallbacks + stopOnReply + replyDetection + maxFollowUps.  
- **Schedule dirty domain:** timezone, days, window, cap — does **not** mark Sequence unsaved.  
- Chrome: **Save Sequence** / **Save Schedule** with separate unsaved bars.  
- Navigation guard applies to Sequence dirty when leaving Sequence.  
- Status text may read Saved / Unsaved Sequence / Unsaved Schedule / both.

---

## 3. Reconciled illustrative dataset

Source: `shared/data.js`. Campaign: **Q4 Enterprise Outreach**.

### Pending

| Field | Value |
|-------|-------|
| enrolled | 248 |
| emailsSent | *hidden (null)* |
| replies | *hidden (null)* |
| timezone | unset → Schedule blocker |

### Active / Paused (same mid-run story)

| Field | Value |
|-------|-------|
| enrolled | 248 |
| emailsSent | 91 |
| replies | 7 |
| notStarted | 20 |
| inProgress | 186 |
| finished | 42 |

**Identity check:** 20 + 186 + 42 = **248**.  
**replies (7)** are a subset of finished — not added to sent.

### Completed (later snapshot of same Campaign)

| Field | Value |
|-------|-------|
| enrolled | 248 |
| emailsSent | 612 |
| replies | 37 |
| finished | 248 |

**Funnel attribution:** Enrolled 248 → Reached Sequence 241 (7 never eligible) → Replied 37 · Finished no reply 204.  
204 + 37 = 241; 241 + 7 = 248.

### Cancelled

Partial-send history retained (91 sent / 7 replies); results actions shown because `hasResults: true`.

### Notes

- Not production data. UI shows a quiet **Example data** mark near metrics.
- No scheduling forecasts. Delays: “N days after previous step” only.
- Sender usage chips illustrative; rotation not claimed (D11).

---

## 4. Readiness contract (V-03 / V-09)

Factors (identical everywhere): Audience · Sequence · Senders · Schedule · Personalization.

| Factor | Blocks Start? |
|--------|---------------|
| Audience / Sequence / Senders / Schedule | Yes when incomplete |
| Personalization | Warning only (D5) |
| Unsaved Sequence | Blocks Start |

Schedule requires **timezone set**. Checklist items deep-link to the fix surface.

---

## 5. Preview contract (V-10)

- Single modal.
- Modes: Step | Full Sequence.
- One `previewRecipientId`.
- Search/filter: missing-data only; Previous / Next.

---

## 6. Authoring contract (V-01 / V-11 / V-14)

- Insert Variable / Apply Template / Fallbacks — editor toolbar (one home each).
- Insert Variable inserts at **saved caret** or replaces selection (C-1 / SM-VARIABLES-01).
- Stop-on-reply visible in Sequence inspector **and** Advanced.
- Follow-up labels renumbered sequentially after add/remove.
- Relative delay inputs on the spine.
- Schedule timezone catalogue = product IANA list (`Intl.supportedValuesOf`); Asia/Karachi included.

---

## 7. Primary actions (V-05)

| Lifecycle | Primary (rail) | Header |
|-----------|----------------|--------|
| Pending | Start Campaign | Preview + Save (when relevant) + Cancel Campaign |
| Active | Pause | … |
| Paused | Resume | … |
| Completed / Cancelled | Duplicate | … |

Modal dismiss = **Keep editing** / Close — never “Cancel”.
