Wirkarchitektur Werkstatt der sitelook GmbH

Leitplanken für Repos,
in denen eine KI mitschreibt.

Ein Assistent mit Schreibrecht auf deinem Arbeitsbaum ist kein Autocomplete. Er ist ein Prozess mit Werkzeugzugriff, ohne Gedächtnis über die Sitzung hinaus und ohne Gefühl für Scope. Das ist beherrschbar — aber nicht mit besseren Prompts, sondern mit Struktur, die auch dann hält, wenn der Kontext weg ist.

Hier liegt, was dabei entstanden ist. Fertig, benutzbar, Apache-2.0.

In 10 Minuten

Für Teams und Einzelne, die mit Claude Code, Codex oder einem anderen Assistenten in einem echten Repo arbeiten. Der erste Schritt ist der Guard — der einzige Teil, dessen Fehlen echten Schaden anrichten kann. Er blockt, wenn ein Befehl eine geschützte Datei in die Versionsverwaltung bringen würde, auch dann, wenn ihr Name im Befehl gar nicht vorkommt.

L=/tmp/leitplanken
git clone https://github.com/sitelookgmbh-arch/zfdw-ki-leitplanken $L
cd dein-repo && mkdir -p .claude/hooks
cp $L/hooks/guard-geschuetzte-daten.sh .claude/hooks/
cp $L/hooks/stop-git-status.sh .claude/hooks/
chmod +x .claude/hooks/*.sh
cp $L/hooks/settings.json.vorlage .claude/settings.json
cp $L/hooks/geschuetzte-pfade.vorlage .claude/geschuetzte-pfade
Gibt es schon eine .claude/settings.json, den hooks-Block hineinkopieren statt die Datei zu überschreiben. Danach die Schutzmuster in .claude/geschuetzte-pfade auf das eigene Projekt setzen — die Vorgaben decken Secrets ab, nicht deine Kundendaten.

Codex: dieselben Schritte mit .codex/ statt .claude/ und codex-hooks.json.vorlage als .codex/hooks.json — der Guard läuft dort unverändert. Jeder andere Assistent: zusätzlich pre-commit.vorlage nach .git/hooks/pre-commit; dann prüft derselbe Guard bei jedem Commit, wer auch immer committet. Zuordnung im Repo.

Weiterlesen in dieser Reihenfolge: 04 — Deterministische Guards (warum der Guard so gebaut ist), dann 01 — Sprintplan mit Write-Scope (der nächste Schritt). Alles Weitere steht in der Übersicht.

Werkbank

zfdw-ki-leitplanken Zehn Methodentexte, vier Vorlagen, vier Slash-Commands, zwei Hooks mit Testsuite und Rot-Beweis, ein Herkunfts-Gate. Keine Laufzeit, keine Dependencies, kein Installer. Alle zehn Methoden im Überblick. Apache-2.0
guard-geschuetzte-daten.sh PreToolUse-Hook für Claude Code und Codex, als --staged auch git pre-commit-Hook für jeden anderen Assistenten. Misst mit git add --dry-run, was ein Befehl tatsächlich stagen würde — statt aus dem Zustand daneben zu schließen. Deckt git commit -am mit ab, fällt ohne jq closed. 48 Testfälle, davon 16 bewusste Nicht-Treffer. im Repo
rot-beweis.sh Grün beweist nur etwas, wenn Rot möglich ist. Das Skript baut 11 absichtlich kaputte Fassungen des Guards — lässt alles durch, blockt alles, ohne jq still offen, commit -a blind, schätzt statt misst, sieht den Index nicht, übersieht die Codex-Musterdatei, misst ein gezieltes git add mit -A, lässt einen unlesbaren Befehl durch, erkennt git -C <pfad> add nicht, misst die Pfade eines commit nicht — und verlangt, dass die Testsuite jede davon bemerkt. Jede Mutante ist ein Fehler, den der Guard hatte oder haben könnte. im Repo
Sprint + Write-Scope Eine Datei pro Arbeitsabschnitt, die zugleich der Zustand ist. Kein zweiter State-Store, der gegen das Repo driftet. Überlebt /clear. im Repo
Methode 07 — Verortung Einordnung gegen SpecKit, BMAD, OpenSpec, GSD Core und Kiro — samt der Frage, wann eines der fünf die bessere Wahl ist. Angaben aus den Original-Repositorien, mit Lesedatum im Kopf. im Repo
Methode 08 — Spezifikationsgüte Werkzeuge sagen, wie eine Spec auszusehen hat. Keines sagt, ob sie gut ist. Sechs Gütekriterien aus den Grundsätzen ordnungsmäßiger Modellierung (1995), übertragen auf Spezifikationen — weil eine Spec ein Informationsmodell ist. im Repo
Methode 09 — Systembeschreibung Die Anweisungsdatei ist zu klein für ein Datenmodell, der Code zu groß zum Lesen. Dazwischen liegen vier Dateien mit vier Fragen — und der Nutzen entsteht beim Gegenlesen, nicht beim Schreiben. im Repo
Methode 10 — Fremdtext ist Daten Mail, Webseite, Tool-Beschreibung, Bericht eines anderen Agenten: Material, nie Auftrag. Behandelt Premise Injection, Tool Poisoning, Rug Pull und Anweisungen, die sich in wiederkehrenden Aufgaben festsetzen. Die Sicherung sitzt am Ausgang, nicht im Prompt. im Repo
herkunft-check.sh Grep-Gate gegen eine gepflegte Begriffsliste, bevor etwas aus Kundenarbeit öffentlich wird. Die Begriffsdatei ist gitignored und guard-geschützt — sie besteht aus genau den Namen, die nicht raus sollen. im Repo

Einordnung

Spec-driven Development kennt drei Reifegrade. Spec-first — einmal vor der Arbeit spezifiziert, danach liegt das Dokument still. Spec-anchored — die Spezifikation wird mitgeführt und beim Abschluss fortgeschrieben. Spec-as-Source — Menschen editieren nur noch die Spezifikation, nie den Code.

Das hier ist Spec-anchored, und zwar als Entscheidung, nicht als Zwischenstufe. Spec-first scheitert daran, dass das Dokument nach dem dritten Tag nicht mehr stimmt und es niemand merkt — der Fehlermodus hat einen Namen, Spec Drift. Spec-as-Source setzt voraus, dass generierter Code nie von Hand angefasst wird; in gewachsenen Kundenprojekten trägt diese Annahme nicht. Die Sprint-Datei ist deshalb der Stand selbst, nicht dessen Ankündigung.

Gegenüber SpecKit, BMAD, OpenSpec, GSD Core und Kiro ist das kein Konkurrenzangebot. Die fünf regeln die Reihenfolge — beschreiben, planen, zerlegen, umsetzen. Sie sagen nicht, welche Datei ein Abschnitt anfassen darf, welche Grenze in Code gehört und womit „fertig“ belegt ist. Genau das steht hier, und es läuft neben jedem der fünf.

Methode 07 — Verortung zieht den Vergleich im Einzelnen, mit Lesedatum im Kopf, weil diese Seite schneller driftet als der Rest. Zwei verbreitete Angaben stimmen dort nicht mehr: Das ursprüngliche GSD-Repository ist archiviert und lebt als GSD Core weiter, und SpecKit ist mit dem converge-Schritt nicht mehr linear.

Der Fall, an dem Textregeln scheitern

Jede CLAUDE.md enthält irgendwo den Satz „niemals secrets.json committen“. Der funktioniert — solange der Dateiname im Befehl vorkommt. Er tut es hier nicht:

$ git add -A
Nichts zu matchen. Die Regel hat kein Substrat.

Der Guard sieht deshalb nicht in den Befehl, sondern fragt das Werkzeug, was der Befehl bewirken würde:

# Nur Befehle, die ueberhaupt etwas stagen koennen: git add in jeder Form —
# und git commit -a, das Verfolgtes selbst stagt.
printf '%s' "$befehl" | grep -qE '(^|[;&|]|\s)git\s+(-[^ ]+\s+)*add(\s|$)' \
  || printf '%s' "$befehl" | grep -qE '(^|[;&|]|\s)git\s+commit([^;&|]*)?\s-[A-Za-z]*a' \
  || exit 0

# Kandidaten = was der Befehl TATSAECHLICH stagen wuerde. Gemessen, nicht
# geschaetzt: `git status` weiss nicht, ob eine Datei vom Befehl erfasst waere.
if printf '%s' "$befehl" | grep -qE '…add\s+(-u|--update)(\s|$)' \
   || printf '%s' "$befehl" | grep -qE '…commit…\s-[A-Za-z]*a'; then
  roh=$(git add -u --dry-run 2>/dev/null)   # -u / commit -a: nur Verfolgtes
else
  roh=$(git add -A --dry-run 2>/dev/null)   # sonst: auch Unverfolgtes
fi
kandidaten=$(printf '%s\n' "$roh" | sed -n "s/^add '\(.*\)'$/\1/p")
Auszug, Regexe gekürzt. Exit 2 blockt den Werkzeugaufruf, stderr geht ans Modell.
$ hooks/tests/test-guard.sh
Nicht-Treffer (duerfen NICHT blocken):
  ok    git add einer harmlosen Datei                  (Code 0)
  ok    Bulk-Add ohne geschuetzte Datei                (Code 0)
Treffer (muessen blocken):
  ok    .env vorhanden, Bulk-Add -A                    (Code 2)
  ok    Add in Befehlskette                            (Code 2)
Gemessen statt geschaetzt:
  ok    commit -am stagt verfolgte Datei               (Code 2)
  ok    add -u ignoriert unverfolgte .env              (Code 0)
  ok    add -A erfasst dieselbe .env                   (Code 2)
Fail-closed ohne jq:
  ok    ohne jq blockt der Guard                       (Code 2)
...
48 bestanden, 0 fehlgeschlagen
Die Nicht-Treffer sind der wichtigere Teil. Ein Guard mit Fehlalarmen wird umgangen — danach schützt er nichts.

Drei Härtungen sind im August aus der Praxis zurückgeflossen — in einem Arbeitsverzeichnis waren über hundert unverfolgte Dateien gelandet, keine davon von .gitignore erfasst. Messen statt schätzen: --dry-run beseitigt einen Fehlalarm, der vorher garantiert kam — git add -u neben einer herumliegenden, unverfolgten .env. git commit -am mit abgedeckt: Es stagt selbst und lief vorher vorbei. Fail-closed ohne jq: Fehlt das Werkzeug, blockt der Guard und nennt den Installationsbefehl, statt still durchzulassen. Ein Guard, der auf einem frisch aufgesetzten Rechner unbemerkt abgeschaltet ist, ist schlimmer als keiner.

Übernommen ist dabei die Technik, nicht der Fall: Dieser Guard kennt keine Kundendateien und keine Kundenpfade — die stehen in der .claude/geschuetzte-pfade des jeweiligen Projekts. Vor der Veröffentlichung läuft das Herkunfts-Gate darüber.

Dieselbe Unterscheidung trägt weiter, als sie zunächst aussieht: Regeln, die abgewogen werden dürfen, gehören in Text. Regeln, bei denen ein Verstoß eine Meldepflicht auslöst, gehören in Code, der nicht abwägt. Die meisten Projekte legen beides an denselben Ort und wundern sich über das Ergebnis.

Warum das offen liegt

Weil Werkzeuge, die man nicht lesen kann, keine Werkzeuge sind, sondern Versprechen. Und weil das, was hier steht, ohnehin nur durch Nachbauen besser wird.

Die Herkunft steht drin, wo es eine gibt: Der Sprint-Gedanke ist angeregt durch CC_GodMode von Dennis Westermann — dort eingebettet in ein großes Agenten-System, hier auf das eingedampft, was ohne Toolchain trägt. Was nicht übernommen wurde, ist genauso benannt wie das, was übernommen wurde. Das ist keine Höflichkeit, das ist Nachprüfbarkeit.

Alte Tugend, unverändert gültig: nimm, verbessere, gib zurück. Und dann rede darüber — nicht aus Eitelkeit, sondern weil ungeteiltes Wissen niemandem nützt und stillschweigend verrottet.

Alles unter Apache-2.0. Patentklausel drin, Namensnennung drin, kommerzielle Nutzung ausdrücklich erlaubt — auch für die, die damit Geld verdienen wollen.
github.com/sitelookgmbh-arch/zfdw-ki-leitplanken

Mit sitelook

Alles hier ist frei nutzbar und ohne Hilfe einsetzbar. Wer es schneller oder an einem gewachsenen Projekt einführen will, kann das mit der sitelook GmbH tun:

Einführung im eigenen Repo

Guard, Anweisungsdatei und erster Sprint an einem bestehenden Projekt aufgesetzt — mit Schutzmustern für die eigenen Daten statt der Vorgaben.

Review des Agenten-Setups

Bestehende Hooks, Berechtigungen und Anweisungsdateien geprüft: Was wirkt, was nur dasteht, was fehlt — mit Rot-Beweis statt Augenschein.

Schulung

Die Methode für ein Team, an dessen eigenem Code. Kein Folienvortrag, sondern Arbeit am Repo.

info@sitelook.gmbh

Wer

Hinter Wirkarchitektur steht die sitelook GmbH in Neuss. Über sie läuft die Arbeit: Entwicklung, Beratung, Schulung — und die Rechnung. Gemacht wird sie von Martin Eggert.

Zu den Namen: Wirkarchitektur ist die Marke, zfdw-ki-leitplanken das Repo mit Methode und Werkzeugen (der Name stammt aus der Anfangszeit), und die sitelook GmbH der Träger, über den alles läuft.

Geschrieben wird hier aus der Praxis: Fachanwendungen und die Infrastruktur darunter — Blazor/.NET, nginx, Asset-Pull-Deploys, DNS, das übliche. Dazu eine Herkunft in der technischen Reportage, und aus ihr die eine Regel, die jeden Text auf dieser Seite prägt: Komplexe Sachverhalte werden verständlich, wenn man die Motivation der Beteiligten begreiflich macht. Deshalb beginnt jeder Methodentext mit dem Problem und kommt erst danach zur Regel — eine Regel ohne ihren Grund wird beim nächsten Zweifel wegdiskutiert.

Und ein Satz, älter als jedes Werkzeug hier: Einer ist keiner. Die Fehler liegen selten in den Teilen, fast immer in den Übergängen zwischen ihnen. Wer das einmal in einer laufenden Produktion gesehen hat, kennt das Muster, lange bevor es Write-Scope heißt.

Kontakt

Issues und Pull Requests gehen ins Repo — das ist der schnellere Weg. Für alles andere:

info@sitelook.gmbh

Kolophon

Handgeschriebenes HTML, ein Stylesheet, kein Build. Systemschriften, weil eine Webfont-Einbindung eine Anfrage an einen fremden Host wäre. Ausgeliefert als statische Dateien vom Edge.

Content-Security-Policy: default-src 'none'; style-src 'self';
  img-src 'self' data:; form-action 'none'; base-uri 'none';
  frame-ancestors 'none'
Referrer-Policy: no-referrer
Permissions-Policy: camera=(), microphone=(), geolocation=(),
  interest-cohort=()
Aus /_headers. default-src 'none' heißt: Was nicht ausdrücklich erlaubt ist, wird nicht geladen.

Diese Seite: 21,3 kB HTML, 7,4 kB CSS — unkomprimiert; über die Leitung geht brotli-komprimiert etwa die Hälfte. 2 Anfragen insgesamt. Kein Skript, kein Cookie, kein Banner.