rea-agents 2.4.0 → 3.0.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 (231) hide show
  1. package/README.md +91 -19
  2. package/bridge/ghidra/ReaGhidraBridge.java +524 -4
  3. package/bridge/hopper_bridge.py +313 -28
  4. package/dist/application/AnalysisClientCleanup.js +14 -0
  5. package/dist/application/AnalysisContextQueries.js +130 -0
  6. package/dist/application/AnalysisSnapshotCache.js +4 -2
  7. package/dist/application/ApplicationWorkflowEvidenceResolver.js +31 -13
  8. package/dist/application/ArtifactInventory/scanCanonical.js +1 -1
  9. package/dist/application/BinarySession.js +20 -8
  10. package/dist/application/BinarySessionComposition.js +21 -0
  11. package/dist/application/BinarySessionRecords.js +79 -9
  12. package/dist/application/BinarySessionStatus.js +31 -1
  13. package/dist/application/BrowserEvidence.js +14 -0
  14. package/dist/application/BrowserScenarioCapturePort.js +1 -0
  15. package/dist/application/BrowserScenarioCaptureService.js +53 -0
  16. package/dist/application/BrowserScenarioEvidence.js +40 -0
  17. package/dist/application/CallPathTracing.js +160 -0
  18. package/dist/application/CapabilityInventory.js +84 -14
  19. package/dist/application/ClientRegistrationStatus.js +4 -1
  20. package/dist/application/CompositeProvider.js +10 -1
  21. package/dist/application/DirectAnalysis.js +13 -4
  22. package/dist/application/EnhancedLiteralTracing.js +118 -0
  23. package/dist/application/EnhancedTools.js +71 -127
  24. package/dist/application/EvidenceLedger.js +45 -16
  25. package/dist/application/JavaScriptApplicationWorkflowEvidence.js +13 -0
  26. package/dist/application/JavaScriptApplicationWorkflowService.js +27 -1
  27. package/dist/application/JavaScriptArtifactAnalysis.js +13 -4
  28. package/dist/application/JavaScriptRuntimeObservationEvidence.js +34 -0
  29. package/dist/application/JavaScriptRuntimeObservationPort.js +1 -0
  30. package/dist/application/JavaScriptRuntimeObservationService.js +46 -0
  31. package/dist/application/JavaScriptSemanticGraphAsyncProjection.js +147 -0
  32. package/dist/application/JavaScriptSemanticGraphBuilder.js +34 -6
  33. package/dist/application/JavaScriptSemanticGraphChildProcessProjection.js +156 -0
  34. package/dist/application/JavaScriptSemanticGraphConstruction.js +2 -2
  35. package/dist/application/JavaScriptSemanticGraphDataProjection.js +203 -0
  36. package/dist/application/JavaScriptSemanticGraphFingerprintProjection.js +25 -0
  37. package/dist/application/JavaScriptSemanticGraphFlowProjection.js +129 -8
  38. package/dist/application/JavaScriptSemanticGraphObjectProjection.js +81 -0
  39. package/dist/application/JavaScriptSemanticGraphProjection.js +14 -7
  40. package/dist/application/JavaScriptSemanticGraphResourceProjection.js +59 -0
  41. package/dist/application/JavaScriptSemanticGraphValueProjection.js +77 -0
  42. package/dist/application/LazyAnalysisProvider.js +77 -0
  43. package/dist/application/LoopbackReplay.js +1 -1
  44. package/dist/application/NativeApiInspection.js +80 -0
  45. package/dist/application/ProcessReactiveEffects.js +6 -0
  46. package/dist/application/ProcessReactiveHarness.js +16 -1
  47. package/dist/application/ProjectPermissionStore.js +1 -0
  48. package/dist/application/ReconstructionObligationAuthority.js +72 -0
  49. package/dist/application/ReconstructionObligationCandidates.js +265 -0
  50. package/dist/application/ReconstructionObligationLedgerDiagnostics.js +47 -0
  51. package/dist/application/ReconstructionObligationLedgerEvaluation.js +263 -0
  52. package/dist/application/ReconstructionObligationLedgerProjection.js +86 -0
  53. package/dist/application/ReconstructionObligationLedgerService.js +72 -0
  54. package/dist/application/ReconstructionObligationOriginalCases.js +33 -0
  55. package/dist/application/ReconstructionObligationPolicies.js +132 -0
  56. package/dist/application/ReconstructionReadinessService.js +48 -0
  57. package/dist/application/SessionProviderRouter.js +6 -6
  58. package/dist/application/SetupClientConfiguration.js +4 -2
  59. package/dist/application/runtime.js +26 -9
  60. package/dist/artifacts/ArtifactProvider.js +87 -22
  61. package/dist/browser/BrowserScenarioSecrets.js +53 -0
  62. package/dist/browser/BrowserScenarioSessionPort.js +1 -0
  63. package/dist/browser/CdpBrowserProvider.js +2 -2
  64. package/dist/browser/CdpCaptureDocuments.js +57 -0
  65. package/dist/browser/CdpCaptureStorage.js +71 -29
  66. package/dist/browser/CdpCaptureStorageFingerprints.js +328 -0
  67. package/dist/browser/CdpEndpoint.js +8 -6
  68. package/dist/browser/CdpPageCapture.js +2 -0
  69. package/dist/browser/JavaScriptRuntimeScope.js +38 -0
  70. package/dist/browser/PlaywrightBrowserScenarioProvider.js +259 -0
  71. package/dist/browser/PlaywrightExecutionBoundary.js +42 -0
  72. package/dist/browser/PlaywrightScenarioActions.js +62 -0
  73. package/dist/browser/PlaywrightScenarioArtifacts.js +238 -0
  74. package/dist/browser/PlaywrightScenarioBrowser.js +144 -0
  75. package/dist/browser/PlaywrightScenarioEvents.js +301 -0
  76. package/dist/browser/PlaywrightScenarioSession.js +300 -0
  77. package/dist/browser/V8InspectorCaptureProjection.js +110 -0
  78. package/dist/browser/V8InspectorEndpoint.js +72 -0
  79. package/dist/browser/V8InspectorProvider.js +267 -0
  80. package/dist/catalogIdentity.js +11 -3
  81. package/dist/cli/artifactCommands.js +44 -3
  82. package/dist/cli/coreAnalysisCommands.js +78 -0
  83. package/dist/cli.js +4 -0
  84. package/dist/cliApplicationCommands.js +30 -2
  85. package/dist/cliBrowserAdvancedCommands.js +17 -5
  86. package/dist/cliBrowserCommands.js +1 -0
  87. package/dist/cliBrowserScenarioCommands.js +43 -0
  88. package/dist/cliCommandNames.js +9 -0
  89. package/dist/cliJavaScriptRuntimeCommands.js +164 -0
  90. package/dist/cliObservationOptions.js +4 -0
  91. package/dist/cliPolicyCommands.js +1 -0
  92. package/dist/config/environment.js +12 -0
  93. package/dist/config/parseConfig.js +88 -17
  94. package/dist/contracts/analysisSearchContract.js +14 -0
  95. package/dist/contracts/applicationToolContracts.js +86 -2
  96. package/dist/contracts/applicationWorkflowInputContracts.js +18 -0
  97. package/dist/contracts/artifactToolContracts.js +29 -2
  98. package/dist/contracts/browserProviderToolContracts.js +7 -0
  99. package/dist/contracts/browserScenarioToolContracts.js +81 -0
  100. package/dist/contracts/browserToolContracts.js +88 -98
  101. package/dist/contracts/enhancedInputs.js +35 -6
  102. package/dist/contracts/functionInstructionContract.js +8 -0
  103. package/dist/contracts/functionWorkflowToolContracts.js +30 -0
  104. package/dist/contracts/hopperMemoryContracts.js +22 -0
  105. package/dist/contracts/javascriptApplicationWorkflowExamples.js +42 -0
  106. package/dist/contracts/javascriptRuntimeObservationToolContracts.js +58 -0
  107. package/dist/contracts/promptContracts.js +14 -15
  108. package/dist/contracts/reconstructionReadinessExample.js +436 -0
  109. package/dist/contracts/toolContractExamples.js +8 -0
  110. package/dist/contracts/toolContractTypes.js +1 -0
  111. package/dist/contracts/toolContracts.js +34 -25
  112. package/dist/contracts/toolEffects.js +25 -0
  113. package/dist/contracts/toolOutputSchemaGroups.js +120 -30
  114. package/dist/contracts/toolOutputSchemaPrimitives.js +37 -0
  115. package/dist/domain/analysisErrorPresentation.js +8 -2
  116. package/dist/domain/analysisErrorProjection.js +9 -0
  117. package/dist/domain/artifactInspection.js +347 -0
  118. package/dist/domain/browserCaptureComparison.js +82 -0
  119. package/dist/domain/browserObservation.js +8 -1
  120. package/dist/domain/browserObservationErrors.js +1 -0
  121. package/dist/domain/browserObservationSchemas.js +26 -0
  122. package/dist/domain/browserScenario.js +165 -0
  123. package/dist/domain/browserScenarioCapture.js +57 -0
  124. package/dist/domain/browserScenarioCaptureValues.js +204 -0
  125. package/dist/domain/browserScenarioDiff.js +324 -0
  126. package/dist/domain/browserScenarioDiffValues.js +157 -0
  127. package/dist/domain/browserScenarioNormalization.js +45 -0
  128. package/dist/domain/browserScenarioValues.js +372 -0
  129. package/dist/domain/bytecodeProvider.js +179 -0
  130. package/dist/domain/conformancePackage.js +169 -0
  131. package/dist/domain/conformanceReplay.js +104 -0
  132. package/dist/domain/conformanceTrustGate.js +193 -0
  133. package/dist/domain/customProtocolCapture.js +137 -0
  134. package/dist/domain/eventProcessTree.js +214 -0
  135. package/dist/domain/evidenceBundle.js +47 -0
  136. package/dist/domain/hopperStartupFailure.js +1 -1
  137. package/dist/domain/hopperValues.js +14 -1
  138. package/dist/domain/inputIssueProjection.js +7 -1
  139. package/dist/domain/javascriptRuntimeObservation.js +170 -0
  140. package/dist/domain/javascriptRuntimeReconciliationParsing.js +120 -2
  141. package/dist/domain/javascriptRuntimeReconciliationResult.js +3 -3
  142. package/dist/domain/javascriptRuntimeReconciliationRuntime.js +2 -2
  143. package/dist/domain/javascriptRuntimeReconciliationSchemas.js +1 -1
  144. package/dist/domain/javascriptSemanticAnalysis.js +13 -16
  145. package/dist/domain/javascriptSemanticAsyncEffects.js +253 -0
  146. package/dist/domain/javascriptSemanticChildProcesses.js +237 -0
  147. package/dist/domain/javascriptSemanticDataEffectHelpers.js +125 -0
  148. package/dist/domain/javascriptSemanticDataEffects.js +284 -0
  149. package/dist/domain/javascriptSemanticDerivedAnalysis.js +41 -0
  150. package/dist/domain/javascriptSemanticFingerprints.js +174 -0
  151. package/dist/domain/javascriptSemanticIr.js +21 -1
  152. package/dist/domain/javascriptSemanticObjects.js +115 -0
  153. package/dist/domain/javascriptSemanticPromises.js +290 -0
  154. package/dist/domain/javascriptSemanticResources.js +136 -0
  155. package/dist/domain/javascriptSourceParser.js +15 -0
  156. package/dist/domain/javascriptStaticAnalysis.js +12 -15
  157. package/dist/domain/javascriptStaticAnalysisBundler.js +38 -0
  158. package/dist/domain/javascriptStaticAnalysisCalls.js +23 -1
  159. package/dist/domain/javascriptStaticAnalysisHelpers.js +8 -0
  160. package/dist/domain/mobileApplicationInvestigation.js +159 -0
  161. package/dist/domain/nativeApiBoundary.js +130 -0
  162. package/dist/domain/objcSwiftMetadata.js +150 -0
  163. package/dist/domain/packageAnalysis.js +123 -0
  164. package/dist/domain/peInspection.js +196 -0
  165. package/dist/domain/processCapture.js +8 -2
  166. package/dist/domain/processReactiveScenario.js +1 -0
  167. package/dist/domain/processReactiveTransition.js +9 -4
  168. package/dist/domain/protocolCapture.js +243 -0
  169. package/dist/domain/providerCleanupError.js +11 -0
  170. package/dist/domain/reconstructionObligationLedgerSchemas.js +278 -0
  171. package/dist/domain/reconstructionReadiness.js +121 -0
  172. package/dist/domain/reconstructionReadinessFindingHelpers.js +17 -0
  173. package/dist/domain/reconstructionReadinessIntegrityFindings.js +118 -0
  174. package/dist/domain/reconstructionReadinessJourneyFindings.js +193 -0
  175. package/dist/domain/reconstructionReadinessSchemas.js +240 -0
  176. package/dist/domain/sourceToBundleComparison.js +335 -0
  177. package/dist/domain/sourceToBundleComparisonSchemas.js +133 -0
  178. package/dist/domain/sourceToBundleSignals.js +202 -0
  179. package/dist/domain/webCaptureDiff.js +141 -27
  180. package/dist/domain/webScreenshot.js +1 -1
  181. package/dist/dotnet/ManagedStaticProvider.js +34 -5
  182. package/dist/generatedMcpToolCatalog.js +37 -0
  183. package/dist/generatedPackageMetadata.js +4 -4
  184. package/dist/ghidra/GhidraDefaults.js +1 -1
  185. package/dist/ghidra/GhidraFunctionValues.js +40 -2
  186. package/dist/ghidra/GhidraProviderCapabilities.js +47 -38
  187. package/dist/hopper/HopperCleanup.js +158 -0
  188. package/dist/hopper/HopperClient.js +93 -99
  189. package/dist/hopper/HopperProvider.js +61 -30
  190. package/dist/hopper/HopperRequestQueue.js +215 -0
  191. package/dist/hopper/HopperResponseStream.js +46 -0
  192. package/dist/hopper/protocol.js +63 -20
  193. package/dist/main/transport.js +24 -27
  194. package/dist/main.js +14 -6
  195. package/dist/mcpDoctor.js +27 -4
  196. package/dist/mcpStartupPolicy.js +14 -0
  197. package/dist/process/ProcessCommandIdentity.js +19 -0
  198. package/dist/process/ProcessOwnership.js +11 -8
  199. package/dist/server/DynamicToolAvailability.js +70 -0
  200. package/dist/server/LazyToolCatalog.js +134 -0
  201. package/dist/server/createServer.js +92 -154
  202. package/dist/server/hydrateServerTools.js +191 -0
  203. package/dist/server/lifecycleProgress.js +10 -0
  204. package/dist/server/permissionFailure.js +12 -0
  205. package/dist/server/registerApplicationTools/compareSourceToBundle.js +35 -0
  206. package/dist/server/registerApplicationTools/helpers.js +11 -7
  207. package/dist/server/registerApplicationTools/obligationLedger.js +27 -0
  208. package/dist/server/registerApplicationTools/readiness.js +55 -0
  209. package/dist/server/registerApplicationTools.js +6 -0
  210. package/dist/server/registerArtifactTools.js +9 -1
  211. package/dist/server/registerBrowserScenarioTool.js +25 -0
  212. package/dist/server/registerBrowserTools.js +2 -2
  213. package/dist/server/registerCloseLifecycleTool.js +57 -0
  214. package/dist/server/registerEnhancedTools.js +28 -7
  215. package/dist/server/registerEvidenceResources.js +54 -101
  216. package/dist/server/registerEvidenceTools.js +9 -2
  217. package/dist/server/registerInvestigationTools.js +1 -2
  218. package/dist/server/registerJavaScriptApplicationGraphResource.js +0 -4
  219. package/dist/server/registerJavaScriptRuntimeObservationTools.js +37 -0
  220. package/dist/server/registerReconstructionObligationLedgerResource.js +32 -0
  221. package/dist/server/registerReconstructionReadinessResource.js +32 -0
  222. package/dist/server/registerSessionRecordTools.js +82 -12
  223. package/dist/server/registerSessionStatusTool.js +11 -8
  224. package/dist/server/registerSessionTools.js +32 -58
  225. package/dist/server/sessionAvailabilityPolicy.js +10 -8
  226. package/dist/server/toolRegistrationOptions.js +21 -6
  227. package/dist/server/toolResult.js +12 -0
  228. package/package.json +28 -11
  229. package/scripts/package-runner-bootstrap.mjs +72 -0
  230. package/scripts/rea.mjs +11 -1
  231. package/skills/reverse-engineer-anything/SKILL.md +10 -3
