agentweaver 0.1.4 → 0.1.6

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 (53) hide show
  1. package/Dockerfile.codex +55 -0
  2. package/README.md +11 -7
  3. package/dist/artifacts.js +64 -6
  4. package/dist/executors/configs/fetch-gitlab-review-config.js +3 -0
  5. package/dist/executors/fetch-gitlab-review-executor.js +25 -0
  6. package/dist/gitlab.js +153 -0
  7. package/dist/index.js +123 -98
  8. package/dist/interactive-ui.js +433 -28
  9. package/dist/pipeline/context.js +1 -0
  10. package/dist/pipeline/flow-specs/auto.json +176 -2
  11. package/dist/pipeline/flow-specs/gitlab-review.json +347 -0
  12. package/dist/pipeline/flow-specs/implement.json +12 -9
  13. package/dist/pipeline/flow-specs/mr-description.json +28 -0
  14. package/dist/pipeline/flow-specs/plan.json +52 -0
  15. package/dist/pipeline/flow-specs/preflight.json +32 -0
  16. package/dist/pipeline/flow-specs/review-fix.json +79 -10
  17. package/dist/pipeline/flow-specs/review.json +79 -0
  18. package/dist/pipeline/flow-specs/run-linter-loop.json +17 -11
  19. package/dist/pipeline/flow-specs/run-tests-loop.json +17 -11
  20. package/dist/pipeline/flow-specs/task-describe.json +29 -1
  21. package/dist/pipeline/node-registry.js +35 -0
  22. package/dist/pipeline/nodes/fetch-gitlab-review-node.js +34 -0
  23. package/dist/pipeline/nodes/gitlab-review-artifacts-node.js +105 -0
  24. package/dist/pipeline/nodes/local-script-check-node.js +81 -0
  25. package/dist/pipeline/nodes/review-findings-form-node.js +65 -0
  26. package/dist/pipeline/nodes/user-input-node.js +93 -0
  27. package/dist/pipeline/prompt-registry.js +1 -3
  28. package/dist/pipeline/registry.js +2 -0
  29. package/dist/pipeline/value-resolver.js +37 -4
  30. package/dist/prompts.js +26 -17
  31. package/dist/structured-artifacts.js +208 -81
  32. package/dist/user-input.js +171 -0
  33. package/docker-compose.yml +384 -0
  34. package/package.json +7 -3
  35. package/run_linter.sh +89 -0
  36. package/run_tests.sh +113 -0
  37. package/verify_build.sh +104 -0
  38. package/dist/executors/claude-summary-executor.js +0 -31
  39. package/dist/executors/configs/claude-summary-config.js +0 -8
  40. package/dist/pipeline/flow-runner.js +0 -13
  41. package/dist/pipeline/flow-specs/test-fix.json +0 -24
  42. package/dist/pipeline/flow-specs/test-linter-fix.json +0 -24
  43. package/dist/pipeline/flow-specs/test.json +0 -19
  44. package/dist/pipeline/flow-types.js +0 -1
  45. package/dist/pipeline/flows/implement-flow.js +0 -47
  46. package/dist/pipeline/flows/plan-flow.js +0 -42
  47. package/dist/pipeline/flows/review-fix-flow.js +0 -62
  48. package/dist/pipeline/flows/review-flow.js +0 -124
  49. package/dist/pipeline/flows/test-fix-flow.js +0 -12
  50. package/dist/pipeline/flows/test-flow.js +0 -32
  51. package/dist/pipeline/nodes/claude-summary-node.js +0 -38
  52. package/dist/pipeline/nodes/implement-codex-node.js +0 -16
  53. package/dist/pipeline/nodes/task-summary-node.js +0 -42
@@ -17,11 +17,23 @@
17
17
  "taskKey": { "ref": "params.taskKey" }
18
18
  }
19
19
  },
20
+ "design_json_file": {
21
+ "artifact": {
22
+ "kind": "design-json-file",
23
+ "taskKey": { "ref": "params.taskKey" }
24
+ }
25
+ },
20
26
  "plan_file": {
21
27
  "artifact": {
22
28
  "kind": "plan-file",
23
29
  "taskKey": { "ref": "params.taskKey" }
24
30
  }
31
+ },
32
+ "plan_json_file": {
33
+ "artifact": {
34
+ "kind": "plan-json-file",
35
+ "taskKey": { "ref": "params.taskKey" }
36
+ }
25
37
  }
26
38
  },
