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
@@ -1,7 +1,7 @@
1
1
  import { join } from "node:path";
2
- import { PRODUCT_IDENTITY } from "../identity.js";
3
2
  import { isOwnedClientRegistrationCommand } from "./ClientRegistrationIdentity.js";
4
3
  import { linuxHopperInstallDisclosure, } from "./LinuxHopper.js";
4
+ import { skillDestinations } from "./SetupSkill.js";
5
5
  import { macHopperInstallDisclosure } from "./MacHopper.js";
6
6
  /** Discover supported clients and current registrations without mutation. */
7
7
  export const discoverSetupState = async (input) => {
@@ -20,10 +20,9 @@ export const discoverSetupState = async (input) => {
20
20
  input.proposeHopper &&
21
21
  (Object.keys(input.providerEnvironment).length === 0 ||
22
22
  linuxHopperRepairNeeded));
23
- const [clients, detectedClients, skillNeedsInstall] = await Promise.all([
23
+ const [clients, detectedClients] = await Promise.all([
24
24
  input.host.supportedClients(),
25
25
  input.host.detectedClients(),
26
- input.host.skillNeedsInstall(),
27
26
  ]);
28
27
  const detectedIds = new Set(detectedClients.map(({ name }) => name));
29
28
  const registrations = initialDoctor.identity?.registrations ?? [];
@@ -56,7 +55,6 @@ export const discoverSetupState = async (input) => {
56
55
  return {
57
56
  initialDoctor,
58
57
  installHopper,
59
- skillNeedsInstall,
60
58
  clients,
61
59
  detectedClientIds: [...detectedIds],
62
60
  defaultClientIds,
@@ -119,6 +117,8 @@ export const planSetupActions = async (input) => {
119
117
  homeDirectory: input.host.homeDirectory,
120
118
  installHopper: input.discovery.installHopper,
121
119
  installSkill: input.installSkill,
120
+ skillClientIds: input.skillClientIds,
121
+ claudeCodeSkillsDirectory: input.host.claudeCodeSkillsDirectory,
122
122
  clients: clientPlans,
123
123
  providerEnvironment: input.providerEnvironment,
124
124
  ...(input.discovery.linuxPackageFamily === undefined
@@ -170,17 +170,21 @@ const setupPlan = (input) => [
170
170
  ...(backupPath === undefined ? {} : { backupPath }),
171
171
  })),
172
172
  ...(input.installSkill
173
- ? [
174
- {
175
- id: "install_skill",
176
- kind: "install_skill",
177
- label: "REA reverse-engineering skill",
178
- target: join(input.homeDirectory, ".agents/skills", PRODUCT_IDENTITY.skillName),
179
- detail: "Install or update the bundled REA reverse-engineering skill and on-demand references.",
180
- external: false,
181
- operation: "install",
182
- },
183
- ]
173
+ ? skillDestinations(input.homeDirectory, input.skillClientIds, input.claudeCodeSkillsDirectory).map(({ client, path }) => ({
174
+ id: client === "claude_code"
175
+ ? "install_skill:claude_code"
176
+ : "install_skill",
177
+ kind: "install_skill",
178
+ label: client === "claude_code"
179
+ ? "REA skill for Claude Code"
180
+ : "REA reverse-engineering skill",
181
+ target: path,
182
+ detail: client === "claude_code"
183
+ ? "Install or update the REA skill in Claude Code's personal skill directory."
184
+ : "Install or update the bundled REA reverse-engineering skill and on-demand references.",
185
+ external: false,
186
+ operation: "install",
187
+ }))
184
188
  : []),
185
189
  ];
186
190
  const linuxDisclosure = (family) => {
@@ -10,7 +10,33 @@ const SKILL_FILES = [
10
10
  "references/runtime-observation.md",
11
11
  "references/evidence-workflows.md",
12
12
  ];
13
- const skillRoot = (home) => join(home, ".agents/skills", PRODUCT_IDENTITY.skillName);
13
+ /** Resolve Claude Code personal skills from the selected environment. */
14
+ export const claudeCodeSkillsDirectory = (home, environment = {}) => join(environment.CLAUDE_CONFIG_DIR ?? join(home, ".claude"), "skills");
15
+ /** Resolve the skill roots required by a client selection, or all owned roots. */
16
+ export const skillDestinations = (home, clientIds, claudeSkillsDirectory = claudeCodeSkillsDirectory(home)) => {
17
+ const includeClaude = clientIds === undefined || clientIds.includes("claude_code");
18
+ const includeShared = clientIds === undefined ||
19
+ clientIds.length === 0 ||
20
+ clientIds.some((clientId) => clientId !== "claude_code");
21
+ return [
22
+ ...(includeShared
23
+ ? [
24
+ {
25
+ client: "shared",
26
+ path: join(home, ".agents/skills", PRODUCT_IDENTITY.skillName),
27
+ },
28
+ ]
29
+ : []),
30
+ ...(includeClaude
31
+ ? [
32
+ {
33
+ client: "claude_code",
34
+ path: join(claudeSkillsDirectory, PRODUCT_IDENTITY.skillName),
35
+ },
36
+ ]
37
+ : []),
38
+ ];
39
+ };
14
40
  const readOptionalText = async (path) => {
15
41
  try {
16
42
  return await readFile(path, "utf8");
@@ -21,18 +47,18 @@ const readOptionalText = async (path) => {
21
47
  throw cause;
22
48
  }
23
49
  };
24
- const canonicalSkillFiles = async (home) => Promise.all(SKILL_FILES.map(async (relativePath) => {
25
- const destination = join(skillRoot(home), relativePath);
50
+ const canonicalSkillFiles = async (home, clientIds, claudeSkillsDirectory) => Promise.all(skillDestinations(home, clientIds, claudeSkillsDirectory).flatMap(({ path: root }) => SKILL_FILES.map(async (relativePath) => {
51
+ const destination = join(root, relativePath);
26
52
  return {
27
53
  destination,
28
54
  content: await readFile(new URL(`../../skills/${PRODUCT_IDENTITY.skillName}/${relativePath}`, import.meta.url), "utf8"),
29
55
  original: await readOptionalText(destination),
30
56
  };
31
- }));
57
+ })));
32
58
  /** Report whether setup would change any file in the managed REA skill bundle. */
33
- export const canonicalSkillNeedsInstall = async (home) => {
59
+ export const canonicalSkillNeedsInstall = async (home, clientIds = [], claudeSkillsDirectory) => {
34
60
  try {
35
- return (await canonicalSkillFiles(home)).some(({ content, original }) => original !== content);
61
+ return (await canonicalSkillFiles(home, clientIds, claudeSkillsDirectory)).some(({ content, original }) => original !== content);
36
62
  }
37
63
  catch (cause) {
38
64
  // Unreadable skill state fails open to install so setup can repair it.
@@ -50,10 +76,10 @@ const restoreSkillFiles = async (changed) => {
50
76
  }
51
77
  };
52
78
  /** Transactionally install or upgrade the canonical REA skill and references. */
53
- export const installCanonicalSkill = async (home) => {
79
+ export const installCanonicalSkill = async (home, clientIds = [], claudeSkillsDirectory) => {
54
80
  let changed = [];
55
81
  try {
56
- const canonical = await canonicalSkillFiles(home);
82
+ const canonical = await canonicalSkillFiles(home, clientIds, claudeSkillsDirectory);
57
83
  changed = canonical.filter(({ content, original }) => original !== content);
58
84
  if (changed.length === 0)
59
85
  return "unchanged";
@@ -82,3 +108,26 @@ export const installCanonicalSkill = async (home) => {
82
108
  return "failed";
83
109
  }
84
110
  };
111
+ /** Read installed skill metadata and compare every managed location. */
112
+ export const readInstalledSkillIdentity = async (home, clientIds, claudeSkillsDirectory) => {
113
+ const destinations = skillDestinations(home, clientIds, claudeSkillsDirectory);
114
+ let content;
115
+ for (const destination of destinations) {
116
+ try {
117
+ content = await readFile(join(destination.path, "SKILL.md"), "utf8");
118
+ break;
119
+ }
120
+ catch {
121
+ // Another selected copy may provide metadata; canonical validation below
122
+ // still marks missing or unreadable copies as stale.
123
+ }
124
+ }
125
+ if (content === undefined)
126
+ return undefined;
127
+ const toolCount = /^\s{2}tool_count:\s*(\d+)\s*$/mu.exec(content)?.[1];
128
+ return {
129
+ canonical: !(await canonicalSkillNeedsInstall(home, clientIds, claudeSkillsDirectory)),
130
+ version: /^\s{2}version:\s*"([^"]+)"\s*$/mu.exec(content)?.[1] ?? null,
131
+ toolCount: toolCount === undefined ? null : Number.parseInt(toolCount, 10),
132
+ };
133
+ };
@@ -34,6 +34,38 @@ export const GROK_BOT_MANUAL_REGISTRATION_REMEDIATION = "Grok Bot keeps connecto
34
34
  export const manualRegistrationRemediation = (clientName) => clientName === "grok_bot"
35
35
  ? GROK_BOT_MANUAL_REGISTRATION_REMEDIATION
36
36
  : undefined;
37
+ const OMP_PROFILE_NAME = /^[a-z0-9][a-z0-9._-]{0,63}$/u;
38
+ /**
39
+ * OMP's active named profile. OMP_PROFILE wins over the legacy PI_PROFILE even
40
+ * when empty; empty and "default" select the default profile. OMP refuses to
41
+ * start with an invalid name, so one leaves the default location in place.
42
+ */
43
+ const ompProfile = ({ env }) => {
44
+ const name = (env.OMP_PROFILE ?? env.PI_PROFILE)?.trim();
45
+ return name === undefined ||
46
+ name === "" ||
47
+ name === "default" ||
48
+ name.endsWith(".") ||
49
+ !OMP_PROFILE_NAME.test(name)
50
+ ? undefined
51
+ : name;
52
+ };
53
+ /**
54
+ * The OMP agent directory whose `mcp.json` holds user-scope MCP servers. OMP
55
+ * joins PI_CONFIG_DIR to the home directory, and a named profile ignores
56
+ * PI_CODING_AGENT_DIR. OMP resolves a relative agent directory against each
57
+ * process's working directory, so only an absolute override names one file.
58
+ */
59
+ const ompAgentDirectory = (context) => {
60
+ const root = join(context.home, context.env.PI_CONFIG_DIR || ".omp");
61
+ const profile = ompProfile(context);
62
+ if (profile !== undefined)
63
+ return join(root, "profiles", profile, "agent");
64
+ const override = context.env.PI_CODING_AGENT_DIR;
65
+ return override !== undefined && override !== "" && isAbsolute(override)
66
+ ? override
67
+ : join(root, "agent");
68
+ };
37
69
  const copilotDirectory = ({ home, env }) => env.COPILOT_HOME ?? join(home, ".copilot");
38
70
  const commandCodeDirectory = ({ home }) => join(home, ".commandcode");
39
71
  const opencodeDirectory = ({ home, env }) => join(env.XDG_CONFIG_HOME ?? join(home, ".config"), "opencode");
@@ -157,6 +189,13 @@ export const SUPPORTED_CLIENT_DEFINITIONS = [
157
189
  markerPath: grokDirectory,
158
190
  format: "grok",
159
191
  },
192
+ {
193
+ name: "omp",
194
+ displayName: "OMP",
195
+ configPath: (context) => join(ompAgentDirectory(context), "mcp.json"),
196
+ markerPath: ompAgentDirectory,
197
+ format: "omp",
198
+ },
160
199
  {
161
200
  name: "grok_bot",
162
201
  displayName: "Grok Bot",
@@ -173,7 +212,11 @@ export const supportedClients = (home, platform = process.platform, env = {
173
212
  CODEX_HOME: process.env.CODEX_HOME,
174
213
  COPILOT_HOME: process.env.COPILOT_HOME,
175
214
  GROK_HOME: process.env.GROK_HOME,
215
+ OMP_PROFILE: process.env.OMP_PROFILE,
176
216
  OPENCODE_CONFIG: process.env.OPENCODE_CONFIG,
217
+ PI_CODING_AGENT_DIR: process.env.PI_CODING_AGENT_DIR,
218
+ PI_CONFIG_DIR: process.env.PI_CONFIG_DIR,
219
+ PI_PROFILE: process.env.PI_PROFILE,
177
220
  SAND_DATA_ROOT: process.env.SAND_DATA_ROOT,
178
221
  XDG_CONFIG_HOME: process.env.XDG_CONFIG_HOME,
179
222
  }) => {
@@ -6,6 +6,7 @@ import { join } from "node:path";
6
6
  import writeFileAtomic from "write-file-atomic";
7
7
  import { z } from "zod";
8
8
  import { PRODUCT_IDENTITY } from "../identity.js";
9
+ import { claudeCodeSkillsDirectory, skillDestinations } from "./SetupSkill.js";
9
10
  import { isOwnedClientRegistrationCommand } from "./ClientRegistrationIdentity.js";
10
11
  import { resolveClientConfigTransactionPath } from "./ClientConfigPath.js";
11
12
  import { manualRegistrationRemediation, supportedClients, } from "./SupportedClients.js";
@@ -95,7 +96,7 @@ export const systemUninstallHost = (selectedHome = undefined, fileSystem = syste
95
96
  : undefined;
96
97
  },
97
98
  removeClient: (client) => removeClient(client, fileSystem),
98
- removeSkill: () => removeManagedSkills(home, fileSystem),
99
+ removeSkill: () => removeManagedSkills(home, fileSystem, environment),
99
100
  purgeData: async () => [
100
101
  await removeManagedPath(join(home, ".rea/cache"), "cache", fileSystem),
101
102
  await removeManagedPath(join(home, ".rea/state"), "state", fileSystem),
@@ -224,7 +225,22 @@ const removeManagedPath = async (path, name, fileSystem) => {
224
225
  : item(name, "failed", "This item could not be removed. Check file permissions, then rerun uninstall.");
225
226
  }
226
227
  };
227
- const removeManagedSkills = async (home, fileSystem) => removeManagedPath(join(home, ".agents/skills", PRODUCT_IDENTITY.skillName), "skill", fileSystem);
228
+ const removeManagedSkills = async (home, fileSystem, environment) => {
229
+ const results = await Promise.all(skillDestinations(home, undefined, claudeCodeSkillsDirectory(home, environment)).map(({ client, path }) => removeManagedPath(path, client === "claude_code" ? "Claude Code skill" : "skill", fileSystem)));
230
+ const failed = results.find(({ status }) => status === "failed");
231
+ if (failed !== undefined)
232
+ return item("skill", "failed", results
233
+ .map(({ name, status, detail }) => `${name}: ${status} (${detail})`)
234
+ .join(" "));
235
+ const status = results.some(({ status: resultStatus }) => resultStatus === "removed")
236
+ ? "removed"
237
+ : results.some(({ status: resultStatus }) => resultStatus === "retained")
238
+ ? "retained"
239
+ : "skipped";
240
+ return item("skill", status, results
241
+ .map(({ name, status: resultStatus, detail }) => `${name}: ${resultStatus} (${detail})`)
242
+ .join(" "));
243
+ };
228
244
  const item = (name, status, detail) => ({ name, status, detail });
229
245
  const registrationSchema = z
230
246
  .object({ command: z.string(), args: z.array(z.string()) })
@@ -4,7 +4,7 @@ import { z } from "zod";
4
4
  import { PRODUCT_IDENTITY } from "../identity.js";
5
5
  import { isOwnedClientRegistrationCommand } from "./ClientRegistrationIdentity.js";
6
6
  import { readClientRegistrationStatuses } from "./ClientRegistrationStatus.js";
7
- import { effectiveClientServer, parseClientConfiguration, } from "./ClientConfigurationDocument.js";
7
+ import { clientServerForcedEnabled, clientServerListedDisabled, effectiveClientServer, parseClientConfiguration, } from "./ClientConfigurationDocument.js";
8
8
  import { supportedClients } from "./SupportedClients.js";
9
9
  const setupPlanSchema = z.object({
10
10
  status: z.literal("planned"),
@@ -41,7 +41,11 @@ export const existingMaintenanceScope = async (home, entryPoint, environment) =>
41
41
  disabled: z.boolean().optional(),
42
42
  })
43
43
  .parse(effectiveClientServer(parsed, PRODUCT_IDENTITY.mcpServerKey));
44
- if (enabled.enabled !== false && enabled.disabled !== true)
44
+ // Root disable lists override enabled entries and OMP's force-on allowlist.
45
+ if ((enabled.enabled !== false ||
46
+ clientServerForcedEnabled(parsed, PRODUCT_IDENTITY.mcpServerKey)) &&
47
+ enabled.disabled !== true &&
48
+ !clientServerListedDisabled(parsed, PRODUCT_IDENTITY.mcpServerKey))
45
49
  clients.push(client.name);
46
50
  }
47
51
  let skill = false;
@@ -0,0 +1,64 @@
1
+ import { constants } from "node:buffer";
2
+ import { AnalysisResourceConstraintError } from "../domain/analysisErrorCore.js";
3
+ import { safeParseJson } from "../domain/safeJson.js";
4
+ /** Recovery that preserves complete, authenticated Evidence workflow inputs. */
5
+ export const JSON_INPUT_RESOURCE_REMEDIATION = "Provide a smaller valid JSON value. For Evidence workflows, re-analyze a smaller selection of the original target and use its complete Evidence; splitting JSON text or trimming Evidence fields does not produce valid workflow input.";
6
+ /** Decode JSON bytes without confusing a runtime string limit with malformed input. */
7
+ export const parseUtf8Json = (bytes, operation, path, boundary = "json-input") => {
8
+ const stringLimitFailure = (cause, decodedUnits) => new AnalysisResourceConstraintError(operation, "memory", "JSON input exceeds the runtime's maximum decoded string length", {
9
+ boundary,
10
+ input_path: path,
11
+ input_bytes: bytes.byteLength,
12
+ max_string_code_units: constants.MAX_STRING_LENGTH,
13
+ ...(decodedUnits === undefined
14
+ ? {}
15
+ : { decoded_string_code_units_at_least: decodedUnits }),
16
+ }, {
17
+ ...(cause === undefined ? {} : { cause }),
18
+ remediationAction: JSON_INPUT_RESOURCE_REMEDIATION,
19
+ });
20
+ let text;
21
+ try {
22
+ const decoder = new TextDecoder("utf-8", { fatal: true, ignoreBOM: true });
23
+ if (bytes.byteLength <= constants.MAX_STRING_LENGTH) {
24
+ text = decoder.decode(bytes);
25
+ }
26
+ else {
27
+ // Node 22's UTF-8 fast path bounds encoded bytes before decoding. Decode
28
+ // large inputs in chunks so valid multibyte text is bounded by its actual
29
+ // UTF-16 length. Streaming also preserves characters spanning chunks.
30
+ const parts = [];
31
+ let decodedUnits = 0;
32
+ const append = (part) => {
33
+ decodedUnits += part.length;
34
+ if (decodedUnits > constants.MAX_STRING_LENGTH)
35
+ throw stringLimitFailure(undefined, decodedUnits);
36
+ parts.push(part);
37
+ };
38
+ const chunkBytes = 1024 * 1024;
39
+ for (let offset = 0; offset < bytes.byteLength; offset += chunkBytes)
40
+ append(decoder.decode(bytes.subarray(offset, offset + chunkBytes), {
41
+ stream: true,
42
+ }));
43
+ append(decoder.decode());
44
+ text = parts.join("");
45
+ }
46
+ }
47
+ catch (cause) {
48
+ if (cause instanceof AnalysisResourceConstraintError)
49
+ throw cause;
50
+ const code = typeof cause === "object" && cause !== null && "code" in cause
51
+ ? cause.code
52
+ : undefined;
53
+ if (code === "ERR_STRING_TOO_LONG")
54
+ throw stringLimitFailure(cause);
55
+ if (code !== "ERR_ENCODING_INVALID_ENCODED_DATA")
56
+ throw cause;
57
+ return {
58
+ ok: false,
59
+ error: "JSON input is not valid UTF-8",
60
+ cause,
61
+ };
62
+ }
63
+ return safeParseJson(text);
64
+ };
@@ -1,5 +1,4 @@
1
1
  import { createHash } from "node:crypto";
2
- import { readFile } from "node:fs/promises";
3
2
  import { isAbsolute } from "node:path";
4
3
  import { z } from "zod";
5
4
  import { ArtifactReaderFailure } from "../artifacts/ArtifactReader.js";
@@ -15,6 +14,8 @@ import { safeParseJson } from "../domain/safeJson.js";
15
14
  import { exportWebScriptsInputSchema, } from "../domain/webScriptExport.js";
16
15
  import { WebScriptExportError } from "../domain/webScriptExportError.js";
17
16
  import { WEB_SCRIPT_EXPORT_PROVIDER as PROVIDER } from "./InvestigationProviders.js";
17
+ import { readRegularFile } from "./RegularFileRead.js";
18
+ import { NonRegularFileReadError } from "../filesystem/RegularFile.js";
18
19
  const OPERATION = "export_web_scripts";
19
20
  /** Export one local capture through the shared CLI/MCP application workflow. */
20
21
  export const exportWebScripts = async (rawInput, options = {}) => {
@@ -97,20 +98,26 @@ export const exportWebScriptsValidated = async (input, options = {}) => {
97
98
  */
98
99
  const readCapture = async (path, signal) => {
99
100
  try {
100
- return ok(await readFile(path, { signal }));
101
+ return ok(await readRegularFile(path, signal));
101
102
  }
102
103
  catch (cause) {
103
104
  const code = cause instanceof Error && "code" in cause ? String(cause.code) : "";
104
105
  if (code === "EACCES" || code === "EPERM")
105
106
  return err(new AnalysisAccessDeniedError(OPERATION, path, code, { cause }));
106
- if (code === "ENOENT" || code === "ENOTDIR" || code === "EISDIR")
107
+ if (cause instanceof NonRegularFileReadError ||
108
+ code === "ENOENT" ||
109
+ code === "ENOTDIR" ||
110
+ code === "EISDIR" ||
111
+ code === "ENXIO")
107
112
  return err(new AnalysisInputError(OPERATION, { cause }, [
108
113
  {
109
114
  path: ["capture_path"],
110
115
  reason: "invalid_value",
111
- message: code === "EISDIR"
112
- ? `Selected capture is a directory, not a file: ${path}`
113
- : `Selected capture could not be read (${code}): ${path}`,
116
+ message: cause instanceof NonRegularFileReadError && code !== "EISDIR"
117
+ ? cause.message
118
+ : code === "EISDIR"
119
+ ? `Selected capture is a directory, not a file: ${path}`
120
+ : `Selected capture could not be read (${code}): ${path}`,
114
121
  },
115
122
  ]));
116
123
  throw cause;
@@ -17,7 +17,7 @@ export class AndroidAnalysisService {
17
17
  const request = androidRequestSchema.safeParse({ operation, input });
18
18
  if (!request.success)
19
19
  return err(new AnalysisInputError(operation, { cause: request.error }));
20
- const target = await parseBinaryTarget(request.data.input.path);
20
+ const target = await parseBinaryTarget(request.data.input.path, options?.signal === undefined ? {} : { signal: options.signal });
21
21
  if (!target.ok)
22
22
  return target;
23
23
  const executed = await this.provider.execute(target.value, request.data, options);
@@ -4,6 +4,7 @@ import {} from "../../domain/analysisErrorBase.js";
4
4
  import { err, ok } from "../../domain/result.js";
5
5
  import { analysisQueryId, createAnalysisSnapshotEntry, createAnalysisSnapshotWorkflowEntry, snapshotBinding, snapshotMatchesProfile, snapshotMatchesTarget, snapshotTarget, parseAnalysisSnapshot, } from "../../domain/analysisSnapshot.js";
6
6
  import { OFFICIAL_TOOL_CONTRACTS } from "../../contracts/officialToolContracts.js";
7
+ import { compareUnicodeCodePoints } from "../../domain/unicodeCodePointOrder.js";
7
8
  const STATEFUL_OPERATIONS = new Set([
8
9
  "health",
9
10
  "current_address",
@@ -87,8 +88,8 @@ export class AnalysisSnapshotCache {
87
88
  try {
88
89
  const snapshotTargetIdentity = snapshotTarget(target);
89
90
  const binding = snapshotBinding(profile);
90
- const entries = [...this.#entries.values()].sort((left, right) => left.query_id.localeCompare(right.query_id));
91
- const workflows = [...this.#workflowEntries.values()].sort((left, right) => left.query_id.localeCompare(right.query_id));
91
+ const entries = [...this.#entries.values()].sort((left, right) => compareUnicodeCodePoints(left.query_id, right.query_id));
92
+ const workflows = [...this.#workflowEntries.values()].sort((left, right) => compareUnicodeCodePoints(left.query_id, right.query_id));
92
93
  // Parsing owns the returned JSON and metadata; pre-cloning the same
93
94
  // payloads here only adds another full materialization.
94
95
  return ok(parseAnalysisSnapshot({
@@ -126,13 +127,13 @@ export class AnalysisSnapshotCache {
126
127
  /** Return canonical entries for persistence. */
127
128
  entries() {
128
129
  return [...this.#entries.values()]
129
- .sort((left, right) => left.query_id.localeCompare(right.query_id))
130
+ .sort((left, right) => compareUnicodeCodePoints(left.query_id, right.query_id))
130
131
  .map((entry) => structuredClone(entry));
131
132
  }
132
133
  /** Return canonical composed-workflow entries for persistence. */
133
134
  workflowEntries() {
134
135
  return [...this.#workflowEntries.values()]
135
- .sort((left, right) => left.query_id.localeCompare(right.query_id))
136
+ .sort((left, right) => compareUnicodeCodePoints(left.query_id, right.query_id))
136
137
  .map((entry) => structuredClone(entry));
137
138
  }
138
139
  /** Record one exact derived workflow result unless the shared cache is full. */
@@ -314,6 +314,22 @@ export class BinarySession extends BinarySessionRecords {
314
314
  this.#calls.set(call, generation);
315
315
  return call.finally(() => this.#calls.delete(call));
316
316
  }
317
+ /** Admit one composed request until its result and session bookkeeping settle. */
318
+ withAdmittedAnalysis(operationName, signal, operation) {
319
+ const generation = this.#transitionGeneration;
320
+ const transition = this.#transition;
321
+ const call = (async () => {
322
+ const admission = await this.#waitForTransition(operationName, signal, transition);
323
+ if (!admission.ok)
324
+ return admission;
325
+ return ok(await operation({
326
+ execute: (name, arguments_, options) => this.#execute(name, arguments_, options, Promise.resolve()),
327
+ }));
328
+ })();
329
+ // Register synchronously before a lifecycle transition can snapshot calls.
330
+ this.#calls.set(call, generation);
331
+ return call.finally(() => this.#calls.delete(call));
332
+ }
317
333
  async #execute(name, arguments_, options, transition) {
318
334
  const transitioned = await this.#waitForTransition(name, options?.signal, transition);
319
335
  if (!transitioned.ok)
@@ -8,7 +8,15 @@ import { SessionProviderRouter } from "./SessionProviderRouter.js";
8
8
  /** Parse a target, resolve its provider route, and validate snapshot binding. */
9
9
  export const resolveSessionOpen = async (input) => {
10
10
  const { path, options } = input;
11
- const parsed = await parseBinaryTarget(path, process.cwd(), process.arch, options.targetKind, options.formatHint);
11
+ const parsed = await parseBinaryTarget(path, {
12
+ ...(options.targetKind === undefined
13
+ ? {}
14
+ : { targetKind: options.targetKind }),
15
+ ...(options.formatHint === undefined
16
+ ? {}
17
+ : { formatHint: options.formatHint }),
18
+ ...(options.signal === undefined ? {} : { signal: options.signal }),
19
+ });
12
20
  if (!parsed.ok)
13
21
  return parsed;
14
22
  return resolveSessionTarget({ ...input, target: parsed.value });
@@ -1,4 +1,4 @@
1
- import { canonicalDigest } from "../../domain/comparisonSemantics.js";
1
+ import { digestCanonicalValue } from "../../domain/canonicalDigest.js";
2
2
  import { createEvidence } from "../../domain/evidence.js";
3
3
  import { jsonObjectSchema, jsonValueSchema } from "../../domain/jsonValue.js";
4
4
  /** Commit the selected Electron experiment and its observed result. */
@@ -24,6 +24,6 @@ const parameters = (input) => {
24
24
  const scenario = jsonObjectSchema.parse(input);
25
25
  return {
26
26
  ...scenario,
27
- scenario_sha256: canonicalDigest(scenario, "Electron scenario"),
27
+ scenario_sha256: digestCanonicalValue(scenario, "Electron scenario"),
28
28
  };
29
29
  };
@@ -1,4 +1,4 @@
1
- import { compareCodePoints } from "../../domain/canonicalOrdering.js";
1
+ import { compareUnicodeCodePoints } from "../../domain/unicodeCodePointOrder.js";
2
2
  import { resolveArtifactPathByContext } from "./JavaScriptArtifactPathResolution.js";
3
3
  /** Flatten all per-file IPC facts into deterministic application records. */
4
4
  export const collectElectronIpcRecords = (analysis) => analysis.files
@@ -7,7 +7,7 @@ export const collectElectronIpcRecords = (analysis) => analysis.files
7
7
  file,
8
8
  finding,
9
9
  })))
10
- .sort((left, right) => compareCodePoints(left.key, right.key));
10
+ .sort((left, right) => compareUnicodeCodePoints(left.key, right.key));
11
11
  /** Match only exact literal channels and retain ambiguous matches separately. */
12
12
  export const classifyElectronIpcPairings = (records) => {
13
13
  const handlers = records.filter(isMainHandler);
@@ -1,5 +1,6 @@
1
1
  import { javascriptAnalysisCoverage, resolveArtifactPath, } from "./JavaScriptArtifactGraphContext.js";
2
2
  import { astObservationEvidence } from "./JavaScriptArtifactGraphEvidence.js";
3
+ import { compositeKey } from "../../domain/unicodeCodePointOrder.js";
3
4
  import { addElectronInferenceEdge, electronFindingSourceNode, electronObservationIdentity, electronRangeKey, } from "./ElectronBoundaryGraphContext.js";
4
5
  /** Project JavaScript-requested native addon binding and re-export surfaces. */
5
6
  export const addElectronNativeBoundaries = (context) => {
@@ -21,7 +22,10 @@ const addNativeBinding = (input) => {
21
22
  const addon = resolved === null ? undefined : context.fileNodes.get(resolved);
22
23
  const binding = context.accumulator.addNode({
23
24
  kind: "native-export",
24
- identity: electronObservationIdentity(context, "javascript-requested-native-export", `${file.path}:${value.specifier}:${value.binding_kind}:${value.members.join("\0")}:${electronRangeKey(value.location)}`),
25
+ identity: electronObservationIdentity(context, "javascript-requested-native-export",
26
+ // Members are a variable-length source-derived list: compositeKey keeps
27
+ // ["a\0b"] distinct from ["a", "b"] inside the digested identity.
28
+ `${file.path}:${value.specifier}:${value.binding_kind}:${compositeKey(value.members)}:${electronRangeKey(value.location)}`),
25
29
  observations: [
26
30
  {
27
31
  label: value.members.join(", "),
@@ -36,4 +36,5 @@ const applicationObservation = (input, result) => ({
36
36
  });
37
37
  const parameters = (input) => ({
38
38
  format: input.format,
39
+ integrity_policy: input.integrity_policy,
39
40
  });