@isaacriehm/cairn-core 0.2.0 → 0.3.1

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 (337) 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 +2 -3
  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 +1 -1
  23. package/dist/doctor/index.js +1 -1
  24. package/dist/events/index.d.ts +1 -1
  25. package/dist/events/index.js +1 -1
  26. package/dist/events/writer.d.ts +1 -1
  27. package/dist/events/writer.js +1 -1
  28. package/dist/gc/canary.d.ts +13 -23
  29. package/dist/gc/canary.js +36 -92
  30. package/dist/gc/canary.js.map +1 -1
  31. package/dist/gc/citation-integrity.d.ts +6 -6
  32. package/dist/gc/citation-integrity.js +64 -20
  33. package/dist/gc/citation-integrity.js.map +1 -1
  34. package/dist/gc/frontmatter.js +1 -1
  35. package/dist/gc/generator-drift.js +1 -1
  36. package/dist/gc/generator-drift.js.map +1 -1
  37. package/dist/gc/index.d.ts +2 -2
  38. package/dist/gc/index.js +1 -1
  39. package/dist/gc/index.js.map +1 -1
  40. package/dist/gc/quality-update.js +1 -1
  41. package/dist/gc/quality-update.js.map +1 -1
  42. package/dist/gc/types.d.ts +1 -30
  43. package/dist/ground/index.d.ts +2 -2
  44. package/dist/ground/index.js +1 -1
  45. package/dist/ground/index.js.map +1 -1
  46. package/dist/ground/ledgers.d.ts +0 -4
  47. package/dist/ground/ledgers.js +10 -8
  48. package/dist/ground/ledgers.js.map +1 -1
  49. package/dist/ground/manifest.js +0 -2
  50. package/dist/ground/manifest.js.map +1 -1
  51. package/dist/ground/quality-grades.js +3 -1
  52. package/dist/ground/quality-grades.js.map +1 -1
  53. package/dist/ground/schemas.d.ts +2 -7
  54. package/dist/ground/schemas.js +7 -2
  55. package/dist/ground/schemas.js.map +1 -1
  56. package/dist/ground/scope-index.d.ts +59 -12
  57. package/dist/ground/scope-index.js +212 -43
  58. package/dist/ground/scope-index.js.map +1 -1
  59. package/dist/hooks/bypass-detection.js +4 -2
  60. package/dist/hooks/bypass-detection.js.map +1 -1
  61. package/dist/hooks/post-tool-use/citation-scanner.d.ts +7 -5
  62. package/dist/hooks/post-tool-use/citation-scanner.js +15 -9
  63. package/dist/hooks/post-tool-use/citation-scanner.js.map +1 -1
  64. package/dist/hooks/post-tool-use/copy-scanner.js +1 -1
  65. package/dist/hooks/post-tool-use/copy-scanner.js.map +1 -1
  66. package/dist/hooks/post-tool-use/ledger-cache.d.ts +8 -0
  67. package/dist/hooks/post-tool-use/ledger-cache.js +53 -0
  68. package/dist/hooks/post-tool-use/ledger-cache.js.map +1 -1
  69. package/dist/hooks/post-tool-use/legend-builder.d.ts +3 -3
  70. package/dist/hooks/post-tool-use/legend-builder.js +30 -8
  71. package/dist/hooks/post-tool-use/legend-builder.js.map +1 -1
  72. package/dist/hooks/post-tool-use/read-enricher.d.ts +1 -1
  73. package/dist/hooks/post-tool-use/read-enricher.js +68 -21
  74. package/dist/hooks/post-tool-use/read-enricher.js.map +1 -1
  75. package/dist/hooks/post-tool-use/write-guardian.js +148 -18
  76. package/dist/hooks/post-tool-use/write-guardian.js.map +1 -1
  77. package/dist/hooks/runners/index.d.ts +1 -0
  78. package/dist/hooks/runners/index.js +1 -0
  79. package/dist/hooks/runners/index.js.map +1 -1
  80. package/dist/hooks/runners/payload.d.ts +1 -1
  81. package/dist/hooks/runners/payload.js +27 -12
  82. package/dist/hooks/runners/payload.js.map +1 -1
  83. package/dist/hooks/runners/session-start.js +212 -66
  84. package/dist/hooks/runners/session-start.js.map +1 -1
  85. package/dist/hooks/runners/stop.d.ts +9 -12
  86. package/dist/hooks/runners/stop.js +67 -36
  87. package/dist/hooks/runners/stop.js.map +1 -1
  88. package/dist/hooks/runners/user-prompt-submit.d.ts +15 -0
  89. package/dist/hooks/runners/user-prompt-submit.js +149 -0
  90. package/dist/hooks/runners/user-prompt-submit.js.map +1 -0
  91. package/dist/hooks/user-prompt-submit.d.ts +7 -0
  92. package/dist/hooks/user-prompt-submit.js +12 -0
  93. package/dist/hooks/user-prompt-submit.js.map +1 -0
  94. package/dist/index.d.ts +1 -6
  95. package/dist/index.js +1 -5
  96. package/dist/index.js.map +1 -1
  97. package/dist/init/baseline-audit.d.ts +5 -1
  98. package/dist/init/baseline-audit.js +25 -2
  99. package/dist/init/baseline-audit.js.map +1 -1
  100. package/dist/init/glob-inference.d.ts +16 -0
  101. package/dist/init/glob-inference.js +108 -0
  102. package/dist/init/glob-inference.js.map +1 -0
  103. package/dist/init/index.d.ts +2 -0
  104. package/dist/init/index.js +1 -0
  105. package/dist/init/index.js.map +1 -1
  106. package/dist/init/ingest-docs.d.ts +1 -1
  107. package/dist/init/ingest-docs.js +19 -6
  108. package/dist/init/ingest-docs.js.map +1 -1
  109. package/dist/init/init.js +12 -7
  110. package/dist/init/init.js.map +1 -1
  111. package/dist/init/mapper-merge.d.ts +8 -2
  112. package/dist/init/mapper-merge.js +50 -32
  113. package/dist/init/mapper-merge.js.map +1 -1
  114. package/dist/init/mapper-parallel.d.ts +2 -3
  115. package/dist/init/mapper-parallel.js +9 -38
  116. package/dist/init/mapper-parallel.js.map +1 -1
  117. package/dist/init/mapper-prompts.js +1 -1
  118. package/dist/init/mapper-prompts.js.map +1 -1
  119. package/dist/init/mapper.d.ts +6 -127
  120. package/dist/init/mapper.js +30 -7
  121. package/dist/init/mapper.js.map +1 -1
  122. package/dist/init/module-slicer.d.ts +1 -1
  123. package/dist/init/module-slicer.js +1 -1
  124. package/dist/init/multi-dev/install.d.ts +5 -11
  125. package/dist/init/multi-dev/install.js +4 -6
  126. package/dist/init/multi-dev/install.js.map +1 -1
  127. package/dist/init/overlay.d.ts +2 -2
  128. package/dist/init/overlay.js +1 -1
  129. package/dist/init/overlay.js.map +1 -1
  130. package/dist/init/phases/10-strip.js +1 -2
  131. package/dist/init/phases/10-strip.js.map +1 -1
  132. package/dist/init/phases/12-multidev.d.ts +1 -6
  133. package/dist/init/phases/12-multidev.js +1 -6
  134. package/dist/init/phases/12-multidev.js.map +1 -1
  135. package/dist/init/phases/3b-seed.d.ts +1 -10
  136. package/dist/init/phases/3b-seed.js +1 -10
  137. package/dist/init/phases/3b-seed.js.map +1 -1
  138. package/dist/init/phases/4-pilot.js +53 -15
  139. package/dist/init/phases/4-pilot.js.map +1 -1
  140. package/dist/init/phases/5-brand.js +10 -10
  141. package/dist/init/phases/5-brand.js.map +1 -1
  142. package/dist/init/prompts.d.ts +6 -8
  143. package/dist/init/prompts.js +3 -6
  144. package/dist/init/prompts.js.map +1 -1
  145. package/dist/init/rules-merge/ingest.js +1 -1
  146. package/dist/init/source-comments/classify.d.ts +1 -41
  147. package/dist/init/source-comments/classify.js +68 -37
  148. package/dist/init/source-comments/classify.js.map +1 -1
  149. package/dist/init/source-comments/index.d.ts +2 -2
  150. package/dist/init/source-comments/index.js +2 -2
  151. package/dist/init/source-comments/index.js.map +1 -1
  152. package/dist/init/source-comments/ingest.d.ts +38 -2
  153. package/dist/init/source-comments/ingest.js +237 -4
  154. package/dist/init/source-comments/ingest.js.map +1 -1
  155. package/dist/init/source-comments/strip-replace.d.ts +10 -19
  156. package/dist/init/source-comments/strip-replace.js +26 -2
  157. package/dist/init/source-comments/strip-replace.js.map +1 -1
  158. package/dist/init/source-comments/walker.d.ts +9 -2
  159. package/dist/init/source-comments/walker.js +38 -19
  160. package/dist/init/source-comments/walker.js.map +1 -1
  161. package/dist/init/submodules.d.ts +3 -2
  162. package/dist/init/types.d.ts +3 -5
  163. package/dist/init/types.js +3 -5
  164. package/dist/init/types.js.map +1 -1
  165. package/dist/init/visual.d.ts +4 -9
  166. package/dist/init/visual.js +1 -16
  167. package/dist/init/visual.js.map +1 -1
  168. package/dist/logger.d.ts +0 -1
  169. package/dist/logger.js +0 -1
  170. package/dist/logger.js.map +1 -1
  171. package/dist/mcp/context.d.ts +2 -3
  172. package/dist/mcp/context.js.map +1 -1
  173. package/dist/mcp/errors.d.ts +1 -1
  174. package/dist/mcp/errors.js.map +1 -1
  175. package/dist/mcp/history/prompt.d.ts +2 -1
  176. package/dist/mcp/history/walker.js +1 -1
  177. package/dist/mcp/history/walker.js.map +1 -1
  178. package/dist/mcp/path-allowlist.d.ts +0 -6
  179. package/dist/mcp/path-allowlist.js +0 -10
  180. package/dist/mcp/path-allowlist.js.map +1 -1
  181. package/dist/mcp/schemas.d.ts +15 -72
  182. package/dist/mcp/schemas.js +21 -70
  183. package/dist/mcp/schemas.js.map +1 -1
  184. package/dist/mcp/serve.d.ts +1 -1
  185. package/dist/mcp/serve.js +2 -5
  186. package/dist/mcp/serve.js.map +1 -1
  187. package/dist/mcp/server.js +10 -4
  188. package/dist/mcp/server.js.map +1 -1
  189. package/dist/mcp/telemetry.d.ts +8 -1
  190. package/dist/mcp/telemetry.js +16 -0
  191. package/dist/mcp/telemetry.js.map +1 -1
  192. package/dist/mcp/tools/decision-get.js +37 -29
  193. package/dist/mcp/tools/decision-get.js.map +1 -1
  194. package/dist/mcp/tools/decisions-in-scope.js +22 -3
  195. package/dist/mcp/tools/decisions-in-scope.js.map +1 -1
  196. package/dist/mcp/tools/index.js +2 -2
  197. package/dist/mcp/tools/index.js.map +1 -1
  198. package/dist/mcp/tools/invariant-get.js +1 -1
  199. package/dist/mcp/tools/invariant-get.js.map +1 -1
  200. package/dist/mcp/tools/invariants-in-scope.js +26 -7
  201. package/dist/mcp/tools/invariants-in-scope.js.map +1 -1
  202. package/dist/mcp/tools/query-history.js +3 -3
  203. package/dist/mcp/tools/query-history.js.map +1 -1
  204. package/dist/mcp/tools/resolve-attention.d.ts +3 -3
  205. package/dist/mcp/tools/resolve-attention.js +40 -28
  206. package/dist/mcp/tools/resolve-attention.js.map +1 -1
  207. package/dist/mcp/tools/search.js +3 -4
  208. package/dist/mcp/tools/search.js.map +1 -1
  209. package/dist/mcp/tools/task-create.d.ts +15 -0
  210. package/dist/mcp/tools/task-create.js +96 -0
  211. package/dist/mcp/tools/task-create.js.map +1 -0
  212. package/dist/mcp/tools/timeline.js +3 -7
  213. package/dist/mcp/tools/timeline.js.map +1 -1
  214. package/dist/profiles/types.d.ts +1 -1
  215. package/dist/profiles/types.js +1 -1
  216. package/dist/session/id.d.ts +1 -3
  217. package/dist/session/id.js +1 -1
  218. package/dist/session/id.js.map +1 -1
  219. package/dist/session-start/build.d.ts +12 -14
  220. package/dist/session-start/build.js +68 -38
  221. package/dist/session-start/build.js.map +1 -1
  222. package/dist/session-start/index.d.ts +2 -2
  223. package/dist/session-start/index.js +2 -2
  224. package/dist/session-start/index.js.map +1 -1
  225. package/dist/session-start/templates.d.ts +20 -4
  226. package/dist/session-start/templates.js +45 -35
  227. package/dist/session-start/templates.js.map +1 -1
  228. package/dist/status-line/format.d.ts +19 -11
  229. package/dist/status-line/format.js +44 -36
  230. package/dist/status-line/format.js.map +1 -1
  231. package/dist/status-line/index.d.ts +3 -1
  232. package/dist/status-line/index.js +1 -1
  233. package/dist/status-line/index.js.map +1 -1
  234. package/dist/status-line/reader.d.ts +9 -6
  235. package/dist/status-line/reader.js +50 -15
  236. package/dist/status-line/reader.js.map +1 -1
  237. package/dist/status-line/writer.d.ts +5 -0
  238. package/dist/status-line/writer.js +9 -0
  239. package/dist/status-line/writer.js.map +1 -1
  240. package/dist/trace/index.d.ts +44 -0
  241. package/dist/trace/index.js +51 -0
  242. package/dist/trace/index.js.map +1 -0
  243. package/package.json +2 -3
  244. package/templates/.archive/README.md +3 -3
  245. package/templates/.cairn/config/sensors.yaml +16 -19
  246. package/templates/.cairn/config/stub-patterns.yaml +4 -4
  247. package/templates/.cairn/config/trust-policy.yaml +3 -35
  248. package/templates/.cairn/config/workflow.md +13 -194
  249. package/templates/.cairn/git-hooks/commit-msg +1 -1
  250. package/templates/.cairn/ground/canonical-map/topics.yaml +3 -26
  251. package/templates/.cairn/ground/capabilities/snippets.yaml +0 -1
  252. package/templates/.cairn/ground/manifest.yaml +5 -8
  253. package/templates/.cairn/ground/product/personas.yaml +0 -1
  254. package/templates/.github/workflows/cairn-check.yml +3 -5
  255. package/dist/context/checkpoint.d.ts +0 -11
  256. package/dist/context/checkpoint.js +0 -30
  257. package/dist/context/checkpoint.js.map +0 -1
  258. package/dist/decision-capture/capture.d.ts +0 -57
  259. package/dist/decision-capture/capture.js +0 -186
  260. package/dist/decision-capture/capture.js.map +0 -1
  261. package/dist/decision-capture/extractor.d.ts +0 -20
  262. package/dist/decision-capture/extractor.js +0 -103
  263. package/dist/decision-capture/extractor.js.map +0 -1
  264. package/dist/decision-capture/prompt.d.ts +0 -15
  265. package/dist/decision-capture/prompt.js +0 -68
  266. package/dist/decision-capture/prompt.js.map +0 -1
  267. package/dist/decision-capture/refinement-prompt.d.ts +0 -25
  268. package/dist/decision-capture/refinement-prompt.js +0 -146
  269. package/dist/decision-capture/refinement-prompt.js.map +0 -1
  270. package/dist/decision-capture/refinement-schema.d.ts +0 -52
  271. package/dist/decision-capture/refinement-schema.js +0 -61
  272. package/dist/decision-capture/refinement-schema.js.map +0 -1
  273. package/dist/decision-capture/refinement.d.ts +0 -60
  274. package/dist/decision-capture/refinement.js +0 -439
  275. package/dist/decision-capture/refinement.js.map +0 -1
  276. package/dist/decision-capture/schema.d.ts +0 -70
  277. package/dist/decision-capture/schema.js +0 -71
  278. package/dist/decision-capture/schema.js.map +0 -1
  279. package/dist/decision-capture/types.d.ts +0 -201
  280. package/dist/decision-capture/types.js +0 -20
  281. package/dist/decision-capture/types.js.map +0 -1
  282. package/dist/decision-capture/writer.d.ts +0 -90
  283. package/dist/decision-capture/writer.js +0 -267
  284. package/dist/decision-capture/writer.js.map +0 -1
  285. package/dist/frontend-types.d.ts +0 -243
  286. package/dist/frontend-types.js +0 -15
  287. package/dist/frontend-types.js.map +0 -1
  288. package/dist/hooks/index.d.ts +0 -14
  289. package/dist/hooks/index.js +0 -14
  290. package/dist/hooks/index.js.map +0 -1
  291. package/dist/inbox.d.ts +0 -17
  292. package/dist/inbox.js +0 -30
  293. package/dist/inbox.js.map +0 -1
  294. package/dist/mcp/tools/append-run-note.d.ts +0 -18
  295. package/dist/mcp/tools/append-run-note.js +0 -54
  296. package/dist/mcp/tools/append-run-note.js.map +0 -1
  297. package/dist/mcp/tools/append.d.ts +0 -8
  298. package/dist/mcp/tools/append.js +0 -37
  299. package/dist/mcp/tools/append.js.map +0 -1
  300. package/dist/mcp/tools/ask-operator.d.ts +0 -34
  301. package/dist/mcp/tools/ask-operator.js +0 -97
  302. package/dist/mcp/tools/ask-operator.js.map +0 -1
  303. package/dist/mcp/tools/drop-task.d.ts +0 -12
  304. package/dist/mcp/tools/drop-task.js +0 -68
  305. package/dist/mcp/tools/drop-task.js.map +0 -1
  306. package/dist/mcp/tools/record-run-event.d.ts +0 -10
  307. package/dist/mcp/tools/record-run-event.js +0 -32
  308. package/dist/mcp/tools/record-run-event.js.map +0 -1
  309. package/dist/prompt.d.ts +0 -19
  310. package/dist/prompt.js +0 -50
  311. package/dist/prompt.js.map +0 -1
  312. package/dist/tier0/classify.d.ts +0 -10
  313. package/dist/tier0/classify.js +0 -110
  314. package/dist/tier0/classify.js.map +0 -1
  315. package/dist/tier0/index.d.ts +0 -2
  316. package/dist/tier0/index.js +0 -2
  317. package/dist/tier0/index.js.map +0 -1
  318. package/dist/tier0/types.d.ts +0 -24
  319. package/dist/tier0/types.js +0 -9
  320. package/dist/tier0/types.js.map +0 -1
  321. package/dist/tightener/index.d.ts +0 -4
  322. package/dist/tightener/index.js +0 -4
  323. package/dist/tightener/index.js.map +0 -1
  324. package/dist/tightener/prompt.d.ts +0 -3
  325. package/dist/tightener/prompt.js +0 -67
  326. package/dist/tightener/prompt.js.map +0 -1
  327. package/dist/tightener/schema.d.ts +0 -68
  328. package/dist/tightener/schema.js +0 -44
  329. package/dist/tightener/schema.js.map +0 -1
  330. package/dist/tightener/tighten.d.ts +0 -2
  331. package/dist/tightener/tighten.js +0 -66
  332. package/dist/tightener/tighten.js.map +0 -1
  333. package/dist/tightener/types.d.ts +0 -74
  334. package/dist/tightener/types.js +0 -6
  335. package/dist/tightener/types.js.map +0 -1
  336. package/templates/.claude/settings.json +0 -57
  337. package/templates/.mcp.json +0 -8
