@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,237 @@
1
+ /**
2
+ * E2E parity test — POC-B SKILL.md vs original web-search.ts
3
+ *
4
+ * Runs BOTH the original TS skill and the MD-loaded variant against
5
+ * the same mocked fetch, then compares output shape + content.
6
+ * Measures cold start of the MD loader path.
7
+ *
8
+ * No network calls — fetch is mocked via globalThis.fetch override.
9
+ *
10
+ * @poc-jetable
11
+ */
12
+
13
+ import { describe, it, expect, beforeEach, afterEach, vi } from "vitest";
14
+ import { join, dirname } from "node:path";
15
+ import { fileURLToPath } from "node:url";
16
+
17
+ // ── Original skill (TS) ───────────────────────────────────────────────────────
18
+ import { webSearch } from "../web-search.js";
19
+ import type { WebSearchOutput } from "../web-search.js";
20
+
21
+ // ── POC loader ────────────────────────────────────────────────────────────────
22
+ import { loadSkillMd } from "./markdown-loader.js";
23
+ import { runSkillMd } from "./runner.js";
24
+
25
+ const __dirname = dirname(fileURLToPath(import.meta.url));
26
+ const SKILL_DIR = join(__dirname, "web-search");
27
+
28
+ // ── Mock fetch helpers ────────────────────────────────────────────────────────
29
+
30
+ const BRAVE_MOCK_RESPONSE = {
31
+ web: {
32
+ results: [
33
+ {
34
+ title: "Mock Result 1",
35
+ url: "https://example.com/1",
36
+ description: "Snippet one",
37
+ },
38
+ {
39
+ title: "Mock Result 2",
40
+ url: "https://example.com/2",
41
+ description: "Snippet two",
42
+ },
43
+ ],
44
+ },
45
+ };
46
+
47
+ function mockFetch(response: unknown, status = 200) {
48
+ return vi.fn().mockResolvedValue({
49
+ ok: status >= 200 && status < 300,
50
+ status,
51
+ json: async () => response,
52
+ });
53
+ }
54
+
55
+ // ── Replay context for original skill ────────────────────────────────────────
56
+
57
+ const REPLAY_CTX = {
58
+ isReplay: true,
59
+ dryRunMocks: {
60
+ web_search: (_input: unknown) => ({
61
+ results: [
62
+ {
63
+ title: "Mock Result 1",
64
+ url: "https://example.com/1",
65
+ snippet: "Snippet one",
66
+ },
67
+ {
68
+ title: "Mock Result 2",
69
+ url: "https://example.com/2",
70
+ snippet: "Snippet two",
71
+ },
72
+ ],
73
+ provider: "replay" as const,
74
+ }),
75
+ },
76
+ agentId: "poc-test",
77
+ runId: "poc-run-1",
78
+ };
79
+
80
+ // ── Tests ─────────────────────────────────────────────────────────────────────
81
+
82
+ describe("POC-B: SKILL.md parity + cold start", () => {
83
+ let originalFetch: typeof globalThis.fetch;
84
+
85
+ beforeEach(() => {
86
+ originalFetch = globalThis.fetch;
87
+ });
88
+
89
+ afterEach(() => {
90
+ globalThis.fetch = originalFetch;
91
+ delete process.env.BRAVE_SEARCH_KEY;
92
+ delete process.env.TAVILY_API_KEY;
93
+ });
94
+
95
+ // ── 1. Manifest loading ──────────────────────────────────────────────────
96
+
97
+ it("loads SKILL.md and returns valid manifest", async () => {
98
+ const { manifest } = await loadSkillMd(join(SKILL_DIR, "SKILL.md"));
99
+
100
+ expect(manifest.name).toBe("web-search");
101
+ expect(manifest.description).toBeTruthy();
102
+ expect(manifest.description.length).toBeLessThanOrEqual(1024);
103
+ expect(manifest["allowed-tools"]).toBe("Bash(curl:*)");
104
+ expect(manifest.metadata?.version).toBe("1.0.0");
105
+ expect(manifest.metadata?.category).toBe("search");
106
+ expect(manifest.metadata?.["env-mode"]).toBe("at-least-one");
107
+ });
108
+
109
+ // ── 2. Output shape parity (replay vs MD) ───────────────────────────────
110
+
111
+ it("MD output shape matches original skill output shape (replay)", async () => {
112
+ // Original skill in replay mode
113
+ const originalOutput = await webSearch.execute(
114
+ { query: "test", limit: 2 },
115
+ REPLAY_CTX as never
116
+ );
117
+
118
+ // MD script in replay mode (mock fetch, BRAVE_SEARCH_KEY set → path taken but mocked)
119
+ process.env.BRAVE_SEARCH_KEY = "test-key";
120
+ globalThis.fetch = mockFetch(BRAVE_MOCK_RESPONSE) as never;
121
+
122
+ const { output: mdOutput } = await runSkillMd<WebSearchOutput>(SKILL_DIR, {
123
+ query: "test",
124
+ limit: 2,
125
+ });
126
+
127
+ // Shape parity: both have results[] and provider
128
+ expect(Object.keys(mdOutput)).toEqual(
129
+ expect.arrayContaining(["results", "provider"])
130
+ );
131
+ expect(Array.isArray(mdOutput.results)).toBe(true);
132
+
133
+ // Original replay returns empty results (no mock for live), MD returns from brave mock
134
+ // Key parity: result items have title/url/snippet
135
+ if (mdOutput.results.length > 0) {
136
+ const r = mdOutput.results[0];
137
+ expect(r).toHaveProperty("title");
138
+ expect(r).toHaveProperty("url");
139
+ expect(r).toHaveProperty("snippet");
140
+ }
141
+
142
+ // Provider field exists and is valid
143
+ expect(["brave", "tavily", "replay"]).toContain(mdOutput.provider);
144
+ });
145
+
146
+ // ── 3. Live path parity (both use mocked fetch, same brave response) ────
147
+
148
+ it("MD script returns same data as original skill on Brave success path", async () => {
149
+ process.env.BRAVE_SEARCH_KEY = "test-brave-key";
150
+ globalThis.fetch = mockFetch(BRAVE_MOCK_RESPONSE) as never;
151
+
152
+ // Original skill — live path with mocked fetch
153
+ const originalOutput = await webSearch.execute(
154
+ { query: "starknet", limit: 2 },
155
+ { isReplay: false, dryRunMocks: {}, agentId: "poc", runId: "r1" } as never
156
+ );
157
+
158
+ // Reset mock (fresh call counter)
159
+ globalThis.fetch = mockFetch(BRAVE_MOCK_RESPONSE) as never;
160
+
161
+ const { output: mdOutput } = await runSkillMd<WebSearchOutput>(SKILL_DIR, {
162
+ query: "starknet",
163
+ limit: 2,
164
+ });
165
+
166
+ // Full output equality
167
+ expect(mdOutput.provider).toBe(originalOutput.provider);
168
+ expect(mdOutput.results).toEqual(originalOutput.results);
169
+ });
170
+
171
+ // ── 4. Tavily fallback parity ────────────────────────────────────────────
172
+
173
+ it("MD script Tavily fallback matches original skill", async () => {
174
+ process.env.TAVILY_API_KEY = "test-tavily-key";
175
+ // No BRAVE key → goes straight to Tavily
176
+
177
+ const tavilyMock = {
178
+ results: [
179
+ {
180
+ title: "Tavily R1",
181
+ url: "https://tavily.com/1",
182
+ content: "Tavily snippet 1",
183
+ },
184
+ ],
185
+ };
186
+
187
+ globalThis.fetch = mockFetch(tavilyMock) as never;
188
+ const originalOutput = await webSearch.execute(
189
+ { query: "cairo", limit: 1 },
190
+ { isReplay: false, dryRunMocks: {}, agentId: "poc", runId: "r2" } as never
191
+ );
192
+
193
+ globalThis.fetch = mockFetch(tavilyMock) as never;
194
+ const { output: mdOutput } = await runSkillMd<WebSearchOutput>(SKILL_DIR, {
195
+ query: "cairo",
196
+ limit: 1,
197
+ });
198
+
199
+ expect(mdOutput.provider).toBe("tavily");
200
+ expect(mdOutput.provider).toBe(originalOutput.provider);
201
+ expect(mdOutput.results).toEqual(originalOutput.results);
202
+ });
203
+
204
+ // ── 5. Error parity: missing env ────────────────────────────────────────
205
+
206
+ it("MD runner throws when no API key configured (env-mode: at-least-one)", async () => {
207
+ // No BRAVE_SEARCH_KEY, no TAVILY_API_KEY
208
+ await expect(runSkillMd(SKILL_DIR, { query: "test" })).rejects.toThrow(
209
+ /at least one of/i
210
+ );
211
+ });
212
+
213
+ // ── 6. Cold start measurement ────────────────────────────────────────────
214
+
215
+ it("cold start (load+parse+execute) is under 500ms", async () => {
216
+ process.env.BRAVE_SEARCH_KEY = "perf-test-key";
217
+ globalThis.fetch = mockFetch(BRAVE_MOCK_RESPONSE) as never;
218
+
219
+ const t0 = performance.now();
220
+ const { coldStartMs } = await runSkillMd(SKILL_DIR, {
221
+ query: "perf",
222
+ limit: 1,
223
+ });
224
+ const wallMs = performance.now() - t0;
225
+
226
+ console.log(
227
+ `[POC-B] cold start: ${coldStartMs.toFixed(2)}ms (wall: ${wallMs.toFixed(
228
+ 2
229
+ )}ms)`
230
+ );
231
+
232
+ // Primary assertion
233
+ expect(coldStartMs).toBeLessThan(500);
234
+ // Sanity: internal timer matches wall clock within 50ms
235
+ expect(Math.abs(coldStartMs - wallMs)).toBeLessThan(50);
236
+ });
237
+ });
@@ -0,0 +1,161 @@
1
+ /**
2
+ * markdown-loader — prototype SKILL.md parser.
3
+ *
4
+ * Parses frontmatter (YAML-subset, no external dep) + markdown body.
5
+ * Returns a typed SkillManifest validated against a Zod schema.
6
+ *
7
+ * Constraint: no new npm deps — uses only node:fs/promises + zod (already in pkg).
8
+ *
9
+ * @poc-jetable
10
+ */
11
+
12
+ import { readFile } from "node:fs/promises";
13
+ import { z } from "zod";
14
+
15
+ // ── Zod schema for SKILL.md frontmatter ──────────────────────────────────────
16
+
17
+ const MetadataSchema = z
18
+ .object({
19
+ version: z.string().default("1.0.0"),
20
+ category: z.string().optional(),
21
+ tags: z.string().optional(),
22
+ "model-hint": z.string().optional(),
23
+ "env-required": z.string().optional(),
24
+ "env-mode": z.enum(["all", "at-least-one"]).default("all"),
25
+ })
26
+ .strict();
27
+
28
+ export const SkillManifestSchema = z
29
+ .object({
30
+ /** kebab-case, 1-64 chars */
31
+ name: z
32
+ .string()
33
+ .min(1)
34
+ .max(64)
35
+ .regex(/^[a-z0-9-]+$/, "name must be kebab-case"),
36
+ /** 1-1024 chars */
37
+ description: z.string().min(1).max(1024),
38
+ /** Space-separated tool grant list, e.g. "Bash(curl:*) Read" */
39
+ "allowed-tools": z.string().optional(),
40
+ metadata: MetadataSchema.optional(),
41
+ })
42
+ .strict();
43
+
44
+ export type SkillManifest = z.infer<typeof SkillManifestSchema>;
45
+
46
+ // ── Minimal YAML-subset parser (no external dep) ─────────────────────────────
47
+ // Supports: string scalars, nested objects (2-space indent), multi-line > strings.
48
+
49
+ function parseYamlSubset(raw: string): Record<string, unknown> {
50
+ const lines = raw.split("\n");
51
+ const result: Record<string, unknown> = {};
52
+ let i = 0;
53
+
54
+ while (i < lines.length) {
55
+ const line = lines[i];
56
+ if (!line.trim() || line.trim().startsWith("#")) {
57
+ i++;
58
+ continue;
59
+ }
60
+
61
+ const colonIdx = line.indexOf(":");
62
+ if (colonIdx === -1) {
63
+ i++;
64
+ continue;
65
+ }
66
+
67
+ const indent = line.match(/^(\s*)/)?.[1].length ?? 0;
68
+ if (indent > 0) {
69
+ // nested key — handled by parent
70
+ i++;
71
+ continue;
72
+ }
73
+
74
+ const key = line.slice(0, colonIdx).trim();
75
+ const rest = line.slice(colonIdx + 1).trim();
76
+
77
+ // Multi-line folded scalar (>) — collect continuation lines
78
+ if (rest === ">") {
79
+ const parts: string[] = [];
80
+ i++;
81
+ while (
82
+ i < lines.length &&
83
+ (lines[i].startsWith(" ") || lines[i].trim() === "")
84
+ ) {
85
+ parts.push(lines[i].trim());
86
+ i++;
87
+ }
88
+ result[key] = parts.filter(Boolean).join(" ");
89
+ continue;
90
+ }
91
+
92
+ // Nested object — collect child lines with 2-space indent
93
+ if (rest === "") {
94
+ const childLines: string[] = [];
95
+ i++;
96
+ while (i < lines.length && lines[i].startsWith(" ")) {
97
+ childLines.push(lines[i].slice(2)); // strip 2-space indent
98
+ i++;
99
+ }
100
+ if (childLines.length > 0) {
101
+ result[key] = parseYamlSubset(childLines.join("\n"));
102
+ }
103
+ continue;
104
+ }
105
+
106
+ // Quoted string
107
+ if (
108
+ (rest.startsWith('"') && rest.endsWith('"')) ||
109
+ (rest.startsWith("'") && rest.endsWith("'"))
110
+ ) {
111
+ result[key] = rest.slice(1, -1);
112
+ i++;
113
+ continue;
114
+ }
115
+
116
+ // Plain scalar
117
+ result[key] = rest;
118
+ i++;
119
+ }
120
+
121
+ return result;
122
+ }
123
+
124
+ // ── SKILL.md parser ───────────────────────────────────────────────────────────
125
+
126
+ export interface ParsedSkillFile {
127
+ manifest: SkillManifest;
128
+ body: string;
129
+ }
130
+
131
+ /**
132
+ * Parse a SKILL.md file at `filePath`.
133
+ * Extracts frontmatter (between --- delimiters) and validates with Zod.
134
+ * Returns typed manifest + raw markdown body.
135
+ */
136
+ export async function loadSkillMd(filePath: string): Promise<ParsedSkillFile> {
137
+ const raw = await readFile(filePath, "utf-8");
138
+
139
+ // Extract frontmatter block
140
+ const fmMatch = raw.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n([\s\S]*)$/);
141
+ if (!fmMatch) {
142
+ throw new Error(
143
+ `SKILL.md at ${filePath}: missing or malformed frontmatter (expected --- delimiters)`
144
+ );
145
+ }
146
+
147
+ const [, frontmatter, body] = fmMatch;
148
+ const rawParsed = parseYamlSubset(frontmatter);
149
+
150
+ // Validate with Zod
151
+ const result = SkillManifestSchema.safeParse(rawParsed);
152
+ if (!result.success) {
153
+ throw new Error(
154
+ `SKILL.md at ${filePath}: invalid frontmatter — ${result.error.issues
155
+ .map((i) => `${i.path.join(".")}: ${i.message}`)
156
+ .join("; ")}`
157
+ );
158
+ }
159
+
160
+ return { manifest: result.data, body: body.trim() };
161
+ }
@@ -0,0 +1,82 @@
1
+ /**
2
+ * runner — prototype SKILL.md execution harness.
3
+ *
4
+ * Loads a SKILL.md manifest, validates env requirements,
5
+ * dynamically imports the companion script.ts, and executes it.
6
+ *
7
+ * No integration with SkillRegistry — standalone POC harness only.
8
+ *
9
+ * @poc-jetable
10
+ */
11
+
12
+ import { join } from "node:path";
13
+ import { loadSkillMd, type SkillManifest } from "./markdown-loader.js";
14
+
15
+ export interface RunnerResult<T = unknown> {
16
+ output: T;
17
+ manifest: SkillManifest;
18
+ coldStartMs: number;
19
+ }
20
+
21
+ /**
22
+ * Run a SKILL.md skill by directory path.
23
+ *
24
+ * @param skillDir Absolute path to directory containing SKILL.md + script.ts
25
+ * @param input Raw input object passed to script.execute()
26
+ */
27
+ export async function runSkillMd<T = unknown>(
28
+ skillDir: string,
29
+ input: unknown
30
+ ): Promise<RunnerResult<T>> {
31
+ const t0 = performance.now();
32
+
33
+ // Step 1: Load + validate SKILL.md
34
+ const skillMdPath = join(skillDir, "SKILL.md");
35
+ const { manifest } = await loadSkillMd(skillMdPath);
36
+
37
+ // Step 2: Check env requirements
38
+ const envRequired = manifest.metadata?.["env-required"];
39
+ const envMode = manifest.metadata?.["env-mode"] ?? "all";
40
+ if (envRequired) {
41
+ const keys = envRequired.split(" ").filter(Boolean);
42
+ const missing = keys.filter((k) => !process.env[k]);
43
+ if (envMode === "all" && missing.length > 0) {
44
+ throw new Error(
45
+ `Skill '${manifest.name}': missing required env vars: ${missing.join(
46
+ ", "
47
+ )}`
48
+ );
49
+ }
50
+ if (envMode === "at-least-one" && missing.length === keys.length) {
51
+ throw new Error(
52
+ `Skill '${manifest.name}': at least one of ${keys.join(
53
+ ", "
54
+ )} must be set`
55
+ );
56
+ }
57
+ }
58
+
59
+ // Step 3: Dynamic import of companion script
60
+ const scriptPath = join(skillDir, "script.js");
61
+ // In test context (tsx/ts-node), import .ts directly; in compiled, import .js
62
+ let scriptModule: { execute: (input: unknown) => Promise<T> };
63
+ try {
64
+ scriptModule = (await import(scriptPath)) as typeof scriptModule;
65
+ } catch {
66
+ // Fallback: try .ts extension (tsx / ts-node context)
67
+ const scriptTsPath = join(skillDir, "script.ts");
68
+ scriptModule = (await import(scriptTsPath)) as typeof scriptModule;
69
+ }
70
+
71
+ if (typeof scriptModule.execute !== "function") {
72
+ throw new Error(
73
+ `Skill '${manifest.name}': script must export an execute() function`
74
+ );
75
+ }
76
+
77
+ // Step 4: Execute
78
+ const output = await scriptModule.execute(input);
79
+ const coldStartMs = performance.now() - t0;
80
+
81
+ return { output, manifest, coldStartMs };
82
+ }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Vitest config for POC-B tests only — not part of production test suite.
3
+ * @poc-jetable
4
+ */
5
+ import { defineConfig } from "vitest/config";
6
+
7
+ export default defineConfig({
8
+ test: {
9
+ environment: "node",
10
+ include: ["src/skills/poc-md-loader/**/*.test.ts"],
11
+ globals: false,
12
+ },
13
+ });
@@ -0,0 +1,42 @@
1
+ ---
2
+ name: web-search
3
+ description: >
4
+ Search the web using Brave Search API (primary) or Tavily (fallback).
5
+ Returns ranked results with title, URL, and snippet. Requires at least
6
+ one of BRAVE_SEARCH_KEY or TAVILY_API_KEY environment variables.
7
+ allowed-tools: "Bash(curl:*)"
8
+ metadata:
9
+ version: "1.0.0"
10
+ category: "search"
11
+ tags: "brave tavily web-search"
12
+ model-hint: "sonnet"
13
+ env-required: "BRAVE_SEARCH_KEY TAVILY_API_KEY"
14
+ env-mode: "at-least-one"
15
+ ---
16
+
17
+ # web-search
18
+
19
+ Searches the web and returns structured results.
20
+
21
+ ## Input
22
+
23
+ | Field | Type | Required | Default | Description |
24
+ |---------|---------|----------|---------|--------------------------|
25
+ | `query` | string | yes | — | Search query (1-512 chars) |
26
+ | `limit` | integer | no | 5 | Max results (1-20) |
27
+
28
+ ## Output
29
+
30
+ ```json
31
+ {
32
+ "results": [
33
+ { "title": "...", "url": "...", "snippet": "..." }
34
+ ],
35
+ "provider": "brave | tavily | replay"
36
+ }
37
+ ```
38
+
39
+ ## Execution
40
+
41
+ See `script.ts` for the execution logic. The script implements the same
42
+ Brave → Tavily fallback chain as the original `web-search.ts` TS skill.
@@ -0,0 +1,109 @@
1
+ /**
2
+ * web-search execution script — POC MD loader variant.
3
+ *
4
+ * Identical logic to web-search.ts but as a standalone function
5
+ * with no SDK imports (no Skill<> interface, no withSkillSpan, no errors.ts).
6
+ * This measures the "pure script" execution path of the SKILL.md pattern.
7
+ *
8
+ * @poc-jetable
9
+ */
10
+
11
+ export interface WebSearchInput {
12
+ query: string;
13
+ limit?: number;
14
+ }
15
+
16
+ export interface WebSearchResult {
17
+ title: string;
18
+ url: string;
19
+ snippet: string;
20
+ }
21
+
22
+ export interface WebSearchOutput {
23
+ results: WebSearchResult[];
24
+ provider: "brave" | "tavily" | "replay";
25
+ }
26
+
27
+ export class SkillNotConfiguredError extends Error {
28
+ constructor(missing: string[]) {
29
+ super(`web-search not configured: missing env ${missing.join(", ")}`);
30
+ this.name = "SkillNotConfiguredError";
31
+ }
32
+ }
33
+
34
+ export class SkillExecutionError extends Error {
35
+ constructor(message: string) {
36
+ super(`web-search failed: ${message}`);
37
+ this.name = "SkillExecutionError";
38
+ }
39
+ }
40
+
41
+ /**
42
+ * Execute web search. Same logic as web-search.ts#webSearch.execute().
43
+ */
44
+ export async function execute(input: WebSearchInput): Promise<WebSearchOutput> {
45
+ const query = input.query;
46
+ const limit = input.limit ?? 5;
47
+
48
+ const braveKey = process.env.BRAVE_SEARCH_KEY;
49
+ const tavilyKey = process.env.TAVILY_API_KEY;
50
+
51
+ if (!braveKey && !tavilyKey) {
52
+ throw new SkillNotConfiguredError(["BRAVE_SEARCH_KEY", "TAVILY_API_KEY"]);
53
+ }
54
+
55
+ if (braveKey) {
56
+ const url = `https://api.search.brave.com/res/v1/web/search?q=${encodeURIComponent(
57
+ query
58
+ )}&count=${limit}`;
59
+ const res = await fetch(url, {
60
+ headers: {
61
+ Accept: "application/json",
62
+ "X-Subscription-Token": braveKey,
63
+ },
64
+ });
65
+ if (res.ok) {
66
+ const data = (await res.json()) as {
67
+ web?: {
68
+ results?: Array<{
69
+ title?: string;
70
+ url?: string;
71
+ description?: string;
72
+ }>;
73
+ };
74
+ };
75
+ const results: WebSearchResult[] = (data.web?.results ?? []).map((r) => ({
76
+ title: r.title ?? "",
77
+ url: r.url ?? "",
78
+ snippet: r.description ?? "",
79
+ }));
80
+ return { results, provider: "brave" };
81
+ }
82
+ if (!tavilyKey) {
83
+ throw new SkillExecutionError(`brave ${res.status}`);
84
+ }
85
+ }
86
+
87
+ // Tavily fallback
88
+ const res = await fetch("https://api.tavily.com/search", {
89
+ method: "POST",
90
+ headers: { "Content-Type": "application/json" },
91
+ body: JSON.stringify({
92
+ api_key: tavilyKey,
93
+ query,
94
+ max_results: limit,
95
+ }),
96
+ });
97
+ if (!res.ok) {
98
+ throw new SkillExecutionError(`tavily ${res.status}`);
99
+ }
100
+ const data = (await res.json()) as {
101
+ results?: Array<{ title?: string; url?: string; content?: string }>;
102
+ };
103
+ const results: WebSearchResult[] = (data.results ?? []).map((r) => ({
104
+ title: r.title ?? "",
105
+ url: r.url ?? "",
106
+ snippet: r.content ?? "",
107
+ }));
108
+ return { results, provider: "tavily" };
109
+ }
@@ -29,6 +29,18 @@ export interface SendEmailOutput {
29
29
  message_id: string | null;
30
30
  }
