docs: remove stale Herdr hub runbook + T1.4 cache-warming design #42

Merged
clawdie merged 1 commit from docs/remove-stale-docs into main 2026-06-13 21:43:07 +02:00
3 changed files with 0 additions and 260 deletions

View file

@ -150,5 +150,4 @@ text+image token budgets.
- Video: "Agent Specs: The Unreasonable Effectiveness of Useful Tokens"
https://www.youtube.com/watch?v=o4KZH_KSqYQ
- Colibri T1.4 Prompt Discipline: `docs/T1.4-PROMPT-DISCIPLINE-PLAN.md`
- Colibri T1.4 Cache Warming: `docs/T1.4-CACHE-WARMING-DESIGN.md`
- Colibri Glasspane Design: `docs/COLIBRI-GLASSPANE-DESIGN.md`

View file

@ -1,124 +0,0 @@
# Herdr hub runbook — domedog as the testing hub
**Goal:** run a Herdr hub on **domedog**, attach **debby** to it over Tailscale,
then layer **Colibri** supervision on top. domedog hosts the agents/work; debby
is a remote operator console; Colibri derives agent state from the Pi events
those agents emit.
**Verified:** 27.maj.2026 (Herdr 0.6.2, Pi 0.75.5, cargo workspace green @ `5d45a0f`).
---
## Topology
```text
Tailscale tailnet (samo.blatnik@)
debby ──ssh──▶ domedog (Herdr hub) ──Pi --mode json──▶ Colibri
100.66.193.10 100.103.255.41 (glasspane/daemon)
remote client herdr server + agents source of truth
```
- **domedog** `100.103.255.41` — Herdr **server** (the hub); agents run here.
- **debby** `100.66.193.10` — Herdr **remote client** (`herdr --remote`).
- **osa** `100.72.229.63` — FreeBSD; native supervision via `colibri-glasspane`
(not a Herdr host — Herdr is Linux/macOS only).
Herdr's model: whoever runs `herdr --remote <target>` is the viewer/client; the
_target_ hosts the server, sessions, panes, and agents.
---
## Phase 0 — Hub baseline on domedog ✅ done
The hub is already up; for the record the steps are:
```bash
herdr status # server: running, protocol 11
herdr integration install pi # needs ~/.pi/agent/extensions to exist first:
# mkdir -p ~/.pi/agent/extensions
herdr integration status # pi: current, claude: current, opencode: current
```
- Server pid runs `herdr server`, sockets in `~/.config/herdr/`:
`herdr.sock` (API) + `herdr-client.sock` (protocol).
- Pi is installed under nvm node v22 (`~/.nvm/versions/node/v22.22.0/bin/pi`,
v0.75.5) — the version glasspane was tested against.
- **Gate:** `herdr status` → server running; `herdr integration status``pi: current`.
---
## Phase 1 — debby attaches in over Tailscale SSH
**Prereqs (all verified on domedog):**
- sshd listening on `:22`, reachable at `100.103.255.41` over Tailscale. ✅
- debby's key `id_123kupola.pub` (`123kupola@gmail.com`) is already in domedog's
`~/.ssh/authorized_keys`, so debby→domedog SSH is authorized. ✅
- Herdr server running on domedog. ✅
**debby-side config (already present in debby `~/.ssh/config`):**
```sshconfig
Host domedog-ts-herdr
HostName 100.103.255.41
User clawdija
IdentityFile ~/.ssh/id_123kupola
IdentitiesOnly yes
```
**Remaining gap:** the `herdr` client binary is **not installed on debby**.
**Steps (run on debby / Hermes):**
```bash
# 1. install the herdr client (same method as domedog; see herdr.dev)
# 2. confirm SSH to the hub works:
ssh domedog-ts-herdr 'echo ok; whoami' # expect: ok / clawdija
# 3. attach to the hub's session:
herdr --remote domedog-ts-herdr --session default
```
- **Gate:** domedog `~/.config/herdr/herdr-server.log` logs `client connected`;
debby's terminal shows the shared `default` session.
> Authorizing a new client is just appending its **public** key to domedog's
> `~/.ssh/authorized_keys`. Public keys are safe to share/paste/commit. Never
> transit a **private** key (the file without `.pub`). Easiest no-paste path,
> run from domedog over the existing outbound trust:
> `ssh debby-ts-herdr 'cat ~/.ssh/id_123kupola.pub'` then append if not present.
---
## Phase 2 — Colibri layered on the hub
Once debby is attached and agents run in the hub:
1. Launch a `pi` agent in a Herdr pane on domedog with `--mode json`; capture its
JSONL stream.
2. `colibri-glasspane` / `colibri-daemon` ingest that JSONL → `GlasspaneSnapshot`
(`clawdie.glasspane.snapshot.v1`) served over the daemon Unix socket.
3. Operator views agent state read-only via `colibri-harness` (the TUI) /
`colibri` (the CLI).
**Boundary (unchanged):** Colibri daemon = source of truth (scheduling, task
ownership, provider logic); Herdr = terminal workspace + display; glasspane =
event-derived supervision. No scheduling/ownership in the display layer.
- **Gate:** a glasspane snapshot shows a pane's state transitioning
idle → working → done, derived from _real_ Pi events, while the agent runs
inside a Herdr pane.
---
## Reference — keys & reachability
| Host | Tailscale IP | Role | SSH identity used |
| ------- | ---------------- | ------------------- | ----------------------------------------------- |
| domedog | `100.103.255.41` | Herdr hub / Colibri | `~/.ssh/id_infra` (outbound to Forgejo + debby) |
| debby | `100.66.193.10` | remote client | `~/.ssh/id_123kupola` (→ domedog as `clawdija`) |
| osa | `100.72.229.63` | FreeBSD, glasspane | — |
- domedog's Forgejo/Tailscale key is `id_infra`; it authenticates fine — no
ssh-agent needed (config points at the file).
- Self-hosted Forgejo is `code.smilepowered.org`; SSH git access uses port
`2222` via host SSH config. Codeberg is no longer the active push target.

