@isaacriehm/cairn-core 0.1.10 → 0.3.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 (399) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/claude/runner.d.ts +1 -1
  3. package/dist/claude/runner.js +62 -1
  4. package/dist/claude/runner.js.map +1 -1
  5. package/dist/claude/types.d.ts +14 -7
  6. package/dist/claude/types.js +5 -7
  7. package/dist/claude/types.js.map +1 -1
  8. package/dist/context/index.d.ts +4 -4
  9. package/dist/context/index.js +3 -4
  10. package/dist/context/index.js.map +1 -1
  11. package/dist/context/spec-delta.js +3 -4
  12. package/dist/context/spec-delta.js.map +1 -1
  13. package/dist/context/task-summary.d.ts +18 -0
  14. package/dist/context/task-summary.js +89 -0
  15. package/dist/context/task-summary.js.map +1 -0
  16. package/dist/decision-capture/id.d.ts +21 -4
  17. package/dist/decision-capture/id.js +56 -5
  18. package/dist/decision-capture/id.js.map +1 -1
  19. package/dist/decision-capture/index.d.ts +7 -22
  20. package/dist/decision-capture/index.js +7 -17
  21. package/dist/decision-capture/index.js.map +1 -1
  22. package/dist/doctor/index.d.ts +2 -2
  23. package/dist/doctor/index.js +5 -60
  24. package/dist/doctor/index.js.map +1 -1
  25. package/dist/events/index.d.ts +1 -1
  26. package/dist/events/index.js +1 -1
  27. package/dist/events/writer.d.ts +1 -1
  28. package/dist/events/writer.js +1 -1
  29. package/dist/gc/canary.d.ts +13 -23
  30. package/dist/gc/canary.js +36 -92
  31. package/dist/gc/canary.js.map +1 -1
  32. package/dist/gc/citation-integrity.d.ts +6 -6
  33. package/dist/gc/citation-integrity.js +64 -20
  34. package/dist/gc/citation-integrity.js.map +1 -1
  35. package/dist/gc/frontmatter.js +1 -1
  36. package/dist/gc/generator-drift.js +1 -1
  37. package/dist/gc/generator-drift.js.map +1 -1
  38. package/dist/gc/index.d.ts +2 -2
  39. package/dist/gc/index.js +1 -1
  40. package/dist/gc/index.js.map +1 -1
  41. package/dist/gc/quality-update.d.ts +4 -4
  42. package/dist/gc/quality-update.js +5 -5
  43. package/dist/gc/quality-update.js.map +1 -1
  44. package/dist/gc/types.d.ts +1 -30
  45. package/dist/ground/index.d.ts +2 -2
  46. package/dist/ground/index.js +1 -1
  47. package/dist/ground/index.js.map +1 -1
  48. package/dist/ground/ledgers.d.ts +0 -4
  49. package/dist/ground/ledgers.js +10 -8
  50. package/dist/ground/ledgers.js.map +1 -1
  51. package/dist/ground/manifest.js +0 -4
  52. package/dist/ground/manifest.js.map +1 -1
  53. package/dist/ground/paths.js +0 -1
  54. package/dist/ground/paths.js.map +1 -1
  55. package/dist/ground/quality-grades.js +3 -1
  56. package/dist/ground/quality-grades.js.map +1 -1
  57. package/dist/ground/schemas.d.ts +2 -7
  58. package/dist/ground/schemas.js +7 -2
  59. package/dist/ground/schemas.js.map +1 -1
  60. package/dist/ground/scope-index.d.ts +62 -14
  61. package/dist/ground/scope-index.js +215 -45
  62. package/dist/ground/scope-index.js.map +1 -1
  63. package/dist/hooks/bypass-detection.js +14 -17
  64. package/dist/hooks/bypass-detection.js.map +1 -1
  65. package/dist/hooks/defer.d.ts +50 -0
  66. package/dist/hooks/defer.js +87 -0
  67. package/dist/hooks/defer.js.map +1 -0
  68. package/dist/hooks/post-tool-use/citation-scanner.d.ts +7 -5
  69. package/dist/hooks/post-tool-use/citation-scanner.js +15 -9
  70. package/dist/hooks/post-tool-use/citation-scanner.js.map +1 -1
  71. package/dist/hooks/post-tool-use/copy-scanner.js +1 -1
  72. package/dist/hooks/post-tool-use/copy-scanner.js.map +1 -1
  73. package/dist/hooks/post-tool-use/ledger-cache.d.ts +10 -2
  74. package/dist/hooks/post-tool-use/ledger-cache.js +58 -4
  75. package/dist/hooks/post-tool-use/ledger-cache.js.map +1 -1
  76. package/dist/hooks/post-tool-use/legend-builder.d.ts +3 -3
  77. package/dist/hooks/post-tool-use/legend-builder.js +30 -8
  78. package/dist/hooks/post-tool-use/legend-builder.js.map +1 -1
  79. package/dist/hooks/post-tool-use/read-enricher.d.ts +1 -1
  80. package/dist/hooks/post-tool-use/read-enricher.js +68 -21
  81. package/dist/hooks/post-tool-use/read-enricher.js.map +1 -1
  82. package/dist/hooks/post-tool-use/write-guardian.js +148 -18
  83. package/dist/hooks/post-tool-use/write-guardian.js.map +1 -1
  84. package/dist/hooks/runners/index.d.ts +3 -0
  85. package/dist/hooks/runners/index.js +2 -0
  86. package/dist/hooks/runners/index.js.map +1 -1
  87. package/dist/hooks/runners/payload.d.ts +1 -1
  88. package/dist/hooks/runners/payload.js +27 -12
  89. package/dist/hooks/runners/payload.js.map +1 -1
  90. package/dist/hooks/runners/session-start.js +250 -75
  91. package/dist/hooks/runners/session-start.js.map +1 -1
  92. package/dist/hooks/runners/stop.d.ts +9 -12
  93. package/dist/hooks/runners/stop.js +129 -41
  94. package/dist/hooks/runners/stop.js.map +1 -1
  95. package/dist/hooks/runners/user-prompt-submit.d.ts +15 -0
  96. package/dist/hooks/runners/user-prompt-submit.js +149 -0
  97. package/dist/hooks/runners/user-prompt-submit.js.map +1 -0
  98. package/dist/hooks/seed-attested.d.ts +25 -0
  99. package/dist/hooks/seed-attested.js +84 -0
  100. package/dist/hooks/seed-attested.js.map +1 -0
  101. package/dist/hooks/user-prompt-submit.d.ts +7 -0
  102. package/dist/hooks/user-prompt-submit.js +12 -0
  103. package/dist/hooks/user-prompt-submit.js.map +1 -0
  104. package/dist/index.d.ts +3 -6
  105. package/dist/index.js +14 -12
  106. package/dist/index.js.map +1 -1
  107. package/dist/init/baseline-audit.d.ts +5 -1
  108. package/dist/init/baseline-audit.js +25 -2
  109. package/dist/init/baseline-audit.js.map +1 -1
  110. package/dist/init/glob-inference.d.ts +16 -0
  111. package/dist/init/glob-inference.js +108 -0
  112. package/dist/init/glob-inference.js.map +1 -0
  113. package/dist/init/index.d.ts +4 -0
  114. package/dist/init/index.js +2 -0
  115. package/dist/init/index.js.map +1 -1
  116. package/dist/init/ingest-docs.d.ts +1 -1
  117. package/dist/init/ingest-docs.js +19 -6
  118. package/dist/init/ingest-docs.js.map +1 -1
  119. package/dist/init/init.js +17 -94
  120. package/dist/init/init.js.map +1 -1
  121. package/dist/init/mapper-merge.d.ts +8 -2
  122. package/dist/init/mapper-merge.js +50 -32
  123. package/dist/init/mapper-merge.js.map +1 -1
  124. package/dist/init/mapper-parallel.d.ts +2 -3
  125. package/dist/init/mapper-parallel.js +9 -38
  126. package/dist/init/mapper-parallel.js.map +1 -1
  127. package/dist/init/mapper-prompts.js +1 -1
  128. package/dist/init/mapper-prompts.js.map +1 -1
  129. package/dist/init/mapper.d.ts +7 -128
  130. package/dist/init/mapper.js +30 -7
  131. package/dist/init/mapper.js.map +1 -1
  132. package/dist/init/module-slicer.d.ts +1 -1
  133. package/dist/init/module-slicer.js +1 -1
  134. package/dist/init/multi-dev/install.d.ts +9 -10
  135. package/dist/init/multi-dev/install.js +15 -84
  136. package/dist/init/multi-dev/install.js.map +1 -1
  137. package/dist/init/overlay.d.ts +14 -0
  138. package/dist/init/overlay.js +65 -0
  139. package/dist/init/overlay.js.map +1 -0
  140. package/dist/init/phases/1-detect.d.ts +10 -0
  141. package/dist/init/phases/1-detect.js +36 -0
  142. package/dist/init/phases/1-detect.js.map +1 -0
  143. package/dist/init/phases/10-strip.d.ts +11 -0
  144. package/dist/init/phases/10-strip.js +79 -0
  145. package/dist/init/phases/10-strip.js.map +1 -0
  146. package/dist/init/phases/12-multidev.d.ts +6 -0
  147. package/dist/init/phases/12-multidev.js +34 -0
  148. package/dist/init/phases/12-multidev.js.map +1 -0
  149. package/dist/init/phases/2-walker.d.ts +8 -0
  150. package/dist/init/phases/2-walker.js +34 -0
  151. package/dist/init/phases/2-walker.js.map +1 -0
  152. package/dist/init/phases/3-mapper.d.ts +14 -0
  153. package/dist/init/phases/3-mapper.js +56 -0
  154. package/dist/init/phases/3-mapper.js.map +1 -0
  155. package/dist/init/phases/3b-seed.d.ts +18 -0
  156. package/dist/init/phases/3b-seed.js +140 -0
  157. package/dist/init/phases/3b-seed.js.map +1 -0
  158. package/dist/init/phases/4-pilot.d.ts +10 -0
  159. package/dist/init/phases/4-pilot.js +108 -0
  160. package/dist/init/phases/4-pilot.js.map +1 -0
  161. package/dist/init/phases/5-brand.d.ts +10 -0
  162. package/dist/init/phases/5-brand.js +66 -0
  163. package/dist/init/phases/5-brand.js.map +1 -0
  164. package/dist/init/phases/6-docs-ingest.d.ts +11 -0
  165. package/dist/init/phases/6-docs-ingest.js +39 -0
  166. package/dist/init/phases/6-docs-ingest.js.map +1 -0
  167. package/dist/init/phases/7b-source-comments.d.ts +6 -0
  168. package/dist/init/phases/7b-source-comments.js +34 -0
  169. package/dist/init/phases/7b-source-comments.js.map +1 -0
  170. package/dist/init/phases/7c-rules-merge.d.ts +6 -0
  171. package/dist/init/phases/7c-rules-merge.js +34 -0
  172. package/dist/init/phases/7c-rules-merge.js.map +1 -0
  173. package/dist/init/phases/8-baseline.d.ts +10 -0
  174. package/dist/init/phases/8-baseline.js +52 -0
  175. package/dist/init/phases/8-baseline.js.map +1 -0
  176. package/dist/init/phases/index.d.ts +15 -0
  177. package/dist/init/phases/index.js +16 -0
  178. package/dist/init/phases/index.js.map +1 -0
  179. package/dist/init/phases/orchestrator.d.ts +49 -0
  180. package/dist/init/phases/orchestrator.js +85 -0
  181. package/dist/init/phases/orchestrator.js.map +1 -0
  182. package/dist/init/phases/state-io.d.ts +19 -0
  183. package/dist/init/phases/state-io.js +73 -0
  184. package/dist/init/phases/state-io.js.map +1 -0
  185. package/dist/init/phases/types.d.ts +93 -0
  186. package/dist/init/phases/types.js +30 -0
  187. package/dist/init/phases/types.js.map +1 -0
  188. package/dist/init/prompts.d.ts +6 -8
  189. package/dist/init/prompts.js +3 -6
  190. package/dist/init/prompts.js.map +1 -1
  191. package/dist/init/rules-merge/ingest.js +1 -1
  192. package/dist/init/seed.js +11 -2
  193. package/dist/init/seed.js.map +1 -1
  194. package/dist/init/source-comments/classify.d.ts +1 -41
  195. package/dist/init/source-comments/classify.js +68 -37
  196. package/dist/init/source-comments/classify.js.map +1 -1
  197. package/dist/init/source-comments/index.d.ts +2 -2
  198. package/dist/init/source-comments/index.js +2 -2
  199. package/dist/init/source-comments/index.js.map +1 -1
  200. package/dist/init/source-comments/ingest.d.ts +38 -2
  201. package/dist/init/source-comments/ingest.js +237 -4
  202. package/dist/init/source-comments/ingest.js.map +1 -1
  203. package/dist/init/source-comments/strip-replace.d.ts +10 -19
  204. package/dist/init/source-comments/strip-replace.js +26 -2
  205. package/dist/init/source-comments/strip-replace.js.map +1 -1
  206. package/dist/init/source-comments/walker.d.ts +9 -2
  207. package/dist/init/source-comments/walker.js +38 -19
  208. package/dist/init/source-comments/walker.js.map +1 -1
  209. package/dist/init/submodules.d.ts +3 -2
  210. package/dist/init/types.d.ts +3 -5
  211. package/dist/init/types.js +3 -5
  212. package/dist/init/types.js.map +1 -1
  213. package/dist/init/visual.d.ts +4 -9
  214. package/dist/init/visual.js +1 -16
  215. package/dist/init/visual.js.map +1 -1
  216. package/dist/init/walker.d.ts +0 -6
  217. package/dist/init/walker.js +2 -3
  218. package/dist/init/walker.js.map +1 -1
  219. package/dist/join/index.js +49 -2
  220. package/dist/join/index.js.map +1 -1
  221. package/dist/logger.d.ts +1 -2
  222. package/dist/logger.js +5 -6
  223. package/dist/logger.js.map +1 -1
  224. package/dist/mcp/context.d.ts +2 -3
  225. package/dist/mcp/context.js.map +1 -1
  226. package/dist/mcp/errors.d.ts +1 -1
  227. package/dist/mcp/errors.js.map +1 -1
  228. package/dist/mcp/history/prompt.d.ts +2 -1
  229. package/dist/mcp/history/walker.js +1 -1
  230. package/dist/mcp/history/walker.js.map +1 -1
  231. package/dist/mcp/path-allowlist.d.ts +0 -6
  232. package/dist/mcp/path-allowlist.js +0 -10
  233. package/dist/mcp/path-allowlist.js.map +1 -1
  234. package/dist/mcp/schemas.d.ts +34 -72
  235. package/dist/mcp/schemas.js +40 -70
  236. package/dist/mcp/schemas.js.map +1 -1
  237. package/dist/mcp/serve.d.ts +1 -1
  238. package/dist/mcp/serve.js +2 -5
  239. package/dist/mcp/serve.js.map +1 -1
  240. package/dist/mcp/server.js +10 -4
  241. package/dist/mcp/server.js.map +1 -1
  242. package/dist/mcp/telemetry.d.ts +8 -1
  243. package/dist/mcp/telemetry.js +16 -0
  244. package/dist/mcp/telemetry.js.map +1 -1
  245. package/dist/mcp/tools/decision-get.js +37 -29
  246. package/dist/mcp/tools/decision-get.js.map +1 -1
  247. package/dist/mcp/tools/decisions-in-scope.js +22 -3
  248. package/dist/mcp/tools/decisions-in-scope.js.map +1 -1
  249. package/dist/mcp/tools/ground-get.js +2 -2
  250. package/dist/mcp/tools/ground-get.js.map +1 -1
  251. package/dist/mcp/tools/index.js +6 -2
  252. package/dist/mcp/tools/index.js.map +1 -1
  253. package/dist/mcp/tools/init-phases.d.ts +24 -0
  254. package/dist/mcp/tools/init-phases.js +140 -0
  255. package/dist/mcp/tools/init-phases.js.map +1 -0
  256. package/dist/mcp/tools/invariant-get.js +1 -1
  257. package/dist/mcp/tools/invariant-get.js.map +1 -1
  258. package/dist/mcp/tools/invariants-in-scope.js +26 -7
  259. package/dist/mcp/tools/invariants-in-scope.js.map +1 -1
  260. package/dist/mcp/tools/query-history.js +3 -3
  261. package/dist/mcp/tools/query-history.js.map +1 -1
  262. package/dist/mcp/tools/resolve-attention.d.ts +6 -4
  263. package/dist/mcp/tools/resolve-attention.js +253 -24
  264. package/dist/mcp/tools/resolve-attention.js.map +1 -1
  265. package/dist/mcp/tools/search.js +3 -4
  266. package/dist/mcp/tools/search.js.map +1 -1
  267. package/dist/mcp/tools/task-create.d.ts +15 -0
  268. package/dist/mcp/tools/task-create.js +96 -0
  269. package/dist/mcp/tools/task-create.js.map +1 -0
  270. package/dist/mcp/tools/timeline.js +3 -7
  271. package/dist/mcp/tools/timeline.js.map +1 -1
  272. package/dist/profiles/types.d.ts +2 -2
  273. package/dist/profiles/types.js +1 -1
  274. package/dist/sensors/catalog.js +8 -3
  275. package/dist/sensors/catalog.js.map +1 -1
  276. package/dist/session/id.d.ts +1 -3
  277. package/dist/session/id.js +1 -1
  278. package/dist/session/id.js.map +1 -1
  279. package/dist/session-start/build.d.ts +7 -11
  280. package/dist/session-start/build.js +62 -34
  281. package/dist/session-start/build.js.map +1 -1
  282. package/dist/session-start/index.d.ts +2 -2
  283. package/dist/session-start/index.js +2 -2
  284. package/dist/session-start/index.js.map +1 -1
  285. package/dist/session-start/templates.d.ts +20 -4
  286. package/dist/session-start/templates.js +45 -35
  287. package/dist/session-start/templates.js.map +1 -1
  288. package/dist/status-line/format.d.ts +20 -9
  289. package/dist/status-line/format.js +45 -35
  290. package/dist/status-line/format.js.map +1 -1
  291. package/dist/status-line/index.d.ts +3 -4
  292. package/dist/status-line/index.js +1 -1
  293. package/dist/status-line/index.js.map +1 -1
  294. package/dist/status-line/reader.d.ts +9 -6
  295. package/dist/status-line/reader.js +50 -18
  296. package/dist/status-line/reader.js.map +1 -1
  297. package/dist/status-line/writer.d.ts +6 -9
  298. package/dist/status-line/writer.js +10 -12
  299. package/dist/status-line/writer.js.map +1 -1
  300. package/dist/trace/index.d.ts +44 -0
  301. package/dist/trace/index.js +51 -0
  302. package/dist/trace/index.js.map +1 -0
  303. package/package.json +2 -3
  304. package/templates/.archive/README.md +3 -3
  305. package/templates/.cairn/JOIN.md +3 -9
  306. package/templates/.cairn/config/sensors.yaml +16 -19
  307. package/templates/.cairn/config/stub-patterns.yaml +4 -4
  308. package/templates/.cairn/config/trust-policy.yaml +3 -35
  309. package/templates/.cairn/config/workflow.md +13 -194
  310. package/templates/.cairn/git-hooks/commit-msg +15 -4
  311. package/templates/.cairn/git-hooks/pre-commit +22 -13
  312. package/templates/.cairn/ground/canonical-map/topics.yaml +3 -26
  313. package/templates/.cairn/ground/capabilities/snippets.yaml +0 -1
  314. package/templates/.cairn/ground/manifest.yaml +5 -8
  315. package/templates/.cairn/ground/product/personas.yaml +0 -1
  316. package/dist/context/checkpoint.d.ts +0 -10
  317. package/dist/context/checkpoint.js +0 -29
  318. package/dist/context/checkpoint.js.map +0 -1
  319. package/dist/decision-capture/capture.d.ts +0 -57
  320. package/dist/decision-capture/capture.js +0 -186
  321. package/dist/decision-capture/capture.js.map +0 -1
  322. package/dist/decision-capture/extractor.d.ts +0 -20
  323. package/dist/decision-capture/extractor.js +0 -103
  324. package/dist/decision-capture/extractor.js.map +0 -1
  325. package/dist/decision-capture/prompt.d.ts +0 -15
  326. package/dist/decision-capture/prompt.js +0 -68
  327. package/dist/decision-capture/prompt.js.map +0 -1
  328. package/dist/decision-capture/refinement-prompt.d.ts +0 -25
  329. package/dist/decision-capture/refinement-prompt.js +0 -146
  330. package/dist/decision-capture/refinement-prompt.js.map +0 -1
  331. package/dist/decision-capture/refinement-schema.d.ts +0 -52
  332. package/dist/decision-capture/refinement-schema.js +0 -61
  333. package/dist/decision-capture/refinement-schema.js.map +0 -1
  334. package/dist/decision-capture/refinement.d.ts +0 -60
  335. package/dist/decision-capture/refinement.js +0 -439
  336. package/dist/decision-capture/refinement.js.map +0 -1
  337. package/dist/decision-capture/schema.d.ts +0 -70
  338. package/dist/decision-capture/schema.js +0 -71
  339. package/dist/decision-capture/schema.js.map +0 -1
  340. package/dist/decision-capture/types.d.ts +0 -201
  341. package/dist/decision-capture/types.js +0 -20
  342. package/dist/decision-capture/types.js.map +0 -1
  343. package/dist/decision-capture/writer.d.ts +0 -90
  344. package/dist/decision-capture/writer.js +0 -267
  345. package/dist/decision-capture/writer.js.map +0 -1
  346. package/dist/frontend-types.d.ts +0 -243
  347. package/dist/frontend-types.js +0 -15
  348. package/dist/frontend-types.js.map +0 -1
  349. package/dist/hooks/index.d.ts +0 -12
  350. package/dist/hooks/index.js +0 -13
  351. package/dist/hooks/index.js.map +0 -1
  352. package/dist/inbox.d.ts +0 -17
  353. package/dist/inbox.js +0 -30
  354. package/dist/inbox.js.map +0 -1
  355. package/dist/mcp/tools/append-run-note.d.ts +0 -18
  356. package/dist/mcp/tools/append-run-note.js +0 -47
  357. package/dist/mcp/tools/append-run-note.js.map +0 -1
  358. package/dist/mcp/tools/append.d.ts +0 -8
  359. package/dist/mcp/tools/append.js +0 -37
  360. package/dist/mcp/tools/append.js.map +0 -1
  361. package/dist/mcp/tools/ask-operator.d.ts +0 -34
  362. package/dist/mcp/tools/ask-operator.js +0 -97
  363. package/dist/mcp/tools/ask-operator.js.map +0 -1
  364. package/dist/mcp/tools/drop-task.d.ts +0 -12
  365. package/dist/mcp/tools/drop-task.js +0 -68
  366. package/dist/mcp/tools/drop-task.js.map +0 -1
  367. package/dist/mcp/tools/record-run-event.d.ts +0 -10
  368. package/dist/mcp/tools/record-run-event.js +0 -32
  369. package/dist/mcp/tools/record-run-event.js.map +0 -1
  370. package/dist/prompt.d.ts +0 -19
  371. package/dist/prompt.js +0 -50
  372. package/dist/prompt.js.map +0 -1
  373. package/dist/tier0/classify.d.ts +0 -10
  374. package/dist/tier0/classify.js +0 -110
  375. package/dist/tier0/classify.js.map +0 -1
  376. package/dist/tier0/index.d.ts +0 -2
  377. package/dist/tier0/index.js +0 -2
  378. package/dist/tier0/index.js.map +0 -1
  379. package/dist/tier0/types.d.ts +0 -24
  380. package/dist/tier0/types.js +0 -9
  381. package/dist/tier0/types.js.map +0 -1
  382. package/dist/tightener/index.d.ts +0 -4
  383. package/dist/tightener/index.js +0 -4
  384. package/dist/tightener/index.js.map +0 -1
  385. package/dist/tightener/prompt.d.ts +0 -3
  386. package/dist/tightener/prompt.js +0 -67
  387. package/dist/tightener/prompt.js.map +0 -1
  388. package/dist/tightener/schema.d.ts +0 -68
  389. package/dist/tightener/schema.js +0 -44
  390. package/dist/tightener/schema.js.map +0 -1
  391. package/dist/tightener/tighten.d.ts +0 -2
  392. package/dist/tightener/tighten.js +0 -66
  393. package/dist/tightener/tighten.js.map +0 -1
  394. package/dist/tightener/types.d.ts +0 -74
  395. package/dist/tightener/types.js +0 -6
  396. package/dist/tightener/types.js.map +0 -1
  397. package/templates/.claude/settings.json +0 -57
  398. package/templates/.mcp.json +0 -8
  399. package/templates/README.md +0 -24
