rea-agents 6.2.0 → 6.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (297) hide show
  1. package/README.md +18 -20
  2. package/bridge/hopper_bridge.py +2 -0
  3. package/dist/android/JadxProvider.js +8 -2
  4. package/dist/android/JadxSession.js +51 -9
  5. package/dist/application/BinaryTargetResolver.js +63 -17
  6. package/dist/application/BrowserScenarioEvidence.js +2 -2
  7. package/dist/application/ClientConfigurationDocument.js +28 -0
  8. package/dist/application/ClientRegistrationStatus.js +19 -6
  9. package/dist/application/DirectAnalysis.js +12 -6
  10. package/dist/application/DirectAnalysisCleanup.js +0 -1
  11. package/dist/application/DirectAnalysisStatus.js +2 -5
  12. package/dist/application/Doctor.js +25 -34
  13. package/dist/application/DoctorDiagnostics.js +1 -1
  14. package/dist/application/EvidenceBundleFiles.js +1 -1
  15. package/dist/application/InvestigationProviders.js +4 -4
  16. package/dist/application/JsonFiles.js +15 -15
  17. package/dist/application/LinuxHopper.js +2 -1
  18. package/dist/application/ReconstructionObligationCandidates.js +9 -2
  19. package/dist/application/ReconstructionObligationLedgerProjection.js +3 -1
  20. package/dist/application/RegularFileRead.js +17 -0
  21. package/dist/application/Setup.js +18 -7
  22. package/dist/application/SetupClientConfiguration.js +18 -7
  23. package/dist/application/SetupHost.js +6 -4
  24. package/dist/application/SetupPlan.js +19 -15
  25. package/dist/application/SetupSkill.js +57 -8
  26. package/dist/application/SupportedClients.js +43 -0
  27. package/dist/application/Uninstall.js +18 -2
  28. package/dist/application/UpdateMaintenance.js +6 -2
  29. package/dist/application/Utf8JsonInput.js +64 -0
  30. package/dist/application/WebScriptExportService.js +13 -6
  31. package/dist/application/android/AndroidAnalysisService.js +1 -1
  32. package/dist/application/binary/AnalysisSnapshotCache.js +5 -4
  33. package/dist/application/binary/BinarySession.js +16 -0
  34. package/dist/application/binary/BinarySessionOpen.js +9 -1
  35. package/dist/application/javascript/ElectronActiveEvidence.js +2 -2
  36. package/dist/application/javascript/ElectronBoundaryAnalysis.js +2 -2
  37. package/dist/application/javascript/ElectronBoundaryGraphNative.js +5 -1
  38. package/dist/application/javascript/JavaScriptApplicationEvidence.js +1 -0
  39. package/dist/application/javascript/JavaScriptApplicationEvidenceGraph.js +107 -46
  40. package/dist/application/javascript/JavaScriptApplicationService.js +1 -0
  41. package/dist/application/javascript/JavaScriptApplicationWorkflowService.js +59 -45
  42. package/dist/application/javascript/JavaScriptArtifactAnalysis.js +0 -6
  43. package/dist/application/javascript/JavaScriptArtifactGraphBuilder.js +8 -18
  44. package/dist/application/javascript/JavaScriptArtifactGraphFindings.js +34 -26
  45. package/dist/application/javascript/JavaScriptArtifactPathResolution.js +44 -12
  46. package/dist/application/javascript/JavaScriptArtifactReconstruction.js +6 -3
  47. package/dist/application/javascript/JavaScriptArtifactReconstructionInput.js +1 -0
  48. package/dist/application/javascript/JavaScriptJsonModules.js +2 -2
  49. package/dist/application/javascript/JavaScriptModuleRelationships.js +5 -17
  50. package/dist/application/javascript/JavaScriptRuntimeReconciliationService.js +11 -27
  51. package/dist/application/javascript/JavaScriptSemanticGraphAsyncProjection.js +2 -2
  52. package/dist/application/javascript/JavaScriptSemanticGraphBuilder.js +8 -6
  53. package/dist/application/javascript/JavaScriptSemanticGraphChildProcessProjection.js +1 -1
  54. package/dist/application/javascript/JavaScriptSemanticGraphConstruction.js +7 -5
  55. package/dist/application/javascript/JavaScriptSemanticGraphDataProjection.js +1 -1
  56. package/dist/application/javascript/JavaScriptSemanticGraphEvidence.js +1 -1
  57. package/dist/application/javascript/JavaScriptSemanticGraphFingerprintProjection.js +2 -2
  58. package/dist/application/javascript/JavaScriptSemanticGraphFlowProjection.js +2 -2
  59. package/dist/application/javascript/JavaScriptSemanticGraphObjectProjection.js +1 -1
  60. package/dist/application/javascript/JavaScriptSemanticGraphProjection.js +4 -4
  61. package/dist/application/javascript/JavaScriptSemanticGraphResourceProjection.js +1 -1
  62. package/dist/application/javascript/JavaScriptSemanticGraphValueProjection.js +10 -7
  63. package/dist/application/javascript/JavaScriptSemanticTraceService.js +15 -10
  64. package/dist/application/native/NativeCallRoutes.js +2 -4
  65. package/dist/artifacts/ArtifactProvider.js +14 -16
  66. package/dist/artifacts/ArtifactProviderMetadata.js +1 -4
  67. package/dist/artifacts/AsarArtifactReader.js +81 -17
  68. package/dist/artifacts/DirectoryArtifactReader.js +2 -2
  69. package/dist/artifacts/NativeDmgArtifactReader.js +152 -67
  70. package/dist/artifacts/NativeDmgOwnership.js +109 -0
  71. package/dist/artifacts/apple/KeyedArchiveReader.js +54 -46
  72. package/dist/artifacts/apple/MachoLoadCommandReader.js +36 -6
  73. package/dist/artifacts/extraction/ArtifactExtraction.js +29 -11
  74. package/dist/artifacts/inventory/ArtifactGraphConstruction.js +7 -8
  75. package/dist/artifacts/inventory/classify.js +33 -14
  76. package/dist/artifacts/inventory/hashStableRootArtifact.js +37 -0
  77. package/dist/artifacts/inventory/scanCanonical.js +28 -22
  78. package/dist/artifacts/inventory/scanReader.js +7 -11
  79. package/dist/artifacts/javascript/JavaScriptArtifactFiles.js +65 -27
  80. package/dist/browser/CdpBrowserProvider.js +4 -3
  81. package/dist/browser/CdpCaptureStorageFingerprints.js +3 -3
  82. package/dist/browser/CdpElectronInspection.js +2 -2
  83. package/dist/browser/CdpElectronProvider.js +4 -3
  84. package/dist/browser/CdpElectronScripts.js +2 -2
  85. package/dist/browser/CdpWebMcpDiscovery.js +16 -13
  86. package/dist/browser/PlaywrightBrowserScenarioProvider.js +6 -6
  87. package/dist/browser/PlaywrightScenarioBrowser.js +145 -42
  88. package/dist/browser/PlaywrightScenarioSession.js +3 -11
  89. package/dist/browser/WebSourceMapFetcher.js +32 -6
  90. package/dist/browser/assets/ScenarioScriptCapture.js +8 -12
  91. package/dist/cli/coreAnalysisCommands.js +2 -2
  92. package/dist/cli/coreBinaryCommands.js +13 -9
  93. package/dist/cli/electronCommands.js +9 -10
  94. package/dist/cli/javascriptApplicationAnalysis.js +2 -12
  95. package/dist/cli/jsonOutput.js +3 -2
  96. package/dist/cli/streamedJsonOutput.js +83 -4
  97. package/dist/cli/utilityCommands.js +2 -4
  98. package/dist/cli.js +5 -2
  99. package/dist/cliJsonFile.js +179 -0
  100. package/dist/cliJsonInput.js +47 -34
  101. package/dist/cliObservationOptions.js +4 -0
  102. package/dist/composition/auxiliaryAnalysisProviders.js +5 -4
  103. package/dist/composition/browserScenario.js +2 -2
  104. package/dist/composition/directAnalysis.js +2 -3
  105. package/dist/contracts/artifactComparisonExample.js +5 -5
  106. package/dist/contracts/errorSchemas.js +3 -1
  107. package/dist/contracts/functionComparisonExample.js +8 -0
  108. package/dist/contracts/inputSchemaPresentation.js +94 -3
  109. package/dist/contracts/javascript/electronToolContracts.js +2 -1
  110. package/dist/contracts/javascript/javascriptApplicationWorkflowExamples.js +3 -2
  111. package/dist/contracts/javascript/javascriptExportShapeComparisonExample.js +6 -3
  112. package/dist/contracts/javascript/javascriptRuntimeReconciliationExample.js +8 -7
  113. package/dist/contracts/managed/managedToolContracts.js +3 -2
  114. package/dist/contracts/mobileApplicationGraphExamples.js +5 -5
  115. package/dist/contracts/native/nativeToolContracts.js +1 -1
  116. package/dist/contracts/sessionLifecycleInputs.js +4 -3
  117. package/dist/contracts/sessionStatusContract.js +3 -2
  118. package/dist/contracts/sessionToolContracts.js +3 -2
  119. package/dist/contracts/sessionToolSchemas.js +3 -2
  120. package/dist/contracts/toolOutputSchemaGroups.js +2 -2
  121. package/dist/contracts/toolOutputSchemaPrimitives.js +2 -5
  122. package/dist/domain/analysisErrorBase.js +5 -0
  123. package/dist/domain/analysisErrorPresentation.js +4 -2
  124. package/dist/domain/analysisSnapshot.js +3 -1
  125. package/dist/domain/analysisView/analysisView.js +1 -3
  126. package/dist/domain/android/androidPartialObservation.js +36 -0
  127. package/dist/domain/apple/dylibResolution.js +1 -1
  128. package/dist/domain/artifactComparison.js +4 -4
  129. package/dist/domain/artifactGraph.js +1 -1
  130. package/dist/domain/artifactIdentity.js +8 -8
  131. package/dist/domain/artifactInspection.js +8 -8
  132. package/dist/domain/artifactInventoryEvidence.js +5 -5
  133. package/dist/domain/browserCompleteness.js +3 -2
  134. package/dist/domain/browserScenarioCaptureValues.js +2 -2
  135. package/dist/domain/browserScenarioNormalization.js +3 -3
  136. package/dist/domain/browserScenarioValues.js +3 -2
  137. package/dist/domain/callPath.js +8 -10
  138. package/dist/domain/canonicalDigest.js +7 -1
  139. package/dist/domain/canonicalOrdering.js +1 -13
  140. package/dist/domain/changedBehavior.js +2 -3
  141. package/dist/domain/comparisonSemantics.js +0 -5
  142. package/dist/domain/digests.js +0 -3
  143. package/dist/domain/evidence.js +10 -5
  144. package/dist/domain/evidenceBundle.js +51 -33
  145. package/dist/domain/firmware/firmwareAnalysis.js +4 -3
  146. package/dist/domain/functionComparison.js +2 -1
  147. package/dist/domain/functionComparisonNormalization.js +4 -3
  148. package/dist/domain/functionComparisonResults.js +2 -2
  149. package/dist/domain/functionDossierEvidence.js +2 -1
  150. package/dist/domain/hopperValues.js +11 -15
  151. package/dist/domain/javascript/electronActiveObservation.js +4 -3
  152. package/dist/domain/javascript/electronStaticAnalysisBrowser.js +2 -2
  153. package/dist/domain/javascript/electronStaticAnalysisIpc.js +9 -1
  154. package/dist/domain/javascript/electronStaticAnalysisNative.js +5 -3
  155. package/dist/domain/javascript/electronStaticAnalysisValues.js +8 -4
  156. package/dist/domain/javascript/javascriptApplicationAnalysis.js +3 -1
  157. package/dist/domain/javascript/javascriptApplicationChangeGraph.js +12 -8
  158. package/dist/domain/javascript/javascriptApplicationEvidenceSchemas.js +4 -0
  159. package/dist/domain/javascript/javascriptApplicationGraph.js +15 -13
  160. package/dist/domain/javascript/javascriptApplicationVersionComparison.js +4 -4
  161. package/dist/domain/javascript/javascriptApplicationVersionComparisonSchemas.js +37 -22
  162. package/dist/domain/javascript/javascriptApplicationVersionItems.js +45 -34
  163. package/dist/domain/javascript/javascriptApplicationVersionKeys.js +7 -7
  164. package/dist/domain/javascript/javascriptAstFingerprint.js +2 -2
  165. package/dist/domain/javascript/javascriptAstValues.js +22 -0
  166. package/dist/domain/javascript/javascriptExportShapeComparison.js +3 -2
  167. package/dist/domain/javascript/javascriptExportShapeComparisonSchemas.js +31 -23
  168. package/dist/domain/javascript/javascriptExportShapeSelection.js +2 -2
  169. package/dist/domain/javascript/javascriptExportShapeVariants.js +3 -2
  170. package/dist/domain/javascript/javascriptFeatureSeed.js +5 -3
  171. package/dist/domain/javascript/javascriptFeatureTrace.js +7 -6
  172. package/dist/domain/javascript/javascriptFeatureTraceSchemas.js +17 -9
  173. package/dist/domain/javascript/javascriptFeatureTraversal.js +4 -4
  174. package/dist/domain/javascript/javascriptNativeHandoff.js +6 -6
  175. package/dist/domain/javascript/javascriptRuntimeObservation.js +8 -5
  176. package/dist/domain/javascript/javascriptRuntimeReconciliation.js +12 -6
  177. package/dist/domain/javascript/javascriptRuntimeReconciliationActive.js +9 -8
  178. package/dist/domain/javascript/javascriptRuntimeReconciliationCaptureParsing.js +212 -0
  179. package/dist/domain/javascript/javascriptRuntimeReconciliationGraph.js +5 -4
  180. package/dist/domain/javascript/javascriptRuntimeReconciliationInputValidation.js +28 -0
  181. package/dist/domain/javascript/javascriptRuntimeReconciliationMatching.js +5 -5
  182. package/dist/domain/javascript/javascriptRuntimeReconciliationParsing.js +12 -223
  183. package/dist/domain/javascript/javascriptRuntimeReconciliationResult.js +2 -2
  184. package/dist/domain/javascript/javascriptRuntimeReconciliationRuntime.js +15 -4
  185. package/dist/domain/javascript/javascriptRuntimeReconciliationSchemas.js +2 -2
  186. package/dist/domain/javascript/javascriptRuntimeStaticCandidates.js +7 -6
  187. package/dist/domain/javascript/javascriptSemanticAnalysis.js +200 -8
  188. package/dist/domain/javascript/javascriptSemanticCallResolution.js +9 -7
  189. package/dist/domain/javascript/javascriptSemanticChildProcesses.js +2 -2
  190. package/dist/domain/javascript/javascriptSemanticCoverage.js +20 -0
  191. package/dist/domain/javascript/javascriptSemanticDataEffectHelpers.js +7 -9
  192. package/dist/domain/javascript/javascriptSemanticDataEffects.js +4 -11
  193. package/dist/domain/javascript/javascriptSemanticFingerprints.js +2 -2
  194. package/dist/domain/javascript/javascriptSemanticGraph.js +142 -35
  195. package/dist/domain/javascript/javascriptSemanticGraphSchemas.js +19 -1
  196. package/dist/domain/javascript/javascriptSemanticIr.js +0 -4
  197. package/dist/domain/javascript/javascriptSemanticIterationSources.js +106 -0
  198. package/dist/domain/javascript/javascriptSemanticMemberMutations.js +497 -113
  199. package/dist/domain/javascript/javascriptSemanticMutationInitializers.js +190 -0
  200. package/dist/domain/javascript/javascriptSemanticMutationValues.js +41 -27
  201. package/dist/domain/javascript/javascriptSemanticObjects.js +2 -6
  202. package/dist/domain/javascript/javascriptSemanticPrimitives.js +7 -2
  203. package/dist/domain/javascript/javascriptSemanticProjection.js +20 -14
  204. package/dist/domain/javascript/javascriptSemanticPromises.js +15 -21
  205. package/dist/domain/javascript/javascriptSemanticPropertyPaths.js +23 -0
  206. package/dist/domain/javascript/javascriptSemanticProvenance.js +3 -3
  207. package/dist/domain/javascript/javascriptSemanticQuery.js +8 -2
  208. package/dist/domain/javascript/javascriptSemanticQueryIdentity.js +3 -2
  209. package/dist/domain/javascript/javascriptSemanticQuerySchemas.js +8 -9
  210. package/dist/domain/javascript/javascriptSemanticRequireOrigin.js +16 -10
  211. package/dist/domain/javascript/javascriptSemanticReturns.js +23 -27
  212. package/dist/domain/javascript/javascriptSemanticTraversal.js +6 -1
  213. package/dist/domain/javascript/javascriptSemanticValues.js +135 -24
  214. package/dist/domain/javascript/javascriptSourceMapPaths.js +11 -1
  215. package/dist/domain/javascript/javascriptSourceParser.js +34 -9
  216. package/dist/domain/javascript/javascriptStaticAnalysisBundler.js +5 -6
  217. package/dist/domain/javascript/javascriptStaticAnalysisHelpers.js +26 -15
  218. package/dist/domain/javascript/sourceToBundleComparison.js +7 -5
  219. package/dist/domain/javascript/sourceToBundleSignals.js +7 -7
  220. package/dist/domain/jsonSerialization.js +109 -55
  221. package/dist/domain/jsonShape.js +46 -19
  222. package/dist/domain/localPath.js +10 -4
  223. package/dist/domain/managed/managedApplicationGraph.js +10 -6
  224. package/dist/domain/managed/managedApplicationGraphNodes.js +82 -57
  225. package/dist/domain/managed/managedMemberComparisonMatch.js +6 -7
  226. package/dist/domain/native/nativeCallObservation.js +2 -4
  227. package/dist/domain/native/nativeValueFlow.js +5 -11
  228. package/dist/domain/native/objcSwiftMetadata.js +15 -17
  229. package/dist/domain/process/processCapture.js +11 -10
  230. package/dist/domain/process/processCaptureCoverage.js +8 -5
  231. package/dist/domain/process/processCaptureExample.js +43 -0
  232. package/dist/domain/process/processCaptureValidation.js +4 -3
  233. package/dist/domain/process/processComparison.js +0 -23
  234. package/dist/domain/process/processScenario.js +3 -3
  235. package/dist/domain/process/processTraceEvaluation.js +4 -4
  236. package/dist/domain/process/processTraceSpecification.js +1 -3
  237. package/dist/domain/providerCleanupError.js +6 -2
  238. package/dist/domain/reconstructionCoverage.js +2 -1
  239. package/dist/domain/reconstructionUnknowns.js +4 -3
  240. package/dist/domain/reconstructionVerification.js +3 -2
  241. package/dist/domain/referenceSourceGraph.js +7 -7
  242. package/dist/domain/referenceSourceImportParsing.js +34 -45
  243. package/dist/domain/residualUnknown.js +3 -2
  244. package/dist/domain/staticRuntimeCorrelation.js +2 -1
  245. package/dist/domain/swiftSymbolClassification.js +6 -1
  246. package/dist/domain/symbolAnalysis.js +17 -2
  247. package/dist/domain/unicodeCodePointOrder.js +6 -0
  248. package/dist/domain/webBundleAnalyzerInspection.js +9 -1
  249. package/dist/domain/webCaptureDiff.js +71 -29
  250. package/dist/domain/webCaptureDiffSchemas.js +2 -8
  251. package/dist/domain/webInventory.js +3 -2
  252. package/dist/domain/webMcpDiscovery.js +4 -3
  253. package/dist/domain/webScriptExport.js +1 -1
  254. package/dist/dotnet/ManagedMemberInstructionDecoder.js +1 -2
  255. package/dist/dotnet/ManagedStaticProvider.js +10 -7
  256. package/dist/dotnet/ManagedStaticProviderMetadata.js +1 -4
  257. package/dist/filesystem/RegularFile.js +41 -0
  258. package/dist/generatedPackageMetadata.js +1 -1
  259. package/dist/ghidra/GhidraClient.js +14 -4
  260. package/dist/ghidra/GhidraInstallation.js +111 -10
  261. package/dist/ghidra/GhidraLauncher.js +43 -19
  262. package/dist/hopper/HopperCleanup.js +1 -1
  263. package/dist/ida/IdaOperationRunner.js +2 -0
  264. package/dist/ida/IdaSessionClient.js +4 -2
  265. package/dist/inspector/JavaScriptRuntimeScope.js +9 -5
  266. package/dist/inspector/V8InspectorCaptureProjection.js +46 -13
  267. package/dist/inspector/V8InspectorProvider.js +60 -8
  268. package/dist/main/shutdown.js +76 -32
  269. package/dist/main/transport.js +1 -1
  270. package/dist/native/AppleObjcDispatchFacets.js +3 -3
  271. package/dist/native/AppleObjcProperties.js +17 -7
  272. package/dist/native/LldbCallTracer.js +241 -75
  273. package/dist/native/NativeMacOSProvider.js +10 -5
  274. package/dist/native/NativeMacOSProviderMetadata.js +1 -2
  275. package/dist/process/ProcessOwnershipObservation.js +9 -13
  276. package/dist/process/capture/FilesystemSnapshot.js +88 -18
  277. package/dist/process/capture/ProcessCaptureLifecycle.js +13 -27
  278. package/dist/process/capture/ProcessFilesystemEffects.js +19 -4
  279. package/dist/process/capture/ProcessHarness.js +8 -21
  280. package/dist/server/analysisAdmission.js +8 -0
  281. package/dist/server/createServer.js +22 -23
  282. package/dist/server/registerApplicationTools/compareExportShapes.js +2 -1
  283. package/dist/server/registerApplicationTools/helpers.js +3 -2
  284. package/dist/server/registerArtifactTools.js +2 -2
  285. package/dist/server/registerCloseLifecycleTool.js +6 -4
  286. package/dist/server/registerEnhancedTools.js +78 -73
  287. package/dist/server/registerEvidenceTools.js +54 -46
  288. package/dist/server/registerManagedTools.js +7 -4
  289. package/dist/server/registerOfficialTools.js +31 -25
  290. package/dist/server/registerSessionTools.js +9 -3
  291. package/native/windows/build/manifest.json +1 -1
  292. package/package.json +6 -3
  293. package/skills/reverse-engineer-anything/SKILL.md +5 -5
  294. package/skills/reverse-engineer-anything/references/native-and-artifacts.md +9 -0
  295. package/dist/artifacts/inventory/policy.js +0 -2
  296. package/dist/domain/managed/managedApplicationGraphNodeCoverage.js +0 -6
  297. package/dist/server/registerNativeTools.js +0 -6