View file

@ -1,135 +0,0 @@
# T1.4 PR3b — Cache Warming Design
## Goal
Pre-warm the DeepSeek prefix cache on daemon startup so the first real
agent task benefits from cached tokens. Reduces latency and cost on
cold starts.
## Design decisions
### 1. Config-gated, disabled by default
```env
COLIBRI_CACHE_WARMING=0|1 # enable startup warming (default: 0)
COLIBRI_CACHE_WARMING_INTERVAL_HOURS=N # re-warm every N hours (default: 0 = disabled)
```
Rationale: cache warming consumes tokens (~3,500 per warm cycle). Until
proven beneficial on the ISO target, it stays opt-in.
### 2. Reuses existing cache probe
The `colibri-deepseek` crate already has `run_cache_probe()` which:
1. Sends a warm request with byte-stable STABLE_SYSTEM_PREFIX
2. Waits 2s for cache commit
3. Sends an identical probe request
4. Returns cache_hit_tokens and cache_hit_observed
We reuse this directly — no new API calls, no new types.
### 3. Lifecycle
```
Daemon start
→ if COLIBRI_CACHE_WARMING=1 AND DEEPSEEK_API_KEY is set
→ run_cache_probe()
→ log result (hit/miss, tokens)
→ record last_warm_at in DaemonState
Daemon loop (every heartbeat tick, 30s)
→ if COLIBRI_CACHE_WARMING_INTERVAL_HOURS > 0
→ if now - last_warm_at > interval
→ run_cache_probe()
→ update last_warm_at
Daemon shutdown
→ no cleanup needed (cache lives on provider side)
```
### 4. Observability
Cache warming results are:
- Logged at INFO level on each warm cycle
- Exposed in daemon status response: `cache_warming_enabled`, `last_warm_at`,
`last_warm_cache_hit`, `last_warm_hit_tokens`
- NOT mixed into per-session CacheMetrics (that's for agent API calls)
### 5. Safety
- If DeepSeek key is missing or empty, warming is silently skipped
- If the probe fails (network, rate limit, balance), it logs a warning
and does not retry — the daemon continues normally
- Warming failures do not affect daemon startup or agent spawning
- On FreeBSD, the key may be in a separate env file — the daemon
reads it from the process environment at startup
### 6. FreeBSD considerations
- Same code path as Linux — no platform-specific logic
- The rc.d service already exports DEEPSEEK_API_KEY via provider.env
- OSA validation: check that warming runs on daemon start, produces
cache_hit_observed=true, and metrics appear in status
## Implementation plan
### Files touched
| File | Change |
| ------------------------------ | ----------------------------------------------------------------------------------------------------- |
| `colibri-daemon/src/config.rs` | Add `cache_warming_enabled`, `cache_warming_interval_hours` |
| `colibri-daemon/src/daemon.rs` | Add `last_warm_at`, `last_warm_result` to DaemonState; call warm on startup; periodic re-warm in loop |
| `colibri-daemon/src/socket.rs` | Expose cache warming fields in cmd_status |
| `colibri-deepseek/src/lib.rs` | No changes — reuse existing run_cache_probe() |
### No changes to
- `colibri-contracts` — ProviderSmokeResult already has all needed fields
- `colibri-store` — no SQLite schema changes (warming is runtime-only)
- `colibri-skills`, `colibri-glasspane` — unrelated
## Test plan
### Unit tests (Linux, on debby)
1. `cache_warming_skipped_when_disabled` — config off, no probe runs
2. `cache_warming_skipped_when_no_key` — config on but no API key
3. `cache_warming_records_last_warm_at` — mock probe result stored
4. `cache_warming_periodic_rewarm` — interval triggers re-warm
5. `cache_warming_status_includes_metrics` — status response has fields
### FreeBSD validation (OSA, after merge)
```sh
# Enable warming
export COLIBRI_CACHE_WARMING=1
export DEEPSEEK_API_KEY=<key>
# Start daemon, check log
cargo run --bin colibri-daemon 2>&1 | grep -i "cache.*warm"
# Check status via socket
echo '{"cmd":"status"}' | nc -U /var/run/colibri/colibri.sock
# Verify: cache_warming_enabled=true, last_warm_at is set,
# last_warm_cache_hit=true, last_warm_hit_tokens > 0
```
### Acceptance criteria
- [ ] Warming runs exactly once on startup when enabled + key present
- [ ] Warming is skipped when disabled or key missing
- [ ] Periodic re-warming fires after interval (if configured)
- [ ] Cache hit observed on OSA FreeBSD (real DeepSeek API call)
- [ ] Status response includes warming metrics
- [ ] Daemon starts normally even if warming fails
- [ ] No workspace test regressions
## Rollout
1. Hermes implements + tests on Linux (debby), opens PR
2. Hermes merges via API after Linux validation
3. Codex validates on OSA FreeBSD with real DeepSeek key
4. ISO image includes `COLIBRI_CACHE_WARMING=0` default in rc.conf.sample
5. Operator enables on FreeBSD after verifying cache hit on their account