dsh-forge 架构文档

September 3, 2026 · View on GitHub

版本:0.1.14(正式版)· 最后更新:2026-09-03

1. 总览

dsh-forge 是 DeepSeek Harness(dsh)的插件组合分析插件。它以只读方式检视 harness 的插件组合树, 输出依赖关系、冲突检测、风险评估、可视化与升级建议,辅助开发者做出安全的组合变更决策。

设计原则

  • 分析只读:所有分析计算只读;simulate_combination 操作虚拟副本;报告生成与历史归档为可选落盘writeReportreports/archive_snapshotdata/history/),路径可经 DSH_FORGE_REPORTS_DIR / DSH_FORGE_HISTORY_DIR 覆盖。
  • 零依赖引擎core/ 仅使用 Node.js 内置 API(fs / path / module),不依赖任何第三方包。
  • 诚实声明:静态扫描结果标注 confidence / evidenceTier,未校准数据标 calibrated: false + 免责声明。
  • 三层分离:分析引擎(core)↔ 插件壳(src)↔ 客户端 UI(ui-plugin)职责清晰,可独立测试。

2. 三层架构

┌─────────────────────────────────────────────────────────┐
│                    Harness (dsh web)                      │
│  ┌───────────────────────┐  ┌──────────────────────────┐ │
│  │   dsh-forge (host)    │  │  dsh-forge-ui (client)   │ │
│  │   src/index.js        │  │  ui-plugin/lib/client.js │ │
│  │   ┌─────────────────┐ │  │  ┌────────────────────┐  │ │
│  │   │  14 tools       │ │  │  │ sidebar 入口       │  │ │
│  │   │  (defineTool)   │ │  │  │ modal + iframe     │  │ │
│  │   └────────┬────────┘ │  │  │ dashboard.html     │  │ │
│  │            │          │  │  └────────────────────┘  │ │
│  │   ┌────────▼────────┐ │  └──────────────────────────┘ │
│  │   │  core/ (引擎)   │ │                               │
│  │   │  30 个纯逻辑模块 │ │                               │
│  │   └─────────────────┘ │                               │
│  └───────────────────────┘                               │
└─────────────────────────────────────────────────────────┘

2.1 core/ — 分析引擎

零依赖纯逻辑层,可脱离 harness 独立运行(node --input-type=module -e "...")。

模块职责关键导出
composition.js组合源发现 + YAML 解析 + 生态收集collectEcosystem, discoverSources, mergeRows
truth.jsdump-config 真相源(三态降级)loadTruthEcosystem
analyze.js依赖图构建 + 风险评估buildGraph, assess, riskScore
conflicts.js冲突检测引擎checkConflicts, scanToolNames, scanServices
scope.js作用域感知(global vs per-agent)scanScopeHints
calibration.js运行期事件校准createCalibration, staticCalibration
leaks.js非可逆副作用泄漏扫描scanLeaks
semver.jsSemVer 解析 + 区间满足性satisfies, parseVersion, compareVersions
upgrade.jsnpm registry 升级检查checkUpgrades
audit.js逐行配置审计auditConfiguration
diff.js快照差异对比diffCombinations
simulate.js组合模拟simulateCombination, applyOps
plan.js升级路径预演(离线:proposeUpgrade 范围/阻断;simulateUpgrade 版本上移编排;cloneWithVersion 版本克隆)proposeUpgrade, simulateUpgrade, cloneWithVersion
visualize.js多格式可视化html, mermaid, asciiTree
dashboard.js交互仪表盘数据构建dashboard, buildEmbedData
skins.js仪表盘皮肤 token(light/dark 双主题,零依赖纯逻辑)SKINS, DEFAULT_SKIN, skinCssVars
history.js快照存档与加载archiveSnapshot, listHistory, loadHistory
report.jsMarkdown 报告生成 + 写入归档(报告/history 路径可配置,history 失败可见)buildMarkdownReport, writeReport, gates, reportsDir, historyDir, pkgVersion
stats.js历史趋势统计historyStats
presets.js预设对比comparePresets, readPreset
verify.js行级装载预检verifyRows
mode.jsTUI/Web/check 四层证据决策(启动入口/环境/场景/复杂度)decideUiMode, hasDesktop, decideAfterPortProbe
suggest.js补丁建议生成suggestPatch
knowledge.js知识库 + 已知模式 + 废弃扫描knownPatterns, scanDeprecations
errors.js统一错误反馈(归一化/聚合/预检/渲染)buildFeedback, normalizeFeedback, preflight, renderFeedback
evidence.js证据元数据(INV-6/A-2):稳定 finding_id + 置信度上限 + schema 校验makeFindingId, attachFindingIds, capConfidence, validateFindings
evidence-fusion.js证据融合(A-1 三态 + A-3 可行动 + INV-3 只降不清除)fuse
gate.js闸门裁决(方向 4):冻结 pass 语义(severity-only)+ 追加 lever/blockedBy/degraded;可配置策略(severity/tier/confidence→block|warn|allow),tier 只收紧、无 policy 时逐字节兼容冻结路径computeGate, gateFromFindings, severityBlocks, validatePolicy, resolveVerdict, stricter
runtime-calibration.js运行时校准(A-4 滑窗 + INV-2 时序边界 + A-2 关联键)createRuntimeCalibration, staticRuntimeCalibration
web-server.jsWeb 面板共享服务(CLI 与 harness 壳复用的 3060 数据通道 + CORS/端口探测/浏览器打开)createWebHandler, startWebServer, probePort, openBrowser

