@codespar/cli 0.14.1 → 0.17.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 (534) hide show
  1. package/README.md +44 -17
  2. package/dist/commands/audit-replay.js +267 -0
  3. package/dist/commands/audit-replay.js.map +1 -0
  4. package/dist/commands/init.js +28 -0
  5. package/dist/commands/init.js.map +1 -1
  6. package/dist/commands/mandate-verify.js +98 -19
  7. package/dist/commands/mandate-verify.js.map +1 -1
  8. package/dist/index.js +17 -3
  9. package/dist/index.js.map +1 -1
  10. package/dist/mandate-codec.js +31 -20
  11. package/dist/mandate-codec.js.map +1 -1
  12. package/dist/surface.js +4 -1
  13. package/dist/surface.js.map +1 -1
  14. package/package.json +1 -1
  15. package/templates/bills-agent/README.md +8 -5
  16. package/templates/bills-agent/agents/bills-agent/.env.example +3 -3
  17. package/templates/bills-agent/agents/bills-agent/AGENTS.md +1 -1
  18. package/templates/bills-agent/agents/bills-agent/CLAUDE.md +1 -1
  19. package/templates/bills-agent/agents/bills-agent/README.md +62 -22
  20. package/templates/bills-agent/agents/bills-agent/SYSTEM_PROMPT.md +1 -1
  21. package/templates/bills-agent/agents/bills-agent/agent.yaml +2 -2
  22. package/templates/bills-agent/agents/bills-agent/package.json +14 -11
  23. package/templates/bills-agent/agents/bills-agent/src/kit.ts +193 -0
  24. package/templates/bills-agent/agents/bills-agent/test/adversarial.test.ts +8 -7
  25. package/templates/bills-agent/agents/bills-agent/test/check.test.ts +19 -2
  26. package/templates/bills-agent/agents/bills-agent/test/cli.test.ts +72 -24
  27. package/templates/bills-agent/agents/bills-agent/test/fixtures/excursao-300.transcript.jsonl +2 -0
  28. package/templates/bills-agent/agents/bills-agent/test/fixtures/material-400.transcript.jsonl +2 -0
  29. package/templates/bills-agent/agents/bills-agent/test/inspect.test.ts +124 -0
  30. package/templates/bills-agent/agents/bills-agent/test/provider.test.ts +25 -0
  31. package/templates/bills-agent/agents/bills-agent/test/scenarios.test.ts +10 -9
  32. package/templates/bills-agent/agents/bills-agent/tsconfig.json +0 -1
  33. package/templates/bills-agent/package.json +5 -2
  34. package/templates/bills-agent/packages/agent-core/README.md +2 -0
  35. package/templates/bills-agent/packages/agent-core/package.json +1 -1
  36. package/templates/bills-agent/packages/agent-core/src/api/charge-rail.ts +27 -6
  37. package/templates/bills-agent/packages/agent-core/src/api/rail.ts +16 -0
  38. package/templates/bills-agent/packages/agent-core/src/api/sandbox-payer.ts +20 -7
  39. package/templates/bills-agent/packages/agent-core/src/approval.ts +16 -2
  40. package/templates/bills-agent/packages/agent-core/src/bundle.ts +50 -4
  41. package/templates/bills-agent/packages/agent-core/src/channels.ts +140 -0
  42. package/templates/bills-agent/packages/agent-core/src/check.ts +90 -8
  43. package/templates/bills-agent/packages/agent-core/src/clock.ts +42 -0
  44. package/templates/bills-agent/packages/agent-core/src/engine.ts +119 -18
  45. package/templates/bills-agent/packages/agent-core/src/hash.ts +13 -0
  46. package/templates/bills-agent/packages/agent-core/src/index.ts +3 -0
  47. package/templates/bills-agent/packages/agent-core/src/manifest.ts +1 -1
  48. package/templates/bills-agent/packages/agent-core/src/rail.ts +16 -2
  49. package/templates/bills-agent/packages/agent-core/src/receipt-verification.ts +401 -0
  50. package/templates/bills-agent/packages/agent-core/src/state-machine.ts +3 -1
  51. package/templates/bills-agent/packages/agent-core/src/stubs/charge-rail.ts +2 -0
  52. package/templates/bills-agent/packages/agent-core/src/stubs/rail.ts +19 -2
  53. package/templates/bills-agent/packages/agent-core/src/types.ts +28 -0
  54. package/templates/bills-agent/packages/agent-core/test/approval.test.ts +36 -2
  55. package/templates/bills-agent/packages/agent-core/test/bundle.test.ts +85 -0
  56. package/templates/bills-agent/packages/agent-core/test/clock.test.ts +25 -0
  57. package/templates/bills-agent/packages/agent-core/test/engine.test.ts +73 -1
  58. package/templates/bills-agent/packages/agent-core/test/fixtures/staging-receipt-keys.json +18 -0
  59. package/templates/bills-agent/packages/agent-core/test/fixtures/staging-receipt.json +24 -0
  60. package/templates/bills-agent/packages/agent-core/test/helpers.ts +1 -1
  61. package/templates/bills-agent/packages/agent-core/test/manifest.test.ts +2 -2
  62. package/templates/bills-agent/packages/agent-core/test/receipt-verification.test.ts +316 -0
  63. package/templates/bills-agent/packages/agent-core/test/receivables.test.ts +51 -0
  64. package/templates/bills-agent/packages/agent-runtime/README.md +68 -0
  65. package/templates/bills-agent/packages/agent-runtime/bin.mjs +32 -0
  66. package/templates/bills-agent/packages/agent-runtime/package.json +23 -0
  67. package/templates/bills-agent/{agents/bills-agent → packages/agent-runtime}/src/adversarial.ts +36 -44
  68. package/templates/bills-agent/packages/agent-runtime/src/agent.ts +68 -0
  69. package/templates/bills-agent/packages/agent-runtime/src/channels/contact.ts +13 -0
  70. package/templates/bills-agent/packages/agent-runtime/src/channels/index.ts +72 -0
  71. package/templates/bills-agent/packages/agent-runtime/src/channels/rules.ts +120 -0
  72. package/templates/bills-agent/packages/agent-runtime/src/channels/types.ts +124 -0
  73. package/templates/bills-agent/packages/agent-runtime/src/channels/whatsapp/cloud-api.ts +358 -0
  74. package/templates/bills-agent/packages/agent-runtime/src/channels/whatsapp/emulator.ts +206 -0
  75. package/templates/bills-agent/packages/agent-runtime/src/channels/whatsapp/evidence.ts +109 -0
  76. package/templates/bills-agent/packages/agent-runtime/src/channels/whatsapp/index.ts +225 -0
  77. package/templates/bills-agent/packages/agent-runtime/src/channels/whatsapp/open.ts +143 -0
  78. package/templates/bills-agent/packages/agent-runtime/src/channels/whatsapp/present.ts +47 -0
  79. package/templates/bills-agent/packages/agent-runtime/src/channels/whatsapp/run.ts +113 -0
  80. package/templates/bills-agent/packages/agent-runtime/src/channels/whatsapp/session.ts +113 -0
  81. package/templates/bills-agent/packages/agent-runtime/src/cli.ts +98 -0
  82. package/templates/bills-agent/packages/agent-runtime/src/commands/check.ts +15 -0
  83. package/templates/bills-agent/packages/agent-runtime/src/commands/decide.ts +63 -0
  84. package/templates/bills-agent/packages/agent-runtime/src/commands/eval.ts +58 -0
  85. package/templates/bills-agent/packages/agent-runtime/src/commands/inspect.ts +100 -0
  86. package/templates/bills-agent/packages/agent-runtime/src/commands/poll-whatsapp.ts +317 -0
  87. package/templates/bills-agent/packages/agent-runtime/src/commands/poll.ts +144 -0
  88. package/templates/bills-agent/packages/agent-runtime/src/commands/reconcile.ts +42 -0
  89. package/templates/bills-agent/packages/agent-runtime/src/commands/rerun.ts +86 -0
  90. package/templates/bills-agent/packages/agent-runtime/src/commands/resume.ts +43 -0
  91. package/templates/bills-agent/packages/agent-runtime/src/commands/start-whatsapp.ts +131 -0
  92. package/templates/bills-agent/packages/agent-runtime/src/commands/start.ts +245 -0
  93. package/templates/bills-agent/packages/agent-runtime/src/commands/verify.ts +129 -0
  94. package/templates/bills-agent/packages/agent-runtime/src/commands/webhook.ts +39 -0
  95. package/templates/bills-agent/packages/agent-runtime/src/default-kit.ts +83 -0
  96. package/templates/bills-agent/packages/agent-runtime/src/index.ts +12 -0
  97. package/templates/bills-agent/packages/agent-runtime/src/inspect.ts +797 -0
  98. package/templates/bills-agent/packages/agent-runtime/src/kit.ts +206 -0
  99. package/templates/{collections-agent/agents/collections-agent → bills-agent/packages/agent-runtime}/src/poll.ts +22 -11
  100. package/templates/{collections-agent/agents/collections-agent → bills-agent/packages/agent-runtime}/src/scenarios.ts +50 -34
  101. package/templates/bills-agent/{agents/bills-agent → packages/agent-runtime}/src/setup.ts +88 -66
  102. package/templates/bills-agent/packages/agent-runtime/src/terminal.ts +154 -0
  103. package/templates/{collections-agent/agents/collections-agent/channels/webhook/index.ts → bills-agent/packages/agent-runtime/src/webhook.ts} +1 -1
  104. package/templates/bills-agent/packages/agent-runtime/test/inspect.test.ts +336 -0
  105. package/templates/bills-agent/packages/agent-runtime/test/verify-cli.test.ts +127 -0
  106. package/templates/bills-agent/packages/agent-runtime/test/whatsapp-cloud-api.test.ts +232 -0
  107. package/templates/bills-agent/packages/agent-runtime/test/whatsapp-emulator.integration.test.ts +204 -0
  108. package/templates/bills-agent/packages/agent-runtime/test/whatsapp-evidence.test.ts +94 -0
  109. package/templates/bills-agent/packages/agent-runtime/test/whatsapp-rules.test.ts +174 -0
  110. package/templates/bills-agent/packages/agent-runtime/test/whatsapp-session.test.ts +135 -0
  111. package/templates/bills-agent/packages/agent-runtime/tsconfig.json +9 -0
  112. package/templates/bills-agent/vitest.config.ts +1 -1
  113. package/templates/collections-agent/README.md +8 -5
  114. package/templates/collections-agent/agents/collections-agent/.env.example +14 -0
  115. package/templates/collections-agent/agents/collections-agent/AGENTS.md +6 -4
  116. package/templates/collections-agent/agents/collections-agent/CLAUDE.md +6 -4
  117. package/templates/collections-agent/agents/collections-agent/README.md +184 -16
  118. package/templates/collections-agent/agents/collections-agent/agent.yaml +3 -3
  119. package/templates/collections-agent/agents/collections-agent/channels/whatsapp/README.md +111 -0
  120. package/templates/collections-agent/agents/collections-agent/channels/whatsapp/acordo-1042.json +11 -0
  121. package/templates/collections-agent/agents/collections-agent/channels/whatsapp/acordo-1103.json +11 -0
  122. package/templates/collections-agent/agents/collections-agent/channels/whatsapp/templates.json +23 -0
  123. package/templates/collections-agent/agents/collections-agent/package.json +12 -10
  124. package/templates/collections-agent/agents/collections-agent/runbook.md +52 -1
  125. package/templates/collections-agent/agents/collections-agent/src/kit.ts +265 -0
  126. package/templates/collections-agent/agents/collections-agent/test/adversarial.test.ts +9 -8
  127. package/templates/collections-agent/agents/collections-agent/test/check.test.ts +43 -1
  128. package/templates/collections-agent/agents/collections-agent/test/cli.test.ts +56 -18
  129. package/templates/collections-agent/agents/collections-agent/test/fixtures/agreed-1042-awaiting-payer.transcript.jsonl +4 -0
  130. package/templates/collections-agent/agents/collections-agent/test/scenarios.test.ts +11 -10
  131. package/templates/collections-agent/agents/collections-agent/test/webhook.test.ts +4 -7
  132. package/templates/collections-agent/agents/collections-agent/test/whatsapp-poll.test.ts +271 -0
  133. package/templates/collections-agent/agents/collections-agent/test/whatsapp.test.ts +213 -0
  134. package/templates/collections-agent/agents/collections-agent/tsconfig.json +0 -1
  135. package/templates/collections-agent/package.json +3 -1
  136. package/templates/collections-agent/packages/agent-core/README.md +2 -0
  137. package/templates/collections-agent/packages/agent-core/package.json +1 -1
  138. package/templates/collections-agent/packages/agent-core/src/api/charge-rail.ts +27 -6
  139. package/templates/collections-agent/packages/agent-core/src/api/rail.ts +16 -0
  140. package/templates/collections-agent/packages/agent-core/src/api/sandbox-payer.ts +20 -7
  141. package/templates/collections-agent/packages/agent-core/src/approval.ts +16 -2
  142. package/templates/collections-agent/packages/agent-core/src/bundle.ts +50 -4
  143. package/templates/collections-agent/packages/agent-core/src/channels.ts +140 -0
  144. package/templates/collections-agent/packages/agent-core/src/check.ts +90 -8
  145. package/templates/collections-agent/packages/agent-core/src/clock.ts +42 -0
  146. package/templates/collections-agent/packages/agent-core/src/engine.ts +119 -18
  147. package/templates/collections-agent/packages/agent-core/src/hash.ts +13 -0
  148. package/templates/collections-agent/packages/agent-core/src/index.ts +3 -0
  149. package/templates/collections-agent/packages/agent-core/src/manifest.ts +1 -1
  150. package/templates/collections-agent/packages/agent-core/src/rail.ts +16 -2
  151. package/templates/collections-agent/packages/agent-core/src/receipt-verification.ts +401 -0
  152. package/templates/collections-agent/packages/agent-core/src/state-machine.ts +3 -1
  153. package/templates/collections-agent/packages/agent-core/src/stubs/charge-rail.ts +2 -0
  154. package/templates/collections-agent/packages/agent-core/src/stubs/rail.ts +19 -2
  155. package/templates/collections-agent/packages/agent-core/src/types.ts +28 -0
  156. package/templates/collections-agent/packages/agent-core/test/approval.test.ts +36 -2
  157. package/templates/collections-agent/packages/agent-core/test/bundle.test.ts +85 -0
  158. package/templates/collections-agent/packages/agent-core/test/clock.test.ts +25 -0
  159. package/templates/collections-agent/packages/agent-core/test/engine.test.ts +73 -1
  160. package/templates/collections-agent/packages/agent-core/test/fixtures/staging-receipt-keys.json +18 -0
  161. package/templates/collections-agent/packages/agent-core/test/fixtures/staging-receipt.json +24 -0
  162. package/templates/collections-agent/packages/agent-core/test/helpers.ts +1 -1
  163. package/templates/collections-agent/packages/agent-core/test/manifest.test.ts +2 -2
  164. package/templates/collections-agent/packages/agent-core/test/receipt-verification.test.ts +316 -0
  165. package/templates/collections-agent/packages/agent-core/test/receivables.test.ts +51 -0
  166. package/templates/collections-agent/packages/agent-runtime/README.md +68 -0
  167. package/templates/collections-agent/packages/agent-runtime/bin.mjs +32 -0
  168. package/templates/collections-agent/packages/agent-runtime/package.json +23 -0
  169. package/templates/collections-agent/{agents/collections-agent → packages/agent-runtime}/src/adversarial.ts +29 -50
  170. package/templates/collections-agent/packages/agent-runtime/src/agent.ts +68 -0
  171. package/templates/collections-agent/packages/agent-runtime/src/channels/contact.ts +13 -0
  172. package/templates/collections-agent/packages/agent-runtime/src/channels/index.ts +72 -0
  173. package/templates/collections-agent/packages/agent-runtime/src/channels/rules.ts +120 -0
  174. package/templates/collections-agent/packages/agent-runtime/src/channels/types.ts +124 -0
  175. package/templates/collections-agent/packages/agent-runtime/src/channels/whatsapp/cloud-api.ts +358 -0
  176. package/templates/collections-agent/packages/agent-runtime/src/channels/whatsapp/emulator.ts +206 -0
  177. package/templates/collections-agent/packages/agent-runtime/src/channels/whatsapp/evidence.ts +109 -0
  178. package/templates/collections-agent/packages/agent-runtime/src/channels/whatsapp/index.ts +225 -0
  179. package/templates/collections-agent/packages/agent-runtime/src/channels/whatsapp/open.ts +143 -0
  180. package/templates/collections-agent/packages/agent-runtime/src/channels/whatsapp/present.ts +47 -0
  181. package/templates/collections-agent/packages/agent-runtime/src/channels/whatsapp/run.ts +113 -0
  182. package/templates/collections-agent/packages/agent-runtime/src/channels/whatsapp/session.ts +113 -0
  183. package/templates/collections-agent/packages/agent-runtime/src/cli.ts +98 -0
  184. package/templates/collections-agent/packages/agent-runtime/src/commands/check.ts +15 -0
  185. package/templates/collections-agent/packages/agent-runtime/src/commands/decide.ts +63 -0
  186. package/templates/collections-agent/packages/agent-runtime/src/commands/eval.ts +58 -0
  187. package/templates/collections-agent/packages/agent-runtime/src/commands/inspect.ts +100 -0
  188. package/templates/collections-agent/packages/agent-runtime/src/commands/poll-whatsapp.ts +317 -0
  189. package/templates/collections-agent/packages/agent-runtime/src/commands/poll.ts +144 -0
  190. package/templates/collections-agent/packages/agent-runtime/src/commands/reconcile.ts +42 -0
  191. package/templates/collections-agent/packages/agent-runtime/src/commands/rerun.ts +86 -0
  192. package/templates/collections-agent/packages/agent-runtime/src/commands/resume.ts +43 -0
  193. package/templates/collections-agent/packages/agent-runtime/src/commands/start-whatsapp.ts +131 -0
  194. package/templates/collections-agent/packages/agent-runtime/src/commands/start.ts +245 -0
  195. package/templates/collections-agent/packages/agent-runtime/src/commands/verify.ts +129 -0
  196. package/templates/collections-agent/packages/agent-runtime/src/commands/webhook.ts +39 -0
  197. package/templates/collections-agent/packages/agent-runtime/src/default-kit.ts +83 -0
  198. package/templates/collections-agent/packages/agent-runtime/src/index.ts +12 -0
  199. package/templates/collections-agent/packages/agent-runtime/src/inspect.ts +797 -0
  200. package/templates/collections-agent/packages/agent-runtime/src/kit.ts +206 -0
  201. package/templates/collections-agent/packages/agent-runtime/src/poll.ts +105 -0
  202. package/templates/{bills-agent/agents/bills-agent → collections-agent/packages/agent-runtime}/src/scenarios.ts +98 -26
  203. package/templates/collections-agent/packages/agent-runtime/src/setup.ts +229 -0
  204. package/templates/collections-agent/packages/agent-runtime/src/terminal.ts +154 -0
  205. package/templates/collections-agent/packages/agent-runtime/src/webhook.ts +131 -0
  206. package/templates/collections-agent/packages/agent-runtime/test/inspect.test.ts +336 -0
  207. package/templates/collections-agent/packages/agent-runtime/test/verify-cli.test.ts +127 -0
  208. package/templates/collections-agent/packages/agent-runtime/test/whatsapp-cloud-api.test.ts +232 -0
  209. package/templates/collections-agent/packages/agent-runtime/test/whatsapp-emulator.integration.test.ts +204 -0
  210. package/templates/collections-agent/packages/agent-runtime/test/whatsapp-evidence.test.ts +94 -0
  211. package/templates/collections-agent/packages/agent-runtime/test/whatsapp-rules.test.ts +174 -0
  212. package/templates/collections-agent/packages/agent-runtime/test/whatsapp-session.test.ts +135 -0
  213. package/templates/collections-agent/packages/agent-runtime/tsconfig.json +9 -0
  214. package/templates/collections-agent/vitest.config.ts +1 -1
  215. package/templates/hello-agent/LICENSE +21 -0
  216. package/templates/hello-agent/README.md +23 -0
  217. package/templates/hello-agent/_gitignore +10 -0
  218. package/templates/hello-agent/agents/hello-agent/.env.example +5 -0
  219. package/templates/hello-agent/agents/hello-agent/AGENTS.md +15 -0
  220. package/templates/hello-agent/agents/hello-agent/CLAUDE.md +15 -0
  221. package/templates/hello-agent/agents/hello-agent/README.md +33 -0
  222. package/templates/hello-agent/agents/hello-agent/SYSTEM_PROMPT.md +19 -0
  223. package/templates/hello-agent/agents/hello-agent/agent.yaml +19 -0
  224. package/templates/hello-agent/agents/hello-agent/evals/adversarial/beneficiary-swap.json +6 -0
  225. package/templates/hello-agent/agents/hello-agent/evals/adversarial/beneficiary-swap.transcript.jsonl +2 -0
  226. package/templates/hello-agent/agents/hello-agent/evals/adversarial/exfiltration.json +6 -0
  227. package/templates/hello-agent/agents/hello-agent/evals/adversarial/exfiltration.transcript.jsonl +2 -0
  228. package/templates/hello-agent/agents/hello-agent/evals/adversarial/false-authority.json +6 -0
  229. package/templates/hello-agent/agents/hello-agent/evals/adversarial/false-authority.transcript.jsonl +2 -0
  230. package/templates/hello-agent/agents/hello-agent/evals/adversarial/fractioning.json +6 -0
  231. package/templates/hello-agent/agents/hello-agent/evals/adversarial/fractioning.transcript.jsonl +2 -0
  232. package/templates/hello-agent/agents/hello-agent/evals/adversarial/model-total.json +6 -0
  233. package/templates/hello-agent/agents/hello-agent/evals/adversarial/model-total.transcript.jsonl +2 -0
  234. package/templates/hello-agent/agents/hello-agent/evals/adversarial/prompt-injection.json +6 -0
  235. package/templates/hello-agent/agents/hello-agent/evals/adversarial/prompt-injection.transcript.jsonl +2 -0
  236. package/templates/hello-agent/agents/hello-agent/evals/adversarial/webhook-replay.json +6 -0
  237. package/templates/hello-agent/agents/hello-agent/evals/eval.yaml +7 -0
  238. package/templates/hello-agent/agents/hello-agent/guardrails.json +8 -0
  239. package/templates/hello-agent/agents/hello-agent/mandate.example.json +17 -0
  240. package/templates/hello-agent/agents/hello-agent/package.json +19 -0
  241. package/templates/hello-agent/agents/hello-agent/runbook.md +10 -0
  242. package/templates/hello-agent/agents/hello-agent/scenarios/happy-path.json +6 -0
  243. package/templates/hello-agent/agents/hello-agent/scenarios/happy-path.transcript.jsonl +2 -0
  244. package/templates/hello-agent/agents/hello-agent/scenarios/prompt-injection.json +6 -0
  245. package/templates/hello-agent/agents/hello-agent/scenarios/prompt-injection.transcript.jsonl +2 -0
  246. package/templates/hello-agent/agents/hello-agent/src/bills.ts +23 -0
  247. package/templates/hello-agent/agents/hello-agent/src/kit.ts +33 -0
  248. package/templates/hello-agent/agents/hello-agent/tools.json +11 -0
  249. package/templates/hello-agent/agents/hello-agent/tsconfig.json +9 -0
  250. package/templates/hello-agent/package.json +30 -0
  251. package/templates/hello-agent/packages/agent-core/README.md +21 -0
  252. package/templates/hello-agent/packages/agent-core/package.json +24 -0
  253. package/templates/hello-agent/packages/agent-core/src/agent.ts +125 -0
  254. package/templates/hello-agent/packages/agent-core/src/api/charge-rail.ts +175 -0
  255. package/templates/hello-agent/packages/agent-core/src/api/client.ts +53 -0
  256. package/templates/hello-agent/packages/agent-core/src/api/mandate-status.ts +58 -0
  257. package/templates/hello-agent/packages/agent-core/src/api/rail.ts +117 -0
  258. package/templates/hello-agent/packages/agent-core/src/api/sandbox-payer.ts +58 -0
  259. package/templates/hello-agent/packages/agent-core/src/approval.ts +123 -0
  260. package/templates/hello-agent/packages/agent-core/src/bundle.ts +159 -0
  261. package/templates/hello-agent/packages/agent-core/src/channels.ts +140 -0
  262. package/templates/hello-agent/packages/agent-core/src/check.ts +253 -0
  263. package/templates/hello-agent/packages/agent-core/src/clock.ts +42 -0
  264. package/templates/hello-agent/packages/agent-core/src/engine.ts +885 -0
  265. package/templates/hello-agent/packages/agent-core/src/escalate.ts +85 -0
  266. package/templates/hello-agent/packages/agent-core/src/events.ts +40 -0
  267. package/templates/hello-agent/packages/agent-core/src/guardrails.ts +45 -0
  268. package/templates/hello-agent/packages/agent-core/src/hash.ts +62 -0
  269. package/templates/hello-agent/packages/agent-core/src/ids.ts +10 -0
  270. package/templates/hello-agent/packages/agent-core/src/index.ts +32 -0
  271. package/templates/hello-agent/packages/agent-core/src/mandate.ts +100 -0
  272. package/templates/hello-agent/packages/agent-core/src/manifest.ts +76 -0
  273. package/templates/hello-agent/packages/agent-core/src/providers/anthropic.ts +76 -0
  274. package/templates/hello-agent/packages/agent-core/src/providers/replay.ts +63 -0
  275. package/templates/hello-agent/packages/agent-core/src/providers/types.ts +39 -0
  276. package/templates/hello-agent/packages/agent-core/src/rail.ts +101 -0
  277. package/templates/hello-agent/packages/agent-core/src/receipt-verification.ts +401 -0
  278. package/templates/hello-agent/packages/agent-core/src/revocation.ts +30 -0
  279. package/templates/hello-agent/packages/agent-core/src/secrets.ts +30 -0
  280. package/templates/hello-agent/packages/agent-core/src/state/store.ts +307 -0
  281. package/templates/hello-agent/packages/agent-core/src/state-machine.ts +148 -0
  282. package/templates/hello-agent/packages/agent-core/src/stubs/charge-rail.ts +195 -0
  283. package/templates/hello-agent/packages/agent-core/src/stubs/mandate-status.ts +57 -0
  284. package/templates/hello-agent/packages/agent-core/src/stubs/rail.ts +141 -0
  285. package/templates/hello-agent/packages/agent-core/src/tools.ts +55 -0
  286. package/templates/hello-agent/packages/agent-core/src/types.ts +134 -0
  287. package/templates/hello-agent/packages/agent-core/test/approval.test.ts +117 -0
  288. package/templates/hello-agent/packages/agent-core/test/bundle.test.ts +85 -0
  289. package/templates/hello-agent/packages/agent-core/test/clock.test.ts +25 -0
  290. package/templates/hello-agent/packages/agent-core/test/engine.test.ts +596 -0
  291. package/templates/hello-agent/packages/agent-core/test/escalate.test.ts +42 -0
  292. package/templates/hello-agent/packages/agent-core/test/fixtures/staging-receipt-keys.json +18 -0
  293. package/templates/hello-agent/packages/agent-core/test/fixtures/staging-receipt.json +24 -0
  294. package/templates/hello-agent/packages/agent-core/test/helpers.ts +139 -0
  295. package/templates/hello-agent/packages/agent-core/test/mandate-status.test.ts +153 -0
  296. package/templates/hello-agent/packages/agent-core/test/manifest.test.ts +45 -0
  297. package/templates/hello-agent/packages/agent-core/test/receipt-verification.test.ts +316 -0
  298. package/templates/hello-agent/packages/agent-core/test/receivables.test.ts +316 -0
  299. package/templates/hello-agent/packages/agent-core/test/secrets.test.ts +28 -0
  300. package/templates/hello-agent/packages/agent-core/test/state-machine.test.ts +67 -0
  301. package/templates/hello-agent/packages/agent-core/test/transitions.type-test.ts +59 -0
  302. package/templates/hello-agent/packages/agent-core/tsconfig.json +10 -0
  303. package/templates/hello-agent/packages/agent-runtime/README.md +68 -0
  304. package/templates/hello-agent/packages/agent-runtime/bin.mjs +32 -0
  305. package/templates/hello-agent/packages/agent-runtime/package.json +23 -0
  306. package/templates/hello-agent/packages/agent-runtime/src/adversarial.ts +169 -0
  307. package/templates/hello-agent/packages/agent-runtime/src/agent.ts +68 -0
  308. package/templates/hello-agent/packages/agent-runtime/src/channels/contact.ts +13 -0
  309. package/templates/hello-agent/packages/agent-runtime/src/channels/index.ts +72 -0
  310. package/templates/hello-agent/packages/agent-runtime/src/channels/rules.ts +120 -0
  311. package/templates/hello-agent/packages/agent-runtime/src/channels/types.ts +124 -0
  312. package/templates/hello-agent/packages/agent-runtime/src/channels/whatsapp/cloud-api.ts +358 -0
  313. package/templates/hello-agent/packages/agent-runtime/src/channels/whatsapp/emulator.ts +206 -0
  314. package/templates/hello-agent/packages/agent-runtime/src/channels/whatsapp/evidence.ts +109 -0
  315. package/templates/hello-agent/packages/agent-runtime/src/channels/whatsapp/index.ts +225 -0
  316. package/templates/hello-agent/packages/agent-runtime/src/channels/whatsapp/open.ts +143 -0
  317. package/templates/hello-agent/packages/agent-runtime/src/channels/whatsapp/present.ts +47 -0
  318. package/templates/hello-agent/packages/agent-runtime/src/channels/whatsapp/run.ts +113 -0
  319. package/templates/hello-agent/packages/agent-runtime/src/channels/whatsapp/session.ts +113 -0
  320. package/templates/hello-agent/packages/agent-runtime/src/cli.ts +98 -0
  321. package/templates/hello-agent/packages/agent-runtime/src/commands/check.ts +15 -0
  322. package/templates/hello-agent/packages/agent-runtime/src/commands/decide.ts +63 -0
  323. package/templates/hello-agent/packages/agent-runtime/src/commands/eval.ts +58 -0
  324. package/templates/hello-agent/packages/agent-runtime/src/commands/inspect.ts +100 -0
  325. package/templates/hello-agent/packages/agent-runtime/src/commands/poll-whatsapp.ts +317 -0
  326. package/templates/hello-agent/packages/agent-runtime/src/commands/poll.ts +144 -0
  327. package/templates/hello-agent/packages/agent-runtime/src/commands/reconcile.ts +42 -0
  328. package/templates/hello-agent/packages/agent-runtime/src/commands/rerun.ts +86 -0
  329. package/templates/hello-agent/packages/agent-runtime/src/commands/resume.ts +43 -0
  330. package/templates/hello-agent/packages/agent-runtime/src/commands/start-whatsapp.ts +131 -0
  331. package/templates/hello-agent/packages/agent-runtime/src/commands/start.ts +245 -0
  332. package/templates/hello-agent/packages/agent-runtime/src/commands/verify.ts +129 -0
  333. package/templates/hello-agent/packages/agent-runtime/src/commands/webhook.ts +39 -0
  334. package/templates/hello-agent/packages/agent-runtime/src/default-kit.ts +83 -0
  335. package/templates/hello-agent/packages/agent-runtime/src/index.ts +12 -0
  336. package/templates/hello-agent/packages/agent-runtime/src/inspect.ts +797 -0
  337. package/templates/hello-agent/packages/agent-runtime/src/kit.ts +206 -0
  338. package/templates/hello-agent/packages/agent-runtime/src/poll.ts +105 -0
  339. package/templates/hello-agent/packages/agent-runtime/src/scenarios.ts +268 -0
  340. package/templates/hello-agent/packages/agent-runtime/src/setup.ts +229 -0
  341. package/templates/hello-agent/packages/agent-runtime/src/terminal.ts +154 -0
  342. package/templates/hello-agent/packages/agent-runtime/src/webhook.ts +131 -0
  343. package/templates/hello-agent/packages/agent-runtime/test/inspect.test.ts +336 -0
  344. package/templates/hello-agent/packages/agent-runtime/test/verify-cli.test.ts +127 -0
  345. package/templates/hello-agent/packages/agent-runtime/test/whatsapp-cloud-api.test.ts +232 -0
  346. package/templates/hello-agent/packages/agent-runtime/test/whatsapp-emulator.integration.test.ts +204 -0
  347. package/templates/hello-agent/packages/agent-runtime/test/whatsapp-evidence.test.ts +94 -0
  348. package/templates/hello-agent/packages/agent-runtime/test/whatsapp-rules.test.ts +174 -0
  349. package/templates/hello-agent/packages/agent-runtime/test/whatsapp-session.test.ts +135 -0
  350. package/templates/hello-agent/packages/agent-runtime/tsconfig.json +9 -0
  351. package/templates/hello-agent/tsconfig.base.json +16 -0
  352. package/templates/hello-agent/vitest.config.ts +12 -0
  353. package/templates/kits.lock.json +60 -12
  354. package/templates/supplier-payments-agent/LICENSE +21 -0
  355. package/templates/supplier-payments-agent/README.md +23 -0
  356. package/templates/supplier-payments-agent/_gitignore +10 -0
  357. package/templates/supplier-payments-agent/agents/supplier-payments-agent/.env.example +7 -0
  358. package/templates/supplier-payments-agent/agents/supplier-payments-agent/AGENTS.md +21 -0
  359. package/templates/supplier-payments-agent/agents/supplier-payments-agent/CLAUDE.md +21 -0
  360. package/templates/supplier-payments-agent/agents/supplier-payments-agent/README.md +118 -0
  361. package/templates/supplier-payments-agent/agents/supplier-payments-agent/SYSTEM_PROMPT.md +29 -0
  362. package/templates/supplier-payments-agent/agents/supplier-payments-agent/agent.yaml +26 -0
  363. package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/batch-tampering.json +12 -0
  364. package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/batch-tampering.transcript.jsonl +3 -0
  365. package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/beneficiary-swap-mandate.json +9 -0
  366. package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/beneficiary-swap.json +10 -0
  367. package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/beneficiary-swap.transcript.jsonl +2 -0
  368. package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/exfiltration.json +13 -0
  369. package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/exfiltration.transcript.jsonl +3 -0
  370. package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/false-authority.json +9 -0
  371. package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/false-authority.transcript.jsonl +3 -0
  372. package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/fractioning.json +15 -0
  373. package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/fractioning.transcript.jsonl +6 -0
  374. package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/model-total.json +10 -0
  375. package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/model-total.transcript.jsonl +2 -0
  376. package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/prompt-injection.json +9 -0
  377. package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/prompt-injection.transcript.jsonl +2 -0
  378. package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/webhook-replay.json +9 -0
  379. package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/eval.yaml +9 -0
  380. package/templates/supplier-payments-agent/agents/supplier-payments-agent/guardrails.json +15 -0
  381. package/templates/supplier-payments-agent/agents/supplier-payments-agent/mandate.example.json +70 -0
  382. package/templates/supplier-payments-agent/agents/supplier-payments-agent/package.json +26 -0
  383. package/templates/supplier-payments-agent/agents/supplier-payments-agent/runbook.md +19 -0
  384. package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/beneficiary-not-allowed.json +14 -0
  385. package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/beneficiary-not-allowed.transcript.jsonl +2 -0
  386. package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/cap-exceeded.json +12 -0
  387. package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/cap-exceeded.transcript.jsonl +2 -0
  388. package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/escalated-above-threshold.json +20 -0
  389. package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/escalated-above-threshold.transcript.jsonl +7 -0
  390. package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/happy-path.json +19 -0
  391. package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/happy-path.transcript.jsonl +3 -0
  392. package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/mandate-revoked.json +21 -0
  393. package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/mandate-revoked.transcript.jsonl +9 -0
  394. package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/partial-batch-failure.json +21 -0
  395. package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/partial-batch-failure.transcript.jsonl +3 -0
  396. package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/prompt-injection.json +12 -0
  397. package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/prompt-injection.transcript.jsonl +2 -0
  398. package/templates/supplier-payments-agent/agents/supplier-payments-agent/src/kit.ts +176 -0
  399. package/templates/supplier-payments-agent/agents/supplier-payments-agent/src/modules/batch-payout.ts +345 -0
  400. package/templates/supplier-payments-agent/agents/supplier-payments-agent/src/modules/pix-out.ts +118 -0
  401. package/templates/supplier-payments-agent/agents/supplier-payments-agent/src/payables.ts +76 -0
  402. package/templates/supplier-payments-agent/agents/supplier-payments-agent/test/adversarial.test.ts +53 -0
  403. package/templates/supplier-payments-agent/agents/supplier-payments-agent/test/batch.test.ts +384 -0
  404. package/templates/supplier-payments-agent/agents/supplier-payments-agent/test/check.test.ts +109 -0
  405. package/templates/supplier-payments-agent/agents/supplier-payments-agent/test/scenarios.test.ts +81 -0
  406. package/templates/supplier-payments-agent/agents/supplier-payments-agent/tools.json +53 -0
  407. package/templates/supplier-payments-agent/agents/supplier-payments-agent/tsconfig.json +9 -0
  408. package/templates/supplier-payments-agent/package.json +36 -0
  409. package/templates/supplier-payments-agent/packages/agent-core/README.md +21 -0
  410. package/templates/supplier-payments-agent/packages/agent-core/package.json +24 -0
  411. package/templates/supplier-payments-agent/packages/agent-core/src/agent.ts +125 -0
  412. package/templates/supplier-payments-agent/packages/agent-core/src/api/charge-rail.ts +175 -0
  413. package/templates/supplier-payments-agent/packages/agent-core/src/api/client.ts +53 -0
  414. package/templates/supplier-payments-agent/packages/agent-core/src/api/mandate-status.ts +58 -0
  415. package/templates/supplier-payments-agent/packages/agent-core/src/api/rail.ts +117 -0
  416. package/templates/supplier-payments-agent/packages/agent-core/src/api/sandbox-payer.ts +58 -0
  417. package/templates/supplier-payments-agent/packages/agent-core/src/approval.ts +123 -0
  418. package/templates/supplier-payments-agent/packages/agent-core/src/bundle.ts +159 -0
  419. package/templates/supplier-payments-agent/packages/agent-core/src/channels.ts +140 -0
  420. package/templates/supplier-payments-agent/packages/agent-core/src/check.ts +253 -0
  421. package/templates/supplier-payments-agent/packages/agent-core/src/clock.ts +42 -0
  422. package/templates/supplier-payments-agent/packages/agent-core/src/engine.ts +885 -0
  423. package/templates/supplier-payments-agent/packages/agent-core/src/escalate.ts +85 -0
  424. package/templates/supplier-payments-agent/packages/agent-core/src/events.ts +40 -0
  425. package/templates/supplier-payments-agent/packages/agent-core/src/guardrails.ts +45 -0
  426. package/templates/supplier-payments-agent/packages/agent-core/src/hash.ts +62 -0
  427. package/templates/supplier-payments-agent/packages/agent-core/src/ids.ts +10 -0
  428. package/templates/supplier-payments-agent/packages/agent-core/src/index.ts +32 -0
  429. package/templates/supplier-payments-agent/packages/agent-core/src/mandate.ts +100 -0
  430. package/templates/supplier-payments-agent/packages/agent-core/src/manifest.ts +76 -0
  431. package/templates/supplier-payments-agent/packages/agent-core/src/providers/anthropic.ts +76 -0
  432. package/templates/supplier-payments-agent/packages/agent-core/src/providers/replay.ts +63 -0
  433. package/templates/supplier-payments-agent/packages/agent-core/src/providers/types.ts +39 -0
  434. package/templates/supplier-payments-agent/packages/agent-core/src/rail.ts +101 -0
  435. package/templates/supplier-payments-agent/packages/agent-core/src/receipt-verification.ts +401 -0
  436. package/templates/supplier-payments-agent/packages/agent-core/src/revocation.ts +30 -0
  437. package/templates/supplier-payments-agent/packages/agent-core/src/secrets.ts +30 -0
  438. package/templates/supplier-payments-agent/packages/agent-core/src/state/store.ts +307 -0
  439. package/templates/supplier-payments-agent/packages/agent-core/src/state-machine.ts +148 -0
  440. package/templates/supplier-payments-agent/packages/agent-core/src/stubs/charge-rail.ts +195 -0
  441. package/templates/supplier-payments-agent/packages/agent-core/src/stubs/mandate-status.ts +57 -0
  442. package/templates/supplier-payments-agent/packages/agent-core/src/stubs/rail.ts +141 -0
  443. package/templates/supplier-payments-agent/packages/agent-core/src/tools.ts +55 -0
  444. package/templates/supplier-payments-agent/packages/agent-core/src/types.ts +134 -0
  445. package/templates/supplier-payments-agent/packages/agent-core/test/approval.test.ts +117 -0
  446. package/templates/supplier-payments-agent/packages/agent-core/test/bundle.test.ts +85 -0
  447. package/templates/supplier-payments-agent/packages/agent-core/test/clock.test.ts +25 -0
  448. package/templates/supplier-payments-agent/packages/agent-core/test/engine.test.ts +596 -0
  449. package/templates/supplier-payments-agent/packages/agent-core/test/escalate.test.ts +42 -0
  450. package/templates/supplier-payments-agent/packages/agent-core/test/fixtures/staging-receipt-keys.json +18 -0
  451. package/templates/supplier-payments-agent/packages/agent-core/test/fixtures/staging-receipt.json +24 -0
  452. package/templates/supplier-payments-agent/packages/agent-core/test/helpers.ts +139 -0
  453. package/templates/supplier-payments-agent/packages/agent-core/test/mandate-status.test.ts +153 -0
  454. package/templates/supplier-payments-agent/packages/agent-core/test/manifest.test.ts +45 -0
  455. package/templates/supplier-payments-agent/packages/agent-core/test/receipt-verification.test.ts +316 -0
  456. package/templates/supplier-payments-agent/packages/agent-core/test/receivables.test.ts +316 -0
  457. package/templates/supplier-payments-agent/packages/agent-core/test/secrets.test.ts +28 -0
  458. package/templates/supplier-payments-agent/packages/agent-core/test/state-machine.test.ts +67 -0
  459. package/templates/supplier-payments-agent/packages/agent-core/test/transitions.type-test.ts +59 -0
  460. package/templates/supplier-payments-agent/packages/agent-core/tsconfig.json +10 -0
  461. package/templates/supplier-payments-agent/packages/agent-runtime/README.md +68 -0
  462. package/templates/supplier-payments-agent/packages/agent-runtime/bin.mjs +32 -0
  463. package/templates/supplier-payments-agent/packages/agent-runtime/package.json +23 -0
  464. package/templates/supplier-payments-agent/packages/agent-runtime/src/adversarial.ts +169 -0
  465. package/templates/supplier-payments-agent/packages/agent-runtime/src/agent.ts +68 -0
  466. package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/contact.ts +13 -0
  467. package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/index.ts +72 -0
  468. package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/rules.ts +120 -0
  469. package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/types.ts +124 -0
  470. package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/whatsapp/cloud-api.ts +358 -0
  471. package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/whatsapp/emulator.ts +206 -0
  472. package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/whatsapp/evidence.ts +109 -0
  473. package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/whatsapp/index.ts +225 -0
  474. package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/whatsapp/open.ts +143 -0
  475. package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/whatsapp/present.ts +47 -0
  476. package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/whatsapp/run.ts +113 -0
  477. package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/whatsapp/session.ts +113 -0
  478. package/templates/supplier-payments-agent/packages/agent-runtime/src/cli.ts +98 -0
  479. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/check.ts +15 -0
  480. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/decide.ts +63 -0
  481. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/eval.ts +58 -0
  482. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/inspect.ts +100 -0
  483. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/poll-whatsapp.ts +317 -0
  484. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/poll.ts +144 -0
  485. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/reconcile.ts +42 -0
  486. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/rerun.ts +86 -0
  487. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/resume.ts +43 -0
  488. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/start-whatsapp.ts +131 -0
  489. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/start.ts +245 -0
  490. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/verify.ts +129 -0
  491. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/webhook.ts +39 -0
  492. package/templates/supplier-payments-agent/packages/agent-runtime/src/default-kit.ts +83 -0
  493. package/templates/supplier-payments-agent/packages/agent-runtime/src/index.ts +12 -0
  494. package/templates/supplier-payments-agent/packages/agent-runtime/src/inspect.ts +797 -0
  495. package/templates/supplier-payments-agent/packages/agent-runtime/src/kit.ts +206 -0
  496. package/templates/supplier-payments-agent/packages/agent-runtime/src/poll.ts +105 -0
  497. package/templates/supplier-payments-agent/packages/agent-runtime/src/scenarios.ts +268 -0
  498. package/templates/supplier-payments-agent/packages/agent-runtime/src/setup.ts +229 -0
  499. package/templates/supplier-payments-agent/packages/agent-runtime/src/terminal.ts +154 -0
  500. package/templates/supplier-payments-agent/packages/agent-runtime/src/webhook.ts +131 -0
  501. package/templates/supplier-payments-agent/packages/agent-runtime/test/inspect.test.ts +336 -0
  502. package/templates/supplier-payments-agent/packages/agent-runtime/test/verify-cli.test.ts +127 -0
  503. package/templates/supplier-payments-agent/packages/agent-runtime/test/whatsapp-cloud-api.test.ts +232 -0
  504. package/templates/supplier-payments-agent/packages/agent-runtime/test/whatsapp-emulator.integration.test.ts +204 -0
  505. package/templates/supplier-payments-agent/packages/agent-runtime/test/whatsapp-evidence.test.ts +94 -0
  506. package/templates/supplier-payments-agent/packages/agent-runtime/test/whatsapp-rules.test.ts +174 -0
  507. package/templates/supplier-payments-agent/packages/agent-runtime/test/whatsapp-session.test.ts +135 -0
  508. package/templates/supplier-payments-agent/packages/agent-runtime/tsconfig.json +9 -0
  509. package/templates/supplier-payments-agent/tsconfig.base.json +16 -0
  510. package/templates/supplier-payments-agent/vitest.config.ts +12 -0
  511. package/templates/bills-agent/agents/bills-agent/channels/terminal/index.ts +0 -108
  512. package/templates/bills-agent/agents/bills-agent/src/commands/approve.ts +0 -9
  513. package/templates/bills-agent/agents/bills-agent/src/commands/check.ts +0 -13
  514. package/templates/bills-agent/agents/bills-agent/src/commands/consent.ts +0 -26
  515. package/templates/bills-agent/agents/bills-agent/src/commands/decide.ts +0 -45
  516. package/templates/bills-agent/agents/bills-agent/src/commands/deny.ts +0 -7
  517. package/templates/bills-agent/agents/bills-agent/src/commands/eval.ts +0 -37
  518. package/templates/bills-agent/agents/bills-agent/src/commands/reconcile.ts +0 -38
  519. package/templates/bills-agent/agents/bills-agent/src/commands/rerun.ts +0 -65
  520. package/templates/bills-agent/agents/bills-agent/src/commands/resume.ts +0 -30
  521. package/templates/bills-agent/agents/bills-agent/src/main.ts +0 -185
  522. package/templates/collections-agent/agents/collections-agent/channels/terminal/index.ts +0 -178
  523. package/templates/collections-agent/agents/collections-agent/src/commands/approve.ts +0 -10
  524. package/templates/collections-agent/agents/collections-agent/src/commands/check.ts +0 -13
  525. package/templates/collections-agent/agents/collections-agent/src/commands/decide.ts +0 -48
  526. package/templates/collections-agent/agents/collections-agent/src/commands/deny.ts +0 -7
  527. package/templates/collections-agent/agents/collections-agent/src/commands/eval.ts +0 -39
  528. package/templates/collections-agent/agents/collections-agent/src/commands/poll.ts +0 -35
  529. package/templates/collections-agent/agents/collections-agent/src/commands/reconcile.ts +0 -38
  530. package/templates/collections-agent/agents/collections-agent/src/commands/rerun.ts +0 -55
  531. package/templates/collections-agent/agents/collections-agent/src/commands/resume.ts +0 -30
  532. package/templates/collections-agent/agents/collections-agent/src/commands/webhook.ts +0 -36
  533. package/templates/collections-agent/agents/collections-agent/src/main.ts +0 -193
  534. package/templates/collections-agent/agents/collections-agent/src/setup.ts +0 -250
