Back to home@sANDzER0

dsh-hippocampus

Cross-session project memory for DeepSeek Harness — capture / consolidate / recall, keyword + optional local-Ollama semantic search. Inspired by magic-context.

Stars
0
Language
JavaScript
Created
Aug 26, 2026
Updated
Aug 26, 2026

Introduction

dsh-hippocampus

License: MIT Platform: DSH web profile

A self-managing cross-session project memory layer for DeepSeek Harness (DSH) — the Capture / Consolidate / Recall loop of cortexkit/magic-context, reimplemented as a native DSH plugin.

Status: feature-complete and verified against real workloads. Memory tools, prompt injection, event-driven auto-capture, consolidation subagents, CJK-tokenized keyword search, optional semantic search (local Ollama or OpenAI-compatible), compaction checkpoints + memory-aware compaction summaries, a signal-gated retrospective capture pass, and a settings page inside the DSH web UI.

Background

DeepSeek Harness (DSH) is a Cordis-based agent harness: every capability is a plugin row in a cordis.yml composition, services/events/slots are the extension primitives, and dsh web serves the GUI. This project ships as one host-composition row, so every session of every preset gets the memory layer — no per-session mounting.

magic-context is an excellent memory system for OpenCode/Pi-style harnesses. This project is a from-scratch native reimplementation of its ideas on DSH primitives — none of its code is used.

How it differs from magic-context

magic-contextdsh-hippocampus
ScopeMemory layer plus context management (historian compartments, m[0]/m[1] cache-stable transform, byte-exact replay)Memory layer only — DSH owns compaction and context shaping
StorageSQLite (context.db, FTS5, vector BLOBs)DSH storageDomain JSON snapshots (whole-snapshot RMW, serialized writes)
Retrievalsqlite-vec / local ONNX / remote embeddingsIntl.Segmenter CJK tokenization + scored ranking; optional local Ollama or any OpenAI-compatible /embeddings; in-JS cosine
CaptureHistorian fact promotion tied to its compartment engine; dreamer cron tasksRegex heuristics + a signal-gated retrospective pass whose child writes through idempotent tool calls; pre-compaction trigger slot
CompactionReplaces the host's compaction entirelyObserves and enriches DSH's native compaction (checkpoint capture + memory-aware summaries) without touching ownership
PackagingMulti-package monorepo (TS + Rust)Two plain-JS function bodies (src/host.js, src/client.js) derived to deployable ESM by one script — zero build dependencies

The full design rationale — scope boundary, pipeline details, and platform implementation notes — lives in DESIGN.md.

Features

  • Durable memoriesctx_memory (write / list / delete) across five curated categories plus auto-managed CHECKPOINT entries; scoped to a stable project identity so memory follows the project, not the session.
  • Recallctx_search over memories and notes: CJK-aware token scoring, verbatim-substring strong hits, optional semantic cosine, plus cross-session history search when the deployment enables session-query-sqlite.
  • Prompt injection — top-importance memories are rendered into every model turn (bounded by count and character budget).
  • Auto-capture — decision/constraint phrasing in user messages and writes to well-known config files become memories; a content classifier keeps machine-originated texts (harness snapshots, reminders, own child reports) out.
  • Retrospective capture/ctx-retro scans buffered recent user messages; correction/restatement signals dispatch one subagent that distills durable facts and writes them itself via idempotent ctx_memory calls. Timer and pre-compaction triggers included, with cooldown and single-flight latches.
  • Dreamer consolidation/ctx-dream spawns a continuable subagent that dedupes/curates memories and reports back into the session.
  • Compaction-aware — compaction summaries are stored as searchable CHECKPOINT memories (T0), and durable memories are injected into the summarizer input so summaries stay continuity-aware (T1).
  • Settings page — a Magic Context section in the DSH web settings: semantic search on/off, provider switch (local Ollama / OpenAI-compatible endpoint), endpoint/model/key, Ollama detection and service start, injection budgets, capture toggles — all live (no restart needed).

Requirements

  • A DSH deployment with the web profile (dsh web). The plugin targets the Node runtime DSH ships (v24-class); no extra dependencies.
  • Optional, for semantic search only: Ollama with a multilingual embedding model (ollama pull bge-m3, ~1.2 GB). Without it the plugin runs fully keyword-only — every failure path degrades silently.

Deploy

node sync.mjs     # derive index.mjs + client.mjs + package manifest into the profile
                  # (~/.dsh/profiles/web/node_modules/@local/dsh-hippocampus/)

then register one insert row in the same profile's patch layer (~/.dsh/profiles/web/cordis.patch.yml):

- insert:
    - id: dsh-hippocampus
      name: '@local/dsh-hippocampus'

and restart dsh web (ESM is cached per process). sync.mjs validates both halves (node --check + import smoke test) before writing anything.

Why a derived file? The loader imports the row as a real ES module while src/host.js / src/client.js are written as plain function bodies (also valid as dynamic-plugin code.host / code.client definitions). Never bare-copy the sources — a top-level return is fatal under ESM.

Configuration

Open Settings → Magic Context in the web UI. Everything applies live:

GroupKnobs
Semantic searchenable · provider (Ollama / OpenAI-compatible) · endpoint · model · API key · connection probe · index rebuild
Local Ollamastatus detection (reachable / installed / missing) · start background service
Injection & captureinjection count cap · character budget · auto-capture toggle · retrospective auto-trigger toggle

Settings persist in the memory domain (mc:cfg) and are merged over defaults at read time. The API key never appears in GET responses, and write routes only accept loopback peers.

Repository layout

dsh-hippocampus/
├── DESIGN.md          # Design doc: scope, pipelines, compaction integration,
│                      #   config model, DSH static-plugin implementation notes
├── src/
│   ├── host.js        # Host half (plain JS function body): tools, injection,
│   │                  #   capture listeners, retrospective, /mc-api bridge, T1 wrap
│   └── client.js      # Client half (plain JS function body): Magic Context settings page
├── sync.mjs           # Derives deployable ESM for both halves + package manifest; validates
├── package.json
├── LICENSE            # MIT
└── README.md

Verification highlights

Exercised against real workloads rather than mocks:

  • Durability and idempotent writes survived process restarts and plugin updates.
  • A real /compact produced a checkpoint memory end-to-end; the summarizer's own output confirmed the injected memory block was present in its input.
  • Zero-overlap paraphrase queries ("怎么发布上线" vs a memory that only ever says "部署必须经 sync.mjs") are recalled by the semantic channel alone (sim ≈ 0.52) — unreachable by keyword scoring by construction.
  • Machine-originated texts (runtime snapshots, harness reminders, child reports) are kept out of the memory pipeline by a content classifier — in live traffic, not just in tests.

Notes & limitations

  • Semantic search adds one embedding call per query (~6 s warm CPU inference for bge-m3; the request pins keep_alive: 30m so idle gaps don't re-pay the ~41 s cold load). Timeouts are split per scenario (query 8 s / probe 60 s / sweep 120 s).
  • Cross-session history search requires enabling session-query-sqlite in the profile patch layer (shipped opt-in with openAt: never).
  • Sub-agent reports spliced into a session are filtered by signature and structure; novel prose-shaped reports remain a theoretical capture risk — delete stray rows via ctx_memory delete if one ever slips through.
  • Concurrent mutations to a storage domain must be serialized: the JSON store persists whole snapshots (read-modify-write). All automatic writes in this plugin go through one promise chain for exactly this reason.
  • The storage layer duck-types domain valueSchema (only .parse/.safeParse are called), so the plugin body needs no zod dependency.

License

MIT — see LICENSE.