27
39
  "extraPrompt": { "ref": "params.extraPrompt" },
@@ -31,15 +43,6 @@
31
43
  "labelText": { "const": "Running Codex implementation mode locally" },
32
44
  "model": { "const": "gpt-5.4" }
33
45
  }
34
- },
35
- {
36
- "id": "verify_build_after_implement",
37
- "when": { "ref": "params.runFollowupVerify" },
38
- "node": "verify-build",
39
- "params": {
40
- "dockerComposeFile": { "ref": "params.dockerComposeFile" },
41
- "labelText": { "const": "Running build verification in isolated Docker" }
42
- }
43
46
  }
44
47
  ]
45
48
  }
@@ -22,6 +22,12 @@
22
22
  "kind": "mr-description-file",
23
23
  "taskKey": { "ref": "params.taskKey" }
24
24
  }
25
+ },
26
+ "mr_description_json_file": {
27
+ "artifact": {
28
+ "kind": "mr-description-json-file",
29
+ "taskKey": { "ref": "params.taskKey" }
30
+ }
25
31
  }
26
32
  },
27
33
  "extraPrompt": { "ref": "params.extraPrompt" },
@@ -37,6 +43,12 @@
37
43
  "kind": "mr-description-file",
38
44
  "taskKey": { "ref": "params.taskKey" }
39
45
  }
46
+ },
47
+ {
48
+ "artifact": {
49
+ "kind": "mr-description-json-file",
50
+ "taskKey": { "ref": "params.taskKey" }
51
+ }
40
52
  }
41
53
  ]
42
54
  }
@@ -52,6 +64,22 @@
52
64
  }
53
65
  },
54
66
  "message": "MR description mode did not produce the MR description artifact."
67
+ },
68
+ {
69
+ "kind": "require-structured-artifacts",
70
+ "when": { "not": { "ref": "context.dryRun" } },
71
+ "items": [
72
+ {
73
+ "path": {
74
+ "artifact": {
75
+ "kind": "mr-description-json-file",
76
+ "taskKey": { "ref": "params.taskKey" }
77
+ }
78
+ },
79
+ "schemaId": "mr-description/v1"
80
+ }
81
+ ],
82
+ "message": "MR description mode produced invalid structured artifacts."
55
83
  }
56
84
  ]
57
85
  }
@@ -48,17 +48,35 @@
48
48
  "taskKey": { "ref": "params.taskKey" }
49
49
  }
50
50
  },
51
+ "design_json_file": {
52
+ "artifact": {
53
+ "kind": "design-json-file",
54
+ "taskKey": { "ref": "params.taskKey" }
55
+ }
56
+ },
51
57
  "plan_file": {
52
58
  "artifact": {
53
59
  "kind": "plan-file",
54
60
  "taskKey": { "ref": "params.taskKey" }
55
61
  }
56
62
  },
63
+ "plan_json_file": {
64
+ "artifact": {
65
+ "kind": "plan-json-file",
66
+ "taskKey": { "ref": "params.taskKey" }
67
+ }
68
+ },
57
69
  "qa_file": {
58
70
  "artifact": {
59
71
  "kind": "qa-file",
60
72
  "taskKey": { "ref": "params.taskKey" }
61
73
  }
74
+ },
75
+ "qa_json_file": {
76
+ "artifact": {
77
+ "kind": "qa-json-file",
78
+ "taskKey": { "ref": "params.taskKey" }
79
+ }
62
80
  }
63
81
  },
64
82
  "extraPrompt": { "ref": "params.extraPrompt" },
@@ -79,6 +97,40 @@
79
97
  }
80
98
  },
81
99
  "message": "Plan mode did not produce the required artifacts."
100
+ },
101
+ {
102
+ "kind": "require-structured-artifacts",
103
+ "when": { "not": { "ref": "context.dryRun" } },
104
+ "items": [
105
+ {
106
+ "path": {
107
+ "artifact": {
108
+ "kind": "design-json-file",
109
+ "taskKey": { "ref": "params.taskKey" }
110
+ }
111
+ },
112
+ "schemaId": "implementation-design/v1"
113
+ },
114
+ {
115
+ "path": {
116
+ "artifact": {
117
+ "kind": "plan-json-file",
118
+ "taskKey": { "ref": "params.taskKey" }
119
+ }
120
+ },
121
+ "schemaId": "implementation-plan/v1"
122
+ },
123
+ {
124
+ "path": {
125
+ "artifact": {
126
+ "kind": "qa-json-file",
127
+ "taskKey": { "ref": "params.taskKey" }
128
+ }
129
+ },
130
+ "schemaId": "qa-plan/v1"
131
+ }
132
+ ],
133
+ "message": "Plan mode produced invalid structured artifacts."
82
134
  }
