rea-agents 2.5.0 → 3.1.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 (253) hide show
  1. package/README.md +20 -12
  2. package/bridge/ghidra/ReaGhidraBridge.java +477 -4
  3. package/bridge/hopper_bridge.py +54 -4
  4. package/dist/application/AnalysisContextQueries.js +142 -0
  5. package/dist/application/AnalysisSnapshotCache.js +4 -2
  6. package/dist/application/ApplicationWorkflowEvidenceResolver.js +19 -11
  7. package/dist/application/ArtifactInventory/policy.js +17 -0
  8. package/dist/application/ArtifactInventory/reader.js +1 -4
  9. package/dist/application/ArtifactInventory/scanCanonical.js +0 -3
  10. package/dist/application/ArtifactInventory/scanReader.js +7 -7
  11. package/dist/application/ArtifactInventory/types.js +1 -5
  12. package/dist/application/BinarySession.js +19 -20
  13. package/dist/application/BinarySessionComposition.js +21 -0
  14. package/dist/application/BinarySessionRecords.js +106 -10
  15. package/dist/application/BinarySessionStatus.js +11 -5
  16. package/dist/application/BrowserEvidence.js +3 -5
  17. package/dist/application/CapabilityClientRequirements.js +26 -0
  18. package/dist/application/CapabilityInventory.js +140 -55
  19. package/dist/application/ClientRegistrationStatus.js +4 -1
  20. package/dist/application/CrossVersionInventory.js +7 -6
  21. package/dist/application/DirectAnalysis.js +6 -2
  22. package/dist/application/ElectronActiveEvidence.js +55 -0
  23. package/dist/application/ElectronActiveObservationPort.js +1 -0
  24. package/dist/application/ElectronActiveObservationService.js +81 -0
  25. package/dist/application/EnhancedTools.js +49 -17
  26. package/dist/application/EvidenceBundleCommands.js +5 -1
  27. package/dist/application/EvidenceLedger.js +53 -17
  28. package/dist/application/JavaScriptArtifactAnalysis.js +13 -4
  29. package/dist/application/JavaScriptReplayPermission.js +1 -1
  30. package/dist/application/JavaScriptReplayService.js +23 -15
  31. package/dist/application/LazyAnalysisProvider.js +77 -0
  32. package/dist/application/LoopbackReplay.js +1 -1
  33. package/dist/application/ManagedRuntimeCorrelationService.js +9 -5
  34. package/dist/application/NativeApiInspection.js +80 -0
  35. package/dist/application/NodeRuntimeCharacterizationService.js +8 -9
  36. package/dist/application/ProcessCaptureLifecycle.js +5 -0
  37. package/dist/application/ProcessCli.js +2 -1
  38. package/dist/application/ProcessHarness.js +8 -3
  39. package/dist/application/ProcessNormalization.js +2 -1
  40. package/dist/application/ProjectPermissionStore.js +1 -0
  41. package/dist/application/ReferenceSourceImport.js +2 -2
  42. package/dist/application/SessionProviderRouter.js +6 -6
  43. package/dist/application/SetupClientConfiguration.js +10 -3
  44. package/dist/application/WindowsCapabilities.js +5 -4
  45. package/dist/application/runtime.js +26 -9
  46. package/dist/artifacts/ArtifactProvider.js +8 -10
  47. package/dist/artifacts/SafeOutputTree.js +7 -8
  48. package/dist/browser/CdpCaptureStorageFingerprints.js +10 -7
  49. package/dist/browser/CdpElectronInspection.js +3 -1
  50. package/dist/browser/JavaScriptRuntimeScope.js +5 -0
  51. package/dist/browser/PlaywrightBrowserScenarioProvider.js +8 -2
  52. package/dist/browser/PlaywrightElectronActiveActions.js +324 -0
  53. package/dist/browser/PlaywrightElectronActiveProvider.js +294 -0
  54. package/dist/browser/PlaywrightScenarioBrowser.js +4 -4
  55. package/dist/browser/PlaywrightScenarioSession.js +4 -4
  56. package/dist/browser/SensitiveTextCapture.js +1 -1
  57. package/dist/browser/V8InspectorCaptureProjection.js +1 -0
  58. package/dist/browser/V8InspectorProvider.js +3 -3
  59. package/dist/catalogIdentity.js +15 -9
  60. package/dist/cli/artifactCommands.js +5 -3
  61. package/dist/cli/coreAnalysisCommands.js +41 -0
  62. package/dist/cli/managedCommands.js +1 -1
  63. package/dist/cliApplicationCommands.js +2 -2
  64. package/dist/cliBrowserAdvancedCommands.js +11 -5
  65. package/dist/cliBrowserCommands.js +14 -7
  66. package/dist/cliCommandNames.js +2 -0
  67. package/dist/cliElectronCommands.js +46 -4
  68. package/dist/cliJavaScriptRuntimeCommands.js +14 -6
  69. package/dist/cliObservationOptions.js +4 -0
  70. package/dist/cliPolicyCommands.js +1 -0
  71. package/dist/config/browserScenario.js +77 -0
  72. package/dist/config/electronAutomation.js +35 -0
  73. package/dist/config/environment.js +6 -0
  74. package/dist/config/javascriptReplay.js +41 -0
  75. package/dist/config/managedRuntime.js +25 -0
  76. package/dist/config/parseConfig.js +56 -200
  77. package/dist/config/parsers.js +10 -1
  78. package/dist/config/passiveObservation.js +157 -0
  79. package/dist/config/processCapture.js +47 -0
  80. package/dist/contracts/applicationToolContracts.js +2 -5
  81. package/dist/contracts/applicationWorkflowInputContracts.js +86 -96
  82. package/dist/contracts/artifactToolContracts.js +35 -37
  83. package/dist/contracts/browserToolContracts.js +2 -2
  84. package/dist/contracts/electronToolContracts.js +30 -1
  85. package/dist/contracts/enhancedInputs.js +21 -27
  86. package/dist/contracts/functionWorkflowToolContracts.js +29 -0
  87. package/dist/contracts/managedToolContracts.js +4 -9
  88. package/dist/contracts/managedWorkflowExamples.js +12 -9
  89. package/dist/contracts/managedWorkflowToolContracts.js +30 -27
  90. package/dist/contracts/nativeToolContracts.js +2 -3
  91. package/dist/contracts/promptContracts.js +14 -15
  92. package/dist/contracts/sessionToolSchemas.js +61 -0
  93. package/dist/contracts/toolContractExamples.js +4 -0
  94. package/dist/contracts/toolContractHelpers.js +23 -0
  95. package/dist/contracts/toolContracts.js +12 -67
  96. package/dist/contracts/toolEffects.js +19 -0
  97. package/dist/contracts/toolOutputSchemaGroups.js +66 -11
  98. package/dist/contracts/toolOutputSchemaPrimitives.js +76 -26
  99. package/dist/contracts/toolSchemaMetadata.js +128 -0
  100. package/dist/doctorRuntime.js +1 -1
  101. package/dist/domain/analysisErrorPresentation.js +8 -2
  102. package/dist/domain/analysisErrorProjection.js +1 -0
  103. package/dist/domain/androidApplication.js +2 -0
  104. package/dist/domain/appleApplication.js +2 -0
  105. package/dist/domain/binaryTarget.js +7 -5
  106. package/dist/domain/binaryTargetTypes.js +1 -0
  107. package/dist/domain/browserCaptureComparison.js +21 -69
  108. package/dist/domain/browserObservation.js +22 -9
  109. package/dist/domain/bytecodeProvider.js +177 -0
  110. package/dist/domain/callPath.js +3 -2
  111. package/dist/domain/conformancePackage.js +169 -0
  112. package/dist/domain/conformanceReplay.js +104 -0
  113. package/dist/domain/conformanceTrustGate.js +328 -0
  114. package/dist/domain/customProtocolCapture.js +137 -0
  115. package/dist/domain/electronActiveObservation.js +277 -0
  116. package/dist/domain/electronObservation.js +15 -11
  117. package/dist/domain/electronStaticAnalysisValues.js +4 -1
  118. package/dist/domain/eventProcessTree.js +217 -0
  119. package/dist/domain/evidenceBundle.js +47 -0
  120. package/dist/domain/functionComparisonNormalization.js +15 -8
  121. package/dist/domain/functionDossierEvidence.js +9 -4
  122. package/dist/domain/hopperStartupFailure.js +1 -1
  123. package/dist/domain/hopperValues.js +68 -68
  124. package/dist/domain/inputIssueProjection.js +11 -2
  125. package/dist/domain/investigationWorkspace.js +16 -15
  126. package/dist/domain/javascriptExportShapeComparisonSchemas.js +2 -2
  127. package/dist/domain/javascriptReplay.js +79 -63
  128. package/dist/domain/javascriptRuntimeObservation.js +1 -0
  129. package/dist/domain/javascriptRuntimeReconciliationActive.js +89 -0
  130. package/dist/domain/javascriptRuntimeReconciliationGraph.js +11 -10
  131. package/dist/domain/javascriptRuntimeReconciliationMatching.js +57 -49
  132. package/dist/domain/javascriptRuntimeReconciliationParsing.js +5 -1
  133. package/dist/domain/javascriptRuntimeReconciliationResult.js +21 -14
  134. package/dist/domain/javascriptRuntimeReconciliationSchemas.js +1 -1
  135. package/dist/domain/javascriptSemanticAnalysis.js +8 -12
  136. package/dist/domain/javascriptSourceParser.js +15 -0
  137. package/dist/domain/javascriptStaticAnalysis.js +8 -12
  138. package/dist/domain/knownPageCoverage.js +15 -7
  139. package/dist/domain/mobileApplicationInvestigation.js +159 -0
  140. package/dist/domain/nativeApiBoundary.js +138 -0
  141. package/dist/domain/nodeRuntimeCharacterization.js +14 -13
  142. package/dist/domain/objcSwiftMetadata.js +150 -0
  143. package/dist/domain/packageAnalysis.js +123 -0
  144. package/dist/domain/peInspection.js +196 -0
  145. package/dist/domain/processCaptureReactiveValidation.js +8 -3
  146. package/dist/domain/processCaptureValidation.js +7 -3
  147. package/dist/domain/processComparison.js +12 -7
  148. package/dist/domain/processObservation.js +5 -6
  149. package/dist/domain/processReactiveMatching.js +14 -7
  150. package/dist/domain/processReactiveTransition.js +9 -3
  151. package/dist/domain/processScenario.js +6 -3
  152. package/dist/domain/processTraceComparison.js +3 -2
  153. package/dist/domain/protocolCapture.js +245 -0
  154. package/dist/domain/reconstructionReadinessSchemas.js +30 -2
  155. package/dist/domain/referenceSourceImportParsing.js +2 -2
  156. package/dist/domain/replayMachineRuntime.js +5 -3
  157. package/dist/domain/sourceToBundleComparison.js +2 -2
  158. package/dist/domain/sourceToBundleComparisonSchemas.js +8 -8
  159. package/dist/domain/sourceToBundleSignals.js +7 -1
  160. package/dist/domain/staticRuntimeCorrelation.js +7 -5
  161. package/dist/domain/webBundleAnalysis.js +14 -14
  162. package/dist/domain/webCaptureDiff.js +15 -12
  163. package/dist/dotnet/ManagedNativeBoundaryInspector.js +2 -3
  164. package/dist/dotnet/ManagedStaticProvider.js +34 -5
  165. package/dist/generatedMcpToolCatalog.js +37 -0
  166. package/dist/generatedPackageMetadata.js +4 -4
  167. package/dist/ghidra/GhidraClient.js +1 -1
  168. package/dist/ghidra/GhidraClientStartup.js +1 -1
  169. package/dist/ghidra/GhidraDefaults.js +1 -1
  170. package/dist/ghidra/GhidraFunctionValues.js +44 -16
  171. package/dist/ghidra/GhidraInventoryValues.js +57 -47
  172. package/dist/ghidra/GhidraProvider.js +18 -10
  173. package/dist/ghidra/GhidraProviderCapabilities.js +45 -39
  174. package/dist/ghidra/GhidraSocketConnection.js +1 -1
  175. package/dist/ghidra/protocol.js +19 -42
  176. package/dist/hopper/BridgeLauncher.js +3 -1
  177. package/dist/hopper/HopperAnalysisProfile.js +2 -4
  178. package/dist/hopper/HopperCleanup.js +5 -6
  179. package/dist/hopper/HopperClient.js +27 -3
  180. package/dist/hopper/HopperProvider.js +42 -44
  181. package/dist/hopper/HopperRequestQueue.js +32 -4
  182. package/dist/hopper/HopperResponseStream.js +2 -2
  183. package/dist/hopper/LinuxPrivateDisplayProbe.js +16 -10
  184. package/dist/hopper/protocol.js +63 -21
  185. package/dist/main/reload.js +1 -6
  186. package/dist/main/state.js +0 -14
  187. package/dist/main/transport.js +31 -41
  188. package/dist/main.js +17 -13
  189. package/dist/mcpDoctor.js +4 -26
  190. package/dist/mcpStartupPolicy.js +14 -0
  191. package/dist/process/PrivateRuntimeRoot.js +17 -0
  192. package/dist/process/ProcessOwnership.js +64 -128
  193. package/dist/process/ProcessOwnershipIdentity.js +13 -0
  194. package/dist/process/ProcessOwnershipObservation.js +88 -0
  195. package/dist/process/ProcessOwnershipProcessTree.js +22 -0
  196. package/dist/process/ProviderDeadline.js +8 -12
  197. package/dist/process/WindowsAuthority.js +32 -0
  198. package/dist/reference/ReferenceSourceReader.js +3 -3
  199. package/dist/reference/ReferenceSourceReaderEntries.js +2 -2
  200. package/dist/replay/JavaScriptReplayWorker.js +95 -11
  201. package/dist/replay/JavaScriptReplayWorkerTypes.js +1 -0
  202. package/dist/replay/LinuxJavaScriptReplayRunner.js +10 -15
  203. package/dist/replay/ReplayOutcome.js +26 -15
  204. package/dist/replay/ReplayWorkerProtocol.js +34 -29
  205. package/dist/server/createServer.js +101 -144
  206. package/dist/server/mcpClientMetadata.js +32 -0
  207. package/dist/server/registerApplicationTools/characterization.js +6 -13
  208. package/dist/server/registerApplicationTools/compareExportShapes.js +2 -7
  209. package/dist/server/registerApplicationTools/compareSourceToBundle.js +2 -7
  210. package/dist/server/registerApplicationTools/compareVersions.js +3 -8
  211. package/dist/server/registerApplicationTools/controlledReplay.js +6 -11
  212. package/dist/server/registerApplicationTools/coverage.js +13 -19
  213. package/dist/server/registerApplicationTools/obligationLedger.js +1 -6
  214. package/dist/server/registerApplicationTools/readiness.js +1 -6
  215. package/dist/server/registerApplicationTools/traceFeature.js +3 -8
  216. package/dist/server/registerApplicationTools/traceSemantics.js +1 -6
  217. package/dist/server/registerArtifactComparisonTool.js +12 -16
  218. package/dist/server/registerBrowserScenarioTool.js +1 -6
  219. package/dist/server/registerBrowserTools.js +37 -79
  220. package/dist/server/registerBundleComparisonTool.js +10 -14
  221. package/dist/server/registerCloseLifecycleTool.js +6 -14
  222. package/dist/server/registerElectronTools.js +30 -47
  223. package/dist/server/registerEnhancedTools.js +124 -122
  224. package/dist/server/registerEvidenceResources.js +50 -101
  225. package/dist/server/registerEvidenceTools.js +5 -9
  226. package/dist/server/registerFunctionComparisonTool.js +11 -15
  227. package/dist/server/registerInvestigationTools.js +42 -59
  228. package/dist/server/registerJavaScriptApplicationGraphResource.js +0 -4
  229. package/dist/server/registerJavaScriptRuntimeObservationTools.js +13 -27
  230. package/dist/server/registerManagedWorkflowTools/compareManagedMembers.js +4 -9
  231. package/dist/server/registerManagedWorkflowTools/contract.js +2 -3
  232. package/dist/server/registerManagedWorkflowTools/importManagedReconstruction.js +3 -8
  233. package/dist/server/registerManagedWorkflowTools/planManagedRuntimeCorrelation.js +3 -8
  234. package/dist/server/registerManagedWorkflowTools/projectManagedApplicationGraph.js +8 -13
  235. package/dist/server/registerManagedWorkflowTools/verifyManagedNativeBoundaries.js +4 -9
  236. package/dist/server/registerOfficialTools.js +8 -9
  237. package/dist/server/registerProcessComparisonTool.js +19 -24
  238. package/dist/server/registerReconstructionObligationLedgerResource.js +0 -7
  239. package/dist/server/registerReconstructionReadinessResource.js +0 -7
  240. package/dist/server/registerReplayMachineTool.js +4 -10
  241. package/dist/server/registerSessionRecordTools.js +146 -47
  242. package/dist/server/registerSessionStatusTool.js +14 -29
  243. package/dist/server/registerSessionTools.js +45 -41
  244. package/dist/server/sessionAvailabilityPolicy.js +2 -1
  245. package/dist/server/sessionToolPolicies.js +1 -5
  246. package/dist/server/toolRegistrationOptions.js +4 -177
  247. package/dist/server/toolResult.js +14 -18
  248. package/package.json +35 -16
  249. package/scripts/electron-active-hook-boundaries.cjs +394 -0
  250. package/scripts/electron-active-hook.cjs +501 -0
  251. package/skills/reverse-engineer-anything/SKILL.md +10 -3
  252. package/dist/server/DynamicToolAvailability.js +0 -70
  253. package/dist/server/toolInputValidation.js +0 -77
