Zum Inhalt springen

KI-Skill (findsl-author)

findsl-author ist ein Agent Skill im offenen Agent-Skills-Format. Installiert in einem KI-Coding-Agenten (Claude Code, OpenCode, Codex) verwandelt er zwei Eingabearten in valides, getestetes FinDSL:

  • Pfad A — Alltagssprache. Eine formlose Beschreibung („Die Steuer ist 14 % vom Bruttolohn, abzüglich eines Freibetrags von 10.000 € im Jahr, mindestens 0, auf volle Euro abrunden.”).
  • Pfad B — Gesetzestext. Ein Paragraph, ein Gesetz-Wortlaut, ein §-Zitat.

Beide münden in dieselbe Architektur und dieselben prüfe-Tests. Der Skill bringt einem Modell die Sprach-Guardrails bei (Geld-Literale, Rundung, Namenskonventionen), die Architektur-Bausteine (konst → datensatz → Stufen-fn → Orchestrator) und die goldene Regel: exakt rechnen, Lücken benennen, nie raten.

Das Skill-Bundle (findsl-skills-v<version>.zip) liegt bei jedem Release. Setze in den Befehlen unten für <version> die aktuelle Version ein (derzeit 1.2.0) — den fertigen Befehl mit eingesetzter Version bietet die Downloads-Seite. Nach dem Download in das Skill-Verzeichnis des Agenten entpacken — eine Datei, kein Paketmanager.

Terminal-Fenster
# global (gilt überall):
unzip findsl-skills-v<version>.zip -d ~/.claude/skills/
# oder projektweit:
unzip findsl-skills-v<version>.zip -d .claude/skills/
Terminal-Fenster
unzip findsl-skills-v<version>.zip -d ~/.config/opencode/skills/

OpenCode entdeckt Skills auch aus .opencode/skills/, .claude/skills/ und .agents/skills/ (projektweit) sowie den entsprechenden Ordnern unter ~/.config/opencode/, ~/.claude/ und ~/.agents/.

Terminal-Fenster
unzip findsl-skills-v<version>.zip -d ~/.agents/skills/

Der Skill ist mit einer direkten Beschreibung versehen: er wird automatisch aktiv, sobald die Anfrage FinDSL betrifft („modelliere § … in FinDSL”, „bau aus dieser Regel ein FinDSL-Modul”, „schreib eine prüfe-Datei dazu”). Ein expliziter Aufruf ist nicht nötig.

Schreibe einfach, was berechnet werden soll. Fehlt eine Information (Reihenfolge, Schwelle, Rundung, Einheit), fragt der Agent gezielt zurück, statt eine Annahme zu verstecken. Wer „nimm sinnvolle Defaults” sagt, bekommt die getroffene Annahme im Doc-Block des Moduls sichtbar dokumentiert.

Liefere einen §-Auszug, einen Gesetzeswortlaut oder ein juristisches Zitat. Der Agent bindet jede Stufe per @Quelle("§ …") zurück an die Norm und teilt bei mehreren Bereichen auf mehrere Dateien auf. Kumulative Staffelwerte werden abgeleitet (KUM_3000 = KUM_2000 + 2000_3000 * 5), nicht handsummiert — damit die Rechnung auditierbar bleibt.

Ein realistischer Wechsel — formlose Regel rein, getestetes FinDSL-Modul raus. Der Dialog folgt dem mit parse (0 Diagnosen) und test (3/3) verifizierten Mini-Beispiel aus den Skill-Vorlagen.

Du

Bau mir ein kleines FinDSL-Modul für eine vereinfachte Umsatzabgabe: 2 % vom Umsatz, aber nur ab 10.000 € Umsatz fällt die Abgabe an. Auf volle Euro abrunden.

findsl-author

Zwei Annahmen, die ich oben sichtbar dokumentiere, damit du sie ggf. korrigieren kannst:

  1. Der Umsatz geht als geprüfte Eingabe in vollen Euro ein.
  2. „Auf volle Euro abrunden” verstehe ich als kaufmännisches Abrunden auf Euro — die rohe EuroCent-Größe umsatz * 2% runde ich an einer typgebundenen var: Euro.
