rea-agents 1.6.0 → 2.0.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.
- package/README.md +157 -66
- package/bridge/ghidra/ReaGhidraBridge.java +2075 -0
- package/bridge/hopper_bridge.py +13 -3
- package/dist/application/AbortablePromise.js +25 -0
- package/dist/application/AnalysisProvider.js +3 -0
- package/dist/application/AnalysisProviderEvaluation.js +60 -0
- package/dist/application/AnalysisProviderRegistry.js +228 -0
- package/dist/application/AnalysisSnapshotCache.js +41 -21
- package/dist/application/AnalysisSnapshotFiles.js +5 -6
- package/dist/application/BinarySession.js +218 -101
- package/dist/application/CapabilityInventory.js +18 -0
- package/dist/application/CompositeProvider.js +20 -8
- package/dist/application/CrossVersionInvestigation.js +10 -6
- package/dist/application/DirectAnalysis.js +49 -35
- package/dist/application/Doctor.js +110 -8
- package/dist/application/ElectronBoundaryAnalysis.js +96 -0
- package/dist/application/ElectronBoundaryGraph.js +9 -0
- package/dist/application/ElectronBoundaryGraphContext.js +62 -0
- package/dist/application/ElectronBoundaryGraphIpc.js +242 -0
- package/dist/application/ElectronBoundaryGraphNative.js +86 -0
- package/dist/application/ElectronBoundaryGraphWindows.js +199 -0
- package/dist/application/EnhancedTools.js +39 -14
- package/dist/application/InvestigationProviders.js +41 -0
- package/dist/application/JavaScriptApplicationEvidence.js +26 -0
- package/dist/application/JavaScriptApplicationEvidenceGraph.js +89 -0
- package/dist/application/JavaScriptApplicationService.js +74 -0
- package/dist/application/JavaScriptApplicationWorkflowEvidence.js +29 -0
- package/dist/application/JavaScriptApplicationWorkflowService.js +90 -0
- package/dist/application/JavaScriptArtifactAnalysis.js +305 -0
- package/dist/application/JavaScriptArtifactAnalysisTypes.js +1 -0
- package/dist/application/JavaScriptArtifactFiles.js +231 -0
- package/dist/application/JavaScriptArtifactGraphAccumulator.js +54 -0
- package/dist/application/JavaScriptArtifactGraphBuilder.js +144 -0
- package/dist/application/JavaScriptArtifactGraphContext.js +205 -0
- package/dist/application/JavaScriptArtifactGraphDocuments.js +108 -0
- package/dist/application/JavaScriptArtifactGraphEvidence.js +99 -0
- package/dist/application/JavaScriptArtifactGraphFindings.js +271 -0
- package/dist/application/JavaScriptArtifactGraphStructure.js +409 -0
- package/dist/application/JavaScriptArtifactReconstruction.js +77 -0
- package/dist/application/JavaScriptArtifactReconstructionInput.js +18 -0
- package/dist/application/JavaScriptReplayPlanning.js +201 -0
- package/dist/application/JavaScriptReplayService.js +266 -0
- package/dist/application/JavaScriptRuntimeReconciliationEvidence.js +25 -0
- package/dist/application/JavaScriptRuntimeReconciliationService.js +27 -0
- package/dist/application/MacHopper.js +20 -4
- package/dist/application/ManagedApplicationGraphService.js +55 -0
- package/dist/application/ManagedMemberComparisonService.js +122 -0
- package/dist/application/ManagedNativeVerificationService.js +39 -0
- package/dist/application/ManagedReconstructionService.js +58 -0
- package/dist/application/ManagedRuntimeCorrelationService.js +103 -0
- package/dist/application/PermissionAuthority.js +1 -1
- package/dist/application/ProcessCaptureLifecycle.js +1 -1
- package/dist/application/ProcessHarness.js +1 -1
- package/dist/application/ProcessSampling.js +16 -12
- package/dist/application/ProjectPermissionStore.js +1 -0
- package/dist/application/SessionProviderRouter.js +219 -0
- package/dist/application/Setup.js +84 -60
- package/dist/application/SetupClients.js +1 -1
- package/dist/application/SetupPlan.js +9 -2
- package/dist/application/SupportedClients.js +40 -16
- package/dist/application/Upgrade.js +1 -1
- package/dist/application/runtime.js +11 -6
- package/dist/artifacts/AsarArtifactReader.js +23 -3
- package/dist/browser/CdpBrowserProvider.js +4 -2
- package/dist/browser/CdpCaptureEvents.js +49 -0
- package/dist/browser/CdpElectronInspection.js +106 -162
- package/dist/browser/CdpElectronProvider.js +9 -3
- package/dist/browser/CdpElectronScriptEvents.js +69 -0
- package/dist/browser/CdpElectronScripts.js +94 -0
- package/dist/browser/CdpElectronWorkers.js +56 -0
- package/dist/browser/CdpEndpoint.js +14 -1
- package/dist/browser/CdpPageCapture.js +8 -4
- package/dist/catalogIdentity.js +6 -42
- package/dist/cli.js +446 -34
- package/dist/cliApplicationCommands.js +62 -0
- package/dist/cliBrowserAdvancedCommands.js +5 -4
- package/dist/cliBrowserCommands.js +5 -4
- package/dist/cliCommandNames.js +56 -0
- package/dist/cliElectronCommands.js +106 -3
- package/dist/cliEvidenceCommands.js +4 -3
- package/dist/cliInvestigationCommands.js +2 -1
- package/dist/cliJsonInput.js +54 -0
- package/dist/cliPolicyCommands.js +2 -1
- package/dist/cliProcessCommands.js +3 -2
- package/dist/config.js +101 -2
- package/dist/contracts/applicationToolContracts.js +91 -0
- package/dist/contracts/artifactToolContracts.js +5 -9
- package/dist/contracts/browserToolContracts.js +14 -62
- package/dist/contracts/electronToolContracts.js +45 -19
- package/dist/contracts/enhancedInputs.js +2 -2
- package/dist/contracts/errorSchemas.js +1 -0
- package/dist/contracts/investigationExamples.js +0 -6
- package/dist/contracts/javascriptApplicationWorkflowExamples.js +46 -0
- package/dist/contracts/javascriptRuntimeReconciliationExample.js +208 -0
- package/dist/contracts/managedToolContracts.js +153 -0
- package/dist/contracts/managedWorkflowExamples.js +346 -0
- package/dist/contracts/managedWorkflowToolContracts.js +203 -0
- package/dist/contracts/nativeToolContracts.js +2 -6
- package/dist/contracts/promptContracts.js +18 -2
- package/dist/contracts/providerSelection.js +28 -0
- package/dist/contracts/sessionLifecycleInputs.js +2 -0
- package/dist/contracts/toolContractExamples.js +10 -25
- package/dist/contracts/toolContracts.js +69 -65
- package/dist/contracts/toolEffects.js +160 -0
- package/dist/contracts/toolOutputSchemas.js +152 -42
- package/dist/doctorRuntime.js +47 -0
- package/dist/domain/analysisProfile.js +78 -0
- package/dist/domain/analysisSnapshot.js +92 -46
- package/dist/domain/artifactComparison.js +3 -4
- package/dist/domain/artifactGraph.js +1 -0
- package/dist/domain/binaryTarget.js +4 -29
- package/dist/domain/browserObservation.js +3 -0
- package/dist/domain/bundleComparison.js +4 -4
- package/dist/domain/electronObservation.js +13 -0
- package/dist/domain/electronStaticAnalysis.js +9 -0
- package/dist/domain/electronStaticAnalysisBrowser.js +194 -0
- package/dist/domain/electronStaticAnalysisIpc.js +171 -0
- package/dist/domain/electronStaticAnalysisNative.js +164 -0
- package/dist/domain/electronStaticAnalysisTypes.js +1 -0
- package/dist/domain/electronStaticAnalysisValues.js +103 -0
- package/dist/domain/errors.js +148 -7
- package/dist/domain/evidence.js +44 -5
- package/dist/domain/evidenceBundle.js +9 -7
- package/dist/domain/functionComparison.js +9 -3
- package/dist/domain/functionComparisonNormalization.js +37 -0
- package/dist/domain/functionComparisonSchemas.js +3 -8
- package/dist/domain/functionDossierEvidence.js +4 -1
- package/dist/domain/hopperValues.js +66 -9
- package/dist/domain/inputIssueProjection.js +52 -0
- package/dist/domain/investigationWorkspace.js +2 -1
- package/dist/domain/javascriptApplicationAnalysis.js +155 -0
- package/dist/domain/javascriptApplicationChangeGraph.js +231 -0
- package/dist/domain/javascriptApplicationEvidenceSchemas.js +379 -0
- package/dist/domain/javascriptApplicationGraph.js +282 -0
- package/dist/domain/javascriptApplicationGraphSchemas.js +139 -0
- package/dist/domain/javascriptApplicationVersionComparison.js +116 -0
- package/dist/domain/javascriptApplicationVersionComparisonSchemas.js +139 -0
- package/dist/domain/javascriptApplicationVersionItems.js +221 -0
- package/dist/domain/javascriptApplicationVersionKeys.js +170 -0
- package/dist/domain/javascriptAstFingerprint.js +143 -0
- package/dist/domain/javascriptFeatureSeed.js +140 -0
- package/dist/domain/javascriptFeatureTrace.js +232 -0
- package/dist/domain/javascriptFeatureTraceSchemas.js +136 -0
- package/dist/domain/javascriptFeatureTraversal.js +88 -0
- package/dist/domain/javascriptNativeHandoff.js +85 -0
- package/dist/domain/javascriptReplay.js +361 -0
- package/dist/domain/javascriptRuntimeLoadState.js +106 -0
- package/dist/domain/javascriptRuntimeReconciliation.js +42 -0
- package/dist/domain/javascriptRuntimeReconciliationGraph.js +169 -0
- package/dist/domain/javascriptRuntimeReconciliationMatching.js +247 -0
- package/dist/domain/javascriptRuntimeReconciliationParsing.js +160 -0
- package/dist/domain/javascriptRuntimeReconciliationResult.js +119 -0
- package/dist/domain/javascriptRuntimeReconciliationRuntime.js +316 -0
- package/dist/domain/javascriptRuntimeReconciliationSchemas.js +245 -0
- package/dist/domain/javascriptRuntimeStaticCandidates.js +191 -0
- package/dist/domain/javascriptStaticAnalysis.js +346 -0
- package/dist/domain/javascriptStaticAnalysisFindings.js +39 -0
- package/dist/domain/javascriptStaticAnalysisHelpers.js +274 -0
- package/dist/domain/javascriptStaticAnalysisState.js +23 -0
- package/dist/domain/javascriptStaticAnalysisTypes.js +1 -0
- package/dist/domain/managedApplicationGraph.js +556 -0
- package/dist/domain/managedArtifact.js +444 -0
- package/dist/domain/managedMemberComparison.js +565 -0
- package/dist/domain/managedNativeVerification.js +408 -0
- package/dist/domain/managedReconstruction.js +183 -0
- package/dist/domain/managedRuntimeCorrelation.js +175 -0
- package/dist/domain/reconstructionVerificationSchemas.js +1 -3
- package/dist/dotnet/ManagedArtifactInspector.js +318 -0
- package/dist/dotnet/ManagedMemberInspector.js +887 -0
- package/dist/dotnet/ManagedMetadataHeaps.js +131 -0
- package/dist/dotnet/ManagedMetadataInventory.js +368 -0
- package/dist/dotnet/ManagedMetadataLayout.js +322 -0
- package/dist/dotnet/ManagedNativeBoundaryInspector.js +391 -0
- package/dist/dotnet/ManagedPeReader.js +157 -0
- package/dist/dotnet/ManagedReaderFailure.js +10 -0
- package/dist/dotnet/ManagedStaticProvider.js +203 -0
- package/dist/generatedPackageMetadata.js +2 -2
- package/dist/ghidra/GhidraAnalysisProfile.js +37 -0
- package/dist/ghidra/GhidraClient.js +400 -0
- package/dist/ghidra/GhidraClientTypes.js +1 -0
- package/dist/ghidra/GhidraDefaults.js +20 -0
- package/dist/ghidra/GhidraDiagnostics.js +43 -0
- package/dist/ghidra/GhidraDoctor.js +59 -0
- package/dist/ghidra/GhidraFunctionValues.js +264 -0
- package/dist/ghidra/GhidraInstallation.js +239 -0
- package/dist/ghidra/GhidraInventoryValues.js +217 -0
- package/dist/ghidra/GhidraLauncher.js +139 -0
- package/dist/ghidra/GhidraProvider.js +366 -0
- package/dist/ghidra/GhidraRequestQueue.js +98 -0
- package/dist/ghidra/GhidraResponseBuffer.js +31 -0
- package/dist/ghidra/GhidraResponseRouter.js +24 -0
- package/dist/ghidra/GhidraSessionError.js +39 -0
- package/dist/ghidra/GhidraSessionValues.js +62 -0
- package/dist/ghidra/GhidraSocketConnection.js +46 -0
- package/dist/ghidra/protocol.js +69 -0
- package/dist/hopper/BridgeLauncher.js +19 -54
- package/dist/hopper/HopperAnalysisProfile.js +106 -0
- package/dist/hopper/HopperClient.js +154 -162
- package/dist/hopper/HopperProvider.js +99 -7
- package/dist/hopper/HopperSessionValues.js +27 -0
- package/dist/hopper/HopperSocketConnection.js +31 -0
- package/dist/main.js +14 -0
- package/dist/native/NativeMacOSProvider.js +3 -1
- package/dist/process/PendingOperations.js +59 -0
- package/dist/process/PrivateRuntimeRoot.js +33 -0
- package/dist/process/ProviderDeadline.js +95 -0
- package/dist/process/ProviderProcess.js +275 -0
- package/dist/replay/JavaScriptReplayWorker.js +286 -0
- package/dist/replay/LinuxJavaScriptReplayRunner.js +434 -0
- package/dist/replay/LinuxRuntimeClosure.js +46 -0
- package/dist/replay/LinuxSeccompPolicy.js +40 -0
- package/dist/replay/ReplayWorkerProtocol.js +55 -0
- package/dist/replay/SystemJavaScriptReplayHost.js +182 -0
- package/dist/server/createServer.js +53 -0
- package/dist/server/promptCompletion.js +9 -3
- package/dist/server/registerApplicationTools.js +115 -0
- package/dist/server/registerArtifactComparisonTool.js +16 -9
- package/dist/server/registerBrowserTools.js +33 -8
- package/dist/server/registerBundleComparisonTool.js +17 -20
- package/dist/server/registerElectronTools.js +45 -3
- package/dist/server/registerEnhancedTools.js +67 -19
- package/dist/server/registerEvidenceTools.js +5 -1
- package/dist/server/registerFunctionComparisonTool.js +14 -7
- package/dist/server/registerInvestigationTools.js +21 -17
- package/dist/server/registerManagedTools.js +6 -0
- package/dist/server/registerManagedWorkflowTools.js +277 -0
- package/dist/server/registerOfficialTools.js +11 -8
- package/dist/server/registerProcessComparisonTool.js +25 -47
- package/dist/server/registerSessionStatusTool.js +7 -7
- package/dist/server/registerSessionTools.js +57 -87
- package/dist/server/sessionEvidence.js +14 -19
- package/dist/server/toolInputValidation.js +77 -0
- package/dist/server/toolRegistrationOptions.js +79 -2
- package/dist/server/toolResult.js +25 -17
- package/package.json +17 -7
- package/scripts/rea.mjs +36 -2
- package/skills/rea-analysis/SKILL.md +59 -3
- /package/dist/{application → process}/ProcessOwnership.js +0 -0
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { Cli, z } from "incur";
|
|
2
|
+
import { compareApplicationVersionsEvidence, traceApplicationFeatureEvidence, } from "./application/JavaScriptApplicationWorkflowService.js";
|
|
3
|
+
import { runControlledReplay } from "./application/JavaScriptReplayService.js";
|
|
4
|
+
import { loadConfiguredPermissionAuthority } from "./application/PermissionConfiguration.js";
|
|
5
|
+
import { CLI_COMMANDS } from "./cliCommandNames.js";
|
|
6
|
+
import { parseCliJsonInput } from "./cliJsonInput.js";
|
|
7
|
+
import { logCliCommand } from "./cliLogging.js";
|
|
8
|
+
import { AnalysisInputError, projectAnalysisError } from "./domain/errors.js";
|
|
9
|
+
import { parseConfig } from "./config.js";
|
|
10
|
+
import { LinuxJavaScriptReplayRunner } from "./replay/LinuxJavaScriptReplayRunner.js";
|
|
11
|
+
import { SystemJavaScriptReplayHost } from "./replay/SystemJavaScriptReplayHost.js";
|
|
12
|
+
/** Register CLI equivalents of provider-neutral application graph workflows. */
|
|
13
|
+
export const registerApplicationCommands = (cli, logger) => {
|
|
14
|
+
registerJsonCommand(cli, logger, CLI_COMMANDS.traceApplicationFeature, "Trace a typed seed through authenticated application Evidence JSON", traceApplicationFeatureEvidence);
|
|
15
|
+
registerJsonCommand(cli, logger, CLI_COMMANDS.compareApplicationVersions, "Compare two authenticated JavaScript Application Graph versions", compareApplicationVersionsEvidence);
|
|
16
|
+
cli.command(CLI_COMMANDS.runControlledReplay, {
|
|
17
|
+
description: "Plan or execute an approved extracted-module replay in the Linux sandbox",
|
|
18
|
+
args: z.object({
|
|
19
|
+
inputJson: z.string().describe("Inline replay JSON or JSON file path"),
|
|
20
|
+
}),
|
|
21
|
+
run: ({ args }) => logCliCommand(logger, CLI_COMMANDS.runControlledReplay, async () => {
|
|
22
|
+
const input = await parseCliJsonInput(args.inputJson, CLI_COMMANDS.runControlledReplay);
|
|
23
|
+
if (!input.ok)
|
|
24
|
+
return input.error;
|
|
25
|
+
const config = parseConfig(process.env);
|
|
26
|
+
if (!config.ok)
|
|
27
|
+
return projectAnalysisError(config.error);
|
|
28
|
+
const authority = await loadConfiguredPermissionAuthority(config.value);
|
|
29
|
+
if (!authority.ok)
|
|
30
|
+
return projectAnalysisError(authority.error);
|
|
31
|
+
const result = await runControlledReplay({
|
|
32
|
+
policy: config.value.javascriptReplayPolicy,
|
|
33
|
+
host: new SystemJavaScriptReplayHost(),
|
|
34
|
+
runner: new LinuxJavaScriptReplayRunner(),
|
|
35
|
+
authority: authority.value,
|
|
36
|
+
}, input.value);
|
|
37
|
+
return result.ok ? result.value : projectAnalysisError(result.error);
|
|
38
|
+
}),
|
|
39
|
+
});
|
|
40
|
+
};
|
|
41
|
+
const registerJsonCommand = (cli, logger, name, description, workflow) => {
|
|
42
|
+
cli.command(name, {
|
|
43
|
+
description,
|
|
44
|
+
args: z.object({
|
|
45
|
+
inputJson: z.string().describe("Inline workflow JSON or JSON file path"),
|
|
46
|
+
}),
|
|
47
|
+
run: ({ args }) => logCliCommand(logger, name, async () => {
|
|
48
|
+
const input = await parseCliJsonInput(args.inputJson, name);
|
|
49
|
+
if (!input.ok)
|
|
50
|
+
return input.error;
|
|
51
|
+
const result = workflow(input.value);
|
|
52
|
+
return result.ok
|
|
53
|
+
? result.value
|
|
54
|
+
: {
|
|
55
|
+
error: "Application workflow failed",
|
|
56
|
+
...projectAnalysisError(result.error instanceof AnalysisInputError
|
|
57
|
+
? result.error
|
|
58
|
+
: new AnalysisInputError(name)),
|
|
59
|
+
};
|
|
60
|
+
}),
|
|
61
|
+
});
|
|
62
|
+
};
|
|
@@ -8,6 +8,7 @@ import { AnalysisInputError, projectAnalysisError } from "./domain/errors.js";
|
|
|
8
8
|
import { compareWebCapturesInputSchema } from "./domain/webCaptureDiff.js";
|
|
9
9
|
import { discoverWebMcpToolsInputSchema } from "./domain/webMcpDiscovery.js";
|
|
10
10
|
import { captureWebScreenshotInputSchema, compareWebScreenshotsInputSchema, } from "./domain/webScreenshot.js";
|
|
11
|
+
import { CLI_COMMANDS } from "./cliCommandNames.js";
|
|
11
12
|
const scopeOptions = {
|
|
12
13
|
allowedOrigins: z.array(z.string().min(1)).optional(),
|
|
13
14
|
approved: z.boolean().default(false),
|
|
@@ -20,7 +21,7 @@ export const registerAdvancedBrowserCommands = (cli, logger) => {
|
|
|
20
21
|
registerScreenshotDiff(cli, logger);
|
|
21
22
|
};
|
|
22
23
|
const registerWebMcp = (cli, logger) => {
|
|
23
|
-
cli.command(
|
|
24
|
+
cli.command(CLI_COMMANDS.discoverWebMcpTools, {
|
|
24
25
|
description: "Passively discover page-declared WebMCP tools",
|
|
25
26
|
args: z.object({ endpoint: z.string(), targetId: z.string() }),
|
|
26
27
|
options: z.object({
|
|
@@ -59,7 +60,7 @@ const registerWebMcp = (cli, logger) => {
|
|
|
59
60
|
});
|
|
60
61
|
};
|
|
61
62
|
const registerCaptureDiff = (cli, logger) => {
|
|
62
|
-
cli.command(
|
|
63
|
+
cli.command(CLI_COMMANDS.compareWebCaptures, {
|
|
63
64
|
description: "Compare two normalized web capture JSON values",
|
|
64
65
|
args: z.object({ beforeJson: z.string(), afterJson: z.string() }),
|
|
65
66
|
options: z.object({
|
|
@@ -81,7 +82,7 @@ const registerCaptureDiff = (cli, logger) => {
|
|
|
81
82
|
});
|
|
82
83
|
};
|
|
83
84
|
const registerScreenshot = (cli, logger) => {
|
|
84
|
-
cli.command(
|
|
85
|
+
cli.command(CLI_COMMANDS.captureWebScreenshot, {
|
|
85
86
|
description: "Capture an explicitly approved visible page viewport",
|
|
86
87
|
args: z.object({ endpoint: z.string(), targetId: z.string() }),
|
|
87
88
|
options: z.object({
|
|
@@ -114,7 +115,7 @@ const registerScreenshot = (cli, logger) => {
|
|
|
114
115
|
});
|
|
115
116
|
};
|
|
116
117
|
const registerScreenshotDiff = (cli, logger) => {
|
|
117
|
-
cli.command(
|
|
118
|
+
cli.command(CLI_COMMANDS.compareWebScreenshots, {
|
|
118
119
|
description: "Compare two self-verifying PNG artifact JSON values",
|
|
119
120
|
args: z.object({ beforeJson: z.string(), afterJson: z.string() }),
|
|
120
121
|
options: z.object({
|
|
@@ -8,6 +8,7 @@ import { inspectWebPageInputSchema, listBrowserTargetsInputSchema, } from "./dom
|
|
|
8
8
|
import { analyzeWebBundleInputSchema } from "./domain/webBundleAnalysis.js";
|
|
9
9
|
import { observeWebSessionInputSchema } from "./domain/browserSession.js";
|
|
10
10
|
import { AnalysisInputError, projectAnalysisError } from "./domain/errors.js";
|
|
11
|
+
import { CLI_COMMANDS } from "./cliCommandNames.js";
|
|
11
12
|
const browserScopeOptions = {
|
|
12
13
|
allowedOrigins: z
|
|
13
14
|
.array(z.string().min(1))
|
|
@@ -23,7 +24,7 @@ export const registerBrowserCommands = (cli, logger) => {
|
|
|
23
24
|
registerObservationSession(cli, logger);
|
|
24
25
|
};
|
|
25
26
|
const registerTargetList = (cli, logger) => {
|
|
26
|
-
cli.command(
|
|
27
|
+
cli.command(CLI_COMMANDS.listBrowserTargets, {
|
|
27
28
|
description: "List approved pages from a user-owned loopback CDP browser",
|
|
28
29
|
args: z.object({
|
|
29
30
|
endpoint: z.string().describe("Configured loopback CDP HTTP endpoint"),
|
|
@@ -52,7 +53,7 @@ const registerTargetList = (cli, logger) => {
|
|
|
52
53
|
});
|
|
53
54
|
};
|
|
54
55
|
const registerPageInspection = (cli, logger) => {
|
|
55
|
-
cli.command(
|
|
56
|
+
cli.command(CLI_COMMANDS.inspectWebPage, {
|
|
56
57
|
description: "Passively inspect one approved page through CDP",
|
|
57
58
|
args: z.object({
|
|
58
59
|
endpoint: z.string().describe("Configured loopback CDP HTTP endpoint"),
|
|
@@ -195,7 +196,7 @@ const registerPageInspection = (cli, logger) => {
|
|
|
195
196
|
});
|
|
196
197
|
};
|
|
197
198
|
const registerBundleAnalysis = (cli, logger) => {
|
|
198
|
-
cli.command(
|
|
199
|
+
cli.command(CLI_COMMANDS.analyzeWebBundle, {
|
|
199
200
|
description: "Capture and statically analyze an approved page bundle",
|
|
200
201
|
args: z.object({
|
|
201
202
|
endpoint: z.string().describe("Configured loopback CDP HTTP endpoint"),
|
|
@@ -262,7 +263,7 @@ const registerBundleAnalysis = (cli, logger) => {
|
|
|
262
263
|
});
|
|
263
264
|
};
|
|
264
265
|
const registerObservationSession = (cli, logger) => {
|
|
265
|
-
cli.command(
|
|
266
|
+
cli.command(CLI_COMMANDS.observeWebSession, {
|
|
266
267
|
description: "Observe user-driven page navigation during a bounded window",
|
|
267
268
|
args: z.object({
|
|
268
269
|
endpoint: z.string().describe("Configured loopback CDP HTTP endpoint"),
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/** Canonical names used by every one-shot CLI command registration. */
|
|
2
|
+
export const CLI_COMMANDS = Object.freeze({
|
|
3
|
+
analyze: "analyze",
|
|
4
|
+
inspect: "inspect",
|
|
5
|
+
decompile: "decompile",
|
|
6
|
+
setup: "setup",
|
|
7
|
+
doctor: "doctor",
|
|
8
|
+
uninstall: "uninstall",
|
|
9
|
+
upgrade: "upgrade",
|
|
10
|
+
xrefs: "xrefs",
|
|
11
|
+
trace: "trace",
|
|
12
|
+
capabilities: "capabilities",
|
|
13
|
+
providers: "providers",
|
|
14
|
+
function: "function",
|
|
15
|
+
search: "search",
|
|
16
|
+
importReferenceSource: "import-reference-source",
|
|
17
|
+
inventoryArtifact: "inventory-artifact",
|
|
18
|
+
extractArtifact: "extract-artifact",
|
|
19
|
+
inspectManagedArtifact: "inspect-managed-artifact",
|
|
20
|
+
inspectManagedMembers: "inspect-managed-members",
|
|
21
|
+
inspectManagedNativeBoundaries: "inspect-managed-native-boundaries",
|
|
22
|
+
compareManagedMembers: "compare-managed-members",
|
|
23
|
+
verifyManagedNativeBoundaries: "verify-managed-native-boundaries",
|
|
24
|
+
importManagedReconstruction: "import-managed-reconstruction",
|
|
25
|
+
planManagedRuntimeCorrelation: "plan-managed-runtime-correlation",
|
|
26
|
+
projectManagedApplicationGraph: "project-managed-application-graph",
|
|
27
|
+
inspectMacho: "inspect-macho",
|
|
28
|
+
inspectSignature: "inspect-signature",
|
|
29
|
+
listArchitectures: "list-architectures",
|
|
30
|
+
inspectPlist: "inspect-plist",
|
|
31
|
+
demangleSwift: "demangle-swift",
|
|
32
|
+
evidenceImport: "evidence-import",
|
|
33
|
+
evidenceExport: "evidence-export",
|
|
34
|
+
compare: "compare",
|
|
35
|
+
investigateVersions: "investigate-versions",
|
|
36
|
+
captureProcess: "capture-process",
|
|
37
|
+
compareProcessCaptures: "compare-process-captures",
|
|
38
|
+
policy: "policy",
|
|
39
|
+
listBrowserTargets: "list-browser-targets",
|
|
40
|
+
inspectWebPage: "inspect-web-page",
|
|
41
|
+
analyzeWebBundle: "analyze-web-bundle",
|
|
42
|
+
observeWebSession: "observe-web-session",
|
|
43
|
+
discoverWebMcpTools: "discover-webmcp-tools",
|
|
44
|
+
compareWebCaptures: "compare-web-captures",
|
|
45
|
+
captureWebScreenshot: "capture-web-screenshot",
|
|
46
|
+
compareWebScreenshots: "compare-web-screenshots",
|
|
47
|
+
listElectronTargets: "list-electron-targets",
|
|
48
|
+
inspectElectronPage: "inspect-electron-page",
|
|
49
|
+
analyzeJavaScriptApplication: "analyze-javascript-application",
|
|
50
|
+
reconcileJavaScriptRuntime: "reconcile-javascript-runtime",
|
|
51
|
+
traceApplicationFeature: "trace-application-feature",
|
|
52
|
+
compareApplicationVersions: "compare-application-versions",
|
|
53
|
+
runControlledReplay: "run-controlled-replay",
|
|
54
|
+
});
|
|
55
|
+
/** Ordered primary CLI inventory; aliases are intentionally excluded. */
|
|
56
|
+
export const CLI_COMMAND_NAMES = Object.freeze(Object.values(CLI_COMMANDS));
|
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
import { Cli, z } from "incur";
|
|
2
2
|
import { inspectElectronPage, listElectronTargets, } from "./application/ElectronObservationService.js";
|
|
3
|
+
import { analyzeJavaScriptApplication } from "./application/JavaScriptApplicationService.js";
|
|
4
|
+
import { reconcileJavaScriptRuntimeEvidence } from "./application/JavaScriptRuntimeReconciliationService.js";
|
|
3
5
|
import { loadConfiguredPermissionAuthority } from "./application/PermissionConfiguration.js";
|
|
4
6
|
import { CdpElectronProvider } from "./browser/CdpElectronProvider.js";
|
|
5
7
|
import { logCliCommand } from "./cliLogging.js";
|
|
6
8
|
import { parseConfig } from "./config.js";
|
|
7
9
|
import { inspectElectronPageInputSchema, listElectronTargetsInputSchema, } from "./domain/electronObservation.js";
|
|
10
|
+
import { analyzeJavaScriptApplicationInputSchema } from "./domain/javascriptApplicationAnalysis.js";
|
|
8
11
|
import { AnalysisInputError, projectAnalysisError } from "./domain/errors.js";
|
|
12
|
+
import { CLI_COMMANDS } from "./cliCommandNames.js";
|
|
13
|
+
import { parseCliJsonInput } from "./cliJsonInput.js";
|
|
9
14
|
const scopeOptions = {
|
|
10
15
|
allowedFileRoots: z
|
|
11
16
|
.array(z.string().min(1))
|
|
@@ -15,7 +20,29 @@ const scopeOptions = {
|
|
|
15
20
|
};
|
|
16
21
|
/** Register CLI equivalents of the Electron MCP tools. */
|
|
17
22
|
export const registerElectronCommands = (cli, logger) => {
|
|
18
|
-
cli
|
|
23
|
+
registerElectronObservationCommands(cli, logger);
|
|
24
|
+
registerJavaScriptApplicationCommand(cli, logger);
|
|
25
|
+
registerJavaScriptRuntimeReconciliationCommand(cli, logger);
|
|
26
|
+
};
|
|
27
|
+
const registerJavaScriptRuntimeReconciliationCommand = (cli, logger) => {
|
|
28
|
+
cli.command(CLI_COMMANDS.reconcileJavaScriptRuntime, {
|
|
29
|
+
description: "Reconcile static application and passive runtime Evidence JSON",
|
|
30
|
+
args: z.object({
|
|
31
|
+
inputJson: z
|
|
32
|
+
.string()
|
|
33
|
+
.describe("Inline JSON or a JSON file path matching reconcile_javascript_runtime"),
|
|
34
|
+
}),
|
|
35
|
+
run: ({ args }) => logCliCommand(logger, CLI_COMMANDS.reconcileJavaScriptRuntime, async () => {
|
|
36
|
+
const input = await parseCliJsonInput(args.inputJson, "reconcile_javascript_runtime");
|
|
37
|
+
if (!input.ok)
|
|
38
|
+
return input.error;
|
|
39
|
+
const result = reconcileJavaScriptRuntimeEvidence(input.value);
|
|
40
|
+
return result.ok ? result.value : cliError(result.error);
|
|
41
|
+
}),
|
|
42
|
+
});
|
|
43
|
+
};
|
|
44
|
+
const registerElectronObservationCommands = (cli, logger) => {
|
|
45
|
+
cli.command(CLI_COMMANDS.listElectronTargets, {
|
|
19
46
|
description: "List root-confined file pages from Electron CDP",
|
|
20
47
|
args: z.object({ endpoint: z.string() }),
|
|
21
48
|
options: z.object({
|
|
@@ -40,7 +67,7 @@ export const registerElectronCommands = (cli, logger) => {
|
|
|
40
67
|
return result.ok ? result.value : cliError(result.error);
|
|
41
68
|
}),
|
|
42
69
|
});
|
|
43
|
-
cli.command(
|
|
70
|
+
cli.command(CLI_COMMANDS.inspectElectronPage, {
|
|
44
71
|
description: "Passively inspect one root-confined Electron file page",
|
|
45
72
|
args: z.object({ endpoint: z.string(), targetId: z.string() }),
|
|
46
73
|
options: z.object({
|
|
@@ -52,6 +79,7 @@ export const registerElectronCommands = (cli, logger) => {
|
|
|
52
79
|
maxDomNodes: z.number().int().min(1).max(10_000).default(2_000),
|
|
53
80
|
maxScripts: z.number().int().min(1).max(2_000).default(500),
|
|
54
81
|
maxResources: z.number().int().min(1).max(10_000).default(2_000),
|
|
82
|
+
maxWorkers: z.number().int().min(1).max(5_000).default(500),
|
|
55
83
|
maxScriptSourceBytes: z
|
|
56
84
|
.number()
|
|
57
85
|
.int()
|
|
@@ -82,6 +110,7 @@ export const registerElectronCommands = (cli, logger) => {
|
|
|
82
110
|
max_dom_nodes: options.maxDomNodes,
|
|
83
111
|
max_scripts: options.maxScripts,
|
|
84
112
|
max_resources: options.maxResources,
|
|
113
|
+
max_workers: options.maxWorkers,
|
|
85
114
|
max_script_source_bytes: options.maxScriptSourceBytes,
|
|
86
115
|
max_total_script_source_bytes: options.maxTotalScriptSourceBytes,
|
|
87
116
|
},
|
|
@@ -93,6 +122,80 @@ export const registerElectronCommands = (cli, logger) => {
|
|
|
93
122
|
}),
|
|
94
123
|
});
|
|
95
124
|
};
|
|
125
|
+
const registerJavaScriptApplicationCommand = (cli, logger) => {
|
|
126
|
+
cli.command(CLI_COMMANDS.analyzeJavaScriptApplication, {
|
|
127
|
+
description: "Statically reconstruct an approved JavaScript/Electron application",
|
|
128
|
+
args: z.object({
|
|
129
|
+
path: z.string().describe("Absolute ASAR or extracted application path"),
|
|
130
|
+
}),
|
|
131
|
+
options: z.object({
|
|
132
|
+
approved: z.boolean().default(false),
|
|
133
|
+
format: z.enum(["auto", "asar", "directory"]).default("auto"),
|
|
134
|
+
sourceMapReadApproved: z.boolean().default(false),
|
|
135
|
+
maxEntries: z.number().int().min(1).default(8_000),
|
|
136
|
+
maxTotalArtifactBytes: z
|
|
137
|
+
.number()
|
|
138
|
+
.int()
|
|
139
|
+
.min(1)
|
|
140
|
+
.default(512 * 1_024 * 1_024),
|
|
141
|
+
maxArtifactEntryBytes: z
|
|
142
|
+
.number()
|
|
143
|
+
.int()
|
|
144
|
+
.min(1)
|
|
145
|
+
.default(128 * 1_024 * 1_024),
|
|
146
|
+
maxCompressionRatio: z.number().min(1).default(1_000),
|
|
147
|
+
maxDepth: z.number().int().min(1).default(64),
|
|
148
|
+
maxPathBytes: z.number().int().min(1).default(4_096),
|
|
149
|
+
maxTextFiles: z.number().int().min(1).default(5_000),
|
|
150
|
+
maxTotalTextBytes: z
|
|
151
|
+
.number()
|
|
152
|
+
.int()
|
|
153
|
+
.min(1)
|
|
154
|
+
.default(128 * 1_024 * 1_024),
|
|
155
|
+
maxTextFileBytes: z
|
|
156
|
+
.number()
|
|
157
|
+
.int()
|
|
158
|
+
.min(1)
|
|
159
|
+
.default(8 * 1_024 * 1_024),
|
|
160
|
+
maxAstNodes: z.number().int().min(1).default(2_000_000),
|
|
161
|
+
maxFindings: z.number().int().min(1).default(8_000),
|
|
162
|
+
maxModules: z.number().int().min(1).default(20_000),
|
|
163
|
+
maxSourceMapSources: z.number().int().min(1).default(5_000),
|
|
164
|
+
maxParseMilliseconds: z.number().int().min(1).default(30_000),
|
|
165
|
+
}),
|
|
166
|
+
run: ({ args, options }) => logCliCommand(logger, CLI_COMMANDS.analyzeJavaScriptApplication, async () => {
|
|
167
|
+
const context = await electronContext();
|
|
168
|
+
if (!context.ok)
|
|
169
|
+
return context.error;
|
|
170
|
+
const parsed = analyzeJavaScriptApplicationInputSchema.safeParse({
|
|
171
|
+
input_path: args.path,
|
|
172
|
+
approved: options.approved,
|
|
173
|
+
format: options.format,
|
|
174
|
+
source_map_read_approved: options.sourceMapReadApproved,
|
|
175
|
+
limits: {
|
|
176
|
+
max_entries: options.maxEntries,
|
|
177
|
+
max_total_artifact_bytes: options.maxTotalArtifactBytes,
|
|
178
|
+
max_artifact_entry_bytes: options.maxArtifactEntryBytes,
|
|
179
|
+
max_compression_ratio: options.maxCompressionRatio,
|
|
180
|
+
max_depth: options.maxDepth,
|
|
181
|
+
max_path_bytes: options.maxPathBytes,
|
|
182
|
+
max_text_files: options.maxTextFiles,
|
|
183
|
+
max_total_text_bytes: options.maxTotalTextBytes,
|
|
184
|
+
max_text_file_bytes: options.maxTextFileBytes,
|
|
185
|
+
max_ast_nodes: options.maxAstNodes,
|
|
186
|
+
max_findings: options.maxFindings,
|
|
187
|
+
max_modules: options.maxModules,
|
|
188
|
+
max_source_map_sources: options.maxSourceMapSources,
|
|
189
|
+
max_parse_milliseconds: options.maxParseMilliseconds,
|
|
190
|
+
},
|
|
191
|
+
});
|
|
192
|
+
if (!parsed.success)
|
|
193
|
+
return inputError("analyze_javascript_application");
|
|
194
|
+
const result = await analyzeJavaScriptApplication(context.authority, parsed.data);
|
|
195
|
+
return result.ok ? result.value : cliError(result.error);
|
|
196
|
+
}),
|
|
197
|
+
});
|
|
198
|
+
};
|
|
96
199
|
const electronContext = async () => {
|
|
97
200
|
const config = parseConfig(process.env);
|
|
98
201
|
if (!config.ok)
|
|
@@ -109,6 +212,6 @@ const electronContext = async () => {
|
|
|
109
212
|
};
|
|
110
213
|
const inputError = (operation) => cliError(new AnalysisInputError(operation));
|
|
111
214
|
const cliError = (error) => ({
|
|
112
|
-
error: "Electron
|
|
215
|
+
error: "Electron analysis failed",
|
|
113
216
|
...projectAnalysisError(error),
|
|
114
217
|
});
|
|
@@ -2,11 +2,12 @@ import { Cli, z } from "incur";
|
|
|
2
2
|
import { compareEvidenceBundlesCommand, exportEvidenceBundleCommand, importEvidenceBundleCommand, } from "./application/EvidenceBundleCommands.js";
|
|
3
3
|
import { parseConfig } from "./config.js";
|
|
4
4
|
import { logCliCommand } from "./cliLogging.js";
|
|
5
|
+
import { CLI_COMMANDS } from "./cliCommandNames.js";
|
|
5
6
|
import { AnalysisProtocolError, PermissionRequiredError, projectAnalysisError, } from "./domain/errors.js";
|
|
6
7
|
import { loadConfiguredPermissionAuthority } from "./application/PermissionConfiguration.js";
|
|
7
8
|
/** Register filesystem-gated Evidence v2 commands. */
|
|
8
9
|
export const registerEvidenceCommands = (cli, logger) => {
|
|
9
|
-
cli.command(
|
|
10
|
+
cli.command(CLI_COMMANDS.evidenceImport, {
|
|
10
11
|
description: "Validate and import a bounded local Evidence v2 bundle",
|
|
11
12
|
args: z.object({
|
|
12
13
|
path: z.string().describe("Evidence bundle JSON path"),
|
|
@@ -24,7 +25,7 @@ export const registerEvidenceCommands = (cli, logger) => {
|
|
|
24
25
|
return imported.ok ? imported.value : cliError(imported.error);
|
|
25
26
|
}),
|
|
26
27
|
});
|
|
27
|
-
cli.command(
|
|
28
|
+
cli.command(CLI_COMMANDS.evidenceExport, {
|
|
28
29
|
description: "Validate and atomically export canonical Evidence v2 JSON",
|
|
29
30
|
args: z.object({
|
|
30
31
|
source: z.string().describe("Existing evidence bundle JSON path"),
|
|
@@ -47,7 +48,7 @@ export const registerEvidenceCommands = (cli, logger) => {
|
|
|
47
48
|
return exported.ok ? exported.value : cliError(exported.error);
|
|
48
49
|
}),
|
|
49
50
|
});
|
|
50
|
-
cli.command(
|
|
51
|
+
cli.command(CLI_COMMANDS.compare, {
|
|
51
52
|
aliases: ["compare-bundles"],
|
|
52
53
|
description: "Compare two canonical Evidence v2 bundles",
|
|
53
54
|
args: z.object({
|
|
@@ -5,6 +5,7 @@ import { parseConfig } from "./config.js";
|
|
|
5
5
|
import { projectAnalysisError } from "./domain/errors.js";
|
|
6
6
|
import { loadConfiguredPermissionAuthority } from "./application/PermissionConfiguration.js";
|
|
7
7
|
import { authorizeFileReadWithDeferredWrite, authorizeRootPermission, } from "./application/DeferredFileAuthorization.js";
|
|
8
|
+
import { CLI_COMMANDS } from "./cliCommandNames.js";
|
|
8
9
|
const investigationOptionsSchema = z.object({
|
|
9
10
|
yes: z
|
|
10
11
|
.boolean()
|
|
@@ -38,7 +39,7 @@ const investigationOptionsSchema = z.object({
|
|
|
38
39
|
});
|
|
39
40
|
/** Register the persistent cross-version CLI workflow. */
|
|
40
41
|
export const registerInvestigationCommands = (cli, logger) => {
|
|
41
|
-
cli.command(
|
|
42
|
+
cli.command(CLI_COMMANDS.investigateVersions, {
|
|
42
43
|
description: "Run or resume a persistent cross-version artifact investigation",
|
|
43
44
|
args: z.object({
|
|
44
45
|
leftPath: z.string().describe("Earlier artifact or directory path"),
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { readFile, stat } from "node:fs/promises";
|
|
2
|
+
import { AnalysisInputError, projectAnalysisError } from "./domain/errors.js";
|
|
3
|
+
const MAX_JSON_INPUT_BYTES = 64 * 1_024 * 1_024;
|
|
4
|
+
/** Parse bounded inline JSON or one bounded local JSON file for a CLI workflow. */
|
|
5
|
+
export const parseCliJsonInput = async (value, operation) => {
|
|
6
|
+
const inline = parseJson(value);
|
|
7
|
+
if (inline !== undefined)
|
|
8
|
+
return { ok: true, value: inline };
|
|
9
|
+
if (["{", "["].includes(value.trimStart()[0] ?? ""))
|
|
10
|
+
return { ok: false, error: inputError(operation) };
|
|
11
|
+
try {
|
|
12
|
+
const metadata = await stat(value);
|
|
13
|
+
if (!metadata.isFile())
|
|
14
|
+
return jsonFileError(value, operation, "not-file");
|
|
15
|
+
if (metadata.size > MAX_JSON_INPUT_BYTES)
|
|
16
|
+
return jsonFileError(value, operation, "too-large");
|
|
17
|
+
const bytes = await readFile(value);
|
|
18
|
+
if (bytes.byteLength > MAX_JSON_INPUT_BYTES)
|
|
19
|
+
return jsonFileError(value, operation, "too-large");
|
|
20
|
+
const parsed = parseJson(bytes.toString("utf8"));
|
|
21
|
+
return parsed === undefined
|
|
22
|
+
? jsonFileError(value, operation, "invalid-json")
|
|
23
|
+
: { ok: true, value: parsed };
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
return jsonFileError(value, operation, "read-failed");
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
const parseJson = (value) => {
|
|
30
|
+
try {
|
|
31
|
+
return JSON.parse(value);
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return undefined;
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
const inputError = (operation) => ({
|
|
38
|
+
error: "Application workflow failed",
|
|
39
|
+
...projectAnalysisError(new AnalysisInputError(operation, undefined, [
|
|
40
|
+
{ path: [], reason: "invalid_format", expected: "JSON" },
|
|
41
|
+
])),
|
|
42
|
+
});
|
|
43
|
+
const jsonFileError = (path, operation, reason) => ({
|
|
44
|
+
ok: false,
|
|
45
|
+
error: {
|
|
46
|
+
error: "Application workflow failed",
|
|
47
|
+
...projectAnalysisError(new AnalysisInputError(operation, undefined, reason === "invalid-json"
|
|
48
|
+
? [{ path: [], reason: "invalid_format", expected: "JSON" }]
|
|
49
|
+
: [])),
|
|
50
|
+
input_path: path,
|
|
51
|
+
input_reason: reason,
|
|
52
|
+
maximum_input_bytes: MAX_JSON_INPUT_BYTES,
|
|
53
|
+
},
|
|
54
|
+
});
|
|
@@ -5,6 +5,7 @@ import { readProjectPermissionStore, revokeProjectPermissionGrant, } from "./app
|
|
|
5
5
|
import { logCliCommand } from "./cliLogging.js";
|
|
6
6
|
import { parseConfig } from "./config.js";
|
|
7
7
|
import { PermissionRequiredError, projectAnalysisError, } from "./domain/errors.js";
|
|
8
|
+
import { CLI_COMMANDS } from "./cliCommandNames.js";
|
|
8
9
|
const capabilitySchema = z.enum([
|
|
9
10
|
"process_capture",
|
|
10
11
|
"browser_observe",
|
|
@@ -32,7 +33,7 @@ export const approvePolicyRevocation = async (options) => {
|
|
|
32
33
|
};
|
|
33
34
|
/** Register inspectable, dry-run, and revocation policy UX for the CLI. */
|
|
34
35
|
export const registerPolicyCommands = (cli, logger) => {
|
|
35
|
-
cli.command(
|
|
36
|
+
cli.command(CLI_COMMANDS.policy, {
|
|
36
37
|
description: "Inspect, explain, or revoke unified local permission grants",
|
|
37
38
|
args: z.object({
|
|
38
39
|
action: z.enum(["status", "list", "explain", "revoke"]),
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import { Cli, z } from "incur";
|
|
2
2
|
import { captureProcessScenarioFile, compareProcessEvidenceFiles, } from "./application/ProcessCli.js";
|
|
3
3
|
import { logCliCommand } from "./cliLogging.js";
|
|
4
|
+
import { CLI_COMMANDS } from "./cliCommandNames.js";
|
|
4
5
|
/** Register Process Capture v4 one-shot commands through shared application services. */
|
|
5
6
|
export const registerProcessCommands = (cli, logger) => {
|
|
6
|
-
cli.command(
|
|
7
|
+
cli.command(CLI_COMMANDS.captureProcess, {
|
|
7
8
|
description: "Capture one approved Process Capture v4 JSON scenario",
|
|
8
9
|
args: z.object({ scenario: z.string().describe("Scenario JSON path") }),
|
|
9
10
|
run: ({ args }) => logCliCommand(logger, "capture-process", () => captureProcessScenarioFile(args.scenario)),
|
|
10
11
|
});
|
|
11
|
-
cli.command(
|
|
12
|
+
cli.command(CLI_COMMANDS.compareProcessCaptures, {
|
|
12
13
|
description: "Compare two Process Capture v4 Evidence JSON files",
|
|
13
14
|
args: z.object({
|
|
14
15
|
left: z.string().describe("Left capture Evidence JSON path"),
|