@misterhuydo/cairn-mcp 1.36.0 → 1.37.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
@@ -497,6 +497,61 @@ cairn cannot type either command.
497
497
  Once the handoff is written, neither option drops anything that was written down, so the
498
498
  choice collapses to that single question about what comes next.
499
499
 
500
+ **v1.36.1 is the release that made the sentence above true.** It was not. The gate would
501
+ demand a thorough `would_be_lost`, the agent would write three and a half thousand
502
+ characters of reasoning that existed nowhere else, correctly tell you a reset was safe —
503
+ and the SessionStart re-injection would hand the fresh session 220 characters of it, cut
504
+ off mid-word. Everything after the first point was gone. The agent could not remember the
505
+ conversation you had just had with it, which read as the checkpoint failing when the
506
+ checkpoint had worked perfectly.
507
+
508
+ Storage was never the problem; delivery was. `inlineResumePayload()` rendered the restore
509
+ payload through the same 220-character clip as the every-prompt budget line. That cap is
510
+ right for the budget line — it rides *every* turn and has to stay one line — and ruinous
511
+ for the restore payload, which fires **once** and is the only copy of the handoff that
512
+ session will ever see. One cap could not serve both, so `handoffSummaryLine()` now takes
513
+ one, and the restore path passes none. It costs about 900 tokens a session.
514
+
515
+ The failure is worth naming because of its shape: the agent was right about what got
516
+ *saved* and wrong about what got *delivered*, and no amount of care inside the writing
517
+ session could have caught the difference. The same bug had a second instance — notes long
518
+ enough to be filed to `.cairn/notes/` are held as objects, and the restore stringified
519
+ them to `[object Object]`, so the most substantial notes were the ones that arrived as
520
+ noise. When a feature demands expensive judgement from the agent, test the whole return
521
+ path, not just the write.
522
+
523
+ **v1.37.0 gives the handoff somewhere permanent to live, and stops previews cutting
524
+ mid-word.** `session.json` holds exactly *one* `would_be_lost`, and every manual
525
+ checkpoint overwrites the last, so a project's history of what each session would have
526
+ lost was destroyed one checkpoint at a time — and the rotation at 100KB scattered
527
+ whatever survived across `session.N.json` files nobody reads. The most expensive field
528
+ cairn ever asks an agent to produce had the shortest life of anything cairn stores.
529
+
530
+ Every answered handoff is now appended to **`.cairn/handoff.md`**: full text, never
531
+ clipped, newlines intact, plain Markdown you can read or grep without cairn. Newest
532
+ first — unlike `roadmap_completed.md`, which appends at the end because it is a shipping
533
+ record read in order. This is a lookup, so it is ordered for the lookup. The every-turn
534
+ heartbeat is not logged; only a real answer is, or a handful of genuine judgements would
535
+ be buried under thousands of identical copies. It is an addition rather than a migration:
536
+ `session.json` keeps the field unchanged as the hooks' fast path, so nothing that reads
537
+ it needs to know the file exists.
538
+
539
+ Previews no longer end mid-word. A cut like `…the re-injection clipped would…` is worse
540
+ than a shorter clean one: the reader cannot tell whether the truncated token was `would`,
541
+ `would_be_lost` or `wouldn't`, so the last thing they are shown is the one thing they
542
+ must not trust. `clip()` backs up to the last space and drops trailing punctuation. The
543
+ exception is deliberate — an unbroken run longer than the cap (a stack trace, a base64
544
+ blob, a Windows path) has no boundary to back up to, so below a 0.6 floor it takes the
545
+ hard cut rather than returning almost nothing. The cap itself went 220 → 400, because at
546
+ 220 the budget line reliably died inside the first sentence of point (1): enough to prove
547
+ a handoff existed, not enough to say what it was about.
548
+
549
+ One test had to change, and it is worth saying which. The v1.36.1 guard asserted the
550
+ every-prompt line stayed under 300 characters — a magic number tied to the old cap, so it
551
+ failed on a change that was entirely intended. It now asserts a *ratio*: the preview must
552
+ stay under half the payload. The invariant was never a particular length, it was that one
553
+ channel stays a preview while the other carries everything.
554
+
500
555
  It needs no rate limit: it self-extinguishes. The moment the handoff is written the
501
556
  demand returns null, and it speaks again only if later commits make that answer stale.
502
557
  Crossing is remembered in `.cairn/.handoff-gate` and forgotten when usage drops back