
Security News
Deno Goes the Way of the Dinosaur
Cloudflare is acquiring Deno’s team, which will provide another year of bug fixes and security updates before ending support for the runtime.
dsh-git-push
Advanced tools
DSH(DeepSeek Harness)git 提交推送与代码审计插件——提交前自动审计门禁,提交推送全链路自动化。
界面:账号信息面板(GitHub ↔ NPM 账号卡滑动切换、离线快照与在线自检)· 审计面板(22 个规则包 + 按包命中数,上下调次序、单击启停)· 设置面板(凭据 / SSH 公钥 / 审计开关与 10 维度权重)。
公开仓库:EIGHTfs/dsh-git-push(2026-09-13 转 public)|全量测试 490 全绿(
npm test一条命令可复现) 界面模拟页:assets/preview.html(单文件自包含,双击即可打开;跑的是真实client.js+ 假数据,三选项卡全部可点)
插件装上并重启后,三种方式直接可用:
常见误解:没有改动 / 没有新提交时,提交推送工具不会报错(返回
ok:true,只是committed:false或pushed:false),而「本地领先远端」的已提交内容照样会被推上去 —— 放心用插件,不要退回手敲 git。
① AI 直接用(DSH 会话里——不用记命令)
git_scan / code_audit / git_commit_push / git_account_check 等② 独立 CLI(git-sluice——脱离 DSH 也能跑)
git-sluice account-check —— 先校验 GitHub 凭据(第一步)git-sluice scan <目录> —— 看有哪些 git 仓库git-sluice audit <仓库> --full —— 全量审计(--json 拿明细)git-sluice commit <仓库> -m "msg" —— 提交推送(自动过审计门禁)git-sluice help③ 侧边栏面板
折叠说明:本文档的长章节(代码审计 / 系统提示词注入 / 独立 CLI / 安装与要求)默认收起, 点章节内的「展开」即可查看全文;标题本身保留,目录锚点照常可用。
长文档不直接内嵌 README,各自存独立 md(README 仅链接引用),由 doc- 前缀脚本自动维护:
| 文档 | 位置 | 维护脚本 | 说明 |
|---|---|---|---|
| 版本列表 | docs/CHANGELOG.md | scripts/doc-version.mjs | git log 聚合版本表(gen/apply/check) |
| 函数列表 | docs/FUNCTIONS.md | scripts/doc-func.mjs | 扫描 lib/scripts/test 函数表(gen/apply/check) |
| 文件目录树 | README「目录结构」节 | scripts/doc-tree.mjs | 目录树(原 tree-doc,2026-09-29 改名统一 doc- 前缀) |
每个脚本命令统一:gen(打印)/ apply(写宿主 md,自动探测带标记块的 md)/ check(查漂移)。宿主 md 带标记块(dshgp-version / dshgp-functions / dshgp-tree),审计按标记块探测并纳入检查。
讲「这个功能是什么、怎么用、边界在哪」,与上表的生成物分开维护:
| 文档 | 讲什么 |
|---|---|
| docs/SPEC.md | 当前有效规格唯一入口:身份 / 17 个工具 / 35 条 HTTP 接口 / 20 个设置键 / 4 个数据文件 / 审计规则体系 / 文档产物 / 版本纪律 / 测试基线 |
| docs/功能-审计规则体系.md | 22 个规则槽位 / 165 条规则的组织方式、作用域字段、三层结构、运行入口、结果怎么读、怎么豁免 |
| docs/功能-历史提交审计.md | 逐提交回放审计:解决什么、怎么跑、与普通审计的差异与成本 |
| docs/功能-文档与结构追踪.md | tree-doc / doc-func / doc-version 三份自动生成文档怎么更新、漂移怎么办 |
| docs/功能-仓库索引与账号状态.md | dsh-repo-index.json 与 account-status.json 的写入时机、读取入口、统一收口约定 |
| docs/DETAILS-EXEMPT-AND-RULES.md | 豁免注释与规则 yml 的写法全录(参考手册) |
插件围绕 DSH 日常开发的高频动作,分两大块——先讲提交推送(GitHub + npm),再讲代码审计。 下面每章都可折叠:长章节默认收起,点章节内的「展开」即可看全文。
| 功能块 | 做什么 | 入口 |
|---|---|---|
| GitHub 提交推送 | token / SSH 密钥管理、提交、推送、clone、建仓、可见性切换、force 强推、版本历史、提交身份自动用登录账号(未配身份的仓库自动写入局部配置)、推送前自动判定正确的 remote | git_commit_push 工具 / CLI / 侧边栏 |
| npm 发包与安装 | npm_publish 发包(默认 dry-run,真发需二次确认)、账号名下包列表(与仓库列表同款行)、四段式安装(目录选择器 / 全局安装 → 进度 → 回执)、npm 账号离线快照 + 在线校验 | npm_publish 工具 / /api/git-push/npm-* / 侧边栏 NPM 标签 |
| 任务完成自动推送 | 监听 AI 回合结束→检测回复含「✅任务完成」→自动 commit+push(复用审计门禁,不裸提交) | 侧边栏开关 autoPushEnabled(默认关)+ 自定义触发文本 |
| 功能块 | 做什么 | 入口 |
|---|---|---|
| 提交前审计门禁 | 提交前自动审计,blocker 拦截;22 个规则槽位 165 条规则、10 维度质量评分、豁免机制、链接检查、三层审计管线(L1 正则初筛 / L2 AST 数据流 / L3 运行时检测) | code_audit 工具 / CLI / 侧边栏 / 输入框 /git-audit |
| 审计结果 API | /api/git-push/audit——请求时自定义聚合审计结果:按规则类型 / 文件名 / 严重级 / 规则包分组,severity 白名单过滤,top 截断,withFindings 附明细 | HTTP GET/POST /api/git-push/audit |
Git 全链路自动化,token / SSH 凭据管理 + 提交推送,无需手动敲 git 命令。
ghp_ / github_pat_ 开头),保存即写入插件配置目录 credentialsDir()/github-token(0600 权限),不落 settings.yaml 明文credentialsDir()/*.pub(按类型 id_rsa.pub / id_ed25519.pub);一键生成密钥对(邮箱 → ssh-keygen 4096 位,公钥自动填入并复制剪贴板,私钥只落本机)GET /api/git-push/account-check 在线校验(token 调 api.github.com + SSH 指纹 + 绑定关系),侧边栏账号面板实时显示登录态| 能力 | 说明 |
|---|---|
git_commit_push | 一键提交+推送(审计门禁默认开启;敏感文件自动 .gitignore;--push/--no-push/--dry-run/--force/--req-confirm/--json;返回带 identity=本次提交身份与来源) |
git_identity_rewrite | 提交身份历史改写(工具 git_identity_rewrite / CLI git-sluice identity-rewrite):非规范身份(工具/AI 产生的 agent@dsh.local 等 + 账号 noreply 旧变体,可用 extraEmails 追加)统一成账号规范身份。默认 dry-run;--write 才改写(先建备份引用 refs/backup/identity-rewrite/<日期>/<分支>,自检「提交数/工作树/身份全规范」通过),--push 再用 --force-with-lease 强推;已跟踪文件有改动则拒改;只处理 origin 属于登录账号的仓库 |
| 零改动也安全 | 没有改动 / 没有新提交时调用不会报错:返回 ok:true + committed:false(job 状态 completed,文案写明「无变更:工作区无改动,无需提交(正常)」);远端已最新 ⇒ ok:true + pushed:false;本地领先远端的已提交内容照样会推上去。零改动调用不产生提交 ⇒ 不涉及 README 核对与 requirementsConfirmed 门禁 |
| remote 自动判定 | 推送前自动选「正确的 GitHub remote」:归属(owner/repo 与登录账号一致)+ 本机可用形态(优先 ssh://git@ssh.github.com:443/…)+ 名字优先级(origin > github-ssh > 其它)。形态不推荐自动 remote set-url;没有可用 remote 时新建;归属不符的 origin 绝不覆盖(改走 github-ssh);dryRun 只报告不写盘;回执带 remote / remoteAction / remoteReasons |
| 推送通道 | ssh(默认)= 只走 SSH 私钥 / token= 先走 Git Data API(用 token 推)失败回落 SSH / auto= 先 ssh 失败回落 token;远端分叉时不静默回落,如实报错 |
| force 强推 | API 通道重建 commit 去旧 parent / SSH 通道 git push --force |
| clone / 建仓 | cloneViaApi(trees+blobs 写文件转 git 仓)/ ensureRemoteRepo(建仓+设 origin) |
| 可见性 | setVisibility PATCH 切换 public/private |
| 网络硬闸 | 只允许 api.github.com(githubFetch 拒绝非该域名,不跟随 302) |
| 能力 | 说明 |
|---|---|
npm_publish | npm 发包(后台 job,返回 jobId):默认 dryRun=只体检 + npm publish --dry-run(不写 registry);真发需同时 confirm:true 且 dryRun:false;体检项:private:true、同名版本占用、npm pack 真实清单 |
| 安装(四段交互) | 列表行「安装」→ 弹目录选择器或选全局安装 → 轮询 /npm-install-progress 显示进度 → 回执与日志。默认 --ignore-scripts、必须 confirm:true、日志落凭据目录 0600 |
| 账号 | /npm-account(离线快照,秒回)+ /npm-check(在线 npm whoami 写快照);与 GitHub 账号同款「离线 + 在线」链路;账号名下包经 /npm-owned 列出(与 GitHub 仓库列表同款行) |
提交必须带身份;仓库没配时 git 会直接以 Author identity unknown 拒提交。插件按下列优先级决定身份,
并在未配身份时把账号身份写进该仓库的局部配置(git config --local;只改该仓库 .git/config,不入库、不动全局):
user.name + user.email → 原样尊重(不覆盖项目/用户自己的选择)name = 登录名,
email = <账号数字 id>+<登录名>@users.noreply.github.com(GitHub 官方 noreply 形式:
不暴露真实邮箱、提交能关联到账号;拿不到数字 id 时退化为 <登录名>@users.noreply.github.com)DSH Agent <agent@dsh.local>,
且不写进仓库配置(避免把兜底身份固化;此时提交由命令行 -c 临时带上,仍能提交)身份同时主动告知 AI,不用它自己猜:git_commit_push 返回 identity{name,email,source,written};
GET /api/git-push/status 暴露 commitIdentity;插件注入给 AI 的提示词里带一行「本机 git 提交身份:…」。
为什么加这一条:实测 AI 经常不知道「该用什么身份」,只能自己编 —— 本机曾同时存在
DSH Agent <agent@dsh.local>、eightfs@local、v2-clone@local、小写 noreply 等多种身份 (如某仓库 226 个提交里 21 个是 DSH Agent)。插件现在自己解析 + 落盘 + 告知,AI 只需按提示走。
提交时顺带提醒「以前」:每次提交的返回里带 legacyIdentity{count,emails,hint} —— 该仓库历史上还有多少条
非规范身份提交(如 agent@dsh.local)。只提醒、不改历史:历史要不要统一由用户决定;需要时用
git_identity_rewrite(工具)/ git-sluice identity-rewrite(CLI)先 dry-run 预览会改哪些分支与提交。
提交推送前自动跑代码审计(见下节):有 blocker 拦截提交(退出码 2),warning 只提示不拦截。审计通过才执行 commit + push。
监听 AI 会话回合结束(turn/end),提取最后一条回复,检测是否含完成标记——默认「✅任务完成」(侧边栏可自定义触发文本/正则,如 ✅(任务完成|已解答))——含则触发自动 commit + push交付物(autoPushEnabled 开关,默认关)。
commitWithAudit(L0 审计 blocker 拦截 / requirements 核对 / pushGate 放行),不裸提交绕过门禁;用户开启开关即一次性授权该自动化通道session(默认,仅会话 cwd 所在仓库)/ all(workspace 全部有变更仓库);范围、开关、触发文本经 config.json 持久化❌ / ⚠️ 未完成)不触发;无完成标记不触发提交前自动审计 + 独立全量扫描,规则可扩展,质量可评分。
auditChanged:变动范围(git diff)——提交前默认auditFull:全量扫描(非 git 目录可查)code_audit 工具 / git-sluice audit CLI:强度、规则包、权重全覆盖全量/变更扫描的目录跳过分三层(lib/skip-dirs.js 统一):
node_modules、.git)——机器依赖/内部元数据,绝对跳过,不受 gitignore 影响;exclude_dirs 并集,如 folder 规则的 dist/build/vendor/.dsh/.trash 等)——候选跳过,但若 gitignore 用 ! 白名单恢复了该目录(如 server/project/* + !server/project/blueprint/、/build/* + !/build/keep/),则保留进入(黑名单不压过白名单);git check-ignore)——被忽略目录整棵跳过;被 ! 恢复的目录照常进入。.auditignore 审计豁免文件(2026-09-16,2026-09-18 补非 git 兜底):仓库根放一个 .auditignore,用 gitignore 语法声明「不审计但可入库」的文件/目录:
# .auditignore 示例:以下内容照常 git 跟踪/提交,但审计扫描跳过
generated/ # 整棵目录豁免审计
src/vendor.js # 单文件豁免审计
*.lock # 匹配 yarn.lock 等 .lock 结尾文件
*.sh # 按文件类型豁免:所有层级的 .sh(gitignore 语义:无 / 的模式匹配任意深度)
generated/)在遍历时整棵剪枝;文件级规则(src/vendor.js、*.lock、*.sh)收集后判定剔除*.sh / *.png / *.min.js 均可,语义与 gitignore 一致——*.sh 匹配任意层级的 .sh(不是只根目录);只要根目录用 /*.sh。实测 *.sh 能命中 deep/nested/dir/run.sh! 前缀恢复审计,且后面的规则覆盖前面的(*.sh + !keep.sh = 只豁免 keep.sh 之外的 .sh)git check-ignore -c core.excludesFile,语义与 git 100% 一致git init 的工程同样生效——改用纯 JS 匹配器 lib/audit/gitignore-match.js(零依赖,语义逐条与真 git 对拍,见 test/test-gitignore-match.mjs)。此前这类目录下 .auditignore 形同不存在,同一个规则在 git init 前后行为相反.gitignore 叠加生效(各自独立、互不覆盖):.gitignore 管「不入库」,.auditignore 管「不入审计」.auditignore 只作用于审计扫描,不写进任何 git 配置,git add 照常跟踪git-sluice audit / 插件 code_audit 共用同一 collector,同一份 .auditignore 双端生效exclude_dirs 黑名单的区别:yml 黑名单是全局规则(所有仓库都跳);.auditignore 是仓库级(仅本仓库豁免,且仍可入库)新增跳过目录一律改 yml(exclude_dirs),不改代码。要调整各层行为见 lib/skip-dirs.js 顶部注释。
规则槽位由目录文件驱动:目录里每个 audit-rules-<名>.yml 即一个槽位,放文件即生效、删文件即移除,无需改代码。内置 22 个槽位:
| 槽位 | 规则数 | 检查内容 |
|---|---|---|
| nodejs | 37 | 凭据硬编码 / 路径穿越 / 魔数 / 依赖 / 异步等 |
| java | 7 | Java/Kotlin 专属:短名 / 魔数 / 嵌套 / 方法长度 / 文件长度 / 注释密度 / 圈复杂度(exts: [java, kt],2.1.0 新增) |
| python | 7 | Python 专属:短名 / 魔数 / 嵌套 / 函数长度 / 文件长度 / 注释密度 / 圈复杂度(exts: [py]) |
| go / rust / swift / cpp / php | 各 0(占位) | 语言专用规则占位槽位——放 yml 即生效,规则待补(AST 语言路由已预留,2.1.0) |
| frontend | 19 | 前端安全 / a11y / 依赖 |
| npm | 12 | 依赖声明 / npmrc 凭据 / 测试入口 / 包版本语义(npm/version-format-triple 只查 package.json、npm/version-commit-mismatch) |
| 0 | 已撤销:原 5 条全是自家提交/发布纪律(「一次提交=一个小版本」等),不该固化成对任何仓库生效的审计规则——纪律留在 skill(versioning-rule / git-commit-discipline);其中 2 条 npm 通用约定迁入 npm 槽位 | |
| dsh | 7 | DSH 插件契约 / 注入通道(仅 dsh- 前缀插件项目加载——非 dsh 项目 require node 内置不误报,2.1.2) |
| comment | 6 | 注释措辞 / 对话残留 |
| folder | 6 | 目录总数 / 单目录文件数 / 解包特征 / .gitignore / cd 到可能不存在的目录 / 写文件到 .gitignore 忽略目录 |
| i18n | 3 | 硬编码文案 / 插值 / 语言包 |
| performance | 2 | memory-bomb / busy-wait |
| docs / robustness / structure / template / private | 各 0-4 | 链接检查 / 写前 mkdir / 循环依赖 / 规则模板 / 私密文件拦截 |
加规则 = 放文件;加字段类型(新 kind)才需加函数(compilers.js 注册制:registerCompiler(kind, detect, compile),加字段=加函数+注册一行,compileRule 主体永不修改)。
| 字段 | 语义 | 典型用途 |
|---|---|---|
exts | 扩展名白名单(如 ["json"]) | 只对某类文件跑 |
include_paths | 路径白名单:不含 / 按文件名匹配(任意层级),含 / 按路径相等 / 前缀 / 后缀匹配 | 只对 package.json 跑(include_paths: ["package.json"]) |
exclude_paths | 路径黑名单(前缀匹配) | 排除 server/、test/ 等目录 |
file_patterns | 文件内容初筛正则(不是路径!L1 只求召回) | 只在正文含某特征时才做重检查 |
为什么要有 include_paths:exts(指定后缀)本来就支持,但它只能收窄到扩展名级——.json 这个粒度太粗:同一个 .json 既可能是 npm 的 package.json,也可能是 Live2D 的 model.json、Unity 的 .asset 清单。npm/version-format-triple(package.json 的 version 必须 SemVer 三段)原先是 exts: ["json"],于是把规则套到了所有 json——第三方资源仓库(实测 0 个 package.json)被报 1435 条 error。补上 include_paths: ["package.json"](文件名级作用域)后规则只对真正的 package.json 生效。
规则设计原则:自家提交/发布纪律不要固化成审计规则——审计规则对任何仓库生效,而自家纪律(「一次提交=一个小版本」「README 必须有版本记录」等)只适用于本机自研项目,写进规则必然在第三方仓库上大面积误报。这类约定放 skill,规则只保留生态通用的检查(如 npm 的 SemVer 格式)。
由
scripts/doc-tree.mjs维护:gen生成 /check查漂移 /apply覆盖本节 /sync索引自动同步(2026-09-29 自 tree-doc.mjs 改名,统一 doc- 前缀)。 注释来源tree-doc.json(路径 → 一句话介绍):键集合自动同步(sync/gen --write新增文件自动补键、删除文件自动删键),描述由 AI/人补(新键标「(待注释)」)。
dsh-git-push/
├── lib/ — 核心实现(10 总入口 + 审计引擎 + git 执行层 + 规则编译层)
│ ├── ARCHITECTURE.md — 架构说明文档
│ ├── BUGFIX-NOTES-2026-09-14.md — Bug 修复说明(diff 审计提速 / 凭据文件拦截三层根因)
│ ├── audit-defaults.js — (待注释)
│ ├── commit-push.js — 审计提交总入口(commitWithAudit + runAudit 同步审计)
│ ├── fsx.js — 文件系统适配层(CIFS/SMB 兼容:copyFile 读写回退、chmod 尽力而为、元数据能力探测)
│ ├── index.js — 插件入口(DSH 接线,再导出全部能力)
│ ├── skip-dirs.js — 跳过目录统一判定(硬编码基线 + yml exclude_dirs 并集 + gitignore 白名单恢复)
│ ├── tool-probes.json — 工具探测清单模板(工具为 key、值为空;运行时实测生成运行目录 tools.json)
│ ├── user-requirements.json — 开发者特殊要求清单(提交推送前逐条核对)
│ ├── app/ — 插件入口层(apply/HTTP 处理/工具调用分发/注入文本/默认扫描根)
│ │ ├── apply.js — 插件装载入口(注册 schema/工具/HTTP/注入钩子)
│ │ ├── audit-api.js — 审计结果 API 聚合层(/api/git-push/audit:按规则/文件/严重级/规则包分组 + severity 过滤 + top 截断)
│ │ ├── command-registry.js — 工具命令注册表(方案 B——CLI/宿主工具/帮助同源,免维护)
│ │ ├── constants.js — 插件名与设置命名空间常量
│ │ ├── host-doc-checks.js — (待注释)
│ │ ├── http-handlers.js — HTTP 路由分发(薄 router:前置校验 + switch 各端点调 handlers/ 模块)
│ │ ├── index.js — 插件入口再导出(宿主 main 指向)
│ │ ├── inject-text.js — 注入文本(工具用法提示 FUNCTION_USAGE_HINT)
│ │ ├── scan-root.js — 默认扫描根解析(配置优先→DSH 家根自动识别)
│ │ ├── schema.js — 配置 schema(宿主导出缺失时兜底)
│ │ ├── settings-bridge.js — 设置读写桥(host scope 共享;绕开 client isLoopback=memory 落盘陷阱)
│ │ ├── slash-commands.js — 用户输入框斜杠命令(目前只注册 /git-audit)
│ │ ├── slot-stats.js — 规则槽位命中统计(模块级状态)
│ │ ├── tool-call.js — 工具调用分发(git_scan/commit_push/audit/status 等全部工具)
│ │ ├── tools.js — 工具定义清单(名称/描述/参数 schema)
│ │ └── …(10 个更深文件)
│ ├── ast/ — AST 实现层(token 级判定:括号/控制流/数据流/凭据/魔数/命名/规模/分词)
│ │ ├── brace.js — 括号配对与区间包含工具
│ │ ├── callgraph.js — 调用链追踪(单文件调用图 + isInRequestPath,io-risk 请求路径判定升级)
│ │ ├── code-lines.js — 代码行判定(真代码 vs 注释/字符串)+ 字符串字面量提取
│ │ ├── consts.js — (待注释)
│ │ ├── control-flow.js — 控制流检查(同步 fs/空 catch/圈复杂度/嵌套深度)
│ │ ├── credential.js — 凭据标识符判定(硬编码/引用/类型检查)
│ │ ├── dataflow.js — 数据流检查(清空后访问,三层审计 L2)
│ │ ├── dup-code.js — (待注释)
│ │ ├── fs-hotspots.js — (待注释)
│ │ ├── index.js — AST 层统一出口
│ │ ├── io-risk-const.js — IO 风险分级·常量与档位工具:fs 调用名集/操作类别/风险标签/搜索窗口与阈值 + raise 升档
│ │ ├── io-risk-fn.js — IO 风险分级·函数边界识别与 token 配对:认普通/箭头/方法简写/类方法,圆括号花括号方括号前后向配对
│ │ ├── io-risk-loop.js — IO 风险分级·循环判定:循环内/迭代器表达式(只执行一次)/小字面量数组降级/collectRanges 范围收集
│ │ ├── io-risk.js — IO 风险分级(四级)判定与评分:scanIoRiskAst 判定上下文/类别 → summarizeIoRisk 统计 → rankIoFixList 优先级清单;并再导出下列三个从属模块的公共符号
│ │ ├── lang.js — 语言路由(2026-10-06):detectLang 内容启发式检测 + javaKtFuncRanges(Java/Kotlin 方法签名+括号配对函数范围)+ LANG_FUNC_RANGES 主流语言占位
│ │ ├── line-count.js — (待注释)
│ │ ├── magic-number.js — 硬编码魔数识别(豁免版本号/日期/状态码)
│ │ ├── naming.js — 命名检查(标识符长度/函数名过短/受控小文件读取)
│ │ ├── perf.js — (待注释)
│ │ ├── scope.js — 变量作用域分类器(module/function/loop 行号区间 + 模块常量赋值判定)
│ │ ├── shell.js — shell 精筛(cd 动态路径/写操作命中 .gitignore)
│ │ ├── size.js — 规模检查(函数长度/文件长度/重复字符串)
│ │ ├── symbol-index.js — (待注释)
│ │ ├── tokenizer.js — 分词器(token 流 + LRU 缓存)
│ │ ├── treesitter.js — (待注释)
│ ├── audit/ — 审计编排层(文件收集/逐文件检查/槽位聚合/审计出口)
│ │ ├── analysis-coverage.js — (待注释)
│ │ ├── audit-file.js — 单文件审计执行(跑检查+豁免)
│ │ ├── checks.js — 检查器入口(纯引用表)
│ │ ├── client-entry.js — (待注释)
│ │ ├── collector.js — 文件收集(gitignore 感知)
│ │ ├── ext-runner.js — 审计扩展运行器(audit-ext 统一入口动态加载/契约执行/失败降级)
│ │ ├── file-context.js — 文件上下文豁免(外部调用超时/mkdir 同函数/版本路径)
│ │ ├── finding.js — 统一问题对象构造器(makeFinding)
│ │ ├── gitignore-match.js — gitignore 语法匹配器(非 git 目录 .auditignore 兜底,语义与 git 对拍)
│ │ ├── glob.js — glob→RegExp 转换(**/*/? 子集)
│ │ ├── history-report.js — (待注释)
│ │ ├── history.js — (待注释)
│ │ ├── ignore-blind.js — 审计静默失明检测(本地 git 排除配置把整仓判成忽略时告警)
│ │ ├── index.js — 审计层统一出口(auditFull/auditChanged)
│ │ ├── orchestrate.js — 审计编排(收集→检查→汇总)
│ │ ├── public.js — (待注释)
│ │ ├── repo-level.js — 仓库级语义规则
│ │ ├── report-yaml.js — (待注释)
│ │ ├── slot.js — 按规则包聚合审计命中(拦截/警告/通过)
│ ├── audit-rules/ — 规则包 yml(nodejs/npm/frontend/comment/dsh/private/structure 等动态槽位)
│ │ ├── audit-rules-comment.yml — 注释类规则(黑名单措辞/对话残留)(规则包 comment)
│ │ ├── audit-rules-cpp.yml — C/C++ 规则包(占位:规则待补,槽位就绪)(规则包 cpp)
│ │ ├── audit-rules-docs.yml — 文档类规则(README/文档措辞)(规则包 docs)
│ │ ├── audit-rules-dsh.yml — DSH 生态规则(宿主/插件约定)(规则包 dsh)
│ │ ├── audit-rules-filehealth.yml — 文件健康度规则(三维分级)(规则包 filehealth)
│ │ ├── audit-rules-folder.yml — 目录级规则(目录数/单目录文件数)(规则包 folder)
│ │ ├── audit-rules-frontend.yml — 前端规则(按钮绑定/魔数)(规则包 frontend)
│ │ ├── audit-rules-go.yml — Go 规则包(占位:规则待补,槽位就绪)(规则包 go)
│ │ ├── audit-rules-i18n.yml — i18n 规则(文案硬编码检查)(规则包 i18n)
│ │ ├── audit-rules-java.yml — Java/Kotlin 规则(短名/魔数/方法长度/复杂度,exts: [java,kt])(规则包 java)
│ │ ├── audit-rules-nodejs.yml — Node.js 规则(同步 fs/空 catch)(规则包 nodejs)
│ │ ├── audit-rules-npm.yml — npm 规则(package.json 规范)(规则包 npm)
│ │ ├── audit-rules-paths.yml — (待注释)
│ │ ├── audit-rules-performance.yml — 性能规则(规则包 performance)
│ │ ├── audit-rules-php.yml — PHP 规则包(占位:规则待补,槽位就绪)(规则包 php)
│ │ ├── audit-rules-private.yml — 私密文件规则(凭据/私密清单)(规则包 private)
│ │ ├── audit-rules-python.yml — (待注释)
│ │ ├── audit-rules-robustness.yml — 健壮性规则(规则包 robustness)
│ │ ├── audit-rules-rust.yml — Rust 规则包(占位:规则待补,槽位就绪)(规则包 rust)
│ │ ├── audit-rules-structure.yml — 结构规则(命名/规模/复杂度)(规则包 structure)
│ │ ├── audit-rules-swift.yml — Swift 规则包(占位:规则待补,槽位就绪)(规则包 swift)
│ │ ├── audit-rules-template.yml — 规则模板(新规则包起点)(规则包 template)
│ ├── checks/ — 检查层(按 kind 调用检查器:正则/语义/结构/文件健康/按钮绑定/私密文件)
│ │ ├── button-bind.js — 按钮事件绑定交叉比对(声明了但没绑定)
│ │ ├── common.js — 检查器公共设施(豁免提示/severity 封顶/分组)
│ │ ├── credential-file.js — 凭据文件检查(.env/密钥文件)
│ │ ├── dataflow.js — 数据流规则包装(L2 token 级→finding)
│ │ ├── dispatch.js — 调度(runChecks 按 kind 分发汇总)
│ │ ├── dup-code.js — (待注释)
│ │ ├── dup-const.js — 同名常量跨文件重复定义检查(DRY:findConstDefs 多语言常量提取 + 模块级过滤 + checkDuplicateConst 跨文件聚合——2026-10-02 新规则)
│ │ ├── file-health.js — 文件健康度(行数/字节/行长三维打分)
│ │ ├── filter.js — 规则作用域过滤(exts/exclude_paths)
│ │ ├── folder.js — 目录级检查(文件夹数/单目录文件数/解包特征)
│ │ ├── fs-scanner.js — (待注释)
│ │ ├── hardcoded-path.js — (待注释)
│ │ ├── index.js — 检查层统一出口
│ │ ├── io.js — IO 风险分级包装:checkIoRisk → lib/ast/io-risk.js(转 warning finding,取代 quality/sync-fs)
│ │ ├── magic-number.js — 魔数检查包装(token 判定→finding)
│ │ ├── npm-json.js — package.json 检查(依赖版本/私有包豁免)
│ │ ├── private.js — 私密文件检查(私有仓可见性核对)
│ │ ├── regex.js — 正则类规则执行(regex/path-regex/blacklist)
│ │ ├── semantic.js — 语义类规则执行(patch insert/仓库级语义)
│ │ ├── structural.js — 结构类规则(函数长度/复杂度/嵌套/同步 fs)
│ ├── cli/ — (待注释)
│ │ ├── commands-account.mjs — (待注释)
│ │ ├── commands-audit.mjs — (待注释)
│ │ ├── commands-doc.mjs — (待注释)
│ │ ├── commands-vcs.mjs — (待注释)
│ ├── client/ — 客户端配置(DEFAULT_CONFIG + SETTINGS_SCHEMA 侧边栏设置项定义)
│ │ ├── index.js — 侧边栏设置 UI 总入口(DEFAULT_CONFIG + SETTINGS_SCHEMA)
│ ├── client-parts/ — 客户端分片源码(13 片,拼接成 lib/client.js;产物不入库)
│ │ ├── 00-loader.js — 首片:__ModuleLoader__.load + factory 头 + require + NS
│ │ ├── 01-const.js — [1] 常量区(忙碌状态键/10 维度表/超时/样式串)
│ │ ├── 02-utils.js — [2] 工具区(ensureCss/getJson/postJson/localGet/copyText)
│ │ ├── 03-icons.js — [3] 图标区
│ │ ├── 10-account.js — [4] 账号信息 Tab
│ │ ├── 11-browser.js — [5] 目录选择器(browse*)
│ │ ├── 20-repo.js — [6] 仓库管理卡(本地/云端仓库、推送、可见性)
│ │ ├── 21-audit.js — [7] 审计 Tab(权重/规则行/规则包/注入开关)
│ │ ├── 22-settings.js — [8] 设置 Tab(token/SSH/邮箱)
│ │ ├── 23-npm.js — (待注释)
│ │ ├── 30-page.js — [9] 页面装配(GitPushPage 三选项卡聚合)
│ │ ├── 40-controller.js — [10] Controller:状态机 + 数据加载(884 行,跨两片)
│ │ ├── 41-actions.js — [10] Controller:动作注入(269 行)
│ │ ├── 99-apply.js — 末片:apply/inject 导出 + factory 返回
│ ├── context/ — 上下文注入(给 AI 会话注入环境:目录映射/工具路径/skill 入口)
│ │ ├── index.js — 上下文注入入口(环境注入文本)
│ ├── core/ — (待注释)
│ │ ├── atomic-json.js — (待注释)
│ │ ├── config.js — (待注释)
│ │ ├── credentials.js — (待注释)
│ │ ├── endpoints.js — (待注释)
│ │ ├── exec.js — (待注释)
│ │ ├── workspace-paths.js — (待注释)
│ ├── exempt/ — 豁免机制(dsh-skip-* 注释标记解析与文件头/行内语义)
│ │ ├── index.js — 豁免注册表(dsh-skip-* 全标记消费)
│ │ ├── tool.js — (待注释)
│ ├── git/ — Git 执行层(runGit/账号/API/克隆/凭据/推送/扫描/索引维护/敏感扫描/传输通道)
│ │ ├── account-status.js — (待注释)
│ │ ├── account.js — 账号校验(token 在线 + SSH 公钥指纹,输出账号状态块)
│ │ ├── api.js — GitHub REST 调用(githubFetch 统一 token/错误识别)
│ │ ├── atomic-json.js — 统一 JSON 原子读写(readJson/writeJsonAtomic/updateJsonAtomic/writeTextAtomic)
│ │ ├── browse.js — 目录浏览(账号卡片路径选择器后端)
│ │ ├── clone-download.js — 并发下载 + .part 断点续传 + 体积守卫 + 进度回调
│ │ ├── clone-history-mode.js — (待注释)
│ │ ├── clone-history.js — (待注释)
│ │ ├── clone-jobs.js — clone 进度/预览内存态(供前端轮询)
│ │ ├── clone-replay-io.js — (待注释)
│ │ ├── clone-replay.js — (待注释)
│ │ ├── clone.js — 克隆(Git Data API,不依赖本地凭据)
│ │ ├── cloud.js — 云端仓库列表(/user/repos 供手动 clone)
│ │ ├── commit-message.js — (待注释)
│ │ ├── config.js — 路径与配置(PLUGIN_ROOT + 开发者要求清单读取)
│ │ ├── cred-env.js — 凭据传递工具(SSH 私钥路径 GIT_SSH_COMMAND / HTTPS askpass 脚本,AI 执行外部 git 不接触明文)
│ │ ├── credentials.js — 凭据解析(token/SSH 私钥:环境变量→凭据文件→settings)
│ │ ├── endpoints.js — (待注释)
│ │ ├── exec.js — git 进程调用(runGit 统一超时/错误规整 + gitRaw 原始字节)
│ │ ├── identity-rewrite.js — (待注释)
│ │ ├── identity.js — (待注释)
│ │ ├── ignore.js — .gitignore 兜底(DEFAULT_IGNORE_PATTERNS 补齐)
│ │ ├── index.js — Git 执行层统一出口
│ │ ├── module-splitter.js — (待注释)
│ │ ├── post-push.js — 推送后增强(remote-tracking ref/aux remote/tag)
│ │ ├── push-diagnose.js — (待注释)
│ │ ├── push.js — 提交推送编排(commitAndPush 全流程:敏感扫描→add/commit→推送)
│ │ ├── remote-resolve.js — (待注释)
│ │ ├── remote.js — 远端仓库管理(建仓默认 private/可见性切换)
│ │ ├── repo-index.js — dsh-repo-index 自动维护(扫描 workspace 生成索引 JSON)
│ │ ├── repos.js — 仓库扫描与展示(describeRepo 分支/远端/领先落后/未提交)
│ │ ├── scan-runner.js — (待注释)
│ │ ├── sensitive.js — 敏感信息扫描(提交前拦截密钥/凭据/私密文件)
│ │ ├── transport.js — 推送通道(dispatchPush 决策:SSH/API/auto + 结果核对)
│ │ ├── visibility.js — (待注释)
│ │ ├── wrapped-git.js — 浅包装 git(自动凭据透传:SSH 私钥/HTTPS token,git-sluice git <args> 与未知命令透传)
│ ├── http/ — HTTP 总入口(鉴权中间件 + 端点处理器骨架)
│ │ ├── index.js — HTTP 总入口(Origin/CSRF/写确认/413/路由分发)
│ ├── link-check/ — 链接判断(文档链接有效性,只 warning 永不 blocker)
│ │ ├── index.js — 链接判断总入口(分级扣分,断网不拦)
│ ├── npm/ — (待注释)
│ │ ├── account.js — (待注释)
│ │ ├── install.js — (待注释)
│ │ ├── npmrc.js — (待注释)
│ │ ├── publish.js — (待注释)
│ │ ├── registry.js — (待注释)
│ ├── plugin/ — Host 侧接线层(插件注册到 DSH:工具/HTTP/配置 schema)
│ │ ├── auto-detect.js — 任务完成自动推送·检测层(纯函数:✅任务完成 触发/❌⚠ 阻断/自定义正则/许可合成判断)
│ │ ├── auto-push.js — 任务完成自动推送·核心(turn/end 监听→检测→autoPushEnabled 开关→调 commitWithAudit 完整门禁,不裸提交)
│ │ ├── index.js — Host 侧接线(插件注册:工具/HTTP/配置注入宿主)
│ ├── readme-templates/ — README 模板 yml
│ │ ├── readme.yml — README 章节模板(git_gen_readme 用)
│ ├── rule/ — 规则引擎(yml 装载/编译注册表/同形字符检测/槽位启停)
│ │ ├── compilers.js — 规则编译器注册表(纯引用文件)
│ │ ├── homoglyph.js — 同形字符检测(yml kind/id 防 ASCII 混淆)
│ │ ├── loader.js — 规则总入口(yml 装载/解析/槽位启停)
│ │ ├── registry.js — 规则编译注册表核心(compileRule 主体)
│ │ ├── scope.js — 审计作用域机制层(scope_rules 规范化 + resolveScopeAction)
│ │ └── …(12 个更深文件)
│ ├── score/ — 10 维度加权评分总入口
│ │ ├── docs-score.js — 文档加分制检查器(文档集结构信号 + 版本一致性交叉验证,0 分起上限 10;不进 findings)
│ │ ├── index.js — 评分总入口(10 维度加权)
│ ├── self/ — 插件自身总入口(VERSION/versionInfo/CLI 帮助)
│ │ ├── index.js — 自身总入口(VERSION 一致性/versionInfo)
│ ├── vendor/ — (待注释)
│ │ └── …(2 个更深文件)
├── scripts/ — 开发工具脚本(版本校验/双副本同步/预览服务/README 目录树维护)
│ ├── audit-runner.mjs — 审计扩展 CLI 统一入口(独立跑 scripts/audit-ext/ 全部扩展)
│ ├── audit-runtime-check.mjs — 三层审计 L3 运行时检测脚本
│ ├── browser-page-probe.mjs — (待注释)
│ ├── build-client.mjs — 客户端分片拼接(PART_ORDER + --check 门禁 + 形态铁律自检)
│ ├── check.mjs — 语法检查脚本(npm run check)
│ ├── clean-date-comments.py — (待注释)
│ ├── cpu-sample.mjs — (待注释)
│ ├── doc-drift.mjs — (待注释)
│ ├── doc-func.mjs — (待注释)
│ ├── doc-tree.mjs — (待注释)
│ ├── doc-version.mjs — (待注释)
│ ├── hot-path-probe-cjs.cjs — (待注释)
│ ├── hot-path-probe-fs-shim.mjs — (待注释)
│ ├── hot-path-probe-fsp-shim.mjs — (待注释)
│ ├── hot-path-probe.mjs — (待注释)
│ ├── module-splitter.py — 巨型单文件按顶层块拆分脚本(analyze/split/verify 三命令,python3 零依赖;module_splitter 工具与 CLI 的底层实现)
│ ├── platform-scan.mjs — (待注释)
│ ├── probe-recheck.mjs — 探针:「重新检测」按钮链路实测(在线校验 token/SSH)
│ ├── readme-gen.mjs — README 生成独立脚本(git_gen_readme 抽出:模板渲染/版本表/目录)
│ ├── rename-locator.mjs — 变量重命名位置定位工具(按作用域聚合引用——单字母变量人工重命名辅助)
│ ├── rule-switch.mjs — 规则槽位手动启停 CLI
│ ├── rules-solo-audit.mjs — 规则单启控制变量扫描(基准全关+逐规则单启+全量对照,报告供 AI/人工审规则有效性与局限,按需运行非常驻)
│ ├── scan-file-io.mjs — 文件读写扫描器(列出所有 fs 读写调用位置 + 路径参数)
│ ├── scan-fs-hotspots.mjs — (待注释)
│ ├── scan-hardcoded-paths.mjs — (待注释)
│ ├── scan-repos.mjs — (待注释)
│ ├── scan-version.mjs — 版本一致性校验脚本
│ ├── scrub-user-wording.mjs — 清理「用户沟通措辞」独立脚本
│ ├── symbol-index.mjs — (待注释)
│ ├── verify-prestep.mjs — 上下文注入自检脚本(真实触发 agent/pre-step 验证注入)
│ ├── audit-ext/ — (待注释)
│ │ ├── _example-readme-present.mjs — 审计扩展契约示例(_ 前缀:演示不参与实际审计)
│ │ ├── variable-min-length.mjs — 审计扩展:variable-min-length(内置规则抽出试点——统一动态入口)
├── assets/ — 预览页与配图(preview.html 交互模拟页 + 面板截图)
│ ├── start.sh — 预览服务器启停脚本(start/stop/restart/status + --port + PID/日志/健康检查 /preview-ping)
│ ├── tree-sitter/ — (待注释)
│ │ ├── LICENSE — (待注释)
│ │ ├── README.md — (待注释)
│ │ ├── VERSIONS.txt — (待注释)
│ │ ├── tree-sitter-javascript.wasm — (待注释)
│ │ ├── tree-sitter-python.wasm — (待注释)
│ │ ├── tree-sitter-typescript.wasm — (待注释)
│ │ ├── tree-sitter.js — (待注释)
│ │ ├── tree-sitter.wasm — (待注释)
├── test/ — node:test 全量单元测试(541+ 条,覆盖审计/推送/账号/HTTP/后台任务)
│ ├── .test — 空文件豁免标记(目录级豁免 .test 目录)
│ ├── e2e-npm-tab-render.mjs — (待注释)
│ ├── regression-2.4.1.mjs — (待注释)
│ ├── run-tests.mjs — (待注释)
│ ├── test-account-refresh-on-push.mjs — (待注释)
│ ├── test-account-ssh.mjs — 账号检查 + SSH 密钥测试
│ ├── test-analysis-coverage.mjs — (待注释)
│ ├── test-ast-confirm-span.mjs — (待注释)
│ ├── test-audit-api-http.mjs — (待注释)
│ ├── test-audit-api.mjs — (待注释)
│ ├── test-audit-bad-file.mjs — 审计拦截门禁测试(硬编码密码/API key/.env 凭据文件)
│ ├── test-audit-defaults.mjs — (待注释)
│ ├── test-audit-empty.mjs — (待注释)
│ ├── test-audit-exempt-paths.mjs — 提交时按文件临时豁免审计(auditExemptPaths)回归
│ ├── test-audit-ext.mjs — 审计扩展自动接入测试(契约加载/降级/match/auditFull 并入)
│ ├── test-audit-false-positive-guards.mjs — (待注释)
│ ├── test-audit-git-boundary.mjs — (待注释)
│ ├── test-audit-npm-publish-rules.mjs — (待注释)
│ ├── test-audit-push-boundary.mjs — (待注释)
│ ├── test-audit-scope.mjs — 审计作用域/凭据占位符回归测试
│ ├── test-audit-slot-order.mjs — (待注释)
│ ├── test-audit.mjs — 审计总入口测试(auditFull/changed/豁免/gitignore)
│ ├── test-auditignore.mjs — (待注释)
│ ├── test-auto-push.mjs — 任务完成自动推送测试(检测纯函数 + registerAutoPush 门控监听注册)
│ ├── test-build-artifact-skip.mjs — 构建/混淆产物跳过专项测试(Pawchive 样本 fixture)
│ ├── test-build-client.mjs — 分片构建门禁测试(产物一致/幂等/形态铁律/dshgp_ 前缀)
│ ├── test-button-bind.mjs — 按钮绑定交叉比对(jsx 工厂形态/注释过滤/行号归属)
│ ├── test-cli-audit-parity.mjs — CLI 与源码全量审计一致性测试(audit --full --json vs 直接 auditFull,含忽略排除)
│ ├── test-cli-help-registry-sync.mjs — (待注释)
│ ├── test-client-fragment-scope.mjs — 客户端分片作用域推导测试(dsh-client-fragment)
│ ├── test-client.mjs — 侧边栏测试(手写 DOM/零外部资源/开关默认)
│ ├── test-clone-concurrency.mjs — clone 并发互斥/可中止/失败保留文件(14 项,CIFS 对照用例可跳)
│ ├── test-clone-history-defaults.mjs — (待注释)
│ ├── test-clone-history-mode.mjs — (待注释)
│ ├── test-clone-history.mjs — (待注释)
│ ├── test-clone-maxfilemb.mjs — (待注释)
│ ├── test-clone-parts-keep.mjs — (待注释)
│ ├── test-clone-preview-buttons.mjs — clone 预览确认框按钮可点(真渲染+真点击)
│ ├── test-clone-replay-io.mjs — (待注释)
│ ├── test-clone-replay.mjs — (待注释)
│ ├── test-clone-token.mjs — (待注释)
│ ├── test-collector-ignore.mjs — (待注释)
│ ├── test-command-registry.mjs — 命令注册表测试(工具入表/查找/parseRegistryArgs/清单生成)
│ ├── test-commit-message.mjs — (待注释)
│ ├── test-context.mjs — 上下文注入测试
│ ├── test-conv-rule-scope.mjs — (待注释)
│ ├── test-cred-env.mjs — git_cred_env 凭据传递测试(双通道/无明文/askpass 调用/无凭据兜底)
│ ├── test-dataflow.mjs — 三层审计 L2 数据流测试
│ ├── test-doc-func.mjs — (待注释)
│ ├── test-doc-version-release-source.mjs — (待注释)
│ ├── test-doc-version.mjs — (待注释)
│ ├── test-docs-score.mjs — 文档加分制测试(文档集圈法/四检查/公式/不一致 review/不冲突)
│ ├── test-dup-code.mjs — (待注释)
│ ├── test-dup-const-idiom.mjs — (待注释)
│ ├── test-dup-const.mjs — duplicate-const 规则测试(多语言提取 JS/Kotlin/Java/Go/Rust/Python、模块级过滤、跨文件聚合、test 目录排除、同值不同名不报)
│ ├── test-empty-catch-promise.mjs — (待注释)
│ ├── test-empty-catch-single-source.mjs — (待注释)
│ ├── test-exempt-hint-classify.mjs — (待注释)
│ ├── test-exempt-hint-effective.mjs — (待注释)
│ ├── test-exempt-tool.mjs — (待注释)
│ ├── test-exempt.mjs — 豁免总入口测试(7 标记 + 位置语义)
│ ├── test-ext-variable-min-length.mjs — (待注释)
│ ├── test-false-positive-fixes.mjs — 误报修复回归测试
│ ├── test-file-health.mjs — 文件健康度矩阵评分测试
│ ├── test-filter-ext.mjs — (待注释)
│ ├── test-folder-scope.mjs — 目录级审计作用域回归测试
│ ├── test-fs-hotspots.mjs — (待注释)
│ ├── test-func-doc-drift.mjs — (待注释)
│ ├── test-generated-html-artifact.mjs — (待注释)
│ ├── test-git-api-tool.mjs — (待注释)
│ ├── test-git-bin-plan.mjs — (待注释)
│ ├── test-git-identity-rewrite.mjs — (待注释)
│ ├── test-git-identity.mjs — (待注释)
│ ├── test-git.mjs — git 总入口测试(runGit/commitAndPush/凭据/克隆)
│ ├── test-gitignore-match.mjs — gitignore 兜底匹配(与真 git 对拍 + 非 git 端到端)
│ ├── test-gitignore-nongit-dir.mjs — (待注释)
│ ├── test-history-audit.mjs — (待注释)
│ ├── test-http.mjs — HTTP 总入口测试(Origin/CSRF/413/路由)
│ ├── test-inject-switch.mjs — 注入开发者要求清单子开关回归
│ ├── test-inject-system-prompt.mjs — 注入系统提示词回归
│ ├── test-io-risk.mjs — IO 风险分级测试(四级判定/字段完整性/汇总/排序/finding 转换)
│ ├── test-java-rules.mjs — Java/Kotlin 语言路由与专项规则测试(javaKtFuncRanges/短名/复杂度/规则联动/聚合型降级)
│ ├── test-line-count.mjs — (待注释)
│ ├── test-link-check.mjs — 链接判断测试(分级扣分/断网不拦)
│ ├── test-loop-no-fallback-return.mjs — (待注释)
│ ├── test-magic-number.mjs — 硬编码魔数检测测试
│ ├── test-max-lines-scope.mjs — (待注释)
│ ├── test-mirror-fallback.mjs — (待注释)
│ ├── test-mirror-gates.mjs — (待注释)
│ ├── test-module-splitter-multiline.mjs — (待注释)
│ ├── test-module-splitter.mjs — module_splitter 工具 + CLI 接入测试(契约 + 行为 + 脚本随插件发布)
│ ├── test-multi-remote.mjs — (待注释)
│ ├── test-name-length-scope.mjs — (待注释)
│ ├── test-npm-enobufs.mjs — (待注释)
│ ├── test-npm-install.mjs — (待注释)
│ ├── test-npm-publish.mjs — (待注释)
│ ├── test-npm-registry.mjs — (待注释)
│ ├── test-npm-token-credential.mjs — (待注释)
│ ├── test-perf-loop-collection.mjs — (待注释)
│ ├── test-perf-repeat-call.mjs — (待注释)
│ ├── test-persist-credentials.mjs — 凭据持久化测试
│ ├── test-platform-scan.mjs — (待注释)
│ ├── test-plugin.mjs — 插件接线测试(入口导出/工具清单/双副本同步)
│ ├── test-private-gate.mjs — (待注释)
│ ├── test-project-type-filter.mjs — 项目类型规则适配测试(非 dsh 项目不加载 dsh 槽位/0.x 版本规则、timeout 限 js 系、folder 尊重 gitignore——Pawchive 误报消除驱动)
│ ├── test-push-diagnose.mjs — (待注释)
│ ├── test-push-false-success.mjs — (待注释)
│ ├── test-push-transport.mjs — 推送通道回归(SSH 优先/一致性语义)
│ ├── test-quality.mjs — 评分总入口测试(AST 质量检查器)
│ ├── test-quota-write.mjs — (待注释)
│ ├── test-readme-gen.mjs — README 生成测试(模板渲染/版本表)
│ ├── test-remote-name-ascii.mjs — (待注释)
│ ├── test-remote-resolve.mjs — (待注释)
│ ├── test-rename-locator.mjs — rename-locator 测试(同名不同作用域分组/模块级/过滤)
│ ├── test-repo-list.mjs — 仓库列表测试(本地扫描/索引读写/HTTP 端点/远端状态)
│ ├── test-rule-include-paths.mjs — (待注释)
│ ├── test-rule-packs.mjs — 规则总入口测试(编译注册/字段指派)
│ ├── test-scan-hardcoded-paths.mjs — (待注释)
│ ├── test-scope.mjs — 作用域最小实验测试(分类器/机制/magic 接入)
│ ├── test-scrub-conv-wording.mjs — (待注释)
│ ├── test-self.mjs — 自身总入口测试(VERSION/CLI/help 比对)
│ ├── test-settings-persistence.mjs — 设置侧边栏持久化专项测试(L1 提交/L2 白名单/L3 回读/L4 消费四层断言)
│ ├── test-settings-roundtrip.mjs — (待注释)
│ ├── test-sidebar-interaction.mjs — 侧边栏规则包列表交互自检
│ ├── test-slash-commands.mjs — 用户输入框 /git-audit 斜杠命令(解析/接线/对本仓库跑 quick)
│ ├── test-smart-hint.mjs — 扫描智能提示 + 评分对数衰减测试
│ ├── test-status-secret.mjs — token 明文不下发安全回归
│ ├── test-symbol-index.mjs — (待注释)
│ ├── test-symlink-resolution.mjs — 软链安装依赖解析回归测试(默认失败/--preserve-symlinks/NODE_PATH/真实副本四种场景)
│ ├── test-task-queue.mjs — 后台化回归测试(官方 job 注册 / 无 jobs 同步保底 / blocker 拦截)
│ ├── test-test-cache.mjs — (待注释)
│ ├── test-tokenizer-multiline-template.mjs — (待注释)
│ ├── test-tool-contract.mjs — (待注释)
│ ├── test-tool-probes.mjs — (待注释)
│ ├── test-tools-e2e.mjs — (待注释)
│ ├── test-tree-doc.mjs — README 目录树脚本测试(gen/check/apply 闭环)
│ ├── test-treesitter.mjs — (待注释)
│ ├── test-version-metrics.mjs — (待注释)
│ ├── test-visibility-unified.mjs — (待注释)
│ ├── test-workspace-paths.mjs — (待注释)
│ ├── fixtures/ — (待注释)
│ │ ├── TimeZoneComboBox-CRnoCikG.js — Pawchive 混淆产物样本(hash 文件名——跳过判定 fixture)
│ ├── helpers/ — (待注释)
│ │ ├── test-cache.mjs — (待注释)
│ │ ├── tmp-dir.mjs — (待注释)
├── docs/ — 开发文档
│ ├── 2.9.0-design.md — (待注释)
│ ├── 2026-10-09-审计插件性能优化.MD — (待注释)
│ ├── 2026-10-11-单一真源与文档漂移治理方案.MD — (待注释)
│ ├── 2026-10-11-硬编码路径改造为审计引擎方案.MD — (待注释)
│ ├── 2026-10-13-UI账号信息-NPM对齐GitHub方案.MD — (待注释)
│ ├── 2026-10-13-UI账号信息-NPM账号卡片与三标签页.MD — (待注释)
│ ├── CHANGELOG.md — 版本列表宿主(doc-version apply 写 dshgp-version 标记块)
│ ├── DETAILS-EXEMPT-AND-RULES.md — 细节补充:豁免注释与规则 yml 用法全录
│ ├── FUNCTIONS.md — 函数列表宿主(doc-func apply 写 dshgp-functions 标记块)
│ ├── PERF-BASELINE.md — (待注释)
│ ├── SPEC.md — (待注释)
│ ├── releases.json — (待注释)
│ ├── 功能-仓库索引与账号状态.md — (待注释)
│ ├── 功能-历史提交审计.md — (待注释)
│ ├── 功能-审计规则体系.md — (待注释)
│ ├── 功能-文档与结构追踪.md — (待注释)
├── skills/ — 插件权威 skill(功能手册/规则/使用说明,安装副本的 skills/ 同步)
│ ├── dsh-repo-index.md — dsh-repo-index skill(源码索引权威说明)
│ ├── dev/ — (待注释)
│ │ ├── audit-rule-authoring.md — (待注释)
│ │ ├── dsh-git-push.md — (待注释)
│ │ ├── git-push-live-fix.md — (待注释)
│ ├── guide/ — (待注释)
│ │ ├── guide-audit.md — (待注释)
│ │ ├── guide-cli-scripts.md — (待注释)
│ │ ├── guide-clone-repos.md — (待注释)
│ │ ├── guide-commit-push.md — (待注释)
│ │ ├── guide-inject-ui.md — (待注释)
│ │ ├── guide-slash-completion.md — (待注释)
│ ├── workflow/ — (待注释)
│ │ ├── README.md — (待注释)
│ │ ├── git-commit-discipline.md — (待注释)
│ │ ├── git-project-startup.md — (待注释)
│ │ ├── git-rebuild-process.md — (待注释)
│ │ ├── github-operations.md — (待注释)
│ │ ├── readme-sync-git-md.md — (待注释)
│ │ ├── task-completion-report.md — (待注释)
│ │ ├── tool-json-add-ask.md — (待注释)
│ │ ├── versioning-rule.md — (待注释)
├── .github/ — (待注释)
│ ├── workflows/ — (待注释)
│ │ ├── test.yml — (待注释)
├── audit-samples/ — (待注释)
│ ├── .samples — (待注释)
│ ├── js-bad.js — (待注释)
│ ├── py-bad.py — (待注释)
├── .auditignore — 审计豁免清单(不影响 git 入库,仅跳过审计扫描)——排除内置第三方代码
├── .gitignore — 忽略规则(node_modules/产物/备份/回收站等)
├── CONTRIBUTING.md — (待注释)
├── LICENSE — (待注释)
├── README.md — 插件 README(功能总览/用法/版本记录)
├── SECURITY.md — (待注释)
├── cli.mjs — 独立 CLI(git-sluice,不依赖宿主可独立运行)
├── cordis.patch.yml — DSH 插件组合 patch(loader 注入定义)
├── package.json — 包声明(零依赖、files 白名单、scripts)
├── tree-doc.json — 目录结构注释映射(路径→一句话介绍,AI 维护)
├── version-metrics.json — (待注释)
分层速查文档:
lib/ARCHITECTURE.md(三层审计架构四层落地位置:规则声明 → AST 实现 → 检查包装 → 编排调度)
lib/ 下每个文件夹只负责一件事,改审计逻辑前先分清所属层,避免在错误的层里打补丁
(尤其不要用「跳过某类行」的补丁去修误报):
| 层 | 位置 | 职责 |
|---|---|---|
| ① 规则声明 | lib/audit-rules/*.yml | 阈值 / severity / 豁免清单 / 上下文关键字 / astConfirm 开关——改阈值先改 yml,不改代码 |
| ② 具体实现(AST) | lib/ast/*.js | token 级精准判断:轻量 tokenizer(区分 ident / num / str / tmpl / comment)→ 括号平衡 → 判定 |
| ③ 调用包装 | lib/checks/*.js | 把判定转成 finding:统一 file/line/rule/severity/message/dimensions/exemptHint/scoreImpact,不重复造检查逻辑 |
| ④ 编排调度 | lib/audit/*.js | 采集文件(collector.js)、glob 转换(glob.js)、单文件审计(audit-file.js)、豁免消费与汇总(finding.js/slot.js)、入口编排(orchestrate.js);index.js 只做再导出 |
| — 插件入口 | lib/app/*.js | 宿主接线:配置 schema(含 schemastery 兜底)、工具声明、注入文本、工具与 HTTP 处理、apply 注册编排(lib/index.js 只做再导出) |
| — 规则编译器 | lib/rule/compilers/*.js | yml 字段类型 → 编译函数(注册制,按维度分模块;compilers.js 只做引用) |
| — git 能力 | lib/git/*.js | 命令执行 / 凭据 / GitHub API / 传输(SSH+API)/ 提交推送 / 克隆 / 仓库与可见性 / 账号校验 |
| — 规则装载 | lib/rule/*.js | 规则加载 / 编译 / 注册(yml → 编译后规则对象) |
| — 评分 | lib/score/index.js | 10 维度对数衰减评分 + 权重(本目录只放评分,不含 AST) |
| — 呈现 / 交互 | lib/client-parts/ → lib/client.js | 侧边栏 UI、审计面板、规则包列表(分片源码 + 拼接产物,改代码只改分片) |
为什么拆这么细:原先 lib/score/ast.js(1029 行)与 lib/audit/checks.js(1259 行)把「评分」「实现」「调用」「调度」全混在一起——
lib/score/ 本应只管评分权重,却装着全部 AST 实现;checks.js 本应只做调用,却塞了 25 个检查实现。拆分后每个文件只做一件事,
新增检查时「实现写哪、调用写哪、调度写哪」一眼可见。
1.1.4 把这套「实现归位到各文件夹」的规则推广到另外五处同类问题:lib/git/index.js(1036 行)
拆成 12 个能力模块 + 35 行出口,lib/rule/compilers.js(459 行)拆成 10 个编译器模块 + 17 行出口,
lib/audit/index.js(482 行)拆成 6 个编排模块 + 32 行出口,lib/index.js(683 行)拆成 lib/app/ 8 个模块 + 24 行出口。
入口文件从此只做再导出、不含实现——新增能力改对应模块即可,入口不再随功能增长而膨胀。
⛔ 替代手改的硬约束:这类拆分靠人眼搬运极易静默丢代码(实测踩过:注册表类文件里大量匿名
registerCompiler('kind', ...) 语句被误并进上一个声明的正文;Schema = makeFallbackSchema() 这类
顶层语句被排到使用它的 Config 之后导致运行期崩溃)。拆分后有四项必查,缺一不可:
Object.keys(module) 集合与顺序必须一致;diff 必须为空;lib/audit/index.js 的 import '../rule/compilers.js' 是编译器注册的
唯一触发点,丢了不报错但检查项全不出,属于「静默失效」,比崩溃更难查;lib/ast/:具体实现(token 级)| 模块 | 职责 |
|---|---|
tokenizer.js | 分词器 + 按文本内容的 LRU 缓存(全部 token 级检查的公共底座) |
brace.js | 括号配对、区间包含判定(供复杂度/嵌套/函数行数复用) |
control-flow.js | 同步 fs 调用、空 catch、圈复杂度、嵌套深度 |
size.js | 函数长度、文件长度、重复字符串 |
naming.js | 标识符长度、函数名过短(含 i18n 缩写豁免)、受控小文件读取 |
code-lines.js | 判断某行是否「真在代码里」、取出代码中的字符串字面量 |
magic-number.js | 硬编码魔数(豁免版本号/日期/HTTP 状态码/命名常量) |
credential.js | 凭据值判定、前缀型密钥串的占位符精筛 |
dataflow.js | 三层审计 L2:同函数「清空后访问」数据流(clear()/=[]/=null/length=0/splice(0) 后 .get()/[0]) |
index.js | 统一出口(只做再导出,不含实现) |
lib/checks/:调用包装| 模块 | 职责 |
|---|---|
common.js | 公共设施(豁免提示、severity 封顶、各 astConfirm 精筛集合的取值函数) |
dispatch.js | 调度 runChecks——只写引用:按 kind 依次调用各检查器并汇总,不含任何检查逻辑 |
filter.js | 规则作用域过滤(exts / include_paths / exclude_paths / file_patterns)——yml 声明的作用域唯一落地点 |
regex.js | 正则类规则(含 astConfirm 精筛消费) |
structural.js | 结构类(函数长度/复杂度/嵌套/文件行数/同步 fs/空 catch) |
semantic.js | 语义类(yml 声明的语义检查、patch insert) |
dataflow.js | 三层审计 L2 包装:checkDataflow → lib/ast/dataflow.js(空规则短路防崩) |
npm-json.js · folder.js · credential-file.js · private.js · button-bind.js · magic-number.js · file-health.js | 各自对象的检查器 |
index.js | 统一出口(只做再导出) |
lib/audit/checks.js 已退化为纯引用文件(export * from '../checks/index.js',17 行),保留它只为让原有调用方
(lib/audit/index.js 与各测试)导入路径稳定。
检查器标准样式 = 薄包装(checkEmptyCatch → 调 checkEmptyCatchAst、checkMagicNumberSmart → 调 checkMagicNumberSmartAst)。
⛔ 反模式:在检查器里自己写正则/逐行扫描重新实现一遍检查逻辑。逐行文本无法区分代码与注释/字符串,必然误报——
历史教训:magic-number 曾在调用层逐行扫,导致注释里的版本号(// v1.8.0)、CSS 字号、i18n 字典值全被误报为魔数。
新检查一律写在 lib/ast/(token 级实现),再在 lib/checks/ 加薄包装,最后在 dispatch.js 加一行调度。
文本型检查统一采用两段式(astConfirm: true 开启):
正则初筛(快) AST 精筛(准)
pattern 扫全文 makeCodeLineFilter(text, 候选行)
→ 得到候选行号列表 → token 级确认「命中行确实是代码行」
注释 / 字符串 / 模板串行 → 丢弃(不是硬编码)
// v1.8.0、2026-09-13)、字符串里的 CSS 字号('.x{font-weight:650}')、i18n 字典值不再报——无需任何「跳过注释行」的补丁。astConfirm(这些恰恰要查注释里的内容,例如注释里贴的 token、// TODO 修复)。| 实现方式 | 位置 | 例子 |
|---|---|---|
| 正则初筛 + AST 精筛 | yml 的 astConfirm: true + makeCodeLineFilter | readability/magic-number |
| 纯 token 级(无需正则) | lib/ast/(各模块,见上表) | checkMagicNumberSmartAst / checkSyncFs / checkEmptyCatchAst / checkComplexityAst / checkNestingDepthAst / checkNameLengthAst / checkFuncLinesAst / checkRepeatedStringsAst / checkClearAccessAst |
| 纯正则(本质是文本特征) | lib/checks/regex.js 的 checkRegexRules | 凭据硬编码、路径穿越、对话残留、黑名单 |
按检测模式的成本分层,解决「正则命中面宽但 AST 精判成本高」的取舍:
| 层 | 工具 | 管什么 | 成本 | 产出 |
|---|---|---|---|---|
| L1 正则初筛 | filter.js 的 filterRulesByFileText | 规则声明 file_patterns(正则数组)时,先对文件文本做一次纯正则扫描——命中任一 = 候选文件,才进 L2;未命中 = 该规则剔除(检查器空规则短路,顺带防 rule.severity 崩溃) | 极低(每文件一次正则) | 候选文件集合 |
| L2 AST+YAML 数据流 | lib/ast/dataflow.js + lib/checks/dataflow.js | 只对候选文件做同函数内数据流判定:清空(clear()/reset()/=[]/=null/length=0/splice(0))后访问(.get()/.at()/[下标])——dataflow/clear-then-access 规则 | 中(只扫候选,非全量 tokenize) | 真实发现(文件:行 + 清空/访问证据) |
| L3 运行时检测 | scripts/audit-runtime-check.mjs(独立 CLI) | 兜住跨文件、闭包、异步时序静态盲区:动态 import 被测模块,先调清空方法再调访问方法,实测是否拿到 undefined/空 | 高(要跑代码,按需触发) | 运行时确认(退出码 1 = 命中) |
L2 判定保守(宁漏不误报):
push/set/重新赋值/引用传参填充(walkVideos(root, files, 0))→ 撤销清空标记,其后访问不算var x = [] 声明初始化不算清空;.length 读、shift/pop 消费式访问不报(while (len) { shift() } 保护模式)yml 声明示例(audit-rules-nodejs.yml 的 dataflow/clear-then-access):
- id: dataflow/clear-then-access
kind: "dataflow"
severity: "warning"
file_patterns: # L1:命中任一才进 L2(纯正则,成本极低)
- "\\b(?:clear|reset|flush|purge|splice)\\(0?\\s*\\)"
- "\\b\\w+\\s*=\\s*(?:\\[\\]|null|undefined)"
- "\\b\\w+\\.length\\s*=\\s*0"
- "\\b(?:get|at|first|last|peek|head)\\(0?"
L3 用法:
node scripts/audit-runtime-check.mjs <被测 js 文件> [--obj 对象名] [--verbose]
node scripts/audit-runtime-check.mjs --all <目录>
退出码:0=全部通过(无运行时命中);1=存在运行时命中(L3 确认的 bug);2=无法检测。
可读性 / 可维护性 / 健壮性 / 安全性 / 性能 / 测试覆盖 / 可观测性 / 可部署性 / 文档 / 开发者体验,默认合计 100,可在侧边栏调权重(weightOverrides JSON)。
max(0.1, 10 - k*ln(1+errorCount)),k 按维度分级(安全性 1.8 衰减最快)每次审计都跑完整的静态初筛 + AST 语义检查,不提供可调强度:
| 阶段 | 检查内容 |
|---|---|
| 静态初筛 | 正则 / 凭据 / 路径 / 黑名单 / 空 catch / 同步 IO |
| AST 语义 | func-lines / max-complexity / max-depth / max-lines / repeated-string / min-occurrences / semantic / credential-file / min-length |
扫描范围由 auditScanScope(diff / full)与 maxScanFiles(全量上限)决定;硬编码检查与审计共用同一范围——审计扫多少,硬编码就扫多少。
2026-09-17:移除「审计强度」「自定规则目录」「硬编码全量扫」三个设置项。它们并非用户可配项:强度固定为完整流程;自定规则目录只保留工具
ruleset参数;硬编码全量扫此前从未接上审计实现(空开关)。
审计豁免按作用粒度分四大类:文件/行注释标记(dsh-skip-*)、目录标记(.test 空文件)、路径类别(test/scripts 刻意用法)、私有库级别(私密文件降级)。安全红线不可豁免:secret-* / cred* / security/* 类规则即使标 disabled 也强制加载(lib/exempt/index.js 为豁免总注册表,lib/audit-rules/audit-rules-private.yml 为强制加载清单)。
dsh-skip-* 注释标记(文件头=整文件 / 行内=单点)| 标记 | 位置 | 豁免内容 |
|---|---|---|
dsh-skip-sensitive | 文件头=整文件 / 行尾=本行 | 凭据/私密类([FUNC]/credential-file/credential-ref/path-regex 及 security、secret、password、hardcoded 等安全词规则) |
dsh-skip-size | 只能文件头 | 大文件/二进制(large-file) |
dsh-skip-func-length | 文件头=全文件 / 函数定义行行尾=单函数 | 函数超长(func-lines) |
dsh-skip-syntax | 只能文件头 | 语法类(syntax/json-parse/yaml-parse) |
dsh-skip-quality | 只能文件头 | 质量评分(func-lines/empty-catch/sync-fs) |
dsh-skip-residue | 行尾=本行 / 文件头=整文件 | 残留类(debugger/todo/console 规则,按规则名前缀细分) |
dsh-skip-style | 只能文件头 | 数值风格规则(min-length/max-lines/max-complexity/max-depth/min-occurrences/repeated-string) |
dsh-skip-i18n | 行尾=本行 / 文件头=整文件 | i18n 硬编码文案审计 |
写法(文件头前 3 行内注释 → 整文件豁免;行尾注释 → 本行豁免,仅支持 sensitive/residue/func-length/i18n):
// dsh-skip-sensitive: 文件含 mock 凭据字面量(仅占位示例,非真实凭据)
const t = "AKIA—占位示例(示例刻意避开密钥检测正则的 16 位字母形态)";
// dsh-skip-func-length: 故意构造的超长函数样本
function longFn() { /* ... */ }
console.log(x); // dsh-skip-residue: 本行为刻意保留的调试输出样本
.test 空文件目录豁免(目录级,最强)在目录内放一个 0 字节 .test 文件,该目录(含全部子目录)整目录跳过扫描、不出任何结果——比 .samples(照常出结果但不拦截)更强。专为测试 fixture 目录设计:test/ 目录放 .test 空文件后,整个测试目录不再被审计(测试用例里故意构造的黑名单词样本/超长函数样本不会被误拦)。全仓收集与变更审计(diff/changed scope)同样生效——以前者为准,改动若涉及 test/ 下文件(如新增测试用例),整个 test 目录自动不进变更审计,不会因样本词被误拦提交。
test/ 目录下文件:residue / console-log / sync-fs / empty-catch / performance 类问题自动豁免scripts/ 目录与 cli.mjs:residue / console-log / sync-fs 自动豁免仓库跟踪到私密文件(清单见 audit-rules-private.yml:**/id_ed25519、**/.ssh/**、**/.env、**/.npmrc 等)时按远端可见性分级:
blocker 拦截提交(私钥/凭据已可被任何人获取,必须移除或转私有)warning 仅提醒(私有边界内放行,转公开前须先移除)——即「私有库豁免」:私密文件与工作留痕(会话记录/凭据/留痕)在私有仓库可正常提交推送,不需要额外豁免标记;单文件想彻底不报再用 dsh-skip-sensitive 注释门禁级豁免(同一可见性分级,覆盖全部槽位):拦截判定同样按远端可见性分级——private 仓库的审计只报告不拦截(返回 privateExempt 标记,明细仍可在审计 API 查),public / unknown 保守拦截(不误放公开库);可见性取 origin 的 GitHub 查询结果,探测失败按 unknown。此前门禁只看「示例目录」、没有任何可见性分级,而 comment / docs / security 等槽位规则不受 private 槽位(凭据 glob)约束,于是私有留痕仓库会被 conv-* 等 blocker 拦下(回归,见 test/test-private-gate.mjs)。
技能/规则文档豁免:skills/ 与 rules/ 目录下的 md 文档里的沟通措辞(如触发场景描述)是设计文本而非代码残留,不触发用户沟通词规则。
侧边栏 → 审计选项卡开关「代码禁用户沟通词」,默认开启:代码注释/文档出现「用户说/用户要求/用户原话」等沟通残留措辞(黑名单见 audit-rules-comment.yml)→ blocker 拦截提交;白名单业务词(用户ID/用户登录/用户角色等)命中则整行豁免。规则文档与测试目录按上述豁免机制自动放行。
扫描 md/文本中的 URL 并访问验证(404/403→-3、DNS→-2、超时→-1 分级扣分),只 warning 永不 blocker(网络不可靠防假阳性拦截)。
astConfirmKind)审计的每条规则(lib/audit-rules/*.yml)先跑正则初筛拿到候选行,再由 lib/ast/ 里的 AST 实现做语义确认——正则快但看的是字符,AST 慢但看的是结构,两层配合才能既不漏报又不误报。
规则通过 astConfirmKind 声明「这条规则命中后还要精筛什么」,lib/checks/regex.js 按名字分派到对应 AST 实现(yml 是规则、lib/ast/ 是实现、lib/checks/ 是调用,各层各司其职):
astConfirmKind | AST 实现 | 精筛语义 | 豁免(不报)的例子 |
|---|---|---|---|
small-file-read | checkSmallFileReadAst | 读文件是否属受控小文件(配置/缓存/字典) | 读 package.json、locale 字典、cache 文件 |
short-func-name | checkShortFunctionNameAst | 函数名是否真过短且非公认缩写 | tr/t/L(i18n)、el/cb/fn |
credential-value | checkCredentialRefAst | 凭据标识符右侧是否直接是有效字面量 | 类型检查 typeof cfg.token === 'string'、透传 cfg.token = init.token、process.env.KEY、占位符 |
shell-cd-dynamic | shellCdDynamicLines | cd 目标是否动态路径(含 $VAR/$())且无失败兜底(同行无 ||、非 && 链、非注释/字符串) | cd "$(dirname "$0")" 自我定位(目录必然存在)、cd "$X" || exit 1 有兜底、cd dist 字面量路径 |
write-into-gitignored | writeIntoGitignoredLines | 写操作(writeFile/mkdir 等)目标路径是否命中仓库 .gitignore(需 repoPath 上下文;单文件审计无上下文不报、不臆测) | node_modules 内写入(安装产物)、/tmp 临时目录、.gitignore 里 ! 取反的路径 |
两种模式:mode: 'deny' 把 AST 判定出的行加入豁免集(集合内不报);mode: 'allow' 要求只有 AST 判定出的行才报(集合外不报)。credential-value 用 allow 模式——只有当「凭据变量右侧直接跟着非占位字符串字面量」才算硬编码。
为什么必须这么做:正则 token\s*[=:]+\s*['"]... 会把 typeof cfg.githubToken === 'string'(类型检查)当成硬编码凭据报出来;function\s+\w{1,2}\( 会把 i18n 的 tr() 报成「函数名无法猜出含义」。这些都是真实误报——修的是审计代码(把判定从字符级提升到 token 级),而不是给业务代码加豁免注释。
全量审计按文件逐个跑检查,单文件约 40ms;文件数上万时(实测某检出目录 29921 个文件)总耗时会到分钟级,弱 CPU 机器上表现为「提交推送卡住不动」。降级策略:
| 环节 | 做法 | 效果 |
|---|---|---|
| 分词结果缓存 | lib/ast/tokenizer.js 对 tokenize() 结果做 LRU 缓存(上限 512 份) | 同一文件被 5 处检查重复分词 → 只算 1 次;单文件 139ms → 42ms |
| 文件数上限 | 新增配置 maxScanFiles(默认 3000,0 = 不限) | 29921 文件不再全量硬扫 |
| 变动文件优先 | 截断时先纳入 git status 里的变动文件,再按顺序补足到上限 | 正要提交的内容不会被截断漏审 |
| 截断告知 | 超限时产出一条 audit/scan-truncated 说明(severity: notice、scoreImpact: 0) | 明确告知「只审了多少 / 总数多少」,且不扣分 |
配置入口:侧边栏 → 审计 → 全量扫描文件上限,或 git-sluice audit <root> --full 时由插件配置读取。
截断只影响
scope: 'full'的全量扫描;默认的scope: 'diff'(只审本次变动)不受影响——日常提交推送走的就是 diff。
assets/preview.html 由 dsh-useful-tools 的 preview 工具生成(action=gen)(内联真实 client.js,只垫片宿主环境 window.__ModuleLoader__/react/settingsScope/fetch,界面与真实插件一致);用 assets/start.sh 启动本地反代服务访问(服务入口 ``preview 工具 action=serve(dsh-useful-tools);产物属生成物、不入库,缺失时生成器与 minihost 会自动生成一次):
./assets/start.sh start [--port 31000] # 启动(默认 30999;已有项目占用时用 --port 错开)
./assets/start.sh status / restart / stop
preview 工具(action=serve)反向代理——/api/git-push/* 全部转发到 DSH 真实后端(默认 http://127.0.0.1:30800 反代,--dsh 可覆盖),并自动完成 token 认证(--token > 环境变量 DSH_PREVIEW_TOKEN > 解析 dsh-proxy.log 兜底)。预览里的账号信息 / 本地仓库 / 云端仓库 / 规则包 / 审计结果 / 设置全部来自真实后端(读取与写入都真实)。?mock=1 切回内置假数据(改动只留页面内、不写文件);跨后端实测用 ?backend=http://127.0.0.1:端口。GET /preview-ping(start.sh 启动判定);PID 落 dsh-git-push.pid(插件根);日志 assets/preview-server.log(超 10MB 轮转)浏览器半侧的源码是 lib/client-parts/ 下的 13 个分片,lib/client.js 是拼接产物(2585 行)。改客户端代码只改分片:
lib/client-parts/00-loader.js loader + factory 头 + require + NS(必须首片)
01-const.js [1] 常量区(忙碌状态键/10 维度表/超时/样式串)
02-utils.js [2] 工具区(ensureCss/getJson/postJson/localGet/copyText…)
03-icons.js [3] 图标区
10-account.js [4] 账号信息 Tab
11-browser.js [5] 目录选择器
20-repo.js [6] 仓库管理卡(本地/云端仓库行、推送、可见性)
21-audit.js [7] 审计 Tab(权重行/规则行/规则包/注入开关)
22-settings.js [8] 设置 Tab(token/SSH/邮箱)
30-page.js [9] 页面装配(GitPushPage 三选项卡聚合)
40-controller.js [10] Controller:状态机 + 数据加载(884 行,跨两片)
41-actions.js [10] Controller:动作注入(269 行)
99-apply.js 收尾:apply/inject 导出 + factory 返回(必须末片)
改动流程(输入 → 处理 → 输出):
① 改分片 编辑 lib/client-parts/**.js(分片是**片段**,单文件 node --check 必然失败,
语法只对拼起来的产物才有意义)
② npm run build:client 按 PART_ORDER 拼接 → 写 lib/client.js(幂等:分片不变则产物逐字节不变)
③ npm run check 语法检查(跳过 client-parts)+ **产物新鲜度校验**:client.js 必须与分片拼出来的一致
④ (用 dsh-useful-tools 的 preview 工具 action=gen 重生成预览页),实际点三选项卡确认渲染与交互
lib/client.js:它是构建产物,下次构建即被覆盖,改动静默丢失;npm run check 会直接报「产物与分片不一致」。.gitignore 已忽略 lib/client.js):源码只维护分片,产物由构建生成。
安装侧靠 package.json 的 prepare(npm 安装/装 git 依赖时自动跑)与 prepack(打包/发布前)自动构建;
直接用 git 拉代码但没跑构建时,手动补一次 npm run build:client 即可(cli.mjs 与 lib/** 都不依赖产物,
只有浏览器半侧需要它——缺了就是设置页 UI 空)。scripts/build-client.mjs 的 PART_ORDER:顺序错会在运行时才炸(const 不提升),
且新分片必须登记进 PART_ORDER——未登记不会被拼进产物(构建脚本会报错拦下,不静默丢失)。client.js 头部注释):产物第一条语句必须是
window.__ModuleLoader__.load(...);全部代码在 factory 函数体内、文件顶层零声明;内部命名统一 dshgp_ 前缀。
构建脚本与 test/test-build-client.mjs 都会校验这三条。lib/client.js 逐字节一致(分片是原文的逐字子串,拼接零加工);
npm run check + test/test-build-client.mjs 共同守住这一点。重新生成预览页(改了客户端分片后):
npm run build:client # 先拼产物
(用 dsh-useful-tools 的 preview 工具 action=gen 重生成预览页)
渲染自检(改了客户端代码或预览生成器后必跑;把「改前端必须真的看一眼」变成一条命令):
PW_ROOT=<含 node_modules/playwright 的目录> \
CHROMIUM=<无头浏览器可执行文件> LD_LIBRARY_PATH=<运行库> FONTCONFIG_FILE=<字体配置> \
node scripts/frontend-preview-check.mjs --html "$PWD/assets/preview.html?mock=1" --out /tmp/frontend-check.png
--html 必须绝对路径(相对路径会让 page.goto 直接 ERR_INVALID_URL)。?mock=1 走预览页内置假数据;不带时页面 fetch 真后端、/repos-cloud 等返回 404,
会报「仓库列表没有 clone 按钮」这类假失败(看着像前端坏了,其实只是没数据)。dsh-git-push/audit)审计部分按独立包设计(对外契约冻结、依赖边界由机器门禁守住);当前形态不单独发包,用包子路径导出对外提供能力——将来若抽成独立包,消费方 import 路径不变或只改一行。
用法
import { auditWithScope, auditFull, summarize } from 'dsh-git-push/audit';
const { findings } = await auditWithScope('/path/to/repo', 'full'); // scope: diff | full
console.log(summarize(findings));
npm i dsh-git-push # 零运行时依赖(js-yaml 已内置 lib/vendor/)
稳定 API 面(冻结)
| 符号 | 用途 |
|---|---|
auditWithScope(repo, scope) | 按范围审计(diff / full,提交门禁用) |
auditFull(repo) | 全量审计 |
auditChanged(repo) | 仅改动集 |
auditFile(file) | 单文件审计 |
buildRuleSlotMap() | 规则槽位映射 |
summarize(findings) | findings → 结论汇总 |
formatAnalysisCoverageLine(...) | 分析覆盖行 |
未列入的符号(lib/checks、lib/rule、lib/score 等内部件)属内部实现,可随版本调整。稳定性承诺:上表符号只在 minor/major 版本增删。
完整流程(数据流)
调用方 → dsh-git-push/audit(门面 lib/audit/public.js,只再导出冻结面)
→ 收集文件(git ls-files + 忽略规则)
→ 规则加载(lib/rule/loader.js 动态发现 lib/audit-rules/*.yml 槽位,放一个 yml 即成为槽位)
→ 检查器(lib/checks/*:语法 / 复杂度 / 安全 / 凭据 / 结构 / 文档漂移 …)
→ findings(严重度 + 维度 + 扣分)→ 调用方自行处理,或调 summarize() 汇总
宿主交互靠注入,不靠反向依赖
「目录树漂移 / 函数列表漂移」属于宿主侧能力:审计不 import 仓库脚本,改由宿主加载 lib/app/host-doc-checks.js 注入(插件工具调用、提交门禁、独立 CLI 三处已接线)。未接线的环境(例如只依赖审计子路径的项目)会跳过这两类 finding,其余检查不受影响。
依赖边界由 test/test-audit-git-boundary.mjs 机器门禁守住:lib/audit/** 与 lib/core/** 不得引用 git 层 / 装配层 / 仓库脚本 / 宿主包(@deepseek-ai/*、cordis 等)。
设计与后续(抽成独立包的迁移路径)见开发者文档《审计独立包设计》。
账号信息区的仓库管理卡由「本地 / 云端」两标签改为「本地 / GitHub / NPM」三标签;NPM 页提供账号态、装包与已装依赖:
NPM 页包含
| 区块 | 内容 | 数据来源 |
|---|---|---|
| NPM 账号卡 | 登录用户(npm whoami)/ registry / 凭据是否配置 + 刷新 | GET /api/git-push/npm-account |
NPM 账号卡与 GitHub 账号卡同一款式:渐变面板 + 图标块(npm 字样)+ 标题/副标题 + 三态状态徽标
(已连接 / 校验未过 / 未配置)+ 勾选明细块(✅ 凭据可用、npm token 与 registry、whoami 结果)+ 底部刷新按钮与提示。
| 安装包 | 包名(多个用空格或逗号分隔,支持 @scope/name@版本)、安装目录、全局开关、--ignore-scripts 开关、二次确认、回执(日志路径 + stdout 摘要) | POST /api/git-push/npm-install |
| 已装依赖 | 目标目录 package.json 的依赖列表 + node_modules 是否存在 | GET /api/git-push/npm-packages |
完整流程(装包)
填包名(+ 选择安装目录,或勾选全局)→ 点「安装」→ 出现「确认安装(二次确认)」→ 点击后:
前端 POST /api/git-push/npm-install { names, dest|global, ignoreScripts, confirm: true }
→ 后端校验包名(拒绝 - 开头与路径穿越)与目录 → 加「进行中」锁 → 把 npm token 物化成 0600 独立 npmrc
→ spawn npm install(默认带 --ignore-scripts、--no-audit --no-fund、--userconfig 指向我们的 npmrc)
→ 结果与日志路径回执(日志落凭据目录 npm-install.log,0600)
安全默认(不可省):默认不执行安装脚本(--ignore-scripts,装包会触发 postinstall 任意代码);默认不全局(避免污染宿主 node 环境);安装必须二次确认;包名不接受 - 开头(防选项注入)与路径穿越;registry 与凭据只走插件自建 npmrc,不碰用户全局 ~/.npmrc。
设置里的 npm 凭据:设置 → 凭据与密钥 新增 npm token 与 registry 两个字段,保存走 settings-set;
token 与 GitHub token 存同一份 config.json(0600,写入走原子读改写,互不覆盖),接口只回派生布尔位与脱敏值,不回传明文。
插件在宿主装配系统提示词时注入四段(ctx.inject(['systemPrompt'], …).section({ name, order, text });text 必须同步返回——async 会让模型读到 [object Promise])。总开关在 设置 → 侧边栏 → Git 提交推送 → 审计 → 注入系统提示词,默认开。
| 段名 | order | 注入内容 | 生效条件 |
|---|---|---|---|
dsh-git-push-usage | 990 | 插件功能用法:各工具做什么、参数要点、调用纪律 | injectSystemPrompt |
dsh-git-push-env | 980 | 当前 cwd · 项目 git 根 · skills 总入口一行 · 工作区根 + 直接子目录 · 工具安装路径(实测探测) | injectSystemPrompt |
dsh-git-push-readme-check | 991 | 提交前必须核对 README(功能表/版本记录/用法)的提醒 | injectSystemPrompt |
dsh-git-push-requirements | 992 | 开发者特殊要求清单正文 | injectSystemPrompt + 审计开关 + injectRequirements |
环境段只给路径、不给正文:skill 只注入总入口一行(<projectRoot>/skills(存在:true/false)),不列 skill 文件清单、不注入 skill 正文——正文由 AI 按需读取,避免每步烧 token。工作区段给「根目录 + 直接子目录」(子目录跳过 .git / node_modules / dist / build / 隐藏目录),便于直接定位项目。
把常用工具的一句话用法连同凭据归属一起常驻:
· git_scan —— 列工作区(含额外路径)所有 git 仓库:分支/remote/未提交与未推送数/最近活动
· git_commit_push —— 一键提交并推送(审计同步拦截,通过后 commit+push 走宿主官方后台 job:立即返回 async:true+jobId,结果完成会自动返回、无需特意查询;如需主动查用宿主 job_output <jobId>)
· code_audit —— 审计仓库(L0 静态检查 + 质量评分),scope=full 全量,可传 ruleset / weights
· git_account_check —— 校验 GitHub 账号与凭据(token 在线校验 + SSH 公钥指纹)
· git_identity_rewrite —— 提交身份历史改写(非规范身份→登录账号规范身份;默认 dry-run,
真改写先建备份引用、自检通过才改写,push 用 force-with-lease;只处理本人远端仓库)
· git_sluice —— 浅包装 git 透传(AI 直接调用任意 git 命令,凭据自动注入):args 传与 git 一致的参数串,返回 status + stdout/stderr;git 的 log/diff/branch/tag 等其余能力用它
· git_clone / link_check —— git_clone 从 GitHub 拉仓库:target=owner/repo、dest=目标目录、branch=分支。
**默认带真实历史**:用 git fetch 取回原始对象,克隆结果与远端 HEAD 逐字节一致(可推回远端、可 git log 读演进),
耗时与体积随历史增长,`historyDepth=N` 可只取最近 N 条;**传 history=false** 才退回整树快照
(与远端无祖先、不能推回)。只读访问**默认走 gh-proxy 镜像**(写操作与带 token 的请求一律直连,
镜像不可用时自动回退直连(含网络失败、服务端故障、以及**镜像侧限流 403/429**));设 `DSH_GIT_MIRROR_PREFIX=off` 可关闭镜像
· git_gen_ssh_key / git_remote_create / git_set_visibility
【凭据由插件托管,不要到处找凭据】GitHub token 与 SSH 私钥存放在插件配置目录
(git-push/ 下 github-token、id_rsa;0600 权限),由插件的推送/校验流程自动读取与选择通道
(默认 SSH,token 401 回退 SSH)。判断登录态 → 调 git_account_check;推送 → 调 git_commit_push。
【调用纪律】提交类操作先 git_scan 确认目标仓库;提交前核对 README;审计 blocker 先修复再提交。
collectToolPaths() 用 which(Windows 走 where)逐项探测 git / node / npm / python3 / curl / ssh / unzip / rsync / 7z 的实际安装路径,只把探测到的工具写进注入文本;结果惰性缓存(首次注入算一次,避免每次装配系统提示词都 spawn 一轮)。探测异常时降级为静态兜底清单,注入不中断。
注入文本还带 运行主机:<主机名>(<局域网 IP>) 行(os.hostname() + os.networkInterfaces() 过滤回环/内网保留地址,多网卡全列,仅 IPv4)——AI 可直接拿到「当前跑在哪台机器、局域网地址」,用于跨机任务/给用户可访问地址。主机名探测异常时该行省略,注入不中断。
关掉「注入系统提示词」→ 四段全部返回空串(段仍注册、内容为空):AI 不再看到功能用法与环境目录,插件工具本身照常可用。切换开关会清掉环境注入缓存,下一轮装配即按新状态生效,无需重启实例。
injectFullSkill(注入全部 skill 正文)与 injectRepoIndexFull(注入 dsh-repo-index.json 全文)已移除:注入固定为目录级,不提供全量正文注入档位——长文正文交给 skill 按需加载。
设置 → 侧边栏 → Git 提交推送,三选项卡(对齐插件市场样式):
⟳ 重新检测
(配额剩余5000/h)):实时查 GitHub GET /rate_limit(不消耗配额),打开页面自动刷新(后端 60s 缓存,?refresh=1 强制刷新);Token/SSH 的登录名与校验时间只在凭据块内各列一遍,不重复展示.git 文件夹,含嵌套子仓库、depth 20);可手动指定路径(文本框 + 📂 目录选择器弹窗浏览),浏览器路径与扫描路径都记住(localStorage,刷新后恢复)。列表显示 路径 / 分支 · 远端子状态 / 未提交数 / 最近提交 + 索引登记;只显示登录同作者的仓库(有远端则 owner=登录账号;无远端按索引归属判定;无登录态时不过滤)。仓库「有远端 + 有未推送提交(ahead>0 或状态未知)」即可点 push(工作树脏不脏不影响);点击后行内绿/红反馈(✅ 推送成功 / ⚠️ 失败原因,含通道 push.reason);领先比较优先 live ls-remote(origin 为 https 时本地 fetch 常失败,过期的 origin/<分支> 缓存不再当真)。仓库路径长时自动省略号截断加载仓库列表 用 token 拉账号名下所有 GitHub 仓库(GET /user/repos,按最近更新),显示 名称 / 私有·公开 / 默认分支 / 最近更新;点行尾 clone 弹出目录选择器选目标目录后克隆(走 Git Data API,不直连 github.com)。克隆在服务端后台运行:提交后立即返回,进度条由轮询驱动,页面刷新后会自动接回仍在跑的任务注入系统提示词(默认开):控制整组注入段启停——功能用法(每个工具怎么用 + 凭据由插件托管)· 环境(工作区目录映射 + 工具安装路径 + skill 总入口一行)· 提交前 README 核对提醒;关闭后这些段全部返回空串,工具本身照常可用。详见 三、系统提示词注入↳ 注入开发者要求清单到系统提示词:挂在「提交前自动审计」下面,随时可勾选(一遍即可);审计关闭时该行只置灰表示「暂不生效」、勾选保留,实际是否注入由 host 侧 injectSystemPrompt && auditEnabled && injectRequirements 三重门控(省掉每次提交推送时 AI 被门禁拦下再回读清单的一轮往返)设置项以 lib/app/schema.js 的 Config 为单一事实源(lib/index.js 只再导出),settingsScope 读写。凭据保存同时写插件配置目录(见「凭据管理」)。
账号信息(token/SSH 有效性 + account-status.json 快照)与本地仓库列表(dsh-repo-index.json 索引)只在下面三种时机读取,不做轮询/不监听索引文件。读取一律纯离线读 json(秒级),网络操作只在需要时单独触发:
| 时机 | 账号信息 | 本地仓库列表 | 说明 |
|---|---|---|---|
| 插件启动时 | ✅ 离线读 json | ✅ 离线读 json | 侧边栏插件加载即读(模块级标记整页只执行一次),读的是 json 文件,不直接改 UI |
| 云端 push 完成后 | ✅ 离线读 | ✅ 离线读 | push 本身在线更新 json(重建索引 + 账号校验落盘),前端接着离线读回最新 |
| 手动刷新 | ✅ 重新检测 = 在线校验写 json,再离线读回 | ✅ 扫描 = 独立进程后台离线扫描,逐条追加 | 两个按钮都是「更新 json 后再读」,读取端仍走离线 json |
扫描全程不占前台、不卡界面,也不再一次性等全量扫完:
扫描 → 前端 POST /api/git-push/repos-local-scan,后端以 child_process.spawn(detached) 拉起独立进程 scripts/scan-repos.mjs(系统级后台,扫描 CPU 密集全在子进程,不拖宿主机)。响应立即返回,扫描中按钮禁用、不可重复点击(alreadyRunning 兜底)。--depth/--max 限性能,owner 用离线账号 json 比对,不联网):每登记一个仓库就 ① 递增写 scan-live.json(version +1、found 追加)、② 读-改-写把该仓库 entry 追加进 dsh-repo-index.json(不覆盖其他条目)。fs.watchFile 监听 scan-live.json,文件一变就唤醒等待者——前端 POST /api/git-push/repos-local-scan-wait { from: 已见数 } 挂起直到有新仓库,只返回「新增的那几条」(newest),前端只把这些追加进列表,不全量重读。非轮询:有新数据才返回。scan-live.json done:true → 前端收到收尾,恢复按钮并读一次索引对齐(补全领先/落后字段)。进度文件:$DSH_HOME/git-push/scan-live.json({ version, found:[仓库名…], done, startedAt })。
索引由独立进程逐仓追加(path 为该仓库真实本地路径),扫描结束即为最新;索引文件不为扫描而整篇重写。
扫描尊重 .gitignore(2026-09-16 修复):被 git 忽略的目录整棵跳过,不再登记为独立仓库——此前 DeepSeekHarness-NAS 的 /src/(官方源码)、/assets/、/build/master-build/(构建产物,内含独立 .git)会被误当仓库扫入。实现为每进入一个仓库根一次 git ls-files --others --ignored --exclude-standard --directory 取忽略目录集合,遍历时整棵跳过(单次 git 调用,全量扫描 ~0.6s)。
索引按本轮扫描结果收敛(同批修复):扫描结束会剔除「owner 一致但本轮未扫到」的条目(SCAN pruned …)——此前只追加/更新不删除,被 .gitignore 忽略后不再扫到的仓库会永远留在索引里。索引 = 本次扫描结果。
读取与写分离:启动 / push 后 / 渲染 → 全部离线读 json(毫秒级);push、重新检测 → 在线更新 json;扫描 → 独立进程离线扫描(逐仓写进度 + 追加索引,界面只追加新增)。三种读取时机都只读 json。
不监控索引、不轮询:读取全部由上面三个事件显式触发(startup / push 成功 / 手动按钮),页面内切 tab 不会反复刷新。
登录 = 或逻辑:ssh 或 token 任意一个有效即视为已登录(loggedIn = tokenValid || sshValid),账号 json 快照与在线校验都按此判定,username 取有效者。
默认扫描路径 = 本地仓库列表选择的路径:前端记住本地面板输入框的路径(localStorage dshgp-scan-path),启动读取与后续扫描都复用该路径;没有则后端自动识别 DSH 家根。
推送通道设置保留(pushMethod:ssh=推本地 HEAD / api=Git Data API 重建提交 / auto=有私钥走 ssh);defaultScanRoot/commitMessage 两项设置已移除(前者复用本地列表路径,后者留空由调用方/AI 生成)。
单测网络隔离:DSH_GIT_PUSH_OFFLINE=1 时 GitHub API 与 SSH 探测全部快速失败,测试不依赖真实网络(test-plugin.mjs 等)。
账号卡片与「自动生成的仓库索引」双向联动(2026-09-14,移植 v1 的 lib/repo-index.js 全量生成实现进 v2 lib/git/repo-index.js):
indexed(索引登记的 owner/repo/可见性)——即使本地未设 remote/上游,也能一眼看出它在 GitHub 的归属;未登记显示无git_commit_push 手动推送 与 账号卡片的 repo-push 推送成功后全量重建索引——可见性走 GitHub API(并发 4,token 缺失回退既有标注/未知)、skills 从 package.json dsh.skills / skills/*.md frontmatter 收集、localOnly 维护 workspace 顶层无远端目录;索引写入 工作区/dsh-git-push-User/<owner>/dsh-repo-index.json(权威源,dsh-repo-index skill 一致),版本+1、generatedAt 刷新、DO NOT EDIT加载仓库列表 也写索引(mergeCloudReposIntoIndex)——云端仓库登记进 dsh-repo-index.json(含 defaultBranch/pushedAt/description/visibility 云端真源、cloudOnly 标记本地无副本),本地已有副本的条目保留本地 path/skills 并刷新云端状态;本地列表透传 defaultBranch/cloudPushedAt/cloudOnly,前端显示「默认分支 / 云端更新 / 仅云端」——云端扫描一次,本地远端状态同步刷新侧边栏 UI 的规则包启停(写规则 yml 顶层 disabled: true / 删除该行)以命令行方式复用同一套实现(lib/rule/loader.js setSlotDisabled),不依赖 GUI。规则装载每次审计实时读 yml——改完立即生效、无需重启实例。
目标目录:默认操作安装版本(部署副本 <DSH>/.dsh-home/.dsh/profiles/web/node_modules/dsh-git-push/lib/audit-rules,即 GUI 实际加载的规则);--workspace 指工作区 lib/audit-rules;--target <目录> 任意指定。
用法:
node scripts/rule-switch.mjs list # 列出全部槽位状态(✔ 启用 / ✖ 禁用)
node scripts/rule-switch.mjs status <槽位> # 单槽位状态
node scripts/rule-switch.mjs disable <槽位> # 禁用(yml 顶层写入 disabled: true)
node scripts/rule-switch.mjs enable <槽位> # 启用(删除 disabled 行)
示例:
node scripts/rule-switch.mjs disable comment # 禁用安装版本的 comment 槽位(用户沟通词审计)
node scripts/rule-switch.mjs enable comment # 重新启用
边界:nodejs / private 属安全红线强制槽位,禁用会被拦截(返回错误、不写 yml),与 UI 行为一致。注意与 ``sync_plugin 工具(write:true) 的协作:同步会按工作区规则文件覆盖部署副本的 disabled 状态(工作区文件里没有 disabled 行则同步后恢复启用)。
会话输入框打 / 会弹出官方发现菜单。本插件注册 6 条只读命令:
| 命令 | 作用 | 参数 |
|---|---|---|
/git-audit | 审计仓库(规则 + 质量评分) | [路径] [--full] |
/git-scan | 列出各仓库分支 / 未提交 / 未推送 | [路径] |
/git-io-scan | 扫描脚本里读写文件的调用与路径,标四级风险 | [路径] [--write] |
/link-check | 检查文档内链接有效性 | [文件或目录] |
/git-account | 校验 GitHub 账号与凭据 | — |
/git-clone-preview | 预览 clone 将下载 / 跳过哪些文件(不落盘) | <owner/repo> [--branch 名] |
为什么只有只读命令:输入框一条命令就改远端(提交、建仓、改可见性)风险过高——写类操作仍走 agent 工具,会经过审计门禁、开发者要求清单与推送门禁。唯一的「远端交互」是 /git-clone-preview:它只读远端文件树并回报将下载什么,不下载、不落盘。
示例:
/git-audit 审当前会话工作区的本次变动
/git-audit /path/to/repo --full 指定仓库全量审计
/git-scan 扫默认扫描根(插件配置)
/git-io-scan --write 只看写类 I/O 的调用与路径
/link-check README.md 检查单个文档的链接
/git-clone-preview EIGHTfs/dsh-git-push
共同规则:
session.header.cwd,与指挥家按工作区分组同一字段);/git-scan 不带路径时用插件配置的默认扫描根/git-audit 的目标必须是 git 仓库(含 .git,或向上找到仓库根);非仓库直接拒绝——code_audit 对无 .git 目录会走全量 auditFull,扫家根会把进程打爆/git-io-scan 复用 scripts/scan-file-io.mjs(AST 四级分级,与审计 robustness/io-risk 同一标准),默认跳过注释行dsh-commands 协议)Host 注册走 ctx.inject(['commands']);无命令适配器的宿主静默跳过。改动需重启主实例后输入框才能看到。
脱离 DSH 独立运行(零第三方依赖,仅需 Node ≥18 与本机 git)。
git-sluice version 查看版本
git-sluice ruleset [槽位...] 编译规则包并输出统计
git-sluice scan <root> [--depth N] 全量扫描目录(非 git 目录可查)
git-sluice repos <root> [--depth N] [--max N] [--json]
扫描本地 git 仓库(尊重 .gitignore:被忽略目录整棵跳过)
git-sluice index <root> [--owner <账号>] [--depth N] [--max N] [--offline] [--json]
重建仓库索引 dsh-repo-index.json(--offline=纯离线不查 GitHub API)
git-sluice audit <root> [--full] [--level quick|standard|deep] [--ruleset <目录>] [--weights <JSON>] [--include-ignored] [--json]
git-sluice commit <repo> -m <msg> [--push|--no-push] [--dry-run] [--force] [--req-confirm] [--json]
git-sluice link-check <路径> 检查 md/文本中的链接有效性(只 warning)
git-sluice yaml-template 输出规则 yml 模板
git-sluice readme-template 输出 README 模板
git-sluice self-check 版本一致性 + HELP↔parseArgv 机器比对
CLI 是引擎的独立入口,功能与结果必须与插件一致——同一份实现、同一份配置、同一套参数:
repos → lib/git/repos.js 的 scanRepos(与插件本地扫描同函数);index → lib/git/repo-index.js 的 maintainRepoIndex;audit/scan → lib/audit/orchestrate.js 的 auditFull/auditWithScope。CLI 不另写一份逻辑。$DSH_HOME/git-push/config.json(经 readSettings + applySettingsToCfg,与插件启动回读同一映射),因此 maxScanFiles、规则包顺序 auditRuleOrder、禁用槽位 auditDisabledSlots、权重 weightOverrides 全部生效。--full(或目录非 git 仓库)走 auditFull,与插件 code_audit 的全量分支同路径;参数优先级同插件:显式 --weights > 配置 weightOverrides > 默认权重表。audit . --full 与插件 code_audit{repo,scope:'full'} 均输出 quality 76.8/B、summary {blocker:0, warning:388, notice:45, total:433}、findings 433 条。scope+depth,不带插件配置 → 跑了已禁用规则包、用默认权重与不同文件上限,表现为「CLI 全量扫描分更低、文件更多」。audit 参数与服务端设置对应:--full ↔ auditScanScope=full、--weights ↔ weightOverrides、--include-ignored ↔ 连 .gitignore 忽略的文件也扫。(2026-09-17:--level / --ruleset 已随设置项移除;--ruleset 仅作为当次调用的自定规则目录参数。)
v1.27~v1.44 曾内置 autoCleanCommentWording(提交前自动改写代码注释里的沟通残留措辞为中性描述),
v1.45.0 因「commentStartOf 字符串不感知」三次静默篡改事故(把测试夹具字符串里的 # 用户说… 当注释改掉)废除,
确立「只警告、不删改」总原则。改写表与审计共用 lib/audit-rules/audit-rules-comment.yml 顶层 rewrites(match/replace;审计只读 rules,不消费改写表)。脚本启动时从该 yml 装载:
插件不注册任何入口(不进 lib/、不注册工具/API/设置项),仅作为可执行脚本,供 AI / 用户手动调用;
脚本随插件发布,在安装副本目录里同样可跑(见「安装与要求」)。
node scripts/scrub-user-wording.mjs <路径...> # dry-run 报告(默认)
node scripts/scrub-user-wording.mjs <路径...> --apply # 逐条预览确认后写盘(每文件 .bak)
node scripts/scrub-user-wording.mjs <路径...> --apply --yes # 非交互强制全改(AI/CI 用)
node scripts/scrub-user-wording.mjs --repo <git仓库路径> [--apply [--yes]] # 只处理未提交 diff 涉及文件
退出码:0=无命中或已处理;2=dry-run 有命中;3=非交互环境未带 --yes 拒绝写盘。改写规则改 audit-rules-comment.yml 的 rewrites 即可,不必改脚本。
相比旧实现的关键修复(三次事故根因):
'# 用户说…'、"// 用户要求" 不会被误伤--apply 逐条 y/n/a/q 确认后才写盘(a=改余下跨文件、q=退出),每文件先写 .bak 备份dsh-skip-sensitive/dsh-skip-residue 整文件跳过;行尾含 dsh-skip-sensitive 本行跳过AI 调用建议:先跑 dry-run 看报告 → 人工/审计核对命中是否真是沟通残留(private 仓库的工作留痕措辞通常不需要清洗)→ 需要清洗时 --apply --yes。
三层审计管线的第三层——兜住静态盲区(跨文件引用、闭包捕获、异步时序),用运行时实测确认 L2 报告的「清空后访问」是否真的拿到 undefined/空。独立脚本,插件不注册入口 (脚本随插件发布,在安装副本目录里同样可跑,见「安装与要求」):
node scripts/audit-runtime-check.mjs <被测 js 文件> [--obj 对象名] [--verbose]
node scripts/audit-runtime-check.mjs --all <目录>
原理:动态 import 被测模块 → 找到导出的容器对象(对象/数组/Map/Set)→ 依次调用其清空方法(clear/reset/flush/purge)再调用访问方法(get/first/peek/at/shift/pop)→ 返回值是 undefined/null/空数组即命中。
退出码:0=全部通过(无运行时命中);1=存在运行时命中(L3 确认的 bug);2=无法检测(文件不可 import / 无导出对象 / 用法错误)。
局限(如实标注):只能测模块导出的入口(内部闭包需测试钩子);依赖被测文件能安全 import(副作用不能炸进程);异步时序建议用 node:test 写专门用例。
环境:DSH(DeepSeek Harness)|Node ≥18 |本机 git
安装(从 GitHub 源安装;公开仓库,匿名可装):
⚠️ dsh plugin --profile <名> add … 当前实测会挂死且零输出(两次都以 timeout 结束、日志为空)⇒
安装改在该 profile 目录里直跑 pnpm(dsh plugin 的设计是把参数转发给 profile 的 pnpm,两者本应等价):
cd <DSH_HOME>/profiles/<profile>
pnpm add github:EIGHTfs/dsh-git-push#<commit> # 用 commit 固定版本(远端暂无 tag)
两条前置条件(缺一即失败):
本机要有 npm —— pnpm 构建 git 来源的包时会在临时目录执行 npm install;
缺 npm 时报 ERR_PNPM_PREPARE_PACKAGE + spawn ENOENT: npm: command not found。
pnpm 11 默认禁止 git 源依赖执行构建脚本(供应链策略),而本插件有 prepare
(构建不入库的 lib/client.js)⇒ 必须先在 profile 的 pnpm-workspace.yaml 里放行,
否则报 ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED:
allowBuilds:
dsh-git-push@https://codeload.github.com/EIGHTfs/dsh-git-push/tar.gz/<commit>: true
⚠️ key 里带 commit 哈希 ⇒ 换版本/换提交要同步改这一行。
装完还要三步:profile package.json 的 dsh.profile.bundles 登记插件名 → 本插件 cordis.patch.yml
顶层 - insert: 新建 loader 行 → 重启宿主并在日志确认 loaded。
客户端产物不入库(C8):浏览器半侧源码是分片 lib/client-parts/**;lib/client.js 是构建产物,
已被 .gitignore 忽略。安装/拉取后若该文件缺失,跑一次 npm run build:client 即可补齐
(package.json 的 prepare 会在 npm 安装与装 git 依赖时自动构建,prepack 覆盖打包/发布;
cli.mjs 与 lib/** 都不依赖该产物——缺了只影响设置页 UI)。
随插件发布的脚本:scripts/ 在发布白名单内(package.json 的 files 的 SYNC_ENTRIES 两处一致,由 test-self.mjs 的「SYNC_ENTRIES 覆盖 files 白名单」测试守住),装好插件后 7 个脚本在安装副本目录内同样可直接运行(零外部依赖,只用 node 内置模块):
scripts/build-client.mjs:客户端分片拼接(PART_ORDER 顺序拼接 + --check 一致性门禁 + 形态铁律自检;见「客户端分片构建」)scripts/scan-version.mjs:版本一致性自检(lib/self 的 VERSION ↔ package.json version ↔ README 版本列表 ↔ cli HELP 模板),不一致 exit 1scripts/audit-runtime-check.mjs:三层审计的 L3 运行时检测(见「独立脚本:运行时检测」)scripts/scrub-user-wording.mjs:清洗注释里的沟通残留措辞(见「独立脚本:清洗用户沟通措辞」)scripts/check.mjs:全仓语法检查(node --check 批量)sync_plugin 工具,默认 dry-run)。安装位置 = local-plugins/<插件>(真源);node_modules/<插件> 只是解析入口,由 DSH/pnpm 安装流程按 profile 的 file:local-plugins/<插件> 声明生成——本脚本不建链、不改链(并会报警「node_modules 下的副本内容与真源不一致」这种会顶掉真源的形态,实测过旧副本顶掉新版;与真源同 inode 的硬链接副本属正常安装产物、不报警)。2026-10-09 起同时做部署形态与免重启热重载自检:--profile <名> 指定 profile(多 profile 时必须显式给,否则报所有候选而不是默默取首个)、--fix 只修 local-plugins 侧形态(解软链 / 建真实目录);每次都报告「该插件改代码能否免重启热重载」(读 profile 的 cordis.patch.yml 里 id: hmr 的 base/root)以及 profile 依赖声明是否该写 file:local-plugins/<插件>dsh-useful-tools/lib/core/plugin-sync/);引用,非独立入口)测试:npm test 一条命令复现全绿(2026-10-09 实测 1195 用例 / 1193 通过 / 0 失败,2 跳过)
npm test 走 test/run-tests.mjs:按「测试文件 + 其传递依赖闭包的内容哈希」判断哪些测试
没变过、上次又通过,直接跳过;实测 102s → 9.3s(92/100 个文件命中缓存,只真跑 8 个)。
npm test # 默认:用缓存(未变更且上次通过的纯本地测试跳过)
node test/run-tests.mjs --dry-run # 只报告「会跑哪些/跳过哪些/为什么」,不执行测试
node test/run-tests.mjs --all # 忽略缓存,全部真跑(交付前门禁)
node test/run-tests.mjs --stats # 打印每个文件「跑/跳过」的原因
安全模型(宁可少跳过,不可漏跑):
| 机制 | 说明 |
|---|---|
键 = 测试文件 + 传递依赖闭包 + package.json + node 版本 | 依赖一变(含版本号)→ 键变 → 必重跑 |
| 整仓不变式测试常跑 | 文件清单/版本表/函数表/架构事实这 8 个测试(test-doc-func/test-doc-version/test-tree-doc/test-func-doc-drift/test-arch-*/test-inject-system-prompt)永不跳过 —— 它们才是「新增文件忘了登记」的守门人(闭包哈希刻画不了「整仓当前状态」) |
| 联网判据 | 只看测试文件自身(先剥离注释与字符串,避免夹具示例误判):真实 await fetch(/createServer(/.listen(/net.connect( → 不缓存。本仓库测试均为注入 fetcher 或进程内 handler(见 test-link-check.mjs 头部) |
| 失败只失效「本轮跑过的文件」 | 不搞「一处失败全清」:被跳过的文件保持命中,下次只重跑可能出问题的那批 |
| 缓存损坏/版本不符 | 按空缓存处理,绝不因缓存本身报错 |
缓存文件 .test-cache/results.json(已 gitignore,不入库)。
scripts/platform-scan.mjs)独立工具,可对任意仓库跑:找出「只在 Linux/macOS 能跑」与「只在 Windows 能跑」的代码, 并区分代码(会真炸)与注释(只是说明,降级为提示);同时统计已做平台分支的正面写法。
node scripts/platform-scan.mjs <目标目录> # 文本报告(按类别分组 + 文件 top)
node scripts/platform-scan.mjs <目标目录> --json # 机器可读(file/line/rule/category/severity/snippet)
node scripts/platform-scan.mjs <目标目录> --strict # 发现「代码里的平台专属写法」→ 退出码 1(可做 CI 门禁)
判据(把实测踩过的坑固化成规则,节选):
| 类别 | 例子 |
|---|---|
| 只在 POSIX 成立 | 硬编码 /tmp·/dev/null、sh -c 与 execFileSync('sh', ['-c', …])、POSIX 专有命令(chmod/sed/which…)、PATH.split(':')(Windows 用 ;,会永远找不到可执行文件却报成「找不到 git」)、硬编码 /usr·/etc、符号链接、sudo、~/.ssh 字面量 |
| 只在 Windows 成立 | 硬编码盘符 C:\…、cmd /c/powershell、.exe/.bat/.cmd 字面量、where/tasklist/wmic、%VAR%、path.win32 |
| 已平台分支(正面) | process.platform === 'win32'、os.platform()、os.tmpdir()、path.delimiter、path.join/resolve/sep |
实测(2026-10-08):本插件仓库 298 个文件 → 130 条命中(POSIX 专属 73 / Windows 专属 38 / 已分支 19),
其中代码里的 94 条多为测试夹具里的 /tmp·/usr/bin 字符串(本仓库测试是内存键/临时目录隔离,不真用这些路径);
dsh-codegraph 52 个文件 → 159 条(Windows 专属 14:c:/windows 保护目录清单、.bat 启动器、C:\ 断言)。
定位说明:这是线索扫描器,不是判决器 —— 夹具字符串里的路径也会命中(按注释/代码分层提示), 最终由人判断;跨平台正确写法不会被判为问题。
compileRule 主体永不修改lib/vendor/,见版本记录),files 白名单含 cli.mjs,npm test 一条命令可复现ghp_testtokenplaceholder123),无真实凭据入库FAQs
DSH git 自动提交推送插件——统一函数入口架构(规则/审计/git/自身/侧边栏/评分/豁免/上下文/HTTP/测试十大总入口)
The npm package dsh-git-push receives a total of 0 weekly downloads. As such, dsh-git-push popularity was classified as not popular.
We found that dsh-git-push demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.

Security News
Cloudflare is acquiring Deno’s team, which will provide another year of bug fixes and security updates before ending support for the runtime.

Security News
Anthropic’s free OSS Scanner uses Mythos and other Claude models to find open source vulnerabilities and send maintainers reports with proposed fixes.

Security News
On Front Lines’ Early Adopters: CISO podcast, Andrew Becherer shares lessons from Datadog, weighs the long-term costs of AI-built tools, and explains how founders can actually gain a CISO’s trust.