@isaacriehm/cairn-core 0.7.0 → 0.7.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 (440) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/align-undo/undo.js +2 -2
  3. package/dist/align-undo/undo.js.map +1 -1
  4. package/dist/attention/bulk-accept.js +48 -40
  5. package/dist/attention/bulk-accept.js.map +1 -1
  6. package/dist/attention/dedup.js +23 -10
  7. package/dist/attention/dedup.js.map +1 -1
  8. package/dist/attention/restore.js +2 -2
  9. package/dist/attention/restore.js.map +1 -1
  10. package/dist/attention/scoring.js +1 -1
  11. package/dist/attention/scoring.js.map +1 -1
  12. package/dist/attention/serve/api.d.ts +1 -0
  13. package/dist/attention/serve/api.js +127 -80
  14. package/dist/attention/serve/api.js.map +1 -1
  15. package/dist/attention/serve/index.d.ts +1 -0
  16. package/dist/attention/serve/index.js +21 -7
  17. package/dist/attention/serve/index.js.map +1 -1
  18. package/dist/attention/source-strip.js +41 -46
  19. package/dist/attention/source-strip.js.map +1 -1
  20. package/dist/claude/cache.d.ts +10 -19
  21. package/dist/claude/cache.js +0 -0
  22. package/dist/claude/cache.js.map +1 -1
  23. package/dist/claude/runner.d.ts +4 -6
  24. package/dist/claude/runner.js +242 -203
  25. package/dist/claude/runner.js.map +1 -1
  26. package/dist/claude/types.d.ts +5 -5
  27. package/dist/context/handoff-builder.d.ts +28 -4
  28. package/dist/context/handoff-builder.js +75 -157
  29. package/dist/context/handoff-builder.js.map +1 -1
  30. package/dist/context/spec-delta.js +61 -9
  31. package/dist/context/spec-delta.js.map +1 -1
  32. package/dist/context/task-summary.js +5 -1
  33. package/dist/context/task-summary.js.map +1 -1
  34. package/dist/decision-capture/id.js +1 -1
  35. package/dist/decision-capture/id.js.map +1 -1
  36. package/dist/doctor/index.d.ts +9 -11
  37. package/dist/doctor/index.js +118 -175
  38. package/dist/doctor/index.js.map +1 -1
  39. package/dist/drain/drain.d.ts +1 -1
  40. package/dist/drain/drain.js +16 -16
  41. package/dist/drain/drain.js.map +1 -1
  42. package/dist/drain/index.d.ts +1 -1
  43. package/dist/drain/index.js +1 -1
  44. package/dist/events/reader.d.ts +9 -10
  45. package/dist/events/reader.js +46 -57
  46. package/dist/events/reader.js.map +1 -1
  47. package/dist/events/writer.js +1 -1
  48. package/dist/events/writer.js.map +1 -1
  49. package/dist/fix-align/index.d.ts +1 -1
  50. package/dist/fix-align/index.js +1 -1
  51. package/dist/fix-align/run.d.ts +1 -1
  52. package/dist/fix-align/run.js +4 -3
  53. package/dist/fix-align/run.js.map +1 -1
  54. package/dist/fix-align/sentinel.d.ts +1 -2
  55. package/dist/fix-align/sentinel.js +3 -4
  56. package/dist/fix-align/sentinel.js.map +1 -1
  57. package/dist/gc/apply.js +1 -1
  58. package/dist/gc/apply.js.map +1 -1
  59. package/dist/gc/attested-commits.d.ts +19 -0
  60. package/dist/gc/attested-commits.js +48 -0
  61. package/dist/gc/attested-commits.js.map +1 -0
  62. package/dist/gc/canary.d.ts +11 -21
  63. package/dist/gc/canary.js +18 -24
  64. package/dist/gc/canary.js.map +1 -1
  65. package/dist/gc/citation-integrity.d.ts +11 -14
  66. package/dist/gc/citation-integrity.js +124 -125
  67. package/dist/gc/citation-integrity.js.map +1 -1
  68. package/dist/gc/classify.d.ts +1 -1
  69. package/dist/gc/classify.js +2 -2
  70. package/dist/gc/classify.js.map +1 -1
  71. package/dist/gc/completion-integrity.d.ts +6 -7
  72. package/dist/gc/completion-integrity.js +45 -53
  73. package/dist/gc/completion-integrity.js.map +1 -1
  74. package/dist/gc/doc-gardening.js +1 -9
  75. package/dist/gc/doc-gardening.js.map +1 -1
  76. package/dist/gc/frontmatter.js +2 -2
  77. package/dist/gc/frontmatter.js.map +1 -1
  78. package/dist/gc/index.d.ts +7 -6
  79. package/dist/gc/index.js +3 -2
  80. package/dist/gc/index.js.map +1 -1
  81. package/dist/gc/quality-update.d.ts +6 -10
  82. package/dist/gc/quality-update.js +12 -15
  83. package/dist/gc/quality-update.js.map +1 -1
  84. package/dist/gc/scope-coverage.js +1 -1
  85. package/dist/gc/scope-coverage.js.map +1 -1
  86. package/dist/gc/stub-hits.d.ts +7 -25
  87. package/dist/gc/stub-hits.js +14 -40
  88. package/dist/gc/stub-hits.js.map +1 -1
  89. package/dist/gc/sweep.js +15 -6
  90. package/dist/gc/sweep.js.map +1 -1
  91. package/dist/gc/types.d.ts +5 -5
  92. package/dist/gc/types.js +2 -2
  93. package/dist/gc/walk-source.js +8 -28
  94. package/dist/gc/walk-source.js.map +1 -1
  95. package/dist/hooks/defer.d.ts +9 -20
  96. package/dist/hooks/defer.js +10 -27
  97. package/dist/hooks/defer.js.map +1 -1
  98. package/dist/hooks/post-tool-use/allowlist-reader.d.ts +2 -1
  99. package/dist/hooks/post-tool-use/allowlist-reader.js +49 -34
  100. package/dist/hooks/post-tool-use/allowlist-reader.js.map +1 -1
  101. package/dist/hooks/post-tool-use/index.d.ts +3 -4
  102. package/dist/hooks/post-tool-use/index.js +3 -3
  103. package/dist/hooks/post-tool-use/index.js.map +1 -1
  104. package/dist/hooks/post-tool-use/legend-builder.d.ts +2 -2
  105. package/dist/hooks/post-tool-use/legend-builder.js +2 -2
  106. package/dist/hooks/post-tool-use/legend-builder.js.map +1 -1
  107. package/dist/hooks/post-tool-use/post-write.d.ts +8 -0
  108. package/dist/hooks/post-tool-use/post-write.js +112 -0
  109. package/dist/hooks/post-tool-use/post-write.js.map +1 -0
  110. package/dist/hooks/post-tool-use/read-enricher.d.ts +10 -5
  111. package/dist/hooks/post-tool-use/read-enricher.js +114 -155
  112. package/dist/hooks/post-tool-use/read-enricher.js.map +1 -1
  113. package/dist/hooks/post-tool-use/sot-align.d.ts +12 -0
  114. package/dist/hooks/post-tool-use/sot-align.js +73 -49
  115. package/dist/hooks/post-tool-use/sot-align.js.map +1 -1
  116. package/dist/hooks/post-tool-use/write-guardian.d.ts +40 -8
  117. package/dist/hooks/post-tool-use/write-guardian.js +202 -254
  118. package/dist/hooks/post-tool-use/write-guardian.js.map +1 -1
  119. package/dist/hooks/pre-commit/sot-align-precommit.js +2 -2
  120. package/dist/hooks/pre-commit/sot-align-precommit.js.map +1 -1
  121. package/dist/hooks/runners/index.d.ts +2 -2
  122. package/dist/hooks/runners/index.js +1 -1
  123. package/dist/hooks/runners/index.js.map +1 -1
  124. package/dist/hooks/runners/payload.d.ts +34 -19
  125. package/dist/hooks/runners/payload.js +47 -44
  126. package/dist/hooks/runners/payload.js.map +1 -1
  127. package/dist/hooks/runners/session-end.js +12 -11
  128. package/dist/hooks/runners/session-end.js.map +1 -1
  129. package/dist/hooks/runners/session-start.d.ts +4 -2
  130. package/dist/hooks/runners/session-start.js +88 -261
  131. package/dist/hooks/runners/session-start.js.map +1 -1
  132. package/dist/hooks/runners/stop.js +27 -8
  133. package/dist/hooks/runners/stop.js.map +1 -1
  134. package/dist/hooks/runners/user-prompt-submit.js +7 -1
  135. package/dist/hooks/runners/user-prompt-submit.js.map +1 -1
  136. package/dist/hooks/sot-align-common.d.ts +1 -2
  137. package/dist/hooks/sot-align-common.js +2 -2
  138. package/dist/hooks/sot-align-common.js.map +1 -1
  139. package/dist/index.d.ts +1 -1
  140. package/dist/index.js +12 -3
  141. package/dist/index.js.map +1 -1
  142. package/dist/init/baseline-audit.d.ts +14 -58
  143. package/dist/init/baseline-audit.js +92 -320
  144. package/dist/init/baseline-audit.js.map +1 -1
  145. package/dist/init/brand-derive.d.ts +11 -15
  146. package/dist/init/brand-derive.js +21 -46
  147. package/dist/init/brand-derive.js.map +1 -1
  148. package/dist/init/brand-setup.d.ts +1 -1
  149. package/dist/init/brand-setup.js +1 -1
  150. package/dist/init/detect.d.ts +25 -6
  151. package/dist/init/detect.js +107 -136
  152. package/dist/init/detect.js.map +1 -1
  153. package/dist/init/index.d.ts +2 -2
  154. package/dist/init/index.js +1 -1
  155. package/dist/init/index.js.map +1 -1
  156. package/dist/init/ingest-docs.d.ts +2 -2
  157. package/dist/init/ingest-docs.js +31 -43
  158. package/dist/init/ingest-docs.js.map +1 -1
  159. package/dist/init/init.d.ts +21 -21
  160. package/dist/init/init.js +41 -61
  161. package/dist/init/init.js.map +1 -1
  162. package/dist/init/mapper-merge.js +1 -1
  163. package/dist/init/mapper-merge.js.map +1 -1
  164. package/dist/init/mapper-parallel.d.ts +1 -1
  165. package/dist/init/mapper-parallel.js +2 -1
  166. package/dist/init/mapper-parallel.js.map +1 -1
  167. package/dist/init/mapper.js +1 -1
  168. package/dist/init/mapper.js.map +1 -1
  169. package/dist/init/multi-dev/install.d.ts +5 -5
  170. package/dist/init/multi-dev/install.js +4 -4
  171. package/dist/init/overlay.js +1 -0
  172. package/dist/init/overlay.js.map +1 -1
  173. package/dist/init/phases/1-detect.js +1 -1
  174. package/dist/init/phases/1-detect.js.map +1 -1
  175. package/dist/init/phases/{7c-rules-merge.d.ts → 10-rules-merge.d.ts} +2 -2
  176. package/dist/init/phases/{7c-rules-merge.js → 10-rules-merge.js} +6 -12
  177. package/dist/init/phases/10-rules-merge.js.map +1 -0
  178. package/dist/init/phases/11-baseline.d.ts +7 -0
  179. package/dist/init/phases/{8-baseline.js → 11-baseline.js} +5 -9
  180. package/dist/init/phases/11-baseline.js.map +1 -0
  181. package/dist/init/phases/12-strip.d.ts +10 -0
  182. package/dist/init/phases/{10-strip.js → 12-strip.js} +10 -14
  183. package/dist/init/phases/12-strip.js.map +1 -0
  184. package/dist/init/phases/{12-multidev.d.ts → 13-multidev.d.ts} +2 -2
  185. package/dist/init/phases/{12-multidev.js → 13-multidev.js} +4 -4
  186. package/dist/init/phases/{12-multidev.js.map → 13-multidev.js.map} +1 -1
  187. package/dist/init/phases/3-mapper.d.ts +1 -1
  188. package/dist/init/phases/3-mapper.js +2 -2
  189. package/dist/init/phases/3-mapper.js.map +1 -1
  190. package/dist/init/phases/{3b-seed.d.ts → 4-seed.d.ts} +2 -2
  191. package/dist/init/phases/{3b-seed.js → 4-seed.js} +7 -7
  192. package/dist/init/phases/4-seed.js.map +1 -0
  193. package/dist/init/phases/{4-pilot.d.ts → 5-pilot.d.ts} +2 -2
  194. package/dist/init/phases/{4-pilot.js → 5-pilot.js} +9 -9
  195. package/dist/init/phases/{4-pilot.js.map → 5-pilot.js.map} +1 -1
  196. package/dist/init/phases/{5-brand.d.ts → 6-brand.d.ts} +2 -7
  197. package/dist/init/phases/{5-brand.js → 6-brand.js} +6 -14
  198. package/dist/init/phases/6-brand.js.map +1 -0
  199. package/dist/init/phases/{5b-topic-index.d.ts → 7-topic-index.d.ts} +2 -11
  200. package/dist/init/phases/{5b-topic-index.js → 7-topic-index.js} +9 -18
  201. package/dist/init/phases/7-topic-index.js.map +1 -0
  202. package/dist/init/phases/8-docs-ingest.d.ts +10 -0
  203. package/dist/init/phases/{6-docs-ingest.js → 8-docs-ingest.js} +6 -11
  204. package/dist/init/phases/8-docs-ingest.js.map +1 -0
  205. package/dist/init/phases/9-source-comments.d.ts +6 -0
  206. package/dist/init/phases/{7b-source-comments.js → 9-source-comments.js} +7 -26
  207. package/dist/init/phases/9-source-comments.js.map +1 -0
  208. package/dist/init/phases/index.d.ts +12 -12
  209. package/dist/init/phases/index.js +11 -11
  210. package/dist/init/phases/index.js.map +1 -1
  211. package/dist/init/phases/{parallel-678.d.ts → parallel-8910.d.ts} +7 -8
  212. package/dist/init/phases/{parallel-678.js → parallel-8910.js} +26 -44
  213. package/dist/init/phases/parallel-8910.js.map +1 -0
  214. package/dist/init/phases/source-comments-output-io.d.ts +3 -3
  215. package/dist/init/phases/source-comments-output-io.js +3 -3
  216. package/dist/init/phases/types.d.ts +1 -1
  217. package/dist/init/phases/types.js +10 -10
  218. package/dist/init/phases/types.js.map +1 -1
  219. package/dist/init/rules-merge/discover.d.ts +2 -2
  220. package/dist/init/rules-merge/discover.js +28 -43
  221. package/dist/init/rules-merge/discover.js.map +1 -1
  222. package/dist/init/rules-merge/ingest.d.ts +6 -6
  223. package/dist/init/rules-merge/ingest.js +9 -10
  224. package/dist/init/rules-merge/ingest.js.map +1 -1
  225. package/dist/init/rules-merge/keep-markers.d.ts +1 -1
  226. package/dist/init/rules-merge/keep-markers.js +1 -1
  227. package/dist/init/rules-merge/regenerate.d.ts +3 -3
  228. package/dist/init/rules-merge/regenerate.js +3 -3
  229. package/dist/init/seed.js +17 -24
  230. package/dist/init/seed.js.map +1 -1
  231. package/dist/init/sot-emit.d.ts +27 -9
  232. package/dist/init/sot-emit.js +39 -7
  233. package/dist/init/sot-emit.js.map +1 -1
  234. package/dist/init/source-comments/classify.d.ts +2 -2
  235. package/dist/init/source-comments/classify.js +9 -1
  236. package/dist/init/source-comments/classify.js.map +1 -1
  237. package/dist/init/source-comments/index.d.ts +1 -1
  238. package/dist/init/source-comments/index.js.map +1 -1
  239. package/dist/init/source-comments/ingest.d.ts +2 -2
  240. package/dist/init/source-comments/ingest.js +6 -8
  241. package/dist/init/source-comments/ingest.js.map +1 -1
  242. package/dist/init/source-comments/strip-replace.js +3 -2
  243. package/dist/init/source-comments/strip-replace.js.map +1 -1
  244. package/dist/init/source-comments/walker.d.ts +3 -26
  245. package/dist/init/source-comments/walker.js +18 -30
  246. package/dist/init/source-comments/walker.js.map +1 -1
  247. package/dist/init/topic-index/index.d.ts +1 -1
  248. package/dist/init/topic-index/index.js +3 -3
  249. package/dist/init/topic-index/index.js.map +1 -1
  250. package/dist/init/topic-index/judge.d.ts +5 -9
  251. package/dist/init/topic-index/judge.js +17 -22
  252. package/dist/init/topic-index/judge.js.map +1 -1
  253. package/dist/init/topic-index/resolve.d.ts +5 -4
  254. package/dist/init/topic-index/resolve.js +6 -6
  255. package/dist/init/topic-index/resolve.js.map +1 -1
  256. package/dist/init/topic-index/walk.d.ts +6 -6
  257. package/dist/init/topic-index/walk.js +9 -9
  258. package/dist/init/topic-index/walk.js.map +1 -1
  259. package/dist/lock.js +4 -1
  260. package/dist/lock.js.map +1 -1
  261. package/dist/logger.js +3 -0
  262. package/dist/logger.js.map +1 -1
  263. package/dist/mcp/history/summarizer.js +1 -1
  264. package/dist/mcp/history/summarizer.js.map +1 -1
  265. package/dist/mcp/history/walker.js +1 -1
  266. package/dist/mcp/history/walker.js.map +1 -1
  267. package/dist/mcp/path-allowlist.js +1 -1
  268. package/dist/mcp/path-allowlist.js.map +1 -1
  269. package/dist/mcp/schemas.d.ts +16 -38
  270. package/dist/mcp/schemas.js +8 -22
  271. package/dist/mcp/schemas.js.map +1 -1
  272. package/dist/mcp/server.js +10 -0
  273. package/dist/mcp/server.js.map +1 -1
  274. package/dist/mcp/tools/archive.js +1 -1
  275. package/dist/mcp/tools/archive.js.map +1 -1
  276. package/dist/mcp/tools/attention-wait.js +12 -2
  277. package/dist/mcp/tools/attention-wait.js.map +1 -1
  278. package/dist/mcp/tools/bulk-accept-attention.js +29 -30
  279. package/dist/mcp/tools/bulk-accept-attention.js.map +1 -1
  280. package/dist/mcp/tools/canonical-for-topic.js +37 -15
  281. package/dist/mcp/tools/canonical-for-topic.js.map +1 -1
  282. package/dist/mcp/tools/decision-get.js +2 -2
  283. package/dist/mcp/tools/decision-get.js.map +1 -1
  284. package/dist/mcp/tools/decisions-for-symbol.js +2 -2
  285. package/dist/mcp/tools/decisions-for-symbol.js.map +1 -1
  286. package/dist/mcp/tools/get-full.js +1 -1
  287. package/dist/mcp/tools/get-full.js.map +1 -1
  288. package/dist/mcp/tools/ground-get.js +1 -1
  289. package/dist/mcp/tools/ground-get.js.map +1 -1
  290. package/dist/mcp/tools/in-scope.d.ts +8 -0
  291. package/dist/mcp/tools/in-scope.js +125 -0
  292. package/dist/mcp/tools/in-scope.js.map +1 -0
  293. package/dist/mcp/tools/index.js +7 -10
  294. package/dist/mcp/tools/index.js.map +1 -1
  295. package/dist/mcp/tools/init-phases.d.ts +3 -2
  296. package/dist/mcp/tools/init-phases.js +125 -124
  297. package/dist/mcp/tools/init-phases.js.map +1 -1
  298. package/dist/mcp/tools/invariant-get.js +2 -2
  299. package/dist/mcp/tools/invariant-get.js.map +1 -1
  300. package/dist/mcp/tools/record-decision.d.ts +4 -3
  301. package/dist/mcp/tools/record-decision.js +111 -36
  302. package/dist/mcp/tools/record-decision.js.map +1 -1
  303. package/dist/mcp/tools/reject-candidate.d.ts +1 -1
  304. package/dist/mcp/tools/reject-candidate.js +3 -3
  305. package/dist/mcp/tools/reject-candidate.js.map +1 -1
  306. package/dist/mcp/tools/resolve-attention.d.ts +5 -18
  307. package/dist/mcp/tools/resolve-attention.js +58 -158
  308. package/dist/mcp/tools/resolve-attention.js.map +1 -1
  309. package/dist/mcp/tools/search-candidates.d.ts +1 -1
  310. package/dist/mcp/tools/search-candidates.js +4 -4
  311. package/dist/mcp/tools/search-candidates.js.map +1 -1
  312. package/dist/mcp/tools/search.js +5 -4
  313. package/dist/mcp/tools/search.js.map +1 -1
  314. package/dist/mcp/tools/supersedes-chain.js +2 -2
  315. package/dist/mcp/tools/supersedes-chain.js.map +1 -1
  316. package/dist/mcp/tools/task-create.d.ts +1 -0
  317. package/dist/mcp/tools/task-create.js +2 -0
  318. package/dist/mcp/tools/task-create.js.map +1 -1
  319. package/dist/mcp/tools/timeline.js +1 -1
  320. package/dist/mcp/tools/timeline.js.map +1 -1
  321. package/dist/mcp/tools/types.d.ts +1 -0
  322. package/dist/mcp/tools/types.js +9 -1
  323. package/dist/mcp/tools/types.js.map +1 -1
  324. package/dist/sensors/attestation.d.ts +1 -1
  325. package/dist/sensors/attestation.js +2 -2
  326. package/dist/sensors/attestation.js.map +1 -1
  327. package/dist/sensors/catalog.d.ts +26 -28
  328. package/dist/sensors/catalog.js +79 -81
  329. package/dist/sensors/catalog.js.map +1 -1
  330. package/dist/sensors/decisions.d.ts +1 -1
  331. package/dist/sensors/decisions.js +15 -14
  332. package/dist/sensors/decisions.js.map +1 -1
  333. package/dist/sensors/diff.js +46 -22
  334. package/dist/sensors/diff.js.map +1 -1
  335. package/dist/sensors/runner.d.ts +2 -2
  336. package/dist/sensors/runner.js +3 -3
  337. package/dist/sensors/shell.d.ts +4 -0
  338. package/dist/sensors/shell.js +16 -0
  339. package/dist/sensors/shell.js.map +1 -0
  340. package/dist/sensors/structural.d.ts +3 -2
  341. package/dist/sensors/structural.js +3 -11
  342. package/dist/sensors/structural.js.map +1 -1
  343. package/dist/sensors/stub-catalog.d.ts +2 -1
  344. package/dist/sensors/stub-catalog.js +2 -9
  345. package/dist/sensors/stub-catalog.js.map +1 -1
  346. package/dist/sensors/types.d.ts +3 -4
  347. package/dist/sensors/types.js +1 -2
  348. package/dist/sensors/types.js.map +1 -1
  349. package/dist/session-start/build.js +1 -1
  350. package/dist/session-start/build.js.map +1 -1
  351. package/dist/status-line/event-queue.js +1 -1
  352. package/dist/status-line/index.d.ts +1 -1
  353. package/package.json +3 -2
  354. package/templates/.cairn/config/sensors.yaml +8 -8
  355. package/templates/attention-ui/app.js +61 -36
  356. package/dist/fs.d.ts +0 -5
  357. package/dist/fs.js +0 -11
  358. package/dist/fs.js.map +0 -1
  359. package/dist/ground/alignment-pending.d.ts +0 -28
  360. package/dist/ground/alignment-pending.js +0 -83
  361. package/dist/ground/alignment-pending.js.map +0 -1
  362. package/dist/ground/anchor-map.d.ts +0 -14
  363. package/dist/ground/anchor-map.js +0 -56
  364. package/dist/ground/anchor-map.js.map +0 -1
  365. package/dist/ground/drift.d.ts +0 -8
  366. package/dist/ground/drift.js +0 -23
  367. package/dist/ground/drift.js.map +0 -1
  368. package/dist/ground/file-candidates-map.d.ts +0 -23
  369. package/dist/ground/file-candidates-map.js +0 -76
  370. package/dist/ground/file-candidates-map.js.map +0 -1
  371. package/dist/ground/frontmatter.d.ts +0 -32
  372. package/dist/ground/frontmatter.js +0 -77
  373. package/dist/ground/frontmatter.js.map +0 -1
  374. package/dist/ground/glob.d.ts +0 -10
  375. package/dist/ground/glob.js +0 -46
  376. package/dist/ground/glob.js.map +0 -1
  377. package/dist/ground/index.d.ts +0 -25
  378. package/dist/ground/index.js +0 -19
  379. package/dist/ground/index.js.map +0 -1
  380. package/dist/ground/ledgers.d.ts +0 -14
  381. package/dist/ground/ledgers.js +0 -105
  382. package/dist/ground/ledgers.js.map +0 -1
  383. package/dist/ground/manifest.d.ts +0 -10
  384. package/dist/ground/manifest.js +0 -84
  385. package/dist/ground/manifest.js.map +0 -1
  386. package/dist/ground/paths.d.ts +0 -43
  387. package/dist/ground/paths.js +0 -109
  388. package/dist/ground/paths.js.map +0 -1
  389. package/dist/ground/quality-grades.d.ts +0 -11
  390. package/dist/ground/quality-grades.js +0 -100
  391. package/dist/ground/quality-grades.js.map +0 -1
  392. package/dist/ground/rejected.d.ts +0 -42
  393. package/dist/ground/rejected.js +0 -100
  394. package/dist/ground/rejected.js.map +0 -1
  395. package/dist/ground/schemas.d.ts +0 -582
  396. package/dist/ground/schemas.js +0 -372
  397. package/dist/ground/schemas.js.map +0 -1
  398. package/dist/ground/scope-index.d.ts +0 -96
  399. package/dist/ground/scope-index.js +0 -290
  400. package/dist/ground/scope-index.js.map +0 -1
  401. package/dist/ground/slug.d.ts +0 -60
  402. package/dist/ground/slug.js +0 -103
  403. package/dist/ground/slug.js.map +0 -1
  404. package/dist/ground/sot-bindings.d.ts +0 -14
  405. package/dist/ground/sot-bindings.js +0 -79
  406. package/dist/ground/sot-bindings.js.map +0 -1
  407. package/dist/ground/sot-cache.d.ts +0 -18
  408. package/dist/ground/sot-cache.js +0 -62
  409. package/dist/ground/sot-cache.js.map +0 -1
  410. package/dist/ground/topic-index.d.ts +0 -27
  411. package/dist/ground/topic-index.js +0 -82
  412. package/dist/ground/topic-index.js.map +0 -1
  413. package/dist/ground/walk.d.ts +0 -7
  414. package/dist/ground/walk.js +0 -53
  415. package/dist/ground/walk.js.map +0 -1
  416. package/dist/hooks/post-tool-use/ledger-cache.d.ts +0 -53
  417. package/dist/hooks/post-tool-use/ledger-cache.js +0 -338
  418. package/dist/hooks/post-tool-use/ledger-cache.js.map +0 -1
  419. package/dist/init/phases/10-strip.d.ts +0 -11
  420. package/dist/init/phases/10-strip.js.map +0 -1
  421. package/dist/init/phases/3b-seed.js.map +0 -1
  422. package/dist/init/phases/5-brand.js.map +0 -1
  423. package/dist/init/phases/5b-topic-index.js.map +0 -1
  424. package/dist/init/phases/6-docs-ingest.d.ts +0 -15
  425. package/dist/init/phases/6-docs-ingest.js.map +0 -1
  426. package/dist/init/phases/7b-source-comments.d.ts +0 -15
  427. package/dist/init/phases/7b-source-comments.js.map +0 -1
  428. package/dist/init/phases/7c-rules-merge.js.map +0 -1
  429. package/dist/init/phases/8-baseline.d.ts +0 -10
  430. package/dist/init/phases/8-baseline.js.map +0 -1
  431. package/dist/init/phases/parallel-678.js.map +0 -1
  432. package/dist/mcp/tools/decisions-in-scope.d.ts +0 -7
  433. package/dist/mcp/tools/decisions-in-scope.js +0 -66
  434. package/dist/mcp/tools/decisions-in-scope.js.map +0 -1
  435. package/dist/mcp/tools/invariants-in-scope.d.ts +0 -7
  436. package/dist/mcp/tools/invariants-in-scope.js +0 -81
  437. package/dist/mcp/tools/invariants-in-scope.js.map +0 -1
  438. package/dist/mcp/tools/propose-decision.d.ts +0 -34
  439. package/dist/mcp/tools/propose-decision.js +0 -200
  440. package/dist/mcp/tools/propose-decision.js.map +0 -1
