docs: harness-neutral cleanup + restore green markdown gate #124
9 changed files with 145 additions and 126 deletions
|
|
@ -10,37 +10,37 @@ bill-of-materials calculation. The obvious answer was Blender — it has
|
|||
|
||||
## Before: Blender
|
||||
|
||||
| Metric | Value |
|
||||
|---|---|
|
||||
| Packages installed | 53 |
|
||||
| Download size | 323 MiB |
|
||||
| Installed size | 1 GiB |
|
||||
| Key dependencies | llvm19, ffmpeg, openimageio, opencolorio, openvdb, pulseaudio |
|
||||
| Headless mode | `blender --background` (still pulls X11 deps) |
|
||||
| Dome generation time | ~14s (Eevee render, 2000×2000) |
|
||||
| Metric | Value |
|
||||
| -------------------- | ------------------------------------------------------------- |
|
||||
| Packages installed | 53 |
|
||||
| Download size | 323 MiB |
|
||||
| Installed size | 1 GiB |
|
||||
| Key dependencies | llvm19, ffmpeg, openimageio, opencolorio, openvdb, pulseaudio |
|
||||
| Headless mode | `blender --background` (still pulls X11 deps) |
|
||||
| Dome generation time | ~14s (Eevee render, 2000×2000) |
|
||||
|
||||
## After: geodesic-dome-mcp
|
||||
|
||||
| Metric | Value |
|
||||
|---|---|
|
||||
| File size | 6 KB (294 lines of Python) |
|
||||
| Dependencies | numpy, Pillow (already installed on all nodes) |
|
||||
| Dome generation time | <1s (wireframe), sub-second (BOM only) |
|
||||
| Headless | Always — no X11, no GPU, no display server |
|
||||
| Outputs | Wireframe PNG + structural BOM (JSON) |
|
||||
| Metric | Value |
|
||||
| -------------------- | ---------------------------------------------- |
|
||||
| File size | 6 KB (294 lines of Python) |
|
||||
| Dependencies | numpy, Pillow (already installed on all nodes) |
|
||||
| Dome generation time | <1s (wireframe), sub-second (BOM only) |
|
||||
| Headless | Always — no X11, no GPU, no display server |
|
||||
| Outputs | Wireframe PNG + structural BOM (JSON) |
|
||||
|
||||
## Capability impact
|
||||
|
||||
| Capability | Before (Blender) | After (geodesic-dome-mcp) |
|
||||
|---|---|---|
|
||||
| Can run on 32GB USB ISO? | ❌ (1 GiB, exceeds headroom) | ✅ (6 KB, negligible) |
|
||||
| Can run on 12GB RAM VPS? | ❌ (would fit disk but overkill) | ✅ (already running) |
|
||||
| Can run on bare-metal? | ✅ (if installed) | ✅ (always) |
|
||||
| Structural BOM? | ❌ (needs separate script) | ✅ (built-in) |
|
||||
| Half-sphere mode? | Manual mesh cut | ✅ (`half=true`) |
|
||||
| Connector analysis? | ❌ | ✅ (3/4/5/6-way counts) |
|
||||
| Strut length table? | ❌ | ✅ (grouped by size) |
|
||||
| Material cost estimates? | ❌ | ✅ (glass/polycarbonate/insulated) |
|
||||
| Capability | Before (Blender) | After (geodesic-dome-mcp) |
|
||||
| ------------------------ | -------------------------------- | ---------------------------------- |
|
||||
| Can run on 32GB USB ISO? | ❌ (1 GiB, exceeds headroom) | ✅ (6 KB, negligible) |
|
||||
| Can run on 12GB RAM VPS? | ❌ (would fit disk but overkill) | ✅ (already running) |
|
||||
| Can run on bare-metal? | ✅ (if installed) | ✅ (always) |
|
||||
| Structural BOM? | ❌ (needs separate script) | ✅ (built-in) |
|
||||
| Half-sphere mode? | Manual mesh cut | ✅ (`half=true`) |
|
||||
| Connector analysis? | ❌ | ✅ (3/4/5/6-way counts) |
|
||||
| Strut length table? | ❌ | ✅ (grouped by size) |
|
||||
| Material cost estimates? | ❌ | ✅ (glass/polycarbonate/insulated) |
|
||||
|
||||
## Registering capabilities
|
||||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ All tools run on the mother node (OSA) and are registered in
|
|||
## Step 1: `gurs-address-lookup` — Address → Coordinates + Parcel ID
|
||||
|
||||
### Input
|
||||
|
||||
```json
|
||||
{
|
||||
"address": "Na vrtu 5",
|
||||
|
|
@ -23,6 +24,7 @@ All tools run on the mother node (OSA) and are registered in
|
|||
```
|
||||
|
||||
### Implementation
|
||||
|
||||
1. WFS GetFeature to GURS Register naslovov
|
||||
- Filter: `ULICA='Na vrtu' AND HISNA_STEVILKA='5' AND POSTNA_STEVILKA='1000'`
|
||||
- EPSG 3794 → reproject to EPSG 4326
|
||||
|
|
@ -31,9 +33,11 @@ All tools run on the mother node (OSA) and are registered in
|
|||
4. No results: partial match, suggest alternatives
|
||||
|
||||
### Output
|
||||
|
||||
Lat/lon + parcel ID + cadastral municipality + land use code.
|
||||
|
||||
### Diagram
|
||||
|
||||
```
|
||||
User "Na vrtu 5, 1000 LJ"
|
||||
│
|
||||
|
|
@ -53,15 +57,18 @@ User "Na vrtu 5, 1000 LJ"
|
|||
## Step 2: `gurs-parcel-boundary` — Parcel ID → Boundary + Metadata
|
||||
|
||||
### Implementation
|
||||
|
||||
1. WFS GetFeature to GURS Kataster nepremičnin (collection: `parcele`)
|
||||
2. Compute: area, centroid, inscribed circle, setback compliance
|
||||
3. Query GJI for road/utility access
|
||||
4. Check OPSI orthophoto availability
|
||||
|
||||
### Output
|
||||
|
||||
Boundary GeoJSON + area + inscribed circle + infrastructure distances + setbacks.
|
||||
|
||||
### Diagram
|
||||
|
||||
```
|
||||
┌─────────────────────────────────┐
|
||||
│ ┌───┐ │
|
||||
|
|
@ -81,6 +88,7 @@ Boundary GeoJSON + area + inscribed circle + infrastructure distances + setbacks
|
|||
## Step 3: `dome-placement` — Optimal Dome Position
|
||||
|
||||
### Implementation
|
||||
|
||||
1. Inscribed circle search (binary search from centroid)
|
||||
2. Orientation: entrance faces south, ramp fits within parcel
|
||||
3. Ground slope from GURS DMR (optional)
|
||||
|
|
@ -88,9 +96,11 @@ Boundary GeoJSON + area + inscribed circle + infrastructure distances + setbacks
|
|||
5. Sun path: winter solstice shadow analysis
|
||||
|
||||
### Output
|
||||
|
||||
Center coordinates + orientation + fit quality rating + conflicts + sun/shadow.
|
||||
|
||||
### Diagram
|
||||
|
||||
```
|
||||
N
|
||||
▲
|
||||
|
|
@ -117,12 +127,14 @@ Already implemented: wireframes, BOM, strut constraint, construction layers.
|
|||
New: site context from Steps 2-3.
|
||||
|
||||
### New output
|
||||
|
||||
- Foundation type based on frost depth + slope
|
||||
- Access path length + gravel estimate
|
||||
- Rebar updated with foundation starter bars
|
||||
- Local Eurocode constants applied
|
||||
|
||||
### BOM Diagram
|
||||
|
||||
```
|
||||
Item │ Qty │ Cost
|
||||
──────────────────┼──────┼──────
|
||||
|
|
@ -145,18 +157,20 @@ Seismic: 0.175g PGA
|
|||
|
||||
### Three options
|
||||
|
||||
| Option | Cost | Quality | Effort |
|
||||
|---|---|---|---|
|
||||
| A: OPSI orthophoto overlay | Free | Good (2D site plan) | ~4h |
|
||||
| B: Google 3D Tiles | Paid | Excellent (3D photoreal) | ~8h |
|
||||
| C: Gemini AI-enhanced | ~$0.04 | Good (4K composite) | ~1h |
|
||||
| Option | Cost | Quality | Effort |
|
||||
| -------------------------- | ------ | ------------------------ | ------ |
|
||||
| A: OPSI orthophoto overlay | Free | Good (2D site plan) | ~4h |
|
||||
| B: Google 3D Tiles | Paid | Excellent (3D photoreal) | ~8h |
|
||||
| C: Gemini AI-enhanced | ~$0.04 | Good (4K composite) | ~1h |
|
||||
|
||||
### Option C (quickest path)
|
||||
|
||||
1. Pass orthophoto + dome wireframe as Gemini reference images
|
||||
2. Prompt: "Photorealistic vegetation matching Slovenian landscape..."
|
||||
3. Output: 4K composite PNG
|
||||
|
||||
### Diagram
|
||||
|
||||
```
|
||||
┌────────────────────────────────────┐
|
||||
│ 3D Perspective — Dome on Site │
|
||||
|
|
@ -185,6 +199,7 @@ Seismic: 0.175g PGA
|
|||
Heavy nodes (USB) request renders from mother. Same MCP pattern as `build-colibri.sh`.
|
||||
|
||||
### Architecture
|
||||
|
||||
```
|
||||
USB (light node) Mother (OSA, Blender 5.0)
|
||||
│ │
|
||||
|
|
@ -200,6 +215,7 @@ USB (light node) Mother (OSA, Blender 5.0)
|
|||
```
|
||||
|
||||
### Capabilities
|
||||
|
||||
- Cycles path-traced rendering (photorealistic)
|
||||
- EEVEE real-time rendering (fast previews)
|
||||
- PBR materials (glass, steel, concrete, wood)
|
||||
|
|
@ -211,11 +227,13 @@ USB (light node) Mother (OSA, Blender 5.0)
|
|||
- 4K+ native resolution
|
||||
|
||||
### Render times (OSA, 6-core CPU, no GPU)
|
||||
|
||||
- Wireframe: ~5s (EEVEE)
|
||||
- Materials + lighting: ~5min (Cycles 128)
|
||||
- Full scene + vegetation: ~15-30min (Cycles 256, 4K)
|
||||
|
||||
### Blender render pipeline diagram
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────┐
|
||||
│ Mother Blender Render Pipeline │
|
||||
|
|
@ -243,25 +261,25 @@ USB (light node) Mother (OSA, Blender 5.0)
|
|||
|
||||
## Implementation Priority
|
||||
|
||||
| Step | Effort | Priority |
|
||||
|---|---|---|
|
||||
| Step 1: address lookup | ~2h | 1 — unlocks everything |
|
||||
| Step 2: parcel boundary | ~3h | 2 |
|
||||
| Step 3: dome placement | ~4h | 3 |
|
||||
| Step 4: site BOM | ~2h | 4 |
|
||||
| Step 5: AI render | ~1h | 5 |
|
||||
| Step 5: orthophoto | ~4h | 6 |
|
||||
| Step 6: Blender render | ~6h | 7 |
|
||||
| Step 5: Google 3D | ~8h | 8 |
|
||||
| Step | Effort | Priority |
|
||||
| ----------------------- | ------ | ---------------------- |
|
||||
| Step 1: address lookup | ~2h | 1 — unlocks everything |
|
||||
| Step 2: parcel boundary | ~3h | 2 |
|
||||
| Step 3: dome placement | ~4h | 3 |
|
||||
| Step 4: site BOM | ~2h | 4 |
|
||||
| Step 5: AI render | ~1h | 5 |
|
||||
| Step 5: orthophoto | ~4h | 6 |
|
||||
| Step 6: Blender render | ~6h | 7 |
|
||||
| Step 5: Google 3D | ~8h | 8 |
|
||||
|
||||
Total: ~30h for complete pipeline.
|
||||
|
||||
## Slovenian building code (Eurocode)
|
||||
|
||||
| Parameter | Central Slovenia |
|
||||
|---|---|
|
||||
| Frost depth | 0.8m |
|
||||
| Snow load | 1.5 kN/m² (≤500m) |
|
||||
| Wind speed | 25 m/s |
|
||||
| Seismic PGA | 0.175g |
|
||||
| Setback | 4.0m |
|
||||
| Parameter | Central Slovenia |
|
||||
| ----------- | ----------------- |
|
||||
| Frost depth | 0.8m |
|
||||
| Snow load | 1.5 kN/m² (≤500m) |
|
||||
| Wind speed | 25 m/s |
|
||||
| Seismic PGA | 0.175g |
|
||||
| Setback | 4.0m |
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ The real lever is **removing the step**, not reskinning it.
|
|||
4. Prompted for BW_CLIENTID, BW_CLIENTSECRET (masked), BW_PASSWORD (masked)
|
||||
5. `clawdie-vault-fetch` pulls API keys from Vaultwarden
|
||||
6. `colibri_daemon` restarted
|
||||
7. Pi agent auto-spawned and live
|
||||
7. agent auto-spawned and live
|
||||
|
||||
### Seed partition path (one double-click)
|
||||
|
||||
|
|
@ -54,7 +54,7 @@ is unnecessary — and the boot ordering already favors zero-touch:
|
|||
So the importer now merges the active agent's direct provider keys (everything
|
||||
except `BW_*`) into the daemon's `provider.env` as well as the operator's
|
||||
`~/.env`. The daemon starts afterward, finds `DEEPSEEK_API_KEY`, and
|
||||
auto-spawns the agent (`COLIBRI_AUTOSPAWN_PI=YES`) — no click, no vault
|
||||
auto-spawns the agent (`COLIBRI_AUTOSPAWN=YES`) — no click, no vault
|
||||
round-trip, no typing. `BW_*` still route to `~/.config/vault-bootstrap.env`
|
||||
for operators who prefer the vault-fetch path.
|
||||
|
||||
|
|
|
|||
|
|
@ -9,70 +9,70 @@ Clawdie USB. Derived from the OSA security audit on 2026-06-23.
|
|||
|
||||
### SSH hardening
|
||||
|
||||
| Check | Command | Expected |
|
||||
|---|---|---|
|
||||
| Check | Command | Expected |
|
||||
| ---------------------- | ---------------------------------------- | --------------------------- |
|
||||
| Password auth disabled | `grep PasswordAuth /etc/ssh/sshd_config` | `PasswordAuthentication no` |
|
||||
| Root login disabled | `grep PermitRoot /etc/ssh/sshd_config` | `PermitRootLogin no` |
|
||||
| Key-only auth | `grep PubkeyAuth /etc/ssh/sshd_config` | `PubkeyAuthentication yes` |
|
||||
| Root login disabled | `grep PermitRoot /etc/ssh/sshd_config` | `PermitRootLogin no` |
|
||||
| Key-only auth | `grep PubkeyAuth /etc/ssh/sshd_config` | `PubkeyAuthentication yes` |
|
||||
|
||||
### Service accounts
|
||||
|
||||
| Check | Command | Expected |
|
||||
|---|---|---|
|
||||
| colibri user exists | `pw usershow colibri` | uid 3002, shell `/usr/sbin/nologin` or `/bin/sh` with restrict |
|
||||
| colibri password locked | `pw usershow colibri \| grep '*'` | `*` (asterisk = locked) |
|
||||
| colibri in clawdie group | `id colibri` | includes `clawdie` group |
|
||||
| SSH key restricted | `cat /var/db/colibri/.ssh/authorized_keys` | `command="colibri-mcp-ssh",restrict,no-pty,...` |
|
||||
| Home dir owned by colibri | `ls -la /var/db/colibri/` | `colibri:colibri` on the directory itself |
|
||||
| Check | Command | Expected |
|
||||
| ------------------------- | ------------------------------------------ | -------------------------------------------------------------- |
|
||||
| colibri user exists | `pw usershow colibri` | uid 3002, shell `/usr/sbin/nologin` or `/bin/sh` with restrict |
|
||||
| colibri password locked | `pw usershow colibri \| grep '*'` | `*` (asterisk = locked) |
|
||||
| colibri in clawdie group | `id colibri` | includes `clawdie` group |
|
||||
| SSH key restricted | `cat /var/db/colibri/.ssh/authorized_keys` | `command="colibri-mcp-ssh",restrict,no-pty,...` |
|
||||
| Home dir owned by colibri | `ls -la /var/db/colibri/` | `colibri:colibri` on the directory itself |
|
||||
|
||||
### MCP socket
|
||||
|
||||
| Check | Command | Expected |
|
||||
|---|---|---|
|
||||
| Socket exists | `ls /var/run/colibri/colibri.sock` | exists |
|
||||
| Check | Command | Expected |
|
||||
| --------------------------- | -------------------------------------- | ---------------------------- |
|
||||
| Socket exists | `ls /var/run/colibri/colibri.sock` | exists |
|
||||
| Restricted to clawdie group | `ls -la /var/run/colibri/colibri.sock` | `srwxrwx--- clawdie:clawdie` |
|
||||
|
||||
### Firewall (pf)
|
||||
|
||||
| Check | Command | Expected |
|
||||
|---|---|---|
|
||||
| Default deny | `sudo pfctl -sr` | `block drop all` as final rule |
|
||||
| Only http/https public | `sudo pfctl -sr \| grep vtnet0` | only ports 80, 443 (and optionally 22) |
|
||||
| SSH Tailscale-only (optional) | `sudo pfctl -sr \| grep ssh` | no vtnet0 ssh rule, only tailscale0 |
|
||||
| Check | Command | Expected |
|
||||
| ----------------------------- | ------------------------------- | -------------------------------------- |
|
||||
| Default deny | `sudo pfctl -sr` | `block drop all` as final rule |
|
||||
| Only http/https public | `sudo pfctl -sr \| grep vtnet0` | only ports 80, 443 (and optionally 22) |
|
||||
| SSH Tailscale-only (optional) | `sudo pfctl -sr \| grep ssh` | no vtnet0 ssh rule, only tailscale0 |
|
||||
|
||||
### Listening ports
|
||||
|
||||
| Check | Command | Expected |
|
||||
|---|---|---|
|
||||
| No unexpected listeners | `sudo sockstat -l` | nginx (80/443), colibri (socket), sshd |
|
||||
| Check | Command | Expected |
|
||||
| ------------------------ | ------------------------------- | ------------------------------------------------------- |
|
||||
| No unexpected listeners | `sudo sockstat -l` | nginx (80/443), colibri (socket), sshd |
|
||||
| Dashboard Tailscale-only | `sudo sockstat -l \| grep 9119` | Hermes dashboard — should be on localhost or tailscale0 |
|
||||
| No 0.0.0.0 bindings | `sudo sockstat -l \| grep '*'` | only nginx 80/443 (public web), nothing else |
|
||||
| No 0.0.0.0 bindings | `sudo sockstat -l \| grep '*'` | only nginx 80/443 (public web), nothing else |
|
||||
|
||||
### MCP access test
|
||||
|
||||
| Check | Command | Expected |
|
||||
|---|---|---|
|
||||
| Local MCP works | `colibri-mcp tools` | lists tools |
|
||||
| SSH MCP from colibri user | `ssh -i mother-mcp colibri@localhost 'tools'` | lists tools (single-word invocation only) |
|
||||
| colibri_external_mcp_servers | via MCP tool | shows registered external servers |
|
||||
| Check | Command | Expected |
|
||||
| ---------------------------- | --------------------------------------------- | ----------------------------------------- |
|
||||
| Local MCP works | `colibri-mcp tools` | lists tools |
|
||||
| SSH MCP from colibri user | `ssh -i mother-mcp colibri@localhost 'tools'` | lists tools (single-word invocation only) |
|
||||
| colibri_external_mcp_servers | via MCP tool | shows registered external servers |
|
||||
|
||||
### External MCP servers
|
||||
|
||||
| Check | Command | Expected |
|
||||
|---|---|---|
|
||||
| Config exists | `cat /usr/local/etc/colibri/external-mcp.json` | valid JSON with servers |
|
||||
| COLIBRI_MCP_EXTERNAL_CALL | `grep EXTERNAL_CALL /usr/local/etc/colibri/provider.env` | `COLIBRI_MCP_EXTERNAL_CALL=1` |
|
||||
| geodesic-dome-mcp installed | `ls /usr/local/bin/geodesic-dome-mcp` | exists, executable |
|
||||
| build-colibri.sh installed | `ls /usr/local/bin/build-colibri.sh` | exists, executable |
|
||||
| colibri-mcp-ssh wrapper | `ls /usr/local/bin/colibri-mcp-ssh` | exists, executable |
|
||||
| Check | Command | Expected |
|
||||
| --------------------------- | -------------------------------------------------------- | ----------------------------- |
|
||||
| Config exists | `cat /usr/local/etc/colibri/external-mcp.json` | valid JSON with servers |
|
||||
| COLIBRI_MCP_EXTERNAL_CALL | `grep EXTERNAL_CALL /usr/local/etc/colibri/provider.env` | `COLIBRI_MCP_EXTERNAL_CALL=1` |
|
||||
| geodesic-dome-mcp installed | `ls /usr/local/bin/geodesic-dome-mcp` | exists, executable |
|
||||
| build-colibri.sh installed | `ls /usr/local/bin/build-colibri.sh` | exists, executable |
|
||||
| colibri-mcp-ssh wrapper | `ls /usr/local/bin/colibri-mcp-ssh` | exists, executable |
|
||||
|
||||
## OSA-specific exceptions (production)
|
||||
|
||||
| Exception | Reason |
|
||||
|---|---|
|
||||
| Password auth enabled on vtnet0 | User preference for OSA access during development |
|
||||
| SSH port 22 on public interface | OSA is the mother node, needs public SSH for now |
|
||||
| Port 9119 on 0.0.0.0 | Hermes dashboard, pf-limited to Tailscale on vtnet0 |
|
||||
| Exception | Reason |
|
||||
| ------------------------------- | --------------------------------------------------- |
|
||||
| Password auth enabled on vtnet0 | User preference for OSA access during development |
|
||||
| SSH port 22 on public interface | OSA is the mother node, needs public SSH for now |
|
||||
| Port 9119 on 0.0.0.0 | Hermes dashboard, pf-limited to Tailscale on vtnet0 |
|
||||
|
||||
These exceptions should NOT be present on a booted USB — the USB is a
|
||||
single-user operator station, not a public server.
|
||||
|
|
|
|||
|
|
@ -8,10 +8,10 @@ sent to mother, and stored in PostgreSQL `mother_hive.usb_nodes`.
|
|||
|
||||
## Hosts used in this guide
|
||||
|
||||
| Host | IP (Tailscale) | User for MCP | Role |
|
||||
|---|---|---|---|
|
||||
| `osa.smilepowered.org` | `100.72.229.63` | `colibri` | Mother — runs PostgreSQL, external MCP servers |
|
||||
| `clawdie-usb` (USB) | `100.66.193.11` | `clawdie` | Operator workstation — sends hw-probe to mother |
|
||||
| Host | IP (Tailscale) | User for MCP | Role |
|
||||
| ---------------------- | --------------- | ------------ | ----------------------------------------------- |
|
||||
| `osa.smilepowered.org` | `100.72.229.63` | `colibri` | Mother — runs PostgreSQL, external MCP servers |
|
||||
| `clawdie-usb` (USB) | `100.66.193.11` | `clawdie` | Operator workstation — sends hw-probe to mother |
|
||||
|
||||
## How it works
|
||||
|
||||
|
|
@ -228,12 +228,12 @@ Once the daemon is restarted with `COLIBRI_AUTOSPAWN=YES` and
|
|||
|
||||
## Troubleshooting
|
||||
|
||||
| Symptom | Likely cause | Fix |
|
||||
|---|---|---|
|
||||
| `ssh m0th3r` hangs | Tailscale not up | `sudo tailscale up` on USB |
|
||||
| `Permission denied (publickey)` | Key not in authorized_keys on mother | Verify: `cat /var/db/c0l1br1/.ssh/authorized_keys` on OSA |
|
||||
| `Permission denied (publickey)` | Key permissions wrong on USB | `chmod 600 ~/.ssh/m0th3r-mcp` |
|
||||
| `daemon: open: Permission denied` | Log file ownership wrong | `chown clawdie: /var/log/colibri/daemon.log` |
|
||||
| Daemon starts but no external tools | `COLIBRI_MCP_EXTERNAL_CALL` not set | Check provider.env, restart daemon |
|
||||
| Daemon starts, external tools visible, but calls fail | SSH key path wrong in external-mcp.json | Use absolute path: `/home/clawdie/.ssh/m0th3r-mcp` |
|
||||
| `error: unrecognized subcommand` | SSH wrapper getting "colibri-mcp tools" instead of "tools" | Use single-word invocation: `ssh m0th3r 'tools'` not `ssh m0th3r 'colibri-mcp tools'` |
|
||||
| Symptom | Likely cause | Fix |
|
||||
| ----------------------------------------------------- | ---------------------------------------------------------- | ------------------------------------------------------------------------------------- |
|
||||
| `ssh m0th3r` hangs | Tailscale not up | `sudo tailscale up` on USB |
|
||||
| `Permission denied (publickey)` | Key not in authorized_keys on mother | Verify: `cat /var/db/c0l1br1/.ssh/authorized_keys` on OSA |
|
||||
| `Permission denied (publickey)` | Key permissions wrong on USB | `chmod 600 ~/.ssh/m0th3r-mcp` |
|
||||
| `daemon: open: Permission denied` | Log file ownership wrong | `chown clawdie: /var/log/colibri/daemon.log` |
|
||||
| Daemon starts but no external tools | `COLIBRI_MCP_EXTERNAL_CALL` not set | Check provider.env, restart daemon |
|
||||
| Daemon starts, external tools visible, but calls fail | SSH key path wrong in external-mcp.json | Use absolute path: `/home/clawdie/.ssh/m0th3r-mcp` |
|
||||
| `error: unrecognized subcommand` | SSH wrapper getting "colibri-mcp tools" instead of "tools" | Use single-word invocation: `ssh m0th3r 'tools'` not `ssh m0th3r 'colibri-mcp tools'` |
|
||||
|
|
|
|||
|
|
@ -11,16 +11,16 @@ mother stores it in PostgreSQL `mother_hive.usb_nodes`.
|
|||
|
||||
## Current state
|
||||
|
||||
| Component | USB (0.11) | OSA (mother) |
|
||||
|---|---|---|
|
||||
| colibri-daemon | ✅ Running, 0.11 binary | ✅ Running, 0.11 binary |
|
||||
| External MCP support | ✅ Built-in (`colibri_external_mcp_call_tool`) | ✅ Built-in |
|
||||
| `COLIBRI_MCP_EXTERNAL_CALL` | ❌ Not set | ✅ `1` |
|
||||
| `external-mcp.json` | ❌ Doesn't exist | ✅ `mother-build` + `geodesic-dome` |
|
||||
| `mother-mcp` SSH key | ❌ Not present | ✅ `/var/db/colibri/.ssh/mother-mcp` |
|
||||
| SSH config for mother | ❌ None | ✅ localhost test confirmed |
|
||||
| `clawdie-hw-probe` | ❌ Not installed (0.12 feature) | ✅ Works, produces valid JSON |
|
||||
| PostgreSQL mother_hive | N/A | ✅ OSA node registered |
|
||||
| Component | USB (0.11) | OSA (mother) |
|
||||
| --------------------------- | ---------------------------------------------- | ------------------------------------ |
|
||||
| colibri-daemon | ✅ Running, 0.11 binary | ✅ Running, 0.11 binary |
|
||||
| External MCP support | ✅ Built-in (`colibri_external_mcp_call_tool`) | ✅ Built-in |
|
||||
| `COLIBRI_MCP_EXTERNAL_CALL` | ❌ Not set | ✅ `1` |
|
||||
| `external-mcp.json` | ❌ Doesn't exist | ✅ `mother-build` + `geodesic-dome` |
|
||||
| `mother-mcp` SSH key | ❌ Not present | ✅ `/var/db/colibri/.ssh/mother-mcp` |
|
||||
| SSH config for mother | ❌ None | ✅ localhost test confirmed |
|
||||
| `clawdie-hw-probe` | ❌ Not installed (0.12 feature) | ✅ Works, produces valid JSON |
|
||||
| PostgreSQL mother_hive | N/A | ✅ OSA node registered |
|
||||
|
||||
## What the USB needs (5 steps)
|
||||
|
||||
|
|
@ -161,12 +161,12 @@ derived capabilities (`has_gpu`, `ram_gb`, `cpu_cores`, etc.).
|
|||
|
||||
## Implementation priority
|
||||
|
||||
| Step | Effort | Blocked by |
|
||||
|---|---|---|
|
||||
| Step 1: SSH key + config | Manual (one-time) | Nothing |
|
||||
| Step 2: Enable external MCP | 1 line | Nothing |
|
||||
| Step 3: external-mcp.json | 10 lines JSON | Nothing |
|
||||
| Step 4: Install hw-probe | Copy file | 0.12 branch |
|
||||
| Step 5: Restart + verify | 2 commands | Steps 1-4 |
|
||||
| Step 6: Seed partition auto-key | Code change | 0.12 ISO build |
|
||||
| Step 7: node_register MCP tool on mother | New MCP tool | Step 6 |
|
||||
| Step | Effort | Blocked by |
|
||||
| ---------------------------------------- | ----------------- | -------------- |
|
||||
| Step 1: SSH key + config | Manual (one-time) | Nothing |
|
||||
| Step 2: Enable external MCP | 1 line | Nothing |
|
||||
| Step 3: external-mcp.json | 10 lines JSON | Nothing |
|
||||
| Step 4: Install hw-probe | Copy file | 0.12 branch |
|
||||
| Step 5: Restart + verify | 2 commands | Steps 1-4 |
|
||||
| Step 6: Seed partition auto-key | Code change | 0.12 ISO build |
|
||||
| Step 7: node_register MCP tool on mother | New MCP tool | Step 6 |
|
||||
|
|
|
|||
|
|
@ -155,18 +155,18 @@ if provider_env_has_bw_creds; then
|
|||
sleep 1
|
||||
_t=$(( _t + 1 ))
|
||||
done
|
||||
# Confirm the auto-spawned Pi came up (colibri auto-spawn on boot).
|
||||
# Confirm the auto-spawned agent came up (colibri auto-spawn on boot).
|
||||
if have colibri; then
|
||||
_p=0
|
||||
while [ "$_p" -lt 10 ]; do
|
||||
if colibri --socket "$SOCKET" status 2>/dev/null | grep -q '"agents":[1-9]'; then
|
||||
echo " Pi agent is live."
|
||||
echo " Agent is live."
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
_p=$(( _p + 1 ))
|
||||
done
|
||||
[ "$_p" -lt 10 ] || echo " NOTE: no Pi agent yet — check: colibri status"
|
||||
[ "$_p" -lt 10 ] || echo " NOTE: no agent yet — check: colibri status"
|
||||
fi
|
||||
else
|
||||
echo " WARNING: daemon restart failed."
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ Inside it, any of these are honored:
|
|||
Routing for the ACTIVE agent:
|
||||
- Provider API keys and toggles
|
||||
(DEEPSEEK_API_KEY=..., OPENROUTER_API_KEY=...,
|
||||
COLIBRI_AUTOSPAWN_PI=YES, ...) are merged
|
||||
COLIBRI_AUTOSPAWN=YES, ...) are merged
|
||||
into BOTH the agent's ~/.env AND the daemon's
|
||||
/usr/local/etc/colibri/provider.env (mode
|
||||
0600). Because the importer runs before the
|
||||
|
|
|
|||
|
|
@ -168,7 +168,8 @@ BW_SERVER="https://vault.smilepowered.org"
|
|||
# Behavior toggles (non-secret):
|
||||
# COLIBRI_AUTOSPAWN="YES" # auto-spawn one agent on daemon startup
|
||||
# COLIBRI_AUTOSPAWN_BINARY="zot" # agent harness: zot (default) | pi
|
||||
# COLIBRI_AUTOSPAWN_ARGS="--mode json" # agent argv
|
||||
# COLIBRI_AUTOSPAWN_ARGS="rpc" # agent argv; default is harness-derived
|
||||
# # (zot -> "rpc", pi -> "--mode json")
|
||||
# COLIBRI_MCP_EXTERNAL_CALL="1" # allow agent (via colibri-mcp) to call
|
||||
# # external MCP servers; set by
|
||||
# # clawdie-enable-mother
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue