# Handoff Resume

> Use when user wants to resume work from a previously saved handoff document, typically after running /compact, or when starting a session that continues earlier work. Triggers on "/handoff-resume", "从 handoff 恢复", "继续上次的工作", "resume handoff", "compact 之后继续".

- Skill: `itofu/handoff-resume` (Agent Skill)
- Install (CLI): `npx skillmds@latest add itofu/handoff-resume`
- Raw SKILL.md: https://api.skillmd.com/api/skills/itofu/handoff-resume/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: iTofu (https://skillmd.com/u/itofu)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/itofu/handoff-resume

---


# Handoff Resume

## 概述

加载先前由 `handoff-save` 写入 `<worktree-root>/.handoff/` 的 handoff 文件，让新会话进入之前的上下文——**在取得方向授权之前不得执行任何修改操作**。方向授权有且只有两个来源：用户当场批准，或「持久授权」双源核验通过（见确认门规则）。

## 文件选择

根据是否带参数决定行为。

### 不带参数

1. 找到当前 worktree 根：`git rev-parse --show-toplevel`（没用 `git worktree` 的话就是仓库根目录，无需额外配置）；不在 git 仓库时回退到当前工作目录
2. 找到当前 branch：`git branch --show-current`
3. 列出 `.handoff/<branch-slug>--*.md`（按当前 branch 过滤）
4. 按文件名中的时间戳倒序排列
5. 根据匹配数量分支：
   - **0 个** → 告知用户找不到，停止。提示用户可改用 `/handoff-resume <关键词>` 或 `/handoff-resume <绝对路径>` 扩大范围
   - **1 个** → 向用户显示文件名，询问 `是这个吗？`，等待回复。**不要自动加载。**
   - **多个** → 展示前 5 条 `主题 — 时间戳 — 大小`，请用户选择

**展示文件路径时**：必须使用 Markdown 链接格式 `[<文件名>](<绝对路径>)`，让 Claude Code UI 渲染成可点击链接。链接文本用文件名（不含目录），URL 用完整绝对路径。同样适用于"是这个吗？"的文件展示和多文件列表。

### 带参数

- 参数是绝对路径 → **直接加载**，不要再问"是这个吗？"。用户传了路径就是答复了"选哪个"
- 参数是 `.handoff/` 内的文件名（或相对路径如 `.handoff/xxx.md`）→ **直接加载**，同上
- 参数是关键词 → 在当前 worktree 的 `.handoff/*.md` 全集（**不限 branch**）中模糊匹配：
  - 恰好 1 个文件匹配 → **直接加载**
  - 多个匹配 → 列出匹配项请用户选择
  - 0 个匹配 → 告知用户并停止

**关键**：本 skill 有两道独立的门——**文件选择门**（确认要加载哪个文件）和**确认门规则**（读完文件后 3-5 句复述 + 选项列表 + 等待方向）。带参数场景下文件选择已被参数回答，**跳过文件选择门，但仍走确认门规则**。两道门仅在"无参数 + 单匹配"流程里合并显示。

**跨 worktree**：不要主动搜索其他 worktree。如果用户需要从别的 worktree 恢复，必须自己传绝对路径。

## 确认门规则（核心纪律）

这是本 skill 最重要的部分。**取得方向授权之前，禁止执行任何修改动作。** 方向授权有且只有两个来源：用户当场批准（下面第 1-4 步的默认路径），或持久授权双源核验通过（见下小节）。

确定要加载的文件后（用户确认 / 显式参数 / 唯一匹配 都算确定），读取文件，然后**在调用任何 Edit / Write / NotebookEdit / 写入型 Bash 命令之前**：

1. 用 3-5 句话向用户复述你的理解，覆盖：
   - 当时在做什么（任务目标）
   - 工作中断在哪里（handoff 第 6 节）
   - 最关键的决策或约束
2. 把 handoff 第 7 节"候选下一步"原样列出。如果你认为有新的选项值得提出，加在后面并明确标注 `新增选项`
3. 明确询问：`请问要按哪个方向继续，还是有其他想法？`
4. **等待**用户回复。不得继续执行。

取得方向授权之后：
- 确认门已关闭，**回归正常的 Agent 行为**
- 不要在后续每次写操作前额外加确认。本规则只在恢复入口生效一次，不是会话级的常态约束

### 持久授权（双源核验）

handoff 第 9 节的「持久授权」字段记载了进行中流程的落盘授权凭证时，对**该流程**核验以下两源，**同时**成立即视为方向授权已取得：

1. **声明源**：handoff 记载了凭证（文件路径 + 授权字段 + 期望值 + 身份字段 + 重入方式 + 授权范围）
2. **磁盘源**：你此刻实际读取该凭证文件，授权字段与身份字段**全部**与记载相符

