# dsh-evolve-in-git
Git-backed long-term memory and evolution plugin for DeepSeek Harness. ## Contents - [What it does](#what-it-does) - [Install](#install) - [Usage](#usage) - [Architecture](#architecture) - [Data layout](#data-layout) - [Config](#config) - [Harness entry points](#harness-entry-points) - [Browser half](#browser-half) - [Development](#development) - [Delivery notes](#delivery-notes) - [License](#license) ## What it does This plugin treats a user-chosen or preconfigured Git repository as the memory store. It can write session notes, branch-specific records, and reusable skill drafts into that repo, then commit them as ordinary Git history. ## Install ```sh # example: install into the web profile dsh plugin --profile web add github:Kytolly/dsh-evolve-in-git ``` The bundle inserts one `dsh-evolve-in-git` row with the plugin defaults. Later profile patches can override `repoPath`, `repoUrl`, `auth`, and the storage roots. ## Usage ### Natural language You do not need to remember tool names — describe the outcome and the model selects the right `evolve_*` / `memory_*` tool: | You say (or similar) | The model uses | | --- | --- | | "Remember: whenever X happens, do Y" | `evolve_remember` / `memory_save` | | "Any memory about the deploy flow?" | `evolve_recall` / `memory_search` | | "Read my recent memory history" | `evolve_timeline` | | "Turn this warning into a reusable skill" | `evolve_skill_draft` → `evolve_skill_promote` | | "What is the memory repo's current state?" | `evolve_status` / `evolve_branches` | | "Undo the last memory commit" | `evolve_rollback` | ### Commands (`/evolve`) For explicit, deterministic control, type `/evolve` uses the same metadata-indexed recall, so it > returns the same ranked results rather than a different matcher. > > **Archive constraint.** `archiveRoot` must stay outside `memoryRoot` (the > default `.dsh-evolve/archive` does). If you point `archiveRoot` inside > `memoryRoot`, forgotten records are still scanned and will not disappear. ### Per-user config file Each DSH user keeps one local config file at `$DSH_HOME/evolve-in-git.json` (`~/.dsh/evolve-in-git.json` by default). It is **user-local and never part of any Git repository** — do not commit it. The file is the **single user configuration layer**: the web Settings → 演进记忆 form reads and writes exactly this file (showing the defaults overlaid by your file values, and saving writes the file immediately), and the `/evolve config show|open|refresh|set` commands edit it too. The embedded config-file editor opens the raw JSON. Example: ```json { "repoPath": "/absolute/path/to/your/local-memory-checkout", "repoUrl": "https://github.com/ / .git" } ``` > **Never put access tokens in this file** — use `auth.tokenEnv` to name an > environment variable, or the web settings token field (write-only). The web Settings → 演进记忆 section also embeds a **config-file editor** that opens this file directly, edits it as raw JSON, and saves it through the loopback-only `/api/evolve-git/config` route (saves apply immediately). ## Harness entry points The plugin targets the current Harness `0.1.1-rc.2` host contracts for commands, tools, system prompt, and invariants (peerDependencies are `^0.1.1-rc.2`). Install it into a profile, then restart that profile so the bundle layer is composed. Tools: - `evolve_connect` - `evolve_status` - `evolve_remember` - `evolve_update` - `evolve_forget` - `evolve_restore` - `evolve_show` - `evolve_export` - `evolve_branches` - `evolve_branch_switch` - `evolve_branch_diff` - `evolve_skill_draft` - `evolve_skill_list` - `evolve_skill_promote` - `evolve_skill_demote` - `evolve_rollback` - `evolve_conflicts` - `evolve_resolve` - `evolve_timeline` - `evolve_recall` - `evolve_help` - `memory_search` (alias of `evolve_recall`) - `memory_save` (alias of `evolve_remember`) - `memory_update` (alias of `evolve_update`) - `memory_delete` (alias of `evolve_forget`) Human command: - `/evolve connect` - `/evolve status` - `/evolve branches` - `/evolve remember [--expires ] :: ` - `/evolve update [--merge] :: ` - `/evolve forget ` - `/evolve restore ` - `/evolve config show|open|refresh|set ` - `/evolve skill draft :: ` - `/evolve skill list` - `/evolve skill promote ` - `/evolve skill demote ` - `/evolve skill sync` - `/evolve rollback [--dry]` - `/evolve conflicts` - `/evolve resolve ` - `/evolve timeline` - `/evolve search [--kind k] [--tag t]` - `/evolve branch switch` \| `/evolve branch diff [b]` \| `/evolve branch revert ` - `/evolve help` After installation, verify composition before starting a long-lived profile: ```sh dsh --profile web --dump-config dsh --profile web ``` The first command should show the `evolve-git` row from the plugin bundle. The second command boots the profile; once loaded, the model sees the `evolve_*` tools and the UI command registry exposes `/evolve`. ### Bundled skills The package ships the `evolve-process` skill under `skills/`. On load the plugin materializes it into the repo's ` /drafts/evolve-process/` (creating it only when missing); `/evolve skill sync` overwrites the bundled copy on demand. Promote it with `/evolve skill promote evolve-process`. The adapter registers the repo's ` /enabled/` directory as a DSH skill provider, so promoted skills become callable without any copy into `~/.dsh/skills`. ## Browser half - `src/client/` - the browser bundle (`lib/client.js`) compiled by `tsc -p tsconfig.client.json && tsdown` (see `tsdown.config.ts`); registered as a `settings.section` slot so the web Settings page renders the config form. - `package.json` - `exports["./client"]` + `dsh.client` (`platform: "web"`) are the manifest contract `dsh-client-modules` scans to include the bundle in `window.__DSH_BOOT__`. ## Development Requires Node.js and pnpm. The workspace sets `nodeLinker: hoisted` and allows the `esbuild` build. ```sh pnpm install pnpm build # tsc (server) + tsc (client) + tsdown browser bundle npx pnpm test # regenerates the @deepseek-ai/dsh-tools stub, then runs tests npx pnpm typecheck # tsc --noEmit for both projects npx pnpm check # build + test (CI uses this) ``` The `prepack` script runs `pnpm build`, so published `lib/` artifacts are always current. Tests live under `tests/*.spec.ts` and run with `node --test` via `tsx`. ## Delivery notes `v0.6.3` finalized the MVP: metadata-indexed recall with budgets, versioned update (`supersedes`/`supersededBy`), soft-delete/restore plus expiry, reversible skill drafts with the repo `enabled/` directory registered as a DSH skill provider, the `block`/`redact`/`ask` privacy write gate, and the `memory_*` aliases plus the session-start `persona`+`warning` digest. Verification: `npx pnpm check` (build + test; `build` also typechecks) is green. ### Known non-blocking TODOs - `getMemoryIndex` still re-walks the memory root on cache hits (correctness over speed); a watcher-based cheap signature is future work. - The privacy gate covers memory writes (`writeMemoryRecord`/`updateMemory`); skill-draft writes (`writeSkillDraft`/`saveSkillDraftFromRecord`) are intentionally outside the gate (documented memory-only scope). - `classifySensitivity` never assigns `internal`; the `internal` export level is reachable only when a record is hand-authored with that frontmatter value. ## License MIT — see [LICENSE](LICENSE).