rea-agents 6.2.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 (636) hide show
  1. package/README.md +24 -23
  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/bridge/hopper_bridge.py +2 -0
  6. package/dist/adb/AdbConfiguration.js +88 -0
  7. package/dist/adb/AdbDeviceOutput.js +186 -0
  8. package/dist/adb/AdbProvider.js +1190 -0
  9. package/dist/adb/AdbShellOutput.js +309 -0
  10. package/dist/android/AndroidTargetSnapshot.js +104 -22
  11. package/dist/android/JadxConfiguration.js +44 -24
  12. package/dist/android/JadxProvider.js +59 -21
  13. package/dist/android/JadxSession.js +51 -9
  14. package/dist/apktool/ApktoolConfiguration.js +84 -0
  15. package/dist/apktool/ApktoolDecodeOutput.js +59 -0
  16. package/dist/apktool/ApktoolProvider.js +506 -0
  17. package/dist/application/AnalysisProvider.js +8 -2
  18. package/dist/application/AppBundleExecutable.js +27 -22
  19. package/dist/application/BinaryTargetResolver.js +85 -19
  20. package/dist/application/BrowserScenarioEvidence.js +2 -2
  21. package/dist/application/CapabilityInventory.js +11 -1
  22. package/dist/application/ClientConfigurationDocument.js +98 -0
  23. package/dist/application/ClientConfigurationFiles.js +91 -0
  24. package/dist/application/ClientRegistrationEnvironment.js +35 -0
  25. package/dist/application/ClientRegistrationStatus.js +75 -27
  26. package/dist/application/DirectAnalysis.js +14 -8
  27. package/dist/application/DirectAnalysisCleanup.js +1 -2
  28. package/dist/application/DirectAnalysisStatus.js +3 -6
  29. package/dist/application/Doctor.js +27 -34
  30. package/dist/application/DoctorDiagnostics.js +1 -1
  31. package/dist/application/EvidenceBundleCommands.js +6 -12
  32. package/dist/application/EvidenceBundleFiles.js +1 -1
  33. package/dist/application/GeminiClientSettings.js +139 -0
  34. package/dist/application/HermesClientHome.js +115 -0
  35. package/dist/application/HopperDownload.js +39 -0
  36. package/dist/application/InvestigationProviders.js +10 -4
  37. package/dist/application/JsonFiles.js +16 -15
  38. package/dist/application/JsonInputFile.js +252 -0
  39. package/dist/application/LinuxHopper.js +6 -13
  40. package/dist/application/MacHopper.js +172 -149
  41. package/dist/application/MipsElfAbiFlags.js +140 -0
  42. package/dist/application/ProviderOperationExecution.js +31 -0
  43. package/dist/application/ReconstructionObligationCandidates.js +16 -3
  44. package/dist/application/ReconstructionObligationLedgerProjection.js +3 -1
  45. package/dist/application/ReferenceSourceImport.js +76 -29
  46. package/dist/application/ReferenceSourceImportEntries.js +18 -9
  47. package/dist/application/ReferenceSourceImportPolicy.js +99 -23
  48. package/dist/application/ReferenceSourceImportTypes.js +30 -22
  49. package/dist/application/ReferenceSourceVcsAdapter.js +145 -30
  50. package/dist/application/RegularFileRead.js +103 -0
  51. package/dist/application/Setup.js +69 -10
  52. package/dist/application/SetupClientConfiguration.js +134 -23
  53. package/dist/application/SetupHost.js +102 -22
  54. package/dist/application/SetupPlan.js +18 -17
  55. package/dist/application/SetupSkill.js +81 -13
  56. package/dist/application/SupportedClients.js +305 -37
  57. package/dist/application/Uninstall.js +172 -8
  58. package/dist/application/UpdateMaintenance.js +23 -23
  59. package/dist/application/Utf8JsonInput.js +71 -0
  60. package/dist/application/WebScriptExportService.js +130 -57
  61. package/dist/application/WebSourceLocationService.js +3 -0
  62. package/dist/application/adb/AdbDeviceAnalysisPort.js +1 -0
  63. package/dist/application/adb/AdbDeviceAnalysisService.js +13 -0
  64. package/dist/application/analysisView/AnalysisViewService.js +40 -2
  65. package/dist/application/android/AndroidAnalysisService.js +1 -1
  66. package/dist/application/apktool/ApktoolResourceAnalysisPort.js +1 -0
  67. package/dist/application/apktool/ApktoolResourceAnalysisService.js +13 -0
  68. package/dist/application/binary/AnalysisClientCleanup.js +0 -24
  69. package/dist/application/binary/AnalysisSnapshotCache.js +5 -4
  70. package/dist/application/binary/BinarySession.js +18 -1
  71. package/dist/application/binary/BinarySessionOpen.js +9 -1
  72. package/dist/application/binaryDiagnostics/BinaryLayoutService.js +2 -1
  73. package/dist/application/binaryDiagnostics/PeResourcesPort.js +1 -0
  74. package/dist/application/binaryDiagnostics/PeResourcesService.js +111 -0
  75. package/dist/application/binaryDiagnostics/RecordedCrashService.js +2 -1
  76. package/dist/application/evm/EvmInterfaceService.js +3 -0
  77. package/dist/application/firmware/FirmwareAnalysisService.js +3 -0
  78. package/dist/application/investigation/InspectEvidenceBundle.js +18 -0
  79. package/dist/application/javascript/ElectronActiveEvidence.js +2 -2
  80. package/dist/application/javascript/ElectronBoundaryAnalysis.js +2 -2
  81. package/dist/application/javascript/ElectronBoundaryGraphContext.js +3 -2
  82. package/dist/application/javascript/ElectronBoundaryGraphIpc.js +2 -2
  83. package/dist/application/javascript/ElectronBoundaryGraphNative.js +20 -3
  84. package/dist/application/javascript/ElectronBoundaryGraphWindows.js +3 -3
  85. package/dist/application/javascript/JavaScriptApplicationEvidence.js +1 -0
  86. package/dist/application/javascript/JavaScriptApplicationEvidenceGraph.js +107 -46
  87. package/dist/application/javascript/JavaScriptApplicationService.js +23 -11
  88. package/dist/application/javascript/JavaScriptApplicationWorkflowEvidence.js +5 -6
  89. package/dist/application/javascript/JavaScriptApplicationWorkflowService.js +59 -45
  90. package/dist/application/javascript/JavaScriptArtifactAnalysis.js +171 -36
  91. package/dist/application/javascript/JavaScriptArtifactGraphAccumulator.js +14 -16
  92. package/dist/application/javascript/JavaScriptArtifactGraphBuilder.js +74 -36
  93. package/dist/application/javascript/JavaScriptArtifactGraphBundlers.js +4 -3
  94. package/dist/application/javascript/JavaScriptArtifactGraphContext.js +11 -5
  95. package/dist/application/javascript/JavaScriptArtifactGraphFindings.js +53 -42
  96. package/dist/application/javascript/JavaScriptArtifactGraphStructure.js +92 -10
  97. package/dist/application/javascript/JavaScriptArtifactPathResolution.js +293 -238
  98. package/dist/application/javascript/JavaScriptArtifactReconstruction.js +120 -28
  99. package/dist/application/javascript/JavaScriptArtifactReconstructionInput.js +4 -0
  100. package/dist/application/javascript/JavaScriptJsonModules.js +2 -2
  101. package/dist/application/javascript/JavaScriptModuleRelationships.js +10 -20
  102. package/dist/application/javascript/JavaScriptRecoveryService.js +3 -0
  103. package/dist/application/javascript/JavaScriptRuntimeReconciliationService.js +11 -27
  104. package/dist/application/javascript/JavaScriptSemanticGraphAsyncProjection.js +11 -5
  105. package/dist/application/javascript/JavaScriptSemanticGraphBuilder.js +206 -66
  106. package/dist/application/javascript/JavaScriptSemanticGraphChildProcessProjection.js +1 -1
  107. package/dist/application/javascript/JavaScriptSemanticGraphConstruction.js +18 -23
  108. package/dist/application/javascript/JavaScriptSemanticGraphDataProjection.js +5 -2
  109. package/dist/application/javascript/JavaScriptSemanticGraphEvidence.js +1 -1
  110. package/dist/application/javascript/JavaScriptSemanticGraphFingerprintProjection.js +2 -2
  111. package/dist/application/javascript/JavaScriptSemanticGraphFlowProjection.js +7 -5
  112. package/dist/application/javascript/JavaScriptSemanticGraphObjectProjection.js +6 -4
  113. package/dist/application/javascript/JavaScriptSemanticGraphProjection.js +4 -4
  114. package/dist/application/javascript/JavaScriptSemanticGraphResourceProjection.js +1 -1
  115. package/dist/application/javascript/JavaScriptSemanticGraphValueProjection.js +29 -15
  116. package/dist/application/javascript/JavaScriptSemanticTraceService.js +15 -10
  117. package/dist/application/jeb/JebAnalysisPort.js +1 -0
  118. package/dist/application/jeb/JebAnalysisService.js +13 -0
  119. package/dist/application/managed/ManagedApplicationGraphService.js +1 -1
  120. package/dist/application/native/NativeCallRoutes.js +2 -4
  121. package/dist/application/native/NativeUiActionTrace.js +16 -8
  122. package/dist/application/native/NativeValueTrace.js +23 -6
  123. package/dist/application/process/ProcessCli.js +25 -20
  124. package/dist/artifacts/ArtifactPaths.js +129 -8
  125. package/dist/artifacts/ArtifactProvider.js +34 -31
  126. package/dist/artifacts/ArtifactProviderMetadata.js +1 -4
  127. package/dist/artifacts/ArtifactReader.js +23 -0
  128. package/dist/artifacts/ArtifactResourceScope.js +100 -0
  129. package/dist/artifacts/AsarArtifactReader.js +218 -80
  130. package/dist/artifacts/AsarHeader.js +24 -0
  131. package/dist/artifacts/DirectoryArtifactReader.js +168 -65
  132. package/dist/artifacts/MachOSliceArtifactReader.js +116 -39
  133. package/dist/artifacts/NativeDmgArtifactReader.js +179 -87
  134. package/dist/artifacts/NativeDmgOwnership.js +109 -0
  135. package/dist/artifacts/SafeOutputTree.js +245 -70
  136. package/dist/artifacts/SafeOutputTreeCleanup.js +45 -0
  137. package/dist/artifacts/SafeOutputTreeCreationFailure.js +20 -0
  138. package/dist/artifacts/SafeOutputTreeIdentity.js +42 -0
  139. package/dist/artifacts/SafeOutputTreeReadback.js +33 -0
  140. package/dist/artifacts/ZipArtifactReader.js +77 -27
  141. package/dist/artifacts/apple/InterfaceBuilderAnalysis.js +58 -18
  142. package/dist/artifacts/apple/InterfaceBuilderDecodeBudget.js +62 -24
  143. package/dist/artifacts/apple/KeyedArchiveReader.js +76 -49
  144. package/dist/artifacts/apple/MachoLoadCommandReader.js +36 -6
  145. package/dist/artifacts/extraction/ArtifactExtraction.js +134 -92
  146. package/dist/artifacts/inventory/ArtifactGraphConstruction.js +116 -50
  147. package/dist/artifacts/inventory/ArtifactInventory.js +5 -4
  148. package/dist/artifacts/inventory/classify.js +87 -25
  149. package/dist/artifacts/inventory/hashStableRootArtifact.js +70 -0
  150. package/dist/artifacts/inventory/reader.js +13 -5
  151. package/dist/artifacts/inventory/scanCanonical.js +73 -30
  152. package/dist/artifacts/inventory/scanReader.js +43 -20
  153. package/dist/artifacts/javascript/JavaScriptArtifactFiles.js +72 -28
  154. package/dist/artifacts/javascript/JavaScriptSourceAnalysis.js +3 -0
  155. package/dist/browser/BrowserScenarioPartialObservation.js +8 -2
  156. package/dist/browser/BrowserScenarioSecrets.js +52 -37
  157. package/dist/browser/CdpBrowserProvider.js +9 -3
  158. package/dist/browser/CdpCaptureDocuments.js +40 -6
  159. package/dist/browser/CdpCaptureDomSvg.js +210 -0
  160. package/dist/browser/CdpCaptureEventBodyShapes.js +4 -8
  161. package/dist/browser/CdpCaptureEventHandlers.js +26 -9
  162. package/dist/browser/CdpCaptureEvents.js +4 -9
  163. package/dist/browser/CdpCaptureStorageFingerprints.js +3 -3
  164. package/dist/browser/CdpConnection.js +22 -5
  165. package/dist/browser/CdpElectronInspection.js +2 -2
  166. package/dist/browser/CdpElectronProvider.js +4 -3
  167. package/dist/browser/CdpElectronScripts.js +2 -2
  168. package/dist/browser/CdpPageCapture.js +1 -1
  169. package/dist/browser/CdpTargetSession.js +30 -34
  170. package/dist/browser/CdpWebMcpDiscovery.js +48 -23
  171. package/dist/browser/ElectronFileScope.js +99 -9
  172. package/dist/browser/PlaywrightBrowserScenarioProvider.js +63 -7
  173. package/dist/browser/PlaywrightElectronActiveProvider.js +11 -6
  174. package/dist/browser/PlaywrightScenarioArtifacts.js +5 -5
  175. package/dist/browser/PlaywrightScenarioBrowser.js +208 -43
  176. package/dist/browser/PlaywrightScenarioSession.js +130 -65
  177. package/dist/browser/PlaywrightScenarioStorage.js +507 -0
  178. package/dist/browser/PngVisualDiff.js +198 -29
  179. package/dist/browser/WebSourceMapFetcher.js +35 -9
  180. package/dist/browser/assets/LocalWebScriptArtifacts.js +3 -1
  181. package/dist/browser/assets/PublishWebScripts.js +75 -20
  182. package/dist/browser/assets/ScenarioScriptCapture.js +8 -12
  183. package/dist/browser/assets/WebArtifactReads.js +23 -1
  184. package/dist/browser/assets/WebSourceLocationArtifacts.js +1 -0
  185. package/dist/browser/execution/CdpExecutionCapture.js +3 -3
  186. package/dist/browser/execution/CdpPreciseCoverage.js +5 -8
  187. package/dist/browser/history/HarCapture.js +14 -0
  188. package/dist/browser/history/HarCaptureProcess.js +2 -10
  189. package/dist/browser/history/MitmproxyCaptureAdapter.js +3 -1
  190. package/dist/browser/modules/WebModuleArtifacts.js +1 -0
  191. package/dist/cli/adbCommands.js +337 -0
  192. package/dist/cli/analysisViewCommands.js +39 -1
  193. package/dist/cli/apktoolCommands.js +53 -0
  194. package/dist/cli/artifactCommands.js +8 -11
  195. package/dist/cli/binaryDiagnosticsCommands.js +19 -1
  196. package/dist/cli/browserAdvancedCommands.js +65 -36
  197. package/dist/cli/coreAnalysisCommands.js +2 -2
  198. package/dist/cli/coreBinaryCommands.js +12 -13
  199. package/dist/cli/coreNativeCommands.js +1 -14
  200. package/dist/cli/electronCommands.js +14 -10
  201. package/dist/cli/evmCommands.js +13 -4
  202. package/dist/cli/firmwareCommands.js +7 -2
  203. package/dist/cli/javascriptApplicationAnalysis.js +19 -13
  204. package/dist/cli/javascriptRecoveryCommands.js +22 -15
  205. package/dist/cli/jebCommands.js +99 -0
  206. package/dist/cli/jsonOutput.js +12 -4
  207. package/dist/cli/referenceSourceImportStatus.js +7 -0
  208. package/dist/cli/setupCommands.js +15 -3
  209. package/dist/cli/streamedJsonOutput.js +83 -4
  210. package/dist/cli/utilityCommands.js +68 -22
  211. package/dist/cli/webScriptCommands.js +20 -1
  212. package/dist/cli/webSourceLocationCommands.js +21 -9
  213. package/dist/cli.js +11 -2
  214. package/dist/cliBrowserScenarioCommands.js +2 -1
  215. package/dist/cliCommandNames.js +32 -0
  216. package/dist/cliJsonInput.js +47 -34
  217. package/dist/cliObservationOptions.js +7 -0
  218. package/dist/composition/adb.js +3 -0
  219. package/dist/composition/apktool.js +3 -0
  220. package/dist/composition/auxiliaryAnalysisProviders.js +5 -4
  221. package/dist/composition/binaryDiagnostics.js +4 -0
  222. package/dist/composition/browserScenario.js +2 -2
  223. package/dist/composition/directAnalysis.js +14 -7
  224. package/dist/composition/javascriptAnalysisWorkerProcess.js +48 -0
  225. package/dist/composition/jeb.js +6 -0
  226. package/dist/config/environment.js +10 -0
  227. package/dist/config/ghidraLanguageOverride.js +9 -0
  228. package/dist/config/mcpInputSchemaProfile.js +27 -0
  229. package/dist/config/parseConfig.js +28 -1
  230. package/dist/contracts/adb/adbToolContracts.js +353 -0
  231. package/dist/contracts/advertisedInputExamples.js +48 -0
  232. package/dist/contracts/analysisDetail.js +10 -0
  233. package/dist/contracts/analysisViewToolContracts.js +17 -2
  234. package/dist/contracts/apktool/apktoolToolContracts.js +33 -0
  235. package/dist/contracts/artifactComparisonExample.js +5 -5
  236. package/dist/contracts/artifactToolContracts.js +8 -5
  237. package/dist/contracts/browserToolContracts.js +1 -1
  238. package/dist/contracts/compactInputSchema.js +256 -0
  239. package/dist/contracts/errorSchemas.js +3 -1
  240. package/dist/contracts/functionComparisonExample.js +8 -0
  241. package/dist/contracts/functionWorkflowToolContracts.js +1 -1
  242. package/dist/contracts/inputSchemaPresentation.js +104 -13
  243. package/dist/contracts/javascript/electronToolContracts.js +16 -3
  244. package/dist/contracts/javascript/javascriptApplicationWorkflowExamples.js +3 -2
  245. package/dist/contracts/javascript/javascriptExportShapeComparisonExample.js +6 -3
  246. package/dist/contracts/javascript/javascriptRecoveryToolContracts.js +1 -1
  247. package/dist/contracts/javascript/javascriptRuntimeReconciliationExample.js +8 -7
  248. package/dist/contracts/jeb/jebToolContracts.js +64 -0
  249. package/dist/contracts/managed/managedToolContracts.js +3 -2
  250. package/dist/contracts/mobileApplicationGraphExamples.js +5 -5
  251. package/dist/contracts/native/binaryDiagnosticsToolContracts.js +25 -3
  252. package/dist/contracts/native/nativeToolContracts.js +1 -1
  253. package/dist/contracts/officialToolContracts.js +5 -5
  254. package/dist/contracts/sessionLifecycleInputs.js +4 -3
  255. package/dist/contracts/sessionStatusContract.js +3 -2
  256. package/dist/contracts/sessionToolContracts.js +5 -4
  257. package/dist/contracts/sessionToolSchemas.js +9 -4
  258. package/dist/contracts/toolContractExamples.js +6 -0
  259. package/dist/contracts/toolContractTypes.js +3 -0
  260. package/dist/contracts/toolContracts.js +6 -0
  261. package/dist/contracts/toolEffects.js +167 -0
  262. package/dist/contracts/toolOutputSchemaGroups.js +7 -5
  263. package/dist/contracts/toolOutputSchemaPrimitives.js +2 -5
  264. package/dist/contracts/toolSchemaMetadata.js +82 -7
  265. package/dist/domain/adb/adbDeviceAnalysis.js +583 -0
  266. package/dist/domain/analysisErrorBase.js +5 -0
  267. package/dist/domain/analysisErrorCleanup.js +29 -0
  268. package/dist/domain/analysisErrorPresentation.js +18 -4
  269. package/dist/domain/analysisErrorProjection.js +4 -1
  270. package/dist/domain/analysisSnapshot.js +5 -2
  271. package/dist/domain/analysisView/analysisView.js +53 -5
  272. package/dist/domain/analysisView/binaryLayoutView.js +2 -0
  273. package/dist/domain/analysisView/javascriptApplicationView.js +2 -0
  274. package/dist/domain/analysisView/nativeFunctionView.js +155 -0
  275. package/dist/domain/android/androidApplication.js +25 -20
  276. package/dist/domain/android/androidPartialObservation.js +36 -0
  277. package/dist/domain/apktool/apktoolResourceAnalysis.js +77 -0
  278. package/dist/domain/apple/appleApplication.js +40 -23
  279. package/dist/domain/apple/appleBundleAnatomy.js +95 -28
  280. package/dist/domain/apple/dyldPaths.js +9 -1
  281. package/dist/domain/apple/dylibResolution.js +3 -3
  282. package/dist/domain/apple/interfaceBuilderGraph.js +22 -19
  283. package/dist/domain/apple/interfaceBuilderKeyedArchive.js +10 -1
  284. package/dist/domain/artifactComparison.js +39 -11
  285. package/dist/domain/artifactGraph.js +6 -4
  286. package/dist/domain/artifactIdentity.js +37 -9
  287. package/dist/domain/artifactInspection.js +10 -50
  288. package/dist/domain/artifactIntegrityPolicy.js +10 -0
  289. package/dist/domain/artifactInventoryEvidence.js +16 -17
  290. package/dist/domain/artifactPathSyntax.js +1 -1
  291. package/dist/domain/binaryTarget.js +16 -0
  292. package/dist/domain/binaryTargetTypes.js +8 -1
  293. package/dist/domain/browserCompleteness.js +3 -2
  294. package/dist/domain/browserObservationSchemas.js +8 -4
  295. package/dist/domain/browserScenarioCaptureValues.js +2 -2
  296. package/dist/domain/browserScenarioNormalization.js +3 -3
  297. package/dist/domain/browserScenarioValues.js +3 -2
  298. package/dist/domain/callPath.js +8 -10
  299. package/dist/domain/canonicalDigest.js +7 -1
  300. package/dist/domain/canonicalJsonDigestSteps.js +34 -12
  301. package/dist/domain/canonicalOrdering.js +1 -13
  302. package/dist/domain/changedBehavior.js +2 -3
  303. package/dist/domain/compactStringIdentity.js +9 -0
  304. package/dist/domain/comparisonSemantics.js +0 -5
  305. package/dist/domain/digests.js +0 -3
  306. package/dist/domain/evidence.js +12 -6
  307. package/dist/domain/evidenceBundle.js +51 -33
  308. package/dist/domain/evidenceRecordSummary.js +144 -0
  309. package/dist/domain/firmware/firmwareAnalysis.js +4 -3
  310. package/dist/domain/functionComparison.js +2 -1
  311. package/dist/domain/functionComparisonNormalization.js +4 -3
  312. package/dist/domain/functionComparisonResults.js +2 -2
  313. package/dist/domain/functionDossierEvidence.js +2 -1
  314. package/dist/domain/hopperValues.js +11 -15
  315. package/dist/domain/inputIssueProjection.js +16 -1
  316. package/dist/domain/javascript/electronActiveObservation.js +4 -3
  317. package/dist/domain/javascript/electronStaticAnalysisBrowser.js +14 -15
  318. package/dist/domain/javascript/electronStaticAnalysisIpc.js +20 -21
  319. package/dist/domain/javascript/electronStaticAnalysisNative.js +73 -41
  320. package/dist/domain/javascript/electronStaticAnalysisValues.js +24 -4
  321. package/dist/domain/javascript/javascriptAnalysisResourceControls.js +45 -0
  322. package/dist/domain/javascript/javascriptApplicationAnalysis.js +6 -1
  323. package/dist/domain/javascript/javascriptApplicationChangeGraph.js +18 -14
  324. package/dist/domain/javascript/javascriptApplicationEvidenceSchemas.js +4 -0
  325. package/dist/domain/javascript/javascriptApplicationGraph.js +91 -28
  326. package/dist/domain/javascript/javascriptApplicationProjectionResources.js +35 -0
  327. package/dist/domain/javascript/javascriptApplicationVersionComparison.js +4 -4
  328. package/dist/domain/javascript/javascriptApplicationVersionComparisonSchemas.js +37 -22
  329. package/dist/domain/javascript/javascriptApplicationVersionItems.js +72 -45
  330. package/dist/domain/javascript/javascriptApplicationVersionKeys.js +16 -8
  331. package/dist/domain/javascript/javascriptAstFingerprint.js +60 -33
  332. package/dist/domain/javascript/javascriptAstValues.js +54 -0
  333. package/dist/domain/javascript/javascriptElectronMemberWrites.js +50 -0
  334. package/dist/domain/javascript/javascriptExportShapeComparison.js +3 -2
  335. package/dist/domain/javascript/javascriptExportShapeComparisonSchemas.js +31 -23
  336. package/dist/domain/javascript/javascriptExportShapeSelection.js +2 -2
  337. package/dist/domain/javascript/javascriptExportShapeVariants.js +3 -2
  338. package/dist/domain/javascript/javascriptFeatureSeed.js +5 -3
  339. package/dist/domain/javascript/javascriptFeatureTrace.js +7 -6
  340. package/dist/domain/javascript/javascriptFeatureTraceSchemas.js +17 -9
  341. package/dist/domain/javascript/javascriptFeatureTraversal.js +4 -4
  342. package/dist/domain/javascript/javascriptModuleSemanticIr.js +15 -0
  343. package/dist/domain/javascript/javascriptNativeHandoff.js +12 -7
  344. package/dist/domain/javascript/javascriptRpcEndpoints.js +253 -0
  345. package/dist/domain/javascript/javascriptRuntimeLoadState.js +1 -3
  346. package/dist/domain/javascript/javascriptRuntimeObservation.js +8 -5
  347. package/dist/domain/javascript/javascriptRuntimeReconciliation.js +12 -6
  348. package/dist/domain/javascript/javascriptRuntimeReconciliationActive.js +9 -8
  349. package/dist/domain/javascript/javascriptRuntimeReconciliationCaptureParsing.js +212 -0
  350. package/dist/domain/javascript/javascriptRuntimeReconciliationGraph.js +12 -6
  351. package/dist/domain/javascript/javascriptRuntimeReconciliationInputValidation.js +28 -0
  352. package/dist/domain/javascript/javascriptRuntimeReconciliationMatching.js +5 -5
  353. package/dist/domain/javascript/javascriptRuntimeReconciliationParsing.js +12 -223
  354. package/dist/domain/javascript/javascriptRuntimeReconciliationResult.js +2 -2
  355. package/dist/domain/javascript/javascriptRuntimeReconciliationRuntime.js +15 -4
  356. package/dist/domain/javascript/javascriptRuntimeReconciliationSchemas.js +2 -2
  357. package/dist/domain/javascript/javascriptRuntimeStaticCandidates.js +15 -17
  358. package/dist/domain/javascript/javascriptSemanticAnalysis.js +379 -30
  359. package/dist/domain/javascript/javascriptSemanticCallResolution.js +9 -7
  360. package/dist/domain/javascript/javascriptSemanticCallableResults.js +42 -0
  361. package/dist/domain/javascript/javascriptSemanticCalls.js +8 -1
  362. package/dist/domain/javascript/javascriptSemanticChildProcesses.js +2 -2
  363. package/dist/domain/javascript/javascriptSemanticCoverage.js +20 -0
  364. package/dist/domain/javascript/javascriptSemanticDataEffectHelpers.js +7 -9
  365. package/dist/domain/javascript/javascriptSemanticDataEffects.js +4 -11
  366. package/dist/domain/javascript/javascriptSemanticDerivedAnalysis.js +15 -4
  367. package/dist/domain/javascript/javascriptSemanticFileProjection.js +1 -0
  368. package/dist/domain/javascript/javascriptSemanticFingerprints.js +43 -42
  369. package/dist/domain/javascript/javascriptSemanticGraph.js +205 -52
  370. package/dist/domain/javascript/javascriptSemanticGraphSchemas.js +21 -11
  371. package/dist/domain/javascript/javascriptSemanticIr.js +0 -4
  372. package/dist/domain/javascript/javascriptSemanticIterationSources.js +139 -0
  373. package/dist/domain/javascript/javascriptSemanticMemberMutations.js +774 -136
  374. package/dist/domain/javascript/javascriptSemanticMutationInitializers.js +190 -0
  375. package/dist/domain/javascript/javascriptSemanticMutationValues.js +98 -41
  376. package/dist/domain/javascript/javascriptSemanticObjectReferences.js +381 -0
  377. package/dist/domain/javascript/javascriptSemanticObjects.js +9 -7
  378. package/dist/domain/javascript/javascriptSemanticPrimitives.js +7 -2
  379. package/dist/domain/javascript/javascriptSemanticProjection.js +72 -28
  380. package/dist/domain/javascript/javascriptSemanticPromises.js +15 -21
  381. package/dist/domain/javascript/javascriptSemanticPropertyPaths.js +100 -0
  382. package/dist/domain/javascript/javascriptSemanticProvenance.js +3 -3
  383. package/dist/domain/javascript/javascriptSemanticQuery.js +33 -29
  384. package/dist/domain/javascript/javascriptSemanticQueryIdentity.js +4 -5
  385. package/dist/domain/javascript/javascriptSemanticQuerySchemas.js +8 -9
  386. package/dist/domain/javascript/javascriptSemanticRequireOrigin.js +16 -10
  387. package/dist/domain/javascript/javascriptSemanticReturnedReferences.js +219 -0
  388. package/dist/domain/javascript/javascriptSemanticReturns.js +34 -48
  389. package/dist/domain/javascript/javascriptSemanticState.js +22 -2
  390. package/dist/domain/javascript/javascriptSemanticTraversal.js +25 -2
  391. package/dist/domain/javascript/javascriptSemanticValues.js +169 -30
  392. package/dist/domain/javascript/javascriptSourceAnalysis.js +1 -0
  393. package/dist/domain/javascript/javascriptSourceMapPaths.js +11 -1
  394. package/dist/domain/javascript/javascriptSourceParser.js +34 -9
  395. package/dist/domain/javascript/javascriptStaticAnalysis.js +29 -17
  396. package/dist/domain/javascript/javascriptStaticAnalysisBundler.js +13 -12
  397. package/dist/domain/javascript/javascriptStaticAnalysisCalls.js +49 -5
  398. package/dist/domain/javascript/javascriptStaticAnalysisFindings.js +8 -4
  399. package/dist/domain/javascript/javascriptStaticAnalysisHelpers.js +26 -15
  400. package/dist/domain/javascript/javascriptStaticAnalysisState.js +1 -0
  401. package/dist/domain/javascript/sourceToBundleComparison.js +7 -5
  402. package/dist/domain/javascript/sourceToBundleSignals.js +7 -7
  403. package/dist/domain/jeb/jebAnalysis.js +114 -0
  404. package/dist/domain/jsonSerialization.js +109 -55
  405. package/dist/domain/jsonShape.js +69 -31
  406. package/dist/domain/jsonValue.js +3 -0
  407. package/dist/domain/localPath.js +10 -4
  408. package/dist/domain/managed/managedApplicationGraph.js +47 -6
  409. package/dist/domain/managed/managedApplicationGraphCoverage.js +8 -2
  410. package/dist/domain/managed/managedApplicationGraphNodes.js +94 -59
  411. package/dist/domain/managed/managedArtifact.js +1 -0
  412. package/dist/domain/managed/managedInspectionEvidence.js +13 -0
  413. package/dist/domain/managed/managedMemberComparisonMatch.js +6 -7
  414. package/dist/domain/native/nativeAotPe.js +1408 -0
  415. package/dist/domain/native/nativeCallObservation.js +2 -4
  416. package/dist/domain/native/nativeInstruction.js +21 -0
  417. package/dist/domain/native/nativeMetadataRecovery.js +79 -6
  418. package/dist/domain/native/nativeValueFlow.js +5 -11
  419. package/dist/domain/native/objcSwiftMetadata.js +15 -17
  420. package/dist/domain/native/peResources.js +94 -0
  421. package/dist/domain/nativeConvention.js +33 -0
  422. package/dist/domain/process/processCapture.js +102 -11
  423. package/dist/domain/process/processCaptureCoverage.js +8 -5
  424. package/dist/domain/process/processCaptureExample.js +67 -0
  425. package/dist/domain/process/processCaptureValidation.js +83 -3
  426. package/dist/domain/process/processComparison.js +0 -23
  427. package/dist/domain/process/processScenario.js +62 -10
  428. package/dist/domain/process/processTraceEvaluation.js +4 -4
  429. package/dist/domain/process/processTraceSpecification.js +1 -3
  430. package/dist/domain/propertyListKeys.js +3 -1
  431. package/dist/domain/providerCleanupError.js +6 -2
  432. package/dist/domain/reconstructionCoverage.js +2 -1
  433. package/dist/domain/reconstructionUnknowns.js +4 -3
  434. package/dist/domain/reconstructionVerification.js +3 -2
  435. package/dist/domain/referenceSourceGraph.js +32 -23
  436. package/dist/domain/referenceSourceImportParsing.js +40 -48
  437. package/dist/domain/referenceSourcePathIdentity.js +22 -0
  438. package/dist/domain/referenceSourceRequireBindings.js +137 -0
  439. package/dist/domain/residualUnknown.js +3 -2
  440. package/dist/domain/staticRuntimeCorrelation.js +2 -1
  441. package/dist/domain/swiftSymbolClassification.js +6 -1
  442. package/dist/domain/symbolAnalysis.js +17 -2
  443. package/dist/domain/unicodeCodePointOrder.js +6 -0
  444. package/dist/domain/webBundleAnalyzerInspection.js +23 -3
  445. package/dist/domain/webCaptureDiff.js +170 -30
  446. package/dist/domain/webCaptureDiffSchemas.js +2 -8
  447. package/dist/domain/webInventory.js +3 -2
  448. package/dist/domain/webMcpDiscovery.js +4 -3
  449. package/dist/domain/webScriptExport.js +1 -1
  450. package/dist/domain/webScriptExportError.js +10 -4
  451. package/dist/domain/webScriptExportPlan.js +7 -13
  452. package/dist/domain/zipPackageFormat.js +4 -1
  453. package/dist/domain/zodCollectionSteps.js +24 -0
  454. package/dist/dotnet/ManagedArtifactInspector.js +55 -43
  455. package/dist/dotnet/ManagedDecodeBudget.js +80 -0
  456. package/dist/dotnet/ManagedMemberInspector.js +13 -6
  457. package/dist/dotnet/ManagedMemberInspectorCore.js +2 -2
  458. package/dist/dotnet/ManagedMemberInstructionDecoder.js +5 -4
  459. package/dist/dotnet/ManagedMemberRows.js +9 -4
  460. package/dist/dotnet/ManagedMetadataHeaps.js +15 -5
  461. package/dist/dotnet/ManagedMetadataInventoryRows.js +20 -11
  462. package/dist/dotnet/ManagedMetadataLayout.js +10 -4
  463. package/dist/dotnet/ManagedMethodBodyReader.js +8 -3
  464. package/dist/dotnet/ManagedNativeBoundaryHelpers.js +3 -2
  465. package/dist/dotnet/ManagedNativeBoundaryInspector.js +49 -34
  466. package/dist/dotnet/ManagedPeReader.js +41 -25
  467. package/dist/dotnet/ManagedReaderFailure.js +2 -1
  468. package/dist/dotnet/ManagedStaticProvider.js +65 -31
  469. package/dist/dotnet/ManagedStaticProviderMetadata.js +1 -4
  470. package/dist/evaluation/AgentEvaluationReport.js +9 -5
  471. package/dist/evaluation/CodexAgentEval.js +43 -13
  472. package/dist/evm/EvmoleFailures.js +0 -2
  473. package/dist/evm/EvmoleInterfaceProvider.js +67 -2
  474. package/dist/filesystem/OwnedDirectoryHandle.js +29 -0
  475. package/dist/filesystem/OwnedFileHandle.js +36 -0
  476. package/dist/filesystem/RegularFile.js +73 -0
  477. package/dist/filesystem/StableFileHash.js +46 -0
  478. package/dist/filesystem/readFileHandleChunks.js +26 -0
  479. package/dist/firmware/FirmwareCommand.js +25 -3
  480. package/dist/firmware/FirmwareFiles.js +23 -8
  481. package/dist/firmware/FirmwareProvider.js +156 -32
  482. package/dist/firmware/FirmwarePublication.js +24 -3
  483. package/dist/firmware/FirmwareRelease.js +1 -0
  484. package/dist/generatedPackageMetadata.js +2 -2
  485. package/dist/ghidra/GhidraAnalysisProfile.js +55 -4
  486. package/dist/ghidra/GhidraAnalysisSeeds.js +211 -0
  487. package/dist/ghidra/GhidraClient.js +90 -8
  488. package/dist/ghidra/GhidraDiagnostics.js +11 -8
  489. package/dist/ghidra/GhidraFunctionValues.js +26 -2
  490. package/dist/ghidra/GhidraInstallation.js +111 -10
  491. package/dist/ghidra/GhidraInventoryValues.js +23 -1
  492. package/dist/ghidra/GhidraLanguageCatalog.js +99 -0
  493. package/dist/ghidra/GhidraLauncher.js +123 -58
  494. package/dist/ghidra/GhidraLoadImageAttest.js +49 -2
  495. package/dist/ghidra/GhidraMipsProfile.js +79 -0
  496. package/dist/ghidra/GhidraProvider.js +57 -9
  497. package/dist/ghidra/GhidraProviderCapabilities.js +18 -8
  498. package/dist/ghidra/GhidraProviderClient.js +282 -21
  499. package/dist/ghidra/GhidraSessionValues.js +9 -2
  500. package/dist/hopper/HopperAnalysisProfile.js +2 -0
  501. package/dist/hopper/HopperCleanup.js +1 -1
  502. package/dist/hopper/HopperClient.js +15 -6
  503. package/dist/hopper/HopperMachOImage.js +2 -0
  504. package/dist/hopper/HopperProvider.js +13 -2
  505. package/dist/ida/IdaOperationRunner.js +10 -2
  506. package/dist/ida/IdaProvider.js +7 -0
  507. package/dist/ida/IdaSessionClient.js +7 -3
  508. package/dist/ida/IdaWorkspace.js +4 -2
  509. package/dist/inspector/JavaScriptRuntimeScope.js +9 -5
  510. package/dist/inspector/V8InspectorCaptureProjection.js +46 -13
  511. package/dist/inspector/V8InspectorProvider.js +60 -8
  512. package/dist/javascript/analysis/JavaScriptAnalysisTransfer.js +326 -0
  513. package/dist/javascript/analysis/JavaScriptAnalysisWorker.js +520 -0
  514. package/dist/javascript/analysis/JavaScriptAnalysisWorkerProtocol.js +63 -0
  515. package/dist/javascript/analysis/JavaScriptAnalysisWorkerSchemas.js +521 -0
  516. package/dist/javascript/analysis/JavaScriptAnalysisWorkerServer.js +116 -0
  517. package/dist/javascript/recovery/RecoveryFiles.js +18 -7
  518. package/dist/javascript/recovery/WakaruCommand.js +22 -9
  519. package/dist/javascript/recovery/WakaruExecution.js +11 -7
  520. package/dist/javascript/recovery/WakaruProvider.js +139 -16
  521. package/dist/javascript/recovery/WakaruPublication.js +14 -4
  522. package/dist/javascript/recovery/WakaruRelease.js +10 -3
  523. package/dist/javascript/recovery/WakaruReport.js +12 -7
  524. package/dist/javascript/recovery/WakaruVersion.js +24 -0
  525. package/dist/javascript/sourceMaps/SourceMapCommand.js +16 -3
  526. package/dist/javascript/sourceMaps/SourceMapDecoder.js +63 -7
  527. package/dist/javascript/sourceMaps/SourceMapFormat.js +15 -4
  528. package/dist/jeb/JebMcpConnection.js +179 -0
  529. package/dist/jeb/JebMcpEndpoint.js +40 -0
  530. package/dist/jeb/JebProvider.js +299 -0
  531. package/dist/main/shutdown.js +76 -32
  532. package/dist/main/transport.js +1 -1
  533. package/dist/mcpDoctor.js +15 -6
  534. package/dist/native/AppleDispatchCoverage.js +25 -12
  535. package/dist/native/AppleDispatchMetadata.js +14 -7
  536. package/dist/native/AppleMachoFixups.js +71 -15
  537. package/dist/native/AppleMachoSelection.js +23 -3
  538. package/dist/native/AppleObjcDispatchFacets.js +3 -3
  539. package/dist/native/AppleObjcProperties.js +17 -7
  540. package/dist/native/LldbCallTracer.js +241 -75
  541. package/dist/native/NativeMacOSProvider.js +100 -20
  542. package/dist/native/NativeMacOSProviderMetadata.js +1 -2
  543. package/dist/native/NativeMachoInspection.js +11 -7
  544. package/dist/native/NativeUiHelperRuntime.js +6 -1
  545. package/dist/native/NativeUiObservation.js +4 -3
  546. package/dist/native/pe/PeResourceLayout.js +120 -0
  547. package/dist/native/pe/PeResourceParser.js +286 -0
  548. package/dist/native/pe/PeResourcesProvider.js +63 -0
  549. package/dist/process/BoundedFileBytes.js +30 -7
  550. package/dist/process/DarwinProcessRunTokenReader.js +8 -3
  551. package/dist/process/OwnedCommand.js +4 -3
  552. package/dist/process/ProcessOwnership.js +104 -112
  553. package/dist/process/ProcessOwnershipObservation.js +104 -51
  554. package/dist/process/ProcessOwnershipProcessTree.js +4 -4
  555. package/dist/process/ProcessRunTokenObservations.js +48 -0
  556. package/dist/process/ProviderDiagnosticRedaction.js +17 -0
  557. package/dist/process/ProviderProcess.js +4 -3
  558. package/dist/process/capture/FilesystemSnapshot.js +116 -22
  559. package/dist/process/capture/ProcessCaptureLifecycle.js +363 -86
  560. package/dist/process/capture/ProcessCaptureProgress.js +62 -0
  561. package/dist/process/capture/ProcessFilesystemEffects.js +19 -4
  562. package/dist/process/capture/ProcessHarness.js +202 -47
  563. package/dist/process/capture/ProcessNormalization.js +3 -1
  564. package/dist/process/capture/ProcessScenarioRuntimeValidation.js +5 -2
  565. package/dist/process/capture/TerminalRenderer.js +24 -7
  566. package/dist/reference/ReferenceSourceReader.js +22 -5
  567. package/dist/reference/ReferenceSourceReaderEntries.js +114 -51
  568. package/dist/reference/ReferenceSourceReaderErrors.js +12 -0
  569. package/dist/reference/ReferenceSourceReaderFile.js +50 -10
  570. package/dist/reference/ReferenceSourceReaderValidate.js +4 -4
  571. package/dist/server/EvidenceMcpServer.js +36 -1
  572. package/dist/server/admittedToolOperation.js +9 -0
  573. package/dist/server/analysisAdmission.js +8 -0
  574. package/dist/server/contractToolHandler.js +21 -0
  575. package/dist/server/createServer.js +118 -47
  576. package/dist/server/registerAdbTools.js +36 -0
  577. package/dist/server/registerAnalysisViewTool.js +4 -9
  578. package/dist/server/registerAndroidTools.js +3 -12
  579. package/dist/server/registerApktoolTools.js +14 -0
  580. package/dist/server/registerApplicationTools/compareExportShapes.js +6 -7
  581. package/dist/server/registerApplicationTools/compareSourceToBundle.js +4 -5
  582. package/dist/server/registerApplicationTools/compareVersions.js +3 -2
  583. package/dist/server/registerApplicationTools/coverage.js +3 -2
  584. package/dist/server/registerApplicationTools/helpers.js +3 -2
  585. package/dist/server/registerApplicationTools/obligationLedger.js +3 -2
  586. package/dist/server/registerApplicationTools/projectMobileApplicationGraph.js +3 -2
  587. package/dist/server/registerApplicationTools/traceFeature.js +3 -2
  588. package/dist/server/registerApplicationTools/traceSemantics.js +4 -5
  589. package/dist/server/registerArtifactComparisonTool.js +5 -2
  590. package/dist/server/registerArtifactTools.js +2 -2
  591. package/dist/server/registerBinaryDiagnosticsTools.js +16 -4
  592. package/dist/server/registerBrowserScenarioTool.js +10 -7
  593. package/dist/server/registerBrowserTools.js +12 -9
  594. package/dist/server/registerBundleComparisonTool.js +16 -2
  595. package/dist/server/registerCloseLifecycleTool.js +36 -5
  596. package/dist/server/registerElectronTools.js +28 -10
  597. package/dist/server/registerEnhancedTools.js +78 -73
  598. package/dist/server/registerEvidenceTools.js +54 -46
  599. package/dist/server/registerEvmTools.js +4 -9
  600. package/dist/server/registerFirmwareTools.js +3 -11
  601. package/dist/server/registerFunctionComparisonTool.js +5 -2
  602. package/dist/server/registerJavaScriptRecoveryTool.js +4 -9
  603. package/dist/server/registerJavaScriptRuntimeObservationTools.js +9 -6
  604. package/dist/server/registerJebTools.js +16 -0
  605. package/dist/server/registerManagedTools.js +7 -4
  606. package/dist/server/registerManagedWorkflowTools/compareManagedMembers.js +4 -6
  607. package/dist/server/registerManagedWorkflowTools/importManagedReconstruction.js +3 -2
  608. package/dist/server/registerManagedWorkflowTools/projectManagedApplicationGraph.js +3 -2
  609. package/dist/server/registerManagedWorkflowTools/verifyManagedNativeBoundaries.js +3 -2
  610. package/dist/server/registerOfficialTools.js +31 -25
  611. package/dist/server/registerPeResourcesTool.js +9 -0
  612. package/dist/server/registerProcessComparisonTool.js +5 -2
  613. package/dist/server/registerRecordedCrashTools.js +4 -9
  614. package/dist/server/registerSessionRecordTools.js +2 -1
  615. package/dist/server/registerSessionTools.js +58 -21
  616. package/dist/server/registerWebModuleTool.js +4 -9
  617. package/dist/server/registerWebNetworkCaptureTool.js +4 -9
  618. package/dist/server/registerWebRuntimeTools.js +6 -5
  619. package/dist/server/registerWebScriptTool.js +6 -3
  620. package/dist/server/registerWebSourceLocationTool.js +4 -9
  621. package/dist/server/toolResult.js +21 -2
  622. package/dist/windows/WindowsPrivateRuntime.js +12 -5
  623. package/install.sh +7 -4
  624. package/licenses/nativeaot-parser-MIT.txt +28 -0
  625. package/native/windows/build/manifest.json +2 -2
  626. package/native/windows/build/rea-windows-x64.node +0 -0
  627. package/package.json +38 -7
  628. package/scripts/rea.mjs +16 -1
  629. package/skills/reverse-engineer-anything/SKILL.md +52 -51
  630. package/skills/reverse-engineer-anything/references/connection-and-recovery.md +127 -0
  631. package/skills/reverse-engineer-anything/references/evidence-workflows.md +8 -0
  632. package/skills/reverse-engineer-anything/references/javascript-applications.md +92 -13
  633. package/skills/reverse-engineer-anything/references/native-and-artifacts.md +31 -1
  634. package/dist/artifacts/inventory/policy.js +0 -2
  635. package/dist/domain/managed/managedApplicationGraphNodeCoverage.js +0 -6
  636. package/dist/server/registerNativeTools.js +0 -6
