---
name: dev-build
description: Build features with TDD or implementation-first per requirement. Use with /dev-build or /dev-build [feature-name] after /dev-define.
disable-model-invocation: true
reads: [feature.requirements]
writes: [feature.requirements, feature.build, backlog.status]
metadata:
  author: mileszeilstra
  version: 1.6.1
  category: dev
---

# Build

**FASE 2** of the dev workflow: define -> **build** -> test

Auto-detects stack from CLAUDE.md, selects technique per requirement (TDD, Implementation First, or Implementation Only), builds sequentially.

**Trigger**: `/dev-build` or `/dev-build [feature-name]`

## Input

Reads `.project/features/{feature-name}/feature.json`: requirements (REQ-XXX), architecture, implementation order.

## Output

```
.project/features/{feature-name}/
└── feature.json    # Enriched with build, packages, tests.checklist sections
```

## Process

**Fase tracking** — eerste actie van de skill: roep `TodoWrite` aan met deze 8 items (status `pending`), daarna markeer per fase `in_progress` aan begin en `completed` aan einde. Bij context compaction blijft TodoWrite-state zichtbaar — geen risico op vergeten fases.

1. FASE 0: Context Loading
2. FASE 1: Technique Mapping
3. FASE 2: Execute Build
4. FASE 2b: Regression Gate
5. FASE 3A: Documentation
6. FASE 3B: Project Sync
7. FASE 3C: Wat hebben we gebouwd?
8. FASE 3D: Scoped Commit

### FASE 0: Context Loading

> **Todo**: roep `TodoWrite` aan met de 8 fase-items (zie boven). Markeer FASE 0 → `in_progress`.

**Capture git baseline** (eerste actie):

```bash
mkdir -p .project/session
# Cleanup stale session state from previous crashed runs (>1 dag oud)
find .project/session -maxdepth 1 \( -name "active-*.json" -o -name "pre-skill-*.txt" \) -mtime +1 -delete 2>/dev/null
git rev-parse HEAD > .project/session/pre-skill-sha.txt
```

**Detect stack:** lees CLAUDE.md `### Stack` sectie + `.claude/research/stack-baseline.md` (als beschikbaar). Fallback: `project.json.stack`.

**Project context** (skip als niet bestaat):

Lees `.project/project.json` en `.project/project-context.json`. Gebruik voor:

- Bestaande endpoints (voorkom dubbele routes)
- Bestaand DB schema (voorkom conflicten)
- Code patterns om te volgen
- Learnings uit eerdere features

**Learnings load** (via [shared/LEARNINGS-LOAD.md](../shared/LEARNINGS-LOAD.md)):

Configuratie:

```
scopes: [component]
pitfall-prefix: true
global-memory: true
current-feature: <feature-name>
```

Toon de geladen output. Pitfall-prefix sectie + component-scoped patterns geven context voor de build (geen constraint — bij twijfel ga uit van root cause, niet pattern-match).

Bewaar de geladen learnings voor FASE 1 (Technique Mapping).

**Load feature:**

If no feature name provided:

1. Parse `.project/backlog.html` (zie `shared/BACKLOG.md`). Filter `status === "DEFINED"` → suggest via **AskUserQuestion**
2. Fallback: list `.project/features/` met `feature.json`, let user select

Load `feature.json`. Extract: `requirements[]`, `buildSequence[]`, `files[]`, `testStrategy[]`, `architecture` (specifiek `registries[]` en `interfaces`). Als `clarifications[]` aanwezig: behandel als harde constraints tijdens implementatie (gray-area beslissingen van de user). Als `architecture.registries[]` aanwezig: gebruik als leidraad — nieuwe instances (endpoints, commands, entities) toevoegen aan het aangegeven registry-bestand, niet verspreiden over losse bestanden.

Niet gevonden → exit: "Run `/dev-define` eerst."

**Dependency check:**

Skip als geen `depends[]` of leeg.

1. Parse `.project/backlog.html`. Niet gevonden → skip.
2. Per dependency: status moet `"DONE"` zijn.
3. Blockers gevonden → **AskUserQuestion**:
   - "Stop — werk eerst {dep} af (Recommended)" / "Toch doorgaan"
   - Stop → exit. Doorgaan → continue.

