@misterhuydo/cairn-mcp 1.34.0 → 1.36.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -426,6 +426,108 @@ was nagging and it had to be shown once per situation; this is a *measurement*,
426
426
  budget you are only shown once it is nearly spent cannot inform the decision to start
427
427
  something. It rides every prompt.
428
428
 
429
+ **Since v1.35.0 the line also says which reset to use.** Every reading carries a
430
+ second line naming `/clear` or `/compact` and why:
431
+
432
+ ```
433
+ [cairn] Context: 90,000 of 1,000,000 tokens (9%, declared for claude-opus-5[1m]).
434
+ Handoff is STALE, written before the 1 commit(s) since: the retry path is untested…
435
+ → If you reset: /compact — the handoff predates the 1 commit(s) since, so it no
436
+ longer describes the work in flight.
437
+ ```
438
+
439
+ Cairn had been computing that recommendation since v1.29.0 and printing none of it:
440
+ `recommendedAction()` decided between the two on every prompt, and the hook built its
441
+ output from the measurement and the protocol alone, so the advice reached the screen
442
+ only if the agent chose to raise it. That routed the whole path through the one
443
+ component with a demonstrated failure record — the same judgement that read 253,500 of
444
+ 1M as an emergency, twice.
445
+
446
+ The advice turns on **what is saved, never on how full the window is**. A current
447
+ handoff means the thread survives a hard reset, so `/clear` is the better trade; a
448
+ missing or stale one means something unwritten is still at risk, so `/compact` keeps it
449
+ reachable. That is why it can print at 9% as readily as at 94%, and why the wording is
450
+ strictly conditional. *If* you reset, use this one. It never says to reset — that
451
+ judgement is still the agent's, and still yours to act on, since cairn cannot type
452
+ either command. A fact about your saved state does not become false or urgent by being
453
+ displayed; the verdict it replaced did, which is why that one had to be rationed.
454
+
455
+ **Since v1.36.0 there is exactly one threshold again: the 90% gate.** At 90% of the
456
+ *declared* window, cairn asks the agent for one specific thing:
457
+
458
+ ```
459
+ ⚠ [cairn] 94% of the declared window (940,000 of 1,000,000 tokens, 60,000 left) and
460
+ nothing has been written down about what this session would lose. Call cairn_checkpoint
461
+ with would_be_lost: the every-turn auto-checkpoint carries that field forward but never
462
+ writes it, so nothing else will. This is not a verdict on whether your next task fits —
463
+ that judgement is still yours.
464
+ ```
465
+
466
+ A threshold is defensible now for a reason that did not exist before v1.34.0: **the
467
+ window is declared, not guessed.** The gate fires only when an agent has stated its
468
+ denominator and never otherwise, so a project that has declared nothing gets no trigger
469
+ and no false alarm — by construction, not by tuning. That is the property the fixed
470
+ 120k, the inferred-smallest and the unwritable env var could never have had.
471
+
472
+ It also asks for something none of them asked for. It does not say stop, and it does not
473
+ rule on whether the work fits. It demands the one field an automatic save must never
474
+ invent: the Stop hook checkpoints every turn, but `would_be_lost` is deliberately carried
475
+ forward untouched rather than fabricated (`checkpoint.js:68`), which makes it precisely
476
+ the field still missing when the window runs out.
477
+
478
+ 90% rather than 95% because the cost is asymmetric — firing early costs about 1k tokens
479
+ for a handoff worth writing anyway, firing late costs the session's whole unwritten
480
+ reasoning — and because usage does not climb smoothly. A single image read or large test
481
+ dump can take 10k in one turn, which is the entire margin 95% leaves on a 200k window.
482
+
483
+ **It also names who picks `/clear` vs `/compact`, and on what basis.** Cairn's own
484
+ recommendation is about *what is saved* — but that is a precondition, not the decision.
485
+ The decision is whether the work ahead needs the context already loaded: a new,
486
+ unrelated phase gains nothing from this conversation, so `/clear` is the better trade,
487
+ while a phase continuing this one would force a re-read of everything, so `/compact` is.
488
+
489
+ Cairn cannot see which of those is coming, and does not try — that is the
490
+ window-inference mistake in a new costume. The *agent* can: it has the incoming
491
+ request, the roadmap cursor, and where the conversation was heading. So the gate demands
492
+ that judgement rather than leaving you a two-branch menu, and the user-facing half
493
+ explains what each command does so you can act on it or overrule it. Same division of
494
+ labour as everywhere else here: cairn measures, the agent judges, you act — because
495
+ cairn cannot type either command.
496
+
497
+ Once the handoff is written, neither option drops anything that was written down, so the
498
+ choice collapses to that single question about what comes next.
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
+ It needs no rate limit: it self-extinguishes. The moment the handoff is written the
524
+ demand returns null, and it speaks again only if later commits make that answer stale.
525
+ Crossing is remembered in `.cairn/.handoff-gate` and forgotten when usage drops back
526
+ below the gate, so a `/clear` makes the next crossing a genuinely new event. The stored
527
+ crossing also closes a hole that `stale` alone cannot: staleness is counted in *commits*,
528
+ so a long research session that commits nothing would keep a handoff from its opening
529
+ minutes marked current all the way to the top of the window.
530
+
429
531
  `CAIRN_CONTEXT_HINT_TOKENS` no longer gates anything, but if you set it, cairn tells
430
532
  the agent when you have passed it rather than ignoring you.
431
533