-- abgabe.findsl --
--
# Umsatzabgabe — 2 % über einer Freigrenze
Einfache Abgabe: 2 % vom Umsatz, aber nur ab 10.000 € Umsatz; Ergebnis auf
volle Euro abgerundet.
**Bewusst nicht modelliert / angenommen:**
- Der Umsatz geht als geprüfte Eingabe (volle Euro) ein.
- „Abrunden" wurde als kaufmännisches Abrunden auf volle Euro angenommen.
--
-- Abgabesatz: 2 % des Umsatzes. --
konst SATZ: Prozent = 2%
-- Freigrenze: unterhalb dieses Umsatzes fällt keine Abgabe an. --
konst FREIGRENZE: Euro = 10.000
-- Eingaben des Abgabefalls. @param umsatz Jahresumsatz (volle Euro). --
datensatz AbgabeFall(umsatz: Euro)
--
Abgabe nach Freigrenze und Satz, auf volle Euro abgerundet.
@param fall Abgabefall.
@rückgabe Abgabe in vollen Euro.
--
fn Abgabe(fall: AbgabeFall): Euro = {
var roh: EuroCent = wähle {
falls fall.umsatz < FREIGRENZE -> 0,00
sonst -> fall.umsatz * SATZ
}
var betrag: Euro = roh.abrunden() // Rundung an typgebundener var
betrag
}
-- abgabe.test.findsl --
--
# Tests Umsatzabgabe (Sollwerte von Hand gerechnet).
--
verwende { AbgabeFall, Abgabe } aus "./abgabe"
prüfe "Umsatzabgabe" {
testfall "knapp unter Freigrenze: keine Abgabe" {
Abgabe(AbgabeFall(umsatz = 9.999)) == 0
}
testfall "an der Freigrenze: 2 % von 10.000 = 200" {
Abgabe(AbgabeFall(umsatz = 10.000)) == 200
}
testfall "Abrundung: 2 % von 50.001 = 1.000,02 → 1.000" {
Abgabe(AbgabeFall(umsatz = 50.001)) == 1.000
}
}
findsl-author

Verifikation:

$ findsl parse abgabe.findsl abgabe.test.findsl
⚠ abgabe.findsl: 2 Warnungen
13:7 warning Konstante "SATZ" hat keine @Quelle-Annotation.
16:7 warning Konstante "FREIGRENZE" hat keine @Quelle-Annotation.
✓ abgabe.test.findsl erfolgreich geparst, keine Diagnosen.
— 2 Dateien geprüft, 0 mit Fehlern —
$ findsl test abgabe.test.findsl
✓ abgabe.test.findsl: 3/3 bestanden

Die zwei @Quelle-Warnungen sind im Pfad A erwartbar — ohne Gesetzesbezug gibt es keine Norm zum Zitieren. Sobald du eine Norm-Fundstelle hast (Pfad B), kommen @Quelle("§ …")-Zeilen vor konst und fn, und die Warnungen verschwinden. Wenn du Cent-Genauigkeit willst, dreh den Rückgabetyp auf EuroCent und entferne den .abrunden()-Schritt — die Annahmen oben sind eine Einzeiler-Änderung.

Bei einem §-Zitat geht jeder Wert über @Quelle("§ …") an die Norm zurück. Aufrundungs- oder Staffel-Regeln werden so umgesetzt, wie sie dort wörtlich stehen.

Du

§ 11 Abs. 1 Satz 3 GewStG: „Der Gewerbeertrag ist auf volle 100 Euro nach unten abzurunden.” Mach mir eine kleine FinDSL-Funktion daraus, die das anwendet.

findsl-author
-- gewerbeertrag.findsl --
--
# § 11 Abs. 1 Satz 3 GewStG — Abrundung des Gewerbeertrags auf volle 100 €.
--
-- Rundungsstufe nach § 11 Abs. 1 Satz 3 GewStG. --
@Quelle("§ 11 Absatz 1 Satz 3 GewStG")
konst RUNDUNGSSTUFE: Euro = 100
--
Rundet den Gewerbeertrag auf volle 100 € nach unten ab.
@param ertrag Gewerbeertrag vor Rundung.
@rückgabe Gewerbeertrag auf volle 100 € abgerundet.
--
@Quelle("§ 11 Absatz 1 Satz 3 GewStG")
fn RundeGewerbeertragAb(ertrag: Euro): Euro =
ertrag.abrundenAuf(RUNDUNGSSTUFE)

Das ist alles, was die Norm sagt — und alles, was im Modul steht. Der Rest (Hebesatz, Messzahl, Freibeträge) gehört in eigene fns mit eigener @Quelle.

Der Skill ist erst dann fertig, wenn beide Befehle grün laufen:

Terminal-Fenster
# 1. Modul + Test parsen ohne Fehler:
findsl parse abgabe.findsl abgabe.test.findsl
# 2. Alle prüfe-Fälle bestehen:
findsl test abgabe.test.findsl

Bei Fehlern rechnet der Skill die Soll-Werte gegen die Regel nach — niemals werden Tests „passend gebogen”. Eine @Quelle-Warnung für gesetzlose Konstanten (im Pfad A) ist erwartbar und kein Fehler.

Der Skill bringt vier Referenz-Dateien mit, die das Modell vor dem Schreiben liest:

DateiInhalt
sprache-referenz.mdTypen, Geld-Arithmetik, Rundung, Fallstrick-Tabelle, Helfer
vorlagen.mdkommentierte Skelette + verifiziertes Mini-Beispiel
workflow-alltagssprache.mdPfad A — von der Prosa zum Modul
workflow-gesetz.mdPfad B — vom Gesetzestext zum Modul + Mehrdatei-Schnitt

Jedes Modul folgt demselben Schema: konst je Regelwert · aufzählung je Klassifizierung · <X>Fall/<X>Ergebnis-Datensätze · Stufen-fns · Helfer · Orchestrator. So entstehen kleine, einzeln testbare Funktionen — und Audit-fähige Zwischengrößen, statt einer Black-Box-Formel.