@contentful/experience-design-system-cli 2.2.1

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 (165) hide show
  1. package/README.md +532 -0
  2. package/bin/cli.js +58 -0
  3. package/dist/package.json +56 -0
  4. package/dist/src/analyze/command.d.ts +3 -0
  5. package/dist/src/analyze/command.js +175 -0
  6. package/dist/src/analyze/extract/astro.d.ts +5 -0
  7. package/dist/src/analyze/extract/astro.js +280 -0
  8. package/dist/src/analyze/extract/pipeline.d.ts +6 -0
  9. package/dist/src/analyze/extract/pipeline.js +298 -0
  10. package/dist/src/analyze/extract/react.d.ts +2 -0
  11. package/dist/src/analyze/extract/react.js +1949 -0
  12. package/dist/src/analyze/extract/slot-detection.d.ts +35 -0
  13. package/dist/src/analyze/extract/slot-detection.js +101 -0
  14. package/dist/src/analyze/extract/stencil.d.ts +2 -0
  15. package/dist/src/analyze/extract/stencil.js +293 -0
  16. package/dist/src/analyze/extract/tsx-shared.d.ts +8 -0
  17. package/dist/src/analyze/extract/tsx-shared.js +263 -0
  18. package/dist/src/analyze/extract/vue-tsx.d.ts +2 -0
  19. package/dist/src/analyze/extract/vue-tsx.js +498 -0
  20. package/dist/src/analyze/extract/vue.d.ts +5 -0
  21. package/dist/src/analyze/extract/vue.js +647 -0
  22. package/dist/src/analyze/extract/web-components.d.ts +2 -0
  23. package/dist/src/analyze/extract/web-components.js +866 -0
  24. package/dist/src/analyze/pre-classify.d.ts +17 -0
  25. package/dist/src/analyze/pre-classify.js +144 -0
  26. package/dist/src/analyze/select/command.d.ts +2 -0
  27. package/dist/src/analyze/select/command.js +256 -0
  28. package/dist/src/analyze/select/index.d.ts +6 -0
  29. package/dist/src/analyze/select/index.js +5 -0
  30. package/dist/src/analyze/select/parser.d.ts +6 -0
  31. package/dist/src/analyze/select/parser.js +53 -0
  32. package/dist/src/analyze/select/persistence.d.ts +9 -0
  33. package/dist/src/analyze/select/persistence.js +42 -0
  34. package/dist/src/analyze/select/stdout.d.ts +7 -0
  35. package/dist/src/analyze/select/stdout.js +3 -0
  36. package/dist/src/analyze/select/tui/App.d.ts +8 -0
  37. package/dist/src/analyze/select/tui/App.js +491 -0
  38. package/dist/src/analyze/select/tui/components/ComponentDetail.d.ts +20 -0
  39. package/dist/src/analyze/select/tui/components/ComponentDetail.js +43 -0
  40. package/dist/src/analyze/select/tui/components/FieldEditor.d.ts +11 -0
  41. package/dist/src/analyze/select/tui/components/FieldEditor.js +531 -0
  42. package/dist/src/analyze/select/tui/components/FinalizeDialog.d.ts +10 -0
  43. package/dist/src/analyze/select/tui/components/FinalizeDialog.js +15 -0
  44. package/dist/src/analyze/select/tui/components/HelpOverlay.d.ts +7 -0
  45. package/dist/src/analyze/select/tui/components/HelpOverlay.js +11 -0
  46. package/dist/src/analyze/select/tui/components/JsonEditor.d.ts +11 -0
  47. package/dist/src/analyze/select/tui/components/JsonEditor.js +154 -0
  48. package/dist/src/analyze/select/tui/components/JsonPanel.d.ts +11 -0
  49. package/dist/src/analyze/select/tui/components/JsonPanel.js +62 -0
  50. package/dist/src/analyze/select/tui/components/PreviewSummaryBar.d.ts +8 -0
  51. package/dist/src/analyze/select/tui/components/PreviewSummaryBar.js +29 -0
  52. package/dist/src/analyze/select/tui/components/QuitDialog.d.ts +8 -0
  53. package/dist/src/analyze/select/tui/components/QuitDialog.js +14 -0
  54. package/dist/src/analyze/select/tui/components/Sidebar.d.ts +15 -0
  55. package/dist/src/analyze/select/tui/components/Sidebar.js +48 -0
  56. package/dist/src/analyze/select/tui/components/SourcePanel.d.ts +11 -0
  57. package/dist/src/analyze/select/tui/components/SourcePanel.js +52 -0
  58. package/dist/src/analyze/select/tui/components/StatusBar.d.ts +11 -0
  59. package/dist/src/analyze/select/tui/components/StatusBar.js +6 -0
  60. package/dist/src/analyze/select/tui/components/TopBar.d.ts +10 -0
  61. package/dist/src/analyze/select/tui/components/TopBar.js +5 -0
  62. package/dist/src/analyze/select/tui/hooks/useImmediateInput.d.ts +24 -0
  63. package/dist/src/analyze/select/tui/hooks/useImmediateInput.js +68 -0
  64. package/dist/src/analyze/select/tui/hooks/useKeymap.d.ts +24 -0
  65. package/dist/src/analyze/select/tui/hooks/useKeymap.js +67 -0
  66. package/dist/src/analyze/select/tui/hooks/useSession.d.ts +19 -0
  67. package/dist/src/analyze/select/tui/hooks/useSession.js +52 -0
  68. package/dist/src/analyze/select/tui/hooks/useUndo.d.ts +8 -0
  69. package/dist/src/analyze/select/tui/hooks/useUndo.js +26 -0
  70. package/dist/src/analyze/select/types.d.ts +46 -0
  71. package/dist/src/analyze/select/types.js +20 -0
  72. package/dist/src/analyze/select-agent/command.d.ts +2 -0
  73. package/dist/src/analyze/select-agent/command.js +208 -0
  74. package/dist/src/analyze/tui/AnalyzeView.d.ts +24 -0
  75. package/dist/src/analyze/tui/AnalyzeView.js +38 -0
  76. package/dist/src/apply/api-client.d.ts +35 -0
  77. package/dist/src/apply/api-client.js +143 -0
  78. package/dist/src/apply/command.d.ts +6 -0
  79. package/dist/src/apply/command.js +787 -0
  80. package/dist/src/apply/manifest.d.ts +1 -0
  81. package/dist/src/apply/manifest.js +1 -0
  82. package/dist/src/apply/tui/SelectView.d.ts +18 -0
  83. package/dist/src/apply/tui/SelectView.js +34 -0
  84. package/dist/src/apply/tui/ServerApplyView.d.ts +32 -0
  85. package/dist/src/apply/tui/ServerApplyView.js +42 -0
  86. package/dist/src/apply/tui/ServerPreviewView.d.ts +9 -0
  87. package/dist/src/apply/tui/ServerPreviewView.js +21 -0
  88. package/dist/src/credentials-store.d.ts +8 -0
  89. package/dist/src/credentials-store.js +30 -0
  90. package/dist/src/generate/agent-runner.d.ts +86 -0
  91. package/dist/src/generate/agent-runner.js +314 -0
  92. package/dist/src/generate/command.d.ts +2 -0
  93. package/dist/src/generate/command.js +545 -0
  94. package/dist/src/generate/edit/command.d.ts +2 -0
  95. package/dist/src/generate/edit/command.js +126 -0
  96. package/dist/src/generate/prompt-builder.d.ts +18 -0
  97. package/dist/src/generate/prompt-builder.js +202 -0
  98. package/dist/src/generate/tui/GenerateView.d.ts +12 -0
  99. package/dist/src/generate/tui/GenerateView.js +10 -0
  100. package/dist/src/import/command.d.ts +2 -0
  101. package/dist/src/import/command.js +96 -0
  102. package/dist/src/import/orchestrator.d.ts +37 -0
  103. package/dist/src/import/orchestrator.js +374 -0
  104. package/dist/src/import/path-utils.d.ts +15 -0
  105. package/dist/src/import/path-utils.js +30 -0
  106. package/dist/src/import/tui/WizardApp.d.ts +10 -0
  107. package/dist/src/import/tui/WizardApp.js +906 -0
  108. package/dist/src/import/tui/steps/CredentialsStep.d.ts +15 -0
  109. package/dist/src/import/tui/steps/CredentialsStep.js +79 -0
  110. package/dist/src/import/tui/steps/DoneStep.d.ts +20 -0
  111. package/dist/src/import/tui/steps/DoneStep.js +17 -0
  112. package/dist/src/import/tui/steps/ErrorStep.d.ts +8 -0
  113. package/dist/src/import/tui/steps/ErrorStep.js +11 -0
  114. package/dist/src/import/tui/steps/GateStep.d.ts +14 -0
  115. package/dist/src/import/tui/steps/GateStep.js +20 -0
  116. package/dist/src/import/tui/steps/GenerateReviewStep.d.ts +8 -0
  117. package/dist/src/import/tui/steps/GenerateReviewStep.js +208 -0
  118. package/dist/src/import/tui/steps/PathValidationStep.d.ts +10 -0
  119. package/dist/src/import/tui/steps/PathValidationStep.js +151 -0
  120. package/dist/src/import/tui/steps/PreviewStep.d.ts +21 -0
  121. package/dist/src/import/tui/steps/PreviewStep.js +36 -0
  122. package/dist/src/import/tui/steps/RunningStep.d.ts +10 -0
  123. package/dist/src/import/tui/steps/RunningStep.js +20 -0
  124. package/dist/src/import/tui/steps/TokenInputStep.d.ts +8 -0
  125. package/dist/src/import/tui/steps/TokenInputStep.js +70 -0
  126. package/dist/src/import/tui/steps/WelcomeStep.d.ts +7 -0
  127. package/dist/src/import/tui/steps/WelcomeStep.js +33 -0
  128. package/dist/src/import/tui/steps/WizardPreviewStep.d.ts +15 -0
  129. package/dist/src/import/tui/steps/WizardPreviewStep.js +121 -0
  130. package/dist/src/import/tui/steps/preview-diff.d.ts +10 -0
  131. package/dist/src/import/tui/steps/preview-diff.js +132 -0
  132. package/dist/src/index.d.ts +1 -0
  133. package/dist/src/index.js +2 -0
  134. package/dist/src/output/format.d.ts +23 -0
  135. package/dist/src/output/format.js +110 -0
  136. package/dist/src/print/command.d.ts +2 -0
  137. package/dist/src/print/command.js +199 -0
  138. package/dist/src/print/validate/tui/ValidateView.d.ts +15 -0
  139. package/dist/src/print/validate/tui/ValidateView.js +37 -0
  140. package/dist/src/print/validate/validators/cdf-validator.d.ts +2 -0
  141. package/dist/src/print/validate/validators/cdf-validator.js +104 -0
  142. package/dist/src/print/validate/validators/dtcg-validator.d.ts +2 -0
  143. package/dist/src/print/validate/validators/dtcg-validator.js +110 -0
  144. package/dist/src/print/validate/validators/format-errors.d.ts +12 -0
  145. package/dist/src/print/validate/validators/format-errors.js +18 -0
  146. package/dist/src/program.d.ts +2 -0
  147. package/dist/src/program.js +25 -0
  148. package/dist/src/session/command.d.ts +2 -0
  149. package/dist/src/session/command.js +261 -0
  150. package/dist/src/session/db.d.ts +111 -0
  151. package/dist/src/session/db.js +1114 -0
  152. package/dist/src/session/migration.d.ts +4 -0
  153. package/dist/src/session/migration.js +117 -0
  154. package/dist/src/session/session-id.d.ts +1 -0
  155. package/dist/src/session/session-id.js +212 -0
  156. package/dist/src/session/stats.d.ts +27 -0
  157. package/dist/src/session/stats.js +89 -0
  158. package/dist/src/setup/command.d.ts +2 -0
  159. package/dist/src/setup/command.js +765 -0
  160. package/dist/src/types.d.ts +48 -0
  161. package/dist/src/types.js +1 -0
  162. package/package.json +55 -0
  163. package/skills/generate-components.md +361 -0
  164. package/skills/generate-tokens.md +194 -0
  165. package/skills/select-components.md +180 -0
