Commit Graph
100 Commits
Author SHA1 Message Date
vh ad2df89c0c feat(litellm): repoint fleet reranker alias to bge-reranker-v2-m3 (Brokkr R43)
The incumbent Qwen3-Reranker-0.6B was measured actively harming 80/90
fleet queries on main+knowledge_base (and inverting the bare-name region
behind Worldtree #389) — no-reranker beat it 89/90 vs 56/90. Brokkr's R43
bake-off selected BAAI/bge-reranker-v2-m3 (A3): 90/90 top-10, mean rank
0.19, multilingual (XLM-R), ~1.2 GB lighter than the incumbent.

Control arm (A2 = same Qwen weights, seq-cls head) scored identical to the
incumbent, proving the fault is a training prior, not the serving head —
which cancelled the expensive Qwen3-4B arm before it cost a GPU seat.

Cutover boundary 2026-08-06T17:37:48Z. The qwen3-reranker alias and the
:8002 backend are retained for one-edit rollback. Adds the process audit
trail at docs/pfi/reranker-selection-ledger.md.
2026-08-06 10:40:26 -07:00
vh 6c6d3f2939 memory: snapshot for /clear — booth 3 features shipped, herald v2.1.2, CI-flip PARKED (runner-auth)
Session (2026-08-05): 3 Booth features live+tagged (verbatim-wrap chip, .md/.txt
doc-viewer, image prev/next arrows); worldtree herald re-nudge bug -> forseti
althing-core v2.1.2; fleet-CI-resilience flip attempted end-to-end and PARKED on
an act_runner->gitea action-fetch auth blocker (infra-ops to research, deferred).
Archived the 2026-07-15/16 recent-decisions batch (8 entries) to keep the index
under the soft cap.
2026-08-05 04:31:59 -07:00
vh c37a425276 feat(booth): prev/next arrows in the image viewer
Zooming an image now shows ‹ / › arrows at the left/right edges that step
to the previous/next image in the booth (gallery sorted-rel order), wrapping
around, plus keyboard ←/→. Arrows are hidden when a booth has a single image.
booth_view_file computes neighbors via a new booth_image_names() helper and
passes prev_url/next_url to view.html. 3 new tests, suite 47 passing;
deployed + verified live on nh3-dev :8090.
2026-08-05 01:30:30 -07:00
vh 315faac4b5 feat(booth): view .md (rendered) and .txt/.log in-booth without downloading
Loose .md/.txt/.log files rendered as forced-download links in the gallery
and downloaded (or showed raw) when opened. Now they open in a readable
in-booth page via the existing /b/<name>/view route:
  - .md  -> rendered HTML (Python-Markdown: fenced code, tables, sane lists),
           styled in an Australis .markdown-body with the viewer chrome;
  - .txt/.log -> preformatted <pre> text view.
The gallery links docs to the viewer (📄) instead of a download; the view
page keeps a ⬇ (?dl=1) for saving. Files over 2 MB hand back raw. New
markdown dep (optional-import: degrades .md to text view if absent).
booth_image_view -> booth_view_file (now handles image + doc + raw-fallback).
9 new tests, suite 44 passing; deployed + verified live on nh3-dev :8090.
2026-08-05 01:13:38 -07:00
vh b5ae9365ff memory: triton backend is a HARD NO on the Ampere comfy box (fp8e4nv), deferred to Ada
Recorded under Tried-and-abandoned: --enable-triton-backend on irv-ml1's
A6000 crashes every render (triton's fp8 dequant needs fp8e4nv/e4m3, which
sm_86 lacks; the global --fp8_e4m3fn-text-enc dequant dies at CLIPTextEncode,
taking fp8 and int8 alike). Reverted cleanly; cu130 rebuild won't fix a
hardware format limit; revisit at the Ada refresh. Also captures the
compose-env-needs-recreate-not-restart mechanics lesson.
2026-08-03 21:29:00 -07:00
vh 348c5c12a2 chore(booth): gitignore uv.lock (stray artifact from uv run; booth tracks no lockfile) 2026-08-03 13:06:02 -07:00
vh 8577e7e248 feat(booth): wrap verbatim index.html booths with a back-to-booths chip + inherited favicon
Verbatim-index.html booths were served raw (FileResponse) with no base
template, so they had no favicon and no way back to the booth index — the
gap the app-rendered gallery/zoom pages already covered via base.html.

booth_view now reads a small verbatim index.html and, via a pure
wrap_verbatim_html(), injects:
  - a fixed-position 'all booths' chip (scoped class, max z-index, hidden
    in print), pinned top-right (empty on left-aligned report layouts; a
    top-left chip clips the page title) and appended at the END of the
    document so it never reorders the page;
  - the Booth favicon at the first head-ish seam, only if the page declares
    no icon of its own.

Injection is doctype/charset-safe for the compact HTML real booths use
(<!doctype html><meta charset><title><style>…content, no explicit head/
body): nothing is ever placed ahead of a leading <!doctype> (which would
force quirks mode), and the ~250B favicon link keeps the charset <meta>
inside the first-1024-byte detection window. The raw file route
(/b/<name>/index.html) stays byte-for-byte, so assets and ?dl=1 downloads
are unchanged; files over 8 MB serve raw, unwrapped.

Verified live on nh3-dev :8090 across the real booth shapes (compact-HTML
crow-*/jackdaw-*/mimir-favicon, well-formed dcc-summarizer-ab, own-icon
edict-favicon). 10 new tests; suite 38 passing.
2026-08-03 13:05:30 -07:00
vh d4d9956fed memory: correct extdev sudo status in 07-25 herald-install entry
The [2026-07-25] nh3-extdev herald-install entry claimed infra-ops was
sudo-less on extdev, explaining the use of the lkraven@ NOPASSWD path.
That parenthetical was wrong: infra-ops has had full NOPASSWD sudo on
extdev since 2026-06-25. Kept the historical action (lkraven@ was used)
and appended a dated correction so a future session self-serves as
infra-ops instead of taking the lkraven@ hop unnecessarily. Surfaced
during the 2026-08-03 herald.py:363 re-nudge-bug arc.
2026-08-03 08:01:17 -07:00
vh bc084edbee memory: snapshot for /clear — worldtree b168/#384/#385 arc complete
Collapsed the completed-arc bloat out of Current state / in-flight (line 125:
6487->1073 chars; runbooks moved to persistent-memory.d/2026-08-03-worldtree-b168-384-385-arc.md).
Added the 2026-08-03 arc Recent-decisions entry. Auto-archived 20 oldest
Recent-decisions entries (2026-07-08..07-14) to archival-memory.md (index 345->308
lines). Refreshed the b169-deploy watch, unpushed-count, and handoff.
2026-08-03 00:12:59 -07:00
vh 4be87f1a94 memory: b169 pull-fail was a shared-containerd race, NOT disk; dont prune in-use img
corviduo-dev demo+personal+pinned share one containerd; concurrent pull of b169's
torch layer failed personal mid-race while demo completed. Image 6e34a87 fully
valid (demo running it healthy). Fix = re-run. NEAR-MISS: prune/rmi 6e34a87 would
have downed demo. Lesson: docker ps running images before any prune cleanup.
2026-08-02 23:57:48 -07:00
vh 45594e3891 memory: config-delta pre-sync rule — only config/ is bind-mounted, agents/ in-image
Verified via docker inspect: worldtree containers bind-mount only config/ host-side
(providers/model_roles/matrix/policies/defaults/env.public = pre-syncable set);
agents/ (schemas.yaml) + code ship in-image. So b169's schemas.yaml delta needs
no host pre-sync; only config/*.yaml changes are boot-blocking-pre-syncable.
2026-08-02 23:40:39 -07:00
vh 523b28f12f memory: production sweep DONE — 785 April DCC dupes deleted, arc complete
Operator-approved: backed up 785 rows (reversible) -> deleted job_id=b59c147c5ce0
from main (4009->3224, target cleared) -> bounced api (HNSW reload) -> confirmed
search fiction-only. #384/#385 closed, worldtree arc complete.
2026-08-02 23:12:21 -07:00
vh b4ef0600d2 memory: BrokenPipe wing-git watch CLOSED (round-2 commits clean, chown enabled)
worldtree-dev closed the watch with git evidence: both round-2 wing commits
landed clean under exec -u 1000; loose-object chown enabled it. Self-healed as
predicted; last thread of the reindex-as-root fallout closed.
2026-08-02 22:54:32 -07:00
vh 3a829890c5 memory: worldtree #384/round-2 arc COMPLETE + #381 restart fired
Both books terminal (DCC 705 / P&P 667 indexed, 0 failures, #385 budget fix
validated); #381 restart-after-ingest fired, api healthy, wing retrievable
(search_library returns DCC+P&P from fiction). ratatoskr verify handed off.
Delete-sweep precondition now met (stale main rows = genuine duplicates).
2026-08-02 22:53:01 -07:00
vh d72597bade memory: /health W_OK blind-spot for root-owned job subdirs (muninn-dev)
os.access(ingestion_root, W_OK) tests only the root dir, so a root-owned job
subdir passes requeue guards + /health both while being unclaimable by uid 1000.
muninn-dev added an ownership column to the post-move check.
2026-08-02 22:47:51 -07:00
vh 8bc5be35ce memory: reindex-as-root contaminated KB tree; adopt docker exec -u 1000 rule
sudo docker exec --reindex ran as root (app=uid 1000), leaving a root-owned
.old- dir (blocked uid-1000 rmtree) + 60 root-owned git objects. Fixed: rm -rf
.old- (tar'd first) + chown 1000:1000 the objects. RULE: docker exec that writes
pipeline state uses -u 1000. GOTCHA: don't head a scope-defining find (.old- had
153 files, head-20 hid the 60 git objects).
2026-08-02 22:45:33 -07:00
vh 3790669fb5 memory: round-2 sequencing (mimir-dev drives, muninn-dev confirms, infra-ops #381)
muninn-dev HOLD LIFTED (guard-verified 02:36Z). Recorded who owns what:
round-2 requeue = mimir-dev browser flow (op ruling pending); muninn-dev = gate
confirmer / post-move board-check custody; infra-ops = #381 restart after both
terminal + later supervised sweep.
2026-08-02 19:40:04 -07:00
vh 9bd5f2a4b1 memory: mv -t is the real guard (trailing slash is a false guard); dont-tidy note
muninn-dev tested on coreutils 9.1: mv src failed/ with failed/ missing STILL
silently renames (rc=0) — trailing slash buys nothing. mv -t <dir> <src> refuses
a missing target loudly (rc=1). Adopted as house convention. Also: DCC+P&P rest
in failed/ with manifest=complete until round-2 (requeue keys on dir placement) —
deliberate, don't tidy.
2026-08-02 19:38:08 -07:00
vh 4eb2724712 memory: add silent-failure-mode note to the mv lesson (muninn-dev)
A misplaced ingestion-state move is silent (list_jobs OK, files inert; sole
symptom = job absent from board, job_row->None/404). Verify job is on the board
+ job.dispatch.json survived after any move; don't trust mv exit codes.
2026-08-02 19:36:06 -07:00
vh f8d0f3081d memory: lesson — mv into nonexistent failed/ renamed the job dir
worldtree-dev round-2 unblock: mv job complete/->failed/ assumed failed/
existed; it didn't on personal, so mv renamed job1 to 'failed' + nested job2.
Caught + reconstructed via complete/ scratch, no data loss. Lesson: verify dir
exists with [ -d ] before mv-into (empty ls is ambiguous); guard peer fs cmds
with mkdir -p.
2026-08-02 19:30:18 -07:00
vh 11f9856cd5 memory: wing-git = self-healing watch; pending prod delete-sweep heads-up
worldtree-dev accepted #384 recovery. Wing-git BrokenPipeError ruled a
watch-item (self-heals on DCC round-2 re-run; escalate only if 2-in-a-row).
Recorded a heads-up for a future production delete-by-job_id of 785 April-era
DCC orphans (job_id=b59c147c5ce0, 'main' collection) — to be handled supervised
(backup + scope-confirm + operator-in-loop) after ratatoskr's verify.
2026-08-02 19:17:56 -07:00
vh c3b6630684 memory: #384 recovery on personal DONE (reindex+restart+verify)
b168 preflight-confirmed live; reindex exit0 (97 concepts); #381 restart
healthy; metadata verify 5/5 fiction rows carry note_id+path. Open item:
wing git commit BrokenPipeError (kb_ingest_degraded, reconcile-visible) —
worldtree-dev's call. Recorded chroma-verify runbook (docker exec -i).
2026-08-02 19:15:39 -07:00
vh 62d5a45182 memory: b168 pushed + pending #384 reindex/#381 restart on personal
worldtree-dev pushed the train (main + tags v1.0.0b168/staging) and verified my
pre-sync matches the commit byte-for-byte. Recorded the next pending op: after
b168 CI-lands on personal, run --reindex of job mimir-6351554e8e8f + #381 restart
on their exact commands.
2026-08-02 19:03:12 -07:00
vh e0b616b946 memory: providers.yaml summarization pre-sync DONE (#384/#385 b168)
Synced the boot-gating summarization block + deep-reasoning desc to demo +
personal via deploy-wt-config (health-gated); replied GO. Recorded gotchas:
unpushed-commit fetch falls back to default branch (verify SHA exists), and
paste-sourced YAML needs indent/validate (8-space desc was invalid).
2026-08-02 19:01:30 -07:00
vh b901468752 memory: track pending providers.yaml summarization pre-sync (#384/#385)
worldtree-dev advance notice: #384/#385 train adds a boot-blocking
'summarization' capability block (vastblueai-gateway/gen) that in-image
muninn/config.yaml references. Must pre-sync into providers.yaml on demo
+ personal via deploy-wt-config BEFORE the image deploy, from the exact
commit. ACKed; recorded as an open watch.
2026-08-02 18:11:28 -07:00
vh a713d3f2c4 memory: #381 restart DONE — fiction wing retrieval-visible on personal
DCC job mimir-6351554e8e8f complete; restarted worldtree-personal-worldtree-api-1
(healthz/readyz 200); Mimir search_library on wings=[fiction] returns 10 DCC hits
(retrieval visibility confirmed, not grounding — ratatoskr runs grounding verify).
Recorded the Mimir-session probe runbook (SSE stream, tool-events).
2026-08-02 14:41:31 -07:00
vh f30c41409f memory: track pending #381 restart (DCC re-ingest, worldtree-dev)
worldtree-dev gave advance notice: standing #381 restart of
worldtree-personal-worldtree-api-1 will be requested when DCC re-ingest
job mimir-6351554e8e8f (fiction wing) goes terminal in a few hours.
ACKed no scheduling constraints; recorded as an open watch so a fresh
session catches the request.
2026-08-02 13:24:31 -07:00
vh 9b2c47602d memory: donut onyx-58 multi-clip ref reverted; emotion-away-from-clone lesson
A/B (5 pinned-seed neutral pairs) showed original single-clip seg000
(16.3s) beats the 52s 4-take concat on timbre fidelity — reverted live +
build-source to seg000-alone. Recorded two craft lessons: more reference
audio is not automatically better when takes vary; emotion steering pulls
output away from a cloned voice fast (keep clones emotion-neutral).
2026-08-02 13:22:41 -07:00
vh cac381a114 memory: donut voice expanded with onyx-58 clips (16.3s->52s ref)
Folded the onyx-58 Booth bundle (seg101/seg110/seg148, all Princess Donut
per operator-confirmed misdiarization of seg148) into the Zonos gateway
donut voice reference alongside the original 65-frost seg000. New ref =
52.0s @ 44.1kHz mono s16, deployed to irv-ml1 live bind-mount +
build-source tree; old ref backed up. A/B audition in booth donut-onyx58.
2026-08-02 13:14:12 -07:00
vh 1ab5465293 memory: snapshot — mimir-inbox/#377 read-path arc (deploy + #380/#381/#382 + donut voice); archived 11 old entries 2026-08-02 07:33:49 -07:00
vh a02ef5d851 docs: note worldtree #383 tier3_wings parity-fold pending (next config sync) 2026-08-01 19:39:26 -07:00
vh dfcf223ff1 docs: park Audio8 TTS-zoo addition (operator, non-blocking) 2026-08-01 17:34:51 -07:00
vh 8a824f85a3 docs(muninn-gate): Dockerfile comment — dispatch pin now 0.1.5, SHA-tag note
Gate rebuilt off vh/muninn-gate main (bc04c4c) for the muninn-dispatch
0.1.4->0.1.5 bump (concept_schema/concept_schema_source row fields). Gate
version unchanged at 0.0.14; note to also tag the image with the source SHA
for traceability, and that the pin is authoritative in pyproject.
2026-08-01 17:27:14 -07:00
vh 0441995ac8 docs(muninn-gate): sync example to reality — mimir-inbox key control scope + staging live (#377)
The mimir-inbox deploy changed two things the committed example documents:
the mimir-inbox key gained the control scope (2026-08-01, for cancel/retry),
and the staging root is no longer a placeholder — it's the real shared dir on
corviduo-dev, path-agreement probe PASS (muninn-dev). Bind was already correct
at :8090 (the stale :8080 was only in the gate repo's own example).
2026-08-01 14:36:31 -07:00
vh 4b54a32d64 feat(mimir-inbox): book-ingestion UI stack on corviduo-dev:8091 (#377)
WG-internal FastAPI+HTMX front end for large-document ingestion into the
Muninn KB, over the muninn-gate API (browser -> mimir-inbox -> staging ->
path-addressed POST /jobs). Co-located on corviduo-dev with the gate (:8090)
and the worldtree-personal muninn watcher per the operator's 2026-08-01
co-location ruling (reversing the earlier off-box/NFS plan; worldtree-dev
approved the box placement).

- Dockerfile: python:3.11-slim + uv sync --no-dev --frozen (--no-dev is
  load-bearing; the dev group's muninn-dispatch path source is absent in-image
  and INV-MI-7 forbids importing it). Single-stage by design — src/ stays in
  the final image (uv installs the project editable-linked to src/).
- compose.yaml: uid 1000, host-net bind 10.250.50.152:8091, staging :rw,
  TCP-liveness healthcheck (deliberately not coupled to gate reachability).
- Built from vh/mimir-inbox HEAD c8ab38f; deployed + healthy.

Records the open-in-place claim semantics (worldtree-dev, runner.py:362-367)
and the INV-MI-19 retention rule (staged files persist until job terminal;
gate retry returns a false-200 on a swept source) in persistent memory.
2026-08-01 14:31:14 -07:00
vh e6eabc1dde memory: snapshot — session close (muninn-gate #377 deployed on corviduo-dev, wtsdk 1.1.0 published + vh token, kimi-k3 reasoning-cap fix relayed to heid, magpie TTS rejected) 2026-07-31 21:27:13 -07:00
vh 786462ac9c feat(muninn-gate): WG-internal Muninn ingestion front door stack (#377)
Deployed on corviduo-dev, co-located with the worldtree-personal muninn
watcher. ingestion_root=/data/state/ingestion (shared state volume, byte-
identical to the watcher); runs as uid 1000 to write the queue; staging
bound :ro at the ratified /mnt/muninn-staging/mimir-inbox (local placeholder
until the shared mount + mimir-inbox writer land). Boot verified: /ping
{"service":"ok"}, /health watcher.running=true (byte-identity proven).

Image built out-of-band with the Gitea read token as a BuildKit secret.
Real config (bearer keys) lives on-server at /opt/docker/conf 0600.
2026-07-30 21:33:29 -07:00
vh 17d776fc90 memory: snapshot — multi-day infra session close (config repo + boundary, Zed FIM route, muninn #377, Kimi, herald, Booth v0.1.4) 2026-07-30 06:39:57 -07:00
vh 792aa2852c docs(zed-fim-proxy): source-IP allowlist stays OFF by design (Zed roams WG 10.0.0.0/8) 2026-07-27 22:58:22 -07:00
vh a300cdcd26 feat: Zed edit-predictions keyless FIM route (Qwen2.5-Coder-1.5B / coder-fast)
Deep-research-picked Qwen2.5-Coder-1.5B (BASE, Apache-2.0, native FIM) as a
low-latency inline-completion seat:
- stacks/vllm: vllm-coder service (ana-ml2 GPU1 :8020) + granite shrunk
  (util 0.27->0.13, max-len 131072->16384, seqs 1024->256; granite phasing out)
  to free GPU1 room.
- stacks/litellm: coder-fast alias -> :8020 (mode: completion, /v1/completions).
- stacks/zed-fim-proxy (NEW): keyless /v1/completions front door on ana-docker
  :4141 for Zed (which can't send an auth header) — POST + path + model
  allowlist, injects a coder-fast-scoped virtual key -> LiteLLM :4000. Anon
  /ping liveness. Verified keyless FIM end-to-end.

Zed api_url = http://10.250.50.70:4141/v1, model coder-fast, prompt_format qwen.
Source-IP allowlist off pending the Mac's observed source IP.
2026-07-27 22:55:21 -07:00
vh 8822a0bb81 memory: Worldtree #377 CLOSED — muninn watcher acceptance passed 2026-07-27 08:35:08 -07:00
vh 038e455897 memory: #377 durability resolved (COMPOSE_PROFILES=muninn) + env.public config-as-code extension 2026-07-27 08:27:47 -07:00
vh e06a96fc3e memory: Muninn ingestion-watcher sidecar deployed on personal Worldtree (#377) 2026-07-27 08:21:05 -07:00
vh 8944531ba0 memory: jackdaw-compose.service decommissioned (AI Composer cut from JackDAW v1) 2026-07-27 06:59:21 -07:00
vh 557d0b56d9 memory: demo BIFROST_CLIENT_ALLOWED_HOSTS delta (wyrd-dev provider) + env-change recreate/image-pin foot-gun 2026-07-26 22:17:20 -07:00
vh a5e2d91dfd memory: record nh3-extdev herald install + Booth v0.1.4 download feature 2026-07-25 17:49:36 -07:00
vh 91a031fdb3 feat(booth): downloadable booths — whole-booth zip + ?dl force-download (v0.1.4)
A verbatim index.html booth (e.g. edict-design-brief: a rendered brief + its
.md) had no download affordance — the page is served raw with no gallery/per-file
chrome. Adds:
  - GET /b/<name>/?download=1 -> streams the whole booth as <name>.zip (attachment)
  - GET /b/<name>/<file>?dl=1 -> forces Content-Disposition: attachment (html/md/
    text otherwise render inline with no easy save)
  - a download link on the index card (the accessible spot for verbatim booths)
    and the gallery header
Tests for both; verified live against edict-design-brief on nh3-dev :8090.
2026-07-25 17:49:11 -07:00
vh df1d87935d memory: wire bil-smithy-dev althing pane route + record the zellij-window-ping mechanism 2026-07-25 11:25:20 -07:00
vh 60accf4cf6 memory: correct Kimi K3 record — coding endpoint primary, gen-api variant kept 2026-07-25 11:01:12 -07:00
vh 9e2f787567 fix(litellm): route kimi-k3 to the Kimi Code (coding) endpoint
The Heid panel plan uses Kimi's coding endpoint, not the general Moonshot API.
kimi-k3 now → openai/k3 @ https://api.kimi.com/coding/v1 (KIMI_CODE_API_KEY,
Vivace); the original general-endpoint entry is kept as kimi-k3-gen-api
(api.moonshot.ai, MOONSHOT_API_KEY). Both verified live through the gateway.
Same k3 constraints on both: temperature MUST be 1 (else 400), reasoning model
(reasoning_content vs content, needs adequate max_tokens).
2026-07-25 11:00:15 -07:00
vh 0b0c915dc9 memory: record Kimi K3 gateway wiring (temp=1 + reasoning-model constraints) 2026-07-25 10:54:28 -07:00
vh edaa9a9c50 feat(litellm): front Kimi K3 (Moonshot) as a paid gateway passthrough
Adds model_name kimi-k3 → openai/kimi-k3 @ https://api.moonshot.ai/v1
(OpenAI-compatible), keyed by MOONSHOT_API_KEY (compose env + .env.example
placeholder; real key on server only). Verified live through the gateway.

Two Moonshot constraints captured in the config comment + pinned: K3 accepts
ONLY temperature=1 (else 400), and it is a reasoning model (CoT in
reasoning_content, answer in content — needs adequate max_tokens or content
returns empty). Model id confirmed via /v1/models.
2026-07-25 10:53:43 -07:00
vh 1fc8016988 memory: WT config-as-code repo shipped + boundary agreed
vh/worldtree-instance-configs (infra-ops) built, pushed, validated; deploy-wt-config
tool (diff/deploy/capture + health-gate + rollback). worldtree-dev agreed the
authoritative-writer boundary (no live-edits to /opt/<instance>/config; admin-API
DB ops carve-out). pinned confirmed out-of-scope (no bind-mount).
2026-07-25 02:45:02 -07:00
vh fd98122b33 memory: snapshot — infra-ops WT config-repo build queued; Booth shipped; #376 closed
Centered on the resume task: build the infra-ops-owned Worldtree per-deployment
config repo + deploy tooling (operator-directed) with the one-time
worldtree-dev boundary agreement. Also records: The Booth shipped (v0.1.3), the
jackdaw-compose nh3-dev deploy, and the Worldtree #376 arc closed (per-instance
config ruled by-design). Two detail files + the /tmp handoff.
2026-07-25 02:22:42 -07:00
vh cd4d52e871 docs(nh3-dev): add Booth + jackdaw-compose to the running-services inventory
Two user-systemd services stood up on nh3-dev this session weren't in the
"What runs here" list:
- The Booth (:8090, booth.service) — eshpfi services/booth ephemeral media board.
- jackdaw-compose (:8787, jackdaw-compose.service) — JackDAW /compose AI backend
  hosted for jackdaw-dev, Origin-gated, fronted by the :4500 bench proxy.
Keyless entries (the jackdaw unit's key stays server-side, uncommitted).
2026-07-23 08:44:19 -07:00
vh d813f152ce feat(booth): copy-id button on the pickup banner (v0.1.3)
Adds a "⧉ copy" button next to the pickup id that copies the id to the
clipboard (flips to "✓ copied"). The Booth serves over plain HTTP on a LAN IP,
where navigator.clipboard is undefined (secure-context only) — so the handler
falls back to a hidden-textarea execCommand('copy') that works over HTTP.
Verified on the LAN-IP (non-secure) path: isSecureContext=false, clipboard API
absent, button state flips, no errors. Reusable via any .copy-btn[data-copy].
2026-07-22 17:51:43 -07:00
vh 966324c5f1 docs(ana-ml2): refresh snapshot + sync README to live GPU state
The README's running-stacks table had drifted well behind reality (still listed
llama-swap + only the embed/rerank/reward trio). Regenerated system-details.txt
and rewrote the stacks + GPU-allocation sections from a live docker ps +
nvidia-smi (2026-07-22):

- GPU 0 (hot): vllm-aeon-gen (qwen3.6-35b-a3b-heretic, NVFP4) + vllm-charrp-
  reasoning-nvfp4 (char-rp-reasoning, NVFP4), ~42+45 GB.
- GPU 1 (on-demand): granite-4.1-8b, selene-1-mini-8b, Skywork reward,
  Qwen3 embed/rerank, and the Magidonia-24B char-RP GGUF (llama-charrp), ~91 GB.
- Recorded the dormant on-disk stacks and llama-swap's retirement.
2026-07-22 15:24:55 -07:00
vh 603d0ad555 feat(booth): image viewer page with Fit/1:1, download, Esc-back (v0.1.2)
Clicking a gallery image now opens a dedicated viewer instead of dumping you on
the raw file.

- GET /b/<name>/view?f=<img> — full-viewport viewer (registered before the file
  catch-all so /view wins; non-image f 307-redirects to the raw file, traversal
  and missing f 404).
- Fit (downscale-only) / 1:1 (natural pixels, scroll-to-pan) toggle that only
  appears when the image is larger than the viewport — when it already fits,
  Fit ≡ 1:1 so the toggle is hidden. Re-evaluates on resize.
- Download button + ✕/Esc back to the gallery. Australis-themed, progressive
  JS (degrades to fit-only, no-JS still shows the image + download + back).
- 5 new tests (34 total, all green); verified Fit/1:1/hidden-toggle states in a
  real browser.
2026-07-20 22:10:46 -07:00
vh 775e9804cd feat(booth): upload-for-pickup with human-readable ids (v0.1.1)
Add a reverse direction to the Booth: the operator (or any client via `curl -F`)
can upload files through the browser and pick them up by a human-readable id.

- POST /upload — streams files to a new booth named with a human-readable id
  (e.g. 4-wombat / star-84), 303-redirects to /b/<id>/ (id in the Location
  header so curl clients can read it). Uploads reuse the whole booth machinery
  (render, per-file download links, 24h TTL sweep, delete).
- Human-readable ids: word+number in either order, collision-checked, from a
  curated 140-word friendly list; secrets-based selection.
- Safety: filenames reduced to a safe basename (no traversal), streaming size
  cap (BOOTH_MAX_UPLOAD_MB, default 1024) + file-count cap (BOOTH_MAX_FILES,
  default 50), partial-write cleanup on any failure.
- UI: Australis-themed upload/drop panel (drag-drop, progressive-enhancement JS,
  degrades to a native file input), a "⬆ pickup" badge on upload booths, a
  pickup banner, and a ⬇ download link on every gallery item.
- python-multipart dependency; homepage tile description updated; 9 new tests
  (24 total, all green).
2026-07-20 14:44:21 -07:00
vh eaece794d7 fix(booth): button legibility in the Australis theme
- Wipe "×" is now an opaque dark control-scrim with an always-light glyph, so
  it stays legible over bright thumbnails bleeding through AND in both themes
  (the glyph no longer follows --fg-*, which flipped dark-on-dark in light mode).
- "Wipe now" is a red-outline danger button (bright-red text/border, fills red
  on hover) instead of muted gray-on-transparent that read as illegible.
- Destructive hover text is white on red (was dark-on-red, low contrast).
- Nudge expiry sub-text --fg-muted -> --fg-3 for a bit more contrast.
2026-07-20 12:52:31 -07:00
vh 3b6fa4a962 style(booth): adopt Corviduo "Australis" theme
Re-skin the Booth in the fleet's Australis palette (aurora accents, dark-first),
token values adopted from ratatoskr-web's canonical colors_and_type.css:
--aus-* palette, --rk-* console surfaces (#171a23 canvas), Space Grotesk /
Inter / Berkeley Mono stacks, aurora-cyan brand + glow focus rings, red
reserved for the destructive wipe action. Self-contained, no webfont CDN;
light theme via prefers-color-scheme. Only base.html changes (the content
templates keep their class names).
2026-07-20 12:48:35 -07:00
vh f4a5ba7c31 feat(booth): add The Booth — ephemeral media drop board for CC sessions
A standing user-level web server (nh3-dev :8090) that renders drop-folders
under ~/booth-data as ephemeral media "booths" so Claude Code sessions can
surface A/B renders and smoke results to the operator, then let them self-wipe.

- Scan-and-serve model, no database, no upload API — a booth is just a folder.
  A folder's own index.html is served verbatim; otherwise an auto-gallery of
  images / webm+mp4 video / audio is rendered, with <file>.txt caption sidecars
  folded in (labels A/B pairs).
- 24h TTL from newest mtime in the tree; background sweeper wipes stale booths.
- Path-traversal + symlink-escape guarded; delete via UI button or DELETE API.
- FastAPI + Jinja2, runs from the checkout under systemctl --user (booth.service),
  alongside the other nh3-dev fleet sidecars. 15 tests, all green.
- Homepage tile added (Apps -> The Booth, siteMonitor /healthz).
- Harden the homepage rsync doc: exclude *.bak* and logs/ so --delete can't
  wipe the host's dated services.yaml backups (footgun found deploying this).
2026-07-20 10:17:40 -07:00
vh a5dcad8bd3 feat(comfyui): switch allocator to cudaMallocAsync (A/B won, fixes LTX OOM)
Mirror comfy-dev's operator-run allocator A/B result off irv-ml1: drop
--disable-cuda-malloc (ComfyUI keeps CUDA's default async allocator) and
remove PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True (native-allocator-only,
inert under cudaMallocAsync). The native+expandable_segments combo was
fragmenting/over-reserving (~45 GB allocated-but-unused) and OOMing the LTX-2.3
v1.5.0 LoRA stack at Gemma TE load; cudaMallocAsync packs tighter + returns
freed blocks so the job fits (stress test peaks ~82% VRAM, 0 OOM). The
shared-A6000 phantom-OOM that --disable-cuda-malloc guarded is gone since TTS
moved to the 3090 (2026-06-18).
2026-07-19 10:36:46 -07:00
vh 1ba6dc3257 docs(comfyui): bake RTX VSR provisioning into canonical README
Record the RTXVideoSuperResolution node clone + the nvidia-vfx pip install
(scoped --extra-index-url, uid 1000) in the stacks/comfyui runbook. Flag the
durability split: the node is persistent (basedir/custom_nodes) but nvidia-vfx
lives in the disposable venv (run/), so it must re-run after every fresh
bootstrap. Deliberately not a global PIP_EXTRA_INDEX_URL (torch-pin safety).
Closes the comfy-dev provisioning ticket.
2026-07-19 08:27:10 -07:00
vh fe78461e8b memory: park comfy-dev RTX VSR provisioning bake (irv-ml1 ComfyUI, low-pri) 2026-07-19 08:19:23 -07:00
vh 38760a48e3 memory: vh PyPI consumer read-access convention (shared read:package token) + wyrd-dev provisioned 2026-07-19 06:19:31 -07:00
vh 1af67bcfb2 memory: snapshot — soong-lab auto-redeploy DONE+validated; worldtree-sdk 1.0.0 (py) published
soong-lab: WT-style CI-deploy step live (SSH deploy@corviduo-dev, compose
pull && up -d from /opt/soong-lab, /api/version health-gate). Dir relocated
+ old retired; dedicated soong deploy key; run #5 green (container recreated,
v0.3.25 live). worldtree-sdk 1.0.0 Python published to vh Gitea PyPI +
acceptance-verified.
2026-07-18 23:18:18 -07:00
vh fb7b5959f3 memory: snapshot — queue soong-lab auto-redeploy for next session
Deferred-work capture: Vuong approved wiring soong-lab auto-redeploy; operator
deferred execution to a fresh context. Recorded in Recent decisions with the
mechanism (WT-style CI-deploy step), the blocker (a vh-owned deploy SSH-key
secret), and next-session steps; handoff updated to make it the primary task.
The "5 AM clock" report was a hallucination in another window — clock verified
correct (US/Pacific, NTP-synced), no change.
2026-07-18 22:16:53 -07:00
vh 0ee8f437f2 memory: nh3-dev /tmp auto-clean rule (tmpfiles 3d) + one-shot purge 2026-07-18 17:35:47 -07:00
vh abc8f0ceab memory: snapshot — soong-lab cutover + zonos 0.2.1 presets + fleet CI recipe + peer creds
End-of-session snapshot for /clear. In-flight compressed (four majors landed:
zonos-gateway 0.2.1 emotion presets, soong-lab containerized cutover, Wyrd +
wtsdk credential provisions). New Recent-decisions + Tried entries and three
detail files capture the durable lessons (fleet Gitea build recipe, the
vh-is-a-user package-write constraint, soong-lab deploy layout).
2026-07-18 16:40:49 -07:00
vh deae057399 memory: zonos-gateway repo reconcile + soong Homepage plan (manual entry, option B) 2026-07-18 02:02:44 -07:00
vh 4bdf01001c docs(zonos-gateway): sync emotion-presets spec + memory (0.2.1 bake)
Mirror the canonical EMOTION-DIALS-SPEC.md from vh/zonos-gateway (now carries
the provisional per-voice emotion presets baked as gateway 0.2.1) and capture
the axes-sweep → bake arc in persistent memory.
2026-07-18 01:37:27 -07:00
vh 89611eb06b memory: snapshot — Zonos emotion-tuning + voice-cloning (8 voices, dial-in studio, emotion canonical) for /clear
Rewrote in-flight for the Zonos character-voice work: 4 cloned voices + host-managed
gateway voices, streaming dial-in studio (source saved to ~/development/zonos-tools/),
and the empirical emotion sweep canonical (single-emotion, two-regime accurate/expressive;
happy/sad usable, angry/surprised broken on named dirs -> axes sweep next). Captured #365
closed + WT#368 forensics + personal agent-memory scrub. Open loops: yt-voice-clipper
yields test, dvalin axes-sweep numbers, re-arm monitor + read mail.
2026-07-18 00:25:18 -07:00
vh 438cd35436 docs(zonos-gateway): sync mirror compose — host-managed voices bind-mount (Emmie)
Reflects the deployed change: ./voices:/app/voices:ro so voices are a filesystem
drop-in. Emmie voice added + committed to vh/zonos-gateway.
2026-07-17 22:54:34 -07:00
vh d725da0c90 docs(zonos-gateway): vh/zonos-gateway stood up in gitea (resolve not-in-gitea flag)
Created private vh/zonos-gateway on gitea, imported the previously-unversioned
~/zonos-gateway working tree (source + dials-first spec + voices). Updated the
stack README, spec §8, and the sister-repos table to point at the repo. Remaining
follow-up: CI + deploy key to wire the irv-ml1 deploy tree to the repo.
2026-07-17 18:49:09 -07:00
vh 0a9fb85a52 docs(zonos-gateway): dials-first emotion spec (operator ruling)
Canonical direction: emotion set by twisting raw dials per-utterance, not preset
selection. Presets demoted to optional examples. Spec covers the dial vocabulary
+ ranges, the emotion_cfg_scale 'deaf by 1.5' rule (NO cap — documented ceiling,
explicit over implicit), measured RTF cost, starting-point dial-sets, an LLM
client system-prompt snippet, and clone reference guidance (~15-24s, no
transcript). Follow-ups flagged: align dials.py cfg help/metadata, trim in-code
PRESETS pending usage check, stand up vh/zonos-gateway for version control.
2026-07-17 18:33:26 -07:00
vh ba0ec64ac3 docs(zonos-gateway): capture the live :8890 gateway stack + emotion-preset system
Captures the production Zonos TTS path that the repo was blind to: stock ZONOS2
:1920 engine (stacks/zonos-engine) fronted by zonos-gateway:0.2.0 :8890, reached
via the LiteLLM ext-tts alias. Documents the emotion-preset system (neutral/warm/
excited/sad/intense/whisper, the simple preset: caller path), the API, and the
measured real-time cost (calibrated steering free at RTF~0.52, cfg1.5 ~0.625 —
still realtime). Flags the gateway source (~/zonos-gateway on irv-ml1) as not yet
in gitea. Marks stacks/zonos (v0.1 Gradio) dead/superseded. Records the emotion-
lever finding (text-priming flat -> native steering works) in persistent memory.
2026-07-17 15:56:11 -07:00
vh 196a0c1e4c memory: #365 CLOSED — personal live on b125, byte-exact, both instances confirmed
worldtree-dev ruled the four other personal deltas code-default-optional (none
boot-required), cut staging/v1.0.0b125 (workflow 1859 green). Personal now on
b125 (877bb577ad36), healthy, booted off the staged bind-mount, live #365 blocks
byte-exact vs baked, clean boot. Demo + personal both confirmed. .bak-pre-365
rollback on both.
2026-07-17 13:38:47 -07:00
vh bb7d38d6dc memory: #365 demo confirmed on b125 (byte-exact) + personal staged; b125 tag held on config-scope ruling
Demo auto-deployed to b125 and passed the boot-FATAL validator live against
the staged bind-mount; staged demo blocks byte-exact vs the baked image.
Personal staged (operator-directed) with the same verbatim blocks + backups,
all b125 checks pass, no restart. worldtree-dev holds staging/v1.0.0b125 until
they rule whether personal's other missing b107-b125 blocks (metrics/kb_audit/
reference_knowledge + affect-debug-observability-allow) are boot-required.
2026-07-17 13:34:46 -07:00
vh dbf511851c memory: Worldtree #365 demo config pre-sync STAGED (internal-comms tiers/rules + gate)
Staged the boot-blocking #365 delta on corviduo-dev DEMO /opt/worldtree/config
per worldtree-dev thread 01KXRE59 (verbatim from their 6a60fe3/b123 blocks):
internal + internal-restricted tiers, four internal-* rules, and the
internal_agent_comms:{enabled:false} gate. Validated via the demo container's
own PyYAML + the exact-set uniqueness guard; no restart (b123 activates off the
bind-mount). Backups .bak-pre-365. Flagged a pre-existing free==pro scope-set
dup to worldtree-dev as a b123 boot-block risk.
2026-07-17 13:10:14 -07:00
vh 069b3c2020 memory: capture Worldtree #365 boot-blocking demo config pre-sync (unblocked, deferred)
worldtree-dev flagged a boot-blocking config delta (commit 6a60fe3/b123, #365
internal-badge layer) needing a pre-sync of the demo policies.yaml + defaults.yaml
before its eventual deploy. Verbatim blocks received (althing 01KXRE59); the two
new scope-sets pre-verified unique vs the demo's 7 existing tiers. No urgency (push
held for heid gates) + FATAL-on-malformed, so deferred to a focused pass and captured
as an open loop (persistent-memory + /tmp handoff) rather than staged at the snapshot tail.
2026-07-17 09:29:42 -07:00
vh 2941158c70 memory: snapshot — Zonos2 containerize + prosody-priming (for /clear to build fresh)
Current state rewritten to the active build task: containerize the production
Zonos2 :1920 TTS engine as a self-contained image (config captured in 14a0004)
and prototype the operator's prosody-priming hypothesis (prime→generate-one-
utterance→parakeet-clip→deliver, adapter-level, engine stays stock). New detail
file + Recent-decisions pointer capture the full plan + the crux (does AR prosody
carry the sentence boundary — A/B the join). /tmp handoff written for the fresh session.
2026-07-17 09:16:43 -07:00
vh 14a0004a47 docs(zonos-engine): capture the production ZONOS2 :1920 launch config (was live-only)
The Zonos TTS engine that zonos-gateway fronts (irv-ml1 3090, feeds asset-engine +
gateway-chat) ran as a bare native process with its real invocation existing ONLY
in the running process argv — the committed harness/zonos_server.sh on irv-ml1 was
STALE (said A6000/:1919, no perf flags; live is 3090/:1920 with cuda-graph/num-pages/
max-running-requests/memory-ratio). Captured the corrected canonical invocation +
tunables + the containerization plan here so the config survives a process death.

Engine = stock Zyphra/Zonos2 @ 194c0a3 (no custom PFI server code); torch 2.9.1+cu128;
15 GB HF weights. Next: containerize in-place on the 3090 (operator: keep off the
A6000, it OOMs under ComfyUI). Not yet built — this commit is the config capture only.
2026-07-17 09:03:05 -07:00
vh 9e69639482 fix(vllm): pin granite --max-num-seqs=1024 (was implicit default 128)
granite (fleet fan-out summarizer/classifier) had no explicit --max-num-seqs,
so vLLM V1 resolved it to 128 — which caps concurrency BELOW granite's own KV
bound (~192 concurrent @ 1K-token calls, more for shorter classify calls).
Pinned it very high (1024) so the KV pool is the only bound; VRAM-neutral
(the KV pool is util-bound, unchanged). Added the flag to the granite command
+ GRANITE_MAX_NUM_SEQS to the env template. Live applied + verified
(resolved max_num_seqs=1024, seat healthy).
2026-07-16 10:47:15 -07:00
vh a2b026d499 feat(gpu): relocate char-rp to GPU1 + re-optimize both ana-ml2 cards for max context
Operator-directed 2026-07-16. Moved the char-rp prose seat (Magidonia-24B,
llama-charrp) from GPU0 to GPU1 (CHARRP_GPU_ID 0->1; recreate llama-charrp
only -- the var is shared with the retired GGUF reasoning service), then
re-optimized every context-relevant seat on both cards to native/max context
with acceptable headroom:

  GPU0 (both seats now 256K native, ~14 GB reserve):
    - char-rp-reasoning 150K -> 256K  (heretic2 stack, util 0.38->0.46, 1.56x)
    - gen 256K, max-num-seqs 16 -> 32 (qwen36-27b-aeon, util 0.30->0.42, 5.43x)
  GPU1 (~6.7 GB headroom):
    - granite 64K -> 128K full-chapter (vllm stack, util 0.18->0.27, 1.50x)
    - char-rp 128K native (4 slots), selene/reward/embed/rerank unchanged

All seats gateway-verified healthy. Live .env changes on ana-ml2 with per-stack
backups (*-20260716). Templates updated to match; the qwen36-27b-aeon template
carries a NOTE that its served-name/model still lag the 2026-07-08 gen model swap
(35B-A3B-heretic) -- separate reconciliation. persistent-memory records the full
layout + the util-floor / per-model-KV-cost lessons.

Note: the heretic2-charrp-reasoning stack (char-rp-reasoning's live config) is
still untracked in git -- standing open-loop, its .env change lives server-side only.
2026-07-16 09:28:07 -07:00
vh f25f494f07 fix(vllm): right-size granite util 0.34->0.18 + max-len ->65536 (free ~10.5GB GPU1)
Operator-directed 2026-07-16: free ~10GB on ana-ml2 GPU1 to relocate a GPU0
model onto GPU1. granite-4.1-8b (fleet summarizer) was over-provisioned at
util 0.34 / max-model-len 131072 with a flat 0.0% KV usage.

Set GRANITE_GPU_MEM_UTIL 0.34 -> 0.18 and GRANITE_MAX_MODEL_LEN 131072 -> 65536
on the live /opt/docker/compose/vllm/.env (backup .env.bak-pre-granite-rightsize-
20260716), recreated vllm-granite ONLY (shared stack). Result: GPU1 62,641 ->
51,897 MiB used (~10.5GB freed, ~45GB free now); KV 6.45 GiB / 84,528 tok /
1.29x concurrency @ 65536; summarizer verified healthy.

The util drop required the max-len drop: on this shared card the effective KV
slope is ~950 MiB per 0.01 util, and vLLM refuses to start unless the KV pool
holds >= 1x max-model-len -- util 0.15 undershot (est max-len 47184 < 65536,
crash-loop, ~2-3 min summarizer outage) before 0.18 landed. 65536 is granite's
precedented summarizer ctx; a summarizer doesn't need 131072.

.env.example updated to the new util (max-len was already 65536 in the template;
live had drifted to 131072). persistent-memory.md updated (parked item closed).
2026-07-16 08:51:05 -07:00
vh 925947c71e fix(litellm): retire image-bench backend, repoint image-judge + qwen-image-bench aliases to gen
Operator-directed 2026-07-15. The dedicated Qwen-Image-Bench NVFP4 judge
backend on ana-ml2 GPU1 (:8014) was stopped to reclaim ~32GB after the
arbo -> gen hero-judge switch. Both LiteLLM gateway aliases that pointed at
it -- image-judge and qwen-image-bench -- now repoint to the gen backend
(:8015, qwen3.6-35b-a3b-heretic, vision-intact), held at deterministic
judge sampling (temp 0 / top_k 1 / rep_pen 1.05) with enable_thinking:false
(a reasoning preamble breaks json_object). Verified live: both answer with
:8014 down, so they are definitively on gen.

Incidental: backfilled the canonical char-rp-reasoning litellm block, which
had lagged live since the 2026-07-14 NVFP4+MTP seat repoint (model
deckard-pkd-27b -> char-rp-reasoning, top_k 40 -> 20, min_p dropped,
enable_thinking:true added). Required so pushing the canonical would not
clobber the correct live block.

Live changes applied out-of-band (config push + litellm restart + stack
stop on ana-ml2); live config backup at
config.yaml.bak-pre-imagejudge-20260715. Revert path documented in the
config comment. persistent-memory.md updated (parked item closed).
2026-07-15 23:07:13 -07:00
vh d710e56aca memory: migrate persistent-memory.md to two-tier index (53 detail files)
Split the 53 over-threshold dated log entries (Recent decisions, Tried
and abandoned) into per-entry persistent-memory.d/<slug>.md detail files,
leaving one-line pointers in the index; the 10 short entries stay inline.
Startup index drops 60,527 -> 25,256 bytes (492 -> 270 lines); entry
bodies move verbatim to on-demand detail files, so a fresh session loads
~25 KB instead of ~60 KB and pulls a detail file only when its pointer is
relevant. Top matter (Repo purpose, Tools & conventions, Current state)
is unchanged; both archival back-references preserved.

CLAUDE.md persistent-memory section now documents the index<->detail read
discipline (read the index, pull details on demand, never bulk-read the
dir, commit both together).

Auto-archival still held every dated entry back (all <30 days old); the
July burst begins aging past the 30-day guard ~2026-07-31.
2026-07-15 13:33:42 -07:00
vh 05a4f54a2a memory: snapshot — 2026-07-15 fleet-ops session
Rewrote Current state / in-flight to reflect the session's landed work +
parked items (in-flight compressed from the now-done NVFP4/#355/deploy-speed
history). Added Recent decisions (homepage AI-tab revamp 569e1af; esh-docker-vm
reboot + NFS fstab fix 21d9a07; HA config repo; char-rp-reasoning OOM rescue;
arbo->gen switch with image-bench eviction parked post-bake; soong-lab library
persistence; statusline overhaul) and Tried-and-abandoned lessons (nofail
defeats After=remote-fs.target; D-state wedge needs a reboot; max-model-len
doesn't free vLLM VRAM; statusline cost is per-session). Nothing archivable
(all dated entries <30 days).
2026-07-15 11:04:13 -07:00
vh 21d9a07bc3 fix(esh-nfs): order docker after the NFS mount units directly
The prior fix (_netdev,nofail + docker.service After=remote-fs.target) looked
correct but silently failed — paperless still Exited(255) on the 2026-07-14
reboot. Root cause: `nofail` drops a mount out of remote-fs.target's blocking
set, so ordering docker After=remote-fs.target does NOT wait for the nofail
NFS mounts. Fix: add x-systemd.before=docker.service,x-systemd.mount-timeout=30
to the 4 NFS fstab lines (direct mount->docker ordering, nofail-safe). Applied
+ verified live (systemctl show docker -p After now lists all 4 mnt-*.mount).
Playbook + verify updated to canonicalize.
2026-07-14 21:53:33 -07:00
vh 569e1af9ca feat(homepage): split AI fleet into role-based groups on a dedicated AI tab
Move the ~22-service flat "AI Systems" group off the Main tab into a new
four-tab layout (Main / AI / Infrastructure / Toolchain). The AI tab sorts
the inference fleet by function into seven groups:

  AI - Inference        gen, char-rp, char-rp-reasoning, Granite summarizer
  AI - Eval & Retrieval Selene, Skywork Reward, Qwen3 rerank/embed, image-bench
  AI - Gateways & Chat  LiteLLM, Asset Engine, Gateway Chat, Open WebUI, ...
  AI - Speech (TTS)     Chatterbox Fast, Kokoro, mOrpheus
  AI - Audio Tools      Parakeet ASR, YT Voice Clipper
  AI - Image & Media    ComfyUI, Arbo
  AI - Dormant          stopped rollback seats + retired auditions

Relabel each stack's homepage.group so canonical stacks/ matches the live
containers on ana-ml2, ana-docker, and irv-ml1. Dormant stacks were refreshed
with `docker compose up --no-start` so they carry the new label while staying
stopped (compose-start rollback preserved). settings.yaml drives tab/order/
columns; services.yaml and README updated to the new scheme.
2026-07-14 20:05:50 -07:00
vh 982c319d9f feat(heretic2-nvfp4): WORKING modelopt NVFP4+MTP seat + full recipe runbook
The fast char-rp-reasoning seat works: ~77 tok/s (vs GGUF ~59.5, base NVFP4 ~53),
MTP draft-acceptance 32-40%, mean acceptance length 2.19. Same Heretic2/NEO-CODE
model, NVFP4 + native qwen3_5_mtp spec-decode.

Full end-to-end recipe + the four landmines in docs/runbooks/heretic2-nvfp4-mtp-seat.md:
(1) load as AutoModelForImageTextToText not AutoModelForCausalLM (namespace/gibberish);
(2) modelopt format not compressed-tensors (compressed-tensors MTP = 0% accept);
(3) modelopt 0.45 <-> transformers 5.12.1 FusedMoE crash (guarded in quant_modelopt.py);
(4) vLLM 0.24.0 does NOT propagate modelopt exclude_modules to the spec-decode draft
model -> BF16 mtp head gets quantized -> shape crash; no checkpoint config fixes it
(is_layer_skipped is exact-membership not glob) -> fix is a mounted sitecustomize that
force-skips mtp.* in is_layer_skipped (upstream vLLM bug to report).

Scripts: quant_modelopt.py (FusedMoE guard + single-shard export + multimodal load),
finalize_modelopt_mtp.py (splice bf16 mtp), serve_modelopt_mtp.sh, run_quant_modelopt.sh,
sitecustomize-mtp-workaround.py.
2026-07-14 14:41:48 -07:00
vh aca45393c2 fix(heretic2-nvfp4): quant as ConditionalGeneration (namespace fix) + modelopt recipe for working MTP
Root-caused the NVFP4 gibberish to a quant-namespace bug: quant_nvfp4.py loaded
via AutoModelForCausalLM -> text-only Qwen3_5ForCausalLM -> flat model.layers.* keys,
but vLLM 0.24 serves only Qwen3_5ForConditionalGeneration (whose weight mapper needs
model.language_model.*). Fixed by loading as AutoModelForImageTextToText; NVFP4 now
serves coherent (validated greedy on ana-ml2 GPU0).

Base NVFP4 (compressed-tensors) measured ~53 tok/s (~= GGUF at batch-1, no single-stream
win) and its MTP is 0% acceptance (vLLM's Qwen3_5MTP drafter loads the bf16 mtp head only
off a modelopt main-model checkpoint). Added quant_modelopt.py (nvidia-modelopt PTQ,
matches AEON's NVFP4 W4A4 g16 + lm_head/linear_attn/visual exclusions) as the path to
working native MTP; graft + splice + serve otherwise unchanged.
2026-07-14 13:10:25 -07:00
vh b972bef10e snapshot: NVFP4+MTP fast-seat quant recipe + failure state (gibberish, unisolated)
Captures the full pipeline recipe (graft->quant->splice->config->serve) with every
gotcha found this session, the 3 gibberish suspects, and the diagnostic ladder
(validate native-config no-MTP coherence FIRST) for a fresh session to finish the
chase. Also stages the NVFP4 scripts + 512-row calib. Recent decisions: NEO-CODE
seat swap (R36), webhook ALLOWED_HOST_LIST fix. Lessons: validate-tracer-bullet-first,
mtp-graft-dropped-at-load, gitea-204-red-herring.
2026-07-14 11:31:57 -07:00
vh 462d528bef fix(soong-lab-ci): webhook auto-deploy real root cause = gitea ALLOWED_HOST_LIST + add listener logging
The ufw fix (prior commit) was necessary but insufficient. The DECISIVE blocker
was gitea webhook.ALLOWED_HOST_LIST = 'external, 10.100.0.0/16' (NH3 only) —
corviduo-dev is 10.250.50.152 (Anaheim), so gitea refused to deliver ('deny
10.250.50.152') and never opened the TCP connection. Fixed to 'external,
10.0.0.0/8' (whole fleet, matches the ufw choice) + gitea restart.

Listener now logs every delivery (source-IP/hmac_ok/ref/action) — the old
log_message=pass silence hid the whole failure. Proven end-to-end: real gitea
delivery -> hmac_ok=True, ref=main, 202 deploying -> green deploy.
2026-07-14 09:19:38 -07:00
vh 4fc0c27485 fix(heretic2-nvfp4): parse tool_call arguments string->dict for Qwen3.6 template
render-verify caught it: Dvalin's calib tool_calls carry OpenAI wire-form JSON
string arguments, but the Qwen3.6 chat template does .items() on arguments (needs
a dict) → jinja TypeError. Parse string->dict in render_verify + the quant's
load_calib_chat. Confirmed: renders the exact qwen3_coder XML the seat emits
(prefixed bifrost.soong-lab.*, v0.3.13 generate_portrait, <think>, <tool_response>).
2026-07-14 09:04:19 -07:00
vh 920f9a3709 feat(heretic2-nvfp4): MTP-graft + NVFP4 quant scripts + pipeline README (fire-ready)
graft_mtp.py: grafts the 15 base-Qwen3.6 MTP tensors into Heretic2 BF16 (CPU-only).
quant_nvfp4.py: llm-compressor NVFP4 (Linear only; GDN/vision/lm-head/norms/MTP
kept BF16 per robbatt's deckard recipe + brokkr's spec); text (AEON-baseline) or
chat (production, apply_chat_template renders qwen3_coder XML) calib modes.
README: fire sequence + gates (GPU window, production calib) + artifacts.

Spike gated only on: (1) off-peak Blackwell GPU window, (2) brokkr's production calib.
2026-07-14 08:57:25 -07:00
vh bbbfe5502e feat(heretic2-nvfp4): stage soong-lab v0.3.13 live 9-tool schema for the NVFP4 calib tool-call-XML slice
Extracted from the deployed backend (bifrost/tools.py) via the venv with a
capturing mock register_tool — the LIVE schema, not a stale copy. OpenAI-function
form for brokkr/Dvalin's ~128-row tool-call-XML calib slice (R36 #355 anchor).
2026-07-14 08:46:49 -07:00
vh b195815586 docs(soong-lab-ci): correct webhook runbook — root cause was ufw firewall (not SSRF)
The auto-deploy silently never worked: corviduo-dev's ufw is default-deny and
port 9010 was never allowed, so gitea's webhook deliveries timed out (DROP).
v0.3.6 was a manual deploy; v0.3.7-v0.3.13 never auto-deployed. The setup-time
'test-delivery 204' was gitea queuing, not the listener receiving. Fixed by
'ufw allow from 10.0.0.0/8' (operator-directed). Confirmed end-to-end.
2026-07-14 08:29:28 -07:00
vh f960a73a79 feat(char-rp-gguf): swap reasoning seat Deckard-PKD → NEO-CODE (Heretic2-Thinking Qwen3.6-27B)
R36 gate (2026-07-14) validated NEO-CODE ships on all axes: tool-calling 0.967
(attach_tool 1.00, 0 runaways — #355 eliminated), prose genre-artifact-fine
(less clichéd than gen), refusal uncensored-as-spec + CSAM-clean.

#355 root cause was MODEL-level, not the reasoning-budget-forcing bug: Deckard
emitted Qwen's native qwen3_coder XML tool format malformed -> llama.cpp leaked
the closing tags into the arg value -> Bifrost attach_tool schema error -> retry
-> reasoning runaway to max_tokens. NEO-CODE emits the same native format cleanly
on the same seat/parser -> no schema error -> no runaway. The fix was the model
swap; there was never a wrong parser (the XML is Qwen3.5/3.6-native).

- reasoning seat: Deckard-PKD (Qwen3.5) -> NEO-CODE=Heretic2-Thinking (Qwen3.6-27B) Q5
- samplers: card defaults (temp 1.0 / top_p 0.95 / top_k 20 / min_p 0.0), DRY dropped
- ctx: 256K max; custom llama.cpp kept (qwen3_coder parse + PR#25544 belt-and-suspenders)
- persistent-memory ACTIVE 1 marked resolved
2026-07-13 22:21:10 -07:00