Agentic Skills

The Delivery Loop

The ds-build-item orchestrator and the branch/build/PR/review skills it composes to take one DevStride story — or a one-off ticket — from selection to shipped, merged code, plus the golden-dataset support skills that back it.

The Delivery Loop

The delivery loop is the set of /ds-* Claude Code skills that carry ONE DevStride story from "next unblocked item" to "merged and Done" — branching, building, self-reviewing, opening a PR, addressing findings, merging, and running the completion ritual, then looping to the next story. /ds-build-item is the orchestrator; /ds-branch-feature, /ds-ultracode-build, and /ds-pr are the skills it composes directly. Below /ds-pr sits a two-layer review stack — /ds-pr-review (the review + CI-gating policy) composing /ds-review (the review engine) — and /ds-push is the git utility nested deepest, called to land fixes. All of these are usable standalone too. Two more entry points feed the same loop: /ds-create-story and /ds-create-defect create a one-off item that isn't part of any plan and hand it to /ds-build-item's single-shot mode. /ds-branch-hotfix is the one skill on this page that truly sits alongside the loop rather than inside it — /ds-build-item never calls it. A short closing section covers the golden-dataset skills, which are supporting infrastructure a developer runs by hand — never part of the story loop itself.

/ds-build-item — the orchestrator

/ds-build-item <item|next> runs the whole loop: select → mark In Progress → branch → build → adversarial review → PR → merge → completion ritual → sync develop → next. It is the ORCHESTRATOR — it composes the other skills below by name and owns only the DevStride-specific glue (next-story selection, lane transitions, the completion ritual). It is explicitly designed to run under /loop for full autonomy.

The steps, in order:

  1. Select the story. Resolve a plan root (from $ARGUMENTS or prior /ds-plan/ds-build-item memory), then pick the highest-priority, not-Done, not-blocked_by-anything Story/Defect in the earliest-dated open Capability/Epic on the plan's critical path — the same canonical "next-unblocked" definition ds-insert-story, ds-insert-defect, and ds-comprehend-plan use. It re-fetches the item's full description and validates it against the actual codebase before treating anything in it as true, and reports the whole "ready-set" of unblocked candidates (not just the one it picked) so parallel waves stay visible even though execution itself is serial.
  2. Mark In Progress — a real update_item lane move on the live item.
  3. Branch — invokes /ds-branch-feature with a slug derived from the item number.
  4. Build — invokes /ds-ultracode-build, which owns the understand/build/adversarial-review engine (below).
  5. Open the PR — invokes /ds-pr in its autonomous, driven-by-ds-build-item mode. /ds-pr opens the PR (with the four-section description format) and then runs the review + CI-gating stack (/ds-pr-review/ds-review) below.
  6. Merge, with merge-gate recovery: rebase develop in before merging so conflicts surface where they're resolvable — pushing the rebased branch goes through /ds-push (force-with-lease), never a bare git push, since a real rebase rewrites SHAs and would otherwise be rejected as non-fast-forward. Watches actual CI check-run status (not just reviewer bots) with a non-blocking snapshot poll — reusing the same check /ds-pr step 4 already surfaced, not a blocking gh pr checks --watch, which would tie up the tool call for the full run (this repo's golden/full gates can run 20+ minutes). Retries flaky failures (bounded, ~2 attempts), fixes real failures in-loop, and merges only once CI is actually observed green — gh pr merge <n> --merge --delete-branch.
  7. Completion ritual — move the item to Done, set startDate/dueDate to the branch/PR window, confirm or manually create the PR↔item link, and — if the build materially diverged from the item's written spec — preserve the original description as a comment and rewrite the description to the as-built spec.
  8. Capture untracked findings (step 6.5) — any real, out-of-scope finding or newly discovered defect with no existing home gets spliced into the dependency graph via /ds-insert-defect or /ds-insert-story so a future loop iteration actually reaches it. See The Planning Loop for what those two skills do.
  9. Sync develop and proceedgit checkout develop && git pull --ff-only, assert a clean tree (the next /ds-branch-feature aborts on a dirty one), persist the resolved plan root, and loop back to step 1 for the next story.

