rea-agents 6.3.0 → 6.4.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 (487) hide show
  1. package/README.md +7 -4
  2. package/bridge/ghidra/ReaGhidraApplySeeds.java +151 -0
  3. package/bridge/ghidra/ReaGhidraBridge.java +597 -209
  4. package/bridge/ghidra/ReaGhidraNoReturnFix.java +123 -0
  5. package/dist/adb/AdbConfiguration.js +88 -0
  6. package/dist/adb/AdbDeviceOutput.js +186 -0
  7. package/dist/adb/AdbProvider.js +1190 -0
  8. package/dist/adb/AdbShellOutput.js +309 -0
  9. package/dist/android/AndroidTargetSnapshot.js +104 -22
  10. package/dist/android/JadxConfiguration.js +44 -24
  11. package/dist/android/JadxProvider.js +51 -19
  12. package/dist/apktool/ApktoolConfiguration.js +84 -0
  13. package/dist/apktool/ApktoolDecodeOutput.js +59 -0
  14. package/dist/apktool/ApktoolProvider.js +506 -0
  15. package/dist/application/AnalysisProvider.js +8 -2
  16. package/dist/application/AppBundleExecutable.js +27 -22
  17. package/dist/application/BinaryTargetResolver.js +22 -2
  18. package/dist/application/CapabilityInventory.js +11 -1
  19. package/dist/application/ClientConfigurationDocument.js +70 -0
  20. package/dist/application/ClientConfigurationFiles.js +91 -0
  21. package/dist/application/ClientRegistrationEnvironment.js +35 -0
  22. package/dist/application/ClientRegistrationStatus.js +66 -31
  23. package/dist/application/DirectAnalysis.js +2 -2
  24. package/dist/application/DirectAnalysisCleanup.js +1 -1
  25. package/dist/application/DirectAnalysisStatus.js +1 -1
  26. package/dist/application/Doctor.js +5 -3
  27. package/dist/application/DoctorDiagnostics.js +1 -1
  28. package/dist/application/EvidenceBundleCommands.js +6 -12
  29. package/dist/application/GeminiClientSettings.js +139 -0
  30. package/dist/application/HermesClientHome.js +115 -0
  31. package/dist/application/HopperDownload.js +39 -0
  32. package/dist/application/InvestigationProviders.js +6 -0
  33. package/dist/application/JsonFiles.js +6 -5
  34. package/dist/{cliJsonFile.js → application/JsonInputFile.js} +108 -35
  35. package/dist/application/LinuxHopper.js +4 -12
  36. package/dist/application/MacHopper.js +172 -149
  37. package/dist/application/MipsElfAbiFlags.js +140 -0
  38. package/dist/application/ProviderOperationExecution.js +31 -0
  39. package/dist/application/ReconstructionObligationCandidates.js +9 -3
  40. package/dist/application/ReferenceSourceImport.js +76 -29
  41. package/dist/application/ReferenceSourceImportEntries.js +18 -9
  42. package/dist/application/ReferenceSourceImportPolicy.js +99 -23
  43. package/dist/application/ReferenceSourceImportTypes.js +30 -22
  44. package/dist/application/ReferenceSourceVcsAdapter.js +145 -30
  45. package/dist/application/RegularFileRead.js +93 -7
  46. package/dist/application/Setup.js +54 -6
  47. package/dist/application/SetupClientConfiguration.js +116 -16
  48. package/dist/application/SetupHost.js +102 -24
  49. package/dist/application/SetupPlan.js +5 -8
  50. package/dist/application/SetupSkill.js +58 -39
  51. package/dist/application/SupportedClients.js +290 -65
  52. package/dist/application/Uninstall.js +158 -10
  53. package/dist/application/UpdateMaintenance.js +17 -21
  54. package/dist/application/Utf8JsonInput.js +7 -0
  55. package/dist/application/WebScriptExportService.js +131 -65
  56. package/dist/application/WebSourceLocationService.js +3 -0
  57. package/dist/application/adb/AdbDeviceAnalysisPort.js +1 -0
  58. package/dist/application/adb/AdbDeviceAnalysisService.js +13 -0
  59. package/dist/application/analysisView/AnalysisViewService.js +40 -2
  60. package/dist/application/apktool/ApktoolResourceAnalysisPort.js +1 -0
  61. package/dist/application/apktool/ApktoolResourceAnalysisService.js +13 -0
  62. package/dist/application/binary/AnalysisClientCleanup.js +0 -24
  63. package/dist/application/binary/BinarySession.js +2 -1
  64. package/dist/application/binaryDiagnostics/BinaryLayoutService.js +2 -1
  65. package/dist/application/binaryDiagnostics/PeResourcesPort.js +1 -0
  66. package/dist/application/binaryDiagnostics/PeResourcesService.js +111 -0
  67. package/dist/application/binaryDiagnostics/RecordedCrashService.js +2 -1
  68. package/dist/application/evm/EvmInterfaceService.js +3 -0
  69. package/dist/application/firmware/FirmwareAnalysisService.js +3 -0
  70. package/dist/application/investigation/InspectEvidenceBundle.js +18 -0
  71. package/dist/application/javascript/ElectronBoundaryGraphContext.js +3 -2
  72. package/dist/application/javascript/ElectronBoundaryGraphIpc.js +2 -2
  73. package/dist/application/javascript/ElectronBoundaryGraphNative.js +19 -6
  74. package/dist/application/javascript/ElectronBoundaryGraphWindows.js +3 -3
  75. package/dist/application/javascript/JavaScriptApplicationService.js +22 -11
  76. package/dist/application/javascript/JavaScriptApplicationWorkflowEvidence.js +5 -6
  77. package/dist/application/javascript/JavaScriptArtifactAnalysis.js +171 -30
  78. package/dist/application/javascript/JavaScriptArtifactGraphAccumulator.js +14 -16
  79. package/dist/application/javascript/JavaScriptArtifactGraphBuilder.js +67 -19
  80. package/dist/application/javascript/JavaScriptArtifactGraphBundlers.js +4 -3
  81. package/dist/application/javascript/JavaScriptArtifactGraphContext.js +11 -5
  82. package/dist/application/javascript/JavaScriptArtifactGraphFindings.js +19 -16
  83. package/dist/application/javascript/JavaScriptArtifactGraphStructure.js +92 -10
  84. package/dist/application/javascript/JavaScriptArtifactPathResolution.js +258 -235
  85. package/dist/application/javascript/JavaScriptArtifactReconstruction.js +115 -26
  86. package/dist/application/javascript/JavaScriptArtifactReconstructionInput.js +4 -1
  87. package/dist/application/javascript/JavaScriptModuleRelationships.js +6 -4
  88. package/dist/application/javascript/JavaScriptRecoveryService.js +3 -0
  89. package/dist/application/javascript/JavaScriptSemanticGraphAsyncProjection.js +9 -3
  90. package/dist/application/javascript/JavaScriptSemanticGraphBuilder.js +199 -61
  91. package/dist/application/javascript/JavaScriptSemanticGraphConstruction.js +12 -19
  92. package/dist/application/javascript/JavaScriptSemanticGraphDataProjection.js +4 -1
  93. package/dist/application/javascript/JavaScriptSemanticGraphFlowProjection.js +5 -3
  94. package/dist/application/javascript/JavaScriptSemanticGraphObjectProjection.js +5 -3
  95. package/dist/application/javascript/JavaScriptSemanticGraphValueProjection.js +19 -8
  96. package/dist/application/jeb/JebAnalysisPort.js +1 -0
  97. package/dist/application/jeb/JebAnalysisService.js +13 -0
  98. package/dist/application/managed/ManagedApplicationGraphService.js +1 -1
  99. package/dist/application/native/NativeUiActionTrace.js +16 -8
  100. package/dist/application/native/NativeValueTrace.js +23 -6
  101. package/dist/application/process/ProcessCli.js +25 -20
  102. package/dist/artifacts/ArtifactPaths.js +129 -8
  103. package/dist/artifacts/ArtifactProvider.js +20 -15
  104. package/dist/artifacts/ArtifactReader.js +23 -0
  105. package/dist/artifacts/ArtifactResourceScope.js +100 -0
  106. package/dist/artifacts/AsarArtifactReader.js +176 -102
  107. package/dist/artifacts/AsarHeader.js +24 -0
  108. package/dist/artifacts/DirectoryArtifactReader.js +168 -65
  109. package/dist/artifacts/MachOSliceArtifactReader.js +116 -39
  110. package/dist/artifacts/NativeDmgArtifactReader.js +29 -22
  111. package/dist/artifacts/SafeOutputTree.js +245 -70
  112. package/dist/artifacts/SafeOutputTreeCleanup.js +45 -0
  113. package/dist/artifacts/SafeOutputTreeCreationFailure.js +20 -0
  114. package/dist/artifacts/SafeOutputTreeIdentity.js +42 -0
  115. package/dist/artifacts/SafeOutputTreeReadback.js +33 -0
  116. package/dist/artifacts/ZipArtifactReader.js +77 -27
  117. package/dist/artifacts/apple/InterfaceBuilderAnalysis.js +58 -18
  118. package/dist/artifacts/apple/InterfaceBuilderDecodeBudget.js +62 -24
  119. package/dist/artifacts/apple/KeyedArchiveReader.js +32 -13
  120. package/dist/artifacts/extraction/ArtifactExtraction.js +110 -86
  121. package/dist/artifacts/inventory/ArtifactGraphConstruction.js +110 -43
  122. package/dist/artifacts/inventory/ArtifactInventory.js +5 -4
  123. package/dist/artifacts/inventory/classify.js +75 -32
  124. package/dist/artifacts/inventory/hashStableRootArtifact.js +48 -15
  125. package/dist/artifacts/inventory/reader.js +13 -5
  126. package/dist/artifacts/inventory/scanCanonical.js +62 -25
  127. package/dist/artifacts/inventory/scanReader.js +38 -11
  128. package/dist/artifacts/javascript/JavaScriptArtifactFiles.js +15 -9
  129. package/dist/artifacts/javascript/JavaScriptSourceAnalysis.js +3 -0
  130. package/dist/browser/BrowserScenarioPartialObservation.js +8 -2
  131. package/dist/browser/BrowserScenarioSecrets.js +52 -37
  132. package/dist/browser/CdpBrowserProvider.js +5 -0
  133. package/dist/browser/CdpCaptureDocuments.js +40 -6
  134. package/dist/browser/CdpCaptureDomSvg.js +210 -0
  135. package/dist/browser/CdpCaptureEventBodyShapes.js +4 -8
  136. package/dist/browser/CdpCaptureEventHandlers.js +26 -9
  137. package/dist/browser/CdpCaptureEvents.js +4 -9
  138. package/dist/browser/CdpConnection.js +22 -5
  139. package/dist/browser/CdpPageCapture.js +1 -1
  140. package/dist/browser/CdpTargetSession.js +30 -34
  141. package/dist/browser/CdpWebMcpDiscovery.js +32 -10
  142. package/dist/browser/ElectronFileScope.js +99 -9
  143. package/dist/browser/PlaywrightBrowserScenarioProvider.js +60 -4
  144. package/dist/browser/PlaywrightElectronActiveProvider.js +11 -6
  145. package/dist/browser/PlaywrightScenarioArtifacts.js +5 -5
  146. package/dist/browser/PlaywrightScenarioBrowser.js +69 -7
  147. package/dist/browser/PlaywrightScenarioSession.js +127 -54
  148. package/dist/browser/PlaywrightScenarioStorage.js +507 -0
  149. package/dist/browser/PngVisualDiff.js +198 -29
  150. package/dist/browser/WebSourceMapFetcher.js +3 -3
  151. package/dist/browser/assets/LocalWebScriptArtifacts.js +3 -1
  152. package/dist/browser/assets/PublishWebScripts.js +75 -20
  153. package/dist/browser/assets/WebArtifactReads.js +23 -1
  154. package/dist/browser/assets/WebSourceLocationArtifacts.js +1 -0
  155. package/dist/browser/execution/CdpExecutionCapture.js +3 -3
  156. package/dist/browser/execution/CdpPreciseCoverage.js +5 -8
  157. package/dist/browser/history/HarCapture.js +14 -0
  158. package/dist/browser/history/HarCaptureProcess.js +2 -10
  159. package/dist/browser/history/MitmproxyCaptureAdapter.js +3 -1
  160. package/dist/browser/modules/WebModuleArtifacts.js +1 -0
  161. package/dist/cli/adbCommands.js +337 -0
  162. package/dist/cli/analysisViewCommands.js +39 -1
  163. package/dist/cli/apktoolCommands.js +53 -0
  164. package/dist/cli/artifactCommands.js +8 -11
  165. package/dist/cli/binaryDiagnosticsCommands.js +19 -1
  166. package/dist/cli/browserAdvancedCommands.js +65 -36
  167. package/dist/cli/coreBinaryCommands.js +0 -5
  168. package/dist/cli/coreNativeCommands.js +1 -14
  169. package/dist/cli/electronCommands.js +6 -1
  170. package/dist/cli/evmCommands.js +13 -4
  171. package/dist/cli/firmwareCommands.js +7 -2
  172. package/dist/cli/javascriptApplicationAnalysis.js +17 -1
  173. package/dist/cli/javascriptRecoveryCommands.js +22 -15
  174. package/dist/cli/jebCommands.js +99 -0
  175. package/dist/cli/jsonOutput.js +11 -4
  176. package/dist/cli/referenceSourceImportStatus.js +7 -0
  177. package/dist/cli/setupCommands.js +15 -3
  178. package/dist/cli/utilityCommands.js +66 -18
  179. package/dist/cli/webScriptCommands.js +20 -1
  180. package/dist/cli/webSourceLocationCommands.js +21 -9
  181. package/dist/cli.js +6 -0
  182. package/dist/cliBrowserScenarioCommands.js +2 -1
  183. package/dist/cliCommandNames.js +32 -0
  184. package/dist/cliJsonInput.js +2 -2
  185. package/dist/cliObservationOptions.js +3 -0
  186. package/dist/composition/adb.js +3 -0
  187. package/dist/composition/apktool.js +3 -0
  188. package/dist/composition/binaryDiagnostics.js +4 -0
  189. package/dist/composition/directAnalysis.js +12 -4
  190. package/dist/composition/javascriptAnalysisWorkerProcess.js +48 -0
  191. package/dist/composition/jeb.js +6 -0
  192. package/dist/config/environment.js +10 -0
  193. package/dist/config/ghidraLanguageOverride.js +9 -0
  194. package/dist/config/mcpInputSchemaProfile.js +27 -0
  195. package/dist/config/parseConfig.js +28 -1
  196. package/dist/contracts/adb/adbToolContracts.js +353 -0
  197. package/dist/contracts/advertisedInputExamples.js +48 -0
  198. package/dist/contracts/analysisDetail.js +10 -0
  199. package/dist/contracts/analysisViewToolContracts.js +17 -2
  200. package/dist/contracts/apktool/apktoolToolContracts.js +33 -0
  201. package/dist/contracts/artifactToolContracts.js +8 -5
  202. package/dist/contracts/browserToolContracts.js +1 -1
  203. package/dist/contracts/compactInputSchema.js +256 -0
  204. package/dist/contracts/functionWorkflowToolContracts.js +1 -1
  205. package/dist/contracts/inputSchemaPresentation.js +10 -10
  206. package/dist/contracts/javascript/electronToolContracts.js +15 -3
  207. package/dist/contracts/javascript/javascriptRecoveryToolContracts.js +1 -1
  208. package/dist/contracts/jeb/jebToolContracts.js +64 -0
  209. package/dist/contracts/native/binaryDiagnosticsToolContracts.js +25 -3
  210. package/dist/contracts/officialToolContracts.js +5 -5
  211. package/dist/contracts/sessionToolContracts.js +2 -2
  212. package/dist/contracts/sessionToolSchemas.js +6 -2
  213. package/dist/contracts/toolContractExamples.js +6 -0
  214. package/dist/contracts/toolContractTypes.js +3 -0
  215. package/dist/contracts/toolContracts.js +6 -0
  216. package/dist/contracts/toolEffects.js +167 -0
  217. package/dist/contracts/toolOutputSchemaGroups.js +5 -3
  218. package/dist/contracts/toolSchemaMetadata.js +82 -7
  219. package/dist/domain/adb/adbDeviceAnalysis.js +583 -0
  220. package/dist/domain/analysisErrorCleanup.js +29 -0
  221. package/dist/domain/analysisErrorPresentation.js +18 -6
  222. package/dist/domain/analysisErrorProjection.js +4 -1
  223. package/dist/domain/analysisSnapshot.js +2 -1
  224. package/dist/domain/analysisView/analysisView.js +52 -2
  225. package/dist/domain/analysisView/binaryLayoutView.js +2 -0
  226. package/dist/domain/analysisView/javascriptApplicationView.js +2 -0
  227. package/dist/domain/analysisView/nativeFunctionView.js +155 -0
  228. package/dist/domain/android/androidApplication.js +25 -20
  229. package/dist/domain/apktool/apktoolResourceAnalysis.js +77 -0
  230. package/dist/domain/apple/appleApplication.js +40 -23
  231. package/dist/domain/apple/appleBundleAnatomy.js +95 -28
  232. package/dist/domain/apple/dyldPaths.js +9 -1
  233. package/dist/domain/apple/dylibResolution.js +2 -2
  234. package/dist/domain/apple/interfaceBuilderGraph.js +22 -19
  235. package/dist/domain/apple/interfaceBuilderKeyedArchive.js +10 -1
  236. package/dist/domain/artifactComparison.js +35 -7
  237. package/dist/domain/artifactGraph.js +5 -3
  238. package/dist/domain/artifactIdentity.js +30 -2
  239. package/dist/domain/artifactInspection.js +3 -43
  240. package/dist/domain/artifactIntegrityPolicy.js +10 -0
  241. package/dist/domain/artifactInventoryEvidence.js +11 -12
  242. package/dist/domain/artifactPathSyntax.js +1 -1
  243. package/dist/domain/binaryTarget.js +16 -0
  244. package/dist/domain/binaryTargetTypes.js +8 -1
  245. package/dist/domain/browserObservationSchemas.js +8 -4
  246. package/dist/domain/canonicalJsonDigestSteps.js +34 -12
  247. package/dist/domain/compactStringIdentity.js +9 -0
  248. package/dist/domain/evidence.js +2 -1
  249. package/dist/domain/evidenceRecordSummary.js +144 -0
  250. package/dist/domain/inputIssueProjection.js +16 -1
  251. package/dist/domain/javascript/electronStaticAnalysisBrowser.js +12 -13
  252. package/dist/domain/javascript/electronStaticAnalysisIpc.js +11 -20
  253. package/dist/domain/javascript/electronStaticAnalysisNative.js +70 -40
  254. package/dist/domain/javascript/electronStaticAnalysisValues.js +16 -0
  255. package/dist/domain/javascript/javascriptAnalysisResourceControls.js +45 -0
  256. package/dist/domain/javascript/javascriptApplicationAnalysis.js +4 -1
  257. package/dist/domain/javascript/javascriptApplicationChangeGraph.js +6 -6
  258. package/dist/domain/javascript/javascriptApplicationGraph.js +79 -18
  259. package/dist/domain/javascript/javascriptApplicationProjectionResources.js +35 -0
  260. package/dist/domain/javascript/javascriptApplicationVersionItems.js +28 -12
  261. package/dist/domain/javascript/javascriptApplicationVersionKeys.js +9 -1
  262. package/dist/domain/javascript/javascriptAstFingerprint.js +58 -31
  263. package/dist/domain/javascript/javascriptAstValues.js +32 -0
  264. package/dist/domain/javascript/javascriptElectronMemberWrites.js +50 -0
  265. package/dist/domain/javascript/javascriptModuleSemanticIr.js +15 -0
  266. package/dist/domain/javascript/javascriptNativeHandoff.js +6 -1
  267. package/dist/domain/javascript/javascriptRpcEndpoints.js +253 -0
  268. package/dist/domain/javascript/javascriptRuntimeLoadState.js +1 -3
  269. package/dist/domain/javascript/javascriptRuntimeReconciliationGraph.js +7 -2
  270. package/dist/domain/javascript/javascriptRuntimeStaticCandidates.js +8 -11
  271. package/dist/domain/javascript/javascriptSemanticAnalysis.js +190 -33
  272. package/dist/domain/javascript/javascriptSemanticCallableResults.js +42 -0
  273. package/dist/domain/javascript/javascriptSemanticCalls.js +8 -1
  274. package/dist/domain/javascript/javascriptSemanticDerivedAnalysis.js +15 -4
  275. package/dist/domain/javascript/javascriptSemanticFileProjection.js +1 -0
  276. package/dist/domain/javascript/javascriptSemanticFingerprints.js +42 -41
  277. package/dist/domain/javascript/javascriptSemanticGraph.js +69 -23
  278. package/dist/domain/javascript/javascriptSemanticGraphSchemas.js +2 -10
  279. package/dist/domain/javascript/javascriptSemanticIterationSources.js +40 -7
  280. package/dist/domain/javascript/javascriptSemanticMemberMutations.js +341 -87
  281. package/dist/domain/javascript/javascriptSemanticMutationValues.js +78 -35
  282. package/dist/domain/javascript/javascriptSemanticObjectReferences.js +381 -0
  283. package/dist/domain/javascript/javascriptSemanticObjects.js +7 -1
  284. package/dist/domain/javascript/javascriptSemanticProjection.js +52 -14
  285. package/dist/domain/javascript/javascriptSemanticPropertyPaths.js +77 -0
  286. package/dist/domain/javascript/javascriptSemanticQuery.js +27 -29
  287. package/dist/domain/javascript/javascriptSemanticQueryIdentity.js +1 -3
  288. package/dist/domain/javascript/javascriptSemanticReturnedReferences.js +219 -0
  289. package/dist/domain/javascript/javascriptSemanticReturns.js +13 -23
  290. package/dist/domain/javascript/javascriptSemanticState.js +22 -2
  291. package/dist/domain/javascript/javascriptSemanticTraversal.js +19 -1
  292. package/dist/domain/javascript/javascriptSemanticValues.js +47 -19
  293. package/dist/domain/javascript/javascriptSourceAnalysis.js +1 -0
  294. package/dist/domain/javascript/javascriptStaticAnalysis.js +29 -17
  295. package/dist/domain/javascript/javascriptStaticAnalysisBundler.js +8 -6
  296. package/dist/domain/javascript/javascriptStaticAnalysisCalls.js +49 -5
  297. package/dist/domain/javascript/javascriptStaticAnalysisFindings.js +8 -4
  298. package/dist/domain/javascript/javascriptStaticAnalysisState.js +1 -0
  299. package/dist/domain/jeb/jebAnalysis.js +114 -0
  300. package/dist/domain/jsonShape.js +63 -52
  301. package/dist/domain/jsonValue.js +3 -0
  302. package/dist/domain/managed/managedApplicationGraph.js +37 -0
  303. package/dist/domain/managed/managedApplicationGraphCoverage.js +8 -2
  304. package/dist/domain/managed/managedApplicationGraphNodes.js +32 -22
  305. package/dist/domain/managed/managedArtifact.js +1 -0
  306. package/dist/domain/managed/managedInspectionEvidence.js +13 -0
  307. package/dist/domain/native/nativeAotPe.js +1408 -0
  308. package/dist/domain/native/nativeInstruction.js +21 -0
  309. package/dist/domain/native/nativeMetadataRecovery.js +79 -6
  310. package/dist/domain/native/peResources.js +94 -0
  311. package/dist/domain/nativeConvention.js +33 -0
  312. package/dist/domain/process/processCapture.js +91 -1
  313. package/dist/domain/process/processCaptureExample.js +24 -0
  314. package/dist/domain/process/processCaptureValidation.js +79 -0
  315. package/dist/domain/process/processScenario.js +59 -7
  316. package/dist/domain/propertyListKeys.js +3 -1
  317. package/dist/domain/referenceSourceGraph.js +25 -16
  318. package/dist/domain/referenceSourceImportParsing.js +6 -3
  319. package/dist/domain/referenceSourcePathIdentity.js +22 -0
  320. package/dist/domain/referenceSourceRequireBindings.js +137 -0
  321. package/dist/domain/webBundleAnalyzerInspection.js +14 -2
  322. package/dist/domain/webCaptureDiff.js +102 -4
  323. package/dist/domain/webScriptExportError.js +10 -4
  324. package/dist/domain/webScriptExportPlan.js +7 -13
  325. package/dist/domain/zipPackageFormat.js +4 -1
  326. package/dist/domain/zodCollectionSteps.js +24 -0
  327. package/dist/dotnet/ManagedArtifactInspector.js +55 -43
  328. package/dist/dotnet/ManagedDecodeBudget.js +80 -0
  329. package/dist/dotnet/ManagedMemberInspector.js +13 -6
  330. package/dist/dotnet/ManagedMemberInspectorCore.js +2 -2
  331. package/dist/dotnet/ManagedMemberInstructionDecoder.js +4 -2
  332. package/dist/dotnet/ManagedMemberRows.js +9 -4
  333. package/dist/dotnet/ManagedMetadataHeaps.js +15 -5
  334. package/dist/dotnet/ManagedMetadataInventoryRows.js +20 -11
  335. package/dist/dotnet/ManagedMetadataLayout.js +10 -4
  336. package/dist/dotnet/ManagedMethodBodyReader.js +8 -3
  337. package/dist/dotnet/ManagedNativeBoundaryHelpers.js +3 -2
  338. package/dist/dotnet/ManagedNativeBoundaryInspector.js +49 -34
  339. package/dist/dotnet/ManagedPeReader.js +41 -25
  340. package/dist/dotnet/ManagedReaderFailure.js +2 -1
  341. package/dist/dotnet/ManagedStaticProvider.js +55 -24
  342. package/dist/evaluation/AgentEvaluationReport.js +9 -5
  343. package/dist/evaluation/CodexAgentEval.js +43 -13
  344. package/dist/evm/EvmoleFailures.js +0 -2
  345. package/dist/evm/EvmoleInterfaceProvider.js +67 -2
  346. package/dist/filesystem/OwnedDirectoryHandle.js +29 -0
  347. package/dist/filesystem/OwnedFileHandle.js +36 -0
  348. package/dist/filesystem/RegularFile.js +33 -1
  349. package/dist/filesystem/StableFileHash.js +46 -0
  350. package/dist/filesystem/readFileHandleChunks.js +26 -0
  351. package/dist/firmware/FirmwareCommand.js +25 -3
  352. package/dist/firmware/FirmwareFiles.js +23 -8
  353. package/dist/firmware/FirmwareProvider.js +156 -32
  354. package/dist/firmware/FirmwarePublication.js +24 -3
  355. package/dist/firmware/FirmwareRelease.js +1 -0
  356. package/dist/generatedPackageMetadata.js +2 -2
  357. package/dist/ghidra/GhidraAnalysisProfile.js +55 -4
  358. package/dist/ghidra/GhidraAnalysisSeeds.js +211 -0
  359. package/dist/ghidra/GhidraClient.js +76 -4
  360. package/dist/ghidra/GhidraDiagnostics.js +11 -8
  361. package/dist/ghidra/GhidraFunctionValues.js +26 -2
  362. package/dist/ghidra/GhidraInstallation.js +1 -1
  363. package/dist/ghidra/GhidraInventoryValues.js +23 -1
  364. package/dist/ghidra/GhidraLanguageCatalog.js +99 -0
  365. package/dist/ghidra/GhidraLauncher.js +80 -39
  366. package/dist/ghidra/GhidraLoadImageAttest.js +49 -2
  367. package/dist/ghidra/GhidraMipsProfile.js +79 -0
  368. package/dist/ghidra/GhidraProvider.js +57 -9
  369. package/dist/ghidra/GhidraProviderCapabilities.js +18 -8
  370. package/dist/ghidra/GhidraProviderClient.js +282 -21
  371. package/dist/ghidra/GhidraSessionValues.js +9 -2
  372. package/dist/hopper/HopperAnalysisProfile.js +2 -0
  373. package/dist/hopper/HopperClient.js +15 -6
  374. package/dist/hopper/HopperMachOImage.js +2 -0
  375. package/dist/hopper/HopperProvider.js +13 -2
  376. package/dist/ida/IdaOperationRunner.js +8 -2
  377. package/dist/ida/IdaProvider.js +7 -0
  378. package/dist/ida/IdaSessionClient.js +3 -1
  379. package/dist/ida/IdaWorkspace.js +4 -2
  380. package/dist/javascript/analysis/JavaScriptAnalysisTransfer.js +326 -0
  381. package/dist/javascript/analysis/JavaScriptAnalysisWorker.js +520 -0
  382. package/dist/javascript/analysis/JavaScriptAnalysisWorkerProtocol.js +63 -0
  383. package/dist/javascript/analysis/JavaScriptAnalysisWorkerSchemas.js +521 -0
  384. package/dist/javascript/analysis/JavaScriptAnalysisWorkerServer.js +116 -0
  385. package/dist/javascript/recovery/RecoveryFiles.js +18 -7
  386. package/dist/javascript/recovery/WakaruCommand.js +22 -9
  387. package/dist/javascript/recovery/WakaruExecution.js +11 -7
  388. package/dist/javascript/recovery/WakaruProvider.js +139 -16
  389. package/dist/javascript/recovery/WakaruPublication.js +14 -4
  390. package/dist/javascript/recovery/WakaruRelease.js +10 -3
  391. package/dist/javascript/recovery/WakaruReport.js +12 -7
  392. package/dist/javascript/recovery/WakaruVersion.js +24 -0
  393. package/dist/javascript/sourceMaps/SourceMapCommand.js +16 -3
  394. package/dist/javascript/sourceMaps/SourceMapDecoder.js +63 -7
  395. package/dist/javascript/sourceMaps/SourceMapFormat.js +15 -4
  396. package/dist/jeb/JebMcpConnection.js +179 -0
  397. package/dist/jeb/JebMcpEndpoint.js +40 -0
  398. package/dist/jeb/JebProvider.js +299 -0
  399. package/dist/mcpDoctor.js +15 -6
  400. package/dist/native/AppleDispatchCoverage.js +25 -12
  401. package/dist/native/AppleDispatchMetadata.js +14 -7
  402. package/dist/native/AppleMachoFixups.js +71 -15
  403. package/dist/native/AppleMachoSelection.js +23 -3
  404. package/dist/native/NativeMacOSProvider.js +91 -16
  405. package/dist/native/NativeMachoInspection.js +11 -7
  406. package/dist/native/NativeUiHelperRuntime.js +6 -1
  407. package/dist/native/NativeUiObservation.js +4 -3
  408. package/dist/native/pe/PeResourceLayout.js +120 -0
  409. package/dist/native/pe/PeResourceParser.js +286 -0
  410. package/dist/native/pe/PeResourcesProvider.js +63 -0
  411. package/dist/process/BoundedFileBytes.js +30 -7
  412. package/dist/process/DarwinProcessRunTokenReader.js +8 -3
  413. package/dist/process/OwnedCommand.js +4 -3
  414. package/dist/process/ProcessOwnership.js +104 -112
  415. package/dist/process/ProcessOwnershipObservation.js +96 -39
  416. package/dist/process/ProcessOwnershipProcessTree.js +4 -4
  417. package/dist/process/ProcessRunTokenObservations.js +48 -0
  418. package/dist/process/ProviderDiagnosticRedaction.js +17 -0
  419. package/dist/process/ProviderProcess.js +4 -3
  420. package/dist/process/capture/FilesystemSnapshot.js +28 -4
  421. package/dist/process/capture/ProcessCaptureLifecycle.js +350 -59
  422. package/dist/process/capture/ProcessCaptureProgress.js +62 -0
  423. package/dist/process/capture/ProcessHarness.js +194 -26
  424. package/dist/process/capture/ProcessNormalization.js +3 -1
  425. package/dist/process/capture/ProcessScenarioRuntimeValidation.js +5 -2
  426. package/dist/process/capture/TerminalRenderer.js +24 -7
  427. package/dist/reference/ReferenceSourceReader.js +22 -5
  428. package/dist/reference/ReferenceSourceReaderEntries.js +114 -51
  429. package/dist/reference/ReferenceSourceReaderErrors.js +12 -0
  430. package/dist/reference/ReferenceSourceReaderFile.js +50 -10
  431. package/dist/reference/ReferenceSourceReaderValidate.js +4 -4
  432. package/dist/server/EvidenceMcpServer.js +36 -1
  433. package/dist/server/admittedToolOperation.js +9 -0
  434. package/dist/server/contractToolHandler.js +21 -0
  435. package/dist/server/createServer.js +97 -25
  436. package/dist/server/registerAdbTools.js +36 -0
  437. package/dist/server/registerAnalysisViewTool.js +4 -9
  438. package/dist/server/registerAndroidTools.js +3 -12
  439. package/dist/server/registerApktoolTools.js +14 -0
  440. package/dist/server/registerApplicationTools/compareExportShapes.js +4 -6
  441. package/dist/server/registerApplicationTools/compareSourceToBundle.js +4 -5
  442. package/dist/server/registerApplicationTools/compareVersions.js +3 -2
  443. package/dist/server/registerApplicationTools/coverage.js +3 -2
  444. package/dist/server/registerApplicationTools/obligationLedger.js +3 -2
  445. package/dist/server/registerApplicationTools/projectMobileApplicationGraph.js +3 -2
  446. package/dist/server/registerApplicationTools/traceFeature.js +3 -2
  447. package/dist/server/registerApplicationTools/traceSemantics.js +4 -5
  448. package/dist/server/registerArtifactComparisonTool.js +5 -2
  449. package/dist/server/registerBinaryDiagnosticsTools.js +16 -4
  450. package/dist/server/registerBrowserScenarioTool.js +10 -7
  451. package/dist/server/registerBrowserTools.js +12 -9
  452. package/dist/server/registerBundleComparisonTool.js +16 -2
  453. package/dist/server/registerCloseLifecycleTool.js +32 -3
  454. package/dist/server/registerElectronTools.js +28 -10
  455. package/dist/server/registerEvmTools.js +4 -9
  456. package/dist/server/registerFirmwareTools.js +3 -11
  457. package/dist/server/registerFunctionComparisonTool.js +5 -2
  458. package/dist/server/registerJavaScriptRecoveryTool.js +4 -9
  459. package/dist/server/registerJavaScriptRuntimeObservationTools.js +9 -6
  460. package/dist/server/registerJebTools.js +16 -0
  461. package/dist/server/registerManagedWorkflowTools/compareManagedMembers.js +4 -6
  462. package/dist/server/registerManagedWorkflowTools/importManagedReconstruction.js +3 -2
  463. package/dist/server/registerManagedWorkflowTools/projectManagedApplicationGraph.js +3 -2
  464. package/dist/server/registerManagedWorkflowTools/verifyManagedNativeBoundaries.js +3 -2
  465. package/dist/server/registerPeResourcesTool.js +9 -0
  466. package/dist/server/registerProcessComparisonTool.js +5 -2
  467. package/dist/server/registerRecordedCrashTools.js +4 -9
  468. package/dist/server/registerSessionRecordTools.js +2 -1
  469. package/dist/server/registerSessionTools.js +49 -18
  470. package/dist/server/registerWebModuleTool.js +4 -9
  471. package/dist/server/registerWebNetworkCaptureTool.js +4 -9
  472. package/dist/server/registerWebRuntimeTools.js +6 -5
  473. package/dist/server/registerWebScriptTool.js +6 -3
  474. package/dist/server/registerWebSourceLocationTool.js +4 -9
  475. package/dist/server/toolResult.js +21 -2
  476. package/dist/windows/WindowsPrivateRuntime.js +12 -5
  477. package/install.sh +7 -4
  478. package/licenses/nativeaot-parser-MIT.txt +28 -0
  479. package/native/windows/build/manifest.json +2 -2
  480. package/native/windows/build/rea-windows-x64.node +0 -0
  481. package/package.json +33 -5
  482. package/scripts/rea.mjs +16 -1
  483. package/skills/reverse-engineer-anything/SKILL.md +52 -51
  484. package/skills/reverse-engineer-anything/references/connection-and-recovery.md +127 -0
  485. package/skills/reverse-engineer-anything/references/evidence-workflows.md +8 -0
  486. package/skills/reverse-engineer-anything/references/javascript-applications.md +92 -13
  487. package/skills/reverse-engineer-anything/references/native-and-artifacts.md +22 -1
