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
@@ -75,6 +75,7 @@ const runAnalysis = async (dependencies, path, tool, arguments_, options) => {
75
75
  const prepared = await prepareSnapshot({
76
76
  path,
77
77
  snapshotPath,
78
+ signal,
78
79
  ...(options.formatHint === undefined
79
80
  ? {}
80
81
  : { formatHint: options.formatHint }),
@@ -144,7 +145,7 @@ const runAnalysis = async (dependencies, path, tool, arguments_, options) => {
144
145
  if (evidence !== undefined) {
145
146
  const recorded = session.recordEvidence(evidence);
146
147
  if (!recorded.ok)
147
- return cliError(recorded.error);
148
+ return cliError(recorded.error.retainPartialObservation(evidence));
148
149
  if (isWorkflowEvidenceTool(tool)) {
149
150
  const unknowns = recordWorkflowUnknowns({
150
151
  name: tool,
@@ -153,7 +154,7 @@ const runAnalysis = async (dependencies, path, tool, arguments_, options) => {
153
154
  recordUnknown: (unknown) => session.recordUnknown(unknown),
154
155
  });
155
156
  if (!unknowns.ok)
156
- return cliError(unknowns.error);
157
+ return cliError(unknowns.error.retainPartialObservation(evidence));
157
158
  }
158
159
  }
159
160
  if (isWorkflowEvidenceTool(tool) &&
@@ -165,7 +166,7 @@ const runAnalysis = async (dependencies, path, tool, arguments_, options) => {
165
166
  if (workflowRecord !== undefined) {
166
167
  const recorded = session.recordWorkflowSnapshot(workflowRecord);
167
168
  if (!recorded.ok)
168
- return cliError(recorded.error);
169
+ return cliError(recorded.error.retainPartialObservation(evidence));
169
170
  }
170
171
  }
171
172
  if (tool !== "trace_native_ui_action" &&
@@ -173,10 +174,10 @@ const runAnalysis = async (dependencies, path, tool, arguments_, options) => {
173
174
  evidence !== undefined) {
174
175
  const snapshot = session.exportAnalysisSnapshot();
175
176
  if (!snapshot.ok)
176
- return cliError(snapshot.error);
177
+ return cliError(snapshot.error.retainPartialObservation(evidence));
177
178
  const written = await writeAnalysisSnapshot(snapshot.value, snapshotPath, true);
178
179
  if (!written.ok)
179
- return cliError(written.error);
180
+ return cliError(written.error.retainPartialObservation(evidence));
180
181
  }
181
182
  return output;
182
183
  }, directAnalysisCleanupFailure);
@@ -266,7 +267,12 @@ const prepareSnapshot = async (options) => {
266
267
  const loaded = await readAnalysisSnapshot(snapshotPath);
267
268
  if (!loaded.ok)
268
269
  return loaded;
269
- const target = await parseBinaryTarget(path, process.cwd(), process.arch, undefined, options.formatHint);
270
+ const target = await parseBinaryTarget(path, {
271
+ signal: options.signal,
272
+ ...(options.formatHint === undefined
273
+ ? {}
274
+ : { formatHint: options.formatHint }),
275
+ });
270
276
  if (!target.ok)
271
277
  return target;
272
278
  if (!snapshotMatchesTarget(loaded.value.target, target.value))
@@ -39,7 +39,6 @@ export const directAnalysisCleanupFailure = (output, error) => {
39
39
  "execution_failure" in primary.data.details
40
40
  ? (primary.data.details.execution_failure ?? primary.data.code)
41
41
  : primary.data.code,
42
- primary_error: projection,
43
42
  cleanup_error: cleanup,
44
43
  },
45
44
  };
@@ -2,7 +2,8 @@ import { projectAnalysisError } from "../domain/analysisErrorProjection.js";
2
2
  import { jsonObjectSchema } from "../domain/jsonValue.js";
3
3
  import { createServerIdentity } from "../serverIdentity.js";
4
4
  import { silentLogger } from "../logger.js";
5
- const runSessionStatus = async (dependencies, logger = silentLogger) => {
5
+ /** Read target-free provider status and operation availability. */
6
+ export const runSessionStatus = async (dependencies, logger = silentLogger) => {
6
7
  const config = dependencies.readConfiguration();
7
8
  if (!config.ok)
8
9
  return { error: projectAnalysisError(config.error) };
@@ -19,7 +20,3 @@ const runSessionStatus = async (dependencies, logger = silentLogger) => {
19
20
  await session.close();
20
21
  }
21
22
  };
22
- /** List binary-session provider candidates and auxiliary operation availability. */
23
- export const runProviderStatus = (dependencies, logger = silentLogger) => runSessionStatus(dependencies, logger);
24
- /** List binary-session operation descriptors; this is not the full MCP catalog. */
25
- export const runCapabilityStatus = (dependencies, logger = silentLogger) => runSessionStatus(dependencies, logger);
@@ -1,13 +1,14 @@
1
1
  import { constants } from "node:fs";
2
- import { access, readFile, readdir } from "node:fs/promises";
2
+ import { access, readdir } from "node:fs/promises";
3
3
  import { homeDirectoryFromEnvironment } from "../config/homeDirectory.js";
4
4
  import { join } from "node:path";
5
5
  import { analysisErrorRemediationAction } from "../domain/analysisErrorPresentation.js";
6
+ import { BinaryTargetError } from "../domain/configurationErrors.js";
6
7
  import { parseBinaryTarget } from "./BinaryTargetResolver.js";
7
8
  import { execFileOutput } from "../process/ExecFileOutput.js";
8
9
  import { installedCaskAppdir, probeHomebrew } from "./homebrew.js";
9
10
  import { linuxHopperBinarySupported, linuxSharedLibrariesAvailable, readLinuxDistribution, } from "./LinuxHopper.js";
10
- import { canonicalSkillNeedsInstall } from "./SetupSkill.js";
11
+ import { claudeCodeSkillsDirectory, readInstalledSkillIdentity, } from "./SetupSkill.js";
11
12
  import { CATALOG_IDENTITY } from "../catalogIdentity.js";
12
13
  import { PRODUCT_IDENTITY, SDK_IDENTITY } from "../identity.js";
13
14
  import { readClientRegistrationStatuses, } from "./ClientRegistrationStatus.js";
@@ -21,8 +22,9 @@ export const DOCTOR_PROVIDER_IDS = ["hopper", "ghidra", "ida"];
21
22
  * or an agent consuming the structured result.
22
23
  */
23
24
  export const runDoctor = async (target, host = systemDoctorHost(), requestedScope) => {
25
+ const scope = normalizeDoctorScope(requestedScope, target);
24
26
  const { checks: diagnosticChecks, hopperPath, providerInspections, } = await collectDoctorDiagnostics(target, host);
25
- const identity = await collectDoctorIdentity(host);
27
+ const identity = await collectDoctorIdentity(host, scope);
26
28
  const checks = [...diagnosticChecks, ...identity.checks];
27
29
  const providers = {
28
30
  hopperAvailable: hopperPath !== undefined &&
@@ -33,7 +35,6 @@ export const runDoctor = async (target, host = systemDoctorHost(), requestedScop
33
35
  providerInspections,
34
36
  };
35
37
  const environmentHealthy = doctorHealthy(checks, providers);
36
- const scope = normalizeDoctorScope(requestedScope, target);
37
38
  const scoped = scopeDoctorChecks({
38
39
  checks,
39
40
  registrations: identity.value.registrations,
@@ -53,11 +54,14 @@ export const runDoctor = async (target, host = systemDoctorHost(), requestedScop
53
54
  identity: identity.value,
54
55
  };
55
56
  };
56
- const collectDoctorIdentity = async (host) => {
57
+ const collectDoctorIdentity = async (host, scope) => {
57
58
  const installationPaths = (await host.installationPaths?.()) ?? [];
58
- const installedSkillIdentity = await host.installedSkillIdentity?.();
59
- const skillAligned = skillIdentityAligned(installedSkillIdentity);
60
59
  const registrations = (await host.clientRegistrations?.()) ?? [];
60
+ const skillClientIds = scope.mode === "audit-wide"
61
+ ? registrations.map(({ client }) => client)
62
+ : scope.clients;
63
+ const installedSkillIdentity = await host.installedSkillIdentity?.(skillClientIds);
64
+ const skillAligned = skillIdentityAligned(installedSkillIdentity);
61
65
  return {
62
66
  checks: [
63
67
  ...(skillAligned ? [] : [skillIdentityCheck(installedSkillIdentity)]),
@@ -81,7 +85,6 @@ const collectDoctorIdentity = async (host) => {
81
85
  skill: {
82
86
  installed_version: installedSkillIdentity?.version ?? null,
83
87
  installed_tool_count: installedSkillIdentity?.toolCount ?? null,
84
- installed_catalog_digest: installedSkillIdentity?.catalogDigest ?? null,
85
88
  state: installedSkillIdentity === undefined
86
89
  ? "missing"
87
90
  : skillAligned
@@ -137,10 +140,16 @@ export const systemDoctorHost = (options = {}) => {
137
140
  macosVersion: () => readMacosVersion(hostExecFileOutput, commandEnvironment),
138
141
  linuxDistribution: readLinuxDistribution,
139
142
  async validTarget(path) {
140
- return (await parseBinaryTarget(path, process.cwd(), architecture)).ok;
143
+ return (await parseBinaryTarget(path, {
144
+ cwd: process.cwd(),
145
+ hostArchitecture: architecture,
146
+ })).ok;
141
147
  },
142
148
  async inspectTarget(path) {
143
- const result = await parseBinaryTarget(path, process.cwd(), architecture);
149
+ const result = await parseBinaryTarget(path, {
150
+ cwd: process.cwd(),
151
+ hostArchitecture: architecture,
152
+ });
144
153
  if (result.ok)
145
154
  return {
146
155
  name: "target",
@@ -149,18 +158,19 @@ export const systemDoctorHost = (options = {}) => {
149
158
  detail: path,
150
159
  };
151
160
  const error = result.error;
161
+ const targetError = error instanceof BinaryTargetError ? error : undefined;
152
162
  return {
153
163
  name: "target",
154
164
  ok: false,
155
- classification: error.constraint === "directory_requires_file"
165
+ classification: targetError?.constraint === "directory_requires_file"
156
166
  ? "unsupported_target"
157
167
  : "config_drift",
158
168
  detail: path,
159
169
  details: {
160
- reason: error.reason,
161
- ...(error.constraint === undefined
170
+ reason: targetError?.reason ?? error.message,
171
+ ...(targetError?.constraint === undefined
162
172
  ? {}
163
- : { constraint: error.constraint }),
173
+ : { constraint: targetError.constraint }),
164
174
  },
165
175
  remediation: analysisErrorRemediationAction(error),
166
176
  };
@@ -218,7 +228,7 @@ export const systemDoctorHost = (options = {}) => {
218
228
  return [];
219
229
  }
220
230
  },
221
- installedSkillIdentity: () => installedSkillIdentity(homeDirectory),
231
+ installedSkillIdentity: (clientIds) => readInstalledSkillIdentity(homeDirectory, clientIds, claudeCodeSkillsDirectory(homeDirectory, environment)),
222
232
  clientRegistrations: () => readClientRegistrationStatuses(homeDirectory, undefined, {
223
233
  platform,
224
234
  environment,
@@ -272,25 +282,6 @@ const manualHopperPaths = async (home) => {
272
282
  }
273
283
  return paths;
274
284
  };
275
- const readInstalledSkill = (home) => readFile(join(home, ".agents/skills", PRODUCT_IDENTITY.skillName, "SKILL.md"), "utf8");
276
- const installedSkillIdentity = async (home) => {
277
- try {
278
- const content = await readInstalledSkill(home);
279
- const countText = /^\s{2}tool_count:\s*(\d+)\s*$/mu.exec(content)?.[1];
280
- return {
281
- canonical: !(await canonicalSkillNeedsInstall(home)),
282
- version: /^\s{2}version:\s*"([^"]+)"\s*$/mu.exec(content)?.[1] ?? null,
283
- toolCount: countText === undefined ? null : Number.parseInt(countText, 10),
284
- catalogDigest: /^\s{2}catalog_digest:\s*"([a-f0-9]{64})"\s*$/mu.exec(content)?.[1] ??
285
- null,
286
- };
287
- }
288
- catch (cause) {
289
- // best-effort cleanup: optional skill probing; failure means unknown.
290
- void cause;
291
- return undefined;
292
- }
293
- };
294
285
  const uniqueLines = (value) => [
295
286
  ...new Set(value
296
287
  .split(/\r?\n/u)
@@ -65,7 +65,7 @@ const hostCheck = async (host) => {
65
65
  ? `${host.platform} ${host.architecture}`
66
66
  : `${linuxDistribution.id} ${linuxDistribution.versionId ?? "unknown"}`);
67
67
  return check("host", supported, detail, {
68
- remediation: "REA supports macOS 12+, Ubuntu 24.04+, Fedora 41+, 64-bit Arch Linux, CachyOS, and the experimental Windows x64 Ghidra P0 boundary.",
68
+ remediation: "REA supports macOS 12+, Ubuntu 24.04+, Fedora 41+, Nobara 44+, 64-bit Arch Linux, CachyOS, and the experimental Windows x64 Ghidra P0 boundary.",
69
69
  classification: "unsupported_host",
70
70
  });
71
71
  };
@@ -1,7 +1,7 @@
1
1
  import { describeEvidenceBundleFailure, describeValidationFailure, parseEvidenceBundle, } from "../domain/evidenceBundle.js";
2
2
  import { EvidenceFileError, EvidenceIntegrityError, } from "../domain/evidenceErrors.js";
3
3
  import { err, ok } from "../domain/result.js";
4
- import { AnalysisCancelledError } from "../domain/analysisErrorCore.js";
4
+ import { AnalysisCancelledError, } from "../domain/analysisErrorCore.js";
5
5
  import { parseProcessCapture } from "../domain/process/processCaptureParsing.js";
6
6
  import { bufferedJsonParts, canonicalJsonParts, } from "../domain/jsonSerialization.js";
7
7
  import { readJsonFile, writeTextParts } from "./JsonFiles.js";
@@ -13,17 +13,17 @@ export const workflowAnalysisProfile = (upstream, operation) => createAnalysisPr
13
13
  : {}),
14
14
  });
15
15
  /** Provider identity for deterministic artifact inventories. */
16
- export const ARTIFACT_GRAPH_PROVIDER = {
16
+ export const ARTIFACT_GRAPH_PROVIDER = Object.freeze({
17
17
  id: "rea-artifact-graph",
18
18
  name: "REA safe artifact graph provider",
19
19
  version: "1",
20
- };
20
+ });
21
21
  /** Provider identity for execution-free managed PE/CLI analysis. */
22
- export const MANAGED_STATIC_PROVIDER = {
22
+ export const MANAGED_STATIC_PROVIDER = Object.freeze({
23
23
  id: "rea-dotnet-static",
24
24
  name: "REA managed static analysis provider",
25
25
  version: "1",
26
- };
26
+ });
27
27
  /** Provider identity for deterministic managed-code comparison workflows. */
28
28
  export const MANAGED_WORKFLOW_PROVIDER = {
29
29
  id: "rea-dotnet-workflows",
@@ -1,31 +1,31 @@
1
- import { link, lstat, mkdtemp, open, readFile, realpath, rename, rm, } from "node:fs/promises";
1
+ import { link, lstat, mkdtemp, open, realpath, rename, rm, } from "node:fs/promises";
2
2
  import { basename, dirname, resolve } from "node:path";
3
3
  import { EvidenceFileError } from "../domain/evidenceErrors.js";
4
- import { AnalysisCancelledError } from "../domain/analysisErrorCore.js";
4
+ import { AnalysisCancelledError, AnalysisResourceConstraintError, } from "../domain/analysisErrorCore.js";
5
5
  import { err, ok } from "../domain/result.js";
6
+ import { parseUtf8Json } from "./Utf8JsonInput.js";
7
+ import { readRegularFile } from "./RegularFileRead.js";
8
+ import { NonRegularFileReadError } from "../filesystem/RegularFile.js";
6
9
  /** Read JSON data from a regular file at the caller-supplied path. */
7
10
  export const readJsonFile = async (path) => {
8
11
  const requestedPath = resolve(path);
9
12
  try {
10
- const canonicalPath = await realpath(requestedPath);
11
- const stats = await lstat(canonicalPath);
12
- if (!stats.isFile())
13
- return err(new EvidenceFileError("read", "not-file", { path: requestedPath }));
14
- const encoded = await readFile(canonicalPath);
15
- let decoded;
16
- try {
17
- decoded = JSON.parse(new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(encoded));
18
- }
19
- catch (cause) {
13
+ const encoded = await readRegularFile(requestedPath);
14
+ const decoded = parseUtf8Json(encoded, "read_evidence_file", requestedPath);
15
+ if (!decoded.ok) {
20
16
  return err(new EvidenceFileError("read", "invalid-json", {
21
- cause,
17
+ cause: decoded.cause,
22
18
  path: requestedPath,
23
19
  }));
24
20
  }
25
- return ok(decoded);
21
+ return ok(decoded.value);
26
22
  }
27
23
  catch (cause) {
28
- return err(new EvidenceFileError("read", missingOrIo(cause), {
24
+ if (cause instanceof AnalysisResourceConstraintError)
25
+ return err(cause);
26
+ return err(new EvidenceFileError("read", cause instanceof NonRegularFileReadError
27
+ ? "not-file"
28
+ : missingOrIo(cause), {
29
29
  cause,
30
30
  path: requestedPath,
31
31
  }));
@@ -63,7 +63,8 @@ export const parseLinuxDistribution = (text) => {
63
63
  (id === "arch" ||
64
64
  id === "cachyos" ||
65
65
  (id === "ubuntu" && versionAtLeast(versionId, 24)) ||
66
- (id === "fedora" && versionAtLeast(versionId, 41)));
66
+ (id === "fedora" && versionAtLeast(versionId, 41)) ||
67
+ (id === "nobara" && versionAtLeast(versionId, 44)));
67
68
  const identity = {
68
69
  id,
69
70
  ...(versionId === undefined ? {} : { versionId }),
@@ -2,6 +2,7 @@ import { createHash } from "node:crypto";
2
2
  import canonicalize from "canonicalize";
3
3
  import { parseEvidenceBundle, } from "../domain/evidenceBundle.js";
4
4
  import { parseProcessCapture } from "../domain/process/processCaptureParsing.js";
5
+ import { resolveJavaScriptSemanticEvidence } from "../domain/javascript/javascriptSemanticGraph.js";
5
6
  import { parseApplicationGraphEvidence } from "./javascript/JavaScriptApplicationEvidenceGraph.js";
6
7
  import { applicationObligationPolicy, semanticObligationPolicy, } from "./ReconstructionObligationPolicies.js";
7
8
  /** Derive conservative candidates from graph, process, and reviewed inputs. */
@@ -29,7 +30,12 @@ const deriveApplicationCandidates = (evidence, records, candidates, limitations)
29
30
  ].includes(evidence.operation))
30
31
  return;
31
32
  try {
32
- const source = parseApplicationGraphEvidence(evidence);
33
+ const parsed = parseApplicationGraphEvidence(evidence);
34
+ if (!parsed.ok) {
35
+ limitations.add(`Application Evidence ${evidence.evidence_id} could not generate candidates because it failed graph validation.`);
36
+ return;
37
+ }
38
+ const source = parsed.value;
33
39
  for (const node of source.graph.nodes) {
34
40
  const candidatePolicy = applicationObligationPolicy(node.kind);
35
41
  if (candidatePolicy === undefined) {
@@ -54,6 +60,7 @@ const deriveApplicationCandidates = (evidence, records, candidates, limitations)
54
60
  const candidatePolicy = semanticObligationPolicy(node.kind);
55
61
  if (candidatePolicy === undefined)
56
62
  continue;
63
+ const evidenceContext = resolveJavaScriptSemanticEvidence(source.semanticGraph, node.evidence);
57
64
  addCandidate(candidates, generatedCandidate({
58
65
  key: `semantic:${node.node_id}:${candidatePolicy.family}`,
59
66
  title: node.label ?? `${node.kind} semantic boundary`,
@@ -63,7 +70,7 @@ const deriveApplicationCandidates = (evidence, records, candidates, limitations)
63
70
  semanticNodeId: node.node_id,
64
71
  location: `semantic-graph:${source.semanticGraph.graph_id}/nodes/${node.node_id}`,
65
72
  authorityReferences: [
66
- graphReference(evidence, records, node.evidence, `${source.semanticGraph.graph_id}/node/${node.node_id}`),
73
+ graphReference(evidence, records, evidenceContext, `${source.semanticGraph.graph_id}/node/${node.node_id}`),
67
74
  ],
68
75
  }));
69
76
  }
@@ -1,5 +1,7 @@
1
1
  import { createHash } from "node:crypto";
2
2
  import canonicalize from "canonicalize";
3
+ import { canonicalJson } from "../domain/comparisonSemantics.js";
4
+ import { compareUnicodeCodePoints } from "../domain/unicodeCodePointOrder.js";
3
5
  export const obligationLedgerCoverage = (incomplete) => ({
4
6
  status: incomplete ? "partial" : "complete",
5
7
  });
@@ -64,7 +66,7 @@ export const obligationLedgerStatus = (obligations) => {
64
66
  return "unknown";
65
67
  return requiredOpen.length === 0 ? "ready" : "open";
66
68
  };
67
- export const obligationEdgeOrder = (left, right) => JSON.stringify(left).localeCompare(JSON.stringify(right));
69
+ export const obligationEdgeOrder = (left, right) => compareUnicodeCodePoints(canonicalJson(left), canonicalJson(right));
68
70
  export const digestObligationLedgerValue = (value) => {
69
71
  const encoded = canonicalize(value);
70
72
  if (encoded === undefined)
@@ -0,0 +1,17 @@
1
+ import { openRegularFile } from "../filesystem/RegularFile.js";
2
+ /** Admit one regular-file handle, retain it through the consumer, and always close it. */
3
+ export const withRegularFile = async (path, read, signal) => {
4
+ const handle = await openRegularFile(path, { symlinks: "follow", signal });
5
+ try {
6
+ const stats = await handle.stat();
7
+ signal?.throwIfAborted();
8
+ const value = await read(handle, stats);
9
+ signal?.throwIfAborted();
10
+ return value;
11
+ }
12
+ finally {
13
+ await handle.close();
14
+ }
15
+ };
16
+ /** Admit a regular file without waiting for a pipe, then read its verified handle. */
17
+ export const readRegularFile = (path, signal) => withRegularFile(path, (handle) => handle.readFile({ signal }), signal);
@@ -34,18 +34,27 @@ export const runSetup = async (options, host = systemSetupHost(), confirm) => {
34
34
  : (options.clientIds ??
35
35
  options.readinessScope?.clients ??
36
36
  discovery.defaultClientIds);
37
+ let skillNeedsInstall = await host.skillNeedsInstall(selectedClientIds);
37
38
  let skillSelected = options.installSkill === true ||
38
39
  (options.installSkill !== false && selectedClientIds.length > 0);
39
- let installSkill = skillSelected && discovery.skillNeedsInstall;
40
+ let installSkill = skillSelected && skillNeedsInstall;
40
41
  let planDiscovery = discovery;
41
42
  if (interactiveSelection) {
42
- const offerSkillAction = options.installSkill !== false && discovery.skillNeedsInstall;
43
+ const selectionSkillClientIds = [
44
+ ...new Set([
45
+ ...discovery.defaultClientIds,
46
+ ...discovery.detectedClientIds,
47
+ ]),
48
+ ];
49
+ const selectionSkillNeedsInstall = await host.skillNeedsInstall(selectionSkillClientIds);
50
+ const offerSkillAction = options.installSkill !== false && selectionSkillNeedsInstall;
43
51
  const selectionActions = await planSetupActions({
44
52
  discovery,
45
53
  host,
46
54
  providerEnvironment,
47
55
  command: host.registrationCommand,
48
56
  clientIds: [],
57
+ skillClientIds: selectionSkillClientIds,
49
58
  installSkill: offerSkillAction,
50
59
  });
51
60
  const decision = await confirm(selectionActions.plannedActions, {
@@ -67,6 +76,7 @@ export const runSetup = async (options, host = systemSetupHost(), confirm) => {
67
76
  selectedClientIds = [...selectedActionIds]
68
77
  .filter((id) => id.startsWith("configure_client:"))
69
78
  .map((id) => id.slice("configure_client:".length));
79
+ skillNeedsInstall = await host.skillNeedsInstall(selectedClientIds);
70
80
  const proposedInstallAction = selectionActions.plannedActions.some(({ id }) => id === "install_hopper");
71
81
  planDiscovery = {
72
82
  ...discovery,
@@ -78,7 +88,7 @@ export const runSetup = async (options, host = systemSetupHost(), confirm) => {
78
88
  (selectedActionIds.has("install_skill") &&
79
89
  selectedClientIds.length === 0) ||
80
90
  (options.installSkill !== false && selectedClientIds.length > 0);
81
- installSkill = skillSelected && discovery.skillNeedsInstall;
91
+ installSkill = skillSelected && skillNeedsInstall;
82
92
  }
83
93
  const planned = await planSetupActions({
84
94
  discovery: planDiscovery,
@@ -86,6 +96,7 @@ export const runSetup = async (options, host = systemSetupHost(), confirm) => {
86
96
  providerEnvironment,
87
97
  command: host.registrationCommand,
88
98
  clientIds: selectedClientIds,
99
+ skillClientIds: selectedClientIds,
89
100
  installSkill,
90
101
  });
91
102
  plannedActions = planned.plannedActions;
@@ -177,8 +188,8 @@ export const runSetup = async (options, host = systemSetupHost(), confirm) => {
177
188
  if (clientFailure !== undefined)
178
189
  return fail(clientFailure);
179
190
  if (planSelection.installSkill &&
180
- !(await installSkillAction(host, options, appliedActions)))
181
- return fail("REA analysis skill could not be installed or verified. Check permissions for `~/.agents/skills`, then rerun setup.");
191
+ !(await installSkillAction(host, options, appliedActions, selectedClientIds)))
192
+ return fail("REA analysis skill could not be installed or verified. Check permissions for its planned skill directories, then rerun setup.");
182
193
  const doctor = summarizeDoctor(await host.doctor(readinessScope));
183
194
  const remediation = combineRemediation(finalSetupRemediation(host.platform, appliedActions.includes("installed_hopper"), doctor.healthy, hopperPath), manualRemediation);
184
195
  return {
@@ -236,14 +247,14 @@ const installHopperAction = async (input) => {
236
247
  selectedClients: await filterClientsNeedingConfigure(input.host, input.selectedClients, providerEnvironment, input.host.registrationCommand),
237
248
  };
238
249
  };
239
- const installSkillAction = async (host, options, appliedActions) => {
250
+ const installSkillAction = async (host, options, appliedActions, skillClientIds) => {
240
251
  const label = "REA reverse-engineering skill";
241
252
  emitProgress(options, {
242
253
  actionId: "install_skill",
243
254
  label,
244
255
  state: "started",
245
256
  });
246
- const skill = await host.installSkill();
257
+ const skill = await host.installSkill(skillClientIds);
247
258
  if (skill === "failed") {
248
259
  emitProgress(options, {
249
260
  actionId: "install_skill",
@@ -1,4 +1,4 @@
1
- import { clientRegistrationEntry, clientConfigurationValuesEqual, clientServerPath, grokServerListedDisabled, legacyClientServerPath, parseClientConfiguration, serializeClientConfiguration, withClientServers, } from "./ClientConfigurationDocument.js";
1
+ import { clientRegistrationEntry, clientConfigurationValuesEqual, clientServerListedDisabled, clientServerPath, legacyClientServerPath, OMP_DISABLED_SERVERS_KEY, parseClientConfiguration, serializeClientConfiguration, withClientServers, } from "./ClientConfigurationDocument.js";
2
2
  import { constants as fsConstants } from "node:fs";
3
3
  import { copyFile, mkdir, readFile, rm, writeFile } from "node:fs/promises";
4
4
  import { dirname } from "node:path";
@@ -7,9 +7,8 @@ import { PRODUCT_IDENTITY } from "../identity.js";
7
7
  import { npxRegistrationCommand } from "./ClientRegistrationIdentity.js";
8
8
  import { MCP_STARTUP_POLICY } from "../mcpStartupPolicy.js";
9
9
  import { resolveClientConfigTransactionPath } from "./ClientConfigPath.js";
10
- const defaultCommand = () => npxRegistrationCommand();
11
10
  /** Configure one supported client's native stdio MCP registration shape. */
12
- export const configureClientConfiguration = (client, environment = {}, command = defaultCommand()) => {
11
+ export const configureClientConfiguration = (client, environment = {}, command = npxRegistrationCommand()) => {
13
12
  if (client.format === undefined || client.format === "unsupported")
14
13
  return Promise.resolve({ status: "failed", reason: "readback" });
15
14
  return configureClientDocument(client, environment, command, client.format);
@@ -45,12 +44,25 @@ const configureClientDocument = async (client, environment, command, format) =>
45
44
  // A native OpenCode V2 entry replaces REA's legacy V1 entry, which would
46
45
  // otherwise conflict with it.
47
46
  const legacyPath = legacyClientServerPath(parsed, PRODUCT_IDENTITY.mcpServerKey);
48
- const document = withClientServers(parsed, { ...parsed.servers, [PRODUCT_IDENTITY.mcpServerKey]: desired }, PRODUCT_IDENTITY.mcpServerKey);
47
+ const registered = withClientServers(parsed, { ...parsed.servers, [PRODUCT_IDENTITY.mcpServerKey]: desired }, PRODUCT_IDENTITY.mcpServerKey);
48
+ // OMP's denylist would hide the registration; keep every other listed name.
49
+ const ompDisabled = parsed.dialect === "omp"
50
+ ? parsed.document[OMP_DISABLED_SERVERS_KEY]
51
+ : undefined;
52
+ const enableOmp = Array.isArray(ompDisabled) &&
53
+ ompDisabled.includes(PRODUCT_IDENTITY.mcpServerKey);
54
+ const document = enableOmp && Array.isArray(ompDisabled)
55
+ ? {
56
+ ...registered,
57
+ [OMP_DISABLED_SERVERS_KEY]: ompDisabled.filter((name) => name !== PRODUCT_IDENTITY.mcpServerKey),
58
+ }
59
+ : registered;
49
60
  try {
50
61
  await mkdir(dirname(client.configPath), { recursive: true });
51
62
  await writeFileAtomic(transactionPath, serializeClientConfiguration(document, format, original, [
52
63
  clientServerPath(parsed, PRODUCT_IDENTITY.mcpServerKey),
53
64
  ...(legacyPath === undefined ? [] : [legacyPath]),
65
+ ...(enableOmp ? [[OMP_DISABLED_SERVERS_KEY]] : []),
54
66
  ]), {
55
67
  encoding: "utf8",
56
68
  mode: 0o600,
@@ -155,11 +167,10 @@ const restoreConfig = async (path, original) => {
155
167
  void cause;
156
168
  }
157
169
  };
158
- /** Whether REA's entry matches, no legacy entry remains, and Grok is not suppressing it. */
170
+ /** Whether REA's entry matches, no legacy entry remains, and no client disable list suppresses it. */
159
171
  const registrationCurrent = (parsed, desired) => clientConfigurationValuesEqual(parsed.servers[PRODUCT_IDENTITY.mcpServerKey], desired) &&
160
172
  !Object.hasOwn(parsed.legacyServers, PRODUCT_IDENTITY.mcpServerKey) &&
161
- !(parsed.dialect === "grok" &&
162
- grokServerListedDisabled(parsed.document, PRODUCT_IDENTITY.mcpServerKey));
173
+ !clientServerListedDisabled(parsed, PRODUCT_IDENTITY.mcpServerKey);
163
174
  const clientConfigurationDesired = (client, providerEnvironment, command, format) => {
164
175
  const environment = Object.fromEntries(Object.entries(providerEnvironment).sort(([left], [right]) => left.localeCompare(right)));
165
176
  const registration = clientRegistrationEntry(format ?? "json", command.length === 0 ? [PRODUCT_IDENTITY.cliBinary, "mcp"] : command, environment);
@@ -7,7 +7,7 @@ import { runDoctor, systemDoctorHost } from "./Doctor.js";
7
7
  import { installLinuxHopper, readLinuxDistribution, systemLinuxHopperInstallHost, } from "./LinuxHopper.js";
8
8
  import { installMacHopper, systemMacHopperInstallHost } from "./MacHopper.js";
9
9
  import { supportedClients } from "./SupportedClients.js";
10
- import { canonicalSkillNeedsInstall, installCanonicalSkill, } from "./SetupSkill.js";
10
+ import { claudeCodeSkillsDirectory as resolveClaudeCodeSkillsDirectory, canonicalSkillNeedsInstall, installCanonicalSkill, } from "./SetupSkill.js";
11
11
  import { clientConfigurationAligned, configureClientConfiguration, inspectClientConfiguration, } from "./SetupClientConfiguration.js";
12
12
  import { setupInstallFailure } from "./SetupInstallFailure.js";
13
13
  import { providerRegistrationEnvironment } from "./SetupRegistrationEnvironment.js";
@@ -40,16 +40,18 @@ export const hostRemediation = async (host, installHopper) => {
40
40
  }
41
41
  if ((await host.linuxDistribution())?.supported === true)
42
42
  return undefined;
43
- return "Automated Hopper setup supports Ubuntu 24.04+, Fedora 41+, 64-bit Arch Linux, and CachyOS; configure an existing supported provider instead.";
43
+ return "Automated Hopper setup supports Ubuntu 24.04+, Fedora 41+, Nobara 44+, 64-bit Arch Linux, and CachyOS; configure an existing supported provider instead.";
44
44
  };
45
45
  /** Production setup effects for Hopper, agent configuration, and the canonical skill directory. */
46
46
  export const systemSetupHost = (selectedDoctorHost = undefined, environment = process.env) => {
47
47
  const doctorHost = selectedDoctorHost ?? systemDoctorHost({ environment });
48
48
  const platform = doctorHost.platform;
49
49
  const { homeDirectory } = doctorHost;
50
+ const claudeSkillsDirectory = resolveClaudeCodeSkillsDirectory(homeDirectory, environment);
50
51
  return {
51
52
  platform,
52
53
  homeDirectory,
54
+ claudeCodeSkillsDirectory: claudeSkillsDirectory,
53
55
  registrationCommand: setupRegistrationCommand(platform, environment.npm_command === "exec"),
54
56
  nodeVersion: process.versions.node,
55
57
  macosVersion: () => doctorHost.macosVersion(),
@@ -86,8 +88,8 @@ export const systemSetupHost = (selectedDoctorHost = undefined, environment = pr
86
88
  ? Promise.resolve(false)
87
89
  : clientConfigurationAligned(client, providerEnvironment, command).then((aligned) => !aligned),
88
90
  inspectClientConfiguration: inspectClientConfiguration,
89
- skillNeedsInstall: () => canonicalSkillNeedsInstall(homeDirectory),
90
- installSkill: () => installCanonicalSkill(homeDirectory),
91
+ skillNeedsInstall: (clientIds) => canonicalSkillNeedsInstall(homeDirectory, clientIds, claudeSkillsDirectory),
92
+ installSkill: (clientIds) => installCanonicalSkill(homeDirectory, clientIds, claudeSkillsDirectory),
91
93
  doctor: (scope) => runDoctor(undefined, doctorHost, scope),
92
94
  };
93
95
  };