M1+M2+M3 — Mission Dependency Readiness
Generated 2026-05-01 02:23 (local) / 2026-04-30 23:23 UTC; verified against VPS 213.159.6.155:23422 and local macbook (darwin 23.4.0).
Status: READY (with caveats)
All hard dependencies resolved on both hosts; VPS has only ~221 MB RAM available and 6.2 GB disk free, and is running an existing openclaw-gateway container plus a live tailscaled.service — these need to be designed around but are not hard blockers. Inbound 80/443 from the macbook gets Connection reset by peer while no service is listening; expected to clear once Caddy binds those ports. Tailscale verification was deferred per user instructions, but tailscaled is already installed/running on the VPS.
A. Local macbook (orchestrator host)
| Item | Result | Detail |
|---|---|---|
| Python 3.12+ | ✓ | Python 3.12.1 at /path/to/python3 |
Project venv (.venv/) | ✓ | Python 3.12.1, editable install of whilly-orchestrator 4.0.0 (pyproject says 4.3.1; editable not re-synced — see Constraints) |
| Project deps in venv | ✓ | alembic 1.18.4, asyncpg 0.31.0, fastapi 0.136.1, httpx 0.28.1, keyring 25.7.0, pydantic 2.13.3, testcontainers 4.14.2. Jinja2 3.1.6 also already present in the system pip (not necessarily venv). No prometheus* / sse-starlette yet — will be added by mission. |
| Docker | ✓ | client 24.0.7 (colima context), server 27.4.0, daemon up, 1 stopped container, 19 images, overlay2 storage driver |
pip resolve: prometheus-fastapi-instrumentator>=7.1.0 | ✓ | resolved to 7.1.0 in throwaway venv /tmp/whilly-readiness-1777580573/venv |
pip resolve: sse-starlette>=2.0 | ✓ | resolved to 3.4.1 |
pip resolve: jinja2>=3.1 | ✓ | resolved to 3.1.6 |
pip resolve: prometheus-client>=0.20 | ✓ | resolved to 0.25.0 |
| Combined import smoke test | ✓ | import prometheus_fastapi_instrumentator, sse_starlette, jinja2, prometheus_client → 'IMPORT OK' |
Local caddy binary | ✗ (acceptable) | not installed; not in brew. Fallback: docker run --rm caddy:2-alpine caddy validate |
gh | ✓ | 2.83.2 (2025-12-10) |
git | ✓ | 2.39.3 (Apple Git-146) |
rg | ✓ | 13.0.0 |
jq | ✓ | 1.8.1 |
curl | ✓ | 8.4.0 (LibreSSL/3.3.6) |
ssh | ✓ | OpenSSH_9.7p1, OpenSSL 3.6.2 7 Apr 2026 |
| Required ports free (8000, 8001, 5432, 3100, 80, 443) | ✓ | lsof … LISTEN returns “none in use” for all six |
agent-browser skill | △ | Listed in Factory <available_skills> (personal); no on-disk path under ~/.factory/skills/ (skill discovery is via Factory runtime, not a filesystem). Invoke via Skill tool. |
tuistory skill | △ | Same as above — present in <available_skills> (personal). |
Repo state: branch main, HEAD 1093009afe8dfddf48ab15ef66c726d6a1a284be (matches 1093009), git status --porcelain shows only ?? .planning/distributed-audit/ (expected per task).
B. VPS (213.159.6.155:23422 as root)
| Item | Result | Detail |
|---|---|---|
| SSH | ✓ | BatchMode=yes succeeds (key-based auth via local agent). uname: Linux srv.tr-anet-01.com 5.10.0-37-amd64 SMP Debian 5.10.247-1 (2025-12-11) x86_64; uptime 80 days, load 0.00. |
| OS / arch | ✓ | Debian GNU/Linux 11 (bullseye) / x86_64 |
| Docker | ✓ | Docker version 29.2.1, build a5c7197; Docker Compose version v5.0.2 (CLI plugin v5.0.2 — note: this is unusually labelled — v2.x is current upstream; v5.0.2 appears to be a Docker Inc. plugin re-numbering. Compose subcommand works.) |
| Docker daemon | ✓ | containerd + docker.service running; 1 container running (openclaw-gateway); containerd v1.x via Docker Engine Community |
| Free ports | ✓ for 80, 443, 8000, 5432; expected listeners only — see detail | Listeners: :23422 sshd, :18789 openclaw-gateway, 127.0.0.1:18792 openclaw-gateway. Nothing on 80/443/8000/5432/3100. |
| Public IP confirmation | ✓ | curl https://ifconfig.me → 213.159.6.155 (matches expected; not behind NAT) |
| sslip.io DNS resolves from macbook | ✓ | dig +short 213-159-6-155.sslip.io → 213.159.6.155 |
| sslip.io DNS resolves from VPS | △ | dig and nslookup not installed on VPS (bash: dig: command not found). However outbound DNS clearly works (PyPI / GitHub HTTPS calls succeed below). Acceptable; getent hosts 213-159-6-155.sslip.io would be the tool to use during M2. |
| Inbound 80 reachable from macbook | △ | TCP handshake completes then Connection reset by peer (curl exit 56). No process is bound to :80 yet, so this is the kernel/firewall behavior with no listener. Expected to “just work” once Caddy binds 80/443; flag for verification at M2 deploy time. |
| Inbound 443 reachable from macbook | △ | Same behaviour as :80 (TLS handshake aborts on RST, curl exit 35). |
Disk headroom (/) | ⚠ | /dev/sda1: 20G total, 13G used, 6.2G available, 68% used. Pulling Caddy + Postgres + control-plane + worker images will eat ~1–2 GB; should fit but leaves <5 GB headroom. Recommend a docker system prune plan in M2. |
| RAM headroom | ⚠ | total 964 MB, used 608 MB, free 70 MB, available 221 MB; swap 2047 MB total / 740 MB used. Postgres + FastAPI + Caddy on 1 GB RAM is tight. Consider shared_buffers=128MB, low max_connections, and --memory limits in compose. |
| Conflicting services | ⚠ | openclaw-gateway container bound to :18789 (and 127.0.0.1:18792) — does not conflict with Whilly ports. tailscaled.service is active (Tailscale check is deferred per user — but the agent is already installed and running). unattended-upgrades active (could cause surprise reboots — flag for ops note). No Postgres, no Caddy, no nginx running. |
| PyPI reachable | ✓ | https://pypi.org/simple/ returns HTML root |
| GitHub reachable | ✓ | https://github.com/ HTTP 200 |
Whilly version pinning
| File | Version |
|---|---|
whilly/__init__.py | __version__ = "4.3.1" |
pyproject.toml (line 7) | version = "4.3.1" |
whilly_worker/pyproject.toml (line 32) | version = "4.3.1" |
✓ All three pins agree on 4.3.1. (The .venv editable install reports 4.0.0 because the editable record was installed before the bump and hasn’t been re-installed; not a release blocker but worth a pip install -e '.[dev]' before mission start to keep version_info consistent.)
Blockers
None. Every hard dependency is satisfied or trivially installable.
Discovered Constraints
- VPS RAM is the tightest constraint. 964 MB total, 221 MB available, swap heavily used. Compose stack must explicitly cap memory; M3 Prometheus scraping should be sampled, not high-rate.
- VPS disk is at 68 % with 6.2 GB free. Plan for image hygiene (
docker image prune,caddy:2-alpineinstead of full image, slim Postgres image). openclaw-gatewayalready runs on:18789and 127.0.0.1:18792. Whilly must not bind those ports. (M1’s planned ports 8000/5432 are clear.)tailscaledis already installed and running on the VPS. (Not verified per user instructions — but mission’s M2 Tailscale spike has a head start: the daemon is up; onlytailscale up/ auth-key flow is needed.)unattended-upgrades.servicecan reboot the box mid-task. M2 should document this and considerdpkg --get-selections/apt-mark holdfor kernel pkgs once up.- Inbound 80/443 right now returns
Connection reset by peerbecause nothing is listening. There is no firewall hop dropping SYN-ACKs — the TCP handshake completes — so when Caddy binds these ports they should serve. Re-verify reachability once Caddy is deployed in M2. - DNS tools (
dig,nslookup) absent on VPS. Adddnsutilsto bootstrap apt-install if Caddy debugging is needed;getent hosts <name>works in the meantime. Composeplugin reportsv5.0.2on the VPS — unusual versioning compared to upstream 2.x; assume it implements the v2 schema. Recommend pinning compose schema withservices.<svc>.imagepatterns that work on both v2 and v5 plugins..venveditable install lags pyproject (records4.3.1source but4.0.0metadata). Runpip install -e '.[dev]' --force-reinstall --no-depsonce before mission to align.agent-browserandtuistoryskills are not on disk under~/.factory/skills/; they are listed in the Factory runtime skill manifest as(personal). Validation invocations must go through theSkilltool — confirmed available.
Recommendations
- Before M1 dispatch: run
pip install -e '.[dev]' --force-reinstall --no-depsin.venv/to align installed version metadata with4.3.1. - M1 LAN compose: bind orchestrator UI/control-plane to
127.0.0.1:8000on the VPS behind Caddy to avoid exposing FastAPI directly; keep Postgres on127.0.0.1:5432. - M2 Caddy: pin
caddy:2-alpine(≈50 MB) and validate the Caddyfile viadocker run --rm -v $(pwd)/Caddyfile:/etc/caddy/Caddyfile caddy:2-alpine caddy validate --config /etc/caddy/Caddyfileon the macbook before pushing. - M2 ACME on sslip.io: HTTP-01 path is viable (public IP confirmed, port 80 free, DNS resolves). Use
213-159-6-155.sslip.ioas the canonical hostname; have a fallback--internalCaddy mode for first-boot smoke tests. - M2 bootstrap tokens:
keyring 25.7.0is already installed in.venv— good to go. - M3 Prometheus: pin
prometheus-fastapi-instrumentator==7.1.0andprometheus-client==0.25.0. Scrape interval ≥ 30 s on the VPS to keep RSS small. Co-locate Grafana/Loki only if you can spare 200–300 MB RSS — otherwise stream metrics to the macbook. - M3 SSE: pin
sse-starlette==3.4.1; test pause/resume against the existingdashboard.Dashboardkeymap. - Docker hygiene: run
docker system prune -af --volumeson the VPS before first M2 deploy to free disk. - Mid-mission validation: use the
Skilltool withagent-browserfor HTMX/SSE UI smoke tests andtuistoryforwhilly worker connectCLI flows — both are present in the runtime skill manifest. - Defer Tailscale work to M2 spike per plan; tailscaled is already running, which de-risks that spike.