Skip to content
Back to skills

R Build

ASecurity

Use when a plan exists and you want it built: dispatches the plan-execution orchestrator (engineer/QA/review gates) per phase at the right tier.

  • 20 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added November 7, 2026
developmentgoshellbashgit

Security analysis

A100/100

Scanned November 7, 2026

npx -y skills add rfxn/rdf --skill r-build --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of R Build?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for R Build
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/rfxn-r-build/badge)](https://www.skillsdirectory.com/skills/rfxn-r-build)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: r-build
description: >
  Use when a plan exists and you want it built: dispatches the plan-execution orchestrator (engineer/QA/review gates) per phase at the right tier.
---

You are the build command. You prepare context and dispatch the
dispatcher subagent to execute an implementation plan.

## Invocation

`/rdf:r-build [N | N-M | --parallel] [--worktree] [--max N] [--consistency-warn-only "<reason>"]`

Arguments:
  N            — single phase (existing behavior)
  N-M          — range of phases (e.g., 1-4) — dispatch in parallel
  --parallel   — auto-batch all pending phases by dependency graph
  --worktree   — force git worktree isolation (overrides auto-derivation)
  --max N      — maximum concurrent dispatchers (default: 4)
  --consistency-warn-only "<reason>" — downgrade a consistency-gate structural
               block to a warning; requires a stated reason (see Section 1)
  (no args)    — next pending phase, serial (existing behavior)

## Protocol

### 1. Locate and Validate the Active Plan

- Source `~/.rdf/state/rdf-bus.sh` and call `rdf_session_init`. If the helper
  is absent (helpers not yet bootstrapped — fresh plugin install before its
  first session restart), stop and tell the user: `/rdf:r-build` needs the
  `~/.rdf/state` helpers — restart your session so the RDF plugin can
  bootstrap them, or run `rdf deploy claude-code` from a checkout.
- `plan_path="$(rdf_active_plan_path)"` — resolves via three-tier
  fallback (session pointer → un-suffixed pointer → root PLAN.md).
- If `$plan_path` is empty, report error and stop:
  "No active plan found. Create one with /rdf:r-plan or write it manually,
   then run /rdf:r-plan --resume <path> to set the pointer."
- `tier="$(rdf_active_tier)"` — resolve the plan's task-class tier
  (`full` when no `**Tier:**` marker); carried into the Section 5
  dispatch payload so the dispatcher can cap gates.
- Read `$plan_path` as the plan input from here forward. Validate
  the plan against
  [reference/plan-schema.md](../reference/plan-schema.md). Apply
  Plan-Version Awareness first, then Rules 1-9 in order. On the first
  violation, print the rule number and the exact failure message from
  the schema doc, then stop without dispatching.

  Rule 9 (test-count self-consistency) is conditional — it fires only
  when a phase contains an explicit test-count assertion. Apply the same
  trigger check as `/rdf:r-plan` Step 2.7: scan each phase's `**Test**`
  field and step prose for an integer adjacent to a test noun; if found
  and not marked `TODO`, verify the declared count matches the `@test`
  references in the phase body. On mismatch, stop with the Rule 9
  failure message before dispatching.

  /rdf:r-plan Step 2.7 should have caught any schema violations before the
  plan was committed. If validation fails here, the plan was authored
  manually, edited after planning, or the pre-reviewer pass was skipped
  — either fix the plan and re-run /rdf:r-build, or re-run /rdf:r-plan to
  regenerate.

- **Consistency micro-gate (spec↔plan↔tasks).** After schema validation,
  run the deterministic cross-check:
  ```bash
  bash ~/.rdf/state/rdf-consistency.sh check "$plan_path"
  ```
  (If a source spec is known, pass it as the second argument for goal /
  edge-case coverage.) Exit 2 = structural break (File-Map/phase mismatch
  or phase-count mismatch) → print the findings and STOP without
  dispatching (fix via `/rdf:r-plan`). Exit 1 = advisory drift (uncovered
  goal/edge case, missing `**Goals:**` field, tier-size) → surface the
  findings and proceed. Exit 0 = clean. Spec Kit `/analyze` precedent;
  mechanical checks only.

  **Escape hatch.** For a rare legitimate structural false-positive (an
  intentional File-Map entry a reviewer approved), re-run with
  `~/.rdf/state/rdf-consistency.sh check --warn-only "$plan_path"` to downgrade
  the exit-2 block to an exit-1 warning. Using `--warn-only` REQUIRES the
  operator to state the reason in the `/rdf:r-build` invocation (e.g.
  `/rdf:r-build --consistency-warn-only "reason: File-Map intentionally lists
  the generated foo.sh"`) — exit-2-with-no-override is too brittle for
  real plans.

### 2. Identify Target Phase

- If `$ARGUMENTS` contains a number N: target Phase N
  - If Phase N does not exist in the active plan, report error and stop
  - If Phase N has `Status: complete`, warn and ask for confirmation
- If no argument: scan phases in order, target first with
  `Status: pending`
  - If all phases are complete, report "All phases complete. Use
    /rdf:r-ship for release workflow." and stop
  - If a phase has `Status: in-progress`, warn that a phase is
    already in progress and ask for confirmation before restarting it

### 2b. Identify Parallel Batch

If arguments contain a range (N-M) or --parallel:

1. Read Phase Dependencies from the active plan preamble
   - Parse structured list: `- Phase N: none` or `- Phase N: [deps]`
   - If no structured list found, fall back to serial with warning:
     "Phase Dependencies section not in structured format. Running
     serially. Use the format: `- Phase N: none` or `- Phase N: [1, 2]`"

2. Determine target phases:
   - Range (N-M): phases N through M inclusive
   - --parallel: all phases with Status: pending
   - If any phase has Status: in-progress, warn and ask:
     "Phase {N} is in-progress (may be from a prior session).
     Include in parallel batch? [Y/skip/abort]"

3. Compute parallel batches from dependency graph:
   - A phase is eligible for a batch when all its dependencies are
     complete (already done or in a prior batch)
   - Phases with `none` dependencies are eligible for the first batch
   - Group eligible phases into batches, respecting --max ceiling
   - Result: ordered list of batches, each batch is a set of
     independent phases

4. Validate file ownership within each batch:
   - For each batch: collect all files from all phases in the batch
   - Parse the **Files:** field from each phase: extract paths from
     lines matching `Create: \`path\``, `Modify: \`path\``, or
     `Delete: \`path\``. This is a best-effort heuristic — if paths
     cannot be extracted (free-form text), skip validation with
     warning: "Cannot parse file list for Phase {N}. Proceeding
     without file ownership validation."
   - If any file appears in more than one phase: split conflicting
     phases into separate batches, warn:
     "Phases {N} and {M} both modify {file}. Serializing."
   - Re-validate after splitting

5. Derive isolation level per batch:
   - For each phase in the batch, derive scope classification
     (same rules as dispatcher: file list + description + governance)
   - Batch isolation = highest scope in the batch:
     scope:multi-file or below → parallel-agent (file-gated)
     scope:cross-cutting or sensitive → parallel-worktree
   - If --worktree flag is set: force parallel-worktree regardless

6. Present dispatch plan to user:
   "Parallel dispatch plan:
    Batch 1 (parallel, {isolation}): Phases {list}
    Batch 2 (serial): Phase {N} (depends: batch 1)
    Batch 3 (parallel, {isolation}): Phases {list}
    Batch 4 (serial): Phase {N} (depends: all)

    {total phases} phases in {total batches} batches. Proceed? [Y/n]"

   Wait for user confirmation.

### 3. Create Task List

Read all phases from the active plan (`$plan_path`) and create a task for each one:

```
For each phase in the active plan, in phase order, one TaskCreate per message:
  TaskCreate:
    subject: "Phase {N}: {description}"
    activeForm: "Building Phase {N}: {short desc}"
Mark already-complete phases as completed immediately.
Mark target phase as in_progress before dispatching.
Mark target phase as completed when dispatcher returns PASS.
```

Issue each `TaskCreate` in its own message — see
[reference/progress-tracking.md](../reference/progress-tracking.md).
Do NOT batch phase TaskCreates in a single message: parallel
execution produces non-deterministic display order (e.g. Phase 1,
7, 6, 5, 3, 4, 2 instead of 1-7).

### 4. Load Governance Context

- Read `.rdf/governance/index.md`
  - If governance index does not exist, warn: "No governance found.
    Run /rdf:r-init to generate governance, or proceed without it."
- Load all governance files unconditionally:
  - conventions.md, constraints.md, verification.md,
    anti-patterns.md, architecture.md
- Read the current operational mode (if `.rdf/governance/index.md`
  has a Mode field other than "development")

### 5. Assemble Dispatch Payload

Build the dispatch prompt for the dispatcher subagent:

```
PHASE: <N>
DESCRIPTION: <phase description from the active plan>
MODE: <execution mode tag: serial-context | serial-agent | parallel-agent>
TIER: <rdf_active_tier — full|quick-plan|bugfix, read at Section 1>
FILES: <file list from the active plan>
ACCEPT: <acceptance criteria from the active plan>
PLAN_PHASE_COUNT: <total phases in the active plan>
PARALLEL_BATCH: <true if dispatched as part of parallel batch, false otherwise>

GOVERNANCE:
  index: .rdf/governance/index.md
  conventions: .rdf/governance/conventions.md
  constraints: .rdf/governance/constraints.md
  verification: .rdf/governance/verification.md
  anti-patterns: .rdf/governance/anti-patterns.md
  architecture: .rdf/governance/architecture.md

OPERATIONAL_MODE: <mode or "development">
PROJECT_ROOT: <absolute path to project root>
```

### 6. Dispatch Dispatcher Subagent

Dispatch the `rdf-dispatcher` subagent with the assembled payload.
The dispatcher handles all execution from here: TDD cycles, engineer
dispatches, quality gates, commit strategy.

### 6b. Dispatch Parallel Batch

Before any worktree creation, source `~/.rdf/state/rdf-bus.sh` and call
`rdf_session_init` to ensure `RDF_SESSION_ID` is set. Each Bash call is a
fresh shell, so every block below that uses `${RDF_SESSION_ID}` starts with
`source ~/.rdf/state/rdf-bus.sh && rdf_session_init` in the same call.
Worktree paths and branch names use the full session id for collision-free
identification across concurrent sessions on the same repository (a resumed
session can reuse its id — see session-safety.md).

For each batch in the dispatch plan (sequential between batches,
parallel within each batch):

**File-gated dispatch (parallel-agent):**
1. Create task per phase in the batch
2. Dispatch N rdf-dispatcher subagents simultaneously
   - Each gets the standard dispatch payload (Section 5) plus:
     PARALLEL_BATCH: true
   - Each operates on the shared working tree
   - File ownership enforced by the plan (validated in 2b.4)
3. Wait for all subagents in the batch to complete
4. Collect results: PASS or FAIL per phase

**Worktree dispatch (parallel-worktree):**
1. Create task per phase in the batch
2. For each phase, create a git worktree from the main worktree. The
   block refuses a submodule, a detached HEAD, and a plan the worktrees
   would not see as committed (they and the scope guard read the committed
   copy), and records the base branch in a file so step 5 never pastes a
   branch name into shell. A retry (Option 2) or a resume (Option 3) in the
   same session reuses the session id, so it first clears any leftover
   worktree and branch for this phase, keeping its result files and logging
   the branch tip so a failed attempt's commits stay recoverable
   (`git branch <name> <tip>`):
   ```
   source ~/.rdf/state/rdf-bus.sh && rdf_session_init
   [ -n "$RDF_SESSION_ID" ] || { echo "rdf: no session id; refusing worktree setup" >&2; exit 1; }
   root="$(cd "$(git rev-parse --git-common-dir)/.." && pwd)" || exit 1
   cd "$root" || exit 1
   inwt="$(git rev-parse --is-inside-work-tree 2>/dev/null)"  # false or fails in .git/modules, a bare repo, or a separate git dir
   [ "$inwt" = true ] && [ -z "$(git rev-parse --show-prefix)" ] \
     || { echo "rdf: $root is not a worktree toplevel (submodule, bare repo, or separate git dir); refusing worktree setup" >&2; exit 1; }
   base="$(git branch --show-current)"
   [ -n "$base" ] || { echo "rdf: HEAD is detached; check out the base branch first" >&2; exit 1; }
   plan="$(rdf_active_plan_path)" || { echo "rdf: no active plan" >&2; exit 1; }
   if [ -n "$(git status --porcelain -- "$plan" 2>/dev/null)" ]; then  # a plan outside the repo has no status
       echo "rdf: commit the plan first; phase worktrees read the committed copy" >&2; exit 1
   fi
   command mkdir -p "${root}/.rdf/work-output"
   printf '%s\n' "$base" > "${root}/.rdf/work-output/base-branch-${RDF_SESSION_ID}"
   wt="${root}/.worktrees/rdf-phase-{N}-${RDF_SESSION_ID}"; br="rdf/phase-{N}-${RDF_SESSION_ID}"
   if tip=$(git rev-parse --verify -q "refs/heads/$br"); then
       echo "removing leftover $br (tip $tip)"
       for f in "${wt}/.rdf/work-output/phase-{N}-"*"-${RDF_SESSION_ID}.md"; do
           [ -f "$f" ] && command cp -- "$f" "${root}/.rdf/work-output/"
       done
       git worktree remove --force "$wt" 2>/dev/null || true  # worktree may already be gone
       git branch -D "$br"
   fi
   git worktree add "$wt" -b "$br" HEAD
   ```
   (RDF_SESSION_ID is the full session id; prevents cross-session collisions)

   After the batch's `git worktree add` calls, activate the phase scope
   guard from the main worktree (idempotent; once per batch is enough):

   ```
   source ~/.rdf/state/rdf-bus.sh
   rdf_phase_hook_install "$(git rev-parse --show-toplevel)" \
     || echo "warn: phase scope guard (layer 1) not installed; post-merge scope check still applies" >&2
   ```

   The helper copies `~/.rdf/state/git-hooks/pre-commit` (falling back
   to `state/git-hooks/pre-commit` when nothing is deployed) into the repo's
   `rdf-hooks/` and adds an `includeIf "onbranch:rdf/phase-**"` include,
   so the hook runs on phase branches only and chains the project's own
   hooks; rc 2 means git < 2.23. The hook enforces phase scope
   (Files ∪ Tests-may-touch) at `git commit` time. See `plan-schema.md`
   Rule 8 and dispatcher.md "Worktree Pre-Commit Hook Installation".

3. Dispatch each phase's `rdf-dispatcher` from inside its worktree. A
   subagent starts in the controller's current directory, fixed at launch
   (a later `cd` does not move it), so `cd` there first — by absolute path,
   since a relative `.worktrees/…` does not resolve once the controller
   sits in another phase's worktree:
   ```
   source ~/.rdf/state/rdf-bus.sh && rdf_session_init
   root="$(cd "$(git rev-parse --git-common-dir)/.." && pwd)" || exit 1
   cd "${root}/.worktrees/rdf-phase-{N}-${RDF_SESSION_ID}" || exit 1
   [ "$(git branch --show-current)" = "rdf/phase-{N}-${RDF_SESSION_ID}" ] \
     || { echo "rdf: not on rdf/phase-{N}-${RDF_SESSION_ID}; refusing dispatch" >&2; exit 1; }
   ```
   then dispatch that phase, and repeat the `cd → dispatch` pair for the
   next one — parallelism comes from the dispatches running in the
   background, not from simultaneous `cd`s. The `cd` also closes the
   non-deterministic-CWD class (the SDK picks an adjacent repo when CWD has
   no `.git/`). After the last dispatch, return to the main worktree
   (`cd "$root"`, `root` derived as above): progress tracking and Section 7
   read `.rdf/work-output/` relative to it, and the running dispatchers
   keep their launch directories.
   - Each gets the standard dispatch payload plus:
     PARALLEL_BATCH: true
     PROJECT_ROOT: {worktree path}
     PROJECT_ROOT_MAIN: {main worktree toplevel}
   - Never add the Agent tool's `isolation: "worktree"` on top: the
     harness would make a second worktree from origin's default branch
     (not local HEAD) on a `worktree-agent-*` branch, so the phase builds
     on stale pushed code and commits outside the phase scope guard.
4. Wait for all subagents in the batch to complete
5. Merge completed phases in plan order (N ascending) from the main
   worktree — a controller left in a phase worktree would merge into that
   phase branch. Rebase inside the phase worktree: the branch is checked
   out there, so `git rebase <base> <branch>` from the main worktree fails.
   ```
   source ~/.rdf/state/rdf-bus.sh && rdf_session_init
   root="$(cd "$(git rev-parse --git-common-dir)/.." && pwd)" || exit 1
   cd "$root" || exit 1
   base="$(command cat "${root}/.rdf/work-output/base-branch-${RDF_SESSION_ID}")" || exit 1
   wt="${root}/.worktrees/rdf-phase-{N}-${RDF_SESSION_ID}"; br="rdf/phase-{N}-${RDF_SESSION_ID}"
   [ -n "$base" ] && [ "$(git branch --show-current)" = "$base" ] \
     || { echo "rdf: main worktree is not on the recorded base branch '$base'" >&2; exit 1; }
   st="$(git -C "$wt" status --porcelain)" || { echo "rdf: phase worktree $wt is missing or unreadable" >&2; exit 1; }
   if [ -n "$st" ]; then
       git -C "$wt" status --short >&2
       echo "rdf: $br has uncommitted changes in its worktree" >&2; exit 1
   fi
   n="$(git rev-list --count "refs/heads/${base}..refs/heads/${br}")" || exit 1
   [ "$n" -gt 0 ] || { echo "rdf: $br has no commits; the phase did not land on its branch" >&2; exit 1; }
   if ! git -C "$wt" rebase "refs/heads/${base}"; then
       git -C "$wt" rebase --abort 2>/dev/null || true  # nothing to abort if the rebase never started
       echo "rdf: rebase conflict on $br" >&2; exit 1
   fi
   git merge --ff-only "refs/heads/${br}"
   ```
   This produces a clean linear history — phase commits appear in
   plan order with no merge commit artifacts. A phase that returned PASS
   with no commits on its branch committed somewhere else: treat it as a
   FAIL, never as an empty phase. Any failure here stops the merge loop:
   report it and enter failure handling (Section 8)
6. Clean up each merged phase from the main worktree. The dispatcher's
   result files sit in the worktree's ignored `.rdf/`, which
   `git worktree remove` deletes without warning — copy them out first:
   ```
   source ~/.rdf/state/rdf-bus.sh && rdf_session_init
   root="$(cd "$(git rev-parse --git-common-dir)/.." && pwd)" || exit 1
   cd "$root" || exit 1
   wt="${root}/.worktrees/rdf-phase-{N}-${RDF_SESSION_ID}"; br="rdf/phase-{N}-${RDF_SESSION_ID}"
   command mkdir -p "${root}/.rdf/work-output"
   for f in "${wt}/.rdf/work-output/phase-{N}-"*"-${RDF_SESSION_ID}.md"; do
       [ -f "$f" ] && command cp -- "$f" "${root}/.rdf/work-output/"
   done
   git worktree remove "$wt" && git branch -d "$br"
   ```
   If `git worktree remove` refuses (modified or untracked files), show
   `git -C "$wt" status --short` and resolve before any `--force` —
   uncommitted work in a phase worktree is a FAIL signal, not debris.
7. Collect results: PASS or FAIL per phase

**Constraint:** Worktree dispatch MUST be invoked from a top-level
session, not from a subagent. Subagents inherit `RDF_SESSION_ID`
from their parent and would create colliding worktree paths.
The `PARALLEL_BATCH` downgrade in `dispatcher.md` ("Nested parallel
downgrade") already prevents nested parallel dispatch; this is its
worktree-specific explicit form.

**Post-batch quality gate (worktree dispatch only):**
After merging all worktrees in a batch, run a batch-level QA check:
- Dispatch rdf-qa subagent across the combined diff of all phases
  in the batch
- This catches semantic conflicts that file ownership validation
  cannot detect (e.g., two phases both adding the same function name
  to different files)
- If QA finds issues: enter failure handling (Section 8)

**Progress tracking:**
Write batch progress to `.rdf/work-output/build-progress-${RDF_SESSION_ID}.md`
(derived via `rdf_scoped_filename` from `~/.rdf/state/rdf-bus.sh`):
  DISPATCH_MODE: parallel
  TOTAL_PHASES: {N}
  TOTAL_BATCHES: {N}
  CURRENT_BATCH: {N}
  BATCH_PHASES: [list]
  COMPLETED_PHASES: [list]
  FAILED_PHASES: [list]

After each batch completes, update and proceed to the next batch.
After all batches complete, proceed to end-of-plan sentinel
(unchanged — runs on cumulative diff from phase 1 to HEAD).

### 7. Report Result

After the dispatcher returns:
- Read the dispatcher's status output from .rdf/work-output/
- Report phase result to the user: PASS (phase complete) or FAIL
  (with failure context and which gate failed)
- If PASS and more phases remain:
  > **Phase {N} complete** — {description}
  > Next: Phase {N+1} — {description}. Run `/rdf:r-build` to continue.
- If PASS and all phases are complete:
  - If PLAN_PHASE_COUNT >= 3: the dispatcher runs end-of-plan sentinel
    automatically (this is dispatcher-internal — the build command
    does not dispatch it separately)
    > **All {N} phases complete.** End-of-plan review: {verdict}.
    > Run `/rdf:r-ship` to begin the release workflow.
  - If PLAN_PHASE_COUNT < 3:
    > **All {N} phases complete.**
    > Run `/rdf:r-ship` to begin the release workflow.

### 8. Parallel Failure Handling

When one or more phases in a parallel batch fail:

1. Wait for all phases in the batch to complete (do not interrupt
   running phases on peer failure)

2. Classify each failure:
   - Gate 1 (engineer self-report) failure → recommendation: retry
   - Gate 2 (QA) failure → recommendation: retry
   - Gate 3 (sentinel) MUST-FIX → recommendation: retry
   - Gate 3 (sentinel) architectural concern → recommendation: pause
   - Merge conflict → recommendation: serialize conflicting phases
   - Dispatcher not in its phase worktree, or PASS with no commits on the
     phase branch → recommendation: pause (check where the controller was
     when it dispatched before retrying)
   - Uncommitted changes left in a phase worktree → recommendation: pause
     (inspect them there; discard and retry the phase rather than
     committing them — a commit made now skips the phase's gates)
   - Post-batch QA failure → recommendation: pause

3. Present to user with Recommendation:
   "Batch {N} results:
    [PASS] Phase 1: Replace dispatcher gate selection
    [FAIL] Phase 2: Update agent finding vocabularies (Gate 2: lint)
    [PASS] Phase 3: Simplify r-plan metadata
    [PASS] Phase 4: Simplify r-build dispatch payload

    Phase 2 failed at Gate 2 (QA lint error).
    **Recommendation: retry** — lint errors are typically fixable.

    Options:
    [1] Merge phases 1, 3, 4 now — retry phase 2 after merge
    [2] Retry phase 2 in isolation (attempt 2/3)
    [3] Pause — review failure before proceeding"

4. Execute user's choice:
   - Option 1: Merge successful phases in plan order, then dispatch
     phase 2 serially against new HEAD
   - Option 2: Re-dispatch phase 2's dispatcher subagent (same
     isolation level, max 3 total attempts); worktree dispatch clears the
     failed attempt's worktree and branch first (step 2)
   - Option 3: Write progress to
     `build-progress-${RDF_SESSION_ID}.md`, stop. User can resume
     with `/rdf:r-build --parallel` (which calls `rdf_session_init`
     and reads the scoped progress file); in the same session (or after
     `claude --resume <id>`) the id matches, and step 2 clears the paused
     phase's leftover worktree before re-dispatching it.

## Constraints

- Never execute plan phases directly — always dispatch to dispatcher
- Never modify the active plan — the dispatcher updates phase status
- If governance is missing, dispatch anyway (dispatcher degrades
  gracefully) but warn the user
- Respect the plan's execution mode tags — pass them through unchanged
- Parallel dispatch is additive — /rdf:r-build N (single phase) works unchanged
- Nested parallel downgrade: dispatchers in parallel batches receive PARALLEL_BATCH: true

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.