mcpField
R
ralph-builder

ralph-builder

github.com/jimwellerAgent 工作流69 次安装
代码仓库

关于 ralph-builder

用于根据给定目标准备仓库,以运行 Ralph 循环的技能。它会创建 Beads 任务图、执行计划,以及供会话内和外部循环驱动使用的独立提示文件。

主要功能

  1. 01初始化 Beads 运行 Epic
  2. 02将目标拆分为依赖任务
  3. 03编写仓库专属执行计划
  4. 04为两种循环模式创建提示文件
  5. 05验证任务图和输出文件

适用场景

  1. 01根据项目目标准备自主执行任务
  2. 02按工作树组织并行 Ralph 运行
  3. 03为任务设置逐项验证指引

MCP 相关

此技能未描述 MCP 接口;它会为 Ralph 循环驱动准备 Beads 任务和提示文件。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/jimweller/clanker-skills --skill ralph-builder

安装后在 Claude Code 中输入/ralph-builder确认已加载。

详细介绍

STARTER_CHARACTER = 🔁

Ralph Builder

为当前仓库编写运行 ralph loop 所需的制品,使其能够自主运行。任务存储在 beads(bd)图数据库中。计划和两个提示词包装文件存放在 .llmtmp/ 中。

参数

用户会提供目标描述,其中可能会引用包含 PRD、计划或任务列表的文件。请从调用消息中提取目标。

输出制品

路径用途
.beads/Beads 数据库(任务状态的唯一来源)
.llmtmp/ralph-plan.md与模式无关的执行计划
.llmtmp/ralph-prompt-insession.md为会话内 ralph-loop 插件提供的斜杠命令包装文件
.llmtmp/ralph-prompt-external.mdscripts/ralph.sh 提供给 claude --print 的正文

每个提示词包装文件都包含特定模式的正文:会话内循环会持续运行,外部模式则在每项任务后停止。

流程

步骤 1:收集上下文

阅读仓库内容,为计划提供依据:

  1. 项目根目录中的 README.md
  2. .llmdocs/ 中的所有 .md 文件
  3. 用户目标参数中引用的任何文件

如果 .llmtmp/ 不存在,请创建它。

步骤 2:初始化 beads 并创建本次运行的 epic

同一仓库的各个工作树共享 bead 图。每次 ralph 运行都按独立的 epic 组织,这样不同工作树中的并发运行便可通过 --parent 筛选保持隔离。

if ! bd list >/dev/null 2>&1; then
  bd init --skip-agents
fi

slug=$(git branch --show-current | tr '/' '-')
epic=$(bd q "Ralph: ${slug}" -t epic -p 1 -l "ralph:${slug}")

--skip-agents 会禁止 bd 默认生成 AGENTS.md、修改 CLAUDE.md 以及注入 .claude/settings.json。项目现有的 Agent 指引和 beads 技能已提供 bd 工作流所需的上下文;bd 的项目级 Agent 文件是多余的,也与项目约定相冲突。

epic 带有标签 ralph:${slug},用作运行标识。步骤 3 创建的子项同时带有 --parent "${epic}" 和相同的标签,提供两种独立标识,以便审核者发现孤立项。

步骤 3:将目标转换为 bd 图

ralph 运行中的每项操作都是一个 bead。每个 bead 都有一个标题(祈使句式的单行描述)和一个说明(为该任务提供给执行者的完整指示)。生命周期脚手架(创建分支、BEGIN 标记、END 标记)以普通 bead 的形式编码,并且都以本次运行的 epic 为父项。

使用 bd create -t task --parent "${epic}" -l "ralph:${slug}" -q --json | jq -r .id 创建子 bead。记录每个 ID,以供后续调用 bd link。使用 bd update <id> -d "<text>"(或通过 heredoc 使用 --body-file - 写入多行内容)设置说明。使用 bd link <a> <b> 设置依赖关系(b 会阻塞 a)。每次运行都以分支任务和 BEGIN 标记任务开头;每次运行都以 END 标记任务结尾,并且该任务以传递方式依赖所有其他任务。

示例

下面的代码块展示了一次假设的运行:向 lib/greeting.go 添加三个问候函数,并更新 README。字面值(SLUG、文件路径、函数名、提交前缀)仅供说明;请替换为实际运行中的信息。Bead 描述只包含任务特定的信息。每个编码任务描述都采用下文定义的 RED/GREEN/VERIFY 结构。通用规则(约定式提交、角色约束)已写在 CLAUDE.md 中。整个运行通用的约定(构建、测试、lint 命令)写在 ralph-plan.md 中。描述中无需重复其中任何一项。

DATE=$(date +%Y%m%d)
SLUG=greeting   # derive from the goal; lowercase alphanumeric plus hyphen, max ~20 chars
HASH=$(openssl rand -hex 2 | head -c 3)
RUN="${DATE}-${SLUG}-${HASH}"
BRANCH="ralph/${RUN}"

# slug and epic are in scope from Step 2.

bdc() {
  bd create "$1" -t task -p 2 --parent "${epic}" -l "ralph:${slug}" -q --json | jq -r .id
}

T_BRANCH=$(bdc "Switch to branch ${BRANCH}")
bd update "$T_BRANCH" -d "Switch to branch ${BRANCH}, creating it if missing. Verify: git rev-parse --abbrev-ref HEAD prints ${BRANCH}."

T_BEGIN=$(bdc "Tag RALPH-${RUN}-BEGIN")
bd link "$T_BEGIN" "$T_BRANCH"
bd update "$T_BEGIN" -d "Run: git tag RALPH-${RUN}-BEGIN. Verify: git tag -l RALPH-${RUN}-BEGIN is non-empty."

T1=$(bdc "Add hello() to lib/greeting.go")
bd link "$T1" "$T_BEGIN"
bd update "$T1" --body-file - <<'DESC'
TDD workflow: write failing tests first, then implement minimum code to pass.

RED phase (write first):
Create lib/greeting_test.go. Test cases: hello() returns "world".

GREEN phase (then implement):
Create hello() in lib/greeting.go returning "world".

VERIFY: go test ./lib/... passes. Commit: feat(greeting): add hello
DESC

T2=$(bdc "Add goodbye() to lib/greeting.go")
bd link "$T2" "$T_BEGIN"
bd update "$T2" --body-file - <<'DESC'
TDD workflow: write failing tests first, then implement minimum code to pass.

RED phase (write first):
Add to lib/greeting_test.go. Test cases: goodbye() returns "bye".

GREEN phase (then implement):
Create goodbye() in lib/greeting.go returning "bye".

VERIFY: go test ./lib/... passes. Commit: feat(greeting): add goodbye
DESC

T3=$(bdc "Add greet(name) to lib/greeting.go")
bd link "$T3" "$T1"
bd link "$T3" "$T2"
bd update "$T3" --body-file - <<'DESC'
TDD workflow: write failing tests first, then implement minimum code to pass.

RED phase (write first):
Add to lib/greeting_test.go. Test cases: greet("Jim") returns
"world Jim bye".

GREEN phase (then implement):
Create greet(name) in lib/greeting.go composing hello() and goodbye().

VERIFY: go test ./lib/... passes. Commit: feat(greeting): add greet
DESC

T4=$(bdc "Document greetings API")
bd link "$T4" "$T3"
bd update "$T4" -d "Run the docs skill (/docs, \$docs) to document hello(), goodbye(), and greet() now exposed by lib/greeting.go. Commit: docs: document greetings API"

T_END=$(bdc "Tag RALPH-${RUN}-END")
bd link "$T_END" "$T4"
bd update "$T_END" -d "Run: git tag RALPH-${RUN}-END. Verify: git tag -l RALPH-${RUN}-END is non-empty."

3 个字符的哈希后缀可防止多个 ralph 运行共用同一日期和 slug 时出现分支和标签冲突。

编写完成后,断言不存在循环依赖、每个子项都有描述、至少有一个任务已就绪,并且父项集合与标签集合相等(不包括 epic):

bd dep cycles
bd list --parent "${epic}" --json | jq -e 'all(.[]; (.description // "") | length > 0)'
bd ready --parent "${epic}" --json | jq 'length'

parent_ids=$(bd list --parent "${epic}" --json | jq -r '.[].id' | sort)
label_ids=$(bd list --label "ralph:${slug}" --json | jq -r '.[] | select(.issue_type != "epic") | .id' | sort)
[[ "${parent_ids}" == "${label_ids}" ]] || { echo "parent/label set mismatch: orphans or misclassified beads"; exit 1; }

标题规则:

  • 使用祈使语气,限一行
  • 写明交付成果,而非操作流程
  • 不要创建“阅读代码库”或“理解架构”等元任务

描述规则:

  • 仅包含任务特定的信息:涉及的文件、行为、此任务的提交消息
  • 只有在验证命令与本次运行的标准测试命令不同时,才注明验证命令(通常是标签和分支任务)
  • 不要重复代码风格或角色规则;这些已写在 CLAUDE.md 中。不要重复整个运行通用的构建、测试或 lint 命令;这些已写在 ralph-plan.md 中
  • 每个编码任务描述都采用 RED/GREEN/VERIFY 结构:RED 阶段注明测试文件,并列出具体测试用例及预期行为。GREEN 阶段仅描述实现。VERIFY 阶段注明测试命令和约定式提交消息。生命周期、配置、SQL、shell、Helm 和文档 bead 不受此要求限制。
  • 切勿创建独立的“编写测试”“添加单元测试”或“集成检查点”bead。测试应通过 RED 阶段纳入各编码任务。不得创建仅用于测试的 bead,也不得延后创建测试套件 bead。

技能委派(强制):

工作技能
更新 README.md、CLAUDE.md 或 .llmdocs/ 中的任何文件docs(/docs、$docs)

这些类别的 bead 必须在描述中调用技能,而不是直接编写编辑内容。例如:Run the docs skill to document the new auth middleware,而不是 Edit .llmdocs/architecture.md to add an Authentication subsection。技能自带防护措施和并行处理能力;在任务描述中自行复现其工作会失去这两者。

