@crediolabs/policy-synth 0.2.0 → 0.3.1

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 (249) hide show
  1. package/README.md +4 -4
  2. package/dist/adapters/interpreter/adapter.d.ts +19 -25
  3. package/dist/adapters/interpreter/adapter.js +54 -487
  4. package/dist/errors.d.ts +1 -1
  5. package/dist/index.d.ts +1 -4
  6. package/dist/index.js +1 -4
  7. package/dist/install/build-add-context-rule.d.ts +3 -19
  8. package/dist/install/build-add-context-rule.js +3 -98
  9. package/dist/install/build-install-policy.d.ts +4 -53
  10. package/dist/install/build-install-policy.js +44 -123
  11. package/dist/install/index.d.ts +0 -2
  12. package/dist/install/index.js +0 -7
  13. package/dist/predicate/decode.d.ts +1 -1
  14. package/dist/predicate/decode.js +2 -70
  15. package/dist/predicate/encode.js +45 -229
  16. package/dist/predicate/from-json.js +1 -42
  17. package/dist/record/decode.js +3 -8
  18. package/dist/record/freshness.d.ts +17 -11
  19. package/dist/record/freshness.js +28 -18
  20. package/dist/review-card/builder.d.ts +4 -3
  21. package/dist/review-card/builder.js +18 -162
  22. package/dist/review-card/cross-check.js +2 -105
  23. package/dist/review-card/render-leaf.d.ts +4 -0
  24. package/dist/review-card/render-leaf.js +47 -0
  25. package/dist/run/index.d.ts +36 -139
  26. package/dist/run/index.js +125 -437
  27. package/dist/run/schemas.d.ts +168 -1929
  28. package/dist/run/schemas.js +40 -269
  29. package/dist/{synth → simulate}/deny-cases.d.ts +4 -8
  30. package/dist/simulate/deny-cases.js +282 -0
  31. package/dist/simulate/evaluate.d.ts +18 -0
  32. package/dist/simulate/evaluate.js +271 -0
  33. package/dist/simulate/index.d.ts +4 -0
  34. package/dist/simulate/index.js +8 -0
  35. package/dist/synth/compose-from-recording.d.ts +24 -51
  36. package/dist/synth/compose-from-recording.js +120 -282
  37. package/dist/synth/index.d.ts +0 -5
  38. package/dist/synth/index.js +0 -5
  39. package/dist/synth/synthesize-from-recording.d.ts +1 -29
  40. package/dist/synth/synthesize-from-recording.js +41 -356
  41. package/dist/types.d.ts +8 -60
  42. package/dist/types.js +5 -2
  43. package/dist-cjs/adapters/interpreter/adapter.d.ts +19 -25
  44. package/dist-cjs/adapters/interpreter/adapter.js +56 -489
  45. package/dist-cjs/errors.d.ts +1 -1
  46. package/dist-cjs/index.d.ts +1 -4
  47. package/dist-cjs/index.js +1 -4
  48. package/dist-cjs/install/build-add-context-rule.d.ts +3 -19
  49. package/dist-cjs/install/build-add-context-rule.js +1 -97
  50. package/dist-cjs/install/build-install-policy.d.ts +4 -53
  51. package/dist-cjs/install/build-install-policy.js +44 -122
  52. package/dist-cjs/install/index.d.ts +0 -2
  53. package/dist-cjs/install/index.js +2 -23
  54. package/dist-cjs/predicate/decode.d.ts +1 -1
  55. package/dist-cjs/predicate/decode.js +2 -70
  56. package/dist-cjs/predicate/encode.js +45 -229
  57. package/dist-cjs/predicate/from-json.js +1 -42
  58. package/dist-cjs/record/decode.js +3 -8
  59. package/dist-cjs/record/freshness.d.ts +17 -11
  60. package/dist-cjs/record/freshness.js +28 -18
  61. package/dist-cjs/review-card/builder.d.ts +4 -3
  62. package/dist-cjs/review-card/builder.js +23 -167
  63. package/dist-cjs/review-card/cross-check.js +7 -110
  64. package/dist-cjs/review-card/render-leaf.d.ts +4 -0
  65. package/dist-cjs/review-card/render-leaf.js +52 -0
  66. package/dist-cjs/run/index.d.ts +36 -139
  67. package/dist-cjs/run/index.js +125 -444
  68. package/dist-cjs/run/schemas.d.ts +168 -1929
  69. package/dist-cjs/run/schemas.js +41 -270
  70. package/dist-cjs/{synth → simulate}/deny-cases.d.ts +4 -8
  71. package/dist-cjs/simulate/deny-cases.js +286 -0
  72. package/dist-cjs/simulate/evaluate.d.ts +18 -0
  73. package/dist-cjs/simulate/evaluate.js +274 -0
  74. package/dist-cjs/simulate/index.d.ts +4 -0
  75. package/dist-cjs/simulate/index.js +13 -0
  76. package/dist-cjs/synth/compose-from-recording.d.ts +24 -51
  77. package/dist-cjs/synth/compose-from-recording.js +120 -282
  78. package/dist-cjs/synth/index.d.ts +0 -5
  79. package/dist-cjs/synth/index.js +1 -11
  80. package/dist-cjs/synth/synthesize-from-recording.d.ts +1 -29
  81. package/dist-cjs/synth/synthesize-from-recording.js +39 -354
  82. package/dist-cjs/types.d.ts +8 -60
  83. package/dist-cjs/types.js +6 -3
  84. package/package.json +5 -5
  85. package/src/adapters/interpreter/adapter.ts +76 -572
  86. package/src/errors.ts +0 -19
  87. package/src/index.ts +1 -4
  88. package/src/install/build-add-context-rule.ts +5 -139
  89. package/src/install/build-install-policy.ts +93 -214
  90. package/src/install/index.ts +0 -34
  91. package/src/predicate/decode.ts +2 -70
  92. package/src/predicate/encode.ts +49 -261
  93. package/src/predicate/from-json.ts +1 -43
  94. package/src/record/decode.ts +3 -8
  95. package/src/record/freshness.ts +29 -18
  96. package/src/review-card/builder.ts +19 -168
  97. package/src/review-card/cross-check.ts +3 -105
  98. package/src/review-card/render-leaf.ts +48 -0
  99. package/src/run/index.ts +144 -572
  100. package/src/run/schemas.ts +42 -291
  101. package/src/simulate/deny-cases.ts +334 -0
  102. package/src/simulate/evaluate.ts +284 -0
  103. package/src/simulate/index.ts +11 -0
  104. package/src/synth/compose-from-recording.ts +148 -347
  105. package/src/synth/index.ts +0 -13
  106. package/src/synth/synthesize-from-recording.ts +43 -456
  107. package/src/types.ts +13 -49
  108. package/dist/adapters/interpreter/index.d.ts +0 -1
  109. package/dist/adapters/interpreter/index.js +0 -2
  110. package/dist/adapters/oz/adapter.d.ts +0 -20
  111. package/dist/adapters/oz/adapter.js +0 -295
  112. package/dist/adapters/oz/index.d.ts +0 -1
  113. package/dist/adapters/oz/index.js +0 -2
  114. package/dist/codegen/compile-gate.d.ts +0 -33
  115. package/dist/codegen/compile-gate.js +0 -124
  116. package/dist/codegen/index.d.ts +0 -2
  117. package/dist/codegen/index.js +0 -8
  118. package/dist/codegen/template.d.ts +0 -18
  119. package/dist/codegen/template.js +0 -148
  120. package/dist/install/authority-overlap.d.ts +0 -134
  121. package/dist/install/authority-overlap.js +0 -0
  122. package/dist/install/build-install-predicate.d.ts +0 -96
  123. package/dist/install/build-install-predicate.js +0 -444
  124. package/dist/install/build-merge-policy.d.ts +0 -70
  125. package/dist/install/build-merge-policy.js +0 -130
  126. package/dist/install/plan-merge-policy.d.ts +0 -49
  127. package/dist/install/plan-merge-policy.js +0 -86
  128. package/dist/install/read-account-rules.d.ts +0 -100
  129. package/dist/install/read-account-rules.js +0 -283
  130. package/dist/ir/index.d.ts +0 -1
  131. package/dist/ir/index.js +0 -2
  132. package/dist/ir/types.d.ts +0 -140
  133. package/dist/ir/types.js +0 -11
  134. package/dist/mandate/index.d.ts +0 -2
  135. package/dist/mandate/index.js +0 -2
  136. package/dist/mandate/to-ir.d.ts +0 -3
  137. package/dist/mandate/to-ir.js +0 -60
  138. package/dist/mandate/types.d.ts +0 -20
  139. package/dist/mandate/types.js +0 -8
  140. package/dist/seams/index.d.ts +0 -1
  141. package/dist/seams/index.js +0 -2
  142. package/dist/seams/types.d.ts +0 -66
  143. package/dist/seams/types.js +0 -11
  144. package/dist/synth/deny-cases.js +0 -562
  145. package/dist/synth/evaluate.d.ts +0 -39
  146. package/dist/synth/evaluate.js +0 -551
  147. package/dist/synth/harness.d.ts +0 -28
  148. package/dist/synth/harness.js +0 -47
  149. package/dist/synth/minimize.d.ts +0 -4
  150. package/dist/synth/minimize.js +0 -38
  151. package/dist/synth/permit-context.d.ts +0 -15
  152. package/dist/synth/permit-context.js +0 -116
  153. package/dist/synth/predicate-literals.d.ts +0 -5
  154. package/dist/synth/predicate-literals.js +0 -25
  155. package/dist/synth/synthesize-from-mandate.d.ts +0 -20
  156. package/dist/synth/synthesize-from-mandate.js +0 -59
  157. package/dist/verify/envelope.d.ts +0 -15
  158. package/dist/verify/envelope.js +0 -22
  159. package/dist/verify/index.d.ts +0 -3
  160. package/dist/verify/index.js +0 -3
  161. package/dist/verify/simulate.d.ts +0 -31
  162. package/dist/verify/simulate.js +0 -258
  163. package/dist/verify/verify.d.ts +0 -21
  164. package/dist/verify/verify.js +0 -189
  165. package/dist-cjs/adapters/interpreter/index.d.ts +0 -1
  166. package/dist-cjs/adapters/interpreter/index.js +0 -8
  167. package/dist-cjs/adapters/oz/adapter.d.ts +0 -20
  168. package/dist-cjs/adapters/oz/adapter.js +0 -300
  169. package/dist-cjs/adapters/oz/index.d.ts +0 -1
  170. package/dist-cjs/adapters/oz/index.js +0 -8
  171. package/dist-cjs/codegen/compile-gate.d.ts +0 -33
  172. package/dist-cjs/codegen/compile-gate.js +0 -128
  173. package/dist-cjs/codegen/index.d.ts +0 -2
  174. package/dist-cjs/codegen/index.js +0 -14
  175. package/dist-cjs/codegen/template.d.ts +0 -18
  176. package/dist-cjs/codegen/template.js +0 -151
  177. package/dist-cjs/install/authority-overlap.d.ts +0 -134
  178. package/dist-cjs/install/authority-overlap.js +0 -0
  179. package/dist-cjs/install/build-install-predicate.d.ts +0 -96
  180. package/dist-cjs/install/build-install-predicate.js +0 -479
  181. package/dist-cjs/install/build-merge-policy.d.ts +0 -70
  182. package/dist-cjs/install/build-merge-policy.js +0 -134
  183. package/dist-cjs/install/plan-merge-policy.d.ts +0 -49
  184. package/dist-cjs/install/plan-merge-policy.js +0 -90
  185. package/dist-cjs/install/read-account-rules.d.ts +0 -100
  186. package/dist-cjs/install/read-account-rules.js +0 -296
  187. package/dist-cjs/ir/index.d.ts +0 -1
  188. package/dist-cjs/ir/index.js +0 -3
  189. package/dist-cjs/ir/types.d.ts +0 -140
  190. package/dist-cjs/ir/types.js +0 -12
  191. package/dist-cjs/mandate/index.d.ts +0 -2
  192. package/dist-cjs/mandate/index.js +0 -6
  193. package/dist-cjs/mandate/to-ir.d.ts +0 -3
  194. package/dist-cjs/mandate/to-ir.js +0 -63
  195. package/dist-cjs/mandate/types.d.ts +0 -20
  196. package/dist-cjs/mandate/types.js +0 -9
  197. package/dist-cjs/seams/index.d.ts +0 -1
  198. package/dist-cjs/seams/index.js +0 -3
  199. package/dist-cjs/seams/types.d.ts +0 -66
  200. package/dist-cjs/seams/types.js +0 -12
  201. package/dist-cjs/synth/deny-cases.js +0 -568
  202. package/dist-cjs/synth/evaluate.d.ts +0 -39
  203. package/dist-cjs/synth/evaluate.js +0 -554
  204. package/dist-cjs/synth/harness.d.ts +0 -28
  205. package/dist-cjs/synth/harness.js +0 -50
  206. package/dist-cjs/synth/minimize.d.ts +0 -4
  207. package/dist-cjs/synth/minimize.js +0 -41
  208. package/dist-cjs/synth/permit-context.d.ts +0 -15
  209. package/dist-cjs/synth/permit-context.js +0 -119
  210. package/dist-cjs/synth/predicate-literals.d.ts +0 -5
  211. package/dist-cjs/synth/predicate-literals.js +0 -28
  212. package/dist-cjs/synth/synthesize-from-mandate.d.ts +0 -20
  213. package/dist-cjs/synth/synthesize-from-mandate.js +0 -62
  214. package/dist-cjs/verify/envelope.d.ts +0 -15
  215. package/dist-cjs/verify/envelope.js +0 -23
  216. package/dist-cjs/verify/index.d.ts +0 -3
  217. package/dist-cjs/verify/index.js +0 -8
  218. package/dist-cjs/verify/simulate.d.ts +0 -31
  219. package/dist-cjs/verify/simulate.js +0 -261
  220. package/dist-cjs/verify/verify.d.ts +0 -21
  221. package/dist-cjs/verify/verify.js +0 -192
  222. package/src/adapters/interpreter/index.ts +0 -8
  223. package/src/adapters/oz/adapter.ts +0 -376
  224. package/src/adapters/oz/index.ts +0 -9
  225. package/src/codegen/compile-gate.ts +0 -167
  226. package/src/codegen/index.ts +0 -17
  227. package/src/codegen/template.ts +0 -165
  228. package/src/install/authority-overlap.ts +0 -0
  229. package/src/install/build-merge-policy.ts +0 -219
  230. package/src/install/plan-merge-policy.ts +0 -133
  231. package/src/install/read-account-rules.ts +0 -376
  232. package/src/ir/index.ts +0 -13
  233. package/src/ir/types.ts +0 -132
  234. package/src/mandate/index.ts +0 -4
  235. package/src/mandate/to-ir.ts +0 -71
  236. package/src/mandate/types.ts +0 -21
  237. package/src/seams/index.ts +0 -11
  238. package/src/seams/types.ts +0 -81
  239. package/src/synth/deny-cases.ts +0 -663
  240. package/src/synth/evaluate.ts +0 -613
  241. package/src/synth/harness.ts +0 -68
  242. package/src/synth/minimize.ts +0 -48
  243. package/src/synth/permit-context.ts +0 -136
  244. package/src/synth/predicate-literals.ts +0 -27
  245. package/src/synth/synthesize-from-mandate.ts +0 -82
  246. package/src/verify/envelope.ts +0 -28
  247. package/src/verify/index.ts +0 -5
  248. package/src/verify/simulate.ts +0 -311
  249. package/src/verify/verify.ts +0 -243
