{"_id":"@ddv12138/dsh-hash-edit","name":"@ddv12138/dsh-hash-edit","dist-tags":{"latest":"0.1.0"},"versions":{"0.1.0":{"name":"@ddv12138/dsh-hash-edit","version":"0.1.0","description":"Hash-anchored read/replace/undo for DeepSeek Harness (DSH), ported from pi-hashline-edit-pro. Every line gets a stable 3-char base-62 anchor; stale/ambiguous anchors are rejected, never fuzzy-matched; undo persists across restarts.","license":"MIT","author":{"name":"ddv12138"},"keywords":["dsh","deepseek-harness","hashline","anchor","editing","plugin","agent","cordis"],"type":"module","main":"index.js","exports":{".":"./index.js","./core":"./src/plugin.js","./takeover":"./src/takeover.js","./engine":"./src/engine.js"},"scripts":{"test":"node --test"},"engines":{"node":">=20"},"dependencies":{"@deepseek-ai/dsh-tools":"^0.0.1-rc.1"},"dsh":{"bundle":{"patch":"./cordis.patch.yml"}},"_id":"@ddv12138/dsh-hash-edit@0.1.0","gitHead":"bd7fb9791b09417c20f36b3902625dae33162041","_nodeVersion":"22.22.3","_npmVersion":"10.9.8","dist":{"integrity":"sha512-3RVJKM2SENTRHSGMPkezWkgDTwpVEroeDFCD0aF10/337VWCvB+mGs0m0+J+cHLqwm/+gAOOsr33GJ3Hbl5i0A==","shasum":"9a18b9769a08b3b51260e2cca165cf125ab0fd97","tarball":"https://registry.npmjs.org/@ddv12138/dsh-hash-edit/-/dsh-hash-edit-0.1.0.tgz","fileCount":10,"unpackedSize":43632,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDriKCkVtHuHvVnCbdnmqc5nRIYbzNts6PhP+Zk95jn+AIgXETeZ9LNpJtmoBopqM6TkX8rPISjslIecfkomwVSRoc="}]},"_npmUser":{"name":"ddv12138","email":"644077730@qq.com"},"directories":{},"maintainers":[{"name":"ddv12138","email":"644077730@qq.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/dsh-hash-edit_0.1.0_1786787324709_0.31678401324349026"},"_hasShrinkwrap":false}},"time":{"created":"2026-08-15T09:48:44.547Z","0.1.0":"2026-08-15T09:48:44.859Z","modified":"2026-08-15T09:48:45.075Z"},"maintainers":[{"name":"ddv12138","email":"644077730@qq.com"}],"description":"Hash-anchored read/replace/undo for DeepSeek Harness (DSH), ported from pi-hashline-edit-pro. Every line gets a stable 3-char base-62 anchor; stale/ambiguous anchors are rejected, never fuzzy-matched; undo persists across restarts.","keywords":["dsh","deepseek-harness","hashline","anchor","editing","plugin","agent","cordis"],"author":{"name":"ddv12138"},"license":"MIT","readme":"<div align=\"center\">\n\n# @ddv12138/dsh-hash-edit\n\n**Hash-anchored read / replace / undo for DeepSeek Harness (DSH)**\n**为 DeepSeek Harness (DSH) 开发的哈希锚行读写 / 替换 / 撤销插件**\n\n_Ported from [`pi-hashline-edit-pro`](https://pi.dev/packages/pi-hashline-edit-pro) · 移植自 pi-hashline-edit-pro_\n\n</div>\n\n[![CI](https://img.shields.io/github/actions/workflow/status/ddv12138/dsh-hash-edit/ci.yml?branch=main&label=CI)](https://github.com/ddv12138/dsh-hash-edit/actions) [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)\n\n---\n\n## What it does · 它能做什么\n\nEvery line of a text file carries a **stable 3-character base-62 anchor**. Tools address lines by\nanchor instead of line number or raw text, so edits never corrupt the file: **stale or ambiguous anchors\nare rejected — never fuzzy-matched**. Undo persists across restarts.\n\n每个文本文件的每一行都带有一个**稳定、唯一的 3 位 base-62 锚点**。工具通过锚点（而非行号或原文）定位行，\n因此编辑绝不会损坏文件：**过期或歧义锚点一律拒绝——绝不模糊匹配**。撤销记录跨重启持久化。\n\n---\n\n## Install · 安装\n\nThis is a DSH **[bundle](https://deepseek-harness.github.io/deepseek-harness/develop/basic/publish)** —\nan npm package that ships a `cordis.patch.yml` layer. A bundle is what you author and distribute; a user\ninstalls it into a **profile**:\n\n这是 DSH 的 **[bundle（插件包）](https://deepseek-harness.github.io/deepseek-harness/develop/basic/publish)**——\n一个携带 `cordis.patch.yml` 配置层的 npm 包。插件作者只发布 bundle；用户把它安装进一个 **profile**：\n\n```sh\n# from a local checkout 从本地检出安装\ndsh plugin --profile demo add ./dsh-hash-edit\n\n# from GitHub 从 GitHub 安装\ndsh plugin --profile demo add github:ddv12138/dsh-hash-edit\n\n# from npm 从 npm 安装\ndsh plugin --profile demo add @ddv12138/dsh-hash-edit\n```\n\nMounting the bundle's patch inserts the `@ddv12138/dsh-hash-edit` row, which **takes over** editing (see next section).\nBecause you install it per profile, it works from **any preset / profile** — this is how \"usable from any\npreset\" is realized in DSH's model.\n\n把该 bundle 的 patch 装载进 profile 后，会插入 `@ddv12138/dsh-hash-edit` 插件行，从而**接管**编辑（见下节）。\n由于是按 profile 安装，它能在**任意 preset / profile** 下工作——这正是 DSH 模型里“任何 preset 都能用”的实现方式。\n\n---\n\n## Takeover · 接管行为(pi-aligned · 对齐 pi)\n\nWhen mounted, the plugin (package main `index.js` ⇐ `src/takeover.js`) does the following **per profile /\nagent scope**:\n\n插件装载后（包入口 `index.js` ⇐ `src/takeover.js`）在**每个 profile / agent 作用域**内执行以下动作：\n\n| Behavior 行为 | Detail 说明 |\n|---|---|\n| Shadow `read` 遮蔽内置 read | registers a hash-anchored `read` (scoped registration shadows the built-in) 注册哈希锚行 `read`（作用域注册遮蔽内置） |\n| `replace` & `undo_last_replace` | pi-faithful single-edit replace + persisted single-level undo 单次编辑替换 + 持久化单级撤销 |\n| Hide built-in `edit` 隐藏内置 edit | `tools.restrict({ deny: ['edit'] })` — session-scoped 会话级隐藏 |\n| Intercept `write` 拦截 write | `tools/result` appends an **auto-read** anchor block so anchors stay fresh 追加 **auto-read** 锚点块，锚点不再过期 |\n| Usage discipline prompt 使用纪律 prompt | one edit per file per message; copy bare hashes only 一个文件一条消息只改一次；只拷贝纯净哈希 |\n\n> **Why in a profile? → 为什么放在 profile？** DSH's `tools.restrict` and `tools/result` are **agent-scoped**,\n> so the takeover lives in the mounted plugin rather than a global host row. A host plugin can only register\n> tools.\n\n> DSH 的 `tools.restrict` 与 `tools/result` 都是 **agent 作用域**的，所以“接管”放在被装载的插件里，而不是全局\n> host 行。Host 插件只能注册工具，无法做每会话的接管。\n\nIf you only want the tools (no takeover), install the `core` plugin instead:\n如果只想要工具（不要接管），改用 `core` 插件：\n\n```yaml\n- id: hashline-core\n  name: '@ddv12138/dsh-hash-edit/core'\n```\n\n---\n\n## Tools · 工具\n\n| Tool 工具 | Purpose 用途 |\n|---|---|\n| `read` (hashline) | line → `HASH│content`, offset/limit paging; records the *served range* 行级输出 + 分页，记录*已展示区间* |\n| `replace` | `remove_from` / `remove_to` (bare 3-char hashes) + `replacement_text`（`\\n` 分隔；`\"\"` 删除区间）; **one edit per call** 一次调用只改一处 |\n| `undo_last_replace` | reverts the most recent replace, byte-exact (content + BOM + endings + anchors) 撤销最近一次替换，字节级还原 |\n\nRejections, **never fuzzy-match** · 拒绝规则，**绝不模糊匹配**：\n\n| Code 码 | Meaning 含义 |\n|---|---|\n| `[E_STALE_ANCHOR]` | anchor no longer exists in the current file 当前文件已无此锚点 |\n| `[E_AMBIGUOUS_ANCHOR]` | anchor matches >1 line 锚点对应多行 |\n| `[E_RANGE_STALE]` | file changed or the range was never shown 文件已变或该区间未被展示 |\n| `[E_BAD_REF]` | anchor not a bare 3-char hash 锚点不是纯净 3 位哈希 |\n| `[E_UNDO_STALE]` | file changed since the last replace 上次替换后文件被改动 |\n| `[E_FILE_TOO_LARGE]` | > 238,328 lines or > 100 MB 超行数/字节上限 |\n\n---\n\n## Anchoring · 锚定算法\n\n- `canon(line) = line.replace(/\\r/g, '').trimEnd()`\n- `xxHash32(canon, seed 0) >>> 14 % 238328` → a 3-char base-62 (`A-Za-z0-9`) anchor\n  （已验证与 `xxhashjs` 参考实现逐位一致 · verified bit-exact vs the `xxhashjs` reference）\n- Collisions resolved via a bitset probing with stride `3907 = 62²+62+1` (coprime with the anchor space) —\n  **unique anchors by construction** 冲突以步长 `3907` 互质位图探测消解，**构造性唯一**\n- Stable mapping 稳定映射：survivors keep anchors by nearest-position match; a removed line's anchor is\n  reused when identical text is re-inserted; new lines get fresh anchors\n  存活行按最近位置保留锚点；相同文本重新插入复用旧锚点；新行发新锚点\n- File caps 文件上限：≤ 238,328 lines 行 && ≤ 100 MB\n\n---\n\n## Store · 存储\n\n`.dsh-hash-edit/store.json` in the project workspace (gitignored) · 位于项目工作区（已 gitignore）：\n\n- `snap[absPath]` — current line/hash snapshot + last-served range + checksum 当前行/哈希快照 + 已展示区间 + 校验和\n- `undo[absPath]` — single-level undo record per file 每文件单级撤销记录\n\n---\n\n## Dev & CI · 开发与自动化测试\n\n```sh\nnpm ci\nnpm test          # node --test → runs test/ (engine unit + read→replace→undo integration)\n```\n\n`.github/workflows/ci.yml` runs `npm test` on **Node 20 & 22 for every push / PR**（每次 push / PR 自动验证）。\n\nTest files · 测试文件：`test/xxhash32.test.js`（xxHash32 位精确）、`test/anchoring.test.js`（唯一性/稳定性/复用）、\n`test/replace-undo.test.js`（读→改→撤字节还原、BOM/CRLF、错误码）。\n\n---\n\n## Repo layout · 仓库结构\n\n```\nindex.js             # main plugin (takeover) main 入口（接管）\ncordis.patch.yml     # the bundle layer applied by dsh plugin 插件配置层\nsrc/engine.js        # pure, dependency-free engine 核心引擎（无依赖）\nsrc/plugin.js        # host-core plugin (./core export) 核心工具插件\nsrc/takeover.js      # pi-aligned takeover plugin 接管插件\ntest/                # node:test suite 测试套件\ndocs/adr/            # architecture decision records 架构决策记录\n```\n\n## References · 参考\n\n- [CONTEXT.md](CONTEXT.md) — glossary 术语表\n- [docs/adr/0001-workspace-store.md](docs/adr/0001-workspace-store.md) — why the store lives in the project\n  workspace 为何存储放在项目工作区\n- [DSH bundle/publish guide](https://deepseek-harness.github.io/deepseek-harness/develop/basic/publish) —\n  the official packaging convention this repo follows 本项目遵循的官方打包规范\n- Upstream 上游：[`pi-hashline-edit-pro`](https://pi.dev/packages/pi-hashline-edit-pro) (MIT), original\n  [`pi-hashline-edit`](https://github.com/yugimob/pi-hashline-edit) by RimuruW\n\n---\n\n## License · 许可\n\n[MIT](LICENSE)\n","readmeFilename":"README.md","_rev":"1-ada2b92995d1507908a04cfb1f6badda"}