第 4 步:编写 .llmtmp/ralph-plan.md

每次迭代都会在没有先前运行记忆的情况下读取此文件。所有命令、模式和约定都必须写在这里。内容详尽且针对仓库是正确的。

“Run Identity”部分记录第 2 步生成的字面值 ${slug} 和 ${epic},这样 Agent 每次迭代都能直接读取,而不必重新推导。

“Inputs”部分的 plan documents: 行记录规划器通过用户参数收到的源文档。审阅者会解析该行,并将所列路径作为权威意图来读取。这是一项原样传递:必须恰好列出用户参数中的文件,不多不少,也不得推断并添加其他文件。如果引用的路径不存在,应以明确的错误使构建失败,而不是将其删去。

必需部分:

# Ralph Plan

## Goal

<one paragraph>

## Approach

<strategy specific to this goal; include all relevant repo-specific detail directly>

## Inputs

plan documents: <comma-separated paths from the user's arguments, or empty if none>

## Run Identity

- Branch slug: `<slug from Step 2>`
- Epic ID: `<epic ID from Step 2>`
- Epic label: `ralph:<slug>`
- Driver: `scripts/ralph.sh .llmtmp/ralph-prompt-external.md`

## Conventions

<repo-specific patterns, tools, test commands, build commands, commit style>

## Git Workflow

All git operations execute as bd tasks per the per-task workflow. Branch creation, BEGIN tag, code commits, docs commits, and END tag are first-class beads in the graph, parented to the run epic. Never commit on `main`.

## Per-Task Workflow

Exactly ONE task per iteration. After step 5, follow the driver instruction. The driver controls whether the agent loops in-session or stops for a fresh context.

Each iteration:

1. Read the epic ID and slug from the "Run Identity" section above.
2. Run `bd ready --parent <epic-id> --json`. If the result is `[]`, run `bd close <epic-id> -m "ralph run complete"`, output `<promise>ALLDONE</promise>`, and stop.
3. Pick the first task. Run `bd show <id>` to read the title and description.
4. Execute the description exactly. The description names the files, commands, verification step, and commit message for this task.
5. Run `bd close <id>`. Follow the driver instruction below.

The sentinel `<promise>ALLDONE</promise>` is emitted only on the iteration where step 2 finds the ready queue empty (all children closed and the epic just closed).

## Driver Instruction




计划规则:

  • 指令必须基于实际的仓库结构和工具
  • 已知时,包含构建、测试和 lint 命令
  • 不要重复项目的 CLAUDE.md
  • 明确任务“完成”的标准(测试通过、lint 无误)
  • 仅陈述当前事实
  • plan documents: 必须恰好列出用户参数中引用的文件。不要添加 README.md、CLAUDE.md 或 .llmdocs/*(审阅者会独立读取这些文件作为基线)。不得从 .llmtmp/ 或其他位置推断相关文件。如果引用的路径不存在,应以明确的错误使构建失败,而不是将其删去。
步骤 5:编写提示词包装

每种模式都有自己的正文,因为驱动指令各不相同。

会话内正文(循环执行,不停止):

Read .llmtmp/ralph-plan.md and follow it. After closing each task, return to step 1 of the Per-Task Workflow to pick the next ready task. Do not stop between tasks.

外部正文(每次调用执行一个任务):

Read .llmtmp/ralph-plan.md and follow it. After closing each task, STOP. The driver spawns a fresh context for the next task.

.llmtmp/ralph-prompt-insession.md 是使用会话内正文的一行内容:

/ralph-loop:ralph-loop "<in-session body>" --max-iterations 100 --completion-promise ALLDONE

.llmtmp/ralph-prompt-external.md 仅包含外部正文,不含包装。

验证

完成前,请确认:

  • bd list >/dev/null 2>&1 以零退出码退出

  • bd dep cycles 以零退出码退出

  • 本次运行存在一个未关闭的 epic:bd list -t epic -l "ralph:${slug}" --json | jq -e 'length == 1'

  • bd ready --parent "${epic}" --json | jq 'length' 的结果大于零

  • epic 的每个子项都有非空描述:bd list --parent "${epic}" --json | jq -e 'all(.[]; (.description // "") | length > 0)'

  • 父项集合与标签集合相同(不包括 epic 本身):

    diff <(bd list --parent "${epic}" --json | jq -r '.[].id' | sort) \
         <(bd list --label "ralph:${slug}" --json | jq -r '.[] | select(.issue_type != "epic") | .id' | sort)
    
  • .llmtmp/ralph-plan.md、.llmtmp/ralph-prompt-insession.md、.llmtmp/ralph-prompt-external.md 均存在

  • 计划中的“Run Identity”部分记录了字面 slug 和 epic ID

  • 会话内提示词包含 "return to step 1" 和 "Do not stop between tasks"

  • 外部提示词包含 "STOP" 和 "fresh context"

如果任何断言失败,请修复并重新验证。

评论

支持 Markdown