@@ -0,0 +1,194 @@
1
+ # Generate Tokens — Classification Skill
2
+
3
+ ## Purpose
4
+
5
+ Classify every raw token from the input into a DTCG token tree. Output one JSON tool call per line to stdout. The CLI reads your stdout and writes each token and group directly to the pipeline database — you do not produce a JSON file.
6
+
7
+ ---
8
+
9
+ ## Prerequisites — Input
10
+
11
+ All input is embedded inline in the prompt before this file:
12
+
13
+ - **Raw token source** — the original source file as-is. This may be any format: SCSS/CSS variable declarations, a JavaScript/TypeScript token module, a JSON object, a Style Dictionary config, Tailwind config, or any other token definition format the project uses. Read it as you would any source file.
14
+ - **Token-name sidecar** — if provided, maps raw names to DTCG paths (read-only context). Use these as authoritative path assignments when present.
15
+
16
+ ---
17
+
18
+ ## Target schema
19
+
20
+ The CLI assembles your output into a DTCG token tree. Each `set_group` call produces an intermediate group node; each `set_token` call produces a leaf with `$type` and `$value`. You do not produce JSON directly — emit tool calls and the CLI writes the rows.
21
+
22
+ ---
23
+
24
+ ## Output protocol
25
+
26
+ Emit one JSON object per line. The CLI parses lines starting with `{`. Lines not starting with `{` are treated as prose and ignored — use them freely for reasoning.
27
+
28
+ **Two tool calls:**
29
+
30
+ ```
31
+ {"tool":"set_group","path":"<dot.notation.path>","description":"<optional>"}
32
+
33
+ {"tool":"set_token","path":"<dot.notation.path>","type":"<DTCG type>","value":<value>,"description":"<reason>"}
34
+ ```
35
+
36
+ Every leaf token must have an explicit `$type` — do not rely on group-level inheritance. Intermediate nodes (groups) must NOT have a `type` field.
37
+
38
+ **Rules:**
39
+ - Emit exactly one JSON object per line. No multi-line JSON.
40
+ - Every intermediate group must have a `set_group` call.
41
+ - Every leaf token must have a `set_token` call.
42
+ - `path` is dot-notation from root, e.g. `colors.brand.primary` — no leading dots or slashes.
43
+ - `type` must be one of the 13 valid DTCG types (see table below).
44
+ - `value` must be valid JSON — string, number, array, or object depending on the type. Do NOT quote complex values.
45
+ - Emit `set_group` calls before the `set_token` calls under them.
46
+ - `description` on `set_token` documents your reasoning — always include it.
47
+
48
+ ---
49
+
50
+ ## Valid types
51
+
52
+ Exactly **13** valid DTCG `$type` values:
53
+
54
+ | type | Typical values |
55
+ |---|---|
56
+ | `color` | `"#0066ff"`, `"rgb(0,102,255)"` |
57
+ | `dimension` | `"8px"`, `"1rem"`, `"0.5em"` |
58
+ | `fontFamily` | `"Inter, sans-serif"` |
59
+ | `fontWeight` | `400`, `"bold"` |
60
+ | `duration` | `"200ms"`, `"0.3s"` |
61
+ | `cubicBezier` | `[0.42, 0, 0.58, 1]` |
62
+ | `number` | `1.5`, `100` |
63
+ | `strokeStyle` | `"solid"`, `"dashed"` |
64
+ | `border` | `{"width":"1px","style":"solid","color":"#000"}` |
65
+ | `transition` | `{"duration":"200ms","timingFunction":[0.42,0,0.58,1],"delay":"0ms"}` |
66
+ | `shadow` | `{"offsetX":"0px","offsetY":"4px","blur":"8px","spread":"0px","color":"#00000026"}` |
67
+ | `gradient` | `[{"color":"#000","position":0},{"color":"#fff","position":1}]` |
68
+ | `typography` | `{"fontFamily":"Inter","fontSize":"16px","fontWeight":400,"lineHeight":1.5,"letterSpacing":"0px"}` |
69
+
70
+ ---
71
+
72
+ ## Mapping guidance — Type resolution
73
+
74
+ For each token value, determine the DTCG `$type` by reading the value and its context:
75
+
76
+ | Value pattern | Type |
77
+ |---|---|
78
+ | Starts with `#`, `rgb(`, `hsl(`, `rgba(` | `color` |
79
+ | Ends with `px`, `rem`, `em`, `%`, `vw`, `vh` | `dimension` |
80
+ | `cubic-bezier(...)` or 4-element array | `cubicBezier` |
81
+ | Ends with `ms` or `s` (animation/transition) | `duration` |
82
+ | Font family name string | `fontFamily` |
83
+ | Numeric `100`–`900`, or `bold`/`normal`/`light` | `fontWeight` |
84
+ | Multi-property shadow value | `shadow` |
85
+ | Multi-property border value | `border` |
86
+ | `solid`, `dashed`, `dotted` alone | `strokeStyle` |
87
+ | Composite font shorthand | `typography` |
88
+ | Unitless number | `number` |
89
+
90
+ When a token's type is ambiguous from its value alone, use its name as context (e.g. `$spacing-*` → `dimension`, `$duration-*` → `duration`). Document your reasoning in `description`. If no type fits, use `number` with a `"WARNING: type unknown"` description.
91
+
92
+ Resolve variable references: if a value references another variable (e.g. SCSS `$black` in `rgba($black, 0.6)`, or a JS alias), substitute the referenced value before classifying.
93
+
94
+ ---
95
+
96
+ ## Grouping
97
+
98
+ Organize tokens into a nested DTCG hierarchy that reflects their semantic purpose:
99
+
100
+ 1. Examine naming patterns and existing structure in the source (variable prefixes, object nesting, file-level categories).
101
+ 2. **For already-nested sources (JS/TS objects, JSON, Style Dictionary)**: derive paths directly from the source key hierarchy — lowercase each key segment and join with dots. Do NOT reorganize, rename, or flatten unless the original key is purely implementation-specific (e.g. `DEFAULT` as a single-child wrapper can be elided). The source structure IS the path. Example: `tokens[SPACING].DEFAULT.8` → `spacing.8`; `tokens[COLOR].text.standard` → `color.text.standard`; `tokens[SHADOW].level.1` → `shadow.level.1`.
102
+ 3. For flat names (SCSS variables, CSS custom properties): strip leading `--` or `$`; replace `-` and `_` separators with `.` to form nested paths. Use the first meaningful segment as the top-level group.
103
+ 4. If neither rule applies, propose a grouping strategy: by kind (`colors`, `spacing`, `typography`), by semantic role (`brand`, `semantic`, `neutral`), or hybrid.
104
+ 5. Emit a `set_group` call for every intermediate node before emitting any `set_token` calls under it.
105
+
106
+ **Determinism rule**: Identical source input MUST produce identical paths on every run. Never invent synonyms, abbreviations, or alternative hierarchies for keys that already exist in the source. If `primary` is the key, the path segment is `primary` — not `brand-primary`, `main`, or `accent`.
107
+
108
+ If the token-name sidecar is provided, use it as authoritative path assignments — it maps raw names to DTCG dot-notation paths already.
109
+
110
+ ---
111
+
112
+ ## Value handling
113
+
114
+ Most values pass through as strings. For composite types, parse the raw string into the required JSON structure:
115
+
116
+ **`border`** — parse `1px solid #ccc` into:
117
+ ```json
118
+ {"width":"1px","style":"solid","color":"#cccccc"}
119
+ ```
120
+
121
+ **`shadow`:**
122
+ ```json
123
+ {"offsetX":"0px","offsetY":"4px","blur":"8px","spread":"0px","color":"#00000026"}
124
+ ```
125
+
126
+ **`transition`:**
127
+ ```json
128
+ {"duration":"200ms","delay":"0ms","timingFunction":[0.42,0,0.58,1]}
129
+ ```
130
+
131
+ **`gradient`** — array of color stops:
132
+ ```json
133
+ [{"color":"#000","position":0},{"color":"#fff","position":1}]
134
+ ```
135
+
136
+ ---
137
+
138
+ ## Examples
139
+
140
+ Input (SCSS):
141
+ ```scss
142
+ $brand-primary: #0066ff;
143
+ $spacing-sm: 8px;
144
+ $anim-speed: 200ms;
145
+ $black: #1a1a1a;
146
+ $overlay: rgba($black, 0.6);
147
+ ```
148
+
149
+ Output:
150
+ ```
151
+ Analyzing SCSS variables: 5 tokens across color, spacing, duration, and composite color categories.
152
+ $overlay references $black — resolving to rgba(26, 26, 26, 0.6).
153
+ {"tool":"set_group","path":"colors","description":"Brand and UI color tokens"}
154
+ {"tool":"set_group","path":"colors.brand","description":"Brand palette"}
155
+ {"tool":"set_token","path":"colors.brand.primary","type":"color","value":"#0066ff","description":"Brand primary color"}
156
+ {"tool":"set_token","path":"colors.neutral.black","type":"color","value":"#1a1a1a","description":"Base black neutral"}
157
+ {"tool":"set_token","path":"colors.neutral.overlay","type":"color","value":"rgba(26, 26, 26, 0.6)","description":"Semi-transparent overlay; $black variable resolved to #1a1a1a"}
158
+ {"tool":"set_group","path":"spacing","description":"Spacing scale"}
159
+ {"tool":"set_token","path":"spacing.sm","type":"dimension","value":"8px","description":"Small spacing step"}
160
+ {"tool":"set_group","path":"motion","description":"Animation timing"}
161
+ {"tool":"set_group","path":"motion.duration","description":"Duration values"}
162
+ {"tool":"set_token","path":"motion.duration.speed","type":"duration","value":"200ms","description":"Standard animation speed"}
163
+ ```
164
+
165
+ ---
166
+
167
+ ## Edge cases
168
+
169
+ - **Empty input** — emit nothing; the CLI will report 0 tokens stored.
170
+ - **Path collision** — two raw tokens resolve to the same dot-notation path: append `_2`, `_3` to disambiguate, and add a `description` warning.
171
+ - **Unrecognizable value** — no heuristic matches and `inferredKind` is invalid → use `number` with a warning in `description`.
172
+ - **Complex composite value** — parse raw string into the required JSON structure; if parsing is ambiguous, use a best-effort parse and document in `description`.
173
+
174
+ ---
175
+
176
+ ## Validation step — Pre-emit checklist
177
+
178
+ Before emitting any tool calls, verify:
179
+
180
+ 1. Every raw token in the input has exactly one `set_token` call.
181
+ 2. Every intermediate group has a `set_group` call.
182
+ 3. All `type` values are from the 13 valid DTCG types.
183
+ 4. `value` is valid JSON for the given type (string for color/dimension/etc., object for border/shadow/etc., array for gradient/cubicBezier).
184
+ 5. All `path` values use dot-notation with no leading dots or slashes.
185
+ 6. No duplicate paths.
186
+ 7. `set_group` calls precede the `set_token` calls under them.
187
+
188
+ After the run, the developer can validate with:
189
+
190
+ ```
191
+ experience-design-system-cli print validate --tokens <out-path>
192
+ ```
193
+
194
+ Re-run or iterate on any tokens flagged by warnings until validation passes.
@@ -0,0 +1,180 @@
1
+ # Analyze Select — Agent Component Selection Skill
2
+
3
+ ## Purpose
4
+
5
+ Review the single extracted React/Next.js component provided below and decide whether it belongs in **Contentful Experience Orchestration** as a Component Type. Output one JSON tool call to stdout.
6
+
7
+ ---
8
+
9
+ ## What is Contentful Experience Orchestration?
10
+
11
+ Contentful Experience Orchestration is a Contentful product that enables **designers, developers, and marketers** to compose and manage digital experiences in Contentful. Component Types are used at every layer of the design system:
12
+
13
+ - **Atoms** — low-level UI primitives: icons, buttons, inputs, badges
14
+ - **Molecules** — composed UI units: cards, search fields, modals, navigation items
15
+ - **Organisms** — larger sections: heroes, banners, footers, press release lists, parallax sections
16
+
17
+ All three levels are valid Component Types in Contentful Experience Orchestration. Designers and developers compose atoms into molecules, molecules into organisms. Marketers then configure content and design values on any of these.
18
+
19
+ The entity being defined — a **Component Type** — is the schema that tells Contentful what is configurable for this component. It defines design properties, content properties, and slots. Even a component with only a few configurable props is a valid Component Type.
20
+
21
+ ---
22
+
23
+ ## The one rule: does it render visible UI?
24
+
25
+ **Accept** the component if it renders visible UI — regardless of whether it is an atom, molecule, or organism, and regardless of whether it has many or few configurable props. A footer icon with two props (`icon`, `label`) is just as valid as a parallax hero with fifteen props.
26
+
27
+ **Reject** the component only if its primary purpose produces zero visual output:
28
+ - It is a React hook (name starts `use` or `Use`)
29
+ - It is a pure context provider with no visual output
30
+ - It is a Ninetailed/personalization platform wrapper (its job is routing to variants, not rendering content)
31
+ - It is an analytics/event-tracking component (fires events, renders nothing)
32
+ - It is a security or infrastructure utility (no UI at all)
33
+
34
+ ---
35
+
36
+ ## What NOT to use as a rejection reason
37
+
38
+ These are **not** valid reasons to reject a component:
39
+
40
+ | Invalid reason | Why it is wrong |
41
+ |---|---|
42
+ | "Only atoms/low-level" | Atoms are first-class Component Types in Contentful Experience Orchestration |
43
+ | "Tightly coupled to a parent component" | Contentful Experience Orchestration handles composition at the experience layer |
44
+ | "Has A/B testing or personalization-related props" | These props are classified as `state` or excluded in the generate step — their presence does not disqualify the component |
45
+ | "Has no marketer-configurable props" | Marketers are not the only users; designers and developers configure components too |
46
+ | "Domain-specific or feature-level" | Press releases, newsrooms, search — all valid content components |
47
+ | "Server-side or SSR" | Server components that render visible UI are valid |
48
+ | "Few configurable props" | One or two props is fine |
49
+
50
+ ---
51
+
52
+ ## Reject only these categories
53
+
54
+ | Category | Why |
55
+ |---|---|
56
+ | **React hooks** | `useXxx` / `UseXxx` — functions, not renderable components. Zero visual output. |
57
+ | **Pure context providers** | Wrap children to pass context but render no UI themselves |
58
+ | **A/B testing or personalization wrappers** | Components whose *entire purpose* is routing users to content variants or tracking experiment participation — they render no UI of their own |
59
+ | **Analytics and event tracking** | Components that only fire analytics events and render nothing visible |
60
+ | **Security utilities** | Non-visual security primitives with no rendered output |
61
+
62
+ > **Variant routing rule**: Reject a component if its entire purpose is deciding *which* content variant to show — that is framework infrastructure, not a Component Type. Do **not** reject a component merely because it *contains* some A/B testing or personalization-related props — those props are handled as `state` in the generate step.
63
+
64
+ ---
65
+
66
+ ## Output protocol
67
+
68
+ Emit one JSON object on a single line. Lines not starting with `{` are ignored by the parser — use them freely for reasoning.
69
+
70
+ **Two tool calls — emit exactly one:**
71
+
72
+ ```
73
+ {"tool":"select_component","name":"<ComponentName>","reason":"<brief reason>"}
74
+
75
+ {"tool":"reject_component","name":"<ComponentName>","reason":"<brief reason>"}
76
+ ```
77
+
78
+ **Rules:**
79
+ - Emit exactly one JSON object, on one line. No multi-line JSON. No markdown fences.
80
+ - The `name` must match the component name in the input.
81
+ - `reason` is a brief phrase documenting your decision.
82
+ - Emit prose lines (not starting with `{`) to log your reasoning before the final tool call.
83
+
84
+ ---
85
+
86
+ ## Examples
87
+
88
+ ```
89
+ Analytics — fires analytics events, no visual output
90
+ {"tool":"reject_component","name":"Analytics","reason":"analytics tracker — no visual output"}
91
+ ```
92
+
93
+ ```
94
+ CanaryToken — security utility, no visual output
95
+ {"tool":"reject_component","name":"CanaryToken","reason":"security utility — no visual output"}
96
+ ```
97
+
98
+ ```
99
+ ClientExperience — personalization wrapper whose entire purpose is routing users to content variants
100
+ {"tool":"reject_component","name":"ClientExperience","reason":"variant routing wrapper — entire purpose is A/B routing, not rendering UI"}
101
+ ```
102
+
103
+ ```
104
+ ComponentMarker — experimentation marker component, no visual output
105
+ {"tool":"reject_component","name":"ComponentMarker","reason":"experimentation marker — no visual output"}
106
+ ```
107
+
108
+ ```
109
+ ComponentTracker — variant attribution tracker, no visual output
110
+ {"tool":"reject_component","name":"ComponentTracker","reason":"variant attribution tracker — no visual output"}
111
+ ```
112
+
113
+ ```
114
+ Refresh — client-side route refresh utility for personalization platform, no visual output
115
+ {"tool":"reject_component","name":"Refresh","reason":"personalization route refresh utility — no visual output"}
116
+ ```
117
+
118
+ ```
119
+ ServerExperience — server-side variant routing wrapper, no visual output
120
+ {"tool":"reject_component","name":"ServerExperience","reason":"server-side variant routing wrapper — no visual output"}
121
+ ```
122
+
123
+ ```
124
+ UseHelpNavigation — React hook, not a renderable component
125
+ {"tool":"reject_component","name":"UseHelpNavigation","reason":"React hook — not a renderable component"}
126
+ ```
127
+
128
+ ```
129
+ Providers — React context provider with no visual output
130
+ {"tool":"reject_component","name":"Providers","reason":"pure context provider — no visual output"}
131
+ ```
132
+
133
+ ```
134
+ FooterIcon — atom: renders an icon with optional label in the footer
135
+ {"tool":"select_component","name":"FooterIcon","reason":"UI atom — renders icon with configurable icon and label"}
136
+ ```
137
+
138
+ ```
139
+ FeedbackModal — modal dialog with visibility state
140
+ {"tool":"select_component","name":"FeedbackModal","reason":"modal UI component with configurable visibility and content"}
141
+ ```
142
+
143
+ ```
144
+ ActiveFilters — renders active filter chips with remove controls
145
+ {"tool":"select_component","name":"ActiveFilters","reason":"filter UI component — renders visible filter chips"}
146
+ ```
147
+
148
+ ```
149
+ FullSizeBarNoContent — full-width text bar with link; has some personalization state props
150
+ The personalization props (hideContentForPersonalization, componentId) are state props handled in the generate step.
151
+ The component renders real visual UI — a bar with text, chevron, and link.
152
+ {"tool":"select_component","name":"FullSizeBarNoContent","reason":"content bar UI — renders visible bar with configurable text, link, and design"}
153
+ ```
154
+
155
+ ```
156
+ ParallaxComponent — parallax marketing section; has some A/B testing props alongside real content props
157
+ The A/B testing props (abmFallback, abmLinkedFromAccount) are state props, not the component's primary purpose.
158
+ The component renders a parallax section with title, subtitle, and visual effects.
159
+ {"tool":"select_component","name":"ParallaxComponent","reason":"marketing section UI — renders parallax content with configurable title, subtitle, and design"}
160
+ ```
161
+
162
+ ```
163
+ NewsroomLandingPressReleases — press release list with pagination and locale
164
+ {"tool":"select_component","name":"NewsroomLandingPressReleases","reason":"content list UI — renders press releases with configurable locale and pagination"}
165
+ ```
166
+
167
+ ```
168
+ ServerHelpNavigation — server-side navigation with configurable search visibility and locale
169
+ {"tool":"select_component","name":"ServerHelpNavigation","reason":"navigation UI — renders help navigation with configurable locale and search toggle"}
170
+ ```
171
+
172
+ ```
173
+ TextImageCard — card with rich text and background image
174
+ {"tool":"select_component","name":"TextImageCard","reason":"content card UI — configurable rich text, image, and layout"}
175
+ ```
176
+
177
+ ```
178
+ SearchInput — search field with dropdown
179
+ {"tool":"select_component","name":"SearchInput","reason":"search UI — configurable placeholder and state"}
180
+ ```