@@ -1,6 +1,6 @@
1
1
  import * as t from "@babel/types";
2
2
  import { boundedExpression, collectContextBridgeMembers, electronStaticValue, objectProperty, } from "./electronStaticAnalysisValues.js";
3
- import { compareCodePoints } from "../canonicalOrdering.js";
3
+ import { compareUnicodeCodePoints } from "../unicodeCodePointOrder.js";
4
4
  import { addLocatedFinding } from "./javascriptStaticAnalysisFindings.js";
5
5
  import { argumentNode, calleeName, range, staticPath, staticPathResolutionContext, } from "./javascriptStaticAnalysisHelpers.js";
6
6
  import { semanticStaticPropertyName } from "./javascriptAstValues.js";
@@ -98,7 +98,7 @@ const collectWebPreferences = (source, object) => {
98
98
  unknown += 1;
99
99
  preferences.push({ name, value });
100
100
  }
101
- preferences.sort((left, right) => compareCodePoints(left.name, right.name));
101
+ preferences.sort((left, right) => compareUnicodeCodePoints(left.name, right.name));
102
102
  return {
103
103
  status: "object-literal",
104
104
  preferences,
@@ -3,6 +3,7 @@ import { boundedExpression, electronStaticValue, handlerKind, } from "./electron
3
3
  import { addLocatedFinding } from "./javascriptStaticAnalysisFindings.js";
4
4
  import { argumentNode, calleeName, range, } from "./javascriptStaticAnalysisHelpers.js";
5
5
  import { semanticStaticPropertyName } from "./javascriptAstValues.js";
6
+ import { compositeKey } from "../unicodeCodePointOrder.js";
6
7
  /** Inspect Electron IPC operations and validation candidates. */
7
8
  export const inspectElectronIpcNode = (node, context) => {
8
9
  if (t.isCallExpression(node)) {
@@ -116,7 +117,14 @@ const addValidation = (context, node, input) => {
116
117
  };
117
118
  addLocatedFinding(context, {
118
119
  collection: context.accumulator.senderValidations,
119
- key: `electron-validation\0${input.subject}\0${input.mechanism}\0${input.expected.status === "literal" ? String(input.expected.value) : input.expected.expression}`,
120
+ key: compositeKey([
121
+ "electron-validation",
122
+ input.subject,
123
+ input.mechanism,
124
+ input.expected.status === "literal"
125
+ ? String(input.expected.value)
126
+ : input.expected.expression,
127
+ ]),
120
128
  node,
121
129
  value: finding,
122
130
  });
@@ -1,5 +1,5 @@
1
1
  import * as t from "@babel/types";
2
- import { compareCodePoints } from "../canonicalOrdering.js";
2
+ import { compareUnicodeCodePoints, compositeKey, } from "../unicodeCodePointOrder.js";
3
3
  import { stripQueryAndFragment } from "../artifactPathSyntax.js";
4
4
  import { addLocatedFinding } from "./javascriptStaticAnalysisFindings.js";
5
5
  import { argumentNode, calleeName, range, stringValue, } from "./javascriptStaticAnalysisHelpers.js";
@@ -98,11 +98,13 @@ const addBinding = (input) => {
98
98
  const { context, node, specifier, kind } = input;
99
99
  const unique = [
100
100
  ...new Set(input.members.filter((member) => member !== "")),
101
- ].sort(compareCodePoints);
101
+ ].sort(compareUnicodeCodePoints);
102
102
  const members = unique.length === 0 ? ["*"] : unique;
103
103
  addLocatedFinding(context, {
104
104
  collection: context.accumulator.nativeAddonBindings,
105
- key: `native-addon-binding\0${kind}\0${specifier}\0${members.join("\0")}`,
105
+ // Members are a variable-length source-derived list: compositeKey keeps
106
+ // ["a\0b"] distinct from ["a", "b"] instead of collapsing one binding.
107
+ key: compositeKey(["native-addon-binding", kind, specifier, members]),
106
108
  node,
107
109
  value: {
108
110
  specifier,
@@ -1,5 +1,5 @@
1
1
  import * as t from "@babel/types";
2
- import { compareCodePoints } from "../canonicalOrdering.js";
2
+ import { compareUnicodeCodePoints } from "../unicodeCodePointOrder.js";
3
3
  import { readExactJavaScriptLiteral, semanticStaticPropertyName, } from "./javascriptAstValues.js";
4
4
  import { sourceSlice } from "./javascriptStaticAnalysisHelpers.js";
5
5
  /** Preserve one literal value or the exact inert expression. */
@@ -72,7 +72,7 @@ export const collectContextBridgeMembers = (node) => {
72
72
  unknown: 0,
73
73
  };
74
74
  collectMembersAt(node, "", 0, state);
75
- const members = [...new Set(state.members)].sort(compareCodePoints);
75
+ const members = [...new Set(state.members)].sort(compareUnicodeCodePoints);
76
76
  return {
77
77
  status: "object-literal",
78
78
  members,
@@ -107,7 +107,11 @@ const literalValue = (node) => {
107
107
  if (literal.found)
108
108
  return literal;
109
109
  if (t.isUnaryExpression(node, { operator: "-" }) &&
110
- t.isNumericLiteral(node.argument))
111
- return { found: true, value: -node.argument.value };
110
+ t.isNumericLiteral(node.argument)) {
111
+ const value = -node.argument.value;
112
+ return Number.isFinite(value) && !Object.is(value, -0)
113
+ ? { found: true, value }
114
+ : { found: false };
115
+ }
112
116
  return { found: false };
113
117
  };
@@ -3,12 +3,14 @@ import { javascriptApplicationGraphSchema, isValidatedImmutableJavaScriptApplica
3
3
  import { javaScriptSemanticGraphSchema, isValidatedImmutableJavaScriptSemanticGraph, } from "./javascriptSemanticGraph.js";
4
4
  import { digestSchema } from "../digests.js";
5
5
  import { prefixedDigestSchema } from "../digests.js";
6
+ import { integrityContradictionSchema } from "../artifactGraph.js";
6
7
  import { localPathStringSchema } from "../localPath.js";
7
8
  const countSchema = z.number().int().min(0);
8
9
  /** Public target-free request for static JavaScript application analysis. */
9
10
  export const analyzeJavaScriptApplicationInputSchema = z.strictObject({
10
11
  input_path: localPathStringSchema,
11
12
  format: z.enum(["auto", "asar", "directory"]).default("auto"),
13
+ integrity_policy: z.enum(["fail", "record-and-continue"]).default("fail"),
12
14
  });
13
15
  /** Compact counts for the high-level Electron architecture/security surface. */
14
16
  const electronBoundarySummarySchema = z.strictObject({
@@ -44,7 +46,6 @@ const reconstructionStatisticsSchema = z.strictObject({
44
46
  findings: countSchema,
45
47
  modules: countSchema,
46
48
  parse_failures: countSchema,
47
- truncated_scopes: countSchema,
48
49
  });
49
50
  const applicationAnalysisResultShape = z.strictObject({
50
51
  input_path: z.string().min(1),
@@ -52,6 +53,7 @@ const applicationAnalysisResultShape = z.strictObject({
52
53
  root_artifact_sha256: digestSchema,
53
54
  inventory_manifest_id: prefixedDigestSchema("agm"),
54
55
  inventory_graph_sha256: digestSchema,
56
+ integrity_contradictions: z.array(integrityContradictionSchema),
55
57
  graph: javascriptApplicationGraphSchema,
56
58
  summary: electronBoundarySummarySchema,
57
59
  statistics: reconstructionStatisticsSchema,
@@ -1,5 +1,6 @@
1
- import { createJavaScriptApplicationEdge, createJavaScriptApplicationGraph, createJavaScriptApplicationNode, } from "./javascriptApplicationGraph.js";
2
- import { compareCodePoints, uniqueSorted } from "../canonicalOrdering.js";
1
+ import { createJavaScriptApplicationEdge, createImmutableJavaScriptApplicationGraphSteps, createJavaScriptApplicationNode, } from "./javascriptApplicationGraph.js";
2
+ import { uniqueSorted } from "../canonicalOrdering.js";
3
+ import { compareUnicodeCodePoints } from "../unicodeCodePointOrder.js";
3
4
  /** Merge compared nodes and add inferred right-to-left changed_from edges. */
4
5
  export const buildJavaScriptApplicationChangeGraph = (input) => {
5
6
  const allNodes = nodeCandidates(input);
@@ -24,7 +25,7 @@ export const buildJavaScriptApplicationChangeGraph = (input) => {
24
25
  const candidateEdges = uniqueEdges([...sourceEdges, ...comparisonEdges]);
25
26
  const rootNodeIds = preferredRoots.filter((nodeId) => retained.has(nodeId));
26
27
  const fallbackRoot = mergedNodes[0]?.node_id;
27
- const graph = createJavaScriptApplicationGraph({
28
+ const steps = createImmutableJavaScriptApplicationGraphSteps({
28
29
  schema: "JavaScriptApplicationGraph",
29
30
  root_node_ids: rootNodeIds.length > 0
30
31
  ? rootNodeIds
@@ -41,7 +42,10 @@ export const buildJavaScriptApplicationChangeGraph = (input) => {
41
42
  "The change graph contains compared entities and their retained relationships; it is not an executable application.",
42
43
  ]),
43
44
  });
44
- return { graph };
45
+ let next = steps.next();
46
+ while (!next.done)
47
+ next = steps.next();
48
+ return { graph: next.value };
45
49
  };
46
50
  const nodeCandidates = (input) => {
47
51
  const required = new Set([
@@ -145,7 +149,7 @@ const changeGraphCoverage = (input) => {
145
149
  };
146
150
  const sourceCoverageLimits = (input) => [
147
151
  ...new Map([...input.left.coverage.limits, ...input.right.coverage.limits].map((limit) => [`${limit.name}\0${limit.value}\0${limit.unit}`, limit])).values(),
148
- ].sort((left, right) => compareCodePoints(left.name, right.name));
152
+ ].sort((left, right) => compareUnicodeCodePoints(left.name, right.name));
149
153
  const combineOmittedCounts = (left, right) => left === null || right === null ? null : left + right;
150
154
  const mergeNodes = (nodes) => {
151
155
  const groups = new Map();
@@ -159,13 +163,13 @@ const mergeNodes = (nodes) => {
159
163
  ...new Map(group
160
164
  .flatMap(({ observations: values }) => values)
161
165
  .map((observation) => [observation.observation_id, observation])).values(),
162
- ].sort((left, right) => compareCodePoints(left.observation_id, right.observation_id));
166
+ ].sort((left, right) => compareUnicodeCodePoints(left.observation_id, right.observation_id));
163
167
  return createJavaScriptApplicationNode({
164
168
  kind: first.kind,
165
169
  identity: first.identity,
166
170
  observations: observations.map(({ observation_id: _id, identifier_strategy: _strategy, ...value }) => value),
167
171
  });
168
172
  });
169
- return merged.sort((left, right) => compareCodePoints(left.node_id, right.node_id));
173
+ return merged.sort((left, right) => compareUnicodeCodePoints(left.node_id, right.node_id));
170
174
  };
171
- const uniqueEdges = (edges) => [...new Map(edges.map((edge) => [edge.edge_id, edge])).values()].sort((left, right) => compareCodePoints(left.edge_id, right.edge_id));
175
+ const uniqueEdges = (edges) => [...new Map(edges.map((edge) => [edge.edge_id, edge])).values()].sort((left, right) => compareUnicodeCodePoints(left.edge_id, right.edge_id));
@@ -232,6 +232,10 @@ const applicationGraphEvidenceBaseSchema = z.strictObject({
232
232
  limitations: z.array(boundedTextSchema),
233
233
  evidence_ids: z.array(prefixedDigestSchema("ev")),
234
234
  });
235
+ /** Shared provenance fields apart from the fact-specific evidence location. */
236
+ export const applicationGraphEvidenceContextSchema = applicationGraphEvidenceBaseSchema.omit({ location: true });
237
+ /** Exact coordinates retained on each graph fact. */
238
+ export const applicationGraphEvidenceLocationSchema = applicationLocationReferenceSchema;
235
239
  const checkAuthorityState = (evidence, context) => {
236
240
  if (evidence.authority === "static-relationship-inference" &&
237
241
  evidence.state !== "inferred")
@@ -1,6 +1,8 @@
1
1
  import { z } from "zod";
2
- import { canonicalDigest, canonicalJson } from "../comparisonSemantics.js";
3
- import { compareCodePoints, uniqueSorted } from "../canonicalOrdering.js";
2
+ import { canonicalJson } from "../comparisonSemantics.js";
3
+ import { digestCanonicalValue } from "../canonicalDigest.js";
4
+ import { uniqueSorted } from "../canonicalOrdering.js";
5
+ import { compareUnicodeCodePoints } from "../unicodeCodePointOrder.js";
4
6
  import { freezeOwnedJsonSnapshotSteps } from "../immutableJson.js";
5
7
  import { applicationEdgeInputSchema, applicationEdgeSchema, applicationNodeInputSchema, applicationNodeObservationSchema, applicationNodeSchema, javascriptApplicationGraphInputSchema, javascriptApplicationGraphRecordSchema, } from "./javascriptApplicationGraphSchemas.js";
6
8
  const OBSERVATION_IDENTIFIER_STRATEGY = {
@@ -12,7 +14,7 @@ const EDGE_IDENTIFIER_STRATEGY = {
12
14
  stability: "relationship-exact",
13
15
  };
14
16
  const limitKey = (limit) => canonicalJson(limit, "JavaScript Application Graph");
15
- const normalizeLimits = (limits) => [...new Map(limits.map((limit) => [limitKey(limit), limit])).values()].sort((left, right) => compareCodePoints(limitKey(left), limitKey(right)));
17
+ const normalizeLimits = (limits) => [...new Map(limits.map((limit) => [limitKey(limit), limit])).values()].sort((left, right) => compareUnicodeCodePoints(limitKey(left), limitKey(right)));
16
18
  const normalizeEvidence = (evidence) => ({
17
19
  ...evidence,
18
20
  coverage: {
@@ -29,13 +31,13 @@ const nodeSemantic = (node) => ({
29
31
  kind: node.kind,
30
32
  identity: node.identity,
31
33
  });
32
- const nodeId = (node) => `jag_node_${canonicalDigest(nodeSemantic(node), "JavaScript Application Graph")}`;
34
+ const nodeId = (node) => `jag_node_${digestCanonicalValue(nodeSemantic(node), "JavaScript Application Graph")}`;
33
35
  const observationSemantic = (nodeIdentifier, observation) => ({ node_id: nodeIdentifier, ...observation });
34
- const observationId = (nodeIdentifier, observation) => `jag_observation_${canonicalDigest(observationSemantic(nodeIdentifier, observation))}`;
35
- const edgeId = (edge) => `jag_edge_${canonicalDigest(edge, "JavaScript Application Graph")}`;
36
+ const observationId = (nodeIdentifier, observation) => `jag_observation_${digestCanonicalValue(observationSemantic(nodeIdentifier, observation))}`;
37
+ const edgeId = (edge) => `jag_edge_${digestCanonicalValue(edge, "JavaScript Application Graph")}`;
36
38
  const sortedUniqueIssue = (values, path, label, context) => {
37
39
  for (let index = 1; index < values.length; index += 1) {
38
- if (compareCodePoints(values[index - 1] ?? "", values[index] ?? "") < 0)
40
+ if (compareUnicodeCodePoints(values[index - 1] ?? "", values[index] ?? "") < 0)
39
41
  continue;
40
42
  context.addIssue({
41
43
  code: "custom",
@@ -213,7 +215,7 @@ const checkGraphInvariants = (graph, context) => {
213
215
  }
214
216
  const { graph_id: identifier, ...semantic } = graph;
215
217
  if (identifier !==
216
- `jag_${canonicalDigest(semantic, "JavaScript Application Graph")}`)
218
+ `jag_${digestCanonicalValue(semantic, "JavaScript Application Graph")}`)
217
219
  context.addIssue({
218
220
  code: "custom",
219
221
  message: "Graph identifier does not match its semantic content",
@@ -239,7 +241,7 @@ export const createJavaScriptApplicationNode = (input) => {
239
241
  observation_id: observationId(identifier, semantic),
240
242
  });
241
243
  })
242
- .sort((left, right) => compareCodePoints(left.observation_id, right.observation_id));
244
+ .sort((left, right) => compareUnicodeCodePoints(left.observation_id, right.observation_id));
243
245
  return applicationNodeSchema.parse({
244
246
  node_id: identifier,
245
247
  kind: parsed.kind,
@@ -266,8 +268,8 @@ export const createJavaScriptApplicationGraph = (input) => {
266
268
  const semantic = {
267
269
  ...parsed,
268
270
  root_node_ids: uniqueSorted(parsed.root_node_ids),
269
- nodes: [...parsed.nodes].sort((left, right) => compareCodePoints(left.node_id, right.node_id)),
270
- edges: [...parsed.edges].sort((left, right) => compareCodePoints(left.edge_id, right.edge_id)),
271
+ nodes: [...parsed.nodes].sort((left, right) => compareUnicodeCodePoints(left.node_id, right.node_id)),
272
+ edges: [...parsed.edges].sort((left, right) => compareUnicodeCodePoints(left.edge_id, right.edge_id)),
271
273
  coverage: {
272
274
  ...parsed.coverage,
273
275
  limits: normalizeLimits(parsed.coverage.limits),
@@ -276,7 +278,7 @@ export const createJavaScriptApplicationGraph = (input) => {
276
278
  };
277
279
  return javascriptApplicationGraphSchema.parse({
278
280
  ...semantic,
279
- graph_id: `jag_${canonicalDigest(semantic, "JavaScript Application Graph")}`,
281
+ graph_id: `jag_${digestCanonicalValue(semantic, "JavaScript Application Graph")}`,
280
282
  });
281
283
  };
282
284
  const validatedImmutableApplicationGraphs = new WeakSet();
@@ -294,6 +296,6 @@ export const isValidatedImmutableJavaScriptApplicationGraph = (value) => typeof
294
296
  /** Parse a stored graph and reject stale IDs. */
295
297
  export const parseJavaScriptApplicationGraph = (input) => javascriptApplicationGraphSchema.parse(input);
296
298
  /** Compute the byte-stable SHA-256 commitment of a verified graph. */
297
- export const computeJavaScriptApplicationGraphSha256 = (input) => canonicalDigest(parseJavaScriptApplicationGraph(input), "JavaScript Application Graph");
299
+ export const computeJavaScriptApplicationGraphSha256 = (input) => digestCanonicalValue(parseJavaScriptApplicationGraph(input), "JavaScript Application Graph");
298
300
  /** Serialize a verified graph as RFC 8785 canonical JSON. */
299
301
  export const serializeJavaScriptApplicationGraph = (input) => canonicalJson(parseJavaScriptApplicationGraph(input), "JavaScript Application Graph");
@@ -1,7 +1,7 @@
1
- import { canonicalDigest } from "../comparisonSemantics.js";
1
+ import { digestCanonicalValue } from "../canonicalDigest.js";
2
2
  import { uniqueSorted } from "../canonicalOrdering.js";
3
3
  import { buildJavaScriptApplicationChangeGraph } from "./javascriptApplicationChangeGraph.js";
4
- import { applicationVersionComparisonResultSchema, } from "./javascriptApplicationVersionComparisonSchemas.js";
4
+ import { ownedApplicationVersionComparisonResultSchema, } from "./javascriptApplicationVersionComparisonSchemas.js";
5
5
  import { classifyJavaScriptApplicationVersions } from "./javascriptApplicationVersionItems.js";
6
6
  import { matchJavaScriptApplicationVersions } from "./javascriptApplicationVersionKeys.js";
7
7
  /** Compare application entities with ordered unique-only identity tiers. */
@@ -47,9 +47,9 @@ export const compareJavaScriptApplicationVersions = (input) => {
47
47
  evidence_links: evidenceLinks,
48
48
  limitations: comparisonLimitations(input),
49
49
  };
50
- return applicationVersionComparisonResultSchema.parse({
50
+ return ownedApplicationVersionComparisonResultSchema.parse({
51
51
  ...semantic,
52
- comparison_id: `javc_${canonicalDigest(semantic, "Application version comparison")}`,
52
+ comparison_id: `javc_${digestCanonicalValue(semantic, "Application version comparison")}`,
53
53
  });
54
54
  };
55
55
  const summary = (items) => ({
@@ -1,21 +1,14 @@
1
1
  import { z } from "zod";
2
2
  import { emptyArraySchema } from "../emptyArraySchema.js";
3
3
  import { evidenceSchema } from "../evidence.js";
4
- import { javascriptApplicationGraphSchema } from "./javascriptApplicationGraph.js";
4
+ import { isValidatedImmutableJavaScriptApplicationGraph, javascriptApplicationGraphSchema, } from "./javascriptApplicationGraph.js";
5
5
  import { JAVASCRIPT_APPLICATION_NODE_KINDS } from "./javascriptApplicationGraphSchemas.js";
6
6
  import { prefixedDigestSchema } from "../digests.js";
7
7
  const evidenceIdSchema = prefixedDigestSchema("ev");
8
8
  const nodeIdSchema = prefixedDigestSchema("jag_node");
9
9
  const textSchema = z.string().min(1);
10
- /** Two authenticated application versions and their native observations. */
11
- export const compareApplicationVersionsInputSchema = z
12
- .strictObject({
13
- left: evidenceSchema,
14
- right: evidenceSchema,
15
- left_native_observations: z.array(evidenceSchema).default([]),
16
- right_native_observations: z.array(evidenceSchema).default([]),
17
- })
18
- .superRefine((input, context) => {
10
+ /** Check paired version identities and per-side native identity uniqueness. */
11
+ const validateApplicationVersionIdentities = (input, context) => {
19
12
  if (input.left.evidence_id === input.right.evidence_id)
20
13
  context.addIssue({
21
14
  code: "custom",
@@ -34,8 +27,26 @@ export const compareApplicationVersionsInputSchema = z
34
27
  message: "Native observations must be unique on each side",
35
28
  });
36
29
  }
37
- });
38
- const emptyCandidateNodesSchema = emptyArraySchema;
30
+ };
31
+ const evidenceIdentitySchema = z.object({ evidence_id: evidenceIdSchema });
32
+ /** Validate paired version identities without capturing whole analysis graphs. */
33
+ export const applicationVersionIdentitiesSchema = z
34
+ .object({
35
+ left: evidenceIdentitySchema,
36
+ right: evidenceIdentitySchema,
37
+ left_native_observations: z.array(evidenceIdentitySchema),
38
+ right_native_observations: z.array(evidenceIdentitySchema),
39
+ })
40
+ .superRefine(validateApplicationVersionIdentities);
41
+ /** Two authenticated application versions and their native observations. */
42
+ export const compareApplicationVersionsInputSchema = z
43
+ .strictObject({
44
+ left: evidenceSchema,
45
+ right: evidenceSchema,
46
+ left_native_observations: z.array(evidenceSchema).default([]),
47
+ right_native_observations: z.array(evidenceSchema).default([]),
48
+ })
49
+ .superRefine(validateApplicationVersionIdentities);
39
50
  const candidateNodesSchema = z.tuple([nodeIdSchema]).rest(nodeIdSchema);
40
51
  const exactMatchSchema = z.strictObject({
41
52
  status: z.literal("matched"),
@@ -45,22 +56,22 @@ const exactMatchSchema = z.strictObject({
45
56
  "exact-module-source-digest",
46
57
  ]),
47
58
  confidence: z.literal("exact"),
48
- candidate_left_node_ids: emptyCandidateNodesSchema,
49
- candidate_right_node_ids: emptyCandidateNodesSchema,
59
+ candidate_left_node_ids: emptyArraySchema,
60
+ candidate_right_node_ids: emptyArraySchema,
50
61
  });
51
62
  const sourceMapMatchSchema = z.strictObject({
52
63
  status: z.literal("matched"),
53
64
  basis: z.literal("source-map-identity"),
54
65
  confidence: z.literal("high"),
55
- candidate_left_node_ids: emptyCandidateNodesSchema,
56
- candidate_right_node_ids: emptyCandidateNodesSchema,
66
+ candidate_left_node_ids: emptyArraySchema,
67
+ candidate_right_node_ids: emptyArraySchema,
57
68
  });
58
69
  const inferredMatchSchema = z.strictObject({
59
70
  status: z.literal("matched"),
60
71
  basis: z.enum(["structural-fingerprint", "semantic-key"]),
61
72
  confidence: z.literal("medium"),
62
- candidate_left_node_ids: emptyCandidateNodesSchema,
63
- candidate_right_node_ids: emptyCandidateNodesSchema,
73
+ candidate_left_node_ids: emptyArraySchema,
74
+ candidate_right_node_ids: emptyArraySchema,
64
75
  });
65
76
  const matchedItemMatchSchema = z.union([
66
77
  exactMatchSchema,
@@ -71,14 +82,14 @@ const unmatchedItemMatchSchema = z.strictObject({
71
82
  status: z.literal("unmatched"),
72
83
  basis: z.literal("none"),
73
84
  confidence: z.literal("unknown"),
74
- candidate_left_node_ids: emptyCandidateNodesSchema,
75
- candidate_right_node_ids: emptyCandidateNodesSchema,
85
+ candidate_left_node_ids: emptyArraySchema,
86
+ candidate_right_node_ids: emptyArraySchema,
76
87
  });
77
88
  const leftAmbiguousMatchSchema = z.strictObject({
78
89
  status: z.literal("ambiguous"),
79
90
  basis: z.literal("none"),
80
91
  confidence: z.literal("unknown"),
81
- candidate_left_node_ids: emptyCandidateNodesSchema,
92
+ candidate_left_node_ids: emptyArraySchema,
82
93
  candidate_right_node_ids: candidateNodesSchema,
83
94
  });
84
95
  const rightAmbiguousMatchSchema = z.strictObject({
@@ -86,7 +97,7 @@ const rightAmbiguousMatchSchema = z.strictObject({
86
97
  basis: z.literal("none"),
87
98
  confidence: z.literal("unknown"),
88
99
  candidate_left_node_ids: candidateNodesSchema,
89
- candidate_right_node_ids: emptyCandidateNodesSchema,
100
+ candidate_right_node_ids: emptyArraySchema,
90
101
  });
91
102
  const comparisonItemContextShape = {
92
103
  item_id: prefixedDigestSchema("javc_item"),
@@ -194,3 +205,7 @@ export const applicationVersionComparisonResultSchema = z
194
205
  message: "Comparison coverage must match source graph completeness",
195
206
  });
196
207
  });
208
+ /** Reuse the exact owned change graph while validating the rest of the result. */
209
+ export const ownedApplicationVersionComparisonResultSchema = applicationVersionComparisonResultSchema.safeExtend({
210
+ graph: z.custom(isValidatedImmutableJavaScriptApplicationGraph),
211
+ });
@@ -1,5 +1,6 @@
1
- import { absenceClaimable, canonicalDigest, canonicalJson, } from "../comparisonSemantics.js";
2
- import { compareCodePoints } from "../canonicalOrdering.js";
1
+ import { absenceClaimable, canonicalJson } from "../comparisonSemantics.js";
2
+ import { digestCanonicalValue } from "../canonicalDigest.js";
3
+ import { compareUnicodeCodePoints } from "../unicodeCodePointOrder.js";
3
4
  /** Classify matched, unmatched, and ambiguous nodes without inventing absence. */
4
5
  export const classifyJavaScriptApplicationVersions = (matching, context) => {
5
6
  const pairByLeft = new Map(matching.pairs.map(({ left, right }) => [
@@ -10,7 +11,13 @@ export const classifyJavaScriptApplicationVersions = (matching, context) => {
10
11
  right.node_id,
11
12
  `pair:${left.node_id}:${right.node_id}`,
12
13
  ]));
13
- const fullContext = { ...context, pairByLeft, pairByRight };
14
+ const fullContext = {
15
+ ...context,
16
+ pairByLeft,
17
+ pairByRight,
18
+ leftRelationships: indexRelationships(context.leftGraph),
19
+ rightRelationships: indexRelationships(context.rightGraph),
20
+ };
14
21
  const leftItems = matching.unmatchedLeft.map((node) => {
15
22
  const candidates = matching.candidatesForLeft.get(node.node_id) ?? [];
16
23
  return unmatchedItem({
@@ -30,7 +37,7 @@ export const classifyJavaScriptApplicationVersions = (matching, context) => {
30
37
  ...matching.pairs.map((pair) => matchedItem(pair, fullContext)),
31
38
  ...leftItems,
32
39
  ...rightItems,
33
- ].sort((left, right) => compareCodePoints(left.item_id, right.item_id)),
40
+ ].sort((left, right) => compareUnicodeCodePoints(left.item_id, right.item_id)),
34
41
  };
35
42
  };
36
43
  const matchedItem = (pair, context) => {
@@ -201,42 +208,46 @@ const contentIdentity = (node) => {
201
208
  };
202
209
  const locations = (node) => node.observations
203
210
  .map(({ evidence }) => evidence.location.available ? evidence.location.value : evidence.location)
204
- .sort((left, right) => compareCodePoints(canonicalJson(left), canonicalJson(right)));
211
+ .sort((left, right) => compareUnicodeCodePoints(canonicalJson(left), canonicalJson(right)));
205
212
  const properties = (node) => node.observations
206
213
  .map(({ label, properties: values, source_map_reference }) => ({
207
214
  label,
208
215
  properties: values,
209
216
  source_map_reference,
210
217
  }))
211
- .sort((left, right) => compareCodePoints(canonicalJson(left), canonicalJson(right)));
218
+ .sort((left, right) => compareUnicodeCodePoints(canonicalJson(left), canonicalJson(right)));
219
+ const indexRelationships = (graph) => {
220
+ const adjacency = new Map();
221
+ const add = (nodeId, relationship) => {
222
+ const existing = adjacency.get(nodeId);
223
+ if (existing === undefined)
224
+ adjacency.set(nodeId, [relationship]);
225
+ else
226
+ existing.push(relationship);
227
+ };
228
+ for (const edge of graph.edges) {
229
+ add(edge.source_node_id, {
230
+ direction: "out",
231
+ relation: edge.relation,
232
+ neighborId: edge.target_node_id,
233
+ });
234
+ if (edge.target_node_id !== edge.source_node_id)
235
+ add(edge.target_node_id, {
236
+ direction: "in",
237
+ relation: edge.relation,
238
+ neighborId: edge.source_node_id,
239
+ });
240
+ }
241
+ return {
242
+ nodeById: new Map(graph.nodes.map((value) => [value.node_id, value])),
243
+ adjacency,
244
+ };
245
+ };
212
246
  const relationshipSignature = (node, side, context) => {
213
- const graph = side === "left" ? context.leftGraph : context.rightGraph;
247
+ const { nodeById, adjacency } = side === "left" ? context.leftRelationships : context.rightRelationships;
214
248
  const paired = side === "left" ? context.pairByLeft : context.pairByRight;
215
- const nodeById = new Map(graph.nodes.map((value) => [value.node_id, value]));
216
- const signatures = graph.edges.flatMap((edge) => {
217
- if (edge.source_node_id === node.node_id)
218
- return [
219
- edgeSignature({
220
- direction: "out",
221
- relation: edge.relation,
222
- neighborId: edge.target_node_id,
223
- paired,
224
- nodeById,
225
- }),
226
- ];
227
- if (edge.target_node_id === node.node_id)
228
- return [
229
- edgeSignature({
230
- direction: "in",
231
- relation: edge.relation,
232
- neighborId: edge.source_node_id,
233
- paired,
234
- nodeById,
235
- }),
236
- ];
237
- return [];
238
- });
239
- return canonicalJson(signatures.sort(compareCodePoints));
249
+ const signatures = (adjacency.get(node.node_id) ?? []).map((relationship) => edgeSignature({ ...relationship, paired, nodeById }));
250
+ return canonicalJson(signatures.sort(compareUnicodeCodePoints));
240
251
  };
241
252
  const edgeSignature = (context) => {
242
253
  const mapped = context.paired.get(context.neighborId);
@@ -250,7 +261,7 @@ const itemEvidenceLinks = (left, right, context) => [
250
261
  ...nativeLinks(left, context.leftNativeEvidence),
251
262
  ...nativeLinks(right, context.rightNativeEvidence),
252
263
  ]),
253
- ].sort(compareCodePoints);
264
+ ].sort(compareUnicodeCodePoints);
254
265
  const nativeLinks = (node, evidence) => {
255
266
  const digest = node === undefined
256
267
  ? null
@@ -283,7 +294,7 @@ const pairLimitations = (pair, status) => [
283
294
  ];
284
295
  const itemWithId = (semantic) => ({
285
296
  ...semantic,
286
- item_id: `javc_item_${canonicalDigest(semantic, "Application version item")}`,
297
+ item_id: `javc_item_${digestCanonicalValue(semantic, "Application version item")}`,
287
298
  });
288
299
  const stringProperty = (node, key) => {
289
300
  const values = [
@@ -1,5 +1,5 @@
1
1
  import { canonicalJson } from "../comparisonSemantics.js";
2
- import { compareCodePoints } from "../canonicalOrdering.js";
2
+ import { compareUnicodeCodePoints, compositeKey, } from "../unicodeCodePointOrder.js";
3
3
  const matchTiers = () => [
4
4
  {
5
5
  match: { basis: "exact-content-digest", confidence: "exact" },
@@ -40,7 +40,7 @@ export const matchJavaScriptApplicationVersions = (leftNodes, rightNodes) => {
40
40
  const leftIds = new Set(remainingLeft.map(({ node_id: id }) => id));
41
41
  const rightIds = new Set(remainingRight.map(({ node_id: id }) => id));
42
42
  return {
43
- pairs: pairs.sort((a, b) => compareCodePoints(`${a.left.node_id}\0${a.right.node_id}`, `${b.left.node_id}\0${b.right.node_id}`)),
43
+ pairs: pairs.sort((a, b) => compareUnicodeCodePoints(`${a.left.node_id}\0${a.right.node_id}`, `${b.left.node_id}\0${b.right.node_id}`)),
44
44
  unmatchedLeft: remainingLeft,
45
45
  unmatchedRight: remainingRight,
46
46
  candidatesForLeft: filteredCandidates(leftCandidates, rightIds),
@@ -50,7 +50,7 @@ export const matchJavaScriptApplicationVersions = (leftNodes, rightNodes) => {
50
50
  const applyTier = (context) => {
51
51
  const leftByKey = nodesByKey(context.left.values(), context.tier.key);
52
52
  const rightByKey = nodesByKey(context.right.values(), context.tier.key);
53
- for (const key of [...leftByKey.keys()].sort(compareCodePoints)) {
53
+ for (const key of [...leftByKey.keys()].sort(compareUnicodeCodePoints)) {
54
54
  const leftGroup = leftByKey.get(key) ?? [];
55
55
  const rightGroup = rightByKey.get(key) ?? [];
56
56
  if (rightGroup.length === 0)
@@ -98,7 +98,7 @@ const recordCandidates = (left, right, leftCandidates, rightCandidates) => {
98
98
  const filteredCandidates = (candidates, retained) => new Map([...candidates.entries()].flatMap(([nodeId, values]) => {
99
99
  const filtered = [...values]
100
100
  .filter((value) => retained.has(value))
101
- .sort(compareCodePoints);
101
+ .sort(compareUnicodeCodePoints);
102
102
  return filtered.length === 0 ? [] : [[nodeId, filtered]];
103
103
  }));
104
104
  const nodeIdentityKey = (node) => `node\0${node.kind}\0${node.node_id}`;
@@ -178,7 +178,7 @@ const uniqueStringProperty = (node, name) => {
178
178
  };
179
179
  const joined = (...values) => {
180
180
  const strings = values.map(nonEmptyString);
181
- return strings.some((value) => value === null) ? null : strings.join("\0");
181
+ return strings.some((value) => value === null) ? null : compositeKey(strings);
182
182
  };
183
183
  const nonEmptyString = (value) => typeof value === "string" && value !== "" ? value : null;
184
184
  /** A literal value such as `ipcMain.handle("")` keeps its exact empty text. */
@@ -186,6 +186,6 @@ const exactString = (value) => typeof value === "string" ? value : null;
186
186
  const stringList = (value) => Array.isArray(value)
187
187
  ? value
188
188
  .filter((item) => typeof item === "string")
189
- .sort(compareCodePoints)
189
+ .sort(compareUnicodeCodePoints)
190
190
  : [];
191
- const sortedNodes = (nodes) => [...nodes].sort((left, right) => compareCodePoints(left.node_id, right.node_id));
191
+ const sortedNodes = (nodes) => [...nodes].sort((left, right) => compareUnicodeCodePoints(left.node_id, right.node_id));
@@ -1,7 +1,7 @@
1
1
  import { createHash } from "node:crypto";
2
2
  import * as t from "@babel/types";
3
3
  import { traverseJavaScriptAst } from "./javascriptSemanticTraversal.js";
4
- import { compareCodePoints } from "../canonicalOrdering.js";
4
+ import { compareUnicodeCodePoints } from "../unicodeCodePointOrder.js";
5
5
  import { propertyName } from "./javascriptAstValues.js";
6
6
  import { stringValue } from "./javascriptStaticAnalysisHelpers.js";
7
7
  /** Derive a rename-resistant syntax fingerprint without code execution. */
@@ -28,7 +28,7 @@ export const collectJavaScriptExports = (node) => {
28
28
  },
29
29
  });
30
30
  return {
31
- values: [...exports].sort(compareCodePoints),
31
+ values: [...exports].sort(compareUnicodeCodePoints),
32
32
  };
33
33
  };
34
34
  const semanticTokens = (node) => {
@@ -1,6 +1,27 @@
1
1
  import * as t from "@babel/types";
2
+ /**
3
+ * Remove wrappers that affect TypeScript or Flow checking but not runtime
4
+ * expression identity. The returned depth lets bounded evaluators account for
5
+ * syntax that normalization would otherwise skip.
6
+ */
7
+ export const unwrapJavaScriptExpression = (node) => {
8
+ let current = node;
9
+ let depth = 0;
10
+ while (t.isParenthesizedExpression(current) ||
11
+ t.isTSAsExpression(current) ||
12
+ t.isTSTypeAssertion(current) ||
13
+ t.isTSNonNullExpression(current) ||
14
+ t.isTSSatisfiesExpression(current) ||
15
+ t.isTSInstantiationExpression(current) ||
16
+ t.isTypeCastExpression(current)) {
17
+ current = current.expression;
18
+ depth += 1;
19
+ }
20
+ return { node: current, depth };
21
+ };
2
22
  /** Read one syntax-level primitive only when its value is exact. */
3
23
  export const readExactJavaScriptLiteral = (node) => {
24
+ node = unwrapJavaScriptExpression(node).node;
4
25
  if (t.isStringLiteral(node))
5
26
  return { found: true, value: node.value };
6
27
  if (t.isNumericLiteral(node) && Number.isFinite(node.value))
@@ -31,6 +52,7 @@ export const propertyName = (node) => {
31
52
  export const semanticStaticPropertyName = (property, computed) => semanticStaticPropertyKey(property, computed) ?? "";
32
53
  /** Read an exact property key, preserving the legal empty-string key. */
33
54
  export const semanticStaticPropertyKey = (property, computed) => {
55
+ property = unwrapJavaScriptExpression(property).node;
34
56
  if (t.isStringLiteral(property) || t.isNumericLiteral(property))
35
57
  return String(property.value);
36
58
  return !computed && t.isIdentifier(property) ? property.name : null;