@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,48 @@
1
+ /**
2
+ * Stack profile — extension surface for project-specific generators, sensors,
3
+ * and adoption-time defaults. Per L47 (Codex audit Q8).
4
+ *
5
+ * The cairn package code is project-agnostic. All references to specific
6
+ * stacks (NestJS, Drizzle, Rails, etc.) live inside profile implementations,
7
+ * NEVER in core code paths. The profile registry is consulted at adoption
8
+ * time and at runtime via id-based lookup.
9
+ */
10
+ export interface ProfileSensorRef {
11
+ /** Stable id used in sensor results. */
12
+ id: string;
13
+ /** What the sensor checks. */
14
+ description: string;
15
+ /** Globs that trigger this sensor. */
16
+ watch?: string[];
17
+ /** Severity if this sensor fails. */
18
+ severity?: "hard" | "soft";
19
+ }
20
+ export interface ProfileExtractorContext {
21
+ /** The repo root the daemon is operating against (mirror path). */
22
+ repoRoot: string;
23
+ }
24
+ export interface ProfileExtractor {
25
+ /** Stable id used in logs + manifest entries. */
26
+ id: string;
27
+ /** Output path relative to repoRoot — usually under .cairn/ground/. */
28
+ outputRelPath: string;
29
+ /** Watch globs that trigger this extractor (relative to repoRoot). */
30
+ watch: string[];
31
+ /** Run extractor; returns content to write, or null to skip writing. */
32
+ run(ctx: ProfileExtractorContext): Promise<string | null>;
33
+ }
34
+ export interface Profile {
35
+ /** Stable id — typescript-next-nest, python-fastapi, rails, go, rust, unknown. */
36
+ id: string;
37
+ name: string;
38
+ /** Returns true if this profile applies to the given repo. */
39
+ detect(repoRoot: string): boolean;
40
+ sensors: ProfileSensorRef[];
41
+ extractors: ProfileExtractor[];
42
+ /** Suggested off-limits paths on adoption. */
43
+ offLimitsDefaults: string[];
44
+ /** Suggested high-stakes globs on adoption. */
45
+ highStakesDefaults: string[];
46
+ /** Suggested start command for the project (e.g., `pnpm dev`). */
47
+ startCommand?: string;
48
+ }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Stack profile — extension surface for project-specific generators, sensors,
3
+ * and adoption-time defaults. Per L47 (Codex audit Q8).
4
+ *
5
+ * The cairn package code is project-agnostic. All references to specific
6
+ * stacks (NestJS, Drizzle, Rails, etc.) live inside profile implementations,
7
+ * NEVER in core code paths. The profile registry is consulted at adoption
8
+ * time and at runtime via id-based lookup.
9
+ */
10
+ export {};
11
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/profiles/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG"}
@@ -0,0 +1,9 @@
1
+ import type { Profile } from "./types.js";
2
+ /**
3
+ * Fallback profile — applies when no other profile detects.
4
+ *
5
+ * Carries no extractors and no stack-specific sensors. The cairn still
6
+ * runs every generic sensor (Layer A/B/C/D/E/U + decision-assertions +
7
+ * invariant-suite) defined in templates/.cairn/config/sensors.yaml.
8
+ */
9
+ export declare const unknownProfile: Profile;
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Fallback profile — applies when no other profile detects.
3
+ *
4
+ * Carries no extractors and no stack-specific sensors. The cairn still
5
+ * runs every generic sensor (Layer A/B/C/D/E/U + decision-assertions +
6
+ * invariant-suite) defined in templates/.cairn/config/sensors.yaml.
7
+ */
8
+ export const unknownProfile = {
9
+ id: "unknown",
10
+ name: "Unknown / generic",
11
+ detect: () => true,
12
+ sensors: [],
13
+ extractors: [],
14
+ offLimitsDefaults: [".git/**", ".archive/**", "node_modules/**", ".env", ".env.local"],
15
+ highStakesDefaults: [],
16
+ };
17
+ //# sourceMappingURL=unknown.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unknown.js","sourceRoot":"","sources":["../../src/profiles/unknown.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,cAAc,GAAY;IACrC,EAAE,EAAE,SAAS;IACb,IAAI,EAAE,mBAAmB;IACzB,MAAM,EAAE,GAAG,EAAE,CAAC,IAAI;IAClB,OAAO,EAAE,EAAE;IACX,UAAU,EAAE,EAAE;IACd,iBAAiB,EAAE,CAAC,SAAS,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,EAAE,YAAY,CAAC;IACtF,kBAAkB,EAAE,EAAE;CACvB,CAAC"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Minimal Liquid-style template renderer. Supports:
3
+ * {{var}} — substitute scalar value
4
+ * {{#each LIST}}...{{/each}} — repeat block per item; inside the block
5
+ * {{this}} resolves to the current item;
6
+ * for object items, {{this.field}} works.
7
+ *
8
+ * Anything not matched is left literal. No conditionals, no nested blocks
9
+ * beyond {{#each}}. The cairn's prompt template (`templates/.cairn/
10
+ * config/workflow.md`) was authored to fit this surface.
11
+ */
12
+ export type TemplateContext = Record<string, string | number | boolean | string[] | Record<string, string>[] | undefined>;
13
+ export declare function renderTemplate(template: string, ctx: TemplateContext): string;
14
+ /**
15
+ * Read the workflow.md template from `<repoRoot>/.cairn/config/workflow.md`,
16
+ * strip the YAML frontmatter, and return only the prompt body (everything
17
+ * after the second `---`).
18
+ */
19
+ export declare function loadWorkflowTemplate(repoRoot: string): string;
package/dist/prompt.js ADDED
@@ -0,0 +1,50 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ export function renderTemplate(template, ctx) {
4
+ // 1. Each blocks first — they are coarser than scalar substitutions.
5
+ const eachBlockRe = /\{\{#each\s+(\w+)\}\}([\s\S]*?)\{\{\/each\}\}/g;
6
+ let out = template.replace(eachBlockRe, (_, key, body) => {
7
+ const list = ctx[key];
8
+ if (!Array.isArray(list))
9
+ return "";
10
+ return list
11
+ .map((item) => {
12
+ if (typeof item === "string") {
13
+ return body.replace(/\{\{this\}\}/g, item);
14
+ }
15
+ if (typeof item === "object" && item !== null) {
16
+ let chunk = body.replace(/\{\{this\}\}/g, JSON.stringify(item));
17
+ chunk = chunk.replace(/\{\{this\.(\w+)\}\}/g, (_m, field) => {
18
+ const v = item[field];
19
+ return v === undefined ? "" : String(v);
20
+ });
21
+ return chunk;
22
+ }
23
+ return "";
24
+ })
25
+ .join("");
26
+ });
27
+ // 2. Scalar substitutions.
28
+ out = out.replace(/\{\{(\w+)\}\}/g, (_match, key) => {
29
+ const v = ctx[key];
30
+ if (v === undefined)
31
+ return "";
32
+ if (Array.isArray(v))
33
+ return v.join(", ");
34
+ return String(v);
35
+ });
36
+ return out;
37
+ }
38
+ /**
39
+ * Read the workflow.md template from `<repoRoot>/.cairn/config/workflow.md`,
40
+ * strip the YAML frontmatter, and return only the prompt body (everything
41
+ * after the second `---`).
42
+ */
43
+ export function loadWorkflowTemplate(repoRoot) {
44
+ const path = join(repoRoot, ".cairn", "config", "workflow.md");
45
+ const raw = readFileSync(path, "utf8");
46
+ // Frontmatter ends at the second `---` line.
47
+ const match = raw.match(/^---\n[\s\S]*?\n---\n([\s\S]*)$/);
48
+ return match ? (match[1] ?? "") : raw;
49
+ }
50
+ //# sourceMappingURL=prompt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt.js","sourceRoot":"","sources":["../src/prompt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAmBjC,MAAM,UAAU,cAAc,CAAC,QAAgB,EAAE,GAAoB;IACnE,qEAAqE;IACrE,MAAM,WAAW,GAAG,gDAAgD,CAAC;IACrE,IAAI,GAAG,GAAG,QAAQ,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,EAAE,GAAW,EAAE,IAAY,EAAE,EAAE;QACvE,MAAM,IAAI,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;QACtB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC;YAAE,OAAO,EAAE,CAAC;QACpC,OAAO,IAAI;aACR,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;YACZ,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAC7B,OAAO,IAAI,CAAC,OAAO,CAAC,eAAe,EAAE,IAAI,CAAC,CAAC;YAC7C,CAAC;YACD,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;gBAC9C,IAAI,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,eAAe,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;gBAChE,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,sBAAsB,EAAE,CAAC,EAAE,EAAE,KAAa,EAAE,EAAE;oBAClE,MAAM,CAAC,GAAI,IAA+B,CAAC,KAAK,CAAC,CAAC;oBAClD,OAAO,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;gBAC1C,CAAC,CAAC,CAAC;gBACH,OAAO,KAAK,CAAC;YACf,CAAC;YACD,OAAO,EAAE,CAAC;QACZ,CAAC,CAAC;aACD,IAAI,CAAC,EAAE,CAAC,CAAC;IACd,CAAC,CAAC,CAAC;IAEH,2BAA2B;IAC3B,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,gBAAgB,EAAE,CAAC,MAAM,EAAE,GAAW,EAAE,EAAE;QAC1D,MAAM,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;QACnB,IAAI,CAAC,KAAK,SAAS;YAAE,OAAO,EAAE,CAAC;QAC/B,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;YAAE,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1C,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC;IACnB,CAAC,CAAC,CAAC;IAEH,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAAC,QAAgB;IACnD,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,aAAa,CAAC,CAAC;IAC/D,MAAM,GAAG,GAAG,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACvC,6CAA6C;IAC7C,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,iCAAiC,CAAC,CAAC;IAC3D,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;AACxC,CAAC"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Layer B — attestation cross-check.
3
+ *
4
+ * The agent emits a fenced YAML block at the end of its final response.
5
+ * This module:
6
+ * 1. Extracts the YAML block from the agent's final text.
7
+ * 2. Parses it into a structured `Attestation`.
8
+ * 3. Cross-checks every claim against the actual diff. Mismatch = lie.
9
+ *
10
+ * Per PRIMER §10 Layer B. Lying must be harder than telling truth.
11
+ */
12
+ import type { Attestation, DiffEntry, SensorResult, StubCatalog } from "./types.js";
13
+ /**
14
+ * Extract the YAML block from a final assistant message. The template
15
+ * instructs the agent to emit a fenced block whose first line is the literal
16
+ * key `attestation:`. We accept either:
17
+ *
18
+ * ```yaml
19
+ * attestation:
20
+ * ...
21
+ * ```
22
+ *
23
+ * or a bare top-level YAML doc starting with `attestation:`.
24
+ */
25
+ export declare function extractAttestation(text: string): Attestation | undefined;
26
+ /**
27
+ * Cross-check the attestation against the diff. Returns the sensor result.
28
+ *
29
+ * Hard fails:
30
+ * - attestation absent or unparseable
31
+ * - files_touched mismatches actual changed paths (set-equality)
32
+ * - todos_introduced != count of TODO/FIXME/XXX/HACK markers added
33
+ * - stubs_introduced != count of hard-severity stub-pattern hits
34
+ * - any delivered item declared `behavior: full` whose path/text contains
35
+ * a stub-pattern hit (lying about completeness)
36
+ */
37
+ export declare function runAttestationCrossCheck(args: {
38
+ attestation: Attestation | undefined;
39
+ diff: DiffEntry[];
40
+ stubCatalog: StubCatalog;
41
+ /** Globs of files always allowed in diff but not required to be in
42
+ * files_touched (e.g. `.cairn/runs/active/**`). */
43
+ ignoreGlobs?: string[];
44
+ }): SensorResult;
@@ -0,0 +1,262 @@
1
+ /**
2
+ * Layer B — attestation cross-check.
3
+ *
4
+ * The agent emits a fenced YAML block at the end of its final response.
5
+ * This module:
6
+ * 1. Extracts the YAML block from the agent's final text.
7
+ * 2. Parses it into a structured `Attestation`.
8
+ * 3. Cross-checks every claim against the actual diff. Mismatch = lie.
9
+ *
10
+ * Per PRIMER §10 Layer B. Lying must be harder than telling truth.
11
+ */
12
+ import { parse as parseYaml } from "yaml";
13
+ import { matchAnyGlob } from "../ground/glob.js";
14
+ import { detectStubMatches } from "./stub-catalog.js";
15
+ const SENSOR_ID = "attestation-cross-check";
16
+ /**
17
+ * Extract the YAML block from a final assistant message. The template
18
+ * instructs the agent to emit a fenced block whose first line is the literal
19
+ * key `attestation:`. We accept either:
20
+ *
21
+ * ```yaml
22
+ * attestation:
23
+ * ...
24
+ * ```
25
+ *
26
+ * or a bare top-level YAML doc starting with `attestation:`.
27
+ */
28
+ export function extractAttestation(text) {
29
+ if (typeof text !== "string" || text.length === 0)
30
+ return undefined;
31
+ // Prefer fenced ```yaml ... ``` block whose body starts with `attestation:`.
32
+ const fenced = /```(?:yaml|yml)?\s*\n([\s\S]*?)\n```/g;
33
+ let match;
34
+ while ((match = fenced.exec(text)) !== null) {
35
+ const body = match[1] ?? "";
36
+ if (/^\s*attestation\s*:/m.test(body)) {
37
+ const parsed = parseAttestationBody(body);
38
+ if (parsed)
39
+ return parsed;
40
+ }
41
+ }
42
+ // Fallback: bare YAML in text starting with `attestation:`.
43
+ const bareIdx = text.search(/^\s*attestation\s*:/m);
44
+ if (bareIdx !== -1) {
45
+ const slice = text.slice(bareIdx);
46
+ return parseAttestationBody(slice);
47
+ }
48
+ return undefined;
49
+ }
50
+ /** Try parsing a YAML body that contains an `attestation:` key. */
51
+ function parseAttestationBody(body) {
52
+ let doc;
53
+ try {
54
+ doc = parseYaml(body);
55
+ }
56
+ catch {
57
+ return undefined;
58
+ }
59
+ if (typeof doc !== "object" || doc === null)
60
+ return undefined;
61
+ const root = doc;
62
+ const at = root["attestation"];
63
+ if (typeof at !== "object" || at === null)
64
+ return undefined;
65
+ const a = at;
66
+ const delivered = Array.isArray(a["delivered"])
67
+ ? a["delivered"].map((d) => ({
68
+ symbol: String(d["symbol"] ?? ""),
69
+ ...(typeof d["path"] === "string" ? { path: d["path"] } : {}),
70
+ behavior: (() => {
71
+ const v = d["behavior"];
72
+ return v === "partial" || v === "scaffolded" ? v : "full";
73
+ })(),
74
+ ...(Array.isArray(d["sensors_passed"])
75
+ ? { sensors_passed: d["sensors_passed"].map(String) }
76
+ : {}),
77
+ }))
78
+ : [];
79
+ const deferred = Array.isArray(a["deferred"])
80
+ ? a["deferred"].map((d) => ({
81
+ symbol: String(d["symbol"] ?? ""),
82
+ reason: String(d["reason"] ?? ""),
83
+ }))
84
+ : [];
85
+ const known_limitations = Array.isArray(a["known_limitations"])
86
+ ? a["known_limitations"].map(String)
87
+ : [];
88
+ const todos_introduced = typeof a["todos_introduced"] === "number" ? a["todos_introduced"] : 0;
89
+ const stubs_introduced = typeof a["stubs_introduced"] === "number" ? a["stubs_introduced"] : 0;
90
+ const files_touched = Array.isArray(a["files_touched"])
91
+ ? a["files_touched"].map(String)
92
+ : [];
93
+ const out = {
94
+ delivered,
95
+ deferred,
96
+ known_limitations,
97
+ todos_introduced,
98
+ stubs_introduced,
99
+ files_touched,
100
+ };
101
+ // Optional blocked_by from the same root or under attestation.
102
+ const block = (root["blocked_by"] ?? a["blocked_by"]);
103
+ if (typeof block === "object" && block !== null) {
104
+ const b = block;
105
+ if (typeof b["reason"] === "string") {
106
+ out.blocked_by = {
107
+ reason: b["reason"],
108
+ ...(typeof b["needed_from_operator"] === "string"
109
+ ? { needed_from_operator: b["needed_from_operator"] }
110
+ : {}),
111
+ };
112
+ }
113
+ }
114
+ return out;
115
+ }
116
+ /**
117
+ * Cross-check the attestation against the diff. Returns the sensor result.
118
+ *
119
+ * Hard fails:
120
+ * - attestation absent or unparseable
121
+ * - files_touched mismatches actual changed paths (set-equality)
122
+ * - todos_introduced != count of TODO/FIXME/XXX/HACK markers added
123
+ * - stubs_introduced != count of hard-severity stub-pattern hits
124
+ * - any delivered item declared `behavior: full` whose path/text contains
125
+ * a stub-pattern hit (lying about completeness)
126
+ */
127
+ export function runAttestationCrossCheck(args) {
128
+ const startedAt = Date.now();
129
+ const findings = [];
130
+ if (!args.attestation) {
131
+ findings.push({
132
+ sensor_id: SENSOR_ID,
133
+ message: "agent emitted no `attestation:` YAML block in final response — Layer B contract requires one",
134
+ severity: "hard",
135
+ });
136
+ return {
137
+ sensor_id: SENSOR_ID,
138
+ ok: false,
139
+ duration_ms: Date.now() - startedAt,
140
+ findings,
141
+ };
142
+ }
143
+ if (args.attestation.blocked_by) {
144
+ // Agent declared it can't proceed. Surface as soft so the orchestrator
145
+ // routes it back to the operator instead of looping.
146
+ findings.push({
147
+ sensor_id: SENSOR_ID,
148
+ message: `agent reported blocked_by: ${args.attestation.blocked_by.reason}`,
149
+ severity: "soft",
150
+ });
151
+ }
152
+ const diffPaths = new Set(args.diff
153
+ .filter((d) => d.status !== "deleted")
154
+ .map((d) => d.path));
155
+ const ignore = args.ignoreGlobs ?? [];
156
+ const declared = new Set(args.attestation.files_touched);
157
+ // Set-equality: every changed file must be declared, and every declared
158
+ // file must be in the diff (catches "I changed these other files too" lies).
159
+ for (const path of diffPaths) {
160
+ if (declared.has(path))
161
+ continue;
162
+ if (ignore.length > 0 && matchAnyGlob(path, ignore))
163
+ continue;
164
+ findings.push({
165
+ sensor_id: SENSOR_ID,
166
+ path,
167
+ message: `file changed but not in attestation.files_touched: ${path}`,
168
+ severity: "hard",
169
+ });
170
+ }
171
+ for (const path of declared) {
172
+ if (diffPaths.has(path))
173
+ continue;
174
+ findings.push({
175
+ sensor_id: SENSOR_ID,
176
+ path,
177
+ message: `attestation.files_touched lists a file not actually changed: ${path}`,
178
+ severity: "hard",
179
+ });
180
+ }
181
+ // Count markers added in the diff.
182
+ const addedTodoCount = countAddedMarkers(args.diff);
183
+ if (args.attestation.todos_introduced !== addedTodoCount) {
184
+ findings.push({
185
+ sensor_id: SENSOR_ID,
186
+ message: `attestation.todos_introduced=${args.attestation.todos_introduced} but diff adds ${addedTodoCount} TODO/FIXME/XXX/HACK marker(s)`,
187
+ severity: "hard",
188
+ });
189
+ }
190
+ // Count hard-stub matches in the diff.
191
+ const stubHits = detectStubMatches({
192
+ diff: args.diff,
193
+ catalog: args.stubCatalog,
194
+ /** All languages — Layer B doesn't get to filter by profile (the agent's
195
+ * number must match the same denominator we'll use). */
196
+ languages: undefined,
197
+ });
198
+ const hardStubCount = stubHits.filter((h) => h.severity === "hard").length;
199
+ if (args.attestation.stubs_introduced !== hardStubCount) {
200
+ findings.push({
201
+ sensor_id: SENSOR_ID,
202
+ message: `attestation.stubs_introduced=${args.attestation.stubs_introduced} but Layer A finds ${hardStubCount} hard-severity stub pattern(s)`,
203
+ severity: "hard",
204
+ });
205
+ }
206
+ // behavior:full + stub-pattern coexistence = lie about completeness.
207
+ for (const d of args.attestation.delivered) {
208
+ if (d.behavior !== "full")
209
+ continue;
210
+ const matches = stubHits.filter((h) => {
211
+ if (d.path && h.path !== d.path)
212
+ return false;
213
+ // If no path, just see whether any matched_text references the symbol.
214
+ if (!d.path)
215
+ return (h.matched_text ?? "").includes(d.symbol);
216
+ return true;
217
+ });
218
+ for (const m of matches) {
219
+ const f = {
220
+ sensor_id: SENSOR_ID,
221
+ message: `delivered "${d.symbol}" claimed behavior:full but contains stub pattern \`${m.pattern_id}\``,
222
+ severity: "hard",
223
+ };
224
+ if (m.path !== undefined)
225
+ f.path = m.path;
226
+ if (m.line !== undefined)
227
+ f.line = m.line;
228
+ if (m.matched_text !== undefined)
229
+ f.matched_text = m.matched_text;
230
+ if (m.pattern_id !== undefined)
231
+ f.pattern_id = m.pattern_id;
232
+ findings.push(f);
233
+ }
234
+ }
235
+ const ok = findings.every((f) => f.severity !== "hard");
236
+ return {
237
+ sensor_id: SENSOR_ID,
238
+ ok,
239
+ duration_ms: Date.now() - startedAt,
240
+ findings,
241
+ };
242
+ }
243
+ /**
244
+ * Count TODO/FIXME/XXX/HACK markers introduced in the diff (added lines only).
245
+ * Modified files: counts markers in content not present at the SHA pin.
246
+ * Added files: counts every marker.
247
+ */
248
+ function countAddedMarkers(diff) {
249
+ const re = /(?:\/\/|#|\/\*|--)\s*(TODO|FIXME|XXX|HACK)\b/g;
250
+ let total = 0;
251
+ for (const entry of diff) {
252
+ if (entry.status === "deleted")
253
+ continue;
254
+ const after = entry.afterContent ?? "";
255
+ const before = entry.beforeContent ?? "";
256
+ const beforeCount = (before.match(re) ?? []).length;
257
+ const afterCount = (after.match(re) ?? []).length;
258
+ total += Math.max(0, afterCount - beforeCount);
259
+ }
260
+ return total;
261
+ }
262
+ //# sourceMappingURL=attestation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attestation.js","sourceRoot":"","sources":["../../src/sensors/attestation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Loaders for the on-disk sensor configuration files.
3
+ *
4
+ * `.cairn/config/stub-patterns.yaml` — Layer A regex catalog
5
+ * `.cairn/config/sensors.yaml` — sensor registry (which sensors run,
6
+ * their layer, fail_severity, glob keys)
7
+ *
8
+ * Both files ship as templates in `cairn/templates/.cairn/config/` and
9
+ * are copied into the adopted project's `.cairn/config/` at init.
10
+ */
11
+ import type { StubCatalog } from "./types.js";
12
+ /** Parse a stub-patterns.yaml document into the typed catalog shape. */
13
+ export declare function parseStubCatalog(yamlText: string): StubCatalog;
14
+ /**
15
+ * Load the stub-pattern catalog. Order:
16
+ * 1. `<repoRoot>/.cairn/config/stub-patterns.yaml` (project override)
17
+ * 2. The package's bundled template file (always present in cairn/dist).
18
+ *
19
+ * Returns the parsed catalog. Throws only if both candidates are missing or
20
+ * unparseable — that would indicate a broken cairn install.
21
+ */
22
+ export declare function loadStubCatalog(repoRoot?: string): StubCatalog;
23
+ /** Sensor registry entry from sensors.yaml. */
24
+ export interface SensorRegistryEntry {
25
+ id: string;
26
+ layer: string;
27
+ kind: string;
28
+ description: string;
29
+ triggers: string[];
30
+ glob_keys?: string[];
31
+ catalog?: string;
32
+ fail_severity?: "hard" | "soft";
33
+ }
34
+ export interface SensorRegistry {
35
+ version: number;
36
+ sensors: SensorRegistryEntry[];
37
+ required_glob_keys: string[];
38
+ disabled_per_project: string[];
39
+ }
40
+ /** Load + parse the sensor registry. */
41
+ export declare function loadSensorRegistry(repoRoot?: string): SensorRegistry;
@@ -0,0 +1,123 @@
1
+ /**
2
+ * Loaders for the on-disk sensor configuration files.
3
+ *
4
+ * `.cairn/config/stub-patterns.yaml` — Layer A regex catalog
5
+ * `.cairn/config/sensors.yaml` — sensor registry (which sensors run,
6
+ * their layer, fail_severity, glob keys)
7
+ *
8
+ * Both files ship as templates in `cairn/templates/.cairn/config/` and
9
+ * are copied into the adopted project's `.cairn/config/` at init.
10
+ */
11
+ import { existsSync, readFileSync } from "node:fs";
12
+ import { dirname, join } from "node:path";
13
+ import { fileURLToPath } from "node:url";
14
+ import { parse as parseYaml } from "yaml";
15
+ const HERE = dirname(fileURLToPath(import.meta.url));
16
+ /**
17
+ * Path to the catalog file shipped inside the cairn package itself. Used
18
+ * as the fallback when the adopted project hasn't customized the catalog.
19
+ *
20
+ * `dist/sensors/catalog.js` runtime path → `templates/.cairn/config/...`.
21
+ */
22
+ const PKG_TEMPLATE_STUB = join(HERE, "..", "..", "templates", ".cairn", "config", "stub-patterns.yaml");
23
+ const PKG_TEMPLATE_SENSORS = join(HERE, "..", "..", "templates", ".cairn", "config", "sensors.yaml");
24
+ const KNOWN_LANGUAGES = [
25
+ "typescript",
26
+ "javascript",
27
+ "python",
28
+ "ruby",
29
+ "go",
30
+ "rust",
31
+ "sql",
32
+ ];
33
+ function isKnownLanguage(s) {
34
+ return typeof s === "string" && KNOWN_LANGUAGES.includes(s);
35
+ }
36
+ /** Parse a stub-patterns.yaml document into the typed catalog shape. */
37
+ export function parseStubCatalog(yamlText) {
38
+ const doc = parseYaml(yamlText);
39
+ const version = typeof doc["version"] === "number" ? doc["version"] : 1;
40
+ const rawPatterns = Array.isArray(doc["patterns"]) ? doc["patterns"] : [];
41
+ const patterns = [];
42
+ for (const raw of rawPatterns) {
43
+ if (typeof raw !== "object" || raw === null)
44
+ continue;
45
+ const r = raw;
46
+ const id = typeof r["id"] === "string" ? r["id"] : "";
47
+ const langs = Array.isArray(r["languages"])
48
+ ? r["languages"].filter(isKnownLanguage)
49
+ : [];
50
+ const description = typeof r["description"] === "string" ? r["description"] : "";
51
+ const regex = typeof r["regex"] === "string" ? r["regex"] : "";
52
+ const severity = r["severity"] === "soft" ? "soft" : "hard";
53
+ if (id === "" || regex === "" || langs.length === 0)
54
+ continue;
55
+ patterns.push({ id, languages: langs, description, regex, severity });
56
+ }
57
+ return { version, patterns };
58
+ }
59
+ /**
60
+ * Load the stub-pattern catalog. Order:
61
+ * 1. `<repoRoot>/.cairn/config/stub-patterns.yaml` (project override)
62
+ * 2. The package's bundled template file (always present in cairn/dist).
63
+ *
64
+ * Returns the parsed catalog. Throws only if both candidates are missing or
65
+ * unparseable — that would indicate a broken cairn install.
66
+ */
67
+ export function loadStubCatalog(repoRoot) {
68
+ const candidates = [];
69
+ if (repoRoot !== undefined) {
70
+ candidates.push(join(repoRoot, ".cairn", "config", "stub-patterns.yaml"));
71
+ }
72
+ candidates.push(PKG_TEMPLATE_STUB);
73
+ for (const p of candidates) {
74
+ if (!existsSync(p))
75
+ continue;
76
+ return parseStubCatalog(readFileSync(p, "utf8"));
77
+ }
78
+ throw new Error(`stub-patterns.yaml not found; checked: ${candidates.join(", ")}`);
79
+ }
80
+ /** Load + parse the sensor registry. */
81
+ export function loadSensorRegistry(repoRoot) {
82
+ const candidates = [];
83
+ if (repoRoot !== undefined) {
84
+ candidates.push(join(repoRoot, ".cairn", "config", "sensors.yaml"));
85
+ }
86
+ candidates.push(PKG_TEMPLATE_SENSORS);
87
+ for (const p of candidates) {
88
+ if (!existsSync(p))
89
+ continue;
90
+ const doc = parseYaml(readFileSync(p, "utf8"));
91
+ const version = typeof doc["version"] === "number" ? doc["version"] : 1;
92
+ const sensors = [];
93
+ for (const raw of doc["sensors"] ?? []) {
94
+ if (typeof raw !== "object" || raw === null)
95
+ continue;
96
+ const r = raw;
97
+ sensors.push({
98
+ id: String(r["id"] ?? ""),
99
+ layer: String(r["layer"] ?? ""),
100
+ kind: String(r["kind"] ?? ""),
101
+ description: String(r["description"] ?? ""),
102
+ triggers: Array.isArray(r["triggers"]) ? r["triggers"] : [],
103
+ ...(Array.isArray(r["glob_keys"]) ? { glob_keys: r["glob_keys"] } : {}),
104
+ ...(typeof r["catalog"] === "string" ? { catalog: r["catalog"] } : {}),
105
+ ...(r["fail_severity"] === "hard" || r["fail_severity"] === "soft"
106
+ ? { fail_severity: r["fail_severity"] }
107
+ : {}),
108
+ });
109
+ }
110
+ return {
111
+ version,
112
+ sensors,
113
+ required_glob_keys: Array.isArray(doc["required_glob_keys"])
114
+ ? doc["required_glob_keys"]
115
+ : [],
116
+ disabled_per_project: Array.isArray(doc["disabled_per_project"])
117
+ ? doc["disabled_per_project"]
118
+ : [],
119
+ };
120
+ }
121
+ throw new Error(`sensors.yaml not found; checked: ${candidates.join(", ")}`);
122
+ }
123
+ //# sourceMappingURL=catalog.js.map