rea-agents 6.1.0 → 6.2.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 +7 -5
- package/bridge/ghidra/ReaGhidraBridge.java +32 -4
- package/bridge/hopper_bridge.py +6 -1
- package/dist/android/JadxConfiguration.js +87 -7
- package/dist/android/JadxMcpTransport.js +14 -2
- package/dist/android/JadxProvider.js +57 -35
- package/dist/application/BinaryTargetResolver.js +5 -3
- package/dist/application/BrowserEvidence.js +3 -8
- package/dist/application/BrowserScenarioEvidence.js +2 -18
- package/dist/application/CapabilityInventory.js +43 -9
- package/dist/application/ClientConfigurationDocument.js +69 -25
- package/dist/application/DirectAnalysis.js +29 -14
- package/dist/application/DirectAnalysisCleanup.js +72 -0
- package/dist/application/DirectAnalysisStatus.js +4 -5
- package/dist/application/Doctor.js +15 -19
- package/dist/application/DoctorDiagnostics.js +1 -2
- package/dist/application/EnhancedTools.js +51 -6
- package/dist/application/EvidenceBundleFiles.js +8 -3
- package/dist/application/InvestigationProviders.js +9 -1
- package/dist/application/JsonFiles.js +42 -9
- package/dist/application/LinuxHopper.js +9 -6
- package/dist/application/MacHopper.js +15 -18
- package/dist/application/RealHopperAssertions.js +0 -11
- package/dist/application/ReconstructionObligationCandidates.js +1 -1
- package/dist/application/ReferenceSourceImportEntries.js +1 -1
- package/dist/application/Setup.js +8 -16
- package/dist/application/SetupHost.js +16 -27
- package/dist/application/SetupPlan.js +6 -6
- package/dist/application/Uninstall.js +81 -29
- package/dist/application/UpdateMaintenance.js +7 -5
- package/dist/application/UpdateRuntime.js +12 -12
- package/dist/application/WebScriptExportService.js +30 -4
- package/dist/application/WorkflowEvidence.js +25 -2
- package/dist/application/XrefsAddressResolution.js +45 -0
- package/dist/application/analysisView/AnalysisViewService.js +76 -0
- package/dist/application/binary/AnalysisClientCleanup.js +30 -5
- package/dist/application/binary/AnalysisProviderEvaluation.js +1 -2
- package/dist/application/binary/AnalysisProviderRegistry.js +2 -6
- package/dist/application/binary/AnalysisSnapshotCache.js +10 -8
- package/dist/application/binary/BinarySession.js +70 -29
- package/dist/application/binary/BinarySessionComposition.js +1 -3
- package/dist/application/binary/BinarySessionExecution.js +3 -5
- package/dist/application/binary/BinarySessionOpen.js +1 -1
- package/dist/application/binary/BinarySessionRecords.js +1 -1
- package/dist/application/binary/BinarySessionStatus.js +1 -6
- package/dist/application/binary/CompositeProvider.js +4 -18
- package/dist/application/binary/LazyAnalysisProvider.js +5 -5
- package/dist/application/binary/SessionProviderRouter.js +27 -135
- package/dist/application/homebrew.js +48 -0
- package/dist/application/javascript/ElectronActiveEvidence.js +9 -13
- package/dist/application/javascript/JavaScriptApplicationEvidence.js +2 -6
- package/dist/application/javascript/JavaScriptApplicationService.js +6 -1
- package/dist/application/javascript/JavaScriptArtifactAnalysis.js +5 -3
- package/dist/application/javascript/JavaScriptArtifactGraphBuilder.js +11 -9
- package/dist/application/javascript/JavaScriptArtifactGraphBundlers.js +11 -3
- package/dist/application/javascript/JavaScriptArtifactGraphContext.js +9 -0
- package/dist/application/javascript/JavaScriptArtifactGraphDocuments.js +8 -5
- package/dist/application/javascript/JavaScriptArtifactGraphFindings.js +12 -3
- package/dist/application/javascript/JavaScriptArtifactGraphStructure.js +0 -1
- package/dist/application/javascript/JavaScriptArtifactPathResolution.js +43 -16
- package/dist/application/javascript/JavaScriptArtifactReconstruction.js +46 -6
- package/dist/application/javascript/JavaScriptModuleRelationships.js +1 -1
- package/dist/application/javascript/JavaScriptRuntimeObservationService.js +3 -3
- package/dist/application/javascript/JavaScriptSemanticGraphAsyncProjection.js +2 -3
- package/dist/application/javascript/JavaScriptSemanticGraphChildProcessProjection.js +1 -2
- package/dist/application/javascript/JavaScriptSemanticGraphDataProjection.js +2 -3
- package/dist/application/javascript/JavaScriptSemanticGraphFlowProjection.js +1 -5
- package/dist/application/javascript/JavaScriptSemanticGraphObjectProjection.js +75 -46
- package/dist/application/javascript/JavaScriptSemanticGraphResourceProjection.js +2 -3
- package/dist/application/javascript/JavaScriptSemanticGraphValueProjection.js +42 -19
- package/dist/application/managed/ManagedMemberComparisonService.js +2 -1
- package/dist/application/managed/ManagedNativeVerificationService.js +2 -1
- package/dist/application/process/ProcessCli.js +11 -11
- package/dist/application/process/ProcessEvidence.js +0 -1
- package/dist/artifacts/ArtifactProvider.js +39 -14
- package/dist/artifacts/ArtifactReader.js +31 -0
- package/dist/artifacts/DirectoryArtifactReader.js +2 -1
- package/dist/artifacts/MachOSliceArtifactReader.js +9 -2
- package/dist/artifacts/NativeDmgArtifactReader.js +65 -20
- package/dist/artifacts/SafeOutputTree.js +16 -2
- package/dist/artifacts/ZipArtifactReader.js +11 -4
- package/dist/artifacts/apple/AppleAssetCatalogAnalysis.js +4 -2
- package/dist/artifacts/apple/DylibResolutionReader.js +17 -7
- package/dist/artifacts/apple/KeyedArchiveReader.js +21 -3
- package/dist/artifacts/extraction/ArtifactExtraction.js +78 -21
- package/dist/artifacts/inventory/ArtifactGraphConstruction.js +67 -61
- package/dist/artifacts/inventory/ArtifactInventory.js +0 -1
- package/dist/artifacts/inventory/reader.js +3 -3
- package/dist/artifacts/inventory/scanCanonical.js +48 -24
- package/dist/artifacts/inventory/scanReader.js +5 -9
- package/dist/browser/BrowserScenarioPartialObservation.js +106 -0
- package/dist/browser/CdpBrowserProvider.js +2 -3
- package/dist/browser/CdpCaptureEventHandlers.js +2 -4
- package/dist/browser/CdpCaptureEvents.js +0 -1
- package/dist/browser/CdpCaptureValues.js +20 -0
- package/dist/browser/CdpElectronProvider.js +0 -2
- package/dist/browser/CdpElectronScriptEvents.js +2 -8
- package/dist/browser/CdpElectronScripts.js +2 -3
- package/dist/browser/CdpPageCaptureScripts.js +2 -3
- package/dist/browser/CdpSafeMetadata.js +10 -10
- package/dist/browser/PlaywrightBrowserScenarioProvider.js +59 -44
- package/dist/browser/PlaywrightElectronActiveActions.js +2 -56
- package/dist/browser/PlaywrightElectronActiveProvider.js +10 -6
- package/dist/browser/PlaywrightScenarioArtifacts.js +1 -1
- package/dist/browser/PlaywrightScenarioBrowser.js +139 -39
- package/dist/browser/PlaywrightScenarioEvents.js +1 -1
- package/dist/browser/PlaywrightScenarioSession.js +39 -22
- package/dist/browser/assets/ScriptCaptureAdapters.js +1 -1
- package/dist/browser/history/CaptureFailures.js +6 -2
- package/dist/browser/history/MitmproxyCaptureAdapter.js +4 -2
- package/dist/catalogIdentity.js +0 -1
- package/dist/cli/analysisViewCommands.js +36 -0
- package/dist/cli/artifactCommands.js +11 -12
- package/dist/cli/coreAnalysisCommands.js +3 -3
- package/dist/cli/coreBinaryCommands.js +32 -27
- package/dist/cli/coreNativeCommands.js +9 -10
- package/dist/cli/electronCommands.js +4 -4
- package/dist/cli/interactiveSetup.js +6 -6
- package/dist/cli/managedCommands.js +7 -8
- package/dist/cli/nativeCallCommands.js +1 -2
- package/dist/cli/omittableDefaults.js +50 -0
- package/dist/cli/processCommands.js +3 -2
- package/dist/cli/setupCommands.js +16 -15
- package/dist/cli/utilityCommands.js +9 -9
- package/dist/cli.js +16 -8
- package/dist/cliBrowserScenarioCommands.js +2 -2
- package/dist/cliCommandNames.js +1 -0
- package/dist/cliJsonInput.js +15 -1
- package/dist/cliOutput.js +0 -38
- package/dist/composition/auxiliaryAnalysisProviders.js +27 -23
- package/dist/composition/binary.js +9 -9
- package/dist/composition/browserScenario.js +2 -1
- package/dist/composition/directAnalysis.js +20 -13
- package/dist/composition/electronScenario.js +1 -1
- package/dist/composition/optionalObservationProviders.js +12 -7
- package/dist/config/environment.js +6 -0
- package/dist/config/ghidraStartupTimeout.js +4 -9
- package/dist/config/homeDirectory.js +12 -0
- package/dist/config/mcpResponseBudget.js +9 -1
- package/dist/config/parseConfig.js +7 -3
- package/dist/config/parsers.js +19 -22
- package/dist/contracts/analysisViewToolContracts.js +56 -0
- package/dist/contracts/applicationToolContracts.js +5 -4
- package/dist/contracts/artifactComparisonExample.js +2 -2
- package/dist/contracts/artifactToolContracts.js +1 -1
- package/dist/contracts/browserScenarioToolContracts.js +1 -1
- package/dist/contracts/browserToolContracts.js +19 -15
- package/dist/contracts/enhancedInputs.js +2 -2
- package/dist/contracts/enhancedToolContracts.js +4 -3
- package/dist/contracts/evm/evmToolContracts.js +1 -1
- package/dist/contracts/functionWorkflowToolContracts.js +1 -1
- package/dist/contracts/inputSchemaPresentation.js +90 -0
- package/dist/contracts/investigationExamples.js +4 -3
- package/dist/contracts/javascript/electronToolContracts.js +1 -1
- package/dist/contracts/javascript/javascriptApplicationWorkflowExamples.js +0 -20
- package/dist/contracts/javascript/javascriptExportShapeComparisonExample.js +245 -0
- package/dist/contracts/javascript/javascriptRuntimeObservationToolContracts.js +1 -1
- package/dist/contracts/managed/managedToolContracts.js +5 -10
- package/dist/contracts/managed/managedWorkflowToolContracts.js +1 -1
- package/dist/contracts/mobileApplicationGraphExamples.js +3 -3
- package/dist/contracts/native/binaryDiagnosticsToolContracts.js +1 -1
- package/dist/contracts/native/nativeToolContracts.js +2 -2
- package/dist/contracts/officialToolContracts.js +2 -1
- package/dist/contracts/promptContracts.js +2 -2
- package/dist/contracts/providerSelection.js +1 -1
- package/dist/contracts/sessionToolContracts.js +14 -2
- package/dist/contracts/sessionToolSchemas.js +1 -14
- package/dist/contracts/toolContracts.js +2 -0
- package/dist/contracts/toolEffects.js +1 -0
- package/dist/contracts/toolOutputSchemaGroups.js +136 -92
- package/dist/contracts/toolOutputSchemaPrimitives.js +11 -21
- package/dist/contracts/toolSchemaMetadata.js +18 -69
- package/dist/contracts/webNetworkCaptureToolContracts.js +1 -1
- package/dist/contracts/webRuntimeToolContracts.js +1 -1
- package/dist/contracts/webScriptToolContracts.js +1 -1
- package/dist/doctorRuntime.js +7 -5
- package/dist/domain/analysisErrorCore.js +3 -0
- package/dist/domain/analysisErrorPresentation.js +18 -3
- package/dist/domain/analysisErrorProjection.js +24 -5
- package/dist/domain/analysisSnapshot.js +29 -31
- package/dist/domain/analysisView/analysisView.js +243 -0
- package/dist/domain/analysisView/analysisViewCoverage.js +19 -0
- package/dist/domain/analysisView/binaryLayoutView.js +159 -0
- package/dist/domain/analysisView/javascriptApplicationView.js +238 -0
- package/dist/domain/android/androidApplication.js +1 -1
- package/dist/domain/apple/appleApplication.js +1 -1
- package/dist/domain/apple/dylibResolution.js +10 -3
- package/dist/domain/apple/interfaceBuilderGraph.js +0 -1
- package/dist/domain/apple/keyedArchive.js +26 -2
- package/dist/domain/artifactComparison.js +15 -6
- package/dist/domain/artifactGraph.js +16 -3
- package/dist/domain/artifactInventoryEvidence.js +9 -16
- package/dist/domain/artifactOperationError.js +3 -3
- package/dist/domain/artifactPartialObservation.js +1 -0
- package/dist/domain/artifactPathSyntax.js +49 -0
- package/dist/domain/binaryTarget.js +39 -13
- package/dist/domain/browserCaptureComparison.js +13 -49
- package/dist/domain/browserNetworkEvidence.js +10 -4
- package/dist/domain/browserObservation.js +0 -1
- package/dist/domain/browserObservationSchemas.js +14 -3
- package/dist/domain/browserScenario.js +0 -1
- package/dist/domain/browserScenarioCapture.js +1 -2
- package/dist/domain/browserScenarioDiff.js +0 -2
- package/dist/domain/browserScenarioDiffEvidence.js +0 -12
- package/dist/domain/browserScenarioDiffValues.js +2 -2
- package/dist/domain/browserScenarioValues.js +3 -4
- package/dist/domain/callPath.js +8 -9
- package/dist/domain/callPathSchemas.js +2 -2
- package/dist/domain/changedBehavior.js +3 -3
- package/dist/domain/completionLedgerGeneration.js +2 -1
- package/dist/domain/configurationErrors.js +12 -0
- package/dist/domain/conformancePackage.js +4 -3
- package/dist/domain/evidence.js +10 -36
- package/dist/domain/evidenceBundle.js +7 -9
- package/dist/domain/evidenceCompletionLedger.js +2 -1
- package/dist/domain/functionComparison.js +4 -5
- package/dist/domain/functionComparisonDimensions.js +120 -87
- package/dist/domain/functionComparisonNormalization.js +23 -34
- package/dist/domain/functionComparisonResults.js +1 -4
- package/dist/domain/functionComparisonSchemas.js +2 -8
- package/dist/domain/functionDossierEvidence.js +2 -37
- package/dist/domain/javascript/electronActiveObservation.js +26 -69
- package/dist/domain/javascript/electronObservation.js +14 -3
- package/dist/domain/javascript/electronStaticAnalysisBrowser.js +10 -9
- package/dist/domain/javascript/electronStaticAnalysisIpc.js +2 -1
- package/dist/domain/javascript/electronStaticAnalysisNative.js +2 -1
- package/dist/domain/javascript/javascriptApplicationEvidenceSchemas.js +2 -0
- package/dist/domain/javascript/javascriptApplicationGraph.js +26 -3
- package/dist/domain/javascript/javascriptApplicationGraphSchemas.js +9 -2
- package/dist/domain/javascript/javascriptApplicationVersionItems.js +5 -2
- package/dist/domain/javascript/javascriptApplicationVersionKeys.js +2 -1
- package/dist/{application/javascript/JavaScriptReturnShapeProjection.js → domain/javascript/javascriptExportReturnShapeProjection.js} +4 -4
- package/dist/domain/javascript/javascriptExportShapeComparison.js +7 -1
- package/dist/domain/javascript/javascriptExportShapeComparisonIdentity.js +6 -1
- package/dist/domain/javascript/javascriptExportShapeComparisonSchemas.js +29 -1
- package/dist/domain/javascript/javascriptExportShapeSelection.js +5 -5
- package/dist/domain/javascript/javascriptExportShapeVariants.js +67 -14
- package/dist/domain/javascript/javascriptFeatureSeed.js +20 -0
- package/dist/domain/javascript/javascriptFeatureTraversal.js +0 -1
- package/dist/domain/javascript/javascriptNativeHandoff.js +1 -1
- package/dist/domain/javascript/javascriptRuntimeLoadState.js +0 -1
- package/dist/domain/javascript/javascriptRuntimeObservation.js +10 -2
- package/dist/domain/javascript/javascriptRuntimeReconciliationMatching.js +1 -1
- package/dist/domain/javascript/javascriptRuntimeReconciliationParsing.js +3 -2
- package/dist/domain/javascript/javascriptRuntimeStaticCandidates.js +0 -1
- package/dist/domain/javascript/javascriptSemanticAnalysis.js +9 -3
- package/dist/domain/javascript/javascriptSemanticAsyncEffects.js +2 -1
- package/dist/domain/javascript/javascriptSemanticCalls.js +2 -1
- package/dist/domain/javascript/javascriptSemanticChildProcesses.js +2 -1
- package/dist/domain/javascript/javascriptSemanticDataEffects.js +1 -1
- package/dist/domain/javascript/javascriptSemanticGraph.js +88 -46
- package/dist/domain/javascript/javascriptSemanticMemberMutations.js +77 -20
- package/dist/domain/javascript/javascriptSemanticMutationValues.js +21 -27
- package/dist/domain/javascript/javascriptSemanticObjects.js +83 -42
- package/dist/domain/javascript/javascriptSemanticPrimitives.js +1 -12
- package/dist/domain/javascript/javascriptSemanticProjection.js +2 -3
- package/dist/domain/javascript/javascriptSemanticPromises.js +2 -1
- package/dist/domain/javascript/javascriptSemanticResourceLimits.js +1 -1
- package/dist/domain/javascript/javascriptSemanticResources.js +1 -1
- package/dist/domain/javascript/javascriptSemanticReturns.js +32 -17
- package/dist/domain/javascript/javascriptSemanticSlots.js +72 -0
- package/dist/domain/javascript/javascriptSemanticValues.js +47 -54
- package/dist/domain/javascript/javascriptSourceMapPaths.js +104 -0
- package/dist/domain/javascript/javascriptStaticAnalysisCalls.js +2 -1
- package/dist/domain/javascript/javascriptStaticAnalysisHelpers.js +0 -1
- package/dist/domain/javascript/sourceToBundleComparison.js +12 -3
- package/dist/domain/javascript/sourceToBundleSignals.js +47 -19
- package/dist/domain/localPath.js +1 -1
- package/dist/domain/managed/managedArtifact.js +6 -4
- package/dist/domain/managed/managedMemberComparison.js +2 -9
- package/dist/domain/managed/managedNativeVerification.js +0 -2
- package/dist/domain/managed/managedNativeVerificationMatch.js +9 -3
- package/dist/domain/native/binaryLayout.js +2 -3
- package/dist/domain/native/nativeApiBoundary.js +1 -1
- package/dist/domain/native/nativeCallObservation.js +5 -3
- package/dist/domain/native/nativeInstruction.js +7 -0
- package/dist/domain/native/recordedCrash.js +2 -3
- package/dist/domain/offsetDateTime.js +17 -0
- package/dist/domain/process/processCapture.js +13 -12
- package/dist/domain/process/processCaptureCoverage.js +67 -0
- package/dist/domain/process/processCaptureExample.js +2 -1
- package/dist/domain/process/processCaptureParsing.js +1 -34
- package/dist/domain/process/processCaptureValidation.js +81 -13
- package/dist/domain/process/processComparison.js +41 -22
- package/dist/domain/process/processObservation.js +10 -2
- package/dist/domain/process/processScenario.js +24 -2
- package/dist/domain/process/processTraceComparison.js +0 -2
- package/dist/domain/process/processTraceDimensionProjection.js +1 -1
- package/dist/domain/process/processTraceEvaluation.js +15 -11
- package/dist/domain/process/processTraceSpecification.js +3 -4
- package/dist/domain/providerAdapterError.js +2 -0
- package/dist/domain/reconstructionCoverage.js +5 -2
- package/dist/domain/reconstructionObligationLedgerSchemas.js +2 -1
- package/dist/domain/reconstructionReadinessSchemas.js +2 -1
- package/dist/domain/reconstructionVerification.js +3 -3
- package/dist/domain/reconstructionVerificationSchemas.js +2 -1
- package/dist/domain/referenceSourceGraph.js +20 -21
- package/dist/domain/staticRuntimeCorrelation.js +2 -2
- package/dist/domain/stringPatterns.js +6 -0
- package/dist/domain/swiftSymbolClassification.js +61 -0
- package/dist/domain/symbolAnalysis.js +66 -18
- package/dist/domain/webCaptureDiff.js +0 -1
- package/dist/domain/webCaptureDiffSchemas.js +6 -3
- package/dist/domain/webEventListeners.js +3 -2
- package/dist/domain/webExecution.js +3 -2
- package/dist/domain/webRuntime.js +0 -2
- package/dist/domain/webScriptExport.js +1 -1
- package/dist/dotnet/ManagedArtifactInspector.js +2 -19
- package/dist/dotnet/ManagedMemberInspector.js +12 -18
- package/dist/dotnet/ManagedMemberInspectorCore.js +47 -44
- package/dist/dotnet/ManagedMemberRows.js +75 -62
- package/dist/dotnet/ManagedMetadataInventory.js +16 -22
- package/dist/dotnet/ManagedMethodBodyReader.js +4 -0
- package/dist/dotnet/ManagedNativeBoundaryHelpers.js +109 -94
- package/dist/dotnet/ManagedNativeBoundaryInspector.js +12 -21
- package/dist/dotnet/ManagedReaderFailure.js +16 -0
- package/dist/dotnet/ManagedStaticProvider.js +3 -5
- package/dist/evaluation/AgentEvaluationFixtures.js +250 -0
- package/dist/evaluation/AgentEvaluationReport.js +28 -0
- package/dist/evaluation/CodexAgentEval.js +12 -8
- package/dist/evaluation/KnownAnswerEvaluation.js +281 -0
- package/dist/evm/EvmoleInterfaceProvider.js +2 -1
- package/dist/firmware/FirmwareCommand.js +9 -5
- package/dist/firmware/FirmwareProvider.js +4 -4
- package/dist/generatedPackageMetadata.js +2 -2
- package/dist/ghidra/GhidraAnalysisProfile.js +3 -6
- package/dist/ghidra/GhidraClient.js +91 -32
- package/dist/ghidra/GhidraClientStartup.js +0 -2
- package/dist/ghidra/GhidraDoctor.js +6 -5
- package/dist/ghidra/GhidraFunctionValues.js +3 -5
- package/dist/ghidra/GhidraInstallation.js +40 -12
- package/dist/ghidra/GhidraJavaLaunch.js +6 -2
- package/dist/ghidra/GhidraLauncher.js +15 -7
- package/dist/ghidra/GhidraProvider.js +6 -2
- package/dist/ghidra/GhidraProviderCapabilities.js +6 -0
- package/dist/ghidra/GhidraProviderClient.js +13 -3
- package/dist/ghidra/GhidraSessionError.js +2 -0
- package/dist/ghidra/GhidraSessionRoot.js +39 -0
- package/dist/ghidra/extensions/GhidraExtensions.js +17 -10
- package/dist/ghidra/extensions/nativeaot/NativeAotAdapter.js +8 -2
- package/dist/hopper/BridgeLauncher.js +34 -45
- package/dist/hopper/HopperAnalysisProfile.js +3 -8
- package/dist/hopper/HopperCleanup.js +56 -27
- package/dist/hopper/HopperClient.js +86 -65
- package/dist/hopper/HopperMachOImage.js +3 -2
- package/dist/hopper/HopperProvider.js +16 -18
- package/dist/hopper/HopperRegexSearch.js +3 -6
- package/dist/hopper/HopperTargetLease.js +132 -49
- package/dist/hopper/LinuxPrivateDisplayProbe.js +6 -0
- package/dist/ida/IdaConfiguration.js +8 -3
- package/dist/ida/IdaInput.js +1 -7
- package/dist/ida/IdaMcpConnection.js +8 -4
- package/dist/ida/IdaOperationRunner.js +3 -3
- package/dist/ida/IdaProvider.js +8 -12
- package/dist/ida/IdaSessionClient.js +20 -18
- package/dist/ida/IdaWorkspace.js +12 -13
- package/dist/inspector/V8InspectorCaptureProjection.js +1 -1
- package/dist/inspector/V8InspectorProvider.js +38 -28
- package/dist/javascript/recovery/WakaruCommand.js +7 -2
- package/dist/javascript/recovery/WakaruExecution.js +5 -2
- package/dist/main/shutdown.js +11 -3
- package/dist/main/startup.js +9 -2
- package/dist/main/transport.js +22 -2
- package/dist/main.js +11 -18
- package/dist/native/AppleMachoSelection.js +16 -6
- package/dist/native/CommandRunner.js +9 -7
- package/dist/native/LldbCallTracer.js +8 -2
- package/dist/native/NativeMacOSProvider.js +25 -15
- package/dist/native/NativeUiHelperRuntime.js +11 -2
- package/dist/native/NativeUiObservation.js +2 -2
- package/dist/native/pwntools/PwntoolsDecoder.js +2 -1
- package/dist/process/DarwinProcessRunTokenReader.js +16 -2
- package/dist/process/ExecFileOutput.js +88 -6
- package/dist/process/PrivateRuntimeRoot.js +10 -5
- package/dist/process/ProcessOwnership.js +1 -4
- package/dist/process/ProcessOwnershipObservation.js +11 -5
- package/dist/process/ProviderProcess.js +1 -3
- package/dist/process/capture/FilesystemSnapshot.js +50 -13
- package/dist/process/capture/ProcessCaptureError.js +13 -0
- package/dist/process/capture/ProcessCaptureLifecycle.js +158 -70
- package/dist/process/capture/ProcessFilesystemEffects.js +33 -3
- package/dist/process/capture/ProcessHarness.js +21 -25
- package/dist/process/capture/ProcessNormalization.js +20 -2
- package/dist/process/capture/ProcessSampling.js +25 -2
- package/dist/process/capture/TerminalRenderer.js +14 -0
- package/dist/process/snapshotEnvironment.js +14 -0
- package/dist/server/EvidenceMcpServer.js +25 -14
- package/dist/server/createServer.js +49 -36
- package/dist/server/mcpClientMetadata.js +12 -5
- package/dist/server/promptCompletion.js +3 -8
- package/dist/server/registerAnalysisViewTool.js +15 -0
- package/dist/server/registerAndroidTools.js +2 -3
- package/dist/server/registerApplicationTools/compareExportShapes.js +4 -5
- package/dist/server/registerApplicationTools/compareSourceToBundle.js +4 -5
- package/dist/server/registerApplicationTools/compareVersions.js +4 -5
- package/dist/server/registerApplicationTools/coverage.js +1 -2
- package/dist/server/registerApplicationTools/helpers.js +1 -2
- package/dist/server/registerApplicationTools/obligationLedger.js +4 -5
- package/dist/server/registerApplicationTools/projectMobileApplicationGraph.js +3 -4
- package/dist/server/registerApplicationTools/traceFeature.js +4 -5
- package/dist/server/registerApplicationTools/traceSemantics.js +4 -5
- package/dist/server/registerArtifactComparisonTool.js +4 -5
- package/dist/server/registerBinaryDiagnosticsTools.js +2 -3
- package/dist/server/registerBrowserScenarioTool.js +3 -4
- package/dist/server/registerBrowserTools.js +13 -16
- package/dist/server/registerBundleComparisonTool.js +5 -6
- package/dist/server/registerCloseLifecycleTool.js +2 -3
- package/dist/server/registerElectronTools.js +10 -13
- package/dist/server/registerEnhancedTools.js +23 -23
- package/dist/server/registerEvidenceTools.js +3 -4
- package/dist/server/registerEvmTools.js +2 -3
- package/dist/server/registerFirmwareTools.js +2 -3
- package/dist/server/registerFunctionComparisonTool.js +7 -8
- package/dist/server/registerInvestigationTools.js +14 -15
- package/dist/server/registerJavaScriptRecoveryTool.js +2 -3
- package/dist/server/registerJavaScriptRuntimeObservationTools.js +6 -6
- package/dist/server/registerManagedWorkflowTools/compareManagedMembers.js +5 -6
- package/dist/server/registerManagedWorkflowTools/importManagedReconstruction.js +4 -5
- package/dist/server/registerManagedWorkflowTools/projectManagedApplicationGraph.js +6 -7
- package/dist/server/registerManagedWorkflowTools/verifyManagedNativeBoundaries.js +6 -7
- package/dist/server/registerOfficialTools.js +4 -19
- package/dist/server/registerProcessComparisonTool.js +8 -8
- package/dist/server/registerRecordedCrashTools.js +2 -3
- package/dist/server/registerSessionRecordTools.js +15 -19
- package/dist/server/registerSessionStatusTool.js +3 -4
- package/dist/server/registerSessionTools.js +12 -18
- package/dist/server/registerWebModuleTool.js +2 -3
- package/dist/server/registerWebNetworkCaptureTool.js +2 -3
- package/dist/server/registerWebRuntimeTools.js +4 -5
- package/dist/server/registerWebScriptTool.js +2 -3
- package/dist/server/registerWebSourceLocationTool.js +2 -3
- package/dist/server/toolResult.js +66 -94
- package/dist/server/toolResultEncoding.js +11 -10
- package/dist/windows/WindowsNativeLoader.js +1 -0
- package/dist/windows/WindowsOwnedProcess.js +60 -15
- package/dist/windows/WindowsPrivateRuntime.js +7 -8
- package/native/windows/README.md +3 -1
- package/native/windows/build/manifest.json +2 -2
- package/native/windows/build/rea-windows-x64.node +0 -0
- package/package.json +39 -30
- package/scripts/rea.mjs +3 -6
- package/skills/reverse-engineer-anything/SKILL.md +9 -8
- package/skills/reverse-engineer-anything/references/android-applications.md +6 -3
- package/skills/reverse-engineer-anything/references/evidence-workflows.md +8 -4
- package/skills/reverse-engineer-anything/references/javascript-applications.md +16 -6
- package/skills/reverse-engineer-anything/references/native-and-artifacts.md +9 -0
- package/dist/config.js +0 -1
- package/dist/contracts/browserCaptureToolInputSchema.js +0 -43
- package/dist/contracts/process/processCaptureExample.js +0 -2
- package/dist/contracts/toolOutputSchemas.js +0 -2
- package/dist/main/reload.js +0 -12
- package/dist/main/state.js +0 -3
- package/dist/server/sessionToolPolicies.js +0 -2
|
@@ -3,18 +3,22 @@ import { constants, statSync } from "node:fs";
|
|
|
3
3
|
import { open, mkdtemp, rm, stat } from "node:fs/promises";
|
|
4
4
|
import { tmpdir } from "node:os";
|
|
5
5
|
import { join } from "node:path";
|
|
6
|
-
import {
|
|
6
|
+
import { setTimeout as delay } from "node:timers/promises";
|
|
7
|
+
import { digestProcessCommitment, processComparisonContract, processScenarioCommitment, } from "../../domain/process/processScenario.js";
|
|
8
|
+
import { parseProcessCapture } from "../../domain/process/processCaptureParsing.js";
|
|
7
9
|
import { PRODUCT_IDENTITY } from "../../identity.js";
|
|
8
10
|
import { snapshotRoots } from "./FilesystemSnapshot.js";
|
|
9
11
|
import { classifyFilesystemEffects } from "./ProcessFilesystemEffects.js";
|
|
10
12
|
import { cleanupOwnedProcessGroup, verifyNoTokenOwnedProcesses, } from "../ProcessOwnership.js";
|
|
11
13
|
import { observeOwnedProcessGroup, prepareProcessOwnershipInspection, systemProcessOwnershipHost, } from "../ProcessOwnershipObservation.js";
|
|
12
|
-
import { describeProcessCaptureExecutionFailure, ProcessCaptureError, } from "./ProcessCaptureError.js";
|
|
14
|
+
import { describeProcessCaptureExecutionFailure, normalizeCaptureFailure, ProcessCaptureError, } from "./ProcessCaptureError.js";
|
|
13
15
|
import { assertNotCancelled } from "./ProcessScenarioRuntimeValidation.js";
|
|
14
16
|
import { normalizeProcessElapsedTime, normalizeProcessSamples, normalizeProcessText, } from "./ProcessNormalization.js";
|
|
15
17
|
import { PROCESS_PROVIDER } from "../../domain/process/processEvidenceProvider.js";
|
|
16
18
|
import { TerminalRenderer } from "./TerminalRenderer.js";
|
|
19
|
+
import { hasCaptureTruncation, } from "../../domain/process/processCaptureCoverage.js";
|
|
17
20
|
import { scheduleProcessInterval } from "./ProcessTimer.js";
|
|
21
|
+
import { partialProcessCaptureObservationSchema } from "../../domain/process/processCapture.js";
|
|
18
22
|
/** Seed explicit observation availability before capture completion begins. */
|
|
19
23
|
export const createProcessCaptureObservationBuffer = (options) => ({
|
|
20
24
|
target_pid: {
|
|
@@ -92,6 +96,9 @@ export const buildCaptureResult = (options) => {
|
|
|
92
96
|
const sensitiveInputUnknown = "Sensitive scripted input values are redacted from process capture Evidence.";
|
|
93
97
|
const filesystemObservationUnknown = "No filesystem observation paths were selected; filesystem effects remain unknown.";
|
|
94
98
|
const hasFilesystemObservations = options.scenario.filesystem_observation_paths.length > 0;
|
|
99
|
+
const filesystemEffects = classifyFilesystemEffects(options.before, options.after);
|
|
100
|
+
const hasUnknownFilesystemEffects = filesystemEffects.some(({ status }) => status === "unknown");
|
|
101
|
+
const incompleteFilesystemUnknown = "Path absence in incomplete enumeration or below an unfollowed symbolic link remains unknown.";
|
|
95
102
|
return {
|
|
96
103
|
manifest: options.manifest,
|
|
97
104
|
normalization: options.scenario.normalization,
|
|
@@ -111,8 +118,13 @@ export const buildCaptureResult = (options) => {
|
|
|
111
118
|
event_journal: options.eventJournal,
|
|
112
119
|
files_before: options.before.files,
|
|
113
120
|
files_after: options.after.files,
|
|
114
|
-
filesystem_effects:
|
|
115
|
-
truncated: options.
|
|
121
|
+
filesystem_effects: filesystemEffects,
|
|
122
|
+
truncated: options.truncationDetails === undefined
|
|
123
|
+
? options.truncated
|
|
124
|
+
: hasCaptureTruncation(options.truncationDetails),
|
|
125
|
+
...(options.truncationDetails === undefined
|
|
126
|
+
? {}
|
|
127
|
+
: { truncation_details: options.truncationDetails }),
|
|
116
128
|
limitations: [
|
|
117
129
|
"The executable digest is a prelaunch file sample; matching path metadata immediately after spawn does not prove an atomic operating-system image binding.",
|
|
118
130
|
"Process trees are sampled and may omit short-lived descendants.",
|
|
@@ -122,6 +134,10 @@ export const buildCaptureResult = (options) => {
|
|
|
122
134
|
"Filesystem observations are before/after snapshots, not syscall traces.",
|
|
123
135
|
"Inherited host environment variables are not recorded and may affect results.",
|
|
124
136
|
...(!hasFilesystemObservations ? [filesystemObservationUnknown] : []),
|
|
137
|
+
...(hasUnknownFilesystemEffects ? [incompleteFilesystemUnknown] : []),
|
|
138
|
+
...(options.truncationDetails === undefined
|
|
139
|
+
? []
|
|
140
|
+
: captureCoverageUnknowns(options.truncationDetails).map(({ reason }) => reason)),
|
|
125
141
|
...(hasSensitiveScriptedInput ? [sensitiveInputUnknown] : []),
|
|
126
142
|
],
|
|
127
143
|
residual_unknowns: [
|
|
@@ -149,12 +165,58 @@ export const buildCaptureResult = (options) => {
|
|
|
149
165
|
},
|
|
150
166
|
]
|
|
151
167
|
: []),
|
|
168
|
+
...(hasUnknownFilesystemEffects
|
|
169
|
+
? [
|
|
170
|
+
{
|
|
171
|
+
scope: "filesystem",
|
|
172
|
+
reason: incompleteFilesystemUnknown,
|
|
173
|
+
},
|
|
174
|
+
]
|
|
175
|
+
: []),
|
|
152
176
|
...(hasSensitiveScriptedInput
|
|
153
177
|
? [{ scope: "interaction", reason: sensitiveInputUnknown }]
|
|
154
178
|
: []),
|
|
179
|
+
...(options.truncationDetails === undefined
|
|
180
|
+
? []
|
|
181
|
+
: captureCoverageUnknowns(options.truncationDetails).filter(({ scope }) => scope !== "terminal")),
|
|
155
182
|
],
|
|
156
183
|
};
|
|
157
184
|
};
|
|
185
|
+
const captureCoverageUnknowns = (details) => {
|
|
186
|
+
const unknowns = [];
|
|
187
|
+
if (details.raw_terminal.observed_frames > details.raw_terminal.retained_frames)
|
|
188
|
+
unknowns.push({
|
|
189
|
+
scope: "terminal",
|
|
190
|
+
reason: "Raw PTY chunks exceeded output_bytes and were omitted; rendered states also lack those inputs. See truncation_details.raw_terminal.",
|
|
191
|
+
});
|
|
192
|
+
if (details.rendered_terminal.observed_frames >
|
|
193
|
+
details.rendered_terminal.retained_frames)
|
|
194
|
+
unknowns.push({
|
|
195
|
+
scope: "terminal",
|
|
196
|
+
reason: "Cumulative rendered state and visible-line bytes exceeded output_bytes; whole rendered frames were omitted. Raw PTY coverage is reported separately. See truncation_details.rendered_terminal.",
|
|
197
|
+
});
|
|
198
|
+
for (const [name, coverage] of [
|
|
199
|
+
["before", details.filesystem_before],
|
|
200
|
+
["after_settlement", details.filesystem_after],
|
|
201
|
+
]) {
|
|
202
|
+
if (coverage.enumeration_truncated)
|
|
203
|
+
unknowns.push({
|
|
204
|
+
scope: "filesystem",
|
|
205
|
+
reason: `Filesystem ${name} path enumeration was incomplete: ${coverage.enumeration_reasons.join(", ")}. See truncation_details.`,
|
|
206
|
+
});
|
|
207
|
+
if (coverage.hash_omissions.length > 0)
|
|
208
|
+
unknowns.push({
|
|
209
|
+
scope: "filesystem",
|
|
210
|
+
reason: `Filesystem ${name} omitted ${String(coverage.hash_omissions.length)} whole-file digests; per-path reasons and remaining file_bytes budget are in truncation_details.`,
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
if (details.process.sampling_partial)
|
|
214
|
+
unknowns.push({
|
|
215
|
+
scope: "process",
|
|
216
|
+
reason: "Process sampling stopped with incomplete observations; sample_limit is reported in truncation_details.process.",
|
|
217
|
+
});
|
|
218
|
+
return unknowns;
|
|
219
|
+
};
|
|
158
220
|
const identityFromStats = (stats) => ({
|
|
159
221
|
dev: stats.dev,
|
|
160
222
|
ino: stats.ino,
|
|
@@ -301,7 +363,8 @@ export const createRunManifest = async (scenario, startedAt, completedAt, execut
|
|
|
301
363
|
normalization_sha256: digestProcessCommitment(scenario.normalization),
|
|
302
364
|
};
|
|
303
365
|
};
|
|
304
|
-
export const observeSettlement = async (runId, processGroupIds, settleMs, recordEvent = () => undefined, platform = process.platform) => {
|
|
366
|
+
export const observeSettlement = async (runId, processGroupIds, settleMs, recordEvent = () => undefined, platform = process.platform, signal) => {
|
|
367
|
+
assertNotCancelled(signal);
|
|
305
368
|
if (platform === "win32") {
|
|
306
369
|
recordEvent("lifecycle", 1);
|
|
307
370
|
return { state: "unverifiable", elapsed_ms: 0 };
|
|
@@ -310,11 +373,9 @@ export const observeSettlement = async (runId, processGroupIds, settleMs, record
|
|
|
310
373
|
let consecutiveEmpty = 0;
|
|
311
374
|
let deadlineReached = false;
|
|
312
375
|
while (!deadlineReached) {
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
processGroupId,
|
|
317
|
-
})));
|
|
376
|
+
assertNotCancelled(signal);
|
|
377
|
+
const observations = await Promise.all([...new Set(processGroupIds)].map((processGroupId) => observeOwnedProcessGroup({ runId, leaderPid: processGroupId, processGroupId }, undefined, signal)));
|
|
378
|
+
assertNotCancelled(signal);
|
|
318
379
|
if (observations.some(({ state }) => state === "unverifiable")) {
|
|
319
380
|
recordEvent("lifecycle", 1);
|
|
320
381
|
return { state: "unverifiable", elapsed_ms: Date.now() - started };
|
|
@@ -331,7 +392,7 @@ export const observeSettlement = async (runId, processGroupIds, settleMs, record
|
|
|
331
392
|
deadlineReached = Date.now() - started >= settleMs;
|
|
332
393
|
if (deadlineReached)
|
|
333
394
|
break;
|
|
334
|
-
await
|
|
395
|
+
await delay(50, undefined, { signal });
|
|
335
396
|
}
|
|
336
397
|
recordEvent("lifecycle", 1);
|
|
337
398
|
return { state: "alive_at_deadline", elapsed_ms: Date.now() - started };
|
|
@@ -403,6 +464,50 @@ const verifyTokenOwnedProcessesUntilSettled = async (verify) => {
|
|
|
403
464
|
}
|
|
404
465
|
return result;
|
|
405
466
|
};
|
|
467
|
+
const releaseCapturedProcessGroup = async (ownership, host) => {
|
|
468
|
+
if (host.platform === "win32")
|
|
469
|
+
return {
|
|
470
|
+
state: "unverified",
|
|
471
|
+
reason: "owned process cleanup is unverifiable on Windows without process-job authority",
|
|
472
|
+
};
|
|
473
|
+
let outcome = {
|
|
474
|
+
state: "cleaned",
|
|
475
|
+
reason: null,
|
|
476
|
+
};
|
|
477
|
+
const unverified = [];
|
|
478
|
+
try {
|
|
479
|
+
const cleaned = await host.cleanupProcessGroup(ownership);
|
|
480
|
+
unverified.push(...(cleaned.unverified ?? []));
|
|
481
|
+
if (!cleaned.cleaned) {
|
|
482
|
+
outcome = { state: "unverified", reason: cleaned.reason };
|
|
483
|
+
}
|
|
484
|
+
else {
|
|
485
|
+
const verified = await verifyTokenOwnedProcessesUntilSettled(() => host.verifyTokenOwnedProcesses(ownership.runId, undefined, ownership.captureBaseline, ownership));
|
|
486
|
+
unverified.push(...(verified.unverified ?? []));
|
|
487
|
+
if (!verified.cleaned)
|
|
488
|
+
outcome = { state: "unverified", reason: verified.reason };
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
catch (cause) {
|
|
492
|
+
outcome = {
|
|
493
|
+
state: "failed",
|
|
494
|
+
reason: cause instanceof Error
|
|
495
|
+
? cause.message || cause.name || "owned process cleanup failed"
|
|
496
|
+
: "owned process cleanup failed",
|
|
497
|
+
};
|
|
498
|
+
}
|
|
499
|
+
return unverified.length === 0
|
|
500
|
+
? outcome
|
|
501
|
+
: {
|
|
502
|
+
...outcome,
|
|
503
|
+
unverified_processes: [
|
|
504
|
+
...new Map(unverified.map(({ pid, diagnostic }) => [
|
|
505
|
+
`${String(pid)}:${diagnostic}`,
|
|
506
|
+
{ pid, reason: diagnostic },
|
|
507
|
+
])).values(),
|
|
508
|
+
],
|
|
509
|
+
};
|
|
510
|
+
};
|
|
406
511
|
export const releaseProcessResources = async (options) => {
|
|
407
512
|
const host = options.host ?? processCaptureCleanupHost;
|
|
408
513
|
for (const timer of options.timers)
|
|
@@ -422,60 +527,20 @@ export const releaseProcessResources = async (options) => {
|
|
|
422
527
|
: "renderer dispose failed",
|
|
423
528
|
};
|
|
424
529
|
}
|
|
425
|
-
|
|
426
|
-
state:
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
leaderPid: terminalPid,
|
|
440
|
-
processGroupId: terminalPid,
|
|
441
|
-
...(options.sampledProcessGroupIds === undefined
|
|
442
|
-
? {}
|
|
443
|
-
: { sampledProcessGroupIds: options.sampledProcessGroupIds }),
|
|
444
|
-
};
|
|
445
|
-
const cleaned = await host.cleanupProcessGroup({
|
|
446
|
-
runId: options.runId,
|
|
447
|
-
leaderPid: terminalPid,
|
|
448
|
-
processGroupId: terminalPid,
|
|
449
|
-
sweepTokenOwnedProcesses: true,
|
|
450
|
-
...(options.sampledProcessGroupIds === undefined
|
|
451
|
-
? {}
|
|
452
|
-
: { sampledProcessGroupIds: options.sampledProcessGroupIds }),
|
|
453
|
-
...(options.captureBaseline === undefined
|
|
454
|
-
? {}
|
|
455
|
-
: { captureBaseline: options.captureBaseline }),
|
|
456
|
-
});
|
|
457
|
-
const unverified = [...(cleaned.unverified ?? [])];
|
|
458
|
-
if (!cleaned.cleaned) {
|
|
459
|
-
ownedProcessGroup = { state: "unverified", reason: cleaned.reason };
|
|
460
|
-
}
|
|
461
|
-
else {
|
|
462
|
-
const verified = await verifyTokenOwnedProcessesUntilSettled(() => host.verifyTokenOwnedProcesses(options.runId, undefined, options.captureBaseline, relation));
|
|
463
|
-
unverified.push(...(verified.unverified ?? []));
|
|
464
|
-
if (!verified.cleaned)
|
|
465
|
-
ownedProcessGroup = { state: "unverified", reason: verified.reason };
|
|
466
|
-
}
|
|
467
|
-
if (unverified.length > 0)
|
|
468
|
-
ownedProcessGroup = {
|
|
469
|
-
...ownedProcessGroup,
|
|
470
|
-
unverified_processes: [
|
|
471
|
-
...new Map(unverified.map(({ pid, diagnostic }) => [
|
|
472
|
-
`${String(pid)}:${diagnostic}`,
|
|
473
|
-
{ pid, reason: diagnostic },
|
|
474
|
-
])).values(),
|
|
475
|
-
],
|
|
476
|
-
};
|
|
477
|
-
}
|
|
478
|
-
}
|
|
530
|
+
const ownedProcessGroup = options.terminal === undefined
|
|
531
|
+
? { state: "not_required", reason: null }
|
|
532
|
+
: await releaseCapturedProcessGroup({
|
|
533
|
+
runId: options.runId,
|
|
534
|
+
leaderPid: options.terminal.pid,
|
|
535
|
+
processGroupId: options.terminal.pid,
|
|
536
|
+
sweepTokenOwnedProcesses: true,
|
|
537
|
+
...(options.sampledProcessGroupIds === undefined
|
|
538
|
+
? {}
|
|
539
|
+
: { sampledProcessGroupIds: options.sampledProcessGroupIds }),
|
|
540
|
+
...(options.captureBaseline === undefined
|
|
541
|
+
? {}
|
|
542
|
+
: { captureBaseline: options.captureBaseline }),
|
|
543
|
+
}, host);
|
|
479
544
|
let temporaryRoot = {
|
|
480
545
|
state: "cleaned",
|
|
481
546
|
reason: null,
|
|
@@ -507,12 +572,14 @@ export const cleanupReportFailure = (report) => {
|
|
|
507
572
|
};
|
|
508
573
|
export const captureTerminalFrames = (options) => {
|
|
509
574
|
let outputBytes = 0;
|
|
510
|
-
let
|
|
575
|
+
let observedBytes = 0;
|
|
576
|
+
let observedFrames = 0;
|
|
511
577
|
options.terminal.onData((data) => {
|
|
512
578
|
options.onOutput();
|
|
513
579
|
const bytes = Buffer.byteLength(data);
|
|
580
|
+
observedBytes += bytes;
|
|
581
|
+
observedFrames += 1;
|
|
514
582
|
if (outputBytes + bytes > options.scenario.limits.output_bytes) {
|
|
515
|
-
truncated = true;
|
|
516
583
|
return;
|
|
517
584
|
}
|
|
518
585
|
outputBytes += bytes;
|
|
@@ -523,11 +590,18 @@ export const captureTerminalFrames = (options) => {
|
|
|
523
590
|
sequence,
|
|
524
591
|
at_ms: atMs,
|
|
525
592
|
data: normalized,
|
|
593
|
+
...(normalized === data ? {} : { raw_data: data }),
|
|
526
594
|
});
|
|
527
595
|
options.renderer.write(data, atMs);
|
|
528
596
|
options.recordEvent("frames", sequence);
|
|
529
597
|
});
|
|
530
|
-
return () =>
|
|
598
|
+
return () => ({
|
|
599
|
+
budget_bytes: options.scenario.limits.output_bytes,
|
|
600
|
+
observed_bytes: observedBytes,
|
|
601
|
+
retained_bytes: outputBytes,
|
|
602
|
+
observed_frames: observedFrames,
|
|
603
|
+
retained_frames: options.frames.length,
|
|
604
|
+
});
|
|
531
605
|
};
|
|
532
606
|
export const resolveProcessResult = (capture, executionFailure, cleanup, observations, partialContext) => {
|
|
533
607
|
const cleanupFailure = cleanupReportFailure(cleanup);
|
|
@@ -660,16 +734,30 @@ export const prepareProcessCapture = async (scenario, signal, captureSnapshot =
|
|
|
660
734
|
await host.prepareOwnershipInspector?.(signal);
|
|
661
735
|
assertNotCancelled(signal);
|
|
662
736
|
const before = await captureSnapshot(scenario, signal);
|
|
737
|
+
const runId = randomUUID();
|
|
663
738
|
const temporaryRoot = await host.createTemporaryRoot();
|
|
664
739
|
try {
|
|
665
740
|
assertNotCancelled(signal);
|
|
666
|
-
const runId = randomUUID();
|
|
667
741
|
const ownershipBaseline = (await host.captureOwnershipBaseline?.(signal)) ?? [];
|
|
668
742
|
assertNotCancelled(signal);
|
|
669
743
|
return { temporaryRoot, runId, ownershipBaseline, before };
|
|
670
744
|
}
|
|
671
745
|
catch (cause) {
|
|
672
|
-
await
|
|
746
|
+
const cleanup = await releaseProcessResources({
|
|
747
|
+
timers: new Set(),
|
|
748
|
+
terminal: undefined,
|
|
749
|
+
renderer: undefined,
|
|
750
|
+
runId,
|
|
751
|
+
temporaryRoot,
|
|
752
|
+
host: { ...processCaptureCleanupHost, removeTemporaryRoot: host.cleanup },
|
|
753
|
+
});
|
|
754
|
+
resolveProcessResult(undefined, normalizeCaptureFailure(cause, signal), cleanup, createProcessCaptureObservationBuffer({
|
|
755
|
+
frames: [],
|
|
756
|
+
interactions: [],
|
|
757
|
+
samples: [],
|
|
758
|
+
eventJournal: [],
|
|
759
|
+
before,
|
|
760
|
+
}), { scenario });
|
|
673
761
|
throw cause;
|
|
674
762
|
}
|
|
675
763
|
};
|
|
@@ -1,12 +1,42 @@
|
|
|
1
|
-
|
|
1
|
+
import { sep } from "node:path";
|
|
2
|
+
const unobservedAbsenceReason = (path, phase, completeRoots, filesByPath) => {
|
|
3
|
+
const alias = path.slice(0, path.indexOf(":"));
|
|
4
|
+
if (!completeRoots.has(alias))
|
|
5
|
+
return `The ${phase} snapshot did not exhaust path enumeration under ${alias}; absence remains unknown.`;
|
|
6
|
+
const rootPath = `${alias}:.`;
|
|
7
|
+
if (path !== rootPath && filesByPath.get(rootPath)?.type === "symlink")
|
|
8
|
+
return `The ${phase} snapshot did not follow the symbolic link at ${rootPath}; descendant absence remains unknown.`;
|
|
9
|
+
for (let index = path.lastIndexOf(sep); index > 0; index = path.lastIndexOf(sep, index - 1)) {
|
|
10
|
+
const parent = path.slice(0, index);
|
|
11
|
+
if (filesByPath.get(parent)?.type === "symlink")
|
|
12
|
+
return `The ${phase} snapshot did not follow the symbolic link at ${parent}; descendant absence remains unknown.`;
|
|
13
|
+
}
|
|
14
|
+
return undefined;
|
|
15
|
+
};
|
|
16
|
+
/** Classify effects only when a snapshot establishes the missing path's absence. */
|
|
2
17
|
export const classifyFilesystemEffects = (before, after) => {
|
|
3
|
-
const beforeByPath = new Map(before.map((file) => [file.path, file]));
|
|
4
|
-
const afterByPath = new Map(after.map((file) => [file.path, file]));
|
|
18
|
+
const beforeByPath = new Map(before.files.map((file) => [file.path, file]));
|
|
19
|
+
const afterByPath = new Map(after.files.map((file) => [file.path, file]));
|
|
20
|
+
const beforeCompleteRoots = new Set(before.completeRoots);
|
|
21
|
+
const afterCompleteRoots = new Set(after.completeRoots);
|
|
5
22
|
return [...new Set([...beforeByPath.keys(), ...afterByPath.keys()])]
|
|
6
23
|
.sort()
|
|
7
24
|
.map((path) => {
|
|
8
25
|
const beforeFile = beforeByPath.get(path) ?? null;
|
|
9
26
|
const afterFile = afterByPath.get(path) ?? null;
|
|
27
|
+
const reason = beforeFile === null
|
|
28
|
+
? unobservedAbsenceReason(path, "before", beforeCompleteRoots, beforeByPath)
|
|
29
|
+
: afterFile === null
|
|
30
|
+
? unobservedAbsenceReason(path, "after", afterCompleteRoots, afterByPath)
|
|
31
|
+
: undefined;
|
|
32
|
+
if (reason !== undefined)
|
|
33
|
+
return {
|
|
34
|
+
path,
|
|
35
|
+
status: "unknown",
|
|
36
|
+
before: beforeFile,
|
|
37
|
+
after: afterFile,
|
|
38
|
+
reason,
|
|
39
|
+
};
|
|
10
40
|
if (beforeFile === null) {
|
|
11
41
|
if (afterFile === null)
|
|
12
42
|
throw new TypeError(`Filesystem effect ${path} has no file state`);
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import { parseProcessCapture } from "../../domain/process/
|
|
1
|
+
import { parseProcessCapture } from "../../domain/process/processCaptureParsing.js";
|
|
2
2
|
import { err, ok } from "../../domain/result.js";
|
|
3
3
|
import { AnalysisCapabilityUnavailableError } from "../../domain/analysisErrorCore.js";
|
|
4
4
|
import {} from "../../domain/analysisErrorBase.js";
|
|
5
|
-
import { describeProcessCaptureExecutionFailure, ProcessCaptureError, processCaptureCancelled, } from "./ProcessCaptureError.js";
|
|
6
|
-
export { ProcessCaptureError } from "./ProcessCaptureError.js";
|
|
5
|
+
import { describeProcessCaptureExecutionFailure, ProcessCaptureError, normalizeCaptureFailure, processCaptureCancelled, } from "./ProcessCaptureError.js";
|
|
7
6
|
import { startProcessSampler } from "./ProcessSampling.js";
|
|
8
7
|
import { snapshotRoots } from "./FilesystemSnapshot.js";
|
|
9
8
|
import { TerminalRenderer } from "./TerminalRenderer.js";
|
|
@@ -15,14 +14,11 @@ import { createProcessCaptureJournal, scheduleScenarioInteractions, } from "./Pr
|
|
|
15
14
|
import { makeProcessCaptureEnvironment } from "./ProcessCaptureEnvironment.js";
|
|
16
15
|
import { classifyFilesystemEffects } from "./ProcessFilesystemEffects.js";
|
|
17
16
|
import { processCaptureOwnershipUnavailableReason } from "./ProcessCaptureCapability.js";
|
|
18
|
-
import { DarwinProcessOwnershipInspectionError } from "../DarwinProcessRunTokenReader.js";
|
|
19
|
-
export { probeProcessCaptureCapability } from "./ProcessCaptureCapability.js";
|
|
20
17
|
const cleanupFailedStartup = async (options) => {
|
|
21
18
|
const sampledProcessGroupIds = options.terminal !== undefined &&
|
|
22
19
|
options.observations?.process_samples.state === "available"
|
|
23
20
|
? selectCapturedProcessGroupIds(options.terminal.pid, options.observations.process_samples.value).filter((groupId) => groupId !== options.terminal?.pid)
|
|
24
21
|
: undefined;
|
|
25
|
-
options.terminal?.kill("SIGKILL");
|
|
26
22
|
if (options.observations !== undefined && options.renderer !== undefined) {
|
|
27
23
|
try {
|
|
28
24
|
options.observations.rendered_frames = {
|
|
@@ -89,7 +85,7 @@ const startCaptureRuntime = async (options) => {
|
|
|
89
85
|
value: scenario.normalization.pids ? 1 : terminal.pid,
|
|
90
86
|
};
|
|
91
87
|
const executableIdentity = observeLaunchedExecutable(scenario.executable, selectedExecutable);
|
|
92
|
-
const
|
|
88
|
+
const rawTerminalRetention = captureTerminalFrames({
|
|
93
89
|
...options,
|
|
94
90
|
terminal,
|
|
95
91
|
started,
|
|
@@ -117,7 +113,7 @@ const startCaptureRuntime = async (options) => {
|
|
|
117
113
|
startedAt,
|
|
118
114
|
executableIdentity,
|
|
119
115
|
lastOutput: () => lastOutput,
|
|
120
|
-
|
|
116
|
+
rawTerminalRetention,
|
|
121
117
|
stopSampler,
|
|
122
118
|
};
|
|
123
119
|
}
|
|
@@ -181,18 +177,6 @@ const finishProcessRun = async (options) => {
|
|
|
181
177
|
: { scenario: options.scenario, rootPid };
|
|
182
178
|
return resolveProcessResult(cleanupFailure === undefined ? verifiedCapture : capture, executionFailure, cleanup, options.observations, partialContext);
|
|
183
179
|
};
|
|
184
|
-
/** Preserve typed process-inspection preflight failures at the capture boundary. */
|
|
185
|
-
export const normalizeCaptureFailure = (cause, signal) => {
|
|
186
|
-
if (cause instanceof ProcessCaptureError)
|
|
187
|
-
return cause;
|
|
188
|
-
if (cause instanceof DarwinProcessOwnershipInspectionError)
|
|
189
|
-
return new ProcessCaptureError(cause.message, { cause });
|
|
190
|
-
if (signal?.aborted === true &&
|
|
191
|
-
(cause === signal.reason ||
|
|
192
|
-
(cause instanceof Error && cause.name === "AbortError")))
|
|
193
|
-
return processCaptureCancelled();
|
|
194
|
-
return cause;
|
|
195
|
-
};
|
|
196
180
|
const completeCapture = async (options) => {
|
|
197
181
|
const unavailableReason = (stage, cause) => `${stage} failed: ${cause instanceof Error ? cause.message : "unknown failure"}`;
|
|
198
182
|
const { runtime, scenario } = options;
|
|
@@ -201,7 +185,7 @@ const completeCapture = async (options) => {
|
|
|
201
185
|
throw processCaptureCancelled();
|
|
202
186
|
let settlement;
|
|
203
187
|
try {
|
|
204
|
-
settlement = await observeSettlement(options.runId, selectCapturedProcessGroupIds(runtime.terminal.pid, options.samples), scenario.settle_ms, options.recordEvent, options.hostPlatform);
|
|
188
|
+
settlement = await observeSettlement(options.runId, selectCapturedProcessGroupIds(runtime.terminal.pid, options.samples), scenario.settle_ms, options.recordEvent, options.hostPlatform, options.signal);
|
|
205
189
|
}
|
|
206
190
|
catch (cause) {
|
|
207
191
|
options.observationBuffer.settlement = {
|
|
@@ -214,7 +198,8 @@ const completeCapture = async (options) => {
|
|
|
214
198
|
state: "available",
|
|
215
199
|
value: settlement,
|
|
216
200
|
};
|
|
217
|
-
const
|
|
201
|
+
const sampling = await runtime.stopSampler();
|
|
202
|
+
const samplingPartial = sampling.partial;
|
|
218
203
|
await settleProcessCaptureJournal(options.eventJournal);
|
|
219
204
|
assertNotCancelled(options.signal);
|
|
220
205
|
let after;
|
|
@@ -266,7 +251,7 @@ const completeCapture = async (options) => {
|
|
|
266
251
|
name: "after_settlement",
|
|
267
252
|
at_ms: Math.max(0, Date.now() - runtime.started),
|
|
268
253
|
files: after.files,
|
|
269
|
-
effects: classifyFilesystemEffects(options.before
|
|
254
|
+
effects: classifyFilesystemEffects(options.before, after),
|
|
270
255
|
truncated: after.truncated,
|
|
271
256
|
},
|
|
272
257
|
];
|
|
@@ -284,7 +269,8 @@ const completeCapture = async (options) => {
|
|
|
284
269
|
options.observationBuffer.manifest = { state: "available", value: manifest };
|
|
285
270
|
const truncated = options.initiallyTruncated ||
|
|
286
271
|
after.truncated ||
|
|
287
|
-
runtime.
|
|
272
|
+
runtime.rawTerminalRetention().observed_frames >
|
|
273
|
+
runtime.rawTerminalRetention().retained_frames ||
|
|
288
274
|
checkpoints.some(({ truncated: partial }) => partial) ||
|
|
289
275
|
samplingPartial ||
|
|
290
276
|
runtime.renderer.truncated();
|
|
@@ -295,6 +281,17 @@ const completeCapture = async (options) => {
|
|
|
295
281
|
before: options.before,
|
|
296
282
|
after,
|
|
297
283
|
truncated,
|
|
284
|
+
...(options.before.coverage === undefined || after.coverage === undefined
|
|
285
|
+
? {}
|
|
286
|
+
: {
|
|
287
|
+
truncationDetails: {
|
|
288
|
+
raw_terminal: runtime.rawTerminalRetention(),
|
|
289
|
+
rendered_terminal: runtime.renderer.retention(),
|
|
290
|
+
filesystem_before: options.before.coverage,
|
|
291
|
+
filesystem_after: after.coverage,
|
|
292
|
+
process: sampling.coverage,
|
|
293
|
+
},
|
|
294
|
+
}),
|
|
298
295
|
scenario,
|
|
299
296
|
rootPid: runtime.terminal.pid,
|
|
300
297
|
samplingPartial,
|
|
@@ -389,7 +386,6 @@ const runProcessScenario = async (scenario, signal, hostEnvironment = process.en
|
|
|
389
386
|
});
|
|
390
387
|
}
|
|
391
388
|
catch (cause) {
|
|
392
|
-
runtime?.terminal.kill("SIGKILL");
|
|
393
389
|
executionFailure = normalizeCaptureFailure(cause, signal);
|
|
394
390
|
if (runtime !== undefined &&
|
|
395
391
|
observations.rendered_frames.state === "unavailable" &&
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isIP } from "node:net";
|
|
1
2
|
/** Bucket one elapsed process-capture timestamp under scenario normalization. */
|
|
2
3
|
export const normalizeProcessElapsedTime = (elapsedMs, timeBucketMs) => Math.floor(elapsedMs / timeBucketMs) * timeBucketMs;
|
|
3
4
|
/** Normalize one terminal/protocol payload under explicitly selected scenario rules. */
|
|
@@ -10,14 +11,31 @@ export const normalizeProcessText = (value, scenario, temporaryRoot, pid) => {
|
|
|
10
11
|
for (const [index, root] of scenario.filesystem_observation_paths.entries())
|
|
11
12
|
normalized = normalized.replaceAll(root, `<filesystem-root-${String(index)}>`);
|
|
12
13
|
}
|
|
14
|
+
if (scenario.normalization.ports)
|
|
15
|
+
normalized = normalizePortTokens(normalized);
|
|
13
16
|
if (scenario.normalization.pids)
|
|
14
17
|
normalized = normalizePidTokens(normalized, [pid]);
|
|
15
|
-
if (scenario.normalization.ports)
|
|
16
|
-
normalized = normalized.replaceAll(/(?<=[:=])\d{2,5}\b/g, "<port>");
|
|
17
18
|
for (const pattern of scenario.normalization.patterns)
|
|
18
19
|
normalized = normalized.replaceAll(pattern.pattern, pattern.replacement);
|
|
19
20
|
return normalized;
|
|
20
21
|
};
|
|
22
|
+
// A port may end a sentence, but a period followed by a letter, digit, or
|
|
23
|
+
// underscore in any script continues a decimal, version, or host name and is
|
|
24
|
+
// not a port boundary.
|
|
25
|
+
// PTY chunks are normalized independently, so a period that ends the chunk
|
|
26
|
+
// stays unnormalized: its continuation may arrive in the next chunk.
|
|
27
|
+
const normalizePortTokens = (value) => {
|
|
28
|
+
const endpointNormalized = value.replaceAll(/(\b[a-z][a-z0-9+.-]*:\/\/[^\s/?#"'<>]+|\blocalhost|\b(?:\d{1,3}\.){3}\d{1,3}|\[[\da-f:.%]+\]):(\d{1,5})(?![\p{L}\p{N}_@:]|\.(?:[\p{L}\p{N}_]|$))/giu, (match, endpoint, port) => {
|
|
29
|
+
if (Number(port) > 65_535)
|
|
30
|
+
return match;
|
|
31
|
+
const isEndpoint = endpoint.includes("://")
|
|
32
|
+
? URL.canParse(`${endpoint}:${port}`)
|
|
33
|
+
: endpoint.toLowerCase() === "localhost" ||
|
|
34
|
+
isIP(endpoint.replace(/^\[|\]$/gu, "")) !== 0;
|
|
35
|
+
return isEndpoint ? `${endpoint}:<port>` : match;
|
|
36
|
+
});
|
|
37
|
+
return endpointNormalized.replaceAll(/(\b(?:port|tcp_port|udp_port|listen)\b["']?\s*[:=]\s*)(\d{1,5})(?![\p{L}\p{N}_]|\.(?:[\p{L}\p{N}_]|$))/giu, (match, prefix, port) => Number(port) <= 65_535 ? `${prefix}<port>` : match);
|
|
38
|
+
};
|
|
21
39
|
/** Project sampled observations under the caller-selected normalization rules. */
|
|
22
40
|
export const normalizeProcessSamples = (samples, scenario, rootPid) => {
|
|
23
41
|
const identifiers = [
|
|
@@ -328,6 +328,9 @@ export const startProcessSampler = (options) => {
|
|
|
328
328
|
let stopped = false;
|
|
329
329
|
let abortCurrent;
|
|
330
330
|
let partial = false;
|
|
331
|
+
let limitReached = false;
|
|
332
|
+
let samplingFailures = 0;
|
|
333
|
+
let firstSamplingFailure = null;
|
|
331
334
|
let rootInitialized = false;
|
|
332
335
|
const sample = () => {
|
|
333
336
|
if (stopped || pending !== undefined)
|
|
@@ -363,6 +366,7 @@ export const startProcessSampler = (options) => {
|
|
|
363
366
|
continue;
|
|
364
367
|
if (samples.length >= limit) {
|
|
365
368
|
partial = true;
|
|
369
|
+
limitReached = true;
|
|
366
370
|
continue;
|
|
367
371
|
}
|
|
368
372
|
lastObservations.set(value.pid, observation);
|
|
@@ -372,8 +376,16 @@ export const startProcessSampler = (options) => {
|
|
|
372
376
|
}
|
|
373
377
|
})
|
|
374
378
|
.catch((cause) => {
|
|
375
|
-
if (!(cause instanceof Error && cause.name === "AbortError"))
|
|
379
|
+
if (!(cause instanceof Error && cause.name === "AbortError")) {
|
|
376
380
|
partial = true;
|
|
381
|
+
samplingFailures += 1;
|
|
382
|
+
firstSamplingFailure ??=
|
|
383
|
+
cause instanceof Error
|
|
384
|
+
? `${cause.name}: ${cause.message}`
|
|
385
|
+
: typeof cause === "string"
|
|
386
|
+
? cause
|
|
387
|
+
: `Unexpected sampling rejection (${typeof cause})`;
|
|
388
|
+
}
|
|
377
389
|
})
|
|
378
390
|
.then(() => {
|
|
379
391
|
abortCurrent = undefined;
|
|
@@ -387,6 +399,17 @@ export const startProcessSampler = (options) => {
|
|
|
387
399
|
clearInterval(timer);
|
|
388
400
|
abortCurrent?.();
|
|
389
401
|
await pending;
|
|
390
|
-
return {
|
|
402
|
+
return {
|
|
403
|
+
partial,
|
|
404
|
+
coverage: {
|
|
405
|
+
sample_limit: limit,
|
|
406
|
+
sampling_partial: partial,
|
|
407
|
+
retained_samples: samples.length,
|
|
408
|
+
sample_limit_reached: limitReached,
|
|
409
|
+
sampling_failures: samplingFailures,
|
|
410
|
+
first_sampling_failure: firstSamplingFailure,
|
|
411
|
+
coverage: "sampled",
|
|
412
|
+
},
|
|
413
|
+
};
|
|
391
414
|
};
|
|
392
415
|
};
|
|
@@ -19,6 +19,8 @@ export class TerminalRenderer {
|
|
|
19
19
|
#frames = [];
|
|
20
20
|
#pending = Promise.resolve();
|
|
21
21
|
#capturedBytes = 0;
|
|
22
|
+
#observedBytes = 0;
|
|
23
|
+
#observedFrames = 0;
|
|
22
24
|
#truncated = false;
|
|
23
25
|
constructor(options) {
|
|
24
26
|
this.options = options;
|
|
@@ -55,6 +57,16 @@ export class TerminalRenderer {
|
|
|
55
57
|
truncated() {
|
|
56
58
|
return this.#truncated;
|
|
57
59
|
}
|
|
60
|
+
/** Budget accounting after awaiting queued writes with frames(). */
|
|
61
|
+
retention() {
|
|
62
|
+
return {
|
|
63
|
+
budget_bytes: this.options.maxBytes,
|
|
64
|
+
observed_bytes: this.#observedBytes,
|
|
65
|
+
retained_bytes: this.#capturedBytes,
|
|
66
|
+
observed_frames: this.#observedFrames,
|
|
67
|
+
retained_frames: this.#frames.length,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
58
70
|
/** Release addon and terminal resources after all writes settle. */
|
|
59
71
|
async dispose() {
|
|
60
72
|
await this.#pending;
|
|
@@ -71,6 +83,8 @@ export class TerminalRenderer {
|
|
|
71
83
|
const serializedState = this.options.normalize(this.#serializeAddon.serialize());
|
|
72
84
|
const bytes = Buffer.byteLength(serializedState) +
|
|
73
85
|
lines.reduce((total, line) => total + Buffer.byteLength(line), 0);
|
|
86
|
+
this.#observedBytes += bytes;
|
|
87
|
+
this.#observedFrames += 1;
|
|
74
88
|
if (this.#capturedBytes + bytes > this.options.maxBytes) {
|
|
75
89
|
this.#truncated = true;
|
|
76
90
|
return;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** Snapshot caller-selected variables using Node child-process key semantics. */
|
|
2
|
+
export const snapshotEnvironment = (environment, platform = process.platform) => {
|
|
3
|
+
if (platform !== "win32")
|
|
4
|
+
return Object.freeze({ ...environment });
|
|
5
|
+
const snapshot = {};
|
|
6
|
+
// Node sorts keys lexicographically and forwards the first case-insensitive
|
|
7
|
+
// match on Windows. Canonical keys also make subsequent lookups deterministic.
|
|
8
|
+
for (const key of Object.keys(environment).sort()) {
|
|
9
|
+
const canonicalKey = key.toUpperCase();
|
|
10
|
+
if (!Object.hasOwn(snapshot, canonicalKey))
|
|
11
|
+
snapshot[canonicalKey] = environment[key];
|
|
12
|
+
}
|
|
13
|
+
return Object.freeze(snapshot);
|
|
14
|
+
};
|