rea-agents 6.2.0 → 6.3.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 (297) hide show
  1. package/README.md +18 -20
  2. package/bridge/hopper_bridge.py +2 -0
  3. package/dist/android/JadxProvider.js +8 -2
  4. package/dist/android/JadxSession.js +51 -9
  5. package/dist/application/BinaryTargetResolver.js +63 -17
  6. package/dist/application/BrowserScenarioEvidence.js +2 -2
  7. package/dist/application/ClientConfigurationDocument.js +28 -0
  8. package/dist/application/ClientRegistrationStatus.js +19 -6
  9. package/dist/application/DirectAnalysis.js +12 -6
  10. package/dist/application/DirectAnalysisCleanup.js +0 -1
  11. package/dist/application/DirectAnalysisStatus.js +2 -5
  12. package/dist/application/Doctor.js +25 -34
  13. package/dist/application/DoctorDiagnostics.js +1 -1
  14. package/dist/application/EvidenceBundleFiles.js +1 -1
  15. package/dist/application/InvestigationProviders.js +4 -4
  16. package/dist/application/JsonFiles.js +15 -15
  17. package/dist/application/LinuxHopper.js +2 -1
  18. package/dist/application/ReconstructionObligationCandidates.js +9 -2
  19. package/dist/application/ReconstructionObligationLedgerProjection.js +3 -1
  20. package/dist/application/RegularFileRead.js +17 -0
  21. package/dist/application/Setup.js +18 -7
  22. package/dist/application/SetupClientConfiguration.js +18 -7
  23. package/dist/application/SetupHost.js +6 -4
  24. package/dist/application/SetupPlan.js +19 -15
  25. package/dist/application/SetupSkill.js +57 -8
  26. package/dist/application/SupportedClients.js +43 -0
  27. package/dist/application/Uninstall.js +18 -2
  28. package/dist/application/UpdateMaintenance.js +6 -2
  29. package/dist/application/Utf8JsonInput.js +64 -0
  30. package/dist/application/WebScriptExportService.js +13 -6
  31. package/dist/application/android/AndroidAnalysisService.js +1 -1
  32. package/dist/application/binary/AnalysisSnapshotCache.js +5 -4
  33. package/dist/application/binary/BinarySession.js +16 -0
  34. package/dist/application/binary/BinarySessionOpen.js +9 -1
  35. package/dist/application/javascript/ElectronActiveEvidence.js +2 -2
  36. package/dist/application/javascript/ElectronBoundaryAnalysis.js +2 -2
  37. package/dist/application/javascript/ElectronBoundaryGraphNative.js +5 -1
  38. package/dist/application/javascript/JavaScriptApplicationEvidence.js +1 -0
  39. package/dist/application/javascript/JavaScriptApplicationEvidenceGraph.js +107 -46
  40. package/dist/application/javascript/JavaScriptApplicationService.js +1 -0
  41. package/dist/application/javascript/JavaScriptApplicationWorkflowService.js +59 -45
  42. package/dist/application/javascript/JavaScriptArtifactAnalysis.js +0 -6
  43. package/dist/application/javascript/JavaScriptArtifactGraphBuilder.js +8 -18
  44. package/dist/application/javascript/JavaScriptArtifactGraphFindings.js +34 -26
  45. package/dist/application/javascript/JavaScriptArtifactPathResolution.js +44 -12
  46. package/dist/application/javascript/JavaScriptArtifactReconstruction.js +6 -3
  47. package/dist/application/javascript/JavaScriptArtifactReconstructionInput.js +1 -0
  48. package/dist/application/javascript/JavaScriptJsonModules.js +2 -2
  49. package/dist/application/javascript/JavaScriptModuleRelationships.js +5 -17
  50. package/dist/application/javascript/JavaScriptRuntimeReconciliationService.js +11 -27
  51. package/dist/application/javascript/JavaScriptSemanticGraphAsyncProjection.js +2 -2
  52. package/dist/application/javascript/JavaScriptSemanticGraphBuilder.js +8 -6
  53. package/dist/application/javascript/JavaScriptSemanticGraphChildProcessProjection.js +1 -1
  54. package/dist/application/javascript/JavaScriptSemanticGraphConstruction.js +7 -5
  55. package/dist/application/javascript/JavaScriptSemanticGraphDataProjection.js +1 -1
  56. package/dist/application/javascript/JavaScriptSemanticGraphEvidence.js +1 -1
  57. package/dist/application/javascript/JavaScriptSemanticGraphFingerprintProjection.js +2 -2
  58. package/dist/application/javascript/JavaScriptSemanticGraphFlowProjection.js +2 -2
  59. package/dist/application/javascript/JavaScriptSemanticGraphObjectProjection.js +1 -1
  60. package/dist/application/javascript/JavaScriptSemanticGraphProjection.js +4 -4
  61. package/dist/application/javascript/JavaScriptSemanticGraphResourceProjection.js +1 -1
  62. package/dist/application/javascript/JavaScriptSemanticGraphValueProjection.js +10 -7
  63. package/dist/application/javascript/JavaScriptSemanticTraceService.js +15 -10
  64. package/dist/application/native/NativeCallRoutes.js +2 -4
  65. package/dist/artifacts/ArtifactProvider.js +14 -16
  66. package/dist/artifacts/ArtifactProviderMetadata.js +1 -4
  67. package/dist/artifacts/AsarArtifactReader.js +81 -17
  68. package/dist/artifacts/DirectoryArtifactReader.js +2 -2
  69. package/dist/artifacts/NativeDmgArtifactReader.js +152 -67
  70. package/dist/artifacts/NativeDmgOwnership.js +109 -0
  71. package/dist/artifacts/apple/KeyedArchiveReader.js +54 -46
  72. package/dist/artifacts/apple/MachoLoadCommandReader.js +36 -6
  73. package/dist/artifacts/extraction/ArtifactExtraction.js +29 -11
  74. package/dist/artifacts/inventory/ArtifactGraphConstruction.js +7 -8
  75. package/dist/artifacts/inventory/classify.js +33 -14
  76. package/dist/artifacts/inventory/hashStableRootArtifact.js +37 -0
  77. package/dist/artifacts/inventory/scanCanonical.js +28 -22
  78. package/dist/artifacts/inventory/scanReader.js +7 -11
  79. package/dist/artifacts/javascript/JavaScriptArtifactFiles.js +65 -27
  80. package/dist/browser/CdpBrowserProvider.js +4 -3
  81. package/dist/browser/CdpCaptureStorageFingerprints.js +3 -3
  82. package/dist/browser/CdpElectronInspection.js +2 -2
  83. package/dist/browser/CdpElectronProvider.js +4 -3
  84. package/dist/browser/CdpElectronScripts.js +2 -2
  85. package/dist/browser/CdpWebMcpDiscovery.js +16 -13
  86. package/dist/browser/PlaywrightBrowserScenarioProvider.js +6 -6
  87. package/dist/browser/PlaywrightScenarioBrowser.js +145 -42
  88. package/dist/browser/PlaywrightScenarioSession.js +3 -11
  89. package/dist/browser/WebSourceMapFetcher.js +32 -6
  90. package/dist/browser/assets/ScenarioScriptCapture.js +8 -12
  91. package/dist/cli/coreAnalysisCommands.js +2 -2
  92. package/dist/cli/coreBinaryCommands.js +13 -9
  93. package/dist/cli/electronCommands.js +9 -10
  94. package/dist/cli/javascriptApplicationAnalysis.js +2 -12
  95. package/dist/cli/jsonOutput.js +3 -2
  96. package/dist/cli/streamedJsonOutput.js +83 -4
  97. package/dist/cli/utilityCommands.js +2 -4
  98. package/dist/cli.js +5 -2
  99. package/dist/cliJsonFile.js +179 -0
  100. package/dist/cliJsonInput.js +47 -34
  101. package/dist/cliObservationOptions.js +4 -0
  102. package/dist/composition/auxiliaryAnalysisProviders.js +5 -4
  103. package/dist/composition/browserScenario.js +2 -2
  104. package/dist/composition/directAnalysis.js +2 -3
  105. package/dist/contracts/artifactComparisonExample.js +5 -5
  106. package/dist/contracts/errorSchemas.js +3 -1
  107. package/dist/contracts/functionComparisonExample.js +8 -0
  108. package/dist/contracts/inputSchemaPresentation.js +94 -3
  109. package/dist/contracts/javascript/electronToolContracts.js +2 -1
  110. package/dist/contracts/javascript/javascriptApplicationWorkflowExamples.js +3 -2
  111. package/dist/contracts/javascript/javascriptExportShapeComparisonExample.js +6 -3
  112. package/dist/contracts/javascript/javascriptRuntimeReconciliationExample.js +8 -7
  113. package/dist/contracts/managed/managedToolContracts.js +3 -2
  114. package/dist/contracts/mobileApplicationGraphExamples.js +5 -5
  115. package/dist/contracts/native/nativeToolContracts.js +1 -1
  116. package/dist/contracts/sessionLifecycleInputs.js +4 -3
  117. package/dist/contracts/sessionStatusContract.js +3 -2
  118. package/dist/contracts/sessionToolContracts.js +3 -2
  119. package/dist/contracts/sessionToolSchemas.js +3 -2
  120. package/dist/contracts/toolOutputSchemaGroups.js +2 -2
  121. package/dist/contracts/toolOutputSchemaPrimitives.js +2 -5
  122. package/dist/domain/analysisErrorBase.js +5 -0
  123. package/dist/domain/analysisErrorPresentation.js +4 -2
  124. package/dist/domain/analysisSnapshot.js +3 -1
  125. package/dist/domain/analysisView/analysisView.js +1 -3
  126. package/dist/domain/android/androidPartialObservation.js +36 -0
  127. package/dist/domain/apple/dylibResolution.js +1 -1
  128. package/dist/domain/artifactComparison.js +4 -4
  129. package/dist/domain/artifactGraph.js +1 -1
  130. package/dist/domain/artifactIdentity.js +8 -8
  131. package/dist/domain/artifactInspection.js +8 -8
  132. package/dist/domain/artifactInventoryEvidence.js +5 -5
  133. package/dist/domain/browserCompleteness.js +3 -2
  134. package/dist/domain/browserScenarioCaptureValues.js +2 -2
  135. package/dist/domain/browserScenarioNormalization.js +3 -3
  136. package/dist/domain/browserScenarioValues.js +3 -2
  137. package/dist/domain/callPath.js +8 -10
  138. package/dist/domain/canonicalDigest.js +7 -1
  139. package/dist/domain/canonicalOrdering.js +1 -13
  140. package/dist/domain/changedBehavior.js +2 -3
  141. package/dist/domain/comparisonSemantics.js +0 -5
  142. package/dist/domain/digests.js +0 -3
  143. package/dist/domain/evidence.js +10 -5
  144. package/dist/domain/evidenceBundle.js +51 -33
  145. package/dist/domain/firmware/firmwareAnalysis.js +4 -3
  146. package/dist/domain/functionComparison.js +2 -1
  147. package/dist/domain/functionComparisonNormalization.js +4 -3
  148. package/dist/domain/functionComparisonResults.js +2 -2
  149. package/dist/domain/functionDossierEvidence.js +2 -1
  150. package/dist/domain/hopperValues.js +11 -15
  151. package/dist/domain/javascript/electronActiveObservation.js +4 -3
  152. package/dist/domain/javascript/electronStaticAnalysisBrowser.js +2 -2
  153. package/dist/domain/javascript/electronStaticAnalysisIpc.js +9 -1
  154. package/dist/domain/javascript/electronStaticAnalysisNative.js +5 -3
  155. package/dist/domain/javascript/electronStaticAnalysisValues.js +8 -4
  156. package/dist/domain/javascript/javascriptApplicationAnalysis.js +3 -1
  157. package/dist/domain/javascript/javascriptApplicationChangeGraph.js +12 -8
  158. package/dist/domain/javascript/javascriptApplicationEvidenceSchemas.js +4 -0
  159. package/dist/domain/javascript/javascriptApplicationGraph.js +15 -13
  160. package/dist/domain/javascript/javascriptApplicationVersionComparison.js +4 -4
  161. package/dist/domain/javascript/javascriptApplicationVersionComparisonSchemas.js +37 -22
  162. package/dist/domain/javascript/javascriptApplicationVersionItems.js +45 -34
  163. package/dist/domain/javascript/javascriptApplicationVersionKeys.js +7 -7
  164. package/dist/domain/javascript/javascriptAstFingerprint.js +2 -2
  165. package/dist/domain/javascript/javascriptAstValues.js +22 -0
  166. package/dist/domain/javascript/javascriptExportShapeComparison.js +3 -2
  167. package/dist/domain/javascript/javascriptExportShapeComparisonSchemas.js +31 -23
  168. package/dist/domain/javascript/javascriptExportShapeSelection.js +2 -2
  169. package/dist/domain/javascript/javascriptExportShapeVariants.js +3 -2
  170. package/dist/domain/javascript/javascriptFeatureSeed.js +5 -3
  171. package/dist/domain/javascript/javascriptFeatureTrace.js +7 -6
  172. package/dist/domain/javascript/javascriptFeatureTraceSchemas.js +17 -9
  173. package/dist/domain/javascript/javascriptFeatureTraversal.js +4 -4
  174. package/dist/domain/javascript/javascriptNativeHandoff.js +6 -6
  175. package/dist/domain/javascript/javascriptRuntimeObservation.js +8 -5
  176. package/dist/domain/javascript/javascriptRuntimeReconciliation.js +12 -6
  177. package/dist/domain/javascript/javascriptRuntimeReconciliationActive.js +9 -8
  178. package/dist/domain/javascript/javascriptRuntimeReconciliationCaptureParsing.js +212 -0
  179. package/dist/domain/javascript/javascriptRuntimeReconciliationGraph.js +5 -4
  180. package/dist/domain/javascript/javascriptRuntimeReconciliationInputValidation.js +28 -0
  181. package/dist/domain/javascript/javascriptRuntimeReconciliationMatching.js +5 -5
  182. package/dist/domain/javascript/javascriptRuntimeReconciliationParsing.js +12 -223
  183. package/dist/domain/javascript/javascriptRuntimeReconciliationResult.js +2 -2
  184. package/dist/domain/javascript/javascriptRuntimeReconciliationRuntime.js +15 -4
  185. package/dist/domain/javascript/javascriptRuntimeReconciliationSchemas.js +2 -2
  186. package/dist/domain/javascript/javascriptRuntimeStaticCandidates.js +7 -6
  187. package/dist/domain/javascript/javascriptSemanticAnalysis.js +200 -8
  188. package/dist/domain/javascript/javascriptSemanticCallResolution.js +9 -7
  189. package/dist/domain/javascript/javascriptSemanticChildProcesses.js +2 -2
  190. package/dist/domain/javascript/javascriptSemanticCoverage.js +20 -0
  191. package/dist/domain/javascript/javascriptSemanticDataEffectHelpers.js +7 -9
  192. package/dist/domain/javascript/javascriptSemanticDataEffects.js +4 -11
  193. package/dist/domain/javascript/javascriptSemanticFingerprints.js +2 -2
  194. package/dist/domain/javascript/javascriptSemanticGraph.js +142 -35
  195. package/dist/domain/javascript/javascriptSemanticGraphSchemas.js +19 -1
  196. package/dist/domain/javascript/javascriptSemanticIr.js +0 -4
  197. package/dist/domain/javascript/javascriptSemanticIterationSources.js +106 -0
  198. package/dist/domain/javascript/javascriptSemanticMemberMutations.js +497 -113
  199. package/dist/domain/javascript/javascriptSemanticMutationInitializers.js +190 -0
  200. package/dist/domain/javascript/javascriptSemanticMutationValues.js +41 -27
  201. package/dist/domain/javascript/javascriptSemanticObjects.js +2 -6
  202. package/dist/domain/javascript/javascriptSemanticPrimitives.js +7 -2
  203. package/dist/domain/javascript/javascriptSemanticProjection.js +20 -14
  204. package/dist/domain/javascript/javascriptSemanticPromises.js +15 -21
  205. package/dist/domain/javascript/javascriptSemanticPropertyPaths.js +23 -0
  206. package/dist/domain/javascript/javascriptSemanticProvenance.js +3 -3
  207. package/dist/domain/javascript/javascriptSemanticQuery.js +8 -2
  208. package/dist/domain/javascript/javascriptSemanticQueryIdentity.js +3 -2
  209. package/dist/domain/javascript/javascriptSemanticQuerySchemas.js +8 -9
  210. package/dist/domain/javascript/javascriptSemanticRequireOrigin.js +16 -10
  211. package/dist/domain/javascript/javascriptSemanticReturns.js +23 -27
  212. package/dist/domain/javascript/javascriptSemanticTraversal.js +6 -1
  213. package/dist/domain/javascript/javascriptSemanticValues.js +135 -24
  214. package/dist/domain/javascript/javascriptSourceMapPaths.js +11 -1
  215. package/dist/domain/javascript/javascriptSourceParser.js +34 -9
  216. package/dist/domain/javascript/javascriptStaticAnalysisBundler.js +5 -6
  217. package/dist/domain/javascript/javascriptStaticAnalysisHelpers.js +26 -15
  218. package/dist/domain/javascript/sourceToBundleComparison.js +7 -5
  219. package/dist/domain/javascript/sourceToBundleSignals.js +7 -7
  220. package/dist/domain/jsonSerialization.js +109 -55
  221. package/dist/domain/jsonShape.js +46 -19
  222. package/dist/domain/localPath.js +10 -4
  223. package/dist/domain/managed/managedApplicationGraph.js +10 -6
  224. package/dist/domain/managed/managedApplicationGraphNodes.js +82 -57
  225. package/dist/domain/managed/managedMemberComparisonMatch.js +6 -7
  226. package/dist/domain/native/nativeCallObservation.js +2 -4
  227. package/dist/domain/native/nativeValueFlow.js +5 -11
  228. package/dist/domain/native/objcSwiftMetadata.js +15 -17
  229. package/dist/domain/process/processCapture.js +11 -10
  230. package/dist/domain/process/processCaptureCoverage.js +8 -5
  231. package/dist/domain/process/processCaptureExample.js +43 -0
  232. package/dist/domain/process/processCaptureValidation.js +4 -3
  233. package/dist/domain/process/processComparison.js +0 -23
  234. package/dist/domain/process/processScenario.js +3 -3
  235. package/dist/domain/process/processTraceEvaluation.js +4 -4
  236. package/dist/domain/process/processTraceSpecification.js +1 -3
  237. package/dist/domain/providerCleanupError.js +6 -2
  238. package/dist/domain/reconstructionCoverage.js +2 -1
  239. package/dist/domain/reconstructionUnknowns.js +4 -3
  240. package/dist/domain/reconstructionVerification.js +3 -2
  241. package/dist/domain/referenceSourceGraph.js +7 -7
  242. package/dist/domain/referenceSourceImportParsing.js +34 -45
  243. package/dist/domain/residualUnknown.js +3 -2
  244. package/dist/domain/staticRuntimeCorrelation.js +2 -1
  245. package/dist/domain/swiftSymbolClassification.js +6 -1
  246. package/dist/domain/symbolAnalysis.js +17 -2
  247. package/dist/domain/unicodeCodePointOrder.js +6 -0
  248. package/dist/domain/webBundleAnalyzerInspection.js +9 -1
  249. package/dist/domain/webCaptureDiff.js +71 -29
  250. package/dist/domain/webCaptureDiffSchemas.js +2 -8
  251. package/dist/domain/webInventory.js +3 -2
  252. package/dist/domain/webMcpDiscovery.js +4 -3
  253. package/dist/domain/webScriptExport.js +1 -1
  254. package/dist/dotnet/ManagedMemberInstructionDecoder.js +1 -2
  255. package/dist/dotnet/ManagedStaticProvider.js +10 -7
  256. package/dist/dotnet/ManagedStaticProviderMetadata.js +1 -4
  257. package/dist/filesystem/RegularFile.js +41 -0
  258. package/dist/generatedPackageMetadata.js +1 -1
  259. package/dist/ghidra/GhidraClient.js +14 -4
  260. package/dist/ghidra/GhidraInstallation.js +111 -10
  261. package/dist/ghidra/GhidraLauncher.js +43 -19
  262. package/dist/hopper/HopperCleanup.js +1 -1
  263. package/dist/ida/IdaOperationRunner.js +2 -0
  264. package/dist/ida/IdaSessionClient.js +4 -2
  265. package/dist/inspector/JavaScriptRuntimeScope.js +9 -5
  266. package/dist/inspector/V8InspectorCaptureProjection.js +46 -13
  267. package/dist/inspector/V8InspectorProvider.js +60 -8
  268. package/dist/main/shutdown.js +76 -32
  269. package/dist/main/transport.js +1 -1
  270. package/dist/native/AppleObjcDispatchFacets.js +3 -3
  271. package/dist/native/AppleObjcProperties.js +17 -7
  272. package/dist/native/LldbCallTracer.js +241 -75
  273. package/dist/native/NativeMacOSProvider.js +10 -5
  274. package/dist/native/NativeMacOSProviderMetadata.js +1 -2
  275. package/dist/process/ProcessOwnershipObservation.js +9 -13
  276. package/dist/process/capture/FilesystemSnapshot.js +88 -18
  277. package/dist/process/capture/ProcessCaptureLifecycle.js +13 -27
  278. package/dist/process/capture/ProcessFilesystemEffects.js +19 -4
  279. package/dist/process/capture/ProcessHarness.js +8 -21
  280. package/dist/server/analysisAdmission.js +8 -0
  281. package/dist/server/createServer.js +22 -23
  282. package/dist/server/registerApplicationTools/compareExportShapes.js +2 -1
  283. package/dist/server/registerApplicationTools/helpers.js +3 -2
  284. package/dist/server/registerArtifactTools.js +2 -2
  285. package/dist/server/registerCloseLifecycleTool.js +6 -4
  286. package/dist/server/registerEnhancedTools.js +78 -73
  287. package/dist/server/registerEvidenceTools.js +54 -46
  288. package/dist/server/registerManagedTools.js +7 -4
  289. package/dist/server/registerOfficialTools.js +31 -25
  290. package/dist/server/registerSessionTools.js +9 -3
  291. package/native/windows/build/manifest.json +1 -1
  292. package/package.json +6 -3
  293. package/skills/reverse-engineer-anything/SKILL.md +5 -5
  294. package/skills/reverse-engineer-anything/references/native-and-artifacts.md +9 -0
  295. package/dist/artifacts/inventory/policy.js +0 -2
  296. package/dist/domain/managed/managedApplicationGraphNodeCoverage.js +0 -6
  297. package/dist/server/registerNativeTools.js +0 -6
