agentweaver 0.1.16 → 0.1.18
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 +148 -27
- package/dist/artifacts.js +114 -3
- package/dist/doctor/checks/executors.js +2 -2
- package/dist/flow-state.js +138 -1
- package/dist/index.js +421 -82
- package/dist/interactive/controller.js +305 -36
- package/dist/interactive/ink/index.js +24 -3
- package/dist/interactive/state.js +1 -0
- package/dist/interactive/tree.js +2 -2
- package/dist/interactive/web/index.js +179 -0
- package/dist/interactive/web/protocol.js +154 -0
- package/dist/interactive/web/server.js +575 -0
- package/dist/interactive/web/static/app.js +709 -0
- package/dist/interactive/web/static/index.html +77 -0
- package/dist/interactive/web/static/styles.css +2 -0
- package/dist/interactive/web/static/styles.input.css +469 -0
- package/dist/pipeline/auto-flow.js +9 -6
- package/dist/pipeline/context.js +6 -5
- package/dist/pipeline/declarative-flows.js +39 -20
- package/dist/pipeline/flow-catalog.js +40 -14
- package/dist/pipeline/flow-specs/auto-common-guided.json +313 -0
- package/dist/pipeline/flow-specs/auto-common.json +4 -1
- package/dist/pipeline/flow-specs/auto-golang.json +27 -1
- package/dist/pipeline/flow-specs/design-review/design-review-loop.json +15 -1
- package/dist/pipeline/flow-specs/design-review.json +2 -0
- package/dist/pipeline/flow-specs/implement.json +3 -1
- package/dist/pipeline/flow-specs/plan.json +8 -2
- package/dist/pipeline/flow-specs/playbook-init.json +199 -0
- package/dist/pipeline/flow-specs/review/review-fix.json +3 -1
- package/dist/pipeline/flow-specs/review/review-loop.json +4 -0
- package/dist/pipeline/flow-specs/review/review.json +2 -0
- package/dist/pipeline/launch-profile-config.js +30 -18
- package/dist/pipeline/node-contract.js +1 -0
- package/dist/pipeline/node-registry.js +119 -5
- package/dist/pipeline/nodes/flow-run-node.js +200 -173
- package/dist/pipeline/nodes/llm-prompt-node.js +15 -33
- package/dist/pipeline/nodes/playbook-ensure-node.js +115 -0
- package/dist/pipeline/nodes/playbook-inventory-node.js +51 -0
- package/dist/pipeline/nodes/playbook-questions-form-node.js +166 -0
- package/dist/pipeline/nodes/playbook-write-node.js +243 -0
- package/dist/pipeline/nodes/project-guidance-node.js +69 -0
- package/dist/pipeline/plugin-loader.js +389 -0
- package/dist/pipeline/plugin-types.js +1 -0
- package/dist/pipeline/prompt-registry.js +4 -1
- package/dist/pipeline/prompt-runtime.js +6 -2
- package/dist/pipeline/registry.js +71 -4
- package/dist/pipeline/spec-compiler.js +1 -0
- package/dist/pipeline/spec-loader.js +14 -0
- package/dist/pipeline/spec-types.js +19 -0
- package/dist/pipeline/spec-validator.js +6 -0
- package/dist/pipeline/value-resolver.js +41 -2
- package/dist/playbook/practice-candidates.js +12 -0
- package/dist/playbook/repo-inventory.js +208 -0
- package/dist/plugin-sdk.js +1 -0
- package/dist/prompts.js +31 -0
- package/dist/runtime/artifact-registry.js +3 -0
- package/dist/runtime/execution-routing.js +25 -19
- package/dist/runtime/interactive-execution-routing.js +66 -57
- package/dist/runtime/playbook.js +485 -0
- package/dist/runtime/project-guidance.js +339 -0
- package/dist/structured-artifact-schema-registry.js +8 -0
- package/dist/structured-artifact-schemas.json +235 -0
- package/dist/structured-artifacts.js +7 -1
- package/docs/declarative-workflows.md +565 -0
- package/docs/example/.flows/examples/claude-example.json +50 -0
- package/docs/example/.plugins/claude-example-plugin/index.js +149 -0
- package/docs/example/.plugins/claude-example-plugin/plugin.json +8 -0
- package/docs/examples/.flows/claude-example.json +50 -0
- package/docs/examples/.plugins/claude-example-plugin/index.js +149 -0
- package/docs/examples/.plugins/claude-example-plugin/plugin.json +8 -0
- package/docs/features.md +77 -0
- package/docs/playbook.md +327 -0
- package/docs/plugin-sdk.md +731 -0
- package/package.json +13 -4
|
@@ -1,27 +1,31 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
|
-
import {
|
|
3
|
-
import { createExecutorRegistry } from "./registry.js";
|
|
2
|
+
import { createPipelineRegistryContext } from "./plugin-loader.js";
|
|
4
3
|
import { compileFlowSpec } from "./spec-compiler.js";
|
|
5
|
-
import { listBuiltInFlowSpecFiles, listProjectFlowSpecFiles, loadFlowSpecSync, projectFlowSpecsDir, resolveBuiltInFlowSpecPath } from "./spec-loader.js";
|
|
4
|
+
import { globalFlowSpecsDir, listBuiltInFlowSpecFiles, listGlobalFlowSpecFiles, listProjectFlowSpecFiles, loadFlowSpecSync, projectFlowSpecsDir, resolveBuiltInFlowSpecPath, } from "./spec-loader.js";
|
|
6
5
|
import { validateExpandedPhases, validateFlowSpec } from "./spec-validator.js";
|
|
7
6
|
const cache = new Map();
|
|
8
7
|
function toFlowSpecSource(ref) {
|
|
9
|
-
return ref.source === "built-in"
|
|
8
|
+
return ref.source === "built-in"
|
|
9
|
+
? { source: "built-in", fileName: ref.fileName }
|
|
10
|
+
: { source: ref.source, filePath: ref.filePath };
|
|
10
11
|
}
|
|
11
|
-
function cacheKey(ref) {
|
|
12
|
-
|
|
12
|
+
function cacheKey(ref, registryContext) {
|
|
13
|
+
const flowKey = ref.source === "built-in"
|
|
14
|
+
? `built-in:${ref.fileName}`
|
|
15
|
+
: `${ref.source}:${path.resolve(ref.filePath)}`;
|
|
16
|
+
return `${registryContext.cacheKey}:${flowKey}`;
|
|
13
17
|
}
|
|
14
|
-
export function loadDeclarativeFlow(flow) {
|
|
18
|
+
export async function loadDeclarativeFlow(flow, options = {}) {
|
|
15
19
|
const ref = typeof flow === "string" ? { source: "built-in", fileName: flow } : flow;
|
|
16
|
-
const
|
|
20
|
+
const cwd = path.resolve(options.cwd ?? options.registryContext?.cwd ?? process.cwd());
|
|
21
|
+
const registryContext = options.registryContext ?? await createPipelineRegistryContext(cwd);
|
|
22
|
+
const cached = cache.get(cacheKey(ref, registryContext));
|
|
17
23
|
if (cached) {
|
|
18
24
|
return cached;
|
|
19
25
|
}
|
|
20
26
|
const spec = loadFlowSpecSync(toFlowSpecSource(ref));
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
validateFlowSpec(spec, nodeRegistry, executorRegistry, {
|
|
24
|
-
resolveFlowByName: (fileName) => resolveNamedDeclarativeFlowRef(fileName, process.cwd()),
|
|
27
|
+
validateFlowSpec(spec, registryContext.nodes, registryContext.executors, {
|
|
28
|
+
resolveFlowByName: (fileName) => resolveNamedDeclarativeFlowRef(fileName, cwd),
|
|
25
29
|
});
|
|
26
30
|
const phases = compileFlowSpec(spec);
|
|
27
31
|
validateExpandedPhases(phases);
|
|
@@ -36,33 +40,48 @@ export function loadDeclarativeFlow(flow) {
|
|
|
36
40
|
fileName: ref.source === "built-in" ? ref.fileName : path.basename(ref.filePath),
|
|
37
41
|
absolutePath: ref.source === "built-in" ? resolveBuiltInFlowSpecPath(ref.fileName) : path.resolve(ref.filePath),
|
|
38
42
|
};
|
|
39
|
-
cache.set(cacheKey(ref), loaded);
|
|
43
|
+
cache.set(cacheKey(ref, registryContext), loaded);
|
|
40
44
|
return loaded;
|
|
41
45
|
}
|
|
42
46
|
export function resolveNamedDeclarativeFlowRef(fileName, cwd) {
|
|
43
47
|
const projectMatches = listProjectFlowSpecFiles(cwd).filter((candidate) => path.basename(candidate) === fileName);
|
|
48
|
+
const globalMatches = listGlobalFlowSpecFiles().filter((candidate) => path.basename(candidate) === fileName);
|
|
44
49
|
const builtInMatches = listBuiltInFlowSpecFiles().filter((candidate) => path.basename(candidate) === fileName);
|
|
45
|
-
|
|
46
|
-
|
|
50
|
+
const matches = [
|
|
51
|
+
...builtInMatches.map((candidate) => ({ source: "built-in", candidate })),
|
|
52
|
+
...globalMatches.map((candidate) => ({ source: "global", candidate })),
|
|
53
|
+
...projectMatches.map((candidate) => ({ source: "project-local", candidate })),
|
|
54
|
+
];
|
|
55
|
+
if (matches.length > 1) {
|
|
56
|
+
throw new Error(`Ambiguous nested flow '${fileName}': matches exist in built-in flows, ${globalFlowSpecsDir()}, or ${projectFlowSpecsDir(cwd)}. Use unique nested flow file names.`);
|
|
47
57
|
}
|
|
48
58
|
if (projectMatches.length > 1) {
|
|
49
59
|
throw new Error(`Ambiguous project-local flow '${fileName}' in ${projectFlowSpecsDir(cwd)}.`);
|
|
50
60
|
}
|
|
61
|
+
if (globalMatches.length > 1) {
|
|
62
|
+
throw new Error(`Ambiguous global flow '${fileName}' in ${globalFlowSpecsDir()}.`);
|
|
63
|
+
}
|
|
51
64
|
if (builtInMatches.length > 1) {
|
|
52
65
|
throw new Error(`Ambiguous built-in flow '${fileName}'. Use unique nested flow file names.`);
|
|
53
66
|
}
|
|
54
67
|
if (projectMatches[0]) {
|
|
55
68
|
return { source: "project-local", filePath: projectMatches[0] };
|
|
56
69
|
}
|
|
70
|
+
if (globalMatches[0]) {
|
|
71
|
+
return { source: "global", filePath: globalMatches[0] };
|
|
72
|
+
}
|
|
57
73
|
if (builtInMatches[0]) {
|
|
58
74
|
return { source: "built-in", fileName: builtInMatches[0] };
|
|
59
75
|
}
|
|
60
76
|
throw new Error(`Nested flow '${fileName}' was not found.`);
|
|
61
77
|
}
|
|
62
|
-
export function loadNamedDeclarativeFlow(fileName, cwd) {
|
|
63
|
-
return loadDeclarativeFlow(resolveNamedDeclarativeFlowRef(fileName, cwd)
|
|
78
|
+
export async function loadNamedDeclarativeFlow(fileName, cwd, options = {}) {
|
|
79
|
+
return loadDeclarativeFlow(resolveNamedDeclarativeFlowRef(fileName, cwd), {
|
|
80
|
+
cwd,
|
|
81
|
+
...(options.registryContext ? { registryContext: options.registryContext } : {}),
|
|
82
|
+
});
|
|
64
83
|
}
|
|
65
|
-
export function collectFlowRoutingGroups(flow, cwd, visited = new Set()) {
|
|
84
|
+
export async function collectFlowRoutingGroups(flow, cwd, visited = new Set(), options = {}) {
|
|
66
85
|
if (visited.has(flow.absolutePath)) {
|
|
67
86
|
return [];
|
|
68
87
|
}
|
|
@@ -80,8 +99,8 @@ export function collectFlowRoutingGroups(flow, cwd, visited = new Set()) {
|
|
|
80
99
|
if (!nestedFlowName || !("const" in nestedFlowName) || typeof nestedFlowName.const !== "string") {
|
|
81
100
|
continue;
|
|
82
101
|
}
|
|
83
|
-
const nestedFlow = loadNamedDeclarativeFlow(nestedFlowName.const, cwd);
|
|
84
|
-
for (const nestedGroup of collectFlowRoutingGroups(nestedFlow, cwd, visited)) {
|
|
102
|
+
const nestedFlow = await loadNamedDeclarativeFlow(nestedFlowName.const, cwd, options);
|
|
103
|
+
for (const nestedGroup of await collectFlowRoutingGroups(nestedFlow, cwd, visited, options)) {
|
|
85
104
|
groups.add(nestedGroup);
|
|
86
105
|
}
|
|
87
106
|
}
|
|
@@ -2,9 +2,10 @@ import path from "node:path";
|
|
|
2
2
|
import { TaskRunnerError } from "../errors.js";
|
|
3
3
|
import { loadAutoGolangFlow } from "./auto-flow.js";
|
|
4
4
|
import { collectFlowRoutingGroups, loadDeclarativeFlow } from "./declarative-flows.js";
|
|
5
|
-
import { listBuiltInFlowSpecFiles, listProjectFlowSpecFiles, projectFlowSpecsDir } from "./spec-loader.js";
|
|
5
|
+
import { globalFlowSpecsDir, listBuiltInFlowSpecFiles, listGlobalFlowSpecFiles, listProjectFlowSpecFiles, projectFlowSpecsDir } from "./spec-loader.js";
|
|
6
6
|
export const BUILT_IN_COMMAND_FLOW_IDS = [
|
|
7
7
|
"auto-golang",
|
|
8
|
+
"auto-common-guided",
|
|
8
9
|
"auto-common",
|
|
9
10
|
"auto-simple",
|
|
10
11
|
"bug-analyze",
|
|
@@ -17,6 +18,7 @@ export const BUILT_IN_COMMAND_FLOW_IDS = [
|
|
|
17
18
|
"mr-description",
|
|
18
19
|
"plan",
|
|
19
20
|
"plan-revise",
|
|
21
|
+
"playbook-init",
|
|
20
22
|
"task-describe",
|
|
21
23
|
"implement",
|
|
22
24
|
"review",
|
|
@@ -27,6 +29,7 @@ export const BUILT_IN_COMMAND_FLOW_IDS = [
|
|
|
27
29
|
];
|
|
28
30
|
const BUILT_IN_COMMAND_FLOW_FILES = {
|
|
29
31
|
"auto-golang": "auto-golang.json",
|
|
32
|
+
"auto-common-guided": "auto-common-guided.json",
|
|
30
33
|
"auto-common": "auto-common.json",
|
|
31
34
|
"auto-simple": "auto-simple.json",
|
|
32
35
|
"bug-analyze": "bugz/bug-analyze.json",
|
|
@@ -39,6 +42,7 @@ const BUILT_IN_COMMAND_FLOW_FILES = {
|
|
|
39
42
|
"mr-description": "gitlab/mr-description.json",
|
|
40
43
|
plan: "plan.json",
|
|
41
44
|
"plan-revise": "plan-revise.json",
|
|
45
|
+
"playbook-init": "playbook-init.json",
|
|
42
46
|
"task-describe": "task-describe.json",
|
|
43
47
|
implement: "implement.json",
|
|
44
48
|
review: "review/review.json",
|
|
@@ -58,11 +62,13 @@ function builtInCommandIdForFile(fileName) {
|
|
|
58
62
|
}
|
|
59
63
|
return null;
|
|
60
64
|
}
|
|
61
|
-
function loadBuiltInCatalogEntry(fileName) {
|
|
65
|
+
async function loadBuiltInCatalogEntry(fileName, options) {
|
|
62
66
|
const commandId = builtInCommandIdForFile(fileName);
|
|
63
67
|
const relativePath = fileName.replace(/\.json$/i, "").split(/[\\/]+/).filter((segment) => segment.length > 0);
|
|
64
68
|
const id = commandId ?? relativePath.join("/");
|
|
65
|
-
const flow = id === "auto-golang"
|
|
69
|
+
const flow = id === "auto-golang"
|
|
70
|
+
? await loadAutoGolangFlow(options)
|
|
71
|
+
: await loadDeclarativeFlow({ source: "built-in", fileName }, options);
|
|
66
72
|
return {
|
|
67
73
|
id,
|
|
68
74
|
source: "built-in",
|
|
@@ -72,8 +78,8 @@ function loadBuiltInCatalogEntry(fileName) {
|
|
|
72
78
|
flow,
|
|
73
79
|
};
|
|
74
80
|
}
|
|
75
|
-
function loadProjectCatalogEntry(cwd, filePath) {
|
|
76
|
-
const flow = loadDeclarativeFlow({ source: "project-local", filePath });
|
|
81
|
+
async function loadProjectCatalogEntry(cwd, filePath, options) {
|
|
82
|
+
const flow = await loadDeclarativeFlow({ source: "project-local", filePath }, { ...options, cwd });
|
|
77
83
|
const relativeFilePath = path.relative(projectFlowSpecsDir(cwd), path.resolve(filePath));
|
|
78
84
|
const relativePathWithoutExt = relativeFilePath.replace(/\.json$/i, "");
|
|
79
85
|
const relativeSegments = relativePathWithoutExt.split(path.sep).filter((segment) => segment.length > 0);
|
|
@@ -86,10 +92,30 @@ function loadProjectCatalogEntry(cwd, filePath) {
|
|
|
86
92
|
flow,
|
|
87
93
|
};
|
|
88
94
|
}
|
|
89
|
-
|
|
90
|
-
const
|
|
95
|
+
async function loadGlobalCatalogEntry(filePath, options) {
|
|
96
|
+
const flow = await loadDeclarativeFlow({ source: "global", filePath }, options);
|
|
97
|
+
const relativeFilePath = path.relative(globalFlowSpecsDir(), path.resolve(filePath));
|
|
98
|
+
const relativePathWithoutExt = relativeFilePath.replace(/\.json$/i, "");
|
|
99
|
+
const relativeSegments = relativePathWithoutExt.split(path.sep).filter((segment) => segment.length > 0);
|
|
100
|
+
return {
|
|
101
|
+
id: relativeSegments.join("/"),
|
|
102
|
+
source: "global",
|
|
103
|
+
fileName: path.basename(filePath),
|
|
104
|
+
absolutePath: path.resolve(filePath),
|
|
105
|
+
treePath: ["global", ...relativeSegments],
|
|
106
|
+
flow,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
export async function loadInteractiveFlowCatalog(cwd, options = {}) {
|
|
110
|
+
const entries = [];
|
|
111
|
+
for (const fileName of listBuiltInFlowSpecFiles()) {
|
|
112
|
+
entries.push(await loadBuiltInCatalogEntry(fileName, { ...options, cwd }));
|
|
113
|
+
}
|
|
114
|
+
for (const filePath of listGlobalFlowSpecFiles()) {
|
|
115
|
+
entries.push(await loadGlobalCatalogEntry(filePath, { ...options, cwd }));
|
|
116
|
+
}
|
|
91
117
|
for (const filePath of listProjectFlowSpecFiles(cwd)) {
|
|
92
|
-
entries.push(loadProjectCatalogEntry(cwd, filePath));
|
|
118
|
+
entries.push(await loadProjectCatalogEntry(cwd, filePath, { ...options, cwd }));
|
|
93
119
|
}
|
|
94
120
|
const visibleEntries = entries.filter((entry) => entry.flow.catalogVisibility !== "hidden");
|
|
95
121
|
const byId = new Map();
|
|
@@ -111,13 +137,13 @@ export function isBuiltInCommandFlowId(flowId) {
|
|
|
111
137
|
export function toDeclarativeFlowRef(entry) {
|
|
112
138
|
return entry.source === "built-in"
|
|
113
139
|
? { source: "built-in", fileName: entry.fileName }
|
|
114
|
-
: { source:
|
|
140
|
+
: { source: entry.source, filePath: entry.absolutePath };
|
|
115
141
|
}
|
|
116
142
|
export function flowRoutingKey(entry) {
|
|
117
|
-
return entry.source === "
|
|
118
|
-
? `
|
|
119
|
-
:
|
|
143
|
+
return entry.source === "built-in"
|
|
144
|
+
? `built-in:${entry.id}`
|
|
145
|
+
: `${entry.source}:${entry.absolutePath}`;
|
|
120
146
|
}
|
|
121
|
-
export function flowRoutingGroups(entry, cwd) {
|
|
122
|
-
return collectFlowRoutingGroups(entry.flow, cwd);
|
|
147
|
+
export async function flowRoutingGroups(entry, cwd, options = {}) {
|
|
148
|
+
return collectFlowRoutingGroups(entry.flow, cwd, new Set(), options);
|
|
123
149
|
}
|
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
{
|
|
2
|
+
"kind": "auto-common-guided-flow",
|
|
3
|
+
"version": 1,
|
|
4
|
+
"description": "End-to-end auto-common pipeline with compact manifest.yaml project guidance generated before guided LLM phases.",
|
|
5
|
+
"phases": [
|
|
6
|
+
{
|
|
7
|
+
"id": "source",
|
|
8
|
+
"steps": [
|
|
9
|
+
{
|
|
10
|
+
"id": "fetch_jira_source",
|
|
11
|
+
"node": "flow-run",
|
|
12
|
+
"params": {
|
|
13
|
+
"fileName": { "const": "jira-fetch.json" },
|
|
14
|
+
"labelText": { "const": "Fetching Jira task source" },
|
|
15
|
+
"jiraApiUrl": { "ref": "params.jiraApiUrl" },
|
|
16
|
+
"taskKey": { "ref": "params.taskKey" }
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
]
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"id": "normalize",
|
|
23
|
+
"steps": [
|
|
24
|
+
{
|
|
25
|
+
"id": "run_normalize_source",
|
|
26
|
+
"node": "flow-run",
|
|
27
|
+
"params": {
|
|
28
|
+
"fileName": { "const": "normalize-task-source.json" },
|
|
29
|
+
"labelText": { "const": "Normalizing task source" },
|
|
30
|
+
"taskKey": { "ref": "params.taskKey" },
|
|
31
|
+
"iteration": { "ref": "params.taskContextIteration" },
|
|
32
|
+
"llmExecutor": { "ref": "params.llmExecutor" },
|
|
33
|
+
"llmModel": { "ref": "params.llmModel" },
|
|
34
|
+
"extraPrompt": { "ref": "params.extraPrompt" }
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
]
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"id": "playbook",
|
|
41
|
+
"steps": [
|
|
42
|
+
{
|
|
43
|
+
"id": "ensure_playbook",
|
|
44
|
+
"node": "playbook-ensure",
|
|
45
|
+
"params": {
|
|
46
|
+
"writeResultJsonFile": { "artifact": { "kind": "playbook-write-result-json-file", "taskKey": { "ref": "params.taskKey" } } },
|
|
47
|
+
"acceptPlaybookDraft": { "ref": "params.acceptPlaybookDraft" }
|
|
48
|
+
},
|
|
49
|
+
"stopFlowIf": {
|
|
50
|
+
"any": [
|
|
51
|
+
{ "equals": [{ "ref": "steps.playbook.ensure_playbook.value.status" }, { "const": "blocked" }] },
|
|
52
|
+
{ "equals": [{ "ref": "steps.playbook.ensure_playbook.value.status" }, { "const": "invalid_manifest" }] },
|
|
53
|
+
{ "equals": [{ "ref": "steps.playbook.ensure_playbook.value.status" }, { "const": "partial_manifest" }] },
|
|
54
|
+
{ "equals": [{ "ref": "steps.playbook.ensure_playbook.value.status" }, { "const": "not_accepted" }] },
|
|
55
|
+
{ "equals": [{ "ref": "steps.playbook.ensure_playbook.value.status" }, { "const": "failed" }] }
|
|
56
|
+
]
|
|
57
|
+
},
|
|
58
|
+
"stopFlowOutcome": "stopped"
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
"id": "run_playbook_init",
|
|
62
|
+
"node": "flow-run",
|
|
63
|
+
"when": { "ref": "steps.playbook.ensure_playbook.value.shouldRunPlaybookInit" },
|
|
64
|
+
"params": {
|
|
65
|
+
"fileName": { "const": "playbook-init.json" },
|
|
66
|
+
"labelText": { "const": "Initializing manifest-based project playbook" },
|
|
67
|
+
"taskKey": { "ref": "params.taskKey" },
|
|
68
|
+
"taskContextJsonFile": { "artifact": { "kind": "task-context-json-file", "taskKey": { "ref": "params.taskKey" }, "iteration": { "ref": "params.taskContextIteration" } } },
|
|
69
|
+
"markdownLanguage": { "ref": "params.mdLang" },
|
|
70
|
+
"iteration": { "ref": "params.planIteration" },
|
|
71
|
+
"launchMode": { "ref": "params.launchMode" },
|
|
72
|
+
"targetManifestPath": { "ref": "steps.playbook.ensure_playbook.value.manifestPath" },
|
|
73
|
+
"acceptPlaybookDraft": { "ref": "params.acceptPlaybookDraft" },
|
|
74
|
+
"llmExecutor": { "ref": "params.llmExecutor" },
|
|
75
|
+
"llmModel": { "ref": "params.llmModel" },
|
|
76
|
+
"extraPrompt": { "ref": "params.extraPrompt" }
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
"id": "verify_playbook",
|
|
81
|
+
"node": "playbook-ensure",
|
|
82
|
+
"when": { "ref": "steps.playbook.ensure_playbook.value.shouldRunPlaybookInit" },
|
|
83
|
+
"params": {
|
|
84
|
+
"writeResultJsonFile": { "artifact": { "kind": "playbook-write-result-json-file", "taskKey": { "ref": "params.taskKey" } } },
|
|
85
|
+
"acceptPlaybookDraft": { "ref": "params.acceptPlaybookDraft" },
|
|
86
|
+
"verifyAfterInit": { "const": true }
|
|
87
|
+
},
|
|
88
|
+
"stopFlowIf": {
|
|
89
|
+
"not": {
|
|
90
|
+
"any": [
|
|
91
|
+
{ "equals": [{ "ref": "steps.playbook.verify_playbook.value.status" }, { "const": "written" }] },
|
|
92
|
+
{ "equals": [{ "ref": "steps.playbook.verify_playbook.value.status" }, { "const": "skipped_valid_existing" }] },
|
|
93
|
+
{ "equals": [{ "ref": "steps.playbook.verify_playbook.value.status" }, { "const": "dry_run_written" }] }
|
|
94
|
+
]
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
"stopFlowOutcome": "stopped"
|
|
98
|
+
}
|
|
99
|
+
]
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
"id": "plan_guidance",
|
|
103
|
+
"steps": [
|
|
104
|
+
{
|
|
105
|
+
"id": "write_plan_guidance",
|
|
106
|
+
"node": "project-guidance",
|
|
107
|
+
"params": {
|
|
108
|
+
"taskContextJsonFile": { "artifact": { "kind": "task-context-json-file", "taskKey": { "ref": "params.taskKey" }, "iteration": { "ref": "params.taskContextIteration" } } },
|
|
109
|
+
"phase": { "const": "plan" },
|
|
110
|
+
"outputJsonFile": { "artifact": { "kind": "project-guidance-plan-json-file", "taskKey": { "ref": "params.taskKey" }, "iteration": { "ref": "params.planIteration" } } },
|
|
111
|
+
"outputFile": { "artifact": { "kind": "project-guidance-plan-file", "taskKey": { "ref": "params.taskKey" }, "iteration": { "ref": "params.planIteration" } } },
|
|
112
|
+
"markdownLanguage": { "ref": "params.mdLang" }
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
]
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
"id": "plan",
|
|
119
|
+
"steps": [
|
|
120
|
+
{
|
|
121
|
+
"id": "run_plan_flow",
|
|
122
|
+
"node": "flow-run",
|
|
123
|
+
"params": {
|
|
124
|
+
"fileName": { "const": "plan.json" },
|
|
125
|
+
"labelText": { "const": "Running planning flow" },
|
|
126
|
+
"taskKey": { "ref": "params.taskKey" },
|
|
127
|
+
"taskContextIteration": { "ref": "params.taskContextIteration" },
|
|
128
|
+
"designIteration": { "ref": "params.designIteration" },
|
|
129
|
+
"planIteration": { "ref": "params.planIteration" },
|
|
130
|
+
"qaIteration": { "ref": "params.qaIteration" },
|
|
131
|
+
"projectGuidanceFile": { "ref": "steps.plan_guidance.write_plan_guidance.value.outputFile" },
|
|
132
|
+
"projectGuidanceJsonFile": { "ref": "steps.plan_guidance.write_plan_guidance.value.outputJsonFile" },
|
|
133
|
+
"llmExecutor": { "ref": "params.llmExecutor" },
|
|
134
|
+
"llmModel": { "ref": "params.llmModel" },
|
|
135
|
+
"extraPrompt": { "ref": "params.extraPrompt" },
|
|
136
|
+
"mdLang": { "ref": "params.mdLang" }
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
]
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
"id": "design_review_guidance",
|
|
143
|
+
"steps": [
|
|
144
|
+
{
|
|
145
|
+
"id": "write_design_review_guidance",
|
|
146
|
+
"node": "project-guidance",
|
|
147
|
+
"params": {
|
|
148
|
+
"taskContextJsonFile": { "artifact": { "kind": "task-context-json-file", "taskKey": { "ref": "params.taskKey" }, "iteration": { "ref": "params.taskContextIteration" } } },
|
|
149
|
+
"phase": { "const": "design-review" },
|
|
150
|
+
"outputJsonFile": { "artifact": { "kind": "project-guidance-design-review-json-file", "taskKey": { "ref": "params.taskKey" }, "iteration": { "ref": "params.planIteration" } } },
|
|
151
|
+
"outputFile": { "artifact": { "kind": "project-guidance-design-review-file", "taskKey": { "ref": "params.taskKey" }, "iteration": { "ref": "params.planIteration" } } },
|
|
152
|
+
"markdownLanguage": { "ref": "params.mdLang" }
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
]
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
"id": "design_review_loop",
|
|
159
|
+
"steps": [
|
|
160
|
+
{
|
|
161
|
+
"id": "run_design_review_loop",
|
|
162
|
+
"node": "flow-run",
|
|
163
|
+
"params": {
|
|
164
|
+
"fileName": { "const": "design-review-loop.json" },
|
|
165
|
+
"labelText": { "const": "Running design-review loop" },
|
|
166
|
+
"taskKey": { "ref": "params.taskKey" },
|
|
167
|
+
"baseIteration": { "ref": "params.designReviewBaseIteration" },
|
|
168
|
+
"workspaceDir": { "ref": "params.workspaceDir" },
|
|
169
|
+
"extraPrompt": { "ref": "params.extraPrompt" },
|
|
170
|
+
"projectGuidanceFile": { "ref": "steps.design_review_guidance.write_design_review_guidance.value.outputFile" },
|
|
171
|
+
"projectGuidanceJsonFile": { "ref": "steps.design_review_guidance.write_design_review_guidance.value.outputJsonFile" },
|
|
172
|
+
"llmExecutor": { "ref": "params.llmExecutor" },
|
|
173
|
+
"llmModel": { "ref": "params.llmModel" }
|
|
174
|
+
},
|
|
175
|
+
"stopFlowIf": {
|
|
176
|
+
"equals": [
|
|
177
|
+
{ "ref": "steps.design_review_loop.run_design_review_loop.value.executionState.terminationOutcome" },
|
|
178
|
+
{ "const": "stopped" }
|
|
179
|
+
]
|
|
180
|
+
},
|
|
181
|
+
"stopFlowOutcome": "stopped"
|
|
182
|
+
}
|
|
183
|
+
]
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
"id": "implement_guidance",
|
|
187
|
+
"steps": [
|
|
188
|
+
{
|
|
189
|
+
"id": "write_implement_guidance",
|
|
190
|
+
"node": "project-guidance",
|
|
191
|
+
"params": {
|
|
192
|
+
"taskContextJsonFile": { "artifact": { "kind": "task-context-json-file", "taskKey": { "ref": "params.taskKey" }, "iteration": { "ref": "params.taskContextIteration" } } },
|
|
193
|
+
"phase": { "const": "implement" },
|
|
194
|
+
"outputJsonFile": { "artifact": { "kind": "project-guidance-implement-json-file", "taskKey": { "ref": "params.taskKey" }, "iteration": { "ref": "params.planIteration" } } },
|
|
195
|
+
"outputFile": { "artifact": { "kind": "project-guidance-implement-file", "taskKey": { "ref": "params.taskKey" }, "iteration": { "ref": "params.planIteration" } } },
|
|
196
|
+
"markdownLanguage": { "ref": "params.mdLang" }
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
]
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
"id": "implement",
|
|
203
|
+
"steps": [
|
|
204
|
+
{
|
|
205
|
+
"id": "resolve_planning_bundle",
|
|
206
|
+
"node": "planning-bundle",
|
|
207
|
+
"params": { "taskKey": { "ref": "params.taskKey" } }
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
"id": "run_implement",
|
|
211
|
+
"node": "llm-prompt",
|
|
212
|
+
"routingGroup": "implementation",
|
|
213
|
+
"prompt": {
|
|
214
|
+
"templateRef": "implement",
|
|
215
|
+
"vars": {
|
|
216
|
+
"design_file": { "ref": "steps.implement.resolve_planning_bundle.value.designFile" },
|
|
217
|
+
"design_json_file": { "ref": "steps.implement.resolve_planning_bundle.value.designJsonFile" },
|
|
218
|
+
"plan_file": { "ref": "steps.implement.resolve_planning_bundle.value.planFile" },
|
|
219
|
+
"plan_json_file": { "ref": "steps.implement.resolve_planning_bundle.value.planJsonFile" },
|
|
220
|
+
"qa_file": { "ref": "steps.implement.resolve_planning_bundle.value.qaFile" },
|
|
221
|
+
"qa_json_file": { "ref": "steps.implement.resolve_planning_bundle.value.qaJsonFile" },
|
|
222
|
+
"project_guidance_file": { "ref": "steps.implement_guidance.write_implement_guidance.value.outputFile" },
|
|
223
|
+
"project_guidance_json_file": { "ref": "steps.implement_guidance.write_implement_guidance.value.outputJsonFile" }
|
|
224
|
+
},
|
|
225
|
+
"extraPrompt": { "ref": "params.extraPrompt" },
|
|
226
|
+
"format": "task-prompt"
|
|
227
|
+
},
|
|
228
|
+
"params": {
|
|
229
|
+
"labelText": { "const": "Running implementation mode locally" },
|
|
230
|
+
"model": { "ref": "params.llmModel" },
|
|
231
|
+
"executor": { "ref": "params.llmExecutor" }
|
|
232
|
+
}
|
|
233
|
+
},
|
|
234
|
+
{
|
|
235
|
+
"id": "notify_implement_complete",
|
|
236
|
+
"node": "telegram-notify",
|
|
237
|
+
"params": { "message": { "template": "Implementation phase for {taskKey} complete.", "vars": { "taskKey": { "ref": "params.taskKey" } } } }
|
|
238
|
+
}
|
|
239
|
+
]
|
|
240
|
+
},
|
|
241
|
+
{
|
|
242
|
+
"id": "review_guidance",
|
|
243
|
+
"steps": [
|
|
244
|
+
{
|
|
245
|
+
"id": "write_review_guidance",
|
|
246
|
+
"node": "project-guidance",
|
|
247
|
+
"params": {
|
|
248
|
+
"taskContextJsonFile": { "artifact": { "kind": "task-context-json-file", "taskKey": { "ref": "params.taskKey" }, "iteration": { "ref": "params.taskContextIteration" } } },
|
|
249
|
+
"phase": { "const": "review" },
|
|
250
|
+
"outputJsonFile": { "artifact": { "kind": "project-guidance-review-json-file", "taskKey": { "ref": "params.taskKey" }, "iteration": { "ref": "params.planIteration" } } },
|
|
251
|
+
"outputFile": { "artifact": { "kind": "project-guidance-review-file", "taskKey": { "ref": "params.taskKey" }, "iteration": { "ref": "params.planIteration" } } },
|
|
252
|
+
"markdownLanguage": { "ref": "params.mdLang" }
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
]
|
|
256
|
+
},
|
|
257
|
+
{
|
|
258
|
+
"id": "repair_guidance",
|
|
259
|
+
"steps": [
|
|
260
|
+
{
|
|
261
|
+
"id": "write_repair_guidance",
|
|
262
|
+
"node": "project-guidance",
|
|
263
|
+
"params": {
|
|
264
|
+
"taskContextJsonFile": { "artifact": { "kind": "task-context-json-file", "taskKey": { "ref": "params.taskKey" }, "iteration": { "ref": "params.taskContextIteration" } } },
|
|
265
|
+
"phase": { "const": "repair/review-fix" },
|
|
266
|
+
"outputJsonFile": { "artifact": { "kind": "project-guidance-repair-review-fix-json-file", "taskKey": { "ref": "params.taskKey" }, "iteration": { "ref": "params.planIteration" } } },
|
|
267
|
+
"outputFile": { "artifact": { "kind": "project-guidance-repair-review-fix-file", "taskKey": { "ref": "params.taskKey" }, "iteration": { "ref": "params.planIteration" } } },
|
|
268
|
+
"markdownLanguage": { "ref": "params.mdLang" }
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
]
|
|
272
|
+
},
|
|
273
|
+
{
|
|
274
|
+
"id": "review-loop",
|
|
275
|
+
"steps": [
|
|
276
|
+
{
|
|
277
|
+
"id": "run_review_loop",
|
|
278
|
+
"node": "flow-run",
|
|
279
|
+
"stopFlowIf": {
|
|
280
|
+
"not": {
|
|
281
|
+
"equals": [
|
|
282
|
+
{ "ref": "steps.review-loop.run_review_loop.value.executionState.terminationOutcome" },
|
|
283
|
+
{ "const": "success" }
|
|
284
|
+
]
|
|
285
|
+
}
|
|
286
|
+
},
|
|
287
|
+
"stopFlowOutcome": "stopped",
|
|
288
|
+
"params": {
|
|
289
|
+
"fileName": { "const": "review-loop.json" },
|
|
290
|
+
"labelText": { "const": "Running review-loop" },
|
|
291
|
+
"taskKey": { "ref": "params.taskKey" },
|
|
292
|
+
"baseIteration": { "ref": "params.baseIteration" },
|
|
293
|
+
"workspaceDir": { "ref": "params.workspaceDir" },
|
|
294
|
+
"extraPrompt": { "ref": "params.extraPrompt" },
|
|
295
|
+
"reviewFixPoints": { "ref": "params.reviewFixPoints" },
|
|
296
|
+
"reviewBlockingSeverities": { "ref": "params.reviewBlockingSeverities" },
|
|
297
|
+
"projectGuidanceFile": { "ref": "steps.review_guidance.write_review_guidance.value.outputFile" },
|
|
298
|
+
"projectGuidanceJsonFile": { "ref": "steps.review_guidance.write_review_guidance.value.outputJsonFile" },
|
|
299
|
+
"repairProjectGuidanceFile": { "ref": "steps.repair_guidance.write_repair_guidance.value.outputFile" },
|
|
300
|
+
"repairProjectGuidanceJsonFile": { "ref": "steps.repair_guidance.write_repair_guidance.value.outputJsonFile" },
|
|
301
|
+
"llmExecutor": { "ref": "params.llmExecutor" },
|
|
302
|
+
"llmModel": { "ref": "params.llmModel" }
|
|
303
|
+
}
|
|
304
|
+
},
|
|
305
|
+
{
|
|
306
|
+
"id": "notify_task_complete",
|
|
307
|
+
"node": "telegram-notify",
|
|
308
|
+
"params": { "message": { "template": "Task {taskKey} complete.", "vars": { "taskKey": { "ref": "params.taskKey" } } } }
|
|
309
|
+
}
|
|
310
|
+
]
|
|
311
|
+
}
|
|
312
|
+
]
|
|
313
|
+
}
|
|
@@ -68,6 +68,7 @@
|
|
|
68
68
|
"fileName": { "const": "design-review-loop.json" },
|
|
69
69
|
"labelText": { "const": "Running design-review loop" },
|
|
70
70
|
"taskKey": { "ref": "params.taskKey" },
|
|
71
|
+
"baseIteration": { "ref": "params.designReviewBaseIteration" },
|
|
71
72
|
"workspaceDir": { "ref": "params.workspaceDir" },
|
|
72
73
|
"extraPrompt": { "ref": "params.extraPrompt" },
|
|
73
74
|
"llmExecutor": { "ref": "params.llmExecutor" },
|
|
@@ -105,7 +106,9 @@
|
|
|
105
106
|
"plan_file": { "ref": "steps.implement.resolve_planning_bundle.value.planFile" },
|
|
106
107
|
"plan_json_file": { "ref": "steps.implement.resolve_planning_bundle.value.planJsonFile" },
|
|
107
108
|
"qa_file": { "ref": "steps.implement.resolve_planning_bundle.value.qaFile" },
|
|
108
|
-
"qa_json_file": { "ref": "steps.implement.resolve_planning_bundle.value.qaJsonFile" }
|
|
109
|
+
"qa_json_file": { "ref": "steps.implement.resolve_planning_bundle.value.qaJsonFile" },
|
|
110
|
+
"project_guidance_file": { "const": "not provided" },
|
|
111
|
+
"project_guidance_json_file": { "const": "not provided" }
|
|
109
112
|
},
|
|
110
113
|
"extraPrompt": { "ref": "params.extraPrompt" },
|
|
111
114
|
"format": "task-prompt"
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"kind": "auto-flow",
|
|
3
3
|
"version": 1,
|
|
4
|
-
"description": "End-to-end resumable pipeline for Go projects. Runs the full sequence: Jira fetch → task source normalization → plan → implement → linter loop → test loop → review loop → final linter loop → final test loop. Supports --from to restart from a specific phase and auto-status/auto-reset for state management.",
|
|
4
|
+
"description": "End-to-end resumable pipeline for Go projects. Runs the full sequence: Jira fetch → task source normalization → plan → design-review loop → implement → linter loop → test loop → review loop → final linter loop → final test loop. Supports --from to restart from a specific phase and auto-status/auto-reset for state management.",
|
|
5
5
|
"constants": {
|
|
6
6
|
"autoReviewFixExtraPrompt": "Fix only blockers, criticals, and important findings"
|
|
7
7
|
},
|
|
@@ -61,6 +61,32 @@
|
|
|
61
61
|
}
|
|
62
62
|
]
|
|
63
63
|
},
|
|
64
|
+
{
|
|
65
|
+
"id": "design_review_loop",
|
|
66
|
+
"steps": [
|
|
67
|
+
{
|
|
68
|
+
"id": "run_design_review_loop",
|
|
69
|
+
"node": "flow-run",
|
|
70
|
+
"params": {
|
|
71
|
+
"fileName": { "const": "design-review-loop.json" },
|
|
72
|
+
"labelText": { "const": "Running design-review loop" },
|
|
73
|
+
"taskKey": { "ref": "params.taskKey" },
|
|
74
|
+
"baseIteration": { "ref": "params.designReviewBaseIteration" },
|
|
75
|
+
"workspaceDir": { "ref": "params.workspaceDir" },
|
|
76
|
+
"extraPrompt": { "ref": "params.extraPrompt" },
|
|
77
|
+
"llmExecutor": { "ref": "params.llmExecutor" },
|
|
78
|
+
"llmModel": { "ref": "params.llmModel" }
|
|
79
|
+
},
|
|
80
|
+
"stopFlowIf": {
|
|
81
|
+
"equals": [
|
|
82
|
+
{ "ref": "steps.design_review_loop.run_design_review_loop.value.executionState.terminationOutcome" },
|
|
83
|
+
{ "const": "stopped" }
|
|
84
|
+
]
|
|
85
|
+
},
|
|
86
|
+
"stopFlowOutcome": "stopped"
|
|
87
|
+
}
|
|
88
|
+
]
|
|
89
|
+
},
|
|
64
90
|
{
|
|
65
91
|
"id": "implement",
|
|
66
92
|
"steps": [
|
|
@@ -23,8 +23,16 @@
|
|
|
23
23
|
"template": "Running design review (iteration ${iteration})"
|
|
24
24
|
},
|
|
25
25
|
"taskKey": { "ref": "params.taskKey" },
|
|
26
|
+
"iteration": {
|
|
27
|
+
"add": [
|
|
28
|
+
{ "ref": "params.baseIteration" },
|
|
29
|
+
{ "add": [{ "ref": "repeat.iteration" }, { "const": -1 }] }
|
|
30
|
+
]
|
|
31
|
+
},
|
|
26
32
|
"workspaceDir": { "ref": "params.workspaceDir" },
|
|
27
33
|
"extraPrompt": { "ref": "params.extraPrompt" },
|
|
34
|
+
"projectGuidanceFile": { "ref": "params.projectGuidanceFile" },
|
|
35
|
+
"projectGuidanceJsonFile": { "ref": "params.projectGuidanceJsonFile" },
|
|
28
36
|
"llmExecutor": { "ref": "params.llmExecutor" },
|
|
29
37
|
"llmModel": { "ref": "params.llmModel" }
|
|
30
38
|
}
|
|
@@ -33,7 +41,13 @@
|
|
|
33
41
|
"id": "check_design_review_verdict",
|
|
34
42
|
"node": "design-review-verdict",
|
|
35
43
|
"params": {
|
|
36
|
-
"taskKey": { "ref": "params.taskKey" }
|
|
44
|
+
"taskKey": { "ref": "params.taskKey" },
|
|
45
|
+
"iteration": {
|
|
46
|
+
"add": [
|
|
47
|
+
{ "ref": "params.baseIteration" },
|
|
48
|
+
{ "add": [{ "ref": "repeat.iteration" }, { "const": -1 }] }
|
|
49
|
+
]
|
|
50
|
+
}
|
|
37
51
|
}
|
|
38
52
|
},
|
|
39
53
|
{
|
|
@@ -134,6 +134,8 @@
|
|
|
134
134
|
"plan_json_file": { "ref": "params.planJsonFile" },
|
|
135
135
|
"qa_file": { "ref": "params.qaFile" },
|
|
136
136
|
"qa_json_file": { "ref": "params.qaJsonFile" },
|
|
137
|
+
"project_guidance_file": { "ref": "params.projectGuidanceFile" },
|
|
138
|
+
"project_guidance_json_file": { "ref": "params.projectGuidanceJsonFile" },
|
|
137
139
|
"review_file": {
|
|
138
140
|
"artifact": {
|
|
139
141
|
"kind": "design-review-file",
|