@explorer02/cfm-survey-sdk 0.2.5 → 0.2.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/dist/cli/index.js +45 -45
  2. package/dist/cli/index.mjs +45 -45
  3. package/package.json +1 -1
  4. package/templates/docs/00-integration/agent-execution-flow.md +18 -6
  5. package/templates/docs/00-integration/agent-operating-contract.md +2 -0
  6. package/templates/docs/00-integration/apply-ui-config.md +15 -2
  7. package/templates/docs/00-integration/component-checklist.md +5 -3
  8. package/templates/docs/00-integration/ui-customization-wizard.md +1 -1
  9. package/templates/docs/00-integration/wizard-chrome-contract.md +284 -0
  10. package/templates/docs/00-integration/wizard-config-handoff.md +7 -1
  11. package/templates/docs/00-integration/wizard-customization-catalog.md +391 -0
  12. package/templates/docs/00-integration/wizard-post-customize-build.md +405 -0
  13. package/templates/docs/00-integration/wizard-preview-build-guide.md +20 -4
  14. package/templates/docs/00-integration/wizard-question-type-styling.md +27 -6
  15. package/templates/docs/01-components/19-survey-sticky-chrome.md +16 -55
  16. package/templates/docs/03-ui-specs/README.md +1 -1
  17. package/templates/docs/MANIFEST.json +10 -1
  18. package/templates/docs/index.md +10 -7
  19. package/templates/docs/templates/Footer.tsx +72 -0
  20. package/templates/docs/templates/Header.tsx +110 -0
  21. package/templates/docs/templates/LanguageSelector.tsx +40 -0
  22. package/templates/docs/templates/PreviewBridgeInit.tsx +13 -0
  23. package/templates/docs/templates/ProgressBar.tsx +33 -0
  24. package/templates/docs/templates/Question.tsx +51 -7
  25. package/templates/docs/templates/RatingScale.tsx +66 -59
  26. package/templates/docs/templates/SurveyStickyChrome.tsx +19 -5
  27. package/templates/docs/templates/uiConfig.ts +33 -0
  28. package/templates/docs/templates/verify-agent-build.sh +31 -1
  29. package/templates/preview-harness/preview-bridge.inline.js +18 -4
  30. package/templates/preview-harness/vite-app/src/preview-live-overrides.css +7 -0
  31. package/templates/previewBridge.ts +144 -39
  32. package/templates/survey-theme.css +7 -0
  33. package/templates/wizard-dist/assets/{PreviewMock-AoZdAEPZ.js → PreviewMock-tTMvwuEy.js} +1 -1
  34. package/templates/wizard-dist/assets/{TypePanel-39FnbtvG.js → TypePanel-B9Ls7BSq.js} +1 -1
  35. package/templates/wizard-dist/assets/index-CjkIlOUI.css +1 -0
  36. package/templates/wizard-dist/assets/index-CoCrnnxt.js +34 -0
  37. package/templates/wizard-dist/index.html +2 -2
  38. package/templates/wizard-dist/assets/index-BhWM50Yu.css +0 -1
  39. package/templates/wizard-dist/assets/index-CWKdsJOp.js +0 -34
@@ -2,7 +2,7 @@
2
2
 
3
3
  > **Blocking gate before Phase 5 (BUILD).** Read [`agent-operating-contract.md`](agent-operating-contract.md) §2–§3 first — do not invent files or paths from memory.
4
4
  >
5
- > **Wizard-ready build (Phase 5 — mandatory):** Every agent build wires live-preview contract per [`agent-execution-flow.md`](agent-execution-flow.md), [`wizard-preview-build-guide.md`](wizard-preview-build-guide.md), and [`wizard-question-type-styling.md`](wizard-question-type-styling.md) — `var(--cfm-*)`, `data-cfm-*` hooks, `selectionStyles.ts`, `labelStyles.ts`, draft `survey-ui-config.json`. Running the wizard (Phase 6b) is optional; wizard-ready artifacts are not.
5
+ > **Wizard-ready build (Phase 5 — mandatory):** Copy chrome templates from [`wizard-chrome-contract.md`](wizard-chrome-contract.md) (`Header.tsx`, `Footer.tsx`, `ProgressBar.tsx`, `SurveyStickyChrome.tsx`, etc.) and wire live-preview contract per [`wizard-preview-build-guide.md`](wizard-preview-build-guide.md) and [`wizard-question-type-styling.md`](wizard-question-type-styling.md) — `var(--cfm-*)`, `data-cfm-*` hooks, `selectionStyles.ts`, `labelStyles.ts`, draft `survey-ui-config.json`. Running the wizard (Phase 6b) is optional; wizard-ready artifacts are not.
6
6
  >
