@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,186 +0,0 @@
1
- /**
2
- * runDecisionCapture — orchestrates the full flow:
3
- *
4
- * raw_text → extract → write draft → adapter dialog 🟢/🟡/🔴
5
- * ├── 🟢 commit → acceptDraft → ledger
6
- * ├── 🟡 edit → leave draft + return correction text
7
- * └── 🔴 reject → rejectDraft → no record
8
- *
9
- * The dialog is supplied by the caller (typically a FrontendAdapter's
10
- * requestDialog) so this entry point works equally well in tests with the
11
- * stub adapter, in CLI with a TTY prompt, and in Discord with the real
12
- * adapter.
13
- */
14
- import { logger } from "../logger.js";
15
- import { runDecisionExtractor } from "./extractor.js";
16
- import { allocateDecisionId } from "./id.js";
17
- import { acceptDraft, rejectDraft, writeDecisionDraft, } from "./writer.js";
18
- import { runDecisionRefinement, } from "./refinement.js";
19
- const log = logger("decision-capture");
20
- const CHOICE_COMMIT = "a";
21
- const CHOICE_EDIT = "b";
22
- const CHOICE_REJECT = "c";
23
- export async function runDecisionCapture(args) {
24
- const startedAt = Date.now();
25
- const tier = args.tier ?? "haiku";
26
- const receivedAt = args.receivedAt ?? new Date().toISOString();
27
- const extract = args.extractorOverride ?? runDecisionExtractor;
28
- const extractorResult = await extract({
29
- raw_text: args.rawText,
30
- author_id: args.authorId,
31
- received_at: receivedAt,
32
- source: args.source,
33
- tier,
34
- });
35
- if (extractorResult.output.not_a_decision) {
36
- log.info({ source: args.source, author: args.authorId }, "decision-extractor flagged not_a_decision — short-circuiting");
37
- return {
38
- short_circuited: true,
39
- duration_ms: Date.now() - startedAt,
40
- };
41
- }
42
- const id = allocateDecisionId(args.repoRoot);
43
- const draft = writeDecisionDraft({
44
- repoRoot: args.repoRoot,
45
- id,
46
- output: extractorResult.output,
47
- rawText: args.rawText,
48
- authorId: args.authorId,
49
- receivedAt,
50
- source: args.source,
51
- });
52
- log.info({ id, draft_path: draft.draft_path, confidence: extractorResult.output.confidence_signal }, "draft written; awaiting confirm");
53
- const decision = await promptConfirm({
54
- adapter: args.adapter,
55
- draft,
56
- ...(args.channelId !== undefined ? { channelId: args.channelId } : {}),
57
- timeoutMs: args.confirmTimeoutMs ?? 60_000,
58
- });
59
- if (decision.decision === "commit") {
60
- const accepted = acceptDraft({ repoRoot: args.repoRoot, draft });
61
- log.info({ id, accepted_path: accepted.acceptedPath, ledger_size: accepted.ledgerSize }, "draft accepted; ledger regenerated");
62
- let refinement;
63
- const hasCandidates = extractorResult.output.candidate_assertions.length > 0;
64
- if (!args.bypassRefinement && hasCandidates) {
65
- try {
66
- refinement = await runDecisionRefinement({
67
- repoRoot: args.repoRoot,
68
- decisionId: id,
69
- adapter: args.adapter,
70
- ...(args.channelId !== undefined ? { channelId: args.channelId } : {}),
71
- tier: args.refinementTier ?? tier,
72
- ...(args.refinementDialogTimeoutMs !== undefined
73
- ? { dialogTimeoutMs: args.refinementDialogTimeoutMs }
74
- : {}),
75
- ...(args.refinementProposerOverride !== undefined
76
- ? { proposerOverride: args.refinementProposerOverride }
77
- : {}),
78
- });
79
- log.info({
80
- id,
81
- operator_choice: refinement.operator_choice,
82
- lifted: refinement.lifted_count,
83
- demoted: refinement.demoted_count,
84
- kept_candidate: refinement.skipped_count,
85
- }, "refinement complete");
86
- }
87
- catch (err) {
88
- // Refinement failure must NEVER roll back the accept. Log and move
89
- // on; candidates stay loose under candidate_assertions: for the
90
- // operator's next refine pass.
91
- log.error({ err: String(err), id }, "refinement threw — accept stands; candidates remain loose");
92
- }
93
- }
94
- return {
95
- short_circuited: false,
96
- draft,
97
- confirm: {
98
- decision: "commit",
99
- accepted_path: accepted.acceptedPath,
100
- ledger_size: accepted.ledgerSize,
101
- draft,
102
- confidence: extractorResult.output.confidence_signal,
103
- },
104
- ...(refinement !== undefined ? { refinement } : {}),
105
- duration_ms: Date.now() - startedAt,
106
- };
107
- }
108
- if (decision.decision === "edit") {
109
- log.info({ id, correction: decision.correction?.slice(0, 120) }, "draft edit requested");
110
- return {
111
- short_circuited: false,
112
- draft,
113
- confirm: {
114
- decision: "edit",
115
- draft,
116
- ...(decision.correction !== undefined ? { correction: decision.correction } : {}),
117
- confidence: extractorResult.output.confidence_signal,
118
- },
119
- duration_ms: Date.now() - startedAt,
120
- };
121
- }
122
- // reject
123
- rejectDraft({ repoRoot: args.repoRoot, draft });
124
- log.info({ id }, "draft rejected; file removed");
125
- return {
126
- short_circuited: false,
127
- draft,
128
- confirm: {
129
- decision: "reject",
130
- draft,
131
- confidence: extractorResult.output.confidence_signal,
132
- },
133
- duration_ms: Date.now() - startedAt,
134
- };
135
- }
136
- async function promptConfirm(args) {
137
- const summary = args.draft.output.summary.split(/\r?\n/).slice(0, 3).join(" ").trim();
138
- const scope = args.draft.output.scope_globs.length > 0
139
- ? args.draft.output.scope_globs.join(", ")
140
- : "(no scope captured)";
141
- const supersedes = args.draft.output.supersedes
142
- ? `Supersedes ${args.draft.output.supersedes}. `
143
- : "";
144
- const assertions = args.draft.output.candidate_assertions.length;
145
- const prompt = [
146
- `Confirm ${args.draft.id}? "${args.draft.output.subject}"`,
147
- summary,
148
- `Scope: ${scope}`,
149
- `${supersedes}Candidate assertions: ${assertions}`,
150
- ].join("\n");
151
- const dialogSpec = {
152
- bundleId: args.draft.id,
153
- prompt,
154
- choices: [
155
- { id: CHOICE_COMMIT, label: "🟢 commit" },
156
- { id: CHOICE_EDIT, label: "🟡 edit" },
157
- { id: CHOICE_REJECT, label: "🔴 not a decision" },
158
- { id: "e_other", label: "E) Other" },
159
- ],
160
- timeoutMs: args.timeoutMs,
161
- };
162
- if (args.channelId !== undefined)
163
- dialogSpec.channelId = args.channelId;
164
- const response = await args.adapter.requestDialog(dialogSpec);
165
- if (response.timedOut) {
166
- // Timeout = treat as edit-with-no-correction so the draft survives in
167
- // _inbox/ and the operator can come back to it. This avoids losing the
168
- // capture on a transient inattentiveness.
169
- return { decision: "edit" };
170
- }
171
- if (response.choiceId === CHOICE_COMMIT) {
172
- return { decision: "commit" };
173
- }
174
- if (response.choiceId === CHOICE_REJECT) {
175
- return { decision: "reject" };
176
- }
177
- if (response.choiceId === CHOICE_EDIT || response.choiceId === "e_other") {
178
- return {
179
- decision: "edit",
180
- ...(response.freeText !== undefined ? { correction: response.freeText } : {}),
181
- };
182
- }
183
- // Unknown id — fall back to edit (preserve the draft).
184
- return { decision: "edit" };
185
- }
186
- //# sourceMappingURL=capture.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"capture.js","sourceRoot":"","sources":["../../src/decision-capture/capture.ts"],"names":[],"mappings":"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"}
@@ -1,20 +0,0 @@
1
- /**
2
- * Decision-extractor runner.
3
- *
4
- * Single Tier-1 (Haiku) call by default per workflow.md
5
- * `decision_extractor: 1`. Output is gated by `--json-schema`. The wrapper
6
- * validates shape via a runtime guard and returns the typed payload.
7
- *
8
- * The runner does NOT touch the filesystem. It returns the extractor's
9
- * structured output; the writer + confirm flow handle persistence.
10
- */
11
- import type { DecisionExtractorInput, DecisionExtractorOutput } from "./types.js";
12
- export interface ExtractorResult {
13
- output: DecisionExtractorOutput;
14
- duration_ms: number;
15
- usage?: {
16
- input_tokens?: number;
17
- output_tokens?: number;
18
- };
19
- }
20
- export declare function runDecisionExtractor(input: DecisionExtractorInput): Promise<ExtractorResult>;
@@ -1,103 +0,0 @@
1
- /**
2
- * Decision-extractor runner.
3
- *
4
- * Single Tier-1 (Haiku) call by default per workflow.md
5
- * `decision_extractor: 1`. Output is gated by `--json-schema`. The wrapper
6
- * validates shape via a runtime guard and returns the typed payload.
7
- *
8
- * The runner does NOT touch the filesystem. It returns the extractor's
9
- * structured output; the writer + confirm flow handle persistence.
10
- */
11
- import { runClaude } from "../claude/index.js";
12
- import { logger } from "../logger.js";
13
- import { DECISION_EXTRACTOR_SYSTEM_PROMPT, buildDecisionExtractorUserPrompt, } from "./prompt.js";
14
- import { DECISION_EXTRACTOR_OUTPUT_SCHEMA } from "./schema.js";
15
- const log = logger("decision-capture.extractor");
16
- export async function runDecisionExtractor(input) {
17
- const userPrompt = buildDecisionExtractorUserPrompt(input);
18
- log.info({
19
- tier: input.tier,
20
- raw_text_len: input.raw_text.length,
21
- accepted_decisions: input.accepted_decisions?.length ?? 0,
22
- }, "decision-extractor dispatch");
23
- const result = await runClaude({
24
- tier: input.tier,
25
- prompt: userPrompt,
26
- system: DECISION_EXTRACTOR_SYSTEM_PROMPT,
27
- jsonSchema: DECISION_EXTRACTOR_OUTPUT_SCHEMA,
28
- timeoutMs: input.timeout_ms ?? 120_000,
29
- });
30
- if (!isOutput(result.parsed)) {
31
- throw new Error(`decision-extractor returned malformed output. preview: ${result.text.slice(0, 200)}`);
32
- }
33
- const output = result.parsed;
34
- log.info({
35
- not_a_decision: output.not_a_decision,
36
- subject_preview: output.subject.slice(0, 80),
37
- assertions: output.candidate_assertions.length,
38
- confidence: output.confidence_signal,
39
- duration_ms: result.durationMs,
40
- }, "decision-extractor complete");
41
- return {
42
- output,
43
- duration_ms: result.durationMs,
44
- ...(result.usage !== undefined
45
- ? {
46
- usage: {
47
- ...(result.usage["input_tokens"] !== undefined
48
- ? { input_tokens: result.usage["input_tokens"] }
49
- : {}),
50
- ...(result.usage["output_tokens"] !== undefined
51
- ? { output_tokens: result.usage["output_tokens"] }
52
- : {}),
53
- },
54
- }
55
- : {}),
56
- };
57
- }
58
- function isOutput(value) {
59
- if (typeof value !== "object" || value === null)
60
- return false;
61
- const v = value;
62
- if (typeof v["subject"] !== "string")
63
- return false;
64
- if (typeof v["summary"] !== "string")
65
- return false;
66
- if (!Array.isArray(v["scope_globs"]))
67
- return false;
68
- for (const g of v["scope_globs"]) {
69
- if (typeof g !== "string")
70
- return false;
71
- }
72
- const supersedes = v["supersedes"];
73
- if (supersedes !== undefined &&
74
- supersedes !== null &&
75
- typeof supersedes !== "string") {
76
- return false;
77
- }
78
- if (!Array.isArray(v["candidate_assertions"]))
79
- return false;
80
- for (const a of v["candidate_assertions"]) {
81
- if (!isCandidateAssertion(a))
82
- return false;
83
- }
84
- if (v["confidence_signal"] !== "high" &&
85
- v["confidence_signal"] !== "medium" &&
86
- v["confidence_signal"] !== "low") {
87
- return false;
88
- }
89
- if (typeof v["not_a_decision"] !== "boolean")
90
- return false;
91
- return true;
92
- }
93
- function isCandidateAssertion(value) {
94
- if (typeof value !== "object" || value === null)
95
- return false;
96
- const v = value;
97
- if (typeof v["kind"] !== "string")
98
- return false;
99
- if (typeof v["description"] !== "string")
100
- return false;
101
- return true;
102
- }
103
- //# sourceMappingURL=extractor.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"extractor.js","sourceRoot":"","sources":["../../src/decision-capture/extractor.ts"],"names":[],"mappings":"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"}
@@ -1,15 +0,0 @@
1
- /**
2
- * Decision-extractor prompts.
3
- *
4
- * Operator submits a direction (slash arg or free-text classified as
5
- * `direction`). The extractor distills it into a typed candidate the
6
- * cairn materializes into a draft decision.
7
- *
8
- * Anti-fabrication framing: when the input isn't actually a direction
9
- * (rambling, off-topic, a question), the extractor sets
10
- * `not_a_decision=true` and the cairn short-circuits without writing a
11
- * draft. This keeps the decisions ledger free of noise.
12
- */
13
- import type { DecisionExtractorInput } from "./types.js";
14
- export declare const DECISION_EXTRACTOR_SYSTEM_PROMPT = "You are the **decision-extractor** for an agent cairn. The operator just spoke a direction \u2014 a binding course-change like \"from now on, X\" or \"scrap that, go with Y\" or \"user_id always required on integration tables\". Your job is to capture it as a typed candidate decision so the cairn can present it for confirmation.\n\nYou read three things:\n1. The raw direction text the operator submitted.\n2. Author / source / received-at metadata for the audit record.\n3. (Optional) A short list of currently-accepted decisions so you can spot supersedes relationships.\n\nYou emit a single JSON object matching the supplied schema. Required fields:\n\n- `subject`: imperative one-line title. Example: \"Filter integration_oauth_tokens queries by user_id\".\n- `summary`: 2-4 sentence paragraph expanding the subject. Capture the *what* and the *why* as the operator stated them \u2014 do NOT invent rationale they didn't give.\n- `scope_globs`: repo-relative globs the decision binds. Be specific. `[\"core/src/integrations/**/*.ts\"]` is good; `[\"**/*.ts\"]` is almost always wrong. When you genuinely can't tell, emit `[]` and let the operator narrow at confirm time.\n- `supersedes`: if the input EXPLICITLY revokes a previously-accepted decision (`scrap DEC-0042`, `undo the FK denorm rule`), set the DEC-id. Otherwise null/omit.\n- `candidate_assertions`: 0-3 mechanical-sensor checks that would enforce the decision going forward. Pick the kind from the schema enum that fits. ZERO is a valid answer when the rule is purely conceptual \u2014 better than fabricating an assertion that can't actually be verified.\n- `confidence_signal`: `high` when the direction is unambiguous + scope is obvious; `medium` when one of those is shaky; `low` when both are.\n- `not_a_decision`: set TRUE if the input is rambling, off-topic, a question rather than a directive, or otherwise lacks a binding rule. The cairn will short-circuit without writing a draft. When in doubt, set true \u2014 false-positive drafts pollute the ledger; false-negatives are recoverable via re-submission.\n\nExamples of inputs that should map to `not_a_decision: true`:\n- \"what's the status?\"\n- \"I'm thinking about switching to FK denorm but not sure\" \u2190 thinking-out-loud, not yet binding\n- \"lol\"\n- \"remind me about Phase 12\"\n\nExamples that should map to `not_a_decision: false`:\n- \"scrap that \u2014 going forward, FK denormalization only\" \u2190 supersedes implicit\n- \"all integration_oauth_tokens queries must filter by user_id\" \u2190 clear assertion candidate\n- \"from now on, no new code in core/src/legacy\" \u2190 scope_globs + file_must_not_be_modified\n\nYour candidate_assertions are *proposals* \u2014 the operator gets one more chance to edit them at the confirm dialog. Don't over-commit; aim for the smallest set of assertions that mechanically captures the binding behavior, not every implication.\n\nOutput ONLY the JSON object. No prose, no code fences, no other content.";
15
- export declare function buildDecisionExtractorUserPrompt(input: DecisionExtractorInput): string;
@@ -1,68 +0,0 @@
1
- /**
2
- * Decision-extractor prompts.
3
- *
4
- * Operator submits a direction (slash arg or free-text classified as
5
- * `direction`). The extractor distills it into a typed candidate the
6
- * cairn materializes into a draft decision.
7
- *
8
- * Anti-fabrication framing: when the input isn't actually a direction
9
- * (rambling, off-topic, a question), the extractor sets
10
- * `not_a_decision=true` and the cairn short-circuits without writing a
11
- * draft. This keeps the decisions ledger free of noise.
12
- */
13
- const PER_DIRECTION_CHAR_CAP = 6_000;
14
- export const DECISION_EXTRACTOR_SYSTEM_PROMPT = `You are the **decision-extractor** for an agent cairn. The operator just spoke a direction — a binding course-change like "from now on, X" or "scrap that, go with Y" or "user_id always required on integration tables". Your job is to capture it as a typed candidate decision so the cairn can present it for confirmation.
15
-
16
- You read three things:
17
- 1. The raw direction text the operator submitted.
18
- 2. Author / source / received-at metadata for the audit record.
19
- 3. (Optional) A short list of currently-accepted decisions so you can spot supersedes relationships.
20
-
21
- You emit a single JSON object matching the supplied schema. Required fields:
22
-
23
- - \`subject\`: imperative one-line title. Example: "Filter integration_oauth_tokens queries by user_id".
24
- - \`summary\`: 2-4 sentence paragraph expanding the subject. Capture the *what* and the *why* as the operator stated them — do NOT invent rationale they didn't give.
25
- - \`scope_globs\`: repo-relative globs the decision binds. Be specific. \`["core/src/integrations/**/*.ts"]\` is good; \`["**/*.ts"]\` is almost always wrong. When you genuinely can't tell, emit \`[]\` and let the operator narrow at confirm time.
26
- - \`supersedes\`: if the input EXPLICITLY revokes a previously-accepted decision (\`scrap DEC-0042\`, \`undo the FK denorm rule\`), set the DEC-id. Otherwise null/omit.
27
- - \`candidate_assertions\`: 0-3 mechanical-sensor checks that would enforce the decision going forward. Pick the kind from the schema enum that fits. ZERO is a valid answer when the rule is purely conceptual — better than fabricating an assertion that can't actually be verified.
28
- - \`confidence_signal\`: \`high\` when the direction is unambiguous + scope is obvious; \`medium\` when one of those is shaky; \`low\` when both are.
29
- - \`not_a_decision\`: set TRUE if the input is rambling, off-topic, a question rather than a directive, or otherwise lacks a binding rule. The cairn will short-circuit without writing a draft. When in doubt, set true — false-positive drafts pollute the ledger; false-negatives are recoverable via re-submission.
30
-
31
- Examples of inputs that should map to \`not_a_decision: true\`:
32
- - "what's the status?"
33
- - "I'm thinking about switching to FK denorm but not sure" ← thinking-out-loud, not yet binding
34
- - "lol"
35
- - "remind me about Phase 12"
36
-
37
- Examples that should map to \`not_a_decision: false\`:
38
- - "scrap that — going forward, FK denormalization only" ← supersedes implicit
39
- - "all integration_oauth_tokens queries must filter by user_id" ← clear assertion candidate
40
- - "from now on, no new code in core/src/legacy" ← scope_globs + file_must_not_be_modified
41
-
42
- Your candidate_assertions are *proposals* — the operator gets one more chance to edit them at the confirm dialog. Don't over-commit; aim for the smallest set of assertions that mechanically captures the binding behavior, not every implication.
43
-
44
- Output ONLY the JSON object. No prose, no code fences, no other content.`;
45
- export function buildDecisionExtractorUserPrompt(input) {
46
- const sections = [];
47
- sections.push("## Raw direction text");
48
- const text = input.raw_text.trim();
49
- sections.push(text.length > PER_DIRECTION_CHAR_CAP
50
- ? text.slice(0, PER_DIRECTION_CHAR_CAP) +
51
- `\n…[truncated; ${text.length - PER_DIRECTION_CHAR_CAP} chars elided]`
52
- : text);
53
- sections.push("\n## Metadata");
54
- sections.push(`author: ${input.author_id}`);
55
- sections.push(`source: ${input.source}`);
56
- sections.push(`received_at: ${input.received_at}`);
57
- if (input.accepted_decisions && input.accepted_decisions.length > 0) {
58
- sections.push("\n## Currently-accepted decisions (most recent first)");
59
- for (const d of input.accepted_decisions.slice(0, 10)) {
60
- sections.push(`- **${d.id}** — ${d.title} (${d.scope_summary})`);
61
- }
62
- sections.push("\nIf the new direction explicitly revokes one of these, set `supersedes` to its id.");
63
- }
64
- sections.push("\n## Your task");
65
- sections.push("Extract the decision per the schema. Emit ONLY the JSON object.");
66
- return sections.join("\n");
67
- }
68
- //# sourceMappingURL=prompt.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"prompt.js","sourceRoot":"","sources":["../../src/decision-capture/prompt.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,MAAM,sBAAsB,GAAG,KAAK,CAAC;AAErC,MAAM,CAAC,MAAM,gCAAgC,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yEA8ByB,CAAC;AAE1E,MAAM,UAAU,gCAAgC,CAC9C,KAA6B;IAE7B,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,QAAQ,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;IACvC,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;IACnC,QAAQ,CAAC,IAAI,CACX,IAAI,CAAC,MAAM,GAAG,sBAAsB;QAClC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,sBAAsB,CAAC;YACnC,kBAAkB,IAAI,CAAC,MAAM,GAAG,sBAAsB,gBAAgB;QAC1E,CAAC,CAAC,IAAI,CACT,CAAC;IAEF,QAAQ,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IAC/B,QAAQ,CAAC,IAAI,CAAC,WAAW,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC;IAC5C,QAAQ,CAAC,IAAI,CAAC,WAAW,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;IACzC,QAAQ,CAAC,IAAI,CAAC,gBAAgB,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC;IAEnD,IAAI,KAAK,CAAC,kBAAkB,IAAI,KAAK,CAAC,kBAAkB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACpE,QAAQ,CAAC,IAAI,CAAC,uDAAuD,CAAC,CAAC;QACvE,KAAK,MAAM,CAAC,IAAI,KAAK,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;YACtD,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,KAAK,MAAM,CAAC,CAAC,aAAa,GAAG,CAAC,CAAC;QACpE,CAAC;QACD,QAAQ,CAAC,IAAI,CACX,qFAAqF,CACtF,CAAC;IACJ,CAAC;IAED,QAAQ,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;IAChC,QAAQ,CAAC,IAAI,CACX,iEAAiE,CAClE,CAAC;IAEF,OAAO,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC7B,CAAC"}
@@ -1,25 +0,0 @@
1
- /**
2
- * Assertion-refiner prompts.
3
- *
4
- * The decision-extractor (Phase 14) emits LOOSE candidate assertions —
5
- * `{kind, description, parameters?}` with `parameters` schema-loose. The
6
- * decision file stores them under frontmatter `candidate_assertions:`,
7
- * NOT under `assertions:` which Layer-D sensors enforce.
8
- *
9
- * The refiner's job is to lift each candidate into a STRICT shape that
10
- * matches one of the eleven `DecisionAssertion` kinds (see
11
- * `src/ground/schemas.ts`). When a candidate is too vague to form
12
- * confident strict params, the refiner DEMOTES it to
13
- * `human_review_hint` (always soft, always passes zod). When the
14
- * candidate description is sound but the strict params would need
15
- * operator input the refiner can't infer, it SKIPS — the candidate
16
- * survives in `candidate_assertions:` for the next refine pass.
17
- *
18
- * Anti-fabrication framing: prefer demote / skip over inventing wrong
19
- * regex / globs / table names. A wrong assertion is a sensor that fires
20
- * on every PR forever; a `human_review_hint` is at worst noise in the
21
- * reviewer's pre-amble.
22
- */
23
- import type { RefinerInput } from "./types.js";
24
- export declare const REFINEMENT_PROPOSER_SYSTEM_PROMPT = "You are the **assertion-refiner** for an agent cairn. The operator just confirmed a binding decision; the decision-extractor proposed N loose candidate assertions to enforce it. Your job is to lift each candidate into the STRICT shape used by the cairn's mechanical sensors, OR demote / skip it.\n\n## The eleven assertion kinds\n\nEach kind requires specific fields. The cairn's zod re-validates at apply time; a malformed `strict_assertion` is auto-demoted, so don't fudge \u2014 when you don't have a confident value for a required field, set status=\"demote\" or status=\"skip\" instead.\n\n- **schema_must_contain** \u2014 { table: string, column: string, column_type?: string, nullable?: boolean }\n Migration / schema rule. Example: \"tokens table must have user_id column NOT NULL\".\n\n- **text_must_match** \u2014 { pattern: string (JS regex source), in_globs: string[] }\n Some text must appear in matching files. Example: license header in src/**/*.ts.\n\n- **text_must_not_match** \u2014 { pattern: string, in_globs: string[] }\n Some text must NOT appear. Example: \"no `process.env.` access in src/**/*.ts\".\n\n- **index_must_exist** \u2014 { table: string, columns: string[], where?: string }\n Database index. Example: \"(provider, user_id) WHERE archived_at IS NULL on tokens\".\n\n- **ast_pattern** \u2014 { language: string (\"ts\"|\"py\"|\"go\"|...), pattern: string (regex fallback), in_globs: string[] }\n Structural pattern. Example: \"all controllers extend BaseController\".\n\n- **file_must_not_be_modified** \u2014 { path: string }\n Frozen file. Example: \"core/src/legacy/billing.ts\".\n\n- **query_must_filter_by** \u2014 { orm: string (\"drizzle\"|\"prisma\"|\"sqlalchemy\"|...), in_globs: string[], table: string, columns: string[], operator: \"eq\"|\"in\"|\"between\"|\"is_not_null\", require_combination: \"and\"|\"or\" }\n ORM-level scope. Example: \"all integration_oauth_tokens queries filter by user_id eq AND provider eq\".\n\n- **route_must_have_guard** \u2014 { in_globs: string[], guard: string, require_on: string[] }\n HTTP guard. Example: \"all routes in api/*/admin.ts have RequireRole guard, require_on: [GET, POST]\".\n\n- **event_must_emit** \u2014 { in_globs: string[], after_method: string, event_key: string, payload_must_include?: string[] }\n Event emission. Example: \"after createInvoice() emit invoice.created with [invoice_id, user_id]\".\n\n- **service_method_must_call** \u2014 { in_globs: string[], in_method: string, must_call: string, before_returning?: boolean }\n Required call inside method. Example: \"in TokenService.refresh(), must call audit.log() before returning\".\n\n- **human_review_hint** \u2014 { description: string }\n Always-soft fallback. Use this for purely conceptual rules (\"prefer simple solutions\", \"avoid magic numbers in pricing logic\").\n\n## Per-candidate verdict\n\nFor each candidate, emit one proposal:\n\n```\n{\n candidate_id: <as given>,\n candidate_kind: <as given>,\n status: \"lift\" | \"demote\" | \"skip\",\n confidence_signal: \"high\" | \"medium\" | \"low\",\n strict_assertion?: { ... } // present iff status=\"lift\"\n rationale: \"one sentence explaining the choice\"\n}\n```\n\n### When to LIFT\n\nYou are confident on every required field for the candidate's kind. The description gave you concrete table / file / regex / glob names, and the decision's scope_globs lets you narrow the in_globs reasonably.\n\nIf the candidate kind is **human_review_hint**, ALWAYS lift \u2014 the kind already has a single-field shape. `description` is the candidate's existing description.\n\n### When to DEMOTE\n\nThe candidate description is sound but the strict params would require input you don't have (e.g., \"no env vars\" \u2014 needs the actual regex pattern; \"must filter by user_id\" \u2014 needs the ORM name and table name and you don't know which).\n\nDemote means: rewrite as `human_review_hint` with a description that captures the rule's intent. The operator + reviewer + UAT still see it; sensors don't enforce it. Better than a hallucinated regex that fires on every PR.\n\n### When to SKIP\n\nThe candidate is weakly-specified to the point that even `human_review_hint` would be too vague to be useful (e.g., the operator's description was \"fix the thing\", the kind doesn't match the description, etc.). Skip leaves it under `candidate_assertions:` for a future refine pass.\n\n## Confidence\n\n- `high`: required fields are explicit in the candidate description. No guesses.\n- `medium`: most fields present, one or two reasonable inferences from scope_globs / decision summary.\n- `low`: status=\"lift\" with low confidence is a defect. Use status=\"demote\" or \"skip\" instead.\n\n## Output\n\nEmit ONLY the JSON object: `{ \"proposals\": [...] }`. One proposal per input candidate, in the order given. No prose, no code fences.";
25
- export declare function buildRefinementProposerUserPrompt(input: RefinerInput): string;
@@ -1,146 +0,0 @@
1
- /**
2
- * Assertion-refiner prompts.
3
- *
4
- * The decision-extractor (Phase 14) emits LOOSE candidate assertions —
5
- * `{kind, description, parameters?}` with `parameters` schema-loose. The
6
- * decision file stores them under frontmatter `candidate_assertions:`,
7
- * NOT under `assertions:` which Layer-D sensors enforce.
8
- *
9
- * The refiner's job is to lift each candidate into a STRICT shape that
10
- * matches one of the eleven `DecisionAssertion` kinds (see
11
- * `src/ground/schemas.ts`). When a candidate is too vague to form
12
- * confident strict params, the refiner DEMOTES it to
13
- * `human_review_hint` (always soft, always passes zod). When the
14
- * candidate description is sound but the strict params would need
15
- * operator input the refiner can't infer, it SKIPS — the candidate
16
- * survives in `candidate_assertions:` for the next refine pass.
17
- *
18
- * Anti-fabrication framing: prefer demote / skip over inventing wrong
19
- * regex / globs / table names. A wrong assertion is a sensor that fires
20
- * on every PR forever; a `human_review_hint` is at worst noise in the
21
- * reviewer's pre-amble.
22
- */
23
- const PER_DECISION_CHAR_CAP = 4_000;
24
- export const REFINEMENT_PROPOSER_SYSTEM_PROMPT = `You are the **assertion-refiner** for an agent cairn. The operator just confirmed a binding decision; the decision-extractor proposed N loose candidate assertions to enforce it. Your job is to lift each candidate into the STRICT shape used by the cairn's mechanical sensors, OR demote / skip it.
25
-
26
- ## The eleven assertion kinds
27
-
28
- Each kind requires specific fields. The cairn's zod re-validates at apply time; a malformed \`strict_assertion\` is auto-demoted, so don't fudge — when you don't have a confident value for a required field, set status="demote" or status="skip" instead.
29
-
30
- - **schema_must_contain** — { table: string, column: string, column_type?: string, nullable?: boolean }
31
- Migration / schema rule. Example: "tokens table must have user_id column NOT NULL".
32
-
33
- - **text_must_match** — { pattern: string (JS regex source), in_globs: string[] }
34
- Some text must appear in matching files. Example: license header in src/**/*.ts.
35
-
36
- - **text_must_not_match** — { pattern: string, in_globs: string[] }
37
- Some text must NOT appear. Example: "no \`process.env.\` access in src/**/*.ts".
38
-
39
- - **index_must_exist** — { table: string, columns: string[], where?: string }
40
- Database index. Example: "(provider, user_id) WHERE archived_at IS NULL on tokens".
41
-
42
- - **ast_pattern** — { language: string ("ts"|"py"|"go"|...), pattern: string (regex fallback), in_globs: string[] }
43
- Structural pattern. Example: "all controllers extend BaseController".
44
-
45
- - **file_must_not_be_modified** — { path: string }
46
- Frozen file. Example: "core/src/legacy/billing.ts".
47
-
48
- - **query_must_filter_by** — { orm: string ("drizzle"|"prisma"|"sqlalchemy"|...), in_globs: string[], table: string, columns: string[], operator: "eq"|"in"|"between"|"is_not_null", require_combination: "and"|"or" }
49
- ORM-level scope. Example: "all integration_oauth_tokens queries filter by user_id eq AND provider eq".
50
-
51
- - **route_must_have_guard** — { in_globs: string[], guard: string, require_on: string[] }
52
- HTTP guard. Example: "all routes in api/*/admin.ts have RequireRole guard, require_on: [GET, POST]".
53
-
54
- - **event_must_emit** — { in_globs: string[], after_method: string, event_key: string, payload_must_include?: string[] }
55
- Event emission. Example: "after createInvoice() emit invoice.created with [invoice_id, user_id]".
56
-
57
- - **service_method_must_call** — { in_globs: string[], in_method: string, must_call: string, before_returning?: boolean }
58
- Required call inside method. Example: "in TokenService.refresh(), must call audit.log() before returning".
59
-
60
- - **human_review_hint** — { description: string }
61
- Always-soft fallback. Use this for purely conceptual rules ("prefer simple solutions", "avoid magic numbers in pricing logic").
62
-
63
- ## Per-candidate verdict
64
-
65
- For each candidate, emit one proposal:
66
-
67
- \`\`\`
68
- {
69
- candidate_id: <as given>,
70
- candidate_kind: <as given>,
71
- status: "lift" | "demote" | "skip",
72
- confidence_signal: "high" | "medium" | "low",
73
- strict_assertion?: { ... } // present iff status="lift"
74
- rationale: "one sentence explaining the choice"
75
- }
76
- \`\`\`
77
-
78
- ### When to LIFT
79
-
80
- You are confident on every required field for the candidate's kind. The description gave you concrete table / file / regex / glob names, and the decision's scope_globs lets you narrow the in_globs reasonably.
81
-
82
- If the candidate kind is **human_review_hint**, ALWAYS lift — the kind already has a single-field shape. \`description\` is the candidate's existing description.
83
-
84
- ### When to DEMOTE
85
-
86
- The candidate description is sound but the strict params would require input you don't have (e.g., "no env vars" — needs the actual regex pattern; "must filter by user_id" — needs the ORM name and table name and you don't know which).
87
-
88
- Demote means: rewrite as \`human_review_hint\` with a description that captures the rule's intent. The operator + reviewer + UAT still see it; sensors don't enforce it. Better than a hallucinated regex that fires on every PR.
89
-
90
- ### When to SKIP
91
-
92
- The candidate is weakly-specified to the point that even \`human_review_hint\` would be too vague to be useful (e.g., the operator's description was "fix the thing", the kind doesn't match the description, etc.). Skip leaves it under \`candidate_assertions:\` for a future refine pass.
93
-
94
- ## Confidence
95
-
96
- - \`high\`: required fields are explicit in the candidate description. No guesses.
97
- - \`medium\`: most fields present, one or two reasonable inferences from scope_globs / decision summary.
98
- - \`low\`: status="lift" with low confidence is a defect. Use status="demote" or "skip" instead.
99
-
100
- ## Output
101
-
102
- Emit ONLY the JSON object: \`{ "proposals": [...] }\`. One proposal per input candidate, in the order given. No prose, no code fences.`;
103
- export function buildRefinementProposerUserPrompt(input) {
104
- const sections = [];
105
- sections.push(`## Decision context — ${input.decision_id}`);
106
- sections.push(`subject: ${input.subject}`);
107
- const summary = input.summary.trim();
108
- sections.push("");
109
- sections.push("summary:");
110
- sections.push(summary.length > PER_DECISION_CHAR_CAP
111
- ? summary.slice(0, PER_DECISION_CHAR_CAP) +
112
- `\n…[truncated; ${summary.length - PER_DECISION_CHAR_CAP} chars elided]`
113
- : summary);
114
- if (input.scope_globs.length > 0) {
115
- sections.push("");
116
- sections.push("scope_globs:");
117
- for (const g of input.scope_globs)
118
- sections.push(` - ${g}`);
119
- }
120
- else {
121
- sections.push("");
122
- sections.push("scope_globs: (none — operator left it unspecified)");
123
- }
124
- sections.push("");
125
- sections.push("## Candidates to refine");
126
- for (let i = 0; i < input.candidates.length; i++) {
127
- const c = input.candidates[i];
128
- if (c === undefined)
129
- continue;
130
- const id = c.id ?? `${input.decision_id}-A${(i + 1).toString().padStart(2, "0")}`;
131
- sections.push("");
132
- sections.push(`### ${id} (kind: ${c.kind})`);
133
- sections.push(`description: ${c.description}`);
134
- if (c.parameters && Object.keys(c.parameters).length > 0) {
135
- sections.push("parameters (loose, from extractor):");
136
- sections.push("```json");
137
- sections.push(JSON.stringify(c.parameters, null, 2));
138
- sections.push("```");
139
- }
140
- }
141
- sections.push("");
142
- sections.push("## Your task");
143
- sections.push("Emit one proposal per candidate in the order given. Use the candidate_id values shown above. Output ONLY the JSON object.");
144
- return sections.join("\n");
145
- }
146
- //# sourceMappingURL=refinement-prompt.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"refinement-prompt.js","sourceRoot":"","sources":["../../src/decision-capture/refinement-prompt.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAIH,MAAM,qBAAqB,GAAG,KAAK,CAAC;AAEpC,MAAM,CAAC,MAAM,iCAAiC,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uIA8EsF,CAAC;AAExI,MAAM,UAAU,iCAAiC,CAAC,KAAmB;IACnE,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,QAAQ,CAAC,IAAI,CAAC,yBAAyB,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC;IAC5D,QAAQ,CAAC,IAAI,CAAC,YAAY,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;IAE3C,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;IACrC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAClB,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC1B,QAAQ,CAAC,IAAI,CACX,OAAO,CAAC,MAAM,GAAG,qBAAqB;QACpC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,qBAAqB,CAAC;YACrC,kBAAkB,OAAO,CAAC,MAAM,GAAG,qBAAqB,gBAAgB;QAC5E,CAAC,CAAC,OAAO,CACZ,CAAC;IAEF,IAAI,KAAK,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACjC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAClB,QAAQ,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAC9B,KAAK,MAAM,CAAC,IAAI,KAAK,CAAC,WAAW;YAAE,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC/D,CAAC;SAAM,CAAC;QACN,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAClB,QAAQ,CAAC,IAAI,CAAC,oDAAoD,CAAC,CAAC;IACtE,CAAC;IAED,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAClB,QAAQ,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC;IACzC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACjD,MAAM,CAAC,GAAG,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QAC9B,IAAI,CAAC,KAAK,SAAS;YAAE,SAAS;QAC9B,MAAM,EAAE,GAAG,CAAC,CAAC,EAAE,IAAI,GAAG,KAAK,CAAC,WAAW,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;QAClF,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAClB,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC;QAC9C,QAAQ,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;QAC/C,IAAI,CAAC,CAAC,UAAU,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACzD,QAAQ,CAAC,IAAI,CAAC,qCAAqC,CAAC,CAAC;YACrD,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YACzB,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;YACrD,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACvB,CAAC;IACH,CAAC;IAED,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAClB,QAAQ,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAC9B,QAAQ,CAAC,IAAI,CACX,2HAA2H,CAC5H,CAAC;IAEF,OAAO,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC7B,CAAC"}