# Long Horizon

> 用一次长程自主运行执行一个定稿的目标——数小时的 agent 工作推完整个验收台账，人只出现在两道闸：运行前的 spec、运行后的 review。适用于 /long-horizon、「长程执行这个任务」「跑一个长程目标」，或在已有 `.long-horizon/` 工作区的仓库中恢复工作时。入口交互式反复迭代；运行由 fan-out 驱动、副作用被授权信封约束；进展只认证据；实时 report.html 以 DAG 呈现台账。

- Skill: `keli-wen/long-horizon-2` (Agent Skill)
- Install (CLI): `npx skillmds@latest add keli-wen/long-horizon-2`
- Raw SKILL.md: https://api.skillmd.com/api/skills/keli-wen/long-horizon-2/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Web & Frontend
- Author: keli-wen (https://skillmd.com/u/keli-wen)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/keli-wen/long-horizon-2

---


# long-horizon

一个目标，两道人的闸，一次长跑。人和 agent 反复迭代 spec 直到签字；然后运行在授权信封内自主推进数小时、推完整个台账；然后人读 report 给出调整。编排上下文只派发和验证——不亲自执行。持久状态在 `.long-horizon/<goal-slug>/`，三道价值闸全程有效：入口（说不出验证方式的不得进入）、证据（进展只在验证后成立）、出口（停下来是设计出来的，不是失败）。

**语言**：聊天跟随用户；工作区文件跟随项目的文档语言。

**Load-on-use**：本文档里每个 `/name` 都是调用指令——做那类工作之前，先加载该 skill 的完整文档（Skill 工具，或读它的 SKILL.md）；绝不凭一行 description 复刻行为。

## 工作区 —— `.long-horizon/<goal-slug>/`

- 一个 goal 一个目录，slug 命名；同时只有一个活跃 goal。任何恢复都先做身份核对：读 `goal.md`——如果它描述的不是你的 goal，停下来问人。
- `goal.md` —— 冻结的 spec：goal、non-goals、invariants、每条 Done-when 附可运行检查，以及**授权信封**。改它必须经人重新定稿，绝不能是顺手为之。
- `ledger.json` —— 验收台账：`{id, desc, verify, passes, evidence, deps, discovered-from}`。每一项生来 `passes: false`。
- `log.md` —— append-only：决策、死胡同、派发记录。失败的尝试留在里面——它们是证据。
- `next.md` —— 恢复指针：什么在飞行中、接下来什么就绪。
- `report.html` —— 实时监督视图；契约见下。
- 工作区**不进 git**：入口阶段就把它加进 .gitignore（以及格式化工具的忽略清单）——被 track 的工作区会污染每个工作分支的 diff。耐久性靠代码 commit、毕业蒸馏和 report。毕业时经 `/to-ctx` 蒸馏，然后归档或删除该目录。

## 第一道闸 —— Spec（交互式；要迭代多久就迭代多久）

1. 把目标交给 `/ctx-grill`。与用户反复迭代，直到 spec 立得住：
   - 每条 Done-when 都说得出可运行的检查——没有检查就不得进入；
   - non-goals 和 invariants 写明；
   - **授权信封**——运行期无人值守时允许做什么。默认：在工作分支 commit、开 PR、push 自己的分支——允许；merge、删除工作区之外的东西、对外发送任何内容、花钱——禁止。收紧或放宽只在此处、显式进行。
   - **验证配置**——问一次：哪些检查由编排者自己重跑、哪些验收项配黑盒验证 agent、验证者用什么档位的模型（默认中档模型）；
   - 初始台账，带依赖关系。
2. 一坐就能干完的目标拒绝进入——正常做掉即可。
3. 签字后：写工作区，开始运行。

## 运行 —— 自主，数小时

- **只编排，不执行。**加载 `/fan-out`，把台账项写成任务契约派给 subagent；自己的上下文只保留 spec、台账、证据摘要和决策——探索噪声由 worker 吸收。这是结构性要求而非可选项：整个台账的执行量装不进一个上下文窗口。
- **按 DAG 调度**：派发就绪集（依赖全部通过的项）；独立项并行——会同时改同一仓库时用 worktree 隔离；高耦合的项簇交给同一个 worker。
- **先验证再翻位**：worker 的说法永远不是证据。机械检查（测试、lint、构建）自己重跑；行为性验收交给黑盒验证 subagent（用 spec 定的档位），它只看产出物和验收标准。
- **一次失败只换来一次重写，换不来原样重来**：派出去的项失败时——worker 报错，或验证否掉了它的说法——只重派一次，且契约必须围绕失败证据重写：试过什么、哪项检查没过、怎么没过。换角度或换 worker；绝不把同一份契约原样再发一遍。每项每轮派发只有这一次战术重试；重试再失败，该项按「没动」计入停滞账，失败写进 `log.md`——本轮不再有第三次。
- **每翻一位就刷新 report 的数据块**——运行期间 report 就是人的实时仪表盘。
- **发现新问题是预期内的**：新问题记为新台账项（`discovered-from`）加入调度。会改变 spec 方向的问题记为 blocked 项并写下待答问题——不依赖它的所有分支继续推进。
- 若 harness 有原生 goal 机制，喂给它：「台账全部 passes 或 blocked，或 N 小时后停」。
- **停止条件**：全部通过；剩余项全部悬在 blocked 上；连续两轮派发（含战术重试）台账不动（停滞——绝不做第三次一模一样的尝试）；或预算耗尽。收尾必产出最终 report 和一份 `/handoff`。

## 第二道闸 —— Review

人读 report、给出评论。调整落为 spec 修正或台账修改——这是验收行可以被改写或删除的唯一通道。下一次运行从工作区恢复，先做身份核对。

## 中断是可幸存的，但不是节奏

假设任何时刻都可能是最后一刻：上下文死亡、崩溃、预算截断。新的编排者读工作区、核对 `goal.md` 身份、从 `ledger.json` + `next.md` 恢复。这些文件为此而存在——不是为了每做几项就把目标交还给人。

## Report —— 契约，而非模板

`report.html` 由模型自作：怎么表达清楚就怎么设计，随模型进步随时整体重画——它可丢弃、可从状态再生。不可协商：

- **视图，绝非事实源**：生成是单向的；展示的一切必须先存在于状态文件。必须展示：目标及其 Done-when；每个台账项及其状态；**依赖结构必须画成图——关键路径和阻塞割点一眼可见，不能只列文字**；blocked 项与待答问题（醒目位置）；关键决策；最后更新时间与 session 计数。
- **自包含**：单文件、`file://` 直接打开、无外部请求。
- **数据与渲染分离**：只嵌一个数据块；日常刷新只碰数据块，不动标记。

## 规则

- 信封在所有阶段都是硬边界：不做不可逆的事，不越界。
- 台账行对 agent 写保护：只能翻 `passes`、追加 `evidence`、新增条目；改写或删除只发生在 review 阶段、由人执行。
- `passes` 翻在验证通过时，不翻在代码写完时。
- 聊天中与工作区文件矛盾的纠正必须同回合写回文件——否则过期文件会赢。
- 依赖方向：可以使用 `/ctx-grill`、`/fan-out`、`/handoff`、`/to-ctx`；long-horizon 位于图的最顶端，没有 skill 会调用它。

