rea-agents 2.5.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 +20 -12
- package/bridge/ghidra/ReaGhidraBridge.java +477 -4
- package/bridge/hopper_bridge.py +54 -4
- package/dist/application/AnalysisContextQueries.js +142 -0
- package/dist/application/AnalysisSnapshotCache.js +4 -2
- 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 +19 -20
- package/dist/application/BinarySessionComposition.js +21 -0
- package/dist/application/BinarySessionRecords.js +106 -10
- 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 +140 -55
- package/dist/application/ClientRegistrationStatus.js +4 -1
- package/dist/application/CrossVersionInventory.js +7 -6
- package/dist/application/DirectAnalysis.js +6 -2
- 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 +49 -17
- package/dist/application/EvidenceBundleCommands.js +5 -1
- package/dist/application/EvidenceLedger.js +53 -17
- package/dist/application/JavaScriptArtifactAnalysis.js +13 -4
- package/dist/application/JavaScriptReplayPermission.js +1 -1
- package/dist/application/JavaScriptReplayService.js +23 -15
- package/dist/application/LazyAnalysisProvider.js +77 -0
- package/dist/application/LoopbackReplay.js +1 -1
- package/dist/application/ManagedRuntimeCorrelationService.js +9 -5
- package/dist/application/NativeApiInspection.js +80 -0
- 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/SessionProviderRouter.js +6 -6
- package/dist/application/SetupClientConfiguration.js +10 -3
- package/dist/application/WindowsCapabilities.js +5 -4
- package/dist/application/runtime.js +26 -9
- 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/PlaywrightBrowserScenarioProvider.js +8 -2
- 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 +15 -9
- package/dist/cli/artifactCommands.js +5 -3
- package/dist/cli/coreAnalysisCommands.js +41 -0
- 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 +2 -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 +35 -37
- package/dist/contracts/browserToolContracts.js +2 -2
- package/dist/contracts/electronToolContracts.js +30 -1
- package/dist/contracts/enhancedInputs.js +21 -27
- package/dist/contracts/functionWorkflowToolContracts.js +29 -0
- 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/promptContracts.js +14 -15
- package/dist/contracts/sessionToolSchemas.js +61 -0
- package/dist/contracts/toolContractExamples.js +4 -0
- package/dist/contracts/toolContractHelpers.js +23 -0
- package/dist/contracts/toolContracts.js +12 -67
- package/dist/contracts/toolEffects.js +19 -0
- package/dist/contracts/toolOutputSchemaGroups.js +66 -11
- package/dist/contracts/toolOutputSchemaPrimitives.js +76 -26
- package/dist/contracts/toolSchemaMetadata.js +128 -0
- package/dist/doctorRuntime.js +1 -1
- package/dist/domain/analysisErrorPresentation.js +8 -2
- package/dist/domain/analysisErrorProjection.js +1 -0
- 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 +177 -0
- package/dist/domain/callPath.js +3 -2
- package/dist/domain/conformancePackage.js +169 -0
- package/dist/domain/conformanceReplay.js +104 -0
- package/dist/domain/conformanceTrustGate.js +328 -0
- package/dist/domain/customProtocolCapture.js +137 -0
- 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 +217 -0
- package/dist/domain/evidenceBundle.js +47 -0
- package/dist/domain/functionComparisonNormalization.js +15 -8
- package/dist/domain/functionDossierEvidence.js +9 -4
- package/dist/domain/hopperStartupFailure.js +1 -1
- package/dist/domain/hopperValues.js +68 -68
- package/dist/domain/inputIssueProjection.js +11 -2
- 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/javascriptSemanticAnalysis.js +8 -12
- package/dist/domain/javascriptSourceParser.js +15 -0
- package/dist/domain/javascriptStaticAnalysis.js +8 -12
- package/dist/domain/knownPageCoverage.js +15 -7
- package/dist/domain/mobileApplicationInvestigation.js +159 -0
- package/dist/domain/nativeApiBoundary.js +138 -0
- package/dist/domain/nodeRuntimeCharacterization.js +14 -13
- package/dist/domain/objcSwiftMetadata.js +150 -0
- package/dist/domain/packageAnalysis.js +123 -0
- package/dist/domain/peInspection.js +196 -0
- 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 +245 -0
- 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/dotnet/ManagedStaticProvider.js +34 -5
- package/dist/generatedMcpToolCatalog.js +37 -0
- package/dist/generatedPackageMetadata.js +4 -4
- package/dist/ghidra/GhidraClient.js +1 -1
- package/dist/ghidra/GhidraClientStartup.js +1 -1
- package/dist/ghidra/GhidraDefaults.js +1 -1
- package/dist/ghidra/GhidraFunctionValues.js +44 -16
- package/dist/ghidra/GhidraInventoryValues.js +57 -47
- package/dist/ghidra/GhidraProvider.js +18 -10
- package/dist/ghidra/GhidraProviderCapabilities.js +45 -39
- 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 +27 -3
- package/dist/hopper/HopperProvider.js +42 -44
- package/dist/hopper/HopperRequestQueue.js +32 -4
- package/dist/hopper/HopperResponseStream.js +2 -2
- package/dist/hopper/LinuxPrivateDisplayProbe.js +16 -10
- package/dist/hopper/protocol.js +63 -21
- package/dist/main/reload.js +1 -6
- package/dist/main/state.js +0 -14
- package/dist/main/transport.js +31 -41
- package/dist/main.js +17 -13
- package/dist/mcpDoctor.js +4 -26
- package/dist/mcpStartupPolicy.js +14 -0
- 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 +101 -144
- 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 +124 -122
- package/dist/server/registerEvidenceResources.js +50 -101
- package/dist/server/registerEvidenceTools.js +5 -9
- package/dist/server/registerFunctionComparisonTool.js +11 -15
- package/dist/server/registerInvestigationTools.js +42 -59
- package/dist/server/registerJavaScriptApplicationGraphResource.js +0 -4
- 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/registerReconstructionObligationLedgerResource.js +0 -7
- package/dist/server/registerReconstructionReadinessResource.js +0 -7
- package/dist/server/registerReplayMachineTool.js +4 -10
- package/dist/server/registerSessionRecordTools.js +146 -47
- package/dist/server/registerSessionStatusTool.js +14 -29
- package/dist/server/registerSessionTools.js +45 -41
- package/dist/server/sessionAvailabilityPolicy.js +2 -1
- package/dist/server/sessionToolPolicies.js +1 -5
- package/dist/server/toolRegistrationOptions.js +4 -177
- package/dist/server/toolResult.js +14 -18
- package/package.json +35 -16
- package/scripts/electron-active-hook-boundaries.cjs +394 -0
- package/scripts/electron-active-hook.cjs +501 -0
- package/skills/reverse-engineer-anything/SKILL.md +10 -3
- package/dist/server/DynamicToolAvailability.js +0 -70
- package/dist/server/toolInputValidation.js +0 -77
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { AnalysisOutputError, HopperProtocolError } from "./errors.js";
|
|
3
3
|
import { err, ok } from "./result.js";
|
|
4
|
+
import { nativeApiBoundarySchema } from "./nativeApiBoundary.js";
|
|
4
5
|
/** Return a bounded byte distance between canonical addresses in one space. */
|
|
5
6
|
export const addressDistance = (start, end) => {
|
|
6
7
|
const left = addressCoordinate(start);
|
|
@@ -33,31 +34,24 @@ const segmentSchema = z.object({
|
|
|
33
34
|
writable: z.boolean().nullable().default(null),
|
|
34
35
|
executable: z.boolean().nullable().default(null),
|
|
35
36
|
});
|
|
36
|
-
const
|
|
37
|
-
.object({
|
|
37
|
+
const addressedPageFacts = {
|
|
38
38
|
items: z.array(z.object({ address: z.string(), value: z.string() })),
|
|
39
39
|
offset: z.number().int().min(0),
|
|
40
40
|
limit: z.number().int().min(1),
|
|
41
41
|
total: z.number().int().min(0),
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
code: "custom",
|
|
56
|
-
message: "a complete page must not provide next_offset",
|
|
57
|
-
path: ["next_offset"],
|
|
58
|
-
});
|
|
59
|
-
}
|
|
60
|
-
});
|
|
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
|
+
]);
|
|
61
55
|
const unavailableAnalysisFactSchema = z
|
|
62
56
|
.object({ available: z.literal(false), reason: z.string() })
|
|
63
57
|
.strict();
|
|
@@ -82,38 +76,42 @@ export const localVariableSchema = z
|
|
|
82
76
|
provenance: z.string().min(1),
|
|
83
77
|
})
|
|
84
78
|
.strict();
|
|
85
|
-
const boundedSchema = (item) =>
|
|
86
|
-
|
|
87
|
-
|
|
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
|
-
|
|
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
|
+
};
|
|
117
115
|
/** Provider-neutral bounded raw-instruction window for one analyzed function. */
|
|
118
116
|
export const functionInstructionWindowSchema = z
|
|
119
117
|
.object({
|
|
@@ -169,14 +167,22 @@ export const functionDossierSchema = z
|
|
|
169
167
|
})
|
|
170
168
|
.strict(),
|
|
171
169
|
pseudocode: z
|
|
172
|
-
.
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
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
|
+
])
|
|
180
186
|
.superRefine((value, context) => {
|
|
181
187
|
if (value.returned_chars !== [...value.text].length) {
|
|
182
188
|
context.addIssue({
|
|
@@ -192,13 +198,6 @@ export const functionDossierSchema = z
|
|
|
192
198
|
path: ["total_chars"],
|
|
193
199
|
});
|
|
194
200
|
}
|
|
195
|
-
if (value.next_offset !== null && !value.truncated) {
|
|
196
|
-
context.addIssue({
|
|
197
|
-
code: "custom",
|
|
198
|
-
message: "a continuation requires truncated pseudocode",
|
|
199
|
-
path: ["next_offset"],
|
|
200
|
-
});
|
|
201
|
-
}
|
|
202
201
|
}),
|
|
203
202
|
assembly: boundedSchema(z.string()),
|
|
204
203
|
comments: boundedSchema(z
|
|
@@ -236,6 +235,7 @@ export const functionDossierSchema = z
|
|
|
236
235
|
instruction_scan: z
|
|
237
236
|
.object({ scanned: z.number().int().min(0), truncated: z.boolean() })
|
|
238
237
|
.strict(),
|
|
238
|
+
native_api: nativeApiBoundarySchema.nullable().default(null),
|
|
239
239
|
limitations: z.array(z.string()).default([]),
|
|
240
240
|
})
|
|
241
241
|
.strict();
|
|
@@ -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],
|
|
@@ -31,14 +33,21 @@ const projectIssue = (issue, input) => {
|
|
|
31
33
|
expected: issue.values.filter(isSafeExpected),
|
|
32
34
|
},
|
|
33
35
|
];
|
|
34
|
-
return [
|
|
36
|
+
return [
|
|
37
|
+
{
|
|
38
|
+
path,
|
|
39
|
+
reason: "invalid_value",
|
|
40
|
+
...(issue.message.length > 0 ? { message: issue.message } : {}),
|
|
41
|
+
},
|
|
42
|
+
];
|
|
35
43
|
};
|
|
36
44
|
const valueAtPath = (input, path) => {
|
|
37
45
|
let current = input;
|
|
38
46
|
for (const part of path) {
|
|
39
47
|
if (typeof current !== "object" || current === null)
|
|
40
48
|
return undefined;
|
|
41
|
-
|
|
49
|
+
const next = Reflect.get(current, part);
|
|
50
|
+
current = next;
|
|
42
51
|
}
|
|
43
52
|
return current;
|
|
44
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",
|