chore(docs): 文档库并入代码仓(R4 选 a)+ 索引/台账跟进

1) dsh-server-docs/ 从工作区(原 E:\...\aliyun-dsh-server\dsh-server-docs)**整体并入本仓**,
   保留目录名 ⇒ 仓库内 dsh-server-docs/... 的相对引用天然继续有效;旧目录(含其 .git)已归档到
   工作区 _中间产物_待清理/,未随本提交带入。
2) .gitattributes:新增 `dsh-server-docs/** -text` —— 原文档库是 `* -text` + autocrlf=false,
   必须保持纯 LF,否则会被本仓的 CRLF 规则翻掉。
3) 活引用里的绝对路径已全部改到新位置(docs 的 INDEX / README / scripts / skills + 用户级 skills
   + ~/.workbuddy/settings.json 的 hooks);历史档案(04-调整方案/、archive/)按「只增不改」未动。
   ⚠️ hooks 路径改动需「完全重启会话」才生效(配置是会话启动快照)。
4) 交接单/T08:新增 §16「生产整体切换执行记录」(形态 / 落地动作 / **4 个只有真上线才暴露的真 bug** /
   验收证据 / 回滚命令 / 残留项);台账 T08 行 → 已完成并归档;03-路线图 §二 登记 T08 收尾项。
5) 统一称谓:**「本机」只指跑 WorkBuddy 的开发机**,47 / 106 一律写「远程服务器」。
This commit is contained in:
admin committed 2026-09-15 18:47:13 +08:00
1 parent c70d5d860e
commit 5ad755116e
173 files changed
+27632

No files matched your search

@@ -0,0 +1,60 @@
# 46-实例共享工具(jq / ripgrep / ffmpeg)(2026-09-11 落地)
## 背景与动机
档案 38a 曾回答「Playwright 等包是否每个用户都要装一份」,结论是**宿主装一次全员共享**
(`/usr` 已 ro-bind = 零改造通道);当时把 `rg` / `jq` / `ffmpeg` 列为待补的**环境基线**,但**一直未执行**。
用户本次追问「还有一些待处理的任务没确认和执行吧,比如 ffmpeg」→ 本条即补齐。
## 结论:不需要每个用户单独安装
| 依据 | 说明 |
|---|---|
| 实例内 `/usr` 是 **ro-bind**,且 `/usr/local/bin` 在实例 PATH **首位** | **宿主装一次 → 全部实例(含新用户)立即可见**,零代码、**无需重启实例** |
| 用户侧本来就装不上 | `/usr` 只读 + 无 sudo(实测 `touch /usr/local/lib/x` = Read-only) |
| 每人一份的代价 | 重复占磁盘(宿主 **无磁盘配额**)、版本不一致、还会落进工作区被 `#/files` 展示 |
## 实现
新增 **`scripts/install-shared-tools.sh`**(幂等 / 固定版本 / **官方 sha256 校验** / 可离线 / 可 `--force`):
| 工具 | 版本 | 来源与校验 |
|---|---|---|
| `jq` | **1.8.2** | 官方静态单文件 + `sha256sum.txt` |
| `rg`(ripgrep) | **15.2.0** | `x86_64-unknown-linux-musl`(静态,无 glibc 依赖)+ 官方 `.sha256` |
| `ffmpeg` / `ffprobe` | master(N-126492) | **BtbN FFmpeg-Builds 静态构建**(单二进制、自带全部编解码库)+ `checksums.sha256` |
- 安装位:`/usr/local/dsh-runtime/bin/`,并在 `/usr/local/bin/` 建软链(**已在实例 PATH 首位**)。
- 生成清单 `/usr/local/dsh-runtime/SHARED-TOOLS.md`(版本 + 时间),供迁移与审计。
- **迁移打包单元 = `/usr/local/dsh-runtime/` 一个目录**(与档案 42 的 Python 同目录):
`tar czf dsh-runtime.tar.gz -C /usr/local dsh-runtime` → 目标机解压回原位 + 重跑两个安装脚本。
**为什么选静态构建**:`ffmpeg` 走 `dnf` 需要 RPM Fusion、且依赖散落在 `/usr/lib64`,迁移不平滑;
静态单文件自包含、**一个目录即迁移单元**,与用户的「方便迁移整体打包」要求一致。
## 验证记录(沙箱内 uid 100002 实测)
| 检查 | 结果 |
|---|---|
| 可见性 | `jq` / `rg` / `ffmpeg` / `ffprobe` 全部 `/usr/local/bin/*` |
| 版本 | `jq-1.8.2`;`ripgrep 15.2.0 (rev e89fff89ac)`;`ffmpeg version N-126492-…` |
| `jq` 真跑 | `echo '{"a":{"b":[1,2,3]}}' \| jq -c '.a.b\|length'` → **3** |
| `rg` 真跑 | `rg -i world /tmp/t.txt` → **WORLD** |
| `ffmpeg` 真跑 | 生成 440Hz 正弦并编码 mp3 → **产物 8585 字节** ✅ |
| `ffprobe` 真跑 | 读出该文件编码 = **mp3** |
| 校验 | 三个包的 sha256 均与官方发布文件一致 |
## 顺带
`scripts/runtime-baseline.cjs` 的基线纳入 `rg` / `jq` / `ffmpeg`(版本漂移会告警)。
⚠️ ffmpeg 的版本号形如 `N-126492-gefb0a7e5e7`(**不含 `x.y` 形式**),
故其提取用 `ffmpeg version (\S+)` 而非通用的 `\d+\.\d+` 规则。
## 注意 / 后续
- **新增共享工具的正确做法**:优先找**静态单文件**发行版 → 放 `/usr/local/dsh-runtime/bin` +
软链到 `/usr/local/bin` → 更新 `SHARED-TOOLS.md` → 跑 `runtime-baseline.cjs --accept` 刷新基线。
- **Playwright(仍未做)**:它**不是**单文件,除浏览器二进制外还缺 **11 个系统 `.so`**
(`libnss3`/`libgbm`/`libatk`/`libcups`/`libdrm`/`libxkbcommon` …)。系统库只能 `dnf install`
(宿主装一次同样全员可见 ✅),浏览器二进制建议放共享位并用 `PLAYWRIGHT_BROWSERS_PATH` 指定
—— 但**注入该 env 属于 R5「给实例注入新 env」= 扩大**,需先出「权限影响评估」并取得确认,故**未做**。