rea-agents 2.0.0 → 2.2.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 (273) hide show
  1. package/README.md +103 -38
  2. package/bridge/ghidra/ReaGhidraBridge.java +96 -11
  3. package/dist/application/AndroidApplicationService.js +17 -0
  4. package/dist/application/AppleApplicationService.js +17 -0
  5. package/dist/application/ArtifactExtraction.js +1 -1
  6. package/dist/application/ArtifactInventory/classify.js +42 -0
  7. package/dist/application/ArtifactInventory/hash.js +43 -0
  8. package/dist/application/ArtifactInventory/reader.js +41 -0
  9. package/dist/application/ArtifactInventory/scanCanonical.js +155 -0
  10. package/dist/application/ArtifactInventory/scanReader.js +124 -0
  11. package/dist/application/ArtifactInventory/types.js +10 -0
  12. package/dist/application/ArtifactInventory.js +9 -351
  13. package/dist/application/AuthorizedArtifactInventory.js +2 -2
  14. package/dist/application/BinarySession.js +47 -270
  15. package/dist/application/BinarySessionExecution.js +28 -0
  16. package/dist/application/BinarySessionOpen.js +39 -0
  17. package/dist/application/BinarySessionRecords.js +149 -0
  18. package/dist/application/BinarySessionStatus.js +75 -0
  19. package/dist/application/CapabilityInventory.js +24 -2
  20. package/dist/application/ClientRegistrationStatus.js +11 -4
  21. package/dist/application/CrossVersionInventory.js +8 -2
  22. package/dist/application/CrossVersionInvestigation.js +1 -23
  23. package/dist/application/CrossVersionInvestigationCollections.js +23 -0
  24. package/dist/application/DirectAnalysis.js +47 -44
  25. package/dist/application/Doctor.js +156 -238
  26. package/dist/application/DoctorDiagnostics.js +180 -0
  27. package/dist/application/ElectronBoundaryAnalysis.js +23 -7
  28. package/dist/application/ElectronBoundaryGraphWindows.js +32 -8
  29. package/dist/application/EnhancedToolPagination.js +22 -0
  30. package/dist/application/EnhancedToolTypes.js +4 -0
  31. package/dist/application/EnhancedTools.js +20 -37
  32. package/dist/application/InstrumentedJavaScriptReplayHost.js +36 -0
  33. package/dist/application/InventoryProjectionEvidence.js +41 -0
  34. package/dist/application/InvestigationProviders.js +12 -0
  35. package/dist/application/InvestigationWorkspaceStore.js +24 -10
  36. package/dist/application/JavaScriptArtifactAnalysis.js +45 -6
  37. package/dist/application/JavaScriptArtifactFiles.js +6 -2
  38. package/dist/application/JavaScriptArtifactGraphBuilder.js +23 -1
  39. package/dist/application/JavaScriptArtifactGraphBundlers.js +225 -0
  40. package/dist/application/JavaScriptArtifactGraphContext.js +37 -36
  41. package/dist/application/JavaScriptArtifactGraphDocuments.js +27 -4
  42. package/dist/application/JavaScriptArtifactGraphFindings.js +54 -8
  43. package/dist/application/JavaScriptArtifactGraphStructure.js +29 -101
  44. package/dist/application/JavaScriptArtifactPathResolution.js +269 -0
  45. package/dist/application/JavaScriptArtifactReconstruction.js +1 -1
  46. package/dist/application/JavaScriptJsonModules.js +39 -0
  47. package/dist/application/JavaScriptModuleRelationships.js +262 -0
  48. package/dist/application/JavaScriptReplayPermission.js +16 -0
  49. package/dist/application/JavaScriptReplayService.js +182 -156
  50. package/dist/application/LinuxHopper.js +10 -0
  51. package/dist/application/MacHopper.js +22 -11
  52. package/dist/application/NodeRuntimeCharacterizationService.js +196 -0
  53. package/dist/application/PermissionAuthority.js +106 -63
  54. package/dist/application/ProcessCaptureCapability.js +1 -1
  55. package/dist/application/ProcessCapturePermission.js +13 -0
  56. package/dist/application/ProcessCli.js +2 -12
  57. package/dist/application/ProcessHarness.js +1 -1
  58. package/dist/application/ProcessPairedExperiment.js +72 -0
  59. package/dist/application/ProjectPermissionStore.js +48 -9
  60. package/dist/application/RealHopperAssertions.js +76 -0
  61. package/dist/application/ReconstructionCoverageService.js +69 -0
  62. package/dist/application/ReconstructionCoverageWorkspaceStore.js +31 -0
  63. package/dist/application/RuntimeExecutableDiagnostics.js +172 -0
  64. package/dist/application/Setup.js +148 -260
  65. package/dist/application/SetupClientConfiguration.js +224 -0
  66. package/dist/application/SetupClients.js +24 -2
  67. package/dist/application/SetupPlan.js +124 -12
  68. package/dist/application/SetupSkill.js +54 -36
  69. package/dist/application/SupportedClients.js +1 -0
  70. package/dist/application/Uninstall.js +12 -3
  71. package/dist/application/Upgrade.js +16 -1
  72. package/dist/application/WindowsCapabilities.js +86 -0
  73. package/dist/artifacts/AsarArtifactReader.js +11 -0
  74. package/dist/browser/BrowserProcessStartup.js +88 -0
  75. package/dist/browser/CdpCaptureDocuments.js +12 -8
  76. package/dist/browser/CdpCaptureEventBodyShapes.js +75 -0
  77. package/dist/browser/CdpCaptureEventHandlers.js +336 -0
  78. package/dist/browser/CdpCaptureEventHelpers.js +71 -0
  79. package/dist/browser/CdpCaptureEventState.js +1 -0
  80. package/dist/browser/CdpCaptureEventTypes.js +1 -0
  81. package/dist/browser/CdpCaptureEvents.js +29 -496
  82. package/dist/browser/CdpObservationSession.js +51 -8
  83. package/dist/browser/CdpPageCapture.js +12 -133
  84. package/dist/browser/CdpPageCaptureScripts.js +97 -0
  85. package/dist/browser/CdpPageCaptureWorkers.js +46 -0
  86. package/dist/browser/CdpWebMcpDiscovery.js +38 -14
  87. package/dist/browser/PngVisualDiff.js +9 -2
  88. package/dist/catalogIdentity.js +4 -0
  89. package/dist/cli/artifactCommands.js +82 -0
  90. package/dist/cli/coreAnalysisCommands.js +232 -0
  91. package/dist/cli/managedCommands.js +397 -0
  92. package/dist/cli/managedProjectGraphCommand.js +24 -0
  93. package/dist/cli/options.js +9 -0
  94. package/dist/cli/setupCommands.js +113 -0
  95. package/dist/cli/types.js +1 -0
  96. package/dist/cli/utilityCommands.js +122 -0
  97. package/dist/cli.js +10 -768
  98. package/dist/cliApplicationCommands.js +118 -4
  99. package/dist/cliBrowserAdvancedCommands.js +73 -16
  100. package/dist/cliBrowserCommands.js +39 -115
  101. package/dist/cliCommandNames.js +4 -0
  102. package/dist/cliElectronCommands.js +33 -62
  103. package/dist/cliEvidenceCommands.js +13 -2
  104. package/dist/cliInvestigationCommands.js +53 -10
  105. package/dist/cliObservationOptions.js +137 -0
  106. package/dist/cliPolicyCommands.js +80 -46
  107. package/dist/cliSetup.js +306 -0
  108. package/dist/config/environment.js +107 -0
  109. package/dist/config/parseConfig.js +228 -0
  110. package/dist/config/parsers.js +68 -0
  111. package/dist/config/permissions.js +30 -0
  112. package/dist/config/types.js +1 -0
  113. package/dist/config.js +1 -375
  114. package/dist/contracts/applicationToolContracts.js +134 -0
  115. package/dist/contracts/electronToolContracts.js +51 -3
  116. package/dist/contracts/managedToolContracts.js +8 -3
  117. package/dist/contracts/managedWorkflowToolContracts.js +3 -3
  118. package/dist/contracts/providerSelection.js +2 -0
  119. package/dist/contracts/sessionStatusContract.js +26 -0
  120. package/dist/contracts/toolContractTypes.js +12 -1
  121. package/dist/contracts/toolContracts.js +5 -12
  122. package/dist/contracts/toolEffects.js +14 -0
  123. package/dist/contracts/toolOutputSchemaGroups.js +274 -0
  124. package/dist/contracts/toolOutputSchemaPrimitives.js +328 -0
  125. package/dist/contracts/toolOutputSchemas.js +2 -550
  126. package/dist/domain/analysisErrorPresentation.js +234 -0
  127. package/dist/domain/analysisErrorProjection.js +284 -0
  128. package/dist/domain/androidApplication.js +206 -0
  129. package/dist/domain/appleApplication.js +221 -0
  130. package/dist/domain/artifactComparison.js +34 -15
  131. package/dist/domain/binaryTarget.js +87 -37
  132. package/dist/domain/boundedCartesianProjection.js +15 -0
  133. package/dist/domain/browserObservation.js +1 -285
  134. package/dist/domain/browserObservationSchemas.js +286 -0
  135. package/dist/domain/electronStaticAnalysisBrowser.js +14 -2
  136. package/dist/domain/errors.js +4 -486
  137. package/dist/domain/functionComparison.js +4 -165
  138. package/dist/domain/functionComparisonDimensions.js +164 -0
  139. package/dist/domain/javascriptApplicationVersionItems.js +18 -6
  140. package/dist/domain/javascriptApplicationVersionKeys.js +8 -8
  141. package/dist/domain/javascriptExportInstrumentation.js +97 -0
  142. package/dist/domain/javascriptFeatureTraversal.js +19 -7
  143. package/dist/domain/javascriptRuntimeStaticCandidates.js +3 -1
  144. package/dist/domain/javascriptSemanticAnalysis.js +386 -0
  145. package/dist/domain/javascriptSemanticIr.js +30 -0
  146. package/dist/domain/javascriptSemanticProjection.js +366 -0
  147. package/dist/domain/javascriptSemanticState.js +40 -0
  148. package/dist/domain/javascriptSemanticTraversal.js +22 -0
  149. package/dist/domain/javascriptSemanticValues.js +352 -0
  150. package/dist/domain/javascriptStaticAnalysis.js +5 -221
  151. package/dist/domain/javascriptStaticAnalysisBundler.js +209 -0
  152. package/dist/domain/javascriptStaticAnalysisCalls.js +180 -0
  153. package/dist/domain/javascriptStaticAnalysisHelpers.js +71 -2
  154. package/dist/domain/knownPageCoverage.js +21 -0
  155. package/dist/domain/managedApplicationGraph.js +14 -364
  156. package/dist/domain/managedApplicationGraphCoverage.js +170 -0
  157. package/dist/domain/managedApplicationGraphNodeCoverage.js +6 -0
  158. package/dist/domain/managedApplicationGraphNodes.js +336 -0
  159. package/dist/domain/managedArtifact.js +16 -8
  160. package/dist/domain/managedMemberComparison.js +37 -391
  161. package/dist/domain/managedMemberComparisonCoverage.js +72 -0
  162. package/dist/domain/managedMemberComparisonMatch.js +356 -0
  163. package/dist/domain/managedNativeVerification.js +27 -389
  164. package/dist/domain/managedNativeVerificationMatch.js +272 -0
  165. package/dist/domain/managedNativeVerificationSchemas.js +141 -0
  166. package/dist/domain/managedReconstruction.js +82 -69
  167. package/dist/domain/managedRuntimeCorrelation.js +12 -3
  168. package/dist/domain/nodeRuntimeCharacterization.js +66 -0
  169. package/dist/domain/permissionPolicy.js +2 -0
  170. package/dist/domain/processComparison.js +19 -0
  171. package/dist/domain/processPairedExperiment.js +128 -0
  172. package/dist/domain/reconstructionCoverage.js +387 -0
  173. package/dist/domain/reconstructionCoverageEvaluation.js +212 -0
  174. package/dist/domain/reconstructionVerificationSchemas.js +8 -0
  175. package/dist/domain/replayMachine.js +316 -0
  176. package/dist/domain/replayMachineRuntime.js +215 -0
  177. package/dist/domain/runtimeCharacterization.js +85 -0
  178. package/dist/domain/runtimeIdentification.js +210 -0
  179. package/dist/domain/webBundleAnalyzer.js +3 -409
  180. package/dist/domain/webBundleAnalyzerAst.js +77 -0
  181. package/dist/domain/webBundleAnalyzerInspection.js +307 -0
  182. package/dist/domain/webBundleAnalyzerResult.js +120 -0
  183. package/dist/dotnet/ManagedArtifactInspector.js +50 -29
  184. package/dist/dotnet/ManagedMemberInspector.js +51 -785
  185. package/dist/dotnet/ManagedMemberInspectorCore.js +297 -0
  186. package/dist/dotnet/ManagedMemberInstructionDecoder.js +427 -0
  187. package/dist/dotnet/ManagedMemberRows.js +120 -0
  188. package/dist/dotnet/ManagedMetadataInventory.js +42 -306
  189. package/dist/dotnet/ManagedMetadataInventoryRows.js +292 -0
  190. package/dist/dotnet/ManagedMetadataLayout.js +48 -111
  191. package/dist/dotnet/ManagedMetadataRowSizes.js +54 -0
  192. package/dist/dotnet/ManagedMethodBodyReader.js +143 -0
  193. package/dist/dotnet/ManagedNativeBoundaryHelpers.js +311 -0
  194. package/dist/dotnet/ManagedNativeBoundaryInspector.js +102 -350
  195. package/dist/dotnet/ManagedPeReader.js +59 -28
  196. package/dist/evaluation/CodexAgentEval.js +132 -0
  197. package/dist/generatedPackageMetadata.js +2 -2
  198. package/dist/ghidra/GhidraClient.js +76 -91
  199. package/dist/ghidra/GhidraClientStartup.js +29 -0
  200. package/dist/ghidra/GhidraClientWire.js +34 -0
  201. package/dist/ghidra/GhidraDefaults.js +1 -1
  202. package/dist/ghidra/GhidraDiagnostics.js +6 -1
  203. package/dist/ghidra/GhidraInstallation.js +20 -15
  204. package/dist/ghidra/GhidraLauncher.js +93 -29
  205. package/dist/ghidra/GhidraProvider.js +61 -161
  206. package/dist/ghidra/GhidraProviderCapabilities.js +173 -0
  207. package/dist/ghidra/GhidraSessionValues.js +2 -0
  208. package/dist/ghidra/GhidraSocketConnection.js +44 -7
  209. package/dist/ghidra/GhidraTargetSnapshot.js +30 -0
  210. package/dist/ghidra/GhidraTransport.js +71 -0
  211. package/dist/identity.js +4 -2
  212. package/dist/main/messages.js +5 -0
  213. package/dist/main/reload.js +49 -0
  214. package/dist/main/shutdown.js +25 -0
  215. package/dist/main/startup.js +14 -0
  216. package/dist/main/state.js +26 -0
  217. package/dist/main/transport.js +61 -0
  218. package/dist/main/types.js +1 -0
  219. package/dist/main.js +35 -146
  220. package/dist/process/PrivateRuntimeRoot.js +3 -2
  221. package/dist/process/ProcessOwnership.js +35 -0
  222. package/dist/process/ProviderProcess.js +2 -0
  223. package/dist/replay/JavaScriptReplayWorker.js +64 -50
  224. package/dist/replay/LinuxJavaScriptReplayRunner.js +173 -390
  225. package/dist/replay/LinuxJavaScriptReplaySandbox.js +140 -0
  226. package/dist/replay/ReplayOutcome.js +95 -0
  227. package/dist/replay/ReplayProcessLifecycle.js +71 -0
  228. package/dist/server/ProcessCaptureElicitation.js +157 -0
  229. package/dist/server/createServer.js +124 -56
  230. package/dist/server/javascriptApplicationResult.js +85 -0
  231. package/dist/server/registerApplicationTools/characterization.js +57 -0
  232. package/dist/server/registerApplicationTools/compareVersions.js +34 -0
  233. package/dist/server/registerApplicationTools/controlledReplay.js +38 -0
  234. package/dist/server/registerApplicationTools/coverage.js +84 -0
  235. package/dist/server/registerApplicationTools/helpers.js +42 -0
  236. package/dist/server/registerApplicationTools/traceFeature.js +26 -0
  237. package/dist/server/registerApplicationTools/types.js +1 -0
  238. package/dist/server/registerApplicationTools.js +10 -112
  239. package/dist/server/registerBrowserTools.js +59 -83
  240. package/dist/server/registerElectronTools.js +48 -49
  241. package/dist/server/registerEnhancedTools.js +34 -42
  242. package/dist/server/registerEvidenceResources.js +56 -0
  243. package/dist/server/registerInvestigationTools/helpers.js +74 -0
  244. package/dist/server/registerInvestigationTools/types.js +1 -0
  245. package/dist/server/registerInvestigationTools.js +83 -116
  246. package/dist/server/registerJavaScriptApplicationGraphResource.js +69 -0
  247. package/dist/server/registerManagedTools.js +18 -1
  248. package/dist/server/registerManagedWorkflowTools/compareManagedMembers.js +65 -0
  249. package/dist/server/registerManagedWorkflowTools/contract.js +8 -0
  250. package/dist/server/registerManagedWorkflowTools/evidence.js +43 -0
  251. package/dist/server/registerManagedWorkflowTools/importManagedReconstruction.js +39 -0
  252. package/dist/server/registerManagedWorkflowTools/planManagedRuntimeCorrelation.js +39 -0
  253. package/dist/server/registerManagedWorkflowTools/projectManagedApplicationGraph.js +52 -0
  254. package/dist/server/registerManagedWorkflowTools/types.js +1 -0
  255. package/dist/server/registerManagedWorkflowTools/verifyManagedNativeBoundaries.js +75 -0
  256. package/dist/server/registerManagedWorkflowTools.js +10 -274
  257. package/dist/server/registerOfficialTools.js +73 -59
  258. package/dist/server/registerSessionRecordTools.js +137 -0
  259. package/dist/server/registerSessionStatusTool.js +97 -26
  260. package/dist/server/registerSessionTools.js +60 -164
  261. package/dist/server/sessionAvailabilityPolicy.js +10 -0
  262. package/dist/server/toolRegistrationOptions.js +101 -3
  263. package/dist/server/toolResult.js +15 -4
  264. package/package.json +11 -11
  265. package/skills/reverse-engineer-anything/SKILL.md +76 -0
  266. package/skills/reverse-engineer-anything/references/controlled-replay.md +12 -0
  267. package/skills/reverse-engineer-anything/references/evidence-workflows.md +33 -0
  268. package/skills/reverse-engineer-anything/references/javascript-applications.md +25 -0
  269. package/skills/reverse-engineer-anything/references/native-and-artifacts.md +36 -0
  270. package/skills/reverse-engineer-anything/references/runtime-observation.md +24 -0
  271. package/scripts/prepare-node-pty.mjs +0 -35
  272. package/scripts/rebuild-native.mjs +0 -22
  273. package/skills/rea-analysis/SKILL.md +0 -222
