dsh-git-push
DSH(DeepSeek Harness)git 自动提交推送插件。把「扫描仓库 → 审计 → 一键 commit + push → 自动维护 dsh-repo-index 源码索引 → 敏感字段文件自动 .gitignore」固化为 agent 工具与 HTTP API,执行零 token 消耗、确定性输出(相比每次让 AI 手敲 git 命令)。默认走 api.github.com(clone / push / 建仓 / 可见性 / 打 tag);token 无效(401)时 push 回退 ssh.github.com:443。禁止直连 github.com、codeload.github.com。
目录
架构设计
- 分层:
lib/core.js 纯函数核心(不依赖 ctx,可独立单测)+ lib/index.js 插件装配(工具注册 + HTTP API + 审计门禁接线 + repo-index 维护)
- 门禁链:
commitWithAudit = README 预览 → L0 静态审计(可选 L1 LLM)→ 拦截判断 → commitAndPush(npm 屏蔽 → 敏感字段扫描 .gitignore → add → commit → push → repo-index 更新)
- 推送通道(v1.18.3):默认 api.github.com Git Data API(blob → tree → commit → ref);无 token / 401 Bad credentials 时回退 ssh.github.com:443(插件配置目录
git-push/ 下 SSH 私钥)。禁止 git push github.com / HTTPS
- 可执行位 / 属主(v1.18.4 / v1.32.0):启动写
git config --global core.filemode false 与 safe.directory=*;每次 git 带 -c core.filemode=false -c safe.directory=*,CIFS 权限与属主噪声不进提交
- 审计体系:L0 静态(语法/JSON/YAML/敏感信息/凭据/大文件/debugger/文档对话类措辞/硬编码路径与局域网 IP)+ 代码质量维度(v1.39.0,依据
docs/code-quality-checklist.yaml:函数行数/静默catch/async同步阻塞/测试覆盖)+ 0-100 评分与 A-D 等级(quality 字段,v1.41.0 起如实标注评分口径)+ L1 LLM 深度审查(可选,diff 喂便宜模型);豁免类型 = 说明类(示例假凭据)+ 备份类(exemptRepos 白名单;硬编码规则不跟私有库豁免)+ json 注释行豁免(v1.41.0:.json 内 // 注释行豁免隐私入库类规则——secret/credential;措辞/对话/质量不豁免)
- 规则包化(v1.47.0):审计规则数据全部外置为 YAML 规则文件(
lib/audit-rules/audit-rules-{nodejs,frontend,comment}.yml,四份含 template 模板默认不加载;归属 DeepSeek + 用户自定义),代码只保留引擎逻辑(lib/rule-packs.js 装载/校验/编译)。顺序装载、后覆盖前:config.auditRuleOrder / auditRuleset(逗号分隔槽位)控制加载顺序,同 id / pattern 后加载覆盖先加载;severity 映射 error→blocker(拦截) / warning→warning(提醒) / info→pass。权重可调(v1.47.0 侧边栏):comment.yml 黑名单权重 ≥40 进门禁措辞 blocker,auditRuleWeights 配置写回覆盖(不影响 YAML 本体)。私密拦截(v1.48.0 强制槽位):audit-rules-private.yml 为强制加载槽位(不受 auditRuleOrder 影响,永远末尾合入优先级最高)——扫描 git ls-files 全量跟踪文件(不依赖 diff),命中私钥/token 类文件时按远端可见性分级:public → blocker 拦截(私密文件已可被任何人获取)、private/unknown → warning 提醒;code_audit / audit_full_scan 工具与 /api/git-push/audit?ruleset= 支持按调用传槽位顺序临时换装;审计结果带 ruleset 溯源。旧 JSON 规则包(eightfs.rules.json)已删除
- 用户门禁(v1.40.0 随插件内置):开发者特殊要求清单内置为
lib/user-requirements.json(归属 EIGHTfs),提交前逐条核对,未核对拦截(requirementsConfirmed 机制);可放 <插件配置目录>/requirements.json 外挂他人清单
- 设置双位 UI(v1.46.0 起 / v1.49.0 重构):①
settings.plugin.item 插件配置卡(折叠)— v1.49.0 起只保留 token / SSH key / 登录信息三块的填写与检测保存;②settings.section 侧边栏独立页(v1.46.0 新增入口,v1.49.0 重新设计)— 不复用折叠卡,平铺展示:顶部登录信息只读(不提供填写)+ 引导条「去插件配置填写 →」,下方高级设置(注入三开关 / 自定义忽略 / 规则引擎槽位排序+权重滑块)即时保存;两处共享同一 controller / store,状态一致
- 设置页凭据(v1.20.0 / v1.40.0):设置 → 插件 → 插件配置 →「Git 提交推送」填 token;写入插件配置目录
git-push/github-token(0600),secret 字段不进 settings.yaml 明文。点「检测可用」时公钥绑定先读 /user/keys,无权则 SSH 实测 ssh.github.com:443
文件目录结构及作用
| 路径 | 作用 |
|---|
lib/core.js | 纯函数核心门面(v1.42.0 拆分):re-export 下方功能模块的 runGit / commitAndPush / scanRepos / auditRepoPath / scanSensitiveFiles / ensureSensitiveIgnored / resolveGitToken / ensureRemoteRepo / pushViaApi / genReadme / rebuildHistory / credentialsDir / maskRemoteUrl / loadRequirements 等,导出面与拆分前一致 |
lib/git-core.js | git 基础执行(v1.42.0 拆分):runGit / gitRaw / 全局配置(filemode false / safe.directory=*) |
lib/github-api.js | GitHub API 访问(v1.42.0 拆分):token 解析 / pushViaApi / 可见性 / 账号检查 / SSH 密钥 |
lib/repo-scan.js | 仓库扫描(v1.42.0 拆分):scanRepos / readExtraReposFile / 变更统计 |
lib/ignore-scan.js | 敏感文件与 .gitignore 维护(v1.42.0 拆分):scanSensitiveFiles / ensureSensitiveIgnored |
lib/commit-push.js | 提交推送编排(v1.42.0 拆分):commitAndPush 步骤拆分(预检 / 忽略 / add+commit / push / remote heads) |
lib/token-credentials.js | 凭据持久化(v1.42.0 拆分):credentialsDir / token 与 SSH 公钥落盘 / requirements 清单 |
lib/workspace-context.js | 环境注入(v1.42.0 拆分):工作目录映射 / 工具安装路径 / tools-index 同步 |
lib/version-history.js | 重建历史(v1.42.0 拆分):rebuildHistory(fresh/squash-bugfixes/drop-versions)+ 身份兜底提交 |
lib/readme-gen.js | README 模板生成(v1.42.0 拆分):genReadme + 版本表构建 |
lib/remote-repo.js | 远端仓库管理(v1.42.0 拆分):ensureRemoteRepo 建仓 / cloneViaApi(api.github.com Git Data API) |
lib/plugin-paths.js | 插件根路径(v1.42.0 拆分):PLUGIN_ROOT |
lib/index.js | 插件装配调度器(v1.42.0 拆分):apply 只负责按序注册;各功能在 plugin-*.js |
lib/plugin-config.js | 插件配置(v1.42.0 拆分):Config schema + 设置命名空间 + 插件名 + textRender |
lib/plugin-setup.js | 插件初始化(v1.42.0 拆分):resolvePluginEnv(配置规范化/规则包装载/comment-wording 解析)+ 设置页注册 |
lib/plugin-context-inject.js | 上下文注入(v1.42.0 拆分):systemPrompt 三段(功能目录/README 检查/环境注入)+ agent/pre-step(skill/repo-index) |
lib/repo-index-sync.js | dsh-repo-index 自动维护(v1.42.0 拆分):推送成功后重建索引 JSON |
lib/plugin-audit.js | 审计服务(v1.42.0 拆分):auditRepoPath(可见性定拦截力度)/ fullScan 全仓扫描(v1.43.0)/ isUserRepoPath |
启动脚本
# 插件随 DSH 主实例自动装载(cordis.patch.yml insert),无需单独启动
curl -s http://127.0.0.1:3083/api/git-push/status # 验证加载
node --check lib/core.js && node --check lib/index.js # 改代码后语法自检
node test/test-core.mjs && node test/test-audit.mjs && node test/test-repo-index.mjs && node test/test-rules.mjs && node test/test-env-inject.mjs # 单测(含硬编码路径/IP;test-apply 需 DSH 运行时依赖)
独立 CLI(脱离 DSH 运行)
v1.44.0 起引擎层(core/audit/rule-packs/full-scan/quality/repo-index 纯函数模块)可脱离 DSH 直接使用:
node cli.mjs audit /path/to/repo # L0 静态审计(blocker 拦截退出码 2)
node cli.mjs full-scan /path/to/repo # 全仓 AI 对话残留注释扫描(只读表格报告)
node cli.mjs commit /path/to/repo -m "msg" # 审计门禁 → 提交(默认不 push;--push 推远端;--force 强推覆盖远端历史;--req-confirm 过门禁)
node cli.mjs scan /path/to/root # 扫描目录下 git 仓库与变更
node cli.mjs ruleset builtin # 规则包自检(校验+编译+规则计数;作者工具)
- 通用选项:
--json(原始 JSON)/ --ruleset <builtin|本地路径|http(s)://>(临时换包)/ --fail-on-warn(full-scan 有⚠时退出 3,CI 用)
- 退出码:0 成功 / 1 用法错误 / 2 拦截或失败 / 3 full-scan 警告
- 零第三方依赖(Node ≥18);L1 LLM 深度审查、设置页、HTTP API、推送许可是 DSH 接线层专属,CLI 不含
- 发布为 npm 包后可
npx git-sluice full-scan <repo>(bin 字段已配)
API 总览
| 接口 | 方法 | 说明 |
|---|
/api/git-push/status | GET | 插件状态(版本 + 配置 + 审计开关 + repoIndex + git 版本) |
/api/git-push/scan | GET | 扫描全部仓库状态 |
/api/git-push/audit?repo=<路径>&llm=true | GET | 审计指定仓库(llm=true 追加深度审查) |
/api/git-push/sensitive?repo=<路径> | GET | 手动扫描仓库含敏感字段的文件 |
/api/git-push/commit | POST | {repo, message, push?, dryRun?, audit?, llmAudit?} 审计通过后一键提交推送 |
/api/git-push/remote-create | POST/GET | 按项目文件夹创建远程仓库(私有/公开 + 设置 origin) |
/api/git-push/permit/status | GET | 推送许可状态(AI 回复 ✅ 是否自动 commit+push;默认关闭) |
/api/git-push/permit/config | POST | {pushOnComplete: true/false, pushScope?} 切换推送许可(默认关,绝不自动推) |
git_clone(agent 工具) | — | 远端 clone 只走 api.github.com Git Data API(git/trees + git/blobs,不下 tarball;/tmp 中转建仓,兼容 CIFS;自动探测默认分支) |
agent 工具:git_scan / git_commit_push(含 requirementsConfirmed 参数)/ code_audit / git_gen_readme / git_rebuild_history / git_remote_create / git_set_visibility / git_clone / push_permit_status / push_permit_config(前 8 个详见 dsh-git-push skill 手册)
配置键(cordis.patch.yml insert config):workspaceRoot / extraRepos / depth / githubOwner(v1.40.0:默认 GitHub owner,兜底 EIGHTfs)/ auditEnabled / blockOn / auditRuleset(v1.47.0:审计规则 YAML 槽位顺序——''=默认 nodejs,frontend,comment、可写逗号分隔槽位如 comment,nodejs;template 槽默认不加载,显式列出才加载)/ auditRuleOrder(v1.47.0:侧边栏可排序的槽位顺序数组,优先于 auditRuleset)/ auditRuleWeights(v1.47.0:侧边栏「调权重」写回——{blacklist:{pattern:weight}},权重≥40 进门禁 blocker)/ llmAudit / llmAuditProvider / llmAuditModel / maxDiffBytes / repoIndexEnabled / repoIndexTokenPath / repoIndexSyncTarget / repoIndexLocalOnly / exemptRepos / pushScope / commentWordingEnabled / commentWordingCustom / commentWordingRulesFile / commentWordingRulesUrl / envInjectionEnabled / envInjectionTools / injectFullSkill(v1.28.0:pre-step 注入 skill 全文,默认 false 只列目录清单;v1.40.0 起来源 = 插件 skills/ + 技能仓库 git-workflow)/ injectRepoIndexFull(v1.35.0:注入 dsh-repo-index.json 正文,默认 false 只注入文件名)/ customIgnorePatterns(v1.28.0:自定义忽略 pattern 逗号/换行分隔,提交时自动写 .gitignore)/ commitMessage(自动推送提交信息,默认 chore(ai): 任务完成自动提交)。注:功能说明书经 systemPrompt 只注入精简目录(v1.32.0);完整 skills/dsh-git-push-functions.md 按需加载。环境注入仍走系统提示词通道。
版本列表
| 版本 | 内容 |
|---|
| 1.60.2(当前) | .samples 目录豁免(与 v2 同步)+ force 强推透传 + npm test 修复:①**.samples 空文件目录豁免**:目录放 0 字节 .samples 空文件 → 该目录(含子目录)内容照常出审计/敏感扫描结果,但不构成提交推送拦截(auditRepo blocked 判定排除该目录 blocker、ensureSensitiveIgnored 不写 .gitignore 不解除跟踪),判定函数 isSampleExemptDir(lib/ignore-scan.js,resolve 防 ../ 逃逸);②force 强推:commitAndPush/commitPushDoPush 透传 force → pushViaApi(API 通道重建 commit 去旧 parent)与 pushViaSsh(git push --force)已支持的 force,CLI commit --force 暴露;③npm test 目录模式修复:node --test test/ 在 Node 24 不认目录参数(Cannot find module)→ 改 glob node --test "test/*.mjs";④test-audit/test-core 补 .samples 豁免断言;全量 36 测试全绿 |
| 1.60.1 | 移除提交历史查看器(viewer 组件):删除 lib/viewer.js / lib/viewer-locales.js / test/test-viewer.mjs + /git-push/viewer 页面 + /api/git-push/repos |
| 1.60.0 | 本项目重构提分(大文件/长函数拆分 18→0 个 blocker,自评 61→77 B 级)+ 豁免体系分维度(全拦截类型)+ 全量扫描 gitignore 感知:①17 个超长函数拆分(子代理串行 + 逐个验收):plugin-tools registerAgentTools 270→23(12 工具抽独立函数)、plugin-http registerHttpApi 246→56(12 handler 抽独立)、plugin-context-inject 131→6、plugin-push-permit 130→14(6 纯函数 + deps 传 Map/并发闸/env 引用)、plugin-setup 100→30、plugin-commit-flow 84→8、rule-packs 三处 90→23/60→10/84→20、viewer 68→62、index 61→39、audit 91→23/55→51、client GitPushRuleCards 84→67——>100 行 blocker 全清零(最大 97),行为零变化/导出面不变/全量 11 套件零失败;②评分公式修正(拆分后仍 61 的根因):func-lines 分级加权(warning 50-100 行 -0.5 / blocker >100 行 -2,此前每 1 个 -2 把 9 个 warning 级函数扣到可读性 0)+ docs/ 参考文件与 test/ 测试代码不计入质量扣分(测试刻意用同步 IO 非质量债)——lib/quality.js scoreQuality 可读性直接扣加权分不再乘 2,lib/audit.js attachQualityScore 分级统计;③gitignore 感知文件收集(用户指示「默认排除 git 忽略的文件」):lib/full-scan.js listTextFiles 调 git check-ignore --stdin 批量判定(尊重 .gitignore 全语法含 negation),按 repoPath 缓存 + 递归透传避免重复 spawn,非 git 目录自动跳过(无 .gitignore 全量收集不报错);④豁免体系分维度(用户指示「所有拦截类型都可以有」):lib/ignore-scan.js makeExemptors 通用工厂 + 6 类标记——dsh-skip-sensitive(secret/凭据/隐私,已有)/ dsh-skip-size(文件大小,只能文件头)/ dsh-skip-func-length(函数长度,文件头=全文件或函数行尾)/ dsh-skip-syntax(语法/JSON/YAML)/ dsh-skip-quality(质量评分)/ dsh-skip-residue(debugger/todo/console)/ dsh-skip-style(styleRules)——文件头注释=整文件豁免、对应位置注释=单点豁免;已接入 audit.js 全消费点(binary/syntax/residue/style/quality/funcLength),端到端实测 6 豁免场景全过 + 对照正确;⑤(可读性 0→5 / 可维护性 0→5.5 / 性能 0→10);全量回归 503/0(11 套件)+ test-audit 新增 6 豁免断言、test-quality 断言同步新评分语义;版本 1.60.0 + cli.mjs/test-cli 同步;看板 docs/WORKBOARD-2026-09-09-quality-split-and-audit-scope.md 实时记录(子代理可接手) |
注意事项
- 推送通道(v1.18.3):默认 api.github.com Git Data API(token 多源探测:同级仓
dsh-git-push-User/github-token → 项目 .git-push-token → workspaceRoot data/sensitive);无 token 或 401 时回退 ssh.github.com:443(dsh-git-push-User/id_ed25519)。禁止 github.com HTTPS
- 分支免疫(v1.12.2):不硬编码 main/master——自动读远端 default_branch,请求分支不存在且不同名时自动改用远端默认分支,防误建新分支
- clone(v1.17.0):git_clone 走 api.github.com Git Data API(git/trees + git/blobs,不跟随 tarball 302);/tmp 中转建仓后整拷回 dest(绕开 CIFS git init EPERM);dest 非空拒绝防覆盖;clone 后 origin 设置为
https://api.github.com/repos/o/r
- 禁止直连 github.com:REST/Git Data 的 hostname 必须是 api.github.com;token 失效时只允许 ssh.github.com:443,不打 github.com
- 远端领先:拒绝推送(防覆盖),需先 pull 同步
- CIFS 卷:每次 git 命令带
-c safe.directory=<cwd>(CIFS 只读卷 doubtful ownership);CIFS 下 git init/git remote add 写 config.lock 会 chmod EPERM——建库用 /tmp 中转复制 .git,origin 用 node 直写 config
- 可执行位噪声(v1.18.4):CIFS/trimafs 上 chmod 不持久,git 会把 100644↔100755 当成变更。插件启动时执行
git config --global core.filemode false;runGit / gitRaw 每次再带 -c core.filemode=false(HOME 只读写不了全局时仍生效)
- 敏感扫描豁免(v1.14.0):①私有库——GitHub 可见性=private 自动豁免(API 探测失败/无 origin 保守不豁免);②注释豁免——文件头前 3 行或行内注释带
dsh-skip-sensitive 即跳过(审计 secret/凭据文件/对话措辞 + 自动 gitignore 两处同认);③只认字符串字面量值(表达式/拼接/变量引用不误报)
- 测试环境门禁(v1.14.0 移除):原 checkTestEnvCommitGate(DSH_HOME 含 dsh-test-* 禁提交)已删除——commitAndPush/rebuildHistory 不再有测试环境拦截
- git_scan 自由配置(v1.15.0):①配置
extraReposFile 指向文本文件(每行一个仓库绝对路径,# 注释),运行时实时读取,改文件即时生效无需重启;②工具 git_scan 支持 root(覆盖扫描根)/ paths(逗号分隔临时追加仓库);③API /api/git-push/scan 支持同名查询参数
- 审计:L1 LLM 依赖 DSH llm 服务已配置,不可用自动跳过;docs-conversation 只查文档类文件新增行;说明类示例假凭据豁免;硬编码路径/IP(v1.31.0)代码 blocker、文档 warning,私有库也不跳过
- 同级仓 dsh-git-push-User(v1.18.0):不再放插件目录
User/(安装拷贝会清空)。恢复:git_clone { target: "EIGHTfs/dsh-git-push-User", dest: "<工作区>/dsh-git-push-User" }(与插件仓同一层级)。本机 github-token / SSH 私钥 git 忽略不入库
- API 推送限制:Git Data API 单仓库 blob 数/请求有 GitHub 限额,超大仓库(千级文件)逐 blob 上传较慢;复用远端已有 sha 已减少重复上传
开发计划 / 疑难杂症