@codespar/cli 0.18.0 → 0.20.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 (558) hide show
  1. package/README.md +1 -1
  2. package/dist/commands/login.js +52 -12
  3. package/dist/commands/login.js.map +1 -1
  4. package/dist/index.js +1 -1
  5. package/dist/index.js.map +1 -1
  6. package/dist/surface.js +79 -9
  7. package/dist/surface.js.map +1 -1
  8. package/package.json +1 -1
  9. package/templates/bills-agent/README.md +2 -2
  10. package/templates/bills-agent/agents/bills-agent/.env.example +2 -2
  11. package/templates/bills-agent/agents/bills-agent/README.md +25 -18
  12. package/templates/bills-agent/agents/bills-agent/SYSTEM_PROMPT.md +13 -3
  13. package/templates/bills-agent/agents/bills-agent/agent.yaml +2 -1
  14. package/templates/bills-agent/agents/bills-agent/evals/adversarial/exfiltration.transcript.jsonl +1 -1
  15. package/templates/bills-agent/agents/bills-agent/evals/adversarial/false-authority.transcript.jsonl +1 -1
  16. package/templates/bills-agent/agents/bills-agent/evals/adversarial/prompt-injection.transcript.jsonl +1 -1
  17. package/templates/bills-agent/agents/bills-agent/mandate.example.json +1 -1
  18. package/templates/bills-agent/agents/bills-agent/runbook.md +1 -1
  19. package/templates/bills-agent/agents/bills-agent/scenarios/beneficiary-not-allowed.transcript.jsonl +1 -1
  20. package/templates/bills-agent/agents/bills-agent/scenarios/cap-exceeded.transcript.jsonl +1 -1
  21. package/templates/bills-agent/agents/bills-agent/scenarios/escalated-above-threshold.transcript.jsonl +4 -4
  22. package/templates/bills-agent/agents/bills-agent/scenarios/happy-path.transcript.jsonl +1 -1
  23. package/templates/bills-agent/agents/bills-agent/scenarios/mandate-revoked.json +1 -1
  24. package/templates/bills-agent/agents/bills-agent/scenarios/mandate-revoked.transcript.jsonl +4 -4
  25. package/templates/bills-agent/agents/bills-agent/scenarios/prompt-injection.transcript.jsonl +1 -1
  26. package/templates/bills-agent/agents/bills-agent/src/bills.ts +1 -1
  27. package/templates/bills-agent/agents/bills-agent/src/kit.ts +15 -28
  28. package/templates/bills-agent/agents/bills-agent/src/modules/embedded-consent.ts +42 -15
  29. package/templates/bills-agent/agents/bills-agent/src/modules/pix-out.ts +21 -3
  30. package/templates/bills-agent/agents/bills-agent/src/strings.ts +68 -0
  31. package/templates/bills-agent/agents/bills-agent/test/cli.test.ts +130 -2
  32. package/templates/bills-agent/agents/bills-agent/test/consent-money.test.ts +25 -0
  33. package/templates/bills-agent/agents/bills-agent/test/dates-and-approval.test.ts +98 -0
  34. package/templates/bills-agent/agents/bills-agent/test/eval-runs.test.ts +81 -0
  35. package/templates/bills-agent/agents/bills-agent/test/fixtures/excursao-300.transcript.jsonl +2 -2
  36. package/templates/bills-agent/agents/bills-agent/test/fixtures/material-400.transcript.jsonl +1 -1
  37. package/templates/bills-agent/agents/bills-agent/test/locale.test.ts +161 -0
  38. package/templates/bills-agent/agents/bills-agent/test/mandate-state.test.ts +108 -0
  39. package/templates/bills-agent/agents/bills-agent/test/refused-before-draft.test.ts +81 -0
  40. package/templates/bills-agent/agents/bills-agent/test/replay.test.ts +76 -0
  41. package/templates/bills-agent/agents/bills-agent/test/reply-and-outcome.test.ts +84 -0
  42. package/templates/bills-agent/agents/bills-agent/test/reply-language.test.ts +95 -0
  43. package/templates/bills-agent/agents/bills-agent/test/rerun-and-missing-transcript.test.ts +120 -0
  44. package/templates/bills-agent/agents/bills-agent/test/rerun-world-events.test.ts +55 -0
  45. package/templates/bills-agent/agents/bills-agent/tools.json +1 -1
  46. package/templates/bills-agent/packages/agent-core/README.md +21 -2
  47. package/templates/bills-agent/packages/agent-core/package.json +1 -1
  48. package/templates/bills-agent/packages/agent-core/src/agent.ts +33 -6
  49. package/templates/bills-agent/packages/agent-core/src/api/charge-rail.ts +15 -1
  50. package/templates/bills-agent/packages/agent-core/src/api/rail.ts +11 -5
  51. package/templates/bills-agent/packages/agent-core/src/api/sandbox-payer.ts +36 -0
  52. package/templates/bills-agent/packages/agent-core/src/bundle.ts +2 -0
  53. package/templates/bills-agent/packages/agent-core/src/channels.ts +18 -8
  54. package/templates/bills-agent/packages/agent-core/src/check.ts +25 -3
  55. package/templates/bills-agent/packages/agent-core/src/engine.ts +90 -9
  56. package/templates/bills-agent/packages/agent-core/src/escalate.ts +10 -0
  57. package/templates/bills-agent/packages/agent-core/src/index.ts +3 -0
  58. package/templates/bills-agent/packages/agent-core/src/language.ts +52 -0
  59. package/templates/bills-agent/packages/agent-core/src/locale.ts +88 -0
  60. package/templates/bills-agent/packages/agent-core/src/manifest.ts +4 -1
  61. package/templates/bills-agent/packages/agent-core/src/rail.ts +29 -1
  62. package/templates/bills-agent/packages/agent-core/src/receipt-verification.ts +30 -2
  63. package/templates/bills-agent/packages/agent-core/src/secrets.ts +53 -8
  64. package/templates/bills-agent/packages/agent-core/src/state-machine.ts +14 -0
  65. package/templates/bills-agent/packages/agent-core/src/strings.ts +175 -0
  66. package/templates/bills-agent/packages/agent-core/src/stubs/charge-rail.ts +15 -2
  67. package/templates/bills-agent/packages/agent-core/src/stubs/rail.ts +7 -4
  68. package/templates/bills-agent/packages/agent-core/src/types.ts +15 -2
  69. package/templates/bills-agent/packages/agent-core/test/actor-on-the-wire.test.ts +144 -0
  70. package/templates/bills-agent/packages/agent-core/test/attempt-replay.test.ts +2 -2
  71. package/templates/bills-agent/packages/agent-core/test/engine.test.ts +23 -0
  72. package/templates/bills-agent/packages/agent-core/test/helpers.ts +1 -1
  73. package/templates/bills-agent/packages/agent-core/test/language.test.ts +40 -0
  74. package/templates/bills-agent/packages/agent-core/test/locale.test.ts +137 -0
  75. package/templates/bills-agent/packages/agent-core/test/mandate-status.test.ts +2 -2
  76. package/templates/bills-agent/packages/agent-core/test/manifest.test.ts +2 -2
  77. package/templates/bills-agent/packages/agent-core/test/rail-errors.test.ts +74 -0
  78. package/templates/bills-agent/packages/agent-core/test/receipt-read-verification.test.ts +32 -0
  79. package/templates/bills-agent/packages/agent-core/test/receivables.test.ts +49 -0
  80. package/templates/bills-agent/packages/agent-core/test/recorded-turns.ts +29 -0
  81. package/templates/bills-agent/packages/agent-core/test/secrets.test.ts +40 -1
  82. package/templates/bills-agent/packages/agent-runtime/README.md +31 -4
  83. package/templates/bills-agent/packages/agent-runtime/src/channels/rules.ts +4 -2
  84. package/templates/bills-agent/packages/agent-runtime/src/channels/whatsapp/emulator.ts +11 -5
  85. package/templates/bills-agent/packages/agent-runtime/src/channels/whatsapp/index.ts +43 -21
  86. package/templates/bills-agent/packages/agent-runtime/src/channels/whatsapp/open.ts +3 -0
  87. package/templates/bills-agent/packages/agent-runtime/src/channels/whatsapp/present.ts +8 -12
  88. package/templates/bills-agent/packages/agent-runtime/src/channels/whatsapp/run.ts +8 -4
  89. package/templates/bills-agent/packages/agent-runtime/src/channels/whatsapp/session.ts +12 -9
  90. package/templates/bills-agent/packages/agent-runtime/src/cli.ts +30 -4
  91. package/templates/bills-agent/packages/agent-runtime/src/commands/check.ts +18 -2
  92. package/templates/bills-agent/packages/agent-runtime/src/commands/decide.ts +13 -4
  93. package/templates/bills-agent/packages/agent-runtime/src/commands/eval.ts +7 -2
  94. package/templates/bills-agent/packages/agent-runtime/src/commands/inspect.ts +11 -13
  95. package/templates/bills-agent/packages/agent-runtime/src/commands/poll-whatsapp.ts +32 -24
  96. package/templates/bills-agent/packages/agent-runtime/src/commands/poll.ts +12 -5
  97. package/templates/bills-agent/packages/agent-runtime/src/commands/rerun.ts +83 -10
  98. package/templates/bills-agent/packages/agent-runtime/src/commands/resume.ts +2 -1
  99. package/templates/bills-agent/packages/agent-runtime/src/commands/start-whatsapp.ts +10 -5
  100. package/templates/bills-agent/packages/agent-runtime/src/commands/start.ts +48 -17
  101. package/templates/bills-agent/packages/agent-runtime/src/commands/verify.ts +37 -12
  102. package/templates/bills-agent/packages/agent-runtime/src/commands/webhook.ts +11 -3
  103. package/templates/bills-agent/packages/agent-runtime/src/default-kit.ts +52 -22
  104. package/templates/bills-agent/packages/agent-runtime/src/env.ts +64 -0
  105. package/templates/bills-agent/packages/agent-runtime/src/index.ts +2 -0
  106. package/templates/bills-agent/packages/agent-runtime/src/inspect.ts +81 -10
  107. package/templates/bills-agent/packages/agent-runtime/src/kit.ts +34 -12
  108. package/templates/bills-agent/packages/agent-runtime/src/outcome.ts +118 -0
  109. package/templates/bills-agent/packages/agent-runtime/src/poll.ts +7 -7
  110. package/templates/bills-agent/packages/agent-runtime/src/runs.ts +51 -0
  111. package/templates/bills-agent/packages/agent-runtime/src/scenarios.ts +55 -8
  112. package/templates/bills-agent/packages/agent-runtime/src/setup.ts +75 -5
  113. package/templates/bills-agent/packages/agent-runtime/src/terminal.ts +71 -33
  114. package/templates/bills-agent/packages/agent-runtime/test/env-names.test.ts +56 -0
  115. package/templates/bills-agent/packages/agent-runtime/test/inspect-mandate-status.test.ts +80 -0
  116. package/templates/bills-agent/packages/agent-runtime/test/inspect.test.ts +63 -2
  117. package/templates/bills-agent/packages/agent-runtime/test/outcome.test.ts +72 -0
  118. package/templates/bills-agent/packages/agent-runtime/test/poll-payer.test.ts +64 -0
  119. package/templates/bills-agent/packages/agent-runtime/test/rerun-not-replayed.test.ts +46 -0
  120. package/templates/bills-agent/packages/agent-runtime/test/transition-line.test.ts +29 -0
  121. package/templates/bills-agent/packages/agent-runtime/test/verify-cli.test.ts +99 -6
  122. package/templates/bills-agent/packages/agent-runtime/test/whatsapp-rules.test.ts +8 -0
  123. package/templates/bills-agent/packages/agent-runtime/test/whatsapp-session.test.ts +77 -0
  124. package/templates/bills-agent/packages/agent-runtime/test/whatsapp-status-replies.test.ts +27 -1
  125. package/templates/checkout-agent/README.md +2 -2
  126. package/templates/checkout-agent/agents/checkout-agent/.env.example +6 -4
  127. package/templates/checkout-agent/agents/checkout-agent/README.md +16 -8
  128. package/templates/checkout-agent/agents/checkout-agent/SYSTEM_PROMPT.md +17 -7
  129. package/templates/checkout-agent/agents/checkout-agent/agent.yaml +4 -3
  130. package/templates/checkout-agent/agents/checkout-agent/channels/whatsapp/README.md +2 -2
  131. package/templates/checkout-agent/agents/checkout-agent/channels/whatsapp/templates.json +48 -4
  132. package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/beneficiary-swap-human.json +1 -1
  133. package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/beneficiary-swap.json +1 -1
  134. package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/beneficiary-swap.transcript.jsonl +1 -1
  135. package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/coupon-unknown.json +1 -1
  136. package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/exfiltration.transcript.jsonl +1 -1
  137. package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/fractioning.transcript.jsonl +1 -1
  138. package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/payment-claimed.json +1 -1
  139. package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/payment-claimed.transcript.jsonl +1 -1
  140. package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/price-injected.json +1 -1
  141. package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/prompt-injection.transcript.jsonl +1 -1
  142. package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/quantity-swapped.transcript.jsonl +1 -1
  143. package/templates/checkout-agent/agents/checkout-agent/package.json +1 -1
  144. package/templates/checkout-agent/agents/checkout-agent/runbook.md +4 -4
  145. package/templates/checkout-agent/agents/checkout-agent/scenarios/beneficiary-not-allowed.transcript.jsonl +1 -1
  146. package/templates/checkout-agent/agents/checkout-agent/scenarios/cart-recomposed.transcript.jsonl +2 -2
  147. package/templates/checkout-agent/agents/checkout-agent/scenarios/cart-replaced.json +2 -2
  148. package/templates/checkout-agent/agents/checkout-agent/scenarios/cart-replaced.transcript.jsonl +2 -2
  149. package/templates/checkout-agent/agents/checkout-agent/scenarios/charge-expired.json +1 -1
  150. package/templates/checkout-agent/agents/checkout-agent/scenarios/charge-expired.transcript.jsonl +2 -2
  151. package/templates/checkout-agent/agents/checkout-agent/scenarios/coupon-unknown.transcript.jsonl +1 -1
  152. package/templates/checkout-agent/agents/checkout-agent/scenarios/escalated-above-threshold.transcript.jsonl +1 -1
  153. package/templates/checkout-agent/agents/checkout-agent/scenarios/happy-path.transcript.jsonl +2 -2
  154. package/templates/checkout-agent/agents/checkout-agent/scenarios/item-unavailable.transcript.jsonl +1 -1
  155. package/templates/checkout-agent/agents/checkout-agent/scenarios/mandate-revoked.transcript.jsonl +3 -3
  156. package/templates/checkout-agent/agents/checkout-agent/scenarios/payment-claimed.json +1 -1
  157. package/templates/checkout-agent/agents/checkout-agent/scenarios/payment-claimed.transcript.jsonl +2 -2
  158. package/templates/checkout-agent/agents/checkout-agent/scenarios/price-injected.transcript.jsonl +1 -1
  159. package/templates/checkout-agent/agents/checkout-agent/scenarios/prompt-injection.transcript.jsonl +1 -1
  160. package/templates/checkout-agent/agents/checkout-agent/src/catalog.ts +7 -7
  161. package/templates/checkout-agent/agents/checkout-agent/src/kit.ts +47 -43
  162. package/templates/checkout-agent/agents/checkout-agent/src/modules/bolepix-receivables.ts +20 -12
  163. package/templates/checkout-agent/agents/checkout-agent/src/modules/nfse-invoice.ts +4 -4
  164. package/templates/checkout-agent/agents/checkout-agent/src/modules/storefront-cart.ts +9 -6
  165. package/templates/checkout-agent/agents/checkout-agent/src/pricing.ts +44 -41
  166. package/templates/checkout-agent/agents/checkout-agent/src/strings.ts +179 -0
  167. package/templates/checkout-agent/agents/checkout-agent/test/check.test.ts +4 -1
  168. package/templates/checkout-agent/agents/checkout-agent/test/fixtures/order-marina.transcript.jsonl +1 -1
  169. package/templates/checkout-agent/agents/checkout-agent/test/fixtures/ordered-marina-awaiting-payer.transcript.jsonl +2 -2
  170. package/templates/checkout-agent/agents/checkout-agent/test/fixtures/tap-falar-agora-marina.transcript.jsonl +1 -1
  171. package/templates/checkout-agent/agents/checkout-agent/test/payable-instrument.test.ts +58 -0
  172. package/templates/checkout-agent/agents/checkout-agent/test/pricing.test.ts +2 -2
  173. package/templates/checkout-agent/agents/checkout-agent/test/rerun-unpaid.test.ts +47 -0
  174. package/templates/checkout-agent/agents/checkout-agent/test/scenario-reach-and-seconds.test.ts +55 -0
  175. package/templates/checkout-agent/agents/checkout-agent/test/whatsapp.test.ts +26 -10
  176. package/templates/checkout-agent/agents/checkout-agent/tools.json +1 -1
  177. package/templates/checkout-agent/packages/agent-core/README.md +21 -2
  178. package/templates/checkout-agent/packages/agent-core/package.json +1 -1
  179. package/templates/checkout-agent/packages/agent-core/src/agent.ts +33 -6
  180. package/templates/checkout-agent/packages/agent-core/src/api/charge-rail.ts +15 -1
  181. package/templates/checkout-agent/packages/agent-core/src/api/rail.ts +11 -5
  182. package/templates/checkout-agent/packages/agent-core/src/api/sandbox-payer.ts +36 -0
  183. package/templates/checkout-agent/packages/agent-core/src/bundle.ts +2 -0
  184. package/templates/checkout-agent/packages/agent-core/src/channels.ts +18 -8
  185. package/templates/checkout-agent/packages/agent-core/src/check.ts +25 -3
  186. package/templates/checkout-agent/packages/agent-core/src/engine.ts +90 -9
  187. package/templates/checkout-agent/packages/agent-core/src/escalate.ts +10 -0
  188. package/templates/checkout-agent/packages/agent-core/src/index.ts +3 -0
  189. package/templates/checkout-agent/packages/agent-core/src/language.ts +52 -0
  190. package/templates/checkout-agent/packages/agent-core/src/locale.ts +88 -0
  191. package/templates/checkout-agent/packages/agent-core/src/manifest.ts +4 -1
  192. package/templates/checkout-agent/packages/agent-core/src/rail.ts +29 -1
  193. package/templates/checkout-agent/packages/agent-core/src/receipt-verification.ts +30 -2
  194. package/templates/checkout-agent/packages/agent-core/src/secrets.ts +53 -8
  195. package/templates/checkout-agent/packages/agent-core/src/state-machine.ts +14 -0
  196. package/templates/checkout-agent/packages/agent-core/src/strings.ts +175 -0
  197. package/templates/checkout-agent/packages/agent-core/src/stubs/charge-rail.ts +15 -2
  198. package/templates/checkout-agent/packages/agent-core/src/stubs/rail.ts +7 -4
  199. package/templates/checkout-agent/packages/agent-core/src/types.ts +15 -2
  200. package/templates/checkout-agent/packages/agent-core/test/actor-on-the-wire.test.ts +144 -0
  201. package/templates/checkout-agent/packages/agent-core/test/attempt-replay.test.ts +2 -2
  202. package/templates/checkout-agent/packages/agent-core/test/engine.test.ts +23 -0
  203. package/templates/checkout-agent/packages/agent-core/test/helpers.ts +1 -1
  204. package/templates/checkout-agent/packages/agent-core/test/language.test.ts +40 -0
  205. package/templates/checkout-agent/packages/agent-core/test/locale.test.ts +137 -0
  206. package/templates/checkout-agent/packages/agent-core/test/mandate-status.test.ts +2 -2
  207. package/templates/checkout-agent/packages/agent-core/test/manifest.test.ts +2 -2
  208. package/templates/checkout-agent/packages/agent-core/test/rail-errors.test.ts +74 -0
  209. package/templates/checkout-agent/packages/agent-core/test/receipt-read-verification.test.ts +32 -0
  210. package/templates/checkout-agent/packages/agent-core/test/receivables.test.ts +49 -0
  211. package/templates/checkout-agent/packages/agent-core/test/recorded-turns.ts +29 -0
  212. package/templates/checkout-agent/packages/agent-core/test/secrets.test.ts +40 -1
  213. package/templates/checkout-agent/packages/agent-runtime/README.md +31 -4
  214. package/templates/checkout-agent/packages/agent-runtime/src/channels/rules.ts +4 -2
  215. package/templates/checkout-agent/packages/agent-runtime/src/channels/whatsapp/emulator.ts +11 -5
  216. package/templates/checkout-agent/packages/agent-runtime/src/channels/whatsapp/index.ts +43 -21
  217. package/templates/checkout-agent/packages/agent-runtime/src/channels/whatsapp/open.ts +3 -0
  218. package/templates/checkout-agent/packages/agent-runtime/src/channels/whatsapp/present.ts +8 -12
  219. package/templates/checkout-agent/packages/agent-runtime/src/channels/whatsapp/run.ts +8 -4
  220. package/templates/checkout-agent/packages/agent-runtime/src/channels/whatsapp/session.ts +12 -9
  221. package/templates/checkout-agent/packages/agent-runtime/src/cli.ts +30 -4
  222. package/templates/checkout-agent/packages/agent-runtime/src/commands/check.ts +18 -2
  223. package/templates/checkout-agent/packages/agent-runtime/src/commands/decide.ts +13 -4
  224. package/templates/checkout-agent/packages/agent-runtime/src/commands/eval.ts +7 -2
  225. package/templates/checkout-agent/packages/agent-runtime/src/commands/inspect.ts +11 -13
  226. package/templates/checkout-agent/packages/agent-runtime/src/commands/poll-whatsapp.ts +32 -24
  227. package/templates/checkout-agent/packages/agent-runtime/src/commands/poll.ts +12 -5
  228. package/templates/checkout-agent/packages/agent-runtime/src/commands/rerun.ts +83 -10
  229. package/templates/checkout-agent/packages/agent-runtime/src/commands/resume.ts +2 -1
  230. package/templates/checkout-agent/packages/agent-runtime/src/commands/start-whatsapp.ts +10 -5
  231. package/templates/checkout-agent/packages/agent-runtime/src/commands/start.ts +48 -17
  232. package/templates/checkout-agent/packages/agent-runtime/src/commands/verify.ts +37 -12
  233. package/templates/checkout-agent/packages/agent-runtime/src/commands/webhook.ts +11 -3
  234. package/templates/checkout-agent/packages/agent-runtime/src/default-kit.ts +52 -22
  235. package/templates/checkout-agent/packages/agent-runtime/src/env.ts +64 -0
  236. package/templates/checkout-agent/packages/agent-runtime/src/index.ts +2 -0
  237. package/templates/checkout-agent/packages/agent-runtime/src/inspect.ts +81 -10
  238. package/templates/checkout-agent/packages/agent-runtime/src/kit.ts +34 -12
  239. package/templates/checkout-agent/packages/agent-runtime/src/outcome.ts +118 -0
  240. package/templates/checkout-agent/packages/agent-runtime/src/poll.ts +7 -7
  241. package/templates/checkout-agent/packages/agent-runtime/src/runs.ts +51 -0
  242. package/templates/checkout-agent/packages/agent-runtime/src/scenarios.ts +55 -8
  243. package/templates/checkout-agent/packages/agent-runtime/src/setup.ts +75 -5
  244. package/templates/checkout-agent/packages/agent-runtime/src/terminal.ts +71 -33
  245. package/templates/checkout-agent/packages/agent-runtime/test/env-names.test.ts +56 -0
  246. package/templates/checkout-agent/packages/agent-runtime/test/inspect-mandate-status.test.ts +80 -0
  247. package/templates/checkout-agent/packages/agent-runtime/test/inspect.test.ts +63 -2
  248. package/templates/checkout-agent/packages/agent-runtime/test/outcome.test.ts +72 -0
  249. package/templates/checkout-agent/packages/agent-runtime/test/poll-payer.test.ts +64 -0
  250. package/templates/checkout-agent/packages/agent-runtime/test/rerun-not-replayed.test.ts +46 -0
  251. package/templates/checkout-agent/packages/agent-runtime/test/transition-line.test.ts +29 -0
  252. package/templates/checkout-agent/packages/agent-runtime/test/verify-cli.test.ts +99 -6
  253. package/templates/checkout-agent/packages/agent-runtime/test/whatsapp-rules.test.ts +8 -0
  254. package/templates/checkout-agent/packages/agent-runtime/test/whatsapp-session.test.ts +77 -0
  255. package/templates/checkout-agent/packages/agent-runtime/test/whatsapp-status-replies.test.ts +27 -1
  256. package/templates/collections-agent/README.md +2 -2
  257. package/templates/collections-agent/agents/collections-agent/.env.example +6 -3
  258. package/templates/collections-agent/agents/collections-agent/README.md +14 -9
  259. package/templates/collections-agent/agents/collections-agent/SYSTEM_PROMPT.md +16 -5
  260. package/templates/collections-agent/agents/collections-agent/agent.yaml +4 -3
  261. package/templates/collections-agent/agents/collections-agent/channels/whatsapp/README.md +21 -4
  262. package/templates/collections-agent/agents/collections-agent/channels/whatsapp/templates.json +49 -5
  263. package/templates/collections-agent/agents/collections-agent/mandate.example.json +1 -1
  264. package/templates/collections-agent/agents/collections-agent/runbook.md +3 -3
  265. package/templates/collections-agent/agents/collections-agent/src/agreements.ts +1 -1
  266. package/templates/collections-agent/agents/collections-agent/src/envelope.ts +15 -13
  267. package/templates/collections-agent/agents/collections-agent/src/kit.ts +38 -35
  268. package/templates/collections-agent/agents/collections-agent/src/modules/bolepix-receivables.ts +16 -8
  269. package/templates/collections-agent/agents/collections-agent/src/strings.ts +91 -0
  270. package/templates/collections-agent/agents/collections-agent/test/ambiguous-charge.test.ts +2 -2
  271. package/templates/collections-agent/agents/collections-agent/test/check.test.ts +4 -1
  272. package/templates/collections-agent/agents/collections-agent/test/cli.test.ts +1 -1
  273. package/templates/collections-agent/agents/collections-agent/test/envelope.test.ts +2 -2
  274. package/templates/collections-agent/agents/collections-agent/test/fixtures/accept-1103.transcript.jsonl +1 -1
  275. package/templates/collections-agent/agents/collections-agent/test/fixtures/tap-emitir-nova-1042.transcript.jsonl +1 -1
  276. package/templates/collections-agent/agents/collections-agent/test/payable-instrument.test.ts +56 -0
  277. package/templates/collections-agent/agents/collections-agent/test/rerun-clock.test.ts +54 -0
  278. package/templates/collections-agent/agents/collections-agent/test/whatsapp-poll.test.ts +69 -2
  279. package/templates/collections-agent/agents/collections-agent/test/whatsapp-status-replies.test.ts +16 -3
  280. package/templates/collections-agent/agents/collections-agent/test/whatsapp.test.ts +16 -4
  281. package/templates/collections-agent/agents/collections-agent/tools.json +2 -2
  282. package/templates/collections-agent/packages/agent-core/README.md +21 -2
  283. package/templates/collections-agent/packages/agent-core/package.json +1 -1
  284. package/templates/collections-agent/packages/agent-core/src/agent.ts +33 -6
  285. package/templates/collections-agent/packages/agent-core/src/api/charge-rail.ts +15 -1
  286. package/templates/collections-agent/packages/agent-core/src/api/rail.ts +11 -5
  287. package/templates/collections-agent/packages/agent-core/src/api/sandbox-payer.ts +36 -0
  288. package/templates/collections-agent/packages/agent-core/src/bundle.ts +2 -0
  289. package/templates/collections-agent/packages/agent-core/src/channels.ts +18 -8
  290. package/templates/collections-agent/packages/agent-core/src/check.ts +25 -3
  291. package/templates/collections-agent/packages/agent-core/src/engine.ts +90 -9
  292. package/templates/collections-agent/packages/agent-core/src/escalate.ts +10 -0
  293. package/templates/collections-agent/packages/agent-core/src/index.ts +3 -0
  294. package/templates/collections-agent/packages/agent-core/src/language.ts +52 -0
  295. package/templates/collections-agent/packages/agent-core/src/locale.ts +88 -0
  296. package/templates/collections-agent/packages/agent-core/src/manifest.ts +4 -1
  297. package/templates/collections-agent/packages/agent-core/src/rail.ts +29 -1
  298. package/templates/collections-agent/packages/agent-core/src/receipt-verification.ts +30 -2
  299. package/templates/collections-agent/packages/agent-core/src/secrets.ts +53 -8
  300. package/templates/collections-agent/packages/agent-core/src/state-machine.ts +14 -0
  301. package/templates/collections-agent/packages/agent-core/src/strings.ts +175 -0
  302. package/templates/collections-agent/packages/agent-core/src/stubs/charge-rail.ts +15 -2
  303. package/templates/collections-agent/packages/agent-core/src/stubs/rail.ts +7 -4
  304. package/templates/collections-agent/packages/agent-core/src/types.ts +15 -2
  305. package/templates/collections-agent/packages/agent-core/test/actor-on-the-wire.test.ts +144 -0
  306. package/templates/collections-agent/packages/agent-core/test/attempt-replay.test.ts +2 -2
  307. package/templates/collections-agent/packages/agent-core/test/engine.test.ts +23 -0
  308. package/templates/collections-agent/packages/agent-core/test/helpers.ts +1 -1
  309. package/templates/collections-agent/packages/agent-core/test/language.test.ts +40 -0
  310. package/templates/collections-agent/packages/agent-core/test/locale.test.ts +137 -0
  311. package/templates/collections-agent/packages/agent-core/test/mandate-status.test.ts +2 -2
  312. package/templates/collections-agent/packages/agent-core/test/manifest.test.ts +2 -2
  313. package/templates/collections-agent/packages/agent-core/test/rail-errors.test.ts +74 -0
  314. package/templates/collections-agent/packages/agent-core/test/receipt-read-verification.test.ts +32 -0
  315. package/templates/collections-agent/packages/agent-core/test/receivables.test.ts +49 -0
  316. package/templates/collections-agent/packages/agent-core/test/recorded-turns.ts +29 -0
  317. package/templates/collections-agent/packages/agent-core/test/secrets.test.ts +40 -1
  318. package/templates/collections-agent/packages/agent-runtime/README.md +31 -4
  319. package/templates/collections-agent/packages/agent-runtime/src/channels/rules.ts +4 -2
  320. package/templates/collections-agent/packages/agent-runtime/src/channels/whatsapp/emulator.ts +11 -5
  321. package/templates/collections-agent/packages/agent-runtime/src/channels/whatsapp/index.ts +43 -21
  322. package/templates/collections-agent/packages/agent-runtime/src/channels/whatsapp/open.ts +3 -0
  323. package/templates/collections-agent/packages/agent-runtime/src/channels/whatsapp/present.ts +8 -12
  324. package/templates/collections-agent/packages/agent-runtime/src/channels/whatsapp/run.ts +8 -4
  325. package/templates/collections-agent/packages/agent-runtime/src/channels/whatsapp/session.ts +12 -9
  326. package/templates/collections-agent/packages/agent-runtime/src/cli.ts +30 -4
  327. package/templates/collections-agent/packages/agent-runtime/src/commands/check.ts +18 -2
  328. package/templates/collections-agent/packages/agent-runtime/src/commands/decide.ts +13 -4
  329. package/templates/collections-agent/packages/agent-runtime/src/commands/eval.ts +7 -2
  330. package/templates/collections-agent/packages/agent-runtime/src/commands/inspect.ts +11 -13
  331. package/templates/collections-agent/packages/agent-runtime/src/commands/poll-whatsapp.ts +32 -24
  332. package/templates/collections-agent/packages/agent-runtime/src/commands/poll.ts +12 -5
  333. package/templates/collections-agent/packages/agent-runtime/src/commands/rerun.ts +83 -10
  334. package/templates/collections-agent/packages/agent-runtime/src/commands/resume.ts +2 -1
  335. package/templates/collections-agent/packages/agent-runtime/src/commands/start-whatsapp.ts +10 -5
  336. package/templates/collections-agent/packages/agent-runtime/src/commands/start.ts +48 -17
  337. package/templates/collections-agent/packages/agent-runtime/src/commands/verify.ts +37 -12
  338. package/templates/collections-agent/packages/agent-runtime/src/commands/webhook.ts +11 -3
  339. package/templates/collections-agent/packages/agent-runtime/src/default-kit.ts +52 -22
  340. package/templates/collections-agent/packages/agent-runtime/src/env.ts +64 -0
  341. package/templates/collections-agent/packages/agent-runtime/src/index.ts +2 -0
  342. package/templates/collections-agent/packages/agent-runtime/src/inspect.ts +81 -10
  343. package/templates/collections-agent/packages/agent-runtime/src/kit.ts +34 -12
  344. package/templates/collections-agent/packages/agent-runtime/src/outcome.ts +118 -0
  345. package/templates/collections-agent/packages/agent-runtime/src/poll.ts +7 -7
  346. package/templates/collections-agent/packages/agent-runtime/src/runs.ts +51 -0
  347. package/templates/collections-agent/packages/agent-runtime/src/scenarios.ts +55 -8
  348. package/templates/collections-agent/packages/agent-runtime/src/setup.ts +75 -5
  349. package/templates/collections-agent/packages/agent-runtime/src/terminal.ts +71 -33
  350. package/templates/collections-agent/packages/agent-runtime/test/env-names.test.ts +56 -0
  351. package/templates/collections-agent/packages/agent-runtime/test/inspect-mandate-status.test.ts +80 -0
  352. package/templates/collections-agent/packages/agent-runtime/test/inspect.test.ts +63 -2
  353. package/templates/collections-agent/packages/agent-runtime/test/outcome.test.ts +72 -0
  354. package/templates/collections-agent/packages/agent-runtime/test/poll-payer.test.ts +64 -0
  355. package/templates/collections-agent/packages/agent-runtime/test/rerun-not-replayed.test.ts +46 -0
  356. package/templates/collections-agent/packages/agent-runtime/test/transition-line.test.ts +29 -0
  357. package/templates/collections-agent/packages/agent-runtime/test/verify-cli.test.ts +99 -6
  358. package/templates/collections-agent/packages/agent-runtime/test/whatsapp-rules.test.ts +8 -0
  359. package/templates/collections-agent/packages/agent-runtime/test/whatsapp-session.test.ts +77 -0
  360. package/templates/collections-agent/packages/agent-runtime/test/whatsapp-status-replies.test.ts +27 -1
  361. package/templates/hello-agent/README.md +2 -2
  362. package/templates/hello-agent/agents/hello-agent/README.md +6 -0
  363. package/templates/hello-agent/agents/hello-agent/SYSTEM_PROMPT.md +27 -13
  364. package/templates/hello-agent/agents/hello-agent/agent.yaml +2 -1
  365. package/templates/hello-agent/agents/hello-agent/evals/adversarial/exfiltration.transcript.jsonl +1 -1
  366. package/templates/hello-agent/agents/hello-agent/evals/adversarial/prompt-injection.transcript.jsonl +1 -1
  367. package/templates/hello-agent/agents/hello-agent/mandate.example.json +1 -1
  368. package/templates/hello-agent/agents/hello-agent/scenarios/happy-path.json +1 -1
  369. package/templates/hello-agent/agents/hello-agent/scenarios/happy-path.transcript.jsonl +1 -1
  370. package/templates/hello-agent/agents/hello-agent/scenarios/prompt-injection.json +1 -1
  371. package/templates/hello-agent/agents/hello-agent/scenarios/prompt-injection.transcript.jsonl +1 -1
  372. package/templates/hello-agent/agents/hello-agent/src/bills.ts +9 -5
  373. package/templates/hello-agent/agents/hello-agent/src/kit.ts +4 -1
  374. package/templates/hello-agent/agents/hello-agent/tools.json +1 -1
  375. package/templates/hello-agent/packages/agent-core/README.md +21 -2
  376. package/templates/hello-agent/packages/agent-core/package.json +1 -1
  377. package/templates/hello-agent/packages/agent-core/src/agent.ts +33 -6
  378. package/templates/hello-agent/packages/agent-core/src/api/charge-rail.ts +15 -1
  379. package/templates/hello-agent/packages/agent-core/src/api/rail.ts +11 -5
  380. package/templates/hello-agent/packages/agent-core/src/api/sandbox-payer.ts +36 -0
  381. package/templates/hello-agent/packages/agent-core/src/bundle.ts +2 -0
  382. package/templates/hello-agent/packages/agent-core/src/channels.ts +18 -8
  383. package/templates/hello-agent/packages/agent-core/src/check.ts +25 -3
  384. package/templates/hello-agent/packages/agent-core/src/engine.ts +90 -9
  385. package/templates/hello-agent/packages/agent-core/src/escalate.ts +10 -0
  386. package/templates/hello-agent/packages/agent-core/src/index.ts +3 -0
  387. package/templates/hello-agent/packages/agent-core/src/language.ts +52 -0
  388. package/templates/hello-agent/packages/agent-core/src/locale.ts +88 -0
  389. package/templates/hello-agent/packages/agent-core/src/manifest.ts +4 -1
  390. package/templates/hello-agent/packages/agent-core/src/rail.ts +29 -1
  391. package/templates/hello-agent/packages/agent-core/src/receipt-verification.ts +30 -2
  392. package/templates/hello-agent/packages/agent-core/src/secrets.ts +53 -8
  393. package/templates/hello-agent/packages/agent-core/src/state-machine.ts +14 -0
  394. package/templates/hello-agent/packages/agent-core/src/strings.ts +175 -0
  395. package/templates/hello-agent/packages/agent-core/src/stubs/charge-rail.ts +15 -2
  396. package/templates/hello-agent/packages/agent-core/src/stubs/rail.ts +7 -4
  397. package/templates/hello-agent/packages/agent-core/src/types.ts +15 -2
  398. package/templates/hello-agent/packages/agent-core/test/actor-on-the-wire.test.ts +144 -0
  399. package/templates/hello-agent/packages/agent-core/test/attempt-replay.test.ts +2 -2
  400. package/templates/hello-agent/packages/agent-core/test/engine.test.ts +23 -0
  401. package/templates/hello-agent/packages/agent-core/test/helpers.ts +1 -1
  402. package/templates/hello-agent/packages/agent-core/test/language.test.ts +40 -0
  403. package/templates/hello-agent/packages/agent-core/test/locale.test.ts +137 -0
  404. package/templates/hello-agent/packages/agent-core/test/mandate-status.test.ts +2 -2
  405. package/templates/hello-agent/packages/agent-core/test/manifest.test.ts +2 -2
  406. package/templates/hello-agent/packages/agent-core/test/rail-errors.test.ts +74 -0
  407. package/templates/hello-agent/packages/agent-core/test/receipt-read-verification.test.ts +32 -0
  408. package/templates/hello-agent/packages/agent-core/test/receivables.test.ts +49 -0
  409. package/templates/hello-agent/packages/agent-core/test/recorded-turns.ts +29 -0
  410. package/templates/hello-agent/packages/agent-core/test/secrets.test.ts +40 -1
  411. package/templates/hello-agent/packages/agent-runtime/README.md +31 -4
  412. package/templates/hello-agent/packages/agent-runtime/src/channels/rules.ts +4 -2
  413. package/templates/hello-agent/packages/agent-runtime/src/channels/whatsapp/emulator.ts +11 -5
  414. package/templates/hello-agent/packages/agent-runtime/src/channels/whatsapp/index.ts +43 -21
  415. package/templates/hello-agent/packages/agent-runtime/src/channels/whatsapp/open.ts +3 -0
  416. package/templates/hello-agent/packages/agent-runtime/src/channels/whatsapp/present.ts +8 -12
  417. package/templates/hello-agent/packages/agent-runtime/src/channels/whatsapp/run.ts +8 -4
  418. package/templates/hello-agent/packages/agent-runtime/src/channels/whatsapp/session.ts +12 -9
  419. package/templates/hello-agent/packages/agent-runtime/src/cli.ts +30 -4
  420. package/templates/hello-agent/packages/agent-runtime/src/commands/check.ts +18 -2
  421. package/templates/hello-agent/packages/agent-runtime/src/commands/decide.ts +13 -4
  422. package/templates/hello-agent/packages/agent-runtime/src/commands/eval.ts +7 -2
  423. package/templates/hello-agent/packages/agent-runtime/src/commands/inspect.ts +11 -13
  424. package/templates/hello-agent/packages/agent-runtime/src/commands/poll-whatsapp.ts +32 -24
  425. package/templates/hello-agent/packages/agent-runtime/src/commands/poll.ts +12 -5
  426. package/templates/hello-agent/packages/agent-runtime/src/commands/rerun.ts +83 -10
  427. package/templates/hello-agent/packages/agent-runtime/src/commands/resume.ts +2 -1
  428. package/templates/hello-agent/packages/agent-runtime/src/commands/start-whatsapp.ts +10 -5
  429. package/templates/hello-agent/packages/agent-runtime/src/commands/start.ts +48 -17
  430. package/templates/hello-agent/packages/agent-runtime/src/commands/verify.ts +37 -12
  431. package/templates/hello-agent/packages/agent-runtime/src/commands/webhook.ts +11 -3
  432. package/templates/hello-agent/packages/agent-runtime/src/default-kit.ts +52 -22
  433. package/templates/hello-agent/packages/agent-runtime/src/env.ts +64 -0
  434. package/templates/hello-agent/packages/agent-runtime/src/index.ts +2 -0
  435. package/templates/hello-agent/packages/agent-runtime/src/inspect.ts +81 -10
  436. package/templates/hello-agent/packages/agent-runtime/src/kit.ts +34 -12
  437. package/templates/hello-agent/packages/agent-runtime/src/outcome.ts +118 -0
  438. package/templates/hello-agent/packages/agent-runtime/src/poll.ts +7 -7
  439. package/templates/hello-agent/packages/agent-runtime/src/runs.ts +51 -0
  440. package/templates/hello-agent/packages/agent-runtime/src/scenarios.ts +55 -8
  441. package/templates/hello-agent/packages/agent-runtime/src/setup.ts +75 -5
  442. package/templates/hello-agent/packages/agent-runtime/src/terminal.ts +71 -33
  443. package/templates/hello-agent/packages/agent-runtime/test/env-names.test.ts +56 -0
  444. package/templates/hello-agent/packages/agent-runtime/test/inspect-mandate-status.test.ts +80 -0
  445. package/templates/hello-agent/packages/agent-runtime/test/inspect.test.ts +63 -2
  446. package/templates/hello-agent/packages/agent-runtime/test/outcome.test.ts +72 -0
  447. package/templates/hello-agent/packages/agent-runtime/test/poll-payer.test.ts +64 -0
  448. package/templates/hello-agent/packages/agent-runtime/test/rerun-not-replayed.test.ts +46 -0
  449. package/templates/hello-agent/packages/agent-runtime/test/transition-line.test.ts +29 -0
  450. package/templates/hello-agent/packages/agent-runtime/test/verify-cli.test.ts +99 -6
  451. package/templates/hello-agent/packages/agent-runtime/test/whatsapp-rules.test.ts +8 -0
  452. package/templates/hello-agent/packages/agent-runtime/test/whatsapp-session.test.ts +77 -0
  453. package/templates/hello-agent/packages/agent-runtime/test/whatsapp-status-replies.test.ts +27 -1
  454. package/templates/kits.lock.json +12 -12
  455. package/templates/supplier-payments-agent/README.md +2 -2
  456. package/templates/supplier-payments-agent/agents/supplier-payments-agent/.env.example +2 -2
  457. package/templates/supplier-payments-agent/agents/supplier-payments-agent/README.md +12 -7
  458. package/templates/supplier-payments-agent/agents/supplier-payments-agent/SYSTEM_PROMPT.md +14 -3
  459. package/templates/supplier-payments-agent/agents/supplier-payments-agent/agent.yaml +2 -1
  460. package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/exfiltration.transcript.jsonl +1 -1
  461. package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/false-authority.transcript.jsonl +1 -1
  462. package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/prompt-injection.transcript.jsonl +1 -1
  463. package/templates/supplier-payments-agent/agents/supplier-payments-agent/mandate.example.json +3 -3
  464. package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/beneficiary-not-allowed.transcript.jsonl +1 -1
  465. package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/cap-exceeded.transcript.jsonl +1 -1
  466. package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/escalated-above-threshold.transcript.jsonl +5 -5
  467. package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/happy-path.transcript.jsonl +1 -1
  468. package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/mandate-revoked.transcript.jsonl +5 -5
  469. package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/partial-batch-failure.json +1 -1
  470. package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/partial-batch-failure.transcript.jsonl +1 -1
  471. package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/prompt-injection.transcript.jsonl +1 -1
  472. package/templates/supplier-payments-agent/agents/supplier-payments-agent/src/kit.ts +37 -26
  473. package/templates/supplier-payments-agent/agents/supplier-payments-agent/src/modules/batch-payout.ts +41 -14
  474. package/templates/supplier-payments-agent/agents/supplier-payments-agent/src/modules/pix-out.ts +12 -3
  475. package/templates/supplier-payments-agent/agents/supplier-payments-agent/src/payables.ts +8 -8
  476. package/templates/supplier-payments-agent/agents/supplier-payments-agent/test/batch.test.ts +75 -10
  477. package/templates/supplier-payments-agent/agents/supplier-payments-agent/test/locale.test.ts +101 -0
  478. package/templates/supplier-payments-agent/agents/supplier-payments-agent/test/run-outcome.test.ts +127 -0
  479. package/templates/supplier-payments-agent/agents/supplier-payments-agent/tools.json +1 -1
  480. package/templates/supplier-payments-agent/packages/agent-core/README.md +21 -2
  481. package/templates/supplier-payments-agent/packages/agent-core/package.json +1 -1
  482. package/templates/supplier-payments-agent/packages/agent-core/src/agent.ts +33 -6
  483. package/templates/supplier-payments-agent/packages/agent-core/src/api/charge-rail.ts +15 -1
  484. package/templates/supplier-payments-agent/packages/agent-core/src/api/rail.ts +11 -5
  485. package/templates/supplier-payments-agent/packages/agent-core/src/api/sandbox-payer.ts +36 -0
  486. package/templates/supplier-payments-agent/packages/agent-core/src/bundle.ts +2 -0
  487. package/templates/supplier-payments-agent/packages/agent-core/src/channels.ts +18 -8
  488. package/templates/supplier-payments-agent/packages/agent-core/src/check.ts +25 -3
  489. package/templates/supplier-payments-agent/packages/agent-core/src/engine.ts +90 -9
  490. package/templates/supplier-payments-agent/packages/agent-core/src/escalate.ts +10 -0
  491. package/templates/supplier-payments-agent/packages/agent-core/src/index.ts +3 -0
  492. package/templates/supplier-payments-agent/packages/agent-core/src/language.ts +52 -0
  493. package/templates/supplier-payments-agent/packages/agent-core/src/locale.ts +88 -0
  494. package/templates/supplier-payments-agent/packages/agent-core/src/manifest.ts +4 -1
  495. package/templates/supplier-payments-agent/packages/agent-core/src/rail.ts +29 -1
  496. package/templates/supplier-payments-agent/packages/agent-core/src/receipt-verification.ts +30 -2
  497. package/templates/supplier-payments-agent/packages/agent-core/src/secrets.ts +53 -8
  498. package/templates/supplier-payments-agent/packages/agent-core/src/state-machine.ts +14 -0
  499. package/templates/supplier-payments-agent/packages/agent-core/src/strings.ts +175 -0
  500. package/templates/supplier-payments-agent/packages/agent-core/src/stubs/charge-rail.ts +15 -2
  501. package/templates/supplier-payments-agent/packages/agent-core/src/stubs/rail.ts +7 -4
  502. package/templates/supplier-payments-agent/packages/agent-core/src/types.ts +15 -2
  503. package/templates/supplier-payments-agent/packages/agent-core/test/actor-on-the-wire.test.ts +144 -0
  504. package/templates/supplier-payments-agent/packages/agent-core/test/attempt-replay.test.ts +2 -2
  505. package/templates/supplier-payments-agent/packages/agent-core/test/engine.test.ts +23 -0
  506. package/templates/supplier-payments-agent/packages/agent-core/test/helpers.ts +1 -1
  507. package/templates/supplier-payments-agent/packages/agent-core/test/language.test.ts +40 -0
  508. package/templates/supplier-payments-agent/packages/agent-core/test/locale.test.ts +137 -0
  509. package/templates/supplier-payments-agent/packages/agent-core/test/mandate-status.test.ts +2 -2
  510. package/templates/supplier-payments-agent/packages/agent-core/test/manifest.test.ts +2 -2
  511. package/templates/supplier-payments-agent/packages/agent-core/test/rail-errors.test.ts +74 -0
  512. package/templates/supplier-payments-agent/packages/agent-core/test/receipt-read-verification.test.ts +32 -0
  513. package/templates/supplier-payments-agent/packages/agent-core/test/receivables.test.ts +49 -0
  514. package/templates/supplier-payments-agent/packages/agent-core/test/recorded-turns.ts +29 -0
  515. package/templates/supplier-payments-agent/packages/agent-core/test/secrets.test.ts +40 -1
  516. package/templates/supplier-payments-agent/packages/agent-runtime/README.md +31 -4
  517. package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/rules.ts +4 -2
  518. package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/whatsapp/emulator.ts +11 -5
  519. package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/whatsapp/index.ts +43 -21
  520. package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/whatsapp/open.ts +3 -0
  521. package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/whatsapp/present.ts +8 -12
  522. package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/whatsapp/run.ts +8 -4
  523. package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/whatsapp/session.ts +12 -9
  524. package/templates/supplier-payments-agent/packages/agent-runtime/src/cli.ts +30 -4
  525. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/check.ts +18 -2
  526. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/decide.ts +13 -4
  527. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/eval.ts +7 -2
  528. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/inspect.ts +11 -13
  529. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/poll-whatsapp.ts +32 -24
  530. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/poll.ts +12 -5
  531. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/rerun.ts +83 -10
  532. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/resume.ts +2 -1
  533. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/start-whatsapp.ts +10 -5
  534. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/start.ts +48 -17
  535. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/verify.ts +37 -12
  536. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/webhook.ts +11 -3
  537. package/templates/supplier-payments-agent/packages/agent-runtime/src/default-kit.ts +52 -22
  538. package/templates/supplier-payments-agent/packages/agent-runtime/src/env.ts +64 -0
  539. package/templates/supplier-payments-agent/packages/agent-runtime/src/index.ts +2 -0
  540. package/templates/supplier-payments-agent/packages/agent-runtime/src/inspect.ts +81 -10
  541. package/templates/supplier-payments-agent/packages/agent-runtime/src/kit.ts +34 -12
  542. package/templates/supplier-payments-agent/packages/agent-runtime/src/outcome.ts +118 -0
  543. package/templates/supplier-payments-agent/packages/agent-runtime/src/poll.ts +7 -7
  544. package/templates/supplier-payments-agent/packages/agent-runtime/src/runs.ts +51 -0
  545. package/templates/supplier-payments-agent/packages/agent-runtime/src/scenarios.ts +55 -8
  546. package/templates/supplier-payments-agent/packages/agent-runtime/src/setup.ts +75 -5
  547. package/templates/supplier-payments-agent/packages/agent-runtime/src/terminal.ts +71 -33
  548. package/templates/supplier-payments-agent/packages/agent-runtime/test/env-names.test.ts +56 -0
  549. package/templates/supplier-payments-agent/packages/agent-runtime/test/inspect-mandate-status.test.ts +80 -0
  550. package/templates/supplier-payments-agent/packages/agent-runtime/test/inspect.test.ts +63 -2
  551. package/templates/supplier-payments-agent/packages/agent-runtime/test/outcome.test.ts +72 -0
  552. package/templates/supplier-payments-agent/packages/agent-runtime/test/poll-payer.test.ts +64 -0
  553. package/templates/supplier-payments-agent/packages/agent-runtime/test/rerun-not-replayed.test.ts +46 -0
  554. package/templates/supplier-payments-agent/packages/agent-runtime/test/transition-line.test.ts +29 -0
  555. package/templates/supplier-payments-agent/packages/agent-runtime/test/verify-cli.test.ts +99 -6
  556. package/templates/supplier-payments-agent/packages/agent-runtime/test/whatsapp-rules.test.ts +8 -0
  557. package/templates/supplier-payments-agent/packages/agent-runtime/test/whatsapp-session.test.ts +77 -0
  558. package/templates/supplier-payments-agent/packages/agent-runtime/test/whatsapp-status-replies.test.ts +27 -1