@@ -4,50 +4,47 @@
4
4
  * Spec: PLUGIN_ARCHITECTURE §9 (MCP write tools — plugin-era addition).
5
5
  *
6
6
  * The cairn-attention skill calls this after the operator picks an
7
- * option. It maps `kind × choice` onto the canonical resolution
8
- * pathway:
9
- *
10
- * | kind | choice | resolution |
11
- * |---------------------|--------|---------------------------------------------|
12
- * | decision_draft | a | accept — move `_inbox/<id>.draft.md` → `<id>.md`, status=accepted |
13
- * | decision_draft | b | reject — rename draft to .rejected.md (id reserved forever) |
14
- * | decision_draft | c | edit-pending — return draft body (no write) |
15
- * | baseline_finding | a | triage-now — no-op (skill opens the file) |
16
- * | baseline_finding | b | suppress — append to baseline/suppressions.yaml |
17
- * | baseline_finding | c | defer — no-op |
18
- * | invalidation_event | a | refresh — re-read in-scope DECs/§INVs |
19
- * | invalidation_event | b | continue-under-old — no-op |
20
- * | invalidation_event | c | abort — caller archives task (no-op here) |
21
- * | drift | a/b/c | acknowledged (drift surface not yet active) |
7
+ * option. It maps the option (a/b/c/d) to a ground-state write (promote
8
+ * draft, suppress finding, record resolution event).
22
9
  */
