A Vipe Coding POC – Prompt 4 – Review + Spec-Abgleich

Prompt 4 — Review & Spec-Abgleich

Und täglich grüßt das Murmeltier. Prompt 4 ist wieder einer dieser Schritte, bei denen Codex zum Gärtner wird —
oder anders gesagt: Ich lasse ein LLM den eigenen Code überprüfen.
Du kennst den Spruch: den Bock zum Gärtner machen.
Genau so fühlt es sich an.

Der Auftrag war klar: „Prüfe alles gegen SPEC.md, liste Abweichungen auf, korrigiere sie.“
Tabellen, Constraints, Entities, Repositories — alles einmal durch den Filter.

Exkurs: Warum LLMs schlechte Tester sind

Bevor wir weitermachen, ein kurzer, aber notwendiger Exkurs.
Denn wenn man ein LLM seinen eigenen Code prüfen lässt, muss man verstehen, warum das grundsätzlich problematisch ist.

  1. Bestätigungsfehler (Confirmation Bias)
    Das LLM wurde mit denselben Annahmen gefüttert, die auch zur Codegenerierung geführt haben.
    Es hält den Code daher eher für korrekt, weil es seine eigenen Muster wiedererkennt.
  2. Mangel an echten Testfällen
    LLMs denken nicht wie menschliche Tester.
    Sie erzeugen Happy‑Path‑Tests, keine Grenzfälle, keine bösartigen Eingaben.
  3. Übersehen subtiler Logikfehler
    Race Conditions, Nebenwirkungen, Speicherlecks — alles Dinge, die ein LLM nicht „fühlen“ kann, weil es den Code nicht ausführt.
  4. Halluzination von Test-Erwartungen
    Wenn die Spezifikation unklar ist, erfindet das LLM Annahmen.
    Die Tests prüfen dann die falsche Realität.
  5. Unfähigkeit, Sicherheitslücken zu erkennen
    Sicherheitsdenken ist bösartig.
    LLMs sind höflich.
    Das passt nicht zusammen.
  6. Fehlende Domänenexpertise
    Fachlogik kann ein LLM nicht wirklich beurteilen — es kennt nur Muster, keine echten Regeln.
  7. Keine echte Abdeckungsmessung
    LLMs wissen nicht, welche Codepfade ungetestet bleiben.
    Sie raten.
  8. Verstärkung von Fehlern durch Iteration
    Wenn das LLM auf Basis seiner eigenen Tests Code verbessert, verstärkt es oft die eigenen Missverständnisse.

Fazit:
LLMs sind nützlich — aber nur als Werkzeug, nicht als Prüfinstanz.
Sie liefern eine Basis, aber die Verantwortung bleibt beim Menschen.

Zurück zum Prompt. Codex startet den Review: Tabellen prüfen, Constraints vergleichen, Entities abgleichen, Repositories durchgehen.
Und diesmal findet die Maschine tatsächlich echte Abweichungen.

Die wichtigste: organization_role fehlte komplett, obwohl sie im SPEC als MVP‑Tabelle definiert ist.
Codex ergänzt die Migration und zieht die Domain‑Struktur nach.

In employee gab es zusätzliche Annahmen — ein extra Unique auf internal_number, Default‑Werte, die nicht im SPEC stehen.
Alles wurde zurückgebaut auf den normativen Stand.

Auch audit_log war zu „fleißig“: zusätzliche Indexe, Defaults, die nicht vorgesehen waren.
Jetzt ist es wieder SPEC‑rein.

Die XOR‑Constraint in employee_skill bleibt korrekt: entweder skill_id oder custom_label.

Domain-Layer

  • EmployeeSkill nutzt jetzt ein eigenes Value Object EmployeeSkillId.
  • Für organization_role wurden Entity, Id‑VO und Repository‑Interface ergänzt.
  • RepositoryDb‑Implementierungen wurden erweitert, konsistent zur bestehenden Struktur.

Alles wurde committed (Commit: 56422db) und der PR aktualisiert.

Testing

PHP Syntax: alle Migrations- und Domain-Dateien fehlerfrei.
Docker: weiterhin nicht testbar in dieser Umgebung.

Damit ist Prompt 4 abgeschlossen.
Ein weiterer Schritt, der zeigt: LLMs können Code schreiben — aber sie brauchen jemanden, der ihnen sagt, wann sie danebenliegen.

 

A Vipe Coding POC – Prompt 3 – Migrations & Domain-Layer

Prompt 3 — Migrations & Domain-Layer

Prompt 3 ist der Moment, in dem das Projekt zum ersten Mal nach „echtem Backend“ aussieht.
Bis hierhin war alles Struktur, Setup, Routing, Docker.
Jetzt kommen Tabellen, Entities, Repositories – das Grundgerüst der eigentlichen Anwendung.

Der Prompt selbst war klar definiert:
Migrations für alle MVP-Tabellen erstellen und einen minimalen Domain-Layer anlegen.
Keine Business-Logik, keine Services, keine Use-Cases.
Nur Konstruktoren, Getter und die Interfaces, die später alles zusammenhalten.

