Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

keepline

Context integrity for LLM chat sessions. Deterministic fact capture, confabulation and sycophancy guards, namesake sealing, tool-syntax scrubbing — and the 13-turn gauntlet that scores them. Zero dependencies, bring your own model.

npm install keepline
import { createTrio, createMemoryStore } from "keepline";
import { anthropicAdapter } from "keepline/src/providers/index.js";

const trio = createTrio({
  callModel: anthropicAdapter({ apiKey: process.env.ANTHROPIC_API_KEY }),
  store: createMemoryStore(),
  sessionId: "demo"
});
const { text } = await trio.turn("our low-stock Slack bot is named Gnocco");
// ... twenty messy turns later ...
await trio.turn("remind me — what did we call the bot?");   // → Gnocco. Not an invention.

Or use the pieces à la carte — every module is pure and standalone: extractFacts / mergeFacts / renderLedgerBlock (capture), runGuards (integrity chain), sealWebResults (namesake seal), scrubToolSyntax (leak scrub).


The investigation this came from

I run a small AI product on a flash-tier model. I built a 13-turn benchmark — 12 facts planted across a messy strategy session, with a tangent, two contradiction attacks, a sycophancy pull, and precision traps — and ran my stack against a frontier model.

Nine runs in one day. The arc: 94 → 91 → 98 → 92 → 75 → 95 → 89.5 → 94 → 98, against a frontier anchor of 99. Every dip was a mechanism with a name, and every fix in this library exists because a specific run failed a specific way:

The failure The run The fix in this repo
Asked for a bot name it never filed, the model invented one ("Tavolo-Alert") 94 recallFabrication + record capture: abstain honestly, or better — recall from the ledger
A web search on my fictional "Osteria del Sole" found the real 500-year-old Bologna wine bar, imported "serves no food", and flipped a strategic verdict to walk-away 91, 89.5 sealWebResults — session entities outrank the web, including on the turn that introduces them
A mid-session re-entry flipped recall to record-first and three stacked "answer from the record" instructions fenced the model off from its own memory — honest abstentions everywhere, score cratered to 75 75 the one-voice rule baked into every rendered block: "prefer", never "only"
The abstain instruction said "that's not in the record" while the code was holding the record — so the rewrite denied a fact that was on file 92 corrections take facts as a parameter: show the record, don't assert about it (recallDenial catches the "we never named it" mask)
Raw draw_diagram(...) calls and JSON payload blobs printed into user-facing replies on no-tools retry paths 92, 89.5 scrubToolSyntax — call + blob excision, code-fence-aware
A "revised" number kept its stale twin: with burn updated to €25k, the record still instructed "use €18k VERBATIM" (caught by tests) temporal supersede in mergeFacts — singular roles revise, plural roles coexist

The through-line: every failure was a good instinct in the wrong place — fluency, grounding, record-discipline, all virtues until the session's world is self-contained. And every fix is structure, not prompt text: control flow keyed on retrieval hits, bounded retries, deterministic fallbacks. An invented fact cannot ship even when the rewrite model fails twice.

What's inside

src/capture/   extractFacts · mergeFacts (temporal supersede) · renderLedgerBlock · buildRecallNote
src/guard/     detectors (fabrication, denial, bait-adoption, stance-flip) · corrections · runGuards chain
src/seal/      findCollisions · sealWebResults (the namesake guard)
src/scrub/     scrubToolSyntax (calls + JSON blobs, fence-aware)
src/agents/    createTrio — reference three-role / shared-record architecture
src/store/     the two-function store contract + in-memory reference
eval/          the gauntlet (13 turns, 12 needles) + scoring rubric + runner

The trio is a reference architecture, not a product harness. Proposer / verifier / builder over one shared record, verifier silent by default, guards on every reply. The role prompts are deliberately generic five-liners — real deployments earn their personas through evals. The mechanism is the gift; the tuning is your work.

Run the gauntlet on YOUR stack

node eval/run-gauntlet.js                 # built-in trio, any API key

or feed any turn(userMsg) → { text } function to runGauntlet() — your app, your agent framework, a raw model. Score the transcript with eval/rubric.md. If you publish numbers, publish the caveats too: N, judge model, run conditions.

The five rules (what actually moved the score)

  1. Fix behaviour with structure, not more prompt text.
  2. Capture facts to a record — then abstain, don't guess.
  3. One voice decides where to look — "prefer", never "only".
  4. Show the record; don't assert about it.
  5. Re-test every change on a clean run, meter on.

Honest scope

Regex-based extraction, English-first, precision over recall by design (a noisy ledger is worse than a thin one — the conversation window remains the primary memory). This is a small sharp kit, not a framework. Maintenance is best-effort: issues with failing-test reproductions get attention first; feature requests may sit.

Where this comes from

Extracted from the context engine behind Doric — an environment where an AI team builds software with you and keeps the line: every decision filed, every fact recorded, nothing lost between sessions. The benchmark story behind this library, run by run: doric.build/blog/keepline.

The bundled gauntlet is ONE scenario; the full multi-scenario suite (with blind-authored scenarios and the tuning disclosure) is plotline.

Sibling packages: shipline (deploy only the Firebase functions your change affects) · wireline (find code that is built but never wired).

MIT © Gabriel Kerner

About

Context integrity for LLM chat sessions: deterministic fact capture, confabulation + sycophancy guards, and the gauntlet that scores them. Zero-dep, bring your own model.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages