99 lines
7.1 KiB
YAML
99 lines
7.1 KiB
YAML
# 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"
|