ZK-Andy
dsh-continual-evolve
Continual self-evolution plugin for DeepSeek Harness: versioned, auditable, rollback-safe harness state refined from session trajectories, with a benchmark-driven validation loop.
- Stars
- 0
- Language
- TypeScript
- Created
- Aug 13, 2026
- Updated
- Aug 14, 2026
Introduction
dsh-continual-evolve
中文 | English
Continual self-evolution for DeepSeek Harness: a versioned, auditable, rollback-safe layer of harness state — prompt notes, memories, skills, and subagent specs — refined from session trajectories.
Status: all phases complete. Phase 2 adds a real system-prompt section:
promptentries are injected as additive prompt notes andsubagententries as reusable delegation specs — both capped (6/kind, 180 chars), inherited by subagents through the parent-session chain, and dropped entirely when the store is empty (zero token cost). On top of that, Phase 3's evaluation matrix runner (host-planesubagents, frozen runtime, structured-output cells) feeds a code-owned scoreboard; the non-regressive acceptance rule decides accept/reject with no model-written aggregates.
Background
This project started as a research question: can a harness improve itself, and what would a production-grade version look like? Three lines of evidence shaped the answer:
- penguin-harness demonstrated the concept (benchmark → evaluate →
optimize → accept/rollback) but with zero code-level enforcement — every
guarantee was a prompt contract. Its report (
docs/research/) became the hardening checklist this project implements. - prime-agent
/refineproved the engineering shape: versioned harness entries, atomic persistence, optimistic concurrency, inverse-op rollback. This package is an original implementation of that shape on the DSH plugin surface. - Academic work (Self-Harness, AHE, HarnessOpt-Bench) supplied the discipline: frozen evaluation runtime, code-owned aggregation, non-regressive acceptance.
The result: the model proposes, the code guarantees. Every mechanical safety property (schema validation, snapshots, versioning, audit trail, acceptance decisions) is enforced in code — never by asking the model to behave.
Why
Agents accumulate reusable experience in every session — repeated failures, durable facts, reusable procedures — and then forget it at the next turn or session. This plugin makes that experience first-class persistent state:
- Versioned entries keyed by kind (
prompt/memory/skill/subagent), each with a recorded provenance and version - Evidence trail: every refinement appends an event carrying
trigger / changes / evidence / outcome - Deterministic rollback: inverse edits are generated from applied results — no LLM re-guessing
- Code-enforced safety, not prompt discipline: schema validation, atomic writes, corrupt-file degrade, optimistic concurrency, immutable base system prompt
- Local (session) and global (cross-session) scopes with merge semantics
Design provenance
Inspired by three bodies of work (see docs/design.md):
- prime-agent
/refine(MIT): the state model, atomic persistence, optimistic concurrency, per-edit validation, and inverse-op rollback this package implements — annotated reference source indocs/research/prime-agent-refinement.ts. The code here is an original implementation, written for the DSH plugin surface. - penguin-harness (Apache-2.0): the benchmark-driven evolution loop — research report in
docs/research/penguin-harness-self-evolution.md; its prompt-only contracts are the anti-pattern this package hardens. - Academic: Self-Harness (arXiv 2606.09498), AHE (arXiv 2604.25850), HarnessOpt-Bench (arXiv 2608.06301).
Tech stack
| Layer | Choice |
|---|---|
| Language | TypeScript (strict, ES2024, ESM) |
| Runtime | Node ^22.19.0 || >=24.0.0 (matches DSH) |
| Plugin seam | @deepseek-ai/cordis (name / apply / inject entry) |
| Package manager | pnpm (DSH ecosystem standard) |
| Build | tsc → lib/ (main lib/index.js, types lib/index.d.ts) |
| Tests | Vitest |
| Lint | oxlint (DSH official repo convention) |
| License | MIT |
Project layout
dsh-continual-evolve/
├── package.json # exports / files / engines / scripts + dsh.bundle manifest
├── cordis.patch.yml # bundle patch (dsh plugin add activates on install)
├── tsconfig.json / .oxlintrc.json / .editorconfig / .gitignore
├── LICENSE / README.md / README.zh.md
├── docs/
│ ├── design.md # full design doc (incl. hardening matrix)
│ └── research/ # penguin-harness report + prime-agent reference source
├── src/
│ ├── index.ts # cordis plugin entry (service mount + wiring)
│ ├── types.ts # HarnessState / entry / edit / result types
│ ├── state.ts # atomic persistence, corrupt degrade, merge, concurrency
│ ├── validate.ts # code-enforced edit validation
│ ├── apply.ts # per-edit apply pass with optimistic locking
│ ├── rollback.ts # deterministic inverse-op rollback
│ ├── plan.ts # proposal JSON parsing (truncation-aware)
│ ├── tool.ts # evolve_* model-facing tools (5)
│ ├── command.ts # /evolve command (incl. benchmark subcommands)
│ ├── planner.ts # ctx.llm planner
│ ├── render.ts # bounded prompt rendering
│ ├── inject.ts # dynamic system-prompt section (prompt notes + delegation specs)
│ ├── auto.ts # auto-review gate (turn/compaction triggers + audit)
│ ├── goal.ts # goal-driven evolution rounds (/evolve goal)
│ ├── review.ts # gate LLM judgment
│ ├── approval.ts # human approval for global edits
│ ├── skill.ts # skill materialization ($DSH_HOME/skills/)
│ ├── mount.ts # hot-mounted skill plugins (loader.create + boot restore)
│ ├── benchmark.ts # benchmark store
│ ├── rubric.ts # rubric ACL (AES-256-GCM envelopes)
│ ├── score.ts # code-owned aggregation + acceptance rule
│ ├── evaluate.ts # evaluation matrix runner (structured-output subagents)
│ ├── store.ts # store layout + snapshots + result history
│ └── service.ts # evolution engine (onApplied hook)
└── test/ # 16 files, 112 tests
In-session usage (after restart)
/evolve help + current local store
/evolve list [global] list entries
/evolve history applied refinements (ids for rollback)
/evolve rollback <id> deterministically revert a refinement
/evolve plan [msg] LLM planner against the current store
/evolve export <path> backup the local store to JSON
/evolve import <path> restore a store from an export file
/evolve mount <skillId> hot-mount a skill entry as a live cordis plugin (tool: skill_<name>)
/evolve mount list list hot-mounted plugins (restored on boot)
/evolve unmount <id> remove a hot-mounted plugin
/evolve goal show the evolution goal (round-driven auto-review)
/evolve goal <objective> create/update the evolution goal — while active, the review gate runs EVERY round
/evolve goal done complete the evolution goal
Model-facing tools: evolve_list, evolve_add, evolve_update, evolve_delete, evolve_rollback.
Benchmark-driven validation (Phase 3)
/evolve benchmark new <title> [runs] create a benchmark (runs = repeats per case, default 1)
/evolve benchmark add-case <bid> <title> <statement> <rubric>
/evolve benchmark list list benchmarks
/evolve benchmark reset <bid> clear the scoreboard (re-run reference)
/evolve benchmark status <bid> scoreboard + decisions
/evolve benchmark run <bid> evaluate current state → reference
/evolve benchmark run <bid> candidate <refinementId> evaluate post-refinement state → decide
The loop: freeze a reference score → evolve a candidate (/evolve plan) →
run the same case × run matrix against the post-refinement state → the
code-owned acceptance rule keeps the candidate only if the overall mean
strictly improves with no case regressing (Self-Harness style). The model
produces raw per-cell scores only; aggregation and decisions live in
src/score.ts. Rubric isolation is by construction (the planner never sees
rubric files); rejection is recorded and suggested for rollback (human in
the loop, no auto-rollback).
Real recorded run (ACCEPT)
A live dsh web session, one case, one candidate — the first genuine
acceptance:
| Step | Command | Outcome |
|---|---|---|
| reference | /evolve benchmark run lint_convention | 90 — the evaluator agent actually grepped the harness store and reported "lint/ruff/eslint/mypy appear in zero entries" |
| candidate | /evolve plan 记住:写代码前必须先运行适用的 lint 检查 | creates memory:convention_lint_before_code |
| re-evaluate | /evolve benchmark run lint_convention candidate <id> | 100 — evaluator ran evolve_list, hit the memory, quoted it verbatim |
| decision | — | overall: 90 → 100 · lint_knowledge: 90 → 100 · DECISION: ACCEPTED |
The evaluator does not grade model common sense — it inspects the actual
harness state under test (grep, evolve_list) and scores against it, so a
harness change measurably moves the score. Earlier runs in the same session
produced honest REJECTED decisions (0 → 0 placeholder cases, and 100 → 100
where the baseline was already perfect).
Configuration
| Key | Default | Meaning |
|---|---|---|
baseDir | resolved DSH home | root for the evolve/ stores |
sectionOrder | 118 | system-prompt section order |
autoReview | false | enable the automatic review gate (costs a cheap model call per interval) |
reviewIntervalTurns | 6 | gate runs when this many turns passed since the last review |
maxReviewInputChars | 40000 | trajectory slice handed to the gate |
reviewBudgetTokens | 4096 | output budget for the gate call |
requireGlobalApproval | true | cross-session (global) edits ask the user for "批准" before applying |
skillsDir | <dshHome>/skills | root where skill entries materialize as SKILL.md bundles |
rubricKey | DSH_EVOLVE_RUBRIC_KEY → dev key | passphrase for AES-256-GCM rubric encryption (benchmark rubrics never touch the disk in plaintext) |
Example (profile cordis.patch.yml):
- insert:
- id: continual-evolve
name: 'dsh-continual-evolve'
config:
autoReview: true
reviewIntervalTurns: 6
Development
pnpm install # install dev deps
pnpm build # tsc -> lib/
pnpm test # vitest run
pnpm lint # oxlint src test
Hit a wall? See docs/FAQ.md — real failure/fix records (service planes, schema DSL, structured output, gate counting, verifying prompt injection).
Roadmap
- Phase 1 (done): pure-core engine — state model, validation, apply, rollback, proposal parsing; tested.
- Phase 1b (done):
evolve_*tools,/evolvecommand, and thectx.llmplanner; installed into the web profile. - Phase 2 (done): ✅ auto-refine review gate (turn-interval checkpoints); ✅ compaction checkpoint (
compaction/start); ✅ global-scope approval gate (userQuestions); ✅ executable skills (materialize to$DSH_HOME/skills/); ✅ prompt entries injected as a real system-prompt section (additive, capped 6/kind, inherited by subagents through the parent chain); ✅ subagent entries rendered as reusable delegation specs at the delegation seam. - Phase 3 (done): ✅ benchmark-driven validation loop — evaluation matrix via the workflow engine, code-owned scoreboard aggregation, non-regressive acceptance rule, rubric isolation by construction; ✅ rubric ACL (rubric plaintext never on disk — AES-256-GCM envelopes, decrypted only by the evaluation runner); ✅ hot-mounted skill plugins (
/evolve mount <skillId>, live loader entry, restored on boot); ✅ goal-driven evolution rounds (/evolve goal— an active goal drives the review gate every round). (Future: automated rollback on rejection.)
License
MIT. Independent project — not affiliated with DeepSeek.