@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,201 @@
1
+ /**
2
+ * Phase 14 — decision capture flow.
3
+ *
4
+ * Per WORKFLOW_GUIDE / L26 / L27 / INTEGRATION_PLAN §5 Phase 14:
5
+ *
6
+ * /direction <text> OR free-text Tier-0 classified as `direction`
7
+ * → Tier-1 decision-extractor produces structured candidate
8
+ * → cairn writes draft to .cairn/ground/decisions/_inbox/DEC-NNNN.draft.md
9
+ * → Discord prompt: 🟢 commit | 🟡 edit | 🔴 not-a-decision
10
+ * → on 🟢: status:accepted, move to .cairn/ground/decisions/DEC-NNNN.md,
11
+ * regenerate decisions.ledger.yaml; assertions become live
12
+ * → on 🟡: leave draft + post correction prompt (re-run extractor on follow-up)
13
+ * → on 🔴: discard draft (no record)
14
+ *
15
+ * The extractor is read-only (no file-write tools). The draft writer + the
16
+ * confirm flow are pure-mechanical. The only LLM call is the extractor;
17
+ * everything else is the cairn assembling state from the typed payload.
18
+ */
19
+ import type { ClaudeTier } from "../claude/index.js";
20
+ /** Assertion shape the extractor proposes — superset of DecisionAssertion kinds. */
21
+ export interface CandidateAssertion {
22
+ /** Optional id; cairn fills in `<DEC-id>-A<N>` if absent. */
23
+ id?: string;
24
+ kind: "schema_must_contain" | "text_must_match" | "text_must_not_match" | "index_must_exist" | "ast_pattern" | "file_must_not_be_modified" | "query_must_filter_by" | "route_must_have_guard" | "event_must_emit" | "service_method_must_call" | "human_review_hint";
25
+ /** Free-form description of what the assertion enforces. */
26
+ description: string;
27
+ /**
28
+ * Inline assertion-specific knobs — typed loosely on this side because the
29
+ * extractor's output is best-effort. Sensors/Layer-D evaluate these against
30
+ * the diff at run time; malformed entries fail loud at evaluation, not here.
31
+ */
32
+ parameters?: Record<string, unknown>;
33
+ }
34
+ export interface DecisionExtractorOutput {
35
+ /** One-line subject — imperative voice. */
36
+ subject: string;
37
+ /** 2-4 sentence summary expanding the subject. */
38
+ summary: string;
39
+ /** Repo-relative globs the decision binds. May be empty. */
40
+ scope_globs: string[];
41
+ /**
42
+ * Existing decision id this one supersedes, when the operator's direction
43
+ * is explicitly a course-change. Format DEC-NNNN. Null/undefined when not
44
+ * applicable.
45
+ */
46
+ supersedes?: string | null;
47
+ /** 0-3 candidate assertions; cairn materializes them into the draft. */
48
+ candidate_assertions: CandidateAssertion[];
49
+ /** Extractor's confidence the input was a real direction. */
50
+ confidence_signal: "high" | "medium" | "low";
51
+ /**
52
+ * Set when the extractor decided the input was not a direction at all
53
+ * (rambling, off-topic, question-shaped). When true, the draft is NOT
54
+ * written; the caller treats it as a no-op.
55
+ */
56
+ not_a_decision: boolean;
57
+ }
58
+ export interface DecisionExtractorInput {
59
+ /** Raw operator text (slash-arg or free-text body). */
60
+ raw_text: string;
61
+ /** Operator id (for audit / decided_by frontmatter). */
62
+ author_id: string;
63
+ /** When the message was received. ISO timestamp. */
64
+ received_at: string;
65
+ /** Source channel/source for traceability. */
66
+ source: string;
67
+ /**
68
+ * Optional: existing accepted-decision summaries the extractor can cite for
69
+ * supersedes. Each item: `{id, title, scope_summary}`. Order: most recent
70
+ * first. Cap to ~10 per call to keep the prompt bounded.
71
+ */
72
+ accepted_decisions?: {
73
+ id: string;
74
+ title: string;
75
+ scope_summary: string;
76
+ }[];
77
+ /** Tier — default 1 (Haiku) per workflow.md `decision_extractor: 1`. */
78
+ tier: ClaudeTier;
79
+ /** Per-call timeout. Default 120_000 ms. */
80
+ timeout_ms?: number;
81
+ }
82
+ /** A draft written to `_inbox/`. Returned by writeDecisionDraft. */
83
+ export interface DecisionDraft {
84
+ /** Allocated DEC-id. */
85
+ id: string;
86
+ /** Repo-relative path of the draft file. */
87
+ draft_path: string;
88
+ /** Path the draft will move to on accept. */
89
+ canonical_path: string;
90
+ /** Original extractor output (for confirmation rendering). */
91
+ output: DecisionExtractorOutput;
92
+ /** Raw direction text the operator submitted. */
93
+ raw_text: string;
94
+ }
95
+ /** Operator's verdict on a draft. */
96
+ export type DraftConfirmDecision = "commit" | "edit" | "reject";
97
+ export interface ConfirmResult {
98
+ decision: DraftConfirmDecision;
99
+ /** Set when decision="commit" — final canonical path of the accepted decision. */
100
+ accepted_path?: string;
101
+ /** Number of ledger entries after regenerate. */
102
+ ledger_size?: number;
103
+ /** Extractor's structured output preserved for downstream observers. */
104
+ draft?: DecisionDraft;
105
+ /** When decision="edit", operator-supplied correction text. */
106
+ correction?: string;
107
+ /** Extractor confidence. */
108
+ confidence?: "high" | "medium" | "low";
109
+ }
110
+ /** Aggregate result handed back from runDecisionCapture. */
111
+ export interface DecisionCaptureResult {
112
+ /** True iff the extractor flagged not_a_decision and the flow short-circuited. */
113
+ short_circuited: boolean;
114
+ /** Set when the extractor produced a draft. */
115
+ draft?: DecisionDraft;
116
+ /** Set when the operator confirmed via the dialog. */
117
+ confirm?: ConfirmResult;
118
+ /**
119
+ * Set when refinement ran after a 🟢 commit. Absent on edit/reject paths,
120
+ * on bypassRefinement, or when the proposer call failed (the accept still
121
+ * succeeds in that case — refinement is best-effort).
122
+ */
123
+ refinement?: RefinementResult;
124
+ /** Total wall-clock time. */
125
+ duration_ms: number;
126
+ }
127
+ /**
128
+ * The Tier-1 proposer's per-candidate verdict on whether a strict
129
+ * `DecisionAssertion` shape can be formed and what it should contain.
130
+ *
131
+ * The proposer never decides what gets persisted — it just provides a
132
+ * recommendation. The operator's dialog choice determines what actually
133
+ * lands in the file. The runner re-validates each `strict_assertion`
134
+ * against the production `DecisionAssertion` zod before lifting; a
135
+ * proposal that fails zod is downgraded to `demote` automatically.
136
+ */
137
+ export interface RefinementProposal {
138
+ /** Stable id of the candidate this proposal corresponds to (`<DEC-id>-A<NN>`). */
139
+ candidate_id: string;
140
+ /** Original loose kind from the candidate. */
141
+ candidate_kind: CandidateAssertion["kind"];
142
+ /**
143
+ * Proposer's verdict:
144
+ * - `lift` — confident strict shape; ready to promote into `assertions:`
145
+ * - `demote` — too vague to form mechanical params; convert to
146
+ * `human_review_hint` (always soft, always zod-valid)
147
+ * - `skip` — leave under `candidate_assertions:` for future refinement
148
+ */
149
+ status: "lift" | "demote" | "skip";
150
+ /** Proposer's confidence in its own recommendation. */
151
+ confidence_signal: "high" | "medium" | "low";
152
+ /**
153
+ * Strict params object the proposer recommends. SHAPE depends on
154
+ * `candidate_kind`. Validated against `DecisionAssertion` zod at apply
155
+ * time; an invalid shape forces auto-demote.
156
+ * Only set when status === "lift".
157
+ */
158
+ strict_assertion?: Record<string, unknown>;
159
+ /**
160
+ * Human-readable explanation rendered into the operator dialog.
161
+ * Always present so the operator can audit each proposal at confirm
162
+ * time without reading the raw JSON.
163
+ */
164
+ rationale: string;
165
+ }
166
+ /** Aggregate output of `proposeStrictAssertions`. */
167
+ export interface RefinerOutput {
168
+ /** One proposal per candidate, in original order. */
169
+ proposals: RefinementProposal[];
170
+ }
171
+ export interface RefinerInput {
172
+ decision_id: string;
173
+ /** Decision's one-line subject (for prompt context). */
174
+ subject: string;
175
+ /** Decision's summary (for prompt context). */
176
+ summary: string;
177
+ /** Repo-relative globs the decision binds. */
178
+ scope_globs: string[];
179
+ /** Candidate assertions to refine. Order preserved on output. */
180
+ candidates: CandidateAssertion[];
181
+ /** Tier — default haiku. */
182
+ tier: ClaudeTier;
183
+ /** Per-call timeout. Default 120_000 ms. */
184
+ timeout_ms?: number;
185
+ }
186
+ /** Final outcome after operator dialog + lift. */
187
+ export interface RefinementResult {
188
+ decision_id: string;
189
+ /** Proposals as returned by the proposer (pre-decision). */
190
+ proposals: RefinementProposal[];
191
+ /** Operator's choice id from the refinement dialog. */
192
+ operator_choice: "approve_all" | "approve_high_only" | "demote_all" | "skip";
193
+ /** Number of candidates lifted into `assertions:`. */
194
+ lifted_count: number;
195
+ /** Number of candidates demoted into `human_review_hint`. */
196
+ demoted_count: number;
197
+ /** Number of candidates kept under `candidate_assertions:`. */
198
+ skipped_count: number;
199
+ /** Set when the proposer threw or returned malformed output. */
200
+ proposer_failed?: boolean;
201
+ }
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Phase 14 — decision capture flow.
3
+ *
4
+ * Per WORKFLOW_GUIDE / L26 / L27 / INTEGRATION_PLAN §5 Phase 14:
5
+ *
6
+ * /direction <text> OR free-text Tier-0 classified as `direction`
7
+ * → Tier-1 decision-extractor produces structured candidate
8
+ * → cairn writes draft to .cairn/ground/decisions/_inbox/DEC-NNNN.draft.md
9
+ * → Discord prompt: 🟢 commit | 🟡 edit | 🔴 not-a-decision
10
+ * → on 🟢: status:accepted, move to .cairn/ground/decisions/DEC-NNNN.md,
11
+ * regenerate decisions.ledger.yaml; assertions become live
12
+ * → on 🟡: leave draft + post correction prompt (re-run extractor on follow-up)
13
+ * → on 🔴: discard draft (no record)
14
+ *
15
+ * The extractor is read-only (no file-write tools). The draft writer + the
16
+ * confirm flow are pure-mechanical. The only LLM call is the extractor;
17
+ * everything else is the cairn assembling state from the typed payload.
18
+ */
19
+ export {};
20
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/decision-capture/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG"}
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Draft writer + confirm-side persistence.
3
+ *
4
+ * `writeDecisionDraft` materializes the extractor output into
5
+ * `.cairn/ground/decisions/_inbox/<DEC-id>.draft.md`. Frontmatter
6
+ * conforms to `DecisionFrontmatter` (status: "draft").
7
+ *
8
+ * `acceptDraft` moves the draft to its canonical path with status flipped
9
+ * to "accepted" and triggers a ledger regenerate.
10
+ *
11
+ * `rejectDraft` removes the draft file entirely. The id remains burned —
12
+ * `allocateDecisionId` always returns mark+1, so a rejected DEC-NNNN never
13
+ * gets reissued (per monotonic-id principle, single source in decision-capture/id.ts).
14
+ */
15
+ import type { DecisionDraft, DecisionExtractorOutput } from "./types.js";
16
+ export interface WriteDecisionDraftArgs {
17
+ repoRoot: string;
18
+ id: string;
19
+ output: DecisionExtractorOutput;
20
+ rawText: string;
21
+ authorId: string;
22
+ receivedAt: string;
23
+ source: string;
24
+ }
25
+ export declare function writeDecisionDraft(args: WriteDecisionDraftArgs): DecisionDraft;
26
+ export interface AcceptDraftResult {
27
+ acceptedPath: string;
28
+ ledgerSize: number;
29
+ ledgerPath: string;
30
+ }
31
+ /**
32
+ * Move a draft to the canonical decisions/ dir, flip status:draft → accepted,
33
+ * then regenerate the decisions ledger so accepted assertions become live.
34
+ *
35
+ * If a `supersedes` link exists, this also stamps `superseded_by` on the
36
+ * referenced decision (when the file is present). Best-effort — a missing
37
+ * referent doesn't block acceptance.
38
+ */
39
+ export declare function acceptDraft(args: {
40
+ repoRoot: string;
41
+ draft: DecisionDraft;
42
+ }): AcceptDraftResult;
43
+ /**
44
+ * Discard a draft. The DEC-id is NOT recycled — the allocator advances
45
+ * past every existing DEC-NNNN.* file. Per the monotonic-id rule, even
46
+ * rejected drafts burn their id, so we leave a tombstone at
47
+ * `_inbox/<DEC-id>.rejected.md` rather than deleting outright. The
48
+ * tombstone has `status: rejected` and is excluded from the ledger by
49
+ * the existing `status === "accepted"` filter.
50
+ */
51
+ export declare function rejectDraft(args: {
52
+ repoRoot: string;
53
+ draft: DecisionDraft;
54
+ }): void;
55
+ export interface LiftVerdict {
56
+ candidate_id: string;
57
+ status: "lift" | "demote" | "skip";
58
+ /** Strict assertion params (without id/kind — writer injects them). */
59
+ strict_assertion?: Record<string, unknown>;
60
+ /** Original candidate kind (carried onto lifted assertion). */
61
+ candidate_kind: "schema_must_contain" | "text_must_match" | "text_must_not_match" | "index_must_exist" | "ast_pattern" | "file_must_not_be_modified" | "query_must_filter_by" | "route_must_have_guard" | "event_must_emit" | "service_method_must_call" | "human_review_hint";
62
+ /** Original candidate description (used when demoted to human_review_hint). */
63
+ candidate_description: string;
64
+ }
65
+ export interface LiftResult {
66
+ decision_id: string;
67
+ decision_path: string;
68
+ lifted_count: number;
69
+ demoted_count: number;
70
+ skipped_count: number;
71
+ ledger_size: number;
72
+ }
73
+ /**
74
+ * Apply per-candidate verdicts to an accepted decision file.
75
+ *
76
+ * For each verdict:
77
+ * - status="lift" → strict_assertion (with id/kind injected) lands in
78
+ * frontmatter `assertions:`
79
+ * - status="demote" → a `{kind: human_review_hint, description}` assertion
80
+ * lands in `assertions:` (always soft, always zod-valid)
81
+ * - status="skip" → original candidate stays under `candidate_assertions:`
82
+ *
83
+ * Then regenerates the decisions ledger so the new strict assertions are
84
+ * visible to Layer-D sensors on the next run.
85
+ */
86
+ export declare function liftCandidatesToAssertions(args: {
87
+ repoRoot: string;
88
+ decisionId: string;
89
+ verdicts: LiftVerdict[];
90
+ }): LiftResult;
@@ -0,0 +1,267 @@
1
+ /**
2
+ * Draft writer + confirm-side persistence.
3
+ *
4
+ * `writeDecisionDraft` materializes the extractor output into
5
+ * `.cairn/ground/decisions/_inbox/<DEC-id>.draft.md`. Frontmatter
6
+ * conforms to `DecisionFrontmatter` (status: "draft").
7
+ *
8
+ * `acceptDraft` moves the draft to its canonical path with status flipped
9
+ * to "accepted" and triggers a ledger regenerate.
10
+ *
11
+ * `rejectDraft` removes the draft file entirely. The id remains burned —
12
+ * `allocateDecisionId` always returns mark+1, so a rejected DEC-NNNN never
13
+ * gets reissued (per monotonic-id principle, single source in decision-capture/id.ts).
14
+ */
15
+ import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
16
+ import { dirname, join } from "node:path";
17
+ import { parse as parseYaml, stringify as stringifyYaml } from "yaml";
18
+ import { decisionsDir, decisionsLedgerPath } from "../ground/paths.js";
19
+ import { writeDecisionsLedger } from "../ground/ledgers.js";
20
+ import { parseFrontmatter } from "../ground/frontmatter.js";
21
+ export function writeDecisionDraft(args) {
22
+ const dir = decisionsDir(args.repoRoot);
23
+ const inboxDir = join(dir, "_inbox");
24
+ mkdirSync(inboxDir, { recursive: true });
25
+ const draftFilename = `${args.id}.draft.md`;
26
+ const canonicalFilename = `${args.id}.md`;
27
+ const draftAbs = join(inboxDir, draftFilename);
28
+ const canonicalAbs = join(dir, canonicalFilename);
29
+ const draftRel = `.cairn/ground/decisions/_inbox/${draftFilename}`;
30
+ const canonicalRel = `.cairn/ground/decisions/${canonicalFilename}`;
31
+ const now = new Date().toISOString();
32
+ // candidate_assertions are PROPOSALS — schema-loose. They live under
33
+ // `candidate_assertions:` in the frontmatter (passthrough), NOT under
34
+ // `assertions:` which DecisionFrontmatter validates strictly. A future
35
+ // refinement step (Phase 14.x) lifts candidates into the strict
36
+ // `assertions:` form once parameters are filled in. Until then the
37
+ // ledger ignores them and Layer-D sensors don't enforce them.
38
+ const candidateAssertions = args.output.candidate_assertions.map((a, idx) => {
39
+ const id = a.id ?? `${args.id}-A${(idx + 1).toString().padStart(2, "0")}`;
40
+ return {
41
+ id,
42
+ kind: a.kind,
43
+ description: a.description,
44
+ ...(a.parameters !== undefined ? { parameters: a.parameters } : {}),
45
+ };
46
+ });
47
+ const frontmatter = {
48
+ id: args.id,
49
+ title: args.output.subject,
50
+ type: "adr",
51
+ status: "draft",
52
+ audience: "dual",
53
+ generated: now,
54
+ "verified-at": now,
55
+ decided_at: args.receivedAt,
56
+ decided_by: args.authorId,
57
+ ...(args.output.scope_globs.length > 0 ? { scope_globs: args.output.scope_globs } : {}),
58
+ ...(args.output.supersedes ? { supersedes: args.output.supersedes } : {}),
59
+ ...(candidateAssertions.length > 0
60
+ ? { candidate_assertions: candidateAssertions }
61
+ : {}),
62
+ capture_source: args.source,
63
+ capture_confidence: args.output.confidence_signal,
64
+ };
65
+ const yaml = stringifyYaml(frontmatter);
66
+ const body = composeDraftBody(args);
67
+ const fileContent = `---\n${yaml}---\n\n${body}\n`;
68
+ writeFileSync(draftAbs, fileContent, "utf8");
69
+ return {
70
+ id: args.id,
71
+ draft_path: draftRel,
72
+ canonical_path: canonicalRel,
73
+ output: args.output,
74
+ raw_text: args.rawText,
75
+ };
76
+ }
77
+ function composeDraftBody(args) {
78
+ const lines = [];
79
+ lines.push(`# ${args.id} — ${args.output.subject}`);
80
+ lines.push("");
81
+ lines.push("## Summary");
82
+ lines.push(args.output.summary.trim());
83
+ lines.push("");
84
+ lines.push("## Original direction");
85
+ lines.push("```");
86
+ lines.push(args.rawText.trim());
87
+ lines.push("```");
88
+ lines.push("");
89
+ if (args.output.scope_globs.length > 0) {
90
+ lines.push("## Scope");
91
+ for (const g of args.output.scope_globs)
92
+ lines.push(`- \`${g}\``);
93
+ lines.push("");
94
+ }
95
+ if (args.output.candidate_assertions.length > 0) {
96
+ lines.push("## Candidate assertions");
97
+ for (const a of args.output.candidate_assertions) {
98
+ lines.push(`- **${a.kind}** — ${a.description}`);
99
+ }
100
+ lines.push("");
101
+ }
102
+ if (args.output.supersedes) {
103
+ lines.push(`## Supersedes`);
104
+ lines.push(`- ${args.output.supersedes}`);
105
+ lines.push("");
106
+ }
107
+ lines.push(`_Confidence: ${args.output.confidence_signal}. This is a DRAFT — pending operator confirmation via Discord._`);
108
+ return lines.join("\n");
109
+ }
110
+ /**
111
+ * Move a draft to the canonical decisions/ dir, flip status:draft → accepted,
112
+ * then regenerate the decisions ledger so accepted assertions become live.
113
+ *
114
+ * If a `supersedes` link exists, this also stamps `superseded_by` on the
115
+ * referenced decision (when the file is present). Best-effort — a missing
116
+ * referent doesn't block acceptance.
117
+ */
118
+ export function acceptDraft(args) {
119
+ const draftAbs = join(args.repoRoot, args.draft.draft_path);
120
+ const canonicalAbs = join(args.repoRoot, args.draft.canonical_path);
121
+ const original = readFileSync(draftAbs, "utf8");
122
+ const flipped = original.replace(/^status:\s*draft\s*$/m, "status: accepted");
123
+ mkdirSync(dirname(canonicalAbs), { recursive: true });
124
+ writeFileSync(canonicalAbs, flipped, "utf8");
125
+ rmSync(draftAbs, { force: true });
126
+ if (args.draft.output.supersedes) {
127
+ stampSupersededBy({
128
+ repoRoot: args.repoRoot,
129
+ supersededId: args.draft.output.supersedes,
130
+ supersedingId: args.draft.id,
131
+ });
132
+ }
133
+ const ledger = writeDecisionsLedger({ repoRoot: args.repoRoot });
134
+ return {
135
+ acceptedPath: args.draft.canonical_path,
136
+ ledgerSize: ledger.entries.length,
137
+ ledgerPath: decisionsLedgerPath(args.repoRoot).replace(args.repoRoot + "/", ""),
138
+ };
139
+ }
140
+ /**
141
+ * Discard a draft. The DEC-id is NOT recycled — the allocator advances
142
+ * past every existing DEC-NNNN.* file. Per the monotonic-id rule, even
143
+ * rejected drafts burn their id, so we leave a tombstone at
144
+ * `_inbox/<DEC-id>.rejected.md` rather than deleting outright. The
145
+ * tombstone has `status: rejected` and is excluded from the ledger by
146
+ * the existing `status === "accepted"` filter.
147
+ */
148
+ export function rejectDraft(args) {
149
+ const draftAbs = join(args.repoRoot, args.draft.draft_path);
150
+ if (!existsSync(draftAbs))
151
+ return;
152
+ const original = readFileSync(draftAbs, "utf8");
153
+ const tombstone = original.replace(/^status:\s*draft\s*$/m, "status: rejected");
154
+ const tombstoneRel = args.draft.draft_path.replace(/\.draft\.md$/, ".rejected.md");
155
+ const tombstoneAbs = join(args.repoRoot, tombstoneRel);
156
+ writeFileSync(tombstoneAbs, tombstone, "utf8");
157
+ rmSync(draftAbs, { force: true });
158
+ }
159
+ function stampSupersededBy(args) {
160
+ const target = join(decisionsDir(args.repoRoot), `${args.supersededId}.md`);
161
+ if (!existsSync(target))
162
+ return;
163
+ const original = readFileSync(target, "utf8");
164
+ // Inject `superseded_by:` into the frontmatter block if not already present.
165
+ if (/^superseded_by:/m.test(original))
166
+ return;
167
+ const fenceEnd = original.indexOf("\n---", 3);
168
+ if (fenceEnd === -1)
169
+ return;
170
+ const fenceText = original.slice(0, fenceEnd);
171
+ const restText = original.slice(fenceEnd);
172
+ const updated = `${fenceText}\nsuperseded_by: ${args.supersedingId}${restText}`;
173
+ writeFileSync(target, updated, "utf8");
174
+ }
175
+ /**
176
+ * Apply per-candidate verdicts to an accepted decision file.
177
+ *
178
+ * For each verdict:
179
+ * - status="lift" → strict_assertion (with id/kind injected) lands in
180
+ * frontmatter `assertions:`
181
+ * - status="demote" → a `{kind: human_review_hint, description}` assertion
182
+ * lands in `assertions:` (always soft, always zod-valid)
183
+ * - status="skip" → original candidate stays under `candidate_assertions:`
184
+ *
185
+ * Then regenerates the decisions ledger so the new strict assertions are
186
+ * visible to Layer-D sensors on the next run.
187
+ */
188
+ export function liftCandidatesToAssertions(args) {
189
+ const decisionRel = `.cairn/ground/decisions/${args.decisionId}.md`;
190
+ const decisionAbs = join(args.repoRoot, decisionRel);
191
+ if (!existsSync(decisionAbs)) {
192
+ throw new Error(`liftCandidatesToAssertions: decision file missing at ${decisionRel}`);
193
+ }
194
+ const original = readFileSync(decisionAbs, "utf8");
195
+ const parsed = parseFrontmatter(original);
196
+ const fmRaw = parsed.raw.length > 0 ? parseYaml(parsed.raw) : {};
197
+ const existingAssertions = Array.isArray(fmRaw["assertions"])
198
+ ? fmRaw["assertions"].slice()
199
+ : [];
200
+ const existingCandidates = Array.isArray(fmRaw["candidate_assertions"])
201
+ ? fmRaw["candidate_assertions"].slice()
202
+ : [];
203
+ let liftedCount = 0;
204
+ let demotedCount = 0;
205
+ let skippedCount = 0;
206
+ const newAssertions = [...existingAssertions];
207
+ const liftedIds = new Set();
208
+ const demotedIds = new Set();
209
+ const skippedIds = new Set();
210
+ for (const v of args.verdicts) {
211
+ if (v.status === "lift" && v.strict_assertion !== undefined) {
212
+ newAssertions.push({
213
+ id: v.candidate_id,
214
+ kind: v.candidate_kind,
215
+ ...v.strict_assertion,
216
+ });
217
+ liftedIds.add(v.candidate_id);
218
+ liftedCount++;
219
+ continue;
220
+ }
221
+ if (v.status === "demote") {
222
+ newAssertions.push({
223
+ id: v.candidate_id,
224
+ kind: "human_review_hint",
225
+ description: v.candidate_description,
226
+ });
227
+ demotedIds.add(v.candidate_id);
228
+ demotedCount++;
229
+ continue;
230
+ }
231
+ skippedIds.add(v.candidate_id);
232
+ skippedCount++;
233
+ }
234
+ const remainingCandidates = existingCandidates.filter((c) => {
235
+ const id = typeof c["id"] === "string" ? c["id"] : "";
236
+ return !liftedIds.has(id) && !demotedIds.has(id);
237
+ });
238
+ // Build the new frontmatter object preserving every existing field, just
239
+ // updating assertions: + candidate_assertions: + verified-at.
240
+ const newFm = { ...fmRaw };
241
+ if (newAssertions.length > 0) {
242
+ newFm["assertions"] = newAssertions;
243
+ }
244
+ else {
245
+ delete newFm["assertions"];
246
+ }
247
+ if (remainingCandidates.length > 0) {
248
+ newFm["candidate_assertions"] = remainingCandidates;
249
+ }
250
+ else {
251
+ delete newFm["candidate_assertions"];
252
+ }
253
+ newFm["verified-at"] = new Date().toISOString();
254
+ const newYaml = stringifyYaml(newFm);
255
+ const newContent = `---\n${newYaml}---\n${parsed.body.startsWith("\n") ? "" : "\n"}${parsed.body}`;
256
+ writeFileSync(decisionAbs, newContent, "utf8");
257
+ const ledger = writeDecisionsLedger({ repoRoot: args.repoRoot });
258
+ return {
259
+ decision_id: args.decisionId,
260
+ decision_path: decisionRel,
261
+ lifted_count: liftedCount,
262
+ demoted_count: demotedCount,
263
+ skipped_count: skippedCount,
264
+ ledger_size: ledger.entries.length,
265
+ };
266
+ }
267
+ //# sourceMappingURL=writer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"writer.js","sourceRoot":"","sources":["../../src/decision-capture/writer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * `cairn doctor` — verify the adoption is healthy.
3
+ *
4
+ * Pure filesystem reads + a status.json check. No LLM. No subprocess fan-out.
5
+ * Returns a structured `DoctorReport` the CLI renders. Exit-code mapping:
6
+ * 0 — all checks pass
7
+ * 1 — at least one error (missing core file, broken layout)
8
+ * 2 — at least one warning (drafty brand, empty scope, daemon not running, …)
9
+ *
10
+ * Spec: BUILD_REPORT.md "Task D — cairn doctor command".
11
+ */
12
+ export type DoctorStatus = "ok" | "warn" | "error" | "info";
13
+ export interface DoctorCheck {
14
+ group: "core" | "ground" | "sensors";
15
+ /** Short label rendered in the report. */
16
+ label: string;
17
+ status: DoctorStatus;
18
+ /** One-line detail rendered next to the icon. */
19
+ detail: string;
20
+ /** When non-null, the exact command the operator can run to fix this. */
21
+ fixCommand?: string;
22
+ }
23
+ export interface DoctorReport {
24
+ projectName: string;
25
+ repoRoot: string;
26
+ checks: DoctorCheck[];
27
+ errors: number;
28
+ warnings: number;
29
+ }
30
+ export interface RunDoctorOptions {
31
+ repoRoot: string;
32
+ }
33
+ export declare function runDoctor(opts: RunDoctorOptions): DoctorReport;
34
+ export interface RunFixOptions {
35
+ repoRoot: string;
36
+ /** Inject a non-default scope-rebuild handler — used by smokes. */
37
+ rebuildScopeIndexFn?: (repoRoot: string) => Promise<{
38
+ filesClassified: number;
39
+ }>;
40
+ }
41
+ export interface FixReport {
42
+ appliedFixes: string[];
43
+ manualFixes: {
44
+ check: string;
45
+ command: string | null;
46
+ }[];
47
+ }
48
+ export declare function runFix(opts: RunFixOptions): Promise<FixReport>;