New:Introducing Socket Scanning for VS Code Marketplace Extensions.Learn more →
Get Started

dsh-git-push

Package Overview
Dependencies
Maintainers
1
Versions
10
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

dsh-git-push

DSH git 自动提交推送插件——统一函数入口架构(规则/审计/git/自身/侧边栏/评分/豁免/上下文/HTTP/测试十大总入口)

latest
Source
npmnpm
Version
2.9.9
Version published
Weekly downloads
0
Maintainers
1
Weekly downloads
 
Created
Source

dsh-git-push

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 等
  • 直接说人话即可:「扫描我的仓库」「审计 Pawchive」「提交推送 xx 仓库」

② 独立 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

③ 侧边栏面板

  • 审计面板:22 个规则包开关/排序/命中数
  • 设置:凭据 / SSH 公钥 / 审计开关与权重

目录

折叠说明:本文档的长章节(代码审计 / 系统提示词注入 / 独立 CLI / 安装与要求)默认收起, 点章节内的「展开」即可查看全文;标题本身保留,目录锚点照常可用。

分体式文档(docs/)

长文档不直接内嵌 README,各自存独立 md(README 仅链接引用),由 doc- 前缀脚本自动维护:

文档位置维护脚本说明
版本列表docs/CHANGELOG.mdscripts/doc-version.mjsgit log 聚合版本表(gen/apply/check)
函数列表docs/FUNCTIONS.mdscripts/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/功能-审计规则体系.md22 个规则槽位 / 165 条规则的组织方式、作用域字段、三层结构、运行入口、结果怎么读、怎么豁免
docs/功能-历史提交审计.md逐提交回放审计:解决什么、怎么跑、与普通审计的差异与成本
docs/功能-文档与结构追踪.mdtree-doc / doc-func / doc-version 三份自动生成文档怎么更新、漂移怎么办
docs/功能-仓库索引与账号状态.mddsh-repo-index.json 与 account-status.json 的写入时机、读取入口、统一收口约定
docs/DETAILS-EXEMPT-AND-RULES.md豁免注释与规则 yml 的写法全录(参考手册)

功能总览

插件围绕 DSH 日常开发的高频动作,分两大块——先讲提交推送(GitHub + npm),再讲代码审计。 下面每章都可折叠:长章节默认收起,点章节内的「展开」即可看全文。

一、提交推送(GitHub + npm)

功能块做什么入口
GitHub 提交推送token / SSH 密钥管理、提交、推送、clone、建仓、可见性切换、force 强推、版本历史、提交身份自动用登录账号(未配身份的仓库自动写入局部配置)、推送前自动判定正确的 remotegit_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 命令。

凭据管理

  • Token:GitHub token(ghp_ / github_pat_ 开头),保存即写入插件配置目录 credentialsDir()/github-token(0600 权限),不落 settings.yaml 明文
  • SSH 公钥:保存写入 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 能力(账号 / 安装 / 发包)

能力说明
npm_publishnpm 发包(后台 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 仓库列表同款行)

提交身份(自动带登录账号,AI 不用猜)

提交必须带身份;仓库没配时 git 会直接以 Author identity unknown 拒提交。插件按下列优先级决定身份, 并在未配身份时把账号身份写进该仓库的局部配置(git config --local;只改该仓库 .git/config,不入库、不动全局):

  • 仓库已配 user.name + user.email → 原样尊重(不覆盖项目/用户自己的选择)
  • 未配(或只缺一侧) → 用登录的 GitHub 账号: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 持久化
  • 并发与去重:同时只跑一个推送 + 同回合只触发一次 + 防抖
  • 阻断标记(❌ / ⚠️ 未完成)不触发;无完成标记不触发

二、代码审计

展开:审计入口 / 扫描忽略语义 / 规则引擎 / 目录结构 / 代码架构 / 10 维度评分 / 豁免机制 / 禁用户沟通词 / 链接检查 / AST 精筛

提交前自动审计 + 独立全量扫描,规则可扩展,质量可评分。

审计入口

  • auditChanged:变动范围(git diff)——提交前默认
  • auditFull:全量扫描(非 git 目录可查)
  • code_audit 工具 / git-sluice audit CLI:强度、规则包、权重全覆盖

扫描忽略语义(黑名单初筛 + 白名单补充)

