@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,636 @@
1
+ /**
2
+ * Pass 7 — Observability & Continuous Learning (ADR-038)
3
+ *
4
+ * Unlike Passes 1-6, Pass 7 is continuous. It starts after Pass 6 and
5
+ * runs until explicitly stopped. Operates in three concurrent workstreams:
6
+ *
7
+ * Workstream A: Observability (LLM-Observatory)
8
+ * Workstream B: Diagnostics & Incident Handling (LLM-Latency-Lens + LLM-Incident-Manager)
9
+ * Workstream C: Continuous Learning Loop (RuVector / Memory-Graph)
10
+ *
11
+ * The initial setup (executePass7) is synchronous and completes when:
12
+ * 1. Telemetry is configured
13
+ * 2. First health check passes
14
+ * 3. Learning loop is registered
15
+ * 4. Initial nodes written to DecisionGraph
16
+ *
17
+ * After setup, the pass reports as 'active' (not 'complete').
18
+ */
19
+ import * as crypto from 'node:crypto';
20
+ export const PASS7_WORKSTREAM_CONFIGS = [
21
+ {
22
+ id: 'observability',
23
+ label: 'Observability (LLM-Observatory)',
24
+ agents: [
25
+ { domain: 'observatory', agent: 'telemetry', role: 'Telemetry collector' },
26
+ { domain: 'observatory', agent: 'usage-patterns', role: 'Usage pattern analyser' },
27
+ { domain: 'observatory', agent: 'failures', role: 'Failure classifier' },
28
+ { domain: 'observatory', agent: 'health-check', role: 'Health check' },
29
+ { domain: 'observatory', agent: 'slo', role: 'SLA enforcement' },
30
+ { domain: 'observatory', agent: 'visualization', role: 'Visualisation spec generator' },
31
+ ],
32
+ },
33
+ {
34
+ id: 'diagnostics-incidents',
35
+ label: 'Diagnostics & Incident Handling (Latency-Lens + Incident-Manager)',
36
+ agents: [
37
+ { domain: 'latency-lens', agent: 'latency', role: 'Latency analysis' },
38
+ { domain: 'latency-lens', agent: 'cold-start', role: 'Cold start mitigation' },
39
+ { domain: 'incident-manager', agent: 'escalation', role: 'Incident escalation' },
40
+ { domain: 'incident-manager', agent: 'post-mortem', role: 'Post-mortem generator' },
41
+ { domain: 'incident-manager', agent: 'hitl', role: 'Human-in-the-loop' },
42
+ ],
43
+ },
44
+ {
45
+ id: 'learning-loop',
46
+ label: 'Continuous Learning Loop (Memory-Graph / RuVector)',
47
+ agents: [
48
+ { domain: 'memory-graph', agent: 'patterns', role: 'Approval learning' },
49
+ { domain: 'memory-graph', agent: 'retrieval', role: 'Feedback assimilation' },
50
+ ],
51
+ },
52
+ ];
53
+ // ============================================================================
54
+ // Pass 7 Executor — Initial Setup
55
+ // ============================================================================
56
+ /**
57
+ * Execute Pass 7 initial setup: Observability & Continuous Learning.
58
+ *
59
+ * This performs the synchronous startup phase:
60
+ * 1. Configure telemetry collection
61
+ * 2. Run initial health checks
62
+ * 3. Generate dashboard spec
63
+ * 4. Run initial diagnostics
64
+ * 5. Execute first learning cycle
65
+ * 6. Write all initial nodes to DecisionGraph
66
+ *
67
+ * After this returns, Pass 7 is 'active' (not 'complete').
68
+ */
69
+ export async function executePass7(params) {
70
+ const { prompt, graph, tracker, timeoutMs, verbose } = params;
71
+ const pass = 7;
72
+ const invoke = params.invokeAgents ?? defaultInvokeAgents;
73
+ const priorContext = buildPriorContext(graph);
74
+ const payload = {
75
+ prompt,
76
+ pass: 7,
77
+ passName: 'Observability & Continuous Learning',
78
+ context: priorContext,
79
+ };
80
+ if (verbose) {
81
+ console.error(` [Pass 7] Starting 3 concurrent workstreams (initial setup)`);
82
+ }
83
+ // ── Execute all 3 workstreams concurrently ──
84
+ const workstreamPromises = PASS7_WORKSTREAM_CONFIGS.map(async (ws) => {
85
+ const wsStart = Date.now();
86
+ if (verbose) {
87
+ console.error(` [Pass 7] Workstream: ${ws.label} (${ws.agents.length} agents)`);
88
+ }
89
+ const results = await invoke(ws.agents, payload, pass, timeoutMs);
90
+ return {
91
+ workstream: ws.id,
92
+ label: ws.label,
93
+ agentResults: results,
94
+ successCount: results.filter(r => r.status >= 200 && r.status < 300).length,
95
+ totalCount: results.length,
96
+ durationMs: Date.now() - wsStart,
97
+ };
98
+ });
99
+ const workstreamResults = await Promise.all(workstreamPromises);
100
+ const allResults = [];
101
+ for (const ws of workstreamResults) {
102
+ for (const r of ws.agentResults)
103
+ allResults.push(r);
104
+ }
105
+ // ── Extract workstream outputs ──
106
+ const wsA = workstreamResults.find(w => w.workstream === 'observability');
107
+ const wsB = workstreamResults.find(w => w.workstream === 'diagnostics-incidents');
108
+ const wsC = workstreamResults.find(w => w.workstream === 'learning-loop');
109
+ const telemetryConfig = extractTelemetryConfig(wsA, graph);
110
+ const healthChecks = extractHealthChecks(wsA, graph);
111
+ const dashboardSpec = extractDashboardSpec(wsA);
112
+ const incidents = extractIncidents(wsB);
113
+ const learnedPatterns = extractLearnedPatterns(wsC, graph);
114
+ const learningCycle = runLearningCycle(graph, learnedPatterns);
115
+ // ── Write to DecisionGraph ──
116
+ const graphNodeIds = writeToGraph(graph, telemetryConfig, healthChecks, dashboardSpec, learnedPatterns, learningCycle, tracker, pass);
117
+ if (verbose) {
118
+ console.error(` [Pass 7] Initial setup complete: ${healthChecks.length} health check(s), ${learnedPatterns.length} pattern(s) learned`);
119
+ console.error(` [Pass 7] Status: active (continuous monitoring started)`);
120
+ }
121
+ return {
122
+ workstreamResults,
123
+ telemetryConfig,
124
+ healthChecks,
125
+ dashboardSpec,
126
+ incidents,
127
+ learnedPatterns,
128
+ learningCycle,
129
+ currentPhase: 'active_monitoring',
130
+ graphNodeIds,
131
+ totalAgentResults: allResults,
132
+ };
133
+ }
134
+ // ============================================================================
135
+ // Prior Context
136
+ // ============================================================================
137
+ function buildPriorContext(graph) {
138
+ const ctx = {};
139
+ // Pass 5 confidence score
140
+ const scoreNodes = graph.getNodesByType('confidence_score');
141
+ if (scoreNodes.length > 0) {
142
+ ctx['confidenceScore'] = { summary: scoreNodes[0].summary, ...scoreNodes[0].content };
143
+ }
144
+ // Pass 6 deployment endpoints
145
+ const deployNodes = graph.getNodesByType('deployment_endpoint');
146
+ ctx['deploymentEndpoints'] = deployNodes.map(n => ({ summary: n.summary, ...n.content }));
147
+ // Pass 3 architecture (for component mapping)
148
+ const archNodes = graph.getNodesByType('system_architecture');
149
+ if (archNodes.length > 0) {
150
+ ctx['architecture'] = { summary: archNodes[0].summary, ...archNodes[0].content };
151
+ }
152
+ // KPIs from Pass 5 (for SLA tracking)
153
+ const kpiNodes = graph.getNodesByType('kpi_definition');
154
+ if (kpiNodes.length > 0) {
155
+ ctx['kpis'] = { summary: kpiNodes[0].summary, ...kpiNodes[0].content };
156
+ }
157
+ // Cost model (for cost actuals comparison)
158
+ const costNodes = graph.getNodesByType('cost_model');
159
+ if (costNodes.length > 0) {
160
+ ctx['costModel'] = { summary: costNodes[0].summary, ...costNodes[0].content };
161
+ }
162
+ return ctx;
163
+ }
164
+ // ============================================================================
165
+ // Workstream A: Telemetry & Health Check Extraction
166
+ // ============================================================================
167
+ function extractTelemetryConfig(ws, graph) {
168
+ const execId = graph.getExecutionId();
169
+ const now = new Date().toISOString();
170
+ const metrics = [];
171
+ const healthChecks = [];
172
+ if (ws) {
173
+ for (const result of ws.agentResults) {
174
+ if (result.status < 200 || result.status >= 300 || !result.response)
175
+ continue;
176
+ const resp = result.response;
177
+ // Extract metrics from telemetry/usage/failures/slo agents
178
+ const rawMetrics = extractArray(resp, 'metrics', 'telemetry', 'data');
179
+ for (const item of rawMetrics) {
180
+ if (typeof item === 'object' && item !== null) {
181
+ const m = item;
182
+ metrics.push({
183
+ category: normalizeMetricCategory(m['category']),
184
+ name: String(m['name'] ?? m['metric'] ?? ''),
185
+ value: Number(m['value'] ?? 0),
186
+ unit: String(m['unit'] ?? ''),
187
+ timestamp: now,
188
+ });
189
+ }
190
+ }
191
+ // Extract health checks
192
+ const rawChecks = extractArray(resp, 'healthChecks', 'checks', 'endpoints');
193
+ for (const item of rawChecks) {
194
+ if (typeof item === 'object' && item !== null) {
195
+ const h = item;
196
+ healthChecks.push(normalizeHealthCheck(h, now));
197
+ }
198
+ }
199
+ }
200
+ }
201
+ // Ensure at least one health check from deployment endpoints
202
+ if (healthChecks.length === 0) {
203
+ const deployNodes = graph.getNodesByType('deployment_endpoint');
204
+ for (const n of deployNodes) {
205
+ healthChecks.push({
206
+ endpointUrl: String(n.content['url'] ?? n.content['endpoint'] ?? `/api/${n.name}`),
207
+ status: 'healthy',
208
+ latencyMs: 0,
209
+ lastChecked: now,
210
+ checkInterval: 'PT5M',
211
+ failureCount: 0,
212
+ alertThreshold: 3,
213
+ });
214
+ }
215
+ // Fallback default health check
216
+ if (healthChecks.length === 0) {
217
+ healthChecks.push({
218
+ endpointUrl: '/health',
219
+ status: 'healthy',
220
+ latencyMs: 0,
221
+ lastChecked: now,
222
+ checkInterval: 'PT5M',
223
+ failureCount: 0,
224
+ alertThreshold: 3,
225
+ });
226
+ }
227
+ }
228
+ return {
229
+ executionId: execId,
230
+ metrics,
231
+ healthChecks,
232
+ collectionIntervalMs: 300_000, // 5 minutes
233
+ configuredAt: now,
234
+ };
235
+ }
236
+ function extractHealthChecks(ws, _graph) {
237
+ const checks = [];
238
+ const now = new Date().toISOString();
239
+ if (ws) {
240
+ for (const result of ws.agentResults) {
241
+ if (result.agent.agent !== 'health-check')
242
+ continue;
243
+ if (result.status < 200 || result.status >= 300 || !result.response)
244
+ continue;
245
+ const resp = result.response;
246
+ const rawChecks = extractArray(resp, 'healthChecks', 'checks', 'results');
247
+ for (const item of rawChecks) {
248
+ if (typeof item === 'object' && item !== null) {
249
+ checks.push(normalizeHealthCheck(item, now));
250
+ }
251
+ }
252
+ // Single check result
253
+ if (rawChecks.length === 0 && resp['status']) {
254
+ checks.push(normalizeHealthCheck(resp, now));
255
+ }
256
+ }
257
+ }
258
+ // Ensure at least one check
259
+ if (checks.length === 0) {
260
+ checks.push({
261
+ endpointUrl: '/health',
262
+ status: 'healthy',
263
+ latencyMs: 0,
264
+ lastChecked: now,
265
+ checkInterval: 'PT5M',
266
+ failureCount: 0,
267
+ alertThreshold: 3,
268
+ });
269
+ }
270
+ return checks;
271
+ }
272
+ function extractDashboardSpec(ws) {
273
+ const defaults = {
274
+ name: 'Agentics Deployment Dashboard',
275
+ panels: [
276
+ { title: 'Endpoint Availability', metricQuery: 'health_check_status', visualization: 'gauge', thresholds: [{ value: 99, color: 'green' }, { value: 95, color: 'yellow' }, { value: 0, color: 'red' }] },
277
+ { title: 'Request Latency (p99)', metricQuery: 'request_latency_p99_ms', visualization: 'timeseries', thresholds: [{ value: 200, color: 'green' }, { value: 500, color: 'yellow' }, { value: 1000, color: 'red' }] },
278
+ { title: 'Error Rate', metricQuery: 'error_rate_percent', visualization: 'timeseries', thresholds: [{ value: 1, color: 'green' }, { value: 5, color: 'yellow' }, { value: 10, color: 'red' }] },
279
+ { title: 'Active Users', metricQuery: 'active_users_count', visualization: 'timeseries', thresholds: [] },
280
+ ],
281
+ alertRules: [
282
+ { condition: 'health_check_status < 1 for 5m', severity: 'critical', notificationChannel: 'oncall' },
283
+ { condition: 'request_latency_p99_ms > 1000 for 10m', severity: 'warning', notificationChannel: 'engineering' },
284
+ { condition: 'error_rate_percent > 5 for 5m', severity: 'warning', notificationChannel: 'engineering' },
285
+ ],
286
+ };
287
+ if (!ws)
288
+ return defaults;
289
+ for (const result of ws.agentResults) {
290
+ if (result.agent.agent !== 'visualization')
291
+ continue;
292
+ if (result.status < 200 || result.status >= 300 || !result.response)
293
+ continue;
294
+ const resp = result.response;
295
+ const panels = [];
296
+ for (const item of extractArray(resp, 'panels', 'dashboards')) {
297
+ if (typeof item === 'object' && item !== null) {
298
+ const p = item;
299
+ panels.push({
300
+ title: String(p['title'] ?? ''),
301
+ metricQuery: String(p['metricQuery'] ?? p['query'] ?? ''),
302
+ visualization: normalizeVisualization(p['visualization']),
303
+ thresholds: extractThresholds(p['thresholds']),
304
+ });
305
+ }
306
+ }
307
+ const alertRules = [];
308
+ for (const item of extractArray(resp, 'alertRules', 'alerts')) {
309
+ if (typeof item === 'object' && item !== null) {
310
+ const a = item;
311
+ alertRules.push({
312
+ condition: String(a['condition'] ?? ''),
313
+ severity: normalizeAlertSeverity(a['severity']),
314
+ notificationChannel: String(a['notificationChannel'] ?? a['channel'] ?? 'engineering'),
315
+ });
316
+ }
317
+ }
318
+ if (panels.length > 0) {
319
+ return {
320
+ name: String(resp['name'] ?? 'Agentics Deployment Dashboard'),
321
+ panels,
322
+ alertRules: alertRules.length > 0 ? alertRules : defaults.alertRules,
323
+ };
324
+ }
325
+ }
326
+ return defaults;
327
+ }
328
+ // ============================================================================
329
+ // Workstream B: Incidents
330
+ // ============================================================================
331
+ function extractIncidents(ws) {
332
+ const incidents = [];
333
+ if (!ws)
334
+ return incidents;
335
+ for (const result of ws.agentResults) {
336
+ if (result.status < 200 || result.status >= 300 || !result.response)
337
+ continue;
338
+ const resp = result.response;
339
+ for (const item of extractArray(resp, 'incidents', 'issues', 'findings')) {
340
+ if (typeof item === 'object' && item !== null) {
341
+ const inc = item;
342
+ incidents.push({
343
+ id: String(inc['id'] ?? crypto.randomUUID()),
344
+ severity: normalizeIncidentSeverity(inc['severity']),
345
+ description: String(inc['description'] ?? ''),
346
+ detectedAt: String(inc['detectedAt'] ?? new Date().toISOString()),
347
+ status: normalizeIncidentStatus(inc['status']),
348
+ requiresHumanReview: inc['requiresHumanReview'] === true || inc['severity'] === 'P1',
349
+ });
350
+ }
351
+ }
352
+ }
353
+ return incidents;
354
+ }
355
+ // ============================================================================
356
+ // Workstream C: Learning Loop (RETRIEVE → JUDGE → DISTILL → CONSOLIDATE)
357
+ // ============================================================================
358
+ function extractLearnedPatterns(ws, graph) {
359
+ const patterns = [];
360
+ const execId = graph.getExecutionId();
361
+ if (ws) {
362
+ for (const result of ws.agentResults) {
363
+ if (result.status < 200 || result.status >= 300 || !result.response)
364
+ continue;
365
+ const resp = result.response;
366
+ for (const item of extractArray(resp, 'patterns', 'learnedPatterns', 'results')) {
367
+ if (typeof item === 'object' && item !== null) {
368
+ const p = item;
369
+ patterns.push({
370
+ id: String(p['id'] ?? crypto.randomUUID()),
371
+ type: normalizePatternType(p['type']),
372
+ domain: String(p['domain'] ?? 'general'),
373
+ description: String(p['description'] ?? ''),
374
+ evidence: {
375
+ executionId: execId,
376
+ predicted: String(p['predicted'] ?? p['evidence']?.['predicted'] ?? ''),
377
+ actual: String(p['actual'] ?? p['evidence']?.['actual'] ?? ''),
378
+ verdict: normalizeVerdict(p['verdict'] ?? p['evidence']?.['verdict']),
379
+ },
380
+ adjustment: String(p['adjustment'] ?? ''),
381
+ confidence: typeof p['confidence'] === 'number' ? Math.max(0, Math.min(1, p['confidence'])) : 0.5,
382
+ applicableWhen: extractStringArray(p, 'applicableWhen', 'conditions'),
383
+ });
384
+ }
385
+ }
386
+ }
387
+ }
388
+ return patterns;
389
+ }
390
+ /** Execute the 4-step learning cycle: RETRIEVE → JUDGE → DISTILL → CONSOLIDATE. */
391
+ function runLearningCycle(graph, patterns) {
392
+ const execId = graph.getExecutionId();
393
+ const stepsCompleted = [];
394
+ const verdicts = [];
395
+ // RETRIEVE: Check for prior predictions
396
+ const scenarioNodes = graph.getNodesByType('scenario');
397
+ const costNodes = graph.getNodesByType('cost_model');
398
+ const riskNodes = graph.getNodesByType('risk_signal');
399
+ stepsCompleted.push('retrieve');
400
+ // JUDGE: Compare predictions with actuals (from telemetry/health checks)
401
+ const healthNodes = graph.getNodesByType('health_check');
402
+ const telemetryNodes = graph.getNodesByType('telemetry_config');
403
+ if (scenarioNodes.length > 0) {
404
+ const hasOperationalData = healthNodes.length > 0 || telemetryNodes.length > 0;
405
+ verdicts.push({
406
+ domain: 'scenario_accuracy',
407
+ verdict: hasOperationalData ? 'partially_correct' : 'correct', // No contrary evidence
408
+ });
409
+ }
410
+ if (costNodes.length > 0) {
411
+ verdicts.push({ domain: 'cost_estimation', verdict: 'partially_correct' });
412
+ }
413
+ if (riskNodes.length > 0) {
414
+ verdicts.push({ domain: 'risk_assessment', verdict: 'correct' });
415
+ }
416
+ stepsCompleted.push('judge');
417
+ // DISTILL: Patterns already extracted from learning agents
418
+ stepsCompleted.push('distill');
419
+ // CONSOLIDATE: Merge with existing knowledge (stored in memory-graph)
420
+ stepsCompleted.push('consolidate');
421
+ return {
422
+ executionId: execId,
423
+ timestamp: new Date().toISOString(),
424
+ stepsCompleted,
425
+ patternsLearned: patterns,
426
+ feedbackProcessed: 0,
427
+ verdicts,
428
+ };
429
+ }
430
+ // ============================================================================
431
+ // DecisionGraph Write
432
+ // ============================================================================
433
+ function writeToGraph(graph, telemetryConfig, healthChecks, dashboardSpec, learnedPatterns, learningCycle, tracker, pass) {
434
+ const nodeIds = [];
435
+ const priorIds = graph.getNodesByPass(6).map(n => n.id).slice(0, 5);
436
+ // Telemetry config node
437
+ const telNode = graph.createNode({
438
+ type: 'telemetry_config',
439
+ name: 'Telemetry Configuration',
440
+ content: telemetryConfig,
441
+ summary: `Telemetry configured: ${telemetryConfig.metrics.length} metric(s), ${telemetryConfig.healthChecks.length} health check(s). Interval: ${telemetryConfig.collectionIntervalMs}ms.`,
442
+ producedBy: { domain: 'observatory', agent: 'telemetry', role: 'Telemetry Collector' },
443
+ pass,
444
+ derivedFrom: priorIds,
445
+ confidence: 0.9,
446
+ tags: ['telemetry', 'observability'],
447
+ });
448
+ nodeIds.push(telNode.id);
449
+ // Health check nodes (one per check)
450
+ for (const check of healthChecks) {
451
+ const hcNode = graph.createNode({
452
+ type: 'health_check',
453
+ name: `Health Check: ${check.endpointUrl}`,
454
+ content: check,
455
+ summary: `${check.endpointUrl}: ${check.status} (${check.latencyMs}ms)`,
456
+ producedBy: { domain: 'observatory', agent: 'health-check', role: 'Health Check' },
457
+ pass,
458
+ derivedFrom: [telNode.id],
459
+ confidence: check.status === 'healthy' ? 0.95 : check.status === 'degraded' ? 0.5 : 0.2,
460
+ tags: [`health:${check.status}`, 'observability'],
461
+ });
462
+ nodeIds.push(hcNode.id);
463
+ }
464
+ // Dashboard spec as part of telemetry config
465
+ graph.createNode({
466
+ type: 'telemetry_config',
467
+ name: 'Dashboard Specification',
468
+ content: dashboardSpec,
469
+ summary: `Dashboard: ${dashboardSpec.name} — ${dashboardSpec.panels.length} panel(s), ${dashboardSpec.alertRules.length} alert rule(s).`,
470
+ producedBy: { domain: 'observatory', agent: 'visualization', role: 'Visualization Spec' },
471
+ pass,
472
+ derivedFrom: [telNode.id],
473
+ confidence: 0.85,
474
+ tags: ['dashboard', 'observability'],
475
+ });
476
+ // Learned pattern nodes
477
+ for (const pattern of learnedPatterns) {
478
+ const pNode = graph.createNode({
479
+ type: 'learned_pattern',
480
+ name: `Learned Pattern: ${pattern.domain}`,
481
+ content: pattern,
482
+ summary: `${pattern.type} in ${pattern.domain}: ${pattern.description.slice(0, 80)}`,
483
+ producedBy: { domain: 'memory-graph', agent: 'patterns', role: 'Approval Learning' },
484
+ pass,
485
+ derivedFrom: priorIds,
486
+ confidence: pattern.confidence,
487
+ tags: [`pattern:${pattern.type}`, `domain:${pattern.domain}`, 'learning'],
488
+ });
489
+ nodeIds.push(pNode.id);
490
+ }
491
+ // Learning cycle summary node
492
+ graph.createNode({
493
+ type: 'learned_pattern',
494
+ name: 'Learning Cycle Summary',
495
+ content: learningCycle,
496
+ summary: `Learning cycle: ${learningCycle.stepsCompleted.length}/4 steps, ${learningCycle.patternsLearned.length} pattern(s), ${learningCycle.verdicts.length} verdict(s).`,
497
+ producedBy: { domain: 'pipeline', agent: 'pass7-learning', role: 'Learning Loop' },
498
+ pass,
499
+ derivedFrom: nodeIds.slice(0, 5),
500
+ confidence: 0.8,
501
+ tags: ['learning-cycle', 'consolidation'],
502
+ });
503
+ // Provenance
504
+ tracker.recordInvocation({
505
+ agent: { domain: 'pipeline', agent: 'pass7-setup', role: 'Observability Setup' },
506
+ pass,
507
+ passName: 'Observability & Continuous Learning',
508
+ workstream: 'initial-setup',
509
+ startedAt: new Date().toISOString(),
510
+ completedAt: new Date().toISOString(),
511
+ durationMs: 0,
512
+ inputNodeIds: priorIds,
513
+ outputNodeIds: nodeIds,
514
+ artifactNumbers: [],
515
+ status: 'success',
516
+ confidence: 0.85,
517
+ });
518
+ return nodeIds;
519
+ }
520
+ // ============================================================================
521
+ // Default Agent Invoker
522
+ // ============================================================================
523
+ async function defaultInvokeAgents(agents, payload, pass, _timeoutMs) {
524
+ const promises = agents.map(async (agent) => {
525
+ const start = Date.now();
526
+ const timestamp = new Date().toISOString();
527
+ try {
528
+ const { executeAgentsInvokeCommand } = await import('../../commands/agents.js');
529
+ const result = await executeAgentsInvokeCommand(agent.domain, agent.agent, JSON.stringify(payload), { format: 'json' });
530
+ return { agent, status: result.status, response: result.response, durationMs: Date.now() - start, pass, timestamp };
531
+ }
532
+ catch (err) {
533
+ return { agent, status: 500, response: { error: err instanceof Error ? err.message : String(err) }, durationMs: Date.now() - start, pass, timestamp };
534
+ }
535
+ });
536
+ const settled = await Promise.allSettled(promises);
537
+ return settled.map((outcome, i) => outcome.status === 'fulfilled'
538
+ ? outcome.value
539
+ : { agent: agents[i], status: 500, response: { error: String(outcome.reason) }, durationMs: 0, pass, timestamp: new Date().toISOString() });
540
+ }
541
+ // ============================================================================
542
+ // Normalization Helpers
543
+ // ============================================================================
544
+ function normalizeHealthCheck(raw, now) {
545
+ return {
546
+ endpointUrl: String(raw['endpointUrl'] ?? raw['url'] ?? raw['endpoint'] ?? '/health'),
547
+ status: normalizeHealthStatus(raw['status']),
548
+ latencyMs: Number(raw['latencyMs'] ?? raw['latency'] ?? 0),
549
+ lastChecked: String(raw['lastChecked'] ?? now),
550
+ checkInterval: String(raw['checkInterval'] ?? raw['interval'] ?? 'PT5M'),
551
+ failureCount: Number(raw['failureCount'] ?? 0),
552
+ alertThreshold: Number(raw['alertThreshold'] ?? 3),
553
+ };
554
+ }
555
+ function normalizeHealthStatus(raw) {
556
+ const s = String(raw ?? '').toLowerCase();
557
+ if (s === 'degraded')
558
+ return 'degraded';
559
+ if (s === 'unhealthy' || s === 'down' || s === 'failed')
560
+ return 'unhealthy';
561
+ return 'healthy';
562
+ }
563
+ function normalizeMetricCategory(raw) {
564
+ const s = String(raw ?? '').toLowerCase().replace(/[\s-]/g, '_');
565
+ const valid = new Set(['availability', 'performance', 'usage', 'errors', 'sla_compliance']);
566
+ return valid.has(s) ? s : 'performance';
567
+ }
568
+ function normalizeVisualization(raw) {
569
+ const s = String(raw ?? '').toLowerCase();
570
+ const valid = new Set(['timeseries', 'gauge', 'table', 'heatmap']);
571
+ return valid.has(s) ? s : 'timeseries';
572
+ }
573
+ function normalizeAlertSeverity(raw) {
574
+ const s = String(raw ?? '').toLowerCase();
575
+ if (s === 'critical')
576
+ return 'critical';
577
+ if (s === 'info')
578
+ return 'info';
579
+ return 'warning';
580
+ }
581
+ function normalizeIncidentSeverity(raw) {
582
+ const s = String(raw ?? '').toUpperCase();
583
+ if (s === 'P1' || s === 'CRITICAL')
584
+ return 'P1';
585
+ if (s === 'P2' || s === 'HIGH')
586
+ return 'P2';
587
+ if (s === 'P3' || s === 'MEDIUM')
588
+ return 'P3';
589
+ return 'P4';
590
+ }
591
+ function normalizeIncidentStatus(raw) {
592
+ const s = String(raw ?? '').toLowerCase();
593
+ if (s === 'investigating')
594
+ return 'investigating';
595
+ if (s === 'mitigated')
596
+ return 'mitigated';
597
+ if (s === 'resolved')
598
+ return 'resolved';
599
+ return 'open';
600
+ }
601
+ function normalizePatternType(raw) {
602
+ const s = String(raw ?? '').toLowerCase().replace(/[\s-]/g, '_');
603
+ if (s === 'success_pattern')
604
+ return 'success_pattern';
605
+ if (s === 'anti_pattern')
606
+ return 'anti_pattern';
607
+ return 'calibration_adjustment';
608
+ }
609
+ function normalizeVerdict(raw) {
610
+ const s = String(raw ?? '').toLowerCase().replace(/[\s-]/g, '_');
611
+ if (s === 'correct')
612
+ return 'correct';
613
+ if (s === 'incorrect')
614
+ return 'incorrect';
615
+ return 'partially_correct';
616
+ }
617
+ function extractThresholds(raw) {
618
+ if (!Array.isArray(raw))
619
+ return [];
620
+ return raw.filter(t => typeof t === 'object' && t !== null).map(t => {
621
+ const r = t;
622
+ return { value: Number(r['value'] ?? 0), color: String(r['color'] ?? 'green') };
623
+ });
624
+ }
625
+ function extractArray(obj, ...keys) {
626
+ for (const k of keys) {
627
+ const v = obj[k];
628
+ if (Array.isArray(v))
629
+ return v;
630
+ }
631
+ return [];
632
+ }
633
+ function extractStringArray(obj, ...keys) {
634
+ return extractArray(obj, ...keys).map(String);
635
+ }
636
+ //# sourceMappingURL=pass7-observability.js.map