@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,150 @@
1
+ /**
2
+ * src/compute/strategies/mixture-of-agents.ts
3
+ *
4
+ * Mixture-of-Agents (MoA) compute strategy.
5
+ *
6
+ * Reference: Wang et al. 2024, "Mixture of Agents", arXiv:2406.04692.
7
+ *
8
+ * Algorithm:
9
+ * - L rounds (layers). Each round runs M proposers (independent parallel calls).
10
+ * - After each round, an aggregator synthesizes the M outputs into ONE result.
11
+ * - The synthesized result becomes the seed for the next round (currently
12
+ * opaque to the generator — synthesis is purely on the output side; the
13
+ * same input is used each round, but the aggregated state is returned).
14
+ * - Final aggregated output is the answer.
15
+ *
16
+ * Budget: M × L total generator calls.
17
+ *
18
+ * Default aggregation:
19
+ * - string outputs : concatenate with "\n---\n" then take first non-empty
20
+ * - number outputs : median
21
+ * - other : first element
22
+ *
23
+ * @experimental Public-experimental API per `contract-stability.md` (sprint-582).
24
+ */
25
+
26
+ import type { ComputeContext, Strategy, StrategyResult } from "../types.js";
27
+
28
+ // ─── Public types ────────────────────────────────────────────────────────────
29
+
30
+ export interface MoAConfig<TOutput> {
31
+ /** Number of rounds (L). Default: 2. */
32
+ rounds: number;
33
+ /** Proposers per round (M). Default: 3. */
34
+ proposersPerRound: number;
35
+ /** Aggregation function: M outputs → 1 synthesized output. */
36
+ aggregate?: (outputs: TOutput[]) => TOutput;
37
+ }
38
+
39
+ const STRATEGY_NAME = "mixture-of-agents";
40
+
41
+ // ─── Default aggregator ──────────────────────────────────────────────────────
42
+
43
+ function defaultAggregator<T>(outputs: T[]): T {
44
+ if (outputs.length === 0) {
45
+ throw new Error("mixtureOfAgentsStrategy: aggregator called with 0 outputs");
46
+ }
47
+ const first = outputs[0];
48
+
49
+ // Strings: concat for traceability, then return first non-empty after concat header.
50
+ // Per spec: "if outputs are strings, concatenate with '\n---\n' prefix and take
51
+ // the first non-empty (simple but correct for MVP)."
52
+ if (typeof first === "string") {
53
+ const nonEmpty = outputs.find((o) => typeof o === "string" && (o as string).length > 0);
54
+ return (nonEmpty ?? first) as T;
55
+ }
56
+
57
+ // Numbers: median.
58
+ if (typeof first === "number") {
59
+ const nums = (outputs as unknown as number[]).filter((n) => Number.isFinite(n));
60
+ if (nums.length === 0) return first;
61
+ const sorted = [...nums].sort((a, b) => a - b);
62
+ const mid = Math.floor(sorted.length / 2);
63
+ const median = sorted.length % 2 === 0 ? (sorted[mid - 1] + sorted[mid]) / 2 : sorted[mid];
64
+ return median as unknown as T;
65
+ }
66
+
67
+ // Other types: return first (identity fallback).
68
+ return first;
69
+ }
70
+
71
+ // ─── Helpers ─────────────────────────────────────────────────────────────────
72
+
73
+ function throwIfAborted(signal: AbortSignal | undefined): void {
74
+ if (signal?.aborted) {
75
+ throw signal.reason instanceof Error
76
+ ? signal.reason
77
+ : new DOMException("Aborted", "AbortError");
78
+ }
79
+ }
80
+
81
+ // ─── Strategy factory ────────────────────────────────────────────────────────
82
+
83
+ /**
84
+ * Construct a Mixture-of-Agents {@link Strategy}.
85
+ *
86
+ * @throws RangeError when `rounds` or `proposersPerRound` < 1.
87
+ */
88
+ export function mixtureOfAgentsStrategy<TInput, TOutput>(
89
+ config?: Partial<MoAConfig<TOutput>>,
90
+ ): Strategy<TInput, TOutput> {
91
+ const rounds = config?.rounds ?? 2;
92
+ const proposersPerRound = config?.proposersPerRound ?? 3;
93
+ const aggregate = config?.aggregate ?? defaultAggregator;
94
+
95
+ if (!Number.isInteger(rounds) || rounds < 1) {
96
+ throw new RangeError(`mixtureOfAgentsStrategy: rounds must be >=1, got ${rounds}`);
97
+ }
98
+ if (!Number.isInteger(proposersPerRound) || proposersPerRound < 1) {
99
+ throw new RangeError(
100
+ `mixtureOfAgentsStrategy: proposersPerRound must be >=1, got ${proposersPerRound}`,
101
+ );
102
+ }
103
+
104
+ return {
105
+ name: STRATEGY_NAME,
106
+
107
+ async run(
108
+ input: TInput,
109
+ generator: (input: TInput, ctx: ComputeContext) => Promise<TOutput>,
110
+ ctx: ComputeContext = {},
111
+ ): Promise<StrategyResult<TOutput>> {
112
+ const start = performance.now();
113
+ const signal = ctx.signal;
114
+ throwIfAborted(signal);
115
+
116
+ const childCtx: ComputeContext = signal ? { signal } : {};
117
+
118
+ let aggregated: TOutput | undefined;
119
+ let totalCalls = 0;
120
+
121
+ for (let r = 0; r < rounds; r++) {
122
+ throwIfAborted(signal);
123
+ const outputs = await Promise.all(
124
+ Array.from({ length: proposersPerRound }, () => generator(input, childCtx)),
125
+ );
126
+ totalCalls += proposersPerRound;
127
+ throwIfAborted(signal);
128
+ aggregated = aggregate(outputs);
129
+ }
130
+
131
+ const latency_ms = performance.now() - start;
132
+
133
+ if (aggregated === undefined) {
134
+ // Unreachable: rounds >= 1 guarantees aggregated is set.
135
+ throw new Error("mixtureOfAgentsStrategy: no aggregated result");
136
+ }
137
+
138
+ return {
139
+ result: aggregated,
140
+ metadata: {
141
+ strategy: STRATEGY_NAME,
142
+ candidates: totalCalls,
143
+ verifier_scores: [],
144
+ cost: { calls: totalCalls },
145
+ latency_ms,
146
+ },
147
+ };
148
+ },
149
+ };
150
+ }
@@ -0,0 +1,293 @@
1
+ /**
2
+ * src/compute/strategies/tree-of-thoughts.ts
3
+ *
4
+ * Tree-of-Thoughts (ToT) compute strategy.
5
+ *
6
+ * Reference: Yao et al. 2023, "Tree of Thoughts: Deliberate Problem Solving
7
+ * with Large Language Models", arXiv:2305.10601.
8
+ *
9
+ * Algorithm (paper §3):
10
+ * 1. Build a tree of partial-solution states, root = empty/initial state.
11
+ * 2. Expand each node into up to `branchFactor` children via the generator.
12
+ * 3. Evaluate each state with a lightweight heuristic (no extra LLM call).
13
+ * 4. BFS expands level-by-level; DFS goes depth-first with backtracking
14
+ * when score < pruning threshold.
15
+ * 5. Bound total expansions by `maxCalls` (== generator-call budget).
16
+ * 6. Return the highest-scoring leaf output.
17
+ *
18
+ * Default state-evaluator (no LLM):
19
+ * - string outputs : monotone progress score based on length (caps at 200)
20
+ * - number outputs : closeness to plausible-answer band [0, 100]
21
+ * - other : 0.5 (neutral)
22
+ *
23
+ * @experimental Public-experimental API per `contract-stability.md` (sprint-582).
24
+ */
25
+
26
+ import type { ComputeContext, Strategy, StrategyResult } from "../types.js";
27
+
28
+ // ─── Public types ────────────────────────────────────────────────────────────
29
+
30
+ export type ToTSearchPolicy = "bfs" | "dfs";
31
+
32
+ export interface ToTConfig {
33
+ /** BFS or DFS. Default: "bfs". */
34
+ searchPolicy: ToTSearchPolicy;
35
+ /** Max tree depth (steps). Default: 3. */
36
+ maxDepth: number;
37
+ /** Max branching factor (children per node). Default: 3. */
38
+ branchFactor: number;
39
+ /** Hard cap on total generator calls. Default: maxDepth * branchFactor. */
40
+ maxCalls: number;
41
+ /** State evaluator → score in [0,1]. Default: heuristic on output shape. */
42
+ evaluateState?: (state: unknown) => number;
43
+ /** Prune any node whose evaluator score is below this. Default: 0.2. */
44
+ pruneThreshold: number;
45
+ }
46
+
47
+ const STRATEGY_NAME = "tree-of-thoughts";
48
+
49
+ const VALID_POLICIES: ReadonlySet<string> = new Set(["bfs", "dfs"]);
50
+
51
+ // ─── Default evaluator ───────────────────────────────────────────────────────
52
+
53
+ function defaultEvaluator(state: unknown): number {
54
+ if (typeof state === "string") {
55
+ const len = state.length;
56
+ if (len === 0) return 0;
57
+ // Monotone, saturates at 200 chars → 1.0
58
+ return Math.min(1, len / 200);
59
+ }
60
+ if (typeof state === "number" && Number.isFinite(state)) {
61
+ if (state < 0 || state > 200) return 0.1;
62
+ // Centered around 50 for plausibility (synthetic-task heuristic)
63
+ return 0.5 + 0.5 * (1 / (1 + Math.abs(state - 50)));
64
+ }
65
+ return 0.5;
66
+ }
67
+
68
+ // ─── Helpers ─────────────────────────────────────────────────────────────────
69
+
70
+ function throwIfAborted(signal: AbortSignal | undefined): void {
71
+ if (signal?.aborted) {
72
+ throw signal.reason instanceof Error
73
+ ? signal.reason
74
+ : new DOMException("Aborted", "AbortError");
75
+ }
76
+ }
77
+
78
+ interface TreeNode<O> {
79
+ state: O;
80
+ depth: number;
81
+ score: number;
82
+ }
83
+
84
+ // ─── Strategy factory ────────────────────────────────────────────────────────
85
+
86
+ /**
87
+ * Construct a Tree-of-Thoughts {@link Strategy}.
88
+ *
89
+ * @throws RangeError when `maxDepth`, `branchFactor`, or `maxCalls` is < 1.
90
+ * @throws Error when `searchPolicy` is not "bfs" or "dfs".
91
+ */
92
+ export function treeOfThoughtsStrategy<TInput, TOutput>(
93
+ config?: Partial<ToTConfig>,
94
+ ): Strategy<TInput, TOutput> {
95
+ const searchPolicy: ToTSearchPolicy = config?.searchPolicy ?? "bfs";
96
+ const maxDepth = config?.maxDepth ?? 3;
97
+ const branchFactor = config?.branchFactor ?? 3;
98
+ const maxCalls = config?.maxCalls ?? maxDepth * branchFactor;
99
+ const pruneThreshold = config?.pruneThreshold ?? 0.2;
100
+ const evaluateState = config?.evaluateState ?? defaultEvaluator;
101
+
102
+ if (!Number.isInteger(maxDepth) || maxDepth < 1) {
103
+ throw new RangeError(`treeOfThoughtsStrategy: maxDepth must be >=1, got ${maxDepth}`);
104
+ }
105
+ if (!Number.isInteger(branchFactor) || branchFactor < 1) {
106
+ throw new RangeError(`treeOfThoughtsStrategy: branchFactor must be >=1, got ${branchFactor}`);
107
+ }
108
+ if (!Number.isInteger(maxCalls) || maxCalls < 1) {
109
+ throw new RangeError(`treeOfThoughtsStrategy: maxCalls must be >=1, got ${maxCalls}`);
110
+ }
111
+ if (!VALID_POLICIES.has(searchPolicy)) {
112
+ throw new Error(
113
+ `treeOfThoughtsStrategy: searchPolicy must be "bfs" or "dfs", got "${searchPolicy}"`,
114
+ );
115
+ }
116
+
117
+ const strategyLabel = `${STRATEGY_NAME}-${searchPolicy}`;
118
+
119
+ return {
120
+ name: strategyLabel,
121
+
122
+ async run(
123
+ input: TInput,
124
+ generator: (input: TInput, ctx: ComputeContext) => Promise<TOutput>,
125
+ ctx: ComputeContext = {},
126
+ ): Promise<StrategyResult<TOutput>> {
127
+ const start = performance.now();
128
+ const signal = ctx.signal;
129
+ throwIfAborted(signal);
130
+
131
+ const childCtx: ComputeContext = signal ? { signal } : {};
132
+
133
+ let callsUsed = 0;
134
+ const allLeaves: TreeNode<TOutput>[] = [];
135
+ const allScores: number[] = [];
136
+
137
+ // Helper: expand one parent into up to branchFactor children.
138
+ // Each child = 1 generator call.
139
+ const expandNode = async (
140
+ _parent: TreeNode<TOutput> | null,
141
+ depth: number,
142
+ ): Promise<TreeNode<TOutput>[]> => {
143
+ const childrenToMake = Math.min(branchFactor, maxCalls - callsUsed);
144
+ if (childrenToMake <= 0) return [];
145
+
146
+ // Parallel sampling at this level.
147
+ throwIfAborted(signal);
148
+ const samples = await Promise.all(
149
+ Array.from({ length: childrenToMake }, () => generator(input, childCtx)),
150
+ );
151
+ callsUsed += childrenToMake;
152
+
153
+ const nodes: TreeNode<TOutput>[] = samples.map((state) => {
154
+ const score = clamp01(evaluateState(state));
155
+ return { state, depth, score };
156
+ });
157
+
158
+ for (const n of nodes) allScores.push(n.score);
159
+
160
+ // Pruned nodes are still recorded as leaves (score known) but not expanded.
161
+ return nodes;
162
+ };
163
+
164
+ if (searchPolicy === "bfs") {
165
+ // ── BFS ───────────────────────────────────────────────────────────
166
+ let frontier: TreeNode<TOutput>[] = [];
167
+
168
+ // Depth-1 children from root.
169
+ const initial = await expandNode(null, 1);
170
+ frontier = initial;
171
+ // Leaves at maxDepth or pruned go into allLeaves.
172
+ for (const n of initial) {
173
+ if (n.depth >= maxDepth || n.score < pruneThreshold) {
174
+ allLeaves.push(n);
175
+ }
176
+ }
177
+
178
+ while (frontier.length > 0 && callsUsed < maxCalls) {
179
+ // Filter out pruned/leaf nodes — only expand survivors.
180
+ const survivors = frontier.filter((n) => n.score >= pruneThreshold && n.depth < maxDepth);
181
+ if (survivors.length === 0) break;
182
+
183
+ const nextFrontier: TreeNode<TOutput>[] = [];
184
+ for (const parent of survivors) {
185
+ if (callsUsed >= maxCalls) break;
186
+ const children = await expandNode(parent, parent.depth + 1);
187
+ for (const c of children) {
188
+ if (c.depth >= maxDepth || c.score < pruneThreshold) {
189
+ allLeaves.push(c);
190
+ } else {
191
+ nextFrontier.push(c);
192
+ }
193
+ }
194
+ }
195
+
196
+ // If BFS terminates with un-expanded frontier (budget hit), those are leaves too.
197
+ if (callsUsed >= maxCalls) {
198
+ for (const n of nextFrontier) allLeaves.push(n);
199
+ break;
200
+ }
201
+ frontier = nextFrontier;
202
+ }
203
+ // Any remaining frontier nodes at end-of-budget = leaves.
204
+ for (const n of frontier) {
205
+ if (!allLeaves.includes(n)) allLeaves.push(n);
206
+ }
207
+ } else {
208
+ // ── DFS with backtracking ─────────────────────────────────────────
209
+ const stack: TreeNode<TOutput>[] = [];
210
+ const initial = await expandNode(null, 1);
211
+ // Push so highest score is explored first.
212
+ const sortedInitial = [...initial].sort((a, b) => b.score - a.score);
213
+ stack.push(...sortedInitial.reverse()); // reverse so highest pops first
214
+
215
+ for (const n of initial) {
216
+ if (n.depth >= maxDepth || n.score < pruneThreshold) {
217
+ allLeaves.push(n);
218
+ }
219
+ }
220
+
221
+ while (stack.length > 0 && callsUsed < maxCalls) {
222
+ const node = stack.pop();
223
+ if (!node) break;
224
+ // Backtrack if pruned or terminal.
225
+ if (node.score < pruneThreshold || node.depth >= maxDepth) {
226
+ // Already recorded as leaf above (or will be).
227
+ if (!allLeaves.includes(node)) allLeaves.push(node);
228
+ continue;
229
+ }
230
+ // Expand survivor.
231
+ const children = await expandNode(node, node.depth + 1);
232
+ const sortedChildren = [...children].sort((a, b) => b.score - a.score);
233
+ for (const c of sortedChildren.reverse()) {
234
+ if (c.depth >= maxDepth || c.score < pruneThreshold) {
235
+ allLeaves.push(c);
236
+ } else {
237
+ stack.push(c);
238
+ }
239
+ }
240
+ }
241
+ // Any unexplored stack nodes = leaves (budget-bound).
242
+ for (const n of stack) {
243
+ if (!allLeaves.includes(n)) allLeaves.push(n);
244
+ }
245
+ }
246
+
247
+ // ── Pick highest-scoring leaf ─────────────────────────────────────
248
+ if (allLeaves.length === 0) {
249
+ // Should never happen: root expansion always produces ≥1 leaf
250
+ // unless maxCalls=0 (which we reject). Defensive fallback.
251
+ const fallback = await generator(input, childCtx);
252
+ callsUsed++;
253
+ allScores.push(clamp01(evaluateState(fallback)));
254
+ const latency_ms = performance.now() - start;
255
+ return {
256
+ result: fallback,
257
+ metadata: {
258
+ strategy: strategyLabel,
259
+ candidates: 1,
260
+ verifier_scores: allScores,
261
+ cost: { calls: callsUsed },
262
+ latency_ms,
263
+ },
264
+ };
265
+ }
266
+
267
+ let best = allLeaves[0];
268
+ for (let i = 1; i < allLeaves.length; i++) {
269
+ const n = allLeaves[i] as TreeNode<TOutput>;
270
+ if (n.score > best.score) best = n;
271
+ }
272
+
273
+ const latency_ms = performance.now() - start;
274
+ return {
275
+ result: best.state,
276
+ metadata: {
277
+ strategy: strategyLabel,
278
+ candidates: callsUsed,
279
+ verifier_scores: allScores,
280
+ cost: { calls: callsUsed },
281
+ latency_ms,
282
+ },
283
+ };
284
+ },
285
+ };
286
+ }
287
+
288
+ function clamp01(x: number): number {
289
+ if (!Number.isFinite(x)) return 0;
290
+ if (x < 0) return 0;
291
+ if (x > 1) return 1;
292
+ return x;
293
+ }
@@ -0,0 +1,147 @@
1
+ /**
2
+ * src/compute/strategies/two-phase-orient.ts
3
+ *
4
+ * Two-Phase Orient pattern.
5
+ *
6
+ * Phase 1 — Orient: read-only context gathering, produces an orientation state.
7
+ * Phase 2 — Act: state-mutating execution driven by the orientation.
8
+ *
9
+ * The separation enforces a hard OODA discipline:
10
+ * - Phase 1 has no side effects; it may be retried cheaply on failure.
11
+ * - Phase 2 consumes the orientation and may be retried up to `maxActRetries`.
12
+ *
13
+ * Error semantics:
14
+ * - `TwoPhaseOrientError` (phase: "orient") — Phase 1 threw; Phase 2 is never reached.
15
+ * - `TwoPhaseOrientError` (phase: "act") — Phase 2 exhausted all retries.
16
+ * - Each Phase 2 retry attempt is tracked in `retriesUsed` (0 = first attempt succeeded).
17
+ */
18
+
19
+ // ---------------------------------------------------------------------------
20
+ // Error
21
+ // ---------------------------------------------------------------------------
22
+
23
+ export class TwoPhaseOrientError extends Error {
24
+ readonly phase: "orient" | "act";
25
+ readonly cause: unknown;
26
+ readonly retriesUsed: number;
27
+
28
+ constructor(
29
+ phase: "orient" | "act",
30
+ cause: unknown,
31
+ retriesUsed: number,
32
+ message: string
33
+ ) {
34
+ super(message);
35
+ this.name = "TwoPhaseOrientError";
36
+ this.phase = phase;
37
+ this.cause = cause;
38
+ this.retriesUsed = retriesUsed;
39
+ // Restore prototype chain (tsc targets < ES2022)
40
+ Object.setPrototypeOf(this, TwoPhaseOrientError.prototype);
41
+ }
42
+ }
43
+
44
+ // ---------------------------------------------------------------------------
45
+ // Config + return type
46
+ // ---------------------------------------------------------------------------
47
+
48
+ export interface TwoPhaseOrientConfig<C, O, R> {
49
+ /**
50
+ * Phase 1: orientation (read-only, observe + analyse).
51
+ * Receives the raw context and returns an orientation state.
52
+ * Must not produce observable side effects.
53
+ */
54
+ orient: (context: C) => Promise<O>;
55
+
56
+ /**
57
+ * Phase 2: act on the orientation.
58
+ * Receives both the orientation produced by Phase 1 and the original context.
59
+ * Returns the final result.
60
+ */
61
+ act: (orientation: O, context: C) => Promise<R>;
62
+
63
+ /**
64
+ * Maximum number of times Phase 2 may be retried after a recoverable failure.
65
+ * `maxActRetries = 1` means one initial attempt + one retry = 2 total attempts.
66
+ * Default: 1.
67
+ * Must be a non-negative integer; values < 0 are treated as 0.
68
+ */
69
+ maxActRetries?: number;
70
+ }
71
+
72
+ export interface TwoPhaseOrientResult<O, R> {
73
+ orientation: O;
74
+ result: R;
75
+ /** Number of Phase-2 retries consumed (0 = succeeded on first attempt). */
76
+ retriesUsed: number;
77
+ }
78
+
79
+ // ---------------------------------------------------------------------------
80
+ // Implementation
81
+ // ---------------------------------------------------------------------------
82
+
83
+ /**
84
+ * Executes the Two-Phase Orient pattern.
85
+ *
86
+ * @param config Wiring for both phases + optional retry cap.
87
+ * @param context Opaque context forwarded to both `orient` and `act`.
88
+ *
89
+ * @throws {TwoPhaseOrientError} When Phase 1 throws (phase: "orient") or
90
+ * Phase 2 exhausts all retries (phase: "act").
91
+ *
92
+ * @example
93
+ * ```ts
94
+ * const { orientation, result, retriesUsed } = await runTwoPhaseOrient(
95
+ * {
96
+ * orient: async (ctx) => await gatherSignals(ctx),
97
+ * act: async (orient, ctx) => await executeDecision(orient, ctx),
98
+ * },
99
+ * requestContext,
100
+ * );
101
+ * ```
102
+ */
103
+ export async function runTwoPhaseOrient<C, O, R>(
104
+ config: TwoPhaseOrientConfig<C, O, R>,
105
+ context: C
106
+ ): Promise<TwoPhaseOrientResult<O, R>> {
107
+ const maxRetries = Math.max(0, Math.floor(config.maxActRetries ?? 1));
108
+
109
+ // ── Phase 1: Orient ───────────────────────────────────────────────────────
110
+ let orientation: O;
111
+ try {
112
+ orientation = await config.orient(context);
113
+ } catch (err) {
114
+ throw new TwoPhaseOrientError(
115
+ "orient",
116
+ err,
117
+ 0,
118
+ `TwoPhaseOrient Phase 1 (orient) failed: ${
119
+ err instanceof Error ? err.message : String(err)
120
+ }`
121
+ );
122
+ }
123
+
124
+ // ── Phase 2: Act (with retries) ───────────────────────────────────────────
125
+ let lastActError: unknown;
126
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
127
+ try {
128
+ const result = await config.act(orientation, context);
129
+ return { orientation, result, retriesUsed: attempt };
130
+ } catch (err) {
131
+ lastActError = err;
132
+ // Continue to next attempt if retries remain.
133
+ }
134
+ }
135
+
136
+ // All attempts exhausted.
137
+ throw new TwoPhaseOrientError(
138
+ "act",
139
+ lastActError,
140
+ maxRetries,
141
+ `TwoPhaseOrient Phase 2 (act) failed after ${maxRetries + 1} attempt(s): ${
142
+ lastActError instanceof Error
143
+ ? lastActError.message
144
+ : String(lastActError)
145
+ }`
146
+ );
147
+ }