全量/变更扫描的目录跳过分三层(lib/skip-dirs.js 统一):

  • 硬编码基线(只允许 node_modules、.git)——机器依赖/内部元数据,绝对跳过,不受 gitignore 影响;
  • yml 黑名单关键词(规则 yml 的 exclude_dirs 并集,如 folder 规则的 dist/build/vendor/.dsh/.trash 等)——候选跳过,但若 gitignore 用 ! 白名单恢复了该目录(如 server/project/* + !server/project/blueprint/、/build/* + !/build/keep/),则保留进入(黑名单不压过白名单);
  • gitignore 忽略判定(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 仓库:走 git check-ignore -c core.excludesFile,语义与 git 100% 一致
  • 非 git 目录(2026-09-18 新增兜底):解压的源码包、临时导出目录、未 git init 的工程同样生效——改用纯 JS 匹配器 lib/audit/gitignore-match.js(零依赖,语义逐条与真 git 对拍,见 test/test-gitignore-match.mjs)。此前这类目录下 .auditignore 形同不存在,同一个规则在 git init 前后行为相反
  • 与 .gitignore 叠加生效(各自独立、互不覆盖):.gitignore 管「不入库」,.auditignore 管「不入审计」
  • 豁免的文件依旧能入库——.auditignore 只作用于审计扫描,不写进任何 git 配置,git add 照常跟踪
  • CLI 与插件天然一致:git-sluice audit / 插件 code_audit 共用同一 collector,同一份 .auditignore 双端生效
  • 与 yml exclude_dirs 黑名单的区别:yml 黑名单是全局规则(所有仓库都跳);.auditignore 是仓库级(仅本仓库豁免,且仍可入库)

新增跳过目录一律改 yml(exclude_dirs),不改代码。要调整各层行为见 lib/skip-dirs.js 顶部注释。

规则引擎(yml 管理)

规则槽位由目录文件驱动:目录里每个 audit-rules-<名>.yml 即一个槽位,放文件即生效、删文件即移除,无需改代码。内置 22 个槽位:

槽位规则数检查内容
nodejs37凭据硬编码 / 路径穿越 / 魔数 / 依赖 / 异步等
java7Java/Kotlin 专属:短名 / 魔数 / 嵌套 / 方法长度 / 文件长度 / 注释密度 / 圈复杂度(exts: [java, kt],2.1.0 新增)
python7Python 专属:短名 / 魔数 / 嵌套 / 函数长度 / 文件长度 / 注释密度 / 圈复杂度(exts: [py])
go / rust / swift / cpp / php各 0(占位)语言专用规则占位槽位——放 yml 即生效,规则待补(AST 语言路由已预留,2.1.0)
frontend19前端安全 / a11y / 依赖
npm12依赖声明 / npmrc 凭据 / 测试入口 / 包版本语义(npm/version-format-triple 只查 package.json、npm/version-commit-mismatch)
version0已撤销:原 5 条全是自家提交/发布纪律(「一次提交=一个小版本」等),不该固化成对任何仓库生效的审计规则——纪律留在 skill(versioning-rule / git-commit-discipline);其中 2 条 npm 通用约定迁入 npm 槽位
dsh7DSH 插件契约 / 注入通道(仅 dsh- 前缀插件项目加载——非 dsh 项目 require node 内置不误报,2.1.2)
comment6注释措辞 / 对话残留
folder6目录总数 / 单目录文件数 / 解包特征 / .gitignore / cd 到可能不存在的目录 / 写文件到 .gitignore 忽略目录
i18n3硬编码文案 / 插值 / 语言包
performance2memory-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/ 各文件夹各司其职

分层速查文档:lib/ARCHITECTURE.md(三层审计架构四层落地位置:规则声明 → AST 实现 → 检查包装 → 编排调度)

lib/ 下每个文件夹只负责一件事,改审计逻辑前先分清所属层,避免在错误的层里打补丁 (尤其不要用「跳过某类行」的补丁去修误报):

层位置职责
① 规则声明lib/audit-rules/*.yml阈值 / severity / 豁免清单 / 上下文关键字 / astConfirm 开关——改阈值先改 yml,不改代码
② 具体实现(AST)lib/ast/*.jstoken 级精准判断:轻量 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/*.jsyml 字段类型 → 编译函数(注册制,按维度分模块;compilers.js 只做引用)
— git 能力lib/git/*.js命令执行 / 凭据 / GitHub API / 传输(SSH+API)/ 提交推送 / 克隆 / 仓库与可见性 / 账号校验
— 规则装载lib/rule/*.js规则加载 / 编译 / 注册(yml → 编译后规则对象)
— 评分lib/score/index.js10 维度对数衰减评分 + 权重(本目录只放评分,不含 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 必须为空;
  • 裸副作用 import 保留——如 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 加一行调度。

两层判定:正则初筛 → AST 精准判断

文本型检查统一采用两段式(astConfirm: true 开启):

正则初筛(快)         AST 精筛(准)
pattern 扫全文          makeCodeLineFilter(text, 候选行)
→ 得到候选行号列表   →   token 级确认「命中行确实是代码行」
                        注释 / 字符串 / 模板串行 → 丢弃(不是硬编码)
  • 为什么两段式:正则快但无法区分代码与注释/字符串(单用必然误报);tokenizer 准但全量 token 化成本高于正则。两段式 = 正则筛候选行 → 只对候选行做 token 判定。
  • 典型收益:注释里的版本号/日期(// v1.8.0、2026-09-13)、字符串里的 CSS 字号('.x{font-weight:650}')、i18n 字典值不再报——无需任何「跳过注释行」的补丁。
  • 不适用:凭据/敏感/对话残留类规则不加 astConfirm(这些恰恰要查注释里的内容,例如注释里贴的 token、// TODO 修复)。
实现方式位置例子
正则初筛 + AST 精筛yml 的 astConfirm: true + makeCodeLineFilterreadability/magic-number
纯 token 级(无需正则)lib/ast/(各模块,见上表)checkMagicNumberSmartAst / checkSyncFs / checkEmptyCatchAst / checkComplexityAst / checkNestingDepthAst / checkNameLengthAst / checkFuncLinesAst / checkRepeatedStringsAst / checkClearAccessAst
纯正则(本质是文本特征)lib/checks/regex.js 的 checkRegexRules凭据硬编码、路径穿越、对话残留、黑名单

三层审计管线(2026-09-14:L1 正则初筛 → L2 AST 数据流 → L3 运行时)

按检测模式的成本分层,解决「正则命中面宽但 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() } 保护模式)
  • 真实跨分支/异步时序无法静态确定 → 交给 L3 运行时确认

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=无法检测。

10 维度质量评分

可读性 / 可维护性 / 健壮性 / 安全性 / 性能 / 测试覆盖 / 可观测性 / 可部署性 / 文档 / 开发者体验,默认合计 100,可在侧边栏调权重(weightOverrides JSON)。

  • 单维度评分对数衰减防零分塌陷:max(0.1, 10 - k*ln(1+errorCount)),k 按维度分级(安全性 1.8 衰减最快)
  • 总分 = Σ(维度得分×权重)/Σ权重×10;A/B/C/D/E 五档

审计范围(固定完整流程,无强度档位)

每次审计都跑完整的静态初筛 + 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 / scripts 刻意用法)

  • test/ 目录下文件:residue / console-log / sync-fs / empty-catch / performance 类问题自动豁免
  • scripts/ 目录与 cli.mjs:residue / console-log / sync-fs 自动豁免

④ 私有库豁免(private 槽位按远端可见性分级)

仓库跟踪到私密文件(清单见 audit-rules-private.yml:**/id_ed25519、**/.ssh/**、**/.env、**/.npmrc 等)时按远端可见性分级:

  • public → blocker 拦截提交(私钥/凭据已可被任何人获取,必须移除或转私有)
  • private / unknown → 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 文档里的沟通措辞(如触发场景描述)是设计文本而非代码残留,不触发用户沟通词规则。