Autonomy boundary

/ds-build-item runs the entire loop — select through next-story — without pausing between steps. It stops and asks a human ONLY at a genuine fork:

  • a story gated on a human decision or external infra that is the user's to do (AWS / DNS / SES / Stripe / secrets / account provisioning);
  • an ambiguous, risky, or unverifiable review finding;
  • a destructive or outward-facing action that needs confirmation.

Everything else proceeds on the loop's own judgment, with every deferral recorded explicitly (in the build plan, the PR body, and project memory) rather than silently dropped. This is exactly the contract /loop needs to drive /ds-build-item unattended.

If a resolved plan has zero not-Done, non-gated, unblocked candidates left, /ds-build-item exits cleanly and reports the terminal state (plan complete, blocked on open items, or gated on human/infra decisions) rather than looping back to re-ask.

Two ways in: the plan walk vs a one-off

/ds-build-item runs in one of two modes, and it auto-detects which from the item you hand it — no flag:

  • Plan-loop mode (the default, and what /loop /ds-build-item drives) — the item is part of a sequenced /ds-plan roadmap: it carries an execution-order [N] title prefix or is wired into the blocked_by/blocks graph. Here the full loop applies: select the next-unblocked item, walk the chain, splice discoveries back in (step 6.5), and loop to the next story.
  • One-off / single-shot mode — the item is a standalone inbound ticket or bug with no [N] prefix and no dependency edges (for example, one just created by /ds-create-story or /ds-create-defect). The inner build loop (steps 1–6: mark In Progress → branch off develop → build → PR → merge → completion ritual) runs verbatim — the whole point is that shipping is identical — but there is no plan-root resolution, no ready-set, no next-story selection, no [N] numbering, and no chain splice; it ships once to develop and terminates. Discoveries become their own one-off items rather than being spliced into a nonexistent chain.

The one-off entry points are /ds-create-story and /ds-create-defect: each creates the item (asking where in the map and which board, assigning it to the current user), then hands off to this single-shot mode. Use them for inbound work that isn't in a plan; use /ds-insert-story / /ds-insert-defect (see The Planning Loop) when the work genuinely belongs in a sequenced plan's chain.

Working base: develop, or an integration branch

By default every story branches off, PRs into, rebases onto, and syncs develop. For a large multi-story initiative, /ds-build-item supports an opt-in integration-branch mode: at kickoff (step 0, asked once per initiative — not per story) it establishes a session working base, which may be a long-lived integration branch instead of develop. In that mode each story merges into the integration branch, leaving the shared dev stage (auto-deployed from develop) untouched until a release point. The default the prompt offers comes from ds-config.json's integrationBranch (or the branch recorded in the plan-handoff memory), but the step-0 answer is authoritative for the run. Release points are owner-cut and never automated — merging integrationBranchdevelopmaster at stable milestones (e.g. an epic boundary) is surfaced to the user, never performed by the loop.

Branch creation: /ds-branch-feature vs /ds-branch-hotfix

/ds-branch-feature/ds-branch-hotfix
Branches offdevelop (freshly pulled)a fresh master, with the local DB reset from production
Naming<user-prefix>/<MM-DD-YY>/<branch-name><user-prefix>/hotfix/<MM-DD-YY>/<branch-name>
Called by /ds-build-item?Yes — step 2 invokes it directlyNo — standalone entry point only
PR targetdevelop (via /ds-pr)master — opened when ready via /ds-pr (which targets master for a hotfix branch); nothing to compare right after creation, so no PR is opened as part of the branch skill itself
Use whenBuilding/shipping a normal story through the delivery loopAn urgent fix that must branch from production code, not develop

/ds-branch-feature is the everyday branch-creation utility: it aborts on a dirty tree, syncs develop, creates and pushes the new branch. It's used both directly and as the building block /ds-build-item calls at step 2.

