afterburn-cli 1.0.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 (188) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +281 -0
  3. package/dist/ai/gemini-client.d.ts +21 -0
  4. package/dist/ai/gemini-client.js +105 -0
  5. package/dist/ai/gemini-client.js.map +1 -0
  6. package/dist/ai/index.d.ts +1 -0
  7. package/dist/ai/index.js +3 -0
  8. package/dist/ai/index.js.map +1 -0
  9. package/dist/analysis/diagnosis-schema.d.ts +106 -0
  10. package/dist/analysis/diagnosis-schema.js +54 -0
  11. package/dist/analysis/diagnosis-schema.js.map +1 -0
  12. package/dist/analysis/error-analyzer.d.ts +9 -0
  13. package/dist/analysis/error-analyzer.js +573 -0
  14. package/dist/analysis/error-analyzer.js.map +1 -0
  15. package/dist/analysis/index.d.ts +4 -0
  16. package/dist/analysis/index.js +6 -0
  17. package/dist/analysis/index.js.map +1 -0
  18. package/dist/analysis/source-mapper.d.ts +19 -0
  19. package/dist/analysis/source-mapper.js +329 -0
  20. package/dist/analysis/source-mapper.js.map +1 -0
  21. package/dist/analysis/ui-auditor.d.ts +9 -0
  22. package/dist/analysis/ui-auditor.js +104 -0
  23. package/dist/analysis/ui-auditor.js.map +1 -0
  24. package/dist/artifacts/artifact-storage.d.ts +44 -0
  25. package/dist/artifacts/artifact-storage.js +99 -0
  26. package/dist/artifacts/artifact-storage.js.map +1 -0
  27. package/dist/artifacts/index.d.ts +1 -0
  28. package/dist/artifacts/index.js +3 -0
  29. package/dist/artifacts/index.js.map +1 -0
  30. package/dist/browser/browser-manager.d.ts +45 -0
  31. package/dist/browser/browser-manager.js +88 -0
  32. package/dist/browser/browser-manager.js.map +1 -0
  33. package/dist/browser/challenge-detector.d.ts +10 -0
  34. package/dist/browser/challenge-detector.js +58 -0
  35. package/dist/browser/challenge-detector.js.map +1 -0
  36. package/dist/browser/cookie-dismisser.d.ts +18 -0
  37. package/dist/browser/cookie-dismisser.js +76 -0
  38. package/dist/browser/cookie-dismisser.js.map +1 -0
  39. package/dist/browser/index.d.ts +4 -0
  40. package/dist/browser/index.js +6 -0
  41. package/dist/browser/index.js.map +1 -0
  42. package/dist/browser/stealth-browser.d.ts +13 -0
  43. package/dist/browser/stealth-browser.js +59 -0
  44. package/dist/browser/stealth-browser.js.map +1 -0
  45. package/dist/cli/commander-cli.d.ts +2 -0
  46. package/dist/cli/commander-cli.js +150 -0
  47. package/dist/cli/commander-cli.js.map +1 -0
  48. package/dist/cli/doctor.d.ts +34 -0
  49. package/dist/cli/doctor.js +124 -0
  50. package/dist/cli/doctor.js.map +1 -0
  51. package/dist/cli/first-run.d.ts +6 -0
  52. package/dist/cli/first-run.js +58 -0
  53. package/dist/cli/first-run.js.map +1 -0
  54. package/dist/cli/index.d.ts +3 -0
  55. package/dist/cli/index.js +5 -0
  56. package/dist/cli/index.js.map +1 -0
  57. package/dist/cli/progress.d.ts +11 -0
  58. package/dist/cli/progress.js +30 -0
  59. package/dist/cli/progress.js.map +1 -0
  60. package/dist/core/engine.d.ts +33 -0
  61. package/dist/core/engine.js +269 -0
  62. package/dist/core/engine.js.map +1 -0
  63. package/dist/core/index.d.ts +3 -0
  64. package/dist/core/index.js +4 -0
  65. package/dist/core/index.js.map +1 -0
  66. package/dist/core/validation.d.ts +52 -0
  67. package/dist/core/validation.js +228 -0
  68. package/dist/core/validation.js.map +1 -0
  69. package/dist/discovery/crawler.d.ts +58 -0
  70. package/dist/discovery/crawler.js +240 -0
  71. package/dist/discovery/crawler.js.map +1 -0
  72. package/dist/discovery/discovery-pipeline.d.ts +22 -0
  73. package/dist/discovery/discovery-pipeline.js +256 -0
  74. package/dist/discovery/discovery-pipeline.js.map +1 -0
  75. package/dist/discovery/element-mapper.d.ts +21 -0
  76. package/dist/discovery/element-mapper.js +422 -0
  77. package/dist/discovery/element-mapper.js.map +1 -0
  78. package/dist/discovery/index.d.ts +8 -0
  79. package/dist/discovery/index.js +8 -0
  80. package/dist/discovery/index.js.map +1 -0
  81. package/dist/discovery/link-validator.d.ts +15 -0
  82. package/dist/discovery/link-validator.js +137 -0
  83. package/dist/discovery/link-validator.js.map +1 -0
  84. package/dist/discovery/sitemap-builder.d.ts +19 -0
  85. package/dist/discovery/sitemap-builder.js +166 -0
  86. package/dist/discovery/sitemap-builder.js.map +1 -0
  87. package/dist/discovery/spa-detector.d.ts +12 -0
  88. package/dist/discovery/spa-detector.js +271 -0
  89. package/dist/discovery/spa-detector.js.map +1 -0
  90. package/dist/execution/error-detector.d.ts +10 -0
  91. package/dist/execution/error-detector.js +87 -0
  92. package/dist/execution/error-detector.js.map +1 -0
  93. package/dist/execution/evidence-capture.d.ts +8 -0
  94. package/dist/execution/evidence-capture.js +37 -0
  95. package/dist/execution/evidence-capture.js.map +1 -0
  96. package/dist/execution/index.d.ts +5 -0
  97. package/dist/execution/index.js +7 -0
  98. package/dist/execution/index.js.map +1 -0
  99. package/dist/execution/step-handlers.d.ts +48 -0
  100. package/dist/execution/step-handlers.js +349 -0
  101. package/dist/execution/step-handlers.js.map +1 -0
  102. package/dist/execution/test-data.d.ts +50 -0
  103. package/dist/execution/test-data.js +160 -0
  104. package/dist/execution/test-data.js.map +1 -0
  105. package/dist/execution/workflow-executor.d.ts +56 -0
  106. package/dist/execution/workflow-executor.js +331 -0
  107. package/dist/execution/workflow-executor.js.map +1 -0
  108. package/dist/index.d.ts +2 -0
  109. package/dist/index.js +5 -0
  110. package/dist/index.js.map +1 -0
  111. package/dist/mcp/entry.d.ts +2 -0
  112. package/dist/mcp/entry.js +5 -0
  113. package/dist/mcp/entry.js.map +1 -0
  114. package/dist/mcp/index.d.ts +2 -0
  115. package/dist/mcp/index.js +4 -0
  116. package/dist/mcp/index.js.map +1 -0
  117. package/dist/mcp/server.d.ts +3 -0
  118. package/dist/mcp/server.js +19 -0
  119. package/dist/mcp/server.js.map +1 -0
  120. package/dist/mcp/tools.d.ts +2 -0
  121. package/dist/mcp/tools.js +162 -0
  122. package/dist/mcp/tools.js.map +1 -0
  123. package/dist/planning/heuristic-planner.d.ts +7 -0
  124. package/dist/planning/heuristic-planner.js +238 -0
  125. package/dist/planning/heuristic-planner.js.map +1 -0
  126. package/dist/planning/index.d.ts +3 -0
  127. package/dist/planning/index.js +5 -0
  128. package/dist/planning/index.js.map +1 -0
  129. package/dist/planning/plan-schema.d.ts +74 -0
  130. package/dist/planning/plan-schema.js +39 -0
  131. package/dist/planning/plan-schema.js.map +1 -0
  132. package/dist/planning/workflow-planner.d.ts +39 -0
  133. package/dist/planning/workflow-planner.js +211 -0
  134. package/dist/planning/workflow-planner.js.map +1 -0
  135. package/dist/reports/health-scorer.d.ts +14 -0
  136. package/dist/reports/health-scorer.js +88 -0
  137. package/dist/reports/health-scorer.js.map +1 -0
  138. package/dist/reports/html-generator.d.ts +10 -0
  139. package/dist/reports/html-generator.js +155 -0
  140. package/dist/reports/html-generator.js.map +1 -0
  141. package/dist/reports/index.d.ts +4 -0
  142. package/dist/reports/index.js +6 -0
  143. package/dist/reports/index.js.map +1 -0
  144. package/dist/reports/markdown-generator.d.ts +10 -0
  145. package/dist/reports/markdown-generator.js +334 -0
  146. package/dist/reports/markdown-generator.js.map +1 -0
  147. package/dist/reports/priority-ranker.d.ts +22 -0
  148. package/dist/reports/priority-ranker.js +608 -0
  149. package/dist/reports/priority-ranker.js.map +1 -0
  150. package/dist/screenshots/dual-format.d.ts +14 -0
  151. package/dist/screenshots/dual-format.js +59 -0
  152. package/dist/screenshots/dual-format.js.map +1 -0
  153. package/dist/screenshots/index.d.ts +2 -0
  154. package/dist/screenshots/index.js +4 -0
  155. package/dist/screenshots/index.js.map +1 -0
  156. package/dist/screenshots/screenshot-manager.d.ts +33 -0
  157. package/dist/screenshots/screenshot-manager.js +86 -0
  158. package/dist/screenshots/screenshot-manager.js.map +1 -0
  159. package/dist/testing/accessibility-auditor.d.ts +23 -0
  160. package/dist/testing/accessibility-auditor.js +44 -0
  161. package/dist/testing/accessibility-auditor.js.map +1 -0
  162. package/dist/testing/index.d.ts +4 -0
  163. package/dist/testing/index.js +5 -0
  164. package/dist/testing/index.js.map +1 -0
  165. package/dist/testing/meta-auditor.d.ts +16 -0
  166. package/dist/testing/meta-auditor.js +268 -0
  167. package/dist/testing/meta-auditor.js.map +1 -0
  168. package/dist/testing/performance-monitor.d.ts +15 -0
  169. package/dist/testing/performance-monitor.js +64 -0
  170. package/dist/testing/performance-monitor.js.map +1 -0
  171. package/dist/types/artifacts.d.ts +58 -0
  172. package/dist/types/artifacts.js +3 -0
  173. package/dist/types/artifacts.js.map +1 -0
  174. package/dist/types/discovery.d.ts +124 -0
  175. package/dist/types/discovery.js +3 -0
  176. package/dist/types/discovery.js.map +1 -0
  177. package/dist/types/execution.d.ts +154 -0
  178. package/dist/types/execution.js +3 -0
  179. package/dist/types/execution.js.map +1 -0
  180. package/dist/types/index.d.ts +2 -0
  181. package/dist/types/index.js +4 -0
  182. package/dist/types/index.js.map +1 -0
  183. package/dist/utils/sanitizer.d.ts +25 -0
  184. package/dist/utils/sanitizer.js +98 -0
  185. package/dist/utils/sanitizer.js.map +1 -0
  186. package/package.json +86 -0
  187. package/templates/report.hbs +202 -0
  188. package/templates/styles/report.css +607 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.js","sourceRoot":"","sources":["../../src/mcp/tools.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { SitemapNode, WorkflowPlan } from '../types/discovery.js';
