diff --git a/persistent-memory.d/2026-07-18-fleet-gitea-runner-build-recipe.md b/persistent-memory.d/2026-07-18-fleet-gitea-runner-build-recipe.md new file mode 100644 index 0000000..2c04e93 --- /dev/null +++ b/persistent-memory.d/2026-07-18-fleet-gitea-runner-build-recipe.md @@ -0,0 +1,57 @@ +- `[2026-07-18]` **Fleet Gitea-Actions build recipe + the `vh`-is-a-user package-write constraint** (learned the hard way across 3 failed soong-lab validation builds; reusable for ANY fleet CI image build or package publish). + +**The runner.** One `act_runner` (`gitea/act_runner`) on ana-docker, labels +`pfi-fleet` / `ana-docker` → both map to job image **`node:20-bookworm-slim`**, +which has **NO docker and NO git**. Config `/opt/docker/conf/gitea-runner/data/config.yaml`: +`valid_volumes: []` (no socket propagated to job containers). So: +- `actions/checkout@v4` fails (needs git); `docker/*` marketplace actions fail + (need docker) — a workflow built on those dies at the first step (~15s). + +**The working recipe (mirror Worldtree `deploy.yml`).** Run the job in a +docker-capable image + drive docker with RAW commands, not the JS actions: +```yaml +runs-on: pfi-fleet +container: + image: docker:24.0.7-cli # has docker+buildx; add git+node +steps: + - run: apk add --no-cache git nodejs # so actions/checkout@v4 works + - uses: actions/checkout@v4 + - name: login # RAW, not docker/login-action + run: echo "$REGISTRY_TOKEN" | docker login gitea.phasefinal.com -u "$REGISTRY_USER" --password-stdin + - name: buildx builder + run: docker buildx create --name X --driver docker-container --use; docker buildx inspect --bootstrap + - name: build+push # RAW, not docker/build-push-action + run: docker buildx build --secret id=,env= -t :latest --push . +``` +The runner mounts the host docker socket into ITSELF; the docker:cli job reaches +the daemon through that. The `docker/*` JS actions are unreliable on act_runner — +raw commands are the fleet convention. + +**`vh` is a USER account, not an org.** Consequences that bit repeatedly: +1. `GET /api/v1/orgs/vh` → 404 "user redirect"; there are **no org teams** to add + a service account to. +2. **User-owned packages are OWNER-WRITE-ONLY.** claude-bot (even repo + admin-*collaborator* on `vh/soong-lab`, even with `write:package` scope + full + basic-auth) gets **`401 unauthorized`** on `docker push` to `vh/soong-lab`, and + `npm publish` to `vh/npm/` would 401 too. Only `vh` itself can write vh packages. + → CI must authenticate AS `vh` for the push (a vh-owned `write:package` PAT as + `REGISTRY_TOKEN` + `REGISTRY_USER=vh`), exactly how WT pushes `vh/worldtree`. + claude-bot CAN still: clone/read repos, READ packages (pulled the image fine), + dispatch workflows, mint demo Worldtree keys. +3. **Repo Actions secrets are OWNER-ONLY too** — `PUT .../actions/secrets/X` as + claude-bot (repo admin-collab) → 403 "user should be the owner of the repo". + Only `vh` can set a repo's secrets. + +**Other gotchas:** +- Gitea **reserves the `GITEA_` secret-name prefix** — a secret named + `GITEA_PYPI_TOKEN` is illegal; use e.g. `PYPI_TOKEN`. +- Gitea **package auth is token-based / username-lenient** — `docker login` / + PyPI basic-auth authenticate via the token; the username is nominal (tested + `-u gitea` and `-u claude-bot` both 200 against the vh PyPI). So a Dockerfile + hardcoding `UV_INDEX_GITEA_USERNAME=gitea` is fine with any valid token. +- Homepage (esh-docker-vm) docker-label auto-discovery only covers the 5 endpoints + in its `docker.yaml` (esh-vm-docker, ana-docker, ana-ml2, nh3-docker, irv-ml1); + **corviduo-dev is NOT watched** → services there need a manual `services.yaml` + entry, not labels. + +Applied in the soong-lab CI: [[2026-07-18-soong-lab-containerize-cutover]]. diff --git a/persistent-memory.d/2026-07-18-soong-lab-containerize-cutover.md b/persistent-memory.d/2026-07-18-soong-lab-containerize-cutover.md new file mode 100644 index 0000000..d46d36a --- /dev/null +++ b/persistent-memory.d/2026-07-18-soong-lab-containerize-cutover.md @@ -0,0 +1,46 @@ +- `[2026-07-18]` **soong-lab containerize cutover — COMPLETE + LIVE on corviduo-dev.** + +Migrated soong-lab (Noonien Soong character-design studio) from a hand-built +`soong-lab-studio.service` (systemd + git-pull-on-webhook) to a containerized +deploy, image built by CI + pushed to the Gitea registry. soong-dev owns the +in-repo artifacts (Dockerfile/compose/workflow/`docs/DEPLOY.md` = checklist); +infra-ops owned the host cutover. Operator confirmed functional ("Soong works +great" — a real Soong turn round-trips + saves) → cutover 100% closed. + +**Final state (corviduo-dev, 10.250.50.152):** +- Container `soong-lab-soong-lab-1` LIVE + healthy on `0.0.0.0:8443`, image + `gitea.phasefinal.com/vh/soong-lab:latest` (v0.3.24), `restart:unless-stopped` + (survives reboot; no systemd unit needed — docker restart policy handles boot). +- Deploy dir **`/home/infra-ops/soong-lab-deploy/`** — pull-based `compose.yaml` + (image + env_file + `8443:8443` + named volumes; NO build/secrets stanza) + + `.env` (copied from the live `soong-lab.env`, STRIPPED of the `SOONG_LAB_*_DIR` + overrides so the container uses image defaults `/data/library` + `/data/portraits` + + `/app/web` → the volumes). +- Named volumes `soong-lab_soong-library` + `soong-lab_soong-portraits`, migrated + from `/home/infra-ops/soong-lab-data/{library,portraits}` (2 saved designs incl. + **Sindra** + 27 portraits), **chowned `10001:999`** (the container `soong` user) + so it can read AND write new designs. +- Old `soong-lab-studio.service` + `soong-webhook.service` (the `:9010` git-pull + redeploy listener) both **stopped + disabled**. + +**Topology reality (≠ what DEPLOY.md assumed):** there is **NO TLS proxy**. +WT-personal (`:8081`) and soong-lab are **co-located on corviduo-dev**, and the +Bifrost callback is **plain-HTTP same-host** `http://10.250.50.152:8443` — the +value of `SOONG_LAB_BIFROST_ENDPOINT_URL`, unchanged by the move, so the WT +Bifrost host-allowlist stayed valid as-is. Nothing on the WT side needed touching. + +**Safety net:** data backup `/home/infra-ops/soong-lab-data-backup-20260718-091831.tar.gz` +(35M) taken BEFORE migration. Verified pre-retire: `/api/version` 200 (0.3.24), +SPA `/` 200, `POST /bifrost/tool-call` → 401 (route present + auth-gated), +bidirectional WT↔soong reachability, container healthcheck green. + +**Ops commands:** +- Redeploy a new image: `cd /home/infra-ops/soong-lab-deploy && sudo docker compose pull && sudo docker compose up -d`. + (Auto-pull-on-`:latest` — watchtower or a deploy hook — is an open follow-up.) +- Rollback: `sudo docker compose down` + `sudo systemctl enable --now soong-lab-studio.service soong-webhook.service`. +- Homepage tile: manual `- Apps:` entry "Soong Lab" (href http://10.250.50.152:8443) + in esh-docker-vm `/opt/docker/conf/homepage/services.yaml` — corviduo-dev isn't + a Homepage-watched docker endpoint, so docker-label auto-discovery can't surface + it (see [[2026-07-18-fleet-gitea-runner-build-recipe]] for the CI half). + +See [[reference_corviduo_dev_emergency_ops]], [[reference_claude_bot_gitea_creds]]. diff --git a/persistent-memory.d/2026-07-18-zonos-gateway-0.2.1-emotion-presets.md b/persistent-memory.d/2026-07-18-zonos-gateway-0.2.1-emotion-presets.md new file mode 100644 index 0000000..9a707e8 --- /dev/null +++ b/persistent-memory.d/2026-07-18-zonos-gateway-0.2.1-emotion-presets.md @@ -0,0 +1,41 @@ +- `[2026-07-18]` **zonos-gateway 0.2.1 — voice-resolved emotion presets baked (provisional) from the axes sweep.** + +After the axes sweep ([[reference_zonos_tts_stack]] + the `[2026-07-18] axes sweep` +Recent-decisions entry) rescued angry and confirmed startled-happy, the operator +green-lit baking the results as **provisional** gateway presets + docs. Shipped +`vh/zonos-gateway` **0.2.1** (main `8f1885b`, tag `v0.2.1`, PUSHED; deployed live +on irv-ml1 `:8890`). + +**Design — voice-resolved, NOT global.** `resolve_preset(name, voice)` picks the +per-voice measured cell, because a single global preset is unsafe (dvalin ruling; +BritishFemale's *named* angry misfires as fear). Presets: +- `angry`, `happy`, `startled_happy` (+ aliases `surprised`, `startled` → + startled_happy). All expressive (`accurate_mode:false`), cfg 1.5, pure-axes + (no named sliders). +- Calibrated cells (the 3 default voices): + - angry: AmF v-0.4/a+1.0 s1.0 (emo0.53/id0.685); BrF v-0.4/a+0.8 s1.0 + (emo0.99/id0.725, metric fear-clean); AmM **two-tier** — soft v-0.6/a+0.8 s1.0 + (0.23/id0.654) + drama v-0.6/a+0.8 s1.2 (1.0/id0.616 clean; strength is NOT a + smooth knob on AmM, 1.0→1.2 is the window, past that flips to disgust). + - happy / startled_happy: AmF v+0.6/a+0.8; AmM v+0.3/a+1.0; BrF v+0.6/a+1.0 + (happy~1.0, id 0.74-0.80; axes-happy keeps +0.15 id over the named happy slider). + - `sad` = unchanged named-slider preset (not axes-tested). +- Uncalibrated voices (Cora + the 4 clones) → mid-region fallback until measured. +- Docs surface: `/v1/dials` exposes `voice_emotion_presets`; the FastAPI `/docs` + description documents it; durable spec `docs/EMOTION-DIALS-SPEC.md` (moved INTO + the repo — was mirror-only); README table. 44 tests green. + +**Repo-hygiene gotcha (fixed).** The local clone `~/development/zonos-gateway` and +gitea `vh/zonos-gateway` had **TWO UNRELATED git histories** (no merge-base) — gitea +held the voice-wav commits, the local clone held the code + no remote. Reconciled +by resetting local→origin/main, overlaying the 7 bake files, `uv lock`, commit, +push (fast-forward). Voices stay tracked; local now shares gitea's lineage + has +origin wired. **The deployed irv-ml1 tree `/opt/docker/compose/zonos-gateway` is +still NON-git** (hand-updated build context) — CI-wire remains an open follow-up. + +**Provisional pending** ear-validation on emotion-congruent text (the neutral-text +audition was inconclusive: "they all sound different, hard to tell"). Follow-ups: +sad axes/text pass on the 3 voices; congruent-text pass; clone-char emotion rows. +Tools `~/development/zonos-tools/{axes_sweep,strength_ladder,gen_auditions,dial-in-studio}.py` +(run ON irv-ml1; scoring env `uv run --with resemblyzer --with funasr --with "numpy<2" +--with soundfile --with requests --with "setuptools<80" --with torchaudio`). diff --git a/persistent-memory.md b/persistent-memory.md index 8d9d010..7bffc3f 100644 --- a/persistent-memory.md +++ b/persistent-memory.md @@ -33,7 +33,8 @@ Sister repos (separate gitea repos, deployed by playbooks here): | `vh/Worldtree` | Conversation API (corviduo-dev demo :8080 / personal :8081 / pinned :8082) — Heimdall auth, Bifrost integration. **gitea-runner builds on ana-docker**; claude-bot ADMIN collaborator (2026-06-20). Now v1.0.0b19. | push-to-main → CI build-and-deploy (runner on ana-docker) | | `vh/yt-voice-clipper` | YouTube → diarized voice-clip dataset builder + audition console (irv-ml1 :8000) | push-to-main → **gitea-webhook auto-deploy** to irv-ml1 (2026-06-03) — see `docs/runbooks/ytvc-autodeploy.md` | | `vh/arbo` | Catalog-driven ComfyUI engine (irv-ml1 :8201, comfy-dev owns engine/catalog/image) | push-to-main → gitea Actions CI (deploy-engine.sh, build-local, health-gated) now LIVE; catalog via :9009 webhook | -| `vh/zonos-gateway` | OpenAI-compatible TTS gateway over stock ZONOS2 (`:8890` irv-ml1); emotion **dials-first** + voice mapping; reached via LiteLLM `ext-tts` alias | **stood up 2026-07-17** (private; internal SSH); NOT yet CI-wired (deployed `/opt/docker/compose/zonos-gateway` is a SEPARATE copy from the repo — CI + deploy key = open follow-up). Dials-first spec at `docs/EMOTION-DIALS-SPEC.md`. **2026-07-18: host-managed voices bind-mount** (`./voices:/app/voices`) → 8 voices incl. 4 cloned chars (Emmie/Penny/Natalie/Miranda); voice wavs committed | +| `vh/zonos-gateway` | OpenAI-compatible TTS gateway over stock ZONOS2 (`:8890` irv-ml1); emotion **dials-first** + voice mapping; reached via LiteLLM `ext-tts` alias. **v0.2.1 (2026-07-18): voice-resolved emotion presets** (`resolve_preset(name,voice)`; angry/happy/startled_happy per-voice). 8 voices incl. 4 clones | pushed to gitea (main `8f1885b`/`v0.2.1`); **deployed irv-ml1 tree still NON-git** (hand-updated build context — CI-wire = open follow-up). Spec `docs/EMOTION-DIALS-SPEC.md`; host-managed voices bind-mount (`./voices:/app/voices`, drop wav + restart, no rebuild) | +| `vh/soong-lab` | Noonien Soong character-design studio (SPA + /api + WT `/bifrost/tool-call`); **containerized 2026-07-18**, LIVE on corviduo-dev `:8443` (image `vh/soong-lab:latest` v0.3.24). soong-dev owns Dockerfile/compose/workflow; infra-ops owns the host | CI = Gitea Actions build+push on tag/dispatch (fleet recipe: docker:cli + raw buildx, pushes AS vh). Deploy `/home/infra-ops/soong-lab-deploy/`; redeploy `docker compose pull && up -d`. → `persistent-memory.d/2026-07-18-soong-lab-containerize-cutover.md` | | `model-training-forge` (mtf-dev) | Fine-tuning recipe forge; **T1 = E-RP writing LoRA, retargeted qwopus-122B→AEON-27B (2026-07-06)** (SFT→DPO, LitBench-RM reward) | training runs, not a deployed sidecar | (`vh/volva` + Heid were re-architected from systemd daemons to Claude Code @@ -108,34 +109,31 @@ no longer deployed sidecars here. See Recent decisions.) ## Current state / in-flight -_As of 2026-07-18 — active work = Zonos2 emotion-tuning + voice-cloning for the character-voice product. Snapshot for a /clear; operator: "read mail after."_ +_As of 2026-07-18 — end of a long session. **Four major items ALL LANDED** (details in Recent decisions): (1) Zonos emotion presets baked → zonos-gateway 0.2.1; (2) soong-lab containerized cutover COMPLETE + live on corviduo-dev :8443 ("Soong works great"); (3) Wyrd conv-api demo key delivered+closed; (4) wtsdk npm-publish token delivered → worldtree-sdk@1.0.0 published. **No active in-flight task.**_ -**Zonos voice + emotion state (all LIVE):** -- **8 voices** in `zonos-gateway` (`:8890` irv-ml1): defaults AmericanFemale/Male/British/Cora + 4 CLONED characters **Emmie/Penny/Natalie/Miranda**. Add a voice = drop `.wav` in `/opt/docker/compose/zonos-gateway/voices/` + `docker compose restart zonos-gateway` (host-managed bind-mount; NO rebuild). All voice wavs committed to `vh/zonos-gateway`. -- **Voice-cloning pipeline:** `/mnt/smithy/voice_clones/.zip` (diarized + WhisperX-scored clips) → `~/development/zonos-tools/assemble_voice.py ` → top-mean_score clips to ~15–24s → drop in gateway voices. (`/mnt/smithy` = irv-ml1 NFS from nh3-nas; remount post-reboot.) Full pipeline + emotion detail in the `[2026-07-18]` Recent-decisions entry. -- **Dial-in studio** at **http://10.100.10.50:8898/** — streaming Web Audio (~0.6s first-audio), voice dropdown (all gateway voices), every Zonos dial as a slider + Reset + Copy-JSON; proxies the gateway. ⚠️ It's a **nohup'd session process** on nh3-dev (NOT a service); source now durable at `~/development/zonos-tools/dial-in-studio.py` — relaunch `nohup python3 ~/development/zonos-tools/dial-in-studio.py >/tmp/zonos-studio.log 2>&1 &`. Systemd-ize if reboot-survival wanted. -- **Emotion CANONICAL established** (empirical sweep, `[2026-07-18]` entry): single-emotion only; two-regime accurate(identity)/expressive(drama) policy; happy/sad usable, angry weak, surprised dead on the named directions. +**Open follow-ups (non-blocking — pick one up or not):** +- **Zonos emotion:** sad axes/text pass on the 3 calibrated voices (only named-sad, untested); emotion-congruent-text pass (validates intensity, may rescue sad id); clone-char (Emmie/Penny/Natalie/Miranda) emotion rows use the mid-region fallback until measured. Presets are **provisional** (neutral-text ear-check was inconclusive). Tools `~/development/zonos-tools/{axes_sweep,strength_ladder,gen_auditions,dial-in-studio,assemble_voice}.py` (run ON irv-ml1; dial-in studio = nohup :8898 on nh3-dev). dvalin thread at rest (`01KXT12FN0AS…`). → `persistent-memory.d/2026-07-18-zonos-gateway-0.2.1-emotion-presets.md` +- **zonos-gateway CI-wire:** deployed irv-ml1 tree `/opt/docker/compose/zonos-gateway` is still NON-git (hand-updated build context) — git-connect + build-on-push like the other sisters. (Same pattern soong-lab now has.) +- **soong-lab:** cutover DONE; future redeploy = `cd /home/infra-ops/soong-lab-deploy && sudo docker compose pull && up -d`; optional auto-pull-on-`:latest` (watchtower/deploy-hook). → `persistent-memory.d/2026-07-18-soong-lab-containerize-cutover.md` -**Open loops for the fresh session:** -- ✅ **yt-voice-clipper yields test CLOSED** (2026-07-18) — job `f3ff746dbae9494d` returned **13 segments / 203.5s** (was 2 pre-fix), `max_gap=1.2` confirmed live; replied verify #3 to yt-voice-clipper-dev (thread `01KXT0T6GYHB61EKJ81PZAMA7W`, msg `01KXT25D…`). All 3 verifies green (A6000 / v0.3.3 / yields). Redeploy done + validated. -- ✅ **Axes sweep DONE + dvalin loop CLOSED** (2026-07-18) — ran the valence×arousal sweep on the 3 calibrated defaults, sent dvalin the graded numbers (thread `01KXT12FN0AS5A3WMKEK06BVPS`, msg `01KXT2ZB8G…`). Result in the `[2026-07-18] axes sweep` Recent-decisions entry below. **Open Qs posed to dvalin** (awaiting reply): (a) strength-ladder at ship cells to find AmericanMale's missing angry sweet spot? (b) emotion-congruent text next, or bake happy/sad/angry canonical first? — monitor armed for the reply. -- ✅ **BAKED — emotion presets shipped as zonos-gateway 0.2.1** (2026-07-18). Operator ear-checked (neutral-text audition inconclusive: "they all sound different, hard to tell" → "call it, provisional, we'll deal with it"), then green-lit bake+docs. Implemented **voice-resolved** emotion presets (`resolve_preset(name, voice)`): `angry`/`happy`/`startled_happy` (+`surprised`/`startled` aliases) resolve to the per-voice measured cell — NOT a global preset (dvalin ruling; BrF named-angry→fear is why). Calibrated for AmF/AmM/BrF; mid-region fallback for Cora+clones. `/v1/dials` exposes `voice_emotion_presets`; `/docs` FastAPI description documents it (the web surface); durable spec at `docs/EMOTION-DIALS-SPEC.md` (moved into vh/zonos-gateway repo — was mirror-only) + README table. 44 tests green; rebuilt + verified live on irv-ml1 (BrF angry→200, Cora surprised→fallback 200). PUSHED to gitea `vh/zonos-gateway` main `8f1885b` + tag `v0.2.1`. ⚠️ **Repo-hygiene gotcha (fixed 2026-07-18):** the local clone `~/development/zonos-gateway` and gitea had TWO UNRELATED git histories (no merge-base) — gitea held the voice-wav commits, local held the code+bake, no remote wired. Reconciled onto gitea's lineage (reset local→origin/main, overlaid the 7 bake files, `uv lock`, committed, pushed); voices stay tracked. Local now shares gitea's lineage + has origin wired. Deployed irv-ml1 tree still non-git (CI-wire follow-up open). Audition tooling: `~/development/zonos-tools/{gen_auditions,axes_sweep,strength_ladder}.py`; audition server was nohup :8901 on nh3-dev (throwaway, tear down). **Ship cells baked (per-voice, exp/cfg1.5, no sliders):** - - **angry** — BritishFemale v-0.4/a+0.8 str1.0 (0.99/id0.725, proxy fear-CLEAN); AmericanFemale v-0.4/a+1.0 str1.0 (0.53/id0.685); AmericanMale **two-tier** (no single ship cell) → soft v-0.6/a+0.8 str1.0 (0.23/id0.654) / drama v-0.6/a+0.8 str1.2 (1.0/id0.616, clean). - - **startled-happy** (="surprised" product alias; never set surprised slider) — AmF v+0.6/a+0.8, AmM v+0.3/a+1.0, BrF v+0.6/a+1.0 (all happy~1.0, id 0.74-0.80). - - **happy** — axes-preferred (same cells as startled-happy; +0.15 id over named-happy); named-happy = fallback. **sad** = unchanged (named exp cfg1.5, not re-tested on these 3). - - dvalin ruling: store as **per-voice dial tables, NOT a global preset** (BrF named-angry→fear is the exhibit). Bake provisional + ear-spot-check 1 clip/cell. - - Follow-ups: emotion-congruent-text pass (validates intensity, may rescue sad id); clone-char voices map to nearest-default table or 1-row confirm. Tools: `~/development/zonos-tools/{axes_sweep,strength_ladder}.py` (scoring env: `uv run --with resemblyzer --with funasr --with "numpy<2" --with soundfile --with requests --with "setuptools<80" --with torchaudio`; run ON irv-ml1 — localhost:8890 + REFDIR). -- **soong-lab containerize cutover on corviduo-dev — AUTHORIZED/slotted** (2026-07-18, operator "slot the soong"; soong-dev thread `01KXT3A6C3908TA4V9THV3AMH7`). In-repo half landed (soong-lab `0e49391`: Dockerfile/compose/`.gitea/workflows/build-and-push.yml`/`docs/DEPLOY.md` = source-of-truth checklist). My side to drive: (1) creds — internal Gitea PyPI read (`bifrost[reference-server]==1.1.0`, BuildKit secret `id=gitea_token`) + container-registry push; **source via claude-bot service account first** (migrate-off-personal-creds), vh fallback only on scope gap; (2) confirm a Gitea Actions runner for the tag/manual build; (3) propose a quiet cutover WINDOW to vh. HARD: migrate `/data/library` (incl. Sindra) + `/data/portraits` into volumes BEFORE first container run; verify Bifrost callback path (`SOONG_LAB_BIFROST_ENDPOINT_URL`, proxy→container + WT host-allowlist) + `/api/version` + one live Soong tool-call round-trip BEFORE retiring `soong-lab-studio.service` + the webhook git-pull deploy. Not started (queued behind Zonos ear-check). **Post-cutover: add a Homepage entry — manual `services.yaml`, NOT docker labels** (operator chose "B" 2026-07-18). Homepage runs on **esh-docker-vm** (`/opt/docker/conf/homepage/`), docker-label auto-discovery only covers the 5 endpoints in its `docker.yaml` (esh-vm-docker, ana-docker, ana-ml2, nh3-docker, irv-ml1) — **corviduo-dev is NOT watched**, so labels alone won't surface it. Add a manual entry (href + `siteMonitor` ping at the live soong-lab URL, icon, description) in a MANUAL group (Apps/Creative/Infra — NOT the AI tab, which is auto-discovery-only and warns against manual entries → double-up). Rejected option A (expose corviduo-dev docker :2375 + label) as too much for one tile on a WT-managed host. ⚠️ corviduo-dev = WT-team-managed, data-affecting → coordinate. [[reference_corviduo_dev_emergency_ops]] [[reference_claude_bot_gitea_creds]] -- **althing monitor ARMED this session** (handle `infra-ops`, wake-listener; herald up). Re-arm after each fire (dies on /clear). Open watch: worldtree-dev (#368 memory-leak forensics done; #363 research-wing ingest PARKED). -- **eshpfi commits UNPUSHED** — the zonos-gateway capture + memory (`14a0004`..`438cd35`) are committed; push is the operator's call. `stacks/heretic2-charrp-reasoning/` still UNTRACKED; `graphify-out/GRAPH_REPORT.md` modified. -- **irv-ml1 3090 oversubscription** (kokoro `:8193` + vibevoicefusion `:9527` idle-pinned; zonos engine :1920 also on 3090) — carried; operator declined to fix. +**Zonos voice stack (LIVE, unchanged):** 8 voices in `zonos-gateway` (`:8890` irv-ml1) — defaults AmericanFemale/Male/BritishFemale/Cora + 4 clones Emmie/Penny/Natalie/Miranda; add a voice = drop `.wav` in `/opt/docker/compose/zonos-gateway/voices/` + `docker compose restart` (host-managed bind-mount, NO rebuild). Clone pipeline: `/mnt/smithy/voice_clones/.zip` → `assemble_voice.py` → drop. Dial-in studio http://10.100.10.50:8898/ (nohup on nh3-dev, relaunch `nohup python3 ~/development/zonos-tools/dial-in-studio.py >/tmp/zonos-studio.log 2>&1 &`). -**Landed this session (2026-07-17→18):** #365 demo+personal → b125 (byte-exact, CLOSED — `[2026-07-17]` entry); PERSONAL agent-memory SCRUBBED (WT#368 remediation, rollback `/opt/worldtree-personal/agent-memory-backup-20260717-181004.tar.gz`); zonos-gateway repo stood up + dials-first spec + host-managed voices; 4 character voices cloned; dial-in studio (streaming); emotion sweep + canonical; yt-voice-clipper → A6000-pinned + v0.3.3. +**althing monitor** ARMED (handle `infra-ops`, wake-listener; herald up). Re-arm after each fire (dies on /clear). Open watch: worldtree-dev (#368 forensics done; #363 research-wing ingest PARKED). -**Carried standing (non-blocking):** ana-ml2 GPU0 ~14 G reserve; Worldtree #363 research-wing ingest (auto-memory, no deadline); T1 SFT LoRA dormant; rotate the 5 rest-server backup creds (operator, offline). Zonos2 engine still NATIVE (containerize deprioritized — priming was flat, emotion-steering is the lever). +**eshpfi UNPUSHED** — this session's memory commits (`4bdf010`, `deae057`, + this snapshot) + the earlier `14a0004`..`438cd35` are committed but unpushed (push = operator's call). `stacks/heretic2-charrp-reasoning/` UNTRACKED; `graphify-out/GRAPH_REPORT.md` modified. + +**Carried standing (non-blocking):** ana-ml2 GPU0 ~14 G reserve; irv-ml1 3090 oversubscription (kokoro :8193 + vibevoicefusion :9527 idle-pinned + zonos :1920 — operator declined to fix); rotate the 5 rest-server backup creds (operator, offline); Worldtree #363 research-wing ingest (parked, no deadline); T1 SFT LoRA dormant; Zonos2 engine still NATIVE (containerize deprioritized). ## Recent decisions +- `[2026-07-18]` **soong-lab containerize cutover COMPLETE + LIVE** — systemd→container on corviduo-dev :8443 (image `vh/soong-lab:latest` v0.3.24), data migrated (Sindra + portraits) + backed up, old service+webhook retired, Homepage tile added, operator functional-confirmed. Deploy `/home/infra-ops/soong-lab-deploy/`; no proxy (co-located WT, plain-http callback). → `persistent-memory.d/2026-07-18-soong-lab-containerize-cutover.md` + +- `[2026-07-18]` **zonos-gateway 0.2.1 — voice-resolved emotion presets baked (provisional)** — `resolve_preset(name,voice)` → per-voice axes cell (angry/happy/startled_happy + aliases); NOT a global preset (BrF named-angry→fear). Docs on /docs + /v1/dials + repo spec. Pushed main `8f1885b`/tag v0.2.1 (after reconciling two-unrelated-git-histories). → `persistent-memory.d/2026-07-18-zonos-gateway-0.2.1-emotion-presets.md` + +- `[2026-07-18]` **Fleet Gitea-Actions build recipe + the `vh`-is-a-USER package-write constraint** (reusable for any fleet CI image build / package publish) — runner job image node:20-slim has no docker/git → use `container: docker:24.0.7-cli` + `apk add git nodejs` + RAW buildx (not the JS `docker/*` actions); vh is a user so its packages are OWNER-WRITE-ONLY (claude-bot can't push/publish/set-secrets — CI must auth AS vh); `GITEA_` secret-prefix is reserved. → `persistent-memory.d/2026-07-18-fleet-gitea-runner-build-recipe.md` + +- `[2026-07-18]` **Peer credential provisions — Wyrd conv-api key + wtsdk npm token, both delivered + closed.** Wyrd: demo Worldtree user-tier key (key_id `da7a0bdf`, user_id `wyrd-dev`) minted via `docker exec worldtree-worldtree-api-1 /admin/keys` (omit tier→user), drop-and-shred delivery. wtsdk: operator-minted vh `write:package` PAT relayed drop-and-shred → worldtree-sdk@1.0.0 published to `vh/npm/`. Secret-delivery pattern = drop to a mode-600 file on the peer's box, they collect+shred+confirm, then shred the holding copy; NEVER cleartext over althing. [[reference_worldtree_demo_key_mint]] + - `[2026-07-18]` **Axes sweep RESCUED angry; surprised-class dead but startled-happy ships.** Valence×arousal grid on the 3 calibrated defaults (AmericanFemale/Male, BritishFemale), exp/cfg1.5/strength1.0, 84 clips, emotion2vec + resemblyzer scored, graded vs dvalin's floor. **ANGRY rescued** (named direction was 0.004–0.15, British named-angry even misfired as fear 0.89): axes ship cells at **negative valence (−0.4..−0.8) + high arousal (+0.8..+1.0)** — BritishFemale v-0.4/a+0.8 angry=0.99/id0.725 SHIP, AmericanFemale v-0.4/a+1.0 angry=0.53/id0.685 SHIP; AmericanMale two-tier post-ladder (no single ship cell — best drama = v-0.6/a+0.8 str1.2 angry=1.0/id0.616 clean, soft = same cell str1.0 angry0.23/id0.654; cell A v-0.6/a+1.0 is a non-monotonic minefield, skip). BrF ship cell proxy-CLEAN of fear (str<1.0 just kills anger). **SURPRISED-class DEAD** (max 0.047 across all 84 cells) but **startled-happy** (happy-proxy) ships all 3 at high arousal + neutral/positive valence, with a **+0.17–0.20 identity LIFT** over the named-surprised route (named hits happy~1.0 but at id0.57–0.61, under floor; axes hits happy~1.0 at id0.74–0.80). Bonus: axes-happy retains ~0.10–0.15 more identity than the named happy slider too. Caveats: response surface non-monotonic/sharp-thresholded; angry region borders fear/disgust (bleed); emotion2vec saturates at 1.0 (needs ear-confirm); neutral text understates. Tooling `~/development/zonos-tools/axes_sweep.py`; per-clip JSON was `irv-ml1:/tmp/axes_sweep_results.json` (ephemeral). Sent dvalin msg `01KXT2ZB8G…`. NEXT = operator ear-confirm → bake presets. [[reference_zonos_tts_stack]] - `[2026-07-18]` **Zonos2 emotion CANONICAL from an empirical sweep + the voice-cloning pipeline** — 4 chars cloned (Emmie/Penny/Natalie/Miranda), host-managed gateway voices, two-regime accurate/expressive policy, happy/sad usable + angry-weak/surprised-dead on named directions, dvalin-synthesized; axes sweep is the NEXT experiment. Studio + sweep tooling at `~/development/zonos-tools/`. → `persistent-memory.d/2026-07-18-zonos-emotion-canonical.md` @@ -222,6 +220,10 @@ _142 older entries archived to archival-memory.md._ ## Tried and abandoned +- `[2026-07-18]` **Fleet Gitea CI foot-guns** (3 failed soong-lab builds): the pfi-fleet runner's `node:20-slim` job image has no docker/git so `actions/checkout` + `docker/*` marketplace actions all fail; `vh` is a USER so its packages are owner-write-only (claude-bot repo-admin-collab still 401s on push/publish, and can't set repo secrets — owner-only); `GITEA_`-prefixed secret names are reserved/illegal. Fixes in → `persistent-memory.d/2026-07-18-fleet-gitea-runner-build-recipe.md` + +- `[2026-07-18]` **zonos-gateway local clone had NO git remote + a history unrelated to gitea's** — "committed to vh/zonos-gateway" was never pushed from that clone; two separate `git init` lineages, no merge-base. Reconcile = reset local→origin/main + overlay the changed files + push (NOT force — that erases gitea's voice-wav commits). Check `git remote -v` + `git merge-base` before assuming a clone is wired. + - `[2026-07-15]` `docker.service After=remote-fs.target` does NOT wait for `nofail` NFS mounts → `persistent-memory.d/2026-07-15-docker-service-after-remote-fs-target-does-not.md` - `[2026-07-15]` The esh-docker-vm D-state/phantom-container wedge is only cleared by a host REBOOT → `persistent-memory.d/2026-07-15-the-esh-docker-vm-d-state-phantom-container.md`