The substrate
contradiction-preserving · evidence-first

donto box — workers, jobs & capacity (live catalogue, 2026-06-29)

A verified-live inventory of every worker, job, daemon and queue on the donto box, the hardware it runs on, and a safe-concurrency budget (what can run together without overloading it). Built from a 6-way parallel live sweep (systemctl / docker / Temporal / psql / coordinator API), not from the docs — several doc entries were stale and are corrected inline. Raw data: donto-resources/infra/worker-catalogue-raw-2026-06-29.json.


1. The box

Host OVH VPS (migrated off GCloud) · public IP 15.235.185.42
CPU 8 vCPU (Intel Haswell, 1 thread/core)
RAM 22 GiB (≈16 GiB available, ~9 GiB buff/cache)
Swap 55 GiB (8 GiB /swapfile + 48 GiB /swapfile2) — both ~fully used
GPU none (virtual Cirrus GD-5446 only). All GPU embedding is off-box (donto.org/help contributors)
Disk / 193 GB, 62% used (75 GB free)
Disk /mnt/donto-data 984 GB, 34% used (623 GB free) — pgdata, blobs, backups, workspace
Substrate DB donto-pg (Postgres 16 + pgvector, docker, host :5432), ~42.4M donto_statement rows

Correction to the docs: CLAUDE.md still says 4 vCPU / 16 GB / GCloud 34.135.161.87. The live box is 8 vCPU / 22 GB / OVH 15.235.185.42, with much larger disks.

This box is multi-tenant. Besides donto it runs: the Omega Discord stack (bot/web/jobs/mongo/postgres/deployer), MobTranslate (web/tts/pg), the full tpmjs.com stack (web/playground/tutorial + 2 Deno sandboxes), and the observability stack (OpenObserve/OTel/Umami). That is the always-on baseline every heavy job competes with.


2. ⚠️ The #1 capacity problem right now: a runaway health-view poll

The single biggest thing overloading the box is not a legitimate worker. A donto-role host service polls dontosrv's substrate-health endpoint — select row_to_json(donto_v_substrate_health.*) — on a long-lived connection. That view full-scans the 42M-row substrate (~20+ minutes each), and because the donto role has no statement_timeout, repeated polls pile up: at sweep time there were 9 concurrent copies, the oldest 24 minutes, driving load to 25–33 on 8 vCPU with ~18 GB swap in use.

This single pile is the cause of: the embedding contributor's submit timeouts (Cloudflare 504/524), slow builds, and the test-runner worker-start timeouts seen all session.

Relieved (cancelled the 18 stuck read-only queries — safe, no data touched), but it recurs because the poller keeps issuing it. Recommended durable fix (needs a decision — touches the substrate):

  1. Make donto_v_substrate_health cheap — back it with reltuples + the existing matviews instead of live count(DISTINCT …) and a SUM over the 6.3M-row donto_contradiction_pressure matview (the same reltuples trick already used by the admin overview). Migration 0147_substrate_health_fast started this; it needs finishing for today's row counts/load.
  2. Throttle / cache the poller (it does not need sub-minute fresh exact counts).
  3. Belt-and-suspenders: a generous statement_timeout for that read path (pg_dump sets its own =0, so backups are unaffected; the align daemon already self-caps).

3. Worker / job catalogue (by function)

All VERIFIED active/running unless marked. 30 donto systemd units, 0 failed.

3.1 Substrate & core APIs

Service Port Role
donto-pg (docker) 5432 THE substrate DB (PG16+pgvector, ~42.4M statements)
dontosrv 7879 Rust substrate HTTP API (the GOAL service; all consumers read through it)
donto-memory-api 7900 Memory consumer API (/memorize /recall /search /jobs)
donto-api 8000 Genealogy extraction/ingest API (doc says ~4001 — stale)
temporal + temporal-ui (docker) 7233 / 8233 Workflow/queue engine + UI

3.2 Extraction (Rust + Temporal fleet — replaced donto-agent-beam)

The doc's headline donto-agent-beam.service is gone/inactive. Extraction is now a Temporal Rust pipeline:

