@isaacriehm/cairn-core 0.2.0 → 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 (336) 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 +3 -11
  220. package/dist/session-start/build.js +55 -34
  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/dist/context/checkpoint.d.ts +0 -11
  255. package/dist/context/checkpoint.js +0 -30
  256. package/dist/context/checkpoint.js.map +0 -1
  257. package/dist/decision-capture/capture.d.ts +0 -57
  258. package/dist/decision-capture/capture.js +0 -186
  259. package/dist/decision-capture/capture.js.map +0 -1
  260. package/dist/decision-capture/extractor.d.ts +0 -20
  261. package/dist/decision-capture/extractor.js +0 -103
  262. package/dist/decision-capture/extractor.js.map +0 -1
  263. package/dist/decision-capture/prompt.d.ts +0 -15
  264. package/dist/decision-capture/prompt.js +0 -68
  265. package/dist/decision-capture/prompt.js.map +0 -1
  266. package/dist/decision-capture/refinement-prompt.d.ts +0 -25
  267. package/dist/decision-capture/refinement-prompt.js +0 -146
  268. package/dist/decision-capture/refinement-prompt.js.map +0 -1
  269. package/dist/decision-capture/refinement-schema.d.ts +0 -52
  270. package/dist/decision-capture/refinement-schema.js +0 -61
  271. package/dist/decision-capture/refinement-schema.js.map +0 -1
  272. package/dist/decision-capture/refinement.d.ts +0 -60
  273. package/dist/decision-capture/refinement.js +0 -439
  274. package/dist/decision-capture/refinement.js.map +0 -1
  275. package/dist/decision-capture/schema.d.ts +0 -70
  276. package/dist/decision-capture/schema.js +0 -71
  277. package/dist/decision-capture/schema.js.map +0 -1
  278. package/dist/decision-capture/types.d.ts +0 -201
  279. package/dist/decision-capture/types.js +0 -20
  280. package/dist/decision-capture/types.js.map +0 -1
  281. package/dist/decision-capture/writer.d.ts +0 -90
  282. package/dist/decision-capture/writer.js +0 -267
  283. package/dist/decision-capture/writer.js.map +0 -1
  284. package/dist/frontend-types.d.ts +0 -243
  285. package/dist/frontend-types.js +0 -15
  286. package/dist/frontend-types.js.map +0 -1
  287. package/dist/hooks/index.d.ts +0 -14
  288. package/dist/hooks/index.js +0 -14
  289. package/dist/hooks/index.js.map +0 -1
  290. package/dist/inbox.d.ts +0 -17
  291. package/dist/inbox.js +0 -30
  292. package/dist/inbox.js.map +0 -1
  293. package/dist/mcp/tools/append-run-note.d.ts +0 -18
  294. package/dist/mcp/tools/append-run-note.js +0 -54
  295. package/dist/mcp/tools/append-run-note.js.map +0 -1
  296. package/dist/mcp/tools/append.d.ts +0 -8
  297. package/dist/mcp/tools/append.js +0 -37
  298. package/dist/mcp/tools/append.js.map +0 -1
  299. package/dist/mcp/tools/ask-operator.d.ts +0 -34
  300. package/dist/mcp/tools/ask-operator.js +0 -97
  301. package/dist/mcp/tools/ask-operator.js.map +0 -1
  302. package/dist/mcp/tools/drop-task.d.ts +0 -12
  303. package/dist/mcp/tools/drop-task.js +0 -68
  304. package/dist/mcp/tools/drop-task.js.map +0 -1
  305. package/dist/mcp/tools/record-run-event.d.ts +0 -10
  306. package/dist/mcp/tools/record-run-event.js +0 -32
  307. package/dist/mcp/tools/record-run-event.js.map +0 -1
  308. package/dist/prompt.d.ts +0 -19
  309. package/dist/prompt.js +0 -50
  310. package/dist/prompt.js.map +0 -1
  311. package/dist/tier0/classify.d.ts +0 -10
  312. package/dist/tier0/classify.js +0 -110
  313. package/dist/tier0/classify.js.map +0 -1
  314. package/dist/tier0/index.d.ts +0 -2
  315. package/dist/tier0/index.js +0 -2
  316. package/dist/tier0/index.js.map +0 -1
  317. package/dist/tier0/types.d.ts +0 -24
  318. package/dist/tier0/types.js +0 -9
  319. package/dist/tier0/types.js.map +0 -1
  320. package/dist/tightener/index.d.ts +0 -4
  321. package/dist/tightener/index.js +0 -4
  322. package/dist/tightener/index.js.map +0 -1
  323. package/dist/tightener/prompt.d.ts +0 -3
  324. package/dist/tightener/prompt.js +0 -67
  325. package/dist/tightener/prompt.js.map +0 -1
  326. package/dist/tightener/schema.d.ts +0 -68
  327. package/dist/tightener/schema.js +0 -44
  328. package/dist/tightener/schema.js.map +0 -1
  329. package/dist/tightener/tighten.d.ts +0 -2
  330. package/dist/tightener/tighten.js +0 -66
  331. package/dist/tightener/tighten.js.map +0 -1
  332. package/dist/tightener/types.d.ts +0 -74
  333. package/dist/tightener/types.js +0 -6
  334. package/dist/tightener/types.js.map +0 -1
  335. package/templates/.claude/settings.json +0 -57
  336. package/templates/.mcp.json +0 -8