@@ -20,14 +20,16 @@ const reconcileEntity = (entity, index, layers) => {
20
20
  const content = index.byCategoryDigest.get(categoryDigestKey(entity.staticKind, entity.sourceSha256)) ?? [];
21
21
  const locatedKeys = new Set(locations.map(({ candidate }) => candidateKey(candidate)));
22
22
  const combined = content.filter((candidate) => locatedKeys.has(candidateKey(candidate)));
23
- if (combined.length === 1)
24
- return matched(entity, combined[0], {
23
+ const combinedCandidate = combined.at(0);
24
+ if (combined.length === 1 && combinedCandidate !== undefined)
25
+ return matched(entity, combinedCandidate, {
25
26
  basis: "content-and-location",
26
27
  confidence: "high",
27
28
  reason: "content-and-location-match",
28
29
  });
29
- if (content.length === 1) {
30
- const candidate = content[0];
30
+ const contentCandidate = content.at(0);
31
+ if (content.length === 1 && contentCandidate !== undefined) {
32
+ const candidate = contentCandidate;
31
33
  const digestBasis = candidate.digests.find(({ sha256 }) => sha256 === entity.sourceSha256)?.basis;
32
34
  return matched(entity, candidate, {
33
35
  basis: digestBasis ?? "content-sha256",
@@ -59,8 +61,9 @@ const reconcileEntity = (entity, index, layers) => {
59
61
  candidates: [],
60
62
  });
61
63
  }
62
- if (locations.length === 1) {
63
- const located = locations[0];
64
+ const location = locations.at(0);
65
+ if (locations.length === 1 && location !== undefined) {
66
+ const located = location;
64
67
  return matched(entity, located.candidate, {
65
68
  basis: located.mapping.basis,
66
69
  confidence: "medium",
@@ -174,50 +177,55 @@ const createItem = (entity, input) => {
174
177
  ...semantic,
175
178
  };
176
179
  };
177
- const reconciliationEvidence = (entity, layer, basis, confidence) => ({
178
- authority: "cross-layer-reconciliation",
179
- state: "inferred",
180
- confidence: confidence === "medium" ? "medium" : "high",
181
- artifact: entity.sourceSha256 === null
182
- ? {
183
- available: false,
184
- reason: "not-observed",
185
- detail: "Runtime source bytes were not captured for this mapping.",
186
- }
187
- : {
188
- available: true,
189
- artifact_id: `art_${entity.sourceSha256}`,
190
- sha256: entity.sourceSha256,
191
- },
192
- location: entity.node.observations[0].evidence.location,
193
- extractor: {
194
- name: "rea-javascript-runtime-reconciliation",
195
- version: "1",
196
- operation: "reconcile_javascript_runtime",
197
- executable_sha256: null,
198
- },
199
- coverage: layer.graph.coverage.status === "complete" &&
200
- entity.capture.scriptsCompleteWithinScope
201
- ? { status: "complete", truncated: false, omitted_count: 0, limits: [] }
202
- : {
203
- status: "partial",
204
- truncated: false,
205
- omitted_count: null,
206
- limits: [],
180
+ const reconciliationEvidence = (entity, layer, basis, confidence) => {
181
+ const observation = entity.node.observations.at(0);
182
+ if (observation === undefined)
183
+ throw new TypeError("Runtime reconciliation entity has no observation");
184
+ return {
185
+ authority: "cross-layer-reconciliation",
186
+ state: "inferred",
187
+ confidence: confidence === "medium" ? "medium" : "high",
188
+ artifact: entity.sourceSha256 === null
189
+ ? {
190
+ available: false,
191
+ reason: "not-observed",
192
+ detail: "Runtime source bytes were not captured for this mapping.",
193
+ }
194
+ : {
195
+ available: true,
196
+ artifact_id: `art_${entity.sourceSha256}`,
197
+ sha256: entity.sourceSha256,
198
+ },
199
+ location: observation.evidence.location,
200
+ extractor: {
201
+ name: "rea-javascript-runtime-reconciliation",
202
+ version: "1",
203
+ operation: "reconcile_javascript_runtime",
204
+ executable_sha256: null,
207
205
  },
208
- limitations: [
209
- basis === "content-sha256" ||
210
- basis === "module-source-sha256" ||
211
- basis === "content-and-location"
212
- ? "Equal content digests establish byte identity, not execution causality."
213
- : "Location correspondence is inferred from an artifact root or caller-declared mapping.",
214
- "Passive script parsing or target presence does not prove feature execution.",
215
- ],
216
- evidence_ids: [
217
- layer.evidence.evidence_id,
218
- entity.capture.evidence.evidence_id,
219
- ].sort(),
220
- });
206
+ coverage: layer.graph.coverage.status === "complete" &&
207
+ entity.capture.scriptsCompleteWithinScope
208
+ ? { status: "complete", truncated: false, omitted_count: 0, limits: [] }
209
+ : {
210
+ status: "partial",
211
+ truncated: false,
212
+ omitted_count: null,
213
+ limits: [],
214
+ },
215
+ limitations: [
216
+ basis === "content-sha256" ||
217
+ basis === "module-source-sha256" ||
218
+ basis === "content-and-location"
219
+ ? "Equal content digests establish byte identity, not execution causality."
220
+ : "Location correspondence is inferred from an artifact root or caller-declared mapping.",
221
+ "Passive script parsing or target presence does not prove feature execution.",
222
+ ],
223
+ evidence_ids: [
224
+ layer.evidence.evidence_id,
225
+ entity.capture.evidence.evidence_id,
226
+ ].sort(),
227
+ };
228
+ };
221
229
  const strongestLocationBasis = (values) => {
222
230
  const bases = new Set(values.map(({ mapping }) => mapping.basis));
223
231
  if (bases.has("artifact-path"))
@@ -9,6 +9,7 @@ import { javascriptRuntimeObservationSchema, javascriptRuntimeKindSchema, } from
9
9
  import { parseEvidence } from "./evidence.js";
10
10
  import { javascriptApplicationAnalysisResultSchema, } from "./javascriptApplicationAnalysis.js";
11
11
  import { compareCodePoints, } from "./javascriptApplicationGraph.js";
12
+ import { parseActiveElectronCapture } from "./javascriptRuntimeReconciliationActive.js";
12
13
  /** Parse and semantically bind every static analysis Evidence layer. */
13
14
  export const parseStaticLayers = (layers) => layers
14
15
  .map((layer) => parseStaticLayer(layer))
@@ -133,7 +134,10 @@ const parseRuntimeCapture = (input) => {
133
134
  scriptsCompleteWithinScope: false,
134
135
  };
135
136
  }
136
- throw new TypeError("Runtime reconciliation requires inspect_web_page, inspect_electron_page, or observe_javascript_runtime Evidence");
137
+ if (evidence.operation === "capture_electron_scenario") {
138
+ return parseActiveElectronCapture(evidence);
139
+ }
140
+ throw new TypeError("Runtime reconciliation requires inspect_web_page, inspect_electron_page, observe_javascript_runtime, or capture_electron_scenario Evidence");
137
141
  };
138
142
  const assertV8RuntimeParameters = (evidence, result) => {
139
143
  const parameters = z
@@ -78,27 +78,34 @@ const sourceMapAuthority = (input) => ({
78
78
  limitation: "Source-map declarations and approved original-source reads retain separate static authority and are not used as primary runtime byte matches.",
79
79
  });
80
80
  const reconciliationCoverage = (input, completion) => ({
81
- status: completion.outputTruncated || completion.inputTruncated
81
+ status: completion.outputTruncated || completion.inputStatus === "truncated"
82
82
  ? "truncated"
83
- : completion.inputPartial
83
+ : completion.inputStatus === "partial"
84
84
  ? "partial"
85
85
  : "complete-within-inputs",
86
- truncated: completion.outputTruncated || completion.inputTruncated,
86
+ truncated: completion.outputTruncated || completion.inputStatus === "truncated",
87
87
  omitted_runtime_entities: input.runtime.omittedEntities,
88
88
  omitted_reconciliation_items: input.matching.omittedItems,
89
89
  omitted_static_load_states: input.loadStates.omittedStates,
90
90
  omitted_graph_items: input.omittedGraphItems,
91
91
  });
92
- const completionFlags = (input) => ({
93
- outputTruncated: input.runtime.omittedEntities > 0 ||
94
- input.matching.omittedItems > 0 ||
95
- input.loadStates.omittedStates > 0 ||
96
- input.omittedGraphItems > 0,
97
- inputTruncated: input.layers.some(({ graph }) => graph.coverage.truncated) ||
98
- input.captures.some(({ inspection }) => inspection.completeness.conditions.includes("truncated")),
99
- inputPartial: input.layers.some(({ graph }) => graph.coverage.status !== "complete") ||
100
- input.captures.some(({ inspection }) => inspection.completeness.status !== "complete_within_window"),
101
- });
92
+ const completionFlags = (input) => {
93
+ const inputTruncated = input.layers.some(({ graph }) => graph.coverage.truncated) ||
94
+ input.captures.some(({ inspection }) => inspection.completeness.conditions.includes("truncated"));
95
+ const inputPartial = input.layers.some(({ graph }) => graph.coverage.status !== "complete") ||
96
+ input.captures.some(({ inspection }) => inspection.completeness.status !== "complete_within_window");
97
+ return {
98
+ outputTruncated: input.runtime.omittedEntities > 0 ||
99
+ input.matching.omittedItems > 0 ||
100
+ input.loadStates.omittedStates > 0 ||
101
+ input.omittedGraphItems > 0,
102
+ inputStatus: inputTruncated
103
+ ? "truncated"
104
+ : inputPartial
105
+ ? "partial"
106
+ : "complete",
107
+ };
108
+ };
102
109
  const reconciliationLimitations = (completion) => uniqueSorted([
103
110
  "Only caller-supplied, semantically verified Evidence records were reconciled.",
104
111
  "Digest equality establishes byte identity but not code reachability, module initialization, or feature execution.",
@@ -106,7 +113,7 @@ const reconciliationLimitations = (completion) => uniqueSorted([
106
113
  "Not-observed means absent from the bounded captures in scope, never globally unloaded.",
107
114
  "Caller-declared file and URL mappings are inference inputs and do not expand CDP origin or filesystem-root authority.",
108
115
  "Source-map authority remains separate from passive runtime authority.",
109
- ...(completion.inputPartial
116
+ ...(completion.inputStatus !== "complete"
110
117
  ? ["One or more static graphs or passive captures were incomplete."]
111
118
  : []),
112
119
  ...(completion.outputTruncated
@@ -133,7 +133,7 @@ const layerSummarySchema = z.strictObject({
133
133
  const captureSummarySchema = z.strictObject({
134
134
  evidence_id: evidenceIdSchema,
135
135
  capture_sha256: digestSchema,
136
- kind: z.enum(["browser", "electron", "v8-inspector"]),
136
+ kind: z.enum(["browser", "electron", "v8-inspector", "electron-active"]),
137
137
  target_node_id: nodeIdSchema,
138
138
  target_key: boundedTextSchema,
139
139
  target_location: boundedTextSchema,
@@ -1,4 +1,3 @@
1
- import { parse } from "@babel/parser";
2
1
  import * as t from "@babel/types";
3
2
  import { DEFAULT_JAVASCRIPT_SEMANTIC_LIMITS, failedJavaScriptSemanticIr, } from "./javascriptSemanticIr.js";
4
3
  import { collectSemanticModuleLink, collectSemanticCallable, collectSemanticReferences, immutableSemanticBindings, immutableSemanticScopes, reachSemanticLimit, semanticModuleOrigin, semanticStaticPropertyName, } from "./javascriptSemanticProjection.js";
@@ -7,20 +6,17 @@ import { traverseJavaScriptAst } from "./javascriptSemanticTraversal.js";
7
6
  import { collectSemanticReturns, resolveSemanticModuleCallables, } from "./javascriptSemanticReturns.js";
8
7
  import { collectJavaScriptDerivedSemantics } from "./javascriptSemanticDerivedAnalysis.js";
9
8
  import { compareCodePoints, propertyName, range, } from "./javascriptStaticAnalysisHelpers.js";
9
+ import { parseJavaScriptSource, } from "./javascriptSourceParser.js";
10
10
  /** Recover bounded lexical bindings, aliases, constants, and module links. */
11
11
  export const analyzeJavaScriptSemantics = (source, inputLimits = {}) => {
12
+ const file = parseJavaScriptSource(source);
13
+ return file === null
14
+ ? failedJavaScriptSemanticIr()
15
+ : analyzeParsedJavaScriptSemantics(file, inputLimits);
16
+ };
17
+ /** Recover semantics from an already parsed JavaScript artifact. */
18
+ export const analyzeParsedJavaScriptSemantics = (file, inputLimits = {}) => {
12
19
  const limits = { ...DEFAULT_JAVASCRIPT_SEMANTIC_LIMITS, ...inputLimits };
13
- let file;
14
- try {
15
- file = parse(source, {
16
- sourceType: "unambiguous",
17
- errorRecovery: true,
18
- plugins: ["jsx", "typescript"],
19
- });
20
- }
21
- catch {
22
- return failedJavaScriptSemanticIr();
23
- }
24
20
  const state = createState(file.program, limits);
25
21
  collectDefinitions(file.program, state);
26
22
  const references = collectSemanticReferences(file.program, state);
@@ -0,0 +1,15 @@
1
+ import { parse } from "@babel/parser";
2
+ /** Parse JavaScript or TypeScript once without retaining unused comment nodes. */
3
+ export const parseJavaScriptSource = (source) => {
4
+ try {
5
+ return parse(source, {
6
+ sourceType: "unambiguous",
7
+ errorRecovery: true,
8
+ attachComment: false,
9
+ plugins: ["jsx", "typescript"],
10
+ });
11
+ }
12
+ catch {
13
+ return null;
14
+ }
15
+ };
@@ -1,4 +1,3 @@
1
- import { parse } from "@babel/parser";
2
1
  import * as t from "@babel/types";
3
2
  import { inspectElectronStaticNode } from "./electronStaticAnalysis.js";
4
3
  import { detectVendors, failedJavaScriptStaticAnalysis, registrationKey, sortedUnique, stringValue, } from "./javascriptStaticAnalysisHelpers.js";
@@ -6,19 +5,16 @@ import { addReference, addSourceMapDirectives, inspectCall, inspectRouteProperty
6
5
  import { inspectBundlerRegistration, inspectEsbuildWrapper, } from "./javascriptStaticAnalysisBundler.js";
7
6
  import { finalizeLocatedFindings } from "./javascriptStaticAnalysisFindings.js";
8
7
  import { createJavaScriptAnalysisAccumulator, } from "./javascriptStaticAnalysisState.js";
8
+ import { parseJavaScriptSource, } from "./javascriptSourceParser.js";
9
9
  /** Parse one bounded JavaScript artifact and recover static structure only. */
10
10
  export const analyzeJavaScriptStaticSource = (source, limits) => {
11
- let file;
12
- try {
13
- file = parse(source, {
14
- sourceType: "unambiguous",
15
- errorRecovery: true,
16
- plugins: ["jsx", "typescript"],
17
- });
18
- }
19
- catch {
20
- return failedJavaScriptStaticAnalysis();
21
- }
11
+ const file = parseJavaScriptSource(source);
12
+ return file === null
13
+ ? failedJavaScriptStaticAnalysis()
14
+ : analyzeParsedJavaScriptStaticSource(source, file, limits);
15
+ };
16
+ /** Recover static structure from an already parsed JavaScript artifact. */
17
+ export const analyzeParsedJavaScriptStaticSource = (source, file, limits) => {
22
18
  const accumulator = createJavaScriptAnalysisAccumulator();
23
19
  traverseStaticSource(source, file, accumulator, limits);
24
20
  addSourceMapDirectives(source, accumulator, limits.maxFindings);
@@ -11,11 +11,19 @@ export const assessKnownPageCoverage = (page, includedCount = page.items.length)
11
11
  page.returned === page.total &&
12
12
  sourceOmittedCount === 0;
13
13
  const omittedCount = Math.max(0, page.total - retainedCount);
14
- return {
15
- complete: sourceComplete && omittedCount === 0,
16
- sourceComplete,
17
- includedCount: retainedCount,
18
- omittedCount,
19
- sourceOmittedCount,
20
- };
14
+ return sourceComplete && omittedCount === 0
15
+ ? {
16
+ complete: true,
17
+ sourceComplete: true,
18
+ includedCount: retainedCount,
19
+ omittedCount: 0,
20
+ sourceOmittedCount: 0,
21
+ }
22
+ : {
23
+ complete: false,
24
+ sourceComplete,
25
+ includedCount: retainedCount,
26
+ omittedCount,
27
+ sourceOmittedCount,
28
+ };
21
29
  };
@@ -0,0 +1,159 @@
1
+ import { z } from "zod";
2
+ /** Supported mobile artifact formats. */
3
+ export const mobileArtifactFormatSchema = z.enum([
4
+ "apk",
5
+ "aab",
6
+ "ipa",
7
+ "dex",
8
+ "native_lib",
9
+ ]);
10
+ /** Mobile platform. */
11
+ export const mobilePlatformSchema = z.enum([
12
+ "android",
13
+ "ios",
14
+ "cross_platform",
15
+ ]);
16
+ /** Android manifest entry. */
17
+ export const androidManifestSchema = z.strictObject({
18
+ package_name: z.string().min(1),
19
+ version_name: z.string().nullable(),
20
+ version_code: z.number().int().nullable(),
21
+ min_sdk: z.number().int().nullable(),
22
+ target_sdk: z.number().int().nullable(),
23
+ permissions: z.array(z.string()).default([]),
24
+ activities: z.array(z.string()).default([]),
25
+ services: z.array(z.string()).default([]),
26
+ receivers: z.array(z.string()).default([]),
27
+ providers: z.array(z.string()).default([]),
28
+ });
29
+ /** iOS app manifest (Info.plist). */
30
+ export const iosManifestSchema = z.strictObject({
31
+ bundle_identifier: z.string().min(1),
32
+ bundle_version: z.string().nullable(),
33
+ short_version: z.string().nullable(),
34
+ minimum_os_version: z.string().nullable(),
35
+ supported_platforms: z.array(z.string()).default([]),
36
+ ui_required_device_capabilities: z.array(z.string()).default([]),
37
+ app_permissions: z.array(z.string()).default([]),
38
+ });
39
+ /** Signing information. */
40
+ export const signingInfoSchema = z.strictObject({
41
+ is_signed: z.boolean().default(false),
42
+ signer_identity: z.string().nullable(),
43
+ certificate_fingerprint: z.string().nullable(),
44
+ signature_scheme: z.string().nullable(),
45
+ is_debuggable: z.boolean().default(false),
46
+ });
47
+ /** Native library entry. */
48
+ export const nativeLibrarySchema = z.strictObject({
49
+ path: z.string().min(1),
50
+ architecture: z.string().nullable(),
51
+ size: z.number().int().nonnegative(),
52
+ digest: z
53
+ .string()
54
+ .regex(/^[a-f0-9]{64}$/u)
55
+ .nullable(),
56
+ });
57
+ /** Resource entry within a mobile artifact. */
58
+ export const mobileResourceSchema = z.strictObject({
59
+ path: z.string().min(1),
60
+ type: z.enum([
61
+ "layout",
62
+ "drawable",
63
+ "string",
64
+ "asset",
65
+ "raw",
66
+ "native_lib",
67
+ "manifest",
68
+ "entitlements",
69
+ "provisioning",
70
+ "other",
71
+ ]),
72
+ size: z.number().int().nonnegative(),
73
+ });
74
+ /** Static analysis result for a mobile artifact. */
75
+ export const mobileArtifactManifestSchema = z.strictObject({
76
+ format: mobileArtifactFormatSchema,
77
+ platform: mobilePlatformSchema,
78
+ app_name: z.string().nullable(),
79
+ android_manifest: androidManifestSchema.nullable(),
80
+ ios_manifest: iosManifestSchema.nullable(),
81
+ signing: signingInfoSchema,
82
+ resources: z.array(mobileResourceSchema).default([]),
83
+ native_libraries: z.array(nativeLibrarySchema).default([]),
84
+ total_size: z.number().int().nonnegative(),
85
+ architectures: z.array(z.string()).default([]),
86
+ });
87
+ /** Detect mobile artifact format from file extension. */
88
+ export function detectMobileFormat(path) {
89
+ const lower = path.toLowerCase();
90
+ if (lower.endsWith(".apk"))
91
+ return "apk";
92
+ if (lower.endsWith(".aab"))
93
+ return "aab";
94
+ if (lower.endsWith(".ipa"))
95
+ return "ipa";
96
+ if (lower.endsWith(".dex"))
97
+ return "dex";
98
+ if (lower.endsWith(".so") || lower.endsWith(".dylib") || lower.endsWith(".a"))
99
+ return "native_lib";
100
+ return null;
101
+ }
102
+ /** Detect platform from format. */
103
+ export function detectPlatform(format) {
104
+ switch (format) {
105
+ case "apk":
106
+ case "aab":
107
+ case "dex":
108
+ return "android";
109
+ case "ipa":
110
+ return "ios";
111
+ case "native_lib":
112
+ return "cross_platform";
113
+ }
114
+ }
115
+ /** Classify a resource by its path. */
116
+ export function classifyMobileResource(path) {
117
+ const lower = path.toLowerCase();
118
+ if (lower.includes("androidmanifest.xml"))
119
+ return "manifest";
120
+ if (lower.includes(".entitlements"))
121
+ return "entitlements";
122
+ if (lower.includes("provisioning") || lower.includes(".mobileprovision"))
123
+ return "provisioning";
124
+ if (lower.includes("/layout/"))
125
+ return "layout";
126
+ if (lower.includes("/drawable/") || lower.includes("/mipmap/"))
127
+ return "drawable";
128
+ if (lower.includes("/values/"))
129
+ return "string";
130
+ if (lower.includes("assets/") || lower.includes("raw/"))
131
+ return "asset";
132
+ if (lower.endsWith(".so") || lower.endsWith(".dylib"))
133
+ return "native_lib";
134
+ if (lower.endsWith(".xml"))
135
+ return "layout";
136
+ return "other";
137
+ }
138
+ /** Get all native libraries for a specific architecture. */
139
+ export function nativeLibsByArchitecture(manifest, arch) {
140
+ return manifest.native_libraries.filter((l) => l.architecture === arch);
141
+ }
142
+ /** Check if an Android artifact has internet permission. */
143
+ export function hasInternetPermission(manifest) {
144
+ if (!manifest.android_manifest)
145
+ return false;
146
+ return manifest.android_manifest.permissions.some((p) => p.includes("INTERNET") || p.includes("android.permission.INTERNET"));
147
+ }
148
+ /** Get all unique architectures across native libraries. */
149
+ export function getAllArchitectures(manifest) {
150
+ const archs = new Set();
151
+ for (const lib of manifest.native_libraries) {
152
+ if (lib.architecture)
153
+ archs.add(lib.architecture);
154
+ }
155
+ for (const arch of manifest.architectures) {
156
+ archs.add(arch);
157
+ }
158
+ return [...archs];
159
+ }
@@ -0,0 +1,138 @@
1
+ import { z } from "zod";
2
+ const inferenceConfidenceSchema = z.enum(["low", "medium", "high"]);
3
+ const inferenceEvidenceSchema = z
4
+ .object({
5
+ kind: z.enum([
6
+ "signature-source",
7
+ "decompiler-type",
8
+ "type-lock",
9
+ "calling-convention",
10
+ "jump-table",
11
+ ]),
12
+ source: z.string().min(1),
13
+ detail: z.string().min(1),
14
+ })
15
+ .strict();
16
+ const inferredBoundaryTypeFacts = {
17
+ ordinal: z.number().int().min(0).nullable(),
18
+ name: z.string().min(1).nullable(),
19
+ data_type: z.string().min(1),
20
+ size_bytes: z.number().int().min(0).nullable(),
21
+ storage: z.string().min(1).nullable(),
22
+ confidence: inferenceConfidenceSchema,
23
+ evidence: z.array(inferenceEvidenceSchema).min(1),
24
+ decompiler_artifacts: z.array(z.enum([
25
+ "recovered-signature",
26
+ "register-or-stack-storage",
27
+ "compiler-generated-variable",
28
+ ])),
29
+ };
30
+ const inferredReturnTypeSchema = z.strictObject({
31
+ ...inferredBoundaryTypeFacts,
32
+ role: z.literal("return"),
33
+ ordinal: z.null(),
34
+ name: z.null(),
35
+ });
36
+ const inferredParameterTypeSchema = z.strictObject({
37
+ ...inferredBoundaryTypeFacts,
38
+ role: z.literal("parameter"),
39
+ ordinal: z.number().int().min(0),
40
+ });
41
+ const jumpTableDataSourceSchema = z
42
+ .object({
43
+ address: z.string().min(1),
44
+ provenance: z.enum([
45
+ "ghidra-decompiler-load-table",
46
+ "ghidra-dispatch-block-data-reference",
47
+ ]),
48
+ entry_size_bytes: z.number().int().min(1).nullable(),
49
+ entry_count: z.number().int().min(0).nullable(),
50
+ confidence: inferenceConfidenceSchema,
51
+ evidence: z.array(inferenceEvidenceSchema).min(1),
52
+ })
53
+ .strict();
54
+ const jumpTableMappingSchema = z
55
+ .object({
56
+ case_value: z.number().int().nullable(),
57
+ target_address: z.string().min(1),
58
+ data_addresses: z.array(z.string().min(1)),
59
+ confidence: inferenceConfidenceSchema,
60
+ evidence: z.array(inferenceEvidenceSchema).min(1),
61
+ })
62
+ .strict();
63
+ const inferredJumpTableSchema = z
64
+ .object({
65
+ dispatch_address: z.string().min(1),
66
+ data_sources: z.array(jumpTableDataSourceSchema),
67
+ data_sources_truncated: z.boolean(),
68
+ mappings: z.array(jumpTableMappingSchema),
69
+ mappings_truncated: z.boolean(),
70
+ limitations: z.array(z.string()),
71
+ })
72
+ .strict();
73
+ const availableNativeApiBoundarySchema = z
74
+ .object({
75
+ available: z.literal(true),
76
+ provenance: z.string().min(1),
77
+ signature_source: z.string().min(1),
78
+ calling_convention: z.string().min(1),
79
+ return_type: inferredReturnTypeSchema,
80
+ parameters: z.array(inferredParameterTypeSchema),
81
+ parameters_truncated: z.boolean(),
82
+ jump_tables: z.array(inferredJumpTableSchema),
83
+ jump_tables_truncated: z.boolean(),
84
+ pseudocode: z
85
+ .object({
86
+ classification: z.literal("decompiler-generated-non-source"),
87
+ compilable: z.literal(false),
88
+ })
89
+ .strict(),
90
+ decompiler_artifacts: z.array(z.enum([
91
+ "recovered-signature",
92
+ "register-and-stack-variables",
93
+ "compiler-generated-control-flow",
94
+ "pointer-arithmetic",
95
+ "pseudocode",
96
+ ])),
97
+ limitations: z.array(z.string()),
98
+ })
99
+ .strict();
100
+ const unavailableNativeApiBoundarySchema = z
101
+ .object({
102
+ available: z.literal(false),
103
+ reason: z.string().min(1),
104
+ residual_unknowns: z.array(z.string().min(1)).min(1),
105
+ })
106
+ .strict();
107
+ /** Provider-neutral native API boundary observations attached to a function dossier. */
108
+ export const nativeApiBoundarySchema = z.discriminatedUnion("available", [
109
+ unavailableNativeApiBoundarySchema,
110
+ availableNativeApiBoundarySchema,
111
+ ]);
112
+ const nativeApiInspectionSubstepSchema = z
113
+ .object({
114
+ operation: z.enum([
115
+ "analyze_function",
116
+ "project_native_api_boundary",
117
+ "preserve_residual_unknowns",
118
+ ]),
119
+ status: z.enum(["completed", "unsupported"]),
120
+ observations: z.array(z.string().min(1)),
121
+ })
122
+ .strict();
123
+ /** Agent-facing projection of structured native API reconstruction substeps. */
124
+ export const nativeApiInspectionResultSchema = z
125
+ .object({
126
+ schema_version: z.literal(1),
127
+ procedure: z
128
+ .object({
129
+ address: z.string().min(1),
130
+ name: z.string().min(1),
131
+ })
132
+ .strict(),
133
+ boundary: nativeApiBoundarySchema,
134
+ substeps: z.array(nativeApiInspectionSubstepSchema).min(3).max(3),
135
+ unsupported_branches: z.array(z.string().min(1)),
136
+ residual_unknowns: z.array(z.string().min(1)),
137
+ })
138
+ .strict();