feat(svos): v0.0.16 live on nh3-svos — app-judge enrolled and up (gen-large drafting, six local task models); owner grants pending

This commit is contained in:
vh
2026-10-18 16:34:58 -07:00
parent e2d2f63693
commit 4f5c01390d
3 changed files with 159 additions and 0 deletions
+31
View File
@@ -0,0 +1,31 @@
# <data root>/config/apps/judge.toml on nh3-svos — app-judge 0.0.1 (U19), from apps/judge/examples/judge.toml at v0.0.16.
# Prime 2026-10-18: drafting on gen-large (local, free); tasks may run on the six local chat models (the hermes runtime's
# `models` in instance.toml). The gateway key (vault nh3-svos/svos-judge-gateway-key, LiteLLM alias svos-app-judge) is
# scoped to exactly those six, so the /tasks model select offers exactly them.
[gateway]
base = "http://10.250.50.70:4000/v1"
credential_env = "SVOS_JUDGE_GATEWAY_KEY" # /etc/svos/judge.env (root 0600); a project-scoped key, never the shared one
[propose]
model = "gen-large" # hosted_vllm qwen3.8-flash on fv-ml1 :8022 — free; step up only on Prime's call
max_tokens = 4000
[admit]
scan_app = "app-terminal"
[[routes]]
role = "*"
runtime = "hermes"
model = "gen-large"
[limits]
models_seconds = 10
propose_seconds = 120
admit_seconds = 8
route_seconds = 5
catalog_seconds = 30
concurrency = 8
reply_bytes = 1048576
brief_bytes = 262144
health_seconds = 5
+30
View File
@@ -0,0 +1,30 @@
# eshpfi configs/svos-apps/ (infra-ops, 2026-10-07, a737a06 refresh), modelled on svoperatingsystem
# deployment/nh3-svos/svos-interface.service. The credential is /etc/svos/judge.env (root 0600, SVOS_APP_CREDENTIAL),
# minted by enrollment on the private kernel listener. Listed in the qemu-ga quiesce hook (configs/qemu-ga/svos/50-svos).
[Unit]
Description=SVOS Judge app (app-judge, U19): model catalogue, drafted checks, admission and routing for task seats
After=svos-kernel.service
Requires=svos-kernel.service
ConditionPathExists=/etc/svos/judge.env
[Service]
Type=simple
User=svc-svos
Group=svc-svos
UMask=0077
WorkingDirectory=/var/lib/svos
EnvironmentFile=/etc/svos/judge.env
Environment=SVOS_KERNEL_URL=http://127.0.0.1:8400
Environment=SVOS_DATA_ROOT=/var/lib/svos
Environment=SVOS_APP_LISTEN=127.0.0.1:8409
ExecStart=/opt/svos/current/apps-env/bin/svos-judge
Restart=on-failure
RestartSec=3
TimeoutStopSec=20
KillMode=control-group
NoNewPrivileges=yes
ProtectSystem=strict
ProtectHome=yes
PrivateTmp=yes
ReadWritePaths=/var/lib/svos
[Install]
WantedBy=multi-user.target
@@ -0,0 +1,98 @@
# nh3-svos -> SVOS v0.0.16 (b51aa5e): kernel 0.0.16, UI 0.0.20, NEW app-judge 0.0.1 (U19; contract § Deployment).
# Prime 2026-10-18 ~0933 "go with your picks, cut over now": drafting model gen-large; tasks may run on the six local
# chat models. PRE-REQS (done before this playbook): the stage playbook; /root/svos-judge-enroll (mint-secret, root 0600);
# /etc/svos/judge.env holding SVOS_JUDGE_GATEWAY_KEY (LiteLLM svos-app-judge, vault nh3-svos/svos-judge-gateway-key).
# This playbook: install unit + judge.toml + quiesce entry; stop; backup; switch; config ([[apps]] app-judge, hermes
# `models`); start; enrol (credential appended to judge.env + printed NOWHERE); start the judge; front door.
# AFTER: Prime's three owner grants (svos-dev's console snippet), then [tasks].judge = "app-judge" + reload.
steps:
- name: Pre-reqs present
sudo: true
shell: test -f /opt/svos/releases/b51aa5e/apps-env/bin/svos-judge && test -s /root/svos-judge-enroll && grep -q '^SVOS_JUDGE_GATEWAY_KEY=' /etc/svos/judge.env && ! grep -q '^SVOS_APP_CREDENTIAL=' /etc/svos/judge.env
changed_when: "false"
- {name: judge unit, upload: {src: configs/svos-apps/svos-judge.service, dest: /etc/systemd/system/svos-judge.service, mode: "0644"}, sudo: true}
- {name: judge config, upload: {src: configs/svos-apps/judge.toml, dest: /var/lib/svos/config/apps/judge.toml, mode: "0600"}, sudo: true}
- name: judge.toml owned by svc-svos; quiesce hook lists svos-judge; daemon-reload
sudo: true
shell: |
set -e
chown svc-svos:svc-svos /var/lib/svos/config/apps/judge.toml
h=/etc/qemu/fsfreeze-hook.d/50-svos
grep -q "svos-judge.service" $h || { cp -p $h $h.pre-judge; sed -i "s/'svos-postoffice.service', 'svos-voice.service')/'svos-postoffice.service', 'svos-voice.service', 'svos-judge.service')/" $h; }
grep -n "svos-judge.service" $h; python3 -m py_compile $h 2>/dev/null || python3 -c "import ast,sys; ast.parse(open('$h').read())"
systemctl daemon-reload
- name: Stop the local apps then the kernel
sudo: true
shell: systemctl stop svos-voice svos-knowledge svos-interface svos-kernel; systemctl is-active svos-kernel svos-interface svos-knowledge svos-voice | tr '\n' ' '; echo
- name: Offline backup to /var/lib/svos/backup/pre-b51aa5e
sudo: true
shell: |
set -e
d=/var/lib/svos/backup/pre-b51aa5e
runuser -u svc-svos -- install -d -m 0700 $d
runuser -u svc-svos -- python3 -c "
import sqlite3
s = sqlite3.connect('/var/lib/svos/state/svos.db'); t = sqlite3.connect('$d/svos.db'); s.backup(t); t.close(); s.close()
c = sqlite3.connect('file:$d/svos.db?mode=ro', uri=True); print('integrity', c.execute('pragma integrity_check').fetchone()[0], 'user_version', c.execute('pragma user_version').fetchone()[0])"
runuser -u svc-svos -- cp -p /var/lib/svos/config/instance.toml /var/lib/svos/config/instance.toml.pre-b51aa5e
- name: Switch current to b51aa5e
sudo: true
shell: ln -sfn /opt/svos/releases/b51aa5e /opt/svos/current.new && chgrp -h svc-svos /opt/svos/current.new && mv -T /opt/svos/current.new /opt/svos/current && readlink /opt/svos/current
- name: Config - [[apps]] app-judge (enrollment sha256 from the minted secret) + the hermes runtime's models; the new kernel must accept it (else restore + 57d90d6)
sudo: true
shell: |
sha=$(sed -nE 's/^sha256 ([0-9a-f]{64})$/\1/p' /root/svos-judge-enroll); test ${#sha} -eq 64
runuser -u svc-svos -- python3 - "$sha" <<'PY'
import os, sys
sha = sys.argv[1]
p = "/var/lib/svos/config/instance.toml"; s = open(p).read()
assert 'slug = "app-judge"' not in s
anchor = '[[apps]]\nslug = "app-knowledge"\n'
assert s.count(anchor) == 1
add = ('[[apps]] # U19 (v0.0.16, 2026-10-18): the judge; enrolled once, unit svos-judge\n'
'slug = "app-judge"\nname = "Judge"\nbase_url = "http://127.0.0.1:8409"\nenrollment_sha256 = "' + sha + '"\n\n')
s = s.replace(anchor, add + anchor)
old = 'task_toolsets = ["terminal", "file"]\n'
assert s.count(old) == 1
s = s.replace(old, old + '# 2026-10-18 (Prime): the chat models a task may run on (the /tasks select = the judge key\'s catalogue ∩ this list)\n'
'models = ["gen-large", "gen", "gen-reasoning", "gen-small", "sec", "sec-reasoning"]\n')
t = p + ".tmp"; fd = os.open(t, os.O_WRONLY | os.O_CREAT | os.O_TRUNC, 0o600)
with os.fdopen(fd, "w") as f: f.write(s)
os.replace(t, p); print("edited")
PY
if runuser -u svc-svos -- /opt/svos/releases/b51aa5e/kernel-env/bin/svos-kernel check-config --data-root /var/lib/svos; then exit 0; fi
runuser -u svc-svos -- cp -p /var/lib/svos/config/instance.toml.pre-b51aa5e /var/lib/svos/config/instance.toml
ln -sfn /opt/svos/releases/57d90d6 /opt/svos/current.new && chgrp -h svc-svos /opt/svos/current.new && mv -T /opt/svos/current.new /opt/svos/current
systemctl start svos-kernel.service svos-interface svos-knowledge svos-voice; echo "RESTORED config + 57d90d6"; exit 1
- name: Start the kernel then the local apps
sudo: true
shell: |
t0=$(date +%s.%N); systemctl start svos-kernel.service; rc=$?; t1=$(date +%s.%N)
echo "kernel start rc=$rc after $(python3 -c "print(round($t1-$t0,2))") s"
systemctl start svos-interface svos-knowledge svos-voice
sleep 8; curl -s http://127.0.0.1:8400/health; echo
- name: Enrol app-judge once; append the credential to judge.env (never printed); vault copy is done from nh3-dev
sudo: true
shell: |
set -e
grep -q '^SVOS_APP_CREDENTIAL=' /etc/svos/judge.env && { echo "already enrolled"; exit 0; }
tok=$(sed -nE 's/^token (sve_[A-Za-z0-9_-]+)$/\1/p' /root/svos-judge-enroll)
body=$(printf 'Authorization: Bearer %s\n' "$tok" | curl -s -X POST -H @- http://127.0.0.1:8400/auth/enroll)
unset tok
printf '%s' "$body" | python3 -c "import sys,json; d=json.load(sys.stdin); assert d['credential'].startswith('svc_'), 'no credential'; print('SVOS_APP_CREDENTIAL=' + d['credential'])" >> /etc/svos/judge.env
printf '%s' "$body" | python3 -c "import sys,json; d=json.load(sys.stdin); print('enrolled principal', d.get('principal'), 'kind', d.get('kind'))"
unset body; chmod 600 /etc/svos/judge.env; grep -oE '^[A-Z_]+=' /etc/svos/judge.env | tr '\n' ' '; echo
- name: Start the judge (its first manifest pins without a card), then the front door
sudo: true
shell: |
systemctl enable --now svos-judge; sleep 6; systemctl is-active svos-judge
journalctl -u svos-judge --since "-60s" --no-pager -o cat | grep -iE "regist|manifest|pin|health|degraded|error" | tail -6 | cut -c1-200
/usr/local/sbin/svos-front-inventory 2>&1 | grep -E 'GENERATED|updated|root \*|path /assets' | head -4
verify:
- name: Health schema 14 ok, nothing down
shell: h=$(curl -s http://127.0.0.1:8400/health); echo "$h"; echo "$h" | grep -q '"status":"ok"' && echo "$h" | grep -q '"down":0'
changed_when: "false"
- name: Front door inventory current
sudo: true
shell: /usr/local/sbin/svos-front-inventory --check
changed_when: "false"