rea-agents 2.4.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (231) hide show
  1. package/README.md +91 -19
  2. package/bridge/ghidra/ReaGhidraBridge.java +524 -4
  3. package/bridge/hopper_bridge.py +313 -28
  4. package/dist/application/AnalysisClientCleanup.js +14 -0
  5. package/dist/application/AnalysisContextQueries.js +130 -0
  6. package/dist/application/AnalysisSnapshotCache.js +4 -2
  7. package/dist/application/ApplicationWorkflowEvidenceResolver.js +31 -13
  8. package/dist/application/ArtifactInventory/scanCanonical.js +1 -1
  9. package/dist/application/BinarySession.js +20 -8
  10. package/dist/application/BinarySessionComposition.js +21 -0
  11. package/dist/application/BinarySessionRecords.js +79 -9
  12. package/dist/application/BinarySessionStatus.js +31 -1
  13. package/dist/application/BrowserEvidence.js +14 -0
  14. package/dist/application/BrowserScenarioCapturePort.js +1 -0
  15. package/dist/application/BrowserScenarioCaptureService.js +53 -0
  16. package/dist/application/BrowserScenarioEvidence.js +40 -0
  17. package/dist/application/CallPathTracing.js +160 -0
  18. package/dist/application/CapabilityInventory.js +84 -14
  19. package/dist/application/ClientRegistrationStatus.js +4 -1
  20. package/dist/application/CompositeProvider.js +10 -1
  21. package/dist/application/DirectAnalysis.js +13 -4
  22. package/dist/application/EnhancedLiteralTracing.js +118 -0
  23. package/dist/application/EnhancedTools.js +71 -127
  24. package/dist/application/EvidenceLedger.js +45 -16
  25. package/dist/application/JavaScriptApplicationWorkflowEvidence.js +13 -0
  26. package/dist/application/JavaScriptApplicationWorkflowService.js +27 -1
  27. package/dist/application/JavaScriptArtifactAnalysis.js +13 -4
  28. package/dist/application/JavaScriptRuntimeObservationEvidence.js +34 -0
  29. package/dist/application/JavaScriptRuntimeObservationPort.js +1 -0
  30. package/dist/application/JavaScriptRuntimeObservationService.js +46 -0
  31. package/dist/application/JavaScriptSemanticGraphAsyncProjection.js +147 -0
  32. package/dist/application/JavaScriptSemanticGraphBuilder.js +34 -6
  33. package/dist/application/JavaScriptSemanticGraphChildProcessProjection.js +156 -0
  34. package/dist/application/JavaScriptSemanticGraphConstruction.js +2 -2
  35. package/dist/application/JavaScriptSemanticGraphDataProjection.js +203 -0
  36. package/dist/application/JavaScriptSemanticGraphFingerprintProjection.js +25 -0
  37. package/dist/application/JavaScriptSemanticGraphFlowProjection.js +129 -8
  38. package/dist/application/JavaScriptSemanticGraphObjectProjection.js +81 -0
  39. package/dist/application/JavaScriptSemanticGraphProjection.js +14 -7
  40. package/dist/application/JavaScriptSemanticGraphResourceProjection.js +59 -0
  41. package/dist/application/JavaScriptSemanticGraphValueProjection.js +77 -0
  42. package/dist/application/LazyAnalysisProvider.js +77 -0
  43. package/dist/application/LoopbackReplay.js +1 -1
  44. package/dist/application/NativeApiInspection.js +80 -0
  45. package/dist/application/ProcessReactiveEffects.js +6 -0
  46. package/dist/application/ProcessReactiveHarness.js +16 -1
  47. package/dist/application/ProjectPermissionStore.js +1 -0
  48. package/dist/application/ReconstructionObligationAuthority.js +72 -0
  49. package/dist/application/ReconstructionObligationCandidates.js +265 -0
  50. package/dist/application/ReconstructionObligationLedgerDiagnostics.js +47 -0
  51. package/dist/application/ReconstructionObligationLedgerEvaluation.js +263 -0
  52. package/dist/application/ReconstructionObligationLedgerProjection.js +86 -0
  53. package/dist/application/ReconstructionObligationLedgerService.js +72 -0
  54. package/dist/application/ReconstructionObligationOriginalCases.js +33 -0
  55. package/dist/application/ReconstructionObligationPolicies.js +132 -0
  56. package/dist/application/ReconstructionReadinessService.js +48 -0
  57. package/dist/application/SessionProviderRouter.js +6 -6
  58. package/dist/application/SetupClientConfiguration.js +4 -2
  59. package/dist/application/runtime.js +26 -9
  60. package/dist/artifacts/ArtifactProvider.js +87 -22
  61. package/dist/browser/BrowserScenarioSecrets.js +53 -0
  62. package/dist/browser/BrowserScenarioSessionPort.js +1 -0
  63. package/dist/browser/CdpBrowserProvider.js +2 -2
  64. package/dist/browser/CdpCaptureDocuments.js +57 -0
  65. package/dist/browser/CdpCaptureStorage.js +71 -29
  66. package/dist/browser/CdpCaptureStorageFingerprints.js +328 -0
  67. package/dist/browser/CdpEndpoint.js +8 -6
  68. package/dist/browser/CdpPageCapture.js +2 -0
  69. package/dist/browser/JavaScriptRuntimeScope.js +38 -0
  70. package/dist/browser/PlaywrightBrowserScenarioProvider.js +259 -0
  71. package/dist/browser/PlaywrightExecutionBoundary.js +42 -0
  72. package/dist/browser/PlaywrightScenarioActions.js +62 -0
  73. package/dist/browser/PlaywrightScenarioArtifacts.js +238 -0
  74. package/dist/browser/PlaywrightScenarioBrowser.js +144 -0
  75. package/dist/browser/PlaywrightScenarioEvents.js +301 -0
  76. package/dist/browser/PlaywrightScenarioSession.js +300 -0
  77. package/dist/browser/V8InspectorCaptureProjection.js +110 -0
  78. package/dist/browser/V8InspectorEndpoint.js +72 -0
  79. package/dist/browser/V8InspectorProvider.js +267 -0
  80. package/dist/catalogIdentity.js +11 -3
  81. package/dist/cli/artifactCommands.js +44 -3
  82. package/dist/cli/coreAnalysisCommands.js +78 -0
  83. package/dist/cli.js +4 -0
  84. package/dist/cliApplicationCommands.js +30 -2
  85. package/dist/cliBrowserAdvancedCommands.js +17 -5
  86. package/dist/cliBrowserCommands.js +1 -0
  87. package/dist/cliBrowserScenarioCommands.js +43 -0
  88. package/dist/cliCommandNames.js +9 -0
  89. package/dist/cliJavaScriptRuntimeCommands.js +164 -0
  90. package/dist/cliObservationOptions.js +4 -0
  91. package/dist/cliPolicyCommands.js +1 -0
  92. package/dist/config/environment.js +12 -0
  93. package/dist/config/parseConfig.js +88 -17
  94. package/dist/contracts/analysisSearchContract.js +14 -0
  95. package/dist/contracts/applicationToolContracts.js +86 -2
  96. package/dist/contracts/applicationWorkflowInputContracts.js +18 -0
  97. package/dist/contracts/artifactToolContracts.js +29 -2
  98. package/dist/contracts/browserProviderToolContracts.js +7 -0
  99. package/dist/contracts/browserScenarioToolContracts.js +81 -0
  100. package/dist/contracts/browserToolContracts.js +88 -98
  101. package/dist/contracts/enhancedInputs.js +35 -6
  102. package/dist/contracts/functionInstructionContract.js +8 -0
  103. package/dist/contracts/functionWorkflowToolContracts.js +30 -0
  104. package/dist/contracts/hopperMemoryContracts.js +22 -0
  105. package/dist/contracts/javascriptApplicationWorkflowExamples.js +42 -0
  106. package/dist/contracts/javascriptRuntimeObservationToolContracts.js +58 -0
  107. package/dist/contracts/promptContracts.js +14 -15
  108. package/dist/contracts/reconstructionReadinessExample.js +436 -0
  109. package/dist/contracts/toolContractExamples.js +8 -0
  110. package/dist/contracts/toolContractTypes.js +1 -0
  111. package/dist/contracts/toolContracts.js +34 -25
  112. package/dist/contracts/toolEffects.js +25 -0
  113. package/dist/contracts/toolOutputSchemaGroups.js +120 -30
  114. package/dist/contracts/toolOutputSchemaPrimitives.js +37 -0
  115. package/dist/domain/analysisErrorPresentation.js +8 -2
  116. package/dist/domain/analysisErrorProjection.js +9 -0
  117. package/dist/domain/artifactInspection.js +347 -0
  118. package/dist/domain/browserCaptureComparison.js +82 -0
  119. package/dist/domain/browserObservation.js +8 -1
  120. package/dist/domain/browserObservationErrors.js +1 -0
  121. package/dist/domain/browserObservationSchemas.js +26 -0
  122. package/dist/domain/browserScenario.js +165 -0
  123. package/dist/domain/browserScenarioCapture.js +57 -0
  124. package/dist/domain/browserScenarioCaptureValues.js +204 -0
  125. package/dist/domain/browserScenarioDiff.js +324 -0
  126. package/dist/domain/browserScenarioDiffValues.js +157 -0
  127. package/dist/domain/browserScenarioNormalization.js +45 -0
  128. package/dist/domain/browserScenarioValues.js +372 -0
  129. package/dist/domain/bytecodeProvider.js +179 -0
  130. package/dist/domain/conformancePackage.js +169 -0
  131. package/dist/domain/conformanceReplay.js +104 -0
  132. package/dist/domain/conformanceTrustGate.js +193 -0
  133. package/dist/domain/customProtocolCapture.js +137 -0
  134. package/dist/domain/eventProcessTree.js +214 -0
  135. package/dist/domain/evidenceBundle.js +47 -0
  136. package/dist/domain/hopperStartupFailure.js +1 -1
  137. package/dist/domain/hopperValues.js +14 -1
  138. package/dist/domain/inputIssueProjection.js +7 -1
  139. package/dist/domain/javascriptRuntimeObservation.js +170 -0
  140. package/dist/domain/javascriptRuntimeReconciliationParsing.js +120 -2
  141. package/dist/domain/javascriptRuntimeReconciliationResult.js +3 -3
  142. package/dist/domain/javascriptRuntimeReconciliationRuntime.js +2 -2
  143. package/dist/domain/javascriptRuntimeReconciliationSchemas.js +1 -1
  144. package/dist/domain/javascriptSemanticAnalysis.js +13 -16
  145. package/dist/domain/javascriptSemanticAsyncEffects.js +253 -0
  146. package/dist/domain/javascriptSemanticChildProcesses.js +237 -0
  147. package/dist/domain/javascriptSemanticDataEffectHelpers.js +125 -0
  148. package/dist/domain/javascriptSemanticDataEffects.js +284 -0
  149. package/dist/domain/javascriptSemanticDerivedAnalysis.js +41 -0
  150. package/dist/domain/javascriptSemanticFingerprints.js +174 -0
  151. package/dist/domain/javascriptSemanticIr.js +21 -1
  152. package/dist/domain/javascriptSemanticObjects.js +115 -0
  153. package/dist/domain/javascriptSemanticPromises.js +290 -0
  154. package/dist/domain/javascriptSemanticResources.js +136 -0
  155. package/dist/domain/javascriptSourceParser.js +15 -0
  156. package/dist/domain/javascriptStaticAnalysis.js +12 -15
  157. package/dist/domain/javascriptStaticAnalysisBundler.js +38 -0
  158. package/dist/domain/javascriptStaticAnalysisCalls.js +23 -1
  159. package/dist/domain/javascriptStaticAnalysisHelpers.js +8 -0
  160. package/dist/domain/mobileApplicationInvestigation.js +159 -0
  161. package/dist/domain/nativeApiBoundary.js +130 -0
  162. package/dist/domain/objcSwiftMetadata.js +150 -0
  163. package/dist/domain/packageAnalysis.js +123 -0
  164. package/dist/domain/peInspection.js +196 -0
  165. package/dist/domain/processCapture.js +8 -2
  166. package/dist/domain/processReactiveScenario.js +1 -0
  167. package/dist/domain/processReactiveTransition.js +9 -4
  168. package/dist/domain/protocolCapture.js +243 -0
  169. package/dist/domain/providerCleanupError.js +11 -0
  170. package/dist/domain/reconstructionObligationLedgerSchemas.js +278 -0
  171. package/dist/domain/reconstructionReadiness.js +121 -0
  172. package/dist/domain/reconstructionReadinessFindingHelpers.js +17 -0
  173. package/dist/domain/reconstructionReadinessIntegrityFindings.js +118 -0
  174. package/dist/domain/reconstructionReadinessJourneyFindings.js +193 -0
  175. package/dist/domain/reconstructionReadinessSchemas.js +240 -0
  176. package/dist/domain/sourceToBundleComparison.js +335 -0
  177. package/dist/domain/sourceToBundleComparisonSchemas.js +133 -0
  178. package/dist/domain/sourceToBundleSignals.js +202 -0
  179. package/dist/domain/webCaptureDiff.js +141 -27
  180. package/dist/domain/webScreenshot.js +1 -1
  181. package/dist/dotnet/ManagedStaticProvider.js +34 -5
  182. package/dist/generatedMcpToolCatalog.js +37 -0
  183. package/dist/generatedPackageMetadata.js +4 -4
  184. package/dist/ghidra/GhidraDefaults.js +1 -1
  185. package/dist/ghidra/GhidraFunctionValues.js +40 -2
  186. package/dist/ghidra/GhidraProviderCapabilities.js +47 -38
  187. package/dist/hopper/HopperCleanup.js +158 -0
  188. package/dist/hopper/HopperClient.js +93 -99
  189. package/dist/hopper/HopperProvider.js +61 -30
  190. package/dist/hopper/HopperRequestQueue.js +215 -0
  191. package/dist/hopper/HopperResponseStream.js +46 -0
  192. package/dist/hopper/protocol.js +63 -20
  193. package/dist/main/transport.js +24 -27
  194. package/dist/main.js +14 -6
  195. package/dist/mcpDoctor.js +27 -4
  196. package/dist/mcpStartupPolicy.js +14 -0
  197. package/dist/process/ProcessCommandIdentity.js +19 -0
  198. package/dist/process/ProcessOwnership.js +11 -8
  199. package/dist/server/DynamicToolAvailability.js +70 -0
  200. package/dist/server/LazyToolCatalog.js +134 -0
  201. package/dist/server/createServer.js +92 -154
  202. package/dist/server/hydrateServerTools.js +191 -0
  203. package/dist/server/lifecycleProgress.js +10 -0
  204. package/dist/server/permissionFailure.js +12 -0
  205. package/dist/server/registerApplicationTools/compareSourceToBundle.js +35 -0
  206. package/dist/server/registerApplicationTools/helpers.js +11 -7
  207. package/dist/server/registerApplicationTools/obligationLedger.js +27 -0
  208. package/dist/server/registerApplicationTools/readiness.js +55 -0
  209. package/dist/server/registerApplicationTools.js +6 -0
  210. package/dist/server/registerArtifactTools.js +9 -1
  211. package/dist/server/registerBrowserScenarioTool.js +25 -0
  212. package/dist/server/registerBrowserTools.js +2 -2
  213. package/dist/server/registerCloseLifecycleTool.js +57 -0
  214. package/dist/server/registerEnhancedTools.js +28 -7
  215. package/dist/server/registerEvidenceResources.js +54 -101
  216. package/dist/server/registerEvidenceTools.js +9 -2
  217. package/dist/server/registerInvestigationTools.js +1 -2
  218. package/dist/server/registerJavaScriptApplicationGraphResource.js +0 -4
  219. package/dist/server/registerJavaScriptRuntimeObservationTools.js +37 -0
  220. package/dist/server/registerReconstructionObligationLedgerResource.js +32 -0
  221. package/dist/server/registerReconstructionReadinessResource.js +32 -0
  222. package/dist/server/registerSessionRecordTools.js +82 -12
  223. package/dist/server/registerSessionStatusTool.js +11 -8
  224. package/dist/server/registerSessionTools.js +32 -58
  225. package/dist/server/sessionAvailabilityPolicy.js +10 -8
  226. package/dist/server/toolRegistrationOptions.js +21 -6
  227. package/dist/server/toolResult.js +12 -0
  228. package/package.json +28 -11
  229. package/scripts/package-runner-bootstrap.mjs +72 -0
  230. package/scripts/rea.mjs +11 -1
  231. package/skills/reverse-engineer-anything/SKILL.md +10 -3
