add zeroclaw dual-repo orchestration toolkit

This commit is contained in:
Clément SAILLANT
2026-02-21 01:10:51 +01:00
parent cf447b1d2a
commit b72fa3d53b
7 changed files with 395 additions and 0 deletions
@@ -0,0 +1,42 @@
name: ZeroClaw Dual Orchestrator
on:
push:
branches: [main]
paths:
- "tools/ai/zeroclaw_dual_*.sh"
- "specs/zeroclaw_dual_hw_*.md"
- ".github/workflows/zeroclaw_dual_orchestrator.yml"
pull_request:
branches: [main]
paths:
- "tools/ai/zeroclaw_dual_*.sh"
- "specs/zeroclaw_dual_hw_*.md"
- ".github/workflows/zeroclaw_dual_orchestrator.yml"
workflow_dispatch:
concurrency:
group: zeroclaw-dual-orchestrator-${{ github.ref }}
cancel-in-progress: true
jobs:
lint-and-contract:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install shellcheck
run: |
sudo apt-get update
sudo apt-get install -y shellcheck
- name: Shellcheck orchestrator scripts
run: |
shellcheck tools/ai/zeroclaw_dual_bootstrap.sh
shellcheck tools/ai/zeroclaw_dual_chat.sh
- name: Verify spec files
run: |
test -s specs/zeroclaw_dual_hw_orchestration_spec.md
test -s specs/zeroclaw_dual_hw_todo.md
+1
View File
@@ -1,5 +1,6 @@
.venv
# Fichiers et dossiers à ignorer pour Kill_LIFE
zeroclaw/
# Python
__pycache__/
+5
View File
@@ -9,3 +9,8 @@ Flux conseillé (itératif) :
6) Implémentation (firmware/hardware) + tests + doc
Le fichier `constraints.yaml` est la **source de vérité** des contraintes non-fonctionnelles et règles repo.
Specs complémentaires:
- `zeroclaw_dual_hw_orchestration_spec.md`: architecture d'orchestration ZeroClaw multi-repo + double matériel.
- `zeroclaw_dual_hw_todo.md`: backlog opérationnel court terme pour autonomie contrôlée.
@@ -0,0 +1,114 @@
# Spec: ZeroClaw Dual-Repo + Dual-Hardware Orchestration
Last updated: 2026-02-21
## 1) Goal
Run one orchestration layer that can:
- converse against `RTC_BL_PHONE` and `le-mystere-professeur-zacus` independently,
- keep workspace boundaries strict per repo,
- run low-cost autonomous loops with guarded command allowlists,
- stay ready for connected hardware checks before any upload/flash action.
## 2) Scope
In scope:
- local ZeroClaw profile bootstrap for both repos,
- deterministic workspace switch (`rtc` vs `zacus`) from one CLI entrypoint,
- hardware discovery/introspection preflight,
- lightweight CI validation for orchestration scripts/spec.
Out of scope:
- storing provider secrets in git,
- hard-coding serial ports in committed config,
- forcing hardware jobs on GitHub-hosted runners.
## 3) Current Hardware Snapshot (local)
Detected at bootstrap time:
- `CP2102 USB to UART Bridge Controller` (`10c4:ea60`)
- `USB Single Serial` (`1a86:55d3`)
Known candidate ports:
- `/dev/tty.SLAB_USBtoUART`
- `/dev/tty.usbserial-0001`
- `/dev/tty.usbmodem5AB90753301`
## 4) Architecture
### 4.1 Repo-local ZeroClaw profile
Each repo gets:
- `<repo>/.zeroclaw/config.toml`
Runtime workspace selection is done via:
- `ZEROCLAW_WORKSPACE=<repo>`
This keeps `autonomy.workspace_only = true` effective on a per-repo boundary.
### 4.2 Orchestrator scripts
- `tools/ai/zeroclaw_dual_bootstrap.sh`
- writes/refreshes both repo profiles,
- archives legacy root `config.toml` + `workspace/` if they match old ZeroClaw layout,
- validates ZeroClaw binary availability,
- runs `zeroclaw status` for both workspaces,
- runs `zeroclaw hardware discover`.
- `tools/ai/zeroclaw_dual_chat.sh`
- target switch by alias (`rtc`, `zacus`) or absolute path,
- message mode (`-m`) or interactive mode,
- provider auto-fallback (`copilot` -> `openai-codex` -> `openrouter`),
- token sourcing from `gh auth token` at runtime only when `copilot` is selected.
### 4.3 Provider/cost strategy
Auto provider selection order in `zeroclaw_dual_chat.sh`:
1. explicit `ZEROCLAW_PROVIDER` override,
2. `copilot` when `gh` auth is valid and Copilot billing endpoint is accessible,
3. `openai-codex` when a ZeroClaw auth profile exists,
4. `openrouter` when `OPENROUTER_API_KEY` is present.
Observed on current machine:
- GitHub API returned `404` for Copilot billing endpoint (no active Copilot subscription on this token), so fallback path is required for autonomous chat.
## 5) Operations Loop
1. Bootstrap configs and hardware probe.
2. Run one focused prompt in `rtc`.
3. Run one focused prompt in `zacus`.
4. Apply patches/tests per repo.
5. Open small PRs + issue links (one concern per PR).
6. Repeat.
## 6) CI Workflow
Workflow:
- `.github/workflows/zeroclaw_dual_orchestrator.yml`
Behavior:
- path-filtered on orchestration scripts/spec files,
- shellcheck scripts,
- verify spec/todo files exist,
- concurrency enabled to cancel stale runs on same ref.
## 7) External References (optimization decisions)
- GitHub Actions path filters and trigger controls:
https://docs.github.com/actions/reference/workflows-and-actions/workflow-syntax
- GitHub Actions concurrency control (cancel stale runs):
https://docs.github.com/actions/using-jobs/using-concurrency
- PlatformIO remote unit test runner and local/remote split strategy:
https://docs.platformio.org/en/latest/plus/remote/unit-testing.html
- PySerial port metadata usage (`serial.tools.list_ports`) for stable device targeting:
https://pyserial.readthedocs.io/en/latest/tools.html
+36
View File
@@ -0,0 +1,36 @@
# TODO: Dual Hardware Autonomy (RTC + Zacus)
Last updated: 2026-02-21
## Phase A: Local Baseline
- [ ] Run `tools/ai/zeroclaw_dual_bootstrap.sh` and capture hardware snapshot.
- [ ] Validate `tools/ai/zeroclaw_dual_chat.sh rtc -m "<diagnostic prompt>"`.
- [ ] Validate `tools/ai/zeroclaw_dual_chat.sh zacus -m "<diagnostic prompt>"`.
- [ ] Record detected ports and map preferred role per board.
## Phase B: Repo Specs and PR Cadence
- [ ] Create/refresh one issue in `RTC_BL_PHONE` for ZeroClaw-assisted hardware loop.
- [ ] Create/refresh one issue in `le-mystere-professeur-zacus` for ZeroClaw-assisted hardware loop.
- [ ] Open one small PR per repo focused on one gate (build, tests, hardware smoke, docs).
- [ ] Require code review pass before merge (`gh pr review --approve` only after checks).
## Phase C: Autonomy + Cost Optimization
- [ ] Keep prompts short, target one repo at a time.
- [ ] Use provider auto-fallback (`copilot` -> `openai-codex` -> `openrouter`) to avoid dead sessions.
- [ ] Add repo-level path filters in workflows to avoid expensive irrelevant runs.
- [ ] Use `workflow_dispatch` for hardware-required jobs to avoid noisy CI failures.
## Phase D: Hardware Robustness
- [ ] Add serial-port resolver step before every upload/flash action.
- [ ] Fail fast if no expected USB device is detected.
- [ ] Archive logs per run for replayability (`artifacts/<timestamp>/...`).
## Exit Criteria
- [ ] Both repos can be targeted with one command (`rtc` or `zacus`) without workspace leakage.
- [ ] Hardware discovery passes before action on connected boards.
- [ ] At least one successful PR cycle completed per repo with this orchestration path.
+98
View File
@@ -0,0 +1,98 @@
#!/usr/bin/env bash
set -euo pipefail
ZEROCLAW_BIN="${ZEROCLAW_BIN:-/Users/cils/Documents/Lelectron_rare/Kill_LIFE/zeroclaw/target/release/zeroclaw}"
RTC_REPO="/Users/cils/Documents/Lelectron_rare/RTC_BL_PHONE"
ZACUS_REPO="/Users/cils/Documents/Lelectron_rare/le-mystere-professeur-zacus"
HARDWARE_ONLY=0
usage() {
cat <<USAGE
Usage: $(basename "$0") [--rtc <path>] [--zacus <path>] [--zeroclaw-bin <path>] [--hardware-only]
Bootstrap local ZeroClaw workspace profiles for both repos and run hardware discovery.
USAGE
}
while [[ $# -gt 0 ]]; do
case "$1" in
--rtc)
RTC_REPO="${2:-}"; shift 2 ;;
--zacus)
ZACUS_REPO="${2:-}"; shift 2 ;;
--zeroclaw-bin)
ZEROCLAW_BIN="${2:-}"; shift 2 ;;
--hardware-only)
HARDWARE_ONLY=1; shift ;;
-h|--help)
usage; exit 0 ;;
*)
echo "Unknown argument: $1" >&2
usage
exit 1 ;;
esac
done
if [[ ! -x "$ZEROCLAW_BIN" ]]; then
if command -v zeroclaw >/dev/null 2>&1; then
ZEROCLAW_BIN="$(command -v zeroclaw)"
else
echo "zeroclaw binary not found." >&2
exit 1
fi
fi
if [[ "$HARDWARE_ONLY" == "1" ]]; then
"$ZEROCLAW_BIN" hardware discover
exit 0
fi
write_repo_config() {
local repo="$1"
mkdir -p "$repo/.zeroclaw"
mkdir -p "$repo/.zeroclaw/legacy"
# If a previous run created a root ZeroClaw profile, archive it so
# ZEROCLAW_WORKSPACE resolves to repo-local .zeroclaw/config.toml.
if [[ -f "$repo/config.toml" ]] && rg -q '^default_provider =|^\[autonomy\]' "$repo/config.toml"; then
mv "$repo/config.toml" "$repo/.zeroclaw/legacy/config.root.auto.toml"
fi
if [[ -d "$repo/workspace" && -d "$repo/workspace/memory" && -d "$repo/workspace/state" ]]; then
mv "$repo/workspace" "$repo/.zeroclaw/legacy/workspace.root.auto"
fi
cat > "$repo/.zeroclaw/config.toml" <<'TOML'
default_provider = "openai-codex"
default_temperature = 0.2
[memory]
backend = "sqlite"
auto_save = true
embedding_provider = "none"
[autonomy]
level = "supervised"
workspace_only = true
allowed_commands = ["git", "gh", "ls", "cat", "rg", "sed", "awk", "find", "make", "python3", "bash", "sh", "pio"]
forbidden_paths = ["/etc", "/root", "/home", "/usr", "/bin", "/sbin", "/lib", "/opt", "/boot", "/dev", "/proc", "/sys", "/var", "/tmp", "~/.ssh", "~/.gnupg", "~/.aws", "~/.config"]
max_actions_per_hour = 40
max_cost_per_day_cents = 150
require_approval_for_medium_risk = true
block_high_risk_commands = true
TOML
}
write_repo_config "$RTC_REPO"
write_repo_config "$ZACUS_REPO"
ZEROCLAW_WORKSPACE="$RTC_REPO" "$ZEROCLAW_BIN" status >/dev/null
ZEROCLAW_WORKSPACE="$ZACUS_REPO" "$ZEROCLAW_BIN" status >/dev/null
"$ZEROCLAW_BIN" hardware discover
echo "Bootstrap complete."
echo "- RTC workspace: $RTC_REPO"
echo "- Zacus workspace: $ZACUS_REPO"
echo "Provider strategy:"
echo "1) export ZEROCLAW_PROVIDER=copilot (requires GitHub Copilot subscription)"
echo "2) zeroclaw auth login --provider openai-codex --device-code"
echo "3) export OPENROUTER_API_KEY=... and use ZEROCLAW_PROVIDER=openrouter"
+99
View File
@@ -0,0 +1,99 @@
#!/usr/bin/env bash
set -euo pipefail
ZEROCLAW_BIN="${ZEROCLAW_BIN:-/Users/cils/Documents/Lelectron_rare/Kill_LIFE/zeroclaw/target/release/zeroclaw}"
RTC_REPO="/Users/cils/Documents/Lelectron_rare/RTC_BL_PHONE"
ZACUS_REPO="/Users/cils/Documents/Lelectron_rare/le-mystere-professeur-zacus"
usage() {
cat <<USAGE
Usage:
$(basename "$0") <rtc|zacus|path> -m "message"
$(basename "$0") <rtc|zacus|path> --interactive
$(basename "$0") <rtc|zacus|path> --hardware
USAGE
}
if [[ $# -lt 2 ]]; then
usage
exit 1
fi
target="$1"
shift
case "$target" in
rtc) workspace="$RTC_REPO" ;;
zacus) workspace="$ZACUS_REPO" ;;
*) workspace="$target" ;;
esac
if [[ ! -d "$workspace" ]]; then
echo "Workspace not found: $workspace" >&2
exit 1
fi
if [[ ! -x "$ZEROCLAW_BIN" ]]; then
if command -v zeroclaw >/dev/null 2>&1; then
ZEROCLAW_BIN="$(command -v zeroclaw)"
else
echo "zeroclaw binary not found." >&2
exit 1
fi
fi
if [[ "${1:-}" == "--hardware" ]]; then
ZEROCLAW_WORKSPACE="$workspace" "$ZEROCLAW_BIN" hardware discover
exit 0
fi
resolve_provider() {
if [[ -n "${ZEROCLAW_PROVIDER:-}" ]]; then
echo "$ZEROCLAW_PROVIDER"
return 0
fi
if command -v gh >/dev/null 2>&1 && gh auth status >/dev/null 2>&1; then
if gh api /user/copilot/billing --silent >/dev/null 2>&1; then
local gh_token
gh_token="$(gh auth token)"
export API_KEY="$gh_token"
echo "copilot"
return 0
fi
fi
if "$ZEROCLAW_BIN" auth list 2>/dev/null | rg -q "openai-codex:"; then
echo "openai-codex"
return 0
fi
if [[ -n "${OPENROUTER_API_KEY:-}" ]]; then
export API_KEY="$OPENROUTER_API_KEY"
echo "openrouter"
return 0
fi
cat <<'ERR' >&2
No provider credentials detected.
- Option 1: ZEROCLAW_PROVIDER=copilot with GitHub Copilot subscription + gh auth login
- Option 2: zeroclaw auth login --provider openai-codex --device-code
- Option 3: export OPENROUTER_API_KEY=... and ZEROCLAW_PROVIDER=openrouter
ERR
return 1
}
export ZEROCLAW_WORKSPACE="$workspace"
provider="$(resolve_provider)"
echo "[zeroclaw-dual-chat] workspace=$workspace provider=$provider"
if [[ "${1:-}" == "--interactive" ]]; then
exec "$ZEROCLAW_BIN" agent -p "$provider"
fi
if [[ "${1:-}" != "-m" || -z "${2:-}" ]]; then
usage
exit 1
fi
exec "$ZEROCLAW_BIN" agent -p "$provider" -m "$2"