agentweaver 0.1.3 → 0.1.4
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.
- package/README.md +48 -14
- package/dist/artifacts.js +34 -0
- package/dist/executors/verify-build-executor.js +110 -9
- package/dist/index.js +82 -5
- package/dist/interactive-ui.js +100 -13
- package/dist/pipeline/checks.js +5 -0
- package/dist/pipeline/declarative-flow-runner.js +16 -0
- package/dist/pipeline/flow-specs/auto.json +17 -3
- package/dist/pipeline/flow-specs/bug-analyze.json +140 -0
- package/dist/pipeline/flow-specs/bug-fix.json +44 -0
- package/dist/pipeline/flow-specs/mr-description.json +61 -0
- package/dist/pipeline/flow-specs/run-linter-loop.json +149 -0
- package/dist/pipeline/flow-specs/run-tests-loop.json +149 -0
- package/dist/pipeline/flow-specs/task-describe.json +61 -0
- package/dist/pipeline/node-registry.js +3 -0
- package/dist/pipeline/nodes/flow-run-node.js +40 -0
- package/dist/pipeline/nodes/verify-build-node.js +1 -0
- package/dist/pipeline/prompt-registry.js +6 -1
- package/dist/pipeline/spec-compiler.js +13 -0
- package/dist/pipeline/spec-validator.js +12 -0
- package/dist/pipeline/value-resolver.js +19 -1
- package/dist/prompts.js +21 -0
- package/dist/structured-artifacts.js +178 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -11,9 +11,10 @@ The package is designed to run as an npm CLI and includes an interactive termina
|
|
|
11
11
|
## What It Does
|
|
12
12
|
|
|
13
13
|
- Fetches a Jira issue by key or browse URL
|
|
14
|
-
- Generates workflow artifacts such as design, implementation plan, QA plan, reviews, and summaries
|
|
15
|
-
-
|
|
16
|
-
-
|
|
14
|
+
- Generates workflow artifacts such as design, implementation plan, QA plan, bug analysis, reviews, and summaries
|
|
15
|
+
- For bug-analysis flows, structured JSON artifacts are the machine-readable source of truth, while Markdown artifacts are for human inspection
|
|
16
|
+
- Runs workflow stages like `bug-analyze`, `bug-fix`, `mr-description`, `plan`, `task-describe`, `implement`, `review`, `review-fix`, `test`, and `auto`
|
|
17
|
+
- Persists compact `auto` pipeline state on disk so runs can resume without storing large agent outputs
|
|
17
18
|
- Uses Docker runtime services for isolated Codex execution and build verification
|
|
18
19
|
|
|
19
20
|
## Architecture
|
|
@@ -23,7 +24,7 @@ The CLI now uses an executor + node + declarative flow architecture.
|
|
|
23
24
|
- `src/index.ts` remains the CLI entrypoint and high-level orchestration layer
|
|
24
25
|
- `src/executors/` contains first-class executors for external actions such as Jira fetch, local Codex, Docker-based build verification, Claude, Claude summaries, and process execution
|
|
25
26
|
- `src/pipeline/nodes/` contains reusable runtime nodes built on top of executors
|
|
26
|
-
- `src/pipeline/flow-specs/` contains declarative JSON flow specs for `preflight`, `plan`, `implement`, `review`, `review-fix`, `test`, `test-fix`, `test-linter-fix`, and `auto`
|
|
27
|
+
- `src/pipeline/flow-specs/` contains declarative JSON flow specs for `preflight`, `bug-analyze`, `bug-fix`, `mr-description`, `plan`, `task-describe`, `implement`, `review`, `review-fix`, `test`, `test-fix`, `test-linter-fix`, `run-tests-loop`, `run-linter-loop`, and `auto`
|
|
27
28
|
- `src/runtime/` contains shared runtime services such as command resolution, Docker runtime environment setup, and subprocess execution
|
|
28
29
|
|
|
29
30
|
This keeps command handlers focused on choosing a flow and providing parameters instead of assembling prompts and subprocess wiring inline.
|
|
@@ -41,7 +42,9 @@ This keeps command handlers focused on choosing a flow and providing parameters
|
|
|
41
42
|
- `src/runtime/` — shared runtime services used by executors
|
|
42
43
|
- `docker-compose.yml` — runtime services for Codex and build verification
|
|
43
44
|
- `Dockerfile.codex` — container image for Codex runtime
|
|
44
|
-
- `verify_build.sh` —
|
|
45
|
+
- `verify_build.sh` — aggregated verification entrypoint used by `verify-build`
|
|
46
|
+
- `run_tests.sh` — isolated test and coverage verification entrypoint
|
|
47
|
+
- `run_linter.sh` — isolated generate + lint verification entrypoint
|
|
45
48
|
- `package.json` — npm package metadata and scripts
|
|
46
49
|
- `tsconfig.json` — TypeScript configuration
|
|
47
50
|
|
|
@@ -50,7 +53,7 @@ This keeps command handlers focused on choosing a flow and providing parameters
|
|
|
50
53
|
- Node.js `>= 18.19.0`
|
|
51
54
|
- npm
|
|
52
55
|
- Docker with `docker compose` or `docker-compose`
|
|
53
|
-
- `codex` CLI for `
|
|
56
|
+
- `codex` CLI for `bug-analyze`, `bug-fix`, `mr-description`, `plan`, and other Codex-driven steps
|
|
54
57
|
- `claude` CLI for review and summary steps
|
|
55
58
|
|
|
56
59
|
## Installation
|
|
@@ -112,8 +115,14 @@ Direct CLI usage:
|
|
|
112
115
|
|
|
113
116
|
```bash
|
|
114
117
|
agentweaver plan DEMO-3288
|
|
118
|
+
agentweaver bug-analyze DEMO-3288
|
|
119
|
+
agentweaver bug-fix DEMO-3288
|
|
120
|
+
agentweaver mr-description DEMO-3288
|
|
121
|
+
agentweaver task-describe DEMO-3288
|
|
115
122
|
agentweaver implement DEMO-3288
|
|
116
123
|
agentweaver review DEMO-3288
|
|
124
|
+
agentweaver run-tests-loop DEMO-3288
|
|
125
|
+
agentweaver run-linter-loop DEMO-3288
|
|
117
126
|
agentweaver auto DEMO-3288
|
|
118
127
|
```
|
|
119
128
|
|
|
@@ -121,6 +130,10 @@ From source checkout:
|
|
|
121
130
|
|
|
122
131
|
```bash
|
|
123
132
|
node dist/index.js plan DEMO-3288
|
|
133
|
+
node dist/index.js bug-analyze DEMO-3288
|
|
134
|
+
node dist/index.js bug-fix DEMO-3288
|
|
135
|
+
node dist/index.js mr-description DEMO-3288
|
|
136
|
+
node dist/index.js task-describe DEMO-3288
|
|
124
137
|
node dist/index.js auto DEMO-3288
|
|
125
138
|
```
|
|
126
139
|
|
|
@@ -145,28 +158,35 @@ agentweaver auto-status DEMO-3288
|
|
|
145
158
|
agentweaver auto-reset DEMO-3288
|
|
146
159
|
```
|
|
147
160
|
|
|
161
|
+
Notes:
|
|
162
|
+
|
|
163
|
+
- `--verbose` streams child process `stdout/stderr` in direct CLI mode
|
|
164
|
+
- the interactive `Activity` pane is intentionally structured: it shows launch separators, prompts, summaries, and short status messages instead of raw Codex/Claude logs by default
|
|
165
|
+
|
|
148
166
|
## Interactive TUI
|
|
149
167
|
|
|
150
168
|
Interactive mode opens a full-screen terminal UI with:
|
|
151
169
|
|
|
152
|
-
-
|
|
170
|
+
- flow list
|
|
171
|
+
- current flow progress
|
|
153
172
|
- activity log
|
|
154
173
|
- task summary pane
|
|
155
|
-
- command list/help
|
|
156
174
|
- keyboard navigation between panes
|
|
157
175
|
|
|
158
176
|
Current navigation:
|
|
159
177
|
|
|
160
|
-
- `Enter` — run
|
|
178
|
+
- `Enter` — run selected flow
|
|
161
179
|
- `Tab` / `Shift+Tab` — switch panes
|
|
162
|
-
- `Ctrl+J` — focus activity log
|
|
163
|
-
- `Ctrl+K` — focus command input
|
|
164
|
-
- `Ctrl+U` — focus task summary
|
|
165
|
-
- `Ctrl+H` — focus commands pane
|
|
166
180
|
- `PgUp` / `PgDn` / `Home` / `End` — scroll focused panes
|
|
167
|
-
-
|
|
181
|
+
- `h` — help overlay
|
|
168
182
|
- `q` or `Ctrl+C` — exit
|
|
169
183
|
|
|
184
|
+
Activity pane behavior:
|
|
185
|
+
|
|
186
|
+
- each external launch is separated with a framed block that shows the current `node`, `executor`, and `model` when available
|
|
187
|
+
- prompts and summaries are rendered as plain text for readability
|
|
188
|
+
- live raw Codex/Claude output is not shown there in normal mode
|
|
189
|
+
|
|
170
190
|
## Docker Runtime
|
|
171
191
|
|
|
172
192
|
Docker is used as an isolated execution environment for Codex and build/test verification.
|
|
@@ -176,6 +196,8 @@ Main services:
|
|
|
176
196
|
- `codex` — interactive Codex container
|
|
177
197
|
- `codex-exec` — non-interactive `codex exec`
|
|
178
198
|
- `verify-build` — project verification script inside container
|
|
199
|
+
- `run-tests` — isolated `run_tests.sh` execution inside container
|
|
200
|
+
- `run-linter` — isolated `run_linter.sh` execution inside container
|
|
179
201
|
- `codex-login` — interactive login container
|
|
180
202
|
- `dockerd` — internal Docker daemon for testcontainers/build flows
|
|
181
203
|
|
|
@@ -205,6 +227,18 @@ Build verification:
|
|
|
205
227
|
PROJECT_DIR="$PWD" docker compose -f "$AGENTWEAVER_HOME/docker-compose.yml" run --rm verify-build
|
|
206
228
|
```
|
|
207
229
|
|
|
230
|
+
Tests only:
|
|
231
|
+
|
|
232
|
+
```bash
|
|
233
|
+
PROJECT_DIR="$PWD" docker compose -f "$AGENTWEAVER_HOME/docker-compose.yml" run --rm run-tests
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
Linter only:
|
|
237
|
+
|
|
238
|
+
```bash
|
|
239
|
+
PROJECT_DIR="$PWD" docker compose -f "$AGENTWEAVER_HOME/docker-compose.yml" run --rm run-linter
|
|
240
|
+
```
|
|
241
|
+
|
|
208
242
|
## Development
|
|
209
243
|
|
|
210
244
|
Install dependencies and build:
|
package/dist/artifacts.js
CHANGED
|
@@ -25,6 +25,24 @@ export function designFile(taskKey) {
|
|
|
25
25
|
export function planFile(taskKey) {
|
|
26
26
|
return artifactFile("plan", taskKey, 1);
|
|
27
27
|
}
|
|
28
|
+
export function bugAnalyzeFile(taskKey) {
|
|
29
|
+
return taskWorkspaceFile(taskKey, `bug-analyze-${taskKey}.md`);
|
|
30
|
+
}
|
|
31
|
+
export function bugAnalyzeJsonFile(taskKey) {
|
|
32
|
+
return taskWorkspaceFile(taskKey, `bug-analyze-${taskKey}.json`);
|
|
33
|
+
}
|
|
34
|
+
export function bugFixDesignFile(taskKey) {
|
|
35
|
+
return taskWorkspaceFile(taskKey, `bug-fix-design-${taskKey}.md`);
|
|
36
|
+
}
|
|
37
|
+
export function bugFixDesignJsonFile(taskKey) {
|
|
38
|
+
return taskWorkspaceFile(taskKey, `bug-fix-design-${taskKey}.json`);
|
|
39
|
+
}
|
|
40
|
+
export function bugFixPlanFile(taskKey) {
|
|
41
|
+
return taskWorkspaceFile(taskKey, `bug-fix-plan-${taskKey}.md`);
|
|
42
|
+
}
|
|
43
|
+
export function bugFixPlanJsonFile(taskKey) {
|
|
44
|
+
return taskWorkspaceFile(taskKey, `bug-fix-plan-${taskKey}.json`);
|
|
45
|
+
}
|
|
28
46
|
export function qaFile(taskKey) {
|
|
29
47
|
return artifactFile("qa", taskKey, 1);
|
|
30
48
|
}
|
|
@@ -37,12 +55,28 @@ export function readyToMergeFile(taskKey) {
|
|
|
37
55
|
export function jiraTaskFile(taskKey) {
|
|
38
56
|
return taskWorkspaceFile(taskKey, `${taskKey}.json`);
|
|
39
57
|
}
|
|
58
|
+
export function jiraDescriptionFile(taskKey) {
|
|
59
|
+
return taskWorkspaceFile(taskKey, `jira-${taskKey}-description.md`);
|
|
60
|
+
}
|
|
61
|
+
export function mrDescriptionFile(taskKey) {
|
|
62
|
+
return taskWorkspaceFile(taskKey, `mr-description-${taskKey}.md`);
|
|
63
|
+
}
|
|
40
64
|
export function autoStateFile(taskKey) {
|
|
41
65
|
return taskWorkspaceFile(taskKey, `.agentweaver-state-${taskKey}.json`);
|
|
42
66
|
}
|
|
43
67
|
export function planArtifacts(taskKey) {
|
|
44
68
|
return [designFile(taskKey), planFile(taskKey), qaFile(taskKey)];
|
|
45
69
|
}
|
|
70
|
+
export function bugAnalyzeArtifacts(taskKey) {
|
|
71
|
+
return [
|
|
72
|
+
bugAnalyzeFile(taskKey),
|
|
73
|
+
bugAnalyzeJsonFile(taskKey),
|
|
74
|
+
bugFixDesignFile(taskKey),
|
|
75
|
+
bugFixDesignJsonFile(taskKey),
|
|
76
|
+
bugFixPlanFile(taskKey),
|
|
77
|
+
bugFixPlanJsonFile(taskKey),
|
|
78
|
+
];
|
|
79
|
+
}
|
|
46
80
|
export function requireArtifacts(paths, message) {
|
|
47
81
|
const missing = paths.filter((filePath) => !existsSync(filePath));
|
|
48
82
|
if (missing.length > 0) {
|
|
@@ -1,22 +1,123 @@
|
|
|
1
1
|
import { verifyBuildExecutorDefaultConfig } from "./configs/verify-build-config.js";
|
|
2
|
+
import { TaskRunnerError } from "../errors.js";
|
|
2
3
|
import { processExecutor } from "./process-executor.js";
|
|
4
|
+
function parseStructuredResult(output, service) {
|
|
5
|
+
const lines = output
|
|
6
|
+
.split(/\r?\n/)
|
|
7
|
+
.map((line) => line.replace(/\u001b\[[0-9;]*m/g, "").trim())
|
|
8
|
+
.filter(Boolean);
|
|
9
|
+
if (lines.length === 0) {
|
|
10
|
+
throw new TaskRunnerError(`Structured result is missing from service '${service}' output.`);
|
|
11
|
+
}
|
|
12
|
+
for (let index = lines.length - 1; index >= 0; index -= 1) {
|
|
13
|
+
const line = lines[index];
|
|
14
|
+
if (!line) {
|
|
15
|
+
continue;
|
|
16
|
+
}
|
|
17
|
+
const candidates = [];
|
|
18
|
+
if (line.startsWith("{") && line.endsWith("}")) {
|
|
19
|
+
candidates.push(line);
|
|
20
|
+
}
|
|
21
|
+
const firstBrace = line.indexOf("{");
|
|
22
|
+
const lastBrace = line.lastIndexOf("}");
|
|
23
|
+
if (firstBrace >= 0 && lastBrace > firstBrace) {
|
|
24
|
+
const slice = line.slice(firstBrace, lastBrace + 1).trim();
|
|
25
|
+
if (slice && !candidates.includes(slice)) {
|
|
26
|
+
candidates.push(slice);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
for (const rawJson of candidates) {
|
|
30
|
+
let parsed;
|
|
31
|
+
try {
|
|
32
|
+
parsed = JSON.parse(rawJson);
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
const candidate = parsed;
|
|
41
|
+
if (typeof candidate.ok !== "boolean" ||
|
|
42
|
+
typeof candidate.kind !== "string" ||
|
|
43
|
+
typeof candidate.stage !== "string" ||
|
|
44
|
+
typeof candidate.exitCode !== "number" ||
|
|
45
|
+
typeof candidate.summary !== "string" ||
|
|
46
|
+
typeof candidate.command !== "string") {
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
const details = candidate.details;
|
|
50
|
+
if (details !== undefined && (!details || typeof details !== "object" || Array.isArray(details))) {
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
return {
|
|
54
|
+
ok: candidate.ok,
|
|
55
|
+
kind: candidate.kind,
|
|
56
|
+
stage: candidate.stage,
|
|
57
|
+
exitCode: candidate.exitCode,
|
|
58
|
+
summary: candidate.summary,
|
|
59
|
+
command: candidate.command,
|
|
60
|
+
details: details ?? {},
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
throw new TaskRunnerError(`Structured result is missing or invalid in service '${service}' output.`);
|
|
65
|
+
}
|
|
3
66
|
export const verifyBuildExecutor = {
|
|
4
67
|
kind: "verify-build",
|
|
5
68
|
version: 1,
|
|
6
69
|
defaultConfig: verifyBuildExecutorDefaultConfig,
|
|
7
70
|
async execute(context, input, config) {
|
|
8
71
|
const composeCommand = context.runtime.resolveDockerComposeCmd();
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
72
|
+
const service = input.service ?? config.service;
|
|
73
|
+
if (context.dryRun) {
|
|
74
|
+
await processExecutor.execute(context, {
|
|
75
|
+
argv: [...composeCommand, config.composeFileFlag, input.dockerComposeFile, ...config.runArgs, service],
|
|
76
|
+
env: context.runtime.dockerRuntimeEnv(),
|
|
77
|
+
verbose: config.verbose,
|
|
78
|
+
label: service,
|
|
79
|
+
}, {
|
|
80
|
+
printFailureOutput: config.printFailureOutput,
|
|
81
|
+
});
|
|
82
|
+
return {
|
|
83
|
+
output: "",
|
|
84
|
+
composeCommand,
|
|
85
|
+
parsed: {
|
|
86
|
+
ok: true,
|
|
87
|
+
kind: service,
|
|
88
|
+
stage: "dry_run",
|
|
89
|
+
exitCode: 0,
|
|
90
|
+
summary: `Dry run for service '${service}'`,
|
|
91
|
+
command: [...composeCommand, config.composeFileFlag, input.dockerComposeFile, ...config.runArgs, service].join(" "),
|
|
92
|
+
details: {},
|
|
93
|
+
},
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
let output = "";
|
|
97
|
+
let exitCode = 0;
|
|
98
|
+
try {
|
|
99
|
+
const result = await processExecutor.execute(context, {
|
|
100
|
+
argv: [...composeCommand, config.composeFileFlag, input.dockerComposeFile, ...config.runArgs, service],
|
|
101
|
+
env: context.runtime.dockerRuntimeEnv(),
|
|
102
|
+
verbose: config.verbose,
|
|
103
|
+
label: service,
|
|
104
|
+
}, {
|
|
105
|
+
printFailureOutput: config.printFailureOutput,
|
|
106
|
+
});
|
|
107
|
+
output = result.output;
|
|
108
|
+
}
|
|
109
|
+
catch (error) {
|
|
110
|
+
output = String(error.output ?? "");
|
|
111
|
+
exitCode = Number(error.returnCode ?? 1);
|
|
112
|
+
}
|
|
113
|
+
const parsed = parseStructuredResult(output, service);
|
|
114
|
+
if (parsed.exitCode !== exitCode && exitCode !== 0) {
|
|
115
|
+
throw new TaskRunnerError(`Structured result exit code mismatch for service '${service}': script=${parsed.exitCode}, runtime=${exitCode}.`);
|
|
116
|
+
}
|
|
17
117
|
return {
|
|
18
|
-
output
|
|
118
|
+
output,
|
|
19
119
|
composeCommand,
|
|
120
|
+
parsed,
|
|
20
121
|
};
|
|
21
122
|
},
|
|
22
123
|
};
|
package/dist/index.js
CHANGED
|
@@ -3,9 +3,10 @@ import { existsSync, readdirSync, readFileSync, rmSync, writeFileSync } from "no
|
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import process from "node:process";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
|
-
import { REVIEW_FILE_RE, REVIEW_REPLY_FILE_RE, autoStateFile, ensureTaskWorkspaceDir, jiraTaskFile, planArtifacts, readyToMergeFile, requireArtifacts, taskWorkspaceDir, taskSummaryFile, } from "./artifacts.js";
|
|
6
|
+
import { REVIEW_FILE_RE, REVIEW_REPLY_FILE_RE, autoStateFile, bugAnalyzeArtifacts, bugAnalyzeJsonFile, bugFixDesignJsonFile, bugFixPlanJsonFile, ensureTaskWorkspaceDir, jiraTaskFile, planArtifacts, readyToMergeFile, requireArtifacts, taskWorkspaceDir, taskSummaryFile, } from "./artifacts.js";
|
|
7
7
|
import { TaskRunnerError } from "./errors.js";
|
|
8
8
|
import { buildJiraApiUrl, buildJiraBrowseUrl, extractIssueKey, requireJiraTaskFile } from "./jira.js";
|
|
9
|
+
import { validateStructuredArtifacts } from "./structured-artifacts.js";
|
|
9
10
|
import { summarizeBuildFailure as summarizeBuildFailureViaPipeline } from "./pipeline/build-failure-summary.js";
|
|
10
11
|
import { createPipelineContext } from "./pipeline/context.js";
|
|
11
12
|
import { loadAutoFlow } from "./pipeline/auto-flow.js";
|
|
@@ -18,18 +19,24 @@ import { runCommand } from "./runtime/process-runner.js";
|
|
|
18
19
|
import { InteractiveUi } from "./interactive-ui.js";
|
|
19
20
|
import { bye, printError, printInfo, printPanel, printSummary, setFlowExecutionState } from "./tui.js";
|
|
20
21
|
const COMMANDS = [
|
|
22
|
+
"bug-analyze",
|
|
23
|
+
"bug-fix",
|
|
24
|
+
"mr-description",
|
|
21
25
|
"plan",
|
|
26
|
+
"task-describe",
|
|
22
27
|
"implement",
|
|
23
28
|
"review",
|
|
24
29
|
"review-fix",
|
|
25
30
|
"test",
|
|
26
31
|
"test-fix",
|
|
27
32
|
"test-linter-fix",
|
|
33
|
+
"run-tests-loop",
|
|
34
|
+
"run-linter-loop",
|
|
28
35
|
"auto",
|
|
29
36
|
"auto-status",
|
|
30
37
|
"auto-reset",
|
|
31
38
|
];
|
|
32
|
-
const AUTO_STATE_SCHEMA_VERSION =
|
|
39
|
+
const AUTO_STATE_SCHEMA_VERSION = 3;
|
|
33
40
|
const MODULE_DIR = path.dirname(fileURLToPath(import.meta.url));
|
|
34
41
|
const PACKAGE_ROOT = path.resolve(MODULE_DIR, "..");
|
|
35
42
|
const runtimeServices = {
|
|
@@ -42,13 +49,19 @@ function usage() {
|
|
|
42
49
|
return `Usage:
|
|
43
50
|
agentweaver <jira-browse-url|jira-issue-key>
|
|
44
51
|
agentweaver --force <jira-browse-url|jira-issue-key>
|
|
52
|
+
agentweaver bug-analyze [--dry] [--verbose] [--prompt <text>] <jira-browse-url|jira-issue-key>
|
|
53
|
+
agentweaver bug-fix [--dry] [--verbose] [--prompt <text>] <jira-browse-url|jira-issue-key>
|
|
54
|
+
agentweaver mr-description [--dry] [--verbose] [--prompt <text>] <jira-browse-url|jira-issue-key>
|
|
45
55
|
agentweaver plan [--dry] [--verbose] [--prompt <text>] <jira-browse-url|jira-issue-key>
|
|
56
|
+
agentweaver task-describe [--dry] [--verbose] [--prompt <text>] <jira-browse-url|jira-issue-key>
|
|
46
57
|
agentweaver implement [--dry] [--verbose] [--prompt <text>] <jira-browse-url|jira-issue-key>
|
|
47
58
|
agentweaver review [--dry] [--verbose] [--prompt <text>] <jira-browse-url|jira-issue-key>
|
|
48
59
|
agentweaver review-fix [--dry] [--verbose] [--prompt <text>] <jira-browse-url|jira-issue-key>
|
|
49
60
|
agentweaver test [--dry] [--verbose] <jira-browse-url|jira-issue-key>
|
|
50
61
|
agentweaver test-fix [--dry] [--verbose] [--prompt <text>] <jira-browse-url|jira-issue-key>
|
|
51
62
|
agentweaver test-linter-fix [--dry] [--verbose] [--prompt <text>] <jira-browse-url|jira-issue-key>
|
|
63
|
+
agentweaver run-tests-loop [--dry] [--verbose] [--prompt <text>] <jira-browse-url|jira-issue-key>
|
|
64
|
+
agentweaver run-linter-loop [--dry] [--verbose] [--prompt <text>] <jira-browse-url|jira-issue-key>
|
|
52
65
|
agentweaver auto [--dry] [--verbose] [--prompt <text>] <jira-browse-url|jira-issue-key>
|
|
53
66
|
agentweaver auto [--dry] [--verbose] [--prompt <text>] --from <phase> <jira-browse-url|jira-issue-key>
|
|
54
67
|
agentweaver auto --help-phases
|
|
@@ -67,7 +80,7 @@ Flags:
|
|
|
67
80
|
--prompt Extra prompt text appended to the base prompt
|
|
68
81
|
|
|
69
82
|
Required environment variables:
|
|
70
|
-
JIRA_API_KEY Jira API key used in Authorization: Bearer <token> for
|
|
83
|
+
JIRA_API_KEY Jira API key used in Authorization: Bearer <token> for Jira-backed flows
|
|
71
84
|
|
|
72
85
|
Optional environment variables:
|
|
73
86
|
JIRA_BASE_URL
|
|
@@ -370,13 +383,20 @@ function buildConfig(command, jiraRef, options = {}) {
|
|
|
370
383
|
};
|
|
371
384
|
}
|
|
372
385
|
function checkPrerequisites(config) {
|
|
373
|
-
if (config.command === "
|
|
386
|
+
if (config.command === "bug-analyze" ||
|
|
387
|
+
config.command === "bug-fix" ||
|
|
388
|
+
config.command === "mr-description" ||
|
|
389
|
+
config.command === "plan" ||
|
|
390
|
+
config.command === "task-describe" ||
|
|
391
|
+
config.command === "review" ||
|
|
392
|
+
config.command === "run-tests-loop" ||
|
|
393
|
+
config.command === "run-linter-loop") {
|
|
374
394
|
resolveCmd("codex", "CODEX_BIN");
|
|
375
395
|
}
|
|
376
396
|
if (config.command === "review") {
|
|
377
397
|
resolveCmd("claude", "CLAUDE_BIN");
|
|
378
398
|
}
|
|
379
|
-
if (["implement", "review-fix", "test"].includes(config.command)) {
|
|
399
|
+
if (["implement", "review-fix", "test", "run-tests-loop", "run-linter-loop"].includes(config.command)) {
|
|
380
400
|
resolveDockerComposeCmd();
|
|
381
401
|
if (!existsSync(config.dockerComposeFile)) {
|
|
382
402
|
throw new TaskRunnerError(`docker-compose file not found: ${config.dockerComposeFile}`);
|
|
@@ -431,13 +451,19 @@ function autoFlowDefinition() {
|
|
|
431
451
|
function interactiveFlowDefinitions() {
|
|
432
452
|
return [
|
|
433
453
|
autoFlowDefinition(),
|
|
454
|
+
declarativeFlowDefinition("bug-analyze", "bug-analyze", "bug-analyze.json"),
|
|
455
|
+
declarativeFlowDefinition("bug-fix", "bug-fix", "bug-fix.json"),
|
|
456
|
+
declarativeFlowDefinition("mr-description", "mr-description", "mr-description.json"),
|
|
434
457
|
declarativeFlowDefinition("plan", "plan", "plan.json"),
|
|
458
|
+
declarativeFlowDefinition("task-describe", "task-describe", "task-describe.json"),
|
|
435
459
|
declarativeFlowDefinition("implement", "implement", "implement.json"),
|
|
436
460
|
declarativeFlowDefinition("review", "review", "review.json"),
|
|
437
461
|
declarativeFlowDefinition("review-fix", "review-fix", "review-fix.json"),
|
|
438
462
|
declarativeFlowDefinition("test", "test", "test.json"),
|
|
439
463
|
declarativeFlowDefinition("test-fix", "test-fix", "test-fix.json"),
|
|
440
464
|
declarativeFlowDefinition("test-linter-fix", "test-linter-fix", "test-linter-fix.json"),
|
|
465
|
+
declarativeFlowDefinition("run-tests-loop", "run-tests-loop", "run-tests-loop.json"),
|
|
466
|
+
declarativeFlowDefinition("run-linter-loop", "run-linter-loop", "run-linter-loop.json"),
|
|
441
467
|
];
|
|
442
468
|
}
|
|
443
469
|
function publishFlowState(flowId, executionState) {
|
|
@@ -589,6 +615,49 @@ async function executeCommand(config, runFollowupVerify = true) {
|
|
|
589
615
|
});
|
|
590
616
|
return false;
|
|
591
617
|
}
|
|
618
|
+
if (config.command === "bug-analyze") {
|
|
619
|
+
if (config.verbose) {
|
|
620
|
+
process.stdout.write(`Fetching Jira issue from browse URL: ${config.jiraBrowseUrl}\n`);
|
|
621
|
+
process.stdout.write(`Resolved Jira API URL: ${config.jiraApiUrl}\n`);
|
|
622
|
+
process.stdout.write(`Saving Jira issue JSON to: ${config.jiraTaskFile}\n`);
|
|
623
|
+
}
|
|
624
|
+
await runDeclarativeFlowBySpecFile("bug-analyze.json", config, {
|
|
625
|
+
jiraApiUrl: config.jiraApiUrl,
|
|
626
|
+
taskKey: config.taskKey,
|
|
627
|
+
extraPrompt: config.extraPrompt,
|
|
628
|
+
});
|
|
629
|
+
return false;
|
|
630
|
+
}
|
|
631
|
+
if (config.command === "bug-fix") {
|
|
632
|
+
requireJiraTaskFile(config.jiraTaskFile);
|
|
633
|
+
requireArtifacts(bugAnalyzeArtifacts(config.taskKey), "Bug-fix mode requires bug-analyze artifacts from the bug analysis phase.");
|
|
634
|
+
validateStructuredArtifacts([
|
|
635
|
+
{ path: bugAnalyzeJsonFile(config.taskKey), schemaId: "bug-analysis/v1" },
|
|
636
|
+
{ path: bugFixDesignJsonFile(config.taskKey), schemaId: "bug-fix-design/v1" },
|
|
637
|
+
{ path: bugFixPlanJsonFile(config.taskKey), schemaId: "bug-fix-plan/v1" },
|
|
638
|
+
], "Bug-fix mode requires valid structured artifacts from the bug analysis phase.");
|
|
639
|
+
await runDeclarativeFlowBySpecFile("bug-fix.json", config, {
|
|
640
|
+
taskKey: config.taskKey,
|
|
641
|
+
extraPrompt: config.extraPrompt,
|
|
642
|
+
});
|
|
643
|
+
return false;
|
|
644
|
+
}
|
|
645
|
+
if (config.command === "mr-description") {
|
|
646
|
+
requireJiraTaskFile(config.jiraTaskFile);
|
|
647
|
+
await runDeclarativeFlowBySpecFile("mr-description.json", config, {
|
|
648
|
+
taskKey: config.taskKey,
|
|
649
|
+
extraPrompt: config.extraPrompt,
|
|
650
|
+
});
|
|
651
|
+
return false;
|
|
652
|
+
}
|
|
653
|
+
if (config.command === "task-describe") {
|
|
654
|
+
requireJiraTaskFile(config.jiraTaskFile);
|
|
655
|
+
await runDeclarativeFlowBySpecFile("task-describe.json", config, {
|
|
656
|
+
taskKey: config.taskKey,
|
|
657
|
+
extraPrompt: config.extraPrompt,
|
|
658
|
+
});
|
|
659
|
+
return false;
|
|
660
|
+
}
|
|
592
661
|
if (config.command === "implement") {
|
|
593
662
|
requireJiraTaskFile(config.jiraTaskFile);
|
|
594
663
|
requireArtifacts(planArtifacts(config.taskKey), "Implement mode requires plan artifacts from the planning phase.");
|
|
@@ -674,6 +743,14 @@ async function executeCommand(config, runFollowupVerify = true) {
|
|
|
674
743
|
});
|
|
675
744
|
return false;
|
|
676
745
|
}
|
|
746
|
+
if (config.command === "run-tests-loop" || config.command === "run-linter-loop") {
|
|
747
|
+
await runDeclarativeFlowBySpecFile(config.command === "run-tests-loop" ? "run-tests-loop.json" : "run-linter-loop.json", config, {
|
|
748
|
+
taskKey: config.taskKey,
|
|
749
|
+
dockerComposeFile: config.dockerComposeFile,
|
|
750
|
+
extraPrompt: config.extraPrompt,
|
|
751
|
+
});
|
|
752
|
+
return false;
|
|
753
|
+
}
|
|
677
754
|
throw new TaskRunnerError(`Unsupported command: ${config.command}`);
|
|
678
755
|
}
|
|
679
756
|
async function runAutoPipelineDryRun(config) {
|