23
10
  import { appendFileSync, existsSync, mkdirSync, readFileSync, readdirSync, renameSync, rmSync, statSync, writeFileSync, } from "node:fs";
24
11
  import { dirname, join } from "node:path";
25
- import { writeFileSafe } from "../../fs.js";
26
12
  import { createHash } from "node:crypto";
27
13
  import { stringify as stringifyYaml } from "yaml";
28
- import { parseDraftMeta, restoreDec, runDecSourceStrip, } from "../../attention/index.js";
14
+ import { z } from "zod";
15
+ import { bindDec, bodyContentHash, conflictsDir, readSotBindings, readSotCache, recordDriftEvent, setSotCacheEntry, writeSotBindings, writeSotCache, decisionsDir, invariantsDir, writeDecisionsLedger, writeInvariantsLedger, parseFrontmatterRecord, deleteSotCacheEntry, unbindDec, alignmentPendingDir, archivedConflictsDir, deriveLedgerDecId, deriveLedgerInvId, writeFileSafe, } from "@isaacriehm/cairn-state";
29
16
  import { writeInvalidationEvent } from "../../events/index.js";
30
- import { alignmentPendingDir, archivedConflictsDir, bindDec, bodyContentHash, conflictsDir, decisionsDir, deleteSotCacheEntry, deriveLedgerDecId, deriveLedgerInvId, invariantsDir, parseFrontmatterRecord, readSotBindings, readSotCache, recordDriftEvent, setSotCacheEntry, unbindDec, writeSotBindings, writeSotCache, } from "../../ground/index.js";
31
- import { tokenize } from "../../text/jaccard.js";
32
- import { applyStripReplace, formatBareCitation, } from "../../init/source-comments/index.js";
33
- import { writeDecisionsLedger, writeInvariantsLedger } from "../../ground/ledgers.js";
34
- import { clearDeferState, writeDeferState, } from "../../hooks/defer.js";
35
17
  import { withWriteLock } from "../../lock.js";