31
31
 
32
+ /**
33
+ * Prefer ctx.secrets (audit-trail-bearing) over process.env. When no secrets
34
+ * accessor is configured, falls back to env so legacy callers see no behavior
35
+ * change. When the secret is absent in both, returns undefined.
36
+ */
37
+ function readSecret(ctx: SkillContext, name: string): string | undefined {
38
+ if (ctx.secrets) {
39
+ if (ctx.secrets.has(name)) return ctx.secrets.get(name);
40
+ }
41
+ return process.env[name];
42
+ }
43
+
32
44
  export const sendEmail: Skill<SendEmailInput, SendEmailOutput> = {
33
45
  name: "send_email",
34
46
  inputSchema,
@@ -39,9 +51,9 @@ export const sendEmail: Skill<SendEmailInput, SendEmailOutput> = {
39
51
  return { delivered: false, provider: "replay", message_id: null };
40
52
  }
41
53
  return withSkillSpan("send_email", async () => {
42
- const resendKey = process.env.RESEND_API_KEY;
43
- const smtpUrl = process.env.SMTP_URL;
44
- const defaultFrom = process.env.EMAIL_FROM ?? input.from;
54
+ const resendKey = readSecret(ctx, "RESEND_API_KEY");
55
+ const smtpUrl = readSecret(ctx, "SMTP_URL");
56
+ const defaultFrom = readSecret(ctx, "EMAIL_FROM") ?? input.from;
45
57
  if (!resendKey && !smtpUrl) {
46
58
  throw new SkillNotConfiguredError("send_email", [
47
59
  "RESEND_API_KEY",