@auto-engineer/component-implementor-react 1.97.2 → 1.99.0

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 (241) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/.turbo/turbo-test.log +6 -6
  3. package/.turbo/turbo-type-check.log +1 -1
  4. package/CHANGELOG.md +99 -0
  5. package/dist/src/commands/implement-component.d.ts +19 -0
  6. package/dist/src/commands/implement-component.d.ts.map +1 -1
  7. package/dist/src/commands/implement-component.js +116 -34
  8. package/dist/src/commands/implement-component.js.map +1 -1
  9. package/dist/src/commands/implement-component.test.js +352 -33
  10. package/dist/src/commands/implement-component.test.js.map +1 -1
  11. package/dist/src/extract-exports.d.ts +6 -0
  12. package/dist/src/extract-exports.d.ts.map +1 -0
  13. package/dist/src/extract-exports.js +46 -0
  14. package/dist/src/extract-exports.js.map +1 -0
  15. package/dist/src/generate-story-deterministic.d.ts +30 -0
  16. package/dist/src/generate-story-deterministic.d.ts.map +1 -0
  17. package/dist/src/generate-story-deterministic.js +229 -0
  18. package/dist/src/generate-story-deterministic.js.map +1 -0
  19. package/dist/src/index.d.ts +4 -0
  20. package/dist/src/index.d.ts.map +1 -1
  21. package/dist/src/index.js +3 -0
  22. package/dist/src/index.js.map +1 -1
  23. package/dist/src/pipeline/run-pipeline.d.ts +69 -0
  24. package/dist/src/pipeline/run-pipeline.d.ts.map +1 -0
  25. package/dist/src/pipeline/run-pipeline.js +78 -0
  26. package/dist/src/pipeline/run-pipeline.js.map +1 -0
  27. package/dist/src/pipeline/run-pipeline.test.d.ts +2 -0
  28. package/dist/src/pipeline/run-pipeline.test.d.ts.map +1 -0
  29. package/dist/src/pipeline/run-pipeline.test.js +247 -0
  30. package/dist/src/pipeline/run-pipeline.test.js.map +1 -0
  31. package/dist/src/pipeline/steps/generate-component.d.ts +4 -0
  32. package/dist/src/pipeline/steps/generate-component.d.ts.map +1 -0
  33. package/dist/src/pipeline/steps/generate-component.js +50 -0
  34. package/dist/src/pipeline/steps/generate-component.js.map +1 -0
  35. package/dist/src/pipeline/steps/generate-component.test.d.ts.map +1 -0
  36. package/dist/src/pipeline/steps/generate-component.test.js +106 -0
  37. package/dist/src/pipeline/steps/generate-component.test.js.map +1 -0
  38. package/dist/src/pipeline/steps/generate-story.d.ts +3 -0
  39. package/dist/src/pipeline/steps/generate-story.d.ts.map +1 -0
  40. package/dist/src/pipeline/steps/generate-story.js +14 -0
  41. package/dist/src/pipeline/steps/generate-story.js.map +1 -0
  42. package/dist/src/pipeline/steps/generate-story.test.d.ts.map +1 -0
  43. package/dist/src/pipeline/steps/generate-story.test.js +41 -0
  44. package/dist/src/pipeline/steps/generate-story.test.js.map +1 -0
  45. package/dist/src/pipeline/steps/generate-test.d.ts +4 -0
  46. package/dist/src/pipeline/steps/generate-test.d.ts.map +1 -0
  47. package/dist/src/pipeline/steps/generate-test.js +19 -0
  48. package/dist/src/pipeline/steps/generate-test.js.map +1 -0
  49. package/dist/src/pipeline/steps/generate-test.test.d.ts.map +1 -0
  50. package/dist/src/pipeline/steps/generate-test.test.js +60 -0
  51. package/dist/src/pipeline/steps/generate-test.test.js.map +1 -0
  52. package/dist/src/pipeline/steps/lint-fix-loop.d.ts +4 -0
  53. package/dist/src/pipeline/steps/lint-fix-loop.d.ts.map +1 -0
  54. package/dist/src/pipeline/steps/lint-fix-loop.js +45 -0
  55. package/dist/src/pipeline/steps/lint-fix-loop.js.map +1 -0
  56. package/dist/src/pipeline/steps/lint-fix-loop.test.d.ts +2 -0
  57. package/dist/src/pipeline/steps/lint-fix-loop.test.d.ts.map +1 -0
  58. package/dist/src/pipeline/steps/lint-fix-loop.test.js +119 -0
  59. package/dist/src/pipeline/steps/lint-fix-loop.test.js.map +1 -0
  60. package/dist/src/pipeline/steps/story-fix-loop.d.ts +4 -0
  61. package/dist/src/pipeline/steps/story-fix-loop.d.ts.map +1 -0
  62. package/dist/src/pipeline/steps/story-fix-loop.js +34 -0
  63. package/dist/src/pipeline/steps/story-fix-loop.js.map +1 -0
  64. package/dist/src/pipeline/steps/story-fix-loop.test.d.ts +2 -0
  65. package/dist/src/pipeline/steps/story-fix-loop.test.d.ts.map +1 -0
  66. package/dist/src/pipeline/steps/story-fix-loop.test.js +94 -0
  67. package/dist/src/pipeline/steps/story-fix-loop.test.js.map +1 -0
  68. package/dist/src/pipeline/steps/storybook-test.d.ts +3 -0
  69. package/dist/src/pipeline/steps/storybook-test.d.ts.map +1 -0
  70. package/dist/src/pipeline/steps/storybook-test.js +22 -0
  71. package/dist/src/pipeline/steps/storybook-test.js.map +1 -0
  72. package/dist/src/pipeline/steps/storybook-test.test.d.ts +2 -0
  73. package/dist/src/pipeline/steps/storybook-test.test.d.ts.map +1 -0
  74. package/dist/src/pipeline/steps/storybook-test.test.js +66 -0
  75. package/dist/src/pipeline/steps/storybook-test.test.js.map +1 -0
  76. package/dist/src/pipeline/steps/test-fix-loop.d.ts +4 -0
  77. package/dist/src/pipeline/steps/test-fix-loop.d.ts.map +1 -0
  78. package/dist/src/pipeline/steps/test-fix-loop.js +44 -0
  79. package/dist/src/pipeline/steps/test-fix-loop.js.map +1 -0
  80. package/dist/src/pipeline/steps/test-fix-loop.test.d.ts +2 -0
  81. package/dist/src/pipeline/steps/test-fix-loop.test.d.ts.map +1 -0
  82. package/dist/src/pipeline/steps/test-fix-loop.test.js +168 -0
  83. package/dist/src/pipeline/steps/test-fix-loop.test.js.map +1 -0
  84. package/dist/src/pipeline/steps/type-fix-loop.d.ts +4 -0
  85. package/dist/src/pipeline/steps/type-fix-loop.d.ts.map +1 -0
  86. package/dist/src/pipeline/steps/type-fix-loop.js +43 -0
  87. package/dist/src/pipeline/steps/type-fix-loop.js.map +1 -0
  88. package/dist/src/pipeline/steps/type-fix-loop.test.d.ts +2 -0
  89. package/dist/src/pipeline/steps/type-fix-loop.test.d.ts.map +1 -0
  90. package/dist/src/pipeline/steps/type-fix-loop.test.js +112 -0
  91. package/dist/src/pipeline/steps/type-fix-loop.test.js.map +1 -0
  92. package/dist/src/pipeline/steps/visual-test.d.ts +3 -0
  93. package/dist/src/pipeline/steps/visual-test.d.ts.map +1 -0
  94. package/dist/src/pipeline/steps/visual-test.js +4 -0
  95. package/dist/src/pipeline/steps/visual-test.js.map +1 -0
  96. package/dist/src/pipeline/steps/visual-test.test.d.ts +2 -0
  97. package/dist/src/pipeline/steps/visual-test.test.d.ts.map +1 -0
  98. package/dist/src/pipeline/steps/visual-test.test.js +9 -0
  99. package/dist/src/pipeline/steps/visual-test.test.js.map +1 -0
  100. package/dist/src/project-context.d.ts +10 -0
  101. package/dist/src/project-context.d.ts.map +1 -0
  102. package/dist/src/project-context.js +178 -0
  103. package/dist/src/project-context.js.map +1 -0
  104. package/dist/src/prompt.d.ts +39 -7
  105. package/dist/src/prompt.d.ts.map +1 -1
  106. package/dist/src/prompt.js +233 -23
  107. package/dist/src/prompt.js.map +1 -1
  108. package/dist/src/prompt.test.js +225 -9
  109. package/dist/src/prompt.test.js.map +1 -1
  110. package/dist/src/scaffold.d.ts +49 -0
  111. package/dist/src/scaffold.d.ts.map +1 -0
  112. package/dist/src/scaffold.js +208 -0
  113. package/dist/src/scaffold.js.map +1 -0
  114. package/dist/src/spec-contract.js +1 -1
  115. package/dist/src/spec-contract.js.map +1 -1
  116. package/dist/src/spec-contract.test.d.ts +2 -0
  117. package/dist/src/spec-contract.test.d.ts.map +1 -0
  118. package/dist/src/spec-contract.test.js +21 -0
  119. package/dist/src/spec-contract.test.js.map +1 -0
  120. package/dist/src/tools/lint-runner.d.ts +7 -0
  121. package/dist/src/tools/lint-runner.d.ts.map +1 -0
  122. package/dist/src/tools/lint-runner.js +48 -0
  123. package/dist/src/tools/lint-runner.js.map +1 -0
  124. package/dist/src/tools/lint-runner.test.d.ts +2 -0
  125. package/dist/src/tools/lint-runner.test.d.ts.map +1 -0
  126. package/dist/src/tools/lint-runner.test.js +90 -0
  127. package/dist/src/tools/lint-runner.test.js.map +1 -0
  128. package/dist/src/tools/storybook-runner.d.ts +6 -0
  129. package/dist/src/tools/storybook-runner.d.ts.map +1 -0
  130. package/dist/src/tools/storybook-runner.js +25 -0
  131. package/dist/src/tools/storybook-runner.js.map +1 -0
  132. package/dist/src/tools/storybook-runner.test.d.ts +2 -0
  133. package/dist/src/tools/storybook-runner.test.d.ts.map +1 -0
  134. package/dist/src/tools/storybook-runner.test.js +43 -0
  135. package/dist/src/tools/storybook-runner.test.js.map +1 -0
  136. package/dist/src/tools/test-runner.d.ts +9 -0
  137. package/dist/src/tools/test-runner.d.ts.map +1 -0
  138. package/dist/src/tools/test-runner.js +74 -0
  139. package/dist/src/tools/test-runner.js.map +1 -0
  140. package/dist/src/tools/test-runner.test.d.ts +2 -0
  141. package/dist/src/tools/test-runner.test.d.ts.map +1 -0
  142. package/dist/src/tools/test-runner.test.js +177 -0
  143. package/dist/src/tools/test-runner.test.js.map +1 -0
  144. package/dist/src/tools/type-checker.d.ts +6 -0
  145. package/dist/src/tools/type-checker.d.ts.map +1 -0
  146. package/dist/src/tools/type-checker.js +36 -0
  147. package/dist/src/tools/type-checker.js.map +1 -0
  148. package/dist/src/tools/type-checker.test.d.ts +2 -0
  149. package/dist/src/tools/type-checker.test.d.ts.map +1 -0
  150. package/dist/src/tools/type-checker.test.js +96 -0
  151. package/dist/src/tools/type-checker.test.js.map +1 -0
  152. package/dist/tsconfig.tsbuildinfo +1 -1
  153. package/inputs/model-a/spec-deltas.json +1460 -0
  154. package/inputs/model-b/spec-deltas.json +1424 -0
  155. package/inputs/model-c/spec-deltas.json +1432 -0
  156. package/inputs/model-d/spec-deltas.json +967 -0
  157. package/inputs/model-e/spec-deltas.json +2292 -0
  158. package/ketchup-plan.md +43 -8
  159. package/package.json +3 -3
  160. package/scoring-heuristic.md +138 -0
  161. package/scripts/improve.ts +23 -18
  162. package/src/commands/implement-component.test.ts +420 -37
  163. package/src/commands/implement-component.ts +163 -35
  164. package/src/extract-exports.ts +53 -0
  165. package/src/generate-story-deterministic.ts +267 -0
  166. package/src/index.ts +12 -0
  167. package/src/pipeline/run-pipeline.test.ts +292 -0
  168. package/src/pipeline/run-pipeline.ts +160 -0
  169. package/src/pipeline/steps/generate-component.test.ts +130 -0
  170. package/src/pipeline/steps/generate-component.ts +60 -0
  171. package/src/pipeline/steps/generate-story.test.ts +54 -0
  172. package/src/pipeline/steps/generate-story.ts +17 -0
  173. package/src/pipeline/steps/generate-test.test.ts +75 -0
  174. package/src/pipeline/steps/generate-test.ts +25 -0
  175. package/src/pipeline/steps/lint-fix-loop.test.ts +155 -0
  176. package/src/pipeline/steps/lint-fix-loop.ts +59 -0
  177. package/src/pipeline/steps/story-fix-loop.test.ts +123 -0
  178. package/src/pipeline/steps/story-fix-loop.ts +47 -0
  179. package/src/pipeline/steps/storybook-test.test.ts +82 -0
  180. package/src/pipeline/steps/storybook-test.ts +27 -0
  181. package/src/pipeline/steps/test-fix-loop.test.ts +201 -0
  182. package/src/pipeline/steps/test-fix-loop.ts +56 -0
  183. package/src/pipeline/steps/type-fix-loop.test.ts +145 -0
  184. package/src/pipeline/steps/type-fix-loop.ts +55 -0
  185. package/src/pipeline/steps/visual-test.test.ts +10 -0
  186. package/src/pipeline/steps/visual-test.ts +5 -0
  187. package/src/project-context.ts +205 -0
  188. package/src/prompt.test.ts +253 -8
  189. package/src/prompt.ts +301 -23
  190. package/src/scaffold.ts +281 -0
  191. package/src/spec-contract.test.ts +23 -0
  192. package/src/spec-contract.ts +1 -1
  193. package/src/tools/lint-runner.test.ts +112 -0
  194. package/src/tools/lint-runner.ts +52 -0
  195. package/src/tools/storybook-runner.test.ts +53 -0
  196. package/src/tools/storybook-runner.ts +29 -0
  197. package/src/tools/test-runner.test.ts +213 -0
  198. package/src/tools/test-runner.ts +84 -0
  199. package/src/tools/type-checker.test.ts +120 -0
  200. package/src/tools/type-checker.ts +42 -0
  201. package/vitest.config.ts +9 -1
  202. package/dist/src/generate-component.d.ts +0 -4
  203. package/dist/src/generate-component.d.ts.map +0 -1
  204. package/dist/src/generate-component.js +0 -14
  205. package/dist/src/generate-component.js.map +0 -1
  206. package/dist/src/generate-component.test.d.ts.map +0 -1
  207. package/dist/src/generate-component.test.js +0 -73
  208. package/dist/src/generate-component.test.js.map +0 -1
  209. package/dist/src/generate-story.d.ts +0 -4
  210. package/dist/src/generate-story.d.ts.map +0 -1
  211. package/dist/src/generate-story.js +0 -14
  212. package/dist/src/generate-story.js.map +0 -1
  213. package/dist/src/generate-story.test.d.ts.map +0 -1
  214. package/dist/src/generate-story.test.js +0 -58
  215. package/dist/src/generate-story.test.js.map +0 -1
  216. package/dist/src/generate-test.d.ts +0 -4
  217. package/dist/src/generate-test.d.ts.map +0 -1
  218. package/dist/src/generate-test.js +0 -14
  219. package/dist/src/generate-test.js.map +0 -1
  220. package/dist/src/generate-test.test.d.ts.map +0 -1
  221. package/dist/src/generate-test.test.js +0 -77
  222. package/dist/src/generate-test.test.js.map +0 -1
  223. package/dist/src/reconcile.d.ts +0 -8
  224. package/dist/src/reconcile.d.ts.map +0 -1
  225. package/dist/src/reconcile.js +0 -18
  226. package/dist/src/reconcile.js.map +0 -1
  227. package/dist/src/reconcile.test.d.ts +0 -2
  228. package/dist/src/reconcile.test.d.ts.map +0 -1
  229. package/dist/src/reconcile.test.js +0 -108
  230. package/dist/src/reconcile.test.js.map +0 -1
  231. package/src/generate-component.test.ts +0 -89
  232. package/src/generate-component.ts +0 -16
  233. package/src/generate-story.test.ts +0 -71
  234. package/src/generate-story.ts +0 -16
  235. package/src/generate-test.test.ts +0 -93
  236. package/src/generate-test.ts +0 -16
  237. package/src/reconcile.test.ts +0 -127
  238. package/src/reconcile.ts +0 -27
  239. /package/dist/src/{generate-component.test.d.ts → pipeline/steps/generate-component.test.d.ts} +0 -0
  240. /package/dist/src/{generate-story.test.d.ts → pipeline/steps/generate-story.test.d.ts} +0 -0
  241. /package/dist/src/{generate-test.test.d.ts → pipeline/steps/generate-test.test.d.ts} +0 -0
