Back to home

MetheusNull

dsh-passive-memory

Evidence-linked passive long-term memory for DeepSeek Harness · 让长期记忆自然涌现

Stars
0
Language
TypeScript
Created
Aug 15, 2026
Updated
Aug 15, 2026

Introduction

DSH Passive Memory

DSH Passive Memory

English · 简体中文

An experimental passive-memory plugin for DeepSeek Harness.

Release status: 0.1.0-alpha.1 developer source preview. It is intended for one operator and a small personal archive. It is not yet an npm package or a production multi-user service.

The project starts from one rule: conversation and tool events are evidence; memories are derived views. Derived memories must remain traceable to their sources and rebuildable when extraction logic changes.

Conversation evidence, L0, L1, passive recall, and neighborhood expansion

Five-minute developer start

The alpha release uses a sibling DeepSeek Harness source checkout. Node.js ^22.19.0 || >=24.0.0, Git, Corepack, and pnpm 11.7.0 are required.

mkdir passive-memory-workspace
cd passive-memory-workspace
git clone https://github.com/deepseek-ai/deepseek-harness.git
git clone https://github.com/MetheusNull/dsh-passive-memory.git

cd deepseek-harness
git checkout 47f943859bef60e4160492346772ded9b24f765a
corepack enable
pnpm install
pnpm run build

cd ..\dsh-passive-memory
pnpm install
Copy-Item .env.example .env

Edit .env and set one absolute database path plus three stable isolation ids:

PASSIVE_MEMORY_DB_PATH=C:/absolute/path/passive-memory.db
PASSIVE_MEMORY_USER_SCOPE=one-user
PASSIVE_MEMORY_AGENT_SCOPE=one-agent
PASSIVE_MEMORY_WORKSPACE_SCOPE=one-workspace

Build, run the complete offline test suite, and launch the local-only lexical baseline:

pnpm run build
pnpm test
pnpm run start:harness -- ../deepseek-harness lexical

Open http://127.0.0.1:3080. Lexical mode makes no external embedding request. The episode and hybrid modes are explicitly opt-in; see deployment/README.md. Protect the resulting database as private conversation history and read PRIVACY.md before enabling remote compression or embeddings.

Current state

L0 ingestion, host-side lexical/semantic retrieval, deterministic L1 candidate segmentation, opt-in automatic L1 compression, and opt-in lexical or hybrid model-visible recall are operational. L1 summaries can now enter that recall as explicitly lossy clues, while two native Harness tools let the Agent inspect their authoritative L0 sources. The repository contains:

  • an L0 external-dialogue format for legacy transcripts;
  • a deterministic Markdown importer;
  • a synthetic public fixture plus an ignored real validation corpus with line-level provenance;
  • a unified SQLite L0 store for native DSH events and external dialogue;
  • a scope-gated Chinese-capable trigram FTS/BM25 lexical search;
  • deterministic, source-linked L1 interval segmentation without model calls;
  • resumable L1 compression through the Harness's registered LLM service, with complete L0 mappings and provider/model/prompt/token provenance;
  • an experimental agent/pre-step recall injection with strict scope and size bounds;
  • model-invisible recall audits in the plugin-owned SQLite store;
  • memory_expand, with HMAC-authorized pagination and three bounded neighborhood rings;
  • memory_search_raw, a scoped L0 full-text fallback for finding a new anchor;
  • content-free active-tool audits, with memory-tool results excluded from L0 ingestion;
  • a synthetic positive/negative recall evaluation runnable without APIs;
  • a rebuildable, content-deduplicated SQLite embedding cache;
  • exact-scope semantic retrieval and reciprocal-rank fusion seams;
  • a synthetic-only live semantic smoke test that never reads the real store;
  • an operator-approved real-corpus hybrid recall validation with redacted output;
  • a real Cordis Loader composition test and two explicit local deployment overlays;
  • a Cordis plugin that backfills live sessions and observes future events;
  • a mapping from a VCP-era persona-design workflow to the new architecture;
  • validation tests that keep reasoning traces quarantined by default.

No fixture is written into a DeepSeek Harness session log. Online DSH sessions will remain the authoritative source for native events; external history enters through a separate source boundary and is recalled later through a DSH form: "recall" context.

Implemented ingestion behavior

  • Direct user messages are stored.
  • Displayed assistant text is stored; reasoning and tool-call blocks are not.
  • Ordinary tool results are stored as evidence but are not recall-eligible yet.
  • memory_expand and memory_search_raw results are derived archive projections and are never copied back into L0.
  • Plugin-produced user-role context is excluded, including form: "recall".
  • Existing live sessions are backfilled when the plugin mounts.
  • Repeated observation of an identical source event is idempotent.
  • A source identity collision with different content fails instead of silently overwriting evidence.
  • Reused session ids remain distinct through the immutable session-header hash.
  • session/flush reports any earlier ingestion failure.
  • Lexical search requires exact user, agent, and workspace scopes and never returns evidence outside them.