7
7
  > Read [`canonical-survey-fixtures.md`](canonical-survey-fixtures.md) when matrix/slider labels are missing.
8
8
 
@@ -108,7 +108,9 @@ bash templates/verify-agent-build.sh
108
108
 
109
109
  ## Step 4: Wizard-ready build (Phase 5 — mandatory)
110
110
 
111
- Read: [`agent-execution-flow.md`](agent-execution-flow.md), [`wizard-preview-build-guide.md`](wizard-preview-build-guide.md), [`wizard-question-type-styling.md`](wizard-question-type-styling.md)
111
+ Read: [`wizard-chrome-contract.md`](wizard-chrome-contract.md), [`agent-execution-flow.md`](agent-execution-flow.md), [`wizard-preview-build-guide.md`](wizard-preview-build-guide.md), [`wizard-question-type-styling.md`](wizard-question-type-styling.md)
112
+
113
+ - [ ] **Copied** `templates/docs/templates/Header.tsx`, `Footer.tsx`, `ProgressBar.tsx`, `SurveyStickyChrome.tsx`, `LanguageSelector.tsx`, `PreviewBridgeInit.tsx` (do not use `apps/client` as reference)
112
114
 
113
115
  - [ ] `src/styles/survey-theme.css` with full `--cfm-*` set (copy from `templates/survey-theme.css`)
114
116
  - [ ] `selectionStyles.ts` + `labelStyles.ts` in `src/lib/surveyUi/`