/ds-branch-hotfix is a heavier, standalone tool for genuine production emergencies. Its preflight is strict: SOURCE_DB_CONNECTION_STRING must be set (the DB reset fails partway without it, leaving the DB half-reset), the working tree must be clean, and it recommends stopping any running ds run backend first since resetting the DB underneath it can cause problems. The steps are git checkout mastergit pull → the destructive ds script reset-db (drops and reseeds the local DB from prod) → create the hotfix branch → ds migrations run → push. On any failure partway through, it does not strand the user on master — it reports exactly which step failed and asks how to proceed rather than guessing.

/ds-ultracode-build — the build engine

/ds-ultracode-build I<number> <one-line goal/scope> is the build engine /ds-build-item invokes internally once a branch exists and the item is already In Progress. It is not a standalone story-selection tool — it assumes the branch, the item state, and the scope are already given — and it does not open a PR or merge; it hands back to /ds-build-item. It runs three phases:

  1. UNDERSTAND — for a substantive story (touches multiple files, adds/changes a backend handler or route, crosses a module boundary, carries real correctness or security surface), this runs as an ultracode Workflow: parallel reader agents (design-doc, downstream-contract, libs/conventions, infra/seam, module-structure, test-plan) each return structured findings, synthesized into a concrete build plan and a buildable-now-vs-deferred scope line. For a genuinely trivial change (a one-line fix, a copy tweak, a config flip with no contract surface), this phase is skipped and the work happens inline — but the skill treats "unsure" as substantive, since an unnecessary Workflow is cheap next to a missed contract mismatch.
  2. BUILD — the main implementation loop: small increment → checks green → commit, repeated. Commits happen often (not one giant commit at the end), following Conventional Commits with an item tag, and every commit carries the required Co-Authored-By: and Claude-Session: trailers. Type-checks, the four pre-commit wiring checks, and the relevant tests must stay green — a red non-SDK check is a stop-and-fix, never a commit-anyway. Generated API artifacts (SDK/openapi/mcp gen output) are regenerated and committed separately from hand-written logic.
  3. ADVERSARIAL REVIEW — another ultracode Workflow, run against the hand-written diff only (generated files excluded). Stage A fans parallel finders across five angles — correctness, security, contract-match, tests/false-green, cleanup/conventions. Stage B runs per-finding verification, classifying each into CONFIRMED, PLAUSIBLE, or REFUTED. Only CONFIRMED and PLAUSIBLE findings get fixed (or explicitly deferred with a reason); REFUTED findings are dropped, never "fixed."

Findings and deferrals that are real but have no existing tracked item to absorb them are not left as prose — they're collected into an untracked-deferral list that /ds-build-item step 6.5 turns into real, dependency-spliced DevStride items via /ds-insert-defect / /ds-insert-story. This is the "mid-build escape hatch" for newly discovered work; see The Planning Loop for how those two skills splice an item into the graph.

/ds-ultracode-build hands back to /ds-build-item with: the item number, a one-line build summary, green-checks confirmation, the finalized scope/deferral line, the untracked-deferral list, and a deviations list — every material way the build diverged from the item's written spec. That deviations list is what /ds-build-item step 6 uses to reconcile the item's as-built description.

The review stack: /ds-pr/ds-pr-review/ds-review

Opening a PR and getting it through review is three skills, each owning one layer, so any of them is usable on its own:

  • /ds-pr — owns PR creation and linking. It opens the PR with a formal description, then delegates all review and CI gating to /ds-pr-review.
  • /ds-pr-review — the review + CI-gating policy for an existing PR: it enforces the adversarial-review standard and defers the long-running golden-build gate, delegating the actual review mechanics to /ds-review.
  • /ds-review — the review engine: launch every reviewer, verify and triage findings, apply fixes, reply-and-resolve threads, settle CI.

/ds-pr — PR creation and linking