83
135
  ]
84
136
  }
@@ -124,6 +124,12 @@
124
124
  "kind": "task-summary-file",
125
125
  "taskKey": { "ref": "params.taskKey" }
126
126
  }
127
+ },
128
+ "task_summary_json_file": {
129
+ "artifact": {
130
+ "kind": "task-summary-json-file",
131
+ "taskKey": { "ref": "params.taskKey" }
132
+ }
127
133
  }
128
134
  },
129
135
  "format": "plain"
@@ -136,6 +142,16 @@
136
142
  "taskKey": { "ref": "params.taskKey" }
137
143
  }
138
144
  },
145
+ "requiredArtifacts": {
146
+ "list": [
147
+ {
148
+ "artifact": {
149
+ "kind": "task-summary-json-file",
150
+ "taskKey": { "ref": "params.taskKey" }
151
+ }
152
+ }
153
+ ]
154
+ },
139
155
  "model": { "const": "haiku" }
140
156
  },
141
157
  "expect": [
@@ -153,6 +169,22 @@
153
169
  ]
154
170
  },
155
171
  "message": "Claude summary did not produce the task summary artifact."
172
+ },
173
+ {
174
+ "kind": "require-structured-artifacts",
175
+ "when": { "not": { "ref": "context.dryRun" } },
176
+ "items": [
177
+ {
178
+ "path": {
179
+ "artifact": {
180
+ "kind": "task-summary-json-file",
181
+ "taskKey": { "ref": "params.taskKey" }
182
+ }
183
+ },
184
+ "schemaId": "task-summary/v1"
185
+ }
186
+ ],
187
+ "message": "Claude summary produced invalid structured artifacts."
156
188
  }
157
189
  ],
158
190
  "after": [
@@ -8,6 +8,48 @@
8
8
  {
9
9
  "id": "review-fix",
10
10
  "steps": [
11
+ {
12
+ "id": "build_review_fix_selection_form",
13
+ "node": "review-findings-form",
14
+ "params": {
15
+ "reviewReplyJsonFile": {
16
+ "artifact": {
17
+ "kind": "review-reply-json-file",
18
+ "taskKey": { "ref": "params.taskKey" },
19
+ "iteration": { "ref": "params.latestIteration" }
20
+ }
21
+ },
22
+ "formId": { "const": "review-fix-selection" },
23
+ "title": { "const": "Review-Fix Selection" },
24
+ "description": {
25
+ "const": "Отметьте findings, которые нужно исправить в этой итерации review-fix. Можно включить режим исправления всех findings."
26
+ }
27
+ }
28
+ },
29
+ {
30
+ "id": "collect_review_fix_selection",
31
+ "node": "user-input",
32
+ "params": {
33
+ "formId": { "ref": "steps.review-fix.build_review_fix_selection_form.value.formId" },
34
+ "title": { "ref": "steps.review-fix.build_review_fix_selection_form.value.title" },
35
+ "description": { "ref": "steps.review-fix.build_review_fix_selection_form.value.description" },
36
+ "submitLabel": { "const": "Run review-fix" },
37
+ "fields": { "ref": "steps.review-fix.build_review_fix_selection_form.value.fields" },
38
+ "outputFile": { "ref": "params.reviewFixSelectionJsonFile" }
39
+ },
40
+ "expect": [
41
+ {
42
+ "kind": "require-structured-artifacts",
43
+ "items": [
44
+ {
45
+ "path": { "ref": "params.reviewFixSelectionJsonFile" },
46
+ "schemaId": "user-input/v1"
47
+ }
48
+ ],
49
+ "message": "Review-fix selection input is missing or invalid."
50
+ }
51
+ ]
52
+ },
11
53
  {
12
54
  "id": "run_codex_review_fix",
13
55
  "node": "codex-local-prompt",
@@ -21,6 +63,13 @@
21
63
  "iteration": { "ref": "params.latestIteration" }
22
64
  }
23
65
  },
66
+ "review_reply_json_file": {
67
+ "artifact": {
68
+ "kind": "review-reply-json-file",
69
+ "taskKey": { "ref": "params.taskKey" },
70
+ "iteration": { "ref": "params.latestIteration" }
71
+ }
72
+ },
24
73
  "items": { "ref": "params.reviewFixPoints" },
25
74
  "review_fix_file": {
26
75
  "artifact": {
@@ -28,9 +77,21 @@
28
77
  "taskKey": { "ref": "params.taskKey" },
29
78
  "iteration": { "ref": "params.latestIteration" }
30
79
  }
80
+ },
81
+ "review_fix_json_file": {
82
+ "artifact": {
83
+ "kind": "review-fix-json-file",
84
+ "taskKey": { "ref": "params.taskKey" },
85
+ "iteration": { "ref": "params.latestIteration" }
86
+ }
87
+ }
88
+ },
89
+ "extraPrompt": {
90
+ "appendPrompt": {
91
+ "base": { "ref": "params.extraPrompt" },
92
+ "suffix": { "ref": "steps.review-fix.collect_review_fix_selection.value.promptSuffix" }
31
93
  }
32
94
  },
33
- "extraPrompt": { "ref": "params.extraPrompt" },
34
95
  "format": "task-prompt"
35
96
  },
