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
@@ -2,9 +2,10 @@ import { z } from "zod";
2
2
  import { processCaptureComparisonSchema, processCaptureSchema, } from "../domain/processCapture.js";
3
3
  import { evidenceBundleSchema } from "../domain/evidenceBundle.js";
4
4
  import { residualUnknownSchema } from "../domain/residualUnknown.js";
5
- import { referenceKindSchema } from "../domain/hopperValues.js";
5
+ import { functionInstructionWindowSchema, referenceKindSchema, } from "../domain/hopperValues.js";
6
6
  import { demangleSwiftSchema, inspectMachoSchema, inspectPlistSchema, inspectSignatureSchema, listArchitecturesSchema, } from "../domain/nativeInspection.js";
7
7
  import { artifactExtractionResultSchema, artifactInventoryResultSchema, } from "../domain/artifactGraph.js";
8
+ import { artifactInspectionResultSchema } from "../domain/artifactInspection.js";
8
9
  import { managedArtifactInspectionSchema, managedMemberInspectionSchema, managedNativeBoundaryInspectionSchema, } from "../domain/managedArtifact.js";
9
10
  import { managedMemberComparisonResultSchema } from "../domain/managedMemberComparison.js";
10
11
  import { managedNativeVerificationResultSchema } from "../domain/managedNativeVerification.js";
@@ -20,7 +21,7 @@ import { staticRuntimeCorrelationResultSchema } from "../domain/staticRuntimeCor
20
21
  import { reconstructionVerificationResultSchema } from "../domain/reconstructionVerification.js";
21
22
  import { replayMachineRunOutputSchema } from "../domain/replayMachineRun.js";
22
23
  import { analysisErrorProjectionSchema } from "./errorSchemas.js";
23
- import { addressList, addressedEntry, bounded, containingProcedureResolution, functionDossierOutput, graphNode, lifecycleResultOf, nullableText, pageOutput, procedureIdentity, procedureInfoOutput, evidenceResultOf as resultOf, searchPageOutput, segmentOutput, sessionProvider, providerIdentity, toolAvailability, symbolDiscoveryOutput, targetFormatSchema, targetKindSchema, } from "./toolOutputSchemaPrimitives.js";
24
+ import { addressList, analysisActivity, addressedEntry, bounded, containingProcedureResolution, clientFeatureAvailabilitySchema, functionDossierOutput, graphNode, lifecycleResultOf, nullableText, pageOutput, procedureIdentity, procedureInfoOutput, evidenceResultOf as resultOf, searchPageOutput, segmentOutput, sessionProvider, providerIdentity, toolAvailability, symbolDiscoveryOutput, targetFormatSchema, targetKindSchema, } from "./toolOutputSchemaPrimitives.js";
24
25
  /** Exact structured-content schemas shared by direct analysis providers. */