@@ -1,243 +0,0 @@
1
- /**
2
- * Frontend adapter contract per `docs/WORKFLOW_GUIDE.md` §0.1.
3
- *
4
- * The orchestrator + grounding daemon + MCP server are frontend-agnostic.
5
- * The operator console is a swappable adapter that consumes a uniform
6
- * task/run/UAT bundle and renders/listens via its native primitive.
7
- *
8
- * Adapters live in `cairn/src/frontend/<name>/`. Each implements
9
- * `FrontendAdapter`. The `cairn run --frontend <name>` CLI loads + starts
10
- * registered adapters; on operator events, adapters drop normalized JSON rows
11
- * to `.cairn/inbox/<ts>-<source>-<slug>.json`. The orchestrator (Phase 8)
12
- * picks them up. Phase 5 lands ingress-only — no orchestrator yet.
13
- */
14
- export type NotifyLevel = "info" | "warn" | "error";
15
- /**
16
- * A normalized inbox entry kind. Adapters drop one of these to
17
- * `.cairn/inbox/`. The orchestrator multiplexes on `kind`.
18
- */
19
- export type InboxKind = "task" | "slash" | "free_text" | "voice" | "interaction";
20
- export interface FrontendTask {
21
- source: string;
22
- intent: string;
23
- rawText: string;
24
- authorId: string;
25
- channelId?: string;
26
- guildId?: string;
27
- messageId?: string;
28
- receivedAt: string;
29
- }
30
- export interface VoiceMessage {
31
- source: string;
32
- attachmentUrl: string;
33
- mime?: string;
34
- authorId: string;
35
- channelId: string;
36
- guildId?: string;
37
- messageId: string;
38
- receivedAt: string;
39
- }
40
- export interface SlashEvent {
41
- source: string;
42
- command: string;
43
- options: Record<string, string | number | boolean>;
44
- authorId: string;
45
- channelId?: string;
46
- guildId?: string;
47
- messageId?: string;
48
- receivedAt: string;
49
- }
50
- export interface FreeTextEvent {
51
- source: string;
52
- intent: string;
53
- rawText: string;
54
- authorId: string;
55
- channelId?: string;
56
- guildId?: string;
57
- messageId?: string;
58
- receivedAt: string;
59
- }
60
- export interface InteractionEvent {
61
- source: string;
62
- bundleId: string;
63
- choiceId: string;
64
- freeText?: string;
65
- authorId: string;
66
- channelId?: string;
67
- guildId?: string;
68
- messageId?: string;
69
- receivedAt: string;
70
- }
71
- export interface DialogChoice {
72
- /** Stable id ("a" | "b" | ... | "e_other"). */
73
- id: string;
74
- label: string;
75
- }
76
- export interface DialogSpec {
77
- /** Origin run / task id used to correlate adapter responses. */
78
- bundleId: string;
79
- prompt: string;
80
- /**
81
- * 2-5 choices. Last MUST be `E) Other` per WORKFLOW_GUIDE §1.4.
82
- * If more than 4 orthogonal questions arise, caller MUST collapse to a
83
- * single tightened-spec proposal per §1.0 (cap = 2 questions/turn).
84
- */
85
- choices: DialogChoice[];
86
- channelId?: string;
87
- timeoutMs?: number;
88
- /**
89
- * When true, the adapter notifies authorized operators (push, mention,
90
- * etc. — adapter-defined) so they see the run is paused. Used for
91
- * agent-initiated `cairn_ask_operator`; routine confirmations leave
92
- * this false to avoid noise.
93
- */
94
- pingOperators?: boolean;
95
- /**
96
- * §3.4 win 1 — multi-step walks (per-question tightener resolution,
97
- * /oops branches) edit one message in place instead of posting N+1
98
- * messages. Set this to the previous step's `bundleId`; the adapter
99
- * looks it up in its dialog-message map and edits that message
100
- * (same channel, new prompt + buttons). When the bundleId is
101
- * unknown (gone, never registered) the adapter falls back to a
102
- * fresh send.
103
- */
104
- replaceBundleId?: string;
105
- /**
106
- * Terminal-dialog flag. When true (default), the adapter compacts
107
- * the message on click — strips buttons, appends an "Answered" line
108
- * — so the channel scrollback shows what was chosen. Walk steps
109
- * that intend to be replaced by a follow-on dialog (per-Q tightener)
110
- * MUST pass false: otherwise the compaction race-edits the message
111
- * the next step is about to overwrite, and either the answer
112
- * annotation or the next prompt loses depending on REST ordering.
113
- * Adapter still fires `deferUpdate` so the click acknowledges.
114
- */
115
- compactOnAnswer?: boolean;
116
- }
117
- export interface DialogResponse {
118
- bundleId: string;
119
- choiceId: string;
120
- /** Populated only when `choiceId` is the `E) Other` option. */
121
- freeText?: string;
122
- timedOut?: boolean;
123
- }
124
- export interface ApprovalArtifact {
125
- kind: "gif" | "screenshot" | "table" | "diff" | "log" | "url" | "text";
126
- label?: string;
127
- path?: string;
128
- url?: string;
129
- content?: string;
130
- }
131
- export interface ApprovalBundle {
132
- bundleId: string;
133
- runId: string;
134
- taskId?: string;
135
- goal: string;
136
- diffSummary?: string;
137
- acceptance?: {
138
- id: string;
139
- status: "pass" | "fail" | "pending";
140
- note?: string;
141
- }[];
142
- artifacts?: ApprovalArtifact[];
143
- channelId?: string;
144
- timeoutMs?: number;
145
- }
146
- export interface Approval {
147
- bundleId: string;
148
- decision: "approve" | "reject" | "ask";
149
- reason?: string;
150
- timedOut?: boolean;
151
- }
152
- export interface PostUpdate {
153
- taskId: string;
154
- runId?: string;
155
- status: string;
156
- /**
157
- * Free-form body. ≤1024 chars renders as inline embed `details` field
158
- * (§3.3 win 3 — drops the live-status + content-message split). >1024
159
- * chars falls back to the chunked secondary-embed path.
160
- */
161
- body?: string;
162
- /**
163
- * Original task spec (the operator's verbatim ask). Replaces the
164
- * standalone `🆕 Task` drop card — the body lives on the same live
165
- * status embed as everything else, so the channel only ever shows
166
- * one self-updating message per task. Truncated at 1024 chars.
167
- */
168
- taskBody?: string;
169
- channelId?: string;
170
- /**
171
- * Tier-0 (Haiku) summary of what the agent is doing right now —
172
- * one-line, present-progressive ("Reading core/src/X", "Editing
173
- * platform/Y"). Surfaces inside the live status embed so the
174
- * operator sees ongoing activity instead of a static "running" badge.
175
- * Set on a throttled cadence by the orchestrator during the
176
- * implementer phase.
177
- */
178
- activity?: string;
179
- /**
180
- * Second-source visibility — extracted from claude stream-json events.
181
- * Independent of the Tier-0 summary; renders even when the Tier-0 call
182
- * fails. Each list capped + deduped at the source.
183
- */
184
- tools?: {
185
- files?: string[];
186
- bash?: string[];
187
- searches?: string[];
188
- };
189
- /**
190
- * Curated narrative tail from `.cairn/runs/active/<run_id>/log.jsonl`
191
- * (§3.3 win 1) — last N transitions, pre-formatted. Renders inside the
192
- * live status embed's description so operator sees actual progress
193
- * instead of a static "phase: running" line.
194
- */
195
- recentEvents?: string[];
196
- /**
197
- * §3.4 win 3 — when status === "failed", the orchestrator classifies
198
- * which gate eject the run so the embed renders class-colored title +
199
- * emoji. Operator can route differently per class.
200
- */
201
- failureClass?: "sensor" | "reviewer" | "uat" | "hard" | "halt";
202
- /**
203
- * §3.4 win 2 — failure remediation guidance surfaced as a dedicated
204
- * embed field. `reason` is a one-liner; `suggestedActions` are the
205
- * operator's next moves (`/ship-anyway`, re-submit, open thread).
206
- */
207
- remediation?: {
208
- reason: string;
209
- suggestedActions: string[];
210
- };
211
- }
212
- export type IngestHandler<T> = (item: T) => void | Promise<void>;
213
- export interface FrontendAdapter {
214
- readonly name: string;
215
- /** Connects, registers commands, prepares to ingest events. */
216
- start(): Promise<void>;
217
- /** Disconnects + cleans up. Idempotent. */
218
- stop(): Promise<void>;
219
- onTask(handler: IngestHandler<FrontendTask>): void;
220
- onVoice(handler: IngestHandler<VoiceMessage>): void;
221
- onSlash(handler: IngestHandler<SlashEvent>): void;
222
- onFreeText(handler: IngestHandler<FreeTextEvent>): void;
223
- onInteraction(handler: IngestHandler<InteractionEvent>): void;
224
- postTaskUpdate(update: PostUpdate): Promise<void>;
225
- requestApproval(bundle: ApprovalBundle): Promise<Approval>;
226
- requestDialog(spec: DialogSpec): Promise<DialogResponse>;
227
- notify(level: NotifyLevel, message: string): Promise<void>;
228
- /**
229
- * Show a "typing" / activity indicator on the given channel until the
230
- * returned stop fn is called. Adapters without a native typing
231
- * indicator should no-op.
232
- */
233
- startTyping?(channelId: string): () => void;
234
- /**
235
- * Pre-flight check: is this channel still reachable + writable?
236
- * Adapters that maintain channels MUST return false when the channel
237
- * has been deleted or the adapter lacks access. The orchestrator uses
238
- * this to skip dispatching a queued task whose channel is gone.
239
- * Adapters without channels should leave this undefined; the
240
- * orchestrator treats undefined as "always alive".
241
- */
242
- isChannelAlive?(channelId: string): Promise<boolean>;
243
- }
@@ -1,15 +0,0 @@
1
- /**
2
- * Frontend adapter contract per `docs/WORKFLOW_GUIDE.md` §0.1.
3
- *
4
- * The orchestrator + grounding daemon + MCP server are frontend-agnostic.
5
- * The operator console is a swappable adapter that consumes a uniform
6
- * task/run/UAT bundle and renders/listens via its native primitive.
7
- *
8
- * Adapters live in `cairn/src/frontend/<name>/`. Each implements
9
- * `FrontendAdapter`. The `cairn run --frontend <name>` CLI loads + starts
10
- * registered adapters; on operator events, adapters drop normalized JSON rows
11
- * to `.cairn/inbox/<ts>-<source>-<slug>.json`. The orchestrator (Phase 8)
12
- * picks them up. Phase 5 lands ingress-only — no orchestrator yet.
13
- */
14
- export {};
15
- //# sourceMappingURL=frontend-types.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"frontend-types.js","sourceRoot":"","sources":["../src/frontend-types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG"}
@@ -1,12 +0,0 @@
1
- /**
2
- * Claude Code hooks — runner functions + bin entrypoints.
3
- *
4
- * Bin entrypoints live at `dist/hooks/<event>.js` (one per event) so
5
- * the plugin manifest can invoke them via
6
- * `node ${CLAUDE_PLUGIN_ROOT}/../cairn-core/dist/hooks/<event>.js`
7
- * without depending on the `cairn` umbrella CLI being on PATH.
8
- *
9
- * The umbrella CLI's `cairn hook <event>` calls the same runners.
10
- */
11
- export * from "./runners/index.js";
12
- export * from "./post-tool-use/index.js";
@@ -1,13 +0,0 @@
1
- /**
2
- * Claude Code hooks — runner functions + bin entrypoints.
3
- *
4
- * Bin entrypoints live at `dist/hooks/<event>.js` (one per event) so
5
- * the plugin manifest can invoke them via
6
- * `node ${CLAUDE_PLUGIN_ROOT}/../cairn-core/dist/hooks/<event>.js`
7
- * without depending on the `cairn` umbrella CLI being on PATH.
8
- *
9
- * The umbrella CLI's `cairn hook <event>` calls the same runners.
10
- */
11
- export * from "./runners/index.js";
12
- export * from "./post-tool-use/index.js";
13
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,cAAc,oBAAoB,CAAC;AACnC,cAAc,0BAA0B,CAAC"}
package/dist/inbox.d.ts DELETED
@@ -1,17 +0,0 @@
1
- import type { InboxKind } from "./frontend-types.js";
2
- /**
3
- * Append a normalized event row to `.cairn/inbox/`.
4
- *
5
- * The orchestrator (Phase 8) tails this directory and acts on each row.
6
- * Phase 5 just lands rows — no orchestrator yet. Inbox is a write-allowed
7
- * path per `cairn/src/mcp/path-allowlist.ts` (`APPEND_ALLOWLIST`).
8
- *
9
- * Filename pattern: `<ts>-<source>-<kind>-<slug>.json`. Sortable, scannable,
10
- * collision-resistant under concurrent writers.
11
- */
12
- export declare function writeInboxRow(args: {
13
- repoRoot: string;
14
- source: string;
15
- kind: InboxKind;
16
- payload: object;
17
- }): Promise<string>;
package/dist/inbox.js DELETED
@@ -1,30 +0,0 @@
1
- import { mkdir, writeFile } from "node:fs/promises";
2
- import { randomBytes } from "node:crypto";
3
- import { join } from "node:path";
4
- /**
5
- * Append a normalized event row to `.cairn/inbox/`.
6
- *
7
- * The orchestrator (Phase 8) tails this directory and acts on each row.
8
- * Phase 5 just lands rows — no orchestrator yet. Inbox is a write-allowed
9
- * path per `cairn/src/mcp/path-allowlist.ts` (`APPEND_ALLOWLIST`).
10
- *
11
- * Filename pattern: `<ts>-<source>-<kind>-<slug>.json`. Sortable, scannable,
12
- * collision-resistant under concurrent writers.
13
- */
14
- export async function writeInboxRow(args) {
15
- const { repoRoot, source, kind, payload } = args;
16
- const dir = join(repoRoot, ".cairn", "inbox");
17
- await mkdir(dir, { recursive: true });
18
- const ts = Date.now();
19
- const slug = randomBytes(4).toString("hex");
20
- const file = join(dir, `${ts}-${source}-${kind}-${slug}.json`);
21
- const row = {
22
- kind,
23
- source,
24
- received_at: new Date().toISOString(),
25
- ...payload,
26
- };
27
- await writeFile(file, `${JSON.stringify(row, null, 2)}\n`, "utf8");
28
- return file;
29
- }
30
- //# sourceMappingURL=inbox.js.map
package/dist/inbox.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"inbox.js","sourceRoot":"","sources":["../src/inbox.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAGjC;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,IAKnC;IACC,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IACjD,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC9C,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACtC,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACtB,MAAM,IAAI,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC5C,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,MAAM,IAAI,IAAI,IAAI,IAAI,OAAO,CAAC,CAAC;IAC/D,MAAM,GAAG,GAAG;QACV,IAAI;QACJ,MAAM;QACN,WAAW,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACrC,GAAG,OAAO;KACX,CAAC;IACF,MAAM,SAAS,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACnE,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -1,18 +0,0 @@
1
- /**
2
- * `cairn_append_run_note` — append a phase-tagged note to a task's notes.md.
3
- *
4
- * The handoff builder (CONTEXT_CONTINUITY_SPEC §2.2) reads notes.md when it
5
- * resumes an in-flight run, so notes survive context compaction by virtue of
6
- * being committed to disk. The MCP write surface is append-only and gated
7
- * by the path allowlist — see `mcp/path-allowlist.ts`.
8
- *
9
- * Spec: docs/CONTEXT_CONTINUITY_SPEC.md §2.3.
10
- */
11
- import type { ToolDef } from "./types.js";
12
- interface Input {
13
- run_id: string;
14
- phase: string;
15
- note: string;
16
- }
17
- export declare const appendRunNoteTool: ToolDef<Input>;
18
- export {};
@@ -1,47 +0,0 @@
1
- /**
2
- * `cairn_append_run_note` — append a phase-tagged note to a task's notes.md.
3
- *
4
- * The handoff builder (CONTEXT_CONTINUITY_SPEC §2.2) reads notes.md when it
5
- * resumes an in-flight run, so notes survive context compaction by virtue of
6
- * being committed to disk. The MCP write surface is append-only and gated
7
- * by the path allowlist — see `mcp/path-allowlist.ts`.
8
- *
9
- * Spec: docs/CONTEXT_CONTINUITY_SPEC.md §2.3.
10
- */
11
- import { appendFileSync, existsSync } from "node:fs";
12
- import { join } from "node:path";
13
- import { mcpError } from "../errors.js";
14
- import { isAppendAllowed, relPosix, safeJoin } from "../path-allowlist.js";
15
- import { appendRunNoteInput } from "../schemas.js";
16
- const RUN_ID_RE = /^[A-Za-z0-9_-]+$/;
17
- async function handler(ctx, input) {
18
- if (!RUN_ID_RE.test(input.run_id) || input.run_id.length > 80) {
19
- return mcpError("VALIDATION_FAILED", `run_id must match path-safe pattern [A-Za-z0-9_-] (≤80 chars)`);
20
- }
21
- const rel = `.cairn/tasks/active/${input.run_id}/notes.md`;
22
- const abs = safeJoin(ctx.repoRoot, rel);
23
- if (typeof abs !== "string")
24
- return abs; // error envelope
25
- const relCanon = relPosix(ctx.repoRoot, abs);
26
- if (!isAppendAllowed(relCanon)) {
27
- return mcpError("PATH_NOT_ALLOWED", `Append-write is not allowed for "${relCanon}".`);
28
- }
29
- const taskDir = join(ctx.repoRoot, ".cairn", "tasks", "active", input.run_id);
30
- if (!existsSync(taskDir)) {
31
- return mcpError("RUN_NOT_FOUND", `No active task dir at .cairn/tasks/active/${input.run_id}/`);
32
- }
33
- const entry = `\n## ${new Date().toISOString()} [${input.phase}]\n${input.note}\n`;
34
- appendFileSync(abs, entry, "utf8");
35
- return {
36
- ok: true,
37
- path: relCanon,
38
- bytes_written: Buffer.byteLength(entry, "utf8"),
39
- };
40
- }
41
- export const appendRunNoteTool = {
42
- name: "cairn_append_run_note",
43
- description: "Append a phase-tagged note to .cairn/tasks/active/<run_id>/notes.md. The handoff builder reads notes.md so notes survive across sessions / context compaction. The run_id field must match the active task dir id (path-safe chars only).",
44
- inputSchema: appendRunNoteInput,
45
- handler,
46
- };
47
- //# sourceMappingURL=append-run-note.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"append-run-note.js","sourceRoot":"","sources":["../../../src/mcp/tools/append-run-note.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAC3E,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AASnD,MAAM,SAAS,GAAG,kBAAkB,CAAC;AAErC,KAAK,UAAU,OAAO,CAAC,GAAe,EAAE,KAAY;IAClD,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,EAAE,EAAE,CAAC;QAC9D,OAAO,QAAQ,CACb,mBAAmB,EACnB,+DAA+D,CAChE,CAAC;IACJ,CAAC;IAED,MAAM,GAAG,GAAG,uBAAuB,KAAK,CAAC,MAAM,WAAW,CAAC;IAC3D,MAAM,GAAG,GAAG,QAAQ,CAAC,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;IACxC,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,GAAG,CAAC,CAAC,iBAAiB;IAE1D,MAAM,QAAQ,GAAG,QAAQ,CAAC,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;IAC7C,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC/B,OAAO,QAAQ,CACb,kBAAkB,EAClB,oCAAoC,QAAQ,IAAI,CACjD,CAAC;IACJ,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAC9E,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QACzB,OAAO,QAAQ,CACb,eAAe,EACf,6CAA6C,KAAK,CAAC,MAAM,GAAG,CAC7D,CAAC;IACJ,CAAC;IAED,MAAM,KAAK,GAAG,QAAQ,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,KAAK,KAAK,CAAC,KAAK,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC;IACnF,cAAc,CAAC,GAAG,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;IACnC,OAAO;QACL,EAAE,EAAE,IAAI;QACR,IAAI,EAAE,QAAQ;QACd,aAAa,EAAE,MAAM,CAAC,UAAU,CAAC,KAAK,EAAE,MAAM,CAAC;KAChD,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,MAAM,iBAAiB,GAAmB;IAC/C,IAAI,EAAE,uBAAuB;IAC7B,WAAW,EACT,2OAA2O;IAC7O,WAAW,EAAE,kBAAkB;IAC/B,OAAO;CACR,CAAC"}
@@ -1,8 +0,0 @@
1
- import type { ToolDef } from "./types.js";
2
- interface Input {
3
- path: string;
4
- content: string;
5
- newline_separator?: boolean;
6
- }
7
- export declare const appendTool: ToolDef<Input>;
8
- export {};
@@ -1,37 +0,0 @@
1
- import { appendFileSync, existsSync, mkdirSync } from "node:fs";
2
- import { dirname } from "node:path";
3
- import { requireBootstrap } from "../bootstrap-guard.js";
4
- import { mcpError } from "../errors.js";
5
- import { isAppendAllowed, relPosix, safeJoin } from "../path-allowlist.js";
6
- import { appendInput } from "../schemas.js";
7
- async function handler(ctx, input) {
8
- const block = requireBootstrap(ctx.repoRoot);
9
- if (block !== null)
10
- return block;
11
- const abs = safeJoin(ctx.repoRoot, input.path);
12
- if (typeof abs !== "string")
13
- return abs; // error envelope
14
- const rel = relPosix(ctx.repoRoot, abs);
15
- if (!isAppendAllowed(rel)) {
16
- return mcpError("PATH_NOT_ALLOWED", `Append-write is not allowed for "${rel}". Allowlist limited to runs/active/<id>/{events,commands}.jsonl, staleness/log.jsonl, and inbox/**.`);
17
- }
18
- // For runs/active/<id>/* paths, the run id segment must exist as a directory.
19
- const runMatch = rel.match(/^\.cairn\/runs\/active\/([^/]+)\//);
20
- if (runMatch) {
21
- const runDir = `${ctx.repoRoot}/.cairn/runs/active/${runMatch[1]}`;
22
- if (!existsSync(runDir)) {
23
- return mcpError("RUN_NOT_FOUND", `No active run dir at ${runDir}`);
24
- }
25
- }
26
- mkdirSync(dirname(abs), { recursive: true });
27
- const sep = input.newline_separator !== false ? "\n" : "";
28
- appendFileSync(abs, input.content + sep, "utf8");
29
- return { ok: true, path: rel, bytes_written: Buffer.byteLength(input.content + sep, "utf8") };
30
- }
31
- export const appendTool = {
32
- name: "cairn_append",
33
- description: "Append-only write to a path-allowlisted file. No read required. Allowlist: runs/active/<id>/{events,commands}.jsonl, staleness/log.jsonl, inbox/**.",
34
- inputSchema: appendInput,
35
- handler,
36
- };
37
- //# sourceMappingURL=append.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"append.js","sourceRoot":"","sources":["../../../src/mcp/tools/append.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAChE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAC3E,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAS5C,KAAK,UAAU,OAAO,CAAC,GAAe,EAAE,KAAY;IAClD,MAAM,KAAK,GAAG,gBAAgB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC7C,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IACjC,MAAM,GAAG,GAAG,QAAQ,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;IAC/C,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,GAAG,CAAC,CAAC,iBAAiB;IAC1D,MAAM,GAAG,GAAG,QAAQ,CAAC,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;IACxC,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,EAAE,CAAC;QAC1B,OAAO,QAAQ,CACb,kBAAkB,EAClB,oCAAoC,GAAG,sGAAsG,CAC9I,CAAC;IACJ,CAAC;IACD,8EAA8E;IAC9E,MAAM,QAAQ,GAAG,GAAG,CAAC,KAAK,CAAC,mCAAmC,CAAC,CAAC;IAChE,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,MAAM,GAAG,GAAG,GAAG,CAAC,QAAQ,uBAAuB,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;QACnE,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;YACxB,OAAO,QAAQ,CAAC,eAAe,EAAE,wBAAwB,MAAM,EAAE,CAAC,CAAC;QACrE,CAAC;IACH,CAAC;IACD,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7C,MAAM,GAAG,GAAG,KAAK,CAAC,iBAAiB,KAAK,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;IAC1D,cAAc,CAAC,GAAG,EAAE,KAAK,CAAC,OAAO,GAAG,GAAG,EAAE,MAAM,CAAC,CAAC;IACjD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,aAAa,EAAE,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,OAAO,GAAG,GAAG,EAAE,MAAM,CAAC,EAAE,CAAC;AAChG,CAAC;AAED,MAAM,CAAC,MAAM,UAAU,GAAmB;IACxC,IAAI,EAAE,cAAc;IACpB,WAAW,EACT,qJAAqJ;IACvJ,WAAW,EAAE,WAAW;IACxB,OAAO;CACR,CAAC"}
@@ -1,34 +0,0 @@
1
- /**
2
- * cairn_ask_operator — agent-initiated operator dialog mid-run.
3
- *
4
- * The implementer agent calls this when it hits an ambiguity, needs
5
- * permission for a non-recoverable action, gets stuck, or wants to
6
- * verify its interpretation. The flow:
7
- *
8
- * 1. Tool writes a question file under
9
- * `.cairn/runs/active/<run_id>/questions/<question_id>.q.json`.
10
- * 2. The orchestrator's question-watcher (chokidar) picks it up,
11
- * fires `adapter.requestDialog()` with the active operator
12
- * pinged (so they see it on mobile push).
13
- * 3. Operator answers via Discord button (or free-form follow-up
14
- * if no `options` were provided).
15
- * 4. The orchestrator writes the answer to
16
- * `.cairn/runs/active/<run_id>/questions/<question_id>.a.json`.
17
- * 5. This tool polls for the answer file and returns its contents to
18
- * the agent.
19
- *
20
- * The agent run continues with the operator's answer in context. If
21
- * `timeout_ms` elapses before the operator answers, the tool returns
22
- * `{ timed_out: true }` and the agent decides what to do (default:
23
- * abort with a remediation note).
24
- */
25
- import type { ToolDef } from "./types.js";
26
- interface Input {
27
- run_id: string;
28
- question: string;
29
- options?: string[];
30
- category?: "ambiguity" | "permission" | "stuck" | "verify";
31
- timeout_ms?: number;
32
- }
33
- export declare const askOperatorTool: ToolDef<Input>;
34
- export {};
@@ -1,97 +0,0 @@
1
- /**
2
- * cairn_ask_operator — agent-initiated operator dialog mid-run.
3
- *
4
- * The implementer agent calls this when it hits an ambiguity, needs
5
- * permission for a non-recoverable action, gets stuck, or wants to
6
- * verify its interpretation. The flow:
7
- *
8
- * 1. Tool writes a question file under
9
- * `.cairn/runs/active/<run_id>/questions/<question_id>.q.json`.
10
- * 2. The orchestrator's question-watcher (chokidar) picks it up,
11
- * fires `adapter.requestDialog()` with the active operator
12
- * pinged (so they see it on mobile push).
13
- * 3. Operator answers via Discord button (or free-form follow-up
14
- * if no `options` were provided).
15
- * 4. The orchestrator writes the answer to
16
- * `.cairn/runs/active/<run_id>/questions/<question_id>.a.json`.
17
- * 5. This tool polls for the answer file and returns its contents to
18
- * the agent.
19
- *
20
- * The agent run continues with the operator's answer in context. If
21
- * `timeout_ms` elapses before the operator answers, the tool returns
22
- * `{ timed_out: true }` and the agent decides what to do (default:
23
- * abort with a remediation note).
24
- */
25
- import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
26
- import { randomBytes } from "node:crypto";
27
- import { join } from "node:path";
28
- import { requireBootstrap } from "../bootstrap-guard.js";
29
- import { mcpError } from "../errors.js";
30
- import { askOperatorInput } from "../schemas.js";
31
- const POLL_INTERVAL_MS = 500;
32
- const DEFAULT_TIMEOUT_MS = 10 * 60_000;
33
- async function handler(ctx, input) {
34
- const block = requireBootstrap(ctx.repoRoot);
35
- if (block !== null)
36
- return block;
37
- const runDir = join(ctx.repoRoot, ".cairn", "runs", "active", input.run_id);
38
- if (!existsSync(runDir)) {
39
- return mcpError("RUN_NOT_FOUND", `No active run dir at ${runDir}. ask_operator must be called from within an in-flight run.`);
40
- }
41
- const questionsDir = join(runDir, "questions");
42
- mkdirSync(questionsDir, { recursive: true });
43
- const questionId = `Q-${Date.now().toString(36)}-${randomBytes(2).toString("hex")}`;
44
- const qPath = join(questionsDir, `${questionId}.q.json`);
45
- const aPath = join(questionsDir, `${questionId}.a.json`);
46
- const qPayload = {
47
- id: questionId,
48
- run_id: input.run_id,
49
- asked_at: new Date().toISOString(),
50
- question: input.question,
51
- ...(input.options !== undefined && input.options.length > 0
52
- ? { options: input.options }
53
- : {}),
54
- ...(input.category !== undefined ? { category: input.category } : {}),
55
- timeout_ms: input.timeout_ms ?? DEFAULT_TIMEOUT_MS,
56
- };
57
- writeFileSync(qPath, JSON.stringify(qPayload, null, 2), "utf8");
58
- // Poll for the answer file. The orchestrator's question-watcher
59
- // observes the question, fires the dialog, writes the answer.
60
- const deadline = Date.now() + (input.timeout_ms ?? DEFAULT_TIMEOUT_MS);
61
- while (Date.now() < deadline) {
62
- if (existsSync(aPath)) {
63
- try {
64
- const raw = readFileSync(aPath, "utf8");
65
- const answer = JSON.parse(raw);
66
- return {
67
- ok: true,
68
- question_id: questionId,
69
- answer: answer.answer,
70
- ...(answer.choice_id !== undefined ? { choice_id: answer.choice_id } : {}),
71
- ...(answer.free_text === true ? { free_text: true } : {}),
72
- ...(answer.timed_out === true ? { timed_out: true } : {}),
73
- };
74
- }
75
- catch (err) {
76
- return mcpError("VALIDATION_FAILED", `Failed to parse answer file ${aPath}: ${String(err)}`);
77
- }
78
- }
79
- await sleep(POLL_INTERVAL_MS);
80
- }
81
- return {
82
- ok: true,
83
- question_id: questionId,
84
- answer: "",
85
- timed_out: true,
86
- };
87
- }
88
- function sleep(ms) {
89
- return new Promise((r) => setTimeout(r, ms));
90
- }
91
- export const askOperatorTool = {
92
- name: "cairn_ask_operator",
93
- description: "Stop and ask the operator a question. Use when the spec is genuinely ambiguous, you need permission for a non-recoverable action, you're stuck, or you want the operator to verify your interpretation. Provide 2-4 short option strings if the answer fits a closed set; omit `options` to invite a free-form reply. The tool blocks until the operator answers or `timeout_ms` (default 10 minutes) elapses.",
94
- inputSchema: askOperatorInput,
95
- handler,
96
- };
97
- //# sourceMappingURL=ask-operator.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ask-operator.js","sourceRoot":"","sources":["../../../src/mcp/tools/ask-operator.ts"],"names":[],"mappings":"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"}
@@ -1,12 +0,0 @@
1
- import type { ToolDef } from "./types.js";
2
- interface Input {
3
- title: string;
4
- body: string;
5
- intent: "run_pilot" | "review_module" | "fix_issue" | "eval" | "staleness_scan" | "unknown";
6
- target_path_globs?: string[];
7
- priority?: number;
8
- parent_task_id?: string;
9
- source?: string;
10
- }
11
- export declare const dropTaskTool: ToolDef<Input>;
12
- export {};