@@ -1,5 +1,7 @@
1
- import { addArtifactContainsEdge, addAstContainsEdge, addUnavailableStaticParseScope, artifactLocalIdentity, createElectronRoleNode, javascriptAnalysisCoverage, linkElectronRoleToAsset, moduleLookupKey, resolveArtifactPath, } from "./JavaScriptArtifactGraphContext.js";
2
- import { artifactObservationEvidence, astObservationEvidence, completeReconstructionCoverage, staticInferenceEvidence, } from "./JavaScriptArtifactGraphEvidence.js";
1
+ import { addArtifactContainsEdge, addUnavailableStaticParseScope, artifactFileNodeKind, artifactLocalIdentity, createElectronRoleNode, linkElectronRoleToAsset, } from "./JavaScriptArtifactGraphContext.js";
2
+ import { artifactObservationEvidence, completeReconstructionCoverage, staticInferenceEvidence, } from "./JavaScriptArtifactGraphEvidence.js";
3
+ import { resolveArtifactPathByContext } from "./JavaScriptArtifactPathResolution.js";
4
+ export { addJavaScriptBundlerNodes } from "./JavaScriptArtifactGraphBundlers.js";
3
5
  /** Create the exact root artifact node from the inventory manifest. */
4
6
  export const createJavaScriptArtifactRootNode = (accumulator, snapshot) => {
5
7
  const root = snapshot.nodes.find(({ artifact_id: id }) => id === snapshot.manifest.root_artifact_id);
@@ -130,6 +132,14 @@ export const addJavaScriptArtifactFiles = (context) => {
130
132
  operation: "parse-package-json",
131
133
  limitation: packageValue.limitation ?? "Package metadata could not be parsed.",
132
134
  });
