o2r-focused localhost Ansible network-debug playbook: capture-once/parse-thrice probes, anonymized diffs posted to an otel-a2a-relay channel.
This repository has been archived on 2026-06-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.
  • Python 88.7%
  • Shell 4.9%
  • Ruby 3.6%
  • Makefile 2.8%
Find a file
2026-06-10 17:43:57 -07:00
.ward refactor: drop ansible and sweep the probe battery with battery.py over battery.yml 2026-06-10 17:43:57 -07:00
docs refactor: drop ansible and sweep the probe battery with battery.py over battery.yml 2026-06-10 17:43:57 -07:00
outputs chore(outputs): record kais-macbook-pro -> kai-server transport + hairpin probes 2026-06-07 11:44:15 -07:00
parsers chore(code-comments): clean comment-discipline violations; bump agentic-os v0.16.0 2026-06-08 16:53:53 -07:00
scripts refactor: drop ansible and sweep the probe battery with battery.py over battery.yml 2026-06-10 17:43:57 -07:00
.agentic-os.toml chore(code-comments): clean comment-discipline violations; bump agentic-os v0.16.0 2026-06-08 16:53:53 -07:00
.gitignore refactor: drop ansible and sweep the probe battery with battery.py over battery.yml 2026-06-10 17:43:57 -07:00
.pre-commit-config.yaml chore(code-comments): clean comment-discipline violations; bump agentic-os v0.16.0 2026-06-08 16:53:53 -07:00
AGENTS.md refactor: drop ansible and sweep the probe battery with battery.py over battery.yml 2026-06-10 17:43:57 -07:00
battery.yml refactor: drop ansible and sweep the probe battery with battery.py over battery.yml 2026-06-10 17:43:57 -07:00
Brewfile refactor: drop ansible and sweep the probe battery with battery.py over battery.yml 2026-06-10 17:43:57 -07:00
CLAUDE.md chore: adopt agentic-os catalog pre-commit suite 2026-06-04 23:02:48 -07:00
Makefile refactor: drop ansible and sweep the probe battery with battery.py over battery.yml 2026-06-10 17:43:57 -07:00
README.md refactor: drop ansible and sweep the probe battery with battery.py over battery.yml 2026-06-10 17:43:57 -07:00

otel-a2a-relay-debug

An o2r-focused, localhost-only network debugger. The point of this repo is not the probe battery - it is the o2r channel. You run a debugging session, every step posts a clean anonymized diff to an otel-a2a-relay Agent Channel, and a human or another agent watches the channel to see what the debugging looks like.

Status: v0 scaffold. The Python transform/diff core is unit-tested. The ping and kubectl probes are verified end-to-end against a live relay; the full battery is not.

Mental model

  • Every session is a (source, target) tuple. Localhost-only: source is the node running the probes, target is the tailnet host under debug. Outputs are keyed outputs/<source>__<target>/.
  • o2r is the crux. The channel carries the story. It never sees a timestamp, a line number, or an IP.
  • STEP is not a choice. Every probe runs through scripts/step.py. There is no raw-probe path, because a raw probe is un-anonymized and would leak into the channel.

Capture once, parse thrice

A command runs exactly once. scripts/step.py saves the capture verbatim, then derives three tiers by parsing the saved capture - it never re-runs the command. Parsers are pure functions over saved raw, so fixing a parser re-derives the tiers without re-probing.

tier scrubbed committed destination
raw nothing no (gitignored) raw/NNNN.{cmd,out}, saved every run
normalized timestamps, RTT, volatile fields no (gitignored) normalized/*.json - machine diff substrate, local only (still holds real IPs/names)
public normalized + IPs, FQDNs, names, ids → placeholders yes public/*.yml - human-read + the only thing posted to o2r

Two-file retention per tier: baseline (last blessed known-good) + current (under debug). scripts/bless.py promotes current → baseline. Only the scrubbed public tier is committed.

Each committed public/*.yml is a result: payload under one line of context: purpose:, the probe's intent. Source, target, probe, tier, and baseline-vs-current already live in the path (outputs/<src>__<tgt>/<probe>/public/<baseline|current>.yml), so they are not duplicated into the file. The purpose string lives once in parsers/_registry.yml (desc per command-id) and is stamped in at capture time; it is constant across baseline/current, so only result drives the diff.

The parser layer is a manual-first gate

Each command-id has a parser at parsers/<id>.yml defining its normalize and anonymize rules. jc is the default normalizer. Commands jc has no parser for declare normalize.text: true instead. The first run of a new command has no parser, so STEP halts and you hand-author the rule, commit it, then re-run. STEP refuses to post un-parsed output - fail-closed, because un-parsed means un-anonymized.

Usage

export DBG_SOURCE=kais-macbook-pro DBG_TARGET=kai-server
scripts/session.py start                 # creates the o2r channel, seeds the charter
scripts/step.py ping -- ping -c3 <host>  # capture once, parse thrice, post public diff
scripts/bless.py ping                    # promote current -> baseline when healthy
scripts/session.py close

Or sweep the whole battery: scripts/battery.py (name ids to run a subset). Setup and deps are in docs/dependencies.md.

See also

Catalog-trifecta convention from coilysiren/agentic-os#59.