第一时间捕获有价值的信号
本文译自 Clayton Farr 的 The Ralph Playbook,这是对 Geoffrey Huntley 提出的 Ralph 方法的深度整理。Ralph 不是一个简单的写代码循环,而是一个完整的漏斗——从想法到 JTBD 对齐的规格,再到全面的实施计划,最后是 Ralph 工作循环。本文将用通俗易懂的方式,带你理解如何让 AI 真正”做自己”,实现高效的自主编程。
那到底该怎么用 Ralph 才最好?
很多人似乎用各种方式都取得了不错的效果,但我想尽可能从那个不仅提出了这个方法,而且花了最多时间实际验证的人那里,读懂其中的细节。
所以我深入研究了最近的视频和 Geoff 的原始文章,想自己搞清楚到底怎么做才最有效。
下面就是结果——一份(可能有点强迫症的)Ralph 操作手册,整理了把这一切付诸实践的各种细节,希望不要在过程中把它的精髓弄丢了。
深入研究这一切也让我想到了一些可能有价值的额外增强方案,这些方案旨在与让 Ralph 如此有效的核心原则保持一致。
目录
Open 目录
工作流
一张图胜过千条推文和一小时视频。Geoff 的这里的概述真的帮我理清了从 1)想法 → 2)单独的 JTBD 对齐的规格 → 3)全面的实施计划 → 4)Ralph 工作循环的工作流细节。

