DSH HUB
HomePlugin StorePlugin PacksCommunityRankingsResourcesPublish Guide
Plugin source
Back to catalog

puppetcat-fire /

puppetcat-fire/dsh-needs-archive

Verified

Verbatim project-user requirement archive for DeepSeek Harness (DSH): stores the user's own words in .needs/ and recalls them by topic.

★ 0 Stars0 Forks0 IssuesN/A Community rating0 Confirmed installs
View on GitHub
READMESource: main@b525b2b3

用户原话档案(needs-archive)

把项目用户自己在对话里提交的原话按主题存进项目内的 .needs/ 目录,开发中途需要核对「当初到底怎么说的」时,按主题或关键词取回原文。

  • 插件名:needs-archive
  • 包名:@local/needs-archive,版本 0.1.0
  • 类型:Host-only Cordis bundle(没有前端面板),一个 profile 一份
  • 目标环境:DeepSeek Harness 0.2.2-rc.1
  • 数据位置:项目根目录下的 .needs/(不是用户目录、不是全局存储)

它做什么

DSH 把用户提交的消息以 user/message 事件写入会话。本插件订阅 session/event,只挑出其中作者本人写的文本:

  • event.type === 'user/message',且 data.role === 'user'
  • data.source.kind === 'user':goal 轮次、compaction 摘要、agent-instructions、working-directory 等插件注入的消息同样以 user/message 出现,但它们的 source.kind 不是 'user',一律不碰
  • 作者会话判定:子代理的初始任务 prompt 也是 user/message 且 source.kind === 'user'(写它的是委派它的 agent),所以还要看会话 header——origin: 'subagent'、存在 parentSession 或 delegationDepth > 0 时整会话排除(lib/session-scope.js)
  • 只取 content 里 type: 'text' 的块;单块原样使用,多块之间用一个换行符连接,没有文本块则跳过

命中的消息交给启发式分类器判断「记不记、记成哪种、归到哪个主题」,然后以逐字节原文写入:

<project>/.needs/<domain>/<topic>/<YYYY-MM-DD>-<短标题>-<hash8>.md

同时注册两个工具:

  • needs_query:按主题/关键词回查原话,返回项目相对路径 + 原文 + 元数据
  • needs_archive:补录自动捕获没归档的、插件加载后已观察到的消息(例如被启发式跳过),可手动指定域/主题/标题/kind(只影响元数据,原文不变)

可选地,当项目已有档案时,插件会向模型上下文注入一小段提示:需要精确原话时可以回查档案。这只是提示,不是工作流步骤。

边界(它不做什么)

  • 不是工作流引擎,不强制 agent 先查档案,也不改变任何任务的执行顺序。
  • 档案是历史引用:后一条记录是更新的说法,但档案里的文字不覆盖当前指令,也不构成任何授权。
  • 不总结、不改写、不翻译、不脱敏后保存。命中的密钥与明显个人信息会被直接跳过(不存),而不是存一份打码版。
  • 不修改、不删除旧记录。更正和撤回都是新增一条记录,原文件保留。
  • 不跨项目共享。.needs/ 属于它所在的项目;两个项目各存各的。
  • 不归档子代理会话。委派的子代理初始任务是 user/message 且 source.kind 也是 user,但那是委派它的 agent 写的;会话 header 带子代理标记(origin: 'subagent'、parentSession 或 delegationDepth > 0)时,整会话不喂档案,needs_archive 也会直接报错。
  • 不做模型分类。分类是关键词与句式启发式,会分错;可用 needs_archive 的 domain / topic 覆盖元数据,或直接手工整理目录。

工作流程

用户提交消息
  └─ DSH 提交 user/message 事件
       └─ 插件:作者会话判定(子代理/子会话整体不归档)
            └─ 来源过滤(source.kind === 'user',仅文本块)
                 └─ 只读检查(read-only 会话跳过)
                      └─ 项目根解析(显式 projectRoot → 最近 .git → 最近 .needs → 当前 .dsh)
                           └─ 分类器:跳过(寒暄/确认/过短/一次性操作/密钥/个人信息/明确不记)
                                或归档(statement / supplement / correction / retraction)
                                └─ 正文 sha256 查重(同一项目只存一份)
                                     └─ 经 ctx.fs + 会话 sandbox 策略写入 .needs/

写入遇到只读会话直接跳过;项目根无法确定时本轮暂缓(deferred),不落盘。

快速开始

前置条件:DSH 0.2.2-rc.1 正在运行,插件目录已在工作区(<workspace>\needs-archive)。插件不依赖 npm 包、没有构建步骤。

