rea-agents 1.7.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (333) hide show
  1. package/README.md +112 -59
  2. package/bridge/ghidra/ReaGhidraBridge.java +96 -11
  3. package/dist/application/ArtifactExtraction.js +1 -1
  4. package/dist/application/ArtifactInventory/classify.js +42 -0
  5. package/dist/application/ArtifactInventory/hash.js +43 -0
  6. package/dist/application/ArtifactInventory/reader.js +41 -0
  7. package/dist/application/ArtifactInventory/scanCanonical.js +155 -0
  8. package/dist/application/ArtifactInventory/scanReader.js +124 -0
  9. package/dist/application/ArtifactInventory/types.js +10 -0
  10. package/dist/application/ArtifactInventory.js +9 -351
  11. package/dist/application/AuthorizedArtifactInventory.js +2 -2
  12. package/dist/application/BinarySession.js +47 -270
  13. package/dist/application/BinarySessionExecution.js +28 -0
  14. package/dist/application/BinarySessionOpen.js +39 -0
  15. package/dist/application/BinarySessionRecords.js +149 -0
  16. package/dist/application/BinarySessionStatus.js +75 -0
  17. package/dist/application/CapabilityInventory.js +42 -2
  18. package/dist/application/ClientRegistrationStatus.js +1 -1
  19. package/dist/application/CrossVersionInventory.js +8 -2
  20. package/dist/application/CrossVersionInvestigation.js +11 -29
  21. package/dist/application/CrossVersionInvestigationCollections.js +23 -0
  22. package/dist/application/DirectAnalysis.js +47 -44
  23. package/dist/application/Doctor.js +165 -197
  24. package/dist/application/DoctorDiagnostics.js +180 -0
  25. package/dist/application/ElectronBoundaryAnalysis.js +112 -0
  26. package/dist/application/ElectronBoundaryGraph.js +9 -0
  27. package/dist/application/ElectronBoundaryGraphContext.js +62 -0
  28. package/dist/application/ElectronBoundaryGraphIpc.js +242 -0
  29. package/dist/application/ElectronBoundaryGraphNative.js +86 -0
  30. package/dist/application/ElectronBoundaryGraphWindows.js +223 -0
  31. package/dist/application/EnhancedToolPagination.js +22 -0
  32. package/dist/application/EnhancedToolTypes.js +4 -0
  33. package/dist/application/EnhancedTools.js +58 -50
  34. package/dist/application/InstrumentedJavaScriptReplayHost.js +36 -0
  35. package/dist/application/InvestigationProviders.js +30 -0
  36. package/dist/application/InvestigationWorkspaceStore.js +24 -10
  37. package/dist/application/JavaScriptApplicationEvidence.js +26 -0
  38. package/dist/application/JavaScriptApplicationEvidenceGraph.js +89 -0
  39. package/dist/application/JavaScriptApplicationService.js +74 -0
  40. package/dist/application/JavaScriptApplicationWorkflowEvidence.js +29 -0
  41. package/dist/application/JavaScriptApplicationWorkflowService.js +90 -0
  42. package/dist/application/JavaScriptArtifactAnalysis.js +52 -7
  43. package/dist/application/JavaScriptArtifactFiles.js +6 -2
  44. package/dist/application/JavaScriptArtifactGraphBuilder.js +82 -17
  45. package/dist/application/JavaScriptArtifactGraphBundlers.js +225 -0
  46. package/dist/application/JavaScriptArtifactGraphContext.js +37 -36
  47. package/dist/application/JavaScriptArtifactGraphDocuments.js +27 -4
  48. package/dist/application/JavaScriptArtifactGraphEvidence.js +24 -14
  49. package/dist/application/JavaScriptArtifactGraphFindings.js +54 -8
  50. package/dist/application/JavaScriptArtifactGraphStructure.js +29 -101
  51. package/dist/application/JavaScriptArtifactPathResolution.js +269 -0
  52. package/dist/application/JavaScriptArtifactReconstruction.js +4 -1
  53. package/dist/application/JavaScriptArtifactReconstructionInput.js +2 -83
  54. package/dist/application/JavaScriptJsonModules.js +39 -0
  55. package/dist/application/JavaScriptModuleRelationships.js +262 -0
  56. package/dist/application/JavaScriptReplayPermission.js +16 -0
  57. package/dist/application/JavaScriptReplayPlanning.js +201 -0
  58. package/dist/application/JavaScriptReplayService.js +292 -0
  59. package/dist/application/JavaScriptRuntimeReconciliationEvidence.js +25 -0
  60. package/dist/application/JavaScriptRuntimeReconciliationService.js +27 -0
  61. package/dist/application/LinuxHopper.js +10 -0
  62. package/dist/application/MacHopper.js +22 -11
  63. package/dist/application/ManagedApplicationGraphService.js +55 -0
  64. package/dist/application/ManagedMemberComparisonService.js +122 -0
  65. package/dist/application/ManagedNativeVerificationService.js +39 -0
  66. package/dist/application/ManagedReconstructionService.js +58 -0
  67. package/dist/application/ManagedRuntimeCorrelationService.js +103 -0
  68. package/dist/application/NodeRuntimeCharacterizationService.js +196 -0
  69. package/dist/application/PermissionAuthority.js +106 -63
  70. package/dist/application/ProcessCaptureCapability.js +1 -1
  71. package/dist/application/ProcessCapturePermission.js +13 -0
  72. package/dist/application/ProcessCli.js +2 -12
  73. package/dist/application/ProcessHarness.js +1 -1
  74. package/dist/application/ProcessSampling.js +15 -11
  75. package/dist/application/ProjectPermissionStore.js +49 -9
  76. package/dist/application/RealHopperAssertions.js +76 -0
  77. package/dist/application/ReconstructionCoverageService.js +69 -0
  78. package/dist/application/ReconstructionCoverageWorkspaceStore.js +31 -0
  79. package/dist/application/RuntimeExecutableDiagnostics.js +172 -0
  80. package/dist/application/Setup.js +147 -259
  81. package/dist/application/SetupClientConfiguration.js +220 -0
  82. package/dist/application/SetupClients.js +24 -2
  83. package/dist/application/SetupPlan.js +123 -12
  84. package/dist/application/SetupSkill.js +26 -12
  85. package/dist/application/SupportedClients.js +1 -0
  86. package/dist/application/Uninstall.js +6 -3
  87. package/dist/application/WindowsCapabilities.js +86 -0
  88. package/dist/application/runtime.js +2 -0
  89. package/dist/artifacts/AsarArtifactReader.js +11 -0
  90. package/dist/browser/BrowserProcessStartup.js +88 -0
  91. package/dist/browser/CdpCaptureDocuments.js +12 -8
  92. package/dist/browser/CdpCaptureEventBodyShapes.js +75 -0
  93. package/dist/browser/CdpCaptureEventHandlers.js +336 -0
  94. package/dist/browser/CdpCaptureEventHelpers.js +71 -0
  95. package/dist/browser/CdpCaptureEventState.js +1 -0
  96. package/dist/browser/CdpCaptureEventTypes.js +1 -0
  97. package/dist/browser/CdpCaptureEvents.js +46 -464
  98. package/dist/browser/CdpElectronInspection.js +106 -162
  99. package/dist/browser/CdpElectronProvider.js +5 -1
  100. package/dist/browser/CdpElectronScriptEvents.js +69 -0
  101. package/dist/browser/CdpElectronScripts.js +94 -0
  102. package/dist/browser/CdpElectronWorkers.js +56 -0
  103. package/dist/browser/CdpObservationSession.js +51 -8
  104. package/dist/browser/CdpPageCapture.js +12 -129
  105. package/dist/browser/CdpPageCaptureScripts.js +97 -0
  106. package/dist/browser/CdpPageCaptureWorkers.js +46 -0
  107. package/dist/browser/CdpWebMcpDiscovery.js +38 -14
  108. package/dist/browser/PngVisualDiff.js +9 -2
  109. package/dist/catalogIdentity.js +8 -1
  110. package/dist/cli/artifactCommands.js +82 -0
  111. package/dist/cli/coreAnalysisCommands.js +232 -0
  112. package/dist/cli/managedCommands.js +397 -0
  113. package/dist/cli/managedProjectGraphCommand.js +24 -0
  114. package/dist/cli/options.js +9 -0
  115. package/dist/cli/setupCommands.js +108 -0
  116. package/dist/cli/types.js +1 -0
  117. package/dist/cli/utilityCommands.js +122 -0
  118. package/dist/cli.js +13 -383
  119. package/dist/cliApplicationCommands.js +176 -0
  120. package/dist/cliBrowserAdvancedCommands.js +73 -16
  121. package/dist/cliBrowserCommands.js +39 -115
  122. package/dist/cliCommandNames.js +17 -0
  123. package/dist/cliElectronCommands.js +100 -27
  124. package/dist/cliEvidenceCommands.js +13 -2
  125. package/dist/cliInvestigationCommands.js +53 -10
  126. package/dist/cliJsonInput.js +54 -0
  127. package/dist/cliObservationOptions.js +137 -0
  128. package/dist/cliPolicyCommands.js +80 -46
  129. package/dist/cliSetup.js +289 -0
  130. package/dist/config/environment.js +107 -0
  131. package/dist/config/parseConfig.js +228 -0
  132. package/dist/config/parsers.js +68 -0
  133. package/dist/config/permissions.js +30 -0
  134. package/dist/config/types.js +1 -0
  135. package/dist/config.js +1 -292
  136. package/dist/contracts/applicationToolContracts.js +225 -0
  137. package/dist/contracts/artifactToolContracts.js +5 -9
  138. package/dist/contracts/browserToolContracts.js +14 -62
  139. package/dist/contracts/electronToolContracts.js +45 -19
  140. package/dist/contracts/errorSchemas.js +1 -0
  141. package/dist/contracts/investigationExamples.js +0 -6
  142. package/dist/contracts/javascriptApplicationWorkflowExamples.js +46 -0
  143. package/dist/contracts/javascriptRuntimeReconciliationExample.js +208 -0
  144. package/dist/contracts/managedToolContracts.js +153 -0
  145. package/dist/contracts/managedWorkflowExamples.js +346 -0
  146. package/dist/contracts/managedWorkflowToolContracts.js +203 -0
  147. package/dist/contracts/nativeToolContracts.js +2 -6
  148. package/dist/contracts/promptContracts.js +18 -2
  149. package/dist/contracts/providerSelection.js +2 -0
  150. package/dist/contracts/toolContractExamples.js +10 -25
  151. package/dist/contracts/toolContracts.js +49 -47
  152. package/dist/contracts/toolEffects.js +174 -0
  153. package/dist/contracts/toolOutputSchemaGroups.js +232 -0
  154. package/dist/contracts/toolOutputSchemaPrimitives.js +327 -0
  155. package/dist/contracts/toolOutputSchemas.js +2 -535
  156. package/dist/doctorRuntime.js +42 -1
  157. package/dist/domain/analysisErrorPresentation.js +234 -0
  158. package/dist/domain/analysisErrorProjection.js +284 -0
  159. package/dist/domain/artifactComparison.js +37 -19
  160. package/dist/domain/binaryTarget.js +87 -37
  161. package/dist/domain/browserObservation.js +1 -282
  162. package/dist/domain/browserObservationSchemas.js +286 -0
  163. package/dist/domain/bundleComparison.js +4 -4
  164. package/dist/domain/electronObservation.js +13 -0
  165. package/dist/domain/electronStaticAnalysis.js +9 -0
  166. package/dist/domain/electronStaticAnalysisBrowser.js +206 -0
  167. package/dist/domain/electronStaticAnalysisIpc.js +171 -0
  168. package/dist/domain/electronStaticAnalysisNative.js +164 -0
  169. package/dist/domain/electronStaticAnalysisTypes.js +1 -0
  170. package/dist/domain/electronStaticAnalysisValues.js +103 -0
  171. package/dist/domain/errors.js +32 -448
  172. package/dist/domain/functionComparison.js +4 -165
  173. package/dist/domain/functionComparisonDimensions.js +164 -0
  174. package/dist/domain/functionComparisonSchemas.js +3 -8
  175. package/dist/domain/inputIssueProjection.js +52 -0
  176. package/dist/domain/javascriptApplicationAnalysis.js +155 -0
  177. package/dist/domain/javascriptApplicationChangeGraph.js +231 -0
  178. package/dist/domain/javascriptApplicationEvidenceSchemas.js +18 -0
  179. package/dist/domain/javascriptApplicationGraph.js +2 -1
  180. package/dist/domain/javascriptApplicationGraphSchemas.js +7 -0
  181. package/dist/domain/javascriptApplicationVersionComparison.js +116 -0
  182. package/dist/domain/javascriptApplicationVersionComparisonSchemas.js +139 -0
  183. package/dist/domain/javascriptApplicationVersionItems.js +233 -0
  184. package/dist/domain/javascriptApplicationVersionKeys.js +170 -0
  185. package/dist/domain/javascriptExportInstrumentation.js +97 -0
  186. package/dist/domain/javascriptFeatureSeed.js +140 -0
  187. package/dist/domain/javascriptFeatureTrace.js +232 -0
  188. package/dist/domain/javascriptFeatureTraceSchemas.js +136 -0
  189. package/dist/domain/javascriptFeatureTraversal.js +100 -0
  190. package/dist/domain/javascriptNativeHandoff.js +85 -0
  191. package/dist/domain/javascriptReplay.js +361 -0
  192. package/dist/domain/javascriptRuntimeLoadState.js +106 -0
  193. package/dist/domain/javascriptRuntimeReconciliation.js +42 -0
  194. package/dist/domain/javascriptRuntimeReconciliationGraph.js +169 -0
  195. package/dist/domain/javascriptRuntimeReconciliationMatching.js +247 -0
  196. package/dist/domain/javascriptRuntimeReconciliationParsing.js +160 -0
  197. package/dist/domain/javascriptRuntimeReconciliationResult.js +119 -0
  198. package/dist/domain/javascriptRuntimeReconciliationRuntime.js +316 -0
  199. package/dist/domain/javascriptRuntimeReconciliationSchemas.js +245 -0
  200. package/dist/domain/javascriptRuntimeStaticCandidates.js +193 -0
  201. package/dist/domain/javascriptSemanticAnalysis.js +386 -0
  202. package/dist/domain/javascriptSemanticIr.js +30 -0
  203. package/dist/domain/javascriptSemanticProjection.js +366 -0
  204. package/dist/domain/javascriptSemanticState.js +40 -0
  205. package/dist/domain/javascriptSemanticTraversal.js +22 -0
  206. package/dist/domain/javascriptSemanticValues.js +352 -0
  207. package/dist/domain/javascriptStaticAnalysis.js +26 -254
  208. package/dist/domain/javascriptStaticAnalysisBundler.js +209 -0
  209. package/dist/domain/javascriptStaticAnalysisCalls.js +180 -0
  210. package/dist/domain/javascriptStaticAnalysisFindings.js +39 -0
  211. package/dist/domain/javascriptStaticAnalysisHelpers.js +81 -2
  212. package/dist/domain/javascriptStaticAnalysisState.js +6 -0
  213. package/dist/domain/knownPageCoverage.js +21 -0
  214. package/dist/domain/managedApplicationGraph.js +206 -0
  215. package/dist/domain/managedApplicationGraphCoverage.js +170 -0
  216. package/dist/domain/managedApplicationGraphNodeCoverage.js +6 -0
  217. package/dist/domain/managedApplicationGraphNodes.js +336 -0
  218. package/dist/domain/managedArtifact.js +452 -0
  219. package/dist/domain/managedMemberComparison.js +211 -0
  220. package/dist/domain/managedMemberComparisonCoverage.js +72 -0
  221. package/dist/domain/managedMemberComparisonMatch.js +356 -0
  222. package/dist/domain/managedNativeVerification.js +46 -0
  223. package/dist/domain/managedNativeVerificationMatch.js +272 -0
  224. package/dist/domain/managedNativeVerificationSchemas.js +141 -0
  225. package/dist/domain/managedReconstruction.js +196 -0
  226. package/dist/domain/managedRuntimeCorrelation.js +184 -0
  227. package/dist/domain/nodeRuntimeCharacterization.js +66 -0
  228. package/dist/domain/permissionPolicy.js +2 -0
  229. package/dist/domain/reconstructionCoverage.js +387 -0
  230. package/dist/domain/reconstructionCoverageEvaluation.js +212 -0
  231. package/dist/domain/reconstructionVerificationSchemas.js +9 -3
  232. package/dist/domain/runtimeCharacterization.js +85 -0
  233. package/dist/domain/webBundleAnalyzer.js +3 -409
  234. package/dist/domain/webBundleAnalyzerAst.js +77 -0
  235. package/dist/domain/webBundleAnalyzerInspection.js +307 -0
  236. package/dist/domain/webBundleAnalyzerResult.js +120 -0
  237. package/dist/dotnet/ManagedArtifactInspector.js +339 -0
  238. package/dist/dotnet/ManagedMemberInspector.js +153 -0
  239. package/dist/dotnet/ManagedMemberInspectorCore.js +297 -0
  240. package/dist/dotnet/ManagedMemberInstructionDecoder.js +427 -0
  241. package/dist/dotnet/ManagedMemberRows.js +120 -0
  242. package/dist/dotnet/ManagedMetadataHeaps.js +131 -0
  243. package/dist/dotnet/ManagedMetadataInventory.js +104 -0
  244. package/dist/dotnet/ManagedMetadataInventoryRows.js +292 -0
  245. package/dist/dotnet/ManagedMetadataLayout.js +259 -0
  246. package/dist/dotnet/ManagedMetadataRowSizes.js +54 -0
  247. package/dist/dotnet/ManagedMethodBodyReader.js +143 -0
  248. package/dist/dotnet/ManagedNativeBoundaryHelpers.js +311 -0
  249. package/dist/dotnet/ManagedNativeBoundaryInspector.js +143 -0
  250. package/dist/dotnet/ManagedPeReader.js +188 -0
  251. package/dist/dotnet/ManagedReaderFailure.js +10 -0
  252. package/dist/dotnet/ManagedStaticProvider.js +203 -0
  253. package/dist/generatedPackageMetadata.js +2 -2
  254. package/dist/ghidra/GhidraClient.js +76 -91
  255. package/dist/ghidra/GhidraClientStartup.js +29 -0
  256. package/dist/ghidra/GhidraClientWire.js +34 -0
  257. package/dist/ghidra/GhidraDefaults.js +1 -1
  258. package/dist/ghidra/GhidraDiagnostics.js +6 -1
  259. package/dist/ghidra/GhidraInstallation.js +20 -15
  260. package/dist/ghidra/GhidraLauncher.js +93 -29
  261. package/dist/ghidra/GhidraProvider.js +67 -161
  262. package/dist/ghidra/GhidraProviderCapabilities.js +173 -0
  263. package/dist/ghidra/GhidraSessionValues.js +2 -0
  264. package/dist/ghidra/GhidraSocketConnection.js +44 -7
  265. package/dist/ghidra/GhidraTargetSnapshot.js +30 -0
  266. package/dist/ghidra/GhidraTransport.js +71 -0
  267. package/dist/identity.js +3 -2
  268. package/dist/main/messages.js +5 -0
  269. package/dist/main/reload.js +49 -0
  270. package/dist/main/shutdown.js +25 -0
  271. package/dist/main/startup.js +14 -0
  272. package/dist/main/state.js +26 -0
  273. package/dist/main/transport.js +61 -0
  274. package/dist/main/types.js +1 -0
  275. package/dist/main.js +35 -132
  276. package/dist/process/PrivateRuntimeRoot.js +3 -2
  277. package/dist/process/ProcessOwnership.js +35 -0
  278. package/dist/process/ProviderProcess.js +2 -0
  279. package/dist/replay/JavaScriptReplayWorker.js +300 -0
  280. package/dist/replay/LinuxJavaScriptReplayRunner.js +217 -0
  281. package/dist/replay/LinuxJavaScriptReplaySandbox.js +140 -0
  282. package/dist/replay/LinuxRuntimeClosure.js +46 -0
  283. package/dist/replay/LinuxSeccompPolicy.js +40 -0
  284. package/dist/replay/ReplayOutcome.js +95 -0
  285. package/dist/replay/ReplayProcessLifecycle.js +71 -0
  286. package/dist/replay/ReplayWorkerProtocol.js +55 -0
  287. package/dist/replay/SystemJavaScriptReplayHost.js +182 -0
  288. package/dist/server/ProcessCaptureElicitation.js +157 -0
  289. package/dist/server/createServer.js +158 -41
  290. package/dist/server/registerApplicationTools/characterization.js +57 -0
  291. package/dist/server/registerApplicationTools/compareVersions.js +34 -0
  292. package/dist/server/registerApplicationTools/controlledReplay.js +38 -0
  293. package/dist/server/registerApplicationTools/coverage.js +84 -0
  294. package/dist/server/registerApplicationTools/helpers.js +42 -0
  295. package/dist/server/registerApplicationTools/traceFeature.js +26 -0
  296. package/dist/server/registerApplicationTools/types.js +1 -0
  297. package/dist/server/registerApplicationTools.js +13 -0
  298. package/dist/server/registerArtifactComparisonTool.js +16 -9
  299. package/dist/server/registerBrowserTools.js +61 -60
  300. package/dist/server/registerBundleComparisonTool.js +17 -20
  301. package/dist/server/registerElectronTools.js +39 -12
  302. package/dist/server/registerEnhancedTools.js +52 -15
  303. package/dist/server/registerEvidenceResources.js +54 -0
  304. package/dist/server/registerEvidenceTools.js +5 -1
  305. package/dist/server/registerFunctionComparisonTool.js +14 -7
  306. package/dist/server/registerInvestigationTools/helpers.js +74 -0
  307. package/dist/server/registerInvestigationTools/types.js +1 -0
  308. package/dist/server/registerInvestigationTools.js +103 -132
  309. package/dist/server/registerManagedTools.js +6 -0
  310. package/dist/server/registerManagedWorkflowTools/compareManagedMembers.js +65 -0
  311. package/dist/server/registerManagedWorkflowTools/contract.js +8 -0
  312. package/dist/server/registerManagedWorkflowTools/evidence.js +43 -0
  313. package/dist/server/registerManagedWorkflowTools/importManagedReconstruction.js +39 -0
  314. package/dist/server/registerManagedWorkflowTools/planManagedRuntimeCorrelation.js +39 -0
  315. package/dist/server/registerManagedWorkflowTools/projectManagedApplicationGraph.js +52 -0
  316. package/dist/server/registerManagedWorkflowTools/types.js +1 -0
  317. package/dist/server/registerManagedWorkflowTools/verifyManagedNativeBoundaries.js +75 -0
  318. package/dist/server/registerManagedWorkflowTools.js +13 -0
  319. package/dist/server/registerOfficialTools.js +81 -67
  320. package/dist/server/registerProcessComparisonTool.js +25 -47
  321. package/dist/server/registerSessionRecordTools.js +137 -0
  322. package/dist/server/registerSessionStatusTool.js +9 -8
  323. package/dist/server/registerSessionTools.js +77 -216
  324. package/dist/server/sessionAvailabilityPolicy.js +10 -0
  325. package/dist/server/sessionEvidence.js +14 -19
  326. package/dist/server/toolInputValidation.js +77 -0
  327. package/dist/server/toolRegistrationOptions.js +177 -2
  328. package/dist/server/toolResult.js +30 -17
  329. package/package.json +21 -14
  330. package/scripts/rea.mjs +1 -1
  331. package/skills/{rea-analysis → reverse-engineer-anything}/SKILL.md +75 -6
  332. package/scripts/prepare-node-pty.mjs +0 -35
  333. package/scripts/rebuild-native.mjs +0 -22
