WorkBuddy 任务垃圾清理
license MIT python 3.8+ no deps Windows macOS Linux read-only first version v1.2.0
≈ 3.0 GB一次实测量可回收
四重保护集合,绝不误删
54 项自检断言全绿
0 依赖纯 Python 标准库
Why

删掉的对话,文件并没有跟着走

WorkBuddy 用久了,磁盘上会悄悄堆起一批"孤儿"—— 任务记录删了,但磁盘上的缓存、转录、日志还留着。

💾磁盘莫名少了几 GB

删掉的对话,磁盘上的文件并没有跟着一起走。用时无感,翻目录时心惊。

🗑️侧边栏没了,空间还占着

任务记录删了,但 tasks/、changes-detail/、projects/ 下的数据留了下来。

📁一串时间戳目录

每次新建对话都会生成一个 playground 工作区,对话删了,目录还在。

🧹想清理又不敢下手

分不清哪个目录属于"活着的"任务,删错了就回不来 —— 这才是最劝退的。

🐌索引与日志越来越臃肿

traces/ 和沙箱日志能悄悄涨到好几个 GB,却没人提醒你。

⏰不敢清,怕删掉定时任务的目录

自动化任务的工作目录不在会话列表里,肉眼根本看不出来,删错就悄悄断了定时任务 —— 所以本工具替你查。

Protection

三重保护 —— 宁可少删,不可错删

这是 v1.1 最重要的改动,补上了 v1.0 的两个盲区。清理前先建三个保护集合,任一命中,绝不删除。

四重保护:存活会话工作区、自动化任务工作目录、工作区记忆、非标准命名目录

🔎保护集合是每次现算的

每次扫描与清理都会重新读一遍数据库、实时构建保护集合,不会用过期的缓存下判断。automations 表还会按 deleted_at IS NULL 过滤 —— 已删除的旧任务不会被误当成"还在用"。

🩺顺带体检你的自动化任务

如果某条自动化任务指向的工作目录已经不存在(运行时必然失败),扫描会把它列为体检项单独提醒你 —— 一个清理工具,顺手做了一件排障的事。

✅ 被保护的工作区会出现在报告里,并注明原因(属于哪个存活会话 / 被哪个自动化任务引用)。此外,若某条自动化任务引用的目录已经不存在,扫描会把它列为体检项提醒你。
Principle

凭什么判断"这是垃圾"

不猜、不看目录时间、不信侧边栏 —— 只认数据库里的权威字段:sessions.deleted_at 与 automations.cwds。

~/.workbuddy/workbuddy.db · sessions 表
-- 唯一权威判定依据(脚本以 mode=ro 只读打开,绝不写入)
SELECT id, cwd, title, deleted_at FROM sessions;

deleted_at IS NULL   → ✅ 存活会话   其数据一律不动
deleted_at 有值      → 🗑️ 已删除任务  磁盘残留即"垃圾"
workbuddy.db · automations 表 —— v1.1 新增的保护依据
-- 自动化任务的工作目录不在 sessions 表里,必须单独查
SELECT id, name, status, cwds, deleted_at FROM automations;

cwds 是 JSON 数组,不是普通字符串 —— 直接按逗号切会解析失败
必须过滤 deleted_at IS NULL,否则会把已删的旧任务也算进来造成误报

→ 被引用的工作目录一律保护,绝不删除

❌不能看目录时间

存活会话的缓存也可能很久没更新,会误伤。

❌不能看目录是否为空

空目录也可能正被存活会话引用着。

❌不能信侧边栏列表

那只是快照,而且不含后台任务。

Tiers

四级分级,分开确认

不同级别的风险天差地别。所以拆开处理 —— 低风险的批量清,动到你成果的逐个过目。

