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,373 @@
1
+ import canonicalize from "canonicalize";
2
+ import { z } from "zod";
3
+ import { jsonValueSchema } from "./jsonValue.js";
4
+ import { comparableProcessObservationPayload, processObservationSourceSchema, } from "./processObservation.js";
5
+ const identifierSchema = z.string().regex(/^[A-Za-z][A-Za-z0-9._-]{0,63}$/u);
6
+ /** Process observation families admitted by a declared trace specification. */
7
+ export const processTraceSourceSchema = processObservationSourceSchema;
8
+ const cardinalitySchema = z.discriminatedUnion("kind", [
9
+ z.strictObject({ kind: z.literal("required") }),
10
+ z.strictObject({ kind: z.literal("optional") }),
11
+ z.strictObject({
12
+ kind: z.literal("exact"),
13
+ count: z.number().int().min(0).max(10_000),
14
+ }),
15
+ z
16
+ .strictObject({
17
+ kind: z.literal("range"),
18
+ min: z.number().int().min(0).max(10_000),
19
+ max: z.number().int().min(0).max(10_000),
20
+ })
21
+ .refine(({ min, max }) => min <= max, {
22
+ message: "cardinality min must not exceed max",
23
+ path: ["min"],
24
+ }),
25
+ ]);
26
+ const eventDeclarationSchema = z.strictObject({
27
+ id: identifierSchema,
28
+ source: processTraceSourceSchema,
29
+ exact: jsonValueSchema,
30
+ ignore_fields: z
31
+ .array(z.enum([
32
+ "sequence",
33
+ "at_ms",
34
+ "scheduled_at_ms",
35
+ "dispatched_at_ms",
36
+ "elapsed_ms",
37
+ ]))
38
+ .max(5)
39
+ .refine((values) => new Set(values).size === values.length, {
40
+ message: "ignored event fields must be unique",
41
+ })
42
+ .optional(),
43
+ cardinality: cardinalitySchema.default({ kind: "required" }),
44
+ });
45
+ const partialOrderLanguageSchema = z.strictObject({
46
+ kind: z.literal("partial_order"),
47
+ happens_before: z
48
+ .array(z.strictObject({
49
+ before: identifierSchema,
50
+ after: identifierSchema,
51
+ }))
52
+ .max(4_096)
53
+ .default([]),
54
+ not_before: z
55
+ .array(z.strictObject({
56
+ event: identifierSchema,
57
+ anchor: identifierSchema,
58
+ }))
59
+ .max(4_096)
60
+ .default([]),
61
+ unordered_groups: z
62
+ .array(z.strictObject({ events: z.array(identifierSchema).min(2).max(256) }))
63
+ .max(256)
64
+ .default([]),
65
+ prefix: z.array(identifierSchema).max(4_096).default([]),
66
+ suffix: z.array(identifierSchema).max(4_096).default([]),
67
+ });
68
+ const finiteTraceTokenSchema = z.union([
69
+ identifierSchema,
70
+ z.strictObject({ unordered: z.array(identifierSchema).min(2).max(256) }),
71
+ ]);
72
+ const finiteTraceLanguageSchema = z.strictObject({
73
+ kind: z.literal("finite_traces"),
74
+ variants: z
75
+ .array(z.strictObject({
76
+ id: identifierSchema,
77
+ trace: z.array(finiteTraceTokenSchema).max(4_096),
78
+ }))
79
+ .min(1)
80
+ .max(64),
81
+ });
82
+ const specificationShapeSchema = z.strictObject({
83
+ version: z.literal(1),
84
+ events: z.array(eventDeclarationSchema).min(1).max(256),
85
+ language: z.discriminatedUnion("kind", [
86
+ partialOrderLanguageSchema,
87
+ finiteTraceLanguageSchema,
88
+ ]),
89
+ });
90
+ export const canonicalTraceJson = (value) => {
91
+ const serialized = canonicalize(value);
92
+ if (serialized === undefined)
93
+ throw new TypeError("Trace specification contains a non-JSON value");
94
+ return serialized;
95
+ };
96
+ /** Remove only explicitly declared schedule metadata before exact matching. */
97
+ export const comparableTracePayload = (value, ignoredFields = []) => comparableProcessObservationPayload(value, ignoredFields);
98
+ export const processTraceCardinalityBounds = (cardinality) => {
99
+ switch (cardinality.kind) {
100
+ case "required":
101
+ return [1, 1];
102
+ case "optional":
103
+ return [0, 1];
104
+ case "exact":
105
+ return [cardinality.count, cardinality.count];
106
+ case "range":
107
+ return [cardinality.min, cardinality.max];
108
+ }
109
+ };
110
+ const addReferenceIssue = (context, known, id, path) => {
111
+ if (!known.has(id))
112
+ context.addIssue({
113
+ code: "custom",
114
+ message: `unknown event id: ${id}`,
115
+ path,
116
+ });
117
+ };
118
+ const pairKey = (left, right) => [left, right].sort().join("\0");
119
+ const buildAdjacency = (language, context, known) => {
120
+ const adjacency = new Map([...known].map((id) => [id, new Set()]));
121
+ for (const [index, edge] of language.happens_before.entries()) {
122
+ const path = ["language", "happens_before", index];
123
+ addReferenceIssue(context, known, edge.before, [...path, "before"]);
124
+ addReferenceIssue(context, known, edge.after, [...path, "after"]);
125
+ if (edge.before === edge.after)
126
+ context.addIssue({
127
+ code: "custom",
128
+ message: "happens-before edges must reference distinct events",
129
+ path,
130
+ });
131
+ adjacency.get(edge.before)?.add(edge.after);
132
+ }
133
+ return adjacency;
134
+ };
135
+ const validateNotBefore = (language, context, known, reachable) => {
136
+ const pairs = new Set();
137
+ for (const [index, constraint] of language.not_before.entries()) {
138
+ const path = ["language", "not_before", index];
139
+ addReferenceIssue(context, known, constraint.event, [...path, "event"]);
140
+ addReferenceIssue(context, known, constraint.anchor, [...path, "anchor"]);
141
+ if (constraint.event === constraint.anchor)
142
+ context.addIssue({
143
+ code: "custom",
144
+ message: "not-before constraints must reference distinct events",
145
+ path,
146
+ });
147
+ const key = pairKey(constraint.event, constraint.anchor);
148
+ if (pairs.has(key))
149
+ context.addIssue({
150
+ code: "custom",
151
+ message: "not-before event pairs must be declared once",
152
+ path,
153
+ });
154
+ pairs.add(key);
155
+ if (reachable.get(constraint.event)?.has(constraint.anchor) === true)
156
+ context.addIssue({
157
+ code: "custom",
158
+ message: "not-before constraint conflicts with happens-before order",
159
+ path,
160
+ });
161
+ }
162
+ return pairs;
163
+ };
164
+ const graphHasCycle = (ids, adjacency) => {
165
+ const active = new Set();
166
+ const complete = new Set();
167
+ const visit = (current) => {
168
+ if (active.has(current))
169
+ return true;
170
+ if (complete.has(current))
171
+ return false;
172
+ active.add(current);
173
+ const cyclic = [...(adjacency.get(current) ?? [])].some(visit);
174
+ active.delete(current);
175
+ complete.add(current);
176
+ return cyclic;
177
+ };
178
+ return ids.some(visit);
179
+ };
180
+ const computeReachability = (ids, adjacency) => {
181
+ const reachable = new Map();
182
+ for (const origin of ids) {
183
+ const seen = new Set();
184
+ const pending = [...(adjacency.get(origin) ?? [])];
185
+ while (pending.length > 0) {
186
+ const current = pending.pop();
187
+ if (current === undefined || seen.has(current))
188
+ continue;
189
+ seen.add(current);
190
+ pending.push(...(adjacency.get(current) ?? []));
191
+ }
192
+ reachable.set(origin, seen);
193
+ }
194
+ return reachable;
195
+ };
196
+ const isOrdered = (reachable, left, right) => reachable.get(left)?.has(right) === true ||
197
+ reachable.get(right)?.has(left) === true;
198
+ const validateUnorderedGroups = (language, context, known, relations) => {
199
+ const pairs = new Set();
200
+ for (const [groupIndex, group] of language.unordered_groups.entries()) {
201
+ const path = ["language", "unordered_groups", groupIndex];
202
+ if (new Set(group.events).size !== group.events.length)
203
+ context.addIssue({
204
+ code: "custom",
205
+ message: "unordered groups must not repeat event ids",
206
+ path: [...path, "events"],
207
+ });
208
+ for (const [eventIndex, id] of group.events.entries())
209
+ addReferenceIssue(context, known, id, [...path, "events", eventIndex]);
210
+ for (const [leftIndex, leftId] of group.events.entries()) {
211
+ for (const rightId of group.events.slice(leftIndex + 1)) {
212
+ const key = pairKey(leftId, rightId);
213
+ if (pairs.has(key))
214
+ context.addIssue({
215
+ code: "custom",
216
+ message: "unordered event pairs must be declared once",
217
+ path,
218
+ });
219
+ pairs.add(key);
220
+ if (isOrdered(relations.reachable, leftId, rightId) ||
221
+ relations.notBeforePairs.has(key))
222
+ context.addIssue({
223
+ code: "custom",
224
+ message: "ordered events cannot also be declared unordered",
225
+ path,
226
+ });
227
+ }
228
+ }
229
+ }
230
+ return pairs;
231
+ };
232
+ const validateCompletePairDeclarations = (ids, relations, unorderedPairs, context) => {
233
+ for (const [leftIndex, leftId] of ids.entries())
234
+ for (const rightId of ids.slice(leftIndex + 1))
235
+ if (!isOrdered(relations.reachable, leftId, rightId) &&
236
+ !relations.notBeforePairs.has(pairKey(leftId, rightId)) &&
237
+ !unorderedPairs.has(pairKey(leftId, rightId)))
238
+ context.addIssue({
239
+ code: "custom",
240
+ message: `event pair ${leftId}/${rightId} must be explicitly ordered or unordered`,
241
+ path: ["language"],
242
+ });
243
+ };
244
+ const validatePartialOrder = (specification, context) => {
245
+ if (specification.language.kind !== "partial_order")
246
+ return;
247
+ const ids = specification.events.map(({ id }) => id);
248
+ const known = new Set(ids);
249
+ const adjacency = buildAdjacency(specification.language, context, known);
250
+ if (graphHasCycle(ids, adjacency))
251
+ context.addIssue({
252
+ code: "custom",
253
+ message: "happens-before graph must be acyclic",
254
+ path: ["language"],
255
+ });
256
+ const reachable = computeReachability(ids, adjacency);
257
+ const notBeforePairs = validateNotBefore(specification.language, context, known, reachable);
258
+ const relations = { reachable, notBeforePairs };
259
+ const unorderedPairs = validateUnorderedGroups(specification.language, context, known, relations);
260
+ validateCompletePairDeclarations(ids, relations, unorderedPairs, context);
261
+ for (const [kind, values] of [
262
+ ["prefix", specification.language.prefix],
263
+ ["suffix", specification.language.suffix],
264
+ ])
265
+ for (const [index, id] of values.entries())
266
+ addReferenceIssue(context, known, id, ["language", kind, index]);
267
+ };
268
+ const countVariantEvents = (trace) => {
269
+ const counts = new Map();
270
+ for (const token of trace)
271
+ for (const id of typeof token === "string" ? [token] : token.unordered)
272
+ counts.set(id, (counts.get(id) ?? 0) + 1);
273
+ return counts;
274
+ };
275
+ const validateFiniteTraces = (specification, context) => {
276
+ if (specification.language.kind !== "finite_traces")
277
+ return;
278
+ const known = new Set(specification.events.map(({ id }) => id));
279
+ const variantIds = new Set();
280
+ const variantTraces = new Set();
281
+ for (const [variantIndex, variant,] of specification.language.variants.entries()) {
282
+ const variantPath = ["language", "variants", variantIndex];
283
+ if (variantIds.has(variant.id))
284
+ context.addIssue({
285
+ code: "custom",
286
+ message: "finite trace variant ids must be unique",
287
+ path: [...variantPath, "id"],
288
+ });
289
+ variantIds.add(variant.id);
290
+ const canonicalTrace = canonicalTraceJson(variant.trace);
291
+ if (variantTraces.has(canonicalTrace))
292
+ context.addIssue({
293
+ code: "custom",
294
+ message: "finite trace variants must not duplicate a trace",
295
+ path: [...variantPath, "trace"],
296
+ });
297
+ variantTraces.add(canonicalTrace);
298
+ for (const [tokenIndex, token] of variant.trace.entries()) {
299
+ const values = typeof token === "string" ? [token] : token.unordered;
300
+ for (const [eventIndex, id] of values.entries())
301
+ addReferenceIssue(context, known, id, [
302
+ ...variantPath,
303
+ "trace",
304
+ tokenIndex,
305
+ ...(typeof token === "string" ? [] : ["unordered", eventIndex]),
306
+ ]);
307
+ }
308
+ const counts = countVariantEvents(variant.trace);
309
+ for (const event of specification.events) {
310
+ const [minimum, maximum] = processTraceCardinalityBounds(event.cardinality);
311
+ const count = counts.get(event.id) ?? 0;
312
+ if (count < minimum || count > maximum)
313
+ context.addIssue({
314
+ code: "custom",
315
+ message: `variant ${variant.id} violates ${event.id} cardinality`,
316
+ path: [...variantPath, "trace"],
317
+ });
318
+ }
319
+ }
320
+ };
321
+ /** Strict, bounded concurrency model for Process Capture observations. */
322
+ export const processTraceSpecificationSchema = specificationShapeSchema.superRefine((specification, context) => {
323
+ const ids = new Set();
324
+ const predicates = new Set();
325
+ const ignoredFieldsBySource = new Map();
326
+ for (const [index, event] of specification.events.entries()) {
327
+ if (ids.has(event.id))
328
+ context.addIssue({
329
+ code: "custom",
330
+ message: "event ids must be unique",
331
+ path: ["events", index, "id"],
332
+ });
333
+ ids.add(event.id);
334
+ const ignoredFields = [...(event.ignore_fields ?? [])].sort();
335
+ if (ignoredFields.length > 0 &&
336
+ (typeof event.exact !== "object" ||
337
+ event.exact === null ||
338
+ Array.isArray(event.exact)))
339
+ context.addIssue({
340
+ code: "custom",
341
+ message: "ignored schedule fields require an exact object payload",
342
+ path: ["events", index, "ignore_fields"],
343
+ });
344
+ const ignoredKey = canonicalTraceJson(ignoredFields);
345
+ const priorIgnoredKey = ignoredFieldsBySource.get(event.source);
346
+ if (priorIgnoredKey !== undefined && priorIgnoredKey !== ignoredKey)
347
+ context.addIssue({
348
+ code: "custom",
349
+ message: "events from one source must use the same ignored schedule fields",
350
+ path: ["events", index, "ignore_fields"],
351
+ });
352
+ ignoredFieldsBySource.set(event.source, ignoredKey);
353
+ if (ignoredFields.some((field) => typeof event.exact === "object" &&
354
+ event.exact !== null &&
355
+ !Array.isArray(event.exact) &&
356
+ field in event.exact))
357
+ context.addIssue({
358
+ code: "custom",
359
+ message: "exact payload must omit every ignored schedule field",
360
+ path: ["events", index, "exact"],
361
+ });
362
+ const predicate = `${event.source}\0${canonicalTraceJson(comparableTracePayload(event.exact, ignoredFields))}`;
363
+ if (predicates.has(predicate))
364
+ context.addIssue({
365
+ code: "custom",
366
+ message: "exact event predicates must not overlap",
367
+ path: ["events", index],
368
+ });
369
+ predicates.add(predicate);
370
+ }
371
+ validatePartialOrder(specification, context);
372
+ validateFiniteTraces(specification, context);
373
+ });
@@ -18,23 +18,24 @@ const MAX_CANONICAL_BYTES = 32 * 1024 * 1024;
18
18
  const providers = {
19
19
  behavioral: {
20
20
  operation: "compare_process_captures",
21
- predicate: "rea.process-comparison/v3",
21
+ predicates: ["rea.process-comparison/v3", "rea.process-comparison/v4"],
22
22
  id: "rea-process",
23
23
  name: "REA deterministic process harness",
24
24
  },
25
25
  "structural-function": {
26
26
  operation: "compare_functions",
27
- predicate: "rea.function-comparison/v1",
27
+ predicates: ["rea.function-comparison/v1"],
28
28
  id: "rea-function-comparison",
29
29
  name: "REA function comparison",
30
30
  },
31
31
  "structural-artifact": {
32
32
  operation: "compare_artifacts",
33
- predicate: "rea.artifact-comparison/v1",
33
+ predicates: ["rea.artifact-comparison/v1"],
34
34
  id: "rea-artifact-comparison",
35
35
  name: "REA artifact comparison",
36
36
  },
37
37
  };
38
+ const acceptsPredicate = (expected, actual) => expected.some((predicate) => predicate === actual);
38
39
  /** Verify only explicitly declared claims; no global equivalence is inferred. */
39
40
  export const verifyReconstruction = (specificationInput, bundleInput, offset, limit) => {
40
41
  const specification = reconstructionSpecificationSchema.parse(specificationInput);
@@ -157,7 +158,7 @@ const validateComparisonIdentity = (claim, evidence) => {
157
158
  parseEvidence(evidence);
158
159
  const expected = providers[claim.kind];
159
160
  if (evidence.operation !== expected.operation ||
160
- evidence.predicate_type !== expected.predicate ||
161
+ !acceptsPredicate(expected.predicates, evidence.predicate_type) ||
161
162
  evidence.provider.id !== expected.id ||
162
163
  evidence.provider.name !== expected.name ||
163
164
  evidence.provider.version !== (claim.kind === "behavioral" ? "3" : "1") ||