@@ -6,13 +6,15 @@ import { fileURLToPath } from "node:url";
6
6
  import { z } from "zod";
7
7
  import { AnalysisCancelledError, AnalysisCapabilityUnavailableError, AnalysisTimeoutError, } from "../domain/analysisErrorCore.js";
8
8
  import { EvidenceIntegrityError } from "../domain/evidenceErrors.js";
9
+ import { projectAnalysisError } from "../domain/analysisErrorProjection.js";
9
10
  import { nativeCallEventSchema, nativeCodeLocationSchema, } from "../domain/native/nativeCallObservation.js";
10
11
  import { ProviderAdapterError } from "../domain/providerAdapterError.js";
12
+ import { ProviderCleanupError } from "../domain/providerCleanupError.js";
11
13
  import { err, ok } from "../domain/result.js";
12
14
  import { safeParseJson } from "../domain/safeJson.js";
13
15
  import { ProviderProcessSupervisor, spawnOwnedProviderProcess, } from "../process/ProviderProcess.js";
14
16
  import { cleanupOwnedProcessGroup } from "../process/ProcessOwnership.js";
15
- import { observeProcessStartIdentity, prepareProcessOwnershipInspection, signalProcessWithStartIdentity, } from "../process/ProcessOwnershipObservation.js";
17
+ import { observeProcessStartIdentity, signalProcessWithStartIdentity, } from "../process/ProcessOwnershipObservation.js";
16
18
  import { ProviderStartupDeadline, waitForAbortableDelay, } from "../process/ProviderDeadline.js";
