@misterhuydo/cairn-mcp 1.19.0 → 1.20.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.
package/README.md CHANGED
@@ -53,7 +53,8 @@ server load.
53
53
  | `PreToolUse[Edit]` | Every file edit | Blocks Edit if Claude only saw compressed content — requires a full re-read first. Reported as a permission decision with a one-line reason, **not** as a red hook error: being sent back to re-read a file is a normal step, and the full source rides along out of sight so it does not fill the screen |
54
54
  | `PostToolUse[ExitPlanMode]` | A plan is approved | The plan is parsed into `### Phase N` entries in `.cairn/roadmap.md`, synced, and the cursor activated |
55
55
  | `PostToolUse[TodoWrite]` | The todo list changes | Todos mirror onto the roadmap as sub-tasks under the current phase (or seed root phases if none exist) |
56
- | `Stop` | End of every response | Session auto-saved to `.cairn/session.json`, Claude auto-memory backed up to `.cairn/memory/`, the roadmap re-surfaced, any git-detected completed phases surfaced for you to confirm, and on a long session one line naming what clearing would cost — all in one line |
56
+ | `Stop` | End of every response | Session auto-saved to `.cairn/session.json`, Claude auto-memory backed up to `.cairn/memory/`, the roadmap re-surfaced, any git-detected completed phases surfaced for you to confirm, and — once the session is genuinely large — a prompt asking whether you want to `/clear` or `/compact`, with a recommendation and the reason. All in one line |
57
+ | `SessionStart[clear]`<br>`SessionStart[compact]` | Right after you `/clear` or `/compact` | The checkpoint is re-injected into the fresh session automatically, so it opens already knowing the open thread and what the last session would have lost. You do not have to type "resume" |
57
58
  | `UserPromptSubmit` | First message of a new session | Fresh project: Claude prompted to run `cairn_maintain`. Returning session: Claude prompted to run `cairn_resume`. Memory restored from `.cairn/memory/` if the Claude store is empty (new machine / fresh clone) |
58
59
 
59
60
  ---
@@ -266,19 +267,53 @@ the judgement on the way in and carries it across the gap**:
266
267
  The handoff is stamped only when it is actually written, never by the
267
268
  heartbeat that copies it forward, and anything written before commits that
268
269
  have since landed is reported as possibly stale.
269
- 4. **Then, and only then, one line.** When the session transcript crosses a coarse
270
- size threshold **and** something is actually at risk, the Stop hook adds a line
271
- naming the loss: *"Clearing now would lose: … — last written before the 3
272
- commits since."* When the handoff is current it says what clearing costs
273
- instead, which is the more useful message and the one that lets you actually
274
- clear.
275
-
276
- Deliberately not built: no percentage (the transcript keeps growing across a
277
- compaction while the window resets, so a precise number would claim an accuracy
278
- it does not have), no transcript parsing (`statSync` only — this runs on every
279
- single turn), no repeating the line when nothing changed, and no auto-clearing,
280
- auto-compacting, or filling the field in on your behalf. Same shape as completed-phase
281
- detection: detect, surface, confirm with the user, never apply.
270
+ 4. **Then, and only then, it asks.** When the session crosses the threshold **and**
271
+ something is actually at risk, the Stop hook asks you to choose, with a
272
+ recommendation and the reason:
273
+
274
+ > **Checkpoint + /clear (Recommended)** — I write the handoff now, then you type `/clear`
275
+ > **Checkpoint + /compact** — I write the handoff now, then you type `/compact`
276
+ > **Keep going** — decline
277
+
278
+ Which one is recommended follows from the handoff, not from fullness. A
279
+ *current* handoff means the thread survives a hard reset, so `/clear` wins and
280
+ you get the full window back. A *missing or stale* one means something unwritten
281
+ is at risk, so `/compact` wins and keeps it reachable. Either choice writes the
282
+ checkpoint first — including `/clear`, which needs it most, not least.
283
+
284
+ 5. **And it is there afterwards.** `SessionStart[clear|compact]` re-injects the
285
+ checkpoint into the fresh session, so it opens already knowing where it is. You
286
+ never have to remember to type "resume", which is exactly the manual step that
287
+ gets skipped on the sessions where skipping it costs the most.
288
+
289
+ **Cairn cannot type the command.** No hook output and no tool can trigger a slash
290
+ command, so the agent does the half it can do (the checkpoint, immediately) and you
291
+ type the six characters. Anything that claimed otherwise would leave you waiting for
292
+ something that never happens.
293
+
294
+ ### How the size is measured
295
+
296
+ Not from file size. No hook input carries token counts, but every hook receives
297
+ `transcript_path`, and the transcript's assistant records carry the usage the API
298
+ actually reported — so cairn tail-reads the last 256 KB and sums the real window
299
+ (input + cache reads + cache creation + output). Measured cost: 6 lines parsed,
300
+ 0.5 ms.
301
+
302
+ v1.19.0 used transcript bytes as the proxy and it was wrong in the one place that
303
+ mattered. Measured on cairn's own session: **3.40 MB of transcript holding 72,285
304
+ tokens of context.** Bytes keep accumulating across a `/compact` while the window
305
+ resets, so a byte threshold is loudest immediately *after* a compaction, when there
306
+ is least reason to speak. Bytes survive now only as a fallback for when no usage
307
+ record is reachable, and when that happens the line says so instead of dressing a
308
+ file size up as a token count.
309
+
310
+ Deliberately not built: no percentage (the context-window size is not observable
311
+ from a hook, so the denominator would be invented — the absolute count is reported
312
+ instead), no full transcript walk (the tail only; a full walk in this hot path once
313
+ froze every terminal in the cockpit for 4.3 seconds), no counting subagent spend as
314
+ main-thread context, no repeating the prompt when nothing changed, and no
315
+ auto-clearing, auto-compacting, or filling the field in on your behalf. Same shape
316
+ as completed-phase detection: detect, surface, confirm with the user, never apply.
282
317
 
283
318
  ---
284
319