@vauban-org/agent-sdk 0.17.4 → 1.2.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 (506) hide show
  1. package/CONTRACT.md +6401 -813
  2. package/dist/adapters/llm/anthropic-direct.d.ts +1 -0
  3. package/dist/adapters/llm/anthropic-direct.d.ts.map +1 -1
  4. package/dist/adapters/llm/anthropic-direct.js +43 -0
  5. package/dist/adapters/llm/anthropic-direct.js.map +1 -1
  6. package/dist/adapters/llm/cascade.d.ts.map +1 -1
  7. package/dist/adapters/llm/cascade.js +57 -14
  8. package/dist/adapters/llm/cascade.js.map +1 -1
  9. package/dist/adapters/llm/litellm.d.ts +2 -0
  10. package/dist/adapters/llm/litellm.d.ts.map +1 -1
  11. package/dist/adapters/llm/litellm.js +44 -0
  12. package/dist/adapters/llm/litellm.js.map +1 -1
  13. package/dist/compute/difficulty-estimator.d.ts +53 -0
  14. package/dist/compute/difficulty-estimator.d.ts.map +1 -0
  15. package/dist/compute/difficulty-estimator.js +82 -0
  16. package/dist/compute/difficulty-estimator.js.map +1 -0
  17. package/dist/compute/strategies/mixture-of-agents.d.ts +40 -0
  18. package/dist/compute/strategies/mixture-of-agents.d.ts.map +1 -0
  19. package/dist/compute/strategies/mixture-of-agents.js +110 -0
  20. package/dist/compute/strategies/mixture-of-agents.js.map +1 -0
  21. package/dist/compute/strategies/tree-of-thoughts.d.ts +48 -0
  22. package/dist/compute/strategies/tree-of-thoughts.d.ts.map +1 -0
  23. package/dist/compute/strategies/tree-of-thoughts.js +242 -0
  24. package/dist/compute/strategies/tree-of-thoughts.js.map +1 -0
  25. package/dist/compute/strategies/two-phase-orient.d.ts +72 -0
  26. package/dist/compute/strategies/two-phase-orient.d.ts.map +1 -0
  27. package/dist/compute/strategies/two-phase-orient.js +85 -0
  28. package/dist/compute/strategies/two-phase-orient.js.map +1 -0
  29. package/dist/constitution/types.d.ts +10 -10
  30. package/dist/container/protocol.d.ts +134 -0
  31. package/dist/container/protocol.d.ts.map +1 -0
  32. package/dist/container/protocol.js +157 -0
  33. package/dist/container/protocol.js.map +1 -0
  34. package/dist/container/runtime.d.ts +140 -0
  35. package/dist/container/runtime.d.ts.map +1 -0
  36. package/dist/container/runtime.js +256 -0
  37. package/dist/container/runtime.js.map +1 -0
  38. package/dist/events/catalogue.d.ts +327 -30
  39. package/dist/events/catalogue.d.ts.map +1 -1
  40. package/dist/events/catalogue.js +18 -0
  41. package/dist/events/catalogue.js.map +1 -1
  42. package/dist/events/index.d.ts +9 -0
  43. package/dist/events/index.d.ts.map +1 -1
  44. package/dist/events/index.js +9 -0
  45. package/dist/events/index.js.map +1 -1
  46. package/dist/events/schemas/agent.completed.v1.d.ts +4 -4
  47. package/dist/events/schemas/agent.failed.v1.d.ts +2 -2
  48. package/dist/events/schemas/agent.hitl_resolved.v1.d.ts +2 -2
  49. package/dist/events/schemas/agent.started.v1.d.ts +2 -2
  50. package/dist/events/schemas/brain.skill.extracted.v1.d.ts +4 -4
  51. package/dist/events/schemas/cc.cost.anomaly_detected.v1.d.ts +2 -2
  52. package/dist/events/schemas/cc.cost.recorded.v1.d.ts +4 -4
  53. package/dist/events/schemas/citadel.sprint.analyzed.v1.d.ts +55 -0
  54. package/dist/events/schemas/citadel.sprint.analyzed.v1.d.ts.map +1 -0
  55. package/dist/events/schemas/citadel.sprint.analyzed.v1.js +22 -0
  56. package/dist/events/schemas/citadel.sprint.analyzed.v1.js.map +1 -0
  57. package/dist/events/schemas/citadel.sprint.closed.v1.d.ts +2 -2
  58. package/dist/events/schemas/forge.inbox.reply_classified.v1.d.ts +33 -0
  59. package/dist/events/schemas/forge.inbox.reply_classified.v1.d.ts.map +1 -0
  60. package/dist/events/schemas/forge.inbox.reply_classified.v1.js +15 -0
  61. package/dist/events/schemas/forge.inbox.reply_classified.v1.js.map +1 -0
  62. package/dist/events/schemas/forge.lead.qualified.v1.d.ts +2 -2
  63. package/dist/events/schemas/forge.outreach.sent.v1.d.ts +4 -4
  64. package/dist/events/schemas/incident.detected.v1.d.ts +2 -2
  65. package/dist/events/schemas/vauban-finance.forecast.generated.v1.d.ts +21 -0
  66. package/dist/events/schemas/vauban-finance.forecast.generated.v1.d.ts.map +1 -0
  67. package/dist/events/schemas/vauban-finance.forecast.generated.v1.js +11 -0
  68. package/dist/events/schemas/vauban-finance.forecast.generated.v1.js.map +1 -0
  69. package/dist/events/schemas/vauban-finance.trade.executed.v1.d.ts +24 -0
  70. package/dist/events/schemas/vauban-finance.trade.executed.v1.d.ts.map +1 -0
  71. package/dist/events/schemas/vauban-finance.trade.executed.v1.js +12 -0
  72. package/dist/events/schemas/vauban-finance.trade.executed.v1.js.map +1 -0
  73. package/dist/events/schemas/vauban.goal.checked.v1.d.ts +21 -0
  74. package/dist/events/schemas/vauban.goal.checked.v1.d.ts.map +1 -0
  75. package/dist/events/schemas/vauban.goal.checked.v1.js +11 -0
  76. package/dist/events/schemas/vauban.goal.checked.v1.js.map +1 -0
  77. package/dist/events/schemas/vauban.rebalancing.checked.v1.d.ts +21 -0
  78. package/dist/events/schemas/vauban.rebalancing.checked.v1.d.ts.map +1 -0
  79. package/dist/events/schemas/vauban.rebalancing.checked.v1.js +11 -0
  80. package/dist/events/schemas/vauban.rebalancing.checked.v1.js.map +1 -0
  81. package/dist/events/schemas/vauban.tax.checked.v1.d.ts +21 -0
  82. package/dist/events/schemas/vauban.tax.checked.v1.d.ts.map +1 -0
  83. package/dist/events/schemas/vauban.tax.checked.v1.js +11 -0
  84. package/dist/events/schemas/vauban.tax.checked.v1.js.map +1 -0
  85. package/dist/events/schemas/vauban.vault.analyzed.v1.d.ts +59 -0
  86. package/dist/events/schemas/vauban.vault.analyzed.v1.d.ts.map +1 -0
  87. package/dist/events/schemas/vauban.vault.analyzed.v1.js +19 -0
  88. package/dist/events/schemas/vauban.vault.analyzed.v1.js.map +1 -0
  89. package/dist/events/schemas/vauban.vault.compounded.v1.d.ts +24 -0
  90. package/dist/events/schemas/vauban.vault.compounded.v1.d.ts.map +1 -0
  91. package/dist/events/schemas/vauban.vault.compounded.v1.js +12 -0
  92. package/dist/events/schemas/vauban.vault.compounded.v1.js.map +1 -0
  93. package/dist/identity/agent-persona.d.ts +73 -0
  94. package/dist/identity/agent-persona.d.ts.map +1 -0
  95. package/dist/identity/agent-persona.js +165 -0
  96. package/dist/identity/agent-persona.js.map +1 -0
  97. package/dist/identity/persona-prompt.d.ts +25 -0
  98. package/dist/identity/persona-prompt.d.ts.map +1 -0
  99. package/dist/identity/persona-prompt.js +71 -0
  100. package/dist/identity/persona-prompt.js.map +1 -0
  101. package/dist/identity/persona-schema.d.ts +120 -0
  102. package/dist/identity/persona-schema.d.ts.map +1 -0
  103. package/dist/identity/persona-schema.js +103 -0
  104. package/dist/identity/persona-schema.js.map +1 -0
  105. package/dist/index.d.ts +37 -2
  106. package/dist/index.d.ts.map +1 -1
  107. package/dist/index.js +29 -1
  108. package/dist/index.js.map +1 -1
  109. package/dist/loop/index.d.ts +1 -1
  110. package/dist/loop/index.d.ts.map +1 -1
  111. package/dist/loop/index.js.map +1 -1
  112. package/dist/loop/minimal-loop.js +293 -287
  113. package/dist/loop/sdk-loop.d.ts +1 -3
  114. package/dist/loop/sdk-loop.d.ts.map +1 -1
  115. package/dist/loop/sdk-loop.js +1 -1
  116. package/dist/loop/sdk-loop.js.map +1 -1
  117. package/dist/memory/episodic-rrf.d.ts +114 -0
  118. package/dist/memory/episodic-rrf.d.ts.map +1 -0
  119. package/dist/memory/episodic-rrf.js +148 -0
  120. package/dist/memory/episodic-rrf.js.map +1 -0
  121. package/dist/mesh/attenuation.d.ts +78 -0
  122. package/dist/mesh/attenuation.d.ts.map +1 -0
  123. package/dist/mesh/attenuation.js +141 -0
  124. package/dist/mesh/attenuation.js.map +1 -0
  125. package/dist/mesh/delegate.d.ts +96 -0
  126. package/dist/mesh/delegate.d.ts.map +1 -0
  127. package/dist/mesh/delegate.js +172 -0
  128. package/dist/mesh/delegate.js.map +1 -0
  129. package/dist/mesh/dispatcher.d.ts +119 -0
  130. package/dist/mesh/dispatcher.d.ts.map +1 -0
  131. package/dist/mesh/dispatcher.js +207 -0
  132. package/dist/mesh/dispatcher.js.map +1 -0
  133. package/dist/mesh/index.d.ts +12 -0
  134. package/dist/mesh/index.d.ts.map +1 -0
  135. package/dist/mesh/index.js +11 -0
  136. package/dist/mesh/index.js.map +1 -0
  137. package/dist/mesh/types.d.ts +30 -0
  138. package/dist/mesh/types.d.ts.map +1 -0
  139. package/dist/mesh/types.js +11 -0
  140. package/dist/mesh/types.js.map +1 -0
  141. package/dist/orchestration/ooda/skills.d.ts +104 -0
  142. package/dist/orchestration/ooda/skills.d.ts.map +1 -1
  143. package/dist/orchestration/ooda/skills.js +106 -0
  144. package/dist/orchestration/ooda/skills.js.map +1 -1
  145. package/dist/orchestration/ooda/types.d.ts +3 -8
  146. package/dist/orchestration/ooda/types.d.ts.map +1 -1
  147. package/dist/ports/bastion-action.contract.test.d.ts +11 -0
  148. package/dist/ports/bastion-action.contract.test.d.ts.map +1 -0
  149. package/dist/ports/bastion-action.contract.test.js +238 -0
  150. package/dist/ports/bastion-action.contract.test.js.map +1 -0
  151. package/dist/ports/bastion-action.d.ts +133 -0
  152. package/dist/ports/bastion-action.d.ts.map +1 -0
  153. package/dist/ports/bastion-action.js +73 -0
  154. package/dist/ports/bastion-action.js.map +1 -0
  155. package/dist/ports/brain.d.ts +31 -0
  156. package/dist/ports/brain.d.ts.map +1 -1
  157. package/dist/ports/brain.js +115 -1
  158. package/dist/ports/brain.js.map +1 -1
  159. package/dist/ports/citadel-action.contract.test.d.ts +11 -0
  160. package/dist/ports/citadel-action.contract.test.d.ts.map +1 -0
  161. package/dist/ports/citadel-action.contract.test.js +317 -0
  162. package/dist/ports/citadel-action.contract.test.js.map +1 -0
  163. package/dist/ports/citadel-action.d.ts +111 -0
  164. package/dist/ports/citadel-action.d.ts.map +1 -0
  165. package/dist/ports/citadel-action.js +62 -0
  166. package/dist/ports/citadel-action.js.map +1 -0
  167. package/dist/ports/compliance-contract.d.ts +123 -0
  168. package/dist/ports/compliance-contract.d.ts.map +1 -0
  169. package/dist/ports/compliance-contract.js +35 -0
  170. package/dist/ports/compliance-contract.js.map +1 -0
  171. package/dist/ports/db.d.ts +38 -0
  172. package/dist/ports/db.d.ts.map +1 -1
  173. package/dist/ports/db.js +88 -1
  174. package/dist/ports/db.js.map +1 -1
  175. package/dist/ports/delegation.contract.test.d.ts +9 -0
  176. package/dist/ports/delegation.contract.test.d.ts.map +1 -0
  177. package/dist/ports/delegation.contract.test.js +337 -0
  178. package/dist/ports/delegation.contract.test.js.map +1 -0
  179. package/dist/ports/delegation.d.ts +134 -0
  180. package/dist/ports/delegation.d.ts.map +1 -0
  181. package/dist/ports/delegation.js +105 -0
  182. package/dist/ports/delegation.js.map +1 -0
  183. package/dist/ports/event-bus.d.ts +29 -13
  184. package/dist/ports/event-bus.d.ts.map +1 -1
  185. package/dist/ports/event-bus.js +106 -1
  186. package/dist/ports/event-bus.js.map +1 -1
  187. package/dist/ports/federation.contract.test.d.ts +9 -0
  188. package/dist/ports/federation.contract.test.d.ts.map +1 -0
  189. package/dist/ports/federation.contract.test.js +279 -0
  190. package/dist/ports/federation.contract.test.js.map +1 -0
  191. package/dist/ports/federation.d.ts +140 -0
  192. package/dist/ports/federation.d.ts.map +1 -0
  193. package/dist/ports/federation.js +57 -0
  194. package/dist/ports/federation.js.map +1 -0
  195. package/dist/ports/index.d.ts +28 -2
  196. package/dist/ports/index.d.ts.map +1 -1
  197. package/dist/ports/index.js +17 -2
  198. package/dist/ports/index.js.map +1 -1
  199. package/dist/ports/llm-provider.d.ts +37 -0
  200. package/dist/ports/llm-provider.d.ts.map +1 -1
  201. package/dist/ports/llm-provider.js +99 -1
  202. package/dist/ports/llm-provider.js.map +1 -1
  203. package/dist/ports/logger.d.ts +27 -0
  204. package/dist/ports/logger.d.ts.map +1 -1
  205. package/dist/ports/logger.js +87 -0
  206. package/dist/ports/logger.js.map +1 -1
  207. package/dist/ports/manifest-registry.contract.test.d.ts +9 -0
  208. package/dist/ports/manifest-registry.contract.test.d.ts.map +1 -0
  209. package/dist/ports/manifest-registry.contract.test.js +246 -0
  210. package/dist/ports/manifest-registry.contract.test.js.map +1 -0
  211. package/dist/ports/manifest-registry.d.ts +116 -0
  212. package/dist/ports/manifest-registry.d.ts.map +1 -0
  213. package/dist/ports/manifest-registry.js +79 -0
  214. package/dist/ports/manifest-registry.js.map +1 -0
  215. package/dist/ports/observability.contract.test.d.ts +12 -0
  216. package/dist/ports/observability.contract.test.d.ts.map +1 -0
  217. package/dist/ports/observability.contract.test.js +260 -0
  218. package/dist/ports/observability.contract.test.js.map +1 -0
  219. package/dist/ports/observability.d.ts +98 -0
  220. package/dist/ports/observability.d.ts.map +1 -0
  221. package/dist/ports/observability.js +59 -0
  222. package/dist/ports/observability.js.map +1 -0
  223. package/dist/ports/outcome.d.ts +26 -0
  224. package/dist/ports/outcome.d.ts.map +1 -1
  225. package/dist/ports/outcome.js +62 -1
  226. package/dist/ports/outcome.js.map +1 -1
  227. package/dist/ports/privacy.contract.test.d.ts +12 -0
  228. package/dist/ports/privacy.contract.test.d.ts.map +1 -0
  229. package/dist/ports/privacy.contract.test.js +325 -0
  230. package/dist/ports/privacy.contract.test.js.map +1 -0
  231. package/dist/ports/privacy.d.ts +132 -0
  232. package/dist/ports/privacy.d.ts.map +1 -0
  233. package/dist/ports/privacy.js +83 -0
  234. package/dist/ports/privacy.js.map +1 -0
  235. package/dist/ports/tenant-context.contract.test.d.ts +14 -0
  236. package/dist/ports/tenant-context.contract.test.d.ts.map +1 -0
  237. package/dist/ports/tenant-context.contract.test.js +352 -0
  238. package/dist/ports/tenant-context.contract.test.js.map +1 -0
  239. package/dist/ports/tenant-context.d.ts +103 -0
  240. package/dist/ports/tenant-context.d.ts.map +1 -0
  241. package/dist/ports/tenant-context.js +48 -0
  242. package/dist/ports/tenant-context.js.map +1 -0
  243. package/dist/ports/vauban-finance-action.contract.test.d.ts +11 -0
  244. package/dist/ports/vauban-finance-action.contract.test.d.ts.map +1 -0
  245. package/dist/ports/vauban-finance-action.contract.test.js +260 -0
  246. package/dist/ports/vauban-finance-action.contract.test.js.map +1 -0
  247. package/dist/ports/vauban-finance-action.d.ts +106 -0
  248. package/dist/ports/vauban-finance-action.d.ts.map +1 -0
  249. package/dist/ports/vauban-finance-action.js +60 -0
  250. package/dist/ports/vauban-finance-action.js.map +1 -0
  251. package/dist/ports/workflow-runtime.d.ts +204 -0
  252. package/dist/ports/workflow-runtime.d.ts.map +1 -0
  253. package/dist/ports/workflow-runtime.js +72 -0
  254. package/dist/ports/workflow-runtime.js.map +1 -0
  255. package/dist/proof/cert-verify.d.ts +80 -0
  256. package/dist/proof/cert-verify.d.ts.map +1 -0
  257. package/dist/proof/cert-verify.js +178 -0
  258. package/dist/proof/cert-verify.js.map +1 -0
  259. package/dist/replay/replay.d.ts.map +1 -1
  260. package/dist/replay/replay.js +5 -1
  261. package/dist/replay/replay.js.map +1 -1
  262. package/dist/retry/index.d.ts +129 -0
  263. package/dist/retry/index.d.ts.map +1 -0
  264. package/dist/retry/index.js +156 -0
  265. package/dist/retry/index.js.map +1 -0
  266. package/dist/retry/presets.d.ts +39 -0
  267. package/dist/retry/presets.d.ts.map +1 -0
  268. package/dist/retry/presets.js +69 -0
  269. package/dist/retry/presets.js.map +1 -0
  270. package/dist/skill-loop/ab-runner.d.ts +67 -0
  271. package/dist/skill-loop/ab-runner.d.ts.map +1 -0
  272. package/dist/skill-loop/ab-runner.js +160 -0
  273. package/dist/skill-loop/ab-runner.js.map +1 -0
  274. package/dist/skill-loop/adoption.d.ts +67 -0
  275. package/dist/skill-loop/adoption.d.ts.map +1 -0
  276. package/dist/skill-loop/adoption.js +126 -0
  277. package/dist/skill-loop/adoption.js.map +1 -0
  278. package/dist/skill-loop/candidate.d.ts +45 -0
  279. package/dist/skill-loop/candidate.d.ts.map +1 -0
  280. package/dist/skill-loop/candidate.js +43 -0
  281. package/dist/skill-loop/candidate.js.map +1 -0
  282. package/dist/skill-loop/evaluator.d.ts +42 -0
  283. package/dist/skill-loop/evaluator.d.ts.map +1 -0
  284. package/dist/skill-loop/evaluator.js +184 -0
  285. package/dist/skill-loop/evaluator.js.map +1 -0
  286. package/dist/skill-loop/index.d.ts +27 -0
  287. package/dist/skill-loop/index.d.ts.map +1 -0
  288. package/dist/skill-loop/index.js +27 -0
  289. package/dist/skill-loop/index.js.map +1 -0
  290. package/dist/skill-loop/reflexion-replay.d.ts +87 -0
  291. package/dist/skill-loop/reflexion-replay.d.ts.map +1 -0
  292. package/dist/skill-loop/reflexion-replay.js +110 -0
  293. package/dist/skill-loop/reflexion-replay.js.map +1 -0
  294. package/dist/skill-loop/sign-off.d.ts +88 -0
  295. package/dist/skill-loop/sign-off.d.ts.map +1 -0
  296. package/dist/skill-loop/sign-off.js +146 -0
  297. package/dist/skill-loop/sign-off.js.map +1 -0
  298. package/dist/skill-loop/value-metric.d.ts +55 -0
  299. package/dist/skill-loop/value-metric.d.ts.map +1 -0
  300. package/dist/skill-loop/value-metric.js +69 -0
  301. package/dist/skill-loop/value-metric.js.map +1 -0
  302. package/dist/skill-loop/versioning.d.ts +36 -0
  303. package/dist/skill-loop/versioning.d.ts.map +1 -0
  304. package/dist/skill-loop/versioning.js +47 -0
  305. package/dist/skill-loop/versioning.js.map +1 -0
  306. package/dist/skill-manifest/anchor.d.ts +91 -0
  307. package/dist/skill-manifest/anchor.d.ts.map +1 -0
  308. package/dist/skill-manifest/anchor.js +331 -0
  309. package/dist/skill-manifest/anchor.js.map +1 -0
  310. package/dist/skill-manifest/builder.d.ts +47 -0
  311. package/dist/skill-manifest/builder.d.ts.map +1 -0
  312. package/dist/skill-manifest/builder.js +93 -0
  313. package/dist/skill-manifest/builder.js.map +1 -0
  314. package/dist/skill-manifest/index.d.ts +13 -0
  315. package/dist/skill-manifest/index.d.ts.map +1 -0
  316. package/dist/skill-manifest/index.js +9 -0
  317. package/dist/skill-manifest/index.js.map +1 -0
  318. package/dist/skill-manifest/types.d.ts +67 -0
  319. package/dist/skill-manifest/types.d.ts.map +1 -0
  320. package/dist/skill-manifest/types.js +16 -0
  321. package/dist/skill-manifest/types.js.map +1 -0
  322. package/dist/skill-manifest/verifier.d.ts +42 -0
  323. package/dist/skill-manifest/verifier.d.ts.map +1 -0
  324. package/dist/skill-manifest/verifier.js +136 -0
  325. package/dist/skill-manifest/verifier.js.map +1 -0
  326. package/dist/skills/brain-query.d.ts +4 -4
  327. package/dist/skills/brain-store.d.ts +6 -6
  328. package/dist/skills/errors.d.ts +15 -0
  329. package/dist/skills/errors.d.ts.map +1 -1
  330. package/dist/skills/errors.js +21 -0
  331. package/dist/skills/errors.js.map +1 -1
  332. package/dist/skills/hitl-request.d.ts +2 -2
  333. package/dist/skills/index.d.ts +3 -1
  334. package/dist/skills/index.d.ts.map +1 -1
  335. package/dist/skills/index.js +4 -1
  336. package/dist/skills/index.js.map +1 -1
  337. package/dist/skills/markdown/loader.d.ts +52 -0
  338. package/dist/skills/markdown/loader.d.ts.map +1 -0
  339. package/dist/skills/markdown/loader.js +93 -0
  340. package/dist/skills/markdown/loader.js.map +1 -0
  341. package/dist/skills/markdown/schema.d.ts +432 -0
  342. package/dist/skills/markdown/schema.d.ts.map +1 -0
  343. package/dist/skills/markdown/schema.js +121 -0
  344. package/dist/skills/markdown/schema.js.map +1 -0
  345. package/dist/skills/poc-md-loader/markdown-loader.d.ts +77 -0
  346. package/dist/skills/poc-md-loader/markdown-loader.d.ts.map +1 -0
  347. package/dist/skills/poc-md-loader/markdown-loader.js +125 -0
  348. package/dist/skills/poc-md-loader/markdown-loader.js.map +1 -0
  349. package/dist/skills/poc-md-loader/runner.d.ts +24 -0
  350. package/dist/skills/poc-md-loader/runner.d.ts.map +1 -0
  351. package/dist/skills/poc-md-loader/runner.js +57 -0
  352. package/dist/skills/poc-md-loader/runner.js.map +1 -0
  353. package/dist/skills/poc-md-loader/vitest.poc.config.d.ts +3 -0
  354. package/dist/skills/poc-md-loader/vitest.poc.config.d.ts.map +1 -0
  355. package/dist/skills/poc-md-loader/vitest.poc.config.js +13 -0
  356. package/dist/skills/poc-md-loader/vitest.poc.config.js.map +1 -0
  357. package/dist/skills/poc-md-loader/web-search/script.d.ts +33 -0
  358. package/dist/skills/poc-md-loader/web-search/script.d.ts.map +1 -0
  359. package/dist/skills/poc-md-loader/web-search/script.js +75 -0
  360. package/dist/skills/poc-md-loader/web-search/script.js.map +1 -0
  361. package/dist/skills/record-outcome.d.ts +4 -4
  362. package/dist/skills/send-email.d.ts.map +1 -1
  363. package/dist/skills/send-email.js +15 -3
  364. package/dist/skills/send-email.js.map +1 -1
  365. package/dist/skills/slack-notify.d.ts +4 -4
  366. package/dist/skills/starknet-balance.d.ts +1 -1
  367. package/dist/skills/telegram-notify.d.ts +4 -4
  368. package/dist/skills/web-search.d.ts +1 -1
  369. package/dist/testing/contracts/event-bus.contract.d.ts.map +1 -1
  370. package/dist/testing/contracts/event-bus.contract.js +14 -12
  371. package/dist/testing/contracts/event-bus.contract.js.map +1 -1
  372. package/dist/testing/index.d.ts +3 -0
  373. package/dist/testing/test-brain-port.d.ts +4 -0
  374. package/dist/testing/test-brain-port.d.ts.map +1 -1
  375. package/dist/testing/test-brain-port.js +75 -20
  376. package/dist/testing/test-brain-port.js.map +1 -1
  377. package/dist/testing/test-event-bus.d.ts.map +1 -1
  378. package/dist/testing/test-event-bus.js +89 -36
  379. package/dist/testing/test-event-bus.js.map +1 -1
  380. package/dist/trace/schema.d.ts +1 -1
  381. package/dist/trace/schema.d.ts.map +1 -1
  382. package/dist/trace/schema.js +1 -1
  383. package/dist/trace/schema.js.map +1 -1
  384. package/dist/verify/formal/index.d.ts +44 -0
  385. package/dist/verify/formal/index.d.ts.map +1 -0
  386. package/dist/verify/formal/index.js +98 -0
  387. package/dist/verify/formal/index.js.map +1 -0
  388. package/dist/verify/formal/policy.d.ts +105 -0
  389. package/dist/verify/formal/policy.d.ts.map +1 -0
  390. package/dist/verify/formal/policy.js +159 -0
  391. package/dist/verify/formal/policy.js.map +1 -0
  392. package/dist/verify/formal/result.d.ts +50 -0
  393. package/dist/verify/formal/result.d.ts.map +1 -0
  394. package/dist/verify/formal/result.js +21 -0
  395. package/dist/verify/formal/result.js.map +1 -0
  396. package/dist/verify/formal/solver.d.ts +67 -0
  397. package/dist/verify/formal/solver.d.ts.map +1 -0
  398. package/dist/verify/formal/solver.js +184 -0
  399. package/dist/verify/formal/solver.js.map +1 -0
  400. package/dist/verify/formal/spec-language.d.ts +80 -0
  401. package/dist/verify/formal/spec-language.d.ts.map +1 -0
  402. package/dist/verify/formal/spec-language.js +219 -0
  403. package/dist/verify/formal/spec-language.js.map +1 -0
  404. package/docs/attestation.md +199 -0
  405. package/docs/identity.md +193 -0
  406. package/package.json +22 -1
  407. package/src/adapters/llm/anthropic-direct.ts +51 -0
  408. package/src/adapters/llm/cascade.ts +64 -19
  409. package/src/adapters/llm/litellm.ts +49 -0
  410. package/src/compute/difficulty-estimator.ts +111 -0
  411. package/src/compute/strategies/mixture-of-agents.ts +150 -0
  412. package/src/compute/strategies/tree-of-thoughts.ts +293 -0
  413. package/src/compute/strategies/two-phase-orient.ts +147 -0
  414. package/src/container/protocol.ts +243 -0
  415. package/src/container/runtime.ts +424 -0
  416. package/src/db/migrations/026_formal_verify_results.sql +30 -0
  417. package/src/events/catalogue.ts +54 -0
  418. package/src/events/index.ts +9 -0
  419. package/src/events/schemas/citadel.sprint.analyzed.v1.ts +23 -0
  420. package/src/events/schemas/forge.inbox.reply_classified.v1.ts +15 -0
  421. package/src/events/schemas/vauban-finance.forecast.generated.v1.ts +11 -0
  422. package/src/events/schemas/vauban-finance.trade.executed.v1.ts +12 -0
  423. package/src/events/schemas/vauban.goal.checked.v1.ts +11 -0
  424. package/src/events/schemas/vauban.rebalancing.checked.v1.ts +11 -0
  425. package/src/events/schemas/vauban.tax.checked.v1.ts +11 -0
  426. package/src/events/schemas/vauban.vault.analyzed.v1.ts +21 -0
  427. package/src/events/schemas/vauban.vault.compounded.v1.ts +12 -0
  428. package/src/identity/agent-persona.ts +203 -0
  429. package/src/identity/persona-prompt.ts +84 -0
  430. package/src/identity/persona-schema.ts +127 -0
  431. package/src/index.ts +338 -1
  432. package/src/loop/index.ts +0 -1
  433. package/src/loop/sdk-loop.ts +5 -8
  434. package/src/memory/episodic-rrf.ts +224 -0
  435. package/src/mesh/attenuation.ts +190 -0
  436. package/src/mesh/delegate.ts +254 -0
  437. package/src/mesh/dispatcher.ts +301 -0
  438. package/src/mesh/index.ts +39 -0
  439. package/src/mesh/types.ts +31 -0
  440. package/src/orchestration/ooda/skills.ts +177 -0
  441. package/src/orchestration/ooda/types.ts +3 -9
  442. package/src/ports/bastion-action.contract.test.ts +355 -0
  443. package/src/ports/bastion-action.ts +198 -0
  444. package/src/ports/brain.ts +177 -15
  445. package/src/ports/citadel-action.contract.test.ts +430 -0
  446. package/src/ports/citadel-action.ts +174 -0
  447. package/src/ports/compliance-contract.ts +191 -0
  448. package/src/ports/db.ts +98 -0
  449. package/src/ports/delegation.contract.test.ts +428 -0
  450. package/src/ports/delegation.ts +211 -0
  451. package/src/ports/event-bus.ts +133 -18
  452. package/src/ports/federation.contract.test.ts +355 -0
  453. package/src/ports/federation.ts +190 -0
  454. package/src/ports/index.ts +186 -1
  455. package/src/ports/llm-provider.ts +123 -0
  456. package/src/ports/logger.ts +104 -0
  457. package/src/ports/manifest-registry.contract.test.ts +324 -0
  458. package/src/ports/manifest-registry.ts +188 -0
  459. package/src/ports/observability.contract.test.ts +315 -0
  460. package/src/ports/observability.ts +150 -0
  461. package/src/ports/outcome.ts +69 -0
  462. package/src/ports/privacy.contract.test.ts +413 -0
  463. package/src/ports/privacy.ts +207 -0
  464. package/src/ports/tenant-context.contract.test.ts +454 -0
  465. package/src/ports/tenant-context.ts +150 -0
  466. package/src/ports/vauban-finance-action.contract.test.ts +335 -0
  467. package/src/ports/vauban-finance-action.ts +166 -0
  468. package/src/ports/workflow-runtime.ts +327 -0
  469. package/src/proof/cert-verify.ts +249 -0
  470. package/src/replay/replay.ts +11 -8
  471. package/src/retry/index.ts +227 -0
  472. package/src/retry/presets.ts +75 -0
  473. package/src/skill-loop/ab-runner.ts +196 -0
  474. package/src/skill-loop/adoption.ts +188 -0
  475. package/src/skill-loop/candidate.ts +75 -0
  476. package/src/skill-loop/evaluator.ts +238 -0
  477. package/src/skill-loop/index.ts +51 -0
  478. package/src/skill-loop/reflexion-replay.ts +173 -0
  479. package/src/skill-loop/sign-off.ts +247 -0
  480. package/src/skill-loop/value-metric.ts +120 -0
  481. package/src/skill-loop/versioning.ts +75 -0
  482. package/src/skill-manifest/anchor.ts +401 -0
  483. package/src/skill-manifest/builder.ts +129 -0
  484. package/src/skill-manifest/index.ts +18 -0
  485. package/src/skill-manifest/types.ts +72 -0
  486. package/src/skill-manifest/verifier.ts +198 -0
  487. package/src/skills/errors.ts +30 -2
  488. package/src/skills/index.ts +19 -0
  489. package/src/skills/markdown/loader.ts +129 -0
  490. package/src/skills/markdown/schema.ts +144 -0
  491. package/src/skills/poc-md-loader/e2e-parity.test.ts +237 -0
  492. package/src/skills/poc-md-loader/markdown-loader.ts +161 -0
  493. package/src/skills/poc-md-loader/runner.ts +82 -0
  494. package/src/skills/poc-md-loader/vitest.poc.config.ts +13 -0
  495. package/src/skills/poc-md-loader/web-search/SKILL.md +42 -0
  496. package/src/skills/poc-md-loader/web-search/script.ts +109 -0
  497. package/src/skills/send-email.ts +15 -3
  498. package/src/testing/contracts/event-bus.contract.ts +16 -14
  499. package/src/testing/test-brain-port.ts +98 -24
  500. package/src/testing/test-event-bus.ts +104 -43
  501. package/src/trace/schema.ts +1 -1
  502. package/src/verify/formal/index.ts +154 -0
  503. package/src/verify/formal/policy.ts +253 -0
  504. package/src/verify/formal/result.ts +52 -0
  505. package/src/verify/formal/solver.ts +235 -0
  506. package/src/verify/formal/spec-language.ts +274 -0