**Workspace setup** (optioneel):

Alleen tonen als we NIET al in een worktree zitten:

1. Check: `git rev-parse --show-toplevel` vs eerste pad uit `git worktree list --porcelain`
   → Verschillend: al in worktree → skip
2. AskUserQuestion:
   ```yaml
   header: "Workspace"
   question: "Wil je in een worktree werken voor deze build?"
   options:
     - label: "Nee, huidige directory (Recommended)"
       description: "Werk op de huidige branch"
     - label: "Ja, worktree aanmaken"
       description: "Geïsoleerde workspace — ideaal bij parallel werken"
   multiSelect: false
   ```
3. Ja → `EnterWorktree(name: "{feature-name}")`

> **Branch-naming**: `EnterWorktree` maakt branch `worktree-{feature-name}` (NIET `{feature-name}`). Vervolgskills (`dev-verify`, `dev-debug`, `dev-refactor` single-mode) detecteren deze worktree automatisch via `shared/WORKTREE.md` en switchen erin. Voor merge/cleanup gebruik je `/core-merge` of handmatig `git worktree remove --force` + `git branch -D worktree-{feature-name}`.

**Tag backlog card als actief** (direct na feature laden):

Lees `.project/backlog.html` (als bestaat), zoek feature op naam → zet `"status": "DOING"`, verwijder `transition` (als aanwezig), `data.updated` naar nu (overgang DEFINED → DOING bij build-start). Schrijf terug via Edit.

**Signal active feature** (na backlog update):

```bash
echo '{"feature":"{feature-name}","skill":"build","startedAt":"{ISO timestamp}"}' > .project/session/active-{feature-name}.json
```

**Display** feature overview:

```
FEATURE: {feature-name}

REQUIREMENTS:
- REQ-001: {description}
  ...

IMPLEMENTATION ORDER:
(from buildSequence, sorted by step)
```

### FASE 1: Technique Mapping

> **Todo**: markeer FASE 0 → `completed`, FASE 1 → `in_progress`.

Assign per requirement:

- **TDD**: validation rules, business logic, calculations, complex conditions, testable math
- **Implementation First**: CRUD, middleware, config, wiring
- **Implementation Only**: pure styling/layout, visual/particle effects, static content, env config, prototype code — alleen wanneer automated tests geen waarde toevoegen. Verplichte reden: `visual-only`, `config-only`, of `prototype`

**Pitfall overlap check**: voor elke requirement, vergelijk met de pitfall-lijst uit FASE 0. Bij duidelijke thematische overlap (zelfde domein, zelfde type bug-risico) → log expliciet welke pitfall geraakt wordt en hoe deze build het voorkomt. Geen forcing — alleen markeren waar relevant.

Display technique map als tabel. Proceed automatically — do NOT confirm with the user.

### FASE 2: Execute Build

> **Todo**: markeer FASE 1 → `completed`, FASE 2 → `in_progress`.

For each buildSequence step:

**Parallel build check** (per step met >1 requirement):