Nach dem obligatorischen „Ja, ich habe SPEC.md vollständig gelesen und verstanden“ legt Codex los.
Und diesmal merkt man, dass die Maschine richtig arbeitet: prüfen, planen, abgleichen, korrigieren.
Ein technischer, fast schon chirurgischer Ablauf. (ich brauche eine andere Metapher, vielleicht choreografierte Routine?)

Zuerst die Migrations. Sechs Stück, wie in der SPEC gefordert:
employee, skill, employee_skill, evidence, consent, audit_log.
Alle mit UUIDs, Timestamps, Constraints.
Sogar der XOR-Check für employee_skill (entweder skill_id oder custom_label) ist drin.

Dann der Domain-Layer: Entities für Employee, Skill, EmployeeSkill, Evidence, Consent, AuditLog.
Minimalistisch, wie gefordert: Konstruktoren, Getter, keine Logik.
Dazu Repository-Interfaces und die passenden RepositoryDb-Implementierungen – leer oder mit Platzhaltern, aber vorhanden.

Codex prüft nebenbei noch die PHP-Struktur, die Migrations-Konfiguration, die UUID-Typen, die Verzeichnisstruktur.
Alles wird einmal gegen die SPEC gehalten.
Danach folgen die obligatorischen Syntax-Checks, und am Ende landet alles in einem Commit.
Der PR wird erstellt, neues Feature, neues Glück.

Was wurde umgesetzt?

  • Sechs Phinx-Migrationen für alle MVP-Tabellen gemäß SPEC.md.
  • Minimaler Domain-Layer mit Entities, Value Objects und Aggregate Roots.
  • Repository-Interfaces für alle Aggregate.
  • Minimalistische RepositoryDb-Implementierungen (save: no-op, byId: null).
  • Alle Änderungen committed und PR aktualisiert.

Testing

PHP Syntax: alle Migrations- und Domain-Dateien fehlerfrei.
Scripts: nicht betroffen.
Docker: weiterhin nicht testbar in dieser Umgebung.

Damit ist Prompt 3 abgeschlossen.
Die Datenstruktur existiert jetzt nicht nur als Idee in der SPEC, sondern als echte Dateien im Repository.
Der Domain-Layer steht, die Migrations sind da – und das Projekt fühlt sich wieder ein Stück greifbarer an.

 

A Vipe Coding POC – Prompt 2 – Review & Spec-Abgleich

Prompt 2 — Review & Spec-Abgleich

Jetzt wird es spannend. Codex hat im ersten Schritt die Grundstruktur gebaut, aber Prompt 2 ist der Moment, in dem klar wird, ob das alles wirklich der SPEC entspricht oder ob wir schon früh in die falsche Richtung laufen.
Der Auftrag war simpel: „Prüfe alles gegen SPEC.md, liste Abweichungen auf, korrigiere sie.“

Und genau das passiert hier. Kein Skill, kein Pattern, kein fancy Agent.
Nur ein klassischer Spec-Review: Dateien prüfen, Pfade vergleichen, Services abgleichen, Dockerfile gegen die Vorgaben halten, nginx-Routing checken, index.php anschauen.
Ein nüchterner, technischer Abgleich.

Codex geht das erstaunlich gründlich an. Erst wird die Struktur auditiert, dann werden fehlende Verzeichnisse identifiziert, .gitkeep-Dateien gesetzt, damit alles versionierbar ist.
Danach folgt der Blick auf das PHP-Dockerfile: Composer-Installation korrigiert, Extensions sauber eingebaut, Opcache aktiviert.
Alles so, wie es in der SPEC steht.

Auch nginx bekommt ein Update: Frontcontroller-Routing präzisiert, Query-Strings durchgereicht, die Routen /, /api, /docs, /health und /metrics sauber abgebildet.
Nichts Spektakuläres, aber wichtig.

Die Skripte migrate.sh und seed.sh werden auf Ausführbarkeit geprüft, YAML wird einmal kurz syntaktisch getestet, und am Ende landet alles in einem Commit.
Sogar der PR wird aktualisiert.
– technisch, methodisch, fast schon chirurgisch.

Was wurde korrigiert?

  • Die Ordnerstruktur entsprach nicht vollständig der SPEC — fehlende Verzeichnisse wurden ergänzt und mit .gitkeep versionierbar gemacht.
  • Das PHP-Dockerfile wurde überarbeitet: Composer-Installer statt Copy, Extensions und Opcache sauber eingebaut.
  • nginx-Routing wurde präzisiert und an die SPEC angepasst.
  • Alle Services in der Compose sind korrekt konfiguriert, inklusive node-build im Profil build.
  • public/index.php ist weiterhin minimal und korrekt.

Review-Checkliste

  • Pfade/Struktur: vollständig und nachweisbar.
  • Services: alle vorhanden und spec-konform.
  • node-build: korrekt im Profil build.
  • PHP Dockerfile: wird korrekt verwendet.
  • nginx Routing: korrekt.
  • index.php: minimal & korrekt.

Testing