@@ -0,0 +1,147 @@
1
+ import { createJavaScriptSemanticGraphUnknown } from "../domain/javascriptSemanticGraph.js";
2
+ import { addSemanticGraphNode, addSemanticGraphRelation, addSemanticGraphUnknown, constructSemanticGraphNode, } from "./JavaScriptSemanticGraphConstruction.js";
3
+ import { unknownSemanticEvidence } from "./JavaScriptSemanticGraphEvidence.js";
4
+ import { semanticCallSiteAt, } from "./JavaScriptSemanticGraphFlowProjection.js";
5
+ /** Project literal EventEmitter registrations, removals, and dispatches. */
6
+ export const projectSemanticEvents = (context) => {
7
+ const eventNodes = new Map();
8
+ for (const operation of context.ir.eventOperations) {
9
+ const eventKey = operation.eventName === null
10
+ ? operation.eventId
11
+ : `${operation.emitterKey}\u0000${operation.eventName}`;
12
+ const event = eventNodes.get(eventKey) ?? addEventNode(context, operation, eventKey);
13
+ if (event === null)
14
+ continue;
15
+ eventNodes.set(eventKey, event);
16
+ const relation = eventRelation(operation);
17
+ if (operation.kind === "dispatch")
18
+ addSemanticGraphRelation(context.state, {
19
+ source: eventEmitterNode(context, operation),
20
+ target: event,
21
+ relation,
22
+ resolution: operation.resolution === "complete" ? "resolved" : "candidate",
23
+ });
24
+ else {
25
+ const listener = addListenerNode(context, operation);
26
+ addSemanticGraphRelation(context.state, {
27
+ source: event,
28
+ target: listener,
29
+ relation,
30
+ resolution: operation.resolution === "complete" ? "resolved" : "candidate",
31
+ });
32
+ }
33
+ if (operation.resolution !== "complete")
34
+ addEventUnknown(context, operation, event, relation);
35
+ }
36
+ };
37
+ const addEventNode = (context, operation, eventKey) => addSemanticGraphNode(context.state, constructSemanticGraphNode(context.file, {
38
+ kind: "event",
39
+ roleKey: `event:${eventKey}`,
40
+ location: operation.eventName === null ? operation.location : null,
41
+ label: operation.eventName,
42
+ functionNodeId: null,
43
+ properties: {
44
+ emitter_key: operation.emitterKey,
45
+ event_name: operation.eventName,
46
+ },
47
+ }, context.state));
48
+ const addListenerNode = (context, operation) => addSemanticGraphNode(context.state, constructSemanticGraphNode(context.file, {
49
+ kind: "listener",
50
+ roleKey: `listener:${operation.eventId}`,
51
+ location: operation.listenerLocation ?? operation.location,
52
+ label: operation.eventName === null
53
+ ? operation.method
54
+ : `${operation.method}:${operation.eventName}`,
55
+ functionNodeId: operation.ownerCallableId === null
56
+ ? null
57
+ : (context.callableNodes.get(operation.ownerCallableId)?.node_id ??
58
+ null),
59
+ properties: {
60
+ emitter_key: operation.emitterKey,
61
+ event_name: operation.eventName,
62
+ method: operation.method,
63
+ },
64
+ }, context.state));
65
+ const eventEmitterNode = (context, operation) => (operation.emitterBindingId === null
66
+ ? undefined
67
+ : context.bindingNodes.get(operation.emitterBindingId)) ??
68
+ (operation.ownerCallableId === null
69
+ ? context.moduleNode
70
+ : (context.callableNodes.get(operation.ownerCallableId) ??
71
+ context.moduleNode));
72
+ const eventRelation = (operation) => operation.kind === "register"
73
+ ? "registers-listener"
74
+ : operation.kind === "remove"
75
+ ? "removes-listener"
76
+ : "dispatches-candidate";
77
+ const addEventUnknown = (context, operation, event, relation) => {
78
+ addSemanticGraphUnknown(context.state, createJavaScriptSemanticGraphUnknown({
79
+ node_id: event.node_id,
80
+ family: "event",
81
+ relation_kinds: [relation],
82
+ reason: "ambiguous-target",
83
+ detail: operation.eventName === null
84
+ ? `Dynamic ${operation.method} event name remains unresolved.`
85
+ : `Static ${operation.method} emitter identity is partial.`,
86
+ candidate_node_ids: [],
87
+ evidence: unknownSemanticEvidence(context.file, operation.location),
88
+ }));
89
+ };
90
+ /** Project Node timer scheduling and exact local handle cancellation. */
91
+ export const projectSemanticTimers = (context) => {
92
+ const timerNodes = new Map(context.ir.timerOperations.flatMap((operation) => {
93
+ if (operation.kind !== "schedule")
94
+ return [];
95
+ const owner = operation.ownerCallableId === null
96
+ ? undefined
97
+ : context.callableNodes.get(operation.ownerCallableId);
98
+ const timer = addSemanticGraphNode(context.state, constructSemanticGraphNode(context.file, {
99
+ kind: "timer",
100
+ roleKey: operation.timerId,
101
+ location: operation.location,
102
+ label: operation.method,
103
+ functionNodeId: owner?.node_id ?? null,
104
+ properties: {
105
+ delay_milliseconds: operation.delayMilliseconds,
106
+ method: operation.method,
107
+ },
108
+ }, context.state));
109
+ return timer === null ? [] : [[operation.timerId, timer]];
110
+ }));
111
+ for (const operation of context.ir.timerOperations)
112
+ if (operation.kind === "schedule")
113
+ projectTimerSchedule(context, operation, timerNodes);
114
+ else
115
+ projectTimerCancellation(context, operation, timerNodes);
116
+ };
117
+ const projectTimerSchedule = (context, operation, timerNodes) => {
118
+ addSemanticGraphRelation(context.state, {
119
+ source: semanticCallSiteAt(context, operation.location),
120
+ target: timerNodes.get(operation.timerId),
121
+ relation: "schedules-timer",
122
+ resolution: "resolved",
123
+ });
124
+ };
125
+ const projectTimerCancellation = (context, operation, timerNodes) => {
126
+ const callSite = semanticCallSiteAt(context, operation.location);
127
+ const target = operation.linkedTimerId === null
128
+ ? undefined
129
+ : timerNodes.get(operation.linkedTimerId);
130
+ addSemanticGraphRelation(context.state, {
131
+ source: callSite,
132
+ target,
133
+ relation: "cancels-timer",
134
+ resolution: operation.resolution === "complete" ? "resolved" : "candidate",
135
+ });
136
+ if (operation.resolution === "complete")
137
+ return;
138
+ addSemanticGraphUnknown(context.state, createJavaScriptSemanticGraphUnknown({
139
+ node_id: callSite?.node_id ?? null,
140
+ family: "timer",
141
+ relation_kinds: ["cancels-timer"],
142
+ reason: "ambiguous-target",
143
+ detail: `Static ${operation.method} handle resolution was ${operation.resolution}.`,
144
+ candidate_node_ids: [],
145
+ evidence: unknownSemanticEvidence(context.file, operation.location),
146
+ }));
147
+ };
@@ -1,16 +1,25 @@
1
1
  import { createJavaScriptSemanticGraph, } from "../domain/javascriptSemanticGraph.js";
