agentweaver 0.1.8 → 0.1.10

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 (55) hide show
  1. package/README.md +71 -25
  2. package/dist/artifacts.js +25 -1
  3. package/dist/errors.js +7 -0
  4. package/dist/executors/configs/fetch-gitlab-diff-config.js +3 -0
  5. package/dist/executors/configs/opencode-config.js +6 -0
  6. package/dist/executors/fetch-gitlab-diff-executor.js +26 -0
  7. package/dist/executors/jira-fetch-executor.js +8 -2
  8. package/dist/executors/opencode-executor.js +35 -0
  9. package/dist/gitlab.js +199 -5
  10. package/dist/index.js +215 -144
  11. package/dist/interactive-ui.js +363 -37
  12. package/dist/jira.js +116 -14
  13. package/dist/pipeline/auto-flow.js +1 -1
  14. package/dist/pipeline/declarative-flows.js +44 -6
  15. package/dist/pipeline/flow-catalog.js +73 -0
  16. package/dist/pipeline/flow-specs/auto.json +183 -1
  17. package/dist/pipeline/flow-specs/gitlab-diff-review.json +226 -0
  18. package/dist/pipeline/flow-specs/gitlab-review.json +1 -31
  19. package/dist/pipeline/flow-specs/opencode/auto-opencode.json +1365 -0
  20. package/dist/pipeline/flow-specs/opencode/bugz/bug-analyze-opencode.json +382 -0
  21. package/dist/pipeline/flow-specs/opencode/bugz/bug-fix-opencode.json +56 -0
  22. package/dist/pipeline/flow-specs/opencode/gitlab/gitlab-diff-review-opencode.json +308 -0
  23. package/dist/pipeline/flow-specs/opencode/gitlab/gitlab-review-opencode.json +437 -0
  24. package/dist/pipeline/flow-specs/opencode/gitlab/mr-description-opencode.json +117 -0
  25. package/dist/pipeline/flow-specs/opencode/go/run-go-linter-loop-opencode.json +321 -0
  26. package/dist/pipeline/flow-specs/opencode/go/run-go-tests-loop-opencode.json +321 -0
  27. package/dist/pipeline/flow-specs/opencode/implement-opencode.json +64 -0
  28. package/dist/pipeline/flow-specs/opencode/plan-opencode.json +603 -0
  29. package/dist/pipeline/flow-specs/opencode/review/review-fix-opencode.json +209 -0
  30. package/dist/pipeline/flow-specs/opencode/review/review-opencode.json +452 -0
  31. package/dist/pipeline/flow-specs/opencode/task-describe-opencode.json +148 -0
  32. package/dist/pipeline/flow-specs/plan.json +183 -1
  33. package/dist/pipeline/node-registry.js +80 -8
  34. package/dist/pipeline/nodes/fetch-gitlab-diff-node.js +34 -0
  35. package/dist/pipeline/nodes/flow-run-node.js +2 -2
  36. package/dist/pipeline/nodes/jira-fetch-node.js +26 -2
  37. package/dist/pipeline/nodes/opencode-prompt-node.js +32 -0
  38. package/dist/pipeline/nodes/planning-questions-form-node.js +69 -0
  39. package/dist/pipeline/nodes/user-input-node.js +9 -1
  40. package/dist/pipeline/prompt-registry.js +3 -1
  41. package/dist/pipeline/registry.js +10 -0
  42. package/dist/pipeline/spec-loader.js +48 -3
  43. package/dist/pipeline/spec-types.js +43 -1
  44. package/dist/pipeline/spec-validator.js +53 -7
  45. package/dist/pipeline/value-resolver.js +15 -1
  46. package/dist/prompts.js +47 -12
  47. package/dist/runtime/process-runner.js +45 -1
  48. package/dist/scope.js +24 -32
  49. package/dist/structured-artifact-schemas.json +154 -1
  50. package/dist/structured-artifacts.js +2 -0
  51. package/dist/user-input.js +7 -0
  52. package/package.json +1 -1
  53. package/dist/pipeline/flow-specs/preflight.json +0 -206
  54. package/dist/pipeline/flow-specs/run-linter-loop.json +0 -155
  55. package/dist/pipeline/flow-specs/run-tests-loop.json +0 -155
package/dist/scope.js CHANGED
@@ -35,10 +35,7 @@ export function sanitizeScopeName(value) {
35
35
  }
