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
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
import { isAbsolute } from "node:path";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
const absolutePathSchema = z
|
|
4
|
+
.string()
|
|
5
|
+
.min(1)
|
|
6
|
+
.max(16_384)
|
|
7
|
+
.refine(isAbsolute, "path must be absolute");
|
|
8
|
+
const windowIndexSchema = z.number().int().min(0).max(99);
|
|
9
|
+
const deepLinkUrlSchema = z
|
|
10
|
+
.string()
|
|
11
|
+
.min(1)
|
|
12
|
+
.max(4_096)
|
|
13
|
+
.refine((value) => {
|
|
14
|
+
try {
|
|
15
|
+
return new URL(value).protocol.length > 0;
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
}, "deep-link url must be an absolute URL");
|
|
21
|
+
const actionSchema = z.discriminatedUnion("kind", [
|
|
22
|
+
z.strictObject({
|
|
23
|
+
step_id: z.string().min(1).max(128),
|
|
24
|
+
kind: z.literal("click"),
|
|
25
|
+
selector: z.string().min(1).max(512),
|
|
26
|
+
window_index: windowIndexSchema.default(0),
|
|
27
|
+
}),
|
|
28
|
+
z.strictObject({
|
|
29
|
+
step_id: z.string().min(1).max(128),
|
|
30
|
+
kind: z.literal("wait"),
|
|
31
|
+
duration_ms: z.number().int().min(0).max(10_000),
|
|
32
|
+
window_index: windowIndexSchema.optional(),
|
|
33
|
+
}),
|
|
34
|
+
z.strictObject({
|
|
35
|
+
step_id: z.string().min(1).max(128),
|
|
36
|
+
kind: z.literal("renderer-reload"),
|
|
37
|
+
window_index: windowIndexSchema.default(0),
|
|
38
|
+
}),
|
|
39
|
+
z.strictObject({
|
|
40
|
+
step_id: z.string().min(1).max(128),
|
|
41
|
+
kind: z.literal("renderer-crash"),
|
|
42
|
+
window_index: windowIndexSchema.default(0),
|
|
43
|
+
}),
|
|
44
|
+
z.strictObject({
|
|
45
|
+
step_id: z.string().min(1).max(128),
|
|
46
|
+
kind: z.literal("deep-link"),
|
|
47
|
+
delivery: z.enum(["open-url", "second-instance"]),
|
|
48
|
+
url: deepLinkUrlSchema,
|
|
49
|
+
}),
|
|
50
|
+
]);
|
|
51
|
+
const limitsSchema = z.strictObject({
|
|
52
|
+
max_duration_ms: z.number().int().min(1).max(120_000).default(60_000),
|
|
53
|
+
action_timeout_ms: z.number().int().min(1).max(30_000).default(5_000),
|
|
54
|
+
max_actions: z.number().int().min(1).max(100).default(20),
|
|
55
|
+
max_ipc_events: z.number().int().min(1).max(10_000).default(2_000),
|
|
56
|
+
max_runtime_events: z.number().int().min(1).max(20_000).default(5_000),
|
|
57
|
+
max_processes: z.number().int().min(1).max(100).default(32),
|
|
58
|
+
max_windows: z.number().int().min(1).max(100).default(32),
|
|
59
|
+
});
|
|
60
|
+
/** Input for one explicit, provider-owned Electron runtime experiment. */
|
|
61
|
+
export const electronActiveObservationInputSchema = z
|
|
62
|
+
.strictObject({
|
|
63
|
+
schema_version: z.literal(1),
|
|
64
|
+
executable_path: absolutePathSchema,
|
|
65
|
+
application_path: absolutePathSchema,
|
|
66
|
+
application_root: absolutePathSchema,
|
|
67
|
+
args: z.array(z.string().max(4_096)).max(32).default([]),
|
|
68
|
+
actions: z.array(actionSchema).max(100).default([]),
|
|
69
|
+
limits: limitsSchema.default({
|
|
70
|
+
max_duration_ms: 60_000,
|
|
71
|
+
action_timeout_ms: 5_000,
|
|
72
|
+
max_actions: 20,
|
|
73
|
+
max_ipc_events: 2_000,
|
|
74
|
+
max_runtime_events: 5_000,
|
|
75
|
+
max_processes: 32,
|
|
76
|
+
max_windows: 32,
|
|
77
|
+
}),
|
|
78
|
+
approved: z.literal(true),
|
|
79
|
+
})
|
|
80
|
+
.superRefine((input, context) => {
|
|
81
|
+
if (input.actions.length > input.limits.max_actions)
|
|
82
|
+
context.addIssue({
|
|
83
|
+
code: "custom",
|
|
84
|
+
path: ["actions"],
|
|
85
|
+
message: "actions exceed the configured max_actions limit",
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
const ipcEventSchema = z.strictObject({
|
|
89
|
+
sequence: z.number().int().min(1),
|
|
90
|
+
correlation_id: z.string().max(256).nullable().default(null),
|
|
91
|
+
kind: z.enum([
|
|
92
|
+
"main-handler-invocation",
|
|
93
|
+
"main-event-invocation",
|
|
94
|
+
"utility-process-fork",
|
|
95
|
+
"utility-process-message",
|
|
96
|
+
"ipc-main-to-renderer",
|
|
97
|
+
"ipc-utility-to-main",
|
|
98
|
+
"ipc-renderer-send",
|
|
99
|
+
"ipc-renderer-invoke",
|
|
100
|
+
"ipc-renderer-post-message",
|
|
101
|
+
]),
|
|
102
|
+
event: z.string().max(128).nullable().optional(),
|
|
103
|
+
phase: z
|
|
104
|
+
.enum(["attempted", "completed", "blocked", "failed", "observed"])
|
|
105
|
+
.nullable()
|
|
106
|
+
.optional(),
|
|
107
|
+
channel: z.string().max(1_024).nullable(),
|
|
108
|
+
channel_truncated: z.boolean().default(false),
|
|
109
|
+
direction: z
|
|
110
|
+
.enum([
|
|
111
|
+
"renderer-to-main",
|
|
112
|
+
"main-to-renderer",
|
|
113
|
+
"main-to-utility",
|
|
114
|
+
"utility-to-main",
|
|
115
|
+
])
|
|
116
|
+
.nullable()
|
|
117
|
+
.optional(),
|
|
118
|
+
sender: z.string().max(256).nullable().optional(),
|
|
119
|
+
receiver: z.string().max(256).nullable().optional(),
|
|
120
|
+
frame: z.string().max(256).nullable().default(null),
|
|
121
|
+
target: z.string().max(256).nullable().optional(),
|
|
122
|
+
argument_shapes: z.array(z.string().max(64)).max(32),
|
|
123
|
+
argument_shapes_truncated: z.boolean().default(false),
|
|
124
|
+
result_shape: z.string().max(64).nullable(),
|
|
125
|
+
process_type: z.string().max(128).nullable(),
|
|
126
|
+
source: z.string().max(64).default("electron-active-hook"),
|
|
127
|
+
capture_method: z
|
|
128
|
+
.enum(["api-wrapper", "event-emitter", "process-hook"])
|
|
129
|
+
.default("api-wrapper"),
|
|
130
|
+
artifact_path: z.string().max(16_384).nullable().default(null),
|
|
131
|
+
artifact_sha256: z
|
|
132
|
+
.string()
|
|
133
|
+
.regex(/^[a-f0-9]{64}$/u)
|
|
134
|
+
.nullable()
|
|
135
|
+
.default(null),
|
|
136
|
+
error: z.boolean(),
|
|
137
|
+
});
|
|
138
|
+
const timelineEventSchema = z.strictObject({
|
|
139
|
+
sequence: z.number().int().min(1),
|
|
140
|
+
correlation_id: z.string().max(256).nullable().default(null),
|
|
141
|
+
kind: z.enum([
|
|
142
|
+
"main-handler-invocation",
|
|
143
|
+
"main-event-invocation",
|
|
144
|
+
"utility-process-fork",
|
|
145
|
+
"utility-process-message",
|
|
146
|
+
"ipc-main-to-renderer",
|
|
147
|
+
"ipc-utility-to-main",
|
|
148
|
+
"ipc-renderer-send",
|
|
149
|
+
"ipc-renderer-invoke",
|
|
150
|
+
"ipc-renderer-post-message",
|
|
151
|
+
"app-lifecycle",
|
|
152
|
+
"window-lifecycle",
|
|
153
|
+
"web-contents-lifecycle",
|
|
154
|
+
"navigation",
|
|
155
|
+
"shell-attempt",
|
|
156
|
+
"process-lifecycle",
|
|
157
|
+
"permission",
|
|
158
|
+
"popup-attempt",
|
|
159
|
+
"download",
|
|
160
|
+
"protocol",
|
|
161
|
+
"preload",
|
|
162
|
+
"native-addon",
|
|
163
|
+
"updater",
|
|
164
|
+
"error",
|
|
165
|
+
]),
|
|
166
|
+
event: z.string().max(128).nullable(),
|
|
167
|
+
phase: z.enum(["attempted", "completed", "blocked", "failed", "observed"]),
|
|
168
|
+
channel: z.string().max(1_024).nullable(),
|
|
169
|
+
channel_truncated: z.boolean(),
|
|
170
|
+
direction: z
|
|
171
|
+
.enum([
|
|
172
|
+
"renderer-to-main",
|
|
173
|
+
"main-to-renderer",
|
|
174
|
+
"main-to-utility",
|
|
175
|
+
"utility-to-main",
|
|
176
|
+
])
|
|
177
|
+
.nullable(),
|
|
178
|
+
sender: z.string().max(256).nullable(),
|
|
179
|
+
receiver: z.string().max(256).nullable(),
|
|
180
|
+
frame: z.string().max(256).nullable(),
|
|
181
|
+
target: z.string().max(256).nullable(),
|
|
182
|
+
argument_shapes: z.array(z.string().max(64)).max(32),
|
|
183
|
+
argument_shapes_truncated: z.boolean(),
|
|
184
|
+
result_shape: z.string().max(64).nullable(),
|
|
185
|
+
process_type: z.string().max(128).nullable(),
|
|
186
|
+
source: z.string().max(64),
|
|
187
|
+
capture_method: z.enum(["api-wrapper", "event-emitter", "process-hook"]),
|
|
188
|
+
artifact_path: z.string().max(16_384).nullable(),
|
|
189
|
+
artifact_sha256: z
|
|
190
|
+
.string()
|
|
191
|
+
.regex(/^[a-f0-9]{64}$/u)
|
|
192
|
+
.nullable(),
|
|
193
|
+
error: z.boolean(),
|
|
194
|
+
});
|
|
195
|
+
const processMetricSchema = z.strictObject({
|
|
196
|
+
pid: z.number().int().min(1),
|
|
197
|
+
type: z.string().min(1).max(128),
|
|
198
|
+
name: z.string().max(256).nullable(),
|
|
199
|
+
service_name: z.string().max(256).nullable(),
|
|
200
|
+
});
|
|
201
|
+
const windowResultSchema = z.strictObject({
|
|
202
|
+
window_id: z.string().max(256),
|
|
203
|
+
web_contents_id: z.string().max(256),
|
|
204
|
+
url: z.string().max(65_536),
|
|
205
|
+
title: z.string().max(16_384),
|
|
206
|
+
visible: z.boolean().nullable(),
|
|
207
|
+
destroyed: z.boolean(),
|
|
208
|
+
});
|
|
209
|
+
const coverageSchema = z.strictObject({
|
|
210
|
+
status: z.enum([
|
|
211
|
+
"complete",
|
|
212
|
+
"partial_attach",
|
|
213
|
+
"capture_truncated",
|
|
214
|
+
"hook_conflict",
|
|
215
|
+
"target_exited",
|
|
216
|
+
"cleanup_failed",
|
|
217
|
+
]),
|
|
218
|
+
observed_event_families: z.array(z.string().max(128)).max(32),
|
|
219
|
+
unavailable_event_families: z.array(z.string().max(128)).max(32),
|
|
220
|
+
observed_roles: z.array(z.string().max(128)).max(16),
|
|
221
|
+
pre_capture_activity: z.literal("unavailable"),
|
|
222
|
+
});
|
|
223
|
+
const actionResultSchema = z.strictObject({
|
|
224
|
+
step_id: z.string().min(1).max(128),
|
|
225
|
+
kind: z.enum([
|
|
226
|
+
"click",
|
|
227
|
+
"wait",
|
|
228
|
+
"renderer-reload",
|
|
229
|
+
"renderer-crash",
|
|
230
|
+
"deep-link",
|
|
231
|
+
]),
|
|
232
|
+
window_index: windowIndexSchema.nullable(),
|
|
233
|
+
target: z.string().max(256).nullable(),
|
|
234
|
+
status: z.enum(["completed", "failed", "cancelled"]),
|
|
235
|
+
elapsed_ms: z.number().int().min(0),
|
|
236
|
+
error: z.string().nullable(),
|
|
237
|
+
});
|
|
238
|
+
/** Bounded result of a provider-owned Electron runtime experiment. */
|
|
239
|
+
export const electronActiveObservationResultSchema = z.strictObject({
|
|
240
|
+
schema_version: z.literal(1),
|
|
241
|
+
application: z.strictObject({
|
|
242
|
+
executable_path: absolutePathSchema,
|
|
243
|
+
application_path: absolutePathSchema,
|
|
244
|
+
electron_version: z.string().min(1).max(256),
|
|
245
|
+
process_ownership: z.literal("provider-owned"),
|
|
246
|
+
cleanup: z.literal("terminated-owned-process"),
|
|
247
|
+
}),
|
|
248
|
+
actions: z.array(actionResultSchema).max(100),
|
|
249
|
+
windows: z.array(windowResultSchema).max(100),
|
|
250
|
+
windows_truncated: z.boolean(),
|
|
251
|
+
processes: z.strictObject({
|
|
252
|
+
items: z.array(processMetricSchema).max(100),
|
|
253
|
+
truncated: z.boolean(),
|
|
254
|
+
}),
|
|
255
|
+
ipc: z.strictObject({
|
|
256
|
+
events: z.array(ipcEventSchema).max(10_000),
|
|
257
|
+
observed: z.number().int().min(0),
|
|
258
|
+
retained: z.number().int().min(0),
|
|
259
|
+
truncated: z.boolean(),
|
|
260
|
+
}),
|
|
261
|
+
timeline: z
|
|
262
|
+
.strictObject({
|
|
263
|
+
events: z.array(timelineEventSchema).max(20_000),
|
|
264
|
+
observed: z.number().int().min(0),
|
|
265
|
+
retained: z.number().int().min(0),
|
|
266
|
+
truncated: z.boolean(),
|
|
267
|
+
})
|
|
268
|
+
.default({ events: [], observed: 0, retained: 0, truncated: false }),
|
|
269
|
+
coverage: coverageSchema.default({
|
|
270
|
+
status: "partial_attach",
|
|
271
|
+
observed_event_families: [],
|
|
272
|
+
unavailable_event_families: [],
|
|
273
|
+
observed_roles: [],
|
|
274
|
+
pre_capture_activity: "unavailable",
|
|
275
|
+
}),
|
|
276
|
+
limitations: z.array(z.string().max(4_096)).max(100),
|
|
277
|
+
});
|
|
@@ -25,13 +25,10 @@ export const listElectronTargetsInputSchema = z.object({
|
|
|
25
25
|
limit: z.number().int().min(1).max(200).default(100),
|
|
26
26
|
});
|
|
27
27
|
/** Input for passive structural inspection of one Electron file page. */
|
|
28
|
-
|
|
29
|
-
.object({
|
|
28
|
+
const inspectElectronPageFacts = {
|
|
30
29
|
...approvedElectronInput,
|
|
31
30
|
target_id: z.string().trim().min(1).max(256),
|
|
32
31
|
observation_ms: z.number().int().min(0).max(10_000).default(100),
|
|
33
|
-
include_script_sources: z.boolean().default(false),
|
|
34
|
-
source_capture_approved: z.boolean().default(false),
|
|
35
32
|
limits: z
|
|
36
33
|
.object({
|
|
37
34
|
max_frames: z.number().int().min(1).max(1_000).default(200),
|
|
@@ -61,14 +58,21 @@ export const inspectElectronPageInputSchema = z
|
|
|
61
58
|
max_script_source_bytes: 1_024 * 1_024,
|
|
62
59
|
max_total_script_source_bytes: 4 * 1_024 * 1_024,
|
|
63
60
|
}),
|
|
64
|
-
}
|
|
61
|
+
};
|
|
62
|
+
export const inspectElectronPageInputSchema = z
|
|
63
|
+
.union([
|
|
64
|
+
z.object({
|
|
65
|
+
...inspectElectronPageFacts,
|
|
66
|
+
include_script_sources: z.literal(false).default(false),
|
|
67
|
+
source_capture_approved: z.literal(false).default(false),
|
|
68
|
+
}),
|
|
69
|
+
z.object({
|
|
70
|
+
...inspectElectronPageFacts,
|
|
71
|
+
include_script_sources: z.literal(true),
|
|
72
|
+
source_capture_approved: z.literal(true),
|
|
73
|
+
}),
|
|
74
|
+
])
|
|
65
75
|
.superRefine((input, context) => {
|
|
66
|
-
if (input.include_script_sources && !input.source_capture_approved)
|
|
67
|
-
context.addIssue({
|
|
68
|
-
code: "custom",
|
|
69
|
-
path: ["source_capture_approved"],
|
|
70
|
-
message: "Electron script source capture requires separate approval",
|
|
71
|
-
});
|
|
72
76
|
if (input.limits.max_script_source_bytes >
|
|
73
77
|
input.limits.max_total_script_source_bytes)
|
|
74
78
|
context.addIssue({
|
|
@@ -51,7 +51,10 @@ export const collectContextBridgeMembers = (node, maximum = 128) => {
|
|
|
51
51
|
unknown: 1,
|
|
52
52
|
omitted: 0,
|
|
53
53
|
};
|
|
54
|
-
const state = {
|
|
54
|
+
const state = {
|
|
55
|
+
members: [],
|
|
56
|
+
unknown: 0,
|
|
57
|
+
};
|
|
55
58
|
collectMembersAt(node, "", 0, state);
|
|
56
59
|
const members = [...new Set(state.members)].sort(compareCodePoints);
|
|
57
60
|
return {
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/** Event types for event-backed process-tree capture. */
|
|
3
|
+
export const processEventTypeSchema = z.enum([
|
|
4
|
+
"spawn",
|
|
5
|
+
"exit",
|
|
6
|
+
"re_exec",
|
|
7
|
+
"reparent",
|
|
8
|
+
"signal",
|
|
9
|
+
"name_change",
|
|
10
|
+
"thread_create",
|
|
11
|
+
"thread_exit",
|
|
12
|
+
]);
|
|
13
|
+
/** A single event-backed process-tree event. */
|
|
14
|
+
export const processTreeEventSchema = z.strictObject({
|
|
15
|
+
/** Monotonic event sequence number. */
|
|
16
|
+
sequence: z.number().int().nonnegative(),
|
|
17
|
+
/** Event timestamp in milliseconds. */
|
|
18
|
+
at_ms: z.number().int().nonnegative(),
|
|
19
|
+
/** Event type. */
|
|
20
|
+
type: processEventTypeSchema,
|
|
21
|
+
/** Process ID. */
|
|
22
|
+
pid: z.number().int().positive(),
|
|
23
|
+
/** Parent process ID. */
|
|
24
|
+
ppid: z.number().int().nullable(),
|
|
25
|
+
/** Process name if known. */
|
|
26
|
+
process_name: z.string().nullable(),
|
|
27
|
+
/** Executable path if known. */
|
|
28
|
+
executable: z.string().nullable(),
|
|
29
|
+
/** Command line arguments. */
|
|
30
|
+
arguments: z.array(z.string()).default([]),
|
|
31
|
+
/** Previous PID (for reparent events). */
|
|
32
|
+
previous_pid: z.number().int().nullable(),
|
|
33
|
+
/** Previous PPID (for reparent events). */
|
|
34
|
+
previous_ppid: z.number().int().nullable(),
|
|
35
|
+
/** Exit code (for exit events). */
|
|
36
|
+
exit_code: z.number().int().nullable(),
|
|
37
|
+
/** Signal number (for signal events). */
|
|
38
|
+
signal: z.number().int().nullable(),
|
|
39
|
+
/** Thread ID (for thread events). */
|
|
40
|
+
tid: z.number().int().nullable(),
|
|
41
|
+
});
|
|
42
|
+
/** Process node in a reconstructed tree. */
|
|
43
|
+
export const processNodeSchema = z.strictObject({
|
|
44
|
+
pid: z.number().int().positive(),
|
|
45
|
+
ppid: z.number().int().nullable(),
|
|
46
|
+
process_name: z.string().nullable(),
|
|
47
|
+
executable: z.string().nullable(),
|
|
48
|
+
arguments: z.array(z.string()).default([]),
|
|
49
|
+
children: z.array(z.number().int()).default([]),
|
|
50
|
+
spawn_time_ms: z.number().int().nullable(),
|
|
51
|
+
exit_time_ms: z.number().int().nullable(),
|
|
52
|
+
exit_code: z.number().int().nullable(),
|
|
53
|
+
is_re_exec: z.boolean().default(false),
|
|
54
|
+
is_reparented: z.boolean().default(false),
|
|
55
|
+
previous_ppid: z.number().int().nullable(),
|
|
56
|
+
});
|
|
57
|
+
/** Result of event-backed process-tree reconstruction. */
|
|
58
|
+
export const processTreeReconstructionSchema = z.strictObject({
|
|
59
|
+
/** Root PID of the process tree. */
|
|
60
|
+
root_pid: z.number().int().positive(),
|
|
61
|
+
/** All reconstructed process nodes. */
|
|
62
|
+
processes: z.array(processNodeSchema).min(0).max(10_000),
|
|
63
|
+
/** Events that were consumed. */
|
|
64
|
+
events_consumed: z.number().int().nonnegative(),
|
|
65
|
+
/** Events that could not be matched. */
|
|
66
|
+
events_unmatched: z.number().int().nonnegative(),
|
|
67
|
+
/** Short-lived descendants that were missed by sampling. */
|
|
68
|
+
short_lived_descendants: z.number().int().nonnegative(),
|
|
69
|
+
/** Whether any re-exec was detected. */
|
|
70
|
+
has_re_exec: z.boolean().default(false),
|
|
71
|
+
/** Whether any reparenting was detected. */
|
|
72
|
+
has_reparenting: z.boolean().default(false),
|
|
73
|
+
});
|
|
74
|
+
const applyProcessTreeEvent = (event, state) => {
|
|
75
|
+
let node = state.nodes.get(event.pid);
|
|
76
|
+
switch (event.type) {
|
|
77
|
+
case "spawn": {
|
|
78
|
+
if (!node) {
|
|
79
|
+
node = {
|
|
80
|
+
pid: event.pid,
|
|
81
|
+
ppid: event.ppid,
|
|
82
|
+
process_name: event.process_name,
|
|
83
|
+
executable: event.executable,
|
|
84
|
+
arguments: event.arguments,
|
|
85
|
+
children: [],
|
|
86
|
+
spawn_time_ms: event.at_ms,
|
|
87
|
+
exit_time_ms: null,
|
|
88
|
+
exit_code: null,
|
|
89
|
+
is_re_exec: false,
|
|
90
|
+
is_reparented: false,
|
|
91
|
+
previous_ppid: null,
|
|
92
|
+
};
|
|
93
|
+
state.nodes.set(event.pid, node);
|
|
94
|
+
}
|
|
95
|
+
if (event.ppid !== null) {
|
|
96
|
+
const parentChildren = state.children.get(event.ppid) ?? [];
|
|
97
|
+
parentChildren.push(event.pid);
|
|
98
|
+
state.children.set(event.ppid, parentChildren);
|
|
99
|
+
}
|
|
100
|
+
break;
|
|
101
|
+
}
|
|
102
|
+
case "exit":
|
|
103
|
+
if (node) {
|
|
104
|
+
node.exit_time_ms = event.at_ms;
|
|
105
|
+
node.exit_code = event.exit_code;
|
|
106
|
+
if (node.spawn_time_ms !== null &&
|
|
107
|
+
event.at_ms - node.spawn_time_ms < 100)
|
|
108
|
+
state.shortLivedDescendants++;
|
|
109
|
+
}
|
|
110
|
+
else
|
|
111
|
+
state.eventsUnmatched++;
|
|
112
|
+
break;
|
|
113
|
+
case "re_exec":
|
|
114
|
+
if (node) {
|
|
115
|
+
node.is_re_exec = true;
|
|
116
|
+
node.executable = event.executable ?? node.executable;
|
|
117
|
+
node.arguments = event.arguments;
|
|
118
|
+
state.hasReExec = true;
|
|
119
|
+
}
|
|
120
|
+
else
|
|
121
|
+
state.eventsUnmatched++;
|
|
122
|
+
break;
|
|
123
|
+
case "reparent":
|
|
124
|
+
if (node) {
|
|
125
|
+
node.previous_ppid = node.ppid;
|
|
126
|
+
node.ppid = event.ppid;
|
|
127
|
+
node.is_reparented = true;
|
|
128
|
+
state.hasReparenting = true;
|
|
129
|
+
}
|
|
130
|
+
else
|
|
131
|
+
state.eventsUnmatched++;
|
|
132
|
+
break;
|
|
133
|
+
case "signal":
|
|
134
|
+
case "name_change":
|
|
135
|
+
case "thread_create":
|
|
136
|
+
case "thread_exit":
|
|
137
|
+
// These events are recorded but don't modify the tree structure.
|
|
138
|
+
break;
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
/** Reconstruct a process tree from event-backed capture. */
|
|
142
|
+
export function reconstructProcessTree(events, rootPid) {
|
|
143
|
+
const nodes = new Map();
|
|
144
|
+
const children = new Map();
|
|
145
|
+
let eventsConsumed = 0;
|
|
146
|
+
const state = {
|
|
147
|
+
nodes,
|
|
148
|
+
children,
|
|
149
|
+
eventsUnmatched: 0,
|
|
150
|
+
hasReExec: false,
|
|
151
|
+
hasReparenting: false,
|
|
152
|
+
shortLivedDescendants: 0,
|
|
153
|
+
};
|
|
154
|
+
const sorted = [...events].sort((a, b) => a.at_ms - b.at_ms);
|
|
155
|
+
for (const event of sorted) {
|
|
156
|
+
eventsConsumed++;
|
|
157
|
+
applyProcessTreeEvent(event, state);
|
|
158
|
+
}
|
|
159
|
+
// Attach children to nodes
|
|
160
|
+
for (const [pid, childPids] of children) {
|
|
161
|
+
const node = nodes.get(pid);
|
|
162
|
+
if (node)
|
|
163
|
+
node.children = childPids;
|
|
164
|
+
}
|
|
165
|
+
return {
|
|
166
|
+
root_pid: rootPid,
|
|
167
|
+
processes: [...nodes.values()],
|
|
168
|
+
events_consumed: eventsConsumed,
|
|
169
|
+
events_unmatched: state.eventsUnmatched,
|
|
170
|
+
short_lived_descendants: state.shortLivedDescendants,
|
|
171
|
+
has_re_exec: state.hasReExec,
|
|
172
|
+
has_reparenting: state.hasReparenting,
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
/** Get all descendant PIDs of a given root PID. */
|
|
176
|
+
export function getDescendants(processes, rootPid) {
|
|
177
|
+
const byPid = new Map(processes.map((p) => [p.pid, p]));
|
|
178
|
+
const visited = new Set();
|
|
179
|
+
const result = [];
|
|
180
|
+
const queue = [rootPid];
|
|
181
|
+
while (queue.length > 0) {
|
|
182
|
+
const pid = queue.shift();
|
|
183
|
+
if (pid === undefined)
|
|
184
|
+
break;
|
|
185
|
+
if (visited.has(pid))
|
|
186
|
+
continue;
|
|
187
|
+
visited.add(pid);
|
|
188
|
+
const node = byPid.get(pid);
|
|
189
|
+
if (node) {
|
|
190
|
+
for (const child of node.children) {
|
|
191
|
+
if (!visited.has(child)) {
|
|
192
|
+
result.push(child);
|
|
193
|
+
queue.push(child);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
return result;
|
|
199
|
+
}
|
|
200
|
+
/** Check if a process tree contains a specific PID. */
|
|
201
|
+
export function containsProcess(processes, pid) {
|
|
202
|
+
return processes.some((p) => p.pid === pid);
|
|
203
|
+
}
|
|
204
|
+
/** Get the maximum tree depth from the root. */
|
|
205
|
+
export function maxTreeDepth(processes, rootPid) {
|
|
206
|
+
const byPid = new Map(processes.map((p) => [p.pid, p]));
|
|
207
|
+
function depth(pid, visited) {
|
|
208
|
+
if (visited.has(pid))
|
|
209
|
+
return 0;
|
|
210
|
+
visited.add(pid);
|
|
211
|
+
const node = byPid.get(pid);
|
|
212
|
+
if (!node || node.children.length === 0)
|
|
213
|
+
return 0;
|
|
214
|
+
return 1 + Math.max(...node.children.map((c) => depth(c, visited)));
|
|
215
|
+
}
|
|
216
|
+
return depth(rootPid, new Set());
|
|
217
|
+
}
|
|
@@ -163,6 +163,53 @@ const validateVerifiedResolution = (unknown, evidenceById) => {
|
|
|
163
163
|
if (qualifies !== true)
|
|
164
164
|
throw new TypeError(`Residual unknown ${unknown.unknown_id} has no qualifying resolution evidence`);
|
|
165
165
|
};
|
|
166
|
+
/**
|
|
167
|
+
* Validate one new residual-unknown revision against an already valid ledger.
|
|
168
|
+
* This keeps ordinary mutations proportional to the affected revision while
|
|
169
|
+
* full bundle imports continue to validate the complete graph.
|
|
170
|
+
*/
|
|
171
|
+
export const validateResidualUnknownAddition = (unknown, evidenceById, currentHeads) => {
|
|
172
|
+
const current = currentHeads.get(unknown.unknown_id);
|
|
173
|
+
if (current === undefined
|
|
174
|
+
? unknown.revision !== 1 || unknown.previous_revision_digest !== null
|
|
175
|
+
: unknown.revision !== current.revision + 1 ||
|
|
176
|
+
unknown.previous_revision_digest !== current.revision_digest)
|
|
177
|
+
throw new TypeError(`Residual unknown ${unknown.unknown_id} revision chain is broken`);
|
|
178
|
+
for (const evidenceId of referencedEvidenceIds(unknown))
|
|
179
|
+
if (!evidenceById.has(evidenceId))
|
|
180
|
+
throw new TypeError(`Residual unknown references missing evidence ${evidenceId}`);
|
|
181
|
+
for (const relationship of unknown.relationships)
|
|
182
|
+
if (relationship.unknown_id !== unknown.unknown_id &&
|
|
183
|
+
!currentHeads.has(relationship.unknown_id))
|
|
184
|
+
throw new TypeError(`Residual unknown references missing unknown ${relationship.unknown_id}`);
|
|
185
|
+
if (unknown.resolution?.disposition === "verified")
|
|
186
|
+
validateVerifiedResolution(unknown, evidenceById);
|
|
187
|
+
for (const relationship of unknown.relationships)
|
|
188
|
+
if (relationship.type === "depends-on" &&
|
|
189
|
+
reachesUnknown(relationship.unknown_id, unknown.unknown_id, currentHeads, unknown))
|
|
190
|
+
throw new TypeError("Residual unknown dependency graph contains a cycle");
|
|
191
|
+
};
|
|
192
|
+
const reachesUnknown = (start, goal, currentHeads, candidate) => {
|
|
193
|
+
const pending = [start];
|
|
194
|
+
const visited = new Set();
|
|
195
|
+
while (pending.length > 0) {
|
|
196
|
+
const id = pending.pop();
|
|
197
|
+
if (id === undefined)
|
|
198
|
+
break;
|
|
199
|
+
if (id === goal)
|
|
200
|
+
return true;
|
|
201
|
+
if (visited.has(id))
|
|
202
|
+
continue;
|
|
203
|
+
visited.add(id);
|
|
204
|
+
const unknown = id === candidate.unknown_id ? candidate : currentHeads.get(id);
|
|
205
|
+
if (unknown === undefined)
|
|
206
|
+
continue;
|
|
207
|
+
for (const relationship of unknown.relationships)
|
|
208
|
+
if (relationship.type === "depends-on")
|
|
209
|
+
pending.push(relationship.unknown_id);
|
|
210
|
+
}
|
|
211
|
+
return false;
|
|
212
|
+
};
|
|
166
213
|
const evidenceQualifies = (unknown, evidence) => {
|
|
167
214
|
if (unknown.required_authority !== null &&
|
|
168
215
|
evidence.authority !== unknown.required_authority)
|
|
@@ -123,14 +123,21 @@ export const stringAndNameProjection = (snapshot) => {
|
|
|
123
123
|
: sorted(values);
|
|
124
124
|
};
|
|
125
125
|
export const sorted = (values) => [...values].sort((left, right) => canonicalJson(left).localeCompare(canonicalJson(right)));
|
|
126
|
-
export const combineCoverage = (left, right) =>
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
126
|
+
export const combineCoverage = (left, right) => {
|
|
127
|
+
const base = {
|
|
128
|
+
items: [...left.items, ...right.items],
|
|
129
|
+
total: left.total === null || right.total === null
|
|
130
|
+
? null
|
|
131
|
+
: left.total + right.total,
|
|
132
|
+
};
|
|
133
|
+
return left.complete && right.complete
|
|
134
|
+
? { ...base, complete: true, truncated: false }
|
|
135
|
+
: {
|
|
136
|
+
...base,
|
|
137
|
+
complete: false,
|
|
138
|
+
truncated: left.truncated || right.truncated,
|
|
139
|
+
};
|
|
140
|
+
};
|
|
134
141
|
export const project = (collection, mapper) => collection.items.map(mapper);
|
|
135
142
|
export const isAutoName = (name) => /^(?:sub_[0-9a-f]+|fcn\.)/iu.test(name);
|
|
136
143
|
const parseAddress = (value) => /^0x[0-9a-f]+$/iu.test(value) ? BigInt(value) : null;
|
|
@@ -109,8 +109,9 @@ const mergePseudocode = (pages) => {
|
|
|
109
109
|
return {
|
|
110
110
|
text: orderedValues(characters).join(""),
|
|
111
111
|
total,
|
|
112
|
-
complete
|
|
113
|
-
|
|
112
|
+
...(complete
|
|
113
|
+
? { complete: true, truncated: false }
|
|
114
|
+
: { complete: false, truncated: true }),
|
|
114
115
|
};
|
|
115
116
|
};
|
|
116
117
|
const mergeCollection = (pages, field) => {
|
|
@@ -140,8 +141,12 @@ const mergeCollection = (pages, field) => {
|
|
|
140
141
|
return {
|
|
141
142
|
items: orderedValues(items),
|
|
142
143
|
total,
|
|
143
|
-
complete
|
|
144
|
-
|
|
144
|
+
...(complete
|
|
145
|
+
? { complete: true, truncated: false }
|
|
146
|
+
: {
|
|
147
|
+
complete: false,
|
|
148
|
+
truncated: scanLimited || !unavailable,
|
|
149
|
+
}),
|
|
145
150
|
};
|
|
146
151
|
};
|
|
147
152
|
const collectionOffset = (page, field) => field === "assembly"
|
|
@@ -27,7 +27,7 @@ const failures = [
|
|
|
27
27
|
[
|
|
28
28
|
75,
|
|
29
29
|
"hopper_exited_during_startup",
|
|
30
|
-
"Hopper exited before the REA bridge was ready.
|
|
30
|
+
"Hopper exited before the REA bridge was ready. In CI, run rea doctor --provider hopper --detail full --json; if Hopper showed a UI or license prompt, complete it in the runner user session, otherwise close stale Hopper sessions and retry.",
|
|
31
31
|
],
|
|
32
32
|
[
|
|
33
33
|
76,
|