core/index.js 是门面模块,统一 re-export 全部公共 API,并提供两条分析管线与 saveSnapshot() / loadSnapshot() 快照序列化:

  • runAnalysis(opts)(同步):一站式管线 collectEcosystem → buildGraph → checkConflicts → assess → scanLeaks → attachFindingIds → capConfidence → fuse → buildFeedback;数据来自 datasetPath 快照或即时扫描,供测试与离线脚本使用。
  • runAnalysisAsync(opts)(异步,CLI/插件壳/Web 统一入口):与工具路径(selectEco)同一真相源偏好——优先经 loadTruthEcosystemdsh --dump-config 真实快照(dump-config),取不到才回退 collectEcosystem 扫描(scan);check / plan / web 与 auto-web 面板均经它装载,避免在可取得 dump 时静默降级。

2.2 src/ — 插件壳

文件职责
src/index.jscordis 插件入口:apply(ctx, config) → 创建 calibration → 遍历 14 个工具工厂 → defineTool 注册;注册后 void startAutoWeb(cfg) 同步拉起共享 Web 面板(3060,不自动开浏览器)
src/tools/index.js + src/tools/*.js14 个工具定义(每工具一文件,共享 common.js):name / description / parameters(JSON Schema) / output.schema / execute / render

工具注册流程:

apply(ctx, config)
  → createRuntimeCalibration(ctx)   // 运行期事件订阅 or 静态降级
  → probeRuntime(ctx)               // 探测 22 个 harness 服务
  → for each factory in ALL_TOOLS:
      ctx.tools.register(defineTool(factory(cfg)))

每个工具的 execute 方法通过 selectEco(args, config) 获取生态数据,再委托 core/ 对应模块计算。

双入口职责(勿混淆)src/index.js(cordis 插件壳)只负责把 14 个工具注册进 harness,并持有运行期探测与启动预检;core/index.js(零依赖分析引擎门面)是 CLI 与全部测试的唯一事实源。新增分析能力一律进 core/ 并在 core/index.js re-export;只有需要暴露给 harness 作为工具时才在 src/tools/<tool>.js 新增定义。CLI(cli/dsh-forge.mjs)与测试套件 import core/,不依赖 src/

2.3 ui-plugin/ — 客户端插件

文件职责
ui-plugin/index.jscordis 客户端插件入口
ui-plugin/lib/client.template.js源模板:2 个 slot 注册 + modal 组件
ui-plugin/lib/client.js构建产物(scripts/build-ui.mjs 打包,内嵌 dashboard.html)

2 个 UI 入口 slot:

  • sidebar.footer.action — sidebar 底部「▦ 插件仪表盘」按钮
  • conversation.chat.turnTail — 对话流引导卡片

子 slot 注册通过 ctx.slots.inject(parent, fn) 等待父 slot 声明后再注册,避免抢跑。

2.4 cli/ — 独立双壳入口(默认 TUI,按需 Web)

cli/dsh-forge.mjs(package.json bin.dsh-forge)复用 core/ 分析引擎, 按 core/mode.js 的四层证据选择形态:

命令形态
dsh-forge自动决策:终端内默认 TUI;无 TTY+桌面会话 → Web;CI/管道 → check
dsh-forge tui强制 TUI(零依赖 ANSI;W 一键开 Web,R 刷新,Q 退出)
dsh-forge web / serve强制 Web(node:http + 10 模块交互仪表盘;缺 client.js 回退自包含 SVG 拓扑;端口占用自动降级)
dsh-forge check / ci纯日志或 --json,无界面,面向脚本消费

TUI 壳与 Web 壳不引入第三方依赖:TUI 用 ANSI 渲染,Web 用 node:http serve core/dashboard.js 生成的 10 模块交互仪表盘(缺 web/dashboard-client.js 时回退 core/visualize.js 的自包含 SVG 页面),保持 core 零依赖与离线可部署。 Web 形态为混合审查:每次请求用当前分析结果新鲜渲染(静态层),live 模式页头提供 ↻ 刷新 按钮(/api/refresh 清除分析缓存后重新分析并返回新嵌入数据,动态层), 静态快照渲染则优雅隐藏该控件。

3. 数据流

3.1 生态数据收集(selectEco)

用户调用工具 execute(args)

  ├─ args.dataset?  ──→ loadSnapshot(file)          // 离线快照模式

  └─ truthSource = auto | dump-config | scan

       ├─ dump-config (首选)
       │    → loadTruthEcosystem({ home, profile })
       │    → dsh --dump-config → 解析生效组合树(含 provenance)
       │    → 成功: 返回 ecosystem + truthSource="dump-config"
       │    → 失败: auto 模式降级到 scan

       └─ scan (回退)
            → collectEcosystem(opts)
            → discoverSources() → 解析 cordis.yml + bundle 补丁 + patch.yml
            → 扫描 node_modules 包清单
            → 返回 ecosystem + truthSource="scan" + warnings

CLI / 插件壳 / Web 统一入口(v0.1.14):工具走 selectEco()(上图),而独立 CLI(cli/dsh-forge.mjsloadAnalysisAsync)、harness 插件壳 auto-web 与 Web 面板 refresh 统一经 runAnalysisAsync() 装载分析——与上图同一真相源偏好:优先 dump-config,不可用才回退 scan。三处不再各自退化为 scan;core/web-server.jscreateWebHandler 已 async 化,readAnalysis() 统一 await 可能返回 Promise 的分析对象。

3.2 冲突检测(check_conflicts)

check_conflicts execute

  ├─ selectEco() → eco
  ├─ buildGraph(eco) → graph
  ├─ checkConflicts(eco, { graph })
  │    ├─ 版本冲突: satisfies() 检查依赖 range
  │    ├─ 工具重名: scanToolNames() + scope.js 作用域分级
  │    │    ├─ 全部 scoped → tool-name-scoped-variant (heuristic/info)
  │    │    └─ 含全局 → tool-collision (contract/high)
  │    ├─ 服务覆盖: scanServices() → provide 重复 (impact: "待实证")
  │    └─ 泄漏扫描: scanLeaks() → apply 路径对账 + 知识库排除
  ├─ calibration.snapshot() → 运行期行为基线 (或 null)
  └─ 返回 { conflicts, leaks, calibration, inputScope, truthSource, disclaimer }

3.3 升级检查(check_upgrades)

check_upgrades execute(args)

  ├─ selectEco() → eco
  └─ checkUpgrades(eco, { limit, registry, timeoutMs, concurrency })
       ├─ 筛选 @deepseek-ai/* 包 (limit 默认 40)
       ├─ 并发池 (默认 6) 查询 npm registry /latest
       │    ├─ 主 registry (npmjs.org) 连续失败 ≥2 → 切镜像 (npmmirror)
       │    ├─ 独立超时 (默认 3.5s) → 失败包入 networkFailures
       │    └─ 404 → 该包无 latest (跳过)
       ├─ 比对 installed vs latest → 过滤非升级
       ├─ 阻断预测: satisfies(latest, consumerRange) === false → blockers
       └─ 返回 { candidates: [{ package, installed, latest, blockers, installCmd }], networkFailures, elapsedMs, ... }

3.4 升级路径预演(plan / plan_upgrade)

dsh-forge plan --to <pkg@ver,...>src/tools/plan.js 暴露 plan_upgrade)是离线且确定性的升级推演:不做行级变更、不改组合、永不触发 check 的 gate-exit

plan(e)  [cli --to pkg@ver | plan_upgrade targets]
└─ 全显式版本 → 纯离线:simulateUpgrade(eco, wish)              (确定性,无网络)
└─ 含 @latest   → proposeUpgrade(eco,{fetch}) 走仓库解析后接 simulateUpgrade
simulateUpgrade(eco, wish)
├─ cloneWithVersion(eco, wish)       # 版本级克隆(不触碰 row)
├─ buildGraph + checkConflicts + assess   # before(基线)
├─ buildGraph + checkConflicts + assess   # after(目标)
└─ 返回 { upgraded[], before, after, riskDelta, newResolved,
          rowDiff, verdict, doSteps }
  • proposeUpgrade 出升级范围与 breaks(consumer 声明范围拒收);breaks 判定复用 upgrade.jssatisfies(version, range),保证单一实现。
  • ESLint 之外的一切纯函数位于 core/plan.js(模块数 28→29),CLI/工具/测试三处复用。

3.5 闸门杠杆与置信分层(方向 4)

冻结契约 gate.pass 不变(任何 blocking/high 即 fail,与置信无关)。core/gate.jspass/blocked 之外追加透明层:

gate 字段含义
leverblock(≥1 strict 高置信阻断)| degraded(触发但全部是置信降级证据)| advisory(PASS)
blockedBy[]装载级明细:「因哪条规则拦了谁」——{ finding_id, rule, finalSeverity, confidence, evidenceTier, capped }
degraded[]blockedBy 的子集:scan cap 或低/中置信却达阻断级别,应先用 dump-config 复核再 enforce
policyApplied本次是否使用了显式 gate 策略(只有调用方传 --policy/{policy} 时才出现)

projectFinding 追加 capped / rule 字段(schema 追加式,不破坏 report@1)。check BLOCKED 时文本列出前 8 条阻断明细;report.md 在闸被触发时输出「闸门明细(blockedBy)」表与降级提示。CLI/report.js::gates 均复用 computeGate(单一实现)。

3.5.1 可配置闸门策略(选项 C,--policy <file.json>

显式传入 policy 才改变裁决;未传时走冻结路径(逐字节兼容)。

{ "severity": { "blocking": "block", "high": "warn", "medium": "allow", "low": "allow" },
  "tier": { "contract-source": "block" },
  "confidence": { "low": "warn" } }
  • 每条 finding:baseline = severity[finalSeverity](缺省:blocking/high→block,其余 allow);tier/confidence 维度只收紧stricter,block>warn>allow)——降级用 severity,权威证据用 tier 钉死。
  • 有 policy 时 gate.pass = 不存在 block 裁决gate.blocked 仍为冻结 severity 计数(报告保留原始红灯)。
  • validatePolicy 确定性校验(非法 key/value 抛错,CLI 读 --policy 失败 exit 2)。
  • CLI:dsh-forge check --dataset X --json --policy policy.jsonexit 1 基于 policy 裁决后的 pass

4. 真相源三态设计(truthSource)

模式数据来源精度降级
dump-configdsh --dump-config 官方输出精确(harness 实际装载树)不可用则报错
auto(默认)优先 dump-config精确失败自动降级 scan + warning
scan源码扫描重建近似(可能偏离)

core/truth.jsfindDshBin() 从 8 层候选路径查找 dsh 可执行文件,超时 20s 兜底。

5. 测试架构

全部自包含、零本机依赖(mock fetch / mock ctx / DOM-mock / VM bundle)。

套件文件项数覆盖
仪表盘结构+交互test/ui-test.mjs77workspace 结构 / 默认页(使用引导)/ 页切换 + 搜索/筛选/排序/toggle/增删候选 + 名词解释/悬停提示 + 旧模块引导条/表头详释 + 133 行数据 + live 动态标记回归
客户端插件 VM 执行test/ui-plugin-test.mjs222 slot 注册 + locale + 模态开关 + wide/collapsed 渲染
SemVer 回归test/semver-consistency.test.mjs30core/semver.js 单一实现 30 用例固定断言 + 防 dashboard 镜像回归
作用域/校准/泄漏test/review-fixes.test.mjs15scope 三态 + mock 事件校准 + 泄漏切片
证据融合引擎test/evidence-fusion.test.mjs23A-1 三态 + A-2 稳定 id + A-3 可行动 + 完整融合矩阵 + tier/confidence 去混淆 + INV-3 绝不清除
运行时校准test/runtime-calibration.test.mjs25A-4 滑窗/基数上限/超限丢帧(可观测)+ INV-2 时序边界(单调时钟)+ 可逆性/dispose 释放引用
真相源三态降级test/truth-source-degradation.test.mjs17INV-4 置信度上限(只降不升、纯函数不突变)+ scan 全局降级 + 64 位 finding_id 哈希
升级检查优化test/upgrade-opt.test.mjs16并发池 + 超时 + 镜像降级 + 安装命令 + 独立性 + 阻断预测
错误反馈冒烟test/feedback-smoke.test.mjs40FORGE 错误码 / 分级 / 聚合 / 渲染
空组合 / 泄漏规则test/empty-plugins.test.mjs24空组合边界 + 泄漏规则
随机子集探索test/exploratory-empty.test.mjs27随机插件池 + 多轮组合一致性
反馈深度探索test/exploratory-feedback.test.mjs563反馈结构合法 / 分级计数 / 排序稳定 / 确定性
TUI/Web/check 决策test/mode-decision.test.mjs19四层证据决策(命令/环境/场景/复杂度)/ env 一致性 / 端口占用降级 / 场景启发
分析缓存守护test/cache-behavior.test.mjs7同参命中 / clear 失效 / 文件变更 / live profile patch 变更 / 淘汰 / 快照 stamp
主链路融合回归test/main-path-fusion.test.mjs8P0 主路径真正 fuse:runAnalysis 项带 runtimeState/finalSeverity/evidenceTag(离线 not-executed)+ INV-3 不清除 + severity 秩有效
启发式检测收敛test/heuristic-detect.test.mjs16句柄捕获感知泄漏(已知安全降级 / leak-context / 全部 BARE 规则)+ 动态工具名按包追踪与显式扫描局限
check --json schema 冻结test/check-report-schema.test.mjs10P0-3 冻结 check report schema(schemaVersion/inputs/findings[]/gate)+ gate 门禁(high/blocking 拦截)
闸门杠杆/置信分层test/gate-lever.test.mjs12方向 4:computeGate/gateFromFindings 的 lever(block/degraded/advisory)、blockedBy 明细、degraded 分层;冻结 gate.pass 语义保持
可配置闸门策略test/gate-policy.test.mjs11方向 4(选项 C):validatePolicy/resolveVerdict 的 severity→baseline + tier 只收紧;契约冲突在 scan cap 下仍 block;severity 降级放行;无 policy 冻结路径逐字节兼容
finding_id 唯一性消重test/finding-id-uniqueness.test.mjs6makeFindingId 纳入 involved packages/service/row,区分同类别多条 finding;A-2 message 不变 id(0 碰撞回归)
14 工具快照半集成test/tools-snapshot-smoke.test.mjs14快照驱动调用 14 个工具 + output.schema 最小校验(防 schema/output 漂移),CI 可运行
YAML fail-loud / vm 沙箱test/composition-strict.test.mjs8严格解析接受合法 patch(含 config block scalar、cordis inject 行键)/ 未知行键与顶层条目抛错 / globalThis 逃逸被拒 / dshHomePath 可用

测试策略:

  • 单一实现回归:semver-consistency 固定断言 core/semver.js 行为,并守护 dashboard.js 不再内嵌镜像副本
  • VM 真实执行:ui-plugin-test 用 vm.createContext 执行 client.js bundle
  • DOM-mock:ui-test 用 mock React createElement 模拟仪表盘交互
  • mock fetch:upgrade-opt.test 用 mock fetch 验证网络逻辑,零真实网络依赖

6. 工程资产

路径说明
.github/workflows/ci.ymlCI 模板(Node 22+,运行自包含测试套件;跳过依赖本机路径/真实 harness 的 smoke13.test.mjs)
scripts/generate-dashboard.mjs用当前 dashboard.js 从离线快照重新生成 reports/dashboard.html
scripts/build-ui.mjs构建客户端 bundle(内嵌 dashboard.html 到 client.js)
scripts/mount-ui.mjs挂载脚本(自动探测部署 node_modules;env:DSH_HOME / DSH_DEPLOY_NM / DSH_FORGE_ROOT / DSH_PROFILE_PATCH)
scripts/mount-ui.ps1Windows PowerShell 挂载脚本
pnpm-workspace.yamlpnpm workspace 配置
data/ecosystem.json离线生态快照(dsh-forge-ecosystem@1 格式)
data/history/历史快照存档(gitignored,运行期生成;data/ecosystem.json 为 versioned 基线)
reports/runtime-verification-checklist.md静态盲区的运行时沙箱验证清单(A 生命周期 / B 事件竞态 / C Seam / D Agent Loop / E 证据规范)

8. 架构设计不变量(Design Invariants)

编号不变量违反后果验证方式
INV-1core 层保持离线零依赖,运行时观测逻辑只在 src 插件壳层core 无法独立运行,离线审计能力丧失CI:纯 Node.js 环境运行 core 测试套件
INV-2运行时校准只观测 dsh-forge 加载之后的事件,不回溯初始化虚假承诺导致漏检,用户信任崩塌文档显式声明 + 测试验证启动时序边界
INV-3运行时未观测到风险仅降级、绝不清除(且未观测三态化,absence≠evidence-of-absence)引入新漏检,违反保守性原则单元测试覆盖全部融合降级 + 三态边界(A-1)
INV-4真相源降级到 scan 后全局降低置信度上限输出虚假高可靠结果,误导自动化决策自动化测试:scan 模式输出校验
INV-5vm 加固仅提升可信配置场景安全性,不用于对抗不可信输入安全边界被突破,代码注入风险安全文档声明 + 威胁模型评审
INV-6所有静态扫描输出必须携带置信度元数据(confidence/evidence),区分推测来源与事实证据证据不可追溯,无法区分误报与真实风险Schema 校验:所有 findings 必须含 confidence 字段

7. 版本策略

  • 遵循三位 SemVer(X.Y.Z),使用 prerelease 后缀标识开发阶段(如 alpha-v0.1.0
  • hotfix/patch 使用 prerelease 后缀(如 alpha-v0.1.0-patch.1),不使用第四位版本号
  • harnessVersion 绑定:0.1.1-rc.2
  • 知识库模式声明验证版本,版本漂移输出 knowledge-version-drift 告警