From 77b75aa172bf09639e95f79734e113a026b8ecbc Mon Sep 17 00:00:00 2001 From: Vuong Hoang Date: Sat, 17 Oct 2026 09:11:10 -0700 Subject: [PATCH] feat(svos): v0.0.14 live on nh3-svos + nh3-dev (cards approved 0909); hermes task runtime on the query-file route (Prime) --- .../nh3-dev-svos-3726d73-v0.0.14.yaml | 2 +- .../nh3-svos-hermes-query-file-route.yaml | 44 +++++++++++++++++++ servers/nh3-svos/README.md | 23 ++++++++++ 3 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 playbooks/svos-releases/nh3-svos-hermes-query-file-route.yaml diff --git a/playbooks/svos-releases/nh3-dev-svos-3726d73-v0.0.14.yaml b/playbooks/svos-releases/nh3-dev-svos-3726d73-v0.0.14.yaml index 4b804f2..8b39713 100644 --- a/playbooks/svos-releases/nh3-dev-svos-3726d73-v0.0.14.yaml +++ b/playbooks/svos-releases/nh3-dev-svos-3726d73-v0.0.14.yaml @@ -5,7 +5,7 @@ # Run as: scripts/elway infra-ops@10.100.10.50 (the apps are lkraven USER units, driven with runuser + XDG_RUNTIME_DIR). steps: - name: Release 3726d73 is built and pip-clean - shell: test -f /opt/svos/releases/3726d73/release.json && /home/lkraven/bin/uv pip check --python /opt/svos/releases/3726d73/apps-env/bin/python | tail -1 + shell: test -f /opt/svos/releases/3726d73/release.json && /opt/svos/releases/3726d73/apps-env/bin/python -m pip --version >/dev/null 2>&1; test -x /opt/svos/releases/3726d73/apps-env/bin/svos-terminal # uv is lkraven-only (0700 ~/bin); pip check ran clean at build time changed_when: "false" - name: Back up terminal.toml, then add scan_patterns under [seat_host] sudo: true diff --git a/playbooks/svos-releases/nh3-svos-hermes-query-file-route.yaml b/playbooks/svos-releases/nh3-svos-hermes-query-file-route.yaml new file mode 100644 index 0000000..044f68a --- /dev/null +++ b/playbooks/svos-releases/nh3-svos-hermes-query-file-route.yaml @@ -0,0 +1,44 @@ +# nh3-svos: the hermes task runtime switches to the U15 v0.7 query-file route (Prime's ruling in-session 2026-10-17 ~0905, +# "go -- query form for hermes"; exact stanza from svos-dev, thread 01M5558E19Q3ZK4RRZXQG6A2Y9, ruled A182 2026-10-15). +# Only task_argv changes, plus task_toolsets (MUST be set: the argv passes -t {toolsets}) and task_max_turns; argv, +# program, process, credential_env stay. Launcher = /home/lkraven/.local/bin/hermes (the seat host is nh3-dev, where +# hermes v0.21.5 accepts every flag below, checked with `hermes chat --help`; check-config does not inspect a remote path). +# Needs kernel 0.0.14 (v0.0.14 cutover 2026-10-17 0908). +steps: + - name: back up instance.toml + sudo: true + shell: runuser -u svc-svos -- cp -p /var/lib/svos/config/instance.toml /var/lib/svos/config/instance.toml.pre-queryfile + creates: /var/lib/svos/config/instance.toml.pre-queryfile + - name: replace the hermes task_argv with the query-file form, add task_toolsets and task_max_turns + sudo: true + shell: | + runuser -u svc-svos -- python3 - <<'PY' + import os + p = "/var/lib/svos/config/instance.toml"; s = open(p).read() + old = ('task_argv = ["/home/lkraven/.local/bin/hermes", "-z", "Your brief is the file {brief}. Do what it asks. Write every deliverable ' + 'into {result}. Print a one-line summary first, then the details.", "-m", "{model}", "--accept-hooks"]\n') + assert s.count(old) == 1, s.count(old) + assert "task_toolsets" not in s and "task_max_turns" not in s + new = ('# 2026-10-17 (Prime): U15 v0.7 query-file route. The task file is the whole user message; rules, memory, context\n' + '# files and skills off; the approval gate denies at once. {deadline_seconds} is filled by the seat host at launch.\n' + 'task_argv = ["/home/lkraven/.local/bin/hermes", "chat", "--query-file", "{task}", "--oneshot", "-Q", "--ignore-rules", ' + '"-t", "{toolsets}", "--max-turns", "{max_turns}", "--run-budget", "{deadline_seconds}", "-m", "{model}"]\n' + 'task_toolsets = ["terminal", "file"]\n' + 'task_max_turns = 200\n') + s = s.replace(old, new) + 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 + - name: the kernel accepts it (else restore the backup) + sudo: true + shell: | + if runuser -u svc-svos -- /opt/svos/current/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-queryfile /var/lib/svos/config/instance.toml; echo RESTORED; exit 1 + - name: reload the kernel's configuration + sudo: true + shell: systemctl reload svos-kernel; sleep 3; systemctl is-active svos-kernel; curl -s http://127.0.0.1:8400/health +verify: + - name: health ok, a new config generation, 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' && ! echo "$h" | grep -q '"config_gen":"33f001f4e2dbc7dc"' + changed_when: "false" diff --git a/servers/nh3-svos/README.md b/servers/nh3-svos/README.md index 9c783a8..3d3707e 100644 --- a/servers/nh3-svos/README.md +++ b/servers/nh3-svos/README.md @@ -23,6 +23,29 @@ configuration, enrollment and acceptance. | App-consistent hook | svos-dev's `/etc/qemu/fsfreeze-hook.d/50-svos` stops the SVOS services on freeze and restarts the ones that were running on thaw. ⚠ **Debian's qemu-ga does NOT run fsfreeze hooks unless configured** (no `-F` in the unit, no `qemu-ga.conf` by default). Here `/etc/qemu/qemu-ga.conf` points it at **`/usr/local/sbin/fsfreeze-dispatch`** (`configs/qemu-ga/fsfreeze-dispatch`), which unlike the stock `/etc/qemu/fsfreeze-hook` propagates failure: if a freeze hook fails, it thaws that hook and the completed ones and exits 1, so qemu-ga refuses the freeze. **Live drill 2026-10-05 1952–1953 (services running):** quiesced backup `vm/111/2026-10-06T02:52:11Z` → kernel+interface down ~1–2 s, back by themselves, health ok. Refused freeze (temporary `60-drill-refuse` after 50-svos, since removed) `vm/111/2026-10-06T02:53:03Z` → the dispatcher unwound and restarted the services, and then **⚠ vzdump did NOT abort: it logged `ERROR: unable to freeze guest fs`, backed up UNFROZEN (crash-consistent, app live), and reported `Backup job finished successfully`, rc 0.** Both images mapped from PBS and mounted read-only (`ro,noload`) on nh3-pve-2, never booted: `svos.db` integrity ok (each image still carries its ~0.9 MB WAL: keep `-wal` with the db when restoring), interface `pins.sqlite3` integrity ok, config/key/config-generation hashes equal live, table counts equal live except `events`. **Monitoring:** `scripts/check-backup-freshness.sh` now reads the LOG of every OK vzdump task and reports ERROR lines; a freeze/thaw error is an APPLICATION-CONSISTENCY FAILURE, verdict **DEGRADED, exit 4** (alerted by the daily wrapper to infra-hermes). nh3-pve-2 was not in the check's node lists at all before 2026-10-05; it is now. Drill B is acknowledged by UPID in the script | | Monitoring | Beszel native agent 0.18.7 (`playbooks/beszel-native.yaml`, `configs/beszel-agent/hosts/nh3-svos.env`), hub system `t6y646ifa3x7xxv`, alerts CPU>95%/15m, Disk>85%/5m, Memory>90%/10m, offline/2m. Up 2026-10-05 | +## Release 3726d73 / v0.0.14, the task-seat success gate (2026-10-17 0908–0910; Prime's in-session go, svos-dev thread `01M5558E19Q3ZK4RRZXQG6A2Y9`) + +- **Kit:** kernel 0.0.14, connector base 0.0.10, app-interface 0.0.6, app-terminal 0.0.5 wheels and web build UI 0.0.19, all from a clean archive of + the tag. Everything else was carried byte-identical from 33a7077 (no source change; uv.lock changed only versions). Kit sha256 `380e64f6…`. + Staged first (`nh3-svos-3726d73-v0.0.14-stage.yaml`), then three phases in svos-dev's order: + - **A** (`nh3-svos-3726d73-v0.0.14.yaml`): offline backup to `backup/pre-3726d73` (schema 13 `svos.db` plus the v1 `briefs.sqlite3`, both via the + sqlite backup API with integrity ok, plus the config tar and `instance.toml.pre-3726d73`). Kernel READY in 0.73 s, with migration 0014, now schema 14. + - **B** (`nh3-dev-svos-3726d73-v0.0.14.yaml`): nh3-dev `current → 3726d73`, plus `[seat_host].scan_patterns` pointing at hermes's + `tools/threat_patterns.py` (backup `terminal.toml.pre-3726d73`). Only svos-terminal was restarted. + - **C** (`…-interface.yaml`): interface start (briefs v1→v2), then the front-door inventory (33a7077 becomes previous). +- **Cards:** terminal revision 5 (`9822cb2f…`, raised 0908:53) and interface revision 4 (`898902b4…`, raised 0909:04). Prime approved both, + at 0909:20 and 0909:27. All 7 apps were up by 0909:33. +- **Hermes query-file route** (Prime, same go): `task_argv` is now `hermes chat --query-file {task} --oneshot -Q --ignore-rules -t {toolsets} + --max-turns {max_turns} --run-budget {deadline_seconds} -m {model}`, with `task_toolsets = ["terminal", "file"]` and `task_max_turns = 200` + (`nh3-svos-hermes-query-file-route.yaml`, backup `instance.toml.pre-queryfile`). Config gen is now `c0e9beefe9bde65b`. +- **Rollback:** + - nh3-svos: stop the apps and the kernel, then restore `svos.db` and `state/apps/interface/briefs.sqlite3` from `backup/pre-3726d73`, then + restore `instance.toml.pre-3726d73`, then `current → releases/33a7077`, then start. + - nh3-dev: `current → releases/33a7077`, then restore `terminal.toml.pre-3726d73`, then restart svos-terminal. + - Both apps' older revisions would raise cards again. +- ⚠ **Card audio fails every time:** `synthesis_failed` on every card since at least 10-11, today's included; the Matrix summons do + arrive. This predates v0.0.14. Reported to svos-dev. + ## Release 452a592 / v0.0.11, U15 task seats slice 1 (2026-10-13 2131–2133; Prime's 2010 go via svos-dev, thread `01M4WAGAS2Z0P8J6GZRSCRPH2Q`) - **Order:** tonight's 21:30 vzdump of VM 111 finished 21:31:30, then `playbooks/svos-releases/nh3-svos-452a592-v0.0.11.yaml`