代码禁用户沟通词(Block 拦截)

侧边栏 → 审计选项卡开关「代码禁用户沟通词」,默认开启:代码注释/文档出现「用户说/用户要求/用户原话」等沟通残留措辞(黑名单见 audit-rules-comment.yml)→ blocker 拦截提交;白名单业务词(用户ID/用户登录/用户角色等)命中则整行豁免。规则文档与测试目录按上述豁免机制自动放行。

链接检查

扫描 md/文本中的 URL 并访问验证(404/403→-3、DNS→-2、超时→-1 分级扣分),只 warning 永不 blocker(网络不可靠防假阳性拦截)。

正则初筛 → AST 精筛(astConfirmKind)

审计的每条规则(lib/audit-rules/*.yml)先跑正则初筛拿到候选行,再由 lib/ast/ 里的 AST 实现做语义确认——正则快但看的是字符,AST 慢但看的是结构,两层配合才能既不漏报又不误报。

规则通过 astConfirmKind 声明「这条规则命中后还要精筛什么」,lib/checks/regex.js 按名字分派到对应 AST 实现(yml 是规则、lib/ast/ 是实现、lib/checks/ 是调用,各层各司其职):

astConfirmKindAST 实现精筛语义豁免(不报)的例子
small-file-readcheckSmallFileReadAst读文件是否属受控小文件(配置/缓存/字典)读 package.json、locale 字典、cache 文件
short-func-namecheckShortFunctionNameAst函数名是否真过短且非公认缩写tr/t/L(i18n)、el/cb/fn
credential-valuecheckCredentialRefAst凭据标识符右侧是否直接是有效字面量类型检查 typeof cfg.token === 'string'、透传 cfg.token = init.token、process.env.KEY、占位符
shell-cd-dynamicshellCdDynamicLinescd 目标是否动态路径(含 $VAR/$())且无失败兜底(同行无 ||、非 && 链、非注释/字符串)cd "$(dirname "$0")" 自我定位(目录必然存在)、cd "$X" || exit 1 有兜底、cd dist 字面量路径
write-into-gitignoredwriteIntoGitignoredLines写操作(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 级),而不是给业务代码加豁免注释。

展开:大仓库性能降级 / 界面预览页 / 审计能力可被外部依赖(audit 子路径导出)/ 账号信息里的 NPM 面板

大仓库性能降级

全量审计按文件逐个跑检查,单文件约 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,真实后端数据)

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
  • 完全真实后端数据:dsh-useful-tools 的 preview 工具(action=serve)反向代理——/api/git-push/* 全部转发到 DSH 真实后端(默认 http://127.0.0.1:30800 反代,--dsh 可覆盖),并自动完成 token 认证(--token > 环境变量 DSH_PREVIEW_TOKEN > 解析 dsh-proxy.log 兜底)。预览里的账号信息 / 本地仓库 / 云端仓库 / 规则包 / 审计结果 / 设置全部来自真实后端(读取与写入都真实)。
  • 离线调试:URL 加 ?mock=1 切回内置假数据(改动只留页面内、不写文件);跨后端实测用 ?backend=http://127.0.0.1:端口。
  • 全部可点:三选项卡切换 · 审计开关 · 注入系统提示词开关 · 「注入开发者要求清单」子开关(含置灰联动)· 规则包启停与 ↑↓ 调序 · 权重编辑 · token/SSH 保存 · 邮箱一键生成 SSH 并回填
  • 健康检查 GET /preview-ping(start.sh 启动判定);PID 落 dsh-git-push.pid(插件根);日志 assets/preview-server.log(超 10MB 轮转)

客户端分片构建(lib/client-parts/ → lib/client.js)

浏览器半侧的源码是 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-modules 聚合 bundle 兼容,见 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 按钮」这类假失败(看着像前端坏了,其实只是没数据)。
  • 判据(任一不满足即非零退出):云端标签 → 仓库列表 → 行内 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 等)。

设计与后续(抽成独立包的迁移路径)见开发者文档《审计独立包设计》。

账号信息里的 NPM 面板(本地 / GitHub / NPM 三标签)

账号信息区的仓库管理卡由「本地 / 云端」两标签改为「本地 / 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-usage990插件功能用法:各工具做什么、参数要点、调用纪律injectSystemPrompt
dsh-git-push-env980当前 cwd · 项目 git 根 · skills 总入口一行 · 工作区根 + 直接子目录 · 工具安装路径(实测探测)injectSystemPrompt
dsh-git-push-readme-check991提交前必须核对 README(功能表/版本记录/用法)的提醒injectSystemPrompt
dsh-git-push-requirements992开发者特殊要求清单正文injectSystemPrompt + 审计开关 + injectRequirements

内容只到「目录级」

环境段只给路径、不给正文:skill 只注入总入口一行(<projectRoot>/skills(存在:true/false)),不列 skill 文件清单、不注入 skill 正文——正文由 AI 按需读取,避免每步烧 token。工作区段给「根目录 + 直接子目录」(子目录跳过 .git / node_modules / dist / build / 隐藏目录),便于直接定位项目。

功能用法段(解决「AI 不知道插件有什么、绕开插件自己找凭据」)

把常用工具的一句话用法连同凭据归属一起常驻:

· 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 提交推送,三选项卡(对齐插件市场样式):

  • 账号信息:渐变卡片 + GitHub 图标 + 状态徽标(已连接/检测中/未连接)+ 检测结果块 + Token/SSH 凭据状态标签 + ⟳ 重新检测
    • 凭据块 Token 行尾显示 API 配额剩余(如 (配额剩余5000/h)):实时查 GitHub GET /rate_limit(不消耗配额),打开页面自动刷新(后端 60s 缓存,?refresh=1 强制刷新);Token/SSH 的登录名与校验时间只在凭据块内各列一遍,不重复展示
    • 卡片下方为仓库管理卡片(本地 / 云端 两子选项卡,2026-09-14):
      • 本地:默认扫描根 = DSH 家根(由 DSH_HOME / workspaceRoot 动态推导,非写死)——覆盖 工作区 / 用户 / profiles / workspace 下全部 git 仓库(遍历所有 .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)。克隆在服务端后台运行:提交后立即返回,进度条由轮询驱动,页面刷新后会自动接回仍在跑的任务
  • 审计:审计开关 + 注入系统提示词开关 + 代码禁用户沟通词开关 + 10 维度权重编辑 + 规则包列表
    • 注入系统提示词(默认开):控制整组注入段启停——功能用法(每个工具怎么用 + 凭据由插件托管)· 环境(工作区目录映射 + 工具安装路径 + skill 总入口一行)· 提交前 README 核对提醒;关闭后这些段全部返回空串,工具本身照常可用。详见 三、系统提示词注入
    • 子开关 ↳ 注入开发者要求清单到系统提示词:挂在「提交前自动审计」下面,随时可勾选(一遍即可);审计关闭时该行只置灰表示「暂不生效」、勾选保留,实际是否注入由 host 侧 injectSystemPrompt && auditEnabled && injectRequirements 三重门控(省掉每次提交推送时 AI 被门禁拦下再回读清单的一轮往返)
    • 规则包行:↑↓ 调次序 · 按住行内信息区悬停显示详情浮层(描述/作者/规则条数口径)· 启停只点行尾按钮
    • 状态底色一眼可辨:启用 = 绿底 + 绿左条,禁用 = 红底 + 红左条(按钮同为绿/红实色胶囊)
    • 拦截级/警告级/提示级 三列显示该规则包内各严重级的规则条数(取自 yml,三档之和 = 规则总数;与是否跑过审计无关)
  • 设置:GitHub token + SSH 公钥 + 邮箱 + 一键生成并复制

设置项以 lib/app/schema.js 的 Config 为单一事实源(lib/index.js 只再导出),settingsScope 读写。凭据保存同时写插件配置目录(见「凭据管理」)。

账号信息 / 本地仓库列表:读取时机(2026-09-16 收敛)

账号信息(token/SSH 有效性 + account-status.json 快照)与本地仓库列表(dsh-repo-index.json 索引)只在下面三种时机读取,不做轮询/不监听索引文件。读取一律纯离线读 json(秒级),网络操作只在需要时单独触发:

时机账号信息本地仓库列表说明
插件启动时✅ 离线读 json✅ 离线读 json侧边栏插件加载即读(模块级标记整页只执行一次),读的是 json 文件,不直接改 UI
云端 push 完成后✅ 离线读✅ 离线读push 本身在线更新 json(重建索引 + 账号校验落盘),前端接着离线读回最新
手动刷新✅ 重新检测 = 在线校验写 json,再离线读回✅ 扫描 = 独立进程后台离线扫描,逐条追加两个按钮都是「更新 json 后再读」,读取端仍走离线 json

本地「扫描」:独立进程后台 + 只读新增 diff(2026-09-16)

扫描全程不占前台、不卡界面,也不再一次性等全量扫完:

  • 点 扫描 → 前端 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 等)。

仓库索引联动(dsh-repo-index.json)

账号卡片与「自动生成的仓库索引」双向联动(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
  • 云端扫描写索引(2026-09-16):账号卡片「云端」加载仓库列表 也写索引(mergeCloudReposIntoIndex)——云端仓库登记进 dsh-repo-index.json(含 defaultBranch/pushedAt/description/visibility 云端真源、cloudOnly 标记本地无副本),本地已有副本的条目保留本地 path/skills 并刷新云端状态;本地列表透传 defaultBranch/cloudPushedAt/cloudOnly,前端显示「默认分支 / 云端更新 / 仅云端」——云端扫描一次,本地远端状态同步刷新
  • 索引缺失/损坏全链路静默降级,不阻塞扫描与推送

独立脚本:规则启用/禁用(scripts/rule-switch.mjs)

侧边栏 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 不带路径时用插件配置的默认扫描根
  • 未分类(cwd 空)必须写路径,否则报错退出,不会扫 DSH 家根
  • 相对路径接到会话 cwd;无 cwd 时相对路径不可用,改给绝对路径
  • /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']);无命令适配器的宿主静默跳过。改动需重启主实例后输入框才能看到。

独立 CLI(git-sluice)

展开:CLI 用法 / 与插件「功能一致、结果一致」的约定

脱离 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 与插件「功能一致、结果一致」(2026-09-16 收敛)

CLI 是引擎的独立入口,功能与结果必须与插件一致——同一份实现、同一份配置、同一套参数:

  • 同一实现:repos → lib/git/repos.js 的 scanRepos(与插件本地扫描同函数);index → lib/git/repo-index.js 的 maintainRepoIndex;audit/scan → lib/audit/orchestrate.js 的 auditFull/auditWithScope。CLI 不另写一份逻辑。
  • 同一配置:CLI 读同一份 $DSH_HOME/git-push/config.json(经 readSettings + applySettingsToCfg,与插件启动回读同一映射),因此 maxScanFiles、规则包顺序 auditRuleOrder、禁用槽位 auditDisabledSlots、权重 weightOverrides 全部生效。
  • 全量走同一入口:--full(或目录非 git 仓库)走 auditFull,与插件 code_audit 的全量分支同路径;参数优先级同插件:显式 --weights > 配置 weightOverrides > 默认权重表。
  • 结果实测一致(同一仓库同一参数):CLI audit . --full 与插件 code_audit{repo,scope:'full'} 均输出 quality 76.8/B、summary {blocker:0, warning:388, notice:45, total:433}、findings 433 条。
  • 修复前的差异根因:CLI 只传 scope+depth,不带插件配置 → 跑了已禁用规则包、用默认权重与不同文件上限,表现为「CLI 全量扫描分更低、文件更多」。

audit 参数与服务端设置对应:--full ↔ auditScanScope=full、--weights ↔ weightOverrides、--include-ignored ↔ 连 .gitignore 忽略的文件也扫。(2026-09-17:--level / --ruleset 已随设置项移除;--ruleset 仅作为当次调用的自定规则目录参数。)

展开:清洗用户沟通措辞脚本 / 运行时检测(三层审计 L3)脚本

独立脚本:清洗用户沟通措辞(scrub-user-wording.mjs)

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 即可,不必改脚本。

相比旧实现的关键修复(三次事故根因):

  • 词法感知:逐字符扫描区分「字符串字面量 / 注释 / 代码」,只改写注释段——字符串里的 '# 用户说…'、"// 用户要求" 不会被误伤
  • md 文档跳过 ``` 围栏代码块:测试夹具/示例代码里的措辞是数据,不是沟通残留;且 md 措辞可能是来源署名/名词用法(如「是否符合用户要求」),交互确认时会标注风险提示
  • 先预览再删改:--apply 逐条 y/n/a/q 确认后才写盘(a=改余下跨文件、q=退出),每文件先写 .bak 备份
  • 豁免与审计同规则:文件头前 3 行含 dsh-skip-sensitive/dsh-skip-residue 整文件跳过;行尾含 dsh-skip-sensitive 本行跳过

AI 调用建议:先跑 dry-run 看报告 → 人工/审计核对命中是否真是沟通残留(private 仓库的工作留痕措辞通常不需要清洗)→ 需要清洗时 --apply --yes。

独立脚本:运行时检测(三层审计 L3)

三层审计管线的第三层——兜住静态盲区(跨文件引用、闭包捕获、异步时序),用运行时实测确认 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 1
    • scripts/audit-runtime-check.mjs:三层审计的 L3 运行时检测(见「独立脚本:运行时检测」)
    • scripts/scrub-user-wording.mjs:清洗注释里的沟通残留措辞(见「独立脚本:清洗用户沟通措辞」)
    • scripts/check.mjs:全仓语法检查(node --check 批量)
    • 同步与安装自检能力已迁往 dsh-useful-tools(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/<插件>
    • 安装形态/HMR 自检实现随同迁移(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 主体永不修改
  • 命名格式统一:一个功能一个根词,各层只做格式转换,对外 API 与函数名完全一致
  • npm 发布完整性:真正零运行时依赖(js-yaml 已内置 lib/vendor/,见版本记录),files 白名单含 cli.mjs,npm test 一条命令可复现
  • 凭据卫生:token 只写插件配置目录 0600;测试用占位符(ghp_testtokenplaceholder123),无真实凭据入库

Keywords

dsh

FAQs

Package last updated on 17 Oct 2026

Related posts