add zeroclaw hardware preflight and orchestration docs (#19)

This commit was merged in pull request #19.
This commit is contained in:
Clément SAILLANT
2026-02-21 01:24:35 +01:00
committed by GitHub
parent b89cda78c2
commit 7f0697b194
4 changed files with 162 additions and 0 deletions
+5
View File
@@ -218,6 +218,11 @@ _pkginfo.txt
# Visual Studio cache files # Visual Studio cache files
*.[Cc]ache *.[Cc]ache
# ZeroClaw local runtime (generated locally, never committed)
/.zeroclaw/
/config.toml
/workspace/
!?*.[Cc]ache/ !?*.[Cc]ache/
# Others # Others
+8
View File
@@ -79,6 +79,14 @@ _Agent Repo & GitHub README généré automatiquement._
5. Ouvrir le moniteur série à 115200 bauds. 5. Ouvrir le moniteur série à 115200 bauds.
6. Connecter puis piloter les appels via commandes série. 6. Connecter puis piloter les appels via commandes série.
## Orchestration ZeroClaw (préflight + agent)
- Guide: `docs/zeroclaw_orchestration.md`
- Préflight hardware avant upload:
- `python3 scripts/zeroclaw_hw_preflight.py --require-port`
- Conversation agent ciblée RTC (depuis `Kill_LIFE`):
- `tools/ai/zeroclaw_dual_chat.sh rtc -m "fais un état hardware et propose 3 actions"`
## Commandes série ## Commandes série
- `h` : aide - `h` : aide
- `s` : statut runtime (hook, HFP, audio, call) - `s` : statut runtime (hook, HFP, audio, call)
+47
View File
@@ -0,0 +1,47 @@
# Orchestration ZeroClaw (RTC)
Dernière mise à jour: 2026-02-21.
## Objectif
Rendre les boucles hardware RTC plus robustes:
- préflight USB obligatoire avant upload/flash,
- session agent ZeroClaw ciblée sur le repo RTC,
- exécution coordonnée avec `Kill_LIFE` (orchestrateur dual-repo).
## 1) Préflight hardware local
Lancer avant `autoflash.py`, `hw_validation.py` ou tout upload PlatformIO:
```bash
python3 scripts/zeroclaw_hw_preflight.py --zeroclaw-bin /Users/cils/Documents/Lelectron_rare/Kill_LIFE/zeroclaw/target/release/zeroclaw --require-port
```
Variantes:
```bash
python3 scripts/zeroclaw_hw_preflight.py --port /dev/tty.SLAB_USBtoUART
python3 scripts/zeroclaw_hw_preflight.py --port /dev/tty.usbserial-0001 --port /dev/tty.usbmodem5AB90753301
```
## 2) Conversation agent ciblée RTC
Depuis `Kill_LIFE`:
```bash
tools/ai/zeroclaw_dual_chat.sh rtc -m "fais un état hardware et propose 3 actions"
```
Si credentials manquants, choisir un provider:
- `zeroclaw auth login --provider openai-codex --device-code`
- ou `export OPENROUTER_API_KEY=... && export ZEROCLAW_PROVIDER=openrouter`
## 3) Boucle recommandée (issue -> PR)
1. Préflight USB (`zeroclaw_hw_preflight.py`).
2. Prompt court RTC.
3. Patch minimal RTC.
4. Tests locaux ciblés.
5. PR dédiée RTC avec logs/artefacts.
+102
View File
@@ -0,0 +1,102 @@
#!/usr/bin/env python3
"""Run ZeroClaw USB discovery/introspection before hardware actions."""
from __future__ import annotations
import argparse
import glob
import os
import shutil
import subprocess
import sys
from pathlib import Path
def resolve_bin(requested: str) -> str:
if os.path.sep in requested:
if not Path(requested).exists():
raise FileNotFoundError(f"ZeroClaw binary not found: {requested}")
return requested
resolved = shutil.which(requested)
if not resolved:
raise FileNotFoundError(
"ZeroClaw binary not found in PATH. Set --zeroclaw-bin explicitly."
)
return resolved
def default_ports() -> list[str]:
patterns = [
"/dev/tty.SLAB_USBtoUART",
"/dev/tty.usbserial-*",
"/dev/tty.usbmodem*",
]
ports: list[str] = []
for pattern in patterns:
ports.extend(glob.glob(pattern))
return sorted(set(ports))
def run_command(cmd: list[str]) -> int:
print(f"$ {' '.join(cmd)}")
proc = subprocess.run(cmd, check=False)
return proc.returncode
def main() -> int:
parser = argparse.ArgumentParser(
description="ZeroClaw preflight for RTC hardware sessions."
)
parser.add_argument(
"--zeroclaw-bin",
default=os.environ.get("ZEROCLAW_BIN", "zeroclaw"),
help="Path/name of zeroclaw binary (default: zeroclaw in PATH).",
)
parser.add_argument(
"--port",
action="append",
default=[],
help="Explicit serial port to introspect (repeatable).",
)
parser.add_argument(
"--require-port",
action="store_true",
help="Fail if no serial port candidate is detected.",
)
args = parser.parse_args()
try:
zc_bin = resolve_bin(args.zeroclaw_bin)
except FileNotFoundError as exc:
print(f"[fail] {exc}", file=sys.stderr)
return 2
if run_command([zc_bin, "hardware", "discover"]) != 0:
print("[fail] zeroclaw hardware discover failed", file=sys.stderr)
return 3
ports = args.port if args.port else default_ports()
if not ports:
message = "[warn] no candidate serial ports detected."
if args.require_port:
print(message, file=sys.stderr)
return 4
print(message)
return 0
failures = 0
for port in ports:
rc = run_command([zc_bin, "hardware", "introspect", port])
if rc != 0:
failures += 1
if failures:
print(f"[fail] introspection failed on {failures} port(s).", file=sys.stderr)
return 5
print("[ok] zeroclaw hardware preflight passed.")
return 0
if __name__ == "__main__":
raise SystemExit(main())