@@ -117,8 +117,8 @@ export class ProviderProcessSupervisor {
117
117
  snapshot() {
118
118
  return {
119
119
  ...(this.#diagnosticTruncated ? { diagnosticTruncated: true } : {}),
120
- stdout: this.#stdout.snapshot(),
121
- stderr: this.#stderr.snapshot(),
120
+ stdout: this.#stdout.snapshot(this.#stdoutObservedBytes),
121
+ stderr: this.#stderr.snapshot(this.#stderrObservedBytes),
122
122
  exitCode: this.#exitObservation?.code,
123
123
  signal: this.#exitObservation?.signal,
124
124
  };
@@ -301,11 +301,12 @@ class ProcessOutputCapture {
301
301
  this.#bytes += chunk.byteLength;
302
302
  this.#chunks.push(Buffer.from(chunk));
303
303
  }
304
- snapshot() {
304
+ snapshot(observedBytes) {
305
305
  const text = Buffer.concat(this.#chunks, this.#bytes).toString("utf8");
306
306
  return {
307
307
  text,
308
308
  bytes: this.#bytes,
309
+ observedBytes,
309
310
  };
310
311
  }
311
312
  }
@@ -1,6 +1,6 @@
1
1
  import { createHash } from "node:crypto";
2
2
  import { constants as fsConstants } from "node:fs";
3
- import { lstat, open, readdir, readlink } from "node:fs/promises";
3
+ import { lstat, open, opendir, readlink } from "node:fs/promises";
4
4
  import { dirname, join, relative, resolve } from "node:path";
5
5
  const hasSameIdentity = (before, after, expected) => before.dev === after.dev &&
6
6
  before.ino === after.ino &&
@@ -115,6 +115,7 @@ export const snapshotRoots = async (scenario, signal) => {
115
115
  const entries = [];
116
116
  const completeRoots = [];
117
117
  let remainingBytes = scenario.limits.file_bytes;
118
+ let pendingNames = 0;
118
119
  let truncated = false;
119
120
  const enumerationReasons = new Set();
120
121
  const hashOmissions = [];
@@ -204,15 +205,38 @@ export const snapshotRoots = async (scenario, signal) => {
204
205
  });
205
206
  if (type !== "directory")
206
207
  return true;
207
- const children = await readdir(path);
208
+ const children = [];
209
+ let complete = true;
210
+ const remainingEntries = scenario.limits.files - entries.length - pendingNames;
211
+ const directory = await opendir(path);
212
+ for await (const child of directory) {
213
+ signal?.throwIfAborted();
214
+ if (children.length >= remainingEntries ||
215
+ depth >= scenario.limits.filesystem_depth) {
216
+ truncated = true;
217
+ complete = false;
218
+ if (children.length >= remainingEntries)
219
+ enumerationReasons.add("files_limit");
220
+ if (depth >= scenario.limits.filesystem_depth)
221
+ enumerationReasons.add("depth_limit");
222
+ break;
223
+ }
224
+ children.push(child.name);
225
+ pendingNames += 1;
226
+ }
208
227
  const afterRead = await lstat(path);
209
228
  if (!hasSameIdentity(stats, afterRead, "directory")) {
229
+ pendingNames -= children.length;
210
230
  truncated = true;
211
231
  enumerationReasons.add("identity_changed");
212
232
  return false;
213
233
  }
214
- let complete = true;
215
- for (const child of children.sort()) {
234
+ children.sort().reverse();
235
+ while (children.length > 0) {
236
+ const child = children.pop();
237
+ if (child === undefined)
238
+ break;
239
+ pendingNames -= 1;
216
240
  if (!(await visit(root, rootAlias, join(path, child), depth + 1)))
217
241
  complete = false;
218
242
  }
@@ -10,7 +10,7 @@ import { PRODUCT_IDENTITY } from "../../identity.js";
10
10
  import { snapshotRoots } from "./FilesystemSnapshot.js";
11
11
  import { classifyFilesystemEffects } from "./ProcessFilesystemEffects.js";
12
12
  import { cleanupOwnedProcessGroup, verifyNoTokenOwnedProcesses, } from "../ProcessOwnership.js";
13
- import { observeOwnedProcessGroup, prepareProcessOwnershipInspection, systemProcessOwnershipHost, } from "../ProcessOwnershipObservation.js";
13
+ import { observeOwnedProcessGroups, prepareProcessOwnershipInspection, systemProcessOwnershipHost, } from "../ProcessOwnershipObservation.js";
14
14
  import { describeProcessCaptureExecutionFailure, normalizeCaptureFailure, ProcessCaptureError, } from "./ProcessCaptureError.js";
15
15
  import { assertNotCancelled } from "./ProcessScenarioRuntimeValidation.js";
16
16
  import { normalizeProcessElapsedTime, normalizeProcessSamples, normalizeProcessText, } from "./ProcessNormalization.js";
@@ -35,6 +35,14 @@ export const createProcessCaptureObservationBuffer = (options) => ({
35
35
  state: "unavailable",
36
36
  reason: "Terminal exit was not observed before the run failed.",
37
37
  },
38
+ ...(options.finalizationEnabled === true
39
+ ? {
40
+ finalization: {
41
+ state: "unavailable",
42
+ reason: "Finalization was not observed before capture completion finished.",
43
+ },
44
+ }
45
+ : {}),
38
46
  settlement: {
39
47
  state: "unavailable",
40
48
  reason: "Process settlement was not observed before capture completion finished.",
@@ -109,6 +117,9 @@ export const buildCaptureResult = (options) => {
109
117
  : null,
110
118
  signal: options.exit.signal ?? null,
111
119
  reason: options.exit.reason,
120
+ ...(options.exit.finalization === undefined
121
+ ? {}
122
+ : { finalization: options.exit.finalization }),
112
123
  },
113
124
  settlement: options.settlement,
114
125
  process_samples: normalizeProcessSamples(options.samples, options.scenario, options.rootPid),
@@ -349,8 +360,9 @@ export const createRunManifest = async (scenario, startedAt, completedAt, execut
349
360
  normalization_sha256: digestProcessCommitment(scenario.normalization),
350
361
  };
351
362
  };
352
- export const observeSettlement = async (runId, processGroupIds, settleMs, recordEvent = () => undefined, platform = process.platform, signal) => {
363
+ export const observeSettlement = async (runId, processGroupIds, settleMs, recordEvent = () => undefined, platform = process.platform, signal, onLiveProgress) => {
353
364
  assertNotCancelled(signal);
365
+ onLiveProgress?.();
354
366
  if (platform === "win32") {
355
367
  recordEvent("lifecycle", 1);
356
368
  return { state: "unverifiable", elapsed_ms: 0 };
@@ -359,14 +371,15 @@ export const observeSettlement = async (runId, processGroupIds, settleMs, record
359
371
  let consecutiveEmpty = 0;
360
372
  let deadlineReached = false;
361
373
  while (!deadlineReached) {
374
+ onLiveProgress?.();
362
375
  assertNotCancelled(signal);
363
- const observations = await Promise.all([...new Set(processGroupIds)].map((processGroupId) => observeOwnedProcessGroup({ runId, leaderPid: processGroupId, processGroupId }, undefined, signal)));
376
+ const observations = await observeOwnedProcessGroups(runId, processGroupIds, undefined, signal);
364
377
  assertNotCancelled(signal);
365
- if (observations.some(({ state }) => state === "unverifiable")) {
378
+ if ([...observations.values()].some(({ state }) => state === "unverifiable")) {
366
379
  recordEvent("lifecycle", 1);
367
380
  return { state: "unverifiable", elapsed_ms: Date.now() - started };
368
381
  }
369
- if (observations.every(({ state }) => state === "empty")) {
382
+ if ([...observations.values()].every(({ state }) => state === "empty")) {
370
383
  consecutiveEmpty += 1;
371
384
  if (consecutiveEmpty >= 2) {
372
385
  recordEvent("lifecycle", 1);
@@ -383,12 +396,137 @@ export const observeSettlement = async (runId, processGroupIds, settleMs, record
383
396
  recordEvent("lifecycle", 1);
384
397
  return { state: "alive_at_deadline", elapsed_ms: Date.now() - started };
385
398
  };
386
- export const awaitTerminalExit = async ({ terminal, scenario, started, lastOutput, signal, timers, interactions, dispatchedEventIndexes, recordEvent, }) => new Promise((resolveExit) => {
399
+ /** Name why an attempt is unverified; a blank message never reaches the capture schema. */
400
+ export const describeUnverifiedCause = (cause, fallback) => {
401
+ const message = cause instanceof Error ? cause.message : String(cause);
402
+ return message.trim() === "" ? fallback : message;
403
+ };
404
+ /**
405
+ * Wait for the captured terminal to exit and report how it ended.
406
+ *
407
+ * A timeout or idle deadline kills the root at once when `finalization_ms` is
408
+ * 0. With a positive interval it sends SIGTERM through `signalTarget`, keeps
409
+ * observing, and sends SIGKILL once if the interval ends first; cancellation
410
+ * during the interval sends that SIGKILL at once. Every attempt is recorded
411
+ * with its delivery result before the delivery is awaited, and each wait is
412
+ * bounded by the cleanup verification grace. If the SIGKILL cannot be
413
+ * delivered the wait ends with `unobserved: true` and no invented exit, so the
414
+ * caller can keep its observations and release the run through cleanup.
415
+ */
416
+ export const awaitTerminalExit = async ({ terminal, scenario, started, lastOutput, signal, signalTarget, recordFinalization, timers, interactions, dispatchedEventIndexes, recordEvent, onLiveProgress, }) => new Promise((resolveExit) => {
387
417
  // The kill caused by a deadline is observed later as an ordinary PTY exit.
388
418
  // Keep the initiating lifecycle reason so comparisons distinguish a target
389
419
  // exit from harness-owned timeout, idle-timeout, and cancellation cleanup.
390
420
  let reason = "exited";
421
+ onLiveProgress?.();
422
+ // A deadline with a finalization interval sends SIGTERM first and keeps
423
+ // observing; SIGKILL follows only when the interval elapses or the request
424
+ // is cancelled. Both go through the identity-checked signaller.
425
+ // The interval is measured on the monotonic clock so a wall-clock change
426
+ // cannot shorten it or produce a negative elapsed time.
427
+ let finalizationStartedAt;
428
+ let escalationSent = false;
429
+ let settled = false;
430
+ let exitObserved = false;
431
+ const finalizationSignals = [];
432
+ const pendingDeliveries = [];
433
+ const snapshot = (elapsed, exitCode = null) => ({
434
+ requested_ms: scenario.finalization_ms,
435
+ elapsed_ms: elapsed,
436
+ exit_code: exitCode,
437
+ signals: finalizationSignals.map((attempt) => ({ ...attempt })),
438
+ });
439
+ const unobservedExit = () => {
440
+ if (settled || exitObserved || finalizationStartedAt === undefined)
441
+ return;
442
+ settled = true;
443
+ for (const timer of timers)
444
+ timer.cancel();
445
+ timers.clear();
446
+ resolveExit({
447
+ unobserved: true,
448
+ reason: reason === "exited" ? "timeout" : reason,
449
+ finalization: snapshot(null),
450
+ });
451
+ };
452
+ // An attempt is recorded before its delivery is awaited, so a hung or
453
+ // failed delivery still leaves the attempt in the observations.
454
+ const attempt = (finalizationSignal) => {
455
+ if (finalizationStartedAt === undefined)
456
+ return;
457
+ const record = {
458
+ signal: finalizationSignal,
459
+ sent_at_ms: Math.round(performance.now() - finalizationStartedAt),
460
+ delivery: "unverified",
461
+ reason: "delivery had not settled when the record was published",
462
+ };
463
+ finalizationSignals.push(record);
464
+ recordFinalization(snapshot(null));
465
+ const deliveryBound = new AbortController();
466
+ // The wait is bounded by the cleanup verification grace: a delivery that
467
+ // never settles is recorded as unverified instead of holding the capture.
468
+ pendingDeliveries.push(Promise.race([
469
+ signalTarget(finalizationSignal),
470
+ delay(PROCESS_CLEANUP_VERIFICATION_GRACE_MS, {
471
+ delivery: "unverified",
472
+ reason: `delivery did not settle within ${String(PROCESS_CLEANUP_VERIFICATION_GRACE_MS)} ms`,
473
+ }, {
474
+ ref: false,
475
+ signal: deliveryBound.signal,
476
+ }).catch(() => ({
477
+ delivery: "unverified",
478
+ reason: "delivery wait was interrupted",
479
+ })),
480
+ ])
481
+ .finally(() => {
482
+ deliveryBound.abort();
483
+ })
484
+ .then(({ delivery, reason: deliveryReason }) => {
485
+ record.delivery = delivery;
486
+ if (deliveryReason !== undefined)
487
+ record.reason = deliveryReason;
488
+ else
489
+ delete record.reason;
490
+ }, (cause) => {
491
+ record.delivery = "unverified";
492
+ record.reason = describeUnverifiedCause(cause, "signal delivery failed without a message");
493
+ })
494
+ .then(() => {
495
+ recordFinalization(snapshot(null));
496
+ // A kill that cannot reach the root leaves no exit to wait for.
497
+ if (finalizationSignal === "SIGKILL" &&
498
+ record.delivery !== "signaled" &&
499
+ record.delivery !== "gone")
500
+ unobservedExit();
501
+ }));
502
+ };
503
+ const forceKill = () => {
504
+ if (finalizationStartedAt !== undefined) {
505
+ if (escalationSent)
506
+ return;
507
+ escalationSent = true;
508
+ attempt("SIGKILL");
509
+ return;
510
+ }
511
+ terminal.kill("SIGKILL");
512
+ };
513
+ const terminateAtDeadline = () => {
514
+ if (scenario.finalization_ms === 0) {
515
+ terminal.kill("SIGKILL");
516
+ return;
517
+ }
518
+ finalizationStartedAt = performance.now();
519
+ attempt("SIGTERM");
520
+ };
391
521
  terminal.onExit((exit) => {
522
+ if (settled)
523
+ return;
524
+ exitObserved = true;
525
+ // Measures when the exit was observed, not when the operating system
526
+ // ended the process; the PTY layer can deliver the notification late.
527
+ const finalizationElapsedMs = finalizationStartedAt === undefined
528
+ ? undefined
529
+ : Math.round(performance.now() - finalizationStartedAt);
392
530
  recordEvent("lifecycle", 0);
393
531
  for (const [eventIndex, event] of scenario.events.entries()) {
394
532
  if (dispatchedEventIndexes.has(eventIndex))
@@ -412,20 +550,59 @@ export const awaitTerminalExit = async ({ terminal, scenario, started, lastOutpu
412
550
  timer.cancel();
413
551
  }
414
552
  timers.clear();
415
- resolveExit({ ...exit, reason });
553
+ const finish = () => {
554
+ if (settled)
555
+ return;
556
+ settled = true;
557
+ resolveExit({
558
+ ...exit,
559
+ reason,
560
+ ...(finalizationElapsedMs === undefined
561
+ ? {}
562
+ : {
563
+ finalization: snapshot(finalizationElapsedMs, exit.exitCode >= 0 && (exit.signal ?? 0) === 0
564
+ ? exit.exitCode
565
+ : null),
566
+ }),
567
+ });
568
+ };
569
+ if (pendingDeliveries.length === 0) {
570
+ finish();
571
+ return;
572
+ }
573
+ // A delivery that never settles must not hold back an observed exit;
574
+ // its attempt stays recorded as unverified.
575
+ const grace = new AbortController();
576
+ void Promise.race([
577
+ Promise.allSettled(pendingDeliveries),
578
+ delay(PROCESS_CLEANUP_VERIFICATION_GRACE_MS, undefined, {
579
+ ref: false,
580
+ signal: grace.signal,
581
+ }).catch(() => undefined),
582
+ ])
583
+ .finally(() => {
584
+ grace.abort();
585
+ })
586
+ .then(finish);
416
587
  });
417
588
  const timeout = scheduleProcessInterval(() => {
589
+ onLiveProgress?.();
418
590
  if (signal?.aborted === true) {
419
591
  reason = "cancelled";
420
- terminal.kill("SIGKILL");
592
+ forceKill();
593
+ }
594
+ else if (finalizationStartedAt !== undefined) {
595
+ if (performance.now() - finalizationStartedAt >=
596
+ scenario.finalization_ms)
597
+ forceKill();
421
598
  }
422
599
  else if (Date.now() - started >= scenario.timeout_ms) {
423
600
  reason = "timeout";
424
- terminal.kill("SIGKILL");
601
+ terminateAtDeadline();
425
602
  }
426
603
  else if (Date.now() - lastOutput() >= scenario.idle_timeout_ms) {
427
604
  reason = "idle_timeout";
428
- terminal.kill("SIGKILL");
605
+ terminateAtDeadline();
429
606
  }
430
607
  }, 20);
431
608
  timers.add(timeout);
@@ -494,60 +671,170 @@ const releaseCapturedProcessGroup = async (ownership, host) => {
494
671
  ],
495
672
  };
496
673
  };
497
- export const releaseProcessResources = async (options) => {
498
- const host = options.host ?? processCaptureCleanupHost;
499
- for (const timer of options.timers)
500
- timer.cancel();
501
- let terminalRenderer = {
502
- state: options.renderer === undefined ? "not_required" : "cleaned",
503
- reason: null,
504
- };
505
- try {
506
- await options.renderer?.dispose();
674
+ /** One capture's exact resource owner, with completion tracked per resource. */
675
+ class ProcessCaptureResourceOwner {
676
+ options;
677
+ #host;
678
+ #terminalRenderer;
679
+ #ownedProcessGroup;
680
+ #temporaryRoot;
681
+ constructor(options) {
682
+ this.options = options;
683
+ this.#host = options.host ?? processCaptureCleanupHost;
684
+ if (options.renderer === undefined)
685
+ this.#terminalRenderer = { state: "not_required", reason: null };
686
+ if (options.terminal === undefined)
687
+ this.#ownedProcessGroup = { state: "not_required", reason: null };
507
688
  }
508
- catch (cause) {
509
- terminalRenderer = {
510
- state: "failed",
511
- reason: cause instanceof Error
512
- ? cause.message || cause.name || "renderer dispose failed"
513
- : "renderer dispose failed",
689
+ async close() {
690
+ for (const timer of this.options.timers)
691
+ timer.cancel();
692
+ await this.#releaseRenderer();
693
+ await this.#releaseOwnedProcessGroup();
694
+ await this.#releaseTemporaryRoot();
695
+ return {
696
+ owned_process_group: this.#ownedProcessGroup ?? {
697
+ state: "unverified",
698
+ reason: "owned process cleanup was not attempted",
699
+ },
700
+ terminal_renderer: this.#terminalRenderer ?? {
701
+ state: "unverified",
702
+ reason: "terminal renderer cleanup was not attempted",
703
+ },
704
+ temporary_root: this.#temporaryRoot ?? {
705
+ state: "unverified",
706
+ reason: "temporary root cleanup was not attempted",
707
+ },
514
708
  };
515
709
  }
516
- const ownedProcessGroup = options.terminal === undefined
517
- ? { state: "not_required", reason: null }
518
- : await releaseCapturedProcessGroup({
519
- runId: options.runId,
520
- leaderPid: options.terminal.pid,
521
- processGroupId: options.terminal.pid,
710
+ async #releaseRenderer() {
711
+ if (this.options.renderer === undefined ||
712
+ this.#terminalRenderer?.state === "cleaned" ||
713
+ this.#terminalRenderer?.state === "not_required")
714
+ return;
715
+ try {
716
+ await this.options.renderer.dispose();
717
+ this.#terminalRenderer = { state: "cleaned", reason: null };
718
+ }
719
+ catch (cause) {
720
+ this.#terminalRenderer = {
721
+ state: "failed",
722
+ reason: cleanupFailureMessage(cause, "renderer dispose failed"),
723
+ };
724
+ }
725
+ }
726
+ async #releaseOwnedProcessGroup() {
727
+ if (this.options.terminal === undefined ||
728
+ this.#ownedProcessGroup?.state === "cleaned" ||
729
+ this.#ownedProcessGroup?.state === "not_required")
730
+ return;
731
+ this.#ownedProcessGroup = await releaseCapturedProcessGroup({
732
+ runId: this.options.runId,
733
+ leaderPid: this.options.terminal.pid,
734
+ processGroupId: this.options.terminal.pid,
522
735
  sweepTokenOwnedProcesses: true,
523
- ...(options.sampledProcessGroupIds === undefined
736
+ ...(this.options.sampledProcessGroupIds === undefined
524
737
  ? {}
525
- : { sampledProcessGroupIds: options.sampledProcessGroupIds }),
526
- ...(options.captureBaseline === undefined
738
+ : { sampledProcessGroupIds: this.options.sampledProcessGroupIds }),
739
+ ...(this.options.captureBaseline === undefined
527
740
  ? {}
528
- : { captureBaseline: options.captureBaseline }),
529
- }, host);
530
- let temporaryRoot = {
531
- state: "cleaned",
532
- reason: null,
533
- };
534
- try {
535
- await host.removeTemporaryRoot(options.temporaryRoot);
741
+ : { captureBaseline: this.options.captureBaseline }),
742
+ }, this.#host);
536
743
  }
537
- catch (cause) {
538
- temporaryRoot = {
539
- state: "failed",
540
- reason: cause instanceof Error
541
- ? cause.message || cause.name || "temporary root removal failed"
542
- : "temporary root removal failed",
543
- };
744
+ async #releaseTemporaryRoot() {
745
+ if (this.#temporaryRoot?.state === "cleaned")
746
+ return;
747
+ const owned = this.#ownedProcessGroup;
748
+ if (owned?.state === "failed" || owned?.state === "unverified") {
749
+ this.#temporaryRoot = {
750
+ state: "unverified",
751
+ reason: `temporary root retained because owned process cleanup is ${owned.state}: ${owned.reason ?? "ownership could not be verified"}`,
752
+ };
753
+ return;
754
+ }
755
+ try {
756
+ await this.#host.removeTemporaryRoot(this.options.temporaryRoot);
757
+ this.#temporaryRoot = { state: "cleaned", reason: null };
758
+ }
759
+ catch (cause) {
760
+ this.#temporaryRoot = {
761
+ state: "failed",
762
+ reason: cleanupFailureMessage(cause, "temporary root removal failed"),
763
+ };
764
+ }
544
765
  }
545
- return {
546
- owned_process_group: ownedProcessGroup,
547
- terminal_renderer: terminalRenderer,
548
- temporary_root: temporaryRoot,
549
- };
550
- };
766
+ }
767
+ const cleanupFailureMessage = (cause, fallback) => cause instanceof Error ? cause.message || cause.name || fallback : fallback;
768
+ /** Release one capture's resources, retaining the exact owner for scoped retry. */
769
+ export const releaseProcessResources = async (options) => new ProcessCaptureResourceOwner(options).close();
770
+ /** Run-local owner collection for resources whose first cleanup did not finish. */
771
+ export class ProcessCaptureResourceScope {
772
+ #pending = new Set();
773
+ #active = new Set();
774
+ #draining;
775
+ #closed = false;
776
+ /** Admit one capture before it starts acquiring resources. */
777
+ async run(operation) {
778
+ while (true) {
779
+ while (this.#draining !== undefined)
780
+ await this.#draining;
781
+ if (this.#closed)
782
+ throw new ProcessCaptureError("process capture lifecycle is closing; start a new server session before capturing again");
783
+ if (this.#pending.size === 0)
784
+ break;
785
+ await this.retryCleanup();
786
+ }
787
+ const running = Promise.resolve().then(operation);
788
+ this.#active.add(running);
789
+ try {
790
+ return await running;
791
+ }
792
+ finally {
793
+ this.#active.delete(running);
794
+ }
795
+ }
796
+ async release(options) {
797
+ const owner = new ProcessCaptureResourceOwner(options);
798
+ const report = await owner.close();
799
+ if (cleanupReportFailure(report) !== undefined) {
800
+ this.#pending.add(owner);
801
+ }
802
+ return report;
803
+ }
804
+ /** Drain active captures, then retry their retained resources without closing admission. */
805
+ retryCleanup() {
806
+ if (this.#draining !== undefined)
807
+ return this.#draining;
808
+ this.#draining = this.#drainAndRetry().finally(() => {
809
+ this.#draining = undefined;
810
+ });
811
+ return this.#draining;
812
+ }
813
+ /** Stop admitting new captures, drain active runs, and retry all retained owners. */
814
+ close() {
815
+ this.#closed = true;
816
+ return this.retryCleanup();
817
+ }
818
+ async #drainAndRetry() {
819
+ while (this.#active.size > 0)
820
+ await Promise.allSettled(this.#active);
821
+ const failures = [];
822
+ for (const owner of this.#pending) {
823
+ try {
824
+ const report = await owner.close();
825
+ if (cleanupReportFailure(report) === undefined)
826
+ this.#pending.delete(owner);
827
+ else
828
+ failures.push(cleanupReportFailure(report) ?? "cleanup incomplete");
829
+ }
830
+ catch (cause) {
831
+ failures.push(cause instanceof Error ? cause.message || cause.name : String(cause));
832
+ }
833
+ }
834
+ if (failures.length > 0)
835
+ throw new AggregateError(failures, `Process capture cleanup remains incomplete: ${failures.join("; ")}`);
836
+ }
837
+ }
551
838
  export const cleanupReportFailure = (report) => {
552
839
  const failures = Object.entries(report).filter(([, outcome]) => outcome.state === "failed" || outcome.state === "unverified");
553
840
  return failures.length === 0
@@ -715,7 +1002,7 @@ export const resolveProcessResult = (capture, executionFailure, cleanup, observa
715
1002
  throw new ProcessCaptureError(`process capture validation failed${cause instanceof Error ? `: ${cause.message}` : ""}`, { cause });
716
1003
  }
717
1004
  };
718
- export const prepareProcessCapture = async (scenario, signal, captureSnapshot = snapshotRoots, host = systemProcessPreparationHost) => {
1005
+ export const prepareProcessCapture = async (scenario, signal, captureSnapshot = snapshotRoots, host = systemProcessPreparationHost, resourceScope) => {
719
1006
  assertNotCancelled(signal);
720
1007
  await host.prepareOwnershipInspector?.(signal);
721
1008
  assertNotCancelled(signal);
@@ -729,20 +1016,24 @@ export const prepareProcessCapture = async (scenario, signal, captureSnapshot =
729
1016
  return { temporaryRoot, runId, ownershipBaseline, before };
730
1017
  }
731
1018
  catch (cause) {
732
- const cleanup = await releaseProcessResources({
1019
+ const cleanupOptions = {
733
1020
  timers: new Set(),
734
1021
  terminal: undefined,
735
1022
  renderer: undefined,
736
1023
  runId,
737
1024
  temporaryRoot,
738
1025
  host: { ...processCaptureCleanupHost, removeTemporaryRoot: host.cleanup },
739
- });
1026
+ };
1027
+ const cleanup = resourceScope === undefined
1028
+ ? await releaseProcessResources(cleanupOptions)
1029
+ : await resourceScope.release(cleanupOptions);
740
1030
  resolveProcessResult(undefined, normalizeCaptureFailure(cause, signal), cleanup, createProcessCaptureObservationBuffer({
741
1031
  frames: [],
742
1032
  interactions: [],
743
1033
  samples: [],
744
1034
  eventJournal: [],
745
1035
  before,
1036
+ finalizationEnabled: scenario.finalization_ms > 0,
746
1037
  }), { scenario });
747
1038
  throw cause;
748
1039
  }
@@ -0,0 +1,62 @@
1
+ const formatProgressMessage = (elapsedMs, counts, disposition, cleanup) => {
2
+ const status = `elapsed_ms=${String(elapsedMs)} frames=${String(counts.frames)} samples=${String(counts.samples)} interactions=${String(counts.interactions)}`;
3
+ const dispositionText = disposition === undefined ? "" : ` disposition=${disposition}`;
4
+ const cleanupText = cleanup === undefined
5
+ ? ""
6
+ : ` owned_process_group=${cleanup.owned_process_group.state} terminal_renderer=${cleanup.terminal_renderer.state} temporary_root=${cleanup.temporary_root.state}`;
7
+ return `${status}${dispositionText}${cleanupText}`;
8
+ };
9
+ /** Serialize observed capture status through one rate-limited reporter. */
10
+ export const createProcessCaptureProgressTracker = (progress, now = Date.now) => {
11
+ const started = now();
12
+ let completed = 0;
13
+ let live = true;
14
+ let next;
15
+ let pending;
16
+ const flush = async () => {
17
+ try {
18
+ while (next !== undefined) {
19
+ const update = next;
20
+ next = undefined;
21
+ try {
22
+ await progress?.report(update);
23
+ }
24
+ catch {
25
+ // Progress delivery is observational; capture and cleanup still finish.
26
+ continue;
27
+ }
28
+ }
29
+ }
30
+ finally {
31
+ pending = undefined;
32
+ }
33
+ };
34
+ return {
35
+ closeLive() {
36
+ live = false;
37
+ if (next?.terminal !== true)
38
+ next = undefined;
39
+ },
40
+ report(update) {
41
+ if (progress === undefined)
42
+ return Promise.resolve();
43
+ if (update.terminal !== true && !live)
44
+ return Promise.resolve();
45
+ const units = update.counts.frames +
46
+ update.counts.samples +
47
+ update.counts.interactions;
48
+ if (units > completed)
49
+ completed = units;
50
+ // A slow observer needs the latest observation, not a queue of old states.
51
+ next = {
52
+ phase: update.phase,
53
+ completed,
54
+ total: null,
55
+ message: formatProgressMessage(Math.max(0, now() - started), update.counts, update.disposition, update.cleanup),
56
+ ...(update.terminal === true ? { terminal: true } : {}),
57
+ };
58
+ pending ??= Promise.resolve().then(flush);
59
+ return pending;
60
+ },
61
+ };
62
+ };