四级分级:A 内部缓存、B1 真空壳工作区、B2 含文件或记忆的工作区、C 诊断日志,另加受保护类别
级别内容典型路径风险实测体量
A 内部缓存与会话转录 tasks/ changes-detail/ file-history/ projects/ 🟢 低≈ 128 MB
B1 真 · 空壳工作区
无用户文件 且 无记忆
~/WorkBuddy/<时间戳>/ 🟢 低≈ 16 KB
B2 含成果文件 或 工作区记忆的孤儿工作区 里面还有你的报告 / 源码 / 图片 / .workbuddy/memory/ 🔴 高≈ 146.5 MB
C 诊断日志与运行追踪 traces/ logs/<日期>/ logs/sandbox/ 🟡 中≈ 2.75 GB
🔒 受保护 被存活会话或自动化任务引用的工作区 删掉可能悄悄打断你的定时任务 ⛔ 绝不删除—
⚠️ B2 是唯一需要逐个人工过目的类别 —— 那里面装的是你自己的劳动成果,或该项目的长期记忆,不是缓存。删 C 之前也请想清楚:删完就失去了历史排障线索。

📌 v1.1 修正:B1 的判定从「只剩 .workbuddy」收紧为「既无用户文件、也无工作区记忆」。含记忆的目录一律升级为 B2 —— 记忆优先,宁可留着。
Context

B2 确认时,最缺的是「这是哪个项目」

只给一个时间戳目录名 + 一堆文件名,你根本想不起来它是干什么的。所以 v1.2 让扫描顺手把线索查出来 —— 两张反向索引:cwd → 会话 与 cwd → 自动化任务。

B2 报告片段
### 2026-10-12-20-17-57   [62.7MB]   用户文件+工作区记忆x1
    曾关联 16 个已删会话:出装查询 / 提莫 / 不需要单件装备的胜率
    曾被 2 条自动化引用:海斗卡片每日更新(已删) / 数据包探测(已删)
       58.1MB  光缆台账(延庆段).xlsx
       4.2MB   现场照片_测试桩/
📌 线索里包含已删除的会话与自动化 —— 那是刻意的,因为「曾经属于谁」恰恰是辨认工作区最有用的信息。但它们不参与保护集合(保护只看 deleted_at IS NULL),否则会把早已删掉的旧任务当成"还在用",造成误报。

🩺只想查一个目录?用 --inspect

python scripts/wb_scan.py --inspect ~/WorkBuddy/2026-09-14-22-35-03 —— 不必跑全量扫描,直接告诉你:目录是否存在、体积、记忆文件、关联了哪些会话与自动化、受不受保护、属于哪个分级。

Restore

删了能还原,而且还原要精确

默认移入系统回收站虽可反悔,但 Windows 上很难按路径精确捞回来(Shell API 只能枚举)。所以 v1.2 加了一个自建隔离区。

🗄️隔离区长什么样

<隔离区>/manifest.json 记录每条的原始路径、体积、类别、删除时间;items/<id>/ 保留原有结构。清理时加 --quarantine 即可。

↩️还原是精确的

因为记了原始路径,wb_restore.py restore --all 直接放回原处,不用你去回收站里翻。跨平台行为一致。

bash
# 清理时移入隔离区(而不是直接删)
python scripts/wb_clean.py --tiers A,B1,C --apply --quarantine

# 查看 / 还原 / 到期清除
python scripts/wb_restore.py list
python scripts/wb_restore.py restore --all
python scripts/wb_restore.py purge --older-than 30
💡 隔离区放在 ~/.workbuddy/.wb-quarantine,本身就是个可以直接删的普通目录 —— 不存在「清理工具的垃圾谁来清理」的问题。purge 是唯一不可逆的操作,会先展示清单再要求确认。
Flow

顺序不可颠倒

第 3 步是硬门槛:没拿到你明确的选择之前,一个字节都不会删。

0
定位环境找到 DB · 建保护集合
1
只读盘点wb_scan.py
2
分类呈现列清单与体积
3
用户确认未确认不删任何东西
4
执行清理默认进回收站
5
二次核验孤儿归零
执行流程图
Install

三步开始

三个脚本只用标准库,Python 3.8+ 即可,不需要 pip install 任何东西。

① 装 Skill
② 直接跑脚本
③ 看报告
从 Releases 下载 workbuddy-task-cleanup.zip,解压到 skills 目录
# Windows(PowerShell)
Expand-Archive -Path workbuddy-task-cleanup.zip -DestinationPath "$env:USERPROFILE\.workbuddy\skills" -Force