2
2
  import { JAVASCRIPT_SEMANTIC_RELATION_FAMILIES, JAVASCRIPT_SEMANTIC_RELATION_FAMILY, } from "../domain/javascriptSemanticGraphSchemas.js";
3
+ import { sourceRangesEqual as rangesEqual } from "../domain/javascriptStaticAnalysisHelpers.js";
4
+ import { projectSemanticEvents, projectSemanticTimers, } from "./JavaScriptSemanticGraphAsyncProjection.js";
5
+ import { projectSemanticChildProcesses } from "./JavaScriptSemanticGraphChildProcessProjection.js";
6
+ import { projectSemanticBoundaries, projectSemanticConfiguration, projectSemanticRequests, } from "./JavaScriptSemanticGraphDataProjection.js";
7
+ import { projectSemanticResources } from "./JavaScriptSemanticGraphResourceProjection.js";
8
+ import { projectSemanticObjects } from "./JavaScriptSemanticGraphObjectProjection.js";
9
+ import { projectSemanticValues } from "./JavaScriptSemanticGraphValueProjection.js";
3
10
  import { inferredSemanticEvidenceAt } from "./JavaScriptSemanticGraphEvidence.js";
4
- import { projectSemanticClosureCaptures, projectSemanticFrontiers, projectSemanticReturnValues, semanticRecoveryLimits, } from "./JavaScriptSemanticGraphFlowProjection.js";
5
- import { owningSemanticCallableNode, semanticFamilyStatus, semanticNodesWithinRange, semanticRangesEqual as rangesEqual, } from "./JavaScriptSemanticGraphProjection.js";
11
+ import { projectSemanticFunctionFingerprints } from "./JavaScriptSemanticGraphFingerprintProjection.js";
12
+ import { projectSemanticClosureCaptures, projectSemanticFrontiers, projectSemanticPromises, projectSemanticReturnValues, semanticRecoveryLimits, } from "./JavaScriptSemanticGraphFlowProjection.js";
13
+ import { owningSemanticCallableNode, semanticFamilyStatus, semanticNodesWithinRange, } from "./JavaScriptSemanticGraphProjection.js";
6
14
  import { addSemanticFallbackRoot as addFallbackRoot, addSemanticGraphNode as addNode, addSemanticGraphRelation as addRelation, constructSemanticGraphNode as semanticNode, createSemanticGraphProjectionState as emptyState, MAX_APPLICATION_NODE_IDS_PER_SEMANTIC_NODE, MAX_SEMANTIC_GRAPH_NODES, MAX_SEMANTIC_GRAPH_RELATIONS, MAX_SEMANTIC_GRAPH_UNKNOWNS, } from "./JavaScriptSemanticGraphConstruction.js";