Service Queue Status
donto-extract-temporal-rust-scheduler leases donto_extract_queue → per-lane queues active, but throughput ~0 (recurring "connection not ready" restarts; MAX_STARTS_PER_TICK=4)
donto-extract-temporal-rust@hyades extract-hyades active, idle — the bulk lane (free holo3.1)
donto-extract-temporal-rust@codex extract-codex active, idle — best-anchored
donto-extract-temporal-rust@glm extract-glm active, idle — lane capped
donto-extract-temporal-rust@openrouter extract-openrouter active, idle — do-not-use (per-token)
donto-extract-citer 7942 always-on evidence anchoring (bge-small)
donto-api-worker Temporal donto-extraction active, idle (genealogy path)

3.3 Embedding fabric (bge-small-en-v1.5 / 384-dim)

Component Port Status
donto-embed-coordinator 7930 active — work queue donto_embed_queue is DRAINED (4.6M done · 233 stuck-leased · 0 pending)
Remote workers — NUC8i7HNK pool (gpu1/gpu2 + w1–w11) only gpu2 leasing; failing every submit (504/524) due to the box overload → 0 productive now
donto-memory-embed-768 7912 bge-base 768-dim query vectors (episodic recall arm) — different model, query-time only
embed_memory.py memory_chunk backfill, ~2–4 chunk/s CPU-bound, not running
Coverage predicate ~100% (1.08M) · entity ~3.0M · claim ~1.49M · memory_chunk ~459K

3.4 Alignment

Component Status
donto-align-daemon active, 600 s tick: embed-gap fill → propose → GLM-adjudicate → ~12 h closure/identity rebuild. Backlogs: predicate-candidate 77,492, identity 1,684. total_accepted=0 / total_rebuilds=0 since the 09:49 restart (last real rebuild 2026-06-22); GLM-rate-limited. CPU-light itself; heavy embed offloaded to the fabric.
Query-time folding donto_predicate_alignment (98,882) · donto_predicate_closure (~1.1M ≈ predicate count). Note: the doc's donto_match_aligned table does not exist.

3.5 Memory

Service Port Role
donto-memory-api 7900 API
donto-memory-worker sleep-path reconsolidation worker (the live successor to the old Temporal memory-worker, which is gone)
donto-memory-rerank 7903 cross-encoder reranker (hybrid recall)
donto-memory-embed-768 7912 query vectors
Queue donto_x_memory_reconsolidation_queue 44,526 rows queued, not draining (its Temporal worker is inactive)

3.6 Web · Bot · Observability · Research

Function Services
Web donto-home:3100 · donto-memory-web:3101 · donto-genealogy-web:3102 · donto-admin-web:3103 · dontopedia-web:3000 (doc says 8000 — stale) · donto-debug:3002
Bot (Omega) omega-tellus-bridge:7940 · omega-pov-view:7941 · omega-vm-omega-bot (Discord, GLM-backed) · omega-vm-omega-jobs (Temporal omega-ai, profile-analysis ~30 min)
Observability otel-collector (4317/4318) · openobserve:5080 · umami:7960 · donto-logs:7950 · donto-scanner-api:7920 · temporal-ui:8233
Research donto-research-worker (Temporal donto-research, SearXNG+GLM) · donto-searxng:8889
Backups/timers donto-db-backup (cron.daily, verified — fresh 17 GB dump today, KEEP=5) · donto-resource-sweep.timer (hourly :17)

4. Inference lanes — the real constraint

Extraction/adjudication/research throughput is gated by inference capacity, not the box. Live state:

