🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

插件兼容守卫 LCYLYM/dsh-plugin-compat-guardian

DeepSeek Harness
LCYLYM23 天前有提交已提供中文文档扫描:含敏感能力

让 DeepSeek Harness 插件自己跟上 DSH 更新。

30.7/100
综合分
1
GitHub 星标
—
npm 周下载
—/5
用户评分

数据截至 2026/10/13 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

该插件未发布到 npm,按作者文档从 GitHub 源安装即可(静态检查只覆盖 npm 路径,不代表插件不可用)。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add LCYLYM/dsh-plugin-compat-guardian
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:已验证
是什么[目录]—
dsh 原生插件 · market
暂无时间戳·判据 →
装得上吗[实装验证]✓
本站已真实安装成功
非静态推断
L4 · 真实安装等级说明 →
数据截至 2026/09/25·判据 →
安全吗[自动扫描]—
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
数据截至 2026/11/04·判据 →
还在维护吗[仓库]✓
活跃:最近一次提交在 23 天前
暂无时间戳·判据 →
图例:✓ 通过! 需注意— 未判定 / 无数据· 「未判定」= 本站尚无数据,不代表插件有问题
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →

可信度证据

安装兼容性检查需源码安装

engines.node 要求 >=24.0.0,不满足 Node 22.19.0;仓库 package.json 标记 private,未发布到 npm,需从源码安装

展开查看检查明细 ↓

以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。

✗npm 包dsh-plugin-compat-guardian(未发布到 npm,仅可源码安装)
✗Node 引擎要求 >=24.0.0 · 基线 Node 22.19 不满足
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明

源码安装时若 pnpm 拦截 prepare 脚本,按其提示在 pnpm-workspace.yaml 的 allowBuilds 中放行后重跑。

验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/10/13 04:27:33

安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。