# macOS / Linux
unzip workbuddy-task-cleanup.zip -d ~/.workbuddy/skills/

# 或者直接 clone
git clone https://github.com/Lemon177777/workbuddy-task-cleanup.git \
  ~/.workbuddy/skills/workbuddy-task-cleanup

💬装好后,直接对 WorkBuddy 说

「清理 workbuddy 垃圾」 · 「WorkBuddy 占空间太大」 · 「清理已删除任务的残留」

bash · 不装 Skill 也能跑
# ① 只读盘点 —— 放心跑,绝不修改任何文件
python scripts/wb_scan.py --json ~/wb_cleanup_report.json

# ② 预览将删除的内容(默认 dry-run,不落盘)
python scripts/wb_clean.py --tiers A,B1,C

# ③ 确认无误后执行 —— 默认移入回收站,可反悔
python scripts/wb_clean.py --tiers A,B1,C --apply

# ④ 想连 B2 一起清,必须额外显式声明(它含你的成果文件与记忆)
python scripts/wb_clean.py --tiers A,B1,C,B2 --include-b2 --apply

# ⑤ 二次核验(务必重跑一次,删除钩子可能延迟落盘)
python scripts/wb_scan.py
更多实用姿势
# 永久删除(绕过回收站)—— 必须显式声明
python scripts/wb_clean.py --tiers A,B1,C --apply --no-trash

# 清 B2,但保留指定的那几个目录
python scripts/wb_clean.py --tiers A,B1,C,B2 --include-b2 --apply \
    --keep-b2 "2026-09-14-22-35-03"

# 只清 30 天前的旧数据,并留一份删除清单
python scripts/wb_clean.py --tiers C --older-than 30 --apply --log clean.json

# 挂定时任务:有残留时退出码 1
python scripts/wb_scan.py --check
参数默认说明
--tiers A,B1,C必填要处理的类别,逗号分隔:A B1 B2 C
--apply关闭真正执行。不加时只预览,不落盘
--to-trash / --no-trash--to-trash移入系统回收站(默认)/ 永久删除
--quarantine [DIR]关闭移入自建隔离区(默认 ~/.workbuddy/.wb-quarantine),可用 wb_restore.py 精确还原
--include-b2关闭清理 B2 的必要开关(含用户文件、记忆,或非标准命名)
--keep-b2 NAMES—B2 中要保留的目录名,逗号分隔
--match KEYWORD—只处理关联到该关键词的工作区(目录名 / 会话标题 / 自动化名)
--older-than DAYS—只清理修改时间早于 N 天的项
--fast关闭跳过体积统计,只数数量
--log FILE—把删除清单写入 JSON 留痕
--json OUT—(仅 scan)额外导出一份 JSON 报告
--inspect PATH—(仅 scan)体检单个目录:这是谁的、能不能清
--check—(仅 scan)有残留或异常时退出码 1
wb_scan.py 只读盘点输出示例
Self-test

自检:先验工具,再动数据

改脚本、或者换台机器之后,先跑一次自检 —— 它会在系统临时目录里造一套假数据,验证分类与保护逻辑,完全不碰你的真实数据。

bash
python scripts/wb_selftest.py

# 预期输出
通过 54 项,失败 0 项
断言防的是什么
含记忆的目录进 B2 而非 B1v1.0 会连工作区记忆一起删掉
自动化引用的目录被保护v1.0 会悄悄打断定时任务
已废弃自动化的目录不受保护反过来别误保护,否则永远清不掉
--keep-b2 指定的目录不动选择性保留要真的生效
dry-run 之后文件仍在原处预览绝不能偷偷落盘
干跑一遍后,存活 / 自动化工作区都还在最终安全底线
Safety

安全设计

这是一个"会删文件"的工具。所以默认动作必须是保守的,任何"多做一步"都需要你显式授权。

判定依据与永久豁免名单

①默认 dry-run

不加 --apply,脚本只打印"将删什么",绝不动盘。

②回收站优先

执行时默认移入回收站;永久删除必须显式加 --no-trash。

③双重显式授权

B2 必须同时给出 --tiers B2 和 --include-b2。

④事后完整性校验

