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,34 @@
1
+ import { compareApplicationVersionsEvidenceValidated } from "../../application/JavaScriptApplicationWorkflowService.js";
2
+ import { APPLICATION_TOOL_CONTRACTS } from "../../contracts/applicationToolContracts.js";
3
+ import { compareApplicationVersionsInputSchema } from "../../domain/javascriptApplicationVersionComparisonSchemas.js";
4
+ import { applicationVersionComparisonResultSchema } from "../../domain/javascriptApplicationVersionComparisonSchemas.js";
5
+ import { logToolExecution } from "../toolLogging.js";
6
+ import { toCallToolResult } from "../toolResult.js";
7
+ import { toolRegistrationOptions } from "../toolRegistrationOptions.js";
8
+ import { safeParseToolInput } from "../toolInputValidation.js";
9
+ import { recordResult, recordSources } from "./helpers.js";
10
+ const compareContract = APPLICATION_TOOL_CONTRACTS[1];
11
+ /** Register the provider-neutral JavaScript version comparison tool. */
12
+ export const registerCompareApplicationVersionsTool = (server, options) => {
13
+ server.registerTool(compareContract.name, toolRegistrationOptions(compareContract), async (input) => {
14
+ const parsedInput = safeParseToolInput(compareApplicationVersionsInputSchema, input, compareContract.name);
15
+ if (!parsedInput.ok)
16
+ return toCallToolResult(parsedInput, compareContract);
17
+ const parsed = parsedInput.value;
18
+ const result = await logToolExecution(options.logger, compareContract.name, () => Promise.resolve(compareApplicationVersionsEvidenceValidated(parsed)));
19
+ if (!result.ok)
20
+ return toCallToolResult(result, compareContract);
21
+ const sources = [
22
+ parsed.left,
23
+ parsed.right,
24
+ ...parsed.left_native_observations,
25
+ ...parsed.right_native_observations,
26
+ ];
27
+ const recorded = recordSources(options.recordEvidence, sources);
28
+ if (!recorded.ok)
29
+ return toCallToolResult(recorded, compareContract);
30
+ const comparison = applicationVersionComparisonResultSchema.parse(result.value.normalized_result);
31
+ const unknown = comparison.summary.unknown > 0;
32
+ return recordResult(options, compareContract, result.value, parsed.unknown_registry_approved === true && unknown);
33
+ });
34
+ };
@@ -0,0 +1,38 @@
1
+ import { runControlledReplayValidated } from "../../application/JavaScriptReplayService.js";
2
+ import { APPLICATION_TOOL_CONTRACTS } from "../../contracts/applicationToolContracts.js";
3
+ import { controlledReplayInputSchema, controlledReplayOutputSchema, } from "../../domain/javascriptReplay.js";
4
+ import { parseEvidence } from "../../domain/evidence.js";
5
+ import { logToolExecution } from "../toolLogging.js";
6
+ import { toCallToolResult } from "../toolResult.js";
7
+ import { toolRegistrationOptions } from "../toolRegistrationOptions.js";
8
+ import { safeParseToolInput } from "../toolInputValidation.js";
9
+ import { mcpProgressReporter } from "../mcpProgress.js";
10
+ import { recordSources } from "./helpers.js";
11
+ const replayContract = APPLICATION_TOOL_CONTRACTS[2];
12
+ /** Register the controlled JavaScript replay tool. */
13
+ export const registerControlledReplayTool = (server, options) => {
14
+ server.registerTool(replayContract.name, toolRegistrationOptions(replayContract), async (input, context) => {
15
+ const parsedInput = safeParseToolInput(controlledReplayInputSchema, input, replayContract.name);
16
+ if (!parsedInput.ok)
17
+ return toCallToolResult(parsedInput, replayContract);
18
+ const parsed = parsedInput.value;
19
+ const result = await logToolExecution(options.logger, replayContract.name, () => runControlledReplayValidated(options.replay, parsed, {
20
+ signal: context.mcpReq.signal,
21
+ progress: mcpProgressReporter(context),
22
+ }));
23
+ if (!result.ok)
24
+ return toCallToolResult(result, replayContract);
25
+ const output = controlledReplayOutputSchema.parse(result.value);
26
+ if (output.evidence !== null) {
27
+ const sourcesRecorded = recordSources(options.recordEvidence, output.source_evidence.map((item) => parseEvidence(item)));
28
+ if (!sourcesRecorded.ok)
29
+ return toCallToolResult(sourcesRecorded, replayContract);
30
+ const recorded = options.recordEvidence?.(parseEvidence(output.evidence));
31
+ if (recorded !== undefined && !recorded.ok)
32
+ return toCallToolResult(recorded, replayContract);
33
+ }
34
+ return toCallToolResult(result, replayContract, {
35
+ evidenceResourcesAvailable: output.evidence !== null && options.recordEvidence !== undefined,
36
+ });
37
+ });
38
+ };
@@ -0,0 +1,84 @@
1
+ import { commitReconstructionCoverage, queryReconstructionCoverage, } from "../../application/ReconstructionCoverageService.js";
2
+ import { readReconstructionCoverageWorkspace } from "../../application/ReconstructionCoverageWorkspaceStore.js";
3
+ import { authorizeFileReadWithDeferredWrite, authorizeRootPermission, } from "../../application/DeferredFileAuthorization.js";
4
+ import { APPLICATION_TOOL_CONTRACTS } from "../../contracts/applicationToolContracts.js";
5
+ import { reconstructionCoverageCommitInputSchema, reconstructionCoverageQueryInputSchema, } from "../../application/ReconstructionCoverageService.js";
6
+ import { reconstructionClosureResultSchema } from "../../domain/reconstructionCoverage.js";
7
+ import { AnalysisCapabilityUnavailableError, EvidenceIntegrityError, } from "../../domain/errors.js";
8
+ import { err } from "../../domain/result.js";
9
+ import { logToolExecution } from "../toolLogging.js";
10
+ import { toCallToolResult } from "../toolResult.js";
11
+ import { toolRegistrationOptions } from "../toolRegistrationOptions.js";
12
+ import { safeParseToolInput } from "../toolInputValidation.js";
13
+ import { coverageWorkspaceUri } from "./helpers.js";
14
+ const commitContract = APPLICATION_TOOL_CONTRACTS[5];
15
+ const queryContract = APPLICATION_TOOL_CONTRACTS[6];
16
+ /** Register reconstruction coverage commit and query tools. */
17
+ export const registerCoverageTools = (server, options) => {
18
+ registerCommitTool(server, options);
19
+ registerQueryTool(server, options);
20
+ };
21
+ const registerCommitTool = (server, options) => {
22
+ server.registerTool(commitContract.name, toolRegistrationOptions(commitContract), async (input, context) => {
23
+ const parsed = safeParseToolInput(reconstructionCoverageCommitInputSchema, input, commitContract.name);
24
+ if (!parsed.ok)
25
+ return toCallToolResult(parsed, commitContract);
26
+ if (options.permissionAuthority === undefined)
27
+ return toCallToolResult(err(new AnalysisCapabilityUnavailableError("rea-reconstruction-coverage", commitContract.name, "workspace permission policy is not configured")), commitContract);
28
+ const authorization = await authorizeFileReadWithDeferredWrite(options.permissionAuthority, {
29
+ path: parsed.value.workspace_path,
30
+ readCapability: "investigation_workspace_read",
31
+ writeCapability: "investigation_workspace_write",
32
+ operation: commitContract.name,
33
+ });
34
+ if (!authorization.ok)
35
+ return toCallToolResult(authorization, commitContract);
36
+ const write = await authorization.value.authorizeWrite();
37
+ if (!write.ok)
38
+ return toCallToolResult(write, commitContract);
39
+ const result = await logToolExecution(options.logger, commitContract.name, () => commitReconstructionCoverage(parsed.value, options.evidenceFilePolicy, { signal: context.mcpReq.signal }));
40
+ if (!result.ok)
41
+ return toCallToolResult(result, commitContract);
42
+ options.retainCoverageWorkspace?.(parsed.value.workspace);
43
+ return toCallToolResult(result, commitContract, {
44
+ resourceLinks: options.retainCoverageWorkspace === undefined
45
+ ? []
46
+ : [
47
+ {
48
+ uri: coverageWorkspaceUri(parsed.value.workspace),
49
+ name: parsed.value.workspace.workspace_id,
50
+ description: "Session-retained reconstruction coverage workspace revision",
51
+ },
52
+ ],
53
+ });
54
+ });
55
+ };
56
+ const registerQueryTool = (server, options) => {
57
+ server.registerTool(queryContract.name, toolRegistrationOptions(queryContract), async (input, context) => {
58
+ const parsed = safeParseToolInput(reconstructionCoverageQueryInputSchema, input, queryContract.name);
59
+ if (!parsed.ok)
60
+ return toCallToolResult(parsed, queryContract);
61
+ if (options.permissionAuthority === undefined)
62
+ return toCallToolResult(err(new AnalysisCapabilityUnavailableError("rea-reconstruction-coverage", queryContract.name, "workspace permission policy is not configured")), queryContract);
63
+ const authorized = await authorizeRootPermission(options.permissionAuthority, {
64
+ capability: "investigation_workspace_read",
65
+ roots: [parsed.value.workspace_path],
66
+ access: "read",
67
+ operation: queryContract.name,
68
+ });
69
+ if (!authorized.ok)
70
+ return toCallToolResult(authorized, queryContract);
71
+ const result = await logToolExecution(options.logger, queryContract.name, () => queryReconstructionCoverage(parsed.value, options.evidenceFilePolicy, Date.now(), { signal: context.mcpReq.signal }));
72
+ if (result.ok && options.retainCoverageWorkspace !== undefined) {
73
+ const closure = reconstructionClosureResultSchema.parse(result.value);
74
+ const loaded = await readReconstructionCoverageWorkspace(parsed.value.workspace_path, options.evidenceFilePolicy);
75
+ if (!loaded.ok)
76
+ return toCallToolResult(loaded, queryContract);
77
+ if (loaded.value === null ||
78
+ loaded.value.revision_sha256 !== closure.workspace_revision_sha256)
79
+ return toCallToolResult(err(new EvidenceIntegrityError("workspace changed while its closure was being retained")), queryContract);
80
+ options.retainCoverageWorkspace(loaded.value);
81
+ }
82
+ return toCallToolResult(result, queryContract);
83
+ });
84
+ };
@@ -0,0 +1,42 @@
1
+ import { APPLICATION_TOOL_CONTRACTS } from "../../contracts/applicationToolContracts.js";
2
+ import { toCallToolResult } from "../toolResult.js";
3
+ export const coverageWorkspaceUri = (workspace) => `rea://reconstruction-coverage/${workspace.workspace_id}/revision/${String(workspace.revision)}`;
4
+ export const recordSources = (recordEvidence, sources) => {
5
+ for (const source of sources) {
6
+ const recorded = recordEvidence?.(source);
7
+ if (recorded !== undefined && !recorded.ok)
8
+ return recorded;
9
+ }
10
+ return { ok: true, value: null };
11
+ };
12
+ export const recordResult = (options, contract, evidence, recordUnknown = false) => {
13
+ const recorded = recordUnknown
14
+ ? options.recordEvidenceWithUnknown?.(evidence, {
15
+ approved: true,
16
+ question: "Which application entities remain unmatched or ambiguous across these versions?",
17
+ severity: "medium",
18
+ domain: "application-version-comparison",
19
+ supporting_evidence_ids: [evidence.evidence_id],
20
+ contradicting_evidence_ids: [],
21
+ required_authority: "shipped-artifact",
22
+ required_confidence: "observed",
23
+ required_environment: null,
24
+ recommended_probes: [
25
+ {
26
+ operation: "analyze_javascript_application",
27
+ rationale: "Repeat static reconstruction with complete artifacts and source maps when available.",
28
+ },
29
+ {
30
+ operation: "reconcile_javascript_runtime",
31
+ rationale: "Add approved passive runtime Evidence without promoting it to static fact.",
32
+ },
33
+ ],
34
+ relationships: [],
35
+ })
36
+ : options.recordEvidence?.(evidence);
37
+ if (recorded !== undefined && !recorded.ok)
38
+ return toCallToolResult(recorded, contract);
39
+ return toCallToolResult({ ok: true, value: evidence }, contract, {
40
+ evidenceResourcesAvailable: recorded !== undefined,
41
+ });
42
+ };
@@ -0,0 +1,26 @@
1
+ import { traceApplicationFeatureEvidenceValidated } from "../../application/JavaScriptApplicationWorkflowService.js";
2
+ import { APPLICATION_TOOL_CONTRACTS } from "../../contracts/applicationToolContracts.js";
3
+ import { traceApplicationFeatureInputSchema } from "../../domain/javascriptFeatureTraceSchemas.js";
4
+ import { logToolExecution } from "../toolLogging.js";
5
+ import { toCallToolResult } from "../toolResult.js";
6
+ import { toolRegistrationOptions } from "../toolRegistrationOptions.js";
7
+ import { safeParseToolInput } from "../toolInputValidation.js";
8
+ import { recordResult, recordSources } from "./helpers.js";
9
+ const traceContract = APPLICATION_TOOL_CONTRACTS[0];
10
+ /** Register the provider-neutral JavaScript feature trace tool. */
11
+ export const registerTraceFeatureTool = (server, options) => {
12
+ server.registerTool(traceContract.name, toolRegistrationOptions(traceContract), async (input) => {
13
+ const parsedInput = safeParseToolInput(traceApplicationFeatureInputSchema, input, traceContract.name);
14
+ if (!parsedInput.ok)
15
+ return toCallToolResult(parsedInput, traceContract);
16
+ const parsed = parsedInput.value;
17
+ const result = await logToolExecution(options.logger, traceContract.name, () => Promise.resolve(traceApplicationFeatureEvidenceValidated(parsed)));
18
+ if (!result.ok)
19
+ return toCallToolResult(result, traceContract);
20
+ const sources = [parsed.application, ...parsed.native_observations];
21
+ const recorded = recordSources(options.recordEvidence, sources);
22
+ if (!recorded.ok)
23
+ return toCallToolResult(recorded, traceContract);
24
+ return recordResult(options, traceContract, result.value);
25
+ });
26
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,13 @@
1
+ import { registerTraceFeatureTool } from "./registerApplicationTools/traceFeature.js";
2
+ import { registerCompareApplicationVersionsTool } from "./registerApplicationTools/compareVersions.js";
3
+ import { registerControlledReplayTool } from "./registerApplicationTools/controlledReplay.js";
4
+ import { registerCharacterizationTools } from "./registerApplicationTools/characterization.js";
5
+ import { registerCoverageTools } from "./registerApplicationTools/coverage.js";
6
+ /** Register provider-neutral JavaScript application graph workflows. */
7
+ export const registerApplicationTools = (server, options) => {
8
+ registerTraceFeatureTool(server, options);
9
+ registerCompareApplicationVersionsTool(server, options);
10
+ registerControlledReplayTool(server, options);
11
+ registerCharacterizationTools(server, options);
12
+ registerCoverageTools(server, options);
13
+ };
@@ -2,27 +2,35 @@ import { artifactComparisonInputSchema, compareArtifacts, } from "../domain/arti
2
2
  import { createEvidence } from "../domain/evidence.js";
3
3
  import { jsonValueSchema } from "../domain/jsonValue.js";
4
4
  import { recordDerivedEvidence } from "./recordDerivedEvidence.js";
5
- import { resolveSessionEvidence } from "./sessionEvidence.js";
5
+ import { resolveSessionEvidenceIds } from "./sessionEvidence.js";
6
6
  import { ARTIFACT_COMPARISON_PROVIDER } from "./sessionToolPolicies.js";
7
7
  import { toCallToolResult } from "./toolResult.js";
8
8
  import { toolRegistrationOptions } from "./toolRegistrationOptions.js";
9
9
  import { runDerivedOperation } from "./runDerivedOperation.js";
10
+ import { safeParseToolInput } from "./toolInputValidation.js";
10
11
  /** Register Evidence-backed deterministic artifact comparison. */
11
12
  export const registerArtifactComparisonTool = (server, session, contract) => {
12
13
  server.registerTool(contract.name, toolRegistrationOptions(contract), async (input, context) => {
13
- const parsed = artifactComparisonInputSchema.parse(input);
14
- const left = resolveSessionEvidence(session, parsed.left);
14
+ const parsedInput = safeParseToolInput(artifactComparisonInputSchema, input, contract.name);
15
+ if (!parsedInput.ok)
16
+ return toCallToolResult(parsedInput, contract);
17
+ const parsed = parsedInput.value;
18
+ const expected = {
19
+ operation: "inventory_artifact",
20
+ predicate: "rea.analysis/v2",
21
+ };
22
+ const left = resolveSessionEvidenceIds(session, parsed.left_evidence_ids, expected);
15
23
  if (!left.ok)
16
24
  return toCallToolResult(left, contract);
17
- const right = resolveSessionEvidence(session, parsed.right);
25
+ const right = resolveSessionEvidenceIds(session, parsed.right_evidence_ids, expected);
18
26
  if (!right.ok)
19
27
  return toCallToolResult(right, contract);
20
28
  const computed = await runDerivedOperation(context, contract.name, () => compareArtifacts(left.value, right.value, parsed.offset, parsed.limit));
21
29
  if (!computed.ok)
22
30
  return toCallToolResult(computed, contract);
23
31
  const comparison = computed.value;
24
- const leftEvidenceIds = evidenceIds(parsed.left);
25
- const rightEvidenceIds = evidenceIds(parsed.right);
32
+ const leftEvidenceIds = parsed.left_evidence_ids;
33
+ const rightEvidenceIds = parsed.right_evidence_ids;
26
34
  const evidence = createEvidence(undefined, ARTIFACT_COMPARISON_PROVIDER, {
27
35
  predicateType: "rea.artifact-comparison/v1",
28
36
  operation: contract.name,
@@ -49,8 +57,8 @@ const artifactUnknownInput = (input, status) => {
49
57
  question: `Artifact comparison is ${status}`,
50
58
  severity: status === "unknown" || status === "truncated" ? "high" : "medium",
51
59
  domain: "artifact-comparison",
52
- supporting_evidence_ids: evidenceIds(input.left),
53
- contradicting_evidence_ids: evidenceIds(input.right),
60
+ supporting_evidence_ids: [...input.left_evidence_ids],
61
+ contradicting_evidence_ids: [...input.right_evidence_ids],
54
62
  required_authority: "shipped-artifact",
55
63
  required_confidence: "observed",
56
64
  required_environment: null,
@@ -63,4 +71,3 @@ const artifactUnknownInput = (input, status) => {
63
71
  relationships: [],
64
72
  };
65
73
  };
66
- const evidenceIds = (input) => (Array.isArray(input) ? input : [input]).map(({ evidence_id: id }) => id);
@@ -9,80 +9,81 @@ import { captureWebScreenshotInputSchema, compareWebScreenshotsInputSchema, } fr
9
9
  import { logToolExecution } from "./toolLogging.js";
10
10
  import { toCallToolResult } from "./toolResult.js";
11
11
  import { toolRegistrationOptions } from "./toolRegistrationOptions.js";
12
+ import { safeParseToolInput } from "./toolInputValidation.js";
12
13
  import { mcpProgressReporter } from "./mcpProgress.js";
13
14
  /** Register browser tools even when policy/provider availability denies execution. */
14
15
  export const registerBrowserTools = (server, options) => {
15
16
  const [listContract, inspectContract, analyzeContract, sessionContract, webMcpContract, captureDiffContract, screenshotContract, screenshotDiffContract,] = BROWSER_TOOL_CONTRACTS;
16
- server.registerTool(listContract.name, toolRegistrationOptions(listContract), async (input, context) => {
17
- const parsed = listBrowserTargetsInputSchema.parse(input);
18
- const result = await logToolExecution(options.logger, listContract.name, () => listBrowserTargets(options.browser, options.permissionAuthority, parsed, { signal: context.mcpReq.signal }));
19
- if (!result.ok)
20
- return toCallToolResult(result, listContract);
21
- return evidenceResult(options, listContract, result.value);
17
+ registerBrowserTool(server, options, {
18
+ contract: listContract,
19
+ schema: listBrowserTargetsInputSchema,
20
+ execute: (parsed, { signal }) => listBrowserTargets(options.browser, options.permissionAuthority, parsed, {
21
+ signal,
22
+ }),
22
23
  });
23
- server.registerTool(inspectContract.name, toolRegistrationOptions(inspectContract), async (input, context) => {
24
- const parsed = inspectWebPageInputSchema.parse(input);
25
- const result = await logToolExecution(options.logger, inspectContract.name, () => inspectWebPage(options.browser, options.permissionAuthority, parsed, {
26
- signal: context.mcpReq.signal,
27
- progress: mcpProgressReporter(context),
28
- }));
29
- if (!result.ok)
30
- return toCallToolResult(result, inspectContract);
31
- return evidenceResult(options, inspectContract, result.value);
24
+ registerBrowserTool(server, options, {
25
+ contract: inspectContract,
26
+ schema: inspectWebPageInputSchema,
27
+ execute: (parsed, { signal, progress }) => inspectWebPage(options.browser, options.permissionAuthority, parsed, {
28
+ signal,
29
+ progress,
30
+ }),
32
31
  });
33
- server.registerTool(analyzeContract.name, toolRegistrationOptions(analyzeContract), async (input, context) => {
34
- const parsed = analyzeWebBundleInputSchema.parse(input);
35
- const result = await logToolExecution(options.logger, analyzeContract.name, () => analyzeWebBundle(options.browser, options.permissionAuthority, parsed, {
36
- signal: context.mcpReq.signal,
37
- progress: mcpProgressReporter(context),
38
- }));
39
- if (!result.ok)
40
- return toCallToolResult(result, analyzeContract);
41
- return evidenceResult(options, analyzeContract, result.value);
32
+ registerBrowserTool(server, options, {
33
+ contract: analyzeContract,
34
+ schema: analyzeWebBundleInputSchema,
35
+ execute: (parsed, { signal, progress }) => analyzeWebBundle(options.browser, options.permissionAuthority, parsed, {
36
+ signal,
37
+ progress,
38
+ }),
42
39
  });
43
- server.registerTool(sessionContract.name, toolRegistrationOptions(sessionContract), async (input, context) => {
44
- const parsed = observeWebSessionInputSchema.parse(input);
45
- const result = await logToolExecution(options.logger, sessionContract.name, () => observeWebSession(options.browser, options.permissionAuthority, parsed, {
46
- signal: context.mcpReq.signal,
47
- progress: mcpProgressReporter(context),
48
- }));
49
- if (!result.ok)
50
- return toCallToolResult(result, sessionContract);
51
- return evidenceResult(options, sessionContract, result.value);
40
+ registerBrowserTool(server, options, {
41
+ contract: sessionContract,
42
+ schema: observeWebSessionInputSchema,
43
+ execute: (parsed, { signal, progress }) => observeWebSession(options.browser, options.permissionAuthority, parsed, {
44
+ signal,
45
+ progress,
46
+ }),
52
47
  });
53
- server.registerTool(webMcpContract.name, toolRegistrationOptions(webMcpContract), async (input, context) => {
54
- const parsed = discoverWebMcpToolsInputSchema.parse(input);
55
- const result = await logToolExecution(options.logger, webMcpContract.name, () => discoverWebMcpTools(options.browser, options.permissionAuthority, parsed, {
56
- signal: context.mcpReq.signal,
57
- progress: mcpProgressReporter(context),
58
- }));
59
- if (!result.ok)
60
- return toCallToolResult(result, webMcpContract);
61
- return evidenceResult(options, webMcpContract, result.value);
48
+ registerBrowserTool(server, options, {
49
+ contract: webMcpContract,
50
+ schema: discoverWebMcpToolsInputSchema,
51
+ execute: (parsed, { signal, progress }) => discoverWebMcpTools(options.browser, options.permissionAuthority, parsed, {
52
+ signal,
53
+ progress,
54
+ }),
62
55
  });
63
- server.registerTool(captureDiffContract.name, toolRegistrationOptions(captureDiffContract), async (input) => {
64
- const parsed = compareWebCapturesInputSchema.parse(input);
65
- const result = await logToolExecution(options.logger, captureDiffContract.name, () => compareWebCaptureEvidence(options.browser, parsed));
66
- if (!result.ok)
67
- return toCallToolResult(result, captureDiffContract);
68
- return evidenceResult(options, captureDiffContract, result.value);
56
+ registerBrowserTool(server, options, {
57
+ contract: captureDiffContract,
58
+ schema: compareWebCapturesInputSchema,
59
+ execute: (parsed, _context) => compareWebCaptureEvidence(options.browser, parsed),
69
60
  });
70
- server.registerTool(screenshotContract.name, toolRegistrationOptions(screenshotContract), async (input, context) => {
71
- const parsed = captureWebScreenshotInputSchema.parse(input);
72
- const result = await logToolExecution(options.logger, screenshotContract.name, () => captureWebScreenshot(options.browser, options.permissionAuthority, parsed, {
61
+ registerBrowserTool(server, options, {
62
+ contract: screenshotContract,
63
+ schema: captureWebScreenshotInputSchema,
64
+ execute: (parsed, { signal, progress }) => captureWebScreenshot(options.browser, options.permissionAuthority, parsed, {
65
+ signal,
66
+ progress,
67
+ }),
68
+ });
69
+ registerBrowserTool(server, options, {
70
+ contract: screenshotDiffContract,
71
+ schema: compareWebScreenshotsInputSchema,
72
+ execute: (parsed, _context) => compareWebScreenshotEvidence(options.browser, parsed),
73
+ });
74
+ };
75
+ const registerBrowserTool = (server, options, spec) => {
76
+ server.registerTool(spec.contract.name, toolRegistrationOptions(spec.contract), async (input, context) => {
77
+ const parsedInput = safeParseToolInput(spec.schema, input, spec.contract.name);
78
+ if (!parsedInput.ok)
79
+ return toCallToolResult(parsedInput, spec.contract);
80
+ const result = await logToolExecution(options.logger, spec.contract.name, () => spec.execute(parsedInput.value, {
73
81
  signal: context.mcpReq.signal,
74
82
  progress: mcpProgressReporter(context),
75
83
  }));
76
84
  if (!result.ok)
77
- return toCallToolResult(result, screenshotContract);
78
- return evidenceResult(options, screenshotContract, result.value);
79
- });
80
- server.registerTool(screenshotDiffContract.name, toolRegistrationOptions(screenshotDiffContract), async (input) => {
81
- const parsed = compareWebScreenshotsInputSchema.parse(input);
82
- const result = await logToolExecution(options.logger, screenshotDiffContract.name, () => compareWebScreenshotEvidence(options.browser, parsed));
83
- if (!result.ok)
84
- return toCallToolResult(result, screenshotDiffContract);
85
- return evidenceResult(options, screenshotDiffContract, result.value);
85
+ return toCallToolResult(result, spec.contract);
86
+ return evidenceResult(options, spec.contract, result.value);
86
87
  });
87
88
  };
88
89
  const evidenceResult = (options, contract, evidence) => {
@@ -1,31 +1,29 @@
1
+ import { readEvidenceBundle } from "../application/EvidenceBundleFiles.js";
1
2
  import { bundleComparisonInputSchema, compareBundles, } from "../domain/bundleComparison.js";
2
3
  import { createEvidence } from "../domain/evidence.js";
3
- import { EvidenceIntegrityError } from "../domain/errors.js";
4
4
  import { jsonValueSchema } from "../domain/jsonValue.js";
5
- import { err, ok } from "../domain/result.js";
5
+ import { ok } from "../domain/result.js";
6
6
  import { BUNDLE_COMPARISON_PROVIDER } from "./sessionToolPolicies.js";
7
7
  import { toCallToolResult } from "./toolResult.js";
8
- import { isSessionEvidence } from "./sessionEvidence.js";
9
8
  import { toolRegistrationOptions } from "./toolRegistrationOptions.js";
10
9
  import { runDerivedOperation } from "./runDerivedOperation.js";
10
+ import { safeParseToolInput } from "./toolInputValidation.js";
11
11
  /** Register canonical Evidence bundle comparison. */
12
- export const registerBundleComparisonTool = (server, session, contract) => {
12
+ export const registerBundleComparisonTool = (server, session, contract, evidenceFilePolicy) => {
13
13
  server.registerTool(contract.name, toolRegistrationOptions(contract), async (input, context) => {
14
- const parsed = bundleComparisonInputSchema.parse(input);
15
- const sourceIds = [
16
- ...new Set([
17
- ...parsed.left.records.map(({ evidence_id: id }) => id),
18
- ...parsed.right.records.map(({ evidence_id: id }) => id),
19
- ]),
20
- ].sort();
21
- if ([...parsed.left.records, ...parsed.right.records].some((evidence) => !isSessionEvidence(session, evidence)))
22
- return toCallToolResult(err(new EvidenceIntegrityError("Bundle comparison input Evidence is not present in this session")), contract);
23
- const ownedUnknownDigests = new Set(session
24
- .exportEvidenceBundle()
25
- .unknowns.map(({ revision_digest: digest }) => digest));
26
- if ([...parsed.left.unknowns, ...parsed.right.unknowns].some(({ revision_digest: digest }) => !ownedUnknownDigests.has(digest)))
27
- return toCallToolResult(err(new EvidenceIntegrityError("Bundle comparison input unknown history is not present in this session")), contract);
28
- const computed = await runDerivedOperation(context, contract.name, () => compareBundles(parsed.left, parsed.right, parsed.record_pairs, parsed.offset, parsed.limit));
14
+ const parsedInput = safeParseToolInput(bundleComparisonInputSchema, input, contract.name);
15
+ if (!parsedInput.ok)
16
+ return toCallToolResult(parsedInput, contract);
17
+ const parsed = parsedInput.value;
18
+ const [left, right] = await Promise.all([
19
+ readEvidenceBundle(parsed.left_bundle_path, evidenceFilePolicy),
20
+ readEvidenceBundle(parsed.right_bundle_path, evidenceFilePolicy),
21
+ ]);
22
+ if (!left.ok)
23
+ return toCallToolResult(left, contract);
24
+ if (!right.ok)
25
+ return toCallToolResult(right, contract);
26
+ const computed = await runDerivedOperation(context, contract.name, () => compareBundles(left.value, right.value, parsed.record_pairs, parsed.offset, parsed.limit));
29
27
  if (!computed.ok)
30
28
  return toCallToolResult(computed, contract);
31
29
  const comparison = computed.value;
@@ -43,7 +41,6 @@ export const registerBundleComparisonTool = (server, session, contract) => {
43
41
  confidence: "derived",
44
42
  authority: "analyst-inference",
45
43
  limitations: comparison.limitations,
46
- evidenceLinks: sourceIds,
47
44
  });
48
45
  const recorded = session.recordEvidence(evidence);
49
46
  return toCallToolResult(recorded.ok ? ok(evidence) : recorded, contract);
@@ -1,29 +1,56 @@
1
+ import { analyzeJavaScriptApplicationValidated } from "../application/JavaScriptApplicationService.js";
2
+ import { reconcileJavaScriptRuntimeEvidenceValidated } from "../application/JavaScriptRuntimeReconciliationService.js";
1
3
  import { inspectElectronPage, listElectronTargets, } from "../application/ElectronObservationService.js";
2
4
  import { ELECTRON_TOOL_CONTRACTS } from "../contracts/electronToolContracts.js";
3
5
  import { inspectElectronPageInputSchema, listElectronTargetsInputSchema, } from "../domain/electronObservation.js";
6
+ import { analyzeJavaScriptApplicationInputSchema } from "../domain/javascriptApplicationAnalysis.js";
7
+ import { reconcileJavaScriptRuntimeInputSchema } from "../domain/javascriptRuntimeReconciliationSchemas.js";
4
8
  import { logToolExecution } from "./toolLogging.js";
5
9
  import { toCallToolResult } from "./toolResult.js";
6
10
  import { toolRegistrationOptions } from "./toolRegistrationOptions.js";
11
+ import { safeParseToolInput } from "./toolInputValidation.js";
7
12
  import { mcpProgressReporter } from "./mcpProgress.js";
8
13
  /** Register Electron tools even when provider or permission policy is absent. */
9
14
  export const registerElectronTools = (server, options) => {
10
- const [listContract, inspectContract] = ELECTRON_TOOL_CONTRACTS;
11
- server.registerTool(listContract.name, toolRegistrationOptions(listContract), async (input, context) => {
12
- const parsed = listElectronTargetsInputSchema.parse(input);
13
- const result = await logToolExecution(options.logger, listContract.name, () => listElectronTargets(options.electron, options.permissionAuthority, parsed, { signal: context.mcpReq.signal }));
14
- if (!result.ok)
15
- return toCallToolResult(result, listContract);
16
- return evidenceResult(options, listContract, result.value);
15
+ const [listContract, inspectContract, analyzeContract, reconcileContract] = ELECTRON_TOOL_CONTRACTS;
16
+ registerElectronTool(server, options, {
17
+ contract: listContract,
18
+ schema: listElectronTargetsInputSchema,
19
+ execute: (parsed, { signal }) => listElectronTargets(options.electron, options.permissionAuthority, parsed, {
20
+ signal,
21
+ }),
22
+ });
23
+ registerElectronTool(server, options, {
24
+ contract: inspectContract,
25
+ schema: inspectElectronPageInputSchema,
26
+ execute: (parsed, { signal, progress }) => inspectElectronPage(options.electron, options.permissionAuthority, parsed, {
27
+ signal,
28
+ progress,
29
+ }),
30
+ });
31
+ registerElectronTool(server, options, {
32
+ contract: analyzeContract,
33
+ schema: analyzeJavaScriptApplicationInputSchema,
34
+ execute: (parsed, { signal, progress }) => analyzeJavaScriptApplicationValidated(options.permissionAuthority, parsed, { signal, progress }),
17
35
  });
18
- server.registerTool(inspectContract.name, toolRegistrationOptions(inspectContract), async (input, context) => {
19
- const parsed = inspectElectronPageInputSchema.parse(input);
20
- const result = await logToolExecution(options.logger, inspectContract.name, () => inspectElectronPage(options.electron, options.permissionAuthority, parsed, {
36
+ registerElectronTool(server, options, {
37
+ contract: reconcileContract,
38
+ schema: reconcileJavaScriptRuntimeInputSchema,
39
+ execute: (parsed, _context) => Promise.resolve(reconcileJavaScriptRuntimeEvidenceValidated(parsed)),
40
+ });
41
+ };
42
+ const registerElectronTool = (server, options, spec) => {
43
+ server.registerTool(spec.contract.name, toolRegistrationOptions(spec.contract), async (input, context) => {
44
+ const parsedInput = safeParseToolInput(spec.schema, input, spec.contract.name);
45
+ if (!parsedInput.ok)
46
+ return toCallToolResult(parsedInput, spec.contract);
47
+ const result = await logToolExecution(options.logger, spec.contract.name, () => spec.execute(parsedInput.value, {
21
48
  signal: context.mcpReq.signal,
22
49
  progress: mcpProgressReporter(context),
23
50
  }));
24
51
  if (!result.ok)
25
- return toCallToolResult(result, inspectContract);
26
- return evidenceResult(options, inspectContract, result.value);
52
+ return toCallToolResult(result, spec.contract);
53
+ return evidenceResult(options, spec.contract, result.value);
27
54
  });
28
55
  };
29
56
  const evidenceResult = (options, contract, evidence) => {