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)
7.6 KiB
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:
- Validate the public XFCE USB artifact download path.
- Prove a simple cross-host coordination contract for future Colibri work.
Roles In The First Test
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
Protocol: HTTPS
Transport: TCP
Port: 443
Direction: debby -> osa.smilepowered.org
The current ISO URL uses the public OSA path:
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
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
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
capinfosoutputtshark -q -z conv,tcpoutput- 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.
cd /home/clawdie/clawdie-iso
TEST_ID="osa-clean-download-$(date -u +%Y%m%dT%H%M%SZ)"
SERVER_DIR="/home/clawdie/clawdie-iso/tmp/network-tests/$TEST_ID"
mkdir -p "$SERVER_DIR"
date -u '+server_pcap_start_utc=%Y-%m-%dT%H:%M:%SZ' > "$SERVER_DIR/timestamps.txt"
If the debby public IP is known:
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:
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:
capinfos "$SERVER_DIR/osa-vtnet0-https-90s.pcapng" > "$SERVER_DIR/capinfos.txt"
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:
curl -4 ifconfig.me
Run the bounded real-path HTTP/1.1 range test:
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:
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:
scp root@osa.smilepowered.org:/home/clawdie/clawdie-iso/tmp/network-tests/$TEST_ID/osa-vtnet0-https-90s.pcapng .
Or over Tailscale SSH/IP:
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.
{
"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_ipandremote_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:
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:
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.0by 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_IDand manifests from each participating host.
Related Documents
doc/COLIBRI-PI-CONTROL-PLAN.mddoc/CONTROLPLANE-MESSAGE-CONTRACT.mddoc/CONTROLPLANE-ARCHITECTURE.md