每次清理后自动检查存活会话工作区,缺失必须为 0。

1

先扫描 → 后呈现 → 再确认 → 末执行,顺序不可颠倒。

2

不动数据库。只读打开(mode=ro),绝不写入一个字节。

3

不碰 blobs/ —— 那是内容寻址存储,存活任务也在引用,删了会破坏数据。

4

不删任何被自动化任务引用的工作目录 —— 删掉等于悄悄打断用户的定时任务。

5

不把含 .workbuddy/memory/ 的工作区当空壳 —— 那是项目长期记忆。

6

不把非标准命名的目录当空壳 —— 即使完全为空,也一律归 B2 待确认。

7

B2 必须逐个列文件 + 关联线索 + 二次确认 —— 那是你的成果、记忆或自建目录。

8

默认走回收站或隔离区;要永久删除才加 --no-trash,且先加粗警告、列出受影响路径。

9

删完必须二次核验,并报告「存活会话工作区缺失 = 0」。

10

保留当天的日志 logs/<今天>/ 与 logs/sandbox/<今天>/。

11

改动脚本后先跑 wb_selftest.py,54 项全绿再交付。

FAQ

常见问题

会删掉我正在使用的对话吗?

不会。判定只依据 sessions.deleted_at:IS NULL 的存活会话,其工作区与数据一律跳过。脚本还会自动把当前正在运行的会话工作区排除在外,清理后额外校验一次完整性。

会误删我定时任务的工作目录吗?v1.1

不会。这是 v1.1 专门补上的保护:脚本会读 automations.cwds(过滤掉已删除的自动化),把被引用的目录并入保护集合。

这类目录往往没有任何存活会话引用 —— v1.0 会把它当孤儿删掉,那正是要修的问题。

什么是「工作区记忆」?为什么不能删?v1.1

工作区目录下的 .workbuddy/memory/ 存放着该项目的长期记忆与每日工作日志:

<工作区>/.workbuddy/memory/ → YYYY-MM-DD.md · automations/<id>/memory.md

一个目录可能看起来"只剩 .workbuddy 了",但里面恰恰只有记忆。v1.0 会把它判成空壳并删除;v1.1 改为含记忆即升级为 B2,列出记忆文件,由你确认。

删了还能恢复吗?

默认可以。执行时有两条路:

· 系统回收站(默认)—— Windows 用 SHFileOperationW,macOS 用 ~/.Trash,Linux 用 freedesktop 规范。

· 自建隔离区(推荐,加 --quarantine)—— 移入 ~/.workbuddy/.wb-quarantine 并记录原始路径,之后用 wb_restore.py list / restore 精确还原,不用去回收站里翻。

只有显式加 --no-trash 才是永久删除 —— 那种情况下请务必看清文件清单。

我删掉的对话里的文件,还能找回来吗?

只要还没清理过,它们大概率还躺在 ~/WorkBuddy/<时间戳>/ 里 —— 这正是 B2 存在的意义。把它们找回来,是可回收的那 146 MB 之外、更值钱的东西。

为什么清理完,目录好像还在?

这是本机 safe-delete 钩子的已知行为:删除会被转成回收站操作,且可能在 rmtree() 返回之后才真正落盘。所以必须重跑一次 wb_scan.py 做二次核验,不要仅凭第一轮输出下结论。

logs/sandbox 整目录删除失败?

已知坑。整目录删会报 Some operations were aborted,必须按日期子目录(如 20261009/)逐个删。脚本已经这么做了,并且会保留当天。

macOS / Linux 能用吗?

能。两个脚本纯标准库,路径基于 ~/.workbuddy 与 ~/WorkBuddy,三个平台通用。用 python3 代替 python 即可。

会不会动到我自己的项目文件?

不会。清理范围只有两处:~/.workbuddy/ 内部的缓存与日志,以及 ~/WorkBuddy/<时间戳>/ 下的孤儿工作区。你在别处创建的项目目录,不在扫描范围内。

能不能定期自动清理?

可以配一个定时任务只跑只读盘点,把报告推给你;但删除动作建议始终保留人工确认 —— 尤其 B2,那是你的成果文件,不该被自动化悄悄带走。