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
@@ -2,8 +2,8 @@ import { createHash } from "node:crypto";
2
2
  import { posix } from "node:path";
3
3
  import { fileURLToPath } from "node:url";
4
4
  import * as t from "@babel/types";
5
- import { readExactJavaScriptLiteral, semanticStaticPropertyName, } from "./javascriptAstValues.js";
6
- import { compareCodePoints } from "../canonicalOrdering.js";
5
+ import { readExactJavaScriptLiteral, semanticStaticPropertyName, unwrapJavaScriptExpression, } from "./javascriptAstValues.js";
6
+ import { compareUnicodeCodePoints, compositeKey, } from "../unicodeCodePointOrder.js";
7
7
  /** Explicit result for source text that Babel cannot parse. */
8
8
  export const failedJavaScriptStaticAnalysis = () => ({
9
9
  parse_status: "failed",
@@ -67,8 +67,9 @@ const findChunkRuntime = (node) => {
67
67
  pending.push(current.right, current.left);
68
68
  continue;
69
69
  }
70
- if (t.isParenthesizedExpression(current) || t.isTSAsExpression(current))
71
- pending.push(current.expression);
70
+ const unwrapped = unwrapJavaScriptExpression(current).node;
71
+ if (unwrapped !== current)
72
+ pending.push(unwrapped);
72
73
  }
73
74
  return undefined;
74
75
  };
@@ -102,26 +103,25 @@ export const staticArrayValues = (array) => {
102
103
  const value = argumentValue(element);
103
104
  return value === undefined ? [] : [value];
104
105
  });
105
- const values = [...new Set(staticValues)].sort(compareCodePoints);
106
+ const values = [...new Set(staticValues)].sort(compareUnicodeCodePoints);
106
107
  return {
107
108
  values,
108
109
  unknown: array.elements.length - staticValues.length,
109
110
  };
110
111
  };
111
- /** Resolve a path composed only from inert literal syntax. */
112
- export const staticPath = (node) => staticPathAt(node);
113
112
  /** Classify whether inert path syntax is a module specifier or file expression. */
114
113
  export const staticPathResolutionContext = (node) => isFilesystemPathExpression(node)
115
114
  ? "filesystem-expression"
116
115
  : "module-specifier";
