发现能力缺口时自动锻造插件并热挂载生效
30.6/100
综合分
1
GitHub 星标
—
npm 周下载
—/5
用户评分
数据截至 2026/9/29 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
该插件未发布到 npm,按作者文档从 GitHub 源安装即可(静态检查只覆盖 npm 路径,不代表插件不可用)。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add csiroqa/self-iteration-forge该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)
状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:需留意
是什么
dsh 原生插件 · dev
装得上吗
作者未把包发布到 npm,只能用源码安装
插件本身没问题,是分发方式不同
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
更新放缓:最近一次提交在 34 天前
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查需源码安装仓库 package.json 标记 private,未发布到 npm,需从源码安装
展开查看检查明细 ↓
以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。
✗npm 包@dsh-external/self-iteration-forge(未发布到 npm,仅可源码安装)
✓Node 引擎要求 >=22 · 基线 Node 22.19 满足
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明
源码安装时若 pnpm 拦截 prepare 脚本,按其提示在 pnpm-workspace.yaml 的 allowBuilds 中放行后重跑。
验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/10/13 15:38:38
安全扫描自动 · 静态分析源码v2.7.0🔵 扫描:含敏感能力尚无人工评估展开查看扫描说明与证据 ↓
安全扫描自动 · 静态分析源码
v2.7.0静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。
读写/删除本地文件
查看扫描证据(共 135 处,展示前 85 条)
- 删除本地文件递归src/call-stats.spec.ts:40
await rm(home, { recursive: true, force: true }) - 读取本地文件src/call-stats.spec.ts:122
const raw: unknown = JSON.parse(await readFile(callStatsPath(), 'utf8')) - 读取本地文件src/call-stats.ts:93
text = await readFile(callStatsPath(), 'utf8') - 写入本地文件src/call-stats.ts:161
await mkdir(path.dirname(file), { recursive: true }) - 写入本地文件src/call-stats.ts:163
await writeFile(tmp, `${JSON.stringify(doc, null, 2)}\n`, 'utf8') - 写入本地文件src/call-stats.ts:164
await rename(tmp, file) - 删除本地文件src/call-stats.ts:266
await rm(callStatsPath(), { force: true }) - 写入本地文件src/call-stats.ts:275
await mkdir(path.dirname(file), { recursive: true }) - 写入本地文件src/call-stats.ts:276
await writeFile(tmp, `${JSON.stringify(doc, null, 2)}\n`, 'utf8') - 写入本地文件src/call-stats.ts:277
await rename(tmp, file) - 写入本地文件src/forge.integration.spec.ts:54
await mkdir(path.join(staging, 'src'), { recursive: true }) - 写入本地文件src/forge.integration.spec.ts:96
await writeFile(path.join(staging, 'package.json'), JSON.stringify({ - 写入本地文件src/forge.integration.spec.ts:115
await writeFile(path.join(staging, 'src', 'index.ts'), indexSource.join('\n')) - 写入本地文件src/forge.integration.spec.ts:116
await writeFile(path.join(staging, 'tsdown.config.ts'), [ - 写入本地文件src/forge.integration.spec.ts:131
await writeFile(path.join(staging, 'cordis.patch.yml'), [ - 写入本地文件src/forge.integration.spec.ts:137
await writeFile(path.join(staging, 'README.md'), `# demo-mini\n\n最小示例插件(第 ${variation} 版)。\n`) - 删除本地文件src/forge.integration.spec.ts:143
await rm(path.join(staging, rel), { force: true }) - 删除本地文件递归src/forge.integration.spec.ts:187
await rm(tempRoot, { recursive: true, force: true }) - 读取本地文件src/forge.integration.spec.ts:222
const pkg = JSON.parse(await readFile(path.join(target, 'package.json'), 'utf8')) as { - 读取本地文件src/forge.integration.spec.ts:229
await expect(stat(path.join(target, 'lib', 'index.js'))).resolves.toBeDefined() - 读取本地文件src/forge.integration.spec.ts:232
await expect(stat(path.join(target, '.git'))).resolves.toBeDefined() - 读取本地文件src/forge.integration.spec.ts:260
await expect(stat(path.join(target, 'legacy.txt'))).resolves.toBeDefined() - 读取本地文件src/forge.integration.spec.ts:272
await expect(stat(path.join(target, 'legacy.txt'))).rejects.toThrow() - 读取本地文件src/forge.integration.spec.ts:299
await expect(readFile(path.join(config.targetRoot, name, 'keep.txt'), 'utf8')) - 删除本地文件递归src/forge.tool.spec.ts:33
await rm(home, { recursive: true, force: true }) - 读取本地文件src/forge.ts:249
const entries = await readdir(dir, { withFileTypes: true }) - 读取本地文件src/forge.ts:328
const pkg = JSON.parse(await readFile(packageJsonPath, 'utf8')) as { - 读取本地文件src/forge.ts:363
const pkg = JSON.parse(await readFile(packageJsonPath, 'utf8')) as { - 读取本地文件src/forge.ts:396
entries = await readdir(stagingRoot, { withFileTypes: true }) - 读取本地文件src/forge.ts:407
const meta = await stat(full) - 删除本地文件递归src/forge.ts:409
await rm(full, { recursive: true, force: true }) - 删除本地文件递归src/forge.ts:481
await rm(staging, { recursive: true, force: true }) - 写入本地文件src/forge.ts:482
await mkdir(staging, { recursive: true }) - 删除本地文件递归src/forge.ts:595
await rm(staging, { recursive: true, force: true }) - 删除本地文件递归src/hotmount.spec.ts:23
await rm(tempRoot, { recursive: true, force: true }) - 写入本地文件src/hotmount.spec.ts:29
await mkdir(libDir, { recursive: true }) - 写入本地文件src/hotmount.spec.ts:51
await writeFile(path.join(libDir, 'index.js'), body, 'utf8') - 读取本地文件src/hotmount.ts:57
const meta = await stat(libPath) - 删除本地文件递归src/index.spec.ts:38
await rm(tempRoot, { recursive: true, force: true }) - 写入本地文件src/index.spec.ts:86
await mkdir(staging, { recursive: true }) - 写入本地文件src/index.spec.ts:88
await writeFile(pkgPath, JSON.stringify({ - 读取本地文件src/index.spec.ts:102
const rewritten = JSON.parse(await readFile(pkgPath, 'utf8')) as { - 写入本地文件src/index.spec.ts:115
await mkdir(staging, { recursive: true }) - 写入本地文件src/index.spec.ts:117
await writeFile(pkgPath, JSON.stringify({ dependencies: { 'some-local': 'link:../other-lib' } })) - 写入本地文件src/index.spec.ts:126
await mkdir(staging, { recursive: true }) - 写入本地文件src/index.spec.ts:130
await writeFile(pkgPath, JSON.stringify({ dependencies: { '@deepseek-ai/cordis': targetLink } })) - 读取本地文件src/index.spec.ts:133
const pkg = JSON.parse(await readFile(pkgPath, 'utf8')) as { dependencies: Record<string, string> } - 读取本地文件src/index.spec.ts:149
const pkg = JSON.parse(await readFile(pkgPath, 'utf8')) as { dependencies: Record<string, string> } - 读取本地文件src/index.spec.ts:160
const content = await readFile(path.join(dir, '.gitignore'), 'utf8') - 读取本地文件src/index.spec.ts:169
const first = await readFile(path.join(dir, '.gitignore'), 'utf8') - 读取本地文件src/index.spec.ts:171
const second = await readFile(path.join(dir, '.gitignore'), 'utf8') - 读取本地文件src/migrate.ts:24
entries = await readdir(dir, { withFileTypes: true }) - 写入本地文件src/migrate.ts:39
await mkdir(path.dirname(tgtFull), { recursive: true }) - 读取本地文件src/migrate.ts:56
const [{ size: aSize }, { size: bSize }] = await Promise.all([stat(a), stat(b)]) - 读取本地文件src/migrate.ts:58
const [aText, bText] = await Promise.all([readFile(a), readFile(b)]) - 读取本地文件src/migrate.ts:74
await access(target) - 写入本地文件src/migrate.ts:86
await mkdir(target, { recursive: true }) - 读取本地文件src/migrate.ts:104
const file = await readFile(packageJsonPath, 'utf8') - 写入本地文件src/migrate.ts:133
await writeFile(packageJsonPath, `${JSON.stringify(pkg, null, 2)}\n`, 'utf8') - 读取本地文件src/migrate.ts:154
lines = (await readFile(file, 'utf8')).split(/ ? /) - 写入本地文件src/migrate.ts:162
await writeFile(file, content, 'utf8') - 写入本地文件src/migrate.ts:194
await writeFile(ciPath, text.replace(pattern, replacement), 'utf8') - 删除本地文件递归src/migrate.ts:249
await rm(targetFull, { recursive: true, force: true }) - 删除本地文件src/migrate.ts:256
await rm(targetFull, { force: true }) - 写入本地文件src/profile.spec.ts:18
await mkdir(profilesDir, { recursive: true }) - 删除本地文件递归src/profile.spec.ts:22
await rm(tempRoot, { recursive: true, force: true }) - 写入本地文件src/profile.spec.ts:26
await mkdir(path.join(profilesDir, name), { recursive: true }) - 写入本地文件src/profile.spec.ts:27
await writeFile( - 写入本地文件src/profile.spec.ts:63
await mkdir(path.join(profilesDir, 'broken'), { recursive: true }) - 写入本地文件src/profile.spec.ts:64
await writeFile(path.join(profilesDir, 'broken', 'package.json'), 'not json', 'utf8') - 写入本地文件src/profile.spec.ts:65
await mkdir(path.join(profilesDir, 'empty'), { recursive: true }) - 读取本地文件src/profile.ts:24
entries = await readdir(profilesDir, { withFileTypes: true }) - 读取本地文件src/profile.ts:33
pkg = JSON.parse(await readFile(path.join(profilesDir, entry.name, 'package.json'), 'utf8')) as ProfilePackage - 读取本地文件src/registry.ts:61
text = await readFile(file, 'utf8') - 读取本地文件src/registry.ts:65
const legacyText = await readFile(legacy, 'utf8').catch(() => undefined) - 写入本地文件src/registry.ts:80
await mkdir(dir, { recursive: true }) - 写入本地文件src/registry.ts:81
await writeFile(tmp, `${JSON.stringify(registry, null, 2)}\n`, 'utf8') - 写入本地文件src/registry.ts:82
await rename(tmp, file) - 删除本地文件递归src/verify-load.spec.ts:26
await rm(tempRoot, { recursive: true, force: true }) - 写入本地文件src/verify-load.spec.ts:40
await mkdir(libDir, { recursive: true }) - 写入本地文件src/verify-load.spec.ts:50
await writeFile(path.join(libDir, 'index.js'), content, 'utf8') - 读取本地文件src/verify-load.spec.ts:202
const src = await readFile( - 读取本地文件src/verify-load.spec.ts:210
const local = (await readFile(path.join(REPO_ROOT, 'src', 'verify-load.ts'), 'utf8')) - 读取本地文件src/verify-load.spec.ts:217
const src = await readFile( - 读取本地文件src/verify-load.spec.ts:223
const local = await readFile(path.join(REPO_ROOT, 'src', 'verify-load.ts'), 'utf8')
扫描于 2026/11/1(0 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库
静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。
依赖的 DSH / Cordis 模块
@deepseek-ai/cordis@deepseek-ai/dsh-commands@deepseek-ai/dsh-llm@deepseek-ai/dsh-session@deepseek-ai/dsh-subagent@deepseek-ai/dsh-system-prompt@deepseek-ai/dsh-tools@deepseek-ai/dsh-util-values@deepseek-ai/schemastery给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
功能亮点
- 发现能力缺口
- 自动锻造插件
- 热挂载生效
README
由 DeepSeek 最新模型翻译生成self-iteration-forge
CI
DSH 的智能体自迭代锻造台:AI 在执行任务时发现能力缺口,调用 extend_self 让子代理把缺失的能力锻造成插件 —— 迁移为「项目根/dsh-plugins/」独立 git 仓库(功能完成即英文 Conventional Commit)→ 自动装入当前 profile → 热挂载当前会话。每个锻造出的插件,其工具调用次数汇入统一账本,由 /self-iteration stats 汇总。
借由一切皆插件理念的智能体自迭代探索,现已实现自举(?
更名记录:2026-09-27 前名为 dsh-plugin-forge,因社区已有同名项目(MYCF711/dsh-plugin-forge 等)易混淆而更名;GitHub 旧链接会重定向。
English: README.en.md
工具 extend_self
别名:同一实现的过渡期别名 add_capability 也可调用,优先用主名 extend_self。账本按实际调用的名字分记,/self-iteration stats 里看不到别名的用量就说明可以撤掉了。
展开完整文档(README 剩余 1 节)
self-iteration-forge
CI
DSH 的智能体自迭代锻造台:AI 在执行任务时发现能力缺口,调用 extend_self 让子代理把缺失的能力锻造成插件 —— 迁移为「项目根/dsh-plugins/」独立 git 仓库(功能完成即英文 Conventional Commit)→ 自动装入当前 profile → 热挂载当前会话。每个锻造出的插件,其工具调用次数汇入统一账本,由 /self-iteration stats 汇总。
借由一切皆插件理念的智能体自迭代探索,现已实现自举(?
更名记录:2026-09-27 前名为 dsh-plugin-forge,因社区已有同名项目(MYCF711/dsh-plugin-forge 等)易混淆而更名;GitHub 旧链接会重定向。
English: README.en.md
工具 extend_self
别名:同一实现的过渡期别名 add_capability 也可调用,优先用主名 extend_self。账本按实际调用的名字分记,/self-iteration stats 里看不到别名的用量就说明可以撤掉了。
| 参数 | 类型 | 默认 | 说明 |
| requirement | string | 必填 | 插件需求(中文优先,尽量具体) |
| name | string | 自动 | 仓库目录名(kebab-case,从需求派生) |
| targetRoot | string | 项目根/dsh-plugins | 迁移根目录(参数 > 配置 > 默认) |
| migrate | boolean | true | 迁移为独立仓库并提交 |
| update | boolean | false | 更新既有仓库(防误覆盖) |
| install | boolean | 缺省自动 | 装入 profile:缺省自动装入当前 profile;false 关闭;installProfile 可显式指定 |
| hot | boolean | true | 热挂载到当前运行时 |
输出 JSON:
| 字段 | 说明 |
| ok pluginName committed build files | 必填;build = passed / skipped / 失败原因 |
| migratedTo | 仓库绝对路径(正斜杠);migrate=false 时缺省 |
| commitSubject | 提交 subject;未提交时缺省 |
| childReport | 子代理 REPORT notes(截断 500 字符) |
| installed installDetail hotMounted hotDetail | profile 装入(installed=false 时 installDetail 为未装入原因)/ 热挂载结果;两者失败均不阻塞交付 |
| duplicated existingName | 子代理判定与既有插件重复:拒绝新建,返回既有仓库名 |
失败(子代理未完成 / 迁移后构建失败 / 加载冒烟未通过)throw,staging 保留。
命令 /self-iteration status 与 /self-iteration stats
/self-iteration status(等价于裸 /self-iteration)逐仓库输出,末段是该插件的工具调用摘要:
- () HEAD: ;工作区:干净|有未提交改动|目录不存在;最近提交:,累计 次;调用 次(成功 / 失败 ,共 个工具),最近
无记录时该段显示「尚无调用记录」;registry 为空时输出「self-iteration-forge 尚未创建任何插件仓库。」
/self-iteration stats [插件名] 输出调用明细表(插件 / 工具 / 调用 / 成功 / 失败 / 最近调用,按调用次数降序),/self-iteration stats reset [插件名] 清空账本(不带插件名则清空全部)。
工具调用次数账本
- 账本文件:$DSH_HOME/storages/plugin-call-stats.json(缺省 ~/.dsh/storages/),形状 {version: 1, plugins: {: {tools: {: {calls, ok, failed, lastCalledAt, lastOkAt?, lastFailedAt?, lastError?}}, firstSeenAt, updatedAt}}}
- 新插件自动带统计:子代理提示词强制要求新建 src/call-stats.ts 并内联 plugin-call-stats.template.ts 下发的标准模块,每个工具的 execute 用 withCallStats('', '', execute) 包裹;各插件是独立仓库,故内联同一份源码而非交叉依赖,src/call-stats.spec.ts 校验两侧不漂移
- self-iteration-forge 自身的 extend_self(及别名)也走同一套接口记账(插件名 self-iteration-forge)
- 旁路保证:只记插件名 / 工具名 / 成败与时间(不记参数与返回值),增量合并 + 原子写(tmp → rename),任何失败都被吞掉,绝不影响工具执行
- 命令型插件(无 defineTool、用户入口是 /xxx 命令):在命令 handler 里显式 recordCall('', '', ok ? 'ok' : 'failed', 原因);后台自动触发(会话钩子等)默认不记,否则次数会随会话数无条件增长
流程 staging → 子代理开发(typecheck/test/build)→ 重复检测 → 迁移 → 目标重建 → 加载冒烟 → git init/commit → 登记 → 装入 profile(缺省自动)→ 热挂载。
- staging:/,默认 工作区/.forge-staging/;子代理仅写此处
- 同名任务进程内互斥;stagingTtlDays > 0 时启动前清理过期目录
- 迁移:link/CI 中 deepseek-harness 路径按深度改写、拒绝 registry 版 @deepseek-ai/ 依赖、写入 .gitignore(排除 node_modules/.git/.pnpm-store/lib/dist)
- 更新模式额外 syncRemoveStale:删除目标中 staging 已不存在的源文件
- 提交:: [: ],header ≤ 72 字符,summary 超预算截断;type 非法回退 feat
- 登记:$DSH_HOME/self-iteration-forge.json,形状 {version: 1, repos: [{name, path, createdAt, lastCommitAt?, commitCount, summaryZh?}]},tmp+rename 原子写
- push 仅配置显式开启时执行(默认关,遵守 AGENTS.md)
防重复
引导节不注入插件清单(省上下文)。子代理开发前自检:读 registry 与 dsh-plugins/ 目录,需求重复则 REPORT duplicate_of → 宿主拒绝新建,返回 duplicated: true + existingName;迭代走 update=true。
配置(cordis.patch.yml)
| 键 | 默认 | 说明 |
| targetRoot | '' | 迁移根;空 = 工作区父目录/dsh-plugins |
| stagingRoot | '' | staging 根;空 = 工作区/.forge-staging |
| harnessRoot | '' | deepseek-harness 检出根;空 = 自动查找 |
| subagentProvider | spawn | 子代理 provider |
| maxChildDepth | 2 | 子代理委托深度上限(1–5) |
| childTimeoutMs | 2700000 | 子代理/构建超时(≥ 60000) |
| commitType | feat | Conventional Commit 类型 |
| push | false | 提交后 push |
| gitAuthorName | csiroqa | 提交作者名 |
| gitAuthorEmail | justinwangyj@163.com | 提交作者邮箱 |
| keepStaging | true | 保留 staging 供排查 |
| stagingTtlDays | 0 | staging 保留天数;0 = 不清理 |
| installProfile | '' | 装入的 profile 名;空 = 自动探测当前 profile |
| autoInstall | true | 成功后自动装入当前 profile(install: false 参数可关闭单次) |
质量门
staging 内 typecheck/test/build → 迁移后目标 pnpm install && pnpm build → main/types 存在 → 拒绝 registry 版 @deepseek-ai/ → 加载冒烟(真实 cordis Context 执行 apply,拦截 apply 期崩溃——真实事故:命令 input.hint 为空导致 DSH 启动即崩)→ 宿主工具名冲突拦截(机制确认:dsh-tools 跨 scope 同名注册不报错但模型侧遮蔽;加载冒烟与热挂载双重拦截)→ 提交前检查 diff。
安装
pnpm install && pnpm build
dsh plugin --profile web add link:D:\2-OGP\self-iteration-forge
重启 dsh web。前置:Node ≥ 22、pnpm、本地 deepseek-harness 检出(依赖 link: ../deepseek-harness)。
交付方式
1. 热挂载(默认):生成后挂载当前运行时,本会话即用
2. 装入 profile(缺省自动):探测当前 profile(installProfile 可显式指定),重启生效
3. repository 源(家目录层 plugin-console):$DSH_HOME/cordis.patch.yml 的 repository-plugins.repositories,面板行管理——添加=安装、更新=锁定远端最新 commit、删行=卸载、立即生效;行格式 github:owner/repo#ref(monorepo 子包加 &path:/packages/)。forge 产物是单包独立仓库,push 后可直接作源;update=true 迭代 push 后面板更新即拉新 commit
真实 LLM 测试(免重启 GUI)
node scripts/llm-e2e-host.mjs prompt ""
node scripts/llm-e2e-host.mjs run "feat: : "
prompt:生成真实子代理提示词;run:执行宿主侧全流程(迁移/link+CI 改写/构建/提交/登记);--update 走更新链路。
安全
- forge 启动子代理、联网 pnpm install、目标目录构建、执行 git commit——只传可信需求
- 提交前 diff 检查、.gitignore 排除构建产物与依赖、不自动 push/tag/release
- 子代理只写 staging(工作区内)
演示
agent 自发提出建插件需求的会话截图: demo-1:agent 自发提出「每次会话结束自动把对话要点存档为 Markdown」
demo-2:审查后 agent 自发提出固化流程的任务
demo-2预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
csiroqa/self-iteration-forge
发现能力缺口时自动锻造插件并热挂载生效
相关插件 · 开发 / 工程
隐私简历生成器reactive-resume/reactive-resume
Reactive Resume 已迁至 GitHub 上的…
★ 45,125已汉化MCP
71.7
AI 架构文档生成器sopaco/deepwiki-rs
🚀 Litho 已进化为 Terrain —— 给你的 AI 智能体一张会呼吸的代码库地图。
★ 3,157已汉化DSH
70.8
长时任务执行闭环AMAP-ML/LongHorizon-Harness
面向 Computer-Use Agent 的 Loop Engineering
★ 1,764已汉化DSH
70.5
AI 编程纪律方法包GanyuanRan/Aegis
让 AI 编程 agent 变得可信:少返工、更安全、说“完成”前先给证据。
★ 1,384已汉化DSH
69.6
多代理编排运行时Enderfga/claw-orchestrator
面向编程智能体的运行时。把 Claude Code、Codex、Antigravity、Grok…
★ 586已汉化MCP
69.4
记忆进化插件csyangwen/dsh-memory-evolve
dsh-memory-evolve 使用场景指南
★ 461已汉化DSH
67.9