|
| 1 | +--- |
| 2 | +slug: hydra-tutorial-2-drie-pipelines |
| 3 | +title: "Hydra leerlijn — Deel 2: De drie pipelines" |
| 4 | +contentType: tutorial |
| 5 | +authors: [conduction] |
| 6 | +date: 2026-05-12 |
| 7 | +summary: Build, code-review en security-review. Wie doet wat, in welke volgorde, en hoe een label-state-machine de hele rit aan elkaar plakt. Tweede van zes korte modules. |
| 8 | +tags: [Hydra, Pipelines, Personas, Intern, Tutorial series] |
| 9 | +apps: [] |
| 10 | +durationMinutes: 15 |
| 11 | +series: hydra-tutorial |
| 12 | +partNumber: 2 |
| 13 | +draft: true |
| 14 | +unlisted: true |
| 15 | +--- |
| 16 | + |
| 17 | +import {Outcomes, Outcome, Prerequisites, PrerequisiteItem, NextSteps, NextStep, HexCard} from '@conduction/docusaurus-preset/components'; |
| 18 | + |
| 19 | +:::warning Intern document — niet extern delen |
| 20 | +Deze leerlijn beschrijft IP van Conduction. Niet doorsturen, niet publiceren, niet citeren in publieke kanalen. |
| 21 | +::: |
| 22 | + |
| 23 | +In deel 1 zag je dat Hydra vier personas heeft. In dit deel kijken we naar de **pipeline**: hoe die personas na elkaar werken aan één issue, welke labels de overgangen markeren, en wanneer de pijplijn afslaat naar `needs-input`. Aan het eind weet je het label-state-machine van Hydra van buiten en kun je een issue terugleiden naar de juiste fase als hij ergens vastloopt. |
| 24 | + |
| 25 | +{/* truncate */} |
| 26 | + |
| 27 | +<Outcomes title="Wat je leert in dit deel"> |
| 28 | + <Outcome>De drie pipelines (build, code-review, security-review) en hoe ze sequentieel op elkaar overdragen.</Outcome> |
| 29 | + <Outcome>Het complete label-state-machine: <code>build:queued → ... → done / needs-input</code>.</Outcome> |
| 30 | + <Outcome>Wat de applier (Axel Pliér) doet, en waarom hij overgeslagen kan worden.</Outcome> |
| 31 | + <Outcome>Het verschil tussen <code>retry:queued</code> en <code>rebuild:queued</code>.</Outcome> |
| 32 | +</Outcomes> |
| 33 | + |
| 34 | +<Prerequisites title="Wat je nodig hebt"> |
| 35 | + <PrerequisiteItem> |
| 36 | + Deel 1 doorgenomen: <a href="/academy/hydra-tutorial-1-wat-is-hydra">Wat is Hydra?</a> |
| 37 | + </PrerequisiteItem> |
| 38 | + <PrerequisiteItem>Een idee van wat labels op een GitHub-issue zijn en hoe je die toevoegt.</PrerequisiteItem> |
| 39 | +</Prerequisites> |
| 40 | + |
| 41 | +## Drie pipelines, één pijplijn |
| 42 | + |
| 43 | +Hydra heeft technisch gezien drie pipelines: **build**, **code-review** en **security-review**. Maar in praktijk werken ze altijd in dezelfde volgorde, automatisch aangestuurd door labels. Onder de motorkap is dat één state-machine: |
| 44 | + |
| 45 | +``` |
| 46 | +ready-to-build (of <prefix>-ready-to-build op een dev-werkstation — zie deel 5) |
| 47 | + ↓ |
| 48 | +build:queued → build:running → build:pass |
| 49 | + ↓ |
| 50 | +code-review:queued → :running → :pass / :fail |
| 51 | + ↓ (altijd doorlopen — ook bij :fail) |
| 52 | +security-review:queued → :running → :pass / :fail |
| 53 | + ↓ |
| 54 | +beslissing: |
| 55 | + beide reviews :pass + 0 fixes → done (Axel overgeslagen) |
| 56 | + beide reviews :pass + ≥1 fix → applier:queued → :running → :pass / :fail |
| 57 | + één van beide reviews :fail → needs-input (Axel overgeslagen, mens beslist) |
| 58 | +``` |
| 59 | + |
| 60 | +De pijplijn heeft één belangrijke regel: **iedere uitkomst na review is terminaal**. Hydra fix-t niet automatisch in een loop. Slaagt het in één run, mooi. Slaagt het niet, dan komt het issue op `needs-input` en moet een mens beslissen wat de volgende stap is. Daarover meer in deel 6. |
| 61 | + |
| 62 | +## Pipeline 1: Build (Al Gorithm, Haiku) |
| 63 | + |
| 64 | +De builder krijgt de spec, een schone clone van de doel-repo, en een turn-budget. Geen review-history, geen feedback van eerdere runs. Hij implementeert de tasks uit `tasks.md`, draait de quality-suite, opent een draft-PR. |
| 65 | + |
| 66 | +Volgorde binnen de build-fase: |
| 67 | + |
| 68 | +1. **Implementatie** — leest `proposal.md`, `design.md`, `tasks.md`, schrijft code. |
| 69 | +2. **Quality checks** — PHPCS, PHPMD, Psalm, PHPStan, ESLint, Stylelint, `composer audit`, `npm audit`. |
| 70 | +3. **PHPUnit + Newman** — backend en API-tests. |
| 71 | +4. **Browser-tests** — Playwright MCP loopt door de UI heen. |
| 72 | +5. **`fix-quality` / `fix-browser`** — als checks rood worden, krijgt Al Gorithm één tot twee pogingen om mechanisch te repareren. Dit is een *pre-review* fixup, geen review-loop. |
| 73 | +6. **Verdict** — `build:pass` (PR is opengezet) of `build:fail` (kapotte build, `needs-input`). |
| 74 | + |
| 75 | +Belangrijk: Al Gorithm draait op **Haiku**. Reden uit deel 1: hij volgt patronen, hij oordeelt niet. Door hem op Haiku te zetten houden we Sonnet-budget vrij voor de reviewers. |
| 76 | + |
| 77 | +<HexCard title="Wat ziet de builder niet?"> |
| 78 | + Geen reviews, geen verdict-history, geen labels behalve het eigen <code>build:*</code>. Hij weet dus niet dat een eerdere reviewer iets afkeurde — die feedback bereikt hem alleen via een expliciete <code>retry:queued</code>-cyclus (zie onder). |
| 79 | +</HexCard> |
| 80 | + |
| 81 | +## Pipeline 2: Code review (Juan Claude van Damme, Sonnet) |
| 82 | + |
| 83 | +Zodra `build:pass` gezet wordt, queue-t de supervisor automatisch `code-review:queued`. Juan Claude pakt het op: |
| 84 | + |
| 85 | +1. Leest **alleen de PR-diff** (`HYDRA_REVIEW_SCOPE=diff`, ADR-020). Niet de spec, niet de hele repo. Zo blijft de scope behapbaar en wordt elke regel die hij commentaar geeft daadwerkelijk in deze PR aangeraakt. |
| 86 | +2. Loopt de ADR-bibliotheek en gate-skills langs (zie deel 3). |
| 87 | +3. Voor **mechanische, in-scope fouten** mag hij zelf fixen (ADR-021: bounded-fix scope). PHPCS-headers ontbreken? Hij voegt ze toe. Pijnlijke variabele-naam? Niet zijn pakkie-an. |
| 88 | +4. Voor elk gevonden probleem schrijft hij een inline-comment op de PR met prefix `[fixed:...]` of `[unfixed:...]`. |
| 89 | +5. Hij commit + pusht zijn fixes naar de feature branch en zet `code-review:pass` of `code-review:fail` op het issue. |
| 90 | + |
| 91 | +De verdict-JSON die hij schrijft (`reviews/1.json`) bevat `fixes_applied[]` en `unfixed[]` — dat is wat Axel Pliér later leest om zijn binaire beslissing te nemen. |
| 92 | + |
| 93 | +## Pipeline 3: Security review (Clyde Barcode, Sonnet) |
| 94 | + |
| 95 | +Direct na code-review (of die nu `:pass` of `:fail` was) queue-t de supervisor `security-review:queued`. Clyde Barcode loopt op de PR-staat ná Juan Claude's fixes: |
| 96 | + |
| 97 | +- Zelfde shape als code-review, plus **Semgrep** en patroon-matching op CWE-klassen (SQL-injectie, XSS, path-traversal, hardcoded secrets, …). |
| 98 | +- Mag ook bounded fixes pushen in PR-mode. |
| 99 | +- Schrijft `security-review:pass` of `security-review:fail`. |
| 100 | + |
| 101 | +Waarom sequentieel en niet parallel? Omdat Clyde reviewed wat Juan Claude heeft achtergelaten. Parallel zou betekenen dat Clyde naar pre-fix code kijkt — dan zou hij security-issues vinden die Juan Claude al weggepoetst had en moet je de verdicts gaan reconciliëren. Sequentieel is simpeler en duidelijker. |
| 102 | + |
| 103 | +## De applier: Axel Pliér's binaire gate |
| 104 | + |
| 105 | +Met beide reviews binnen heeft Hydra drie opties: |
| 106 | + |
| 107 | +1. **Beide reviews `:pass` én Juan en Clyde hebben samen 0 fixes gepusht.** |
| 108 | + Niets veranderd ná de oorspronkelijke build, dus geen nieuwe risico's. **Axel wordt overgeslagen.** Issue krijgt `done`. Bespaart tokens. |
| 109 | + |
| 110 | +2. **Beide reviews `:pass` én er is ≥ 1 fix gepusht.** |
| 111 | + De code is gewijzigd na de oorspronkelijke build. Voor we vertrouwen op de uiteindelijke staat draait de orchestrator opnieuw de mechanische gates (PHPCS, Psalm, PHPStan, ...). Slagen die, dan komt Axel Pliér aan zet. Hij leest: |
| 112 | + - de uiteindelijke diff, |
| 113 | + - de `fixes_applied[]` + `unfixed[]` uit beide reviews, |
| 114 | + - alle inline-comments op de PR. |
| 115 | + |
| 116 | + En geeft één binair antwoord: `{pass: true}` of `{pass: false, blocking: [...]}`. Hij heeft géén Write- of Edit-tools. Hij oordeelt, hij grijpt niet in. |
| 117 | + |
| 118 | +3. **Eén van beide reviews `:fail`.** |
| 119 | + De reviewers zijn de autoriteit. Axel wordt overgeslagen. Issue gaat naar `needs-input`. Een mens beslist of dit een `retry:queued` of `rebuild:queued` waard is (zie deel 6). |
| 120 | + |
| 121 | +## Labels: één bron van waarheid |
| 122 | + |
| 123 | +Hydra is **stateless**. Het hele state-machine staat op de issue-labels op GitHub. De supervisor (de daemon) leest om de zoveel seconden de labels en beslist wat te doen. Crasht een container, dan kijkt de supervisor opnieuw naar de labels en pakt op waar het ophield. |
| 124 | + |
| 125 | +Per stage zijn er vier mogelijke states: `:queued`, `:running`, `:pass`, `:fail`. Die staan **altijd op het issue, nooit op de PR.** Dat is een bewuste keuze: het issue is de eenheid van werk, de PR is een artefact van een buildcycle. |
| 126 | + |
| 127 | +Naast de stage-labels zijn er metadata-labels die ernaast bestaan: |
| 128 | + |
| 129 | +| Label | Betekenis | |
| 130 | +|---|---| |
| 131 | +| `openspec` | Issue volgt het OpenSpec-werkmodel | |
| 132 | +| `yolo` | Mag auto-mergen mits alle gates groen zijn — geen menselijke approve nodig | |
| 133 | +| `agent-maxed-out` | Persona heeft zijn turn-budget opgemaakt; output is mogelijk incompleet | |
| 134 | +| `needs-input` | Hydra heeft de pijplijn gestopt, mens is aan zet | |
| 135 | + |
| 136 | +## `retry:queued` versus `rebuild:queued` |
| 137 | + |
| 138 | +Twee menselijk-getriggerde herstel-labels die teruggrijpen in de pijplijn. Allebei **single-shot** (geen loop): |
| 139 | + |
| 140 | +- **`retry:queued`** — de bestaande PR blijft staan. Hydra bouwt een `feedback.md` met daarin de `unfixed[]`-bevindingen + applier-blockers, dispatcht Al Gorithm in `HYDRA_MODE=fix`, gescoped tot precies de geflagde bestanden. Goedkoop. Geschikt voor: "de reviewers hadden gelijk, builder moet alleen even bijschaven". |
| 141 | +- **`rebuild:queued`** — bestaande PR sluit, branch reset naar `development`, alle cycle-labels eraf, terug naar `build:queued`. Duur. Geschikt voor: "de aanpak van Al Gorithm klopte niet, we beginnen opnieuw met dezelfde spec". |
| 142 | + |
| 143 | +Stelregel: pak altijd het goedkoopste herstel eerst. Eerst `gh pr update-branch <N>` (development → PR mergen), dan `retry:queued`, dan pas `rebuild:queued`. Deel 6 gaat hier dieper op in. |
| 144 | + |
| 145 | +## Pluvo-vragen |
| 146 | + |
| 147 | +1. **In welke volgorde lopen de drie pipelines, en waarom is security-review sequentieel ná code-review en niet parallel?** |
| 148 | + *(Hint: denk aan wat Clyde Barcode leest — de pre- of de post-fix versie.)* |
| 149 | + |
| 150 | +2. **Wat is het verschil tussen <code>build:fail</code> en <code>code-review:fail</code> qua vervolgactie?** |
| 151 | + *(Hint: één leidt direct tot <code>needs-input</code>; bij de andere loopt de pijplijn nog door naar de volgende stage.)* |
| 152 | + |
| 153 | +3. **In welke situatie wordt Axel Pliér (de applier) overgeslagen, en waarom is dat een bewuste keuze?** |
| 154 | + *(Hint: er zijn twee scenario's — beide gaan over of er iets *veranderd* is na de oorspronkelijke build.)* |
| 155 | + |
| 156 | +4. **Wanneer kies je <code>retry:queued</code> en wanneer <code>rebuild:queued</code>?** |
| 157 | + *(Hint: de keuze hangt af van of de oorspronkelijke build-aanpak deugde of niet.)* |
| 158 | + |
| 159 | +<NextSteps title="Volgende stap" lede="Nu je het pipeline-skelet ziet, gaan we in deel 3 in op de quality gates — de mechanische scheidsrechters die alle drie de personas in toom houden."> |
| 160 | + <NextStep |
| 161 | + title="Deel 3 — Quality gates" |
| 162 | + href="/academy/hydra-tutorial-3-quality-gates" |
| 163 | + description="Wat zijn de gates? Waarom mechanisch en niet AI-geoordeeld? Wat doe je als een gate fout positief slaat?" |
| 164 | + /> |
| 165 | + <NextStep |
| 166 | + title="Vorige stap — Wat is Hydra?" |
| 167 | + href="/academy/hydra-tutorial-1-wat-is-hydra" |
| 168 | + description="Korte herhaling van het waarom en de vier personas." |
| 169 | + /> |
| 170 | + <NextStep |
| 171 | + title="De pipeline-architectuur in detail" |
| 172 | + href="https://github.com/ConductionNL/hydra/blob/main/docs/pipeline-overview.md" |
| 173 | + description="De volledige pipeline-overview-doc, met alle subtiliteiten over rate-limit fallback, sloten en cron-schedule." |
| 174 | + /> |
| 175 | +</NextSteps> |
| 176 | + |
| 177 | +--- |
| 178 | + |
| 179 | +*Intern document — niet extern delen.* |
0 commit comments