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.
Files changed (48) hide show
  1. package/README.md +112 -23
  2. package/dist/artifacts.js +41 -0
  3. package/dist/index.js +258 -29
  4. package/dist/interactive/controller.js +323 -13
  5. package/dist/interactive/ink/index.js +2 -2
  6. package/dist/interactive/state.js +10 -0
  7. package/dist/interactive/web/index.js +326 -0
  8. package/dist/interactive/web/protocol.js +160 -0
  9. package/dist/interactive/web/server.js +1011 -0
  10. package/dist/interactive/web/static/app.js +1580 -0
  11. package/dist/interactive/web/static/index.html +114 -0
  12. package/dist/interactive/web/static/styles.css +2 -0
  13. package/dist/interactive/web/static/styles.input.css +849 -0
  14. package/dist/pipeline/flow-catalog.js +4 -0
  15. package/dist/pipeline/flow-specs/auto-common-guided.json +313 -0
  16. package/dist/pipeline/flow-specs/auto-common.json +3 -1
  17. package/dist/pipeline/flow-specs/design-review/design-review-loop.json +2 -0
  18. package/dist/pipeline/flow-specs/design-review.json +2 -0
  19. package/dist/pipeline/flow-specs/implement.json +3 -1
  20. package/dist/pipeline/flow-specs/plan.json +4 -0
  21. package/dist/pipeline/flow-specs/playbook-init.json +199 -0
  22. package/dist/pipeline/flow-specs/review/review-fix.json +3 -1
  23. package/dist/pipeline/flow-specs/review/review-loop.json +4 -0
  24. package/dist/pipeline/flow-specs/review/review.json +2 -0
  25. package/dist/pipeline/node-registry.js +45 -0
  26. package/dist/pipeline/nodes/flow-run-node.js +13 -1
  27. package/dist/pipeline/nodes/playbook-ensure-node.js +115 -0
  28. package/dist/pipeline/nodes/playbook-inventory-node.js +51 -0
  29. package/dist/pipeline/nodes/playbook-questions-form-node.js +166 -0
  30. package/dist/pipeline/nodes/playbook-write-node.js +243 -0
  31. package/dist/pipeline/nodes/project-guidance-node.js +69 -0
  32. package/dist/pipeline/prompt-registry.js +4 -1
  33. package/dist/pipeline/prompt-runtime.js +6 -2
  34. package/dist/pipeline/spec-types.js +19 -0
  35. package/dist/pipeline/value-resolver.js +39 -1
  36. package/dist/playbook/practice-candidates.js +12 -0
  37. package/dist/playbook/repo-inventory.js +208 -0
  38. package/dist/prompts.js +31 -0
  39. package/dist/runtime/artifact-catalog.js +379 -0
  40. package/dist/runtime/playbook.js +485 -0
  41. package/dist/runtime/project-guidance.js +339 -0
  42. package/dist/structured-artifact-schema-registry.js +8 -0
  43. package/dist/structured-artifact-schemas.json +235 -0
  44. package/dist/structured-artifacts.js +7 -1
  45. package/docs/declarative-workflows.md +565 -0
  46. package/docs/features.md +77 -0
  47. package/docs/playbook.md +327 -0
  48. 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 = "Generate all markdown output files in English language.";
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 = "Generate all markdown output files in Russian language.";
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
+ }