@explorer02/cfm-survey-sdk 0.2.2 → 0.2.4

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 (113) hide show
  1. package/dist/cli/index.js +140 -33
  2. package/dist/cli/index.mjs +140 -33
  3. package/dist/index.js +1 -1
  4. package/dist/index.mjs +1 -1
  5. package/package.json +8 -1
  6. package/postinstall.js +8 -5
  7. package/templates/AGENT.md +62 -17
  8. package/templates/deploy-wizard-to-s3.sh +52 -0
  9. package/templates/docs/00-integration/agent-execution-flow.md +281 -0
  10. package/templates/docs/00-integration/agent-operating-contract.md +260 -0
  11. package/templates/docs/00-integration/analytics-events-catalog.md +54 -0
  12. package/templates/docs/00-integration/apply-ui-config.md +365 -0
  13. package/templates/docs/00-integration/canonical-survey-fixtures.md +94 -0
  14. package/templates/docs/00-integration/client-integration-guide.md +10 -8
  15. package/templates/docs/00-integration/client-lib-folder.md +115 -0
  16. package/templates/docs/00-integration/component-checklist.md +90 -54
  17. package/templates/docs/00-integration/constraints.md +13 -5
  18. package/templates/docs/00-integration/custom-field-logic-and-navigation.md +56 -0
  19. package/templates/docs/00-integration/display-logic-and-navigation.md +16 -1
  20. package/templates/docs/00-integration/file-upload-aws.md +116 -0
  21. package/templates/docs/00-integration/logic-fields-catalog.md +105 -0
  22. package/templates/docs/00-integration/partial-save-and-recovery.md +24 -0
  23. package/templates/docs/00-integration/progress.md +4 -2
  24. package/templates/docs/00-integration/question-type-sdk-matrix.md +11 -9
  25. package/templates/docs/00-integration/setup.md +15 -3
  26. package/templates/docs/00-integration/skip-logic-and-navigation.md +1 -1
  27. package/templates/docs/00-integration/survey-lifecycle-analytics.md +1 -1
  28. package/templates/docs/00-integration/ui-customization-wizard.md +144 -0
  29. package/templates/docs/00-integration/useSurveySDK.md +35 -1
  30. package/templates/docs/00-integration/wizard-api.md +134 -0
  31. package/templates/docs/00-integration/wizard-config-handoff.md +246 -0
  32. package/templates/docs/00-integration/wizard-preview-build-guide.md +400 -0
  33. package/templates/docs/00-integration/wizard-question-type-styling.md +195 -0
  34. package/templates/docs/01-components/01-survey-page.md +18 -8
  35. package/templates/docs/01-components/02-question.md +2 -2
  36. package/templates/docs/01-components/03-rating-scale.md +12 -18
  37. package/templates/docs/01-components/05-csat-matrix-scale.md +18 -26
  38. package/templates/docs/01-components/06-likert-matrix-scale.md +19 -38
  39. package/templates/docs/01-components/07-slider-matrix-scale.md +48 -33
  40. package/templates/docs/01-components/08-file-upload-scale.md +15 -52
  41. package/templates/docs/01-components/09-custom-slider-track.md +15 -25
  42. package/templates/docs/01-components/10-header-footer.md +23 -4
  43. package/templates/docs/01-components/11-progress-bar.md +14 -6
  44. package/templates/docs/01-components/13-matrix-dropdown.md +28 -33
  45. package/templates/docs/01-components/17-heatmap-scale.md +4 -4
  46. package/templates/docs/01-components/18-rank-order-scale.md +24 -31
  47. package/templates/docs/01-components/19-survey-sticky-chrome.md +79 -0
  48. package/templates/docs/01-components/README.md +2 -2
  49. package/templates/docs/02-reference/question-types/10-slider-matrix.md +38 -26
  50. package/templates/docs/02-reference/question-types/11-file-upload.md +36 -21
  51. package/templates/docs/02-reference/question-types/README.md +11 -1
  52. package/templates/docs/02-reference/routing-table.md +1 -0
  53. package/templates/docs/02-reference/value-derivation.md +1 -1
  54. package/templates/docs/03-ui-specs/00-question-shell.md +10 -0
  55. package/templates/docs/03-ui-specs/01-rating.md +28 -2
  56. package/templates/docs/03-ui-specs/02-radio.md +94 -24
  57. package/templates/docs/03-ui-specs/03-text.md +12 -1
  58. package/templates/docs/03-ui-specs/04-csat.md +90 -26
  59. package/templates/docs/03-ui-specs/06-slider.md +3 -1
  60. package/templates/docs/03-ui-specs/07-matrix-cfm.md +74 -35
  61. package/templates/docs/03-ui-specs/08-matrix-csat-rating.md +50 -16
  62. package/templates/docs/03-ui-specs/09-slider-matrix.md +70 -26
  63. package/templates/docs/03-ui-specs/10-file-upload.md +52 -20
  64. package/templates/docs/03-ui-specs/11-text-and-media.md +4 -0
  65. package/templates/docs/03-ui-specs/12-survey-chrome.md +92 -5
  66. package/templates/docs/03-ui-specs/13-heatmap.md +21 -3
  67. package/templates/docs/03-ui-specs/14-rank-order.md +108 -28
  68. package/templates/docs/03-ui-specs/README.md +11 -7
  69. package/templates/docs/03-ui-specs/shared/custom-slider-track.md +28 -35
  70. package/templates/docs/03-ui-specs/shared/matrix-dropdown.md +1 -1
  71. package/templates/docs/MANIFEST.json +187 -6
  72. package/templates/docs/index.md +116 -116
  73. package/templates/docs/templates/CsatMatrixScale.tsx +637 -0
  74. package/templates/docs/templates/CustomSliderTrack.tsx +144 -0
  75. package/templates/docs/templates/FileUploadScale.tsx +262 -0
  76. package/templates/docs/templates/HeatmapScale.tsx +114 -0
  77. package/templates/docs/templates/LikertMatrixScale.tsx +414 -0
  78. package/templates/docs/templates/MatrixDropdown.tsx +216 -0
  79. package/templates/docs/templates/Question.tsx +3 -0
  80. package/templates/docs/templates/RankOrderScale.tsx +353 -0
  81. package/templates/docs/templates/RatingScale.tsx +129 -0
  82. package/templates/docs/templates/SliderMatrixScale.tsx +248 -0
  83. package/templates/docs/templates/SurveyStickyChrome.tsx +24 -0
  84. package/templates/docs/templates/customFieldValues.ts +36 -0
  85. package/templates/docs/templates/implementation_plan.md +75 -8
  86. package/templates/docs/templates/labelStyles.ts +33 -0
  87. package/templates/docs/templates/selectionStyles.ts +100 -0
  88. package/templates/docs/templates/survey-inventory.schema.json +28 -23
  89. package/templates/docs/templates/surveyUiIcons.tsx +63 -0
  90. package/templates/docs/templates/surveyUiScaleUtils.ts +51 -0
  91. package/templates/docs/templates/verify-agent-build.sh +151 -0
  92. package/templates/preview-harness/preview-bridge.inline.js +201 -0
  93. package/templates/preview-harness/previewPages.js +108 -0
  94. package/templates/preview-harness/previewPages.ts +298 -0
  95. package/templates/preview-harness/vite-app/src/PreviewConfigContext.tsx +67 -0
  96. package/templates/preview-harness/vite-app/src/QuestionPreview.tsx +122 -0
  97. package/templates/preview-harness/vite-app/src/SurveyPagePreview.tsx +75 -0
  98. package/templates/preview-harness/vite-app/src/fixtures/questions.ts +311 -0
  99. package/templates/preview-harness/vite-app/src/globals.css +16 -0
  100. package/templates/preview-harness/vite-app/src/mount.tsx +9 -0
  101. package/templates/preview-harness/vite-app/src/preview-live-overrides.css +101 -0
  102. package/templates/preview-harness/vite-app/stubs/next-dynamic.tsx +25 -0
  103. package/templates/preview-harness/vite-app/stubs/next-image.tsx +29 -0
  104. package/templates/previewBridge.ts +153 -0
  105. package/templates/survey-theme.css +295 -0
  106. package/templates/survey-ui-config.schema.json +213 -0
  107. package/templates/wizard-dist/assets/PreviewMock-DgHfrVeb.js +1 -0
  108. package/templates/wizard-dist/assets/TypePanel-CFVC3Ptn.js +1 -0
  109. package/templates/wizard-dist/assets/index-BhWM50Yu.css +1 -0
  110. package/templates/wizard-dist/assets/index-DYK3X1e5.js +34 -0
  111. package/templates/wizard-dist/assets/vendor-BwkXDkd3.js +17 -0
  112. package/templates/wizard-dist/index.html +20 -0
  113. package/templates/wizard.html +13 -1129
