rea-agents 2.4.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 (186) 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/BinarySession.js +15 -4
  7. package/dist/application/BinarySessionStatus.js +31 -1
  8. package/dist/application/BrowserEvidence.js +14 -0
  9. package/dist/application/BrowserScenarioCapturePort.js +1 -0
  10. package/dist/application/BrowserScenarioCaptureService.js +53 -0
  11. package/dist/application/BrowserScenarioEvidence.js +40 -0
  12. package/dist/application/CallPathTracing.js +160 -0
  13. package/dist/application/CapabilityInventory.js +68 -12
  14. package/dist/application/CompositeProvider.js +10 -1
  15. package/dist/application/DirectAnalysis.js +7 -2
  16. package/dist/application/EnhancedLiteralTracing.js +118 -0
  17. package/dist/application/EnhancedTools.js +35 -121
  18. package/dist/application/JavaScriptApplicationWorkflowEvidence.js +13 -0
  19. package/dist/application/JavaScriptApplicationWorkflowService.js +27 -1
  20. package/dist/application/JavaScriptRuntimeObservationEvidence.js +34 -0
  21. package/dist/application/JavaScriptRuntimeObservationPort.js +1 -0
  22. package/dist/application/JavaScriptRuntimeObservationService.js +46 -0
  23. package/dist/application/JavaScriptSemanticGraphAsyncProjection.js +147 -0
  24. package/dist/application/JavaScriptSemanticGraphBuilder.js +34 -6
  25. package/dist/application/JavaScriptSemanticGraphChildProcessProjection.js +156 -0
  26. package/dist/application/JavaScriptSemanticGraphConstruction.js +2 -2
  27. package/dist/application/JavaScriptSemanticGraphDataProjection.js +203 -0
  28. package/dist/application/JavaScriptSemanticGraphFingerprintProjection.js +25 -0
  29. package/dist/application/JavaScriptSemanticGraphFlowProjection.js +129 -8
  30. package/dist/application/JavaScriptSemanticGraphObjectProjection.js +81 -0
  31. package/dist/application/JavaScriptSemanticGraphProjection.js +14 -7
  32. package/dist/application/JavaScriptSemanticGraphResourceProjection.js +59 -0
  33. package/dist/application/JavaScriptSemanticGraphValueProjection.js +77 -0
  34. package/dist/application/ProcessReactiveEffects.js +6 -0
  35. package/dist/application/ProcessReactiveHarness.js +16 -1
  36. package/dist/application/ProjectPermissionStore.js +1 -0
  37. package/dist/application/ReconstructionObligationAuthority.js +72 -0
  38. package/dist/application/ReconstructionObligationCandidates.js +265 -0
  39. package/dist/application/ReconstructionObligationLedgerDiagnostics.js +47 -0
  40. package/dist/application/ReconstructionObligationLedgerEvaluation.js +263 -0
  41. package/dist/application/ReconstructionObligationLedgerProjection.js +86 -0
  42. package/dist/application/ReconstructionObligationLedgerService.js +72 -0
  43. package/dist/application/ReconstructionObligationOriginalCases.js +33 -0
  44. package/dist/application/ReconstructionObligationPolicies.js +132 -0
  45. package/dist/application/ReconstructionReadinessService.js +48 -0
  46. package/dist/artifacts/ArtifactProvider.js +87 -22
  47. package/dist/browser/BrowserScenarioSecrets.js +53 -0
  48. package/dist/browser/BrowserScenarioSessionPort.js +1 -0
  49. package/dist/browser/CdpBrowserProvider.js +2 -2
  50. package/dist/browser/CdpCaptureDocuments.js +57 -0
  51. package/dist/browser/CdpCaptureStorage.js +71 -29
  52. package/dist/browser/CdpCaptureStorageFingerprints.js +328 -0
  53. package/dist/browser/CdpEndpoint.js +8 -6
  54. package/dist/browser/CdpPageCapture.js +2 -0
  55. package/dist/browser/JavaScriptRuntimeScope.js +38 -0
  56. package/dist/browser/PlaywrightBrowserScenarioProvider.js +253 -0
  57. package/dist/browser/PlaywrightExecutionBoundary.js +42 -0
  58. package/dist/browser/PlaywrightScenarioActions.js +62 -0
  59. package/dist/browser/PlaywrightScenarioArtifacts.js +238 -0
  60. package/dist/browser/PlaywrightScenarioBrowser.js +144 -0
  61. package/dist/browser/PlaywrightScenarioEvents.js +301 -0
  62. package/dist/browser/PlaywrightScenarioSession.js +300 -0
  63. package/dist/browser/V8InspectorCaptureProjection.js +110 -0
  64. package/dist/browser/V8InspectorEndpoint.js +72 -0
  65. package/dist/browser/V8InspectorProvider.js +267 -0
  66. package/dist/catalogIdentity.js +8 -0
  67. package/dist/cli/artifactCommands.js +39 -0
  68. package/dist/cli/coreAnalysisCommands.js +37 -0
  69. package/dist/cli.js +4 -0
  70. package/dist/cliApplicationCommands.js +30 -2
  71. package/dist/cliBrowserAdvancedCommands.js +17 -5
  72. package/dist/cliBrowserCommands.js +1 -0
  73. package/dist/cliBrowserScenarioCommands.js +43 -0
  74. package/dist/cliCommandNames.js +8 -0
  75. package/dist/cliJavaScriptRuntimeCommands.js +164 -0
  76. package/dist/cliObservationOptions.js +4 -0
  77. package/dist/cliPolicyCommands.js +1 -0
  78. package/dist/config/environment.js +12 -0
  79. package/dist/config/parseConfig.js +88 -17
  80. package/dist/contracts/analysisSearchContract.js +14 -0
  81. package/dist/contracts/applicationToolContracts.js +86 -2
  82. package/dist/contracts/applicationWorkflowInputContracts.js +18 -0
  83. package/dist/contracts/artifactToolContracts.js +22 -0
  84. package/dist/contracts/browserProviderToolContracts.js +7 -0
  85. package/dist/contracts/browserScenarioToolContracts.js +81 -0
  86. package/dist/contracts/browserToolContracts.js +88 -98
  87. package/dist/contracts/enhancedInputs.js +25 -6
  88. package/dist/contracts/functionInstructionContract.js +8 -0
  89. package/dist/contracts/hopperMemoryContracts.js +22 -0
  90. package/dist/contracts/javascriptApplicationWorkflowExamples.js +42 -0
  91. package/dist/contracts/javascriptRuntimeObservationToolContracts.js +58 -0
  92. package/dist/contracts/reconstructionReadinessExample.js +436 -0
  93. package/dist/contracts/toolContractExamples.js +5 -0
  94. package/dist/contracts/toolContractTypes.js +1 -0
  95. package/dist/contracts/toolContracts.js +13 -21
  96. package/dist/contracts/toolEffects.js +21 -0
  97. package/dist/contracts/toolOutputSchemaGroups.js +70 -20
  98. package/dist/contracts/toolOutputSchemaPrimitives.js +37 -0
  99. package/dist/domain/analysisErrorProjection.js +8 -0
  100. package/dist/domain/artifactInspection.js +347 -0
  101. package/dist/domain/browserCaptureComparison.js +82 -0
  102. package/dist/domain/browserObservation.js +8 -1
  103. package/dist/domain/browserObservationErrors.js +1 -0
  104. package/dist/domain/browserObservationSchemas.js +26 -0
  105. package/dist/domain/browserScenario.js +165 -0
  106. package/dist/domain/browserScenarioCapture.js +57 -0
  107. package/dist/domain/browserScenarioCaptureValues.js +204 -0
  108. package/dist/domain/browserScenarioDiff.js +324 -0
  109. package/dist/domain/browserScenarioDiffValues.js +157 -0
  110. package/dist/domain/browserScenarioNormalization.js +45 -0
  111. package/dist/domain/browserScenarioValues.js +372 -0
  112. package/dist/domain/hopperValues.js +10 -0
  113. package/dist/domain/javascriptRuntimeObservation.js +170 -0
  114. package/dist/domain/javascriptRuntimeReconciliationParsing.js +120 -2
  115. package/dist/domain/javascriptRuntimeReconciliationResult.js +3 -3
  116. package/dist/domain/javascriptRuntimeReconciliationRuntime.js +2 -2
  117. package/dist/domain/javascriptRuntimeReconciliationSchemas.js +1 -1
  118. package/dist/domain/javascriptSemanticAnalysis.js +5 -4
  119. package/dist/domain/javascriptSemanticAsyncEffects.js +253 -0
  120. package/dist/domain/javascriptSemanticChildProcesses.js +237 -0
  121. package/dist/domain/javascriptSemanticDataEffectHelpers.js +125 -0
  122. package/dist/domain/javascriptSemanticDataEffects.js +284 -0
  123. package/dist/domain/javascriptSemanticDerivedAnalysis.js +41 -0
  124. package/dist/domain/javascriptSemanticFingerprints.js +174 -0
  125. package/dist/domain/javascriptSemanticIr.js +21 -1
  126. package/dist/domain/javascriptSemanticObjects.js +115 -0
  127. package/dist/domain/javascriptSemanticPromises.js +290 -0
  128. package/dist/domain/javascriptSemanticResources.js +136 -0
  129. package/dist/domain/javascriptStaticAnalysis.js +4 -3
  130. package/dist/domain/javascriptStaticAnalysisBundler.js +38 -0
  131. package/dist/domain/javascriptStaticAnalysisCalls.js +23 -1
  132. package/dist/domain/javascriptStaticAnalysisHelpers.js +8 -0
  133. package/dist/domain/processCapture.js +8 -2
  134. package/dist/domain/processReactiveScenario.js +1 -0
  135. package/dist/domain/processReactiveTransition.js +9 -4
  136. package/dist/domain/providerCleanupError.js +11 -0
  137. package/dist/domain/reconstructionObligationLedgerSchemas.js +278 -0
  138. package/dist/domain/reconstructionReadiness.js +121 -0
  139. package/dist/domain/reconstructionReadinessFindingHelpers.js +17 -0
  140. package/dist/domain/reconstructionReadinessIntegrityFindings.js +118 -0
  141. package/dist/domain/reconstructionReadinessJourneyFindings.js +193 -0
  142. package/dist/domain/reconstructionReadinessSchemas.js +240 -0
  143. package/dist/domain/sourceToBundleComparison.js +335 -0
  144. package/dist/domain/sourceToBundleComparisonSchemas.js +133 -0
  145. package/dist/domain/sourceToBundleSignals.js +202 -0
  146. package/dist/domain/webCaptureDiff.js +141 -27
  147. package/dist/domain/webScreenshot.js +1 -1
  148. package/dist/generatedPackageMetadata.js +1 -1
  149. package/dist/ghidra/GhidraDefaults.js +1 -1
  150. package/dist/ghidra/GhidraFunctionValues.js +13 -1
  151. package/dist/ghidra/GhidraProviderCapabilities.js +7 -0
  152. package/dist/hopper/HopperCleanup.js +158 -0
  153. package/dist/hopper/HopperClient.js +69 -99
  154. package/dist/hopper/HopperProvider.js +20 -1
  155. package/dist/hopper/HopperRequestQueue.js +187 -0
  156. package/dist/hopper/HopperResponseStream.js +46 -0
  157. package/dist/hopper/protocol.js +1 -0
  158. package/dist/main/transport.js +24 -24
  159. package/dist/main.js +6 -0
  160. package/dist/mcpDoctor.js +25 -2
  161. package/dist/process/ProcessCommandIdentity.js +19 -0
  162. package/dist/process/ProcessOwnership.js +11 -8
  163. package/dist/server/DynamicToolAvailability.js +70 -0
  164. package/dist/server/createServer.js +46 -1
  165. package/dist/server/lifecycleProgress.js +10 -0
  166. package/dist/server/permissionFailure.js +12 -0
  167. package/dist/server/registerApplicationTools/compareSourceToBundle.js +35 -0
  168. package/dist/server/registerApplicationTools/helpers.js +11 -7
  169. package/dist/server/registerApplicationTools/obligationLedger.js +27 -0
  170. package/dist/server/registerApplicationTools/readiness.js +55 -0
  171. package/dist/server/registerApplicationTools.js +6 -0
  172. package/dist/server/registerArtifactTools.js +9 -1
  173. package/dist/server/registerBrowserScenarioTool.js +25 -0
  174. package/dist/server/registerBrowserTools.js +2 -2
  175. package/dist/server/registerCloseLifecycleTool.js +57 -0
  176. package/dist/server/registerEnhancedTools.js +16 -5
  177. package/dist/server/registerEvidenceResources.js +4 -0
  178. package/dist/server/registerEvidenceTools.js +9 -2
  179. package/dist/server/registerJavaScriptRuntimeObservationTools.js +37 -0
  180. package/dist/server/registerReconstructionObligationLedgerResource.js +39 -0
  181. package/dist/server/registerReconstructionReadinessResource.js +39 -0
  182. package/dist/server/registerSessionStatusTool.js +11 -8
  183. package/dist/server/registerSessionTools.js +11 -57
  184. package/dist/server/sessionAvailabilityPolicy.js +10 -8
  185. package/package.json +12 -6
  186. package/skills/reverse-engineer-anything/SKILL.md +2 -2