17
19
  import { PrivateRuntimeRoot } from "../process/PrivateRuntimeRoot.js";
18
20
  import { resolveXcrunTool } from "./CommandRunner.js";
@@ -93,37 +95,147 @@ export class LldbCallTracer {
93
95
  launch;
94
96
  resolveTool;
95
97
  environment;
98
+ #tail = Promise.resolve();
99
+ #pendingCleanup;
96
100
  constructor(environment, launch = runLldb, resolveTool = (tool, signal) => resolveXcrunTool(tool, this.environment, signal)) {
97
101
  this.launch = launch;
98
102
  this.resolveTool = resolveTool;
99
103
  this.environment = snapshotEnvironment(environment);
100
104
  }
101
105
  async trace(request, signal) {
106
+ return this.#serialize(() => this.#trace(request, signal));
107
+ }
108
+ async #trace(request, signal) {
109
+ const pendingCleanup = await this.#retryPendingCleanup();
110
+ if (pendingCleanup !== undefined)
111
+ return err(pendingCleanup);
102
112
  const lldb = await this.resolveTool("lldb", signal);
103
113
  if (!lldb.ok)
104
114
  return err(lldb.error.reason === "cancelled"
105
115
  ? new AnalysisCancelledError(OPERATION)
106
116
  : new AnalysisCapabilityUnavailableError(PROVIDER, OPERATION, LLDB_REQUIREMENT, { userMessage: LLDB_REQUIREMENT }));
107
117
  const root = await PrivateRuntimeRoot.create({ prefix: "rea-lldb-" });
118
+ const paths = lldbRuntimePaths(root.path);
119
+ let result;
108
120
  try {
109
- return await this.#run(lldb.value, root.path, request, signal);
121
+ result = await this.#run(lldb.value, root, request, signal);
110
122
  }
111
- finally {
123
+ catch (cause) {
124
+ const partialObservation = await partialNativeObservation({
125
+ request,
126
+ pidPath: paths.pid,
127
+ stdoutPath: paths.stdoutCapture,
128
+ stderrPath: paths.stderrCapture,
129
+ observationPath: paths.observations,
130
+ version: null,
131
+ reason: "tracer-failure",
132
+ });
133
+ const retained = this.#pendingCleanup;
134
+ const resources = retained === undefined ? [] : await lldbCleanupResources(retained);
135
+ result = err(new ProviderAdapterError(PROVIDER, OPERATION, {
136
+ cause,
137
+ diagnostics: {
138
+ reason: cause instanceof Error ? cause.message : String(cause),
139
+ },
140
+ partialObservation,
141
+ ...(retained === undefined
142
+ ? {}
143
+ : {
144
+ cleanup: {
145
+ reason: "LLDB trace failed while owned resources remain",
146
+ resources,
147
+ },
148
+ }),
149
+ }));
150
+ }
151
+ if (this.#pendingCleanup?.root === root)
152
+ return result;
153
+ try {
112
154
  await root.close();
113
155
  }
156
+ catch (cause) {
157
+ this.#pendingCleanup = {
158
+ root,
159
+ supervisor: undefined,
160
+ pidPath: paths.pid,
161
+ targetIdentity: undefined,
162
+ processStopped: true,
163
+ targetStopped: true,
164
+ };
165
+ const partialObservation = result.ok
166
+ ? partialObservationFromTrace(request, result.value)
167
+ : result.error.partialObservation;
168
+ return err(new ProviderCleanupError(PROVIDER, [root.path], {
169
+ reason: cause instanceof Error ? cause.message : String(cause),
170
+ ...(result.ok
171
+ ? {}
172
+ : {
173
+ execution_failure: projectAnalysisError(result.error).code,
174
+ primary_failure: result.error.message,
175
+ }),
176
+ }, {
177
+ operation: OPERATION,
178
+ cause: result.ok
179
+ ? cause
180
+ : new AggregateError([result.error, cause], "LLDB trace and runtime cleanup both failed"),
181
+ ...(partialObservation === undefined ? {} : { partialObservation }),
182
+ }));
183
+ }
184
+ return result;
114
185
  }
115
- async #run(lldb, directory, request, signal) {
116
- const paths = {
117
- config: join(directory, "config.json"),
118
- result: join(directory, "result.json"),
119
- pid: join(directory, "pid"),
120
- identityAck: join(directory, "identity.ack"),
121
- stdout: join(directory, "stdout"),
122
- stderr: join(directory, "stderr"),
123
- stdoutCapture: join(directory, "stdout.capture"),
124
- stderrCapture: join(directory, "stderr.capture"),
125
- observations: join(directory, "observations.jsonl"),
126
- };
186
+ /** Retry retained LLDB cleanup without abandoning its process or runtime owner. */
187
+ async close() {
188
+ return this.#serialize(() => this.#close());
189
+ }
190
+ async #close() {
191
+ const failure = await this.#retryPendingCleanup();
192
+ return failure === undefined ? ok(null) : err(failure);
193
+ }
194
+ #serialize(operation) {
195
+ const call = this.#tail.then(operation, operation);
196
+ this.#tail = call.then(() => undefined, () => undefined);
197
+ return call;
198
+ }
199
+ async #retryPendingCleanup() {
200
+ const owner = this.#pendingCleanup;
201
+ if (owner === undefined)
202
+ return undefined;
203
+ let firstFailure;
204
+ if (!owner.processStopped) {
205
+ const stopped = await owner.supervisor?.stop();
206
+ if (stopped?.status === "incomplete")
207
+ firstFailure = stopped.reason;
208
+ else {
209
+ owner.supervisor?.dispose();
210
+ owner.processStopped = true;
211
+ }
212
+ }
213
+ if (firstFailure === undefined && !owner.targetStopped) {
214
+ const targetTermination = await ensureTerminated(owner.pidPath, owner.targetIdentity, true);
215
+ if (targetTermination !== "terminated")
216
+ firstFailure = targetTerminationReason(targetTermination);
217
+ else
218
+ owner.targetStopped = true;
219
+ }
220
+ if (firstFailure === undefined) {
221
+ try {
222
+ await owner.root.close();
223
+ this.#pendingCleanup = undefined;
224
+ return undefined;
225
+ }
226
+ catch (cause) {
227
+ firstFailure = cause instanceof Error ? cause.message : String(cause);
228
+ }
229
+ }
230
+ const resources = await lldbCleanupResources(owner);
231
+ return new ProviderCleanupError(PROVIDER, resources, {
232
+ reason: firstFailure ?? "LLDB cleanup remains incomplete",
233
+ resources,
234
+ }, { operation: OPERATION });
235
+ }
236
+ async #run(lldb, root, request, signal) {
237
+ const directory = root.path;
238
+ const paths = lldbRuntimePaths(directory);
127
239
  const { input } = request;