117
- const staticPathAt = (node) => {
116
+ /** Resolve a path composed only from inert literal syntax. */
117
+ export const staticPath = (node) => {
118
118
  if (t.isStringLiteral(node))
119
119
  return node.value;
120
120
  if (t.isTemplateLiteral(node) && node.expressions.length === 0)
121
121
  return stringValue(node);
122
122
  if (t.isBinaryExpression(node, { operator: "+" })) {
123
- const left = staticPathAt(node.left);
124
- const right = staticPathAt(node.right);
123
+ const left = staticPath(node.left);
124
+ const right = staticPath(node.right);
125
125
  return left === undefined || right === undefined
126
126
  ? undefined
127
127
  : `${left}${right}`;
@@ -152,7 +152,7 @@ const staticCallPath = (node) => {
152
152
  for (const argument of node.arguments) {
153
153
  if (isDirectoryIdentity(argumentNode(argument)))
154
154
  continue;
155
- const value = t.isNode(argument) ? staticPathAt(argument) : undefined;
155
+ const value = t.isNode(argument) ? staticPath(argument) : undefined;
156
156
  if (value === undefined)
157
157
  return undefined;
158
158
  parts.push(value);
@@ -164,7 +164,7 @@ const staticFileUrlPath = (argument) => {
164
164
  return undefined;
165
165
  return isSourceFileUrl(argument)
166
166
  ? sourceRelativeFileUrlPath(argument)
167
- : staticPathAt(argument);
167
+ : staticPath(argument);
168
168
  };
169
169
  /** Project a known source-relative URL through the actual file URL decoder. */
170
170
  const sourceRelativeFileUrlPath = (node) => {
@@ -213,7 +213,7 @@ const staticResolvedPath = (node) => {
213
213
  parts.push(null);
214
214
  continue;
215
215
  }
216
- const value = t.isNode(argument) ? staticPathAt(argument) : undefined;
216
+ const value = t.isNode(argument) ? staticPath(argument) : undefined;
217
217
  // Validate every argument, including those before the last anchor.
218
218
  if (value === undefined)
219
219
  return undefined;
@@ -521,9 +521,20 @@ const pointForOffset = (source, offset) => {
521
521
  /** Observe known bundler/framework marker strings without claiming dependency use. */
522
522
  export const detectVendors = (source) => vendorPatterns.flatMap(({ name, patterns }) => patterns.some((pattern) => source.includes(pattern)) ? [name] : []);
523
523
  /** Commit the static semantic content used to deduplicate registrations. */
524
- export const registrationKey = (registration) => `${registration.runtime}\0${registration.chunk_keys.join("\0")}\0${String(registration.unknown_chunk_keys)}\0${registration.modules.map(({ module_key: key, source_sha256: digest }) => `${key}:${digest}`).join("\0")}`;
524
+ export const registrationKey = (registration) =>
525
+ // Collision-free tuple: chunk/module keys are variable-length source-derived
526
+ // lists, so NUL-joins would collapse ["a\0b"] with ["a", "b"].
527
+ compositeKey([
528
+ registration.runtime,
529
+ registration.chunk_keys,
530
+ String(registration.unknown_chunk_keys),
531
+ registration.modules.map(({ module_key: key, source_sha256: digest }) => [
532
+ key,
533
+ digest,
534
+ ]),
535
+ ]);
525
536
  /** Sort values by a deterministic unique semantic key. */
526
- export const sortedUnique = (values, key) => [...new Map(values.map((value) => [key(value), value])).values()].sort((left, right) => compareCodePoints(key(left), key(right)));
537
+ export const sortedUnique = (values, key) => [...new Map(values.map((value) => [key(value), value])).values()].sort((left, right) => compareUnicodeCodePoints(key(left), key(right)));
527
538
  /** Hash exact UTF-8 source text. */
528
539
  export const sha256Text = (value) => createHash("sha256").update(value).digest("hex");
529
540
  /** Recognized route-construction call suffixes. */
@@ -1,5 +1,7 @@
1
- import { compareCodePoints, uniqueSorted } from "../canonicalOrdering.js";
2
- import { absenceClaimable, canonicalDigest } from "../comparisonSemantics.js";
1
+ import { uniqueSorted } from "../canonicalOrdering.js";
2
+ import { compareUnicodeCodePoints } from "../unicodeCodePointOrder.js";
3
+ import { absenceClaimable } from "../comparisonSemantics.js";
4
+ import { digestCanonicalValue } from "../canonicalDigest.js";
3
5
  import { SOURCE_TO_BUNDLE_SIGNAL_WEIGHTS, sourceToBundleComparisonResultSchema, } from "./sourceToBundleComparisonSchemas.js";
4
6
  import { buildSourceToBundleCandidateIndex, candidateHasDigest, candidateIdsForSource, historicalSourceFiles, scoreSourceToBundleCandidate, sourceBearingNodes, } from "./sourceToBundleSignals.js";
5
7
  /** Compare historical source files to static source-bearing application nodes. */
@@ -33,7 +35,7 @@ export const compareSourceToBundle = (input) => {
33
35
  };
34
36
  return sourceToBundleComparisonResultSchema.parse({
35
37
  ...semanticResult,
36
- comparison_id: `stbc_${canonicalDigest(semanticResult, "Source-to-bundle comparison")}`,
38
+ comparison_id: `stbc_${digestCanonicalValue(semanticResult, "Source-to-bundle comparison")}`,
37
39
  });
38
40
  };
39
41
  const projectComparison = (input) => {
@@ -218,7 +220,7 @@ const markMergedMappings = (input, items) => {
218
220
  return { ...semantic, mapping_id: mappingId(input, semantic) };
219
221
  });
220
222
  };
221
- const mappingId = (input, item) => `stbc_item_${canonicalDigest({
223
+ const mappingId = (input, item) => `stbc_item_${digestCanonicalValue({
222
224
  reference_root_sha256: input.reference.root_sha256,
223
225
  application_graph_id: input.application.graph.graph_id,
224
226
  ...item,
@@ -256,4 +258,4 @@ const comparisonLimitations = (factors) => uniqueSorted([
256
258
  ]);
257
259
  const hasSignal = (candidate, kind) => candidate.signals.some((signal) => signal.kind === kind);
258
260
  const compareCandidates = (left, right) => right.score - left.score ||
259
- compareCodePoints(left.current_node_id, right.current_node_id);
261
+ compareUnicodeCodePoints(left.current_node_id, right.current_node_id);
@@ -1,5 +1,5 @@
1
1
  import { posix } from "node:path";
2
- import { compareCodePoints } from "../canonicalOrdering.js";
2
+ import { compareUnicodeCodePoints, compositeKey, } from "../unicodeCodePointOrder.js";
3
3
  import { SOURCE_TO_BUNDLE_SIGNAL_WEIGHTS, } from "./sourceToBundleComparisonSchemas.js";
4
4
  import { isDigest } from "../digests.js";
5
5
  const RELEVANT_NODE_KINDS = new Set([
@@ -24,11 +24,11 @@ const signalWeight = (kind) => {
24
24
  /** Keep source-bearing application nodes in stable identifier order. */
25
25
  export const sourceBearingNodes = (nodes) => nodes
26
26
  .filter(({ kind }) => RELEVANT_NODE_KINDS.has(kind))
27
- .sort((left, right) => compareCodePoints(left.node_id, right.node_id));
27
+ .sort((left, right) => compareUnicodeCodePoints(left.node_id, right.node_id));
28
28
  /** Keep historical source files in stable path order. */
29
29
  export const historicalSourceFiles = (graph) => graph.entries
30
30
  .filter((entry) => entry.kind === "file" && entry.classifications.includes("source"))
31
- .sort((left, right) => compareCodePoints(left.path, right.path));
31
+ .sort((left, right) => compareUnicodeCodePoints(left.path, right.path));
32
32
  /** Build deterministic candidate indices without assigning fuzzy matches. */
33
33
  export const buildSourceToBundleCandidateIndex = (nodes) => {
34
34
  const projections = nodes.map(projectCurrentNode);
@@ -65,7 +65,7 @@ export const candidateIdsForSource = (source, index) => {
65
65
  for (const group of groups) {
66
66
  if (group === undefined)
67
67
  continue;
68
- for (const nodeId of [...group].sort(compareCodePoints)) {
68
+ for (const nodeId of [...group].sort(compareUnicodeCodePoints)) {
69
69
  if (seen.has(nodeId))
70
70
  continue;
71
71
  seen.add(nodeId);
@@ -166,7 +166,7 @@ const signal = (kind, sourceValue, currentValues) => ({
166
166
  kind,
167
167
  weight: signalWeight(kind),
168
168
  source_value: sourceValue,
169
- current_values: [...new Set(currentValues)].sort(compareCodePoints),
169
+ current_values: [...new Set(currentValues)].sort(compareUnicodeCodePoints),
170
170
  });
171
171
  const candidateConfidence = (signals) => {
172
172
  const kinds = new Set(signals.map(({ kind }) => kind));
@@ -216,10 +216,10 @@ const normalizeCurrentPath = (raw) => {
216
216
  };
217
217
  const uniquePaths = (paths) => [
218
218
  ...new Map(paths.map((path) => [
219
- `${path.kind}\0${path.value}\0${String(path.allowSuffix)}`,
219
+ compositeKey([path.kind, path.value, String(path.allowSuffix)]),
220
220
  path,
221
221
  ])).values(),
222
- ].sort((left, right) => compareCodePoints(`${left.kind}\0${left.value}`, `${right.kind}\0${right.value}`));
222
+ ].sort((left, right) => compareUnicodeCodePoints(compositeKey([left.kind, left.value]), compositeKey([right.kind, right.value])));
223
223
  const pathSuffixes = (path) => {
224
224
  const parts = path.split("/");
225
225
  return parts.map((_, index) => parts.slice(index).join("/"));
@@ -1,10 +1,10 @@
1
1
  /** Encode ordinary JSON as bounded string parts without a document-sized allocation. */
2
2
  export function* jsonParts(value, pretty = false) {
3
- yield* encodeValue(value, pretty, 0, new Set(), false);
3
+ yield* encodeValue(value, pretty, false);
4
4
  }
5
5
  /** Encode validated JSON with canonical key ordering without allocating the whole document. */
6
6
  export function* canonicalJsonParts(value) {
7
- yield* encodeValue(value, false, 0, new Set(), true);
7
+ yield* encodeValue(value, false, true);
8
8
  }
9
9
  /** Buffer JSON parts while preserving complete UTF-16 surrogate pairs. */
10
10
  export function* bufferedJsonParts(parts) {
@@ -41,69 +41,123 @@ function* encodeString(value) {
41
41
  }
42
42
  yield '"';
43
43
  }
44
- function* encodeValue(value, pretty, depth, ancestors, canonical) {
45
- if (typeof value === "string") {
46
- yield* encodeString(value);
47
- return;
48
- }
49
- if (value === null || typeof value === "boolean") {
50
- yield value === null ? "null" : String(value);
51
- return;
52
- }
53
- if (typeof value === "number" && Number.isFinite(value)) {
54
- yield String(value);
55
- return;
56
- }
44
+ /** Encoded text accumulated before it is yielded as one part. */
45
+ const PART_CHARACTERS = 16 * 1024;
46
+ const indentation = [];
47
+ const indent = (depth) => (indentation[depth] ??= `\n${" ".repeat(depth)}`);
48
+ /** Encoded text of a scalar, or undefined for a container or a long string. */
49
+ const scalarText = (value) => {
50
+ if (typeof value === "string")
51
+ return value.length <= 8192 ? JSON.stringify(value) : undefined;
52
+ if (value === null)
53
+ return "null";
54
+ if (typeof value === "boolean")
55
+ return String(value);
56
+ if (typeof value === "number" && Number.isFinite(value))
57
+ return String(value);
58
+ return undefined;
59
+ };
60
+ const openContainer = (value, depth, ancestors, canonical) => {
57
61
  if (typeof value !== "object" || value === null)
58
62
  throw new TypeError("JSON output requires ordinary JSON values");
59
63
  if (ancestors.has(value))
60
64
  throw new TypeError("JSON output contains a circular reference");
61
- if (!Array.isArray(value) &&
62
- Object.prototype.toString.call(value) !== "[object Object]")
65
+ const array = Array.isArray(value);
66
+ if (!array && Object.prototype.toString.call(value) !== "[object Object]")
63
67
  throw new TypeError("JSON output requires ordinary JSON objects");
64
68
  ancestors.add(value);
65
- try {
66
- const array = Array.isArray(value);
67
- const keys = array ? undefined : Object.keys(value);
68
- if (canonical)
69
- keys?.sort();
70
- const count = array ? value.length : (keys?.length ?? 0);
71
- let written = 0;
72
- yield array ? "[" : "{";
73
- for (let index = 0; index < count; index += 1) {
74
- let item;
75
- let key;
76
- if (array) {
77
- item = value[index];
69
+ const keys = array ? undefined : Object.keys(value);
70
+ if (canonical)
71
+ keys?.sort();
72
+ const count = array ? value.length : (keys?.length ?? 0);
73
+ return { value, array, keys, count, depth, index: 0, written: 0 };
74
+ };
75
+ /** The next written member of a container, skipping values JSON omits. */
76
+ const nextMember = (frame) => {
77
+ while (frame.index < frame.count) {
78
+ const index = frame.index;
79
+ frame.index += 1;
80
+ if (frame.array)
81
+ return { key: undefined, item: Reflect.get(frame.value, index) };
82
+ const key = frame.keys?.[index];
83
+ if (key === undefined)
84
+ throw new TypeError("JSON object changed during serialization");
85
+ const item = Reflect.get(frame.value, key);
86
+ // Incur's filter can select inherited methods. Match native JSON's
87
+ // omission without eagerly reading the rest of a bounded result.
88
+ if (item !== undefined &&
89
+ typeof item !== "function" &&
90
+ typeof item !== "symbol")
91
+ return { key, item };
92
+ }
93
+ return undefined;
94
+ };
95
+ /**
96
+ * Encode iteratively into bounded parts. Recursive `yield*` delegation passed
97
+ * every token through one generator frame per nesting level, which dominated
98
+ * the cost of writing large nested results.
99
+ */
100
+ function* encodeValue(root, pretty, canonical) {
101
+ const ancestors = new Set();
102
+ const stack = [];
103
+ let buffer = "";
104
+ let pending = root;
105
+ let hasPending = true;
106
+ while (true) {
107
+ if (hasPending) {
108
+ hasPending = false;
109
+ const text = scalarText(pending);
110
+ if (text !== undefined)
111
+ buffer += text;
112
+ else if (typeof pending === "string") {
113
+ // A long string is split into surrogate-safe parts of its own.
114
+ if (buffer !== "")
115
+ yield buffer;
116
+ buffer = "";
117
+ yield* encodeString(pending);
78
118
  }
79
119
  else {
80
- key = keys?.[index];
81
- if (key === undefined)
82
- throw new TypeError("JSON object changed during serialization");
83
- item = Reflect.get(value, key);
84
- // Incur's filter can select inherited methods. Match native JSON's
85
- // omission without eagerly reading the rest of a bounded result.
86
- if (item === undefined ||
87
- typeof item === "function" ||
88
- typeof item === "symbol")
89
- continue;
120
+ const frame = openContainer(pending, stack.length, ancestors, canonical);
121
+ stack.push(frame);
122
+ buffer += frame.array ? "[" : "{";
90
123
  }
91
- if (written > 0)
92
- yield ",";
93
- if (pretty)
94
- yield `\n${" ".repeat(depth + 1)}`;
95
- if (key !== undefined) {
96
- yield* encodeString(key);
97
- yield pretty ? ": " : ":";
124
+ }
125
+ if (buffer.length >= PART_CHARACTERS) {
126
+ yield buffer;
127
+ buffer = "";
128
+ }
129
+ const frame = stack.at(-1);
130
+ if (frame === undefined)
131
+ break;
132
+ const member = nextMember(frame);
133
+ if (member === undefined) {
134
+ if (pretty && frame.written > 0)
135
+ buffer += indent(frame.depth);
136
+ buffer += frame.array ? "]" : "}";
137
+ ancestors.delete(frame.value);
138
+ stack.pop();
139
+ continue;
140
+ }
141
+ if (frame.written > 0)
142
+ buffer += ",";
143
+ if (pretty)
144
+ buffer += indent(frame.depth + 1);
145
+ if (member.key !== undefined) {
146
+ const key = scalarText(member.key);
147
+ if (key !== undefined)
148
+ buffer += key;
149
+ else {
150
+ if (buffer !== "")
151
+ yield buffer;
152
+ buffer = "";
153
+ yield* encodeString(member.key);
98
154
  }
99
- yield* encodeValue(item, pretty, depth + 1, ancestors, canonical);
100
- written += 1;
155
+ buffer += pretty ? ": " : ":";
101
156
  }
102
- if (pretty && written > 0)
103
- yield `\n${" ".repeat(depth)}`;
104
- yield array ? "]" : "}";
105
- }
106
- finally {
107
- ancestors.delete(value);
157
+ frame.written += 1;
158
+ pending = member.item;
159
+ hasPending = true;
108
160
  }
161
+ if (buffer !== "")
162
+ yield buffer;
109
163
  }
@@ -1,5 +1,5 @@
1
1
  import { z } from "zod";
2
- import { compareCodePoints } from "./canonicalOrdering.js";
2
+ import { compareUnicodeCodePoints } from "./unicodeCodePointOrder.js";
3
3
  const jsonValueTypeSchema = z.enum([
4
4
  "object",
5
5
  "array",
@@ -8,13 +8,17 @@ const jsonValueTypeSchema = z.enum([
8
8
  "boolean",
9
9
  "null",
10
10
  ]);
11
+ const jsonShapePathSegmentSchema = z.discriminatedUnion("kind", [
12
+ z.object({ kind: z.literal("property"), name: z.string() }),
13
+ z.object({ kind: z.literal("array-element") }),
14
+ ]);
11
15
  /** Value-free structural summary of one approved JSON payload. */
12
16
  export const jsonShapeSchema = z.object({
13
17
  root_type: jsonValueTypeSchema,
14
18
  node_count: z.number().int().min(1),
15
19
  max_depth_observed: z.number().int().min(0),
16
20
  properties: z.array(z.object({
17
- path: z.string(),
21
+ path: z.array(jsonShapePathSegmentSchema).min(1),
18
22
  types: z.array(jsonValueTypeSchema).min(1),
19
23
  observations: z.number().int().min(1),
20
24
  })),
@@ -31,7 +35,7 @@ export const inferJsonShape = (text) => {
31
35
  return null;
32
36
  }
33
37
  const properties = new Map();
34
- const pending = [{ value: root, path: "", depth: 0 }];
38
+ const pending = [{ value: root, path: [], depth: 0 }];
35
39
  let nodeCount = 0;
36
40
  let maxDepthObserved = 0;
37
41
  while (pending.length > 0) {
@@ -40,11 +44,26 @@ export const inferJsonShape = (text) => {
40
44
  break;
41
45
  nodeCount += 1;
42
46
  maxDepthObserved = Math.max(maxDepthObserved, current.depth);
47
+ if (current.path.length > 0) {
48
+ const key = JSON.stringify(current.path);
49
+ const type = jsonValueType(current.value);
50
+ const existing = properties.get(key);
51
+ if (existing === undefined)
52
+ properties.set(key, {
53
+ path: current.path,
54
+ types: new Set([type]),
55
+ observations: 1,
56
+ });
57
+ else {
58
+ existing.types.add(type);
59
+ existing.observations += 1;
60
+ }
61
+ }
43
62
  if (Array.isArray(current.value)) {
44
63
  for (let index = current.value.length - 1; index >= 0; index -= 1)
45
64
  pending.push({
46
65
  value: current.value[index],
47
- path: `${current.path}/*`,
66
+ path: [...current.path, { kind: "array-element" }],
48
67
  depth: current.depth + 1,
49
68
  });
50
69
  continue;
@@ -57,15 +76,10 @@ export const inferJsonShape = (text) => {
57
76
  if (entry === undefined)
58
77
  continue;
59
78
  const [name, value] = entry;
60
- const path = `${current.path}/${pointerName(name)}`;
61
- const type = jsonValueType(value);
62
- const existing = properties.get(path);
63
- if (existing === undefined)
64
- properties.set(path, { types: new Set([type]), observations: 1 });
65
- else {
66
- existing.types.add(type);
67
- existing.observations += 1;
68
- }
79
+ const path = [
80
+ ...current.path,
81
+ { kind: "property", name },
82
+ ];
69
83
  pending.push({ value, path, depth: current.depth + 1 });
70
84
  }
71
85
  }
@@ -73,14 +87,13 @@ export const inferJsonShape = (text) => {
73
87
  root_type: jsonValueType(root),
74
88
  node_count: nodeCount,
75
89
  max_depth_observed: maxDepthObserved,
76
- properties: [...properties.entries()]
77
- .map(([path, value]) => ({
78
- path,
90
+ properties: [...properties.values()]
91
+ .map((value) => ({
92
+ path: value.path,
79
93
  types: [...value.types].sort(),
80
94
  observations: value.observations,
81
95
  }))
82
- .sort((left, right) => left.path.localeCompare(right.path) ||
83
- compareCodePoints(left.path, right.path)),
96
+ .sort((left, right) => compareShapePaths(left.path, right.path)),
84
97
  });
85
98
  };
86
99
  const jsonValueType = (value) => {
@@ -100,4 +113,18 @@ const jsonValueType = (value) => {
100
113
  }
101
114
  };
102
115
  const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
103
- const pointerName = (value) => value.replaceAll("~", "~0").replaceAll("/", "~1");
116
+ const compareShapePaths = (left, right) => {
117
+ for (let index = 0; index < Math.min(left.length, right.length); index += 1) {
118
+ const a = left[index];
119
+ const b = right[index];
120
+ if (a === undefined || b === undefined)
121
+ break;
122
+ const order = compareUnicodeCodePoints(a.kind, b.kind) ||
123
+ (a.kind === "property" && b.kind === "property"
124
+ ? compareUnicodeCodePoints(a.name, b.name)
125
+ : 0);
126
+ if (order !== 0)
127
+ return order;
128
+ }
129
+ return left.length - right.length;
130
+ };
@@ -1,12 +1,18 @@
1
1
  import { isAbsolute, relative, sep } from "node:path";
2
2
  import { z } from "zod";
3
- /** Preserve selected filesystem names while rejecting OS-invalid NUL bytes. */
3
+ /**
4
+ * Preserve selected filesystem names while rejecting OS-invalid NUL bytes.
5
+ *
6
+ * The pattern spells NUL as `\x00` rather than `\u0000`. Both accept exactly the
7
+ * same strings. The hex form also avoids the short `\0` spelling rejected by
8
+ * strict schema consumers. A client can reject its entire tool request when
9
+ * one advertised pattern cannot compile. See `offsetDateTimeSchema` for the
10
+ * same hex-escape convention.
11
+ */
4
12
  export const localPathStringSchema = z
5
13
  .string()
6
14
  .min(1)
7
- .regex(/^[^\u0000]*$/u, "Local filesystem paths cannot contain NUL");
8
- /** True when the value is an absolute filesystem path on the host platform. */
9
- export const isAbsoluteLocalPath = (value) => isAbsolute(value);
15
+ .regex(/^[^\x00]*$/u, "Local filesystem paths cannot contain NUL");
10
16
  /** Test lexical containment on the host platform; callers must resolve symlinks first. */
11
17
  export const isPathWithinRoot = (root, path) => {
12
18
  const value = relative(root, path);
@@ -82,8 +82,8 @@ export const projectManagedApplicationGraph = (input) => {
82
82
  };
83
83
  const artifactNode = addArtifactNode(state);
84
84
  addArtifactIdentityNodes(state, artifactNode, parsed);
85
- const memberCounts = addMemberNodes(state, artifactNode, parsed);
86
- const boundaryCounts = addBoundaryNodes(state, artifactNode, parsed);
85
+ addMemberNodes(state, artifactNode, parsed);
86
+ addBoundaryNodes(state, artifactNode, parsed);
87
87
  const omissions = omittedCounts(parsed);
88
88
  const limitations = projectionLimitations(parsed, omissions);
89
89
  const graph = createJavaScriptApplicationGraph({
@@ -104,10 +104,13 @@ export const projectManagedApplicationGraph = (input) => {
104
104
  summary: {
105
105
  graph_nodes: graph.nodes.length,
106
106
  graph_edges: graph.edges.length,
107
- assemblies: parsed.artifact?.result.assembly === null ? 0 : 1,
108
- modules: parsed.artifact?.result.module === null ? 0 : 1,
109
- ...memberCounts,
110
- ...boundaryCounts,
107
+ assemblies: countNodes(graph.nodes, "managed-assembly"),
108
+ modules: countNodes(graph.nodes, "managed-module"),
109
+ types: countNodes(graph.nodes, "managed-type"),
110
+ methods: countNodes(graph.nodes, "managed-method"),
111
+ fields: countNodes(graph.nodes, "managed-field"),
112
+ pinvoke_imports: countNodes(graph.nodes, "managed-pinvoke-import"),
113
+ native_implementations: countNodes(graph.nodes, "managed-native-implementation"),
111
114
  },
112
115
  graph,
113
116
  coverage: managedGraphResultCoverage(omissions),
@@ -119,6 +122,7 @@ export const projectManagedApplicationGraph = (input) => {
119
122
  projection_id: `magp_${sha256(withoutId)}`,
120
123
  });
121
124
  };
125
+ const countNodes = (nodes, kind) => nodes.filter((node) => node.kind === kind).length;
122
126
  const parseManagedInputs = (input) => ({
123
127
  artifact: input.managed_artifact === undefined
124
128
  ? null