@@ -0,0 +1,243 @@
1
+ import { z } from "zod";
2
+ import { jsonValueSchema } from "./jsonValue.js";
3
+ /** Supported protocol families for structured protocol capture. */
4
+ export const protocolFamilySchema = z.enum([
5
+ "grpc",
6
+ "protobuf",
7
+ "json-rpc",
8
+ "messagepack",
9
+ ]);
10
+ /** A decoded field from a protocol message. */
11
+ export const decodedFieldSchema = z.strictObject({
12
+ /** Field name or path within the message structure. */
13
+ path: z.string().min(1),
14
+ /** Wire type or encoding hint. */
15
+ wire_type: z.string().nullable(),
16
+ /** Decoded field value. */
17
+ value: jsonValueSchema.nullable(),
18
+ /** Whether this field value was inferred rather than decoded. */
19
+ inferred: z.boolean().default(false),
20
+ });
21
+ /** Schema inference hypothesis for a repeated message pattern. */
22
+ export const schemaHypothesisSchema = z.strictObject({
23
+ /** Hypothesized field name. */
24
+ field_name: z.string().min(1),
25
+ /** Inferred type. */
26
+ inferred_type: z.string().min(1),
27
+ /** Confidence: 0-1 */
28
+ confidence: z.number().min(0).max(1),
29
+ /** Supporting evidence count. */
30
+ evidence_count: z.number().int().nonnegative(),
31
+ });
32
+ /** Result of decoding a single protocol message. */
33
+ export const protocolMessageSchema = z.strictObject({
34
+ /** Monotonic sequence number. */
35
+ sequence: z.number().int().nonnegative(),
36
+ /** Timestamp in milliseconds. */
37
+ at_ms: z.number().int().nonnegative(),
38
+ /** Protocol family. */
39
+ family: protocolFamilySchema,
40
+ /** Direction of the message. */
41
+ direction: z.enum(["request", "response"]),
42
+ /** Transport endpoint or path (e.g. gRPC method path). */
43
+ endpoint: z.string().nullable(),
44
+ /** Content type of the raw payload. */
45
+ content_type: z.string().nullable(),
46
+ /** Raw payload bytes as base64. */
47
+ raw_payload: z.string().nullable(),
48
+ /** Decoded fields from the payload. */
49
+ decoded_fields: z.array(decodedFieldSchema).default([]),
50
+ /** Inferred schema hypotheses. */
51
+ schema_hypotheses: z.array(schemaHypothesisSchema).default([]),
52
+ /** Whether decoding was truncated. */
53
+ truncated: z.boolean().default(false),
54
+ /** Whether credentials were detected and redacted. */
55
+ credentials_redacted: z.boolean().default(false),
56
+ });
57
+ /** A captured protocol session with messages and inferred schemas. */
58
+ export const protocolCaptureSchema = z.strictObject({
59
+ /** Protocol family for this capture. */
60
+ family: protocolFamilySchema,
61
+ /** Captured messages in order. */
62
+ messages: z.array(protocolMessageSchema).min(0).max(10_000),
63
+ /** Aggregated schema hypotheses across all messages. */
64
+ inferred_schema: z.array(schemaHypothesisSchema).default([]),
65
+ /** Whether any message was truncated. */
66
+ has_truncated: z.boolean().default(false),
67
+ /** Whether credentials were detected and redacted. */
68
+ credentials_detected: z.boolean().default(false),
69
+ });
70
+ /** Classification of a byte sequence as a known protocol family. */
71
+ export function classifyProtocolFamily(contentType, path) {
72
+ if (contentType) {
73
+ if (contentType.includes("application/grpc"))
74
+ return "grpc";
75
+ if (contentType.includes("application/x-protobuf"))
76
+ return "protobuf";
77
+ if (contentType.includes("application/json-rpc"))
78
+ return "json-rpc";
79
+ if (contentType.includes("application/msgpack") ||
80
+ contentType.includes("application/x-msgpack"))
81
+ return "messagepack";
82
+ }
83
+ if (path) {
84
+ if (path.startsWith("/grpc.") || path.includes("/grpc/"))
85
+ return "grpc";
86
+ if (path.includes("/json-rpc") || path.includes("/jsonrpc"))
87
+ return "json-rpc";
88
+ }
89
+ return null;
90
+ }
91
+ /** Credential-like field names that should be redacted. */
92
+ const CREDENTIAL_PATTERNS = [
93
+ "password",
94
+ "passwd",
95
+ "secret",
96
+ "token",
97
+ "api_key",
98
+ "apikey",
99
+ "authorization",
100
+ "auth",
101
+ "credential",
102
+ "private_key",
103
+ ];
104
+ /** Check if a field path looks like it may contain credentials. */
105
+ export function looksLikeCredential(path) {
106
+ const lower = path.toLowerCase();
107
+ return CREDENTIAL_PATTERNS.some((p) => lower.includes(p));
108
+ }
109
+ /** Decode a JSON-RPC message from raw payload bytes. */
110
+ export function decodeJsonRpc(rawPayload) {
111
+ const text = new TextDecoder().decode(rawPayload);
112
+ const parsed = JSON.parse(text);
113
+ const fields = [];
114
+ if (typeof parsed === "object" && parsed !== null) {
115
+ for (const [key, value] of Object.entries(parsed)) {
116
+ if (looksLikeCredential(key)) {
117
+ fields.push({
118
+ path: key,
119
+ wire_type: "json",
120
+ value: "[REDACTED]",
121
+ inferred: false,
122
+ });
123
+ }
124
+ else {
125
+ fields.push({
126
+ path: key,
127
+ wire_type: "json",
128
+ value: value,
129
+ inferred: false,
130
+ });
131
+ }
132
+ }
133
+ }
134
+ return { decoded_fields: fields, truncated: false };
135
+ }
136
+ /** Decode a MessagePack message (simplified: only checks basic structure). */
137
+ export function decodeMessagePack(rawPayload) {
138
+ const fields = [];
139
+ // MessagePack uses a single-byte type tag
140
+ if (rawPayload.length === 0) {
141
+ return { decoded_fields: [], truncated: false };
142
+ }
143
+ const tag = rawPayload[0];
144
+ // Map type: 0x80-0x8f (fixmap), 0xde (map16), 0xdf (map32)
145
+ if ((tag >= 0x80 && tag <= 0x8f) || tag === 0xde || tag === 0xdf) {
146
+ fields.push({
147
+ path: "type",
148
+ wire_type: "msgpack",
149
+ value: "map",
150
+ inferred: false,
151
+ });
152
+ }
153
+ // Array type: 0x90-0x9f (fixarray), 0xdc (array16), 0xdd (array32)
154
+ else if ((tag >= 0x90 && tag <= 0x9f) || tag === 0xdc || tag === 0xdd) {
155
+ fields.push({
156
+ path: "type",
157
+ wire_type: "msgpack",
158
+ value: "array",
159
+ inferred: false,
160
+ });
161
+ }
162
+ else {
163
+ fields.push({
164
+ path: "type",
165
+ wire_type: "msgpack",
166
+ value: "unknown",
167
+ inferred: true,
168
+ });
169
+ }
170
+ return {
171
+ decoded_fields: fields,
172
+ truncated: rawPayload.length > 10_000,
173
+ };
174
+ }
175
+ /** Decode a gRPC frame (5-byte header + protobuf payload). */
176
+ export function decodeGrpcFrame(rawPayload) {
177
+ // gRPC uses a 5-byte prefix: 1 byte compressed flag + 4 byte length
178
+ if (rawPayload.length < 5) {
179
+ return {
180
+ decoded_fields: [
181
+ {
182
+ path: "error",
183
+ wire_type: "grpc",
184
+ value: "frame too short",
185
+ inferred: false,
186
+ },
187
+ ],
188
+ truncated: false,
189
+ };
190
+ }
191
+ const compressed = rawPayload[0] !== 0;
192
+ const length = (rawPayload[1] << 24) |
193
+ (rawPayload[2] << 16) |
194
+ (rawPayload[3] << 8) |
195
+ rawPayload[4];
196
+ return {
197
+ decoded_fields: [
198
+ {
199
+ path: "compressed",
200
+ wire_type: "grpc",
201
+ value: compressed,
202
+ inferred: false,
203
+ },
204
+ {
205
+ path: "message_length",
206
+ wire_type: "grpc",
207
+ value: length,
208
+ inferred: false,
209
+ },
210
+ ],
211
+ truncated: length > 10_000,
212
+ };
213
+ }
214
+ /** Infer schema hypotheses from a set of decoded messages. */
215
+ export function inferMessageSchema(messages) {
216
+ const fieldCounts = new Map();
217
+ for (const msg of messages) {
218
+ for (const field of msg.decoded_fields) {
219
+ const existing = fieldCounts.get(field.path);
220
+ if (existing) {
221
+ existing.count++;
222
+ if (field.wire_type)
223
+ existing.types.add(field.wire_type);
224
+ }
225
+ else {
226
+ fieldCounts.set(field.path, {
227
+ count: 1,
228
+ types: new Set(field.wire_type ?? "unknown"),
229
+ });
230
+ }
231
+ }
232
+ }
233
+ const hypotheses = [];
234
+ for (const [field_name, data] of fieldCounts) {
235
+ hypotheses.push({
236
+ field_name,
237
+ inferred_type: [...data.types].join("|"),
238
+ confidence: Math.min(1, data.count / messages.length || 0),
239
+ evidence_count: data.count,
240
+ });
241
+ }
242
+ return hypotheses;
243
+ }
@@ -0,0 +1,11 @@
1
+ import { ProviderAdapterError } from "./errors.js";
2
+ /** Provider resources could not be proven closed after bounded cleanup. */
3
+ export class ProviderCleanupError extends ProviderAdapterError {
4
+ cleanupIncomplete = true;
5
+ cleanupResources;
6
+ userMessage = "Provider cleanup could not be fully confirmed. Review the reported local resources before opening another target.";
7
+ constructor(providerId, resources, diagnostics, options) {
8
+ super(providerId, "close_binary", { ...options, diagnostics });
9
+ this.cleanupResources = [...resources];
10
+ }
11
+ }
@@ -0,0 +1,278 @@
1
+ import canonicalize from "canonicalize";
2
+ import { z } from "zod";
3
+ import { evidenceBundleSchema } from "./evidenceBundle.js";
4
+ const digestSchema = z.string().regex(/^[a-f0-9]{64}$/u);
5
+ const evidenceIdSchema = z.string().regex(/^ev_[a-f0-9]{64}$/u);
6
+ const stableIdSchema = z.string().regex(/^[A-Za-z][A-Za-z0-9._:/-]{0,199}$/u);
7
+ const boundedTextSchema = z.string().trim().min(1).max(4_096);
8
+ export const obligationStatusSchema = z.enum([
9
+ "unowned",
10
+ "characterized",
11
+ "implemented",
12
+ "verified",
13
+ "contradicted",
14
+ "blocked",
15
+ "out-of-scope",
16
+ "unknown",
17
+ ]);
18
+ export const obligationLayerSchema = z.enum([
19
+ "cli",
20
+ "protocol",
21
+ "electron",
22
+ "persistence",
23
+ "process",
24
+ "runtime",
25
+ "packaging",
26
+ "native-abi",
27
+ "application",
28
+ "other",
29
+ ]);
30
+ export const obligationCaseKindSchema = z.enum([
31
+ "positive",
32
+ "negative",
33
+ "malformed",
34
+ "cancellation",
35
+ "teardown",
36
+ ]);
37
+ export const obligationProofAuthoritySchema = z.enum([
38
+ "unit",
39
+ "integration",
40
+ "protocol",
41
+ "renderer",
42
+ "packaged-process",
43
+ "native-abi",
44
+ "live-observation",
45
+ "external",
46
+ ]);
47
+ export const obligationOriginalAuthoritySchema = z.enum([
48
+ "static",
49
+ "runtime",
50
+ "process",
51
+ "external",
52
+ ]);
53
+ const obligationTargetSchema = z.strictObject({
54
+ artifact_sha256: digestSchema.nullable(),
55
+ application_node_id: z
56
+ .string()
57
+ .regex(/^jag_node_[a-f0-9]{64}$/u)
58
+ .nullable(),
59
+ semantic_node_id: z
60
+ .string()
61
+ .regex(/^jsrg_node_[a-f0-9]{64}$/u)
62
+ .nullable(),
63
+ location: boundedTextSchema,
64
+ });
65
+ const authorityReferenceSchema = z.strictObject({
66
+ evidence_id: evidenceIdSchema,
67
+ authority: z.enum([
68
+ "shipped-artifact",
69
+ "controlled-replay",
70
+ "historical-reference",
71
+ "external-service",
72
+ "analyst-inference",
73
+ ]),
74
+ state: z.enum(["candidate", "observed", "reviewed", "unknown"]),
75
+ location: boundedTextSchema,
76
+ });
77
+ const observedCaseSchema = z.strictObject({
78
+ kind: obligationCaseKindSchema,
79
+ evidence_id: evidenceIdSchema,
80
+ location: boundedTextSchema,
81
+ });
82
+ const ownerBindingSchema = z.strictObject({
83
+ module_path: boundedTextSchema,
84
+ symbol: z.string().trim().min(1).max(1_024),
85
+ owner_sha256: digestSchema,
86
+ });
87
+ const parserTypeBindingSchema = z.strictObject({
88
+ parser: boundedTextSchema,
89
+ schema: boundedTextSchema,
90
+ domain_type: boundedTextSchema,
91
+ });
92
+ const fixtureBindingSchema = z.strictObject({
93
+ fixture_id: stableIdSchema,
94
+ case_kind: obligationCaseKindSchema,
95
+ authority: obligationProofAuthoritySchema,
96
+ evidence_ids: z.array(evidenceIdSchema).min(1).max(100),
97
+ });
98
+ const nondeterminismSchema = z.strictObject({
99
+ mode: z.enum(["total-order", "partial-order", "finite-traces"]),
100
+ specification: boundedTextSchema,
101
+ });
102
+ const verifierBindingSchema = z.strictObject({
103
+ verifier_id: stableIdSchema,
104
+ claim_id: stableIdSchema,
105
+ command: boundedTextSchema,
106
+ authority: obligationProofAuthoritySchema,
107
+ status: z.enum(["pass", "fail", "unknown", "unsupported", "skipped"]),
108
+ result_evidence_id: evidenceIdSchema,
109
+ enumerated_obligation_ids: z.array(stableIdSchema).min(1).max(10_000),
110
+ nondeterminism: nondeterminismSchema,
111
+ });
112
+ export const reconstructionObligationManifestBindingSchema = z.strictObject({
113
+ obligation_id: stableIdSchema,
114
+ owner: ownerBindingSchema,
115
+ parser_type: parserTypeBindingSchema.nullable(),
116
+ original_cases: z.array(observedCaseSchema).max(100),
117
+ fixtures: z.array(fixtureBindingSchema).max(100),
118
+ verifier: verifierBindingSchema.nullable(),
119
+ });
120
+ export const reconstructionObligationManifestSchema = z.strictObject({
121
+ schema_version: z.literal(1),
122
+ bindings: z.array(reconstructionObligationManifestBindingSchema).max(10_000),
123
+ contradictions: z
124
+ .array(z.strictObject({
125
+ obligation_id: stableIdSchema,
126
+ evidence_ids: z.array(evidenceIdSchema).min(2).max(100),
127
+ }))
128
+ .max(10_000),
129
+ });
130
+ export const reviewedReconstructionObligationSchema = z.strictObject({
131
+ obligation_id: stableIdSchema,
132
+ obligation_version: z.number().int().min(1),
133
+ title: z.string().trim().min(1).max(500),
134
+ application_layer: obligationLayerSchema,
135
+ family: z.string().trim().min(1).max(100),
136
+ target: obligationTargetSchema,
137
+ required: z.boolean(),
138
+ required_case_kinds: z.array(obligationCaseKindSchema).min(1).max(5),
139
+ required_original_authority: obligationOriginalAuthoritySchema,
140
+ required_fixture_authority: obligationProofAuthoritySchema,
141
+ required_verifier_authority: obligationProofAuthoritySchema,
142
+ requires_parser_type: z.boolean(),
143
+ dependency_obligation_ids: z.array(stableIdSchema).max(1_000),
144
+ residual_unknown_ids: z.array(stableIdSchema).max(1_000),
145
+ unavailable_authority: z.array(boundedTextSchema).max(100),
146
+ required_next_evidence: z.array(boundedTextSchema).max(100),
147
+ disposition: z.enum(["active", "blocked", "out-of-scope"]),
148
+ review_evidence_ids: z.array(evidenceIdSchema).min(1).max(100),
149
+ });
150
+ const diagnosticSchema = z.strictObject({
151
+ code: z.enum([
152
+ "duplicate-definition",
153
+ "missing-owner",
154
+ "ambiguous-owner",
155
+ "missing-parser-type",
156
+ "missing-original-case",
157
+ "weak-original-case-authority",
158
+ "missing-case",
159
+ "weak-fixture-authority",
160
+ "missing-verifier",
161
+ "verifier-does-not-enumerate",
162
+ "missing-verifier-result",
163
+ "weak-verifier-authority",
164
+ "verifier-failed",
165
+ "static-only",
166
+ "contradiction",
167
+ "contradiction-evidence-missing",
168
+ "residual-unknown",
169
+ "dependency-missing",
170
+ "dependency-open",
171
+ "unavailable-authority",
172
+ "blocked",
173
+ "out-of-scope",
174
+ ]),
175
+ detail: boundedTextSchema,
176
+ });
177
+ export const reconstructionObligationSchema = z.strictObject({
178
+ obligation_id: stableIdSchema,
179
+ obligation_version: z.number().int().min(1),
180
+ title: z.string().trim().min(1).max(500),
181
+ origin: z.enum(["generated", "reviewed"]),
182
+ application_layer: obligationLayerSchema,
183
+ family: z.string().trim().min(1).max(100),
184
+ target: obligationTargetSchema,
185
+ authority_references: z.array(authorityReferenceSchema).min(1).max(1_000),
186
+ source_state: z.enum(["candidate", "observed", "reviewed", "unknown"]),
187
+ observed_cases: z.array(observedCaseSchema).max(100),
188
+ required: z.boolean(),
189
+ required_case_kinds: z.array(obligationCaseKindSchema).min(1).max(5),
190
+ required_original_authority: obligationOriginalAuthoritySchema,
191
+ required_fixture_authority: obligationProofAuthoritySchema,
192
+ required_verifier_authority: obligationProofAuthoritySchema,
193
+ requires_parser_type: z.boolean(),
194
+ dependency_obligation_ids: z.array(stableIdSchema).max(1_000),
195
+ residual_unknown_ids: z.array(stableIdSchema).max(1_000),
196
+ unavailable_authority: z.array(boundedTextSchema).max(100),
197
+ required_next_evidence: z.array(boundedTextSchema).max(100),
198
+ binding: reconstructionObligationManifestBindingSchema.nullable(),
199
+ status: obligationStatusSchema,
200
+ diagnostics: z.array(diagnosticSchema).max(1_000),
201
+ });
202
+ const countBySchema = (key) => z.array(z.strictObject({
203
+ key,
204
+ count: z.number().int().min(0),
205
+ }));
206
+ export const reconstructionObligationLedgerSchema = z.strictObject({
207
+ schema: z.literal("ReconstructionObligationLedger"),
208
+ schema_version: z.literal(1),
209
+ ledger_id: z.string().regex(/^rol_[a-f0-9]{64}$/u),
210
+ closure_digest: digestSchema,
211
+ status: z.enum(["ready", "open", "failed", "unknown"]),
212
+ coverage: z.strictObject({
213
+ status: z.enum(["complete", "partial"]),
214
+ truncated: z.boolean(),
215
+ omitted_count: z.number().int().min(0),
216
+ max_obligations: z.number().int().min(1),
217
+ }),
218
+ summary: z.strictObject({
219
+ total: z.number().int().min(0),
220
+ required: z.number().int().min(0),
221
+ verified: z.number().int().min(0),
222
+ required_open: z.number().int().min(0),
223
+ by_status: countBySchema(obligationStatusSchema),
224
+ by_application_layer: countBySchema(obligationLayerSchema),
225
+ by_evidence_authority: countBySchema(z.enum(["candidate", "observed", "reviewed", "unknown"])),
226
+ }),
227
+ reports: z.strictObject({
228
+ missing_owner_obligation_ids: z.array(stableIdSchema),
229
+ missing_verifier_obligation_ids: z.array(stableIdSchema),
230
+ contradicted_obligation_ids: z.array(stableIdSchema),
231
+ residual_unknown_ids: z.array(stableIdSchema),
232
+ }),
233
+ ownership_graph: z.array(z.strictObject({
234
+ obligation_id: stableIdSchema,
235
+ module_path: boundedTextSchema,
236
+ symbol: z.string().trim().min(1).max(1_024),
237
+ })),
238
+ dependency_graph: z.array(z.strictObject({
239
+ obligation_id: stableIdSchema,
240
+ depends_on_obligation_id: stableIdSchema,
241
+ })),
242
+ obligations: z.array(reconstructionObligationSchema).max(10_000),
243
+ evidence_links: z.array(evidenceIdSchema).max(100_000),
244
+ limitations: z.array(boundedTextSchema).max(1_000),
245
+ });
246
+ export const reconstructionObligationLedgerInputSchema = z.strictObject({
247
+ evidence_bundle: evidenceBundleSchema,
248
+ reviewed_obligations: z
249
+ .array(reviewedReconstructionObligationSchema)
250
+ .max(10_000),
251
+ manifest: reconstructionObligationManifestSchema,
252
+ limits: z.strictObject({
253
+ max_obligations: z.number().int().min(1).max(10_000),
254
+ }),
255
+ page: z.strictObject({
256
+ offset: z.number().int().min(0).max(10_000),
257
+ limit: z.number().int().min(1).max(100),
258
+ }),
259
+ });
260
+ export const reconstructionObligationLedgerPageSchema = z.strictObject({
261
+ ...reconstructionObligationLedgerSchema.omit({ obligations: true }).shape,
262
+ page: z.strictObject({
263
+ offset: z.number().int().min(0),
264
+ limit: z.number().int().min(1).max(100),
265
+ total: z.number().int().min(0),
266
+ returned: z.number().int().min(0),
267
+ next_offset: z.number().int().min(0).nullable(),
268
+ }),
269
+ obligations: z.array(reconstructionObligationSchema).max(100),
270
+ });
271
+ /** Parse and canonically serialize one complete reconstruction obligation ledger. */
272
+ export const serializeReconstructionObligationLedger = (input) => {
273
+ const ledger = reconstructionObligationLedgerSchema.parse(input);
274
+ const encoded = canonicalize(ledger);
275
+ if (encoded === undefined)
276
+ throw new TypeError("Reconstruction obligation ledger is not canonical JSON");
277
+ return encoded;
278
+ };
@@ -0,0 +1,121 @@
1
+ import { createHash } from "node:crypto";
2
+ import canonicalize from "canonicalize";
3
+ import { parseEvidenceBundle } from "./evidenceBundle.js";
4
+ import { readinessFindingOrder } from "./reconstructionReadinessFindingHelpers.js";
5
+ import { READINESS_STAGE_IDS, readinessJourneyFindings, } from "./reconstructionReadinessJourneyFindings.js";
6
+ import { readinessIntegrityFindings } from "./reconstructionReadinessIntegrityFindings.js";
7
+ import { reconstructionReadinessInputSchema, reconstructionReadinessReportSchema, } from "./reconstructionReadinessSchemas.js";
8
+ /** Evaluate one public-contract journey into a deterministic fail-closed report. */
9
+ export const createReconstructionReadinessReport = (inputValue) => {
10
+ const input = reconstructionReadinessInputSchema.parse(inputValue);
11
+ const sourceDigest = digest(sourceValue(input));
12
+ const evidenceIds = new Set(parseEvidenceBundle(input.evidence_bundle).records.map(({ evidence_id: evidenceId }) => evidenceId));
13
+ const findings = [
14
+ ...readinessJourneyFindings(input, evidenceIds),
15
+ ...readinessIntegrityFindings(input, evidenceIds, sourceDigest),
16
+ ].sort(readinessFindingOrder);
17
+ const stages = effectiveStages(input, findings);
18
+ const status = aggregateStatus(stages);
19
+ const semantic = {
20
+ source_digest: sourceDigest,
21
+ status,
22
+ summary: {
23
+ stages: stages.length,
24
+ required_stages: stages.filter(({ required }) => required).length,
25
+ passed_required_stages: stages.filter(({ required, status: stageStatus }) => required && stageStatus === "pass").length,
26
+ findings: findings.length,
27
+ failed_findings: findings.filter(({ status: findingStatus }) => findingStatus === "fail").length,
28
+ unknown_findings: findings.filter(({ status: findingStatus }) => findingStatus === "unknown").length,
29
+ },
30
+ metrics: readinessMetrics(input),
31
+ stages,
32
+ findings,
33
+ evidence_links: [...evidenceIds].sort(),
34
+ snapshot: input,
35
+ };
36
+ const reportDigest = digest({
37
+ schema: "rea.reconstruction-readiness-report/v1",
38
+ ...semantic,
39
+ });
40
+ return reconstructionReadinessReportSchema.parse({
41
+ schema: "ReconstructionReadinessReport",
42
+ schema_version: 1,
43
+ report_id: `rr_${reportDigest}`,
44
+ report_digest: reportDigest,
45
+ ...semantic,
46
+ });
47
+ };
48
+ const effectiveStages = (input, findings) => READINESS_STAGE_IDS.map((stageId) => {
49
+ const stage = input.stages.find(({ stage_id: id }) => id === stageId);
50
+ const stageFindings = findings.filter(({ stage_id: id }) => id === stageId);
51
+ const status = stageFindings.some(({ status: findingStatus }) => findingStatus === "fail")
52
+ ? "fail"
53
+ : stage !== undefined && stage.status !== "pass"
54
+ ? stage.status
55
+ : stageFindings.length > 0
56
+ ? "unknown"
57
+ : (stage?.status ?? "fail");
58
+ return stage === undefined
59
+ ? {
60
+ stage_id: stageId,
61
+ required: true,
62
+ status,
63
+ capability_issue: null,
64
+ next_action: "Supply the missing conformance stage.",
65
+ evidence_ids: [],
66
+ checks: [],
67
+ }
68
+ : { ...stage, required: true, status };
69
+ });
70
+ const aggregateStatus = (stages) => {
71
+ const required = stages.filter(({ required }) => required);
72
+ if (required.some(({ status }) => status === "fail"))
73
+ return "fail";
74
+ if (required.every(({ status }) => status === "pass"))
75
+ return "pass";
76
+ for (const status of [
77
+ "unknown",
78
+ "truncated",
79
+ "unsupported",
80
+ "skipped",
81
+ ])
82
+ if (required.some(({ status: stageStatus }) => stageStatus === status))
83
+ return status;
84
+ return "unknown";
85
+ };
86
+ const readinessMetrics = (input) => {
87
+ const selectedFixtures = input.fixtures.filter((fixture) => input.workflow_candidates.some(({ fixture_id: fixtureId, selected, compatibility }) => fixtureId === fixture.fixture_id &&
88
+ selected &&
89
+ compatibility === "compatible")).length;
90
+ const prerequisiteFailures = input.operation_outcomes.filter(({ call_kind: kind, expected_success: success }) => !success && ["setup", "permission"].includes(kind));
91
+ const localized = input.comparisons.filter(({ deliberate_divergence_ref: expected, divergence_refs: observed }) => expected !== null && observed.includes(expected)).length;
92
+ const deliberate = input.comparisons.filter(({ deliberate_divergence_ref: expected }) => expected !== null).length;
93
+ const falseEquivalence = input.comparisons.filter((comparison) => comparison.verdict === "equivalent" &&
94
+ (comparison.truncated ||
95
+ comparison.unavailable_authority ||
96
+ comparison.unstable ||
97
+ comparison.contradiction_ids.length > 0)).length;
98
+ return {
99
+ first_valid_workflow_selection_rate: ratio(selectedFixtures, input.fixtures.length),
100
+ malformed_or_over_limit_call_rate: ratio(input.operation_outcomes.filter(({ call_kind: kind }) => ["malformed", "over-limit"].includes(kind)).length, input.operation_outcomes.length),
101
+ incompatible_provider_invocations: input.workflow_candidates.filter(({ invoked, compatibility }) => invoked && compatibility !== "compatible").length,
102
+ failed_calls_before_prerequisites: prerequisiteFailures.length,
103
+ recovery_rate: ratio(prerequisiteFailures.filter(({ recovered }) => recovered).length, prerequisiteFailures.length),
104
+ divergence_localization_precision: ratio(localized, deliberate),
105
+ false_equivalence_count: falseEquivalence,
106
+ unowned_obligation_count: input.obligation_ledger.reports.missing_owner_obligation_ids.length,
107
+ cleanup_leak_count: input.cleanup.filter(({ owned_resources_remaining: remaining }) => remaining > 0).length,
108
+ nondeterministic_replay_count: input.replay.deterministic ? 0 : 1,
109
+ };
110
+ };
111
+ const sourceValue = (input) => ({
112
+ ...input,
113
+ replay: { ...input.replay, expected_source_digest: null },
114
+ });
115
+ const ratio = (numerator, denominator) => denominator === 0 ? 1 : numerator / denominator;
116
+ const digest = (value) => {
117
+ const encoded = canonicalize(value);
118
+ if (encoded === undefined)
119
+ throw new TypeError("Reconstruction readiness value is not canonical JSON");
120
+ return createHash("sha256").update(encoded).digest("hex");
121
+ };
@@ -0,0 +1,17 @@
1
+ export const addMissingEvidenceFindings = (findings, stageId, referencedIds, availableIds) => {
2
+ for (const evidenceId of new Set(referencedIds))
3
+ if (!availableIds.has(evidenceId))
4
+ findings.push(readinessFinding("referenced-evidence-missing", stageId, "unknown", `Referenced Evidence is absent from the bundle: ${evidenceId}.`));
5
+ };
6
+ export const readinessFinding = (...[code, stageId, status, detail, evidenceIds = []]) => ({
7
+ code,
8
+ stage_id: stageId,
9
+ status,
10
+ detail,
11
+ evidence_ids: [...new Set(evidenceIds)].sort(),
12
+ });
13
+ export const readinessFindingOrder = (left, right) => {
14
+ const leftKey = `${left.stage_id}:${left.code}:${left.detail}`;
15
+ const rightKey = `${right.stage_id}:${right.code}:${right.detail}`;
16
+ return leftKey < rightKey ? -1 : leftKey > rightKey ? 1 : 0;
17
+ };