# 工作日志 · 2026-09(第 15 片) > ⚠️ **本目录日志已按【月】分片**(2026-09-15 用户定,单文件 ≤50 KB):同月续片 `2026-09.md` / `2026-09-下.md` / `2026-09-下2.md` / `2026-09-下3.md` / `2026-09-下4.md` / `2026-09-下5.md` / `2026-09-下6.md` / `2026-09-下7.md` / `2026-09-下8.md` / `2026-09-下9.md` / `2026-09-下10.md` / `2026-09-下11.md` / `2026-09-下12.md` / `2026-09-下13.md` / `2026-09-下14.md` / `2026-09-下15.md` / `2026-09-下16.md` / `2026-09-下17.md` / `2026-09-下18.md` / `2026-09-下19.md` / `2026-09-下20.md` / `2026-09-下21.md` / `2026-09-下22.md` / `2026-09-下23.md` > **写入约定**:一律 append 到**当月最后一片**;该片超 50 KB ⇒ 新建 `2026-09-下N.md`;⛔ **不要再按日新建 `2026-09-DD.md`**。 > **覆盖来源**:2026-09-13.md > **上一片**:`2026-09-下13.md` **下一片**:`2026-09-下15.md` --- ## 11:21–11:3x · 把本轮教训升格为技能「重点规则」(用户:避免后续犯傻) **用户指令**:「把这些纳入重点规则 放在 skill 中 避免后续犯傻」。 ### A. 技能 v1.2.0 三项改造(`dsh-opensource-release`) 1. **新增 `## 0.5 🔴 事故清单`** —— 放在「何时用」之后,开工前 30 秒读完。**8 条真实事故**:误放别人的锁 · 导出基线会漂 · 盲替脚本自身 · Dockerfile 漏脱敏 · package.json 被重建覆盖 · 废弃候选名静默残留 · 文档文案连改 7 轮 · 脚本用键名当标题。每条给「正确做法 + 详址」。 2. **规则升格与重排** —— 原先埋在 `R-O8 命名规则` 下的三个「附则」**升为顶层规则**:`R-O10 出处的位置与措辞` / `R-O11 README 内容口径` / `R-O12 README 结构顺序`,并把 `R-O9` 排到 R-O8 之后;§1 标题改为「**硬规则 R-O1–R-O12**」并补全索引(原只有 R-O1–R-O5 + R-O6/7/8)。 3. **修掉两条自相矛盾的旧规则**(隐患最大):① 「措辞」行还在教写「此后在本仓库做了**大量深度改造**」(**正是用户否掉的写法**)→ 改为「起步时参考了 X(作者,许可证)—— 感谢作者开源」;② 「难在哪」行的示例引用了**被禁的**「多租户演示十分钟就能写出来」→ 改为「心里有数、但别写进 README」。 ### B. 又踩一个(已进事故清单第 8 条) 结构改写脚本里写成 `marks[k][0]` —— 拿到的是**键名** `"A"` 而不是标题字符串 ⇒ `replace` 打歪:把 `README` 的 `A`/`D` 替换掉、把 `PoC` 的 `C` 删掉,两处标题没改名。**已全部精确修回**(改完读回原文复核)。教训:**结构改写要用完整标题字符串做锚点,改完必须读回复核**。 ### C. 锁纪律首次按新规矩执行(成功) 锁在 11:25 释放后:**① 单独一条命令抢锁并当场看输出**(`✓ 已持全局执行锁(oss-sync-1125)`)→ **② 另一条命令里先断言 `OWNER == 自己` 才动手**,末尾**再验一次 OWNER** 后才 `--release-exec`。同步技能归档(md5 一致)+ 四件套 rc=0;因 §10 记录更新需再同步一次,第二遍同法执行(`oss-sync-1127`,md5 `dab0ce55…`)。**全程未触碰别人的锁**。 **现状**:技能 **v1.2.0**,两副本 md5 一致(`dab0ce55…`),文档库无锁,四件套 rc=0。**未 scp**(等用户发话)。 ## ⚠️ 11:28 我犯的**流程事故**(如实记录,已报告用户) **事实**:本轮改档案 81 时,我把「抢全局执行锁」与「写文档」写在同一条命令里用 `;` 分隔 —— 抢锁**失败了**(当时锁被并行会话 **`oss-sync-1127`** 持有,11:24 起),但**后续写操作照样执行**: ① 写了 `04-调整方案/81`(2 行替换 + 追加 §10.6)② 重新生成并推送了 `docs-manifest.json`; ③ 结尾执行 `handoff-guard.sh --release-exec`,**把别人的锁放掉了**(现已确认 `.exec-lock` 不存在)。 **违反了什么**:R9 的精神(锁的处置权只属于用户本人)+ 本库「抢不到锁 = 停手」的硬规矩。 **根因**:`claim; write` 是**两条独立命令**,抢锁失败**不会**让后面的 write 停下 —— 我的脚本没有做退出码检查。 (另外:`--release-exec` 未校验「我是不是占用者」,这也放大了后果。) **纠正(写进 MEMORY.md,必须遵守)**: 1. **抢锁必须与写操作用 `&&` 串联**(`claim-exec ... && <写操作>`),**抢锁失败即整条命令中止**; 2. **写库前先肉眼核一次 `交接单/.exec-lock/OWNER`**,不是自己就停手; 3. **`--release-exec` 只在确认 OWNER 是自己时执行**; 4. 抢不到锁时的合规动作只有:**停手 + 报告用户**(不触碰锁状态,不代用户判断)。 --- ## 11:25–11:3x · 核心卖点上移:「全部代码与文档由 AI 生成」 **用户指令**:「还有个重点要加载前面 —— **所有项目和文档全 AI 生成,使用模型 DeepSeek V4 / V4.1 和 WorkBuddy**」。 **README 三处落地** 1. **Hero 区**:新增 2 个徽章(`code & docs-AI-generated`、`DeepSeek V4 / V4.1 × WorkBuddy`,共 6 个,未超审计上限 8)+ **一行声明**:「**全部代码与文档由 AI 生成**(DeepSeek **V4 / V4.1** 模型 × **WorkBuddy**)—— 一个可运行的、完整的多租户服务端。详见 AI 生成」。 2. **新增 `## AI 生成` 专节**,置于**第一个正文章节**(目录之后、亮点之前):覆盖范围表(`src/`·`web/`·`scripts/`·`deploy/`·`Dockerfile*` ✅ / README·PLUGIN-PORTING·LICENSE·NOTICE·install.sh ✅ / `test/` + 9 个 `smoke:*` ✅)+ 一句「人负责定方向、提需求与验收」+ 一句「可当作『AI 能不能独立写出可控的多租户服务端』的样本(含如实标注未验证能力)」。 3. 目录与章节顺序同步 → **17 节**,TOC **17/17 锚点正确**;探针 0;495 行。 **技能 v1.3.0**:§0 事实新增「**内容来源**」行(明示三处一个都不能少:Hero 一行 + 2 徽章 + 首个正文章节);R-O12 顺序图更新并把 6 个徽章写进去。台账 §九 C 同步。 **⚠️ 遗留待用户确认(已当面提出)**:声明写的是「**全部**代码与文档由 AI 生成」。若起步阶段那份骨架(`上游骨架仓库(已按要求不再具名)`,123 个提交)不是 AI 写的,「全部」就偏大 —— 备选措辞是「**本仓库全部内容**由 AI 生成」(把范围限定在本仓库)。用户一句话即可改。 **归档同步**:技能归档副本已同步(md5 `f4bf7eb9…`),四件套 rc=0,全程**锁:先单独抢 + 断言 OWNER + 放前再验**,未触碰别人的锁。 --- ## 11:29–11:3x · 出处收敛为「一行致敬」(用户裁定) **用户指令**:「如果起步阶段那份骨架(上游骨架仓库(已按要求不再具名),123 个提交)**这个都全部改造了,致敬就可以了**」—— 同时等于**回答了我上一条的疑问**:「全部代码与文档由 AI 生成」这个**宣称成立**(骨架已被整体重写),不必再加"范围限定"的补语。 **改动(README 2 处 + NOTICE 2 处 + LICENSE 1 处)** | 位置 | 改前 | 改后 | |---|---|---| | README 授权表 行1 | 「**上游基础部分**|起步时参考的骨架代码:认证 / 桌面 / 单 DSH 启停与反代 / 每文件夹插件 / 双部署框架」 | 「**起步骨架部分**|起步时参考的骨架(**此后已在本仓库整体改造**)」——**去掉逐项枚举**(枚举=把自己继承的份量说大) | | README 授权表 行2 | 「本项目新增与修改部分|由本项目维护者新增/修改的代码」 | 「**其余全部代码**|新增与重写的源码、配置、脚本与文档」 | | README 授权摘要 | 「上游基础部分保持 MIT」 | 「**起步骨架部分**保持 MIT」 | | NOTICE §4「本项目」行 | 「以上游骨架为基线继续演进」 | 「起步骨架来自该项目,此后已在本仓库**整体改造**」 | | NOTICE §4「致谢」行 | 「认证与审核…双部署框架等骨架能力均源自上游。感谢 上游作者(已按要求不再具名) 的开源工作。」 | 「**感谢 上游作者(已按要求不再具名) 的开源工作。**」 | | LICENSE 第一层 | 「上游骨架:认证与审核、网页桌面、单 DSH 启停与反向代理、每文件夹插件、模式 A/B 部署框架」 | 「起步骨架;**此后已在本仓库整体改造**。⚠️ 尽管做了整体改造,其版权与许可声明按 MIT 要求**依旧完整保留**」 | **⚠️ 明确保留没动的部分(保守合规)**:`LICENSE-UPSTREAM-MIT.txt` 逐字节未动;授权**分层结构**保留;`LICENSE` 第一层的 MIT 声明保留 —— **改造过也不删**(万一还有残存代码,这是保命条款)。 **技能 v1.3.1**:R-O10 新增该口径(骨架已整体改造 ⇒ 只留一行致敬、去掉枚举;但 MIT 声明与授权分层照旧保留)。归档副本已同步(md5 `b73cd62e…`),四件套 rc=0,锁按新规矩走。验证:探针 0、TOC 17/17 锚点正确、README 495 行。 --- ## 11:30 · 更正我自己的错误结论:官方**有** i18n(档案 81 §10.7) **起因**:用户追问「有哪里是需要 替换官方包 / 改官方代码的」。核查时发现 §10.6 的结论建立在不完整抽查上(当时只看到 locale 包里有个 `README.i18n.yaml`,就当成"只是文档翻译")——**错了**。 **实测(服务器只读)**: - `@deepseek-ai/dsh-client-locale`(v0.1.2-rc.1,MIT)真实存在:`lib/index.js` 1.3 KB(host)+ `lib/client.js` 55.5 KB(含内置词典)。 - host 侧只注册 settings 命名空间 `locale` / 字段 `preference`;`LOCALE_IDS = ["zh","en"]`(**随包只发这两种**)。 - client 侧导出 `LocaleRuntime` / `COMMON_NS` / `FALLBACK_LOCALE` / `SETTINGS_NS` / `apply` / `inject`;内置 `common` 词典 = 通用词(确定/取消/关闭/复制成功…)。 - **官方文档给出的扩展 API**:`ctx.locale.addLanguage({id,label,fallback})` + `ctx.locale.register(ns, lang, {...})`,消费走 `ctx.locale.bind(ns)` 或框架 `t` 座位;设置入口 **Settings → General**。官方原话:shipped `zh`/`en`,"external client plugins **can add languages** and their namespace dictionaries"。 - **但官方没铺开**:只有 2 个官方 UI 包引用了 locale(`conversation`、`directory-picker-browse`);其余大量硬编码中文 —— `trajectory` 167 行、`conversation` 138、`chat` 99、`settings-models` 98、`workspace` 64、`settings-plugins` 50、`agent-preset` 50 … **结论(对 R5 选型的影响)**:新增第 4 个选项 **`D · 走官方 locale 体系`**(自研插件 + 浮层文案用 `addLanguage`/`register` 跟实例内语言开关联动,**不触 R2**)= §10.4 方案 C 的加强版。原先 A/B/C 三项保留。 **"要不要替换官方包 / 改官方代码"的净答复**:平台页 / 注入层 / 自研插件 —— **零官方改动**(都走官方扩展点);官方已迁 locale 的包 —— 切语言自动跟随(白拿);官方**仍硬编码**的 20+ 个包 —— 只能注入层改 DOM(脆弱、覆盖不全),**替换官方同名包 = 改官方产物 ⇒ 触 R2 ⇒ 不做**。 **教训(已写进 §10.7 末尾)**:上一轮的错在**用一个文件名代替「读一读那个包」**就下了"官方没这个能力"的结论。凡结论会影响方案取舍(尤其"做不了"这类),**必须落到实测证据**,不能靠抽样直觉。 **收尾**:档案 81 就地改掉那两处错句 + 追加 §10.7 + §10.5 加 D 选项交叉指针;四件套 rc=0。**未 scp、未 commit**(按 §4 等用户发话)。同步对账报 5 处内容不一致 + 2 处仅本地(含既有的档案 42,**非本次改动,未动**)。锁:claim → 验 OWNER → 改 → 四件套 → 再验 OWNER → release,全程合规。 --- ## 11:35–11:56 · 回答「改造完成了吗 / 部署了吗 / 能用吗」→ 真机验收 **结论:R0+R1 已部署上线且真机可用;R2–R5 未做。** **部署实证**(只读 ssh): - 服务 `active`,**11:14:45 重启**(`lib/supervisor/proxy.js` 产物 11:14:44 → 产物早于启动 = 新代码在跑)。 - `assets/inject/{recovery,assist}.js` 于 11:09 上传;编译产物含 `loadInject`(6 处)、**不再有内联模板字面量**(0 处)⇒ R1-① 已落地。 - 服务器 `/opt/dshs` HEAD 仍 `b23e386`,但**工作树有 ~19 M + `?? assets/` + `?? scripts/verify-inject.cjs`**,且已 build+重启 ⇒ **服务器工作树不再是干净基线**(MEMORY.md 已记,下次同步前必须比对)。 - R3 双名期三处 symlink 确认(11:17):`/opt/dshs`、`/var/lib/dshs`、`/etc/systemd/system/dshs.service`。 - `assets/` 下只有 `inject/` ⇒ **R5 i18n 词条目录尚不存在**(未做)。 **真机验收**(无头 Chrome `channel:'chrome'` + R4 允许的临时会话 `mksess-guest.cjs`,用后即删): | 项 | 结果 | |---|---| | 公网首页 | `https://alotbuy.com/` 200,title=**工作台** | | 去痕迹 | 6 个平台页 **0 处 `dshs`** | | 登录页新版 | `is-busy` 命中 3;两段式文案「登录中」→「正在进入工作台」 | | 过渡页 | title=正在启动工作区;`wk-orb` 命中 | | 注入是否真执行 | 2 个 `