2
+ /**
3
+ * Generates workflow plans from sitemap data using heuristics instead of AI.
4
+ * Produces the same WorkflowPlan[] format that Gemini returns, so downstream
5
+ * pipeline stages (executor, analyzer, reporter) work unchanged.
6
+ */
7
+ export declare function generateHeuristicPlans(sitemap: SitemapNode): WorkflowPlan[];
@@ -0,0 +1,238 @@
1
+ // Generates basic workflow plans from discovered page elements without AI (fallback when GEMINI_API_KEY is not set)
2
+ /** Maximum number of workflows to generate (keeps runtime manageable) */
3
+ const MAX_WORKFLOWS = 8;
4
+ /**
5
+ * Generates workflow plans from sitemap data using heuristics instead of AI.
6
+ * Produces the same WorkflowPlan[] format that Gemini returns, so downstream
7
+ * pipeline stages (executor, analyzer, reporter) work unchanged.
8
+ */
9
+ export function generateHeuristicPlans(sitemap) {
10
+ const pages = collectAllPages(sitemap);
11
+ const plans = [];
12
+ // 1. Form workflows — highest value (signup, login, contact, search)
13
+ for (const page of pages) {
14
+ for (const form of page.pageData.forms) {
15
+ if (plans.length >= MAX_WORKFLOWS)
16
+ break;
17
+ const plan = buildFormWorkflow(page, form);
18
+ if (plan)
19
+ plans.push(plan);
20
+ }
21
+ if (plans.length >= MAX_WORKFLOWS)
22
+ break;
23
+ }
24
+ // 2. CTA / prominent button workflows
25
+ for (const page of pages) {
26
+ const ctaButtons = page.pageData.buttons
27
+ .filter(b => b.visible && b.text.trim().length > 0)
28
+ .slice(0, 3); // top 3 visible buttons per page
29
+ for (const button of ctaButtons) {
30
+ if (plans.length >= MAX_WORKFLOWS)
31
+ break;
32
+ const plan = buildButtonWorkflow(page, button);
33
+ if (plan)
34
+ plans.push(plan);
35
+ }
36
+ if (plans.length >= MAX_WORKFLOWS)
37
+ break;
38
+ }
39
+ // 3. Navigation workflows — verify key internal links load without errors
40
+ const navPlan = buildNavigationWorkflow(pages);
41
+ if (navPlan && plans.length < MAX_WORKFLOWS) {
42
+ plans.push(navPlan);
43
+ }
44
+ // Sort: critical first, then important, then nice-to-have
45
+ const priorityOrder = { critical: 0, important: 1, 'nice-to-have': 2 };
46
+ plans.sort((a, b) => priorityOrder[a.priority] - priorityOrder[b.priority]);
47
+ return plans;
48
+ }
49
+ // ─── Workflow builders ───────────────────────────────────────────────
50
+ function buildFormWorkflow(page, form) {
51
+ if (form.fields.length === 0)
52
+ return null;
53
+ const steps = [];
54
+ // Step 1: Navigate to the page containing the form
55
+ steps.push({
56
+ action: 'navigate',
57
+ selector: page.url,
58
+ value: undefined,
59
+ expectedResult: `Page "${page.pageData.title}" loads successfully`,
60
+ confidence: 1.0,
61
+ });
62
+ // Step 2-N: Fill each field with synthetic test data
63
+ for (const field of form.fields) {
64
+ const testValue = syntheticValue(field.type, field.name, field.label);
65
+ const label = field.label || field.name || field.type;
66
+ steps.push({
67
+ action: 'fill',
68
+ selector: fieldSelector(form, field),
69
+ value: testValue,
70
+ expectedResult: `Field "${label}" accepts input`,
71
+ confidence: 0.7,
72
+ });
73
+ }
74
+ // Final step: Submit (click submit button or the form's submit element)
75
+ steps.push({
76
+ action: 'click',
77
+ selector: `${form.selector} [type="submit"], ${form.selector} button:last-of-type`,
78
+ value: undefined,
79
+ expectedResult: 'Form submits without errors',
80
+ confidence: 0.6,
81
+ });
82
+ // Add an expect step to verify no console errors
83
+ steps.push({
84
+ action: 'expect',
85
+ selector: 'body',
86
+ value: undefined,
87
+ expectedResult: 'Page does not show error messages after submission',
88
+ confidence: 0.7,
89
+ });
90
+ const formName = classifyForm(form);
91
+ const priority = formName.includes('login') || formName.includes('signup') || formName.includes('search')
92
+ ? 'critical'
93
+ : 'important';
94
+ return {
95
+ workflowName: `${capitalize(formName)} Form Submission`,
96
+ description: `Fill and submit the ${formName} form on ${page.pageData.title} to verify it works without errors`,
97
+ steps,
98
+ priority,
99
+ estimatedDuration: 10 + form.fields.length * 2,
100
+ source: 'auto-discovered',
101
+ };
102
+ }
103
+ function buildButtonWorkflow(page, button) {
104
+ const text = button.text.trim();
105
+ if (!text)
106
+ return null;
107
+ const steps = [
108
+ {
109
+ action: 'navigate',
110
+ selector: page.url,
111
+ value: undefined,
112
+ expectedResult: `Page "${page.pageData.title}" loads successfully`,
113
+ confidence: 1.0,
114
+ },
115
+ {
116
+ action: 'click',
117
+ selector: button.selector,
118
+ value: undefined,
119
+ expectedResult: `Button "${text}" responds to click without errors`,
120
+ confidence: 0.7,
121
+ },
122
+ {
123
+ action: 'expect',
124
+ selector: 'body',
125
+ value: undefined,
126
+ expectedResult: 'Page does not show error state after button click',
127
+ confidence: 0.7,
128
+ },
129
+ ];
130
+ return {
131
+ workflowName: `Click "${text}" Button`,
132
+ description: `Click the "${text}" button on ${page.pageData.title} and verify no errors occur`,
133
+ steps,
134
+ priority: 'nice-to-have',
135
+ estimatedDuration: 8,
136
+ source: 'auto-discovered',
137
+ };
138
+ }
139
+ function buildNavigationWorkflow(pages) {
140
+ // Pick up to 5 unique internal pages (prefer shallow depth)
141
+ const navTargets = pages
142
+ .filter(p => p.depth <= 2)
143
+ .slice(0, 5);
144
+ if (navTargets.length === 0)
145
+ return null;
146
+ const steps = navTargets.map(page => ({
147
+ action: 'navigate',
148
+ selector: page.url,
149
+ value: undefined,
150
+ expectedResult: `"${page.pageData.title}" loads without errors`,
151
+ confidence: 1.0,
152
+ }));
153
+ return {
154
+ workflowName: 'Core Page Navigation',
155
+ description: `Navigate to ${navTargets.length} key pages and verify they load without errors`,
156
+ steps,
157
+ priority: 'important',
158
+ estimatedDuration: navTargets.length * 5,
159
+ source: 'auto-discovered',
160
+ };
161
+ }
162
+ // ─── Helpers ─────────────────────────────────────────────────────────
163
+ /** Recursively collect all pages from sitemap tree, sorted by importance */
164
+ function collectAllPages(node) {
165
+ const pages = [node];
166
+ for (const child of node.children) {
167
+ pages.push(...collectAllPages(child));
168
+ }
169
+ // Sort: pages with forms first, then by number of interactive elements, then by depth
170
+ pages.sort((a, b) => {
171
+ const aScore = a.pageData.forms.length * 10 + a.pageData.buttons.length * 2;
172
+ const bScore = b.pageData.forms.length * 10 + b.pageData.buttons.length * 2;
173
+ if (aScore !== bScore)
174
+ return bScore - aScore;
175
+ return a.depth - b.depth;
176
+ });
177
+ return pages;
178
+ }
179
+ /** Build a Playwright selector for a form field */
180
+ function fieldSelector(form, field) {
181
+ if (field.label) {
182
+ return `${form.selector} [aria-label="${field.label}"], ${form.selector} input[name="${field.name}"]`;
183
+ }
184
+ if (field.name) {
185
+ return `${form.selector} [name="${field.name}"]`;
186
+ }
187
+ return `${form.selector} input[type="${field.type}"]`;
188
+ }
189
+ /** Generate synthetic test data based on field type */
190
+ function syntheticValue(type, name, label) {
191
+ const hint = `${type} ${name} ${label}`.toLowerCase();
192
+ if (hint.includes('email'))
193
+ return 'test@example.com';
194
+ if (hint.includes('password') || hint.includes('pass'))
195
+ return 'TestPass123!';
196
+ if (hint.includes('phone') || hint.includes('tel'))
197
+ return '555-0100';
198
+ if (hint.includes('url') || hint.includes('website'))
199
+ return 'https://example.com';
200
+ if (hint.includes('zip') || hint.includes('postal'))
201
+ return '90210';
202
+ if (hint.includes('name') && hint.includes('first'))
203
+ return 'Test';
204
+ if (hint.includes('name') && hint.includes('last'))
205
+ return 'User';
206
+ if (hint.includes('name'))
207
+ return 'Test User';
208
+ if (hint.includes('search') || hint.includes('query') || hint.includes('q'))
209
+ return 'test search query';
210
+ if (hint.includes('message') || hint.includes('comment') || hint.includes('textarea'))
211
+ return 'This is a test message from Afterburn.';
212
+ if (type === 'number')
213
+ return '42';
214
+ if (type === 'date')
215
+ return '2025-01-15';
216
+ return 'test input';
217
+ }
218
+ /** Classify a form by its fields and action */
219
+ function classifyForm(form) {
220
+ const fieldHints = form.fields.map(f => `${f.type} ${f.name} ${f.label}`.toLowerCase()).join(' ');
221
+ const action = (form.action || '').toLowerCase();
222
+ if (fieldHints.includes('password') && fieldHints.includes('email')) {
223
+ return fieldHints.includes('confirm') || fieldHints.includes('register') ? 'signup' : 'login';
224
+ }
225
+ if (action.includes('search') || fieldHints.includes('search') || fieldHints.includes('query'))
226
+ return 'search';
227
+ if (action.includes('contact') || fieldHints.includes('message') || fieldHints.includes('subject'))
228
+ return 'contact';
229
+ if (action.includes('subscribe') || fieldHints.includes('newsletter'))
230
+ return 'subscribe';
231
+ if (fieldHints.includes('password'))
232
+ return 'login';
233
+ return 'general';
234
+ }
235
+ function capitalize(s) {
236
+ return s.charAt(0).toUpperCase() + s.slice(1);
237
+ }
238
+ //# sourceMappingURL=heuristic-planner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"heuristic-planner.js","sourceRoot":"","sources":["../../src/planning/heuristic-planner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export * from './plan-schema.js';
2
+ export { WorkflowPlanner } from './workflow-planner.js';
3
+ export { generateHeuristicPlans } from './heuristic-planner.js';
@@ -0,0 +1,5 @@
1
+ // Planning module barrel exports
2
+ export * from './plan-schema.js';
3
+ export { WorkflowPlanner } from './workflow-planner.js';
4
+ export { generateHeuristicPlans } from './heuristic-planner.js';
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/planning/index.ts"],"names":[],"mappings":"AAAA,iCAAiC;AAEjC,cAAc,kBAAkB,CAAC;AACjC,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC"}
@@ -0,0 +1,74 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * Single step in a workflow plan
4
+ */
5
+ export declare const WorkflowStepSchema: z.ZodObject<{
6
+ action: z.ZodEnum<{
7
+ select: "select";
8
+ navigate: "navigate";
9
+ click: "click";
10
+ fill: "fill";
11
+ wait: "wait";
12
+ expect: "expect";
13
+ }>;
14
+ selector: z.ZodString;
15
+ value: z.ZodOptional<z.ZodString>;
16
+ expectedResult: z.ZodString;
17
+ confidence: z.ZodNumber;
18
+ }, z.core.$strip>;
19
+ /**
20
+ * Complete AI-generated workflow test plan
21
+ */
22
+ export declare const WorkflowPlanSchema: z.ZodObject<{
23
+ workflowName: z.ZodString;
24
+ description: z.ZodString;
25
+ steps: z.ZodArray<z.ZodObject<{
26
+ action: z.ZodEnum<{
27
+ select: "select";
28
+ navigate: "navigate";
29
+ click: "click";
30
+ fill: "fill";
31
+ wait: "wait";
32
+ expect: "expect";
33
+ }>;
34
+ selector: z.ZodString;
35
+ value: z.ZodOptional<z.ZodString>;
36
+ expectedResult: z.ZodString;
37
+ confidence: z.ZodNumber;
38
+ }, z.core.$strip>>;
39
+ priority: z.ZodEnum<{
40
+ critical: "critical";
41
+ important: "important";
42
+ "nice-to-have": "nice-to-have";
43
+ }>;
44
+ estimatedDuration: z.ZodNumber;
45
+ }, z.core.$strip>;
46
+ /**
47
+ * Gemini structured output wrapper (array of workflows)
48
+ */
49
+ export declare const WorkflowPlansResponseSchema: z.ZodObject<{
50
+ workflows: z.ZodArray<z.ZodObject<{
51
+ workflowName: z.ZodString;
52
+ description: z.ZodString;
53
+ steps: z.ZodArray<z.ZodObject<{
54
+ action: z.ZodEnum<{
55
+ select: "select";
56
+ navigate: "navigate";
57
+ click: "click";
58
+ fill: "fill";
59
+ wait: "wait";
60
+ expect: "expect";
61
+ }>;
62
+ selector: z.ZodString;
63
+ value: z.ZodOptional<z.ZodString>;
64
+ expectedResult: z.ZodString;
65
+ confidence: z.ZodNumber;
66
+ }, z.core.$strip>>;
67
+ priority: z.ZodEnum<{
68
+ critical: "critical";
69
+ important: "important";
70
+ "nice-to-have": "nice-to-have";
71
+ }>;
72
+ estimatedDuration: z.ZodNumber;
73
+ }, z.core.$strip>>;
74
+ }, z.core.$strip>;
@@ -0,0 +1,39 @@
1
+ // Zod schemas for AI-generated workflow plans (structured output validation)
2
+ import { z } from 'zod';
3
+ /**
4
+ * Single step in a workflow plan
5
+ */
6
+ export const WorkflowStepSchema = z.object({
7
+ action: z.enum(['navigate', 'click', 'fill', 'select', 'wait', 'expect'])
8
+ .describe('Action to perform'),
9
+ selector: z.string()
10
+ .describe('Playwright selector for the target element (role=, label=, text=, or CSS)'),
11
+ value: z.string().optional()
12
+ .describe('Value to fill or select'),
13
+ expectedResult: z.string()
14
+ .describe('What should happen after this step'),
15
+ confidence: z.number().min(0).max(1)
16
+ .describe('How confident are you this step will work (0-1)'),
17
+ });
18
+ /**
19
+ * Complete AI-generated workflow test plan
20
+ */
21
+ export const WorkflowPlanSchema = z.object({
22
+ workflowName: z.string()
23
+ .describe('Human-readable name like "User Signup Flow"'),
24
+ description: z.string()
25
+ .describe('What this workflow tests in plain English'),
26
+ steps: z.array(WorkflowStepSchema).min(1).max(20)
27
+ .describe('Step-by-step test actions'),
28
+ priority: z.enum(['critical', 'important', 'nice-to-have'])
29
+ .describe('Importance level'),
30
+ estimatedDuration: z.number()
31
+ .describe('Estimated seconds to execute'),
32
+ });
33
+ /**
34
+ * Gemini structured output wrapper (array of workflows)
35
+ */
36
+ export const WorkflowPlansResponseSchema = z.object({
37
+ workflows: z.array(WorkflowPlanSchema),
38
+ });
39
+ //# sourceMappingURL=plan-schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan-schema.js","sourceRoot":"","sources":["../../src/planning/plan-schema.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAE7E,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;GAEG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC;IACzC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;SACtE,QAAQ,CAAC,mBAAmB,CAAC;IAChC,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;SACjB,QAAQ,CAAC,2EAA2E,CAAC;IACxF,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;SACzB,QAAQ,CAAC,yBAAyB,CAAC;IACtC,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE;SACvB,QAAQ,CAAC,oCAAoC,CAAC;IACjD,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;SACjC,QAAQ,CAAC,iDAAiD,CAAC;CAC/D,CAAC,CAAC;AAEH;;GAEG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC;IACzC,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE;SACrB,QAAQ,CAAC,6CAA6C,CAAC;IAC1D,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE;SACpB,QAAQ,CAAC,2CAA2C,CAAC;IACxD,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC;SAC9C,QAAQ,CAAC,2BAA2B,CAAC;IACxC,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,WAAW,EAAE,cAAc,CAAC,CAAC;SACxD,QAAQ,CAAC,kBAAkB,CAAC;IAC/B,iBAAiB,EAAE,CAAC,CAAC,MAAM,EAAE;SAC1B,QAAQ,CAAC,8BAA8B,CAAC;CAC5C,CAAC,CAAC;AAEH;;GAEG;AACH,MAAM,CAAC,MAAM,2BAA2B,GAAG,CAAC,CAAC,MAAM,CAAC;IAClD,SAAS,EAAE,CAAC,CAAC,KAAK,CAAC,kBAAkB,CAAC;CACvC,CAAC,CAAC"}
@@ -0,0 +1,39 @@
1
+ import { GeminiClient } from '../ai/index.js';
2
+ import type { SitemapNode, WorkflowPlan } from '../types/discovery.js';
3
+ /**
4
+ * Generates realistic user workflow test plans from sitemap using Gemini AI.
5
+ * Plans include step-by-step actions with Playwright selectors and confidence scores.
6
+ */
7
+ export declare class WorkflowPlanner {
8
+ private gemini;
9
+ constructor(geminiClient: GeminiClient);
10
+ /**
11
+ * Generate workflow test plans from sitemap structure
12
+ * @param sitemap Hierarchical sitemap tree from Phase 2 discovery
13
+ * @param userHints Optional user-specified workflows to prioritize (from --flows flag)
14
+ * @returns Array of workflow plans sorted by priority
15
+ */
16
+ generatePlans(sitemap: SitemapNode, userHints?: string[]): Promise<WorkflowPlan[]>;
17
+ /**
18
+ * Create condensed text summary of sitemap for LLM prompt
19
+ * Truncates at maxChars to stay within token limits
20
+ */
21
+ private summarizeSitemap;
22
+ /**
23
+ * Recursively collect all pages from sitemap tree
24
+ */
25
+ private collectPages;
26
+ /**
27
+ * Score page importance for prioritization
28
+ * Higher score = more likely to contain important workflows
29
+ */
30
+ private getPageImportance;
31
+ /**
32
+ * Format a single page as text summary
33
+ */
34
+ private formatPageSummary;
35
+ /**
36
+ * Format form as concise description
37
+ */
38
+ private formatForm;
39
+ }
@@ -0,0 +1,211 @@
1
+ // AI-powered workflow plan generator from sitemap data
2
+ import { WorkflowPlansResponseSchema } from './plan-schema.js';
3
+ /**
4
+ * Generates realistic user workflow test plans from sitemap using Gemini AI.
5
+ * Plans include step-by-step actions with Playwright selectors and confidence scores.
6
+ */
7
+ export class WorkflowPlanner {
8
+ gemini;
9
+ constructor(geminiClient) {
10
+ this.gemini = geminiClient;
11
+ }
12
+ /**
13
+ * Generate workflow test plans from sitemap structure
14
+ * @param sitemap Hierarchical sitemap tree from Phase 2 discovery
15
+ * @param userHints Optional user-specified workflows to prioritize (from --flows flag)
16
+ * @returns Array of workflow plans sorted by priority
17
+ */
18
+ async generatePlans(sitemap, userHints) {
19
+ try {
20
+ // Create condensed sitemap summary for LLM (token-efficient)
21
+ const sitemapSummary = this.summarizeSitemap(sitemap, { maxChars: 40000 });
22
+ // Build prompt with sitemap and user hints
23
+ let prompt = `You are analyzing a website to identify realistic user workflows that should be tested.
24
+
25
+ SITE STRUCTURE:
26
+ ${sitemapSummary}
27
+ `;
28
+ if (userHints && userHints.length > 0) {
29
+ prompt += `
30
+ USER-SPECIFIED WORKFLOWS TO PRIORITIZE:
31
+ ${userHints.map(hint => `- ${hint}`).join('\n')}
32
+ `;
33
+ }
34
+ prompt += `
35
+ Generate workflow test plans for this website. For each workflow:
36
+
37
+ 1. Identify a realistic user journey (signup, login, checkout, search, contact form, navigation, etc.)
38
+ 2. Create step-by-step plan using Playwright selectors
39
+ 3. Use selector syntax that works directly with page.click/fill/select/isVisible:
40
+ - Preferred: role=button[name="Sign Up"], role=textbox[name="Email"]
41
+ - Also valid: label=Email, text=Sign Up, CSS selectors
42
+ - Do NOT use JS helper strings like getByRole(...) or getByLabel(...)
43
+ 4. Include expected result for each step (what the user should see after the action)
44
+ 5. Assign confidence 0-1 for each step (1.0 = selector definitely exists, 0.5 = guessing)
45
+ 6. Assign priority: critical (auth, core features), important (secondary features), nice-to-have (edge cases)
46
+
47
+ Focus on workflows that a real user would actually do. Skip admin/internal paths.
48
+ If user provided hints, those workflows are top priority.
49
+
50
+ Return JSON with a "workflows" array.`;
51
+ // Call Gemini with structured output
52
+ let response;
53
+ try {
54
+ response = await this.gemini.generateStructured(prompt, WorkflowPlansResponseSchema);
55
+ }
56
+ catch (error) {
57
+ // Retry once with simpler prompt if JSON parsing fails
58
+ console.warn('Gemini API call failed, retrying with simpler prompt:', error);
59
+ const simplerPrompt = `Analyze this website and generate 3-5 realistic user workflow test plans.
60
+
61
+ ${sitemapSummary}
62
+
63
+ Return JSON with a "workflows" array where each workflow has: workflowName, description, steps (action, selector, value, expectedResult, confidence), priority, estimatedDuration.`;
64
+ response = await this.gemini.generateStructured(simplerPrompt, WorkflowPlansResponseSchema);
65
+ }
66
+ // Post-process workflows
67
+ const workflows = response.workflows
68
+ .map(workflow => {
69
+ // Filter out very low-confidence steps (likely hallucinated)
70
+ const filteredSteps = workflow.steps.filter(step => step.confidence >= 0.3);
71
+ // Flag workflows with low-confidence steps
72
+ const hasLowConfidence = filteredSteps.some(step => step.confidence < 0.7);
73
+ const description = hasLowConfidence
74
+ ? `${workflow.description} [Low confidence - verify selectors]`
75
+ : workflow.description;
76
+ // Determine source
77
+ const isUserHint = userHints?.some(hint => workflow.workflowName.toLowerCase().includes(hint.toLowerCase()) ||
78
+ workflow.description.toLowerCase().includes(hint.toLowerCase())) ?? false;
79
+ return {
80
+ ...workflow,
81
+ description,
82
+ steps: filteredSteps,
83
+ source: isUserHint ? 'user-hint' : 'auto-discovered',
84
+ };
85
+ })
86
+ // Remove workflows with no valid steps
87
+ .filter(workflow => workflow.steps.length > 0)
88
+ // Sort by priority
89
+ .sort((a, b) => {
90
+ const priorityOrder = { critical: 0, important: 1, 'nice-to-have': 2 };
91
+ const aPriority = priorityOrder[a.priority];
92
+ const bPriority = priorityOrder[b.priority];
93
+ // User hints first within same priority
94
+ if (aPriority === bPriority) {
95
+ if (a.source === 'user-hint' && b.source !== 'user-hint')
96
+ return -1;
97
+ if (a.source !== 'user-hint' && b.source === 'user-hint')
98
+ return 1;
99
+ }
100
+ return aPriority - bPriority;
101
+ });
102
+ return workflows;
103
+ }
104
+ catch (error) {
105
+ // Graceful degradation: don't crash, return empty array
106
+ console.warn('Failed to generate workflow plans:', error);
107
+ return [];
108
+ }
109
+ }
110
+ /**
111
+ * Create condensed text summary of sitemap for LLM prompt
112
+ * Truncates at maxChars to stay within token limits
113
+ */
114
+ summarizeSitemap(node, options) {
115
+ const maxChars = options?.maxChars ?? 40000;
116
+ let output = '';
117
+ let charCount = 0;
118
+ let pageCount = 0;
119
+ let truncated = false;
120
+ // Sort pages by importance: forms first, then interactive elements, then depth
121
+ const sortedPages = this.collectPages(node).sort((a, b) => {
122
+ const aScore = this.getPageImportance(a.pageData);
123
+ const bScore = this.getPageImportance(b.pageData);
124
+ if (aScore !== bScore)
125
+ return bScore - aScore; // Higher score first
126
+ return a.depth - b.depth; // Shallower first
127
+ });
128
+ // Add pages until we hit the char limit
129
+ for (const page of sortedPages) {
130
+ const pageSummary = this.formatPageSummary(page, page.depth);
131
+ if (charCount + pageSummary.length > maxChars) {
132
+ truncated = true;
133
+ break;
134
+ }
135
+ output += pageSummary;
136
+ charCount += pageSummary.length;
137
+ pageCount++;
138
+ }
139
+ // Add truncation notice if needed
140
+ if (truncated) {
141
+ const remaining = sortedPages.length - pageCount;
142
+ output += `\n... and ${remaining} more pages (truncated for brevity). Focus workflows on the pages shown above.\n`;
143
+ }
144
+ return output;
145
+ }
146
+ /**
147
+ * Recursively collect all pages from sitemap tree
148
+ */
149
+ collectPages(node) {
150
+ const pages = [node];
151
+ for (const child of node.children) {
152
+ pages.push(...this.collectPages(child));
153
+ }
154
+ return pages;
155
+ }
156
+ /**
157
+ * Score page importance for prioritization
158
+ * Higher score = more likely to contain important workflows
159
+ */
160
+ getPageImportance(pageData) {
161
+ let score = 0;
162
+ // Forms are high priority (auth, search, contact, etc.)
163
+ score += pageData.forms.length * 10;
164
+ // Buttons indicate interactions
165
+ score += pageData.buttons.length * 2;
166
+ // Menus and other interactive elements
167
+ score += pageData.menus.length * 3;
168
+ score += pageData.otherInteractive.length * 1;
169
+ // Links indicate navigation structure
170
+ score += Math.min(pageData.links.length, 20) * 0.5;
171
+ return score;
172
+ }
173
+ /**
174
+ * Format a single page as text summary
175
+ */
176
+ formatPageSummary(node, depth) {
177
+ const indent = ' '.repeat(depth);
178
+ const { pageData } = node;
179
+ let summary = `${indent}Page: ${pageData.title} (${node.path})\n`;
180
+ // Forms
181
+ if (pageData.forms.length > 0) {
182
+ const formDescriptions = pageData.forms.map(form => this.formatForm(form));
183
+ summary += `${indent} Forms: ${formDescriptions.join('; ')}\n`;
184
+ }
185
+ // Buttons
186
+ if (pageData.buttons.length > 0) {
187
+ const visibleButtons = pageData.buttons.filter(b => b.visible).slice(0, 10); // Limit to avoid token bloat
188
+ const buttonTexts = visibleButtons.map(b => `"${b.text}"`).join(', ');
189
+ summary += `${indent} Buttons: ${buttonTexts}\n`;
190
+ }
191
+ // Menus
192
+ if (pageData.menus.length > 0) {
193
+ const menuTexts = pageData.menus.slice(0, 5).map(m => `"${m.text}"`).join(', ');
194
+ summary += `${indent} Menus: ${menuTexts}\n`;
195
+ }
196
+ // Link counts
197
+ const internalLinks = pageData.links.filter(l => l.isInternal).length;
198
+ const externalLinks = pageData.links.filter(l => !l.isInternal).length;
199
+ summary += `${indent} Links: ${internalLinks} internal, ${externalLinks} external\n`;
200
+ summary += '\n';
201
+ return summary;
202
+ }
203
+ /**
204
+ * Format form as concise description
205
+ */
206
+ formatForm(form) {
207
+ const fieldNames = form.fields.map(f => f.name || f.label).filter(Boolean).slice(0, 8);
208
+ return `${form.method} form (${fieldNames.join(', ')})`;
209
+ }
210
+ }
211
+ //# sourceMappingURL=workflow-planner.js.map