Unfuck documentation and comments
This commit is contained in:
3 files changed
+25
-88
No files matched your search
@@ -1,11 +1,7 @@
|
||||
# marvin-turnstone
|
||||
|
||||
Local turnstone deployment as a **container-VM**: a podman image is turned
|
||||
into a bootable VM with [boco](https://git.nubo.sh/hulthe/boco) (custom
|
||||
init + ext4 qcow2 + QEMU direct kernel boot). Replaces the older
|
||||
opencode-in-a-container setup (`~/marvin`).
|
||||
Local turnstone deployment as a [boco](https://git.nubo.sh/hulthe/boco) **container-VM**.
|
||||
|
||||
```
|
||||
host podman build ──> boco build qcow2 ──> boco boot
|
||||
│ QEMU/KVM (virtio, user-net)
|
||||
┌─────────────────────┴───────────────────┐
|
||||
@@ -16,23 +12,9 @@ host podman build ──> boco build qcow2 ──> boco boot
|
||||
│ └─ turnstone-server :8080 PID 1 │
|
||||
└─────────────────────────────────────────┘
|
||||
host :8080 ──hostfwd──> web UI host :2222 ──> guest sshd :22
|
||||
guest ──HTTPS (double slirp egress)──> api.tensorx.ai (LLM)
|
||||
```
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Host (Arch):
|
||||
- `podman`, `qemu-base`, `virtiofsd`, `croc` (only if fetching the kernel)
|
||||
- `boco` CLI on PATH and `boco-init` at `~/.local/share/boco/boco-init`
|
||||
(build from the boco repo)
|
||||
- Kernel at `~/.local/share/boco/registry/vmlinuz` (x86 bzImage with
|
||||
`CONFIG_VIRTIO_FS=y`; transfer via croc)
|
||||
|
||||
VM image:
|
||||
- Arch base with python + turnstone (venv at `/opt/turnstone`), git,
|
||||
helix, podman (rootless, subuid range), openssh, build toolchain
|
||||
- `marvin` user; sshd + turnstone-server started by
|
||||
`start-turnstone.sh` (server runs as `marvin`, PID 1)
|
||||
- `podman`, `qemu-base`, `virtiofsd`, `boco`
|
||||
|
||||
## Build
|
||||
|
||||
@@ -49,41 +31,11 @@ image, then packs it as `boco` qcow2 into the boco registry.
|
||||
scripts/run.sh
|
||||
```
|
||||
|
||||
- Console (proxy to the node; chat UI + admin panel): :8080 — login
|
||||
`marvin` / `marvin-turnstone` unless `ADMIN_PASSWORD` was overridden.
|
||||
The node binds :8081 guest-internal only (no host forward); the
|
||||
console routes to it, so all chat/admin goes through one port.
|
||||
- Ops SSH: `ssh -i configs/ssh/id_ed25519 -p 2222 marvin@localhost`
|
||||
- QEMU runs foreground; quit with `ctrl-a x`
|
||||
|
||||
### Access from another machine (tailcat)
|
||||
|
||||
`localhost` above is the machine running QEMU. To reach the VM from
|
||||
elsewhere, run `scripts/expose.sh` next to it — a tailcat tunnel
|
||||
(WireGuard over Tailscale's DERP relays, outbound-only, no account):
|
||||
|
||||
```
|
||||
host $ scripts/expose.sh
|
||||
# 🐈 Server listening with saved key "default": tcpGFwWCCH...
|
||||
|
||||
your $ tailcat forward tcpGFwWCCH... 8080:8080 2222:2222
|
||||
```
|
||||
|
||||
Then browse `http://localhost:8080` / `ssh -p 2222 marvin@localhost`
|
||||
from *your* machine. The address is stable across VM restarts (saved
|
||||
key) and is a bearer secret — share it only privately.
|
||||
This exposes the turnstone console on `:8080`, and ssh on `:2222`
|
||||
|
||||
### LLM backend
|
||||
|
||||
`[models.tensorx]` in `configs/turnstone/config.toml` points at the
|
||||
TensorX OpenAI-compatible gateway (`https://api.tensorx.ai/v1`, same
|
||||
key this machine's opencode uses — see
|
||||
`~/.local/share/opencode/auth.json`). Guest egress to HTTPS endpoints
|
||||
works through both slirp layers; no relay needed.
|
||||
|
||||
Self-hosted provider later: add a `[models.*]` entry with any
|
||||
OpenAI-compatible endpoint reachable from the guest (see
|
||||
`config.toml.example`).
|
||||
Set up `configs/turnstone/config.toml` with an OpenAI-compatible endpoint.
|
||||
|
||||
## Shares (virtiofs, survives reboots)
|
||||
|
||||
@@ -93,29 +45,26 @@ OpenAI-compatible endpoint reachable from the guest (see
|
||||
| `data/` | `/var/lib/turnstone` | SQLite database |
|
||||
| `work/` | `/home/marvin/work` | agent workspace |
|
||||
|
||||
Guest-written files appear on the host owned by subuid-range UIDs
|
||||
(virtiofsd runs under `podman unshare`) — cosmetic, and stable across
|
||||
boots.
|
||||
Note that virtiofsd runs under `podman unshare`, which means that files
|
||||
written by the guest-VM will be owned by a subuid-range.
|
||||
|
||||
## Configuration
|
||||
|
||||
Edit `configs/turnstone/config.toml` (gitignored; see
|
||||
`config.toml.example`):
|
||||
Edit `configs/turnstone/config.toml` (see `config.toml.example`):
|
||||
|
||||
- `[models.tensorx]` — TensorX gateway; `api_key` must be set
|
||||
(currently mirrored from opencode's `auth.json`).
|
||||
- `[auth] jwt_secret` — required, generate once.
|
||||
- `[database] path` — SQLite on the `data/` share.
|
||||
- `[tools]` — `workspace_dir` surfaced to the model
|
||||
(`/home/marvin/work`, mounted from `./work`).
|
||||
- `[models.<provider>]` - LLM provider; `api_key` must be set.
|
||||
- `[auth] jwt_secret` - required, generate once.
|
||||
- `[database] path` - SQLite on the `data/` share.
|
||||
- `[tools]` - `workspace_dir` surfaced to the model.
|
||||
|
||||
### Personas
|
||||
|
||||
Built-ins (Engineer, Writer, Researcher, Scribe, Manager, Executive)
|
||||
are seeded by turnstone's migration. This deployment adds a custom
|
||||
default persona `marvin` (VM-specific: persistence rules, Gitea remotes,
|
||||
podman) via `scripts/persona.py` — the prompt text is versioned there
|
||||
and re-applied after a DB reset:
|
||||
Turnstone offers a few built-in personas (Engineer, Writer, Researcher,
|
||||
Scribe, Manager, Executive), which are seeded by turnstone's migration.
|
||||
|
||||
This deployment adds a custom default persona `marvin` (VM-specific:
|
||||
persistence rules, Gitea remotes, podman) via `scripts/persona.py` -
|
||||
the prompt text is versioned there and re-applied after a DB reset:
|
||||
|
||||
```sh
|
||||
python3 scripts/persona.py # --db data/turnstone.db default
|
||||
@@ -126,11 +75,9 @@ with `turnstone-console` running, use its admin API/Personas tab.)
|
||||
|
||||
### Skills
|
||||
|
||||
The 13 skills from the old opencode setup (`~/marvin/configs/opencode/skills`,
|
||||
copied into this repo under `skills/`) are imported into turnstone's
|
||||
DB-backed catalog via `scripts/import_skills.py`. The script runs
|
||||
INSIDE the VM (uses turnstone's storage layer + SKILL.md parser +
|
||||
risk scanner):
|
||||
Skills are checked in under `skills` in the `SKILL.md format.`
|
||||
These are imported into turnstone's DB-backed catalog via
|
||||
`scripts/import_skills.py`. The script runs inside the VM.
|
||||
|
||||
```sh
|
||||
scp -O -i configs/ssh/id_ed25519 -P 2222 -r skills scripts/import_skills.py \
|
||||
@@ -140,13 +87,5 @@ ssh -i configs/ssh/id_ed25519 -p 2222 marvin@localhost \
|
||||
```
|
||||
|
||||
Idempotent (`--update` re-imports + appends version rows). **Reboot the
|
||||
VM after importing** — the running server holds a stale WAL snapshot
|
||||
VM after importing** - the running server holds a stale WAL snapshot
|
||||
and won't see new rows until restart.
|
||||
|
||||
## Notes / trade-offs
|
||||
|
||||
- boco boots with `-snapshot`: **only the virtiofs shares persist.**
|
||||
Agent-installed packages, git clones outside `work/`, and podman image
|
||||
storage inside the VM are discarded on shutdown.
|
||||
- boco hardcodes `-smp 8`; memory via `VM_MEMORY=...M scripts/run.sh`.
|
||||
- The old setup's Traefik is dropped — hostfwd replaces it.
|
||||
@@ -34,7 +34,7 @@ Use the `tea` command to interact with Gitea.
|
||||
- **Communication**: Use `tea comment <number> "message"` to communicate with project maintainers (e.g., `@hulthe`).
|
||||
|
||||
## Responsibility
|
||||
- **Don't Drop the Ball**: When assigned a task or receiving a review comment, you MUST address it before moving on to other things. Ensure all follow-up actions ( (like replying to a comment) are completed.
|
||||
- **Don't Drop the Ball**: When assigned a task or receiving a review comment, you MUST address it before moving on to other things. Ensure all follow-up actions (like replying to a comment) are completed.
|
||||
|
||||
## Tips for Agents
|
||||
- **Stay Updated**: Regularly run `tea notifications` to check for new issues or PR reviews.
|
||||
|
||||
+3
-5
@@ -6,11 +6,9 @@ set -euo pipefail
|
||||
|
||||
export HOME=/home/marvin
|
||||
|
||||
# The boco kernel boots with hostname "(none)" (no systemd to read
|
||||
# /etc/hostname) — set it live so turnstone node IDs and service URLs
|
||||
# are sane (turnstone-vm_xxxx instead of (none)_xxxx). The Arch base
|
||||
# has no `hostname` binary, so use the syscall via python.
|
||||
python3 -c 'import socket; socket.sethostname("turnstone-vm")' || true
|
||||
# Set hostname here since podman prevents us from setting it during
|
||||
# build.-time. Turnstone requires a hostname to be set.
|
||||
python3 -c 'import socket; socket.sethostname("marvin-vm")' || true
|
||||
|
||||
# sshd: host keys baked per-boot, ops channel on guest port 22
|
||||
ssh-keygen -A
|
||||
|
||||
Reference in new issue
Block a user