@@ -0,0 +1,797 @@
1
+ /**
2
+ * Section 11: the proof bundle read back as a timeline. A run folder answers
3
+ * "why could the agent pay this", but only to somebody willing to join six
4
+ * files by hand. `inspect` does the join: who proposed what, who approved it
5
+ * and when, under which version of the mandate, every state transition with
6
+ * its actor, which call went out and what the rail answered, and which
7
+ * receipts came back.
8
+ *
9
+ * It reads the bundle and nothing else — no state.db, no network, no kit — so
10
+ * it works on any agent's run, and on a bundle somebody copied to a laptop
11
+ * that has never seen the agent.
12
+ *
13
+ * Masking is the bundle's: `maskPayee` is what wrote the mandate snapshot and
14
+ * the receipts, and it is applied again here to the payees the event log and
15
+ * the approval artifact still hold raw. It is idempotent on its own output, so
16
+ * a value the bundle already masked passes through unchanged. Nothing here
17
+ * un-masks anything, and the conversation is reported as counts, never as
18
+ * text: a debtor's own words are in `transcript.jsonl` and are not this
19
+ * command's to re-publish.
20
+ */
21
+ import { maskPayee, type ApprovalArtifact, type ExecutionBatch, type ProofBundle } from "@codespar/agent-core";
22
+ import { formatMinor } from "./default-kit.js";
23
+
24
+ export interface InspectItem {
25
+ beneficiary: string;
26
+ /** Masked exactly as the bundle masks it. */
27
+ payee: string;
28
+ amount_minor: number;
29
+ currency: string;
30
+ description: string | null;
31
+ due_date: string | null;
32
+ }
33
+
34
+ export interface InspectTransition {
35
+ at: string;
36
+ from: string | null;
37
+ to: string;
38
+ actor: string;
39
+ reason: string | null;
40
+ detail: string | null;
41
+ }
42
+
43
+ export interface InspectAttempt {
44
+ attempt_id: string;
45
+ idempotency_key: string | null;
46
+ payee: string | null;
47
+ amount_minor: number | null;
48
+ rail: string | null;
49
+ dispatched_at: string | null;
50
+ /** What the rail said when it was called, and ONLY that: a later settlement does not rewrite the answer it gave. */
51
+ answer: {
52
+ at: string;
53
+ status: string;
54
+ code: string | null;
55
+ message: string | null;
56
+ transaction_id: string | null;
57
+ receipt_id: string | null;
58
+ money_moved: boolean | null;
59
+ sandbox: boolean | null;
60
+ } | null;
61
+ /** The attempt's outcome as last known, from the call, a later look or a settlement event. */
62
+ status: string | null;
63
+ transaction_id: string | null;
64
+ receipt_id: string | null;
65
+ /** What a later look at the same attempt found. `reconcile` never re-sends; it reads. */
66
+ reconciles: Array<{ at: string; found: string }>;
67
+ /** The payable legs of a receivable, as the issuer last registered them. */
68
+ instrument: Array<{ at: string; status: string; payable: boolean; due_date: string | null }>;
69
+ }
70
+
71
+ export interface InspectExecution {
72
+ execution_id: string;
73
+ final_state: string;
74
+ mode: string | null;
75
+ proposed_at: string | null;
76
+ items: InspectItem[];
77
+ total_minor: number | null;
78
+ /** What the model claimed the total was. Recorded, never used to pay. */
79
+ model_claimed_total: number | null;
80
+ /** The batch this execution is one line of, when it is one: which list, and where in it. */
81
+ batch: ExecutionBatch | null;
82
+ approval: {
83
+ approval_id: string;
84
+ approver: ApprovalArtifact["approver"];
85
+ approved_at: string;
86
+ expires_at: string;
87
+ items_hash: string;
88
+ /** The set binding as the ARTIFACT carries it, which is the signed copy. */
89
+ batch: ExecutionBatch | null;
90
+ mandate: { id: string; version: number };
91
+ escalation: { trigger: string; detail: string } | null;
92
+ } | null;
93
+ transitions: InspectTransition[];
94
+ attempts: InspectAttempt[];
95
+ receipts: string[];
96
+ /** Lines that are neither a transition nor a rail call: an uncertain outcome, a resumed dispatch, a total the core overrode. */
97
+ notes: Array<{ at: string; type: string; detail: string }>;
98
+ }
99
+
100
+ export interface InspectReceipt {
101
+ receipt_id: string;
102
+ file: string;
103
+ state: string | null;
104
+ amount_minor: number | null;
105
+ payee: string | null;
106
+ money_moved: boolean | null;
107
+ sandbox: boolean | null;
108
+ at: string | null;
109
+ }
110
+
111
+ /**
112
+ * One batch the run touched, assembled from the `batch_hash` its executions
113
+ * carry. This is what lets a reader see "3 of 4 lines" instead of three
114
+ * timelines with nothing to compare against: `count` is what the list held
115
+ * when it was presented for approval, and everything below is measured
116
+ * against it.
117
+ *
118
+ * Keyed by (ref, batch_hash) and not by ref alone. A bundle that holds two
119
+ * lists under one ref is a bundle where the list changed, and collapsing
120
+ * them into one header would hide exactly the thing `batch_hash` exists to
121
+ * show.
122
+ */
123
+ export interface InspectBatch {
124
+ ref: string;
125
+ batch_hash: string;
126
+ /** Lines the list held when it was presented. */
127
+ count: number;
128
+ /** The lines this bundle holds an execution for, by their position in the list. */
129
+ lines: Array<{ index: number; execution_id: string; final_state: string; attested: boolean }>;
130
+ /** How many of the lines carry an approval artifact. The "3" of "3 of 4". */
131
+ attested: number;
132
+ /** Positions of the presented list this bundle holds no execution for at all. */
133
+ missing: number[];
134
+ }
135
+
136
+ export interface InspectReport {
137
+ run: {
138
+ run_id: string;
139
+ agent: string | null;
140
+ mode: string | null;
141
+ rail: string | null;
142
+ mandate_id: string | null;
143
+ mandate_version: number | null;
144
+ started_at: string | null;
145
+ bundle_dir: string;
146
+ };
147
+ mandate: {
148
+ id: string;
149
+ version: number;
150
+ status: string;
151
+ expires_at: string;
152
+ currency: string;
153
+ per_tx_cap_minor: number;
154
+ cap_minor: number;
155
+ periodic_cap: { window: string; cap_minor: number } | null;
156
+ beneficiaries: Array<{ alias: string; name: string; payee: string }>;
157
+ } | null;
158
+ executions: InspectExecution[];
159
+ /** The batches this run's executions belong to. Empty for a run that ran no batch. */
160
+ batches: InspectBatch[];
161
+ /** Events the run holds that belong to no execution: a proposal refused before it was drafted, a tool outside `tools.json`. */
162
+ run_events: Array<{ at: string; type: string; detail: string }>;
163
+ receipts: InspectReceipt[];
164
+ conversation: { turns: number; tool_calls: number; tools: string[]; refused_tools: string[] };
165
+ /** Section 11: `verify.json` is the output of `codespar audit replay`, which is not a registered CLI command. */
166
+ verify: { present: boolean; note: string };
167
+ }
168
+
169
+ export const VERIFY_NOTE =
170
+ "absent by design: verify.json is the output of `codespar audit replay`, which is not a registered command of @codespar/cli, and the spec forbids a second implementation of the hash-chain check (sections 11 and 14.5)";
171
+
172
+ type Event = Record<string, unknown>;
173
+
174
+ function str(value: unknown): string | null {
175
+ return typeof value === "string" ? value : null;
176
+ }
177
+
178
+ function num(value: unknown): number | null {
179
+ return typeof value === "number" ? value : null;
180
+ }
181
+
182
+ function bool(value: unknown): boolean | null {
183
+ return typeof value === "boolean" ? value : null;
184
+ }
185
+
186
+ function payload(event: Event): Record<string, unknown> {
187
+ const p = event["payload"];
188
+ return p !== null && typeof p === "object" ? (p as Record<string, unknown>) : {};
189
+ }
190
+
191
+ /** `agent bills-agent@0.1.0 for usr_x`, `usr_x (person, terminal)`: who acted, in one phrase. */
192
+ export function actorLabel(actor: unknown): string {
193
+ if (actor === null || typeof actor !== "object") return "unknown";
194
+ const a = actor as Record<string, unknown>;
195
+ if (a["type"] === "agent") return `agent ${String(a["agent"])} for ${String(a["on_behalf_of"])}`;
196
+ if (a["type"] === "human") return `${String(a["id"])} (person, ${String(a["channel"])})`;
197
+ if (a["type"] === "person") return `${String(a["id"])} (person, ${String(a["channel"])})`;
198
+ if (a["type"] === "mandate") return `the mandate ${String(a["id"])}`;
199
+ return "unknown";
200
+ }
201
+
202
+ function maskMaybe(value: unknown): string | null {
203
+ const s = str(value);
204
+ return s === null ? null : maskPayee(s);
205
+ }
206
+
207
+ /**
208
+ * A payee key also turns up inside free text: an escalation detail names the
209
+ * payee it escalated on, a refusal names the one it refused. Masking the
210
+ * `payee` field alone would leave the same key readable one line below, so
211
+ * every raw payee the bundle holds is replaced by its mask wherever it
212
+ * appears. Longest first, or a key that is a prefix of another masks it twice.
213
+ */
214
+ export function redactorFor(rawPayees: Iterable<string>): (value: string | null) => string | null {
215
+ const pairs = [...new Set([...rawPayees].filter((p) => p.length > 0 && p !== "*"))]
216
+ .sort((a, b) => b.length - a.length)
217
+ .map((raw) => [raw, maskPayee(raw)] as const)
218
+ .filter(([raw, masked]) => raw !== masked);
219
+ if (!pairs.length) return (value) => value;
220
+ return (value) => {
221
+ if (value === null) return null;
222
+ let out = value;
223
+ for (const [raw, masked] of pairs) out = out.split(raw).join(masked);
224
+ return out;
225
+ };
226
+ }
227
+
228
+ /** Every raw payee this bundle holds: the drafted items, the rail calls, the settlement events and the approval artifacts. */
229
+ function rawPayeesOf(events: Event[], approvals: ApprovalArtifact[]): string[] {
230
+ const out: string[] = [];
231
+ const push = (value: unknown) => {
232
+ const s = str(value);
233
+ if (s) out.push(s);
234
+ };
235
+ for (const event of events) {
236
+ const p = payload(event);
237
+ push(p["payee"]);
238
+ if (Array.isArray(p["items"])) for (const i of p["items"] as Array<Record<string, unknown>>) push(i?.["payee"]);
239
+ }
240
+ for (const artifact of approvals) for (const i of artifact.items) push(i.payee);
241
+ return out;
242
+ }
243
+
244
+ /**
245
+ * A batch binding as the bundle holds it, refusing anything that is not one.
246
+ * A bundle is a file somebody may have edited, so "line 5 of 3" is read as no
247
+ * binding at all rather than rendered as a count a reader would then trust.
248
+ */
249
+ function batchBinding(raw: unknown): ExecutionBatch | null {
250
+ if (raw === null || typeof raw !== "object") return null;
251
+ const b = raw as Record<string, unknown>;
252
+ const ref = str(b["ref"]);
253
+ const hash = str(b["batch_hash"]);
254
+ const index = num(b["index"]);
255
+ const count = num(b["count"]);
256
+ if (!ref || !hash || index === null || count === null) return null;
257
+ if (!Number.isInteger(index) || !Number.isInteger(count) || count < 1 || index < 0 || index >= count) return null;
258
+ return { ref, batch_hash: hash, index, count };
259
+ }
260
+
261
+ function item(raw: unknown, currency: string): InspectItem {
262
+ const i = (raw ?? {}) as Record<string, unknown>;
263
+ return {
264
+ beneficiary: str(i["beneficiary"]) ?? str(i["alias"]) ?? "unknown",
265
+ payee: maskMaybe(i["payee"]) ?? "unknown",
266
+ amount_minor: num(i["amount"]) ?? 0,
267
+ currency: str(i["currency"]) ?? currency,
268
+ description: str(i["description"]),
269
+ due_date: str(i["due_date"]),
270
+ };
271
+ }
272
+
273
+ function attemptOf(attempts: Map<string, InspectAttempt>, attemptId: string): InspectAttempt {
274
+ const existing = attempts.get(attemptId);
275
+ if (existing) return existing;
276
+ const fresh: InspectAttempt = {
277
+ attempt_id: attemptId,
278
+ idempotency_key: null,
279
+ payee: null,
280
+ amount_minor: null,
281
+ rail: null,
282
+ dispatched_at: null,
283
+ answer: null,
284
+ status: null,
285
+ transaction_id: null,
286
+ receipt_id: null,
287
+ reconciles: [],
288
+ instrument: [],
289
+ };
290
+ attempts.set(attemptId, fresh);
291
+ return fresh;
292
+ }
293
+
294
+ /**
295
+ * The bundle, joined. Every field comes from a file in the run folder; a run
296
+ * that is missing one is reported with nulls rather than refused, because an
297
+ * interrupted run is exactly when somebody wants to look at it.
298
+ */
299
+ export function assembleTimeline(bundle: ProofBundle): InspectReport {
300
+ const meta = bundle.readMeta() ?? {};
301
+ const events = bundle.readEvents();
302
+ const approvals = bundle.readApprovals();
303
+ const snapshot = bundle.readMandateSnapshot();
304
+ const currency = str(snapshot?.["currency"]) ?? "BRL";
305
+
306
+ const redact = redactorFor(rawPayeesOf(events, approvals));
307
+ const executions = new Map<string, InspectExecution>();
308
+ const attemptsBy = new Map<string, Map<string, InspectAttempt>>();
309
+ const runEvents: InspectReport["run_events"] = [];
310
+
311
+ const executionOf = (id: string): InspectExecution => {
312
+ const existing = executions.get(id);
313
+ if (existing) return existing;
314
+ const fresh: InspectExecution = {
315
+ execution_id: id,
316
+ final_state: "unknown",
317
+ mode: null,
318
+ proposed_at: null,
319
+ items: [],
320
+ total_minor: null,
321
+ model_claimed_total: null,
322
+ batch: null,
323
+ approval: null,
324
+ transitions: [],
325
+ attempts: [],
326
+ receipts: [],
327
+ notes: [],
328
+ };
329
+ executions.set(id, fresh);
330
+ attemptsBy.set(id, new Map());
331
+ return fresh;
332
+ };
333
+
334
+ for (const event of events) {
335
+ const type = str(event["type"]) ?? "unknown";
336
+ const at = str(event["at"]) ?? "";
337
+ const executionId = str(event["execution_id"]);
338
+ const p = payload(event);
339
+
340
+ if (!executionId) {
341
+ const detail = str(p["detail"]) ?? str(p["reason"]) ?? str(event["reason"]) ?? str(event["tool"]) ?? str(event["message"]) ?? "";
342
+ const tool = str(event["tool"]);
343
+ runEvents.push({ at, type, detail: redact(tool ? `${tool}: ${detail || String(event["reason"] ?? "")}` : detail) ?? "" });
344
+ continue;
345
+ }
346
+
347
+ const execution = executionOf(executionId);
348
+ const attempts = attemptsBy.get(executionId)!;
349
+
350
+ switch (type) {
351
+ case "execution.drafted": {
352
+ execution.proposed_at = at;
353
+ execution.items = Array.isArray(p["items"]) ? (p["items"] as unknown[]).map((i) => item(i, currency)) : [];
354
+ execution.total_minor = num(p["total"]);
355
+ execution.model_claimed_total = num(p["model_claimed_total"]);
356
+ execution.mode = str(p["mode"]);
357
+ execution.batch = batchBinding(p["batch"]);
358
+ break;
359
+ }
360
+ case "execution.transition": {
361
+ const to = str(p["to"]) ?? "unknown";
362
+ 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"])) });
363
+ execution.final_state = to;
364
+ break;
365
+ }
366
+ case "approval.created":
367
+ // The artifact itself is `approval.json`; the event is only the stamp that says when it was written.
368
+ break;
369
+ case "rail.dispatch": {
370
+ const attemptId = str(p["attempt_id"]);
371
+ if (!attemptId) break;
372
+ const attempt = attemptOf(attempts, attemptId);
373
+ attempt.dispatched_at = at;
374
+ attempt.payee = maskMaybe(p["payee"]);
375
+ attempt.amount_minor = num(p["amount"]);
376
+ attempt.rail = str(p["rail"]);
377
+ attempt.idempotency_key = str(p["idempotency_key"]);
378
+ break;
379
+ }
380
+ case "rail.outcome": {
381
+ const attemptId = str(p["attempt_id"]);
382
+ if (!attemptId) break;
383
+ const attempt = attemptOf(attempts, attemptId);
384
+ attempt.answer = {
385
+ at,
386
+ status: str(p["status"]) ?? "unknown",
387
+ code: str(p["code"]),
388
+ message: redact(str(p["message"])),
389
+ transaction_id: str(p["transaction_id"]),
390
+ receipt_id: str(p["receipt_id"]),
391
+ money_moved: bool(p["money_moved"]),
392
+ sandbox: bool(p["sandbox"]),
393
+ };
394
+ attempt.status = attempt.answer.status;
395
+ attempt.transaction_id = attempt.answer.transaction_id ?? attempt.transaction_id;
396
+ attempt.receipt_id = attempt.answer.receipt_id ?? attempt.receipt_id;
397
+ break;
398
+ }
399
+ case "rail.uncertain": {
400
+ const attemptId = str(p["attempt_id"]);
401
+ const attempt = attemptId ? attemptOf(attempts, attemptId) : undefined;
402
+ if (attempt?.answer) {
403
+ attempt.answer.message = redact(str(p["message"])) ?? attempt.answer.message;
404
+ attempt.answer.code = str(p["code"]) ?? attempt.answer.code;
405
+ }
406
+ break;
407
+ }
408
+ case "rail.reconcile": {
409
+ const attemptId = str(p["attempt_id"]);
410
+ if (!attemptId) break;
411
+ const found = str(p["found"]) ?? "unknown";
412
+ const attempt = attemptOf(attempts, attemptId);
413
+ attempt.reconciles.push({ at, found });
414
+ if (found !== "absent" && found !== "unknown") attempt.status = found;
415
+ break;
416
+ }
417
+ case "charge.instrument": {
418
+ const attemptId = str(p["attempt_id"]);
419
+ if (!attemptId) break;
420
+ const attempt = attemptOf(attempts, attemptId);
421
+ attempt.transaction_id = str(p["charge_id"]) ?? attempt.transaction_id;
422
+ attempt.instrument.push({ at, status: str(p["status"]) ?? "unknown", payable: bool(p["payable"]) ?? false, due_date: str(p["due_date"]) });
423
+ break;
424
+ }
425
+ case "receipt.saved": {
426
+ const receiptId = str(p["receipt_id"]);
427
+ if (receiptId && !execution.receipts.includes(receiptId)) execution.receipts.push(receiptId);
428
+ break;
429
+ }
430
+ default: {
431
+ const attemptId = str(p["attempt_id"]);
432
+ if (type.startsWith("commerce.")) {
433
+ // The rail's own settlement event, which may be the ONLY place a receipt id appears (a webhook closed the attempt).
434
+ const receiptId = str(p["receipt_id"]);
435
+ if (attemptId) {
436
+ const attempt = attemptOf(attempts, attemptId);
437
+ attempt.receipt_id = receiptId ?? attempt.receipt_id;
438
+ }
439
+ execution.notes.push({ at, type, detail: [attemptId ? `attempt ${attemptId}` : "", receiptId ? `receipt ${receiptId}` : ""].filter(Boolean).join(" · ") });
440
+ break;
441
+ }
442
+ execution.notes.push({ at, type, detail: redact(str(p["detail"]) ?? str(p["message"]) ?? str(p["reason"]) ?? "") ?? "" });
443
+ }
444
+ }
445
+ }
446
+
447
+ for (const artifact of approvals) {
448
+ const execution = executionOf(artifact.execution_id);
449
+ execution.approval = {
450
+ approval_id: artifact.approval_id,
451
+ approver: artifact.approver,
452
+ approved_at: artifact.approved_at,
453
+ expires_at: artifact.expires_at,
454
+ items_hash: artifact.items_hash,
455
+ batch: batchBinding(artifact.batch),
456
+ mandate: artifact.mandate,
457
+ escalation: artifact.escalation ? { trigger: artifact.escalation.trigger, detail: redact(artifact.escalation.detail) ?? "" } : null,
458
+ };
459
+ // A run whose event log was truncated still knows what was approved.
460
+ if (execution.items.length === 0) execution.items = artifact.items.map((i) => item(i, currency));
461
+ if (!execution.batch) execution.batch = batchBinding(artifact.batch);
462
+ }
463
+
464
+ for (const [id, attempts] of attemptsBy) executionOf(id).attempts = [...attempts.values()];
465
+
466
+ const receipts: InspectReceipt[] = bundle.listReceipts().map((file) => {
467
+ const raw = bundle.readReceipt(file) ?? {};
468
+ const payment = (raw["payment"] ?? {}) as Record<string, unknown>;
469
+ return {
470
+ receipt_id: str(raw["receipt_id"]) ?? file.replace(/\.json$/, ""),
471
+ file: `receipts/${file}`,
472
+ state: str(raw["state"]),
473
+ amount_minor: num(payment["amount_minor"]),
474
+ payee: maskMaybe(payment["payee"]),
475
+ money_moved: bool(payment["money_moved"]),
476
+ sandbox: bool(payment["sandbox"]),
477
+ at: str(payment["at"]),
478
+ };
479
+ });
480
+
481
+ const transcript = bundle.readTranscript();
482
+ const toolCalls = transcript.filter((l) => l.kind === "tool_call");
483
+ const refusedTools = transcript.filter((l) => l.kind === "tool_result" && l["refused"] === true).map((l) => String(l["name"]));
484
+
485
+ return {
486
+ run: {
487
+ run_id: bundle.runId,
488
+ agent: str(meta["agent"]),
489
+ mode: str(meta["mode"]),
490
+ rail: str(meta["rail"]),
491
+ mandate_id: str(meta["mandate_id"]),
492
+ mandate_version: num(meta["mandate_version"]) ?? num(snapshot?.["version"]),
493
+ started_at: str(meta["started_at"]),
494
+ bundle_dir: bundle.dir,
495
+ },
496
+ mandate: snapshot
497
+ ? {
498
+ id: str(snapshot["id"]) ?? "unknown",
499
+ version: num(snapshot["version"]) ?? 0,
500
+ status: str(snapshot["status"]) ?? "unknown",
501
+ expires_at: str(snapshot["expires_at"]) ?? "unknown",
502
+ currency,
503
+ per_tx_cap_minor: num(snapshot["per_tx_cap_minor"]) ?? 0,
504
+ cap_minor: num(snapshot["cap_minor"]) ?? 0,
505
+ periodic_cap: snapshot["periodic_cap"] && typeof snapshot["periodic_cap"] === "object" ? { window: String((snapshot["periodic_cap"] as Record<string, unknown>)["window"]), cap_minor: Number((snapshot["periodic_cap"] as Record<string, unknown>)["cap_minor"]) } : null,
506
+ beneficiaries: Array.isArray(snapshot["beneficiaries"])
507
+ ? (snapshot["beneficiaries"] as Array<Record<string, unknown>>).map((b) => ({ alias: String(b["alias"]), name: String(b["name"]), payee: maskMaybe(b["payee"]) ?? "unknown" }))
508
+ : [],
509
+ }
510
+ : null,
511
+ executions: [...executions.values()],
512
+ batches: assembleBatches([...executions.values()]),
513
+ run_events: runEvents,
514
+ receipts,
515
+ conversation: {
516
+ turns: transcript.filter((l) => l.kind === "user").length,
517
+ tool_calls: toolCalls.length,
518
+ tools: [...new Set(toolCalls.map((l) => String(l["name"])))],
519
+ refused_tools: [...new Set(refusedTools)],
520
+ },
521
+ verify: { present: bundle.hasVerify(), note: VERIFY_NOTE },
522
+ };
523
+ }
524
+
525
+ /**
526
+ * The batches of a run, from the bindings its executions carry. A line is
527
+ * `attested` when the bundle holds its approval artifact: a line a person
528
+ * DENIED has an execution and no artifact, and a line dropped before it ran
529
+ * has neither, so the two are counted apart and both are visible.
530
+ */
531
+ function assembleBatches(executions: InspectExecution[]): InspectBatch[] {
532
+ const batches = new Map<string, InspectBatch>();
533
+ for (const execution of executions) {
534
+ const binding = execution.batch;
535
+ if (!binding) continue;
536
+ const key = `${binding.ref}\u0000${binding.batch_hash}`;
537
+ const entry = batches.get(key) ?? { ref: binding.ref, batch_hash: binding.batch_hash, count: binding.count, lines: [], attested: 0, missing: [] };
538
+ entry.lines.push({ index: binding.index, execution_id: execution.execution_id, final_state: execution.final_state, attested: execution.approval !== null });
539
+ batches.set(key, entry);
540
+ }
541
+ for (const entry of batches.values()) {
542
+ entry.lines.sort((a, b) => a.index - b.index);
543
+ entry.attested = entry.lines.filter((l) => l.attested).length;
544
+ const held = new Set(entry.lines.map((l) => l.index));
545
+ entry.missing = [...Array(entry.count).keys()].filter((i) => !held.has(i));
546
+ }
547
+ return [...batches.values()];
548
+ }
549
+
550
+ // ---- the terminal rendering --------------------------------------------
551
+
552
+ function clock(at: string | null): string {
553
+ if (!at) return "--:--:--";
554
+ const m = /T(\d{2}:\d{2}:\d{2})/.exec(at);
555
+ return m?.[1] ?? at;
556
+ }
557
+
558
+ function approverLabel(approver: ApprovalArtifact["approver"]): string {
559
+ return approver.type === "person" ? `${approver.id} (person, ${approver.channel})` : `the mandate ${approver.id}`;
560
+ }
561
+
562
+ /** One ordered list of lines per execution: the proposal, the decision, every transition, the call and its answer. */
563
+ function executionLines(execution: InspectExecution): Array<{ at: string; label: string; text: string; wrapped: string[] }> {
564
+ const lines: Array<{ at: string; label: string; text: string; wrapped: string[] }> = [];
565
+
566
+ if (execution.proposed_at) {
567
+ const wrapped = execution.items.map((i) => `${i.beneficiary} <${i.payee}> ${formatMinor(i.amount_minor)}${i.description ? ` ${i.description}` : ""}${i.due_date ? ` due ${i.due_date}` : ""}`);
568
+ if (execution.total_minor !== null) {
569
+ wrapped.push(`total ${formatMinor(execution.total_minor)} computed by the core${execution.model_claimed_total !== null ? `; the model said ${formatMinor(execution.model_claimed_total)}` : ""}`);
570
+ }
571
+ lines.push({ at: execution.proposed_at, label: "proposed", text: `${execution.items.length} item(s)${execution.mode ? ` in ${execution.mode} mode` : ""}`, wrapped });
572
+ }
573
+
574
+ const approval = execution.approval;
575
+ if (approval) {
576
+ const wrapped = [`${approval.approval_id} · items_hash ${approval.items_hash}`, `under mandate ${approval.mandate.id} v${approval.mandate.version} · the artifact expires ${clock(approval.expires_at)}`];
577
+ if (approval.batch) wrapped.push(`line ${approval.batch.index + 1} of ${approval.batch.count} of batch ${approval.batch.ref} · batch_hash ${approval.batch.batch_hash}`);
578
+ if (approval.escalation) wrapped.push(`escalated by ${approval.escalation.trigger}: ${approval.escalation.detail}`);
579
+ lines.push({ at: approval.approved_at, label: "approved", text: approverLabel(approval.approver), wrapped });
580
+ }
581
+
582
+ for (const t of execution.transitions) {
583
+ const suffix = [t.reason ? `reason ${t.reason}` : "", t.detail ?? ""].filter(Boolean).join(" · ");
584
+ lines.push({ at: t.at, label: "state", text: `${t.from ?? "-"} -> ${t.to} by ${t.actor}`, wrapped: suffix ? [suffix] : [] });
585
+ }
586
+
587
+ for (const a of execution.attempts) {
588
+ if (a.dispatched_at) {
589
+ const wrapped = a.idempotency_key ? [`idempotency_key ${a.idempotency_key}`] : [];
590
+ lines.push({ at: a.dispatched_at, label: "call out", text: `${a.attempt_id} -> ${a.rail ?? "rail"}${a.amount_minor !== null ? ` ${formatMinor(a.amount_minor)}` : ""}${a.payee ? ` to ${a.payee}` : ""}`, wrapped });
591
+ }
592
+ const answer = a.answer;
593
+ if (answer) {
594
+ 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);
595
+ const why = [answer.code, answer.message].filter(Boolean).join(": ");
596
+ lines.push({ at: answer.at, label: "rail says", text: `${answer.status}${why ? ` ${why}` : ""}`, wrapped: bits.length ? [bits.join(" · ")] : [] });
597
+ }
598
+ 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: [] });
599
+ for (const r of a.reconciles) lines.push({ at: r.at, label: "look again", text: `${a.attempt_id} the rail says ${r.found}`, wrapped: [] });
600
+ }
601
+
602
+ for (const n of execution.notes) lines.push({ at: n.at, label: n.type.startsWith("commerce.") ? "rail event" : "note", text: `${n.type}${n.detail ? ` ${n.detail}` : ""}`, wrapped: [] });
603
+
604
+ return lines.sort((a, b) => (a.at === b.at ? 0 : a.at < b.at ? -1 : 1));
605
+ }
606
+
607
+ /**
608
+ * The batch header, in the words a reader needs: how many lines the approved
609
+ * list held, how many of them this bundle attests, and which positions it
610
+ * holds nothing for. "3 of 4 lines attested" is the sentence; the rest of the
611
+ * block says which 3 and which 4th.
612
+ */
613
+ export function batchSummary(batch: InspectBatch): string {
614
+ const bits = [`${batch.attested} of ${batch.count} line(s) attested`];
615
+ if (batch.lines.length !== batch.attested) bits.push(`${batch.lines.length} with an execution`);
616
+ if (batch.missing.length) bits.push(`no execution for line(s) ${batch.missing.map((i) => i + 1).join(", ")}`);
617
+ return bits.join(" · ");
618
+ }
619
+
620
+ /** One row per position of the presented list, present in the bundle or not. */
621
+ export function batchLineRows(batch: InspectBatch): string[] {
622
+ const byIndex = new Map(batch.lines.map((l) => [l.index, l]));
623
+ return [...Array(batch.count).keys()].map((i) => {
624
+ const line = byIndex.get(i);
625
+ const where = `line ${i + 1} of ${batch.count}`;
626
+ if (!line) return `${where} — no execution in this bundle: approved as part of this list, and nothing here says it ran`;
627
+ return `${where} ${line.execution_id} ${line.final_state} ${line.attested ? "approval artifact present" : "no approval artifact"}`;
628
+ });
629
+ }
630
+
631
+ /** `execution exe_x — settled` gains ` · folha-2026-10 line 2 of 3` when it is one line of a batch. */
632
+ function executionHeading(execution: InspectExecution): string {
633
+ const b = execution.batch;
634
+ return `execution ${execution.execution_id} — ${execution.final_state}${b ? ` · ${b.ref} line ${b.index + 1} of ${b.count}` : ""}`;
635
+ }
636
+
637
+ export function renderText(report: InspectReport): string {
638
+ const out: string[] = [];
639
+ const r = report.run;
640
+ out.push(`${r.run_id}${r.agent ? ` — ${r.agent}` : ""}`);
641
+ out.push(` mode ${r.mode ?? "?"} · rail ${r.rail ?? "?"} · mandate ${r.mandate_id ?? "?"}${r.mandate_version !== null ? ` v${r.mandate_version}` : ""}${r.started_at ? ` · started ${r.started_at}` : ""}`);
642
+ const m = report.mandate;
643
+ if (m) {
644
+ 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);
645
+ out.push(` mandate ${m.status}, expires ${m.expires_at} · ${caps.join(" · ")}`);
646
+ if (m.beneficiaries.length) out.push(` named payees: ${m.beneficiaries.map((b) => `${b.name} <${b.payee}>`).join(", ")}`);
647
+ }
648
+
649
+ for (const batch of report.batches) {
650
+ out.push("");
651
+ out.push(`batch ${batch.ref} — ${batchSummary(batch)}`);
652
+ out.push(` batch_hash ${batch.batch_hash}`);
653
+ for (const row of batchLineRows(batch)) out.push(` ${row}`);
654
+ }
655
+
656
+ for (const execution of report.executions) {
657
+ out.push("");
658
+ out.push(executionHeading(execution));
659
+ for (const line of executionLines(execution)) {
660
+ out.push(` ${clock(line.at)} ${line.label.padEnd(10)} ${line.text}`);
661
+ for (const w of line.wrapped) out.push(` ${" ".repeat(8)} ${" ".repeat(10)} ${w}`);
662
+ }
663
+ }
664
+
665
+ if (report.run_events.length) {
666
+ out.push("");
667
+ out.push("outside any execution");
668
+ for (const e of report.run_events) out.push(` ${clock(e.at)} ${e.type.padEnd(10)} ${e.detail}`);
669
+ }
670
+
671
+ out.push("");
672
+ out.push(`receipts (${report.receipts.length})`);
673
+ for (const receipt of report.receipts) {
674
+ 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);
675
+ out.push(` ${receipt.receipt_id} ${bits.join(" ")}`);
676
+ out.push(` ${receipt.file}`);
677
+ }
678
+ if (!report.receipts.length) out.push(" none");
679
+
680
+ out.push("");
681
+ const c = report.conversation;
682
+ out.push(`conversation: ${c.turns} turn(s), ${c.tool_calls} tool call(s)${c.tools.length ? ` (${c.tools.join(", ")})` : ""}${c.refused_tools.length ? ` · refused: ${c.refused_tools.join(", ")}` : ""}`);
683
+ out.push(`verify.json: ${report.verify.present ? "present" : report.verify.note}`);
684
+ return out.join("\n") + "\n";
685
+ }
686
+
687
+ // ---- the static HTML rendering ------------------------------------------
688
+
689
+ function escapeHtml(value: string): string {
690
+ return value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
691
+ }
692
+
693
+ /**
694
+ * One file, no network: the CSS is inline, there is no script, and nothing is
695
+ * fetched. A bundle inspected on an air-gapped machine renders the same as on
696
+ * a connected one, which is the whole point of a proof you can hand over.
697
+ */
698
+ export function renderHtml(report: InspectReport): string {
699
+ const r = report.run;
700
+ const m = report.mandate;
701
+ const esc = escapeHtml;
702
+
703
+ const header = [
704
+ `<h1>${esc(r.run_id)}</h1>`,
705
+ `<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>`,
706
+ m
707
+ ? `<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>`
708
+ : "",
709
+ m && m.beneficiaries.length ? `<p class="lede">named payees: ${m.beneficiaries.map((b) => `${esc(b.name)} <code>${esc(b.payee)}</code>`).join(", ")}</p>` : "",
710
+ ].join("\n");
711
+
712
+ // The batch header comes before the timelines it is a header FOR: a reader
713
+ // must know the list held four lines before reading the three that ran.
714
+ const batches = report.batches
715
+ .map((batch) => {
716
+ const rows = batchLineRows(batch)
717
+ .map((row) => `<tr><td>${esc(row)}</td></tr>`)
718
+ .join("\n");
719
+ return `<section><h2>batch ${esc(batch.ref)} <span class="state">${esc(batchSummary(batch))}</span></h2><p class="lede">batch_hash <code>${esc(batch.batch_hash)}</code></p><table>${rows}</table></section>`;
720
+ })
721
+ .join("\n");
722
+
723
+ const executions = report.executions
724
+ .map((execution) => {
725
+ const rows = executionLines(execution)
726
+ .map((line) => {
727
+ const extra = line.wrapped.map((w) => `<div class="sub">${esc(w)}</div>`).join("");
728
+ return `<tr><td class="t">${esc(clock(line.at))}</td><td class="k"><span class="tag tag-${esc(line.label.replace(/\s+/g, "-"))}">${esc(line.label)}</span></td><td>${esc(line.text)}${extra}</td></tr>`;
729
+ })
730
+ .join("\n");
731
+ const b = execution.batch;
732
+ const where = b ? `<span class="state">${esc(`${b.ref} line ${b.index + 1} of ${b.count}`)}</span>` : "";
733
+ 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>`;
734
+ })
735
+ .join("\n");
736
+
737
+ const runEvents = report.run_events.length
738
+ ? `<section><h2>outside any execution</h2><table>${report.run_events.map((e) => `<tr><td class="t">${esc(clock(e.at))}</td><td class="k">${esc(e.type)}</td><td>${esc(e.detail)}</td></tr>`).join("")}</table></section>`
739
+ : "";
740
+
741
+ const receipts = report.receipts.length
742
+ ? `<table>${report.receipts
743
+ .map((receipt) => {
744
+ 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(" · ");
745
+ return `<tr><td class="k"><code>${esc(receipt.receipt_id)}</code></td><td>${esc(bits)}<div class="sub">${esc(receipt.file)}</div></td></tr>`;
746
+ })
747
+ .join("")}</table>`
748
+ : "<p class=\"lede\">none</p>";
749
+
750
+ const c = report.conversation;
751
+ const footer = `<p class="lede">conversation: ${c.turns} turn(s), ${c.tool_calls} tool call(s)${c.tools.length ? ` (${esc(c.tools.join(", "))})` : ""}${c.refused_tools.length ? ` · refused: ${esc(c.refused_tools.join(", "))}` : ""}</p><p class="lede">verify.json: ${report.verify.present ? "present" : esc(report.verify.note)}</p><p class="lede">Payees are masked the way the proof bundle masks them. The conversation is reported as counts; its text stays in transcript.jsonl.</p>`;
752
+
753
+ return `<!doctype html>
754
+ <html lang="en">
755
+ <head>
756
+ <meta charset="utf-8">
757
+ <meta name="viewport" content="width=device-width, initial-scale=1">
758
+ <title>${esc(r.run_id)} — CodeSpar proof bundle</title>
759
+ <style>
760
+ :root { color-scheme: light dark; --bg: #fbfbfa; --fg: #1a1a18; --muted: #6b6b63; --line: #e2e2dc; --card: #ffffff; --accent: #2f5d50; }
761
+ @media (prefers-color-scheme: dark) { :root { --bg: #16171a; --fg: #e8e8e4; --muted: #9a9a92; --line: #2c2d31; --card: #1d1e22; --accent: #7fc3ae; } }
762
+ * { box-sizing: border-box; }
763
+ body { margin: 0; padding: 32px 16px 64px; background: var(--bg); color: var(--fg); font: 15px/1.5 ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; }
764
+ main { max-width: 980px; margin: 0 auto; }
765
+ h1 { font-size: 20px; margin: 0 0 4px; font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; word-break: break-all; }
766
+ h2 { font-size: 15px; margin: 0 0 10px; font-weight: 600; font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; word-break: break-all; }
767
+ h3 { font-size: 15px; margin: 28px 0 10px; }
768
+ .lede { color: var(--muted); margin: 2px 0; font-size: 13px; }
769
+ section { background: var(--card); border: 1px solid var(--line); border-radius: 10px; padding: 16px; margin: 20px 0; }
770
+ table { width: 100%; border-collapse: collapse; }
771
+ td { padding: 5px 8px 5px 0; vertical-align: top; border-top: 1px solid var(--line); font-size: 13px; }
772
+ tr:first-child td { border-top: 0; }
773
+ td.t { width: 78px; color: var(--muted); font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; white-space: nowrap; }
774
+ td.k { width: 120px; white-space: nowrap; }
775
+ .sub { color: var(--muted); font-size: 12px; margin-top: 2px; word-break: break-word; }
776
+ code { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 12px; overflow-wrap: anywhere; }
777
+ .tag { display: inline-block; padding: 1px 7px; border-radius: 999px; border: 1px solid var(--line); font-size: 11px; color: var(--muted); }
778
+ .tag-proposed, .tag-approved { border-color: var(--accent); color: var(--accent); }
779
+ .state { display: inline-block; padding: 1px 8px; border-radius: 999px; border: 1px solid var(--line); font-size: 11px; font-family: ui-sans-serif, system-ui, sans-serif; color: var(--muted); }
780
+ .state-settled { border-color: var(--accent); color: var(--accent); }
781
+ .state-denied, .state-failed, .state-expired { border-color: #b4552f; color: #b4552f; }
782
+ @media (max-width: 620px) { td.t, td.k { width: auto; white-space: normal; } body { padding: 20px 12px 48px; } }
783
+ </style>
784
+ </head>
785
+ <body>
786
+ <main>
787
+ ${header}
788
+ ${batches}
789
+ ${executions}
790
+ ${runEvents}
791
+ <section><h2>receipts (${report.receipts.length})</h2>${receipts}</section>
792
+ ${footer}
793
+ </main>
794
+ </body>
795
+ </html>
796
+ `;
797
+ }