rea-agents 3.0.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 (219) hide show
  1. package/README.md +14 -16
  2. package/dist/application/AnalysisContextQueries.js +21 -9
  3. package/dist/application/ApplicationWorkflowEvidenceResolver.js +19 -11
  4. package/dist/application/ArtifactInventory/policy.js +17 -0
  5. package/dist/application/ArtifactInventory/reader.js +1 -4
  6. package/dist/application/ArtifactInventory/scanCanonical.js +0 -3
  7. package/dist/application/ArtifactInventory/scanReader.js +7 -7
  8. package/dist/application/ArtifactInventory/types.js +1 -5
  9. package/dist/application/BinarySession.js +14 -16
  10. package/dist/application/BinarySessionRecords.js +31 -5
  11. package/dist/application/BinarySessionStatus.js +11 -5
  12. package/dist/application/BrowserEvidence.js +3 -5
  13. package/dist/application/CapabilityClientRequirements.js +26 -0
  14. package/dist/application/CapabilityInventory.js +134 -63
  15. package/dist/application/CrossVersionInventory.js +7 -6
  16. package/dist/application/ElectronActiveEvidence.js +55 -0
  17. package/dist/application/ElectronActiveObservationPort.js +1 -0
  18. package/dist/application/ElectronActiveObservationService.js +81 -0
  19. package/dist/application/EnhancedTools.js +22 -20
  20. package/dist/application/EvidenceBundleCommands.js +5 -1
  21. package/dist/application/EvidenceLedger.js +8 -1
  22. package/dist/application/JavaScriptReplayPermission.js +1 -1
  23. package/dist/application/JavaScriptReplayService.js +23 -15
  24. package/dist/application/ManagedRuntimeCorrelationService.js +9 -5
  25. package/dist/application/NodeRuntimeCharacterizationService.js +8 -9
  26. package/dist/application/ProcessCaptureLifecycle.js +5 -0
  27. package/dist/application/ProcessCli.js +2 -1
  28. package/dist/application/ProcessHarness.js +8 -3
  29. package/dist/application/ProcessNormalization.js +2 -1
  30. package/dist/application/ProjectPermissionStore.js +1 -0
  31. package/dist/application/ReferenceSourceImport.js +2 -2
  32. package/dist/application/SetupClientConfiguration.js +6 -1
  33. package/dist/application/WindowsCapabilities.js +5 -4
  34. package/dist/artifacts/ArtifactProvider.js +8 -10
  35. package/dist/artifacts/SafeOutputTree.js +7 -8
  36. package/dist/browser/CdpCaptureStorageFingerprints.js +10 -7
  37. package/dist/browser/CdpElectronInspection.js +3 -1
  38. package/dist/browser/JavaScriptRuntimeScope.js +5 -0
  39. package/dist/browser/PlaywrightElectronActiveActions.js +324 -0
  40. package/dist/browser/PlaywrightElectronActiveProvider.js +294 -0
  41. package/dist/browser/PlaywrightScenarioBrowser.js +4 -4
  42. package/dist/browser/PlaywrightScenarioSession.js +4 -4
  43. package/dist/browser/SensitiveTextCapture.js +1 -1
  44. package/dist/browser/V8InspectorCaptureProjection.js +1 -0
  45. package/dist/browser/V8InspectorProvider.js +3 -3
  46. package/dist/catalogIdentity.js +12 -6
  47. package/dist/cli/managedCommands.js +1 -1
  48. package/dist/cliApplicationCommands.js +2 -2
  49. package/dist/cliBrowserAdvancedCommands.js +11 -5
  50. package/dist/cliBrowserCommands.js +14 -7
  51. package/dist/cliCommandNames.js +1 -0
  52. package/dist/cliElectronCommands.js +46 -4
  53. package/dist/cliJavaScriptRuntimeCommands.js +14 -6
  54. package/dist/cliObservationOptions.js +4 -0
  55. package/dist/cliPolicyCommands.js +1 -0
  56. package/dist/config/browserScenario.js +77 -0
  57. package/dist/config/electronAutomation.js +35 -0
  58. package/dist/config/environment.js +6 -0
  59. package/dist/config/javascriptReplay.js +41 -0
  60. package/dist/config/managedRuntime.js +25 -0
  61. package/dist/config/parseConfig.js +56 -200
  62. package/dist/config/parsers.js +10 -1
  63. package/dist/config/passiveObservation.js +157 -0
  64. package/dist/config/processCapture.js +47 -0
  65. package/dist/contracts/applicationToolContracts.js +2 -5
  66. package/dist/contracts/applicationWorkflowInputContracts.js +86 -96
  67. package/dist/contracts/artifactToolContracts.js +27 -34
  68. package/dist/contracts/browserToolContracts.js +2 -2
  69. package/dist/contracts/electronToolContracts.js +30 -1
  70. package/dist/contracts/enhancedInputs.js +13 -29
  71. package/dist/contracts/functionWorkflowToolContracts.js +2 -3
  72. package/dist/contracts/managedToolContracts.js +4 -9
  73. package/dist/contracts/managedWorkflowExamples.js +12 -9
  74. package/dist/contracts/managedWorkflowToolContracts.js +30 -27
  75. package/dist/contracts/nativeToolContracts.js +2 -3
  76. package/dist/contracts/sessionToolSchemas.js +61 -0
  77. package/dist/contracts/toolContractExamples.js +1 -0
  78. package/dist/contracts/toolContractHelpers.js +23 -0
  79. package/dist/contracts/toolContracts.js +5 -77
  80. package/dist/contracts/toolEffects.js +15 -0
  81. package/dist/contracts/toolOutputSchemaGroups.js +17 -2
  82. package/dist/contracts/toolOutputSchemaPrimitives.js +76 -26
  83. package/dist/contracts/toolSchemaMetadata.js +128 -0
  84. package/dist/doctorRuntime.js +1 -1
  85. package/dist/domain/androidApplication.js +2 -0
  86. package/dist/domain/appleApplication.js +2 -0
  87. package/dist/domain/binaryTarget.js +7 -5
  88. package/dist/domain/binaryTargetTypes.js +1 -0
  89. package/dist/domain/browserCaptureComparison.js +21 -69
  90. package/dist/domain/browserObservation.js +22 -9
  91. package/dist/domain/bytecodeProvider.js +33 -35
  92. package/dist/domain/callPath.js +3 -2
  93. package/dist/domain/conformanceReplay.js +3 -3
  94. package/dist/domain/conformanceTrustGate.js +151 -16
  95. package/dist/domain/customProtocolCapture.js +3 -3
  96. package/dist/domain/electronActiveObservation.js +277 -0
  97. package/dist/domain/electronObservation.js +15 -11
  98. package/dist/domain/electronStaticAnalysisValues.js +4 -1
  99. package/dist/domain/eventProcessTree.js +82 -79
  100. package/dist/domain/functionComparisonNormalization.js +15 -8
  101. package/dist/domain/functionDossierEvidence.js +9 -4
  102. package/dist/domain/hopperValues.js +68 -71
  103. package/dist/domain/inputIssueProjection.js +4 -1
  104. package/dist/domain/investigationWorkspace.js +16 -15
  105. package/dist/domain/javascriptExportShapeComparisonSchemas.js +2 -2
  106. package/dist/domain/javascriptReplay.js +79 -63
  107. package/dist/domain/javascriptRuntimeObservation.js +1 -0
  108. package/dist/domain/javascriptRuntimeReconciliationActive.js +89 -0
  109. package/dist/domain/javascriptRuntimeReconciliationGraph.js +11 -10
  110. package/dist/domain/javascriptRuntimeReconciliationMatching.js +57 -49
  111. package/dist/domain/javascriptRuntimeReconciliationParsing.js +5 -1
  112. package/dist/domain/javascriptRuntimeReconciliationResult.js +21 -14
  113. package/dist/domain/javascriptRuntimeReconciliationSchemas.js +1 -1
  114. package/dist/domain/knownPageCoverage.js +15 -7
  115. package/dist/domain/nativeApiBoundary.js +15 -7
  116. package/dist/domain/nodeRuntimeCharacterization.js +14 -13
  117. package/dist/domain/processCaptureReactiveValidation.js +8 -3
  118. package/dist/domain/processCaptureValidation.js +7 -3
  119. package/dist/domain/processComparison.js +12 -7
  120. package/dist/domain/processObservation.js +5 -6
  121. package/dist/domain/processReactiveMatching.js +14 -7
  122. package/dist/domain/processReactiveTransition.js +9 -3
  123. package/dist/domain/processScenario.js +6 -3
  124. package/dist/domain/processTraceComparison.js +3 -2
  125. package/dist/domain/protocolCapture.js +8 -6
  126. package/dist/domain/reconstructionReadinessSchemas.js +30 -2
  127. package/dist/domain/referenceSourceImportParsing.js +2 -2
  128. package/dist/domain/replayMachineRuntime.js +5 -3
  129. package/dist/domain/sourceToBundleComparison.js +2 -2
  130. package/dist/domain/sourceToBundleComparisonSchemas.js +8 -8
  131. package/dist/domain/sourceToBundleSignals.js +7 -1
  132. package/dist/domain/staticRuntimeCorrelation.js +7 -5
  133. package/dist/domain/webBundleAnalysis.js +14 -14
  134. package/dist/domain/webCaptureDiff.js +15 -12
  135. package/dist/dotnet/ManagedNativeBoundaryInspector.js +2 -3
  136. package/dist/generatedMcpToolCatalog.js +1 -1
  137. package/dist/generatedPackageMetadata.js +1 -1
  138. package/dist/ghidra/GhidraClient.js +1 -1
  139. package/dist/ghidra/GhidraClientStartup.js +1 -1
  140. package/dist/ghidra/GhidraFunctionValues.js +17 -15
  141. package/dist/ghidra/GhidraInventoryValues.js +57 -47
  142. package/dist/ghidra/GhidraProvider.js +18 -10
  143. package/dist/ghidra/GhidraProviderCapabilities.js +5 -1
  144. package/dist/ghidra/GhidraSocketConnection.js +1 -1
  145. package/dist/ghidra/protocol.js +19 -42
  146. package/dist/hopper/BridgeLauncher.js +3 -1
  147. package/dist/hopper/HopperAnalysisProfile.js +2 -4
  148. package/dist/hopper/HopperCleanup.js +5 -6
  149. package/dist/hopper/HopperClient.js +1 -1
  150. package/dist/hopper/HopperProvider.js +0 -14
  151. package/dist/hopper/LinuxPrivateDisplayProbe.js +16 -10
  152. package/dist/main/reload.js +1 -6
  153. package/dist/main/state.js +0 -14
  154. package/dist/main/transport.js +30 -37
  155. package/dist/main.js +17 -15
  156. package/dist/mcpDoctor.js +2 -24
  157. package/dist/process/PrivateRuntimeRoot.js +17 -0
  158. package/dist/process/ProcessOwnership.js +64 -128
  159. package/dist/process/ProcessOwnershipIdentity.js +13 -0
  160. package/dist/process/ProcessOwnershipObservation.js +88 -0
  161. package/dist/process/ProcessOwnershipProcessTree.js +22 -0
  162. package/dist/process/ProviderDeadline.js +8 -12
  163. package/dist/process/WindowsAuthority.js +32 -0
  164. package/dist/reference/ReferenceSourceReader.js +3 -3
  165. package/dist/reference/ReferenceSourceReaderEntries.js +2 -2
  166. package/dist/replay/JavaScriptReplayWorker.js +95 -11
  167. package/dist/replay/JavaScriptReplayWorkerTypes.js +1 -0
  168. package/dist/replay/LinuxJavaScriptReplayRunner.js +10 -15
  169. package/dist/replay/ReplayOutcome.js +26 -15
  170. package/dist/replay/ReplayWorkerProtocol.js +34 -29
  171. package/dist/server/createServer.js +158 -94
  172. package/dist/server/mcpClientMetadata.js +32 -0
  173. package/dist/server/registerApplicationTools/characterization.js +6 -13
  174. package/dist/server/registerApplicationTools/compareExportShapes.js +2 -7
  175. package/dist/server/registerApplicationTools/compareSourceToBundle.js +2 -7
  176. package/dist/server/registerApplicationTools/compareVersions.js +3 -8
  177. package/dist/server/registerApplicationTools/controlledReplay.js +6 -11
  178. package/dist/server/registerApplicationTools/coverage.js +13 -19
  179. package/dist/server/registerApplicationTools/obligationLedger.js +1 -6
  180. package/dist/server/registerApplicationTools/readiness.js +1 -6
  181. package/dist/server/registerApplicationTools/traceFeature.js +3 -8
  182. package/dist/server/registerApplicationTools/traceSemantics.js +1 -6
  183. package/dist/server/registerArtifactComparisonTool.js +12 -16
  184. package/dist/server/registerBrowserScenarioTool.js +1 -6
  185. package/dist/server/registerBrowserTools.js +37 -79
  186. package/dist/server/registerBundleComparisonTool.js +10 -14
  187. package/dist/server/registerCloseLifecycleTool.js +6 -14
  188. package/dist/server/registerElectronTools.js +30 -47
  189. package/dist/server/registerEnhancedTools.js +114 -122
  190. package/dist/server/registerEvidenceTools.js +5 -9
  191. package/dist/server/registerFunctionComparisonTool.js +11 -15
  192. package/dist/server/registerInvestigationTools.js +41 -57
  193. package/dist/server/registerJavaScriptRuntimeObservationTools.js +13 -27
  194. package/dist/server/registerManagedWorkflowTools/compareManagedMembers.js +4 -9
  195. package/dist/server/registerManagedWorkflowTools/contract.js +2 -3
  196. package/dist/server/registerManagedWorkflowTools/importManagedReconstruction.js +3 -8
  197. package/dist/server/registerManagedWorkflowTools/planManagedRuntimeCorrelation.js +3 -8
  198. package/dist/server/registerManagedWorkflowTools/projectManagedApplicationGraph.js +8 -13
  199. package/dist/server/registerManagedWorkflowTools/verifyManagedNativeBoundaries.js +4 -9
  200. package/dist/server/registerOfficialTools.js +8 -9
  201. package/dist/server/registerProcessComparisonTool.js +19 -24
  202. package/dist/server/registerReplayMachineTool.js +4 -10
  203. package/dist/server/registerSessionRecordTools.js +69 -40
  204. package/dist/server/registerSessionStatusTool.js +13 -28
  205. package/dist/server/registerSessionTools.js +36 -52
  206. package/dist/server/sessionAvailabilityPolicy.js +2 -1
  207. package/dist/server/sessionToolPolicies.js +1 -5
  208. package/dist/server/toolRegistrationOptions.js +4 -192
  209. package/dist/server/toolResult.js +2 -18
  210. package/package.json +22 -14
  211. package/scripts/electron-active-hook-boundaries.cjs +394 -0
  212. package/scripts/electron-active-hook.cjs +501 -0
  213. package/scripts/rea.mjs +1 -11
  214. package/skills/reverse-engineer-anything/SKILL.md +2 -2
  215. package/dist/server/DynamicToolAvailability.js +0 -70
  216. package/dist/server/LazyToolCatalog.js +0 -134
  217. package/dist/server/hydrateServerTools.js +0 -191
  218. package/dist/server/toolInputValidation.js +0 -77
  219. package/scripts/package-runner-bootstrap.mjs +0 -72
