@stelis/say-ur-intent 0.0.0 → 0.0.2

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 (234) hide show
  1. package/README.md +4 -39
  2. package/dist/adapters/adapterLifecycleValidators.js +7 -0
  3. package/dist/adapters/adapterPromptSurfaces.js +71 -0
  4. package/dist/adapters/deepbook/deepbookHumanReviewProducer.js +175 -0
  5. package/dist/adapters/deepbook/deepbookQuotePolicy.js +112 -0
  6. package/dist/adapters/deepbook/deepbookReviewEvidence.js +507 -0
  7. package/dist/adapters/deepbook/deepbookReviewLifecycle.js +85 -0
  8. package/dist/adapters/deepbook/deepbookSwapIntent.js +79 -0
  9. package/dist/adapters/deepbook/deepbookTransactionMaterialProducer.js +269 -0
  10. package/dist/adapters/flowx/flowxSwapHumanReviewProducer.js +176 -0
  11. package/dist/adapters/flowx/flowxSwapIntent.js +79 -0
  12. package/dist/adapters/flowx/flowxSwapQuotePolicy.js +104 -0
  13. package/dist/adapters/flowx/flowxSwapReviewEvidence.js +468 -0
  14. package/dist/adapters/flowx/flowxSwapReviewLifecycle.js +85 -0
  15. package/dist/adapters/flowx/flowxSwapTransactionMaterialProducer.js +362 -0
  16. package/dist/adapters/intentPlanFactories.js +59 -0
  17. package/dist/adapters/reviewAdapters.js +81 -0
  18. package/dist/core/action/adapterLifecycleValidation.js +12 -0
  19. package/dist/core/action/forbiddenFields.js +43 -0
  20. package/dist/core/action/humanReadableReviewEvidence.js +203 -0
  21. package/dist/core/action/humanReadableReviewProjectionVerifier.js +29 -0
  22. package/dist/core/action/ptbVisualizationProducer.js +66 -0
  23. package/dist/core/action/reviewCheckResults.js +6 -0
  24. package/dist/core/action/reviewStateValidation.js +11 -0
  25. package/dist/core/action/reviewTimeSimulationEvidence.js +471 -0
  26. package/dist/core/action/schemas.js +529 -0
  27. package/dist/core/action/signableAdapterContract.js +993 -0
  28. package/dist/core/action/swapHumanReadableReviewProjection.js +124 -0
  29. package/dist/core/action/swapQuotePolicyEvidence.js +278 -0
  30. package/dist/core/action/transactionObjectOwnershipEvidence.js +247 -0
  31. package/dist/core/action/transactionObjectOwnershipProducer.js +329 -0
  32. package/dist/core/action/types.js +35 -0
  33. package/dist/core/action/walletReviewContractAssembler.js +282 -0
  34. package/dist/core/activity/activityStore.js +15 -0
  35. package/dist/core/activity/localDataService.js +258 -0
  36. package/dist/core/activity/localDataTypes.js +11 -0
  37. package/dist/core/activity/localDataValidation.js +396 -0
  38. package/dist/core/activity/schemaVersion.js +1 -0
  39. package/dist/core/activity/sqliteActivityStore.js +820 -0
  40. package/dist/core/activity/sqliteActivityStoreRows.js +430 -0
  41. package/dist/core/activity/sqliteActivityStoreSchema.js +258 -0
  42. package/dist/core/activity/sqliteActivityStoreTypes.js +5 -0
  43. package/dist/core/activity/suiFunctionTarget.js +43 -0
  44. package/dist/core/activity/transactionActivityAccountEffects.js +189 -0
  45. package/dist/core/activity/transactionActivityAnalysis.js +295 -0
  46. package/dist/core/activity/transactionActivityClassifier.js +306 -0
  47. package/dist/core/activity/transactionActivityDetails.js +229 -0
  48. package/dist/core/activity/transactionActivityProtocolRules.js +218 -0
  49. package/dist/core/activity/transactionActivityScanPolicy.js +170 -0
  50. package/dist/core/activity/transactionActivityService.js +379 -0
  51. package/dist/core/activity/transactionActivityTypes.js +18 -0
  52. package/dist/core/eventlog/sink.js +35 -0
  53. package/dist/core/evidence/settlementFamilies.js +87 -0
  54. package/dist/core/evidence/userAnswerUse.js +1 -0
  55. package/dist/core/numeric/rawU64.js +63 -0
  56. package/dist/core/preferences/preferencesStore.js +26 -0
  57. package/dist/core/preferences/sqlitePreferencesRepository.js +136 -0
  58. package/dist/core/proposal/externalProposalReview.js +347 -0
  59. package/dist/core/proposal/schemas.js +208 -0
  60. package/dist/core/proposal/types.js +35 -0
  61. package/dist/core/read/amounts.js +14 -0
  62. package/dist/core/read/coinMetadata.js +60 -0
  63. package/dist/core/read/deepbookRawQuoteClient.js +86 -0
  64. package/dist/core/read/deepbookReadHelpers.js +265 -0
  65. package/dist/core/read/deepbookRegistry.js +133 -0
  66. package/dist/core/read/flowxQuoteClient.js +117 -0
  67. package/dist/core/read/flowxReadHelpers.js +145 -0
  68. package/dist/core/read/flowxRegistry.js +174 -0
  69. package/dist/core/read/intentEvidenceResponseFormatting.js +228 -0
  70. package/dist/core/read/readResponseGuidance.js +451 -0
  71. package/dist/core/read/readService.js +1164 -0
  72. package/dist/core/read/readServiceTypes.js +59 -0
  73. package/dist/core/read/settlementParityFormatting.js +82 -0
  74. package/dist/core/read/walletReadHelpers.js +99 -0
  75. package/dist/core/review/reviewChecks.js +54 -0
  76. package/dist/core/review/reviewComputation.js +38 -0
  77. package/dist/core/review/reviewComputationResult.js +87 -0
  78. package/dist/core/session/localSession.js +31 -0
  79. package/dist/core/session/privateReviewArtifacts.js +73 -0
  80. package/dist/core/session/sessionErrors.js +9 -0
  81. package/dist/core/session/sessionStore.js +821 -0
  82. package/dist/core/session/settingsSession.js +1 -0
  83. package/dist/core/session/settingsSessions.js +43 -0
  84. package/dist/core/session/status.js +86 -0
  85. package/dist/core/session/transactionMaterialStore.js +205 -0
  86. package/dist/core/session/wait.js +102 -0
  87. package/dist/core/session/walletIdentity.js +103 -0
  88. package/dist/core/session/walletIdentitySessions.js +189 -0
  89. package/dist/core/suiAddress.js +18 -0
  90. package/dist/core/suiEndpoint.js +72 -0
  91. package/dist/mcp/activeAccountResponse.js +24 -0
  92. package/dist/mcp/prompts.js +146 -0
  93. package/dist/mcp/registerTool.js +19 -0
  94. package/dist/mcp/resources.js +72 -0
  95. package/dist/mcp/responseGuidance.js +381 -0
  96. package/dist/mcp/result.js +17 -0
  97. package/dist/mcp/schemas.js +8 -0
  98. package/dist/mcp/server.js +30 -0
  99. package/dist/mcp/serverInfo.js +123 -0
  100. package/dist/mcp/toolErrors.js +105 -0
  101. package/dist/mcp/toolNames.js +50 -0
  102. package/dist/mcp/tools/account/index.js +44 -0
  103. package/dist/mcp/tools/action/prepareSuiActionReview.js +120 -0
  104. package/dist/mcp/tools/read/commonSchemas.js +43 -0
  105. package/dist/mcp/tools/read/deepbookReadTools.js +453 -0
  106. package/dist/mcp/tools/read/flowxReadTools.js +135 -0
  107. package/dist/mcp/tools/read/index.js +16 -0
  108. package/dist/mcp/tools/read/readToolHelpers.js +68 -0
  109. package/dist/mcp/tools/read/reviewActivityTools.js +176 -0
  110. package/dist/mcp/tools/read/serverStatusTools.js +103 -0
  111. package/dist/mcp/tools/read/transactionActivityOutput.js +300 -0
  112. package/dist/mcp/tools/read/transactionActivityTools.js +544 -0
  113. package/dist/mcp/tools/read/walletReadTools.js +733 -0
  114. package/dist/mcp/tools/session/executionResultTools.js +92 -0
  115. package/dist/mcp/tools/session/index.js +8 -0
  116. package/dist/mcp/tools/session/shared.js +79 -0
  117. package/dist/mcp/tools/session/statusTools.js +134 -0
  118. package/dist/mcp/tools/session/walletIdentityTools.js +119 -0
  119. package/dist/mcp/tools/settings/index.js +64 -0
  120. package/dist/review-app/analysis.css +1 -0
  121. package/dist/review-app/analysis.js +1 -0
  122. package/dist/review-app/arc-BjIacwQm.js +1 -0
  123. package/dist/review-app/architecture-U656AL7Q-aSB9x1OK.js +1 -0
  124. package/dist/review-app/architectureDiagram-VXUJARFQ-C5W6re2I.js +36 -0
  125. package/dist/review-app/array-BmXUUrU6.js +1 -0
  126. package/dist/review-app/blockDiagram-VD42YOAC-20MLNcUm.js +122 -0
  127. package/dist/review-app/c4Diagram-YG6GDRKO-BZXRrcck.js +10 -0
  128. package/dist/review-app/channel-lk2p_CUu.js +1 -0
  129. package/dist/review-app/chunk-4BX2VUAB-BPITOdjX.js +1 -0
  130. package/dist/review-app/chunk-55IACEB6-Dz-pyw5k.js +1 -0
  131. package/dist/review-app/chunk-76Q3JFCE-cK_X1P_l.js +1 -0
  132. package/dist/review-app/chunk-ABZYJK2D-Dt4W53JI.js +81 -0
  133. package/dist/review-app/chunk-ATLVNIR6-fZHLXURb.js +1 -0
  134. package/dist/review-app/chunk-B4BG7PRW-BbgcjusC.js +165 -0
  135. package/dist/review-app/chunk-BJD4TVEz.js +1 -0
  136. package/dist/review-app/chunk-CVBHYZKI-CViawAKX.js +1 -0
  137. package/dist/review-app/chunk-DI55MBZ5-C5aoul-d.js +220 -0
  138. package/dist/review-app/chunk-FMBD7UC4-Chxmw62A.js +15 -0
  139. package/dist/review-app/chunk-FPAJGGOC-DDHjQ09H.js +80 -0
  140. package/dist/review-app/chunk-FWNWRKHM-CVVQUptk.js +1 -0
  141. package/dist/review-app/chunk-HN2XXSSU-yzNpjaSZ.js +1 -0
  142. package/dist/review-app/chunk-JA3XYJ7Z-C5ZJdU01.js +70 -0
  143. package/dist/review-app/chunk-JZLCHNYA-BBST4Cnk.js +54 -0
  144. package/dist/review-app/chunk-LBM3YZW2-CdwAPuHr.js +1 -0
  145. package/dist/review-app/chunk-LHMN2FUI-BtB5uDcp.js +1 -0
  146. package/dist/review-app/chunk-O7ZBX7Z2-pxdK4Sa3.js +1 -0
  147. package/dist/review-app/chunk-QN33PNHL-CbVv3uGK.js +1 -0
  148. package/dist/review-app/chunk-QXUST7PY-DKM2-t2c.js +7 -0
  149. package/dist/review-app/chunk-QZHKN3VN-C5ni2pN_.js +1 -0
  150. package/dist/review-app/chunk-S3R3BYOJ-BWvOhDs0.js +2 -0
  151. package/dist/review-app/chunk-S6J4BHB3-D9Fk0YeD.js +1 -0
  152. package/dist/review-app/chunk-T53DSG4Q-C1qEyzyV.js +1 -0
  153. package/dist/review-app/chunk-TZMSLE5B-B--7eU69.js +1 -0
  154. package/dist/review-app/classDiagram-2ON5EDUG-DlL1m2bp.js +1 -0
  155. package/dist/review-app/classDiagram-v2-WZHVMYZB-FXRskT1j.js +1 -0
  156. package/dist/review-app/clone-BZZb7gpZ.js +1 -0
  157. package/dist/review-app/cose-bilkent-S5V4N54A-CRIb8XEO.js +1 -0
  158. package/dist/review-app/cytoscape.esm-C7jYqDP5.js +321 -0
  159. package/dist/review-app/dagre-6UL2VRFP-FNCAXbdE.js +4 -0
  160. package/dist/review-app/dagre-Be46QtUd.js +1 -0
  161. package/dist/review-app/defaultLocale-BaWNtAUL.js +1 -0
  162. package/dist/review-app/diagram-PSM6KHXK-ylLWjiNM.js +24 -0
  163. package/dist/review-app/diagram-QEK2KX5R-BCDcESxs.js +43 -0
  164. package/dist/review-app/diagram-S2PKOQOG-Vdrc-vrO.js +24 -0
  165. package/dist/review-app/dist-WPc74x_f.js +1 -0
  166. package/dist/review-app/erDiagram-Q2GNP2WA-E5ZsUbDF.js +60 -0
  167. package/dist/review-app/flatten-DHf9IeNI.js +1 -0
  168. package/dist/review-app/flowDiagram-NV44I4VS-DBSQuj6x.js +162 -0
  169. package/dist/review-app/ganttDiagram-LVOFAZNH-CKUOsqwl.js +267 -0
  170. package/dist/review-app/gitGraph-F6HP7TQM-DsAD6qK1.js +1 -0
  171. package/dist/review-app/gitGraphDiagram-NY62KEGX-BCeIMWdl.js +65 -0
  172. package/dist/review-app/graphlib-CiX5CXxR.js +1 -0
  173. package/dist/review-app/http-DMvwuuFk.js +1 -0
  174. package/dist/review-app/identity-DY8PXc6t.js +1 -0
  175. package/dist/review-app/info-NVLQJR56-Dlx1nZic.js +1 -0
  176. package/dist/review-app/infoDiagram-F6ZHWCRC-CAuANIrz.js +2 -0
  177. package/dist/review-app/init-BvqephKz.js +1 -0
  178. package/dist/review-app/journeyDiagram-XKPGCS4Q-C-Z9phnx.js +139 -0
  179. package/dist/review-app/kanban-definition-3W4ZIXB7-DufgZABq.js +89 -0
  180. package/dist/review-app/katex-B-Z-NXXN.js +257 -0
  181. package/dist/review-app/line-DiIv3Jgw.js +1 -0
  182. package/dist/review-app/linear-Cv-UPvo1.js +1 -0
  183. package/dist/review-app/math-kmyYrkHL.js +1 -0
  184. package/dist/review-app/mermaid-parser.core-DkwUYTPl.js +4 -0
  185. package/dist/review-app/mindmap-definition-VGOIOE7T-TM_CqdmV.js +68 -0
  186. package/dist/review-app/ordinal-BliTlkoG.js +1 -0
  187. package/dist/review-app/packet-BFZMPI3H-DqbnU92v.js +1 -0
  188. package/dist/review-app/path-AEo9W6mQ.js +1 -0
  189. package/dist/review-app/pie-7BOR55EZ-LJzaLkgr.js +1 -0
  190. package/dist/review-app/pieDiagram-ADFJNKIX-BAs8OfRS.js +30 -0
  191. package/dist/review-app/quadrantDiagram-AYHSOK5B-CyUDZP5S.js +7 -0
  192. package/dist/review-app/radar-NHE76QYJ-DBpHc8_Y.js +1 -0
  193. package/dist/review-app/reduce-B-HuPpdd.js +1 -0
  194. package/dist/review-app/requirementDiagram-UZGBJVZJ-BEHix78P.js +64 -0
  195. package/dist/review-app/review.css +1 -0
  196. package/dist/review-app/review.js +43 -0
  197. package/dist/review-app/sankeyDiagram-TZEHDZUN-B2bKbmsm.js +10 -0
  198. package/dist/review-app/sequenceDiagram-WL72ISMW-DVLOORFJ.js +145 -0
  199. package/dist/review-app/settings.css +1 -0
  200. package/dist/review-app/settings.js +1 -0
  201. package/dist/review-app/src-Buml7cM5.js +1 -0
  202. package/dist/review-app/stateDiagram-FKZM4ZOC-sFGGp2kV.js +1 -0
  203. package/dist/review-app/stateDiagram-v2-4FDKWEC3-BHfCF4dX.js +1 -0
  204. package/dist/review-app/timeline-definition-IT6M3QCI-BESnBijC.js +61 -0
  205. package/dist/review-app/treemap-KMMF4GRG-wnVLBDeQ.js +1 -0
  206. package/dist/review-app/walletStatus-CcojOdGy.js +7 -0
  207. package/dist/review-app/xychartDiagram-PRI3JC2R-BGWVfCx4.js +7 -0
  208. package/dist/review-server/assets.js +48 -0
  209. package/dist/review-server/html.js +66 -0
  210. package/dist/review-server/http.js +47 -0
  211. package/dist/review-server/middleware/hostOrigin.js +48 -0
  212. package/dist/review-server/middleware/reviewToken.js +7 -0
  213. package/dist/review-server/reviewServerPolicy.js +10 -0
  214. package/dist/review-server/server.js +568 -0
  215. package/dist/review-server/settingsApi.js +182 -0
  216. package/dist/review-server/walletIdentityResponse.js +13 -0
  217. package/dist/runtime/config.js +103 -0
  218. package/dist/runtime/localSettingsService.js +198 -0
  219. package/dist/runtime/logger.js +50 -0
  220. package/dist/runtime/reviewServerAcquire.js +128 -0
  221. package/dist/runtime/smokeMainnetRead.js +529 -0
  222. package/dist/runtime/smokeMainnetReadAssertions.js +308 -0
  223. package/dist/runtime/start.js +295 -0
  224. package/dist/runtime/suiEndpoint.js +97 -0
  225. package/dist/runtime/suiTransactionGraphqlMapping.js +200 -0
  226. package/dist/runtime/suiTransactionGraphqlQueries.js +231 -0
  227. package/dist/runtime/suiTransactionGraphqlSource.js +148 -0
  228. package/docs/AGENT_BEHAVIOR.md +1 -1
  229. package/docs/AGENT_DEVELOPMENT_POLICY.md +20 -0
  230. package/docs/FRONTEND_POLICY.md +4 -3
  231. package/docs/MCP_SETUP.md +59 -7
  232. package/docs/MCP_TOOLS.md +1 -1
  233. package/docs/SDK_API.md +5 -1
  234. package/package.json +3 -2
