@probelabs/visor 0.1.113 → 0.1.122

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 (120) hide show
  1. package/defaults/workflow-builder.tests.yaml +363 -0
  2. package/defaults/workflow-builder.yaml +720 -0
  3. package/dist/ai-review-service.d.ts.map +1 -1
  4. package/dist/cli-main.d.ts.map +1 -1
  5. package/dist/cli.d.ts.map +1 -1
  6. package/dist/defaults/workflow-builder.tests.yaml +363 -0
  7. package/dist/defaults/workflow-builder.yaml +720 -0
  8. package/dist/docs/workflow-creation-guide.md +1274 -0
  9. package/dist/frontends/slack-frontend.d.ts +3 -0
  10. package/dist/frontends/slack-frontend.d.ts.map +1 -1
  11. package/dist/generated/config-schema.d.ts +14 -6
  12. package/dist/generated/config-schema.d.ts.map +1 -1
  13. package/dist/generated/config-schema.json +14 -6
  14. package/dist/index.js +36879 -13895
  15. package/dist/logger.d.ts +9 -0
  16. package/dist/logger.d.ts.map +1 -1
  17. package/dist/mcp-server.d.ts +4 -4
  18. package/dist/output/traces/{run-2026-01-21T12-31-10-108Z.ndjson → run-2026-01-28T13-56-32-263Z.ndjson} +84 -84
  19. package/dist/output/traces/run-2026-01-28T13-57-13-140Z.ndjson +1357 -0
  20. package/dist/providers/ai-check-provider.d.ts.map +1 -1
  21. package/dist/providers/check-provider.interface.d.ts +15 -1
  22. package/dist/providers/check-provider.interface.d.ts.map +1 -1
  23. package/dist/providers/command-check-provider.d.ts.map +1 -1
  24. package/dist/providers/git-checkout-provider.d.ts.map +1 -1
  25. package/dist/sdk/{check-provider-registry-534KL5HT.mjs → check-provider-registry-JMNLGIMJ.mjs} +11 -11
  26. package/dist/sdk/{chunk-AIVFBIS4.mjs → chunk-35NT3725.mjs} +30 -10
  27. package/dist/sdk/chunk-35NT3725.mjs.map +1 -0
  28. package/dist/sdk/{chunk-AGIZJ4UZ.mjs → chunk-3NMLT3YS.mjs} +42 -8
  29. package/dist/sdk/chunk-3NMLT3YS.mjs.map +1 -0
  30. package/dist/sdk/{chunk-AK6BVWIT.mjs → chunk-7GUAFV6L.mjs} +2 -2
  31. package/dist/sdk/{chunk-QY2XYPEV.mjs → chunk-CUNPH6TR.mjs} +18 -10
  32. package/dist/sdk/chunk-CUNPH6TR.mjs.map +1 -0
  33. package/dist/sdk/{chunk-HTOKWMPO.mjs → chunk-HQL734ZI.mjs} +2 -2
  34. package/dist/sdk/{chunk-7UK3NIIT.mjs → chunk-IHZOSIF4.mjs} +2 -2
  35. package/dist/sdk/{chunk-AUT26LHW.mjs → chunk-J2QWVDXK.mjs} +2 -2
  36. package/dist/sdk/{chunk-QR7MOMJH.mjs → chunk-J6EVEXC2.mjs} +2 -2
  37. package/dist/sdk/{chunk-SIWNBRTK.mjs → chunk-SWEEZ5D5.mjs} +3 -3
  38. package/dist/sdk/{chunk-23L3QRYX.mjs → chunk-VPEQOQ7G.mjs} +279 -70
  39. package/dist/sdk/chunk-VPEQOQ7G.mjs.map +1 -0
  40. package/dist/sdk/{command-executor-TYUV6HUS.mjs → command-executor-Q7MHJKZJ.mjs} +3 -3
  41. package/dist/sdk/{config-YNC2EOOT.mjs → config-MK4XTU45.mjs} +3 -3
  42. package/dist/sdk/{failure-condition-evaluator-YGTF2GHG.mjs → failure-condition-evaluator-HB35XRLZ.mjs} +4 -4
  43. package/dist/sdk/{github-frontend-SIAEOCON.mjs → github-frontend-6Q4BISZX.mjs} +4 -4
  44. package/dist/sdk/{host-DXUYTNMU.mjs → host-P5NQICP7.mjs} +3 -3
  45. package/dist/sdk/{liquid-extensions-PKWCKK7E.mjs → liquid-extensions-DFDEBMUI.mjs} +4 -4
  46. package/dist/sdk/{memory-store-XGBB7LX7.mjs → memory-store-RW5N2NGJ.mjs} +3 -3
  47. package/dist/sdk/{prompt-state-YRJY6QAL.mjs → prompt-state-EZYOUG75.mjs} +3 -3
  48. package/dist/sdk/{renderer-schema-LPKN5UJS.mjs → renderer-schema-CKFB5NDB.mjs} +2 -2
  49. package/dist/sdk/{routing-6N45MJ4F.mjs → routing-KZ345OFG.mjs} +5 -5
  50. package/dist/sdk/sdk.d.mts +19 -1
  51. package/dist/sdk/sdk.d.ts +19 -1
  52. package/dist/sdk/sdk.js +421 -75
  53. package/dist/sdk/sdk.js.map +1 -1
  54. package/dist/sdk/sdk.mjs +35 -18
  55. package/dist/sdk/sdk.mjs.map +1 -1
  56. package/dist/sdk/{slack-frontend-BVKW3GD5.mjs → slack-frontend-J442FJWZ.mjs} +61 -3
  57. package/dist/sdk/slack-frontend-J442FJWZ.mjs.map +1 -0
  58. package/dist/sdk/{workflow-registry-R6KSACFR.mjs → workflow-registry-6LZKCWHP.mjs} +3 -3
  59. package/dist/state-machine/context/build-engine-context.d.ts.map +1 -1
  60. package/dist/state-machine/dispatch/history-snapshot.d.ts.map +1 -1
  61. package/dist/state-machine/runner.d.ts.map +1 -1
  62. package/dist/state-machine/states/level-dispatch.d.ts.map +1 -1
  63. package/dist/state-machine/states/routing.d.ts.map +1 -1
  64. package/dist/state-machine/states/wave-planning.d.ts.map +1 -1
  65. package/dist/ter-u14b.json +17826 -0
  66. package/dist/ter-u14n.json +17826 -0
  67. package/dist/test-runner/index.d.ts.map +1 -1
  68. package/dist/traces/{run-2026-01-21T12-31-10-108Z.ndjson → run-2026-01-28T13-56-32-263Z.ndjson} +84 -84
  69. package/dist/traces/run-2026-01-28T13-57-13-140Z.ndjson +1357 -0
  70. package/dist/tui.d.ts +51 -0
  71. package/dist/tui.d.ts.map +1 -0
  72. package/dist/types/cli.d.ts +10 -0
  73. package/dist/types/cli.d.ts.map +1 -1
  74. package/dist/types/config.d.ts +4 -0
  75. package/dist/types/config.d.ts.map +1 -1
  76. package/dist/types/engine.d.ts +3 -0
  77. package/dist/types/engine.d.ts.map +1 -1
  78. package/dist/usr/fonts/AUTHORS +1 -0
  79. package/dist/usr/fonts/LICENSE +94 -0
  80. package/dist/usr/fonts/README +340 -0
  81. package/dist/usr/fonts/ter-u14b.json +17826 -0
  82. package/dist/usr/fonts/ter-u14n.json +17826 -0
  83. package/dist/usr/linux +0 -0
  84. package/dist/usr/windows-ansi +0 -0
  85. package/dist/usr/xterm +0 -0
  86. package/dist/usr/xterm-256color +0 -0
  87. package/dist/usr/xterm.termcap +243 -0
  88. package/dist/usr/xterm.terminfo +1977 -0
  89. package/dist/utils/workspace-manager.d.ts +2 -0
  90. package/dist/utils/workspace-manager.d.ts.map +1 -1
  91. package/dist/utils/worktree-manager.d.ts +5 -0
  92. package/dist/utils/worktree-manager.d.ts.map +1 -1
  93. package/dist/xterm +0 -0
  94. package/dist/xterm.termcap +243 -0
  95. package/package.json +9 -7
  96. package/dist/output/traces/run-2026-01-21T12-32-04-510Z.ndjson +0 -1067
  97. package/dist/sdk/chunk-23L3QRYX.mjs.map +0 -1
  98. package/dist/sdk/chunk-AGIZJ4UZ.mjs.map +0 -1
  99. package/dist/sdk/chunk-AIVFBIS4.mjs.map +0 -1
  100. package/dist/sdk/chunk-QY2XYPEV.mjs.map +0 -1
  101. package/dist/sdk/slack-frontend-BVKW3GD5.mjs.map +0 -1
  102. package/dist/traces/run-2026-01-21T12-32-04-510Z.ndjson +0 -1067
  103. /package/dist/sdk/{check-provider-registry-534KL5HT.mjs.map → check-provider-registry-JMNLGIMJ.mjs.map} +0 -0
  104. /package/dist/sdk/{chunk-AK6BVWIT.mjs.map → chunk-7GUAFV6L.mjs.map} +0 -0
  105. /package/dist/sdk/{chunk-HTOKWMPO.mjs.map → chunk-HQL734ZI.mjs.map} +0 -0
  106. /package/dist/sdk/{chunk-7UK3NIIT.mjs.map → chunk-IHZOSIF4.mjs.map} +0 -0
  107. /package/dist/sdk/{chunk-AUT26LHW.mjs.map → chunk-J2QWVDXK.mjs.map} +0 -0
  108. /package/dist/sdk/{chunk-QR7MOMJH.mjs.map → chunk-J6EVEXC2.mjs.map} +0 -0
  109. /package/dist/sdk/{chunk-SIWNBRTK.mjs.map → chunk-SWEEZ5D5.mjs.map} +0 -0
  110. /package/dist/sdk/{command-executor-TYUV6HUS.mjs.map → command-executor-Q7MHJKZJ.mjs.map} +0 -0
  111. /package/dist/sdk/{config-YNC2EOOT.mjs.map → config-MK4XTU45.mjs.map} +0 -0
  112. /package/dist/sdk/{failure-condition-evaluator-YGTF2GHG.mjs.map → failure-condition-evaluator-HB35XRLZ.mjs.map} +0 -0
  113. /package/dist/sdk/{github-frontend-SIAEOCON.mjs.map → github-frontend-6Q4BISZX.mjs.map} +0 -0
  114. /package/dist/sdk/{host-DXUYTNMU.mjs.map → host-P5NQICP7.mjs.map} +0 -0
  115. /package/dist/sdk/{liquid-extensions-PKWCKK7E.mjs.map → liquid-extensions-DFDEBMUI.mjs.map} +0 -0
  116. /package/dist/sdk/{memory-store-XGBB7LX7.mjs.map → memory-store-RW5N2NGJ.mjs.map} +0 -0
  117. /package/dist/sdk/{prompt-state-YRJY6QAL.mjs.map → prompt-state-EZYOUG75.mjs.map} +0 -0
  118. /package/dist/sdk/{renderer-schema-LPKN5UJS.mjs.map → renderer-schema-CKFB5NDB.mjs.map} +0 -0
  119. /package/dist/sdk/{routing-6N45MJ4F.mjs.map → routing-KZ345OFG.mjs.map} +0 -0
  120. /package/dist/sdk/{workflow-registry-R6KSACFR.mjs.map → workflow-registry-6LZKCWHP.mjs.map} +0 -0
