Skip to content
Back to skills

Feature Build

ASecurity

Drives a feature's PLAN.md checklist to completion, task by task — a builder subagent implements, a reviewer subagent gates, commit only on pass. Owns BUILD-LOG.md in the feature's plan folder. Use once feature-plan has produced an ordered task list and it's time to actually write code.

  • 2 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 15, 2026
developmentgosqltestinggitapisecurity

Works with

  • claude code
  • cli
  • api

Security analysis

A100/100

Scanned October 15, 2026

npx -y skills add mattbrailsford/umbraco-devkit --skill feature-build --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Feature Build?

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

Security grade badge for Feature Build
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/mattbrailsford-feature-build/badge)](https://www.skillsdirectory.com/skills/mattbrailsford-feature-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: feature-build
description: >-
  Drives a feature's PLAN.md checklist to completion, task by task — a builder subagent
  implements, a reviewer subagent gates, commit only on pass. Owns BUILD-LOG.md in the
  feature's plan folder. Use once feature-plan has produced an ordered task list and it's time to
  actually write code.
user-invocable: true
argument-hint: [path to the feature's plan folder, optional]
---

# feature-build

> 🎯 **Design for change.** Each task's diff should be small, local, and behind a stable
> seam. The reviewer fails work that couples modules or bloats blast radius; the builder
> should pre-empt that.

Execute the task checklist in a feature's plan folder, one task at a time. You are the
orchestrator. You do **not** write or review feature code yourself. You dispatch to the
`builder` and `reviewer` subagents and gate on their verdicts.

**On the gate granularity:** review runs before every commit, not once at the end, so a bad
task is caught before it compounds into the next. This is the default, not optional. It
doesn't replace the whole-feature review (see "Finish"); the two catch different things.

## Scope

- IN: build each unchecked task, get it through review, commit it.
- OUT: planning, writing the task list, authoring specs — this **consumes** a plan, it
  doesn't author one.

## Preflight

1. Resolve the plan folder: the path given in the argument; else, if the current
   branch/worktree name matches a plan folder under the project's convention (see
   `CLAUDE.md`'s "Finding the current feature's plan folder" rule; the normal case when
   resuming), use that match; else **stop and ask**. Don't guess. Its name is the feature slug
   used below for the branch/worktree.
2. Read `PLAN.md`. It must be a checklist (`- [ ]` / `- [x]`). If it has no checkboxes, stop
   and send the user to `feature-plan`.
3. **Resuming or first run?** If any task in `PLAN.md` is already `- [x]`, or `BUILD-LOG.md`
   has entries, an earlier run already cut the branch/worktree: skip to step 5. Otherwise
   continue to step 4.
4. **Cut the feature's branch/worktree.** The one point in the pipeline that touches git
   before feature code exists (see `git-workflow`'s "Branch/worktree per feature" section).
   In order:
   1. Confirm the working tree is clean *except* for the plan folder and any new or refreshed
      mockup starters in `docs/mockups/starters/` (`feature-explore`/`feature-design`/`feature-plan` never
      commit them). Any *other* uncommitted change is unrelated work; stop and report.
   2. Confirm you're on the project's trunk branch (see `CLAUDE.md`'s Feature workflow
      section). If not, stop and ask. Don't guess which branch to fork from.
   3. **Ask the user to confirm before running any of this.** It commits to trunk, which the
      "always ask before touching main" rule covers however small the change.
   4. Commit the plan folder as-is, on trunk, with any changed project starters: `git add
      <plan-folder> docs/mockups/starters && git commit -m "docs: add plan folder for
      <feature-slug>"`.
   5. Create the branch/worktree named after `<feature-slug>`, off that commit. Prefer Claude
      Code's native worktree mechanism (`isolation: "worktree"` on the `Agent` tool, or the
      project's `WorktreeCreate` hook) so the project decides the real branch name and
      location; else fall back to `git checkout -b <feature-slug>` off trunk. Never invent a
      separate worktree/branch mechanism.
5. Before touching code, confirm `pwd` and the current branch match `<feature-slug>` (or
   whatever the project's hook named it).
6. **Check the demo/test site is worktree-safe, if one exists.** Check its `.csproj`
   references `Umbraco.Community.WorktreeDevPort`. Without it, the site runs on a fixed port
   (two worktrees smoke-testing at once collide, and it looks like a broken build) or on a
   random `:0` port nothing can find. If missing, **stop and flag it** and suggest re-running
   `project-init`; its "Demo site ports" step adds the package and fixes anything that finds the
   site by a hardcoded port. No demo/test site: this step is a no-op.

## The loop

For each task still unchecked (`- [ ]`) in `PLAN.md`, in order, top to bottom:

1. **Build.** If the task changes an existing screen, first screenshot it at 1440×900 as
   `screenshots/<screen>-before.png`. Once the builder starts, the old screen is gone, and the
   PR needs before and after.

   Then dispatch a `builder` subagent (Agent tool, `subagent_type: builder`, model
   sonnet). Give it: the exact task text, the relevant sections of `ARCHITECTURE.md` and
   `SPEC.md`, the path to any mockup for a screen the task touches, the files/extension points
   it owns, and an instruction to invoke the project's
   stack skills (`dotnet-best-practices`, `umbraco-extensibility`, `umbraco-package-
   conventions`, `ef-core-data`, `umbraco-backoffice-conventions`, etc. as relevant) and run
   the existing specs before reporting back. If the project has e2e tests and none covers the
   task's path, tell the builder to add one (the smoke step runs it). The builder does not
   commit.

2. **Review.** Dispatch a `reviewer` subagent (Agent tool, `subagent_type: reviewer`, model
   opus, must be ≥ builder). It invokes `security-dotnet`/`security-lit` (whichever the diff
   touches) and the relevant stack skills, reads the builder's diff, and returns `PASS` or
   `FAIL` with specific findings.

3. **Recurse.** If `FAIL`: send the findings to a fresh `builder` for the same task. Repeat
   build → review until `PASS`. No cap: a task isn't done until it passes code and security
   review. Nothing reaches git history before `PASS`. If a finding is a repeatable mistake a
   future `builder` would likely make on another task, write it to `.claude/memory/` (type:
   `gotcha`) once fixed.

4. **Smoke the real entry point.** Before commit, exercise the deployed artifact. Use the
   first of these the project has:
   - **An end-to-end (e2e) test suite.** Run the e2e test covering the task's path. If none
     covers it, the builder adds one as part of the task. A suite passing without touching
     the new code proves nothing.
   - **A demo site.** Start it and run through the change yourself: drive the backoffice UI
     (Playwright or equivalent), or send one real request through the Management API
     controller for a change with no screen.
   - **Neither**, because you're building the host itself (like Umbraco CMS), not a package
     installed into one: a thorough integration test that boots the real hosting/DI pipeline
     (not a unit test through an internal seam) is the equivalent gate.

   Fakes for external services are fine in all three; the request must travel through the
   real entry point, not an internal function that bypasses it. If the smoke fails, recurse
   to step 3 with a finding. A green unit test suite is not enough to ship.

   **If the task adds or changes a migration** and the project supports SQL Server, the smoke
   includes running it on a real SQL Server, as `ef-core-data` describes. Note in the task's
   `BUILD-LOG.md` entry which providers it actually ran on.

   **If the task renders a screen that has a mockup,** screenshot the built screen at 1440×900
   and compare it with `mockups/<screen>.png`. A difference in layout, components used, or
   what's shown (a missing or extra column, a box split or merged, a different chart type) is
   a smoke failure unless the builder's report flagged it as a deliberate departure. Small
   spacing and colour differences are not. Once the screen is complete, save its screenshot as
   `screenshots/<screen>.png` in the plan folder (this loop's folder; `mockups/` belongs to
   `feature-design`). Link it from the task's `BUILD-LOG.md` entry with the click path to reach it
   ("Settings › Webhooks › any webhook › Deliveries tab"), so `pr-describe` can tell
   reviewers where to find it.

5. **Commit.** On `PASS` + smoke green, have the builder commit *only this task's changes*
   with a message naming the task, following the project's commit conventions (see
   `git-workflow`). One commit per task.

6. **Check the box.** Edit `PLAN.md`: `- [ ]` → `- [x]` for the completed task, and add a
   one-line entry to `BUILD-LOG.md` (commit SHA, what was verified). Commit that change, plus
   any `screenshots/` this task saved, with the task commit or immediately after.
   `pr-describe` links screenshots by commit, so an uncommitted one is a broken image in the
   PR. If the builder's report named "any decision the plan left implicit that you had to
   make" (step 6 of its workflow), such as an assumption, spec deviation, or workaround,
   append a dated one-line entry to `DECISION-LOG.md` too. Otherwise it is lost when the task
   ends; `decision-review` depends on it being on disk.

7. Next task.

## Finish

When every box is checked: run the full test suite once more. If `BRIEF.md` has a `Repro`
section, run it through the real entry point, as step 4 does, and see it pass; a failure goes
to a fresh `builder` like a review finding. Then run the whole-feature review below, then
report a summary (tasks completed, commits, anything still red).

**Whole-feature review.** The per-task `reviewer` sees one task's diff, so it misses what
builds up across tasks: duplicated logic, a class that took on a second job, a component that
started calling a repository directly, drift from `ARCHITECTURE.md`. Dispatch one `reviewer`
subagent in whole-feature mode with the full branch diff (`git diff <base>...HEAD`),
`ARCHITECTURE.md` and `SPEC.md`.

- On `FAIL`, send the findings to a fresh `builder`, then review the whole branch again. Repeat
  until `PASS`. Commit each round as its own `refactor:` commit and add a `BUILD-LOG.md` line
  for it.
- If a finding means the design itself is wrong, not just the code, stop and hand off to
  `feature-design`.

A human still reviews the PR; this pass means they aren't the first to see cross-task
problems. Update the `BUILD-LOG.md` line in `README.md`: check its box and replace
`<pending>` with one plain-English line (task count, commit count). Never touch another
phase's line. If this feature is (or completes) a standalone package ready to publish, invoke
`umbraco-marketplace` before tagging a release; it's not part of this loop.

**Open the PR: invoke `pr-describe` directly (via the Skill tool). Don't write the body
yourself.** Claude Code's built-in `gh pr create --body "$(cat <<'EOF' ... EOF)"` recipe does
**not** apply here. Per `git-workflow`, the PR body is always `pr-describe`'s job, no
exceptions: never `--body` at all. `pr-describe` handles branch/push via `git-workflow` and
runs `decision-review`, so the assumptions, deviations, and workarounds in `DECISION-LOG.md`
reach a human in the PR. (`decision-review` is also user-invocable on its own, read-only, for
an earlier look.)

If this feature built inside a worktree, don't remove it here. That's post-merge cleanup (the
project's `WorktreeRemove` hook, or `git worktree remove`). Archiving the plan folder is
post-merge too: `feature-close`, once the PR is merged.

## Rules

- Sequential, dependency-ordered. This is a pipeline, not a parallel team.
- Builder owns code; reviewer owns the gate; this loop owns sequencing, `PLAN.md` checkbox
  state, `BUILD-LOG.md`, `screenshots/`, and its own line in `README.md`. Never collapse these roles.
- If a gate can't pass after repeated attempts and the builder is stuck, stop and report the
  task + findings rather than committing degraded code.

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.