可执行外部命令读写/删除本地文件读取剪贴板或密钥环境变量发起外部网络请求
查看扫描证据(共 105 处,展示前 95 条)
  • 读取本地文件
    lib/delivery.js:20
    reportPath ? readFile(resolve(reportPath), 'utf8').then(JSON.parse) : {},
  • 读取本地文件
    lib/onboard.js:15
    await readFile(path);
  • 读取本地文件
    lib/onboard.js:29
    for (const file of await readdir(lib)) if (file.endsWith('.js')) candidates.push(resolve(lib, file));
  • 读取本地文件
    lib/onboard.js:36
    source = await readFile(file, 'utf8');
  • 读取密钥环境变量
    lib/onboard.js:56
    const key = process.env[config.credentials.api_key_env] ?? process.env.DEEPSEEK_API_KEY;
  • 写入本地文件
    lib/onboard.js:62
    await Promise.all([mkdir(runner), mkdir(dshHome)]);
  • 写入本地文件
    lib/onboard.js:63
    await writeFile(join(runner, 'package.json'), '{"private":true}\n');
  • 写入本地文件
    lib/onboard.js:68
    await writeFile(overlayPath, stringify(dshRouteRows(config)));
  • 删除本地文件递归
    lib/onboard.js:84
    await rm(temporaryRoot, { recursive: true, force: true });
  • 读取本地文件
    lib/onboard.js:139
    const manifest = JSON.parse(await readFile(resolve(root, 'package.json'), 'utf8'));
  • 读取密钥环境变量
    lib/onboard.js:143
    if (process.env[config.credentials.api_key_env] || process.env.DEEPSEEK_API_KEY) {
  • 写入本地文件
    lib/onboard.js:179
    await mkdir(dirname(target), { recursive: true });
  • 写入本地文件
    lib/onboard.js:180
    await writeFile(target, content);
  • 读取本地文件
    lib/publisher.js:54
    const report = JSON.parse(await readFile(reportPath, 'utf8'));
  • 读取本地文件
    lib/publisher.js:60
    const repair = report.kind === 'repair' || await readFile(join(evidencePath, 'repair.patch'), 'utf8').then(() => true, () => false);
  • 读取本地文件
    lib/publisher.js:64
    const patch = await readFile(patchPath, 'utf8');
  • 读取本地文件
    lib/publisher.js:77
    await writeFile(resolve(repoPath, '.dsh-compat.lock.json'), await readFile(join(evidencePath, lockName)));
  • 写入本地文件
    lib/publisher.js:77
    await writeFile(resolve(repoPath, '.dsh-compat.lock.json'), await readFile(join(evidencePath, lockName)));
  • 读取密钥环境变量
    lib/publisher.js:84
    const env = { ...process.env, GH_TOKEN: process.env.GH_TOKEN };
  • 发起网络请求
    lib/notifier.js:36
    const response = await fetch(url, {
  • 读取本地文件
    lib/notifier.js:100
    const report = JSON.parse(await readFile(resolve(options.reportPath), 'utf8'));
  • 读取密钥环境变量
    lib/notifier.js:108
    const ghEnv = { ...process.env, GH_TOKEN: process.env.GH_TOKEN };
  • 读取本地文件
    lib/model-smoke.js:58
    const root = await realpath(repoPath);
  • 读取本地文件
    lib/model-smoke.js:68
    const path = await realpath(resolve(root, item.path));
  • 读取本地文件
    lib/model-smoke.js:70
    data = await readFile(path);
  • 发起网络请求
    lib/model-smoke.js:84
    const response = await fetch(url, { redirect: 'error', signal: AbortSignal.timeout(30_000) });
  • 发起网络请求
    lib/model-smoke.js:134
    const metadata = await fetch(`${baseUrl}${root}/batches`, {
  • 发起网络请求
    lib/model-smoke.js:142
    const uploaded = await fetch(`${baseUrl}${root}/batches/${encodeURIComponent(batch.batchId)}/files/0`, {
  • 发起网络请求
    lib/model-smoke.js:147
    const committed = await fetch(`${baseUrl}${root}/batches/${encodeURIComponent(batch.batchId)}/commit`, {
  • 读取本地文件
    lib/model-smoke.js:157
    const repoPath = await realpath(resolve(options.repoPath));
  • 写入本地文件
    lib/model-smoke.js:160
    await mkdir(outputDirectory, { recursive: true });
  • 读取本地文件
    lib/model-smoke.js:165
    ? JSON.parse(await readFile(resolve(options.baseLockPath), 'utf8'))
  • 读取本地文件
    lib/model-smoke.js:166
    : JSON.parse(await readFile(resolve(repoPath, '.dsh-compat.lock.json'), 'utf8'));
  • 写入本地文件
    lib/model-smoke.js:246
    writeFile(join(outputDirectory, 'verified-lock.json'), `${JSON.stringify(nextLock, null, 2)}\n`, { mode: 0o600 }),
  • 写入本地文件
    lib/model-smoke.js:262
    writeFile(join(outputDirectory, 'blocked-lock.json'), `${JSON.stringify(blockedLock, null, 2)}\n`, { mode: 0o600 }),
  • 读取密钥环境变量
    lib/model-smoke.js:272
    const key = process.env[config.credentials.api_key_env] ?? process.env.DEEPSEEK_API_KEY;
  • 写入本地文件
    lib/model-smoke.js:289
    await Promise.all([mkdir(runner), mkdir(dshHome), mkdir(pack)]);
  • 写入本地文件
    lib/model-smoke.js:290
    await writeFile(join(runner, 'package.json'), `${JSON.stringify(dshRunnerManifest(options.dshVersion))}\n`);
  • 写入本地文件
    lib/model-smoke.js:301
    await writeFile(overlayPath, overlay(config, sessions, options.dshVersion, fixtures.length > 0));
  • 删除本地文件递归
    lib/model-smoke.js:449
    if (temporaryRoot) await rm(temporaryRoot, { recursive: true, force: true });
  • 写入本地文件
    lib/repair.js:313
    await mkdir(outputDirectory, { recursive: true });
  • 读取本地文件
    lib/repair.js:314
    const failureReport = JSON.parse(await readFile(resolve(options.failureReportPath), 'utf8'));
  • 读取密钥环境变量
    lib/repair.js:392
    const credential = process.env[config.credentials.api_key_env] ?? process.env.DEEPSEEK_API_KEY;
  • 写入本地文件
    lib/repair.js:421
    await Promise.all([mkdir(repairRunner), mkdir(dshHome)]);
  • 写入本地文件
    lib/repair.js:422
    await writeFile(join(repairRunner, 'package.json'), `${JSON.stringify(dshRunnerManifest(config.repair.dsh_version), null, 2)}\n`);
  • 写入本地文件
    lib/repair.js:423
    await writeFile(overlayPath, overlay(config));
  • 写入本地文件
    lib/repair.js:430
    await writeFile(guidancePath, guidance.text, { mode: 0o400 });
  • 写入本地文件
    lib/repair.js:431
    await writeFile(join(outputDirectory, 'migration-guidance.md'), guidance.text, { mode: 0o600 });
  • 删除本地文件递归
    lib/repair.js:789
    if (temporaryRoot) await rm(temporaryRoot, { recursive: true, force: true });
  • 发起网络请求
    lib/verifier.js:151
    const response = await fetch(url, { headers, signal: AbortSignal.timeout(2_000) });
  • 发起网络请求
    lib/verifier.js:195
    const response = await fetch(launchUrl, {
  • 发起网络请求
    lib/verifier.js:209
    const response = await fetch(baseUrl, { redirect: 'manual', signal: AbortSignal.timeout(2_000) });
  • 发起网络请求
    lib/verifier.js:234
    const response = await fetch(new URL(assertion.path, baseUrl), {
  • 读取本地文件
    lib/verifier.js:289
    const repoPath = await realpath(resolve(options.repoPath ?? '.'));
  • 写入本地文件
    lib/verifier.js:378
    await Promise.all([mkdir(runnerDirectory, { recursive: true }), mkdir(dshHome), mkdir(packDirectory)]);
  • 读取本地文件
    lib/verifier.js:386
    readFile(join(options.candidateGraphCacheDirectory, 'package.json'), 'utf8'),
  • 读取本地文件
    lib/verifier.js:387
    readFile(join(options.candidateGraphCacheDirectory, 'pnpm-lock.yaml'), 'utf8'),
  • 写入本地文件
    lib/verifier.js:395
    writeFile(candidatePackagePath, cachedPackage),
  • 写入本地文件
    lib/verifier.js:396
    writeFile(candidateLockPath, cachedLock),
  • 写入本地文件
    lib/verifier.js:405
    await writeFile(candidatePackagePath, `${JSON.stringify({ ...dshRunnerManifest(candidate.version), type: 'module' }, null, 2)}\n`);
  • 写入本地文件
    lib/verifier.js:430
    await mkdir(options.candidateGraphCacheDirectory, { recursive: true });
  • 读取本地文件
    lib/verifier.js:432
    writeFile(join(options.candidateGraphCacheDirectory, 'package.json'), await readFile(candidatePackagePath, 'utf8')),
  • 写入本地文件
    lib/verifier.js:432
    writeFile(join(options.candidateGraphCacheDirectory, 'package.json'), await readFile(candidatePackagePath, 'utf8')),
  • 读取本地文件
    lib/verifier.js:433
    writeFile(join(options.candidateGraphCacheDirectory, 'pnpm-lock.yaml'), await readFile(candidateLockPath, 'utf8')),
  • 读取本地文件
    lib/verifier.js:437
    const manifest = JSON.parse(await readFile(pluginPaths.packageJson, 'utf8'));
  • 删除本地文件递归
    lib/verifier.js:747
    if (temporaryRoot && !options.keepTemp) await rm(temporaryRoot, { recursive: true, force: true });
  • 读取本地文件
    lib/config.js:242
    const root = await realpath(resolve(repoPath));
  • 读取本地文件
    lib/config.js:246
    workspace = await realpath(resolve(root, config.plugin.workspace));
  • 读取本地文件
    lib/config.js:247
    packageJson = await realpath(resolve(workspace, config.plugin.package_json));
  • 读取本地文件
    lib/config.js:264
    override = parse(await readFile(absolute, 'utf8')) ?? {};
  • 读取本地文件
    lib/config.js:275
    contract = parse(await readFile(absolute, 'utf8'));
  • 执行外部命令来自配置/变量
    lib/process.js:63
    const child = spawn(command, args, {
  • 执行外部命令来自配置/变量
    lib/process.js:141
    const child = spawn(command, args, {
  • 读取本地文件
    lib/runtime.js:11
    return (await readFile(path, 'utf8')).trim();
  • 读取本地文件
    lib/runtime.js:20
    return JSON.parse(await readFile(resolve(repoPath, 'package.json'), 'utf8'));
  • 读取本地文件
    lib/hash.js:9
    return sha256(await readFile(path));
  • 读取本地文件
    lib/budget.js:52
    entries = await readdir(directory, { withFileTypes: true });
  • 读取本地文件
    lib/budget.js:72
    for (const line of (await readFile(path, 'utf8')).split('\n')) {
  • 读取本地文件
    lib/budget.js:95
    for (const line of (await readFile(path, 'utf8')).split('\n')) {
  • 写入本地文件
    lib/report.js:193
    await mkdir(directory, { recursive: true });
  • 写入本地文件
    lib/report.js:198
    writeFile(jsonPath, `${JSON.stringify(report, null, 2)}\n`, { mode: 0o600 }),
  • 写入本地文件
    lib/report.js:199
    writeFile(markdownPath, `${markdown}\n`, { mode: 0o600 }),
  • 写入本地文件
    lib/report.js:201
    if (process.env.GITHUB_STEP_SUMMARY) await appendFile(process.env.GITHUB_STEP_SUMMARY, `${markdown}\n`);
  • 读取本地文件
    lib/report.js:207
    const lock = JSON.parse(await readFile(lockPath, 'utf8'));
  • 写入本地文件
    lib/report.js:217
    await mkdir(dirname(lockPath), { recursive: true });
  • 写入本地文件
    lib/report.js:219
    await writeFile(temporary, `${JSON.stringify(lock, null, 2)}\n`, { mode: 0o600 });
  • 发起网络请求
    lib/dsh-web-transport.js:8
    response = await fetch(`${baseUrl}/api/${method}`, {
  • 读取本地文件
    lib/diff-policy.js:85
    const after = JSON.parse(await readFile(resolve(repoPath, manifestRelative), 'utf8'));
  • 读取本地文件
    lib/migration-guidance.js:30
    const snapshot = JSON.parse(await readFile(snapshotPath, 'utf8'));
  • 读取本地文件
    lib/migration-guidance.js:31
    const root = await realpath(repoPath);
  • 读取本地文件
    lib/migration-guidance.js:41
    const path = await realpath(resolve(root, file));
  • 读取本地文件
    lib/migration-guidance.js:43
    if ((await stat(path)).size > 1_048_576) { skipped.push(file); continue; }
  • 读取本地文件
    lib/migration-guidance.js:44
    const text = await readFile(path, 'utf8');
  • 发起网络请求
    lib/registry.js:25
    response = await fetch(url, {
  • 发起网络请求
    lib/registry.js:75
    response = await fetch(url, { signal: AbortSignal.timeout(timeoutMs) });
扫描于 2026/11/4(0 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

社区实装还没有人打卡 · 装过的第一个就是你
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

功能亮点

  • CI修复机器人
  • 跟进新版DSH发布

装在仓库里的 CI 修复机器人,让 DeepSeek Harness 插件跟上新版 DSH 发布

README

由 DeepSeek 最新模型翻译生成
DSH Plugin Compatibility Guardian 让 DeepSeek Harness 插件自己跟上 DSH 更新。 自动发现新版 → 隔离安装与真实启动 → 不兼容时用 DSH 本身修复 → 独立复验 → 交付可合并 PR。 English · 设计白皮书 · 真实验收 DeepSeek Harness 官方把当前阶段标为 developer preview,并明确提醒可能有破坏性变更。Guardian 只解决这一个问题:DSH 更新后,插件还能否安装、启动和工作?不能时能否自动修好? 正式安装:放进你的插件仓库 要求:目标插件仓库已有可运行的测试/构建命令,本机已登录 gh,工作树干净。
展开完整文档(README 剩余 1 节)
DSH Plugin Compatibility Guardian
让 DeepSeek Harness 插件自己跟上 DSH 更新。
自动发现新版 → 隔离安装与真实启动 → 不兼容时用 DSH 本身修复 → 独立复验 → 交付可合并 PR。

English · 设计白皮书 · 真实验收

DeepSeek Harness 官方把当前阶段标为 developer preview,并明确提醒可能有破坏性变更。Guardian 只解决这一个问题:DSH 更新后,插件还能否安装、启动和工作?不能时能否自动修好?

正式安装:放进你的插件仓库

要求:目标插件仓库已有可运行的测试/构建命令,本机已登录 gh,工作树干净。

npm exec --yes \
--package=github:LCYLYM/dsh-plugin-compat-guardian#637f97543993bb16999c83a1c4fa779131c4c15d \
-- dsh-plugin-compat-guardian onboard \
--guardian-ref LCYLYM/dsh-plugin-compat-guardian/.github/workflows/guardian.yml@637f97543993bb16999c83a1c4fa779131c4c15d

这条命令会打开 onboarding PR,不会直接改默认分支。你只需首次审核三件事:

1. .dsh-compat.yml 里的测试命令、额度和交付模式。
2. compatibility/dsh-smoke.yml 是否真的证明了你的插件能力。
3. workflow 是否固定到完整 40 位 Guardian commit SHA。

然后在仓库设置中完成两项:

安全地提示输入,不把 key 写进文件或 shell 历史 gh secret set DEEPSEEK_API_KEY

允许 GitHub Actions 创建维修 PR;默认权限仍保持 read
gh api --method PUT repos/{owner}/{repo}/actions/permissions/workflow \
-f default_workflow_permissions=read \
-F can_approve_pull_request_reviews=true

不想让 Actions 建 PR 也可以。Guardian 会推送已验证分支并停在 WAITING_FOR_GITHUB_APPROVAL,你手工开 PR 即可。

原仓库和 fork 测试仓库有什么不同?

| | 插件原仓库 | 只用来试 Guardian 的 fork |
| 目标 | 长期自动跟进 DSH latest | 证明一次真实 AI 维修闭环 |
| 触发 | 保留每 6 小时和手动检查 | 只保留 workflow_dispatch |
| Secret | 在原仓库设置 | fork 不会继承 Secret,必须在 fork 里单独设置 |
| 交付 | 默认产出可审核 PR | 测完合并测试 PR,然后关闭 fork 的 Actions 总开关并删 Secret |

如果插件对新 DSH 本来就兼容,Guardian 只跑确定性验证,不调 AI;这是正常的生产行为,不能拿来证明“AI 修过了”。要做真实维修演练,先建立旧 DSH 的 PASS 基线,再让新 DSH 触发可解释的兼容边界,最后必须看到非零模型 usage、代码 diff、独立 verifier 耗时和可合并 PR。

完整操作和本项目的四个公开 fork 案例见 fork 真实 AI 维修测试教程。

它实际做什么

flowchart LR
A[官方 GitHub Release / NPM 安装图变化] --> B[无 Key 机械验证]
B --> C{插件是否通过?}
C -- 是 --> D[更新 verified lock]
D --> E[PR / auto-merge / direct-push]
C -- 否 --> F{已有可信基线?}
F -- 否 --> G[ONBOARDING_BLOCKED不调用模型]
F -- 是 --> H[固定 repair DSHDeepSeek 有额度修复]
H --> I[原 smoke contract独立 verifier 复验]
I --> E
I -- 仍失败/额度到顶 --> J[FROZEN等待 resetBudget=N→Y]

无模型 verifier 会在临时目录中:

- 冻结当次 @deepseek-ai/dsh 精确版本、NPM integrity 和完整安装图。
- 按仓库原生 npm/pnpm/yarn 规则安装依赖并跑测试/构建。
- 用 npm pack 产出真实插件 tarball,安装到隔离 DSH_HOME。
- 检查 dump-config,真实启动 dsh web,执行插件专属 smoke,再卸载并确认无残留。
- 仅当“旧基线 PASS、新候选 FAIL”时才允许模型维修。

一眼能看懂的报告

Actions Summary、Issue 和 PR 默认使用中文,先给结论和下一步,再折叠展开机械证据:

🛡️ DSH 插件兼容性报告 ✅ 已通过

目标 DSH @deepseek-ai/dsh@0.1.1-rc.2 插件 dsh-whale-report@0.1.4 检查 22 项通过 / 0 项失败下一步 审核并合并 verified lock PR

报告只保存脱敏后的命令摘要、hash、状态、耗时和 usage。API Key、认证头、完整模型对话和本机私有路径不进报告。

交付模式

| 模式 | 会发生什么 | 默认 |
| pull-request | 生成可审核 PR | ✅ |
| auto-merge | 先建 PR,checks/分支规则通过后合并 | 关 |
| direct-push | 通过复验后直接推默认分支 | 关 |

auto-merge 和 direct-push 是真能力,但不默认开启。如果修复改了测试、测试命令、安装脚本、依赖 major 或新增/删除依赖,无论仓库选什么都强制回到人工 PR。

额度、低价时段与防死循环

默认的每个“仓库 + 目标 DSH 版本”维修活动:

- 最多 100,000,000 token、10 CNY 估算、60 分钟活跃时间、2 轮模型尝试。
- token 按仓库与目标 DSH 版本跨运行累计,配置不能超过 100,000,000;不是每轮重新获得 1 亿。时间、估算 CNY 与维修轮次仍独立限制,可在仓库配置中明确覆盖。
- 预算只剩 30% 时,默认给 repair DSH 发一次“尽快收敛”提醒,可关闭。
- 确定性测试立即跑;只有确实要调模型修代码时,才可选等待 DeepSeek 低价时段。
- 同一版本默认只自动维修一次。额度到顶后,只有提高限额,或把 .dsh-compat.lock.json 中 resetBudget 从 N 改成 Y 并提交,才再维修一次;该次 Y 会立即消费回 N。
- 缺 Key、401/403、错误 model/base URL/provider 会产生可读的 BLOCKED_CONFIG 状态 PR;修正前 schedule 不会每 6 小时再调模型。
- timeout/429/5xx/明确过载不直接放弃:DSH provider 在同一模型回合内每两分钟自动重试一次、最多再试两次,仍失败才持久化为 BLOCKED_EXTERNAL。
- 同目标存在 open 状态 PR 或维修 PR 时,后续 schedule 在调模型前就停下,不会重复维修;已合并后保留的分支不算阻塞。

CNY 是按 DSH 暴露的 usage 和仓库中的价格快照估算,不是 DeepSeek 账户账单级硬限额。绝对账户限额仍应在 provider 侧设置。

attempts_used 记的是 Guardian 维修轮次,不是底层 HTTP 请求数。一个 DSH 回合可能包含流式续请求、工具回合或 provider 内部的一次短重试。

默认与可配置项

- 候选 DSH:默认跟踪官方 deepseek-ai/deepseek-harness 的 dsh-v* GitHub Release,包含 prerelease;随后要求同版本 NPM 包存在并用它做真实安装。GitHub Release 已发布但 NPM 尚未发布时进入 WAITING_FOR_NPM_ARTIFACT,不调用模型、不建 PR。
- 兼容候选按 Release tag + commit SHA + NPM integrity 锁定;同版本重新打 tag 也会被识别为新快照。需要兼容旧行为时可将 watch.source 改为 npm。
- repair DSH:默认固定 0.1.1-rc.2,可改;每次 campaign 开始后锁定。
- provider/model:默认 deepseek-official/deepseek-v4-flash-vision-exp。已实测支持自定义 DeepSeek base_url、Key 值、Key 环境变量引用和 model ID;Guardian 会直接 patch DSH 原生 llm-deepseek adapter。repair.reasoning_effort 默认 high,支持原生适配器的 off/low/high/max,不支持 xhigh;该值进入 repair 和 model-smoke 的请求及去重指纹。自定义路由的单次输出上限低于 DSH 默认值时,用 repair.max_output_tokens 明确配置;这和整个 campaign 的 budget.max_tokens 是两个概念。
- GitHub Secret:默认只需建立 DEEPSEEK_API_KEY。.dsh-compat.yml 的 api_key_env 是 DSH 进程内的凭据引用,不是 GitHub Secret 的名字;仓库用别的 Secret 名时,只改薄 workflow 中 deepseek_api_key 的 Secret 映射。
- 其他 provider:只填一个 provider 字符串不会自动安装 adapter。V1 只对 deepseek-official 路由做自动配置;其他 provider 必须已在所选 DSH profile 中注册,否则会停在 MODEL_PROVIDER_NOT_REGISTERED。
- DeepSeek 官方搜索:repair DSH 可按需使用,不要求每轮搜,不另设搜索次数上限。
- monorepo:用 plugin.workspace 指向真实插件 package;仓库依赖安装和 gates 仍在 root 运行。
- 通知:GitHub Summary/Issue 内置;email、Telegram 和 webhook 是可选窄网关。

完整示例见 .dsh-compat.example.yml。

版本限定的升级依据

Guardian 0.1.1-dev.0 参考 oh-my-dsh 的升级指引,保留它的版本走廊、移除项和行为变化卡片,不复制整套规划框架,也不执行其中的脚本。

- 指导数据固定到可审查的 Git SHA,保留原 MIT 许可;运行时不下载浮动的指引。
- 卡片全文作为消融实验中的只读参考文件,提示词只给路径和覆盖缺口;自动注入不默认启用。扫描到的 touchpoint 只是导航线索,不会按关键词删掉其它必要迁移项;可选新能力不进入维修目标。
- 单纯 maxHost 边界的首轮仍只改一个字段,不加载升级上下文。复验发现具体 API 故障后,提供准确的 verifier 报告路径、去敏错误和精确目标来源;实验开关才额外提供卡片。
- 指导有断档时明确说明。参考文件不能替代精确目标源码,更不能替代原测试、真实安装、真实启动和独立 smoke。

本版本同时适配旧 RPC 与新版原生 Session stream;协议探测只读,认证拒绝不绕过。自定义模型会按本轮输入模态声明目录,避免 auto 被第一方模型列表拒绝。旧 0.1.1-rc.2 的隔离 runner 使用经四组启动对照验证的 HMR 兼容措施;不将它泛化到未测试版本。

设计和消融的验收记录见 2026-10 升级验证。

真实证据

| 样本 | 结果 | 当前证明的边界 |
| dsh-attachments-guardian-fixture | ✅ 真实自动修复 | 受控不兼容 → DSH 维修 → 独立复验 → PR,另有视觉 smoke/direct-push/auto-merge/NOOP 证据 |
| dsh-whale-report fork | 🧪 真实维修演练 | 旧版 PASS 基线、rc.2 repair DSH、独立复验与 PR |
| dsh-web-ui fork | 🧪 真实维修演练 | 大型 pnpm monorepo 中的 Skill Explorer package |
| dsh-ankh-guard fork | 🧪 真实维修演练 | 安装/组合/web 启动;不宣称 watchdog 行为已验收 |
| better-sidebar-office fork | 🧪 真实维修演练 | 额外先修复上游已撤包和 Windows 本地 link,再建可复现基线 |

完整运行 ID、PR、实际 token/估算 CNY 和尚未绑定的可选外部渠道,见 最终验收报告。

社区 fork 的详细结果以 最终验收报告 中列出的最新 run/PR 为准。旧 run 中只跑了机械兼容检查或 onboarding 阻断的,不写成 AI 维修成功。

边界和风险

- Guardian 是维修机器人,不是通用依赖升级、测试改写或代码整理机器人。
- 插件专属 smoke 的证明力决定兼容结论的上限。客户端插件如果只断言了 web shell,就只能证明安装/启动,不能宣称 UI 行为已验收。
- direct-push 能绕过人工 review;开启前应配合分支保护、CODEOWNERS 和仓库自带测试。
- Secret 只进入可信默认分支上的 repair job,以及 contract 明确启用的无 Git 写权模型 smoke job。fork PR 和普通 PR 代码不会拿到 Key。
- node_modules 和 npm/pnpm/Yarn 缓存是不可配置放宽的禁止路径;Guardian 在暂存前检查,并拒绝截断、摘要不一致或无法干净应用的补丁。
- 命令失败报告展示最多 500 字符的去敏 stderr 摘要;真实 dsh web 进程退出时保留最多 1000 字符的去敏可行动诊断,供人和第二轮维修定位。两者都保留错误代码、耗时和哈希,不保存完整模型对话、Secret 或本机路径。
- 本项目与 DeepSeek 官方无隶属关系。使用前请审核 workflow、固定 SHA 和仓库权限。

文档导航

- 方案与状态机
- 白皮书
- 完整需求与落地对照
- 原设计偏离/缺失/多做审计
- 最终验收报告
- fork 真实 AI 维修测试教程
- 历史证据
- 长期验收合同 · 当前状态

开发

npm ci
npm run check

当前本地套件:79/79 通过;另有真实 DSH rc.2 自定义 route/故障端点探针。项目采用 MIT License。
预览分享卡片长什么样 ↓LCYLYM/dsh-plugin-compat-guardian
分享 · DeepSeek Harness Hub
LCYLYM/dsh-plugin-compat-guardian

让 DeepSeek Harness 插件自己跟上 DSH 更新。

这个插件是你维护的吗?
作者本人可认领并核对本条目;认领通过后,详情页会显示「作者已认领」标记。
认领条目 →
回到顶部