@@ -0,0 +1,277 @@
1
+ import { isAbsolute } from "node:path";
2
+ import { z } from "zod";
3
+ const absolutePathSchema = z
4
+ .string()
5
+ .min(1)
6
+ .max(16_384)
7
+ .refine(isAbsolute, "path must be absolute");
8
+ const windowIndexSchema = z.number().int().min(0).max(99);
9
+ const deepLinkUrlSchema = z
10
+ .string()
11
+ .min(1)
12
+ .max(4_096)
13
+ .refine((value) => {
14
+ try {
15
+ return new URL(value).protocol.length > 0;
16
+ }
17
+ catch {
18
+ return false;
19
+ }
20
+ }, "deep-link url must be an absolute URL");
21
+ const actionSchema = z.discriminatedUnion("kind", [
22
+ z.strictObject({
23
+ step_id: z.string().min(1).max(128),
24
+ kind: z.literal("click"),
25
+ selector: z.string().min(1).max(512),
26
+ window_index: windowIndexSchema.default(0),
27
+ }),
28
+ z.strictObject({
29
+ step_id: z.string().min(1).max(128),
30
+ kind: z.literal("wait"),
31
+ duration_ms: z.number().int().min(0).max(10_000),
32
+ window_index: windowIndexSchema.optional(),
33
+ }),
34
+ z.strictObject({
35
+ step_id: z.string().min(1).max(128),
36
+ kind: z.literal("renderer-reload"),
37
+ window_index: windowIndexSchema.default(0),
38
+ }),
39
+ z.strictObject({
40
+ step_id: z.string().min(1).max(128),
41
+ kind: z.literal("renderer-crash"),
42
+ window_index: windowIndexSchema.default(0),
43
+ }),
44
+ z.strictObject({
45
+ step_id: z.string().min(1).max(128),
46
+ kind: z.literal("deep-link"),
47
+ delivery: z.enum(["open-url", "second-instance"]),
48
+ url: deepLinkUrlSchema,
49
+ }),
50
+ ]);
51
+ const limitsSchema = z.strictObject({
52
+ max_duration_ms: z.number().int().min(1).max(120_000).default(60_000),
53
+ action_timeout_ms: z.number().int().min(1).max(30_000).default(5_000),
54
+ max_actions: z.number().int().min(1).max(100).default(20),
55
+ max_ipc_events: z.number().int().min(1).max(10_000).default(2_000),
56
+ max_runtime_events: z.number().int().min(1).max(20_000).default(5_000),
57
+ max_processes: z.number().int().min(1).max(100).default(32),
58
+ max_windows: z.number().int().min(1).max(100).default(32),
59
+ });
60
+ /** Input for one explicit, provider-owned Electron runtime experiment. */
61
+ export const electronActiveObservationInputSchema = z
62
+ .strictObject({
63
+ schema_version: z.literal(1),
64
+ executable_path: absolutePathSchema,
65
+ application_path: absolutePathSchema,
66
+ application_root: absolutePathSchema,
67
+ args: z.array(z.string().max(4_096)).max(32).default([]),
68
+ actions: z.array(actionSchema).max(100).default([]),
69
+ limits: limitsSchema.default({
70
+ max_duration_ms: 60_000,
71
+ action_timeout_ms: 5_000,
72
+ max_actions: 20,
73
+ max_ipc_events: 2_000,
74
+ max_runtime_events: 5_000,
75
+ max_processes: 32,
76
+ max_windows: 32,
77
+ }),
78
+ approved: z.literal(true),
79
+ })
80
+ .superRefine((input, context) => {
81
+ if (input.actions.length > input.limits.max_actions)
82
+ context.addIssue({
83
+ code: "custom",
84
+ path: ["actions"],
85
+ message: "actions exceed the configured max_actions limit",
86
+ });
87
+ });
88
+ const ipcEventSchema = z.strictObject({
89
+ sequence: z.number().int().min(1),
90
+ correlation_id: z.string().max(256).nullable().default(null),
91
+ kind: z.enum([
92
+ "main-handler-invocation",
93
+ "main-event-invocation",
94
+ "utility-process-fork",
95
+ "utility-process-message",
96
+ "ipc-main-to-renderer",
97
+ "ipc-utility-to-main",
98
+ "ipc-renderer-send",
99
+ "ipc-renderer-invoke",
100
+ "ipc-renderer-post-message",
101
+ ]),
102
+ event: z.string().max(128).nullable().optional(),
103
+ phase: z
104
+ .enum(["attempted", "completed", "blocked", "failed", "observed"])
105
+ .nullable()
106
+ .optional(),
107
+ channel: z.string().max(1_024).nullable(),
108
+ channel_truncated: z.boolean().default(false),
109
+ direction: z
110
+ .enum([
111
+ "renderer-to-main",
112
+ "main-to-renderer",
113
+ "main-to-utility",
114
+ "utility-to-main",
115
+ ])
116
+ .nullable()
117
+ .optional(),
118
+ sender: z.string().max(256).nullable().optional(),
119
+ receiver: z.string().max(256).nullable().optional(),
120
+ frame: z.string().max(256).nullable().default(null),
121
+ target: z.string().max(256).nullable().optional(),
122
+ argument_shapes: z.array(z.string().max(64)).max(32),
123
+ argument_shapes_truncated: z.boolean().default(false),
124
+ result_shape: z.string().max(64).nullable(),
125
+ process_type: z.string().max(128).nullable(),
126
+ source: z.string().max(64).default("electron-active-hook"),
127
+ capture_method: z
128
+ .enum(["api-wrapper", "event-emitter", "process-hook"])
129
+ .default("api-wrapper"),
130
+ artifact_path: z.string().max(16_384).nullable().default(null),
131
+ artifact_sha256: z
132
+ .string()
133
+ .regex(/^[a-f0-9]{64}$/u)
134
+ .nullable()
135
+ .default(null),
136
+ error: z.boolean(),
137
+ });
138
+ const timelineEventSchema = z.strictObject({
139
+ sequence: z.number().int().min(1),
140
+ correlation_id: z.string().max(256).nullable().default(null),
141
+ kind: z.enum([
142
+ "main-handler-invocation",
143
+ "main-event-invocation",
144
+ "utility-process-fork",
145
+ "utility-process-message",
146
+ "ipc-main-to-renderer",
147
+ "ipc-utility-to-main",
148
+ "ipc-renderer-send",
149
+ "ipc-renderer-invoke",
150
+ "ipc-renderer-post-message",
151
+ "app-lifecycle",
152
+ "window-lifecycle",
153
+ "web-contents-lifecycle",
154
+ "navigation",
155
+ "shell-attempt",
156
+ "process-lifecycle",
157
+ "permission",
158
+ "popup-attempt",
159
+ "download",
160
+ "protocol",
161
+ "preload",
162
+ "native-addon",
163
+ "updater",
164
+ "error",
165
+ ]),
166
+ event: z.string().max(128).nullable(),
167
+ phase: z.enum(["attempted", "completed", "blocked", "failed", "observed"]),
168
+ channel: z.string().max(1_024).nullable(),
169
+ channel_truncated: z.boolean(),
170
+ direction: z
171
+ .enum([
172
+ "renderer-to-main",
173
+ "main-to-renderer",
174
+ "main-to-utility",
175
+ "utility-to-main",
176
+ ])
177
+ .nullable(),
178
+ sender: z.string().max(256).nullable(),
179
+ receiver: z.string().max(256).nullable(),
180
+ frame: z.string().max(256).nullable(),
181
+ target: z.string().max(256).nullable(),
182
+ argument_shapes: z.array(z.string().max(64)).max(32),
183
+ argument_shapes_truncated: z.boolean(),
184
+ result_shape: z.string().max(64).nullable(),
185
+ process_type: z.string().max(128).nullable(),
186
+ source: z.string().max(64),
187
+ capture_method: z.enum(["api-wrapper", "event-emitter", "process-hook"]),
188
+ artifact_path: z.string().max(16_384).nullable(),
189
+ artifact_sha256: z
190
+ .string()
191
+ .regex(/^[a-f0-9]{64}$/u)
192
+ .nullable(),
193
+ error: z.boolean(),
194
+ });
195
+ const processMetricSchema = z.strictObject({
196
+ pid: z.number().int().min(1),
197
+ type: z.string().min(1).max(128),
198
+ name: z.string().max(256).nullable(),
199
+ service_name: z.string().max(256).nullable(),
200
+ });
201
+ const windowResultSchema = z.strictObject({
202
+ window_id: z.string().max(256),
203
+ web_contents_id: z.string().max(256),
204
+ url: z.string().max(65_536),
205
+ title: z.string().max(16_384),
206
+ visible: z.boolean().nullable(),
207
+ destroyed: z.boolean(),
208
+ });
209
+ const coverageSchema = z.strictObject({
210
+ status: z.enum([
211
+ "complete",
212
+ "partial_attach",
213
+ "capture_truncated",
214
+ "hook_conflict",
215
+ "target_exited",
216
+ "cleanup_failed",
217
+ ]),
218
+ observed_event_families: z.array(z.string().max(128)).max(32),
219
+ unavailable_event_families: z.array(z.string().max(128)).max(32),
220
+ observed_roles: z.array(z.string().max(128)).max(16),
221
+ pre_capture_activity: z.literal("unavailable"),
222
+ });
223
+ const actionResultSchema = z.strictObject({
224
+ step_id: z.string().min(1).max(128),
225
+ kind: z.enum([
226
+ "click",
227
+ "wait",
228
+ "renderer-reload",
229
+ "renderer-crash",
230
+ "deep-link",
231
+ ]),
232
+ window_index: windowIndexSchema.nullable(),
233
+ target: z.string().max(256).nullable(),
234
+ status: z.enum(["completed", "failed", "cancelled"]),
235
+ elapsed_ms: z.number().int().min(0),
236
+ error: z.string().nullable(),
237
+ });
238
+ /** Bounded result of a provider-owned Electron runtime experiment. */
239
+ export const electronActiveObservationResultSchema = z.strictObject({
240
+ schema_version: z.literal(1),
241
+ application: z.strictObject({
242
+ executable_path: absolutePathSchema,
243
+ application_path: absolutePathSchema,
244
+ electron_version: z.string().min(1).max(256),
245
+ process_ownership: z.literal("provider-owned"),
246
+ cleanup: z.literal("terminated-owned-process"),
247
+ }),
248
+ actions: z.array(actionResultSchema).max(100),
249
+ windows: z.array(windowResultSchema).max(100),
250
+ windows_truncated: z.boolean(),
251
+ processes: z.strictObject({
252
+ items: z.array(processMetricSchema).max(100),
253
+ truncated: z.boolean(),
254
+ }),
255
+ ipc: z.strictObject({
256
+ events: z.array(ipcEventSchema).max(10_000),
257
+ observed: z.number().int().min(0),
258
+ retained: z.number().int().min(0),
259
+ truncated: z.boolean(),
260
+ }),
261
+ timeline: z
262
+ .strictObject({
263
+ events: z.array(timelineEventSchema).max(20_000),
264
+ observed: z.number().int().min(0),
265
+ retained: z.number().int().min(0),
266
+ truncated: z.boolean(),
267
+ })
268
+ .default({ events: [], observed: 0, retained: 0, truncated: false }),
269
+ coverage: coverageSchema.default({
270
+ status: "partial_attach",
271
+ observed_event_families: [],
272
+ unavailable_event_families: [],
273
+ observed_roles: [],
274
+ pre_capture_activity: "unavailable",
275
+ }),
276
+ limitations: z.array(z.string().max(4_096)).max(100),
277
+ });
@@ -25,13 +25,10 @@ export const listElectronTargetsInputSchema = z.object({
25
25
  limit: z.number().int().min(1).max(200).default(100),
26
26
  });
