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.
Files changed (193) hide show
  1. package/README.md +84 -18
  2. package/dist/application/AndroidApplicationService.js +17 -0
  3. package/dist/application/AppleApplicationService.js +17 -0
  4. package/dist/application/ApplicationWorkflowEvidenceResolver.js +162 -0
  5. package/dist/application/BinarySession.js +9 -2
  6. package/dist/application/BinarySessionStatus.js +39 -1
  7. package/dist/application/CapabilityInventory.js +15 -0
  8. package/dist/application/ClientRegistrationStatus.js +11 -4
  9. package/dist/application/CommandShimReplay.js +6 -3
  10. package/dist/application/CompositeProvider.js +5 -2
  11. package/dist/application/DirectAnalysis.js +1 -20
  12. package/dist/application/DirectAnalysisStatus.js +83 -0
  13. package/dist/application/Doctor.js +34 -25
  14. package/dist/application/DoctorDiagnostics.js +1 -4
  15. package/dist/application/DoctorProjection.js +43 -0
  16. package/dist/application/DoctorScope.js +102 -0
  17. package/dist/application/EvidenceReferenceResolver.js +26 -0
  18. package/dist/application/InventoryProjectionEvidence.js +41 -0
  19. package/dist/application/InvestigationProviders.js +12 -0
  20. package/dist/application/JavaScriptApplicationEvidence.js +1 -1
  21. package/dist/application/JavaScriptApplicationEvidenceGraph.js +10 -1
  22. package/dist/application/JavaScriptApplicationService.js +3 -2
  23. package/dist/application/JavaScriptApplicationWorkflowEvidence.js +26 -0
  24. package/dist/application/JavaScriptApplicationWorkflowService.js +49 -1
  25. package/dist/application/JavaScriptArtifactReconstruction.js +7 -0
  26. package/dist/application/JavaScriptModuleRelationships.js +25 -1
  27. package/dist/application/JavaScriptReturnShapeProjection.js +111 -0
  28. package/dist/application/JavaScriptSemanticGraphBuilder.js +294 -0
  29. package/dist/application/JavaScriptSemanticGraphConstruction.js +144 -0
  30. package/dist/application/JavaScriptSemanticGraphEvidence.js +86 -0
  31. package/dist/application/JavaScriptSemanticGraphFlowProjection.js +72 -0
  32. package/dist/application/JavaScriptSemanticGraphProjection.js +33 -0
  33. package/dist/application/JavaScriptSemanticTraceService.js +45 -0
  34. package/dist/application/LoopbackReplay.js +277 -133
  35. package/dist/application/LoopbackReplayRecorder.js +101 -0
  36. package/dist/application/PermissionAuthority.js +7 -3
  37. package/dist/application/ProcessCaptureJournal.js +95 -0
  38. package/dist/application/ProcessCaptureLifecycle.js +24 -13
  39. package/dist/application/ProcessCheckpoints.js +30 -4
  40. package/dist/application/ProcessCli.js +26 -4
  41. package/dist/application/ProcessHarness.js +20 -50
  42. package/dist/application/ProcessNormalization.js +3 -2
  43. package/dist/application/ProcessPairedExperiment.js +72 -0
  44. package/dist/application/ProcessReactiveCoordinator.js +218 -0
  45. package/dist/application/ProcessReactiveEffects.js +133 -0
  46. package/dist/application/ProcessReactiveObservations.js +20 -0
  47. package/dist/application/ProcessSampling.js +2 -0
  48. package/dist/application/SessionProviderRouter.js +7 -6
  49. package/dist/application/Setup.js +14 -13
  50. package/dist/application/SetupClientConfiguration.js +10 -6
  51. package/dist/application/SetupPlan.js +4 -3
  52. package/dist/application/SetupRegistrationEnvironment.js +12 -0
  53. package/dist/application/SetupSkill.js +44 -40
  54. package/dist/application/TerminalRenderer.js +3 -1
  55. package/dist/application/Uninstall.js +7 -1
  56. package/dist/application/Upgrade.js +16 -1
  57. package/dist/browser/CdpEndpoint.js +37 -4
  58. package/dist/catalogIdentity.js +16 -7
  59. package/dist/cli/coreAnalysisCommands.js +34 -2
  60. package/dist/cli/javascriptApplicationAnalysis.js +19 -0
  61. package/dist/cli/setupCommands.js +84 -30
  62. package/dist/cli/utilityCommands.js +10 -2
  63. package/dist/cliApplicationCommands.js +79 -16
  64. package/dist/cliCommandNames.js +3 -0
  65. package/dist/cliElectronCommands.js +23 -33
  66. package/dist/cliObservationOptions.js +1 -1
  67. package/dist/cliOutput.js +56 -0
  68. package/dist/cliProcessCommands.js +32 -1
  69. package/dist/cliSetup.js +55 -29
  70. package/dist/contracts/applicationToolContracts.js +54 -7
  71. package/dist/contracts/applicationWorkflowInputContracts.js +119 -0
  72. package/dist/contracts/electronToolContracts.js +73 -4
  73. package/dist/contracts/javascriptApplicationWorkflowExamples.js +32 -9
  74. package/dist/contracts/managedToolContracts.js +7 -2
  75. package/dist/contracts/processCaptureExample.js +1 -0
  76. package/dist/contracts/replayMachineExample.js +37 -0
  77. package/dist/contracts/sessionStatusContract.js +26 -0
  78. package/dist/contracts/toolContractExamples.js +2 -0
  79. package/dist/contracts/toolContractTypes.js +12 -1
  80. package/dist/contracts/toolContracts.js +8 -11
  81. package/dist/contracts/toolEffects.js +3 -0
  82. package/dist/contracts/toolOutputSchemaGroups.js +53 -9
  83. package/dist/contracts/toolOutputSchemaPrimitives.js +73 -32
  84. package/dist/doctorRuntime.js +41 -0
  85. package/dist/domain/analysisErrorPresentation.js +5 -3
  86. package/dist/domain/analysisErrorProjection.js +7 -1
  87. package/dist/domain/androidApplication.js +206 -0
  88. package/dist/domain/appleApplication.js +221 -0
  89. package/dist/domain/boundedCartesianProjection.js +15 -0
  90. package/dist/domain/changedBehavior.js +5 -4
  91. package/dist/domain/completionLedgerGeneration.js +190 -0
  92. package/dist/domain/errors.js +4 -2
  93. package/dist/domain/evidenceCompletionLedger.js +113 -0
  94. package/dist/domain/hopperStartupFailure.js +9 -0
  95. package/dist/domain/javascriptApplicationAnalysis.js +44 -2
  96. package/dist/domain/javascriptExportShapeComparison.js +145 -0
  97. package/dist/domain/javascriptExportShapeComparisonIdentity.js +11 -0
  98. package/dist/domain/javascriptExportShapeComparisonSchemas.js +277 -0
  99. package/dist/domain/javascriptExportShapeSelection.js +132 -0
  100. package/dist/domain/javascriptExportShapeVariants.js +272 -0
  101. package/dist/domain/javascriptRuntimeReconciliationParsing.js +2 -2
  102. package/dist/domain/javascriptSemanticAnalysis.js +17 -36
  103. package/dist/domain/javascriptSemanticCallResolution.js +129 -0
  104. package/dist/domain/javascriptSemanticCalls.js +269 -0
  105. package/dist/domain/javascriptSemanticGraph.js +356 -0
  106. package/dist/domain/javascriptSemanticGraphSchemas.js +329 -0
  107. package/dist/domain/javascriptSemanticGraphSerialization.js +23 -0
  108. package/dist/domain/javascriptSemanticIr.js +14 -1
  109. package/dist/domain/javascriptSemanticPrimitives.js +36 -0
  110. package/dist/domain/javascriptSemanticProjection.js +36 -4
  111. package/dist/domain/javascriptSemanticProvenance.js +29 -0
  112. package/dist/domain/javascriptSemanticQuery.js +294 -0
  113. package/dist/domain/javascriptSemanticQueryAssessment.js +74 -0
  114. package/dist/domain/javascriptSemanticQueryIdentity.js +86 -0
  115. package/dist/domain/javascriptSemanticQueryRelations.js +15 -0
  116. package/dist/domain/javascriptSemanticQuerySchemas.js +188 -0
  117. package/dist/domain/javascriptSemanticReturns.js +187 -0
  118. package/dist/domain/javascriptSemanticState.js +32 -0
  119. package/dist/domain/javascriptSemanticTraceSchemas.js +14 -0
  120. package/dist/domain/javascriptSemanticValues.js +54 -70
  121. package/dist/domain/processCapture.js +36 -0
  122. package/dist/domain/processCaptureValidation.js +101 -12
  123. package/dist/domain/processComparison.js +96 -24
  124. package/dist/domain/processObservation.js +153 -0
  125. package/dist/domain/processPairedExperiment.js +128 -0
  126. package/dist/domain/processReactiveCheckpointDataflow.js +32 -0
  127. package/dist/domain/processReactiveMatching.js +210 -0
  128. package/dist/domain/processReactiveRuntime.js +109 -0
  129. package/dist/domain/processReactiveScenario.js +361 -0
  130. package/dist/domain/processReactiveScenarioPreflight.js +120 -0
  131. package/dist/domain/processReactiveTransition.js +159 -0
  132. package/dist/domain/processScenario.js +12 -0
  133. package/dist/domain/processTraceComparison.js +43 -0
  134. package/dist/domain/processTraceDimensionProjection.js +50 -0
  135. package/dist/domain/processTraceEvaluation.js +312 -0
  136. package/dist/domain/processTraceSpecification.js +373 -0
  137. package/dist/domain/reconstructionVerification.js +5 -4
  138. package/dist/domain/replayMachine.js +332 -0
  139. package/dist/domain/replayMachineRun.js +216 -0
  140. package/dist/domain/replayMachineRuntime.js +294 -0
  141. package/dist/domain/runtimeIdentification.js +210 -0
  142. package/dist/domain/staticRuntimeCorrelation.js +4 -2
  143. package/dist/evaluation/CodexAgentEval.js +156 -0
  144. package/dist/generatedPackageMetadata.js +2 -2
  145. package/dist/ghidra/GhidraClient.js +13 -2
  146. package/dist/ghidra/GhidraDiagnostics.js +1 -0
  147. package/dist/ghidra/GhidraLauncher.js +7 -3
  148. package/dist/ghidra/GhidraProvider.js +8 -1
  149. package/dist/hopper/BridgeLauncher.js +56 -14
  150. package/dist/hopper/HopperClient.js +23 -10
  151. package/dist/hopper/HopperDiagnostics.js +14 -0
  152. package/dist/hopper/HopperProcessDiagnostic.js +14 -0
  153. package/dist/hopper/HopperProvider.js +8 -1
  154. package/dist/hopper/LinuxPrivateDisplayDiagnostic.js +72 -0
  155. package/dist/hopper/LinuxPrivateDisplayProbe.js +217 -0
  156. package/dist/identity.js +2 -1
  157. package/dist/main/transport.js +2 -0
  158. package/dist/mcpDoctor.js +310 -0
  159. package/dist/process/ProcessOwnership.js +200 -53
  160. package/dist/process/ProviderRunLineage.js +21 -0
  161. package/dist/server/createServer.js +8 -2
  162. package/dist/server/javascriptApplicationResult.js +106 -0
  163. package/dist/server/registerApplicationTools/characterization.js +3 -3
  164. package/dist/server/registerApplicationTools/compareExportShapes.js +37 -0
  165. package/dist/server/registerApplicationTools/compareVersions.js +12 -6
  166. package/dist/server/registerApplicationTools/controlledReplay.js +2 -2
  167. package/dist/server/registerApplicationTools/coverage.js +3 -3
  168. package/dist/server/registerApplicationTools/helpers.js +37 -25
  169. package/dist/server/registerApplicationTools/traceFeature.js +9 -5
  170. package/dist/server/registerApplicationTools/traceSemantics.js +30 -0
  171. package/dist/server/registerApplicationTools.js +4 -0
  172. package/dist/server/registerElectronTools.js +19 -5
  173. package/dist/server/registerEvidenceResources.js +7 -1
  174. package/dist/server/registerJavaScriptApplicationGraphResource.js +69 -0
  175. package/dist/server/registerManagedTools.js +18 -1
  176. package/dist/server/registerProcessComparisonTool.js +17 -7
  177. package/dist/server/registerReplayMachineTool.js +20 -0
  178. package/dist/server/registerSessionStatusTool.js +95 -25
  179. package/dist/server/registerSessionTools.js +12 -7
  180. package/dist/server/sessionAvailabilityPolicy.js +2 -1
  181. package/dist/server/toolResult.js +10 -4
  182. package/dist/serverIdentity.js +19 -0
  183. package/package.json +62 -29
  184. package/scripts/hopper-demo-x11.py +459 -61
  185. package/scripts/prepack.mjs +55 -0
  186. package/scripts/prepare.mjs +28 -0
  187. package/scripts/rea.mjs +26 -5
  188. package/skills/reverse-engineer-anything/SKILL.md +69 -228
  189. package/skills/reverse-engineer-anything/references/controlled-replay.md +12 -0
  190. package/skills/reverse-engineer-anything/references/evidence-workflows.md +33 -0
  191. package/skills/reverse-engineer-anything/references/javascript-applications.md +35 -0
  192. package/skills/reverse-engineer-anything/references/native-and-artifacts.md +36 -0
  193. package/skills/reverse-engineer-anything/references/runtime-observation.md +24 -0
