rea-agents 3.2.1 → 4.0.1

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 (434) hide show
  1. package/README.md +183 -332
  2. package/bridge/ghidra/ReaGhidraBridge.java +561 -74
  3. package/bridge/hopper_bridge.py +70 -27
  4. package/bridge/native/ReaNativeUI.swift +157 -0
  5. package/dist/application/AnalysisContextQueries.js +19 -5
  6. package/dist/application/AnalysisSnapshotCache.js +30 -11
  7. package/dist/application/AppleAssetCatalogAnalysis.js +171 -0
  8. package/dist/application/ArtifactExtractionDestination.js +0 -12
  9. package/dist/application/ArtifactGraphConstruction.js +44 -11
  10. package/dist/application/ArtifactInventory/classify.js +7 -15
  11. package/dist/application/ArtifactInventory/hash.js +4 -2
  12. package/dist/application/ArtifactInventory/policy.js +2 -17
  13. package/dist/application/ArtifactInventory/reader.js +3 -3
  14. package/dist/application/ArtifactInventory/scanCanonical.js +2 -2
  15. package/dist/application/ArtifactInventory/scanReader.js +12 -4
  16. package/dist/application/ArtifactInventory/types.js +0 -3
  17. package/dist/application/BinarySession.js +28 -43
  18. package/dist/application/BinarySessionExecution.js +37 -1
  19. package/dist/application/BinaryTargetResolver.js +50 -4
  20. package/dist/application/BrowserEvidence.js +36 -7
  21. package/dist/application/BrowserObservationService.js +17 -44
  22. package/dist/application/BrowserScenarioCaptureService.js +2 -35
  23. package/dist/application/BrowserScenarioEvidence.js +13 -9
  24. package/dist/application/CapabilityClientRequirements.js +2 -11
  25. package/dist/application/CapabilityInventory.js +21 -35
  26. package/dist/application/ClientConfigurationDocument.js +84 -7
  27. package/dist/application/ClientRegistrationIdentity.js +32 -0
  28. package/dist/application/ClientRegistrationStatus.js +59 -6
  29. package/dist/application/DirectAnalysis.js +37 -58
  30. package/dist/application/DirectAnalysisStatus.js +4 -4
  31. package/dist/application/Doctor.js +89 -80
  32. package/dist/application/DoctorDiagnostics.js +2 -26
  33. package/dist/application/DoctorScope.js +8 -14
  34. package/dist/application/ElectronActiveEvidence.js +10 -27
  35. package/dist/application/ElectronActiveObservationService.js +9 -36
  36. package/dist/application/ElectronBoundaryAnalysis.js +2 -0
  37. package/dist/application/ElectronBoundaryGraphNative.js +1 -1
  38. package/dist/application/ElectronEvidence.js +8 -3
  39. package/dist/application/ElectronObservationService.js +9 -25
  40. package/dist/application/EnhancedLiteralTracing.js +4 -8
  41. package/dist/application/EnhancedTools.js +15 -35
  42. package/dist/application/FilesystemSnapshot.js +7 -8
  43. package/dist/application/JavaScriptApplicationEvidenceGraph.js +2 -1
  44. package/dist/application/JavaScriptApplicationWorkflowService.js +31 -7
  45. package/dist/application/JavaScriptArtifactAnalysis.js +6 -4
  46. package/dist/application/JavaScriptArtifactFiles.js +5 -0
  47. package/dist/application/JavaScriptArtifactPathResolution.js +179 -47
  48. package/dist/application/JavaScriptRuntimeObservationEvidence.js +6 -3
  49. package/dist/application/JavaScriptRuntimeObservationService.js +9 -25
  50. package/dist/application/JavaScriptRuntimeReconciliationService.js +45 -4
  51. package/dist/application/JavaScriptSemanticGraphAsyncProjection.js +11 -0
  52. package/dist/application/JavaScriptSemanticGraphChildProcessProjection.js +11 -0
  53. package/dist/application/JavaScriptSemanticGraphDataProjection.js +11 -0
  54. package/dist/application/JavaScriptSemanticGraphFlowProjection.js +14 -5
  55. package/dist/application/JsonFiles.js +1 -1
  56. package/dist/application/LazyAnalysisProvider.js +27 -6
  57. package/dist/application/ManagedMemberComparisonService.js +19 -6
  58. package/dist/application/NativeApiInspection.js +2 -0
  59. package/dist/application/NativeCallRoutes.js +72 -0
  60. package/dist/application/NativeDispatchMetadataInspection.js +33 -0
  61. package/dist/application/NativeUiActionTrace.js +73 -49
  62. package/dist/application/NativeValueTrace.js +320 -0
  63. package/dist/application/ProcessCaptureCapability.js +32 -5
  64. package/dist/application/ProcessCaptureEnvironment.js +9 -26
  65. package/dist/application/ProcessCaptureError.js +1 -5
  66. package/dist/application/ProcessCaptureJournal.js +3 -40
  67. package/dist/application/ProcessCaptureLifecycle.js +102 -111
  68. package/dist/application/ProcessCli.js +18 -25
  69. package/dist/application/ProcessEvidence.js +5 -7
  70. package/dist/application/ProcessFilesystemEffects.js +36 -0
  71. package/dist/application/ProcessHarness.js +41 -120
  72. package/dist/application/ProcessNormalization.js +2 -17
  73. package/dist/application/ProcessScenarioRuntimeValidation.js +76 -0
  74. package/dist/application/ReferenceSourceImport.js +3 -4
  75. package/dist/application/Setup.js +236 -84
  76. package/dist/application/SetupClientConfiguration.js +14 -9
  77. package/dist/application/SetupPlan.js +138 -86
  78. package/dist/application/SetupSkill.js +0 -1
  79. package/dist/application/SupportedClients.js +102 -21
  80. package/dist/application/Uninstall.js +31 -20
  81. package/dist/application/Update.js +93 -0
  82. package/dist/application/UpdateMaintenance.js +108 -0
  83. package/dist/application/UpdateRuntime.js +126 -0
  84. package/dist/application/runtime.js +13 -2
  85. package/dist/artifacts/ArtifactPaths.js +6 -8
  86. package/dist/artifacts/ArtifactProvider.js +94 -41
  87. package/dist/artifacts/AsarArtifactReader.js +19 -4
  88. package/dist/artifacts/KeyedArchiveReader.js +110 -0
  89. package/dist/artifacts/MachOSliceArtifactReader.js +53 -5
  90. package/dist/artifacts/ZipArtifactReader.js +18 -1
  91. package/dist/browser/BrowserScenarioSecrets.js +28 -1
  92. package/dist/browser/CdpBrowserProvider.js +36 -15
  93. package/dist/browser/CdpCaptureDocuments.js +22 -8
  94. package/dist/browser/CdpCaptureEventHandlers.js +14 -5
  95. package/dist/browser/CdpCaptureEventHelpers.js +13 -0
  96. package/dist/browser/CdpCaptureEvents.js +10 -1
  97. package/dist/browser/CdpElectronInspection.js +5 -10
  98. package/dist/browser/CdpElectronProvider.js +1 -5
  99. package/dist/browser/CdpElectronScripts.js +1 -1
  100. package/dist/browser/CdpEndpoint.js +3 -2
  101. package/dist/browser/CdpObservationSession.js +14 -10
  102. package/dist/browser/CdpPageCapture.js +1 -1
  103. package/dist/browser/CdpPageCaptureScripts.js +1 -1
  104. package/dist/browser/CdpSafeMetadata.js +5 -4
  105. package/dist/browser/CdpScreenshot.js +16 -5
  106. package/dist/browser/CdpTargetSession.js +25 -4
  107. package/dist/browser/CdpWebMcpDiscovery.js +93 -20
  108. package/dist/browser/JavaScriptRuntimeScope.js +28 -2
  109. package/dist/browser/PlaywrightBrowserScenarioProvider.js +9 -8
  110. package/dist/browser/PlaywrightElectronActiveActions.js +3 -10
  111. package/dist/browser/PlaywrightElectronActiveProvider.js +5 -5
  112. package/dist/browser/PlaywrightScenarioActions.js +1 -1
  113. package/dist/browser/PlaywrightScenarioArtifacts.js +13 -25
  114. package/dist/browser/PlaywrightScenarioBrowser.js +28 -25
  115. package/dist/browser/PlaywrightScenarioEvents.js +82 -93
  116. package/dist/browser/PlaywrightScenarioSession.js +27 -123
  117. package/dist/browser/PngVisualDiff.js +22 -3
  118. package/dist/browser/V8InspectorCaptureProjection.js +7 -1
  119. package/dist/browser/V8InspectorProvider.js +60 -7
  120. package/dist/browser/WebSourceMapFetcher.js +99 -53
  121. package/dist/cli/artifactCommands.js +56 -12
  122. package/dist/cli/coreAnalysisCommands.js +110 -0
  123. package/dist/cli/managedCommands.js +1 -31
  124. package/dist/cli/setupCommands.js +16 -14
  125. package/dist/cli/utilityCommands.js +61 -4
  126. package/dist/cli.js +5 -7
  127. package/dist/cliApplicationCommands.js +0 -83
  128. package/dist/cliBrowserAdvancedCommands.js +7 -11
  129. package/dist/cliBrowserCommands.js +15 -23
  130. package/dist/cliBrowserContext.js +3 -24
  131. package/dist/cliBrowserScenarioCommands.js +2 -10
  132. package/dist/cliCommandNames.js +82 -7
  133. package/dist/cliElectronCommands.js +10 -36
  134. package/dist/cliJavaScriptRuntimeCommands.js +6 -30
  135. package/dist/cliJsonInput.js +4 -2
  136. package/dist/cliLogging.js +16 -7
  137. package/dist/cliObservationOptions.js +1 -1
  138. package/dist/cliOutput.js +2 -4
  139. package/dist/cliProcessCommands.js +6 -33
  140. package/dist/cliSetup.js +90 -160
  141. package/dist/config/environment.js +2 -78
  142. package/dist/config/parseConfig.js +18 -109
  143. package/dist/config/parsers.js +0 -23
  144. package/dist/contracts/applicationToolContracts.js +1 -118
  145. package/dist/contracts/artifactToolContracts.js +11 -19
  146. package/dist/contracts/browserScenarioToolContracts.js +1 -5
  147. package/dist/contracts/browserToolContracts.js +9 -16
  148. package/dist/contracts/electronToolContracts.js +5 -6
  149. package/dist/contracts/enhancedInputs.js +3 -2
  150. package/dist/contracts/errorSchemas.js +16 -40
  151. package/dist/contracts/functionWorkflowToolContracts.js +2 -2
  152. package/dist/contracts/javascriptApplicationWorkflowExamples.js +2 -2
  153. package/dist/contracts/javascriptRuntimeObservationToolContracts.js +4 -4
  154. package/dist/contracts/javascriptRuntimeReconciliationExample.js +1 -1
  155. package/dist/contracts/managedToolContracts.js +7 -4
  156. package/dist/contracts/managedWorkflowExamples.js +0 -22
  157. package/dist/contracts/managedWorkflowToolContracts.js +16 -31
  158. package/dist/contracts/nativeToolContracts.js +9 -0
  159. package/dist/contracts/promptContracts.js +6 -6
  160. package/dist/contracts/sessionToolSchemas.js +3 -3
  161. package/dist/contracts/toolContractExamples.js +4 -3
  162. package/dist/contracts/toolContracts.js +18 -7
  163. package/dist/contracts/toolEffects.js +34 -21
  164. package/dist/contracts/toolOutputSchemaGroups.js +18 -5
  165. package/dist/contracts/toolOutputSchemaPrimitives.js +9 -6
  166. package/dist/contracts/toolSchemaMetadata.js +5 -8
  167. package/dist/doctorRuntime.js +0 -41
  168. package/dist/domain/analysisErrorPresentation.js +4 -28
  169. package/dist/domain/analysisErrorProjection.js +33 -50
  170. package/dist/domain/analysisProfile.js +1 -1
  171. package/dist/domain/analysisSnapshot.js +77 -3
  172. package/dist/domain/androidApplication.js +5 -4
  173. package/dist/domain/appleApplication.js +5 -4
  174. package/dist/domain/appleAssetCatalog.js +127 -0
  175. package/dist/domain/artifactComparison.js +7 -11
  176. package/dist/domain/artifactGraph.js +8 -6
  177. package/dist/domain/artifactInspection.js +13 -12
  178. package/dist/domain/binaryTarget.js +23 -9
  179. package/dist/domain/browserObservation.js +43 -24
  180. package/dist/domain/browserObservationSchemas.js +2 -1
  181. package/dist/domain/browserScenario.js +7 -107
  182. package/dist/domain/browserScenarioCapture.js +0 -1
  183. package/dist/domain/browserScenarioCaptureValues.js +5 -4
  184. package/dist/domain/browserScenarioDiff.js +1 -3
  185. package/dist/domain/browserScenarioValues.js +16 -107
  186. package/dist/domain/bundleComparison.js +18 -17
  187. package/dist/domain/callPathSchemas.js +17 -7
  188. package/dist/domain/changedBehavior.js +2 -3
  189. package/dist/domain/comparisonSemantics.js +19 -0
  190. package/dist/domain/completionLedgerGeneration.js +3 -2
  191. package/dist/domain/conformancePackage.js +2 -1
  192. package/dist/domain/conformanceTrustGate.js +3 -5
  193. package/dist/domain/customProtocolCapture.js +2 -2
  194. package/dist/domain/digests.js +30 -0
  195. package/dist/domain/dosMz.js +83 -0
  196. package/dist/domain/electronActiveObservation.js +7 -5
  197. package/dist/domain/electronObservation.js +3 -2
  198. package/dist/domain/electronStaticAnalysisNative.js +15 -6
  199. package/dist/domain/emptyArraySchema.js +3 -0
  200. package/dist/domain/errors.js +10 -28
  201. package/dist/domain/evidence.js +5 -3
  202. package/dist/domain/evidenceCompletionLedger.js +3 -2
  203. package/dist/domain/functionComparisonNormalization.js +24 -18
  204. package/dist/domain/functionComparisonResults.js +3 -7
  205. package/dist/domain/functionComparisonSchemas.js +3 -2
  206. package/dist/domain/hopperValues.js +108 -8
  207. package/dist/domain/javascriptApplicationAnalysis.js +4 -7
  208. package/dist/domain/javascriptApplicationEvidenceSchemas.js +4 -3
  209. package/dist/domain/javascriptApplicationGraphSchemas.js +8 -7
  210. package/dist/domain/javascriptApplicationVersionComparisonSchemas.js +9 -7
  211. package/dist/domain/javascriptApplicationVersionItems.js +12 -18
  212. package/dist/domain/javascriptAstValues.js +4 -0
  213. package/dist/domain/javascriptExportShapeComparison.js +1 -6
  214. package/dist/domain/javascriptExportShapeComparisonSchemas.js +6 -10
  215. package/dist/domain/javascriptExportShapeVariants.js +15 -2
  216. package/dist/domain/javascriptFeatureTraceSchemas.js +8 -7
  217. package/dist/domain/javascriptRuntimeObservation.js +14 -2
  218. package/dist/domain/javascriptRuntimeReconciliationMatching.js +8 -0
  219. package/dist/domain/javascriptRuntimeReconciliationParsing.js +4 -2
  220. package/dist/domain/javascriptRuntimeReconciliationResult.js +6 -4
  221. package/dist/domain/javascriptRuntimeReconciliationRuntime.js +15 -4
  222. package/dist/domain/javascriptRuntimeReconciliationSchemas.js +19 -18
  223. package/dist/domain/javascriptRuntimeStaticCandidates.js +18 -6
  224. package/dist/domain/javascriptSemanticAnalysis.js +57 -19
  225. package/dist/domain/javascriptSemanticAsyncEffects.js +39 -40
  226. package/dist/domain/javascriptSemanticCalls.js +46 -27
  227. package/dist/domain/javascriptSemanticChildProcesses.js +43 -50
  228. package/dist/domain/javascriptSemanticDataEffectHelpers.js +91 -18
  229. package/dist/domain/javascriptSemanticDataEffects.js +22 -10
  230. package/dist/domain/javascriptSemanticGraphSchemas.js +8 -6
  231. package/dist/domain/javascriptSemanticObjects.js +13 -3
  232. package/dist/domain/javascriptSemanticProjection.js +144 -38
  233. package/dist/domain/javascriptSemanticPromises.js +14 -27
  234. package/dist/domain/javascriptSemanticQuerySchemas.js +6 -9
  235. package/dist/domain/javascriptSemanticResources.js +2 -5
  236. package/dist/domain/javascriptSemanticState.js +4 -0
  237. package/dist/domain/javascriptSemanticTraceSchemas.js +2 -1
  238. package/dist/domain/javascriptSemanticTraversal.js +13 -5
  239. package/dist/domain/javascriptSemanticValues.js +10 -9
  240. package/dist/domain/javascriptSourceParser.js +5 -1
  241. package/dist/domain/javascriptStaticAnalysisCalls.js +8 -5
  242. package/dist/domain/javascriptStaticAnalysisHelpers.js +16 -7
  243. package/dist/domain/keyedArchive.js +181 -0
  244. package/dist/domain/managedApplicationGraph.js +4 -3
  245. package/dist/domain/managedArtifact.js +2 -1
  246. package/dist/domain/managedMemberComparison.js +18 -13
  247. package/dist/domain/managedMemberComparisonCoverage.js +2 -1
  248. package/dist/domain/managedMemberComparisonItems.js +27 -7
  249. package/dist/domain/managedMemberComparisonMatch.js +22 -6
  250. package/dist/domain/managedNativeVerificationMatch.js +2 -2
  251. package/dist/domain/managedNativeVerificationSchemas.js +7 -5
  252. package/dist/domain/managedReconstruction.js +6 -5
  253. package/dist/domain/nativeApiBoundary.js +7 -0
  254. package/dist/domain/nativeDataType.js +51 -0
  255. package/dist/domain/nativeInspection.js +0 -1
  256. package/dist/domain/nativeInstruction.js +82 -0
  257. package/dist/domain/nativeInvestigationGraph.js +9 -5
  258. package/dist/domain/nativeUiObservation.js +123 -0
  259. package/dist/domain/nativeValueFlow.js +17 -0
  260. package/dist/domain/nativeValueTrace.js +64 -0
  261. package/dist/domain/objcSwiftMetadata.js +39 -0
  262. package/dist/domain/peInspection.js +1 -0
  263. package/dist/domain/processCapture.js +5 -55
  264. package/dist/domain/processCaptureExample.js +0 -9
  265. package/dist/domain/processCaptureValidation.js +13 -144
  266. package/dist/domain/processComparison.js +3 -25
  267. package/dist/domain/processObservation.js +0 -29
  268. package/dist/domain/processScenario.js +28 -228
  269. package/dist/domain/processTraceDimensionProjection.js +0 -15
  270. package/dist/domain/processTraceEvaluation.js +0 -6
  271. package/dist/domain/protocolCapture.js +8 -36
  272. package/dist/domain/reconstructionCoverage.js +3 -2
  273. package/dist/domain/reconstructionObligationLedgerSchemas.js +4 -12
  274. package/dist/domain/reconstructionReadinessSchemas.js +4 -3
  275. package/dist/domain/reconstructionVerification.js +2 -1
  276. package/dist/domain/reconstructionVerificationSchemas.js +6 -13
  277. package/dist/domain/referenceSourceClassification.js +0 -110
  278. package/dist/domain/referenceSourceGraph.js +15 -5
  279. package/dist/domain/residualUnknown.js +3 -2
  280. package/dist/domain/runtimeIdentification.js +6 -5
  281. package/dist/domain/sourceMapContents.js +5 -0
  282. package/dist/domain/sourceToBundleComparison.js +3 -10
  283. package/dist/domain/sourceToBundleComparisonSchemas.js +7 -6
  284. package/dist/domain/sourceToBundleSignals.js +9 -3
  285. package/dist/domain/staticRuntimeCorrelation.js +5 -11
  286. package/dist/domain/webBundleAnalysis.js +17 -9
  287. package/dist/domain/webBundleAnalyzer.js +1 -1
  288. package/dist/domain/webCaptureDiff.js +5 -11
  289. package/dist/domain/webCaptureDiffSchemas.js +2 -1
  290. package/dist/domain/webMcpDiscovery.js +2 -1
  291. package/dist/dotnet/ManagedMemberInspectorCore.js +15 -7
  292. package/dist/dotnet/ManagedMemberInstructionDecoder.js +57 -40
  293. package/dist/dotnet/ManagedMemberRows.js +2 -0
  294. package/dist/dotnet/ManagedMethodBodyReader.js +15 -8
  295. package/dist/dotnet/ManagedPeReader.js +2 -0
  296. package/dist/generatedMcpToolCatalog.js +1 -1
  297. package/dist/generatedPackageMetadata.js +2 -2
  298. package/dist/ghidra/GhidraAnalysisProfile.js +15 -5
  299. package/dist/ghidra/GhidraClient.js +38 -8
  300. package/dist/ghidra/GhidraFunctionValues.js +56 -20
  301. package/dist/ghidra/GhidraInstallation.js +7 -4
  302. package/dist/ghidra/GhidraInventoryValues.js +44 -9
  303. package/dist/ghidra/GhidraLauncher.js +18 -3
  304. package/dist/ghidra/GhidraProvider.js +23 -2
  305. package/dist/ghidra/GhidraRequestQueue.js +45 -4
  306. package/dist/ghidra/GhidraSessionValues.js +5 -0
  307. package/dist/hopper/HopperAnalysisProfile.js +2 -0
  308. package/dist/hopper/HopperProvider.js +29 -6
  309. package/dist/hopper/HopperTargetLease.js +18 -4
  310. package/dist/logger.js +0 -13
  311. package/dist/main/messages.js +0 -1
  312. package/dist/main/reload.js +3 -32
  313. package/dist/main/shutdown.js +1 -2
  314. package/dist/main/transport.js +0 -17
  315. package/dist/main.js +0 -10
  316. package/dist/native/AppleDispatchMetadata.js +582 -0
  317. package/dist/native/AppleObjcProtocols.js +88 -0
  318. package/dist/native/AppleSwiftVtables.js +86 -0
  319. package/dist/native/CommandRunner.js +1 -1
  320. package/dist/native/NativeHostCapabilities.js +23 -0
  321. package/dist/native/NativeMacOSProvider.js +61 -9
  322. package/dist/native/NativeMachoInspection.js +39 -6
  323. package/dist/native/NativeUiHelperRuntime.js +42 -0
  324. package/dist/native/NativeUiObservation.js +174 -0
  325. package/dist/native/parsers/codesign.js +4 -1
  326. package/dist/native/parsers/dyldInfo.js +51 -25
  327. package/dist/native/parsers/lipo.js +13 -4
  328. package/dist/native/parsers/otool.js +84 -39
  329. package/dist/native/parsers/plist.js +2 -1
  330. package/dist/process/ExecFileOutput.js +5 -1
  331. package/dist/process/ProcessOwnership.js +69 -33
  332. package/dist/process/ProcessOwnershipObservation.js +31 -12
  333. package/dist/process/ProviderProcess.js +4 -2
  334. package/dist/reference/ReferenceSourceReaderEntries.js +48 -31
  335. package/dist/reference/ReferenceSourceReaderErrors.js +24 -0
  336. package/dist/reference/ReferenceSourceReaderFile.js +11 -5
  337. package/dist/reference/ReferenceSourceReaderValidate.js +22 -8
  338. package/dist/server/createServer.js +7 -62
  339. package/dist/server/registerApplicationTools/helpers.js +2 -9
  340. package/dist/server/registerApplicationTools.js +0 -4
  341. package/dist/server/registerArtifactComparisonTool.js +1 -1
  342. package/dist/server/registerBrowserScenarioTool.js +4 -2
  343. package/dist/server/registerBrowserTools.js +7 -7
  344. package/dist/server/registerBundleComparisonTool.js +1 -1
  345. package/dist/server/registerCloseLifecycleTool.js +1 -1
  346. package/dist/server/registerElectronTools.js +10 -4
  347. package/dist/server/registerEnhancedTools.js +20 -12
  348. package/dist/server/registerEvidenceTools.js +4 -28
  349. package/dist/server/registerFunctionComparisonTool.js +1 -1
  350. package/dist/server/registerInvestigationTools.js +6 -6
  351. package/dist/server/registerJavaScriptRuntimeObservationTools.js +2 -2
  352. package/dist/server/registerManagedTools.js +28 -14
  353. package/dist/server/registerManagedWorkflowTools.js +0 -2
  354. package/dist/server/registerProcessComparisonTool.js +1 -3
  355. package/dist/server/registerSessionRecordTools.js +9 -9
  356. package/dist/server/registerSessionStatusTool.js +1 -1
  357. package/dist/server/registerSessionTools.js +28 -57
  358. package/dist/server/sessionAvailabilityPolicy.js +2 -3
  359. package/dist/server/sessionToolPolicies.js +0 -4
  360. package/dist/server/toolResult.js +8 -10
  361. package/package.json +32 -22
  362. package/skills/reverse-engineer-anything/SKILL.md +15 -11
  363. package/skills/reverse-engineer-anything/references/evidence-workflows.md +3 -2
  364. package/skills/reverse-engineer-anything/references/javascript-applications.md +3 -2
  365. package/skills/reverse-engineer-anything/references/native-and-artifacts.md +8 -6
  366. package/skills/reverse-engineer-anything/references/runtime-observation.md +15 -11
  367. package/dist/application/CommandShimReplay.js +0 -152
  368. package/dist/application/ConfiguredRoots.js +0 -19
  369. package/dist/application/InstrumentedJavaScriptReplayHost.js +0 -36
  370. package/dist/application/JavaScriptReplayPermission.js +0 -16
  371. package/dist/application/JavaScriptReplayPlanning.js +0 -207
  372. package/dist/application/JavaScriptReplayService.js +0 -274
  373. package/dist/application/LoopbackReplay.js +0 -389
  374. package/dist/application/LoopbackReplayRecorder.js +0 -129
  375. package/dist/application/ManagedRuntimeCorrelationService.js +0 -104
  376. package/dist/application/NodeRuntimeCharacterizationService.js +0 -191
  377. package/dist/application/PermissionAuthority.js +0 -268
  378. package/dist/application/PermissionConfiguration.js +0 -26
  379. package/dist/application/PermissionFailure.js +0 -5
  380. package/dist/application/ProcessCaptureAuthority.js +0 -24
  381. package/dist/application/ProcessCapturePermission.js +0 -13
  382. package/dist/application/ProcessCheckpoints.js +0 -178
  383. package/dist/application/ProcessReactiveCoordinator.js +0 -223
  384. package/dist/application/ProcessReactiveEffects.js +0 -153
  385. package/dist/application/ProcessReactiveHarness.js +0 -106
  386. package/dist/application/ProcessReactiveObservations.js +0 -105
  387. package/dist/application/ProjectPermissionStore.js +0 -199
  388. package/dist/application/RuntimeExecutableDiagnostics.js +0 -198
  389. package/dist/application/Upgrade.js +0 -134
  390. package/dist/browser/SensitiveTextCapture.js +0 -8
  391. package/dist/cliPolicyCommands.js +0 -185
  392. package/dist/config/browserScenario.js +0 -77
  393. package/dist/config/electronAutomation.js +0 -35
  394. package/dist/config/javascriptReplay.js +0 -41
  395. package/dist/config/managedRuntime.js +0 -25
  396. package/dist/config/passiveObservation.js +0 -87
  397. package/dist/config/permissions.js +0 -23
  398. package/dist/config/processCapture.js +0 -47
  399. package/dist/contracts/replayMachineExample.js +0 -37
  400. package/dist/domain/javascriptExportInstrumentation.js +0 -95
  401. package/dist/domain/javascriptReplay.js +0 -360
  402. package/dist/domain/managedRuntimeCorrelation.js +0 -181
  403. package/dist/domain/nodeRuntimeCharacterization.js +0 -63
  404. package/dist/domain/permissionPolicy.js +0 -176
  405. package/dist/domain/processCaptureReactiveSchema.js +0 -68
  406. package/dist/domain/processCaptureReactiveValidation.js +0 -180
  407. package/dist/domain/processReactiveCheckpointDataflow.js +0 -32
  408. package/dist/domain/processReactiveMatching.js +0 -196
  409. package/dist/domain/processReactiveRuntime.js +0 -116
  410. package/dist/domain/processReactiveScenario.js +0 -296
  411. package/dist/domain/processReactiveScenarioPreflight.js +0 -95
  412. package/dist/domain/processReactiveTransition.js +0 -187
  413. package/dist/domain/replayMachine.js +0 -320
  414. package/dist/domain/replayMachineRun.js +0 -168
  415. package/dist/domain/replayMachineRuntime.js +0 -296
  416. package/dist/domain/replayMachineValues.js +0 -84
  417. package/dist/domain/runtimeCharacterization.js +0 -84
  418. package/dist/replay/JavaScriptReplayWorker.js +0 -382
  419. package/dist/replay/JavaScriptReplayWorkerTypes.js +0 -1
  420. package/dist/replay/LinuxJavaScriptReplayRunner.js +0 -216
  421. package/dist/replay/LinuxJavaScriptReplaySandbox.js +0 -121
  422. package/dist/replay/LinuxRuntimeClosure.js +0 -44
  423. package/dist/replay/LinuxSeccompPolicy.js +0 -40
  424. package/dist/replay/ReplayOutcome.js +0 -104
  425. package/dist/replay/ReplayProcessLifecycle.js +0 -96
  426. package/dist/replay/ReplaySeccompFile.js +0 -29
  427. package/dist/replay/ReplayWorkerProtocol.js +0 -58
  428. package/dist/replay/SystemJavaScriptReplayHost.js +0 -153
  429. package/dist/server/ProcessCaptureElicitation.js +0 -153
  430. package/dist/server/registerApplicationTools/characterization.js +0 -46
  431. package/dist/server/registerApplicationTools/controlledReplay.js +0 -31
  432. package/dist/server/registerManagedWorkflowTools/planManagedRuntimeCorrelation.js +0 -29
  433. package/dist/server/registerReplayMachineTool.js +0 -14
  434. package/skills/reverse-engineer-anything/references/controlled-replay.md +0 -12
