phase 1: unfirehose reconstruction from session JSONL ingest
Source: ~/.unfirehose/unfirehose.db (project_id=81, 4 sessions covering
2026-03-29 through 2026-04-05). Reconstructed via chronological replay
of Write/Edit tool_input on file_paths under /home/fox/zebra-report/.
stats:
files reconstructed: 20
writes baselined: all (zero missing)
edits applied: 68
edits unapplied: 8 (1 SKIP pre-baseline, 6 FAIL old_string drift, 1 AMBIGUOUS)
unapplied edits represent small drift in 6 files; baseline content for
each is intact. quality verification deferred to phase 2.
recovered tree:
CLAUDE.md, Makefile
src/{tx,rx,pulse,carrier,chat,bt}.c
include/{modem,zebra}.h
test/{functional,integration,unit}.c, test/test.h
web/{index,kernel}.html, web/blog/style.css
blog/build.py, blog/posts/{001-volume-modem,002-sse-chatroom}.md
report: /tmp/zebra_recover_report.txt
script: /tmp/zebra_recover.py
This commit is contained in:
commit
b77da42bbe
20 changed files with 4062 additions and 0 deletions
121
CLAUDE.md
Normal file
121
CLAUDE.md
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
# Agent Blackops
|
||||
|
||||
This repo is operated by **agent blackops** — ml agent for fox/timehexon on the unsandbox/unturf/permacomputer platform.
|
||||
|
||||
## Identity
|
||||
|
||||
Full shard: `~/git/unsandbox.com/blackops/BLACKOPS.md`
|
||||
|
||||
## Rules
|
||||
|
||||
- I propose, fox decides. Unsure = ask. Can't ask = stop.
|
||||
- No autonomous ops decisions. No destructive commands without explicit instruction.
|
||||
- Fail-closed. Cleanup crew, not demolition.
|
||||
- Check the time every session. Gaps are information.
|
||||
- DRY in context — single source of truth, no sprawl.
|
||||
- Never say "AI" — always say "machine learning."
|
||||
- Prefer "defect" over "bug."
|
||||
|
||||
## Orientation
|
||||
|
||||
```bash
|
||||
date -u
|
||||
pwd
|
||||
git log --oneline -5
|
||||
git status
|
||||
```
|
||||
|
||||
Then ask fox what the mission is.
|
||||
|
||||
## Zebra Report System
|
||||
|
||||
**Concept**: covert bidirectional communication channel using browser tab volume as the modulation medium — dial-up modem principles, userland only, no kernel involvement, no network stack.
|
||||
|
||||
### Collaborators & Stakeholders
|
||||
|
||||
| Handle | Role |
|
||||
|--------|------|
|
||||
| **foxhop** | fox — handler, operator, TimeHexOn |
|
||||
| **brackishbert** | collaborator |
|
||||
| **SEW** | collaborator |
|
||||
| **russell@unturf** | Russell Ballestrini — unturf founder, permacomputer manifesto, `ago` library |
|
||||
| **TimeHexOn** | oracle platform — primary deployment target |
|
||||
| **groupr** | related project |
|
||||
|
||||
### How it works
|
||||
|
||||
PulseAudio exposes each browser tab as a separate sink input, visible and controllable in `pavucontrol`. Volume is settable per-tab in userland with no kernel involvement. Each tab has a range of **0–100** (101 discrete levels — 101 dalmatians).
|
||||
|
||||
By modulating volume at a consistent rate (bauds), two sides can exchange data:
|
||||
|
||||
- **transmitter**: steps volume through values at a fixed clock rate
|
||||
- **receiver**: reads volume at the same clock rate, decodes the steps back to data
|
||||
- **bidirectional**: two tabs (or two processes watching different tabs) run opposite directions simultaneously
|
||||
|
||||
### Signal space
|
||||
|
||||
- 101 levels = ~6.66 bits per symbol
|
||||
- practical: use power-of-2 subsets — 2 levels (1 bit), 4 levels (2 bits), 64 levels (6 bits)
|
||||
- higher symbol depth trades noise margin for throughput
|
||||
- low baud rate = high reliability, low throughput (like 300 baud dialup)
|
||||
- high baud rate = races PulseAudio update latency
|
||||
- measured ceiling on neoblanka: ~1000–1200 baud (PA IPC ~350–400µs avg)
|
||||
|
||||
### Binaries
|
||||
|
||||
| Binary | Description |
|
||||
|--------|-------------|
|
||||
| `tx` | transmitter — reads stdin, modulates tab volume |
|
||||
| `rx` | receiver — reads tab volume, writes decoded bytes to stdout |
|
||||
| `chat` | bidirectional chat — two tabs, two threads |
|
||||
| `bt` | **Battle Toads** — stereo dual-channel, 2x bandwidth |
|
||||
|
||||
### Project Battle Toads
|
||||
|
||||
One stereo browser tab carries **two independent UART streams** simultaneously — L channel and R channel. PulseAudio's `pa_cvolume` is per-channel; a single `get_sink_input_info` call returns both L and R volumes.
|
||||
|
||||
- TX sets L and R to independent bit values each symbol
|
||||
- RX decodes L and R from a single PA poll — no extra IPC cost
|
||||
- Net: 2x throughput at same baud rate, same PA polling budget
|
||||
- Web carrier upgraded to stereo: two oscillators (440Hz L, 441Hz R) merged into a stereo stream → PA sees `channels=2`
|
||||
|
||||
```bash
|
||||
# After opening web/index.html and clicking 'start audio' (stereo tab):
|
||||
./bt -T MY_SINK -R THEIR_SINK -b 500
|
||||
```
|
||||
|
||||
### Auto-negotiate (handshake protocol)
|
||||
|
||||
RX benchmarks its own PA polling speed and signals the max safe baud to TX. No manual baud matching needed.
|
||||
|
||||
```bash
|
||||
./rx -s RX_SINK -t TX_SINK # RX benchmarks, sends offer at 50 baud
|
||||
./tx -s TX_SINK -r RX_SINK # TX listens for offer, locks to RX's rate
|
||||
```
|
||||
|
||||
Handshake frame: `[0x5A 0x42 0x01 baud_lo baud_hi xor_cksum]` — 6 bytes at 50 baud (~1.2s).
|
||||
|
||||
**Known defect**: 3-way handshake not yet implemented. TX can fire before RX enters receive loop at high baud rates. Fix: RX-ready signal back to TX before data phase.
|
||||
|
||||
### Tools
|
||||
|
||||
- `pactl set-sink-input-volume` — set volume by sink-input index
|
||||
- `pactl list sink-inputs` — enumerate tabs, read current volume
|
||||
- `pavucontrol` — visual verification of modulation
|
||||
- `./tx -l` — list all PA sink inputs with index, volume, channels
|
||||
- sink-input index maps to tab; stable within a session
|
||||
|
||||
### Use cases
|
||||
|
||||
- agent-to-agent signaling without touching the filesystem or network stack
|
||||
- side-channel between sandboxed browser tab and host process
|
||||
- low-bandwidth status heartbeat (alive/dead/mode) at ~1–10 baud
|
||||
- covert channel for oracle↔host communication on TimeHexOn
|
||||
|
||||
### Constraints
|
||||
|
||||
- sink-input index resets when tab navigates or crashes — handshake needed on reconnect
|
||||
- PA polling latency sets the baud ceiling — benchmark with `./rx -s SINK -t SINK2` before sending
|
||||
- stereo (channels=2) required for Battle Toads — open web/index.html, click 'start audio'
|
||||
- userland only — survives without root
|
||||
- **Operation Voyeur**: all terminal output is public — never pass secrets through these channels unencrypted. The web page does ECDH key exchange + AES-256-GCM before TX.
|
||||
Loading…
Add table
Add a link
Reference in a new issue