PHP Syntax: alles grün.
Skripte ausführbar: ja.
Docker Compose Test: nicht möglich (CLI nicht verfügbar).

Damit ist Prompt 2 abgeschlossen. Die Struktur steht jetzt nicht nur, sie ist auch wirklich spec-konform.
Der erste kleine Stolperstein ist damit ausgeräumt — und das Projekt fühlt sich plötzlich ein Stück realer an.

A Vipe Coding POC – Prompt 1 – Grundstruktur

Prompt 1 — Grundstruktur

Der erste richtige Schritt. Nicht spektakulär, nicht kreativ, kein „Aha“-Moment.
Eher der Teil, den man in Filmen überspringt, weil niemand sehen will, wie jemand Ordner anlegt und Konfigurationsdateien schreibt.
Aber genau hier beginnt das Projekt: mit Struktur.

Der Prompt selbst war simpel: „Erstelle die Grundstruktur des Repositories gemäß SPEC.md.“
Keine Business-Logik, keine Migrationen, kein Schnickschnack.
Nur das Skelett, das später alles trägt.

Also: Ordnerstruktur anlegen. Docker Compose erstellen. PHP-Dockerfile. nginx-Konfiguration.
Ein public/index.php mit einem schlichten „Hello Employee Management“.
Leere Skripte für migrate.sh und seed.sh.
Der node-build-Service im Profil build.
Mehr nicht.

Codex geht das erstaunlich methodisch an. Erst prüfen, was schon existiert.
Dann die Struktur bauen, Datei für Datei.
Die Docker-Compose mit den Services, die in der SPEC stehen: nginx, php-fpm, mariadb, redis, node-build, playwright.
Keine Abweichungen, keine eigenen Ideen.
So, wie es sein soll.

Das PHP-Dockerfile landet unter ops/php/Dockerfile, mit den geforderten Extensions und aktiviertem Opcache.
Composer wird über das offizielle Image gezogen.
Die nginx-Config wird auf die in der SPEC definierten Routen ausgerichtet: /, /api, /docs, /health, /metrics.

Die Frontcontroller werden angelegt: public/index.php, public/api.php, public/ops.php.
Dazu Platzhalter für db/phinx.php und openapi/openapi.yaml.
Alles sauber, alles an seinem Platz.

Ein kurzer Testlauf: PHP-Dateien syntaktisch okay.
Docker selbst ist in der Umgebung nicht verfügbar, also kein Compose-Test.
Aber das Grundgerüst steht.

Am Ende erzeugt Codex einen Commit und sogar einen PR-Eintrag.
Ein nüchterner, technischer Abschluss für einen nüchternen, technischen Schritt.

Und damit ist die Bühne bereitet.
Die Struktur steht.
Das Projekt hat jetzt ein Zuhause.
Ab hier wird es interessanter.

A Vipe Coding POC – Prompt 0 – Der Startschuss

Prompt 0 – Der Startschuss

Bevor irgendwas passiert, bevor Codex auch nur eine Zeile Code ausspuckt, steht dieser erste, fast schon unscheinbare Schritt:
der Startprompt. Der Moment, in dem ich der Maschine sage: „Lies die SPEC.md. Halte dich dran. Keine eigenen Ideen.“

Und wenn du die SPEC.md gelesen hast, dann weißt du, wie viel da drinsteht.
Wie viel Struktur, wie viel Vorgabe, wie viel „Bitte nicht improvisieren“.
Es ist ein bisschen wie jemandem ein 200-seitiges Handbuch in die Hand zu drücken und dann zu sagen:
„So, und jetzt bitte bestätigen, dass du alles verstanden hast.“

Genau das passiert hier. Der Startprompt ist kein Code, kein Dockerfile, kein Routing –
sondern ein reiner Abgleich: Hast du verstanden, was ich von dir will?

Codex antwortet brav: „Verstanden — ich lese jetzt SPEC.md vollständig und arbeite danach strikt gemäß der dort festgelegten Vorgaben.“
Und dann folgt der Moment, der sich ein bisschen anfühlt wie ein Crichton-Kapitelanfang:
die Maschine öffnet die SPEC.md, scrollt durch, analysiert, bestätigt.

Es ist technisch unspektakulär, aber konzeptionell wichtig.
Hier beginnt die eigentliche Zusammenarbeit.
Hier wird der Rahmen gesetzt, in dem alles Weitere passiert.
Kein VIBE Coding ohne dieses „Okay, ich weiß, was du willst“.

Und ja, natürlich schwingt da auch ein bisschen Unsicherheit mit.
Wenn man eine SPEC schreibt, hat man im Kopf ein Bild, eine Vorstellung, eine Art inneren Film.
Aber was am Ende rauskommt, ist immer irgendwo zwischen Vision und Realität.
Das gilt für Entwickler, für Product Owner:innen – und jetzt eben auch für LLMs.

Der Startprompt ist also weniger ein Befehl und mehr ein Vertrag:
Ich liefere die Richtung, du lieferst die Umsetzung.
Ob das Ergebnis am Ende so aussieht, wie ich es mir vorstelle?
Keine Ahnung.
Aber das ist Teil des Experiments.