@@ -0,0 +1,43 @@
1
+ import { validateProcessCapture } from "./processCaptureValidation.js";
2
+ import { evaluateProcessTraceSide, processTraceComparisonResultSchema, } from "./processTraceEvaluation.js";
3
+ import { processTraceSpecificationSchema, } from "./processTraceSpecification.js";
4
+ export { processTraceComparisonResultSchema, } from "./processTraceEvaluation.js";
5
+ export { processTraceSourceSchema, processTraceSpecificationSchema, } from "./processTraceSpecification.js";
6
+ /** Compare two captures against an explicit finite trace language. */
7
+ export const compareProcessTraces = (left, right, specificationInput) => {
8
+ const captureIssues = [
9
+ ...validateProcessCapture(left),
10
+ ...validateProcessCapture(right),
11
+ ];
12
+ if (captureIssues.length > 0)
13
+ throw new TypeError(`Invalid Process Capture v4: ${captureIssues[0].path}`);
14
+ const specification = processTraceSpecificationSchema.parse(specificationInput);
15
+ const leftEvaluation = evaluateProcessTraceSide(left, specification);
16
+ const rightEvaluation = evaluateProcessTraceSide(right, specification);
17
+ const diagnostic = leftEvaluation.diagnostic === null
18
+ ? rightEvaluation.diagnostic === null
19
+ ? null
20
+ : { side: "right", ...rightEvaluation.diagnostic }
21
+ : { side: "left", ...leftEvaluation.diagnostic };
22
+ const outcomesDiffer = leftEvaluation.result.status !== rightEvaluation.result.status ||
23
+ JSON.stringify(leftEvaluation.result.raw_trace.map(({ event_id }) => event_id)) !==
24
+ JSON.stringify(rightEvaluation.result.raw_trace.map(({ event_id }) => event_id));
25
+ return processTraceComparisonResultSchema.parse({
26
+ verdict: leftEvaluation.result.status === "unknown" ||
27
+ rightEvaluation.result.status === "unknown"
28
+ ? "unknown"
29
+ : leftEvaluation.result.status === "pass" &&
30
+ rightEvaluation.result.status === "pass"
31
+ ? "equivalent"
32
+ : outcomesDiffer
33
+ ? "different"
34
+ : "nonconforming",
35
+ left: leftEvaluation.result,
36
+ right: rightEvaluation.result,
37
+ diagnostic,
38
+ });
39
+ };
40
+ /** Whether trace conformance or raw declared order differs across captures. */
41
+ export const processTraceOutcomesDiffer = (comparison) => comparison.left.status !== comparison.right.status ||
42
+ JSON.stringify(comparison.left.raw_trace.map(({ event_id }) => event_id)) !==
43
+ JSON.stringify(comparison.right.raw_trace.map(({ event_id }) => event_id));
@@ -0,0 +1,50 @@
1
+ /** Map declared trace sources to legacy process-comparison dimensions. */
2
+ export const dimensionsForTraceSources = (sources) => {
3
+ const dimensions = new Set();
4
+ for (const source of sources) {
5
+ if (source.startsWith("terminal_"))
6
+ dimensions.add("terminal");
7
+ else if (source === "interaction")
8
+ dimensions.add("interaction");
9
+ else if (source === "lifecycle")
10
+ dimensions.add("exit");
11
+ else if (source === "filesystem")
12
+ dimensions.add("filesystem");
13
+ else if (source === "http" ||
14
+ source === "websocket" ||
15
+ source === "replay_transition")
16
+ dimensions.add("protocol");
17
+ else if (source === "process")
18
+ dimensions.add("process");
19
+ else if (source === "shim")
20
+ dimensions.add("shim");
21
+ }
22
+ return dimensions;
23
+ };
24
+ /** Whether a trace specification covers every observed source in a dimension. */
25
+ export const traceCoversObservedDimension = (dimension, sources, left, right) => {
26
+ const any = (leftValues, rightValues) => leftValues.length > 0 || rightValues.length > 0;
27
+ switch (dimension) {
28
+ case "terminal":
29
+ return ((!any(left.frames, right.frames) || sources.has("terminal_raw")) &&
30
+ (!any(left.rendered_frames, right.rendered_frames) ||
31
+ sources.has("terminal_rendered")));
32
+ case "interaction":
33
+ return sources.has("interaction");
34
+ case "exit":
35
+ return sources.has("lifecycle");
36
+ case "filesystem":
37
+ return false;
38
+ case "protocol":
39
+ return ((![...left.protocol_events, ...right.protocol_events].some(({ protocol }) => protocol === "http") ||
40
+ sources.has("http")) &&
41
+ (![...left.protocol_events, ...right.protocol_events].some(({ protocol }) => protocol === "websocket") ||
42
+ sources.has("websocket")) &&
43
+ (!any(left.replay_transitions, right.replay_transitions) ||
44
+ sources.has("replay_transition")));
45
+ case "process":
46
+ return sources.has("process");
47
+ case "shim":
48
+ return sources.has("shim");
49
+ }
50
+ };
@@ -0,0 +1,312 @@
1
+ import { z } from "zod";
2
+ import { processObservationLocationSchema, projectProcessObservation, } from "./processObservation.js";
3
+ import { canonicalTraceJson, comparableTracePayload, processTraceCardinalityBounds, } from "./processTraceSpecification.js";
4
+ const identifierSchema = z.string().regex(/^[A-Za-z][A-Za-z0-9._-]{0,63}$/u);
5
+ const locationSchema = processObservationLocationSchema;
6
+ const matchedEventSchema = z.strictObject({
7
+ event_id: identifierSchema,
8
+ location: locationSchema,
9
+ });
10
+ const sideResultSchema = z.strictObject({
11
+ status: z.enum(["pass", "fail", "unknown"]),
12
+ matched_variant: identifierSchema.nullable(),
13
+ satisfied_constraints: z.array(z.string()),
14
+ raw_trace: z.array(matchedEventSchema),
15
+ });
16
+ const diagnosticSchema = z.strictObject({
17
+ kind: z.enum([
18
+ "journal",
19
+ "predicate",
20
+ "cardinality",
21
+ "edge",
22
+ "prefix",
23
+ "suffix",
24
+ "trace",
25
+ ]),
26
+ side: z.enum(["left", "right"]),
27
+ message: z.string(),
28
+ event_ids: z.array(identifierSchema),
29
+ locations: z.array(locationSchema),
30
+ });
31
+ /** Structured verdict for one declared process trace language. */
32
+ export const processTraceComparisonResultSchema = z.strictObject({
33
+ verdict: z.enum(["equivalent", "different", "nonconforming", "unknown"]),
34
+ left: sideResultSchema,
35
+ right: sideResultSchema,
36
+ diagnostic: diagnosticSchema.nullable(),
37
+ });
38
+ const scopesFor = (sources) => new Set([...sources].map((source) => {
39
+ if (source.startsWith("terminal_"))
40
+ return "terminal";
41
+ if (source === "lifecycle")
42
+ return "exit";
43
+ if (source === "http" ||
44
+ source === "websocket" ||
45
+ source === "replay_transition")
46
+ return "protocol";
47
+ if (source === "filesystem")
48
+ return "filesystem";
49
+ if (source === "process")
50
+ return "process";
51
+ if (source === "shim")
52
+ return "shim";
53
+ return "interaction";
54
+ }));
55
+ const unknownSide = () => ({
56
+ status: "unknown",
57
+ matched_variant: null,
58
+ satisfied_constraints: [],
59
+ raw_trace: [],
60
+ });
61
+ const failure = (input) => ({
62
+ result: {
63
+ status: "fail",
64
+ matched_variant: null,
65
+ satisfied_constraints: [],
66
+ raw_trace: input.rawTrace,
67
+ },
68
+ diagnostic: {
69
+ kind: input.kind,
70
+ message: input.message,
71
+ event_ids: [...input.eventIds],
72
+ locations: [...input.locations],
73
+ },
74
+ });
75
+ const evaluateFiniteTrace = (ids, specification) => {
76
+ if (specification.language.kind !== "finite_traces")
77
+ return null;
78
+ for (const variant of specification.language.variants) {
79
+ let offset = 0;
80
+ let accepted = true;
81
+ for (const token of variant.trace) {
82
+ if (typeof token === "string") {
83
+ if (ids[offset] !== token)
84
+ accepted = false;
85
+ offset += 1;
86
+ continue;
87
+ }
88
+ const actual = ids.slice(offset, offset + token.unordered.length).sort();
89
+ const expected = [...token.unordered].sort();
90
+ if (canonicalTraceJson(actual) !== canonicalTraceJson(expected))
91
+ accepted = false;
92
+ offset += token.unordered.length;
93
+ }
94
+ if (accepted && offset === ids.length)
95
+ return variant.id;
96
+ }
97
+ return null;
98
+ };
99
+ const collectRecords = (capture, sources) => {
100
+ const records = [];
101
+ for (const location of capture.event_journal ?? []) {
102
+ const record = projectProcessObservation(capture, location);
103
+ if (record !== null && sources.has(record.source))
104
+ records.push({
105
+ source: record.source,
106
+ payload: record.payload,
107
+ location,
108
+ });
109
+ }
110
+ return records;
111
+ };
112
+ const matchRecords = (records, specification) => {
113
+ const rawTrace = [];
114
+ const locationsById = new Map();
115
+ const ignoredFieldsBySource = new Map();
116
+ const eventsByKey = new Map();
117
+ for (const event of specification.events) {
118
+ const ignoredFields = event.ignore_fields ?? [];
119
+ ignoredFieldsBySource.set(event.source, ignoredFields);
120
+ eventsByKey.set(`${event.source}\0${canonicalTraceJson(comparableTracePayload(event.exact, ignoredFields))}`, event);
121
+ }
122
+ for (const record of records) {
123
+ const match = eventsByKey.get(`${record.source}\0${canonicalTraceJson(comparableTracePayload(record.payload, ignoredFieldsBySource.get(record.source)))}`);
124
+ if (match === undefined)
125
+ return failure({
126
+ kind: "predicate",
127
+ message: "Observed event does not match any declared exact predicate.",
128
+ eventIds: [],
129
+ locations: [record.location],
130
+ rawTrace,
131
+ });
132
+ rawTrace.push({ event_id: match.id, location: record.location });
133
+ const locations = locationsById.get(match.id) ?? [];
134
+ locations.push(record.location);
135
+ locationsById.set(match.id, locations);
136
+ }
137
+ return { rawTrace, locationsById };
138
+ };
139
+ const cardinalityFailure = (trace, specification) => {
140
+ for (const event of specification.events) {
141
+ const [minimum, maximum] = processTraceCardinalityBounds(event.cardinality);
142
+ const locations = trace.locationsById.get(event.id) ?? [];
143
+ if (locations.length < minimum || locations.length > maximum)
144
+ return failure({
145
+ kind: "cardinality",
146
+ message: `${event.id} observed ${String(locations.length)} times; expected ${String(minimum)}..${String(maximum)}.`,
147
+ eventIds: [event.id],
148
+ locations,
149
+ rawTrace: trace.rawTrace,
150
+ });
151
+ }
152
+ return null;
153
+ };
154
+ const evaluateOrderingConstraints = (trace, language) => {
155
+ const satisfied = [];
156
+ for (const edge of language.happens_before) {
157
+ const before = trace.locationsById.get(edge.before) ?? [];
158
+ const after = trace.locationsById.get(edge.after) ?? [];
159
+ const lastBefore = before.at(-1);
160
+ const firstAfter = after[0];
161
+ if (lastBefore === undefined && firstAfter !== undefined)
162
+ return {
163
+ failure: failure({
164
+ kind: "edge",
165
+ message: `${edge.before} is required when ${edge.after} occurs.`,
166
+ eventIds: [edge.before, edge.after],
167
+ locations: [firstAfter],
168
+ rawTrace: trace.rawTrace,
169
+ }),
170
+ satisfied,
171
+ };
172
+ if (lastBefore !== undefined &&
173
+ firstAfter !== undefined &&
174
+ lastBefore.capture_order >= firstAfter.capture_order)
175
+ return {
176
+ failure: failure({
177
+ kind: "edge",
178
+ message: `${edge.before} must happen before ${edge.after}.`,
179
+ eventIds: [edge.before, edge.after],
180
+ locations: [lastBefore, firstAfter],
181
+ rawTrace: trace.rawTrace,
182
+ }),
183
+ satisfied,
184
+ };
185
+ satisfied.push(`happens_before:${edge.before}:${edge.after}`);
186
+ }
187
+ for (const constraint of language.not_before) {
188
+ const events = trace.locationsById.get(constraint.event) ?? [];
189
+ const anchors = trace.locationsById.get(constraint.anchor) ?? [];
190
+ const firstEvent = events[0];
191
+ const firstAnchor = anchors[0];
192
+ if (firstEvent !== undefined && firstAnchor === undefined)
193
+ return {
194
+ failure: failure({
195
+ kind: "edge",
196
+ message: `${constraint.anchor} is required when ${constraint.event} occurs.`,
197
+ eventIds: [constraint.event, constraint.anchor],
198
+ locations: [firstEvent],
199
+ rawTrace: trace.rawTrace,
200
+ }),
201
+ satisfied,
202
+ };
203
+ if (firstEvent !== undefined &&
204
+ firstAnchor !== undefined &&
205
+ firstEvent.capture_order < firstAnchor.capture_order)
206
+ return {
207
+ failure: failure({
208
+ kind: "edge",
209
+ message: `${constraint.event} must not occur before ${constraint.anchor}.`,
210
+ eventIds: [constraint.event, constraint.anchor],
211
+ locations: [firstEvent, firstAnchor],
212
+ rawTrace: trace.rawTrace,
213
+ }),
214
+ satisfied,
215
+ };
216
+ satisfied.push(`not_before:${constraint.event}:${constraint.anchor}`);
217
+ }
218
+ return { failure: null, satisfied };
219
+ };
220
+ const boundaryFailure = (trace, kind, expected) => {
221
+ const ids = trace.rawTrace.map(({ event_id }) => event_id);
222
+ const actual = kind === "prefix"
223
+ ? ids.slice(0, expected.length)
224
+ : expected.length === 0
225
+ ? []
226
+ : ids.slice(-expected.length);
227
+ if (canonicalTraceJson(actual) === canonicalTraceJson(expected))
228
+ return null;
229
+ const locations = kind === "prefix"
230
+ ? trace.rawTrace.slice(0, expected.length)
231
+ : trace.rawTrace.slice(-expected.length);
232
+ return failure({
233
+ kind,
234
+ message: `Observed trace does not satisfy the declared ${kind}.`,
235
+ eventIds: expected,
236
+ locations: locations.map(({ location }) => location),
237
+ rawTrace: trace.rawTrace,
238
+ });
239
+ };
240
+ const evaluatePartialOrder = (trace, language) => {
241
+ const ordering = evaluateOrderingConstraints(trace, language);
242
+ if (ordering.failure !== null)
243
+ return ordering.failure;
244
+ const prefixFailure = boundaryFailure(trace, "prefix", language.prefix);
245
+ if (prefixFailure !== null)
246
+ return prefixFailure;
247
+ const suffixFailure = boundaryFailure(trace, "suffix", language.suffix);
248
+ if (suffixFailure !== null)
249
+ return suffixFailure;
250
+ const satisfied = ordering.satisfied;
251
+ satisfied.push(...language.unordered_groups.map(({ events }) => `unordered:${events.join(":")}`));
252
+ if (language.prefix.length > 0)
253
+ satisfied.push(`prefix:${language.prefix.join(":")}`);
254
+ if (language.suffix.length > 0)
255
+ satisfied.push(`suffix:${language.suffix.join(":")}`);
256
+ return {
257
+ result: {
258
+ status: "pass",
259
+ matched_variant: null,
260
+ satisfied_constraints: satisfied,
261
+ raw_trace: trace.rawTrace,
262
+ },
263
+ diagnostic: null,
264
+ };
265
+ };
266
+ const evaluateMatchedTrace = (trace, specification) => {
267
+ const invalidCardinality = cardinalityFailure(trace, specification);
268
+ if (invalidCardinality !== null)
269
+ return invalidCardinality;
270
+ if (specification.language.kind === "partial_order")
271
+ return evaluatePartialOrder(trace, specification.language);
272
+ const ids = trace.rawTrace.map(({ event_id }) => event_id);
273
+ const variant = evaluateFiniteTrace(ids, specification);
274
+ return variant === null
275
+ ? failure({
276
+ kind: "trace",
277
+ message: "Observed events do not match any finite trace variant.",
278
+ eventIds: ids,
279
+ locations: trace.rawTrace.map(({ location }) => location),
280
+ rawTrace: trace.rawTrace,
281
+ })
282
+ : {
283
+ result: {
284
+ status: "pass",
285
+ matched_variant: variant,
286
+ satisfied_constraints: [`variant:${variant}`],
287
+ raw_trace: trace.rawTrace,
288
+ },
289
+ diagnostic: null,
290
+ };
291
+ };
292
+ export const evaluateProcessTraceSide = (capture, specification) => {
293
+ const sources = new Set(specification.events.map(({ source }) => source));
294
+ const relevantScopes = scopesFor(sources);
295
+ if (capture.truncated ||
296
+ capture.residual_unknowns.some(({ scope }) => relevantScopes.has(scope)))
297
+ return { result: unknownSide(), diagnostic: null };
298
+ if ((capture.event_journal ?? []).length === 0)
299
+ return {
300
+ result: unknownSide(),
301
+ diagnostic: {
302
+ kind: "journal",
303
+ message: "Capture has no cross-source event journal.",
304
+ event_ids: [],
305
+ locations: [],
306
+ },
307
+ };
308
+ const matched = matchRecords(collectRecords(capture, sources), specification);
309
+ return "rawTrace" in matched
310
+ ? evaluateMatchedTrace(matched, specification)
311
+ : matched;
312
+ };