hasenbau

command
v0.0.0-...-3064ea2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 20, 2026 License: EUPL-1.2 Imports: 38 Imported by: 0

Documentation

Overview

bau.go: `hasenbau describe bau` — die Diagnose (Hasenbau-ha0.6).

Zwei verschiedene Fragen, deshalb zwei Befehle. Hier: **ist dieser Bau in Ordnung?** Bei `status`: was liegt hier und was ist passiert. Der Unterschied ist nicht kosmetisch — eine Diagnose darf Fehler melden und tut das laut, ein Dashboard soll nur zeigen.

baumeister.go: `hasenbau baumeister <ziel>` setzt den Baumeister auf einen Lauf an (PLAN.md §8, Phase 2).

Der Befehl ist bewusst dünn. Der Baumeister ist kein Sonderpfad im Code, sondern ein ganz normaler Auftrag mit einem ganz normalen Hasen — sein Material sind nur keine PDFs, sondern Läufe, und seine deterministische Vorverarbeitung ist ein Gang wie jeder andere. Was hier passiert: den Auftrag aus hasenbau.yaml holen, das Ziel zu einer Lauf-ID auflösen, den Lauf fahren und hinterher sagen, was in den out-Raum geschrieben wurde.

Was hier NICHT passiert: aktivieren. Der Baumeister hat auf auftraege/ kein Schreibrecht (die Permissions des generierten Agenten kommen aus den Räumen, §6), und dieser Befehl trägt nichts ein. PLAN.md §8/§10: ein gegrabener Gang wird nie automatisch scharf geschaltet.

definitionen.go: die lesende Sicht auf das, was im Bau definiert ist — Aufträge, Hasen und die Gang-Dateien, die sie benutzen.

Zwei Dinge stehen hier, die in keiner Datei stehen und deshalb der eigentliche Grund für `describe` sind: welche Räume eines Auftrags Schreibrecht geben, und welche Permissions ein Hase in einem konkreten Auftrag effektiv hat (die entstehen erst aus dessen Räumen, PLAN.md §6).

describe.go: das erklärende Verb der CLI (Hasenbau-ha0).

`describe` ist kein `cat`. Es zeigt ein Objekt gerendert, samt allem, was der Hasenbau darüber hinaus darüber weiß — bei einem Lauf also die Notizen aus dem Rückkanal, die sonst nur als Beifang von `dig` sichtbar wären. Dateien gibt es nie im Volltext aus; wer sie will, bekommt den Pfad genannt.

dockerfile.go beantwortet die Frage, die das README bisher als Fließtext beantwortet hat: **was muss installiert sein, damit ein Bau läuft?** (Hasenbau-sss)

Die Liste ist deshalb interessant, weil ihr Fehlen still ist. Ohne `bwrap` registriert das Plugin kein einziges Werkzeug — fail-closed, und nur der Daemon-Log sagt es. Ohne Git-Commit bekommt der Bau keine Projekt-ID und die Raum-Permissions greifen nicht (§11.5). Ohne `tzdata` nimmt `cron.New()` die Zeitzone des Containers, und das ist UTC: ein `0 10 * * *` feuert dann um zwölf.

Grenze, und sie ist bewusst: hier steht nur, was **Hasenbau** ruft. Was der Bau ruft — `pdftotext` für einen Gang, ein MCP-Server — kennt der Hasenbau nicht und rät es auch nicht. Dafür trägt die erzeugte Datei einen markierten Block am Ende.

findings.go: `hasenbau findings <auftrag>` — was sich über die Läufe eines Auftrags rechnen lässt (PLAN.md §8 Phase 2, Hasenbau-4cx.2).

Kein opencode-Server, kein Modell: die Zahlen liegen in der Bau-DB. Das ist der Punkt — das Anschauen kostet nichts, ist reproduzierbar, und jeder Vorschlag nennt die Läufe, auf denen er beruht. Ausgesucht wird von Hand; ausgearbeitet vom Baumeister, aber erst danach.