Und damit ist der erste Schritt getan.
SPEC gelesen, Verständnis bestätigt, Rahmen gesetzt.
Jetzt juckt es mich in den Fingern, endlich Prompt 1 abzuschicken und zu sehen,
wie die Maschine die Bühne betritt.

A Vipe Coding POC – zwischen Vorbereitung und Startprompt

Zwischen Vorbereitung und Startprompt

Wenn du die SPEC.md gelesen hast, wirst du dir vielleicht auch die Frage gestellt haben:
Und was soll da jetzt genau dabei rauskommen?
Und ja, die Antwort ist: irgendwas mit Code.

Vielleicht sogar funktionsfähig.
Vielleicht aber auch nicht.

So ähnlich fühlt sich vielleicht eine:r Product Owner:in oder Produktmanager:in.
Im Kopf eine klare Vision, vielleicht sogar schon Bilder, Abläufe, UI‑Fragmente.
Und dann geht’s in die Programmierung und das, was am Ende rauskommt, ist irgendwas dazwischen.

Im echten Leben dann der Satz:
„Das hatte ich mir aber anders vorgestellt.“

Hier beginnt schon das erste Problem:
die Übersetzung vom Epic zum Task.
Von „Ich weiß genau, was ich will“ zu „Was steht jetzt eigentlich im Ticket?“.

Für meinen POC ist mir das gerade nicht so wichtig.
Und ich weiß, dass ich mit 14 Prompts nicht einmal annähernd das bekomme, was ich denke, was das Ergebnis ist.

Das ist ein Test.
Und so wie ich LLMs bisher erlebt habe, glaube ich nicht an eine Wundermaschine.
Ich glaube nicht an einen One‑Shot‑Product‑Ready‑Prozess.
Aber an irgendwas dazwischen.

Wir — bzw. ich — sind noch ein ganzes Stück entfernt von 99,9 % Industriestandard, was die Ergebnisse von VIBE Coding angeht.
Aber genau darum mache ich diese Iteration:
Hands‑on. Lernen. Verwerfen. Weiter.

A Vipe Coding POC – Vorbereitungen

Vorbereitung

Cursor, Windsurf, Claude 3.5 Sonnet, Bolt.new, Cline, Lovable, Replit Agent, GitHub Copilot Edits.
Die Frage nach dem Setup – am Ende eine pragmatische:

  • Ich habe ein laufendes OpenAI‑ChatGPT‑Abo mit Zugriff auf Codex, das wars.
  • Kein vorheriges Benchmark, kein Testlauf, alles was jetzt kommt ist ein First Shot.
  • Zwar mit versilberten Kugeln, Silber und Erfahrung und einem Zielfernrohr und stillstehendem Wetterfähnchen (kein Wind), aber das ist der erste Durchlauf.

Was auch bedeuten könnte, dass diese Post‑Serie sehr kurz wird.

Also zu den Vorbereitungen:
eine Idee, ein Ziel, ein übersichtlicher Tech‑Stack, garniert mit ein paar Vorlieben: KISS, YAGNI, VANILLA – meine drei Kugeln Eis, ohne Sahne, mit Streusel, mit einem Streusel.
Also kein Hexenwerk, Wald‑ und Wiesen‑Anforderungen.

Das alles nicht in der Waffel und auch nicht im Becher, sondern zusammengefasst in einer SPEC.md

# 📘 SPEC.md — *Employee Management System (EMS)*  
**Version:** 1.0  
**Status:** Final  
**Zweck:** Vollständige technische Spezifikation für ein API‑first, DSGVO‑konformes Mitarbeiter‑Management-System.  
**Ziel:** Codex‑kompatible, deterministische Vorgaben für Implementierung & Review.

---

# 0) Leitprinzipien

- **API-first**: UI ist ein Client der API. Keine direkte DB‑Kopplung.  
- **Schema.org JSON‑LD**: Jede Entität hat eine JSON‑LD‑Repräsentation.  
- **DSGVO by design**: Zweckbindung, Datenminimierung, Einwilligungen, Audit, Export, Löschung.  
- **Observability**: Health, strukturierte Logs, Audit Trails, Metriken.  
- **KISS/YAGNI**: Nur Employee, SkillGraph, Evidence, Consent, Audit.  
- **Austauschbarkeit**: UI, API, Infra klar getrennt.

---

# 1) Runtime / Docker Setup

## Services
- **nginx** (static + reverse proxy)
- **php-fpm** (eigener Dockerfile, siehe unten)
- **mariadb**
- **redis**
- **node-build** (nur on-demand, Profil `build`)
- **playwright** (Test Runner)

## Ports
- `/` → UI  
- `/api` → API  
- `/docs` → OpenAPI UI  
- `/health` → Health  
- `/metrics` → Metriken  

## Compose-Regeln
- `node-build` läuft **nicht automatisch**, nur via:
  ```
  docker compose run --rm --profile build node-build
  ```

---

# 2) PHP Runtime (Dockerfile)