7
15
  /** Project bounded per-file semantic IR into an artifact-bound companion graph. */
8
16
  export const buildJavaScriptSemanticGraph = ({ rootArtifactSha256, applicationGraph, analysis, }) => {
9
17
  const state = emptyState(applicationGraph);
18
+ const fingerprints = [];
10
19
  for (const analyzed of analysis.files) {
11
20
  if (analyzed.semantic === null)
12
21
  continue;
13
- projectFile(analyzed.file, analyzed.semantic.ir, state);
22
+ fingerprints.push(...projectFile(analyzed.file, analyzed.semantic.ir, state));
14
23
  }
15
24
  if (state.roots.size === 0)
16
25
  addFallbackRoot(rootArtifactSha256, state);
@@ -25,7 +34,7 @@ export const buildJavaScriptSemanticGraph = ({ rootArtifactSha256, applicationGr
25
34
  root_node_ids: [...state.roots],
26
35
  nodes: [...state.nodes.values()],
27
36
  relations: [...state.relations.values()],
28
- fingerprints: [],
37
+ fingerprints,
29
38
  unknowns,
30
39
  coverage: {
31
40
  status: truncated ? "partial" : "unknown",
@@ -68,7 +77,15 @@ export const buildJavaScriptSemanticGraph = ({ rootArtifactSha256, applicationGr
68
77
  limitations: [
69
78
  "The semantic graph contains static syntax observations and conservative relationship candidates; it does not claim runtime execution.",
70
79
  "Local data flow does not claim control-flow-sensitive reaching definitions or arbitrary dynamic property resolution.",
71
- "Function fingerprints and promise, event, process, request, boundary, timer, configuration, and resource extraction are not available in this graph version's current extractor coverage.",
80
+ "Promise ownership covers explicit unshadowed Promise construction, static factories, aggregation, chaining, and await syntax only.",
81
+ "Function fingerprints are bounded static candidates; equal digests can remain ambiguous and do not prove behavioral equivalence.",
82
+ "Event extraction covers EventEmitter-style literal registrations, removals, and dispatch candidates; dynamic names remain unknown.",
83
+ "Timer extraction covers global or node:timers scheduling and exact local-handle cancellation.",
84
+ "Child-process extraction covers asynchronous node:child_process creation, literal argv/env/stdio options, exit/error listeners, and kill signals.",
85
+ "Configuration extraction covers process.env, process.argv, node:fs reads, and direct logical defaults.",
86
+ "Request extraction covers fetch, WebSocket, node:http/node:https construction, direct option fields, and exact local response consumers.",
87
+ "Boundary extraction covers unshadowed JSON/global coercions plus parse and validation method candidates.",
88
+ "Resource extraction covers built-in filesystem/network acquisition and exact local close/destroy/end handles.",
72
89
  ...(truncated
73
90
  ? [
74
91
  "Semantic graph projection reached one or more explicit hard limits.",
@@ -86,7 +103,7 @@ const projectFile = (file, ir, state) => {
86
103
  functionNodeId: null,
87
104
  }, state));
88
105
  if (moduleNode === null)
89
- return;
106
+ return [];
90
107
  state.roots.add(moduleNode.node_id);
91
108
  const callableNodes = new Map(ir.callables.flatMap((callable) => {
92
109
  const node = addNode(state, semanticNode(file, {
@@ -130,9 +147,20 @@ const projectFile = (file, ir, state) => {
130
147
  ])),
131
148
  };
132
149
  projectDefinitionsAndReferences(context);
150
+ projectSemanticValues(context);
151
+ projectSemanticObjects(context);
133
152
  projectCalls(context);
153
+ projectSemanticPromises(context);
154
+ projectSemanticEvents(context);
155
+ projectSemanticTimers(context);
156
+ projectSemanticChildProcesses(context);
157
+ projectSemanticConfiguration(context);
158
+ projectSemanticRequests(context);
159
+ projectSemanticBoundaries(context);
160
+ projectSemanticResources(context);
134
161
  projectSemanticClosureCaptures(context);
135
162
  projectSemanticFrontiers(context);
163
+ return projectSemanticFunctionFingerprints(file, ir, callableNodes);
136
164
  };
137
165
  const createReturnSiteNodes = (file, ir, callables, state) => {
138
166
  const result = new Map();
@@ -0,0 +1,156 @@
1
+ import { createJavaScriptSemanticGraphUnknown } from "../domain/javascriptSemanticGraph.js";
2
+ import { addSemanticGraphNode, addSemanticGraphRelation, addSemanticGraphUnknown, constructSemanticGraphNode, } from "./JavaScriptSemanticGraphConstruction.js";
3
+ import { unknownSemanticEvidence } from "./JavaScriptSemanticGraphEvidence.js";
4
+ import { semanticCallSiteAt, } from "./JavaScriptSemanticGraphFlowProjection.js";
5
+ /** Project child creation, argv/env/stdio, listeners, and signals. */
6
+ export const projectSemanticChildProcesses = (context) => {
7
+ const processNodes = new Map(context.ir.childProcessSpawns.flatMap((spawn) => {
8
+ const node = addChildProcessNode(context, spawn);
9
+ return node === null ? [] : [[spawn.processId, node]];
10
+ }));
11
+ for (const spawn of context.ir.childProcessSpawns) {
12
+ const child = processNodes.get(spawn.processId);
13
+ if (child === undefined)
14
+ continue;
15
+ projectSpawn(context, spawn, child);
16
+ }
17
+ for (const interaction of context.ir.childProcessInteractions)
18
+ projectInteraction(context, interaction, processNodes);
19
+ };
20
+ const addChildProcessNode = (context, spawn) => addSemanticGraphNode(context.state, constructSemanticGraphNode(context.file, {
21
+ kind: "child-process",
22
+ roleKey: spawn.processId,
23
+ location: spawn.location,
24
+ label: spawn.command ?? spawn.method,
25
+ functionNodeId: spawn.ownerCallableId === null
26
+ ? null
27
+ : (context.callableNodes.get(spawn.ownerCallableId)?.node_id ??
28
+ null),
29
+ properties: {
30
+ argv_count: spawn.argvCount,
31
+ command: spawn.command,
32
+ environment_supplied: spawn.environmentSupplied,
33
+ method: spawn.method,
34
+ stdio_mode: spawn.stdioMode,
35
+ },
36
+ }, context.state));
37
+ const projectSpawn = (context, spawn, child) => {
38
+ const callSite = semanticCallSiteAt(context, spawn.location);
39
+ addSemanticGraphRelation(context.state, {
40
+ source: callSite,
41
+ target: child,
42
+ relation: "spawns",
43
+ resolution: spawn.resolution === "complete" ? "resolved" : "candidate",
44
+ });
45
+ if (spawn.argvCount !== null)
46
+ addSemanticGraphRelation(context.state, {
47
+ source: callSite,
48
+ target: child,
49
+ relation: "supplies-argv",
50
+ resolution: "resolved",
51
+ properties: { argument_count: spawn.argvCount },
52
+ });
53
+ if (spawn.environmentSupplied)
54
+ addSemanticGraphRelation(context.state, {
55
+ source: callSite,
56
+ target: child,
57
+ relation: "supplies-env",
58
+ resolution: "resolved",
59
+ });
60
+ const stdio = addStdioNode(context, spawn, child);
61
+ addSemanticGraphRelation(context.state, {
62
+ source: child,
63
+ target: stdio,
64
+ relation: "connects-stdio",
65
+ resolution: spawn.stdioMode === "dynamic" ? "candidate" : "resolved",
66
+ });
67
+ if (spawn.resolution !== "complete")
68
+ addChildUnknown({
69
+ context,
70
+ node: child,
71
+ location: spawn.location,
72
+ relationKinds: ["spawns"],
73
+ detail: `Static ${spawn.method} command remains unresolved.`,
74
+ candidateNodeIds: [],
75
+ });
76
+ };
77
+ const addStdioNode = (context, spawn, child) => addSemanticGraphNode(context.state, constructSemanticGraphNode(context.file, {
78
+ kind: "stdio",
79
+ roleKey: `stdio:${spawn.processId}`,
80
+ location: spawn.location,
81
+ label: spawn.stdioMode,
82
+ functionNodeId: child.function_node_id,
83
+ properties: { mode: spawn.stdioMode },
84
+ }, context.state));
85
+ const projectInteraction = (context, interaction, processNodes) => {
86
+ const children = interaction.linkedProcessIds.flatMap((identifier) => {
87
+ const child = processNodes.get(identifier);
88
+ return child === undefined ? [] : [child];
89
+ });
90
+ const effect = interaction.kind === "listener"
91
+ ? addChildListenerNode(context, interaction)
92
+ : addSignalNode(context, interaction);
93
+ for (const child of children)
94
+ addSemanticGraphRelation(context.state, {
95
+ source: interaction.kind === "listener" ? child : effect,
96
+ target: interaction.kind === "listener" ? effect : child,
97
+ relation: interaction.kind === "signal"
98
+ ? "forwards-signal"
99
+ : interaction.eventName === "exit"
100
+ ? "listens-exit"
101
+ : "listens-error",
102
+ resolution: interaction.resolution === "complete" ? "resolved" : "candidate",
103
+ });
104
+ if (interaction.resolution !== "complete")
105
+ addChildUnknown({
106
+ context,
107
+ node: effect,
108
+ location: interaction.location,
109
+ relationKinds: [
110
+ interaction.kind === "signal"
111
+ ? "forwards-signal"
112
+ : interaction.eventName === "exit"
113
+ ? "listens-exit"
114
+ : "listens-error",
115
+ ],
116
+ detail: `Static child ${interaction.method} ownership is ambiguous.`,
117
+ candidateNodeIds: children.map(({ node_id: identifier }) => identifier),
118
+ });
119
+ };
120
+ const addChildListenerNode = (context, interaction) => addSemanticGraphNode(context.state, constructSemanticGraphNode(context.file, {
121
+ kind: "listener",
122
+ roleKey: interaction.interactionId,
123
+ location: interaction.listenerLocation ?? interaction.location,
124
+ label: interaction.eventName,
125
+ functionNodeId: interaction.ownerCallableId === null
126
+ ? null
127
+ : (context.callableNodes.get(interaction.ownerCallableId)
128
+ ?.node_id ?? null),
129
+ properties: {
130
+ event_name: interaction.eventName,
131
+ method: interaction.method,
132
+ },
133
+ }, context.state));
134
+ const addSignalNode = (context, interaction) => addSemanticGraphNode(context.state, constructSemanticGraphNode(context.file, {
135
+ kind: "signal",
136
+ roleKey: interaction.interactionId,
137
+ location: interaction.location,
138
+ label: interaction.signalName,
139
+ functionNodeId: interaction.ownerCallableId === null
140
+ ? null
141
+ : (context.callableNodes.get(interaction.ownerCallableId)
142
+ ?.node_id ?? null),
143
+ properties: { signal_name: interaction.signalName },
144
+ }, context.state));
145
+ const addChildUnknown = (input) => {
146
+ const { context, node, location, relationKinds, detail, candidateNodeIds } = input;
147
+ addSemanticGraphUnknown(context.state, createJavaScriptSemanticGraphUnknown({
148
+ node_id: node?.node_id ?? null,
149
+ family: "child-process",
150
+ relation_kinds: relationKinds,
151
+ reason: "ambiguous-target",
152
+ detail,
153
+ candidate_node_ids: candidateNodeIds,
154
+ evidence: unknownSemanticEvidence(context.file, location),
155
+ }));
156
+ };
@@ -32,7 +32,7 @@ export const constructSemanticGraphNode = (file, input, state) => createJavaScri
32
32
  function_node_id: input.functionNodeId,
33
33
  application_node_ids: matchingApplicationNodeIds(file, input, state),
34
34
  label: input.label,
35
- properties: {},
35
+ properties: input.properties ?? {},
36
36
  evidence: observedSemanticEvidence(file, input.location),
37
37
  });
38
38
  /** Retain one canonical node unless the hard graph bound was reached. */
@@ -60,7 +60,7 @@ export const addSemanticGraphRelation = (state, input) => {
60
60
  target_node_id: input.target.node_id,
61
61
  relation: input.relation,
62
62
  resolution: input.resolution ?? "candidate",
63
- properties: {},
63
+ properties: input.properties ?? {},
64
64
  evidence: input.evidence ?? inferredSemanticEvidence(input.source),
65
65
  });
66
66
  if (state.relations.has(value.relation_id))
@@ -0,0 +1,203 @@
1
+ import { createJavaScriptSemanticGraphUnknown } from "../domain/javascriptSemanticGraph.js";
2
+ import { addSemanticGraphNode, addSemanticGraphRelation, addSemanticGraphUnknown, constructSemanticGraphNode, } from "./JavaScriptSemanticGraphConstruction.js";
3
+ import { unknownSemanticEvidence } from "./JavaScriptSemanticGraphEvidence.js";
4
+ import { semanticCallSiteAt, } from "./JavaScriptSemanticGraphFlowProjection.js";
5
+ /** Project environment, argv, file, default, and precedence candidates. */
6
+ export const projectSemanticConfiguration = (context) => {
7
+ const configNodes = new Map(context.ir.configurationOperations.flatMap((operation) => {
8
+ const node = addConfigurationNode(context, operation);
9
+ return node === null ? [] : [[operation.configId, node]];
10
+ }));
11
+ for (const operation of context.ir.configurationOperations) {
12
+ const config = configNodes.get(operation.configId);
13
+ if (config === undefined)
14
+ continue;
15
+ const target = bindingOrOwner(context, operation.resultBindingId, operation.ownerCallableId);
16
+ addSemanticGraphRelation(context.state, {
17
+ source: config,
18
+ target,
19
+ relation: configurationRelation(operation),
20
+ resolution: operation.resolution === "complete" ? "resolved" : "candidate",
21
+ });
22
+ if (operation.kind === "default" && operation.sourceConfigId !== null)
23
+ addSemanticGraphRelation(context.state, {
24
+ source: configNodes.get(operation.sourceConfigId),
25
+ target: config,
26
+ relation: "overrides",
27
+ resolution: operation.resolution === "complete" ? "resolved" : "candidate",
28
+ });
29
+ if (operation.resolution !== "complete")
30
+ addDataUnknown({
31
+ context,
32
+ node: config,
33
+ family: "configuration",
34
+ relationKinds: [
35
+ configurationRelation(operation),
36
+ ...(operation.kind === "default" ? ["overrides"] : []),
37
+ ],
38
+ location: operation.location,
39
+ detail: `Static ${operation.kind} configuration identity is partial.`,
40
+ candidateNodeIds: [],
41
+ });
42
+ }
43
+ };
44
+ const addConfigurationNode = (context, operation) => addSemanticGraphNode(context.state, constructSemanticGraphNode(context.file, {
45
+ kind: "config-source",
46
+ roleKey: operation.configId,
47
+ location: operation.location,
48
+ label: operation.key ?? operation.kind,
49
+ functionNodeId: operation.ownerCallableId === null
50
+ ? null
51
+ : (context.callableNodes.get(operation.ownerCallableId)?.node_id ??
52
+ null),
53
+ properties: {
54
+ key: operation.key,
55
+ source_kind: operation.kind,
56
+ value: operation.value,
57
+ },
58
+ }, context.state));
59
+ const configurationRelation = (operation) => operation.kind === "environment"
60
+ ? "reads-environment"
61
+ : operation.kind === "argv"
62
+ ? "reads-argv"
63
+ : operation.kind === "file"
64
+ ? "reads-config"
65
+ : "defaults";
66
+ /** Project request construction, field provenance, and response consumers. */
67
+ export const projectSemanticRequests = (context) => {
68
+ const requestNodes = new Map(context.ir.requestOperations.flatMap((operation) => {
69
+ const node = addRequestNode(context, operation);
70
+ return node === null ? [] : [[operation.requestId, node]];
71
+ }));
72
+ for (const operation of context.ir.requestOperations) {
73
+ const request = requestNodes.get(operation.requestId);
74
+ if (request === undefined)
75
+ continue;
76
+ if (operation.kind === "request")
77
+ projectRequestConstruction(context, operation, request);
78
+ else
79
+ projectResponseConsumer(context, operation, request);
80
+ if (operation.resolution !== "complete")
81
+ addDataUnknown({
82
+ context,
83
+ node: request,
84
+ family: "request",
85
+ relationKinds: operation.kind === "request"
86
+ ? ["constructs-request", "supplies-request-field"]
87
+ : ["consumed-by"],
88
+ location: operation.location,
89
+ detail: `Static ${operation.method} request resolution was ${operation.resolution}.`,
90
+ candidateNodeIds: operation.linkedRequestIds.flatMap((identifier) => {
91
+ const candidate = requestNodes.get(identifier);
92
+ return candidate === undefined ? [] : [candidate.node_id];
93
+ }),
94
+ });
95
+ }
96
+ };
97
+ const addRequestNode = (context, operation) => addSemanticGraphNode(context.state, constructSemanticGraphNode(context.file, {
98
+ kind: operation.kind === "request" ? "request" : "response",
99
+ roleKey: operation.requestId,
100
+ location: operation.location,
101
+ label: operation.endpoint ?? operation.method,
102
+ functionNodeId: operation.ownerCallableId === null
103
+ ? null
104
+ : (context.callableNodes.get(operation.ownerCallableId)?.node_id ??
105
+ null),
106
+ properties: {
107
+ endpoint: operation.endpoint,
108
+ method: operation.method,
109
+ operation_kind: operation.kind,
110
+ },
111
+ }, context.state));
112
+ const projectRequestConstruction = (context, operation, request) => {
113
+ const callSite = semanticCallSiteAt(context, operation.location);
114
+ addSemanticGraphRelation(context.state, {
115
+ source: callSite,
116
+ target: request,
117
+ relation: "constructs-request",
118
+ resolution: operation.resolution === "complete" ? "resolved" : "candidate",
119
+ });
120
+ for (const field of operation.fields)
121
+ addSemanticGraphRelation(context.state, {
122
+ source: field.sourceBindingId === null
123
+ ? callSite
124
+ : context.bindingNodes.get(field.sourceBindingId),
125
+ target: request,
126
+ relation: "supplies-request-field",
127
+ resolution: field.sourceBindingId === null ? "candidate" : "resolved",
128
+ properties: { field: field.name },
129
+ });
130
+ };
131
+ const projectResponseConsumer = (context, operation, response) => {
132
+ addSemanticGraphRelation(context.state, {
133
+ source: response,
134
+ target: semanticCallSiteAt(context, operation.location),
135
+ relation: "consumed-by",
136
+ resolution: operation.resolution === "complete" ? "resolved" : "candidate",
137
+ properties: { method: operation.method },
138
+ });
139
+ };
140
+ /** Project parse, coercion, and validation consumers as static boundaries. */
141
+ export const projectSemanticBoundaries = (context) => {
142
+ for (const operation of context.ir.boundaryOperations) {
143
+ const boundary = addBoundaryNode(context, operation);
144
+ if (boundary === null)
145
+ continue;
146
+ addSemanticGraphRelation(context.state, {
147
+ source: bindingOrOwner(context, operation.sourceBindingId, operation.ownerCallableId),
148
+ target: boundary,
149
+ relation: operation.kind === "parse"
150
+ ? "parses"
151
+ : operation.kind === "coerce"
152
+ ? "coerces"
153
+ : "validates",
154
+ resolution: operation.resolution === "complete" ? "resolved" : "candidate",
155
+ });
156
+ if (operation.resolution !== "complete")
157
+ addDataUnknown({
158
+ context,
159
+ node: boundary,
160
+ family: "boundary",
161
+ relationKinds: [
162
+ operation.kind === "parse"
163
+ ? "parses"
164
+ : operation.kind === "coerce"
165
+ ? "coerces"
166
+ : "validates",
167
+ ],
168
+ location: operation.location,
169
+ detail: `Static ${operation.method} boundary kind is a candidate.`,
170
+ candidateNodeIds: [],
171
+ });
172
+ }
173
+ };
174
+ const addBoundaryNode = (context, operation) => addSemanticGraphNode(context.state, constructSemanticGraphNode(context.file, {
175
+ kind: "boundary",
176
+ roleKey: operation.boundaryId,
177
+ location: operation.location,
178
+ label: operation.method,
179
+ functionNodeId: operation.ownerCallableId === null
180
+ ? null
181
+ : (context.callableNodes.get(operation.ownerCallableId)?.node_id ??
182
+ null),
183
+ properties: {
184
+ boundary_kind: operation.kind,
185
+ method: operation.method,
186
+ },
187
+ }, context.state));
188
+ const bindingOrOwner = (context, bindingId, callableId) => (bindingId === null ? undefined : context.bindingNodes.get(bindingId)) ??
189
+ (callableId === null
190
+ ? context.moduleNode
191
+ : (context.callableNodes.get(callableId) ?? context.moduleNode));
192
+ const addDataUnknown = (input) => {
193
+ const { context, node, family, relationKinds, location, detail, candidateNodeIds, } = input;
194
+ addSemanticGraphUnknown(context.state, createJavaScriptSemanticGraphUnknown({
195
+ node_id: node.node_id,
196
+ family,
197
+ relation_kinds: relationKinds,
198
+ reason: "ambiguous-target",
199
+ detail,
200
+ candidate_node_ids: candidateNodeIds,
201
+ evidence: unknownSemanticEvidence(context.file, location),
202
+ }));
203
+ };
@@ -0,0 +1,25 @@
1
+ import { createJavaScriptSemanticFingerprint, } from "../domain/javascriptSemanticGraph.js";
2
+ import { observedSemanticEvidence } from "./JavaScriptSemanticGraphEvidence.js";
3
+ /** Bind domain fingerprint components to exact semantic function nodes. */
4
+ export const projectSemanticFunctionFingerprints = (file, ir, callableNodes) => ir.functionFingerprints.flatMap((fingerprint) => {
5
+ const callable = callableNodes.get(fingerprint.callableId);
6
+ if (callable === undefined)
7
+ return [];
8
+ return [
9
+ createJavaScriptSemanticFingerprint({
10
+ function_node_id: callable.node_id,
11
+ algorithm: "rea.javascript-semantic-function/v1",
12
+ status: fingerprint.status,
13
+ components: {
14
+ parameter_arity: fingerprint.components.parameterArity,
15
+ normalized_ast_sha256: fingerprint.components.normalizedAstSha256,
16
+ control_flow_sha256: fingerprint.components.controlFlowSha256,
17
+ relation_shape_sha256: fingerprint.components.relationShapeSha256,
18
+ literal_set_sha256: fingerprint.components.literalSetSha256,
19
+ effects: fingerprint.components.effects,
20
+ },
21
+ limitations: fingerprint.limitations,
22
+ evidence: observedSemanticEvidence(file, callable.identity.source_range),
23
+ }),
24
+ ];
25
+ });