跳转到正文
莫尔索随笔
返回

Ralph 操作手册:AI 自主编程的完整指南

预计 21 分钟

第一时间捕获有价值的信号

本文译自 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-diagram.png

三个阶段,两个提示,一个循环

这张图让我明白,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

规划模式循环生命周期:

  1. 子代理研究 specs/* 和现有的 /src
  2. 比较规格与代码(差距分析)
  3. 创建/更新 IMPLEMENTATION_PLAN.md 并列出优先级任务
  4. 不实施任何内容

构建模式循环生命周期:

  1. 定位 – 子代理研究 specs/*(需求)
  2. 阅读计划 – 研究 IMPLEMENTATION_PLAN.md
  3. 选择 – 选择最重要的任务
  4. 调查 – 子代理研究相关的 /src(“不要假设没实现”)
  5. 实施 – N 个子代理进行文件操作
  6. 验证 – 1 个子代理进行构建/测试(反压)
  7. 更新 IMPLEMENTATION_PLAN.md – 标记任务完成,记录发现/bug
  8. 更新 AGENTS.md – 如果有操作层面的经验
  9. 提交
  10. 循环结束 → 上下文清空 → 下一次迭代重新开始

概念

术语定义
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 可以发现的_任何东西_:

  • 提示护栏——明确的指示,如”不要假设没实现”
  • AGENTS.md——关于如何构建/测试的操作经验
  • 代码库中的工具——当你添加一个模式时,Ralph 会发现并遵循它
  • 其他可发现的、相关的输入……

记住,计划是可丢弃的:

  • 如果错了,扔掉它,重新开始
  • 重新生成的成本是一个规划循环;与 Ralph 绕圈子相比很便宜
  • 在这些情况下重新生成:
    • Ralph 偏离轨道(实施错误的东西,重复工作)
    • 计划感觉过时或与当前状态不匹配
    • 已完成项目的混乱太多
    • 你做了重大的规格更改
    • 你对实际完成的内容感到困惑

循环机制

外层循环控制

Geoff 最初的最简形式 loop.sh 脚本:

while :; do cat PROMPT.md | claude ; done

注意: 同样的方法可以用于其他 CLI;例如 ampcodexopencode 等。

什么控制任务继续?

继续机制非常简单:

  1. Bash 循环运行 → 将 PROMPT.md 喂给 claude
  2. PROMPT.md 指示 → “研究 IMPLEMENTATION_PLAN.md 并选择最重要的事情”
  3. 代理完成一个任务 → 更新磁盘上的 IMPLEMENTATION_PLAN.md,提交,退出
  4. Bash 循环立即重启 → 新鲜的上下文窗口
  5. 代理读取更新的计划 → 选择下一个最重要的事情

关键见解: 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 文件。

流程:

  1. 从已知信息开始 →
  2. Claude 通过 AskUserQuestion 采访
  3. 迭代直到清晰 →
  4. Claude 编写带有验收标准的规格 →
  5. 继续规划/构建

不需要代码或提示更改——这只是使用现有 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 方法:

  1. 定义需求:人类 + LLM 定义 JTBD 关注点 → specs/*.md
  2. 创建任务计划:LLM 分析所有规格 + 当前代码 → IMPLEMENTATION_PLAN.md
  3. 构建:Ralph 针对完整范围构建

这对于能力导向的工作(功能、重构、基础设施)效果很好。但它不会自然地产生有价值的(SLC)产品发布——它产生”规格描述的任何东西”。

活动 → SLC 发布方法:

为了获得 SLC 发布,我们需要将活动建立在受众上下文中。受众定义谁有 JTBD,这反过来告知什么活动重要以及”可爱”意味着什么。

受众(谁)
    └── 有 JTBD(为什么)
            └── 通过活动实现(如何)
工作流

I. 需求阶段(2 步):

仍然在与人类的 LLM 对话中执行,类似于默认的 Ralph 方法。

  1. 定义受众及其 JTBD ——我们为谁构建,他们想要什么结果?

    • 人类 + LLM 讨论并确定受众及其 JTBD(他们想要的结果)
    • 可能包含多个连接的受众(例如”设计师”创建,“客户”审查)
    • 生成 AUDIENCE_JTBD.md
  2. 定义活动 ——用户做什么来完成他们的 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(“上传照片”服务于”捕捉”和”收集灵感”)