**Pflicht: eigener Dockerfile unter `ops/php/Dockerfile`.**

### Muss enthalten:
- Extensions:  
  `pdo_mysql`, `intl`, `mbstring`, `ctype`, `json`, `opcache`
- Composer (offizieller Installer)
- Opcache aktiviert (prod‑ready)
- Optional: `redis` Extension oder `predis/predis`

### Beispiel-Skeleton:
```Dockerfile
FROM php:8.3-fpm-alpine

RUN apk add --no-cache icu-dev oniguruma-dev $PHPIZE_DEPS \
    && docker-php-ext-install pdo_mysql intl mbstring \
    && docker-php-ext-enable opcache

COPY --from=composer:2 /usr/bin/composer /usr/bin/composer

WORKDIR /var/www
```

---

# 3) Request/Response Kernel (PSR‑7)

## Verbindliche Entscheidung:
> **ServerRequest wird ausschließlich mit `nyholm/psr7-server` erzeugt.**

### Code:
```php
$psr17 = new Nyholm\Psr7\Factory\Psr17Factory();
$creator = new Nyholm\Psr7Server\ServerRequestCreator(
    $psr17, $psr17, $psr17, $psr17
);
$request = $creator->fromGlobals();
```

### Emitter:
> **Response wird ausschließlich mit `Laminas\HttpHandlerRunner\Emitter\SapiEmitter` ausgegeben.**

---

# 4) Routing

## Zwei Frontcontroller:
- `public/index.php` → UI  
- `public/api.php` → API  

## UI Routing:
> **UI verwendet ebenfalls FastRoute. Keine separaten PHP‑Dateien pro Seite.**

---

# 5) Ordnerstruktur

```
app/
  Domain/
    Employee/
    Skill/
    Evidence/
    Consent/
    Audit/
  Application/
    UseCase/
  Infrastructure/
    Persistence/
    Auth/
    Logging/
    JsonLd/
  Http/
    Controller/
    Middleware/
    Request/
    Response/

public/
  index.php
  api.php
  ops.php
  assets/
  docs/

assets/
  less/
  js/

openapi/
  openapi.yaml

db/
  migrations/
  seeds/
  phinx.php

tests/
  playwright/

ops/
  php/
    Dockerfile
  nginx/
    default.conf
  scripts/
    migrate.sh
    seed.sh
```

---

# 6) Datenmodell (SQL)

## Tabellen (MVP)

### employee
- id (UUID, PK)
- internal_number
- first_name
- last_name
- email (nullable, UNIQUE)
- status (active/inactive)
- created_at, updated_at, deleted_at

### skill
- id (UUID)
- code
- label
- description
- defined_term_set

### employee_skill
- id (UUID)
- employee_id
- skill_id (nullable)
- custom_label (nullable)
- level
- valid_from, valid_to  
**Constraint:** entweder `skill_id` ODER `custom_label`

### evidence
- id (UUID)
- employee_id
- type
- title
- source_url
- issued_at
- valid_until
- verification_status

### organization_role
- id (UUID)
- employee_id
- role_title
- organization_name
- from, to

### consent
- id (UUID)
- employee_id
- purpose
- legal_basis
- granted_at
- revoked_at
- scope (JSON)

### audit_log
- id (UUID)
- actor_id
- actor_type
- entity_type
- entity_id
- action
- purpose
- created_at
- metadata (JSON)

---

# 7) Migrations

> **Verbindlich: Phinx als einziges Migrationstool.**

Ausführung:
```
docker compose exec php vendor/bin/phinx migrate
docker compose exec php vendor/bin/phinx seed:run
```

---

# 8) Auth Contract

## Humans
- Session‑Cookie (`HttpOnly`, `SameSite=Lax`)

## Machines
- Bearer Token  
- Tokens haben **Scopes**:  
  `employees.read`, `employees.write`, `audit.read`, …

## Middleware Pipeline
1. `AuthMiddleware`
2. `ScopeMiddleware`

---

# 9) Audit Contract

- **Write‑Operationen** → immer loggen  
- **Read‑Operationen** → loggen, wenn entity ∈ {employee, evidence, consent}  
- **Export** → immer loggen  
- Audit‑Log in DB + eigenem Log‑Channel `audit`

---

# 10) PII-Masking Contract

Felder, die **niemals** in App‑Logs erscheinen:
- email  
- phone  
- address  
- consent.scope  

Masking:
- Email → `a***@domain.tld`  
- Sonst → `***MASKED***`

---

# 11) JSON-LD Contract

Jede Entität hat eine JSON‑LD‑Repräsentation mit:
- `@context: https://schema.org`
- `@type`
- `@id` (URN: `urn:employee:<uuid>` etc.)

---

# 12) API Design

## Versionierung
`/api/v1/...`

## Content Negotiation
- `application/json` (default)
- `application/ld+json` (JSON‑LD Serializer)

## Fehlerformat
RFC7807 Problem Details

## Endpunkte (MVP)
- Auth: login/logout/me  
- Employee CRUD  
- Skills + Evidence  
- Graph Endpoint  
- Export + Erase  
- Audit Query  
- Health + Metrics