36
- import { logger } from "../../logger.js";
37
18
  import { requireBootstrap } from "../bootstrap-guard.js";
38
- import { mcpError } from "../errors.js";
39
- import { resolveAttentionInput } from "../schemas.js";
40
- const log = logger("mcp.resolve-attention");
19
+ import { mcpError } from "./types.js";
20
+ import { parseDraftMeta, runDecSourceStrip, } from "../../attention/source-strip.js";
21
+ import { restoreDec } from "../../attention/restore.js";
22
+ import { tokenize } from "../../text/jaccard.js";
23
+ import { applyStripReplace, formatBareCitation, } from "../../init/source-comments/strip-replace.js";
24
+ import { writeDeferState, clearDeferState } from "../../hooks/defer.js";
25
+ import { logger } from "../../logger.js";
26
+ const log = logger("mcp.tools.resolve-attention");
27
+ const resolveAttentionInput = {
28
+ kind: z.enum([
29
+ "decision_draft",
30
+ "baseline_finding",
31
+ "invalidation_event",
32
+ "drift",
33
+ "bypass",
34
+ "review",
35
+ "conflict",
36
+ "alignment_pending",
37
+ ]),
38
+ item_id: z.string(),
39
+ choice: z.enum(["a", "b", "c", "d"]),
40
+ rationale: z.string().optional(),
41
+ defer_hours: z.number().optional(),
42
+ flagged_items: z.array(z.string()).optional(),
43
+ };
41
44
  async function handler(ctx, input) {
42
45
  const block = requireBootstrap(ctx.repoRoot);
43
46
  if (block !== null)
44
47
  return block;
45
- // The fourth choice slot is only meaningful for conflict resolution.
46
- // Reject `d` on every other kind so the schema's permissive enum
47
- // doesn't quietly fall through.
48
- if (input.choice === "d" && input.kind !== "conflict") {
49
- return mcpError("VALIDATION_FAILED", `choice "d" is only valid for kind=conflict, got kind=${input.kind}`);
50
- }
51
48
  switch (input.kind) {
52
49
  case "decision_draft":
53
50
  return resolveDecisionDraft(ctx, input);
@@ -55,28 +52,18 @@ async function handler(ctx, input) {
55
52
  return resolveBaselineFinding(ctx, input);
56
53
  case "invalidation_event":
57
54
  return resolveInvalidationEvent(ctx, input);
58
- case "drift":
59
- return {
60
- ok: true,
61
- resolved_kind: "drift_acknowledged",
62
- note: "drift resolution surface not yet implemented (step 7+); item left in queue",
63
- };
64
55
  case "bypass":
65
- return resolveBypass(ctx, input);
56
+ return resolveStopSignal(ctx, input, "bypass");
66
57
  case "review":
67
- return resolveReview(ctx, input);
58
+ return resolveStopSignal(ctx, input, "review");
68
59
  case "conflict":
69
60
  return resolveConflict(ctx, input);
70
61
  case "alignment_pending":
71
62
  return resolveAlignmentPending(ctx, input);
63
+ default:
64
+ return mcpError("VALIDATION_FAILED", `unknown kind: ${input.kind}`);
72
65
  }
73
66
  }
74
- function resolveBypass(ctx, input) {
75
- return resolveStopSignal(ctx, input, "bypass");
76
- }
77
- function resolveReview(ctx, input) {
78
- return resolveStopSignal(ctx, input, "review");
79
- }
80
67
  /**
81
68
  * Shared resolution path for the two Stop-hook surfaces. choice=a/b
82
69
  * are kind-specific intents (the calling skill executes them); the
@@ -92,7 +79,6 @@ function resolveStopSignal(ctx, input, kind) {
92
79
  const state = writeDeferState(ctx.repoRoot, kind, {
93
80
  flagged_shas: kind === "bypass" ? flagged : [],
94
81
  flagged_task_ids: kind === "review" ? flagged : [],
95
- ...(input.defer_hours !== undefined ? { hours: input.defer_hours } : {}),
96
82
  });
97
83
  return {
98
84
  ok: true,
@@ -133,13 +119,6 @@ async function resolveDecisionDraft(ctx, input) {
133
119
  const inboxPath = join(decDir, "_inbox", `${input.item_id}.draft.md`);
134
120
  const rejectedPath = join(decDir, "_inbox", `${input.item_id}.rejected.md`);
135
121
  const acceptedPath = join(decDir, `${input.item_id}.md`);
136
- // Auto-restore: when the draft is missing but the same id sits as a
137
- // rejected or already-accepted entry, transparently roll it back to
138
- // a draft so the operator's choice (a/b/c) lands in one MCP call
139
- // instead of needing an explicit `cairn_attention_restore` first.
140
- // Idempotent re-accept on a still-canonical accepted DEC is the same
141
- // shape as accepting a fresh draft — rebuild ledger, no double-strip
142
- // (already-stripped check inside runDecSourceStrip).
143
122
  let autoRestoredFrom = null;
144
123
  if (!existsSync(inboxPath)) {
145
124
  if (existsSync(rejectedPath) || existsSync(acceptedPath)) {
@@ -160,8 +139,6 @@ async function resolveDecisionDraft(ctx, input) {
160
139
  }
161
140
  }
162
141
  if (input.choice === "c") {
163
- // Edit-pending: return the draft body so the skill can hand it to
164
- // the operator's editor flow. No state change.
165
142
  const body = readFileSync(inboxPath, "utf8");
166
143
  const editBase = {
167
144
  ok: true,
@@ -174,7 +151,7 @@ async function resolveDecisionDraft(ctx, input) {
174
151
  ? editBase
175
152
  : { ...editBase, auto_restored_from: autoRestoredFrom };
176
153
  }
177
- return withWriteLock(ctx.repoRoot, () => {
154
+ return withWriteLock(ctx.repoRoot, async () => {
178
155
  if (input.choice === "a") {
179
156
  const acceptedPath = join(decDir, `${input.item_id}.md`);
180
157
  mkdirSync(dirname(acceptedPath), { recursive: true });
@@ -182,25 +159,18 @@ async function resolveDecisionDraft(ctx, input) {
182
159
  const draftMeta = parseDraftMeta(draft);
183
160
  const promoted = promoteDraftStatus(draft);
184
161
  writeFileSync(acceptedPath, promoted, "utf8");
185
- // Remove the draft after promoting so the inbox stays clean.
186
- // The canonical accepted file at <decDir>/<id>.md is the
187
- // recoverable copy if the rmSync interrupts.
188
162
  try {
189
163
  rmSync(inboxPath, { force: true });
190
164
  }
191
165
  catch {
192
- // ignore — best effort, the accepted file is what matters
166
+ // ignore
193
167
  }
194
168
  try {
195
169
  emitEvent(ctx, "decision_accepted", input.item_id, `.cairn/ground/decisions/${input.item_id}.md`);
196
170
  }
197
171
  catch {
198
- // event emission must never roll back the resolution
172
+ // ignore
199
173
  }
200
- // Rebuild `.cairn/ground/decisions/decisions.ledger.yaml` from
201
- // every accepted DEC on disk. Cairn Lens reads the ledger to
202
- // resolve `// DEC-NNNN` citations inline; without this rebuild
203
- // the ledger sits empty and lens renders nothing.
204
174
  try {
205
175
  writeDecisionsLedger({ repoRoot: ctx.repoRoot });
206
176
  }
@@ -226,8 +196,7 @@ async function resolveDecisionDraft(ctx, input) {
226
196
  ? withStrip
227
197
  : { ...withStrip, auto_restored_from: autoRestoredFrom };
228
198
  }
229
- // choice === "b" — reject. Rename to .rejected.md so scanExistingDecisionIds
230
- // keeps the id in the high-water mark and it is never recycled.
199
+ // choice === "b" — reject.
231
200
  renameSync(inboxPath, rejectedPath);
232
201
  const rejectedRel = `.cairn/ground/decisions/_inbox/${input.item_id}.rejected.md`;
233
202
  try {
@@ -265,9 +234,6 @@ function resolveBaselineFinding(ctx, input) {
265
234
  return withWriteLock(ctx.repoRoot, () => {
266
235
  const suppressionsPath = join(ctx.repoRoot, ".cairn", "baseline", "suppressions.yaml");
267
236
  mkdirSync(dirname(suppressionsPath), { recursive: true });
268
- // Empty / missing file → seed the YAML root key so the appended
269
- // entries land under a valid `suppressions:` list. statSync may
270
- // throw on race; treat any error as "needs header".
271
237
  let needsHeader = !existsSync(suppressionsPath);
272
238
  if (!needsHeader) {
273
239
  try {
@@ -391,20 +357,6 @@ function deleteConflictFile(conflict) {
391
357
  /* best-effort */
392
358
  }