@@ -9,14 +9,14 @@
9
9
  //
10
10
  // i128 amounts and other large integers are carried as base-10 decimal strings
11
11
  // end-to-end. Networks are pinned to the same closed set the core defines.
12
- // The discriminated union on `source` exposes BOTH synthesize_policy
13
- // front-ends through a single tool input.
12
+ // `source` is a single-variant discriminator (`recording`); it stays a union
13
+ // so an unknown value is rejected with a discriminator error.
14
14
  //
15
15
  // This module is the SINGLE source of truth for these shapes. The MCP package
16
16
  // imports them here so its tool-shape bindings stay in step; the CLI imports
17
17
  // them here so it can build the same args envelope the MCP transport builds.
18
18
  Object.defineProperty(exports, "__esModule", { value: true });
19
- exports.ToolErrorSchema = exports.GetInterpreterInfoInputSchema = exports.RevokePolicyInputSchema = exports.MergePolicyInputSchema = exports.InstallPolicyInputSchema = exports.NETWORK_PASSPHRASES = exports.DEFAULT_AUTH_VALID_UNTIL_LEDGERS = exports.RPC_URL_BY_NETWORK = exports.PINNED_INTERPRETER_WASM_SHA256_BY_NETWORK = exports.PINNED_INTERPRETER_ADDRESS_BY_NETWORK = exports.MAINNET_RPC_URL = exports.TESTNET_RPC_URL = exports.PINNED_INTERPRETER_GRAMMAR_VERSION = exports.PINNED_INTERPRETER_WASM_SHA256_TESTNET = exports.PINNED_INTERPRETER_WASM_SHA256 = exports.PINNED_INTERPRETER_MAINNET_ADDRESS = exports.PINNED_INTERPRETER_TESTNET_ADDRESS = exports.VerifyPolicyInputSchema = exports.SimulatePolicyInputSchema = exports.OraclePriceFixtureSchema = exports.PredicateNodeSchema = exports.PredicateLeafSchema = exports.SynthesizePolicyInputSchema = exports.SynthesizePolicyRecordingInputSchema = exports.InterpreterOptionsSchema = exports.SynthesizePolicyMandateInputSchema = exports.RecordTransactionInputSchema = exports.OzAdapterConfigSchema = exports.ComposeUserResponsesSchema = exports.MandateSpecSchema = exports.RecordedTransactionSchema = exports.ParseConfidenceSchema = exports.OnChainEventSchema = exports.TokenMovementSchema = exports.ContractInvocationSchema = exports.ScValSchema = exports.NetworkSchema = void 0;
19
+ exports.ToolErrorSchema = exports.GetInterpreterInfoInputSchema = exports.RevokePolicyInputSchema = exports.InstallPolicyInputSchema = exports.NETWORK_PASSPHRASES = exports.RPC_URL_BY_NETWORK = exports.PINNED_INTERPRETER_ADDRESS_BY_NETWORK = exports.MAINNET_RPC_URL = exports.TESTNET_RPC_URL = exports.PINNED_INTERPRETER_GRAMMAR_VERSION = exports.PINNED_INTERPRETER_WASM_SHA256 = exports.PINNED_INTERPRETER_MAINNET_ADDRESS = exports.PINNED_INTERPRETER_TESTNET_ADDRESS = exports.VerifyPolicyInputSchema = exports.SimulatePolicyInputSchema = exports.PredicateNodeSchema = exports.PredicateLeafSchema = exports.SynthesizePolicyInputSchema = exports.InterpreterOptionsSchema = exports.RecordTransactionInputSchema = exports.ComposeUserResponsesSchema = exports.RecordedTransactionSchema = exports.ParseConfidenceSchema = exports.OnChainEventSchema = exports.TokenMovementSchema = exports.ContractInvocationSchema = exports.ScValSchema = exports.NetworkSchema = void 0;
20
20
  const zod_1 = require("zod");