36
97
  "params": {
@@ -58,17 +119,25 @@
58
119
  ]
59
120
  },
60
121
  "message": "Review-fix mode did not produce the required review-fix artifact."
122
+ },
123
+ {
124
+ "kind": "require-structured-artifacts",
125
+ "when": { "not": { "ref": "context.dryRun" } },
126
+ "items": [
127
+ {
128
+ "path": {
129
+ "artifact": {
130
+ "kind": "review-fix-json-file",
131
+ "taskKey": { "ref": "params.taskKey" },
132
+ "iteration": { "ref": "params.latestIteration" }
133
+ }
134
+ },
135
+ "schemaId": "review-fix-report/v1"
136
+ }
137
+ ],
138
+ "message": "Review-fix mode produced invalid structured artifacts."
61
139
  }
62
140
  ]
63
- },
64
- {
65
- "id": "verify_build_after_review_fix",
66
- "when": { "ref": "params.runFollowupVerify" },
67
- "node": "verify-build",
68
- "params": {
69
- "dockerComposeFile": { "ref": "params.dockerComposeFile" },
70
- "labelText": { "const": "Running build verification in isolated Docker" }
71
- }
72
141
  }
73
142
  ]
74
143
  }
@@ -23,18 +23,37 @@
23
23
  "taskKey": { "ref": "params.taskKey" }
24
24
  }
25
25
  },
26
+ "design_json_file": {
27
+ "artifact": {
28
+ "kind": "design-json-file",
29
+ "taskKey": { "ref": "params.taskKey" }
30
+ }
31
+ },
26
32
  "plan_file": {
27
33
  "artifact": {
28
34
  "kind": "plan-file",
29
35
  "taskKey": { "ref": "params.taskKey" }
30
36
  }
31
37
  },
38
+ "plan_json_file": {
39
+ "artifact": {
40
+ "kind": "plan-json-file",
41
+ "taskKey": { "ref": "params.taskKey" }
42
+ }
43
+ },
32
44
  "review_file": {
33
45
  "artifact": {
34
46
  "kind": "review-file",
35
47
  "taskKey": { "ref": "params.taskKey" },
36
48
  "iteration": { "ref": "params.iteration" }
37
49
  }
50
+ },
51
+ "review_json_file": {
52
+ "artifact": {
53
+ "kind": "review-json-file",
54
+ "taskKey": { "ref": "params.taskKey" },
55
+ "iteration": { "ref": "params.iteration" }
56
+ }
38
57
  }
39
58
  },
40
59
  "extraPrompt": { "ref": "params.extraPrompt" },
@@ -65,6 +84,23 @@
65
84
  ]
66
85
  },
67
86
  "message": "Claude review did not produce the required review artifact."
87
+ },
88
+ {
89
+ "kind": "require-structured-artifacts",
90
+ "when": { "not": { "ref": "context.dryRun" } },
91
+ "items": [
92
+ {
93
+ "path": {
94
+ "artifact": {
95
+ "kind": "review-json-file",
96
+ "taskKey": { "ref": "params.taskKey" },
97
+ "iteration": { "ref": "params.iteration" }
98
+ }
99
+ },
100
+ "schemaId": "review-findings/v1"
101
+ }
102
+ ],
103
+ "message": "Claude review produced invalid structured artifacts."
68
104
  }
69
105
  ]
70
106
  },
