clawdie-ai/doc/INTERAGENT-RUN-CONTRACT.md
Operator & Codex c5820dec84 Document Colibri Pi control plan
Park the Pi-only control simplification and cross-host run contract so other agents can review before implementation starts.

---
Build: pass | Tests: pass — 2456 passed (182 files)
2026-05-24 19:26:19 +02:00

298 lines
7.6 KiB
Markdown

# Interagent Run Contract
**Date:** 14.maj.2026
**Status:** PLANNED — use as the first Colibri testground
## Purpose
Use the OSA ↔ debby network throughput test as a practical testground for
interagent communication while also diagnosing the public ISO download path.
This frees two birds at once:
1. Validate the public XFCE USB artifact download path.
2. Prove a simple cross-host coordination contract for future Colibri work.
## Roles In The First Test
```text
OSA / FreeBSD
Role: server-side capture and summary
Agent: Codex ISO Builder or FreeBSD/Pi operator agent
Interface under test: vtnet0
Scratch path: /home/clawdie/clawdie-iso/tmp/network-tests/$TEST_ID
Debby / Linux
Role: client-side download, optional client capture, summary
Agent: Hermes/Pi Linux operator agent
Scratch path: ~/.local/state/hermes/net-tests/$TEST_ID
Domedog / Linux
Role: optional coordinator hub
Agent: operator-side Pi/Colibri prototype
Function: aggregate manifests and display state, later via Herdr if useful
```
## Protocol Separation
There are three separate protocol layers. Keep them separate in reports.
### 1. Download Under Test
```text
Protocol: HTTPS
Transport: TCP
Port: 443
Direction: debby -> osa.smilepowered.org
```
The current ISO URL uses the public OSA path:
```text
https://osa.smilepowered.org/downloads/iso/clawdie-xfce-quindecim-usb-24.05.26-9ba32d9.img.gz
```
This should traverse the public internet to OSA `vtnet0`, not `tailscale0`,
unless the URL or routing is changed to a `100.x.y.z` Tailscale address.
### 2. Packet Capture
```text
Mechanism: local libpcap capture
Tools: dumpcap, tcpdump, tshark, capinfos
Network port: none for the capture itself
```
Packet capture writes local `.pcapng` files. The pcap is not streamed between
hosts during capture.
### 3. Artifact Transfer If Needed
```text
Protocol: SSH file transfer
Transport: TCP
Port: 22
Tools: scp or rsync -e ssh
Preferred path: Tailscale SSH/IP when available
```
Raw pcaps are binary diagnostic artifacts. Do not commit them to git.
## Summary-First Exchange Rule
Agents exchange summaries first. Raw pcaps move only if summaries are not
enough.
Exchange these text artifacts first:
- `TEST_ID`
- exact URL
- host role
- timestamps
- curl timing output
- `capinfos` output
- `tshark -q -z conv,tcp` output
- retransmit/reset/PMTU notes if collected
- local pcap path
Only then, if deeper analysis is needed, pull the raw `.pcapng` via `scp` or
`rsync` over SSH/TCP/22.
## OSA Server-Side Workflow
Use a repo-local scratch path, not `/root/net-tests`.
```sh
cd /home/clawdie/clawdie-iso
```
```sh
TEST_ID="osa-clean-download-$(date -u +%Y%m%dT%H%M%SZ)"
```
```sh
SERVER_DIR="/home/clawdie/clawdie-iso/tmp/network-tests/$TEST_ID"
```
```sh
mkdir -p "$SERVER_DIR"
```
```sh
date -u '+server_pcap_start_utc=%Y-%m-%dT%H:%M:%SZ' > "$SERVER_DIR/timestamps.txt"
```
If the debby public IP is known:
```sh
dumpcap -i vtnet0 -f 'host <DEBBY_PUBLIC_IP> and (tcp port 443 or icmp or icmp6)' -a duration:90 -w "$SERVER_DIR/osa-vtnet0-https-90s.pcapng"
```
If it is not known yet:
```sh
dumpcap -i vtnet0 -f 'tcp port 443 or icmp or icmp6' -a duration:90 -w "$SERVER_DIR/osa-vtnet0-https-90s.pcapng"
```
Then summarize locally:
```sh
capinfos "$SERVER_DIR/osa-vtnet0-https-90s.pcapng" > "$SERVER_DIR/capinfos.txt"
```
```sh
tshark -r "$SERVER_DIR/osa-vtnet0-https-90s.pcapng" -q -z conv,tcp > "$SERVER_DIR/tcp-conversations.txt"
```
## Debby Client-Side Workflow
If the public IP is needed for the OSA capture filter:
```sh
curl -4 ifconfig.me
```
Run the bounded real-path HTTP/1.1 range test:
```sh
curl -L --http1.1 --range 0-536870911 -o /dev/null -w 'remote_ip=%{remote_ip}\nremote_port=%{remote_port}\ntime=%{time_total}s\nspeed=%{speed_download} B/s\n' https://osa.smilepowered.org/downloads/iso/clawdie-xfce-quindecim-usb-24.05.26-9ba32d9.img.gz
```
Route check for the public path:
```sh
ip route get <REMOTE_PUBLIC_IP_FROM_CURL>
```
If `remote_ip` is public and the route is not `tailscale0`, Tailscale is not in
the ISO download data path.
## Optional Raw Pcap Transfer
Pull OSA pcap from debby over SSH/TCP/22:
```sh
scp root@osa.smilepowered.org:/home/clawdie/clawdie-iso/tmp/network-tests/$TEST_ID/osa-vtnet0-https-90s.pcapng .
```
Or over Tailscale SSH/IP:
```sh
scp root@100.72.229.63:/home/clawdie/clawdie-iso/tmp/network-tests/$TEST_ID/osa-vtnet0-https-90s.pcapng .
```
Use `rsync -e ssh` instead of `scp` for resumable larger transfers.
## Manifest Schema
Each side should write a small JSON manifest. This becomes the first concrete
interagent message format for Colibri.
```json
{
"schema": "clawdie.interagent.run-manifest.v1",
"test_id": "osa-clean-download-YYYYMMDDTHHMMSSZ",
"role": "server-capture",
"host": "osa",
"agent": "codex-iso-builder",
"started_at": "2026-05-14T12:00:00Z",
"ended_at": "2026-05-14T12:01:30Z",
"protocols": {
"download": "HTTPS over TCP/443",
"capture": "local libpcap",
"artifact_transfer": "SSH over TCP/22 when needed"
},
"network": {
"capture_interface": "vtnet0",
"remote_host": "debby",
"remote_public_ip": "<DEBBY_PUBLIC_IP>",
"filter": "host <DEBBY_PUBLIC_IP> and (tcp port 443 or icmp or icmp6)"
},
"artifacts": {
"pcapng": "/home/clawdie/clawdie-iso/tmp/network-tests/$TEST_ID/osa-vtnet0-https-90s.pcapng",
"capinfos": "/home/clawdie/clawdie-iso/tmp/network-tests/$TEST_ID/capinfos.txt",
"tcp_conversations": "/home/clawdie/clawdie-iso/tmp/network-tests/$TEST_ID/tcp-conversations.txt"
},
"summary": {
"curl_time_total_sec": null,
"curl_speed_download_bps": null,
"retransmits_observed": null,
"resets_observed": null,
"pmtu_icmp_observed": null
},
"raw_transfer_required": false,
"notes": []
}
```
Debby uses the same schema with `role: "client-download"` and its local artifact
paths.
## Tailscale Bottleneck Rule
For the current public ISO URL, Tailscale is probably not the download
bottleneck because the tested URL resolves to the public OSA path and the OSA
capture interface is `vtnet0`.
Prove this with:
- curl `remote_ip` and `remote_port`
- `ip route get <remote_ip>` on debby
- OSA packet presence on `vtnet0`
- absence of the same bulk flow on `tailscale0`
Tailscale can still affect:
- SSH sessions
- pcap transfer
- interagent coordination
- control/status polling
But that is separate from the public HTTPS download unless a `100.x.y.z` path is
used.
## Colibri Integration Path
The run manifest is intentionally simple. Colibri can later ingest it as:
```text
local run manifest(s)
-> Colibri parser
-> Clawdie task/activity state
-> optional Herdr display on Linux
```
Do not make agents talk directly to each other as the primary design. Prefer a
hub-and-spoke model:
```text
OSA / FreeBSD spoke
local safety: watchdog + hostd
local artifacts: network-test summaries and pcaps
Debby / Linux spoke
local artifacts: curl output, optional client pcaps
Coordinator hub
Colibri aggregates manifests and Pi events
Herdr optionally renders operator panes/status
```
The hub may be domedog or another operator Linux host. The hub is not allowed to
bypass FreeBSD local safety.
## Guardrails
- Bind future sockets to loopback or Tailscale only; never `0.0.0.0` by default.
- Use SSH keys and Tailscale ACLs for host-to-host transfers.
- Keep status/read paths separate from command/write paths.
- Raw pcaps stay out of git.
- Summaries are exchanged before raw artifacts.
- FreeBSD watchdog/hostd remain locally authoritative.
- Every run gets a `TEST_ID` and manifests from each participating host.
## Related Documents
- `doc/COLIBRI-PI-CONTROL-PLAN.md`
- `doc/CONTROLPLANE-MESSAGE-CONTRACT.md`
- `doc/CONTROLPLANE-ARCHITECTURE.md`