@h9-foundry/agentforge-cli 0.4.2 → 0.6.0
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/dist/.tsbuildinfo +1 -1
- package/dist/bin.js +7 -3
- package/dist/bin.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +247 -5
- package/dist/index.js.map +1 -1
- package/dist/internal/builtin-agents.d.ts.map +1 -1
- package/dist/internal/builtin-agents.js +959 -1
- package/dist/internal/builtin-agents.js.map +1 -1
- package/package.json +8 -8
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { agentManifestSchema, agentOutputSchema, designArtifactSchema, implementationArtifactSchema, implementationInventorySchema, qaRequestSchema, planningArtifactSchema } from "@h9-foundry/agentforge-schemas";
|
|
2
4
|
const contextCollectorAgent = {
|
|
3
5
|
manifest: agentManifestSchema.parse({
|
|
4
6
|
version: 1,
|
|
@@ -22,6 +24,12 @@ const contextCollectorAgent = {
|
|
|
22
24
|
sections: ["repo", "changes", "context"],
|
|
23
25
|
minimalContext: true
|
|
24
26
|
},
|
|
27
|
+
catalog: {
|
|
28
|
+
domain: "foundation",
|
|
29
|
+
supportLevel: "official",
|
|
30
|
+
maturity: "mvp",
|
|
31
|
+
trustScope: "official-core-only"
|
|
32
|
+
},
|
|
25
33
|
trust: {
|
|
26
34
|
tier: "core",
|
|
27
35
|
source: "official",
|
|
@@ -49,6 +57,929 @@ const contextCollectorAgent = {
|
|
|
49
57
|
});
|
|
50
58
|
}
|
|
51
59
|
};
|
|
60
|
+
function isRecord(value) {
|
|
61
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
62
|
+
}
|
|
63
|
+
function asStringArray(value) {
|
|
64
|
+
return Array.isArray(value) ? value.filter((entry) => typeof entry === "string") : [];
|
|
65
|
+
}
|
|
66
|
+
function parsePackageScripts(packageJsonPath) {
|
|
67
|
+
if (!existsSync(packageJsonPath)) {
|
|
68
|
+
return {};
|
|
69
|
+
}
|
|
70
|
+
const parsed = JSON.parse(readFileSync(packageJsonPath, "utf8"));
|
|
71
|
+
if (!isRecord(parsed) || !isRecord(parsed.scripts)) {
|
|
72
|
+
return {};
|
|
73
|
+
}
|
|
74
|
+
return Object.fromEntries(Object.entries(parsed.scripts).filter((entry) => typeof entry[1] === "string"));
|
|
75
|
+
}
|
|
76
|
+
const allowedValidationScriptNames = new Set(["test", "lint", "typecheck", "build", "build:packages", "release:verify"]);
|
|
77
|
+
function normalizeRequestedCommand(command) {
|
|
78
|
+
return command.trim().replace(/\s+/g, " ");
|
|
79
|
+
}
|
|
80
|
+
function buildValidationCommand(packageManager, scriptName, packageName) {
|
|
81
|
+
if (packageName) {
|
|
82
|
+
return `${packageManager} --filter ${packageName} ${scriptName}`;
|
|
83
|
+
}
|
|
84
|
+
return `${packageManager} ${scriptName}`;
|
|
85
|
+
}
|
|
86
|
+
function derivePackageScope(pathValue) {
|
|
87
|
+
const segments = pathValue.split("/").filter(Boolean);
|
|
88
|
+
if (segments.length < 2) {
|
|
89
|
+
return undefined;
|
|
90
|
+
}
|
|
91
|
+
const [topLevel, scope] = segments;
|
|
92
|
+
if (topLevel === "packages" || topLevel === "agents" || topLevel === "adapters") {
|
|
93
|
+
return `${topLevel}/${scope}`;
|
|
94
|
+
}
|
|
95
|
+
return undefined;
|
|
96
|
+
}
|
|
97
|
+
function getWorkflowInput(stateSlice, key) {
|
|
98
|
+
if (!isRecord(stateSlice.workflowInputs)) {
|
|
99
|
+
return undefined;
|
|
100
|
+
}
|
|
101
|
+
return stateSlice.workflowInputs[key];
|
|
102
|
+
}
|
|
103
|
+
function buildArtifactEnvelopeBase(state, summary, inputRefs, issueRefs) {
|
|
104
|
+
return {
|
|
105
|
+
schemaVersion: state.version,
|
|
106
|
+
workflow: {
|
|
107
|
+
name: state.workflow
|
|
108
|
+
},
|
|
109
|
+
source: {
|
|
110
|
+
sourceType: "workflow-run",
|
|
111
|
+
runId: state.runId,
|
|
112
|
+
inputRefs: [...inputRefs],
|
|
113
|
+
issueRefs: [...issueRefs]
|
|
114
|
+
},
|
|
115
|
+
status: "complete",
|
|
116
|
+
generatedAt: new Date().toISOString(),
|
|
117
|
+
repo: {
|
|
118
|
+
root: state.repo.root,
|
|
119
|
+
name: state.repo.name,
|
|
120
|
+
branch: state.repo.branch
|
|
121
|
+
},
|
|
122
|
+
provenance: {
|
|
123
|
+
generatedBy: "agentforge-runtime",
|
|
124
|
+
schemaVersion: state.version,
|
|
125
|
+
executionEnvironment: state.context.ciExecution ? "ci" : "local",
|
|
126
|
+
repoRoot: state.repo.root
|
|
127
|
+
},
|
|
128
|
+
redaction: {
|
|
129
|
+
applied: true,
|
|
130
|
+
strategyVersion: "1.0.0",
|
|
131
|
+
categories: ["github-token", "api-key", "aws-key", "bearer-token", "password", "private-key"]
|
|
132
|
+
},
|
|
133
|
+
auditLink: {
|
|
134
|
+
entryIds: [],
|
|
135
|
+
findingIds: [],
|
|
136
|
+
proposedActionIds: []
|
|
137
|
+
},
|
|
138
|
+
summary
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
const planningIntakeAgent = {
|
|
142
|
+
manifest: agentManifestSchema.parse({
|
|
143
|
+
version: 1,
|
|
144
|
+
name: "planning-intake",
|
|
145
|
+
displayName: "Planning Intake",
|
|
146
|
+
category: "planning",
|
|
147
|
+
runtime: {
|
|
148
|
+
minVersion: "0.1.0",
|
|
149
|
+
kind: "deterministic"
|
|
150
|
+
},
|
|
151
|
+
permissions: {
|
|
152
|
+
model: false,
|
|
153
|
+
network: false,
|
|
154
|
+
tools: [],
|
|
155
|
+
readPaths: [".agentops/requests/**"],
|
|
156
|
+
writePaths: []
|
|
157
|
+
},
|
|
158
|
+
inputs: ["workflowInputs", "repo"],
|
|
159
|
+
outputs: ["summary", "metadata"],
|
|
160
|
+
contextPolicy: {
|
|
161
|
+
sections: ["workflowInputs", "repo", "context"],
|
|
162
|
+
minimalContext: true
|
|
163
|
+
},
|
|
164
|
+
catalog: {
|
|
165
|
+
domain: "plan",
|
|
166
|
+
supportLevel: "internal",
|
|
167
|
+
maturity: "mvp",
|
|
168
|
+
trustScope: "official-core-only"
|
|
169
|
+
},
|
|
170
|
+
trust: {
|
|
171
|
+
tier: "core",
|
|
172
|
+
source: "official",
|
|
173
|
+
reviewed: true
|
|
174
|
+
}
|
|
175
|
+
}),
|
|
176
|
+
outputSchema: agentOutputSchema,
|
|
177
|
+
async execute({ stateSlice }) {
|
|
178
|
+
const planningRequest = getWorkflowInput(stateSlice, "planningRequest");
|
|
179
|
+
const requestFile = getWorkflowInput(stateSlice, "requestFile");
|
|
180
|
+
if (!planningRequest) {
|
|
181
|
+
throw new Error("planning-discovery requires a validated planning request before runtime execution.");
|
|
182
|
+
}
|
|
183
|
+
return agentOutputSchema.parse({
|
|
184
|
+
summary: `Loaded planning request from ${requestFile ?? ".agentops/requests/planning.yaml"}.`,
|
|
185
|
+
findings: [],
|
|
186
|
+
proposedActions: [],
|
|
187
|
+
lifecycleArtifacts: [],
|
|
188
|
+
requestedTools: [],
|
|
189
|
+
blockedActionFlags: [],
|
|
190
|
+
metadata: {
|
|
191
|
+
requestFile,
|
|
192
|
+
problemStatement: planningRequest.problemStatement,
|
|
193
|
+
goals: planningRequest.goals,
|
|
194
|
+
constraints: planningRequest.constraints,
|
|
195
|
+
issueRefs: planningRequest.issueRefs,
|
|
196
|
+
pathHints: planningRequest.pathHints
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
};
|
|
201
|
+
const planningAnalystAgent = {
|
|
202
|
+
manifest: agentManifestSchema.parse({
|
|
203
|
+
version: 1,
|
|
204
|
+
name: "planning-analyst",
|
|
205
|
+
displayName: "Planning Analyst",
|
|
206
|
+
category: "planning",
|
|
207
|
+
runtime: {
|
|
208
|
+
minVersion: "0.1.0",
|
|
209
|
+
kind: "reasoning"
|
|
210
|
+
},
|
|
211
|
+
permissions: {
|
|
212
|
+
model: true,
|
|
213
|
+
network: false,
|
|
214
|
+
tools: [],
|
|
215
|
+
readPaths: ["**/*"],
|
|
216
|
+
writePaths: []
|
|
217
|
+
},
|
|
218
|
+
inputs: ["workflowInputs", "repo", "changes", "agentResults"],
|
|
219
|
+
outputs: ["lifecycleArtifacts"],
|
|
220
|
+
contextPolicy: {
|
|
221
|
+
sections: ["workflowInputs", "repo", "changes", "agentResults"],
|
|
222
|
+
minimalContext: true
|
|
223
|
+
},
|
|
224
|
+
catalog: {
|
|
225
|
+
domain: "plan",
|
|
226
|
+
supportLevel: "official",
|
|
227
|
+
maturity: "mvp",
|
|
228
|
+
trustScope: "official-core-only"
|
|
229
|
+
},
|
|
230
|
+
trust: {
|
|
231
|
+
tier: "core",
|
|
232
|
+
source: "official",
|
|
233
|
+
reviewed: true
|
|
234
|
+
}
|
|
235
|
+
}),
|
|
236
|
+
outputSchema: agentOutputSchema,
|
|
237
|
+
async execute({ state, stateSlice }) {
|
|
238
|
+
const planningRequest = getWorkflowInput(stateSlice, "planningRequest");
|
|
239
|
+
const requestFile = getWorkflowInput(stateSlice, "requestFile");
|
|
240
|
+
if (!planningRequest) {
|
|
241
|
+
throw new Error("planning-discovery requires a validated planning request before planning analysis.");
|
|
242
|
+
}
|
|
243
|
+
const topLevelHints = [...new Set(planningRequest.pathHints.map((hint) => hint.split("/")[0] ?? hint).filter(Boolean))];
|
|
244
|
+
const objectives = planningRequest.goals.length > 0
|
|
245
|
+
? planningRequest.goals
|
|
246
|
+
: [`Produce a bounded plan for: ${planningRequest.problemStatement}`];
|
|
247
|
+
const inScope = planningRequest.pathHints.length > 0
|
|
248
|
+
? planningRequest.pathHints
|
|
249
|
+
: ["Repository discovery", "Planning brief synthesis", "Next-step recommendation"];
|
|
250
|
+
const outOfScope = ["Source-file mutation", "Network-backed intake", "Architecture/design decisions"];
|
|
251
|
+
const openQuestions = [
|
|
252
|
+
...(planningRequest.issueRefs.length === 0 ? ["Should this planning work be linked to a tracked issue?"] : []),
|
|
253
|
+
...(planningRequest.pathHints.length === 0 ? ["Which repository paths should be prioritized in follow-up design work?"] : [])
|
|
254
|
+
];
|
|
255
|
+
const candidateWorkstreams = topLevelHints.length > 0 ? topLevelHints : state.changes.impactedPaths;
|
|
256
|
+
const risks = [
|
|
257
|
+
...(planningRequest.pathHints.length === 0 ? ["Impact area is broad because no path hints were supplied."] : []),
|
|
258
|
+
...(planningRequest.assumptions.length === 0 ? ["Planning assumptions were not supplied and may need confirmation."] : [])
|
|
259
|
+
];
|
|
260
|
+
const summary = `Planning brief scoped ${objectives.length} objective(s) for ${state.repo.name}.`;
|
|
261
|
+
const planningBrief = planningArtifactSchema.parse({
|
|
262
|
+
...buildArtifactEnvelopeBase(state, summary, [requestFile ?? ".agentops/requests/planning.yaml"], planningRequest.issueRefs),
|
|
263
|
+
artifactKind: "planning-brief",
|
|
264
|
+
lifecycleDomain: "plan",
|
|
265
|
+
workflow: {
|
|
266
|
+
name: state.workflow,
|
|
267
|
+
displayName: "Planning And Discovery"
|
|
268
|
+
},
|
|
269
|
+
payload: {
|
|
270
|
+
problemStatement: planningRequest.problemStatement,
|
|
271
|
+
objectives,
|
|
272
|
+
constraints: planningRequest.constraints,
|
|
273
|
+
assumptions: planningRequest.assumptions,
|
|
274
|
+
inScope,
|
|
275
|
+
outOfScope,
|
|
276
|
+
recommendedNextSteps: [
|
|
277
|
+
"Review the generated planning brief and refine missing constraints or path hints.",
|
|
278
|
+
"Open or update follow-on implementation issues for the accepted planning scope.",
|
|
279
|
+
"Use the planning brief as input to `architecture-design-review` for the next design slice."
|
|
280
|
+
],
|
|
281
|
+
stakeholders: planningRequest.issueRefs.length > 0 ? ["Maintainers linked to the referenced issues"] : [],
|
|
282
|
+
risks,
|
|
283
|
+
openQuestions,
|
|
284
|
+
candidateWorkstreams,
|
|
285
|
+
linkedIssues: planningRequest.issueRefs
|
|
286
|
+
}
|
|
287
|
+
});
|
|
288
|
+
return agentOutputSchema.parse({
|
|
289
|
+
summary,
|
|
290
|
+
findings: [],
|
|
291
|
+
proposedActions: [],
|
|
292
|
+
lifecycleArtifacts: [planningBrief],
|
|
293
|
+
requestedTools: [],
|
|
294
|
+
blockedActionFlags: [],
|
|
295
|
+
confidence: 0.8,
|
|
296
|
+
metadata: {
|
|
297
|
+
deterministicContext: {
|
|
298
|
+
pathHints: planningRequest.pathHints,
|
|
299
|
+
impactedPaths: state.changes.impactedPaths,
|
|
300
|
+
repository: state.repo.name
|
|
301
|
+
},
|
|
302
|
+
synthesizedPlanning: {
|
|
303
|
+
recommendedNextSteps: planningBrief.payload.recommendedNextSteps,
|
|
304
|
+
openQuestions
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
};
|
|
310
|
+
const designIntakeAgent = {
|
|
311
|
+
manifest: agentManifestSchema.parse({
|
|
312
|
+
version: 1,
|
|
313
|
+
name: "design-intake",
|
|
314
|
+
displayName: "Design Intake",
|
|
315
|
+
category: "design",
|
|
316
|
+
runtime: {
|
|
317
|
+
minVersion: "0.1.0",
|
|
318
|
+
kind: "deterministic"
|
|
319
|
+
},
|
|
320
|
+
permissions: {
|
|
321
|
+
model: false,
|
|
322
|
+
network: false,
|
|
323
|
+
tools: [],
|
|
324
|
+
readPaths: [".agentops/requests/**", ".agentops/runs/**"],
|
|
325
|
+
writePaths: []
|
|
326
|
+
},
|
|
327
|
+
inputs: ["workflowInputs", "repo"],
|
|
328
|
+
outputs: ["summary", "metadata"],
|
|
329
|
+
contextPolicy: {
|
|
330
|
+
sections: ["workflowInputs", "repo", "context"],
|
|
331
|
+
minimalContext: true
|
|
332
|
+
},
|
|
333
|
+
catalog: {
|
|
334
|
+
domain: "design",
|
|
335
|
+
supportLevel: "internal",
|
|
336
|
+
maturity: "mvp",
|
|
337
|
+
trustScope: "official-core-only"
|
|
338
|
+
},
|
|
339
|
+
trust: {
|
|
340
|
+
tier: "core",
|
|
341
|
+
source: "official",
|
|
342
|
+
reviewed: true
|
|
343
|
+
}
|
|
344
|
+
}),
|
|
345
|
+
outputSchema: agentOutputSchema,
|
|
346
|
+
async execute({ stateSlice }) {
|
|
347
|
+
const designRequest = getWorkflowInput(stateSlice, "designRequest");
|
|
348
|
+
const planningBrief = getWorkflowInput(stateSlice, "planningBrief");
|
|
349
|
+
const requestFile = getWorkflowInput(stateSlice, "requestFile");
|
|
350
|
+
if (!designRequest || !planningBrief) {
|
|
351
|
+
throw new Error("architecture-design-review requires a validated design request and planning brief before runtime execution.");
|
|
352
|
+
}
|
|
353
|
+
return agentOutputSchema.parse({
|
|
354
|
+
summary: `Loaded design request from ${requestFile ?? ".agentops/requests/design.yaml"} with planning brief ${designRequest.planningBriefRef}.`,
|
|
355
|
+
findings: [],
|
|
356
|
+
proposedActions: [],
|
|
357
|
+
lifecycleArtifacts: [],
|
|
358
|
+
requestedTools: [],
|
|
359
|
+
blockedActionFlags: [],
|
|
360
|
+
metadata: {
|
|
361
|
+
requestFile,
|
|
362
|
+
planningBriefRef: designRequest.planningBriefRef,
|
|
363
|
+
decisionTarget: designRequest.decisionTarget,
|
|
364
|
+
planningObjectives: planningBrief.payload.objectives
|
|
365
|
+
}
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
};
|
|
369
|
+
const designInventoryAgent = {
|
|
370
|
+
manifest: agentManifestSchema.parse({
|
|
371
|
+
version: 1,
|
|
372
|
+
name: "design-inventory",
|
|
373
|
+
displayName: "Design Inventory",
|
|
374
|
+
category: "design",
|
|
375
|
+
runtime: {
|
|
376
|
+
minVersion: "0.1.0",
|
|
377
|
+
kind: "deterministic"
|
|
378
|
+
},
|
|
379
|
+
permissions: {
|
|
380
|
+
model: false,
|
|
381
|
+
network: false,
|
|
382
|
+
tools: ["filesystem.list-files"],
|
|
383
|
+
readPaths: ["**/*"],
|
|
384
|
+
writePaths: []
|
|
385
|
+
},
|
|
386
|
+
inputs: ["workflowInputs", "repo", "changes"],
|
|
387
|
+
outputs: ["summary", "metadata"],
|
|
388
|
+
contextPolicy: {
|
|
389
|
+
sections: ["workflowInputs", "repo", "changes"],
|
|
390
|
+
minimalContext: true
|
|
391
|
+
},
|
|
392
|
+
catalog: {
|
|
393
|
+
domain: "design",
|
|
394
|
+
supportLevel: "internal",
|
|
395
|
+
maturity: "mvp",
|
|
396
|
+
trustScope: "official-core-only"
|
|
397
|
+
},
|
|
398
|
+
trust: {
|
|
399
|
+
tier: "core",
|
|
400
|
+
source: "official",
|
|
401
|
+
reviewed: true
|
|
402
|
+
}
|
|
403
|
+
}),
|
|
404
|
+
outputSchema: agentOutputSchema,
|
|
405
|
+
async execute({ stateSlice, invokeTool }) {
|
|
406
|
+
const designRequest = getWorkflowInput(stateSlice, "designRequest");
|
|
407
|
+
const planningBrief = getWorkflowInput(stateSlice, "planningBrief");
|
|
408
|
+
if (!designRequest || !planningBrief) {
|
|
409
|
+
throw new Error("architecture-design-review requires deterministic inventory inputs before design analysis.");
|
|
410
|
+
}
|
|
411
|
+
const candidatePaths = [...new Set([...designRequest.pathHints, ...(stateSlice.changes?.impactedPaths ?? [])])];
|
|
412
|
+
const repoRoot = stateSlice.repo?.root;
|
|
413
|
+
const inspectedPaths = candidatePaths
|
|
414
|
+
.filter((pathHint) => {
|
|
415
|
+
if (!pathHint) {
|
|
416
|
+
return false;
|
|
417
|
+
}
|
|
418
|
+
const finalSegment = pathHint.split("/").at(-1) ?? pathHint;
|
|
419
|
+
if (pathHint !== ".agentops" && finalSegment.includes(".")) {
|
|
420
|
+
return false;
|
|
421
|
+
}
|
|
422
|
+
if (!repoRoot) {
|
|
423
|
+
return true;
|
|
424
|
+
}
|
|
425
|
+
return existsSync(join(repoRoot, pathHint));
|
|
426
|
+
})
|
|
427
|
+
.slice(0, 8);
|
|
428
|
+
const listedEntries = [];
|
|
429
|
+
for (const pathHint of inspectedPaths) {
|
|
430
|
+
const listed = await invokeTool({
|
|
431
|
+
tool: "filesystem.list-files",
|
|
432
|
+
input: { path: pathHint },
|
|
433
|
+
requestedBy: "design-inventory",
|
|
434
|
+
requestedAt: new Date().toISOString()
|
|
435
|
+
});
|
|
436
|
+
if (listed.status === "success" && isRecord(listed.output) && Array.isArray(listed.output.entries)) {
|
|
437
|
+
for (const entry of listed.output.entries) {
|
|
438
|
+
if (typeof entry === "string") {
|
|
439
|
+
listedEntries.push(`${pathHint}/${entry}`.replaceAll("//", "/"));
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
const impactedInterfaces = [
|
|
445
|
+
...new Set([...candidatePaths, ...listedEntries].filter((entry) => entry.endsWith("src/index.ts") || entry.endsWith("package.json") || entry.endsWith("agent.manifest.json")))
|
|
446
|
+
];
|
|
447
|
+
const schemaSurfaces = [
|
|
448
|
+
...new Set([...candidatePaths, ...listedEntries].filter((entry) => entry.includes("packages/schemas") || entry.includes("schema") || entry.endsWith(".yaml")))
|
|
449
|
+
];
|
|
450
|
+
const policySurfaces = [
|
|
451
|
+
...new Set([...candidatePaths, ...listedEntries].filter((entry) => entry.includes("policy") || entry.includes("packages/policy-engine") || entry.includes(".agentops/policy.yaml")))
|
|
452
|
+
];
|
|
453
|
+
return agentOutputSchema.parse({
|
|
454
|
+
summary: `Collected deterministic design inventory across ${inspectedPaths.length} candidate path(s).`,
|
|
455
|
+
findings: [],
|
|
456
|
+
proposedActions: [],
|
|
457
|
+
lifecycleArtifacts: [],
|
|
458
|
+
requestedTools: [],
|
|
459
|
+
blockedActionFlags: [],
|
|
460
|
+
metadata: {
|
|
461
|
+
inspectedPaths,
|
|
462
|
+
impactedInterfaces,
|
|
463
|
+
schemaSurfaces,
|
|
464
|
+
policySurfaces,
|
|
465
|
+
planningScope: planningBrief.payload.inScope
|
|
466
|
+
}
|
|
467
|
+
});
|
|
468
|
+
}
|
|
469
|
+
};
|
|
470
|
+
const implementationIntakeAgent = {
|
|
471
|
+
manifest: agentManifestSchema.parse({
|
|
472
|
+
version: 1,
|
|
473
|
+
name: "implementation-intake",
|
|
474
|
+
displayName: "Implementation Intake",
|
|
475
|
+
category: "implementation",
|
|
476
|
+
runtime: {
|
|
477
|
+
minVersion: "0.1.0",
|
|
478
|
+
kind: "deterministic"
|
|
479
|
+
},
|
|
480
|
+
permissions: {
|
|
481
|
+
model: false,
|
|
482
|
+
network: false,
|
|
483
|
+
tools: [],
|
|
484
|
+
readPaths: [".agentops/requests/**", ".agentops/runs/**"],
|
|
485
|
+
writePaths: []
|
|
486
|
+
},
|
|
487
|
+
inputs: ["workflowInputs", "repo"],
|
|
488
|
+
outputs: ["summary", "metadata"],
|
|
489
|
+
contextPolicy: {
|
|
490
|
+
sections: ["workflowInputs", "repo", "context"],
|
|
491
|
+
minimalContext: true
|
|
492
|
+
},
|
|
493
|
+
catalog: {
|
|
494
|
+
domain: "build",
|
|
495
|
+
supportLevel: "internal",
|
|
496
|
+
maturity: "mvp",
|
|
497
|
+
trustScope: "official-core-only"
|
|
498
|
+
},
|
|
499
|
+
trust: {
|
|
500
|
+
tier: "core",
|
|
501
|
+
source: "official",
|
|
502
|
+
reviewed: true
|
|
503
|
+
}
|
|
504
|
+
}),
|
|
505
|
+
outputSchema: agentOutputSchema,
|
|
506
|
+
async execute({ stateSlice }) {
|
|
507
|
+
const implementationRequest = getWorkflowInput(stateSlice, "implementationRequest");
|
|
508
|
+
const designRecord = getWorkflowInput(stateSlice, "designRecord");
|
|
509
|
+
const requestFile = getWorkflowInput(stateSlice, "requestFile");
|
|
510
|
+
if (!implementationRequest || !designRecord) {
|
|
511
|
+
throw new Error("implementation-proposal requires a validated implementation request and design record before runtime execution.");
|
|
512
|
+
}
|
|
513
|
+
return agentOutputSchema.parse({
|
|
514
|
+
summary: `Loaded implementation request from ${requestFile ?? ".agentops/requests/implementation.yaml"} with design record ${implementationRequest.designRecordRef}.`,
|
|
515
|
+
findings: [],
|
|
516
|
+
proposedActions: [],
|
|
517
|
+
lifecycleArtifacts: [],
|
|
518
|
+
requestedTools: [],
|
|
519
|
+
blockedActionFlags: [],
|
|
520
|
+
metadata: {
|
|
521
|
+
requestFile,
|
|
522
|
+
designRecordRef: implementationRequest.designRecordRef,
|
|
523
|
+
implementationGoal: implementationRequest.implementationGoal,
|
|
524
|
+
approvalMode: implementationRequest.approvalMode,
|
|
525
|
+
targetPaths: implementationRequest.targetPaths,
|
|
526
|
+
validationCommands: implementationRequest.validationCommands,
|
|
527
|
+
designDecisionSummary: designRecord.payload.decisionSummary
|
|
528
|
+
}
|
|
529
|
+
});
|
|
530
|
+
}
|
|
531
|
+
};
|
|
532
|
+
const qaIntakeAgent = {
|
|
533
|
+
manifest: agentManifestSchema.parse({
|
|
534
|
+
version: 1,
|
|
535
|
+
name: "qa-intake",
|
|
536
|
+
displayName: "QA Intake",
|
|
537
|
+
category: "qa",
|
|
538
|
+
runtime: {
|
|
539
|
+
minVersion: "0.1.0",
|
|
540
|
+
kind: "deterministic"
|
|
541
|
+
},
|
|
542
|
+
permissions: {
|
|
543
|
+
model: false,
|
|
544
|
+
network: false,
|
|
545
|
+
tools: [],
|
|
546
|
+
readPaths: [".agentops/requests/**", ".agentops/runs/**"],
|
|
547
|
+
writePaths: []
|
|
548
|
+
},
|
|
549
|
+
inputs: ["workflowInputs", "repo"],
|
|
550
|
+
outputs: ["summary", "metadata"],
|
|
551
|
+
contextPolicy: {
|
|
552
|
+
sections: ["workflowInputs", "repo", "context"],
|
|
553
|
+
minimalContext: true
|
|
554
|
+
},
|
|
555
|
+
catalog: {
|
|
556
|
+
domain: "test",
|
|
557
|
+
supportLevel: "internal",
|
|
558
|
+
maturity: "mvp",
|
|
559
|
+
trustScope: "official-core-only"
|
|
560
|
+
},
|
|
561
|
+
trust: {
|
|
562
|
+
tier: "core",
|
|
563
|
+
source: "official",
|
|
564
|
+
reviewed: true
|
|
565
|
+
}
|
|
566
|
+
}),
|
|
567
|
+
outputSchema: agentOutputSchema,
|
|
568
|
+
async execute({ stateSlice }) {
|
|
569
|
+
const qaRequest = getWorkflowInput(stateSlice, "qaRequest");
|
|
570
|
+
const requestFile = getWorkflowInput(stateSlice, "requestFile");
|
|
571
|
+
if (!qaRequest) {
|
|
572
|
+
throw new Error("qa-review requires a validated QA request before runtime execution.");
|
|
573
|
+
}
|
|
574
|
+
const targetType = qaRequest.targetRef.endsWith("bundle.json")
|
|
575
|
+
? "artifact-bundle"
|
|
576
|
+
: qaRequest.targetRef.endsWith(".xml") || qaRequest.targetRef.endsWith(".json") || qaRequest.targetRef.endsWith(".log")
|
|
577
|
+
? "validation-output"
|
|
578
|
+
: "local-reference";
|
|
579
|
+
return agentOutputSchema.parse({
|
|
580
|
+
summary: `Loaded QA request from ${requestFile ?? ".agentops/requests/qa.yaml"} targeting ${qaRequest.targetRef}.`,
|
|
581
|
+
findings: [],
|
|
582
|
+
proposedActions: [],
|
|
583
|
+
lifecycleArtifacts: [],
|
|
584
|
+
requestedTools: [],
|
|
585
|
+
blockedActionFlags: [],
|
|
586
|
+
metadata: {
|
|
587
|
+
...qaRequestSchema.parse({
|
|
588
|
+
...qaRequest,
|
|
589
|
+
evidenceSources: [...new Set([qaRequest.targetRef, ...qaRequest.evidenceSources])]
|
|
590
|
+
}),
|
|
591
|
+
targetType
|
|
592
|
+
}
|
|
593
|
+
});
|
|
594
|
+
}
|
|
595
|
+
};
|
|
596
|
+
const implementationInventoryAgent = {
|
|
597
|
+
manifest: agentManifestSchema.parse({
|
|
598
|
+
version: 1,
|
|
599
|
+
name: "implementation-inventory",
|
|
600
|
+
displayName: "Implementation Inventory",
|
|
601
|
+
category: "implementation",
|
|
602
|
+
runtime: {
|
|
603
|
+
minVersion: "0.1.0",
|
|
604
|
+
kind: "deterministic"
|
|
605
|
+
},
|
|
606
|
+
permissions: {
|
|
607
|
+
model: false,
|
|
608
|
+
network: false,
|
|
609
|
+
tools: [],
|
|
610
|
+
readPaths: ["**/*"],
|
|
611
|
+
writePaths: []
|
|
612
|
+
},
|
|
613
|
+
inputs: ["workflowInputs", "repo", "changes"],
|
|
614
|
+
outputs: ["summary", "metadata"],
|
|
615
|
+
contextPolicy: {
|
|
616
|
+
sections: ["workflowInputs", "repo", "changes"],
|
|
617
|
+
minimalContext: true
|
|
618
|
+
},
|
|
619
|
+
catalog: {
|
|
620
|
+
domain: "build",
|
|
621
|
+
supportLevel: "internal",
|
|
622
|
+
maturity: "mvp",
|
|
623
|
+
trustScope: "official-core-only"
|
|
624
|
+
},
|
|
625
|
+
trust: {
|
|
626
|
+
tier: "core",
|
|
627
|
+
source: "official",
|
|
628
|
+
reviewed: true
|
|
629
|
+
}
|
|
630
|
+
}),
|
|
631
|
+
outputSchema: agentOutputSchema,
|
|
632
|
+
async execute({ stateSlice }) {
|
|
633
|
+
const implementationRequest = getWorkflowInput(stateSlice, "implementationRequest");
|
|
634
|
+
const designRecord = getWorkflowInput(stateSlice, "designRecord");
|
|
635
|
+
if (!implementationRequest || !designRecord) {
|
|
636
|
+
throw new Error("implementation-proposal requires deterministic inventory inputs before proposal analysis.");
|
|
637
|
+
}
|
|
638
|
+
const repoRoot = stateSlice.repo?.root;
|
|
639
|
+
const packageManager = stateSlice.repo?.packageManager || "pnpm";
|
|
640
|
+
const candidatePaths = [
|
|
641
|
+
...new Set([
|
|
642
|
+
...implementationRequest.targetPaths,
|
|
643
|
+
...designRecord.payload.interfacesImpacted,
|
|
644
|
+
...designRecord.payload.schemaChangesNeeded,
|
|
645
|
+
...designRecord.payload.policyChangesNeeded
|
|
646
|
+
])
|
|
647
|
+
];
|
|
648
|
+
const resolvedAffectedPaths = candidatePaths.filter((pathValue) => {
|
|
649
|
+
if (!pathValue) {
|
|
650
|
+
return false;
|
|
651
|
+
}
|
|
652
|
+
if (!repoRoot) {
|
|
653
|
+
return true;
|
|
654
|
+
}
|
|
655
|
+
return existsSync(join(repoRoot, pathValue));
|
|
656
|
+
});
|
|
657
|
+
const affectedPackages = [...new Set(resolvedAffectedPaths.map(derivePackageScope).filter((value) => Boolean(value)))];
|
|
658
|
+
const entrypoints = [
|
|
659
|
+
...new Set(resolvedAffectedPaths.filter((pathValue) => pathValue.endsWith("src/index.ts") || pathValue.endsWith("package.json") || pathValue.endsWith("agent.manifest.json")))
|
|
660
|
+
];
|
|
661
|
+
const schemaSurfaces = [...new Set(resolvedAffectedPaths.filter((pathValue) => pathValue.includes("schema")))];
|
|
662
|
+
const policySurfaces = [
|
|
663
|
+
...new Set(resolvedAffectedPaths.filter((pathValue) => pathValue.includes("policy") || pathValue.includes(".agentops/policy.yaml")))
|
|
664
|
+
];
|
|
665
|
+
const discoveredValidationCommands = [];
|
|
666
|
+
const registerScripts = (packageJsonPath, source, packageName) => {
|
|
667
|
+
const scripts = parsePackageScripts(packageJsonPath);
|
|
668
|
+
for (const scriptName of Object.keys(scripts)) {
|
|
669
|
+
const command = buildValidationCommand(packageManager, scriptName, packageName);
|
|
670
|
+
discoveredValidationCommands.push({
|
|
671
|
+
command,
|
|
672
|
+
source,
|
|
673
|
+
classification: allowedValidationScriptNames.has(scriptName) ? "approval_required" : "deny",
|
|
674
|
+
reason: allowedValidationScriptNames.has(scriptName)
|
|
675
|
+
? "Discovered from a bounded repository script; execution would still require approval."
|
|
676
|
+
: "Command is not in the bounded allowlist for implementation validation."
|
|
677
|
+
});
|
|
678
|
+
}
|
|
679
|
+
};
|
|
680
|
+
if (repoRoot) {
|
|
681
|
+
registerScripts(join(repoRoot, "package.json"), "package-script");
|
|
682
|
+
for (const packageScope of affectedPackages) {
|
|
683
|
+
const packageJsonPath = join(repoRoot, packageScope, "package.json");
|
|
684
|
+
if (!existsSync(packageJsonPath)) {
|
|
685
|
+
continue;
|
|
686
|
+
}
|
|
687
|
+
const parsed = JSON.parse(readFileSync(packageJsonPath, "utf8"));
|
|
688
|
+
const packageName = isRecord(parsed) && typeof parsed.name === "string" ? parsed.name : packageScope;
|
|
689
|
+
registerScripts(packageJsonPath, "workspace-script", packageName);
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
const normalizedRequestedCommands = implementationRequest.validationCommands.map(normalizeRequestedCommand);
|
|
693
|
+
const allowlistedCommands = new Set(discoveredValidationCommands
|
|
694
|
+
.filter((entry) => entry.classification === "approval_required")
|
|
695
|
+
.map((entry) => entry.command));
|
|
696
|
+
for (const requestedCommand of normalizedRequestedCommands) {
|
|
697
|
+
if (!allowlistedCommands.has(requestedCommand)) {
|
|
698
|
+
throw new Error(`Implementation request contains non-allowlisted validation command: ${requestedCommand}`);
|
|
699
|
+
}
|
|
700
|
+
discoveredValidationCommands.push({
|
|
701
|
+
command: requestedCommand,
|
|
702
|
+
source: "request",
|
|
703
|
+
classification: "approval_required",
|
|
704
|
+
reason: "Requested command matches a discovered allowlisted validation script."
|
|
705
|
+
});
|
|
706
|
+
}
|
|
707
|
+
const inventory = implementationInventorySchema.parse({
|
|
708
|
+
requestedTargetPaths: implementationRequest.targetPaths,
|
|
709
|
+
resolvedAffectedPaths,
|
|
710
|
+
affectedPackages,
|
|
711
|
+
entrypoints,
|
|
712
|
+
schemaSurfaces,
|
|
713
|
+
policySurfaces,
|
|
714
|
+
discoveredValidationCommands
|
|
715
|
+
});
|
|
716
|
+
return agentOutputSchema.parse({
|
|
717
|
+
summary: `Collected deterministic implementation inventory across ${inventory.resolvedAffectedPaths.length} path(s) and ${inventory.discoveredValidationCommands.length} validation command(s).`,
|
|
718
|
+
findings: [],
|
|
719
|
+
proposedActions: [],
|
|
720
|
+
lifecycleArtifacts: [],
|
|
721
|
+
requestedTools: [],
|
|
722
|
+
blockedActionFlags: [],
|
|
723
|
+
metadata: inventory
|
|
724
|
+
});
|
|
725
|
+
}
|
|
726
|
+
};
|
|
727
|
+
const implementationPlannerAgent = {
|
|
728
|
+
manifest: agentManifestSchema.parse({
|
|
729
|
+
version: 1,
|
|
730
|
+
name: "implementation-planner",
|
|
731
|
+
displayName: "Implementation Planner",
|
|
732
|
+
category: "implementation",
|
|
733
|
+
runtime: {
|
|
734
|
+
minVersion: "0.1.0",
|
|
735
|
+
kind: "reasoning"
|
|
736
|
+
},
|
|
737
|
+
permissions: {
|
|
738
|
+
model: true,
|
|
739
|
+
network: false,
|
|
740
|
+
tools: [],
|
|
741
|
+
readPaths: ["**/*"],
|
|
742
|
+
writePaths: []
|
|
743
|
+
},
|
|
744
|
+
inputs: ["workflowInputs", "repo", "changes", "agentResults"],
|
|
745
|
+
outputs: ["lifecycleArtifacts"],
|
|
746
|
+
contextPolicy: {
|
|
747
|
+
sections: ["workflowInputs", "repo", "changes", "agentResults"],
|
|
748
|
+
minimalContext: true
|
|
749
|
+
},
|
|
750
|
+
catalog: {
|
|
751
|
+
domain: "build",
|
|
752
|
+
supportLevel: "official",
|
|
753
|
+
maturity: "mvp",
|
|
754
|
+
trustScope: "official-core-only"
|
|
755
|
+
},
|
|
756
|
+
trust: {
|
|
757
|
+
tier: "core",
|
|
758
|
+
source: "official",
|
|
759
|
+
reviewed: true
|
|
760
|
+
}
|
|
761
|
+
}),
|
|
762
|
+
outputSchema: agentOutputSchema,
|
|
763
|
+
async execute({ state, stateSlice }) {
|
|
764
|
+
const implementationRequest = getWorkflowInput(stateSlice, "implementationRequest");
|
|
765
|
+
const designRecord = getWorkflowInput(stateSlice, "designRecord");
|
|
766
|
+
const requestFile = getWorkflowInput(stateSlice, "requestFile");
|
|
767
|
+
if (!implementationRequest || !designRecord) {
|
|
768
|
+
throw new Error("implementation-proposal requires validated implementation inputs before proposal analysis.");
|
|
769
|
+
}
|
|
770
|
+
const inventoryMetadata = implementationInventorySchema.safeParse(stateSlice.agentResults?.inventory?.metadata);
|
|
771
|
+
const inventory = inventoryMetadata.success ? inventoryMetadata.data : undefined;
|
|
772
|
+
const normalizedAffectedPaths = inventory && inventory.resolvedAffectedPaths.length > 0
|
|
773
|
+
? inventory.resolvedAffectedPaths
|
|
774
|
+
: [
|
|
775
|
+
...new Set([
|
|
776
|
+
...implementationRequest.targetPaths,
|
|
777
|
+
...designRecord.payload.interfacesImpacted,
|
|
778
|
+
...designRecord.payload.schemaChangesNeeded,
|
|
779
|
+
...designRecord.payload.policyChangesNeeded
|
|
780
|
+
])
|
|
781
|
+
];
|
|
782
|
+
const finalAffectedPaths = normalizedAffectedPaths.length > 0
|
|
783
|
+
? normalizedAffectedPaths
|
|
784
|
+
: ["Repository paths still need deterministic build-surface confirmation."];
|
|
785
|
+
const proposedChanges = [
|
|
786
|
+
`Prepare a bounded implementation plan for ${implementationRequest.implementationGoal}.`,
|
|
787
|
+
...finalAffectedPaths.slice(0, 5).map((pathValue) => `Plan targeted edits for ${pathValue}.`)
|
|
788
|
+
];
|
|
789
|
+
const selectedCommands = inventory
|
|
790
|
+
? inventory.discoveredValidationCommands.filter((entry) => entry.classification === "approval_required" &&
|
|
791
|
+
(implementationRequest.validationCommands.length === 0 || entry.source === "request"))
|
|
792
|
+
: [];
|
|
793
|
+
const validationPlan = selectedCommands.length > 0
|
|
794
|
+
? selectedCommands.map((entry) => `Command \`${entry.command}\` is available but approval-required before execution.`)
|
|
795
|
+
: ["Confirm allowlisted validation commands in the next deterministic implementation slice before execution."];
|
|
796
|
+
const approvalRequiredSteps = implementationRequest.approvalMode === "apply-capable"
|
|
797
|
+
? [
|
|
798
|
+
"Any future patch application requires explicit approval before execution.",
|
|
799
|
+
"Any future build or validation execution requires approval after allowlist review."
|
|
800
|
+
]
|
|
801
|
+
: ["The default path remains proposal-only; any patch or build execution requires a separate approved workflow."];
|
|
802
|
+
const risks = [
|
|
803
|
+
...(implementationRequest.targetPaths.length === 0
|
|
804
|
+
? ["Target paths were not supplied, so affected surfaces may still broaden after deterministic discovery."]
|
|
805
|
+
: []),
|
|
806
|
+
...(implementationRequest.validationCommands.length === 0
|
|
807
|
+
? ["Validation commands are not yet specified and will need deterministic allowlist confirmation later."]
|
|
808
|
+
: [])
|
|
809
|
+
];
|
|
810
|
+
const openQuestions = [
|
|
811
|
+
...(implementationRequest.constraints.length === 0
|
|
812
|
+
? ["Which additional implementation constraints should be captured before execution work begins?"]
|
|
813
|
+
: []),
|
|
814
|
+
...(designRecord.payload.policyChangesNeeded.length > 0
|
|
815
|
+
? ["Do the policy surfaces identified in the design record require a separate approval review?"]
|
|
816
|
+
: [])
|
|
817
|
+
];
|
|
818
|
+
const summary = `Implementation proposal prepared for ${implementationRequest.implementationGoal}.`;
|
|
819
|
+
const implementationProposal = implementationArtifactSchema.parse({
|
|
820
|
+
...buildArtifactEnvelopeBase(state, summary, [requestFile ?? ".agentops/requests/implementation.yaml", implementationRequest.designRecordRef], designRecord.source.issueRefs),
|
|
821
|
+
artifactKind: "implementation-proposal",
|
|
822
|
+
lifecycleDomain: "build",
|
|
823
|
+
workflow: {
|
|
824
|
+
name: state.workflow,
|
|
825
|
+
displayName: "Implementation Proposal"
|
|
826
|
+
},
|
|
827
|
+
payload: {
|
|
828
|
+
designRecordRef: implementationRequest.designRecordRef,
|
|
829
|
+
implementationGoal: implementationRequest.implementationGoal,
|
|
830
|
+
affectedPaths: finalAffectedPaths,
|
|
831
|
+
proposedChanges,
|
|
832
|
+
validationPlan,
|
|
833
|
+
approvalRequiredSteps,
|
|
834
|
+
risks,
|
|
835
|
+
openQuestions
|
|
836
|
+
}
|
|
837
|
+
});
|
|
838
|
+
return agentOutputSchema.parse({
|
|
839
|
+
summary,
|
|
840
|
+
findings: [],
|
|
841
|
+
proposedActions: [],
|
|
842
|
+
lifecycleArtifacts: [implementationProposal],
|
|
843
|
+
requestedTools: [],
|
|
844
|
+
blockedActionFlags: [],
|
|
845
|
+
confidence: 0.76,
|
|
846
|
+
metadata: {
|
|
847
|
+
deterministicInputs: {
|
|
848
|
+
targetPaths: implementationRequest.targetPaths,
|
|
849
|
+
validationCommands: implementationRequest.validationCommands,
|
|
850
|
+
constraints: implementationRequest.constraints,
|
|
851
|
+
designInterfaces: designRecord.payload.interfacesImpacted,
|
|
852
|
+
inventory: inventory ?? null
|
|
853
|
+
},
|
|
854
|
+
synthesizedProposal: {
|
|
855
|
+
affectedPaths: finalAffectedPaths,
|
|
856
|
+
approvalRequiredSteps,
|
|
857
|
+
openQuestions
|
|
858
|
+
}
|
|
859
|
+
}
|
|
860
|
+
});
|
|
861
|
+
}
|
|
862
|
+
};
|
|
863
|
+
const designAnalystAgent = {
|
|
864
|
+
manifest: agentManifestSchema.parse({
|
|
865
|
+
version: 1,
|
|
866
|
+
name: "design-analyst",
|
|
867
|
+
displayName: "Design Analyst",
|
|
868
|
+
category: "design",
|
|
869
|
+
runtime: {
|
|
870
|
+
minVersion: "0.1.0",
|
|
871
|
+
kind: "reasoning"
|
|
872
|
+
},
|
|
873
|
+
permissions: {
|
|
874
|
+
model: true,
|
|
875
|
+
network: false,
|
|
876
|
+
tools: [],
|
|
877
|
+
readPaths: ["**/*"],
|
|
878
|
+
writePaths: []
|
|
879
|
+
},
|
|
880
|
+
inputs: ["workflowInputs", "repo", "changes", "agentResults"],
|
|
881
|
+
outputs: ["lifecycleArtifacts"],
|
|
882
|
+
contextPolicy: {
|
|
883
|
+
sections: ["workflowInputs", "repo", "changes", "agentResults"],
|
|
884
|
+
minimalContext: true
|
|
885
|
+
},
|
|
886
|
+
catalog: {
|
|
887
|
+
domain: "design",
|
|
888
|
+
supportLevel: "official",
|
|
889
|
+
maturity: "mvp",
|
|
890
|
+
trustScope: "official-core-only"
|
|
891
|
+
},
|
|
892
|
+
trust: {
|
|
893
|
+
tier: "core",
|
|
894
|
+
source: "official",
|
|
895
|
+
reviewed: true
|
|
896
|
+
}
|
|
897
|
+
}),
|
|
898
|
+
outputSchema: agentOutputSchema,
|
|
899
|
+
async execute({ state, stateSlice }) {
|
|
900
|
+
const designRequest = getWorkflowInput(stateSlice, "designRequest");
|
|
901
|
+
const planningBrief = getWorkflowInput(stateSlice, "planningBrief");
|
|
902
|
+
const requestFile = getWorkflowInput(stateSlice, "requestFile");
|
|
903
|
+
if (!designRequest || !planningBrief) {
|
|
904
|
+
throw new Error("architecture-design-review requires validated design inputs before design analysis.");
|
|
905
|
+
}
|
|
906
|
+
const inventoryMetadata = isRecord(stateSlice.agentResults?.inventory?.metadata) ? stateSlice.agentResults.inventory.metadata : {};
|
|
907
|
+
const impactedInterfaces = asStringArray(inventoryMetadata.impactedInterfaces);
|
|
908
|
+
const schemaSurfaces = asStringArray(inventoryMetadata.schemaSurfaces);
|
|
909
|
+
const policySurfaces = asStringArray(inventoryMetadata.policySurfaces);
|
|
910
|
+
const optionsConsidered = designRequest.alternatives.length > 0
|
|
911
|
+
? designRequest.alternatives.map((option) => ({
|
|
912
|
+
option,
|
|
913
|
+
summary: `Evaluate ${option} against the validated planning brief and bounded repository inventory.`
|
|
914
|
+
}))
|
|
915
|
+
: [
|
|
916
|
+
{
|
|
917
|
+
option: "single-workflow-pass",
|
|
918
|
+
summary: "Keep the workflow narrow by validating intake, inventory, and design analysis in one local pass."
|
|
919
|
+
},
|
|
920
|
+
{
|
|
921
|
+
option: "split-manual-design-doc",
|
|
922
|
+
summary: "Rely on ad hoc notes outside the workflow and treat design as manual-only."
|
|
923
|
+
}
|
|
924
|
+
];
|
|
925
|
+
const chosenApproach = optionsConsidered[0]?.option ?? "single-workflow-pass";
|
|
926
|
+
const followUpWork = [
|
|
927
|
+
"Translate the accepted design into bounded implementation issues before coding begins.",
|
|
928
|
+
"Use the deterministic inventory to drive follow-up schema, policy, or interface validation.",
|
|
929
|
+
"Keep the planning brief and design record linked when implementation and QA workflows land."
|
|
930
|
+
];
|
|
931
|
+
const summary = `Design record prepared for ${designRequest.decisionTarget}.`;
|
|
932
|
+
const designRecord = designArtifactSchema.parse({
|
|
933
|
+
...buildArtifactEnvelopeBase(state, summary, [requestFile ?? ".agentops/requests/design.yaml", designRequest.planningBriefRef], planningBrief.source.issueRefs),
|
|
934
|
+
artifactKind: "design-record",
|
|
935
|
+
lifecycleDomain: "design",
|
|
936
|
+
workflow: {
|
|
937
|
+
name: state.workflow,
|
|
938
|
+
displayName: "Architecture And Design Review"
|
|
939
|
+
},
|
|
940
|
+
payload: {
|
|
941
|
+
decisionSummary: designRequest.decisionTarget,
|
|
942
|
+
context: `Planning brief summary: ${planningBrief.summary}`,
|
|
943
|
+
optionsConsidered,
|
|
944
|
+
chosenApproach,
|
|
945
|
+
tradeOffs: [
|
|
946
|
+
"Keeping the workflow local-first limits external specification ingestion in the MVP.",
|
|
947
|
+
"Deterministic inventory remains heuristic until deeper static-analysis surfaces land."
|
|
948
|
+
],
|
|
949
|
+
risks: [
|
|
950
|
+
...(impactedInterfaces.length === 0 ? ["No impacted interfaces were identified from the provided path hints."] : []),
|
|
951
|
+
...(schemaSurfaces.length === 0 ? ["Schema touch points may still need manual confirmation."] : [])
|
|
952
|
+
],
|
|
953
|
+
followUpWork,
|
|
954
|
+
interfacesImpacted: impactedInterfaces,
|
|
955
|
+
schemaChangesNeeded: schemaSurfaces,
|
|
956
|
+
policyChangesNeeded: policySurfaces,
|
|
957
|
+
migrationNotes: [],
|
|
958
|
+
compatibilityNotes: ["Requires a valid planning-brief bundle reference from planning-discovery."]
|
|
959
|
+
}
|
|
960
|
+
});
|
|
961
|
+
return agentOutputSchema.parse({
|
|
962
|
+
summary,
|
|
963
|
+
findings: [],
|
|
964
|
+
proposedActions: [],
|
|
965
|
+
lifecycleArtifacts: [designRecord],
|
|
966
|
+
requestedTools: [],
|
|
967
|
+
blockedActionFlags: [],
|
|
968
|
+
confidence: 0.78,
|
|
969
|
+
metadata: {
|
|
970
|
+
deterministicInventory: {
|
|
971
|
+
impactedInterfaces,
|
|
972
|
+
schemaSurfaces,
|
|
973
|
+
policySurfaces
|
|
974
|
+
},
|
|
975
|
+
synthesizedDecision: {
|
|
976
|
+
chosenApproach,
|
|
977
|
+
followUpWork
|
|
978
|
+
}
|
|
979
|
+
}
|
|
980
|
+
});
|
|
981
|
+
}
|
|
982
|
+
};
|
|
52
983
|
const codeReviewAgent = {
|
|
53
984
|
manifest: agentManifestSchema.parse({
|
|
54
985
|
version: 1,
|
|
@@ -72,6 +1003,12 @@ const codeReviewAgent = {
|
|
|
72
1003
|
sections: ["repo", "changes", "agentResults"],
|
|
73
1004
|
minimalContext: true
|
|
74
1005
|
},
|
|
1006
|
+
catalog: {
|
|
1007
|
+
domain: "review",
|
|
1008
|
+
supportLevel: "official",
|
|
1009
|
+
maturity: "mvp",
|
|
1010
|
+
trustScope: "official-core-only"
|
|
1011
|
+
},
|
|
75
1012
|
trust: {
|
|
76
1013
|
tier: "core",
|
|
77
1014
|
source: "official",
|
|
@@ -158,6 +1095,12 @@ const securityAuditAgent = {
|
|
|
158
1095
|
sections: ["repo", "changes", "policy"],
|
|
159
1096
|
minimalContext: true
|
|
160
1097
|
},
|
|
1098
|
+
catalog: {
|
|
1099
|
+
domain: "security",
|
|
1100
|
+
supportLevel: "official",
|
|
1101
|
+
maturity: "mvp",
|
|
1102
|
+
trustScope: "official-core-only"
|
|
1103
|
+
},
|
|
161
1104
|
trust: {
|
|
162
1105
|
tier: "core",
|
|
163
1106
|
source: "official",
|
|
@@ -222,6 +1165,12 @@ const testGenerationAgent = {
|
|
|
222
1165
|
sections: ["changes"],
|
|
223
1166
|
minimalContext: true
|
|
224
1167
|
},
|
|
1168
|
+
catalog: {
|
|
1169
|
+
domain: "test",
|
|
1170
|
+
supportLevel: "official",
|
|
1171
|
+
maturity: "mvp",
|
|
1172
|
+
trustScope: "official-core-only"
|
|
1173
|
+
},
|
|
225
1174
|
trust: {
|
|
226
1175
|
tier: "core",
|
|
227
1176
|
source: "official",
|
|
@@ -263,6 +1212,15 @@ const testGenerationAgent = {
|
|
|
263
1212
|
export function createBuiltinAgentRegistry() {
|
|
264
1213
|
return new Map([
|
|
265
1214
|
["context-collector", contextCollectorAgent],
|
|
1215
|
+
["planning-intake", planningIntakeAgent],
|
|
1216
|
+
["planning-analyst", planningAnalystAgent],
|
|
1217
|
+
["design-intake", designIntakeAgent],
|
|
1218
|
+
["design-inventory", designInventoryAgent],
|
|
1219
|
+
["implementation-intake", implementationIntakeAgent],
|
|
1220
|
+
["qa-intake", qaIntakeAgent],
|
|
1221
|
+
["implementation-inventory", implementationInventoryAgent],
|
|
1222
|
+
["implementation-planner", implementationPlannerAgent],
|
|
1223
|
+
["design-analyst", designAnalystAgent],
|
|
266
1224
|
["code-review", codeReviewAgent],
|
|
267
1225
|
["security-audit", securityAuditAgent],
|
|
268
1226
|
["test-generation", testGenerationAgent]
|