21
21
  const address_ts_1 = require("../synth/address.js");
22
22
  /** Soroban `valid_until` is a u32 ledger sequence; a value above this cannot be
@@ -101,56 +101,13 @@ exports.RecordedTransactionSchema = zod_1.z
101
101
  sourceAccount: zod_1.z.string(),
102
102
  })
103
103
  .passthrough();
104
- /** MandateSpec mirrors the core MandateSpec. The deterministic Mandate
105
- * front-end needs no parseConfidence; the tool adapter injects the full
106
- * confidence after synthesis so the orchestrator can compare. */
107
- exports.MandateSpecSchema = zod_1.z
108
- .object({
109
- chain: zod_1.z.literal('stellar'),
110
- contract: zod_1.z.string(),
111
- method: zod_1.z.string().optional(),
112
- spendingLimit: zod_1.z
113
- .object({
114
- token: zod_1.z.string(),
115
- limit: zod_1.z.string().regex(/^[0-9]+$/),
116
- windowSeconds: zod_1.z.number().int().positive(),
117
- })
118
- .optional(),
119
- // A threshold of 0 means "0 approvals", which is not a real M-of-N gate.
120
- approvalThreshold: zod_1.z.number().int().positive().optional(),
121
- recipients: zod_1.z.array(zod_1.z.string()).optional(),
122
- expiry: zod_1.z
123
- .object({
124
- validUntilLedger: zod_1.z.number().int().positive().max(U32_MAX).optional(),
125
- validUntilUnixSeconds: zod_1.z.number().int().positive().optional(),
126
- })
127
- .optional(),
128
- })
129
- .passthrough()
130
- // TS-F4/F6: a `recipients` allowlist is only meaningful against a SEP-41
131
- // method whose arg 1 IS the recipient (SAC/SEP-41 `transfer(from, to,
132
- // amount)` and SEP-41 `mint(to, amount)`). Without this gate the
133
- // `to-ir.ts` lowering pins the allowlist to `RECIPIENT_ARG_INDEX = 1`
134
- // for any contract+method, which would let a non-SEP-41 method's
135
- // arg[1] (e.g. an amount, an op type, an arbitrary address payload)
136
- // be silently constrained as if it were a recipient. Refusing
137
- // non-SEP-41 methods at the boundary is the fail-closed shape.
138
- .refine((v) => v.recipients === undefined ||
139
- v.recipients.length === 0 ||
140
- v.method === 'transfer' ||
141
- v.method === 'mint', {
142
- message: 'recipients is only valid when method is a SEP-41 method (transfer or mint); other methods do not have a recipient at arg[1]',
143
- });
144
- /** ComposeUserResponses mirrors the core. */
145
104
  exports.ComposeUserResponsesSchema = zod_1.z