/ds-pr [item-number] opens the pull request and then runs the review stack over it. It has two modes:

  • Standalone — a human runs /ds-pr [item-number] directly. It asks which base branch to target (develop for a feature branch, master for a hotfix), keeps every interactive ask-gate, and offers to link the PR to a DevStride item as its final step.
  • Autonomous, driven-by-ds-build-item — invoked as /ds-build-item step 4. The base branch is pre-answered (the session working base — develop or the initiative's integration branch), the review runs non-interactively, and the linking step is skipped entirely/ds-build-item owns PR-to-item linking in its own step 6, and linking in both places would double-own it. Even in autonomous mode it still pauses for a genuine fork (an ambiguous/risky/unverifiable finding, or a destructive/outward-facing action) — only "out of scope but real" findings are captured rather than asked about.

The formal PR description format. /ds-pr no longer relies on gh pr create --fill; it authors the body in a required four-section format, each a Markdown ## heading, in this order:

  1. Simple ELI5 Description — a plain-language, non-technical summary of what the change does and why.
  2. Technical Description — how it's implemented: the approach and the key commands/queries/services/components touched.
  3. Notable Changes to System Architecture or Behavior — anything that alters architecture, data flow, public contracts, migrations, permissions, or user-visible behavior (or an explicit "None").
  4. Testing Steps — concrete steps a reviewer can follow to exercise the change, plus which automated tests cover it.

There is no Co-Authored-By or AI-attribution text in the PR body — those trailers live on commits only. Once the body is written and the PR is open, /ds-pr hands the PR number to /ds-pr-review.

/ds-pr-review — review policy and CI gating

/ds-pr-review [PR#] runs an already-open PR through the full review-and-settle loop and CI gating. It composes /ds-review for the engine and adds two policies of its own:

  • Adversarial review is a first-class gate. It actively watches for the automated adversarial reviewers (Codex and Copilot) to post, and for every comment they leave it evaluates the point, implements the fix (or dismisses a refuted/out-of-scope one per triage), replies to the thread with the implemented solution, and only then marks that thread Resolved. Addressed comments are never left unresolved, and a comment is never resolved without a reply.
  • The golden-build gate is deferred until review comments are settled. The golden-build test suite is a very long-running CI gate (20+ minutes), and every fix pushed to address a comment invalidates a prior golden run — so /ds-pr-review does not wait on it until all Codex/Copilot comments are evaluated, addressed, replied-to, and Resolved. It then lets the gate run and waits only on the final run after the last review fix lands.

/ds-pr-review propagates its driven-vs-standalone mode down to /ds-review, and carries the untracked-deferral list back up to its caller.

/ds-review — the review engine

/ds-review [PR#] is the reusable engine every path above ultimately runs (and it's runnable standalone on any open PR). Its loop:

  1. Launch every review stream in parallel — the native /code-review high (a background workflow that returns findings as a task notification) AND each configured automated reviewer (@codex review as a PR comment for Codex; the requested_reviewers API for Copilot).
  2. Wait for all streams (interruptible), polling bots + CI — an interruptible background wait, not a blocking sleep; if a reviewer stays silent past review.pollTimeoutMinutes, proceed with the findings in hand rather than blocking the loop on one bot.
  3. Collect and de-duplicate findings across the native and automated reviewers into one list.
  4. Verify and triage each finding — reading the actual code before changing anything — into exactly one bucket:
    • REFUTED / incorrect → dismissed with a posted rationale — never silently ignored.
    • CONFIRMED / PLAUSIBLE and in-scope → fixed now, in this PR.
    • Real but out of scope → captured, not just asked about: added to the untracked-deferral list (driven) or offered via /ds-insert-defect / /ds-insert-story under a root the user names (standalone — it never guesses a plan root).
    • Genuinely ambiguous / risky / unverifiable → the one bucket that legitimately stalls an autonomous run — listed with a recommendation, and it stops to ask.
  5. Apply fixes and push with /ds-push (see below) — it never opens a second PR to land review fixes.
  6. Reply to AND resolve every addressed thread — a reply carrying the fix's commit ref or the dismissal rationale, then a GraphQL resolveReviewThread on the thread. It only resolves threads it actually addressed — never a blanket "clear the board."
  7. Settle CI to green — re-poll after pushing, distinguishing flaky/infra failures (re-run, bounded to ~2 tries) from real ones (fix in-loop).

Because it triages external, unauthenticated-relative-to-the-agent content — GitHub bot review comments and PR comments — and in driven mode acts on it with reduced oversight, /ds-review (and the whole stack above it) treats any embedded instruction inside a review comment (beyond a normal code-review suggestion) as untrusted data, not a legitimate instruction, and flags it to the user if it appears.

/ds-push — a smaller, direct utility

/ds-push is a small git-workflow utility, not part of the phased build/review engine: git add -u (already-tracked files only — it deliberately never sweeps in untracked files with git add .), show git status and a staged diff summary, commit with a message carrying the required Co-Authored-By:/Claude-Session: trailers — using the exact per-session values, never a stale example, and stopping to ask rather than guessing if those values aren't clearly available — run pnpm --dir backend run check:ts && pnpm --dir frontend run check:ts, then push (falling back to git push --force-with-lease — never a bare --force — on a non-fast-forward rejection). If the type-check fails with non-SDK errors, it does not push; it reports and asks. It explicitly does not open a pull request — it's the stage/typecheck/push building block /ds-review calls internally to land review fixes, and it's equally usable standalone whenever you want to push without opening a PR.

How it composes

/ds-build-item <item|next>
├─ 0. select story              (get_item, dependency graph, ready-set)
├─ 1. mark In Progress           (update_item — PRODUCTION write)
├─ 2. /ds-branch-feature I<####>-<slug>
├─ 3. /ds-ultracode-build I<####> <scope>
│     ├─ UNDERSTAND   (ultracode Workflow: parallel readers → build plan)
│     ├─ BUILD        (commit often, keep checks green)
│     └─ ADVERSARIAL REVIEW (Workflow: finders → per-finding verify → fix)
│           └─ compiles an untracked-deferral list for anything real
│              with no existing tracked home (not invoked here —
│              handed back to /ds-build-item, see step 6.5 below)
├─ 4. /ds-pr   (autonomous / driven-by-ds-build-item mode)
│     ├─ open PR with 4-section body (ELI5 / technical / notable changes / testing)
│     └─ /ds-pr-review   (review policy + CI gating)
│           ├─ adversarial gate: evaluate → fix → reply → RESOLVE each thread
│           ├─ defer golden-build gate until all comments settled
│           └─ /ds-review   (the engine)
│                 ├─ launch: local /code-review high + Codex + Copilot
│                 ├─ verify + triage: dismiss REFUTED / capture out-of-scope / ask on forks
│                 ├─ /ds-push  (commit + typecheck + push the fixes)
│                 └─ reply-and-resolve threads → settle CI green
├─ 5. merge          (rebase working base in, watch CI, retry flaky, fix real failures)
├─ 6. completion ritual (Done lane, dates, PR link, as-built spec reconciliation — PRODUCTION writes)
├─ 6.5 capture untracked findings → /ds-insert-story · /ds-insert-defect
└─ 7. sync working base → back to step 0 (next story, or exit on terminal condition)

/ds-branch-hotfix is deliberately absent from this diagram — it's a standalone entry point for production emergencies, not a step /ds-build-item ever calls. The one-off path (/ds-create-story / /ds-create-defect) enters this same diagram at step 1, running steps 1–6 once and then terminating instead of looping at step 7.

Repo configuration: .claude/ds-config.json

Every concrete value this page cites — the base branch (develop), the hotfix/production branch (master), the type-check commands (pnpm --dir backend run check:ts …), the local review command (/code-review high), and the automated reviewers (Codex via @codex review, Copilot via the requested_reviewers API) — is not hard-coded inside the skills. It lives in one checked-in file, .claude/ds-config.json, that the delivery skills load and treat as authoritative: /ds-branch-feature, /ds-branch-hotfix, /ds-ultracode-build, /ds-pr, /ds-pr-review, /ds-review, /ds-push, and /ds-build-item's own git glue each substitute the file's values wherever a step names a concrete branch, command, path, or reviewer. If the file disagrees with a literal shown in the skill, the file wins; if it's absent, the skills fall back to the inline default and say so.

What lives there: baseBranch / hotfixBaseBranch / protectedBranches, the opt-in integrationBranch (the default working base for a multi-story initiative — see the working-base section above), branchNaming, the verify.* type-check/test/lint commands, the generated.* file paths + regen command + tolerated-error patterns, and the review.* block: review.localCommand, review.automatedReviewers, review.pollTimeoutMinutes, review.resolveAddressedThreads, and review.notifyWhenSettled. What deliberately does not: commit trailers (the Claude-Session URL is per-session, so they come from the session's Git policy, never a static file) and coding conventions (those stay in the repo's AGENTS.md).

The planning skills (/ds-plan, /ds-comprehend-plan, /ds-insert-story, /ds-insert-defect, /ds-rationalize-gantt) read nothing from this file — they self-resolve org-specific config through the DevStride MCP at runtime, so they're already portable. The practical payoff: porting the delivery loop to a different repo is drop in a ds-config.json with that repo's values, not edit six skills — a light skill edit is needed only where the repo's structure genuinely differs (for example, it isn't a backend/frontend pnpm split).

Golden dataset & local DB support skills

/ds-golden, /ds-golden-build, /ds-golden-push, and /ds-reset-db are supporting infrastructure a developer runs directly — none of them is invoked by /ds-build-item, and they are not steps in the delivery loop. They exist to keep your local database and stage data usable while you build. Each is a thin, judgment-adding layer over the underlying ds golden / ds script CLI; for what those CLI verbs actually do, see Golden Dataset.

  • /ds-golden [org] — checks dataset health and, if needed, restores it. It always starts read-only (ds golden status, which mutates nothing); if the dataset is unhealthy, it only proposes a fix (a re-import, a reanchor) for the user to confirm — it never auto-runs a mutating verb on its own judgment.
  • /ds-golden-build [representative|full] — the heavy, rare, hours-long content-authoring flow: rebuilds the dataset from the generator (backend/tests/golden/) and, once it passes the §16 pre-ship assertion gate (which stamps a marker the publish step refuses to proceed without), optionally publishes it to the canonical golden source DB. It does not touch any stage.
  • /ds-golden-push <stage> — deploys/refreshes the golden Acme dataset onto a named stage, choosing the safe verb for that target: additive ds golden import for a shared, populated stage like dev (app.devstride.dev), or a whole-DB push --force-full-reset only for a confirmed-disposable stage. It hard-refuses prod outright — the CLI's own stage guard blocks every mutating golden verb against api.devstride.com, and this skill won't attempt a workaround.
  • /ds-reset-db — resets the local database from production, then re-applies the current branch's migrations on top. Strict preflight: SOURCE_DB_CONNECTION_STRING must be set (the reset fails partway without it), the working tree should be clean, and it recommends stopping any running ds run backend first. If any step fails, it does not leave you stranded on master — it checks out your original branch to restore you before reporting what broke.

Per the golden dataset's own directive, any correction to golden data belongs in the generator, never in a direct database edit — a stage reset or reseed is expected to wipe hand-patched rows.

Next Steps

  • The Planning Loop/ds-plan, /ds-insert-story, /ds-insert-defect, and /ds-comprehend-plan: how work gets onto the dependency graph that /ds-build-item selects from
  • Skill Audit — the flat reference for every delivery skill's arguments and behavior
  • Golden Dataset — the ds golden CLI these skills wrap
  • Command Reference — the full ds CLI surface