@gracker/smartperfetto 1.0.15 → 1.0.16

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 (156) hide show
  1. package/dist/agent/agents/base/baseAgent.d.ts.map +1 -1
  2. package/dist/agent/agents/base/baseAgent.js +5 -1
  3. package/dist/agent/agents/base/baseAgent.js.map +1 -1
  4. package/dist/agent/context/enhancedSessionContext.d.ts +5 -0
  5. package/dist/agent/context/enhancedSessionContext.d.ts.map +1 -1
  6. package/dist/agent/context/enhancedSessionContext.js +13 -0
  7. package/dist/agent/context/enhancedSessionContext.js.map +1 -1
  8. package/dist/agent/core/conclusionContract.d.ts +16 -1
  9. package/dist/agent/core/conclusionContract.d.ts.map +1 -1
  10. package/dist/agent/core/conclusionGenerator.d.ts.map +1 -1
  11. package/dist/agent/core/conclusionGenerator.js +90 -7
  12. package/dist/agent/core/conclusionGenerator.js.map +1 -1
  13. package/dist/agent/core/executors/directSkillExecutor.d.ts.map +1 -1
  14. package/dist/agent/core/executors/directSkillExecutor.js +6 -12
  15. package/dist/agent/core/executors/directSkillExecutor.js.map +1 -1
  16. package/dist/agent/core/orchestratorTypes.d.ts +6 -0
  17. package/dist/agent/core/orchestratorTypes.d.ts.map +1 -1
  18. package/dist/agent/core/orchestratorTypes.js.map +1 -1
  19. package/dist/agent/experts/crossDomain/moduleExpertInvoker.d.ts.map +1 -1
  20. package/dist/agent/experts/crossDomain/moduleExpertInvoker.js +4 -1
  21. package/dist/agent/experts/crossDomain/moduleExpertInvoker.js.map +1 -1
  22. package/dist/agent/scene/sceneStage1Runner.d.ts +1 -1
  23. package/dist/agent/scene/sceneStage1Runner.d.ts.map +1 -1
  24. package/dist/agent/scene/sceneStage1Runner.js +1 -1
  25. package/dist/agent/scene/sceneStage1Runner.js.map +1 -1
  26. package/dist/agent/scene/sceneStoryService.d.ts +1 -1
  27. package/dist/agent/scene/sceneStoryService.d.ts.map +1 -1
  28. package/dist/agent/scene/sceneStoryService.js +4 -1
  29. package/dist/agent/scene/sceneStoryService.js.map +1 -1
  30. package/dist/agent/types/agentProtocol.d.ts.map +1 -1
  31. package/dist/agent/types/agentProtocol.js +4 -1
  32. package/dist/agent/types/agentProtocol.js.map +1 -1
  33. package/dist/agent/types.d.ts +7 -0
  34. package/dist/agent/types.d.ts.map +1 -1
  35. package/dist/agent/types.js.map +1 -1
  36. package/dist/agentv3/artifactStore.d.ts +5 -0
  37. package/dist/agentv3/artifactStore.d.ts.map +1 -1
  38. package/dist/agentv3/artifactStore.js +3 -0
  39. package/dist/agentv3/artifactStore.js.map +1 -1
  40. package/dist/agentv3/claudeMcpServer.d.ts.map +1 -1
  41. package/dist/agentv3/claudeMcpServer.js +125 -86
  42. package/dist/agentv3/claudeMcpServer.js.map +1 -1
  43. package/dist/agentv3/claudeRuntime.js.map +1 -1
  44. package/dist/agentv3/sessionStateSnapshot.d.ts +23 -0
  45. package/dist/agentv3/sessionStateSnapshot.d.ts.map +1 -1
  46. package/dist/assistant/application/agentAnalyzeSessionService.d.ts +6 -0
  47. package/dist/assistant/application/agentAnalyzeSessionService.d.ts.map +1 -1
  48. package/dist/assistant/application/agentAnalyzeSessionService.js +9 -3
  49. package/dist/assistant/application/agentAnalyzeSessionService.js.map +1 -1
  50. package/dist/assistant/application/assistantApplicationService.d.ts.map +1 -1
  51. package/dist/assistant/application/assistantApplicationService.js +3 -1
  52. package/dist/assistant/application/assistantApplicationService.js.map +1 -1
  53. package/dist/cli-user/commands/report.js +64 -0
  54. package/dist/cli-user/commands/report.js.map +1 -1
  55. package/dist/cli-user/io/paths.d.ts +3 -0
  56. package/dist/cli-user/io/paths.d.ts.map +1 -1
  57. package/dist/cli-user/io/paths.js +6 -0
  58. package/dist/cli-user/io/paths.js.map +1 -1
  59. package/dist/cli-user/io/sessionStore.d.ts +1 -0
  60. package/dist/cli-user/io/sessionStore.d.ts.map +1 -1
  61. package/dist/cli-user/io/sessionStore.js +5 -0
  62. package/dist/cli-user/io/sessionStore.js.map +1 -1
  63. package/dist/cli-user/repl/renderer.d.ts +8 -0
  64. package/dist/cli-user/repl/renderer.d.ts.map +1 -1
  65. package/dist/cli-user/repl/renderer.js.map +1 -1
  66. package/dist/cli-user/services/cliAnalyzeService.d.ts +3 -0
  67. package/dist/cli-user/services/cliAnalyzeService.d.ts.map +1 -1
  68. package/dist/cli-user/services/cliAnalyzeService.js +67 -0
  69. package/dist/cli-user/services/cliAnalyzeService.js.map +1 -1
  70. package/dist/cli-user/services/turnPersistence.d.ts +0 -10
  71. package/dist/cli-user/services/turnPersistence.d.ts.map +1 -1
  72. package/dist/cli-user/services/turnPersistence.js +62 -0
  73. package/dist/cli-user/services/turnPersistence.js.map +1 -1
  74. package/dist/routes/agentReportRoutes.d.ts +1 -0
  75. package/dist/routes/agentReportRoutes.d.ts.map +1 -1
  76. package/dist/routes/agentReportRoutes.js +13 -2
  77. package/dist/routes/agentReportRoutes.js.map +1 -1
  78. package/dist/routes/agentResumeRoutes.d.ts.map +1 -1
  79. package/dist/routes/agentResumeRoutes.js +29 -5
  80. package/dist/routes/agentResumeRoutes.js.map +1 -1
  81. package/dist/routes/agentRoutes.d.ts.map +1 -1
  82. package/dist/routes/agentRoutes.js +293 -91
  83. package/dist/routes/agentRoutes.js.map +1 -1
  84. package/dist/services/agentEventStore.d.ts.map +1 -1
  85. package/dist/services/agentEventStore.js +13 -3
  86. package/dist/services/agentEventStore.js.map +1 -1
  87. package/dist/services/agentReportData.d.ts +3 -0
  88. package/dist/services/agentReportData.d.ts.map +1 -1
  89. package/dist/services/agentReportData.js.map +1 -1
  90. package/dist/services/analysisResultSnapshotPipeline.d.ts +3 -0
  91. package/dist/services/analysisResultSnapshotPipeline.d.ts.map +1 -1
  92. package/dist/services/analysisResultSnapshotPipeline.js +3 -0
  93. package/dist/services/analysisResultSnapshotPipeline.js.map +1 -1
  94. package/dist/services/analysisResultSnapshotStore.d.ts.map +1 -1
  95. package/dist/services/analysisResultSnapshotStore.js +34 -2
  96. package/dist/services/analysisResultSnapshotStore.js.map +1 -1
  97. package/dist/services/enterpriseSchema.d.ts.map +1 -1
  98. package/dist/services/enterpriseSchema.js +11 -0
  99. package/dist/services/enterpriseSchema.js.map +1 -1
  100. package/dist/services/evidence/evidenceContractBuilder.d.ts +11 -0
  101. package/dist/services/evidence/evidenceContractBuilder.d.ts.map +1 -0
  102. package/dist/services/evidence/evidenceContractBuilder.js +530 -0
  103. package/dist/services/evidence/evidenceContractBuilder.js.map +1 -0
  104. package/dist/services/htmlReportGenerator.d.ts +7 -0
  105. package/dist/services/htmlReportGenerator.d.ts.map +1 -1
  106. package/dist/services/htmlReportGenerator.js +66 -0
  107. package/dist/services/htmlReportGenerator.js.map +1 -1
  108. package/dist/services/persistAgentSession.d.ts.map +1 -1
  109. package/dist/services/persistAgentSession.js +5 -0
  110. package/dist/services/persistAgentSession.js.map +1 -1
  111. package/dist/services/processIdentity/identityContractMapper.d.ts +14 -0
  112. package/dist/services/processIdentity/identityContractMapper.d.ts.map +1 -0
  113. package/dist/services/processIdentity/identityContractMapper.js +135 -0
  114. package/dist/services/processIdentity/identityContractMapper.js.map +1 -0
  115. package/dist/services/processIdentity/types.d.ts +5 -0
  116. package/dist/services/processIdentity/types.d.ts.map +1 -1
  117. package/dist/services/processIdentity/types.js.map +1 -1
  118. package/dist/services/skillEngine/skillExecutor.d.ts +14 -2
  119. package/dist/services/skillEngine/skillExecutor.d.ts.map +1 -1
  120. package/dist/services/skillEngine/skillExecutor.js +133 -13
  121. package/dist/services/skillEngine/skillExecutor.js.map +1 -1
  122. package/dist/services/skillEngine/types.d.ts +2 -0
  123. package/dist/services/skillEngine/types.d.ts.map +1 -1
  124. package/dist/services/verifier/claimVerificationRunner.d.ts +20 -0
  125. package/dist/services/verifier/claimVerificationRunner.d.ts.map +1 -0
  126. package/dist/services/verifier/claimVerificationRunner.js +88 -0
  127. package/dist/services/verifier/claimVerificationRunner.js.map +1 -0
  128. package/dist/services/verifier/deterministicClaimVerifier.d.ts +8 -0
  129. package/dist/services/verifier/deterministicClaimVerifier.d.ts.map +1 -0
  130. package/dist/services/verifier/deterministicClaimVerifier.js +178 -0
  131. package/dist/services/verifier/deterministicClaimVerifier.js.map +1 -0
  132. package/dist/types/claimVerification.d.ts +38 -0
  133. package/dist/types/claimVerification.d.ts.map +1 -0
  134. package/dist/types/claimVerification.js +6 -0
  135. package/dist/types/claimVerification.js.map +1 -0
  136. package/dist/types/dataContract.d.ts +30 -0
  137. package/dist/types/dataContract.d.ts.map +1 -1
  138. package/dist/types/dataContract.js +7 -0
  139. package/dist/types/dataContract.js.map +1 -1
  140. package/dist/types/evidenceContract.d.ts +100 -0
  141. package/dist/types/evidenceContract.d.ts.map +1 -0
  142. package/dist/types/evidenceContract.js +6 -0
  143. package/dist/types/evidenceContract.js.map +1 -0
  144. package/dist/types/identityContract.d.ts +57 -0
  145. package/dist/types/identityContract.d.ts.map +1 -0
  146. package/dist/types/identityContract.js +6 -0
  147. package/dist/types/identityContract.js.map +1 -0
  148. package/dist/types/multiTraceComparison.d.ts +3 -0
  149. package/dist/types/multiTraceComparison.d.ts.map +1 -1
  150. package/package.json +1 -1
  151. package/skills/atomic/process_identity_resolver.skill.yaml +130 -1
  152. package/skills/atomic/process_slice_cpu_hotspots.skill.yaml +321 -0
  153. package/strategies/anr.strategy.md +2 -2
  154. package/strategies/game.strategy.md +1 -1
  155. package/strategies/general.strategy.md +1 -1
  156. package/strategies/scrolling.strategy.md +1 -0
