agentweaver 0.1.17 → 0.1.19
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 +112 -23
- package/dist/artifacts.js +41 -0
- package/dist/index.js +258 -29
- package/dist/interactive/controller.js +323 -13
- package/dist/interactive/ink/index.js +2 -2
- package/dist/interactive/state.js +10 -0
- package/dist/interactive/web/index.js +326 -0
- package/dist/interactive/web/protocol.js +160 -0
- package/dist/interactive/web/server.js +1011 -0
- package/dist/interactive/web/static/app.js +1580 -0
- package/dist/interactive/web/static/index.html +114 -0
- package/dist/interactive/web/static/styles.css +2 -0
- package/dist/interactive/web/static/styles.input.css +849 -0
- package/dist/pipeline/flow-catalog.js +4 -0
- package/dist/pipeline/flow-specs/auto-common-guided.json +313 -0
- package/dist/pipeline/flow-specs/auto-common.json +3 -1
- package/dist/pipeline/flow-specs/design-review/design-review-loop.json +2 -0
- 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 +4 -0
- 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/node-registry.js +45 -0
- package/dist/pipeline/nodes/flow-run-node.js +13 -1
- 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/prompt-registry.js +4 -1
- package/dist/pipeline/prompt-runtime.js +6 -2
- package/dist/pipeline/spec-types.js +19 -0
- package/dist/pipeline/value-resolver.js +39 -1
- package/dist/playbook/practice-candidates.js +12 -0
- package/dist/playbook/repo-inventory.js +208 -0
- package/dist/prompts.js +31 -0
- package/dist/runtime/artifact-catalog.js +379 -0
- 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/features.md +77 -0
- package/docs/playbook.md +327 -0
- package/package.json +8 -3
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { buildLogicalKeyForPayload } from "../../artifact-manifest.js";
|
|
4
|
+
import { TaskRunnerError } from "../../errors.js";
|
|
5
|
+
import { loadProjectPlaybook } from "../../runtime/playbook.js";
|
|
6
|
+
import { validateStructuredArtifact, validateStructuredArtifactValue } from "../../structured-artifacts.js";
|
|
7
|
+
function readJson(filePath) {
|
|
8
|
+
try {
|
|
9
|
+
return JSON.parse(readFileSync(filePath, "utf8"));
|
|
10
|
+
}
|
|
11
|
+
catch (error) {
|
|
12
|
+
throw new TaskRunnerError(`Failed to read JSON from ${filePath}: ${error.message}`);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
function finalPlaybookPaths(cwd) {
|
|
16
|
+
const dir = path.join(cwd, ".agentweaver", "playbook");
|
|
17
|
+
return {
|
|
18
|
+
dir,
|
|
19
|
+
manifestFile: path.join(dir, "manifest.yaml"),
|
|
20
|
+
projectFile: path.join(dir, "project.md"),
|
|
21
|
+
practiceFile: path.join(dir, "practices", "generated-rules.md"),
|
|
22
|
+
exampleFile: path.join(dir, "examples", "generated-example.md"),
|
|
23
|
+
templateFile: path.join(dir, "templates", "default.md"),
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
function detectExistingState(cwd, manifestFile) {
|
|
27
|
+
if (!existsSync(manifestFile)) {
|
|
28
|
+
return { status: "absent", blockedPaths: [], message: "No manifest-based playbook exists." };
|
|
29
|
+
}
|
|
30
|
+
try {
|
|
31
|
+
loadProjectPlaybook(cwd);
|
|
32
|
+
return { status: "accepted", blockedPaths: [manifestFile], message: "A valid manifest-based playbook already exists." };
|
|
33
|
+
}
|
|
34
|
+
catch (error) {
|
|
35
|
+
return {
|
|
36
|
+
status: "blocked",
|
|
37
|
+
blockedPaths: [manifestFile],
|
|
38
|
+
message: `Existing manifest-based playbook is invalid or partial: ${error.message}`,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
function toFinalPlaybook(draft, draftJsonFile) {
|
|
43
|
+
const evidence = Array.from(new Set([
|
|
44
|
+
...(Array.isArray(draft.evidence_paths) ? draft.evidence_paths : []),
|
|
45
|
+
...draft.accepted_rules.flatMap((rule) => rule.evidence_paths),
|
|
46
|
+
])).sort((left, right) => left.localeCompare(right));
|
|
47
|
+
return {
|
|
48
|
+
status: "accepted",
|
|
49
|
+
accepted_at: new Date().toISOString(),
|
|
50
|
+
source_draft_artifact: draftJsonFile,
|
|
51
|
+
summary: draft.summary,
|
|
52
|
+
rules: draft.accepted_rules,
|
|
53
|
+
evidence_paths: evidence,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
function renderFinalMarkdown(finalPlaybook) {
|
|
57
|
+
const rules = Array.isArray(finalPlaybook.rules) ? finalPlaybook.rules : [];
|
|
58
|
+
return [
|
|
59
|
+
"# Project playbook",
|
|
60
|
+
"",
|
|
61
|
+
String(finalPlaybook.summary ?? ""),
|
|
62
|
+
"",
|
|
63
|
+
"## Required rules",
|
|
64
|
+
...(rules.length === 0
|
|
65
|
+
? ["- No accepted required rules."]
|
|
66
|
+
: rules.map((rule) => `- ${rule.title}: ${rule.rule}\n Evidence: ${rule.evidence_paths.join(", ")}`)),
|
|
67
|
+
"",
|
|
68
|
+
].join("\n");
|
|
69
|
+
}
|
|
70
|
+
function yamlStringArray(values) {
|
|
71
|
+
return Array.from(new Set(values.filter((value) => value.trim().length > 0))).sort();
|
|
72
|
+
}
|
|
73
|
+
function quotedYamlString(value) {
|
|
74
|
+
return JSON.stringify(value);
|
|
75
|
+
}
|
|
76
|
+
function yamlList(values, indent = "") {
|
|
77
|
+
return values.length > 0 ? values.map((value) => `${indent}- ${quotedYamlString(value)}`) : [`${indent}[]`];
|
|
78
|
+
}
|
|
79
|
+
function renderPracticeMarkdown(draft) {
|
|
80
|
+
const body = draft.accepted_rules.length === 0
|
|
81
|
+
? "No accepted project rules were generated."
|
|
82
|
+
: draft.accepted_rules.map((rule) => `## ${rule.title}\n\n${rule.rule}\n\nEvidence: ${rule.evidence_paths.join(", ")}`).join("\n\n");
|
|
83
|
+
return [
|
|
84
|
+
"---",
|
|
85
|
+
'id: "practice.generated-rules"',
|
|
86
|
+
'title: "Generated project rules"',
|
|
87
|
+
"phases:",
|
|
88
|
+
...yamlList(["plan", "design_review", "implement", "review", "repair"], " "),
|
|
89
|
+
"priority: 10",
|
|
90
|
+
'severity: "must"',
|
|
91
|
+
"related_practices: []",
|
|
92
|
+
"related_examples: []",
|
|
93
|
+
"---",
|
|
94
|
+
"",
|
|
95
|
+
body,
|
|
96
|
+
"",
|
|
97
|
+
].join("\n");
|
|
98
|
+
}
|
|
99
|
+
function renderExampleMarkdown() {
|
|
100
|
+
return [
|
|
101
|
+
"---",
|
|
102
|
+
'id: "example.generated-guidance"',
|
|
103
|
+
'title: "Generated guidance reference"',
|
|
104
|
+
"phases:",
|
|
105
|
+
...yamlList(["plan", "design_review", "implement", "review", "repair"], " "),
|
|
106
|
+
"priority: 0",
|
|
107
|
+
'severity: "info"',
|
|
108
|
+
"related_practices:",
|
|
109
|
+
...yamlList(["practice.generated-rules"], " "),
|
|
110
|
+
"related_examples: []",
|
|
111
|
+
"---",
|
|
112
|
+
"",
|
|
113
|
+
"Use this entry as a reference marker for generated playbook guidance.",
|
|
114
|
+
"",
|
|
115
|
+
].join("\n");
|
|
116
|
+
}
|
|
117
|
+
function renderManifest(draft) {
|
|
118
|
+
const evidence = yamlStringArray([
|
|
119
|
+
...(Array.isArray(draft.evidence_paths) ? draft.evidence_paths : []),
|
|
120
|
+
...draft.accepted_rules.flatMap((rule) => rule.evidence_paths),
|
|
121
|
+
]);
|
|
122
|
+
return [
|
|
123
|
+
"version: 1",
|
|
124
|
+
"project:",
|
|
125
|
+
' name: "Generated Project Playbook"',
|
|
126
|
+
"context_budgets:",
|
|
127
|
+
" plan: 1200",
|
|
128
|
+
" design_review: 1000",
|
|
129
|
+
" implement: 1400",
|
|
130
|
+
" review: 1000",
|
|
131
|
+
" repair: 1000",
|
|
132
|
+
"practices:",
|
|
133
|
+
" paths:",
|
|
134
|
+
...yamlList(["practices/generated-rules.md"], " "),
|
|
135
|
+
" globs: []",
|
|
136
|
+
"examples:",
|
|
137
|
+
" paths:",
|
|
138
|
+
...yamlList(["examples/generated-example.md"], " "),
|
|
139
|
+
" globs: []",
|
|
140
|
+
"templates:",
|
|
141
|
+
" paths:",
|
|
142
|
+
...yamlList(["templates/default.md"], " "),
|
|
143
|
+
" globs: []",
|
|
144
|
+
"always_include:",
|
|
145
|
+
...yamlList(["project.md"], " "),
|
|
146
|
+
"selection:",
|
|
147
|
+
" include_examples: true",
|
|
148
|
+
" max_examples: 1",
|
|
149
|
+
"evidence_paths:",
|
|
150
|
+
...yamlList(evidence, " "),
|
|
151
|
+
"",
|
|
152
|
+
].join("\n");
|
|
153
|
+
}
|
|
154
|
+
function writeResult(filePath, result) {
|
|
155
|
+
validateStructuredArtifactValue(result, "playbook-write-result/v1", filePath);
|
|
156
|
+
mkdirSync(path.dirname(filePath), { recursive: true });
|
|
157
|
+
writeFileSync(filePath, `${JSON.stringify(result, null, 2)}\n`, "utf8");
|
|
158
|
+
}
|
|
159
|
+
function baseResult(status, message, intendedFiles) {
|
|
160
|
+
return {
|
|
161
|
+
status,
|
|
162
|
+
message,
|
|
163
|
+
written_files: [],
|
|
164
|
+
skipped_files: [],
|
|
165
|
+
existing_playbook_path: "",
|
|
166
|
+
intended_files: intendedFiles,
|
|
167
|
+
blocked_paths: [],
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
export const playbookWriteNode = {
|
|
171
|
+
kind: "playbook-write",
|
|
172
|
+
version: 1,
|
|
173
|
+
async run(context, params) {
|
|
174
|
+
const { dir, manifestFile, projectFile, practiceFile, exampleFile, templateFile } = finalPlaybookPaths(context.cwd);
|
|
175
|
+
const intendedFiles = [manifestFile, projectFile, practiceFile, exampleFile, templateFile];
|
|
176
|
+
const answers = existsSync(params.answersJsonFile) ? readJson(params.answersJsonFile) : {};
|
|
177
|
+
const accepted = answers.final_write_accepted === true;
|
|
178
|
+
let result;
|
|
179
|
+
if (!accepted) {
|
|
180
|
+
result = baseResult("not_accepted", "Final playbook write was not accepted in playbook-answers.json.", intendedFiles);
|
|
181
|
+
writeResult(params.writeResultJsonFile, result);
|
|
182
|
+
return { value: { ...result, finalJsonFile: manifestFile, finalMarkdownFile: projectFile, finalManifestFile: manifestFile }, outputs: outputSpecs(context.issueKey, params.writeResultJsonFile) };
|
|
183
|
+
}
|
|
184
|
+
if (context.dryRun) {
|
|
185
|
+
result = baseResult("dry_run_written", "Dry-run mode accepted the generated manifest layout but did not write final playbook files.", intendedFiles);
|
|
186
|
+
writeResult(params.writeResultJsonFile, result);
|
|
187
|
+
return { value: { ...result, finalJsonFile: manifestFile, finalMarkdownFile: projectFile, finalManifestFile: manifestFile }, outputs: outputSpecs(context.issueKey, params.writeResultJsonFile) };
|
|
188
|
+
}
|
|
189
|
+
const existing = detectExistingState(context.cwd, manifestFile);
|
|
190
|
+
if (existing.status === "accepted") {
|
|
191
|
+
result = {
|
|
192
|
+
...baseResult("skipped_valid_existing", existing.message, intendedFiles),
|
|
193
|
+
skipped_files: intendedFiles,
|
|
194
|
+
existing_playbook_path: manifestFile,
|
|
195
|
+
};
|
|
196
|
+
writeResult(params.writeResultJsonFile, result);
|
|
197
|
+
return { value: { ...result, finalJsonFile: manifestFile, finalMarkdownFile: projectFile, finalManifestFile: manifestFile }, outputs: outputSpecs(context.issueKey, params.writeResultJsonFile) };
|
|
198
|
+
}
|
|
199
|
+
if (existing.status === "blocked") {
|
|
200
|
+
result = {
|
|
201
|
+
...baseResult("blocked", existing.message, intendedFiles),
|
|
202
|
+
blocked_paths: existing.blockedPaths,
|
|
203
|
+
};
|
|
204
|
+
writeResult(params.writeResultJsonFile, result);
|
|
205
|
+
return { value: { ...result, finalJsonFile: manifestFile, finalMarkdownFile: projectFile, finalManifestFile: manifestFile }, outputs: outputSpecs(context.issueKey, params.writeResultJsonFile) };
|
|
206
|
+
}
|
|
207
|
+
validateStructuredArtifact(params.draftJsonFile, "playbook-draft/v1");
|
|
208
|
+
const draft = readJson(params.draftJsonFile);
|
|
209
|
+
const finalPlaybook = toFinalPlaybook(draft, params.draftJsonFile);
|
|
210
|
+
mkdirSync(dir, { recursive: true });
|
|
211
|
+
mkdirSync(path.dirname(practiceFile), { recursive: true });
|
|
212
|
+
mkdirSync(path.dirname(exampleFile), { recursive: true });
|
|
213
|
+
mkdirSync(path.dirname(templateFile), { recursive: true });
|
|
214
|
+
writeFileSync(manifestFile, renderManifest(draft), "utf8");
|
|
215
|
+
writeFileSync(projectFile, renderFinalMarkdown(finalPlaybook), "utf8");
|
|
216
|
+
writeFileSync(practiceFile, renderPracticeMarkdown(draft), "utf8");
|
|
217
|
+
writeFileSync(exampleFile, renderExampleMarkdown(), "utf8");
|
|
218
|
+
writeFileSync(templateFile, "# Default Template\n", "utf8");
|
|
219
|
+
loadProjectPlaybook(context.cwd);
|
|
220
|
+
result = {
|
|
221
|
+
...baseResult("written", "Accepted playbook was written to the canonical manifest.yaml layout.", intendedFiles),
|
|
222
|
+
written_files: intendedFiles,
|
|
223
|
+
};
|
|
224
|
+
writeResult(params.writeResultJsonFile, result);
|
|
225
|
+
return { value: { ...result, finalJsonFile: manifestFile, finalMarkdownFile: projectFile, finalManifestFile: manifestFile }, outputs: outputSpecs(context.issueKey, params.writeResultJsonFile) };
|
|
226
|
+
},
|
|
227
|
+
};
|
|
228
|
+
function outputSpecs(scopeKey, writeResultJsonFile) {
|
|
229
|
+
return [
|
|
230
|
+
{
|
|
231
|
+
kind: "artifact",
|
|
232
|
+
path: writeResultJsonFile,
|
|
233
|
+
required: true,
|
|
234
|
+
manifest: {
|
|
235
|
+
publish: true,
|
|
236
|
+
logicalKey: buildLogicalKeyForPayload(scopeKey, writeResultJsonFile),
|
|
237
|
+
payloadFamily: "structured-json",
|
|
238
|
+
schemaId: "playbook-write-result/v1",
|
|
239
|
+
schemaVersion: 1,
|
|
240
|
+
},
|
|
241
|
+
},
|
|
242
|
+
];
|
|
243
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { buildLogicalKeyForPayload } from "../../artifact-manifest.js";
|
|
4
|
+
import { TaskRunnerError } from "../../errors.js";
|
|
5
|
+
import { buildProjectGuidance, renderProjectGuidanceMarkdown } from "../../runtime/project-guidance.js";
|
|
6
|
+
import { validateStructuredArtifactValue } from "../../structured-artifacts.js";
|
|
7
|
+
function readTaskContext(filePath) {
|
|
8
|
+
try {
|
|
9
|
+
return JSON.parse(readFileSync(filePath, "utf8"));
|
|
10
|
+
}
|
|
11
|
+
catch (error) {
|
|
12
|
+
throw new TaskRunnerError(`Failed to read task context JSON ${filePath}: ${error.message}`);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
export const projectGuidanceNode = {
|
|
16
|
+
kind: "project-guidance",
|
|
17
|
+
version: 1,
|
|
18
|
+
async run(context, params) {
|
|
19
|
+
const taskContext = readTaskContext(params.taskContextJsonFile);
|
|
20
|
+
const guidance = buildProjectGuidance({
|
|
21
|
+
projectRoot: context.cwd,
|
|
22
|
+
taskContext,
|
|
23
|
+
phase: params.phase,
|
|
24
|
+
...(params.budgetLimit !== undefined ? { budgetLimit: params.budgetLimit } : {}),
|
|
25
|
+
...(params.inlineThreshold !== undefined ? { inlineThreshold: params.inlineThreshold } : {}),
|
|
26
|
+
invalidPlaybookPolicy: params.invalidPlaybookPolicy ?? "fail_before_prompt",
|
|
27
|
+
});
|
|
28
|
+
validateStructuredArtifactValue(guidance, "project-guidance/v1", params.outputJsonFile);
|
|
29
|
+
mkdirSync(path.dirname(params.outputJsonFile), { recursive: true });
|
|
30
|
+
writeFileSync(params.outputJsonFile, `${JSON.stringify(guidance, null, 2)}\n`, "utf8");
|
|
31
|
+
const markdown = renderProjectGuidanceMarkdown(guidance, params.markdownLanguage ?? context.mdLang ?? "en");
|
|
32
|
+
mkdirSync(path.dirname(params.outputFile), { recursive: true });
|
|
33
|
+
writeFileSync(params.outputFile, markdown, "utf8");
|
|
34
|
+
return {
|
|
35
|
+
value: {
|
|
36
|
+
status: guidance.status,
|
|
37
|
+
phase: guidance.phase,
|
|
38
|
+
outputJsonFile: params.outputJsonFile,
|
|
39
|
+
outputFile: params.outputFile,
|
|
40
|
+
},
|
|
41
|
+
outputs: [
|
|
42
|
+
{
|
|
43
|
+
kind: "artifact",
|
|
44
|
+
path: params.outputJsonFile,
|
|
45
|
+
required: true,
|
|
46
|
+
manifest: {
|
|
47
|
+
publish: true,
|
|
48
|
+
logicalKey: buildLogicalKeyForPayload(context.issueKey, params.outputJsonFile),
|
|
49
|
+
payloadFamily: "structured-json",
|
|
50
|
+
schemaId: "project-guidance/v1",
|
|
51
|
+
schemaVersion: 1,
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
kind: "artifact",
|
|
56
|
+
path: params.outputFile,
|
|
57
|
+
required: true,
|
|
58
|
+
manifest: {
|
|
59
|
+
publish: true,
|
|
60
|
+
logicalKey: buildLogicalKeyForPayload(context.issueKey, params.outputFile),
|
|
61
|
+
payloadFamily: "markdown",
|
|
62
|
+
schemaId: "markdown/v1",
|
|
63
|
+
schemaVersion: 1,
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
],
|
|
67
|
+
};
|
|
68
|
+
},
|
|
69
|
+
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BUG_ANALYZE_PROMPT_TEMPLATE, COMMIT_MESSAGE_PROMPT_TEMPLATE, DESIGN_REVIEW_PROMPT_TEMPLATE, GITLAB_DIFF_REVIEW_PROMPT_TEMPLATE, GITLAB_REVIEW_PROMPT_TEMPLATE, BUG_FIX_PROMPT_TEMPLATE, IMPLEMENT_PROMPT_TEMPLATE, JIRA_DESCRIPTION_PROMPT_TEMPLATE, MR_DESCRIPTION_PROMPT_TEMPLATE, PLAN_PROMPT_TEMPLATE, PLAN_QUESTIONS_PROMPT_TEMPLATE, PLAN_REVISE_PROMPT_TEMPLATE, REVIEW_FIX_PROMPT_TEMPLATE, REVIEW_PROJECT_PROMPT_TEMPLATE, REVIEW_PROMPT_TEMPLATE, REVIEW_SUMMARY_PROMPT_TEMPLATE, RUN_GO_LINTER_LOOP_FIX_PROMPT_TEMPLATE, RUN_GO_TESTS_LOOP_FIX_PROMPT_TEMPLATE, TASK_CONTEXT_FROM_JIRA_PROMPT_TEMPLATE, TASK_CONTEXT_FROM_MANUAL_PROMPT_TEMPLATE, TASK_SUMMARY_PROMPT_TEMPLATE, } from "../prompts.js";
|
|
1
|
+
import { BUG_ANALYZE_PROMPT_TEMPLATE, COMMIT_MESSAGE_PROMPT_TEMPLATE, DESIGN_REVIEW_PROMPT_TEMPLATE, GITLAB_DIFF_REVIEW_PROMPT_TEMPLATE, GITLAB_REVIEW_PROMPT_TEMPLATE, BUG_FIX_PROMPT_TEMPLATE, IMPLEMENT_PROMPT_TEMPLATE, JIRA_DESCRIPTION_PROMPT_TEMPLATE, MR_DESCRIPTION_PROMPT_TEMPLATE, PLAN_PROMPT_TEMPLATE, PLAN_QUESTIONS_PROMPT_TEMPLATE, PLAYBOOK_DRAFT_PROMPT_TEMPLATE, PLAYBOOK_PRACTICE_CANDIDATES_PROMPT_TEMPLATE, PLAYBOOK_QUESTIONS_PROMPT_TEMPLATE, PLAN_REVISE_PROMPT_TEMPLATE, REVIEW_FIX_PROMPT_TEMPLATE, REVIEW_PROJECT_PROMPT_TEMPLATE, REVIEW_PROMPT_TEMPLATE, REVIEW_SUMMARY_PROMPT_TEMPLATE, RUN_GO_LINTER_LOOP_FIX_PROMPT_TEMPLATE, RUN_GO_TESTS_LOOP_FIX_PROMPT_TEMPLATE, TASK_CONTEXT_FROM_JIRA_PROMPT_TEMPLATE, TASK_CONTEXT_FROM_MANUAL_PROMPT_TEMPLATE, TASK_SUMMARY_PROMPT_TEMPLATE, } from "../prompts.js";
|
|
2
2
|
const promptTemplates = {
|
|
3
3
|
"bug-analyze": BUG_ANALYZE_PROMPT_TEMPLATE,
|
|
4
4
|
"bug-fix": BUG_FIX_PROMPT_TEMPLATE,
|
|
@@ -10,6 +10,9 @@ const promptTemplates = {
|
|
|
10
10
|
"task-describe": JIRA_DESCRIPTION_PROMPT_TEMPLATE,
|
|
11
11
|
"mr-description": MR_DESCRIPTION_PROMPT_TEMPLATE,
|
|
12
12
|
"plan-questions": PLAN_QUESTIONS_PROMPT_TEMPLATE,
|
|
13
|
+
"playbook-draft": PLAYBOOK_DRAFT_PROMPT_TEMPLATE,
|
|
14
|
+
"playbook-practice-candidates": PLAYBOOK_PRACTICE_CANDIDATES_PROMPT_TEMPLATE,
|
|
15
|
+
"playbook-questions": PLAYBOOK_QUESTIONS_PROMPT_TEMPLATE,
|
|
13
16
|
plan: PLAN_PROMPT_TEMPLATE,
|
|
14
17
|
"plan-revise": PLAN_REVISE_PROMPT_TEMPLATE,
|
|
15
18
|
review: REVIEW_PROMPT_TEMPLATE,
|
|
@@ -18,10 +18,14 @@ export function renderPrompt(binding, context) {
|
|
|
18
18
|
const jsonInstruction = STRUCTURED_JSON_LANGUAGE_INSTRUCTION.trim();
|
|
19
19
|
let langInstruction = null;
|
|
20
20
|
if (mdLang === "en") {
|
|
21
|
-
langInstruction =
|
|
21
|
+
langInstruction =
|
|
22
|
+
"Generate workflow markdown artifact files in English language. " +
|
|
23
|
+
"This language setting applies only to generated AgentWeaver artifacts, not to repository source files, code comments, committed documentation, or project-local playbook rules.";
|
|
22
24
|
}
|
|
23
25
|
else if (mdLang === "ru" || mdLang === null || mdLang === undefined) {
|
|
24
|
-
langInstruction =
|
|
26
|
+
langInstruction =
|
|
27
|
+
"Generate workflow markdown artifact files in Russian language. " +
|
|
28
|
+
"This language setting applies only to generated AgentWeaver artifacts, not to repository source files, code comments, committed documentation, or project-local playbook rules.";
|
|
25
29
|
}
|
|
26
30
|
const finalExtraPrompt = [extraPrompt, jsonInstruction, langInstruction].filter(Boolean).join("\n");
|
|
27
31
|
if ((binding.format ?? "task-prompt") === "plain") {
|
|
@@ -25,11 +25,30 @@ export const ARTIFACT_REF_KINDS = [
|
|
|
25
25
|
"mr-description-json-file",
|
|
26
26
|
"planning-answers-json-file",
|
|
27
27
|
"planning-questions-json-file",
|
|
28
|
+
"playbook-answers-json-file",
|
|
29
|
+
"playbook-draft-file",
|
|
30
|
+
"playbook-draft-json-file",
|
|
31
|
+
"playbook-questions-json-file",
|
|
32
|
+
"playbook-write-result-json-file",
|
|
28
33
|
"plan-file",
|
|
29
34
|
"plan-json-file",
|
|
30
35
|
"qa-file",
|
|
31
36
|
"qa-json-file",
|
|
37
|
+
"practice-candidates-file",
|
|
38
|
+
"practice-candidates-json-file",
|
|
39
|
+
"project-guidance-plan-file",
|
|
40
|
+
"project-guidance-plan-json-file",
|
|
41
|
+
"project-guidance-design-review-file",
|
|
42
|
+
"project-guidance-design-review-json-file",
|
|
43
|
+
"project-guidance-implement-file",
|
|
44
|
+
"project-guidance-implement-json-file",
|
|
45
|
+
"project-guidance-review-file",
|
|
46
|
+
"project-guidance-review-json-file",
|
|
47
|
+
"project-guidance-repair-review-fix-file",
|
|
48
|
+
"project-guidance-repair-review-fix-json-file",
|
|
32
49
|
"ready-to-merge-file",
|
|
50
|
+
"repo-inventory-file",
|
|
51
|
+
"repo-inventory-json-file",
|
|
33
52
|
"review-file",
|
|
34
53
|
"review-json-file",
|
|
35
54
|
"review-assessment-file",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { existsSync } from "node:fs";
|
|
2
|
-
import { artifactFile, bugAnalyzeArtifacts, bugAnalyzeFile, bugAnalyzeJsonFile, bugFixDesignFile, bugFixDesignJsonFile, bugFixPlanFile, bugFixPlanJsonFile, designFile, designJsonFile, designReviewFile, designReviewJsonFile, gitlabDiffFile, gitlabDiffJsonFile, gitlabDiffReviewInputJsonFile, gitlabReviewFile, gitlabReviewInputJsonFile, gitlabReviewJsonFile, jiraAttachmentsContextFile, jiraAttachmentsManifestFile, jiraDescriptionFile, jiraDescriptionJsonFile, instantTaskInputJsonFile, jiraTaskFile, mrDescriptionFile, mrDescriptionJsonFile, planningAnswersJsonFile, planningQuestionsJsonFile, planArtifacts, planFile, planJsonFile, qaFile, qaJsonFile, readyToMergeFile, reviewAssessmentFile, reviewAssessmentJsonFile, reviewFile, reviewFixFile, reviewFixJsonFile, reviewJsonFile, runGoLinterResultJsonFile, runGoTestsResultJsonFile, taskSummaryFile, taskDescribeInputJsonFile, taskSummaryJsonFile, taskContextFile, taskContextJsonFile, gitStatusJsonFile, gitCommitMessageJsonFile, gitCommitInputJsonFile, selectFilesOutputJsonFile, commitMessageOutputJsonFile, gitDiffFile as gitDiffFileHelper, } from "../artifacts.js";
|
|
2
|
+
import { artifactFile, bugAnalyzeArtifacts, bugAnalyzeFile, bugAnalyzeJsonFile, bugFixDesignFile, bugFixDesignJsonFile, bugFixPlanFile, bugFixPlanJsonFile, designFile, designJsonFile, designReviewFile, designReviewJsonFile, gitlabDiffFile, gitlabDiffJsonFile, gitlabDiffReviewInputJsonFile, gitlabReviewFile, gitlabReviewInputJsonFile, gitlabReviewJsonFile, jiraAttachmentsContextFile, jiraAttachmentsManifestFile, jiraDescriptionFile, jiraDescriptionJsonFile, instantTaskInputJsonFile, jiraTaskFile, mrDescriptionFile, mrDescriptionJsonFile, playbookAnswersJsonFile, playbookDraftFile, playbookDraftJsonFile, playbookQuestionsJsonFile, playbookWriteResultJsonFile, planningAnswersJsonFile, planningQuestionsJsonFile, planArtifacts, planFile, planJsonFile, practiceCandidatesFile, practiceCandidatesJsonFile, projectGuidanceFile, projectGuidanceJsonFile, qaFile, qaJsonFile, readyToMergeFile, repoInventoryFile, repoInventoryJsonFile, reviewAssessmentFile, reviewAssessmentJsonFile, reviewFile, reviewFixFile, reviewFixJsonFile, reviewJsonFile, runGoLinterResultJsonFile, runGoTestsResultJsonFile, taskSummaryFile, taskDescribeInputJsonFile, taskSummaryJsonFile, taskContextFile, taskContextJsonFile, gitStatusJsonFile, gitCommitMessageJsonFile, gitCommitInputJsonFile, selectFilesOutputJsonFile, commitMessageOutputJsonFile, gitDiffFile as gitDiffFileHelper, } from "../artifacts.js";
|
|
3
3
|
import { TaskRunnerError } from "../errors.js";
|
|
4
4
|
import { formatTemplate } from "../prompts.js";
|
|
5
5
|
function readStepRef(segments, context, originalPath) {
|
|
@@ -130,16 +130,54 @@ function resolveArtifact(spec, context) {
|
|
|
130
130
|
return planningAnswersJsonFile(taskKey);
|
|
131
131
|
case "planning-questions-json-file":
|
|
132
132
|
return planningQuestionsJsonFile(taskKey);
|
|
133
|
+
case "playbook-answers-json-file":
|
|
134
|
+
return playbookAnswersJsonFile(taskKey);
|
|
135
|
+
case "playbook-draft-file":
|
|
136
|
+
return playbookDraftFile(taskKey);
|
|
137
|
+
case "playbook-draft-json-file":
|
|
138
|
+
return playbookDraftJsonFile(taskKey);
|
|
139
|
+
case "playbook-questions-json-file":
|
|
140
|
+
return playbookQuestionsJsonFile(taskKey);
|
|
141
|
+
case "playbook-write-result-json-file":
|
|
142
|
+
return playbookWriteResultJsonFile(taskKey);
|
|
133
143
|
case "plan-file":
|
|
134
144
|
return planFile(taskKey, iteration);
|
|
135
145
|
case "plan-json-file":
|
|
136
146
|
return planJsonFile(taskKey, iteration);
|
|
147
|
+
case "practice-candidates-file":
|
|
148
|
+
return practiceCandidatesFile(taskKey);
|
|
149
|
+
case "practice-candidates-json-file":
|
|
150
|
+
return practiceCandidatesJsonFile(taskKey);
|
|
151
|
+
case "project-guidance-plan-file":
|
|
152
|
+
return projectGuidanceFile(taskKey, "plan", iteration);
|
|
153
|
+
case "project-guidance-plan-json-file":
|
|
154
|
+
return projectGuidanceJsonFile(taskKey, "plan", iteration);
|
|
155
|
+
case "project-guidance-design-review-file":
|
|
156
|
+
return projectGuidanceFile(taskKey, "design-review", iteration);
|
|
157
|
+
case "project-guidance-design-review-json-file":
|
|
158
|
+
return projectGuidanceJsonFile(taskKey, "design-review", iteration);
|
|
159
|
+
case "project-guidance-implement-file":
|
|
160
|
+
return projectGuidanceFile(taskKey, "implement", iteration);
|
|
161
|
+
case "project-guidance-implement-json-file":
|
|
162
|
+
return projectGuidanceJsonFile(taskKey, "implement", iteration);
|
|
163
|
+
case "project-guidance-review-file":
|
|
164
|
+
return projectGuidanceFile(taskKey, "review", iteration);
|
|
165
|
+
case "project-guidance-review-json-file":
|
|
166
|
+
return projectGuidanceJsonFile(taskKey, "review", iteration);
|
|
167
|
+
case "project-guidance-repair-review-fix-file":
|
|
168
|
+
return projectGuidanceFile(taskKey, "repair/review-fix", iteration);
|
|
169
|
+
case "project-guidance-repair-review-fix-json-file":
|
|
170
|
+
return projectGuidanceJsonFile(taskKey, "repair/review-fix", iteration);
|
|
137
171
|
case "qa-file":
|
|
138
172
|
return qaFile(taskKey, iteration);
|
|
139
173
|
case "qa-json-file":
|
|
140
174
|
return qaJsonFile(taskKey, iteration);
|
|
141
175
|
case "ready-to-merge-file":
|
|
142
176
|
return readyToMergeFile(taskKey);
|
|
177
|
+
case "repo-inventory-file":
|
|
178
|
+
return repoInventoryFile(taskKey);
|
|
179
|
+
case "repo-inventory-json-file":
|
|
180
|
+
return repoInventoryJsonFile(taskKey);
|
|
143
181
|
case "review-file":
|
|
144
182
|
if (iteration === undefined) {
|
|
145
183
|
throw new TaskRunnerError("review-file requires iteration");
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { TaskRunnerError } from "../errors.js";
|
|
2
|
+
const CONFIDENCE_VALUES = new Set(["low", "medium", "high"]);
|
|
3
|
+
export function validatePracticeCandidatesArtifact(artifact) {
|
|
4
|
+
for (const candidate of artifact.candidates) {
|
|
5
|
+
if (!CONFIDENCE_VALUES.has(candidate.confidence)) {
|
|
6
|
+
throw new TaskRunnerError(`Practice candidate '${candidate.id}' has unsupported confidence '${candidate.confidence}'.`);
|
|
7
|
+
}
|
|
8
|
+
if (!Array.isArray(candidate.evidence_paths) || candidate.evidence_paths.length === 0) {
|
|
9
|
+
throw new TaskRunnerError(`Practice candidate '${candidate.id}' must cite at least one evidence path.`);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
}
|