@@ -118,6 +154,13 @@
118
154
  "iteration": { "ref": "params.iteration" }
119
155
  }
120
156
  },
157
+ "review_json_file": {
158
+ "artifact": {
159
+ "kind": "review-json-file",
160
+ "taskKey": { "ref": "params.taskKey" },
161
+ "iteration": { "ref": "params.iteration" }
162
+ }
163
+ },
121
164
  "jira_task_file": {
122
165
  "artifact": {
123
166
  "kind": "jira-task-file",
@@ -130,18 +173,37 @@
130
173
  "taskKey": { "ref": "params.taskKey" }
131
174
  }
132
175
  },
176
+ "design_json_file": {
177
+ "artifact": {
178
+ "kind": "design-json-file",
179
+ "taskKey": { "ref": "params.taskKey" }
180
+ }
181
+ },
133
182
  "plan_file": {
134
183
  "artifact": {
135
184
  "kind": "plan-file",
136
185
  "taskKey": { "ref": "params.taskKey" }
137
186
  }
138
187
  },
188
+ "plan_json_file": {
189
+ "artifact": {
190
+ "kind": "plan-json-file",
191
+ "taskKey": { "ref": "params.taskKey" }
192
+ }
193
+ },
139
194
  "review_reply_file": {
140
195
  "artifact": {
141
196
  "kind": "review-reply-file",
142
197
  "taskKey": { "ref": "params.taskKey" },
143
198
  "iteration": { "ref": "params.iteration" }
144
199
  }
200
+ },
201
+ "review_reply_json_file": {
202
+ "artifact": {
203
+ "kind": "review-reply-json-file",
204
+ "taskKey": { "ref": "params.taskKey" },
205
+ "iteration": { "ref": "params.iteration" }
206
+ }
145
207
  }
146
208
  },
147
209
  "extraPrompt": { "ref": "params.extraPrompt" },
@@ -172,6 +234,23 @@
172
234
  ]
173
235
  },
174
236
  "message": "Codex review reply did not produce the required review-reply artifact."
237
+ },
238
+ {
239
+ "kind": "require-structured-artifacts",
240
+ "when": { "not": { "ref": "context.dryRun" } },
241
+ "items": [
242
+ {
243
+ "path": {
244
+ "artifact": {
245
+ "kind": "review-reply-json-file",
246
+ "taskKey": { "ref": "params.taskKey" },
247
+ "iteration": { "ref": "params.iteration" }
248
+ }
249
+ },
250
+ "schemaId": "review-reply/v1"
251
+ }
252
+ ],
253
+ "message": "Codex review reply produced invalid structured artifacts."
175
254
  }
176
255
  ]
177
256
  },
