@llm-dev-ops/agentics-cli 1.5.9 → 1.5.11

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 (105) hide show
  1. package/README.md +478 -148
  2. package/dist/bundled-agents/manifest.json +1 -0
  3. package/dist/commands/phase4.d.ts.map +1 -1
  4. package/dist/commands/phase4.js +4 -2
  5. package/dist/commands/phase4.js.map +1 -1
  6. package/dist/commands/phase6.d.ts.map +1 -1
  7. package/dist/commands/phase6.js +4 -2
  8. package/dist/commands/phase6.js.map +1 -1
  9. package/dist/mcp/mcp-server.js +11 -10
  10. package/dist/mcp/mcp-server.js.map +1 -1
  11. package/dist/pipeline/auto-chain.d.ts +5 -0
  12. package/dist/pipeline/auto-chain.d.ts.map +1 -1
  13. package/dist/pipeline/auto-chain.js +131 -47
  14. package/dist/pipeline/auto-chain.js.map +1 -1
  15. package/dist/pipeline/enterprise/artifact-assembler.d.ts +64 -0
  16. package/dist/pipeline/enterprise/artifact-assembler.d.ts.map +1 -0
  17. package/dist/pipeline/enterprise/artifact-assembler.js +542 -0
  18. package/dist/pipeline/enterprise/artifact-assembler.js.map +1 -0
  19. package/dist/pipeline/enterprise/artifact-renderers.d.ts +42 -0
  20. package/dist/pipeline/enterprise/artifact-renderers.d.ts.map +1 -0
  21. package/dist/pipeline/enterprise/artifact-renderers.js +513 -0
  22. package/dist/pipeline/enterprise/artifact-renderers.js.map +1 -0
  23. package/dist/pipeline/enterprise/code-resolver.d.ts +43 -0
  24. package/dist/pipeline/enterprise/code-resolver.d.ts.map +1 -0
  25. package/dist/pipeline/enterprise/code-resolver.js +219 -0
  26. package/dist/pipeline/enterprise/code-resolver.js.map +1 -0
  27. package/dist/pipeline/enterprise/decision-graph-client.d.ts +171 -0
  28. package/dist/pipeline/enterprise/decision-graph-client.d.ts.map +1 -0
  29. package/dist/pipeline/enterprise/decision-graph-client.js +222 -0
  30. package/dist/pipeline/enterprise/decision-graph-client.js.map +1 -0
  31. package/dist/pipeline/enterprise/decision-graph-memory.d.ts +104 -0
  32. package/dist/pipeline/enterprise/decision-graph-memory.d.ts.map +1 -0
  33. package/dist/pipeline/enterprise/decision-graph-memory.js +292 -0
  34. package/dist/pipeline/enterprise/decision-graph-memory.js.map +1 -0
  35. package/dist/pipeline/enterprise/decision-graph.d.ts +237 -0
  36. package/dist/pipeline/enterprise/decision-graph.d.ts.map +1 -0
  37. package/dist/pipeline/enterprise/decision-graph.js +654 -0
  38. package/dist/pipeline/enterprise/decision-graph.js.map +1 -0
  39. package/dist/pipeline/enterprise/index.d.ts +40 -0
  40. package/dist/pipeline/enterprise/index.d.ts.map +1 -0
  41. package/dist/pipeline/enterprise/index.js +43 -0
  42. package/dist/pipeline/enterprise/index.js.map +1 -0
  43. package/dist/pipeline/enterprise/pass-executor.d.ts +33 -0
  44. package/dist/pipeline/enterprise/pass-executor.d.ts.map +1 -0
  45. package/dist/pipeline/enterprise/pass-executor.js +459 -0
  46. package/dist/pipeline/enterprise/pass-executor.js.map +1 -0
  47. package/dist/pipeline/enterprise/pass-registry.d.ts +19 -0
  48. package/dist/pipeline/enterprise/pass-registry.d.ts.map +1 -0
  49. package/dist/pipeline/enterprise/pass-registry.js +243 -0
  50. package/dist/pipeline/enterprise/pass-registry.js.map +1 -0
  51. package/dist/pipeline/enterprise/pass2-simulation.d.ts +130 -0
  52. package/dist/pipeline/enterprise/pass2-simulation.d.ts.map +1 -0
  53. package/dist/pipeline/enterprise/pass2-simulation.js +691 -0
  54. package/dist/pipeline/enterprise/pass2-simulation.js.map +1 -0
  55. package/dist/pipeline/enterprise/pass4-governance.d.ts +195 -0
  56. package/dist/pipeline/enterprise/pass4-governance.d.ts.map +1 -0
  57. package/dist/pipeline/enterprise/pass4-governance.js +748 -0
  58. package/dist/pipeline/enterprise/pass4-governance.js.map +1 -0
  59. package/dist/pipeline/enterprise/pass5-decision.d.ts +90 -0
  60. package/dist/pipeline/enterprise/pass5-decision.d.ts.map +1 -0
  61. package/dist/pipeline/enterprise/pass5-decision.js +487 -0
  62. package/dist/pipeline/enterprise/pass5-decision.js.map +1 -0
  63. package/dist/pipeline/enterprise/pass7-observability.d.ts +198 -0
  64. package/dist/pipeline/enterprise/pass7-observability.d.ts.map +1 -0
  65. package/dist/pipeline/enterprise/pass7-observability.js +636 -0
  66. package/dist/pipeline/enterprise/pass7-observability.js.map +1 -0
  67. package/dist/pipeline/enterprise/pipeline-orchestrator.d.ts +29 -0
  68. package/dist/pipeline/enterprise/pipeline-orchestrator.d.ts.map +1 -0
  69. package/dist/pipeline/enterprise/pipeline-orchestrator.js +283 -0
  70. package/dist/pipeline/enterprise/pipeline-orchestrator.js.map +1 -0
  71. package/dist/pipeline/enterprise/provenance-tracker.d.ts +135 -0
  72. package/dist/pipeline/enterprise/provenance-tracker.d.ts.map +1 -0
  73. package/dist/pipeline/enterprise/provenance-tracker.js +437 -0
  74. package/dist/pipeline/enterprise/provenance-tracker.js.map +1 -0
  75. package/dist/pipeline/enterprise/trace-middleware.d.ts +37 -0
  76. package/dist/pipeline/enterprise/trace-middleware.d.ts.map +1 -0
  77. package/dist/pipeline/enterprise/trace-middleware.js +188 -0
  78. package/dist/pipeline/enterprise/trace-middleware.js.map +1 -0
  79. package/dist/pipeline/enterprise/types.d.ts +199 -0
  80. package/dist/pipeline/enterprise/types.d.ts.map +1 -0
  81. package/dist/pipeline/enterprise/types.js +30 -0
  82. package/dist/pipeline/enterprise/types.js.map +1 -0
  83. package/dist/pipeline/phase2/phases/adr-generator.d.ts.map +1 -1
  84. package/dist/pipeline/phase2/phases/adr-generator.js +56 -8
  85. package/dist/pipeline/phase2/phases/adr-generator.js.map +1 -1
  86. package/dist/pipeline/phase3/phases/test-generator.d.ts.map +1 -1
  87. package/dist/pipeline/phase3/phases/test-generator.js +53 -0
  88. package/dist/pipeline/phase3/phases/test-generator.js.map +1 -1
  89. package/dist/pipeline/phase4/phases/deployment-generator.d.ts.map +1 -1
  90. package/dist/pipeline/phase4/phases/deployment-generator.js +147 -0
  91. package/dist/pipeline/phase4/phases/deployment-generator.js.map +1 -1
  92. package/dist/pipeline/phase4-adrs/phase4-adrs-coordinator.d.ts.map +1 -1
  93. package/dist/pipeline/phase4-adrs/phase4-adrs-coordinator.js +52 -1
  94. package/dist/pipeline/phase4-adrs/phase4-adrs-coordinator.js.map +1 -1
  95. package/dist/pipeline/phase6/phases/deployment-finalizer.d.ts.map +1 -1
  96. package/dist/pipeline/phase6/phases/deployment-finalizer.js +226 -0
  97. package/dist/pipeline/phase6/phases/deployment-finalizer.js.map +1 -1
  98. package/dist/pipeline/phase6/phases/service-registrar.d.ts +1 -1
  99. package/dist/pipeline/phase6/phases/service-registrar.d.ts.map +1 -1
  100. package/dist/pipeline/phase6/phases/service-registrar.js +47 -7
  101. package/dist/pipeline/phase6/phases/service-registrar.js.map +1 -1
  102. package/dist/pipeline/swarm-orchestrator.d.ts.map +1 -1
  103. package/dist/pipeline/swarm-orchestrator.js +47 -19
  104. package/dist/pipeline/swarm-orchestrator.js.map +1 -1
  105. package/package.json +1 -1
