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.
- package/README.md +14 -16
- package/dist/application/AnalysisContextQueries.js +21 -9
- package/dist/application/ApplicationWorkflowEvidenceResolver.js +19 -11
- package/dist/application/ArtifactInventory/policy.js +17 -0
- package/dist/application/ArtifactInventory/reader.js +1 -4
- package/dist/application/ArtifactInventory/scanCanonical.js +0 -3
- package/dist/application/ArtifactInventory/scanReader.js +7 -7
- package/dist/application/ArtifactInventory/types.js +1 -5
- package/dist/application/BinarySession.js +14 -16
- package/dist/application/BinarySessionRecords.js +31 -5
- package/dist/application/BinarySessionStatus.js +11 -5
- package/dist/application/BrowserEvidence.js +3 -5
- package/dist/application/CapabilityClientRequirements.js +26 -0
- package/dist/application/CapabilityInventory.js +134 -63
- package/dist/application/CrossVersionInventory.js +7 -6
- package/dist/application/ElectronActiveEvidence.js +55 -0
- package/dist/application/ElectronActiveObservationPort.js +1 -0
- package/dist/application/ElectronActiveObservationService.js +81 -0
- package/dist/application/EnhancedTools.js +22 -20
- package/dist/application/EvidenceBundleCommands.js +5 -1
- package/dist/application/EvidenceLedger.js +8 -1
- package/dist/application/JavaScriptReplayPermission.js +1 -1
- package/dist/application/JavaScriptReplayService.js +23 -15
- package/dist/application/ManagedRuntimeCorrelationService.js +9 -5
- package/dist/application/NodeRuntimeCharacterizationService.js +8 -9
- package/dist/application/ProcessCaptureLifecycle.js +5 -0
- package/dist/application/ProcessCli.js +2 -1
- package/dist/application/ProcessHarness.js +8 -3
- package/dist/application/ProcessNormalization.js +2 -1
- package/dist/application/ProjectPermissionStore.js +1 -0
- package/dist/application/ReferenceSourceImport.js +2 -2
- package/dist/application/SetupClientConfiguration.js +6 -1
- package/dist/application/WindowsCapabilities.js +5 -4
- package/dist/artifacts/ArtifactProvider.js +8 -10
- package/dist/artifacts/SafeOutputTree.js +7 -8
- package/dist/browser/CdpCaptureStorageFingerprints.js +10 -7
- package/dist/browser/CdpElectronInspection.js +3 -1
- package/dist/browser/JavaScriptRuntimeScope.js +5 -0
- package/dist/browser/PlaywrightElectronActiveActions.js +324 -0
- package/dist/browser/PlaywrightElectronActiveProvider.js +294 -0
- package/dist/browser/PlaywrightScenarioBrowser.js +4 -4
- package/dist/browser/PlaywrightScenarioSession.js +4 -4
- package/dist/browser/SensitiveTextCapture.js +1 -1
- package/dist/browser/V8InspectorCaptureProjection.js +1 -0
- package/dist/browser/V8InspectorProvider.js +3 -3
- package/dist/catalogIdentity.js +12 -6
- package/dist/cli/managedCommands.js +1 -1
- package/dist/cliApplicationCommands.js +2 -2
- package/dist/cliBrowserAdvancedCommands.js +11 -5
- package/dist/cliBrowserCommands.js +14 -7
- package/dist/cliCommandNames.js +1 -0
- package/dist/cliElectronCommands.js +46 -4
- package/dist/cliJavaScriptRuntimeCommands.js +14 -6
- package/dist/cliObservationOptions.js +4 -0
- package/dist/cliPolicyCommands.js +1 -0
- package/dist/config/browserScenario.js +77 -0
- package/dist/config/electronAutomation.js +35 -0
- package/dist/config/environment.js +6 -0
- package/dist/config/javascriptReplay.js +41 -0
- package/dist/config/managedRuntime.js +25 -0
- package/dist/config/parseConfig.js +56 -200
- package/dist/config/parsers.js +10 -1
- package/dist/config/passiveObservation.js +157 -0
- package/dist/config/processCapture.js +47 -0
- package/dist/contracts/applicationToolContracts.js +2 -5
- package/dist/contracts/applicationWorkflowInputContracts.js +86 -96
- package/dist/contracts/artifactToolContracts.js +27 -34
- package/dist/contracts/browserToolContracts.js +2 -2
- package/dist/contracts/electronToolContracts.js +30 -1
- package/dist/contracts/enhancedInputs.js +13 -29
- package/dist/contracts/functionWorkflowToolContracts.js +2 -3
- package/dist/contracts/managedToolContracts.js +4 -9
- package/dist/contracts/managedWorkflowExamples.js +12 -9
- package/dist/contracts/managedWorkflowToolContracts.js +30 -27
- package/dist/contracts/nativeToolContracts.js +2 -3
- package/dist/contracts/sessionToolSchemas.js +61 -0
- package/dist/contracts/toolContractExamples.js +1 -0
- package/dist/contracts/toolContractHelpers.js +23 -0
- package/dist/contracts/toolContracts.js +5 -77
- package/dist/contracts/toolEffects.js +15 -0
- package/dist/contracts/toolOutputSchemaGroups.js +17 -2
- package/dist/contracts/toolOutputSchemaPrimitives.js +76 -26
- package/dist/contracts/toolSchemaMetadata.js +128 -0
- package/dist/doctorRuntime.js +1 -1
- package/dist/domain/androidApplication.js +2 -0
- package/dist/domain/appleApplication.js +2 -0
- package/dist/domain/binaryTarget.js +7 -5
- package/dist/domain/binaryTargetTypes.js +1 -0
- package/dist/domain/browserCaptureComparison.js +21 -69
- package/dist/domain/browserObservation.js +22 -9
- package/dist/domain/bytecodeProvider.js +33 -35
- package/dist/domain/callPath.js +3 -2
- package/dist/domain/conformanceReplay.js +3 -3
- package/dist/domain/conformanceTrustGate.js +151 -16
- package/dist/domain/customProtocolCapture.js +3 -3
- package/dist/domain/electronActiveObservation.js +277 -0
- package/dist/domain/electronObservation.js +15 -11
- package/dist/domain/electronStaticAnalysisValues.js +4 -1
- package/dist/domain/eventProcessTree.js +82 -79
- package/dist/domain/functionComparisonNormalization.js +15 -8
- package/dist/domain/functionDossierEvidence.js +9 -4
- package/dist/domain/hopperValues.js +68 -71
- package/dist/domain/inputIssueProjection.js +4 -1
- package/dist/domain/investigationWorkspace.js +16 -15
- package/dist/domain/javascriptExportShapeComparisonSchemas.js +2 -2
- package/dist/domain/javascriptReplay.js +79 -63
- package/dist/domain/javascriptRuntimeObservation.js +1 -0
- package/dist/domain/javascriptRuntimeReconciliationActive.js +89 -0
- package/dist/domain/javascriptRuntimeReconciliationGraph.js +11 -10
- package/dist/domain/javascriptRuntimeReconciliationMatching.js +57 -49
- package/dist/domain/javascriptRuntimeReconciliationParsing.js +5 -1
- package/dist/domain/javascriptRuntimeReconciliationResult.js +21 -14
- package/dist/domain/javascriptRuntimeReconciliationSchemas.js +1 -1
- package/dist/domain/knownPageCoverage.js +15 -7
- package/dist/domain/nativeApiBoundary.js +15 -7
- package/dist/domain/nodeRuntimeCharacterization.js +14 -13
- package/dist/domain/processCaptureReactiveValidation.js +8 -3
- package/dist/domain/processCaptureValidation.js +7 -3
- package/dist/domain/processComparison.js +12 -7
- package/dist/domain/processObservation.js +5 -6
- package/dist/domain/processReactiveMatching.js +14 -7
- package/dist/domain/processReactiveTransition.js +9 -3
- package/dist/domain/processScenario.js +6 -3
- package/dist/domain/processTraceComparison.js +3 -2
- package/dist/domain/protocolCapture.js +8 -6
- package/dist/domain/reconstructionReadinessSchemas.js +30 -2
- package/dist/domain/referenceSourceImportParsing.js +2 -2
- package/dist/domain/replayMachineRuntime.js +5 -3
- package/dist/domain/sourceToBundleComparison.js +2 -2
- package/dist/domain/sourceToBundleComparisonSchemas.js +8 -8
- package/dist/domain/sourceToBundleSignals.js +7 -1
- package/dist/domain/staticRuntimeCorrelation.js +7 -5
- package/dist/domain/webBundleAnalysis.js +14 -14
- package/dist/domain/webCaptureDiff.js +15 -12
- package/dist/dotnet/ManagedNativeBoundaryInspector.js +2 -3
- package/dist/generatedMcpToolCatalog.js +1 -1
- package/dist/generatedPackageMetadata.js +1 -1
- package/dist/ghidra/GhidraClient.js +1 -1
- package/dist/ghidra/GhidraClientStartup.js +1 -1
- package/dist/ghidra/GhidraFunctionValues.js +17 -15
- package/dist/ghidra/GhidraInventoryValues.js +57 -47
- package/dist/ghidra/GhidraProvider.js +18 -10
- package/dist/ghidra/GhidraProviderCapabilities.js +5 -1
- package/dist/ghidra/GhidraSocketConnection.js +1 -1
- package/dist/ghidra/protocol.js +19 -42
- package/dist/hopper/BridgeLauncher.js +3 -1
- package/dist/hopper/HopperAnalysisProfile.js +2 -4
- package/dist/hopper/HopperCleanup.js +5 -6
- package/dist/hopper/HopperClient.js +1 -1
- package/dist/hopper/HopperProvider.js +0 -14
- package/dist/hopper/LinuxPrivateDisplayProbe.js +16 -10
- package/dist/main/reload.js +1 -6
- package/dist/main/state.js +0 -14
- package/dist/main/transport.js +30 -37
- package/dist/main.js +17 -15
- package/dist/mcpDoctor.js +2 -24
- package/dist/process/PrivateRuntimeRoot.js +17 -0
- package/dist/process/ProcessOwnership.js +64 -128
- package/dist/process/ProcessOwnershipIdentity.js +13 -0
- package/dist/process/ProcessOwnershipObservation.js +88 -0
- package/dist/process/ProcessOwnershipProcessTree.js +22 -0
- package/dist/process/ProviderDeadline.js +8 -12
- package/dist/process/WindowsAuthority.js +32 -0
- package/dist/reference/ReferenceSourceReader.js +3 -3
- package/dist/reference/ReferenceSourceReaderEntries.js +2 -2
- package/dist/replay/JavaScriptReplayWorker.js +95 -11
- package/dist/replay/JavaScriptReplayWorkerTypes.js +1 -0
- package/dist/replay/LinuxJavaScriptReplayRunner.js +10 -15
- package/dist/replay/ReplayOutcome.js +26 -15
- package/dist/replay/ReplayWorkerProtocol.js +34 -29
- package/dist/server/createServer.js +158 -94
- package/dist/server/mcpClientMetadata.js +32 -0
- package/dist/server/registerApplicationTools/characterization.js +6 -13
- package/dist/server/registerApplicationTools/compareExportShapes.js +2 -7
- package/dist/server/registerApplicationTools/compareSourceToBundle.js +2 -7
- package/dist/server/registerApplicationTools/compareVersions.js +3 -8
- package/dist/server/registerApplicationTools/controlledReplay.js +6 -11
- package/dist/server/registerApplicationTools/coverage.js +13 -19
- package/dist/server/registerApplicationTools/obligationLedger.js +1 -6
- package/dist/server/registerApplicationTools/readiness.js +1 -6
- package/dist/server/registerApplicationTools/traceFeature.js +3 -8
- package/dist/server/registerApplicationTools/traceSemantics.js +1 -6
- package/dist/server/registerArtifactComparisonTool.js +12 -16
- package/dist/server/registerBrowserScenarioTool.js +1 -6
- package/dist/server/registerBrowserTools.js +37 -79
- package/dist/server/registerBundleComparisonTool.js +10 -14
- package/dist/server/registerCloseLifecycleTool.js +6 -14
- package/dist/server/registerElectronTools.js +30 -47
- package/dist/server/registerEnhancedTools.js +114 -122
- package/dist/server/registerEvidenceTools.js +5 -9
- package/dist/server/registerFunctionComparisonTool.js +11 -15
- package/dist/server/registerInvestigationTools.js +41 -57
- package/dist/server/registerJavaScriptRuntimeObservationTools.js +13 -27
- package/dist/server/registerManagedWorkflowTools/compareManagedMembers.js +4 -9
- package/dist/server/registerManagedWorkflowTools/contract.js +2 -3
- package/dist/server/registerManagedWorkflowTools/importManagedReconstruction.js +3 -8
- package/dist/server/registerManagedWorkflowTools/planManagedRuntimeCorrelation.js +3 -8
- package/dist/server/registerManagedWorkflowTools/projectManagedApplicationGraph.js +8 -13
- package/dist/server/registerManagedWorkflowTools/verifyManagedNativeBoundaries.js +4 -9
- package/dist/server/registerOfficialTools.js +8 -9
- package/dist/server/registerProcessComparisonTool.js +19 -24
- package/dist/server/registerReplayMachineTool.js +4 -10
- package/dist/server/registerSessionRecordTools.js +69 -40
- package/dist/server/registerSessionStatusTool.js +13 -28
- package/dist/server/registerSessionTools.js +36 -52
- package/dist/server/sessionAvailabilityPolicy.js +2 -1
- package/dist/server/sessionToolPolicies.js +1 -5
- package/dist/server/toolRegistrationOptions.js +4 -192
- package/dist/server/toolResult.js +2 -18
- package/package.json +22 -14
- package/scripts/electron-active-hook-boundaries.cjs +394 -0
- package/scripts/electron-active-hook.cjs +501 -0
- package/scripts/rea.mjs +1 -11
- package/skills/reverse-engineer-anything/SKILL.md +2 -2
- package/dist/server/DynamicToolAvailability.js +0 -70
- package/dist/server/LazyToolCatalog.js +0 -134
- package/dist/server/hydrateServerTools.js +0 -191
- package/dist/server/toolInputValidation.js +0 -77
- package/scripts/package-runner-bootstrap.mjs +0 -72
|
@@ -1,28 +1,13 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
+
import { providerCapability, } from "../contracts/toolOutputSchemaPrimitives.js";
|
|
2
3
|
import { GENERATED_MCP_TOOL_CATALOG } from "../generatedMcpToolCatalog.js";
|
|
4
|
+
import { clientRequirementsFor, NO_CLIENT_FEATURES, } from "./CapabilityClientRequirements.js";
|
|
3
5
|
const statusSchema = z.object({
|
|
4
6
|
open: z.boolean(),
|
|
5
7
|
kind: z.enum(["executable", "database", "archive", "artifact"]).optional(),
|
|
6
8
|
format: z.string().optional(),
|
|
7
|
-
capabilities: z.array(
|
|
8
|
-
operation: z.string(),
|
|
9
|
-
available: z.boolean(),
|
|
10
|
-
reason: z.string().nullable(),
|
|
11
|
-
availability_code: z.string().nullable().optional(),
|
|
12
|
-
})),
|
|
9
|
+
capabilities: z.array(providerCapability),
|
|
13
10
|
});
|
|
14
|
-
const NO_CLIENT_FEATURES = {
|
|
15
|
-
elicitation_form: false,
|
|
16
|
-
elicitation_url: false,
|
|
17
|
-
roots: false,
|
|
18
|
-
sampling: false,
|
|
19
|
-
};
|
|
20
|
-
const CLIENT_FEATURE_REQUIREMENTS = {
|
|
21
|
-
capture_process_scenario: {
|
|
22
|
-
required: [],
|
|
23
|
-
optional: ["elicitation_form"],
|
|
24
|
-
},
|
|
25
|
-
};
|
|
26
11
|
const ENHANCED_REQUIREMENTS = {
|
|
27
12
|
swift_classes: ["list_procedures"],
|
|
28
13
|
get_objc_classes: ["list_names"],
|
|
@@ -46,24 +31,24 @@ const ENHANCED_REQUIREMENTS = {
|
|
|
46
31
|
"resolve_containing_procedure",
|
|
47
32
|
],
|
|
48
33
|
};
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
"
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
34
|
+
const NAVIGATION_CONTEXT_MODES = [
|
|
35
|
+
{
|
|
36
|
+
name: "current_selection",
|
|
37
|
+
requirements: [
|
|
38
|
+
"current_document",
|
|
39
|
+
"current_address",
|
|
40
|
+
"resolve_containing_procedure",
|
|
41
|
+
],
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
name: "explicit_document",
|
|
45
|
+
requirements: ["current_address", "resolve_containing_procedure"],
|
|
46
|
+
},
|
|
47
|
+
];
|
|
56
48
|
/** Build stable per-operation availability for discovery and tool visibility. */
|
|
57
49
|
export const buildCapabilityInventory = (sessionStatus, policy, clientFeatures = NO_CLIENT_FEATURES) => {
|
|
58
50
|
const status = statusSchema.parse(sessionStatus);
|
|
59
|
-
const descriptors = new Map(status.capabilities.map((descriptor) => [
|
|
60
|
-
descriptor.operation,
|
|
61
|
-
{
|
|
62
|
-
available: descriptor.available,
|
|
63
|
-
reason: descriptor.reason,
|
|
64
|
-
availability_code: descriptor.availability_code ?? null,
|
|
65
|
-
},
|
|
66
|
-
]));
|
|
51
|
+
const descriptors = new Map(status.capabilities.map((descriptor) => [descriptor.operation, descriptor]));
|
|
67
52
|
return GENERATED_MCP_TOOL_CATALOG.map((contract) => {
|
|
68
53
|
const availability = availabilityFor({
|
|
69
54
|
name: contract.name,
|
|
@@ -75,16 +60,15 @@ export const buildCapabilityInventory = (sessionStatus, policy, clientFeatures =
|
|
|
75
60
|
});
|
|
76
61
|
const clientRequirements = clientRequirementsFor(contract.name, clientFeatures);
|
|
77
62
|
const clientBlocked = clientRequirements.missing_required.length > 0;
|
|
78
|
-
|
|
63
|
+
const facts = {
|
|
79
64
|
name: contract.name,
|
|
80
65
|
surface: contract.kind,
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
: availability.remediation,
|
|
66
|
+
...(availability.defaultModeAvailable === undefined
|
|
67
|
+
? {}
|
|
68
|
+
: { default_mode_available: availability.defaultModeAvailable }),
|
|
69
|
+
...(availability.modes === undefined
|
|
70
|
+
? {}
|
|
71
|
+
: { modes: [...availability.modes] }),
|
|
88
72
|
client_requirements: clientRequirements,
|
|
89
73
|
effects: { ...contract.effects },
|
|
90
74
|
annotations: {
|
|
@@ -94,24 +78,31 @@ export const buildCapabilityInventory = (sessionStatus, policy, clientFeatures =
|
|
|
94
78
|
open_world: contract.annotations.openWorldHint ?? true,
|
|
95
79
|
},
|
|
96
80
|
};
|
|
81
|
+
if (clientBlocked)
|
|
82
|
+
return {
|
|
83
|
+
...facts,
|
|
84
|
+
available: false,
|
|
85
|
+
reason: "client_capability_missing",
|
|
86
|
+
remediation: `Use an MCP client that supports: ${clientRequirements.missing_required.join(", ")}.`,
|
|
87
|
+
};
|
|
88
|
+
return availability.reason === "available"
|
|
89
|
+
? {
|
|
90
|
+
...facts,
|
|
91
|
+
available: true,
|
|
92
|
+
reason: availability.reason,
|
|
93
|
+
remediation: null,
|
|
94
|
+
}
|
|
95
|
+
: {
|
|
96
|
+
...facts,
|
|
97
|
+
available: false,
|
|
98
|
+
reason: availability.reason,
|
|
99
|
+
remediation: availability.remediation,
|
|
100
|
+
};
|
|
97
101
|
}).sort((left, right) => left.name.localeCompare(right.name));
|
|
98
102
|
};
|
|
99
|
-
const clientRequirementsFor = (name, clientFeatures) => {
|
|
100
|
-
const requirements = CLIENT_FEATURE_REQUIREMENTS[name] ?? {
|
|
101
|
-
required: [],
|
|
102
|
-
optional: [],
|
|
103
|
-
};
|
|
104
|
-
return {
|
|
105
|
-
required: [...requirements.required],
|
|
106
|
-
optional: [...requirements.optional],
|
|
107
|
-
missing_required: requirements.required.filter((feature) => !clientFeatures[feature]),
|
|
108
|
-
missing_optional: requirements.optional.filter((feature) => !clientFeatures[feature]),
|
|
109
|
-
};
|
|
110
|
-
};
|
|
111
103
|
const availabilityFor = (context) => {
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
return composedAvailabilityFor(sessionComposition, context.descriptors);
|
|
104
|
+
if (context.name === "get_navigation_context")
|
|
105
|
+
return navigationContextAvailability(context.descriptors);
|
|
115
106
|
const javascriptApplication = javascriptApplicationAvailability(context);
|
|
116
107
|
if (javascriptApplication !== null)
|
|
117
108
|
return javascriptApplication;
|
|
@@ -166,13 +157,9 @@ const policyAvailability = ({ name, kind, policy, }) => {
|
|
|
166
157
|
reason: "policy_disabled",
|
|
167
158
|
remediation: "Configure or grant an evidence_read root.",
|
|
168
159
|
};
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
: {
|
|
173
|
-
reason: "policy_disabled",
|
|
174
|
-
remediation: "Enable Electron observation and configure a loopback CDP endpoint and canonical file roots.",
|
|
175
|
-
};
|
|
160
|
+
const electron = electronPolicyAvailability(name, kind, policy);
|
|
161
|
+
if (electron !== null)
|
|
162
|
+
return electron;
|
|
176
163
|
if (kind === "runtime-provider")
|
|
177
164
|
return policy.v8InspectorObservationEnabled === true
|
|
178
165
|
? { reason: "available", remediation: null }
|
|
@@ -184,6 +171,23 @@ const policyAvailability = ({ name, kind, policy, }) => {
|
|
|
184
171
|
return { reason: "available", remediation: null };
|
|
185
172
|
return null;
|
|
186
173
|
};
|
|
174
|
+
const electronPolicyAvailability = (name, kind, policy) => {
|
|
175
|
+
if (kind !== "electron-provider")
|
|
176
|
+
return null;
|
|
177
|
+
if (name === "capture_electron_scenario")
|
|
178
|
+
return policy.electronAutomationEnabled === true
|
|
179
|
+
? { reason: "available", remediation: null }
|
|
180
|
+
: {
|
|
181
|
+
reason: "policy_disabled",
|
|
182
|
+
remediation: "Enable active Electron automation and configure exact executable and application roots.",
|
|
183
|
+
};
|
|
184
|
+
return policy.electronObservationEnabled === true
|
|
185
|
+
? { reason: "available", remediation: null }
|
|
186
|
+
: {
|
|
187
|
+
reason: "policy_disabled",
|
|
188
|
+
remediation: "Enable Electron observation and configure a loopback CDP endpoint and canonical file roots.",
|
|
189
|
+
};
|
|
190
|
+
};
|
|
187
191
|
const browserPolicyAvailability = (name, kind, policy) => {
|
|
188
192
|
if (name === "capture_browser_scenario")
|
|
189
193
|
return policy.browserScenarioEnabled === true
|
|
@@ -272,3 +276,70 @@ const composedAvailabilityFor = (requirements, descriptors) => {
|
|
|
272
276
|
};
|
|
273
277
|
return { reason: "available", remediation: null };
|
|
274
278
|
};
|
|
279
|
+
const navigationContextAvailability = (descriptors) => {
|
|
280
|
+
const modeResults = NAVIGATION_CONTEXT_MODES.map((mode) => {
|
|
281
|
+
const availability = composedAvailabilityFor(mode.requirements, descriptors);
|
|
282
|
+
if (availability.reason === "available")
|
|
283
|
+
return {
|
|
284
|
+
name: mode.name,
|
|
285
|
+
available: true,
|
|
286
|
+
reason: availability.reason,
|
|
287
|
+
missing_operations: [],
|
|
288
|
+
remediation: null,
|
|
289
|
+
};
|
|
290
|
+
return {
|
|
291
|
+
name: mode.name,
|
|
292
|
+
available: false,
|
|
293
|
+
reason: availability.reason,
|
|
294
|
+
missing_operations: mode.requirements.filter((operation) => {
|
|
295
|
+
const descriptor = descriptors.get(operation);
|
|
296
|
+
return descriptor === undefined || descriptor.available === false;
|
|
297
|
+
}),
|
|
298
|
+
remediation: availability.remediation,
|
|
299
|
+
};
|
|
300
|
+
});
|
|
301
|
+
const modes = modeResults.map((mode) => mode.available
|
|
302
|
+
? {
|
|
303
|
+
name: mode.name,
|
|
304
|
+
available: true,
|
|
305
|
+
missing_operations: [],
|
|
306
|
+
remediation: null,
|
|
307
|
+
}
|
|
308
|
+
: {
|
|
309
|
+
name: mode.name,
|
|
310
|
+
available: false,
|
|
311
|
+
missing_operations: [...mode.missing_operations],
|
|
312
|
+
remediation: mode.remediation,
|
|
313
|
+
});
|
|
314
|
+
const availableMode = modeResults.find((mode) => mode.available);
|
|
315
|
+
const failures = modeResults.flatMap((mode) => mode.available ? [] : [mode]);
|
|
316
|
+
const failure = failures.sort((left, right) => navigationFailurePriority(left.reason) -
|
|
317
|
+
navigationFailurePriority(right.reason))[0];
|
|
318
|
+
const specificFailureRemediation = failure?.reason === "provider_missing" ? undefined : failure?.remediation;
|
|
319
|
+
const facts = {
|
|
320
|
+
defaultModeAvailable: modes[0]?.available ?? false,
|
|
321
|
+
modes,
|
|
322
|
+
};
|
|
323
|
+
if (availableMode !== undefined)
|
|
324
|
+
return { ...facts, reason: "available", remediation: null };
|
|
325
|
+
return {
|
|
326
|
+
...facts,
|
|
327
|
+
reason: failure?.reason ?? "provider_missing",
|
|
328
|
+
remediation: specificFailureRemediation ??
|
|
329
|
+
`Configure a provider for one of: ${modes
|
|
330
|
+
.flatMap((mode) => mode.missing_operations)
|
|
331
|
+
.join(", ")}.`,
|
|
332
|
+
};
|
|
333
|
+
};
|
|
334
|
+
const navigationFailurePriority = (reason) => {
|
|
335
|
+
switch (reason) {
|
|
336
|
+
case "unsupported_host":
|
|
337
|
+
return 0;
|
|
338
|
+
case "provider_unavailable":
|
|
339
|
+
return 1;
|
|
340
|
+
case "provider_missing":
|
|
341
|
+
return 2;
|
|
342
|
+
default:
|
|
343
|
+
return 3;
|
|
344
|
+
}
|
|
345
|
+
};
|
|
@@ -6,6 +6,7 @@ import { err, ok } from "../domain/result.js";
|
|
|
6
6
|
import { paginateArtifactInventory, } from "./ArtifactInventory.js";
|
|
7
7
|
import { scanAuthorizedArtifactInventory } from "./AuthorizedArtifactInventory.js";
|
|
8
8
|
import { ARTIFACT_GRAPH_PROVIDER } from "./InvestigationProviders.js";
|
|
9
|
+
import { resolveArtifactIntegrityPolicy } from "./ArtifactInventory/policy.js";
|
|
9
10
|
export const AUTOMATIC_RUN_LIMITATION = "Automatic cross-version runs compare shipped artifact structure only; they do not execute either version.";
|
|
10
11
|
/** Start both independent version scans while preserving left/right identity. */
|
|
11
12
|
export const scanVersionInventories = async (options, scanner = scanAuthorizedArtifactInventory) => {
|
|
@@ -27,12 +28,12 @@ export const scanVersions = async (input, inputRoots, signal, integrityContinueE
|
|
|
27
28
|
if (signal?.aborted === true)
|
|
28
29
|
return err(new AnalysisCancelledError("find_changed_behavior"));
|
|
29
30
|
const limits = artifactLimits(input.options);
|
|
30
|
-
const integrity =
|
|
31
|
-
mode:
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
31
|
+
const integrity = resolveArtifactIntegrityPolicy(input.integrity_policy === "fail"
|
|
32
|
+
? { mode: "fail" }
|
|
33
|
+
: {
|
|
34
|
+
mode: input.integrity_policy,
|
|
35
|
+
maxMismatches: input.max_integrity_mismatches,
|
|
36
|
+
}, integrityContinueEnabled);
|
|
36
37
|
return ok(await scanVersionInventories({
|
|
37
38
|
leftPath: input.left_path,
|
|
38
39
|
rightPath: input.right_path,
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { createEvidence } from "../domain/evidence.js";
|
|
2
|
+
import { jsonValueSchema } from "../domain/jsonValue.js";
|
|
3
|
+
import { digestJson } from "./JavaScriptReplayPlanning.js";
|
|
4
|
+
/** Create Evidence v2 without retaining arbitrary runtime argument values. */
|
|
5
|
+
export const createElectronActiveEvidence = (input, result, provider) => createEvidence(undefined, provider, {
|
|
6
|
+
predicateType: "rea.electron-active-scenario/v1",
|
|
7
|
+
operation: "capture_electron_scenario",
|
|
8
|
+
parameters: parameters(input),
|
|
9
|
+
result: jsonValueSchema.parse(result),
|
|
10
|
+
confidence: "observed",
|
|
11
|
+
authority: "controlled-replay",
|
|
12
|
+
environment: {
|
|
13
|
+
id: `${result.application.electron_version}@${process.platform}`,
|
|
14
|
+
platform: process.platform,
|
|
15
|
+
architecture: process.arch,
|
|
16
|
+
isolation: "none",
|
|
17
|
+
},
|
|
18
|
+
limitations: result.limitations,
|
|
19
|
+
});
|
|
20
|
+
const scenarioProjection = (input) => ({
|
|
21
|
+
approved: input.approved,
|
|
22
|
+
schema_version: input.schema_version,
|
|
23
|
+
executable_path: input.executable_path,
|
|
24
|
+
application_path: input.application_path,
|
|
25
|
+
application_root: input.application_root,
|
|
26
|
+
args: redactArguments(input.args),
|
|
27
|
+
actions: input.actions.map(({ step_id, kind }) => ({ step_id, kind })),
|
|
28
|
+
limits: input.limits,
|
|
29
|
+
});
|
|
30
|
+
const parameters = (input) => ({
|
|
31
|
+
...scenarioProjection(input),
|
|
32
|
+
scenario_sha256: digestJson(scenarioProjection(input)),
|
|
33
|
+
});
|
|
34
|
+
const redactArguments = (arguments_) => {
|
|
35
|
+
let redactNext = false;
|
|
36
|
+
return arguments_.map((argument) => {
|
|
37
|
+
if (redactNext) {
|
|
38
|
+
redactNext = false;
|
|
39
|
+
return "<redacted>";
|
|
40
|
+
}
|
|
41
|
+
if (sensitiveFlag.test(argument)) {
|
|
42
|
+
redactNext = true;
|
|
43
|
+
return argument;
|
|
44
|
+
}
|
|
45
|
+
return redactArgument(argument);
|
|
46
|
+
});
|
|
47
|
+
};
|
|
48
|
+
const sensitiveFlag = /^--?(?:password|token|secret|api[-_]?key|authorization|cookie)$/iu;
|
|
49
|
+
const redactArgument = (argument) => {
|
|
50
|
+
if (/^--?(?:password|token|secret|api[-_]?key|authorization|cookie)=/iu.test(argument))
|
|
51
|
+
return `${argument.slice(0, argument.indexOf("=") + 1)}<redacted>`;
|
|
52
|
+
return argument.length > 256
|
|
53
|
+
? `${argument.slice(0, 256)}<redacted>`
|
|
54
|
+
: argument;
|
|
55
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { realpath } from "node:fs/promises";
|
|
2
|
+
import { digestJson } from "./JavaScriptReplayPlanning.js";
|
|
3
|
+
import { AnalysisCapabilityUnavailableError, AnalysisInputError, AnalysisProtocolError, PermissionRequiredError, } from "../domain/errors.js";
|
|
4
|
+
import { isPathContained } from "../domain/permissionPolicy.js";
|
|
5
|
+
import { err } from "../domain/result.js";
|
|
6
|
+
import { createElectronActiveEvidence } from "./ElectronActiveEvidence.js";
|
|
7
|
+
const OPERATION = "capture_electron_scenario";
|
|
8
|
+
const PROVIDER_ID = "rea-playwright-electron-active";
|
|
9
|
+
const canonicalizeInput = async (input) => {
|
|
10
|
+
try {
|
|
11
|
+
const [executablePath, applicationPath, applicationRoot] = await Promise.all([
|
|
12
|
+
realpath(input.executable_path),
|
|
13
|
+
realpath(input.application_path),
|
|
14
|
+
realpath(input.application_root),
|
|
15
|
+
]);
|
|
16
|
+
if (!isPathContained(applicationRoot, applicationPath))
|
|
17
|
+
return err(new AnalysisInputError(OPERATION, undefined, [
|
|
18
|
+
{
|
|
19
|
+
path: ["application_path"],
|
|
20
|
+
reason: "invalid_value",
|
|
21
|
+
message: "application_path must remain beneath application_root after symlink resolution",
|
|
22
|
+
},
|
|
23
|
+
]));
|
|
24
|
+
return {
|
|
25
|
+
ok: true,
|
|
26
|
+
value: {
|
|
27
|
+
...input,
|
|
28
|
+
executable_path: executablePath,
|
|
29
|
+
application_path: applicationPath,
|
|
30
|
+
application_root: applicationRoot,
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
catch (cause) {
|
|
35
|
+
return err(new AnalysisInputError(OPERATION, { cause }, [
|
|
36
|
+
{
|
|
37
|
+
path: ["application_path"],
|
|
38
|
+
reason: "invalid_format",
|
|
39
|
+
message: "Electron executable, application, and root must resolve to existing paths",
|
|
40
|
+
},
|
|
41
|
+
]));
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
const authorize = async (authority, input) => {
|
|
45
|
+
const canonical = await canonicalizeInput(input);
|
|
46
|
+
if (!canonical.ok)
|
|
47
|
+
return canonical;
|
|
48
|
+
if (authority === undefined)
|
|
49
|
+
return err(new AnalysisCapabilityUnavailableError(PROVIDER_ID, OPERATION, "active Electron observation permission policy is not configured"));
|
|
50
|
+
const authorized = await authority.authorize({
|
|
51
|
+
capability: "electron_automate",
|
|
52
|
+
roots: [canonical.value.application_root],
|
|
53
|
+
executables: [canonical.value.executable_path],
|
|
54
|
+
environment_names: [],
|
|
55
|
+
network: "external",
|
|
56
|
+
mount: false,
|
|
57
|
+
operation_identity: `${OPERATION}:${digestJson(canonical.value)}`,
|
|
58
|
+
}, "write");
|
|
59
|
+
if (!authorized.ok)
|
|
60
|
+
return err(authorized.error instanceof PermissionRequiredError
|
|
61
|
+
? authorized.error
|
|
62
|
+
: new AnalysisProtocolError(authorized.error.message, {
|
|
63
|
+
cause: authorized.error,
|
|
64
|
+
}));
|
|
65
|
+
return canonical;
|
|
66
|
+
};
|
|
67
|
+
/** Authorize and execute one bounded, provider-owned Electron experiment. */
|
|
68
|
+
export const captureElectronScenario = async (provider, authority, input, options = {}) => {
|
|
69
|
+
const authorized = await authorize(authority, input);
|
|
70
|
+
if (!authorized.ok)
|
|
71
|
+
return authorized;
|
|
72
|
+
if (provider === undefined)
|
|
73
|
+
return err(new AnalysisCapabilityUnavailableError(PROVIDER_ID, OPERATION, "active Electron observation provider is not configured"));
|
|
74
|
+
const captured = await provider.capture(authorized.value, options);
|
|
75
|
+
return captured.ok
|
|
76
|
+
? {
|
|
77
|
+
ok: true,
|
|
78
|
+
value: createElectronActiveEvidence(authorized.value, captured.value, provider.identity()),
|
|
79
|
+
}
|
|
80
|
+
: captured;
|
|
81
|
+
};
|
|
@@ -102,32 +102,34 @@ export class EnhancedTools {
|
|
|
102
102
|
}
|
|
103
103
|
}
|
|
104
104
|
#executeTracing(name, input, signal) {
|
|
105
|
-
|
|
105
|
+
if (name === "trace_call_path") {
|
|
106
|
+
const parsed = enhancedInputSchemas.trace_call_path.safeParse(input);
|
|
107
|
+
if (!parsed.success)
|
|
108
|
+
return invalidEnhancedInput(name, parsed.error);
|
|
109
|
+
return this.executeValidated({ name, input: parsed.data }, signal);
|
|
110
|
+
}
|
|
111
|
+
if (name === "trace_feature") {
|
|
112
|
+
const parsed = enhancedInputSchemas.trace_feature.safeParse(input);
|
|
113
|
+
if (!parsed.success)
|
|
114
|
+
return invalidEnhancedInput(name, parsed.error);
|
|
115
|
+
return this.executeValidated({ name, input: parsed.data }, signal);
|
|
116
|
+
}
|
|
117
|
+
const parsed = enhancedInputSchemas.find_code_for_string.safeParse(input);
|
|
106
118
|
if (!parsed.success)
|
|
107
119
|
return invalidEnhancedInput(name, parsed.error);
|
|
108
|
-
|
|
109
|
-
return this.executeValidated({
|
|
110
|
-
name,
|
|
111
|
-
input: enhancedInputSchemas.trace_call_path.parse(parsed.data),
|
|
112
|
-
}, signal);
|
|
113
|
-
return this.executeValidated({
|
|
114
|
-
name,
|
|
115
|
-
input: enhancedInputSchemas[name].parse(parsed.data),
|
|
116
|
-
}, signal);
|
|
120
|
+
return this.executeValidated({ name, input: parsed.data }, signal);
|
|
117
121
|
}
|
|
118
122
|
#executeFunctionAnalysis(name, input, signal) {
|
|
119
|
-
|
|
123
|
+
if (name === "analyze_function") {
|
|
124
|
+
const parsed = enhancedInputSchemas.analyze_function.safeParse(input);
|
|
125
|
+
if (!parsed.success)
|
|
126
|
+
return invalidEnhancedInput(name, parsed.error);
|
|
127
|
+
return this.executeValidated({ name, input: parsed.data }, signal);
|
|
128
|
+
}
|
|
129
|
+
const parsed = enhancedInputSchemas.inspect_native_api.safeParse(input);
|
|
120
130
|
if (!parsed.success)
|
|
121
131
|
return invalidEnhancedInput(name, parsed.error);
|
|
122
|
-
|
|
123
|
-
return this.executeValidated({
|
|
124
|
-
name,
|
|
125
|
-
input: enhancedInputSchemas.analyze_function.parse(parsed.data),
|
|
126
|
-
}, signal);
|
|
127
|
-
return this.executeValidated({
|
|
128
|
-
name,
|
|
129
|
-
input: enhancedInputSchemas.inspect_native_api.parse(parsed.data),
|
|
130
|
-
}, signal);
|
|
132
|
+
return this.executeValidated({ name, input: parsed.data }, signal);
|
|
131
133
|
}
|
|
132
134
|
async #analyzeFunction(input, signal) {
|
|
133
135
|
const result = await this.#call("analyze_function", input, signal);
|
|
@@ -12,7 +12,11 @@ export const importEvidenceBundleCommand = async (path, policy) => {
|
|
|
12
12
|
const ledger = createLedger();
|
|
13
13
|
const imported = ledger.import(loaded.value);
|
|
14
14
|
return imported.ok
|
|
15
|
-
? ok({
|
|
15
|
+
? ok({
|
|
16
|
+
imported: imported.value.recordsAdded,
|
|
17
|
+
unknowns_added: imported.value.unknownsAdded,
|
|
18
|
+
total: ledger.export().records.length,
|
|
19
|
+
})
|
|
16
20
|
: imported;
|
|
17
21
|
};
|
|
18
22
|
/** Validate a source bundle and atomically export canonical bytes. */
|
|
@@ -63,6 +63,7 @@ export class EvidenceLedger {
|
|
|
63
63
|
pending.set(evidence.evidence_id, evidence);
|
|
64
64
|
}
|
|
65
65
|
const pendingUnknowns = new Map(this.#unknownRevisions);
|
|
66
|
+
let unknownsAdded = 0;
|
|
66
67
|
for (const unknown of bundle.unknowns) {
|
|
67
68
|
const key = unknownRevisionKey(unknown);
|
|
68
69
|
const existing = pendingUnknowns.get(key);
|
|
@@ -70,6 +71,8 @@ export class EvidenceLedger {
|
|
|
70
71
|
existing.revision_digest !== unknown.revision_digest)
|
|
71
72
|
return err(new EvidenceIntegrityError("Conflicting unknown revision"));
|
|
72
73
|
pendingUnknowns.set(key, unknown);
|
|
74
|
+
if (existing === undefined)
|
|
75
|
+
unknownsAdded += 1;
|
|
73
76
|
}
|
|
74
77
|
const checked = this.#validateCandidate(pending, pendingUnknowns);
|
|
75
78
|
if (!checked.ok) {
|
|
@@ -81,7 +84,11 @@ export class EvidenceLedger {
|
|
|
81
84
|
}
|
|
82
85
|
const added = pending.size - this.#records.size;
|
|
83
86
|
this.#commit(pending, pendingUnknowns, checked.value);
|
|
84
|
-
return ok(
|
|
87
|
+
return ok({
|
|
88
|
+
recordsAdded: added,
|
|
89
|
+
unknownsAdded,
|
|
90
|
+
changed: added > 0 || unknownsAdded > 0,
|
|
91
|
+
});
|
|
85
92
|
}
|
|
86
93
|
/** Export records in deterministic, semantically irrelevant ID order. */
|
|
87
94
|
export() {
|
|
@@ -12,5 +12,5 @@ export const replayPermissionRequest = (input, policy) => ({
|
|
|
12
12
|
environment_names: [],
|
|
13
13
|
network: "none",
|
|
14
14
|
mount: true,
|
|
15
|
-
operation_identity: `run_controlled_replay:${input.
|
|
15
|
+
operation_identity: `run_controlled_replay:${input.mode === "plan" ? "plan" : input.plan_digest}`,
|
|
16
16
|
});
|
|
@@ -19,10 +19,10 @@ export const runControlledReplay = async (dependencies, rawInput, options = {})
|
|
|
19
19
|
};
|
|
20
20
|
/** Plan or execute replay input already parsed by a trusted adapter. */
|
|
21
21
|
export const runControlledReplayValidated = async (dependencies, input, options = {}) => {
|
|
22
|
-
const authorized = await authorizeReplay(dependencies, input, options.signal);
|
|
22
|
+
const authorized = await authorizeReplay(dependencies, dependencies.policy(), input, options.signal);
|
|
23
23
|
if (!authorized.ok)
|
|
24
24
|
return authorized;
|
|
25
|
-
const prepared = await prepareValidatedReplay(dependencies, input, options.signal);
|
|
25
|
+
const prepared = await prepareValidatedReplay(dependencies, authorized.value, input, options.signal);
|
|
26
26
|
if (!prepared.ok)
|
|
27
27
|
return prepared;
|
|
28
28
|
if (isAborted(options.signal))
|
|
@@ -35,11 +35,17 @@ export const runControlledReplayValidated = async (dependencies, input, options
|
|
|
35
35
|
evidence: null,
|
|
36
36
|
}));
|
|
37
37
|
if (input.plan_digest !== prepared.value.publicPlan.plan_digest)
|
|
38
|
-
return err(new ReplayPlanStaleError(input.plan_digest
|
|
38
|
+
return err(new ReplayPlanStaleError(input.plan_digest, prepared.value.publicPlan.plan_digest));
|
|
39
39
|
const exportContext = await authorizeReproducerExport(dependencies.authority, input, prepared.value);
|
|
40
40
|
if (!exportContext.ok)
|
|
41
41
|
return exportContext;
|
|
42
|
-
const executed = await executeValidatedReplay(
|
|
42
|
+
const executed = await executeValidatedReplay({
|
|
43
|
+
runner: dependencies.runner,
|
|
44
|
+
policy: authorized.value,
|
|
45
|
+
prepared: prepared.value,
|
|
46
|
+
exportContext: exportContext.value,
|
|
47
|
+
options,
|
|
48
|
+
});
|
|
43
49
|
if (!executed.ok)
|
|
44
50
|
return executed;
|
|
45
51
|
try {
|
|
@@ -51,14 +57,14 @@ export const runControlledReplayValidated = async (dependencies, input, options
|
|
|
51
57
|
: "Controlled replay could not establish or clean up its sandbox", { cause }));
|
|
52
58
|
}
|
|
53
59
|
};
|
|
54
|
-
const authorizeReplay = async (dependencies, input, signal) => {
|
|
55
|
-
if (
|
|
60
|
+
const authorizeReplay = async (dependencies, policy, input, signal) => {
|
|
61
|
+
if (policy.status === "disabled")
|
|
56
62
|
return err(new AnalysisCapabilityUnavailableError("rea-javascript-replay", OPERATION, "controlled replay is disabled; configure exact roots and executables before enabling it"));
|
|
57
63
|
if (dependencies.authority === undefined)
|
|
58
64
|
return err(new AnalysisCapabilityUnavailableError("rea-javascript-replay", OPERATION, "JavaScript replay permission policy is not configured"));
|
|
59
65
|
if (isAborted(signal))
|
|
60
66
|
return err(new AnalysisCancelledError(OPERATION));
|
|
61
|
-
const request = replayPermissionRequest(input,
|
|
67
|
+
const request = replayPermissionRequest(input, policy);
|
|
62
68
|
const authorized = input.mode === "plan"
|
|
63
69
|
? await dependencies.authority.explain(request, "read")
|
|
64
70
|
: await dependencies.authority.authorize(request, "read");
|
|
@@ -68,13 +74,13 @@ const authorizeReplay = async (dependencies, input, signal) => {
|
|
|
68
74
|
: new AnalysisProtocolError(authorized.error.message, {
|
|
69
75
|
cause: authorized.error,
|
|
70
76
|
}));
|
|
71
|
-
return ok(
|
|
77
|
+
return ok(policy);
|
|
72
78
|
};
|
|
73
|
-
const prepareValidatedReplay = async (dependencies, input, signal) => {
|
|
79
|
+
const prepareValidatedReplay = async (dependencies, policy, input, signal) => {
|
|
74
80
|
if (isAborted(signal))
|
|
75
81
|
return err(new AnalysisCancelledError(OPERATION));
|
|
76
82
|
try {
|
|
77
|
-
return ok(await prepareReplayPlan(input,
|
|
83
|
+
return ok(await prepareReplayPlan(input, policy, dependencies.host));
|
|
78
84
|
}
|
|
79
85
|
catch (cause) {
|
|
80
86
|
return err(new AnalysisCapabilityUnavailableError("rea-javascript-replay", OPERATION, cause instanceof Error ? cause.message : "replay planning failed"));
|
|
@@ -83,8 +89,6 @@ const prepareValidatedReplay = async (dependencies, input, signal) => {
|
|
|
83
89
|
const authorizeReproducerExport = async (authority, input, prepared) => {
|
|
84
90
|
if (input.reproducer_export === undefined)
|
|
85
91
|
return ok(undefined);
|
|
86
|
-
if (input.reproducer_export.approved !== true)
|
|
87
|
-
return err(new AnalysisInputError(`${OPERATION}:reproducer_export`));
|
|
88
92
|
if (authority === undefined)
|
|
89
93
|
return err(new AnalysisCapabilityUnavailableError("rea-javascript-replay", OPERATION, "JavaScript replay permission policy is not configured"));
|
|
90
94
|
const exportAuthorized = await authority.authorize({
|
|
@@ -112,7 +116,8 @@ const authorizeReproducerExport = async (authority, input, prepared) => {
|
|
|
112
116
|
includeSources: input.reproducer_export.include_sources === true,
|
|
113
117
|
});
|
|
114
118
|
};
|
|
115
|
-
const executeValidatedReplay = async (
|
|
119
|
+
const executeValidatedReplay = async (context) => {
|
|
120
|
+
const { runner, policy, prepared, exportContext, options } = context;
|
|
116
121
|
await options.progress?.report({
|
|
117
122
|
phase: OPERATION,
|
|
118
123
|
completed: 0,
|
|
@@ -122,7 +127,7 @@ const executeValidatedReplay = async (dependencies, prepared, exportContext, opt
|
|
|
122
127
|
if (isAborted(options.signal))
|
|
123
128
|
return err(new AnalysisCancelledError(OPERATION));
|
|
124
129
|
try {
|
|
125
|
-
let executed = replayExecutionResultSchema.parse(await
|
|
130
|
+
let executed = replayExecutionResultSchema.parse(await runner.execute(prepared, policy, options.signal));
|
|
126
131
|
await options.progress?.report({
|
|
127
132
|
phase: OPERATION,
|
|
128
133
|
completed: 1,
|
|
@@ -289,4 +294,7 @@ const createReplayEvidence = (prepared, executed, side, outcomes) => {
|
|
|
289
294
|
})),
|
|
290
295
|
});
|
|
291
296
|
};
|
|
292
|
-
const asJson = (value) =>
|
|
297
|
+
const asJson = (value) => {
|
|
298
|
+
const serialized = JSON.parse(JSON.stringify(controlledReplayOutputSchema.parse(value)));
|
|
299
|
+
return jsonValueSchema.parse(serialized);
|
|
300
|
+
};
|