三个阶段,两个提示,一个循环
这张图让我明白,Ralph 不只是”一个写代码的循环”。它是一个漏斗,有 3 个阶段、2 个提示和 1 个循环。
阶段 1. 定义需求(LLM 对话)
- 讨论项目想法 → 识别 Jobs to Be Done (JTBD)
- 将单个 JTBD 拆解为关注点
- 使用子代理从 URL 加载信息到上下文中
- LLM 理解 JTBD 关注点:子代理为每个关注点编写
specs/FILENAME.md
阶段 2 / 3. 运行 Ralph 循环(两种模式,根据需要切换 PROMPT.md)
相同的循环机制,不同的提示用于不同的目标:
| 模式 | 何时使用 | 提示重点 |
|---|---|---|
| 规划 | 没有计划,或计划过时/错误 | 仅生成/更新 IMPLEMENTATION_PLAN.md |
| 构建 | 计划已存在 | 按计划实施,提交,顺便更新计划 |
每种模式的提示差异:
- “规划”提示进行差距分析(规格 vs 代码)并输出优先级待办事项列表——不实施,不提交。
- “构建”提示假设计划已存在,从中选择任务,实施,运行测试(反压),提交。
为什么两种模式都用循环?
- 构建需要它:本质上是迭代的(许多任务 × 新鲜上下文 = 隔离)
- 规划用它是为了一致性:相同的执行模型,虽然通常 1-2 次迭代就完成
- 灵活性:如果计划需要细化,循环允许多次读取自己的输出
- 简单:一个机制搞定一切;清晰的文件 I/O;易于停止/重启
每次迭代加载的上下文: PROMPT.md + AGENTS.md
规划模式循环生命周期:
- 子代理研究
specs/*和现有的/src - 比较规格与代码(差距分析)
- 创建/更新
IMPLEMENTATION_PLAN.md并列出优先级任务 - 不实施任何内容
构建模式循环生命周期:
- 定位 – 子代理研究
specs/*(需求) - 阅读计划 – 研究
IMPLEMENTATION_PLAN.md - 选择 – 选择最重要的任务
- 调查 – 子代理研究相关的
/src(“不要假设没实现”) - 实施 – N 个子代理进行文件操作
- 验证 – 1 个子代理进行构建/测试(反压)
- 更新
IMPLEMENTATION_PLAN.md– 标记任务完成,记录发现/bug - 更新
AGENTS.md– 如果有操作层面的经验 - 提交
- 循环结束 → 上下文清空 → 下一次迭代重新开始
概念
| 术语 | 定义 |
|---|---|
| Job to Be Done (JTBD) | 高层级的用户需求或结果 |
| 关注点 | JTBD 内的一个独立方面/组件 |
| 规格 | 一个关注点的需求文档(specs/FILENAME.md) |
| 任务 | 通过比较规格与代码得出的工作单元 |
关系:
- 1 个 JTBD → 多个关注点
- 1 个关注点 → 1 个规格
- 1 个规格 → 多个任务(规格比任务大)
例子:
- JTBD:“帮助设计师创建情绪板”
- 关注点:图片收集、颜色提取、布局、分享
- 每个关注点 → 一个规格文件
- 每个规格 → 实施计划中的许多任务
关注点范围测试:“一句话不带’和’”
- 你能用一句话描述关注点,而不连接不相关的功能吗?
- ✓ “颜色提取系统分析图片以识别主色调”
- ✗ “用户系统处理认证、资料和账单” → 3 个关注点
- 如果你需要用”和”来描述它的功能,那可能是多个关注点
核心原则
⏳ 上下文就是一切
- 当宣传 200K+ token 时 = 实际可用约 176K
- 而”智能区域”的上下文利用率为 40-60%
- 紧凑的任务 + 每个循环 1 个任务 = 100% 智能区域上下文利用率
这决定并驱动了其他一切:
- 使用主代理/上下文作为调度器
- 不要把昂贵的工作分配给主上下文;尽可能改用子代理
- 使用子代理作为内存扩展
- 每个子代理获得约 156kb,会被垃圾回收
- 分散出去以避免污染主上下文
- 简单和简洁胜出
- 适用于系统中的部件数量、循环配置和内容
- 冗长的输入会降低确定性
- 优先使用 Markdown 而非 JSON
- 为了更好的 token 效率来定义和跟踪工作
🧭 引导 Ralph:模式 + 反压
创建正确的信号和门控来引导 Ralph 成功输出 至关重要。你可以从两个方向引导:
- 从上游引导
- 确保确定性设置:
- 为规格分配前约 5,000 个 token
- 每个循环的上下文都分配相同的文件,这样模型从已知状态开始(
PROMPT.md+AGENTS.md)
- 你现有的代码塑造了使用和生成的内容
- 如果 Ralph 生成错误的模式,添加/更新工具和现有代码模式来引导它走向正确的模式
- 确保确定性设置:
- 从下游引导
- 通过测试、类型检查、lint、构建等创建反压,拒绝无效/不可接受的工作
- 提示泛泛地说”运行测试”。
AGENTS.md指定实际命令,使反压针对特定项目 - 反压可以扩展到代码验证之外:一些验收标准抗拒程序化检查——创意质量、美学、用户体验感觉。LLM 作为法官的测试可以为主观标准提供二进制通过/失败的反压。(下面有关于如何用 Ralph 处理这个的更详细想法)
- 提醒 Ralph 创建/使用反压
- 提醒 Ralph 在实施时使用反压:“重要:在编写文档时,记录原因——测试和实施的重要性。”
🙏 让 Ralph 做自己
Ralph 的有效性来自于你多大程度信任它做正确的事(最终)并培养它这样做的能力。
- 让 Ralph 做自己
- 利用 LLM 自我识别、自我纠正和自我改进的能力
- 适用于实施计划、任务定义和优先级排序
- 通过迭代实现最终一致性
- 使用保护措施
- 为了自主操作,Ralph 需要
--dangerously-skip-permissions——每次工具调用都请求批准会打破循环。这完全绕过了 Claude 的权限系统——所以沙箱成为你唯一的安全边界。 - 理念:“不是会不会被攻破,而是什么时候。以及影响范围有多大?”
- 没有沙箱运行会暴露你机器上的凭证、浏览器 cookie、SSH 密钥和访问令牌
- 在具有最小可行访问权限的隔离环境中运行:
- 只需要任务所需的 API 密钥和部署密钥
- 除了需求外,不访问私人数据
- 尽可能限制网络连接
- 选项:Docker 沙箱(本地)、Fly Sprites/E2B 等(远程/生产)- 附加说明
- 额外的紧急出口:Ctrl+C 停止循环;
git reset --hard还原未提交的更改;如果轨迹出错,重新生成计划
- 为了自主操作,Ralph 需要
🚦 移到循环外面
为了充分利用 Ralph,你需要让开道。Ralph 应该做_所有_的工作,包括决定下一步实施哪个计划工作以及如何实施。你的工作现在是坐在循环上,而不是在里面——设计设置和环境,让 Ralph 能够成功。
观察和纠正方向——尤其是在早期,坐下来观察。出现了什么模式?Ralph 哪里出错了?他需要什么信号?你开始用的提示不会是你结束用的提示——它们通过观察到的失败模式演变。
像调吉他一样调整它——不是预先规定一切,而是观察和被动调整。当 Ralph 以特定方式失败时,添加一个信号下次帮助他。
但信号不只是提示文本。它们是 Ralph 可以发现的_任何东西_:
- 提示护栏——明确的指示,如”不要假设没实现”
AGENTS.md——关于如何构建/测试的操作经验- 代码库中的工具——当你添加一个模式时,Ralph 会发现并遵循它
- 其他可发现的、相关的输入……
记住,计划是可丢弃的:
- 如果错了,扔掉它,重新开始
- 重新生成的成本是一个规划循环;与 Ralph 绕圈子相比很便宜
- 在这些情况下重新生成:
- Ralph 偏离轨道(实施错误的东西,重复工作)
- 计划感觉过时或与当前状态不匹配
- 已完成项目的混乱太多
- 你做了重大的规格更改
- 你对实际完成的内容感到困惑
循环机制
外层循环控制
Geoff 最初的最简形式 loop.sh 脚本:
while :; do cat PROMPT.md | claude ; done
注意: 同样的方法可以用于其他 CLI;例如 amp、codex、opencode 等。
什么控制任务继续?
继续机制非常简单:
- Bash 循环运行 → 将
PROMPT.md喂给 claude - PROMPT.md 指示 → “研究 IMPLEMENTATION_PLAN.md 并选择最重要的事情”
- 代理完成一个任务 → 更新磁盘上的 IMPLEMENTATION_PLAN.md,提交,退出
- Bash 循环立即重启 → 新鲜的上下文窗口
- 代理读取更新的计划 → 选择下一个最重要的事情
关键见解: IMPLEMENTATION_PLAN.md 文件在迭代之间持久保存在磁盘上,并充当其他隔离循环执行之间的共享状态。每次迭代确定性地加载相同的文件(PROMPT.md + AGENTS.md + specs/*)并从磁盘读取当前状态。
不需要复杂的编排——只是一个不断重启代理的笨拙 bash 循环,代理通过每次读取计划文件来弄清楚下一步该做什么。
内层循环控制(任务执行)
单个任务执行没有硬性技术限制。控制依赖于:
- 范围纪律 - PROMPT.md 指示”一个任务”和”测试通过时提交”
- 反压 - 测试/构建失败强制代理在提交前修复问题
- 自然完成 - 代理在成功提交后退出
Ralph 可能会绕圈子、忽略指示或走错方向——这是预期的,也是调整过程的一部分。当 Ralph”测试你”以特定方式失败时,你向提示添加护栏或调整反压机制。通过观察和迭代,不确定性是可管理的。
增强循环示例
用模式选择(规划/构建)、最大迭代支持和每次迭代后的 git push 包装核心循环。
这个增强使用两个保存的提示文件:
PROMPT_plan.md- 规划模式(差距分析,生成/更新计划)PROMPT_build.md- 构建模式(按计划实施)
#!/bin/bash
# 用法:./loop.sh [plan] [max_iterations]
# 示例:
# ./loop.sh # 构建模式,无限制迭代
# ./loop.sh 20 # 构建模式,最多 20 次迭代
# ./loop.sh plan # 规划模式,无限制迭代
# ./loop.sh plan 5 # 规划模式,最多 5 次迭代
# 解析参数
if [ "$1" = "plan" ]; then
# 规划模式
MODE="plan"
PROMPT_FILE="PROMPT_plan.md"
MAX_ITERATIONS=${2:-0}
elif [[ "$1" =~ ^[0-9]+$ ]]; then
# 带最大迭代的构建模式
MODE="build"
PROMPT_FILE="PROMPT_build.md"
MAX_ITERATIONS=$1
else
# 构建模式,无限制(无参数或无效输入)
MODE="build"
PROMPT_FILE="PROMPT_build.md"
MAX_ITERATIONS=0
fi
ITERATION=0
CURRENT_BRANCH=$(git branch --show-current)
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "模式: $MODE"
echo "提示: $PROMPT_FILE"
echo "分支: $CURRENT_BRANCH"
[ $MAX_ITERATIONS -gt 0 ] && echo "最大: $MAX_ITERATIONS 次迭代"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
# 验证提示文件存在
if [ ! -f "$PROMPT_FILE" ]; then
echo "错误:$PROMPT_FILE 未找到"
exit 1
fi
while true; do
if [ $MAX_ITERATIONS -gt 0 ] && [ $ITERATION -ge $MAX_ITERATIONS ]; then
echo "已达到最大迭代次数:$MAX_ITERATIONS"
break
fi
# 使用选定的提示运行 Ralph 迭代
# -p:无头模式(非交互,从标准输入读取)
# --dangerously-skip-permissions:自动批准所有工具调用(放手干模式)
# --output-format=stream-json:用于日志/监控的结构化输出
# --model opus:主代理使用 Opus 进行复杂推理(任务选择、优先级排序)
# 如果计划清晰且任务定义明确,可以在构建模式中使用 'sonnet' 以提高速度
# --verbose:详细执行日志
cat "$PROMPT_FILE" | claude -p \
--dangerously-skip-permissions \
--output-format=stream-json \
--model opus \
--verbose
# 每次迭代后推送更改
git push origin "$CURRENT_BRANCH" || {
echo "推送失败。正在创建远程分支..."
git push -u origin "$CURRENT_BRANCH"
}
ITERATION=$((ITERATION + 1))
echo -e "\n\n======================== 循环 $ITERATION ========================\n"
done
模式选择:
- 无关键字 → 使用
PROMPT_build.md进行构建(实施) plan关键字 → 使用PROMPT_plan.md进行规划(差距分析,计划生成)
最大迭代:
- 限制_外层循环_(尝试的任务数量;不是单个任务内的工具调用)
- 每次迭代 = 一个新鲜的上下文窗口 = IMPLEMENTATION_PLAN.md 中的一个任务 = 一次提交
./loop.sh无限制运行(用 Ctrl+C 手动停止)./loop.sh 20最多运行 20 次迭代然后停止
Claude CLI 标志:
-p(无头模式):启用非交互操作,从标准输入读取提示--dangerously-skip-permissions:绕过所有权限提示以进行完全自动化运行--output-format=stream-json:输出结构化 JSON 用于日志/监控/可视化--model opus:主代理使用 Opus 进行任务选择、优先级排序和协调(如果任务清晰,可以使用sonnet以提高速度)--verbose:提供详细的执行日志
文件说明
project-root/
├── loop.sh # Ralph 循环脚本
├── PROMPT_build.md # 构建模式指令
├── PROMPT_plan.md # 规划模式指令
├── AGENTS.md # 每次迭代加载的操作指南
├── IMPLEMENTATION_PLAN.md # 优先级任务列表(由 Ralph 生成/更新)
├── specs/ # 需求规格(每个 JTBD 关注点一个)
│ ├── [jtbd-topic-a].md
│ └── [jtbd-topic-b].md
├── src/ # 应用源代码
└── src/lib/ # 共享工具和组件
loop.sh
编排 Ralph 迭代的外层循环脚本。
有关详细的实现示例和配置选项,请参阅循环机制部分。
设置: 在首次使用前使脚本可执行:
chmod +x loop.sh
核心功能: 持续将提示文件喂给 claude,管理迭代限制,并在每个任务完成后推送更改。
提示
每个循环迭代的指令集。根据需要在规划和构建版本之间切换。
提示结构:
| 部分 | 目的 |
|---|---|
| 阶段 0 (0a, 0b, 0c) | 定位:研究规格、源位置、当前计划 |
| 阶段 1-4 | 主要指令:任务、验证、提交 |
| 999… 编号 | 护栏/不变量(编号越高 = 越关键) |
关键语言模式(Geoff 的特定措辞):
- “study”(不是”read”或”look at”)
- “don’t assume not implemented”(关键——致命弱点)
- “using parallel subagents” / “up to N subagents”
- “only 1 subagent for build/tests”(反压控制)
- “Think extra hard”(现在是”Ultrathink”)
- “capture the why”
- “keep it up to date”
- “if functionality is missing then it’s your job to add it”
- “resolve them or document them”
PROMPT_plan.md 模板
注意: 更新下面的 [项目特定目标] 占位符。
- 当前的子代理名称假设使用 Claude。
0a. 使用最多 250 个并行 Sonnet 子代理研究 `specs/*` 以了解应用规格。
0b. 研究 @IMPLEMENTATION_PLAN.md(如果存在)以了解到目前为止的计划。
0c. 使用最多 250 个并行 Sonnet 子代理研究 `src/lib/*` 以了解共享工具和组件。
0d. 作为参考,应用源代码在 `src/*` 中。
1. 研究 @IMPLEMENTATION_PLAN.md(如果存在;可能不正确)并使用最多 500 个 Sonnet 子代理研究 `src/*` 中的现有源代码,并将其与 `specs/*` 进行比较。使用 Opus 子代理分析发现、确定任务优先级,并创建/更新 @IMPLEMENTATION_PLAN.md 作为按尚未实施项目的优先级排序的项目符号列表。Ultrathink。考虑搜索 TODO、最小实现、占位符、跳过/不稳定测试和不一致的模式。研究 @IMPLEMENTATION_PLAN.md 以确定研究的起点,并使用子代理保持其更新,标记已完成/未完成的项目。
重要:仅规划。不要实施任何内容。不要假设功能缺失;先用代码搜索确认。将 `src/lib` 视为项目的共享工具和组件标准库。优先考虑那里的整合、惯用实现,而不是临时复制。
最终目标:我们要实现 [项目特定目标]。考虑缺失的元素并相应规划。如果元素缺失,先搜索确认它不存在,然后根据需要在 specs/FILENAME.md 编写规格。如果你创建了一个新元素,那么使用子代理在 @IMPLEMENTATION_PLAN.md 中记录实施它的计划。
PROMPT_build.md 模板
注意: 当前的子代理名称假设使用 Claude。
0a. 使用最多 500 个并行 Sonnet 子代理研究 `specs/*` 以了解应用规格。
0b. 研究 @IMPLEMENTATION_PLAN.md。
0c. 作为参考,应用源代码在 `src/*` 中。
1. 你的任务是使用并行子代理按照规格实施功能。遵循 @IMPLEMENTATION_PLAN.md 并选择要处理的最重要项目。在进行更改之前,使用 Sonnet 子代理搜索代码库(不要假设没实现)。你可以使用最多 500 个并行 Sonnet 子代理进行搜索/读取,仅使用 1 个 Sonnet 子代理进行构建/测试。需要复杂推理时使用 Opus 子代理(调试、架构决策)。
2. 在实施功能或解决问题后,运行该改进代码单元的测试。如果功能缺失,那么你的工作是按照应用规格添加它。Ultrathink。
3. 当你发现问题时,立即使用子代理用你的发现更新 @IMPLEMENTATION_PLAN.md。解决后,更新并删除该项目。
4. 当测试通过时,更新 @IMPLEMENTATION_PLAN.md,然后 `git add -A` 然后 `git commit`,提交消息描述更改。提交后,`git push`。
99999. 重要:在编写文档时,记录原因——测试和实施的重要性。
999999. 重要:单一事实来源,无迁移/适配器。如果与你的工作无关的测试失败,将它们作为增量的一部分解决。
9999999. 一旦没有构建或测试错误,创建一个 git tag。如果没有 git tag,从 0.0.0 开始,例如如果 0.0.0 不存在,则补丁递增 1 到 0.0.1。
99999999. 如果需要调试问题,你可以添加额外的日志。
999999999. 使用子代理保持 @IMPLEMENTATION_PLAN.md 更新——未来的工作依赖于此以避免重复工作。特别是在完成你的回合后更新。
9999999999. 当你学到关于如何运行应用的新东西时,使用子代理更新 @AGENTS.md,但保持简洁。例如,如果你在学习正确命令之前多次运行命令,那么应该更新该文件。
99999999999. 对于你注意到的任何 bug,即使与当前工作无关,也要解决它们或使用子代理在 @IMPLEMENTATION_PLAN.md 中记录它们。
999999999999. 完全实施功能。占位符和存根浪费精力和时间重做同样的工作。
9999999999999. 当 @IMPLEMENTATION_PLAN.md 变大时,使用子代理定期从文件中清除已完成的项目。
99999999999999. 如果你在 specs/* 中发现不一致,使用请求'ultrathink'的 Opus 4.5 子代理更新规格。
999999999999999. 重要:保持 @AGENTS.md 仅用于操作——状态更新和进度记录属于 `IMPLEMENTATION_PLAN.md`。臃肿的 AGENTS.md 会污染每个未来循环的上下文。
AGENTS.md
单一、规范的”循环核心”——一份简洁、可操作的”如何运行/构建”指南。
- 不是变更日志或进度日记
- 描述如何构建/运行项目
- 捕获改进循环的操作经验
- 保持简洁(约 60 行)
状态、进度和规划属于 IMPLEMENTATION_PLAN.md,不属于这里。
环回 / 即时自我评估:
AGENTS.md 应该包含项目特定的命令,这些命令启用环回——Ralph 在同一循环内立即评估他的工作的能力。这包括:
- 构建命令
- 测试命令(目标和完整套件)
- 类型检查/lint 命令
- 任何其他验证工具
构建提示泛泛地说”运行测试”;AGENTS.md 指定实际命令。这就是反压如何按项目连接的。
示例
## 构建和运行
关于如何构建项目的简洁规则:
## 验证
实施后运行这些以获得即时反馈:
- 测试:`[测试命令]`
- 类型检查:`[类型检查命令]`
- Lint:`[lint 命令]`
## 操作说明
关于如何运行项目的简洁经验:
...
### 代码库模式
...
IMPLEMENTATION_PLAN.md
从差距分析(规格 vs 代码)得出的优先级项目符号列表——由 Ralph 生成。
- 通过规划模式_创建_
- 在构建模式期间_更新_(标记完成,添加发现,记录 bug)
- 可以_重新生成_——Geoff:“我已经多次删除 TODO 列表”→ 切换到规划模式
- 自我纠正——构建模式甚至可以在缺失时创建新规格
循环是有意的:通过迭代实现最终一致性。
没有预先指定的模板——让 Ralph/LLM 决定和管理最适合它的格式。
specs/*
每个关注点一个 markdown 文件。这些是应该构建什么的事实来源。
- 在需求阶段创建(人类 + LLM 对话)
- 被规划和构建模式使用
- 如果发现不一致可以更新(很少,使用子代理)
没有预先指定的模板——让 Ralph/LLM 决定和管理最适合它的格式。
src/ 和 src/lib/
应用源代码和共享工具/组件。
在 PROMPT.md 模板中引用以用于定位步骤。
增强方案?
我(Clayton)还在确定这些可能增强方案的价值/可行性,但机会听起来很有希望。
我还在确定这些的价值/可行性,但机会听起来很有希望:
- 使用 Claude 的 AskUserQuestionTool 进行规划 - 使用 Claude 的内置访谈工具系统地澄清 JTBD、边缘情况和规格的验收标准。
- 验收驱动的反压 - 在规划期间从验收标准派生测试需求。防止”作弊”——没有适当的测试通过就不能声称完成。
- 非确定性反压 - 使用 LLM 作为法官对主观任务(语气、美学、用户体验)进行测试。二进制通过/失败审查,迭代直到通过。
- Ralph 友好的工作分支 - 要求 Ralph 在运行时”过滤到功能 X”是不可靠的。相反,预先为每个分支创建范围计划。
- JTBD → 故事地图 → SLC 发布 - 推动”让 Ralph 做自己”的力量,将 JTBD 的受众和活动连接到简单/可爱/完整的发布。
使用 Claude 的 AskUserQuestionTool 进行规划
在阶段 1(定义需求)期间,使用 Claude 的内置 AskUserQuestionTool 通过结构化访谈系统地探索 JTBD、关注点、边缘情况和验收标准,然后再编写规格。
何时使用: 最小/模糊的初始需求,需要澄清约束,或存在多种有效方法。
调用: “使用 AskUserQuestion 采访我以了解 [JTBD/关注点/验收标准/…]”
Claude 会提出有针对性的问题以澄清需求并确保对齐,然后再生成 specs/*.md 文件。
流程:
- 从已知信息开始 →
- Claude 通过 AskUserQuestion 采访 →
- 迭代直到清晰 →
- Claude 编写带有验收标准的规格 →
- 继续规划/构建
不需要代码或提示更改——这只是使用现有 Claude Code 功能增强阶段 1。
灵感 - Thariq 的 X 帖子:
验收驱动的反压
Geoff 的 Ralph_隐含地_通过涌现迭代连接规格 → 实施 → 测试。这个增强将通过在规划期间派生测试需求使那个连接_明确化_,创建从”成功是什么样子”到”什么验证它”的直接线路。
这个增强将验收标准(在规格中)直接连接到测试需求(在实施计划中),通过以下方式提高反压质量:
- 防止”不作弊” - 没有从验收标准派生的所需测试就不能声称完成
- 启用 TDD 工作流 - 测试需求在实施开始前已知
- 改进收敛 - 清晰的完成信号(所需测试通过)vs 模糊(“好像完成了?”)
- 保持确定性 - 计划中的测试需求(已知状态)不是涌现的(概率性的)
与核心理念的兼容性
| 原则 | 保持? | 如何 |
|---|---|---|
| 单体操作 | ✓ 是 | 一个代理,一个任务,一次一个循环 |
| 反压至关重要 | ✓ 是 | 测试是机制,只是现在明确派生 |
| 上下文效率 | ✓ 是 | 规划一次决定测试 vs 构建重新发现 |
| 确定性设置 | ✓ 是 | 计划中的测试需求(已知状态)不是涌现的 |
| 让 Ralph 做自己 | ✓ 是 | Ralph 仍然确定优先级并选择实施方法 |
| 计划是可丢弃的 | ✓ 是 | 错误的测试需求?重新生成计划 |
| ”记录原因” | ✓ 是 | 测试意图在实施前记录在计划中 |
| 不作弊 | ✓ 是 | 所需测试防止占位符实施 |
规定性平衡
关键区别:
验收标准(在规格中)= 行为结果、可观察结果、成功是什么样子
- ✓ “从任何上传的图片中提取 5-10 种主色调”
- ✓ “在 <100ms 内处理 <5MB 的图片”
- ✓ “处理边缘情况:灰度、单色、透明背景”
测试需求(在实施计划中)= 从验收标准派生的验证点
- ✓ “所需测试:提取 5-10 种颜色、性能 <100ms、处理灰度边缘情况”
实施方法(由 Ralph 决定)= 关于如何实现它的技术决策
- ❌ “使用 K-means 聚类,3 次迭代和 LAB 颜色空间转换”
关键:指定要验证什么(结果),而不是如何实施(方法)
这保持了”让 Ralph 做自己”原则——Ralph 决定实施细节,同时有清晰的成功信号。
架构:三阶段连接
阶段 1:需求定义
specs/*.md + 验收标准
↓
阶段 2:规划(派生测试需求)
IMPLEMENTATION_PLAN.md + 所需测试
↓
阶段 3:构建(用测试实施)
实施 + 测试 → 反压
阶段 1:需求定义
在生成规格的人类 + LLM 对话期间:
- 讨论 JTBD 并拆解为关注点
- 根据需要使用子代理加载外部上下文
- 讨论并定义验收标准——什么可观察、可验证的结果表明成功
- 保持标准是行为的(结果),而不是实施的(如何构建它)
- LLM 编写规格,包括验收标准,以对规格最有意义的方式
- 验收标准成为在规划阶段派生测试需求的基础
阶段 2:规划模式增强
修改 PROMPT_plan.md 指令 1 以包含测试派生。在第一句话后添加:
对于计划中的每个任务,从规格中的验收标准派生所需测试——需要验证哪些特定结果(行为、性能、边缘情况)。测试验证什么有效,而不是如何实施。作为任务定义的一部分包含。
阶段 3:构建模式增强
修改 PROMPT_build.md 指令:
指令 1: 在”选择要处理的最重要项目”后添加:
任务包括所需测试——将测试实施为任务范围的一部分。
指令 2: 将”运行该代码单元的测试”替换为:
运行任务定义中指定的所有所需测试。在任务被视为完成之前,所有所需测试必须存在并通过。
添加新护栏(在 9 序列中):
999. 在提交之前,从验收标准派生的所需测试必须存在并通过。测试是实施范围的一部分,不是可选的。测试驱动开发方法:测试可以先写或与实施一起写。
非确定性反压
一些验收标准抗拒程序化验证:
- 创意质量 - 写作语气、叙事流程、参与度
- 美学判断 - 视觉和谐、设计平衡、品牌一致性
- 用户体验质量 - 直观导航、清晰的信息层次
- 内容适当性 - 上下文感知消息传递、受众适配
这些需要类似人类的判断,但在构建循环期间需要反压以满足验收标准。
解决方案: 添加 LLM 作为法官测试作为反压,二进制通过/失败。
LLM 审查是非确定性的(同一工件在不同运行中可能收到不同的判断)。这与 Ralph 理念一致:“在一个不确定的世界中确定性地糟糕。“循环通过迭代提供最终一致性——审查运行直到通过,接受自然方差。
需要创建什么(第一步)
在 src/lib/ 中创建两个文件:
src/lib/
llm-review.ts # 核心夹具——单一函数,简洁 API
llm-review.test.ts # 显示模式的参考示例(Ralph 从这些学习)
llm-review.ts - Ralph 发现的二进制通过/失败 API:
interface ReviewResult {
pass: boolean;
feedback?: string; // 仅在 pass=false 时存在
}
function createReview(config: {
criteria: string; // 要评估的内容(行为的、可观察的)
artifact: string; // 文本内容 OR 截图路径
intelligence?: "fast" | "smart"; // 可选,默认为 'fast'
}): Promise<ReviewResult>;
多模态支持: 两种智能级别都将使用多模态模型(文本 + 视觉)。工件类型检测是自动的:
- 文本评估:
artifact: "Your content here"→ 作为文本输入路由 - 视觉评估:
artifact: "./tmp/screenshot.png"→ 作为视觉输入路由(检测 .png、.jpg、.jpeg 扩展名)
智能级别(判断质量,而不是能力类型):
fast(默认):快速、经济高效的模型,用于直接评估- 示例:Gemini 3.0 Flash(多模态、快速、便宜)
smart:更高质量的模型,用于细致的美学/创意判断- 示例:GPT 5.1(多模态、更好的判断、更高成本)
夹具实现选择适当的模型。(示例是当前选项,不是要求。)
llm-review.test.ts - 向 Ralph 展示如何使用它(文本和视觉示例):
import { createReview } from "@/lib/llm-review";
// 示例 1:文本评估
test("欢迎消息语气", async () => {
const message = generateWelcomeMessage();
const result = await createReview({
criteria:
"消息使用适合设计专业人士的温暖、对话语气,同时清晰传达价值主张",
artifact: message, // 文本内容
});
expect(result.pass).toBe(true);
});
// 示例 2:视觉评估(截图路径)
test("仪表板视觉层次", async () => {
await page.screenshot({ path: "./tmp/dashboard.png" });
const result = await createReview({
criteria:
"布局展示清晰的视觉层次,有明显的主要操作",
artifact: "./tmp/dashboard.png", // 截图路径
});
expect(result.pass).toBe(true);
});
// 示例 3:用于复杂判断的智能级别
test("品牌视觉一致性", async () => {
await page.screenshot({ path: "./tmp/homepage.png" });
const result = await createReview({
criteria:
"视觉设计保持适合金融服务的专业品牌标识,同时避免企业呆板",
artifact: "./tmp/homepage.png",
intelligence: "smart", // 复杂的美学判断
});
expect(result.pass).toBe(true);
});
Ralph 从这些示例学习: 文本和截图都作为工件工作。根据需要评估的内容选择。夹具在内部处理其余部分。
未来可扩展性: 当前设计为简单起见使用单一 artifact: string。如果出现需要多个工件的清晰模式(之前/之后比较、项目间一致性、多视角评估),可以扩展到 artifact: string | string[]。复合截图或连接文本可以处理大多数多项目需求。
与 Ralph 工作流集成
规划阶段 - 更新 PROMPT_plan.md:
在之后:
...研究 @IMPLEMENTATION_PLAN.md 以确定研究的起点,并使用子代理保持其更新,标记已完成/未完成的项目。
插入这个:
从验收标准派生测试需求时,识别验证是否需要程序化验证(可测量、可检查)或类似人类的判断(感知质量、语气、美学)。两种类型都是同样有效的反压机制。对于抗拒程序化验证的主观标准,探索 src/lib 以获取非确定性评估模式。
构建阶段 - 更新 PROMPT_build.md:
添加新护栏(在 9 序列中):
9999. 创建测试以验证实施满足验收标准,并包括传统测试(行为、性能、正确性)和感知质量测试(对于主观标准,参阅 src/lib 模式)。
发现,不是文档: Ralph 在 src/lib 探索(阶段 0c)期间从 llm-review.test.ts 示例学习 LLM 审查模式。不需要 AGENTS.md 更新——代码示例就是文档。
与核心理念的兼容性
| 原则 | 保持? | 如何 |
|---|---|---|
| 反压至关重要 | ✓ 是 | 将反压扩展到非程序化验收 |
| 确定性设置 | ⚠️ 部分 | 计划中的标准(确定性),评估非确定性但通过迭代收敛。为了主观质量有意权衡。 |
| 上下文效率 | ✓ 是 | 夹具通过 src/lib 重用,小测试定义 |
| 让 Ralph 做自己 | ✓ 是 | Ralph 发现模式,选择何时使用,编写标准 |
| 计划是可丢弃的 | ✓ 是 | 审查需求是计划的一部分,如果错误重新生成 |
| 简单胜出 | ✓ 是 | 单一函数,二进制结果,无评分复杂性 |
| 为 Ralph 添加信号 | ✓ 是 | 轻量提示添加,从代码探索学习 |
Ralph 友好的工作分支
关键原则: Geoff 的 Ralph 从单一、可丢弃的计划工作,Ralph 在其中选择”最重要的”。要与 Ralph 一起使用分支同时保持这个模式,你必须在计划创建时确定范围,而不是在任务选择时。
为什么这很重要:
- ❌ 错误方法:创建完整计划,然后要求 Ralph 在运行时”过滤”任务 → 不可靠(70-80%),违反确定性
- ✓ 正确方法:预先为每个工作分支创建范围计划 → 确定性、简单、保持”计划是可丢弃的”
解决方案: 添加一个 plan-work 模式以在当前分支上创建工作范围的 IMPLEMENTATION_PLAN.md。用户创建工作分支,然后用工作重点的自然语言描述运行 plan-work。LLM 使用这个描述来确定计划范围。规划后,Ralph 从这个已经确定范围的计划构建,零语义过滤——只是像往常一样选择”最重要的”。
术语: “工作”有意广泛——它可以描述功能、关注点、重构工作、基础设施更改、bug 修复或任何相关更改的连贯主体。你传递给 plan-work 的工作描述是给 LLM 的自然语言——它可以是散文,不受 git 分支命名规则约束。
设计原则
- ✓ _每个 Ralph 会话在每个分支上_单体地_操作于一个工作主体
- ✓ 用户手动创建分支——完全控制命名约定和策略(例如 worktrees)
- ✓ 自然语言工作描述——传递散文给 LLM,不受 git 命名规则约束
- ✓ 在计划创建时确定范围(确定性)而不是任务选择(概率性)
- ✓ 每个分支一个计划——每个分支一个 IMPLEMENTATION_PLAN.md
- ✓ 计划保持可丢弃——当分支错误/过时时重新生成范围计划
- ✓ 循环会话内没有动态分支切换
- ✓ 保持简单和确定性
- ✓ 可选——主分支工作流仍然有效
- ✓ 构建时没有语义过滤——Ralph 只是选择”最重要的”
工作流
1. 完整规划(在主分支上)
./loop.sh plan
# 为整个项目生成完整的 IMPLEMENTATION_PLAN.md
2. 创建工作分支
用户执行:
git checkout -b ralph/user-auth-oauth
# 使用你喜欢的任何命名约定创建分支
# 建议:工作分支使用 ralph/* 前缀
3. 范围规划(在工作分支上)
./loop.sh plan-work "带有 OAuth 和会话管理的用户认证系统"
# 传递自然语言描述——LLM 使用这个来确定计划范围
# 创建仅包含此工作任务的重点 IMPLEMENTATION_PLAN.md
4. 从计划构建(在工作分支上)
./loop.sh
# Ralph 从范围计划构建(不需要过滤)
# 从已经确定范围的计划中选择最重要的任务
5. PR 创建(工作完成时)
用户执行:
gh pr create --base main --head ralph/user-auth-oauth --fill
工作范围循环脚本
扩展基础增强循环脚本以添加带有范围规划的工作分支支持:
#!/bin/bash
set -euo pipefail
# 用法:
# ./loop.sh [plan] [max_iterations] # 在当前分支上规划/构建
# ./loop.sh plan-work "work description" # 在当前分支上创建范围计划
# 示例:
# ./loop.sh # 构建模式,无限制
# ./loop.sh 20 # 构建模式,最多 20
# ./loop.sh plan 5 # 完整规划,最多 5
# ./loop.sh plan-work "user auth" # 范围规划
# 解析参数
MODE="build"
PROMPT_FILE="PROMPT_build.md"
if [ "$1" = "plan" ]; then
# 完整规划模式
MODE="plan"
PROMPT_FILE="PROMPT_plan.md"
MAX_ITERATIONS=${2:-0}
elif [ "$1" = "plan-work" ]; then
# 范围规划模式
if [ -z "$2" ]; then
echo "错误:plan-work 需要工作描述"
echo "用法:./loop.sh plan-work \"工作描述\""
exit 1
fi
MODE="plan-work"
WORK_DESCRIPTION="$2"
PROMPT_FILE="PROMPT_plan_work.md"
MAX_ITERATIONS=${3:-5} # 工作规划默认为 5
elif [[ "$1" =~ ^[0-9]+$ ]]; then
# 带最大迭代的构建模式
MAX_ITERATIONS=$1
else
# 构建模式,无限制
MAX_ITERATIONS=0
fi
ITERATION=0
CURRENT_BRANCH=$(git branch --show-current)
# 为 plan-work 模式验证分支
if [ "$MODE" = "plan-work" ]; then
if [ "$CURRENT_BRANCH" = "main" ] || [ "$CURRENT_BRANCH" = "master" ]; then
echo "错误:plan-work 应该在工作分支上运行,而不是 main/master"
echo "先创建工作分支:git checkout -b ralph/your-work"
exit 1
fi
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "模式: plan-work"
echo "分支: $CURRENT_BRANCH"
echo "工作: $WORK_DESCRIPTION"
echo "提示: $PROMPT_FILE"
echo "计划: 将创建范围 IMPLEMENTATION_PLAN.md"
[ "$MAX_ITERATIONS" -gt 0 ] && echo "最大: $MAX_ITERATIONS 次迭代"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
# 警告 IMPLEMENTATION_PLAN.md 的未提交更改
if [ -f "IMPLEMENTATION_PLAN.md" ] && ! git diff --quiet IMPLEMENTATION_PLAN.md 2>/dev/null; then
echo "警告:IMPLEMENTATION_PLAN.md 有将被覆盖的未提交更改"
read -p "继续?[y/N] " -n 1 -r
echo
[[ ! $REPLY =~ ^[Yy]$ ]] && exit 1
fi
# 导出工作描述给 PROMPT_plan_work.md
export WORK_SCOPE="$WORK_DESCRIPTION"
else
# 正常规划/构建模式
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "模式: $MODE"
echo "分支: $CURRENT_BRANCH"
echo "提示: $PROMPT_FILE"
echo "计划: IMPLEMENTATION_PLAN.md"
[ "$MAX_ITERATIONS" -gt 0 ] && echo "最大: $MAX_ITERATIONS 次迭代"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
fi
# 验证提示文件存在
if [ ! -f "$PROMPT_FILE" ]; then
echo "错误:$PROMPT_FILE 未找到"
exit 1
fi
# 主循环
while true; do
if [ "$MAX_ITERATIONS" -gt 0 ] && [ $ITERATION -ge "$MAX_ITERATIONS" ]; then
echo "已达到最大迭代次数:$MAX_ITERATIONS"
if [ "$MODE" = "plan-work" ]; then
echo ""
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "已创建范围计划:$WORK_DESCRIPTION"
echo "要构建,运行:"
echo " ./loop.sh 20"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
fi
break
fi
# 使用选定的提示运行 Ralph 迭代
# -p:无头模式(非交互,从标准输入读取)
# --dangerously-skip-permissions:自动批准所有工具调用(放手干模式)
# --output-format=stream-json:用于日志/监控的结构化输出
# --model opus:主代理使用 Opus 进行复杂推理(任务选择、优先级排序)
# 如果计划清晰且任务定义明确,可以在构建模式中使用 'sonnet' 以提高速度
# --verbose:详细执行日志
# 对于 plan-work 模式,在管道传输之前替换提示中的 ${WORK_SCOPE}
if [ "$MODE" = "plan-work" ]; then
envsubst < "$PROMPT_FILE" | claude -p \
--dangerously-skip-permissions \
--output-format=stream-json \
--model opus \
--verbose
else
cat "$PROMPT_FILE" | claude -p \
--dangerously-skip-permissions \
--output-format=stream-json \
--model opus \
--verbose
fi
# 推送到当前分支
CURRENT_BRANCH=$(git branch --show-current)
git push origin "$CURRENT_BRANCH" || {
echo "推送失败。正在创建远程分支..."
git push -u origin "$CURRENT_BRANCH"
}
ITERATION=$((ITERATION + 1))
echo -e "\n\n======================== 循环 $ITERATION ========================\n"
done
PROMPT_plan_work.md 模板
注意: 与 PROMPT_plan.md 相同,但带有范围指令和 WORK_SCOPE 环境变量替换(由循环脚本自动执行)。
0a. 使用最多 250 个并行 Sonnet 子代理研究 `specs/*` 以了解应用规格。
0b. 研究 @IMPLEMENTATION_PLAN.md(如果存在)以了解到目前为止的计划。
0c. 使用最多 250 个并行 Sonnet 子代理研究 `src/lib/*` 以了解共享工具和组件。
0d. 作为参考,应用源代码在 `src/*` 中。
1. 你正在为工作创建一个范围实施计划:"${WORK_SCOPE}"。研究 @IMPLEMENTATION_PLAN.md(如果存在;可能不正确)并使用最多 500 个 Sonnet 子代理研究 `src/*` 中的现有源代码,并将其与 `specs/*` 进行比较。使用 Opus 子代理分析发现、确定任务优先级,并创建/更新 @IMPLEMENTATION_PLAN.md 作为按尚未实施项目的优先级排序的项目符号列表。Ultrathink。考虑搜索 TODO、最小实现、占位符、跳过/不稳定测试和不一致的模式。研究 @IMPLEMENTATION_PLAN.md 以确定研究的起点,并使用子代理保持其更新,标记已完成/未完成的项目。
重要:这仅针对"${WORK_SCOPE}"的范围规划。创建仅包含与此工作范围直接相关的任务的计划。保守——如果不确定任务是否属于此工作,排除它。如果太窄可以重新生成计划。仅规划。不要实施任何内容。不要假设功能缺失;先用代码搜索确认。将 `src/lib` 视为项目的共享工具和组件标准库。优先考虑那里的整合、惯用实现,而不是临时复制。
最终目标:我们要实现范围工作"${WORK_SCOPE}"。考虑与此工作相关的缺失元素并相应规划。如果元素缺失,先搜索确认它不存在,然后根据需要在 specs/FILENAME.md 编写规格。如果你创建了一个新元素,那么使用子代理在 @IMPLEMENTATION_PLAN.md 中记录实施它的计划。
与核心理念的兼容性
| 原则 | 保持? | 如何 |
|---|---|---|
| 单体操作 | ✓ 是 | Ralph 仍作为分支内的单个进程操作 |
| 每个循环一个任务 | ✓ 是 | 未更改 |
| 新鲜上下文 | ✓ 是 | 未更改 |
| 确定性 | ✓ 是 | 在计划创建时确定范围(确定性),而不是运行时(概率) |
| 简单 | ✓ 是 | 可选增强,主工作流仍然有效 |
| 计划驱动 | ✓ 是 | 每个分支一个 IMPLEMENTATION_PLAN.md |
| 单一事实来源 | ✓ 是 | 每个分支一个计划——范围计划替换分支上的完整计划 |
| 计划是可丢弃的 | ✓ 是 | 随时重新生成范围计划:./loop.sh plan-work "工作描述" |
| Markdown 优于 JSON | ✓ 是 | 仍然是 markdown 计划 |
| 让 Ralph 做自己 | ✓ 是 | Ralph 从已经确定范围的计划中选择”最重要的”——没有过滤 |
JTBD → 故事地图 → SLC 发布
关注点 → 活动
Geoff 的建议工作流已经将规划与 Jobs-to-Be-Done 对齐——将 JTBD 拆解为关注点,这些关注点反过来成为规格。我喜欢这个,而且我认为有机会通过将_关注点_重新定义为_活动_来进一步利用这种方法提供的产品优势。
活动是旅程中的动词(“上传照片”、“提取颜色”),而不是能力(“颜色提取系统”)。它们自然地由用户意图确定范围。
关注点:“颜色提取”、“布局引擎” → 能力导向 活动:“上传照片”、“看到提取的颜色”、“安排布局” → 旅程导向
活动 → 用户旅程
活动——及其组成步骤——自然地序列化为用户流程,创建一个_旅程结构_,使差距和依赖关系可见。一个_用户故事地图_将活动组织为列(旅程骨干),能力深度为行——可以构建的完整空间:
上传 → 提取 → 安排 → 分享
基础 自动 手动 导出
批量 调色板 模板 协作
批处理 AI 主题 自动布局 嵌入
用户旅程 → 发布切片
通过地图的水平切片成为候选发布。不是每个活动在每个发布中都需要新能力——一些单元格保持空白,如果切片仍然连贯那没关系:
上传 → 提取 → 安排 → 分享
发布 1: 基础 自动 导出
───────────────────────────────────────────────────
发布 2: 调色板 手动
───────────────────────────────────────────────────
发布 3: 批量 AI 主题 模板 嵌入
发布切片 → SLC 发布
故事地图给你切片的_结构_。Jason Cohen 的_简单、可爱、完整 (SLC)给你什么构成一个好切片的_标准:
- 简单——范围狭窄,你可以快速发布。不是每个活动,不是每个深度。
- 完整——在该范围内完全完成一项工作。不是一个破碎的预览。
- 可爱——人们真的想用它。在其边界内令人愉悦。
为什么 SLC 胜过 MVP? MVP 以牺牲客户为代价优化学习——“最小”通常意味着破碎或令人沮丧。SLC 翻转了这个:在交付真正价值的同时在市场中学习。如果成功,你有选择权。如果失败,你仍然善待了用户。
每个切片都可以成为具有清晰价值和标识的发布:
上传 → 提取 → 安排 → 分享
调色板选择器: 基础 自动 导出
───────────────────────────────────────────────────
情绪板: 调色板 手动
───────────────────────────────────────────────────
设计工作室: 批量 AI 主题 模板 嵌入
- 调色板选择器 ——上传、提取、导出。从第一天起即时价值。
- 情绪板 ——添加安排。创意表达进入旅程。
- 设计工作室 ——专业功能:批处理、AI 主题、可嵌入输出。
用 Ralph 实施
上面的概念——活动、故事地图、SLC 发布——是_思考工具_。我们如何将它们转化为 Ralph 的工作流?
默认 Ralph 方法:
- 定义需求:人类 + LLM 定义 JTBD 关注点 →
specs/*.md - 创建任务计划:LLM 分析所有规格 + 当前代码 →
IMPLEMENTATION_PLAN.md - 构建:Ralph 针对完整范围构建
这对于能力导向的工作(功能、重构、基础设施)效果很好。但它不会自然地产生有价值的(SLC)产品发布——它产生”规格描述的任何东西”。
活动 → SLC 发布方法:
为了获得 SLC 发布,我们需要将活动建立在受众上下文中。受众定义谁有 JTBD,这反过来告知什么活动重要以及”可爱”意味着什么。
受众(谁)
└── 有 JTBD(为什么)
└── 通过活动实现(如何)
工作流
I. 需求阶段(2 步):
仍然在与人类的 LLM 对话中执行,类似于默认的 Ralph 方法。
-
定义受众及其 JTBD ——我们为谁构建,他们想要什么结果?
- 人类 + LLM 讨论并确定受众及其 JTBD(他们想要的结果)
- 可能包含多个连接的受众(例如”设计师”创建,“客户”审查)
- 生成
AUDIENCE_JTBD.md
-
定义活动 ——用户做什么来完成他们的 JTBD?
- 由
AUDIENCE_JTBD.md告知 - 对于每个 JTBD,识别完成它所需的活动
- 对于每个活动,确定:
- 能力深度(基础 → 增强)——复杂程度
- 每个深度的期望结果——成功是什么样子?
- 生成
specs/*.md(每个活动一个)
活动内的离散步骤是隐式的,LLM 可以在规划期间推断它们。
- 由
II. 规划阶段:
在带有_更新的_规划提示的 Ralph 循环中执行。
- LLM 分析:
AUDIENCE_JTBD.md(谁,期望结果)specs/*(可以构建什么)- 当前代码状态(存在什么)
- LLM 确定下一个 SLC 切片(哪些活动,在什么能力深度)并规划该切片的任务
- LLM 生成
IMPLEMENTATION_PLAN.md - 人类验证 构建前的计划:
- 范围是否代表一个连贯的 SLC 发布?
- 正确的活动是否以正确的深度包含?
- 如果错误 → 重新运行规划循环以重新生成计划,可选更新输入或规划提示
- 如果正确 → 继续构建
III. 构建阶段:
在带有标准构建提示的 Ralph 循环中执行。
更新的规划提示
PROMPT_plan.md 的变体,添加受众上下文和 SLC 导向的切片推荐。
注意:
- 与默认模板不同,这没有
[项目特定目标]占位符——目标是隐式的:为受众推荐最有价值的下一个发布。 - 当前的子代理名称假设使用 Claude。
0a. 研究 @AUDIENCE_JTBD.md 以了解我们为谁构建以及他们的 Jobs to Be Done。
0b. 使用最多 250 个并行 Sonnet 子代理研究 `specs/*` 以学习 JTBD 活动。
0c. 研究 @IMPLEMENTATION_PLAN.md(如果存在)以了解到目前为止的计划。
0d. 使用最多 250 个并行 Sonnet 子代理研究 `src/lib/*` 以了解共享工具和组件。
0e. 作为参考,应用源代码在 `src/*` 中。
1. 将 `specs/*` 中的活动排序为 @AUDIENCE_JTBD.md 中受众的用户旅程地图。考虑活动如何相互流动以及存在什么依赖关系。
2. 确定下一个 SLC 发布。使用最多 500 个 Sonnet 子代理比较 `src/*` 与 `specs/*`。使用 Opus 子代理分析发现。Ultrathink。鉴于已经实施的内容,推荐哪些活动(在什么能力深度)形成最有价值的下一个发布。优先选择薄水平切片——仍然交付真正价值的最窄范围。一个好的切片是简单(狭窄、可实现)、可爱(人们想用它)和完整(完全完成一项有意义的工作,而不是破碎的预览)。
3. 使用 Opus 子代理(ultrathink)分析和综合发现、确定任务优先级,并创建/更新 @IMPLEMENTATION_PLAN.md 作为为推荐的 SLC 发布尚未实施的项目按优先级排序的项目符号列表。以推荐的 SLC 发布摘要开始计划(包含什么以及为什么),然后列出该范围的优先级任务。考虑 TODO、占位符、最小实现、跳过测试——但范围限于发布。将范围外的发现记录为未来工作。
重要:仅规划。不要实施任何内容。不要假设功能缺失;先用代码搜索确认。将 `src/lib` 视为项目的共享工具和组件标准库。优先考虑那里的整合、惯用实现,而不是临时复制。
最终目标:我们要为 @AUDIENCE_JTBD.md 中的受众实现最有价值的下一个发布。考虑缺失元素并相应规划。如果元素缺失,先搜索确认它不存在,然后根据需要在 specs/FILENAME.md 编写规格。如果你创建了一个新元素,那么使用子代理在 @IMPLEMENTATION_PLAN.md 中记录实施它的计划。
备注
为什么 AUDIENCE_JTBD.md 作为单独的工件:
- 单一事实来源——防止规格间漂移
- 启用整体推理:“这个受众最需要什么?”
- JTBD 与受众一起捕获(“为什么”与”谁”在一起)
- 被引用两次:在规格创建期间 AND SLC 规划期间
- 保持活动规格专注于什么,而不重复谁
基数:
- 一个受众 → 许多 JTBD(“设计师”有”捕捉空间”、“探索概念”、“向客户展示”)
- 一个 JTBD → 许多活动(“捕捉空间”包括上传、测量、房间检测)
- 一个活动 → 可以服务多个 JTBD(“上传照片”服务于”捕捉”和”收集灵感”)