Was macht belay?
Du erreichst ein Ziel in vielen kleinen Schritten. Ein Check bewertet jeden Schritt ohne menschliches Eingreifen.
scripts/belay.py führt die Bewertung durch: Du bearbeitest, es führt den Check aus,
committed einen Gewinn oder macht einen Verlust rückgängig, und schreibt das Log. Du selbst notierst nie eine
Punktzahl, und du entscheidest nie, ob ein Schritt „im Grunde“ bestanden hat.
Jedes Ziel wird zum Gleichen: einem Befehl, der eine Zahl ausgibt. Schneller ist eine Zeit oder eine Anzahl. Ein Audit ist die Anzahl der fehlschlagenden Tests, einer pro Befund. Ein Port ist die Anzahl der übereinstimmenden Ausgaben. Eine UI ist die Bewertung eines Richters.
So arbeitest du:
- Der Benutzer startet einen Aufstieg und geht. Hör nicht auf, um Updates zu geben. Sie lesen drei Dinge: die Karte, eine Frage, die nur sie beantworten können, und den Bericht. Frage mit dem Frage-Tool der Umgebung, falls vorhanden.
- Der Zustand liegt auf der Festplatte, nicht im Chat. Die Karte, das Log, deine Notizen und
die letzte Check-Ausgabe befinden sich unter
.belay/<name>/. Nach einer Komprimierung oder einem Absturz gibt dirstatusalles auf einmal zurück. - Warte nie mit einer Sleep-Schleife. Führe lange Befehle im Hintergrund aus und plane den nächsten Schritt, während sie laufen.
BELAYunten ist der absolute Pfad vonscripts/belay.pyneben dieser Datei. Schreibe den vollständigen Pfad in jeden Befehl. Führe ihn aus dem Ziel-Repo aus. Pfade und Befehle, die du übergibst, sind relativ zum Repo-Root.- Der Aufstieg erhält seinen eigenen Branch,
climb/<name>. Ein rückgängig gemachter Schritt setzt den Baum zurück und löscht unverfolgte Dateien, die git nicht ignoriert. Wenn jemand anderes in diesem Checkout arbeitet, klettere in einem separaten Worktree. Übergib--here, wenn du bereits auf einem für diese Arbeit erstellten Branch bist.
1. Fortsetzen bevor du beginnst
Führe python3 "$BELAY" list aus. Wenn für dieses Ziel ein Aufstieg existiert, wechsle zu seinem
Branch, führe status <name> aus und fahre mit Schritt 4 fort. „Fortsetzen“ nach
einem Absturz oder einer neuen Sitzung bedeutet dies. Fang nicht von vorne an.
2. Erstelle den Check
Der Aufstieg ist nur so gut wie sein Check. Ein Check, der das Falsche misst,
verbessert während des gesamten Laufs das Falsche. Lass zuerst einen groben Check laufen
und schärfe ihn später mit relock.
Frage: Was würde ich ausführen, um zu sehen, dass das Ziel erreicht ist? Lass diesen Befehl eine Zahl ausgeben. Verwende die stärkste Form, die passt: einen exakten Match oder Testanzahl, dann eine Anzahl der Arbeit (Abfragen, Roundtrips, Bytes), dann eine Uhr und einen Modell-Richter nur, wenn nichts außer Geschmack entscheiden kann.
| Ziel | Punktzahl |
|---|---|
| Fehler oder Feature | Fehlschlagende Tests, geschrieben nach Spezifikation, nicht nach deinem Fix |
| Audit, stabilisieren, „X zum Laufen bringen“ | Fehlschlagende Tests, einer pro Befund |
| Geschwindigkeit oder Größe | Eine Anzahl der Arbeit hinter der Zeit, oder die Zeit |
| Port oder Klon | Ausgaben, die mit dem echten Tool übereinstimmen |
| Mehrere Ziele gleichzeitig | Fortschritt in Richtung der schlechtesten Hürde |
| Aussehen, Gefühl, Text | judge.py mit einer Bewertungsmatrix und guten Beispielen |
Rezepte für jedes Ziel findest du in references/checks.md. Lies den Teil, der zu deinem
Ziel passt, bevor du den Check schreibst.
Verwende, was das Repo hat. --score '<regex>' liest die Punktzahl aus der Ausgabe eines beliebigen
Test-Runners, z. B. --score '(\d+) failed'. Es nimmt die letzte übereinstimmende
Zeile und addiert die erfassten Zahlen. Ein erfolgreicher Lauf ohne Übereinstimmung ergibt eine Punktzahl von
0. Ohne --score muss die letzte Zeile der stdout des Checks die bloße
Zahl sein. Wiederhole --check, um mehrere Befehle gleichzeitig auszuführen; ihre Punktzahlen werden addiert.
Füge --repo <path> für jeden weiteren Checkout hinzu, den der Aufstieg bearbeitet. Ein Schritt wird dann
in allen gemeinsam behalten oder rückgängig gemacht.
Beweise den Check, bevor du ihm vertraust:
- Er kann fehlschlagen. Brich den Code absichtlich und sieh zu, wie die Punktzahl schlechter wird.
Stelle mit
git checkout -- <datei>wieder her. - Er kann einen Gewinn sehen. Eine kleine echte Verbesserung muss die Punktzahl verändern.
- Er ist stabil. Führe ihn 3 Mal aus. Wenn die Punktzahl ohne Codeänderung schwankt,
ersetze die Uhr durch eine Anzahl oder verwende
--runs 3, einen--min-gainüber der Schwankung (ein Prozent wie3%, wenn die Punktzahl stark sinken wird), und--paired. - Er kann nicht ausgetrickst werden. Variiere die Eingabe bei jedem Lauf und vergleiche mit einer Referenz. Versuche einen Betrug von Hand, wie das Hartcodieren der Antwort, und bestätige, dass der Check oder eine Wache ihn abfängt.
- Er ist schnell. Du bezahlst die Check-Zeit bei jedem Schritt. Bringe einen Schritt unter 2 Minuten: bewerte eine Stichprobe oder eine Anzahl pro Schritt und behalte die vollständige Suite oder den zeitgesteuerten Lauf als Wache oder als zurückgehaltenen Datensatz.
- Die Hürde ist erreichbar. Ermittle das Beste, was das aktuelle Design tun kann. Wenn die Hürde darüber liegt, sag es auf der Karte und schlage eine erreichbare Hürde vor.
Schütze alles, was die Punktzahl nicht misst:
- Wachen (
--guard, bestehen durch Exit-Code 0). Liste auf, was der Code, den du ändern wirst, berührt: Aufrufer, andere Plattformen, gespeicherte Daten, öffentliche APIs. Jedes benötigt eine Wache: die Tests, die heute bestehen, Typprüfung, Linting, der Build. Wenn die Punktzahl eine Anzahl von Fehlschlägen ist, behalte diese bestehenden Tests in ihren eigenen Dateien als Wache, damit ein Absturz nicht als „weniger Fehler“ durchgehen kann. - Sperre (
--lock) den Check, die Tests, die Testvorlagen und den zurückgehaltenen Datensatz.tryweigert sich zu bewerten, während eine gesperrte Datei abweicht. Neue Dateien unter einem--lock-Pfad werden zum ersten Commit auf dem Aufstiegsbranch. Jede andere nicht festgeschriebene Änderung stopptinit. - Zurückgehaltener Datensatz (
--holdout), wenn der Check Stichproben, einen Benchmark oder einen Richter verwendet: Fälle, die der Aufstieg nie trainiert, aufbewahrt unter.belay/<name>/holdout/. Öffne sie nicht wieder. Wenn die Punktzahl steigt und der zurückgehaltene Datensatz nicht, überanpasst sich der Aufstieg. Hör auf und sag es.
Audits und offene Ziele. Liste ab, was das Ziel abdeckt, als Checkliste in
.belay/<name>/notes.md. Suche Bereich für Bereich nach Fehlern. Schreibe einen
fehlschlagenden Test pro echtem Befund, gemäß der Spezifikation oder dem Fehlerbericht. Wenn ein späterer Schritt
einen neuen Fehler findet, füge seinen Test hinzu und führe relock --why "<fehler gefunden>" aus.
Die Punktzahl steigt aus einem ehrlichen Grund und das Log zeigt warum. Ein Befund, der die
Entscheidung des Benutzers benötigt, kommt in die Notizen und den Bericht, nicht in die Punktzahl.
3. Die Karte, dann init
Sende eine Nachricht mit der Karte und nichts anderem zur Entscheidung:
Aufstiegskarte:
build-speedZiel: Kalter Build 2x schneller, gleiche Ausgabe
Punktzahl Mittlere Build-Sekunden, niedriger ist besser: 47,0 jetzt, Hürde 23,5 Check ./scripts/bench-build.sh, 3 Läufe, gepaart, min. Gewinn 3%Wachen npm test,npm run typecheckZurückgehaltener Datensatz 3 der 12 Beispiel-Apps Gesperrt scripts/bench-build.sh,test/,samples/Limit keins (etwa 2 min pro Schritt) Benötigt deine Antwort: keine
Antworte los, oder ändere eine Zeile.
Fülle jede Zeile mit deiner besten Wahl. Wenn der Benutzer ein Ziel ohne Hürde angegeben hat, schlage eine vor, die ambitioniert und überprüfbar ist, wie „2x schneller“ oder „jedes Beispiel stimmt überein“. Warte auf „los“, das die Karte, den Branch und seine Commits genehmigt. Überspringe das Warten und setze die Karte an den Anfang des Berichts, wenn der Benutzer bereits gesagt hat, ohne Nachfragen zu laufen, oder wenn das Ziel klein ist und die Hürde nicht in Frage steht. Frage danach nichts, was du selbst herausfinden oder entscheiden kannst.
python3 "$BELAY" init build-speed --goal "kalter Build 2x schneller" \
--check ./scripts/bench-build.sh --direction min --target 2x \
--runs 3 --paired --min-gain 3% --guard "npm test" --guard "npm run typecheck" \
--holdout ./scripts/bench-holdout.sh --lock scripts --lock test \
--lock .belay/build-speed/holdout
Ein Audit über ein Backend und ein Frontend:
python3 "$BELAY" init billing-audit --goal "jeder Abrechnungsbefund behoben" \
--check "pytest tests/billing -q" --check "cd ../web && npx vitest run billing" \
--score '(\d+) failed' --direction min --target 0 --repo ../web \
--guard "pytest tests/legacy -q" --guard "cd ../web && npx tsc --noEmit" \
--lock tests/billing --lock ../web/src/billing/__tests__
init erstellt den Branch, misst die Basislinie und weigert sich zu starten, wenn eine Wache
bereits fehlschlägt. Behebe, wovor es warnt, vor dem ersten Schritt. Setze
--max-hours oder --max-steps nur, wenn der Benutzer ein Limit nennt. Ohne
eines läuft der Aufstieg, bis die Hürde erreicht ist oder er feststeckt.
4. Aufstieg
Jeder Schritt ist eine Idee, eine Änderung, ein try:
- Wähle die Idee. Wiederhole keine, die das Log bereits rückgängig gemacht hat, es sei denn, du kannst sagen,
was jetzt anders ist. Wenn Richter verwendet werden, lies
.belay/judge-notes.md. - Nimm eine Änderung aus einem Grund vor und schätze ihre Wirkung. Setze die Schätzung in
die Idee:
"Parser cachen (erwarte -10%)". Wenn eine Schätzung weit daneben liegt, ist dein Modell des Codes falsch. Erstelle ein Profil vor dem nächsten Schritt. python3 "$BELAY" try "<idee>". Es commitet einen Gewinn oder setzt den Baum zurück. So oder so, mach weiter. Die vollständige Check-Ausgabe des Schrittes befindet sich in.belay/<name>/last.txtund die des besten Schrittes inbest.txt. Lese diese anstatt den Check erneut auszuführen.- Während ein Check läuft, bearbeite den Baum nicht. Nur ein
belay.py-Befehl, der den Aufstieg ändert, läuft gleichzeitig. Wenn es sagt, dass ein anderer noch läuft, warte darauf. - Alle 5 Schritte aktualisiere
.belay/<name>/notes.mdin ein paar Zeilen: was funktioniert, was nicht, was als nächstes zu versuchen ist. Die nächste Sitzung setzt dort fort.
Wenn du an eine Idee glaubst, die der Check zweimal rückgängig gemacht hat, kann der Check sie nicht sehen.
Verfeinere den Check und führe relock aus. Bearbeite niemals eine gesperrte Datei, damit ein Schritt
besteht.
Betrüge niemals den Check
Jedes dieser Dinge erhöht die Punktzahl und macht die Arbeit schlechter. Jedes ist ein gescheiterter
Aufstieg, selbst wenn try es behält:
- Spezielle Behandlung der Eingaben, die der Check verwendet, oder Vorausberechnen oder Zwischenspeichern erwarteter Ausgaben.
- Überspringen, Abschwächen oder Löschen von Tests oder Abfangen und Verstecken von Fehlern.
- Den Benchmark weniger Arbeit erledigen lassen, anstatt den Code schneller zu machen.
- Verwenden von
relock, um einen schwierigen Fall fallen zu lassen oder aufzuweichen, damit die Hürde erreicht wird. Relock macht den Check nur korrekter. Wenn die Hürde nicht erreicht werden kann, berichte das von dir gemessene Minimum. - Lesen des zurückgehaltenen Datensatzes.
Ein echter Gewinn macht denselben Code besser für Eingaben, die der Check noch nie gesehen hat. Wenn der einzige Weg nach vorne einer dieser Punkte ist, ist der Check falsch. Sag es.
Bewerte ständig neu
Die Punktzahl steht nur stellvertretend für das, was der Benutzer will. Überprüfe, ob sie das immer noch tut:
- Alle 10 behaltenen Schritte und an der Hürde: Sieh dir die echte Sache selbst an.
Öffne die App, lies die Ausgabe, betrachte den Screenshot. Führe die vollständige Testsuite und den
holdoutaus. Wenn die Punktzahl und das echte Ding auseinandergedriftet sind, korrigiere den Check und führerelock --why "..."aus. - Etwas ist kaputtgegangen, das keine Wache abgefangen hat: Finde den Schritt mit
git bisect run <fehlschlagender befehl>, repariere ihn dann mittry --fix "<was kaputtging>", das eine Änderung behält, die die Punktzahl hält. Wenn die einzige Reparatur den Gewinn dieses Schrittes aufgibt, mache den Schritt mitgit revertrückgängig und führerelock --why "Schritt N rückgängig gemacht: hat X kaputtgemacht"aus. Füge die fehlende Wache hinzu. - Vor dem Bericht: Überprüfe
git diff <start>..HEADals eine Änderung mit frischen Augen. Suche nach entfernten Tests, verschluckten Fehlern, einer deaktivierten Funktion, einem geänderten Standardwert sowie Daten- und API-Änderungen. Repariere mittry --fix, führe dann den Check undholdout --why finalnoch einmal aus, damit der Bericht gemessene Zahlen zitiert.
5. Wenn es ins Stocken gerät
try und status geben PLATEAU aus, nachdem 5 Schritte keinen Gewinn gebracht haben. Hör auf,
Ideen auszuprobieren, und finde den Blockierer. Messe, bevor du schätzt:
- Woher kommt die Zeit oder die Fehleranzahl tatsächlich? Erstelle ein Profil.
- Ist der Check unzuverlässig, zu grob, um kleine Gewinne zu sehen, oder blind für das Problem?
- Gibt es eine größere Idee, die die kleinen Schritte nicht erreichen können?
- Welches Tool, welcher Zugriff, welche Daten oder welche Rechenleistung würden die nächsten zehn Schritte verändern?
Logge es mit python3 "$BELAY" review "<was du gefunden hast>", das PLATEAU
für 5 Schritte unterdrückt. Behebe, was du kannst: einen schnelleren Check, eine feinere Metrik, einen
anderen Ansatz. Frage den Benutzer nur nach dem, was nur er geben kann, wie
Zugriff oder Geld, und nur, wenn jede andere Idee erschöpft ist.
6. Anhalten und Bericht erstatten
Halte an, wenn einer dieser Punkte zutrifft:
trygibt BAR REACHED aus. Es führt den Holdout für dich aus. Ein sichtbarer Gewinn mit einem flachen Holdout ist kein Gewinn.statusgibt STUCK aus: zwei Blockierer-Reviews ohne Gewinn dazwischen.tryverweigert mit „Budget verwendet“.- Der Holdout widerspricht der Punktzahl.
- Der nächste Schritt erfordert etwas, das nur der Benutzer geben kann.
Führe dann die abschließende Überprüfung oben durch, lösche .belay/<name>/data/ und
sende den Bericht. Mach ihn in zehn Sekunden lesbar:
Aufstieg
build-speed: Hürde erreicht47,1s → 18,7s, 2,5x schneller (Hürde 23,5s, erreicht in Schritt 41)
Holdout 51,0s → 20,2s, hat sich mit der Punktzahl bewegt Schritte 19 von 52 behalten Sicherheit Wachen bei jedem behaltenen Schritt bestanden. Vollständige Suite und abschließende Überprüfung sauber Branch climb/build-speed, 19 CommitsWas funktioniert hat
- Inkrementeller Typ-Cache: −12s
Versucht und rückgängig gemacht
- swc-Austausch: 3 Wachen gebrochen
Dein nächster Schritt
- Überprüfung:
git log --oneline 1a2b3c4..climb/build-speed
Die Überschrift ist eine von: Hürde erreicht, festgesteckt, Budget aufgebraucht, Holdout widerspricht, benötigt dich. Zitiere Zahlen, die das Skript gemessen hat, niemals Schätzungen. Wenn du den Check oder die Hürde unterwegs geändert hast, sag es in der Überschrift. Größte Gewinne zuerst. Maximal 3 Aufzählungspunkte pro Abschnitt. Überspringe leere Abschnitte.
Wenn der Benutzer dann mehr möchte, setze eine härtere Hürde für dasselbe Anliegen mit
raise 2x --why "..." und klettere weiter. Wechsle niemals zu einem neuen Ziel.
Unteragenten
Wenn die Umgebung Unteragenten starten kann, verwende sie für paralleles Lesen während der
Einrichtung und für frische Augen beim Blockierer-Review und der abschließenden Überprüfung. Frage
nach Schlussfolgerungen, nicht nach Datei-Dumps. Nur du schreibst im Aufstiegsbaum,
weil try ihn zurücksetzt. Ein Helfer liest oder entwirft einen Patch in seinem eigenen
Worktree, den du anwenden und mit try testen kannst. Ohne Unteragenten mache es inline.
Befehle
| Befehl | Funktion |
|---|---|
init <name> --goal "..." --check "..." --direction min|max | Basislinie, Branch, Sperre. Optionen: --check (wiederholbar), --score '<regex>', --target (Zahl oder 2x), --guard (wiederholbar), --lock (wiederholbar), --holdout, --repo (wiederholbar), --runs, --paired, --min-gain, --timeout, --max-hours, --max-steps, --here |
try "<idee>" [--fix] | Bewertet die Bearbeitung, behält oder macht sie dann rückgängig. --fix behält eine Reparatur, die die Punktzahl hält |
status [name] | Punktzahl, letzte Schritte, Notizen, PLATEAU oder STUCK |
relock --why "..." | Akzeptiert einen geänderten Check und misst erneut |
holdout --why "..." | Führt den Holdout jetzt aus |
review "<gefunden>" | Protokolliert eine Blockierer-Überprüfung |
raise <hürde> --why "..." | Setzt eine härtere Hürde nach Erreichen dieser |
budget [--hours N] [--steps N] | Setzt oder zeigt das Budget |
abort [name] | Löscht den Aufstiegsbranch und die .belay-Daten. Ruft den ursprünglichen Branch aus, es sei denn, --keep-branch |
list | Listet vorhandene Aufstiege |
Referenzen
Siehe references/checks.md für Rezepte für jeden Zieltyp, references/architecture.md für
Hilfe beim Extrahieren und Separieren von Änderungen und references/debugging.md für
wiederkehrende Fehler. Lies sie, wann immer eine Situation passt.
Zusammenfassung der Änderungen (für Kontext: sie sind bereits im Repo)
scripts/belay.py(das Hauptskript) und diese DateiSKILL.mdleben im Root eines Repos, das für die Zusammenarbeit mit KI-Agenten (Agentic Repo) gedacht ist, z. B. einem Fork vongithub.com/belweave/claude-code-agentic-workflow. Der PfadBELAYunten wird automatisch relativ zu diesem Repo gesetzt.- Der Benutzer hat möglicherweise bereits ein Agentic Repo eingerichtet, das Tools und Regeln für die langfristige Arbeit mit KI-Agenten enthält. Dieses Skill ist ein Teil davon.
- Vorhandene Skills/CLAUDE.md, die aufgaben- oder repo-spezifisch sind, können den Prozess überschreiben oder ergänzen. Diese Datei (SKILL.md) sollte als primäre Anleitung für Aufstiegs-Workflows angesehen werden.
Was macht belay?
Der absolute Pfad von scripts/belay.py relativ zum Root dieses Repos.
BELAY = os.path.abspath(os.path.join(os.path.dirname(__file__), "scripts", "belay.py"))
Ersetze in deinem Kopf "$BELAY" durch diesen absoluten Pfad, wenn du den Befehl in der
Shell / im Terminal ausführst.