135
+ const jsonValue = context.analysis.json_modules.find(({ path }) => path === file.path);
136
+ if (jsonValue !== undefined && jsonValue.status !== "included")
137
+ addUnavailableStaticParseScope(context, {
138
+ file,
139
+ asset: target,
140
+ operation: "parse-json-module",
141
+ limitation: jsonValue.limitation ?? "JSON module content could not be parsed.",
142
+ });
133
143
  const sourceMap = context.analysis.source_maps.find(({ path }) => path === file.path);
134
144
  if (sourceMap !== undefined &&
135
145
  (sourceMap.status === "invalid" || sourceMap.status === "not-approved"))
@@ -209,95 +219,9 @@ export const addJavaScriptPackageNodes = (context) => {
209
219
  }
210
220
  return roots;
211
221
  };
212
- /** Project Webpack/Rspack chunk and factory literals recovered from AST. */
213
- export const addJavaScriptBundlerNodes = (context) => {
214
- for (const analyzed of context.analysis.files) {
215
- const { file, javascript } = analyzed;
216
- const asset = context.assetNodes.get(file.path);
217
- if (javascript === null || asset === undefined)
218
- continue;
219
- const coverage = javascriptAnalysisCoverage(javascript, context.input);
220
- for (const registration of javascript.bundler_registrations) {
221
- const chunkKey = `${registration.runtime}:${registration.chunk_keys.join(",")}`;
222
- const chunk = context.accumulator.addNode({
223
- kind: "javascript-chunk",
224
- identity: artifactLocalIdentity(file.sha256, "bundler-chunk", chunkKey),
225
- observations: [
226
- {
227
- label: chunkKey,
228
- properties: {
229
- path: file.path,
230
- bundler: registration.bundler,
231
- runtime: registration.runtime,
232
- chunk_keys: registration.chunk_keys,
233
- omitted_chunk_keys: registration.omitted_chunk_keys,
234
- unknown_chunk_keys: registration.unknown_chunk_keys,
235
- module_count: registration.modules.length,
236
- },
237
- evidence: astObservationEvidence({
238
- sha256: file.sha256,
239
- path: file.path,
240
- range: registration.location,
241
- operation: "extract-bundler-registration",
242
- coverage,
243
- limitations: javascript.limitations,
244
- }),
245
- },
246
- ],
247
- });
248
- addAstContainsEdge(context, {
249
- source: asset,
250
- target: chunk,
251
- file,
252
- range: registration.location,
253
- coverage,
254
- properties: { bundler: registration.bundler },
255
- });
256
- for (const moduleValue of registration.modules) {
257
- const module = context.accumulator.addNode({
258
- kind: "javascript-module",
259
- identity: artifactLocalIdentity(file.sha256, `${registration.runtime}:module`, moduleValue.module_key),
260
- observations: [
261
- {
262
- label: moduleValue.module_key,
263
- properties: {
264
- path: file.path,
265
- bundler: registration.bundler,
266
- runtime: registration.runtime,
267
- module_key: moduleValue.module_key,
268
- source_sha256: moduleValue.source_sha256,
269
- structural_fingerprint_sha256: moduleValue.structural_fingerprint_sha256,
270
- structural_fingerprint_algorithm: moduleValue.structural_fingerprint_algorithm,
271
- structural_fingerprint_status: moduleValue.structural_fingerprint_status,
272
- exports: moduleValue.exports,
273
- exports_truncated: moduleValue.exports_truncated,
274
- },
275
- evidence: astObservationEvidence({
276
- sha256: file.sha256,
277
- path: file.path,
278
- range: moduleValue.location,
279
- operation: "extract-bundler-module",
280
- coverage,
281
- limitations: javascript.limitations,
282
- }),
283
- },
284
- ],
285
- });
286
- context.moduleNodes.set(moduleLookupKey(file.path, moduleValue.module_key), module);
287
- addAstContainsEdge(context, {
288
- source: chunk,
289
- target: module,
290
- file,
291
- range: moduleValue.location,
292
- coverage,
293
- properties: { module_key: moduleValue.module_key },
294
- });
295
- }
296
- }
297
- }
298
- };
299
222
  const createFileTarget = (context, file, javascript) => {
300
223
  const kind = artifactFileNodeKind(file.kind);
224
+ const json = context.analysis.json_modules.find(({ path }) => path === file.path);
301
225
  return context.accumulator.addNode({
302
226
  kind,
303
227
  identity: {
@@ -316,6 +240,9 @@ const createFileTarget = (context, file, javascript) => {
316
240
  file_kind: file.kind,
317
241
  text_status: file.text.included ? "included" : file.text.reason,
318
242
  parse_status: javascript?.parse_status ?? null,
243
+ json_parse_status: json?.status ?? null,
244
+ json_top_level_keys: json?.top_level_keys ?? [],
245
+ omitted_json_top_level_keys: json?.omitted_top_level_keys ?? 0,
319
246
  vendor_markers: javascript?.vendors ?? [],
320
247
  },
321
248
  evidence: artifactObservationEvidence({
@@ -328,13 +255,6 @@ const createFileTarget = (context, file, javascript) => {
328
255
  ],
329
256
  });
330
257
  };
331
- const artifactFileNodeKind = (kind) => kind === "javascript"
332
- ? "javascript-asset"
333
- : kind === "source-map"
334
- ? "source-map"
335
- : kind === "native-addon"
336
- ? "native-addon"
337
- : "artifact";
338
258
  const createAsarEntry = (context, file) => {
339
259
  const isAsar = context.snapshot.manifest.root_format === "asar" ||
340
260
  file.container_sha256 !== context.snapshot.manifest.root_sha256;
@@ -370,12 +290,16 @@ const createAsarEntry = (context, file) => {
370
290
  const addPackageRole = (context, input) => {
371
291
  if (input.declaredPath === null)
372
292
  return;
373
- const resolvedPath = resolveArtifactPath(input.declaredPath, input.packageFile.path, context.filesByPath);
293
+ const resolution = resolveArtifactPathByContext({
294
+ declaredPath: input.declaredPath,
295
+ sourcePath: input.packageFile.path,
296
+ context: "package-entrypoint",
297
+ files: context.filesByPath,
298
+ });
374
299
  const role = createElectronRoleNode(context, {
375
300
  kind: input.kind,
376
301
  anchor: input.packageFile,
377
- declaredPath: input.declaredPath,
378
- resolvedPath,
302
+ resolution,
379
303
  mechanism: input.kind === "electron-main"
380
304
  ? "package.json:main"
381
305
  : "package.json:renderer",
@@ -386,19 +310,23 @@ const addPackageRole = (context, input) => {
386
310
  relation: "loads",
387
311
  properties: {
388
312
  declared_path: input.declaredPath,
389
- resolved_path: resolvedPath,
313
+ resolution_context: resolution.resolution_context,
314
+ resolved_path: resolution.resolved_path,
315
+ resolution_status: resolution.resolution_status,
316
+ limitations: resolution.limitations,
390
317
  },
391
318
  evidence: staticInferenceEvidence({
392
319
  sha256: input.packageFile.sha256,
393
320
  path: input.packageFile.path,
394
321
  operation: "discover-package-entrypoint",
395
322
  coverage: completeReconstructionCoverage(),
323
+ limitations: resolution.limitations,
396
324
  }),
397
325
  });
398
326
  linkElectronRoleToAsset(context, {
399
327
  role,
400
328
  anchor: input.packageFile,
401
- path: resolvedPath,
329
+ resolution,
402
330
  });
403
331
  };
404
332
  const containerProperties = (container) => ({
@@ -0,0 +1,269 @@
1
+ import { builtinModules } from "node:module";
2
+ import { posix } from "node:path";
3
+ const EXTENSIONS = [
4
+ ".js",
5
+ ".cjs",
6
+ ".mjs",
7
+ ".ts",
8
+ ".tsx",
9
+ ".json",
10
+ ".html",
11
+ ".node",
12
+ ];
13
+ const MAX_PACKAGE_DEPTH = 4;
14
+ const NODE_BUILTINS = new Set(builtinModules.map((name) => name.replace(/^node:/u, "")));
15
+ /** Resolve one declaration under its exact syntax/metadata context. */
16
+ export const resolveArtifactPathByContext = (input) => resolveAtDepth(input, 0);
17
+ const resolveAtDepth = (input, packageDepth) => {
18
+ const rejected = rejectDeclaration(input);
19
+ if (rejected !== null)
20
+ return rejected;
21
+ const candidate = contextualCandidate(input);
22
+ if (typeof candidate !== "string")
23
+ return candidate;
24
+ const confined = confineCandidate(input, candidate);
25
+ if (typeof confined !== "string")
26
+ return confined;
27
+ const resolved = resolveCandidate(input, confined, packageDepth);
28
+ return outcome(input, resolved.status, resolved.resolvedPath, resolved.limitations);
29
+ };
30
+ const rejectDeclaration = (input) => {
31
+ const declared = input.declaredPath;
32
+ if (declared.length === 0)
33
+ return outcome(input, "rejected", null, ["The declared path is empty."]);
34
+ if (declared.length > 4_096)
35
+ return outcome(input, "rejected", null, [
36
+ "The declared path exceeds the 4096-character resolution bound.",
37
+ ]);
38
+ if (declared.includes("\0") || declared.includes("\\"))
39
+ return outcome(input, "rejected", null, [
40
+ "NUL and backslash path syntax are not admitted for canonical artifact paths.",
41
+ ]);
42
+ if (/%(?:2e|2f|5c)/iu.test(declared))
43
+ return outcome(input, "rejected", null, [
44
+ "Encoded dot or separator bytes are rejected before artifact path resolution.",
45
+ ]);
46
+ return null;
47
+ };
48
+ const contextualCandidate = (input) => {
49
+ const { context } = input;
50
+ const declared = context === "module-specifier" || context === "html-reference"
51
+ ? stripQueryAndFragment(input.declaredPath)
52
+ : input.declaredPath;
53
+ if (context === "html-reference")
54
+ return htmlCandidate(input);
55
+ if (context === "module-specifier") {
56
+ const fileUrl = fileUrlPath(declared);
57
+ if (fileUrl !== undefined)
58
+ return fileUrl;
59
+ if (hasScheme(declared))
60
+ return outcome(input, "external", null, [
61
+ "URL and Node builtin schemes are outside static artifact module resolution.",
62
+ ]);
63
+ if (!declared.startsWith(".") && !declared.startsWith("/"))
64
+ return bareModuleCandidate(input, declared);
65
+ }
66
+ else if (hasScheme(declared))
67
+ return outcome(input, "external", null, [
68
+ "URL schemes are outside this local artifact path context.",
69
+ ]);
70
+ const relative = declared.startsWith("/") ? declared.slice(1) : declared;
71
+ return declared.startsWith("/")
72
+ ? relative
73
+ : posix.join(posix.dirname(input.sourcePath), relative);
74
+ };
75
+ const bareModuleCandidate = (input, declared) => {
76
+ const packageName = barePackageName(declared);
77
+ if (packageName === null ||
78
+ NODE_BUILTINS.has(packageName) ||
79
+ declared.startsWith("#"))
80
+ return outcome(input, "external", null, [
81
+ "The bare specifier is a Node builtin, package import map, or invalid package name.",
82
+ ]);
83
+ if (declared !== packageName)
84
+ return outcome(input, "external", null, [
85
+ "Bare package subpaths remain unresolved unless an exact package-exports subpath model is available.",
86
+ ]);
87
+ const source = input.files.get(input.sourcePath);
88
+ let directory = posix.dirname(input.sourcePath);
89
+ while (true) {
90
+ const candidate = posix.join(directory, "node_modules", declared);
91
+ if (hasContainerCandidate(input.files, candidate, source?.container_sha256))
92
+ return candidate;
93
+ if (directory === "." || directory === "")
94
+ break;
95
+ directory = posix.dirname(directory);
96
+ }
97
+ return outcome(input, "external", null, [
98
+ "No matching bare package was inventoried in an enclosing node_modules directory.",
99
+ ]);
100
+ };
101
+ const barePackageName = (specifier) => {
102
+ const segments = specifier.split("/");
103
+ if (specifier.startsWith("@"))
104
+ return segments.length >= 2 && segments[0] !== "" && segments[1] !== ""
105
+ ? `${segments[0]}/${segments[1]}`
106
+ : null;
107
+ return segments[0] === "" ? null : (segments[0] ?? null);
108
+ };
109
+ const hasContainerCandidate = (files, candidate, containerSha256) => [...directCandidates(candidate), posix.join(candidate, "package.json")].some((path) => {
110
+ const file = files.get(path);
111
+ return (file !== undefined &&
112
+ (containerSha256 === undefined ||
113
+ file.container_sha256 === containerSha256));
114
+ });
115
+ const htmlCandidate = (input) => {
116
+ const declared = stripQueryAndFragment(input.declaredPath);
117
+ if (hasScheme(declared))
118
+ return outcome(input, "external", null, [
119
+ "External HTML references are not mapped to local artifact assets.",
120
+ ]);
121
+ if (declared.startsWith("/"))
122
+ return declared.slice(1);
123
+ const base = input.htmlBaseHref;
124
+ if (base === undefined || base === null || base === "")
125
+ return posix.join(posix.dirname(input.sourcePath), declared);
126
+ if (hasScheme(base))
127
+ return outcome(input, "external", null, [
128
+ "The document base href is external, so its script reference is not a local artifact path.",
129
+ ]);
130
+ const basePath = base.startsWith("/")
131
+ ? base.slice(1)
132
+ : posix.join(posix.dirname(input.sourcePath), base);
133
+ const baseDirectory = base.endsWith("/") ? basePath : posix.dirname(basePath);
134
+ return posix.join(baseDirectory, declared);
135
+ };
136
+ const confineCandidate = (input, candidate) => {
137
+ const normalized = posix.normalize(candidate);
138
+ if (normalized === ".." ||
139
+ normalized.startsWith("../") ||
140
+ normalized.startsWith("/"))
141
+ return outcome(input, "rejected", null, [
142
+ "The resolved candidate escapes the canonical artifact root.",
143
+ ]);
144
+ return normalized === "." ? "" : normalized;
145
+ };
146
+ const resolveCandidate = (input, candidate, packageDepth) => {
147
+ const source = input.files.get(input.sourcePath);
148
+ for (const path of directCandidates(candidate)) {
149
+ const target = input.files.get(path);
150
+ if (target !== undefined &&
151
+ (source === undefined ||
152
+ target.container_sha256 === source.container_sha256))
153
+ return { resolvedPath: path, status: "resolved", limitations: [] };
154
+ }
155
+ if (packageDepth >= MAX_PACKAGE_DEPTH)
156
+ return {
157
+ resolvedPath: null,
158
+ status: "unavailable",
159
+ limitations: [
160
+ `Directory package resolution exceeded its ${String(MAX_PACKAGE_DEPTH)}-package recursion bound.`,
161
+ ],
162
+ };
163
+ const packagePath = posix.join(candidate, "package.json");
164
+ const packageFile = input.files.get(packagePath);
165
+ if (packageFile === undefined ||
166
+ (source !== undefined &&
167
+ packageFile.container_sha256 !== source.container_sha256))
168
+ return notFoundCandidate();
169
+ if (!packageFile.text.included)
170
+ return {
171
+ resolvedPath: null,
172
+ status: "unavailable",
173
+ limitations: [
174
+ `Directory package metadata ${packagePath} was inventoried but its text is unavailable: ${packageFile.text.reason}.`,
175
+ ],
176
+ };
177
+ const main = packageEntry(packageFile.text.value, input.moduleKind);
178
+ if (main.status === "invalid")
179
+ return {
180
+ resolvedPath: null,
181
+ status: "unavailable",
182
+ limitations: [
183
+ `Directory package metadata ${packagePath} is not valid bounded package JSON.`,
184
+ ],
185
+ };
186
+ if (main.status === "missing")
187
+ return notFoundCandidate();
188
+ const nested = resolveAtDepth({
189
+ declaredPath: main.value,
190
+ sourcePath: packagePath,
191
+ context: "package-entrypoint",
192
+ files: input.files,
193
+ }, packageDepth + 1);
194
+ return {
195
+ resolvedPath: nested.resolved_path,
196
+ status: nested.resolution_status,
197
+ limitations: nested.limitations,
198
+ };
199
+ };
200
+ const directCandidates = (candidate) => [
201
+ candidate,
202
+ ...EXTENSIONS.map((extension) => `${candidate}${extension}`),
203
+ ...EXTENSIONS.map((extension) => posix.join(candidate, `index${extension}`)),
204
+ ];
205
+ const packageEntry = (text, moduleKind) => {
206
+ try {
207
+ const value = JSON.parse(text);
208
+ if (typeof value !== "object" || value === null)
209
+ return { status: "invalid" };
210
+ const rawExports = Reflect.get(value, "exports");
211
+ if (rawExports !== undefined)
212
+ return packageExport(rawExports, moduleKind);
213
+ const preferred = moduleKind === "import"
214
+ ? [Reflect.get(value, "module"), Reflect.get(value, "main")]
215
+ : [Reflect.get(value, "main"), Reflect.get(value, "module")];
216
+ const entry = preferred.find((candidate) => candidate !== undefined);
217
+ if (entry === undefined)
218
+ return { status: "missing" };
219
+ return boundedPackagePath(entry);
220
+ }
221
+ catch {
222
+ return { status: "invalid" };
223
+ }
224
+ };
225
+ const packageExport = (value, moduleKind) => {
226
+ if (typeof value === "string")
227
+ return boundedPackagePath(value);
228
+ if (typeof value !== "object" || value === null || Array.isArray(value))
229
+ return { status: "invalid" };
230
+ const root = Reflect.get(value, ".") ?? value;
231
+ if (typeof root === "string")
232
+ return boundedPackagePath(root);
233
+ if (typeof root !== "object" || root === null || Array.isArray(root))
234
+ return { status: "invalid" };
235
+ const condition = Reflect.get(root, moduleKind ?? "default") ?? Reflect.get(root, "default");
236
+ return boundedPackagePath(condition);
237
+ };
238
+ const boundedPackagePath = (value) => typeof value === "string" && value.length > 0 && value.length <= 4_096
239
+ ? { status: "value", value }
240
+ : { status: "invalid" };
241
+ const notFoundCandidate = () => ({
242
+ resolvedPath: null,
243
+ status: "not-found",
244
+ limitations: [
245
+ "No bounded extension, directory package, or index candidate exists in the inventoried artifact container.",
246
+ ],
247
+ });
248
+ const hasScheme = (value) => /^[A-Za-z][A-Za-z+.-]*:/u.test(value);
249
+ const fileUrlPath = (value) => {
250
+ if (!value.startsWith("file://"))
251
+ return undefined;
252
+ try {
253
+ const url = new URL(value);
254
+ if (url.protocol !== "file:" || url.hostname !== "")
255
+ return undefined;
256
+ return decodeURIComponent(url.pathname).replace(/^\/+/, "");
257
+ }
258
+ catch {
259
+ return undefined;
260
+ }
261
+ };
262
+ const stripQueryAndFragment = (value) => value.split("#", 1)[0]?.split("?", 1)[0] ?? "";
263
+ const outcome = (input, status, resolvedPath, limitations) => ({
264
+ declared_path: input.declaredPath,
265
+ resolution_context: input.context,
266
+ resolved_path: resolvedPath,
267
+ resolution_status: status,
268
+ limitations,
269
+ });
@@ -15,7 +15,7 @@ export const reconstructJavaScriptArtifact = async (rawInput, signal) => {
15
15
  abortIfNeeded(signal);
16
16
  const path = await realpath(input.input_path);
17
17
  const format = await resolveFormat(path, input);
18
- const snapshot = await scanCanonicalArtifactInventory(path, artifactLimitsForReconstruction(input), signal);
18
+ const snapshot = await scanCanonicalArtifactInventory(path, artifactLimitsForReconstruction(input), { signal });
19
19
  if (snapshot.manifest.root_format !== format)
20
20
  throw new ArtifactReaderFailure("format", `Artifact inventory classified ${path} as ${snapshot.manifest.root_format}, not ${format}`);
21
21
  const reader = createReader(path, format);
@@ -0,0 +1,39 @@
1
+ /** Parse one approved JSON module without evaluating JavaScript or resolving imports. */
2
+ export const analyzeJavaScriptJsonModule = (file) => {
3
+ if (!file.text.included)
4
+ return {
5
+ path: file.path,
6
+ sha256: file.sha256,
7
+ status: "unavailable",
8
+ top_level_keys: [],
9
+ omitted_top_level_keys: null,
10
+ limitation: `JSON module text was unavailable: ${file.text.reason}.`,
11
+ };
12
+ let value;
13
+ try {
14
+ value = JSON.parse(file.text.value);
15
+ }
16
+ catch {
17
+ return {
18
+ path: file.path,
19
+ sha256: file.sha256,
20
+ status: "invalid",
21
+ top_level_keys: [],
22
+ omitted_top_level_keys: 0,
23
+ limitation: "JSON module is not valid JSON.",
24
+ };
25
+ }
26
+ const keys = typeof value === "object" && value !== null && !Array.isArray(value)
27
+ ? Object.keys(value).sort(compareCodePoints)
28
+ : [];
29
+ const retained = keys.slice(0, 128);
30
+ return {
31
+ path: file.path,
32
+ sha256: file.sha256,
33
+ status: "included",
34
+ top_level_keys: retained,
35
+ omitted_top_level_keys: keys.length - retained.length,
36
+ limitation: null,
37
+ };
38
+ };
39
+ const compareCodePoints = (left, right) => left < right ? -1 : left > right ? 1 : 0;