@@ -7,12 +7,14 @@ export class OwnedCommandFailure extends Error {
7
7
  snapshot;
8
8
  cleanupFailure;
9
9
  resources;
10
- constructor(reason, message, snapshot = null, cleanupFailure = null, options, resources = []) {
10
+ cleanupOwner;
11
+ constructor(reason, message, snapshot = null, cleanupFailure = null, options, resources = [], cleanupOwner) {
11
12
  super(message, options);
12
13
  this.reason = reason;
13
14
  this.snapshot = snapshot;
14
15
  this.cleanupFailure = cleanupFailure;
15
16
  this.resources = resources;
17
+ this.cleanupOwner = cleanupOwner;
16
18
  }
17
19
  }
18
20
  /** Execute a single owned process with independent cleanup and bounded diagnostic retention. */
@@ -102,14 +104,13 @@ const collectOwnedCommand = async (spawn, limits, launcher, deadline, callerSign
102
104
  }
103
105
  const stopped = await supervisor.stop();
104
106
  const snapshot = supervisor.snapshot();
105
- supervisor.dispose();
106
107
  if (stopped.status === "incomplete")
107
108
  throw new OwnedCommandFailure(failure?.reason ?? "process", failure?.message ?? "Command cleanup failed.", snapshot, stopped.reason, failure === undefined ? undefined : { cause: failure }, [
108
109
  spawn.runId,
109
110
  ...(spawn.cwd === undefined ? [] : [spawn.cwd]),
110
111
  `pid:${launched.ownership.leaderPid}`,
111
112
  `process-group:${launched.ownership.processGroupId}`,
112
- ]);
113
+ ], supervisor);
113
114
  if (failure !== undefined)