146
105
  .object({
147
- windowSeconds: zod_1.z.number().int().positive().optional(),
148
106
  validUntilLedger: zod_1.z.number().int().positive().max(U32_MAX).optional(),
149
107
  limitAmount: zod_1.z
150
108
  .string()
151
109
  .regex(/^[0-9]+$/)
152
110
  .optional(),
153
- invocationLimit: zod_1.z.number().int().positive().optional(),
154
111
  // Swap recipient allowlist (SoroSwap call_arg[3]). Each entry must be a
155
112
  // Stellar address (G... wallet or C... contract); supplying it REPLACES the
156
113
  // default pin to the recorded recipient. Validated with the shared StrKey
@@ -158,33 +115,11 @@ exports.ComposeUserResponsesSchema = zod_1.z
158
115
  swapRecipientAllowlist: zod_1.z
159
116
  .array(zod_1.z.string().refine(address_ts_1.isStellarAddress, 'must be a Stellar address (G... or C...)'))
160
117
  .optional(),
161
- // Per-asset oracle-price bound, one entry per asset. Reaches
162
- // `compose-from-recording` and emits an `oracle_price` compare. Declared
163
- // here because the object is `.passthrough()`: the field already worked
164
- // undeclared, which left the accepted surface wider than the documented
165
- // one. `decimals` is REQUIRED - oracle prices normalise to 9 dp and a
166
- // threshold silently assumed to share that basis is what let a raw 14-dp
167
- // bound permit everything.
168
- oraclePriceBound: zod_1.z
169
- .array(zod_1.z.object({
170
- asset: zod_1.z.string().refine(address_ts_1.isStellarAddress, 'must be a Stellar address (G... or C...)'),
171
- operator: zod_1.z.enum(['eq', 'lt', 'lte', 'gt', 'gte']),
172
- value: zod_1.z.string().regex(/^[0-9]+$/),
173
- decimals: zod_1.z.number().int().min(0).max(U32_MAX),
174
- }))
175
- .optional(),
176
118
  })
177
- .passthrough();
178
- /** OzAdapterConfig - the per-network OZ built-in instance addresses. */
179
- exports.OzAdapterConfigSchema = zod_1.z.object({
180
- network: exports.NetworkSchema,
181
- instances: zod_1.z.object({
182
- spending_limit: zod_1.z.string(),
183
- simple_threshold: zod_1.z.string(),
184
- weighted_threshold: zod_1.z.string(),
185
- }),
186
- });
187
- // ===== record_transaction =====
119
+ // Strict, not passthrough: a response key the synthesiser no longer reads
120
+ // (or a typo) would otherwise be accepted in silence, and the caller would
121
+ // believe they had answered a question that is still open.
122
+ .strict();
188
123
  exports.RecordTransactionInputSchema = zod_1.z
