<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"><channel><title>My Blog</title><description>A personal blog about tech and writing.</description><link>http://localhost:4321/</link><item><title>从零学透 DeepSeek Harness：系列路线图</title><link>http://localhost:4321/posts/dsh-learning-path/</link><guid isPermaLink="true">http://localhost:4321/posts/dsh-learning-path/</guid><description>围绕 DeepSeek 开源的 Agent Harness（代号 dsh），我写了八篇源码解读和十三课配套课程。这一页是路线图——说清楚每份材料管什么、按什么顺序读。</description><pubDate>Sat, 29 Aug 2026 01:00:00 GMT</pubDate></item><item><title>第 13 课 · 工程文化与门禁：把正确变成机器可执行</title><link>http://localhost:4321/posts/dsh-tutorials/13-engineering-culture/</link><guid isPermaLink="true">http://localhost:4321/posts/dsh-tutorials/13-engineering-culture/</guid><description>前十二课讲「系统如何工作」，最后一课讲「系统如何保持正确」。dsh 跟别的项目最不一样的地方：架构规则大多不靠评审自觉，直接接进了可执行的顶层门禁。读懂这套，你才能跟别人讲清「这些设计凭什么能维持」。</description><pubDate>Fri, 28 Aug 2026 12:00:00 GMT</pubDate></item><item><title>第 12 课 · Web 客户端：Slots、模块图与三层分层</title><link>http://localhost:4321/posts/dsh-tutorials/12-web-client/</link><guid isPermaLink="true">http://localhost:4321/posts/dsh-tutorials/12-web-client/</guid><description>第 07 课结尾提到 host/client 双编译面。现在看浏览器那一面：Web UI 的每个面板、每个工具卡片，是怎么被组合出来的？为什么说在浏览器里写 UI 组件和写宿主插件是两套语法？</description><pubDate>Fri, 28 Aug 2026 11:00:00 GMT</pubDate></item><item><title>第 11 课 · 自扩展：skill 与 extensions</title><link>http://localhost:4321/posts/dsh-tutorials/11-self-extension/</link><guid isPermaLink="true">http://localhost:4321/posts/dsh-tutorials/11-self-extension/</guid><description>「一切皆插件」再往前一步：让模型在运行时自己写插件。dsh 靠两套机制做到——skill（内容注入）与 extensions（代码求值 + 插件挂载）。这一课讲清两套机制的边界，顺带精读四篇 postmortem，看这个系统怎么被现实教育。</description><pubDate>Fri, 28 Aug 2026 10:00:00 GMT</pubDate></item><item><title>第 10 课 · 毕业项目：写一个完整插件</title><link>http://localhost:4321/posts/dsh-tutorials/10-capstone-first-plugin/</link><guid isPermaLink="true">http://localhost:4321/posts/dsh-tutorials/10-capstone-first-plugin/</guid><description>从零走完一次「扩展 dsh」的完整闭环：写插件 → 装进 profile → 组合验证 → 行为验证 → 留下决策记录。这是本课程的毕业项目：前九课学没学会，做一遍就见分晓。</description><pubDate>Fri, 28 Aug 2026 09:00:00 GMT</pubDate></item><item><title>第 09 课 · 工具执行管线与安全三旋钮</title><link>http://localhost:4321/posts/dsh-tutorials/09-tool-pipeline-and-safety/</link><guid isPermaLink="true">http://localhost:4321/posts/dsh-tutorials/09-tool-pipeline-and-safety/</guid><description>第 04 课的工具调用事件流跳过了执行本身。这一课补上最敏感的一段：模型说「帮我删这个文件」，从决策到落地之间有几道闸门？谁有权拦？拦了之后怎么审计？ dsh 的答案：四道关卡 + 三个正交旋钮 + 一条铁律——fail-closed。</description><pubDate>Fri, 28 Aug 2026 08:00:00 GMT</pubDate></item><item><title>第 08 课 · 能力接缝：三角色与两种形态</title><link>http://localhost:4321/posts/dsh-tutorials/08-capability-seam/</link><guid isPermaLink="true">http://localhost:4321/posts/dsh-tutorials/08-capability-seam/</guid><description>前七课你理解了骨架、事件、主干、组合。现在看扩展模型的核心抽象：dsh 怎么让「文件系统在本地还是远程」「模型是 DeepSeek 还是别的」这类问题变成改两行补丁的事？ 答案是 Capability Seam：把一种能力切成三个角色，让接口、实现、消费者独立演进。</description><pubDate>Fri, 28 Aug 2026 07:00:00 GMT</pubDate></item><item><title>第 07 课 · Profile 与 Bundle：组合即配置</title><link>http://localhost:4321/posts/dsh-tutorials/07-profile-and-bundle/</link><guid isPermaLink="true">http://localhost:4321/posts/dsh-tutorials/07-profile-and-bundle/</guid><description>第 02 课说插件条目来自显式声明，第 01 课你见过 --dump-config 的组合树。这一课补上中间的机制：dsh-base 的 80 余行插件、你的自定义行为、应用层，是怎么叠成一棵树的？ 一句话答案：Profile = 有序 Bundle 列表 +…</description><pubDate>Fri, 28 Aug 2026 06:00:00 GMT</pubDate></item><item><title>第 06 课 · 持久层、投影与「日志化状态」</title><link>http://localhost:4321/posts/dsh-tutorials/06-persistence-and-logged-state/</link><guid isPermaLink="true">http://localhost:4321/posts/dsh-tutorials/06-persistence-and-logged-state/</guid><description>第 05 课说内存日志是「上半身」。这一课看下半身：重启之后会话怎么回来？状态（计划、目标、待办）存在哪？ dsh 给出的统一答案有点反直觉：状态就是日志的纯函数。没有独立的状态机，恢复即重放。</description><pubDate>Fri, 28 Aug 2026 05:00:00 GMT</pubDate></item><item><title>模型看到的必须在日志里：dsh 的 Turn 执行流</title><link>http://localhost:4321/posts/dsh-turn-loop/</link><guid isPermaLink="true">http://localhost:4321/posts/dsh-turn-loop/</guid><description>[上一篇](/posts/dsh-overview)讲了 dsh 的插件架构。这篇看它的心脏：一条用户输入进来之后，「模型思考 → 调工具 → 再思考」的循环怎么被驱动，以及每一步为什么都要留痕。（约 6 分钟）</description><pubDate>Fri, 28 Aug 2026 04:30:00 GMT</pubDate></item><item><title>逐文件 100% 覆盖：dsh 的质量门禁长什么样</title><link>http://localhost:4321/posts/dsh-quality-gates/</link><guid isPermaLink="true">http://localhost:4321/posts/dsh-quality-gates/</guid><description>前三篇讲了 dsh 的架构、执行流和能力接缝。这些设计靠什么守住？答案藏在根目录 package.json 里：44 个 verify- 脚本，加上一条毫不客气的覆盖率注释。（约 7 分钟）</description><pubDate>Fri, 28 Aug 2026 04:00:00 GMT</pubDate></item><item><title>第 05 课 · 会话日志与「模型可见 ⟺ 已记录」</title><link>http://localhost:4321/posts/dsh-tutorials/05-session-event-log/</link><guid isPermaLink="true">http://localhost:4321/posts/dsh-tutorials/05-session-event-log/</guid><description>第 04 课你看到请求体来自 session.deriveMessages()。这一课回答随之而来的问题：这个日志凭什么能重建请求？如果有人往日志里塞了一个模型看得见但没走正常通道的事件呢？ dsh 的答案是三层防御，并且每一层都有具体的代码载体。</description><pubDate>Fri, 28 Aug 2026 04:00:00 GMT</pubDate></item><item><title>崩溃的 turn 要关闭，不是截断：dsh 的会话持久化</title><link>http://localhost:4321/posts/dsh-persistence/</link><guid isPermaLink="true">http://localhost:4321/posts/dsh-persistence/</guid><description>第二篇说过，session log 是 dsh 的唯一事实来源。那这条日志怎么落盘、崩了怎么办、又能从里面长出什么？这篇讲 packages/session/ 这个组。（约 6 分钟）</description><pubDate>Fri, 28 Aug 2026 03:30:00 GMT</pubDate></item><item><title>一切皆插件：读 DeepSeek Harness 的架构</title><link>http://localhost:4321/posts/dsh-overview/</link><guid isPermaLink="true">http://localhost:4321/posts/dsh-overview/</guid><description>DeepSeek 开源了一个 Agent Harness，代号 dsh。装起来一行命令：npx @deepseek-ai/dsh web，默认在 127.0.0.1:3080 起一个 Web UI。（约 6 分钟）</description><pubDate>Fri, 28 Aug 2026 03:00:00 GMT</pubDate></item><item><title>第 04 课 · 一次 Turn 的完整旅程</title><link>http://localhost:4321/posts/dsh-tutorials/04-turn-execution-flow/</link><guid isPermaLink="true">http://localhost:4321/posts/dsh-tutorials/04-turn-execution-flow/</guid><description>前两课是骨架和语法，现在看产品主干：用户发一句话，到模型回复并执行完工具，中间到底发生了什么？ 答案浓缩成一句：kick() 就是 while (await this.turn()) {}（packages/core/agent-loop/src/agent.…</description><pubDate>Fri, 28 Aug 2026 03:00:00 GMT</pubDate></item><item><title>状态就是日志：plan、todo、goal 在 dsh 里怎么存</title><link>http://localhost:4321/posts/dsh-logged-state/</link><guid isPermaLink="true">http://localhost:4321/posts/dsh-logged-state/</guid><description>agent 产品里常见一批「状态」：计划模式开了没、待办列表写了啥、长期目标推进到哪。多数实现里它们是运行时内存对象或独立存储。dsh 给出的答案是同一个词：_logged state_——状态就是日志事件折叠出来的结果。（约 6 分钟）</description><pubDate>Fri, 28 Aug 2026 02:30:00 GMT</pubDate></item><item><title>压缩自己也进日志：dsh 的 Compaction 设计</title><link>http://localhost:4321/posts/dsh-compaction/</link><guid isPermaLink="true">http://localhost:4321/posts/dsh-compaction/</guid><description>长会话总会撞上下文上限，做 agent 的都逃不掉压缩这个课题。多数做法是「改历史」——把旧消息替换成摘要。dsh 的做法不太一样：压缩产生的摘要不是历史的一部分，压缩这个动作本身才进日志。（约 5 分钟）</description><pubDate>Fri, 28 Aug 2026 02:00:00 GMT</pubDate></item><item><title>第 03 课 · 五种事件分发模式：协作的语法</title><link>http://localhost:4321/posts/dsh-tutorials/03-event-dispatch-modes/</link><guid isPermaLink="true">http://localhost:4321/posts/dsh-tutorials/03-event-dispatch-modes/</guid><description>第 02 课解决了「谁先激活」。这一课解决「事件发生时，多个监听器如何协作」。 dsh 的事件不是一种泛型广播，而是五种语义——同一个 on() 注册，按事件名声明的模式被调度。选错模式的后果从「副作用顺序错乱」到「整条链被意外否决」不等，所以这是写插件的语法课。</description><pubDate>Fri, 28 Aug 2026 02:00:00 GMT</pubDate></item><item><title>声明即授权：dsh Web 客户端的 slot 体系</title><link>http://localhost:4321/posts/dsh-client-slots/</link><guid isPermaLink="true">http://localhost:4321/posts/dsh-client-slots/</guid><description>dsh 的浏览器端同样是插件系统，但 UI 组合有个额外难题：谁有权把组件渲染进谁的洞里？前端插件化项目在这里常常退化成约定俗成，dsh 把它做成了加载期的硬约束。（约 6 分钟）</description><pubDate>Fri, 28 Aug 2026 01:30:00 GMT</pubDate></item><item><title>Capability Seam：让 shell、文件系统和沙箱都可替换</title><link>http://localhost:4321/posts/dsh-capability-seam/</link><guid isPermaLink="true">http://localhost:4321/posts/dsh-capability-seam/</guid><description>读 dsh 源码最大的一个疑问：为什么 packages/shell/ 这一个「能力域」下面有九个包，一个跑 bash 的活儿至于拆这么细吗？看到 docs/glossary.md 里的一个词才反应过来：seam（接缝）。（约 6 分钟）</description><pubDate>Fri, 28 Aug 2026 01:00:00 GMT</pubDate></item><item><title>第 02 课 · 一切皆插件：Cordis 骨架二十分钟</title><link>http://localhost:4321/posts/dsh-tutorials/02-cordis-in-twenty-minutes/</link><guid isPermaLink="true">http://localhost:4321/posts/dsh-tutorials/02-cordis-in-twenty-minutes/</guid><description>第 01 课的组合树里每一条都是「插件」。问题是：插件之间怎么找到彼此？谁先加载？卸载时谁先走？ dsh 的回答是把这些问题全部交给运行时骨架 Cordis（vendor 进仓库：vendor/cordis/），并且给出三条统一规则：属性访问即服务解析、可用性即…</description><pubDate>Fri, 28 Aug 2026 01:00:00 GMT</pubDate></item><item><title>第 01 课 · 跑起来：三种运行形态与观察窗口</title><link>http://localhost:4321/posts/dsh-tutorials/01-run-and-observe/</link><guid isPermaLink="true">http://localhost:4321/posts/dsh-tutorials/01-run-and-observe/</guid><description>先别管架构图。假设你拿到这个仓库，第一个问题一定是：这东西怎么跑？跑起来之后，状态存在哪？ 这一课不读源码，只做三件事：跑起来、看配置、找日志。后面的每一课都会反复用到这些观察窗口。</description><pubDate>Fri, 28 Aug 2026 00:00:00 GMT</pubDate></item><item><title>把 CI 构建从 90 秒降到 12 秒</title><link>http://localhost:4321/posts/ci-90-to-12/</link><guid isPermaLink="true">http://localhost:4321/posts/ci-90-to-12/</guid><description>先说结论：PR 的 CI 反馈时间从 92 秒降到 12 秒，改动只有三处——缓存 key、一个 postinstall 脚本、任务编排。没有换工具链。（约 5 分钟）</description><pubDate>Wed, 19 Aug 2026 01:00:00 GMT</pubDate></item></channel></rss>