@@ -0,0 +1,260 @@
1
+ # Agent Operating Contract — Anti-Hallucination Guide
2
+
3
+ > **Read with** [`agent-execution-flow.md`](agent-execution-flow.md) and [`index.md`](../index.md).
4
+ > This doc tells the **client-side coding agent** exactly how to use SDK docs — and what is **forbidden** to invent.
5
+
6
+ **Prime directive:** If a behavior, API, file path, CSS variable, answer shape, or CLI command is **not** written in these docs (or copied from `docs/templates/`), **do not implement it from memory**.
7
+
8
+ ---
9
+
10
+ ## 1. Authoritative source hierarchy
11
+
12
+ Use sources **only** in this order. Lower items never override higher ones.
13
+
14
+ | Priority | Source | Use for |
15
+ |----------|--------|---------|
16
+ | **1** | [`MANIFEST.json`](../MANIFEST.json) | Phase order, `typeLiterals`, per-type `blueprint` / `reference` / `uiSpec` paths |
17
+ | **2** | [`agent-execution-flow.md`](agent-execution-flow.md) | Pipeline, client questions, phase gates |
18
+ | **3** | This file | Anti-hallucination rules, doc routing, verification |
19
+ | **4** | `00-integration/*` | Wiring, constraints, wizard, deploy |
20
+ | **5** | `01-components/*` + `03-ui-specs/*` | UI anatomy per type |
21
+ | **6** | `02-reference/*` | Data shapes, exports, value derivation |
22
+ | **7** | `docs/templates/*` | Copy-paste starting code (`Question.tsx`, scales, libs) |
23
+
24
+ ### Forbidden sources (never use to implement)
25
+
26
+ | Forbidden | Why |
27
+ |-----------|-----|
28
+ | `packages/sdk/src/**` or `node_modules/.../src/**` | Internal SDK — not a public contract |
29
+ | `apps/client/**` | Monorepo snapshot — may be stale; not agent deliverable |
30
+ | Legacy `survey-config.json` | Replaced by `survey-ui-config.json` + wizard |
31
+ | Training memory / other survey libs | Wrong answer shapes, wrong hooks, wrong types |
32
+ | Guessing from component names alone | Types and helpers are defined in docs only |
33
+
34
+ **If two docs conflict:** `MANIFEST.json` + `agent-execution-flow.md` win. Open an issue in the monorepo — do not pick a guess.
35
+
36
+ ---
37
+
38
+ ## 2. Read-before-write protocol (mandatory)
39
+
40
+ **Never write or edit React/TS/CSS until the listed docs for the current phase are read.**
41
+
42
+ ### Phase gate table
43
+
44
+ | Phase | Read these files **before any code** | Extract and record |
45
+ |-------|--------------------------------------|--------------------|
46
+ | **0** | `agent-operating-contract.md`, `agent-execution-flow.md`, `index.md`, `MANIFEST.json` | Framework, `typeLiterals`, branding notes |
47
+ | **1** | `setup.md` (framework section) | Install list, AWS export flags if prompt mentions AWS |
48
+ | **2** | `useSurveySDK.md` | `instanceId` wiring location — then **ask client for JWT** |
49
+ | **3** | `client-integration-guide.md`, `question-type-sdk-matrix.md`, logic + lifecycle docs per MANIFEST phase 3 | `onAction` shapes, `state.answers`, visibility helpers |
50
+ | **4** | `component-checklist.md`, `implementation_plan.md` template, `00-question-shell.md`, `12-survey-chrome.md`, **per-type** MANIFEST routes | Inventory table in `implementation_plan.md` §3b |
51
+ | **5** | `constraints.md`, `wizard-preview-build-guide.md`, `wizard-question-type-styling.md`, **each** `03-ui-specs/{type}.md` in inventory | Tokens, `data-cfm-*`, selection pattern |
52
+ | **6** | `constraints.md`, `component-checklist.md` Step 3–4 | Run `verify-agent-build.sh` — fix failures |
53
+ | **6b** | `ui-customization-wizard.md`, `wizard-api.md` | CLI env vars — only if client said **yes** |
54
+ | **6c** | `apply-ui-config.md`, `wizard-question-type-styling.md` | UI tokens only |
55
+ | **7** | `aws-deploy.md` or deploy section in `setup.md` | Deploy target from prompt / config |
56
+
57
+ ### Per-question-type gate (Phase 4–5)
58
+
59
+ For **each** `question.type` in the fetched survey, read **all three** MANIFEST paths before touching that component:
60
+
61
+ ```
62
+ questionTypes.{TYPE}.blueprint → 01-components/*
63
+ questionTypes.{TYPE}.reference → 02-reference/question-types/*
64
+ questionTypes.{TYPE}.uiSpec → 03-ui-specs/*
65
+ ```
66
+
67
+ **Blocking rule:** If you have not read the ui-spec for a type, you may not implement that type.
68
+
69
+ ---
70
+
71
+ ## 3. Doc routing — task → exact files
72
+
73
+ Use this table when deciding what to read. **Do not substitute similar-sounding docs.**
74
+
75
+ | Task | Read (in order) | Do not guess |
76
+ |------|-----------------|--------------|
77
+ | Wire `useSurveySDK` | `useSurveySDK.md`, `client-integration-guide.md` | Hook return field names |
78
+ | Dispatch questions | `templates/Question.tsx`, `question-type-sdk-matrix.md`, `routing-table.md` | `subType`, stub fallbacks |
79
+ | NPS scale | `03-ui-specs/01-rating.md`, `templates/RatingScale.tsx`, `value-derivation.md` | `optionValue`, `accentColor` on options |
80
+ | MCQ | `03-ui-specs/02-radio.md`, `question-type-sdk-matrix.md#mcq` | `isMultiSelect` — use `selectionMode` |
81
+ | Matrix CFM | `03-ui-specs/07-matrix-cfm.md`, `templates/LikertMatrixScale.tsx`, `canonical-survey-fixtures.md` | Bare radio grid without row labels |
82
+ | Matrix CSAT/Rating | `03-ui-specs/04-csat.md`, `08-matrix-csat-rating.md`, `templates/CsatMatrixScale.tsx` | Separate RatingMatrixScale file |
83
+ | Slider matrix | `03-ui-specs/09-slider-matrix.md`, `templates/SliderMatrixScale.tsx` | Orphan slider without header row |
84
+ | File upload | `03-ui-specs/10-file-upload.md`, `file-upload-aws.md` | Raw `File[]` in submit payload |
85
+ | Heatmap | `03-ui-specs/13-heatmap.md`, `templates/heatmapCoords.ts` | Region overlays on respondent UI |
86
+ | Rank order | `03-ui-specs/14-rank-order.md`, `templates/RankOrderScale.tsx` | Client-side re-shuffle |
87
+ | Custom fields | `custom-field-logic-and-navigation.md`, `templates/customFieldValues.ts` | Skip wiring hook + Question prop |
88
+ | Wizard chrome | `wizard-preview-build-guide.md`, `03-ui-specs/12-survey-chrome.md` | External logo URLs |
89
+ | Wizard per-type colors | `wizard-question-type-styling.md` | Hardcoded Telekom hex for wizard tokens |
90
+ | Selection colors | `wizard-question-type-styling.md`, `templates/selectionStyles.ts` | Single color for ring + fill — use annulus pattern |
91
+ | Matrix column labels | `wizard-question-type-styling.md`, `templates/labelStyles.ts` | Hint labels on CFM column headers |
92
+ | Logo seed | `constraints.md` §4, `wizard-api.md`, `parse-client-header` behavior in wizard docs | Random `public/logo_*` scan |
93
+ | Wizard session (wait) | `wizard-config-handoff.md`, `ui-customization-wizard.md` |
94
+ | Apply all wizard paths | `apply-ui-config.md` | Changing `Question.tsx` dispatch |
95
+ | Deploy AWS | `aws-deploy.md`, `setup.md#nextjs-aws-static-export` | `assetPrefix: "/"` for static export |
96
+
97
+ ---
98
+
99
+ ## 4. Hallucination blocklist — never invent these
100
+
101
+ | ❌ Hallucination | ✅ Doc-backed truth |
102
+ |-----------------|---------------------|
103
+ | `question.subType` routing | Flat `question.type` — 11 literals in `MANIFEST.json` `typeLiterals` |
104
+ | `state.values` for answers | `state.answers` — `MANIFEST.json` `hookContract.answersField` |
105
+ | `isMultiSelect` on MCQ | `selectionMode: 'single' \| 'multiple'` |
106
+ | Default branch: "Not implemented" | Copy `templates/Question.tsx` — all types explicit |
107
+ | Import `@repo/sdk/src/...` | Package root only — `hookContract.forbiddenImports` |
108
+ | Implement from `apps/client` | Copy `docs/templates/*` |
109
+ | `npx cfm-sdk customize` before build | Build + verify first; AWS = `customize-ui` |
110
+ | `survey-config.json` | `survey-ui-config.json` + schema in `templates/` |
111
+ | NPS `option.accentColor` | Derive from value — `value-derivation.md` |
112
+ | Matrix value = column label text | `matrixColumnStoredValue(col)` → column **`id`** |
113
+ | FILE_UPLOAD answer = `File[]` | `UploadedFileAnswer[]` after presigned upload |
114
+ | CFM column headers = hint labels | `matrixColumnLabelStyle()` — label **items** only |
115
+ | Focus ring = cell fill (same element) | Ring = border + dot; cell selected = annulus between |
116
+ | Wizard optional → skip `survey-theme.css` | Wizard-ready build is **mandatory** Phase 5 |
117
+ | Logo from any `public/logo_*` | `Header.tsx` `data-cfm-logo` / `data-cfm-logo-text` contract |
118
+ | `getVisible*` without 4th arg when CRM logic exists | Pass `customFieldValues` — `hookContract.visibilityHelpers` |
119
+ | New question types or SDK actions | Only documented `onAction` types in `useSurveySDK.md` |
120
+ | Placeholder unstable inline object | Stable ref + `useMemo` on hook options |
121
+ | Slider matrix without tick header | `canonical-survey-fixtures.md` + ui-spec |
122
+ | RATING_MATRIX as new component | Reuse `CsatMatrixScale.tsx` |
123
+ | Killed CLI during wizard poll | Keep running until `Configuration ready`; see `wizard-config-handoff.md` |
124
+ | Applied before client submitted | Wait for CLI exit 0; use `.final.json` not seed |
125
+ | Skipped diff paths | Read entire `survey-ui-config.diff.md`; apply every path |
126
+
127
+ ---
128
+
129
+ ## 5. Copy-first code generation
130
+
131
+ **Default action = copy template, then extend.** Not rewrite from ui-spec prose.
132
+
133
+ | Always copy first | Destination |
134
+ |-------------------|-------------|
135
+ | `templates/Question.tsx` | `src/components/Question.tsx` |
136
+ | `templates/survey-theme.css` | `src/styles/survey-theme.css` |
137
+ | `templates/selectionStyles.ts` | `src/lib/surveyUi/selectionStyles.ts` |
138
+ | `templates/labelStyles.ts` | `src/lib/surveyUi/labelStyles.ts` |
139
+ | `templates/previewBridge.ts` | `src/lib/previewBridge.ts` |
140
+ | Per-inventory scale templates | `src/components/` |
141
+
142
+ **After copy, only change:**
143
+
144
+ - Branding tokens (`var(--cfm-*)`) per client prompt
145
+ - Imports paths for project alias
146
+ - Cosmetic styling per `wizard-question-type-styling.md`
147
+
148
+ **Never change in copied dispatcher:**
149
+
150
+ - `onAction` payload shapes
151
+ - `question.type` switch cases / missing branches
152
+ - Visibility helper call signatures
153
+
154
+ ---
155
+
156
+ ## 6. Phase completion evidence
157
+
158
+ Do **not** tell the client a phase is done without evidence.
159
+
160
+ | Phase | Required evidence |
161
+ |-------|-------------------|
162
+ | **4** | `implementation_plan.md` exists; §3b lists every fetched `question.type` |
163
+ | **5** | All inventory components exist; draft `survey-ui-config.json` present |
164
+ | **6** | `bash templates/verify-agent-build.sh` exit 0; `npm run build` exit 0; dev server loads |
165
+ | **6b** | Client explicitly said yes; `survey-ui-config.json` updated by CLI |
166
+ | **6c** | Tokens synced per `apply-ui-config.md`; verify script re-run |
167
+ | **7** | Deploy only after INPUT 4 yes |
168
+
169
+ ### Verification commands (run, do not assume)
170
+
171
+ ```bash
172
+ # From project root — paths may vary; see component-checklist.md
173
+ bash templates/verify-agent-build.sh
174
+ npm run build
175
+ grep -r "not yet implemented" src/ components/ app/ # must be empty
176
+ grep -r "subType" src/components/Question.tsx # must be empty
177
+ ```
178
+
179
+ ---
180
+
181
+ ## 7. When uncertain — stop and read
182
+
183
+ | Situation | Action | Do not |
184
+ |-----------|--------|--------|
185
+ | Field not in ui-spec config table | Check `02-reference/config-field-index.md` | Add imaginary prop |
186
+ | Matrix labels missing in API | Read `canonical-survey-fixtures.md` | Omit label row |
187
+ | Unknown `question.type` in survey | Re-fetch; check `typeLiterals` | Add `default` stub |
188
+ | Wizard token name unclear | Read `wizard-question-type-styling.md` + `survey-theme.css` | Invent `--cfm-*` name |
189
+ | CLI fails | Read error + `constraints.md` troubleshooting | Retry random flags |
190
+ | Custom field id `_c_…` | Read `custom-field-logic-and-navigation.md` | Ignore in visibility |
191
+ | AWS vs Vercel deploy | Prompt keywords + `survey-ui-config.json` `deploy.target` | Assume Vercel |
192
+
193
+ **Uncertainty rule:** Open the MANIFEST-routed doc for that topic. If still absent, ask the client — do not implement.
194
+
195
+ ---
196
+
197
+ ## 8. Client communication rules
198
+
199
+ ### Exact questions (only these four)
200
+
201
+ 1. *(Prompt — usually provided at start)*
202
+ 2. *"Please provide your survey instance ID (JWT token)."* — Phase 2 only
203
+ 3. *"Your survey is running locally. Would you like to customize the UI through the web wizard?"* — Phase 6 only
204
+ 4. *"Your survey is built and verified. Ready to deploy to production?"* — Phase 7 only
205
+
206
+ **Do not ask:** architecture opinions, stub approval, wizard before build, or "should I read the docs."
207
+
208
+ ### Status updates to client
209
+
210
+ When reporting progress, cite **phase number** and **doc section** completed, e.g.:
211
+
212
+ - "Phase 4 complete — inventory: NPS_SCALE, MCQ, CFM_MATRIX per `implementation_plan.md` §3b"
213
+ - "Phase 5 — wired `--cfm-matrix-selected` / `--cfm-input-focus-ring` per `wizard-question-type-styling.md`"
214
+
215
+ Do not claim "integrated SDK" without naming hook doc and verify result.
216
+
217
+ ---
218
+
219
+ ## 9. Wizard-ready build checklist (Phase 5 — non-optional)
220
+
221
+ Even when the client will skip the wizard, verify each item:
222
+
223
+ - [ ] `src/styles/survey-theme.css` copied from template
224
+ - [ ] `selectionStyles.ts` + `labelStyles.ts` in `src/lib/surveyUi/`
225
+ - [ ] `./survey-ui-config.json` draft at project root
226
+ - [ ] `data-cfm-logo` or `data-cfm-logo-text`, `data-cfm-btn-next`, `data-cfm-btn-back`, `data-cfm-survey-title` in chrome
227
+ - [ ] Scale components use `var(--cfm-*)` for wizard-controlled tokens
228
+ - [ ] Selection pattern: focus ring = border + dot; cell selected = annulus
229
+ - [ ] `previewBridge.ts` + layout init for local `customize`
230
+
231
+ ---
232
+
233
+ ## 10. Quick self-audit before handoff
234
+
235
+ Answer **yes** to all before telling the client the survey is ready:
236
+
237
+ 1. Did I read `agent-operating-contract.md` and `agent-execution-flow.md` at session start?
238
+ 2. Did I read ui-specs for **every** type in the fetched survey?
239
+ 3. Did I copy `Question.tsx` from templates (not write a new dispatcher)?
240
+ 4. Are all 11 `typeLiterals` handled with no stub branch?
241
+ 5. Did `verify-agent-build.sh` pass?
242
+ 6. Did I ask wizard question only after Phase 6 verify?
243
+ 7. Did I avoid `apps/client` and SDK `/src/` imports?
244
+ 8. Are matrix row + column labels visible per `canonical-survey-fixtures.md`?
245
+ 9. Is FILE_UPLOAD using presigned flow if present?
246
+ 10. Is `customFieldValues` wired in hook **and** Question when `_c_…` ids exist?
247
+
248
+ **Any "no" → go back to the routed doc in §3; do not hand off.**
249
+
250
+ ---
251
+
252
+ ## Related docs
253
+
254
+ | Doc | Role |
255
+ |-----|------|
256
+ | [`agent-execution-flow.md`](agent-execution-flow.md) | Phase order and client inputs |
257
+ | [`component-checklist.md`](component-checklist.md) | File inventory and copy table |
258
+ | [`constraints.md`](constraints.md) | Hard limits (logo, imports, stubs) |
259
+ | [`question-type-sdk-matrix.md`](question-type-sdk-matrix.md) | Answer shapes + visibility per type |
260
+ | [`index.md`](../index.md) | Master index |
@@ -0,0 +1,54 @@
1
+ # Analytics Events Catalog
2
+
3
+ > Consolidated SDK telemetry and client-wired lifecycle events. Most events log to console as `[SDK:ANALYTICS]` — **no client code required** unless noted.
4
+
5
+ See also: [`survey-lifecycle-analytics.md`](survey-lifecycle-analytics.md) · [`client-integration-guide.md`](client-integration-guide.md) § Debug logging
6
+
7
+ ---
8
+
9
+ ## Client must wire
10
+
11
+ | Event / action | How | When |
12
+ |----------------|-----|------|
13
+ | Mark as started | `onAction({ type: 'SCROLL' })` once on first window scroll | First content engagement |
14
+ | Question viewed | `onAction({ type: 'RECORD_QUESTION_VIEW', payload: { questionId } })` via IntersectionObserver on `#question.id` | Question 50% visible |
15
+ | Partial save feedback | Monitor `partialSaveResults.isLoading` / `.error` | When `savePartialResponse: true` |
16
+
17
+ First `CHANGE` also triggers mark-as-started (SDK) — no extra client call.
18
+
19
+ ---
20
+
21
+ ## SDK-emitted (always — no `debug` flag required)
22
+
23
+ | Event | When | Metadata highlights |
24
+ |-------|------|---------------------|
25
+ | `fetch_survey_latency` | Survey GET completes | durationMs, status, payloadSize (UTF-8 KB) |
26
+ | `fetch_survey_error` | Survey GET fails | status, url, message |
27
+ | `submit_survey_latency` | Submit POST completes | durationMs, status |
28
+ | `submit_survey_error` | Submit fails | status, message |
29
+ | `page_time_spent` | Leaving a content page | pageIndex, durationMs |
30
+ | `optional_question_skipped` | Optional question left blank on forward nav | questionId, pageIndex |
31
+ | `backtrack_revisited` | User returns to earlier page and changes answers | fromPage, toPage, changedAnswers |
32
+ | `question_viewed` | After RECORD_QUESTION_VIEW deduped | questionId |
33
+ | `display_logic_matched` | Display condition newly true | questionId, logic details |
34
+ | `answer_logic_matched` | Answer-logic sub-entity newly visible | entity scope |
35
+ | `question_variant_matched` | Variant text switches | variant id |
36
+ | `end_page_logic_matched` | Resolved end page changes | endPageId |
37
+ | `skip_logic_triggered` | Skip logic newly activates | skip target |
38
+
39
+ ---
40
+
41
+ ## Post-submit rollups
42
+
43
+ | Event | When | Contents |
44
+ |-------|------|----------|
45
+ | `survey_session_summary` | Successful submit | `completed`, `maxVisitedPageIndex`, `totalDurationMs`, question counts (total/answered/skipped), `validationErrorsCount`, `backtrackCount`, `validationHistory` |
46
+ | `logic_session_summary` | Successful submit | Per-logic-kind counts, viewed vs on-path-not-viewed, final end page, `logicEventTimeline` audit (console.table) |
47
+
48
+ Enable `debug: true` in hook options for additional `[SDK:INFO]` transition logs (display/answer/variant/end/skip matches on answer change).
49
+
50
+ ---
51
+
52
+ ## Validation error tracking
53
+
54
+ SDK increments validation error counts and records per-page error history in session summary. Client displays `state.validationErrors[questionId]` banners and uses `id={question.id}` for scroll-to-error.
@@ -0,0 +1,365 @@
1
+ # Apply UI Config (`survey-ui-config.json`)
2
+
3
+ > **Phase 6c** — after wizard handoff. Read [`wizard-config-handoff.md`](wizard-config-handoff.md) first (wait protocol + review artifacts).
4
+ > **Build-time contract:** [`wizard-preview-build-guide.md`](wizard-preview-build-guide.md).
5
+ > **Per-type tokens:** [`wizard-question-type-styling.md`](wizard-question-type-styling.md).
6
+
7
+ ## Which file to apply from
8
+
9
+ | Wizard mode | Apply source | When |
10
+ |-------------|--------------|------|
11
+ | AWS review (default) | `survey-ui-config.final.json` | After CLI prints `Configuration ready` |
12
+ | AWS `--apply` | `survey-ui-config.json` | Immediately after CLI exits |
13
+ | Local `customize` | `survey-ui-config.json` | After `UI configuration saved` |
14
+
15
+ **AWS review mode:** `survey-ui-config.json` remains **seed** until `npx cfm-sdk confirm-ui-config` — always apply codebase from **`.final.json`**.
16
+
17
+ ---
18
+
19
+ ## Scope (UI-only)
20
+
21
+ **May change:** CSS vars, chrome components, nav labels, logo path, placeholders, debug flag, cosmetic scale tokens.
22
+
23
+ **Must NOT change:** `Question.tsx` dispatch, `onAction` payloads, answer shapes, visibility helpers, matrix routing, file upload presigned flow.
24
+
25
+ ---
26
+
27
+ ## Apply workflow (ordered — do not skip steps)
28
+
29
+ ### 1. Capture and audit
30
+
31
+ ```bash
32
+ # AWS review mode — mandatory read
33
+ cat survey-ui-config.diff.md
34
+ ```
35
+
36
+ - Count entries: `changed + added + removed` from CLI output or diff JSON
37
+ - Open `survey-ui-config.final.json` (or `survey-ui-config.json` for local)
38
+
39
+ ### 2. Validate
40
+
41
+ - JSON parses without error
42
+ - Validate against `templates/survey-ui-config.schema.json`
43
+ - `surveyTypes` matches fetched survey inventory
44
+
45
+ ### 3. Sync CSS (full regen — not diff-only)
46
+
47
+ **Regenerate entire `src/styles/survey-theme.css`** from final config so derived tokens stay consistent.
48
+
49
+ Use the mapping tables below: every config field → `--cfm-*` var. Reference implementation: wizard `configToCssVars()` (same var names as `templates/survey-theme.css`).
50
+
51
+ Minimum global vars from `global.colorScheme` + `global.theme`:
52
+
53
+ ```css
54
+ :root {
55
+ --cfm-primary: /* global.colorScheme.primary */;
56
+ --cfm-accent: /* global.colorScheme.accent */;
57
+ --cfm-matrix-selected: /* global.theme.cellSelectedColor */;
58
+ --cfm-input-focus-ring: /* global.theme.focusRingColor */;
59
+ --cfm-mcq-selected-accent: var(--cfm-matrix-selected);
60
+ /* … all vars in templates/survey-theme.css */
61
+ }
62
+ ```
63
+
64
+ Import in `globals.css`: `@import './styles/survey-theme.css';`
65
+
66
+ ### 4. Apply content patches (`data-cfm-*`)
67
+
68
+ | Config path | DOM target | Attribute / content |
69
+ |-------------|------------|---------------------|
70
+ | `global.surveyTitle` | Intro / title slot | `data-cfm-survey-title` text |
71
+ | `global.companyName` | Header | `data-cfm-company` text |
72
+ | `global.thankYouMessage` | End page | `data-cfm-thank-you` text |
73
+ | `global.browserTabTitle` | `layout.tsx` / metadata | `document.title` |
74
+ | `global.buttons.next` | SurveyPage | `data-cfm-btn-next` text |
75
+ | `global.buttons.back` | SurveyPage | `data-cfm-btn-back` text |
76
+ | `global.buttons.submit` | SurveyPage submit label | button text |
77
+ | `global.logo.fileName` | Header | `data-cfm-logo` src=`/${fileName}` (or `./${fileName}` for static AWS export); remove `data-cfm-logo-text` when image |
78
+ | `global.logo.url` | Agent reference only | Public CloudFront URL after wizard — download to `public/`; do **not** use as `img src` in the survey |
79
+ | `global.footer.copyrightText` | Footer | `data-cfm-copyright` |
80
+ | `global.footer.links[]` | Footer | `data-cfm-footer-links` (render links) |
81
+ | `questionTypes.MCQ.optionStyle` | `:root` or survey wrapper | `data-cfm-mcq-style` |
82
+ | `questionTypes.NPS_SCALE.buttonStyle` | `:root` | `data-cfm-nps-button-style` |
83
+ | `questionTypes.FILE_UPLOAD.dropzoneStyle` | `:root` | `data-cfm-dropzone-style` |
84
+
85
+ ### 5. Apply layout toggles (chrome only)
86
+
87
+ | `global.layout.*` | Apply in |
88
+ |-------------------|----------|
89
+ | `showHeader` | `SurveyPage` — conditional `<Header />` |
90
+ | `showFooter` | Conditional `<Footer />` |
91
+ | `showProgressBar` | `SurveyStickyChrome` / `ProgressBar` |
92
+ | `showLanguageSwitcher` | `LanguageSelector` |
93
+ | `showNextButton` / `showBackButton` | Nav button visibility |
94
+ | `showQuestionNumbers` | Question title prefix |
95
+ | `showRequiredAsterisk` | Required `*` in shell |
96
+ | `width` | Container `max-w-*` via `--cfm-max-width` |
97
+ | `borderStyle` | `--cfm-border-radius` |
98
+ | `fontStyle` | `--cfm-font-family` |
99
+
100
+ | `global.header.*` | CSS vars on `:root` (see § Header) |
101
+ | `global.footer.*` | CSS vars + footer structure |
102
+
103
+ ### 6. Apply hook options
104
+
105
+ | Config path | Wire in |
106
+ |-------------|---------|
107
+ | `placeholders.*` | `useSurveySDK({ options: { placeholders } })` — stable ref |
108
+ | `customFields` | `src/lib/customFieldValues.ts` + hook + `Question` prop |
109
+ | `debug.enabled` | `debug: true` in hook options |
110
+
111
+ ### 7. Per-type tokens (inventory only)
112
+
113
+ For each type in `surveyTypes[]`, apply `questionTypes.{TYPE}` per § Question types below.
114
+
115
+ ### 8. Logo file
116
+
117
+ - Local / `confirm-ui-config`: file in `public/{fileName}`
118
+ - If missing after confirm: re-run with `CFM_INSTANCE_ID` + `CFM_DEPLOY_API_BASE`
119
+
120
+ ### 9. Promote active config (AWS review only)
121
+
122
+ ```bash
123
+ npx cfm-sdk confirm-ui-config
124
+ ```
125
+
126
+ Run **after** codebase apply succeeds.
127
+
128
+ ### 10. Verify nothing missed
129
+
130
+ ```bash
131
+ bash templates/verify-agent-build.sh
132
+ npm run build
133
+ ```
134
+
135
+ **Diff cross-check:** For each path in `survey-ui-config.diff.json` → `changed` + `added` + `removed`, confirm a corresponding update exists (CSS var, DOM attr, or layout branch). If a path has no mapping in this doc, search `wizard-question-type-styling.md` and `templates/survey-theme.css`.
136
+
137
+ ---
138
+
139
+ ## Complete config path → apply target
140
+
141
+ ### `global.colorScheme`
142
+
143
+ | Path | CSS variable |
144
+ |------|----------------|
145
+ | `primary` | `--cfm-primary` |
146
+ | `secondary` | `--cfm-secondary` |
147
+ | `accent` | `--cfm-accent` |
148
+ | `background` | `--cfm-background` (fallback; `theme.pageBackground` wins) |
149
+ | `text` | `--cfm-text` |
150
+ | `buttonText` | `--cfm-button-text` |
151
+
152
+ ### `global.theme` (Question card + chrome)
153
+
154
+ | Path | CSS variable / effect |
155
+ |------|----------------------|
156
+ | `pageBackground` | `--cfm-background` |
157
+ | `cardBackground` | `--cfm-card-bg` |
158
+ | `cardBorderColor` | `--cfm-card-border-color` |
159
+ | `cardPadding` | `--cfm-card-padding` |
160
+ | `cardShadowEnabled` | `--cfm-card-shadow` |
161
+ | `cellSelectedColor` | `--cfm-matrix-selected`, `--cfm-mcq-selected-accent`, `--cfm-csat-ring-color` |
162
+ | `focusRingColor` | `--cfm-input-focus-ring` |
163
+ | `selectedBackground` | `--cfm-selected-bg`, `--cfm-mcq-selected-bg` |
164
+ | `zebraRowColor` | `--cfm-zebra-row` |
165
+ | `rowBandColor` | `--cfm-row-band` |
166
+ | `validationBorder` | `--cfm-validation-border` |
167
+ | `validationBackground` | `--cfm-validation-bg` |
168
+ | `tooltipBackground` | `--cfm-tooltip-bg` |
169
+ | `progressTrackHeight` | `--cfm-progress-height` |
170
+ | `progressTrackColor` | `--cfm-progress-track` |
171
+ | `progressFillColor` | `--cfm-progress-fill` |
172
+ | `stickyChromePaddingTop` | `--cfm-sticky-pt` |
173
+ | `stickyChromePaddingBottom` | `--cfm-sticky-pb` |
174
+ | `languageSelectorBackground` | `--cfm-language-bg` |
175
+ | `languageSelectorTextColor` | `--cfm-language-text` |
176
+ | `languageSelectorBorderColor` | `--cfm-language-border` |
177
+
178
+ ### `global.header`
179
+
180
+ | Path | CSS variable |
181
+ |------|----------------|
182
+ | `height` | `--cfm-header-height` |
183
+ | `logoBoxWidth` | `--cfm-header-logo-width` |
184
+ | `logoBoxHeight` | `--cfm-header-logo-height` |
185
+ | `logoPadding` | `--cfm-header-logo-padding` |
186
+ | `logoPlacement` | `--cfm-header-logo-col`, `--cfm-header-logo-justify` |
187
+ | `showCompanyName` | `--cfm-header-show-company` |
188
+ | `companyNamePlacement` | `--cfm-header-company-col`, `--cfm-header-company-justify` |
189
+ | `companyNameFontSize` | `--cfm-header-company-size` |
190
+ | `companyNameFontWeight` | `--cfm-header-company-weight` |
191
+ | `companyNameColor` | `--cfm-header-company-color` |
192
+ | `backgroundColor` | `--cfm-header-bg` |
193
+ | `shadowEnabled` | `--cfm-header-shadow` |
194
+ | `borderBottomColor` | `--cfm-header-border` |
195
+ | `contentPaddingX` | `--cfm-header-padding-x` |
196
+
197
+ ### `global.footer`
198
+
199
+ | Path | CSS variable / DOM |
200
+ |------|-------------------|
201
+ | `backgroundColor` | `--cfm-footer-bg` |
202
+ | `textColor` | `--cfm-footer-text` |
203
+ | `linkColor` | `--cfm-footer-link` |
204
+ | `linkHoverColor` | `--cfm-footer-link-hover` |
205
+ | `showLogo` | layout flag + footer logo slot |
206
+ | `logoWidth` / `logoHeight` | `--cfm-footer-logo-width`, `--cfm-footer-logo-height` |
207
+ | `logoPlacement` | `--cfm-footer-logo-col`, grid vars |
208
+ | `copyrightText` | `data-cfm-copyright` |
209
+ | `layout` | `--cfm-footer-layout`, `--cfm-footer-inner-display` |
210
+ | `paddingY` / `paddingX` | `--cfm-footer-padding-y`, `--cfm-footer-padding-x` |
211
+ | `links[]` | `data-cfm-footer-links` |
212
+
213
+ ### `global.typography` + `global.motion`
214
+
215
+ | Path | CSS variable |
216
+ |------|----------------|
217
+ | `typography.fontFamily` | fallback for `--cfm-font-family` |
218
+ | `typography.headingWeight` | `--cfm-heading-weight` |
219
+ | `motion.durationMs` | `--cfm-motion-duration` |
220
+
221
+ ### `questionTypes.MCQ`
222
+
223
+ | Path | Apply |
224
+ |------|-------|
225
+ | `optionStyle` / `cardStyle` | `data-cfm-mcq-style` |
226
+ | `optionGap` | `--cfm-mcq-option-gap` |
227
+ | `borderRadius` | `--cfm-mcq-border-radius` |
228
+ | `optionPadding` / `cardPadding` | `--cfm-mcq-card-padding` |
229
+ | `hoverBorderColor` | `--cfm-mcq-hover-border` |
230
+ | Selection colors | from `global.theme` cellSelected + focusRing |
231
+
232
+ ### `questionTypes.TEXTFIELD`
233
+
234
+ | Path | CSS variable |
235
+ |------|----------------|
236
+ | `inputRadius` | `--cfm-input-radius` |
237
+ | `borderColor` | `--cfm-input-border` |
238
+ | `inputPadding` | `--cfm-input-padding` |
239
+ | `inputHeight` | `--cfm-input-height` |
240
+ | `placeholderColor` | `--cfm-input-placeholder` |
241
+ | `defaultPlaceholder` | placeholder text in preview / optional default |
242
+
243
+ ### `questionTypes.NPS_SCALE`
244
+
245
+ | Path | CSS variable / DOM |
246
+ |------|-------------------|
247
+ | `buttonStyle` | `data-cfm-nps-button-style` |
248
+ | `selectedFill` | `--cfm-nps-selected-fill` |
249
+ | `trackBarColor` | `--cfm-nps-track-bar` |
250
+ | `trackHighlightColor` | `--cfm-nps-track-highlight` |
251
+ | `cellSize` / `cellGap` | `--cfm-nps-cell-size`, `--cfm-nps-cell-gap` |
252
+ | `hintMinText` / `hintMaxText` | NPS anchor row text |
253
+ | `hintLabelColor` / `hintLabelBgColor` | `--cfm-hint-label-color`, `--cfm-hint-label-bg` |
254
+ | `numberLabelMode` | `--cfm-number-label-mode` |
255
+ | `monochromeNumberColor` | `--cfm-number-mono-color` |
256
+ | `individualNumberColors[n]` | `--cfm-number-color-{n}` |
257
+
258
+ ### `questionTypes.CFM_MATRIX`
259
+
260
+ | Path | CSS variable |
261
+ |------|----------------|
262
+ | `rowLabelWidth` | `--cfm-matrix-row-width` |
263
+ | `bipolarColumnWidthPercent` | `--cfm-matrix-bipolar-width` |
264
+ | `cellPadding` | `--cfm-matrix-cell-padding` |
265
+ | `columnLabelColor` / `columnLabelBgColor` | `--cfm-matrix-column-label-color`, `--cfm-matrix-column-label-bg` |
266
+
267
+ ### `questionTypes.CSAT_MATRIX` / `RATING_MATRIX`
268
+
269
+ | Path | CSS variable |
270
+ |------|----------------|
271
+ | `emojiSize` | `--cfm-csat-emoji-size` |
272
+ | `unselectedOpacity` | `--cfm-csat-unselected-opacity` |
273
+ | `cellSize` | `--cfm-csat-cell-size` |
274
+ | `tooltipBg` | `--cfm-csat-tooltip-bg` |
275
+ | `rowLabelWidth` | `--cfm-matrix-row-width` |
276
+ | `columnLabelColor` / `columnLabelBgColor` | `--cfm-csat-column-label-*` |
277
+ | Number label fields | same as NPS `--cfm-number-*` |
278
+
279
+ ### `questionTypes.SLIDER_MATRIX`
280
+
281
+ | Path | CSS variable |
282
+ |------|----------------|
283
+ | `trackColor` / `thumbColor` | slider track vars in theme |
284
+ | `tickLabelColor` / `tickLabelBgColor` | `--cfm-slider-tick-label-color`, `--cfm-slider-tick-label-bg` |
285
+ | Row band | `--cfm-row-band` from global theme |
286
+
287
+ ### `questionTypes.FILE_UPLOAD`
288
+
289
+ | Path | Apply |
290
+ |------|-------|
291
+ | `dropzoneStyle` | `data-cfm-dropzone-style` |
292
+ | `borderColor` | `--cfm-upload-border-color` |
293
+
294
+ ### `questionTypes.HEATMAP`
295
+
296
+ | Path | CSS variable |
297
+ |------|----------------|
298
+ | `pinColor` | `--cfm-heatmap-pin` |
299
+ | `pinSize` | `--cfm-heatmap-pin-size` |
300
+ | `pinBorderColor` | `--cfm-heatmap-pin-border` |
301
+
302
+ ### `questionTypes.RANK_ORDER`
303
+
304
+ | Path | CSS variable |
305
+ |------|----------------|
306
+ | `drag.itemBg` / `dropdown.itemBg` | `--cfm-rank-item-bg` |
307
+ | `drag.rankBadgeColor` / `dropdown.rankBadgeColor` | `--cfm-rank-badge` |
308
+ | `drag.itemPadding` / `itemGap` | `--cfm-rank-item-padding`, `--cfm-rank-item-gap` |
309
+ | `drag.dragHandleColor` | `--cfm-rank-handle` |
310
+ | `dropdown.selectBorderColor` | `--cfm-rank-select-border` |
311
+
312
+ ### `deploy`
313
+
314
+ | Path | Phase 7 |
315
+ |------|---------|
316
+ | `deploy.target` | `aws` → `aws-deploy.md`; `vercel` → `npx cfm-sdk deploy` |
317
+ | `deploy.autoDeploy` | informational — agent still asks INPUT 4 |
318
+
319
+ ---
320
+
321
+ ## Diff-driven apply (zero omissions)
322
+
323
+ When `survey-ui-config.diff.json` exists:
324
+
325
+ 1. Load `diff.changed`, `diff.added`, `diff.removed`
326
+ 2. For each entry, look up `entry.path` in the tables above
327
+ 3. Apply the **After** value (or remove DOM/CSS for `removed`)
328
+ 4. Track progress: `appliedCount === changed.length + added.length + removed.length`
329
+
330
+ **Categories easy to miss** (always check diff for these):
331
+
332
+ - `global.footer.links` (array — full replace)
333
+ - `global.header.showCompanyName` + placement pairs
334
+ - `questionTypes.*.individualNumberColors` (array)
335
+ - `placeholders.*` (every key)
336
+ - `customFields.*` (every `_c_` key)
337
+ - `global.theme.cellSelectedColor` + `focusRingColor` (drive all scale selections)
338
+ - `global.logo.fileName` (image swap)
339
+ - `global.logo.url` (download reference — ensure file in `public/`)
340
+
341
+ ---
342
+
343
+ ## Selection styling (verify after apply)
344
+
345
+ ```tsx
346
+ import { scaleRadioRingStyle, scaleRadioDotStyle } from '@/lib/surveyUi/selectionStyles';
347
+ ```
348
+
349
+ Ensure components use `selectionStyles.ts` — config only changes CSS vars, not component structure.
350
+
351
+ ---
352
+
353
+ ## Re-run policy
354
+
355
+ Do not re-run `customize-ui` unless the client explicitly requests another customization session. Each run overwrites review artifacts.
356
+
357
+ ---
358
+
359
+ ## Related
360
+
361
+ | Doc | Role |
362
+ |-----|------|
363
+ | [`wizard-config-handoff.md`](wizard-config-handoff.md) | Wait + capture + confirm order |
364
+ | [`wizard-question-type-styling.md`](wizard-question-type-styling.md) | Visual selection patterns |
365
+ | [`agent-operating-contract.md`](agent-operating-contract.md) | Do not change dispatch logic |