@isaacriehm/cairn-core 0.1.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 (616) hide show
  1. package/LICENSE +21 -0
  2. package/dist/.tsbuildinfo +1 -0
  3. package/dist/claude/error.d.ts +33 -0
  4. package/dist/claude/error.js +58 -0
  5. package/dist/claude/error.js.map +1 -0
  6. package/dist/claude/index.d.ts +3 -0
  7. package/dist/claude/index.js +3 -0
  8. package/dist/claude/index.js.map +1 -0
  9. package/dist/claude/runner.d.ts +11 -0
  10. package/dist/claude/runner.js +132 -0
  11. package/dist/claude/runner.js.map +1 -0
  12. package/dist/claude/types.d.ts +52 -0
  13. package/dist/claude/types.js +14 -0
  14. package/dist/claude/types.js.map +1 -0
  15. package/dist/context/checkpoint.d.ts +10 -0
  16. package/dist/context/checkpoint.js +29 -0
  17. package/dist/context/checkpoint.js.map +1 -0
  18. package/dist/context/handoff-builder.d.ts +11 -0
  19. package/dist/context/handoff-builder.js +268 -0
  20. package/dist/context/handoff-builder.js.map +1 -0
  21. package/dist/context/index.d.ts +11 -0
  22. package/dist/context/index.js +11 -0
  23. package/dist/context/index.js.map +1 -0
  24. package/dist/context/spec-delta.d.ts +47 -0
  25. package/dist/context/spec-delta.js +237 -0
  26. package/dist/context/spec-delta.js.map +1 -0
  27. package/dist/decision-capture/capture.d.ts +57 -0
  28. package/dist/decision-capture/capture.js +186 -0
  29. package/dist/decision-capture/capture.js.map +1 -0
  30. package/dist/decision-capture/extractor.d.ts +20 -0
  31. package/dist/decision-capture/extractor.js +103 -0
  32. package/dist/decision-capture/extractor.js.map +1 -0
  33. package/dist/decision-capture/id.d.ts +21 -0
  34. package/dist/decision-capture/id.js +60 -0
  35. package/dist/decision-capture/id.js.map +1 -0
  36. package/dist/decision-capture/index.d.ts +25 -0
  37. package/dist/decision-capture/index.js +21 -0
  38. package/dist/decision-capture/index.js.map +1 -0
  39. package/dist/decision-capture/prompt.d.ts +15 -0
  40. package/dist/decision-capture/prompt.js +68 -0
  41. package/dist/decision-capture/prompt.js.map +1 -0
  42. package/dist/decision-capture/refinement-prompt.d.ts +25 -0
  43. package/dist/decision-capture/refinement-prompt.js +146 -0
  44. package/dist/decision-capture/refinement-prompt.js.map +1 -0
  45. package/dist/decision-capture/refinement-schema.d.ts +52 -0
  46. package/dist/decision-capture/refinement-schema.js +61 -0
  47. package/dist/decision-capture/refinement-schema.js.map +1 -0
  48. package/dist/decision-capture/refinement.d.ts +60 -0
  49. package/dist/decision-capture/refinement.js +439 -0
  50. package/dist/decision-capture/refinement.js.map +1 -0
  51. package/dist/decision-capture/schema.d.ts +70 -0
  52. package/dist/decision-capture/schema.js +71 -0
  53. package/dist/decision-capture/schema.js.map +1 -0
  54. package/dist/decision-capture/types.d.ts +201 -0
  55. package/dist/decision-capture/types.js +20 -0
  56. package/dist/decision-capture/types.js.map +1 -0
  57. package/dist/decision-capture/writer.d.ts +90 -0
  58. package/dist/decision-capture/writer.js +267 -0
  59. package/dist/decision-capture/writer.js.map +1 -0
  60. package/dist/doctor/index.d.ts +48 -0
  61. package/dist/doctor/index.js +460 -0
  62. package/dist/doctor/index.js.map +1 -0
  63. package/dist/events/index.d.ts +15 -0
  64. package/dist/events/index.js +14 -0
  65. package/dist/events/index.js.map +1 -0
  66. package/dist/events/paths.d.ts +2 -0
  67. package/dist/events/paths.js +6 -0
  68. package/dist/events/paths.js.map +1 -0
  69. package/dist/events/reader.d.ts +40 -0
  70. package/dist/events/reader.js +139 -0
  71. package/dist/events/reader.js.map +1 -0
  72. package/dist/events/writer.d.ts +61 -0
  73. package/dist/events/writer.js +68 -0
  74. package/dist/events/writer.js.map +1 -0
  75. package/dist/frontend-types.d.ts +243 -0
  76. package/dist/frontend-types.js +15 -0
  77. package/dist/frontend-types.js.map +1 -0
  78. package/dist/gc/apply.d.ts +26 -0
  79. package/dist/gc/apply.js +48 -0
  80. package/dist/gc/apply.js.map +1 -0
  81. package/dist/gc/canary.d.ts +42 -0
  82. package/dist/gc/canary.js +134 -0
  83. package/dist/gc/canary.js.map +1 -0
  84. package/dist/gc/citation-integrity.d.ts +24 -0
  85. package/dist/gc/citation-integrity.js +151 -0
  86. package/dist/gc/citation-integrity.js.map +1 -0
  87. package/dist/gc/classify.d.ts +25 -0
  88. package/dist/gc/classify.js +89 -0
  89. package/dist/gc/classify.js.map +1 -0
  90. package/dist/gc/completion-integrity.d.ts +22 -0
  91. package/dist/gc/completion-integrity.js +165 -0
  92. package/dist/gc/completion-integrity.js.map +1 -0
  93. package/dist/gc/doc-gardening.d.ts +29 -0
  94. package/dist/gc/doc-gardening.js +146 -0
  95. package/dist/gc/doc-gardening.js.map +1 -0
  96. package/dist/gc/frontmatter.d.ts +35 -0
  97. package/dist/gc/frontmatter.js +105 -0
  98. package/dist/gc/frontmatter.js.map +1 -0
  99. package/dist/gc/generator-drift.d.ts +28 -0
  100. package/dist/gc/generator-drift.js +53 -0
  101. package/dist/gc/generator-drift.js.map +1 -0
  102. package/dist/gc/index.d.ts +42 -0
  103. package/dist/gc/index.js +30 -0
  104. package/dist/gc/index.js.map +1 -0
  105. package/dist/gc/quality-update.d.ts +23 -0
  106. package/dist/gc/quality-update.js +69 -0
  107. package/dist/gc/quality-update.js.map +1 -0
  108. package/dist/gc/scope-coverage.d.ts +20 -0
  109. package/dist/gc/scope-coverage.js +70 -0
  110. package/dist/gc/scope-coverage.js.map +1 -0
  111. package/dist/gc/stub-hits.d.ts +31 -0
  112. package/dist/gc/stub-hits.js +78 -0
  113. package/dist/gc/stub-hits.js.map +1 -0
  114. package/dist/gc/sweep.d.ts +56 -0
  115. package/dist/gc/sweep.js +205 -0
  116. package/dist/gc/sweep.js.map +1 -0
  117. package/dist/gc/types.d.ts +129 -0
  118. package/dist/gc/types.js +26 -0
  119. package/dist/gc/types.js.map +1 -0
  120. package/dist/gc/walk-source.d.ts +14 -0
  121. package/dist/gc/walk-source.js +59 -0
  122. package/dist/gc/walk-source.js.map +1 -0
  123. package/dist/ground/drift.d.ts +8 -0
  124. package/dist/ground/drift.js +23 -0
  125. package/dist/ground/drift.js.map +1 -0
  126. package/dist/ground/frontmatter.d.ts +20 -0
  127. package/dist/ground/frontmatter.js +49 -0
  128. package/dist/ground/frontmatter.js.map +1 -0
  129. package/dist/ground/glob.d.ts +10 -0
  130. package/dist/ground/glob.js +46 -0
  131. package/dist/ground/glob.js.map +1 -0
  132. package/dist/ground/index.d.ts +16 -0
  133. package/dist/ground/index.js +11 -0
  134. package/dist/ground/index.js.map +1 -0
  135. package/dist/ground/ledgers.d.ts +18 -0
  136. package/dist/ground/ledgers.js +103 -0
  137. package/dist/ground/ledgers.js.map +1 -0
  138. package/dist/ground/manifest.d.ts +10 -0
  139. package/dist/ground/manifest.js +88 -0
  140. package/dist/ground/manifest.js.map +1 -0
  141. package/dist/ground/paths.d.ts +20 -0
  142. package/dist/ground/paths.js +61 -0
  143. package/dist/ground/paths.js.map +1 -0
  144. package/dist/ground/quality-grades.d.ts +11 -0
  145. package/dist/ground/quality-grades.js +98 -0
  146. package/dist/ground/quality-grades.js.map +1 -0
  147. package/dist/ground/schemas.d.ts +306 -0
  148. package/dist/ground/schemas.js +188 -0
  149. package/dist/ground/schemas.js.map +1 -0
  150. package/dist/ground/scope-index.d.ts +48 -0
  151. package/dist/ground/scope-index.js +120 -0
  152. package/dist/ground/scope-index.js.map +1 -0
  153. package/dist/ground/walk.d.ts +7 -0
  154. package/dist/ground/walk.js +53 -0
  155. package/dist/ground/walk.js.map +1 -0
  156. package/dist/hooks/bypass-detection.d.ts +28 -0
  157. package/dist/hooks/bypass-detection.js +106 -0
  158. package/dist/hooks/bypass-detection.js.map +1 -0
  159. package/dist/hooks/index.d.ts +12 -0
  160. package/dist/hooks/index.js +13 -0
  161. package/dist/hooks/index.js.map +1 -0
  162. package/dist/hooks/post-tool-use/allowlist-reader.d.ts +14 -0
  163. package/dist/hooks/post-tool-use/allowlist-reader.js +69 -0
  164. package/dist/hooks/post-tool-use/allowlist-reader.js.map +1 -0
  165. package/dist/hooks/post-tool-use/citation-scanner.d.ts +23 -0
  166. package/dist/hooks/post-tool-use/citation-scanner.js +59 -0
  167. package/dist/hooks/post-tool-use/citation-scanner.js.map +1 -0
  168. package/dist/hooks/post-tool-use/copy-scanner.d.ts +25 -0
  169. package/dist/hooks/post-tool-use/copy-scanner.js +192 -0
  170. package/dist/hooks/post-tool-use/copy-scanner.js.map +1 -0
  171. package/dist/hooks/post-tool-use/index.d.ts +19 -0
  172. package/dist/hooks/post-tool-use/index.js +15 -0
  173. package/dist/hooks/post-tool-use/index.js.map +1 -0
  174. package/dist/hooks/post-tool-use/ledger-cache.d.ts +32 -0
  175. package/dist/hooks/post-tool-use/ledger-cache.js +236 -0
  176. package/dist/hooks/post-tool-use/ledger-cache.js.map +1 -0
  177. package/dist/hooks/post-tool-use/legend-builder.d.ts +15 -0
  178. package/dist/hooks/post-tool-use/legend-builder.js +84 -0
  179. package/dist/hooks/post-tool-use/legend-builder.js.map +1 -0
  180. package/dist/hooks/post-tool-use/read-enricher.d.ts +13 -0
  181. package/dist/hooks/post-tool-use/read-enricher.js +157 -0
  182. package/dist/hooks/post-tool-use/read-enricher.js.map +1 -0
  183. package/dist/hooks/post-tool-use/write-guardian.d.ts +17 -0
  184. package/dist/hooks/post-tool-use/write-guardian.js +176 -0
  185. package/dist/hooks/post-tool-use/write-guardian.js.map +1 -0
  186. package/dist/hooks/read-enrich.d.ts +6 -0
  187. package/dist/hooks/read-enrich.js +11 -0
  188. package/dist/hooks/read-enrich.js.map +1 -0
  189. package/dist/hooks/runners/index.d.ts +12 -0
  190. package/dist/hooks/runners/index.js +11 -0
  191. package/dist/hooks/runners/index.js.map +1 -0
  192. package/dist/hooks/runners/payload.d.ts +32 -0
  193. package/dist/hooks/runners/payload.js +70 -0
  194. package/dist/hooks/runners/payload.js.map +1 -0
  195. package/dist/hooks/runners/session-end.d.ts +7 -0
  196. package/dist/hooks/runners/session-end.js +42 -0
  197. package/dist/hooks/runners/session-end.js.map +1 -0
  198. package/dist/hooks/runners/session-start.d.ts +10 -0
  199. package/dist/hooks/runners/session-start.js +167 -0
  200. package/dist/hooks/runners/session-start.js.map +1 -0
  201. package/dist/hooks/runners/stop.d.ts +18 -0
  202. package/dist/hooks/runners/stop.js +165 -0
  203. package/dist/hooks/runners/stop.js.map +1 -0
  204. package/dist/hooks/session-end.d.ts +5 -0
  205. package/dist/hooks/session-end.js +10 -0
  206. package/dist/hooks/session-end.js.map +1 -0
  207. package/dist/hooks/session-start.d.ts +7 -0
  208. package/dist/hooks/session-start.js +12 -0
  209. package/dist/hooks/session-start.js.map +1 -0
  210. package/dist/hooks/stop.d.ts +5 -0
  211. package/dist/hooks/stop.js +10 -0
  212. package/dist/hooks/stop.js.map +1 -0
  213. package/dist/hooks/write-guard.d.ts +6 -0
  214. package/dist/hooks/write-guard.js +11 -0
  215. package/dist/hooks/write-guard.js.map +1 -0
  216. package/dist/inbox.d.ts +17 -0
  217. package/dist/inbox.js +30 -0
  218. package/dist/inbox.js.map +1 -0
  219. package/dist/index.d.ts +33 -0
  220. package/dist/index.js +32 -0
  221. package/dist/index.js.map +1 -0
  222. package/dist/init/baseline-audit.d.ts +71 -0
  223. package/dist/init/baseline-audit.js +377 -0
  224. package/dist/init/baseline-audit.js.map +1 -0
  225. package/dist/init/brand-setup.d.ts +44 -0
  226. package/dist/init/brand-setup.js +201 -0
  227. package/dist/init/brand-setup.js.map +1 -0
  228. package/dist/init/daemon-autostart.d.ts +16 -0
  229. package/dist/init/daemon-autostart.js +95 -0
  230. package/dist/init/daemon-autostart.js.map +1 -0
  231. package/dist/init/detect.d.ts +25 -0
  232. package/dist/init/detect.js +319 -0
  233. package/dist/init/detect.js.map +1 -0
  234. package/dist/init/index.d.ts +32 -0
  235. package/dist/init/index.js +18 -0
  236. package/dist/init/index.js.map +1 -0
  237. package/dist/init/ingest-docs.d.ts +74 -0
  238. package/dist/init/ingest-docs.js +499 -0
  239. package/dist/init/ingest-docs.js.map +1 -0
  240. package/dist/init/init.d.ts +165 -0
  241. package/dist/init/init.js +1166 -0
  242. package/dist/init/init.js.map +1 -0
  243. package/dist/init/mapper-legacy.d.ts +148 -0
  244. package/dist/init/mapper-legacy.js +238 -0
  245. package/dist/init/mapper-legacy.js.map +1 -0
  246. package/dist/init/mapper-merge.d.ts +38 -0
  247. package/dist/init/mapper-merge.js +238 -0
  248. package/dist/init/mapper-merge.js.map +1 -0
  249. package/dist/init/mapper-parallel.d.ts +48 -0
  250. package/dist/init/mapper-parallel.js +409 -0
  251. package/dist/init/mapper-parallel.js.map +1 -0
  252. package/dist/init/mapper-prompts.d.ts +135 -0
  253. package/dist/init/mapper-prompts.js +189 -0
  254. package/dist/init/mapper-prompts.js.map +1 -0
  255. package/dist/init/mapper.d.ts +211 -0
  256. package/dist/init/mapper.js +151 -0
  257. package/dist/init/mapper.js.map +1 -0
  258. package/dist/init/module-slicer.d.ts +39 -0
  259. package/dist/init/module-slicer.js +809 -0
  260. package/dist/init/module-slicer.js.map +1 -0
  261. package/dist/init/multi-dev/index.d.ts +2 -0
  262. package/dist/init/multi-dev/index.js +2 -0
  263. package/dist/init/multi-dev/index.js.map +1 -0
  264. package/dist/init/multi-dev/install.d.ts +40 -0
  265. package/dist/init/multi-dev/install.js +139 -0
  266. package/dist/init/multi-dev/install.js.map +1 -0
  267. package/dist/init/preflight-guards.d.ts +42 -0
  268. package/dist/init/preflight-guards.js +108 -0
  269. package/dist/init/preflight-guards.js.map +1 -0
  270. package/dist/init/prompts.d.ts +61 -0
  271. package/dist/init/prompts.js +66 -0
  272. package/dist/init/prompts.js.map +1 -0
  273. package/dist/init/rules-merge/discover.d.ts +21 -0
  274. package/dist/init/rules-merge/discover.js +78 -0
  275. package/dist/init/rules-merge/discover.js.map +1 -0
  276. package/dist/init/rules-merge/index.d.ts +10 -0
  277. package/dist/init/rules-merge/index.js +6 -0
  278. package/dist/init/rules-merge/index.js.map +1 -0
  279. package/dist/init/rules-merge/ingest.d.ts +56 -0
  280. package/dist/init/rules-merge/ingest.js +336 -0
  281. package/dist/init/rules-merge/ingest.js.map +1 -0
  282. package/dist/init/rules-merge/keep-markers.d.ts +39 -0
  283. package/dist/init/rules-merge/keep-markers.js +97 -0
  284. package/dist/init/rules-merge/keep-markers.js.map +1 -0
  285. package/dist/init/rules-merge/parse-sections.d.ts +24 -0
  286. package/dist/init/rules-merge/parse-sections.js +71 -0
  287. package/dist/init/rules-merge/parse-sections.js.map +1 -0
  288. package/dist/init/rules-merge/regenerate.d.ts +33 -0
  289. package/dist/init/rules-merge/regenerate.js +163 -0
  290. package/dist/init/rules-merge/regenerate.js.map +1 -0
  291. package/dist/init/secrets.d.ts +18 -0
  292. package/dist/init/secrets.js +76 -0
  293. package/dist/init/secrets.js.map +1 -0
  294. package/dist/init/seed.d.ts +21 -0
  295. package/dist/init/seed.js +96 -0
  296. package/dist/init/seed.js.map +1 -0
  297. package/dist/init/setup-runners.d.ts +15 -0
  298. package/dist/init/setup-runners.js +143 -0
  299. package/dist/init/setup-runners.js.map +1 -0
  300. package/dist/init/source-comments/classify.d.ts +98 -0
  301. package/dist/init/source-comments/classify.js +244 -0
  302. package/dist/init/source-comments/classify.js.map +1 -0
  303. package/dist/init/source-comments/index.d.ts +8 -0
  304. package/dist/init/source-comments/index.js +5 -0
  305. package/dist/init/source-comments/index.js.map +1 -0
  306. package/dist/init/source-comments/ingest.d.ts +51 -0
  307. package/dist/init/source-comments/ingest.js +236 -0
  308. package/dist/init/source-comments/ingest.js.map +1 -0
  309. package/dist/init/source-comments/strip-replace.d.ts +106 -0
  310. package/dist/init/source-comments/strip-replace.js +284 -0
  311. package/dist/init/source-comments/strip-replace.js.map +1 -0
  312. package/dist/init/source-comments/walker.d.ts +65 -0
  313. package/dist/init/source-comments/walker.js +777 -0
  314. package/dist/init/source-comments/walker.js.map +1 -0
  315. package/dist/init/submodules.d.ts +48 -0
  316. package/dist/init/submodules.js +149 -0
  317. package/dist/init/submodules.js.map +1 -0
  318. package/dist/init/types.d.ts +55 -0
  319. package/dist/init/types.js +10 -0
  320. package/dist/init/types.js.map +1 -0
  321. package/dist/init/visual.d.ts +69 -0
  322. package/dist/init/visual.js +265 -0
  323. package/dist/init/visual.js.map +1 -0
  324. package/dist/init/walker.d.ts +82 -0
  325. package/dist/init/walker.js +585 -0
  326. package/dist/init/walker.js.map +1 -0
  327. package/dist/init/workflow-block.d.ts +34 -0
  328. package/dist/init/workflow-block.js +110 -0
  329. package/dist/init/workflow-block.js.map +1 -0
  330. package/dist/join/index.d.ts +67 -0
  331. package/dist/join/index.js +256 -0
  332. package/dist/join/index.js.map +1 -0
  333. package/dist/lock.d.ts +39 -0
  334. package/dist/lock.js +129 -0
  335. package/dist/lock.js.map +1 -0
  336. package/dist/logger.d.ts +13 -0
  337. package/dist/logger.js +78 -0
  338. package/dist/logger.js.map +1 -0
  339. package/dist/mcp/bootstrap-guard.d.ts +29 -0
  340. package/dist/mcp/bootstrap-guard.js +47 -0
  341. package/dist/mcp/bootstrap-guard.js.map +1 -0
  342. package/dist/mcp/context.d.ts +23 -0
  343. package/dist/mcp/context.js +9 -0
  344. package/dist/mcp/context.js.map +1 -0
  345. package/dist/mcp/errors.d.ts +17 -0
  346. package/dist/mcp/errors.js +23 -0
  347. package/dist/mcp/errors.js.map +1 -0
  348. package/dist/mcp/history/index.d.ts +6 -0
  349. package/dist/mcp/history/index.js +5 -0
  350. package/dist/mcp/history/index.js.map +1 -0
  351. package/dist/mcp/history/prompt.d.ts +32 -0
  352. package/dist/mcp/history/prompt.js +99 -0
  353. package/dist/mcp/history/prompt.js.map +1 -0
  354. package/dist/mcp/history/schema.d.ts +58 -0
  355. package/dist/mcp/history/schema.js +41 -0
  356. package/dist/mcp/history/schema.js.map +1 -0
  357. package/dist/mcp/history/summarizer.d.ts +81 -0
  358. package/dist/mcp/history/summarizer.js +196 -0
  359. package/dist/mcp/history/summarizer.js.map +1 -0
  360. package/dist/mcp/history/walker.d.ts +57 -0
  361. package/dist/mcp/history/walker.js +156 -0
  362. package/dist/mcp/history/walker.js.map +1 -0
  363. package/dist/mcp/index.d.ts +13 -0
  364. package/dist/mcp/index.js +9 -0
  365. package/dist/mcp/index.js.map +1 -0
  366. package/dist/mcp/path-allowlist.d.ts +29 -0
  367. package/dist/mcp/path-allowlist.js +71 -0
  368. package/dist/mcp/path-allowlist.js.map +1 -0
  369. package/dist/mcp/result.d.ts +8 -0
  370. package/dist/mcp/result.js +18 -0
  371. package/dist/mcp/result.js.map +1 -0
  372. package/dist/mcp/schemas.d.ts +192 -0
  373. package/dist/mcp/schemas.js +174 -0
  374. package/dist/mcp/schemas.js.map +1 -0
  375. package/dist/mcp/serve.d.ts +15 -0
  376. package/dist/mcp/serve.js +71 -0
  377. package/dist/mcp/serve.js.map +1 -0
  378. package/dist/mcp/server.d.ts +11 -0
  379. package/dist/mcp/server.js +58 -0
  380. package/dist/mcp/server.js.map +1 -0
  381. package/dist/mcp/telemetry.d.ts +15 -0
  382. package/dist/mcp/telemetry.js +13 -0
  383. package/dist/mcp/telemetry.js.map +1 -0
  384. package/dist/mcp/tools/append-run-note.d.ts +18 -0
  385. package/dist/mcp/tools/append-run-note.js +47 -0
  386. package/dist/mcp/tools/append-run-note.js.map +1 -0
  387. package/dist/mcp/tools/append.d.ts +8 -0
  388. package/dist/mcp/tools/append.js +37 -0
  389. package/dist/mcp/tools/append.js.map +1 -0
  390. package/dist/mcp/tools/archive.d.ts +8 -0
  391. package/dist/mcp/tools/archive.js +72 -0
  392. package/dist/mcp/tools/archive.js.map +1 -0
  393. package/dist/mcp/tools/ask-operator.d.ts +34 -0
  394. package/dist/mcp/tools/ask-operator.js +97 -0
  395. package/dist/mcp/tools/ask-operator.js.map +1 -0
  396. package/dist/mcp/tools/canonical-for-topic.d.ts +6 -0
  397. package/dist/mcp/tools/canonical-for-topic.js +40 -0
  398. package/dist/mcp/tools/canonical-for-topic.js.map +1 -0
  399. package/dist/mcp/tools/decision-get.d.ts +6 -0
  400. package/dist/mcp/tools/decision-get.js +49 -0
  401. package/dist/mcp/tools/decision-get.js.map +1 -0
  402. package/dist/mcp/tools/decisions-for-symbol.d.ts +7 -0
  403. package/dist/mcp/tools/decisions-for-symbol.js +42 -0
  404. package/dist/mcp/tools/decisions-for-symbol.js.map +1 -0
  405. package/dist/mcp/tools/decisions-in-scope.d.ts +7 -0
  406. package/dist/mcp/tools/decisions-in-scope.js +47 -0
  407. package/dist/mcp/tools/decisions-in-scope.js.map +1 -0
  408. package/dist/mcp/tools/drop-task.d.ts +12 -0
  409. package/dist/mcp/tools/drop-task.js +68 -0
  410. package/dist/mcp/tools/drop-task.js.map +1 -0
  411. package/dist/mcp/tools/get-full.d.ts +7 -0
  412. package/dist/mcp/tools/get-full.js +46 -0
  413. package/dist/mcp/tools/get-full.js.map +1 -0
  414. package/dist/mcp/tools/ground-get.d.ts +7 -0
  415. package/dist/mcp/tools/ground-get.js +77 -0
  416. package/dist/mcp/tools/ground-get.js.map +1 -0
  417. package/dist/mcp/tools/index.d.ts +3 -0
  418. package/dist/mcp/tools/index.js +40 -0
  419. package/dist/mcp/tools/index.js.map +1 -0
  420. package/dist/mcp/tools/invariant-get.d.ts +6 -0
  421. package/dist/mcp/tools/invariant-get.js +49 -0
  422. package/dist/mcp/tools/invariant-get.js.map +1 -0
  423. package/dist/mcp/tools/invariants-in-scope.d.ts +7 -0
  424. package/dist/mcp/tools/invariants-in-scope.js +62 -0
  425. package/dist/mcp/tools/invariants-in-scope.js.map +1 -0
  426. package/dist/mcp/tools/query-history.d.ts +20 -0
  427. package/dist/mcp/tools/query-history.js +51 -0
  428. package/dist/mcp/tools/query-history.js.map +1 -0
  429. package/dist/mcp/tools/record-decision.d.ts +14 -0
  430. package/dist/mcp/tools/record-decision.js +98 -0
  431. package/dist/mcp/tools/record-decision.js.map +1 -0
  432. package/dist/mcp/tools/record-run-event.d.ts +10 -0
  433. package/dist/mcp/tools/record-run-event.js +32 -0
  434. package/dist/mcp/tools/record-run-event.js.map +1 -0
  435. package/dist/mcp/tools/resolve-attention.d.ts +31 -0
  436. package/dist/mcp/tools/resolve-attention.js +191 -0
  437. package/dist/mcp/tools/resolve-attention.js.map +1 -0
  438. package/dist/mcp/tools/search.d.ts +9 -0
  439. package/dist/mcp/tools/search.js +164 -0
  440. package/dist/mcp/tools/search.js.map +1 -0
  441. package/dist/mcp/tools/supersedes-chain.d.ts +6 -0
  442. package/dist/mcp/tools/supersedes-chain.js +66 -0
  443. package/dist/mcp/tools/supersedes-chain.js.map +1 -0
  444. package/dist/mcp/tools/timeline.d.ts +9 -0
  445. package/dist/mcp/tools/timeline.js +65 -0
  446. package/dist/mcp/tools/timeline.js.map +1 -0
  447. package/dist/mcp/tools/types.d.ts +9 -0
  448. package/dist/mcp/tools/types.js +2 -0
  449. package/dist/mcp/tools/types.js.map +1 -0
  450. package/dist/mirror/clone.d.ts +6 -0
  451. package/dist/mirror/clone.js +48 -0
  452. package/dist/mirror/clone.js.map +1 -0
  453. package/dist/mirror/dirty-overlap.d.ts +13 -0
  454. package/dist/mirror/dirty-overlap.js +42 -0
  455. package/dist/mirror/dirty-overlap.js.map +1 -0
  456. package/dist/mirror/index.d.ts +7 -0
  457. package/dist/mirror/index.js +7 -0
  458. package/dist/mirror/index.js.map +1 -0
  459. package/dist/mirror/paths.d.ts +18 -0
  460. package/dist/mirror/paths.js +45 -0
  461. package/dist/mirror/paths.js.map +1 -0
  462. package/dist/mirror/push.d.ts +9 -0
  463. package/dist/mirror/push.js +27 -0
  464. package/dist/mirror/push.js.map +1 -0
  465. package/dist/mirror/state.d.ts +4 -0
  466. package/dist/mirror/state.js +36 -0
  467. package/dist/mirror/state.js.map +1 -0
  468. package/dist/mirror/sync.d.ts +9 -0
  469. package/dist/mirror/sync.js +33 -0
  470. package/dist/mirror/sync.js.map +1 -0
  471. package/dist/mirror/types.d.ts +77 -0
  472. package/dist/mirror/types.js +2 -0
  473. package/dist/mirror/types.js.map +1 -0
  474. package/dist/paths/index.d.ts +23 -0
  475. package/dist/paths/index.js +50 -0
  476. package/dist/paths/index.js.map +1 -0
  477. package/dist/profiles/index.d.ts +3 -0
  478. package/dist/profiles/index.js +3 -0
  479. package/dist/profiles/index.js.map +1 -0
  480. package/dist/profiles/registry.d.ts +5 -0
  481. package/dist/profiles/registry.js +31 -0
  482. package/dist/profiles/registry.js.map +1 -0
  483. package/dist/profiles/types.d.ts +48 -0
  484. package/dist/profiles/types.js +11 -0
  485. package/dist/profiles/types.js.map +1 -0
  486. package/dist/profiles/unknown.d.ts +9 -0
  487. package/dist/profiles/unknown.js +17 -0
  488. package/dist/profiles/unknown.js.map +1 -0
  489. package/dist/prompt.d.ts +19 -0
  490. package/dist/prompt.js +50 -0
  491. package/dist/prompt.js.map +1 -0
  492. package/dist/sensors/attestation.d.ts +44 -0
  493. package/dist/sensors/attestation.js +262 -0
  494. package/dist/sensors/attestation.js.map +1 -0
  495. package/dist/sensors/catalog.d.ts +41 -0
  496. package/dist/sensors/catalog.js +123 -0
  497. package/dist/sensors/catalog.js.map +1 -0
  498. package/dist/sensors/decisions.d.ts +30 -0
  499. package/dist/sensors/decisions.js +393 -0
  500. package/dist/sensors/decisions.js.map +1 -0
  501. package/dist/sensors/diff.d.ts +27 -0
  502. package/dist/sensors/diff.js +148 -0
  503. package/dist/sensors/diff.js.map +1 -0
  504. package/dist/sensors/index.d.ts +13 -0
  505. package/dist/sensors/index.js +9 -0
  506. package/dist/sensors/index.js.map +1 -0
  507. package/dist/sensors/remediation.d.ts +20 -0
  508. package/dist/sensors/remediation.js +65 -0
  509. package/dist/sensors/remediation.js.map +1 -0
  510. package/dist/sensors/runner.d.ts +44 -0
  511. package/dist/sensors/runner.js +95 -0
  512. package/dist/sensors/runner.js.map +1 -0
  513. package/dist/sensors/structural.d.ts +30 -0
  514. package/dist/sensors/structural.js +204 -0
  515. package/dist/sensors/structural.js.map +1 -0
  516. package/dist/sensors/stub-catalog.d.ts +39 -0
  517. package/dist/sensors/stub-catalog.js +115 -0
  518. package/dist/sensors/stub-catalog.js.map +1 -0
  519. package/dist/sensors/types.d.ts +135 -0
  520. package/dist/sensors/types.js +14 -0
  521. package/dist/sensors/types.js.map +1 -0
  522. package/dist/session/events-marker.d.ts +39 -0
  523. package/dist/session/events-marker.js +74 -0
  524. package/dist/session/events-marker.js.map +1 -0
  525. package/dist/session/id.d.ts +83 -0
  526. package/dist/session/id.js +166 -0
  527. package/dist/session/id.js.map +1 -0
  528. package/dist/session/index.d.ts +14 -0
  529. package/dist/session/index.js +13 -0
  530. package/dist/session/index.js.map +1 -0
  531. package/dist/session-start/build.d.ts +53 -0
  532. package/dist/session-start/build.js +645 -0
  533. package/dist/session-start/build.js.map +1 -0
  534. package/dist/session-start/index.d.ts +18 -0
  535. package/dist/session-start/index.js +18 -0
  536. package/dist/session-start/index.js.map +1 -0
  537. package/dist/session-start/templates.d.ts +6 -0
  538. package/dist/session-start/templates.js +38 -0
  539. package/dist/session-start/templates.js.map +1 -0
  540. package/dist/status-line/format.d.ts +14 -0
  541. package/dist/status-line/format.js +40 -0
  542. package/dist/status-line/format.js.map +1 -0
  543. package/dist/status-line/index.d.ts +29 -0
  544. package/dist/status-line/index.js +14 -0
  545. package/dist/status-line/index.js.map +1 -0
  546. package/dist/status-line/reader.d.ts +13 -0
  547. package/dist/status-line/reader.js +76 -0
  548. package/dist/status-line/reader.js.map +1 -0
  549. package/dist/status-line/writer.d.ts +33 -0
  550. package/dist/status-line/writer.js +72 -0
  551. package/dist/status-line/writer.js.map +1 -0
  552. package/dist/tier0/classify.d.ts +10 -0
  553. package/dist/tier0/classify.js +110 -0
  554. package/dist/tier0/classify.js.map +1 -0
  555. package/dist/tier0/index.d.ts +2 -0
  556. package/dist/tier0/index.js +2 -0
  557. package/dist/tier0/index.js.map +1 -0
  558. package/dist/tier0/ollama.d.ts +22 -0
  559. package/dist/tier0/ollama.js +63 -0
  560. package/dist/tier0/ollama.js.map +1 -0
  561. package/dist/tier0/types.d.ts +24 -0
  562. package/dist/tier0/types.js +9 -0
  563. package/dist/tier0/types.js.map +1 -0
  564. package/dist/tightener/index.d.ts +4 -0
  565. package/dist/tightener/index.js +4 -0
  566. package/dist/tightener/index.js.map +1 -0
  567. package/dist/tightener/prompt.d.ts +3 -0
  568. package/dist/tightener/prompt.js +67 -0
  569. package/dist/tightener/prompt.js.map +1 -0
  570. package/dist/tightener/schema.d.ts +68 -0
  571. package/dist/tightener/schema.js +44 -0
  572. package/dist/tightener/schema.js.map +1 -0
  573. package/dist/tightener/tighten.d.ts +2 -0
  574. package/dist/tightener/tighten.js +66 -0
  575. package/dist/tightener/tighten.js.map +1 -0
  576. package/dist/tightener/types.d.ts +74 -0
  577. package/dist/tightener/types.js +6 -0
  578. package/dist/tightener/types.js.map +1 -0
  579. package/dist/voice/index.d.ts +4 -0
  580. package/dist/voice/index.js +4 -0
  581. package/dist/voice/index.js.map +1 -0
  582. package/dist/voice/model.d.ts +23 -0
  583. package/dist/voice/model.js +46 -0
  584. package/dist/voice/model.js.map +1 -0
  585. package/dist/voice/pipe.d.ts +9 -0
  586. package/dist/voice/pipe.js +47 -0
  587. package/dist/voice/pipe.js.map +1 -0
  588. package/dist/voice/transcribe.d.ts +3 -0
  589. package/dist/voice/transcribe.js +43 -0
  590. package/dist/voice/transcribe.js.map +1 -0
  591. package/dist/voice/types.d.ts +26 -0
  592. package/dist/voice/types.js +9 -0
  593. package/dist/voice/types.js.map +1 -0
  594. package/package.json +54 -0
  595. package/templates/.archive/README.md +67 -0
  596. package/templates/.cairn/JOIN.md +87 -0
  597. package/templates/.cairn/config/sensors.yaml +185 -0
  598. package/templates/.cairn/config/stub-patterns.yaml +231 -0
  599. package/templates/.cairn/config/trust-policy.yaml +95 -0
  600. package/templates/.cairn/config/workflow.md +230 -0
  601. package/templates/.cairn/git-hooks/commit-msg +17 -0
  602. package/templates/.cairn/git-hooks/post-commit +28 -0
  603. package/templates/.cairn/git-hooks/pre-commit +24 -0
  604. package/templates/.cairn/ground/brand/overview.md +24 -0
  605. package/templates/.cairn/ground/brand/voice.md +20 -0
  606. package/templates/.cairn/ground/canonical-map/topics.yaml +54 -0
  607. package/templates/.cairn/ground/capabilities/mcp-tools.yaml +4 -0
  608. package/templates/.cairn/ground/capabilities/skills.yaml +3 -0
  609. package/templates/.cairn/ground/capabilities/snippets.yaml +3 -0
  610. package/templates/.cairn/ground/manifest.yaml +16 -0
  611. package/templates/.cairn/ground/product/personas.yaml +4 -0
  612. package/templates/.cairn/ground/product/positioning.md +21 -0
  613. package/templates/.claude/settings.json +57 -0
  614. package/templates/.github/workflows/cairn-check.yml +31 -0
  615. package/templates/.mcp.json +8 -0
  616. package/templates/README.md +24 -0
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Minimal Ollama HTTP client. Avoids pulling another dep just for two POSTs.
3
+ * Server defaults to http://localhost:11434 (Ollama's listen). The harness
4
+ * exposes `OLLAMA_HOST` env override per `.env.example`.
5
+ */
6
+ export async function ollamaGenerate(req) {
7
+ const ctrl = new AbortController();
8
+ const timer = setTimeout(() => ctrl.abort(), req.timeoutMs ?? 30_000);
9
+ try {
10
+ const body = {
11
+ model: req.model,
12
+ prompt: req.prompt,
13
+ stream: false,
14
+ };
15
+ if (req.system !== undefined)
16
+ body["system"] = req.system;
17
+ if (req.format !== undefined)
18
+ body["format"] = req.format;
19
+ const res = await fetch(`${req.host}/api/generate`, {
20
+ method: "POST",
21
+ headers: { "content-type": "application/json" },
22
+ signal: ctrl.signal,
23
+ body: JSON.stringify(body),
24
+ });
25
+ if (!res.ok) {
26
+ throw new Error(`ollama HTTP ${res.status}: ${await res.text()}`);
27
+ }
28
+ return (await res.json());
29
+ }
30
+ finally {
31
+ clearTimeout(timer);
32
+ }
33
+ }
34
+ export async function ollamaIsAvailable(host) {
35
+ try {
36
+ const ctrl = new AbortController();
37
+ const timer = setTimeout(() => ctrl.abort(), 1000);
38
+ const res = await fetch(`${host}/api/tags`, { signal: ctrl.signal });
39
+ clearTimeout(timer);
40
+ return res.ok;
41
+ }
42
+ catch {
43
+ return false;
44
+ }
45
+ }
46
+ export async function ollamaHasModel(host, model) {
47
+ try {
48
+ const ctrl = new AbortController();
49
+ const timer = setTimeout(() => ctrl.abort(), 1500);
50
+ const res = await fetch(`${host}/api/tags`, { signal: ctrl.signal });
51
+ clearTimeout(timer);
52
+ if (!res.ok)
53
+ return false;
54
+ const json = (await res.json());
55
+ if (!json.models)
56
+ return false;
57
+ return json.models.some((m) => m.name === model || m.name.startsWith(`${model}:`));
58
+ }
59
+ catch {
60
+ return false;
61
+ }
62
+ }
63
+ //# sourceMappingURL=ollama.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ollama.js","sourceRoot":"","sources":["../../src/tier0/ollama.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Tier-0 classifier contract. Per docs/PLUGIN_ARCHITECTURE.md §14: Haiku
3
+ * (escalating to Sonnet for complex prompts) via the Claude binary
4
+ * subprocess. Falls back to a deterministic regex matcher if the Claude
5
+ * binary is unavailable so smoke tests + scripted callers stay green.
6
+ * Production flows assume the Claude binary is present.
7
+ */
8
+ export type Tier0Intent = "code_task" | "review" | "direction" | "question" | "halt" | "status" | "unknown";
9
+ export interface ClassificationResult {
10
+ intent: Tier0Intent;
11
+ confidence: number;
12
+ source: "claude" | "fallback";
13
+ }
14
+ export interface Tier0RegexFallback {
15
+ (text: string): {
16
+ intent: Tier0Intent;
17
+ confidence: number;
18
+ };
19
+ }
20
+ export interface Tier0ClassifyOptions {
21
+ timeoutMs?: number;
22
+ /** Used when the Claude binary is unreachable or returns malformed output. */
23
+ regexFallback?: Tier0RegexFallback;
24
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Tier-0 classifier contract. Per docs/PLUGIN_ARCHITECTURE.md §14: Haiku
3
+ * (escalating to Sonnet for complex prompts) via the Claude binary
4
+ * subprocess. Falls back to a deterministic regex matcher if the Claude
5
+ * binary is unavailable so smoke tests + scripted callers stay green.
6
+ * Production flows assume the Claude binary is present.
7
+ */
8
+ export {};
9
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/tier0/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG"}
@@ -0,0 +1,4 @@
1
+ export { tightenSpec } from "./tighten.js";
2
+ export { TIGHTENER_OUTPUT_SCHEMA } from "./schema.js";
3
+ export { TIGHTENER_SYSTEM_PROMPT, buildTightenerUserPrompt, } from "./prompt.js";
4
+ export type { Ambiguity, TightenerInput, TightenerOutput, TightenerResult, } from "./types.js";
@@ -0,0 +1,4 @@
1
+ export { tightenSpec } from "./tighten.js";
2
+ export { TIGHTENER_OUTPUT_SCHEMA } from "./schema.js";
3
+ export { TIGHTENER_SYSTEM_PROMPT, buildTightenerUserPrompt, } from "./prompt.js";
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tightener/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EACL,uBAAuB,EACvB,wBAAwB,GACzB,MAAM,aAAa,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { TightenerInput } from "./types.js";
2
+ export declare const TIGHTENER_SYSTEM_PROMPT: string;
3
+ export declare function buildTightenerUserPrompt(input: TightenerInput): string;
@@ -0,0 +1,67 @@
1
+ export const TIGHTENER_SYSTEM_PROMPT = [
2
+ "You are the SPEC TIGHTENER for a developer cairn.",
3
+ "",
4
+ "Your job: read a task spec and decide if an implementer can act on it without asking questions. You DO NOT write code, run tools, or modify files. You analyze the spec and return one structured JSON object.",
5
+ "",
6
+ "Examine the spec for:",
7
+ "- AMBIGUITIES — wording that an honest implementer could read two ways. Each ambiguity gets a stable id (Q1, Q2, ...), a focused question, and 2-4 concrete A/B/C/D candidate resolutions (per the cairn UX rule: squares-into-square-holes, no free-text-only options).",
8
+ "- CONFLICTS — direct contradictions with decisions or invariants in scope.",
9
+ "- MISSING ACCEPTANCE — observable behaviors the spec implies but does not state, that an implementer would need to assert.",
10
+ "- SCOPE CONCERNS — paths/modules the spec might touch that look out of bounds.",
11
+ "- EXISTING STUB OVERLAP — TODOs / placeholder functions the spec would resolve, called out explicitly so the implementer doesn't add a parallel implementation.",
12
+ "",
13
+ "Score the spec 0-10 on `spec_quality_score`:",
14
+ " 0-3 = vague, multiple interpretations, missing acceptance",
15
+ " 4-6 = workable but several decisions deferred",
16
+ " 7-8 = clear, minor wording-level ambiguities at most",
17
+ " 9-10 = unambiguous, complete acceptance, ready to dispatch",
18
+ "",
19
+ "Set `ready_to_execute = true` ONLY when score >= 7 AND `ambiguities` is empty AND no conflicts. Otherwise false.",
20
+ "",
21
+ "Always populate `tightened_spec_proposal` with your best rewrite of the spec, taking the most defensible default for each ambiguity. This is the fallback if the operator clicks `[approve as drafted]` without resolving questions individually (per cairn Codex audit Finding #7 — collapse 3+ ambiguities into one tightened-proposal-with-edit-button).",
22
+ "",
23
+ "Return ONLY the JSON object. No prose, no preamble.",
24
+ ].join("\n");
25
+ export function buildTightenerUserPrompt(input) {
26
+ const parts = [];
27
+ parts.push("# Task spec to tighten");
28
+ parts.push("");
29
+ parts.push(`## Title`);
30
+ parts.push(input.title);
31
+ parts.push("");
32
+ parts.push(`## Body`);
33
+ parts.push(input.body);
34
+ if (input.decisions_in_scope && input.decisions_in_scope.length > 0) {
35
+ parts.push("");
36
+ parts.push("## Decisions in scope");
37
+ for (const d of input.decisions_in_scope) {
38
+ parts.push(`- **${d.id}** — ${d.title}: ${d.summary}`);
39
+ }
40
+ }
41
+ if (input.invariants_in_scope && input.invariants_in_scope.length > 0) {
42
+ parts.push("");
43
+ parts.push("## Invariants in scope");
44
+ for (const v of input.invariants_in_scope) {
45
+ parts.push(`- **${v.id}** — ${v.title}`);
46
+ }
47
+ }
48
+ if (input.ground_extracts && input.ground_extracts.length > 0) {
49
+ parts.push("");
50
+ parts.push("## Ground extracts");
51
+ for (const g of input.ground_extracts) {
52
+ parts.push(`### ${g.key}`);
53
+ parts.push(g.snippet);
54
+ }
55
+ }
56
+ if (input.existing_stubs && input.existing_stubs.length > 0) {
57
+ parts.push("");
58
+ parts.push("## Existing stubs / TODOs the spec may step on");
59
+ for (const stub of input.existing_stubs) {
60
+ parts.push(`- ${stub}`);
61
+ }
62
+ }
63
+ parts.push("");
64
+ parts.push("Now return the JSON object per the schema.");
65
+ return parts.join("\n");
66
+ }
67
+ //# sourceMappingURL=prompt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt.js","sourceRoot":"","sources":["../../src/tightener/prompt.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,68 @@
1
+ /**
2
+ * JSON Schema enforced by `claude --json-schema` for the tightener output.
3
+ * Mirrors `TightenerOutput` exactly. Keep in sync.
4
+ */
5
+ export declare const TIGHTENER_OUTPUT_SCHEMA: {
6
+ readonly type: "object";
7
+ readonly additionalProperties: false;
8
+ readonly properties: {
9
+ readonly ambiguities: {
10
+ readonly type: "array";
11
+ readonly items: {
12
+ readonly type: "object";
13
+ readonly additionalProperties: false;
14
+ readonly properties: {
15
+ readonly id: {
16
+ readonly type: "string";
17
+ };
18
+ readonly question: {
19
+ readonly type: "string";
20
+ };
21
+ readonly candidate_resolutions: {
22
+ readonly type: "array";
23
+ readonly items: {
24
+ readonly type: "string";
25
+ };
26
+ };
27
+ };
28
+ readonly required: readonly ["id", "question", "candidate_resolutions"];
29
+ };
30
+ };
31
+ readonly conflicts: {
32
+ readonly type: "array";
33
+ readonly items: {
34
+ readonly type: "string";
35
+ };
36
+ };
37
+ readonly missing_acceptance: {
38
+ readonly type: "array";
39
+ readonly items: {
40
+ readonly type: "string";
41
+ };
42
+ };
43
+ readonly scope_concerns: {
44
+ readonly type: "array";
45
+ readonly items: {
46
+ readonly type: "string";
47
+ };
48
+ };
49
+ readonly existing_stub_overlap: {
50
+ readonly type: "array";
51
+ readonly items: {
52
+ readonly type: "string";
53
+ };
54
+ };
55
+ readonly spec_quality_score: {
56
+ readonly type: "integer";
57
+ readonly minimum: 0;
58
+ readonly maximum: 10;
59
+ };
60
+ readonly ready_to_execute: {
61
+ readonly type: "boolean";
62
+ };
63
+ readonly tightened_spec_proposal: {
64
+ readonly type: "string";
65
+ };
66
+ };
67
+ readonly required: readonly ["ambiguities", "conflicts", "missing_acceptance", "scope_concerns", "existing_stub_overlap", "spec_quality_score", "ready_to_execute", "tightened_spec_proposal"];
68
+ };
@@ -0,0 +1,44 @@
1
+ /**
2
+ * JSON Schema enforced by `claude --json-schema` for the tightener output.
3
+ * Mirrors `TightenerOutput` exactly. Keep in sync.
4
+ */
5
+ export const TIGHTENER_OUTPUT_SCHEMA = {
6
+ type: "object",
7
+ additionalProperties: false,
8
+ properties: {
9
+ ambiguities: {
10
+ type: "array",
11
+ items: {
12
+ type: "object",
13
+ additionalProperties: false,
14
+ properties: {
15
+ id: { type: "string" },
16
+ question: { type: "string" },
17
+ candidate_resolutions: {
18
+ type: "array",
19
+ items: { type: "string" },
20
+ },
21
+ },
22
+ required: ["id", "question", "candidate_resolutions"],
23
+ },
24
+ },
25
+ conflicts: { type: "array", items: { type: "string" } },
26
+ missing_acceptance: { type: "array", items: { type: "string" } },
27
+ scope_concerns: { type: "array", items: { type: "string" } },
28
+ existing_stub_overlap: { type: "array", items: { type: "string" } },
29
+ spec_quality_score: { type: "integer", minimum: 0, maximum: 10 },
30
+ ready_to_execute: { type: "boolean" },
31
+ tightened_spec_proposal: { type: "string" },
32
+ },
33
+ required: [
34
+ "ambiguities",
35
+ "conflicts",
36
+ "missing_acceptance",
37
+ "scope_concerns",
38
+ "existing_stub_overlap",
39
+ "spec_quality_score",
40
+ "ready_to_execute",
41
+ "tightened_spec_proposal",
42
+ ],
43
+ };
44
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/tightener/schema.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG;IACrC,IAAI,EAAE,QAAQ;IACd,oBAAoB,EAAE,KAAK;IAC3B,UAAU,EAAE;QACV,WAAW,EAAE;YACX,IAAI,EAAE,OAAO;YACb,KAAK,EAAE;gBACL,IAAI,EAAE,QAAQ;gBACd,oBAAoB,EAAE,KAAK;gBAC3B,UAAU,EAAE;oBACV,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;oBACtB,QAAQ,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;oBAC5B,qBAAqB,EAAE;wBACrB,IAAI,EAAE,OAAO;wBACb,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;qBAC1B;iBACF;gBACD,QAAQ,EAAE,CAAC,IAAI,EAAE,UAAU,EAAE,uBAAuB,CAAC;aACtD;SACF;QACD,SAAS,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;QACvD,kBAAkB,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;QAChE,cAAc,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;QAC5D,qBAAqB,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;QACnE,kBAAkB,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE;QAChE,gBAAgB,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;QACrC,uBAAuB,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;KAC5C;IACD,QAAQ,EAAE;QACR,aAAa;QACb,WAAW;QACX,oBAAoB;QACpB,gBAAgB;QAChB,uBAAuB;QACvB,oBAAoB;QACpB,kBAAkB;QAClB,yBAAyB;KAC1B;CACO,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { TightenerInput, TightenerResult } from "./types.js";
2
+ export declare function tightenSpec(input: TightenerInput): Promise<TightenerResult>;
@@ -0,0 +1,66 @@
1
+ import { runClaude } from "../claude/index.js";
2
+ import { logger } from "../logger.js";
3
+ import { buildTightenerUserPrompt, TIGHTENER_SYSTEM_PROMPT } from "./prompt.js";
4
+ import { TIGHTENER_OUTPUT_SCHEMA } from "./schema.js";
5
+ const log = logger("tightener");
6
+ /** Word-count cutoff at which we auto-escalate from Haiku → Sonnet. */
7
+ const ESCALATE_WORDS = 500;
8
+ /** Default `spec_quality_floor` per templates/.cairn/config/workflow.md. */
9
+ const DEFAULT_QUALITY_FLOOR = 7;
10
+ function chooseTier(input) {
11
+ if (input.force_tier !== undefined)
12
+ return input.force_tier;
13
+ const wordCount = `${input.title} ${input.body}`.split(/\s+/).filter(Boolean).length;
14
+ return wordCount > ESCALATE_WORDS ? "sonnet" : "haiku";
15
+ }
16
+ function isOutput(value) {
17
+ if (typeof value !== "object" || value === null)
18
+ return false;
19
+ const v = value;
20
+ return (Array.isArray(v["ambiguities"]) &&
21
+ Array.isArray(v["conflicts"]) &&
22
+ Array.isArray(v["missing_acceptance"]) &&
23
+ Array.isArray(v["scope_concerns"]) &&
24
+ Array.isArray(v["existing_stub_overlap"]) &&
25
+ typeof v["spec_quality_score"] === "number" &&
26
+ typeof v["ready_to_execute"] === "boolean" &&
27
+ typeof v["tightened_spec_proposal"] === "string");
28
+ }
29
+ export async function tightenSpec(input) {
30
+ const tier = chooseTier(input);
31
+ const userPrompt = buildTightenerUserPrompt(input);
32
+ log.info({ tier, body_len: input.body.length, ship_anyway: input.ship_anyway === true }, "tightener dispatch");
33
+ const result = await runClaude({
34
+ tier,
35
+ prompt: userPrompt,
36
+ system: TIGHTENER_SYSTEM_PROMPT,
37
+ jsonSchema: TIGHTENER_OUTPUT_SCHEMA,
38
+ timeoutMs: 300_000,
39
+ });
40
+ if (!isOutput(result.parsed)) {
41
+ throw new Error(`tightener returned malformed output (no parsed). preview: ${result.text.slice(0, 200)}`);
42
+ }
43
+ const output = result.parsed;
44
+ const ready = input.ship_anyway === true ||
45
+ (output.ready_to_execute === true && output.spec_quality_score >= DEFAULT_QUALITY_FLOOR);
46
+ return {
47
+ output,
48
+ tier,
49
+ ready,
50
+ quality_floor: DEFAULT_QUALITY_FLOOR,
51
+ duration_ms: result.durationMs,
52
+ ...(result.usage !== undefined
53
+ ? {
54
+ usage: {
55
+ ...(result.usage.input_tokens !== undefined
56
+ ? { input_tokens: result.usage.input_tokens }
57
+ : {}),
58
+ ...(result.usage.output_tokens !== undefined
59
+ ? { output_tokens: result.usage.output_tokens }
60
+ : {}),
61
+ },
62
+ }
63
+ : {}),
64
+ };
65
+ }
66
+ //# sourceMappingURL=tighten.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tighten.js","sourceRoot":"","sources":["../../src/tightener/tighten.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Spec tightener (Layer F) per `docs/PRIMER.md` §10. Single Tier-1 (Haiku)
3
+ * call before any code is written.
4
+ */
5
+ export interface Ambiguity {
6
+ /** Stable id within this tightener call (e.g. "Q1"). */
7
+ id: string;
8
+ question: string;
9
+ /** Concrete A/B/C/D candidate resolutions; empty when caller must free-text. */
10
+ candidate_resolutions: string[];
11
+ }
12
+ export interface TightenerOutput {
13
+ ambiguities: Ambiguity[];
14
+ conflicts: string[];
15
+ missing_acceptance: string[];
16
+ scope_concerns: string[];
17
+ existing_stub_overlap: string[];
18
+ /** 0-10 integer; >= 7 AND ready_to_execute → safe to dispatch. */
19
+ spec_quality_score: number;
20
+ ready_to_execute: boolean;
21
+ /**
22
+ * The model's proposed tightened version of the spec body. Must always
23
+ * be set so callers have a fallback when ambiguities exist (the proposal
24
+ * uses the most defensible default per L44).
25
+ */
26
+ tightened_spec_proposal: string;
27
+ }
28
+ export interface TightenerInput {
29
+ title: string;
30
+ body: string;
31
+ /** Recent decisions in scope (id + summary). Loaded from MCP by caller. */
32
+ decisions_in_scope?: {
33
+ id: string;
34
+ title: string;
35
+ summary: string;
36
+ }[];
37
+ /** Invariants in scope (id + title). Loaded from MCP by caller. */
38
+ invariants_in_scope?: {
39
+ id: string;
40
+ title: string;
41
+ }[];
42
+ /** Ground extracts in scope (key + content snippet). */
43
+ ground_extracts?: {
44
+ key: string;
45
+ snippet: string;
46
+ }[];
47
+ /** Existing stubs/TODOs the agent may step on. */
48
+ existing_stubs?: string[];
49
+ /** Operator override per L24: ship even when score below threshold. */
50
+ ship_anyway?: boolean;
51
+ /**
52
+ * Force a specific tier instead of the body-length heuristic. Useful for
53
+ * smoke tests and for operators who know they want Sonnet on a touchy
54
+ * spec without rewriting it to trip the auto-escalate threshold.
55
+ */
56
+ force_tier?: "haiku" | "sonnet";
57
+ }
58
+ export interface TightenerResult {
59
+ /** Raw tightener output as returned by the model. */
60
+ output: TightenerOutput;
61
+ /** Tier actually used (auto-escalated if body length tripped the threshold). */
62
+ tier: "haiku" | "sonnet";
63
+ /** True when the gate passes: score >= floor AND ready_to_execute, OR ship_anyway. */
64
+ ready: boolean;
65
+ /** Quality floor used to compute `ready`. Default 7 per workflow.md `spec_quality_floor`. */
66
+ quality_floor: number;
67
+ /** Wall-clock duration of the model call. */
68
+ duration_ms: number;
69
+ /** Token usage if reported by the CLI. */
70
+ usage?: {
71
+ input_tokens?: number;
72
+ output_tokens?: number;
73
+ };
74
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Spec tightener (Layer F) per `docs/PRIMER.md` §10. Single Tier-1 (Haiku)
3
+ * call before any code is written.
4
+ */
5
+ export {};
6
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/tightener/types.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
@@ -0,0 +1,4 @@
1
+ export { transcribeBuffer, transcribeUrl } from "./transcribe.js";
2
+ export { freeWhisper, getWhisper, whisperModelExists, WHISPER_MODEL_FILE, WHISPER_MODEL_PATH, WHISPER_MODELS_DIR, } from "./model.js";
3
+ export { audioToPcm } from "./pipe.js";
4
+ export type { TranscribeOptions, TranscriptionResult, TranscriptionSegment, } from "./types.js";
@@ -0,0 +1,4 @@
1
+ export { transcribeBuffer, transcribeUrl } from "./transcribe.js";
2
+ export { freeWhisper, getWhisper, whisperModelExists, WHISPER_MODEL_FILE, WHISPER_MODEL_PATH, WHISPER_MODELS_DIR, } from "./model.js";
3
+ export { audioToPcm } from "./pipe.js";
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/voice/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAClE,OAAO,EACL,WAAW,EACX,UAAU,EACV,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC"}
@@ -0,0 +1,23 @@
1
+ import { Whisper } from "smart-whisper";
2
+ /**
3
+ * Whisper model spec is locked at L11: large-v3-turbo Q5_0. Hardcoded path
4
+ * (operator hates env vars; only secrets/brand/domain go in env).
5
+ *
6
+ * Operator install:
7
+ * brew install whisper-cpp
8
+ * curl -L -o ~/.local/harness/models/ggml-large-v3-turbo-q5_0.bin \
9
+ * "https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-large-v3-turbo-q5_0.bin?download=true"
10
+ *
11
+ * Phase 16 init script automates the curl.
12
+ */
13
+ export declare const WHISPER_MODEL_FILE = "ggml-large-v3-turbo-q5_0.bin";
14
+ export declare const WHISPER_MODELS_DIR: string;
15
+ export declare const WHISPER_MODEL_PATH: string;
16
+ export declare function whisperModelExists(): boolean;
17
+ /**
18
+ * Lazy-singleton Whisper. smart-whisper's `offload` parameter offloads the
19
+ * model from RAM after N idle seconds; loading on next call. Default 60s
20
+ * keeps the model warm during a burst of voice notes.
21
+ */
22
+ export declare function getWhisper(): Whisper;
23
+ export declare function freeWhisper(): Promise<void>;
@@ -0,0 +1,46 @@
1
+ import { existsSync } from "node:fs";
2
+ import { homedir } from "node:os";
3
+ import { join } from "node:path";
4
+ import { Whisper } from "smart-whisper";
5
+ import { logger } from "../logger.js";
6
+ const log = logger("voice.model");
7
+ /**
8
+ * Whisper model spec is locked at L11: large-v3-turbo Q5_0. Hardcoded path
9
+ * (operator hates env vars; only secrets/brand/domain go in env).
10
+ *
11
+ * Operator install:
12
+ * brew install whisper-cpp
13
+ * curl -L -o ~/.local/harness/models/ggml-large-v3-turbo-q5_0.bin \
14
+ * "https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-large-v3-turbo-q5_0.bin?download=true"
15
+ *
16
+ * Phase 16 init script automates the curl.
17
+ */
18
+ export const WHISPER_MODEL_FILE = "ggml-large-v3-turbo-q5_0.bin";
19
+ export const WHISPER_MODELS_DIR = join(homedir(), ".local", "harness", "models");
20
+ export const WHISPER_MODEL_PATH = join(WHISPER_MODELS_DIR, WHISPER_MODEL_FILE);
21
+ export function whisperModelExists() {
22
+ return existsSync(WHISPER_MODEL_PATH);
23
+ }
24
+ let _whisper;
25
+ /**
26
+ * Lazy-singleton Whisper. smart-whisper's `offload` parameter offloads the
27
+ * model from RAM after N idle seconds; loading on next call. Default 60s
28
+ * keeps the model warm during a burst of voice notes.
29
+ */
30
+ export function getWhisper() {
31
+ if (_whisper)
32
+ return _whisper;
33
+ if (!whisperModelExists()) {
34
+ throw new Error(`whisper model not found at ${WHISPER_MODEL_PATH} — run \`harness init\` or download manually`);
35
+ }
36
+ log.info({ path: WHISPER_MODEL_PATH }, "loading whisper model");
37
+ _whisper = new Whisper(WHISPER_MODEL_PATH, { gpu: true, offload: 60 });
38
+ return _whisper;
39
+ }
40
+ export async function freeWhisper() {
41
+ if (_whisper) {
42
+ await _whisper.free();
43
+ _whisper = undefined;
44
+ }
45
+ }
46
+ //# sourceMappingURL=model.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model.js","sourceRoot":"","sources":["../../src/voice/model.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAEtC,MAAM,GAAG,GAAG,MAAM,CAAC,aAAa,CAAC,CAAC;AAElC;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,8BAA8B,CAAC;AACjE,MAAM,CAAC,MAAM,kBAAkB,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;AACjF,MAAM,CAAC,MAAM,kBAAkB,GAAG,IAAI,CAAC,kBAAkB,EAAE,kBAAkB,CAAC,CAAC;AAE/E,MAAM,UAAU,kBAAkB;IAChC,OAAO,UAAU,CAAC,kBAAkB,CAAC,CAAC;AACxC,CAAC;AAED,IAAI,QAA6B,CAAC;AAElC;;;;GAIG;AACH,MAAM,UAAU,UAAU;IACxB,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAC9B,IAAI,CAAC,kBAAkB,EAAE,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CACb,8BAA8B,kBAAkB,8CAA8C,CAC/F,CAAC;IACJ,CAAC;IACD,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,kBAAkB,EAAE,EAAE,uBAAuB,CAAC,CAAC;IAChE,QAAQ,GAAG,IAAI,OAAO,CAAC,kBAAkB,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC;IACvE,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QACtB,QAAQ,GAAG,SAAS,CAAC;IACvB,CAAC;AACH,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Pipe arbitrary audio bytes through ffmpeg → 16 kHz mono Float32 PCM.
3
+ *
4
+ * Audio bytes flow stdin→stdout; nothing touches disk (L12).
5
+ *
6
+ * `ffmpeg` must be on PATH. macOS: `brew install ffmpeg`. Phase 16 init
7
+ * script verifies and prompts to install.
8
+ */
9
+ export declare function audioToPcm(audio: Buffer): Promise<Float32Array>;
@@ -0,0 +1,47 @@
1
+ import { spawn } from "node:child_process";
2
+ /**
3
+ * Pipe arbitrary audio bytes through ffmpeg → 16 kHz mono Float32 PCM.
4
+ *
5
+ * Audio bytes flow stdin→stdout; nothing touches disk (L12).
6
+ *
7
+ * `ffmpeg` must be on PATH. macOS: `brew install ffmpeg`. Phase 16 init
8
+ * script verifies and prompts to install.
9
+ */
10
+ export async function audioToPcm(audio) {
11
+ return new Promise((resolve, reject) => {
12
+ const ff = spawn("ffmpeg", [
13
+ "-loglevel",
14
+ "error",
15
+ "-i",
16
+ "pipe:0",
17
+ "-ar",
18
+ "16000",
19
+ "-ac",
20
+ "1",
21
+ "-f",
22
+ "f32le",
23
+ "pipe:1",
24
+ ]);
25
+ const chunks = [];
26
+ let stderr = "";
27
+ ff.stdout.on("data", (chunk) => chunks.push(chunk));
28
+ ff.stderr.on("data", (chunk) => {
29
+ stderr += chunk.toString("utf8");
30
+ });
31
+ ff.on("error", (err) => reject(err));
32
+ ff.on("close", (code) => {
33
+ if (code !== 0) {
34
+ reject(new Error(`ffmpeg exited ${code}: ${stderr.trim()}`));
35
+ return;
36
+ }
37
+ const concat = Buffer.concat(chunks);
38
+ // Float32Array requires a 4-byte-aligned ArrayBuffer; copy to ensure.
39
+ const aligned = new ArrayBuffer(concat.length);
40
+ new Uint8Array(aligned).set(concat);
41
+ resolve(new Float32Array(aligned));
42
+ });
43
+ ff.stdin.write(audio);
44
+ ff.stdin.end();
45
+ });
46
+ }
47
+ //# sourceMappingURL=pipe.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipe.js","sourceRoot":"","sources":["../../src/voice/pipe.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAE3C;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,KAAa;IAC5C,OAAO,IAAI,OAAO,CAAe,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACnD,MAAM,EAAE,GAAG,KAAK,CAAC,QAAQ,EAAE;YACzB,WAAW;YACX,OAAO;YACP,IAAI;YACJ,QAAQ;YACR,KAAK;YACL,OAAO;YACP,KAAK;YACL,GAAG;YACH,IAAI;YACJ,OAAO;YACP,QAAQ;SACT,CAAC,CAAC;QACH,MAAM,MAAM,GAAa,EAAE,CAAC;QAC5B,IAAI,MAAM,GAAG,EAAE,CAAC;QAChB,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;QAC5D,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE;YACrC,MAAM,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACnC,CAAC,CAAC,CAAC;QACH,EAAE,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QACrC,EAAE,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;YACtB,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;gBACf,MAAM,CAAC,IAAI,KAAK,CAAC,iBAAiB,IAAI,KAAK,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC;gBAC7D,OAAO;YACT,CAAC;YACD,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YACrC,sEAAsE;YACtE,MAAM,OAAO,GAAG,IAAI,WAAW,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YAC/C,IAAI,UAAU,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YACpC,OAAO,CAAC,IAAI,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC;QACrC,CAAC,CAAC,CAAC;QACH,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACtB,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;IACjB,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { TranscribeOptions, TranscriptionResult } from "./types.js";
2
+ export declare function transcribeBuffer(audio: Buffer, opts?: TranscribeOptions): Promise<TranscriptionResult>;
3
+ export declare function transcribeUrl(attachmentUrl: string, opts?: TranscribeOptions): Promise<TranscriptionResult>;