安装(任选一种,不要手改 profile 的 package.json 或组合包列表):

  • GUI:侧栏「插件」→「添加插件」→ 输入插件目录的绝对路径(例如 C:\Users\<you>\Documents\deepseek-harness\default-workspace\needs-archive)→ 安装。安装成功后该包出现在「已安装插件」里。
  • 让会话里的 agent 调 plugin_manager:action: install_bundle,target 传同一个绝对目录。返回 application: applied 表示已生效;安装需要批准时按提示确认。

安装后,在任意一个含 .git(或已有 .needs/,或配置了 projectRoot)的项目里新建会话,发一条真正的需求,例如:

侧边栏宽度固定在 240px,不要自适应;窄屏下保持 240px 并出现横向滚动。

提交后,项目里应出现类似文件:

<project>/.needs/inbox/unclassified/2026-11-11-侧边栏宽度固定在-240px-不要自适应-窄屏下-d8e76885.md

没配 domains 时域是 inbox、主题是 unclassified;文件名里的短标题来自正文标题(保留汉字,最多 24 个码点,标点与空格转成 -),标题全文保留在 frontmatter 里。

之后问一句「我当初侧边栏是怎么说的?」,agent 会调用 needs_query,返回那条原文与路径。

安装

前置检查

项目 要求
DSH 版本 0.2.2-rc.1(插件只使用 Host 服务 tools / fs / systemPrompt / workingDirectory,sandboxPolicy 可选)
Node 随 DSH 内置的运行时即可;本地跑测试需要 Node 24 及以上
目录 插件目录必须包含 package.json、cordis.patch.yml、index.js
权限 安装会写入当前 profile,需允许该操作

安装步骤

  1. 确认插件目录的绝对路径。
  2. 用上面「快速开始」里的 GUI 或 plugin_manager 方式安装。本地目录安装会以 link: 方式登记到 profile 的 package.json(由插件管理器写入,不要自己改),并默认启用。
  3. 判读结果:install_bundle 返回里 application 为 applied、warnings 为空或与你无关;插件页的「已安装插件」出现 @local/needs-archive,其组合包详情里有一行 id 为 needs-archive 且在启用状态。安装接口的返回与插件页状态才是判据,不要用进程列表或页面是否刷新来判断。
  4. 在新会话里确认工具存在(needs_query / needs_archive),并确认插件启动日志(插件用 Host logger,前缀 needs-archive:;当前日志级别下可能看不到 ready 行)。

插件代码更新之后

