rea-agents 2.1.0 → 2.3.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 +84 -18
- package/dist/application/AndroidApplicationService.js +17 -0
- package/dist/application/AppleApplicationService.js +17 -0
- package/dist/application/ApplicationWorkflowEvidenceResolver.js +162 -0
- package/dist/application/BinarySession.js +9 -2
- package/dist/application/BinarySessionStatus.js +39 -1
- package/dist/application/CapabilityInventory.js +15 -0
- package/dist/application/ClientRegistrationStatus.js +11 -4
- package/dist/application/CommandShimReplay.js +6 -3
- package/dist/application/CompositeProvider.js +5 -2
- package/dist/application/DirectAnalysis.js +1 -20
- package/dist/application/DirectAnalysisStatus.js +83 -0
- package/dist/application/Doctor.js +34 -25
- package/dist/application/DoctorDiagnostics.js +1 -4
- package/dist/application/DoctorProjection.js +43 -0
- package/dist/application/DoctorScope.js +102 -0
- package/dist/application/EvidenceReferenceResolver.js +26 -0
- package/dist/application/InventoryProjectionEvidence.js +41 -0
- package/dist/application/InvestigationProviders.js +12 -0
- package/dist/application/JavaScriptApplicationEvidence.js +1 -1
- package/dist/application/JavaScriptApplicationEvidenceGraph.js +10 -1
- package/dist/application/JavaScriptApplicationService.js +3 -2
- package/dist/application/JavaScriptApplicationWorkflowEvidence.js +26 -0
- package/dist/application/JavaScriptApplicationWorkflowService.js +49 -1
- package/dist/application/JavaScriptArtifactReconstruction.js +7 -0
- package/dist/application/JavaScriptModuleRelationships.js +25 -1
- package/dist/application/JavaScriptReturnShapeProjection.js +111 -0
- package/dist/application/JavaScriptSemanticGraphBuilder.js +294 -0
- package/dist/application/JavaScriptSemanticGraphConstruction.js +144 -0
- package/dist/application/JavaScriptSemanticGraphEvidence.js +86 -0
- package/dist/application/JavaScriptSemanticGraphFlowProjection.js +72 -0
- package/dist/application/JavaScriptSemanticGraphProjection.js +33 -0
- package/dist/application/JavaScriptSemanticTraceService.js +45 -0
- package/dist/application/LoopbackReplay.js +277 -133
- package/dist/application/LoopbackReplayRecorder.js +101 -0
- package/dist/application/PermissionAuthority.js +7 -3
- package/dist/application/ProcessCaptureJournal.js +95 -0
- package/dist/application/ProcessCaptureLifecycle.js +24 -13
- package/dist/application/ProcessCheckpoints.js +30 -4
- package/dist/application/ProcessCli.js +26 -4
- package/dist/application/ProcessHarness.js +20 -50
- package/dist/application/ProcessNormalization.js +3 -2
- package/dist/application/ProcessPairedExperiment.js +72 -0
- package/dist/application/ProcessReactiveCoordinator.js +218 -0
- package/dist/application/ProcessReactiveEffects.js +133 -0
- package/dist/application/ProcessReactiveObservations.js +20 -0
- package/dist/application/ProcessSampling.js +2 -0
- package/dist/application/SessionProviderRouter.js +7 -6
- package/dist/application/Setup.js +14 -13
- package/dist/application/SetupClientConfiguration.js +10 -6
- package/dist/application/SetupPlan.js +4 -3
- package/dist/application/SetupRegistrationEnvironment.js +12 -0
- package/dist/application/SetupSkill.js +44 -40
- package/dist/application/TerminalRenderer.js +3 -1
- package/dist/application/Uninstall.js +7 -1
- package/dist/application/Upgrade.js +16 -1
- package/dist/browser/CdpEndpoint.js +37 -4
- package/dist/catalogIdentity.js +16 -7
- package/dist/cli/coreAnalysisCommands.js +34 -2
- package/dist/cli/javascriptApplicationAnalysis.js +19 -0
- package/dist/cli/setupCommands.js +84 -30
- package/dist/cli/utilityCommands.js +10 -2
- package/dist/cliApplicationCommands.js +79 -16
- package/dist/cliCommandNames.js +3 -0
- package/dist/cliElectronCommands.js +23 -33
- package/dist/cliObservationOptions.js +1 -1
- package/dist/cliOutput.js +56 -0
- package/dist/cliProcessCommands.js +32 -1
- package/dist/cliSetup.js +55 -29
- package/dist/contracts/applicationToolContracts.js +54 -7
- package/dist/contracts/applicationWorkflowInputContracts.js +119 -0
- package/dist/contracts/electronToolContracts.js +73 -4
- package/dist/contracts/javascriptApplicationWorkflowExamples.js +32 -9
- package/dist/contracts/managedToolContracts.js +7 -2
- package/dist/contracts/processCaptureExample.js +1 -0
- package/dist/contracts/replayMachineExample.js +37 -0
- package/dist/contracts/sessionStatusContract.js +26 -0
- package/dist/contracts/toolContractExamples.js +2 -0
- package/dist/contracts/toolContractTypes.js +12 -1
- package/dist/contracts/toolContracts.js +8 -11
- package/dist/contracts/toolEffects.js +3 -0
- package/dist/contracts/toolOutputSchemaGroups.js +53 -9
- package/dist/contracts/toolOutputSchemaPrimitives.js +73 -32
- package/dist/doctorRuntime.js +41 -0
- package/dist/domain/analysisErrorPresentation.js +5 -3
- package/dist/domain/analysisErrorProjection.js +7 -1
- package/dist/domain/androidApplication.js +206 -0
- package/dist/domain/appleApplication.js +221 -0
- package/dist/domain/boundedCartesianProjection.js +15 -0
- package/dist/domain/changedBehavior.js +5 -4
- package/dist/domain/completionLedgerGeneration.js +190 -0
- package/dist/domain/errors.js +4 -2
- package/dist/domain/evidenceCompletionLedger.js +113 -0
- package/dist/domain/hopperStartupFailure.js +9 -0
- package/dist/domain/javascriptApplicationAnalysis.js +44 -2
- package/dist/domain/javascriptExportShapeComparison.js +145 -0
- package/dist/domain/javascriptExportShapeComparisonIdentity.js +11 -0
- package/dist/domain/javascriptExportShapeComparisonSchemas.js +277 -0
- package/dist/domain/javascriptExportShapeSelection.js +132 -0
- package/dist/domain/javascriptExportShapeVariants.js +272 -0
- package/dist/domain/javascriptRuntimeReconciliationParsing.js +2 -2
- package/dist/domain/javascriptSemanticAnalysis.js +17 -36
- package/dist/domain/javascriptSemanticCallResolution.js +129 -0
- package/dist/domain/javascriptSemanticCalls.js +269 -0
- package/dist/domain/javascriptSemanticGraph.js +356 -0
- package/dist/domain/javascriptSemanticGraphSchemas.js +329 -0
- package/dist/domain/javascriptSemanticGraphSerialization.js +23 -0
- package/dist/domain/javascriptSemanticIr.js +14 -1
- package/dist/domain/javascriptSemanticPrimitives.js +36 -0
- package/dist/domain/javascriptSemanticProjection.js +36 -4
- package/dist/domain/javascriptSemanticProvenance.js +29 -0
- package/dist/domain/javascriptSemanticQuery.js +294 -0
- package/dist/domain/javascriptSemanticQueryAssessment.js +74 -0
- package/dist/domain/javascriptSemanticQueryIdentity.js +86 -0
- package/dist/domain/javascriptSemanticQueryRelations.js +15 -0
- package/dist/domain/javascriptSemanticQuerySchemas.js +188 -0
- package/dist/domain/javascriptSemanticReturns.js +187 -0
- package/dist/domain/javascriptSemanticState.js +32 -0
- package/dist/domain/javascriptSemanticTraceSchemas.js +14 -0
- package/dist/domain/javascriptSemanticValues.js +54 -70
- package/dist/domain/processCapture.js +36 -0
- package/dist/domain/processCaptureValidation.js +101 -12
- package/dist/domain/processComparison.js +96 -24
- package/dist/domain/processObservation.js +153 -0
- package/dist/domain/processPairedExperiment.js +128 -0
- package/dist/domain/processReactiveCheckpointDataflow.js +32 -0
- package/dist/domain/processReactiveMatching.js +210 -0
- package/dist/domain/processReactiveRuntime.js +109 -0
- package/dist/domain/processReactiveScenario.js +361 -0
- package/dist/domain/processReactiveScenarioPreflight.js +120 -0
- package/dist/domain/processReactiveTransition.js +159 -0
- package/dist/domain/processScenario.js +12 -0
- package/dist/domain/processTraceComparison.js +43 -0
- package/dist/domain/processTraceDimensionProjection.js +50 -0
- package/dist/domain/processTraceEvaluation.js +312 -0
- package/dist/domain/processTraceSpecification.js +373 -0
- package/dist/domain/reconstructionVerification.js +5 -4
- package/dist/domain/replayMachine.js +332 -0
- package/dist/domain/replayMachineRun.js +216 -0
- package/dist/domain/replayMachineRuntime.js +294 -0
- package/dist/domain/runtimeIdentification.js +210 -0
- package/dist/domain/staticRuntimeCorrelation.js +4 -2
- package/dist/evaluation/CodexAgentEval.js +156 -0
- package/dist/generatedPackageMetadata.js +2 -2
- package/dist/ghidra/GhidraClient.js +13 -2
- package/dist/ghidra/GhidraDiagnostics.js +1 -0
- package/dist/ghidra/GhidraLauncher.js +7 -3
- package/dist/ghidra/GhidraProvider.js +8 -1
- package/dist/hopper/BridgeLauncher.js +56 -14
- package/dist/hopper/HopperClient.js +23 -10
- package/dist/hopper/HopperDiagnostics.js +14 -0
- package/dist/hopper/HopperProcessDiagnostic.js +14 -0
- package/dist/hopper/HopperProvider.js +8 -1
- package/dist/hopper/LinuxPrivateDisplayDiagnostic.js +72 -0
- package/dist/hopper/LinuxPrivateDisplayProbe.js +217 -0
- package/dist/identity.js +2 -1
- package/dist/main/transport.js +2 -0
- package/dist/mcpDoctor.js +310 -0
- package/dist/process/ProcessOwnership.js +200 -53
- package/dist/process/ProviderRunLineage.js +21 -0
- package/dist/server/createServer.js +8 -2
- package/dist/server/javascriptApplicationResult.js +106 -0
- package/dist/server/registerApplicationTools/characterization.js +3 -3
- package/dist/server/registerApplicationTools/compareExportShapes.js +37 -0
- package/dist/server/registerApplicationTools/compareVersions.js +12 -6
- package/dist/server/registerApplicationTools/controlledReplay.js +2 -2
- package/dist/server/registerApplicationTools/coverage.js +3 -3
- package/dist/server/registerApplicationTools/helpers.js +37 -25
- package/dist/server/registerApplicationTools/traceFeature.js +9 -5
- package/dist/server/registerApplicationTools/traceSemantics.js +30 -0
- package/dist/server/registerApplicationTools.js +4 -0
- package/dist/server/registerElectronTools.js +19 -5
- package/dist/server/registerEvidenceResources.js +7 -1
- package/dist/server/registerJavaScriptApplicationGraphResource.js +69 -0
- package/dist/server/registerManagedTools.js +18 -1
- package/dist/server/registerProcessComparisonTool.js +17 -7
- package/dist/server/registerReplayMachineTool.js +20 -0
- package/dist/server/registerSessionStatusTool.js +95 -25
- package/dist/server/registerSessionTools.js +12 -7
- package/dist/server/sessionAvailabilityPolicy.js +2 -1
- package/dist/server/toolResult.js +10 -4
- package/dist/serverIdentity.js +19 -0
- package/package.json +62 -29
- package/scripts/hopper-demo-x11.py +459 -61
- package/scripts/prepack.mjs +55 -0
- package/scripts/prepare.mjs +28 -0
- package/scripts/rea.mjs +26 -5
- package/skills/reverse-engineer-anything/SKILL.md +69 -228
- package/skills/reverse-engineer-anything/references/controlled-replay.md +12 -0
- package/skills/reverse-engineer-anything/references/evidence-workflows.md +33 -0
- package/skills/reverse-engineer-anything/references/javascript-applications.md +35 -0
- package/skills/reverse-engineer-anything/references/native-and-artifacts.md +36 -0
- package/skills/reverse-engineer-anything/references/runtime-observation.md +24 -0
package/README.md
CHANGED
|
@@ -36,17 +36,18 @@ Reverse engineering normally makes the operator choose a tool, learn its API, mo
|
|
|
36
36
|
|
|
37
37
|
## Just ask your agent
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
Run setup once. Agent integration installs an aligned MCP registration and the
|
|
40
|
+
bundled routing skill together:
|
|
40
41
|
|
|
41
42
|
```bash
|
|
42
|
-
npx
|
|
43
|
+
npx rea-agents setup
|
|
43
44
|
```
|
|
44
45
|
|
|
45
46
|
Then ask:
|
|
46
47
|
|
|
47
48
|
```text
|
|
48
|
-
|
|
49
|
-
|
|
49
|
+
Understand how search works in the Notes app, show me the evidence, and build a
|
|
50
|
+
similar feature for my project.
|
|
50
51
|
```
|
|
51
52
|
|
|
52
53
|
Notes is only an example. Name any app you want to understand, or ask the agent to start with an overview.
|
|
@@ -97,9 +98,9 @@ shows its complete plan and asks before applying it. Setup does not update
|
|
|
97
98
|
Homebrew, Node.js, or npm. `npx rea-agents setup` opens with the work it
|
|
98
99
|
enables: investigate local apps from an agent, recover evidence through a
|
|
99
100
|
deep-analysis provider, and reuse REA's guided workflow. It summarizes the
|
|
100
|
-
detected agents, then asks which
|
|
101
|
-
|
|
102
|
-
|
|
101
|
+
detected agents, then asks which capabilities to set up: agent integration
|
|
102
|
+
(MCP plus the matching guided workflow) and—when needed—the Hopper provider.
|
|
103
|
+
Nothing is preselected. Choosing agent integration opens a second empty
|
|
103
104
|
checklist for the specific detected agents that should receive a registration.
|
|
104
105
|
|
|
105
106
|
REA keeps the journey inline so its history remains in the terminal. Selecting
|
|
@@ -131,10 +132,12 @@ Pass installer options after `bash -s --`, for example `--dry-run`, `--no-setup`
|
|
|
131
132
|
### With an agent — recommended
|
|
132
133
|
|
|
133
134
|
```bash
|
|
134
|
-
npx
|
|
135
|
+
npx rea-agents setup
|
|
135
136
|
```
|
|
136
137
|
|
|
137
|
-
|
|
138
|
+
Choose Agent Integration in the reviewed setup plan. REA installs the pinned MCP
|
|
139
|
+
registration and its matching routing skill as one transaction. After setup,
|
|
140
|
+
restart the configured agent so it loads the aligned integration.
|
|
138
141
|
|
|
139
142
|
Review the setup plan, approve it if appropriate, then describe the app or feature you want to understand. Hopper can run in its free demo mode; if it shows a first-run prompt, choose the demo or enter an existing license.
|
|
140
143
|
|
|
@@ -259,7 +262,7 @@ Uninstall preserves Hopper, Node.js, evidence, captures, external evidence roots
|
|
|
259
262
|
| Inspect or decompile one part of an app from the Terminal | `rea analyze` or `rea decompile` |
|
|
260
263
|
| Validate, canonicalize, or compare Evidence v2 bundles | `rea evidence-import`, `rea evidence-export`, or `rea compare` |
|
|
261
264
|
| Run or resume a persistent two-version artifact analysis | `rea investigate-versions` |
|
|
262
|
-
| Map a local JavaScript/Electron application without executing it | `rea analyze-javascript-application`
|
|
265
|
+
| Map a local JavaScript/Electron application without executing it | `rea analyze PATH --approved` or `rea analyze-javascript-application` |
|
|
263
266
|
| Reuse immutable analysis results without relaunching a provider | Pass `--snapshot /approved/path/analysis.json` to a deep-analysis command |
|
|
264
267
|
| Import source as historical reference | `rea import-reference-source` |
|
|
265
268
|
| Capture or compare controlled process behavior | `rea capture-process` or `rea compare-process-captures` |
|
|
@@ -273,9 +276,21 @@ rea evidence-import /absolute/path/to/evidence/bundle.json
|
|
|
273
276
|
rea evidence-export /absolute/path/to/evidence/bundle.json /absolute/path/to/evidence/canonical.json
|
|
274
277
|
rea compare /absolute/path/to/evidence/left.json /absolute/path/to/evidence/right.json
|
|
275
278
|
rea investigate-versions /absolute/path/to/releases/v1 /absolute/path/to/releases/v2 /absolute/path/to/evidence/releases.json --yes --workspace-name releases
|
|
279
|
+
rea analyze /absolute/path/to/releases/app.asar --approved --json
|
|
276
280
|
rea analyze-javascript-application /absolute/path/to/releases/app.asar --approved --json
|
|
277
281
|
```
|
|
278
282
|
|
|
283
|
+
For a directory or `.asar`, generic `rea analyze` automatically selects the
|
|
284
|
+
static JavaScript application provider when neither `--provider` nor
|
|
285
|
+
`--snapshot` is supplied. The dedicated command remains available for explicit
|
|
286
|
+
format and resource-limit controls. Both routes require `--approved` and an
|
|
287
|
+
administrator-approved investigation input root.
|
|
288
|
+
|
|
289
|
+
If REA is registered with an MCP client, run approved `rea setup` while the
|
|
290
|
+
explicit investigation-root variable is set, then restart that client. Setup
|
|
291
|
+
copies this non-secret policy into the managed registration; changing the shell
|
|
292
|
+
environment alone cannot update an already-running MCP process.
|
|
293
|
+
|
|
279
294
|
`investigate-versions` inventories both versions, checkpoints their observed
|
|
280
295
|
Evidence, derives an artifact comparison, and records a changed-behavior report.
|
|
281
296
|
Both input paths must resolve beneath `REA_INVESTIGATION_INPUT_ROOTS_JSON`;
|
|
@@ -365,8 +380,8 @@ REA handles the app analysis in steps 1–5. The agent performs step 6 with its
|
|
|
365
380
|
| Managed PE/CLI | 8 | PE/CLI identity, metadata members, CIL hashes, P/Invoke/native-boundary declarations and verification, application-graph projection, decompiler reconstruction import, token remapping, runtime-correlation plans, and version comparison |
|
|
366
381
|
| Browser observation | 8 | exact-origin CDP capture, bundle and source-map analysis, WebMCP discovery, session timelines, capture diff, and visual evidence |
|
|
367
382
|
| Electron analysis | 4 | passive root-confined observation, bounded static application mapping, and evidence-backed static/runtime reconciliation |
|
|
368
|
-
| Application workflows |
|
|
369
|
-
| Workspace and observation |
|
|
383
|
+
| Application workflows | 9 | bounded cross-layer traces, unique-only version matching, static export return-shape comparison, approved Linux-isolated extracted-module replay, managed-runtime characterization, and reconstruction coverage closure |
|
|
384
|
+
| Workspace and observation | 19 | target lifecycle, Evidence v2 bundles, direct finite replay-machine evaluation, process/artifact/function comparison, evidence-linked residual-unknown lifecycle |
|
|
370
385
|
|
|
371
386
|
The public interface describes what the agent is trying to learn. Providers decide how to answer. macOS utilities handle common semantic inspection without launching Hopper; Hopper handles deeper native analysis; the process harness implements controlled behavioral capture.
|
|
372
387
|
|
|
@@ -381,7 +396,7 @@ REA is already useful for native application, browser, and Electron investigatio
|
|
|
381
396
|
- Validate and canonically serialize a provider-neutral [JavaScript Application Graph v1](docs/javascript-application-graph.md) spanning packages, ASAR entries, Electron roles, JavaScript/source-map entities, browser/runtime instances, IPC, endpoints, storage, and native add-ons. This shipped domain contract performs no extraction or I/O by itself.
|
|
382
397
|
- Reconstruct bounded static package, entrypoint, Webpack/Rspack module, import, worker, endpoint, storage, source-map, BrowserWindow, preload, contextBridge, IPC, utility-process, and native-add-on structure from an approved local directory or ASAR through `analyze_javascript_application` or `rea analyze-javascript-application`. The AST-only [application service](docs/javascript-artifact-reconstruction.md) never executes bootstrap code, pairs only unique exact literal IPC channels, and reports dynamic or ambiguous channels as unresolved.
|
|
383
398
|
- Reconcile that static graph with existing passive web or Electron Evidence through `reconcile_javascript_runtime` or `rea reconcile-javascript-runtime`. Exact captured bytes outrank caller-declared file/URL mappings; target, frame, script, worker, cache, and asset ambiguity stays explicit, source-map authority stays separate, and a module resident in an observed bundle is never reported as executed. See [JavaScript static/runtime reconciliation](docs/javascript-runtime-reconciliation.md).
|
|
384
|
-
- Trace a literal route, string, API, IPC channel, module, or native export through authenticated application Evidence with explicit traversal bounds, then hand exact native artifact digests and requested exports to retained Ghidra or Hopper Evidence without automatic provider switching. Compare application versions using unique-only digest, source-map, structural, and semantic tiers;
|
|
399
|
+
- Trace a literal route, string, API, IPC channel, module, or native export through authenticated application Evidence with explicit traversal bounds, then hand exact native artifact digests and requested exports to retained Ghidra or Hopper Evidence without automatic provider switching. Compare application versions using unique-only digest, source-map, structural, and semantic tiers; compare one exact JavaScript export's static return shapes through unique literal discriminants and bounded JSON Pointer changes. Duplicate, dynamic, incomplete, and truncated facts stay unknown. See [cross-layer JavaScript application workflows](docs/javascript-application-workflows.md).
|
|
385
400
|
- Classify PE/CLI managed artifacts with `inspect_managed_artifact` / `rea inspect-managed-artifact`, inspect bounded metadata members, signatures, raw CIL hashes, limited decoded-instruction-tuple v1 hashes, separately reported exception regions, call edges, and field-access anchors with `inspect_managed_members` / `rea inspect-managed-members`, inventory declared ModuleRef/ImplMap/PInvoke and non-IL method boundary indicators with `inspect_managed_native_boundaries` / `rea inspect-managed-native-boundaries`, then compare two authenticated member observations with `compare_managed_members` / `rea compare-managed-members`. `verify_managed_native_boundaries` / `rea verify-managed-native-boundaries` checks managed P/Invoke declarations against authenticated native export or function Evidence while keeping verified, inferred, contradicted, and unresolved states distinct. The comparison treats build-local tokens as build-local and uses unique decoded-CIL/signature and structural method-shape tiers, never names alone; the v1 tuple hash does not itself resolve tokens or fully commit control flow. `project_managed_application_graph` / `rea project-managed-application-graph` projects authenticated managed artifact/member/native-boundary Evidence into the existing application graph for cross-layer feature tracing. `import_managed_reconstruction` / `rea import-managed-reconstruction` admits user-supplied decompiler C#/IL/pseudocode as analyst inference only after exact artifact SHA-256, MVID, signature, and the shipped v1 decoded-IL commitment match. Separately, `plan_managed_runtime_correlation` / `rea plan-managed-runtime-correlation` can admit a default-disabled, permission-gated runtime-correlation plan locked to the same build evidence. These paths never load the assembly, resolve CLR dependencies, execute target code, run a decompiler, or translate managed tokens into native addresses; full normalized-CIL v2 semantics, native-body bridge mapping, and an actual runtime executor remain future managed-code contracts.
|
|
386
401
|
- Configure `REA_ILSPY_CMD_PATH=/absolute/path/to/ilspycmd` only when you want
|
|
387
402
|
doctor and `verify:managed` to inspect a bring-your-own ILSpy command as a
|
|
@@ -394,6 +409,7 @@ REA is already useful for native application, browser, and Electron investigatio
|
|
|
394
409
|
- Export and import evidence bundles across sessions.
|
|
395
410
|
- Persist automatic cross-version artifact runs as canonical, lock-protected workspaces with tamper-evident revision commitments.
|
|
396
411
|
- Capture approved PTY scenarios as Process Capture v4 Evidence, including committed run manifests, raw and rendered terminal frames, scripted interactions, descendant settlement, named filesystem checkpoints, deterministic command shims, and loopback HTTP/WebSocket exchanges.
|
|
412
|
+
- Validate finite replay machines without launching a target through `run_replay_machine` or `rea run-replay-machine`; ordered events return typed decisions, actions, captured aliases, transition journals, final state, and exact limit use without echoing request or captured values.
|
|
397
413
|
- Compare complete artifact inventories by stable path, content, metadata, and relations; incomplete evidence never implies equivalence.
|
|
398
414
|
- Compare explicit function dossiers across text, calls, references, strings, and address-normalized CFG topology with per-facet unknowns.
|
|
399
415
|
- Compare canonical Evidence bundles by exact membership, explicit observation pairs, and residual-unknown histories without turning omissions into behavioral absence.
|
|
@@ -422,7 +438,7 @@ rea inspect-web-page http://127.0.0.1:9222 TARGET_ID --approved --json
|
|
|
422
438
|
|
|
423
439
|
All eight browser tools expose the same Evidence v2 contracts over CLI and MCP. Inspection is passive: REA does not evaluate page JavaScript, navigate, click, close the page, or close the browser. Query values, credentials, cookies, authorization headers, storage values, and raw JSON or WebSocket values are never retained. Separately approved captures can retain bounded redacted console primitives, value-free JSON/WebSocket shapes, script sources, accessibility text, or screenshot pixels. Existing activity before attach is explicitly unavailable. See [Website observation with CDP](docs/browser-observation.md) for browser startup, schemas, limits, and the threat model.
|
|
424
440
|
|
|
425
|
-
Exact package, tool-family, provider, setup-client, public schema-version, and CLI facts are generated from source in [`docs/product-catalog.json`](docs/product-catalog.json).
|
|
441
|
+
Exact package, tool-family, provider, setup-client, public schema-version, and CLI facts are generated from source in [`docs/product-catalog.json`](docs/product-catalog.json). PR CI verifies this catalog, narrative documentation, generated schemas, and a clean TypeDoc render.
|
|
426
442
|
|
|
427
443
|
## Roadmap
|
|
428
444
|
|
|
@@ -456,17 +472,28 @@ Setup detects Claude Code, Claude Desktop, Codex, Cursor, Gemini CLI, Windsurf,
|
|
|
456
472
|
|
|
457
473
|
### Manual MCP configuration
|
|
458
474
|
|
|
475
|
+
<!-- x-release-please-start-version -->
|
|
476
|
+
|
|
459
477
|
```json
|
|
460
478
|
{
|
|
461
479
|
"mcpServers": {
|
|
462
480
|
"rea": {
|
|
463
481
|
"command": "npx",
|
|
464
|
-
"args": ["-y", "rea-agents@
|
|
482
|
+
"args": ["-y", "rea-agents@2.3.0", "mcp"]
|
|
465
483
|
}
|
|
466
484
|
}
|
|
467
485
|
}
|
|
468
486
|
```
|
|
469
487
|
|
|
488
|
+
<!-- x-release-please-end -->
|
|
489
|
+
|
|
490
|
+
Persistent registrations should use one exact package version. `rea setup`
|
|
491
|
+
maintains that pin, upgrades the bundled skill at the same time, and gives Codex
|
|
492
|
+
a 30-second startup allowance for a cold package-runner start. An interactive
|
|
493
|
+
`rea upgrade` opens the updated setup plan after installing the new executable;
|
|
494
|
+
structured or non-interactive upgrades tell you to run that sync explicitly.
|
|
495
|
+
Restart clients whose approved registration changed.
|
|
496
|
+
|
|
470
497
|
MCP clients that support prompts can also discover six ordered investigation
|
|
471
498
|
workflows through `prompts/list`. Their optional identifier arguments use the
|
|
472
499
|
current session for bounded `completion/complete` suggestions; see
|
|
@@ -558,8 +585,15 @@ operations still work. An explicit unknown, unavailable, or unsupported
|
|
|
558
585
|
provider fails with candidate IDs, stable rejection codes, and actionable local
|
|
559
586
|
diagnostics. `binary_session`, `rea providers`, and `rea capabilities` expose
|
|
560
587
|
the authoritative `analysis_provider_candidates` and
|
|
561
|
-
`analysis_provider_binding` fields.
|
|
562
|
-
|
|
588
|
+
`analysis_provider_binding` fields. Each open target also has an
|
|
589
|
+
`analysis_run.run_id` allocated before provider startup. When dynamic providers
|
|
590
|
+
start, `analysis_run.process_lineage` changes from `not_observed` to `snapshots`
|
|
591
|
+
and retains one provider-attributed, token-verified observation per started
|
|
592
|
+
provider. Each observation carries `observed_at` and remains `unavailable` or
|
|
593
|
+
`verified`; a verified empty descendant list is distinct from both. Snapshots
|
|
594
|
+
describe bounded observations, not current live state or historical absence.
|
|
595
|
+
Reopening same target without a selector keeps its binding; runtime failure
|
|
596
|
+
never selects another provider silently.
|
|
563
597
|
Ghidra can appear as an available, target-compatible candidate after doctor
|
|
564
598
|
validates its exact installation. Its capability list contains the 18 admitted
|
|
565
599
|
read-only inventory and function-analysis operations; selecting it still does
|
|
@@ -691,7 +725,39 @@ Any agent that can run a local MCP server can use the manual configuration. Setu
|
|
|
691
725
|
|
|
692
726
|
## Development
|
|
693
727
|
|
|
694
|
-
See [CONTRIBUTING.md](CONTRIBUTING.md) for setup, architecture, tests, and release instructions.
|
|
728
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for setup, architecture, tests, and release instructions. PR CI publishes generated API documentation as the `api-docs` workflow artifact.
|
|
729
|
+
|
|
730
|
+
`npm run verify:agent` runs brandless native, JavaScript-application, managed,
|
|
731
|
+
and browser prompts through a real local Codex CLI. Its JSON report measures
|
|
732
|
+
natural MCP use, first-tool routing, repeated calls, actual Codex token usage,
|
|
733
|
+
completion quality, and explicit treatment of authority and unknowns.
|
|
734
|
+
|
|
735
|
+
`npm run evidence:generate` regenerates the managed conformance manifest and
|
|
736
|
+
Evidence v2 completion ledger from live verifier output. `npm run
|
|
737
|
+
evidence:check` reruns the verifier and fails when artifacts, scenarios,
|
|
738
|
+
providers, schemas, claim counts, Evidence IDs, or the bundled skill have
|
|
739
|
+
drifted. Unsupported claims remain explicit and never count as passes.
|
|
740
|
+
Verifier JSON reports include an ephemeral `verifier_run` UUID allocated before
|
|
741
|
+
the verifier performs work and inherited by its child processes through
|
|
742
|
+
`REA_PROCESS_RUN_ID`. The final report includes the verifier and parent PIDs
|
|
743
|
+
plus `process_lineage` and its ISO `observed_at` timestamp: POSIX verifiers
|
|
744
|
+
report a token-verified, point-in-time launcher process group and live
|
|
745
|
+
descendants, while platforms without an owned
|
|
746
|
+
lineage primitive report `status: "unavailable"` and a reason. An empty verified
|
|
747
|
+
descendant list means no child was live during the final observation; it does
|
|
748
|
+
not claim the verifier launched no children earlier. Nested verifier entrypoints
|
|
749
|
+
in the same process reuse its UUID; each new verifier process replaces any
|
|
750
|
+
inherited parent token with a fresh run identity.
|
|
751
|
+
Generated completion commitments deliberately exclude this per-execution
|
|
752
|
+
identity, so check mode remains deterministic while live reports remain
|
|
753
|
+
attributable.
|
|
754
|
+
|
|
755
|
+
Owned Hopper shutdown logs retain the launcher PID, process-group ID, cleanup
|
|
756
|
+
status, and whether a verified group signal was required. They omit the run
|
|
757
|
+
token and unexpected exception text. The real-Hopper verifier also starts an
|
|
758
|
+
unrelated `Hopper`-named sentinel in a distinct process group and fails unless
|
|
759
|
+
that process survives every session close; the sentinel is removed only by the
|
|
760
|
+
verifier after the survival check.
|
|
695
761
|
|
|
696
762
|
## Project links
|
|
697
763
|
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { androidApplicationProjectionInputSchema, projectAndroidApplication, } from "../domain/androidApplication.js";
|
|
2
|
+
import { ANDROID_APPLICATION_PROVIDER } from "./InvestigationProviders.js";
|
|
3
|
+
import { projectInventoryEvidence } from "./InventoryProjectionEvidence.js";
|
|
4
|
+
const OPERATION = "project_android_application_graph";
|
|
5
|
+
/** Project authenticated APK inventory Evidence into Android application Evidence. */
|
|
6
|
+
export const projectAndroidApplicationEvidence = (rawInput) => {
|
|
7
|
+
return projectInventoryEvidence({
|
|
8
|
+
rawInput,
|
|
9
|
+
schema: androidApplicationProjectionInputSchema,
|
|
10
|
+
project: projectAndroidApplication,
|
|
11
|
+
operation: OPERATION,
|
|
12
|
+
predicateType: "rea.android-application-graph/v1",
|
|
13
|
+
provider: ANDROID_APPLICATION_PROVIDER,
|
|
14
|
+
subjectFormat: () => "apk",
|
|
15
|
+
protocolError: "Android application projection produced an invalid result",
|
|
16
|
+
});
|
|
17
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { appleApplicationProjectionInputSchema, projectAppleApplication, } from "../domain/appleApplication.js";
|
|
2
|
+
import { APPLE_APPLICATION_PROVIDER } from "./InvestigationProviders.js";
|
|
3
|
+
import { projectInventoryEvidence } from "./InventoryProjectionEvidence.js";
|
|
4
|
+
const OPERATION = "project_apple_application_graph";
|
|
5
|
+
/** Project authenticated IPA inventory Evidence into Apple application evidence. */
|
|
6
|
+
export const projectAppleApplicationEvidence = (rawInput) => {
|
|
7
|
+
return projectInventoryEvidence({
|
|
8
|
+
rawInput,
|
|
9
|
+
schema: appleApplicationProjectionInputSchema,
|
|
10
|
+
project: projectAppleApplication,
|
|
11
|
+
operation: OPERATION,
|
|
12
|
+
predicateType: "rea.apple-application-graph/v1",
|
|
13
|
+
provider: APPLE_APPLICATION_PROVIDER,
|
|
14
|
+
subjectFormat: () => "ipa",
|
|
15
|
+
protocolError: "Apple application projection produced an invalid result",
|
|
16
|
+
});
|
|
17
|
+
};
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { compareApplicationVersionsRequestSchema, compareJavaScriptExportShapesRequestSchema, traceApplicationFeatureRequestSchema, traceJavaScriptSemanticsRequestSchema, } from "../contracts/applicationWorkflowInputContracts.js";
|
|
3
|
+
import { AnalysisInputError } from "../domain/errors.js";
|
|
4
|
+
import { projectInputIssues } from "../domain/inputIssueProjection.js";
|
|
5
|
+
import { compareApplicationVersionsInputSchema } from "../domain/javascriptApplicationVersionComparisonSchemas.js";
|
|
6
|
+
import { compareJavaScriptExportShapesInputSchema } from "../domain/javascriptExportShapeComparisonSchemas.js";
|
|
7
|
+
import { traceApplicationFeatureInputSchema } from "../domain/javascriptFeatureTraceSchemas.js";
|
|
8
|
+
import { traceJavaScriptSemanticsInputSchema } from "../domain/javascriptSemanticTraceSchemas.js";
|
|
9
|
+
import { err, ok } from "../domain/result.js";
|
|
10
|
+
import { resolveEvidenceReferences, } from "./EvidenceReferenceResolver.js";
|
|
11
|
+
const APPLICATION_GRAPH_IDENTITIES = [
|
|
12
|
+
{
|
|
13
|
+
operation: "analyze_javascript_application",
|
|
14
|
+
predicate: "rea.javascript-application-analysis/v1",
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
operation: "analyze_javascript_application",
|
|
18
|
+
predicate: "rea.javascript-application-analysis/v2",
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
operation: "reconcile_javascript_runtime",
|
|
22
|
+
predicate: "rea.javascript-runtime-reconciliation/v1",
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
operation: "project_managed_application_graph",
|
|
26
|
+
predicate: "rea.managed-application-graph/v1",
|
|
27
|
+
},
|
|
28
|
+
];
|
|
29
|
+
/** Parse and resolve one trace adapter request into its canonical domain input. */
|
|
30
|
+
export const resolveTraceApplicationFeatureRequest = (input, lookup) => {
|
|
31
|
+
const parsed = traceApplicationFeatureRequestSchema.safeParse(input);
|
|
32
|
+
return parsed.success
|
|
33
|
+
? resolveTraceApplicationFeatureRequestValidated(parsed.data, lookup)
|
|
34
|
+
: invalid("trace_application_feature", parsed.error, input);
|
|
35
|
+
};
|
|
36
|
+
/** Resolve a trace request already parsed by the caller-facing contract. */
|
|
37
|
+
export const resolveTraceApplicationFeatureRequestValidated = (input, lookup) => {
|
|
38
|
+
const application = input.application === undefined
|
|
39
|
+
? resolveEvidenceReferences(lookup, input.application_evidence_id === undefined
|
|
40
|
+
? []
|
|
41
|
+
: [input.application_evidence_id], APPLICATION_GRAPH_IDENTITIES)
|
|
42
|
+
: ok([input.application]);
|
|
43
|
+
if (!application.ok)
|
|
44
|
+
return application;
|
|
45
|
+
const native = resolveEvidenceReferences(lookup, input.native_observation_evidence_ids);
|
|
46
|
+
if (!native.ok)
|
|
47
|
+
return native;
|
|
48
|
+
const raw = {
|
|
49
|
+
application: application.value[0],
|
|
50
|
+
native_observations: [...input.native_observations, ...native.value],
|
|
51
|
+
seed: input.seed,
|
|
52
|
+
direction: input.direction,
|
|
53
|
+
limits: input.limits,
|
|
54
|
+
};
|
|
55
|
+
const parsed = traceApplicationFeatureInputSchema.safeParse(raw);
|
|
56
|
+
return parsed.success
|
|
57
|
+
? ok(parsed.data)
|
|
58
|
+
: invalid("trace_application_feature", parsed.error, raw);
|
|
59
|
+
};
|
|
60
|
+
/** Parse and resolve one semantic trace adapter request. */
|
|
61
|
+
export const resolveTraceJavaScriptSemanticsRequest = (input, lookup) => {
|
|
62
|
+
const parsed = traceJavaScriptSemanticsRequestSchema.safeParse(input);
|
|
63
|
+
return parsed.success
|
|
64
|
+
? resolveTraceJavaScriptSemanticsRequestValidated(parsed.data, lookup)
|
|
65
|
+
: invalid("trace_javascript_semantics", parsed.error, input);
|
|
66
|
+
};
|
|
67
|
+
/** Resolve a semantic trace request already parsed by its public contract. */
|
|
68
|
+
export const resolveTraceJavaScriptSemanticsRequestValidated = (input, lookup) => {
|
|
69
|
+
const application = input.application === undefined
|
|
70
|
+
? resolveEvidenceReferences(lookup, input.application_evidence_id === undefined
|
|
71
|
+
? []
|
|
72
|
+
: [input.application_evidence_id], APPLICATION_GRAPH_IDENTITIES)
|
|
73
|
+
: ok([input.application]);
|
|
74
|
+
if (!application.ok)
|
|
75
|
+
return application;
|
|
76
|
+
const raw = { application: application.value[0], query: input.query };
|
|
77
|
+
const parsed = traceJavaScriptSemanticsInputSchema.safeParse(raw);
|
|
78
|
+
return parsed.success
|
|
79
|
+
? ok(parsed.data)
|
|
80
|
+
: invalid("trace_javascript_semantics", parsed.error, raw);
|
|
81
|
+
};
|
|
82
|
+
/** Parse and resolve one comparison adapter request into canonical input. */
|
|
83
|
+
export const resolveCompareApplicationVersionsRequest = (input, lookup) => {
|
|
84
|
+
const parsed = compareApplicationVersionsRequestSchema.safeParse(input);
|
|
85
|
+
return parsed.success
|
|
86
|
+
? resolveCompareApplicationVersionsRequestValidated(parsed.data, lookup)
|
|
87
|
+
: invalid("compare_application_versions", parsed.error, input);
|
|
88
|
+
};
|
|
89
|
+
/** Resolve a comparison request parsed by the caller-facing contract. */
|
|
90
|
+
export const resolveCompareApplicationVersionsRequestValidated = (input, lookup) => {
|
|
91
|
+
const left = graphEvidence(input.left, input.left_evidence_id, lookup);
|
|
92
|
+
if (!left.ok)
|
|
93
|
+
return left;
|
|
94
|
+
const right = graphEvidence(input.right, input.right_evidence_id, lookup);
|
|
95
|
+
if (!right.ok)
|
|
96
|
+
return right;
|
|
97
|
+
const leftNative = resolveEvidenceReferences(lookup, input.left_native_observation_evidence_ids);
|
|
98
|
+
if (!leftNative.ok)
|
|
99
|
+
return leftNative;
|
|
100
|
+
const rightNative = resolveEvidenceReferences(lookup, input.right_native_observation_evidence_ids);
|
|
101
|
+
if (!rightNative.ok)
|
|
102
|
+
return rightNative;
|
|
103
|
+
const raw = {
|
|
104
|
+
left: left.value,
|
|
105
|
+
right: right.value,
|
|
106
|
+
left_native_observations: [
|
|
107
|
+
...input.left_native_observations,
|
|
108
|
+
...leftNative.value,
|
|
109
|
+
],
|
|
110
|
+
right_native_observations: [
|
|
111
|
+
...input.right_native_observations,
|
|
112
|
+
...rightNative.value,
|
|
113
|
+
],
|
|
114
|
+
limits: input.limits,
|
|
115
|
+
...(input.unknown_registry_approved === undefined
|
|
116
|
+
? {}
|
|
117
|
+
: { unknown_registry_approved: input.unknown_registry_approved }),
|
|
118
|
+
};
|
|
119
|
+
const parsed = compareApplicationVersionsInputSchema.safeParse(raw);
|
|
120
|
+
return parsed.success
|
|
121
|
+
? ok(parsed.data)
|
|
122
|
+
: invalid("compare_application_versions", parsed.error, raw);
|
|
123
|
+
};
|
|
124
|
+
/** Parse and resolve an export-shape adapter request into canonical input. */
|
|
125
|
+
export const resolveCompareJavaScriptExportShapesRequest = (input, lookup) => {
|
|
126
|
+
const parsed = compareJavaScriptExportShapesRequestSchema.safeParse(input);
|
|
127
|
+
return parsed.success
|
|
128
|
+
? resolveCompareJavaScriptExportShapesRequestValidated(parsed.data, lookup)
|
|
129
|
+
: invalid("compare_javascript_export_shapes", parsed.error, input);
|
|
130
|
+
};
|
|
131
|
+
/** Resolve an export-shape request already parsed by the adapter contract. */
|
|
132
|
+
export const resolveCompareJavaScriptExportShapesRequestValidated = (input, lookup) => {
|
|
133
|
+
const left = graphEvidence(input.left, input.left_evidence_id, lookup);
|
|
134
|
+
if (!left.ok)
|
|
135
|
+
return left;
|
|
136
|
+
const right = graphEvidence(input.right, input.right_evidence_id, lookup);
|
|
137
|
+
if (!right.ok)
|
|
138
|
+
return right;
|
|
139
|
+
const raw = {
|
|
140
|
+
left: left.value,
|
|
141
|
+
right: right.value,
|
|
142
|
+
left_module_path: input.left_module_path,
|
|
143
|
+
left_export_name: input.left_export_name,
|
|
144
|
+
right_module_path: input.right_module_path,
|
|
145
|
+
right_export_name: input.right_export_name,
|
|
146
|
+
limits: input.limits,
|
|
147
|
+
...(input.unknown_registry_approved === undefined
|
|
148
|
+
? {}
|
|
149
|
+
: { unknown_registry_approved: input.unknown_registry_approved }),
|
|
150
|
+
};
|
|
151
|
+
const parsed = compareJavaScriptExportShapesInputSchema.safeParse(raw);
|
|
152
|
+
return parsed.success
|
|
153
|
+
? ok(parsed.data)
|
|
154
|
+
: invalid("compare_javascript_export_shapes", parsed.error, raw);
|
|
155
|
+
};
|
|
156
|
+
const graphEvidence = (evidence, evidenceId, lookup) => {
|
|
157
|
+
if (evidence !== undefined)
|
|
158
|
+
return ok(evidence);
|
|
159
|
+
const resolved = resolveEvidenceReferences(lookup, evidenceId === undefined ? [] : [evidenceId], APPLICATION_GRAPH_IDENTITIES);
|
|
160
|
+
return resolved.ok ? ok(resolved.value[0]) : resolved;
|
|
161
|
+
};
|
|
162
|
+
const invalid = (operation, cause, input) => err(new AnalysisInputError(operation, undefined, projectInputIssues(cause.issues, input)));
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
1
2
|
import { analysisProfilesEqual, } from "../domain/analysisProfile.js";
|
|
2
3
|
import { AnalysisCancelledError, ProviderAdapterError, } from "../domain/errors.js";
|
|
3
4
|
import { err, ok } from "../domain/result.js";
|
|
@@ -116,7 +117,8 @@ export class BinarySession extends BinarySessionRecords {
|
|
|
116
117
|
const previous = this.#active;
|
|
117
118
|
this.#active = undefined;
|
|
118
119
|
await previous?.client.close();
|
|
119
|
-
const
|
|
120
|
+
const runId = randomUUID();
|
|
121
|
+
const client = route.createClient(target, { runId });
|
|
120
122
|
const started = await client.execute("health", {}, options);
|
|
121
123
|
if (!started.ok) {
|
|
122
124
|
await client.close();
|
|
@@ -134,6 +136,7 @@ export class BinarySession extends BinarySessionRecords {
|
|
|
134
136
|
profile,
|
|
135
137
|
compatibility: structuredClone(compatibility),
|
|
136
138
|
route,
|
|
139
|
+
runId,
|
|
137
140
|
};
|
|
138
141
|
this.#clearRuntimeAvailability();
|
|
139
142
|
if (profile === null)
|
|
@@ -172,6 +175,8 @@ export class BinarySession extends BinarySessionRecords {
|
|
|
172
175
|
route: this.#currentRoute(),
|
|
173
176
|
router: this.#providerRouter,
|
|
174
177
|
runtimeAvailability: this.#runtimeAvailability,
|
|
178
|
+
runId: this.#active?.runId,
|
|
179
|
+
runtimeLineageSnapshots: this.#active?.client.runtimeLineageSnapshots?.() ?? [],
|
|
175
180
|
});
|
|
176
181
|
}
|
|
177
182
|
/** Return the immutable artifact identity captured before its provider started. */
|
|
@@ -300,7 +305,8 @@ export class BinarySession extends BinarySessionRecords {
|
|
|
300
305
|
async #restore(previous) {
|
|
301
306
|
if (previous === undefined)
|
|
302
307
|
return;
|
|
303
|
-
const
|
|
308
|
+
const runId = randomUUID();
|
|
309
|
+
const client = previous.route.createClient(previous.target, { runId });
|
|
304
310
|
const started = await client.execute("health", {});
|
|
305
311
|
if (started.ok)
|
|
306
312
|
this.#active = {
|
|
@@ -309,6 +315,7 @@ export class BinarySession extends BinarySessionRecords {
|
|
|
309
315
|
profile: previous.profile,
|
|
310
316
|
compatibility: previous.compatibility,
|
|
311
317
|
route: previous.route,
|
|
318
|
+
runId,
|
|
312
319
|
};
|
|
313
320
|
else
|
|
314
321
|
await client.close();
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** Project internal provider routing state into the caller-visible session status. */
|
|
2
|
-
export const binarySessionStatus = ({ target, route, router, runtimeAvailability, }) => {
|
|
2
|
+
export const binarySessionStatus = ({ target, route, router, runtimeAvailability, runId, runtimeLineageSnapshots, }) => {
|
|
3
3
|
const configuredProvider = router.configuredIdentity();
|
|
4
4
|
const provider = providerSummary(configuredProvider);
|
|
5
5
|
const providers = router.providerIdentities(route).map(providerSummary);
|
|
@@ -35,6 +35,12 @@ export const binarySessionStatus = ({ target, route, router, runtimeAvailability
|
|
|
35
35
|
capabilities,
|
|
36
36
|
analysis_provider_binding: analysisProviderBinding,
|
|
37
37
|
analysis_provider_candidates: analysisProviderCandidates,
|
|
38
|
+
analysis_run: runId === undefined
|
|
39
|
+
? null
|
|
40
|
+
: {
|
|
41
|
+
run_id: runId,
|
|
42
|
+
process_lineage: processLineageStatus(runtimeLineageSnapshots),
|
|
43
|
+
},
|
|
38
44
|
};
|
|
39
45
|
return target === undefined
|
|
40
46
|
? { open: false, ...common }
|
|
@@ -49,6 +55,38 @@ export const binarySessionStatus = ({ target, route, router, runtimeAvailability
|
|
|
49
55
|
};
|
|
50
56
|
};
|
|
51
57
|
const providerSummary = ({ id, name, version, }) => ({ id, name, version });
|
|
58
|
+
const processLineageStatus = (snapshots) => snapshots.length === 0
|
|
59
|
+
? { status: "not_observed" }
|
|
60
|
+
: {
|
|
61
|
+
status: "snapshots",
|
|
62
|
+
snapshots: snapshots
|
|
63
|
+
.slice()
|
|
64
|
+
.sort((left, right) => left.provider.id.localeCompare(right.provider.id))
|
|
65
|
+
.map(({ provider, observation }) => ({
|
|
66
|
+
provider: providerSummary(provider),
|
|
67
|
+
observation: observation.status === "unavailable"
|
|
68
|
+
? {
|
|
69
|
+
status: observation.status,
|
|
70
|
+
observed_at: observation.observedAt,
|
|
71
|
+
launcher_pid: observation.launcherPid,
|
|
72
|
+
process_group_id: observation.processGroupId,
|
|
73
|
+
reason: observation.reason,
|
|
74
|
+
}
|
|
75
|
+
: {
|
|
76
|
+
status: observation.status,
|
|
77
|
+
observed_at: observation.observedAt,
|
|
78
|
+
schema_version: observation.lineage.schemaVersion,
|
|
79
|
+
launcher_pid: observation.lineage.launcherPid,
|
|
80
|
+
launcher_parent_pid: observation.lineage.launcherParentPid,
|
|
81
|
+
process_group_id: observation.lineage.processGroupId,
|
|
82
|
+
descendants: observation.lineage.descendants.map(({ pid, parentPid, processGroupId }) => ({
|
|
83
|
+
pid,
|
|
84
|
+
parent_pid: parentPid,
|
|
85
|
+
process_group_id: processGroupId,
|
|
86
|
+
})),
|
|
87
|
+
},
|
|
88
|
+
})),
|
|
89
|
+
};
|
|
52
90
|
const capabilityStatus = (descriptor) => ({
|
|
53
91
|
operation: descriptor.operation,
|
|
54
92
|
available: descriptor.available,
|
|
@@ -62,6 +62,9 @@ export const buildCapabilityInventory = (sessionStatus, policy) => {
|
|
|
62
62
|
}).sort((left, right) => left.name.localeCompare(right.name));
|
|
63
63
|
};
|
|
64
64
|
const availabilityFor = (context) => {
|
|
65
|
+
const javascriptApplication = javascriptApplicationAvailability(context);
|
|
66
|
+
if (javascriptApplication !== null)
|
|
67
|
+
return javascriptApplication;
|
|
65
68
|
const policyDecision = policyAvailability(context);
|
|
66
69
|
if (policyDecision !== null)
|
|
67
70
|
return policyDecision;
|
|
@@ -70,6 +73,18 @@ const availabilityFor = (context) => {
|
|
|
70
73
|
return targetDecision;
|
|
71
74
|
return providerAvailability(context);
|
|
72
75
|
};
|
|
76
|
+
const javascriptApplicationAvailability = ({ name, policy, }) => {
|
|
77
|
+
if (name === "analyze_javascript_application")
|
|
78
|
+
return policy.investigationInputRoots === 0
|
|
79
|
+
? {
|
|
80
|
+
reason: "policy_disabled",
|
|
81
|
+
remediation: "Configure an exact REA_INVESTIGATION_INPUT_ROOTS_JSON root in the MCP registration, then restart the registered MCP server or client.",
|
|
82
|
+
}
|
|
83
|
+
: { reason: "available", remediation: null };
|
|
84
|
+
return name === "reconcile_javascript_runtime"
|
|
85
|
+
? { reason: "available", remediation: null }
|
|
86
|
+
: null;
|
|
87
|
+
};
|
|
73
88
|
const policyAvailability = ({ name, kind, policy, }) => {
|
|
74
89
|
if (name === "capture_process_scenario" && !policy.processCaptureEnabled)
|
|
75
90
|
return {
|
|
@@ -6,7 +6,11 @@ import { PRODUCT_IDENTITY } from "../identity.js";
|
|
|
6
6
|
import { supportedClients } from "./SupportedClients.js";
|
|
7
7
|
const objectSchema = z.record(z.string(), z.unknown());
|
|
8
8
|
const registrationSchema = z
|
|
9
|
-
.object({
|
|
9
|
+
.object({
|
|
10
|
+
command: z.string().min(1),
|
|
11
|
+
args: z.array(z.string()).default([]),
|
|
12
|
+
startup_timeout_sec: z.number().positive().optional(),
|
|
13
|
+
})
|
|
10
14
|
.passthrough();
|
|
11
15
|
/** Inspect supported client registrations without reading their environment. */
|
|
12
16
|
export const readClientRegistrationStatuses = async (home, currentCommandPath = resolve(process.argv[1] ?? "unknown")) => {
|
|
@@ -25,7 +29,7 @@ export const readClientRegistrationStatuses = async (home, currentCommandPath =
|
|
|
25
29
|
}
|
|
26
30
|
const registration = registrationSchema.parse(raw);
|
|
27
31
|
const command = [registration.command, ...registration.args];
|
|
28
|
-
statuses.push(status(client.name, client.configPath, command, registrationAligned(
|
|
32
|
+
statuses.push(status(client.name, client.configPath, command, registrationAligned(registration, client.name, currentCommandPath)
|
|
29
33
|
? "aligned"
|
|
30
34
|
: "stale"));
|
|
31
35
|
}
|
|
@@ -35,11 +39,14 @@ export const readClientRegistrationStatuses = async (home, currentCommandPath =
|
|
|
35
39
|
}
|
|
36
40
|
return statuses.sort((left, right) => left.client.localeCompare(right.client));
|
|
37
41
|
};
|
|
38
|
-
const registrationAligned = (
|
|
42
|
+
const registrationAligned = (registration, client, currentCommandPath) => {
|
|
43
|
+
const command = [registration.command, ...registration.args];
|
|
44
|
+
if (client === "codex" && registration.startup_timeout_sec !== 30)
|
|
45
|
+
return false;
|
|
39
46
|
if (command.length === 4 &&
|
|
40
47
|
command[0] === "npx" &&
|
|
41
48
|
command[1] === "-y" &&
|
|
42
|
-
command[2] === PRODUCT_IDENTITY.
|
|
49
|
+
command[2] === PRODUCT_IDENTITY.registrationPackageSpecifier &&
|
|
43
50
|
command[3] === "mcp")
|
|
44
51
|
return true;
|
|
45
52
|
return (command.length === 2 &&
|
|
@@ -27,7 +27,7 @@ const shellQuote = (value) => `'${value.replaceAll("'", `'\\''`)}'`;
|
|
|
27
27
|
* would make an unmatched dependency call look authoritative. Unmatched and
|
|
28
28
|
* exhausted routes therefore fail visibly and remain part of the capture.
|
|
29
29
|
*/
|
|
30
|
-
export const startCommandShimReplay = async (scenario, temporaryRoot, started) => {
|
|
30
|
+
export const startCommandShimReplay = async (scenario, temporaryRoot, started, recordEvent = () => undefined) => {
|
|
31
31
|
const binPath = join(temporaryRoot, "shims");
|
|
32
32
|
await mkdir(binPath);
|
|
33
33
|
const runnerPath = join(temporaryRoot, "shim-runner.mjs");
|
|
@@ -62,9 +62,10 @@ export const startCommandShimReplay = async (scenario, temporaryRoot, started) =
|
|
|
62
62
|
: "matched";
|
|
63
63
|
if (events.length >= scenario.limits.protocol_events)
|
|
64
64
|
truncated = true;
|
|
65
|
-
else
|
|
65
|
+
else {
|
|
66
|
+
const index = events.length;
|
|
66
67
|
events.push({
|
|
67
|
-
sequence:
|
|
68
|
+
sequence: index,
|
|
68
69
|
at_ms: Math.max(0, Date.now() - started),
|
|
69
70
|
command: invocation.command,
|
|
70
71
|
route_index: routeIndex !== undefined && routeIndex >= 0 ? routeIndex : null,
|
|
@@ -72,6 +73,8 @@ export const startCommandShimReplay = async (scenario, temporaryRoot, started) =
|
|
|
72
73
|
working_directory: invocation.working_directory,
|
|
73
74
|
outcome,
|
|
74
75
|
});
|
|
76
|
+
recordEvent("shim_events", index);
|
|
77
|
+
}
|
|
75
78
|
if (outcome !== "matched" || route === undefined) {
|
|
76
79
|
response.writeHead(409).end();
|
|
77
80
|
return;
|
|
@@ -51,13 +51,13 @@ export class CompositeProvider {
|
|
|
51
51
|
? Promise.resolve(ok({ profile: null, compatibility: {} }))
|
|
52
52
|
: resolve.call(this.#profileProvider, target, options);
|
|
53
53
|
}
|
|
54
|
-
createClient(target, profile) {
|
|
54
|
+
createClient(target, profile, context) {
|
|
55
55
|
const clients = new Map();
|
|
56
56
|
const clientFor = (provider) => {
|
|
57
57
|
const existing = clients.get(provider);
|
|
58
58
|
if (existing !== undefined)
|
|
59
59
|
return existing;
|
|
60
|
-
const created = provider.createClient(target, profile?.provider.id === provider.identity().id ? profile : undefined);
|
|
60
|
+
const created = provider.createClient(target, profile?.provider.id === provider.identity().id ? profile : undefined, context);
|
|
61
61
|
clients.set(provider, created);
|
|
62
62
|
return created;
|
|
63
63
|
};
|
|
@@ -77,6 +77,9 @@ export class CompositeProvider {
|
|
|
77
77
|
? Promise.resolve(err(new AnalysisCapabilityUnavailableError(this.#identity.id, operation, "operation is not declared by this provider set")))
|
|
78
78
|
: clientFor(provider).execute(operation, parameters, options);
|
|
79
79
|
},
|
|
80
|
+
runtimeLineageSnapshots: () => [...clients.values()]
|
|
81
|
+
.flatMap((client) => client.runtimeLineageSnapshots?.() ?? [])
|
|
82
|
+
.sort((left, right) => left.provider.id.localeCompare(right.provider.id)),
|
|
80
83
|
close: async () => {
|
|
81
84
|
await Promise.allSettled([...clients.values()].map(async (client) => client.close()));
|
|
82
85
|
},
|