@@ -7,13 +7,16 @@
7
7
  "steps": [
8
8
  {
9
9
  "id": "run_linter",
10
- "node": "verify-build",
10
+ "node": "local-script-check",
11
11
  "params": {
12
- "dockerComposeFile": { "ref": "params.dockerComposeFile" },
13
- "labelText": {
14
- "const": "Running run_linter.sh in isolated Docker (attempt 1)"
12
+ "argv": {
13
+ "list": [
14
+ { "ref": "params.runLinterScript" }
15
+ ]
15
16
  },
16
- "service": { "const": "run-linter" }
17
+ "labelText": {
18
+ "const": "Running run_linter.sh locally (attempt 1)"
19
+ }
17
20
  },
18
21
  "stopFlowIf": {
19
22
  "equals": [
@@ -74,13 +77,16 @@
74
77
  "steps": [
75
78
  {
76
79
  "id": "run_linter",
77
- "node": "verify-build",
80
+ "node": "local-script-check",
78
81
  "params": {
79
- "dockerComposeFile": { "ref": "params.dockerComposeFile" },
80
- "labelText": {
81
- "template": "Running run_linter.sh in isolated Docker (attempt ${attempt})"
82
+ "argv": {
83
+ "list": [
84
+ { "ref": "params.runLinterScript" }
85
+ ]
82
86
  },
83
- "service": { "const": "run-linter" }
87
+ "labelText": {
88
+ "template": "Running run_linter.sh locally (attempt ${attempt})"
89
+ }
84
90
  },
85
91
  "stopFlowIf": {
86
92
  "equals": [
@@ -132,7 +138,7 @@
132
138
  "id": "assert_run_linter_success",
133
139
  "node": "file-check",
134
140
  "params": {
135
- "path": { "ref": "params.dockerComposeFile" }
141
+ "path": { "ref": "params.runLinterScript" }
136
142
  },
137
143
  "expect": [
138
144
  {
@@ -7,13 +7,16 @@
7
7
  "steps": [
8
8
  {
9
9
  "id": "run_tests",
10
- "node": "verify-build",
10
+ "node": "local-script-check",
11
11
  "params": {
12
- "dockerComposeFile": { "ref": "params.dockerComposeFile" },
13
- "labelText": {
14
- "const": "Running run_tests.sh in isolated Docker (attempt 1)"
12
+ "argv": {
13
+ "list": [
14
+ { "ref": "params.runTestsScript" }
15
+ ]
15
16
  },
16
- "service": { "const": "run-tests" }
17
+ "labelText": {
18
+ "const": "Running run_tests.sh locally (attempt 1)"
19
+ }
17
20
  },
18
21
  "stopFlowIf": {
19
22
  "equals": [
@@ -74,13 +77,16 @@
74
77
  "steps": [
75
78
  {
76
79
  "id": "run_tests",
77
- "node": "verify-build",
80
+ "node": "local-script-check",
78
81
  "params": {
79
- "dockerComposeFile": { "ref": "params.dockerComposeFile" },
80
- "labelText": {
81
- "template": "Running run_tests.sh in isolated Docker (attempt ${attempt})"
82
+ "argv": {
83
+ "list": [
84
+ { "ref": "params.runTestsScript" }
85
+ ]
82
86
  },
83
- "service": { "const": "run-tests" }
87
+ "labelText": {
88
+ "template": "Running run_tests.sh locally (attempt ${attempt})"
89
+ }
84
90
  },
85
91
  "stopFlowIf": {
86
92
  "equals": [
@@ -132,7 +138,7 @@
132
138
  "id": "assert_run_tests_success",
133
139
  "node": "file-check",
134
140
  "params": {
135
- "path": { "ref": "params.dockerComposeFile" }
141
+ "path": { "ref": "params.runTestsScript" }
136
142
  },
137
143
  "expect": [
138
144
  {
@@ -9,7 +9,7 @@
9
9
  "id": "run_codex_task_describe",
10
10
  "node": "codex-local-prompt",
11
11
  "prompt": {
12
- "inlineTemplate": "Посмотри задачу в {jira_task_file}. Проанализируй код и оформи описание для Jira, без лишних подробностей. Запиши в {jira_description_file}.",
12
+ "inlineTemplate": "Посмотри задачу в {jira_task_file}. Проанализируй код и оформи краткое описание для Jira, без лишних подробностей. Сначала запиши source-of-truth JSON в {jira_description_json_file} в виде объекта { summary: string }, затем markdown-версию в {jira_description_file}.",
13
13
  "vars": {
14
14
  "jira_task_file": {
15
15
  "artifact": {
@@ -22,6 +22,12 @@
22
22
  "kind": "jira-description-file",
23
23
  "taskKey": { "ref": "params.taskKey" }
24
24
  }
25
+ },
26
+ "jira_description_json_file": {
27
+ "artifact": {
28
+ "kind": "jira-description-json-file",
29
+ "taskKey": { "ref": "params.taskKey" }
30
+ }
25
31
  }
26
32
  },
27
33
  "extraPrompt": { "ref": "params.extraPrompt" },
@@ -37,6 +43,12 @@
37
43
  "kind": "jira-description-file",
38
44
  "taskKey": { "ref": "params.taskKey" }
39
45
  }
46
+ },
47
+ {
48
+ "artifact": {
49
+ "kind": "jira-description-json-file",
50
+ "taskKey": { "ref": "params.taskKey" }
51
+ }
40
52
  }
41
53
  ]
42
54
  }
@@ -52,6 +64,22 @@
52
64
  }
53
65
  },
54
66
  "message": "Task describe mode did not produce the Jira description artifact."
67
+ },
68
+ {
69
+ "kind": "require-structured-artifacts",
70
+ "when": { "not": { "ref": "context.dryRun" } },
71
+ "items": [
72
+ {
73
+ "path": {
74
+ "artifact": {
75
+ "kind": "jira-description-json-file",
76
+ "taskKey": { "ref": "params.taskKey" }
77
+ }
78
+ },
79
+ "schemaId": "jira-description/v1"
80
+ }
81
+ ],
82
+ "message": "Task describe mode produced invalid structured artifacts."
55
83
  }
56
84
  ]
57
85
  }