本地目录是链接安装,profile 里指向的就是工作区这份代码。实测(2026-11-11):改完 index.js / lib/** 后必须重启 DSH 才能载入新的模块代际;plugin_manager 禁用/启用插件行只会重挂入口,不会刷新已加载的 ESM 模块缓存(旧模块会继续跑)。headless 每次都是新进程,不受此影响。

配置改动:桌面 profile 启用了 HMR,改 profile patch 后可能热重载;这一点没有单独实测,改完建议重启确认。

配置速查

所有字段都可省略,省略即用默认值。完整字段说明、边界与示例见 docs/configuration.md。

字段 类型 默认值 一句话作用
enabled boolean true 总开关;false 时插件不监听、不注册工具
minLength integer 2 自动归档的最短字符数(按 Unicode 码点;0–1000)
domains array [] 关键词 → 域目录映射,每项 { name, keywords, defaultTopic? }
defaultDomain string inbox 没有命中任何域关键词时使用的域目录
secretPatterns array [] 额外的密钥匹配模式,命中即跳过
skipPatterns array [] 额外的「永不归档」匹配模式,命中即跳过
promptMode string auto 上下文提示策略:auto / always / never
maxQueryResults integer 20 needs_query 不传 limit 时的默认返回上限(1–500)
projectRoot string | null null 显式项目根,给非 Git 项目或无 .git 的目录用

配置写在你自己的 profile patch 层($env:DSH_HOME\profiles\<profile>\cordis.patch.yml)里,对 needs-archive 行做 override。注意:按 id 定位的 override 会把该行的整个 config 替换掉,不会与之前的值深度合并,因此这一行里要写全你想保留的字段。

- id: needs-archive
  name: "@local/needs-archive"
  config:
    enabled: true
    domains:
      - name: ui
        keywords: [侧边栏, sidebar, 按钮, 布局]
        defaultTopic: sidebar
      - name: api
        keywords: [接口, api, 端点]
        defaultTopic: api-design
    promptMode: auto

插件没有声明配置 schema,也没有前端配置页,所以当前版本不会在插件页出现配置表单;改配置就是改上面这段 patch。不合法的字段会在启动时回落到默认值,并在日志里以 needs-archive: config: … 给出告警。

使用

三类操作,详见 docs/usage.md:

  • 自动归档:插件加载后,每条提交的人写消息都会被评估,不需要调用工具。
  • 回查:让 agent 调 needs_query,或直接打开 .needs/ 下的 Markdown 文件。
  • 手动补录:对插件加载后、被自动分类跳过的已观察消息,或想显式指定主题/kind 的记录,调 needs_archive。

回查样例:

needs_query(query: "侧边栏")
needs_query(domain: "ui", topic: "sidebar")
needs_query(query: "240px", kind: "correction")

文件格式

每条记录是一个 Markdown 文件:YAML frontmatter(下文 --- 开闭)+ 一份逐字节原文。

---
format: 1
id: "0f1e2d3c-4b5a-6978-8796-a5b4c3d2e1f0"
sha256: "…64 位小写十六进制…"
created: "2026-11-11T02:00:01.000Z"
domain: "ui"
topic: "sidebar"
subtopic: null
title: "侧边栏交互"
kind: "statement"
related: []
session: "session-a"
message: "msg-1"
source: "user"
pluginVersion: "0.1.0"
---
## 侧边栏交互

希望侧边栏默认是**收起**的,鼠标悬停时才展开;移动端不要跟随页面滚动。

- 展开时保留上次选中的 tab
- 收起动画 120ms,别用弹跳  
- 键盘聚焦时展开

(正文对应 scripts/verify.mjs 场景 1 实际写入的内容,逐字节一致;id / sha256 / session 等为示例值。注意示例里「收起动画」那一行末尾保留了原文的两个空格。)

frontmatter 字段 含义
format 记录格式版本,当前为 1;没有 frontmatter 的手写文件按 0 处理
id 记录 UUID
sha256 正文的 sha256,用于跨文件查重
created 归档时间,ISO 8601(UTC)
domain / topic / subtopic 目录归属;subtopic 目前恒为 null(保留字段)
title 从正文首个一、二级标题或首行提取的标题,最多 40 个码点
kind statement / supplement / correction / retraction
related 关联记录,目前恒为 [](保留字段)
session / message 来源会话 id 与消息 id,可为空
source 固定 user
pluginVersion 写入该记录的插件版本

正文规则:renderRecord 只做 frontmatter + "---\n" + body,不追加结尾换行、不 trim、不转换 CRLF/LF;解析时以 frontmatter 之后第一个独立 --- 行作为分隔,因此正文本身以 --- 开头也能原样还原。

目录示例(配置了 ui 域与 sidebar 主题;文件名为同一规则的实际产出):

<project>/.needs/
├── ui/
│   └── sidebar/
│       ├── 2026-11-11-侧边栏交互-7df0b132.md                     # statement:原始需求
│       ├── 2026-11-11-另外侧边栏还要支持折叠-d1736793.md         # supplement:补充
│       └── 2026-11-11-侧边栏改成-280px-240-太窄了-2cd32ae6.md    # correction:更正
└── inbox/
    └── unclassified/
        └── 2026-11-11-上面那条不算-撤回-82913bbe.md             # 没命中关键词的撤回

文件名规则:<YYYY-MM-DD>-<短标题>-<hash8>.md。

  • YYYY-MM-DD 是本机本地日历日期(frontmatter 里的 created 才是 UTC 时间戳);
  • 短标题来自标题,保留英文字母、数字、汉字(U+4E00–U+9FFF)与 -;标点、空格、emoji 等转成 -,折叠重复分隔符,最长 24 个码点,空则用 record;
  • hash8 是正文 sha256 的前 8 位,更换日期不会改变它;
  • 目录段(domain / topic / subtopic)仍限定小写 ASCII,中文不会出现在目录名里。

.needs/.needs.lock 是写入时的临时排他锁,正常结束即删除;异常残留超过 30 秒会被回收,不要手工编辑它。

已知限制(0.2.2-rc.1 / 插件 0.1.0)

以下是按源码能确认、且在当前版本上成立的行为,不是待办清单:

  1. 只捕获插件加载之后提交的消息。 插件不会回放历史会话,也不会重新触发 session/event。插件加载前的消息无法补录(没有被观察,事件也不会重放);needs_archive 只能补本会话插件加载后观察到的最近 8 条人写消息。
  2. 没有 GUI 面板。 只有工具与 .needs/ 文件;没有列表页、搜索页、编辑页。
  3. 依赖 session/event 的 live append。 会话恢复、导出导入、重放等路径不会重新触发归档。好在同一正文重复落盘会被去重,因此不会产生重复文件。
  4. 只读会话跳过。 会话的 sandbox 策略为 read-only 时自动归档直接跳过;即使写入请求到达文件系统,也会被沙箱拒绝。没有 sandbox 后端的环境(策略解析为 undefined)按普通写入处理。
  5. 分类是启发式的,不调模型。 域与主题来自 domains 关键词匹配,kind 来自句式(另外/补充 → supplement,改成/不是…而是 → correction,撤回/上面那条不算 → retraction)。关键词没命中就落到 inbox/unclassified;中文标题且没配 defaultTopic 时主题同样是 unclassified,只保留文件名里的中文标题。
  6. 项目根必须有明确归属。 判定顺序:显式 projectRoot → 最近的含 .git 祖先(文件或目录都算)→ 最近的已存在 .needs/ 祖先 → 当前目录含 .dsh/。都不满足时本轮 deferred,什么都不写。非 Git 项目要么配 projectRoot,要么先在项目里建 .needs/。
  7. 主题沿用只在进程内有效。 更正/补充会沿用本会话「上一条已归档记录」的 domain/topic,这份记忆只存在内存里;插件重载或 DSH 重启后丢失,之后按关键词重新分类,可能落进 inbox/unclassified。跨会话的更正不保证落在同一主题。
  8. 同一正文在一个项目里只存一份。 之后再说一遍完全相同的话不会产生第二条记录(duplicate),也就没有新的时间戳。要保留新的说法,正文必须不同。
  9. 撤回不删除原件。 撤回只新增一条 retraction 记录;原记录仍在,回查时按时间顺序同时看到。归档文件的删除只能手工做。
  10. 没有配置表单。 插件未声明 Config schema、没有前端,配置只能写在 profile patch 的 override 行;非法值回落到默认并告警。
  11. 子代理/子会话不归档。 判定依据是会话 header:origin === 'subagent'、存在 parentSession,或 delegationDepth > 0 时,该会话的自动归档静默跳过、上下文提示不注入、needs_archive 直接报错;needs_query 仍可在子代理里查询。用户自己 fork 的会话没有这些标记,照常归档。该守卫是源码行为;已安装但仍在运行的 desktop 进程要重启 DSH 后才载入(见「插件代码更新之后」)。

验证

本地离线验证与真实 DSH 加载步骤都在 docs/verification.md。两个命令(cwd 位于 needs-archive):

node --test
node scripts/verify.mjs

node --test 当前工作树通过(94 个用例,0 失败,Node v24.13.0,2026-11-11);node scripts/verify.mjs 5/5 通过;真实 DSH 已分项验证:desktop profile 验证了安装、工具注册、真实 needs_query 与条件提示注入;headless 新进程验证了提交 → 落盘、同 session 更正 → 第二份记录、只读会话不落盘。受限之处(headless 无模型凭据;desktop 运行中进程为安装时模块代际,需重启才载入最新源码)写在 docs/verification.md。

卸载

用插件管理器卸载,不要手改 profile:

  • GUI:「插件」→「已安装插件」→ 该组合包 → 移除。
  • 或让 agent 调 plugin_manager:action: remove_bundle,target: '@local/needs-archive'。

卸载后两个工具消失,插件不再监听消息;已经写入的 .needs/ 不会被删除,它们仍是普通 Markdown 文件,可以直接阅读或备份。需要清理由你自行删除项目里的 .needs/(如果项目已把档案纳入 Git,还要一并处理版本库)。

目录与文件

needs-archive/
├── index.js                 # Host 入口:事件监听、上下文提示、两个工具
├── cordis.patch.yml         # 组合包 patch(插入一行 needs-archive)
├── package.json             # @local/needs-archive,声明 dsh.bundle.patch
├── locale/{en,zh}.json      # 插件管理器里的标题/描述
├── icon.svg                 # 插件图标
├── lib/
│   ├── dsh-io.js            # ctx.fs 实现存储 I/O 端口 + 按会话策略执行
│   ├── guidance.js          # 上下文提示与工具描述文案
│   ├── session-scope.js     # 作者会话判定(子代理/子会话不喂档案)
│   └── core/                # 纯 Node 核心(不依赖任何 @deepseek-ai/* 包)
│       ├── config.js        # 配置默认值与容错归一化
│       ├── classify.js      # 跳过规则、kind 判定、域/主题选择
│       ├── source.js        # 只取 source.kind === 'user' 的文本块
│       ├── project.js       # 项目根解析、文件名与路径安全
│       ├── format.js        # frontmatter 渲染/解析、sha256
│       ├── io.js            # 存储 I/O 端口契约(附带 node:fs 实现供单测)
│       ├── store.js         # 去重、锁、原子写、查询
│       └── engine.js        # 编排层(可注入依赖,单测直接用)
├── scripts/verify.mjs       # 端到端离线验证脚本
├── test/*.test.mjs          # node:test 单测
└── docs/                    # 本目录:配置、使用、验证
—/ 5

No ratings yet

Verified DSH bundle

Commit b525b2b3a214

Community comments

No comments yet. Be the first to write one.

DSH HUB

A community index for DSH plugins. Not an official GitHub or DeepSeek AI product.

CommunityResourcesAPIAbout