@@ -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)
@@ -0,0 +1,81 @@
1
+ import { createJavaScriptSemanticGraphUnknown } from "../domain/javascriptSemanticGraph.js";
2
+ import { addSemanticGraphNode, addSemanticGraphRelation, addSemanticGraphUnknown, constructSemanticGraphNode, } from "./JavaScriptSemanticGraphConstruction.js";
3
+ import { unknownSemanticEvidence } from "./JavaScriptSemanticGraphEvidence.js";
4
+ import { semanticPropertySlot } from "./JavaScriptSemanticGraphValueProjection.js";
5
+ /** Project static object reads, writes, spreads, and destructuring. */
6
+ export const projectSemanticObjects = (context) => {
7
+ for (const operation of context.ir.objectOperations) {
8
+ const occurrence = addObjectOccurrence(context, operation);
9
+ const slot = operation.objectBindingId === null || operation.propertyName === null
10
+ ? null
11
+ : semanticPropertySlot(context, operation.objectBindingId, operation.propertyName);
12
+ if (operation.kind === "read")
13
+ addSemanticGraphRelation(context.state, {
14
+ source: slot,
15
+ target: occurrence,
16
+ relation: "reads-property",
17
+ resolution: operation.resolution === "complete" ? "resolved" : "candidate",
18
+ });
19
+ else if (operation.kind === "write")
20
+ addSemanticGraphRelation(context.state, {
21
+ source: occurrence,
22
+ target: slot,
23
+ relation: "writes-property",
24
+ resolution: operation.resolution === "complete" ? "resolved" : "candidate",
25
+ });
26
+ else if (operation.kind === "destructure")
27
+ addSemanticGraphRelation(context.state, {
28
+ source: slot,
29
+ target: operation.targetBindingId === null
30
+ ? undefined
31
+ : context.bindingNodes.get(operation.targetBindingId),
32
+ relation: "destructures",
33
+ resolution: operation.resolution === "complete" ? "resolved" : "candidate",
34
+ });
35
+ else
36
+ addSemanticGraphRelation(context.state, {
37
+ source: operation.objectBindingId === null
38
+ ? undefined
39
+ : context.bindingNodes.get(operation.objectBindingId),
40
+ target: occurrence,
41
+ relation: "spreads",
42
+ resolution: operation.resolution === "complete" ? "resolved" : "candidate",
43
+ });
44
+ if (operation.resolution !== "complete")
45
+ addObjectUnknown(context, operation, slot ?? occurrence);
46
+ }
47
+ };
48
+ const addObjectOccurrence = (context, operation) => addSemanticGraphNode(context.state, constructSemanticGraphNode(context.file, {
49
+ kind: "expression",
50
+ roleKey: operation.objectOperationId,
51
+ location: operation.location,
52
+ label: operation.propertyName === null
53
+ ? operation.kind
54
+ : `${operation.kind}:${operation.propertyName}`,
55
+ functionNodeId: operation.ownerCallableId === null
56
+ ? null
57
+ : (context.callableNodes.get(operation.ownerCallableId)?.node_id ??
58
+ null),
59
+ properties: {
60
+ operation_kind: operation.kind,
61
+ property_name: operation.propertyName,
62
+ },
63
+ }, context.state));
64
+ const addObjectUnknown = (context, operation, node) => {
65
+ const relation = operation.kind === "read"
66
+ ? "reads-property"
67
+ : operation.kind === "write"
68
+ ? "writes-property"
69
+ : operation.kind === "spread"
70
+ ? "spreads"
71
+ : "destructures";
72
+ addSemanticGraphUnknown(context.state, createJavaScriptSemanticGraphUnknown({
73
+ node_id: node?.node_id ?? null,
74
+ family: "object-flow",
75
+ relation_kinds: [relation],
76
+ reason: "ambiguous-target",
77
+ detail: `Static ${operation.kind} object identity is partial.`,
78
+ candidate_node_ids: [],
79
+ evidence: unknownSemanticEvidence(context.file, operation.location),
80
+ }));
81
+ };
@@ -15,18 +15,25 @@ export const semanticNodesWithinRange = (nodes, range) => nodes.filter((node) =>
15
15
  contains(range, node.identity.source_range));
