Files
dsh_ai1net_server/dsh-server-docs/skills/dsh-opensource-release/SKILL.md
T
admin d2ef362a98 feat(overlay): 覆盖网络线 序㊾ —— 探针观测面改「两台中继并集」(附 序㊽ 源码/文档补提交)
序㊾(本棒):
- scripts/overlay-probe.cjs:OBS-01 / OBS-08 / OBS-09 的数据源由「只读 47 中继」
  改为「按两台中继取并集」,消除 worker 归属漂移时的假红 / 假 SKIP
  · endpoints 以 network:hostId:port 为键合并,online 取「或」、localPort 取在线那一侧
  · used 按 network/hostId 去重计数(不求和,避免凭空放大在册数)
  · localPort 属中继机回环落点 ⇒ 按归属分机探活(106 侧落点由 106 机上探)
  · derived(OBS-11)保持 47 视角;阈值与判据一律未放宽
  · OBS-16 计数约束:对 47 /status 的读取仍为三次、Δ 只取 47 的 counters;
    对端 106 的采样为独立一次,落在第三次采样之后,不进 (status2, status3] 门窗口
  · 新增 --peer-status-fixture(并集的对端那一半)与「并集不可取证」强制留痕
- 交接单《覆盖网络-序45-低熵块治理-测熵与实现》§16 全节(§8 前前缀逐字未变)
- 参数表 §11.16 补记(§10 现算指纹未变,值格未动)