@@ -0,0 +1,720 @@
1
+ version: "1.0"
2
+
3
+ # Meta-workflow for building and editing Visor workflows through AI-powered generation
4
+ # Uses an AI router to interpret user intent and determine create vs edit mode.
5
+ #
6
+ # Flow:
7
+ # 1. User describes what they want (natural language)
8
+ # 2. AI router interprets intent, finds existing files if editing
9
+ # 3. Claude CLI generates/edits the workflow (with optional MCP tools)
10
+ # 4. Validation → Lint → Test → Review loop with auto-fix
11
+ #
12
+ # Uses Claude CLI directly via command type (no SDK required).
13
+ #
14
+ # MCP Server Support:
15
+ # Pass mcp_config input to enable MCP tools for Claude (e.g., Probe Agent for codebase exploration)
16
+ # Example: --input mcp_config='{"mcpServers":{"probe":{"command":"npx","args":["@anthropic/probe-agent"]}}}'
17
+
18
+ id: workflow-builder
19
+ name: Workflow Builder
20
+ description: AI-powered Visor workflow generator and editor with integrated validation
21
+
22
+ workspace:
23
+ enabled: true
24
+ base_path: .visor-workspaces
25
+
26
+ inputs:
27
+ - name: mcp_config
28
+ description: Optional MCP server configuration JSON for Claude CLI
29
+ required: false
30
+ schema:
31
+ type: string
32
+
33
+ routing:
34
+ max_loops: 30
35
+
36
+ outputs:
37
+ - name: workflow_path
38
+ description: Path to the generated/edited workflow file
39
+ value: "{{ outputs['interpret-request'].workflow_path }}"
40
+
41
+ - name: success
42
+ description: Whether the workflow was successfully generated/edited
43
+ value_js: |
44
+ const review = outputs['review-workflow'];
45
+ return review && !(review.issues?.some(i =>
46
+ i.severity === 'critical' || i.severity === 'error'
47
+ ));
48
+
49
+ steps:
50
+ # 1. Get requirements from user
51
+ get-requirements:
52
+ type: human-input
53
+ group: input
54
+ prompt: |
55
+ What would you like to do?
56
+
57
+ Examples:
58
+ - "Create a workflow that validates PR titles follow conventional commits"
59
+ - "Edit defaults/code-review.yaml to add a security check step"
60
+ - "Add tests to my-workflow.yaml"
61
+ - "Fix the routing in defaults/task-refinement.yaml"
62
+
63
+ Describe your request:
64
+
65
+ multiline: true
66
+ allow_empty: false
67
+
68
+ # 2. AI interprets the request and determines mode
69
+ interpret-request:
70
+ type: ai
71
+ group: input
72
+ criticality: internal
73
+ depends_on: [get-requirements]
74
+
75
+ assume:
76
+ - "outputs['get-requirements']?.text != null"
77
+
78
+ guarantee: "output && output.mode && output.workflow_path && output.requirements"
79
+
80
+ timeout: 120000
81
+
82
+ prompt: |
83
+ Analyze this user request and determine if they want to CREATE a new workflow
84
+ or EDIT an existing one.
85
+
86
+ User request:
87
+ {{ outputs['get-requirements'].text }}
88
+
89
+ Instructions:
90
+ 1. If the user mentions a specific file path, they want to EDIT that file
91
+ 2. If they say "create", "new", "build" without a file path, they want to CREATE
92
+ 3. If they reference an existing workflow by name (e.g., "code-review workflow"),
93
+ try to find it - check defaults/*.yaml and *.yaml in current directory
94
+ 4. Extract the core requirements/changes they want
95
+
96
+ IMPORTANT PATH RULES:
97
+ - For CREATE mode: ALWAYS use "./generated-workflow.yaml" as workflow_path (MUST be this exact path)
98
+ - For EDIT mode: Use the actual path to the existing file
99
+ - Tests should ALWAYS be included inline in the same workflow file (not separate)
100
+
101
+ schema:
102
+ type: object
103
+ properties:
104
+ mode:
105
+ type: string
106
+ enum: [create, edit]
107
+ description: Whether to create new or edit existing workflow
108
+ workflow_path:
109
+ type: string
110
+ description: Path to the workflow file (./generated-workflow.yaml for create)
111
+ requirements:
112
+ type: string
113
+ description: Cleaned up requirements string
114
+ existing_workflow_summary:
115
+ type: string
116
+ description: Summary of existing workflow (only for edit mode)
117
+ required: [mode, workflow_path, requirements]
118
+
119
+ # 3. Checkout Visor source for context (provides docs and examples)
120
+ checkout-visor:
121
+ type: git-checkout
122
+ group: setup
123
+ criticality: internal
124
+ depends_on: [interpret-request]
125
+
126
+ assume:
127
+ - "outputs['interpret-request']?.mode != null"
128
+
129
+ repository: probelabs/visor
130
+ ref: new-branch
131
+ fetch_depth: 1
132
+ working_directory: "{% if env.VISOR_WORKSPACE_MAIN_PROJECT %}{{ env.VISOR_WORKSPACE_MAIN_PROJECT }}/.visor-context{% else %}./.visor-context{% endif %}"
133
+
134
+ # 4. Generate/edit workflow using AI with file editing capabilities
135
+ generate-workflow:
136
+ type: ai
137
+ group: generation
138
+ criticality: internal
139
+ depends_on: [checkout-visor]
140
+
141
+ assume:
142
+ - "outputs['checkout-visor']?.success === true"
143
+ - "outputs['interpret-request']?.requirements != null"
144
+
145
+ guarantee: "output != null"
146
+ timeout: 600000
147
+
148
+ ai:
149
+ allowEdit: true
150
+ allowBash: true
151
+ bashConfig:
152
+ allow:
153
+ - "npx:*"
154
+ - "visor:*"
155
+ - "ls:*"
156
+ - "cat:*"
157
+ - "head:*"
158
+ - "tail:*"
159
+
160
+ prompt: |
161
+ {% assign r = outputs['interpret-request'] %}
162
+ {% assign workflowPath = r.workflow_path | default: './generated-workflow.yaml' %}
163
+ {% assign visorPath = outputs['checkout-visor'].path | default: '/tmp/visor-context' %}
164
+
165
+ {% if r.mode == 'edit' %}
166
+ EDIT the existing Visor workflow based on these requirements:
167
+
168
+ {{ r.requirements }}
169
+
170
+ The workflow to edit is at: {{ workflowPath }}
171
+ {% if r.existing_workflow_summary %}
172
+ Current structure: {{ r.existing_workflow_summary }}
173
+ {% endif %}
174
+ {% else %}
175
+ CREATE a new Visor workflow based on these requirements:
176
+
177
+ {{ r.requirements }}
178
+
179
+ Create the workflow at this EXACT path: {{ workflowPath }}
180
+ The working directory is the workspace project folder; create/edit files there (relative paths resolve inside the workspace).
181
+
182
+ CRITICAL: The file MUST be named exactly "{{ workflowPath }}" - no variations!
183
+ - DO NOT use names like "generated-workflow-fixed.yaml" or "hello-world.yaml"
184
+ - DO NOT add suffixes like "-fixed", "-v2", "-new"
185
+ {% endif %}
186
+
187
+ AVAILABLE TOOLS - You can ONLY use these tools:
188
+ - `create` - Create a new file. Arguments: file_path (string), content (string)
189
+ - `edit` - Edit an existing file. Arguments: file_path (string), old_string (string), new_string (string)
190
+ - `search` - Search for files or content
191
+ - `bash` - Run shell commands (only npx, visor, ls, cat, head, tail are allowed)
192
+
193
+ IMPORTANT: Do NOT try to use tools like "implement", "write", or any other tool name.
194
+ To create a file, use the `create` tool with file_path and content arguments.
195
+
196
+ INSTRUCTIONS:
197
+ 1. Read the guide: {{ visorPath }}/docs/workflow-creation-guide.md
198
+ 2. Study examples: {{ visorPath }}/defaults/code-review.yaml, {{ visorPath }}/defaults/task-refinement.yaml
199
+
200
+ {% if r.mode == 'edit' %}
201
+ 3. READ the existing workflow: {{ workflowPath }}
202
+ 4. Make targeted changes using the `edit` tool - preserve existing functionality
203
+ 5. Update inline tests if needed (tests: section in the same file)
204
+ {% else %}
205
+ 3. Use the `create` tool to create the workflow file at EXACTLY: {{ workflowPath }}
206
+ 4. Include tests INLINE in the same file using the tests: section
207
+ {% endif %}
208
+
209
+ IMPORTANT: Tests must be included INLINE in the workflow file using a "tests:" section.
210
+ Do NOT create separate test files. Add tests that cover ALL intended use-cases
211
+ (happy paths, error paths, and edge cases). Example structure:
212
+ ```yaml
213
+ version: "1.0"
214
+ steps:
215
+ my-step:
216
+ type: log
217
+ message: "Hello"
218
+ tests:
219
+ cases:
220
+ - name: test-case
221
+ mocks:
222
+ my-step: { success: true }
223
+ expect:
224
+ calls:
225
+ - step: my-step
226
+ ```
227
+
228
+ Follow style guide: one step/one responsibility, guards, contracts, proper key ordering.
229
+
230
+ VALIDATION COMMANDS - You may run ONLY these commands to verify your work:
231
+ - Validate: npx @probelabs/visor@latest validate --config {{ workflowPath }}
232
+ - Test: npx @probelabs/visor@latest test --config {{ workflowPath }}
233
+
234
+ IMPORTANT: You MUST use "npx @probelabs/visor@latest" - do NOT use just "visor".
235
+ Only "npx @probelabs/visor" commands are allowed in bash.
236
+ DO NOT run this agent/workflow directly from this step.
237
+ Do NOT run validate or lint manually; the workflow will handle validation.
238
+
239
+ After creating the file with the `create` tool, run the validate command first, then the test command if needed.
240
+ If there are errors, fix them using the `edit` tool before finishing.
241
+
242
+ on_success:
243
+ goto: validate-workflow
244
+
245
+ # 5. Validate against Visor conventions
246
+ validate-workflow:
247
+ type: command
248
+ group: validation
249
+ criticality: internal
250
+ depends_on: [generate-workflow]
251
+
252
+ assume:
253
+ - "outputs['generate-workflow'] != null"
254
+
255
+ exec: |
256
+ {% assign r = outputs['interpret-request'] %}
257
+ WORKFLOW_PATH={{ r.workflow_path | default: './generated-workflow.yaml' | shell_escape }}
258
+ echo "DEBUG: Current directory: $(pwd)"
259
+ echo "DEBUG: Looking for: $WORKFLOW_PATH"
260
+ echo "DEBUG: Files in current directory:"
261
+ ls -la . 2>&1 | head -20
262
+ if [ -f "$WORKFLOW_PATH" ]; then
263
+ npx @probelabs/visor@latest validate --config "$WORKFLOW_PATH" 2>&1
264
+ else
265
+ echo "Error: $WORKFLOW_PATH not found" >&2
266
+ exit 1
267
+ fi
268
+
269
+ guarantee: "output != null"
270
+ fail_if: "output.exit_code !== 0"
271
+
272
+ on_fail:
273
+ run: [fix-validation-errors]
274
+
275
+ on_success:
276
+ goto: lint-workflow
277
+
278
+ # 6. Fix validation errors using AI
279
+ fix-validation-errors:
280
+ type: ai
281
+ group: fixes
282
+ criticality: internal
283
+ depends_on: [validate-workflow]
284
+
285
+ assume:
286
+ - "outputs['interpret-request']?.workflow_path != null || true"
287
+
288
+ guarantee: "output != null"
289
+ timeout: 300000
290
+
291
+ ai:
292
+ allowEdit: true
293
+ allowBash: true
294
+ bashConfig:
295
+ allow:
296
+ - "npx:*"
297
+ - "visor:*"
298
+ - "cat:*"
299
+ - "ls:*"
300
+
301
+ prompt: |
302
+ {% assign r = outputs['interpret-request'] %}
303
+ {% assign workflowPath = r.workflow_path | default: './generated-workflow.yaml' %}
304
+
305
+ The workflow validation failed. Fix the issues.
306
+
307
+ CRITICAL: The workflow file MUST be at this EXACT path: {{ workflowPath }}
308
+ DO NOT create any other file. Only edit {{ workflowPath }}.
309
+
310
+ Validation output:
311
+ {{ outputs['validate-workflow'].stdout }}
312
+ {{ outputs['validate-workflow'].stderr }}
313
+
314
+ AVAILABLE TOOLS - You can ONLY use these tools:
315
+ - `create` - Create a new file. Arguments: file_path (string), content (string)
316
+ - `edit` - Edit an existing file. Arguments: file_path (string), old_string (string), new_string (string)
317
+ - `search` - Search for files or content
318
+ - `bash` - Run shell commands (only npx, visor, cat, ls are allowed)
319
+
320
+ Instructions:
321
+ 1. If {{ workflowPath }} doesn't exist, use the `create` tool to create it at EXACTLY that path
322
+ 2. If it exists, read the file to understand current content
323
+ 3. Make targeted fixes using the `edit` tool - don't rewrite everything
324
+ 4. NEVER create a file with a different name like "generated-workflow-fixed.yaml"
325
+ 5. Do NOT run this agent/workflow directly from this step.
326
+ 6. Only the validate and test commands are allowed for verification.
327
+
328
+ If you need to verify after fixing, use ONLY these commands:
329
+ npx @probelabs/visor@latest validate --config {{ workflowPath }}
330
+ npx @probelabs/visor@latest test --config {{ workflowPath }}
331
+
332
+ Keep iterating until validation passes.
333
+
334
+ on_success:
335
+ goto: validate-workflow
336
+ on_fail:
337
+ goto: validate-workflow
338
+
339
+ # 7. Run validation (lint subcommand not available in @latest)
340
+ lint-workflow:
341
+ type: command
342
+ group: validation
343
+ criticality: internal
344
+ depends_on: [validate-workflow]
345
+
346
+ assume:
347
+ - "outputs['validate-workflow'] != null"
348
+
349
+ exec: |
350
+ {% assign r = outputs['interpret-request'] %}
351
+ WORKFLOW_PATH={{ r.workflow_path | default: './generated-workflow.yaml' | shell_escape }}
352
+ if [ -f "$WORKFLOW_PATH" ]; then
353
+ npx @probelabs/visor@latest validate --config "$WORKFLOW_PATH" 2>&1
354
+ else
355
+ echo "Error: $WORKFLOW_PATH not found" >&2
356
+ exit 1
357
+ fi
358
+
359
+ guarantee: "output != null"
360
+ fail_if: "output.exit_code !== 0"
361
+
362
+ on_fail:
363
+ run: [fix-lint-errors]
364
+
365
+ on_success:
366
+ goto: run-tests
367
+
368
+ # 8. Fix lint errors using AI
369
+ fix-lint-errors:
370
+ type: ai
371
+ group: fixes
372
+ criticality: internal
373
+ depends_on: [lint-workflow]
374
+
375
+ assume:
376
+ - "outputs['interpret-request']?.workflow_path != null || true"
377
+
378
+ guarantee: "output != null"
379
+ timeout: 300000
380
+
381
+ ai:
382
+ allowEdit: true
383
+ allowBash: true
384
+ bashConfig:
385
+ allow:
386
+ - "npx:*"
387
+ - "visor:*"
388
+ - "cat:*"
389
+ - "ls:*"
390
+
391
+ prompt: |
392
+ {% assign r = outputs['interpret-request'] %}
393
+ {% assign workflowPath = r.workflow_path | default: './generated-workflow.yaml' %}
394
+
395
+ The workflow has validation issues. Fix them.
396
+
397
+ Workflow path: {{ workflowPath }}
398
+
399
+ Lint output:
400
+ {{ outputs['lint-workflow'].stdout }}
401
+ {{ outputs['lint-workflow'].stderr }}
402
+
403
+ AVAILABLE TOOLS - You can ONLY use these tools:
404
+ - `edit` - Edit an existing file. Arguments: file_path (string), old_string (string), new_string (string)
405
+ - `search` - Search for files or content
406
+ - `bash` - Run shell commands (only npx, visor, cat, ls are allowed)
407
+
408
+ Instructions:
409
+ 1. Read {{ workflowPath }} to understand current content
410
+ 2. Fix validation errors using the `edit` tool - warnings can be left if minor
411
+ 3. Make targeted fixes, don't rewrite everything
412
+ 4. Do NOT run this agent/workflow directly from this step.
413
+ 5. Only the validate and test commands are allowed for verification.
414
+
415
+ If you need to verify after fixing, use ONLY these commands:
416
+ npx @probelabs/visor@latest validate --config {{ workflowPath }}
417
+ npx @probelabs/visor@latest test --config {{ workflowPath }}
418
+
419
+ IMPORTANT: Use "npx @probelabs/visor@latest" - NOT just "visor".
420
+
421
+ Keep iterating until validation passes.
422
+
423
+ on_success:
424
+ goto: lint-workflow
425
+ on_fail:
426
+ goto: lint-workflow
427
+
428
+ # 9. Run YAML tests
429
+ run-tests:
430
+ type: command
431
+ group: testing
432
+ criticality: internal
433
+ depends_on: [lint-workflow]
434
+
435
+ assume:
436
+ - "outputs['lint-workflow'] != null"
437
+
438
+ exec: |
439
+ {% assign r = outputs['interpret-request'] %}
440
+ WORKFLOW_PATH={{ r.workflow_path | default: './generated-workflow.yaml' | shell_escape }}
441
+ if grep -q "^tests:" -- "$WORKFLOW_PATH" 2>/dev/null; then
442
+ npx @probelabs/visor@latest test --config "$WORKFLOW_PATH" 2>&1
443
+ else
444
+ echo "Warning: No inline tests found. Skipping test execution."
445
+ echo '{"skipped": true, "reason": "no tests section in workflow"}'
446
+ fi
447
+
448
+ output_format: text
449
+ guarantee: "output != null"
450
+ fail_if: "output.exit_code !== 0"
451
+
452
+ on_fail:
453
+ run: [fix-test-failures]
454
+
455
+ on_success:
456
+ goto: review-workflow
457
+
458
+ # 10. Fix test failures using AI
459
+ fix-test-failures:
460
+ type: ai
461
+ group: fixes
462
+ criticality: internal
463
+ depends_on: [run-tests]
464
+
465
+ assume:
466
+ - "outputs['interpret-request']?.workflow_path != null || true"
467
+
468
+ guarantee: "output != null"
469
+ timeout: 300000
470
+
471
+ ai:
472
+ allowEdit: true
473
+ allowBash: true
474
+ bashConfig:
475
+ allow:
476
+ - "npx:*"
477
+ - "visor:*"
478
+ - "cat:*"
479
+ - "ls:*"
480
+
481
+ prompt: |
482
+ {% assign r = outputs['interpret-request'] %}
483
+ {% assign workflowPath = r.workflow_path | default: './generated-workflow.yaml' %}
484
+
485
+ The workflow tests failed. Analyze and fix.
486
+
487
+ Workflow: {{ workflowPath }}
488
+ Tests are inline in the same file (look for the "tests:" section)
489
+
490
+ Test output:
491
+ {{ outputs['run-tests'].stdout }}
492
+ {{ outputs['run-tests'].stderr }}
493
+
494
+ AVAILABLE TOOLS - You can ONLY use these tools:
495
+ - `edit` - Edit an existing file. Arguments: file_path (string), old_string (string), new_string (string)
496
+ - `search` - Search for files or content
497
+ - `bash` - Run shell commands (only npx, visor, cat, ls are allowed)
498
+
499
+ Instructions:
500
+ 1. Read the workflow file to understand the steps and inline tests
501
+ 2. Analyze the test failures
502
+ 3. Fix either the workflow steps (if logic is wrong) or the inline tests using the `edit` tool
503
+ 4. Ensure tests cover ALL intended use-cases (happy paths, error paths, edge cases)
504
+ 5. Do NOT run this agent/workflow directly from this step.
505
+ 6. Only the validate and test commands are allowed for verification.
506
+
507
+ After fixing, verify with this EXACT command:
508
+ npx @probelabs/visor@latest test --config {{ workflowPath }}
509
+
510
+ IMPORTANT: Use "npx @probelabs/visor@latest" - NOT just "visor".
511
+
512
+ Keep iterating until tests pass.
513
+
514
+ on_success:
515
+ goto: run-tests
516
+ on_fail:
517
+ goto: run-tests
518
+
519
+ # 11. Code review the generated workflow
520
+ review-workflow:
521
+ type: ai
522
+ group: review
523
+ criticality: policy
524
+ depends_on: [run-tests]
525
+
526
+ guarantee: "output && Array.isArray(output.issues) && typeof output.summary === 'string' && typeof output.approval === 'boolean'"
527
+
528
+ timeout: 180000
529
+
530
+ ai:
531
+ allowBash: true
532
+ bashConfig:
533
+ allow:
534
+ - "cat:*"
535
+
536
+ prompt: |
537
+ {% assign r = outputs['interpret-request'] %}
538
+ {% assign workflowPath = r.workflow_path | default: './generated-workflow.yaml' %}
539
+
540
+ Review the {% if r.mode == 'edit' %}edited{% else %}generated{% endif %} workflow for:
541
+
542
+ 1. **Security Issues** - guards, credentials, input sanitization
543
+ 2. **Missing Edge Cases** - failure handling, loop bounds, timeouts
544
+ 3. **Test Coverage** - happy path, failures, meaningful assertions
545
+ 4. **Style Guide** - key ordering, single-responsibility, guards/contracts
546
+
547
+ Original requirements:
548
+ {{ r.requirements }}
549
+
550
+ Workflow file: {{ workflowPath }}
551
+
552
+ First read the workflow file, then provide your review.
553
+ Be constructive and specific. Flag critical issues.
554
+ Do NOT run this agent/workflow directly from this step.
555
+ Only the validate and test commands are allowed for verification if you must run one.
556
+
557
+ schema:
558
+ type: object
559
+ properties:
560
+ issues:
561
+ type: array
562
+ items:
563
+ type: object
564
+ properties:
565
+ severity:
566
+ type: string
567
+ enum: [critical, error, warning, info]
568
+ category:
569
+ type: string
570
+ enum: [security, edge-case, coverage, style, other]
571
+ message:
572
+ type: string
573
+ suggestion:
574
+ type: string
575
+ required: [severity, category, message]
576
+ summary:
577
+ type: string
578
+ description: Overall review summary
579
+ approval:
580
+ type: boolean
581
+ description: Whether the workflow is ready for use
582
+ required: [issues, summary, approval]
583
+
584
+ fail_if: "output.issues?.some(i => i.severity === 'critical' || i.severity === 'error')"
585
+
586
+ on_fail:
587
+ run: [apply-review-fixes]
588
+
589
+ on_success:
590
+ goto: publish-workflow
591
+
592
+ # 12. Publish workflow to original working directory
593
+ publish-workflow:
594
+ type: command
595
+ group: output
596
+ criticality: info
597
+ depends_on: [review-workflow]
598
+
599
+ assume:
600
+ - "outputs['review-workflow'] != null"
601
+
602
+ exec: |
603
+ {% assign r = outputs['interpret-request'] %}
604
+ WORKFLOW_PATH={{ r.workflow_path | default: './generated-workflow.yaml' | shell_escape }}
605
+ ORIG_DIR="${VISOR_ORIGINAL_WORKDIR:-$PWD}"
606
+ if [ -f "$WORKFLOW_PATH" ]; then
607
+ mkdir -p "$ORIG_DIR"
608
+ cp "$WORKFLOW_PATH" "$ORIG_DIR/$(basename "$WORKFLOW_PATH")"
609
+ echo "Copied to $ORIG_DIR/$(basename "$WORKFLOW_PATH")"
610
+ else
611
+ echo "Error: $WORKFLOW_PATH not found" >&2
612
+ exit 1
613
+ fi
614
+
615
+ guarantee: "output != null"
616
+ fail_if: "output.exit_code !== 0"
617
+
618
+ on_success:
619
+ goto: finalize
620
+
621
+ # 13. Apply review fixes using AI
622
+ apply-review-fixes:
623
+ type: ai
624
+ group: fixes
625
+ criticality: internal
626
+ depends_on: [review-workflow]
627
+
628
+ if: "outputs['review-workflow']?.issues?.length > 0"
629
+
630
+ guarantee: "output != null"
631
+ timeout: 300000
632
+
633
+ ai:
634
+ allowEdit: true
635
+ allowBash: true
636
+ bashConfig:
637
+ allow:
638
+ - "npx:*"
639
+ - "visor:*"
640
+ - "cat:*"
641
+ - "ls:*"
642
+
643
+ prompt: |
644
+ {% assign r = outputs['interpret-request'] %}
645
+ {% assign review = outputs['review-workflow'] %}
646
+ {% assign workflowPath = r.workflow_path | default: './generated-workflow.yaml' %}
647
+
648
+ Apply these review suggestions to the workflow:
649
+
650
+ {% for issue in review.issues %}
651
+ - [{{ issue.severity | upcase }}] {{ issue.category }}: {{ issue.message }}
652
+ {% if issue.suggestion %} Suggestion: {{ issue.suggestion }}{% endif %}
653
+ {% endfor %}
654
+
655
+ Summary: {{ review.summary }}
656
+
657
+ AVAILABLE TOOLS - You can ONLY use these tools:
658
+ - `edit` - Edit an existing file. Arguments: file_path (string), old_string (string), new_string (string)
659
+ - `search` - Search for files or content
660
+ - `bash` - Run shell commands (only npx, visor, cat, ls are allowed)
661
+
662
+ Instructions:
663
+ Fix the issues in {{ workflowPath }} using the `edit` tool (workflow steps and inline tests are in the same file).
664
+
665
+ - Critical/Error issues must be fixed
666
+ - Warning issues should be addressed if straightforward
667
+ - Info issues are optional improvements
668
+ - Ensure tests cover ALL intended use-cases after changes
669
+ - Do NOT run this agent/workflow directly from this step
670
+ - Only the validate and test commands are allowed for verification
671
+
672
+ on_success:
673
+ goto: run-tests
674
+ on_fail:
675
+ goto: run-tests
676
+
677
+ # 14. Final output
678
+ finalize:
679
+ type: log
680
+ group: output
681
+ criticality: info
682
+ depends_on: [publish-workflow]
683
+
684
+ message: |
685
+ {% assign r = outputs['interpret-request'] %}
686
+ {% assign workflowPath = r.workflow_path | default: './generated-workflow.yaml' %}
687
+
688
+ Workflow {% if r.mode == 'edit' %}updated{% else %}created{% endif %} successfully!
689
+
690
+ File: {{ workflowPath }}
691
+ (Tests included inline in the same file)
692
+ Published: {{ outputs['publish-workflow'] | default: 'copy step did not run' }}
693
+
694
+ Review Summary:
695
+ {{ outputs['review-workflow'].summary }}
696
+
697
+ {% assign issues = outputs['review-workflow'].issues %}
698
+ {% if issues.size > 0 %}
699
+ Remaining Notes:
700
+ {% for issue in issues %}
701
+ - [{{ issue.severity }}] {{ issue.message }}
702
+ {% endfor %}
703
+ {% endif %}
704
+
705
+ Next Steps:
706
+ {% if r.mode == 'edit' %}
707
+ 1. Review the changes made to {{ workflowPath }}
708
+ 2. Run tests: npx @probelabs/visor@latest test --config {{ workflowPath }}
709
+ 3. Commit the changes when satisfied
710
+ {% else %}
711
+ 1. Review the generated workflow
712
+ 2. Move it to your project's defaults/ or workflows/ directory
713
+ 3. Configure it in your .visor.yaml
714
+ 4. Run it with: npx @probelabs/visor@latest --config {{ workflowPath }}
715
+ {% endif %}
716
+
717
+ level: info
718
+ include_pr_context: false
719
+ include_dependencies: false
720
+ include_metadata: false