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
English · 简体中文
An experimental passive-memory plugin for DeepSeek Harness.
Release status:
0.1.0-alpha.1developer 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.
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-steprecall 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_expandandmemory_search_rawresults 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/flushreports 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.