A supplied real external corpus was locally verified; its displayed messages entered L0 while its recorded reasoning traces remained quarantined and did not enter the SQLite evidence table. The corpus and its derived metadata are excluded from Git by LOCAL_DATA_POLICY.md.

Plugin configuration

The plugin requires a database path and explicit retrieval scopes:

plugin: "dsh-passive-memory"
config:
  path: "./runtime/passive-memory.db"
  userScope: "user"
  agentScope: "deepseek-agent"
  workspaceScope: "personal"
  journalMode: "wal"
  recallEnabled: true
  recallMaxResults: 3
  recallMaxCharacters: 2400
  recallQueryMaxTerms: 24
  semanticRecallEnabled: false
  semanticMaintenanceEnabled: true
  semanticMaintenanceIntervalMs: 60000
  semanticMaintenanceRetryBaseMs: 5000
  semanticMaintenanceRetryMaxMs: 300000
  semanticBackfillMaxRecords: 64
  semanticBatchSize: 32
  semanticCandidateDepth: 24
  semanticMinimumScore: 0.62
  fusionRankConstant: 60
  semanticFailurePolicy: lexical-fallback
  episodeCompressionEnabled: false
  episodeCompressionPromptVersion: episode-summary-v1
  episodeCompressionMaxTokens: 1024
  episodeCompressionMaxSummaryCharacters: 4000
  episodeSegmentationMaxCharacters: 12000
  episodeSegmentationIdleGapMs: 1800000
  episodeMinimumNativeTailAgeMs: 21600000
  episodeMaintenanceMaxEpisodes: 4
  episodeMaintenanceIntervalMs: 300000
  episodeMaintenanceRetryBaseMs: 30000
  episodeMaintenanceRetryMaxMs: 1800000
  episodeRecallEnabled: true
  episodeRecallMaxResults: 2
  episodeRecallMaxCharacters: 2000
  memoryToolsEnabled: true
  memoryExpandMaxDepth: 3
  memoryExpandMaxCharacters: 6000
  memoryExpandLocalRecordsEachSide: 4
  memoryExpandSessionRecordsEachSide: 16
  memoryRawSearchMaxResults: 5
  memoryRawSearchMaxCharacters: 8000

All four scope/path strings must be non-empty. The deployment, rather than the plugin, decides what an agent and workspace identity mean. Model-visible recall is experimental and defaults to false; the example opts in explicitly. Semantic recall is a second opt-in and remains disabled in the example. When enabled, its provider settings and credential come from the PASSIVE_MEMORY_EMBEDDING_* process environment variables shown in .env.example; the plugin configuration never contains the key. Its document vectors are maintained in bounded background passes; the request path sends only the current query. lexical-fallback keeps local recall available during a provider outage, while fail-request preserves strict failure semantics.

Episode compression is independent of model-visible recall and defaults to false. When enabled without episodeCompressionProvider and episodeCompressionModel, a native episode inherits the last assistant model recorded in its L0 evidence; an episode without such provenance (including an external import) uses Harness's current agentDefaultModel. Setting both fields selects a fixed compression model instead. The plugin introduces no API key or provider client of its own. Each maintenance pass can make at most episodeMaintenanceMaxEpisodes model calls; external transcript tails are eligible immediately, while a native session tail waits episodeMinimumNativeTailAgeMs unless a stronger deterministic boundary closed it. The inherited policy remains one derivation when the user later changes the chat model, so completed memories are not recompressed; only future uncovered episodes use the new default. Changing segmentation, closure, prompt version, output budget, or an explicit fixed-model override creates a separate derivation.

L1 clue recall and active tools are separate opt-ins. When episodeRecallEnabled is true, a matching title/summary is injected only as a source-labelled clue containing an episode_id; raw text covered by that clue is not duplicated in the automatic L0 excerpt block. memory_expand starts at depth 1 (the exact episode mapping or evidence hit), then returns an opaque authorization token for depth 2 (the immediate neighborhood) and depth 3 (the broader same-collection neighborhood). The model cannot select or forge a depth. Truncated text uses a same-depth page token, so pagination is not mistaken for broader recall. A per-call ceiling and a per-turn ceiling of at most memoryExpandMaxDepth × memoryExpandMaxCharacters bound tool output.

memory_search_raw remains a separate fallback rather than a fourth expansion depth. It searches exact user/agent/workspace scopes, excludes the current session, and returns L0 evidence IDs plus any L1 episode anchors. Both tools label returned content as untrusted data, keep content out of their audit records, and preserve the original content hash and source coordinates.

ctx.passiveMemory.embeddingMaintenanceStatus() exposes content-free, process-local health counters and timestamps. See docs/maintenance-operations-v0.1.md. The corresponding L1 snapshot is available from ctx.passiveMemory.episodeMaintenanceStatus().

Memory layers

  • L0 evidence: append-only native session events and immutable imported source records.
  • L1 episodes: automatically segmented, compressed views with mappings back to L0.
  • Stable identity kernel: deliberately small, human-reviewed identity and relationship facts.
  • Evolving self-model: versioned, slow-changing interpretations derived from experience; never silently overwrites the identity kernel.
  • Diary: voluntary contemporaneous expression, not a required memory-write protocol.
  • Knowledge: a future structurally maintained corpus for private, non-standard, practice-linked information.