@@ -1,54 +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 { withWriteLock } from "../../lock.js";
14
- import { requireBootstrap } from "../bootstrap-guard.js";
15
- import { mcpError } from "../errors.js";
16
- import { isAppendAllowed, relPosix, safeJoin } from "../path-allowlist.js";
17
- import { appendRunNoteInput } from "../schemas.js";
18
- const RUN_ID_RE = /^[A-Za-z0-9_-]+$/;
19
- async function handler(ctx, input) {
20
- const block = requireBootstrap(ctx.repoRoot);
21
- if (block !== null)
22
- return block;
23
- if (!RUN_ID_RE.test(input.run_id) || input.run_id.length > 80) {
24
- return mcpError("VALIDATION_FAILED", `run_id must match path-safe pattern [A-Za-z0-9_-] (≤80 chars)`);
25
- }
26
- const rel = `.cairn/tasks/active/${input.run_id}/notes.md`;
27
- const abs = safeJoin(ctx.repoRoot, rel);
28
- if (typeof abs !== "string")
29
- return abs; // error envelope
30
- const relCanon = relPosix(ctx.repoRoot, abs);
31
- if (!isAppendAllowed(relCanon)) {
32
- return mcpError("PATH_NOT_ALLOWED", `Append-write is not allowed for "${relCanon}".`);
33
- }
34
- const taskDir = join(ctx.repoRoot, ".cairn", "tasks", "active", input.run_id);
35
- if (!existsSync(taskDir)) {
36
- return mcpError("RUN_NOT_FOUND", `No active task dir at .cairn/tasks/active/${input.run_id}/`);
37
- }
38
- const entry = `\n## ${new Date().toISOString()} [${input.phase}]\n${input.note}\n`;
39
- return withWriteLock(ctx.repoRoot, () => {
40
- appendFileSync(abs, entry, "utf8");
41
- return {
42
- ok: true,
43
- path: relCanon,
44
- bytes_written: Buffer.byteLength(entry, "utf8"),
45
- };
46
- });
47
- }
48
- export const appendRunNoteTool = {
49
- name: "cairn_append_run_note",
50
- 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).",
51
- inputSchema: appendRunNoteInput,
52
- handler,
53
- };
54
- //# 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;AACjC,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAEzD,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,MAAM,KAAK,GAAG,gBAAgB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC7C,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IAEjC,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,OAAO,aAAa,CAAC,GAAG,CAAC,QAAQ,EAAE,GAAG,EAAE;QACtC,cAAc,CAAC,GAAG,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;QACnC,OAAO;YACL,EAAE,EAAE,IAAI;YACR,IAAI,EAAE,QAAQ;YACd,aAAa,EAAE,MAAM,CAAC,UAAU,CAAC,KAAK,EAAE,MAAM,CAAC;SAChD,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,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 {};
@@ -1,68 +0,0 @@
1
- import { mkdirSync, writeFileSync } from "node:fs";
2
- import { join } from "node:path";
3
- import { stringify as stringifyYaml } from "yaml";
4
- import { writeInvalidationEvent } from "../../events/index.js";
5
- import { withWriteLock } from "../../lock.js";
6
- import { requireBootstrap } from "../bootstrap-guard.js";
7
- import { dropTaskInput } from "../schemas.js";
8
- async function handler(ctx, input) {
9
- const block = requireBootstrap(ctx.repoRoot);
10
- if (block !== null)
11
- return block;
12
- return withWriteLock(ctx.repoRoot, () => {
13
- const today = new Date().toISOString().slice(0, 10);
14
- const slug = input.title
15
- .toLowerCase()
16
- .replace(/[^a-z0-9]+/g, "-")
17
- .replace(/^-+|-+$/g, "")
18
- .slice(0, 60);
19
- // ms-suffix gives uniqueness when the same agent files multiple tasks per second.
20
- const id = `TSK-${today}-${slug || "task"}-${Date.now() % 100000}`;
21
- const dir = join(ctx.repoRoot, ".cairn", "tasks", "active", id);
22
- mkdirSync(dir, { recursive: true });
23
- const frontmatter = {
24
- id,
25
- type: "spec",
26
- status: "tightening",
27
- audience: "dual",
28
- generated: new Date().toISOString(),
29
- source: input.source ?? "agent_spawned",
30
- intent: input.intent,
31
- priority: input.priority ?? 5,
32
- ...(input.parent_task_id !== undefined ? { parent_task_id: input.parent_task_id } : {}),
33
- ...(input.target_path_globs !== undefined
34
- ? { target_path_globs: input.target_path_globs }
35
- : {}),
36
- trust_class: "code",
37
- };
38
- const spec = `---\n${stringifyYaml(frontmatter)}---\n\n# ${input.title}\n\n${input.body}\n`;
39
- writeFileSync(join(dir, "spec.md"), spec, "utf8");
40
- const status = {
41
- phase: "tightening",
42
- attempts: 0,
43
- last_event_at: new Date().toISOString(),
44
- queued_position: null,
45
- related_run_ids: [],
46
- };
47
- writeFileSync(join(dir, "status.yaml"), stringifyYaml(status), "utf8");
48
- try {
49
- writeInvalidationEvent(ctx.repoRoot, {
50
- kind: "task_created",
51
- refs: [{ kind: "task", id }],
52
- path: `.cairn/tasks/active/${id}/spec.md`,
53
- source: { session_id: ctx.sessionId ?? null, tool: "cairn_drop_task" },
54
- });
55
- }
56
- catch {
57
- // Event emission must never roll back the task spec write.
58
- }
59
- return { ok: true, id, path: `.cairn/tasks/active/${id}/spec.md` };
60
- });
61
- }
62
- export const dropTaskTool = {
63
- name: "cairn_drop_task",
64
- description: "Create a new active task — writes spec.md + status.yaml under .cairn/tasks/active/<id>/.",
65
- inputSchema: dropTaskInput,
66
- handler,
67
- };
68
- //# sourceMappingURL=drop-task.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"drop-task.js","sourceRoot":"","sources":["../../../src/mcp/tools/drop-task.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,SAAS,IAAI,aAAa,EAAE,MAAM,MAAM,CAAC;AAElD,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAa9C,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,OAAO,aAAa,CAAC,GAAG,CAAC,QAAQ,EAAE,GAAG,EAAE;QACtC,MAAM,KAAK,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACpD,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK;aACrB,WAAW,EAAE;aACb,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC;aAC3B,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC;aACvB,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAChB,kFAAkF;QAClF,MAAM,EAAE,GAAG,OAAO,KAAK,IAAI,IAAI,IAAI,MAAM,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,EAAE,CAAC;QACnE,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,CAAC,CAAC;QAChE,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAEpC,MAAM,WAAW,GAAG;YAClB,EAAE;YACF,IAAI,EAAE,MAAM;YACZ,MAAM,EAAE,YAAY;YACpB,QAAQ,EAAE,MAAM;YAChB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACnC,MAAM,EAAE,KAAK,CAAC,MAAM,IAAI,eAAe;YACvC,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,QAAQ,EAAE,KAAK,CAAC,QAAQ,IAAI,CAAC;YAC7B,GAAG,CAAC,KAAK,CAAC,cAAc,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,KAAK,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACvF,GAAG,CAAC,KAAK,CAAC,iBAAiB,KAAK,SAAS;gBACvC,CAAC,CAAC,EAAE,iBAAiB,EAAE,KAAK,CAAC,iBAAiB,EAAE;gBAChD,CAAC,CAAC,EAAE,CAAC;YACP,WAAW,EAAE,MAAM;SACpB,CAAC;QAEF,MAAM,IAAI,GAAG,QAAQ,aAAa,CAAC,WAAW,CAAC,YAAY,KAAK,CAAC,KAAK,OAAO,KAAK,CAAC,IAAI,IAAI,CAAC;QAC5F,aAAa,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;QAElD,MAAM,MAAM,GAAG;YACb,KAAK,EAAE,YAAY;YACnB,QAAQ,EAAE,CAAC;YACX,aAAa,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACvC,eAAe,EAAE,IAAI;YACrB,eAAe,EAAE,EAAE;SACpB,CAAC;QACF,aAAa,CAAC,IAAI,CAAC,GAAG,EAAE,aAAa,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC;QAEvE,IAAI,CAAC;YACH,sBAAsB,CAAC,GAAG,CAAC,QAAQ,EAAE;gBACnC,IAAI,EAAE,cAAc;gBACpB,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;gBAC5B,IAAI,EAAE,uBAAuB,EAAE,UAAU;gBACzC,MAAM,EAAE,EAAE,UAAU,EAAE,GAAG,CAAC,SAAS,IAAI,IAAI,EAAE,IAAI,EAAE,iBAAiB,EAAE;aACvE,CAAC,CAAC;QACL,CAAC;QAAC,MAAM,CAAC;YACP,2DAA2D;QAC7D,CAAC;QAED,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,uBAAuB,EAAE,UAAU,EAAE,CAAC;IACrE,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,MAAM,YAAY,GAAmB;IAC1C,IAAI,EAAE,iBAAiB;IACvB,WAAW,EACT,0FAA0F;IAC5F,WAAW,EAAE,aAAa;IAC1B,OAAO;CACR,CAAC"}
@@ -1,10 +0,0 @@
1
- import type { ToolDef } from "./types.js";
2
- interface Input {
3
- run_id: string;
4
- event: {
5
- kind: string;
6
- payload?: unknown;
7
- };
8
- }
9
- export declare const recordRunEventTool: ToolDef<Input>;
10
- export {};
@@ -1,32 +0,0 @@
1
- import { appendFileSync, existsSync, mkdirSync } from "node:fs";
2
- import { join } from "node:path";
3
- import { requireBootstrap } from "../bootstrap-guard.js";
4
- import { mcpError } from "../errors.js";
5
- import { recordRunEventInput } from "../schemas.js";
6
- async function handler(ctx, input) {
7
- const block = requireBootstrap(ctx.repoRoot);
8
- if (block !== null)
9
- return block;
10
- const runDir = join(ctx.repoRoot, ".cairn", "runs", "active", input.run_id);
11
- if (!existsSync(runDir)) {
12
- return mcpError("RUN_NOT_FOUND", `No active run dir at ${runDir}`);
13
- }
14
- const path = join(runDir, "events.jsonl");
15
- // Server-fills ts. Seq is omitted in this naive implementation; the orchestrator
16
- // re-numbers in the post-run pass when it materializes the canonical event log.
17
- const row = {
18
- ts: new Date().toISOString(),
19
- kind: input.event.kind,
20
- ...(input.event.payload !== undefined ? { payload: input.event.payload } : {}),
21
- };
22
- mkdirSync(runDir, { recursive: true });
23
- appendFileSync(path, `${JSON.stringify(row)}\n`, "utf8");
24
- return { ok: true, run_id: input.run_id, kind: input.event.kind };
25
- }
26
- export const recordRunEventTool = {
27
- name: "cairn_record_run_event",
28
- description: "Append a structured event to .cairn/runs/active/<run_id>/events.jsonl. Server fills `ts`; sequence is renumbered in post-run materialization.",
29
- inputSchema: recordRunEventInput,
30
- handler,
31
- };
32
- //# sourceMappingURL=record-run-event.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"record-run-event.js","sourceRoot":"","sources":["../../../src/mcp/tools/record-run-event.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAChE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAQpD,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,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAC5E,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;QACxB,OAAO,QAAQ,CAAC,eAAe,EAAE,wBAAwB,MAAM,EAAE,CAAC,CAAC;IACrE,CAAC;IACD,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAC1C,iFAAiF;IACjF,gFAAgF;IAChF,MAAM,GAAG,GAAG;QACV,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QAC5B,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,IAAI;QACtB,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC/E,CAAC;IACF,SAAS,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACvC,cAAc,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACzD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;AACpE,CAAC;AAED,MAAM,CAAC,MAAM,kBAAkB,GAAmB;IAChD,IAAI,EAAE,wBAAwB;IAC9B,WAAW,EACT,+IAA+I;IACjJ,WAAW,EAAE,mBAAmB;IAChC,OAAO;CACR,CAAC"}
package/dist/prompt.d.ts DELETED
@@ -1,19 +0,0 @@
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 DELETED
@@ -1,50 +0,0 @@
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
@@ -1 +0,0 @@
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"}
@@ -1,10 +0,0 @@
1
- import type { ClassificationResult, Tier0ClassifyOptions, Tier0RegexFallback } from "./types.js";
2
- export declare const REGEX_FALLBACK: Tier0RegexFallback;
3
- /**
4
- * Classify a free-text developer message into a tier0 intent. Calls the
5
- * Claude binary (Haiku tier) for nuanced reasoning; falls back to a regex
6
- * matcher when the binary is unreachable so smoke tests + scripted callers
7
- * stay green. The regex fallback is escape-only — production flows assume
8
- * the Claude binary is present (per docs/PLUGIN_ARCHITECTURE.md §16).
9
- */
10
- export declare function classifyTier0(text: string, opts?: Tier0ClassifyOptions): Promise<ClassificationResult>;
@@ -1,110 +0,0 @@
1
- import { ClaudeError, runClaude } from "../claude/index.js";
2
- import { logger } from "../logger.js";
3
- const log = logger("tier0.classify");
4
- const VALID_INTENTS = [
5
- "code_task",
6
- "review",
7
- "direction",
8
- "question",
9
- "halt",
10
- "status",
11
- "unknown",
12
- ];
13
- const SYSTEM_PROMPT = [
14
- "You classify a free-text developer message into a single intent for the cairn.",
15
- 'Respond ONLY with JSON: { "intent": <one of: code_task, review, direction, question, halt, status, unknown>, "confidence": <number between 0 and 1> }.',
16
- "Definitions:",
17
- "- code_task: operator wants code written or changed (fix, add, build, refactor, delete, migrate, wire, hook).",
18
- "- review: read-only audit/check of code or docs (no code change).",
19
- "- direction: a binding decision change. Phrases like 'scrap that', 'going forward', 'from now on', 'new direction'.",
20
- "- question: operator is asking, not directing.",
21
- "- halt: operator wants something stopped/cancelled.",
22
- "- status: operator wants current state of cairn or run.",
23
- "- unknown: none of the above match.",
24
- "Be honest with confidence; below 0.7 means it is genuinely ambiguous.",
25
- ].join("\n");
26
- const INTENT_SCHEMA = {
27
- type: "object",
28
- required: ["intent", "confidence"],
29
- additionalProperties: false,
30
- properties: {
31
- intent: {
32
- type: "string",
33
- enum: [
34
- "code_task",
35
- "review",
36
- "direction",
37
- "question",
38
- "halt",
39
- "status",
40
- "unknown",
41
- ],
42
- },
43
- confidence: { type: "number", minimum: 0, maximum: 1 },
44
- },
45
- };
46
- function regexFallbackDefault(text) {
47
- const rules = [
48
- { intent: "halt", pattern: /^\s*(halt|stop|cancel|kill)\b/i },
49
- { intent: "status", pattern: /^\s*(status|state|how['’]?s it going)\b/i },
50
- {
51
- intent: "direction",
52
- pattern: /^\s*(scrap that|actually|new direction|going forward|from now on)\b/i,
53
- },
54
- {
55
- intent: "code_task",
56
- pattern: /^\s*(fix|add|update|create|build|implement|refactor|delete|remove|migrate|wire|hook|land|rip out|rip)\b/i,
57
- },
58
- {
59
- intent: "review",
60
- pattern: /^\s*(review|audit|check|inspect|look at|smoke|sanity)\b/i,
61
- },
62
- {
63
- intent: "question",
64
- pattern: /^\s*(why|how|what|when|where|which|is|are|does|do|can|should)\b/i,
65
- },
66
- ];
67
- for (const r of rules) {
68
- if (r.pattern.test(text))
69
- return { intent: r.intent, confidence: 0.6 };
70
- }
71
- return { intent: "unknown", confidence: 0 };
72
- }
73
- export const REGEX_FALLBACK = regexFallbackDefault;
74
- /**
75
- * Classify a free-text developer message into a tier0 intent. Calls the
76
- * Claude binary (Haiku tier) for nuanced reasoning; falls back to a regex
77
- * matcher when the binary is unreachable so smoke tests + scripted callers
78
- * stay green. The regex fallback is escape-only — production flows assume
79
- * the Claude binary is present (per docs/PLUGIN_ARCHITECTURE.md §16).
80
- */
81
- export async function classifyTier0(text, opts = {}) {
82
- const fallback = opts.regexFallback ?? REGEX_FALLBACK;
83
- const timeoutMs = opts.timeoutMs ?? 30_000;
84
- try {
85
- const res = await runClaude({
86
- tier: "haiku",
87
- system: SYSTEM_PROMPT,
88
- prompt: `Message:\n${text}\n\nReturn the JSON now.`,
89
- jsonSchema: INTENT_SCHEMA,
90
- timeoutMs,
91
- });
92
- const parsed = (res.parsed ??
93
- JSON.parse(res.text));
94
- const intent = typeof parsed.intent === "string" &&
95
- VALID_INTENTS.includes(parsed.intent)
96
- ? parsed.intent
97
- : "unknown";
98
- const confidence = typeof parsed.confidence === "number" && Number.isFinite(parsed.confidence)
99
- ? Math.max(0, Math.min(1, parsed.confidence))
100
- : 0;
101
- return { intent, confidence, source: "claude" };
102
- }
103
- catch (err) {
104
- const reason = err instanceof ClaudeError ? err.kind : err instanceof Error ? err.message : String(err);
105
- log.warn({ reason }, "tier0 claude classify failed; falling back to regex");
106
- const r = fallback(text);
107
- return { intent: r.intent, confidence: r.confidence, source: "fallback" };
108
- }
109
- }
110
- //# sourceMappingURL=classify.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"classify.js","sourceRoot":"","sources":["../../src/tier0/classify.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export { classifyTier0, REGEX_FALLBACK } from "./classify.js";
2
- export type { ClassificationResult, Tier0ClassifyOptions, Tier0Intent, Tier0RegexFallback, } from "./types.js";
@@ -1,2 +0,0 @@
1
- export { classifyTier0, REGEX_FALLBACK } from "./classify.js";
2
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tier0/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC"}
@@ -1,24 +0,0 @@
1
- /**
2
- * Tier-0 classifier contract. Per docs/PLUGIN_ARCHITECTURE.md §14: Haiku
3
- * (escalating to Sonnet for complex prompts) via the Claude binary
4
- * subprocess. Falls back to a deterministic regex matcher if the Claude
5
- * binary is unavailable so smoke tests + scripted callers stay green.
6
- * Production flows assume the Claude binary is present.
7
- */
8
- export type Tier0Intent = "code_task" | "review" | "direction" | "question" | "halt" | "status" | "unknown";
9
- export interface ClassificationResult {
10
- intent: Tier0Intent;
11
- confidence: number;
12
- source: "claude" | "fallback";
13
- }
14
- export interface Tier0RegexFallback {
15
- (text: string): {
16
- intent: Tier0Intent;
17
- confidence: number;
18
- };
19
- }
20
- export interface Tier0ClassifyOptions {
21
- timeoutMs?: number;
22
- /** Used when the Claude binary is unreachable or returns malformed output. */
23
- regexFallback?: Tier0RegexFallback;
24
- }