36
36
  export function detectGitBranchName() {
37
37
  const branchName = gitOutput(["rev-parse", "--abbrev-ref", "HEAD"]);
38
- if (!branchName) {
39
- return null;
40
- }
41
- if (branchName === "HEAD") {
38
+ if (!branchName || branchName === "HEAD") {
42
39
  return null;
43
40
  }
44
41
  return branchName;
@@ -66,7 +63,7 @@ export function buildProjectScopeKey(explicitScope) {
66
63
  projectRoot,
67
64
  };
68
65
  }
69
- function parseTaskScope(jiraRef) {
66
+ export function parseJiraContext(jiraRef) {
70
67
  return {
71
68
  jiraRef,
72
69
  jiraIssueKey: extractIssueKey(jiraRef),
@@ -74,30 +71,34 @@ function parseTaskScope(jiraRef) {
74
71
  jiraApiUrl: buildJiraApiUrl(jiraRef),
75
72
  };
76
73
  }
77
- export function resolveTaskScope(jiraRef, explicitScope) {
78
- const parsedTaskScope = parseTaskScope(jiraRef);
79
- const scopeKey = explicitScope?.trim() ? sanitizeScopeName(explicitScope) : parsedTaskScope.jiraIssueKey;
80
- ensureScopeWorkspaceDir(scopeKey);
81
- return {
82
- scopeType: "task",
83
- scopeKey,
84
- jiraRef: parsedTaskScope.jiraRef,
85
- jiraIssueKey: parsedTaskScope.jiraIssueKey,
86
- jiraBrowseUrl: parsedTaskScope.jiraBrowseUrl,
87
- jiraApiUrl: parsedTaskScope.jiraApiUrl,
88
- jiraTaskFile: jiraTaskFile(scopeKey),
89
- };
90
- }
91
- export function resolveProjectScope(explicitScope) {
74
+ export function resolveProjectScope(explicitScope, jiraRef) {
92
75
  const { scopeKey, gitBranchName, worktreeHash, projectRoot } = buildProjectScopeKey(explicitScope);
93
76
  ensureScopeWorkspaceDir(scopeKey);
94
- return {
77
+ const baseScope = {
95
78
  scopeType: "project",
96
79
  scopeKey,
97
80
  gitBranchName,
98
81
  worktreeHash,
99
82
  projectRoot,
100
83
  };
84
+ if (!jiraRef?.trim()) {
85
+ return baseScope;
86
+ }
87
+ const jiraContext = parseJiraContext(jiraRef);
88
+ return {
89
+ ...baseScope,
90
+ ...jiraContext,
91
+ jiraTaskFile: jiraTaskFile(scopeKey),
92
+ };
93
+ }
94
+ export function attachJiraContext(scope, jiraRef) {
95
+ const jiraContext = parseJiraContext(jiraRef);
96
+ ensureScopeWorkspaceDir(scope.scopeKey);
97
+ return {
98
+ ...scope,
99
+ ...jiraContext,
100
+ jiraTaskFile: jiraTaskFile(scope.scopeKey),
101
+ };
101
102
  }
102
103
  export function buildJiraTaskInputForm() {
103
104
  return {
@@ -116,20 +117,11 @@ export function buildJiraTaskInputForm() {
116
117
  ],
117
118
  };
118
119
  }
119
- export async function requestTaskScope(requestUserInput) {
120
+ export async function requestJiraContext(requestUserInput) {
120
121
  const result = await requestUserInput(buildJiraTaskInputForm());
121
122
  const jiraRef = String(result.values.jira_ref ?? "").trim();
122
123
  if (!jiraRef) {
123
124
  throw new TaskRunnerError("Jira issue key or browse URL is required.");
124
125
  }
125
- const parsedTaskScope = parseTaskScope(jiraRef);
126
- return {
127
- scopeType: "task",
128
- scopeKey: parsedTaskScope.jiraIssueKey,
129
- jiraRef: parsedTaskScope.jiraRef,
130
- jiraIssueKey: parsedTaskScope.jiraIssueKey,
131
- jiraBrowseUrl: parsedTaskScope.jiraBrowseUrl,
132
- jiraApiUrl: parsedTaskScope.jiraApiUrl,
133
- jiraTaskFile: jiraTaskFile(parsedTaskScope.jiraIssueKey),
134
- };
126
+ return parseJiraContext(jiraRef);
135
127
  }
@@ -219,6 +219,74 @@
219
219
  },
220
220
  "required": ["summary", "merge_request_url", "project_path", "merge_request_iid", "fetched_at", "comments"]
221
221
  },
222
+ "gitlab-mr-diff/v1": {
223
+ "type": "object",
224
+ "properties": {
225
+ "summary": { "type": "string", "nonEmpty": true },
226
+ "merge_request_url": { "type": "string", "nonEmpty": true },
227
+ "project_path": { "type": "string", "nonEmpty": true },
228
+ "merge_request_iid": { "type": "number" },
229
+ "fetched_at": { "type": "string", "nonEmpty": true },
230
+ "merge_request": {
231
+ "type": "object",
232
+ "properties": {
233
+ "title": { "type": "string", "nonEmpty": true },
234
+ "description": { "type": "string" },
235
+ "state": { "type": "string", "nonEmpty": true },
236
+ "draft": { "type": "boolean" },
237
+ "source_branch": { "type": "string", "nonEmpty": true },
238
+ "target_branch": { "type": "string", "nonEmpty": true },
239
+ "sha": { "type": "string", "nonEmpty": true },
240
+ "author": { "type": "string", "nonEmpty": true },
241
+ "created_at": { "type": "string", "nonEmpty": true },
242
+ "updated_at": { "type": "string", "nonEmpty": true }
243
+ },
244
+ "required": [
245
+ "title",
246
+ "description",
247
+ "state",
248
+ "draft",
249
+ "source_branch",
250
+ "target_branch",
251
+ "sha",
252
+ "author",
253
+ "created_at",
254
+ "updated_at"
255
+ ]
256
+ },
257
+ "files": {
258
+ "type": "array",
259
+ "items": {
260
+ "type": "object",
261
+ "properties": {
262
+ "old_path": { "type": "string", "nonEmpty": true },
263
+ "new_path": { "type": "string", "nonEmpty": true },
264
+ "change_type": { "type": "string", "nonEmpty": true },
265
+ "new_file": { "type": "boolean" },
266
+ "renamed_file": { "type": "boolean" },
267
+ "deleted_file": { "type": "boolean" },
268
+ "generated_file": { "type": "boolean" },
269
+ "too_large": { "type": "boolean" },
270
+ "collapsed": { "type": "boolean" },
271
+ "diff": { "type": "string", "nonEmpty": true }
272
+ },
273
+ "required": [
274
+ "old_path",
275
+ "new_path",
276
+ "change_type",
277
+ "new_file",
278
+ "renamed_file",
279
+ "deleted_file",
280
+ "generated_file",
281
+ "too_large",
282
+ "collapsed",
283
+ "diff"
284
+ ]
285
+ }
286
+ }
287
+ },
288
+ "required": ["summary", "merge_request_url", "project_path", "merge_request_iid", "fetched_at", "merge_request", "files"]
289
+ },
222
290
  "implementation-design/v1": {
223
291
  "type": "object",
224
292
  "properties": {
@@ -237,6 +305,33 @@
237
305
  "items": { "type": "string", "nonEmpty": true },
238
306
  "minItems": 1
239
307
  },
308
+ "current_state": {
309
+ "type": "array",
310
+ "items": { "type": "string", "nonEmpty": true }
311
+ },
312
+ "target_state": {
313
+ "type": "array",
314
+ "items": { "type": "string", "nonEmpty": true }
315
+ },
316
+ "affected_code": {
317
+ "type": "array",
318
+ "items": {
319
+ "type": "object",
320
+ "properties": {
321
+ "area": { "type": "string", "nonEmpty": true },
322
+ "files": {
323
+ "type": "array",
324
+ "items": { "type": "string", "nonEmpty": true }
325
+ },
326
+ "details": { "type": "string", "nonEmpty": true }
327
+ },
328
+ "required": ["area", "files", "details"]
329
+ }
330
+ },
331
+ "business_rules": {
332
+ "type": "array",
333
+ "items": { "type": "string", "nonEmpty": true }
334
+ },
240
335
  "decisions": {
241
336
  "type": "array",
242
337
  "items": {
@@ -250,10 +345,26 @@
250
345
  },
251
346
  "minItems": 1
252
347
  },
348
+ "migration_strategy": {
349
+ "type": "array",
350
+ "items": { "type": "string", "nonEmpty": true }
351
+ },
352
+ "database_changes": {
353
+ "type": "array",
354
+ "items": { "type": "string", "nonEmpty": true }
355
+ },
356
+ "api_changes": {
357
+ "type": "array",
358
+ "items": { "type": "string", "nonEmpty": true }
359
+ },
253
360
  "risks": {
254
361
  "type": "array",
255
362
  "items": { "type": "string", "nonEmpty": true }
256
363
  },
364
+ "acceptance_criteria": {
365
+ "type": "array",
366
+ "items": { "type": "string", "nonEmpty": true }
367
+ },
257
368
  "open_questions": {
258
369
  "type": "array",
259
370
  "items": { "type": "string", "nonEmpty": true }
@@ -269,6 +380,10 @@
269
380
  "type": "array",
270
381
  "items": { "type": "string", "nonEmpty": true }
271
382
  },
383
+ "workstreams": {
384
+ "type": "array",
385
+ "items": { "type": "string", "nonEmpty": true }
386
+ },
272
387
  "implementation_steps": {
273
388
  "type": "array",
274
389
  "items": {
@@ -276,7 +391,19 @@
276
391
  "properties": {
277
392
  "id": { "type": "string", "nonEmpty": true },
278
393
  "title": { "type": "string", "nonEmpty": true },
279
- "details": { "type": "string", "nonEmpty": true }
394
+ "details": { "type": "string", "nonEmpty": true },
395
+ "affected_files": {
396
+ "type": "array",
397
+ "items": { "type": "string", "nonEmpty": true }
398
+ },
399
+ "verification": {
400
+ "type": "array",
401
+ "items": { "type": "string", "nonEmpty": true }
402
+ },
403
+ "dependencies": {
404
+ "type": "array",
405
+ "items": { "type": "string", "nonEmpty": true }
406
+ }
280
407
  },
281
408
  "required": ["id", "title", "details"]
282
409
  },
@@ -290,6 +417,10 @@
290
417
  "rollout_notes": {
291
418
  "type": "array",
292
419
  "items": { "type": "string", "nonEmpty": true }
420
+ },
421
+ "follow_up_items": {
422
+ "type": "array",
423
+ "items": { "type": "string", "nonEmpty": true }
293
424
  }
294
425
  },
295
426
  "required": ["summary", "prerequisites", "implementation_steps", "tests", "rollout_notes"]
@@ -308,6 +439,28 @@
308
439
  },
309
440
  "required": ["summary"]
310
441
  },
442
+ "planning-questions/v1": {
443
+ "type": "object",
444
+ "properties": {
445
+ "summary": { "type": "string", "nonEmpty": true },
446
+ "questions": {
447
+ "type": "array",
448
+ "items": {
449
+ "type": "object",
450
+ "properties": {
451
+ "id": { "type": "string", "nonEmpty": true },
452
+ "question": { "type": "string", "nonEmpty": true },
453
+ "details": { "type": "string" },
454
+ "required": { "type": "boolean" },
455
+ "multiline": { "type": "boolean" },
456
+ "placeholder": { "type": "string" }
457
+ },
458
+ "required": ["id", "question", "details", "required", "multiline", "placeholder"]
459
+ }
460
+ }
461
+ },
462
+ "required": ["summary", "questions"]
463
+ },
311
464
  "qa-plan/v1": {
312
465
  "type": "object",
313
466
  "properties": {
@@ -6,11 +6,13 @@ export const STRUCTURED_ARTIFACT_SCHEMA_IDS = [
6
6
  "bug-analysis/v1",
7
7
  "bug-fix-design/v1",
8
8
  "bug-fix-plan/v1",
9
+ "gitlab-mr-diff/v1",
9
10
  "gitlab-review/v1",
10
11
  "implementation-design/v1",
11
12
  "implementation-plan/v1",
12
13
  "jira-description/v1",
13
14
  "mr-description/v1",
15
+ "planning-questions/v1",
14
16
  "qa-plan/v1",
15
17
  "review-findings/v1",
16
18
  "review-fix-report/v1",
@@ -83,6 +83,13 @@ function parseBoolean(value) {
83
83
  return null;
84
84
  }
85
85
  export async function requestUserInputInTerminal(form) {
86
+ if (form.fields.length === 0) {
87
+ return {
88
+ formId: form.formId,
89
+ submittedAt: new Date().toISOString(),
90
+ values: {},
91
+ };
92
+ }
86
93
  if (!process.stdin.isTTY || !process.stdout.isTTY) {
87
94
  throw new TaskRunnerError(`Flow requires interactive user input for form '${form.formId}', but no TTY is available.`);
88
95
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentweaver",
3
- "version": "0.1.8",
3
+ "version": "0.1.10",
4
4
  "description": "CLI orchestrator for Jira/Codex/Claude engineering workflows",
5
5
  "keywords": [
6
6
  "agent",
@@ -1,206 +0,0 @@
1
- {
2
- "kind": "interactive-preflight-flow",
3
- "version": 1,
4
- "phases": [
5
- {
6
- "id": "preflight",
7
- "steps": [
8
- {
9
- "id": "check_commands",
10
- "node": "command-check",
11
- "params": {
12
- "commands": {
13
- "const": [
14
- { "commandName": "codex", "envVarName": "CODEX_BIN" },
15
- { "commandName": "claude", "envVarName": "CLAUDE_BIN" }
16
- ]
17
- }
18
- }
19
- },
20
- {
21
- "id": "fetch_jira_if_needed",
22
- "when": {
23
- "any": [
24
- { "ref": "params.forceRefresh" },
25
- {
26
- "not": {
27
- "exists": {
28
- "artifact": {
29
- "kind": "jira-task-file",
30
- "taskKey": { "ref": "params.taskKey" }
31
- }
32
- }
33
- }
34
- }
35
- ]
36
- },
37
- "node": "jira-fetch",
38
- "params": {
39
- "jiraApiUrl": { "ref": "params.jiraApiUrl" },
40
- "outputFile": {
41
- "artifact": {
42
- "kind": "jira-task-file",
43
- "taskKey": { "ref": "params.taskKey" }
44
- }
45
- }
46
- },
47
- "expect": [
48
- {
49
- "kind": "require-file",
50
- "path": {
51
- "artifact": {
52
- "kind": "jira-task-file",
53
- "taskKey": { "ref": "params.taskKey" }
54
- }
55
- },
56
- "message": "Jira fetch node did not produce the Jira task file."
57
- }
58
- ]
59
- },
60
- {
61
- "id": "load_existing_task_summary",
62
- "when": {
63
- "all": [
64
- {
65
- "not": { "ref": "params.forceRefresh" }
66
- },
67
- {
68
- "exists": {
69
- "artifact": {
70
- "kind": "jira-task-file",
71
- "taskKey": { "ref": "params.taskKey" }
72
- }
73
- }
74
- },
75
- {
76
- "exists": {
77
- "artifact": {
78
- "kind": "task-summary-file",
79
- "taskKey": { "ref": "params.taskKey" }
80
- }
81
- }
82
- }
83
- ]
84
- },
85
- "node": "summary-file-load",
86
- "params": {
87
- "path": {
88
- "artifact": {
89
- "kind": "task-summary-file",
90
- "taskKey": { "ref": "params.taskKey" }
91
- }
92
- }
93
- }
94
- },
95
- {
96
- "id": "generate_task_summary",
97
- "when": {
98
- "any": [
99
- { "ref": "params.forceRefresh" },
100
- {
101
- "not": {
102
- "exists": {
103
- "artifact": {
104
- "kind": "task-summary-file",
105
- "taskKey": { "ref": "params.taskKey" }
106
- }
107
- }
108
- }
109
- }
110
- ]
111
- },
112
- "node": "claude-prompt",
113
- "prompt": {
114
- "templateRef": "task-summary",
115
- "vars": {
116
- "jira_task_file": {
117
- "artifact": {
118
- "kind": "jira-task-file",
119
- "taskKey": { "ref": "params.taskKey" }
120
- }
121
- },
122
- "task_summary_file": {
123
- "artifact": {
124
- "kind": "task-summary-file",
125
- "taskKey": { "ref": "params.taskKey" }
126
- }
127
- },
128
- "task_summary_json_file": {
129
- "artifact": {
130
- "kind": "task-summary-json-file",
131
- "taskKey": { "ref": "params.taskKey" }
132
- }
133
- }
134
- },
135
- "format": "plain"
136
- },
137
- "params": {
138
- "labelText": { "const": "Preparing task summary" },
139
- "outputFile": {
140
- "artifact": {
141
- "kind": "task-summary-file",
142
- "taskKey": { "ref": "params.taskKey" }
143
- }
144
- },
145
- "requiredArtifacts": {
146
- "list": [
147
- {
148
- "artifact": {
149
- "kind": "task-summary-json-file",
150
- "taskKey": { "ref": "params.taskKey" }
151
- }
152
- }
153
- ]
154
- },
155
- "model": { "const": "haiku" }
156
- },
157
- "expect": [
158
- {
159
- "kind": "require-artifacts",
160
- "when": { "not": { "ref": "context.dryRun" } },
161
- "paths": {
162
- "list": [
163
- {
164
- "artifact": {
165
- "kind": "task-summary-file",
166
- "taskKey": { "ref": "params.taskKey" }
167
- }
168
- }
169
- ]
170
- },
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."
188
- }
189
- ],
190
- "after": [
191
- {
192
- "kind": "set-summary-from-file",
193
- "when": { "not": { "ref": "context.dryRun" } },
194
- "path": {
195
- "artifact": {
196
- "kind": "task-summary-file",
197
- "taskKey": { "ref": "params.taskKey" }
198
- }
199
- }
200
- }
201
- ]
202
- }
203
- ]
204
- }
205
- ]
206
- }