Lane Model Cost Status now
Hyades holo3.1 (256K ctx) + AEON-7/Qwen3.6-27B (128K) free / no cap (user's gateway) UP — the workhorse with headroom. Route bulk here.
codex gpt-5.3-codex-spark (ChatGPT Pro) flat (hidden weekly cap) UP, leftover — best-anchored
GLM z.ai coding flat (weekly cap) EXHAUSTED (error 1310) until 2026-07-01 16:43Z → degrades omega bot, research, tribunal, align adjudication
Cerebras flat / sold-out DEAD (payment_required)
OpenRouter per-token reachable but OFF-LIMITS (budget)

Net usable inference right now = Hyades + codex. Everything that depends on GLM is degraded until 2026-07-01.


5. Queues & backlogs (the work waiting)

Queue Depth Worker State
donto_extract_queue 352,175 pending / 10,051 done (1.33M claims) extract scheduler + lanes STALLED — scheduler not draining; growth ~0 since Jun-27
donto_x_memory_reconsolidation_queue 44,526 (Temporal memory-worker) not draining (worker inactive)
donto_embed_queue 0 pending / 4.6M done / 233 stuck-leased coordinator + remote drained (embed CPU is free)
align predicate-candidate 77,492 align daemon draining slowly (GLM-capped)

6. Safe-concurrency budget

Baseline (idle, healthy): Postgres + Temporal(java) + OTel + OpenObserve + ~15 web/python services ≈ load 4–8 at rest on 8 vCPU. RAM is comfortable (16 GB available); swap is heavily used but cold.

The CPU-bound contenders (each wants a core under load): donto-align-daemon (bge-small), donto-extract-citer (bge-small), donto-memory-rerank (cross-encoder), embed_memory.py backfill, local embed services, and any Next.js build. The extraction lane workers are network/inference-bound (the CPU cost is the citer+ingest, not the model), so extraction throughput is capped by the lane, not the box.

Empirical (measured this session):

  • one next build → load +3–6; four parallel builds → load ~25 (serialize them).
  • the test runner (vitest) can't boot its workers if load > ~12 (60 s startup timeout).
  • the runaway substrate_health poll alone → load +20.

Rules of thumb:

  1. Fix §2 first. With the health-view pileup gone, the legit fleet sits at ~load 4–8 and everything else has room.
  2. Serialize heavy CPU jobs. Run at most one of {a build, an embed_memory backfill, a CPU-heavy extraction batch} at a time. Two+ pushes load > 15 and starves the daemons.
  3. Extraction scales on the lane, not the box. You can run many extract-hyades/extract-codex tasks concurrently against the inference lanes with little box load — as long as the citer + ingest keep up (those are the CPU cost). Hyades parallelizes (~5 concurrent cleanly).
  4. Embedding backlog is currently zero, so embed CPU is free — but a big new backfill is single-process CPU-bound (~2–4 chunk/s); budget it as one heavy job and prefer the off-box GPU contributors for volume.
  5. Keep ~2 cores free for Postgres + Temporal at all times; they back every worker.

7. Issues found — prioritized action list

  1. ⚠️ substrate_health poll overload (§2) — relieved, recurs. Make the view cheap + throttle the poller. Biggest single win.
  2. ⚠️ Duplicate Postgres on the same data dir. donto-pg-pre-pgvector is a second live postmaster bind-mounted to the same /mnt/donto-data/pgdata as donto-pg (verified identical PG_VERSION). Two postmasters on one data dir is a corruption hazard — stop/remove it. (No published port, so nothing reaches it — but I3 "never lose data" says fix this.)
  3. dontopedia-worker crash-looping. Container "Up" but fatal-looping on TEMPORAL_ADDRESS=10.128.0.3:7233 (a dead GCloud IP). Repoint to temporal:7233.
  4. Extraction stalled — 352K backlog, scheduler not draining ("connection not ready" restarts; MAX_STARTS_PER_TICK=4). Route to Hyades+codex once the box is healthy.
  5. Memory reconsolidation backlog 44,526 not draining (worker inactive).
  6. GLM lane exhausted until 2026-07-01 — omega bot, research, tribunal, align-adjudication all degraded.
  7. 7 of 8 matviews drift (no refresh job) — incl. donto_contradiction_pressure (1.7 GB), subject_count (1.26 GB), predicate_idf. Only donto_mv_context_stats auto-refreshes.
  8. donto_align_daemon_tick history stopped writing 2026-06-22 (status table still ticks).
  9. omega-vm-caddy-1 stuck "Created" (port-80 conflict with host caddy) — harmless leftover.