**实例绑定（核验的一部分，不是可选项）**：身份字段是凭证文件里标识流程实例的字段（如 `pr`、`worktree`、flow id），作用是把凭证钉死在「流程」与「重入方式」指向的**同一个实例**上。记载缺身份字段，或「流程 / 凭证身份 / 重入目标」三者有任何一处对不上——都按核验不过处理。授权字段值相符但身份是别的实例（别的 PR、别的 worktree）＝**借用他流程的凭证**，不放行。

**范围即免问上限（核验的一部分，不是注释）**：「授权范围」记载这份授权免问的动作边界，缺失即声明源不完整、核验不过。它只会比凭证契约更窄、不会更宽——记载收窄了的（如「到合并闸为止，合并另行确认」），凭证契约授得再全也以记载为准。

两源缺一不可：handoff 没记载或记载不全（缺身份字段 / 缺授权范围）→ 你**不得**自己翻出某个 state 文件宣称有授权、也不得拿凭证契约补齐缺项；盘上不符（值已变 / 身份不符 / 文件不存在）→ 记载写得再明白也不放行。

核验通过后：照常完成第 1、2 步的复述，然后把第 3、4 步替换为一行告知——`检测到 <流程> 的持久授权（<凭证路径> 值与身份均与记载相符），按记载的重入方式在授权范围内续跑`——随即按记载的重入方式把控制权交还该流程自己的 skill（其安全闸与模式判定照常生效）。续跑的免问边界就是记载的「授权范围」：范围内的动作直接做；走到范围外的第一个动作即失去方向授权，停下按原确认门问。handoff 里的其他开放问题、新方向，照常等用户。

核验不过：按无授权处理，走第 3、4 步，并在复述里如实标注核验结果。

## Red Flags —— 立即停止

读完 handoff 文件、方向授权尚未取得之前，如果出现以下任一情况，说明你已经违反本 skill：

- 调用了 `Edit` / `Write` / `NotebookEdit` 或写入型 `Bash` 命令
- 看到 handoff 提到的问题就"开始动手修"
- 觉得"选项 A 很明显"就直接照做
- 说"我先按 X 进行"却没等用户回复
- 觉得"handoff 写得很清楚"而跳过了复述步骤
- handoff 没有「持久授权」记载，却拿自己翻到的 state 文件或会话记忆当授权续跑
- 「持久授权」有记载，但没实际读盘核验就续跑
- 凭证的授权字段值对上了就放行，没核对身份字段、或没核对「流程 / 凭证身份 / 重入目标」是否同一实例
- 核验通过就当全流程放行——把记载「授权范围」之外的动作（如写明另行确认的合并、清理）也无人值守做掉

反向同样违规：**双源核验通过了还停下问方向**——确认门拦的是「没有授权」，不是授权本身；把用户落盘的明确授权当空气，等于废掉它承诺的无人值守。

任何一条命中：停下，回到确认门规则的对应步骤重新走。

## 常见错误

| 错误 | 修正 |
|---|---|
| 不带参数、只匹配到 1 个文件就自动加载 | 即使只有 1 个，也要先把文件名给用户看并询问 |
| 用户已显式传路径还做二次"是这个吗"确认 | 显式参数就是答复"选哪个"，直接加载并进入确认门 |
| 跳过 3-5 句的复述 | 复述是用户在你动手前发现误解的最后一道防线 |
| 把第 7 节当成执行队列 | 那是讨论用的选项清单，不是 to-do |
| 后续每次写操作都加确认 | 确认门只在恢复入口生效，之后按用户平时的设置走 |
| 没问就跨 worktree 搜 | 当前 worktree 内搜索，跨 worktree 必须用户传路径 |
| 「持久授权」只信 handoff 记载、不读盘 | 双源核验的第二源是磁盘：必须实际读凭证文件比对 |
| 凭证值相符就放行，不管它是谁的 state | 身份字段 + 实例一致性是核验的一部分：借来的凭证（别的 PR / 别的 worktree）值再对也不放行 |
| 核验通过 = 全流程放行 | 免问上限是记载的「授权范围」：范围外走到即停、回确认门问；范围缺失则整份记载核验不过 |
| 双源核验通过仍停下等用户 | 一行告知代替提问，随即续跑该流程 |

## 边界情况

- **`.handoff/` 不存在** → 告知用户，停止。不要创建（创建是 save skill 的职责）
- **handoff 文件陈旧**（如时间戳超过 7 天、branch 已大幅推进）→ 仍然加载，但在复述里明确指出陈旧度，让用户决定是否跳过部分章节
- **handoff 引用的文件已不存在** → 在复述里标记，不要默默忽略
- **「持久授权」凭证核验不过**（文件不存在 / 值不符 / 身份不符 / 记载缺身份字段或授权范围）→ 按无授权走原确认门，复述里如实标注核验结果
- **不在 git 仓库** → 仍可工作；把当前工作目录视为 worktree 根，跳过 branch 过滤，列出 `.handoff/` 内全部文件