@@ -1,9 +1,13 @@
1
1
  import { describe, expect, it } from 'vitest';
2
2
  import {
3
3
  buildComponentPrompt,
4
+ buildLintFixPrompt,
4
5
  buildReconcilerPrompt,
6
+ buildStoryFixPrompt,
5
7
  buildStoryPrompt,
8
+ buildTestFixPrompt,
6
9
  buildTestPrompt,
10
+ buildTypeFixPrompt,
7
11
  componentPromptSections,
8
12
  reconcilerPromptSections,
9
13
  storyPromptSections,
@@ -17,16 +21,18 @@ const specDeltas = {
17
21
  styling: ['applies elevated style when raised=true'],
18
22
  };
19
23
 
24
+ const projectSection = '## Project Dependencies\ntest project context';
25
+
20
26
  describe('prompt builders', () => {
21
27
  describe('buildComponentPrompt', () => {
22
28
  it('returns system and prompt', () => {
23
- const result = buildComponentPrompt({ componentName: 'Card', specDeltas });
29
+ const result = buildComponentPrompt({ componentName: 'Card', specDeltas, projectSection });
24
30
  expect(result.system).toBeTruthy();
25
31
  expect(result.prompt).toBeTruthy();
26
32
  });
27
33
 
28
34
  it('system prompt contains all sections', () => {
29
- const { system } = buildComponentPrompt({ componentName: 'Card', specDeltas });
35
+ const { system } = buildComponentPrompt({ componentName: 'Card', specDeltas, projectSection });
30
36
  expect(system).toContain('YOUR INPUT');
31
37
  expect(system).toContain('YOUR OUTPUT');
32
38
  expect(system).toContain('METHODOLOGY');
@@ -35,7 +41,7 @@ describe('prompt builders', () => {
35
41
  });
36
42
 
37
43
  it('user prompt includes component name and spec deltas', () => {
38
- const { prompt } = buildComponentPrompt({ componentName: 'Card', specDeltas });
44
+ const { prompt } = buildComponentPrompt({ componentName: 'Card', specDeltas, projectSection });
39
45
  expect(prompt).toContain('**Card**');
40
46
  expect(prompt).toContain('renders a Card element');
41
47
  expect(prompt).toContain('shows skeleton when loading');
@@ -46,25 +52,32 @@ describe('prompt builders', () => {
46
52
  componentName: 'Card',
47
53
  specDeltas,
48
54
  existingComponent: 'export function Card() {}',
55
+ projectSection,
49
56
  });
50
57
  expect(prompt).toContain('## Existing Component');
51
58
  expect(prompt).toContain('export function Card() {}');
52
59
  });
53
60
 
54
61
  it('user prompt omits existing component section when not provided', () => {
55
- const { prompt } = buildComponentPrompt({ componentName: 'Card', specDeltas });
62
+ const { prompt } = buildComponentPrompt({ componentName: 'Card', specDeltas, projectSection });
56
63
  expect(prompt).not.toContain('## Existing Component');
57
64
  });
65
+
66
+ it('user prompt includes project section', () => {
67
+ const { prompt } = buildComponentPrompt({ componentName: 'Card', specDeltas, projectSection });
68
+ expect(prompt).toContain('## Project Dependencies');
69
+ expect(prompt).toContain('test project context');
70
+ });
58
71
  });
59
72
 
60
73
  describe('buildTestPrompt', () => {
61
74
  it('system prompt establishes tests as source of truth', () => {
62
- const { system } = buildTestPrompt({ componentName: 'Card', specDeltas });
75
+ const { system } = buildTestPrompt({ componentName: 'Card', specDeltas, projectSection });
63
76
  expect(system).toContain('source of truth');
64
77
  });
65
78
 
66
79
  it('user prompt includes spec deltas', () => {
67
- const { prompt } = buildTestPrompt({ componentName: 'Card', specDeltas });
80
+ const { prompt } = buildTestPrompt({ componentName: 'Card', specDeltas, projectSection });
68
81
  expect(prompt).toContain('## Spec Deltas');
69
82
  expect(prompt).toContain('calls onSelect when clicked');
70
83
  });
@@ -74,26 +87,90 @@ describe('prompt builders', () => {
74
87
  componentName: 'Card',
75
88
  specDeltas,
76
89
  existingComponent: 'existing code',
90
+ projectSection,
77
91
  });
78
92
  expect(prompt).toContain('## Existing Component');
79
93
  expect(prompt).toContain('existing code');
80
94
  });
95
+
96
+ it('user prompt includes project section', () => {
97
+ const { prompt } = buildTestPrompt({ componentName: 'Card', specDeltas, projectSection });
98
+ expect(prompt).toContain('## Project Dependencies');
99
+ expect(prompt).toContain('test project context');
100
+ });
101
+
102
+ it('system prompt contains Tailwind test rule', () => {
103
+ const { system } = buildTestPrompt({ componentName: 'Card', specDeltas, projectSection });
104
+ expect(system).toContain('Tailwind classes, not inline styles');
105
+ expect(system).toContain('toHaveClass');
106
+ expect(system).toContain('NEVER use `toHaveStyle()`');
107
+ });
108
+
109
+ it('system prompt contains semantic element verification rule', () => {
110
+ const { system } = buildTestPrompt({ componentName: 'Card', specDeltas, projectSection });
111
+ expect(system).toContain('Verify semantic elements from component source');
112
+ expect(system).toContain('getByText');
113
+ });
81
114
  });
82
115
 
83
116
  describe('buildStoryPrompt', () => {
84
117
  it('system prompt covers CSF3 and story conventions', () => {
85
- const { system } = buildStoryPrompt({ componentName: 'Card', specDeltas });
118
+ const { system } = buildStoryPrompt({
119
+ componentName: 'Card',
120
+ specDeltas,
121
+ projectSection,
122
+ componentImportPath: '@/components/Card',
123
+ });
86
124
  expect(system).toContain('CSF3');
87
125
  expect(system).toContain('Meta');
88
126
  expect(system).toContain('StoryObj');
89
127
  });
90
128
 
91
129
  it('user prompt includes spec deltas without component code', () => {
92
- const { prompt } = buildStoryPrompt({ componentName: 'Card', specDeltas });
130
+ const { prompt } = buildStoryPrompt({
131
+ componentName: 'Card',
132
+ specDeltas,
133
+ projectSection,
134
+ componentImportPath: '@/components/Card',
135
+ });
93
136
  expect(prompt).toContain('## Spec Deltas');
94
137
  expect(prompt).toContain('applies elevated style when raised=true');
95
138
  expect(prompt).not.toContain('## Component Code');
96
139
  });
140
+
141
+ it('user prompt includes component code when provided', () => {
142
+ const { prompt } = buildStoryPrompt({
143
+ componentName: 'Card',
144
+ specDeltas,
145
+ projectSection,
146
+ componentImportPath: '@/components/Card',
147
+ componentCode: 'export function Card() {}',
148
+ });
149
+ expect(prompt).toContain('## Component Code');
150
+ expect(prompt).toContain('export function Card() {}');
151
+ });
152
+
153
+ it('user prompt includes project section', () => {
154
+ const { prompt } = buildStoryPrompt({
155
+ componentName: 'Card',
156
+ specDeltas,
157
+ projectSection,
158
+ componentImportPath: '@/components/Card',
159
+ });
160
+ expect(prompt).toContain('## Project Dependencies');
161
+ expect(prompt).toContain('test project context');
162
+ });
163
+
164
+ it('user prompt includes component import path', () => {
165
+ const { prompt } = buildStoryPrompt({
166
+ componentName: 'Card',
167
+ specDeltas,
168
+ projectSection,
169
+ componentImportPath: '@/components/Card',
170
+ });
171
+ expect(prompt).toContain('## Component Import Path');
172
+ expect(prompt).toContain("import { Card } from '@/components/Card'");
173
+ });
97
174
  });
98
175
 
99
176
  describe('buildReconcilerPrompt', () => {
@@ -103,6 +180,7 @@ describe('prompt builders', () => {
103
180
  componentCode: 'component source',
104
181
  testCode: 'test source',
105
182
  storyCode: 'story source',
183
+ projectSection,
106
184
  };
107
185
 
108
186
  it('system prompt establishes test immutability', () => {
@@ -129,6 +207,96 @@ describe('prompt builders', () => {
129
207
  expect(prompt).toContain('## Existing Component');
130
208
  expect(prompt).toContain('old code');
131
209
  });
210
+
211
+ it('user prompt includes project section', () => {
212
+ const { prompt } = buildReconcilerPrompt(reconcileInput);
213
+ expect(prompt).toContain('## Project Dependencies');
214
+ expect(prompt).toContain('test project context');
215
+ });
216
+ });
217
+
218
+ describe('buildComponentPrompt handles undefined specDelta fields', () => {
219
+ const specDeltasWithUndefined = {
220
+ structure: ['renders a Card element'],
221
+ rendering: undefined as unknown as string[],
222
+ interaction: undefined as unknown as string[],
223
+ styling: ['applies elevated style when raised=true'],
224
+ };
225
+
226
+ it('returns valid result when rendering and interaction are undefined', () => {
227
+ const result = buildComponentPrompt({
228
+ componentName: 'Card',
229
+ specDeltas: specDeltasWithUndefined,
230
+ projectSection,
231
+ });
232
+ expect(result.system).toBeTruthy();
233
+ expect(result.prompt).toBeTruthy();
234
+ expect(result.prompt).toContain('renders a Card element');
235
+ });
236
+ });
237
+
238
+ describe('buildTestPrompt handles undefined specDelta fields', () => {
239
+ const specDeltasWithUndefined = {
240
+ structure: undefined as unknown as string[],
241
+ rendering: ['shows skeleton when loading'],
242
+ interaction: undefined as unknown as string[],
243
+ styling: ['applies elevated style when raised=true'],
244
+ };
245
+
246
+ it('returns valid result when structure and interaction are undefined', () => {
247
+ const result = buildTestPrompt({
248
+ componentName: 'Card',
249
+ specDeltas: specDeltasWithUndefined,
250
+ projectSection,
251
+ });
252
+ expect(result.system).toBeTruthy();
253
+ expect(result.prompt).toBeTruthy();
254
+ expect(result.prompt).toContain('shows skeleton when loading');
255
+ });
256
+ });
257
+
258
+ describe('buildStoryPrompt handles undefined specDelta fields', () => {
259
+ const specDeltasWithUndefined = {
260
+ structure: ['renders a Card element'],
261
+ rendering: undefined as unknown as string[],
262
+ interaction: ['calls onSelect when clicked'],
263
+ styling: undefined as unknown as string[],
264
+ };
265
+
266
+ it('returns valid result when rendering and styling are undefined', () => {
267
+ const result = buildStoryPrompt({
268
+ componentName: 'Card',
269
+ specDeltas: specDeltasWithUndefined,
270
+ projectSection,
271
+ componentImportPath: '@/components/Card',
272
+ });
273
+ expect(result.system).toBeTruthy();
274
+ expect(result.prompt).toBeTruthy();
275
+ expect(result.prompt).toContain('renders a Card element');
276
+ });
277
+ });
278
+
279
+ describe('buildReconcilerPrompt handles undefined specDelta fields', () => {
280
+ const specDeltasWithUndefined = {
281
+ structure: ['renders a Card element'],
282
+ rendering: ['shows skeleton when loading'],
283
+ interaction: undefined as unknown as string[],
284
+ styling: undefined as unknown as string[],
285
+ };
286
+
287
+ it('returns valid result when interaction and styling are undefined', () => {
288
+ const result = buildReconcilerPrompt({
289
+ componentName: 'Card',
290
+ specDeltas: specDeltasWithUndefined,
291
+ componentCode: 'component source',
292
+ testCode: 'test source',
293
+ storyCode: 'story source',
294
+ projectSection,
295
+ });
296
+ expect(result.system).toBeTruthy();
297
+ expect(result.prompt).toBeTruthy();
298
+ expect(result.prompt).toContain('renders a Card element');
299
+ });
132
300
  });
133
301
 
134
302
  describe('exported prompt sections', () => {
@@ -160,4 +328,81 @@ describe('prompt builders', () => {
160
328
  }
161
329
  });
162
330
  });
331
+
332
+ describe('buildTypeFixPrompt', () => {
333
+ it('includes errors, component code, and test code', () => {
334
+ const result = buildTypeFixPrompt({
335
+ componentCode: 'const x: number = "bad"',
336
+ testCode: 'import { Card } from "./Card"',
337
+ errors: ['src/Card.tsx(1,7): error TS2322: Type string not assignable to number'],
338
+ });
339
+
340
+ expect(result.system).toContain('TypeScript error fixer');
341
+ expect(result.system).toContain('two code blocks');
342
+ expect(result.prompt).toContain('## TypeScript Errors');
343
+ expect(result.prompt).toContain('error TS2322');
344
+ expect(result.prompt).toContain('## Component Code');
345
+ expect(result.prompt).toContain('const x: number = "bad"');
346
+ expect(result.prompt).toContain('## Test Code');
347
+ expect(result.prompt).toContain('import { Card } from "./Card"');
348
+ });
349
+ });
350
+
351
+ describe('buildTestFixPrompt', () => {
352
+ it('includes failures, output, component code, and test code', () => {
353
+ const result = buildTestFixPrompt({
354
+ componentCode: 'export function Card() { return <div /> }',
355
+ testCode: 'expect(screen.getByRole("button")).toBeInTheDocument()',
356
+ failures: ['renders button: Expected element not found'],
357
+ testOutput: 'FAIL src/Card.test.tsx',
358
+ });
359
+
360
+ expect(result.system).toContain('test failure fixer');
361
+ expect(result.system).toContain('source of truth');
362
+ expect(result.prompt).toContain('## Test Failures');
363
+ expect(result.prompt).toContain('Expected element not found');
364
+ expect(result.prompt).toContain('## Test Output');
365
+ expect(result.prompt).toContain('FAIL src/Card.test.tsx');
366
+ expect(result.prompt).toContain('## Component Code');
367
+ expect(result.prompt).toContain('## Test Code');
368
+ });
369
+ });
370
+
371
+ describe('buildLintFixPrompt', () => {
372
+ it('includes errors, component code, and test code', () => {
373
+ const result = buildLintFixPrompt({
374
+ componentCode: 'var x = 1',
375
+ testCode: 'var y = 2',
376
+ errors: ['src/Card.tsx:1:1 lint/style/useConst: Use const instead of var'],
377
+ });
378
+
379
+ expect(result.system).toContain('lint error fixer');
380
+ expect(result.system).toContain('two code blocks');
381
+ expect(result.prompt).toContain('## Lint Errors');
382
+ expect(result.prompt).toContain('useConst');
383
+ expect(result.prompt).toContain('## Component Code');
384
+ expect(result.prompt).toContain('var x = 1');
385
+ expect(result.prompt).toContain('## Test Code');
386
+ expect(result.prompt).toContain('var y = 2');
387
+ });
388
+ });
389
+
390
+ describe('buildStoryFixPrompt', () => {
391
+ it('includes errors, story code, and component code as reference', () => {
392
+ const result = buildStoryFixPrompt({
393
+ storyCode: 'import { Card } from "./Card"',
394
+ componentCode: 'export function Card() {}',
395
+ errors: ['src/Card.stories.tsx(1,10): error TS2305: Module has no exported member'],
396
+ });
397
+
398
+ expect(result.system).toContain('Storybook story fixer');
399
+ expect(result.system).toContain('one code block');
400
+ expect(result.prompt).toContain('## TypeScript Errors');
401
+ expect(result.prompt).toContain('error TS2305');
402
+ expect(result.prompt).toContain('## Story Code');
403
+ expect(result.prompt).toContain('import { Card } from "./Card"');
404
+ expect(result.prompt).toContain('## Component Code (reference)');
405
+ expect(result.prompt).toContain('export function Card() {}');
406
+ });
407
+ });
163
408
  });