# dsh-workspace-hygiene [English](README.md) | 中文 `dsh-workspace-hygiene` 是一个面向 DeepSeek Harness 的插件,用来处理长程 Agent 任务中不断增长的中间产物:日志、代码以及各类文件等。 我在使用各种Agent执行任务时发现一个问题,就是在执行长程任务时,Agent会在工作区输出大量的中间结果文件,这些文件对大模型上下文和磁盘空间都是一种负担,且会导致工作空间内容杂乱。文件只存在于磁盘上时,本身虽然一般不会直接消耗 token,但真正的问题是,当 Agent 反复 glob、grep、列目录、读取文件、重新理解自己之前留下的中间结果时,这些冗余文件会造成:**搜索空间膨胀 → 更多工具调用 → 更多无关内容进入上下文 → reasoning noise 增加 → token cost/latency 上升,推理性能下降。** **如何让长程 Agent 自动管理工作区中不断增长的中间产物,使工作区在整个任务生命周期内保持高信息密度、低冗余、高易读性?** 这是一个值得研究的问题。 DeepSeek Harness 自己其实已经强调了 workspace-context budget 等机制,但当前 filesystem/workspace 子系统主要解决文件访问、workspace identity、读写安全等问题,而不是回答:**哪些文件还值得存在?现存文件应该如何命名?现存文件应该组织为怎样的目录结构?** `dsh-workspace-hygiene`是我对上述三个问题的一个初步回答。具体而言,`dsh-workspace-hygiene`的解决思路,是把工作区看作一个会随着任务推进不断变化的有序信息空间,而不是一个只负责存放文件的目录。插件关注的不是简单地删除旧文件,而是持续回答三个问题:这个文件现在还有没有价值?如果有,它应该放在哪里、叫什么名字?如果暂时没有明确答案,应该如何保留并等待进一步判断? 首先,插件会对工作区中的文件进行价值判断。它会区分任务中的核心资料、最终交付物、可复用的中间结果、仅用于调试或过程记录的临时文件,以及已经没有价值的冗余产物。这个判断既考虑文件本身的特征,也考虑它在当前任务中的位置、作用和生命周期,并向用户说明作出判断的理由。这样,Agent不再只是机械地发现“看起来像临时文件”的内容,而是能够形成一份关于文件价值的、可被人理解和修正的判断结果。 其次,插件将“判断价值”和“执行动作”分开。对于有价值的文件,建议保留,并给出该文件的命名和所在目录建议;对于仍可能有参考意义的中间结果,建议保留,并给出该文件的命名和所在目录建议;对于明显没有继续价值的文件,建议删除;对于证据不足的文件,则暂时不给出建议操作,交给用户复核。用户可以接受、修改或否决这些建议。这样既能让 Agent主动参与工作区管理,也不会让一次错误判断直接造成不可逆的损失。 接着,插件会帮助工作区形成稳定、清晰、易读的组织方式。不同生命周期阶段的文件应该进入不同的目录,最终成果、中间材料、待复核内容和待删除内容应当能够被快速区分。文件名也不应只是随机生成或保留原始临时名称,而应该包含能够帮助人和 Agent 理解其来源、用途等信息。目录结构和命名规则一旦稳定下来,工作区就不再是一堆彼此孤立的杂乱文件,而会变成一种可以快速浏览、搜索和理解的知识结构。 最后,这种整理应该贯穿整个任务生命周期,而不是在任务结束后才进行一次性清理。随着 Agent 不断产生新文件,工作区需要持续进行价值评估、整理和更新:有价值的内容逐渐沉淀为清晰的成果,中间过程被集中管理,确认无用的内容被删除,暂时无法判断的内容则被保留下来等待复核。这样可以让工作区始终保持较高的信息密度,减少 Agent 在后续搜索和理解时面对的无关内容。 因此,`dsh-workspace-hygiene`的目标并不仅仅是替用户做一个简单的“自动清理器”,而是建立一种面向长程 Agent 的工作区治理方式:让文件的价值、位置、名称都变得清晰易读,**在减少磁盘空间占用的同时,让人能够理解 Agent 做过什么,也让 Agent 能够更高效地理解自己和其他 Agent 留下的工作成果。** ## 工作区标签页 `dsh-workspace-hygiene`会在 `dsh web` 的 **“轨迹”后增加“工作区”标签页**。页面采用左右双栏:左侧展示目录树、文件分类与用途简述、100 分制整洁度评分和整理模式,右侧固定显示独立整理 Agent 会话。进入该页面时隐藏主 Agent 的底部输入框,切回“对话”标签后恢复。 长程 Agent 任务会留下日志、失败补丁、临时导出和重复的中间结果。文件留在磁盘上本身通常不消耗上下文,但反复检索、读取和判断这些文件,会增加工具调用与推理噪声。本插件将文件生命周期显式呈现,并把日常维护从主 Agent 的对话中独立出来。 - 展开当前会话工作区的目录与文件,包括隐藏文件、源码目录和依赖目录。目录按需读取,大目录分页加载;符号链接显示为链接,不跟随到目标目录。 - 文件和目录显示**受保护 / 有价值 / 中间产物 / 可清理 / 待确认**分类和用途简述;点击后查看路径保护、分类来源、评估依据、建议路径和大小。默认结合主 Agent 任务上下文和目录元数据进行模型推断;未完成的部分显示规则分类。 - 查看整洁度、候选文件数、最近评估时间、维护进程 PID,以及整理、验证和恢复状态。 - 切换“手动整理”或“自动整理”。模式按工作区保存,重启后保留。 - 在右侧固定会话中查看刷新、扫描、上下文分类、方案生成、整理、校验、复核和回滚过程。周期监控没有检测到变化时不会反复刷消息;大工作区评估期间仍显示实时批次进度。 - 在同一个右侧面板中与独立整理 Agent 讨论文件用途和保护要求。它拥有独立历史,不出现在其它 Agent 可读取的普通会话列表中。 - 整理方案以内嵌会话卡列出每个文件的操作。用户可以先发送补充要求并重新生成方案,再从右侧选择“暂不整理”或“确认并开始整理”。 浏览器只传会话 ID,宿主从活跃会话解析工作区路径,并使用 DSH 原生 Connection RPC 及其信任检查。客户端不能任意指定磁盘根目录;配置 `workspaceRoot` 后还会固定插件可操作的工作区。历史会话需要先打开或恢复。 以下为隔离测试工作区中的真实 DSH Web 截图: ![带右侧整理 Agent 的工作区标签页](assets/dsh-workspace-tab.jpg) ![右侧会话中等待确认的整理方案](assets/dsh-workspace-confirmation.jpg) ## 手动整理与自动整理 **默认为手动模式。** 独立维护进程监听文件变化并定期评估,不移动源文件、不向主 Agent 注入监控消息,也不占用它的空闲维护阶段。只有点击“整理工作区”、查看方案并点击“确认并开始整理”后才执行。 **自动模式负责评估和询问,仍需逐次确认。** 每轮主 Agent 会话结束后重新评估;完整扫描的整洁度低于阈值(默认 80 分),且存在候选文件时,在右侧整理会话中发送建议。用户可以生成并查看具体方案,或选择“暂不整理”。已经拒绝且候选文件未变化的建议不会反复出现。切换自动模式本身不会立即整理。 两种模式使用同一条执行流程: ```mermaid flowchart LR A[独立进程监控] --> B[目录与评分] B --> C[手动点击或回合结束后的建议] C --> D[右侧会话中的方案卡与用户确认] D --> E[占用空闲工作区] E --> F[基线测试与引用检查] F --> G[可恢复整理] G --> H[完整性与项目校验] H --> I[独立 DSH Agent 审核] I --> J[主 Agent 再次核查] H -->|失败| K[回滚] I -->|不通过| K J -->|不通过,回合结束后| K ``` 只有用户确认后的整理阶段,才通过 `runMaintenance` 短暂占用当前 DSH 宿主中共享该工作区的所有活跃 Agent 的空闲阶段。新输入会排队等待,忙碌中的工作区拒绝整理;取消操作会在事务记录稳定后尝试回滚。该协调范围不包括其他编辑器或其他 DSH 宿主进程。 ## 独立 Agent 进程与两次核查 每个被观察的工作区拥有一个独立 Node 子进程(`src/worker.js`)。`.dsh-hygiene/agent/context.json` 仅保存公开的模式、整理方案与审核结果,私有聊天历史另行加密保存。 每次扫描只读获取同一规范化工作区路径下、当前 DSH 宿主已加载会话的可见消息,优先当前主 Agent;不导入隐藏推理、其它工作区会话或插件的整理回执。默认总上限 40,000 字符,每个会话最多最近 80 条消息、20,000 字符,每条最多 4,000 字符。UI 显示来源数量、进度与截断状态;不会声称读取了所有历史会话。 文件元数据或任务上下文变化后,独立进程通过宿主的 `llm` 服务调用当前会话配置的模型,按批评估文件和目录用途。请求使用自己的上下文、不携带主会话 ID、不写入主会话事件,也不能调用工具。无变化的扫描复用结果;点击“刷新”可重试评估。**上下文分类会消耗模型 token 和服务额度**,大工作区需要多个批次。没有任务上下文时使用规则;模型失败或目录范围不完整时阻止整理。自动模式等待分类完成后再决定是否询问。 模型只能进一步保留候选文件,不能绕过源码、路径、引用和事务保护,不能把非候选文件提升为可整理文件。基于上下文判断为有价值、受保护或不确定的候选文件保持原位,即使启用了物理重命名。执行前会再次比较上下文与私有会话版本;变化后旧方案失效。 ### 整理会话与单向隔离 打开“工作区”,使用页面右侧固定的整理会话。设置至少 12 个字符的密码后,即可向独立整理 Agent 发送整理建议和需求。刷新与整理过程按时间顺序显示在同一信息流中,完整方案也会在这里以内嵌卡片等待确认。聊天只讨论整理问题,不能直接执行文件操作。保护要求参与后续评估;已有私有会话必须解锁后才能生成/执行整理方案,避免忽略其中的保留要求。 会话默认保存在工作区外的 `~/.dsh-workspace-hygiene/private/`,使用 scrypt 派生密钥与 AES-256-GCM 加密;密码不保存。会话不注册到 DSH 的普通会话/Agent 列表,不暴露为主 Agent 工具。读取、发送和锁定接口都要求解锁后获得的随机访问凭证,凭证仅保存在页面内存中。刷新页面需重新解锁;“锁定会话”或进程退出会清除内存密钥并使访问凭证失效。密码丢失后无法恢复加密历史。 以下为确定性测试模型驱动的真实 DSH Web 整理会话: ![右侧面板中的独立整理会话](assets/dsh-workspace-chat.jpg) 数据流是“其它会话 → 整理 Agent”。公开的用途说明只根据主任务上下文生成,不把私有聊天交给这个生成步骤;私有保护要求通过独立模型判断,只允许输出已知路径的保留集合。目录分类、保护结论和整理结果属于公开信息,聊天原文不会进入普通会话、公开快照或整理报告。模型服务会收到相应分析/聊天请求,因此仍适用所配置服务商的数据处理规则。 这里实现的是**会话接口与加密存储层的隔离**。拥有同一系统账户任意 Shell、进程调试或可信宿主插件权限的 Agent,仍可能接触进程内存;插件无法提供操作系统级的绝对隔离。要求这一强边界时,应将整理进程放到不同账户或容器,并限制其它 Agent 的权限。 用户确认、事务执行且项目校验通过后,维护进程会启动**另一个 `dsh --profile headless` 进程和独立会话**进行证据审核。它使用 headless profile 的模型与凭据;上下文仅包含变更清单、引用与完整性检查、项目校验结果及有限的历史维护摘要,不复制主会话。该审核 Agent 隐藏全部继承工具,并由执行层限制为只能调用 `hygiene_verdict`,不能修改工作区或运行命令。审核不可用、执行失败或不批准时,回滚本次整理。 然后宿主把整理结果作为一次后续请求交给主 Agent。主 Agent 再检查文件路径、引用和项目行为,并调用 `workspace_hygiene_review` 提交结论与具体校验证据。只有被指派的主 Agent 能确认该次运行。**发出请求不代表复核通过**:在明确回执前,UI 一直显示“等待主 Agent 复核”。主 Agent 不通过时,在该轮结束、工作区空闲后回滚;用户也可从结果面板主动回滚。 ## 避免改名或移动导致错误 现有的限时计划、哈希绑定、路径保护、文件数/字节预算、隔离区与恢复日志继续作为执行边界。Web 工作流不会永久删除文件。源码、Git 已跟踪文件、凭据和受保护路径继续受到策略保护。 生成方案前,以及用户确认后,会检查项目文本中是否引用了候选路径或文件名。被引用的文件保留在原处,并在方案中列明原因。检查偏保守,文档里的引用也可能使文件被保留;动态拼接的引用或工作区外的消费者无法据此证明不存在。 整理前后都会运行项目校验。默认使用项目声明的 `npm test`;其他项目可配置 `verificationCommands`。基线测试失败则保持文件原位;整理后测试失败、无关文件发生变化或独立审核不通过则恢复事务。恢复遇到后来修改的文件时不会强制覆盖,UI 会保留“需要恢复”状态及冲突信息。 证据检查默认最多 10,000 个文件,引用检查的**文本**总量最多 128 MiB,分别由 `maxVerificationFiles`、`maxReferenceBytes` 配置。所有文件均流式计算哈希;PPTX、视频等二进制文件不占用文本预算,不再因为工作区总量超过 128 MiB 就拒绝生成方案。版本控制、依赖目录和插件自身状态/元数据目录排除。文本或文件数量超限仍拒绝整理。没有项目测试命令时只做静态校验,并明确显示 `static-only`。两轮审核与测试提供其覆盖范围内的证据,不能保证任意项目绝对没有 bug。 如果旧版点击整理按钮显示 `invalid_union` / `error.details`,这是失败响应缺少 DSH 协议要求的 `details` 对象,掩盖了真正的错误。0.3.0 补齐该字段,并修复上述大文件预算问题;其它失败会显示实际原因。 配置 `valuePolicy.organization.moveFiles: true` 后,还可对符合策略的 retain/review 产物应用建议命名或目录。源码和被引用文件仍保留原位;插件不会进行任意语言的自动重构。元数据目录的建议路径不会被当作源文件的物理目标。 ## 整洁度评分 设 `N` 为本次评估中排除受保护文件后的文件数: ```text 整洁度 = 四舍五入(100 − 70 × 可清理数/N − 20 × 中间产物数/N − 10 × 待确认数/N) ``` 分数限制在 0–100;计分集合为空时为 100。面板公开分类数量、扣分项与排除范围。它衡量产物生命周期整洁程度,不衡量代码质量。受保护目录、依赖和忽略目录仍可浏览,但不参与评分。扫描超限时标注暂估,不能自动提出整理或生成可执行方案。 独立审核的证据上限为 20,000 字符;超限则拒绝审核并回滚,不会静默截断证据。 ## 安装与升级 需要 Node `^22.19.0 || >=24`,以及提供 `conversation.view`、`connection.rpc` 和 `Agent.runMaintenance` 的 DSH Web profile。Web 集成已针对本机 DSH `0.1.1-rc.2` 验证,并核对当前上游扩展接口。预览版接口仍会变化,实验复现时应固定版本。 ```sh dsh plugin --profile web add github:taoshi1999/dsh-workspace-hygiene#main dsh web ``` 本地开发可先安装依赖,再从检出目录安装: ```sh npm ci dsh plugin --profile web add . ``` 升级后**重启 DSH Web 并刷新浏览器**。包中声明 `dsh.client`,并导出 `./client` 和 `./package.json`,由原生客户端模块加载器注册标签,不需要修改 DSH 核心或注入页面 DOM。 ```sh dsh plugin --profile web remove dsh-workspace-hygiene ``` ## 配置示例 在 profile 的 `cordis.patch.yml` 中按 ID 覆盖已有插件行: ```yaml - id: workspace-hygiene name: dsh-workspace-hygiene config: mode: manual # manual 或 automatic cleanlinessThreshold: 80 monitorIntervalMs: 30000 debounceMs: 1500 contextAware: true contextMaxChars: 40000 contextBatchSize: 60 contextModelTimeoutMs: 120000 # 可选:必须在工作区之外,不能经过符号链接 # privateStorageRoot: C:/private/hygiene-conversations maxVerificationFiles: 10000 maxReferenceBytes: 134217728 managedRoots: [tmp, scratch, outputs] minAgeHours: 24 maxScanFiles: 5000 maxArchiveFiles: 20 maxArchiveBytes: 104857600 stateDir: .dsh-hygiene verificationCommands: - command: npm args: [test] verificationTimeoutMs: 120000 reviewerTimeoutMs: 180000 # 可选:已安装 dsh/lib/bin.js 的绝对路径 # reviewerCli: C:/path/node_modules/@deepseek-ai/dsh/lib/bin.js valuePolicy: discardPatterns: ['tmp/**', 'scratch/**'] retainPatterns: ['outputs/release/**'] organization: moveFiles: false ``` 校验命令属于部署配置,以参数数组执行,不使用 shell;UI 不能传入任意命令。Windows 下的 `npm` 通过 Node 加载 npm CLI,命令超时会终止 Windows 子进程树。`autoScan: false` 关闭定期监控,UI 刷新仍可显式扫描,自动模式仍评估已结束回合。`enabled: false` 关闭宿主集成。用户从 UI 保存过模式后,该工作区的已保存值优先。 旧的 `autoArchive`、`autonomousMode`、`notifyAgent`、`autoScanEveryTurns` 不再授权 Web 无人确认执行或日常主 Agent 通知。需要每轮评估时请迁移到 `mode: automatic`。六个旧 scan/plan/apply/restore/status/explain 工具适配器仍可由库调用者显式使用,但本 bundle 不再把它们注册到主 Agent;仅注册整理结果回执工具 `workspace_hygiene_review`。 更多配置见 [profile 示例](examples/cordis.patch.example.yml)和[价值策略示例](examples/workspace-hygiene.config.json)。`.hygieneignore` 继续控制整理评估范围,目录浏览仍可显示这些路径。 `contextAware: false` 关闭模型分类,改用规则,私有聊天仍可使用,但聊天要求不再参与分类。上下文分类元数据遍历包含受保护源码目录,跳过依赖、版本控制和插件存储目录,受 `maxScanFiles` 限制;它不读取每个文件的完整内容。聊天请求只附带有限文件清单,较大的历史与目录范围会截断。保留要求对模型判断的影响属于推断,关键文件仍应配置明确的 `retainPatterns`。 ## CLI 与元数据目录 保留独立 CLI,供用户显式执行已有扫描、计划和恢复流程: ```sh node bin/dsh-workspace-hygiene.mjs scan ./project node bin/dsh-workspace-hygiene.mjs plan ./project node bin/dsh-workspace-hygiene.mjs --help ``` CLI apply/restore 和底层库保留原有确认与策略契约,不经过 Web 的协调器或双 Agent 核查流程。需要完整新流程时使用“工作区”标签页。 `workspace-artifacts/` 仍是供事务/CLI 使用的可选元数据目录,保存源路径、用途、价值评估和处理决定,不复制源文件。实时 UI 读取文件系统元数据与独立扫描结果;日常监控不需要反复重写 catalog 或把它塞进主 Agent 上下文。 ## 工作区生命周期示例 以下已有静态示意图用于说明文件生命周期,并非新版实时标签页截图。 ![未管理的工作区](assets/workspace-before.png) ![反复检索带来的噪声](assets/workspace-search-noise.png) ![文件价值评估](assets/workspace-value-review.png) ![整理后的工作区](assets/workspace-after.png) ## 开发与验证 ```sh npm ci npm run check npm run pack-check node scripts/dev-web.mjs ``` `dev-web.mjs` 使用临时 home、profile 和示例工作区启动真实 DSH Web,不修改正常使用的 profile,也不复制凭据。需要已安装 DSH CLI,可用 `HYGIENE_DSH_CLI` 指定路径;Ctrl+C 停止。 加上 `--fixture-model` 可加载确定性测试模型,离线验证上下文分类与私有聊天 UI;这是界面/协议验证,不代表真实模型的分类质量。 测试覆盖独立 PID、上下文范围与缓存、密码加密、越权拒绝、锁定与重启、私有信息不进入公开快照、上下文变化使方案失效、大二进制文件校验、手动/自动确认、引用保护、回滚及主 Agent 回执。Windows 目录重解析点使用无需提权的 junction 验证;无法创建文件符号链接时,相应测试明确跳过。 研究动机和实验方向见[研究议程](docs/research-agenda.zh.md)及[社区研究](docs/community-research.zh.md)。 MIT License。