@@ -116,7 +118,7 @@ Read: [`agent-execution-flow.md`](agent-execution-flow.md), [`wizard-preview-bui
116
118
  - [ ] `previewBridge.ts` + `PreviewBridgeInit` in root layout
117
119
  - [ ] Header/Footer/ProgressBar/SurveyPage use `var(--cfm-*)` — no hardcoded brand hex for wizard-controlled tokens
118
120
  - [ ] `data-cfm-logo` / `data-cfm-logo-text`, `data-cfm-company`, `data-cfm-survey-title`, `data-cfm-btn-next`, `data-cfm-btn-back`, `data-cfm-thank-you` on chrome
119
- - [ ] **Layout toggles:** `data-cfm-progress`, `[data-cfm-question-number]`, `[data-cfm-required]`, `.cfm-footer` — see `wizard-troubleshooting.md` §3
121
+ - [ ] **Layout toggles:** `data-cfm-progress`, `data-cfm-question-number`, `data-cfm-required`, `cfm-footer`, `cfm-header` — see [`wizard-chrome-contract.md`](wizard-chrome-contract.md)
120
122
  - [ ] Per-type scale vars per `wizard-question-type-styling.md` for **all 11 types** (wizard exports all; survey inventory may be smaller)
121
123
  - [ ] Selection pattern: focus ring = outer border + inner dot; cell selected = annulus fill
122
124
  - [ ] `npx cfm-sdk export-previews` succeeds from project root (when previews needed for AWS wizard)
@@ -15,7 +15,7 @@ This is the **recommended default** because it:
15
15
  - Serves wizard + component previews from **one local server** (`localhost:4200`)
16
16
  - Auto-exports all **11** question-type previews from agent components
17
17
  - Writes `survey-ui-config.json` **directly** on save — no S3, no session polling
18
- - Cleans up automatically when the CLI exits (no orphan S3 garbage)
18
+ - Cleans up local `out/previews/` when client quits without saving (`POST /api/wizard-quit`) or when CLI exits (Ctrl+C)
19
19
  - Updates live previews via the same iframe + preview bridge as production
20
20
 
21
21
  **Agent script after client says yes:**
@@ -0,0 +1,284 @@
1
+ # Wizard Chrome Contract — Required DOM + CSS Hooks
2
+
3
+ > **Mandatory Phase 5.** If any hook is missing, wizard live preview fails for that control — even though the survey may look fine in localhost dev without the wizard open.
4
+ > **Copy-first templates:** [`templates/Header.tsx`](../templates/Header.tsx), [`Footer.tsx`](../templates/Footer.tsx), [`ProgressBar.tsx`](../templates/ProgressBar.tsx), [`SurveyStickyChrome.tsx`](../templates/SurveyStickyChrome.tsx), [`LanguageSelector.tsx`](../templates/LanguageSelector.tsx), [`PreviewBridgeInit.tsx`](../templates/PreviewBridgeInit.tsx), [`previewBridge.ts`](../../previewBridge.ts).
5
+
6
+ Pipeline: [`wizard-preview-build-guide.md`](wizard-preview-build-guide.md) · [`apply-ui-config.md`](apply-ui-config.md)
7
+
8
+ ---
9
+
10
+ ## Symptom → missing hook (quick fix)
11
+
12
+ | Wizard control / symptom | Required fix |
13
+ |--------------------------|--------------|
14
+ | Logo not updating in Branding / Header preview | `data-cfm-logo` img + `data-cfm-logo-text` fallback in `Header.tsx` |
15
+ | Company name not updating | `data-cfm-company` span in `Header.tsx` |
16
+ | Show header works but progress bar toggle does nothing | Progress bar needs `data-cfm-progress` + class `cfm-progress`; header needs class `cfm-header` only — **not** on sticky wrapper |
17
+ | Show footer toggle does nothing | `footer` + class `cfm-footer` |
18
+ | Question numbers / required asterisk toggles | `data-cfm-question-number` + `data-cfm-required` on every question title |
19
+ | Question card padding/shadow/colors not live-updating | Question wrapper uses `var(--cfm-card-*)` — not hardcoded `bg-white shadow-sm` |
20
+ | MCQ / NPS / dropzone style pickers | Root reads `html[data-cfm-mcq-style]`, `[data-cfm-nps-button-style]`, `[data-cfm-dropzone-style]` from bridge |
21
+ | Scale selection colors not updating | Import `selectionStyles.ts`; use `var(--cfm-matrix-selected)` / `var(--cfm-input-focus-ring)` |
22
+ | Company name not showing after logo | Copy `Header.tsx` template — brand row is `[logo][data-cfm-company]` in one flex container |
23
+ | Company shows when empty | Bridge clears `[data-cfm-company]` when `companyName` is `""` — do not hardcode "Company Name" as visible default |
24
+ | NPS colors / rings not updating | Copy `RatingScale.tsx` + `selectionStyles.ts` — no hardcoded `#e20074` |
25
+ | Text placeholder color not updating | `data-cfm-textfield` + `--cfm-input-placeholder` in CSS / `::placeholder` rule |
26
+ | Matrix 2nd row toggle | Harness adds row via `previewMultiStatement` — `LikertMatrixScale` must render all `statementRows` from props |
27
+ | Blank page after deploy | **Never** reference `UI_CONFIG` without import — use `src/lib/uiConfig.ts` |
28
+ | Logo wrong on CloudFront | Never change `global.logo.fileName` manually — use wizard file in `public/` |
29
+
30
+ ---
31
+
32
+ ## Copy order (agents — do this in Phase 5)
33
+
34
+ ```bash
35
+ # From SDK templates folder (monorepo or node_modules)
36
+ cp templates/docs/templates/Header.tsx src/components/Header.tsx
37
+ cp templates/docs/templates/Footer.tsx src/components/Footer.tsx
38
+ cp templates/docs/templates/ProgressBar.tsx src/components/ProgressBar.tsx
39
+ cp templates/docs/templates/SurveyStickyChrome.tsx src/components/SurveyStickyChrome.tsx
40
+ cp templates/docs/templates/LanguageSelector.tsx src/components/LanguageSelector.tsx
41
+ cp templates/docs/templates/PreviewBridgeInit.tsx src/components/PreviewBridgeInit.tsx
42
+ cp templates/previewBridge.ts src/lib/previewBridge.ts
43
+ cp templates/survey-theme.css src/styles/survey-theme.css
44
+ cp templates/docs/templates/uiConfig.ts src/lib/uiConfig.ts
45
+ cp templates/docs/templates/RatingScale.tsx src/components/RatingScale.tsx
46
+ cp templates/docs/templates/selectionStyles.ts src/lib/surveyUi/selectionStyles.ts
47
+ cp templates/docs/templates/labelStyles.ts src/lib/surveyUi/labelStyles.ts
48
+ ```
49
+
50
+ Wire `PreviewBridgeInit` in `layout.tsx` (local dev). Wizard iframes use injected `preview-bridge.inline.js` at export time.
51
+
52
+ Run verification:
53
+
54
+ ```bash
55
+ bash templates/verify-agent-build.sh
56
+ ```
57
+
58
+ ---
59
+
60
+ ## Layer 1 — CSS variables (`--cfm-*`)
61
+
62
+ Wizard sends SNAPSHOT (full) + DELTA (partial) CSS vars to `:root`.
63
+
64
+ **Rule:** Every color, radius, spacing, or chrome dimension editable in the wizard must be consumed via `var(--cfm-…)` — not hardcoded `#e20074` / `bg-[#e20074]`.
65
+
66
+ Minimum files:
67
+
68
+ | File | Role |
69
+ |------|------|
70
+ | `src/styles/survey-theme.css` | All default `--cfm-*` vars |
71
+ | `globals.css` | `@import './styles/survey-theme.css'` |
72
+ | Scale components | `selectionStyles.ts` + `labelStyles.ts` |
73
+
74
+ ---
75
+
76
+ ## Layer 2 — Content patches (`data-cfm-*` + layout flags)
77
+
78
+ Wizard sends `contentPatch` on SNAPSHOT (not DELTA). Preview bridge applies patches to matching DOM nodes.
79
+
80
+ ### Branding & header
81
+
82
+ | Patch field | DOM target | Template location |
83
+ |-------------|------------|-------------------|
84
+ | `logoUrl` | `[data-cfm-logo]` → sets `src`, shows img; hides `[data-cfm-logo-text]` | `Header.tsx` |
85
+ | `companyName` | `[data-cfm-company]` text; fills logo-text when img hidden | `Header.tsx` |
86
+ | `layoutFlags.showCompanyName` | `[data-cfm-company]` display | bridge |
87
+
88
+ ### Layout toggles (independent — critical)
89
+
90
+ | `layoutFlags` key | Bridge selector | Component requirement |
91
+ |-------------------|-----------------|----------------------|
92
+ | `showHeader` | `.cfm-header`, `header.cfm-header` | Class on `<header>` only |
93
+ | `showProgressBar` | `.cfm-progress`, `[data-cfm-progress]` | **Separate** from header — `ProgressBar.tsx` |
94
+ | `showFooter` | `.cfm-footer`, `footer.cfm-footer` | Class on `<footer>` |
95
+ | `showLanguageSwitcher` | `[data-cfm-language]` | `LanguageSelector.tsx` |
96
+ | `showNextButton` | `[data-cfm-btn-next]` | `SurveyPage.tsx` nav |
97
+ | `showBackButton` | `[data-cfm-btn-back]` | `SurveyPage.tsx` nav |
98
+ | `showQuestionNumbers` | `[data-cfm-question-number]` | `Question.tsx` title |
99
+ | `showRequiredAsterisk` | `[data-cfm-required]` | `Question.tsx` title |
100
+ | `showFooterLogo` | `[data-cfm-footer-logo]` | `Footer.tsx` |
101
+
102
+ **Anti-pattern:** Putting `sticky top-0` on the same element as `cfm-header` — bridge used to hide progress when toggling header. Templates use `cfm-sticky-chrome` wrapper without using it for `showHeader`.
103
+
104
+ ### Survey chrome content
105
+
106
+ | Patch field | DOM target |
107
+ |-------------|------------|
108
+ | `surveyTitle` | `[data-cfm-survey-title]` |
109
+ | `thankYouMessage` | `[data-cfm-thank-you]` |
110
+ | `buttonLabels.next` / `.back` | `[data-cfm-btn-next]` / `[data-cfm-btn-back]` |
111
+ | `copyrightText` | `[data-cfm-copyright]` |
112
+ | `footerLinks[]` | `[data-cfm-footer-links]` innerHTML |
113
+
114
+ ### Question-type DOM attributes (on `<html>`)
115
+
116
+ Set via `contentPatch.domAttributes`:
117
+
118
+ | Attribute | Wizard source | Component reads |
119
+ |-----------|---------------|-----------------|
120
+ | `data-cfm-mcq-style` | `questionTypes.MCQ.optionStyle` | MCQ card classes / CSS |
121
+ | `data-cfm-nps-button-style` | `questionTypes.NPS_SCALE.buttonStyle` | `RatingScale.tsx` |
122
+ | `data-cfm-dropzone-style` | `questionTypes.FILE_UPLOAD.dropzoneStyle` | `FileUploadScale.tsx` |
123
+
124
+ Vite preview harness also applies `previewState` via `PreviewConfigContext` for placeholders, NPS hints, rank variant, etc.
125
+
126
+ ---
127
+
128
+ ## Question card (Theme step)
129
+
130
+ Question outer wrapper **must** use theme vars:
131
+
132
+ ```tsx
133
+ <section
134
+ id={question.id}
135
+ className="cfm-question-card space-y-4"
136
+ style={{
137
+ background: 'var(--cfm-card-bg, #fff)',
138
+ borderColor: 'var(--cfm-card-border-color, #e5e7eb)',
139
+ padding: 'var(--cfm-card-padding, 24px)',
140
+ boxShadow: 'var(--cfm-card-shadow, 0 1px 3px rgba(0,0,0,0.1))',
141
+ borderRadius: 'var(--cfm-border-radius, 12px)',
142
+ borderWidth: 1,
143
+ borderStyle: 'solid',
144
+ }}
145
+ >
146
+ ```
147
+
148
+ Question title hooks:
149
+
150
+ ```tsx
151
+ <h2>
152
+ {question.questionNumber != null && (
153
+ <span data-cfm-question-number className="mr-1 font-semibold">
154
+ {question.questionNumber}.
155
+ </span>
156
+ )}
157
+ <span dangerouslySetInnerHTML={{ __html: displayQuestionText }} />
158
+ {question.required && (
159
+ <span data-cfm-required className="ml-1 text-red-500">*</span>
160
+ )}
161
+ </h2>
162
+ ```
163
+
164
+ TEXTFIELD placeholder live preview: `data-cfm-textfield` on input/textarea.
165
+
166
+ ---
167
+
168
+ ### Branding & header — company name after logo
169
+
170
+ **Layout rule:** Logo and company name share one flex row (`.cfm-header-brand`):
171
+
172
+ ```
173
+ [ data-cfm-logo img ] [ data-cfm-company text ]
174
+ ```
175
+
176
+ | State | What preview shows |
177
+ |-------|-------------------|
178
+ | No logo, no company | Empty header brand slot (no text) |
179
+ | No logo, company set | `data-cfm-logo-text` shows company name |
180
+ | Logo uploaded, company set | Image visible + `data-cfm-company` text **after** logo |
181
+ | Logo uploaded, company empty | Image only; company span hidden |
182
+
183
+ Wizard **Logo** step controls size via `global.header.logoBoxWidth`, `logoBoxHeight`, `logoPadding` → CSS vars `--cfm-header-logo-width/height/padding`.
184
+
185
+ **Agent must copy** [`uiConfig.ts`](../templates/uiConfig.ts) — Header reads `survey-ui-config.json` at build time. **Never** use a global `UI_CONFIG` variable (causes `ReferenceError` blank page).
186
+
187
+ ### Logo pipeline (wizard → CloudFront) — all 4 steps must match
188
+
189
+ ```
190
+ 1. Wizard upload → public/logo_{timestamp}_{name}.jpg
191
+ 2. save-config → survey-ui-config.json global.logo.fileName (same name)
192
+ 3. Phase 6c apply → Header img src="./{fileName}" via uiConfig.ts
193
+ 4. build + deploy → out/{fileName} → S3 deploy prefix → CloudFront
194
+ ```
195
+
196
+ **Forbidden during deploy troubleshooting:**
197
+ - Changing `global.logo.fileName` to `telekom-logo.svg` because JPG "wasn't ready"
198
+ - Using `global.logo.url` (data: or /assets/ URL) as img src
199
+
200
+ If deploy preflight fails on missing logo: wait for wizard save (file lands in `public/`), then rebuild — do not substitute a different filename.
201
+
202
+ See [`aws-deploy.md`](aws-deploy.md) § Logos & local assets.
203
+
204
+ ### Question card — cell selected + focus ring
205
+
206
+ Theme → Question card exposes two tokens used on **every** radio/scale cell:
207
+
208
+ | Token | CSS var | Visual |
209
+ |-------|---------|--------|
210
+ | Cell selected | `--cfm-matrix-selected` | **Fill** inside outer ring (annulus) |
211
+ | Focus ring | `--cfm-input-focus-ring` | **Outer border** + **inner dot** |
212
+
213
+ Copy [`selectionStyles.ts`](../templates/selectionStyles.ts) and use in `RatingScale.tsx`, `LikertMatrixScale.tsx`, `CsatMatrixScale.tsx`, MCQ options.
214
+
215
+ ### Per-type live preview (all 11 types)
216
+
217
+ | Type | Required wiring |
218
+ |------|-----------------|
219
+ | MCQ | `var(--cfm-mcq-*)` on option cards; `html[data-cfm-mcq-style]` |
220
+ | TEXTFIELD | `data-cfm-textfield` + `--cfm-input-placeholder` on `::placeholder` |
221
+ | NPS_SCALE | Copy wizard `RatingScale.tsx`; `selectionStyles` on radio rings |
222
+ | CFM_MATRIX | `matrixRadioRingStyle`; render **all** `statementRows` (wizard multi-row toggle adds 2nd row in harness) |
223
+ | CSAT/RATING_MATRIX | `CsatMatrixScale.tsx` + `labelStyles.ts` |
224
+ | SLIDER_MATRIX | `CustomSliderTrack.tsx` + slider tick vars |
225
+ | FILE_UPLOAD | `data-cfm-dropzone-style` + `--cfm-upload-border-color` |
226
+ | HEATMAP | `--cfm-heatmap-pin*` |
227
+ | RANK_ORDER | `--cfm-rank-*` |
228
+ | TEXT_AND_MEDIA | `--cfm-media-*` |
229
+
230
+ Full table: [`wizard-question-type-styling.md`](wizard-question-type-styling.md).
231
+
232
+ ---
233
+
234
+ ## SurveyPage wiring (content phase)
235
+
236
+ ```tsx
237
+ <div className="flex min-h-screen flex-col" style={{ background: 'var(--cfm-background)' }}>
238
+ <SurveyStickyChrome progressPercentage={state.progressPercentage} />
239
+ <main style={{ maxWidth: 'var(--cfm-max-width)' }}>...</main>
240
+ <Footer />
241
+ </div>
242
+ ```
243
+
244
+ Intro / end / paused: standalone `<Header />` (not sticky chrome). Footer still uses `cfm-footer`.
245
+
246
+ ---
247
+
248
+ ## Local wizard — preview garbage collection
249
+
250
+ | Event | Action |
251
+ |-------|--------|
252
+ | Client **saves** (Review & Build) | `POST /api/save-config` → writes config → **deletes `out/previews/`** → CLI exits |
253
+ | Client **quits** without saving | `POST /api/wizard-quit` → deletes `out/previews/` → CLI exits |
254
+ | Agent **Ctrl+C** on customize CLI | Same cleanup on shutdown |
255
+
256
+ EC2 `customize-ui`: quit/save uses disk session GC — see [`wizard-config-handoff.md`](wizard-config-handoff.md).
257
+
258
+ **Note:** GC removes **preview export cache** (`out/previews/`), not your `src/` or production `out/` build. Re-run `export-previews` on next wizard session.
259
+
260
+ ---
261
+
262
+ ## Verification checklist (blocking before Phase 6b)
263
+
264
+ - [ ] Copied all templates from § Copy order
265
+ - [ ] `grep -r data-cfm-logo src/components/Header.tsx` — match
266
+ - [ ] `grep -r data-cfm-progress src/components/ProgressBar.tsx` — match
267
+ - [ ] `grep -r cfm-footer src/components/Footer.tsx` — match
268
+ - [ ] `grep -r data-cfm-question-number src/components/Question.tsx` — match
269
+ - [ ] `grep -rE 'var\\(--cfm-' src/components/` — no wizard colors as hardcoded hex only
270
+ - [ ] `bash templates/verify-agent-build.sh` exit 0
271
+ - [ ] `npx cfm-sdk export-previews` exit 0
272
+
273
+ ---
274
+
275
+ ## Related
276
+
277
+ | Doc | Role |
278
+ |-----|------|
279
+ | [`wizard-customization-catalog.md`](wizard-customization-catalog.md) | Every wizard control → CSS var → component |
280
+ | [`wizard-preview-build-guide.md`](wizard-preview-build-guide.md) | Full build guide |
281
+ | [`wizard-post-customize-build.md`](wizard-post-customize-build.md) | After wizard save — apply all formats + build |
282
+ | [`wizard-question-type-styling.md`](wizard-question-type-styling.md) | Per-type CSS vars |
283
+ | [`10-header-footer.md`](../01-components/10-header-footer.md) | Branding patterns |
284
+ | [`12-survey-chrome.md`](../03-ui-specs/12-survey-chrome.md) | Chrome layout spec |
@@ -1,6 +1,7 @@
1
1
  # Wizard Config Handoff — Wait, Capture, Apply
2
2
 
3
3
  > **Phase 6b → 6c.** Read with [`ui-customization-wizard.md`](ui-customization-wizard.md) and [`apply-ui-config.md`](apply-ui-config.md).
4
+ > **Phase 6c runbook (all formats + build):** [`wizard-post-customize-build.md`](wizard-post-customize-build.md).
4
5
  > Pipeline: [`agent-execution-flow.md`](agent-execution-flow.md).
5
6
 
6
7
  This doc tells the agent **exactly** how to wait for the client to finish the wizard, capture the JSON output, and apply **every** change without omission.
@@ -53,6 +54,10 @@ When the client uploads a logo in the local wizard:
53
54
 
54
55
  The logo is **not** fetched from wizard memory on CloudFront — only from the deploy bundle. See [`aws-deploy.md`](aws-deploy.md) § Logos & local assets.
55
56
 
57
+ **Local quit (preview GC):** If the client exits without saving, wizard calls `POST /api/wizard-quit` → CLI deletes `out/previews/`.
58
+
59
+ **After save:** `POST /api/save-config` also deletes `out/previews/` before CLI exits (preview garbage collection).
60
+
56
61
  ---
57
62
 
58
63
  ## Remote client flow — `customize-ui` (fallback only)
@@ -139,7 +144,7 @@ For **every** section in the diff (`Changed`, `Added`, `Removed`):
139
144
 
140
145
  ### Step 4 — Apply to codebase (Phase 6c)
141
146
 
142
- Follow [`apply-ui-config.md`](apply-ui-config.md) using **`survey-ui-config.final.json`** as input.
147
+ Follow [`wizard-post-customize-build.md`](wizard-post-customize-build.md) (ordered checklist + format matrix), then [`apply-ui-config.md`](apply-ui-config.md) path tables using **`survey-ui-config.final.json`** (EC2) or **`survey-ui-config.json`** (local) as input.
143
148
 
144
149
  Order:
145
150
 
@@ -286,6 +291,7 @@ npx cfm-sdk fetch-ui-config
286
291
 
287
292
  | Doc | Role |
288
293
  |-----|------|
294
+ | [`wizard-post-customize-build.md`](wizard-post-customize-build.md) | Phase 6c runbook — all question formats + verify/build |
289
295
  | [`apply-ui-config.md`](apply-ui-config.md) | Complete config path → file mapping |
290
296
  | [`wizard-api.md`](wizard-api.md) | Poll endpoint, complete payload |
291
297
  | [`wizard-question-type-styling.md`](wizard-question-type-styling.md) | Per-type CSS vars |