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,5 +1,4 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import { jsonValueSchema } from "./jsonValue.js";
|
|
3
2
|
import { AnalysisOutputError, HopperProtocolError } from "./errors.js";
|
|
4
3
|
import { err, ok } from "./result.js";
|
|
5
4
|
import { nativeApiBoundarySchema } from "./nativeApiBoundary.js";
|
|
@@ -35,31 +34,24 @@ const segmentSchema = z.object({
|
|
|
35
34
|
writable: z.boolean().nullable().default(null),
|
|
36
35
|
executable: z.boolean().nullable().default(null),
|
|
37
36
|
});
|
|
38
|
-
const
|
|
39
|
-
.object({
|
|
37
|
+
const addressedPageFacts = {
|
|
40
38
|
items: z.array(z.object({ address: z.string(), value: z.string() })),
|
|
41
39
|
offset: z.number().int().min(0),
|
|
42
40
|
limit: z.number().int().min(1),
|
|
43
41
|
total: z.number().int().min(0),
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
code: "custom",
|
|
58
|
-
message: "a complete page must not provide next_offset",
|
|
59
|
-
path: ["next_offset"],
|
|
60
|
-
});
|
|
61
|
-
}
|
|
62
|
-
});
|
|
42
|
+
};
|
|
43
|
+
const addressedPageSchema = z.discriminatedUnion("has_more", [
|
|
44
|
+
z.object({
|
|
45
|
+
...addressedPageFacts,
|
|
46
|
+
has_more: z.literal(true),
|
|
47
|
+
next_offset: z.number().int().min(0),
|
|
48
|
+
}),
|
|
49
|
+
z.object({
|
|
50
|
+
...addressedPageFacts,
|
|
51
|
+
has_more: z.literal(false),
|
|
52
|
+
next_offset: z.null(),
|
|
53
|
+
}),
|
|
54
|
+
]);
|
|
63
55
|
const unavailableAnalysisFactSchema = z
|
|
64
56
|
.object({ available: z.literal(false), reason: z.string() })
|
|
65
57
|
.strict();
|
|
@@ -84,38 +76,42 @@ export const localVariableSchema = z
|
|
|
84
76
|
provenance: z.string().min(1),
|
|
85
77
|
})
|
|
86
78
|
.strict();
|
|
87
|
-
const boundedSchema = (item) =>
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
79
|
+
const boundedSchema = (item) => {
|
|
80
|
+
const boundedFacts = {
|
|
81
|
+
items: z.array(item),
|
|
82
|
+
total: z.number().int().min(0).nullable(),
|
|
83
|
+
returned: z.number().int().min(0),
|
|
84
|
+
};
|
|
85
|
+
return z
|
|
86
|
+
.discriminatedUnion("truncated", [
|
|
87
|
+
z.strictObject({
|
|
88
|
+
...boundedFacts,
|
|
89
|
+
truncated: z.literal(false),
|
|
90
|
+
next_offset: z.null(),
|
|
91
|
+
}),
|
|
92
|
+
z.strictObject({
|
|
93
|
+
...boundedFacts,
|
|
94
|
+
truncated: z.literal(true),
|
|
95
|
+
next_offset: z.number().int().min(0).nullable(),
|
|
96
|
+
}),
|
|
97
|
+
])
|
|
98
|
+
.superRefine((value, context) => {
|
|
99
|
+
if (value.returned !== value.items.length) {
|
|
100
|
+
context.addIssue({
|
|
101
|
+
code: "custom",
|
|
102
|
+
message: "returned must equal the number of items",
|
|
103
|
+
path: ["returned"],
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
if (value.total !== null && value.total < value.returned) {
|
|
107
|
+
context.addIssue({
|
|
108
|
+
code: "custom",
|
|
109
|
+
message: "total cannot be smaller than returned",
|
|
110
|
+
path: ["total"],
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
};
|
|
119
115
|
/** Provider-neutral bounded raw-instruction window for one analyzed function. */
|
|
120
116
|
export const functionInstructionWindowSchema = z
|
|
121
117
|
.object({
|
|
@@ -171,14 +167,22 @@ export const functionDossierSchema = z
|
|
|
171
167
|
})
|
|
172
168
|
.strict(),
|
|
173
169
|
pseudocode: z
|
|
174
|
-
.
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
170
|
+
.discriminatedUnion("truncated", [
|
|
171
|
+
z.strictObject({
|
|
172
|
+
text: z.string(),
|
|
173
|
+
total_chars: z.number().int().min(0),
|
|
174
|
+
returned_chars: z.number().int().min(0),
|
|
175
|
+
truncated: z.literal(false),
|
|
176
|
+
next_offset: z.null(),
|
|
177
|
+
}),
|
|
178
|
+
z.strictObject({
|
|
179
|
+
text: z.string(),
|
|
180
|
+
total_chars: z.number().int().min(0),
|
|
181
|
+
returned_chars: z.number().int().min(0),
|
|
182
|
+
truncated: z.literal(true),
|
|
183
|
+
next_offset: z.number().int().min(0).nullable(),
|
|
184
|
+
}),
|
|
185
|
+
])
|
|
182
186
|
.superRefine((value, context) => {
|
|
183
187
|
if (value.returned_chars !== [...value.text].length) {
|
|
184
188
|
context.addIssue({
|
|
@@ -194,13 +198,6 @@ export const functionDossierSchema = z
|
|
|
194
198
|
path: ["total_chars"],
|
|
195
199
|
});
|
|
196
200
|
}
|
|
197
|
-
if (value.next_offset !== null && !value.truncated) {
|
|
198
|
-
context.addIssue({
|
|
199
|
-
code: "custom",
|
|
200
|
-
message: "a continuation requires truncated pseudocode",
|
|
201
|
-
path: ["next_offset"],
|
|
202
|
-
});
|
|
203
|
-
}
|
|
204
201
|
}),
|
|
205
202
|
assembly: boundedSchema(z.string()),
|
|
206
203
|
comments: boundedSchema(z
|
|
@@ -238,7 +235,7 @@ export const functionDossierSchema = z
|
|
|
238
235
|
instruction_scan: z
|
|
239
236
|
.object({ scanned: z.number().int().min(0), truncated: z.boolean() })
|
|
240
237
|
.strict(),
|
|
241
|
-
native_api: nativeApiBoundarySchema.
|
|
238
|
+
native_api: nativeApiBoundarySchema.nullable().default(null),
|
|
242
239
|
limitations: z.array(z.string()).default([]),
|
|
243
240
|
})
|
|
244
241
|
.strict();
|
|
@@ -246,7 +243,7 @@ export const functionDossierSchema = z
|
|
|
246
243
|
export const parseFunctionDossier = (value) => {
|
|
247
244
|
const parsed = functionDossierSchema.safeParse(value);
|
|
248
245
|
return parsed.success
|
|
249
|
-
? ok(
|
|
246
|
+
? ok(parsed.data)
|
|
250
247
|
: err(new AnalysisOutputError("analyze_function", "provider output did not match the dossier contract", { cause: parsed.error }));
|
|
251
248
|
};
|
|
252
249
|
/** Parse page entries and continuation metadata returned by list operations. */
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
export const projectInputIssues = (issues, input) => issues.flatMap((issue) => projectIssue(issue, input));
|
|
3
3
|
const projectIssue = (issue, input) => {
|
|
4
4
|
const path = issue.path.flatMap((part) => typeof part === "string" || typeof part === "number" ? [part] : []);
|
|
5
|
+
if (issue.code === "invalid_union")
|
|
6
|
+
return issue.errors.flatMap((branch) => branch.flatMap((branchIssue) => projectIssue(branchIssue, input)));
|
|
5
7
|
if (issue.code === "unrecognized_keys")
|
|
6
8
|
return issue.keys.map((key) => ({
|
|
7
9
|
path: [...path, key],
|
|
@@ -44,7 +46,8 @@ const valueAtPath = (input, path) => {
|
|
|
44
46
|
for (const part of path) {
|
|
45
47
|
if (typeof current !== "object" || current === null)
|
|
46
48
|
return undefined;
|
|
47
|
-
|
|
49
|
+
const next = Reflect.get(current, part);
|
|
50
|
+
current = next;
|
|
48
51
|
}
|
|
49
52
|
return current;
|
|
50
53
|
};
|
|
@@ -37,8 +37,7 @@ const DEFAULT_INVESTIGATION_RUN_OPTIONS = {
|
|
|
37
37
|
change_limit: 500,
|
|
38
38
|
};
|
|
39
39
|
/** Explicit write approval and two local versions for an automatic run. */
|
|
40
|
-
|
|
41
|
-
.object({
|
|
40
|
+
const crossVersionInvestigationFacts = {
|
|
42
41
|
approved: z.literal(true),
|
|
43
42
|
workspace_path: z.string().min(1).max(4_096),
|
|
44
43
|
workspace_name: z.string().trim().min(1).max(200).default("default"),
|
|
@@ -49,20 +48,22 @@ export const crossVersionInvestigationInputSchema = z
|
|
|
49
48
|
.optional(),
|
|
50
49
|
left_path: z.string().min(1).max(4_096),
|
|
51
50
|
right_path: z.string().min(1).max(4_096),
|
|
52
|
-
integrity_policy: z.enum(["fail", "record-and-continue"]).default("fail"),
|
|
53
|
-
integrity_continue_approved: z.boolean().default(false),
|
|
54
|
-
max_integrity_mismatches: z.number().int().min(1).max(100).default(10),
|
|
55
51
|
options: investigationRunOptionsSchema.default(DEFAULT_INVESTIGATION_RUN_OPTIONS),
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
52
|
+
};
|
|
53
|
+
export const crossVersionInvestigationInputSchema = z.union([
|
|
54
|
+
z.object({
|
|
55
|
+
...crossVersionInvestigationFacts,
|
|
56
|
+
integrity_policy: z.literal("fail").default("fail"),
|
|
57
|
+
integrity_continue_approved: z.literal(false).default(false),
|
|
58
|
+
max_integrity_mismatches: z.number().int().min(1).max(100).default(10),
|
|
59
|
+
}),
|
|
60
|
+
z.object({
|
|
61
|
+
...crossVersionInvestigationFacts,
|
|
62
|
+
integrity_policy: z.literal("record-and-continue"),
|
|
63
|
+
integrity_continue_approved: z.literal(true),
|
|
64
|
+
max_integrity_mismatches: z.number().int().min(1).max(100).default(10),
|
|
65
|
+
}),
|
|
66
|
+
]);
|
|
66
67
|
const targetSchema = z.object({
|
|
67
68
|
root_sha256: digestSchema,
|
|
68
69
|
graph_sha256: digestSchema,
|
|
@@ -223,7 +223,7 @@ const comparisonChangeSchema = z.strictObject({
|
|
|
223
223
|
right: valueAvailabilitySchema,
|
|
224
224
|
left_source_range: sourceRangeSchema.nullable(),
|
|
225
225
|
right_source_range: sourceRangeSchema.nullable(),
|
|
226
|
-
evidence_links: z.
|
|
226
|
+
evidence_links: z.array(evidenceIdSchema).length(2),
|
|
227
227
|
limitations: z.array(boundedTextSchema).max(20),
|
|
228
228
|
});
|
|
229
229
|
/** Bounded static export-return comparison with explicit unknown semantics. */
|
|
@@ -267,7 +267,7 @@ export const javaScriptExportShapeComparisonResultSchema = z.strictObject({
|
|
|
267
267
|
omitted_candidates: z.number().int().min(0),
|
|
268
268
|
omitted_changes: z.number().int().min(0),
|
|
269
269
|
}),
|
|
270
|
-
evidence_links: z.
|
|
270
|
+
evidence_links: z.array(evidenceIdSchema).length(2),
|
|
271
271
|
limitations: z.array(boundedTextSchema).max(1_000),
|
|
272
272
|
runtime_validation: z.strictObject({
|
|
273
273
|
recommended_tool: z.literal("run_controlled_replay"),
|
|
@@ -105,9 +105,7 @@ const determinismSchema = z
|
|
|
105
105
|
platform: z.literal("linux").default("linux"),
|
|
106
106
|
})
|
|
107
107
|
.strict();
|
|
108
|
-
|
|
109
|
-
.object({
|
|
110
|
-
mode: z.enum(["plan", "execute"]),
|
|
108
|
+
const controlledReplayInputShape = {
|
|
111
109
|
left: replaySideSchema,
|
|
112
110
|
right: replaySideSchema.optional(),
|
|
113
111
|
cases: z.array(explicitCaseSchema).max(128).default([]),
|
|
@@ -133,18 +131,32 @@ export const controlledReplayInputSchema = z
|
|
|
133
131
|
result_depth: 16,
|
|
134
132
|
result_nodes: 10_000,
|
|
135
133
|
}),
|
|
136
|
-
approved: z.boolean().default(false),
|
|
137
|
-
plan_digest: digestSchema.optional(),
|
|
138
134
|
reproducer_export: z
|
|
139
|
-
.
|
|
135
|
+
.strictObject({
|
|
140
136
|
path: absolutePathSchema,
|
|
141
|
-
approved: z.
|
|
137
|
+
approved: z.literal(true),
|
|
142
138
|
include_sources: z.boolean().default(false),
|
|
143
139
|
})
|
|
144
|
-
.strict()
|
|
145
140
|
.optional(),
|
|
146
|
-
}
|
|
147
|
-
|
|
141
|
+
};
|
|
142
|
+
/** Parse a replay request that can only construct a plan. */
|
|
143
|
+
export const controlledReplayPlanInputSchema = z.strictObject({
|
|
144
|
+
...controlledReplayInputShape,
|
|
145
|
+
mode: z.literal("plan"),
|
|
146
|
+
});
|
|
147
|
+
/** Parse a replay request carrying literal approval for one exact plan. */
|
|
148
|
+
export const controlledReplayExecutionInputSchema = z.strictObject({
|
|
149
|
+
...controlledReplayInputShape,
|
|
150
|
+
mode: z.literal("execute"),
|
|
151
|
+
approved: z.literal(true),
|
|
152
|
+
plan_digest: digestSchema,
|
|
153
|
+
});
|
|
154
|
+
/** Parse a controlled replay request into its legal plan or execution state. */
|
|
155
|
+
export const controlledReplayInputSchema = z
|
|
156
|
+
.discriminatedUnion("mode", [
|
|
157
|
+
controlledReplayPlanInputSchema,
|
|
158
|
+
controlledReplayExecutionInputSchema,
|
|
159
|
+
])
|
|
148
160
|
.superRefine((value, context) => {
|
|
149
161
|
if (value.cases.length === 0 && value.generator === undefined)
|
|
150
162
|
context.addIssue({
|
|
@@ -158,13 +170,6 @@ export const controlledReplayInputSchema = z
|
|
|
158
170
|
path: ["generator", "count"],
|
|
159
171
|
message: "Explicit and generated replay cases must total at most 128",
|
|
160
172
|
});
|
|
161
|
-
if (value.mode === "execute" &&
|
|
162
|
-
(value.approved !== true || value.plan_digest === undefined))
|
|
163
|
-
context.addIssue({
|
|
164
|
-
code: "custom",
|
|
165
|
-
path: ["approved"],
|
|
166
|
-
message: "Execution requires literal approval and a plan digest",
|
|
167
|
-
});
|
|
168
173
|
});
|
|
169
174
|
const moduleCommitmentSchema = z
|
|
170
175
|
.object({
|
|
@@ -201,7 +206,7 @@ const replayPlanSchema = z
|
|
|
201
206
|
filesystem: z
|
|
202
207
|
.object({
|
|
203
208
|
host_writes: z.literal(false),
|
|
204
|
-
private_tmpfs_bytes: z.number().int(),
|
|
209
|
+
private_tmpfs_bytes: z.number().int().nonnegative(),
|
|
205
210
|
})
|
|
206
211
|
.strict(),
|
|
207
212
|
runtime: z
|
|
@@ -255,34 +260,45 @@ const replayPlanSchema = z
|
|
|
255
260
|
.nullable(),
|
|
256
261
|
})
|
|
257
262
|
.strict();
|
|
258
|
-
const
|
|
259
|
-
.object({
|
|
263
|
+
const replayOutcomeFacts = {
|
|
260
264
|
case_id: z.string(),
|
|
261
|
-
outcome: z.enum([
|
|
262
|
-
"return",
|
|
263
|
-
"exception",
|
|
264
|
-
"serialization_error",
|
|
265
|
-
"denied",
|
|
266
|
-
"timeout",
|
|
267
|
-
"oom",
|
|
268
|
-
"crash",
|
|
269
|
-
"cancelled",
|
|
270
|
-
"protocol_error",
|
|
271
|
-
]),
|
|
272
|
-
value: z.json().optional(),
|
|
273
|
-
exception: z
|
|
274
|
-
.object({
|
|
275
|
-
name: z.string(),
|
|
276
|
-
message: z.string(),
|
|
277
|
-
stack: z.string().nullable(),
|
|
278
|
-
})
|
|
279
|
-
.strict()
|
|
280
|
-
.optional(),
|
|
281
265
|
input_sha256: digestSchema,
|
|
282
|
-
|
|
283
|
-
|
|
266
|
+
};
|
|
267
|
+
const replayExceptionSchema = z
|
|
268
|
+
.object({
|
|
269
|
+
name: z.string(),
|
|
270
|
+
message: z.string(),
|
|
271
|
+
stack: z.string().nullable(),
|
|
284
272
|
})
|
|
285
273
|
.strict();
|
|
274
|
+
const replayOutcomeSchema = z.discriminatedUnion("outcome", [
|
|
275
|
+
z.strictObject({
|
|
276
|
+
...replayOutcomeFacts,
|
|
277
|
+
outcome: z.literal("return"),
|
|
278
|
+
value: z.json(),
|
|
279
|
+
output_sha256: digestSchema,
|
|
280
|
+
truncated: z.literal(false),
|
|
281
|
+
}),
|
|
282
|
+
z.strictObject({
|
|
283
|
+
...replayOutcomeFacts,
|
|
284
|
+
outcome: z.enum(["exception", "serialization_error", "denied"]),
|
|
285
|
+
exception: z.object(replayExceptionSchema.shape).strict(),
|
|
286
|
+
output_sha256: digestSchema,
|
|
287
|
+
truncated: z.literal(false),
|
|
288
|
+
}),
|
|
289
|
+
z.strictObject({
|
|
290
|
+
...replayOutcomeFacts,
|
|
291
|
+
outcome: z.enum(["timeout", "oom", "crash", "cancelled"]),
|
|
292
|
+
output_sha256: z.null(),
|
|
293
|
+
truncated: z.literal(false),
|
|
294
|
+
}),
|
|
295
|
+
z.strictObject({
|
|
296
|
+
...replayOutcomeFacts,
|
|
297
|
+
outcome: z.literal("protocol_error"),
|
|
298
|
+
output_sha256: z.null(),
|
|
299
|
+
truncated: z.literal(true),
|
|
300
|
+
}),
|
|
301
|
+
]);
|
|
286
302
|
export const replayExecutionResultSchema = z
|
|
287
303
|
.object({
|
|
288
304
|
schema_version: z.literal(1),
|
|
@@ -337,25 +353,25 @@ export const replayExecutionResultSchema = z
|
|
|
337
353
|
export const replayEvidenceSchema = evidenceEnvelopeSchema
|
|
338
354
|
.omit({ normalized_result: true })
|
|
339
355
|
.extend({ normalized_result: replayExecutionResultSchema });
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
phase: z.
|
|
343
|
-
plan: replayPlanSchema
|
|
344
|
-
source_evidence: z
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
.
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
value.source_evidence.length === 0)))
|
|
357
|
-
context.addIssue({
|
|
358
|
-
code: "custom",
|
|
359
|
-
message: "Replay output phase does not match its payload",
|
|
360
|
-
});
|
|
356
|
+
/** A replay plan result with no claimed runtime observation. */
|
|
357
|
+
export const controlledReplayPlanOutputSchema = z.strictObject({
|
|
358
|
+
phase: z.literal("plan"),
|
|
359
|
+
plan: replayPlanSchema,
|
|
360
|
+
source_evidence: z
|
|
361
|
+
.array(replayEvidenceSchema)
|
|
362
|
+
.length(0)
|
|
363
|
+
.brand(),
|
|
364
|
+
evidence: z.null(),
|
|
365
|
+
});
|
|
366
|
+
/** An executed replay result with its required source and aggregate Evidence. */
|
|
367
|
+
export const controlledReplayExecutionOutputSchema = z.strictObject({
|
|
368
|
+
phase: z.literal("execute"),
|
|
369
|
+
plan: z.null(),
|
|
370
|
+
source_evidence: z.array(replayEvidenceSchema).min(1),
|
|
371
|
+
evidence: replayEvidenceSchema,
|
|
361
372
|
});
|
|
373
|
+
/** Parse replay output into its legal plan or execution state. */
|
|
374
|
+
export const controlledReplayOutputSchema = z.discriminatedUnion("phase", [
|
|
375
|
+
controlledReplayPlanOutputSchema,
|
|
376
|
+
controlledReplayExecutionOutputSchema,
|
|
377
|
+
]);
|
|
@@ -83,6 +83,7 @@ export const javascriptRuntimeLocationSchema = z.discriminatedUnion("kind", [
|
|
|
83
83
|
z.strictObject({
|
|
84
84
|
kind: z.literal("file"),
|
|
85
85
|
file_path: z.string().min(1).max(16_384),
|
|
86
|
+
authority: z.literal("scope-fallback").optional(),
|
|
86
87
|
}),
|
|
87
88
|
z.strictObject({
|
|
88
89
|
kind: z.literal("url"),
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { isAbsolute, relative } from "node:path";
|
|
3
|
+
import canonicalize from "canonicalize";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
import { classifyBrowserCompleteness, } from "./browserCompleteness.js";
|
|
6
|
+
import { electronActiveObservationResultSchema, } from "./electronActiveObservation.js";
|
|
7
|
+
/** Parse active Electron Evidence as a bounded, target-only runtime capture. */
|
|
8
|
+
export const parseActiveElectronCapture = (evidence) => {
|
|
9
|
+
assertIdentity(evidence);
|
|
10
|
+
const result = electronActiveObservationResultSchema.parse(evidence.normalized_result);
|
|
11
|
+
const parameters = z
|
|
12
|
+
.object({
|
|
13
|
+
approved: z.literal(true),
|
|
14
|
+
application_path: absolutePathSchema,
|
|
15
|
+
application_root: absolutePathSchema,
|
|
16
|
+
})
|
|
17
|
+
.passthrough()
|
|
18
|
+
.parse(evidence.parameters);
|
|
19
|
+
if (result.application.application_path !== parameters.application_path ||
|
|
20
|
+
!isWithinRoot(parameters.application_root, result.application.application_path))
|
|
21
|
+
throw new TypeError("Active Electron Evidence application path disagrees with its approved root");
|
|
22
|
+
return {
|
|
23
|
+
kind: "electron-active",
|
|
24
|
+
evidence,
|
|
25
|
+
inspection: normalizeInspection(result),
|
|
26
|
+
captureSha256: digestCanonical(result),
|
|
27
|
+
scriptsCompleteWithinScope: false,
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
const absolutePathSchema = z.string().min(1).max(16_384).refine(isAbsolute);
|
|
31
|
+
const assertIdentity = (evidence) => {
|
|
32
|
+
if (evidence.operation !== "capture_electron_scenario" ||
|
|
33
|
+
evidence.predicate_type !== "rea.electron-active-scenario/v1" ||
|
|
34
|
+
evidence.provider.id !== "rea-playwright-electron-active" ||
|
|
35
|
+
evidence.provider.name !==
|
|
36
|
+
"REA Playwright active Electron observation provider" ||
|
|
37
|
+
evidence.provider.version !== "1" ||
|
|
38
|
+
evidence.authority !== "controlled-replay" ||
|
|
39
|
+
evidence.confidence !== "observed")
|
|
40
|
+
throw new TypeError("Evidence does not match the supported capture_electron_scenario contract");
|
|
41
|
+
};
|
|
42
|
+
const normalizeInspection = (result) => ({
|
|
43
|
+
target: {
|
|
44
|
+
target_id: `electron-active:${digestCanonical(result.application.application_path).slice(0, 32)}`,
|
|
45
|
+
type: "electron-application",
|
|
46
|
+
title: result.application.application_path,
|
|
47
|
+
attached: true,
|
|
48
|
+
file_path: result.application.application_path,
|
|
49
|
+
},
|
|
50
|
+
frames: [],
|
|
51
|
+
scripts: { items: [] },
|
|
52
|
+
workers: [],
|
|
53
|
+
completeness: classifyBrowserCompleteness({
|
|
54
|
+
policyFilteredSections: new Set(),
|
|
55
|
+
attachLimitedSections: new Set(),
|
|
56
|
+
truncatedSections: new Set(result.windows_truncated ||
|
|
57
|
+
result.processes.truncated ||
|
|
58
|
+
result.ipc.truncated ||
|
|
59
|
+
result.timeline.truncated
|
|
60
|
+
? ["timeline"]
|
|
61
|
+
: []),
|
|
62
|
+
unavailableSections: new Set([
|
|
63
|
+
"frames",
|
|
64
|
+
"scripts",
|
|
65
|
+
"script_sources",
|
|
66
|
+
"workers",
|
|
67
|
+
]),
|
|
68
|
+
excluded: [],
|
|
69
|
+
droppedEvents: {
|
|
70
|
+
scripts: 0,
|
|
71
|
+
network_requests: 0,
|
|
72
|
+
console_events: 0,
|
|
73
|
+
websocket_connections: 0,
|
|
74
|
+
websocket_frames: 0,
|
|
75
|
+
webmcp_tools: 0,
|
|
76
|
+
timeline_events: result.timeline.truncated ? result.timeline.observed : 0,
|
|
77
|
+
},
|
|
78
|
+
}),
|
|
79
|
+
});
|
|
80
|
+
const digestCanonical = (value) => {
|
|
81
|
+
const encoded = canonicalize(value);
|
|
82
|
+
if (encoded === undefined)
|
|
83
|
+
throw new TypeError("Runtime reconciliation could not canonicalize input");
|
|
84
|
+
return createHash("sha256").update(encoded).digest("hex");
|
|
85
|
+
};
|
|
86
|
+
const isWithinRoot = (root, path) => {
|
|
87
|
+
const remainder = relative(root, path);
|
|
88
|
+
return (remainder === "" || (!remainder.startsWith("..") && !isAbsolute(remainder)));
|
|
89
|
+
};
|
|
@@ -24,7 +24,7 @@ export const buildReconciledApplicationGraph = (input) => {
|
|
|
24
24
|
"Runtime presence is bounded to passive capture windows and does not prove feature execution.",
|
|
25
25
|
"Cross-layer observed_as edges are inferences; digest equality proves byte identity only.",
|
|
26
26
|
"Source-map relationships retain their original static authority and are not promoted into runtime matches.",
|
|
27
|
-
...(facts.
|
|
27
|
+
...(facts.inputStatus === "truncated"
|
|
28
28
|
? [
|
|
29
29
|
"One or more source graphs or passive captures were incomplete or truncated.",
|
|
30
30
|
]
|
|
@@ -83,6 +83,8 @@ const graphCoverageFacts = (input, omittedNodeObservations) => {
|
|
|
83
83
|
const captureHasUnknownOmissions = input.captures.some(({ inspection }) => inspection.completeness.unavailable_sections.length > 0);
|
|
84
84
|
const inputTruncated = input.layers.some(({ graph }) => graph.coverage.truncated) ||
|
|
85
85
|
captureTruncated;
|
|
86
|
+
const inputComplete = input.layers.every(({ graph }) => graph.coverage.status === "complete") &&
|
|
87
|
+
input.captures.every(({ inspection }) => inspection.completeness.status === "complete_within_window");
|
|
86
88
|
const outputTruncated = projectionOmissions > 0;
|
|
87
89
|
const sourceOmissions = input.layers.reduce((total, { graph }) => total + (graph.coverage.omitted_count ?? 0), 0);
|
|
88
90
|
const omissionsKnown = !captureTruncated &&
|
|
@@ -92,24 +94,23 @@ const graphCoverageFacts = (input, omittedNodeObservations) => {
|
|
|
92
94
|
projectionOmissions,
|
|
93
95
|
knownOmissions: projectionOmissions + sourceOmissions,
|
|
94
96
|
omissionsKnown,
|
|
95
|
-
inputTruncated
|
|
97
|
+
inputStatus: inputTruncated
|
|
98
|
+
? "truncated"
|
|
99
|
+
: inputComplete
|
|
100
|
+
? "complete"
|
|
101
|
+
: "partial",
|
|
96
102
|
outputTruncated,
|
|
97
|
-
truncated: inputTruncated || outputTruncated,
|
|
98
|
-
complete: !inputTruncated &&
|
|
99
|
-
!outputTruncated &&
|
|
100
|
-
input.layers.every(({ graph }) => graph.coverage.status === "complete") &&
|
|
101
|
-
input.captures.every(({ inspection }) => inspection.completeness.status === "complete_within_window"),
|
|
102
103
|
};
|
|
103
104
|
};
|
|
104
|
-
const graphCoverage = (input, facts, nodeCount) => facts.complete
|
|
105
|
+
const graphCoverage = (input, facts, nodeCount) => facts.inputStatus === "complete" && !facts.outputTruncated
|
|
105
106
|
? { status: "complete", truncated: false, omitted_count: 0, limits: [] }
|
|
106
|
-
: facts.truncated
|
|
107
|
+
: facts.inputStatus === "truncated" || facts.outputTruncated
|
|
107
108
|
? {
|
|
108
109
|
status: "partial",
|
|
109
110
|
truncated: true,
|
|
110
111
|
omitted_count: facts.omissionsKnown ? facts.knownOmissions : null,
|
|
111
112
|
limits: [
|
|
112
|
-
...(facts.
|
|
113
|
+
...(facts.inputStatus === "truncated"
|
|
113
114
|
? [
|
|
114
115
|
{
|
|
115
116
|
name: "runtime-reconciliation-input-coverage",
|