114
115
  throw new OwnedCommandFailure(failure.reason, failure.message, snapshot, failure.cleanupFailure, { cause: failure }, failure.resources);
115
116
  if (callerSignal?.aborted)
@@ -3,6 +3,7 @@ import { promisify } from "node:util";
3
3
  import { errorMessage, systemProcessOwnershipHost as systemHost, } from "./ProcessOwnershipObservation.js";
4
4
  import { launcherIdentityFailure } from "./ProcessOwnershipIdentity.js";
5
5
  import { descendantsOf, liveProcesses } from "./ProcessOwnershipProcessTree.js";
6
+ import { readProcessRunTokens } from "./ProcessRunTokenObservations.js";
6
7
  const execFileAsync = promisify(execFile);
7
8
  /**
8
9
  * Terminate one Windows process tree through the platform utility.
@@ -115,7 +116,38 @@ const readLiveProcessTable = async (host) => {
115
116
  return { available: false, reason: errorMessage(cause) };
116
117
  }
117
118
  };
118
- const createOwnedCleanupPlan = async (ownership, processes, host) => {
119
+ // A process-table read can race exit and retain the old state with an altered
120
+ // command. Only a fresh table proving that PID is no longer live can settle
121
+ // that mismatch; surviving group members still require normal token checks.
122
+ const settleLauncherExit = async (ownership, processes, host) => {
123
+ const launcher = processes.find(({ pid }) => pid === ownership.leaderPid);
124
+ if (launcher === undefined)
125
+ return processes;
126
+ const reason = launcherIdentityFailure(launcher, ownership);
127
+ if (reason === null)
128
+ return processes;
129
+ const refreshed = await readLiveProcessTable(host);
130
+ if (refreshed.available &&
131
+ !refreshed.processes.some(({ pid }) => pid === launcher.pid)) {
132
+ // Refreshing must not discard a surviving detached descendant's lineage,
133
+ // including a child that changed groups while the launcher exited.
134
+ const descendants = descendantsOf([launcher.pid], processes);
135
+ const descendantPids = new Set(descendants.map(({ pid }) => pid));
136
+ const descendantGroupIds = new Set(descendants.map(({ processGroupId }) => processGroupId));
137
+ const refreshedDescendantPids = new Set(descendantsOf(descendants.map(({ pid }) => pid), refreshed.processes).map(({ pid }) => pid));
138
+ if (refreshed.processes.some((process) => process.processGroupId !== ownership.processGroupId &&
139
+ (refreshedDescendantPids.has(process.pid) ||
140
+ descendantPids.has(process.pid) ||
141
+ descendantGroupIds.has(process.processGroupId))))
142
+ return { cleaned: false, reason };
143
+ return refreshed.processes;
144
+ }
145
+ return { cleaned: false, reason };
146
+ };
147
+ const createOwnedCleanupPlan = async (ownership, initialProcesses, host) => {
148
+ const processes = await settleLauncherExit(ownership, initialProcesses, host);
149
+ if ("cleaned" in processes)
150
+ return processes;
119
151
  const sampledProcessGroupIds = new Set((ownership.sampledProcessGroupIds ?? []).filter((processGroupId) => Number.isSafeInteger(processGroupId) && processGroupId > 0));
120
152
  const tokenOwned = ownership.sweepTokenOwnedProcesses === true
121
153
  ? await scanTokenOwnedProcesses(processes, ownership.runId, host, ownership.captureBaseline, {
@@ -149,10 +181,7 @@ const createOwnedCleanupPlan = async (ownership, processes, host) => {
149
181
  };
150
182
  let descendants = [];
151
183
  if (launcher !== undefined) {
152
- const identityFailure = launcherIdentityFailure(launcher, ownership);
153
- if (identityFailure !== null)
154
- return { cleaned: false, reason: identityFailure };
155
- descendants = descendantsOf(launcher.pid, processes);
184
+ descendants = descendantsOf([launcher.pid], processes);
156
185
  }
157
186
  const descendantPids = new Set(descendants.map(({ pid }) => pid));
158
187
  const processGroupIds = new Set([ownership.processGroupId]);
@@ -218,7 +247,10 @@ const createOwnedCleanupPlan = async (ownership, processes, host) => {
218
247
  const revalidateOwnedProcessGroup = async (processGroupId, ownership, host, expectedIdentities) => {
219
248
  let members;
220
249
  try {
221
- members = liveProcesses(await host.listProcesses()).filter(({ processGroupId: observedGroupId }) => observedGroupId === processGroupId);
250
+ const processes = await settleLauncherExit(ownership, liveProcesses(await host.listProcesses()), host);
251
+ if ("cleaned" in processes)
252
+ return processes;
253
+ members = processes.filter(({ processGroupId: observedGroupId }) => observedGroupId === processGroupId);
222
254
  }
223
255
  catch (cause) {
224
256
  return {
@@ -229,14 +261,6 @@ const revalidateOwnedProcessGroup = async (processGroupId, ownership, host, expe
229
261
  const failures = await processOwnershipFailures(members, ownership.runId, host, expectedIdentities);
230
262
  if (failures.length > 0)
231
263
  return cleanupValidationFailure(failures);
232
- if (processGroupId === ownership.processGroupId) {
233
- const launcher = members.find(({ pid }) => pid === ownership.leaderPid);
234
- if (launcher !== undefined) {
235
- const identityFailure = launcherIdentityFailure(launcher, ownership);
236
- if (identityFailure !== null)
237
- return { cleaned: false, reason: identityFailure };
238
- }
239
- }
240
264
  if (processGroupId !== ownership.processGroupId &&
241
265
  members.length > 0 &&
242
266
  !members.some(({ pid }) => pid === processGroupId) &&
@@ -328,53 +352,29 @@ const processOwnershipFailures = async (members, runId, host, expectedIdentities
328
352
  if (expectedIdentities.size > 0 && host.processIdentities !== undefined) {
329
353
  const expectedMembers = members.filter(({ pid }) => expectedIdentities.has(pid));
330
354
  const observed = await host.processIdentities(expectedMembers);
355
+ const identityFailures = [];
331
356
  for (const member of expectedMembers) {
332
357
  const expected = expectedIdentities.get(member.pid);
333
358
  const current = observed.get(member.pid);
334
359
  if (expected === null ||
335
360
  current?.state !== "readable" ||
336
361
  current.identity !== expected) {
337
- if (await processIsGone(host, member.pid))
338
- continue;
339
- failures.push({
362
+ identityFailures.push({
340
363
  pid: member.pid,
341
364
  reason: "process-identity-unavailable",
342
365
  diagnostic: "process identity changed or became unavailable before signal",
343
366
  });
344
367
  }
345
368
  }
369
+ failures.push(...(await recheckOwnershipFailures(identityFailures, host)));
346
370
  }
347
- for (const member of members) {
348
- try {
349
- if ((await host.environment(member.pid)).REA_PROCESS_RUN_ID !== runId)
350
- failures.push({ pid: member.pid, reason: "run-token-mismatch" });
351
- }
352
- catch (cause) {
353
- try {
354
- const live = liveProcesses(await host.listProcesses());
355
- if (!live.some(({ pid }) => pid === member.pid))
356
- continue;
357
- }
358
- catch (recheckCause) {
359
- failures.push({
360
- pid: member.pid,
361
- reason: "environment-unreadable",
362
- diagnostic: `${errorMessage(cause)}; process liveness recheck failed: ${errorMessage(recheckCause)}`,
363
- });
364
- continue;
365
- }
366
- failures.push({
367
- pid: member.pid,
368
- reason: "environment-unreadable",
369
- diagnostic: errorMessage(cause),
370
- });
371
- }
372
- }
371
+ failures.push(...(await processRunTokenFailures(members, runId, host)));
373
372
  if (failures.length === 0 &&
374
373
  expectedIdentities.size > 0 &&
375
374
  host.processIdentities !== undefined) {
376
375
  const expectedMembers = members.filter(({ pid }) => expectedIdentities.has(pid));
377
376
  const observed = await host.processIdentities(expectedMembers);
377
+ const identityFailures = [];
378
378
  for (const member of expectedMembers) {
379
379
  const expected = expectedIdentities.get(member.pid);
380
380
  const current = observed.get(member.pid);
@@ -382,17 +382,53 @@ const processOwnershipFailures = async (members, runId, host, expectedIdentities
382
382
  current?.state === "readable" &&
383
383
  current.identity === expected)
384
384
  continue;
385
- if (await processIsGone(host, member.pid))
386
- continue;
387
- failures.push({
385
+ identityFailures.push({
388
386
  pid: member.pid,
389
387
  reason: "process-identity-unavailable",
390
388
  diagnostic: "process identity changed or became unavailable during token validation",
391
389
  });
392
390
  }
391
+ failures.push(...(await recheckOwnershipFailures(identityFailures, host)));
393
392
  }
394
393
  return failures;
395
394
  };
395
+ const processRunTokenFailures = async (members, runId, host) => {
396
+ const failures = [];
397
+ for await (const { process: member, observation } of readProcessRunTokens(host, members)) {
398
+ if (observation.state === "readable") {
399
+ if (observation.runId !== runId)
400
+ failures.push({ pid: member.pid, reason: "run-token-mismatch" });
401
+ continue;
402
+ }
403
+ failures.push({
404
+ pid: member.pid,
405
+ reason: "environment-unreadable",
406
+ diagnostic: observation.reason,
407
+ });
408
+ }
409
+ return recheckOwnershipFailures(failures, host);
410
+ };
411
+ /**
412
+ * Take a fresh liveness snapshot after each ownership-read phase. Only an
413
+ * absent PID resolves an unreadable observation; a readable token mismatch
414
+ * remains a failure. Never reuse this snapshot across identity/token reads.
415
+ */
416
+ const recheckOwnershipFailures = async (failures, host) => {
417
+ if (!failures.some(({ reason }) => reason !== "run-token-mismatch"))
418
+ return failures;
419
+ try {
420
+ const live = new Set(liveProcesses(await host.listProcesses()).map(({ pid }) => pid));
421
+ return failures.filter(({ pid, reason }) => reason === "run-token-mismatch" || live.has(pid));
422
+ }
423
+ catch (cause) {
424
+ return failures.map((failure) => failure.reason === "run-token-mismatch"
425
+ ? failure
426
+ : {
427
+ ...failure,
428
+ diagnostic: `${failure.diagnostic}; process liveness recheck failed: ${errorMessage(cause)}`,
429
+ });
430
+ }
431
+ };
396
432
  const TOKEN_READ_RETRY_ATTEMPTS = 3;
