rea-agents 5.0.0 → 6.0.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 (275) hide show
  1. package/README.md +157 -650
  2. package/bridge/mitmproxy/capture.py +210 -0
  3. package/bridge/native/rea_lldb_tracer.py +303 -0
  4. package/bridge/process/ProcessRunTokenReader.swift +263 -0
  5. package/bridge/process/ProcessRunTokenReaderMain.swift +35 -0
  6. package/bridge/pwndbg/core_context.py +101 -0
  7. package/bridge/pwndbg/launch.py +39 -0
  8. package/bridge/pwndbg/launch_impl.py +34 -0
  9. package/bridge/pwntools/decoder_runtime.py +59 -0
  10. package/bridge/pwntools/layout.py +39 -0
  11. package/bridge/pwntools/layout_impl.py +309 -0
  12. package/bridge/pwntools/recorded_crash.py +39 -0
  13. package/bridge/pwntools/recorded_crash_impl.py +143 -0
  14. package/dist/android/JadxProvider.js +1 -0
  15. package/dist/application/CapabilityInventory.js +21 -0
  16. package/dist/application/DirectAnalysis.js +97 -23
  17. package/dist/application/EvidenceBundleFiles.js +1 -1
  18. package/dist/application/ReconstructionObligationCandidates.js +5 -1
  19. package/dist/application/WebNetworkCapturePort.js +1 -0
  20. package/dist/application/WebNetworkCaptureService.js +132 -0
  21. package/dist/application/WindowsCapabilities.js +1 -1
  22. package/dist/application/binary/AnalysisSnapshotCache.js +49 -6
  23. package/dist/application/binary/BinarySession.js +38 -10
  24. package/dist/application/binary/BinarySessionOpen.js +16 -3
  25. package/dist/application/binary/BinarySessionRecords.js +20 -0
  26. package/dist/application/binaryDiagnostics/BinaryLayoutPort.js +1 -0
  27. package/dist/application/binaryDiagnostics/BinaryLayoutService.js +57 -0
  28. package/dist/application/binaryDiagnostics/RecordedCrashPort.js +1 -0
  29. package/dist/application/binaryDiagnostics/RecordedCrashService.js +60 -0
  30. package/dist/application/evm/EvmInterfacePort.js +1 -0
  31. package/dist/application/evm/EvmInterfaceService.js +62 -0
  32. package/dist/application/javascript/JavaScriptApplicationEvidence.js +1 -2
  33. package/dist/application/javascript/JavaScriptApplicationService.js +15 -2
  34. package/dist/application/javascript/JavaScriptArtifactAnalysis.js +42 -23
  35. package/dist/application/javascript/JavaScriptArtifactGraphDocuments.js +26 -2
  36. package/dist/application/javascript/JavaScriptArtifactPathResolution.js +74 -24
  37. package/dist/application/javascript/JavaScriptArtifactReconstruction.js +23 -10
  38. package/dist/application/javascript/JavaScriptSemanticGraphAsyncProjection.js +7 -7
  39. package/dist/application/javascript/JavaScriptSemanticGraphBuilder.js +145 -70
  40. package/dist/application/javascript/JavaScriptSemanticGraphChildProcessProjection.js +14 -15
  41. package/dist/application/javascript/JavaScriptSemanticGraphConstruction.js +41 -1
  42. package/dist/application/javascript/JavaScriptSemanticGraphDataProjection.js +7 -7
  43. package/dist/application/javascript/JavaScriptSemanticGraphFlowProjection.js +5 -9
  44. package/dist/application/javascript/JavaScriptSemanticGraphObjectProjection.js +3 -3
  45. package/dist/application/javascript/JavaScriptSemanticGraphProjection.js +118 -12
  46. package/dist/application/javascript/JavaScriptSemanticGraphResourceProjection.js +3 -3
  47. package/dist/application/javascript/JavaScriptSemanticGraphValueProjection.js +5 -5
  48. package/dist/application/{ProcessCli.js → process/ProcessCli.js} +10 -10
  49. package/dist/application/{ProcessEvidence.js → process/ProcessEvidence.js} +4 -4
  50. package/dist/artifacts/ArtifactProvider.js +30 -3
  51. package/dist/artifacts/ArtifactProviderMetadata.js +2 -1
  52. package/dist/artifacts/ZipArtifactReader.js +3 -0
  53. package/dist/artifacts/apple/DylibResolutionReader.js +259 -0
  54. package/dist/artifacts/apple/MachoLoadCommandReader.js +294 -0
  55. package/dist/{application → artifacts/extraction}/ArtifactExtraction.js +10 -10
  56. package/dist/{application → artifacts/inventory}/ArtifactGraphConstruction.js +3 -3
  57. package/dist/{application → artifacts/inventory}/ArtifactInventory.js +4 -4
  58. package/dist/{application/ArtifactInventory → artifacts/inventory}/classify.js +2 -2
  59. package/dist/{application/ArtifactInventory → artifacts/inventory}/reader.js +5 -5
  60. package/dist/{application/ArtifactInventory → artifacts/inventory}/scanCanonical.js +3 -3
  61. package/dist/{application/ArtifactInventory → artifacts/inventory}/scanReader.js +5 -5
  62. package/dist/artifacts/readStableArtifact.js +20 -4
  63. package/dist/browser/CdpCaptureEventHandlers.js +90 -2
  64. package/dist/browser/CdpCaptureEvents.js +9 -0
  65. package/dist/browser/PlaywrightElectronActiveProvider.js +12 -3
  66. package/dist/browser/history/CaptureFailures.js +101 -0
  67. package/dist/browser/history/CaptureFormatError.js +10 -0
  68. package/dist/browser/history/CaptureRedaction.js +65 -0
  69. package/dist/browser/history/CaptureRelease.js +12 -0
  70. package/dist/browser/history/HarCapture.js +165 -0
  71. package/dist/browser/history/HarCaptureAdapter.js +20 -0
  72. package/dist/browser/history/HarCaptureProcess.js +57 -0
  73. package/dist/browser/history/HarJson.js +91 -0
  74. package/dist/browser/history/HarSchema.js +72 -0
  75. package/dist/browser/history/HistoricalCaptureDecoder.js +186 -0
  76. package/dist/browser/history/HistoricalCaptureFormatAdapter.js +1 -0
  77. package/dist/browser/history/MitmproxyCaptureAdapter.js +42 -0
  78. package/dist/cli/artifactCommands.js +26 -1
  79. package/dist/cli/binaryDiagnosticsCommands.js +39 -0
  80. package/dist/cli/coreAnalysisCommands.js +2 -2
  81. package/dist/cli/coreBinaryCommands.js +8 -8
  82. package/dist/cli/electronCommands.js +16 -9
  83. package/dist/cli/evmCommands.js +24 -0
  84. package/dist/cli/firmwareCommands.js +6 -3
  85. package/dist/cli/javascriptApplicationAnalysis.js +16 -3
  86. package/dist/cli/jsonOutput.js +133 -0
  87. package/dist/cli/nativeCallCommands.js +35 -0
  88. package/dist/cli/processCommands.js +1 -1
  89. package/dist/cli/streamedJsonOutput.js +56 -0
  90. package/dist/cli/utilityCommands.js +2 -0
  91. package/dist/cli/webNetworkCaptureCommands.js +40 -0
  92. package/dist/cli.js +9 -3
  93. package/dist/cliBrowserScenarioCommands.js +2 -2
  94. package/dist/cliCommandNames.js +6 -0
  95. package/dist/cliJsonInput.js +30 -1
  96. package/dist/cliOutput.js +21 -6
  97. package/dist/composition/binaryDiagnostics.js +8 -0
  98. package/dist/composition/evm.js +4 -0
  99. package/dist/composition/webNetworkCaptures.js +6 -0
  100. package/dist/contracts/artifactToolContracts.js +6 -0
  101. package/dist/contracts/browserCaptureToolInputSchema.js +43 -0
  102. package/dist/contracts/browserToolContracts.js +4 -3
  103. package/dist/contracts/errorSchemas.js +8 -1
  104. package/dist/contracts/evm/evmToolContracts.js +20 -0
  105. package/dist/contracts/investigationExamples.js +2 -2
  106. package/dist/contracts/managed/managedToolContracts.js +7 -3
  107. package/dist/contracts/native/binaryDiagnosticsToolContracts.js +42 -0
  108. package/dist/contracts/native/nativeToolContracts.js +17 -1
  109. package/dist/contracts/officialToolContracts.js +12 -9
  110. package/dist/contracts/process/processCaptureExample.js +2 -0
  111. package/dist/contracts/sessionLifecycleInputs.js +22 -5
  112. package/dist/contracts/sessionStatusContract.js +10 -2
  113. package/dist/contracts/sessionToolContracts.js +8 -1
  114. package/dist/contracts/sessionToolSchemas.js +10 -3
  115. package/dist/contracts/toolContractExamples.js +1 -1
  116. package/dist/contracts/toolContracts.js +6 -0
  117. package/dist/contracts/toolEffects.js +30 -0
  118. package/dist/contracts/toolOutputSchemaGroups.js +5 -1
  119. package/dist/contracts/toolOutputSchemaPrimitives.js +1 -1
  120. package/dist/contracts/webNetworkCaptureToolContracts.js +24 -0
  121. package/dist/domain/analysisErrorBase.js +15 -0
  122. package/dist/domain/analysisErrorCore.js +59 -5
  123. package/dist/domain/analysisErrorPresentation.js +29 -1
  124. package/dist/domain/analysisErrorProjection.js +52 -2
  125. package/dist/domain/analysisSnapshot.js +166 -2
  126. package/dist/domain/apple/dyldPaths.js +81 -0
  127. package/dist/domain/apple/dylibResolution.js +367 -0
  128. package/dist/domain/apple/dylibResolutionFindings.js +75 -0
  129. package/dist/domain/artifactPathSyntax.js +1 -1
  130. package/dist/domain/browserObservation.js +1 -1
  131. package/dist/domain/browserObservationSchemas.js +13 -0
  132. package/dist/domain/browserScenarioValues.js +9 -2
  133. package/dist/domain/callPathSchemas.js +1 -1
  134. package/dist/domain/canonicalDigest.js +13 -1
  135. package/dist/domain/changedBehavior.js +3 -3
  136. package/dist/domain/comparisonStatus.js +2 -30
  137. package/dist/domain/conformanceTrustGate.js +0 -16
  138. package/dist/domain/evidence.js +17 -5
  139. package/dist/domain/evm/evmInterface.js +63 -0
  140. package/dist/domain/explicitSensitiveFailure.js +92 -0
  141. package/dist/domain/explicitSensitiveValues.js +10 -0
  142. package/dist/domain/firmware/firmwareAnalysis.js +8 -1
  143. package/dist/domain/javascript/electronActiveObservation.js +9 -4
  144. package/dist/domain/javascript/htmlArtifactReferences.js +40 -0
  145. package/dist/domain/javascript/javascriptExportShapeComparison.js +21 -5
  146. package/dist/domain/javascript/javascriptExportShapeVariants.js +0 -10
  147. package/dist/domain/javascript/javascriptSemanticGraph.js +21 -5
  148. package/dist/domain/jsonValue.js +4 -0
  149. package/dist/domain/localPath.js +2 -0
  150. package/dist/domain/native/binaryLayout.js +357 -0
  151. package/dist/domain/native/nativeCallObservation.js +164 -0
  152. package/dist/domain/native/objcSwiftMetadata.js +0 -39
  153. package/dist/domain/native/recordedCrash.js +266 -0
  154. package/dist/domain/native/recordedCrashNoteCoverage.js +73 -0
  155. package/dist/domain/{processCapture.js → process/processCapture.js} +139 -2
  156. package/dist/domain/{processCaptureExample.js → process/processCaptureExample.js} +5 -0
  157. package/dist/domain/process/processCaptureParsing.js +54 -0
  158. package/dist/domain/{processCaptureValidation.js → process/processCaptureValidation.js} +18 -2
  159. package/dist/domain/{processComparison.js → process/processComparison.js} +1 -1
  160. package/dist/domain/{processObservation.js → process/processObservation.js} +1 -1
  161. package/dist/domain/{processTraceSpecification.js → process/processTraceSpecification.js} +1 -1
  162. package/dist/domain/providerSelectionError.js +4 -2
  163. package/dist/domain/reconstructionVerification.js +3 -3
  164. package/dist/domain/reconstructionVerificationSchemas.js +1 -1
  165. package/dist/domain/residualUnknown.js +3 -2
  166. package/dist/domain/staticRuntimeCorrelation.js +3 -3
  167. package/dist/domain/webCaptureDiff.js +1 -0
  168. package/dist/domain/webNetworkCapture.js +118 -0
  169. package/dist/domain/webNetworkCaptureCoordinates.js +58 -0
  170. package/dist/dotnet/ManagedExceptionRegionValidation.js +41 -0
  171. package/dist/dotnet/ManagedMemberInspector.js +4 -2
  172. package/dist/dotnet/ManagedMemberInspectorCore.js +38 -32
  173. package/dist/dotnet/ManagedMemberInstructionDecoder.js +23 -7
  174. package/dist/dotnet/ManagedMemberRows.js +14 -3
  175. package/dist/dotnet/ManagedMetadataHeaps.js +20 -2
  176. package/dist/dotnet/ManagedMetadataInventory.js +38 -28
  177. package/dist/dotnet/ManagedMetadataInventoryRows.js +24 -10
  178. package/dist/dotnet/ManagedMethodBodyReader.js +7 -1
  179. package/dist/dotnet/ManagedNativeBoundaryHelpers.js +15 -3
  180. package/dist/dotnet/ManagedNativeBoundaryInspector.js +3 -1
  181. package/dist/dotnet/ManagedPeReader.js +11 -0
  182. package/dist/evm/EvmBytecodeCarrier.js +21 -0
  183. package/dist/evm/EvmWorkerLimits.js +40 -0
  184. package/dist/evm/EvmoleFailures.js +126 -0
  185. package/dist/evm/EvmoleInterfaceAdapter.js +53 -0
  186. package/dist/evm/EvmoleInterfaceProvider.js +273 -0
  187. package/dist/evm/EvmoleInterfaceWorker.js +87 -0
  188. package/dist/evm/EvmoleRelease.js +16 -0
  189. package/dist/firmware/FirmwareCommand.js +1 -0
  190. package/dist/generatedPackageMetadata.js +2 -2
  191. package/dist/ghidra/GhidraLauncher.js +1 -0
  192. package/dist/ghidra/GhidraProvider.js +2 -2
  193. package/dist/ghidra/GhidraProviderCapabilities.js +1 -1
  194. package/dist/hopper/BridgeLauncher.js +2 -0
  195. package/dist/hopper/LinuxPrivateDisplayProbe.js +4 -2
  196. package/dist/javascript/recovery/WakaruCommand.js +3 -0
  197. package/dist/javascript/sourceMaps/SourceMapCommand.js +1 -0
  198. package/dist/native/CommandRunner.js +2 -1
  199. package/dist/native/LldbCallTracer.js +278 -0
  200. package/dist/native/NativeCallObservation.js +135 -0
  201. package/dist/native/NativeMacOSProvider.js +19 -3
  202. package/dist/native/NativeMacOSProviderMetadata.js +8 -3
  203. package/dist/native/pwndbg/PwndbgCoreContext.js +160 -0
  204. package/dist/native/pwntools/PwntoolsDecoder.js +203 -0
  205. package/dist/native/pwntools/PwntoolsFailures.js +180 -0
  206. package/dist/native/pwntools/PwntoolsLayoutProvider.js +36 -0
  207. package/dist/native/pwntools/PwntoolsRecordedCrashProvider.js +75 -0
  208. package/dist/native/pwntools/PwntoolsRelease.js +19 -0
  209. package/dist/native/pwntools/PwntoolsResourceLimits.js +76 -0
  210. package/dist/native/pwntools/RecordedCrashSourceBindings.js +46 -0
  211. package/dist/native/pwntools/RecordedCrashStructureBindings.js +101 -0
  212. package/dist/process/DarwinProcessRunTokenReader.js +294 -0
  213. package/dist/process/OwnedCommand.js +113 -0
  214. package/dist/process/ProcessOwnership.js +263 -33
  215. package/dist/process/ProcessOwnershipObservation.js +161 -24
  216. package/dist/process/ProviderProcess.js +30 -3
  217. package/dist/{application → process/capture}/ProcessCaptureCapability.js +15 -0
  218. package/dist/{application → process/capture}/ProcessCaptureError.js +17 -1
  219. package/dist/process/capture/ProcessCaptureLifecycle.js +615 -0
  220. package/dist/{application → process/capture}/ProcessHarness.js +195 -29
  221. package/dist/{application → process/capture}/ProcessSampling.js +2 -2
  222. package/dist/server/createServer.js +22 -0
  223. package/dist/server/promptCompletion.js +10 -3
  224. package/dist/server/registerBinaryDiagnosticsTools.js +17 -0
  225. package/dist/server/registerEvidenceTools.js +1 -1
  226. package/dist/server/registerEvmTools.js +17 -0
  227. package/dist/server/registerProcessComparisonTool.js +1 -1
  228. package/dist/server/registerRecordedCrashTools.js +17 -0
  229. package/dist/server/registerSessionTools.js +2 -2
  230. package/dist/server/registerWebNetworkCaptureTool.js +28 -0
  231. package/dist/server/sessionAvailabilityPolicy.js +3 -0
  232. package/dist/server/sessionToolPolicies.js +1 -1
  233. package/dist/server/toolResult.js +1 -1
  234. package/native/windows/build/manifest.json +2 -2
  235. package/native/windows/build/rea-windows-x64.node +0 -0
  236. package/package.json +37 -9
  237. package/scripts/rea.mjs +11 -3
  238. package/skills/reverse-engineer-anything/SKILL.md +23 -3
  239. package/skills/reverse-engineer-anything/references/native-and-artifacts.md +29 -0
  240. package/third_party/README.md +60 -0
  241. package/third_party/evmole/LICENSE +21 -0
  242. package/third_party/evmole/README.md +22 -0
  243. package/third_party/pwndbg/LICENSE.md +21 -0
  244. package/third_party/pwndbg/README.md +23 -0
  245. package/third_party/pwntools/README.md +40 -0
  246. package/dist/application/AuthorizedArtifactInventory.js +0 -7
  247. package/dist/application/ProcessCaptureLifecycle.js +0 -299
  248. package/dist/application/StoreFileLock.js +0 -124
  249. package/dist/contracts/processCaptureExample.js +0 -2
  250. package/dist/domain/bytecodeProvider.js +0 -178
  251. package/dist/domain/customProtocolCapture.js +0 -137
  252. package/dist/domain/eventProcessTree.js +0 -225
  253. package/dist/domain/mobileApplicationInvestigation.js +0 -159
  254. package/dist/domain/packageAnalysis.js +0 -123
  255. package/dist/domain/peInspection.js +0 -197
  256. package/dist/domain/processCaptureParsing.js +0 -21
  257. package/dist/domain/protocolCapture.js +0 -217
  258. package/dist/domain/runtimeIdentification.js +0 -212
  259. package/dist/generatedMcpToolCatalog.js +0 -37
  260. /package/dist/application/{ArtifactExtractionDestination.js → artifacts/ArtifactExtractionDestination.js} +0 -0
  261. /package/dist/{application/ArtifactInventory → artifacts/inventory}/policy.js +0 -0
  262. /package/dist/{application/ArtifactInventory → artifacts/inventory}/types.js +0 -0
  263. /package/dist/domain/{processEvidenceProvider.js → process/processEvidenceProvider.js} +0 -0
  264. /package/dist/domain/{processScenario.js → process/processScenario.js} +0 -0
  265. /package/dist/domain/{processTraceComparison.js → process/processTraceComparison.js} +0 -0
  266. /package/dist/domain/{processTraceDimensionProjection.js → process/processTraceDimensionProjection.js} +0 -0
  267. /package/dist/domain/{processTraceEvaluation.js → process/processTraceEvaluation.js} +0 -0
  268. /package/dist/{application → process/capture}/FilesystemSnapshot.js +0 -0
  269. /package/dist/{application → process/capture}/ProcessCaptureEnvironment.js +0 -0
  270. /package/dist/{application → process/capture}/ProcessCaptureJournal.js +0 -0
  271. /package/dist/{application → process/capture}/ProcessFilesystemEffects.js +0 -0
  272. /package/dist/{application → process/capture}/ProcessNormalization.js +0 -0
  273. /package/dist/{application → process/capture}/ProcessScenarioRuntimeValidation.js +0 -0
  274. /package/dist/{application → process/capture}/ProcessTimer.js +0 -0
  275. /package/dist/{application → process/capture}/TerminalRenderer.js +0 -0
