FinClaw V1 Hand-off Anchor Template
状态:Accepted Initial Protocol / V1 sub-packet 完成时必须产出的 hand-off anchor 标准模板 日期:2026-05-16 项目:FinClaw 文档级别:项目级方法论协议 上游协议:v1-multi-agent-execution-protocol.md、v1-task-packet-context-budget-schema.md
1. Purpose
Hand-off anchor 是 V1 工程化期间跨 Agent 闭环之间的唯一权威传递载体。它的作用:
- 让下一个 Agent 启动时不需要读取上一个 Agent 的完整对话历史;
- 把上一个 packet 闭环的关键结论压缩成 ≤ 5K token;
- 防止「同一问题反复讨论」与「决策漂移」;
- 让长周期工程化可断点续跑。
2. Hard Constraints
| 约束 | 值 |
|---|---|
| 总长度 | ≤ 5K tokens(强约束) |
| 格式 | YAML 文件 |
| 存放路径 | /Users/mlabs/Programs/Labs-FinTecAI/projects/finclaw/handoff-anchors/<packet-id>.yaml |
| 写入时机 | 在 sub-packet 标记为 done / partial / blocked 的同一次 Agent 闭环内 |
| 写入权限 | 完成该 sub-packet 的 Agent;禁止后续 Agent 修改原 anchor |
| 修订方式 | 不修改原 anchor;新建 <packet-id>.hotfix-<N>.yaml 显式修正 |
| 抗中断 partial anchor(见 §2A) | 任务进度达 50% 时强制写一次 <packet-id>.partial-<N>.yaml;TLS / PING / API 中断后由后继 Agent 续作 |
2A. Mid-flight Partial Anchor Protocol(抗 TLS / PING / API 中断)
2A.0 启动信号(Started Anchor,Dashboard 可感知)
规则:Agent 启动 sub-packet 执行时,必须立即写一个 <packet-id>.started.yaml,包含以下最小字段集:
packet_id: <packet-id>
completion_status: started
started_at: <ISO8601>
completed_at: <ISO8601> # 与 started_at 相同(兼容 anchor schema)
started_by_agent: <agent-role-id>
completed_by_agent: <agent-role-id>
progress_pct_estimated: 0
目的:让 Coordination Dashboard 能立即感知到任务已开始执行(从 pending 切换到 in-progress),消除"Agent 已开始工作但 Dashboard 仍显示 pending"的信息盲区。
时机:在 Agent 完成 must_read 文档加载后、正式开始工程化工作(写代码 / 写文档)前写入。不需要等到 50% 进度门。
命名:handoff-anchors/<packet-id>.started.yaml(注意与 partial-<N>.yaml 区分;started 只写一次)。
后续覆盖:当 Agent 写出第一个 partial anchor 或 final anchor 后,Dashboard 会使用更新的 anchor 状态(started anchor 不需要删除,保留为审计材料)。
2A.1 触发条件(任一满足即必须写 partial anchor)
| 触发器 | 说明 |
|---|---|
| 50% 进度门 | Agent 估计自己完成本 packet 核心 acceptance criteria 的 ≥ 50% 时,立即写一次 partial-1.yaml |
| 3 小时挂钟门 | Agent 单次会话连续运行超过 3 小时仍未完成时,每 90 分钟追加 partial-<N>.yaml |
| 多文件批量生成门 | 一次 packet 需写入 ≥ 3 个文档 / 代码文件时,每完成 1 个文件即追加 partial anchor(最小颗粒度) |
| 关键决策刚锁定后 | key_decisions_locked 中新增任一条目时,立即追加 partial anchor(哪怕距上次 < 10 分钟) |
| 声明 destruction(不可逆操作前) | 准备做 git push --force / 大段文件删除 / DB migrate 前,先写 partial anchor 记录前状态 |
2A.2 Partial Anchor 文件命名
handoff-anchors/<packet-id>.started.yaml ← 启动信号(Agent 开始执行时立即写入)
handoff-anchors/<packet-id>.yaml ← 最终 done / partial / blocked anchor
handoff-anchors/<packet-id>.partial-1.yaml ← 第一次中段快照
handoff-anchors/<packet-id>.partial-2.yaml ← 第二次中段快照
handoff-anchors/<packet-id>.hotfix-N.yaml ← 已完成 anchor 后的显式修正(与 partial 区分)
.partial-<N>.yaml 文件可以在最终 anchor 写入后保留为审计材料,也可由完成 sub-packet 的 Agent 在 final anchor 中标 superseded_by_final: true 但不删除(保留中段证据)。
2A.3 Partial Anchor 必填字段(其余字段可省略,与 §3 schema 一致)
packet_id: <packet-id>
packet_type: task-packet | sub-packet
completion_status: partial # 固定为 partial(即使你估计自己马上要完成)
completed_at: <ISO8601> # 写 partial 的时间
completed_by_agent: <agent role / model>
parent_anchor: <如有>
progress_pct_estimated: <0..100> # 自报进度
key_decisions_locked: [...] # 截至此刻已锁定的决策(重要:丢失这部分会让续作 Agent 重启讨论)
produced_artifacts: [...] # 截至此刻已落盘的文件(带绝对路径 + bytes / lines 估算)
do_not_re_explore: [...] # 截至此刻已闭环、不应重启的话题
remaining_scope: | # 自报剩余范围
<短文:剩下要完成什么 + 估计耗时>
context_to_carry_forward: | # ≤ 800 字(partial 版本可简短)
<续作 Agent 启动时应当知道的最重要 3-5 点>
可以省略:verification_evidence(任务尚未完成)、next_packets_unblocked(任务未完成不解锁下游)、risks_or_debt(若空可省)。
2A.4 后继 Agent 读取 Partial Anchor 的行为约束
| 行为 | 约束 |
|---|---|
| 必读 | 读最新 <packet-id>.partial-<N>.yaml(N 最大者)+ 原 packet frontmatter |
| 禁止 | 重新做 produced_artifacts 中已声明完成的文件(除非 verification 失败) |
| 禁止 | 重启 do_not_re_explore 列表中的话题 |
| 禁止 | 推翻 key_decisions_locked 中的条目(如必须推翻,需 escalate 到项目发起人) |
| 必做 | 把 progress_pct_estimated 作为续作起点;优先完成 remaining_scope |
| 必做 | 完成时写最终 anchor,明确引用 partial chain:continued_from_partials: ["v1-xxx.partial-1.yaml", "v1-xxx.partial-2.yaml"] |
2A.5 与「断点续跑」的一致性
V1 工程化的 multi-agent 协同假设单 Agent 闭环可断点续跑(v1-multi-agent-execution-protocol.md §4)。Partial anchor 是该假设的物理实现:
- 不依赖对话历史;
- 不依赖网络层重连;
- 不依赖 IDE 进程不崩溃;
- 任何 Agent / 任何 stack(Cursor / Codex / OOSO)从 partial anchor 都能续作。
2A.6 Failure Mode:忘记写 partial anchor
如果某次 sub-packet 失败(TLS / PING / OOM / crash)且没有任何 partial anchor 文件,后继 Agent 必须:
- 不假设 packet 进度 > 0;
- 验证已落盘文件的完整性(不能信任部分写入的文件);
- 决定:从头开始 / 或基于已落盘文件做 spot-fix;
- 在最终 anchor 的
notes_if_overrun字段说明「没有 partial anchor,按 fail-safe 重做 / spot-fix」。
经验提醒(来自 V1 Wave 2 工程实施前期):曾发生 2 次 subagent 在写完核心文档后因 PING / TLS 中断退出,导致 README / handoff anchor 未能落盘。本协议(§2A.1 50% 门 + 多文件批量门)就是从那次事件总结的强制规则。
3. Schema
# 治理库路径:projects/finclaw/handoff-anchors/<packet-id>.yaml
packet_id: <sub-packet 或 packet 的 document_id>
packet_type: task-packet | sub-packet
completion_status: done | partial | blocked | started
completed_at: <YYYY-MM-DDTHH:MM:SS+TZ>
completed_by_agent: <agent role / model 标识,例如 "cursor-claude-4.6-opus" 或 "codex-gpt-5.5">
completed_in_worktree: <如果是工程实现 packet,记录 worktree 路径;否则填 "n/a">
completed_on_branch: <git 分支名 或 "n/a">
# === 关键决策与产出 ===
key_decisions_locked:
- "<以陈述句形式列出本 packet 内已经做出且不可逆的决策>"
- "<另一条决策>"
produced_artifacts:
- path: <相对路径>
type: design-doc | code | test | config | report
short_description: <一句话>
revision: <git commit sha 或 doc revision 标识>
- ...
# === 给下一个 Agent 的指引 ===
open_questions_for_next_packet:
- "<问题 1:要求下一个 packet 解决>"
- "<问题 2>"
context_to_carry_forward: |
<≤ 1500 字精炼摘要,覆盖:
- 本 packet 完成了什么(一段)
- 关键设计选择与理由(一段)
- 已验证但易被忽略的隐藏假设(一段)
- 与上游决策的对齐情况(一段)>
do_not_re_explore:
- "<下一个 packet 不要重复讨论的问题>"
- "<另一条已闭环的话题>"
# === 风险登记 ===
risks_or_debt:
- description: "<已知遗留的技术债 / 风险>"
severity: low | medium | high
suggested_owner: <packet-id 或 agent / 人>
# === 验证证据 ===
verification_evidence:
acceptance_criteria_passed: [<criteria-id 列表>]
acceptance_criteria_failed: [<如有>]
tests_run: <命令 + 结果,例如 "pytest server/tests/test_profile_consent.py: 12 passed">
manual_checks: [<如有,列出人工验证项>]
# === Context Budget 实际消耗 ===
context_budget_actual:
estimated_total_budget: <来自 packet 声明>
actual_input_tokens: <agent 实际消耗>
actual_tool_call_tokens: <累积工具调用 token>
actual_output_tokens: <实际产出>
total_actual: <三者之和>
within_budget: true | false
notes_if_overrun: "<如超 budget,说明原因>"
# === 下游 packet 路由 ===
next_packets_unblocked:
- <packet-id 列表,表示本 packet 完成解除了哪些后续 packet 的依赖>
# === 引用 ===
references:
parent_packet: <如本身是 sub-packet>
upstream_decisions: [<v1-engineering-kickoff-decisions.md 中的 D-XX 列表>]
related_anchors: [<相关 anchor 路径>]
4. Field Guidelines
4.1 completion_status
| 值 | 含义 | 后续动作 |
|---|---|---|
| started | Agent 已开始执行但尚未有实质产出 | Dashboard 显示 in-progress;Agent 继续工作 |
| done | 完全完成;所有 acceptance criteria 通过 | 解除依赖此 packet 的下游 packet |
| partial | 部分完成;有未完成项写入 open_questions | 必须由下一个 packet 接手 |
| blocked | 因外部因素阻塞;本 packet 无法推进 | 升级到项目发起人 |
禁止:状态 done 但 acceptance_criteria_failed 非空。
4.2 key_decisions_locked
只写「本 packet 内做出且对后续工作有约束力」的决策。
✅ 好例子:
- "ProfileConsent 对象设计采用 opt-in 而非 opt-out,已与 D-12 对齐"
- "API endpoint
/v1/consent/grant返回 204 No Content(无返回体)" - "Pydantic v2 BaseModel 替代旧 v1 BaseSettings"
❌ 坏例子(不要写):
- "我们决定开始这个 packet"(不是决策)
- "ProfileConsent 是个好对象"(不是决策)
- "GPT-5.5 比 Claude 好"(与本 packet 无关的笼统判断)
4.3 context_to_carry_forward
精炼摘要的撰写要求:
- ≤ 1500 字;
- 不复制本 packet 内代码 / 配置 / 测试输出;
- 不复制治理库已有内容;
- 着重「假设与上下文」:下一个 Agent 看不到本 packet 的对话历史,看到的 anchor 必须能让 ta 立即理解为什么这些决策是这样的;
- 主动指出易被忽略的隐藏假设(这通常是 Agent 漂移的源头)。
4.4 do_not_re_explore
列出已经反复讨论且达成共识的话题,明确告知下一个 Agent 不要重启。
例如:
- "GPT-5.5 + Kimi K2.6 的选择已经在 D-04 锁定;如有质量问题,进入 evaluation 流程而非重新讨论 provider"
- "ProfileConsent 是否使用 opt-in 已经在本 packet 与 D-12 对齐,不要重启讨论"
4.5 context_budget_actual
实际消耗记录:
- 由 Agent 自报;
- 如果
actual_total > estimated_total_budget * 1.2(超 20%),标within_budget: false并填notes_if_overrun; - 多次 overrun 是「packet 切片不够细」的信号,需要在后续 packet 设计时反馈。
4.6 next_packets_unblocked
明确列出本 packet 完成后解除了哪些下游 packet 的依赖。
这是 multi-agent 编排的关键:让项目发起人 / 编排者一眼看到「现在可以启动哪些 packet」。
5. Anti-Patterns
| 反模式 | 为什么禁止 |
|---|---|
| 把整个工程仓库 git diff 粘贴到 context_to_carry_forward | 超 5K 限制;浪费 |
| anchor 中复制 must_read 文档原文 | 浪费;下一个 Agent 自己能读 |
| 用「TODO」「待补充」「稍后处理」 | 没有责任主体;应明确写入 open_questions_for_next_packet 或 risks_or_debt |
| 用模糊词「优化」「重构」「改进」 | 让下一个 Agent 不知道边界;应写「将 X 模块的 Y 函数从 N 行减至 M 行」 |
| 跳过 verification_evidence | 让 acceptance 不可验证;下游 Agent 无法信任 |
| done 但 actual_total > 2 * estimated | 强烈预警 packet 切片不当;下次必须更细切片 |
6. Example Hand-off Anchor
# /Users/mlabs/Programs/Labs-FinTecAI/projects/finclaw/handoff-anchors/v1-eng-impl-sub-1-profile-consent.yaml
packet_id: v1-eng-impl-sub-1-profile-consent
packet_type: sub-packet
completion_status: done
completed_at: 2026-05-18T11:23:04+08:00
completed_by_agent: cursor-claude-4.7-opus
completed_in_worktree: /Users/mlabs/Programs/CurvatureLabs/finclaw-agent-A
completed_on_branch: feature/profile-consent
key_decisions_locked:
- "ProfileConsent 采用 opt-in 模型,opt-out 用户不能进入 trial(已与 D-12 对齐)"
- "Consent 持久化路径:data/consents/<user_id>.yaml(与 D-10.b 选择性迁移保持一致的文件持久化模式)"
- "撤回 consent 后,已生成的 snapshot 保留,但 instrumentation 停止上报"
- "Pydantic v2 BaseModel;不使用 dataclass(一致性原因)"
produced_artifacts:
- path: server/agent/models.py
type: code
short_description: "新增 ProfileConsent + ConsentScope 模型"
revision: feature/profile-consent @ a3f5b21
- path: server/api/consent_routes.py
type: code
short_description: "POST /v1/consent/grant、DELETE /v1/consent/revoke 两个端点"
revision: feature/profile-consent @ a3f5b21
- path: web/src/domains/onboarding/ProfileConsentDialog.tsx
type: code
short_description: "Onboarding 弹窗,包含 4 类 ConsentScope checkbox"
revision: feature/profile-consent @ a3f5b21
- path: server/tests/test_profile_consent.py
type: test
short_description: "12 个测试:grant/revoke/list/expiry/storage"
revision: feature/profile-consent @ a3f5b21
open_questions_for_next_packet:
- "ProfileConsent 与 TrainingAssetCandidate 的关联待 sub-3 处理"
- "Onboarding 流程是否需要在 ConsentDialog 之前增加 Labs 内部知会函页面(D-13)"
context_to_carry_forward: |
ProfileConsent 实现完成,对应 AL-1。模型采用 opt-in 而非 opt-out(用户必须显式同意才能进入 trial),
这与 D-12 隐私复核延后但不豁免的策略一致:内测期间内置 opt-in 不阻塞后续法务复核。
Consent 持久化采用文件而非数据库,是为了与现有 CognitionStore 文件持久化模式一致(保持 V1 整体
「无数据库依赖」的轻量化原则)。后续如需迁移到数据库,CRUD 层已经抽象,迁移成本低。
Onboarding 流程当前只覆盖 ConsentDialog,缺 Labs 内部知会函页面(D-13 提到内部同意书)。这个
页面需要在 sub-2 或独立 sub-packet 中补齐。
与 GDPR 复核(C-1)的对齐情况:模型字段已包含 consent_version、consent_timestamp、
revoke_path、retention_policy 四个 GDPR-friendly 字段,但**真正的 GDPR 合规需要法务复核**
(这不是本 sub-packet 范围)。
隐藏假设:本 sub-packet 假定「Labs 内测期间不需要多语言 consent text」。trial 公开扩展时
需要重新评估。
do_not_re_explore:
- "ProfileConsent 是否 opt-in(已锁定)"
- "持久化是否用数据库(已锁定为文件)"
- "consent 字段命名(已锁定)"
risks_or_debt:
- description: "Onboarding 流程缺 Labs 知会函页面"
severity: medium
suggested_owner: v1-eng-impl-sub-2-onboarding-completion
- description: "GDPR 法务复核未完成"
severity: high
suggested_owner: C-1 / 项目发起人
verification_evidence:
acceptance_criteria_passed:
- AC-1: ProfileConsent 模型字段完整
- AC-2: grant/revoke endpoint 工作
- AC-3: 撤回后 instrumentation 停止
- AC-4: Onboarding UI 显示
acceptance_criteria_failed: []
tests_run: "pytest server/tests/test_profile_consent.py: 12 passed in 0.42s"
manual_checks:
- "在新工程仓库 dev 环境验证 ConsentDialog 显示正常"
context_budget_actual:
estimated_total_budget: 45_000
actual_input_tokens: 23_500
actual_tool_call_tokens: 12_800
actual_output_tokens: 7_200
total_actual: 43_500
within_budget: true
notes_if_overrun: ""
next_packets_unblocked:
- v1-eng-impl-sub-2-onboarding-completion
- v1-eng-impl-sub-3-training-asset-candidate
references:
parent_packet: v1-engineering-implementation-task-packet
upstream_decisions:
- D-12 (隐私 / 合规复核)
- D-13 (NDA / 同意书)
- AL-1 (alignment Action Item)
related_anchors: []
7. Anchor Directory Layout
/Users/mlabs/Programs/Labs-FinTecAI/projects/finclaw/handoff-anchors/
├── README.md ← 本目录说明 + anchor 索引
├── <packet-id-1>.yaml
├── <packet-id-1>.hotfix-1.yaml ← 显式修正(如有)
├── <packet-id-2>.yaml
└── ...
注:handoff-anchors/ 目录将在阶段 0 完成时一并创建(含 README)。
8. Anchor Reading by Next Agent
下一个 Agent 启动时只载入以下 anchor 资料:
| 加载项 | tokens |
|---|---|
| 直接前置 packet 的 anchor | ≤ 5K |
| 同 milestone 内的相关 anchor 摘要(如有) | ≤ 3K |
| 当前 packet 自己的 frontmatter | ≤ 2K |
总计 ≤ 10K,远低于 sweet spot 30-80K,保留给 must_read 文档和实际工作。
9. Open Items
- Anchor 自动校验脚本(验证 YAML schema、check
within_budget、checkacceptance_criteria覆盖)尚未实现; - Anchor 索引页(README + 自动列出所有 anchor 的状态摘要)需要在阶段 0 完成时建立;
- 跨 packet 的依赖图自动可视化工具尚未实现。