@@ -0,0 +1,361 @@
1
+ import { z } from "zod";
2
+ import { evidenceEnvelopeSchema } from "./evidence.js";
3
+ const digestSchema = z.string().regex(/^[a-f0-9]{64}$/u);
4
+ const absolutePathSchema = z.string().startsWith("/").max(4096);
5
+ const aliasSchema = z
6
+ .string()
7
+ .min(1)
8
+ .max(256)
9
+ .regex(/^[A-Za-z0-9_./:@-]+$/u);
10
+ const replayModuleSchema = z
11
+ .object({
12
+ alias: aliasSchema,
13
+ path: absolutePathSchema,
14
+ format: z.enum(["esm", "commonjs-factory"]),
15
+ role: z.enum(["module", "stub"]).default("module"),
16
+ dependencies: z
17
+ .record(z.string().min(1).max(256), aliasSchema)
18
+ .refine((value) => Object.keys(value).length <= 128, {
19
+ message: "Replay modules may declare at most 128 dependencies",
20
+ })
21
+ .default({}),
22
+ })
23
+ .strict();
24
+ const replaySideSchema = z
25
+ .object({
26
+ modules: z.array(replayModuleSchema).min(1).max(128),
27
+ entry_alias: aliasSchema,
28
+ entry_export: z.string().min(1).max(256).default("default"),
29
+ })
30
+ .strict();
31
+ const explicitCaseSchema = z
32
+ .object({
33
+ case_id: z.string().min(1).max(128),
34
+ arguments: z.array(z.json()).max(16),
35
+ })
36
+ .strict();
37
+ const generatorSchema = z
38
+ .object({
39
+ preset: z.enum([
40
+ "parser-boundaries",
41
+ "sanitizer-boundaries",
42
+ "clipboard-boundaries",
43
+ ]),
44
+ seed: z.number().int().min(0).max(0xffff_ffff),
45
+ count: z.number().int().min(1).max(64),
46
+ })
47
+ .strict();
48
+ const replayLimitsSchema = z
49
+ .object({
50
+ wall_time_ms: z.number().int().min(100).max(10_000).default(3_000),
51
+ memory_bytes: z
52
+ .number()
53
+ .int()
54
+ .min(16 * 1024 * 1024)
55
+ .max(512 * 1024 * 1024)
56
+ .default(128 * 1024 * 1024),
57
+ tasks: z.number().int().min(1).max(32).default(8),
58
+ cpu_quota_percent: z.number().int().min(1).max(100).default(50),
59
+ tmpfs_bytes: z
60
+ .number()
61
+ .int()
62
+ .min(1024 * 1024)
63
+ .max(64 * 1024 * 1024)
64
+ .default(16 * 1024 * 1024),
65
+ module_bytes: z
66
+ .number()
67
+ .int()
68
+ .min(1)
69
+ .max(16 * 1024 * 1024)
70
+ .default(4 * 1024 * 1024),
71
+ input_bytes: z
72
+ .number()
73
+ .int()
74
+ .min(1)
75
+ .max(1024 * 1024)
76
+ .default(256 * 1024),
77
+ protocol_bytes: z
78
+ .number()
79
+ .int()
80
+ .min(1024 * 1024)
81
+ .max(64 * 1024 * 1024)
82
+ .default(16 * 1024 * 1024),
83
+ output_bytes: z
84
+ .number()
85
+ .int()
86
+ .min(1)
87
+ .max(4 * 1024 * 1024)
88
+ .default(512 * 1024),
89
+ stderr_bytes: z
90
+ .number()
91
+ .int()
92
+ .min(0)
93
+ .max(256 * 1024)
94
+ .default(32 * 1024),
95
+ result_depth: z.number().int().min(1).max(64).default(16),
96
+ result_nodes: z.number().int().min(1).max(100_000).default(10_000),
97
+ })
98
+ .strict();
99
+ const determinismSchema = z
100
+ .object({
101
+ clock_iso: z.iso.datetime().default("2000-01-01T00:00:00.000Z"),
102
+ random_seed: z.number().int().min(0).max(0xffff_ffff).default(0),
103
+ locale: z.literal("en-US").default("en-US"),
104
+ timezone: z.literal("UTC").default("UTC"),
105
+ platform: z.literal("linux").default("linux"),
106
+ })
107
+ .strict();
108
+ export const controlledReplayInputSchema = z
109
+ .object({
110
+ mode: z.enum(["plan", "execute"]),
111
+ left: replaySideSchema,
112
+ right: replaySideSchema.optional(),
113
+ cases: z.array(explicitCaseSchema).max(128).default([]),
114
+ generator: generatorSchema.optional(),
115
+ determinism: determinismSchema.default({
116
+ clock_iso: "2000-01-01T00:00:00.000Z",
117
+ random_seed: 0,
118
+ locale: "en-US",
119
+ timezone: "UTC",
120
+ platform: "linux",
121
+ }),
122
+ limits: replayLimitsSchema.default({
123
+ wall_time_ms: 3_000,
124
+ memory_bytes: 128 * 1024 * 1024,
125
+ tasks: 8,
126
+ cpu_quota_percent: 50,
127
+ tmpfs_bytes: 16 * 1024 * 1024,
128
+ module_bytes: 4 * 1024 * 1024,
129
+ input_bytes: 256 * 1024,
130
+ protocol_bytes: 16 * 1024 * 1024,
131
+ output_bytes: 512 * 1024,
132
+ stderr_bytes: 32 * 1024,
133
+ result_depth: 16,
134
+ result_nodes: 10_000,
135
+ }),
136
+ approved: z.boolean().default(false),
137
+ plan_digest: digestSchema.optional(),
138
+ reproducer_export: z
139
+ .object({
140
+ path: absolutePathSchema,
141
+ approved: z.boolean(),
142
+ include_sources: z.boolean().default(false),
143
+ })
144
+ .strict()
145
+ .optional(),
146
+ })
147
+ .strict()
148
+ .superRefine((value, context) => {
149
+ if (value.cases.length === 0 && value.generator === undefined)
150
+ context.addIssue({
151
+ code: "custom",
152
+ path: ["cases"],
153
+ message: "At least one explicit or generated case is required",
154
+ });
155
+ if (value.cases.length + (value.generator?.count ?? 0) > 128)
156
+ context.addIssue({
157
+ code: "custom",
158
+ path: ["generator", "count"],
159
+ message: "Explicit and generated replay cases must total at most 128",
160
+ });
161
+ if (value.mode === "execute" &&
162
+ (value.approved !== true || value.plan_digest === undefined))
163
+ context.addIssue({
164
+ code: "custom",
165
+ path: ["approved"],
166
+ message: "Execution requires literal approval and a plan digest",
167
+ });
168
+ });
169
+ const moduleCommitmentSchema = z
170
+ .object({
171
+ alias: aliasSchema,
172
+ canonical_path: z.string().min(1),
173
+ format: z.enum(["esm", "commonjs-factory"]),
174
+ role: z.enum(["module", "stub"]),
175
+ byte_count: z.number().int().min(0),
176
+ sha256: digestSchema,
177
+ dependencies: z.record(z.string(), aliasSchema),
178
+ })
179
+ .strict();
180
+ const runtimeIdentitySchema = z
181
+ .object({
182
+ path: z.string().min(1),
183
+ version: z.string().min(1),
184
+ sha256: digestSchema,
185
+ })
186
+ .strict();
187
+ const runtimeFileIdentitySchema = z
188
+ .object({
189
+ source_path: z.string().min(1),
190
+ destination_path: z.string().min(1),
191
+ sha256: digestSchema,
192
+ })
193
+ .strict();
194
+ const replayPlanSchema = z
195
+ .object({
196
+ schema_version: z.literal(1),
197
+ plan_digest: digestSchema,
198
+ policy_version: z.literal("linux-bwrap-systemd-v1"),
199
+ policy_sha256: digestSchema,
200
+ network: z.literal("none"),
201
+ filesystem: z
202
+ .object({
203
+ host_writes: z.literal(false),
204
+ private_tmpfs_bytes: z.number().int(),
205
+ })
206
+ .strict(),
207
+ runtime: z
208
+ .object({
209
+ executable: runtimeIdentitySchema,
210
+ worker: runtimeIdentitySchema,
211
+ read_only_files: z.array(runtimeFileIdentitySchema).min(1),
212
+ })
213
+ .strict(),
214
+ sandbox: z
215
+ .object({
216
+ bubblewrap: runtimeIdentitySchema,
217
+ systemd_run: runtimeIdentitySchema,
218
+ systemctl: runtimeIdentitySchema,
219
+ shell: runtimeIdentitySchema,
220
+ seccomp_sha256: digestSchema,
221
+ })
222
+ .strict(),
223
+ left: z
224
+ .object({
225
+ modules: z.array(moduleCommitmentSchema),
226
+ entry_alias: aliasSchema,
227
+ entry_export: z.string(),
228
+ })
229
+ .strict(),
230
+ right: z
231
+ .object({
232
+ modules: z.array(moduleCommitmentSchema),
233
+ entry_alias: aliasSchema,
234
+ entry_export: z.string(),
235
+ })
236
+ .strict()
237
+ .optional(),
238
+ cases: z.array(z
239
+ .object({
240
+ case_id: z.string(),
241
+ arguments: z.array(z.json()),
242
+ sha256: digestSchema,
243
+ })
244
+ .strict()),
245
+ determinism: determinismSchema,
246
+ limits: replayLimitsSchema,
247
+ effects: z.array(z.string()),
248
+ reproducer_export: z
249
+ .object({
250
+ path: z.string().min(1),
251
+ include_sources: z.boolean(),
252
+ authority: z.literal("evidence_write"),
253
+ })
254
+ .strict()
255
+ .nullable(),
256
+ })
257
+ .strict();
258
+ const replayOutcomeSchema = z
259
+ .object({
260
+ case_id: z.string(),
261
+ outcome: z.enum([
262
+ "return",
263
+ "exception",
264
+ "serialization_error",
265
+ "denied",
266
+ "timeout",
267
+ "oom",
268
+ "crash",
269
+ "cancelled",
270
+ "protocol_error",
271
+ ]),
272
+ value: z.json().optional(),
273
+ exception: z
274
+ .object({
275
+ name: z.string(),
276
+ message: z.string(),
277
+ stack: z.string().nullable(),
278
+ })
279
+ .strict()
280
+ .optional(),
281
+ input_sha256: digestSchema,
282
+ output_sha256: digestSchema.nullable(),
283
+ truncated: z.boolean(),
284
+ })
285
+ .strict();
286
+ export const replayExecutionResultSchema = z
287
+ .object({
288
+ schema_version: z.literal(1),
289
+ plan_digest: digestSchema,
290
+ outcomes: z.array(replayOutcomeSchema),
291
+ comparison: z
292
+ .array(z
293
+ .object({
294
+ case_id: z.string(),
295
+ status: z.enum(["equal", "changed", "unknown"]),
296
+ left_index: z.number().int(),
297
+ right_index: z.number().int(),
298
+ })
299
+ .strict())
300
+ .optional(),
301
+ stderr: z.string(),
302
+ termination: z.enum([
303
+ "completed",
304
+ "timeout",
305
+ "oom",
306
+ "crash",
307
+ "cancelled",
308
+ "protocol_error",
309
+ ]),
310
+ cleanup: z
311
+ .object({
312
+ state: z.enum(["complete", "incomplete"]),
313
+ residual_resources: z.array(z.string()),
314
+ })
315
+ .strict(),
316
+ limitations: z.array(z.string()),
317
+ reproducer: z
318
+ .discriminatedUnion("state", [
319
+ z
320
+ .object({
321
+ state: z.literal("written"),
322
+ path: z.string(),
323
+ sha256: digestSchema,
324
+ })
325
+ .strict(),
326
+ z
327
+ .object({
328
+ state: z.literal("failed"),
329
+ path: z.string(),
330
+ error: z.string(),
331
+ })
332
+ .strict(),
333
+ ])
334
+ .nullable(),
335
+ })
336
+ .strict();
337
+ export const replayEvidenceSchema = evidenceEnvelopeSchema
338
+ .omit({ normalized_result: true })
339
+ .extend({ normalized_result: replayExecutionResultSchema });
340
+ export const controlledReplayOutputSchema = z
341
+ .object({
342
+ phase: z.enum(["plan", "execute"]),
343
+ plan: replayPlanSchema.nullable(),
344
+ source_evidence: z.array(replayEvidenceSchema),
345
+ evidence: replayEvidenceSchema.nullable(),
346
+ })
347
+ .strict()
348
+ .superRefine((value, context) => {
349
+ if ((value.phase === "plan" &&
350
+ (value.plan === null ||
351
+ value.evidence !== null ||
352
+ value.source_evidence.length !== 0)) ||
353
+ (value.phase === "execute" &&
354
+ (value.plan !== null ||
355
+ value.evidence === null ||
356
+ value.source_evidence.length === 0)))
357
+ context.addIssue({
358
+ code: "custom",
359
+ message: "Replay output phase does not match its payload",
360
+ });
361
+ });
@@ -0,0 +1,106 @@
1
+ import { compareCodePoints, } from "./javascriptApplicationGraph.js";
2
+ import { createStaticRuntimeScope, mappedRuntimePaths, staticNodeWithinRuntimeScope, } from "./javascriptRuntimeStaticCandidates.js";
3
+ /** Classify static code presence without claiming bundled module execution. */
4
+ export const classifyStaticLoadStates = (layers, runtimeEntities, matches, options) => {
5
+ const states = [];
6
+ let totalStates = 0;
7
+ for (const layer of layers) {
8
+ const projection = classifyLayer(layer, runtimeEntities, matches, {
9
+ reconciliationComplete: options.reconciliationComplete,
10
+ maximumStates: Math.max(0, options.maximumStates - states.length),
11
+ });
12
+ totalStates += projection.total;
13
+ states.push(...projection.states);
14
+ }
15
+ return { states, omittedStates: totalStates - states.length };
16
+ };
17
+ const classifyLayer = (layer, runtimeEntities, matches, options) => {
18
+ const nodes = layer.graph.nodes.filter(isLoadStateNode);
19
+ if (options.maximumStates === 0)
20
+ return { states: [], total: nodes.length };
21
+ const direct = new Map();
22
+ for (const match of matches)
23
+ if (match.status === "matched" &&
24
+ match.static_layer_id === layer.layerId &&
25
+ match.static_node_id !== null)
26
+ append(direct, match.static_node_id, match.runtime_node_id);
27
+ const resident = residentNodes(layer, new Set(direct.keys()));
28
+ const runtimeScope = createStaticRuntimeScope(layer, runtimeEntities);
29
+ const scopedEntities = runtimeEntities.filter((entity) => mappedRuntimePaths(layer, entity).length > 0);
30
+ const layerComplete = options.reconciliationComplete &&
31
+ layer.graph.coverage.status === "complete" &&
32
+ scopedEntities.length > 0 &&
33
+ scopedEntities.every(({ capture }) => captureScriptsComplete(capture.evidence.evidence_id, runtimeEntities));
34
+ const states = nodes.slice(0, options.maximumStates).map((node) => {
35
+ const runtimeNodeIds = uniqueSorted(direct.get(node.node_id) ?? []);
36
+ if (runtimeNodeIds.length > 0)
37
+ return state(layer, node, {
38
+ status: "loaded",
39
+ runtimeNodeIds,
40
+ reason: "runtime-script-correspondence",
41
+ });
42
+ if (resident.has(node.node_id))
43
+ return state(layer, node, {
44
+ status: "resident-in-loaded-asset",
45
+ runtimeNodeIds: [],
46
+ reason: "containing-asset-was-loaded",
47
+ });
48
+ const nodeWithinScope = staticNodeWithinRuntimeScope(node, runtimeScope);
49
+ if (layerComplete && nodeWithinScope)
50
+ return state(layer, node, {
51
+ status: "not-observed-in-capture",
52
+ runtimeNodeIds: [],
53
+ reason: "not-observed-in-bounded-capture",
54
+ });
55
+ return state(layer, node, {
56
+ status: "unknown",
57
+ runtimeNodeIds: [],
58
+ reason: !nodeWithinScope
59
+ ? "layer-outside-runtime-scope"
60
+ : "static-or-runtime-coverage-incomplete",
61
+ });
62
+ });
63
+ return { states, total: nodes.length };
64
+ };
65
+ const residentNodes = (layer, directlyLoaded) => {
66
+ const nodeKinds = new Map(layer.graph.nodes.map(({ node_id: id, kind }) => [id, kind]));
67
+ const children = new Map();
68
+ for (const edge of layer.graph.edges)
69
+ if (edge.relation === "contains")
70
+ append(children, edge.source_node_id, edge.target_node_id);
71
+ const pending = [...directlyLoaded].filter((nodeId) => nodeKinds.get(nodeId) === "javascript-asset");
72
+ const resident = new Set();
73
+ for (let index = 0; index < pending.length; index += 1) {
74
+ const current = pending[index];
75
+ if (current === undefined)
76
+ break;
77
+ for (const child of children.get(current) ?? []) {
78
+ if (resident.has(child))
79
+ continue;
80
+ resident.add(child);
81
+ pending.push(child);
82
+ }
83
+ }
84
+ return resident;
85
+ };
86
+ const append = (values, key, value) => {
87
+ const current = values.get(key);
88
+ if (current === undefined)
89
+ values.set(key, [value]);
90
+ else
91
+ current.push(value);
92
+ };
93
+ const captureScriptsComplete = (evidenceId, entities) => entities.find(({ capture }) => capture.evidence.evidence_id === evidenceId)
94
+ ?.capture.scriptsCompleteWithinScope === true;
95
+ const isLoadStateNode = (node) => node.kind === "javascript-asset" ||
96
+ node.kind === "javascript-chunk" ||
97
+ node.kind === "javascript-module";
98
+ const state = (layer, node, input) => ({
99
+ static_layer_id: layer.layerId,
100
+ static_node_id: node.node_id,
101
+ kind: node.kind,
102
+ status: input.status,
103
+ runtime_node_ids: [...input.runtimeNodeIds],
104
+ reason: input.reason,
105
+ });
106
+ const uniqueSorted = (values) => [...new Set(values)].sort(compareCodePoints);
@@ -0,0 +1,42 @@
1
+ import { classifyStaticLoadStates } from "./javascriptRuntimeLoadState.js";
2
+ import { buildReconciledApplicationGraph } from "./javascriptRuntimeReconciliationGraph.js";
3
+ import { reconcileRuntimeEntities } from "./javascriptRuntimeReconciliationMatching.js";
4
+ import { parseRuntimeCaptures, parseStaticLayers, } from "./javascriptRuntimeReconciliationParsing.js";
5
+ import { createJavaScriptRuntimeReconciliationResult } from "./javascriptRuntimeReconciliationResult.js";
6
+ import { reconcileJavaScriptRuntimeInputSchema } from "./javascriptRuntimeReconciliationSchemas.js";
7
+ import { projectRuntimeCaptures } from "./javascriptRuntimeReconciliationRuntime.js";
8
+ import { collectStaticRuntimeCandidates } from "./javascriptRuntimeStaticCandidates.js";
9
+ /** Reconcile static JAG layers with authorized passive CDP Evidence. */
10
+ export const reconcileJavaScriptRuntime = (input) => {
11
+ const parsed = reconcileJavaScriptRuntimeInputSchema.parse(input);
12
+ const layers = parseStaticLayers(parsed.static_layers);
13
+ const captures = parseRuntimeCaptures(parsed.runtime_observations);
14
+ const runtime = projectRuntimeCaptures(captures, parsed.limits.max_runtime_entities);
15
+ const candidates = collectStaticRuntimeCandidates(layers);
16
+ const matching = reconcileRuntimeEntities({
17
+ entities: runtime.entities,
18
+ candidates,
19
+ layers,
20
+ maximumItems: parsed.limits.max_reconciliation_items,
21
+ });
22
+ const loadStates = classifyStaticLoadStates(layers, runtime.entities, matching.items, {
23
+ maximumStates: parsed.limits.max_static_load_states,
24
+ reconciliationComplete: runtime.omittedEntities === 0 && matching.omittedItems === 0,
25
+ });
26
+ const graph = buildReconciledApplicationGraph({
27
+ layers,
28
+ captures,
29
+ runtime,
30
+ reconciliationEdges: matching.edges,
31
+ omittedReconciliationItems: matching.omittedItems,
32
+ });
33
+ return createJavaScriptRuntimeReconciliationResult({
34
+ layers,
35
+ captures,
36
+ runtime,
37
+ matching,
38
+ loadStates,
39
+ graph: graph.graph,
40
+ omittedGraphItems: graph.omittedGraphItems,
41
+ });
42
+ };
@@ -0,0 +1,169 @@
1
+ import { compareCodePoints, createJavaScriptApplicationGraph, createJavaScriptApplicationNode, } from "./javascriptApplicationGraph.js";
2
+ /** Merge source graphs, runtime nodes, and inferred mappings into one valid JAG. */
3
+ export const buildReconciledApplicationGraph = (input) => {
4
+ const merged = mergeNodes([
5
+ ...input.layers.flatMap(({ graph }) => graph.nodes),
6
+ ...input.runtime.nodes,
7
+ ]);
8
+ const allEdges = uniqueEdges([
9
+ ...input.layers.flatMap(({ graph }) => graph.edges),
10
+ ...input.runtime.edges,
11
+ ...input.reconciliationEdges,
12
+ ]);
13
+ const bounded = boundGraphContent(input, merged.nodes, allEdges);
14
+ const facts = graphCoverageFacts(input, merged.omittedObservations + bounded.omittedItems);
15
+ const graph = createJavaScriptApplicationGraph({
16
+ schema: "JavaScriptApplicationGraph",
17
+ schema_version: 1,
18
+ root_node_ids: bounded.rootNodeIds,
19
+ nodes: bounded.nodes,
20
+ edges: bounded.edges,
21
+ coverage: graphCoverage(input, facts, bounded.nodes.length),
22
+ limitations: uniqueSorted([
23
+ ...input.layers.flatMap(({ graph }) => graph.limitations),
24
+ "Runtime presence is bounded to passive capture windows and does not prove feature execution.",
25
+ "Cross-layer observed_as edges are inferences; digest equality proves byte identity only.",
26
+ "Source-map relationships retain their original static authority and are not promoted into runtime matches.",
27
+ ...(facts.inputTruncated
28
+ ? [
29
+ "One or more source graphs or passive captures were incomplete or truncated.",
30
+ ]
31
+ : []),
32
+ ...(facts.outputTruncated
33
+ ? [
34
+ "The reconciled graph omitted entities or classifications at caller limits.",
35
+ ]
36
+ : []),
37
+ ]),
38
+ });
39
+ return {
40
+ graph,
41
+ omittedGraphItems: merged.omittedObservations + bounded.omittedItems,
42
+ };
43
+ };
44
+ const boundGraphContent = (input, nodes, edges) => {
45
+ const allRoots = preferredRootIds(input);
46
+ const rootNodeIds = allRoots.slice(0, 1_000);
47
+ const roots = new Set(rootNodeIds);
48
+ const sortedNodes = [...nodes].sort((left, right) => compareCodePoints(left.node_id, right.node_id));
49
+ const retainedNodes = [
50
+ ...sortedNodes.filter(({ node_id: id }) => roots.has(id)),
51
+ ...sortedNodes.filter(({ node_id: id }) => !roots.has(id)),
52
+ ].slice(0, 100_000);
53
+ const retainedIds = new Set(retainedNodes.map(({ node_id: id }) => id));
54
+ const retainedEdges = [...edges]
55
+ .sort((left, right) => compareCodePoints(left.edge_id, right.edge_id))
56
+ .filter(({ source_node_id: source, target_node_id: target }) => retainedIds.has(source) && retainedIds.has(target))
57
+ .slice(0, 200_000);
58
+ return {
59
+ rootNodeIds,
60
+ nodes: retainedNodes,
61
+ edges: retainedEdges,
62
+ omittedItems: allRoots.length -
63
+ rootNodeIds.length +
64
+ (nodes.length - retainedNodes.length) +
65
+ (edges.length - retainedEdges.length),
66
+ };
67
+ };
68
+ const preferredRootIds = (input) => {
69
+ const runtime = [...input.runtime.targetNodeByEvidenceId.values()].map(({ node_id: id }) => id);
70
+ const application = input.layers
71
+ .filter(({ role }) => role === "application")
72
+ .flatMap(({ graph }) => graph.root_node_ids);
73
+ const supplemental = input.layers
74
+ .filter(({ role }) => role !== "application")
75
+ .flatMap(({ graph }) => graph.root_node_ids);
76
+ return [...new Set([...runtime, ...application, ...supplemental])];
77
+ };
78
+ const graphCoverageFacts = (input, omittedNodeObservations) => {
79
+ const projectionOmissions = input.runtime.omittedEntities +
80
+ input.omittedReconciliationItems +
81
+ omittedNodeObservations;
82
+ const captureTruncated = input.captures.some(({ inspection }) => inspection.completeness.conditions.includes("truncated"));
83
+ const captureHasUnknownOmissions = input.captures.some(({ inspection }) => inspection.completeness.unavailable_sections.length > 0);
84
+ const inputTruncated = input.layers.some(({ graph }) => graph.coverage.truncated) ||
85
+ captureTruncated;
86
+ const outputTruncated = projectionOmissions > 0;
87
+ const sourceOmissions = input.layers.reduce((total, { graph }) => total + (graph.coverage.omitted_count ?? 0), 0);
88
+ const omissionsKnown = !captureTruncated &&
89
+ !captureHasUnknownOmissions &&
90
+ input.layers.every(({ graph }) => graph.coverage.omitted_count !== null);
91
+ return {
92
+ projectionOmissions,
93
+ knownOmissions: projectionOmissions + sourceOmissions,
94
+ omissionsKnown,
95
+ inputTruncated,
96
+ outputTruncated,
97
+ truncated: inputTruncated || outputTruncated,
98
+ complete: !inputTruncated &&
99
+ !outputTruncated &&
100
+ input.layers.every(({ graph }) => graph.coverage.status === "complete") &&
101
+ input.captures.every(({ inspection }) => inspection.completeness.status === "complete_within_window"),
102
+ };
103
+ };
104
+ const graphCoverage = (input, facts, nodeCount) => facts.complete
105
+ ? { status: "complete", truncated: false, omitted_count: 0, limits: [] }
106
+ : facts.truncated
107
+ ? {
108
+ status: "partial",
109
+ truncated: true,
110
+ omitted_count: facts.omissionsKnown ? facts.knownOmissions : null,
111
+ limits: [
112
+ ...(facts.inputTruncated
113
+ ? [
114
+ {
115
+ name: "runtime-reconciliation-input-coverage",
116
+ value: input.layers.length + input.captures.length,
117
+ unit: "items",
118
+ },
119
+ ]
120
+ : []),
121
+ ...(facts.outputTruncated
122
+ ? [
123
+ {
124
+ name: "runtime-reconciliation-output-limits",
125
+ value: nodeCount,
126
+ unit: "items",
127
+ },
128
+ ]
129
+ : []),
130
+ ],
131
+ }
132
+ : {
133
+ status: "partial",
134
+ truncated: false,
135
+ omitted_count: facts.omissionsKnown ? facts.knownOmissions : null,
136
+ limits: [],
137
+ };
138
+ const mergeNodes = (nodes) => {
139
+ const grouped = new Map();
140
+ for (const node of nodes)
141
+ grouped.set(node.node_id, [...(grouped.get(node.node_id) ?? []), node]);
142
+ let omittedObservations = 0;
143
+ const merged = [...grouped.values()].map((group) => {
144
+ const first = group[0];
145
+ if (first === undefined)
146
+ throw new TypeError("Empty JAG node group");
147
+ if (group.some(({ kind, identity }) => kind !== first.kind ||
148
+ JSON.stringify(identity) !== JSON.stringify(first.identity)))
149
+ throw new TypeError("Colliding JAG node identifiers disagree");
150
+ const observations = [
151
+ ...new Map(group
152
+ .flatMap(({ observations: values }) => values)
153
+ .map((observation) => [observation.observation_id, observation])).values(),
154
+ ].sort((left, right) => compareCodePoints(left.observation_id, right.observation_id));
155
+ omittedObservations += Math.max(0, observations.length - 64);
156
+ return createJavaScriptApplicationNode({
157
+ kind: first.kind,
158
+ identity: first.identity,
159
+ observations: observations
160
+ .slice(0, 64)
161
+ .map(({ observation_id: _id, identifier_strategy: _strategy, ...value }) => value),
162
+ });
163
+ });
164
+ return { nodes: merged, omittedObservations };
165
+ };
166
+ const uniqueEdges = (edges) => [
167
+ ...new Map(edges.map((edge) => [edge.edge_id, edge])).values(),
168
+ ];
169
+ const uniqueSorted = (values) => [...new Set(values)].sort(compareCodePoints);