rea-agents 2.3.0 → 2.5.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 (209) hide show
  1. package/README.md +80 -18
  2. package/bridge/ghidra/ReaGhidraBridge.java +48 -1
  3. package/bridge/hopper_bridge.py +259 -24
  4. package/dist/application/AnalysisClientCleanup.js +14 -0
  5. package/dist/application/ApplicationWorkflowEvidenceResolver.js +31 -13
  6. package/dist/application/ArtifactExtraction.js +5 -1
  7. package/dist/application/ArtifactGraphConstruction.js +3 -15
  8. package/dist/application/ArtifactInventory/classify.js +5 -1
  9. package/dist/application/ArtifactInventory/reader.js +2 -0
  10. package/dist/application/BinarySession.js +15 -4
  11. package/dist/application/BinarySessionStatus.js +32 -1
  12. package/dist/application/BrowserEvidence.js +14 -0
  13. package/dist/application/BrowserScenarioCapturePort.js +1 -0
  14. package/dist/application/BrowserScenarioCaptureService.js +53 -0
  15. package/dist/application/BrowserScenarioEvidence.js +40 -0
  16. package/dist/application/CallPathTracing.js +160 -0
  17. package/dist/application/CapabilityInventory.js +79 -15
  18. package/dist/application/CompositeProvider.js +10 -1
  19. package/dist/application/DirectAnalysis.js +7 -2
  20. package/dist/application/EnhancedLiteralTracing.js +118 -0
  21. package/dist/application/EnhancedTools.js +35 -121
  22. package/dist/application/JavaScriptApplicationWorkflowEvidence.js +13 -0
  23. package/dist/application/JavaScriptApplicationWorkflowService.js +27 -1
  24. package/dist/application/JavaScriptRuntimeObservationEvidence.js +34 -0
  25. package/dist/application/JavaScriptRuntimeObservationPort.js +1 -0
  26. package/dist/application/JavaScriptRuntimeObservationService.js +46 -0
  27. package/dist/application/JavaScriptSemanticGraphAsyncProjection.js +147 -0
  28. package/dist/application/JavaScriptSemanticGraphBuilder.js +34 -6
  29. package/dist/application/JavaScriptSemanticGraphChildProcessProjection.js +156 -0
  30. package/dist/application/JavaScriptSemanticGraphConstruction.js +2 -2
  31. package/dist/application/JavaScriptSemanticGraphDataProjection.js +203 -0
  32. package/dist/application/JavaScriptSemanticGraphFingerprintProjection.js +25 -0
  33. package/dist/application/JavaScriptSemanticGraphFlowProjection.js +129 -8
  34. package/dist/application/JavaScriptSemanticGraphObjectProjection.js +81 -0
  35. package/dist/application/JavaScriptSemanticGraphProjection.js +14 -7
  36. package/dist/application/JavaScriptSemanticGraphResourceProjection.js +59 -0
  37. package/dist/application/JavaScriptSemanticGraphValueProjection.js +77 -0
  38. package/dist/application/ProcessCaptureEnvironment.js +26 -0
  39. package/dist/application/ProcessCaptureLifecycle.js +1 -0
  40. package/dist/application/ProcessCheckpoints.js +5 -0
  41. package/dist/application/ProcessHarness.js +45 -34
  42. package/dist/application/ProcessNormalization.js +6 -0
  43. package/dist/application/ProcessReactiveCoordinator.js +10 -3
  44. package/dist/application/ProcessReactiveEffects.js +15 -1
  45. package/dist/application/ProcessReactiveHarness.js +100 -0
  46. package/dist/application/ProcessReactiveObservations.js +101 -16
  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/artifacts/ArtifactProvider.js +87 -22
  58. package/dist/browser/BrowserScenarioSecrets.js +53 -0
  59. package/dist/browser/BrowserScenarioSessionPort.js +1 -0
  60. package/dist/browser/CdpBrowserProvider.js +2 -2
  61. package/dist/browser/CdpCaptureDocuments.js +57 -0
  62. package/dist/browser/CdpCaptureStorage.js +71 -29
  63. package/dist/browser/CdpCaptureStorageFingerprints.js +328 -0
  64. package/dist/browser/CdpEndpoint.js +8 -6
  65. package/dist/browser/CdpPageCapture.js +2 -0
  66. package/dist/browser/JavaScriptRuntimeScope.js +38 -0
  67. package/dist/browser/PlaywrightBrowserScenarioProvider.js +253 -0
  68. package/dist/browser/PlaywrightExecutionBoundary.js +42 -0
  69. package/dist/browser/PlaywrightScenarioActions.js +62 -0
  70. package/dist/browser/PlaywrightScenarioArtifacts.js +238 -0
  71. package/dist/browser/PlaywrightScenarioBrowser.js +144 -0
  72. package/dist/browser/PlaywrightScenarioEvents.js +301 -0
  73. package/dist/browser/PlaywrightScenarioSession.js +300 -0
  74. package/dist/browser/V8InspectorCaptureProjection.js +110 -0
  75. package/dist/browser/V8InspectorEndpoint.js +72 -0
  76. package/dist/browser/V8InspectorProvider.js +267 -0
  77. package/dist/catalogIdentity.js +8 -0
  78. package/dist/cli/artifactCommands.js +39 -0
  79. package/dist/cli/coreAnalysisCommands.js +37 -0
  80. package/dist/cli.js +4 -0
  81. package/dist/cliApplicationCommands.js +30 -2
  82. package/dist/cliBrowserAdvancedCommands.js +17 -5
  83. package/dist/cliBrowserCommands.js +1 -0
  84. package/dist/cliBrowserScenarioCommands.js +43 -0
  85. package/dist/cliCommandNames.js +8 -0
  86. package/dist/cliJavaScriptRuntimeCommands.js +164 -0
  87. package/dist/cliObservationOptions.js +4 -0
  88. package/dist/cliPolicyCommands.js +1 -0
  89. package/dist/config/environment.js +12 -0
  90. package/dist/config/parseConfig.js +88 -17
  91. package/dist/contracts/analysisSearchContract.js +14 -0
  92. package/dist/contracts/applicationToolContracts.js +86 -2
  93. package/dist/contracts/applicationWorkflowInputContracts.js +18 -0
  94. package/dist/contracts/artifactToolContracts.js +22 -0
  95. package/dist/contracts/browserProviderToolContracts.js +7 -0
  96. package/dist/contracts/browserScenarioToolContracts.js +81 -0
  97. package/dist/contracts/browserToolContracts.js +88 -98
  98. package/dist/contracts/enhancedInputs.js +25 -6
  99. package/dist/contracts/functionInstructionContract.js +8 -0
  100. package/dist/contracts/hopperMemoryContracts.js +22 -0
  101. package/dist/contracts/javascriptApplicationWorkflowExamples.js +42 -0
  102. package/dist/contracts/javascriptRuntimeObservationToolContracts.js +58 -0
  103. package/dist/contracts/reconstructionReadinessExample.js +436 -0
  104. package/dist/contracts/toolContractExamples.js +5 -0
  105. package/dist/contracts/toolContractTypes.js +1 -0
  106. package/dist/contracts/toolContracts.js +13 -21
  107. package/dist/contracts/toolEffects.js +21 -0
  108. package/dist/contracts/toolOutputSchemaGroups.js +70 -20
  109. package/dist/contracts/toolOutputSchemaPrimitives.js +40 -0
  110. package/dist/domain/analysisErrorProjection.js +8 -0
  111. package/dist/domain/analysisSnapshot.js +2 -0
  112. package/dist/domain/artifactGraph.js +2 -0
  113. package/dist/domain/artifactInspection.js +347 -0
  114. package/dist/domain/binaryTarget.js +3 -6
  115. package/dist/domain/browserCaptureComparison.js +82 -0
  116. package/dist/domain/browserObservation.js +8 -1
  117. package/dist/domain/browserObservationErrors.js +1 -0
  118. package/dist/domain/browserObservationSchemas.js +26 -0
  119. package/dist/domain/browserScenario.js +165 -0
  120. package/dist/domain/browserScenarioCapture.js +57 -0
  121. package/dist/domain/browserScenarioCaptureValues.js +204 -0
  122. package/dist/domain/browserScenarioDiff.js +324 -0
  123. package/dist/domain/browserScenarioDiffValues.js +157 -0
  124. package/dist/domain/browserScenarioNormalization.js +45 -0
  125. package/dist/domain/browserScenarioValues.js +372 -0
  126. package/dist/domain/evidence.js +2 -0
  127. package/dist/domain/hopperValues.js +10 -0
  128. package/dist/domain/javascriptRuntimeObservation.js +170 -0
  129. package/dist/domain/javascriptRuntimeReconciliationParsing.js +120 -2
  130. package/dist/domain/javascriptRuntimeReconciliationResult.js +3 -3
  131. package/dist/domain/javascriptRuntimeReconciliationRuntime.js +2 -2
  132. package/dist/domain/javascriptRuntimeReconciliationSchemas.js +1 -1
  133. package/dist/domain/javascriptSemanticAnalysis.js +5 -4
  134. package/dist/domain/javascriptSemanticAsyncEffects.js +253 -0
  135. package/dist/domain/javascriptSemanticChildProcesses.js +237 -0
  136. package/dist/domain/javascriptSemanticDataEffectHelpers.js +125 -0
  137. package/dist/domain/javascriptSemanticDataEffects.js +284 -0
  138. package/dist/domain/javascriptSemanticDerivedAnalysis.js +41 -0
  139. package/dist/domain/javascriptSemanticFingerprints.js +174 -0
  140. package/dist/domain/javascriptSemanticIr.js +21 -1
  141. package/dist/domain/javascriptSemanticObjects.js +115 -0
  142. package/dist/domain/javascriptSemanticPromises.js +290 -0
  143. package/dist/domain/javascriptSemanticResources.js +136 -0
  144. package/dist/domain/javascriptStaticAnalysis.js +4 -3
  145. package/dist/domain/javascriptStaticAnalysisBundler.js +38 -0
  146. package/dist/domain/javascriptStaticAnalysisCalls.js +23 -1
  147. package/dist/domain/javascriptStaticAnalysisHelpers.js +8 -0
  148. package/dist/domain/processCapture.js +71 -1
  149. package/dist/domain/processCaptureReactiveValidation.js +175 -0
  150. package/dist/domain/processCaptureValidation.js +2 -0
  151. package/dist/domain/processObservation.js +15 -6
  152. package/dist/domain/processReactiveRuntime.js +21 -10
  153. package/dist/domain/processReactiveScenario.js +1 -0
  154. package/dist/domain/processReactiveTransition.js +17 -10
  155. package/dist/domain/processScenario.js +21 -0
  156. package/dist/domain/providerCleanupError.js +11 -0
  157. package/dist/domain/reconstructionObligationLedgerSchemas.js +278 -0
  158. package/dist/domain/reconstructionReadiness.js +121 -0
  159. package/dist/domain/reconstructionReadinessFindingHelpers.js +17 -0
  160. package/dist/domain/reconstructionReadinessIntegrityFindings.js +118 -0
  161. package/dist/domain/reconstructionReadinessJourneyFindings.js +193 -0
  162. package/dist/domain/reconstructionReadinessSchemas.js +240 -0
  163. package/dist/domain/sourceToBundleComparison.js +335 -0
  164. package/dist/domain/sourceToBundleComparisonSchemas.js +133 -0
  165. package/dist/domain/sourceToBundleSignals.js +202 -0
  166. package/dist/domain/webCaptureDiff.js +141 -27
  167. package/dist/domain/webScreenshot.js +1 -1
  168. package/dist/domain/zipPackageFormat.js +20 -0
  169. package/dist/generatedPackageMetadata.js +1 -1
  170. package/dist/ghidra/GhidraDefaults.js +1 -1
  171. package/dist/ghidra/GhidraFunctionValues.js +13 -1
  172. package/dist/ghidra/GhidraProviderCapabilities.js +7 -0
  173. package/dist/hopper/HopperCleanup.js +158 -0
  174. package/dist/hopper/HopperClient.js +69 -99
  175. package/dist/hopper/HopperProvider.js +20 -1
  176. package/dist/hopper/HopperRequestQueue.js +187 -0
  177. package/dist/hopper/HopperResponseStream.js +46 -0
  178. package/dist/hopper/protocol.js +1 -0
  179. package/dist/main/transport.js +24 -24
  180. package/dist/main.js +6 -0
  181. package/dist/mcpDoctor.js +25 -2
  182. package/dist/native/NativeMacOSProvider.js +1 -0
  183. package/dist/process/ProcessCommandIdentity.js +19 -0
  184. package/dist/process/ProcessOwnership.js +11 -8
  185. package/dist/server/DynamicToolAvailability.js +70 -0
  186. package/dist/server/createServer.js +46 -1
  187. package/dist/server/lifecycleProgress.js +10 -0
  188. package/dist/server/permissionFailure.js +12 -0
  189. package/dist/server/registerApplicationTools/compareSourceToBundle.js +35 -0
  190. package/dist/server/registerApplicationTools/helpers.js +11 -7
  191. package/dist/server/registerApplicationTools/obligationLedger.js +27 -0
  192. package/dist/server/registerApplicationTools/readiness.js +55 -0
  193. package/dist/server/registerApplicationTools.js +6 -0
  194. package/dist/server/registerArtifactTools.js +9 -1
  195. package/dist/server/registerBrowserScenarioTool.js +25 -0
  196. package/dist/server/registerBrowserTools.js +2 -2
  197. package/dist/server/registerCloseLifecycleTool.js +57 -0
  198. package/dist/server/registerEnhancedTools.js +16 -5
  199. package/dist/server/registerEvidenceResources.js +4 -0
  200. package/dist/server/registerEvidenceTools.js +9 -2
  201. package/dist/server/registerJavaScriptRuntimeObservationTools.js +37 -0
  202. package/dist/server/registerReconstructionObligationLedgerResource.js +39 -0
  203. package/dist/server/registerReconstructionReadinessResource.js +39 -0
  204. package/dist/server/registerSessionStatusTool.js +11 -8
  205. package/dist/server/registerSessionTools.js +11 -57
  206. package/dist/server/sessionAvailabilityPolicy.js +10 -8
  207. package/package.json +12 -6
  208. package/skills/reverse-engineer-anything/SKILL.md +4 -3
  209. package/skills/reverse-engineer-anything/references/native-and-artifacts.md +2 -2
