@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,42 +1,50 @@
1
- /**
2
- * Render a StatusJson as the single-line string Claude Code's status_line
3
- * hook displays. Pure function; no I/O.
4
- *
5
- * Format: `⬡ cairn decisions:N inv:N <state> <icon>`
6
- *
7
- * <state> reports the most operator-actionable signal: pending attention
8
- * count first (ranks above tasks), GC sweep state second, task state
9
- * last; falls back to "ready" when nothing else is happening.
10
- *
11
- * Health icon:
12
- * attention > 0 → ⚑
13
- * gc running → ◐
14
- * idle / running → ●
15
- */
16
- export function formatStatus(s) {
17
- const parts = ["⬡ cairn"];
18
- parts.push(`decisions:${s.decisions_in_scope}`);
19
- parts.push(`inv:${s.invariants_in_scope}`);
20
- let stateField;
21
- let icon;
1
+ const ANSI_RESET = "\x1b[0m";
2
+ const ANSI_GREEN = "\x1b[32m";
3
+ const ANSI_YELLOW = "\x1b[33m";
4
+ const ANSI_ORANGE = "\x1b[38;5;208m";
5
+ const ANSI_RED = "\x1b[31m";
6
+ function ctxColor(usedTokens) {
7
+ if (usedTokens < 100_000)
8
+ return ANSI_GREEN;
9
+ if (usedTokens < 300_000)
10
+ return ANSI_YELLOW;
11
+ if (usedTokens < 600_000)
12
+ return ANSI_ORANGE;
13
+ return ANSI_RED;
14
+ }
15
+ export function renderCtxMeter(ctx) {
16
+ const pct = Math.max(0, Math.min(100, Math.round(ctx.usedPct)));
17
+ const filled = Math.floor(pct / 10);
18
+ const bar = "█".repeat(filled) + "░".repeat(10 - filled);
19
+ return `${ctxColor(ctx.usedTokens)}${bar} ${pct}%${ANSI_RESET}`;
20
+ }
21
+ function renderSignal(s) {
22
+ if (s.bypass_count > 0)
23
+ return `⚠ ${s.bypass_count} unattested`;
22
24
  if (s.attention_count > 0) {
23
- stateField = `attention:${s.attention_count}`;
24
- icon = "⚑";
25
- }
26
- else if (s.gc_running) {
27
- stateField = "gc:active";
28
- icon = "◐";
25
+ const noun = s.attention_count === 1 ? "draft" : "drafts";
26
+ return `⚑ ${s.attention_count} ${noun}`;
29
27
  }
30
- else if (s.task_state !== "idle") {
31
- stateField = `task:${s.task_state}`;
32
- icon = "";
28
+ if (s.gc_running)
29
+ return "◐ gc";
30
+ if (s.task_state !== "idle") {
31
+ if (s.task_id && s.task_module)
32
+ return `${s.task_id} ${s.task_module}`;
33
+ if (s.task_id)
34
+ return s.task_id;
35
+ if (s.task_module)
36
+ return s.task_module;
37
+ return `task: ${s.task_state}`;
33
38
  }
34
- else {
35
- stateField = "ready";
36
- icon = "●";
37
- }
38
- parts.push(stateField);
39
- parts.push(icon);
39
+ return null;
40
+ }
41
+ export function formatStatus(s, ctx) {
42
+ const parts = ["⬡ cairn"];
43
+ const signal = renderSignal(s);
44
+ if (signal)
45
+ parts.push(signal);
46
+ if (ctx)
47
+ parts.push(renderCtxMeter(ctx));
40
48
  return parts.join(" ");
41
49
  }
42
50
  //# sourceMappingURL=format.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"format.js","sourceRoot":"","sources":["../../src/status-line/format.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,YAAY,CAAC,CAAa;IACxC,MAAM,KAAK,GAAa,CAAC,SAAS,CAAC,CAAC;IAEpC,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,kBAAkB,EAAE,CAAC,CAAC;IAChD,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,mBAAmB,EAAE,CAAC,CAAC;IAE3C,IAAI,UAAkB,CAAC;IACvB,IAAI,IAAY,CAAC;IACjB,IAAI,CAAC,CAAC,eAAe,GAAG,CAAC,EAAE,CAAC;QAC1B,UAAU,GAAG,aAAa,CAAC,CAAC,eAAe,EAAE,CAAC;QAC9C,IAAI,GAAG,GAAG,CAAC;IACb,CAAC;SAAM,IAAI,CAAC,CAAC,UAAU,EAAE,CAAC;QACxB,UAAU,GAAG,WAAW,CAAC;QACzB,IAAI,GAAG,GAAG,CAAC;IACb,CAAC;SAAM,IAAI,CAAC,CAAC,UAAU,KAAK,MAAM,EAAE,CAAC;QACnC,UAAU,GAAG,QAAQ,CAAC,CAAC,UAAU,EAAE,CAAC;QACpC,IAAI,GAAG,GAAG,CAAC;IACb,CAAC;SAAM,CAAC;QACN,UAAU,GAAG,OAAO,CAAC;QACrB,IAAI,GAAG,GAAG,CAAC;IACb,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACvB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAEjB,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
1
+ {"version":3,"file":"format.js","sourceRoot":"","sources":["../../src/status-line/format.ts"],"names":[],"mappings":"AA0BA,MAAM,UAAU,GAAG,SAAS,CAAC;AAC7B,MAAM,UAAU,GAAG,UAAU,CAAC;AAC9B,MAAM,WAAW,GAAG,UAAU,CAAC;AAC/B,MAAM,WAAW,GAAG,gBAAgB,CAAC;AACrC,MAAM,QAAQ,GAAG,UAAU,CAAC;AAE5B,SAAS,QAAQ,CAAC,UAAkB;IAClC,IAAI,UAAU,GAAG,OAAO;QAAE,OAAO,UAAU,CAAC;IAC5C,IAAI,UAAU,GAAG,OAAO;QAAE,OAAO,WAAW,CAAC;IAC7C,IAAI,UAAU,GAAG,OAAO;QAAE,OAAO,WAAW,CAAC;IAC7C,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,GAAkB;IAC/C,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IAChE,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,EAAE,CAAC,CAAC;IACpC,MAAM,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,GAAG,MAAM,CAAC,CAAC;IACzD,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,GAAG,IAAI,GAAG,IAAI,UAAU,EAAE,CAAC;AAClE,CAAC;AAED,SAAS,YAAY,CAAC,CAAa;IACjC,IAAI,CAAC,CAAC,YAAY,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC,CAAC,YAAY,aAAa,CAAC;IAChE,IAAI,CAAC,CAAC,eAAe,GAAG,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,GAAG,CAAC,CAAC,eAAe,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC;QAC1D,OAAO,KAAK,CAAC,CAAC,eAAe,IAAI,IAAI,EAAE,CAAC;IAC1C,CAAC;IACD,IAAI,CAAC,CAAC,UAAU;QAAE,OAAO,MAAM,CAAC;IAChC,IAAI,CAAC,CAAC,UAAU,KAAK,MAAM,EAAE,CAAC;QAC5B,IAAI,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,WAAW;YAAE,OAAO,GAAG,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;QACvE,IAAI,CAAC,CAAC,OAAO;YAAE,OAAO,CAAC,CAAC,OAAO,CAAC;QAChC,IAAI,CAAC,CAAC,WAAW;YAAE,OAAO,CAAC,CAAC,WAAW,CAAC;QACxC,OAAO,SAAS,CAAC,CAAC,UAAU,EAAE,CAAC;IACjC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,CAAa,EAAE,GAAmB;IAC7D,MAAM,KAAK,GAAa,CAAC,SAAS,CAAC,CAAC;IACpC,MAAM,MAAM,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;IAC/B,IAAI,MAAM;QAAE,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC/B,IAAI,GAAG;QAAE,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC;IACzC,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
@@ -15,12 +15,14 @@ export interface StatusJson {
15
15
  decisions_in_scope: number;
16
16
  invariants_in_scope: number;
17
17
  task_state: TaskState;
18
+ task_id: string | null;
18
19
  task_module: string | null;
19
20
  gc_running: boolean;
20
21
  attention_count: number;
22
+ bypass_count: number;
21
23
  last_run_result: "succeeded" | "failed" | null;
22
24
  last_run_at: string | null;
23
25
  }
24
26
  export { defaultStatusJson, statusJsonPath, writeStatusJson, } from "./writer.js";
25
27
  export { readStatusForCLI } from "./reader.js";
26
- export { formatStatus } from "./format.js";
28
+ export { formatStatus, renderCtxMeter, type CtxMeterInput } from "./format.js";
@@ -10,5 +10,5 @@
10
10
  */
11
11
  export { defaultStatusJson, statusJsonPath, writeStatusJson, } from "./writer.js";
12
12
  export { readStatusForCLI } from "./reader.js";
13
- export { formatStatus } from "./format.js";
13
+ export { formatStatus, renderCtxMeter } from "./format.js";
14
14
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/status-line/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAwBH,OAAO,EACL,iBAAiB,EACjB,cAAc,EACd,eAAe,GAChB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/status-line/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AA0BH,OAAO,EACL,iBAAiB,EACjB,cAAc,EACd,eAAe,GAChB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,cAAc,EAAsB,MAAM,aAAa,CAAC"}
@@ -1,13 +1,16 @@
1
+ import { type CtxMeterInput } from "./format.js";
1
2
  /**
2
3
  * Render the current status-line string for a session inside the
3
4
  * adopted repo at `repoRoot`. `sessionId` is the Claude Code session id
4
- * (passed via the status-line hook's stdin payload).
5
+ * (passed via the status-line hook's stdin payload). `ctx` is the
6
+ * decoded `context_window` block from the same payload.
5
7
  *
6
- * Returns the placeholder `⬡ cairn no session ○` when:
7
- * - `sessionId` is null/empty (status-line invoked outside a session)
8
- * - the per-session status.json is missing
9
- * - the file is unreadable, malformed JSON, or fails shape validation
8
+ * Falls back to ground-state summary when:
9
+ * - `sessionId` is null/empty
10
+ * - the per-session status.json is missing, unreadable, or malformed
11
+ *
12
+ * Returns empty string when `.cairn/` doesn't exist (cairn not adopted).
10
13
  *
11
14
  * Hot path — invoked on every Claude Code prompt. Keep this cheap.
12
15
  */
13
- export declare function readStatusForCLI(repoRoot: string, sessionId: string | null): string;
16
+ export declare function readStatusForCLI(repoRoot: string, sessionId: string | null, ctx?: CtxMeterInput): string;
@@ -1,7 +1,7 @@
1
- import { existsSync, readFileSync } from "node:fs";
2
- import { formatStatus } from "./format.js";
1
+ import { existsSync, readdirSync, readFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { formatStatus, renderCtxMeter } from "./format.js";
3
4
  import { statusJsonPath } from "./writer.js";
4
- const PLACEHOLDER = "⬡ cairn no session ○";
5
5
  const TASK_STATES = [
6
6
  "idle",
7
7
  "running",
@@ -28,46 +28,81 @@ function isStatusJson(x) {
28
28
  typeof o["decisions_in_scope"] === "number" &&
29
29
  typeof o["invariants_in_scope"] === "number" &&
30
30
  isTaskState(o["task_state"]) &&
31
+ isStringOrNull(o["task_id"]) &&
31
32
  isStringOrNull(o["task_module"]) &&
32
33
  typeof o["gc_running"] === "boolean" &&
33
34
  typeof o["attention_count"] === "number" &&
35
+ typeof o["bypass_count"] === "number" &&
34
36
  isLastRunResult(o["last_run_result"]) &&
35
37
  isStringOrNull(o["last_run_at"]));
36
38
  }
39
+ /**
40
+ * Ground-state fallback when no per-session status.json is available.
41
+ * Counts pending drafts from `_inbox/`; renders `⬡ cairn ⚑ N drafts` or
42
+ * just `⬡ cairn`. Returns empty string when `.cairn/` is absent.
43
+ *
44
+ * Ctx meter is appended when supplied — operator-side dropdown stays
45
+ * informative even when the session hook hasn't written status yet.
46
+ */
47
+ function groundStateFallback(repoRoot, ctx) {
48
+ const cairnDir = join(repoRoot, ".cairn");
49
+ if (!existsSync(cairnDir))
50
+ return "";
51
+ let drafts = 0;
52
+ const inboxDir = join(cairnDir, "ground", "decisions", "_inbox");
53
+ if (existsSync(inboxDir)) {
54
+ try {
55
+ drafts = readdirSync(inboxDir, { encoding: "utf8" }).filter((f) => f.endsWith(".draft.md")).length;
56
+ }
57
+ catch {
58
+ drafts = 0;
59
+ }
60
+ }
61
+ const parts = ["⬡ cairn"];
62
+ if (drafts > 0) {
63
+ const noun = drafts === 1 ? "draft" : "drafts";
64
+ parts.push(`⚑ ${drafts} ${noun}`);
65
+ }
66
+ if (ctx)
67
+ parts.push(renderCtxMeter(ctx));
68
+ return parts.join(" ");
69
+ }
37
70
  /**
38
71
  * Render the current status-line string for a session inside the
39
72
  * adopted repo at `repoRoot`. `sessionId` is the Claude Code session id
40
- * (passed via the status-line hook's stdin payload).
73
+ * (passed via the status-line hook's stdin payload). `ctx` is the
74
+ * decoded `context_window` block from the same payload.
75
+ *
76
+ * Falls back to ground-state summary when:
77
+ * - `sessionId` is null/empty
78
+ * - the per-session status.json is missing, unreadable, or malformed
41
79
  *
42
- * Returns the placeholder `⬡ cairn no session ○` when:
43
- * - `sessionId` is null/empty (status-line invoked outside a session)
44
- * - the per-session status.json is missing
45
- * - the file is unreadable, malformed JSON, or fails shape validation
80
+ * Returns empty string when `.cairn/` doesn't exist (cairn not adopted).
46
81
  *
47
82
  * Hot path — invoked on every Claude Code prompt. Keep this cheap.
48
83
  */
49
- export function readStatusForCLI(repoRoot, sessionId) {
84
+ export function readStatusForCLI(repoRoot, sessionId, ctx) {
50
85
  if (sessionId === null || sessionId.length === 0)
51
- return PLACEHOLDER;
86
+ return groundStateFallback(repoRoot, ctx);
52
87
  const filePath = statusJsonPath(repoRoot, sessionId);
53
88
  if (!existsSync(filePath))
54
- return PLACEHOLDER;
89
+ return groundStateFallback(repoRoot, ctx);
55
90
  let raw;
56
91
  try {
57
92
  raw = readFileSync(filePath, "utf8");
58
93
  }
59
94
  catch {
60
- return PLACEHOLDER;
95
+ return groundStateFallback(repoRoot, ctx);
61
96
  }
62
97
  let parsed;
63
98
  try {
64
99
  parsed = JSON.parse(raw);
65
100
  }
66
101
  catch {
67
- return PLACEHOLDER;
102
+ return groundStateFallback(repoRoot, ctx);
68
103
  }
69
104
  if (!isStatusJson(parsed))
70
- return PLACEHOLDER;
71
- return formatStatus(parsed);
105
+ return groundStateFallback(repoRoot, ctx);
106
+ return formatStatus(parsed, ctx);
72
107
  }
73
108
  //# sourceMappingURL=reader.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"reader.js","sourceRoot":"","sources":["../../src/status-line/reader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C,MAAM,WAAW,GAAG,wBAAwB,CAAC;AAE7C,MAAM,WAAW,GAAyB;IACxC,MAAM;IACN,SAAS;IACT,QAAQ;IACR,YAAY;IACZ,SAAS;IACT,WAAW;IACX,UAAU;CACX,CAAC;AAEF,SAAS,WAAW,CAAC,CAAU;IAC7B,OAAO,OAAO,CAAC,KAAK,QAAQ,IAAK,WAAiC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AACjF,CAAC;AAED,SAAS,cAAc,CAAC,CAAU;IAChC,OAAO,CAAC,KAAK,IAAI,IAAI,OAAO,CAAC,KAAK,QAAQ,CAAC;AAC7C,CAAC;AAED,SAAS,eAAe,CAAC,CAAU;IACjC,OAAO,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,WAAW,IAAI,CAAC,KAAK,QAAQ,CAAC;AAC3D,CAAC;AAED,SAAS,YAAY,CAAC,CAAU;IAC9B,IAAI,CAAC,KAAK,IAAI,IAAI,OAAO,CAAC,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IACtD,MAAM,CAAC,GAAG,CAA4B,CAAC;IACvC,OAAO,CACL,OAAO,CAAC,CAAC,YAAY,CAAC,KAAK,QAAQ;QACnC,OAAO,CAAC,CAAC,oBAAoB,CAAC,KAAK,QAAQ;QAC3C,OAAO,CAAC,CAAC,qBAAqB,CAAC,KAAK,QAAQ;QAC5C,WAAW,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC;QAC5B,cAAc,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC;QAChC,OAAO,CAAC,CAAC,YAAY,CAAC,KAAK,SAAS;QACpC,OAAO,CAAC,CAAC,iBAAiB,CAAC,KAAK,QAAQ;QACxC,eAAe,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC;QACrC,cAAc,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CACjC,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,gBAAgB,CAAC,QAAgB,EAAE,SAAwB;IACzE,IAAI,SAAS,KAAK,IAAI,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,WAAW,CAAC;IACrE,MAAM,QAAQ,GAAG,cAAc,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;IACrD,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC;QAAE,OAAO,WAAW,CAAC;IAE9C,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACH,GAAG,GAAG,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IACvC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,WAAW,CAAC;IACrB,CAAC;IAED,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,WAAW,CAAC;IACrB,CAAC;IAED,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC;QAAE,OAAO,WAAW,CAAC;IAE9C,OAAO,YAAY,CAAC,MAAM,CAAC,CAAC;AAC9B,CAAC"}
1
+ {"version":3,"file":"reader.js","sourceRoot":"","sources":["../../src/status-line/reader.ts"],"names":[],"mappings":"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"}
@@ -12,6 +12,11 @@ export declare function statusJsonPath(repoRoot: string, sessionId: string): str
12
12
  * the pretty-printed result back. Creates the per-session directory if
13
13
  * missing.
14
14
  *
15
+ * Refuses to write when the repo's `.cairn/` directory is missing — a
16
+ * caller that forgot to gate on `resolveRepoRoot` would otherwise
17
+ * `mkdir -p` a phantom `.cairn/sessions/` tree in a non-adopted
18
+ * project.
19
+ *
15
20
  * Best-effort write; no atomic-rename ceremony. The status file is
16
21
  * cosmetic — torn writes self-heal on the next hook tick.
17
22
  */
@@ -16,10 +16,17 @@ export function statusJsonPath(repoRoot, sessionId) {
16
16
  * the pretty-printed result back. Creates the per-session directory if
17
17
  * missing.
18
18
  *
19
+ * Refuses to write when the repo's `.cairn/` directory is missing — a
20
+ * caller that forgot to gate on `resolveRepoRoot` would otherwise
21
+ * `mkdir -p` a phantom `.cairn/sessions/` tree in a non-adopted
22
+ * project.
23
+ *
19
24
  * Best-effort write; no atomic-rename ceremony. The status file is
20
25
  * cosmetic — torn writes self-heal on the next hook tick.
21
26
  */
22
27
  export function writeStatusJson(repoRoot, sessionId, patch) {
28
+ if (!existsSync(join(repoRoot, ".cairn")))
29
+ return;
23
30
  const stateDir = sessionStateDir(repoRoot, sessionId);
24
31
  const filePath = join(stateDir, "status.json");
25
32
  let existing = {};
@@ -51,9 +58,11 @@ export function defaultStatusJson() {
51
58
  decisions_in_scope: 0,
52
59
  invariants_in_scope: 0,
53
60
  task_state: "idle",
61
+ task_id: null,
54
62
  task_module: null,
55
63
  gc_running: false,
56
64
  attention_count: 0,
65
+ bypass_count: 0,
57
66
  last_run_result: null,
58
67
  last_run_at: null,
59
68
  };
@@ -1 +1 @@
1
- {"version":3,"file":"writer.js","sourceRoot":"","sources":["../../src/status-line/writer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAGpD;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,QAAgB,EAAE,SAAiB;IAChE,OAAO,IAAI,CAAC,eAAe,CAAC,QAAQ,EAAE,SAAS,CAAC,EAAE,aAAa,CAAC,CAAC;AACnE,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,eAAe,CAC7B,QAAgB,EAChB,SAAiB,EACjB,KAA0B;IAE1B,MAAM,QAAQ,GAAG,eAAe,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;IACtD,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;IAE/C,IAAI,QAAQ,GAAwB,EAAE,CAAC;IACvC,IAAI,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QACzB,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;YAC3C,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAY,CAAC;YAC1C,IAAI,MAAM,KAAK,IAAI,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;gBAClD,QAAQ,GAAG,MAA6B,CAAC;YAC3C,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,QAAQ,GAAG,EAAE,CAAC;QAChB,CAAC;IACH,CAAC;IAED,MAAM,MAAM,GAAwB,EAAE,GAAG,QAAQ,EAAE,GAAG,KAAK,EAAE,CAAC;IAE9D,SAAS,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACzC,aAAa,CAAC,QAAQ,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AAC1E,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB;IAC/B,OAAO;QACL,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACpC,kBAAkB,EAAE,CAAC;QACrB,mBAAmB,EAAE,CAAC;QACtB,UAAU,EAAE,MAAM;QAClB,WAAW,EAAE,IAAI;QACjB,UAAU,EAAE,KAAK;QACjB,eAAe,EAAE,CAAC;QAClB,eAAe,EAAE,IAAI;QACrB,WAAW,EAAE,IAAI;KAClB,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"writer.js","sourceRoot":"","sources":["../../src/status-line/writer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAGpD;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,QAAgB,EAAE,SAAiB;IAChE,OAAO,IAAI,CAAC,eAAe,CAAC,QAAQ,EAAE,SAAS,CAAC,EAAE,aAAa,CAAC,CAAC;AACnE,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,eAAe,CAC7B,QAAgB,EAChB,SAAiB,EACjB,KAA0B;IAE1B,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QAAE,OAAO;IAElD,MAAM,QAAQ,GAAG,eAAe,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;IACtD,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;IAE/C,IAAI,QAAQ,GAAwB,EAAE,CAAC;IACvC,IAAI,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QACzB,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;YAC3C,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAY,CAAC;YAC1C,IAAI,MAAM,KAAK,IAAI,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;gBAClD,QAAQ,GAAG,MAA6B,CAAC;YAC3C,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,QAAQ,GAAG,EAAE,CAAC;QAChB,CAAC;IACH,CAAC;IAED,MAAM,MAAM,GAAwB,EAAE,GAAG,QAAQ,EAAE,GAAG,KAAK,EAAE,CAAC;IAE9D,SAAS,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACzC,aAAa,CAAC,QAAQ,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AAC1E,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB;IAC/B,OAAO;QACL,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACpC,kBAAkB,EAAE,CAAC;QACrB,mBAAmB,EAAE,CAAC;QACtB,UAAU,EAAE,MAAM;QAClB,OAAO,EAAE,IAAI;QACb,WAAW,EAAE,IAAI;QACjB,UAAU,EAAE,KAAK;QACjB,eAAe,EAAE,CAAC;QAClB,YAAY,EAAE,CAAC;QACf,eAAe,EAAE,IAAI;QACrB,WAAW,EAAE,IAAI;KAClB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Unified trace log for live-session debugging.
3
+ *
4
+ * Every cairn surface (Claude Code hooks, MCP tools, `claude --print`
5
+ * subprocess calls, init phases) appends a single jsonl row per event
6
+ * to `~/.local/cairn/trace/trace-<YYYY-MM-DD>.jsonl`. The `cairn trace`
7
+ * CLI subcommand reads them back time-sorted across the most recent
8
+ * day(s) so the operator can post-mortem an entire live session in one
9
+ * pane.
10
+ *
11
+ * Best-effort: trace failures NEVER throw — debug logging that breaks
12
+ * the surface it's monitoring is worse than no logging.
13
+ */
14
+ export type TraceSource = "hook" | "mcp" | "claude" | "init-phase" | "subagent";
15
+ export interface TraceEvent {
16
+ /** ISO 8601 with millisecond precision. */
17
+ ts: string;
18
+ /** Top-level surface emitting the event. */
19
+ source: TraceSource;
20
+ /** Event-specific kind ("session-start", "tool-call", "claude-request", …). */
21
+ kind: string;
22
+ /** Adopted-repo root, when known. */
23
+ repo_root: string | null;
24
+ /** Claude Code session id, when known. */
25
+ session_id: string | null;
26
+ /** Wall time spent, when applicable. */
27
+ duration_ms?: number;
28
+ /** Success / failure outcome, when applicable. */
29
+ ok?: boolean;
30
+ /** Free-form payload — keep small; large bodies should be stored separately. */
31
+ payload: Record<string, unknown>;
32
+ }
33
+ export declare function traceDir(): string;
34
+ export declare function traceFilePath(now?: Date): string;
35
+ /**
36
+ * Append one trace row. Best-effort — swallows any IO error so callers
37
+ * never break their primary surface on trace-write failure.
38
+ */
39
+ export declare function appendTrace(event: TraceEvent): void;
40
+ /**
41
+ * Build a TraceEvent with `ts` set to now. Convenience for callsites
42
+ * that build the rest of the row inline.
43
+ */
44
+ export declare function nowEvent(args: Omit<TraceEvent, "ts">): TraceEvent;
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Unified trace log for live-session debugging.
3
+ *
4
+ * Every cairn surface (Claude Code hooks, MCP tools, `claude --print`
5
+ * subprocess calls, init phases) appends a single jsonl row per event
6
+ * to `~/.local/cairn/trace/trace-<YYYY-MM-DD>.jsonl`. The `cairn trace`
7
+ * CLI subcommand reads them back time-sorted across the most recent
8
+ * day(s) so the operator can post-mortem an entire live session in one
9
+ * pane.
10
+ *
11
+ * Best-effort: trace failures NEVER throw — debug logging that breaks
12
+ * the surface it's monitoring is worse than no logging.
13
+ */
14
+ import { appendFileSync, existsSync, mkdirSync } from "node:fs";
15
+ import { homedir } from "node:os";
16
+ import { join } from "node:path";
17
+ export function traceDir() {
18
+ return join(homedir(), ".local", "cairn", "trace");
19
+ }
20
+ function todayFilename(now) {
21
+ const y = now.getUTCFullYear();
22
+ const m = String(now.getUTCMonth() + 1).padStart(2, "0");
23
+ const d = String(now.getUTCDate()).padStart(2, "0");
24
+ return `trace-${y}-${m}-${d}.jsonl`;
25
+ }
26
+ export function traceFilePath(now = new Date()) {
27
+ return join(traceDir(), todayFilename(now));
28
+ }
29
+ /**
30
+ * Append one trace row. Best-effort — swallows any IO error so callers
31
+ * never break their primary surface on trace-write failure.
32
+ */
33
+ export function appendTrace(event) {
34
+ try {
35
+ const dir = traceDir();
36
+ if (!existsSync(dir))
37
+ mkdirSync(dir, { recursive: true });
38
+ appendFileSync(traceFilePath(), `${JSON.stringify(event)}\n`, "utf8");
39
+ }
40
+ catch {
41
+ // best-effort
42
+ }
43
+ }
44
+ /**
45
+ * Build a TraceEvent with `ts` set to now. Convenience for callsites
46
+ * that build the rest of the row inline.
47
+ */
48
+ export function nowEvent(args) {
49
+ return { ts: new Date().toISOString(), ...args };
50
+ }
51
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/trace/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAChE,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAuBjC,MAAM,UAAU,QAAQ;IACtB,OAAO,IAAI,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;AACrD,CAAC;AAED,SAAS,aAAa,CAAC,GAAS;IAC9B,MAAM,CAAC,GAAG,GAAG,CAAC,cAAc,EAAE,CAAC;IAC/B,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IACzD,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IACpD,OAAO,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC;AACtC,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,MAAY,IAAI,IAAI,EAAE;IAClD,OAAO,IAAI,CAAC,QAAQ,EAAE,EAAE,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC;AAC9C,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,KAAiB;IAC3C,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,QAAQ,EAAE,CAAC;QACvB,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC1D,cAAc,CAAC,aAAa,EAAE,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACxE,CAAC;IAAC,MAAM,CAAC;QACP,cAAc;IAChB,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,QAAQ,CAAC,IAA4B;IACnD,OAAO,EAAE,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,GAAG,IAAI,EAAE,CAAC;AACnD,CAAC"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@isaacriehm/cairn-core",
3
- "version": "0.2.0",
4
- "description": "Cairn core — state + context layer. Curated `.cairn/ground/` (decisions, §V invariants, canonical-map, brand, quality-grades), MCP server, init wizard, hook runners, sensors, GC drift sweep.",
3
+ "version": "0.3.0",
4
+ "description": "Cairn core — state + context layer. Curated `.cairn/ground/` (decisions, §INV invariants, canonical-map, brand, quality-grades), MCP server, init wizard, hook runners, sensors, GC drift sweep.",
5
5
  "author": "Isaac Riehm",
6
6
  "license": "MIT",
7
7
  "homepage": "https://github.com/isaacriehm/cairn",
@@ -43,7 +43,6 @@
43
43
  "devDependencies": {
44
44
  "@types/cli-progress": "^3.11.6",
45
45
  "@types/node": "^25.6.0",
46
- "tsx": "^4.21.0",
47
46
  "typescript": "^6.0.3"
48
47
  },
49
48
  "scripts": {
@@ -21,7 +21,7 @@ This directory holds files that were once canonical but are no longer current. *
21
21
 
22
22
  ## What does NOT live here
23
23
 
24
- - Files marked `[STALE]` in canonical paths — Cairn rejects this pattern. Stale files are MOVED here, never banner-flagged in place. (See `docs/PRIMER.md` §11 anti-patterns.)
24
+ - Files marked `[STALE]` in canonical paths — Cairn rejects this pattern. Stale files are MOVED here, never banner-flagged in place.
25
25
  - Branches or tagged refs — `.archive/` is filesystem-only.
26
26
  - Secrets — `.env*` patterns stay in `.gitignore` regardless.
27
27
 
@@ -54,7 +54,7 @@ PreToolUse-style interception is **not** used (operator decision 2026-05-04). Th
54
54
 
55
55
  ## Writing to `.archive/`
56
56
 
57
- Only via `cairn_archive(path, reason)`. Direct moves are accepted but discouraged because they bypass the audit log. The MCP tool records the reason, the operator who issued the move (frontend-adapter user-id), and the timestamp.
57
+ Only via `cairn_archive(path, reason)`. Direct moves are accepted but discouraged because they bypass the audit log. The MCP tool records the reason and timestamp.
58
58
 
59
59
  ## Why we don't delete
60
60
 
@@ -64,4 +64,4 @@ Only via `cairn_archive(path, reason)`. Direct moves are accepted but discourage
64
64
 
65
65
  ## Restoring an archived file
66
66
 
67
- `cairn restore <path>` (CLI subcommand, future) — moves a file out of `.archive/<bucket>/` back to its original location and writes a `cairn_record_run_event` of the restoration. Use sparingly.
67
+ `cairn restore <path>` (CLI subcommand, future) — moves a file out of `.archive/<bucket>/` back to its original location and logs the restoration. Use sparingly.
@@ -1,15 +1,13 @@
1
1
  # Cairn sensor registry.
2
2
  #
3
- # Sensors are mechanical checks the orchestrator runs against an agent's diff.
3
+ # Sensors are mechanical checks run against an agent's diff.
4
4
  # Listed here are the GENERIC kinds that ship with the Cairn package. Stack
5
- # profiles (typescript-next-nest, python-fastapi, rails, go, rust, unknown see
6
- # INTEGRATION_PLAN.md §16.1) propose profile-specific sensors at adoption; the
7
- # operator confirms each one. Project-specific sensors live in the adopting
8
- # project's extension block (see workflow.md).
5
+ # profiles propose profile-specific sensors at adoption; the operator confirms
6
+ # each one. Project-specific sensors live in the adopting project's extension
7
+ # block (see workflow.md).
9
8
  #
10
- # Per operator answer S1: Cairn package code does NOT hardcode any specific
11
- # project's sensor names. All concrete sensor identifiers below are
12
- # stack-profile-agnostic primitives.
9
+ # Cairn package code does NOT hardcode any specific project's sensor names.
10
+ # All concrete sensor identifiers below are stack-profile-agnostic primitives.
13
11
 
14
12
  version: 1
15
13
 
@@ -80,11 +78,11 @@ sensors:
80
78
  - every_run
81
79
  fail_severity: hard
82
80
 
83
- # ── §V invariant sensors (auto-registered by backprop) ───────────────────
81
+ # ── §INV invariant sensors (auto-registered by backprop) ────────────────
84
82
  - id: invariant-suite
85
83
  layer: invariants
86
84
  kind: invariant_runner
87
- description: "Runs every active §V invariant's linked sensor script (see backprop protocol — PRIMER §13). Active invariants accumulate over time; superseded ones are skipped."
85
+ description: "Runs every active §INV invariant's linked sensor script. Active invariants accumulate over time; superseded ones are skipped."
88
86
  triggers:
89
87
  - every_run
90
88
  sources:
@@ -95,25 +93,25 @@ sensors:
95
93
  - id: reviewer-subagent
96
94
  layer: C
97
95
  kind: inferential
98
- description: "Same model as implementer; fresh context. Reads only spec.tightened.md + diff + decisions ledger + in-scope assertions. Anti-completionist framing. For high-stakes runs, also enforces query-scope completeness (Codex audit Q1)."
96
+ description: "Same model as implementer; fresh context. Reads only spec.tightened.md + diff + decisions ledger + in-scope assertions. Anti-completionist framing. For high-stakes runs, also enforces query-scope completeness."
99
97
  model_strategy: same_as_implementer
100
98
  triggers:
101
99
  - all_layer_d_sensors_passed
102
- fail_severity: soft # produces verdict; orchestrator gates on operator override or auto-fail
100
+ fail_severity: soft
103
101
 
104
102
  # ── Layer E — high-stakes E2E / demo ─────────────────────────────────────
105
103
  - id: e2e-real-db
106
104
  layer: E
107
105
  kind: e2e
108
- description: "Runs the project's E2E suite against a real database (no mocks). High-stakes UAT MUST include a cross-tenant negative fixture (Codex audit Q1) — a request from user/org B against a resource owned by user/org A returning the expected denial."
106
+ description: "Runs the project's E2E suite against a real database (no mocks). High-stakes UAT MUST include a cross-tenant negative fixture — a request from user/org B against a resource owned by user/org A returning the expected denial."
109
107
  triggers:
110
108
  - high_stakes_glob_match
111
109
  profile_hook: profile.e2e_command
112
110
  fail_severity: hard
113
111
  requires:
114
- cross_tenant_fixture: true # per L43
112
+ cross_tenant_fixture: true
115
113
 
116
- # ── Layer U — UAT-on-phone ───────────────────────────────────────────────
114
+ # ── Layer U — UAT headless ───────────────────────────────────────────────
117
115
  - id: uat-headless-chrome
118
116
  layer: U
119
117
  kind: uat
@@ -131,7 +129,7 @@ sensors:
131
129
  - nightly_cron
132
130
  fail_severity: soft
133
131
 
134
- # ── Local-dirty-overlap gate (per Codex audit Q3) ─────────────────────────
132
+ # ── Local-dirty-overlap gate ──────────────────────────────────────────────
135
133
  - id: local-dirty-overlap
136
134
  layer: pre_dispatch
137
135
  kind: working_tree_check
@@ -139,7 +137,7 @@ sensors:
139
137
  triggers:
140
138
  - pre_dispatch
141
139
  - pre_push
142
- fail_severity: soft # operator decides resolution
140
+ fail_severity: soft
143
141
 
144
142
  # ──────────────────────────────────────────────────────────────────────────────
145
143
  # Scoped-glob keys.
@@ -178,8 +176,7 @@ copy_safety:
178
176
 
179
177
  # ──────────────────────────────────────────────────────────────────────────────
180
178
  # Disable list — sensors known to false-positive at >50% on a given project.
181
- # Default empty; populated per-project via /oops dialog (PRIMER §11 anti-pattern:
182
- # we DO NOT mock or stub sensor results to make them pass).
179
+ # Default empty; populated per-project via the attention flow.
183
180
  # ──────────────────────────────────────────────────────────────────────────────
184
181
 
185
182
  disabled_per_project: []
@@ -1,12 +1,12 @@
1
1
  # Layer A — mechanical stub-pattern catalog.
2
2
  #
3
- # Initial seed (~30 patterns). Grows additively via the /oops dialog
4
- # (PRIMER §10 Layer A; L25). Patterns NEVER added by typed CLI command.
3
+ # Initial seed (~30 patterns). Grows additively via the attention flow.
4
+ # Patterns NEVER added by typed CLI command.
5
5
  #
6
6
  # Each pattern is language-tagged. The orchestrator filters patterns by the
7
7
  # stack profile's language list before running. False-positive cases are not
8
- # silenced by editing this file — they're handled per-failure via the /oops
9
- # dialog (PRIMER §11 anti-pattern: do NOT disable sensors to make diffs pass).
8
+ # silenced by editing this file — they're handled per-failure via the attention
9
+ # flow (do NOT disable sensors to make diffs pass).
10
10
  #
11
11
  # Format:
12
12
  # - id: <stable identifier; cited in failure messages>