agentweaver 0.1.6 → 0.1.8

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.
@@ -1,17 +1,20 @@
1
- import { BUG_ANALYZE_PROMPT_TEMPLATE, BUG_FIX_PROMPT_TEMPLATE, IMPLEMENT_PROMPT_TEMPLATE, MR_DESCRIPTION_PROMPT_TEMPLATE, PLAN_PROMPT_TEMPLATE, REVIEW_FIX_PROMPT_TEMPLATE, REVIEW_PROMPT_TEMPLATE, REVIEW_REPLY_PROMPT_TEMPLATE, REVIEW_REPLY_SUMMARY_PROMPT_TEMPLATE, REVIEW_SUMMARY_PROMPT_TEMPLATE, RUN_LINTER_LOOP_FIX_PROMPT_TEMPLATE, RUN_TESTS_LOOP_FIX_PROMPT_TEMPLATE, TASK_SUMMARY_PROMPT_TEMPLATE, } from "../prompts.js";
1
+ import { BUG_ANALYZE_PROMPT_TEMPLATE, BUG_FIX_PROMPT_TEMPLATE, IMPLEMENT_PROMPT_TEMPLATE, JIRA_DESCRIPTION_PROMPT_TEMPLATE, MR_DESCRIPTION_PROMPT_TEMPLATE, PLAN_PROMPT_TEMPLATE, REVIEW_FIX_PROMPT_TEMPLATE, REVIEW_PROJECT_PROMPT_TEMPLATE, REVIEW_PROMPT_TEMPLATE, REVIEW_REPLY_PROJECT_PROMPT_TEMPLATE, REVIEW_REPLY_PROMPT_TEMPLATE, REVIEW_REPLY_SUMMARY_PROMPT_TEMPLATE, REVIEW_SUMMARY_PROMPT_TEMPLATE, RUN_GO_LINTER_LOOP_FIX_PROMPT_TEMPLATE, RUN_GO_TESTS_LOOP_FIX_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,
5
5
  implement: IMPLEMENT_PROMPT_TEMPLATE,
6
+ "task-describe": JIRA_DESCRIPTION_PROMPT_TEMPLATE,
6
7
  "mr-description": MR_DESCRIPTION_PROMPT_TEMPLATE,
7
8
  plan: PLAN_PROMPT_TEMPLATE,
8
9
  review: REVIEW_PROMPT_TEMPLATE,
10
+ "review-project": REVIEW_PROJECT_PROMPT_TEMPLATE,
9
11
  "review-fix": REVIEW_FIX_PROMPT_TEMPLATE,
10
12
  "review-reply": REVIEW_REPLY_PROMPT_TEMPLATE,
13
+ "review-reply-project": REVIEW_REPLY_PROJECT_PROMPT_TEMPLATE,
11
14
  "review-reply-summary": REVIEW_REPLY_SUMMARY_PROMPT_TEMPLATE,
12
15
  "review-summary": REVIEW_SUMMARY_PROMPT_TEMPLATE,
13
- "run-linter-loop-fix": RUN_LINTER_LOOP_FIX_PROMPT_TEMPLATE,
14
- "run-tests-loop-fix": RUN_TESTS_LOOP_FIX_PROMPT_TEMPLATE,
16
+ "run-go-linter-loop-fix": RUN_GO_LINTER_LOOP_FIX_PROMPT_TEMPLATE,
17
+ "run-go-tests-loop-fix": RUN_GO_TESTS_LOOP_FIX_PROMPT_TEMPLATE,
15
18
  "task-summary": TASK_SUMMARY_PROMPT_TEMPLATE,
16
19
  };