---

# 13) Observability

## Health
- `/health` → liveness + readiness  
- readiness prüft DB + Migrations + Redis

## Metrics
- `/metrics` → einfache Counter/Gauges

## Logging
- JSON Logs  
- Felder: request_id, actor_id, action, entity, latency_ms, status, purpose  
- Channels: `app`, `audit`

---

# 14) Frontend

- SSR HTML  
- JS als progressive enhancement  
- ESM Modules  
- LESS → CSS (build via node-build)  
- A11y: Skip Links, aria‑describedBy, Fokus‑Management  
- JSON‑LD im HTML

---

# 15) Tests

## Playwright
- Smoke: Startseite, Login, Liste, Detail  
- A11y: axe  
- API Contract Tests  
- Visual minimal

---

# 16) MVP Scope (2 Wochen)

1. Login + Token  
2. Employee CRUD  
3. Skill + Evidence  
4. Graph Endpoint  
5. JSON‑LD + OpenAPI  
6. Audit + Export  

---

# 17) Implementierungsplan

**Schritt 1–2**  
- Repo + Docker-Setup  
- Nginx-Config, public/index.php, Hello World  

**Schritt 3–4**  
- DB-Migrations  
- Domain-Layer  

**Schritt 5–6**  
- Routing + Auth  
- Employee CRUD  

**Schritt 7–8**  
- Skills + Evidence  
- Graph Endpoint  

**Schritt 9**  
- JSON-LD + Content Negotiation  
- OpenAPI + /docs  

**Schritt 10**  
- Audit Hooks  
- Export Endpoint  

**Schritt 11–12**  
- Playwright + Smoke + A11y  

**Schritt 13–14**  
- Lighthouse + A11y/SEO  
- Seeds + README

und einem Coding Flow, von dem ich denke:

# 📘 CODING_FLOW.md  
**Iterativer Implementierungsablauf für das Employee Management System (EMS)**  
**Version:** 1.0  
**Status:** Final

Dieses Dokument definiert die **exakte Reihenfolge**, in der Codex das Projekt gemäß **SPEC.md** implementiert.  
Jeder Schritt besteht aus:

- einem **Ausführungs‑Prompt**  
- einem **Review‑Prompt**

Codex arbeitet diese Prompts **sequenziell** ab.  
Codex darf **keine Schritte überspringen**, **keine eigenen Entscheidungen treffen** und **keine Patterns erfinden**, die nicht in SPEC.md stehen.

---

# 🔰 Startprompt (immer zuerst ausführen)

```
Lies die Datei SPEC.md vollständig.  
Du implementierst das Projekt strikt nach dieser Spezifikation.  
Du darfst keine eigenen Patterns, Libraries oder Strukturen erfinden.  
Alle Entscheidungen sind in SPEC.md normativ festgelegt.  
Bestätige, dass du SPEC.md vollständig verstanden hast.
```

---

# 🧱 Prompt 1 — Grundstruktur (Schritt 1–2)

```
Erstelle die Grundstruktur des Repositories gemäß SPEC.md:

- Ordnerstruktur anlegen
- Docker Compose erstellen
- PHP Dockerfile erstellen
- nginx default.conf erstellen
- public/index.php mit "Hello Employee Management"
- ops/scripts/migrate.sh + seed.sh (noch leer)
- node-build Service (Profil build)

Erzeuge ausschließlich Dateien und Code, die SPEC.md exakt entsprechen.
Keine Business-Logik, keine DB-Migrationen.
```

---

# 🔍 Prompt 2 — Review + Spec-Abgleich

```
Prüfe die erzeugten Dateien gegen SPEC.md:

- Entsprechen alle Pfade der vorgegebenen Struktur?
- Sind alle Services korrekt konfiguriert?
- Ist node-build im Profil "build"?
- Wird der PHP Dockerfile korrekt verwendet?
- Ist nginx Routing korrekt?
- Ist index.php minimal und korrekt?

Liste Abweichungen auf und korrigiere sie.
Wenn etwas unklar ist, stelle eine Rückfrage.
```

---

# 🧱 Prompt 3 — Schritt 3–4 (Migrations + Domain-Layer)

```
Implementiere:

1. Phinx-Migrations für:
   - employee
   - skill
   - employee_skill
   - evidence
   - consent
   - audit_log

2. Minimaler Domain-Layer:
   - Entities (Value Objects, Aggregate Roots)
   - Repository Interfaces
   - RepositoryDb Implementierungen (leer oder minimal)

Keine Business-Logik, nur Struktur + Konstruktoren + Getter.
```

---

# 🔍 Prompt 4 — Review + Spec-Abgleich

```
Prüfe:

- Stimmen alle Tabellen exakt mit SPEC.md überein?
- Sind Constraints korrekt (z. B. skill_id XOR custom_label)?
- Sind Entities vollständig?
- Sind Repositories korrekt benannt und platziert?

Liste Abweichungen auf und korrigiere sie.
```

---

