This repository has been archived on 2026-09-17. You can view files and clone it, but you cannot make any changes to its state, such as pushing and creating new issues, pull requests or comments.
nixos-config/docs/intent/board-session-usage-indicator.md
pijukka 41e05ed43f board: automatic escalation ladder for limit_reached Builder retries
The Operator's ===OPERATOR-DECISION=== schema gains an optional
"escalation" field (<=2 steps of model/reasoning_effort/iteration_limit,
validated against a new per-runtime orchestration.MODEL_POOL allowlist):
per-parent for direct_builder, per-child for split. On limit_reached,
completion_watcher.py now walks this ladder (via the shared
fanout.escalation_ladder_for()) instead of a single flat identical-params
retry, escalating model/iteration_limit before falling back to today's
manual repair/Aufteilen-angefordert checkpoints. A card that never went
through the Operator keeps its existing flat single-retry behavior
unchanged. orchestration.child_failed(), fanout.child_terminal(), and
trigger.py's Aufteilen-angefordert guard all switch from the old hardcoded
">= 1" threshold to the card's actual ladder length. board.html surfaces
the current attempt count on affected cards.

Also includes the board-session-usage-indicator research writeup (Codex
app-server JSON-RPC + Claude /api/oauth/usage as the two non-interactive
usage sources) and its Operator-produced child intents, plus the
operator_klaerung_noetig phase-visibility fix already staged in this
checkout (distinct phase for a needs_human/crashed Operator run that never
produced children, instead of reusing "durch_kinder_blockiert").

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SyeDivnWm6hgiNd3YKjK7Z
2026-09-10 13:58:52 +02:00

7.7 KiB

Intent: Anzeige der verbleibenden Claude-/Codex-Sitzungslimits im Intent-Board

Ziel

Ein kleines, dauerhaft sichtbares UI-Element im Intent-Board (z. B. in der Kopfzeile neben Titel/Untertitel), das anzeigt, wie viel Prozent des aktuellen Nutzungslimits für Claude Code und für Codex CLI noch übrig sind — für die eine interaktive drone-Identität, deren Login/Kontingent von den meisten Board-Rollen gemeinsam genutzt wird (Reviewer/Researcher/ Planner über Claude, Builder/Worker/Agent über Codex; siehe board-agent.nixs eigene Kommentare zu diesem geteilten Login-Tradeoff). Zweck: auf einen Blick sehen, ob gerade noch Spielraum für weitere Board-Läufe ist, bevor eine Karte losgeschickt wird.

Rechercheergebnis (geklärt, 10.09.2026)

Live auf blunix nachrecherchiert (interaktive Klärung mit dem Operator, 10.09.2026), nachdem der ursprüngliche Rechercheversuch vom 09.09.2026 (reine --help/doctor-Prüfung) korrekt feststellte, dass keine der offensichtlichen CLI-Unterprozeduren einen Prozentsatz liefert. Ein tieferer Blick fand für beide Runtimes eine echte, nicht-interaktive Quelle:

Codex: codex app-server (dokumentiertes, wenn auch als „[experimental]" markiertes CLI-Subcommand) beantwortet über sein Stdio-JSON-RPC-Protokoll die Methode account/rateLimits/read nach einem initialize-Handshake, ohne dass eine interaktive Sitzung nötig ist — live getestet, Antwortzeit deutlich unter einer Sekunde. Die Antwort enthält rateLimits.primary.usedPercent (5-Stunden-Fenster, windowDurationMins: 300) und rateLimits.secondary.usedPercent (Wochenfenster, windowDurationMins: 10080), je mit resetsAt (Unix-Timestamp). Eine bereits laufende codex app-server-Instanz ist dafür nicht nötig; ein kurzlebiger Kindprozess pro Abfrage reicht. Einschränkung: codex app-server schreibt beim Start in mehrere Dateien im eigenen CODEX_HOME (u. a. logs_2.sqlite, goals_1.sqlite, state_5.sqlite, models_cache.json, Plugin-/Skill-Cache) — kein enger, vorhersagbarer Satz, sondern praktisch der gesamte Home-Baumstand. Da board-agent-trigger.service mit ProtectHome = "read-only" läuft, ist ein direkter Aufruf gegen das echte /home/drone/.codex nicht schreibfähig. Entscheidung: ein eigenes, dauerhaftes, beschreibbares Probe-CODEX_HOME unterhalb des Board-Agent-State-Verzeichnisses anlegen (kein neuer ProtectHome-Downgrade), dessen auth.json vor jeder Anfrage frisch aus /home/drone/.codex/auth.json kopiert wird — nicht nur einmalig beim Servicestart wie beim bestehenden prepareCodexHome-Muster für die isolierte Builder-Identität, weil dieser Dienst dauerhaft läuft (Restart = "always") und ein zwischenzeitlich rotiertes Token sonst erst nach einem Neustart wieder funktionieren würde. Die Kopierkosten (wenige KB) sind gegenüber dem ohnehin unter einer Sekunde liegenden RPC-Aufruf vernachlässigbar, bei einem Frontend-Poll-Intervall von rund 60 Sekunden erst recht.

Claude: Es gibt kein offizielles CLI-Subcommand analog zu codex app-server. claude auth status --json liefert Konto-Metadaten (u. a. subscriptionType), aber keinen Prozentsatz. Ein Blick in die Strings des installierten claude-Binaries (.claude-wrapped, aktuell Version 2.1.257) zeigt jedoch echte, im Client verdrahtete API-Oberflächen: HTTP-Antwort-Header nach dem Muster anthropic-ratelimit-unified-5h-utilization / anthropic-ratelimit-unified-7d-utilization (analog zu Codex' primärem/ sekundärem Fenster) sowie den Pfad /api/oauth/usage. Live getestet mit dem in ~/.claude/.credentials.json gespeicherten OAuth-Access-Token (Authorization: Bearer …, zusätzlich Header anthropic-beta: oauth-2025-04-20, gefunden als Literal-String im selben Binary) gegen https://api.anthropic.com/api/oauth/usage: Antwort 200 OK mit direkt nutzbarem JSON-Body, u. a. five_hour.utilization (Prozentzahl, 5-Stunden-Fenster), seven_day.utilization (Prozentzahl, Wochenfenster) und je einem resets_at-ISO-Zeitstempel — keine Header-Auswertung nötig. Zum Vergleich probeweise auch das offizielle, öffentliche und kostenlose /v1/messages/count_tokens aufgerufen: authentifiziert erfolgreich (kein 401), aber im Test mit 404 auf ein veraltetes Modellkürzel gescheitert und selbst korrekt beantwortet nur die Rate-Limit-Header, nicht diesen direkt nutzbaren Body. Entscheidung: /api/oauth/usage verwenden, trotz des Risikos eines undokumentierten, privaten Endpunkts — bewusst dieselbe Abwägung wie bei Codex' selbst als „[experimental]" markiertem app-server. Der Aufruf braucht keinerlei Schreibzugriff (nur Lesen von ~/.claude/.credentials.json, das bestehende ProtectHome = "read-only" reicht) und board-agent-trigger hat schon heute uneingeschränkten ausgehenden Netzwerkzugriff — hier ist also keine Sandbox-Anpassung nötig, anders als bei Codex.

Damit ist die ursprünglich blockierende Recherche abgeschlossen und beide Quellen sind bestätigt nicht-interaktiv, ohne TUI-Sitzung abrufbar.

Umfang

  • Neuer, ausschließlich lesender API-Endpunkt in board-agent/trigger.py (GET /api/board/usage):
    • Codex-Seite: auth.json aus /home/drone/.codex in ein eigenes, dauerhaftes Probe-CODEX_HOME unterhalb des Board-Agent-State- Verzeichnisses kopieren, codex app-server als kurzlebigen Kindprozess starten, initialize + account/rateLimits/read per Stdio-JSON-RPC senden, rateLimits.primary.usedPercent und rateLimits.secondary.usedPercent auslesen.
    • Claude-Seite: Access-Token aus ~/.claude/.credentials.json lesen, GET https://api.anthropic.com/api/oauth/usage mit Authorization: Bearer … und anthropic-beta: oauth-2025-04-20 aufrufen, five_hour.utilization und seven_day.utilization auslesen.
    • Der Endpunkt gibt ausschließlich die berechneten Prozentwerte (plus optional die resets_at-Zeitstempel) zurück — nie Access-Tokens, rohe Limit-/Dollar-Felder oder sonstige Rohdaten an das Frontend durchreichen.
    • Schlägt eine der beiden Quellen fehl, liefert der Endpunkt für genau diese Seite eine Leerdarstellung statt den ganzen Aufruf fehlschlagen zu lassen — die jeweils andere Quelle bleibt unabhängig nutzbar.
  • Kleines, unauffälliges UI-Element in board-agent/board.html (Kopfzeile oder schmale eigene Leiste), das den Endpunkt periodisch abruft (alle 60 Sekunden) und knapp anzeigt, etwa „Claude: 60 % übrig · Codex: 0 % übrig". Kein neuer Dialog, keine eigene Spalte.
  • Bei fehlender/nicht auslesbarer Quelle: klare, unaufdringliche Leerdarstellung (z. B. „—") statt eines falschen oder geratenen Werts.

Explizit ausgeschlossen

  • Keine historische Verlaufsanzeige/Graph über die Zeit — nur der aktuelle Momentanwert.
  • Keine Alarmierung/Benachrichtigung bei niedrigem Kontingent (z. B. XMPP-Nachricht) — reine passive Anzeige in diesem Schritt.
  • Keine Aufschlüsselung pro Rolle/Spalte (Reviewer vs. Builder vs. Researcher) — ein einziger Wert je Anbieter (Claude, Codex) für die eine geteilte Identität.
  • Keine Änderung an den Board-Spalten/Trigger-Logik — rein additiv.

Annahmen

  • Die relevante Zahl bezieht sich auf die geteilte interaktive drone-Identität (ein Login, viele Rollen), nicht auf einen hypothetischen Wert pro Rolle/Secret.
  • Ein grober, klar als Schätzung gekennzeichneter Näherungswert ist besser als gar keine Anzeige, aber nur falls das Rechercheergebnis keine echte Quelle findet — Priorität liegt auf einer echten Zahl, falls verfügbar.

Erfolgskriterien

  • Das Board zeigt einen aktuellen, unaufdringlichen Prozentwert für Claude und für Codex (oder eine klare Leerdarstellung, falls technisch nicht möglich).
  • Keine Secrets/Tokens/Rohdaten verlassen den Server-Endpunkt.
  • Die Anzeige aktualisiert sich automatisch, ohne dass die Seite neu geladen werden muss.