393
359
  }
394
- /**
395
- * Plan §5.4.1 — losing-side prose stays in its source file
396
- * post-resolution; the doc / CLAUDE.md / AGENTS.md narrative is
397
- * preserved as-is. The original sot_path entry is now bound to a
398
- * superseded / archived id, so phase 5b's next walk would re-emit a
399
- * fresh DEC with the same content-addressed id (loop). Recording an
400
- * `orphan_path` drift event surfaces the prose to the operator's
401
- * attention queue so they can pick: re-cite the winner manually,
402
- * promote it to a fresh DEC, or delete the orphan paragraph.
403
- *
404
- * The drift event includes `dec_id` pointing at the just-superseded
405
- * entity so the attention surface can render context (which side won,
406
- * what the orphan body looks like).
407
- */
408
360
  function recordOrphanDriftEvents(repoRoot, refs) {
409
361
  const ts = new Date().toISOString();
410
362
  for (const { ref, parsed } of refs) {
@@ -436,22 +388,15 @@ function rebuildLedgers(repoRoot) {
436
388
  writeDecisionsLedger({ repoRoot });
437
389
  }
438
390
  catch (err) {
439
- log.warn({ err: err instanceof Error ? err.message : String(err) }, "decisions ledger rebuild failed after conflict resolution");
391
+ log.warn({ err: err instanceof Error ? err.message : String(err) }, "decisions ledger rebuild failed");
440
392
  }
441
393
  try {
442
394
  writeInvariantsLedger({ repoRoot });
443
395
  }
444
396
  catch (err) {
445
- log.warn({ err: err instanceof Error ? err.message : String(err) }, "invariants ledger rebuild failed after conflict resolution");
397
+ log.warn({ err: err instanceof Error ? err.message : String(err) }, "invariants ledger rebuild failed");
446
398
  }
447
399
  }
448
- /**
449
- * Drop superseded / archived losers from sot-bindings + sot-cache so
450
- * Layer A's pre-filter doesn't pick them as candidates and phase 5b
451
- * doesn't loop on a path bound to a now-superseded id. The orphan_path
452
- * drift event (recorded separately for sot_kind="path" losers) remains
453
- * the operator-facing surface to recover the orphaned prose.
454
- */
455
400
  function cleanLosersFromSotState(repoRoot, losers) {
456
401
  let bindings = readSotBindings(repoRoot);
457
402
  let cache = readSotCache(repoRoot);
@@ -473,30 +418,24 @@ function cleanLosersFromSotState(repoRoot, losers) {
473
418
  try {
474
419
  writeSotBindings(repoRoot, bindings);
475
420
  }
476
- catch (err) {
477
- log.warn({ err: err instanceof Error ? err.message : String(err) }, "sot-bindings rewrite failed during conflict resolution cleanup");
421
+ catch {
422
+ /* ignore */
478
423
  }
479
424
  try {
480
425
  writeSotCache(repoRoot, cache);
481
426
  }
482
- catch (err) {
483
- log.warn({ err: err instanceof Error ? err.message : String(err) }, "sot-cache rewrite failed during conflict resolution cleanup");
427
+ catch {
428
+ /* ignore */
484
429
  }
485
430
  }
486
- /**
487
- * Bind + cache a merged entity that was just written to ground. Mirrors
488
- * the bind/cache wiring in `emitFreshDec` so Layer A's pre-filter sees
489
- * the merged DEC as a Tier-2 candidate immediately, instead of waiting
490
- * for the next SessionStart drain to rebuild sot-cache.
491
- */
492
431
  function bindAndCacheMergedEntity(repoRoot, mergedId, mergedBody) {
493
432
  let bindings = readSotBindings(repoRoot);
494
433
  bindings = bindDec(bindings, mergedId, "ledger");
495
434
  try {
496
435
  writeSotBindings(repoRoot, bindings);
497
436
  }
498
- catch (err) {
499
- log.warn({ err: err instanceof Error ? err.message : String(err) }, "sot-bindings rewrite failed for merged entity");
437
+ catch {
438
+ /* ignore */
500
439
  }
501
440
  let cache = readSotCache(repoRoot);
502
441
  cache = setSotCacheEntry(cache, mergedId, {
@@ -510,8 +449,8 @@ function bindAndCacheMergedEntity(repoRoot, mergedId, mergedBody) {
510
449
  try {
511
450
  writeSotCache(repoRoot, cache);
512
451
  }
513
- catch (err) {
514
- log.warn({ err: err instanceof Error ? err.message : String(err) }, "sot-cache rewrite failed for merged entity");
452
+ catch {
453
+ /* ignore */
515
454
  }
516
455
  }
517
456
  function loadAlignmentPending(repoRoot, itemId) {
@@ -528,11 +467,8 @@ function loadAlignmentPending(repoRoot, itemId) {
528
467
  return null;
529
468
  }
530
469
  const { fm, body } = parseFrontmatterRecord(raw);
531
- // Block prose lives between the first ```/``` fence pair under the
532
- // "## Block ..." heading. Pick the first fenced block.
533
470
  const blockMatch = body.match(/##\s+Block[^\n]*\n+```\n([\s\S]*?)\n```/);
534
471
  const blockProse = blockMatch?.[1]?.trim() ?? "";
535
- // Existing entity body (tier2-ambiguous only) lives in a second fenced block.
536
472
  const existingId = typeof fm["existing_id"] === "string" ? fm["existing_id"] : null;
537
473
  let existingBody = null;
538
474
  if (existingId !== null) {
@@ -579,7 +515,6 @@ async function resolveAlignmentPending(ctx, input) {
579
515
  return mcpError("VALIDATION_FAILED", "tier2-ambiguous pending entry missing existing_id");
580
516
  }
581
517
  if (input.choice === "a") {
582
- // Same — cite existing.
583
518
  const replacement = formatBareCitation(lang, state.existingId);
584
519
  const item = buildPendingReplaceItem(state.fm, state.blockProse, replacement);
585
520
  if (item !== null)
@@ -597,10 +532,6 @@ async function resolveAlignmentPending(ctx, input) {
597
532
  };
598
533
  }
599
534
  if (input.choice === "b") {
600
- // Augments — emit sibling DEC linked via `related`. Source gets
601
- // both cites stacked. (Operator-driven augments emit a DEC
602
- // sibling; constraint augments still flow through the Layer A
603
- // delta classifier on a future Write.)
604
535
  const id = emitOperatorAugmentSibling(ctx.repoRoot, {
605
536
  source_file: sourceFile,
606
537
  source_offset: startLine,
@@ -634,7 +565,6 @@ async function resolveAlignmentPending(ctx, input) {
634
565
  };
635
566
  }
636
567
  if (input.choice === "c") {
637
- // New decision — emit fresh DEC, source carries new cite only.
638
568
  const id = emitFreshDec(ctx.repoRoot, {
639
569
  source_file: sourceFile,
640
570
  source_offset: startLine,
@@ -665,7 +595,6 @@ async function resolveAlignmentPending(ctx, input) {
665
595
  };
666
596
  }
667
597
  if (input.choice === "d") {
668
- // Replace — new becomes canonical, existing superseded.
669
598
  const id = emitFreshDec(ctx.repoRoot, {
670
599
  source_file: sourceFile,
671
600
  source_offset: startLine,
@@ -673,7 +602,6 @@ async function resolveAlignmentPending(ctx, input) {
673
602
  captureSuffix: "operator-replace",
674
603
  related: state.existingId,
675
604
  });
676
- // Mark existing as superseded.
677
605
  const existingRef = entityRefFor(ctx.repoRoot, state.existingId);
678
606
  const parsed = readEntity(existingRef);
679
607
  if (parsed !== null) {
@@ -744,8 +672,6 @@ async function resolveAlignmentPending(ctx, input) {
744
672
  };
745
673
  }
746
674
  if (input.choice === "c" || input.choice === "d") {
747
- // Descriptive / none-of-these — drop the pending file. Source
748
- // stays untouched (operator's narrative preserved).
749
675
  rmSync(state.abs, { force: true });
750
676
  return {
751
677
  ok: true,
@@ -822,9 +748,9 @@ function firstLineOf(text) {
822
748
  async function resolveConflict(ctx, input) {
823
749
  const conflict = parseConflictFile(ctx.repoRoot, input.item_id);
824
750
  if (conflict === null) {
825
- return mcpError("FILE_NOT_FOUND", `no conflict file for item_id=${input.item_id} (expected .cairn/ground/conflicts/${input.item_id}.md)`);
751
+ return mcpError("FILE_NOT_FOUND", `no conflict file for item_id=${input.item_id}`);
826
752
  }
827
- return withWriteLock(ctx.repoRoot, () => {
753
+ return withWriteLock(ctx.repoRoot, async () => {
828
754
  const winner = input.choice === "a" ? conflict.aRef : conflict.bRef;
829
755
  const loser = input.choice === "a" ? conflict.bRef : conflict.aRef;
830
756
  if (input.choice === "a" || input.choice === "b") {
@@ -832,7 +758,7 @@ async function resolveConflict(ctx, input) {
832
758
  const winnerOk = setSupersedes(loser, winner);
833
759
  const loserOk = setSupersededBy(ctx.repoRoot, loser, winner.id, "superseded");
834
760
  if (!winnerOk || !loserOk) {
835
- return mcpError("VALIDATION_FAILED", `conflict resolution failed: missing entity (winner=${winnerOk ? "ok" : "missing"}, loser=${loserOk ? "ok" : "missing"})`);
761
+ return mcpError("VALIDATION_FAILED", `conflict resolution failed: missing entity`);
836
762
  }
837
763
  recordOrphanDriftEvents(ctx.repoRoot, [{ ref: loser, parsed: loserBefore }]);
838
764
  deleteConflictFile(conflict);
@@ -850,7 +776,7 @@ async function resolveConflict(ctx, input) {
850
776
  });
851
777
  }
852
778
  catch {
853
- /* best-effort */
779
+ /* ignore */
854
780
  }
855
781
  return {
856
782
  ok: true,
@@ -895,7 +821,7 @@ async function resolveConflict(ctx, input) {
895
821
  });
896
822
  }
897
823
  catch {
898
- /* best-effort */
824
+ /* ignore */
899
825
  }
900
826
  return {
901
827
  ok: true,
@@ -908,11 +834,11 @@ async function resolveConflict(ctx, input) {
908
834
  ...(input.rationale !== undefined ? { rationale: input.rationale } : {}),
909
835
  };
910
836
  }
911
- // choice === "d" — archive both. Conflict file moves to _archived/.
837
+ // choice === "d" — archive both.
912
838
  const aBefore = readEntity(conflict.aRef);
913
839
  const bBefore = readEntity(conflict.bRef);
914
- const aOk = setSupersededBy(ctx.repoRoot, conflict.aRef, conflict.bRef.id, "archived");
915
- const bOk = setSupersededBy(ctx.repoRoot, conflict.bRef, conflict.aRef.id, "archived");
840
+ setSupersededBy(ctx.repoRoot, conflict.aRef, conflict.bRef.id, "archived");
841
+ setSupersededBy(ctx.repoRoot, conflict.bRef, conflict.aRef.id, "archived");
916
842
  recordOrphanDriftEvents(ctx.repoRoot, [
917
843
  { ref: conflict.aRef, parsed: aBefore },
918
844
  { ref: conflict.bRef, parsed: bBefore },
@@ -938,10 +864,7 @@ async function resolveConflict(ctx, input) {
938
864
  });
939
865
  }
940
866
  catch {
941
- /* best-effort */
942
- }
943
- if (!aOk || !bOk) {
944
- log.warn({ aOk, bOk, item_id: input.item_id }, "archive-both: one or both entities missing on disk");
867
+ /* ignore */
945
868
  }
946
869
  return {
947
870
  ok: true,
@@ -959,13 +882,10 @@ function mergeConflict(repoRoot, conflict, rationale) {
959
882
  const b = readEntity(conflict.bRef);
960
883
  if (a === null || b === null) {
961
884
  return {
962
- error: mcpError("VALIDATION_FAILED", `merge requires both entities present on disk (a=${a !== null}, b=${b !== null})`),
885
+ error: mcpError("VALIDATION_FAILED", `merge requires both entities present on disk`),
963
886
  };
964
887
  }
965
888
  const now = new Date().toISOString();
966
- // Merged entity inherits the kind of A (the freshly captured side).
967
- // Mixed DEC/INV merges produce a DEC by convention — the merged
968
- // entity carries combined narrative, not a single hard constraint.
969
889
  const mergedKind = conflict.aRef.kind === "INV" && conflict.bRef.kind === "INV" ? "INV" : "DEC";
970
890
  const mergedId = synthesizeMergedId(repoRoot, mergedKind);
971
891
  const mergedRel = mergedKind === "DEC"
@@ -1013,20 +933,12 @@ function mergeConflict(repoRoot, conflict, rationale) {
1013
933
  mergedFm["decided_by"] = "cairn-conflict-merge";
1014
934
  }
1015
935
  writeFileSafe(mergedAbs, `---\n${stringifyYaml(mergedFm).trimEnd()}\n---\n${mergedBody}`);
1016
- // Both old entries get superseded_by → new merged id.
1017
936
  setSupersededBy(repoRoot, conflict.aRef, mergedId, "superseded");
1018
937
  setSupersededBy(repoRoot, conflict.bRef, mergedId, "superseded");
1019
- // Bind + cache the merged entity so Layer A picks it up on the next
1020
- // PostToolUse without waiting for SessionStart drain.
1021
938
  bindAndCacheMergedEntity(repoRoot, mergedId, mergedBody);
1022
939
  return { mergedId, mergedRel };
1023
940
  }
1024
941
  function synthesizeMergedId(repoRoot, kind) {
1025
- // Content-addressed style — derive from the timestamp + a counter so
1026
- // re-runs in the same millisecond don't collide. We don't have the
1027
- // verbatim merged-body hash easily reachable here without circular
1028
- // dependencies; the timestamp gives us a stable-enough seed since
1029
- // merges are operator-driven and infrequent.
1030
942
  const dir = kind === "DEC" ? decisionsDir(repoRoot) : invariantsDir(repoRoot);
1031
943
  const existing = new Set();
1032
944
  if (existsSync(dir)) {
@@ -1038,7 +950,7 @@ function synthesizeMergedId(repoRoot, kind) {
1038
950
  }
1039
951
  }
1040
952
  catch {
1041
- /* best-effort */
953
+ /* ignore */
1042
954
  }
1043
955
  }
1044
956
  const seed = `merge-${Date.now()}-${Math.floor(Math.random() * 1_000_000)}`;
@@ -1054,17 +966,11 @@ function hashHex(input) {
1054
966
  return createHash("sha256").update(input, "utf8").digest("hex");
1055
967
  }
1056
968
  function resolveInvalidationEvent(_ctx, input) {
1057
- // Per spec §7: A=refresh, B=continue-under-old, C=abort. The marker
1058
- // stamping + scope refresh happens in the calling skill, since it
1059
- // owns the session id. This tool just acknowledges the resolution
1060
- // so the skill can record it.
1061
969
  const map = {
1062
970
  a: "refresh",
1063
971
  b: "continue_under_old",
1064
972
  c: "abort",
1065
973
  };
1066
- // The "d" slot is filtered out for non-conflict kinds in the top
1067
- // dispatcher, so this cast is safe.
1068
974
  const choice = input.choice;
1069
975
  return Promise.resolve({
1070
976
  ok: true,
@@ -1074,12 +980,6 @@ function resolveInvalidationEvent(_ctx, input) {
1074
980
  });
1075
981
  }
1076
982
  function promoteDraftStatus(body) {
1077
- // Frontmatter `status: draft*` → `status: accepted`. Best-effort
1078
- // regex — covers every draft marker the init pipeline emits:
1079
- // - `draft` (legacy / generic)
1080
- // - `draft-from-init-docs` (phase 6)
1081
- // - `draft-from-source-comment` (phase 7b)
1082
- // - `draft-from-rules-merge` (phase 7c)
1083
983
  return body.replace(/^status:\s*draft(?:-from-[a-z-]+)?\b/m, "status: accepted");
1084
984
  }
1085
985
  function emitEvent(ctx, kind, decId, path) {