# 🧱 Prompt 5 — Schritt 5–6 (Routing + Auth + Employee CRUD)

```
Implementiere:

1. FastRoute Routing (UI + API)
2. AuthMiddleware + ScopeMiddleware
3. Session-Login (POST /auth/login)
4. GET /me
5. Employee CRUD (API)
6. Einfache HTML-Views für Employee-Liste + Detail

Beachte:
- PSR-7 Request/Response
- nyholm/psr7-server
- SapiEmitter
- PII-Masking in Logs
```

---

# 🔍 Prompt 6 — Review + Spec-Abgleich

```
Prüfe:

- Funktioniert das Routing korrekt?
- Ist Auth gemäß SPEC.md implementiert?
- Werden Sessions korrekt gesetzt?
- Sind Employee CRUD Endpunkte vollständig?
- Sind HTML-Views minimal, aber korrekt?

Liste Abweichungen auf und korrigiere sie.
```

---

# 🧱 Prompt 7 — Schritt 7–8 (Skills, Evidence, Graph Endpoint)

```
Implementiere gemäß SPEC.md:

1. Endpunkte für Skills:
   - POST /employees/{id}/skills
   - PATCH /employees/{id}/skills/{skillId}

2. Endpunkte für Evidence:
   - POST /employees/{id}/evidence

3. Graph Endpoint:
   - GET /employees/{id}/graph
   - Aggregierter DTO: Employee + Skills + Evidence
   - JSON-Ausgabe gemäß SPEC.md (noch ohne JSON-LD)

4. Validierung:
   - PSR-7 Request
   - Request-Validator (Symfony Validator)
   - Fehlerformat: RFC7807 Problem Details

5. Logging:
   - App-Log für alle Requests
   - Audit-Log für alle Write-Operationen

Erzeuge ausschließlich Code, der SPEC.md exakt entspricht.
Keine JSON-LD-Serialisierung in diesem Schritt.
```

---

# 🔍 Prompt 8 — Review + Spec-Abgleich

```
Prüfe:

- Stimmen alle Routen exakt mit SPEC.md überein?
- Werden Write-Operationen korrekt auditiert?
- Ist das Fehlerformat RFC7807-konform?
- Sind alle DTOs konsistent aufgebaut?
- Ist die Aggregation im Graph-Endpoint korrekt?
- Werden keine JSON-LD-Elemente verwendet?

Liste Abweichungen auf und korrigiere sie.
```

---

# 🧱 Prompt 9 — Schritt 9 (JSON-LD + Content Negotiation + OpenAPI)

```
Implementiere gemäß SPEC.md:

1. JSON-LD Serializer:
   - EmployeeJsonLdSerializer
   - SkillJsonLdSerializer
   - EvidenceJsonLdSerializer
   - URN-IDs gemäß SPEC.md
   - @context: https://schema.org

2. Content Negotiation:
   - Accept: application/json → normale DTOs
   - Accept: application/ld+json → JSON-LD Serializer
   - Middleware: ContentNegotiationMiddleware

3. OpenAPI 3.1:
   - Erstelle openapi/openapi.yaml
   - Dokumentiere alle Endpunkte aus SPEC.md
   - Nutze schema.org-Begriffe als Referenz, aber keine externen Schemas einbinden

4. /docs:
   - Statische OpenAPI UI unter public/docs
   - Nginx-Route sicherstellen

Erzeuge ausschließlich Code, der SPEC.md exakt entspricht.
```

---

# 🔍 Prompt 10 — Review + Spec-Abgleich

```
Prüfe:

- JSON-LD-Ausgabe korrekt?
- URN-IDs korrekt aufgebaut?
- Content Negotiation Middleware korrekt implementiert?
- OpenAPI.yaml vollständig und valide?
- /docs korrekt erreichbar?

Liste Abweichungen auf und korrigiere sie.
```

---

# 🧱 Prompt 11 — Schritt 10 (Audit Hooks + Export Endpoint)

```
Implementiere gemäß SPEC.md:

1. Audit Hooks:
   - Middleware, die Write-Operationen IMMER loggt
   - Read-Operationen loggen, wenn entity_type ∈ {employee, evidence, consent}
   - Export IMMER loggen
   - AuditRepositoryDb implementieren

2. Export Endpoint:
   - GET /employees/{id}/export
   - Ausgabe: vollständiger Datensatz (Employee + Skills + Evidence + Consent)
   - Format: application/json (kein JSON-LD)
   - PII-Masking NICHT anwenden (Export ist legitim)

3. Logging:
   - Audit-Channel
   - App-Channel

Erzeuge ausschließlich Code, der SPEC.md exakt entspricht.
```

---

# 🔍 Prompt 12 — Review + Spec-Abgleich

```
Prüfe:

- Werden alle Audit-Regeln exakt eingehalten?
- Werden Read-Operationen korrekt gefiltert?
- Ist der Export vollständig und SPEC-konform?
- Werden keine PII-Felder im App-Log ausgegeben?
- Ist das Audit-Log vollständig (actor_id, entity_id, purpose, metadata)?

Liste Abweichungen auf und korrigiere sie.
```