397
433
  const TOKEN_READ_RETRY_DELAY_MS = 40;
398
434
  /** Darwin reports this when the kernel withholds a platform binary's environment. */
@@ -433,18 +469,19 @@ const scanTokenOwnedProcesses = async (processes, runId, host, captureBaseline,
433
469
  const failures = [];
434
470
  if (captureBaseline !== undefined && host.processIdentities !== undefined) {
435
471
  const stableCandidates = [];
472
+ const identityFailures = [];
436
473
  for (const process of candidates) {
437
474
  if (candidateIdentities.get(process.pid)?.state === "readable") {
438
475
  stableCandidates.push(process);
439
476
  continue;
440
477
  }
441
- if (!(await processIsGone(host, process.pid)))
442
- failures.push({
443
- pid: process.pid,
444
- reason: "process-identity-unavailable",
445
- diagnostic: "process identity was unavailable during token scan",
446
- });
478
+ identityFailures.push({
479
+ pid: process.pid,
480
+ reason: "process-identity-unavailable",
481
+ diagnostic: "process identity was unavailable during token scan",
482
+ });
447
483
  }
484
+ failures.push(...(await recheckOwnershipFailures(identityFailures, host)));
448
485
  candidates = stableCandidates;
449
486
  }
450
487
  const owned = [];
@@ -454,35 +491,21 @@ const scanTokenOwnedProcesses = async (processes, runId, host, captureBaseline,
454
491
  const identity = candidateIdentities.get(process.pid);
455
492
  ownedIdentities.set(process.pid, identity?.state === "readable" ? identity.identity : null);
456
493
  };
457
- let bulkTokens;
458
- if (host.runTokens !== undefined)
459
- bulkTokens = await host.runTokens(candidates);
460
494
  const unreadable = [];
461
- for (const process of candidates) {
462
- const bulkToken = bulkTokens?.get(process.pid);
463
- if (bulkToken !== undefined) {
464
- if (bulkToken.state === "readable") {
465
- if (bulkToken.runId === runId)
466
- recordOwned(process);
467
- continue;
468
- }
469
- unreadable.push({ process, diagnostic: bulkToken.reason });
470
- continue;
471
- }
472
- try {
473
- if ((await host.environment(process.pid)).REA_PROCESS_RUN_ID === runId)
495
+ for await (const { process, observation } of readProcessRunTokens(host, candidates)) {
496
+ if (observation.state === "readable") {
497
+ if (observation.runId === runId)
474
498
  recordOwned(process);
475
499
  }
476
- catch (cause) {
477
- unreadable.push({ process, diagnostic: errorMessage(cause) });
478
- }
500
+ else
501
+ unreadable.push({ process, diagnostic: observation.reason });
479
502
  }
480
503
  const remaining = await settleUnreadableTokenCandidates(unreadable, runId, host, recordOwned);
481
504
  const relatedPids = new Set();
482
505
  const relatedGroupIds = new Set();
483
506
  if (relation !== undefined) {
484
507
  relatedPids.add(relation.leaderPid);
485
- for (const descendant of descendantsOf(relation.leaderPid, processes))
508
+ for (const descendant of descendantsOf([relation.leaderPid], processes))
486
509
  relatedPids.add(descendant.pid);
487
510
  relatedGroupIds.add(relation.processGroupId);
488
511
  for (const processGroupId of relation.sampledProcessGroupIds ?? [])
@@ -533,6 +556,7 @@ const scanTokenOwnedProcesses = async (processes, runId, host, captureBaseline,
533
556
  if (candidates.length > 0 && host.processIdentities !== undefined) {
534
557
  const afterRead = await host.processIdentities(candidates);
535
558
  const stillOwned = [];
559
+ const identityFailures = [];
536
560
  const ownedPids = new Set(owned.map(({ pid }) => pid));
537
561
  for (const process of candidates) {
538
562
  const before = candidateIdentities.get(process.pid);
@@ -544,14 +568,13 @@ const scanTokenOwnedProcesses = async (processes, runId, host, captureBaseline,
544
568
  stillOwned.push(process);
545
569
  continue;
546
570
  }
547
- if (await processIsGone(host, process.pid))
548
- continue;
549
- failures.push({
571
+ identityFailures.push({
550
572
  pid: process.pid,
551
573
  reason: "process-identity-unavailable",
552
574
  diagnostic: "process identity changed or became unavailable during token validation",
553
575
  });
554
576
  }
577
+ failures.push(...(await recheckOwnershipFailures(identityFailures, host)));
555
578
  return {
556
579
  owned: stillOwned,
557
580
  failures,
@@ -579,29 +602,18 @@ const settleUnreadableTokenCandidates = async (pending, runId, host, recordOwned
579
602
  void cause;
580
603
  live = undefined;
581
604
  }
582
- let observations;
583
- if (host.runTokens !== undefined) {
584
- try {
585
- observations = await host.runTokens(remaining.map(({ process }) => process));
586
- }
587
- catch (cause) {
588
- void cause;
589
- observations = undefined;
590
- }
591
- }
592
605
  const stillUnreadable = [];
593
- for (const candidate of remaining) {
594
- const pid = candidate.process.pid;
595
- if (live !== undefined && !live.has(pid))
596
- continue;
597
- const observation = observations?.get(pid) ?? (await readEnvironmentRunToken(host, pid));
606
+ const candidates = remaining
607
+ .map(({ process }) => process)
608
+ .filter(({ pid }) => live === undefined || live.has(pid));
609
+ for await (const { process, observation } of readProcessRunTokens(host, candidates)) {
598
610
  if (observation.state === "readable") {
599
611
  if (observation.runId === runId)
600
- recordOwned(candidate.process);
612
+ recordOwned(process);
601
613
  continue;
602
614
  }
603
615
  stillUnreadable.push({
604
- process: candidate.process,
616
+ process,
605
617
  diagnostic: observation.reason,
606
618
  });
607
619
  }
@@ -609,23 +621,3 @@ const settleUnreadableTokenCandidates = async (pending, runId, host, recordOwned
609
621
  }
610
622
  return remaining;
611
623
  };
612
- const readEnvironmentRunToken = async (host, pid) => {
613
- try {
614
- return {
615
- state: "readable",
616
- runId: (await host.environment(pid)).REA_PROCESS_RUN_ID,
617
- };
618
- }
619
- catch (cause) {
620
- return { state: "unavailable", reason: errorMessage(cause) };
621
- }
622
- };
623
- const processIsGone = async (host, pid) => {
624
- try {
625
- return !liveProcesses(await host.listProcesses()).some((process) => process.pid === pid);
626
- }
627
- catch (cause) {
628
- void cause;
629
- return false;
630
- }
631
- };
@@ -4,49 +4,74 @@ import { launcherIdentityFailure } from "./ProcessOwnershipIdentity.js";
4
4
  import { descendantsOf, liveProcesses } from "./ProcessOwnershipProcessTree.js";
5
5
  import { execFileOutput } from "./ExecFileOutput.js";
6
6
  import { createDarwinProcessRunTokenReader } from "./DarwinProcessRunTokenReader.js";
7
- /** Observe one group without signaling it, failing closed on identity doubt. */
8
- export const observeOwnedProcessGroupWithHost = async (ownership, host, signal) => {
7
+ import { readProcessRunTokens } from "./ProcessRunTokenObservations.js";
8
+ /** Observe multiple groups from one process snapshot and one token batch. */
9
+ export const observeOwnedProcessGroups = async (runId, processGroupIds, host = systemProcessOwnershipHost, signal) => {
9
10
  signal?.throwIfAborted();
10
- let members;
11
+ const groupIds = [...new Set(processGroupIds)];
12
+ if (groupIds.length === 0)
13
+ return new Map();
14
+ let processes;
11
15
  try {
12
- members = (await host.listProcesses(signal)).filter(({ processGroupId }) => processGroupId === ownership.processGroupId);
16
+ processes = liveProcesses(await host.listProcesses(signal));
13
17
  }
14
18
  catch (cause) {
15
19
  signal?.throwIfAborted();
16
- return {
20
+ const failure = {
17
21
  state: "unverifiable",
18
22
  reason: `process group could not be inspected: ${errorMessage(cause)}`,
19
23
  };
24
+ return new Map(groupIds.map((groupId) => [groupId, failure]));
20
25
  }
21
26
  signal?.throwIfAborted();
22
- const liveMembers = liveProcesses(members);
23
- if (liveMembers.length === 0)
24
- return { state: "empty" };
25
- for (const member of liveMembers) {
26
- signal?.throwIfAborted();
27
- try {
28
- const runId = (await host.environment(member.pid)).REA_PROCESS_RUN_ID;
29
- signal?.throwIfAborted();
30
- if (runId !== ownership.runId)
31
- return {
27
+ const membersByGroup = new Map(groupIds.map((groupId) => [groupId, []]));
28
+ for (const process of processes)
29
+ membersByGroup.get(process.processGroupId)?.push(process);
30
+ const observations = new Map(groupIds.map((groupId) => [
31
+ groupId,
32
+ (membersByGroup.get(groupId)?.length ?? 0) > 0
33
+ ? { state: "alive" }
34
+ : { state: "empty" },
35
+ ]));
36
+ const liveMembers = groupIds.flatMap((groupId) => membersByGroup.get(groupId) ?? []);
37
+ const pendingGroups = new Set(groupIds.filter((groupId) => (membersByGroup.get(groupId)?.length ?? 0) > 0));
38
+ for await (const { process: member, observation } of readProcessRunTokens(host, liveMembers, signal)) {
39
+ if (!pendingGroups.has(member.processGroupId))
40
+ continue;
41
+ if (observation.state === "readable") {
42
+ if (observation.runId !== runId) {
43
+ observations.set(member.processGroupId, {
32
44
  state: "unverifiable",
33
45
  reason: "process ownership did not match",
34
- };
46
+ });
47
+ pendingGroups.delete(member.processGroupId);
48
+ }
35
49
  }
36
- catch (cause) {
50
+ else {
51
+ const gone = await processIsGone(host, member.pid);
37
52
  signal?.throwIfAborted();
38
- if (!(await processIsGone(host, member.pid))) {
39
- return {
53
+ if (!gone) {
54
+ observations.set(member.processGroupId, {
40
55
  state: "unverifiable",
41
- reason: `process ownership could not be revalidated for PID ${member.pid}: ${errorMessage(cause)}`,
42
- };
56
+ reason: `process ownership could not be revalidated for PID ${member.pid}: ${observation.reason}`,
57
+ });
58
+ pendingGroups.delete(member.processGroupId);
43
59
  }
44
60
  }
61
+ if (pendingGroups.size === 0)
62
+ break;
45
63
  }
46
- return { state: "alive" };
64
+ signal?.throwIfAborted();
65
+ return observations;
47
66
  };
48
- /** Record the live launcher and descendant lineage after run-token validation. */
49
- export const observeOwnedProcessLineageWithHost = async (ownership, host) => {
67
+ /**
68
+ * Record the live launcher and descendant lineage after run-token validation.
69
+ *
70
+ * The observation is intentionally point-in-time. A verified empty descendant
71
+ * list means no descendants were live during this observation, not that the
72
+ * run never created a short-lived child.
73
+ */
74
+ export const observeOwnedProcessLineage = async (ownership, host = systemProcessOwnershipHost) => {
50
75
  let processes;
51
76
  try {
52
77
  processes = liveProcesses(await host.listProcesses());
@@ -60,23 +85,22 @@ export const observeOwnedProcessLineageWithHost = async (ownership, host) => {
60
85
  const identityFailure = launcherIdentityFailure(launcher, ownership);
61
86
  if (identityFailure !== null)
62
87
  return unavailableLineage(ownership, identityFailure);
63
- const descendants = descendantsOf(launcher.pid, processes);
88
+ const descendants = descendantsOf([launcher.pid], processes);
64
89
  const verifiedDescendants = [];
65
- for (const member of [launcher, ...descendants]) {
66
- try {
67
- if ((await host.environment(member.pid)).REA_PROCESS_RUN_ID !==
68
- ownership.runId)
90
+ for await (const { process: member, observation } of readProcessRunTokens(host, [launcher, ...descendants])) {
91
+ if (observation.state === "readable") {
92
+ if (observation.runId !== ownership.runId)
69
93
  return unavailableLineage(ownership, "process lineage contains an unowned or PID-reused process");
70
94
  if (member.pid !== launcher.pid)
71
95
  verifiedDescendants.push(member);
72
96
  }
73
- catch (cause) {
97
+ else {
74
98
  if (await processIsGone(host, member.pid)) {
75
99
  if (member.pid === launcher.pid)
76
100
  return unavailableLineage(ownership, "owned launcher exited during lineage validation");
77
101
  continue;
78
102
  }
79
- return unavailableLineage(ownership, `process ownership could not be revalidated for PID ${member.pid}: ${errorMessage(cause)}`);
103
+ return unavailableLineage(ownership, `process ownership could not be revalidated for PID ${member.pid}: ${observation.reason}`);
80
104
  }
81
105
  }
82
106
  return {
@@ -245,14 +269,15 @@ export const createSystemProcessOwnershipHost = (platform = process.platform, ho
245
269
  }
246
270
  },
247
271
  listProcesses,
248
- async environment(pid) {
272
+ async environment(pid, signal) {
273
+ signal?.throwIfAborted();
249
274
  if (platform === "linux")
250
- return parseProcessEnvironment(await readFile(`/proc/${pid}/environ`, "utf8"));
275
+ return parseProcessEnvironment(await readFile(`/proc/${pid}/environ`, { encoding: "utf8", signal }));
251
276
  if (platform === "darwin") {
252
- const process = (await listProcesses()).find((entry) => entry.pid === pid);
277
+ const process = (await listProcesses(signal)).find((entry) => entry.pid === pid);
253
278
  if (process === undefined)
254
279
  throw new Error(`process ${String(pid)} is not live`);
255
- const observation = (await darwinTokens?.read([process]))?.get(pid);
280
+ const observation = (await darwinTokens?.read([process], signal))?.get(pid);
256
281
  if (observation === undefined || observation.state === "unavailable")
257
282
  throw new Error(observation?.reason ?? "process run token could not be read");
258
283
  return observation.runId === undefined
@@ -261,6 +286,7 @@ export const createSystemProcessOwnershipHost = (platform = process.platform, ho
261
286
  }
262
287
  const { stdout } = await execFileOutput("ps", ["eww", "-p", String(pid)], {
263
288
  env: hostEnvironment,
289
+ ...(signal === undefined ? {} : { signal }),
264
290
  });
265
291
  const observedEnvironment = {};
266
292
  for (const match of stdout.matchAll(/(?:^|\s)([A-Za-z_][A-Za-z0-9_]*)=([^\s]*)/gu)) {
@@ -270,13 +296,16 @@ export const createSystemProcessOwnershipHost = (platform = process.platform, ho
270
296
  }
271
297
  return observedEnvironment;
272
298
  },
273
- async runTokens(processes) {
299
+ async runTokens(processes, signal) {
300
+ signal?.throwIfAborted();
274
301
  if (platform !== "darwin" || processes.length === 0)
275
302
  return new Map();
276
303
  try {
277
- return (await darwinTokens?.read(processes)) ?? new Map();
304
+ return (await darwinTokens?.read(processes, signal)) ?? new Map();
278
305
  }
279
306
  catch (cause) {
307
+ if (isExpectedAbort(cause, signal))
308
+ throw cause;
280
309
  void cause;
281
310
  return new Map(processes.map(({ pid }) => [
282
311
  pid,
@@ -297,17 +326,51 @@ export const createSystemProcessOwnershipHost = (platform = process.platform, ho
297
326
  };
298
327
  };
299
328
  export const systemProcessOwnershipHost = createSystemProcessOwnershipHost();
300
- /** Observe the current OS start identity for one live PID, when supported. */
301
- export const observeProcessStartIdentity = async (pid, host = systemProcessOwnershipHost) => {
329
+ /**
330
+ * Observe a live PID's start identity, optionally binding it to an owned run.
331
+ * Token validation is bracketed by identity reads so PID reuse cannot supply
332
+ * the first identity of a different process for an owned launch.
333
+ */
334
+ export const observeProcessStartIdentity = async (pid, host = systemProcessOwnershipHost, expectedRunId) => {
302
335
  const process = (await host.listProcesses()).find((entry) => entry.pid === pid);
303
336
  if (process === undefined || liveProcesses([process]).length === 0)
304
337
  return undefined;
305
338
  if (host.processIdentities === undefined)
306
339
  return { state: "unavailable", reason: "process identity is unsupported" };
307
- return ((await host.processIdentities([process])).get(pid) ?? {
340
+ const identity = (await host.processIdentities([process])).get(pid) ?? {
308
341
  state: "unavailable",
309
342
  reason: "process identity was not returned",
310
- });
343
+ };
344
+ if (expectedRunId === undefined || identity.state !== "readable")
345
+ return identity;
346
+ let owned = false;
347
+ for await (const { observation } of readProcessRunTokens(host, [process])) {
348
+ if (observation.state === "unavailable")
349
+ return {
350
+ state: "unavailable",
351
+ reason: `process ownership token could not be read for PID ${String(pid)}: ${observation.reason}`,
352
+ };
353
+ if (observation.runId !== expectedRunId)
354
+ return {
355
+ state: "unavailable",
356
+ reason: `process ownership token did not match the captured run for PID ${String(pid)}`,
357
+ };
358
+ owned = true;
359
+ }
360
+ if (!owned)
361
+ return {
362
+ state: "unavailable",
363
+ reason: `process ownership token was not returned for PID ${String(pid)}`,
364
+ };
365
+ const confirmed = await observeProcessStartIdentity(pid, host);
366
+ if (confirmed === undefined || confirmed.state !== "readable")
367
+ return confirmed;
368
+ return confirmed.identity === identity.identity
369
+ ? identity
370
+ : {
371
+ state: "unavailable",
372
+ reason: `process identity changed while validating the captured run token for PID ${String(pid)}`,
373
+ };
311
374
  };
312
375
  /** Revalidate a launch-time start identity immediately before signaling a PID. */
313
376
  export const signalProcessWithStartIdentity = async (pid, expectedIdentity, signal, options = {}) => {
@@ -331,16 +394,6 @@ export const signalProcessWithStartIdentity = async (pid, expectedIdentity, sign
331
394
  export const prepareProcessOwnershipInspection = async (signal) => {
332
395
  await systemProcessOwnershipHost.prepare?.(signal);
333
396
  };
334
- /** Observe one group without signaling it, failing closed on identity doubt. */
335
- export const observeOwnedProcessGroup = async (ownership, host = systemProcessOwnershipHost, signal) => observeOwnedProcessGroupWithHost(ownership, host, signal);
336
- /**
337
- * Record the live launcher and descendant lineage after run-token validation.
338
- *
339
- * The observation is intentionally point-in-time. A verified empty descendant
340
- * list means no descendants were live during this observation, not that the
341
- * run never created a short-lived child.
342
- */
343
- export const observeOwnedProcessLineage = async (ownership, host = systemProcessOwnershipHost) => observeOwnedProcessLineageWithHost(ownership, host);
344
397
  const processIsGone = async (host, pid) => {
345
398
  try {
346
399
  return !liveProcesses(await host.listProcesses()).some((process) => process.pid === pid);
@@ -1,7 +1,7 @@
1
1
  /** Exclude process-table entries that the operating system has already reaped. */
2
2
  export const liveProcesses = (members) => members.filter(({ state }) => !state.startsWith("Z"));
3
- /** Return every live-table descendant of a launcher in breadth-first order. */
4
- export const descendantsOf = (launcherPid, processes) => {
3
+ /** Return every live-table descendant of the selected roots in breadth-first order. */
4
+ export const descendantsOf = (rootPids, processes) => {
5
5
  const childrenByParent = new Map();
6
6
  for (const process of processes) {
7
7
  const siblings = childrenByParent.get(process.parentPid) ?? [];
@@ -9,8 +9,8 @@ export const descendantsOf = (launcherPid, processes) => {
9
9
  childrenByParent.set(process.parentPid, siblings);
10
10
  }
11
11
  const descendants = [];
12
- const pending = [...(childrenByParent.get(launcherPid) ?? [])];
13
- const visited = new Set([launcherPid]);
12
+ const pending = rootPids.flatMap((pid) => childrenByParent.get(pid) ?? []);
13
+ const visited = new Set(rootPids);
14
14
  for (const process of pending) {
15
15
  if (visited.has(process.pid))
16
16
  continue;