@@ -52,7 +52,7 @@ export const parseLipoArchitectures = (output) => {
52
52
  return architectures;
53
53
  };
54
54
  const integer = (value) => {
55
- if (value === undefined)
55
+ if (value === undefined || !/^\d+$/u.test(value))
56
56
  return null;
57
57
  const parsed = Number.parseInt(value, 10);
58
58
  return Number.isSafeInteger(parsed) && parsed >= 0 ? parsed : null;
@@ -60,8 +60,17 @@ const integer = (value) => {
60
60
  const alignment = (value) => {
61
61
  if (value === undefined)
62
62
  return null;
63
- const exponent = /2\^(\d+)/u.exec(value)?.[1];
64
- if (exponent !== undefined)
65
- return 2 ** Number.parseInt(exponent, 10);
63
+ const exponent = /^2\^(\d+)(?: \((\d+)\))?$/u.exec(value);
64
+ const powerText = exponent?.[1];
65
+ if (powerText !== undefined) {
66
+ const power = Number.parseInt(powerText, 10);
67
+ if (power > 52)
68
+ return null;
69
+ const alignment = 2 ** power;
70
+ const reported = exponent?.[2];
71
+ return reported === undefined || integer(reported) === alignment
72
+ ? alignment
73
+ : null;
74
+ }
66
75
  return integer(value);
67
76
  };
@@ -1,11 +1,20 @@
1
+ /**
2
+ * otool emits LF, but a capture replayed from another host or toolchain can
3
+ * carry CRLF. The section/command boundaries below match a bare `\n`, so a
4
+ * stray `\r` would swallow the terminator and silently empty `sections` while
5
+ * leaking section fields into the command. Normalizing once at the boundary
6
+ * keeps every parser below working on one line ending.
7
+ */
8
+ const normalizeLineEndings = (output) => output.replaceAll("\r\n", "\n");
1
9
  /** Parse stable fields from `otool -l`, preserving unknown command fields. */
2
- export const parseOtoolLoadCommands = (output) => {
3
- const headerTokens = parseHeaderTokens(output);
4
- const state = createLoadCommandState(headerTokens);
10
+ export const parseOtoolLoadCommands = (raw) => {
11
+ const output = normalizeLineEndings(raw);
12
+ const header = parseHeader(output);
13
+ const state = createLoadCommandState(header?.flags);
5
14
  for (const block of output.split(/(?=Load command \d+)/u))
6
15
  parseLoadCommand(block, state);
7
16
  return {
8
- fileType: headerTokens?.[4] ?? null,
17
+ fileType: header?.fileType ?? null,
9
18
  flags: [...state.flags].sort(),
10
19
  uuid: state.uuid,
11
20
  commands: state.commands,
@@ -15,19 +24,42 @@ export const parseOtoolLoadCommands = (output) => {
15
24
  builds: state.builds,
16
25
  };
17
26
  };
18
- const parseHeaderTokens = (output) => output
19
- .split(/\r?\n/u)
20
- .map((line) => line.trim())
21
- .find((line) => /^0x[a-fA-F0-9]+\s/u.test(line))
22
- ?.split(/\s+/u);
23
- const createLoadCommandState = (headerTokens) => ({
27
+ const parseHeader = (output) => {
28
+ const lines = output.split(/\r?\n/u).map((line) => line.trim());
29
+ const columnsLine = lines.findIndex((line) => /(?:^|\s)magic\s/u.test(line));
30
+ if (columnsLine < 0)
31
+ return undefined;
32
+ const columns = lines[columnsLine]?.split(/\s+/u);
33
+ const dataLine = lines.slice(columnsLine + 1).find((line) => line.length > 0);
34
+ const values = dataLine?.split(/\s+/u);
35
+ if (columns === undefined || values === undefined)
36
+ return undefined;
37
+ const fileTypeIndex = columns.indexOf("filetype");
38
+ const flagsIndex = columns.indexOf("flags");
39
+ const complete = values.length >= columns.length;
40
+ const fileTypeValueIndex = flagsIndex >= 0 && fileTypeIndex > flagsIndex
41
+ ? values.length - (columns.length - fileTypeIndex)
42
+ : fileTypeIndex;
43
+ const flagsEnd = flagsIndex >= 0 ? values.length - (columns.length - flagsIndex - 1) : 0;
44
+ return {
45
+ fileType: complete && fileTypeValueIndex >= 0 && fileTypeValueIndex < values.length
46
+ ? (values[fileTypeValueIndex] ?? null)
47
+ : null,
48
+ flags: !complete || flagsIndex < 0 || flagsIndex >= flagsEnd
49
+ ? []
50
+ : values
51
+ .slice(flagsIndex, flagsEnd)
52
+ .filter((value) => value.length > 0),
53
+ };
54
+ };
55
+ const createLoadCommandState = (headerFlags) => ({
24
56
  commands: [],
25
57
  segments: [],
26
58
  dependencies: [],
27
59
  entrypoints: [],
28
60
  builds: [],
29
61
  uuid: null,
30
- flags: new Set(headerTokens?.slice(7) ?? []),
62
+ flags: new Set(headerFlags ?? []),
31
63
  });
32
64
  const parseLoadCommand = (block, state) => {
33
65
  const indexText = /^Load command (\d+)/u.exec(block)?.[1];
@@ -39,7 +71,6 @@ const parseLoadCommand = (block, state) => {
39
71
  state.commands.push({
40
72
  index: Number.parseInt(indexText, 10),
41
73
  kind,
42
- file_offset: null,
43
74
  fields,
44
75
  });
45
76
  collectUuid(kind, fields, state);
@@ -47,7 +78,6 @@ const parseLoadCommand = (block, state) => {
47
78
  collectBuild(kind, block, fields, state);
48
79
  collectDependency(kind, fields, state);
49
80
  collectSegment(kind, block, fields, state);
50
- collectFlags(fields, state.flags);
51
81
  };
52
82
  const collectUuid = (kind, fields, state) => {
53
83
  if (kind === "LC_UUID")
@@ -61,17 +91,28 @@ const collectEntrypoint = (kind, fields, state) => {
61
91
  state.entrypoints.push({ file_offset: entry });
62
92
  };
63
93
  const collectBuild = (kind, block, fields, state) => {
64
- if (kind !== "LC_BUILD_VERSION")
94
+ if (kind === "LC_BUILD_VERSION") {
95
+ state.builds.push({
96
+ platform: stringField(fields, "platform"),
97
+ minimum_os: stringField(fields, "minos"),
98
+ sdk: stringField(fields, "sdk"),
99
+ tools: parseBuildTools(block),
100
+ });
65
101
  return;
66
- state.builds.push({
67
- platform: stringField(fields, "platform"),
68
- minimum_os: stringField(fields, "minos"),
69
- sdk: stringField(fields, "sdk"),
70
- tools: parseBuildTools(block),
71
- });
102
+ }
103
+ if (kind.startsWith("LC_VERSION_MIN_"))
104
+ state.builds.push({
105
+ platform: kind.slice("LC_VERSION_MIN_".length) || null,
106
+ minimum_os: stringField(fields, "version"),
107
+ sdk: stringField(fields, "sdk"),
108
+ tools: [],
109
+ });
72
110
  };
73
111
  const collectDependency = (kind, fields, state) => {
74
- if (!kind.startsWith("LC_LOAD_") && kind !== "LC_ID_DYLIB")
112
+ if (!kind.startsWith("LC_LOAD_") &&
113
+ kind !== "LC_ID_DYLIB" &&
114
+ kind !== "LC_REEXPORT_DYLIB" &&
115
+ kind !== "LC_LAZY_LOAD_DYLIB")
75
116
  return;
76
117
  state.dependencies.push({
77
118
  path: stripOffsetSuffix(stringField(fields, "name")),
@@ -84,19 +125,15 @@ const collectSegment = (kind, block, fields, state) => {
84
125
  if (kind === "LC_SEGMENT" || kind === "LC_SEGMENT_64")
85
126
  state.segments.push(parseSegment(block, fields));
86
127
  };
87
- const collectFlags = (fields, flags) => {
88
- const rawFlags = stringField(fields, "flags");
89
- if (rawFlags === null)
90
- return;
91
- for (const flag of rawFlags.split(/\s+/u))
92
- if (flag.length > 0)
93
- flags.add(flag);
94
- };
95
128
  const parseFields = (block) => {
96
129
  const fields = {};
97
130
  for (const rawLine of block.split(/\r?\n/u).slice(1)) {
98
131
  const line = rawLine.trim();
99
- const match = /^(\S+(?:\s+version)?)\s+(.+)$/u.exec(line);
132
+ // Keys are `token` or a compound `token version`. `time stamp` is the one
133
+ // other real key, and it must be matched as a whole: treating `stamp` as a
134
+ // generic suffix would swallow an install name such as
135
+ // `name stamp plugin.dylib`, hiding the dependency path behind `unknown`.
136
+ const match = /^((?:time stamp)|\S+(?:\s+version)?)\s+(.+)$/u.exec(line);
100
137
  if (match?.[1] === undefined || match[2] === undefined)
101
138
  continue;
102
139
  const value = match[2].trim();
@@ -125,7 +162,7 @@ const parseSections = (block) => block
125
162
  address: hexField(fields, "addr"),
126
163
  size: numberField(fields, "size"),
127
164
  file_offset: numberField(fields, "offset"),
128
- alignment: sectionAlignment(numberField(fields, "align")),
165
+ alignment: sectionAlignment(stringField(fields, "align")),
129
166
  flags: (stringField(fields, "flags") ?? "")
130
167
  .split(/\s+/u)
131
168
  .filter((flag) => flag.length > 0),
@@ -148,9 +185,9 @@ const permissions = (raw) => {
148
185
  const numericValue = numeric(raw);
149
186
  if (numericValue !== null)
150
187
  return {
151
- read: (numericValue & 4) !== 0,
188
+ read: (numericValue & 1) !== 0,
152
189
  write: (numericValue & 2) !== 0,
153
- execute: (numericValue & 1) !== 0,
190
+ execute: (numericValue & 4) !== 0,
154
191
  raw,
155
192
  };
156
193
  if (/^[r-][w-][x-]$/u.test(raw))
@@ -162,11 +199,12 @@ const permissions = (raw) => {
162
199
  };
163
200
  return { read: null, write: null, execute: null, raw };
164
201
  };
202
+ /** A whole decimal or hexadecimal integer literal, with no surrounding text. */
203
+ const NUMERIC_PATTERN = /^(?:0x[a-fA-F0-9]+|\d+)$/u;
165
204
  const numeric = (value) => {
166
- const token = value.split(/\s+/u)[0];
167
- if (token === undefined || !/^(?:0x[a-fA-F0-9]+|\d+)$/u.test(token))
205
+ if (!NUMERIC_PATTERN.test(value))
168
206
  return null;
169
- const parsed = Number.parseInt(token, token.startsWith("0x") ? 16 : 10);
207
+ const parsed = Number.parseInt(value, value.startsWith("0x") ? 16 : 10);
170
208
  return Number.isSafeInteger(parsed) && parsed >= 0 ? parsed : null;
171
209
  };
172
210
  const stringField = (fields, name) => {
@@ -186,8 +224,15 @@ const numberField = (fields, name) => {
186
224
  : null;
187
225
  };
188
226
  const hexField = (fields, name) => {
189
- const value = numberField(fields, name);
190
- return value === null ? null : `0x${value.toString(16)}`;
227
+ const value = stringField(fields, name);
228
+ if (value === null || !NUMERIC_PATTERN.test(value))
229
+ return null;
230
+ return `0x${BigInt(value).toString(16)}`;
191
231
  };
192
232
  const stripOffsetSuffix = (value) => value?.replace(/\s+\(offset\s+\d+\)$/u, "") ?? "unknown";
193
- const sectionAlignment = (exponent) => exponent === null || exponent > 52 ? null : 2 ** exponent;
233
+ const sectionAlignment = (raw) => {
234
+ if (raw === null)
235
+ return null;
236
+ const exponent = numeric(/^2\^(\d+)(?:\s+\(\d+\))?$/u.exec(raw)?.[1] ?? raw);
237
+ return exponent === null || exponent > 52 ? null : 2 ** exponent;
238
+ };
@@ -2,7 +2,8 @@ import { z } from "zod";
2
2
  const plistObject = z.record(z.string(), z.unknown());
3
3
  /** Parse plutil JSON output and project stable bundle metadata. */
4
4
  export const parsePlistJson = (output) => {
5
- const value = JSON.parse(output);
5
+ // plutil output can carry a UTF-8 BOM, which JSON.parse rejects outright.
6
+ const value = JSON.parse(output.replace(/^\uFEFF/u, ""));
6
7
  const object = plistObject.safeParse(value);
7
8
  const field = (name) => {
8
9
  if (!object.success)
@@ -1,7 +1,11 @@
1
1
  import { execFile, } from "node:child_process";
2
2
  /** Run a shell-free command while capturing its complete UTF-8 output. */
3
3
  export const execFileOutput = (command, arguments_, options = {}) => new Promise((resolve, reject) => {
4
- execFile(command, [...arguments_], { ...options, encoding: "utf8", maxBuffer: Number.POSITIVE_INFINITY }, (error, stdout, stderr) => {
4
+ execFile(command, [...arguments_], {
5
+ ...options,
6
+ encoding: "utf8",
7
+ maxBuffer: options.maxBuffer ?? Number.POSITIVE_INFINITY,
8
+ }, (error, stdout, stderr) => {
5
9
  if (error !== null) {
6
10
  reject(error);
7
11
  return;
@@ -48,14 +48,13 @@ export const parseProcessEnvironment = (value) => Object.fromEntries(value
48
48
  const separator = entry.indexOf("=");
49
49
  return [entry.slice(0, separator), entry.slice(separator + 1)];
50
50
  }));
51
- const systemHost = {
51
+ /** Create the operating-system process inspector for an explicit host context. */
52
+ export const createSystemProcessOwnershipHost = (platform = process.platform, hostEnvironment = process.env) => ({
53
+ platform,
52
54
  async listProcesses() {
53
- if (process.platform === "win32")
55
+ if (platform === "win32")
54
56
  return [];
55
- const { stdout } = await execFileOutput("ps", [
56
- "-axo",
57
- "pid=,ppid=,pgid=,stat=,command=",
58
- ]);
57
+ const { stdout } = await execFileOutput("ps", ["-axo", "pid=,ppid=,pgid=,stat=,command="], { env: hostEnvironment });
59
58
  return stdout
60
59
  .split("\n")
61
60
  .map((line) => /\s*(\d+)\s+(\d+)\s+(\d+)\s+(\S+)\s+(.*)/u.exec(line))
@@ -69,22 +68,24 @@ const systemHost = {
69
68
  }));
70
69
  },
71
70
  async environment(pid) {
72
- if (process.platform === "linux") {
71
+ if (platform === "linux")
73
72
  return parseProcessEnvironment(await readFile(`/proc/${pid}/environ`, "utf8"));
74
- }
75
- const { stdout } = await execFileOutput("ps", ["eww", "-p", String(pid)]);
76
- const environment = {};
73
+ const { stdout } = await execFileOutput("ps", ["eww", "-p", String(pid)], {
74
+ env: hostEnvironment,
75
+ });
76
+ const observedEnvironment = {};
77
77
  for (const match of stdout.matchAll(/(?:^|\s)([A-Za-z_][A-Za-z0-9_]*)=([^\s]*)/gu)) {
78
78
  const name = match[1];
79
79
  if (name !== undefined)
80
- environment[name] = match[2] ?? "";
80
+ observedEnvironment[name] = match[2] ?? "";
81
81
  }
82
- return environment;
82
+ return observedEnvironment;
83
83
  },
84
84
  signalGroup(processGroupId, signal) {
85
85
  process.kill(-processGroupId, signal);
86
86
  },
87
- };
87
+ });
88
+ const systemHost = createSystemProcessOwnershipHost();
88
89
  const systemWindowsProcessTreeHost = {
89
90
  async terminateTree(rootPid) {
90
91
  try {
@@ -104,10 +105,13 @@ const systemWindowsProcessTreeHost = {
104
105
  export const readProcessRunId = async (pid, host = systemHost) => (await host.environment(pid)).REA_PROCESS_RUN_ID;
105
106
  /** Token-validate every rooted POSIX process group before signaling any. */
106
107
  export const cleanupOwnedProcessGroup = async (ownership, host = systemHost) => {
107
- const processes = await readLiveProcessTable(host);
108
- if (processes === undefined)
109
- return { cleaned: false, reason: "process table could not be inspected" };
110
- const plan = await createOwnedCleanupPlan(ownership, processes, host);
108
+ const processTable = await readLiveProcessTable(host);
109
+ if (!processTable.available)
110
+ return {
111
+ cleaned: false,
112
+ reason: `process table could not be inspected: ${processTable.reason}`,
113
+ };
114
+ const plan = await createOwnedCleanupPlan(ownership, processTable.processes, host);
111
115
  if ("cleaned" in plan)
112
116
  return plan;
113
117
  let signaled = false;
@@ -124,17 +128,23 @@ export const cleanupOwnedProcessGroup = async (ownership, host = systemHost) =>
124
128
  catch (cause) {
125
129
  const code = cause instanceof Error && "code" in cause ? cause.code : undefined;
126
130
  if (code !== "ESRCH")
127
- return { cleaned: false, reason: "owned process group signal failed" };
131
+ return {
132
+ cleaned: false,
133
+ reason: `owned process group signal failed: ${errorMessage(cause)}`,
134
+ };
128
135
  }
129
136
  }
130
137
  return { cleaned: true, signaled };
131
138
  };
132
139
  /** Verify that no live process still carries an owned capture run token. */
133
140
  export const verifyNoTokenOwnedProcesses = async (runId, host = systemHost) => {
134
- const processes = await readLiveProcessTable(host);
135
- if (processes === undefined)
136
- return { cleaned: false, reason: "process table could not be inspected" };
137
- const scan = await scanTokenOwnedProcesses(processes, runId, host);
141
+ const processTable = await readLiveProcessTable(host);
142
+ if (!processTable.available)
143
+ return {
144
+ cleaned: false,
145
+ reason: `process table could not be inspected: ${processTable.reason}`,
146
+ };
147
+ const scan = await scanTokenOwnedProcesses(processTable.processes, runId, host);
138
148
  if (scan.failures.length > 0)
139
149
  return cleanupValidationFailure(scan.failures);
140
150
  return scan.owned.length === 0
@@ -143,10 +153,13 @@ export const verifyNoTokenOwnedProcesses = async (runId, host = systemHost) => {
143
153
  };
144
154
  const readLiveProcessTable = async (host) => {
145
155
  try {
146
- return liveProcesses(await host.listProcesses());
156
+ return {
157
+ available: true,
158
+ processes: liveProcesses(await host.listProcesses()),
159
+ };
147
160
  }
148
- catch {
149
- return undefined;
161
+ catch (cause) {
162
+ return { available: false, reason: errorMessage(cause) };
150
163
  }
151
164
  };
152
165
  const createOwnedCleanupPlan = async (ownership, processes, host) => {
@@ -201,10 +214,10 @@ const revalidateOwnedProcessGroup = async (processGroupId, ownership, host) => {
201
214
  try {
202
215
  members = liveProcesses(await host.listProcesses()).filter(({ processGroupId: observedGroupId }) => observedGroupId === processGroupId);
203
216
  }
204
- catch {
217
+ catch (cause) {
205
218
  return {
206
219
  cleaned: false,
207
- reason: "process ownership could not be revalidated",
220
+ reason: `process ownership could not be revalidated: ${errorMessage(cause)}`,
208
221
  };
209
222
  }
210
223
  const failures = await processOwnershipFailures(members, ownership.runId, host);
@@ -242,14 +255,25 @@ const processOwnershipFailures = async (members, runId, host) => {
242
255
  if ((await host.environment(member.pid)).REA_PROCESS_RUN_ID !== runId)
243
256
  failures.push({ pid: member.pid, reason: "run-token-mismatch" });
244
257
  }
245
- catch {
258
+ catch (cause) {
246
259
  try {
247
260
  const live = liveProcesses(await host.listProcesses());
248
261
  if (!live.some(({ pid }) => pid === member.pid))
249
262
  continue;
250
263
  }
251
- catch { }
252
- failures.push({ pid: member.pid, reason: "environment-unreadable" });
264
+ catch (recheckCause) {
265
+ failures.push({
266
+ pid: member.pid,
267
+ reason: "environment-unreadable",
268
+ diagnostic: `${errorMessage(cause)}; process liveness recheck failed: ${errorMessage(recheckCause)}`,
269
+ });
270
+ continue;
271
+ }
272
+ failures.push({
273
+ pid: member.pid,
274
+ reason: "environment-unreadable",
275
+ diagnostic: errorMessage(cause),
276
+ });
253
277
  }
254
278
  }
255
279
  return failures;
@@ -262,18 +286,30 @@ const scanTokenOwnedProcesses = async (processes, runId, host) => {
262
286
  if ((await host.environment(process.pid)).REA_PROCESS_RUN_ID === runId)
263
287
  owned.push(process);
264
288
  }
265
- catch {
289
+ catch (cause) {
266
290
  try {
267
291
  const live = liveProcesses(await host.listProcesses());
268
292
  if (!live.some(({ pid }) => pid === process.pid))
269
293
  continue;
270
294
  }
271
- catch { }
272
- failures.push({ pid: process.pid, reason: "environment-unreadable" });
295
+ catch (recheckCause) {
296
+ failures.push({
297
+ pid: process.pid,
298
+ reason: "environment-unreadable",
299
+ diagnostic: `${errorMessage(cause)}; process liveness recheck failed: ${errorMessage(recheckCause)}`,
300
+ });
301
+ continue;
302
+ }
303
+ failures.push({
304
+ pid: process.pid,
305
+ reason: "environment-unreadable",
306
+ diagnostic: errorMessage(cause),
307
+ });
273
308
  }
274
309
  }
275
310
  return { owned, failures };
276
311
  };
312
+ const errorMessage = (cause) => cause instanceof Error ? cause.message : String(cause);
277
313
  /** Observe one group without signaling it, failing closed on identity doubt. */
278
314
  export const observeOwnedProcessGroup = async (ownership, host = systemHost) => observeOwnedProcessGroupWithHost(ownership, host);
279
315
  /**
@@ -6,10 +6,10 @@ export const observeOwnedProcessGroupWithHost = async (ownership, host) => {
6
6
  try {
7
7
  members = (await host.listProcesses()).filter(({ processGroupId }) => processGroupId === ownership.processGroupId);
8
8
  }
9
- catch {
9
+ catch (cause) {
10
10
  return {
11
11
  state: "unverifiable",
12
- reason: "process group could not be inspected",
12
+ reason: `process group could not be inspected: ${errorMessage(cause)}`,
13
13
  };
14
14
  }
15
15
  const liveMembers = liveProcesses(members);
@@ -24,11 +24,13 @@ export const observeOwnedProcessGroupWithHost = async (ownership, host) => {
24
24
  reason: "process ownership did not match",
25
25
  };
26
26
  }
27
- catch {
28
- return {
29
- state: "unverifiable",
30
- reason: "process ownership could not be revalidated",
31
- };
27
+ catch (cause) {
28
+ if (!(await processIsGone(host, member.pid))) {
29
+ return {
30
+ state: "unverifiable",
31
+ reason: `process ownership could not be revalidated for PID ${member.pid}: ${errorMessage(cause)}`,
32
+ };
33
+ }
32
34
  }
33
35
  }
34
36
  return { state: "alive" };
@@ -39,8 +41,8 @@ export const observeOwnedProcessLineageWithHost = async (ownership, host) => {
39
41
  try {
40
42
  processes = liveProcesses(await host.listProcesses());
41
43
  }
42
- catch {
43
- return unavailableLineage(ownership, "process table could not be inspected");
44
+ catch (cause) {
45
+ return unavailableLineage(ownership, `process table could not be inspected: ${errorMessage(cause)}`);
44
46
  }
45
47
  const launcher = processes.find(({ pid }) => pid === ownership.leaderPid);
46
48
  if (launcher === undefined)
@@ -49,14 +51,22 @@ export const observeOwnedProcessLineageWithHost = async (ownership, host) => {
49
51
  if (identityFailure !== null)
50
52
  return unavailableLineage(ownership, identityFailure);
51
53
  const descendants = descendantsOf(launcher.pid, processes);
54
+ const verifiedDescendants = [];
52
55
  for (const member of [launcher, ...descendants]) {
53
56
  try {
54
57
  if ((await host.environment(member.pid)).REA_PROCESS_RUN_ID !==
55
58
  ownership.runId)
56
59
  return unavailableLineage(ownership, "process lineage contains an unowned or PID-reused process");
60
+ if (member.pid !== launcher.pid)
61
+ verifiedDescendants.push(member);
57
62
  }
58
- catch {
59
- return unavailableLineage(ownership, "process ownership could not be revalidated");
63
+ catch (cause) {
64
+ if (await processIsGone(host, member.pid)) {
65
+ if (member.pid === launcher.pid)
66
+ return unavailableLineage(ownership, "owned launcher exited during lineage validation");
67
+ continue;
68
+ }
69
+ return unavailableLineage(ownership, `process ownership could not be revalidated for PID ${member.pid}: ${errorMessage(cause)}`);
60
70
  }
61
71
  }
62
72
  return {
@@ -67,7 +77,7 @@ export const observeOwnedProcessLineageWithHost = async (ownership, host) => {
67
77
  launcherPid: launcher.pid,
68
78
  launcherParentPid: launcher.parentPid,
69
79
  processGroupId: launcher.processGroupId,
70
- descendants: descendants
80
+ descendants: verifiedDescendants
71
81
  .sort((left, right) => left.pid - right.pid)
72
82
  .map(({ pid, parentPid, processGroupId }) => ({
73
83
  pid,
@@ -85,3 +95,12 @@ const unavailableLineage = (ownership, reason) => ({
85
95
  processGroupId: ownership.processGroupId,
86
96
  reason,
87
97
  });
98
+ const processIsGone = async (host, pid) => {
99
+ try {
100
+ return !liveProcesses(await host.listProcesses()).some((process) => process.pid === pid);
101
+ }
102
+ catch {
103
+ return false;
104
+ }
105
+ };
106
+ const errorMessage = (cause) => cause instanceof Error ? cause.message : String(cause);
@@ -8,14 +8,16 @@ const DEFAULT_KILL_GRACE_MS = 1_000;
8
8
  * selecting provider-specific command arguments or environment values.
9
9
  */
10
10
  export const spawnOwnedProviderProcess = async (options) => {
11
+ const platform = options.platform ?? process.platform;
12
+ const hostEnvironment = options.hostEnvironment ?? process.env;
11
13
  const child = spawn(options.command, [...options.arguments], {
12
14
  shell: false,
13
15
  windowsHide: true,
14
16
  stdio: ["ignore", "pipe", "pipe"],
15
- detached: process.platform !== "win32",
17
+ detached: platform !== "win32",
16
18
  windowsVerbatimArguments: options.windowsVerbatimArguments ?? false,
17
19
  env: {
18
- ...process.env,
20
+ ...hostEnvironment,
19
21
  ...options.env,
20
22
  REA_PROCESS_RUN_ID: options.runId,
21
23
  },