Files
dsh_ai1net_server/.workbuddy/memory/.backup-20260916/MEMORY.md
T

56 lines
12 KiB
Markdown
Raw Normal View History

# DSH 平台 — 记忆(**状态层**)
> **判据**:不看它会不会导致「违规」或「事故」?会 ⇒ 写实体;只"更慢更绕" ⇒ 只留指针。
> **落点**:动作前必须生效的规则 → 根 `CODEBUDDY.md`(**不在此重复**)|**会变的状态**(在途单/版本/基线/位置)→ 本文件|方法论 → 技能|一次性事实·复盘·命令原文 → `PLAYBOOK` / `04/<NN>`|当天流水 → `memory/YYYY-MM-DD.md`|跨项目偏好 → `~/.workbuddy/MEMORY.md`。
> 📄 **详版 = `.workbuddy/memory/PLAYBOOK-实例与插件坑.md`**(**报障第一件事就开它**)。§ 速查:1 插件边界|2 GLIBC|3 插件加载失败三真因|4 铺插件陷阱|5 ETag|6 技术债|7 K8s 清理|8 兼容收口|9 实例取数四坑 + UI 分区三步定位 + 部署硬规矩|10 本机 Python 编码坑|11 去查索引|12 省积分。
## 一、最近闭环
- **09-16 覆盖网络线**:10 份规划转正式档案 **103–112**(`4e3a1a4`)+**会合/中继拆分只读取证与改造方案**(工作区根 `会合中继拆分_取证与改造方案_20260916.md`,S0–S4)。零代码、零服务器改动。
- **09-15 T08 集群化 + 生产整体切换**|档案 96 实例内存与插件开关解耦|档案 100/101 实例内「我的技能」+ 改名「能力管理」+ 页内 tab(`business-plugins` 0.3.22)|档案 102 语言切换搬入「用户设置」(0.3.23 + `portal-entry` 0.5.5)|档案 93 兼容收口|档案 88 内置 dsh 安装路径探测。
- 🔑 **「用户设置」= 我们自己的 `@dsh-local/portal-entry`**(id `user-settings` / order 103 / label 存**转义 unicode** ⇒ 按 UTF-8 grep 搜不到);语言走官方 `ctx.locale`;持久化 = `POST /api/me/locale` 写用户 `settings.yaml`。⇒ `07-实例UI分区登记表.md`;🔧 `node scripts/find-ui.mjs [关键词]`。
- 交互规则 4 连改(待拍板项**置末 + 逐条编号 + 候选竖排成段 + 必须写优缺点**)已固化进 `dsh-change-workflow §5`。
## 二、状态速查
| 项 | 状态 |
|---|---|
| **在途单** | **无在途**(`T01–T08` 全完成归档)。T08 残留见 `03-路线图 §二` 🟡 |
| **生产形态(09-15 起)** | 47 = **Manager**(cluster;控制面库 = 47 上 PG13 `/var/lib/dshs-pg`,单元 `dshs-pg`,`127.0.0.1:15432`)+ 本地 Worker `w-47`(19100);**106 = Worker `w-106`(19000,经 SSH 反向隧道)**。存量用户锚 `w-47`、新用户按容量落 `w-106`(**粘性优先**)。**09-16 `guest` 已迁至 `w-106`**(epoch 4)。⚠️ **权威库 = 47 的 PG**,`/var/lib/dshs/dshs.db` 仅回滚用。⛔ 47 兼作 Worker 是**有意设计**、别当待修项。**回滚** = 删 `…/dshs.service.d/cluster.conf` + `daemon-reload` + `restart dshs` |
| **106 节点** | 已补齐实例运行能力(dsh 0.1.5-rc.1 + `/usr/local/bin/dsh` + `/usr/local/dsh-runtime` + `/var/lib/dshs/{bundled-skills,business-plugins}` + **`users/` 权限 711** —— 原 `drwx------` **会致实例必崩**);ffmpeg/ffprobe 已用**内网源 dnf** 装好(⛔ 别再想"从 47 搬")。⏳ **provisioner 未铺**(新用户落 106 无人建号)。⚠️ 有**旧控制面** `dsh-users-platform.service`(3080,早于集群化切换)⇒ 待拍板清理。方案 = `跨节点迁移与节点自举_完整流程方案_20260916.md`(工作区根) |
| 集群化 | 单一来源 = 项目根 `集群化改造方案_Manager-Worker_20260914.md`;D1–D5 已定,⏳ 仅 **D6**(不阻塞);数据分层判据见 §三 |
| 实例内存(档案 96) | 与插件开关**解耦**:`MemoryHigh=MIN=448` + `MemoryMax=MAX=1024`;`/api/dsh/status` 带 `quota{...}`。⚠️ `MEM_TABLE` **仅预估、不驱动配额** |
| 安装路径(档案 88) | ✅ 走 `src/web/dsh-install.ts`(env 认 `DSHS_DSH_BIN` / `DSH_USERS_PLATFORM_DSH_BIN`);导出侧待重建 |
| R2–R5 | R2 管理面就地化 / R3 标识迁移 / R5 多语言 ✅;**R4 ✅ 选 (a) = 文档库并入代码仓** |
| 个人技能(用户自传) | ✅ 全链路;后端 6 路由(`requireAuth`);启用位 `$DSH_HOME/skills` / 禁用位 `home/skills-library`(watch 即时生效) |
| 归档编号 | 至 **112**(103–112 = 覆盖网络线 10 份);**63 空号**,勿补占 |
| **覆盖网络线** | 入口 = 工作区根 `接续入口_覆盖网络线_20260916.md`;**零代码零服务器改动**。🔑 第一件实事 = 会合/中继从 Manager 拆分(方案已出)⇒ ⏳ **唯一待拍板 = 骨干服务范围**(档案 **105 §七**,倾向 A→B 渐进) |
| 熔断 / MCN / univer | 熔断 78:冷却 6h + 双通道告警已上线,**L1 实测未做**|MCN 0.3.10 已铺发,`mcn-task` 重复建组未解|univer = **内存探针,有意保留 ⇒ 勿以下架** |
**提交基线**:代码仓 **`4e3a1a4`**(未提交:`scripts/*.py`×3、`skill-load-guard.py`(新)、`skills/*/SKILL.md`×3、`package.json`、`src/worker/agent.ts`、`bootstrap-worker.sh`(新)、`test/worker-provision.test.mjs`(新))。**均未 push**(对账 `git ls-remote origin refs/heads/master`;本机 `refs/remotes/**` 写不进去)。
🗣 **称谓**:**「本机」只能指跑 WorkBuddy 的开发机**;47 / 106 一律写「远程服务器」或用 IP。
## 三、本机铁律(CODEBUDDY.md 未覆盖的部分)
- 🔴 **R10 实例起不来先查属主 / EACCES,别先怀疑 OOM** —— root 跑 `dsh --profile` ⇒ 属主变 root ⇒ 崩溃循环 / 404。修 `find <home> -user root -exec chown <uid>:<uid> {} +` → 重启。⚠️ 用户 home 是 watch 域 ⇒ 读不了的文件同样致命 ⇒ 平台侧备份一律 `/opt/dsh/backups/`。
- 🔴 **改 bwrap 参数前先看目标机 bubblewrap 版本**(**47 = 0.4.0 / 106 = 0.11.0**):`--perms` 属 0.5+ ⇒ 47 上 `Unknown option` ⇒ **沙箱起不来 = 所有实例全挂**;要权限**用 `--tmpfs`**。⚠️ `smoke-isolation` **不能**作 account 模式验收。⇒ `交接单/T08-§10`。
- 🔴 **集群化数据分层判据**(用户原话:「不一定 worker 不连数据库…」):① 归属/租约 ⇒ **只有 Manager 能写**(双写 = 脑裂)② 跟着用户走 ⇒ 放**实例 home**,别塞控制面 PG ③ 本机运维用 ⇒ **Worker 本地库**。⇒ 设计文档 §1.3。
- 🔴 **hook 脚本必须走 `sys.stdout.buffer.write(bytes)`** —— 文本层 `sys.stdout.write` + 文案含 `⛔` ⇒ 宿主 stdout 非 UTF-8 ⇒ `UnicodeEncodeError` ⇒ **stdout 空 ⇒ 静默放行**(日志却写 deny ⇒ 表现成"判了但拦不住")。判据 = **"写日志 + emit"双动作且 emit 走 buffer**。`PreToolUse` 的 `deny` **确有效**;锁主力仍是三把锁 + `handoff-guard.sh` + 约定,hook 是加固层。⛔ 别再写"hook 拦不住"。📂 自证日志真路径 = `D:\github\dsh_shenxian\.workbuddy\lock-hook.log`(跟 `DOCS_ROOT` 走)。⇒ PB §10。
- 🔔 **技能加载闸门(09-16 装)**:钩子 `dsh-server-docs/scripts/skill-load-guard.py` —— 命中「决策方法 / 参考决策 / 按你的规划 / 别问我 / 自行决策 / 自主决策」⇒ 自动注入"必须先加载 `dsh-decision-method`"(急停 `DSH_SKILL_GUARD_OFF=1` 或 `.workbuddy/skill-guard.disabled`)。⚠️ **需完全重启才加载**。
- 🔴 **两条命令坑**:① `pkill -f` 要匹配"实际 argv" ⇒ ✅ 按端口定位 `ss -lntpH 'sport = :PORT' | grep -oP 'pid=\K[0-9]+' | head -1`。② **`fetch` 静默丢 `Host` 头**(undici)⇒ 多租户验证落到"无租户"路由、**假 404/200** ⇒ ✅ `curl -H "Host: …"`、别跨用户测、判据别只看状态码。
- 🔴 **「单机自用」≠「不需要互联」**(09-16 用户原话:「**单机用也要互联,这正是建立覆盖网络的目的**」):**租户维度收窄(1 个用户)与网络维度收窄(1 台机器)正交** ⇒ ⛔ 不得再用"单机自用所以没流量要互联"当前提(推演 v1 因此作废、已重写 v2)。
- 🔴 **覆盖网络按异构设计**:① **中继按 45% 设计、55% 留余量**(⛔ 别用同构假设的 15%)② **必须补 443/TCP 兜底**(否则封 UDP 的整类节点进不来)③ 有公网 IP 的节点自动升格为中继候选,但**权威状态仍必须单点 Manager** ④ VPN/代理类**检测即降级中继**,不重试 ⑤ **节点自报网络画像**。
- 🔴 **方案只做技术实现,合规不进方案**(09-16 用户原话:「**方案只考虑技术实现,跨境数据合规是谁用谁自己考虑**」)⇒ ⛔ 不再把合规 / 数据主权 / 备案当前置条件、约束或上抛项。多区域就近 = **性能**最优,不是合规动作。
- ⚠️ **本机执行环境**:**Python stdin/stdout 必须走 `buffer` 显式 UTF-8**(`-E` 屏蔽 `PYTHONUTF8=1` ⇒ cp936 ⇒ 含中文静默炸)|改文件**必用 `newline=""`(读也要)**|**ESM**|bash **PATH 被 shim 重置** ⇒ 先 `export PATH=<PortableGit>/usr/bin:…:/c/Windows/System32:/c/Windows:$PATH`|**Python 原生 exe 不认 `/e/…`** ⇒ 传参 `E:/…`|bash 内联 `\` 被 MSYS 改写 ⇒ 含 Windows 路径的 Python **落成 .py 再跑**|`tar czf E:/…` 加 `--force-local`|**bash 的 `cd` 认中文路径、`ls` 等被 MSYS 编码搞坏** ⇒ 先 `cd` 再用相对路径。⇒ PB §10。
- ⚠️ **行尾只信字节级**(`grep -c $'\r$'` 会误报)⇒ Python `b.count(b'\r')`。BRIEF/README/`skills/**`/`memory/**` = 纯 LF;**`INDEX.md` = 混合** ⇒ 改它走**字节级单行插入**;⛔ 别对它跑 `git checkout --`。⚠️ **源仓 `refs/remotes/**` 写不进去**(报成功但引用不存在 ⇒ `[gone]`)⇒ 对账一律 `git ls-remote origin refs/heads/master`;`git` 走 SSH 加 `GIT_SSH_COMMAND="ssh -o BatchMode=yes -o ConnectTimeout=15 -o StrictHostKeyChecking=accept-new"`。
- ⚠️ **引用用户口径只写原话**|**含反引号的内容一律用 Write/Edit 写**|**进程替换 `diff <(a) <(b)` 不可用**|**`Edit` 是替换不是追加**|**省积分四招**:批量活写脚本 / 拦大输出(`bash-output-guard.py`)/ 命令限流 / **切会话**(唯一能归零)—— 最贵的不是第 1 轮而是"水位已高还跑 50+ 请求"的轮。⇒ PB §12。
- ⚠️ **打包与改名**(`npm pack` 前核断言锚点、先删 `lib/*.bak` 与 `*.tgz`、升号前确认号没用过、每包必须有 `.npmignore` 排除 `*.tgz`;`--force` 只准替换自己那一段;改名三件套 = SQLite `.db`+`-wal`+`-shm` 一起改 / 压缩包内 grep-sed 够不到 ⇒ 解压→改→重压 / 改完真环境跑一次)。⇒ PB。
- 浏览器只准 `agent-browser` / `browser-harness`(CDP 9223);⛔ **Playwright 全面禁止**。
## 四、仓库 / 推送 / 授权
- 📦 **09-15 文档库已并入代码仓**(R4 选 a)⇒ **`D:\github\dsh_shenxian\dsh-server-docs\`**(git = `D:/github/dsh_shenxian/.git`)。锁脚本 = `…\dsh-server-docs\scripts\handoff-guard.sh`。镜像 `/opt/dsh/docs` 不变。⚠️ hooks 路径改动要**完全重启**才生效。
- 代码仓 `D:\github\dsh_shenxian` → `…dsh_shenxian.git`(master)|**推送只能从本机**;服务器改码走 `git bundle`。文档库 `autocrlf=false` + `.gitattributes(* -text)` **必须保持**。
- ⚠️ **技能是「三处」**:本机 `.workbuddy/skills/<name>/` ← 文档库 `skills/<name>/` ← 镜像 `/opt/dsh/docs/skills/`。**验收 = 两副本 md5 一致 + 镜像一致 + `README.md` / `INDEX.md` 登记跟着改**;同步前先抢全局执行锁。
- 📄 **「去查」索引 = PLAYBOOK §11**(权限档位 / 插件启停 / UI·univer / 个人技能 / docx / `business-plugins` 升级 / admin 跨用户 / 加新能力 / dsh 版本 / 开源导出)。
- 🔒 **授权类**:文件已全部移除(不属改造范围、不得再列为待办或上抛)。上游 MIT、**不得对上游代码附加限制**;**对外发布前先放回那三份**(`_授权归档_发布时再放回\`)。