27
27
  /** Input for passive structural inspection of one Electron file page. */
28
- export const inspectElectronPageInputSchema = z
29
- .object({
28
+ const inspectElectronPageFacts = {
30
29
  ...approvedElectronInput,
31
30
  target_id: z.string().trim().min(1).max(256),
32
31
  observation_ms: z.number().int().min(0).max(10_000).default(100),
33
- include_script_sources: z.boolean().default(false),
34
- source_capture_approved: z.boolean().default(false),
35
32
  limits: z
36
33
  .object({
37
34
  max_frames: z.number().int().min(1).max(1_000).default(200),
@@ -61,14 +58,21 @@ export const inspectElectronPageInputSchema = z
61
58
  max_script_source_bytes: 1_024 * 1_024,
62
59
  max_total_script_source_bytes: 4 * 1_024 * 1_024,
63
60
  }),
64
- })
61
+ };
62
+ export const inspectElectronPageInputSchema = z
63
+ .union([
64
+ z.object({
65
+ ...inspectElectronPageFacts,
66
+ include_script_sources: z.literal(false).default(false),
67
+ source_capture_approved: z.literal(false).default(false),
68
+ }),
69
+ z.object({
70
+ ...inspectElectronPageFacts,
71
+ include_script_sources: z.literal(true),
72
+ source_capture_approved: z.literal(true),
73
+ }),
74
+ ])
65
75
  .superRefine((input, context) => {
66
- if (input.include_script_sources && !input.source_capture_approved)
67
- context.addIssue({
68
- code: "custom",
69
- path: ["source_capture_approved"],
70
- message: "Electron script source capture requires separate approval",
71
- });
72
76
  if (input.limits.max_script_source_bytes >
73
77
  input.limits.max_total_script_source_bytes)
74
78
  context.addIssue({
@@ -51,7 +51,10 @@ export const collectContextBridgeMembers = (node, maximum = 128) => {
51
51
  unknown: 1,
52
52
  omitted: 0,
53
53
  };
54
- const state = { members: [], unknown: 0 };
54
+ const state = {
55
+ members: [],
56
+ unknown: 0,
57
+ };
55
58
  collectMembersAt(node, "", 0, state);
56
59
  const members = [...new Set(state.members)].sort(compareCodePoints);
57
60
  return {
@@ -71,89 +71,90 @@ export const processTreeReconstructionSchema = z.strictObject({
71
71
  /** Whether any reparenting was detected. */
72
72
  has_reparenting: z.boolean().default(false),
73
73
  });
74
+ const applyProcessTreeEvent = (event, state) => {
75
+ let node = state.nodes.get(event.pid);
76
+ switch (event.type) {
77
+ case "spawn": {
78
+ if (!node) {
79
+ node = {
80
+ pid: event.pid,
81
+ ppid: event.ppid,
82
+ process_name: event.process_name,
83
+ executable: event.executable,
84
+ arguments: event.arguments,
85
+ children: [],
86
+ spawn_time_ms: event.at_ms,
87
+ exit_time_ms: null,
88
+ exit_code: null,
89
+ is_re_exec: false,
90
+ is_reparented: false,
91
+ previous_ppid: null,
92
+ };
93
+ state.nodes.set(event.pid, node);
94
+ }
95
+ if (event.ppid !== null) {
96
+ const parentChildren = state.children.get(event.ppid) ?? [];
97
+ parentChildren.push(event.pid);
98
+ state.children.set(event.ppid, parentChildren);
99
+ }
100
+ break;
101
+ }
102
+ case "exit":
103
+ if (node) {
104
+ node.exit_time_ms = event.at_ms;
105
+ node.exit_code = event.exit_code;
106
+ if (node.spawn_time_ms !== null &&
107
+ event.at_ms - node.spawn_time_ms < 100)
108
+ state.shortLivedDescendants++;
109
+ }
110
+ else
111
+ state.eventsUnmatched++;
112
+ break;
113
+ case "re_exec":
114
+ if (node) {
115
+ node.is_re_exec = true;
116
+ node.executable = event.executable ?? node.executable;
117
+ node.arguments = event.arguments;
118
+ state.hasReExec = true;
119
+ }
120
+ else
121
+ state.eventsUnmatched++;
122
+ break;
123
+ case "reparent":
124
+ if (node) {
125
+ node.previous_ppid = node.ppid;
126
+ node.ppid = event.ppid;
127
+ node.is_reparented = true;
128
+ state.hasReparenting = true;
129
+ }
130
+ else
131
+ state.eventsUnmatched++;
132
+ break;
133
+ case "signal":
134
+ case "name_change":
135
+ case "thread_create":
136
+ case "thread_exit":
137
+ // These events are recorded but don't modify the tree structure.
138
+ break;
139
+ }
140
+ };
74
141
  /** Reconstruct a process tree from event-backed capture. */
75
142
  export function reconstructProcessTree(events, rootPid) {
76
143
  const nodes = new Map();
77
144
  const children = new Map();
78
145
  let eventsConsumed = 0;
79
- let eventsUnmatched = 0;
80
- let hasReExec = false;
81
- let hasReparenting = false;
82
- let shortLivedDescendants = 0;
146
+ const state = {
147
+ nodes,
148
+ children,
149
+ eventsUnmatched: 0,
150
+ hasReExec: false,
151
+ hasReparenting: false,
152
+ shortLivedDescendants: 0,
153
+ };
83
154
  const sorted = [...events].sort((a, b) => a.at_ms - b.at_ms);
84
155
  for (const event of sorted) {
85
156
  eventsConsumed++;
86
- let node = nodes.get(event.pid);
87
- switch (event.type) {
88
- case "spawn": {
89
- if (!node) {
90
- node = {
91
- pid: event.pid,
92
- ppid: event.ppid,
93
- process_name: event.process_name,
94
- executable: event.executable,
95
- arguments: event.arguments,
96
- children: [],
97
- spawn_time_ms: event.at_ms,
98
- exit_time_ms: null,
99
- exit_code: null,
100
- is_re_exec: false,
101
- is_reparented: false,
102
- previous_ppid: null,
103
- };
104
- nodes.set(event.pid, node);
105
- }
106
- if (event.ppid !== null) {
107
- const parentChildren = children.get(event.ppid) ?? [];
108
- parentChildren.push(event.pid);
109
- children.set(event.ppid, parentChildren);
110
- }
111
- break;
112
- }
113
- case "exit": {
114
- if (node) {
115
- node.exit_time_ms = event.at_ms;
116
- node.exit_code = event.exit_code;
117
- if (node.spawn_time_ms !== null &&
118
- event.at_ms - node.spawn_time_ms < 100)
119
- shortLivedDescendants++;
120
- }
121
- else {
122
- eventsUnmatched++;
123
- }
124
- break;
125
- }
126
- case "re_exec": {
127
- if (node) {
128
- node.is_re_exec = true;
129
- node.executable = event.executable ?? node.executable;
130
- node.arguments = event.arguments;
131
- hasReExec = true;
132
- }
133
- else {
134
- eventsUnmatched++;
135
- }
136
- break;
137
- }
138
- case "reparent": {
139
- if (node) {
140
- node.previous_ppid = node.ppid;
141
- node.ppid = event.ppid;
142
- node.is_reparented = true;
143
- hasReparenting = true;
144
- }
145
- else {
146
- eventsUnmatched++;
147
- }
148
- break;
149
- }
150
- case "signal":
151
- case "name_change":
152
- case "thread_create":
153
- case "thread_exit":
154
- // These events are recorded but don't modify the tree structure
155
- break;
156
- }
157
+ applyProcessTreeEvent(event, state);
157
158
  }
158
159
  // Attach children to nodes
159
160
  for (const [pid, childPids] of children) {
@@ -165,10 +166,10 @@ export function reconstructProcessTree(events, rootPid) {
165
166
  root_pid: rootPid,
166
167
  processes: [...nodes.values()],
167
168
  events_consumed: eventsConsumed,
168
- events_unmatched: eventsUnmatched,
169
- short_lived_descendants: shortLivedDescendants,
170
- has_re_exec: hasReExec,
171
- has_reparenting: hasReparenting,
169
+ events_unmatched: state.eventsUnmatched,
170
+ short_lived_descendants: state.shortLivedDescendants,
171
+ has_re_exec: state.hasReExec,
172
+ has_reparenting: state.hasReparenting,
172
173
  };
173
174
  }
174
175
  /** Get all descendant PIDs of a given root PID. */
@@ -179,6 +180,8 @@ export function getDescendants(processes, rootPid) {
179
180
  const queue = [rootPid];
180
181
  while (queue.length > 0) {
181
182
  const pid = queue.shift();
183
+ if (pid === undefined)
184
+ break;
182
185
  if (visited.has(pid))
183
186
  continue;
184
187
  visited.add(pid);
@@ -123,14 +123,21 @@ export const stringAndNameProjection = (snapshot) => {
123
123
  : sorted(values);
124
124
  };
125
125
  export const sorted = (values) => [...values].sort((left, right) => canonicalJson(left).localeCompare(canonicalJson(right)));
126
- export const combineCoverage = (left, right) => ({
127
- items: [...left.items, ...right.items],
128
- total: left.total === null || right.total === null
129
- ? null
130
- : left.total + right.total,
131
- complete: left.complete && right.complete,
132
- truncated: left.truncated || right.truncated,
133
- });
126
+ export const combineCoverage = (left, right) => {
127
+ const base = {
128
+ items: [...left.items, ...right.items],
129
+ total: left.total === null || right.total === null
130
+ ? null
131
+ : left.total + right.total,
132
+ };
133
+ return left.complete && right.complete
134
+ ? { ...base, complete: true, truncated: false }
135
+ : {
136
+ ...base,
137
+ complete: false,
138
+ truncated: left.truncated || right.truncated,
139
+ };
140
+ };
134
141
  export const project = (collection, mapper) => collection.items.map(mapper);
135
142
  export const isAutoName = (name) => /^(?:sub_[0-9a-f]+|fcn\.)/iu.test(name);
136
143
  const parseAddress = (value) => /^0x[0-9a-f]+$/iu.test(value) ? BigInt(value) : null;
@@ -109,8 +109,9 @@ const mergePseudocode = (pages) => {
109
109
  return {
110
110
  text: orderedValues(characters).join(""),
111
111
  total,
112
- complete,
113
- truncated: !complete,
112
+ ...(complete
113
+ ? { complete: true, truncated: false }
114
+ : { complete: false, truncated: true }),
114
115
  };
115
116
  };
116
117
  const mergeCollection = (pages, field) => {
@@ -140,8 +141,12 @@ const mergeCollection = (pages, field) => {
140
141
  return {
141
142
  items: orderedValues(items),
142
143
  total,
143
- complete,
144
- truncated: scanLimited || (!unavailable && !complete),
144
+ ...(complete
145
+ ? { complete: true, truncated: false }
146
+ : {
147
+ complete: false,
148
+ truncated: scanLimited || !unavailable,
149
+ }),
145
150
  };
146
151
  };
147
152
  const collectionOffset = (page, field) => field === "assembly"