rea-agents 3.2.0 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +183 -332
- package/bridge/ghidra/ReaGhidraBridge.java +561 -74
- package/bridge/hopper_bridge.py +70 -27
- package/bridge/native/ReaNativeUI.swift +157 -0
- package/dist/application/AnalysisContextQueries.js +19 -5
- package/dist/application/AnalysisSnapshotCache.js +30 -11
- package/dist/application/AppleAssetCatalogAnalysis.js +171 -0
- package/dist/application/ArtifactExtractionDestination.js +0 -12
- package/dist/application/ArtifactGraphConstruction.js +44 -11
- package/dist/application/ArtifactInventory/classify.js +7 -15
- package/dist/application/ArtifactInventory/hash.js +4 -2
- package/dist/application/ArtifactInventory/policy.js +2 -17
- package/dist/application/ArtifactInventory/reader.js +3 -3
- package/dist/application/ArtifactInventory/scanCanonical.js +2 -2
- package/dist/application/ArtifactInventory/scanReader.js +12 -4
- package/dist/application/ArtifactInventory/types.js +0 -3
- package/dist/application/BinarySession.js +28 -43
- package/dist/application/BinarySessionExecution.js +37 -1
- package/dist/application/BinaryTargetResolver.js +50 -4
- package/dist/application/BrowserEvidence.js +36 -7
- package/dist/application/BrowserObservationService.js +17 -44
- package/dist/application/BrowserScenarioCaptureService.js +2 -35
- package/dist/application/BrowserScenarioEvidence.js +13 -9
- package/dist/application/CapabilityClientRequirements.js +2 -11
- package/dist/application/CapabilityInventory.js +21 -35
- package/dist/application/ClientConfigurationDocument.js +84 -7
- package/dist/application/ClientRegistrationIdentity.js +32 -0
- package/dist/application/ClientRegistrationStatus.js +59 -6
- package/dist/application/DirectAnalysis.js +37 -58
- package/dist/application/DirectAnalysisStatus.js +4 -4
- package/dist/application/Doctor.js +89 -80
- package/dist/application/DoctorDiagnostics.js +2 -26
- package/dist/application/DoctorScope.js +8 -14
- package/dist/application/ElectronActiveEvidence.js +10 -27
- package/dist/application/ElectronActiveObservationService.js +9 -36
- package/dist/application/ElectronBoundaryAnalysis.js +2 -0
- package/dist/application/ElectronBoundaryGraphNative.js +1 -1
- package/dist/application/ElectronEvidence.js +8 -3
- package/dist/application/ElectronObservationService.js +9 -25
- package/dist/application/EnhancedLiteralTracing.js +4 -8
- package/dist/application/EnhancedTools.js +15 -35
- package/dist/application/FilesystemSnapshot.js +7 -8
- package/dist/application/JavaScriptApplicationEvidenceGraph.js +2 -1
- package/dist/application/JavaScriptApplicationWorkflowService.js +31 -7
- package/dist/application/JavaScriptArtifactAnalysis.js +6 -4
- package/dist/application/JavaScriptArtifactFiles.js +5 -0
- package/dist/application/JavaScriptArtifactPathResolution.js +179 -47
- package/dist/application/JavaScriptRuntimeObservationEvidence.js +6 -3
- package/dist/application/JavaScriptRuntimeObservationService.js +9 -25
- package/dist/application/JavaScriptRuntimeReconciliationService.js +45 -4
- package/dist/application/JavaScriptSemanticGraphAsyncProjection.js +11 -0
- package/dist/application/JavaScriptSemanticGraphChildProcessProjection.js +11 -0
- package/dist/application/JavaScriptSemanticGraphDataProjection.js +11 -0
- package/dist/application/JavaScriptSemanticGraphFlowProjection.js +14 -5
- package/dist/application/JsonFiles.js +1 -1
- package/dist/application/LazyAnalysisProvider.js +27 -6
- package/dist/application/ManagedMemberComparisonService.js +19 -6
- package/dist/application/NativeApiInspection.js +2 -0
- package/dist/application/NativeCallRoutes.js +72 -0
- package/dist/application/NativeDispatchMetadataInspection.js +33 -0
- package/dist/application/NativeUiActionTrace.js +73 -49
- package/dist/application/NativeValueTrace.js +320 -0
- package/dist/application/ProcessCaptureCapability.js +32 -5
- package/dist/application/ProcessCaptureEnvironment.js +9 -26
- package/dist/application/ProcessCaptureError.js +1 -5
- package/dist/application/ProcessCaptureJournal.js +3 -40
- package/dist/application/ProcessCaptureLifecycle.js +102 -111
- package/dist/application/ProcessCli.js +18 -25
- package/dist/application/ProcessEvidence.js +5 -7
- package/dist/application/ProcessFilesystemEffects.js +36 -0
- package/dist/application/ProcessHarness.js +41 -120
- package/dist/application/ProcessNormalization.js +2 -17
- package/dist/application/ProcessScenarioRuntimeValidation.js +76 -0
- package/dist/application/ReferenceSourceImport.js +3 -4
- package/dist/application/Setup.js +236 -84
- package/dist/application/SetupClientConfiguration.js +14 -9
- package/dist/application/SetupPlan.js +138 -86
- package/dist/application/SetupSkill.js +0 -1
- package/dist/application/SupportedClients.js +102 -21
- package/dist/application/Uninstall.js +31 -20
- package/dist/application/Update.js +93 -0
- package/dist/application/UpdateMaintenance.js +108 -0
- package/dist/application/UpdateRuntime.js +126 -0
- package/dist/application/runtime.js +13 -2
- package/dist/artifacts/ArtifactPaths.js +6 -8
- package/dist/artifacts/ArtifactProvider.js +94 -41
- package/dist/artifacts/AsarArtifactReader.js +19 -4
- package/dist/artifacts/KeyedArchiveReader.js +110 -0
- package/dist/artifacts/MachOSliceArtifactReader.js +53 -5
- package/dist/artifacts/ZipArtifactReader.js +18 -1
- package/dist/browser/BrowserScenarioSecrets.js +28 -1
- package/dist/browser/CdpBrowserProvider.js +36 -15
- package/dist/browser/CdpCaptureDocuments.js +22 -8
- package/dist/browser/CdpCaptureEventHandlers.js +14 -5
- package/dist/browser/CdpCaptureEventHelpers.js +13 -0
- package/dist/browser/CdpCaptureEvents.js +10 -1
- package/dist/browser/CdpElectronInspection.js +5 -10
- package/dist/browser/CdpElectronProvider.js +1 -5
- package/dist/browser/CdpElectronScripts.js +1 -1
- package/dist/browser/CdpEndpoint.js +3 -2
- package/dist/browser/CdpObservationSession.js +14 -10
- package/dist/browser/CdpPageCapture.js +1 -1
- package/dist/browser/CdpPageCaptureScripts.js +1 -1
- package/dist/browser/CdpSafeMetadata.js +5 -4
- package/dist/browser/CdpScreenshot.js +16 -5
- package/dist/browser/CdpTargetSession.js +25 -4
- package/dist/browser/CdpWebMcpDiscovery.js +93 -20
- package/dist/browser/JavaScriptRuntimeScope.js +28 -2
- package/dist/browser/PlaywrightBrowserScenarioProvider.js +9 -8
- package/dist/browser/PlaywrightElectronActiveActions.js +3 -10
- package/dist/browser/PlaywrightElectronActiveProvider.js +5 -5
- package/dist/browser/PlaywrightScenarioActions.js +1 -1
- package/dist/browser/PlaywrightScenarioArtifacts.js +13 -25
- package/dist/browser/PlaywrightScenarioBrowser.js +28 -25
- package/dist/browser/PlaywrightScenarioEvents.js +82 -93
- package/dist/browser/PlaywrightScenarioSession.js +27 -123
- package/dist/browser/PngVisualDiff.js +22 -3
- package/dist/browser/V8InspectorCaptureProjection.js +7 -1
- package/dist/browser/V8InspectorProvider.js +60 -7
- package/dist/browser/WebSourceMapFetcher.js +99 -53
- package/dist/cli/artifactCommands.js +56 -12
- package/dist/cli/coreAnalysisCommands.js +110 -0
- package/dist/cli/managedCommands.js +1 -31
- package/dist/cli/setupCommands.js +16 -14
- package/dist/cli/utilityCommands.js +61 -4
- package/dist/cli.js +5 -7
- package/dist/cliApplicationCommands.js +0 -83
- package/dist/cliBrowserAdvancedCommands.js +7 -11
- package/dist/cliBrowserCommands.js +15 -23
- package/dist/cliBrowserContext.js +3 -24
- package/dist/cliBrowserScenarioCommands.js +2 -10
- package/dist/cliCommandNames.js +82 -7
- package/dist/cliElectronCommands.js +10 -36
- package/dist/cliJavaScriptRuntimeCommands.js +6 -30
- package/dist/cliJsonInput.js +4 -2
- package/dist/cliLogging.js +16 -7
- package/dist/cliObservationOptions.js +1 -1
- package/dist/cliOutput.js +2 -4
- package/dist/cliProcessCommands.js +6 -33
- package/dist/cliSetup.js +90 -160
- package/dist/config/environment.js +2 -78
- package/dist/config/parseConfig.js +18 -109
- package/dist/config/parsers.js +0 -23
- package/dist/contracts/applicationToolContracts.js +1 -118
- package/dist/contracts/artifactToolContracts.js +11 -19
- package/dist/contracts/browserScenarioToolContracts.js +1 -5
- package/dist/contracts/browserToolContracts.js +9 -16
- package/dist/contracts/electronToolContracts.js +5 -6
- package/dist/contracts/enhancedInputs.js +3 -2
- package/dist/contracts/errorSchemas.js +16 -40
- package/dist/contracts/functionWorkflowToolContracts.js +2 -2
- package/dist/contracts/javascriptApplicationWorkflowExamples.js +2 -2
- package/dist/contracts/javascriptRuntimeObservationToolContracts.js +4 -4
- package/dist/contracts/javascriptRuntimeReconciliationExample.js +1 -1
- package/dist/contracts/managedToolContracts.js +7 -4
- package/dist/contracts/managedWorkflowExamples.js +0 -22
- package/dist/contracts/managedWorkflowToolContracts.js +16 -31
- package/dist/contracts/nativeToolContracts.js +9 -0
- package/dist/contracts/promptContracts.js +6 -6
- package/dist/contracts/sessionToolSchemas.js +3 -3
- package/dist/contracts/toolContractExamples.js +4 -3
- package/dist/contracts/toolContracts.js +18 -7
- package/dist/contracts/toolEffects.js +34 -21
- package/dist/contracts/toolOutputSchemaGroups.js +18 -5
- package/dist/contracts/toolOutputSchemaPrimitives.js +9 -6
- package/dist/contracts/toolSchemaMetadata.js +5 -8
- package/dist/doctorRuntime.js +0 -41
- package/dist/domain/analysisErrorPresentation.js +4 -28
- package/dist/domain/analysisErrorProjection.js +33 -50
- package/dist/domain/analysisProfile.js +1 -1
- package/dist/domain/analysisSnapshot.js +77 -3
- package/dist/domain/androidApplication.js +5 -4
- package/dist/domain/appleApplication.js +5 -4
- package/dist/domain/appleAssetCatalog.js +127 -0
- package/dist/domain/artifactComparison.js +7 -11
- package/dist/domain/artifactGraph.js +8 -6
- package/dist/domain/artifactInspection.js +13 -12
- package/dist/domain/binaryTarget.js +23 -9
- package/dist/domain/browserObservation.js +43 -24
- package/dist/domain/browserObservationSchemas.js +2 -1
- package/dist/domain/browserScenario.js +7 -107
- package/dist/domain/browserScenarioCapture.js +0 -1
- package/dist/domain/browserScenarioCaptureValues.js +5 -4
- package/dist/domain/browserScenarioDiff.js +1 -3
- package/dist/domain/browserScenarioValues.js +16 -107
- package/dist/domain/bundleComparison.js +18 -17
- package/dist/domain/callPathSchemas.js +17 -7
- package/dist/domain/changedBehavior.js +2 -3
- package/dist/domain/comparisonSemantics.js +19 -0
- package/dist/domain/completionLedgerGeneration.js +3 -2
- package/dist/domain/conformancePackage.js +2 -1
- package/dist/domain/conformanceTrustGate.js +3 -5
- package/dist/domain/customProtocolCapture.js +2 -2
- package/dist/domain/digests.js +30 -0
- package/dist/domain/dosMz.js +83 -0
- package/dist/domain/electronActiveObservation.js +7 -5
- package/dist/domain/electronObservation.js +3 -2
- package/dist/domain/electronStaticAnalysisNative.js +15 -6
- package/dist/domain/emptyArraySchema.js +3 -0
- package/dist/domain/errors.js +10 -28
- package/dist/domain/evidence.js +5 -3
- package/dist/domain/evidenceCompletionLedger.js +3 -2
- package/dist/domain/functionComparisonNormalization.js +24 -18
- package/dist/domain/functionComparisonResults.js +3 -7
- package/dist/domain/functionComparisonSchemas.js +3 -2
- package/dist/domain/hopperValues.js +108 -8
- package/dist/domain/javascriptApplicationAnalysis.js +4 -7
- package/dist/domain/javascriptApplicationEvidenceSchemas.js +4 -3
- package/dist/domain/javascriptApplicationGraphSchemas.js +8 -7
- package/dist/domain/javascriptApplicationVersionComparisonSchemas.js +9 -7
- package/dist/domain/javascriptApplicationVersionItems.js +12 -18
- package/dist/domain/javascriptAstValues.js +4 -0
- package/dist/domain/javascriptExportShapeComparison.js +1 -6
- package/dist/domain/javascriptExportShapeComparisonSchemas.js +6 -10
- package/dist/domain/javascriptExportShapeVariants.js +15 -2
- package/dist/domain/javascriptFeatureTraceSchemas.js +8 -7
- package/dist/domain/javascriptRuntimeObservation.js +14 -2
- package/dist/domain/javascriptRuntimeReconciliationMatching.js +8 -0
- package/dist/domain/javascriptRuntimeReconciliationParsing.js +4 -2
- package/dist/domain/javascriptRuntimeReconciliationResult.js +6 -4
- package/dist/domain/javascriptRuntimeReconciliationRuntime.js +15 -4
- package/dist/domain/javascriptRuntimeReconciliationSchemas.js +19 -18
- package/dist/domain/javascriptRuntimeStaticCandidates.js +18 -6
- package/dist/domain/javascriptSemanticAnalysis.js +57 -19
- package/dist/domain/javascriptSemanticAsyncEffects.js +39 -40
- package/dist/domain/javascriptSemanticCalls.js +46 -27
- package/dist/domain/javascriptSemanticChildProcesses.js +43 -50
- package/dist/domain/javascriptSemanticDataEffectHelpers.js +91 -18
- package/dist/domain/javascriptSemanticDataEffects.js +22 -10
- package/dist/domain/javascriptSemanticGraphSchemas.js +8 -6
- package/dist/domain/javascriptSemanticObjects.js +13 -3
- package/dist/domain/javascriptSemanticProjection.js +144 -38
- package/dist/domain/javascriptSemanticPromises.js +14 -27
- package/dist/domain/javascriptSemanticQuerySchemas.js +6 -9
- package/dist/domain/javascriptSemanticResources.js +2 -5
- package/dist/domain/javascriptSemanticState.js +4 -0
- package/dist/domain/javascriptSemanticTraceSchemas.js +2 -1
- package/dist/domain/javascriptSemanticTraversal.js +13 -5
- package/dist/domain/javascriptSemanticValues.js +10 -9
- package/dist/domain/javascriptSourceParser.js +5 -1
- package/dist/domain/javascriptStaticAnalysisCalls.js +8 -5
- package/dist/domain/javascriptStaticAnalysisHelpers.js +16 -7
- package/dist/domain/keyedArchive.js +181 -0
- package/dist/domain/managedApplicationGraph.js +4 -3
- package/dist/domain/managedArtifact.js +2 -1
- package/dist/domain/managedMemberComparison.js +18 -13
- package/dist/domain/managedMemberComparisonCoverage.js +2 -1
- package/dist/domain/managedMemberComparisonItems.js +27 -7
- package/dist/domain/managedMemberComparisonMatch.js +22 -6
- package/dist/domain/managedNativeVerificationMatch.js +2 -2
- package/dist/domain/managedNativeVerificationSchemas.js +7 -5
- package/dist/domain/managedReconstruction.js +6 -5
- package/dist/domain/nativeApiBoundary.js +7 -0
- package/dist/domain/nativeDataType.js +51 -0
- package/dist/domain/nativeInspection.js +0 -1
- package/dist/domain/nativeInstruction.js +82 -0
- package/dist/domain/nativeInvestigationGraph.js +9 -5
- package/dist/domain/nativeUiObservation.js +123 -0
- package/dist/domain/nativeValueFlow.js +17 -0
- package/dist/domain/nativeValueTrace.js +64 -0
- package/dist/domain/objcSwiftMetadata.js +39 -0
- package/dist/domain/peInspection.js +1 -0
- package/dist/domain/processCapture.js +5 -55
- package/dist/domain/processCaptureExample.js +0 -9
- package/dist/domain/processCaptureValidation.js +13 -144
- package/dist/domain/processComparison.js +3 -25
- package/dist/domain/processObservation.js +0 -29
- package/dist/domain/processScenario.js +28 -228
- package/dist/domain/processTraceDimensionProjection.js +0 -15
- package/dist/domain/processTraceEvaluation.js +0 -6
- package/dist/domain/protocolCapture.js +8 -36
- package/dist/domain/reconstructionCoverage.js +3 -2
- package/dist/domain/reconstructionObligationLedgerSchemas.js +4 -12
- package/dist/domain/reconstructionReadinessSchemas.js +4 -3
- package/dist/domain/reconstructionVerification.js +2 -1
- package/dist/domain/reconstructionVerificationSchemas.js +6 -13
- package/dist/domain/referenceSourceClassification.js +0 -110
- package/dist/domain/referenceSourceGraph.js +15 -5
- package/dist/domain/residualUnknown.js +3 -2
- package/dist/domain/runtimeIdentification.js +6 -5
- package/dist/domain/sourceMapContents.js +5 -0
- package/dist/domain/sourceToBundleComparison.js +3 -10
- package/dist/domain/sourceToBundleComparisonSchemas.js +7 -6
- package/dist/domain/sourceToBundleSignals.js +9 -3
- package/dist/domain/staticRuntimeCorrelation.js +5 -11
- package/dist/domain/webBundleAnalysis.js +17 -9
- package/dist/domain/webBundleAnalyzer.js +1 -1
- package/dist/domain/webCaptureDiff.js +5 -11
- package/dist/domain/webCaptureDiffSchemas.js +2 -1
- package/dist/domain/webMcpDiscovery.js +2 -1
- package/dist/dotnet/ManagedMemberInspectorCore.js +15 -7
- package/dist/dotnet/ManagedMemberInstructionDecoder.js +57 -40
- package/dist/dotnet/ManagedMemberRows.js +2 -0
- package/dist/dotnet/ManagedMethodBodyReader.js +15 -8
- package/dist/dotnet/ManagedPeReader.js +2 -0
- package/dist/generatedMcpToolCatalog.js +1 -1
- package/dist/generatedPackageMetadata.js +2 -2
- package/dist/ghidra/GhidraAnalysisProfile.js +15 -5
- package/dist/ghidra/GhidraClient.js +38 -8
- package/dist/ghidra/GhidraFunctionValues.js +56 -20
- package/dist/ghidra/GhidraInstallation.js +7 -4
- package/dist/ghidra/GhidraInventoryValues.js +44 -9
- package/dist/ghidra/GhidraLauncher.js +18 -3
- package/dist/ghidra/GhidraProvider.js +23 -2
- package/dist/ghidra/GhidraRequestQueue.js +45 -4
- package/dist/ghidra/GhidraSessionValues.js +5 -0
- package/dist/hopper/HopperAnalysisProfile.js +2 -0
- package/dist/hopper/HopperProvider.js +29 -6
- package/dist/hopper/HopperTargetLease.js +18 -4
- package/dist/logger.js +0 -13
- package/dist/main/messages.js +0 -1
- package/dist/main/reload.js +3 -32
- package/dist/main/shutdown.js +1 -2
- package/dist/main/transport.js +0 -17
- package/dist/main.js +0 -10
- package/dist/native/AppleDispatchMetadata.js +582 -0
- package/dist/native/AppleObjcProtocols.js +88 -0
- package/dist/native/AppleSwiftVtables.js +86 -0
- package/dist/native/CommandRunner.js +1 -1
- package/dist/native/NativeHostCapabilities.js +23 -0
- package/dist/native/NativeMacOSProvider.js +61 -9
- package/dist/native/NativeMachoInspection.js +39 -6
- package/dist/native/NativeUiHelperRuntime.js +42 -0
- package/dist/native/NativeUiObservation.js +174 -0
- package/dist/native/parsers/codesign.js +4 -1
- package/dist/native/parsers/dyldInfo.js +51 -25
- package/dist/native/parsers/lipo.js +13 -4
- package/dist/native/parsers/otool.js +84 -39
- package/dist/native/parsers/plist.js +2 -1
- package/dist/process/ExecFileOutput.js +5 -1
- package/dist/process/ProcessOwnership.js +69 -33
- package/dist/process/ProcessOwnershipObservation.js +31 -12
- package/dist/process/ProviderProcess.js +4 -2
- package/dist/reference/ReferenceSourceReaderEntries.js +48 -31
- package/dist/reference/ReferenceSourceReaderErrors.js +24 -0
- package/dist/reference/ReferenceSourceReaderFile.js +11 -5
- package/dist/reference/ReferenceSourceReaderValidate.js +22 -8
- package/dist/server/createServer.js +7 -62
- package/dist/server/registerApplicationTools/helpers.js +2 -9
- package/dist/server/registerApplicationTools.js +0 -4
- package/dist/server/registerArtifactComparisonTool.js +1 -1
- package/dist/server/registerBrowserScenarioTool.js +4 -2
- package/dist/server/registerBrowserTools.js +7 -7
- package/dist/server/registerBundleComparisonTool.js +1 -1
- package/dist/server/registerCloseLifecycleTool.js +1 -1
- package/dist/server/registerElectronTools.js +10 -4
- package/dist/server/registerEnhancedTools.js +20 -12
- package/dist/server/registerEvidenceTools.js +4 -28
- package/dist/server/registerFunctionComparisonTool.js +1 -1
- package/dist/server/registerInvestigationTools.js +6 -6
- package/dist/server/registerJavaScriptRuntimeObservationTools.js +2 -2
- package/dist/server/registerManagedTools.js +28 -14
- package/dist/server/registerManagedWorkflowTools.js +0 -2
- package/dist/server/registerProcessComparisonTool.js +1 -3
- package/dist/server/registerSessionRecordTools.js +9 -9
- package/dist/server/registerSessionStatusTool.js +1 -1
- package/dist/server/registerSessionTools.js +28 -57
- package/dist/server/sessionAvailabilityPolicy.js +2 -3
- package/dist/server/sessionToolPolicies.js +0 -4
- package/dist/server/toolResult.js +8 -10
- package/package.json +32 -22
- package/skills/reverse-engineer-anything/SKILL.md +15 -11
- package/skills/reverse-engineer-anything/references/evidence-workflows.md +3 -2
- package/skills/reverse-engineer-anything/references/javascript-applications.md +3 -2
- package/skills/reverse-engineer-anything/references/native-and-artifacts.md +8 -6
- package/skills/reverse-engineer-anything/references/runtime-observation.md +15 -11
- package/dist/application/CommandShimReplay.js +0 -152
- package/dist/application/ConfiguredRoots.js +0 -19
- package/dist/application/InstrumentedJavaScriptReplayHost.js +0 -36
- package/dist/application/JavaScriptReplayPermission.js +0 -16
- package/dist/application/JavaScriptReplayPlanning.js +0 -207
- package/dist/application/JavaScriptReplayService.js +0 -274
- package/dist/application/LoopbackReplay.js +0 -389
- package/dist/application/LoopbackReplayRecorder.js +0 -129
- package/dist/application/ManagedRuntimeCorrelationService.js +0 -104
- package/dist/application/NodeRuntimeCharacterizationService.js +0 -191
- package/dist/application/PermissionAuthority.js +0 -268
- package/dist/application/PermissionConfiguration.js +0 -26
- package/dist/application/PermissionFailure.js +0 -5
- package/dist/application/ProcessCaptureAuthority.js +0 -24
- package/dist/application/ProcessCapturePermission.js +0 -13
- package/dist/application/ProcessCheckpoints.js +0 -178
- package/dist/application/ProcessReactiveCoordinator.js +0 -223
- package/dist/application/ProcessReactiveEffects.js +0 -153
- package/dist/application/ProcessReactiveHarness.js +0 -106
- package/dist/application/ProcessReactiveObservations.js +0 -105
- package/dist/application/ProjectPermissionStore.js +0 -199
- package/dist/application/RuntimeExecutableDiagnostics.js +0 -198
- package/dist/application/Upgrade.js +0 -134
- package/dist/browser/SensitiveTextCapture.js +0 -8
- package/dist/cliPolicyCommands.js +0 -185
- package/dist/config/browserScenario.js +0 -77
- package/dist/config/electronAutomation.js +0 -35
- package/dist/config/javascriptReplay.js +0 -41
- package/dist/config/managedRuntime.js +0 -25
- package/dist/config/passiveObservation.js +0 -87
- package/dist/config/permissions.js +0 -23
- package/dist/config/processCapture.js +0 -47
- package/dist/contracts/replayMachineExample.js +0 -37
- package/dist/domain/javascriptExportInstrumentation.js +0 -95
- package/dist/domain/javascriptReplay.js +0 -360
- package/dist/domain/managedRuntimeCorrelation.js +0 -181
- package/dist/domain/nodeRuntimeCharacterization.js +0 -63
- package/dist/domain/permissionPolicy.js +0 -176
- package/dist/domain/processCaptureReactiveSchema.js +0 -68
- package/dist/domain/processCaptureReactiveValidation.js +0 -180
- package/dist/domain/processReactiveCheckpointDataflow.js +0 -32
- package/dist/domain/processReactiveMatching.js +0 -196
- package/dist/domain/processReactiveRuntime.js +0 -116
- package/dist/domain/processReactiveScenario.js +0 -296
- package/dist/domain/processReactiveScenarioPreflight.js +0 -95
- package/dist/domain/processReactiveTransition.js +0 -187
- package/dist/domain/replayMachine.js +0 -320
- package/dist/domain/replayMachineRun.js +0 -168
- package/dist/domain/replayMachineRuntime.js +0 -296
- package/dist/domain/replayMachineValues.js +0 -84
- package/dist/domain/runtimeCharacterization.js +0 -84
- package/dist/replay/JavaScriptReplayWorker.js +0 -382
- package/dist/replay/JavaScriptReplayWorkerTypes.js +0 -1
- package/dist/replay/LinuxJavaScriptReplayRunner.js +0 -216
- package/dist/replay/LinuxJavaScriptReplaySandbox.js +0 -121
- package/dist/replay/LinuxRuntimeClosure.js +0 -44
- package/dist/replay/LinuxSeccompPolicy.js +0 -40
- package/dist/replay/ReplayOutcome.js +0 -104
- package/dist/replay/ReplayProcessLifecycle.js +0 -96
- package/dist/replay/ReplaySeccompFile.js +0 -29
- package/dist/replay/ReplayWorkerProtocol.js +0 -58
- package/dist/replay/SystemJavaScriptReplayHost.js +0 -153
- package/dist/server/ProcessCaptureElicitation.js +0 -153
- package/dist/server/registerApplicationTools/characterization.js +0 -46
- package/dist/server/registerApplicationTools/controlledReplay.js +0 -31
- package/dist/server/registerManagedWorkflowTools/planManagedRuntimeCorrelation.js +0 -29
- package/dist/server/registerReplayMachineTool.js +0 -14
- package/skills/reverse-engineer-anything/references/controlled-replay.md +0 -12
|
@@ -1,176 +0,0 @@
|
|
|
1
|
-
import { isAbsolute, relative, resolve, sep } from "node:path";
|
|
2
|
-
import { err, ok } from "./result.js";
|
|
3
|
-
/** Canonical local capabilities governed by the shared REA permission policy. */
|
|
4
|
-
export const PERMISSION_CAPABILITIES = [
|
|
5
|
-
"process_capture",
|
|
6
|
-
"browser_observe",
|
|
7
|
-
"browser_automate",
|
|
8
|
-
"electron_observe",
|
|
9
|
-
"electron_automate",
|
|
10
|
-
"v8_inspector_observe",
|
|
11
|
-
"artifact_extract",
|
|
12
|
-
"native_mount",
|
|
13
|
-
"javascript_replay",
|
|
14
|
-
"managed_runtime",
|
|
15
|
-
];
|
|
16
|
-
/** A proposed grant exceeds the administrator-owned maximum authority. */
|
|
17
|
-
export class PermissionGrantError extends Error {
|
|
18
|
-
reason;
|
|
19
|
-
missing;
|
|
20
|
-
_tag = "PermissionGrantError";
|
|
21
|
-
constructor(reason, missing) {
|
|
22
|
-
super(`Permission grant rejected: ${reason}`);
|
|
23
|
-
this.reason = reason;
|
|
24
|
-
this.missing = missing;
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
/** Create a fail-closed policy with no implicit grants. */
|
|
28
|
-
export const createPermissionPolicy = (ceilings, grants = []) => ({
|
|
29
|
-
ceilings: ceilings.map(normalizeScope),
|
|
30
|
-
grants: grants.map(normalizeGrant),
|
|
31
|
-
revoked_grant_ids: new Set(),
|
|
32
|
-
consumed_grant_ids: new Set(),
|
|
33
|
-
});
|
|
34
|
-
/** Add one grant only when it is a subset of its administrator ceiling. */
|
|
35
|
-
export const grantPermission = (policy, grant) => {
|
|
36
|
-
const normalized = normalizeGrant(grant);
|
|
37
|
-
if (normalized.lifetime === "once" && normalized.operation_identity === null)
|
|
38
|
-
return err(new PermissionGrantError("invalid_once_scope", {}));
|
|
39
|
-
const missing = missingFromScopes(normalized, policy.ceilings);
|
|
40
|
-
if (hasMissing(missing))
|
|
41
|
-
return err(new PermissionGrantError("outside_administrator_ceiling", missing));
|
|
42
|
-
return ok({ ...policy, grants: [...policy.grants, normalized] });
|
|
43
|
-
};
|
|
44
|
-
/** Evaluate exact requested authority against the ceiling and active grants. */
|
|
45
|
-
export const evaluatePermission = (policy, request, now = new Date()) => {
|
|
46
|
-
const normalized = normalizeRequest(request);
|
|
47
|
-
const outsideCeiling = missingFromScopes(normalized, policy.ceilings);
|
|
48
|
-
if (hasMissing(outsideCeiling))
|
|
49
|
-
return {
|
|
50
|
-
allowed: false,
|
|
51
|
-
reason: "outside_administrator_ceiling",
|
|
52
|
-
missing: outsideCeiling,
|
|
53
|
-
};
|
|
54
|
-
const candidates = policy.grants.filter((grant) => grant.capability === normalized.capability &&
|
|
55
|
-
!policy.revoked_grant_ids.has(grant.grant_id) &&
|
|
56
|
-
!policy.consumed_grant_ids.has(grant.grant_id) &&
|
|
57
|
-
!isExpired(grant, now) &&
|
|
58
|
-
(grant.lifetime !== "once" ||
|
|
59
|
-
grant.operation_identity === normalized.operation_identity));
|
|
60
|
-
const selected = candidates.find((grant) => !hasMissing(missingFromScopes(normalized, [grant])));
|
|
61
|
-
if (selected !== undefined)
|
|
62
|
-
return {
|
|
63
|
-
allowed: true,
|
|
64
|
-
grant_id: selected.grant_id,
|
|
65
|
-
lifetime: selected.lifetime,
|
|
66
|
-
};
|
|
67
|
-
const coveringGrant = policy.grants.find((grant) => grant.capability === normalized.capability &&
|
|
68
|
-
(grant.lifetime !== "once" ||
|
|
69
|
-
grant.operation_identity === normalized.operation_identity) &&
|
|
70
|
-
!hasMissing(missingFromScopes(normalized, [grant])));
|
|
71
|
-
return {
|
|
72
|
-
allowed: false,
|
|
73
|
-
reason: coveringGrant !== undefined && isExpired(coveringGrant, now)
|
|
74
|
-
? "grant_expired"
|
|
75
|
-
: coveringGrant !== undefined
|
|
76
|
-
? "grant_revoked_or_consumed"
|
|
77
|
-
: "grant_required",
|
|
78
|
-
missing: missingFromScopes(normalized, candidates),
|
|
79
|
-
};
|
|
80
|
-
};
|
|
81
|
-
/** Test whether one exact request is wholly contained by one ceiling. */
|
|
82
|
-
export const isPermissionRequestWithinCeiling = (request, ceiling) => !hasMissing(missingFromScopes(normalizeRequest(request), [ceiling]));
|
|
83
|
-
/** Consume an allowed one-shot decision; longer-lived grants are unchanged. */
|
|
84
|
-
export const consumePermission = (policy, decision) => decision.lifetime === "once"
|
|
85
|
-
? {
|
|
86
|
-
...policy,
|
|
87
|
-
consumed_grant_ids: new Set([
|
|
88
|
-
...policy.consumed_grant_ids,
|
|
89
|
-
decision.grant_id,
|
|
90
|
-
]),
|
|
91
|
-
}
|
|
92
|
-
: policy;
|
|
93
|
-
/** Revoke one grant for every future evaluation. */
|
|
94
|
-
export const revokePermission = (policy, grantId) => ({
|
|
95
|
-
...policy,
|
|
96
|
-
revoked_grant_ids: new Set([...policy.revoked_grant_ids, grantId]),
|
|
97
|
-
});
|
|
98
|
-
/** Drop connection-bound authority when an MCP or CLI session ends. */
|
|
99
|
-
export const clearSessionPermissions = (policy) => ({
|
|
100
|
-
...policy,
|
|
101
|
-
grants: policy.grants.filter(({ lifetime }) => lifetime !== "once" && lifetime !== "session"),
|
|
102
|
-
});
|
|
103
|
-
/** Atomically replace administrator ceilings while retaining auditable grants. */
|
|
104
|
-
export const reloadPermissionCeilings = (policy, ceilings) => ({
|
|
105
|
-
...policy,
|
|
106
|
-
ceilings: ceilings.map(normalizeScope),
|
|
107
|
-
});
|
|
108
|
-
const normalizeScope = (scope) => ({
|
|
109
|
-
capability: scope.capability,
|
|
110
|
-
roots: uniqueSorted(scope.roots.map((path) => resolve(path))),
|
|
111
|
-
executables: uniqueSorted(scope.executables.map((path) => resolve(path))),
|
|
112
|
-
environment_names: uniqueSorted(scope.environment_names),
|
|
113
|
-
...(scope.origins === undefined
|
|
114
|
-
? {}
|
|
115
|
-
: { origins: uniqueSorted(scope.origins) }),
|
|
116
|
-
network: scope.network,
|
|
117
|
-
mount: scope.mount,
|
|
118
|
-
});
|
|
119
|
-
const normalizeGrant = (grant) => ({
|
|
120
|
-
...normalizeScope(grant),
|
|
121
|
-
grant_id: grant.grant_id,
|
|
122
|
-
lifetime: grant.lifetime,
|
|
123
|
-
operation_identity: grant.operation_identity,
|
|
124
|
-
expires_at: grant.expires_at,
|
|
125
|
-
});
|
|
126
|
-
const normalizeRequest = (request) => ({
|
|
127
|
-
...normalizeScope(request),
|
|
128
|
-
operation_identity: request.operation_identity,
|
|
129
|
-
});
|
|
130
|
-
const missingFromScopes = (request, scopes) => {
|
|
131
|
-
const relevant = scopes.filter(({ capability }) => capability === request.capability);
|
|
132
|
-
const roots = request.roots.filter((path) => !relevant.some((scope) => containsAny(scope.roots, path)));
|
|
133
|
-
const executables = request.executables.filter((path) => !relevant.some((scope) => containsAny(scope.executables, path)));
|
|
134
|
-
const environmentNames = request.environment_names.filter((name) => !relevant.some((scope) => scope.environment_names.includes(name)));
|
|
135
|
-
const origins = (request.origins ?? []).filter((origin) => !relevant.some((scope) => (scope.origins ?? []).includes(origin)));
|
|
136
|
-
const network = request.network === "none" ||
|
|
137
|
-
relevant.some((scope) => networkRank(scope.network) >= networkRank(request.network))
|
|
138
|
-
? undefined
|
|
139
|
-
: request.network;
|
|
140
|
-
const mount = !request.mount || relevant.some((scope) => scope.mount)
|
|
141
|
-
? undefined
|
|
142
|
-
: true;
|
|
143
|
-
return {
|
|
144
|
-
...(roots.length === 0 ? {} : { roots }),
|
|
145
|
-
...(executables.length === 0 ? {} : { executables }),
|
|
146
|
-
...(environmentNames.length === 0
|
|
147
|
-
? {}
|
|
148
|
-
: { environment_names: environmentNames }),
|
|
149
|
-
...(origins.length === 0 ? {} : { origins }),
|
|
150
|
-
...(network === undefined ? {} : { network }),
|
|
151
|
-
...(mount === undefined ? {} : { mount }),
|
|
152
|
-
};
|
|
153
|
-
};
|
|
154
|
-
const HOST_PATH_OPERATIONS = { relative, isAbsolute, sep };
|
|
155
|
-
/** Test whether a candidate is inside a root using one platform path flavor. */
|
|
156
|
-
export const isPathContained = (root, candidate, operations = HOST_PATH_OPERATIONS) => {
|
|
157
|
-
const relation = operations.relative(root, candidate);
|
|
158
|
-
return (relation === "" ||
|
|
159
|
-
(relation !== ".." &&
|
|
160
|
-
!relation.startsWith(`..${operations.sep}`) &&
|
|
161
|
-
!operations.isAbsolute(relation)));
|
|
162
|
-
};
|
|
163
|
-
const containsAny = (roots, candidate) => roots.some((root) => isPathContained(root, candidate));
|
|
164
|
-
const networkRank = (network) => {
|
|
165
|
-
switch (network) {
|
|
166
|
-
case "none":
|
|
167
|
-
return 0;
|
|
168
|
-
case "loopback":
|
|
169
|
-
return 1;
|
|
170
|
-
case "external":
|
|
171
|
-
return 2;
|
|
172
|
-
}
|
|
173
|
-
};
|
|
174
|
-
const isExpired = (grant, now) => grant.expires_at !== null && Date.parse(grant.expires_at) <= now.getTime();
|
|
175
|
-
const hasMissing = (missing) => Object.keys(missing).length > 0;
|
|
176
|
-
const uniqueSorted = (values) => [...new Set(values)].sort((left, right) => left.localeCompare(right));
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import { z } from "zod";
|
|
2
|
-
const processReactiveOutcomeSchema = z.enum([
|
|
3
|
-
"passed",
|
|
4
|
-
"predicate_timeout",
|
|
5
|
-
"scenario_deadline",
|
|
6
|
-
"ambiguous_match",
|
|
7
|
-
"action_rejected",
|
|
8
|
-
"target_lost",
|
|
9
|
-
"capture_incomplete",
|
|
10
|
-
"cancelled",
|
|
11
|
-
"cleanup_failed",
|
|
12
|
-
]);
|
|
13
|
-
const processReactiveTransitionShape = {
|
|
14
|
-
sequence: z.number().int().nonnegative(),
|
|
15
|
-
transition_id: z.string().min(1),
|
|
16
|
-
state_before: z.string().min(1),
|
|
17
|
-
trigger_event_ids: z.array(z.string().min(1)),
|
|
18
|
-
action_event_ids: z.array(z.string().min(1)),
|
|
19
|
-
action_types: z.array(z.enum([
|
|
20
|
-
"send_input",
|
|
21
|
-
"resize",
|
|
22
|
-
"close_stdin",
|
|
23
|
-
"send_signal",
|
|
24
|
-
"checkpoint",
|
|
25
|
-
])),
|
|
26
|
-
};
|
|
27
|
-
const processReactiveTransitionSchema = z.union([
|
|
28
|
-
z.object({
|
|
29
|
-
...processReactiveTransitionShape,
|
|
30
|
-
state_after: z.string().min(1),
|
|
31
|
-
outcome: z.null(),
|
|
32
|
-
}),
|
|
33
|
-
z.object({
|
|
34
|
-
...processReactiveTransitionShape,
|
|
35
|
-
state_after: z.null(),
|
|
36
|
-
outcome: z.literal("passed"),
|
|
37
|
-
}),
|
|
38
|
-
]);
|
|
39
|
-
const processReactiveRunShape = {
|
|
40
|
-
active_state: z.string().min(1),
|
|
41
|
-
controls: z
|
|
42
|
-
.array(z.object({
|
|
43
|
-
sequence: z.number().int().nonnegative(),
|
|
44
|
-
kind: z.enum([
|
|
45
|
-
"state_deadline",
|
|
46
|
-
"scenario_deadline",
|
|
47
|
-
"target_lost",
|
|
48
|
-
"cancelled",
|
|
49
|
-
"cleanup_failed",
|
|
50
|
-
]),
|
|
51
|
-
after_capture_order: z.number().int().min(-1),
|
|
52
|
-
}))
|
|
53
|
-
.default([]),
|
|
54
|
-
transitions: z.array(processReactiveTransitionSchema),
|
|
55
|
-
};
|
|
56
|
-
/** Serialized reactive reducer state admitted by process capture. */
|
|
57
|
-
export const processReactiveRunSchema = z.discriminatedUnion("status", [
|
|
58
|
-
z.object({
|
|
59
|
-
status: z.literal("running"),
|
|
60
|
-
outcome: z.null(),
|
|
61
|
-
...processReactiveRunShape,
|
|
62
|
-
}),
|
|
63
|
-
z.object({
|
|
64
|
-
status: z.literal("finished"),
|
|
65
|
-
outcome: processReactiveOutcomeSchema,
|
|
66
|
-
...processReactiveRunShape,
|
|
67
|
-
}),
|
|
68
|
-
]);
|
|
@@ -1,180 +0,0 @@
|
|
|
1
|
-
import canonicalize from "canonicalize";
|
|
2
|
-
import { projectProcessObservation, } from "./processObservation.js";
|
|
3
|
-
import { commitProcessReactiveProposal, createProcessReactiveSnapshot, reduceProcessReactiveScenario, } from "./processReactiveRuntime.js";
|
|
4
|
-
import { processReactiveScenarioSchema, } from "./processReactiveScenario.js";
|
|
5
|
-
const admittedCollection = (collection) => [
|
|
6
|
-
"frames",
|
|
7
|
-
"interaction_events",
|
|
8
|
-
"process_samples",
|
|
9
|
-
"filesystem_checkpoints",
|
|
10
|
-
"shim_events",
|
|
11
|
-
"protocol_events",
|
|
12
|
-
].includes(collection);
|
|
13
|
-
const reactiveObservations = (capture) => (capture.event_journal ?? []).flatMap((location) => {
|
|
14
|
-
if (!admittedCollection(location.collection))
|
|
15
|
-
return [];
|
|
16
|
-
const observation = projectProcessObservation(capture, location);
|
|
17
|
-
return observation === null ? [] : [observation];
|
|
18
|
-
});
|
|
19
|
-
const validateTransitionDeclaration = (transition, next, context) => {
|
|
20
|
-
const { index, scenario, require } = context;
|
|
21
|
-
const path = `reactive_run.transitions[${String(index)}]`;
|
|
22
|
-
const declared = scenario.states
|
|
23
|
-
.find(({ id }) => id === transition.state_before)
|
|
24
|
-
?.on.find(({ id }) => id === transition.transition_id);
|
|
25
|
-
require(declared !==
|
|
26
|
-
undefined, path, "reactive transition is not declared by its recorded source state");
|
|
27
|
-
if (declared !== undefined) {
|
|
28
|
-
const stateAfter = declared.target.kind === "goto" ? declared.target.state : null;
|
|
29
|
-
const outcome = declared.target.kind === "finish" ? declared.target.outcome : null;
|
|
30
|
-
require(transition.state_after === stateAfter &&
|
|
31
|
-
transition.outcome ===
|
|
32
|
-
outcome, path, "reactive transition target or outcome differs from the committed graph");
|
|
33
|
-
require(canonicalize(transition.action_types) ===
|
|
34
|
-
canonicalize(declared.actions.map(({ type }) => type)), `${path}.action_types`, "reactive transition actions differ from the committed graph");
|
|
35
|
-
}
|
|
36
|
-
require(transition.sequence ===
|
|
37
|
-
index, `${path}.sequence`, "reactive transition sequence must be contiguous from zero");
|
|
38
|
-
if (next !== undefined)
|
|
39
|
-
require(transition.state_after ===
|
|
40
|
-
next.state_before, `reactive_run.transitions[${String(index + 1)}].state_before`, "reactive transition states must be contiguous");
|
|
41
|
-
};
|
|
42
|
-
const validateTransitionDeclarations = (run, scenario, require) => {
|
|
43
|
-
require(run.transitions[0]?.state_before === scenario.initial_state ||
|
|
44
|
-
run.transitions.length ===
|
|
45
|
-
0, "reactive_run.transitions[0].state_before", "reactive transition journal must start at the declared initial state");
|
|
46
|
-
for (const [index, transition] of run.transitions.entries())
|
|
47
|
-
validateTransitionDeclaration(transition, run.transitions[index + 1], {
|
|
48
|
-
index,
|
|
49
|
-
scenario,
|
|
50
|
-
require,
|
|
51
|
-
});
|
|
52
|
-
};
|
|
53
|
-
const commitRecordedEffects = (options) => commitProcessReactiveProposal(options.scenario, options.proposal, options.recordedFailure === undefined
|
|
54
|
-
? options.proposal.effects.map((_, index) => {
|
|
55
|
-
const eventId = options.expected?.action_event_ids[index];
|
|
56
|
-
const observation = eventId === undefined
|
|
57
|
-
? undefined
|
|
58
|
-
: options.observations.get(eventId);
|
|
59
|
-
return observation === undefined
|
|
60
|
-
? { status: "rejected" }
|
|
61
|
-
: { status: "succeeded", observation };
|
|
62
|
-
})
|
|
63
|
-
: [
|
|
64
|
-
options.recordedFailure === "target_lost"
|
|
65
|
-
? { status: "target_lost" }
|
|
66
|
-
: { status: "rejected" },
|
|
67
|
-
], { committedSensitiveInputs: true });
|
|
68
|
-
const replayTransitions = (scenario, run, observations, require) => {
|
|
69
|
-
const observationsById = new Map(observations.map((observation) => [observation.event_id, observation]));
|
|
70
|
-
let snapshot = createProcessReactiveSnapshot(scenario);
|
|
71
|
-
let transitionIndex = 0;
|
|
72
|
-
const advance = (input) => {
|
|
73
|
-
let decision = reduceProcessReactiveScenario(scenario, snapshot, input);
|
|
74
|
-
if (decision.kind === "proposal") {
|
|
75
|
-
const proposal = decision;
|
|
76
|
-
decision = commitRecordedEffects({
|
|
77
|
-
scenario,
|
|
78
|
-
proposal: decision,
|
|
79
|
-
expected: run.transitions[transitionIndex],
|
|
80
|
-
observations: observationsById,
|
|
81
|
-
recordedFailure: run.transitions[transitionIndex] === undefined &&
|
|
82
|
-
decision.effects.length > 0 &&
|
|
83
|
-
(run.outcome === "action_rejected" || run.outcome === "target_lost")
|
|
84
|
-
? run.outcome
|
|
85
|
-
: undefined,
|
|
86
|
-
});
|
|
87
|
-
require(decision.kind !== "finished" ||
|
|
88
|
-
decision.outcome !== "action_rejected" ||
|
|
89
|
-
run.outcome ===
|
|
90
|
-
"action_rejected", `reactive_run.transitions[${String(transitionIndex)}].action_event_ids`, `recorded action observations do not match proposed effects: ${canonicalize({
|
|
91
|
-
effects: proposal.effects,
|
|
92
|
-
observations: run.transitions[transitionIndex]?.action_event_ids.map((eventId) => observationsById.get(eventId)),
|
|
93
|
-
})}`);
|
|
94
|
-
}
|
|
95
|
-
if (decision.kind === "transition") {
|
|
96
|
-
const expected = run.transitions[transitionIndex];
|
|
97
|
-
require(expected !== undefined &&
|
|
98
|
-
canonicalize(decision.record) ===
|
|
99
|
-
canonicalize(expected), `reactive_run.transitions[${String(transitionIndex)}]`, "reactive transition differs from deterministic journal replay");
|
|
100
|
-
transitionIndex += 1;
|
|
101
|
-
}
|
|
102
|
-
snapshot = decision.snapshot;
|
|
103
|
-
};
|
|
104
|
-
const advanceControl = (control, index) => {
|
|
105
|
-
require(snapshot.status !== "finished" ||
|
|
106
|
-
control.kind ===
|
|
107
|
-
"cleanup_failed", `reactive_run.controls[${String(index)}]`, "reactive control cannot follow a finished run");
|
|
108
|
-
advance(control.kind === "state_deadline"
|
|
109
|
-
? {
|
|
110
|
-
kind: control.kind,
|
|
111
|
-
state_id: snapshot.active_state,
|
|
112
|
-
state_entry_capture_order: snapshot.state_entry_capture_order,
|
|
113
|
-
}
|
|
114
|
-
: { kind: control.kind });
|
|
115
|
-
};
|
|
116
|
-
let controlIndex = 0;
|
|
117
|
-
for (const observation of observations) {
|
|
118
|
-
while ((run.controls[controlIndex]?.after_capture_order ??
|
|
119
|
-
Number.MAX_SAFE_INTEGER) < observation.capture_order) {
|
|
120
|
-
const control = run.controls[controlIndex];
|
|
121
|
-
if (control === undefined)
|
|
122
|
-
break;
|
|
123
|
-
advanceControl(control, controlIndex);
|
|
124
|
-
controlIndex += 1;
|
|
125
|
-
}
|
|
126
|
-
advance({ kind: "observation", observation });
|
|
127
|
-
}
|
|
128
|
-
for (; controlIndex < run.controls.length; controlIndex += 1) {
|
|
129
|
-
const control = run.controls[controlIndex];
|
|
130
|
-
if (control === undefined)
|
|
131
|
-
break;
|
|
132
|
-
advanceControl(control, controlIndex);
|
|
133
|
-
}
|
|
134
|
-
require(transitionIndex ===
|
|
135
|
-
run.transitions
|
|
136
|
-
.length, "reactive_run.transitions", `reactive transition journal is not reproduced by deterministic replay (replayed ${String(transitionIndex)} of ${String(run.transitions.length)}; outcome ${snapshot.outcome})`);
|
|
137
|
-
return snapshot;
|
|
138
|
-
};
|
|
139
|
-
const validateControls = (run, observations, require) => {
|
|
140
|
-
const admittedOrders = new Set([
|
|
141
|
-
-1,
|
|
142
|
-
...observations.map(({ capture_order }) => capture_order),
|
|
143
|
-
]);
|
|
144
|
-
for (const [index, control] of run.controls.entries()) {
|
|
145
|
-
require(control.sequence ===
|
|
146
|
-
index, `reactive_run.controls[${String(index)}].sequence`, "reactive control sequence must be contiguous");
|
|
147
|
-
require(admittedOrders.has(control.after_capture_order), `reactive_run.controls[${String(index)}].after_capture_order`, "reactive control cutoff must identify the last admitted observation");
|
|
148
|
-
const previous = run.controls.at(index - 1);
|
|
149
|
-
require(index === 0 ||
|
|
150
|
-
(previous !== undefined &&
|
|
151
|
-
control.after_capture_order >=
|
|
152
|
-
previous.after_capture_order), `reactive_run.controls[${String(index)}].after_capture_order`, "reactive control cutoffs must be ordered");
|
|
153
|
-
}
|
|
154
|
-
};
|
|
155
|
-
/** Validate one capture's reactive journal by replaying the production reducer. */
|
|
156
|
-
export const validateProcessCaptureReactiveRun = (capture, require) => {
|
|
157
|
-
const declared = capture.manifest.scenario["reactive"];
|
|
158
|
-
const run = capture.reactive_run;
|
|
159
|
-
const declaredReactive = declared !== undefined && declared !== null;
|
|
160
|
-
require(declaredReactive ===
|
|
161
|
-
(run !==
|
|
162
|
-
null), "reactive_run", "reactive result presence must match the committed scenario");
|
|
163
|
-
if (run === null)
|
|
164
|
-
return;
|
|
165
|
-
const parsed = processReactiveScenarioSchema.safeParse(declared);
|
|
166
|
-
require(parsed.success, "manifest.scenario.reactive", "committed reactive scenario does not satisfy its declared schema");
|
|
167
|
-
if (!parsed.success)
|
|
168
|
-
return;
|
|
169
|
-
require(run.status === "finished" &&
|
|
170
|
-
run.outcome !==
|
|
171
|
-
null, "reactive_run.outcome", "completed capture requires a finished reactive outcome");
|
|
172
|
-
validateTransitionDeclarations(run, parsed.data, require);
|
|
173
|
-
const observations = reactiveObservations(capture);
|
|
174
|
-
validateControls(run, observations, require);
|
|
175
|
-
const snapshot = replayTransitions(parsed.data, run, observations, require);
|
|
176
|
-
require(snapshot.outcome ===
|
|
177
|
-
run.outcome, "reactive_run.outcome", "reactive outcome differs from deterministic journal replay");
|
|
178
|
-
require(snapshot.active_state ===
|
|
179
|
-
run.active_state, "reactive_run.active_state", "reactive active state differs from deterministic journal replay");
|
|
180
|
-
};
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
/** Checkpoints guaranteed on every known path entering each reactive state. */
|
|
2
|
-
export const definitelyAvailableCheckpoints = (scenario) => {
|
|
3
|
-
const available = new Map([
|
|
4
|
-
[scenario.initial_state, new Set()],
|
|
5
|
-
]);
|
|
6
|
-
let changed = true;
|
|
7
|
-
while (changed) {
|
|
8
|
-
changed = false;
|
|
9
|
-
for (const state of scenario.states) {
|
|
10
|
-
const before = available.get(state.id);
|
|
11
|
-
if (before === undefined)
|
|
12
|
-
continue;
|
|
13
|
-
for (const transition of state.on) {
|
|
14
|
-
if (transition.target.kind !== "goto")
|
|
15
|
-
continue;
|
|
16
|
-
const after = new Set(before);
|
|
17
|
-
for (const name of transition.actions.flatMap((action) => action.type === "checkpoint" ? [action.name] : []))
|
|
18
|
-
after.add(name);
|
|
19
|
-
const prior = available.get(transition.target.state);
|
|
20
|
-
const next = prior === undefined
|
|
21
|
-
? after
|
|
22
|
-
: new Set([...prior].filter((name) => after.has(name)));
|
|
23
|
-
if (prior !== undefined && setsEqual(prior, next))
|
|
24
|
-
continue;
|
|
25
|
-
available.set(transition.target.state, next);
|
|
26
|
-
changed = true;
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
return available;
|
|
31
|
-
};
|
|
32
|
-
const setsEqual = (left, right) => left.size === right.size && [...left].every((value) => right.has(value));
|
|
@@ -1,196 +0,0 @@
|
|
|
1
|
-
import canonicalize from "canonicalize";
|
|
2
|
-
import { comparableProcessObservationPayload } from "./processObservation.js";
|
|
3
|
-
const noMatch = () => ({
|
|
4
|
-
eventIds: [],
|
|
5
|
-
consumeIds: [],
|
|
6
|
-
lastOrder: -1,
|
|
7
|
-
matched: false,
|
|
8
|
-
});
|
|
9
|
-
const frontierOrder = (frontier, snapshot) => {
|
|
10
|
-
switch (frontier.kind) {
|
|
11
|
-
case "scenario_start":
|
|
12
|
-
return -1;
|
|
13
|
-
case "state_entry":
|
|
14
|
-
return snapshot.state_entry_capture_order - 1;
|
|
15
|
-
case "checkpoint":
|
|
16
|
-
return (snapshot.checkpoints.findLast(({ name }) => name === frontier.name)
|
|
17
|
-
?.capture_order ?? null);
|
|
18
|
-
case "event_id":
|
|
19
|
-
return (snapshot.observations.find(({ event_id }) => event_id === frontier.event_id)?.capture_order ?? null);
|
|
20
|
-
}
|
|
21
|
-
};
|
|
22
|
-
const eligibleObservations = (frontier, context) => {
|
|
23
|
-
const frontierValue = frontierOrder(frontier, context.snapshot);
|
|
24
|
-
if (frontierValue === null)
|
|
25
|
-
return [];
|
|
26
|
-
const lowerBound = Math.max(frontierValue, context.afterOrder);
|
|
27
|
-
const consumed = new Set(context.snapshot.consumed_event_ids);
|
|
28
|
-
return context.snapshot.observations.filter(({ capture_order, event_id }) => capture_order > lowerBound &&
|
|
29
|
-
(context.upperOrder === null || capture_order <= context.upperOrder) &&
|
|
30
|
-
!consumed.has(event_id));
|
|
31
|
-
};
|
|
32
|
-
const canonicalJson = (value) => {
|
|
33
|
-
const serialized = canonicalize(value);
|
|
34
|
-
if (serialized === undefined)
|
|
35
|
-
throw new TypeError("Reactive scenario value is not canonical JSON");
|
|
36
|
-
return serialized;
|
|
37
|
-
};
|
|
38
|
-
const matchEvent = (trigger, context) => {
|
|
39
|
-
const expected = canonicalJson(comparableProcessObservationPayload(trigger.exact, trigger.ignore_fields));
|
|
40
|
-
const matches = [];
|
|
41
|
-
for (const observation of eligibleObservations(trigger.since, context)) {
|
|
42
|
-
if (observation.source === trigger.source &&
|
|
43
|
-
canonicalJson(comparableProcessObservationPayload(observation.payload, trigger.ignore_fields)) === expected)
|
|
44
|
-
matches.push(observation);
|
|
45
|
-
}
|
|
46
|
-
if (matches.length < trigger.cardinality.min ||
|
|
47
|
-
matches.length > trigger.cardinality.max)
|
|
48
|
-
return noMatch();
|
|
49
|
-
const eventIds = matches.map(({ event_id }) => event_id);
|
|
50
|
-
return {
|
|
51
|
-
eventIds,
|
|
52
|
-
consumeIds: trigger.consume ? eventIds : [],
|
|
53
|
-
lastOrder: matches.at(-1)?.capture_order ?? context.afterOrder,
|
|
54
|
-
matched: true,
|
|
55
|
-
};
|
|
56
|
-
};
|
|
57
|
-
const occurrenceRange = (haystack, needle, occurrence) => {
|
|
58
|
-
let offset = 0;
|
|
59
|
-
let start = -1;
|
|
60
|
-
for (let found = 0; found < occurrence; found += 1) {
|
|
61
|
-
start = haystack.indexOf(needle, offset);
|
|
62
|
-
if (start < 0)
|
|
63
|
-
return null;
|
|
64
|
-
offset = start + needle.length;
|
|
65
|
-
}
|
|
66
|
-
return { start, end: offset };
|
|
67
|
-
};
|
|
68
|
-
const matchTerminalText = (trigger, context) => {
|
|
69
|
-
const chunks = [];
|
|
70
|
-
for (const observation of eligibleObservations(trigger.since, context)) {
|
|
71
|
-
if (observation.source === "terminal_raw" &&
|
|
72
|
-
typeof observation.payload === "object" &&
|
|
73
|
-
observation.payload !== null &&
|
|
74
|
-
!Array.isArray(observation.payload) &&
|
|
75
|
-
typeof observation.payload["data"] === "string")
|
|
76
|
-
chunks.push({ observation, text: observation.payload["data"] });
|
|
77
|
-
}
|
|
78
|
-
const range = occurrenceRange(chunks.map(({ text }) => text).join(""), trigger.literal, trigger.occurrence);
|
|
79
|
-
if (range === null)
|
|
80
|
-
return noMatch();
|
|
81
|
-
let firstChunk = 0;
|
|
82
|
-
let lastChunk = 0;
|
|
83
|
-
let characters = 0;
|
|
84
|
-
for (const [index, chunk] of chunks.entries()) {
|
|
85
|
-
characters += chunk.text.length;
|
|
86
|
-
if (characters <= range.start)
|
|
87
|
-
firstChunk = index + 1;
|
|
88
|
-
if (characters >= range.end) {
|
|
89
|
-
lastChunk = index;
|
|
90
|
-
break;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
const matched = chunks
|
|
94
|
-
.slice(firstChunk, lastChunk + 1)
|
|
95
|
-
.map(({ observation }) => observation);
|
|
96
|
-
const eventIds = matched.map(({ event_id }) => event_id);
|
|
97
|
-
return {
|
|
98
|
-
eventIds,
|
|
99
|
-
consumeIds: trigger.consume ? eventIds : [],
|
|
100
|
-
lastOrder: matched.at(-1)?.capture_order ?? context.afterOrder,
|
|
101
|
-
matched: true,
|
|
102
|
-
};
|
|
103
|
-
};
|
|
104
|
-
const mergeMatches = (matches) => {
|
|
105
|
-
const eventIds = new Set();
|
|
106
|
-
const consumeIds = new Set();
|
|
107
|
-
let lastOrder = -1;
|
|
108
|
-
let matched = true;
|
|
109
|
-
for (const match of matches) {
|
|
110
|
-
for (const eventId of match.eventIds)
|
|
111
|
-
eventIds.add(eventId);
|
|
112
|
-
for (const eventId of match.consumeIds)
|
|
113
|
-
consumeIds.add(eventId);
|
|
114
|
-
lastOrder = Math.max(lastOrder, match.lastOrder);
|
|
115
|
-
matched &&= match.matched;
|
|
116
|
-
}
|
|
117
|
-
return {
|
|
118
|
-
eventIds: [...eventIds],
|
|
119
|
-
consumeIds: [...consumeIds],
|
|
120
|
-
lastOrder,
|
|
121
|
-
matched,
|
|
122
|
-
};
|
|
123
|
-
};
|
|
124
|
-
const matchEarliestPrefix = (trigger, context) => {
|
|
125
|
-
for (const observation of context.snapshot.observations) {
|
|
126
|
-
if (observation.capture_order <= context.afterOrder)
|
|
127
|
-
continue;
|
|
128
|
-
if (context.upperOrder !== null &&
|
|
129
|
-
observation.capture_order > context.upperOrder)
|
|
130
|
-
break;
|
|
131
|
-
const matched = matchTrigger(trigger, {
|
|
132
|
-
...context,
|
|
133
|
-
upperOrder: observation.capture_order,
|
|
134
|
-
});
|
|
135
|
-
if (matched.matched)
|
|
136
|
-
return matched;
|
|
137
|
-
}
|
|
138
|
-
return noMatch();
|
|
139
|
-
};
|
|
140
|
-
const matchTrigger = (trigger, context) => {
|
|
141
|
-
if (trigger.kind === "event")
|
|
142
|
-
return matchEvent(trigger, context);
|
|
143
|
-
if (trigger.kind === "terminal_text")
|
|
144
|
-
return matchTerminalText(trigger, context);
|
|
145
|
-
if (trigger.kind === "all")
|
|
146
|
-
return mergeMatches(trigger.triggers.map((child) => matchTrigger(child, context)));
|
|
147
|
-
if (trigger.kind === "any") {
|
|
148
|
-
const evaluated = trigger.triggers.map((child) => matchTrigger(child, context));
|
|
149
|
-
const matches = evaluated.filter(({ matched }) => matched);
|
|
150
|
-
return matches.length === 0 ? noMatch() : mergeMatches(matches);
|
|
151
|
-
}
|
|
152
|
-
if (trigger.kind === "sequence") {
|
|
153
|
-
const matches = [];
|
|
154
|
-
let cursor = context.afterOrder;
|
|
155
|
-
for (const child of trigger.triggers) {
|
|
156
|
-
const matched = matchEarliestPrefix(child, {
|
|
157
|
-
...context,
|
|
158
|
-
afterOrder: cursor,
|
|
159
|
-
});
|
|
160
|
-
if (!matched.matched)
|
|
161
|
-
return noMatch();
|
|
162
|
-
matches.push(matched);
|
|
163
|
-
cursor = matched.lastOrder;
|
|
164
|
-
}
|
|
165
|
-
return mergeMatches(matches);
|
|
166
|
-
}
|
|
167
|
-
const matches = [];
|
|
168
|
-
let cursor = context.afterOrder;
|
|
169
|
-
while (matches.length < trigger.max) {
|
|
170
|
-
const matched = matchEarliestPrefix(trigger.trigger, {
|
|
171
|
-
...context,
|
|
172
|
-
afterOrder: cursor,
|
|
173
|
-
});
|
|
174
|
-
if (!matched.matched || matched.lastOrder <= cursor)
|
|
175
|
-
break;
|
|
176
|
-
matches.push(matched);
|
|
177
|
-
cursor = matched.lastOrder;
|
|
178
|
-
}
|
|
179
|
-
if (matches.length === trigger.max) {
|
|
180
|
-
const excess = matchEarliestPrefix(trigger.trigger, {
|
|
181
|
-
...context,
|
|
182
|
-
afterOrder: cursor,
|
|
183
|
-
});
|
|
184
|
-
if (excess.matched)
|
|
185
|
-
return noMatch();
|
|
186
|
-
}
|
|
187
|
-
if (matches.length < trigger.min)
|
|
188
|
-
return noMatch();
|
|
189
|
-
return mergeMatches(matches);
|
|
190
|
-
};
|
|
191
|
-
/** Match one trigger against every eligible retained observation. */
|
|
192
|
-
export const matchProcessReactiveTrigger = (trigger, snapshot) => matchTrigger(trigger, {
|
|
193
|
-
snapshot,
|
|
194
|
-
afterOrder: -1,
|
|
195
|
-
upperOrder: null,
|
|
196
|
-
});
|