@@ -0,0 +1,243 @@
1
+ /**
2
+ * Container Execution Protocol — standard contract for running automations
3
+ * inside containers or as local binaries.
4
+ *
5
+ * Contract:
6
+ *
7
+ * Input (via env vars):
8
+ * VAUBAN_EXECUTION_ID — unique execution identifier (UUID)
9
+ * VAUBAN_AUTOMATION_NAME — automation name (kebab-case)
10
+ * VAUBAN_INPUT — JSON-encoded input parameters
11
+ * VAUBAN_TIMEOUT — timeout in seconds
12
+ * VAUBAN_MODE — execution mode (default: "execute")
13
+ *
14
+ * Output (via stdout, last non-empty line, JSON):
15
+ * { "status": "completed", "output": <any> }
16
+ * { "status": "failed", "error": { "code": "...", "message": "...", "details"?: <any> } }
17
+ *
18
+ * Diagnostics (via stderr, optional, one JSON object per line):
19
+ * { "level": "info", "message": "...", "timestamp": "..." }
20
+ * { "progress": 0.5, "message": "..." }
21
+ *
22
+ * @public @since 1.2.0
23
+ */
24
+
25
+ /**
26
+ * Reserved environment variable names. All caller env merged on top must NOT
27
+ * shadow these keys, or the automation's view of its own context becomes
28
+ * undefined.
29
+ *
30
+ * @public
31
+ */
32
+ export const PROTOCOL_ENV = {
33
+ EXECUTION_ID: "VAUBAN_EXECUTION_ID",
34
+ AUTOMATION_NAME: "VAUBAN_AUTOMATION_NAME",
35
+ INPUT: "VAUBAN_INPUT",
36
+ TIMEOUT: "VAUBAN_TIMEOUT",
37
+ MODE: "VAUBAN_MODE",
38
+ } as const;
39
+
40
+ /**
41
+ * Default protocol mode set when caller does not specify one.
42
+ * @public
43
+ */
44
+ export const DEFAULT_PROTOCOL_MODE = "execute";
45
+
46
+ /**
47
+ * Final status reported by a container/binary on stdout.
48
+ * @public
49
+ */
50
+ export type ProtocolStatus = "completed" | "failed";
51
+
52
+ /**
53
+ * Discriminated union of protocol outputs parsed from stdout.
54
+ * @public
55
+ */
56
+ export type ProtocolResult<T = unknown> =
57
+ | { readonly status: "completed"; readonly output: T }
58
+ | {
59
+ readonly status: "failed";
60
+ readonly error: {
61
+ readonly code: string;
62
+ readonly message: string;
63
+ readonly details?: unknown;
64
+ };
65
+ };
66
+
67
+ /**
68
+ * Outcome of an execution attempt, combining protocol result with timing,
69
+ * captured logs, and propagated metadata.
70
+ *
71
+ * @public
72
+ */
73
+ export interface ExecutionResult<T = unknown> {
74
+ readonly executionId: string;
75
+ readonly automationName: string;
76
+ readonly status: "completed" | "failed" | "timeout";
77
+ readonly input: unknown;
78
+ readonly output?: T;
79
+ readonly error?: {
80
+ code: string;
81
+ message: string;
82
+ details?: unknown;
83
+ };
84
+ readonly startedAt: Date;
85
+ readonly completedAt: Date;
86
+ readonly durationMs: number;
87
+ readonly logs: ReadonlyArray<{
88
+ readonly level: string;
89
+ readonly message: string;
90
+ readonly timestamp: string;
91
+ }>;
92
+ }
93
+
94
+ /**
95
+ * Thrown when stdout does not contain a parseable protocol result on its last
96
+ * non-empty line.
97
+ *
98
+ * @public
99
+ */
100
+ export class ProtocolParseError extends Error {
101
+ readonly rawTail: string;
102
+ constructor(reason: string, rawTail: string) {
103
+ super(`container-protocol: ${reason}`);
104
+ this.name = "ProtocolParseError";
105
+ this.rawTail = rawTail;
106
+ }
107
+ }
108
+
109
+ /**
110
+ * Build the protocol's environment variables. Caller `extraEnv` is merged
111
+ * AFTER protocol env, so it cannot accidentally override reserved keys.
112
+ *
113
+ * @public
114
+ */
115
+ export function buildProtocolEnv(args: {
116
+ executionId: string;
117
+ automationName: string;
118
+ input: unknown;
119
+ timeoutSeconds: number;
120
+ mode?: string;
121
+ extraEnv?: Readonly<Record<string, string>>;
122
+ }): Record<string, string> {
123
+ const env: Record<string, string> = {};
124
+ if (args.extraEnv) {
125
+ for (const [k, v] of Object.entries(args.extraEnv)) {
126
+ env[k] = v;
127
+ }
128
+ }
129
+ env[PROTOCOL_ENV.EXECUTION_ID] = args.executionId;
130
+ env[PROTOCOL_ENV.AUTOMATION_NAME] = args.automationName;
131
+ env[PROTOCOL_ENV.INPUT] = JSON.stringify(args.input);
132
+ env[PROTOCOL_ENV.TIMEOUT] = String(args.timeoutSeconds);
133
+ env[PROTOCOL_ENV.MODE] = args.mode ?? DEFAULT_PROTOCOL_MODE;
134
+ return env;
135
+ }
136
+
137
+ /**
138
+ * Parse the last non-empty line of stdout as a {@link ProtocolResult}.
139
+ *
140
+ * @throws {@link ProtocolParseError} when stdout is empty, has no JSON tail,
141
+ * or the JSON does not match the protocol shape.
142
+ *
143
+ * @public
144
+ */
145
+ export function parseProtocolOutput<T = unknown>(
146
+ stdout: string
147
+ ): ProtocolResult<T> {
148
+ const trimmed = stdout.trim();
149
+ if (trimmed.length === 0) {
150
+ throw new ProtocolParseError("stdout is empty", "");
151
+ }
152
+ const lines = trimmed.split("\n");
153
+ const lastLine = lines[lines.length - 1]!.trim();
154
+ if (lastLine.length === 0) {
155
+ throw new ProtocolParseError(
156
+ "last stdout line is empty",
157
+ trimmed.slice(-200)
158
+ );
159
+ }
160
+
161
+ let parsed: unknown;
162
+ try {
163
+ parsed = JSON.parse(lastLine);
164
+ } catch {
165
+ throw new ProtocolParseError(
166
+ "last stdout line is not valid JSON",
167
+ lastLine.slice(0, 500)
168
+ );
169
+ }
170
+
171
+ if (typeof parsed !== "object" || parsed === null || !("status" in parsed)) {
172
+ throw new ProtocolParseError(
173
+ "protocol JSON missing 'status' field",
174
+ lastLine.slice(0, 500)
175
+ );
176
+ }
177
+
178
+ const obj = parsed as Record<string, unknown>;
179
+ const status = obj["status"];
180
+
181
+ if (status === "completed") {
182
+ return { status: "completed", output: (obj["output"] ?? null) as T };
183
+ }
184
+
185
+ if (status === "failed") {
186
+ const err = (obj["error"] as Record<string, unknown> | undefined) ?? {};
187
+ const code =
188
+ typeof err["code"] === "string" ? (err["code"] as string) : "UNKNOWN";
189
+ const message =
190
+ typeof err["message"] === "string"
191
+ ? (err["message"] as string)
192
+ : "(no message)";
193
+ const details = err["details"];
194
+ return { status: "failed", error: { code, message, details } };
195
+ }
196
+
197
+ throw new ProtocolParseError(
198
+ `unknown protocol status: ${String(status)}`,
199
+ lastLine.slice(0, 500)
200
+ );
201
+ }
202
+
203
+ /**
204
+ * Parse stderr lines as JSON log entries when possible; fall back to plain
205
+ * text wrapped at level "info". Used by {@link ContainerRuntime} to populate
206
+ * `ExecutionResult.logs`.
207
+ *
208
+ * @public
209
+ */
210
+ export function parseStderrLogs(stderr: string): Array<{
211
+ level: string;
212
+ message: string;
213
+ timestamp: string;
214
+ }> {
215
+ const logs: Array<{ level: string; message: string; timestamp: string }> = [];
216
+ const lines = stderr.split("\n");
217
+ for (const raw of lines) {
218
+ const line = raw.trim();
219
+ if (line.length === 0) continue;
220
+ try {
221
+ const obj = JSON.parse(line) as Record<string, unknown>;
222
+ logs.push({
223
+ level:
224
+ typeof obj["level"] === "string" ? (obj["level"] as string) : "info",
225
+ message:
226
+ typeof obj["message"] === "string"
227
+ ? (obj["message"] as string)
228
+ : line.slice(0, 500),
229
+ timestamp:
230
+ typeof obj["timestamp"] === "string"
231
+ ? (obj["timestamp"] as string)
232
+ : new Date().toISOString(),
233
+ });
234
+ } catch {
235
+ logs.push({
236
+ level: "info",
237
+ message: line.slice(0, 500),
238
+ timestamp: new Date().toISOString(),
239
+ });
240
+ }
241
+ }
242
+ return logs;
243
+ }
@@ -0,0 +1,424 @@
1
+ /**
2
+ * ContainerRuntime — execute automations as local binaries or as containers,
3
+ * speaking the {@link ./protocol.ts | Container Execution Protocol}.
4
+ *
5
+ * Two modes:
6
+ *
7
+ * - **Binary**: spawn a local executable directly (Rust/Go/Python binary).
8
+ * The runtime uses `node:child_process.spawn` by default; tests inject a
9
+ * `SpawnFn` to avoid actually running anything.
10
+ *
11
+ * - **Container**: delegate to a host-provided {@link SandboxExecutor}.
12
+ * This is structurally compatible with Command Center's `DockerExecutor`
13
+ * (hardened isolation), so the SDK stays decoupled from any specific
14
+ * sandbox implementation.
15
+ *
16
+ * @public @since 1.2.0
17
+ */
18
+
19
+ import { randomUUID } from "node:crypto";
20
+ import { type ChildProcess, spawn as nodeSpawn } from "node:child_process";
21
+
22
+ import {
23
+ buildProtocolEnv,
24
+ type ExecutionResult,
25
+ parseProtocolOutput,
26
+ parseStderrLogs,
27
+ ProtocolParseError,
28
+ } from "./protocol.js";
29
+
30
+ /**
31
+ * Description of a sandboxed job — structurally identical to Command Center's
32
+ * `SandboxJob`. Defined here so the SDK has no dependency on a specific
33
+ * sandbox implementation.
34
+ *
35
+ * @public
36
+ */
37
+ export interface SandboxJob {
38
+ image: string;
39
+ command: string[];
40
+ stdin?: string;
41
+ env?: Record<string, string>;
42
+ cwd?: string;
43
+ timeoutMs: number;
44
+ networkMode?: "none" | "outbound" | "bridge";
45
+ readOnlyRoot?: boolean;
46
+ memoryMb?: number;
47
+ cpuQuota?: number;
48
+ }
49
+
50
+ /**
51
+ * Outcome of a sandbox run — structurally identical to Command Center's
52
+ * `SandboxResult`.
53
+ *
54
+ * @public
55
+ */
56
+ export interface SandboxResult {
57
+ exitCode: number;
58
+ stdout: string;
59
+ stderr: string;
60
+ timedOut: boolean;
61
+ durationMs: number;
62
+ }
63
+
64
+ /**
65
+ * Port for a process sandbox (Docker, Firecracker, etc.). The host injects an
66
+ * implementation at runtime; the SDK never depends on a concrete sandbox.
67
+ *
68
+ * @public
69
+ */
70
+ export interface SandboxExecutor {
71
+ run(job: SandboxJob): Promise<SandboxResult>;
72
+ }
73
+
74
+ /**
75
+ * Spawn function signature, mirrors `node:child_process.spawn`. Injectable so
76
+ * tests can avoid spawning real subprocesses.
77
+ *
78
+ * @public
79
+ */
80
+ export type SpawnFn = (
81
+ cmd: string,
82
+ args: string[],
83
+ opts: {
84
+ env?: NodeJS.ProcessEnv;
85
+ cwd?: string;
86
+ stdio: ["pipe", "pipe", "pipe"];
87
+ signal?: AbortSignal;
88
+ }
89
+ ) => ChildProcess;
90
+
91
+ /**
92
+ * Options for {@link ContainerRuntime.executeContainer}.
93
+ *
94
+ * @public
95
+ */
96
+ export interface ContainerExecutionOptions {
97
+ executionId?: string;
98
+ timeoutSeconds?: number;
99
+ extraEnv?: Record<string, string>;
100
+ mode?: string;
101
+ networkMode?: "none" | "outbound" | "bridge";
102
+ readOnlyRoot?: boolean;
103
+ memoryMb?: number;
104
+ cpuQuota?: number;
105
+ }
106
+
107
+ /**
108
+ * Options for {@link ContainerRuntime.executeBinary}.
109
+ *
110
+ * @public
111
+ */
112
+ export interface BinaryExecutionOptions {
113
+ executionId?: string;
114
+ timeoutSeconds?: number;
115
+ extraEnv?: Record<string, string>;
116
+ cwd?: string;
117
+ mode?: string;
118
+ }
119
+
120
+ /**
121
+ * Construct a {@link ContainerRuntime} bound to a {@link SandboxExecutor}
122
+ * (for container mode) and optionally a custom {@link SpawnFn} (for binary
123
+ * mode tests).
124
+ *
125
+ * @public
126
+ */
127
+ export interface ContainerRuntimeOptions {
128
+ /** Sandbox executor for container mode. Required if executeContainer() is called. */
129
+ sandbox?: SandboxExecutor;
130
+ /** Spawn function for binary mode. Defaults to node:child_process.spawn. */
131
+ spawnFn?: SpawnFn;
132
+ /** Default timeout when callers don't specify one. */
133
+ defaultTimeoutSeconds?: number;
134
+ }
135
+
136
+ const DEFAULT_TIMEOUT_SECONDS = 300;
137
+ const MAX_OUTPUT_BYTES = 1_048_576; // 1 MB
138
+ const TRUNCATION_MARKER = "\n[TRUNCATED — output exceeded 1 MB]";
139
+
140
+ /**
141
+ * Run automations via either a sandboxed container (host-injected) or a local
142
+ * binary subprocess. Both paths produce a uniform {@link ExecutionResult}.
143
+ *
144
+ * @public
145
+ */
146
+ export class ContainerRuntime {
147
+ private readonly sandbox: SandboxExecutor | undefined;
148
+ private readonly spawnFn: SpawnFn;
149
+ private readonly defaultTimeoutSeconds: number;
150
+
151
+ constructor(opts: ContainerRuntimeOptions = {}) {
152
+ this.sandbox = opts.sandbox;
153
+ this.spawnFn = opts.spawnFn ?? (nodeSpawn as unknown as SpawnFn);
154
+ this.defaultTimeoutSeconds =
155
+ opts.defaultTimeoutSeconds ?? DEFAULT_TIMEOUT_SECONDS;
156
+ }
157
+
158
+ /**
159
+ * Execute an automation packaged as a container image. Delegates to the
160
+ * injected {@link SandboxExecutor} so isolation policy (caps, network,
161
+ * read-only FS) lives in the host implementation.
162
+ */
163
+ async executeContainer<T = unknown>(
164
+ image: string,
165
+ automationName: string,
166
+ input: unknown,
167
+ options: ContainerExecutionOptions = {}
168
+ ): Promise<ExecutionResult<T>> {
169
+ if (!this.sandbox) {
170
+ throw new Error(
171
+ "ContainerRuntime.executeContainer: no SandboxExecutor injected"
172
+ );
173
+ }
174
+ const executionId = options.executionId ?? randomUUID();
175
+ const timeoutSeconds = options.timeoutSeconds ?? this.defaultTimeoutSeconds;
176
+ const startedAt = new Date();
177
+
178
+ const env = buildProtocolEnv({
179
+ executionId,
180
+ automationName,
181
+ input,
182
+ timeoutSeconds,
183
+ mode: options.mode,
184
+ extraEnv: options.extraEnv,
185
+ });
186
+
187
+ const job: SandboxJob = {
188
+ image,
189
+ command: [],
190
+ env,
191
+ timeoutMs: timeoutSeconds * 1000,
192
+ networkMode: options.networkMode ?? "none",
193
+ readOnlyRoot: options.readOnlyRoot ?? true,
194
+ memoryMb: options.memoryMb ?? 256,
195
+ cpuQuota: options.cpuQuota ?? 0.5,
196
+ };
197
+
198
+ const result = await this.sandbox.run(job);
199
+ return this.toExecutionResult<T>({
200
+ executionId,
201
+ automationName,
202
+ input,
203
+ startedAt,
204
+ sandboxResult: result,
205
+ });
206
+ }
207
+
208
+ /**
209
+ * Execute an automation packaged as a local binary (Rust release, Python
210
+ * wrapper, shell script). No container — just a hardened subprocess.
211
+ */
212
+ async executeBinary<T = unknown>(
213
+ command: string[],
214
+ automationName: string,
215
+ input: unknown,
216
+ options: BinaryExecutionOptions = {}
217
+ ): Promise<ExecutionResult<T>> {
218
+ if (!Array.isArray(command) || command.length === 0) {
219
+ throw new Error(
220
+ "ContainerRuntime.executeBinary: command must be a non-empty array"
221
+ );
222
+ }
223
+ const executionId = options.executionId ?? randomUUID();
224
+ const timeoutSeconds = options.timeoutSeconds ?? this.defaultTimeoutSeconds;
225
+ const startedAt = new Date();
226
+
227
+ const protocolEnv = buildProtocolEnv({
228
+ executionId,
229
+ automationName,
230
+ input,
231
+ timeoutSeconds,
232
+ mode: options.mode,
233
+ extraEnv: options.extraEnv,
234
+ });
235
+ const env: NodeJS.ProcessEnv = { ...process.env, ...protocolEnv };
236
+
237
+ const result = await this.runSubprocess({
238
+ cmd: command[0]!,
239
+ args: command.slice(1),
240
+ env,
241
+ cwd: options.cwd,
242
+ timeoutMs: timeoutSeconds * 1000,
243
+ });
244
+
245
+ return this.toExecutionResult<T>({
246
+ executionId,
247
+ automationName,
248
+ input,
249
+ startedAt,
250
+ sandboxResult: result,
251
+ });
252
+ }
253
+
254
+ // ─── Internals ────────────────────────────────────────────────────────
255
+
256
+ private async runSubprocess(args: {
257
+ cmd: string;
258
+ args: string[];
259
+ env: NodeJS.ProcessEnv;
260
+ cwd: string | undefined;
261
+ timeoutMs: number;
262
+ }): Promise<SandboxResult> {
263
+ const startedAt = Date.now();
264
+ const abortController = new AbortController();
265
+ const timeoutHandle = setTimeout(
266
+ () => abortController.abort(),
267
+ args.timeoutMs
268
+ );
269
+
270
+ let stdoutBuf = "";
271
+ let stderrBuf = "";
272
+ let timedOut = false;
273
+
274
+ const spawnOpts: {
275
+ env?: NodeJS.ProcessEnv;
276
+ cwd?: string;
277
+ stdio: ["pipe", "pipe", "pipe"];
278
+ signal?: AbortSignal;
279
+ } = {
280
+ env: args.env,
281
+ stdio: ["pipe", "pipe", "pipe"],
282
+ signal: abortController.signal,
283
+ };
284
+ if (args.cwd !== undefined) spawnOpts.cwd = args.cwd;
285
+
286
+ const child = this.spawnFn(args.cmd, args.args, spawnOpts);
287
+
288
+ if (child.stdin) child.stdin.end();
289
+
290
+ child.stdout?.on("data", (chunk: Buffer) => {
291
+ const remaining = MAX_OUTPUT_BYTES - Buffer.byteLength(stdoutBuf, "utf8");
292
+ if (remaining <= 0) return;
293
+ const piece = chunk.toString("utf8");
294
+ if (Buffer.byteLength(piece, "utf8") <= remaining) {
295
+ stdoutBuf += piece;
296
+ } else {
297
+ stdoutBuf += piece.slice(0, remaining) + TRUNCATION_MARKER;
298
+ }
299
+ });
300
+
301
+ child.stderr?.on("data", (chunk: Buffer) => {
302
+ const remaining = MAX_OUTPUT_BYTES - Buffer.byteLength(stderrBuf, "utf8");
303
+ if (remaining <= 0) return;
304
+ const piece = chunk.toString("utf8");
305
+ if (Buffer.byteLength(piece, "utf8") <= remaining) {
306
+ stderrBuf += piece;
307
+ } else {
308
+ stderrBuf += piece.slice(0, remaining) + TRUNCATION_MARKER;
309
+ }
310
+ });
311
+
312
+ const exitCode = await new Promise<number>((resolve) => {
313
+ child.on("close", (code) => resolve(code ?? 1));
314
+ child.on("error", (err: NodeJS.ErrnoException) => {
315
+ if (err.name === "AbortError" || abortController.signal.aborted) {
316
+ timedOut = true;
317
+ resolve(137);
318
+ } else {
319
+ resolve(1);
320
+ }
321
+ });
322
+ });
323
+
324
+ clearTimeout(timeoutHandle);
325
+
326
+ return {
327
+ exitCode,
328
+ stdout: stdoutBuf,
329
+ stderr: stderrBuf,
330
+ timedOut,
331
+ durationMs: Date.now() - startedAt,
332
+ };
333
+ }
334
+
335
+ private toExecutionResult<T>(args: {
336
+ executionId: string;
337
+ automationName: string;
338
+ input: unknown;
339
+ startedAt: Date;
340
+ sandboxResult: SandboxResult;
341
+ }): ExecutionResult<T> {
342
+ const completedAt = new Date(
343
+ args.startedAt.getTime() + args.sandboxResult.durationMs
344
+ );
345
+ const logs = parseStderrLogs(args.sandboxResult.stderr);
346
+
347
+ if (args.sandboxResult.timedOut) {
348
+ return {
349
+ executionId: args.executionId,
350
+ automationName: args.automationName,
351
+ status: "timeout",
352
+ input: args.input,
353
+ error: {
354
+ code: "TIMEOUT",
355
+ message: `execution timed out after ${args.sandboxResult.durationMs}ms`,
356
+ },
357
+ startedAt: args.startedAt,
358
+ completedAt,
359
+ durationMs: args.sandboxResult.durationMs,
360
+ logs,
361
+ };
362
+ }
363
+
364
+ // Try to parse the protocol result FIRST — a non-zero exit with a valid
365
+ // protocol "failed" payload is a business failure, not a container crash.
366
+ try {
367
+ const protocol = parseProtocolOutput<T>(args.sandboxResult.stdout);
368
+ if (protocol.status === "completed") {
369
+ return {
370
+ executionId: args.executionId,
371
+ automationName: args.automationName,
372
+ status: "completed",
373
+ input: args.input,
374
+ output: protocol.output,
375
+ startedAt: args.startedAt,
376
+ completedAt,
377
+ durationMs: args.sandboxResult.durationMs,
378
+ logs,
379
+ };
380
+ }
381
+ return {
382
+ executionId: args.executionId,
383
+ automationName: args.automationName,
384
+ status: "failed",
385
+ input: args.input,
386
+ error: { ...protocol.error },
387
+ startedAt: args.startedAt,
388
+ completedAt,
389
+ durationMs: args.sandboxResult.durationMs,
390
+ logs,
391
+ };
392
+ } catch (err) {
393
+ // No parseable protocol output. If the process exited non-zero, surface
394
+ // it as a container crash; otherwise the binary returned 0 but said
395
+ // nothing useful — also a protocol violation.
396
+ const code =
397
+ args.sandboxResult.exitCode === 0
398
+ ? "INVALID_OUTPUT"
399
+ : "CONTAINER_EXIT_ERROR";
400
+ const message =
401
+ args.sandboxResult.exitCode === 0
402
+ ? "process exited 0 but produced no protocol result"
403
+ : `process exited with code ${args.sandboxResult.exitCode}`;
404
+ const stderrTail = args.sandboxResult.stderr.slice(-2000);
405
+ const stdoutTail = args.sandboxResult.stdout.slice(-2000);
406
+ const rawTail = err instanceof ProtocolParseError ? err.rawTail : "";
407
+ return {
408
+ executionId: args.executionId,
409
+ automationName: args.automationName,
410
+ status: "failed",
411
+ input: args.input,
412
+ error: {
413
+ code,
414
+ message,
415
+ details: { stderr: stderrTail, stdout: stdoutTail, rawTail },
416
+ },
417
+ startedAt: args.startedAt,
418
+ completedAt,
419
+ durationMs: args.sandboxResult.durationMs,
420
+ logs,
421
+ };
422
+ }
423
+ }
424
+ }
@@ -0,0 +1,30 @@
1
+ -- 026_formal_verify_results.sql
2
+ --
3
+ -- Sprint-587 — Persistence for Z3 formal verification outcomes.
4
+ --
5
+ -- One row per (cycle_id, axiom) verification attempt. UNKNOWN and SKIPPED
6
+ -- are first-class states (NOT folded into SAFE/UNSAFE). The `mode` and
7
+ -- `context` columns preserve enough metadata to reproduce the decision
8
+ -- under a different policy without re-running the solver.
9
+
10
+ CREATE TABLE IF NOT EXISTS formal_verify_results (
11
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
12
+ cycle_id TEXT NOT NULL,
13
+ axiom TEXT NOT NULL,
14
+ state TEXT NOT NULL CHECK (state IN ('SAFE','UNSAFE','UNKNOWN','SKIPPED')),
15
+ rationale TEXT,
16
+ witness TEXT,
17
+ counterexample TEXT,
18
+ time_ms INT,
19
+ mode TEXT NOT NULL DEFAULT 'permissive'
20
+ CHECK (mode IN ('strict','permissive','audit_only')),
21
+ context TEXT NOT NULL DEFAULT 'runtime'
22
+ CHECK (context IN ('runtime','skill_ingestion')),
23
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
24
+ );
25
+
26
+ CREATE INDEX IF NOT EXISTS idx_formal_verify_cycle
27
+ ON formal_verify_results (cycle_id);
28
+
29
+ CREATE INDEX IF NOT EXISTS idx_formal_verify_state
30
+ ON formal_verify_results (state, created_at DESC);