@misterhuydo/cairn-mcp 1.36.1 → 1.38.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 +70 -0
- package/dist/cairn-cli.js +90 -71
- package/dist/index.js +85 -66
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -520,6 +520,76 @@ them to `[object Object]`, so the most substantial notes were the ones that arri
|
|
|
520
520
|
noise. When a feature demands expensive judgement from the agent, test the whole return
|
|
521
521
|
path, not just the write.
|
|
522
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
|
+
|
|
555
|
+
**v1.38.0 adds the other half of the question.** Everything above is retrospective.
|
|
556
|
+
`would_be_lost` asks what a fresh session would not *know*, and every example in it is
|
|
557
|
+
something that already happened. So a restored session inherited the whole of what the
|
|
558
|
+
last one learned and nothing of what it was going to do with it — thorough notes, a
|
|
559
|
+
legible thread, and an agent that still opened with "what now?" to a user who had
|
|
560
|
+
answered that an hour earlier.
|
|
561
|
+
|
|
562
|
+
`cairn_checkpoint` now takes **`next_step`**, carried by exactly the same rules as the
|
|
563
|
+
handoff: the heartbeat copies it forward but never restamps it, it ages against commits,
|
|
564
|
+
and it is delivered in full on restore, directly under the handoff. It asks for the
|
|
565
|
+
*reason* as well as the action, because the action alone already survives in the roadmap
|
|
566
|
+
and the message field — what does not survive is why that action was next rather than the
|
|
567
|
+
alternatives, and an agent that inherits only "run the Windows fixtures" will happily do
|
|
568
|
+
it in the wrong order or redo the deliberation that chose it.
|
|
569
|
+
|
|
570
|
+
Staleness means something sharper on this half. A stale handoff is still *true*: what was
|
|
571
|
+
learned stays learned, and later commits only mean it may be incomplete. A stale next step
|
|
572
|
+
may be actively *false* — commits landing after "next I will run the fixtures" are quite
|
|
573
|
+
often that step being done, so the warning says **verify before acting on it** rather than
|
|
574
|
+
"may be stale". A restored agent acting confidently on a completed instruction is worse
|
|
575
|
+
than one told nothing.
|
|
576
|
+
|
|
577
|
+
The 90% gate now demands both halves, and only the missing one. Asking for a handoff that
|
|
578
|
+
is already current invites it to be rewritten, and a rewrite restamps `at` — which is how
|
|
579
|
+
a thorough answer gets replaced by a hurried one at the worst possible moment.
|
|
580
|
+
|
|
581
|
+
**And when nothing forward is registered anywhere, the gate says so.** If the roadmap has
|
|
582
|
+
no cursor and no open phase, then after the reset there is nothing outside the discarded
|
|
583
|
+
conversation that says what comes next, and the gate suggests registering the phase. This
|
|
584
|
+
is not cairn inferring the plan — that remains the thing it cannot see and must not guess.
|
|
585
|
+
It reports an *observed absence*: the plan points at nothing. Absence is observable,
|
|
586
|
+
content is not, and that distinction is the only reason this arm is allowed to exist. When
|
|
587
|
+
the roadmap cannot be read at all — no index, no sqlite — it stays silent rather than
|
|
588
|
+
claiming a bare plan it never saw, the same honest-absence rule the commit counter uses.
|
|
589
|
+
|
|
590
|
+
The probe is deliberately not the roadmap renderer: it is two cheap queries, run only when
|
|
591
|
+
the gate is actually crossing, so the every-prompt path opens no database at all.
|
|
592
|
+
|
|
523
593
|
It needs no rate limit: it self-extinguishes. The moment the handoff is written the
|
|
524
594
|
demand returns null, and it speaks again only if later commits make that answer stale.
|
|
525
595
|
Crossing is remembered in `.cairn/.handoff-gate` and forgotten when usage drops back
|