@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,253 @@
1
+ /**
2
+ * src/verify/formal/policy.ts
3
+ *
4
+ * Sprint-587 — Per-axiom policy + consumer mode resolution.
5
+ *
6
+ * The policy layer maps a 4-state {@link FormalVerifyResult} to an action
7
+ * (proceed / block / escalate / log), parameterised by :
8
+ * - the axiom (Robuste, Institutionnel, … — each has different sensitivity)
9
+ * - the consumer mode (strict / permissive / audit_only)
10
+ * - the calling context (runtime vs skill_ingestion — see Tension Sprint C)
11
+ *
12
+ * Tension Sprint C : skill-loop ingestion is ALWAYS strict on UNKNOWN.
13
+ * Even if the runtime policy says "proceed_with_log" on UNKNOWN for the
14
+ * Profitable axiom, the skill-ingestion path must refuse to ingest the
15
+ * skill until UNKNOWN becomes SAFE. This prevents UNKNOWN-tainted skills
16
+ * from accumulating in the skill library.
17
+ *
18
+ * @module verify/formal/policy
19
+ */
20
+
21
+ import type { FormalVerifyResult } from "./result.js";
22
+
23
+ /**
24
+ * Action chosen by the policy resolver.
25
+ *
26
+ * `proceed` : continue without intervention
27
+ * `block` : refuse the operation outright
28
+ * `escalate_human` : pause and request human approval (HITL)
29
+ * `log` : continue but emit an audit-grade log entry
30
+ */
31
+ export type PolicyAction = "proceed" | "block" | "escalate_human" | "log";
32
+
33
+ /**
34
+ * Strategy for handling UNKNOWN outcomes.
35
+ *
36
+ * `escalate_human` : refuse to make a unilateral decision
37
+ * `proceed_with_log` : continue and emit a regular log entry
38
+ * `proceed_with_audit_log`: continue and emit an audit-grade log entry
39
+ */
40
+ export type OnUnknown =
41
+ | "escalate_human"
42
+ | "proceed_with_log"
43
+ | "proceed_with_audit_log";
44
+
45
+ /**
46
+ * Strategy for handling UNSAFE outcomes — either hard-block or escalate.
47
+ */
48
+ export type OnUnsafe = "block" | "escalate_human";
49
+
50
+ /**
51
+ * Policy bundle for one axiom.
52
+ *
53
+ * `skillLoopStrict` is ALWAYS true by design : it is exposed as a field so
54
+ * downstream code can read it but is not configurable (see Tension Sprint C).
55
+ */
56
+ export interface AxiomPolicy {
57
+ /** Action on SAFE. Fixed at `"proceed"` — kept explicit for symmetry. */
58
+ onSafe: "proceed";
59
+ /** Action on UNSAFE. */
60
+ onUnsafe: OnUnsafe;
61
+ /** Action on UNKNOWN. */
62
+ onUnknown: OnUnknown;
63
+ /** Solver timeout for this axiom, in milliseconds. */
64
+ timeout_ms: number;
65
+ /**
66
+ * Skill-loop ingestion strict mode — always true. Exposed so callers can
67
+ * assert the invariant. Do not set to false ; Tension Sprint C invariant.
68
+ */
69
+ skillLoopStrict: boolean;
70
+ }
71
+
72
+ /**
73
+ * Default per-axiom policies.
74
+ *
75
+ * Rationale :
76
+ * Robuste / Institutionnel : hard axioms — UNSAFE blocks, UNKNOWN escalates
77
+ * SOTA : UNKNOWN allowed with audit log (SOTA evolves)
78
+ * AntiFragile / Profitable : softer — UNSAFE escalates, UNKNOWN logs
79
+ */
80
+ export const DEFAULT_POLICIES: Record<string, AxiomPolicy> = {
81
+ Robuste: {
82
+ onSafe: "proceed",
83
+ onUnsafe: "block",
84
+ onUnknown: "escalate_human",
85
+ timeout_ms: 5000,
86
+ skillLoopStrict: true,
87
+ },
88
+ Institutionnel: {
89
+ onSafe: "proceed",
90
+ onUnsafe: "block",
91
+ onUnknown: "escalate_human",
92
+ timeout_ms: 10_000,
93
+ skillLoopStrict: true,
94
+ },
95
+ SOTA: {
96
+ onSafe: "proceed",
97
+ onUnsafe: "escalate_human",
98
+ onUnknown: "proceed_with_audit_log",
99
+ timeout_ms: 2000,
100
+ skillLoopStrict: true,
101
+ },
102
+ AntiFragile: {
103
+ onSafe: "proceed",
104
+ onUnsafe: "escalate_human",
105
+ onUnknown: "proceed_with_log",
106
+ timeout_ms: 1000,
107
+ skillLoopStrict: true,
108
+ },
109
+ Profitable: {
110
+ onSafe: "proceed",
111
+ onUnsafe: "escalate_human",
112
+ onUnknown: "proceed_with_log",
113
+ timeout_ms: 1000,
114
+ skillLoopStrict: true,
115
+ },
116
+ };
117
+
118
+ /**
119
+ * Consumer-level mode for the formal verifier.
120
+ *
121
+ * `strict` : enforce all policies as declared
122
+ * `permissive` : downgrade non-critical UNSAFE to log (Robuste/Institutionnel
123
+ * remain enforced), and treat UNKNOWN as SKIPPED
124
+ * `audit_only` : never block ; map every actionable outcome to `log`
125
+ */
126
+ export type ConsumerMode = "strict" | "permissive" | "audit_only";
127
+
128
+ /**
129
+ * Calling context — distinguishes between live runtime verification and
130
+ * skill-loop ingestion. The latter has stricter rules on UNKNOWN.
131
+ */
132
+ export type VerifyContext = "runtime" | "skill_ingestion";
133
+
134
+ /**
135
+ * Resolution outcome of {@link applyPolicy}.
136
+ */
137
+ export interface PolicyDecision {
138
+ action: PolicyAction;
139
+ rationale: string;
140
+ }
141
+
142
+ /**
143
+ * Whether an axiom is in the "hard" set (Robuste, Institutionnel) whose
144
+ * UNSAFE outcomes are non-negotiable.
145
+ */
146
+ function isHardAxiom(axiom: string): boolean {
147
+ return axiom === "Robuste" || axiom === "Institutionnel";
148
+ }
149
+
150
+ /**
151
+ * Apply the policy + mode + context to a single verification result.
152
+ *
153
+ * Decision order :
154
+ * 1. SKIPPED → log
155
+ * 2. skill_ingestion + UNKNOWN → block (Tension Sprint C)
156
+ * 3. mode = audit_only → log
157
+ * 4. mode = permissive + UNKNOWN → log (treated as SKIPPED)
158
+ * 5. mode = permissive + UNSAFE + non-hard axiom → log
159
+ * 6. otherwise → policy.on{Safe,Unsafe,Unknown}
160
+ */
161
+ export function applyPolicy(
162
+ result: FormalVerifyResult,
163
+ policy: AxiomPolicy,
164
+ mode: ConsumerMode,
165
+ context: VerifyContext
166
+ ): PolicyDecision {
167
+ // 1. SKIPPED → log
168
+ if (result.state === "SKIPPED") {
169
+ return {
170
+ action: "log",
171
+ rationale: `Axiom ${result.axiom} verification was skipped (${result.rationale})`,
172
+ };
173
+ }
174
+
175
+ // 2. Tension Sprint C : skill_ingestion + UNKNOWN → block, always.
176
+ if (context === "skill_ingestion" && result.state === "UNKNOWN") {
177
+ return {
178
+ action: "block",
179
+ rationale:
180
+ `Skill ingestion refuses UNKNOWN on axiom ${result.axiom} ` +
181
+ `(Tension Sprint C : skill-loop is always strict on UNKNOWN)`,
182
+ };
183
+ }
184
+
185
+ // 3. audit_only never blocks.
186
+ if (mode === "audit_only") {
187
+ return {
188
+ action: "log",
189
+ rationale: `audit_only mode : axiom ${result.axiom} = ${result.state}`,
190
+ };
191
+ }
192
+
193
+ // SAFE is always proceed.
194
+ if (result.state === "SAFE") {
195
+ return {
196
+ action: "proceed",
197
+ rationale: `Axiom ${result.axiom} proved SAFE in ${result.time_ms.toFixed(
198
+ 0
199
+ )}ms`,
200
+ };
201
+ }
202
+
203
+ // 4 + 5. Permissive softening.
204
+ if (mode === "permissive") {
205
+ if (result.state === "UNKNOWN") {
206
+ return {
207
+ action: "log",
208
+ rationale:
209
+ `permissive mode : UNKNOWN on axiom ${result.axiom} treated as ` +
210
+ `non-blocking (${result.rationale})`,
211
+ };
212
+ }
213
+ if (result.state === "UNSAFE" && !isHardAxiom(result.axiom)) {
214
+ return {
215
+ action: "log",
216
+ rationale:
217
+ `permissive mode : UNSAFE on soft axiom ${result.axiom} downgraded ` +
218
+ `to log (${result.rationale})`,
219
+ };
220
+ }
221
+ // UNSAFE on hard axiom : fall through to strict policy.
222
+ }
223
+
224
+ // 6. Strict policy resolution.
225
+ if (result.state === "UNSAFE") {
226
+ return {
227
+ action: policy.onUnsafe,
228
+ rationale:
229
+ `UNSAFE on axiom ${result.axiom} : ${policy.onUnsafe} ` +
230
+ `(counterexample : ${result.counterexample ?? "n/a"})`,
231
+ };
232
+ }
233
+
234
+ // result.state === "UNKNOWN" (runtime context only)
235
+ switch (policy.onUnknown) {
236
+ case "escalate_human":
237
+ return {
238
+ action: "escalate_human",
239
+ rationale: `UNKNOWN on axiom ${result.axiom} : escalating (${result.rationale})`,
240
+ };
241
+ case "proceed_with_audit_log":
242
+ return {
243
+ action: "log",
244
+ rationale: `UNKNOWN on axiom ${result.axiom} : audit-log proceed (${result.rationale})`,
245
+ };
246
+ case "proceed_with_log":
247
+ default:
248
+ return {
249
+ action: "log",
250
+ rationale: `UNKNOWN on axiom ${result.axiom} : log-proceed (${result.rationale})`,
251
+ };
252
+ }
253
+ }
@@ -0,0 +1,52 @@
1
+ /**
2
+ * src/verify/formal/result.ts
3
+ *
4
+ * Sprint-587 — Z3 formal verification result type.
5
+ *
6
+ * 4-state result discipline:
7
+ * - SAFE : Z3 proved the post-conditions hold under pre-conditions
8
+ * - UNSAFE : Z3 found a counterexample (state where pre-conditions hold
9
+ * but post-conditions are violated)
10
+ * - UNKNOWN : Z3 returned `unknown` (timeout, undecidable, or solver
11
+ * limitation). EXPLICIT — never silently treated as SAFE.
12
+ * - SKIPPED : Verification not run (consumer mode = permissive opt-out,
13
+ * or solver binary unavailable when caller chooses to skip)
14
+ *
15
+ * The distinction between UNKNOWN and SAFE is the core epistemic discipline
16
+ * of this module : we never assert proof when none was produced.
17
+ *
18
+ * @module verify/formal/result
19
+ */
20
+
21
+ /**
22
+ * Discriminated state of a formal verification attempt.
23
+ */
24
+ export type FormalVerifyState = "SAFE" | "UNSAFE" | "UNKNOWN" | "SKIPPED";
25
+
26
+ /**
27
+ * Solver backend identifier — currently only Z3 or `none` (no solver).
28
+ */
29
+ export type FormalSolver = "z3" | "none";
30
+
31
+ /**
32
+ * Result of running a single axiom spec through the formal verifier.
33
+ *
34
+ * `state` : 4-state outcome (see {@link FormalVerifyState})
35
+ * `axiom` : human-readable axiom label (e.g. "Robuste")
36
+ * `rationale` : human-readable explanation of the outcome
37
+ * `witness` : when SAFE, optional UNSAT-core or proof witness string
38
+ * emitted by the solver (informational only)
39
+ * `counterexample` : when UNSAFE, SMT model (variable assignment) that
40
+ * violates the post-conditions
41
+ * `time_ms` : wall-clock time spent in the solver, in milliseconds
42
+ * `solver` : which backend produced the result
43
+ */
44
+ export interface FormalVerifyResult {
45
+ state: FormalVerifyState;
46
+ axiom: string;
47
+ rationale: string;
48
+ witness?: string;
49
+ counterexample?: string;
50
+ time_ms: number;
51
+ solver: FormalSolver;
52
+ }
@@ -0,0 +1,235 @@
1
+ /**
2
+ * src/verify/formal/solver.ts
3
+ *
4
+ * Sprint-587 — Z3 SMT solver wrapper.
5
+ *
6
+ * Strategy : avoid adding `z3-solver` as a hard npm dependency (heavy WASM
7
+ * package, ~5MB) by spawning the `z3` binary as a subprocess and piping
8
+ * SMT-LIB v2 source on stdin. If `z3` is not in PATH, the wrapper degrades
9
+ * gracefully by returning `{ sat: null }` so callers can map that to the
10
+ * UNKNOWN state.
11
+ *
12
+ * This keeps the SDK lean : consumers that want formal verification install
13
+ * `z3` system-wide (apt / brew / scoop). Consumers that do not, get UNKNOWN
14
+ * results and can route them according to their policy.
15
+ *
16
+ * @module verify/formal/solver
17
+ */
18
+
19
+ import { spawn } from "node:child_process";
20
+ import { performance } from "node:perf_hooks";
21
+
22
+ /**
23
+ * Options accepted by {@link checkSmt}.
24
+ */
25
+ export interface SolverOptions {
26
+ /** Wall-clock timeout in milliseconds. Defaults to 5000ms. */
27
+ timeout_ms?: number;
28
+ /** Optional path to the z3 binary (defaults to `z3` resolved via PATH). */
29
+ z3_path?: string;
30
+ }
31
+
32
+ /**
33
+ * Outcome of a single SMT-LIB check-sat invocation.
34
+ *
35
+ * `sat` : `true` → solver returned `sat` (formula is satisfiable, i.e.
36
+ * a counterexample exists for a violation query)
37
+ * `false` → solver returned `unsat` (no counterexample, the
38
+ * property holds)
39
+ * `null` → solver returned `unknown`, timed out, was not
40
+ * installed, or failed to run
41
+ * `model` : when `sat === true`, the textual SMT-LIB model string emitted
42
+ * by `(get-model)` — useful as a counterexample witness
43
+ * `time_ms` : wall-clock time spent waiting on the solver subprocess
44
+ * `reason` : optional human-readable diagnostic for UNKNOWN / null outcomes
45
+ */
46
+ export interface SmtCheckResult {
47
+ sat: boolean | null;
48
+ model?: string;
49
+ time_ms: number;
50
+ reason?: string;
51
+ }
52
+
53
+ const DEFAULT_TIMEOUT_MS = 5000;
54
+
55
+ /**
56
+ * Run a single SMT-LIB v2 formula through Z3 and return the satisfiability
57
+ * outcome.
58
+ *
59
+ * Convention : the caller frames the property as a NEGATION (i.e. asserts the
60
+ * conjunction of preconditions AND the negation of the postcondition). Then :
61
+ * - `sat` → counterexample found → property VIOLATED → UNSAFE
62
+ * - `unsat` → no counterexample exists → property HOLDS → SAFE
63
+ * - `unknown` / timeout / missing binary → UNKNOWN
64
+ *
65
+ * The function never throws : transport errors and missing binaries are
66
+ * surfaced via `sat: null` with a `reason` string.
67
+ */
68
+ export async function checkSmt(
69
+ smtFormula: string,
70
+ options: SolverOptions = {}
71
+ ): Promise<SmtCheckResult> {
72
+ const timeoutMs = options.timeout_ms ?? DEFAULT_TIMEOUT_MS;
73
+ const z3Path = options.z3_path ?? "z3";
74
+
75
+ const start = performance.now();
76
+
77
+ return new Promise<SmtCheckResult>((resolve) => {
78
+ let child;
79
+ try {
80
+ child = spawn(z3Path, ["-in", `-T:${Math.ceil(timeoutMs / 1000)}`], {
81
+ stdio: ["pipe", "pipe", "pipe"],
82
+ });
83
+ } catch (err) {
84
+ resolve({
85
+ sat: null,
86
+ time_ms: performance.now() - start,
87
+ reason: `z3 spawn failed : ${
88
+ err instanceof Error ? err.message : String(err)
89
+ }`,
90
+ });
91
+ return;
92
+ }
93
+
94
+ let stdout = "";
95
+ let stderr = "";
96
+ let settled = false;
97
+
98
+ const settle = (r: SmtCheckResult): void => {
99
+ if (settled) return;
100
+ settled = true;
101
+ resolve(r);
102
+ };
103
+
104
+ const timer = setTimeout(() => {
105
+ try {
106
+ child.kill("SIGKILL");
107
+ } catch {
108
+ /* ignored */
109
+ }
110
+ settle({
111
+ sat: null,
112
+ time_ms: performance.now() - start,
113
+ reason: `z3 timeout after ${timeoutMs}ms`,
114
+ });
115
+ }, timeoutMs);
116
+
117
+ child.stdout.on("data", (chunk: Buffer) => {
118
+ stdout += chunk.toString();
119
+ });
120
+ child.stderr.on("data", (chunk: Buffer) => {
121
+ stderr += chunk.toString();
122
+ });
123
+
124
+ child.on("error", (err) => {
125
+ clearTimeout(timer);
126
+ settle({
127
+ sat: null,
128
+ time_ms: performance.now() - start,
129
+ reason: `z3 not available : ${err.message}`,
130
+ });
131
+ });
132
+
133
+ child.on("close", (code) => {
134
+ clearTimeout(timer);
135
+ const time_ms = performance.now() - start;
136
+ // z3 exits 0 even on `unsat`; non-zero usually means parse error.
137
+ const out = stdout.trim();
138
+ const firstLine = out.split(/\r?\n/)[0]?.trim() ?? "";
139
+
140
+ if (firstLine === "sat") {
141
+ // Extract model block if present (everything after the first line).
142
+ const modelStart = out.indexOf("\n");
143
+ const model =
144
+ modelStart >= 0 ? out.slice(modelStart + 1).trim() : undefined;
145
+ settle({ sat: true, model: model || undefined, time_ms });
146
+ return;
147
+ }
148
+ if (firstLine === "unsat") {
149
+ settle({ sat: false, time_ms });
150
+ return;
151
+ }
152
+ if (firstLine === "unknown") {
153
+ settle({
154
+ sat: null,
155
+ time_ms,
156
+ reason:
157
+ "z3 returned unknown (likely timeout or undecidable fragment)",
158
+ });
159
+ return;
160
+ }
161
+ // Parse error or other failure : surface stderr.
162
+ settle({
163
+ sat: null,
164
+ time_ms,
165
+ reason: `z3 unexpected output (exit ${code}) : ${(stderr || out).slice(
166
+ 0,
167
+ 200
168
+ )}`,
169
+ });
170
+ });
171
+
172
+ try {
173
+ child.stdin.write(smtFormula);
174
+ child.stdin.end();
175
+ } catch (err) {
176
+ clearTimeout(timer);
177
+ settle({
178
+ sat: null,
179
+ time_ms: performance.now() - start,
180
+ reason: `z3 stdin write failed : ${
181
+ err instanceof Error ? err.message : String(err)
182
+ }`,
183
+ });
184
+ }
185
+ });
186
+ }
187
+
188
+ /**
189
+ * Probe : check whether a usable `z3` binary is reachable.
190
+ * Returns `true` if `z3 --version` exits 0 within 1s.
191
+ *
192
+ * Cached for the lifetime of the process — the binary's presence does not
193
+ * change at runtime.
194
+ */
195
+ let z3Available: boolean | undefined;
196
+
197
+ export async function isZ3Available(z3Path = "z3"): Promise<boolean> {
198
+ if (z3Available !== undefined) return z3Available;
199
+ z3Available = await new Promise<boolean>((resolve) => {
200
+ let child;
201
+ try {
202
+ child = spawn(z3Path, ["--version"], {
203
+ stdio: ["ignore", "pipe", "pipe"],
204
+ });
205
+ } catch {
206
+ resolve(false);
207
+ return;
208
+ }
209
+ const t = setTimeout(() => {
210
+ try {
211
+ child.kill("SIGKILL");
212
+ } catch {
213
+ /* ignored */
214
+ }
215
+ resolve(false);
216
+ }, 1000);
217
+ child.on("error", () => {
218
+ clearTimeout(t);
219
+ resolve(false);
220
+ });
221
+ child.on("close", (code) => {
222
+ clearTimeout(t);
223
+ resolve(code === 0);
224
+ });
225
+ });
226
+ return z3Available;
227
+ }
228
+
229
+ /**
230
+ * Test-only helper to reset the cached availability probe.
231
+ * @internal
232
+ */
233
+ export function __resetZ3AvailabilityCache(): void {
234
+ z3Available = undefined;
235
+ }