附(前几棒已完成并已部署、但尚未入仓的源码 / 文档):
- src/net/relay/content/*.ts、src/net/relay/index.ts、main.ts:块级寻址 C 域分离
- src/supervisor/orchestrator.ts、src/worker/agent.ts:日志采集与巡检(方案 C)
- test/overlay-content.test.mjs:随附用例(npm test = 200 pass / 0 fail / 1 skipped,Node 22)
- scripts/dshlog.mjs(跨机日志取证)、scripts/overlay-entropy.cjs(熵探针)
- dsh-server-docs/04-调整方案/129、133;INDEX.md / docs-manifest.json / 交接单 README 登记
2026-09-19 05:35:35 +08:00

595 lines
83 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
name: dsh-opensource-release
description: DSH 多租户托管平台的「开源导出与版本迭代」技能 —— 把私有代码仓导出成可公开的开源副本(脱敏 / 去插件 / 分层授权 / 重写说明文档),并在后续版本里安全地重跑导出、登记版本。当用户说「开源一份」「导出到 GitHub」「发新版本」「改一下开源那份的脱敏/授权/说明」「开源那份同步一下」时触发。核心:**源仓库只读** + **阻断性探针 0 命中**才准放行 + **OVERLAY 手工撰写层**不得被重建抹掉。
version: 1.7.8
updated_at: 2026-09-18
last_change: 1.7.8(2026-09-18):**双轨的轨 2 从「README 一段散文」升格为独立文件**(用户选「B 模式」后的正向落地,提交 `25f930f`)—— 新增 `_overlay/COMMERCIAL-LICENSE.md` + `.zh-CN.md`,`OVERLAY` **28 → 30**、`REQUIRED_EXPORT` **58 → 60**,四份 README 授权节尾各 +1 句链接;并立 **§5 三条措辞铁律**(⚠️ 写成「平行的许可选择」⛔ 绝不写成"对 AGPL 的限制" · **文件名刻意不以 `LICENSE` 开头** · **正文不含项目名** ⇒ 改名窗口期两版通用);同时记 🔴 **归档里那份自拟「个人免费/商用须书面授权」`LICENSE` 不得放回**(§三 放 AGPL 项目里 = §10 追加限制 = 罗盒案否定)。新增 **坑 20 —— 新增中英文件对必须同步登记 `_check_parity.mjs` 的 `PAIRS`,否则这对中英**静默跳过**对等检查**。1.7.7(2026-09-18):**新增 §6b「多远端推送」**(GitHub 主仓 `origin` + CNB 镜像 `cnb`)—— 含远端表、`git remote add` 一次性配置、**只推 main(备份分支含改名泄漏期旧内容,绝不外推)**、⚠️ **CNB 推送必须后台跑**(实测前台 180s 被 SIGTERM 杀掉,仓库仅 1.67 MB、207 objects ⇒ 与体积无关;后台 20s 完成),以及**「三方同 hash」验收判据**;并记录「README clone 地址保持指向主仓、如需改指镜像须先问用户」。1.7.6(2026-09-18):**新增坑 19 —— `cp _overlay/<f> <仓>/` 会把「下一版内容」整份带进当前版**(改名窗口期血证,已误发上公网)—— 真实危害是**功能性缺陷**(README 让用户 clone 一个当时**空**的新仓 ⇒ 照做的人克隆到空仓库、部署直接断);最阴的一点是这类误覆盖会让「导出仓 vs `_overlay` 的 diff **变空**」,而**空 diff 本身就是覆盖证据**、不是"一致"的好消息;并加**推前两条必做复核**(新名 grep 须为空 + 部署命令自洽)。1.7.5(2026-09-17):**新增「发布合规审查」为验证第 ⑦ 件套**(用户要求:查**侵权 / 负面影响 / 涉政治**)—— 附「合规审查三关」表与判据(⚠️ **负面词命中不必然要改**,判据是「这句对外有正面价值,还是只在自曝」;自曝已发生事故的一律改为只讲**设计动因**);同时把 `core.autocrlf=true` 的陷阱写进第 ② 项(比对 overlay ↔ 仓库**必须用 git blob**)。1.7.4(2026-09-17):**「AI 生成」口径改为「人负责规划与关键判断,AI 负责实施」**(用户同日 11:44 曾要求全删、**11:48 改为本条 ⇒ 以本条为唯一现行口径**)—— 落点:README Hero 徽章 `code & docs-human-planned, AI-implemented`(徽章 **5** 个)+ 一行声明 · `manual/project.{md,zh-CN.md}` **新增 `## How this project is built` / `## 项目如何建成`**(一行声明 + 2 行「环节 → 由谁负责」表)· 两份 README 文档地图 · `_upload_audit.mjs` 提交文案。**这是法律加固**:中国版权保护中心 2026 新规判据 = **人类独创性智力投入**,旧口径「全部由 AI 生成」= 自认纯 AI ⇒ 商业授权缺标的物;新口径**恰恰确立人类投入**。⛔ 不要写回「全部由 AI 生成」,⛔ 也不要照 09-13 删掉「人的角色」。1.7.3(2026-09-17):**按用户指令删除全部「AI 生成」表述** —— 范围:README Hero 的 `AI-generated` 徽章与一行声明 · `manual/project.{md,zh-CN.md}` 的 `## AI generation` 整节 + 4 行来源表 + H1 字样 · README 文档地图字样 · `_upload_audit.mjs` 提交文案(顺带修掉同行过时的「模式 B(Kubernetes)实验性」)。**起因** = 中国版权保护中心 **2026 新规「纯 AI 生成的软件不予登记」**⇒ 自认纯 AI 会让商业授权**缺标的物**。⚠️ **推翻 2026-09-13 的旧口径**(当时要求「AI 生成」是第 1 个正文章节、「三处一个都不能少」)—— 以 09-17 为准。✅ 保留 `DeepSeek V4 / V4.1 flash` 模型标注徽章(徽章 5 → **4** 个)。1.7.2(2026-09-17):**授权定案「双轨」并落地** —— 用户两轮追问 Commons Clause 后选定:**轨 1 = AGPL-3.0 原样(不加任何限制)**、**轨 2 = 商业授权**(`[email protected]`)。重写 **§5** 整章,含两条铁律(① **绝不在 AGPL 上加限制**,含「只禁售源项目」这种窄限制 —— 依据 §10/§7 + OSD 第 6 条,判据是「有没有限制」不是「限制多窄」;② **也不需要加** —— AGPL 的 copyleft 本身就实现防白嫖转售)与两条配套事实(**CC 只能替换不能叠加** · **已发布版本收不回**);README 中英末节改写为双轨表述。1.7.1(2026-09-17):**更名 `dsh_ai1net`(中文「能力网络」)进入执行** —— 用户选定**方案 A**(env 前缀与数据根一并改)⇒ ① `_build_export.py` **46 行规则**改完(12 处目标值 + 34 处匹配/注释,⛔ 源模式与行序不动)、**新增 3 条旧名阻断探针**;② 6 个工具脚本(`_verify_tsc` / `_sop_check` / `_upload_audit` / `_verify_all` / `_k8s_comment_scan`)的新目录名与新仓 URL;③ `_overlay/` **13 文件 139 处**(含「DSH 用户平台」→「能力网络」)。全部静态验证通过(AST / `node --check` / 英文文档汉字数 = 4 / 旧名残留 0)。⏳ **待源仓冻结基线后重建**。1.7.0(2026-09-17):**修掉工作根改名后遗留的失效引用 + 一批过期事实** —— ① 工作根 2026-09-16 由 `dsh-laijing-github` 改名 **`dsh-ai1net-github`**,技能内 2 条 `cd` 命令与工作根表同步更新;② **坑 9 补「改名前先扫全部引用点」**(实测要同步的是 **5 处**脚本常量而非 2 处:`OUT` · `EX` · `_sop_check` / `_upload_audit` / `_verify_all` 各自的 `W`);③ 过期事实修正:`OVERLAY` **3 份 → 26 份**(`LICENSE` 已按 B 方案以 **AGPL-3.0** 加回)、版本 `v1.1.0/153` → **v1.2.0 / 远端 `c39758d` / 172 tracked**、计数按 **AST 实读**重刷(REQUIRED 56 · DROP_SCRIPTS 28 · LEAK_PROBES 72 …)、`<导出根>\dsh-web-platform\` → `dsh-users-platform`、补 `_check_links.mjs` / `_check_parity.mjs <repoDir>` 用法;④ **新增 🔴 新名称 `dsh_ai1net`**(用户 09-17 定 = 本项目对应开源项目的新名称;旧仓保留不动;影响面 97 文件/257 处 + env 194 处 + overlay 134 处,**待执行**)。1.6.0(2026-09-15):用户立 **K8s 长期策略** —— 「后续获取开发项目代码时**跳过** K8s 相关部分,**就用当前清除/修改后的版本**」⇒ 新增 **R-O14**(源仓那侧视为**废弃分支**;判定标准 = 构建 `blocking hits: 0`),并**修掉会误导未来会话的过期事实**:① §2「保留」列表原写 `deploy/`(11) 与 `poc/`(16) **要保留** —— 与 K8s 政策**直接冲突**(会让未来会话把它们加回来)⇒ 改为「K8s 相关一律不带」+ 指向 `_K8s排除台账.md` / `_k8s_scan.py`;② §0 的 `dsh-web-platform` → **`dsh-users-platform`**、中文母本 → **英文为主(`*.zh-CN.md`)**、首发行 → **v1.1.0 / 153 文件 / 历史已重置为单条提交 `a327649`**、补计数现状;③ 标注 `K8S_SEMANTIC_RULES` 与 `_apply_k8s_semantics.py`(本机 `--force` 被安全删除层拦下时的**热应用**替代路径)。1.5.2(2026-09-13):`assets/` 漏收录 + 空括号残渣两处真问题。
agent_created: true
---
# dsh-opensource-release — 开源导出与版本迭代
## 何时用
- 要把 `dsh_shenxian`(私有部署版)导出成可公开的仓库副本;
- 要**发新版本**(v1.0.1 / v1.1.0 …)→ 重跑导出 + 登记版本表;
- 要改开源那份的**脱敏口径 / 保留范围 / 授权结构 / 说明文档**;
- 有人问「开源那份怎么维护 / 怎么保证不泄密」。
**不适用**:日常平台改造(用 `dsh-change-workflow`)、知识库维护(用 `dsh-knowledge-upkeep`)。
---
## 0.5 🔴 事故清单(真发生过 —— **开工前 30 秒读完**)
| # | 事故(真实) | 正确做法 | 详见 |
|---|---|---|---|
| 1 | **误放别的会话的全局执行锁** —— 抢锁失败**没看输出** + `claim`/`release` 写在同一条命令 ⇒ 末尾的 `--release-exec` 是 `rm -rf` 语义,删掉了 `R1-注入层-1104` 的锁 | 抢锁**单独一条命令**并**当场看输出**;看到占用者不是自己 ⇒ 停手;放锁前 `cat 交接单/.exec-lock/OWNER` 确认首行是自己;**误放**则按 `handoff-guard.sh:43` 格式原样重建**并告知用户** | §8 坑 16 |
| 2 | **导出基线在漂** —— 导出脚本复制的是**工作树**,而多会话在并行改源码仓 ⇒ 导出混入**别人未提交的改动**,还会冒出新的需脱敏标识(`'dsh-plugin-mcn-suite'` 触发探针) | 发布前**按 commit 取**(`git archive <commit>`)=冻结版本;否则**每次重建都必须重跑探针**并复核 README 描述与实际一致 | §10 |
| 3 | **盲替 `_build_export.py` 自身** —— 脚本里同时有「源模式」与「目标值」,批量替换把**源模式**改掉 ⇒ 改名规则**静默失效** | 改脚本只用**精确 `Edit`**;改完**必须重建 + `grep` 复查** | §8 坑 9 |
| 4 | **`Dockerfile` / `Dockerfile.dsh` 整份跳过脱敏** —— `is_text()` 按扩展名判断 | `is_text()` 已加特判;**新增无扩展名文件**要复核是否进了脱敏 | §8 坑 10 |
| 5 | **`package.json` 手改被重建覆盖** —— 它属「源派生」而不是 OVERLAY | 项目自有字段(version/description/repository/license)必须写成 **GLOBAL 规则** | §8 坑 11 |
| 6 | **废弃的中间候选名静默残留** —— 探针只探最老的名字,`_overlay` 里的中间名(`dsh-hosting`)漏了 72 处 | **所有曾用名**都进 `LEAK_PROBES` | §8 坑 14 |
| 7 | **说明文档文案连改 7 轮**(替别人宣传 / 开头讲基线 / 议论式表述 / 授权在最前 / 把未验证的当可用 / 致谢太长) | 严格照 **R-O9–R-O12** 写;**写完自审一遍**再交付 | R-O9–R-O12 |
| 8 | **脚本里用键名当标题**(`marks[k][0]` 拿到的是键 `"A"` 不是标题)⇒ 结构改写打歪,误删 `PoC` 的一个字母 | 结构改写用**完整标题字符串**做锚点;改完**读回原文复核**关键块 | 本表 #7 的同一节 |
| 9 | **改工作根时漏改脚本常量 ⇒ 旧目录被"重建复活"**(2026-09-13 迁移到 `dsh-laijing-github` 时:先搬目录、后改 `OUT`,中间跑了一次重建 ⇒ 旧位置被重新建出 135 个文件,且**因旧位置没有 `_overlay` 而缺了 6 个手工层文件**;`_overlay` 本身侥幸没被洗掉) | **顺序必须是:① 改脚本常量 → ② 再搬/删目录 → ③ 重建验证**。迁完**必查旧目录没有复活**(`ls`),并核对 `find <repo> -type f \| wc -l` 与手工层文件是否都在。<br>🔴 **改名前先 `grep -rn "<旧路径>" --include="*.py" --include="*.mjs" --include="*.sh"` 把全部引用点扫出来** —— 2026-09-16 由 `dsh-laijing-github` 改名时实测:要同步的**不是 2 处而是 5 处**(`OUT` · `EX` · `_sop_check.mjs` / `_upload_audit.mjs` / `_verify_all.mjs` 各自的 `W`) | §8 坑 17 |
| 10 | **白名单收录静默漏项:`assets/` 没进 `INCLUDE_DIRS`**(2026-09-13 用户问"确认都同步了吗"时查出)—— 导出的仓库缺 `assets/inject/{recovery,assist}.js`:`proxy.ts` 的 `loadInject` 会 **fail-fast 抛错**(平台起不来)、仓库自带 `scripts/verify-inject.cjs` 也会**判失败**;`package.json` 的 `files` 同样缺 `assets`(npm/git 安装也会缺) | 已补 `INCLUDE_DIRS`、`package.json` files 规则,并**新增 `REQUIRED_EXPORT` 清单(**23 项**)**:缺任何一项 ⇒ **构建判失败**(`return 1`)。以后新增"运行时要读的文件"必须同步加进该清单 | §3 · §8 坑 18 |
| **10** | 🔴 **"顺手清理"的正则把 ASCII 标点也吃进去 ⇒ 直接改坏源码**(2026-09-13 去「档案 NN」时:清理规则写成 `[((]\s*[))]` / `[;;,,]\s*[))]`,**字符类里混了 ASCII `(` `)` `,` `;`** ⇒ 源码里所有 `foo()` 被删成 `foo`,`whitelist.ts` / `security-scan.ts` 当场语法错(tsc 报 *Invalid character* / *Unterminated string literal*)。**而当时 leak 探针全过**) | ⛔ **清理类正则只准碰全角标点(()·、,:;),绝不可把 ASCII 语法符号写进字符类**;<br>✅ **改完必跑 `_verify_tsc.mjs`,`exit 0 + no diagnostics` 是"没改坏代码"的唯一证据** —— **探针全过 ≠ 代码还活着**,两者查的是完全不同的东西;<br>另:`(\s*/\s*` 这类"吃掉前导斜杠"的规则会毁掉 `(/api/x)` 路径,一律不要写 | 本表新条目 · 台账 §八 D |
| **11** | 🔴 **同一个名字既当"脱敏目标"又当"公开值" ⇒ 自相矛盾**(2026-09-13 填 `PUBLISH_*` 时:`maogeigei` 同时在 `GLOBAL`(替换为占位符)与 `LEAK_PROBES`(判泄露)里 ⇒ ① 刚填好的公开值被规则**改回占位符**,② 探针报 `blocking hits: 4`。**"占位符残留 0"是假象**) | ⛔ **任何进入 `PUBLISH_*` 的值,先 `grep -n "<该值>" _build_export.py` 确认它不在 `GLOBAL`/`LEAK_PROBES`/`INFO_PROBES` 里**;升格为公开身份后要**同时**从 GLOBAL **与** 探针移除(只删一处 = 另一种错);<br>公开联系方式的兜底应靠**更具体的探针**(如私有仓库域名 `work.alotbuy`),不要靠账号名 | 台账 §八 D2 |
| **12** | ⚠️ **`--dry-run` 报"假成功"**(2026-09-13 真机预演时:`run()` 会把命令加 `[dry-run]` 前缀跳过执行,**但结果提示语是硬编码的** ⇒ 预演满屏 `✓ 构建完成` / `✓ 服务已启动` / `✓ 部署完成`;更糟的是**打印了一个假的初始管理员密码** —— `bootstrap-admin` 根本没跑,用户会照着登录失败。另:未设域名时文案出现空缺「把 与 *. 的 DNS A 记录」) | **dry-run 必须"只读":既不落盘,也不得宣称成功**。所有**结果类提示**(不只是动作)都要有 `DRY_RUN` 分支;**凡是"执行后才产生的值"(密码/ID/路径)在 dry-run 下必须标为"未生成"**;文案里的变量要有 `${VAR:-默认}` 兜底。<br>**验收方式**:`--dry-run` 的输出里**不允许出现任何 `✓`**,只允许 `[dry-run]` | 台账 §八 E |
| **13** | 🔴 **`_build_export.py --force` 在本机跑不动**(2026-09-14 实测:`shutil.rmtree(DST)` 被 WorkBuddy 的「安全删除层」shim 拦下 ⇒ `SAFE_DELETE_FAIL_CLOSED`;⚠️ 而且 `--force` 会**连导出物里的本地 `.git` 一起删** —— 本轮实测提交历史被吃掉后由会话重新 `git init` 建单条提交) | ① 新规则要**抽成具名列表**(如 `K8S_SEMANTIC_RULES`)再 `REGEX_RULES += …`,不要直接内联 —— 具名才能被热应用工具复用;<br>② 本机改规则后用 `<导出根>\_apply_k8s_semantics.py --write` **就地热应用**(不删任何东西,结果与整目录重建**逐字节一致**,且幂等:复跑命中 0);<br>③ 确实要整目录重建:先 `mv dsh-users-platform/.git <导出根>/_keep_git_tmp`,重建完 `mv` 回来 | 台账 §五·补 |
| **14** | 🔴 **「K8s 残留」只按 `k8s` 字面量清 ⇒ 清不干净**(2026-09-14:字面量已清零,仍有 **10 处注释**在讲 `Pod` / `file sidecar` —— 描述的是**已被移除的 K8s 形态**,属悬空描述) | 判据是**「这段描述在单机形态下还成立吗」**,不是「有没有 `k8s` 字样」:`Pod`(K8s Pod ≠ DSH 子进程)· `sidecar`(已移除的 per-user file sidecar)· `a Linux Pod` 都要清;<br>⛔ **噪音不要清**:`--profile headless`(dsh 自己的 profile 名)· `headless-univer`(第三方插件包名)· `manifest`(npm 包清单,不是 K8s manifest)· `egress`(nftables 出网护栏,本项目**保留**能力);<br>复核用 `<导出根>\_k8s_comment_scan.py [--wide]` —— 它按「**注释 / 代码**」分类输出,可直接核对「只清注释」这件事 | 台账 §五·补 |
| **15** | 🔴 **只删「构建步骤」、没删「使用者」⇒ CI 必红**(2026-09-15 实测:撤下 `Dockerfile.dsh` 后,构建 `dsh:ci` 镜像的那条步骤删了,但 **3 条使用者仍在** —— `Smoke — dsh resolves runtime plugin` / `Trivy — dsh` / `Push dsh to ACR` ⇒ 首次推送 CI 必红) | 判据 =「**产物不在,引用它的步骤也不该在**」:删任何产物(镜像 / 文件 / 模块 / 脚本)时,**必须把它的「使用者」一并处理**(本次已把 3 条步骤整块删除 + 把 `dsh:ci` 加进 `LEAK_PROBES`);<br>⚠️ 复核**务必用 `os.walk` 脚本**(`_k8s_comment_scan.py`),`bash grep -r` 会漏隐藏目录 —— 见 #16 | 影响说明 §7 |
| **16** | 🔴 **`bash grep -r` 不遍历隐藏目录 ⇒ 静默漏掉 `.github/`**(2026-09-15 实测:据此一度误判「CI 没问题」,靠 Read 才看到 `dsh:ci` 仍在) | 全仓复核用**自带脚本**(走 `os.walk`)或给**显式路径**;<br>本机另注:bash 的 `PATH` 会被 shim 重置(`dirname`/`grep`/`awk` 全 `command not found`)⇒ 先 `export PATH=<PortableGit>/usr/bin:<…>/mingw64/bin:/c/Windows/System32:/c/Windows:$PATH`,`python` / `node` 一律用**绝对路径** | 影响说明 §8 |
---
## 0. 事实(硬编码,勿猜)
| 项 | 值 |
|---|---|
| **中文名 / English name** | **DSH 用户平台** / **DSH Users Platform**(2026-09-14 由 `dsh-web-platform` 定稿改名) |
| **文档语言(2026-09-14 定稿,覆盖 R-O13)** | **英文为主**:主文档 `*.md` 为英文 + 顶部中文入口;中文全文在 **`*.zh-CN.md`**;**`manual/` 8 篇 ×2 语言**;架构图也分语言(`diagrams/architecture{,.zh-CN}.svg`) |
| **内容来源(🔴 2026-09-17 定稿口径)** | **「人负责规划与关键判断,AI 负责实施」**(英文 `Human planning and key judgment; implementation by AI`)—— 模型 `DeepSeek V4 / V4.1 flash`(**不写工具名**)。⛔ 不要写成「全部由 AI 生成」(法律风险:中国版权保护中心 2026 新规「纯 AI 生成的软件不予登记」⇒ 商业授权缺标的物);⛔ 也不要照 2026-09-13 删掉「人的角色」。落点见下方「本项目定稿顺序」 |
| ~~**文档语言**~~ | ⛔ **本行已作废** —— 2026-09-14 起改为**英文为主**,见上表「文档语言(2026-09-14 定稿)」行;<br>**R-O13 的「中文母本 + `*.en.md`」口径同时作废**,现状是 `*.zh-CN.md` 副本 |
| **技术标识(仓库·包·服务·env 前缀)** | **`dsh-users-platform`** | `DSH_USERS_PLATFORM_*` | `/var/lib/dsh-users-platform`(中文名「DSH 用户平台」/ English「DSH Users Platform」) |
| 🔴 **新名称(2026-09-17 用户定,🟡 执行中)** | **`dsh_ai1net`** —— 中文名 **「能力网络」** | 英文名 **`DSH AI1NET`** | 技术标识 `dsh_ai1net` / `DSH_AI1NET_*`。用户原话:「是 `E:\ProgramData\AI技能\aliyun-dsh-server` 对应**开源项目的新名称**」。**旧仓 `maogeigei/dsh-users-platform` 保留不动**(用户 09-16「之前的不动」),新仓 `maogeigei/dsh_ai1net` 已建(空仓),密钥 `id_ed25519_ai1net` 已绑。<br>**口径 = 方案 A(用户 09-17 08:18 选定)**:env 前缀 → `DSH_AI1NET_*` · 数据根 → `/var/lib/dsh-ai1net` · 库文件 → `dsh_ai1net.db`(与源仓在此项上**永久分叉**,映射规则在导出层)。<br>✅ **已完成(09-17 08:3x)**:`_build_export.py` **46 行规则** + 3 条旧名探针 · 6 个工具脚本 · `_overlay/` **13 文件 139 处** —— 均静态验证通过。<br>⏳ **待做**:源仓提交出冻结基线 → 重建 → `.git` 迁移 → 全量验证 → 推送新仓。<br>📄 作业书:`_改名执行清单_dsh_ai1net_20260917.md`(§零 进度 / §三 规则清单 / §四 步骤) |
| **曾用名(全部必须在 `LEAK_PROBES` 里)** | `dshs` · `dsh-multitenant` · `dsh-hosting` · **`dsh-web-platform`** · `DSH_WEB_PLATFORM_*` · `/var/lib/dsh-web-platform`;`taimiao` 未落地也一并加入。**⚠️ 改名 `dsh_ai1net` 执行后,须把 `dsh-users-platform` / `DSH_USERS_PLATFORM_*` / `/var/lib/dsh-users-platform` 补进 `LEAK_PROBES`** |
| **前名(已废弃,现为阻断探针项)** | `dsh-multitenant` / `DSH_MULTITENANT_*` / `/var/lib/dsh-multitenant` —— 2026-09-13 20:2x 由用户定名 `dsh-web-platform` 取代;`LEAK_PROBES` 已收录,**出现即判泄露** |
| **源仓库(只读!)** | `D:\github\dsh_shenxian` |
| **工作根(GitHub 开源专用文件夹)** | `E:\ProgramData\AI技能\dsh-ai1net-github\`(2026-09-13 由 `aliyun-dsh-server\_开源导出_20260913\` 整体迁入;**2026-09-16 由 `dsh-laijing-github` 改名**;**本项目的独立开源工作区**,不再是 `aliyun-dsh-server` 的子目录) |
| **仓库根(可直接 git init)** | `<导出根>\dsh-users-platform\`(**172 tracked 文件**) |
| 构建脚本 | `<导出根>\_build_export.py`(**默认拒跑**,须 `--force`) |
| 手工撰写层快照 | `<导出根>\_overlay\`(脚本自动维护) |
| 类型检查 | `<导出根>\_verify_tsc.mjs`(建 junction → tsc → `rmdirSync` 拆) |
| 文档校验 | `<导出根>\_check_links.mjs <repoDir>`(链接/锚点/配图)· `<导出根>\_check_parity.mjs <repoDir>`(中英对等 + 列出英文里的汉字;**英文文档汉字数应恒为 4**) |
| 给人看的台账 | `<导出根>\_导出说明与脱敏台账.md`(**不随仓库上传**;§七 = 改名记录) |
| 手工撰写层(`OVERLAY`:重建时自动快照→恢复,**不得被抹掉**) | **现为 30 份**:`README.md` · `LICENSE`(**AGPL-3.0,2026-09-14 按用户选定 B 方案加回**)· **`COMMERCIAL-LICENSE.md` + `.zh-CN.md`(2026-09-18 新增 · 双轨的轨 2)** · `PLUGIN-PORTING.md` · `install.sh` · `install.md` · `AGENTS.md` + 5 个 `*.zh-CN.md` + `manual/` **9 对 18 份**(2026-09-17 新增 `decisions.{md,zh-CN.md}`) |
| 当前版本 | **v1.2.0 / 2026-09-15**,已发布至远端 `main` = **`25f930f`**(普通推送累计;`332afff` 后追加商业轨文件)| 首发 v1.0.0 / 2026-09-13 | v1.1.0 / 2026-09-14 |
| 计数现状(2026-09-18 AST 实读) | `OVERLAY` **30** | `REQUIRED_EXPORT` **60** | `INCLUDE_DIRS` **6** | `INCLUDE_FILES` **8** | `EXCLUDE_FILES` **9** | `DROP_SCRIPTS` **28** | `LEAK_PROBES` **75** | `INFO_PROBES` **2** | `REGEX_RULES` **73** | `GLOBAL` **71** | `K8S_SEMANTIC_RULES` **14** | `TEXT_EXT` **16** | `EXTRA_TREES` **3** |
| 上游基线(三方) | `上游骨架仓库(已按要求不再具名)` → **MIT**(GitHub 仓库 + DSH 插件目录已收录) |
| 运行期上游 | `@deepseek-ai/dsh`(DeepSeek Harness)→ **MIT** |
| 本机 Python | `/e/ProgramData/.workbuddy/binaries/python/versions/3.13.12/python.exe` |
> ⚠️ **工作根 = `E:\ProgramData\AI技能\dsh-ai1net-github\`**(独立 GitHub 开源文件夹)。**不要再改名或迁移** —— 这个名字被 **5 个工具脚本** + 本技能 + 项目 MEMORY 同时引用。真要迁:① 先改**全部 5 处脚本常量**(`_build_export.py:13` `OUT` · `_verify_tsc.mjs:5` `EX` · `_sop_check.mjs:5` / `_upload_audit.mjs:5` / `_verify_all.mjs:5` `W`)→ ② 再搬/删目录 → ③ 复跑重建 + tsc,并检查旧目录**没有被重建脚本重新建出来**(2026-09-13 曾因漏改 `OUT` 而复活一次;**2026-09-16 由 `dsh-laijing-github` 改成现名时,已于 09-17 按此顺序把 5 处全部同步完**)。
---
## 1. 硬规则 R-O1–R-O13(= 用户原始要求 + 实际踩过的坑,任何会话**不得放宽**)
| # | 规则 | 判据 |
|---|---|---|
| **R-O1** | **源仓库只读** | 所有改写只落在导出副本。任何 `git`/写操作碰 `D:\github\dsh_shenxian` = 违规 |
| **R-O2** | **去掉本机 / 服务器信息** | 域名 / IP / 账号 / 绝对路径 / 私有仓库地址 → **占位符或通用化**;收尾探针 **0 命中** |
| **R-O3** | **去掉所有已投放的插件** | 插件包目录 + 插件投放脚本 + 构建产物(`*.tgz`)全部不带;**代码注释里的插件名也要中性化** —— ⚠️ **唯一例外见下表**:`dsh-univer-office` 经用户 2026-09-13 特许保留 |
| **R-O4** | **不带任何项目文档与 skill** | `docs/`、档案类 md、`skills/`、`.workbuddy/`、`lib/`、**`.git`** 一律不带;只留 4 个新写文档(见 §6) |
| **R-O5** | ~~授权:个人/非商业免费 + 商业收费~~ → **2026-09-13 用户定:授权类内容全部移除、不再处理、不再上抛** | 见 §5;**但「上游 MIT 不得被附加限制」是事实,保留** |
外加**操作纪律与文档口径(R-O6–R-O12)**,每条都对应 §0.5 里的真实事故:
- **R-O6** 未经明确要求 **不做 `git init` / commit / push / scp**(同项目 §4)。
- **R-O7** 导出的**手工撰写层**(README / LICENSE / NOTICE / PLUGIN-PORTING / install.sh)是资产,**不得被重建抹掉** —— 靠 `_overlay` 自动快照恢复。
- **R-O8 · 命名** —— **绝不沿用三方项目名**(详下)。
- **R-O9 · 能力宣称** —— **只写「已验证的」**:有代码 + 有单测 + 有 PoC **都不等于可用**;未验证的标「实验性 · 未验证」(详下)。
- **R-O10 · 出处** —— 只放**文末**,且**只写一行致谢**;不写骨架枚举、不写自我表扬、不写改名理由(详下)。
- **R-O11 · README 内容口径** —— 开头写**重心**不写门槛 · **面向读者**不写议论 · 每条亮点**带机制与数值** · 亮点**先读码再写**(详下)。
- **R-O12 · README 结构顺序** —— 认知漏斗 Hook→Onboarding→Content→Trust→Meta · **授权压轴** · Hero 前 50 行有可视块 · TOC 锚点机检(详下)。
- **R-O13 · 双语文档** —— **中文是母本**;英文版**在同步 GitHub 之前**才生成(`*.en.md`),两份顶部再加语言切换行;法律文本不翻译(详下)。
### R-O8 · 命名规则(2026-09-13 立,因踩过)
> 上游 `dshs` **是 上游作者(已按要求不再具名) 的三方项目**(GitHub 仓库 + **已被 DSH 插件目录收录**,含 L1–L5 验证记录)。
> 沿用它当发布名 = **冒名 / 指代混淆**,还会让上游作者的工作被误认作本项目产出。
**发布前必须做三件事**:
| # | 动作 | 判据 |
|---|---|---|
| 1 | **起自己的名**,并**实测未被占用**(npm `registry.npmjs.org/<name>` + 插件目录 `dshbase.com/plugins/<name>`,两处都 404 才可用) | 🔴 **现行命名(用户 2026-09-17 定,🟡 执行中)**:中文 **「能力网络」** | English **`DSH AI1NET`** | 技术标识 **`dsh_ai1net`**(详见 §0 表「新名称」行)。<br>**同口径历史**:中文 **DSH 用户平台** | English **DSH Users Platform** | 技术标识 **`dsh-users-platform`**(2026-09-14 定,线上旧仓仍用此名,**冻结不动**)。<br>⚠️ **已排除的候选**:**`dsh-hive`**(第三方插件 `llluchy/dsh-hive` 已占用);**`dsh-hosting`**(中间候选,已被取代 ⇒ **仓库里不得残留**,已列入阻断性探针);**`taimiao`**(仅候选,未落地)。 |
| 2 | **改完全部自指标识**:包名 / bin / cordis plugin id / env 前缀(36 种)/ 数据根 / systemd 单元 / nginx conf / 库文件名 / 镜像与 k8s / 导出目录名 | 全仓 `grep` 旧名,**只剩出处引用**才算干净 |
| 3 | **保留出处并正式致敬 —— 但只放在文末**(用户 2026-09-13 明确:"在最后提一下引用了谁就行,不要上来就重点讲用了谁") | ① 上游 = **DeepSeek Harness(MIT)**,**本项目不包含、不分发其代码** ⇒ 无需单独 MIT 声明文件,README 文末保留**一行道义致敬**(`dshs`,MIT,⛔ 不许删);② README **不得在开头单独设「名称与渊源 / 基于 XX」章节** —— 出处只出现在**文末**的「第三方组件与致谢」里,**一句话带过**;③ 本项目的法律归属由 **`LICENSE`(AGPL-3.0 官方全文)** + README 末节「授权与商业使用」承载 |
⚠️ **改名时最容易误伤的两处**:① 把「致敬上游」的引用一起改掉(= 抹掉出处,法律与道义双重问题);② 把脚本里作**源模式**的旧名改掉(见 §8 坑 9)。
### R-O9 · 只写「已验证的」能力
> 用户原话:「模式 B · Kubernetes **去掉这个,根本没验证**,应该是**待开发验证**」。
| 规则 | 做法 |
|---|---|
| **宣称必须可复现** | 只把**真正跑过端到端验收**的路径写成「可用」。**有代码 + 有单元测试 + 有 PoC 记录,都不等于可用** |
| **未验证的照实标注,不删代码** | 保留代码与清单,但标注 **「实验性 · 未验证」**,并与可用路径**在同一张表里用状态行对照**,不要让读者自己猜 |
| **删掉「已完整落地 / Phase 0–4」式表述** | 这类词最容易把"写完了"说成"验证过了"(2026-09-13 从「部署形态」章节删掉的就是它) |
| **配置表 / 脚本文案同步标注** | 未验证路径的 env 变量统一加「(模式 X · 未验证)」前缀;`install.sh` 的报错/提示文案要与 README 口径一致 |
| **FAQ 给一句直答** | 加一条「X 现在能用吗?」→ 直接回答「**还不能**」,并说清**缺哪一步**(如「从未做过端到端部署验收」) |
| **归属措辞也要改** | 出处/致谢里描述对方贡献时,把「双部署**形态**」降级为「双部署**框架**」,避免暗示未验证的路径是可选项 |
| **落点清单(照抄)** | README:部署形态表 + 快速开始 + 配置表 + 功能详解 + 安全模型 + 亮点 + 目录结构 + FAQ;`install.sh` 文案;README **末节「授权与商业使用」**与**文末致敬行**的措辞 |
---
---
### R-O10 · 出处的位置与措辞
> 用户原话:「在最后提一下引用了谁就行,**不要上来就重点讲用了谁**,感觉是在宣传别人的项目,已经很多地方深度改造过了。」
| 规则 | 说明 |
|---|---|
| **位置** | 只在**文末**(README 的「第三方组件与致谢」+ 末节「授权与商业使用」)。**不得**在开头/前部单设「名称与渊源」「基于 XX」章节 |
| **主语** | 正文一律**以本项目为主语**。写「本项目做了…」,**不要**写成「上游提供了骨架,我们在此基础上…」这种自我降格的框架 |
| **措辞** | 用「**起步时参考了** X(作者,许可证)—— **感谢作者开源**」;**不要**用「仅仅接着往前走了一步」「离开它就没有这个项目」这类过度抬举,**也不要**补「我们做了大量深度改造」这类**自我表扬**(见下表「致谢只写一行」) |
| **边界** | 「轻描淡写」**只作用于 README 正文**;**`LICENSE`(AGPL-3.0 官方全文,逐字节)与 README 末节的授权说明一处都不能省** |
| **JS/注释里的名字** | 代码注释里也**不主动**出现上游名(它们已经被 R-O8 第 2 步改成新名;只剩出处语境才允许) |
| **致谢只写一行**(2026-09-13 第七次纠正) | 出处行 = **「起步时参考了 X(作者,许可证)—— 感谢作者开源」**,一行结束。**不要**写:① 骨架范围的枚举(那是 `LICENSE` 与 README 末节授权说明的职责,**重复即冗余**);② 「此后我们做了大量深度改造」(**自我表扬**,致谢不是讲功绩的地方);③ 「项目名从它的 X 换成我们的 Y(避免指代混淆…)」(**内部事务**,读者不关心 ⇒ 不进公开文档)。用户原话:「**有必要讲这么多吗,好好想想**」 |
| **别解释我们为什么这么写** | 「—— 这是 MIT 的硬性要求,必须保留」「因此 README 与 install.sh 一律以模式 A 为准」这类**关于文档自身**的话术删掉;正文只陈述事实与规则本体 |
| **指针行不重复** | 「机制见亮点」这类导航指针**全文留 1–2 处**(Hero + 功能详解)即可,Content 各节末尾各来一句 = 冗余 |
---
### R-O11 · README 内容口径
> 🧭 **体例 = 说明书,不是技术文档**(2026-09-13 20:4x 用户定):「readme 是说明不是技术文档 用语需要简明扼要 排版要方便观看」。
> ⇒ 只写**怎么用 / 有什么 / 限制**;机制级细节(链名、flag、常量、函数语义)留给代码注释与 `PLUGIN-PORTING.md`;
> ⇒ **不写内部变更日志式长表**(如「v1.0.0 的六组改造」);表格单元格要短、可扫读;多用列表少用长段落。
> 用户原话:「部署到一台服务器,多个用户注册并经管理员审核,各自获得一套相互隔离 —— **这个只是项目的基础不是重点**,重点是多租户各自进程的安全隔离、状态恢复、插件和技能的管理。**多看看项目找出这个项目的亮点**」「对了多想想 **不要弄了半天亮点都体现不出来**」。
| 规则 | 做法 |
|---|---|
| **开头 = 亮点,不是门槛** | 开篇**不要**写「部署到一台服务器,多个用户注册…」这类「能跑」描述(那是基线)。改成**一句定位 + 三条主线速览**:① 进程级安全隔离 ② 故障自愈与状态恢复 ③ 插件与技能的受控管理 |
| **亮点必须先于功能清单** | README 的第一个正文章节就是**亮点**(`## 亮点`),且**要早于**「快速开始 / 功能详解」。功能清单只做**索引**,并在开头声明「机制见亮点」 |
| **每条亮点必须带机制** | 禁止「真隔离」「会自愈」这类空词。每条要写**具体机制 + 关键数值/常量 + 为什么这么设计**(例:端口守卫要在 OUTPUT 链按**客户端 uid** 匹配、且 `-I OUTPUT 1` 插链首,否则 ufw/conntrack 的 ACCEPT 会先吃包;宿主不支持就 fail loud) |
| **先读代码再写亮点** | 亮点**必须来自实际读码**(`src/**` 的头注与关键函数就写得很好),不要凭 README 旧文或印象复述。读法:`find src -name '*.ts' \| xargs wc -l \| sort -rn` 找最重的模块 → 读头注 → 再挑 3-5 个「反直觉且踩过坑」的细节 |
| **「难在哪」心里有数(但别写进 README)** | 每条主线要能回答「为什么这不容易」(租户之间**真的**隔得住 / 崩溃后**无感**恢复 / 装了**不出事**)—— 用于**决定亮点写什么**;⚠️ 但「多租户演示十分钟就能写出来」这类**对比式议论本身不许出现在 README**(见下表「面向读者」) |
| **补一节工程纵深** | 用「双后端同接口 / 关键决策是纯函数 / `npm test` 覆盖 + 注入脚本运行时校验」这类事实回答「凭什么信这些机制」 |
| **面向读者,不是面向作者**(2026-09-13 第三次纠正) | README 是给**使用者 / 贡献者**看的。禁止出现「**重点不是 X,而是 Y**」「X **十分钟就能写出来**」这类**议论式 / 对比式**表述 —— 那是在跟作者对话,读者不关心。直接陈述「**项目做什么 + 重心在哪**」即可 |
| **小节标题别加议论** | 标题只写名词短语(`### 一、进程级安全隔离`),**不要**写成 `(不是「同机不同目录」)` `(「能装」和「装了不出事」是两件事)` 这种反问/抖机灵。对比与理由放到**表格单元格**里当技术说明 |
| **别重复定位句** | 标题下的一句 tagline 与 badges 之后的描述段**不要重复同一个句式**(「把 DSH 变成…」说了两遍)。tagline 一句话,描述段讲**用户视角的事实 + 三条重心** |
---
---
### R-O12 · README 结构顺序
**依据**:`readme-craft`(SkillHub 技能,蒸馏 awesome-readme / Standard README / Art of README / Make a README / GitHub Docs / thoughtbot)+ `standard-readme`。核心是**认知漏斗**:**Hook → Onboarding → Content → Trust → Meta**,**不得倒序**。
**本项目定稿顺序(Hero + 16 节)**
```
标题 → 一行描述 → 徽章(**5 个**:Node · Version · built on DSH · **code & docs-human-planned, AI-implemented** · DeepSeek V4/V4.1 flash;**无 License 徽章**)
→ Hero(三条主线 + **一行「人负责规划与关键判断,AI 负责实施」** + 拓扑图)→ 快速开始片段
目录 → 亮点 → 快速开始 → 功能详解 → 架构 → 安全模型 → 部署形态 → 配置
→ 控制面 API → 插件移植指南 → 开发 → 常见问题 → 目录结构 → 版本与迭代 → 贡献
→ 第三方组件与致谢 → 授权与商业使用(必须最后)→ 授权摘要收尾(全文唯一一处摘要)
```
> 🔴 **「本项目由谁建成」= 现行唯一口径(2026-09-17 11:48 用户定):「人负责规划与关键判断,AI 负责实施」**(英文 `Human planning and key judgment; implementation by AI`)。
> · **落点**:README Hero 的 `code & docs-human-planned, AI-implemented` 徽章 + 一行声明 · `manual/project.{md,zh-CN.md}` 的 **`## How this project is built` / `## 项目如何建成`**(一行声明 + 2 行「环节 → 由谁负责」表:人 = 方向/范围/架构决策/评审验收;AI = 代码/测试/文档/插件改造示例)。
> · **为什么必须这样写**:中国版权保护中心 **2026 新规「纯 AI 生成的软件不予登记」**,判据 = **人类独创性智力投入**。旧口径「全部代码与文档由 AI 生成」= **自认纯 AI** ⇒ 商业授权**缺标的物**;新口径**恰恰确立人类投入** ⇒ 是**法律加固**,⚠️ 不要简化回「AI 生成」(详见 §5 与 `<工作根>\_授权决策与法律依据_20260917.md`)。
> ⛔ **不要再写回「全部由 AI 生成」**(用户 09-17 **11:44 曾短暂要求全部删除,11:48 改为本条**);⛔ **也不要照 2026-09-13 的「删掉人的角色」** —— 两者均已被推翻。
> ✅ 一并保留:`DeepSeek V4 / V4.1 flash` 模型标注徽章 · README 的 `**能力网络** · **DSH AI1NET**` 行。
| # | 硬规则 | 理由 |
|---|---|---|
| 1 | **授权章节放最后** | 6 个权威来源共识 + readme-craft 的 Trust 评分项就是「License 在最后?」 |
| 2 | **授权信息不要出现在前排正文**(2026-09-13 用户纠正):靠**顶部 License 徽章**承载(本项目 = `license-personal free \| commercial paid`,并链接到末节)+ **文末**「授权与商业使用」章节尾的一行摘要。**不要在徽章下方另加一句授权 blockquote** —— 用户明确「说明文档还是在前面」不接受 |
| 3 | **Hero 区(前 50 行)必须有可视块** | 审计项 H3 占 7 分(拓扑图 / 截图 / GIF 任选) |
| 4 | 一行描述 **< 120 字符**,且与 `package.json` 的 `description` **开头一致** | 审计项 H2 占 8 分,单项最高 |
| 5 | 超 100 行**必须有 TOC**,且**锚点逐条可解析** | 自查法:把标题按 GitHub 规则转锚点(小写 / 去标点 / 空格→`-`)后与 TOC 比对 |
| 6 | 功能用**表格/列表**不写散文;**清单型章节要声明「机制见亮点」** | 避免 C1 扣分与 S3 信息重复 |
| 7 | **API 概览必须从代码抓真实路由**(`grep -oE "app\.(get\|post\|put\|delete)\("`),别凭印象写 | 审计项 C3;写错路由比不写更糟 |
| 8 | 章节重排要用**脚本按标题切分再拼装**,重排后**复跑 TOC 校验** | 手工搬章节极易丢内容 |
| 9 | **表格单元格里不要写裸 `\|`**(如 `GET\|POST`)—— 会截断表格,改写「(`POST` 同形)」 | 格式错误扣 P2 |
| 10 | 发布后补 **CI 徽章** 与**真实联系方式**;上线前不要加 CI 徽章(占位符 = 死链) | T3 / T4 是唯二「因尚未发布」而扣分的项 |
**审计口径**(readme-craft 22 项 / 100 分):Hook 25 · Onboarding 25 · Content 20 · Trust 15 · Structure 10 · Polish 5;等级 **S**≥90 / **A**≥80 / **B**≥70 / **C**≥60 / **D**<60。
**本项目首轮自审 = 93/100(S)**,扣分仅:CI 徽章 0/3 · 维护者信息 0/3(`<CONTACT_EMAIL>` 未填)· S3 信息重复 2/3。
---
### R-O13 · 双语文档(2026-09-13 用户定:**中文优先,英文在同步 GitHub 时生成**)
> 用户原话:「文档别忘了**中英文双语**,后续**优先写中文**,需要同步到 GitHub 时再更新英语。」
| 项 | 口径 |
|---|---|
| **母本** | **中文**(`README.md` / `PLUGIN-PORTING.md`)。**日常只维护中文**;英文文件**不要求随时同步**,避免双份维护成本 |
| **英文文件名** | `README.en.md`、`PLUGIN-PORTING.en.md`(与中文同目录,后缀 `.en.md`) |
| **生成时机** | **发布 / 推送 GitHub 之前那一步**(SOP 的 5.5)—— 也就是 §7 验证之后、§6 交付之前 |
| **语言切换行** | 两份文件**顶部都要有**:中文版写 `[中文](README.md) · [English](README.en.md)`;英文版写 `[English](README.en.md) · [中文](README.md)`。⚠️ **英文文件存在之前不要加**(否则是死链,扣 P1) |
| **翻译时严格保持** | 代码块、命令、路径、env 名、包名、URL、图(ASCII/Mermaid)、表格结构与「版本与迭代」表内容 —— **逐字保留**;占位符(`<YOUR_GITHUB_ACCOUNT>` 等)**同步替换** |
| **不翻译(保持原文)** | `LICENSE` —— **AGPL-3.0 官方英文全文,逐字节不许翻译或改写** |
| **校验** | 英文版同样要跑 **TOC 锚点校验**(按英文标题算锚点)与**相对链接存在性**;两版的「版本与迭代」表**行数与版本号必须一致** |
| **别忘** | 这是**发布前唯一会因为"没做"而显得半成品**的项 —— 写进 SOP 与 §10 待办,接手先看 |
---
### R-O14 · 🚫 K8s 相关内容:**源仓那侧视为废弃分支**(2026-09-14 定稿;2026-09-15 用户升级为**长期策略**)
> 用户原话(2026-09-15):「记住这部分和 K8S 相关的代码 **后续获取开发项目代码时 跳过就用当前清除或修改后的版本**」
| 规则 | 判据 |
|---|---|
| **① 不回流** | 源仓的 K8s 资源 / 文档 / 注释 / 语义描述 / K8s 专属配置,**不得**因源仓更新而重新进入导出物 |
| **② 不重复实现** | 导出层已有的清除与改写就是**唯一口径**,不要每次重新发明 |
| **③ 改了源仓也不跟** | 源仓若再改 K8s 那段代码,**以导出层版本为准**(源仓那侧视为**废弃分支**) |
| **判定标准** | 构建输出 **`blocking hits: 0`**;不为 0 = 回流了 ⇒ 按台账 §四 处置 |
| **权威清单** | **`_K8s排除台账.md`**(本工作根)—— 含「下次取新版本怎么做」的步骤 + 判读表 + 噪音清单 |
| **扫描器** | **`_k8s_scan.py`**(`--source` 扫源仓 / 无参数扫导出物;**EXIT=1 = 有未覆盖项**) |
**三重强制手段**(缺一会静默失效):
`INCLUDE_DIRS`/`INCLUDE_FILES` 白名单 → `EXCLUDE_FILES`/`DROP_SCRIPTS` → `REGEX_RULES` ⑦⑧⑨ + **`K8S_SEMANTIC_RULES`** + `LEAK_PROBES`。
**已清到 0(源码与注释)**:62 → 0;含 K8s 专属配置项(`config.ts` 7 字段 + 3 常量 + `parseCidrs()`)、
`DeployMode` 收窄为 `'local'`、全部注释与**语义描述**(`Pod`/`file sidecar`/`ConfigMap`)。
⚠️ **连带必做**(否则 `tsc` 报错):`proxy.ts` 的 `deployMode === 'k8s'` 实参改常量 `false`;`web/server.ts` 的 fail-loud 守卫删除。
⏳ **唯一剩项**:`@kubernetes/client-node` 依赖 + lock(8 处)—— 导出层删不了(须重生成 lock,⛔ 不手改 lock)。
⚠️ **但这不等于「去源仓 `npm uninstall` 就行」**(2026-09-15 更正):**导出物**里它 0 import(3 个 import 它的模块被 `EXCLUDE_FILES` 剔了),可**源仓仍保留 K8s 后端**(`src/supervisor/{k8s-spawner,leader,reconcile}.ts` 都 import 它)⇒ **在源仓直接删会打断源仓 `tsc`**。
**正确顺序**:源仓先下线 K8s 后端 → 再 `npm uninstall` 重生成 lock → 最后重跑导出。三条路线见 `_K8s清理影响评估与回归说明_20260915.md §9`。
---
## 1.5 🔴🔴🔴 用户当场纠正过的硬口径(2026-09-14 凌晨:连纠 8 次)!!!
> **这不是"建议",是硬口径 —— 一条不遵守就要返工。** 全部来自真实纠正,逐条附用户原话。
| !!! | 规则 | 判据 / 用户原话 |
|---|---|---|
| **!!! 1 !!!** | **没验证的能力:不写(不是标注「未验证」,是整条删)** | 「**没验证的不要写意思就是不要写 !!!**」,点名删「双部署后端同一接口(K8s 后端未验证)」。⇒ README **不得出现**「未验证 / 实验性 / 模式 B / K8s 后端 / Postgres」等字样 —— 已**全清**(代码可留,**文档不提**)|
| **!!! 2 !!!** | **不写废话**:括号里的体贴话、推销话 | 「(想自己掌控每一步)**不要写这种没用的废话**」;「商业授权…联系 xxx **不用写这个废话**」。**判据:括号里若没有机制 / 数值 / 真实行为 / UI 提示 = 废话,一律删**。已删:`手动部署(想自己掌控每一步)`、`(建议先审一遍)`、整段「商业授权」+ 邮箱、章节名「授权与商业使用」→「**授权**」|
| **!!! 3 !!!** | **归类必须准:DeepSeek Harness 是「基座」,不是「第三方组件」** | 「**这个不叫三方组件…所有开发都是基于这个来的**」⇒ ① 删掉「第三方组件与致谢」整节;② 在「架构」里讲清 **DSH = DeepSeek AI 开源的 agent harness**(everything-is-a-plugin / Cordis 驱动 / 默认 `npx @deepseek-ai/dsh web` → `127.0.0.1:3080` **本机单用户** Web UI);③ 补上 **developer preview ⇒ 官方明说会破坏性变更**(它才是"为什么要有兼容性预检 + 版本冻结"的钩子)|
| **!!! 4 !!!** | **读码找亮点:亮点必须来自实际读码,且区分「已验证」** | 「在分析一遍项目看看还有哪些亮点」⇒ 按 R-O11 逐个读 `src/**` 头注;**没验证过的不写**(本次挖到的"模型管理两层""迁移账本同形"等因**未实测**而**未采纳**)|
| **!!! 5 !!!** | **未持锁 ≠ 不能改导出物;但「重建」会删掉本地 `.git`** | ① 本工作根**不在**锁保护范围(钩子只护「文档库 / 代码仓」)—— **别再拿锁当理由拒改导出物**(本次被纠正);② ⚠️ **`_build_export.py --force` 的 `rmtree(DST)` 会连仓库里本地 `.git` 一起删**(本次实测)⇒ 顺序必须 **重建 → 六件套 → `git init`/commit → 推送**,**提交后不得再重建** |
| **!!! 6 !!!** | **安装成功才准提交 / 推送(用户定的闸门)** | 「**必须按照说明文档 安装成功才能提交**」⇒ **平台本体跑通**(install 成功 + 登录 200 + 管理台 / 桌面 API 200)是**下限**;`--dry-run` 通过、组件级验证、探针全绿 **都不算通过** |
| **!!! 7 !!!** | **敏感信息一律不进仓库**(测试 IP / 账号密码 / 实例 ID / 服务器信息) | 本次把**真实测试 IP** 写进 README 示例被当场抓到 ⇒ 改用 **RFC 5737 文档保留地址**(如 `203.0.113.10.nip.io`);并把 `106.54.21.172` / `ins-3q6k1p8t` / 测试账号密码**四项加进 `LEAK_PROBES`** |
| **!!! 8 !!!** | **提「注意事项」前先对齐本技能 §1 的 R-O1–R-O13** | 「感觉都不是我最早说的注意事项,**你看看 skill**」⇒ 用户要的是**他原始定的硬规则**,**不是**实现坑;计划/清单按 R-O 组织 |
| **!!! 9 !!!** | **章节顺序服务于读者;参考性章节别放太后;排版要整体看** | 「目录结构 是不是放的太靠后了,**在整体看看你的排版呢**」⇒ ①「**目录结构**」从 Meta 区**上移到「架构」之后**(逻辑结构 → 物理结构,读者顺着一路读);② 排版检查要**整体过**:分隔线用法、标题层级、表格/列表一致性、长句拆分、括号废话(见 !!! 2 !!!)。⚠️ 与 R-O12 的社区标准顺序冲突时,**以用户当场指令为准**并说明理由 |
### 改文档时的**固定动作**(本次反复用到,照抄)
1. **两份同步**:`_overlay\<文件>` 与 `dsh-users-platform\<文件>` **必须逐字节一致**(改一份 = 改两份,改完 `md5` 比一次);
2. **改完必验**:`md5` 相同 + **TOC 锚点机检无悬空** + **全篇关键词扫描**(`模式 B / K8s / 未验证 / 实验性 / WorkBuddy / 旧名 / 敏感串` 应**全 0**);
3. **提交**:`git -c core.autocrlf=false add -A` → `commit --amend --no-edit`(**首发阶段**保持单条发布提交);**提交后不得再重建**;
4. **改本技能**:两副本(活跃 + 文档库归档)**md5 必须一致**,同步前**先抢全局执行锁**。
## 2. 保留 / 移除清单(delta · 改口径先改这里)
### 保留
```
assets/ 注入脚本(2:inject/recovery.js · inject/assist.js)—— ⚠️ **proxy.ts 的 loadInject 按包根解析 ⇒ 缺了平台启动即抛错**,必须随包
src/ 控制面 TS 源码(**已剔除 6 个 K8s 后端模块**,见下)
web/ 静态页
scripts/ 运维与冒烟脚本(**已剔除 5 个 K8s / 已排除插件相关脚本**)
test/ 单测(**已剔除 2 个 K8s 模块的测试**)
.github/workflows/build.yml
package.json package-lock.json tsconfig.json cordis.patch.yml
Dockerfile .dockerignore .gitignore(重建)
mksess.cjs ensure-role-profile-patch.cjs(临时会话 / profile 补丁)
```
> 🔴 **K8s 相关一律不带**(2026-09-14 用户定稿,2026-09-15 升级为**长期策略**):
> ⛔ **不再保留** `deploy/`(11 个 K8s 清单)· `poc/`(4 个 K8s 可行性验证件)· `Dockerfile.dsh`(每用户 Pod 镜像)·
> 6 个 K8s 后端模块(`k8s-spawner` `k8s-user-fs` `leader` `reconcile` `tcp-bridge` `web/file-service`)·
> 2 个 K8s 测试 · `smoke-file-service.mjs` · CI 里的 dsh 镜像步骤 · `config.ts` 的 K8s 专属配置项 ·
> 以及**全部 k8s 注释与语义描述**。
> ✅ **保留** `src/db/pg.ts`(Postgres = 共享 HA,**不是** K8s 专属)。
> 📌 **权威清单与处置办法**:**`_K8s排除台账.md`**(本工作根下)—— 含「下次取新版本怎么做」的步骤与判读表;
> 扫描器 **`_k8s_scan.py`**(`--source` 扫源仓 / 不给参数扫导出物);判定标准 = 构建 **`blocking hits: 0`**。
### 移除
| 路径 | 理由 |
|---|---|
| `poc/business-plugins/` | **已投放插件**(功能管理分区插件,含全部 `.tgz`) |
| `poc/workspace-scoped-picker/` | **已投放插件**(目录选择器) |
| `scripts/ensure-anysearch-admin.cjs`<br>`scripts/ensure-anysearch-pool.mjs` | 特定插件投放脚本 |
| `scripts/ensure-biz-plugins.cjs`<br>`scripts/ensure-portal-entry.cjs`<br>`scripts/install-workspace-picker.sh`<br>`scripts/provision-new-users.sh` | 插件 / 本平台专属投放与开通脚本 |
| `docs/`(7 篇) | R-O4:项目文档 |
| `STANDARD.md` · `poc/README.md` · `poc/*/README.md` | R-O4:文档 |
| `.workbuddy/` · `lib/` · `node_modules/` · `data/` | 本地状态与构建产物 |
| **`.git`** | ⛔ 历史里含全部内部信息 ⇒ **必须全新仓库** |
| 全部 `*.tgz` | 构建产物 |
### 本就不在代码仓(别去找)
**MCN 工作台(`dsh-plugin-mcn-suite`)、douyin-accounts、vision-router、各 skill 本体(含 MCN 相关 skill)** 都不在 `dsh_shenxian` 里 —— 它们在其他仓库 / 实例 profile。收尾探针会复核 `mcn` / `douyin` / `抖音` / `vision-router` **0 命中**。
### ⚠️ 特许保留项(**不要在脱敏里动它**)
| 项 | 处置 | 依据 |
|---|---|---|
| **`dsh-univer-office`**(插件名 + 实例侧 unix-socket 适配) | **保留原名、保留代码**:`src/supervisor/orchestrator.ts` 的 `DSH_INSTANCE_UNIVER_SOCKET` / `UNIVER_DSH_GATEWAY_SOCKET` 段**不得删**;`src/web/routes/whitelist.ts` 注释里点名 `dsh-univer-office`;探针 `LEAK_PROBES` 里**不得**出现 `dsh-univer` / `UNIVER` | 用户 2026-09-13:「univer 可以保留这个插件 专门讲讲如何把开源插件改造为可在多租户平台运行」 |
| ↳ 为什么值得保留 | 它是 `PLUGIN-PORTING.md`(插件移植指南)的**唯一实证样本** —— 一个「静态预检通过但在托管平台完全不可用」的真实案例,含两层根因、3 条设计决策、2 个平台侧机制坑 | 同上 |
### 待决项(用户没拍板前维持现状)
- `poc/business-plugins` + `poc/workspace-scoped-picker`:现按**严格口径移除**(「所有已投放的插件」)。若判定它们属「平台自带界面」而非投放插件 → 加回,并同步改本节 + 探针。
---
## 3. 脱敏映射表(**唯一口径**,改只改这里 + 脚本里的 `GLOBAL`)
| 类别 | 原值 | 替换为 | 命中 |
|---|---|---|---|
| 平台域名 | `dsh.alotbuy.com` / `*.alotbuy.com` / `alotbuy` | `<baseDomain>` | 3 文件 |
| ↳ **特例** | `web/wake.html` 的 `safeNext()` 正则 | 改成**运行时从 `location.hostname` 推导注册域**(`split('.')` 去最左一段),彻底去硬编码 | — |
| 服务器公网 IP | `47.77.182.89` | `<SERVER_PUBLIC_IP>` | 1 |
| 宿主内网 IP | `172.18.16.212` | `<HOST_LAN_IP>` | 1 |
| 服务器代码路径 | `/opt/dshs` | `<INSTALL_DIR>` | 8 |
| ↳ **特例** | `require('/opt/dshs/node_modules/better-sqlite3')` | `require('better-sqlite3')`(等价且更规范) | — |
| 服务器平台目录 | `/opt/dsh/{state,artifacts,backups}` | `/var/lib/dsh-web-platform/{state,artifacts,backups}`(与上游文档一致的数据根) | 6 |
| **内部档案号** | 全角/ASCII 括号里的 `档案 NN`(含 `档案 81 · R1`、`(档案 20)`、`backoff (档案 20)`) | **整块删**(号无对外意义);残渣(空括号 `()` / ` ().`)由后续规则清掉 | 183 |
| **悬空文档引用** | `docs/k8s.md §5.2` / `docs/blueprint.md` / `docs/domain-config.md` | 映射到 README 真实小节(`README「部署形态」` / `README「架构」` / `README「配置」`);`§号` 一并去掉 | 42 |
| ↳ **实现位置** | 以上两项由 `_build_export.py` 的 **`REGEX_RULES`** 做(不是 `GLOBAL`);⛔ **清理规则只准碰全角标点**,唯一放开的两条 ASCII 规则:① `(档案 NN)`(模式里必须有档案号 ⇒ 不会误伤 `foo()`)② ` ().`+句末标点(`(): void` 后面是 `:` ⇒ 不命中)。**每次改 REGEX_RULES 必须重建 + `tsc` 复核**(第一次踩过:ASCII 括号进字符类把 `foo()` 删了,tsc 报 Invalid character) | — |
| ↳ tar 相对写法 | `opt/dsh*`(无前导斜杠) | `var/lib/dsh-web-platform*` | — |
| 账号 / 私有仓库 | `maogeigei`、`[email protected]:...dsh_shenxian_doc.git` | `<YOUR_GITHUB_ACCOUNT>`;文档库引用随 README 重写整体移除 | 1 |
| 云厂商标识 | 「阿里云内网 DNS」「BT-Panel 58888/8765」「sshd 22/32022」 | 「云厂商内网 DNS」「面板」「sshd」 | 1 |
| 插件具体名 | `anysearch` / `@anysearch/anysearch-dsh` / `@liustack/modlens` / `mcn-workstation` | 「该插件」/「某第三方插件」→ 再**整行重写**成中性描述 | 6 |
| ↳ **例外(保留原名)** | **`dsh-univer-office`** 与其实例侧适配(`DSH_INSTANCE_UNIVER_SOCKET` / `UNIVER_DSH_GATEWAY_SOCKET`) | **不脱敏、不删代码**(用户 2026-09-13 明确「可以保留这个插件」);它同时是 `PLUGIN-PORTING.md` 的实证样本 ⇒ 其 env 名、注释、`DELETE_LINES` 条目**都不得再动** | 3 |
| **项目改名** | `dshs` 全部自指标识 | `dsh-web-platform`(规则顺序:`dshs.db` → `dshs.db` → `/var/lib/dshs` → `DSHS_` → `dshs`) | 149 |
| ↳ **必须保留** | `上游骨架仓库(已按要求不再具名)`、`上游 \`dshs\`` | **原样不动**(出处/致谢);`LICENSE`(**AGPL-3.0 官方全文**)逐字节不动 | — |
**发布前必须替换的占位符**(写在台账里):
| 占位符 | 出现位置 |
|---|---|
| `<YOUR_GITHUB_ACCOUNT>` | `README.md`、`package.json` → repository |
| ~~`<CONTACT_EMAIL>`~~ | 原为 `README.md` 授权章节 / `LICENSE` —— **授权章节与 LICENSE 已于 2026-09-13 移除**,该占位符随之消失(见 §5) |
| `<COPYRIGHT_HOLDER>` | `LICENSE` |
| `<SERVER_PUBLIC_IP>` / `<HOST_LAN_IP>` | `scripts/install-egress-guard.sh`(部署时按自己服务器填) |
| `<INSTALL_DIR>` / `<baseDomain>` | 仅注释,可留 |
> `install.sh` 里的 `dsh.example.com` / `you@example.com` 是文档示例,符合惯例,**不改**。
---
## 4. 保留未动(刻意)
- **183 处「档案 NN」内部编号引用**(仅代码注释):属内部档案号,**不是**本机/服务器信息。已列入「可选后续」;要清需用户点头(做一次纯注释替换)。
- 上游 `docs/` 内容虽为 MIT 可带走,但 R-O4「不带任何文档」⇒ 不带。
---
## 5. 授权结构(**现状:2026-09-17 定案「双轨」—— AGPL-3.0 原样 + 商业授权**)
> 🔴 **现状(以本条为准,覆盖本章所有历史描述)** —— **双轨授权**:
> - **轨 1 · 开源轨 = AGPL-3.0 原样(默认)**:`LICENSE` = AGPL-3.0 官方全文(**34,523 B,逐字节未改**);`package.json` 保持 `"license": "AGPL-3.0-only"`;已在 `OVERLAY` 与 `REQUIRED_EXPORT`(**60 项**)内。
> - **轨 2 · 商业轨**:给「**不愿承担 AGPL 开源义务**」(闭源托管 / 嵌入专有产品)的人 ⇒ 联系 `maogeigei@gmail.com` 谈条款与报价。**商业授权是「另开一条平行许可路径」,不是「对 AGPL 加限制」** —— 这是它不违反 OSD 的关键。**自 2026-09-18 起轨 2 有独立文件**:`COMMERCIAL-LICENSE.md` + `.zh-CN.md`(提交 `25f930f`)。
> - 🔴 **三条措辞铁律(2026-09-18 立,⛔ 违反即等于把项目踢出开源)**:① 全文写成「**平行的许可选择**」(parallel choice),⛔ **绝不**写成"对 AGPL 附加的限制";② **文件名刻意不以 `LICENSE` 开头** —— 免被 licensee 误判为主许可;③ **正文不含项目名**(含新名 / 旧名)⇒ **改名窗口期两版通用**,零泄漏面。
> - 🔴 **归档里的自拟 `LICENSE` 不得放回**:`_授权归档_发布时再放回\LICENSE`(5,931 B,自拟「个人免费/商用须书面授权」)的 §三「商业使用必须事先取得书面授权」**放在已发布 AGPL 项目里 = §10 追加限制** ⇒ 正是罗盒案否定、09-17 定案要避开的那一步。**归档 ≠ 照原样拷回**(逐项判定 → `_导出说明与脱敏台账.md` §F)。
> - **README 末节** = `## License` / 中文 `## 授权`,承载双轨表述(各 4 段),**授权压轴**符合 R-O12;⚠️ 改后须复核 **英文文档汉字数 = 4**。
> - ⛔ **仍有意不带回**:`LICENSE-UPSTREAM-MIT.txt` · `THIRD-PARTY-NOTICES.md`。上游口径:**DeepSeek Harness(MIT,不包含、不分发其代码)**;README 文末保留一行对 `dshs`(MIT)的道义致敬(⛔ 不许删)。
> - ✅ **发版前必查**:`LICENSE` 被 OVERLAY 正确恢复 · `package.json` license 由规则生成 · `required present: 60/60` · **README 双轨表述中英同构** · **轨 2 文件存在且中英对等(`_check_parity.mjs` 的 `PAIRS` 已登记)**。
> 🔴🔴 **两条铁律(2026-09-17 用户连问两轮后确立,不许放宽)**:
> 1. **绝不在 AGPL 上加任何限制** —— 包括「只禁止销售源项目」这种看起来很窄的限制。依据:AGPL **§10** 禁追加 further restriction、**§7** 把非许可性附加条款定义为 "further restriction";且 **OSD 第 6 条「不得歧视任何领域」** ⇒ **判据是「有没有附加限制」,不是「限制多窄」**(Commons Clause 官方对 "Is this Open Source?" 的回答就是 **No.**)。
> 2. **也不需要加** —— AGPL 的 copyleft **本身就实现了**「防白嫖转售」:想**闭源**改造后销售/托管的人,**§13** 要求其向使用者提供全部修改源码 ⇒ 不愿开源就只能来买商业授权。**这就是双轨的全部机制。**
> ⚠️ **两条配套事实**:Commons Clause 原文 "The combined text **replaces** the existing license"(**只能替换、不能叠加**);官方 FAQ "Licenses applied to previous versions are **not revoked**"(**已发布版本收不回** ⇒ 本项目 v1.0.0–v1.2.0 永远是 AGPL)。
> 📜 **历史(2026-09-13 15:1x – 09-17 的中间状态,仅作留痕,⛔ 不是要求)**:一度把三份授权文件**全部移除**(`LICENSE` / `LICENSE-UPSTREAM-MIT.txt` / `THIRD-PARTY-NOTICES.md`),`package.json` 的 license 回到上游原值 `MIT`;09-14 一度**记录**为「AGPL + 商业授权」,但**当时 README 实际只有 AGPL 单轨**(09-17 核实并改正后真正落地双轨)。原文备份在 **`E:\ProgramData\_已移出项目_授权归档\_授权归档_发布时再放回\`**(⚠️ 09-13 曾误记为"该目录已不存在",**2026-09-18 实测仍在**;恢复步骤见 `_导出说明与脱敏台账.md` §F)。
> ⛔ **不要再照那段历史去移除 `LICENSE`** —— 那会让公开仓库退回「保留所有权利」状态。
> ⚠️ **硬法律前提(客观事实,任何会话都不许删)**:**上游 DeepSeek Harness 是 MIT,且本项目不包含、不分发其代码** ⇒ 对本项目自有部分采用 AGPL-3.0 **不构成**对上游 MIT 的附加限制。若日后要恢复「个人免费 / 商用收费」的旧思路,仍须**分层**,不得把整个仓库标成「商用需授权」。
> ⚖️ **中国司法立场(2026-09-17 查证,判例充分 —— 用户问「中国法律是否支持」时直接引这些)**:
> · **【支持】协议有效** = 「**附解除条件的著作权许可合同**」(**罗盒案** (2019)粤73知民初207号,**最高法 2021 年十大知产案件**;另有数字天堂案 · 风灵案)。
> · **【支持】不开源 = 侵权** ⇒ 授权自动终止 ⇒ 构成侵权:罗盒 **50 万** · 亿邦 (2021)最高法知民终51号 **50 万** · 南京 2022 年案 **300 万**。
> · **【支持】收费本身合法** —— 罗盒案明认「收取会员费仅用于运营维护和技术支持,**不违反 GPL v3**」;**违法的是不提供源码** ⇒ AGPL 防的是「不开源」,**不是**「收钱」。
> · **【支持】项目管理人可单独起诉**(最高法知产法庭 2024 年两案)⇒ 维权无需集齐贡献者。
> · 🔴 **【不支持】在开源项目里加商业使用限制条款** —— 罗盒案判决评析原文:「开源软件权利人**不能**在开源项目中添加商业使用限制保留条款来限制用户使用源代码的目的和用户范围,因上述限制保留条款与 GPL V3 协议保证用户自由使用的特性矛盾」。
> · ⚠️ **中国暂无 AGPL 直接判例**(判例均为 GPL);实务界将 AGPL 与 GPL 并列为 Copyleft 强传染许可,明确「**AGPL v3 将 SaaS 视为分发**,对云与 SaaS 商业模式构成高风险」⇒ 效力被认可。
> · 📌 中国实务界建议:开源作者应选 **OSI 认证许可**,**别用自定义/非 OSI 许可 —— 法律认可度低,难以保障作者知识产权**(反向印证「别用 Commons Clause」)。
> ⚠️🔴 **另有一个**不在协议、而在版权基础**的风险(本项目特有)**:中国版权保护中心 **2026 新规「纯 AI 生成的软件不予登记」**,判据 = **人类独创性智力投入**(「春风送来了温柔」案 ✅/「蝴蝶座椅」案 ❌),最高法 2026-09-07 法发〔2026〕10号 已将 AI 生成物权属列重点。✅ **已于 2026-09-17 把口径改为「人负责规划与关键判断,AI 负责实施」** —— 该口径**恰好确立人类独创性智力投入**,正面对冲这条新规(旧口径「全部代码与文档由 AI 生成」= **自认纯 AI** ⇒ 商业授权缺标的物)。仍有待办:留存人类投入证据 · 考虑软著登记 · 报价前请律师。全部细节 → `<工作根>\_授权决策与法律依据_20260917.md`。
每次发版要动的地方:`README.md` / `README.zh-CN.md` 的授权节(若条款变)· `LICENSE`(**须保持官方全文逐字节**)· `package.json` 的 `license` 字段。
---
## 6. 迭代发布 SOP
```sh
# 0) 先抢全局执行锁(会写文档库/或要动导出物时)
cd "/d/github/dsh_shenxian/dsh-server-docs"
ME="<会话名>" bash scripts/handoff-guard.sh --claim-exec "<会话名>"
# 1) 源仓库确认基线(只读)
export PATH="/e/ProgramData/.workbuddy/binaries/PortableGit/versions/1.2.0/usr/bin:/e/ProgramData/.workbuddy/binaries/PortableGit/versions/1.2.0/mingw64/bin:/c/Windows/System32:$PATH"
git -C "D:/github/dsh_shenxian" status --short --branch
git -C "D:/github/dsh_shenxian" log --oneline -10
# 2) 若本次要改脱敏/保留口径 → 先改 _build_export.py 的 GLOBAL / INCLUDE_* / DROP_SCRIPTS / OVERLAY
# 3) 重建(手工撰写层会自动快照→恢复)
cd "/e/ProgramData/AI技能/dsh-ai1net-github"
"/e/ProgramData/.workbuddy/binaries/python/versions/3.13.12/python.exe" _build_export.py --force
# 4) 改版本(三个地方一起改,否则不一致)
# package.json 的 version | README.md「版本与迭代」表新增一行 | LICENSE 的版本/日期(条款没变就不用)
# 5) 六项验证(§7)——**全绿才准交付**
# 5.5) 【**发布到 GitHub 前必做**】补齐英文版(见 R-O13)——中文是母本,英文此刻才生成
# README.en.md + PLUGIN-PORTING.en.md + 两份 README 顶部加语言切换行
# 6) 交付/推送(**R-O6:未经明确要求不做**)
```
### 6b. 多远端推送(2026-09-18 定型:GitHub 主仓 + CNB 镜像)
| 远端 | 地址 | 备注 |
|---|---|---|
| `origin` | `[email protected]:maogeigei/dsh-users-platform.git` | **主仓**(SSH,密钥顺序见 §8 坑) |
| `cnb` | `https://cnb.cool/maogeigei/dsh-users-platform.git` | **镜像**(HTTPS + 凭据管理器,已存好凭据 ⇒ 无需配 SSH) |
```sh
cd "/e/ProgramData/AI技能/dsh-ai1net-github/dsh-users-platform"
# 加镜像远端(一次即可)
git remote add cnb https://cnb.cool/maogeigei/dsh-users-platform.git
# ⛔ 只推 main —— 本地备份分支(backup-before-orphan-*)含改名泄漏期旧内容,绝不外推
GIT_TERMINAL_PROMPT=0 git push origin main # 主仓
# ⚠️ CNB 首次/大推送**必须后台跑**:实测前台 180s 被 SIGTERM 杀掉
# (仓库仅 1.67 MB、207 objects ⇒ 与体积无关,是连接/服务端处理慢),
# 后台运行 20s 完成。⇒ 用 run_in_background,别用前台短超时。
GIT_TERMINAL_PROMPT=0 git push cnb main # 镜像
# 核对「三方同 hash」——这是多远端同步的唯一验收判据
git ls-remote origin refs/heads/main | cut -c1-12
git ls-remote cnb refs/heads/main | cut -c1-12
git rev-parse --short=12 HEAD
```
⚠️ **README 里的 clone 地址保持指向主仓(GitHub)**,不改指镜像 —— 这是「多远端同步」的正常形态,CNB 页面自带自己的克隆按钮。若要改指 CNB,属改变对外口径,先问用户。
**版本号约定**:遵循语义化版本。写 README 版本表时**同时写「类型」列**(首个公开发布 / 特性 / 修复 / 内部迭代)。
**登记格式**(README「版本与迭代」表):
```
| **v1.1.0** | 2026-10-xx | 特性 | 一句话摘要(对外能看懂,不写内部档案号)。 |
```
---
## 7. 验证七件套(缺一不可)
| # | 验证 | 命令 / 判据 |
|---|---|---|
| ① | **阻断性探针 0 命中** | 脚本内置 `LEAK_PROBES` 与 `INFO_PROBES` 两档;**`blocking hits: 0`** 才放行。`INFO_PROBES`(`档案` / `交接单`)是**有意保留**的注释引用 |
| ② | 未改动文件**逐字节一致** | 抽样 `cmp -s <源> <导出>` → `IDENTICAL` |
| ③ | **行尾符不被改写** | `grep -c $'\r'` 两边相等(CRLF 源必须仍是 CRLF) |
| ④ | **能编译** | 见下「tsc 验证法」→ `tsc -p tsconfig.json --noEmit` 退出码 **0** |
| ⑤ | `install.sh` 语法 | `bash -n install.sh` + `bash install.sh --help` |
| ⑥ | **已移除项核对** | 逐一 `[ -e ]` 确认 `docs` / 两个插件目录 / `STANDARD.md` / `lib` / `node_modules` / `.workbuddy` 均不存在 |
| ⑦ | 🔴 **发布合规审查**(2026-09-17 补,用户要求) | 对**将要公开的文字**逐字过三关,见下方「合规审查三关」 |
### 合规审查三关(每次发布前必过)
| 关 | 扫什么 | 判据 |
|---|---|---|
| **侵权** | 第三方项目名 / 作者名 / 商标 / 上游仓库的原创文字 | 出现即须处理(按致敬口径写,或删) |
| **负面影响** | 事故类词:**事故 · 丢失 · 失败 · 失效 · 忘记 · 混乱 · 崩溃 · 覆盖 · 难以维护**;以及一切**自曝严重问题**的叙述 | ⚠️ **命中不必然要改** —— 判据是「**这句对外有正面价值吗,还是只在自曝**」。例:「报错而不是静默覆盖」= **设计原则**(fail loud)⇒ 保留;「已两次造成内容丢失」= 自曝事故、且易被误读成**产品可靠性问题** ⇒ 改为只讲**设计动因**,不提已发生的事故 |
| **涉政治** | 政治 / 民族 / 宗教 / 地域 / 政府 / 国际关系表述;**国家及地区指称** | 一律避免;涉中国主权与领土的表述必须与中国官方立场一致(港澳台一律写「中国香港 / 中国澳门 / 中国台湾」) |
**副作用提醒**:收紧措辞后要**同步中英两版**(结构对等、英文汉字数 = 4 的判据不因改词而放宽),并确认 `_overlay` ↔ 仓库**逐字节一致**。
**tsc 验证法**(导出物没有 `node_modules`,靠**临时联接**;用脚本而不是手敲,**并且绝不能用 recursive 删除**):
```sh
# 脚本已备好:<导出根>\_verify_tsc.mjs(建 junction → 跑 tsc → rmdirSync 拆联接)
"/e/ProgramData/.workbuddy/binaries/node/versions/22.22.2-3/node.exe" "<导出根>\_verify_tsc.mjs"
# 判据:tsc exit = 0 | junction removed = true
# 收尾再确认「导出物无 node_modules 残留」+「源仓库 node_modules 条目数未变」
```
⚠️ **绝不要用 `rm -rf` / `rmSync(…, {recursive:true})` 删这个联接** —— 在 Windows 上会**顺着联接删掉源仓库的 `node_modules`**。只用 `rmdirSync`(只摘链、不进目标)。
---
## 8. 实测坑(全部踩过,别再踩)
1. **`text` 被重新赋值导致替换未落盘** —— 脱敏函数里 `text = text.replace(...)` 之后再用 `if text2 != text` 判「是否需要写盘」⇒ 全局替换**永远不落盘**(只落行级改动)。**必须留 `orig = text` 做比较基准。**
2. **行级重写的 key 必须写「全局替换之后的文本」** —— 例:原行 `(档案 70 的 anysearch 事故…)`,key 要写 `(档案 70 的 该插件 事故…)`。用替换前的原文当 key ⇒ 静默不命中,留下半吊子句子。
3. **行级重写会丢缩进** —— 按 `strip()` 匹配就必须把**原行的 indent 补回去**(多行替换值还要给后续行也加 indent),否则 TS 缩进错乱。
4. **全局替换顺序敏感** —— `wake.html` 的专用规则必须在笼统的 `alotbuy → <baseDomain>` **之前**,否则专用规则永远不命中(会被先替换成 `<baseDomain>.com` 这种半成品)。
5. **重建会抹掉手写文件** —— 所以有 `OVERLAY`(先快照 `_overlay/` 后恢复)+ `--force` 安全闸。**验证过一次**:重建后 5/5 个 overlay 文件逐字节一致。
6. **`.git` 绝不能带过去** —— 历史里含全部内部信息;必须是**全新仓库**。
7. **Windows 下 `install.sh` 没有执行位** —— README 一律写 `sudo bash install.sh`;要执行位就 `chmod +x` 后再提交。
8. **别信「探针没命中」的直觉** —— 探针必须**在重建之后、还原 overlay 之后**跑(overlay 里也可能带泄漏)。
9. ⛔ **绝不对 `_build_export.py` 本身做批量替换** —— 脚本里同时存在「源模式」与「目标值」(例如规则 `("dshs", "dsh-web-platform")`),盲替会把**源模式**一起改掉 ⇒ **改名规则静默失效**(2026-09-13 实际误伤 4 处)。改脚本只用精确 `Edit`,改完**必须重建一次并用 grep 复查**。
10. **`Dockerfile` / `Dockerfile.dsh` 曾被整份跳过脱敏** —— `is_text()` 按扩展名判断,二者无扩展名(或 `.dsh` 不在白名单)⇒ 漏掉。已在 `is_text()` 里加特判。
11. **`package.json` 属「源派生」而非 OVERLAY** —— 手改 version / description / repository / license 会在下次 `--force` **被覆盖**。这类项目自有字段必须写成 **GLOBAL 规则**。
12. **`dshs.db` 是无前缀写法** —— `src/config.ts` 里默认库文件名不带 `dsh-` 前缀,只替换 `dshs` 会漏掉它;要单独一条规则。
13. **改名要连导出目录名一起改**,并同步两个辅助脚本里的绝对路径(`_build_export.py` 的 `DST`、`_verify_tsc.mjs` 的 `EX`),改完**重跑一次 tsc** 验证路径仍对。
14. **废弃的旧候选名要进阻断性探针** —— 改名改了两轮时(`dshs` → 中间候选 → 终选),若只探最老的那个名,**中间名会静默残留**(`_overlay` 里最容易中招)。做法:把**所有曾用名**都加进 `LEAK_PROBES`。
15. **改 overlay 的自指标识可以做批量替换**(overlay 里只有本项目自己的标识,上游出处名是另一个字符串)—— 但**必须先用 grep 确认「旧名出现处全是自指」**再替换;`_build_export.py` 本身**绝不**能这么干(见坑 9)。
16. 🔴 **`--claim-exec` 的输出必须当场看;claim 与 release 绝不能写进同一条命令**(2026-09-13 **实际闯祸**)—— 把 claim 结果重定向到文件、只显示 `OWNER` 首行 ⇒ **没发现抢锁失败**;命令末尾的 `--release-exec` 是 `rm -rf` 语义,于是**把另一个会话(`R1-注入层-1104`)的锁删掉了**。正确姿势:
- 抢锁**单独一条命令**,且**当场看它的输出**(`✓ 已持全局执行锁` vs `✗ 抢锁失败`);
- 看到「占用者」不是自己 ⇒ **立即停手**,不碰文档库/代码库;
- **放锁前再 `cat 交接单/.exec-lock/OWNER` 确认首行是自己**;
- 万一误放:脚本实现是 `rm -rf "$LOCKEXEC"`、**不留档** ⇒ 按 `handoff-guard.sh` 第 43 行的格式原样重建(`OWNER` / `开始:MM-DD HH:MM` / `在做:…`,值取自抢锁失败时的输出),再用 `bash scripts/handoff-guard.sh` 的信息模式验证「占用者」已回到原会话,并**在回复里明确告知用户**;若该会话其实已结束,请用户自行撤锁(处置权只属于用户)。
17. 🔴 **迁移工作根:先改脚本常量,再搬目录**(2026-09-13 实际踩)—— 顺序颠倒(先 `mv` 后改 `OUT`)时,任何一次重建都会**在旧位置把整个仓库重新建出来**(那次建出 135 个文件),而且因为旧位置**没有 `_overlay`**,**6 个手工层文件(README / LICENSE / NOTICE / PLUGIN-PORTING / install.sh / LICENSE-UPSTREAM-MIT)全部缺席** —— 若此时旧目录被当成交付物,就是一次「文档凭空消失」的事故。
**正确顺序**:① 改 `_build_export.py` 的 `OUT` **和** `_verify_tsc.mjs` 的 `EX` → ② 复制/搬运目录 → ③ 在新位置重建 → ④ 核对 `文件数` 与**手工层 6/6** + 跑 `tsc` → ⑤ **`ls` 确认旧位置不存在**(没被重建复活)→ ⑥ 同步本技能与项目 MEMORY 里的路径引用。
⚠️ 附带教训:`_build_export.py` 的安全闸与 OVERLAY 机制**都依赖 `OUT` 指向真实工作根**;`OUT` 指错时它**不会报错**,而是**默默在别处新建一套**。
18. 🔴 **`INCLUDE_DIRS` / `INCLUDE_FILES` 是白名单:漏了不报错,只是少文件**(2026-09-13 实际踩:`assets/` 漏收录 ⇒ 导出的仓库缺注入脚本,平台会 fail-fast、自带校验脚本也会失败)。**两条防线**:
- **`REQUIRED_EXPORT` 清单**(脚本内,26 项):构建时逐个 `os.path.exists`,**缺一即 `return 1`**;新增"运行时要读的文件"必须加进去。
- **用被导出仓库自带的校验脚本验收** —— `node scripts/verify-inject.cjs`(读 `assets/inject/*.js` + 检查 `proxy.ts` 走 `loadInject`)。这比"我看了一眼目录"可靠得多。
⚠️ 同类风险点:`package.json` 的 `files`(npm/git 安装按它过滤,与 `INCLUDE_*` 是**两套名单**,都要补)。
19. 🔴🔴 **`cp _overlay/<f> <仓>/` 会把「下一版内容」整份带进当前版**(2026-09-18 血证,已误发上公网)—— `_overlay/` 在**改名窗口期**是「未来版」,导出仓是「当前版」;为修一处残留引用而 `cp _overlay/README.md` 覆盖旧仓 ⇒ 把 **新名 + 新中文名 + `git clone …/<新仓>.git` + `cd <新仓>` + `systemctl is-active <新仓>`** 一并推了上去。
⛔ **真实危害不是"名字不对"而是功能性缺陷**:README 让用户 clone 的那个仓库当时**是空的**(只有建仓提交)⇒ **照 README 做的人克隆到空仓库,部署直接断**。
✅ **规矩**:`_overlay` 处于下一版状态时**绝不整文件 `cp` 到导出仓**,只准**逐处精确 `Edit`**,只落本次要发的那几段。
⚠️ **最阴的一点**:这种误覆盖会让「导出仓 vs `_overlay` 的 diff **变空**」—— **diff 为空本身就是"新版被覆盖进去"的证据**,不是"一致"的好消息。**看到意外的一致要停下来查原因。**
✅ **推前必做两条复核**:① `grep -rn "<新名>\\|<新中文名>" .` ⇒ **须为空**;② **部署命令自洽** —— `git clone` 指向的仓库**真有内容**、`cd` 的目录名、`systemctl` 的服务名三者一致。
20. 🔴 **新增「中英文件对」时必须同步登记 `_check_parity.mjs` 的 `PAIRS`**(2026-09-18 实证)—— `PAIRS` 是**白名单**:没登记的文件对**不会报错,而是静默跳过对等检查**(标题数 / 表格行数 / 图数 / 英文汉字数全部不检)。⇒ 新增 `X.md` + `X.zh-CN.md` 时,**三处一起改**:`OVERLAY` · `REQUIRED_EXPORT` · **`PAIRS`**。
⚠️ **同类静默跳过已出现三次**(坑 18 `INCLUDE_*` / `REQUIRED_EXPORT`、本节 `PAIRS`)⇒ 判据统一为:**凡"清单式"机制,新增对象后必须回读清单计数是否 +N**(AST 实读,别数文件)。
21. **`COMMERCIAL-LICENSE.*` 的落位规矩(2026-09-18 立)**:① 只在**四份 README**(仓 + `_overlay/` 各中英)授权节尾加**一句**链接,⛔ 不在正文铺开;② ⛔ **不得**把「商用须授权」的句子写进 `LICENSE` 或 README 的 AGPL 段落(那才是 §10 追加限制);③ 英文版**汉字数仍须恒为 4**(只在顶部入口行出现「中文文档」)。
---
## 9. 命令速查
```sh
# 重建
cd "/e/ProgramData/AI技能/dsh-ai1net-github"
"/e/ProgramData/.workbuddy/binaries/python/versions/3.13.12/python.exe" _build_export.py --force
# 只跑探针/看结构(不重建)
grep -rIlF "alotbuy" dsh-web-platform/ ; find dsh-web-platform -type f | wc -l
# 看某文件与源的差异
diff -u "D:/github/dsh_shenxian/<f>" "dsh-web-platform/<f>"
# 行尾对照
grep -c $'\r' "<源 f>" ; grep -c $'\r' "dsh-web-platform/<f>"
```
---
## 10. 已知待办 / 漂移(接手先看)
> ✅ **2026-09-13 15:1x 全部清零** —— 以下原待办均已处理:
> · `install.sh` 已在服务器隔离目录跑通 `--dry-run`(并修 4 个缺陷)| · 悬空 `docs/*.md` 42→0| · 「档案 NN」197→0| · 7 处占位符已按 `PUBLISH_*` 填| · `poc/` 两个插件的加回结论 = **保持移除**。
> ⛔ **「授权条款 / 法律意见 / `上游作者(已按要求不再具名)` 是否本人」已从本项目移除** —— 用户明确「你的任务是改造和优化,这些内容全部删除」⇒ **不再列为待办、不再上抛**(事实层面的 MIT 约束见 §5,那条不许删)。
**当前仍需注意的(非待办,是风险提示)**:
- ⚠️ **首装从未在干净机器上真跑过**:`--dry-run` 已验证全流程,但**真实安装会写 `/etc`、建 systemd unit、起服务** ⇒ 首次真装请在一台干净机器上做。
- ⚠️ **导出基线会漂**:导出脚本复制的是**工作树**(多会话并行在改源码仓)⇒ 发布前按 `git archive <commit>` 冻结,或**每次重建必重跑探针 + `_verify_tsc.mjs`**。
- ✅ **项目名已定稿**(用户 2026-09-13):中文 **DSH Web 平台** | English **DSH Web Platform** | 技术标识 **`dsh-web-platform`**(已在 npm 与插件目录实测未占用)。若日后要换名,按 **R-O8** 重走「查占用 → 改全量标识 → 保留出处致敬」,并把**新废弃的旧名加进探针**。
- ✅ **本技能的归档副本 + `INDEX.md` 登记已补**(2026-09-13):`dsh-server-docs/skills/dsh-opensource-release/SKILL.md`,两副本 md5 一致;INDEX §一/§二 已登记;四件套全绿。
⚠️ **本技能每次改动后都要同步归档副本**(md5 必须一致),同步前**先抢全局执行锁**;纪律 = 先单独抢锁**当场看输出** → 验 `OWNER` 是自己 → `cp` → 两副本 md5 一致 → 复跑四件套 → **再验 `OWNER`** → `--release-exec`。
- ⏳ **英文版待生成(发布前必做,见 R-O13)**:`README.en.md` + `PLUGIN-PORTING.en.md` + 两份顶部的语言切换行。**当前刻意不做**(用户口径:中文优先,同步 GitHub 时再更新英语)—— ⚠️ 但**切换行要等英文文件存在后再加**,否则是死链。
- 🔴 **导出基线会漂(2026-09-13 11:2x 实测)**:导出脚本复制的是**工作树**,而**多个会话在并行改源码仓** —— 当时 `D:\github\dsh_shenxian` 的 HEAD 仍是 `da3e0f9`(⚠️ 2026-09-13 20:2x 实测已变为 **`43976fe`「初始提交」**,且**仅 1 条提交**),但**工作树有 20 个未提交文件**(`orchestrator.ts` / `crash-policy.ts` / `proxy.ts` / `spawner.ts` / `config.ts` / `web/*.html` / `test/*` …),导出里因此混入了**别人未完成的改动**;同时新增了需脱敏的标识(`'dsh-plugin-mcn-suite'`)触发探针。**发布前必须二选一**:① 把导出改成**按 commit 取**(`git archive <commit>`,才是"冻结版本");② 或明确接受"含未提交工作"并**每次重建后重跑探针**(新增插件名/内部名会随别人提交冒出来)。
- ⚠️(知识库侧,非本技能职责):本机 `.workbuddy/skills/dsh-instance-diagnose/` **尚无归档副本**;`INDEX.md` 只登记了 3 个 skill(`dsh-knowledge-upkeep` 未登记)。属既有漂移,**未擅自修**。
---
## 相关
- 台账(唯一事实源):`_导出说明与脱敏台账.md`(在本工作根下)
- 构建脚本:`_build_export.py` | 类型检查:`_verify_tsc.mjs` | 手工层快照:`_overlay\`(三者都在本工作根下)
- **插件移植指南**(随仓库发布):`dsh-web-platform\PLUGIN-PORTING.md` —— 讲「把开源插件改造成多租户平台可用」,含六个失败模式 H1–H6 与五条规范 R-a~R-e,样本 = `dsh-univer-office`
- 内部权威源(**只读参考,不外带**):`dsh-server-docs/04-调整方案/75-*.md`(托管友好性 + 资源成本两维度)· `76-*.md`(univer 改造全过程)· `71-*.md`(兼容性预检)
- 技能:`dsh-change-workflow`(改动流程与红线)· `dsh-knowledge-upkeep`(文档库维护)· `dsh-instance-diagnose`(实例故障)
- 项目事实:`dsh-server-docs/BRIEF.md`(现行事实)· `dsh-server-docs/CODEBUDDY.md`(动作前规则)