@@ -0,0 +1,748 @@
1
+ /**
2
+ * Pass 4 — Governance, Compliance & CostOps (ADR-036)
3
+ *
4
+ * Executes four concurrent workstreams that converge into a unified
5
+ * Governance Convergence Report stored in the DecisionGraph:
6
+ *
7
+ * Workstream A: Security & Compliance Analysis (LLM-Shield)
8
+ * Workstream B: Policy Enforcement (LLM-Policy-Engine)
9
+ * Workstream C: Financial Modeling (LLM-CostOps)
10
+ * Workstream D: Governance Visibility (LLM-Governance-Dashboard)
11
+ *
12
+ * Key design: simulation data (Pass 2) feeds directly into cost models.
13
+ * Security findings (Workstream A) inform policy analysis (Workstream B).
14
+ */
15
+ export const PASS4_WORKSTREAM_CONFIGS = [
16
+ {
17
+ id: 'security-compliance',
18
+ label: 'Security & Compliance Analysis (LLM-Shield)',
19
+ agents: [
20
+ { domain: 'shield', agent: 'prompt-injection', role: 'Prompt injection detection' },
21
+ { domain: 'shield', agent: 'pii', role: 'PII detection' },
22
+ { domain: 'shield', agent: 'redaction', role: 'Data redaction' },
23
+ { domain: 'shield', agent: 'secrets', role: 'Secrets leakage detection' },
24
+ { domain: 'shield', agent: 'toxicity', role: 'Toxicity detection' },
25
+ { domain: 'shield', agent: 'safety-boundary', role: 'Safety boundary enforcement' },
26
+ { domain: 'shield', agent: 'moderation', role: 'Content moderation' },
27
+ { domain: 'shield', agent: 'abuse', role: 'Model abuse detection' },
28
+ { domain: 'shield', agent: 'credential-exposure', role: 'Credential exposure detection' },
29
+ ],
30
+ },
31
+ {
32
+ id: 'policy-enforcement',
33
+ label: 'Policy Enforcement (LLM-Policy-Engine)',
34
+ agents: [
35
+ { domain: 'policy-engine', agent: 'enforce', role: 'Policy enforcement' },
36
+ { domain: 'policy-engine', agent: 'constraints', role: 'Constraint solver' },
37
+ { domain: 'policy-engine', agent: 'approval', role: 'Approval routing' },
38
+ ],
39
+ },
40
+ {
41
+ id: 'financial-modeling',
42
+ label: 'Financial Modeling (LLM-CostOps)',
43
+ agents: [
44
+ { domain: 'costops', agent: 'attribution', role: 'Cost attribution' },
45
+ { domain: 'costops', agent: 'forecast', role: 'Cost forecasting' },
46
+ { domain: 'costops', agent: 'budget', role: 'Budget enforcement' },
47
+ { domain: 'costops', agent: 'roi', role: 'ROI estimation' },
48
+ { domain: 'costops', agent: 'tradeoff', role: 'Cost-performance tradeoff' },
49
+ ],
50
+ },
51
+ {
52
+ id: 'governance-visibility',
53
+ label: 'Governance Visibility (LLM-Governance-Dashboard)',
54
+ agents: [
55
+ { domain: 'governance-dashboard', agent: 'audit', role: 'Governance audit' },
56
+ { domain: 'governance-dashboard', agent: 'impact', role: 'Change impact' },
57
+ { domain: 'governance-dashboard', agent: 'oversight', role: 'Usage oversight' },
58
+ ],
59
+ },
60
+ ];
61
+ // ============================================================================
62
+ // Pass 4 Executor
63
+ // ============================================================================
64
+ /**
65
+ * Execute Pass 4: Governance, Compliance & CostOps.
66
+ *
67
+ * Dispatches four workstreams concurrently, processes results into
68
+ * typed domain objects, converges into a GovernanceConvergence report,
69
+ * and writes all outputs to the DecisionGraph.
70
+ */
71
+ export async function executePass4(params) {
72
+ const { prompt, graph, tracker, timeoutMs, verbose } = params;
73
+ const pass = 4;
74
+ // Build context from Passes 1-3
75
+ const priorContext = buildPriorContext(graph);
76
+ const payload = {
77
+ prompt,
78
+ pass: 4,
79
+ passName: 'Governance, Compliance & CostOps',
80
+ context: priorContext,
81
+ };
82
+ const invoke = params.invokeAgents ?? defaultInvokeAgents;
83
+ if (verbose) {
84
+ console.error(` [Pass 4] Starting 4 concurrent workstreams`);
85
+ }
86
+ // ── Execute all 4 workstreams concurrently ──
87
+ const workstreamPromises = PASS4_WORKSTREAM_CONFIGS.map(async (ws) => {
88
+ const wsStart = Date.now();
89
+ if (verbose) {
90
+ console.error(` [Pass 4] Workstream: ${ws.label} (${ws.agents.length} agents)`);
91
+ }
92
+ const results = await invoke(ws.agents, payload, pass, timeoutMs);
93
+ const successCount = results.filter(r => r.status >= 200 && r.status < 300).length;
94
+ return {
95
+ workstream: ws.id,
96
+ label: ws.label,
97
+ agentResults: results,
98
+ successCount,
99
+ totalCount: results.length,
100
+ durationMs: Date.now() - wsStart,
101
+ };
102
+ });
103
+ const workstreamResults = await Promise.all(workstreamPromises);
104
+ const allResults = [];
105
+ for (const ws of workstreamResults) {
106
+ for (const r of ws.agentResults) {
107
+ allResults.push(r);
108
+ }
109
+ }
110
+ // ── Extract typed domain objects per workstream ──
111
+ const wsA = workstreamResults.find(w => w.workstream === 'security-compliance');
112
+ const wsB = workstreamResults.find(w => w.workstream === 'policy-enforcement');
113
+ const wsC = workstreamResults.find(w => w.workstream === 'financial-modeling');
114
+ const wsD = workstreamResults.find(w => w.workstream === 'governance-visibility');
115
+ const securityAnalysis = extractSecurityAnalysis(wsA);
116
+ const policyAnalysis = extractPolicyAnalysis(wsB, priorContext);
117
+ const costModel = extractCostModel(wsC, graph);
118
+ const governanceReport = extractGovernanceReport(wsD, graph);
119
+ // ── Converge ──
120
+ const convergence = buildConvergence(securityAnalysis, policyAnalysis, costModel, governanceReport);
121
+ // ── Write to DecisionGraph ──
122
+ const graphNodeIds = writeToGraph(graph, securityAnalysis, policyAnalysis, costModel, governanceReport, convergence, tracker, pass);
123
+ if (verbose) {
124
+ console.error(` [Pass 4] Complete: security=${securityAnalysis.overallRiskLevel}, compliance=${policyAnalysis.overallComplianceStatus}, governance=${governanceReport.governanceReadiness.overallScore}`);
125
+ }
126
+ return {
127
+ workstreamResults,
128
+ securityAnalysis,
129
+ policyAnalysis,
130
+ costModel,
131
+ governanceReport,
132
+ convergence,
133
+ graphNodeIds,
134
+ totalAgentResults: allResults,
135
+ };
136
+ }
137
+ // ============================================================================
138
+ // Prior Context Builder
139
+ // ============================================================================
140
+ function buildPriorContext(graph) {
141
+ const ctx = {};
142
+ // Pass 1
143
+ for (const n of graph.getNodesByPass(1)) {
144
+ if (n.type === 'business_context')
145
+ ctx['businessContext'] = { summary: n.summary, ...n.content };
146
+ if (n.type === 'problem_definition')
147
+ ctx['problemDefinition'] = { summary: n.summary, ...n.content };
148
+ if (n.type === 'technical_scope')
149
+ ctx['technicalScope'] = { summary: n.summary, ...n.content };
150
+ }
151
+ // Pass 2 — scenarios & risk signals feed into CostOps
152
+ const scenarios = [];
153
+ const riskSignals = [];
154
+ for (const n of graph.getNodesByPass(2)) {
155
+ if (n.type === 'scenario')
156
+ scenarios.push({ summary: n.summary, ...n.content });
157
+ if (n.type === 'risk_signal')
158
+ riskSignals.push({ summary: n.summary, ...n.content });
159
+ if (n.type === 'reliability_report')
160
+ ctx['reliabilityReport'] = { summary: n.summary, ...n.content };
161
+ }
162
+ ctx['scenarios'] = scenarios;
163
+ ctx['riskSignals'] = riskSignals;
164
+ // Pass 3 — architecture
165
+ for (const n of graph.getNodesByPass(3)) {
166
+ if (n.type === 'system_architecture')
167
+ ctx['architecture'] = { summary: n.summary, ...n.content };
168
+ if (n.type === 'integration_map')
169
+ ctx['integrationMap'] = { summary: n.summary, ...n.content };
170
+ if (n.type === 'prototype')
171
+ ctx['prototype'] = { summary: n.summary, ...n.content };
172
+ }
173
+ return ctx;
174
+ }
175
+ // ============================================================================
176
+ // Workstream A: Security Analysis Extraction
177
+ // ============================================================================
178
+ function extractSecurityAnalysis(ws) {
179
+ const defaults = {
180
+ overallRiskLevel: 'medium',
181
+ dataExposureMap: [],
182
+ safetyAssessment: { injectionVectors: [], contentRisks: [], boundaryViolations: [] },
183
+ credentialAnalysis: { authFlows: [], storageLocations: [], abuseVectors: [] },
184
+ remediationPriorities: [],
185
+ };
186
+ if (!ws || ws.successCount === 0)
187
+ return defaults;
188
+ const exposures = [];
189
+ const injVectors = [];
190
+ const contentRisks = [];
191
+ const boundaryViolations = [];
192
+ const authFlows = [];
193
+ const storageLocations = [];
194
+ const abuseVectors = [];
195
+ const remediations = [];
196
+ let worstRisk = 'low';
197
+ for (const result of ws.agentResults) {
198
+ if (result.status < 200 || result.status >= 300 || !result.response)
199
+ continue;
200
+ const resp = result.response;
201
+ const agentName = result.agent.agent;
202
+ // Data protection agents
203
+ if (['pii', 'redaction', 'secrets'].includes(agentName)) {
204
+ const items = extractArray(resp, 'exposures', 'findings', 'data');
205
+ for (const item of items) {
206
+ if (typeof item === 'object' && item !== null) {
207
+ const r = item;
208
+ exposures.push({
209
+ dataType: String(r['dataType'] ?? r['type'] ?? agentName),
210
+ location: String(r['location'] ?? ''),
211
+ risk: String(r['risk'] ?? ''),
212
+ remediation: String(r['remediation'] ?? ''),
213
+ });
214
+ }
215
+ }
216
+ }
217
+ // Safety agents
218
+ if (['prompt-injection', 'toxicity', 'safety-boundary', 'moderation'].includes(agentName)) {
219
+ const vectors = extractStringArray(resp, 'vectors', 'injectionVectors', 'findings');
220
+ const risks = extractStringArray(resp, 'risks', 'contentRisks');
221
+ const violations = extractStringArray(resp, 'violations', 'boundaryViolations');
222
+ injVectors.push(...vectors);
223
+ contentRisks.push(...risks);
224
+ boundaryViolations.push(...violations);
225
+ }
226
+ // Credential agents
227
+ if (['credential-exposure', 'abuse'].includes(agentName)) {
228
+ authFlows.push(...extractStringArray(resp, 'authFlows', 'flows'));
229
+ storageLocations.push(...extractStringArray(resp, 'storageLocations', 'locations'));
230
+ abuseVectors.push(...extractStringArray(resp, 'abuseVectors', 'vectors'));
231
+ }
232
+ // Remediation from any agent
233
+ const rems = extractArray(resp, 'remediations', 'remediationPriorities', 'recommendations');
234
+ for (const item of rems) {
235
+ if (typeof item === 'object' && item !== null) {
236
+ const r = item;
237
+ remediations.push({
238
+ finding: String(r['finding'] ?? r['description'] ?? ''),
239
+ severity: normalizeRiskLevel(r['severity']),
240
+ effort: normalizeEffort(r['effort']),
241
+ recommendation: String(r['recommendation'] ?? ''),
242
+ });
243
+ }
244
+ }
245
+ const level = normalizeRiskLevel(resp['riskLevel'] ?? resp['overallRiskLevel'] ?? resp['severity']);
246
+ worstRisk = worstOf(worstRisk, level);
247
+ }
248
+ return {
249
+ overallRiskLevel: worstRisk,
250
+ dataExposureMap: exposures,
251
+ safetyAssessment: { injectionVectors: injVectors, contentRisks, boundaryViolations },
252
+ credentialAnalysis: { authFlows, storageLocations, abuseVectors },
253
+ remediationPriorities: remediations,
254
+ };
255
+ }
256
+ // ============================================================================
257
+ // Workstream B: Policy Analysis Extraction
258
+ // ============================================================================
259
+ function extractPolicyAnalysis(ws, _context) {
260
+ const defaults = {
261
+ applicableFrameworks: [],
262
+ aiGovernance: { explainabilityScore: 'partial', biasAssessment: '', humanOversightRequired: true, requirements: [] },
263
+ approvalRouting: [],
264
+ overallComplianceStatus: 'gaps_identified',
265
+ };
266
+ if (!ws || ws.successCount === 0)
267
+ return defaults;
268
+ const frameworks = [];
269
+ const approvals = [];
270
+ let aiGov = defaults.aiGovernance;
271
+ let complianceStatus = 'compliant';
272
+ for (const result of ws.agentResults) {
273
+ if (result.status < 200 || result.status >= 300 || !result.response)
274
+ continue;
275
+ const resp = result.response;
276
+ // Frameworks
277
+ const fws = extractArray(resp, 'frameworks', 'applicableFrameworks', 'regulations');
278
+ for (const item of fws) {
279
+ if (typeof item === 'object' && item !== null) {
280
+ const r = item;
281
+ frameworks.push({
282
+ framework: String(r['framework'] ?? r['name'] ?? ''),
283
+ applicability: String(r['applicability'] ?? r['reason'] ?? ''),
284
+ complianceGaps: extractStringArray(r, 'complianceGaps', 'gaps'),
285
+ remediationSteps: extractStringArray(r, 'remediationSteps', 'remediation', 'steps'),
286
+ });
287
+ }
288
+ else if (typeof item === 'string') {
289
+ frameworks.push({ framework: item, applicability: 'Detected from context', complianceGaps: [], remediationSteps: [] });
290
+ }
291
+ }
292
+ // AI Governance
293
+ if (resp['aiGovernance'] && typeof resp['aiGovernance'] === 'object') {
294
+ const ag = resp['aiGovernance'];
295
+ aiGov = {
296
+ explainabilityScore: normalizeExplainability(ag['explainabilityScore']),
297
+ biasAssessment: String(ag['biasAssessment'] ?? ''),
298
+ humanOversightRequired: ag['humanOversightRequired'] !== false,
299
+ requirements: extractStringArray(ag, 'requirements'),
300
+ };
301
+ }
302
+ // Approval routing
303
+ const apprs = extractArray(resp, 'approvalRouting', 'approvals');
304
+ for (const item of apprs) {
305
+ if (typeof item === 'object' && item !== null) {
306
+ const r = item;
307
+ approvals.push({
308
+ approver: String(r['approver'] ?? r['role'] ?? ''),
309
+ reason: String(r['reason'] ?? ''),
310
+ threshold: String(r['threshold'] ?? ''),
311
+ });
312
+ }
313
+ }
314
+ // Compliance status
315
+ const status = normalizeComplianceStatus(resp['complianceStatus'] ?? resp['overallComplianceStatus']);
316
+ if (status === 'non_compliant')
317
+ complianceStatus = 'non_compliant';
318
+ else if (status === 'gaps_identified' && complianceStatus !== 'non_compliant')
319
+ complianceStatus = 'gaps_identified';
320
+ }
321
+ // If no frameworks detected but gaps exist, mark as gaps_identified
322
+ if (frameworks.length === 0)
323
+ complianceStatus = 'gaps_identified';
324
+ return { applicableFrameworks: frameworks, aiGovernance: aiGov, approvalRouting: approvals, overallComplianceStatus: complianceStatus };
325
+ }
326
+ // ============================================================================
327
+ // Workstream C: Cost Model Extraction
328
+ // ============================================================================
329
+ function extractCostModel(ws, graph) {
330
+ const defaults = {
331
+ infrastructure: [],
332
+ integrationCosts: [],
333
+ operationalCosts: [],
334
+ tco: { year1: 0, year3: 0, year5: 0 },
335
+ roi: { expectedReturn: 0, paybackPeriodMonths: 0, confidenceLevel: 'low' },
336
+ scenarioVariants: [],
337
+ budgetRisk: { contingencyRequired: 0, budgetExceedanceProbability: 0, riskFactors: [] },
338
+ };
339
+ if (!ws || ws.successCount === 0)
340
+ return defaults;
341
+ const infra = [];
342
+ const integ = [];
343
+ const ops = [];
344
+ let tco = defaults.tco;
345
+ let roi = defaults.roi;
346
+ const variants = [];
347
+ let budgetRisk = defaults.budgetRisk;
348
+ for (const result of ws.agentResults) {
349
+ if (result.status < 200 || result.status >= 300 || !result.response)
350
+ continue;
351
+ const resp = result.response;
352
+ // Infrastructure costs
353
+ for (const item of extractArray(resp, 'infrastructure', 'infrastructureCosts')) {
354
+ if (typeof item === 'object' && item !== null) {
355
+ const r = item;
356
+ infra.push({
357
+ category: String(r['category'] ?? ''),
358
+ provider: String(r['provider'] ?? ''),
359
+ monthlyCost: Number(r['monthlyCost'] ?? r['monthly_cost'] ?? 0),
360
+ annualCost: Number(r['annualCost'] ?? r['annual_cost'] ?? 0),
361
+ assumptions: extractStringArray(r, 'assumptions'),
362
+ });
363
+ }
364
+ }
365
+ // Integration costs
366
+ for (const item of extractArray(resp, 'integrationCosts', 'integrations')) {
367
+ if (typeof item === 'object' && item !== null) {
368
+ const r = item;
369
+ integ.push({
370
+ system: String(r['system'] ?? r['name'] ?? ''),
371
+ setupCost: Number(r['setupCost'] ?? r['setup_cost'] ?? 0),
372
+ ongoingMonthlyCost: Number(r['ongoingMonthlyCost'] ?? r['monthly_cost'] ?? 0),
373
+ assumptions: extractStringArray(r, 'assumptions'),
374
+ });
375
+ }
376
+ }
377
+ // Operational costs
378
+ for (const item of extractArray(resp, 'operationalCosts', 'operational')) {
379
+ if (typeof item === 'object' && item !== null) {
380
+ const r = item;
381
+ ops.push({
382
+ category: String(r['category'] ?? ''),
383
+ annualCost: Number(r['annualCost'] ?? r['annual_cost'] ?? 0),
384
+ fteRequired: Number(r['fteRequired'] ?? r['fte'] ?? 0),
385
+ });
386
+ }
387
+ }
388
+ // TCO
389
+ if (resp['tco'] && typeof resp['tco'] === 'object') {
390
+ const t = resp['tco'];
391
+ tco = {
392
+ year1: Number(t['year1'] ?? 0),
393
+ year3: Number(t['year3'] ?? 0),
394
+ year5: Number(t['year5'] ?? 0),
395
+ };
396
+ }
397
+ // ROI
398
+ if (resp['roi'] && typeof resp['roi'] === 'object') {
399
+ const r = resp['roi'];
400
+ roi = {
401
+ expectedReturn: Number(r['expectedReturn'] ?? r['expected_return'] ?? 0),
402
+ paybackPeriodMonths: Number(r['paybackPeriodMonths'] ?? r['payback_months'] ?? 0),
403
+ confidenceLevel: normalizeConfidence(r['confidenceLevel'] ?? r['confidence']),
404
+ };
405
+ }
406
+ // Budget risk
407
+ if (resp['budgetRisk'] && typeof resp['budgetRisk'] === 'object') {
408
+ const b = resp['budgetRisk'];
409
+ budgetRisk = {
410
+ contingencyRequired: Number(b['contingencyRequired'] ?? 0),
411
+ budgetExceedanceProbability: Number(b['budgetExceedanceProbability'] ?? 0),
412
+ riskFactors: extractStringArray(b, 'riskFactors', 'factors'),
413
+ };
414
+ }
415
+ }
416
+ // Build scenario variants from Pass 2 scenarios
417
+ const scenarioNodes = graph.getNodesByType('scenario');
418
+ for (const sn of scenarioNodes) {
419
+ if (sn.pass !== 2)
420
+ continue;
421
+ const sc = sn.content;
422
+ variants.push({
423
+ scenarioId: sn.id,
424
+ scenarioName: String(sc['name'] ?? sn.name),
425
+ costDelta: Number(sc['costDelta'] ?? 0),
426
+ explanation: String(sc['mitigationStrategy'] ?? sc['description'] ?? ''),
427
+ });
428
+ }
429
+ return { infrastructure: infra, integrationCosts: integ, operationalCosts: ops, tco, roi, scenarioVariants: variants, budgetRisk };
430
+ }
431
+ // ============================================================================
432
+ // Workstream D: Governance Report Extraction
433
+ // ============================================================================
434
+ function extractGovernanceReport(ws, graph) {
435
+ const defaults = {
436
+ auditTrail: [],
437
+ changeImpact: [],
438
+ governanceReadiness: { overallScore: 'not_ready', conditions: [], strengths: [], gaps: [] },
439
+ };
440
+ const auditTrail = [];
441
+ const changes = [];
442
+ let readiness = defaults.governanceReadiness;
443
+ if (!ws || ws.successCount === 0) {
444
+ // Fall through to auto-audit logic below
445
+ }
446
+ else {
447
+ for (const result of ws.agentResults) {
448
+ if (result.status < 200 || result.status >= 300 || !result.response)
449
+ continue;
450
+ const resp = result.response;
451
+ // Audit trail
452
+ for (const item of extractArray(resp, 'auditTrail', 'audit', 'decisions')) {
453
+ if (typeof item === 'object' && item !== null) {
454
+ const r = item;
455
+ auditTrail.push({
456
+ decision: String(r['decision'] ?? ''),
457
+ madeBy: String(r['madeBy'] ?? r['agent'] ?? ''),
458
+ timestamp: String(r['timestamp'] ?? new Date().toISOString()),
459
+ rationale: String(r['rationale'] ?? ''),
460
+ dataInputs: extractStringArray(r, 'dataInputs', 'inputs'),
461
+ });
462
+ }
463
+ }
464
+ // Change impact
465
+ for (const item of extractArray(resp, 'changeImpact', 'changes', 'impacts')) {
466
+ if (typeof item === 'object' && item !== null) {
467
+ const r = item;
468
+ changes.push({
469
+ affectedSystem: String(r['affectedSystem'] ?? r['system'] ?? ''),
470
+ changeType: String(r['changeType'] ?? r['type'] ?? ''),
471
+ impactLevel: normalizeRiskLevel(r['impactLevel'] ?? r['impact']),
472
+ stakeholders: extractStringArray(r, 'stakeholders'),
473
+ });
474
+ }
475
+ }
476
+ // Governance readiness
477
+ if (resp['governanceReadiness'] && typeof resp['governanceReadiness'] === 'object') {
478
+ const g = resp['governanceReadiness'];
479
+ readiness = {
480
+ overallScore: normalizeReadiness(g['overallScore'] ?? g['score']),
481
+ conditions: extractStringArray(g, 'conditions'),
482
+ strengths: extractStringArray(g, 'strengths'),
483
+ gaps: extractStringArray(g, 'gaps'),
484
+ };
485
+ }
486
+ }
487
+ } // end else (ws has successful agents)
488
+ // Auto-generate audit trail from prior graph nodes if none from agents
489
+ if (auditTrail.length === 0) {
490
+ for (const n of graph.getAllNodes()) {
491
+ if (n.pass <= 3) {
492
+ auditTrail.push({
493
+ decision: `${n.type}: ${n.name}`,
494
+ madeBy: `${n.producedBy.domain}/${n.producedBy.agent}`,
495
+ timestamp: n.timestamp,
496
+ rationale: n.summary,
497
+ dataInputs: [...n.derivedFrom].slice(0, 5),
498
+ });
499
+ }
500
+ }
501
+ }
502
+ return { auditTrail, changeImpact: changes, governanceReadiness: readiness };
503
+ }
504
+ // ============================================================================
505
+ // Convergence
506
+ // ============================================================================
507
+ function buildConvergence(security, policy, cost, governance) {
508
+ const financialViability = cost.roi.expectedReturn > 0 && cost.tco.year1 > 0 ? cost.roi.confidenceLevel
509
+ : cost.tco.year1 > 0 ? 'medium'
510
+ : 'low';
511
+ const parts = [];
512
+ parts.push(`Security: ${security.overallRiskLevel}`);
513
+ parts.push(`Compliance: ${policy.overallComplianceStatus}`);
514
+ parts.push(`Financial: ${financialViability}`);
515
+ parts.push(`Governance: ${governance.governanceReadiness.overallScore}`);
516
+ return {
517
+ securityRiskLevel: security.overallRiskLevel,
518
+ complianceStatus: policy.overallComplianceStatus,
519
+ financialViability,
520
+ governanceReadiness: governance.governanceReadiness.overallScore,
521
+ overallAssessment: parts.join(' | '),
522
+ };
523
+ }
524
+ // ============================================================================
525
+ // DecisionGraph Write
526
+ // ============================================================================
527
+ function writeToGraph(graph, security, policy, cost, governance, convergence, tracker, pass) {
528
+ const nodeIds = [];
529
+ const priorIds = [...graph.getNodesByPass(1), ...graph.getNodesByPass(2), ...graph.getNodesByPass(3)]
530
+ .map(n => n.id).slice(0, 5);
531
+ // Security Analysis
532
+ const secNode = graph.createNode({
533
+ type: 'security_analysis',
534
+ name: 'Security & Compliance Analysis',
535
+ content: security,
536
+ summary: `Security risk: ${security.overallRiskLevel}. ${security.dataExposureMap.length} data exposure(s), ${security.remediationPriorities.length} remediation(s).`,
537
+ producedBy: { domain: 'shield', agent: 'security-analysis', role: 'Security Analyst' },
538
+ pass,
539
+ derivedFrom: priorIds,
540
+ confidence: riskLevelToConfidence(security.overallRiskLevel),
541
+ tags: [`security:${security.overallRiskLevel}`],
542
+ });
543
+ nodeIds.push(secNode.id);
544
+ // Policy Analysis
545
+ const polNode = graph.createNode({
546
+ type: 'policy_analysis',
547
+ name: 'Policy Enforcement Analysis',
548
+ content: policy,
549
+ summary: `Compliance: ${policy.overallComplianceStatus}. ${policy.applicableFrameworks.length} framework(s), ${policy.approvalRouting.length} approval(s).`,
550
+ producedBy: { domain: 'policy-engine', agent: 'enforce', role: 'Policy Analyst' },
551
+ pass,
552
+ derivedFrom: [secNode.id, ...priorIds.slice(0, 4)],
553
+ confidence: complianceToConfidence(policy.overallComplianceStatus),
554
+ tags: [`compliance:${policy.overallComplianceStatus}`],
555
+ });
556
+ nodeIds.push(polNode.id);
557
+ // Compliance Report (distinct from policy analysis per ADR-036)
558
+ const compNode = graph.createNode({
559
+ type: 'compliance_report',
560
+ name: 'Regulatory Compliance Report',
561
+ content: {
562
+ frameworks: policy.applicableFrameworks,
563
+ aiGovernance: policy.aiGovernance,
564
+ status: policy.overallComplianceStatus,
565
+ },
566
+ summary: `${policy.applicableFrameworks.length} regulatory framework(s) assessed. Status: ${policy.overallComplianceStatus}.`,
567
+ producedBy: { domain: 'policy-engine', agent: 'constraints', role: 'Compliance Analyst' },
568
+ pass,
569
+ derivedFrom: [polNode.id],
570
+ confidence: complianceToConfidence(policy.overallComplianceStatus),
571
+ tags: [`compliance:${policy.overallComplianceStatus}`],
572
+ });
573
+ nodeIds.push(compNode.id);
574
+ // Cost Model
575
+ const costNode = graph.createNode({
576
+ type: 'cost_model',
577
+ name: 'CostOps Financial Model',
578
+ content: cost,
579
+ summary: `TCO Year 1: ${cost.tco.year1}, ROI: ${cost.roi.expectedReturn}, Payback: ${cost.roi.paybackPeriodMonths}mo. ${cost.scenarioVariants.length} scenario variant(s).`,
580
+ producedBy: { domain: 'costops', agent: 'forecast', role: 'Financial Modeler' },
581
+ pass,
582
+ derivedFrom: priorIds,
583
+ confidence: confidenceToNumber(cost.roi.confidenceLevel),
584
+ tags: [`roi-confidence:${cost.roi.confidenceLevel}`],
585
+ });
586
+ nodeIds.push(costNode.id);
587
+ // Governance Report
588
+ const govNode = graph.createNode({
589
+ type: 'governance_report',
590
+ name: 'Governance Readiness Report',
591
+ content: governance,
592
+ summary: `Governance readiness: ${governance.governanceReadiness.overallScore}. ${governance.auditTrail.length} audit entries, ${governance.changeImpact.length} impact(s).`,
593
+ producedBy: { domain: 'governance-dashboard', agent: 'audit', role: 'Governance Assessor' },
594
+ pass,
595
+ derivedFrom: [...nodeIds],
596
+ confidence: readinessToConfidence(governance.governanceReadiness.overallScore),
597
+ tags: [`readiness:${governance.governanceReadiness.overallScore}`],
598
+ });
599
+ nodeIds.push(govNode.id);
600
+ // Convergence node
601
+ graph.createNode({
602
+ type: 'governance_report',
603
+ name: 'Governance Convergence Report',
604
+ content: convergence,
605
+ summary: convergence.overallAssessment,
606
+ producedBy: { domain: 'pipeline', agent: 'pass4-convergence', role: 'Governance Convergence' },
607
+ pass,
608
+ derivedFrom: nodeIds.slice(0, 5),
609
+ confidence: 0.8,
610
+ tags: ['convergence'],
611
+ });
612
+ // Record provenance
613
+ tracker.recordInvocation({
614
+ agent: { domain: 'pipeline', agent: 'pass4-convergence', role: 'Governance Convergence' },
615
+ pass,
616
+ passName: 'Governance, Compliance & CostOps',
617
+ workstream: 'convergence',
618
+ startedAt: new Date().toISOString(),
619
+ completedAt: new Date().toISOString(),
620
+ durationMs: 0,
621
+ inputNodeIds: priorIds,
622
+ outputNodeIds: nodeIds,
623
+ artifactNumbers: [5, 6, 7],
624
+ status: 'success',
625
+ confidence: 0.8,
626
+ });
627
+ return nodeIds;
628
+ }
629
+ // ============================================================================
630
+ // Default Agent Invoker
631
+ // ============================================================================
632
+ async function defaultInvokeAgents(agents, payload, pass, _timeoutMs) {
633
+ const promises = agents.map(async (agent) => {
634
+ const start = Date.now();
635
+ const timestamp = new Date().toISOString();
636
+ try {
637
+ const { executeAgentsInvokeCommand } = await import('../../commands/agents.js');
638
+ const result = await executeAgentsInvokeCommand(agent.domain, agent.agent, JSON.stringify(payload), { format: 'json' });
639
+ return { agent, status: result.status, response: result.response, durationMs: Date.now() - start, pass, timestamp };
640
+ }
641
+ catch (err) {
642
+ return { agent, status: 500, response: { error: err instanceof Error ? err.message : String(err) }, durationMs: Date.now() - start, pass, timestamp };
643
+ }
644
+ });
645
+ const settled = await Promise.allSettled(promises);
646
+ return settled.map((outcome, i) => outcome.status === 'fulfilled'
647
+ ? outcome.value
648
+ : { agent: agents[i], status: 500, response: { error: String(outcome.reason) }, durationMs: 0, pass, timestamp: new Date().toISOString() });
649
+ }
650
+ // ============================================================================
651
+ // Normalization Helpers
652
+ // ============================================================================
653
+ function normalizeRiskLevel(raw) {
654
+ const s = String(raw ?? '').toLowerCase();
655
+ if (s === 'critical')
656
+ return 'critical';
657
+ if (s === 'high')
658
+ return 'high';
659
+ if (s === 'low')
660
+ return 'low';
661
+ return 'medium';
662
+ }
663
+ function normalizeEffort(raw) {
664
+ const s = String(raw ?? '').toLowerCase();
665
+ if (s === 'high')
666
+ return 'high';
667
+ if (s === 'low')
668
+ return 'low';
669
+ return 'medium';
670
+ }
671
+ function normalizeComplianceStatus(raw) {
672
+ const s = String(raw ?? '').toLowerCase().replace(/[\s-]/g, '_');
673
+ if (s === 'compliant')
674
+ return 'compliant';
675
+ if (s === 'non_compliant')
676
+ return 'non_compliant';
677
+ return 'gaps_identified';
678
+ }
679
+ function normalizeExplainability(raw) {
680
+ const s = String(raw ?? '').toLowerCase();
681
+ if (s === 'full')
682
+ return 'full';
683
+ if (s === 'opaque')
684
+ return 'opaque';
685
+ return 'partial';
686
+ }
687
+ function normalizeReadiness(raw) {
688
+ const s = String(raw ?? '').toLowerCase().replace(/[\s-]/g, '_');
689
+ if (s === 'ready')
690
+ return 'ready';
691
+ if (s === 'conditionally_ready')
692
+ return 'conditionally_ready';
693
+ return 'not_ready';
694
+ }
695
+ function normalizeConfidence(raw) {
696
+ const s = String(raw ?? '').toLowerCase();
697
+ if (s === 'high')
698
+ return 'high';
699
+ if (s === 'low')
700
+ return 'low';
701
+ return 'medium';
702
+ }
703
+ function worstOf(a, b) {
704
+ const order = { critical: 4, high: 3, medium: 2, low: 1 };
705
+ return order[a] >= order[b] ? a : b;
706
+ }
707
+ function riskLevelToConfidence(level) {
708
+ switch (level) {
709
+ case 'critical': return 0.95;
710
+ case 'high': return 0.85;
711
+ case 'medium': return 0.7;
712
+ default: return 0.5;
713
+ }
714
+ }
715
+ function complianceToConfidence(status) {
716
+ switch (status) {
717
+ case 'compliant': return 0.95;
718
+ case 'gaps_identified': return 0.7;
719
+ default: return 0.4;
720
+ }
721
+ }
722
+ function confidenceToNumber(level) {
723
+ switch (level) {
724
+ case 'high': return 0.9;
725
+ case 'medium': return 0.7;
726
+ default: return 0.5;
727
+ }
728
+ }
729
+ function readinessToConfidence(score) {
730
+ switch (score) {
731
+ case 'ready': return 0.95;
732
+ case 'conditionally_ready': return 0.7;
733
+ default: return 0.4;
734
+ }
735
+ }
736
+ function extractArray(obj, ...keys) {
737
+ for (const k of keys) {
738
+ const v = obj[k];
739
+ if (Array.isArray(v))
740
+ return v;
741
+ }
742
+ return [];
743
+ }
744
+ function extractStringArray(obj, ...keys) {
745
+ const arr = extractArray(obj, ...keys);
746
+ return arr.map(String);
747
+ }
748
+ //# sourceMappingURL=pass4-governance.js.map