@@ -1,299 +0,0 @@
1
- import { createHash, randomUUID } from "node:crypto";
2
- import { createReadStream } from "node:fs";
3
- import { mkdtemp, rm } from "node:fs/promises";
4
- import { tmpdir } from "node:os";
5
- import { join } from "node:path";
6
- import { digestProcessCommitment, processComparisonContract, processScenarioCommitment, } from "../domain/processCapture.js";
7
- import { PRODUCT_IDENTITY } from "../identity.js";
8
- import { snapshotRoots } from "./FilesystemSnapshot.js";
9
- import { classifyFilesystemEffects } from "./ProcessFilesystemEffects.js";
10
- import { cleanupOwnedProcessGroup } from "../process/ProcessOwnership.js";
11
- import { observeOwnedProcessGroup } from "../process/ProcessOwnershipObservation.js";
12
- import { ProcessCaptureError } from "./ProcessCaptureError.js";
13
- import { assertNotCancelled } from "./ProcessScenarioRuntimeValidation.js";
14
- import { normalizeProcessElapsedTime, normalizeProcessSamples, normalizeProcessText, } from "./ProcessNormalization.js";
15
- import { PROCESS_PROVIDER } from "./ProcessEvidence.js";
16
- import { TerminalRenderer } from "./TerminalRenderer.js";
17
- import { scheduleProcessInterval } from "./ProcessTimer.js";
18
- /** Wait for trailing PTY callbacks before the capture becomes immutable. */
19
- export const settleProcessCaptureJournal = async (journal, quietMs = 25, maxWaitMs = 500) => {
20
- const deadline = Date.now() + maxWaitMs;
21
- let observed = journal.length;
22
- let lastChangeAt = Date.now();
23
- while (Date.now() < deadline) {
24
- await new Promise((resolve) => setTimeout(resolve, 4));
25
- if (journal.length !== observed) {
26
- observed = journal.length;
27
- lastChangeAt = Date.now();
28
- }
29
- else if (Date.now() - lastChangeAt >= quietMs)
30
- return;
31
- }
32
- };
33
- export const buildCaptureResult = (options) => {
34
- const hasSensitiveScriptedInput = options.scenario.events.some((event) => event.type === "input" && event.sensitive);
35
- const sensitiveInputUnknown = "Sensitive scripted input values are redacted from process capture Evidence.";
36
- const filesystemObservationUnknown = "No filesystem observation paths were selected; filesystem effects remain unknown.";
37
- const hasFilesystemObservations = options.scenario.filesystem_observation_paths.length > 0;
38
- return {
39
- manifest: options.manifest,
40
- normalization: options.scenario.normalization,
41
- frames: options.frames,
42
- rendered_frames: options.renderedFrames,
43
- interaction_events: options.interactions,
44
- exit: {
45
- code: options.exit.reason === "exited" && options.exit.exitCode >= 0
46
- ? options.exit.exitCode
47
- : null,
48
- signal: options.exit.signal ?? null,
49
- reason: options.exit.reason,
50
- },
51
- settlement: options.settlement,
52
- process_samples: normalizeProcessSamples(options.samples, options.scenario, options.rootPid),
53
- filesystem_checkpoints: options.checkpoints,
54
- event_journal: options.eventJournal,
55
- files_before: options.before.files,
56
- files_after: options.after.files,
57
- filesystem_effects: classifyFilesystemEffects(options.before.files, options.after.files),
58
- truncated: options.truncated,
59
- limitations: [
60
- "Process trees are sampled and may omit short-lived descendants.",
61
- ...(options.samplingPartial
62
- ? ["Process-tree sampling ended with an incomplete observation."]
63
- : []),
64
- "Filesystem observations are before/after snapshots, not syscall traces.",
65
- "Inherited host environment variables are not recorded and may affect results.",
66
- ...(!hasFilesystemObservations ? [filesystemObservationUnknown] : []),
67
- ...(hasSensitiveScriptedInput ? [sensitiveInputUnknown] : []),
68
- ],
69
- residual_unknowns: [
70
- {
71
- scope: "process",
72
- reason: "Process trees are sampled and may omit short-lived descendants.",
73
- },
74
- {
75
- scope: "environment",
76
- reason: "Inherited host environment variables are not recorded.",
77
- },
78
- {
79
- scope: "network",
80
- reason: "Network activity is not observed by this capture.",
81
- },
82
- ...(!hasFilesystemObservations
83
- ? [
84
- {
85
- scope: "filesystem",
86
- reason: filesystemObservationUnknown,
87
- },
88
- ]
89
- : []),
90
- ...(hasSensitiveScriptedInput
91
- ? [{ scope: "interaction", reason: sensitiveInputUnknown }]
92
- : []),
93
- ],
94
- };
95
- };
96
- const hashFile = async (path) => {
97
- const hash = createHash("sha256");
98
- for await (const chunk of createReadStream(path))
99
- hash.update(chunk);
100
- return hash.digest("hex");
101
- };
102
- export const createRunManifest = async (scenario, startedAt, completedAt, host = {
103
- platform: process.platform,
104
- architecture: process.arch,
105
- }) => {
106
- const executableSha256 = await hashFile(scenario.executable);
107
- const scenarioCommitment = processScenarioCommitment(scenario, executableSha256);
108
- const comparisonContract = processComparisonContract(scenario);
109
- return {
110
- rea_version: PRODUCT_IDENTITY.packageVersion,
111
- provider_version: PROCESS_PROVIDER.version,
112
- platform: host.platform,
113
- architecture: host.architecture,
114
- pty_backend: "node-pty",
115
- started_at: startedAt.toISOString(),
116
- completed_at: completedAt.toISOString(),
117
- scenario: scenarioCommitment,
118
- comparison_contract: comparisonContract,
119
- full_scenario_sha256: digestProcessCommitment(scenarioCommitment),
120
- comparison_contract_sha256: digestProcessCommitment(comparisonContract),
121
- executable_sha256: executableSha256,
122
- normalization_sha256: digestProcessCommitment(scenario.normalization),
123
- };
124
- };
125
- export const observeSettlement = async (runId, processGroupIds, settleMs, recordEvent = () => undefined, platform = process.platform) => {
126
- if (platform === "win32") {
127
- recordEvent("lifecycle", 1);
128
- return { state: "unverifiable", elapsed_ms: 0 };
129
- }
130
- const started = Date.now();
131
- let consecutiveEmpty = 0;
132
- let deadlineReached = false;
133
- while (!deadlineReached) {
134
- const observations = await Promise.all([...new Set(processGroupIds)].map((processGroupId) => observeOwnedProcessGroup({
135
- runId,
136
- leaderPid: processGroupId,
137
- processGroupId,
138
- })));
139
- if (observations.some(({ state }) => state === "unverifiable")) {
140
- recordEvent("lifecycle", 1);
141
- return { state: "unverifiable", elapsed_ms: Date.now() - started };
142
- }
143
- if (observations.every(({ state }) => state === "empty")) {
144
- consecutiveEmpty += 1;
145
- if (consecutiveEmpty >= 2) {
146
- recordEvent("lifecycle", 1);
147
- return { state: "quiesced", elapsed_ms: Date.now() - started };
148
- }
149
- }
150
- else
151
- consecutiveEmpty = 0;
152
- deadlineReached = Date.now() - started >= settleMs;
153
- if (deadlineReached)
154
- break;
155
- await new Promise((resolve) => setTimeout(resolve, 50));
156
- }
157
- recordEvent("lifecycle", 1);
158
- return { state: "alive_at_deadline", elapsed_ms: Date.now() - started };
159
- };
160
- export const awaitTerminalExit = async ({ terminal, scenario, started, lastOutput, signal, timers, interactions, dispatchedEventIndexes, recordEvent, }) => new Promise((resolveExit) => {
161
- // The kill caused by a deadline is observed later as an ordinary PTY exit.
162
- // Keep the initiating lifecycle reason so comparisons distinguish a target
163
- // exit from harness-owned timeout, idle-timeout, and cancellation cleanup.
164
- let reason = "exited";
165
- terminal.onExit((exit) => {
166
- recordEvent("lifecycle", 0);
167
- for (const [eventIndex, event] of scenario.events.entries()) {
168
- if (dispatchedEventIndexes.has(eventIndex))
169
- continue;
170
- const sequence = interactions.length;
171
- interactions.push({
172
- sequence,
173
- scheduled_at_ms: event.at_ms,
174
- dispatched_at_ms: Math.max(0, Date.now() - started),
175
- type: event.type,
176
- data: event.type === "input"
177
- ? "<not-dispatched>"
178
- : event.type === "resize"
179
- ? `${String(event.columns)}x${String(event.rows)}`
180
- : event.signal,
181
- outcome: "target_exited",
182
- });
183
- recordEvent("interaction_events", sequence);
184
- }
185
- for (const timer of timers) {
186
- timer.cancel();
187
- }
188
- timers.clear();
189
- resolveExit({ ...exit, reason });
190
- });
191
- const timeout = scheduleProcessInterval(() => {
192
- if (signal?.aborted === true) {
193
- reason = "cancelled";
194
- terminal.kill("SIGKILL");
195
- }
196
- else if (Date.now() - started >= scenario.timeout_ms) {
197
- reason = "timeout";
198
- terminal.kill("SIGKILL");
199
- }
200
- else if (Date.now() - lastOutput() >= scenario.idle_timeout_ms) {
201
- reason = "idle_timeout";
202
- terminal.kill("SIGKILL");
203
- }
204
- }, 20);
205
- timers.add(timeout);
206
- });
207
- const processCaptureCleanupHost = {
208
- platform: process.platform,
209
- cleanupProcessGroup: cleanupOwnedProcessGroup,
210
- removeTemporaryRoot: (path) => rm(path, { recursive: true, force: true }),
211
- };
212
- export const releaseProcessResources = async (options) => {
213
- const host = options.host ?? processCaptureCleanupHost;
214
- for (const timer of options.timers)
215
- timer.cancel();
216
- let failure;
217
- try {
218
- await options.renderer?.dispose();
219
- }
220
- catch (cause) {
221
- void cause;
222
- failure ??= "terminal renderer cleanup failed";
223
- }
224
- if (options.terminal !== undefined && host.platform !== "win32") {
225
- for (const processGroupId of new Set(options.capturedProcessGroupIds)) {
226
- const cleaned = await host.cleanupProcessGroup({
227
- runId: options.runId,
228
- leaderPid: processGroupId,
229
- processGroupId,
230
- });
231
- if (!cleaned.cleaned)
232
- failure ??= cleaned.reason;
233
- }
234
- }
235
- try {
236
- await host.removeTemporaryRoot(options.temporaryRoot);
237
- }
238
- catch (cause) {
239
- void cause;
240
- failure ??= "temporary process root cleanup failed";
241
- }
242
- return failure;
243
- };
244
- export const captureTerminalFrames = (options) => {
245
- let outputBytes = 0;
246
- let truncated = false;
247
- options.terminal.onData((data) => {
248
- options.onOutput();
249
- const bytes = Buffer.byteLength(data);
250
- if (outputBytes + bytes > options.scenario.limits.output_bytes) {
251
- truncated = true;
252
- return;
253
- }
254
- outputBytes += bytes;
255
- const atMs = normalizeProcessElapsedTime(Date.now() - options.started, options.scenario.normalization.time_bucket_ms);
256
- const normalized = normalizeProcessText(data, options.scenario, options.temporaryRoot, options.terminal.pid);
257
- const sequence = options.frames.length;
258
- options.frames.push({
259
- sequence,
260
- at_ms: atMs,
261
- data: normalized,
262
- });
263
- options.renderer.write(data, atMs);
264
- options.recordEvent("frames", sequence);
265
- });
266
- return () => truncated;
267
- };
268
- export const resolveProcessResult = (capture, executionFailure, cleanupFailure) => {
269
- if (executionFailure instanceof ProcessCaptureError)
270
- throw executionFailure;
271
- if (executionFailure !== undefined)
272
- throw new ProcessCaptureError("process capture failed", {
273
- cause: executionFailure,
274
- });
275
- if (cleanupFailure !== undefined)
276
- throw new ProcessCaptureError(cleanupFailure, {
277
- reason: "cleanup_incomplete",
278
- });
279
- if (capture === undefined)
280
- throw new ProcessCaptureError("process capture produced no result");
281
- return capture;
282
- };
283
- export const prepareProcessCapture = async (scenario, signal, captureSnapshot = snapshotRoots, host = systemProcessPreparationHost) => {
284
- assertNotCancelled(signal);
285
- const before = await captureSnapshot(scenario, signal);
286
- const temporaryRoot = await host.createTemporaryRoot();
287
- try {
288
- const runId = randomUUID();
289
- return { temporaryRoot, runId, before };
290
- }
291
- catch (cause) {
292
- await host.cleanup(temporaryRoot);
293
- throw cause;
294
- }
295
- };
296
- const systemProcessPreparationHost = {
297
- createTemporaryRoot: () => mkdtemp(join(tmpdir(), "rea-process-")),
298
- cleanup: (path) => rm(path, { recursive: true, force: true }),
299
- };
@@ -1,124 +0,0 @@
1
- import { randomUUID } from "node:crypto";
2
- import { lstat, mkdtemp, open, readdir, rename, rm, rmdir, unlink, } from "node:fs/promises";
3
- import { dirname, join } from "node:path";
4
- import { readBoundedFileBytes } from "../process/BoundedFileBytes.js";
5
- class StoreFileLockOccupied extends Error {
6
- code = "EEXIST";
7
- constructor(cause) {
8
- super("Store transaction lock is occupied", { cause });
9
- }
10
- }
11
- /** Atomically publish a populated directory so another owner cannot replace a live lock. */
12
- export const createStoreFileLock = async (path) => {
13
- if (await exists(path))
14
- throw new StoreFileLockOccupied();
15
- const staged = await mkdtemp(join(dirname(path), ".rea-store-lock-"));
16
- const owner = `owner-${randomUUID()}`;
17
- try {
18
- const handle = await open(join(staged, owner), "wx", 0o600);
19
- try {
20
- await handle.writeFile(`${String(process.pid)}\n`, "utf8");
21
- await handle.sync();
22
- }
23
- finally {
24
- await handle.close();
25
- }
26
- try {
27
- // Rename cannot replace a nonempty directory: the owner entry is present before publication.
28
- await rename(staged, path);
29
- }
30
- catch (cause) {
31
- if (await exists(path))
32
- throw new StoreFileLockOccupied(cause);
33
- throw cause;
34
- }
35
- return {
36
- release: async () => {
37
- await removeOwner(path, owner).catch((cause) => {
38
- // best-effort cleanup: lock release must not reject unhandled.
39
- void cause;
40
- });
41
- },
42
- };
43
- }
44
- finally {
45
- await rm(staged, { recursive: true, force: true });
46
- }
47
- };
48
- /** Recover a dead owner's directory lock or a legacy PID file; leave live and unknown owners intact. */
49
- export const removeStaleStoreFileLock = async (path) => {
50
- try {
51
- const stats = await lstat(path);
52
- if (stats.isFile()) {
53
- if (!(await ownerIsDead(path)))
54
- return false;
55
- await unlink(path);
56
- return true;
57
- }
58
- if (!stats.isDirectory())
59
- return false;
60
- const entries = await readdir(path);
61
- if (entries.length === 0) {
62
- await rmdir(path);
63
- return true;
64
- }
65
- const owner = entries[0];
66
- if (entries.length !== 1 ||
67
- owner === undefined ||
68
- !/^owner-[a-f0-9]{8}(?:-[a-f0-9]{4}){3}-[a-f0-9]{12}$/u.test(owner) ||
69
- !(await ownerIsDead(join(path, owner))))
70
- return false;
71
- await removeOwner(path, owner);
72
- return true;
73
- }
74
- catch (cause) {
75
- // best-effort cleanup: stale lock probing; failure means the lock stands.
76
- void cause;
77
- return false;
78
- }
79
- };
80
- const removeOwner = async (path, owner) => {
81
- // A successor has a different entry, so stale cleanup cannot make its directory empty.
82
- await unlink(join(path, owner));
83
- await rmdir(path);
84
- };
85
- const ownerIsDead = async (path) => {
86
- const stats = await lstat(path);
87
- if (!stats.isFile() || stats.size > 32)
88
- return false;
89
- const handle = await open(path, "r");
90
- let bytes;
91
- try {
92
- bytes = await readBoundedFileBytes(handle, 32);
93
- }
94
- finally {
95
- await handle.close();
96
- }
97
- const encoded = bytes?.toString("utf8").trim();
98
- return (encoded !== undefined &&
99
- /^[1-9][0-9]{0,9}$/u.test(encoded) &&
100
- !processIsAlive(Number(encoded)));
101
- };
102
- const exists = async (path) => {
103
- try {
104
- await lstat(path);
105
- return true;
106
- }
107
- catch (cause) {
108
- if (errorCode(cause) === "ENOENT")
109
- return false;
110
- throw cause;
111
- }
112
- };
113
- const processIsAlive = (pid) => {
114
- try {
115
- process.kill(pid, 0);
116
- return true;
117
- }
118
- catch (cause) {
119
- return errorCode(cause) !== "ESRCH";
120
- }
121
- };
122
- const errorCode = (cause) => typeof cause === "object" && cause !== null && "code" in cause
123
- ? cause.code
124
- : undefined;
@@ -1,2 +0,0 @@
1
- /** Minimal valid process capture retained as a public contract example. */
2
- export { EMPTY_PROCESS_CAPTURE_EXAMPLE } from "../domain/processCaptureExample.js";
@@ -1,178 +0,0 @@
1
- import { z } from "zod";
2
- /** Supported managed-runtime bytecode families. */
3
- export const bytecodeFamilySchema = z.enum(["jvm", "python"]);
4
- /** Classification of bytecode provenance. */
5
- export const bytecodeProvenanceSchema = z.enum([
6
- "application",
7
- "generated",
8
- "vendored",
9
- "bundled",
10
- "standard_library",
11
- ]);
12
- /** A bytecode symbol discovered through static analysis. */
13
- export const bytecodeSymbolSchema = z.strictObject({
14
- /** Fully qualified name. */
15
- name: z.string().min(1),
16
- /** Raw bytecode location or offset. */
17
- raw_location: z.string().min(1),
18
- /** Normalized symbol type. */
19
- kind: z.enum([
20
- "class",
21
- "interface",
22
- "method",
23
- "field",
24
- "function",
25
- "module",
26
- "variable",
27
- ]),
28
- /** Bytecode version if known. */
29
- bytecode_version: z.number().int().nullable(),
30
- /** Provenance classification. */
31
- provenance: bytecodeProvenanceSchema,
32
- /** Whether the symbol is accessible (public). */
33
- is_public: z.boolean().default(false),
34
- });
35
- /** A discovered bytecode artifact (class file, wheel, etc). */
36
- export const bytecodeArtifactSchema = z.strictObject({
37
- /** Artifact path relative to the analysis root. */
38
- path: z.string().min(1),
39
- /** Bytecode family. */
40
- family: bytecodeFamilySchema,
41
- /** Artifact format. */
42
- format: z.enum(["class", "jar", "war", "ear", "pyc", "pyo", "whl", "zipapp"]),
43
- /** Size in bytes. */
44
- size: z.number().int().nonnegative(),
45
- /** SHA-256 digest. */
46
- digest: z.string().regex(/^[a-f0-9]{64}$/u),
47
- /** Discovered symbols. */
48
- symbols: z.array(bytecodeSymbolSchema).default([]),
49
- /** Whether this is a standard library artifact. */
50
- is_standard_library: z.boolean().default(false),
51
- /** Whether this is a generated artifact. */
52
- is_generated: z.boolean().default(false),
53
- /** Whether this is a vendored artifact. */
54
- is_vendored: z.boolean().default(false),
55
- });
56
- /** Static bytecode analysis result. */
57
- export const bytecodeAnalysisSchema = z.strictObject({
58
- /** Bytecode family. */
59
- family: bytecodeFamilySchema,
60
- /** All discovered artifacts. */
61
- artifacts: z.array(bytecodeArtifactSchema),
62
- /** Total symbols across all artifacts. */
63
- total_symbols: z.number().int().nonnegative(),
64
- /** Symbols classified as application code. */
65
- application_symbols: z.number().int().nonnegative(),
66
- /** Symbols classified as generated code. */
67
- generated_symbols: z.number().int().nonnegative(),
68
- /** Symbols classified as vendored code. */
69
- vendored_symbols: z.number().int().nonnegative(),
70
- /** Symbols classified as standard library. */
71
- standard_library_symbols: z.number().int().nonnegative(),
72
- });
73
- /** Detect bytecode family from file extension. */
74
- export function detectBytecodeFamily(path) {
75
- const lower = path.toLowerCase();
76
- if (lower.endsWith(".class") ||
77
- lower.endsWith(".jar") ||
78
- lower.endsWith(".war") ||
79
- lower.endsWith(".ear")) {
80
- return "jvm";
81
- }
82
- if (lower.endsWith(".pyc") ||
83
- lower.endsWith(".pyo") ||
84
- lower.endsWith(".whl") ||
85
- lower.endsWith(".pyz") ||
86
- lower.endsWith(".zipapp")) {
87
- return "python";
88
- }
89
- return null;
90
- }
91
- /** Detect artifact format from file path. */
92
- export function detectArtifactFormat(path) {
93
- const lower = path.toLowerCase();
94
- if (lower.endsWith(".class"))
95
- return "class";
96
- if (lower.endsWith(".jar"))
97
- return "jar";
98
- if (lower.endsWith(".war"))
99
- return "war";
100
- if (lower.endsWith(".ear"))
101
- return "ear";
102
- if (lower.endsWith(".pyc"))
103
- return "pyc";
104
- if (lower.endsWith(".pyo"))
105
- return "pyo";
106
- if (lower.endsWith(".whl"))
107
- return "whl";
108
- if (lower.endsWith(".pyz") || lower.endsWith(".zipapp"))
109
- return "zipapp";
110
- return null;
111
- }
112
- const STANDARD_LIBRARY_PATH_MARKERS = [
113
- "/stdlib/",
114
- "/site-packages/",
115
- "java/",
116
- "javax/",
117
- "sun/",
118
- ];
119
- const STANDARD_LIBRARY_SYMBOL_MARKERS = ["java.", "javax.", "sun.", "__"];
120
- const GENERATED_PATH_MARKERS = [
121
- "/generated/",
122
- "_generated",
123
- "/build/",
124
- "/target/",
125
- "/dist-packages/",
126
- "/__pycache__/",
127
- ];
128
- const GENERATED_SYMBOL_MARKERS = ["Generated", "_generated"];
129
- const VENDORED_PATH_MARKERS = [
130
- "/vendor/",
131
- "/vendored/",
132
- "/third_party/",
133
- "/3rdparty/",
134
- "/node_modules/",
135
- ];
136
- const BUNDLED_PATH_MARKERS = ["/bundle/", "/bundled/", ".jar!", ".war!"];
137
- const includesAny = (value, markers) => markers.some((marker) => value.includes(marker));
138
- const startsWithAny = (value, markers) => markers.some((marker) => value.startsWith(marker));
139
- /** Classify bytecode symbol provenance. */
140
- export function classifyProvenance(path, symbolName) {
141
- const lower = path.toLowerCase();
142
- if (includesAny(lower, STANDARD_LIBRARY_PATH_MARKERS) ||
143
- startsWithAny(symbolName, STANDARD_LIBRARY_SYMBOL_MARKERS))
144
- return "standard_library";
145
- if (includesAny(lower, GENERATED_PATH_MARKERS) ||
146
- includesAny(symbolName, GENERATED_SYMBOL_MARKERS))
147
- return "generated";
148
- if (includesAny(lower, VENDORED_PATH_MARKERS))
149
- return "vendored";
150
- if (includesAny(lower, BUNDLED_PATH_MARKERS))
151
- return "bundled";
152
- return "application";
153
- }
154
- /** Analyze a set of bytecode artifacts and produce a summary. */
155
- export function analyzeBytecodeArtifacts(artifacts, family) {
156
- const totals = artifacts.reduce((counts, artifact) => {
157
- counts.total += artifact.symbols.length;
158
- for (const symbol of artifact.symbols)
159
- counts[symbol.provenance] += 1;
160
- return counts;
161
- }, {
162
- total: 0,
163
- application: 0,
164
- generated: 0,
165
- vendored: 0,
166
- standard_library: 0,
167
- bundled: 0,
168
- });
169
- return {
170
- family,
171
- artifacts: [...artifacts],
172
- total_symbols: totals.total,
173
- application_symbols: totals.application,
174
- generated_symbols: totals.generated,
175
- vendored_symbols: totals.vendored,
176
- standard_library_symbols: totals.standard_library,
177
- };
178
- }