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,118 @@
1
+ import { addMissingEvidenceFindings, readinessFinding as finding, } from "./reconstructionReadinessFindingHelpers.js";
2
+ export const readinessIntegrityFindings = (input, evidenceIds, sourceDigest) => [
3
+ ...comparisonFindings(input, evidenceIds),
4
+ ...contradictionFindings(input, evidenceIds),
5
+ ...closureFindings(input, evidenceIds),
6
+ ...cleanupFindings(input, evidenceIds),
7
+ ...replayFindings(input, evidenceIds, sourceDigest),
8
+ ];
9
+ const comparisonFindings = (input, evidenceIds) => {
10
+ const findings = [];
11
+ for (const comparison of input.comparisons) {
12
+ const unsafeEquivalent = comparison.verdict === "equivalent" &&
13
+ (comparison.truncated ||
14
+ comparison.unavailable_authority ||
15
+ comparison.unstable ||
16
+ comparison.contradiction_ids.length > 0);
17
+ if (unsafeEquivalent)
18
+ findings.push(finding("false-equivalence", "compare-authority-candidate", "fail", `${comparison.comparison_id} claims equivalence across incomplete or contradicted Evidence.`, comparison.evidence_ids));
19
+ if (comparison.concurrent &&
20
+ comparison.schedule_semantics === "total-order")
21
+ findings.push(finding("unsafe-concurrency-semantics", "compare-authority-candidate", "fail", `${comparison.comparison_id} uses total-order semantics for concurrent behavior.`, comparison.evidence_ids));
22
+ if (comparison.deliberate_divergence_ref !== null &&
23
+ !comparison.divergence_refs.includes(comparison.deliberate_divergence_ref))
24
+ findings.push(finding("divergence-not-localized", "compare-authority-candidate", "fail", `${comparison.comparison_id} did not localize its deliberate primary divergence.`, comparison.evidence_ids));
25
+ addMissingEvidenceFindings(findings, "compare-authority-candidate", comparison.evidence_ids, evidenceIds);
26
+ }
27
+ return findings;
28
+ };
29
+ const contradictionFindings = (input, evidenceIds) => {
30
+ const findings = [];
31
+ const comparisons = new Map(input.comparisons.map((comparison) => [
32
+ comparison.comparison_id,
33
+ comparison,
34
+ ]));
35
+ for (const contradiction of input.contradictions) {
36
+ if (contradiction.declared_sha256 === contradiction.observed_sha256 ||
37
+ new Set(contradiction.evidence_ids).size < 2)
38
+ findings.push(finding("contradiction-proof-incomplete", "preserve-contradictions", "fail", `${contradiction.contradiction_id} must preserve distinct hashes and Evidence records.`, contradiction.evidence_ids));
39
+ for (const comparisonId of contradiction.affected_comparison_ids) {
40
+ const comparison = comparisons.get(comparisonId);
41
+ if (comparison === undefined)
42
+ findings.push(finding("contradiction-comparison-missing", "preserve-contradictions", "unknown", `Contradiction references missing comparison ${comparisonId}.`, contradiction.evidence_ids));
43
+ else if (comparison.verdict === "equivalent" ||
44
+ !comparison.contradiction_ids.includes(contradiction.contradiction_id))
45
+ findings.push(finding("contradiction-equivalence-not-blocked", "preserve-contradictions", "fail", `${comparisonId} does not preserve contradiction ${contradiction.contradiction_id}.`, contradiction.evidence_ids));
46
+ }
47
+ addMissingEvidenceFindings(findings, "preserve-contradictions", contradiction.evidence_ids, evidenceIds);
48
+ }
49
+ return findings;
50
+ };
51
+ const closureFindings = (input, evidenceIds) => {
52
+ const findings = [];
53
+ if (input.obligation_ledger.summary.required === 0)
54
+ findings.push(finding("reconstruction-obligations-empty", "verify-reconstruction-closure", "unknown", "A ready ledger must include at least one required reconstruction obligation."));
55
+ if (input.obligation_ledger.status !== "ready" ||
56
+ input.obligation_ledger.summary.required_open > 0)
57
+ findings.push(finding("reconstruction-closure-open", "verify-reconstruction-closure", "unknown", `Obligation ledger is ${input.obligation_ledger.status} with ${String(input.obligation_ledger.summary.required_open)} required obligations open.`, input.obligation_ledger.evidence_links));
58
+ addMissingEvidenceFindings(findings, "verify-reconstruction-closure", input.obligation_ledger.evidence_links, evidenceIds);
59
+ evaluateClosureHistory(input, findings, evidenceIds);
60
+ for (const check of input.delegation_checks) {
61
+ if (check.delegates_to_authority)
62
+ findings.push(finding("candidate-delegates-to-authority", "verify-reconstruction-closure", "fail", `${check.candidate_id} delegates behavior back to the authority.`, check.evidence_ids));
63
+ addMissingEvidenceFindings(findings, "verify-reconstruction-closure", check.evidence_ids, evidenceIds);
64
+ }
65
+ return findings;
66
+ };
67
+ const evaluateClosureHistory = (input, findings, evidenceIds) => {
68
+ const history = [...input.closure_history].sort((left, right) => left.sequence - right.sequence);
69
+ if (new Set(history.map(({ sequence }) => sequence)).size !== history.length ||
70
+ history.at(-1)?.ledger_digest !== input.obligation_ledger.closure_digest)
71
+ findings.push(finding("closure-history-identity-mismatch", "verify-reconstruction-closure", "fail", "Closure history sequences must be unique and end at the supplied ledger digest."));
72
+ if (history[0]?.required_open === 0 ||
73
+ history.at(-1)?.required_open !== 0 ||
74
+ history.at(-1)?.status !== "ready")
75
+ findings.push(finding("incremental-closure-history-missing", "verify-reconstruction-closure", "unknown", "Closure history must begin partial and end ready with zero required obligations open."));
76
+ for (const [index, observation] of history.entries()) {
77
+ const previous = history[index - 1];
78
+ if (previous !== undefined &&
79
+ (observation.required_open > previous.required_open ||
80
+ observation.newly_verified_obligation_ids.length !==
81
+ previous.required_open - observation.required_open))
82
+ findings.push(finding("invalid-obligation-closure-transition", "verify-reconstruction-closure", "fail", `Closure observation ${String(observation.sequence)} does not match its newly verified obligations.`, observation.evidence_ids));
83
+ if (observation.newly_verified_obligation_ids.some((obligationId) => !input.obligation_ledger.obligations.some(({ obligation_id: candidateId, status }) => candidateId === obligationId && status === "verified")))
84
+ findings.push(finding("closure-obligation-proof-missing", "verify-reconstruction-closure", "fail", `Closure observation ${String(observation.sequence)} names an obligation without verified ledger proof.`, observation.evidence_ids));
85
+ addMissingEvidenceFindings(findings, "verify-reconstruction-closure", observation.evidence_ids, evidenceIds);
86
+ }
87
+ };
88
+ const cleanupFindings = (input, evidenceIds) => {
89
+ const findings = [];
90
+ for (const cleanup of input.cleanup) {
91
+ if (cleanup.owned_resources_remaining > 0)
92
+ findings.push(finding("owned-resource-leak", "reactive-scenarios", "fail", `${cleanup.run_id} retained ${String(cleanup.owned_resources_remaining)} owned resources.`, cleanup.diagnostic_evidence_ids));
93
+ if (cleanup.cancelled && cleanup.diagnostic_evidence_ids.length === 0)
94
+ findings.push(finding("cancelled-diagnostic-evidence-missing", "reactive-scenarios", "unknown", `${cleanup.run_id} cancellation retained no diagnostic Evidence.`));
95
+ addMissingEvidenceFindings(findings, "reactive-scenarios", cleanup.diagnostic_evidence_ids, evidenceIds);
96
+ }
97
+ for (const grant of input.grants) {
98
+ if (["denied", "cancelled"].includes(grant.decision) &&
99
+ grant.launched_process)
100
+ findings.push(finding("denied-authority-launched-process", "acquire-authority", "fail", `${grant.grant_id} launched a process after ${grant.decision}.`, grant.evidence_ids));
101
+ addMissingEvidenceFindings(findings, "acquire-authority", grant.evidence_ids, evidenceIds);
102
+ }
103
+ return findings;
104
+ };
105
+ const replayFindings = (input, evidenceIds, sourceDigest) => {
106
+ const findings = [];
107
+ if (!input.replay.deterministic)
108
+ findings.push(finding("replay-nondeterministic", "export-replay", "fail", "Clean replay did not reproduce the same semantic report.", input.replay.evidence_ids));
109
+ if (!input.replay.tamper_detected)
110
+ findings.push(finding("tamper-not-detected", "export-replay", "fail", "The conformance replay did not reject a tampered input.", input.replay.evidence_ids));
111
+ if (!input.replay.stale_input_detected)
112
+ findings.push(finding("stale-input-not-detected", "export-replay", "fail", "The conformance replay did not reject a stale digest.", input.replay.evidence_ids));
113
+ if (input.replay.expected_source_digest !== null &&
114
+ input.replay.expected_source_digest !== sourceDigest)
115
+ findings.push(finding("replay-source-digest-mismatch", "export-replay", "fail", `Expected ${input.replay.expected_source_digest}; observed ${sourceDigest}.`, input.replay.evidence_ids));
116
+ addMissingEvidenceFindings(findings, "export-replay", input.replay.evidence_ids, evidenceIds);
117
+ return findings;
118
+ };
@@ -0,0 +1,193 @@
1
+ import { addMissingEvidenceFindings, readinessFinding as finding, } from "./reconstructionReadinessFindingHelpers.js";
2
+ import { readinessStageIdSchema, } from "./reconstructionReadinessSchemas.js";
3
+ export const READINESS_REQUIRED_CHECKS = {
4
+ "discover-classify": [
5
+ "target-free-start",
6
+ "artifact-inventory",
7
+ "compatible-workflow-selected",
8
+ "limits-visible",
9
+ ],
10
+ "diagnose-environment": [
11
+ "broken-runtime-distinguished",
12
+ "version-skew-detected",
13
+ "revision-changed-after-recovery",
14
+ ],
15
+ "acquire-authority": [
16
+ "missing-scope-reported",
17
+ "narrow-grant-resumed",
18
+ "expansion-reprompted",
19
+ "denial-launched-nothing",
20
+ ],
21
+ "static-analysis": [
22
+ "native-routed",
23
+ "javascript-routed",
24
+ "unknowns-preserved",
25
+ ],
26
+ "reactive-scenarios": [
27
+ "predicate-driven",
28
+ "descendant-settled",
29
+ "electron-correlated",
30
+ "cancel-cleanup-preserved-evidence",
31
+ ],
32
+ "compare-authority-candidate": [
33
+ "partial-order-accepted",
34
+ "divergence-localized",
35
+ "incomplete-is-unknown",
36
+ ],
37
+ "preserve-contradictions": [
38
+ "record-and-continue",
39
+ "affected-equivalence-blocked",
40
+ "unaffected-comparison-continued",
41
+ ],
42
+ "verify-reconstruction-closure": [
43
+ "incomplete-detected",
44
+ "incremental-verifier-closure",
45
+ "delegation-rejected",
46
+ ],
47
+ "export-replay": [
48
+ "cli-mcp-parity",
49
+ "failure-status-parity",
50
+ "deterministic-replay",
51
+ "tamper-detected",
52
+ "stale-input-detected",
53
+ ],
54
+ };
55
+ export const READINESS_STAGE_IDS = readinessStageIdSchema.options;
56
+ export const readinessJourneyFindings = (input, evidenceIds) => [
57
+ ...identityFindings(input),
58
+ ...fixtureFindings(input),
59
+ ...stageFindings(input, evidenceIds),
60
+ ...capabilityFindings(input),
61
+ ...workflowFindings(input),
62
+ ...authorityFindings(input),
63
+ ...outcomeFindings(input, evidenceIds),
64
+ ];
65
+ const identityFindings = (input) => {
66
+ const findings = [];
67
+ if (!input.identity.versions.some(({ state }) => state === "stale"))
68
+ findings.push(finding("version-skew-observation-missing", "diagnose-environment", "fail", "The journey did not preserve a stale version observation."));
69
+ if (!input.identity.versions.some(({ state }) => state === "current"))
70
+ findings.push(finding("corrected-version-observation-missing", "diagnose-environment", "fail", "The journey did not preserve corrected current version state."));
71
+ if (!input.identity.providers.some(({ state }) => state === "broken-host"))
72
+ findings.push(finding("broken-host-observation-missing", "diagnose-environment", "fail", "The journey did not distinguish a broken host dependency."));
73
+ return findings;
74
+ };
75
+ const fixtureFindings = (input) => {
76
+ const requiredKinds = [
77
+ "native",
78
+ "javascript-cli",
79
+ "electron",
80
+ "incomplete-reconstruction",
81
+ "broken-runtime",
82
+ ];
83
+ return requiredKinds.flatMap((kind) => input.fixtures.some(({ kind: fixtureKind }) => fixtureKind === kind)
84
+ ? []
85
+ : [
86
+ finding("representative-fixture-missing", "discover-classify", "fail", `The required ${kind} fixture is missing.`),
87
+ ]);
88
+ };
89
+ const stageFindings = (input, evidenceIds) => {
90
+ const findings = [];
91
+ for (const stageId of READINESS_STAGE_IDS) {
92
+ const matching = input.stages.filter(({ stage_id: id }) => id === stageId);
93
+ if (matching.length !== 1) {
94
+ findings.push(finding("stage-cardinality", stageId, "fail", `Expected exactly one ${stageId} stage; observed ${String(matching.length)}.`));
95
+ continue;
96
+ }
97
+ const stage = matching[0];
98
+ if (stage === undefined)
99
+ continue;
100
+ if (!stage.required)
101
+ findings.push(finding("required-stage-disabled", stageId, "fail", "The public conformance journey requires this stage."));
102
+ const checks = new Map(stage.checks.map((check) => [check.check_id, check]));
103
+ if (checks.size !== stage.checks.length)
104
+ findings.push(finding("duplicate-stage-check", stageId, "fail", "Stage check IDs must be unique."));
105
+ for (const checkId of READINESS_REQUIRED_CHECKS[stageId]) {
106
+ const check = checks.get(checkId);
107
+ if (check === undefined) {
108
+ findings.push(finding("missing-stage-check", stageId, "fail", `Required conformance check is missing: ${checkId}.`));
109
+ continue;
110
+ }
111
+ if (check.status !== "pass")
112
+ findings.push(finding("stage-check-not-pass", stageId, check.status === "fail" ? "fail" : "unknown", `${checkId} is ${check.status}: ${check.detail}`, check.evidence_ids));
113
+ if (check.evidence_ids.length === 0)
114
+ findings.push(finding("stage-check-evidence-missing", stageId, "unknown", `${checkId} has no attributable Evidence.`));
115
+ addMissingEvidenceFindings(findings, stageId, [...stage.evidence_ids, ...check.evidence_ids], evidenceIds);
116
+ }
117
+ }
118
+ return findings;
119
+ };
120
+ const capabilityFindings = (input) => input.capabilities.flatMap((capability) => {
121
+ const findings = [];
122
+ if (capability.bounded && capability.limits.length === 0)
123
+ findings.push(finding("bounded-limit-hidden", "discover-classify", "fail", `${capability.capability_id} is bounded but declares no exact limits.`));
124
+ if (!capability.available && capability.unavailable_reason === null)
125
+ findings.push(finding("unavailable-reason-missing", "discover-classify", "unknown", `${capability.capability_id} is unavailable without an actionable reason.`));
126
+ return findings;
127
+ });
128
+ const workflowFindings = (input) => {
129
+ const findings = [];
130
+ for (const fixture of input.fixtures) {
131
+ const selected = input.workflow_candidates.filter(({ fixture_id: fixtureId, selected: isSelected }) => fixtureId === fixture.fixture_id && isSelected);
132
+ if (selected.length !== 1 || selected[0]?.compatibility !== "compatible")
133
+ findings.push(finding("compatible-workflow-not-selected", "discover-classify", "fail", `${fixture.fixture_id} does not have exactly one compatible selected workflow.`));
134
+ }
135
+ for (const candidate of input.workflow_candidates)
136
+ if (candidate.invoked && candidate.compatibility !== "compatible")
137
+ findings.push(finding("incompatible-provider-invoked", "static-analysis", "fail", `${candidate.workflow_id} was invoked despite ${candidate.compatibility} routing.`));
138
+ return findings;
139
+ };
140
+ const authorityFindings = (input) => {
141
+ const deniedScopes = new Set(input.grants
142
+ .filter(({ decision }) => ["denied", "cancelled"].includes(decision))
143
+ .map(({ scope }) => scope));
144
+ const recoveredScopes = new Set(input.grants
145
+ .filter(({ decision }) => decision === "granted")
146
+ .map(({ scope }) => scope));
147
+ return [...deniedScopes].some((scope) => recoveredScopes.has(scope))
148
+ ? []
149
+ : [
150
+ finding("narrow-authority-recovery-missing", "acquire-authority", "fail", "No denied or cancelled scope was later recovered by a narrow grant."),
151
+ ];
152
+ };
153
+ const outcomeFindings = (input, evidenceIds) => {
154
+ const findings = [];
155
+ const parity = new Map();
156
+ for (const outcome of input.operation_outcomes) {
157
+ const expectedCliExit = outcome.expected_success ? 0 : 1;
158
+ if (outcome.surface === "cli" &&
159
+ (outcome.cli_exit_code === null ||
160
+ (expectedCliExit === 0
161
+ ? outcome.cli_exit_code !== 0
162
+ : outcome.cli_exit_code === 0)))
163
+ findings.push(finding("cli-status-mismatch", "export-replay", "fail", `${outcome.operation} CLI process status contradicts its structured outcome.`, outcome.evidence_ids));
164
+ if (outcome.surface === "mcp" &&
165
+ outcome.mcp_status !==
166
+ (outcome.expected_success ? "success" : "non-success"))
167
+ findings.push(finding("mcp-status-mismatch", "export-replay", "fail", `${outcome.operation} MCP status contradicts its structured outcome.`, outcome.evidence_ids));
168
+ const key = `${outcome.operation}:${outcome.call_kind}:${String(outcome.expected_success)}`;
169
+ parity.set(key, new Set([...(parity.get(key) ?? []), outcome.surface]));
170
+ addMissingEvidenceFindings(findings, "export-replay", outcome.evidence_ids, evidenceIds);
171
+ }
172
+ for (const [key, surfaces] of parity)
173
+ if (surfaces.size !== 2)
174
+ findings.push(finding("surface-parity-missing", "export-replay", "fail", `CLI/MCP outcome pair is incomplete: ${key}.`));
175
+ for (const [key, outcomes] of groupedOutcomes(input)) {
176
+ const cli = outcomes.find(({ surface }) => surface === "cli");
177
+ const mcp = outcomes.find(({ surface }) => surface === "mcp");
178
+ if (cli !== undefined &&
179
+ mcp !== undefined &&
180
+ (cli.expected_success !== mcp.expected_success ||
181
+ cli.error_code !== mcp.error_code))
182
+ findings.push(finding("surface-semantic-drift", "export-replay", "fail", `CLI/MCP structured outcomes disagree: ${key}.`, [...cli.evidence_ids, ...mcp.evidence_ids]));
183
+ }
184
+ return findings;
185
+ };
186
+ const groupedOutcomes = (input) => {
187
+ const grouped = new Map();
188
+ for (const outcome of input.operation_outcomes) {
189
+ const key = `${outcome.operation}:${outcome.call_kind}`;
190
+ grouped.set(key, [...(grouped.get(key) ?? []), outcome]);
191
+ }
192
+ return grouped;
193
+ };
@@ -0,0 +1,240 @@
1
+ import { z } from "zod";
2
+ import { evidenceBundleSchema } from "./evidenceBundle.js";
3
+ import { reconstructionObligationLedgerSchema } from "./reconstructionObligationLedgerSchemas.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 readinessStatusSchema = z.enum([
9
+ "pass",
10
+ "fail",
11
+ "unknown",
12
+ "unsupported",
13
+ "truncated",
14
+ "skipped",
15
+ ]);
16
+ export const readinessStageIdSchema = z.enum([
17
+ "discover-classify",
18
+ "diagnose-environment",
19
+ "acquire-authority",
20
+ "static-analysis",
21
+ "reactive-scenarios",
22
+ "compare-authority-candidate",
23
+ "preserve-contradictions",
24
+ "verify-reconstruction-closure",
25
+ "export-replay",
26
+ ]);
27
+ const versionObservationSchema = z.strictObject({
28
+ component: stableIdSchema,
29
+ version: boundedTextSchema.nullable(),
30
+ digest: digestSchema.nullable(),
31
+ state: z.enum(["current", "stale", "unavailable"]),
32
+ remediation: boundedTextSchema.nullable(),
33
+ });
34
+ const providerIdentitySchema = z.strictObject({
35
+ provider_id: stableIdSchema,
36
+ version: boundedTextSchema.nullable(),
37
+ digest: digestSchema.nullable(),
38
+ state: z.enum(["available", "unavailable", "incompatible", "broken-host"]),
39
+ reason_code: stableIdSchema.nullable(),
40
+ });
41
+ const limitSchema = z.strictObject({
42
+ name: stableIdSchema,
43
+ value: z.number().finite().nonnegative(),
44
+ unit: z.enum(["count", "bytes", "milliseconds", "ratio"]),
45
+ });
46
+ const capabilitySchema = z.strictObject({
47
+ capability_id: stableIdSchema,
48
+ available: z.boolean(),
49
+ bounded: z.boolean(),
50
+ side_effect: z.enum([
51
+ "none",
52
+ "reads-target",
53
+ "launches-process",
54
+ "writes-workspace",
55
+ "network-observation",
56
+ ]),
57
+ authority_scopes: z.array(stableIdSchema).max(100),
58
+ limits: z.array(limitSchema).max(100),
59
+ unavailable_reason: boundedTextSchema.nullable(),
60
+ });
61
+ const fixtureSchema = z.strictObject({
62
+ fixture_id: stableIdSchema,
63
+ kind: z.enum([
64
+ "native",
65
+ "javascript-cli",
66
+ "electron",
67
+ "incomplete-reconstruction",
68
+ "broken-runtime",
69
+ ]),
70
+ artifact_sha256: digestSchema,
71
+ environment_id: stableIdSchema,
72
+ deliberate_faults: z.array(stableIdSchema).min(1).max(100),
73
+ });
74
+ const workflowCandidateSchema = z.strictObject({
75
+ fixture_id: stableIdSchema,
76
+ workflow_id: stableIdSchema,
77
+ provider_id: stableIdSchema.nullable(),
78
+ selected: z.boolean(),
79
+ invoked: z.boolean(),
80
+ compatibility: z.enum(["compatible", "incompatible", "unavailable"]),
81
+ reason_code: stableIdSchema,
82
+ });
83
+ const grantSchema = z.strictObject({
84
+ grant_id: stableIdSchema,
85
+ scope: stableIdSchema,
86
+ decision: z.enum(["granted", "denied", "cancelled", "restart-required"]),
87
+ launched_process: z.boolean(),
88
+ evidence_ids: z.array(evidenceIdSchema).max(100),
89
+ });
90
+ const comparisonSchema = z.strictObject({
91
+ comparison_id: stableIdSchema,
92
+ verdict: z.enum(["equivalent", "different", "unknown"]),
93
+ schedule_semantics: z.enum(["total-order", "partial-order", "finite-traces"]),
94
+ concurrent: z.boolean(),
95
+ truncated: z.boolean(),
96
+ unavailable_authority: z.boolean(),
97
+ unstable: z.boolean(),
98
+ deliberate_divergence_ref: boundedTextSchema.nullable(),
99
+ divergence_refs: z.array(boundedTextSchema).max(100),
100
+ contradiction_ids: z.array(stableIdSchema).max(100),
101
+ evidence_ids: z.array(evidenceIdSchema).min(1).max(1_000),
102
+ });
103
+ const contradictionSchema = z.strictObject({
104
+ contradiction_id: stableIdSchema,
105
+ declared_sha256: digestSchema,
106
+ observed_sha256: digestSchema,
107
+ policy: z.literal("record-and-continue"),
108
+ affected_comparison_ids: z.array(stableIdSchema).min(1).max(100),
109
+ evidence_ids: z.array(evidenceIdSchema).min(2).max(100),
110
+ });
111
+ const operationOutcomeSchema = z.strictObject({
112
+ sequence: z.number().int().min(0),
113
+ operation: stableIdSchema,
114
+ surface: z.enum(["cli", "mcp"]),
115
+ call_kind: z.enum([
116
+ "valid",
117
+ "malformed",
118
+ "over-limit",
119
+ "incompatible-provider",
120
+ "setup",
121
+ "permission",
122
+ "operation",
123
+ ]),
124
+ expected_success: z.boolean(),
125
+ cli_exit_code: z.number().int().min(0).nullable(),
126
+ mcp_status: z.enum(["success", "non-success"]).nullable(),
127
+ error_code: stableIdSchema.nullable(),
128
+ recovered: z.boolean(),
129
+ evidence_ids: z.array(evidenceIdSchema).max(100),
130
+ });
131
+ const cleanupSchema = z.strictObject({
132
+ run_id: stableIdSchema,
133
+ cancelled: z.boolean(),
134
+ owned_resources_remaining: z.number().int().min(0),
135
+ diagnostic_evidence_ids: z.array(evidenceIdSchema).max(100),
136
+ });
137
+ const closureObservationSchema = z.strictObject({
138
+ sequence: z.number().int().min(0),
139
+ ledger_digest: digestSchema,
140
+ status: z.enum(["ready", "open", "failed", "unknown"]),
141
+ required_open: z.number().int().min(0),
142
+ newly_verified_obligation_ids: z.array(stableIdSchema).max(10_000),
143
+ evidence_ids: z.array(evidenceIdSchema).min(1).max(1_000),
144
+ });
145
+ const delegationCheckSchema = z.strictObject({
146
+ candidate_id: stableIdSchema,
147
+ delegates_to_authority: z.boolean(),
148
+ evidence_ids: z.array(evidenceIdSchema).min(1).max(100),
149
+ });
150
+ const stageCheckSchema = z.strictObject({
151
+ check_id: stableIdSchema,
152
+ status: readinessStatusSchema,
153
+ detail: boundedTextSchema,
154
+ evidence_ids: z.array(evidenceIdSchema).max(100),
155
+ });
156
+ const stageSchema = z.strictObject({
157
+ stage_id: readinessStageIdSchema,
158
+ required: z.boolean(),
159
+ status: readinessStatusSchema,
160
+ capability_issue: stableIdSchema.nullable(),
161
+ next_action: boundedTextSchema.nullable(),
162
+ evidence_ids: z.array(evidenceIdSchema).max(1_000),
163
+ checks: z.array(stageCheckSchema).max(100),
164
+ });
165
+ const replaySchema = z.strictObject({
166
+ expected_source_digest: digestSchema.nullable(),
167
+ deterministic: z.boolean(),
168
+ tamper_detected: z.boolean(),
169
+ stale_input_detected: z.boolean(),
170
+ evidence_ids: z.array(evidenceIdSchema).max(100),
171
+ });
172
+ export const reconstructionReadinessInputSchema = z.strictObject({
173
+ schema_version: z.literal(1),
174
+ identity: z.strictObject({
175
+ cli_version: boundedTextSchema,
176
+ server_version: boundedTextSchema,
177
+ catalog_digest: digestSchema,
178
+ skill_digest: digestSchema.nullable(),
179
+ versions: z.array(versionObservationSchema).min(1).max(100),
180
+ providers: z.array(providerIdentitySchema).max(100),
181
+ }),
182
+ client: z.strictObject({
183
+ name: boundedTextSchema,
184
+ version: boundedTextSchema,
185
+ negotiated_capabilities: z.array(stableIdSchema).max(100),
186
+ }),
187
+ capabilities: z.array(capabilitySchema).min(1).max(1_000),
188
+ fixtures: z.array(fixtureSchema).min(1).max(100),
189
+ workflow_candidates: z.array(workflowCandidateSchema).min(1).max(1_000),
190
+ grants: z.array(grantSchema).max(1_000),
191
+ evidence_bundle: evidenceBundleSchema,
192
+ comparisons: z.array(comparisonSchema).max(1_000),
193
+ contradictions: z.array(contradictionSchema).max(1_000),
194
+ obligation_ledger: reconstructionObligationLedgerSchema,
195
+ operation_outcomes: z.array(operationOutcomeSchema).max(10_000),
196
+ cleanup: z.array(cleanupSchema).max(1_000),
197
+ closure_history: z.array(closureObservationSchema).min(2).max(1_000),
198
+ delegation_checks: z.array(delegationCheckSchema).min(1).max(1_000),
199
+ replay: replaySchema,
200
+ stages: z.array(stageSchema).max(20),
201
+ });
202
+ const findingSchema = z.strictObject({
203
+ code: stableIdSchema,
204
+ stage_id: readinessStageIdSchema,
205
+ status: z.enum(["fail", "unknown"]),
206
+ detail: boundedTextSchema,
207
+ evidence_ids: z.array(evidenceIdSchema).max(100),
208
+ });
209
+ export const reconstructionReadinessReportSchema = z.strictObject({
210
+ schema: z.literal("ReconstructionReadinessReport"),
211
+ schema_version: z.literal(1),
212
+ report_id: z.string().regex(/^rr_[a-f0-9]{64}$/u),
213
+ source_digest: digestSchema,
214
+ report_digest: digestSchema,
215
+ status: readinessStatusSchema,
216
+ summary: z.strictObject({
217
+ stages: z.number().int().min(0),
218
+ required_stages: z.number().int().min(0),
219
+ passed_required_stages: z.number().int().min(0),
220
+ findings: z.number().int().min(0),
221
+ failed_findings: z.number().int().min(0),
222
+ unknown_findings: z.number().int().min(0),
223
+ }),
224
+ metrics: z.strictObject({
225
+ first_valid_workflow_selection_rate: z.number().min(0).max(1),
226
+ malformed_or_over_limit_call_rate: z.number().min(0).max(1),
227
+ incompatible_provider_invocations: z.number().int().min(0),
228
+ failed_calls_before_prerequisites: z.number().int().min(0),
229
+ recovery_rate: z.number().min(0).max(1),
230
+ divergence_localization_precision: z.number().min(0).max(1),
231
+ false_equivalence_count: z.number().int().min(0),
232
+ unowned_obligation_count: z.number().int().min(0),
233
+ cleanup_leak_count: z.number().int().min(0),
234
+ nondeterministic_replay_count: z.number().int().min(0),
235
+ }),
236
+ stages: z.array(stageSchema).max(20),
237
+ findings: z.array(findingSchema).max(10_000),
238
+ evidence_links: z.array(evidenceIdSchema).max(100_000),
239
+ snapshot: reconstructionReadinessInputSchema,
240
+ });