16
16
  /** Report extractor support without treating missing families as absence. */
17
17
  export const semanticFamilyStatus = (family, analysis, truncated) => {
18
- if (!["call-flow", "closure", "data-flow", "object-flow"].includes(family))
18
+ if (![
19
+ "call-flow",
20
+ "boundary",
21
+ "child-process",
22
+ "closure",
23
+ "configuration",
24
+ "data-flow",
25
+ "event",
26
+ "object-flow",
27
+ "promise-ownership",
28
+ "request",
29
+ "resource-lifecycle",
30
+ "timer",
31
+ ].includes(family))
19
32
  return "unsupported";
20
33
  if (truncated)
21
34
  return "unknown";
22
35
  return analysis.truncated_scopes === 0 ? "partial" : "unknown";
23
36
  };
24
- /** Compare two exact semantic source ranges. */
25
- export const semanticRangesEqual = (left, right) => left !== null &&
26
- left.start.line === right.start.line &&
27
- left.start.column === right.start.column &&
28
- left.end.line === right.end.line &&
29
- left.end.column === right.end.column;
30
37
  const contains = (outer, inner) => pointCompare(outer.start, inner.start) <= 0 &&
31
38
  pointCompare(outer.end, inner.end) >= 0;
32
39
  const pointCompare = (left, right) => left.line - right.line || left.column - right.column;