25
26
  export const officialOutputSchemas = {
26
27
  address_name: resultOf(nullableText),
@@ -43,6 +44,18 @@ export const officialOutputSchemas = {
43
44
  procedure_callees: resultOf(addressList),
44
45
  procedure_callers: resultOf(addressList),
45
46
  procedure_info: procedureInfoOutput,
47
+ read_function_instructions: resultOf(functionInstructionWindowSchema),
48
+ read_bytes: resultOf(z.object({
49
+ address: z.string(),
50
+ requested_bytes: z.number().int().min(1).max(4_096),
51
+ returned_bytes: z.number().int().min(0).max(4_096),
52
+ bytes_hex: z.string().regex(/^(?:[a-f0-9]{2})*$/u),
53
+ complete: z.boolean(),
54
+ })),
55
+ address_to_file_offset: resultOf(z.object({
56
+ address: z.string(),
57
+ file_offset: z.number().int().min(0).max(Number.MAX_SAFE_INTEGER),
58
+ })),
46
59
  procedure_references: resultOf(z.object({
47
60
  procedure: procedureIdentity,
48
61
  direction: z.enum(["incoming", "outgoing"]),
@@ -69,6 +82,55 @@ export const officialOutputSchemas = {
69
82
  unset_bookmark: resultOf(z.boolean()),
70
83
  xrefs: resultOf(addressList),
71
84
  };
85
+ const literalTraceOutput = resultOf(z.object({
86
+ query: z.string(),
87
+ search_mode: z.literal("literal"),
88
+ operations_used: z.number().int().min(0),
89
+ operation_budget: z.number().int().min(1),
90
+ matches: z.array(z.object({
91
+ type: z.enum(["string", "procedure"]),
92
+ address: z.string(),
93
+ value: z.string(),
94
+ })),
95
+ references: z.array(z.object({
96
+ target_address: z.string(),
97
+ source_address: z.string(),
98
+ containing_procedure: containingProcedureResolution,
99
+ })),
100
+ truncated: z.boolean(),
101
+ residual_unknowns: z.array(z.string()),
102
+ }));
103
+ const callPathTraceOutput = resultOf(z.object({
104
+ start: z.string(),
105
+ goal: z.string().nullable(),
106
+ direction: z.enum(["forward", "backward"]),
107
+ goal_status: z.enum(["not_requested", "reached", "not_reached"]),
108
+ nodes: z.array(z.object({
109
+ address: z.string(),
110
+ depth: z.number().int().min(0),
111
+ })),
112
+ edges: z.array(z.object({
113
+ source_address: z.string(),
114
+ target_address: z.string(),
115
+ discovery_depth: z.number().int().min(1),
116
+ })),
117
+ traversal_path: z.array(z.string()),
118
+ failures: z.array(z.object({
119
+ address: z.string(),
120
+ error: analysisErrorProjectionSchema,
121
+ })),
122
+ frontier: z.array(z.string()),
123
+ limits: z.object({
124
+ max_depth: z.number().int().min(1),
125
+ max_nodes: z.number().int().min(1),
126
+ max_operations: z.number().int().min(1),
127
+ nodes_visited: z.number().int().min(1),
128
+ operations_used: z.number().int().min(0),
129
+ }),
130
+ truncated: z.boolean(),
131
+ residual_unknowns: z.array(z.string()),
132
+ limitations: z.array(z.string()),
133
+ }));
72
134
  /** Exact structured-content schemas for composed analysis workflows. */
73
135
  export const enhancedOutputSchemas = {
74
136
  swift_classes: symbolDiscoveryOutput("classes"),
@@ -126,24 +188,9 @@ export const enhancedOutputSchemas = {
126
188
  string_count: z.number().int().min(0),
127
189
  })),
128
190
  analyze_function: functionDossierOutput,
129
- trace_feature: resultOf(z.object({
130
- query: z.string(),
131
- search_mode: z.literal("literal"),
132
- operations_used: z.number().int().min(0),
133
- operation_budget: z.number().int().min(1),
134
- matches: z.array(z.object({
135
- type: z.enum(["string", "procedure"]),
136
- address: z.string(),
137
- value: z.string(),
138
- })),
139
- references: z.array(z.object({
140
- target_address: z.string(),
141
- source_address: z.string(),
142
- containing_procedure: containingProcedureResolution,
143
- })),
144
- truncated: z.boolean(),
145
- residual_unknowns: z.array(z.string()),
146
- })),
191
+ trace_feature: literalTraceOutput,
192
+ find_code_for_string: literalTraceOutput,
193
+ trace_call_path: callPathTraceOutput,
147
194
  };
148
195
  /** Exact Evidence v2 schemas for provider-neutral native inspection. */
149
196
  export const nativeOutputSchemas = {
@@ -156,6 +203,7 @@ export const nativeOutputSchemas = {
156
203
  /** Exact Evidence v2 schemas for provider-neutral artifact graph operations. */
157
204
  export const artifactOutputSchemas = {
158
205
  inventory_artifact: resultOf(artifactInventoryResultSchema),
206
+ inspect_artifact: resultOf(artifactInspectionResultSchema),
159
207
  extract_artifact: resultOf(artifactExtractionResultSchema),
160
208
  };
161
209
  /** Exact Evidence v2 schema for execution-free managed static analysis. */
@@ -210,6 +258,7 @@ export const sessionOutputSchemas = {
210
258
  reasons: z.array(z.string()),
211
259
  remediation: z.string().nullable(),
212
260
  }),
261
+ analysis_activity: analysisActivity,
213
262
  recommended_actions: z.array(z.string()),
214
263
  }),
215
264
  z.object({
@@ -226,6 +275,7 @@ export const sessionOutputSchemas = {
226
275
  next_cursor: z.number().int().min(0).nullable(),
227
276
  has_more: z.boolean(),
228
277
  }),
278
+ client_features: clientFeatureAvailabilitySchema,
229
279
  }),
230
280
  z.union([
231
281
  sessionProvider.extend({
@@ -27,6 +27,8 @@ export const targetFormatSchema = z.enum([
27
27
  "zip",
28
28
  "ipa",
29
29
  "apk",
30
+ "msix",
31
+ "appx",
30
32
  "asar",
31
33
  "dmg",
32
34
  "pkg",
@@ -44,6 +46,7 @@ const providerCapability = z.object({
44
46
  operation: z.string(),
45
47
  available: z.boolean(),
46
48
  reason: z.string().nullable(),
49
+ availability_code: z.enum(PROVIDER_REJECTION_CODES).nullable(),
47
50
  input_contract_version: z.number().int().min(1),
48
51
  output_contract_version: z.number().int().min(1),
49
52
  pagination: z.enum(["none", "offset", "cursor"]),
@@ -108,6 +111,22 @@ const analysisRun = z
108
111
  ]),
109
112
  })
110
113
  .nullable();
114
+ export const analysisActivity = z.object({
115
+ status: z.enum(["not_observed", "idle", "busy", "timed_out_busy"]),
116
+ providers: z.array(z.object({
117
+ provider: providerIdentity,
118
+ active: z
119
+ .object({
120
+ request_id: z.number().int().min(1),
121
+ operation: z.string().min(1),
122
+ elapsed_ms: z.number().int().min(0),
123
+ timeout_ms: z.number().int().min(0),
124
+ caller_state: z.enum(["waiting", "timed_out", "cancelled"]),
125
+ })
126
+ .nullable(),
127
+ queued_requests: z.number().int().min(0),
128
+ })),
129
+ });
111
130
  const providerRejectionCode = z.enum(PROVIDER_REJECTION_CODES);
112
131
  const providerDiagnostics = z.record(z.string(), z.json());
113
132
  const providerAvailability = z.discriminatedUnion("status", [
@@ -150,12 +169,26 @@ const providerTargetSupport = z.discriminatedUnion("status", [
150
169
  diagnostics: providerDiagnostics,
151
170
  }),
152
171
  ]);
172
+ const clientFeatureNameSchema = z.enum([
173
+ "elicitation_form",
174
+ "elicitation_url",
175
+ "roots",
176
+ "sampling",
177
+ ]);
178
+ /** Negotiated MCP client features that affect REA workflow availability. */
179
+ export const clientFeatureAvailabilitySchema = z.object({
180
+ elicitation_form: z.boolean(),
181
+ elicitation_url: z.boolean(),
182
+ roots: z.boolean(),
183
+ sampling: z.boolean(),
184
+ });
153
185
  export const toolAvailability = z.object({
154
186
  name: z.string(),
155
187
  surface: z.string(),
156
188
  available: z.boolean(),
157
189
  reason: z.enum([
158
190
  "available",
191
+ "client_capability_missing",
159
192
  "target_required",
160
193
  "provider_missing",
161
194
  "provider_unavailable",
@@ -164,6 +197,12 @@ export const toolAvailability = z.object({
164
197
  "policy_disabled",
165
198
  ]),
166
199
  remediation: z.string().nullable(),
200
+ client_requirements: z.object({
201
+ required: z.array(clientFeatureNameSchema),
202
+ optional: z.array(clientFeatureNameSchema),
203
+ missing_required: z.array(clientFeatureNameSchema),
204
+ missing_optional: z.array(clientFeatureNameSchema),
205
+ }),
167
206
  effects: z.strictObject({
168
207
  mutatesTarget: z.boolean(),
169
208
  mutatesSession: z.boolean(),
@@ -186,6 +225,7 @@ export const sessionProvider = z.object({
186
225
  providers: z.array(providerIdentity),
187
226
  capabilities: z.array(providerCapability),
188
227
  analysis_run: analysisRun,
228
+ analysis_activity: analysisActivity,
189
229
  analysis_provider_binding: z
190
230
  .object({
191
231
  provider: providerIdentity,
@@ -21,6 +21,8 @@ export const projectAnalysisError = (error) => {
21
21
  };
22
22
  };
23
23
  const errorCode = (error) => {
24
+ if (error.cleanupIncomplete)
25
+ return "cleanup_incomplete";
24
26
  if (error instanceof ReplayPlanStaleError)
25
27
  return "plan_stale";
26
28
  if (error instanceof PermissionRequiredError)
@@ -221,6 +223,12 @@ const providerErrorDetails = (error) => {
221
223
  return {
222
224
  provider_id: error.providerId,
223
225
  operation: error.operation,
226
+ ...(error.cleanupIncomplete
227
+ ? {
228
+ cleanup: "incomplete",
229
+ resources: [...error.cleanupResources],
230
+ }
231
+ : {}),
224
232
  ...(error.diagnostics === undefined
225
233
  ? {}
226
234
  : { diagnostics: error.diagnostics }),
@@ -15,6 +15,8 @@ const formatSchema = z.enum([
15
15
  "zip",
16
16
  "ipa",
17
17
  "apk",
18
+ "msix",
19
+ "appx",
18
20
  "asar",
19
21
  "dmg",
20
22
  "pkg",
@@ -45,6 +45,8 @@ const artifactFormatSchema = z.enum([
45
45
  "analysis-database",
46
46
  "ipa",
47
47
  "apk",
48
+ "msix",
49
+ "appx",
48
50
  "plist",
49
51
  "entitlements",
50
52
  "directory",
@@ -0,0 +1,347 @@
1
+ import { createHash } from "node:crypto";
2
+ import canonicalize from "canonicalize";
3
+ import { z } from "zod";
4
+ import { artifactInventoryResultSchema, } from "./artifactGraph.js";
5
+ import { evidenceSchema, parseEvidence } from "./evidence.js";
6
+ import { jsonValueSchema } from "./jsonValue.js";
7
+ const boundedTextSchema = z.string().min(1).max(4_096);
8
+ const evidenceIdSchema = z.string().regex(/^ev_[a-f0-9]{64}$/u);
9
+ const artifactIdSchema = z.string().regex(/^art_[a-f0-9]{64}$/u);
10
+ const inspectionLimitsSchema = z.strictObject({
11
+ max_observations: z.number().int().min(1).max(500).default(100),
12
+ max_relationships: z.number().int().min(1).max(500).default(100),
13
+ max_hypotheses: z.number().int().min(1).max(100).default(20),
14
+ max_unexplored_branches: z.number().int().min(1).max(100).default(20),
15
+ max_next_probes: z.number().int().min(1).max(50).default(20),
16
+ max_substeps: z.literal(1).default(1),
17
+ });
18
+ export const artifactInspectionLimitsSchema = inspectionLimitsSchema;
19
+ const inspectionObservationSchema = z.strictObject({
20
+ observation_id: z.string().regex(/^aio_[a-f0-9]{64}$/u),
21
+ kind: z.enum(["root-manifest", "artifact", "occurrence", "integrity"]),
22
+ subject: boundedTextSchema,
23
+ value: jsonValueSchema,
24
+ evidence_id: evidenceIdSchema,
25
+ });
26
+ const inspectionRelationshipSchema = z.strictObject({
27
+ relationship_id: z.string().regex(/^air_[a-f0-9]{64}$/u),
28
+ relation: z.enum([
29
+ "contains",
30
+ "extracts",
31
+ "slice-of",
32
+ "embeds",
33
+ "loads",
34
+ "maps-source",
35
+ "derived-from",
36
+ ]),
37
+ source_artifact_id: artifactIdSchema,
38
+ target_artifact_id: artifactIdSchema,
39
+ occurrence_id: z.string().regex(/^occ_[a-f0-9]{64}$/u),
40
+ logical_path: boundedTextSchema.nullable(),
41
+ evidence_id: evidenceIdSchema,
42
+ });
43
+ const inspectionHypothesisSchema = z.strictObject({
44
+ hypothesis_id: z.string().regex(/^aih_[a-f0-9]{64}$/u),
45
+ statement: boundedTextSchema,
46
+ confidence: z.enum(["medium", "low"]),
47
+ basis_evidence_ids: z.array(evidenceIdSchema).min(1).max(8),
48
+ limitation: boundedTextSchema,
49
+ });
50
+ const inspectionContradictionSchema = z.strictObject({
51
+ contradiction_id: z.string().regex(/^aic_[a-f0-9]{64}$/u),
52
+ statement: boundedTextSchema,
53
+ occurrence_id: z.string().regex(/^occ_[a-f0-9]{64}$/u),
54
+ declared_sha256: z.string().regex(/^[a-f0-9]{64}$/u),
55
+ observed_sha256: z.string().regex(/^[a-f0-9]{64}$/u),
56
+ evidence_id: evidenceIdSchema,
57
+ });
58
+ const nextProbeSchema = z.strictObject({
59
+ operation: z.string().min(1).max(128),
60
+ rationale: boundedTextSchema,
61
+ authority: z.enum([
62
+ "artifact-bytes",
63
+ "managed-static-analysis",
64
+ "native-analysis-provider",
65
+ "ast-static-analysis",
66
+ ]),
67
+ });
68
+ const unexploredBranchSchema = z.strictObject({
69
+ branch_id: z.string().regex(/^aib_[a-f0-9]{64}$/u),
70
+ reason: z.enum([
71
+ "page-limit",
72
+ "format-specific-analysis-required",
73
+ "unknown-format",
74
+ ]),
75
+ detail: boundedTextSchema,
76
+ next_probe: nextProbeSchema.nullable(),
77
+ evidence_id: evidenceIdSchema,
78
+ });
79
+ /** Provider-neutral inspection result with its atomic source Evidence. */
80
+ export const artifactInspectionResultSchema = z.strictObject({
81
+ schema_version: z.literal(1),
82
+ inspection_id: z.string().regex(/^ai_[a-f0-9]{64}$/u),
83
+ subject: z.strictObject({
84
+ manifest_id: z.string().regex(/^agm_[a-f0-9]{64}$/u),
85
+ root_artifact_id: artifactIdSchema,
86
+ root_sha256: z.string().regex(/^[a-f0-9]{64}$/u),
87
+ root_format: z.string().min(1).max(128),
88
+ }),
89
+ substeps: z
90
+ .array(z.strictObject({
91
+ substep_id: z.string().regex(/^ais_[a-f0-9]{64}$/u),
92
+ operation: z.literal("inventory_artifact"),
93
+ status: z.literal("completed"),
94
+ evidence_id: evidenceIdSchema,
95
+ evidence: evidenceSchema,
96
+ }))
97
+ .min(1)
98
+ .max(1),
99
+ observations: z.array(inspectionObservationSchema).max(500),
100
+ derived_relationships: z.array(inspectionRelationshipSchema).max(500),
101
+ hypotheses: z.array(inspectionHypothesisSchema).max(100),
102
+ contradictions: z.array(inspectionContradictionSchema).max(100),
103
+ unexplored_branches: z.array(unexploredBranchSchema).max(100),
104
+ next_probes: z.array(nextProbeSchema).max(50),
105
+ coverage: z.strictObject({
106
+ status: z.enum(["complete-within-substeps", "partial", "truncated"]),
107
+ substeps_completed: z.literal(1),
108
+ observations_retained: z.number().int().min(0),
109
+ observations_omitted: z.number().int().min(0),
110
+ relationships_retained: z.number().int().min(0),
111
+ relationships_omitted: z.number().int().min(0),
112
+ hypotheses_retained: z.number().int().min(0),
113
+ hypotheses_omitted: z.number().int().min(0),
114
+ unexplored_branches_retained: z.number().int().min(0),
115
+ unexplored_branches_omitted: z.number().int().min(0),
116
+ next_probes_retained: z.number().int().min(0),
117
+ next_probes_omitted: z.number().int().min(0),
118
+ }),
119
+ evidence_links: z.array(evidenceIdSchema).min(1).max(1),
120
+ limitations: z.array(boundedTextSchema).max(1_000),
121
+ });
122
+ /** Project one successful inventory Evidence record into an inspection report. */
123
+ export const createArtifactInspection = (inventoryInput, limits) => {
124
+ const inventoryEvidence = parseInventoryEvidence(inventoryInput);
125
+ const inventory = artifactInventoryResultSchema.parse(inventoryEvidence.normalized_result);
126
+ const observations = allObservations(inventory, inventoryEvidence.evidence_id);
127
+ const relationships = allRelationships(inventory, inventoryEvidence.evidence_id);
128
+ const hypotheses = allHypotheses(inventory, inventoryEvidence.evidence_id);
129
+ const nextProbes = probesFor(inventory);
130
+ const branches = allUnexploredBranches(inventory, inventoryEvidence.evidence_id, nextProbes);
131
+ const retained = {
132
+ observations: observations.slice(0, limits.max_observations),
133
+ relationships: relationships.slice(0, limits.max_relationships),
134
+ hypotheses: hypotheses.slice(0, limits.max_hypotheses),
135
+ branches: branches.slice(0, limits.max_unexplored_branches),
136
+ probes: nextProbes.slice(0, limits.max_next_probes),
137
+ };
138
+ const omissions = {
139
+ observations: observations.length - retained.observations.length,
140
+ relationships: relationships.length - retained.relationships.length,
141
+ hypotheses: hypotheses.length - retained.hypotheses.length,
142
+ branches: branches.length - retained.branches.length,
143
+ probes: nextProbes.length - retained.probes.length,
144
+ };
145
+ const semantic = {
146
+ schema_version: 1,
147
+ subject: {
148
+ manifest_id: inventory.manifest.manifest_id,
149
+ root_artifact_id: inventory.manifest.root_artifact_id,
150
+ root_sha256: inventory.manifest.root_sha256,
151
+ root_format: inventory.manifest.root_format,
152
+ },
153
+ substeps: [
154
+ {
155
+ substep_id: `ais_${digestCanonical({
156
+ operation: "inventory_artifact",
157
+ evidence_id: inventoryEvidence.evidence_id,
158
+ })}`,
159
+ operation: "inventory_artifact",
160
+ status: "completed",
161
+ evidence_id: inventoryEvidence.evidence_id,
162
+ evidence: inventoryEvidence,
163
+ },
164
+ ],
165
+ observations: retained.observations,
166
+ derived_relationships: retained.relationships,
167
+ hypotheses: retained.hypotheses,
168
+ contradictions: contradictions(inventory, inventoryEvidence.evidence_id),
169
+ unexplored_branches: retained.branches,
170
+ next_probes: retained.probes,
171
+ coverage: {
172
+ status: inspectionCoverage(inventory, omissions),
173
+ substeps_completed: 1,
174
+ observations_retained: retained.observations.length,
175
+ observations_omitted: omissions.observations,
176
+ relationships_retained: retained.relationships.length,
177
+ relationships_omitted: omissions.relationships,
178
+ hypotheses_retained: retained.hypotheses.length,
179
+ hypotheses_omitted: omissions.hypotheses,
180
+ unexplored_branches_retained: retained.branches.length,
181
+ unexplored_branches_omitted: omissions.branches,
182
+ next_probes_retained: retained.probes.length,
183
+ next_probes_omitted: omissions.probes,
184
+ },
185
+ evidence_links: [inventoryEvidence.evidence_id],
186
+ limitations: uniqueSorted([
187
+ ...inventory.limitations,
188
+ "Inspection derives bounded static hypotheses and next probes; it does not execute the artifact or claim format-specific semantics.",
189
+ ]),
190
+ };
191
+ return artifactInspectionResultSchema.parse({
192
+ ...semantic,
193
+ inspection_id: `ai_${digestCanonical(semantic)}`,
194
+ });
195
+ };
196
+ const parseInventoryEvidence = (input) => {
197
+ const evidence = parseEvidence(input);
198
+ if (evidence.operation !== "inventory_artifact")
199
+ throw new TypeError("Artifact inspection substep requires inventory_artifact Evidence");
200
+ return evidence;
201
+ };
202
+ const allObservations = (inventory, evidenceId) => [
203
+ observation("root-manifest", inventory.manifest.root_artifact_id, inventory.manifest, evidenceId),
204
+ ...inventory.nodes.items.map((node) => observation("artifact", node.artifact_id, node, evidenceId)),
205
+ ...inventory.occurrences.items.map((occurrence) => observation("occurrence", occurrence.occurrence_id, occurrence, evidenceId)),
206
+ ...inventory.integrity_contradictions.map((value) => observation("integrity", value.contradiction_id, value, evidenceId)),
207
+ ];
208
+ const observation = (kind, subject, value, evidenceId) => {
209
+ const semantic = {
210
+ kind,
211
+ subject,
212
+ value: jsonValueSchema.parse(value),
213
+ evidence_id: evidenceId,
214
+ };
215
+ return { observation_id: `aio_${digestCanonical(semantic)}`, ...semantic };
216
+ };
217
+ const allRelationships = (inventory, evidenceId) => inventory.edges.items.map((edge) => {
218
+ const semantic = {
219
+ relation: edge.relation,
220
+ source_artifact_id: edge.parent_artifact_id,
221
+ target_artifact_id: edge.child_artifact_id,
222
+ occurrence_id: edge.occurrence_id,
223
+ logical_path: edge.logical_path,
224
+ evidence_id: evidenceId,
225
+ };
226
+ return {
227
+ relationship_id: `air_${digestCanonical(semantic)}`,
228
+ ...semantic,
229
+ };
230
+ });
231
+ const allHypotheses = (inventory, evidenceId) => {
232
+ const statements = inventory.manifest.root_format === "pe"
233
+ ? [
234
+ "The PE artifact may contain managed CLI metadata or native code; inventory bytes alone do not distinguish them.",
235
+ ]
236
+ : ["asar", "javascript-bundle"].includes(inventory.manifest.root_format)
237
+ ? [
238
+ "The artifact may contain a recoverable JavaScript application graph.",
239
+ ]
240
+ : [];
241
+ return statements.map((statement) => {
242
+ const semantic = {
243
+ statement,
244
+ confidence: "low",
245
+ basis_evidence_ids: [evidenceId],
246
+ limitation: "Format classification proposes a bounded follow-up; it is not semantic proof.",
247
+ };
248
+ return { hypothesis_id: `aih_${digestCanonical(semantic)}`, ...semantic };
249
+ });
250
+ };
251
+ const contradictions = (inventory, evidenceId) => inventory.integrity_contradictions.map((value) => {
252
+ const semantic = {
253
+ statement: `Declared integrity for ${value.logical_path} contradicts observed bytes.`,
254
+ occurrence_id: value.occurrence_id,
255
+ declared_sha256: value.declared_sha256,
256
+ observed_sha256: value.observed_sha256,
257
+ evidence_id: evidenceId,
258
+ };
259
+ return {
260
+ contradiction_id: `aic_${digestCanonical(semantic)}`,
261
+ ...semantic,
262
+ };
263
+ });
264
+ const probesFor = (inventory) => {
265
+ const format = inventory.manifest.root_format;
266
+ if (["asar", "javascript-bundle", "directory"].includes(format))
267
+ return [
268
+ {
269
+ operation: "analyze_javascript_application",
270
+ rationale: "Recover bounded JavaScript modules, source maps, Electron boundaries, and application relationships.",
271
+ authority: "ast-static-analysis",
272
+ },
273
+ ];
274
+ if (format === "pe")
275
+ return [
276
+ {
277
+ operation: "inspect_managed_artifact",
278
+ rationale: "Check execution-free CLI metadata before choosing a deep native provider.",
279
+ authority: "managed-static-analysis",
280
+ },
281
+ {
282
+ operation: "open_binary",
283
+ rationale: "Open as native code only when managed inspection reports a native or mixed boundary.",
284
+ authority: "native-analysis-provider",
285
+ },
286
+ ];
287
+ if (["mach-o", "mach-o-universal", "elf"].includes(format))
288
+ return [
289
+ {
290
+ operation: "open_binary",
291
+ rationale: "Bind one deep native provider before function-level analysis.",
292
+ authority: "native-analysis-provider",
293
+ },
294
+ ];
295
+ if (format === "plist")
296
+ return [
297
+ {
298
+ operation: "inspect_plist",
299
+ rationale: "Parse property-list values without executing the artifact.",
300
+ authority: "artifact-bytes",
301
+ },
302
+ ];
303
+ return [];
304
+ };
305
+ const allUnexploredBranches = (inventory, evidenceId, nextProbes) => {
306
+ const pages = [
307
+ ["nodes", inventory.nodes.next_offset],
308
+ ["occurrences", inventory.occurrences.next_offset],
309
+ ["relationships", inventory.edges.next_offset],
310
+ ];
311
+ const branches = pages.flatMap(([collection, nextOffset]) => nextOffset === null
312
+ ? []
313
+ : [
314
+ branch("page-limit", `${collection} continue at offset ${String(nextOffset)}.`, null, evidenceId),
315
+ ]);
316
+ branches.push(...nextProbes.map((probe) => branch("format-specific-analysis-required", `${probe.operation} was not run by provider-neutral artifact inspection.`, probe, evidenceId)));
317
+ if (inventory.manifest.root_format === "unknown")
318
+ branches.push(branch("unknown-format", "Artifact bytes did not match an admitted format classifier.", null, evidenceId));
319
+ return branches;
320
+ };
321
+ const branch = (reason, detail, nextProbe, evidenceId) => {
322
+ const semantic = {
323
+ reason,
324
+ detail,
325
+ next_probe: nextProbe,
326
+ evidence_id: evidenceId,
327
+ };
328
+ return { branch_id: `aib_${digestCanonical(semantic)}`, ...semantic };
329
+ };
330
+ const inspectionCoverage = (inventory, omissions) => {
331
+ if (Object.values(omissions).some((count) => count > 0))
332
+ return "truncated";
333
+ return [
334
+ inventory.nodes.next_offset,
335
+ inventory.occurrences.next_offset,
336
+ inventory.edges.next_offset,
337
+ ].some((offset) => offset !== null)
338
+ ? "partial"
339
+ : "complete-within-substeps";
340
+ };
341
+ const digestCanonical = (value) => {
342
+ const encoded = canonicalize(value);
343
+ if (encoded === undefined)
344
+ throw new TypeError("Artifact inspection could not canonicalize");
345
+ return createHash("sha256").update(encoded).digest("hex");
346
+ };
347
+ const uniqueSorted = (values) => [...new Set(values)].sort((left, right) => left < right ? -1 : left > right ? 1 : 0);
@@ -6,6 +6,7 @@ import { extname, isAbsolute, join, relative, resolve, sep } from "node:path";
6
6
  import { promisify } from "node:util";
7
7
  import { BinaryTargetError } from "./errors.js";
8
8
  import { err, ok } from "./result.js";
9
+ import { zipPackageFormatForPath } from "./zipPackageFormat.js";
9
10
  const execFileAsync = promisify(execFile);
10
11
  /**
11
12
  * Resolve and classify a readable local target before a provider is selected.
@@ -71,11 +72,7 @@ const detectArtifactFormat = async (path, handle) => {
71
72
  magic[1] === 0x4b &&
72
73
  [0x03, 0x05, 0x07].includes(magic[2] ?? -1) &&
73
74
  [0x04, 0x06, 0x08].includes(magic[3] ?? -1)) {
74
- return lower.endsWith(".ipa")
75
- ? "ipa"
76
- : lower.endsWith(".apk")
77
- ? "apk"
78
- : "zip";
75
+ return zipPackageFormatForPath(lower) ?? "zip";
79
76
  }
80
77
  const named = namedArtifactFormat(lower);
81
78
  if (named !== undefined)
@@ -104,7 +101,7 @@ const namedArtifactFormat = (lowerPath) => {
104
101
  return "source-map";
105
102
  return /\.(?:m?js|cjs)$/u.test(lowerPath) ? "javascript" : undefined;
106
103
  };
107
- const isArchiveFormat = (format) => ["zip", "ipa", "apk", "asar", "dmg", "pkg"].includes(format);
104
+ const isArchiveFormat = (format) => ["zip", "ipa", "apk", "msix", "appx", "asar", "dmg", "pkg"].includes(format);
108
105
  const sha256Handle = async (handle) => {
109
106
  const hash = createHash("sha256");
110
107
  const chunk = Buffer.allocUnsafe(64 * 1024);