@@ -92,6 +92,7 @@ const analysisRunStore_1 = require("../services/analysisRunStore");
92
92
  const agentAnalyzeSessionService_1 = require("../assistant/application/agentAnalyzeSessionService");
93
93
  const assistantResultContract_1 = require("../assistant/contracts/assistantResultContract");
94
94
  const analysisResultSnapshotPipeline_1 = require("../services/analysisResultSnapshotPipeline");
95
+ const claimVerificationRunner_1 = require("../services/verifier/claimVerificationRunner");
95
96
  // DataEnvelope types for v2.0 data contract
96
97
  const dataContract_1 = require("../types/dataContract");
97
98
  const skillExecutor_1 = require("../services/skillEngine/skillExecutor");
@@ -412,6 +413,51 @@ function sendReplayableSessionEvent(session, res, eventType, payload) {
412
413
  streamProjector.sendEvent(res, eventType, payload, event.seqId);
413
414
  return event.seqId;
414
415
  }
416
+ function appendAndPersistReplayableSessionEvent(session, eventType, payload) {
417
+ const event = (0, sessionSseReplay_1.appendReplayableSseEvent)(session, eventType, payload);
418
+ persistBufferedAgentEvent(session, {
419
+ cursor: event.seqId,
420
+ eventType: event.eventType,
421
+ eventData: event.eventData,
422
+ createdAt: Date.now(),
423
+ });
424
+ return event;
425
+ }
426
+ function writeBufferedSessionEvent(res, event) {
427
+ res.write(`id: ${event.seqId}\n`);
428
+ res.write(`event: ${event.eventType}\n`);
429
+ res.write(`data: ${event.eventData}\n\n`);
430
+ }
431
+ function loadPersistedCompletedAnalysisSseEvents(session) {
432
+ const scope = agentEventScopeFromSession(session);
433
+ if (!scope)
434
+ return [];
435
+ const events = (0, agentEventStore_1.listSerializedAgentEventsAfter)(scope, scope.runId, 0)
436
+ .filter(event => event.eventType === 'snapshot_created' ||
437
+ event.eventType === 'analysis_completed' ||
438
+ event.eventType === 'scene_reconstruction_completed' ||
439
+ event.eventType === 'end')
440
+ .map(event => ({
441
+ seqId: event.cursor,
442
+ eventType: event.eventType,
443
+ eventData: event.eventData,
444
+ }));
445
+ if (!events.some(event => event.eventType === 'analysis_completed') ||
446
+ !events.some(event => event.eventType === 'end')) {
447
+ return [];
448
+ }
449
+ session.sseEventSeq = Math.max(session.sseEventSeq || 0, ...events.map(event => event.seqId));
450
+ const existing = new Set(session.sseEventBuffer.map(event => `${event.seqId}:${event.eventType}`));
451
+ for (const event of events) {
452
+ const key = `${event.seqId}:${event.eventType}`;
453
+ if (!existing.has(key))
454
+ session.sseEventBuffer.push(event);
455
+ }
456
+ if (session.sseEventBuffer.length > streamProjector_1.SSE_RING_BUFFER_SIZE) {
457
+ session.sseEventBuffer.splice(0, session.sseEventBuffer.length - streamProjector_1.SSE_RING_BUFFER_SIZE);
458
+ }
459
+ return events;
460
+ }
415
461
  function resolveSessionContextForReview(sessionId) {
416
462
  const activeSession = assistantAppService.getSession(sessionId);
417
463
  if (activeSession) {
@@ -607,6 +653,10 @@ function buildRecoveredResultFromContext(sessionId, context) {
607
653
  partial: turn.result.partial,
608
654
  terminationReason: turn.result.terminationReason,
609
655
  terminationMessage: turn.result.terminationMessage,
656
+ conclusionContract: turn.result.conclusionContract,
657
+ claimSupport: turn.result.claimSupport,
658
+ claimVerificationResult: turn.result.claimVerificationResult,
659
+ identityResolutions: turn.result.identityResolutions,
610
660
  };
611
661
  }
612
662
  function recoverResultForSessionIfNeeded(sessionId, session) {
@@ -1180,11 +1230,8 @@ function handleSessionStream(req, res, sessionId) {
1180
1230
  recoverResultForSessionIfNeeded(sessionId, session);
1181
1231
  if (session.result) {
1182
1232
  sendAgentDrivenResult(res, session);
1183
- sendReplayableSessionEvent(session, res, 'end', {
1184
- timestamp: Date.now(),
1185
- ...buildStreamObservability(session),
1186
- });
1187
1233
  res.end();
1234
+ assistantAppService.removeSseClient(sessionId, res);
1188
1235
  return;
1189
1236
  }
1190
1237
  }
@@ -1266,16 +1313,35 @@ router.get('/:sessionId/status', (req, res) => {
1266
1313
  sceneId: sceneIdHint,
1267
1314
  }) ||
1268
1315
  undefined;
1316
+ const qualityArtifacts = recoveredResult.claimSupport &&
1317
+ recoveredResult.claimVerificationResult &&
1318
+ recoveredResult.identityResolutions
1319
+ ? {
1320
+ claimSupport: recoveredResult.claimSupport,
1321
+ claimVerificationResult: recoveredResult.claimVerificationResult,
1322
+ identityResolutions: recoveredResult.identityResolutions,
1323
+ }
1324
+ : ensureAnalysisQualityArtifacts(session, conclusionContract, recoveredResult);
1325
+ const completedPayload = ensureCompletedAnalysisResultPayload(session);
1326
+ const finalArtifacts = completedPayload?.finalArtifacts;
1327
+ const normalizedCompletedConclusion = completedPayload?.normalizedConclusion || conclusion;
1328
+ const normalizedCompletedContract = completedPayload?.normalizedConclusionContract || conclusionContract;
1269
1329
  response.result = {
1270
- answer: conclusion,
1271
- conclusion,
1272
- conclusionContract,
1330
+ answer: normalizedCompletedConclusion,
1331
+ conclusion: normalizedCompletedConclusion,
1332
+ conclusionContract: normalizedCompletedContract,
1333
+ claimSupport: qualityArtifacts.claimSupport,
1334
+ claimVerificationResult: qualityArtifacts.claimVerificationResult,
1335
+ identityResolutions: qualityArtifacts.identityResolutions,
1273
1336
  confidence: recoveredResult.confidence,
1274
1337
  totalDurationMs: recoveredResult.totalDurationMs,
1275
1338
  rounds: recoveredResult.rounds,
1276
1339
  partial: recoveredResult.partial,
1277
1340
  terminationReason: recoveredResult.terminationReason,
1278
1341
  terminationMessage: recoveredResult.terminationMessage,
1342
+ reportUrl: finalArtifacts?.reportUrl,
1343
+ reportError: finalArtifacts?.reportError,
1344
+ resultSnapshotId: finalArtifacts?.resultSnapshotId,
1279
1345
  findings: recoveredResult.findings,
1280
1346
  findingsCount: recoveredResult.findings.length,
1281
1347
  resultContract,
@@ -2233,6 +2299,7 @@ async function detectScenesQuick(traceProcessorService, traceId) {
2233
2299
  normalizeNarrativeForClient,
2234
2300
  buildClientFindings,
2235
2301
  buildSessionResultContract,
2302
+ getCompletedPayload: ensureCompletedAnalysisResultPayload,
2236
2303
  });
2237
2304
  // ============================================================================
2238
2305
  // Agent-Driven Analysis Helper Functions (Phase 2-4)
@@ -2311,9 +2378,14 @@ async function runAgentDrivenAnalysis(sessionId, query, traceId, options = {}) {
2311
2378
  console.log(`[AgentRoutes.AgentDriven] Received event: ${update.type}`, update.content?.phase);
2312
2379
  logger.debug('Stream', `Update: ${update.type}`, update.content);
2313
2380
  const normalizedUpdate = augmentConclusionUpdateWithEvidenceIndex(session, normalizeAgentDrivenUpdate(update));
2314
- // Broadcast the original event so the frontend receives raw events
2315
- // (answer_token, thought, agent_response, conclusion, etc.) for rendering.
2316
- broadcastToAgentDrivenClients(sessionId, normalizedUpdate);
2381
+ // Final narrative is emitted through analysis_completed after deterministic
2382
+ // evidence/claim verification has run. Suppress early conclusion events so
2383
+ // clients do not render an unverified terminal answer.
2384
+ const shouldBroadcastOriginalUpdate = normalizedUpdate.type !== 'conclusion' &&
2385
+ normalizedUpdate.type !== 'answer_token';
2386
+ if (shouldBroadcastOriginalUpdate) {
2387
+ broadcastToAgentDrivenClients(sessionId, normalizedUpdate);
2388
+ }
2317
2389
  // Also derive a conversation_step for the timeline/observability layer.
2318
2390
  const conversationStep = buildConversationStepUpdate(session, normalizedUpdate);
2319
2391
  if (conversationStep) {
@@ -2361,7 +2433,7 @@ async function runAgentDrivenAnalysis(sessionId, query, traceId, options = {}) {
2361
2433
  // (answer_token, thought, conclusion, etc.) are already broadcast above
2362
2434
  // and remapping would cause duplicate delivery to the frontend.
2363
2435
  const eventType = mapToAgentDrivenEventType(normalizedUpdate);
2364
- if (eventType !== normalizedUpdate.type) {
2436
+ if (shouldBroadcastOriginalUpdate && eventType !== normalizedUpdate.type) {
2365
2437
  broadcastToAgentDrivenClients(sessionId, {
2366
2438
  type: eventType,
2367
2439
  content: normalizedUpdate.content,
@@ -2440,6 +2512,7 @@ async function runAgentDrivenAnalysis(sessionId, query, traceId, options = {}) {
2440
2512
  });
2441
2513
  console.log('[AgentRoutes.AgentDriven] analyze completed, success:', result.success);
2442
2514
  session.result = result;
2515
+ delete session.completedAnalysisFinalArtifacts;
2443
2516
  // Accumulate hypotheses across turns (deduplicate by id)
2444
2517
  const existingIds = new Set(session.hypotheses.map(h => h.id));
2445
2518
  for (const h of result.hypotheses) {
@@ -2454,10 +2527,6 @@ async function runAgentDrivenAnalysis(sessionId, query, traceId, options = {}) {
2454
2527
  }
2455
2528
  }
2456
2529
  const terminalRunStatus = terminalRunStatusForResult(result);
2457
- session.status = terminalRunStatus === 'quota_exceeded'
2458
- ? 'quota_exceeded'
2459
- : result.success ? 'completed' : 'failed';
2460
- markSessionRunStatus(session, terminalRunStatus);
2461
2530
  // Record conclusion in cross-turn history
2462
2531
  if (!session.conclusionHistory)
2463
2532
  session.conclusionHistory = [];
@@ -2496,12 +2565,35 @@ async function runAgentDrivenAnalysis(sessionId, query, traceId, options = {}) {
2496
2565
  };
2497
2566
  }
2498
2567
  }
2568
+ if (result.success || result.partial === true) {
2569
+ const sceneIdHint = resolveConclusionSceneIdHint({
2570
+ sessionId,
2571
+ query,
2572
+ findings: result.findings,
2573
+ });
2574
+ const normalizedConclusionContract = (result.conclusionContract ||
2575
+ (0, agentResultNormalizer_1.deriveConclusionContractForNarrative)(result.conclusion, {
2576
+ mode: result.rounds > 1 ? 'focused_answer' : 'initial_report',
2577
+ sceneId: sceneIdHint,
2578
+ }) ||
2579
+ undefined);
2580
+ if (normalizedConclusionContract) {
2581
+ result.conclusionContract = normalizedConclusionContract;
2582
+ }
2583
+ ensureAnalysisQualityArtifacts(session, normalizedConclusionContract);
2584
+ }
2585
+ session.status = terminalRunStatus === 'quota_exceeded'
2586
+ ? 'quota_exceeded'
2587
+ : result.success ? 'completed' : 'failed';
2588
+ markSessionRunStatus(session, terminalRunStatus);
2499
2589
  // Log completion details
2500
2590
  logger.info('AgentDrivenAnalysis', 'Agent-driven analysis completed', {
2501
2591
  confidence: result.confidence,
2502
2592
  rounds: result.rounds,
2503
2593
  findingsCount: result.findings.length,
2504
2594
  hypothesesCount: result.hypotheses.length,
2595
+ claimSupportCount: result.claimSupport?.length || 0,
2596
+ claimVerifierStatus: result.claimVerificationResult?.status,
2505
2597
  partial: result.partial,
2506
2598
  terminationReason: result.terminationReason,
2507
2599
  runId: session.activeRun?.runId,
@@ -2524,14 +2616,11 @@ async function runAgentDrivenAnalysis(sessionId, query, traceId, options = {}) {
2524
2616
  // Send final result
2525
2617
  const clientCount = session.sseClients.length;
2526
2618
  logger.info('AgentRoutes', 'Sending agent-driven result', { clientCount });
2619
+ ensureCompletedAnalysisSseEvents(session);
2527
2620
  session.sseClients.forEach((client, index) => {
2528
2621
  try {
2529
2622
  logger.info('AgentRoutes', `Sending agent-driven result to client ${index + 1}/${clientCount}`);
2530
2623
  sendAgentDrivenResult(client, session);
2531
- sendReplayableSessionEvent(session, client, 'end', {
2532
- timestamp: Date.now(),
2533
- ...buildStreamObservability(session),
2534
- });
2535
2624
  }
2536
2625
  catch (e) {
2537
2626
  logger.error('AgentRoutes', `Error sending agent-driven result to client ${index + 1}`, e);
@@ -4030,53 +4119,67 @@ function augmentConclusionUpdateWithEvidenceIndex(session, update) {
4030
4119
  },
4031
4120
  };
4032
4121
  }
4033
- /**
4034
- * Send agent-driven analysis result to SSE client
4035
- */
4036
- function sendAgentDrivenResult(res, session) {
4037
- const result = session.result;
4122
+ function ensureAnalysisQualityArtifacts(session, conclusionContract, resultOverride) {
4123
+ const result = resultOverride || session.result;
4038
4124
  if (!result)
4039
- return;
4040
- const observability = buildStreamObservability(session);
4041
- const replayOnlyScene = isSceneReplayOnlyQuery(session.query);
4042
- const hasEvidenceBackedConclusion = result.success || result.partial === true;
4043
- const normalizedConclusion = replayOnlyScene
4044
- ? buildSceneReplayNarrative(session.scenes || [])
4045
- : hasEvidenceBackedConclusion ? appendEvidenceIndexIfMissing(normalizeNarrativeForClient(result.conclusion), session.dataEnvelopes || []) : normalizeNarrativeForClient(result.conclusion);
4046
- const sceneIdHint = replayOnlyScene
4047
- ? undefined
4048
- : resolveConclusionSceneIdHint({
4049
- sessionId: session.sessionId,
4050
- query: session.query,
4051
- findings: result.findings,
4125
+ return {};
4126
+ if (result.claimSupport &&
4127
+ result.claimVerificationResult &&
4128
+ result.identityResolutions) {
4129
+ session.claimSupport = result.claimSupport;
4130
+ session.claimVerificationResult = result.claimVerificationResult;
4131
+ session.identityResolutions = result.identityResolutions;
4132
+ const context = enhancedSessionContext_1.sessionContextManager.get(session.sessionId, session.traceId);
4133
+ context?.annotateLatestCompletedTurn({
4134
+ conclusionContract,
4135
+ claimSupport: result.claimSupport,
4136
+ claimVerificationResult: result.claimVerificationResult,
4137
+ identityResolutions: result.identityResolutions,
4052
4138
  });
4053
- // Fallback: re-derive contract if the orchestrator didn't populate it.
4054
- // Note: mode heuristic uses rounds (available here) as proxy for turnCount
4055
- // (which only the orchestrator knows). Both signal "multi-interaction" analysis.
4056
- const normalizedConclusionContract = replayOnlyScene
4057
- ? undefined
4058
- : hasEvidenceBackedConclusion ? (result.conclusionContract ||
4059
- (0, agentResultNormalizer_1.deriveConclusionContractForNarrative)(result.conclusion, {
4060
- mode: result.rounds > 1 ? 'focused_answer' : 'initial_report',
4061
- sceneId: sceneIdHint,
4062
- }) ||
4063
- undefined) : undefined;
4064
- const resultForClient = normalizedConclusion === result.conclusion && normalizedConclusionContract === result.conclusionContract
4065
- ? result
4066
- : { ...result, conclusion: normalizedConclusion, conclusionContract: normalizedConclusionContract };
4067
- const clientFindings = replayOnlyScene ? [] : buildClientFindings(result.findings, session.scenes || []);
4068
- const resultContract = buildSessionResultContract(session, clientFindings);
4069
- // Generate HTML report
4070
- let reportUrl;
4071
- let reportError;
4072
- const reportId = `agent-report-${session.sessionId}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
4073
- let resultSnapshotId;
4074
- let resultSnapshotEventData;
4075
- let reportLease = null;
4076
- if (!hasEvidenceBackedConclusion) {
4077
- reportError = `analysis did not complete successfully (${result.terminationReason || 'failed'})`;
4139
+ return {
4140
+ claimSupport: result.claimSupport,
4141
+ claimVerificationResult: result.claimVerificationResult,
4142
+ identityResolutions: result.identityResolutions,
4143
+ };
4144
+ }
4145
+ const artifacts = (0, claimVerificationRunner_1.runClaimVerification)({
4146
+ conclusionContract,
4147
+ dataEnvelopes: session.dataEnvelopes || [],
4148
+ comparisonReportSection: session.comparisonReportSection,
4149
+ policy: 'record_only',
4150
+ });
4151
+ result.claimSupport = artifacts.claimSupport;
4152
+ result.claimVerificationResult = artifacts.claimVerificationResult;
4153
+ result.identityResolutions = artifacts.identityResolutions;
4154
+ const context = enhancedSessionContext_1.sessionContextManager.get(session.sessionId, session.traceId);
4155
+ context?.annotateLatestCompletedTurn({
4156
+ conclusionContract,
4157
+ claimSupport: artifacts.claimSupport,
4158
+ claimVerificationResult: artifacts.claimVerificationResult,
4159
+ identityResolutions: artifacts.identityResolutions,
4160
+ });
4161
+ session.claimSupport = artifacts.claimSupport;
4162
+ session.claimVerificationResult = artifacts.claimVerificationResult;
4163
+ session.identityResolutions = artifacts.identityResolutions;
4164
+ return {
4165
+ claimSupport: artifacts.claimSupport,
4166
+ claimVerificationResult: artifacts.claimVerificationResult,
4167
+ identityResolutions: artifacts.identityResolutions,
4168
+ };
4169
+ }
4170
+ function ensureCompletedAnalysisFinalArtifacts(session, input) {
4171
+ const cached = session.completedAnalysisFinalArtifacts;
4172
+ if (cached)
4173
+ return cached;
4174
+ const result = input.result;
4175
+ const finalArtifacts = { generatedAt: Date.now() };
4176
+ let reportId;
4177
+ if (!input.hasEvidenceBackedConclusion) {
4178
+ finalArtifacts.reportError = `analysis did not complete successfully (${result.terminationReason || 'failed'})`;
4078
4179
  }
4079
4180
  else {
4181
+ let reportLease = null;
4182
+ reportId = `agent-report-${session.sessionId}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
4080
4183
  try {
4081
4184
  if (enterpriseLeasesEnabled()) {
4082
4185
  const scope = leaseScopeFromSession(session);
@@ -4100,18 +4203,15 @@ function sendAgentDrivenResult(res, session) {
4100
4203
  }
4101
4204
  }
4102
4205
  const generator = (0, htmlReportGenerator_1.getHTMLReportGenerator)();
4103
- // Report assembly (cumulative findings dedup, empty-conclusion fallback,
4104
- // snapshot-first analysisNotes/Plan/Flags) lives in the shared builder so
4105
- // the CLI path produces identical output.
4106
4206
  const reportData = (0, agentReportData_1.buildAgentDrivenReportData)({
4107
4207
  session,
4108
- result: resultForClient,
4208
+ result: input.resultForClient,
4109
4209
  });
4110
4210
  console.log(`[AgentRoutes] Generating HTML report, data keys:`, {
4111
4211
  hasResult: !!result,
4112
- conclusionLength: normalizedConclusion?.length || 0,
4113
- conclusionPreview: (normalizedConclusion || '').substring(0, 100),
4114
- hasConclusionContract: !!normalizedConclusionContract,
4212
+ conclusionLength: input.normalizedConclusion?.length || 0,
4213
+ conclusionPreview: (input.normalizedConclusion || '').substring(0, 100),
4214
+ hasConclusionContract: !!input.normalizedConclusionContract,
4115
4215
  findingsCount: result.findings?.length || 0,
4116
4216
  hypothesesCount: session.hypotheses?.length || 0,
4117
4217
  dialogueCount: session.agentDialogue?.length || 0,
@@ -4123,9 +4223,10 @@ function sendAgentDrivenResult(res, session) {
4123
4223
  snapshotNotes: session._lastSnapshot?.analysisNotes?.length ?? 'n/a',
4124
4224
  snapshotPlan: !!session._lastSnapshot?.analysisPlan,
4125
4225
  snapshotFlags: session._lastSnapshot?.uncertaintyFlags?.length ?? 'n/a',
4226
+ claimSupportCount: input.qualityArtifacts.claimSupport?.length || 0,
4227
+ claimVerifierStatus: input.qualityArtifacts.claimVerificationResult?.status,
4126
4228
  });
4127
4229
  const html = generator.generateAgentDrivenHTML(reportData);
4128
- // Store report
4129
4230
  (0, reportRoutes_1.persistReport)(reportId, {
4130
4231
  html,
4131
4232
  generatedAt: Date.now(),
@@ -4137,13 +4238,15 @@ function sendAgentDrivenResult(res, session) {
4137
4238
  userId: session.userId,
4138
4239
  visibility: 'private',
4139
4240
  });
4140
- reportUrl = `/api/reports/${reportId}`;
4241
+ finalArtifacts.reportId = reportId;
4242
+ finalArtifacts.reportUrl = `/api/reports/${reportId}`;
4141
4243
  console.log(`[AgentRoutes] Generated agent-driven HTML report: ${reportId} (${html.length} bytes)`);
4142
4244
  }
4143
4245
  catch (error) {
4144
- reportError = error.message || 'Unknown error';
4246
+ reportId = undefined;
4247
+ finalArtifacts.reportError = error.message || 'Unknown error';
4145
4248
  console.error('[AgentRoutes] Failed to generate agent-driven HTML report:', {
4146
- error: reportError,
4249
+ error: finalArtifacts.reportError,
4147
4250
  stack: error.stack?.split('\n').slice(0, 5).join('\n'),
4148
4251
  resultConclusion: result?.conclusion ? `${result.conclusion.length} chars` : 'EMPTY/NULL',
4149
4252
  resultConfidence: result?.confidence,
@@ -4155,7 +4258,7 @@ function sendAgentDrivenResult(res, session) {
4155
4258
  const scope = leaseScopeFromSession(session);
4156
4259
  if (scope) {
4157
4260
  try {
4158
- (0, traceProcessorLeaseStore_1.getTraceProcessorLeaseStore)().releaseHolder(scope, reportLease.id, 'report_generation', reportId);
4261
+ (0, traceProcessorLeaseStore_1.getTraceProcessorLeaseStore)().releaseHolder(scope, reportLease.id, 'report_generation', finalArtifacts.reportId || reportId || 'report_generation');
4159
4262
  }
4160
4263
  catch (releaseError) {
4161
4264
  console.warn(`[AgentRoutes] Failed to release report_generation lease ${reportLease.id}: ${releaseError.message}`);
@@ -4164,7 +4267,7 @@ function sendAgentDrivenResult(res, session) {
4164
4267
  }
4165
4268
  }
4166
4269
  }
4167
- if (hasEvidenceBackedConclusion) {
4270
+ if (input.hasEvidenceBackedConclusion) {
4168
4271
  try {
4169
4272
  const resultSnapshot = (0, analysisResultSnapshotPipeline_1.persistCompletedAnalysisResultSnapshot)({
4170
4273
  tenantId: session.tenantId,
@@ -4173,20 +4276,23 @@ function sendAgentDrivenResult(res, session) {
4173
4276
  traceId: session.traceId,
4174
4277
  sessionId: session.sessionId,
4175
4278
  runId: session.lastRun?.runId || session.activeRun?.runId,
4176
- reportId: reportUrl ? reportId : undefined,
4279
+ reportId: finalArtifacts.reportId,
4177
4280
  query: session.query,
4178
4281
  traceLabel: session.traceId,
4179
- conclusion: normalizedConclusion,
4180
- conclusionContract: normalizedConclusionContract,
4282
+ conclusion: input.normalizedConclusion,
4283
+ conclusionContract: input.normalizedConclusionContract,
4284
+ claimSupport: input.qualityArtifacts.claimSupport,
4285
+ claimVerificationResult: input.qualityArtifacts.claimVerificationResult,
4286
+ identityResolutions: input.qualityArtifacts.identityResolutions,
4181
4287
  confidence: result.confidence,
4182
4288
  partial: result.partial,
4183
4289
  terminationReason: result.terminationReason,
4184
4290
  terminationMessage: result.terminationMessage,
4185
4291
  dataEnvelopes: session.dataEnvelopes,
4186
4292
  });
4187
- resultSnapshotId = resultSnapshot?.id;
4293
+ finalArtifacts.resultSnapshotId = resultSnapshot?.id;
4188
4294
  if (resultSnapshot) {
4189
- resultSnapshotEventData = {
4295
+ finalArtifacts.resultSnapshotEventData = {
4190
4296
  snapshotId: resultSnapshot.id,
4191
4297
  status: resultSnapshot.status,
4192
4298
  sceneType: resultSnapshot.sceneType,
@@ -4209,24 +4315,108 @@ function sendAgentDrivenResult(res, session) {
4209
4315
  });
4210
4316
  }
4211
4317
  }
4212
- if (resultSnapshotEventData) {
4213
- sendReplayableSessionEvent(session, res, 'snapshot_created', {
4318
+ session.completedAnalysisFinalArtifacts = finalArtifacts;
4319
+ return finalArtifacts;
4320
+ }
4321
+ function ensureCompletedAnalysisResultPayload(session) {
4322
+ const result = session.result;
4323
+ if (!result)
4324
+ return undefined;
4325
+ const replayOnlyScene = isSceneReplayOnlyQuery(session.query);
4326
+ const hasEvidenceBackedConclusion = result.success || result.partial === true;
4327
+ const normalizedConclusion = replayOnlyScene
4328
+ ? buildSceneReplayNarrative(session.scenes || [])
4329
+ : hasEvidenceBackedConclusion ? appendEvidenceIndexIfMissing(normalizeNarrativeForClient(result.conclusion), session.dataEnvelopes || []) : normalizeNarrativeForClient(result.conclusion);
4330
+ const sceneIdHint = replayOnlyScene
4331
+ ? undefined
4332
+ : resolveConclusionSceneIdHint({
4333
+ sessionId: session.sessionId,
4334
+ query: session.query,
4335
+ findings: result.findings,
4336
+ });
4337
+ const normalizedConclusionContract = replayOnlyScene
4338
+ ? undefined
4339
+ : hasEvidenceBackedConclusion ? (result.conclusionContract ||
4340
+ (0, agentResultNormalizer_1.deriveConclusionContractForNarrative)(result.conclusion, {
4341
+ mode: result.rounds > 1 ? 'focused_answer' : 'initial_report',
4342
+ sceneId: sceneIdHint,
4343
+ }) ||
4344
+ undefined) : undefined;
4345
+ const qualityArtifacts = hasEvidenceBackedConclusion && !replayOnlyScene
4346
+ ? ensureAnalysisQualityArtifacts(session, normalizedConclusionContract)
4347
+ : {};
4348
+ const resultForClient = normalizedConclusion === result.conclusion &&
4349
+ normalizedConclusionContract === result.conclusionContract &&
4350
+ qualityArtifacts.claimSupport === result.claimSupport &&
4351
+ qualityArtifacts.claimVerificationResult === result.claimVerificationResult &&
4352
+ qualityArtifacts.identityResolutions === result.identityResolutions
4353
+ ? result
4354
+ : {
4355
+ ...result,
4356
+ conclusion: normalizedConclusion,
4357
+ conclusionContract: normalizedConclusionContract,
4358
+ ...qualityArtifacts,
4359
+ };
4360
+ const clientFindings = replayOnlyScene ? [] : buildClientFindings(result.findings, session.scenes || []);
4361
+ const resultContract = buildSessionResultContract(session, clientFindings);
4362
+ const finalArtifacts = ensureCompletedAnalysisFinalArtifacts(session, {
4363
+ result,
4364
+ hasEvidenceBackedConclusion,
4365
+ normalizedConclusion,
4366
+ normalizedConclusionContract,
4367
+ qualityArtifacts,
4368
+ resultForClient: resultForClient,
4369
+ });
4370
+ return {
4371
+ result,
4372
+ replayOnlyScene,
4373
+ normalizedConclusion,
4374
+ normalizedConclusionContract,
4375
+ qualityArtifacts,
4376
+ clientFindings,
4377
+ resultContract,
4378
+ finalArtifacts,
4379
+ };
4380
+ }
4381
+ /**
4382
+ * Send agent-driven analysis result to SSE client
4383
+ */
4384
+ function ensureCompletedAnalysisSseEvents(session) {
4385
+ const cached = session.completedAnalysisSseEvents;
4386
+ if (cached?.length)
4387
+ return cached;
4388
+ const persisted = loadPersistedCompletedAnalysisSseEvents(session);
4389
+ if (persisted.length > 0) {
4390
+ session.completedAnalysisSseEvents = persisted;
4391
+ return persisted;
4392
+ }
4393
+ const completedPayload = ensureCompletedAnalysisResultPayload(session);
4394
+ if (!completedPayload)
4395
+ return [];
4396
+ const { result, normalizedConclusion, normalizedConclusionContract, qualityArtifacts, clientFindings, resultContract, finalArtifacts, } = completedPayload;
4397
+ const observability = buildStreamObservability(session);
4398
+ const events = [];
4399
+ if (finalArtifacts.resultSnapshotEventData) {
4400
+ events.push(appendAndPersistReplayableSessionEvent(session, 'snapshot_created', {
4214
4401
  type: 'snapshot_created',
4215
4402
  architecture: 'agent-driven',
4216
4403
  ...observability,
4217
- data: resultSnapshotEventData,
4404
+ data: finalArtifacts.resultSnapshotEventData,
4218
4405
  timestamp: Date.now(),
4219
- });
4406
+ }));
4220
4407
  }
4221
4408
  // Send analysis_completed event with full result. Keep it replayable so a
4222
4409
  // reconnect between conclusion and report generation can recover reportUrl.
4223
- sendReplayableSessionEvent(session, res, 'analysis_completed', {
4410
+ events.push(appendAndPersistReplayableSessionEvent(session, 'analysis_completed', {
4224
4411
  type: 'analysis_completed',
4225
4412
  architecture: 'agent-driven',
4226
4413
  ...observability,
4227
4414
  data: {
4228
4415
  conclusion: normalizedConclusion,
4229
4416
  conclusionContract: normalizedConclusionContract,
4417
+ claimSupport: qualityArtifacts.claimSupport,
4418
+ claimVerificationResult: qualityArtifacts.claimVerificationResult,
4419
+ identityResolutions: qualityArtifacts.identityResolutions,
4230
4420
  confidence: result.confidence,
4231
4421
  rounds: result.rounds,
4232
4422
  totalDurationMs: result.totalDurationMs,
@@ -4246,8 +4436,8 @@ function sendAgentDrivenResult(res, session) {
4246
4436
  agentDialogueCount: session.agentDialogue.length,
4247
4437
  conversationTimelineCount: session.conversationSteps.length,
4248
4438
  conversationTimeline: session.conversationSteps,
4249
- reportUrl,
4250
- reportError,
4439
+ reportUrl: finalArtifacts.reportUrl,
4440
+ reportError: finalArtifacts.reportError,
4251
4441
  comparisonReportSection: session.comparisonReportSection
4252
4442
  ? {
4253
4443
  source: session.comparisonReportSection.source,
@@ -4257,14 +4447,15 @@ function sendAgentDrivenResult(res, session) {
4257
4447
  evidencePack: session.comparisonReportSection.evidencePack,
4258
4448
  }
4259
4449
  : undefined,
4260
- resultSnapshotId,
4450
+ resultSnapshotId: finalArtifacts.resultSnapshotId,
4261
4451
  observability,
4452
+ terminalRunStatus: session.status === 'quota_exceeded' ? 'quota_exceeded' : 'completed',
4262
4453
  },
4263
4454
  timestamp: Date.now(),
4264
- });
4455
+ }));
4265
4456
  // Backward-compatible scene reconstruction payload (used by the legacy /scene-reconstruct clients).
4266
4457
  if ((session.scenes?.length || 0) > 0 || (session.trackEvents?.length || 0) > 0) {
4267
- sendReplayableSessionEvent(session, res, 'scene_reconstruction_completed', {
4458
+ events.push(appendAndPersistReplayableSessionEvent(session, 'scene_reconstruction_completed', {
4268
4459
  type: 'scene_reconstruction_completed',
4269
4460
  ...observability,
4270
4461
  data: {
@@ -4292,7 +4483,18 @@ function sendAgentDrivenResult(res, session) {
4292
4483
  observability,
4293
4484
  },
4294
4485
  timestamp: Date.now(),
4295
- });
4486
+ }));
4487
+ }
4488
+ events.push(appendAndPersistReplayableSessionEvent(session, 'end', {
4489
+ timestamp: Date.now(),
4490
+ ...observability,
4491
+ }));
4492
+ session.completedAnalysisSseEvents = events;
4493
+ return events;
4494
+ }
4495
+ function sendAgentDrivenResult(res, session) {
4496
+ for (const event of ensureCompletedAnalysisSseEvents(session)) {
4497
+ writeBufferedSessionEvent(res, event);
4296
4498
  }
4297
4499
  }
4298
4500
  (0, agentLogsRoutes_1.registerAgentLogsRoutes)(router);