get.go: das lesende Verb der CLI (Hasenbau-ha0). `hasenbau get <ressource>` zeigt, was der Bau kennt — angelehnt an kubectl, damit die Befehle einem Schema folgen statt einzeln zu wachsen. Die Verben zum Auslösen (`lauf`, `baumeister`, `daemon`) bleiben davon unberührt.

lauf.go: der einmalige Lauf aus der CLI. `hasenbau lauf` und `hasenbau baumeister` teilen sich denselben Aufbau — DB auf, verwaiste Läufe schließen, Definitionen laden, Rückkanal eintragen, eigener Server hoch — und unterscheiden sich nur darin, welchen Auftrag sie womit ansetzen.

hasenbau ist das CLI und der Daemon (PLAN.md §2, §8 Phase 0).

new.go: das anlegende Verb der CLI (Hasenbau-ha0.8).

`get` zeigt Zeilen, `describe` zeigt ein Objekt, `new` legt eines an. Das Frontmatter-Schema kennt der Hasenbau — der Mensch soll es nicht auswendig können müssen. Deshalb entsteht hier kein leeres Blatt, sondern ein Gerüst, das seine Felder selbst erklärt: Pflichtfelder ausgefüllt, alles Optionale auskommentiert daneben.

Zwei Regeln: Der Befehl überschreibt nie (eine handgeschriebene Datei zu ersetzen bleibt eine bewusste Handlung), und er prüft, was er geschrieben hat — ein Gerüst, das nicht lädt, wäre ein Fehler des Hasenbaus, nicht des Nutzers.

probelauf.go sperrt den Probelauf eines Schmied-Werkzeugs ein (Hasenbau-9w6).

NICHT zu verwechseln mit `sandbox.go` daneben: dort geht es um den Sandbox-Wächter im Server-Prozess, der einem HASEN auf die Finger sieht (PLAN §6, Hasenbau-d2p). Hier geht es um die Bedingungen, unter denen ein MENSCH ein noch ungeprüftes Skript einmal laufen lässt.

Der Anlass ist eine Frage von Moritz: „wenn das malicious code ist, dann wird tool test den ja ausführen, was haben wir damit gewonnen?" Die ehrliche Antwort war: nichts. `tool test` ist gegen bösartigen Code keine Abwehr, sondern die Ausführung — und der Weg dorthin ist real (ein Hase liest fremdes Material, darin steht ein eingeschleuster Auftrag, er stellt einen Werkzeug-Wunsch, der Schmied baut, was im Wunsch steht).

Was der Sandkasten leistet: er nimmt dem Probelauf das Netz, den Rest des Dateisystems und jedes Schreibrecht. Damit fällt auch auf, wenn ein Werkzeug heimlich nach draußen telefoniert — das ist etwas anderes als „es stürzt nicht ab".

Was er NICHT leistet: das freigegebene Werkzeug läuft im Betrieb weiterhin ungesandboxed im opencode-Prozess. Ein Sandkasten um die Probe schützt die Probe, nicht den Betrieb; letzteres ist ein eigener Entwurf zu PLAN §3 und offen.

Und er hat einen Preis, der in PLAN §4 steht und hier den Schalter begründet: ein Sandkasten ändert das Ergebnis. Ein Werkzeug, das legitim schreibt oder eine Datei außerhalb des Baus liest, scheitert darin — und dann prüft man etwas anderes als den Ernstfall.

sandbox.go: `hasenbau sandbox-incident` — die Gegenstelle des Sandbox-Wächters (Hasenbau-d2p).

Der Wächter ist ein opencode-Plugin und sitzt im Server-Prozess; er sieht jeden Werkzeug-Aufruf, auch den eines Subagenten. Entscheiden darf er nichts: er meldet hierher und tut, was zurückkommt. Damit bleibt die Sandbox-Regel im Hasenbau und überlebt einen Wechsel des Backends (PLAN.md §6) — nachzubauen wäre dann ein dünner Hook, keine Semantik.

Exit-Codes sind die Antwort an den Wächter:

3  abweisen. Was auf stdout steht, bekommt der Hase als Fehlertext
   seines Werkzeugs zu lesen (verifiziert 2026-08-12: der Text
   kommt beim Modell an und ist dort verwertbar).