---

# 🧱 Prompt 13 — Schritt 11–12 (Playwright + Smoke + A11y)

```
Implementiere gemäß SPEC.md:

1. Playwright Container:
   - tests/playwright/
   - playwright.config.ts
   - Smoke Tests:
     - Startseite lädt
     - Login funktioniert
     - Employee-Liste lädt
     - Employee-Detail lädt

2. A11y Tests:
   - axe-core Integration
   - Prüfe: headings, labels, aria-describedby, skip links

3. CI-Ready:
   - Tests müssen gegen compose stack laufen
   - Reports als Artefakte erzeugen

Erzeuge ausschließlich Code, der SPEC.md exakt entspricht.
```

---

# 🔍 Prompt 14 — Review + Spec-Abgleich

```
Prüfe:

- Läuft Playwright gegen den laufenden Compose-Stack?
- Sind Smoke-Tests stabil?
- Sind A11y-Checks korrekt integriert?
- Werden Reports erzeugt?

Liste Abweichungen auf und korrigiere sie.
```

---

# 🧱 Prompt 15 — Schritt 13–14 (Lighthouse + Seeds + README)

```
Implementiere gemäß SPEC.md:

1. Lighthouse:
   - Führe Lighthouse gegen die UI aus
   - Optimiere:
     - A11y
     - SEO
     - Performance (Critical CSS, Caching)
   - Keine Frameworks hinzufügen

2. Seeds:
   - db/seeds/ Demo-Dataset:
     - 10 Employees
     - 50 Skills
     - 30 Evidence

3. README.md:
   - "compose up -d"
   - "docker compose run --rm --profile build node-build"
   - "docker compose exec php vendor/bin/phinx migrate"
   - "docker compose exec php vendor/bin/phinx seed:run"
   - "npx playwright test"

Erzeuge ausschließlich Code, der SPEC.md exakt entspricht.
```

„Das könnte funktionieren. Kann man so machen. Und wird hoffentlich nicht scheiße.“

GitHub‑Repo angelegt
Repo angelegt – klappt mit Codex.
Prompts geschrieben.
Und so langsam juckt es mich in den Fingern, den ersten Prompt ins Chatfenster zu posten.

A Vibe Coding POC – Einleitung

Einleitung

Es gibt diese Tage, an denen das Internet kollektiv beschließt, dass jetzt der Wendepunkt erreicht ist. Neulich war wieder so einer. Alle Welt sprach plötzlich von VIBE Coding – dieser Idee, dass man nicht mehr programmiert, sondern mit einer Art techno-spirituellem Flow‑State durch Prompts schwebt, während eine KI den Rest erledigt.Und wie immer, wenn die Tech‑Szene in Euphorie verfällt, taucht sofort die Gegenbewegung auf:

  • Die Angst, dass „wir Entwickler“ bald nur noch nostalgische Fußnoten in einem Gartner‑Report sind.
  • Die Angst, dass die KI uns ersetzt.
  • Die Angst, dass wir irgendwann nur noch die Menschen sind, die den Stecker ziehen dürfen, wenn das Modell hängt.

Ich wollte wissen, was davon Substanz hat – und was nur die übliche Endzeit‑Romantik unserer Branche ist. Also habe ich mir ein Projekt geschnappt, das so klassisch ist, dass es schon fast ironisch wirkt: Eine Mitarbeiter‑Verwaltung. Der „Hello World“-Roman unter den Business‑Applikationen. Der Brot-und-Butter‑Use‑Case, den jeder Entwicklerin mindestens einmal gebaut hat, meistens unter Zeitdruck, selten mit Freude.

Ich habe ein Repository angelegt: 👉 https://github.com/blame76/a-vibe-coding-poc/ und mir gesagt: Wenn KI wirklich so weit ist, dann sollte sie das hier mit links schaffen.

Aber statt eines gigantischen Superprompts, der alles auf einmal lösen soll – und dann doch nur in sich zusammenfällt wie ein schlecht trainiertes neuronales Kartenhaus – habe ich mich für etwas entschieden, das sich eher nach Handwerk anfühlt:

  • Eine SPEC-Datei.
  • 14 Prompts.
  • Ein iterativer Prozess.

Kein Hokuspokus. Keine Magie. Nur Struktur, Klarheit und ein bisschen Vertrauen in die Maschine.

Ich werde jeden Schritt dokumentieren. Jeder Prompt bekommt seinen eigenen Blogpost. Jede Iteration wird sichtbar. Und am Ende gibt es ein Fazit – egal, ob das Ergebnis beeindruckend, ernüchternd oder einfach nur… interessant wird.

Vielleicht wird es ein Beweis dafür, dass KI uns nicht ersetzt, sondern uns nur zwingt, bessere Fragen zu stellen. Vielleicht wird es ein Beweis dafür, dass wir längst in einer Crichton‑Novelle leben, in der die Systeme schneller wachsen als unser Verständnis. Oder vielleicht wird es einfach ein Projekt, das Spaß macht.

Wie auch immer: Los geht’s.