17
20
  export function isPromptTemplateRef(value) {
@@ -1,5 +1,5 @@
1
1
  import { existsSync } from "node:fs";
2
- import { artifactFile, bugAnalyzeArtifacts, bugAnalyzeFile, bugAnalyzeJsonFile, bugFixDesignFile, bugFixDesignJsonFile, bugFixPlanFile, bugFixPlanJsonFile, designFile, designJsonFile, gitlabReviewFile, gitlabReviewInputJsonFile, gitlabReviewJsonFile, jiraDescriptionFile, jiraDescriptionJsonFile, jiraTaskFile, mrDescriptionFile, mrDescriptionJsonFile, planArtifacts, planFile, planJsonFile, qaFile, qaJsonFile, readyToMergeFile, reviewFile, reviewFixFile, reviewFixJsonFile, reviewJsonFile, reviewReplyFile, reviewReplyJsonFile, taskSummaryFile, taskSummaryJsonFile, } from "../artifacts.js";
2
+ import { artifactFile, bugAnalyzeArtifacts, bugAnalyzeFile, bugAnalyzeJsonFile, bugFixDesignFile, bugFixDesignJsonFile, bugFixPlanFile, bugFixPlanJsonFile, designFile, designJsonFile, gitlabReviewFile, gitlabReviewInputJsonFile, gitlabReviewJsonFile, jiraDescriptionFile, jiraDescriptionJsonFile, jiraTaskFile, mrDescriptionFile, mrDescriptionJsonFile, planArtifacts, planFile, planJsonFile, qaFile, qaJsonFile, readyToMergeFile, reviewFile, reviewFixFile, reviewFixJsonFile, reviewJsonFile, reviewReplyFile, reviewReplyJsonFile, runGoLinterResultJsonFile, runGoTestsResultJsonFile, taskSummaryFile, taskSummaryJsonFile, } from "../artifacts.js";
3
3
  import { TaskRunnerError } from "../errors.js";
4
4
  import { formatTemplate } from "../prompts.js";
5
5
  function readStepRef(segments, context, originalPath) {
@@ -144,6 +144,16 @@ function resolveArtifact(spec, context) {
144
144
  throw new TaskRunnerError("review-reply-json-file requires iteration");
145
145
  }
146
146
  return reviewReplyJsonFile(taskKey, iteration);
147
+ case "run-go-linter-result-json-file":
148
+ if (iteration === undefined) {
149
+ throw new TaskRunnerError("run-go-linter-result-json-file requires iteration");
150
+ }
151
+ return runGoLinterResultJsonFile(taskKey, iteration);
152
+ case "run-go-tests-result-json-file":
153
+ if (iteration === undefined) {
154
+ throw new TaskRunnerError("run-go-tests-result-json-file requires iteration");
155
+ }
156
+ return runGoTestsResultJsonFile(taskKey, iteration);
147
157
  case "review-reply-summary-file":
148
158
  if (iteration === undefined) {
149
159
  throw new TaskRunnerError("review-reply-summary-file requires iteration");
package/dist/prompts.js CHANGED
@@ -37,10 +37,19 @@ export const REVIEW_PROMPT_TEMPLATE = "Проведи код-ревью теку
37
37
  "Сначала запиши структурированный результат в {review_json_file} в виде объекта { summary: string, ready_to_merge: boolean, findings: [{ severity: string, title: string, description: string }] }. " +
38
38
  "Затем запиши производную markdown-версию в {review_file}. " +
39
39
  "Если ready_to_merge=true и нет блокеров, препятствующих merge - создай файл ready-to-merge.md.";
40
+ export const REVIEW_PROJECT_PROMPT_TEMPLATE = "Проведи код-ревью текущих изменений в проекте без Jira-контекста. " +
41
+ "Оцени качество изменений по текущему коду, тестам, рискам регрессий и общему инженерному качеству. " +
42
+ "Сначала запиши структурированный результат в {review_json_file} в виде объекта { summary: string, ready_to_merge: boolean, findings: [{ severity: string, title: string, description: string }] }. " +
43
+ "Затем запиши производную markdown-версию в {review_file}. " +
44
+ "Если ready_to_merge=true и нет блокеров, создай файл {ready_to_merge_file}.";
40
45
  export const REVIEW_REPLY_PROMPT_TEMPLATE = "Твой коллега провёл код-ревью и записал структурированный результат в {review_json_file}. " +
41
46
  "Используй только структурированные артефакты как source of truth: задачу в {jira_task_file}, дизайн в {design_json_file}, план в {plan_json_file} и review в {review_json_file}. " +
42
47
  "Сначала запиши структурированный ответ в {review_reply_json_file} в виде объекта { summary: string, ready_to_merge: boolean, responses: [{ finding_title: string, disposition: string, action: string }] }. " +
43
48
  "Затем запиши производную markdown-версию в {review_reply_file}.";
49
+ export const REVIEW_REPLY_PROJECT_PROMPT_TEMPLATE = "Твой коллега провёл код-ревью и записал структурированный результат в {review_json_file}. " +
50
+ "Используй review в {review_json_file} как source of truth, разберись в замечаниях и подготовь структурированный ответ. " +
51
+ "Сначала запиши структурированный ответ в {review_reply_json_file} в виде объекта { summary: string, ready_to_merge: boolean, responses: [{ finding_title: string, disposition: string, action: string }] }. " +
52
+ "Затем запиши производную markdown-версию в {review_reply_file}.";
44
53
  export const REVIEW_SUMMARY_PROMPT_TEMPLATE = "Посмотри в {review_file}. " +
45
54
  "Сделай краткий список комментариев без подробностей, 3-7 пунктов. " +
46
55
  "Запиши результат в {review_summary_file}.";
@@ -56,8 +65,13 @@ export const REVIEW_FIX_PROMPT_TEMPLATE = "Используй только ст
56
65
  export const TASK_SUMMARY_PROMPT_TEMPLATE = "Посмотри в {jira_task_file}. " +
57
66
  "Сделай краткое резюме задачи, на 1-2 абзаца. " +
58
67
  "Сначала запиши source-of-truth JSON в {task_summary_json_file} в виде объекта { summary: string }, затем markdown-версию в {task_summary_file}.";
59
- export const RUN_TESTS_LOOP_FIX_PROMPT_TEMPLATE = "Запусти ./run_tests.sh, проанализируй последнюю ошибку проверки, исправь код и подготовь изменения так, чтобы следующий прогон run_tests.sh прошёл успешно.";
60
- export const RUN_LINTER_LOOP_FIX_PROMPT_TEMPLATE = "Запусти ./run_linter.sh, проанализируй последнюю ошибку линтера или генерации, исправь код и подготовь изменения так, чтобы следующий прогон run_linter.sh прошёл успешно.";
68
+ export const JIRA_DESCRIPTION_PROMPT_TEMPLATE = "Посмотри задачу в {jira_task_file}. " +
69
+ "Проанализируй код и оформи краткое описание для Jira, упомяни ключевые точки, модели данных, сервисы, REST-методы. " +
70
+ "Сначала запиши source-of-truth JSON в {jira_description_json_file} в виде объекта { summary: string }, затем markdown-версию в {jira_description_file}.";
71
+ export const RUN_GO_TESTS_LOOP_FIX_PROMPT_TEMPLATE = "Используй структурированный результат последнего запуска run_go_tests.py из {tests_result_json_file} как source of truth. " +
72
+ "Проанализируй последнюю ошибку проверки, исправь код и подготовь изменения так, чтобы следующий прогон run_go_tests.py прошёл успешно.";
73
+ export const RUN_GO_LINTER_LOOP_FIX_PROMPT_TEMPLATE = "Используй структурированный результат последнего запуска run_go_linter.py из {linter_result_json_file} как source of truth. " +
74
+ "Проанализируй последнюю ошибку линтера или генерации, исправь код и подготовь изменения так, чтобы следующий прогон run_go_linter.py прошёл успешно.";
61
75
  export const AUTO_REVIEW_FIX_EXTRA_PROMPT = "Исправлять только блокеры, критикалы и важные";
62
76
  export function formatTemplate(template, values) {
63
77
  let result = template;
package/dist/scope.js ADDED
@@ -0,0 +1,135 @@
1
+ import crypto from "node:crypto";
2
+ import process from "node:process";
3
+ import { execFileSync } from "node:child_process";
4
+ import { ensureScopeWorkspaceDir, jiraTaskFile } from "./artifacts.js";
5
+ import { TaskRunnerError } from "./errors.js";
6
+ import { buildJiraApiUrl, buildJiraBrowseUrl, extractIssueKey } from "./jira.js";
7
+ function gitOutput(args) {
8
+ try {
9
+ const output = execFileSync("git", args, {
10
+ cwd: process.cwd(),
11
+ encoding: "utf8",
12
+ stdio: ["ignore", "pipe", "ignore"],
13
+ });
14
+ const trimmed = output.trim();
15
+ return trimmed.length > 0 ? trimmed : null;
16
+ }
17
+ catch {
18
+ return null;
19
+ }
20
+ }
21
+ function shortHash(input) {
22
+ return crypto.createHash("sha1").update(input).digest("hex").slice(0, 8);
23
+ }
24
+ export function sanitizeScopeName(value) {
25
+ const normalized = value
26
+ .trim()
27
+ .toLowerCase()
28
+ .replaceAll(/[^a-z0-9._@-]+/g, "-")
29
+ .replaceAll(/-+/g, "-")
30
+ .replaceAll(/^-|-$/g, "");
31
+ if (!normalized) {
32
+ throw new TaskRunnerError("Scope name is empty after sanitization. Use letters, digits, '.', '_', '-' or '@'.");
33
+ }
34
+ return normalized;
35
+ }
36
+ export function detectGitBranchName() {
37
+ const branchName = gitOutput(["rev-parse", "--abbrev-ref", "HEAD"]);
38
+ if (!branchName) {
39
+ return null;
40
+ }
41
+ if (branchName === "HEAD") {
42
+ return null;
43
+ }
44
+ return branchName;
45
+ }
46
+ export function detectProjectRoot() {
47
+ return gitOutput(["rev-parse", "--show-toplevel"]) ?? process.cwd();
48
+ }
49
+ export function buildProjectScopeKey(explicitScope) {
50
+ const projectRoot = detectProjectRoot();
51
+ const worktreeHash = shortHash(projectRoot);
52
+ if (explicitScope?.trim()) {
53
+ return {
54
+ scopeKey: sanitizeScopeName(explicitScope),
55
+ gitBranchName: detectGitBranchName(),
56
+ worktreeHash,
57
+ projectRoot,
58
+ };
59
+ }
60
+ const branchName = detectGitBranchName();
61
+ const branchSlug = sanitizeScopeName(branchName ?? "detached-head");
62
+ return {
63
+ scopeKey: `${branchSlug}@${worktreeHash}`,
64
+ gitBranchName: branchName,
65
+ worktreeHash,
66
+ projectRoot,
67
+ };
68
+ }
69
+ function parseTaskScope(jiraRef) {
70
+ return {
71
+ jiraRef,
72
+ jiraIssueKey: extractIssueKey(jiraRef),
73
+ jiraBrowseUrl: buildJiraBrowseUrl(jiraRef),
74
+ jiraApiUrl: buildJiraApiUrl(jiraRef),
75
+ };
76
+ }
77
+ export function resolveTaskScope(jiraRef, explicitScope) {
78
+ const parsedTaskScope = parseTaskScope(jiraRef);
79
+ const scopeKey = explicitScope?.trim() ? sanitizeScopeName(explicitScope) : parsedTaskScope.jiraIssueKey;
80
+ ensureScopeWorkspaceDir(scopeKey);
81
+ return {
82
+ scopeType: "task",
83
+ scopeKey,
84
+ jiraRef: parsedTaskScope.jiraRef,
85
+ jiraIssueKey: parsedTaskScope.jiraIssueKey,
86
+ jiraBrowseUrl: parsedTaskScope.jiraBrowseUrl,
87
+ jiraApiUrl: parsedTaskScope.jiraApiUrl,
88
+ jiraTaskFile: jiraTaskFile(scopeKey),
89
+ };
90
+ }
91
+ export function resolveProjectScope(explicitScope) {
92
+ const { scopeKey, gitBranchName, worktreeHash, projectRoot } = buildProjectScopeKey(explicitScope);
93
+ ensureScopeWorkspaceDir(scopeKey);
94
+ return {
95
+ scopeType: "project",
96
+ scopeKey,
97
+ gitBranchName,
98
+ worktreeHash,
99
+ projectRoot,
100
+ };
101
+ }
102
+ export function buildJiraTaskInputForm() {
103
+ return {
104
+ formId: "jira-task-input",
105
+ title: "Jira Task",
106
+ description: "Укажи Jira issue key или browse URL для task-driven flow.",
107
+ submitLabel: "Continue",
108
+ fields: [
109
+ {
110
+ id: "jira_ref",
111
+ type: "text",
112
+ label: "Jira issue key or browse URL",
113
+ help: "Например: DEMO-3288 или https://jira.example.ru/browse/DEMO-3288",
114
+ required: true,
115
+ },
116
+ ],
117
+ };
118
+ }
119
+ export async function requestTaskScope(requestUserInput) {
120
+ const result = await requestUserInput(buildJiraTaskInputForm());
121
+ const jiraRef = String(result.values.jira_ref ?? "").trim();
122
+ if (!jiraRef) {
123
+ throw new TaskRunnerError("Jira issue key or browse URL is required.");
124
+ }
125
+ const parsedTaskScope = parseTaskScope(jiraRef);
126
+ return {
127
+ scopeType: "task",
128
+ scopeKey: parsedTaskScope.jiraIssueKey,
129
+ jiraRef: parsedTaskScope.jiraRef,
130
+ jiraIssueKey: parsedTaskScope.jiraIssueKey,
131
+ jiraBrowseUrl: parsedTaskScope.jiraBrowseUrl,
132
+ jiraApiUrl: parsedTaskScope.jiraApiUrl,
133
+ jiraTaskFile: jiraTaskFile(parsedTaskScope.jiraIssueKey),
134
+ };
135
+ }
@@ -0,0 +1,407 @@
1
+ {
2
+ "bug-analysis/v1": {
3
+ "type": "object",
4
+ "properties": {
5
+ "summary": { "type": "string", "nonEmpty": true },
6
+ "suspected_root_cause": {
7
+ "type": "object",
8
+ "properties": {
9
+ "hypothesis": { "type": "string", "nonEmpty": true },
10
+ "confidence": { "type": "string", "nonEmpty": true }
11
+ },
12
+ "required": ["hypothesis", "confidence"]
13
+ },
14
+ "reproduction_steps": {
15
+ "type": "array",
16
+ "items": { "type": "string", "nonEmpty": true },
17
+ "minItems": 1
18
+ },
19
+ "affected_components": {
20
+ "type": "array",
21
+ "items": { "type": "string", "nonEmpty": true },
22
+ "minItems": 1
23
+ },
24
+ "evidence": {
25
+ "type": "array",
26
+ "items": { "type": "string", "nonEmpty": true },
27
+ "minItems": 1
28
+ },
29
+ "risks": {
30
+ "type": "array",
31
+ "items": { "type": "string", "nonEmpty": true }
32
+ },
33
+ "open_questions": {
34
+ "type": "array",
35
+ "items": { "type": "string", "nonEmpty": true }
36
+ }
37
+ },
38
+ "required": [
39
+ "summary",
40
+ "suspected_root_cause",
41
+ "reproduction_steps",
42
+ "affected_components",
43
+ "evidence",
44
+ "risks",
45
+ "open_questions"
46
+ ]
47
+ },
48
+ "bug-fix-design/v1": {
49
+ "anyOf": [
50
+ {
51
+ "type": "object",
52
+ "properties": {
53
+ "summary": { "type": "string", "nonEmpty": true },
54
+ "goals": {
55
+ "type": "array",
56
+ "items": { "type": "string", "nonEmpty": true },
57
+ "minItems": 1
58
+ },
59
+ "non_goals": {
60
+ "type": "array",
61
+ "items": { "type": "string", "nonEmpty": true }
62
+ },
63
+ "components": {
64
+ "type": "array",
65
+ "items": { "type": "string", "nonEmpty": true },
66
+ "minItems": 1
67
+ },
68
+ "decisions": {
69
+ "type": "array",
70
+ "items": {
71
+ "type": "object",
72
+ "properties": {
73
+ "component": { "type": "string", "nonEmpty": true },
74
+ "decision": { "type": "string", "nonEmpty": true },
75
+ "rationale": { "type": "string", "nonEmpty": true }
76
+ },
77
+ "required": ["component", "decision", "rationale"]
78
+ },
79
+ "minItems": 1
80
+ },
81
+ "risks": {
82
+ "type": "array",
83
+ "items": { "type": "string", "nonEmpty": true }
84
+ },
85
+ "open_questions": {
86
+ "type": "array",
87
+ "items": { "type": "string", "nonEmpty": true }
88
+ }
89
+ },
90
+ "required": ["summary", "goals", "non_goals", "components", "decisions", "risks", "open_questions"]
91
+ },
92
+ {
93
+ "type": "object",
94
+ "properties": {
95
+ "summary": { "type": "string", "nonEmpty": true },
96
+ "goals": {
97
+ "type": "array",
98
+ "items": { "type": "string", "nonEmpty": true },
99
+ "minItems": 1
100
+ },
101
+ "non_goals": {
102
+ "type": "array",
103
+ "items": { "type": "string", "nonEmpty": true }
104
+ },
105
+ "target_components": {
106
+ "type": "array",
107
+ "items": { "type": "string", "nonEmpty": true },
108
+ "minItems": 1
109
+ },
110
+ "proposed_changes": {
111
+ "type": "array",
112
+ "items": {
113
+ "type": "object",
114
+ "properties": {
115
+ "component": { "type": "string", "nonEmpty": true },
116
+ "change": { "type": "string", "nonEmpty": true },
117
+ "rationale": { "type": "string", "nonEmpty": true }
118
+ },
119
+ "required": ["component", "change", "rationale"]
120
+ },
121
+ "minItems": 1
122
+ },
123
+ "alternatives_considered": {
124
+ "type": "array",
125
+ "items": {
126
+ "type": "object",
127
+ "properties": {
128
+ "option": { "type": "string", "nonEmpty": true },
129
+ "decision": { "type": "string", "nonEmpty": true },
130
+ "rationale": { "type": "string", "nonEmpty": true }
131
+ },
132
+ "required": ["option", "decision", "rationale"]
133
+ }
134
+ },
135
+ "risks": {
136
+ "type": "array",
137
+ "items": { "type": "string", "nonEmpty": true }
138
+ },
139
+ "validation_strategy": {
140
+ "type": "array",
141
+ "items": { "type": "string", "nonEmpty": true },
142
+ "minItems": 1
143
+ }
144
+ },
145
+ "required": [
146
+ "summary",
147
+ "goals",
148
+ "non_goals",
149
+ "target_components",
150
+ "proposed_changes",
151
+ "alternatives_considered",
152
+ "risks",
153
+ "validation_strategy"
154
+ ]
155
+ }
156
+ ]
157
+ },
158
+ "bug-fix-plan/v1": {
159
+ "type": "object",
160
+ "properties": {
161
+ "summary": { "type": "string", "nonEmpty": true },
162
+ "prerequisites": {
163
+ "type": "array",
164
+ "items": { "type": "string", "nonEmpty": true }
165
+ },
166
+ "implementation_steps": {
167
+ "type": "array",
168
+ "items": {
169
+ "type": "object",
170
+ "properties": {
171
+ "id": { "type": "string", "nonEmpty": true },
172
+ "title": { "type": "string", "nonEmpty": true },
173
+ "details": { "type": "string", "nonEmpty": true }
174
+ },
175
+ "required": ["id", "title", "details"]
176
+ },
177
+ "minItems": 1
178
+ },
179
+ "tests": {
180
+ "type": "array",
181
+ "items": { "type": "string", "nonEmpty": true },
182
+ "minItems": 1
183
+ },
184
+ "rollout_notes": {
185
+ "type": "array",
186
+ "items": { "type": "string", "nonEmpty": true }
187
+ }
188
+ },
189
+ "required": ["summary", "prerequisites", "implementation_steps", "tests", "rollout_notes"]
190
+ },
191
+ "gitlab-review/v1": {
192
+ "type": "object",
193
+ "properties": {
194
+ "summary": { "type": "string", "nonEmpty": true },
195
+ "merge_request_url": { "type": "string", "nonEmpty": true },
196
+ "project_path": { "type": "string", "nonEmpty": true },
197
+ "merge_request_iid": { "type": "number" },
198
+ "fetched_at": { "type": "string", "nonEmpty": true },
199
+ "comments": {
200
+ "type": "array",
201
+ "items": {
202
+ "type": "object",
203
+ "properties": {
204
+ "id": { "type": "string", "nonEmpty": true },
205
+ "discussion_id": { "type": "string", "nonEmpty": true },
206
+ "body": { "type": "string", "nonEmpty": true },
207
+ "author": { "type": "string", "nonEmpty": true },
208
+ "created_at": { "type": "string", "nonEmpty": true },
209
+ "file_path": {
210
+ "anyOf": [
211
+ { "type": "null" },
212
+ { "type": "string", "nonEmpty": true }
213
+ ]
214
+ }
215
+ },
216
+ "required": ["id", "discussion_id", "body", "author", "created_at"]
217
+ }
218
+ }
219
+ },
220
+ "required": ["summary", "merge_request_url", "project_path", "merge_request_iid", "fetched_at", "comments"]
221
+ },
222
+ "implementation-design/v1": {
223
+ "type": "object",
224
+ "properties": {
225
+ "summary": { "type": "string", "nonEmpty": true },
226
+ "goals": {
227
+ "type": "array",
228
+ "items": { "type": "string", "nonEmpty": true },
229
+ "minItems": 1
230
+ },
231
+ "non_goals": {
232
+ "type": "array",
233
+ "items": { "type": "string", "nonEmpty": true }
234
+ },
235
+ "components": {
236
+ "type": "array",
237
+ "items": { "type": "string", "nonEmpty": true },
238
+ "minItems": 1
239
+ },
240
+ "decisions": {
241
+ "type": "array",
242
+ "items": {
243
+ "type": "object",
244
+ "properties": {
245
+ "component": { "type": "string", "nonEmpty": true },
246
+ "decision": { "type": "string", "nonEmpty": true },
247
+ "rationale": { "type": "string", "nonEmpty": true }
248
+ },
249
+ "required": ["component", "decision", "rationale"]
250
+ },
251
+ "minItems": 1
252
+ },
253
+ "risks": {
254
+ "type": "array",
255
+ "items": { "type": "string", "nonEmpty": true }
256
+ },
257
+ "open_questions": {
258
+ "type": "array",
259
+ "items": { "type": "string", "nonEmpty": true }
260
+ }
261
+ },
262
+ "required": ["summary", "goals", "non_goals", "components", "decisions", "risks", "open_questions"]
263
+ },
264
+ "implementation-plan/v1": {
265
+ "type": "object",
266
+ "properties": {
267
+ "summary": { "type": "string", "nonEmpty": true },
268
+ "prerequisites": {
269
+ "type": "array",
270
+ "items": { "type": "string", "nonEmpty": true }
271
+ },
272
+ "implementation_steps": {
273
+ "type": "array",
274
+ "items": {
275
+ "type": "object",
276
+ "properties": {
277
+ "id": { "type": "string", "nonEmpty": true },
278
+ "title": { "type": "string", "nonEmpty": true },
279
+ "details": { "type": "string", "nonEmpty": true }
280
+ },
281
+ "required": ["id", "title", "details"]
282
+ },
283
+ "minItems": 1
284
+ },
285
+ "tests": {
286
+ "type": "array",
287
+ "items": { "type": "string", "nonEmpty": true },
288
+ "minItems": 1
289
+ },
290
+ "rollout_notes": {
291
+ "type": "array",
292
+ "items": { "type": "string", "nonEmpty": true }
293
+ }
294
+ },
295
+ "required": ["summary", "prerequisites", "implementation_steps", "tests", "rollout_notes"]
296
+ },
297
+ "jira-description/v1": {
298
+ "type": "object",
299
+ "properties": {
300
+ "summary": { "type": "string", "nonEmpty": true }
301
+ },
302
+ "required": ["summary"]
303
+ },
304
+ "mr-description/v1": {
305
+ "type": "object",
306
+ "properties": {
307
+ "summary": { "type": "string", "nonEmpty": true }
308
+ },
309
+ "required": ["summary"]
310
+ },
311
+ "qa-plan/v1": {
312
+ "type": "object",
313
+ "properties": {
314
+ "summary": { "type": "string", "nonEmpty": true },
315
+ "test_scenarios": {
316
+ "type": "array",
317
+ "items": {
318
+ "type": "object",
319
+ "properties": {
320
+ "id": { "type": "string", "nonEmpty": true },
321
+ "title": { "type": "string", "nonEmpty": true },
322
+ "expected_result": { "type": "string", "nonEmpty": true }
323
+ },
324
+ "required": ["id", "title", "expected_result"]
325
+ },
326
+ "minItems": 1
327
+ },
328
+ "non_functional_checks": {
329
+ "type": "array",
330
+ "items": { "type": "string", "nonEmpty": true }
331
+ }
332
+ },
333
+ "required": ["summary", "test_scenarios", "non_functional_checks"]
334
+ },
335
+ "review-findings/v1": {
336
+ "type": "object",
337
+ "properties": {
338
+ "summary": { "type": "string", "nonEmpty": true },
339
+ "ready_to_merge": { "type": "boolean" },
340
+ "findings": {
341
+ "type": "array",
342
+ "items": {
343
+ "type": "object",
344
+ "properties": {
345
+ "severity": { "type": "string", "nonEmpty": true },
346
+ "title": { "type": "string", "nonEmpty": true },
347
+ "description": { "type": "string", "nonEmpty": true }
348
+ },
349
+ "required": ["severity", "title", "description"]
350
+ }
351
+ }
352
+ },
353
+ "required": ["summary", "ready_to_merge", "findings"]
354
+ },
355
+ "review-fix-report/v1": {
356
+ "type": "object",
357
+ "properties": {
358
+ "summary": { "type": "string", "nonEmpty": true },
359
+ "completed_actions": {
360
+ "type": "array",
361
+ "items": { "type": "string", "nonEmpty": true },
362
+ "minItems": 1
363
+ },
364
+ "validation_steps": {
365
+ "type": "array",
366
+ "items": { "type": "string", "nonEmpty": true }
367
+ }
368
+ },
369
+ "required": ["summary", "completed_actions", "validation_steps"]
370
+ },
371
+ "review-reply/v1": {
372
+ "type": "object",
373
+ "properties": {
374
+ "summary": { "type": "string", "nonEmpty": true },
375
+ "responses": {
376
+ "type": "array",
377
+ "items": {
378
+ "type": "object",
379
+ "properties": {
380
+ "finding_title": { "type": "string", "nonEmpty": true },
381
+ "disposition": { "type": "string", "nonEmpty": true },
382
+ "action": { "type": "string", "nonEmpty": true }
383
+ },
384
+ "required": ["finding_title", "disposition", "action"]
385
+ }
386
+ },
387
+ "ready_to_merge": { "type": "boolean" }
388
+ },
389
+ "required": ["summary", "responses", "ready_to_merge"]
390
+ },
391
+ "task-summary/v1": {
392
+ "type": "object",
393
+ "properties": {
394
+ "summary": { "type": "string", "nonEmpty": true }
395
+ },
396
+ "required": ["summary"]
397
+ },
398
+ "user-input/v1": {
399
+ "type": "object",
400
+ "properties": {
401
+ "form_id": { "type": "string", "nonEmpty": true },
402
+ "submitted_at": { "type": "string", "nonEmpty": true },
403
+ "values": { "type": "object" }
404
+ },
405
+ "required": ["form_id", "submitted_at", "values"]
406
+ }
407
+ }