128
240
  await writeFile(paths.config, JSON.stringify({
129
241
  executable: request.executable,
@@ -149,7 +261,6 @@ export class LldbCallTracer {
149
261
  identity_ack_path: paths.identityAck,
150
262
  observation_path: paths.observations,
151
263
  }), { mode: 0o600 });
152
- await prepareProcessOwnershipInspection(signal);
153
264
  const exited = await this.launch(lldb.path, [
154
265
  "--batch",
155
266
  "--no-lldbinit",
@@ -165,16 +276,30 @@ export class LldbCallTracer {
165
276
  environment: this.environment,
166
277
  ...(signal === undefined ? {} : { signal }),
167
278
  });
279
+ const retained = {
280
+ root,
281
+ supervisor: exited.cleanupOwner,
282
+ pidPath: paths.pid,
283
+ targetIdentity: exited.targetIdentity,
284
+ processStopped: exited.cleanupOwner === undefined,
285
+ targetStopped: !exited.targetLaunched,
286
+ };
287
+ this.#pendingCleanup = retained;
168
288
  const output = exited.kind === "exited"
169
289
  ? await readTracerOutput(paths.result)
170
290
  : undefined;
171
- let targetTermination = await ensureTerminated(paths.pid, exited.targetIdentity, true);
291
+ let targetTermination = exited.targetLaunched
292
+ ? await ensureTerminated(paths.pid, exited.targetIdentity, true)
293
+ : "terminated";
172
294
  // These two bridge outcomes are emitted before a target process exists.
173
295
  // Other missing-PID cases, including a missing result, remain unknown.
174
296
  if (output !== undefined &&
175
297
  (output.status === "target-error" || output.status === "launch-error") &&
176
298
  (await readTargetPid(paths.pid)) === undefined)
177
299
  targetTermination = "terminated";
300
+ retained.targetStopped = targetTermination === "terminated";
301
+ if (retained.processStopped && retained.targetStopped)
302
+ this.#pendingCleanup = undefined;
178
303
  const terminated = targetTermination === "terminated";
179
304
  const cleanupDetails = [
180
305
  exited.cleanupFailure,
@@ -184,16 +309,7 @@ export class LldbCallTracer {
184
309
  ? undefined
185
310
  : {
186
311
  reason: cleanupDetails.join("; "),
187
- resources: [
188
- ...(exited.cleanupFailure === undefined
189
- ? []
190
- : ["lldb-process-group"]),
191
- ...(terminated
192
- ? []
193
- : [
194
- `native-target:${String((await readTargetPid(paths.pid)) ?? "unknown")}`,
195
- ]),
196
- ],
312
+ resources: await lldbCleanupResources(retained),
197
313
  };
198
314
  const partialReason = exited.kind === "cancelled"
199
315
  ? "cancelled"
@@ -228,18 +344,24 @@ export class LldbCallTracer {
228
344
  if (output !== undefined && output.status !== "traced")
229
345
  return err(tracerFailure(output, lifecycleCleanup, await getPartialObservation()));
230
346
  if (exited.cleanupFailure !== undefined)
231
- return err(new ProviderAdapterError(PROVIDER, OPERATION, {
232
- cleanup: lifecycleCleanup ?? {
233
- reason: exited.cleanupFailure,
234
- resources: ["lldb-process-group"],
235
- },
236
- diagnostics: {
237
- reason: "LLDB process-group cleanup could not be verified",
238
- cleanup_failure: exited.cleanupFailure,
239
- ...(lifecycleCleanup === undefined
240
- ? {}
241
- : { target_cleanup: lifecycleCleanup }),
242
- },
347
+ return err(new ProviderCleanupError(PROVIDER, await lldbCleanupResources(retained), {
348
+ reason: "LLDB process-group cleanup could not be verified",
349
+ cleanup_failure: exited.cleanupFailure,
350
+ ...(lifecycleCleanup === undefined
351
+ ? {}
352
+ : { target_cleanup: lifecycleCleanup }),
353
+ }, {
354
+ operation: OPERATION,
355
+ partialObservation: await getPartialObservation(),
356
+ }));
357
+ if (!terminated)
358
+ return err(new ProviderCleanupError(PROVIDER, await lldbCleanupResources(retained), {
359
+ reason: "LLDB target process termination could not be verified",
360
+ ...(lifecycleCleanup === undefined
361
+ ? {}
362
+ : { target_cleanup: lifecycleCleanup }),
363
+ }, {
364
+ operation: OPERATION,
243
365
  partialObservation: await getPartialObservation(),
244
366
  }));
245
367
  if (output === undefined)
@@ -345,6 +467,37 @@ const partialNativeObservation = async (options) => {
345
467
  reason: options.reason,
346
468
  });
347
469
  };
470
+ const partialObservationFromTrace = (request, trace) => projectLldbPartialObservation({
471
+ target: {
472
+ path: request.executable,
473
+ sha256: request.expectedSha256,
474
+ architecture: request.architecture,
475
+ arguments: request.input.arguments,
476
+ environment: request.input.environment,
477
+ working_directory: request.input.working_directory ?? null,
478
+ },
479
+ pid: trace.run.pid,
480
+ stdout: trace.stdout,
481
+ stderr: trace.stderr,
482
+ version: trace.run.version,
483
+ journal: {
484
+ events: trace.run.events,
485
+ otherStops: trace.run.other_stops,
486
+ limitations: [],
487
+ },
488
+ reason: "cleanup-failure",
489
+ });
490
+ const lldbRuntimePaths = (directory) => ({
491
+ config: join(directory, "config.json"),
492
+ result: join(directory, "result.json"),
493
+ pid: join(directory, "pid"),
494
+ identityAck: join(directory, "identity.ack"),
495
+ stdout: join(directory, "stdout"),
496
+ stderr: join(directory, "stderr"),
497
+ stdoutCapture: join(directory, "stdout.capture"),
498
+ stderrCapture: join(directory, "stderr.capture"),
499
+ observations: join(directory, "observations.jsonl"),
500
+ });
348
501
  const readTracerOutput = async (path) => {
349
502
  let text;
350
503
  try {
@@ -389,17 +542,43 @@ const capturedOutput = async (path, observedBytes, truncated, complete) => {
389
542
  return err(failure);
390
543
  }
391
544
  };
545
+ const lldbCleanupResources = async (owner) => [
546
+ ...(owner.processStopped ? [] : ["lldb-process-group"]),
547
+ ...(owner.targetStopped
548
+ ? []
549
+ : [
550
+ `native-target:${String((await readTargetPid(owner.pidPath)) ?? "unknown")}`,
551
+ ]),
552
+ owner.root.path,
553
+ ];
392
554
  /** Supervise LLDB as an owned process group while observing its target PID identity. */
393
555
  const runLldb = async (executable, arguments_, options) => {
394
556
  if (options.signal?.aborted === true)
395
557
  return {
396
558
  kind: "cancelled",
559
+ targetLaunched: false,
397
560
  targetIdentity: undefined,
398
561
  cleanupFailure: undefined,
399
562
  };
400
563
  const deadline = new ProviderStartupDeadline(options.deadlineMs, options.signal);
401
564
  let targetIdentity;
402
565
  let supervisor;
566
+ let retained = false;
567
+ const finish = async (outcome) => {
568
+ const stopped = await supervisor?.stop();
569
+ retained = stopped?.status === "incomplete";
570
+ return {
571
+ ...(deadline.interruption === undefined
572
+ ? outcome
573
+ : { kind: deadline.interruption }),
574
+ targetLaunched: supervisor !== undefined,
575
+ targetIdentity,
576
+ cleanupFailure: stopped?.status === "incomplete" ? stopped.reason : undefined,
577
+ ...(retained && supervisor !== undefined
578
+ ? { cleanupOwner: supervisor }
579
+ : {}),
580
+ };
581
+ };
403
582
  try {
404
583
  const launched = await spawnOwnedProviderProcess({
405
584
  command: executable,
@@ -431,49 +610,33 @@ const runLldb = async (executable, arguments_, options) => {
431
610
  identityAckWritten = true;
432
611
  }
433
612
  const interruption = deadline.interruption;
434
- if (interruption !== undefined) {
435
- const stopped = await supervisor.stop();
436
- const cleanupFailure = stopped.status === "incomplete" ? stopped.reason : undefined;
437
- return interruption === "cancelled"
438
- ? { kind: "cancelled", targetIdentity, cleanupFailure }
439
- : { kind: "timeout", targetIdentity, cleanupFailure };
440
- }
613
+ if (interruption !== undefined)
614
+ return await finish({ kind: interruption });
441
615
  await waitForAbortableDelay(20, deadline.signal);
442
616
  }
443
617
  const snapshot = supervisor.snapshot();
444
- const stopped = await supervisor.stop();
445
- const cleanupFailure = stopped.status === "incomplete" ? stopped.reason : undefined;
446
618
  const interruption = deadline.interruption;
447
- if (interruption === "cancelled")
448
- return { kind: "cancelled", targetIdentity, cleanupFailure };
449
- if (interruption === "timeout")
450
- return { kind: "timeout", targetIdentity, cleanupFailure };
451
- return {
452
- kind: "exited",
453
- exitCode: snapshot.exitCode ?? null,
454
- output: `${snapshot.stdout.text}${snapshot.stderr.text}`.slice(-DIAGNOSTIC_BYTES),
455
- targetIdentity,
456
- cleanupFailure,
457
- };
619
+ return await finish(interruption === undefined
620
+ ? {
621
+ kind: "exited",
622
+ exitCode: snapshot.exitCode ?? null,
623
+ output: `${snapshot.stdout.text}${snapshot.stderr.text}`.slice(-DIAGNOSTIC_BYTES),
624
+ }
625
+ : { kind: interruption });
458
626
  }
459
627
  catch (cause) {
460
628
  const interruption = deadline.interruption;
461
- const stopped = await supervisor?.stop();
462
- const cleanupFailure = stopped?.status === "incomplete" ? stopped.reason : undefined;
463
- return interruption === "timeout"
464
- ? { kind: "timeout", targetIdentity, cleanupFailure }
465
- : interruption === "cancelled"
466
- ? { kind: "cancelled", targetIdentity, cleanupFailure }
467
- : {
468
- kind: "exited",
469
- exitCode: null,
470
- output: cause instanceof Error ? cause.message : String(cause),
471
- targetIdentity,
472
- cleanupFailure,
473
- };
629
+ return await finish(interruption === undefined
630
+ ? {
631
+ kind: "exited",
632
+ exitCode: null,
633
+ output: cause instanceof Error ? cause.message : String(cause),
634
+ }
635
+ : { kind: interruption });
474
636
  }
475
637
  finally {
476
- supervisor?.dispose();
638
+ if (!retained)
639
+ supervisor?.dispose();
477
640
  deadline.dispose();
478
641
  }
479
642
  };
@@ -483,8 +646,11 @@ const runLldb = async (executable, arguments_, options) => {
483
646
  */
484
647
  const readTargetPid = async (pidPath) => {
485
648
  try {
486
- const pid = Number.parseInt(await readFile(pidPath, "utf8"), 10);
487
- return Number.isSafeInteger(pid) && pid > 0 ? pid : undefined;
649
+ const contents = (await readFile(pidPath, "utf8")).trim();
650
+ if (!/^[1-9]\d*$/u.test(contents))
651
+ return undefined;
652
+ const pid = Number(contents);
653
+ return Number.isSafeInteger(pid) ? pid : undefined;
488
654
  }
489
655
  catch {
490
656
  return undefined;
@@ -29,13 +29,14 @@ import { architectureLocations, inspectNativeMacho, } from "./NativeMachoInspect
29
29
  /** Read-only semantic provider composed from Xcode command-line utilities. */
30
30
  export class NativeMacOSProvider {
31
31
  runner;
32
- tracer;
33
32
  #capabilities;
34
33
  #environment;
35
- constructor(environment, runner = new XcrunCommandRunner(environment), platform = process.platform, tracer = new LldbCallTracer(environment)) {
34
+ #tracerFactory;
35
+ constructor(environment, runner = new XcrunCommandRunner(environment), platform = process.platform, tracerFactory) {
36
36
  this.runner = runner;
37
- this.tracer = tracer;
38
37
  this.#environment = snapshotEnvironment(environment, platform);
38
+ this.#tracerFactory =
39
+ tracerFactory ?? (() => new LldbCallTracer(this.#environment));
39
40
  this.#capabilities = nativeMacOSCapabilities(platform);
40
41
  }
41
42
  identity() {
@@ -45,7 +46,7 @@ export class NativeMacOSProvider {
45
46
  return this.#capabilities;
46
47
  }
47
48
  createClient(target) {
48
- return new NativeMacOSClient(target, this.runner, this.tracer, this.#environment);
49
+ return new NativeMacOSClient(target, this.runner, this.#tracerFactory(), this.#environment);
49
50
  }
50
51
  }
51
52
  class NativeMacOSClient {
@@ -133,7 +134,7 @@ class NativeMacOSClient {
133
134
  }
134
135
  }
135
136
  close() {
136
- return Promise.resolve(ok(null));
137
+ return this.tracer.close();
137
138
  }
138
139
  #dispatch(operation, parameters, signal) {
139
140
  switch (operation) {
@@ -154,6 +155,10 @@ class NativeMacOSClient {
154
155
  }
155
156
  }
156
157
  async #listArchitectures(signal) {
158
+ // lipo reads only Mach-O; its refusal of a PE, ELF, or plist target is not
159
+ // a tool failure that a retry or `rea doctor` could repair.
160
+ if (this.target.format !== "mach-o")
161
+ return err(new AnalysisCapabilityUnavailableError(IDENTITY.id, "list_architectures", "Active artifact is not Mach-O."));
157
162
  const capture = await this.#run("list_architectures", "lipo", ["-detailed_info", this.target.path], { signal });
158
163
  if (!capture.ok)
159
164
  return capture;
@@ -5,7 +5,6 @@ export const NATIVE_MACOS_PROVIDER_IDENTITY = Object.freeze({
5
5
  name: "macOS native inspection utilities",
6
6
  version: null,
7
7
  });
8
- const IDENTITY = NATIVE_MACOS_PROVIDER_IDENTITY;
9
8
  /** Operations whose target process can show UI, use the network and write files. */
10
9
  const OWNED_PROCESS_OPERATIONS = new Set([
11
10
  "capture_native_ui_scenario",
@@ -26,7 +25,7 @@ export const nativeMacOSCapabilities = (platform = process.platform) => {
26
25
  reason: "Native macOS utilities require macOS.",
27
26
  };
28
27
  return Object.freeze({
29
- provider: IDENTITY,
28
+ provider: NATIVE_MACOS_PROVIDER_IDENTITY,
30
29
  operation: contract.name,
31
30
  ...availability,
32
31
  effects: Object.freeze({
@@ -5,7 +5,7 @@ import { descendantsOf, liveProcesses } from "./ProcessOwnershipProcessTree.js";
5
5
  import { execFileOutput } from "./ExecFileOutput.js";
6
6
  import { createDarwinProcessRunTokenReader } from "./DarwinProcessRunTokenReader.js";
7
7
  /** Observe one group without signaling it, failing closed on identity doubt. */
8
- export const observeOwnedProcessGroupWithHost = async (ownership, host, signal) => {
8
+ export const observeOwnedProcessGroup = async (ownership, host = systemProcessOwnershipHost, signal) => {
9
9
  signal?.throwIfAborted();
10
10
  let members;
11
11
  try {
@@ -45,8 +45,14 @@ export const observeOwnedProcessGroupWithHost = async (ownership, host, signal)
45
45
  }
46
46
  return { state: "alive" };
47
47
  };
48
- /** Record the live launcher and descendant lineage after run-token validation. */
49
- export const observeOwnedProcessLineageWithHost = async (ownership, host) => {
48
+ /**
49
+ * Record the live launcher and descendant lineage after run-token validation.
50
+ *
51
+ * The observation is intentionally point-in-time. A verified empty descendant
52
+ * list means no descendants were live during this observation, not that the
53
+ * run never created a short-lived child.
54
+ */
55
+ export const observeOwnedProcessLineage = async (ownership, host = systemProcessOwnershipHost) => {
50
56
  let processes;
51
57
  try {
52
58
  processes = liveProcesses(await host.listProcesses());
@@ -331,16 +337,6 @@ export const signalProcessWithStartIdentity = async (pid, expectedIdentity, sign
331
337
  export const prepareProcessOwnershipInspection = async (signal) => {
332
338
  await systemProcessOwnershipHost.prepare?.(signal);
333
339
  };
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
340
  const processIsGone = async (host, pid) => {
345
341
  try {
346
342
  return !liveProcesses(await host.listProcesses()).some((process) => process.pid === pid);