@@ -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
+ });
@@ -1,7 +1,134 @@
1
1
  import { createJavaScriptSemanticGraphUnknown } from "../domain/javascriptSemanticGraph.js";
2
- import { addSemanticGraphRelation, addSemanticGraphUnknown, } from "./JavaScriptSemanticGraphConstruction.js";
2
+ import { sourceRangesEqual } from "../domain/javascriptStaticAnalysisHelpers.js";
3
+ import { addSemanticGraphNode, addSemanticGraphRelation, addSemanticGraphUnknown, constructSemanticGraphNode, } from "./JavaScriptSemanticGraphConstruction.js";
3
4
  import { inferredSemanticEvidenceAt, unknownSemanticEvidence, } from "./JavaScriptSemanticGraphEvidence.js";
4
5
  import { semanticNodesWithinRange } from "./JavaScriptSemanticGraphProjection.js";
6
+ /** Find the retained call-site node at one exact semantic source range. */
7
+ export const semanticCallSiteAt = (context, location) => {
8
+ const call = context.ir.callSites.find(({ location: candidate }) => sourceRangesEqual(candidate, location));
9
+ return call === undefined
10
+ ? undefined
11
+ : context.callSiteNodes.get(call.callSiteId);
12
+ };
13
+ /** Project explicit static Promise/task ownership without runtime claims. */
14
+ export const projectSemanticPromises = (context) => {
15
+ const promiseNodes = new Map(context.ir.promiseOperations.flatMap((operation) => {
16
+ const owner = operation.ownerCallableId === null
17
+ ? undefined
18
+ : context.callableNodes.get(operation.ownerCallableId);
19
+ const node = addSemanticGraphNode(context.state, constructSemanticGraphNode(context.file, {
20
+ kind: operation.kind === "awaited-expression" ? "task" : "promise",
21
+ roleKey: operation.promiseId,
22
+ location: operation.location,
23
+ label: promiseLabel(operation),
24
+ functionNodeId: owner?.node_id ?? null,
25
+ properties: {
26
+ method: operation.method,
27
+ operation_kind: operation.kind,
28
+ ownership: operation.ownership,
29
+ source_resolution: operation.sourceResolution,
30
+ },
31
+ }, context.state));
32
+ return node === null ? [] : [[operation.promiseId, node]];
33
+ }));
34
+ for (const operation of context.ir.promiseOperations) {
35
+ const promise = promiseNodes.get(operation.promiseId);
36
+ if (promise === undefined)
37
+ continue;
38
+ projectPromiseCreation(context, operation, promise);
39
+ projectPromiseSources(context, operation, promise, promiseNodes);
40
+ projectPromiseOwnership(context, operation, promise);
41
+ if (operation.sourceResolution !== "complete" &&
42
+ ["chain", "aggregate", "awaited-expression"].includes(operation.kind))
43
+ addPromiseUnknown(context, operation, promise, promiseNodes);
44
+ }
45
+ };
46
+ const promiseLabel = (operation) => operation.kind === "awaited-expression"
47
+ ? "awaited expression"
48
+ : `Promise.${operation.method}`;
49
+ const projectPromiseCreation = (context, operation, promise) => {
50
+ if (operation.kind === "awaited-expression")
51
+ return;
52
+ addSemanticGraphRelation(context.state, {
53
+ source: semanticCallSiteAt(context, operation.location),
54
+ target: promise,
55
+ relation: "creates-promise",
56
+ resolution: operation.kind === "chain" || operation.sourceResolution !== "complete"
57
+ ? "candidate"
58
+ : "resolved",
59
+ });
60
+ };
61
+ const projectPromiseSources = (context, operation, promise, promiseNodes) => {
62
+ for (const sourceId of operation.sourcePromiseIds) {
63
+ const source = promiseNodes.get(sourceId);
64
+ if (operation.kind === "aggregate")
65
+ addSemanticGraphRelation(context.state, {
66
+ source: promise,
67
+ target: source,
68
+ relation: "aggregates",
69
+ resolution: operation.sourceResolution === "complete" ? "resolved" : "candidate",
70
+ });
71
+ else
72
+ addSemanticGraphRelation(context.state, {
73
+ source,
74
+ target: promise,
75
+ relation: "chains",
76
+ resolution: operation.sourceResolution === "complete" ? "resolved" : "candidate",
77
+ });
78
+ }
79
+ };
80
+ const projectPromiseOwnership = (context, operation, promise) => {
81
+ const owner = operation.ownerCallableId === null
82
+ ? context.moduleNode
83
+ : context.callableNodes.get(operation.ownerCallableId);
84
+ if (operation.ownership === "awaited")
85
+ addSemanticGraphRelation(context.state, {
86
+ source: owner,
87
+ target: promise,
88
+ relation: "awaits",
89
+ resolution: "resolved",
90
+ });
91
+ else if (operation.ownership === "assigned")
92
+ addSemanticGraphRelation(context.state, {
93
+ source: operation.ownerBindingId === null
94
+ ? undefined
95
+ : context.bindingNodes.get(operation.ownerBindingId),
96
+ target: promise,
97
+ relation: "owns",
98
+ resolution: "resolved",
99
+ });
100
+ else if (operation.ownership === "returned")
101
+ addSemanticGraphRelation(context.state, {
102
+ source: operation.returnSiteId === null
103
+ ? undefined
104
+ : context.returnSiteNodes.get(operation.returnSiteId),
105
+ target: promise,
106
+ relation: "returns-task",
107
+ resolution: "resolved",
108
+ });
109
+ else if (operation.ownership === "detached")
110
+ addSemanticGraphRelation(context.state, {
111
+ source: owner,
112
+ target: promise,
113
+ relation: "detaches-task",
114
+ resolution: "resolved",
115
+ });
116
+ };
117
+ const addPromiseUnknown = (context, operation, promise, promiseNodes) => {
118
+ const relation = operation.kind === "aggregate" ? "aggregates" : "chains";
119
+ addSemanticGraphUnknown(context.state, createJavaScriptSemanticGraphUnknown({
120
+ node_id: promise.node_id,
121
+ family: "promise-ownership",
122
+ relation_kinds: [relation],
123
+ reason: "ambiguous-target",
124
+ detail: `Static ${operation.method} source resolution was ${operation.sourceResolution}.`,
125
+ candidate_node_ids: operation.sourcePromiseIds.flatMap((identifier) => {
126
+ const candidate = promiseNodes.get(identifier);
127
+ return candidate === undefined ? [] : [candidate.node_id];
128
+ }),
129
+ evidence: unknownSemanticEvidence(context.file, operation.location),
130
+ }));
131
+ };
5
132
  /** Link direct return expressions to their retained semantic references. */
6
133
  export const projectSemanticReturnValues = (context) => {
7
134
  for (const callable of context.ir.callables)
@@ -14,18 +141,12 @@ export const projectSemanticReturnValues = (context) => {
14
141
  target: returnNode,
15
142
  relation: "aliases",
16
143
  resolution: site.identityReferenceLocation !== null &&
17
- rangesEqual(reference.identity.source_range, site.identityReferenceLocation)
144
+ sourceRangesEqual(reference.identity.source_range, site.identityReferenceLocation)
18
145
  ? "resolved"
19
146
  : "candidate",
20
147
  });
21
148
  }
22
149
  };
23
- const rangesEqual = (left, right) => left !== null &&
24
- right !== null &&
25
- left.start.line === right.start.line &&
26
- left.start.column === right.start.column &&
27
- left.end.line === right.end.line &&
28
- left.end.column === right.end.column;
29
150
  /** Link each captured binding to the callable at the exact reference site. */
30
151
  export const projectSemanticClosureCaptures = (context) => {
31
152
  for (const capture of context.ir.closureCaptures)