@@ -0,0 +1,203 @@
1
+ import { z } from "zod";
2
+ import { assertNoForbiddenMcpFields } from "./forbiddenFields.js";
3
+ import { WALLET_REVIEW_REQUIRED_HUMAN_FIELDS, adapterHumanReadableReviewSchema } from "./signableAdapterContract.js";
4
+ import { humanReadableReviewSummarySchema } from "./schemas.js";
5
+ import { normalizedSuiAddressSchema, parseSuiAddress, suiTransactionDigestSchema } from "../suiAddress.js";
6
+ export const HUMAN_READABLE_REVIEW_EVIDENCE_VERSION = "human-readable-review-v1";
7
+ const isoUtcStringSchema = z.string().refine((value) => {
8
+ const parsed = new Date(value);
9
+ return Number.isFinite(parsed.getTime()) && parsed.toISOString() === value;
10
+ }, "Expected ISO 8601 UTC timestamp");
11
+ export const humanReadableReviewEvidenceSchema = z.object({
12
+ evidenceVersion: z.literal(HUMAN_READABLE_REVIEW_EVIDENCE_VERSION),
13
+ materialId: z.string().min(1),
14
+ reviewSessionId: z.string().min(1),
15
+ planId: z.string().min(1),
16
+ account: normalizedSuiAddressSchema,
17
+ transactionDigest: suiTransactionDigestSchema,
18
+ kind: z.literal("human_readable_review"),
19
+ adapterId: z.string().min(1).max(120),
20
+ protocol: z.string().min(1).max(120),
21
+ actionKind: z.string().min(1).max(120),
22
+ network: z.literal("sui:mainnet"),
23
+ fields: z.array(z.enum(WALLET_REVIEW_REQUIRED_HUMAN_FIELDS)).min(WALLET_REVIEW_REQUIRED_HUMAN_FIELDS.length),
24
+ boundToCommitment: suiTransactionDigestSchema,
25
+ source: z.literal("review_model_or_adapter_equivalent"),
26
+ purpose: z.literal("human_review_before_wallet_authorization"),
27
+ review: humanReadableReviewSummarySchema,
28
+ derivedAt: isoUtcStringSchema,
29
+ expiresAt: isoUtcStringSchema
30
+ }).strict().superRefine((value, ctx) => {
31
+ const duplicateField = findDuplicate(value.fields);
32
+ if (duplicateField) {
33
+ ctx.addIssue({
34
+ code: "custom",
35
+ path: ["fields"],
36
+ message: `Human-readable review fields contains duplicate field '${duplicateField}'`
37
+ });
38
+ }
39
+ if (!WALLET_REVIEW_REQUIRED_HUMAN_FIELDS.every((field) => value.fields.includes(field))) {
40
+ ctx.addIssue({
41
+ code: "custom",
42
+ path: ["fields"],
43
+ message: "Human-readable review fields must include every required review field"
44
+ });
45
+ }
46
+ if (value.boundToCommitment !== value.transactionDigest) {
47
+ ctx.addIssue({
48
+ code: "custom",
49
+ path: ["boundToCommitment"],
50
+ message: "boundToCommitment must equal transactionDigest"
51
+ });
52
+ }
53
+ if (value.review.freshness.evaluatedAt !== value.derivedAt ||
54
+ value.review.freshness.expiresAt !== value.expiresAt) {
55
+ ctx.addIssue({
56
+ code: "custom",
57
+ path: ["review", "freshness"],
58
+ message: "review freshness must match evidence derivedAt and expiresAt"
59
+ });
60
+ }
61
+ if (value.review.proposedAction.adapterId !== value.adapterId ||
62
+ value.review.proposedAction.protocol !== value.protocol ||
63
+ value.review.proposedAction.actionKind !== value.actionKind) {
64
+ ctx.addIssue({
65
+ code: "custom",
66
+ path: ["review", "proposedAction"],
67
+ message: "review proposedAction must match the human-readable review evidence identity"
68
+ });
69
+ }
70
+ });
71
+ export function parseHumanReadableReviewEvidence(value) {
72
+ return humanReadableReviewEvidenceSchema.parse(value);
73
+ }
74
+ export function createHumanReadableReviewEvidence(input) {
75
+ return verifyHumanReadableReviewEvidence({
76
+ transactionMaterial: input.transactionMaterial,
77
+ transactionMaterialDigest: input.transactionMaterialDigest,
78
+ evidence: {
79
+ evidenceVersion: HUMAN_READABLE_REVIEW_EVIDENCE_VERSION,
80
+ materialId: input.transactionMaterial.materialId,
81
+ reviewSessionId: input.transactionMaterial.reviewSessionId,
82
+ planId: input.transactionMaterial.planId,
83
+ account: input.transactionMaterial.account,
84
+ transactionDigest: input.transactionMaterialDigest.transactionDigest,
85
+ kind: "human_readable_review",
86
+ adapterId: input.adapterId,
87
+ protocol: input.protocol,
88
+ actionKind: input.actionKind,
89
+ network: "sui:mainnet",
90
+ fields: [...WALLET_REVIEW_REQUIRED_HUMAN_FIELDS],
91
+ boundToCommitment: input.transactionMaterialDigest.transactionDigest,
92
+ source: "review_model_or_adapter_equivalent",
93
+ purpose: "human_review_before_wallet_authorization",
94
+ review: input.review,
95
+ derivedAt: input.derivedAt.toISOString(),
96
+ expiresAt: input.transactionMaterial.expiresAt
97
+ },
98
+ now: input.derivedAt
99
+ });
100
+ }
101
+ export function verifyHumanReadableReviewEvidence(input) {
102
+ const evidence = parseHumanReadableReviewEvidence(input.evidence);
103
+ const now = input.now ?? new Date();
104
+ const nowMs = now.getTime();
105
+ if (!Number.isFinite(nowMs)) {
106
+ throw new Error("now must be a valid Date");
107
+ }
108
+ if (evidence.materialId !== input.transactionMaterial.materialId ||
109
+ evidence.reviewSessionId !== input.transactionMaterial.reviewSessionId ||
110
+ evidence.planId !== input.transactionMaterial.planId ||
111
+ evidence.account !== input.transactionMaterial.account ||
112
+ evidence.expiresAt !== input.transactionMaterial.expiresAt ||
113
+ evidence.transactionDigest !== input.transactionMaterialDigest.transactionDigest ||
114
+ evidence.boundToCommitment !== input.transactionMaterialDigest.transactionDigest) {
115
+ throw new Error("human-readable review evidence must match material and digest identity");
116
+ }
117
+ if (input.transactionMaterialDigest.materialId !== input.transactionMaterial.materialId ||
118
+ input.transactionMaterialDigest.reviewSessionId !== input.transactionMaterial.reviewSessionId ||
119
+ input.transactionMaterialDigest.planId !== input.transactionMaterial.planId ||
120
+ input.transactionMaterialDigest.account !== input.transactionMaterial.account ||
121
+ input.transactionMaterialDigest.expiresAt !== input.transactionMaterial.expiresAt) {
122
+ throw new Error("transaction material digest must match material identity before human review evidence is accepted");
123
+ }
124
+ assertHumanReadableReviewConnectedAccount(evidence);
125
+ assertHumanReadableReviewEvidenceSources(evidence);
126
+ const materialCreatedAtMs = Date.parse(input.transactionMaterial.createdAt);
127
+ const derivedAtMs = Date.parse(evidence.derivedAt);
128
+ const expiresAtMs = Date.parse(evidence.expiresAt);
129
+ if (derivedAtMs < materialCreatedAtMs || derivedAtMs > nowMs || derivedAtMs >= expiresAtMs) {
130
+ throw new Error("human-readable review derivedAt must be between material creation, now, and material expiry");
131
+ }
132
+ if (expiresAtMs <= nowMs) {
133
+ throw new Error("human-readable review evidence must not be expired");
134
+ }
135
+ adapterHumanReadableReviewSchema.parse({
136
+ fields: evidence.fields,
137
+ boundToCommitment: evidence.boundToCommitment,
138
+ source: evidence.source,
139
+ purpose: evidence.purpose
140
+ });
141
+ assertNoForbiddenMcpFields(evidence.review);
142
+ return evidence;
143
+ }
144
+ export function publicHumanReadableReviewFromEvidence(evidenceInput) {
145
+ const evidence = parseHumanReadableReviewEvidence(evidenceInput);
146
+ assertNoForbiddenMcpFields(evidence.review);
147
+ return humanReadableReviewSummarySchema.parse(structuredClone(evidence.review));
148
+ }
149
+ function findDuplicate(values) {
150
+ const seen = new Set();
151
+ for (const value of values) {
152
+ if (seen.has(value)) {
153
+ return value;
154
+ }
155
+ seen.add(value);
156
+ }
157
+ return undefined;
158
+ }
159
+ function assertHumanReadableReviewConnectedAccount(evidence) {
160
+ const recipientsByRole = new Map();
161
+ for (const recipient of evidence.review.recipients) {
162
+ if (recipientsByRole.has(recipient.role)) {
163
+ throw new Error(`human-readable review recipients contains duplicate role '${recipient.role}'`);
164
+ }
165
+ const normalizedAddress = parseSuiAddress(recipient.address);
166
+ if (!normalizedAddress) {
167
+ throw new Error("human-readable review recipients must contain valid Sui addresses");
168
+ }
169
+ recipientsByRole.set(recipient.role, normalizedAddress);
170
+ }
171
+ if (recipientsByRole.get("connected_account") !== evidence.account) {
172
+ throw new Error("human-readable review connected account recipient must match the reviewed account");
173
+ }
174
+ }
175
+ export function assertPreSimulationHumanReadableReviewBoundaryClaims(evidence) {
176
+ requireGapId("missingEvidence", evidence.review.missingEvidence, "review_time_simulation");
177
+ requireGapId("requiredUserChoices", evidence.review.requiredUserChoices, "wallet_authorization_later");
178
+ for (const id of [
179
+ "no_signing_readiness",
180
+ "no_execution_readiness"
181
+ ]) {
182
+ requireGapId("unsupportedClaims", evidence.review.unsupportedClaims, id);
183
+ }
184
+ if (!evidence.review.blockingChecks.some((check) => check.source === "simulation" &&
185
+ check.status === "fail")) {
186
+ throw new Error("human-readable review blockingChecks must include a failed simulation check");
187
+ }
188
+ }
189
+ function assertHumanReadableReviewEvidenceSources(evidence) {
190
+ for (const source of ["digest_commitment"]) {
191
+ requireFactSource(evidence.review.evidenceUsed, source);
192
+ }
193
+ }
194
+ function requireFactSource(facts, source) {
195
+ if (!facts.some((fact) => fact.source === source)) {
196
+ throw new Error(`human-readable review evidenceUsed must include source '${source}'`);
197
+ }
198
+ }
199
+ function requireGapId(label, gaps, id) {
200
+ if (!gaps.some((gap) => gap.id === id)) {
201
+ throw new Error(`human-readable review ${label} must include '${id}'`);
202
+ }
203
+ }
@@ -0,0 +1,29 @@
1
+ import { verifyHumanReadableReviewEvidence } from "./humanReadableReviewEvidence.js";
2
+ import { verifySwapHumanReadableReviewEvidence } from "./swapHumanReadableReviewProjection.js";
3
+ export function verifySupportedHumanReadableReviewEvidence(input) {
4
+ const evidence = verifyHumanReadableReviewEvidence({
5
+ transactionMaterial: input.transactionMaterial,
6
+ transactionMaterialDigest: input.transactionMaterialDigest,
7
+ evidence: input.evidence,
8
+ now: input.now
9
+ });
10
+ switch (evidence.review.kind) {
11
+ case "swap_human_readable_review":
12
+ return verifySwapHumanReadableReviewEvidence({
13
+ transactionMaterial: input.transactionMaterial,
14
+ transactionMaterialDigest: input.transactionMaterialDigest,
15
+ swapQuotePolicy: requireProjectionArtifact(input.swapQuotePolicy, "swap human-readable review evidence requires swap quote policy evidence"),
16
+ transactionObjectOwnership: requireProjectionArtifact(input.transactionObjectOwnership, "swap human-readable review evidence requires transaction object ownership evidence"),
17
+ evidence,
18
+ now: input.now
19
+ });
20
+ }
21
+ const unsupportedKind = evidence.review.kind;
22
+ throw new Error(`unsupported human-readable review projection kind: ${String(unsupportedKind)}`);
23
+ }
24
+ function requireProjectionArtifact(value, message) {
25
+ if (value === undefined) {
26
+ throw new Error(message);
27
+ }
28
+ return value;
29
+ }
@@ -0,0 +1,66 @@
1
+ import { Transaction } from "@mysten/sui/transactions";
2
+ import { rawTransactionToIR, transactionIRToMermaid } from "@zktx.io/ptb-model";
3
+ import { PTB_VISUALIZATION_CONTRACT_VERSION, PTB_VISUALIZATION_REQUIRED_UNSUPPORTED_USES, ptbVisualizationArtifactSchema } from "./signableAdapterContract.js";
4
+ export const PTB_VISUALIZATION_RENDERER = {
5
+ name: "transactionIRToMermaid",
6
+ packageName: "@zktx.io/ptb-model",
7
+ version: "0.5.0"
8
+ };
9
+ export async function producePtbVisualizationArtifact(input) {
10
+ const material = input.materialStore.getTransactionMaterial(input.transactionMaterial, input.now);
11
+ if (!material) {
12
+ return { status: "declined", reason: "transaction material is unavailable for visualization" };
13
+ }
14
+ let mermaidText;
15
+ try {
16
+ const transaction = Transaction.from(material.transactionBytes);
17
+ const recomputedDigest = await transaction.getDigest();
18
+ if (recomputedDigest !== input.transactionMaterialDigest.transactionDigest) {
19
+ return {
20
+ status: "declined",
21
+ reason: "stored transaction bytes do not match the bound transaction material commitment"
22
+ };
23
+ }
24
+ const data = transaction.getData();
25
+ const ir = rawTransactionToIR({ inputs: data.inputs, commands: data.commands });
26
+ mermaidText = transactionIRToMermaid(ir, { direction: "LR" });
27
+ }
28
+ catch (error) {
29
+ return {
30
+ status: "declined",
31
+ reason: `ptb renderer failed: ${error instanceof Error ? error.message : String(error)}`
32
+ };
33
+ }
34
+ const candidate = {
35
+ contractVersion: PTB_VISUALIZATION_CONTRACT_VERSION,
36
+ artifactKind: "ptb_visualization",
37
+ generatedAt: input.now.toISOString(),
38
+ source: {
39
+ adapterId: input.adapterId,
40
+ ...(input.planId !== undefined ? { planId: input.planId } : {}),
41
+ sourceKind: "review_time_generated_transaction_kind",
42
+ authority: "visualization_only_not_wallet_authorization",
43
+ renderer: PTB_VISUALIZATION_RENDERER
44
+ },
45
+ mermaid: {
46
+ diagramType: "flowchart",
47
+ text: mermaidText
48
+ },
49
+ diagnostics: [],
50
+ unsupportedUse: [...PTB_VISUALIZATION_REQUIRED_UNSUPPORTED_USES],
51
+ executableMaterial: {
52
+ included: false,
53
+ policy: "mcp_and_review_ui_outputs_must_not_include_executable_transaction_material"
54
+ }
55
+ };
56
+ const parsed = ptbVisualizationArtifactSchema.safeParse(candidate);
57
+ if (!parsed.success) {
58
+ const issue = parsed.error.issues[0];
59
+ const path = issue?.path.join(".") ?? "";
60
+ return {
61
+ status: "declined",
62
+ reason: `ptb visualization artifact rejected: ${path ? `${path}: ` : ""}${issue?.message ?? "unknown issue"}`
63
+ };
64
+ }
65
+ return { status: "rendered", artifact: parsed.data };
66
+ }
@@ -0,0 +1,6 @@
1
+ export function passReviewCheck(id, label, message, source) {
2
+ return { id, label, status: "pass", message, source };
3
+ }
4
+ export function failReviewCheck(id, label, message, source) {
5
+ return { id, label, status: "fail", message, source };
6
+ }
@@ -0,0 +1,11 @@
1
+ import { reviewStateStructuralInvariantSchema } from "./schemas.js";
2
+ export function parseReviewStateStructuralInvariants(input) {
3
+ return reviewStateStructuralInvariantSchema.parse(input);
4
+ }
5
+ export function parseLifecycleValidatedReviewState(input, validateAdapterLifecycle) {
6
+ const parsed = parseReviewStateStructuralInvariants(input);
7
+ if (parsed.adapterLifecycle) {
8
+ validateAdapterLifecycle(parsed.adapterLifecycle);
9
+ }
10
+ return parsed;
11
+ }