@@ -57,6 +57,8 @@ export interface InspectAttempt {
57
57
  receipt_id: string | null;
58
58
  money_moved: boolean | null;
59
59
  sandbox: boolean | null;
60
+ /** The rail answered from its record of an earlier presentation: the payment it names was not made by this call. */
61
+ idempotent_replay: boolean;
60
62
  } | null;
61
63
  /** The attempt's outcome as last known, from the call, a later look or a settlement event. */
62
64
  status: string | null;
@@ -71,6 +73,13 @@ export interface InspectAttempt {
71
73
  export interface InspectExecution {
72
74
  execution_id: string;
73
75
  final_state: string;
76
+ /**
77
+ * Settled, and every attempt that settled was answered at dispatch as a
78
+ * replay: the money moved, and this run did not move it. An attempt closed
79
+ * by a later look is never counted as one, because a look re-presents an
80
+ * attempt this run already sent and cannot say whose payment it reads.
81
+ */
82
+ replayed: boolean;
74
83
  mode: string | null;
75
84
  proposed_at: string | null;
76
85
  items: InspectItem[];
@@ -108,6 +117,8 @@ export interface InspectReceipt {
108
117
  money_moved: boolean | null;
109
118
  sandbox: boolean | null;
110
119
  at: string | null;
120
+ /** Every attempt naming this receipt got it back as a replay: the receipt of an earlier payment, read back by this run. */
121
+ replayed: boolean;
111
122
  }
112
123
 
113
124
  /**
@@ -128,7 +139,7 @@ export interface InspectBatch {
128
139
  /** Lines the list held when it was presented. */
129
140
  count: number;
130
141
  /** The lines this bundle holds an execution for, by their position in the list. */
131
- lines: Array<{ index: number; execution_id: string; final_state: string; attested: boolean }>;
142
+ lines: Array<{ index: number; execution_id: string; final_state: string; replayed: boolean; attested: boolean }>;
132
143
  /** How many of the lines carry an approval artifact. The "3" of "3 of 4". */
133
144
  attested: number;
134
145
  /** Positions of the presented list this bundle holds no execution for at all. */
@@ -149,7 +160,10 @@ export interface InspectReport {
149
160
  mandate: {
150
161
  id: string;
151
162
  version: number;
163
+ /** The status in `mandate.snapshot.json`: what the local copy said when the run started. */
152
164
  status: string;
165
+ /** What the status source answered at a gate of this run, when that is the last word the run has on the mandate; null when no gate refused for it, or when a payment executed after the refusal. */
166
+ status_seen: MandateStatusSeen | null;
153
167
  expires_at: string;
154
168
  currency: string;
155
169
  per_tx_cap_minor: number;
@@ -309,6 +323,7 @@ export function assembleTimeline(bundle: ProofBundle): InspectReport {
309
323
  const executions = new Map<string, InspectExecution>();
310
324
  const attemptsBy = new Map<string, Map<string, InspectAttempt>>();
311
325
  const runEvents: InspectReport["run_events"] = [];
326
+ let statusSeen: MandateStatusSeen | null = null;
312
327
 
313
328
  const executionOf = (id: string): InspectExecution => {
314
329
  const existing = executions.get(id);
@@ -316,6 +331,7 @@ export function assembleTimeline(bundle: ProofBundle): InspectReport {
316
331
  const fresh: InspectExecution = {
317
332
  execution_id: id,
318
333
  final_state: "unknown",
334
+ replayed: false,
319
335
  mode: null,
320
336
  proposed_at: null,
321
337
  items: [],
@@ -340,6 +356,7 @@ export function assembleTimeline(bundle: ProofBundle): InspectReport {
340
356
  const p = payload(event);
341
357
 
342
358
  if (!executionId) {
359
+ if (type === "execution.refused_before_draft") statusSeen = mandateStatusSeen(str(p["reason"]), str(p["detail"]), at) ?? statusSeen;
343
360
  const detail = str(p["detail"]) ?? str(p["reason"]) ?? str(event["reason"]) ?? str(event["tool"]) ?? str(event["message"]) ?? "";
344
361
  const tool = str(event["tool"]);
345
362
  runEvents.push({ at, type, detail: redact(tool ? `${tool}: ${detail || String(event["reason"] ?? "")}` : detail) ?? "" });
@@ -363,6 +380,8 @@ export function assembleTimeline(bundle: ProofBundle): InspectReport {
363
380
  const to = str(p["to"]) ?? "unknown";
364
381
  execution.transitions.push({ at: str(p["at"]) ?? at, from: str(p["from"]), to, actor: actorLabel(p["actor"] ?? event["actor"]), reason: str(p["reason"]), detail: redact(str(p["detail"])) });
365
382
  execution.final_state = to;
383
+ // A gate that let a payment through read `active` after whatever an earlier gate saw (a mandate paused and resumed).
384
+ statusSeen = to === "executing" ? null : (mandateStatusSeen(str(p["reason"]), str(p["detail"]), str(p["at"]) ?? at) ?? statusSeen);
366
385
  break;
367
386
  }
368
387
  case "approval.created":
@@ -392,6 +411,7 @@ export function assembleTimeline(bundle: ProofBundle): InspectReport {
392
411
  receipt_id: str(p["receipt_id"]),
393
412
  money_moved: bool(p["money_moved"]),
394
413
  sandbox: bool(p["sandbox"]),
414
+ idempotent_replay: p["idempotent_replay"] === true,
395
415
  };
396
416
  attempt.status = attempt.answer.status;
397
417
  attempt.transaction_id = attempt.answer.transaction_id ?? attempt.transaction_id;
@@ -465,6 +485,15 @@ export function assembleTimeline(bundle: ProofBundle): InspectReport {
465
485
  }
466
486
 
467
487
  for (const [id, attempts] of attemptsBy) executionOf(id).attempts = [...attempts.values()];
488
+ for (const execution of executions.values()) {
489
+ const settled = execution.attempts.filter((a) => a.status === "settled");
490
+ execution.replayed = execution.final_state === "settled" && settled.length > 0 && settled.every((a) => a.answer?.idempotent_replay === true);
491
+ }
492
+ const replayedReceipts = new Set<string>();
493
+ const paidReceipts = new Set<string>();
494
+ for (const execution of executions.values()) {
495
+ for (const a of execution.attempts) if (a.receipt_id) (a.answer?.idempotent_replay ? replayedReceipts : paidReceipts).add(a.receipt_id);
496
+ }
468
497
 
469
498
  const receipts: InspectReceipt[] = bundle.listReceipts().map((file) => {
470
499
  const raw = bundle.readReceipt(file) ?? {};
@@ -478,8 +507,10 @@ export function assembleTimeline(bundle: ProofBundle): InspectReport {
478
507
  money_moved: bool(payment["money_moved"]),
479
508
  sandbox: bool(payment["sandbox"]),
480
509
  at: str(payment["at"]),
510
+ replayed: false,
481
511
  };
482
512
  });
513
+ for (const receipt of receipts) receipt.replayed = replayedReceipts.has(receipt.receipt_id) && !paidReceipts.has(receipt.receipt_id);
483
514
 
484
515
  const transcript = bundle.readTranscript();
485
516
  const toolCalls = transcript.filter((l) => l.kind === "tool_call");
@@ -501,6 +532,7 @@ export function assembleTimeline(bundle: ProofBundle): InspectReport {
501
532
  id: str(snapshot["id"]) ?? "unknown",
502
533
  version: num(snapshot["version"]) ?? 0,
503
534
  status: str(snapshot["status"]) ?? "unknown",
535
+ status_seen: statusSeen,
504
536
  expires_at: str(snapshot["expires_at"]) ?? "unknown",
505
537
  currency,
506
538
  per_tx_cap_minor: num(snapshot["per_tx_cap_minor"]) ?? 0,
@@ -538,7 +570,7 @@ function assembleBatches(executions: InspectExecution[]): InspectBatch[] {
538
570
  if (!binding) continue;
539
571
  const key = `${binding.ref}\u0000${binding.batch_hash}`;
540
572
  const entry = batches.get(key) ?? { ref: binding.ref, batch_hash: binding.batch_hash, count: binding.count, lines: [], attested: 0, missing: [] };
541
- entry.lines.push({ index: binding.index, execution_id: execution.execution_id, final_state: execution.final_state, attested: execution.approval !== null });
573
+ entry.lines.push({ index: binding.index, execution_id: execution.execution_id, final_state: execution.final_state, replayed: execution.replayed, attested: execution.approval !== null });
542
574
  batches.set(key, entry);
543
575
  }
544
576
  for (const entry of batches.values()) {
@@ -597,7 +629,9 @@ function executionLines(execution: InspectExecution): Array<{ at: string; label:
597
629
  if (answer) {
598
630
  const bits = [answer.transaction_id ? `tx ${answer.transaction_id}` : "", answer.receipt_id ? `receipt ${answer.receipt_id}` : "", answer.money_moved !== null ? `money_moved ${answer.money_moved}` : "", answer.sandbox ? "sandbox" : ""].filter(Boolean);
599
631
  const why = [answer.code, answer.message].filter(Boolean).join(": ");
600
- lines.push({ at: answer.at, label: "rail says", text: `${answer.status}${why ? ` ${why}` : ""}`, wrapped: bits.length ? [bits.join(" · ")] : [] });
632
+ const wrapped = bits.length ? [bits.join(" · ")] : [];
633
+ if (answer.idempotent_replay) wrapped.push(REPLAY_NOTE);
634
+ lines.push({ at: answer.at, label: "rail says", text: `${answer.status}${answer.idempotent_replay ? " (replayed)" : ""}${why ? ` ${why}` : ""}`, wrapped });
601
635
  }
602
636
  for (const i of a.instrument) lines.push({ at: i.at, label: "instrument", text: `${a.attempt_id} ${i.status}${i.payable ? ", payable" : ", not payable yet"}${i.due_date ? `, due ${i.due_date}` : ""}`, wrapped: [] });
603
637
  for (const r of a.reconciles) lines.push({ at: r.at, label: "look again", text: `${a.attempt_id} the rail says ${r.found}`, wrapped: [] });
@@ -616,6 +650,8 @@ function executionLines(execution: InspectExecution): Array<{ at: string; label:
616
650
  */
617
651
  export function batchSummary(batch: InspectBatch): string {
618
652
  const bits = [`${batch.attested} of ${batch.count} line(s) attested`];
653
+ const replayed = batch.lines.filter((l) => l.replayed).length;
654
+ if (replayed) bits.push(`${replayed} replayed, paid before and not by this run`);
619
655
  if (batch.lines.length !== batch.attested) bits.push(`${batch.lines.length} with an execution`);
620
656
  if (batch.missing.length) bits.push(`no execution for line(s) ${batch.missing.map((i) => i + 1).join(", ")}`);
621
657
  return bits.join(" · ");
@@ -628,14 +664,48 @@ export function batchLineRows(batch: InspectBatch): string[] {
628
664
  const line = byIndex.get(i);
629
665
  const where = `line ${i + 1} of ${batch.count}`;
630
666
  if (!line) return `${where} — no execution in this bundle: approved as part of this list, and nothing here says it ran`;
631
- return `${where} ${line.execution_id} ${line.final_state} ${line.attested ? "approval artifact present" : "no approval artifact"}`;
667
+ return `${where} ${line.execution_id} ${line.final_state}${line.replayed ? " (replayed)" : ""} ${line.attested ? "approval artifact present" : "no approval artifact"}`;
632
668
  });
633
669
  }
634
670
 
671
+ /** The mandate's status as a gate of the run saw it, and who answered. */
672
+ export interface MandateStatusSeen {
673
+ status: "revoked" | "paused" | "expired";
674
+ /** `api` or `stub`: the status source that answered. Null when the refusal names none: the run's own clock passed `expires_at`, or the bundle predates the source on the detail. */
675
+ source: "api" | "stub" | null;
676
+ at: string;
677
+ }
678
+
679
+ const SEEN_BY_REASON: Record<string, MandateStatusSeen["status"]> = { mandate_revoked: "revoked", mandate_paused: "paused", mandate_expired: "expired" };
680
+
681
+ /** A refusal the mandate gate recorded (`mandateGate` in the core): the reason is the status, and the detail ends with the source that answered. */
682
+ function mandateStatusSeen(reason: string | null, detail: string | null, at: string): MandateStatusSeen | undefined {
683
+ const status = reason ? SEEN_BY_REASON[reason] : undefined;
684
+ if (!status) return undefined;
685
+ const source = /\(source: (api|stub)\)/.exec(detail ?? "")?.[1] as "api" | "stub" | undefined;
686
+ return { status, source: source ?? null, at };
687
+ }
688
+
689
+ /**
690
+ * The header's word for the mandate. The snapshot is the local copy at the
691
+ * start of the run, and it goes on saying `active` under a mandate the API
692
+ * answered was revoked; where a gate of the run heard otherwise, the header
693
+ * says what it heard, from whom, and what the snapshot had said.
694
+ */
695
+ function mandateStatusLabel(m: NonNullable<InspectReport["mandate"]>): string {
696
+ const seen = m.status_seen;
697
+ if (!seen || seen.status === m.status) return m.status;
698
+ const by = seen.source ? `source: ${seen.source}` : seen.status === "expired" ? "by the run's clock" : "source not recorded";
699
+ return `${seen.status} (${by}, ${clock(seen.at)}; ${m.status} in the snapshot at the start of the run)`;
700
+ }
701
+
702
+ /** What a replayed answer means, in the one sentence both renderings print under it. */
703
+ export const REPLAY_NOTE = "idempotent_replay: the rail answered with an earlier payment of this attempt; this run moved no money for it";
704
+
635
705
  /** `execution exe_x — settled` gains ` · folha-2026-10 line 2 of 3` when it is one line of a batch. */
636
706
  function executionHeading(execution: InspectExecution): string {
637
707
  const b = execution.batch;
638
- return `execution ${execution.execution_id} — ${execution.final_state}${b ? ` · ${b.ref} line ${b.index + 1} of ${b.count}` : ""}`;
708
+ return `execution ${execution.execution_id} — ${execution.final_state}${execution.replayed ? " (replayed, not paid by this run)" : ""}${b ? ` · ${b.ref} line ${b.index + 1} of ${b.count}` : ""}`;
639
709
  }
640
710
 
641
711
  export function renderText(report: InspectReport): string {
@@ -646,7 +716,7 @@ export function renderText(report: InspectReport): string {
646
716
  const m = report.mandate;
647
717
  if (m) {
648
718
  const caps = [`per payment ${formatMinor(m.per_tx_cap_minor)}`, m.periodic_cap ? `per ${m.periodic_cap.window} ${formatMinor(m.periodic_cap.cap_minor)}` : "", `lifetime ${formatMinor(m.cap_minor)}`].filter(Boolean);
649
- out.push(` mandate ${m.status}, expires ${m.expires_at} · ${caps.join(" · ")}`);
719
+ out.push(` mandate ${mandateStatusLabel(m)}, expires ${m.expires_at} · ${caps.join(" · ")}`);
650
720
  if (m.beneficiaries.length) out.push(` named payees: ${m.beneficiaries.map((b) => `${b.name} <${b.payee}>`).join(", ")}`);
651
721
  }
652
722
 
@@ -675,7 +745,7 @@ export function renderText(report: InspectReport): string {
675
745
  out.push("");
676
746
  out.push(`receipts (${report.receipts.length})`);
677
747
  for (const receipt of report.receipts) {
678
- const bits = [receipt.state ?? "?", receipt.amount_minor !== null ? formatMinor(receipt.amount_minor) : "", receipt.payee ?? "", receipt.sandbox ? "sandbox" : "", receipt.money_moved === false ? "no money moved" : ""].filter(Boolean);
748
+ const bits = [receipt.state ?? "?", receipt.amount_minor !== null ? formatMinor(receipt.amount_minor) : "", receipt.payee ?? "", receipt.sandbox ? "sandbox" : "", receipt.money_moved === false ? "no money moved" : "", receipt.replayed ? "read back from a replay, not paid by this run" : ""].filter(Boolean);
679
749
  out.push(` ${receipt.receipt_id} ${bits.join(" ")}`);
680
750
  out.push(` ${receipt.file}`);
681
751
  }
@@ -708,7 +778,7 @@ export function renderHtml(report: InspectReport): string {
708
778
  `<h1>${esc(r.run_id)}</h1>`,
709
779
  `<p class="lede">${esc(r.agent ?? "unknown agent")} · mode <b>${esc(r.mode ?? "?")}</b> · rail <b>${esc(r.rail ?? "?")}</b> · mandate <b>${esc(r.mandate_id ?? "?")}</b>${r.mandate_version !== null ? ` v${r.mandate_version}` : ""}${r.started_at ? ` · started ${esc(r.started_at)}` : ""}</p>`,
710
780
  m
711
- ? `<p class="lede">mandate ${esc(m.status)}, expires ${esc(m.expires_at)} · per payment ${esc(formatMinor(m.per_tx_cap_minor))}${m.periodic_cap ? ` · per ${esc(m.periodic_cap.window)} ${esc(formatMinor(m.periodic_cap.cap_minor))}` : ""} · lifetime ${esc(formatMinor(m.cap_minor))}</p>`
781
+ ? `<p class="lede">mandate ${esc(mandateStatusLabel(m))}, expires ${esc(m.expires_at)} · per payment ${esc(formatMinor(m.per_tx_cap_minor))}${m.periodic_cap ? ` · per ${esc(m.periodic_cap.window)} ${esc(formatMinor(m.periodic_cap.cap_minor))}` : ""} · lifetime ${esc(formatMinor(m.cap_minor))}</p>`
712
782
  : "",
713
783
  m && m.beneficiaries.length ? `<p class="lede">named payees: ${m.beneficiaries.map((b) => `${esc(b.name)} <code>${esc(b.payee)}</code>`).join(", ")}</p>` : "",
714
784
  ].join("\n");
@@ -734,7 +804,8 @@ export function renderHtml(report: InspectReport): string {
734
804
  .join("\n");
735
805
  const b = execution.batch;
736
806
  const where = b ? `<span class="state">${esc(`${b.ref} line ${b.index + 1} of ${b.count}`)}</span>` : "";
737
- return `<section><h2>execution ${esc(execution.execution_id)} <span class="state state-${esc(execution.final_state)}">${esc(execution.final_state)}</span> ${where}</h2><table>${rows}</table></section>`;
807
+ const replayed = execution.replayed ? ` <span class="state">replayed, not paid by this run</span>` : "";
808
+ return `<section><h2>execution ${esc(execution.execution_id)} <span class="state state-${esc(execution.final_state)}">${esc(execution.final_state)}</span>${replayed} ${where}</h2><table>${rows}</table></section>`;
738
809
  })
739
810
  .join("\n");
740
811
 
@@ -745,7 +816,7 @@ export function renderHtml(report: InspectReport): string {
745
816
  const receipts = report.receipts.length
746
817
  ? `<table>${report.receipts
747
818
  .map((receipt) => {
748
- const bits = [receipt.state ?? "?", receipt.amount_minor !== null ? formatMinor(receipt.amount_minor) : "", receipt.payee ?? "", receipt.sandbox ? "sandbox" : "", receipt.money_moved === false ? "no money moved" : ""].filter(Boolean).join(" · ");
819
+ const bits = [receipt.state ?? "?", receipt.amount_minor !== null ? formatMinor(receipt.amount_minor) : "", receipt.payee ?? "", receipt.sandbox ? "sandbox" : "", receipt.money_moved === false ? "no money moved" : "", receipt.replayed ? "read back from a replay, not paid by this run" : ""].filter(Boolean).join(" · ");
749
820
  return `<tr><td class="k"><code>${esc(receipt.receipt_id)}</code></td><td>${esc(bits)}<div class="sub">${esc(receipt.file)}</div></td></tr>`;
750
821
  })
751
822
  .join("")}</table>`
@@ -15,6 +15,8 @@ import type {
15
15
  LoadedManifest,
16
16
  LocalMandateStatusStub,
17
17
  Guardrails,
18
+ Locale,
19
+ LocaleTable,
18
20
  Mandate,
19
21
  MandateStatusSource,
20
22
  PaymentRail,
@@ -95,12 +97,30 @@ export interface RailBuild {
95
97
  pollIntervalMs?: number;
96
98
  }
97
99
 
100
+ /**
101
+ * What an agent calls the people and the records of a run. None of it is
102
+ * localized, on purpose: who approved is an id in a signed artifact, and an
103
+ * approver that changed with the language would be a different approver.
104
+ */
98
105
  export interface RuntimeLabels {
99
106
  /** Who decides when no `--user` is given: `usr_terminal`, `usr_operator`. */
100
107
  defaultUser: string;
101
108
  /** Who decides inside a scenario or an adversarial case. */
102
109
  evalUser: string;
103
- /** The word for the signed instrument in the banner: `mandato`, `politica`. */
110
+ /** `reconcile`'s finding kind and detail for a sealed outcome the bundle does not hold. */
111
+ missingReceiptKind: string;
112
+ missingReceiptDetail(receiptId: string, runId: string): string;
113
+ /** `resume`'s line for an execution it could not close. */
114
+ stillExecuting(execution: Execution): string;
115
+ }
116
+
117
+ /**
118
+ * The words the runner prints on an agent's behalf, one entry per locale
119
+ * (`kit.strings`). A kit adds keys of its own to the same entries; every key
120
+ * must exist in every locale, which `npm run check` verifies.
121
+ */
122
+ export interface KitStrings {
123
+ /** The word for the signed instrument in the banner: `mandato`, `política`. */
104
124
  mandateWord: string;
105
125
  /** The word for a sealed outcome in the console: `recibo`, `registro`. */
106
126
  receiptWord: string;
@@ -108,15 +128,12 @@ export interface RuntimeLabels {
108
128
  intro: string;
109
129
  /** The interactive prompt. */
110
130
  prompt: string;
111
- /** The question an `awaiting_approval` execution asks at the keyboard. */
131
+ /** The question an `awaiting_approval` execution asks at the keyboard. Its answers are read the same in every locale. */
112
132
  approveQuestion: string;
113
133
  /** What the console says when a dispatch ended with an unknown outcome. */
114
134
  uncertainDispatch: string;
115
- /** `reconcile`'s finding kind and detail for a sealed outcome the bundle does not hold. */
116
- missingReceiptKind: string;
117
- missingReceiptDetail(receiptId: string, runId: string): string;
118
- /** `resume`'s line for an execution it could not close. */
119
- stillExecuting(execution: Execution): string;
135
+ /** Who refuses a blocked execution: "o mandato não autoriza", "the policy does not authorize". */
136
+ notAuthorized: string;
120
137
  /** `await-payer` only: the line printed every few looks while the payer has not acted. */
121
138
  waitingForPayer?(round: number): string;
122
139
  }
@@ -132,6 +149,8 @@ export interface OneShotContext {
132
149
 
133
150
  export interface ConsentContext {
134
151
  agentDir: string;
152
+ /** The run's locale: the consent summary and its question are printed in it. */
153
+ locale: Locale;
135
154
  argv: string[];
136
155
  say(line: string): void;
137
156
  }
@@ -153,6 +172,8 @@ export interface AgentKit {
153
172
  */
154
173
  scenarioRail?: "stub" | "requested";
155
174
  labels: RuntimeLabels;
175
+ /** The words the runner prints for this agent, per locale. */
176
+ strings: LocaleTable<KitStrings>;
156
177
  /** The usage text `--help`, a bad flag and a bad `--now` print. */
157
178
  usage(manifest: LoadedManifest): string;
158
179
  buildRail(ctx: RailContext): RailBuild;
@@ -169,13 +190,13 @@ export interface AgentKit {
169
190
  */
170
191
  executeOnApproval?: boolean;
171
192
  /** The deterministic policy the core runs as its `policyExtension`. `store` is the run's state.db, for a policy that judges durable state of the agent's own (a cart). */
172
- policyExtension?(ctx: { agentDir: string; manifest: LoadedManifest; guardrails: Guardrails; store: StateStore }): PolicyExtension | undefined;
193
+ policyExtension?(ctx: { agentDir: string; manifest: LoadedManifest; guardrails: Guardrails; store: StateStore; locale: () => Locale }): PolicyExtension | undefined;
173
194
  /** The console lines that describe one execution. */
174
195
  describeExecution(execution: Execution, setup: Setup): string[];
175
196
  /** The `--json` body of a one-shot. */
176
197
  oneShotPayload(ctx: OneShotContext): Record<string, unknown>;
177
198
  /** `await-payer` only: what the payer reads when a receivable becomes payable. */
178
- presentInstrument?(execution: Execution, instalment: number, chargeId: string, instrument: ChargeInstrument, tell: (line: string) => void): void;
199
+ presentInstrument?(execution: Execution, instalment: number, chargeId: string, instrument: ChargeInstrument, tell: (line: string) => void, locale: Locale): void;
179
200
  /** `await-payer` only: the one message per outcome the counterparty receives. */
180
201
  announceOutcome?(execution: Execution, setup: Setup, tell: (line: string) => void): boolean;
181
202
  /**
@@ -189,12 +210,13 @@ export interface AgentKit {
189
210
  * close on, or it cannot tell the person at all.
190
211
  *
191
212
  * The name must be one the agent declares in
192
- * `channels/whatsapp/templates.json`; the language is the registry's and is
193
- * not repeated here. `undefined` means this agent has no approved copy for
213
+ * `channels/whatsapp/templates.json`; the language is the conversation's
214
+ * locale's, and the registry declares every template in each. `locale` is
215
+ * there for the variables, which are display text too (a formatted total). `undefined` means this agent has no approved copy for
194
216
  * that outcome, which the caller REPORTS rather than papers over: a person
195
217
  * who was not told was not told.
196
218
  */
197
- outcomeTemplate?(execution: Execution): { template: string; variables: string[] } | undefined;
219
+ outcomeTemplate?(execution: Execution, locale: Locale): { template: string; variables: string[] } | undefined;
198
220
  /**
199
221
  * Work that FOLLOWS an outcome and is not part of it: a sale's service
200
222
  * invoice once the order is `settled`. Runs after `announceOutcome`,
@@ -0,0 +1,118 @@
1
+ /**
2
+ * What a run did, counted from what the engine holds and not from what the
3
+ * model said. A reply is the model's (or a recording's) and may claim a
4
+ * payroll ran when every line was already paid or every line failed; this is
5
+ * the line the terminal prints after it, and the one-shot's exit code.
6
+ *
7
+ * The unit is the payment, not the execution: an execution that paid three
8
+ * bills and failed the fourth closes `failed`, and counts three settled and
9
+ * one failed.
10
+ */
11
+ import { isDeclinedReason, isTerminal, type CoreStrings, type Execution, type ExecutionEngine, type NotRunLine, type StateStore } from "@codespar/agent-core";
12
+
13
+ export interface RunOutcome {
14
+ /** Payments this run settled. */
15
+ settled: number;
16
+ /** Payments the rail failed, executions that failed before any, and lines refused before a draft existed. */
17
+ failed: number;
18
+ /** Denied or expired, or closed by a declined reason (`isDeclinedReason`): somebody said no, or nobody answered or paid in time. */
19
+ declined: number;
20
+ /** Payments an earlier run already made: skipped here, or answered by the API with the earlier payment. */
21
+ already_paid: number;
22
+ /** Executions not yet terminal, plus lines an earlier execution still holds. */
23
+ open: number;
24
+ }
25
+
26
+ /** A request the engine refused before a draft existed (`execution.refused_before_draft`): the gate's own reason and detail. */
27
+ export interface DraftRefusal {
28
+ reason: string;
29
+ detail: string;
30
+ }
31
+
32
+ /**
33
+ * Every refusal before a draft the engine recorded for this run, in order,
34
+ * for the sentence on the terminal and for `--json`. It is NOT what the count
35
+ * is taken from: each tool reports its refused request through `onNotRun`,
36
+ * and that is the one source of the count.
37
+ */
38
+ export function draftRefusals(store: StateStore, runId: string): DraftRefusal[] {
39
+ return store
40
+ .listEvents({ run_id: runId })
41
+ .filter((e) => e.type === "execution.refused_before_draft")
42
+ .map((e) => {
43
+ const payload = e.payload as { reason?: unknown; detail?: unknown };
44
+ return { reason: String(payload.reason ?? "unknown"), detail: String(payload.detail ?? "") };
45
+ });
46
+ }
47
+
48
+ export function refusalLine(refusal: DraftRefusal): string {
49
+ return ` -> refused_before_draft (${refusal.reason}): ${refusal.detail}`;
50
+ }
51
+
52
+ export function runOutcome(executions: readonly Execution[], notRun: readonly NotRunLine[]): RunOutcome {
53
+ const out: RunOutcome = { settled: 0, failed: 0, declined: 0, already_paid: 0, open: 0 };
54
+ for (const e of executions) {
55
+ if (!isTerminal(e.state)) out.open += 1;
56
+ else if (e.state === "denied" || e.state === "expired") out.declined += 1;
57
+ // Closed with no attempt on record: the execution is the one thing to count.
58
+ else if (e.outcomes.length === 0) out[e.state === "settled" ? "settled" : isDeclinedReason(e.reason) ? "declined" : "failed"] += 1;
59
+ else {
60
+ for (const o of e.outcomes) {
61
+ if (o.status === "settled") out[o.replayed === true ? "already_paid" : "settled"] += 1;
62
+ else if (o.status === "failed") out[isDeclinedReason(o.code) ? "declined" : "failed"] += 1;
63
+ else out.open += 1;
64
+ }
65
+ }
66
+ }
67
+ for (const line of notRun) {
68
+ if (line.why === "already_settled") out.already_paid += 1;
69
+ else if (line.why === "refused") out.failed += 1;
70
+ else out.open += 1;
71
+ }
72
+ return out;
73
+ }
74
+
75
+ export function outcomeLine(text: CoreStrings, outcome: RunOutcome): string {
76
+ return text.runOutcome(outcome.settled, outcome.failed, outcome.declined, outcome.already_paid, outcome.open);
77
+ }
78
+
79
+ /** The executions of one run as the engine holds them now, each once. */
80
+ export function runExecutions(engine: ExecutionEngine, runId: string): Execution[] {
81
+ const byId = new Map<string, Execution>();
82
+ for (const e of engine.list()) if (e.run_id === runId) byId.set(e.id, e);
83
+ return [...byId.values()];
84
+ }
85
+
86
+ /**
87
+ * The one place the terminal and the one-shot count a run: the engine's
88
+ * executions of this run plus the lines that created none. The refusals
89
+ * before a draft come back with it, to be said and listed. `say`, when given,
90
+ * receives the count line.
91
+ */
92
+ export function sayOutcome(
93
+ source: { engine: ExecutionEngine; store: StateStore; runId: string; coreStrings: CoreStrings },
94
+ notRun: readonly NotRunLine[],
95
+ say?: (line: string) => void,
96
+ ): { executions: Execution[]; refusals: DraftRefusal[]; outcome: RunOutcome; line: string } {
97
+ const executions = runExecutions(source.engine, source.runId);
98
+ const refusals = draftRefusals(source.store, source.runId);
99
+ const outcome = runOutcome(executions, notRun);
100
+ const line = outcomeLine(source.coreStrings, outcome);
101
+ say?.(line);
102
+ return { executions, refusals, outcome, line };
103
+ }
104
+
105
+ /**
106
+ * The one-shot's exit code. 1 when a payment failed or a line was refused
107
+ * before a draft, and it wins over 3: a run that failed something and left
108
+ * something else `executing` is a failed run, and the line still counts what
109
+ * is open. 3 when nothing failed and an execution OF THIS RUN was left
110
+ * `executing`, whose outcome the rail did not say. 0 otherwise: settled,
111
+ * already paid, still open, and also denied or expired, which are the agent
112
+ * doing its job and are named on the line. A line an earlier run still holds
113
+ * (`in_progress`) is open and exits 0: this run left nothing behind.
114
+ */
115
+ export function outcomeExitCode(outcome: RunOutcome, executions: readonly Execution[] = []): 0 | 1 | 3 {
116
+ if (outcome.failed > 0) return 1;
117
+ return executions.some((e) => e.state === "executing") ? 3 : 0;
118
+ }
@@ -30,9 +30,8 @@ export interface PollOptions extends PollHooks {
30
30
  timeoutMs: number;
31
31
  /** Cap on looks, for a zero-interval (stub) loop: the fixture payer acts within two looks; a third proves nothing changes. */
32
32
  maxRounds?: number;
33
- /** When set, the payer plays once every instalment is payable, or after `payerAfterRounds` looks (a scenario, `--simulate-payer`). */
33
+ /** When set, the payer plays once every instalment is payable (a scenario, `--simulate-payer`), and never before. */
34
34
  payer?: SandboxPayer | undefined;
35
- payerAfterRounds?: number;
36
35
  clock?: () => Date;
37
36
  sleep?: (ms: number) => Promise<void>;
38
37
  }
@@ -85,13 +84,14 @@ export async function pollUntilClosed(engine: ExecutionEngine, executionId: stri
85
84
  rounds += 1;
86
85
  execution = await engine.reconcile(execution.id);
87
86
  await present(execution);
88
- // The sandbox payer plays once every receivable is payable (the QR was shown first, as in the scene), or after a few looks if the
89
- // clearing house is still registering: the API's test route settles a PROCESSING charge too, and on the shared sandbox the
90
- // registration can take minutes. A real payer is not this hook.
87
+ // The sandbox payer plays once every receivable is payable, the QR shown first, as in the scene, and never before. It used to
88
+ // play after a few looks whatever it found, because the API's test route settles a charge still registering; on staging on
89
+ // 2026-09-27 that route settled a charge the issuer had ended in ERROR, with no QR at all, and the scenario called the order
90
+ // settled (OPEN_QUESTIONS §63, ent#1816). A payer can only pay what it can see, so a registration that never ends payable
91
+ // leaves the order open until the wait runs out, or closes it with the issuer's own failure.
91
92
  const issued = execution.outcomes.filter((o) => o.status === "accepted" && o.transaction_id);
92
93
  const allPayable = issued.length > 0 && issued.every((o) => o.instrument?.payable);
93
- const patienceOver = rounds >= (options.payerAfterRounds ?? 5);
94
- if (options.payer && !paidRequested && execution.state === "executing" && issued.length > 0 && issued.length === execution.outcomes.filter((o) => o.status === "accepted").length && (allPayable || patienceOver)) {
94
+ if (options.payer && !paidRequested && execution.state === "executing" && issued.length > 0 && issued.length === execution.outcomes.filter((o) => o.status === "accepted").length && allPayable) {
95
95
  paidRequested = true;
96
96
  for (const outcome of issued) {
97
97
  const result = await options.payer.pay(outcome.transaction_id!, outcome.attempt_id);
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Where a run's proof bundle lives. A run a person made (`npm start`, a
3
+ * scenario pack run by name) is `runs/<run-id>`. `npm run eval` writes dozens
4
+ * per pass, and they used to land beside the person's own, so the folder a
5
+ * person looks in was mostly the suite's. They go to `runs/eval/<run-id>`.
6
+ *
7
+ * A run id is still all `inspect` and `rerun` take: an eval run is found by
8
+ * its id alone, and `eval/<run-id>` is accepted too.
9
+ */
10
+ import { existsSync, readdirSync } from "node:fs";
11
+ import { join } from "node:path";
12
+ import { ProofBundle } from "@codespar/agent-core";
13
+ import type { Agent } from "./agent.js";
14
+ import { runsDir } from "./setup.js";
15
+
16
+ /** The folder name under `runs/` that holds what the eval suite wrote. Never a run id: every run id starts with `run_`. */
17
+ export const EVAL_RUNS = "eval";
18
+
19
+ export function evalRunsDir(agent: Agent, env: NodeJS.ProcessEnv = process.env): string {
20
+ return join(runsDir(agent, env), EVAL_RUNS);
21
+ }
22
+
23
+ /** The bundle of a run by its id, a person's or the eval suite's, and the folder it was found in. */
24
+ export function openRun(agent: Agent, runId: string, env: NodeJS.ProcessEnv = process.env): { bundle: ProofBundle; runsDir: string } | undefined {
25
+ const own = runsDir(agent, env);
26
+ const id = runId.startsWith(`${EVAL_RUNS}/`) ? runId.slice(EVAL_RUNS.length + 1) : runId;
27
+ // The folder itself is not a run, and neither is a path that climbs out of the runs folder.
28
+ if (id === "" || id === EVAL_RUNS || id.includes("/") || id.includes("\\") || id === "." || id === "..") return undefined;
29
+ for (const dir of runId === id ? [own, evalRunsDir(agent, env)] : [evalRunsDir(agent, env)]) {
30
+ const bundle = ProofBundle.open(dir, id);
31
+ if (bundle) return { bundle, runsDir: dir };
32
+ }
33
+ return undefined;
34
+ }
35
+
36
+ /** Run ids in a folder, newest first. Run ids start with a timestamp or a case name, so the order is by name. */
37
+ function idsIn(dir: string): string[] {
38
+ if (!existsSync(dir)) return [];
39
+ return readdirSync(dir, { withFileTypes: true })
40
+ .filter((e) => e.isDirectory() && e.name !== EVAL_RUNS)
41
+ .map((e) => e.name)
42
+ .sort()
43
+ .reverse();
44
+ }
45
+
46
+ /** The runs a person made, and how many the eval suite left beside them. */
47
+ export function listRuns(agent: Agent, env: NodeJS.ProcessEnv = process.env): { dir: string; ids: string[]; evalDir: string; evalCount: number } {
48
+ const dir = runsDir(agent, env);
49
+ const evalDir = evalRunsDir(agent, env);
50
+ return { dir, ids: idsIn(dir), evalDir, evalCount: idsIn(evalDir).length };
51
+ }