1. Check file overlap: vergelijk `files[]` waar `requirements` arrays overlappen tussen REQs in deze step
2. **Geen overlap** → launch Agent per REQ (max 3 parallel). Elke agent krijgt: technique file content, relevante source files uit feature.json `files[]`, stack context (CLAUDE.md ### Stack), eerdere SYNC notes van deze build
3. **Wel overlap** → serieel bouwen (onderstaande stappen)
4. Parse agent resultaten via `BUILD_RESULT_START...BUILD_RESULT_END` markers, update feature.json per REQ

   ```
   BUILD_RESULT_START
   REQ: {id}
   Technique: {TDD | Implementation First | Implementation Only}
   Status: {GREEN | BLOCKED}
   Files modified: {lijst}
   Files created: {lijst}
   Test output: {PASS | FAIL met details}
   SYNC: {pattern/concept in file(s) — what, why, depends on}
   BUILD_RESULT_END
   ```

Bij steps met 1 requirement of bij overlap, voor elke requirement sequentieel:

1. Load technique: `Read(".claude/skills/dev-build/techniques/{technique}.md")`
2. **Read existing code**: lees alle bestanden uit feature.json `files[]` die `action: "modify"` hebben, plus 1 bestaand test bestand voor setup/teardown patronen (before/after hooks, DB lifecycle, import conventies).
3. Execute technique workflow
4. **Stack-aware enforcement**:
   - Strict types (TS: geen `any`; JS: validatie op boundaries)
   - Async error handling
   - Geen secrets in client code
   - **Code clarity**: descriptieve namen boven comments. Geen comments die herhalen wat de code al zegt. Wel comments voor: niet-obvioze "waarom" beslissingen, workarounds, en compatibility notes. Volg bestaande project comment-stijl.
   - **Code rules**: volg `shared/RULES.md` — Algemeen (R007-R008) + stack-specifieke secties. Bij twijfel: MUST_DO regels altijd, SHOULD_DO regels tenzij bewuste afwijking met reden.
5. **Update feature.json** na elke REQ: zet `requirements[].status` → `"built"` en voeg `technique` + `syncNote` toe. Bij Implementation Only: voeg ook `skipTestReason` toe (`visual-only`, `config-only`, of `prototype`). Dit bewaart voortgang bij context compaction.
6. Output per requirement:
   ```
   [REQ-XXX] {description}
   Technique: {TDD | Implementation First | Implementation Only}
   {technique-specific output}
   SYNC: {pattern/concept} in {file(s)} — {what, why, what depends on it}
   Progress: {done}/{total}
   ```

**Edge cases:**

- **Combined steps** (e.g. "REQ-002 + REQ-003"): build als één unit. Technique = die van het eerste REQ in de combinatie.
- **Already covered**: als een REQ al (deels) werkt door een eerder REQ → schrijf alleen tests, verify GREEN. Output: `RED: N/A (covered by REQ-XXX)`

**On blocker:** log in feature.json `build.blockers[]`, mark BLOCKED, ga door met andere requirements. Suggest `/thinking-decide` voor architecturele blockers.

**⚠️ Check TodoWrite — er zijn nog 6 fases open (2b → 3D). Ga door met FASE 2b: Regression Gate.**

### FASE 2b: Regression Gate

> **Todo**: markeer FASE 2 → `completed`, FASE 2b → `in_progress`.

Na succesvolle afronding van alle requirements, run de **volledige test suite** met timeout (hangende tests = FAIL). Inclusief acceptance tests uit eerdere `/dev-verify` runs (`test/acceptance/*.test.js`) — deze beschermen tegen spec-regressies.

```bash
timeout 300 {stack-aware test command} --test-timeout 30000
```

**PASS:** Alle tests slagen → door naar FASE 3A.

```
REGRESSION CHECK: {total}/{total} PASS — geen regressies
```

**FAIL:** Andere feature tests falen — dit is een gate.

```
REGRESSION CHECK: {passed}/{total} PASS
REGRESSIES GEVONDEN:
- {test_file}.{test_name}: {reason}

Bestanden overlap: {lijst van bestanden die zowel door deze feature
als de falende tests worden gerefereerd}
```

Bij regressie:

1. Analyseer of de huidige feature de regressie veroorzaakt (check gedeelde files/imports)
2. Als JA: fix de regressie voordat je doorgaat. Re-run full suite na fix.
3. Als NEE (pre-existing failure): waarschuw gebruiker, laat kiezen via AskUserQuestion:
   - "Fix eerst de regressie (Recommended)" — "Voorkomt dat de regressie doorschuift naar /dev-verify"
   - "Toch doorgaan" — "Regressie was er al voor deze build"
4. Max 2 fix-pogingen. Daarna: rapporteer als blocker en laat gebruiker beslissen.

**Skip:** Als er geen test bestanden bestaan, geen test runner geconfigureerd, of stack niet herkend.

```
REGRESSION CHECK: overgeslagen ({reden})
```

### FASE 3A: Documentation

> **Todo**: markeer FASE 2b → `completed`, FASE 3A → `in_progress`.

**Build summary** — display:

```
BUILD COMPLETE: {feature}
========================
Techniques: TDD ({n}), Implementation First ({n}), Implementation Only ({n})
Tests: {passed}/{total} PASS
Files created: {count}
```

### FASE 3B: Project Sync

> **Todo**: markeer FASE 3A → `completed`, FASE 3B → `in_progress`.

Volg `shared/SYNC.md` 3-File Sync Pattern. Skill-specifieke mutaties:

**feature.json**: `status → "DOING"`, `files[]` → merge met actuele bestanden. Add: `build {}` (started, completed, techniques, testsPass, testsTotal, decisions), `packages[]`, `tests.checklist[]`. Bestaande secties NIET overschrijven. Note: `requirements[]` is al enriched in FASE 2 stap 4.

**tests.checklist[]** — per requirement minimaal 1 test item:

```json
{
  "id": 1,
  "title": "beschrijving van wat te verifiëren",
  "requirementId": "REQ-XXX",
  "steps": ["stap 1", "stap 2"],
  "expected": "verwacht resultaat",
  "status": "pending"
}
```

Richtlijnen:

- UI features: steps als browser-interacties (navigeer, klik, vul in)
- API features: steps als HTTP-verzoeken met concrete endpoints en payloads
- Expected = observable resultaat (response body, status code, zichtbaar effect)
- Voeg GEEN "run npm test" items toe — unit tests zijn al gedekt door de build

**Backlog**: `data.updated` → nu. Status blijft `"DOING"`.

**Context**: update `context.structure` (overwrite), `context.routing` (overwrite), `context.patterns` (merge), `context.updated`. Skip als geen structurele impact.

**Architecture** (volg component-first model uit `shared/DASHBOARD.md`): update `architecture.components[]` — gebouwde componenten `status: "planned"` → `"done"`, vul `description` (korte functionele beschrijving, max 200 chars — wat doet dit component?), `src`, `test`, `connects_to` (typed edges `{ to, type }` uit werkelijke imports en runtime IO — `calls` voor function/HTTP calls, `reads`/`writes` voor DB of state IO, `depends_on` voor pure library/config dependencies), `endpoints` (bijv. `"POST /api/auth/login"`), `entities` (gebruikte model namen), `feature` (huidige feature naam). Nieuwe componenten die tijdens build zijn ontstaan: push met alle velden inclusief `feature`. Skip als geen structurele impact.

**Routes** (`architecture.routes[]`): bevestig routes die tijdens build daadwerkelijk geïmplementeerd zijn — controleer `auth` veld klopt met de werkelijke middleware/guard (`"public" | "user" | "admin"`), update `purpose` als de pagina nu beter beschreven kan worden. Nieuwe routes die tijdens build zijn ontstaan: push `{ path, purpose, auth, feature }`. Endpoints in `endpoints[]` met daadwerkelijke auth-check: migreer `auth: false` → `"public"` en `auth: true` → `"user"` (of `"admin"` bij role-check).

Learning extraction gebeurt in `/dev-verify` — dat is de natuurlijke plek (features zijn pas "geleerd" na test + fix). Hier alleen `build.decisions[]` in feature.json vastleggen, geen `learnings[]` append.

### FASE 3C: Wat hebben we gebouwd?

> **Todo**: markeer FASE 3B → `completed`, FASE 3C → `in_progress`.

**STOP — ga NIET door naar de commit zonder deze fase volledig af te ronden.**

Display een visuele separator:

```
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
WAT HEBBEN WE GEBOUWD?
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
```

**Stap 1 — Uitleg displayen (verplicht, niet overslaan)**

De gebruiker moet begrijpen hoe de feature werkt voor goede beslissingen in test- en refactor-fases. Display de volgende uitleg alsof je het aan een student uitlegt:

- **Wat doet het?**: 1-2 zinnen zoals je het aan een vriend zou uitleggen. Beschrijf wat de gebruiker ziet en kan doen — geen technische termen.
- **Voorbeeld**: 1 concreet scenario in 2-3 zinnen. UI feature: "Stel je voor: je klikt op X, vult Y in, ziet Z." Backend/API feature: "Er komt een verzoek binnen met X, het systeem doet Y, en stuurt Z terug."
- **Hoe werkt het?**: 1 ASCII diagram dat het hele verhaal vertelt. Gebruik blokjes en pijlen met korte labels. De gebruiker moet het diagram kunnen lezen zonder uitleg ernaast. Voorbeeld: `[Gebruiker klikt "Opslaan"] → [Formulier checkt invoer] → [Server slaat op] → [✓ Bevestiging]`

**Stap 2 — Begripscheck (verplicht, niet overslaan)**

**BELANGRIJK**: Display **minimaal 15 lege regels** (`\n`) na de uitleg, VÓÓR de AskUserQuestion. Dit is nodig zodat de modal-popup de uitleg niet overlapt en de gebruiker alle tekst kan lezen.

**AskUserQuestion** na de witruimte:

Vraag: "Snap je hoe de feature werkt?"
Opties: "Ja, helder" / "Leg het uitgebreider uit" / "Ik heb een vraag"

Follow-up loop tot "Ja, helder". Sla uitleg op als `build.explanation` in feature.json (targeted Edit).

### FASE 3D: Scoped Commit

> **Todo**: markeer FASE 3C → `completed`, FASE 3D → `in_progress`.

**Strategie**: stage alleen files die door deze build zijn aangemaakt of gewijzigd. Laat pre-existing dirty files met rust.

```bash
git status --porcelain
```

Categoriseer elke file:

1. **Check baseline**: vergelijk met de SHA uit `.project/session/pre-skill-sha.txt`:
   ```bash
   git diff --name-only $(cat .project/session/pre-skill-sha.txt) HEAD 2>/dev/null
   ```
   Als diff leeg is (geen mid-build commits): gebruik `git diff --name-only $(cat .project/session/pre-skill-sha.txt)` (zonder HEAD) voor unstaged changes, plus `git ls-files --others --exclude-standard` voor nieuwe bestanden.
   Bestanden die NIET door deze build zijn gewijzigd EN al dirty waren → PRE-EXISTING, niet stagen.
2. **Nieuwe/gewijzigde bestanden van deze feature** (bestanden uit `feature.json files[]`, test files, feature.json zelf) → `git add`.
3. **Untracked bestanden** die niet bij de feature horen → niet stagen.
4. **.project/ bestanden** (project.json, backlog.html, project-context.json) → probeer toe te voegen. Als skip-worktree of sparse-checkout dit blokkeert: accepteer en ga door (deze bestanden zijn lokaal bijgewerkt maar worden niet gecommit).

```bash
git commit -m "build({feature}): {n} requirements ({tdd} TDD, {impl} impl-first)"
```

Clean up: `rm -f .project/session/pre-skill-sha.txt .project/session/active-{feature-name}.json`

**Output:**

```
BUILD COMPLETE: {feature}
========================
Techniques: TDD ({n}), Implementation First ({n}), Implementation Only ({n})
Tests: {passed}/{total} PASS
Files created: {count}

Next steps:
  1. /dev-verify {feature} → hybrid test verificatie
  2. /dev-debug → als er onverwachte failures zijn
```

**Worktree reminder** — voeg één extra blok toe aan de output als de huidige branch matcht `worktree-*` pattern (`git branch --show-current`):

```
💡 Worktree actief: {worktree_path}
   Volgende skills (/dev-verify, /dev-refactor, /dev-debug) starten in een NIEUWE chat —
   ze detecteren deze worktree automatisch en switchen erin.
   Voor merge/cleanup: /core-merge {feature}
```

> **Todo**: markeer FASE 3D → `completed`. Alle 8 fases moeten nu `completed` zijn.

## Test Output Parsing

Condense test output:

**PASS:** `TESTS: {n}/{n} PASS ({time})`

**FAIL:**

```
TESTS: {passed}/{total} PASS ({time})
FAILED:
- {file}:{line} - {reason <50 chars}
```