189
124
  .object({
190
125
  hash: zod_1.z.string().min(1).optional(),
@@ -198,45 +133,17 @@ exports.RecordTransactionInputSchema = zod_1.z
198
133
  .refine((v) => Boolean(v.hash) || Boolean(v.xdr), {
199
134
  message: 'one of `hash` or `xdr` is required',
200
135
  });
201
- // ===== synthesize_policy =====
202
- //
203
- // Discriminated union on `source` exposes BOTH front-ends through ONE tool.
204
- // - `source: 'mandate'` -> calls synthesizeFromMandate
205
- // - `source: 'recording'` -> calls synthesizeFromRecording
206
- exports.SynthesizePolicyMandateInputSchema = zod_1.z.object({
207
- source: zod_1.z.literal('mandate'),
208
- mandate: exports.MandateSpecSchema,
209
- ozConfig: exports.OzAdapterConfigSchema.optional(),
210
- // --explain opt-in. When true, the orchestrator attaches the
211
- // in-memory predicate tree (null for the mandate path) + a minimal
212
- // honest SimulationResult to the success envelope. Absent or false
213
- // -> the success envelope is unchanged (byte-identical to today).
214
- explain: zod_1.z.boolean().optional(),
215
- });
216
- /** Interpreter opt-in for the recording path. Present -> constraints OZ cannot
217
- * express (per-method scoping, invocation-count windows, oracle bounds, exact
218
- * hop paths) lower to a real interpreter predicate document instead of being
219
- * surfaced as warnings. The core deep-validates `smartAccountAddress` (a C...
220
- * contract, not the recording's G... source) and the tighten-only oracle
221
- * bounds; the schema stays light so the core owns the friendly ToolErrors. */
222
136
  exports.InterpreterOptionsSchema = zod_1.z.object({
223
137
  smartAccountAddress: zod_1.z.string(),
224
138
  installNonce: zod_1.z.number().int().positive().optional(),
225
- oracleParams: zod_1.z
226
- .object({
227
- maxStalenessSeconds: zod_1.z.number().int().positive().optional(),
228
- maxDeviationBps: zod_1.z.number().int().positive().optional(),
229
- })
230
- .optional(),
231
139
  });
232
- exports.SynthesizePolicyRecordingInputSchema = zod_1.z.object({
140
+ exports.SynthesizePolicyInputSchema = zod_1.z.object({
233
141
  source: zod_1.z.literal('recording'),
234
142
  recordedTx: exports.RecordedTransactionSchema,
235
143
  network: exports.NetworkSchema,
236
144
  userResponses: exports.ComposeUserResponsesSchema.optional(),
237
145
  confidenceOverride: zod_1.z.object({ threshold: zod_1.z.number().min(0).max(1) }).optional(),
238
146
  interpreter: exports.InterpreterOptionsSchema.optional(),
239
- ozConfig: exports.OzAdapterConfigSchema.optional(),
240
147
  // --explain opt-in. When true, the orchestrator attaches the
241
148
  // in-memory PredicateNode + the corresponding SimulationResult
242
149
  // (real one from the self-verify pipeline when the interpreter is
@@ -247,10 +154,6 @@ exports.SynthesizePolicyRecordingInputSchema = zod_1.z.object({
247
154
  // explain.
248
155
  explain: zod_1.z.boolean().optional(),
249
156
  });
250
- exports.SynthesizePolicyInputSchema = zod_1.z.discriminatedUnion('source', [
251
- exports.SynthesizePolicyMandateInputSchema,
252
- exports.SynthesizePolicyRecordingInputSchema,
253
- ]);
254
157
  // ===== PredicateNode / PredicateLeaf =====
255
158
  //
256
159
  // Hand-written zod mirrors of the predicate grammar in types.ts:132-180.
@@ -277,41 +180,6 @@ exports.PredicateLeafSchema = zod_1.z.lazy(() => zod_1.z.union([
277
180
  element: zod_1.z.number().int().nonnegative(),
278
181
  field: zod_1.z.string(),
279
182
  }),
280
- // num/den are i128 on chain; JSON numbers lose precision past 2^53,
281
- // so the wire is a decimal string. The contract refuses `den == 0` and
282
- // `num <= 0` / `den <= 0` at install (types.ts:162-163 + the install
283
- // gate); mirroring that bound here closes the gap where simulate /
284
- // verify green-light a policy the install gate will reject. The
285
- // positive-only regex is the cheapest unambiguous check.
286
- zod_1.z.object({
287
- kind: zod_1.z.literal('call_arg_scaled'),
288
- index: zod_1.z.number().int().nonnegative(),
289
- num: zod_1.z.string().regex(/^[1-9][0-9]*$/),
290
- den: zod_1.z.string().regex(/^[1-9][0-9]*$/),
291
- }),
292
- zod_1.z.object({ kind: zod_1.z.literal('amount'), token: zod_1.z.string() }),
293
- zod_1.z.object({
294
- kind: zod_1.z.literal('window_spent'),
295
- token: zod_1.z.string(),
296
- windowSeconds: zod_1.z.number().int().positive(),
297
- }),
298
- zod_1.z.object({ kind: zod_1.z.literal('now') }),
299
- // `valid_until` is NOT in the public predicate grammar: the encoder +
300
- // decoder already throw on it, so accepting it here would let a
301
- // hand-crafted payload through the schema and only surface a 200+
302
- // character internal-commentary error at encode time. Drop it - the
303
- // policy's expiry is carried at the install layer (MandateSpec +
304
- // validUntilLedger) instead.
305
- zod_1.z.object({
306
- kind: zod_1.z.literal('invocation_count_in_window'),
307
- windowSecs: zod_1.z.number().int().positive(),
308
- }),
309
- zod_1.z.object({ kind: zod_1.z.literal('oracle_price'), asset: zod_1.z.string() }),
310
- zod_1.z.object({
311
- kind: zod_1.z.literal('oracle_threshold'),
312
- value: zod_1.z.string().regex(/^-?[0-9]+$/),
313
- decimals: zod_1.z.number().int().nonnegative(),
314
- }),
315
183
  zod_1.z.object({ kind: zod_1.z.literal('literal_address'), value: zod_1.z.string() }),
316
184
  zod_1.z.object({ kind: zod_1.z.literal('literal_i128'), value: zod_1.z.string().regex(/^-?[0-9]+$/) }),
317
185
  zod_1.z.object({ kind: zod_1.z.literal('literal_symbol'), value: zod_1.z.string() }),
@@ -323,36 +191,20 @@ exports.PredicateLeafSchema = zod_1.z.lazy(() => zod_1.z.union([
323
191
  kind: zod_1.z.literal('literal_u32'),
324
192
  value: zod_1.z.number().int().nonnegative().max(U32_MAX),
325
193
  }),
326
- zod_1.z.object({ kind: zod_1.z.literal('literal_u64'), value: zod_1.z.string().regex(/^[0-9]+$/) }),
327
- // `literal_bytes` is hex on chain. `Buffer.from(value, 'hex')` silently
328
- // drops non-hex chars AND yields an empty buffer when the whole input
329
- // is non-hex - so a user passing 'zzzz' would get a predicate that
330
- // compares against empty bytes instead of being rejected. The
331
- // strict even-length hex regex closes that gap at the boundary.
332
- zod_1.z.object({
333
- kind: zod_1.z.literal('literal_bytes'),
334
- value: zod_1.z
335
- .string()
336
- .regex(/^[0-9a-fA-F]*$/)
337
- .refine((v) => v.length % 2 === 0, 'must be even-length hex'),
338
- }),
339
194
  // elements are themselves PredicateLeaf; lazy to break the cycle.
340
195
  zod_1.z.object({ kind: zod_1.z.literal('literal_vec'), elements: zod_1.z.array(exports.PredicateLeafSchema) }),
341
196
  ]));
342
197
  /** PredicateNode mirrors the core `PredicateNode` union. Recursive through
343
- * `and`/`or`/`not`; the lazy + annotation pattern keeps the recursion
344
- * type-safe. */
198
+ * `and`; the lazy + annotation pattern keeps the recursion type-safe. */
345
199
  exports.PredicateNodeSchema = zod_1.z.lazy(() => zod_1.z.union([
346
200
  zod_1.z.object({ op: zod_1.z.literal('and'), children: zod_1.z.array(exports.PredicateNodeSchema) }),
347
- zod_1.z.object({ op: zod_1.z.literal('or'), children: zod_1.z.array(exports.PredicateNodeSchema) }),
348
- zod_1.z.object({ op: zod_1.z.literal('not'), child: exports.PredicateNodeSchema }),
349
201
  zod_1.z.object({
350
202
  op: zod_1.z.literal('eq'),
351
203
  left: exports.PredicateLeafSchema,
352
204
  right: exports.PredicateLeafSchema,
353
205
  }),
354
206
  zod_1.z.object({
355
- op: zod_1.z.enum(['lt', 'lte', 'gt', 'gte']),
207
+ op: zod_1.z.literal('lte'),
356
208
  left: exports.PredicateLeafSchema,
357
209
  right: exports.PredicateLeafSchema,
358
210
  }),
@@ -364,38 +216,16 @@ exports.PredicateNodeSchema = zod_1.z.lazy(() => zod_1.z.union([
364
216
  ]));
365
217
  // ===== simulate_policy / verify_policy =====
366
218
  //
367
- // The oracle fixture shape mirrors `SimulateOptions` / `VerifyOptions`
368
- // in packages/policy-synth/src/verify/{simulate,verify}.ts - the same
369
- // sorted set of error enum values is used by both engines. u32
370
- // `validUntilLedger` is bounded at the boundary so a hand-crafted
371
- // payload cannot leak a u32 overflow into the engine's permit context.
372
- /** Oracle price fixture - mirror of the entry type in `SimulateOptions` /
373
- * `VerifyOptions`. Discriminated by presence of `error` vs `price`. */
374
- exports.OraclePriceFixtureSchema = zod_1.z.union([
375
- zod_1.z.object({
376
- price: zod_1.z.string().regex(/^[0-9]+$/),
377
- timestampSeconds: zod_1.z.number().int().nonnegative(),
378
- }),
379
- zod_1.z.object({
380
- error: zod_1.z.enum(['stale', 'missing', 'deviation', 'paused', 'decimals', 'fingerprint']),
381
- }),
382
- ]);
219
+ // Both tools evaluate the same predicate against the same recording, so they
220
+ // take the same input. A null predicate used to mean "OZ built-in policies
221
+ // only"; that backend is gone, so every policy carries a predicate and there is
222
+ // nothing to simulate without one.
383
223
  exports.SimulatePolicyInputSchema = zod_1.z.object({
384
- // simulatePolicy accepts a null predicate (OZ-only policy); verifyPolicy
385
- // does not. The asymmetry is mirrored at the schema boundary.
386
- predicate: exports.PredicateNodeSchema.nullable(),
387
- permitTx: exports.RecordedTransactionSchema,
388
- validUntilLedger: zod_1.z.number().int().positive().max(U32_MAX).optional(),
389
- oraclePricesByAsset: zod_1.z.record(zod_1.z.string(), exports.OraclePriceFixtureSchema).optional(),
390
- });
391
- exports.VerifyPolicyInputSchema = zod_1.z.object({
392
- // verifyPolicy requires a non-null predicate; the engine refuses
393
- // `null` outright. The schema mirrors that contract.
394
224
  predicate: exports.PredicateNodeSchema,
395
225
  permitTx: exports.RecordedTransactionSchema,
396
226
  validUntilLedger: zod_1.z.number().int().positive().max(U32_MAX).optional(),
397
- oraclePricesByAsset: zod_1.z.record(zod_1.z.string(), exports.OraclePriceFixtureSchema).optional(),
398
227
  });
228
+ exports.VerifyPolicyInputSchema = exports.SimulatePolicyInputSchema;
399
229
  // ===== install_policy / revoke_policy / get_interpreter_info =====
400
230
  //
401
231
  // The install/revoke pair drives the OZ smart-account admin flow. Both surface
@@ -408,7 +238,7 @@ exports.VerifyPolicyInputSchema = zod_1.z.object({
408
238
  // optional `grammar_version()` RPC call to check whether the deployed contract
409
239
  // matches the pin. A mismatch is worth MORE than a fabricated audit field.
410
240
  //
411
- // All three input schemas live BELOW the MandateSpecSchemaForRule declaration
241
+ // All three input schemas live BELOW the ContextRuleDraftSchema declaration
412
242
  // so the const reference there is not in the temporal dead zone (no JS hoisting
413
243
  // for `const`).
414
244
  /** Minimal rule-draft schema for the install input. Mirrors ContextRuleDraft
@@ -419,7 +249,7 @@ exports.VerifyPolicyInputSchema = zod_1.z.object({
419
249
  * the temporal dead zone (no JS hoisting for `const`). */
420
250
  const MAX_SIGNERS_PER_RULE = 15;
421
251
  const MAX_POLICIES_PER_RULE = 5;
422
- const MandateSpecSchemaForRule = zod_1.z
252
+ const ContextRuleDraftSchema = zod_1.z
423
253
  .object({
424
254
  contextRuleType: zod_1.z.discriminatedUnion('kind', [
425
255
  zod_1.z.object({ kind: zod_1.z.literal('default') }),
@@ -439,21 +269,11 @@ const MandateSpecSchemaForRule = zod_1.z
439
269
  ]))
440
270
  .max(MAX_SIGNERS_PER_RULE),
441
271
  policies: zod_1.z
442
- .array(zod_1.z.discriminatedUnion('kind', [
443
- zod_1.z.object({
444
- kind: zod_1.z.literal('interpreter'),
445
- interpreterAddress: zod_1.z.string(),
446
- predicateBlobBase64: zod_1.z.string().min(1),
447
- }),
448
- zod_1.z.object({
449
- kind: zod_1.z.literal('oz_builtin'),
450
- primitive: zod_1.z.object({
451
- primitive: zod_1.z.enum(['spending_limit', 'simple_threshold', 'weighted_threshold']),
452
- params: zod_1.z.record(zod_1.z.unknown()),
453
- }),
454
- instanceAddress: zod_1.z.string(),
455
- }),
456
- ]))
272
+ .array(zod_1.z.object({
273
+ kind: zod_1.z.literal('interpreter'),
274
+ interpreterAddress: zod_1.z.string(),
275
+ predicateBlobBase64: zod_1.z.string().min(1),
276
+ }))
457
277
  .max(MAX_POLICIES_PER_RULE),
458
278
  })
459
279
  .passthrough()
@@ -463,27 +283,23 @@ const MandateSpecSchemaForRule = zod_1.z
463
283
  // existing four.
464
284
  /** Pinned interpreter address (testnet).
465
285
  * Single source for the MCP layer; do not embed elsewhere. */
466
- exports.PINNED_INTERPRETER_TESTNET_ADDRESS = 'CALHNU4LXZRKFAXYRBODTGDANTNXHJPBTJNYGLUWLIFIP24NWSGWIE4K';
467
- /** Pinned interpreter address (mainnet), deployed 2026-08-04.
468
- * UNAUDITED at the time of writing. */
469
- exports.PINNED_INTERPRETER_MAINNET_ADDRESS = 'CALZAMUPREIRY4TULBEXIK77AUTOEJG63XLCPUWEHHQDOVK6ZVVS7VQ2';
470
- /** Pinned interpreter wasm sha256 (hex), mainnet.
286
+ exports.PINNED_INTERPRETER_TESTNET_ADDRESS = 'CCL336TCK2Y5OFNRCMN2M3HVPBCEX4PW5H6EQ5VW5NPMXOCP4ESB5XR4';
287
+ /** Pinned interpreter address (mainnet), redeployed 2026-08-22 from a reproducible build. The mainnet
288
+ * interpreter IS the binary exercised on testnet - both instances were created
289
+ * from the same uploaded wasm hash (see PINNED_INTERPRETER_WASM_SHA256), and
290
+ * both were read back with `grammar_version()` returning 3. The address differs
291
+ * because instance ids are network-scoped. UNAUDITED at the time of writing.
471
292
  *
472
- * The two networks no longer run the same binary. Testnet carries the
473
- * selector-leaf minimum and the signer-set cap; mainnet predates both. Read
474
- * the hash through `PINNED_INTERPRETER_WASM_SHA256_BY_NETWORK` rather than
475
- * this constant unless mainnet is specifically what is meant, or
476
- * `get_interpreter_info` will report a hash the queried network does not
477
- * run. */
478
- exports.PINNED_INTERPRETER_WASM_SHA256 = '6e6c13d93e197aa380303a42cd120f5ddb080dd36ef2a343ee1dbd04ca52a443';
479
- /** Pinned interpreter wasm sha256 (hex), testnet. Byte-identical to the
480
- * artifact built from `contracts/policy-interpreter` at the commit that
481
- * introduced errors 216 and 217, verified by fetching the deployed wasm back
482
- * off chain. */
483
- exports.PINNED_INTERPRETER_WASM_SHA256_TESTNET = 'a4d58bc88fd82bbb8e223941ba5889db919717fae92ced13f6f55bfe583b8e22';
293
+ * These four constants move together or not at all. The grammar version and
294
+ * wasm hash are single values covering BOTH networks, so re-pinning one network
295
+ * alone would have the builder emit a version the other network refuses - with
296
+ * a green test run, since `grammar-version-parity.test.ts` would then pass. */
297
+ exports.PINNED_INTERPRETER_MAINNET_ADDRESS = 'CBZXLSTQUITBFZHQH6XRXF3XIVRQR4RHRI64Q5WELS5KGY3ZKJPFWDPF';
298
+ /** Pinned interpreter wasm sha256 (hex). */
299
+ exports.PINNED_INTERPRETER_WASM_SHA256 = 'a2b36e8ac5a61caf3757af26aa79e83f2995b451099f44772383806a55fe3414';
484
300
  /** The grammar version the interpreter enforces (matches SELF_VERSION in
485
301
  * contracts/policy-interpreter/src/version.rs). */
486
- exports.PINNED_INTERPRETER_GRAMMAR_VERSION = 1;
302
+ exports.PINNED_INTERPRETER_GRAMMAR_VERSION = 3;
487
303
  /** Default Soroban RPC for the install / revoke / info tools. The recorder
488
304
  * keeps its own copy in record/rpc.ts because it hands back a fetcher rather
489
305
  * than a Server; the two are deliberately different surfaces, so this is
@@ -494,25 +310,18 @@ exports.TESTNET_RPC_URL = 'https://soroban-testnet.stellar.org';
494
310
  * RPC rather than always testnet. Public mainnet endpoint, the same one
495
311
  * the deploy script hit during the 2026-08-04 mainnet rollout. */
496
312
  exports.MAINNET_RPC_URL = 'https://mainnet.sorobanrpc.com';
497
- /** Pin + RPC lookup for the gate enforcement. Addresses, RPCs and wasm
498
- * hashes are all network-scoped: the networks diverged when the
499
- * selector-leaf and signer-cap controls were deployed to testnet ahead of
500
- * mainnet. */
313
+ /** Pin + RPC lookup for the gate enforcement. The interpreters' wasm sha256
314
+ * is identical across both networks (the same binary was uploaded both
315
+ * places), so `PINNED_INTERPRETER_WASM_SHA256` stays
316
+ * a single constant - only the addresses and RPCs are network-scoped. */
501
317
  exports.PINNED_INTERPRETER_ADDRESS_BY_NETWORK = {
502
318
  testnet: exports.PINNED_INTERPRETER_TESTNET_ADDRESS,
503
319
  mainnet: exports.PINNED_INTERPRETER_MAINNET_ADDRESS,
504
320
  };
505
- exports.PINNED_INTERPRETER_WASM_SHA256_BY_NETWORK = {
506
- testnet: exports.PINNED_INTERPRETER_WASM_SHA256_TESTNET,
507
- mainnet: exports.PINNED_INTERPRETER_WASM_SHA256,
508
- };
509
321
  exports.RPC_URL_BY_NETWORK = {
510
322
  testnet: exports.TESTNET_RPC_URL,
511
323
  mainnet: exports.MAINNET_RPC_URL,
512
324
  };
513
- /** Soroban `valid_until` window (ledgers) added to the latest ledger when
514
- * building the auth entry. ~25 minutes at 5s/ledger. */
515
- exports.DEFAULT_AUTH_VALID_UNTIL_LEDGERS = 300;
516
325
  /** Stellar network passphrases. Pinned here so the XDR envelope uses the
517
326
  * matching passphrase when the wallet signs (a mismatch yields invalid
518
327
  * hashes). */
@@ -549,7 +358,7 @@ exports.InstallPolicyInputSchema = zod_1.z
549
358
  * pin and RPC pin do not move by themselves). */
550
359
  network: exports.NetworkSchema.optional(),
551
360
  /** The proposed rule draft. Mirrors the core `ContextRuleDraft` shape. */
552
- rule: MandateSpecSchemaForRule,
361
+ rule: ContextRuleDraftSchema,
553
362
  /** Per-rule install nonce; 1 for a fresh install. */
554
363
  installNonce: zod_1.z.number().int().positive(),
555
364
  /** Optional RPC URL override. Defaults to the pinned RPC for the
@@ -569,50 +378,12 @@ exports.InstallPolicyInputSchema = zod_1.z
569
378
  * everything. Selecting `network: 'mainnet'` is NOT an opt-in -
570
379
  * the mainnet pin is its own deny-by-default anchor. */
571
380
  allowUnpinnedInterpreter: zod_1.z.boolean().optional(),
572
- /** Opt-in to installing when a signer of this rule can already reach the
573
- * same calls through a context rule that has NO policy attached. OZ lets
574
- * the signer choose which rule authorises a call and enforces only that
575
- * rule's policies, so an unpoliced rule covering the same calls makes
576
- * this policy decorative. Default-deny, because the caller almost
577
- * certainly believes they are restricting something. */
578
- allowAuthorityOverlap: zod_1.z.boolean().optional(),
579
- /** Skip the cross-rule authority scan entirely. The scan costs one RPC
580
- * read per rule on the account; skipping it means the response carries
581
- * no statement about what the signers can already do. */
582
- skipAuthorityScan: zod_1.z.boolean().optional(),
583
381
  /** Base fee in stroops; defaults to BASE_FEE (100). */
584
382
  baseFee: zod_1.z.number().int().positive().optional(),
585
383
  })
586
384
  .refine((v) => Boolean(v.smartAccount) && Boolean(v.sourceAccount), {
587
385
  message: 'smartAccount and sourceAccount are required',
588
386
  });
589
- /** `merge_policy` input.
590
- *
591
- * The tightening remedy for a cross-rule overlap: replace a rule's predicate
592
- * with the conjunction of it and a new one. Two transactions, in order,
593
- * because OZ refuses to re-attach a policy already on the rule - so the
594
- * caller runs `detach`, waits for it to confirm, then runs `reinstall`. */
595
- exports.MergePolicyInputSchema = zod_1.z
596
- .object({
597
- smartAccount: zod_1.z
598
- .string()
599
- .regex(STELLAR_CONTRACT_ADDRESS, 'smartAccount must be a Stellar contract address (C...)'),
600
- sourceAccount: zod_1.z
601
- .string()
602
- .regex(STELLAR_ACCOUNT_ADDRESS, 'sourceAccount must be a Stellar account address (G...)'),
603
- /** The rule whose predicate is being tightened. */
604
- ruleId: zod_1.z.number().int().nonnegative(),
605
- /** The predicate to conjoin, base64 canonical ScVal, as emitted by
606
- * `synthesize_policy`. */
607
- incomingPredicateBlobBase64: zod_1.z.string().min(1),
608
- /** Which half of the remedy to build. */
609
- step: zod_1.z.enum(['detach', 'reinstall']),
610
- network: exports.NetworkSchema.optional(),
611
- rpcUrl: zod_1.z.string().url().optional(),
612
- allowUnpinnedRpcUrl: zod_1.z.boolean().optional(),
613
- baseFee: zod_1.z.number().int().positive().optional(),
614
- })
615
- .strict();
616
387
  exports.RevokePolicyInputSchema = zod_1.z
617
388
  .object({
618
389
  /** The smart account contract address (C...). */
@@ -13,17 +13,13 @@ export interface GeneratedCases {
13
13
  permit: EvalContext;
14
14
  denies: DenyCase[];
15
15
  }
16
- declare const OVERPERMISSIVE_DIMENSIONS: readonly ["argument_reorder"];
17
- declare const ORIGINAL_DIMENSIONS: string[];
18
- export { ORIGINAL_DIMENSIONS, OVERPERMISSIVE_DIMENSIONS };
19
16
  /** Build deterministic model-evaluated alternatives without mutating the intended call.
20
17
  *
21
18
  * @param predicate - the synthesized predicate
22
- * @param permitCtx - EvalContext for the intended (permitted) call
23
- * @param dimensions - optional whitelist of dimension names to emit; when omitted
24
- * all known dimensions (including over-permissiveness mutations)
25
- * are emitted. The synth pipeline passes ORIGINAL_DIMENSIONS so
26
- * existing fixtures do not regress. */
19
+ * @param permitCtx - EvalContext for the intended (permitted) call
20
+ * @param dimensions - optional whitelist of dimension names to emit; when omitted
21
+ * all known dimensions (including over-permissiveness mutations)
22
+ * are emitted. */
27
23
  export declare function generateCases(predicate: PredicateNode, permitCtx: EvalContext, dimensions?: string[]): GeneratedCases;
28
24
  /** Deep-copy an ScVal so a mutation cannot alias the recorded call.
29
25
  * Exported so the permit-context builder shares this one implementation. */