dsh-project-nav
Manifest validAnti-drift project governance plugin for DSH — bidirectional feature-map, mainline vector, architecture-first protocol | DSH project anti-drift governance plugin
核心理念(唯一上位约束)
所有开发动作必须从架构出发。 架构不出错,开发过程中出现一点问题也只是局部小问题;反之,架构错了,局部补得再好也是在错误的骨架上堆砌。
它解决的问题:AI 写单个文件没问题,但在引用之间没有全局思想—— 改一个文件不知道牵动谁,于是只能在一个文件里越堆越长。本插件把「谁属于谁」和**「谁引用谁」**一起摊给模型看。
v0.10.0 是架构换代:模型从「包含树」升级为**「包含树 + 依赖图」。
依赖边由 import 静态扫描派生**(不是登记、不是手写、不会过期),同时闸门六 → 七,新增影响面闸。
设计契约见 ARCHITECTURE.md。
1. 一句话架构
一条 append-only 事件流(唯一事实源)+ 一个由它折叠出的架构模型(可丢弃缓存)+ 一层按需产出(零落盘)。 模型 = 包含树 + 依赖图;依赖图由磁盘 import 派生。闸门是对模型的查询,产出是模型的重渲染。
┌────────────────────────────────────────────────────────────────┐
│ ① 事件流 .internal/events.jsonl ← 唯一事实源(append-only)│
│ commit{锚点,scope,arch=,phase} · decide{ADR} · node{} · set{} │
└───────────────────────────┬────────────────────────────────────┘
│ 纯函数折叠(I1)
┌───────────────────────────▼────────────────────────────────────┐
│ ② 模型 .internal/runtime/arch-model.json ← 可丢弃(I3) │
│ 包含树(项目/模块/功能/工件) + 依赖图 + 证据 + 向量 + 计数 │
│ 依赖图 = import 静态扫描派生(磁盘实况,与 STALE/缺口同层) │
└───────────────────────────┬────────────────────────────────────┘
│ 全部派生(I2)
┌──────────────────────┴──────────────────────┐
▼ ▼
nav_graph 按需直出 【在场层】每轮注入 agent 上下文
(闸门=查询 / 影响面 / 健康) (systemPrompt 常驻·单一注入路径)
└──────────── 零落盘:无任何投影文件(0.12.0)────────────┘
三条不变式(可机检)
| 不变式 | 验法 | |
|---|---|---|
| I1 | 单源:模型每条属性都能由「事件流 + 磁盘实况」复算,无第二手写真相 | 复算 == 缓存(依赖图两路径必须一致,否则缓存就是第二个答案) |
| I2 | 渲染:一切机器可读产出都是对模型的纯函数派生(直出 / 注入),治理面零落盘 | 渲染调用后治理根无任何新文件 |
| I3 | 可丢弃:删掉整个 .internal/runtime/ → 治理零损失(依赖图同办) | 删后跑全量查询,结果一致 |
2. 治理面最小化(第一性判据)
会因代码变更而"过期"的文档,不该是文档 —— 该是投影。
投影 = 零手写、随时重生、没有"过期"这回事(因为没人维护它)。于是手写面只剩两样:
| 面 | 载体 | 何时改 |
|---|---|---|
| 契约 | ARCHITECTURE.md · AGENTS.md | 只在架构换代 / 纪律变更时 |
| 产出 | nav_graph 按需直出 · 在场层注入(0.12.0:不再物化成文件) | 永不手写,随时重算 |
⚠ 0.12.0 换代(ADR-268):投影的"物化"整体退场 —— PROJECT.md 标记区 / .internal/ARCH-MODEL.md /
地图 HTML 三个落盘投影已删除。判因:它们的唯一读者是人,而定案是治理面只服务 agent;
实测全仓零机器读者,且 ARCH-MODEL.md 自述的唯一理由「进仓以便 git diff 审查」在治理根 D:\FF
不成立(那不是 git 仓库)。其 agent 形态的替代物是在场层(见 §3.1)。
.internal/arch/*.md 曾是要维护的资产(sha1 指纹 + 新鲜度机检 + 行号重锚),
0.10.0 起降级为按需临时投影:不盖指纹、不做机检。要让它被按任务检索到,
登记成普通 artifact 节点(nav_node layer=artifact when=…),走 nav_graph mode=docs。
3. 五个工具(11 → 5)
工具数下降不是目标,是"闸门变查询、产出变在场"的结果。
| 工具 | 模型操作 | 典型用法 |
|---|---|---|
nav_graph | 读:落点 / 影响面 / 缺口 / 覆盖度 / 文档路由 / 健康快照(含文件职责)/ 地图 | nav_graph mode=impact target=core/model.js |
nav_commit | 写:登记改动意图(锚点 + scope + arch= 一句话),跑七闸;自动按证据收上一笔 | nav_commit task="加一层校验" anchor=PN-F01 arch="架构不变" features=PN-F01 |
nav_decide | 写:架构决策(挂节点,登记即重置该节点补丁计数) | nav_decide anchor=PN-F01 reason=… decision=… |
nav_node | 写:节点 upsert / 退役并级联 / 参考文档工件 | nav_node target=E-F01 name=编辑器 files=src/a.js |
nav_set | 写:主线向量(doing / next / notDoing / exit) | nav_set doing="收口 shoucang" notDoing="pmg 融合" |
3.1 在场层:治理不再只等被调用(0.12.0)
病根(0.11.0 自述的实测):七闸只在 nav_commit 内跑 ⇒ 不调用它 = 完全绕行无痕迹,
治理根登记率仅 3%(4747 文件 / 4600 未登记)。根因不是闸门不够,而是治理只在被调用时存在。
落盘投影曾是"给人读"的产物;只服务 agent 之后,正确的替代物不是另一个文件,而是 把治理放进 agent 的上下文。⚠ 只有一条注入路径(0.12.0 修正,ADR-277):
| 出口 | 机制 | 触发 |
|---|---|---|
| 常驻摘要 | ctx.systemPrompt.section({ text: (c) => … }) | 每轮组装求值(text 是函数,不是静态串) |
为什么删掉了第二条(
tools/post-execute+additionalContexts):0.12.0 初版曾有,实测是纯重复 ——text每轮组装即求值,故每次请求的系统提示里已是最新治理;再在写类工具后注入同一份文本等于零新增信息 (真实会话日志实测:system/message每轮 1 份,而agent/inbox/spliced含同一文本 24 条、累计 ~31KB)。 更要紧的是它创建消息,而注入消息的source是承重字段:0.12.0 初版漏传source时, 下游插件的agent/pre-step无保护地读message.source.kind⇒ TypeError ⇒ 整轮turn/end {kind:'error'}(界面:"Cannot read properties of undefined (reading 'kind')")。systemPrompt.section从不创建消息 ⇒ 结构上不可能触发它。 故删路径比补source更根本: 补字段是修一个可能再次写错的点,删掉它让整类错误无处发生。
三条硬约束(缺一即是回退):
- 走廉价路径:只吃纯事件流折叠(
foldOnly,实测 5.1ms),绝不在组装期跑buildModel(含磁盘扫描,实测 177ms,每轮白付)。 - 零写盘:不落
runtime/、不建锁、不追加事件 ⇒ I1/I3 完好。任何"先落盘再注入"的实现都是回退。 - 不知道的不说:磁盘实况(STALE / 缺口 / 依赖图)不在廉价模型里,故摘要不报它们 —— 报一个没算过的数就是假绿。
为什么不与 0.11.0 的"观测层自我否决"冲突:那里否决的是订阅并记录活动事实(信息纯可派生、 只能落
runtime/⇒ 违反 I1/I3)。在场层不记录任何事实,它把已可派生的状态注入上下文。 同一份信息,被消费 ≠ 被存储。为什么不做成
pre-execute拒绝闸:治理在场的正确形态是可见,不是阻断—— 未经登记的写入被当场拒 ⇒ agent 无法开发,直接违背"让 AI 更好地把控和开发"这个目标本身。 这与 §4/§10 记录的判例同源:代理指标做成闸门必然退化成狼来了。
看一眼影响面:nav_graph mode=impact
这是本插件存在的理由。动手前问一句「我改的东西,谁在引用」:
File: core/model.js — 1 个落点文件
↓ 我引用谁:
core/model.js → core/log.js, core/paths.js, core/scope.js
↑ 谁引用我 = 影响面(9 个文件 · 7 个节点):
bootstrap.mjs ← 被 core/model.js 引用
core/commit.js ← 被 core/model.js 引用
...
最重要的行为变化:收口不需要第二个动作
- 登记一笔改动 = 一次
nav_commit,它记下 scope 内每个文件的{size, mtimeMs, sha1}作为证据。 - 改完文件后,下一次任意工具调用(任意会话)发现证据变了 → 自动收口。
- 收口不依赖会话:会话死了,意图照旧被任意会话按证据收口。
- 证据没变 ⇒ 意图继续在途(有人正在改 = 正常状态,不是孤儿)。
- 唯一绕过证据的出口:
nav_commit mode=archive id=ACT-N reason=…。
4. 七个闸门(全部是 nav_commit 内的模型查询)
| 闸门 | 问题 | 判据 | 强度 |
|---|---|---|---|
| 锚点闸 | 架构节点真实存在吗? | 节点在模型中,或锚定 .internal/arch/*.md | 拒 |
| 范围闸 | 撞主线反面吗?撞别人在途 scope 吗? | notDoing 命中 → 拒;与他在途重叠 → 告警 | 拒/告警 |
| 主线闸 | scope 里的模块在主线上吗? | 未被 doing/next 引用 → 告警 | 告警 |
| 影响面闸 | scope 的落点被别的节点引用了吗? | 跨节点下游未纳入 scope → 告警(测试文件不算意外下游) | 告警 |
| 计数闸 | 同一锚点又在反复打补丁? | 自上次决策以来 ≥ 3 次 → 强制先出决策 | 拒 |
| 决策闸 | 这次改动需要架构变更吗? | arch= 缺失 → 告警要求一句话回答 | 告警 |
| 完结闸 | 有该收而未收的意图吗? | 开新笔时按证据自动收旧;异常才报 | 自动 + 报异常 |
闸门是查询而不是流程,因此不可能产生"孤儿状态",也无法被"另开一条路"绕过——写入只有一个入口。
文件职责:治「一个文件越堆越长」的那条只读信号(不是闸门)
nav_graph mode=health 里除了闸门压力,还有一节文件职责:一个落点文件被几个不同架构节点登记。
文件职责(登记落点派生 · 只读):143 个落点文件 · ⚠ 1 个被 ≥3 个节点共用
⚠ deepseek/prompt-enhancer-release/lib/index.cjs — 归属 3 · 被引 2 · 引用 9
⚠ 示例必须取自真实输出:本节先前引用的示例里写着
nav_query/nav_update/nav_docs/nav_status/nav_set_vector五个工具名,而它们在 0.10.0 之后已不存在(工具面收敛为 6 个)。 门面上的失效示例与代码里的失效守卫同害:它训练人相信一份错的契约。 上例为治理根实测输出,跑nav_graph mode=health即得。
为什么不用行数红线:行数是代理指标。长文件未必坏,短文件照样能混三个职责;而一旦把行数做成闸门, 它必然退化成"狼来了"——与 0.10.0 修掉的计数闸退化(每笔改动被计两次、阈值 3 实际 ~1.5 就触发)是同一类错。
判据是结构,不是长度:归属数 = 这个文件被几个节点声明为落点(1 个 = 职责单一);被引/引用 = 依赖度数。
它们全部由落点表 + 依赖图派生,零手写、删 runtime/ 可无损重建。
函数只报告不拒绝——拆不拆是架构判断(走 ADR),不是阈值判断。
要拆就先改 ARCHITECTURE.md §9 落点表:新增文件 = 架构变更。
5. 数据面:2 层(3 → 2,0.12.0)
| 层 | 路径 | 生命周期 | 版本控制 |
|---|---|---|---|
| 事件流 | .internal/events.jsonl | 永久 | 是(唯一事实源) |
| 运行时 | .internal/runtime/(模型缓存 · 依赖图 · 在途 · 锁 · 诊断) | 短命 | 否(gitignore,可丢弃可重建) |
⚠ 原第三层「渲染投影」已随 0.12.0 换代退场(无文件可进仓)。
不存在第三层:任何新的长期状态先回答"它是事件,还是渲染?",两者都不是就不该存在。 依赖图不是第三层——它是磁盘实况,与 STALE 探测、缺口扫描在同一位置计算。
.gitignore必须只排除 runtime,不能整目录排除.internal/—— 否则事件流不进版本控制,新 clone 读不到任何决策,"决策可传播"就是一句空话。
6. 安装
# 1) 打包(在插件仓根)—— 产物名含版本号,从 package.json 派生
npm pack --cache .npm-cache # 产出 dsh-external-project-nav-<ver>.tgz
# 2) 装进 profile:直接跑装脚本(它自己从 package.json 读版本、摊开 tgz、定点改声明、自证)
powershell -NoProfile -ExecutionPolicy Bypass -File D:\FF\project-nav\install.ps1
powershell -NoProfile -ExecutionPolicy Bypass -File D:\FF\project-nav\verify-install.ps1
# 3) 重启 dsh —— 装与重启是两条时间线,重启前线上仍是旧版
⚠ profile 里不能跑 npm install(
link:协议不被接受)。用install.ps1直接tar展开。 脚本版本无关(版本从package.json读)—— 换代不再新增脚本。详见AGENTS.md§4。verify-install.ps1验五级:声明面 / 实体面 / 树 = 包 = 装 / 架构面 / 运行时面。 最后一级是必需的——静态对得上 ≠ 能加载。
配置(profile 里的插件项):
| 键 | 默认 | 说明 |
|---|---|---|
root | '' → 进程 cwd | 被治理工作区根(其 .internal/ 存事件流)。建议显式设置 |
7. 测试
npm test # 四个套件(项数跑一次即得,不写在这里——那是会漂移的数字)
npm run test:node-runner # 同一批用例走 node --test
| 套件 | 覆盖 |
|---|---|
test/core.test.mjs | 事件流 / 折叠 / scope 解析 / 七闸 / 依赖图扫描与影响面 / 收口 |
test/architecture.test.mjs | 不变量 I1·I2·I3(含依赖图双路径一致与可重建)· A1·A4·A5·A6 · 信息可达性(投影索引完整性 / 确定性渲染零 diff / 源码静默截断扫描 / json 按 mode 对应) |
test/concurrency.test.mjs | F1 并发追加不丢 / F2 破锁竞态 / token 校验 / 重入 / 无锁残留 |
test/host.test.mjs | 真 host 代码 + 桩 ctx:装配面 6 工具、闸门接线、nav_graph mode=impact 端到端、归属归一回归 |
沙箱提示:
node --test会用管道 spawn 子进程,在某些受限沙箱下报spawn EPERM。npm test直接执行测试文件(文件被直接运行时node:test同样执行),因此不受影响。
8. 版本规则
每次更新一律 +0.0.1,不因"加功能"跳中间位(lk 2026-09-10 定调)。 例外:架构换代才允许跳位,且必须在变更日志里写明"换代"二字。
0.8.6 → 0.9.0:换骨架(决策丢弃、事实 F1–F9 保留)。0.9.2 → 0.10.0:换代 —— 模型从「包含树」升级为「包含树 + 依赖图」,闸门六 → 七。0.10.0 → 0.10.1:修 bug(非换代)—— 计数闸曾把closed收口回执也当补丁数,每笔改动被计两次、 阈值 3 实际在 ~1.5 笔就触发;另修.d.ts被当代码扫、退役锚点计数仍显示。0.10.1 → 0.10.2:修 bug + 补一条只读信号(非换代)—— ① 锚点归一修漏:normalizeAnchor只走nodeId(layer, a),而nodeId会再key()一次, 于是module:pn-m03这类完整节点 id 被折成module:module:pn-m03→ 恒 NULL。 症状是「工具描述写着锚点可为节点 id,照写的反而全被锚点闸拒」——描述与实现不符会把人训练成猜别名。 ②nav_graph mode=health新增文件职责一节:一个文件被几个不同架构节点登记为落点 (由落点表与依赖图派生,只读、不拒、不设行数红线——行数是代理指标,做成闸门必然退化成狼来了)。0.10.2 → 0.10.3:仓清理(非换代、非功能) —— 删除三个不进包的死投影 (PROJECT.md/.internal/ARCH-MODEL.md/.internal/events.jsonl):产自 0.9 自举期, 而本仓不是治理根(治理根D:\FF,事件流在那边)⇒ 永不被nav_render重算 ⇒ 是历史快照而非投影, 且带着假事实(主线仍写"安装 0.9.0"、引用已删的HANDOFF.md/core/legacy.js)。 包内容与 0.10.2 逐字节相同(三者都不在files内),本版仅版本号与文档变化。- 口径澄清(2026-09-12):「每次更新」= 任何合并进 main 的改动,含不进包的仓清理
(
.gitignore/test// 本地脚本等)—— 一律 +0.0.1,不设「太小不必升」的判断口子; 只有架构换代才跳位。理由:可判定性高于省一个版本号;且0.10.0–0.10.2的发布链缺档 正是「靠判断决定要不要发布」的产物 —— 留判断口子 = 重造同类缺陷。 0.10.3 → 0.10.4:仓清理(非换代、非功能) ——.gitignore收敛三条已失效的.internal强制入仓规则(本仓非治理根;PROJECT.md/.internal/ARCH-MODEL.md/.internal/events.jsonl已随死投影清理删除)。不进包(files不含.gitignore)⇒ 除版本号外包内容与 0.10.3 相同。0.10.4 → 0.10.5:纪律变更(非换代、非功能) —— 治理开销从"理念"落成 ARCHITECTURE §2「信息可达性」判据 (压缩去冗余可以,静默丢信息不行,字节上限刻意不设)。实现:① 工具描述与输出文本去重 (mode 语义三处 → 一处、retire 级联预写删除、commit 成功回显压成一行全勾清单、教义复述收敛); ②format=json不再无视 mode 回全量(与所读 mode 一一对应;mode=json仍是真全量且不 slice); ③ gaps 的未登记文件按顶层目录聚合(计数守恒,一条不丢);④ ARCH-MODEL.md 的 ADR 节改全量一行索引 (老决策不再整条消失,实测投影体积大头是此节的逐条展开);⑤ 全仓定长 slice 补"共N/+N + 取回路径"; ⑥ 投影去时间戳 ⇒ 确定性渲染(模型不变 ⇒ 字节不变 ⇒ 重渲染零写盘),nav_render自报体积(信号非裁决); ⑦ 新增四条机检(投影索引完整性 / 确定性渲染 / 源码静默截断扫描 / json 按 mode 对应)。0.10.5 → 0.10.6:加功能(非换代) —— 「先查后造」的可见化三册(A 极简路线,圆桌会议定案): ① PN-S1 查证申报可见:plan此前写而不渲(治理根 45 条非空 plan 对模型完全不可见)⇒ 补三个出口 ——renderCommitResult(写入回执;启用那个零引用的model形参,取值必须走model.commits而非res.commit〔后者只有{id,seq,at}〕)·renderModelDoc收口表新增一列 (取src.plan:闭笔事件结构性带plan:'',照抄c.plan会得到"永远空白"的假绿)·nav_graph mode=json的openCommits[]补plan;renderHealth在途行顺带。渲染形态<原文>(N 段)/(未填)—— 裸串无法区分"填了"与"填得完整",只渲原文会让判据永不失败(假绿)。 ② PN-S2 零命中给候选:locate未知分支补确定性候选(2-gram 重叠打分 + 落点文件后缀命中), 零扫盘(不调walkFiles,实测 80ms/4471 文件);零候选时明说"候选 0 条",不凑数。 ③ PN-S3 既有决策点名:本锚点已有 ADR 时在回执里点名(带理由摘要);无决策时零输出。 ⚠ 架构面零变更:闸门仍七、事件 kind 仍 4、工具仍 6、无新增文件、未改两份契约 (PN-S3 的施工落点由草案的gates.js移到可见路径:通过的闸其 detail 不渲染,挂闸上等于死文本)。 新增机检 10 条(可见性三出口 marker〔变异验证:三处打回原状即三条变红〕/ 未附申报不阻断 / 闭笔后可追回 / json 见 plan / 未知 kind 必抛 / 零命中给候选 / 零候选不凑 / 后缀命中 / 有决策点名 / 无决策不点名),测试项数跑一次即得(不写死在这里 —— 那是会漂移的数字,见 §7)。0.10.6 → 0.11.0:换代 —— 治理面从「被调用的工具包」升级为「在场的治理层」。 判据来自实测:插件当时零事件监听、零外来治理探测,七闸只在nav_commit内跑 ⇒ 不调用它 = 完全绕行、 无痕迹。治理根实测登记率仅 3%(4747 文件 / 4600 未登记),而它治理的shoucang自建了 **105 个治理脚本- 3 本并行账本** ⇒ 插件根本不知道项目在自己建治理。本次换代补齐四件:
① 响应性(
runtime/scan-cache.json):scanImports是纯磁盘重活(2730 代码文件 ≈ 360ms), 每次调用白付;缓存指纹 = 文件清单 +size/mtimeMs,实测loadModel193ms → 70ms(省 64%)。 ⚠ 判据取fromCache布尔,不用耗时(耗时是代理指标会漂)。 ② 治理主权(governanceSovereignty):纯磁盘派生,报外来治理脚本与并行账本;只报告不处置 (删除属危险操作,且产品/构建脚本与治理脚本同名相似)。artifact的when写exempt即退出告警 (对标 Allstar 的 opt-out 策略,撤销后复现)。 ③ 治理活力(governanceVitality):mtime+ 事件流派生"改动是否晚于治理登记"(容差 60s,否则狼来了)。 ④ 健康三层:nav_graph mode=health分 覆盖 / 主权 / 活力 报告。 ⚠ 架构面变更:闸门仍七、事件 kind 仍 4、工具仍 6、无新增文件;scope → log依赖收紧 (扫描缓存要落runtime/,而 runtime 文件的唯一写法是rewriteVerified,复制第二份写法即下一个两处真相)。 ⚠ 一处架构自我否决:原方案设"观测层"(订阅tools/post-execute/fs/write-intent)记录活动事实, 实测证明其信息量为零(主权与绕过信号纯由磁盘+事件流派生),且订阅产出只能落runtime/(可丢) ⇒ 取消,三层收敛为两层。这是减法:能被丢掉的那份不可能是真相(I1)。 另修三处门面漂移:版本三处不一致(0.10.6/0.10.4/0.10.5)、README 写死测试项数(实测不符)、 示例里的 5 个已删工具名(nav_query等)——三条均已加机检守卫(含变异验证)。 ⚠ 配置面对账(2026-09-21 复核):本条目曾声称 profile 里的autoBindWorkspace/boundaryWorkspaces两个死键「已删除」—— 实测那是假记录: 两个键一直留在 profile 的cordis.patch.yml里(且 schemastery 会把未知键保留并传给插件, 并非静默丢弃)。现已真正清除(备份cordis.patch.yml.bak-deadkeys2-2026*)。 判例同 0.10.3("死投影携带假事实"):文档声称一件事已做,而实测它没做 —— 效果与"训练人相信一份错的东西"相同。声称"已删除"必须先实测它不在。
- 3 本并行账本** ⇒ 插件根本不知道项目在自己建治理。本次换代补齐四件:
① 响应性(
0.11.0 → 0.12.0:换代 —— 治理面收敛为「只服务 agent」。 判因(实测):落盘投影(PROJECT.md标记区 /.internal/ARCH-MODEL.md/ 地图 HTML)的 唯一读者是人,而定案是治理面只服务 agent;全仓 grep 零机器读者;且ARCH-MODEL.md自述的 唯一理由「进仓以便git diff审查」在治理根D:\FF不成立(实测它不是 git 仓库)。 架构面变更:① 工具 6→5(nav_render退场 —— 它唯一的操作是重生成落盘投影, 落盘面消失后它无事可做;留一个空工具比删掉更坏,它会让工具面说谎); ② 数据面 3→2 层(原「渲染投影」层退场);③ 落盘产出面整体消失;④ 新增在场层。 在场层是落盘投影的 agent 形态替代物(§3.1):ctx.systemPrompt.section常驻摘要 (text是函数,每轮组装求值)。它直接治 0.11.0 自述的病根 ——「七闸只在nav_commit内跑 ⇒ 不调用它 = 完全绕行无痕迹」(治理根登记率仅 3%)。 ⚠ 不是重开 0.11.0 否决的"观测层":那里否决的是记录活动事实(信息纯可派生、只能落runtime/⇒ 违反 I1/I3);在场层不记录任何事实,它把已可派生的状态注入上下文 —— 同一份信息,被消费 ≠ 被存储。 ⚠ 不是pre-execute拒绝闸:治理在场的正确形态是可见,不是阻断 —— 未经登记的写入被当场拒 ⇒ agent 无法开发,直接违背"让 AI 更好地把控和开发"这一目标本身。 三条硬约束(缺一即回退):只吃纯事件流折叠(foldOnly实测 5.1ms vs 全量buildModel177ms,35×)· 零落盘(不建 runtime、不加事件)· 不知道的不说(磁盘实况不在廉价模型里, 故摘要不报 STALE/缺口 —— 报一个没算过的数就是假绿)。 不变式的收紧:I2 从「手改渲染物会被覆盖」变为**「治理面零落盘」**(更强的机检判据: 调用渲染后治理根无任何新文件)。I1/I3 完好(在场层零状态)。 ⚠ 一处对旧实现的自我纠正:renderModelDoc里那个"回查closes指向的原始笔以取plan" 实为 no-op(closes只写在原笔自己身上;治理根 21 条带closes的记录中closes !== seq者 0 条)—— 值对、注释错,契约里已改述为实测语义。0.12.0 → 0.12.1:修 bug(非换代) —— 在场层收敛为唯一一路(ADR-277)。 0.12.0 初版有两条注入路径,其中tools/post-execute+additionalContexts是纯重复:systemPrompt.section的text每轮组装即求值,故每次请求的系统提示里已是最新治理, 再在写类工具后注入同一份文本等于零新增信息(真实会话日志实测:system/message每轮 1 份, 而agent/inbox/spliced含同一文本 24 条、累计 ~31KB)⇒ 违反 §2①「零信息重复必删」。 更要紧的是它创建消息:注入消息的source是承重字段(类型必填),0.12.0 初版漏传时 下游dsh-repeat-tool-reminder的agent/pre-step无保护地读message.source.kind⇒ TypeError ⇒ 整轮turn/end {kind:'error'}(界面:"Cannot read properties of undefined (reading 'kind')")。systemPrompt.section从不创建消息 ⇒ 结构上不可能触发它。 ⇒ 删路径比补source更根本: 补字段是修一个可能再次写错的点,删掉它让整类错误无处发生。 架构面:工具仍 5、闸门仍七、kind 仍 4、零新增文件、零新增状态;inject仍['tools','systemPrompt']。 新增机检:host 内不得出现additionalContexts/createUserMessage/'tools/post-execute'(源码级 + 行为级双重断言,含变异验证)。0.12.1 → 0.12.2:记录面对账(非换代、非功能) —— 清掉 profile 里两个真正的死配置键 (autoBindWorkspace/boundaryWorkspaces,全装机零消费者、插件Config只消费root), 并修正 README 的一条假记录:0.11.0 条目曾声称这两个键「已删除」,实测它们一直留在 profile 的cordis.patch.yml里(且 schemastery 会保留未知键并传给插件,并非静默丢弃)。 判例同 0.10.3("死投影携带假事实"):文档声称一件事已做而实测没做,效果是同一种 —— 训练人相信一份错的东西。新增机检:README 若提到这两个键,必须是对账叙述而非既成事实句, 且core/+host/源码不得再出现它们(含变异验证)。 本次包内容确有变化(实测逐文件 SHA 比对 0.12.1 包):ARCHITECTURE.md(在files内) 与README.md(不在files内,但 npm 总是自动包含它)都改了 ⇒ 须走完整发布链。 ⚠ 施工中我曾误判为"不进包、除版本号外相同"——「不在files里」不等于「不进包」:README/LICENSE/package.json是 npm 的自动成员。这类判断只能靠解包逐文件比对, 不能靠读files白名单推断(本仓第 N 次同类教训:判据打在实测上,不打在推断上)。0.12.2 → 0.12.3:修 bug(非换代) —— 主线向量的缺席不可观测(ADR-372)。 病根不是"少显示一行":同一份向量曾在四个渲染站点各自手写,对"未填"给出四种语义 ——nav_set回执四字段全显式(unset);renderHealth/renderPresence只显式doing/next,notDoing/exitCondition整行消失;renderTreeText干脆不渲染exitCondition。 于是「新增字段漏改一处」与「某字段从未被渲染」都不产生任何信号 (实测:全仓exitCondition13 处命中中消费面仅 2 处打印、七闸无一读取它)。 这与本仓 2026-09-23 刚治过的 ACT-341「空扫不得判绿」同族:失败不可观测。 修法:格式化收敛为单一权威vectorFields()(core/render.js导出,四站点全走它); 缺席一律显式(unset)。判据从模型派生(Object.keys(model.vector)排除updatedAt) ⇒ 向量长出新字段而无人渲染时自动失败,无需人维护。 架构面:工具仍 5、闸门仍七、kind 仍 4、零新增文件、零新增状态、vector 形状不变; 显示态与数据/判定态分离 —— JSON 快照缺席仍是空串(''),gates.js谓词仍取空串,(unset)只存在于给 agent 看的文本里。新增机检用例带变异验证(删掉一处理染 ⇒ 必须变红)。
9. 开发纪律
- 改代码前先读
ARCHITECTURE.md——它是本仓的架构契约,不是说明书。 - 改了架构先改契约;契约之外不新增文件(新增即架构变更)。
- 治理面零落盘:产出只有两种形态 ——
nav_graph按需直出、在场层注入上下文。 任何"先写个文件"的实现都是回退(0.12.0,ADR-268)。 - 会因代码变更而过期的文档,不该是文档 —— 该是投影。(§2)
- 事故事实(F1–F9)不可丢弃:它们是需求,只有实现方式可以换。
License
BSD-3-Clause © Fishsb (lk)
Comments
Loading…
Similar plugins
by hoyyang
思维导图式项目规划可视 + 最强防跑偏:计划→模块→任务树/DAG、执行序号、Agent GPS 站位、改图人审门、git 交叉核对、阻断级漂移防护(DeepSeek Harness 插件)
★ 0
BSD-3-Clause
TypeScript
Sep 16, 2026
dsh plugin --profile web add @dsh-external/dsh-plan-boardby moazzamak
A DeepSeek Harness plugin that shows a research graph: one JSON node store drawn as a node-link graph, a filterable board, and a steering frontier in the right pane, with a knowledge_dag tool for the model.
★ 0
NOASSERTION
JavaScript
Oct 6, 2026
dsh plugin --profile web add dsh-knowledge-dagby lzhphantom
DSH(DeepSeek Harness)组合包插件:只读扫描任意项目目录,自动构建**模块级 + 文件级知识图谱**,帮助快速理解项目整体架构与设计思路,为后续进化、优化提供依据。
★ 0
MIT
JavaScript
Aug 16, 2026
dsh plugin --profile web add dsh-kgraph-pluginby pioneer666-user
DSH(DeepSeek Harness)流程图管理插件:浏览 Archify 业务流程图目录、按 Git 附注标签阅读历史版本、保存版本。A workflow-diagram manager plugin for DSH.
★ 3
↓ 65/wk
MIT
JavaScript
Oct 7, 2026
dsh plugin --profile web add @pioneer_zmc/dsh-workbenchby huabai-flowerwhite
面向 DeepSeek Harness(dsh)第三方插件生态的 **Plugin Design**:发现第三方插件、检查其源码与配置、对照 DH-TP-SDK 工程化规范做静态分析、生成 `design.md`,经用户确认后对插件逐项修改并支持备份与回滚。
★ 6
MIT
JavaScript
Aug 29, 2026
dsh plugin --profile web add dsh-plugin-designby Oscar-Williams
Task-aware DSH plugin navigator: builds a local index from GitHub topics and community lists, retrieves across 28 bilingual capability classes, and provides commit-level static risk audit, consent-gat
★ 1
MIT
TypeScript
Sep 26, 2026
dsh plugin --profile web add dsh-deepatlas