@@ -1,267 +0,0 @@
1
- /**
2
- * Draft writer + confirm-side persistence.
3
- *
4
- * `writeDecisionDraft` materializes the extractor output into
5
- * `.cairn/ground/decisions/_inbox/<DEC-id>.draft.md`. Frontmatter
6
- * conforms to `DecisionFrontmatter` (status: "draft").
7
- *
8
- * `acceptDraft` moves the draft to its canonical path with status flipped
9
- * to "accepted" and triggers a ledger regenerate.
10
- *
11
- * `rejectDraft` removes the draft file entirely. The id remains burned —
12
- * `allocateDecisionId` always returns mark+1, so a rejected DEC-NNNN never
13
- * gets reissued (per monotonic-id principle, single source in decision-capture/id.ts).
14
- */
15
- import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
16
- import { dirname, join } from "node:path";
17
- import { parse as parseYaml, stringify as stringifyYaml } from "yaml";
18
- import { decisionsDir, decisionsLedgerPath } from "../ground/paths.js";
19
- import { writeDecisionsLedger } from "../ground/ledgers.js";
20
- import { parseFrontmatter } from "../ground/frontmatter.js";
21
- export function writeDecisionDraft(args) {
22
- const dir = decisionsDir(args.repoRoot);
23
- const inboxDir = join(dir, "_inbox");
24
- mkdirSync(inboxDir, { recursive: true });
25
- const draftFilename = `${args.id}.draft.md`;
26
- const canonicalFilename = `${args.id}.md`;
27
- const draftAbs = join(inboxDir, draftFilename);
28
- const canonicalAbs = join(dir, canonicalFilename);
29
- const draftRel = `.cairn/ground/decisions/_inbox/${draftFilename}`;
30
- const canonicalRel = `.cairn/ground/decisions/${canonicalFilename}`;
31
- const now = new Date().toISOString();
32
- // candidate_assertions are PROPOSALS — schema-loose. They live under
33
- // `candidate_assertions:` in the frontmatter (passthrough), NOT under
34
- // `assertions:` which DecisionFrontmatter validates strictly. A future
35
- // refinement step (Phase 14.x) lifts candidates into the strict
36
- // `assertions:` form once parameters are filled in. Until then the
37
- // ledger ignores them and Layer-D sensors don't enforce them.
38
- const candidateAssertions = args.output.candidate_assertions.map((a, idx) => {
39
- const id = a.id ?? `${args.id}-A${(idx + 1).toString().padStart(2, "0")}`;
40
- return {
41
- id,
42
- kind: a.kind,
43
- description: a.description,
44
- ...(a.parameters !== undefined ? { parameters: a.parameters } : {}),
45
- };
46
- });
47
- const frontmatter = {
48
- id: args.id,
49
- title: args.output.subject,
50
- type: "adr",
51
- status: "draft",
52
- audience: "dual",
53
- generated: now,
54
- "verified-at": now,
55
- decided_at: args.receivedAt,
56
- decided_by: args.authorId,
57
- ...(args.output.scope_globs.length > 0 ? { scope_globs: args.output.scope_globs } : {}),
58
- ...(args.output.supersedes ? { supersedes: args.output.supersedes } : {}),
59
- ...(candidateAssertions.length > 0
60
- ? { candidate_assertions: candidateAssertions }
61
- : {}),
62
- capture_source: args.source,
63
- capture_confidence: args.output.confidence_signal,
64
- };
65
- const yaml = stringifyYaml(frontmatter);
66
- const body = composeDraftBody(args);
67
- const fileContent = `---\n${yaml}---\n\n${body}\n`;
68
- writeFileSync(draftAbs, fileContent, "utf8");
69
- return {
70
- id: args.id,
71
- draft_path: draftRel,
72
- canonical_path: canonicalRel,
73
- output: args.output,
74
- raw_text: args.rawText,
75
- };
76
- }
77
- function composeDraftBody(args) {
78
- const lines = [];
79
- lines.push(`# ${args.id} — ${args.output.subject}`);
80
- lines.push("");
81
- lines.push("## Summary");
82
- lines.push(args.output.summary.trim());
83
- lines.push("");
84
- lines.push("## Original direction");
85
- lines.push("```");
86
- lines.push(args.rawText.trim());
87
- lines.push("```");
88
- lines.push("");
89
- if (args.output.scope_globs.length > 0) {
90
- lines.push("## Scope");
91
- for (const g of args.output.scope_globs)
92
- lines.push(`- \`${g}\``);
93
- lines.push("");
94
- }
95
- if (args.output.candidate_assertions.length > 0) {
96
- lines.push("## Candidate assertions");
97
- for (const a of args.output.candidate_assertions) {
98
- lines.push(`- **${a.kind}** — ${a.description}`);
99
- }
100
- lines.push("");
101
- }
102
- if (args.output.supersedes) {
103
- lines.push(`## Supersedes`);
104
- lines.push(`- ${args.output.supersedes}`);
105
- lines.push("");
106
- }
107
- lines.push(`_Confidence: ${args.output.confidence_signal}. This is a DRAFT — pending operator confirmation via Discord._`);
108
- return lines.join("\n");
109
- }
110
- /**
111
- * Move a draft to the canonical decisions/ dir, flip status:draft → accepted,
112
- * then regenerate the decisions ledger so accepted assertions become live.
113
- *
114
- * If a `supersedes` link exists, this also stamps `superseded_by` on the
115
- * referenced decision (when the file is present). Best-effort — a missing
116
- * referent doesn't block acceptance.
117
- */
118
- export function acceptDraft(args) {
119
- const draftAbs = join(args.repoRoot, args.draft.draft_path);
120
- const canonicalAbs = join(args.repoRoot, args.draft.canonical_path);
121
- const original = readFileSync(draftAbs, "utf8");
122
- const flipped = original.replace(/^status:\s*draft\s*$/m, "status: accepted");
123
- mkdirSync(dirname(canonicalAbs), { recursive: true });
124
- writeFileSync(canonicalAbs, flipped, "utf8");
125
- rmSync(draftAbs, { force: true });
126
- if (args.draft.output.supersedes) {
127
- stampSupersededBy({
128
- repoRoot: args.repoRoot,
129
- supersededId: args.draft.output.supersedes,
130
- supersedingId: args.draft.id,
131
- });
132
- }
133
- const ledger = writeDecisionsLedger({ repoRoot: args.repoRoot });
134
- return {
135
- acceptedPath: args.draft.canonical_path,
136
- ledgerSize: ledger.entries.length,
137
- ledgerPath: decisionsLedgerPath(args.repoRoot).replace(args.repoRoot + "/", ""),
138
- };
139
- }
140
- /**
141
- * Discard a draft. The DEC-id is NOT recycled — the allocator advances
142
- * past every existing DEC-NNNN.* file. Per the monotonic-id rule, even
143
- * rejected drafts burn their id, so we leave a tombstone at
144
- * `_inbox/<DEC-id>.rejected.md` rather than deleting outright. The
145
- * tombstone has `status: rejected` and is excluded from the ledger by
146
- * the existing `status === "accepted"` filter.
147
- */
148
- export function rejectDraft(args) {
149
- const draftAbs = join(args.repoRoot, args.draft.draft_path);
150
- if (!existsSync(draftAbs))
151
- return;
152
- const original = readFileSync(draftAbs, "utf8");
153
- const tombstone = original.replace(/^status:\s*draft\s*$/m, "status: rejected");
154
- const tombstoneRel = args.draft.draft_path.replace(/\.draft\.md$/, ".rejected.md");
155
- const tombstoneAbs = join(args.repoRoot, tombstoneRel);
156
- writeFileSync(tombstoneAbs, tombstone, "utf8");
157
- rmSync(draftAbs, { force: true });
158
- }
159
- function stampSupersededBy(args) {
160
- const target = join(decisionsDir(args.repoRoot), `${args.supersededId}.md`);
161
- if (!existsSync(target))
162
- return;
163
- const original = readFileSync(target, "utf8");
164
- // Inject `superseded_by:` into the frontmatter block if not already present.
165
- if (/^superseded_by:/m.test(original))
166
- return;
167
- const fenceEnd = original.indexOf("\n---", 3);
168
- if (fenceEnd === -1)
169
- return;
170
- const fenceText = original.slice(0, fenceEnd);
171
- const restText = original.slice(fenceEnd);
172
- const updated = `${fenceText}\nsuperseded_by: ${args.supersedingId}${restText}`;
173
- writeFileSync(target, updated, "utf8");
174
- }
175
- /**
176
- * Apply per-candidate verdicts to an accepted decision file.
177
- *
178
- * For each verdict:
179
- * - status="lift" → strict_assertion (with id/kind injected) lands in
180
- * frontmatter `assertions:`
181
- * - status="demote" → a `{kind: human_review_hint, description}` assertion
182
- * lands in `assertions:` (always soft, always zod-valid)
183
- * - status="skip" → original candidate stays under `candidate_assertions:`
184
- *
185
- * Then regenerates the decisions ledger so the new strict assertions are
186
- * visible to Layer-D sensors on the next run.
187
- */
188
- export function liftCandidatesToAssertions(args) {
189
- const decisionRel = `.cairn/ground/decisions/${args.decisionId}.md`;
190
- const decisionAbs = join(args.repoRoot, decisionRel);
191
- if (!existsSync(decisionAbs)) {
192
- throw new Error(`liftCandidatesToAssertions: decision file missing at ${decisionRel}`);
193
- }
194
- const original = readFileSync(decisionAbs, "utf8");
195
- const parsed = parseFrontmatter(original);
196
- const fmRaw = parsed.raw.length > 0 ? parseYaml(parsed.raw) : {};
197
- const existingAssertions = Array.isArray(fmRaw["assertions"])
198
- ? fmRaw["assertions"].slice()
199
- : [];
200
- const existingCandidates = Array.isArray(fmRaw["candidate_assertions"])
201
- ? fmRaw["candidate_assertions"].slice()
202
- : [];
203
- let liftedCount = 0;
204
- let demotedCount = 0;
205
- let skippedCount = 0;
206
- const newAssertions = [...existingAssertions];
207
- const liftedIds = new Set();
208
- const demotedIds = new Set();
209
- const skippedIds = new Set();
210
- for (const v of args.verdicts) {
211
- if (v.status === "lift" && v.strict_assertion !== undefined) {
212
- newAssertions.push({
213
- id: v.candidate_id,
214
- kind: v.candidate_kind,
215
- ...v.strict_assertion,
216
- });
217
- liftedIds.add(v.candidate_id);
218
- liftedCount++;
219
- continue;
220
- }
221
- if (v.status === "demote") {
222
- newAssertions.push({
223
- id: v.candidate_id,
224
- kind: "human_review_hint",
225
- description: v.candidate_description,
226
- });
227
- demotedIds.add(v.candidate_id);
228
- demotedCount++;
229
- continue;
230
- }
231
- skippedIds.add(v.candidate_id);
232
- skippedCount++;
233
- }
234
- const remainingCandidates = existingCandidates.filter((c) => {
235
- const id = typeof c["id"] === "string" ? c["id"] : "";
236
- return !liftedIds.has(id) && !demotedIds.has(id);
237
- });
238
- // Build the new frontmatter object preserving every existing field, just
239
- // updating assertions: + candidate_assertions: + verified-at.
240
- const newFm = { ...fmRaw };
241
- if (newAssertions.length > 0) {
242
- newFm["assertions"] = newAssertions;
243
- }
244
- else {
245
- delete newFm["assertions"];
246
- }
247
- if (remainingCandidates.length > 0) {
248
- newFm["candidate_assertions"] = remainingCandidates;
249
- }
250
- else {
251
- delete newFm["candidate_assertions"];
252
- }
253
- newFm["verified-at"] = new Date().toISOString();
254
- const newYaml = stringifyYaml(newFm);
255
- const newContent = `---\n${newYaml}---\n${parsed.body.startsWith("\n") ? "" : "\n"}${parsed.body}`;
256
- writeFileSync(decisionAbs, newContent, "utf8");
257
- const ledger = writeDecisionsLedger({ repoRoot: args.repoRoot });
258
- return {
259
- decision_id: args.decisionId,
260
- decision_path: decisionRel,
261
- lifted_count: liftedCount,
262
- demoted_count: demotedCount,
263
- skipped_count: skippedCount,
264
- ledger_size: ledger.entries.length,
265
- };
266
- }
267
- //# sourceMappingURL=writer.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"writer.js","sourceRoot":"","sources":["../../src/decision-capture/writer.ts"],"names":[],"mappings":"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"}
@@ -1,243 +0,0 @@
1
- /**
2
- * Frontend adapter contract per `docs/WORKFLOW_GUIDE.md` §0.1.
3
- *
4
- * Cairn's MCP server + ground layer are frontend-agnostic. The operator
5
- * console is a swappable adapter that consumes a uniform task/run/UAT
6
- * 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
- * Cairn's MCP server + ground layer are frontend-agnostic. The operator
5
- * console is a swappable adapter that consumes a uniform task/run/UAT
6
- * 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,14 +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
- export { clearDeferState, deferStatePath, isDeferActive, readDeferState, writeDeferState, } from "./defer.js";
14
- export type { DeferKind, DeferState } from "./defer.js";
@@ -1,14 +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
- export { clearDeferState, deferStatePath, isDeferActive, readDeferState, writeDeferState, } from "./defer.js";
14
- //# 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;AACzC,OAAO,EACL,eAAe,EACf,cAAc,EACd,aAAa,EACb,cAAc,EACd,eAAe,GAChB,MAAM,YAAY,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 {};