从本机 WorkBuddy 会话记录还原历史指令的逐字原文与任务模式设置,支持「当前空间全量提取」与「报告增量追加」,生成可交付的 txt 报告。当用户问"我最早干了什么""我发的前几条指令写出来""当时任务设的什么模式(代码开发/通用、Plan/Craft、权限)""这个项目什么时候开始的""之前我是怎么干的""把当时那句原话找出来""把这个空间的指令都整理出来"时使用。也适用于写教程、复盘、考证时需要引用历史指令原文的场景。
---
name: 指令复原
description: 从本机 WorkBuddy 会话记录还原历史指令的逐字原文与任务模式设置,支持「当前空间全量提取」与「报告增量追加」,生成可交付的 txt 报告。当用户问"我最早干了什么""我发的前几条指令写出来""当时任务设的什么模式(代码开发/通用、Plan/Craft、权限)""这个项目什么时候开始的""之前我是怎么干的""把当时那句原话找出来""把这个空间的指令都整理出来"时使用。也适用于写教程、复盘、考证时需要引用历史指令原文的场景。
agent_created: true
---
# 指令复原
把用户问"我当初说了啥"变成一份**有原文、有时间戳、有模式设置、可复核**的报告。
**v2 两项核心能力:**
1. **当前空间全量** —— 不指定会话时,自动归集当前工作区下的**所有**会话,提取全部指令,按时间升序合并。
2. **增量追加** —— 报告已存在时只追加新指令并重算概览,历史条目原样保留,不重头重建。
## 核心认知(先读这个,能省一半时间)
**云端对话检索(`conversation_search`)只返回 AI 生成的摘要,拿不到逐字原文。**
要原文必须读**本地会话记录**。云端检索只配用来缩小范围、定位会话 ID,拿到 ID 后立刻转本地。
**三个数据源,各管一段:**
| 要什么 | 去哪拿 |
|---|---|
| 指令**逐字原文** + 时间戳 | `~/.workbuddy/projects/<cwd-slug>/<session-id>.jsonl` |
| **任务模式**设置(代码开发/通用、Plan/Craft、权限、模型) | `~/.workbuddy/workbuddy.db` → `sessions` 表 |
| AI 侧干了什么(摘要佐证) | 工作区 `.workbuddy/memory/YYYY-MM-DD.md` |
| 物理产物时序佐证 | 项目文件最早 mtime |
## 快速上手
脚本:`scripts/restore_instructions.py`(纯标准库,无依赖,跨平台)。
```bash
PY="C:/Users/<你的用户名>/.workbuddy/binaries/python/versions/3.13.12/python.exe"
S="C:/Users/<你的用户名>/.workbuddy/skills/instruction-restore/scripts/restore_instructions.py"
# 1) 列出所有历史会话,定位目标(支持按标题/路径/ID 过滤)
"$PY" "$S" list
"$PY" "$S" list -k 关键词
# 2) 当前空间:生成全量指令记录(首次运行)
"$PY" "$S" report -o "指令记录_当前空间.txt"
# 3) 以后每次跑同一条命令 = 增量追加,只补新指令
"$PY" "$S" report -o "指令记录_当前空间.txt"
# 4) 只看有没有新增、不写文件
"$PY" "$S" check -o "指令记录_当前空间.txt"
# 5) 快速查看(不落文件)
"$PY" "$S" dump -n 10 # 当前空间前 10 条
"$PY" "$S" dump -s 7a260bff -n 5 # 指定会话
"$PY" "$S" timeline -n 15 # 开场动作时间线(AI 说了啥 + 调了啥工具)
```
报告默认输出 UTF-8,Windows 记事本可直接打开。生成后用 present_files 交付。
## 标准流程
1. **生成 / 增量更新** —— 在当前工作区直接 `report -o 报告.txt`。
- 首次:全量生成;之后:增量追加。同一条命令,不用记两种用法。
- 想限定本次最多补多少条:加 `-n 20`(不影响已收录部分)。
- 要推倒重来:`--full-rebuild`。
2. **确认范围对不对** —— 看报告「一、概览」里的会话数量和首尾时间。
拿不准先用 `list` 看全部会话,或用 `dump -n 3` 扫一眼首条指令内容。
3. **人工加工(脚本做不了,必须做)** —— 脚本只给原料,价值在解读:
- 点出**起点时刻**(精确到秒)与**当时设的模式**
- 给指令**标注性质**:需求 / 权限 / 复盘 / 技术疑问 / 追加要求
- 从时间线里提炼**关键转折**(如"从提问到首版跑通用了 57 分钟")
- **易混淆点单列一节**:不同工作区可能有同名/近名会话(标题都带同一缩写但内容无关),
必须按"工作区路径 + 首条指令内容"双重判定,并显式说明哪条**不是**目标。
## 参数速查
| 子命令 | 关键参数 | 说明 |
|---|---|---|
| `list` | `-k/--keyword`、`-v` | 按标题/路径/ID 过滤;`-v` 附带显示工作区路径 |
| `report` | `-o`(必填)、`-n`、`--cwd`、`-s`、`--all`、`--full-rebuild` | 默认当前空间全量;`-s` 单会话;`--all` 所有工作区 |
| `check` | `-o`(必填) | 报告体检:已收录多少条、待新增多少条、预览前 3 条 |
| `dump` | `-n`(默认 0=全部)、`--full`、`--truncate N` | 快速查看,不落文件 |
| `timeline` | `-s`、`--limit N` | 开场动作时间线 |
| 通用 | `--home`、`--no-dedup` | 指定配置目录;关闭内容去重 |
## 报告结构与增量机制
```
# 指令复原报告 · 当前空间 <路径>
# 首次生成 / 最近更新
一、概览 ← 每次都重算(会话数、指令总数、本次新增、首尾时间)
二、会话与任务模式 ← 每个会话一行,附 addon_selection 原始 JSON
三、说明与考证方法 ← 静态章节,放在指令区之前
四、指令逐字原文 ← 增量追加区(BODY:BEGIN / BODY:END 之间)
```
- 每条指令标题形如 `【第 12 条】2026-09-03 09:11:03 | id=3544155b | 会话标题`
- `id=` 是内容指纹(md5 前 8 位),**增量就靠它判重**,已收录的不会重复写入
- 追加只在文件末尾发生,所以「说明与考证方法」必须排在指令区**之前**(顺序别调)
- `BODY:BEGIN` / `BODY:END` 两行标记是增量解析的锚点,报告里已注明勿删
## 模式字段怎么翻译成人话
| 字段 | 取值 | 含义 |
|---|---|---|
| `addon_selection.welcomeMode` | `coding` / `working` | **代码开发** / **通用·工作** |
| `addon_selection.interactionMode` | `plan` / `craft` | Plan 先出计划 / Craft 直接干 |
| `addon_selection.permissionMode` | `bypassPermissions` / `fullAccess` / `default` | 始终允许 / 完全访问 / 逐次确认 |
| `mode` / `source_mode` | `craft` / `plan` | 运行态 / 来源态 |
| `permission_mode` | `fullAccess` / `bypassPermissions` | 授权级别 |
| `model` | 如 `deepseek-v4-flash` | 当时用的模型 |
`addon_selection` 是**建任务时的选择**,`mode`/`permission_mode` 是**当前状态**,
两者可能不一致(出现过建时选"始终允许"、前半小时仍反复弹确认的情况),值得单独点出来。
## 脚本已封装的坑(改脚本时别改回去)
1. **文本块 `type` 是 `input_text` 不是 `text`** —— 按 `"text"` 过滤会一无所获且静默返回空。
2. **用户原文在 `<user_query>` 标签内** —— 直接取标签内容最干净,
天然避开 `<system-reminder>` / `<user_info>` / `<identity_context>` 等大段系统注入
(第一条记录常达 9000 字符,不剥掉会把系统内容当成用户指令)。
3. **整条级剔除必须先于剥离系统块** —— `<cb_summary>` 压缩块内部常含**未闭合**的
`<system-reminder>`,先剥离会触发兜底正则吞掉整块,只剩末尾重放的 `<user_query>`,
被误计成"用户又把首条指令发了一遍"。
4. **压缩后会重放真实发言** —— 上下文压缩时系统把被压缩掉的原始发言**重放成一条结构
完全相同的 `role=user` 记录**(连时间戳都跟压缩时刻一致),JSON 结构上无法与真实发言
区分,只能靠"内容在此之前出现过"判定。脚本默认全局去重,`--no-dedup` 可关闭。
5. **自动续接提示不是人发的** —— `Please continue with the conversation based on the summarized
context above.` / `请根据以上总结的上下文继续` 是压缩后系统生成的,必须剔除。
6. **同一文件会被扫两遍** —— db 按 cwd 匹配和 `projects/<slug>` 目录兜底会各找到一次,
两边路径斜杠方向不同,字符串判重失效。**必须用 `os.path.normcase(os.path.normpath(p))`
归一后再去重**,否则指令数虚高、重复计数翻倍。
7. **别用文件 mtime 跳过扫描** —— 文件没变过 ≠ 内容已收全(上次可能限量写入,
或当时规则有 bug 漏了内容)。踩过:只写了 100 条,剩余 14 条因"文件未变动"被永久漏掉。
增量判重只认 id 指纹,每次都全量扫描(实测 4 个会话、30MB+ 记录约 2 秒,可接受)。
## 交叉验证(别只信一个源)
- 工作区 `.workbuddy/memory/YYYY-MM-DD.md` —— AI 侧当日摘要,与会话原文对照
- 项目文件最早 mtime:`find <dir> -type f -printf "%T+ | %p\n" | sort | head -20`
—— 首个物理产物应**晚于**第一条指令,时序自洽才算对上
- 会话元数据 `~/.workbuddy/sessions/<pid>.json` 含 `sessionId`、`cwd`、`startedAt`
(注意它的 `mode: "local"` 是**运行模式**,不是任务模式,别搞混)
## "任务找不到了"类查询的快速定位(实战沉淀 2026-09-07)
场景:用户重启后找不到某个刚做过的任务/会话。别只按标题搜(老会话续用是常态——
8/26 建的会话 9/7 下午还在加新指令,list 按关键词可能零命中)。按这套走:
1. **先定"重启/崩溃"时刻**:`ls -lt ~/.workbuddy/logs/Crash-Log/` 与 `logs/startup/<日期>/`
—— crash-report-main-*.json 的时间戳就是应用崩溃/重启点,用户说的"重启前"以此为锚。
2. **按文件活动反查会话**(最有效):
```bash
find ~/.workbuddy/{file-history,changes-detail,artifact-index} \
-newermt "崩溃时刻-10分钟" ! -newermt "崩溃后N分钟" -type f | head -30
```
路径里的 `<session-id>` 就是该时段在改文件的会话——直接命中"丢了的任务"。
3. **查技能/skill 落盘时间**:`ls -lt ~/.workbuddy/skills/<名字>/`
若任务产物是 skill(如录屏工具),其 SKILL.md 的 mtime 就是任务执行窗口。
4. 锁定了 session-id 再用 `dump -s <id>` 还原原文;注意 `dump -n 12` 只给前 12 条,
老会话续用时会话记录上百条,**要看当天新增必须 dump 全部后按日期过滤**。
5. 用户侧界面"找不到"≠ 数据丢:会话可能在**另一个工作区**的老会话尾部,
界面重启后只显示最近活跃项。定位后直接报"工作区路径 + 会话标题 + 上次活动时间"。
## 环境备注(Windows / Git Bash)
- Python 用托管解释器:`C:/Users/<你的用户名>/.workbuddy/binaries/python/versions/3.13.12/python.exe`
- 路径用 `C:/` 正斜杠格式,避免 Git Bash 路径转换
- jsonl 可能几十 MB,**必须流式逐行读**,绝不 `readlines()` 全量载入
- 会话 ID 支持前缀;同名多份记录时脚本自动取最大的一份(主会话)
- 工作区 slug 映射:`C:/Users/x/WorkBuddy/y` → `c-users-x-workbuddy-y`
(脚本自动算,同时用 db 的 `cwd` 字段双重匹配,双保险)