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 一律写「远程服务器」。
79 lines
6.7 KiB
Markdown
79 lines
6.7 KiB
Markdown
# 28 · 用户数据清理策略(工作区 / 会话 / 回收站)
|
||
|
||
- 日期:2026-09-11
|
||
- 背景:用户提出「**AI 生成的代码和脚本等才是需要定期清理的重点**」,并明确「这些脚本基本都是根据某个对话任务产生,**没有复用价值**」;同时要求「会话记录达到某个大小阈值后,可清除 90 天前的记录」。
|
||
- 结论一句话:**已落地三件套**(`ws-cleanup` 工作区清理 / `session-gc` 会话回收 / `purge-trash` 回收站清空)+ **修掉一个平台自身 bug**(pnpm store/cache 污染用户工作区);全部走"**先 mv 到回收站、30 天后才真删**"。
|
||
|
||
## 一、先说结论:谁在吃盘
|
||
|
||
| 用户 | 清理前 ws | 其中"平台产物" | 真正用户内容 | sessions |
|
||
|---|---|---|---|---|
|
||
| admin | 18 MB / **2045 文件** | **17.6 MB**(pnpm store 16.1M + cache 1.5M + 6 个 tgz + poc/.poc-backup) | 92 KB | 708 KB |
|
||
| guest | 2.5 MB / 30 文件 | 2.0 MB(cache 1.8M + store 180K + 3 个 tgz) | 504 KB | 1.1 MB |
|
||
|
||
> **发现(平台 bug)**:安装脚本原用 `HOME=<用户 ws> pnpm add …` → pnpm 把 **store**(`$HOME/.local/share/pnpm/store`)与 **cache**(`$HOME/.cache/pnpm`)写进了**用户工作区**,再加我们复制进去的 `*.tgz`、`poc/`。这不是 AI 产物,是**平台自己制造的污染**,且掩盖了真正要治理的对象。
|
||
> **已修**:安装改为 `--store-dir <home>/.pnpm-store --cache-dir <home>/.pnpm-cache` + 直接用 `/opt/dsh/artifacts/` 的 tgz(不再复制进 ws)。
|
||
> **已清**:存量污染 `mv` 到 `<userRoot>/trash/2026-09-11-ws-pollution/`;效果 **admin 18M/2045 文件 → 12K/0 文件**、**guest 2.5M/30 → 480K/8**;并实测清理后真实 dsh 仍正常启动、插件正常加载。
|
||
|
||
## 二、清理策略:三档分类(判定依据只有"路径/文件名模式 + 年龄")
|
||
|
||
**前提说明**:**无法按"是不是 AI 生成的"判定**(没有可靠标记),所以规则只认**模式 + 年龄**,并强制分档:
|
||
|
||
| 档 | 对象 | 规则 | 动作 |
|
||
|---|---|---|---|
|
||
| **T1 平台产物/明确垃圾** | `ws/{.local,.cache,.poc-backup,poc,__pycache__,.pytest_cache,node_modules,.ipynb_checkpoints}`、`*.tgz/.tmp/.log/.bak/.part/.crdownload` | 白名单**精确匹配** | 达阈值即清(mv 到回收站) |
|
||
| **T2 一次性临时脚本** | `ws` **顶层**的 `*.py/.js/.mjs/.cjs/.sh/.ps1/.bat/.ts/.ipynb/.sql` | 且 **mtime 超过 90 天**(用户口径:无复用价值) | 达阈值即清 |
|
||
| **T3 其它一切** | 目录、文档、表格、图片、视频、数据、报告… | — | **永不自动删**,只统计与告警 |
|
||
|
||
**阈值(per-user,达到才动手)**:`ws` ≥ **2048 MB**;`sessions` ≥ **1024 MB**。
|
||
**保留期**:`ws`(T1/T2)**90 天**;**`sessions` 365 天**(用户 2026-09-11 定:**对话记忆要留长些**);**回收站 30 天**。
|
||
|
||
**豁免机制**:在 `ws/` 顶层放一个 `.keep` 文件 → **该用户跳过 T2**(一次性脚本不清理),T1 仍清。
|
||
|
||
## 三、落地组件
|
||
|
||
| 组件 | 作用 |
|
||
|---|---|
|
||
| `scripts/ws-cleanup.cjs` | 工作区画像(ws/T1/T2/资产 占比)+ 按阈值清理(`--apply`;默认 dry-run) |
|
||
| `scripts/session-gc.cjs` | 会话保留期回收:`sessions/<slug>/<session-id>/session.jsonl.zstd` 超 N 天且该用户 sessions 达阈值 → mv(含 dry-run) |
|
||
| `scripts/clean-ws-pollution.cjs` | 一次性:清平台自身污染(白名单同 T1 的前 4 项 + tgz) |
|
||
| `scripts/storage-report.cjs` | 每小时生成用量快照 `/var/run/dsh-storage-report.json`(每用户 ws/sessions/trash/总计 + 可清理候选 + 阈值状态) |
|
||
| `scripts/purge-trash.sh` | 清空 `<userRoot>/trash/` 下超 30 天的回收目录(**只有它会真删**) |
|
||
| 门户 **「存储用量」面板** | `admin.html` 新增一区块(表:工作区/会话/回收站/可清理项数),数据来自 **`GET /api/admin/storage`**(`requireAdmin`,直接读快照,不做实时 du) |
|
||
| `/etc/cron.d/dsh-maintenance` | 每小时 05 分 storage-report;每天 04:10 ws-cleanup(2048MB/90d)/ 04:20 session-gc(1024MB/**365d**)/ 04:40 purge-trash;日志 `/var/log/dsh-*.log` |
|
||
|
||
**安全设计**:所有清理动作都是 **`mv` 到 `<userRoot>/trash/<日期>-<任务>/`**(同盘秒级、可整目录移回恢复),**30 天后**才由 `purge-trash.sh` 真正删除。
|
||
|
||
## 四、为什么不"按 AI 产物"直接清
|
||
|
||
1. **不可判定**:AI 与用户都可能写脚本/文件,平台拿不到"这是 AI 生成的"标记;
|
||
2. **误删代价高**:`ws` 里同时有**用户资产**(guest 的 `MCN短视频创作/` 对标数据、报告);
|
||
3. **折中**:只清"**模式明确 + 超龄**"的东西(T1/T2),其余一律保留并只做用量告警 —— 宁可少清,不可误删。
|
||
|
||
## 五、风险与回滚
|
||
|
||
| 风险 | 缓解 |
|
||
|---|---|
|
||
| 误清 T2(用户其实想留的脚本) | 30 天回收期可整目录移回;且只清"ws 顶层 + 超 90 天" |
|
||
| 回收站膨胀 | `purge-trash.sh` 每日清 30 天以上 |
|
||
| 阈值调错 | 三个脚本都支持 `--threshold/--days`;cron 里可见当前值 |
|
||
| 会话删除影响 dsh | **结构已实测**:`sessions/` 无索引文件、按工作区分桶;只在超阈值时动,且走回收站;**并同步回收 `session_projcache/sessions/<session-id>.json`**(按 id 精确匹配,不会误删他人会话) |
|
||
| 误伤运行中实例 | 脚本只动 `ws/` 与超龄 `sessions/`,不动 profile/node_modules |
|
||
|
||
## 六、硬配额:评估结论 = **不做**(2026-09-11 定)
|
||
|
||
- 本机根文件系统实测为 **ext4**(`/dev/vda3`,`/ : ext4 rw,relatime`),**未启用 prjquota** → 无法直接使用 XFS project quota;
|
||
- 若强行上配额,需要"重挂载/重建文件系统或改用 loopback+XFS 镜像",**停机与数据风险都不可接受**;
|
||
- 当前用量仅 **24%**(8.6G/40G)、单用户最大 33MB → **无压力**;
|
||
- ⇒ 用"**软阈值 + 每小时用量快照 + 门户可视 + 每日自动清理**"替代硬配额;真到压力再评估(可选方案:loop 镜像挂到 `ws/`,成本中等)。
|
||
|
||
## 七、已完成(本轮"一次性优化到位")
|
||
|
||
1. ✅ **会话保留期加长**:90 → **365 天**(阈值 500 → 1024 MB);
|
||
2. ✅ **`.keep` 豁免**:`ws/.keep` 存在则跳过 T2;
|
||
3. ✅ **projcache 同步回收**:删会话时按 session-id 精确回收投影缓存;
|
||
4. ✅ **用量可见**:`storage-report.cjs`(每小时)+ 门户 admin.html「存储用量」面板(`GET /api/admin/storage`,实测未登录 401 即受 `requireAdmin` 保护);
|
||
5. ✅ **硬配额评估**:结论"不做"(ext4 无 prjquota,风险不对称)。
|
||
|
||
**剩余可选**(非必要):T2 更细的豁免(项目目录内 `scripts/`)、按用户差异化阈值、用量面板加"趋势/告警"。
|