See docs/architecture-v0.1.md and docs/import-contract-v0.1.md. Local DSH loading is documented in deployment/README.md. The privacy-preserving real-corpus check is recorded in docs/real-memory-validation-v0.1.md. The real DeepSeek Harness conversation, compression, and cross-session recall smoke is recorded in docs/live-harness-validation-2026-08-15.md. The native Agent behavior tests for one-level and recursive L0 expansion are recorded in docs/real-model-active-memory-validation-2026-08-15.md.

Model experience

L0 ingestion with recall disabled

The model sees no additional text. The current plugin observes committed session events, writes normalized evidence, and exposes host-side lexical search.

Token effect is zero. KV-cache behavior is unchanged because no request prefix or surface message is added.

Experimental passive recall

When enabled, the first step containing direct human input derives a bounded lexical query and prepends one durable user-role context message immediately before the direct prompt. The source is { kind: "plugin", plugin: "passive-memory", form: "recall" }. Current-session evidence, exact prompt duplicates, duplicate excerpts, reasoning traces, and plugin-produced context are excluded. Tool continuations do not trigger another recall.

When L1 clue recall is enabled, derived title/summary text appears in a separate <passive_memory_clues> block. It explicitly instructs the model not to treat the compression as factual authority and to call memory_expand before relying on details omitted by compression. L0 remains the source of truth throughout.

The injected message has a hard character ceiling but no exact token guarantee; token cost depends on the selected model tokenizer. Because recall is a per-request suffix rather than a stable system-prompt prefix, it does not deliberately invalidate the stable-prefix KV cache. See docs/passive-recall-v0.1.md.

Every accepted recall attempt records an independent audit containing prompt and derived-query hashes, selected evidence/source ids, BM25 scores, limits, outcome, and rendered-text hash. Prompt and recalled text are not duplicated in the audit row.

Known limitations and deferred work

  • L1 compression and clue recall are implemented but default off. Hybrid evidence recall also defaults off; its 0.62 score floor is only a provisional result from a small synthetic calibration.
  • Trigram FTS ignores query terms shorter than three Unicode code points; a later hybrid retriever must cover short identifiers such as AI.
  • Non-text blocks are left only in the source DSH log and need explicit future importers.
  • Ordinary tool results remain evidence-only until a broader trust, sensitivity, and size policy is implemented; the two memory-tool projections are excluded.
  • Scopes are fixed per mounted plugin instance; multi-user and per-preset scope resolution is deferred.
  • The SQLite schema is prerelease version 7. Versions 2 through 6 migrate in place by adding missing tables, preserving each v5 L1 route as an explicit fixed-model policy, and backfilling the rebuildable L1 FTS index; other unknown versions are rejected.
  • Provider request failures are either audited lexical fallbacks or request failures according to semanticFailurePolicy. Local store and consistency errors always fail explicitly.
  • Semantic ranking currently performs an exact linear scan over all cached vectors inside the selected scope. This is suitable for correctness testing, not a production-scale personal archive; an indexed vector backend remains required before large-corpus deployment.
  • Maintenance health is inspectable through the Cordis service but is not yet persisted or exported to a UI, HTTP endpoint, or metrics backend.

Fixture policy

Legacy files may contain text labelled as model reasoning. Such blocks are kept for source fidelity but are marked restricted, quarantined, and ineligible for default memory indexing or replay. Final answers and user messages remain eligible L0 evidence.

Run the public lexical recall baseline with npm run evaluate:recall. It uses only synthetic fixtures and reports outcomes and counts without printing prompt or memory content.

The optional embedding-provider boundary and one-request connectivity probe are documented in docs/embedding-provider-v0.1.md. Live semantic recall remains separately opt-in and requires explicit provider configuration and credentials.

Feedback and contributing

The most useful report is a reproducible memory behavior: a missed recall, a false recall, an L1 clue whose expansion did not reach the necessary L0, a scope leak, or a memory feedback loop. The repository provides dedicated issue forms for memory quality, bugs, and feature requests.

Use synthetic or redacted examples. Never post credentials, complete private transcripts, databases, or private filesystem paths. See CONTRIBUTING.md for the reporting contract.

License and attribution

This project is released under the MIT License. It is an independent implementation inspired in part by the passive-memory-emergence ideas explored by lionsky through VCPToolBox and RiverMemo / 浪潮 Memo. No VCP source code or VCP-specific algorithm implementation is included in release 0.1.0-alpha.1.

See NOTICE.md, VCP_PROVENANCE.md, and DSH_PROVENANCE.md for attribution and provenance. Runtime data handling and security boundaries are documented in PRIVACY.md and SECURITY.md.

Release history is recorded in CHANGELOG.md. The alpha publication checks are recorded in docs/release-verification-v0.1.md.