0  durchlassen. Gemeldet wurde trotzdem.
1  der Vorfall konnte nicht verbucht werden — der Wächter loggt das
   und lässt durch. Ein Wächter, der Läufe umbringt, wird
   abgeschaltet und misst dann gar nichts mehr.

tool.go: `hasenbau tool test <name> [--arg wert …]` (Hasenbau-kf5).

Der Befehl schließt die Lücke, die der erste echte Schmied-Lauf gezeigt hat. Der Schmied lieferte ein Werkzeug samt tadellosem Manifest, und nichts in der Kette merkte, dass es nicht läuft: das Manifest war gültig, `get tools` führte es klaglos, die Diagnose meldete „1 im Entwurf". Erst der Aufruf gegen eine echte Datei brachte einen TypeError zutage — und nach dessen Behebung einen Parser, der reale PDFs nicht liest.

Die Ursache steckt im Zuschnitt: der Schmied hat `bash: deny` wie jeder Hase und kann sein Skript kein einziges Mal ausführen. Wir verlangen Code und nehmen zugleich jede Möglichkeit, ihn zu probieren. Bis das anders ist, gehört der eine Probelauf dorthin, wo ohnehin ein Mensch steht: an die Freigabe.

SEIT Hasenbau-lnk gibt es doch einen Vergleich — aber gegen etwas anderes, als hier einmal ausgeschlossen wurde. Der Einwand von damals steht und ist nicht widerlegt: die ERWARTUNG DES LESERS lässt sich nicht ins Manifest schreiben, und ein Test, der nur fragt „stürzt es ab?", meldet nach der ersten Korrektur grün.

Verglichen wird deshalb nicht mit dem Urteil des Lesers, sondern mit der VORHERSAGE DES SCHMIEDS (`example.expect`). Das ist eine schwächere Aussage und genau deshalb tragfähig: sie bindet niemanden außer den, der sie gemacht hat. Weicht die Ausgabe ab, hat sich das Modell über sein eigenes Skript geirrt — das darf eine Maschine feststellen, und es macht `invalid`. Stimmt sie überein, ist damit NICHTS bewiesen: Vorhersage und Skript stammen aus derselben Feder. Der Zustand bleibt `hypothetical`, das Urteil fällt weiterhin ein Mensch bei `release`.

Der praktische Anlass war eine Frage von Moritz, auf die es keine gute Antwort gab: welche Datei soll ein Mensch beim Probelauf eigentlich angeben? Das weiß nur der Hase, der das Werkzeug angefordert hat, und der steht beim Review nicht daneben.

WAS DIESER BEFEHL NICHT IST: eine Sicherheitsprüfung. Er FÜHRT das Skript AUS. Seit Hasenbau-9w6 tut er das im Sandkasten (probelauf.go: kein Netz, Bau nur lesbar, kein $HOME, Zeitlimit), und das ist eine echte Grenze — aber keine Prüfung. Er findet Fehler, keine Absichten, und das freigegebene Werkzeug läuft später ungesandboxed im Server-Prozess.

Das ist keine Spitzfindigkeit, denn der Weg dorthin ist real: ein Hase liest fremdes Material (eine PDF, eine Notiz), darin stehen eingeschleuste Anweisungen, er stellt daraufhin einen Werkzeug-Wunsch, und der Schmied baut, was im Wunsch steht. Am Ende dieser Kette liegt Python, das im Server-Prozess laufen soll.

Die Reihenfolge lautet deshalb LESEN, dann probieren, dann freigeben — nicht umgekehrt. Ein Befehl, der das Ausführen bequem macht, verführt dazu, das Lesen zu überspringen; dagegen hilft nur, es überall hinzuschreiben, wo jemand vorbeikommt (hier, in `describe bau`, im README und in der Ausgabe des Befehls selbst). Der Sandkasten nimmt dem Versäumnis inzwischen die Spitze, ersetzt das Lesen aber nicht: er hält den Probelauf klein, nicht den Betrieb.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL