Commit Graph
521 Commits
Author SHA1 Message Date
Frank 949f68e2b5 frankbook-pro: *arr stack + qbittorrent quadlets inside podman machine
Seven units installed INSIDE the Mac VM (/home/core/.config/containers/
systemd) by a new deploy_frankbook_stack handler: gluetun (ProtonVPN
WireGuard, env-file credentials, publishes qbit's 8080/6881), qbittorrent
(Network=gluetun.container, verbatim /Volumes data roots, first-boot
config seed with fresh machine-local WebUI password and the Finished
Torrents category), and prowlarr/sonarr/radarr/lidarr/readarr (grab-only,
config migrated from dankserver at provisioning, readarr pinned to
amd64-1.0.980). deploy.sh routes the new target through the ssh-config
alias with REMOTE_SHELL=/usr/local/bin/bash (macOS bash 3.2 lacks
associative arrays); the planner learns FRANKBOOK_SERVICES and the
gluetun->qbittorrent netns pairing; new seam test pins the contract.
2026-09-01 14:10:23 -07:00
Frank 4d5bea42e0 frank-default-small: revert to Huihui FP8 — FreeToken v0.1.2 cannot load compressed-tensors FP8
Two live-verified loader failures on Dankserver (2026-09-01), each a
clean exit at load (no swap-thrash, 37 GB fits RAM):

1. ornith-ai/Ornith-1.5-35B-A3B-FP8 (compressed-tensors PER-CHANNEL fp8):
   ValueError: Missing MoE expert source layers: {'gate_up': [0, 1, ...]}
   — nonstandard expert tensor naming, provider finds no expert sources.

2. lamianlbe/Qwen3.6-35B-A3B-Uncensored-HauhauCS-Aggressive-fp8
   (compressed-tensors BLOCK-fp8 128x128, standard per-expert naming):
   RuntimeError: The size of tensor a (2048) must match the size of
   tensor b (...) in _dequant_fp8_weight — the dequant path multiplies
   weight * weight_scale directly and cannot expand compressed-tensors
   block scales.

Empirical matrix for FreeToken v0.1.2 on qwen3_5_moe (RTX 3090):
  modelopt block-fp8 (quant_method 'fp8' + weight_scale_inv)  -> LOADS
  compressed-tensors per-channel FP8                          -> fails
  compressed-tensors block-fp8 128x128                        -> fails

batsclamp/Huihui-...-abliterated-FP8 is the proven uncensored checkpoint;
restoring it until a modelopt/NVFP4 requant of a wanted model exists or
FreeToken learns compressed-tensors.
2026-09-01 14:02:27 -07:00
Frank 272ef6f0b0 docs: record quadlet standardization of dankserver media + dankclaw data roots
Phase 1/2 of the podman standardization plan: service pages updated to the
quadlet reality (units, Containers data roots, env-file secret convention,
the v1-generator findings each caught live), Storage Policy documents the
two rootless ownership regimes and the merge-move migration, Deployment
Flow's service-manager table no longer claims dankserver media is bare
inventory-only. Bundle change log entry added.
2026-09-01 13:57:33 -07:00
Frank 34ab6b4d0c frank-default-small: retarget to lamianlbe/Qwen3.6-35B-A3B-Uncensored-HauhauCS-Aggressive-fp8
Ornith-1.5-35B-A3B-FP8 failed to load on FreeToken v0.1.2: its
compressed-tensors checkpoint uses a nonstandard expert tensor layout
(FreeToken: 'Missing MoE expert source layers: gate_up').  Retarget to
the HauhauCS Aggressive FP8 finetune of the SAME Qwen3.6-35B-A3B arch
Huihui used, which carries compressed-tensors BLOCK-fp8 (128x128) with
the standard per-expert naming (mlp.experts.N.gate_proj/up_proj/down_proj
+ .weight_scale) that FreeToken's MoE loader reads.

- MODEL_DIR -> /home/dank/models/hauhaucs-qwen36-35b-a3b-aggressive-fp8
- use the checkpoint's own chat_template.jinja (drop the Sharp override;
  forcing a template the finetune wasn't trained on risks format drift)
- pool plan unchanged (same ~35 GB FP8 mass / qwen3_5_moe arch)
2026-09-01 13:56:22 -07:00
Frank a14a70a404 dankserver: copyparty PublishPort=3923 + seam pinning host-served ports
The cutover unit joined dankserver_appnet but dropped the compose-era
0.0.0.0:3923 mapping (live inspect: bridge, 3923 published), so
copyparty listened inside the netns while the host refused. New seam
asserts every host-facing port matches the pre-cutover PortBindings:
romm 8085->8080, jellyfin 8096, calibre-web 8083, copyparty 3923.
2026-09-01 13:53:10 -07:00
Frank 06de2b4cbf dankserver: jellyfin GPU device via AddDevice=, seam guard for Device=
The podman 5.x v1 quadlet generator rejected the whole jellyfin unit on
the unsupported Device= key (generator log: unsupported key 'Device' in
group 'Container'), so no jellyfin.service was generated and the cutover
restart failed with 'Unit not found' after the data root had already
migrated cleanly. gluetun proves AddDevice= is the house key. New seam
test denies Device= across all six dankserver units and pins the
AddDevice=/dev/dri replacement.
2026-09-01 13:49:45 -07:00
Frank 26b0d4c357 deploy-remote: privileged rename + deep merge in migrate_data_root
rename() of a directory requires write on the directory itself; mariadb/
redis data roots are owned by the containers' mapped subuids (100998),
so the deploy user cannot move them. Use run_privileged mv (numeric
ownership preserved = rootless mapping contract) and skip the chown pass
for romm via the new keep mode — chowning mapped subuid data to the
deploy uid breaks the in-container mysql/redis users. Collisions with
rescued anonymous-volume stubs now merge one level deep instead of
stranding real data under /opt. Reverse the podman rm order so the
dependent romm container is removed before its backends.
2026-09-01 13:42:31 -07:00
Frank a18bb62d30 deploy-remote: ensure quadlet unit dir exists for all handlers
dankserver's ~/.config/containers/systemd did not exist (no quadlet units
had ever been installed there); the dankserver media handlers cp'd into it
without mkdir -p, failing before touching any container.
2026-09-01 13:40:17 -07:00
Frank af6cd72d02 frank-default-small: swap to ornith-ai/Ornith-1.5-35B-A3B-FP8 + Qwen-Sharp chat template
- MODEL_DIR -> /home/dank/models/ornith-1.5-35b-a3b-fp8 (37 GB,
  compressed-tensors per-channel FP8, same qwen3_5_moe arch/mass as
  Huihui so the pool plan carries unchanged)
- CHAT_TEMPLATE_FILE -> scripts/chat-template.jinja (Qwen-Sharp, shared
  with frank-default-large); the checkpoint's stock template
  mis-serializes reasoning per its own model card
- env/serve/unit headers updated; loader-risk + BF16-does-not-fit note
2026-09-01 13:40:12 -07:00
Frank cdfaf48191 deploy-remote: migrate_data_root merges into pre-seeded destinations
mv of a data root onto a non-empty directory fails (Directory not empty).
The romm/copyparty cutover creates Containers/<svc>/ before migrating:
the seed env file lands there first, and the romm anonymous-volume rescue
extracts into it before the /opt move. Merge the old root's entries in
without overwriting existing state (mv -n), warn and leave residue if a
collision kept the new side, and keep the plain rename when the
destination is absent or empty.
2026-09-01 13:38:31 -07:00
Frank 9e904d23a3 deploy-remote: daemon-reload after copying hermes units, before restarts
The first deploy after a unit-file edit restarted with the stale generated
unit (generator had not seen the new Volume= paths), crash-looping hermes on
statfs ENOENT for the just-renamed data root. Reload between cp and restart.
2026-09-01 05:16:27 -07:00
Frank e570d92bb9 dankclaw: standardize gitea/authentik/hermes data roots under /home/dank/Containers
Repoint Volume=/EnvironmentFile= in the 8 affected quadlet units to the
caddy-established Containers/<svc> layout: gitea (data, postgres, env),
authentik (data, postgres), hermes (data, webui checkout). Data-root mv on the
target happens at deploy time before each group's unit restart; same-fs rename,
instantly reversible. Running containers keep their inode-bound binds until the
unit restart flips them to the new path.
2026-09-01 04:57:41 -07:00
Frank b206f477ad dankserver: quadlet units + deploy handlers for romm trio, jellyfin, calibre-web, copyparty
Cutover of the six surviving dankserver services from compose-era bare
containers to boot-persistent Quadlet units (WantedBy=default.target; podman
5.x v1 generator honors it at user-manager start).

Units are faithful to live inspect ground truth (image pins = running tags,
not compose inventory):
- romm trio shares one data root: /home/dank/Containers/romm mounted whole at
  /romm; mariadb datadir and redis data dir live inside it. Aliases mariadb/
  redis preserved on dankserver_appnet via Network=...:alias=. Secrets stay in
  the host-local env file (EnvironmentFile + ${VAR} expansion in the generated
  ExecStart, gitea precedent). copyparty passes its admin account via
  Exec=-a ${COPAY_ACCOUNT}:${COPAY_PASSWORD} (Exec= not Command=: the v1
  generator hard-fails on Command=); entropy stays rw only there.
- jellyfin keeps every creation-time env as Environment= lines (zero drift);
  Device=/dev/dri + GroupAdd=keep-groups preserve hardware transcoding.
- calibre-web pins the exact running image tag (id 986277563e76 =
  0.6.27-ls397), pasta network preserved.

Deployer: first-cutover handlers retire the old container, rescue unshadowed
anonymous-volume content (podman volume export + tar --skip-old-files), mv
data roots on the same fs, then start units in dependency order with health
gates. Re-deploys restart only the selected unit. deploy-plan.py maps compose
keys mariadb/redis to the new unit names; allowlists updated. New seam test
tests/dankserver_quadlet.bats pins boot-persistence + v1-generator contract;
test-changed.sh maps the new dirs to it. Full suite green (209 tests).
2026-09-01 04:14:08 -07:00
Frank 11638442e7 Revert frank-default-small to Huihui FP8: Thomson-1.0-Small is BF16 ~66GB, exceeds Dankserver 62GB RAM (thrash/OOM); needs a quantized checkpoint 2026-09-01 02:53:20 -07:00
Frank 415f64964a frank-default-small: swap Huihui FP8 for thomsonreuters/Thomson-1.0-Small 2026-09-01 02:11:35 -07:00
Frank bb5508b2ec docs: frank-default-sightsound runbook — model swap + tag switching 2026-09-01 01:53:59 -07:00
Frank 1401bd42d4 NPU: swap gemma4-it:e4b for qwen3.8-distilled-heretic:9b 2026-09-01 01:51:44 -07:00
Frank 5ba32ccecd Add FLM gemma4-it:e4b model to Hermes config
- Add dankclaw-npu provider with gemma4-it:e4b model at port 7771
- Wire auxiliary vision routing to FLM (sight+sound NPU model)
2026-08-31 17:10:24 -07:00
Frank 8e1b00646f copyparty: read-only volume (no uploads); correct runbook anon-perms claim
-v /w::A granted anonymous full rwmda on the LAN (verified: anon PUT -> 201,
PROPFIND -> 207). New perms ::r:ra,dank: browse/download for anonymous
(required by the guarded files.franksdank.cloud chain), admin for dank,
no w/m/d for anyone. Runbook corrected with the --help-accounts semantics.
2026-08-31 16:37:38 -07:00
Frank 207235420c hermes: CDP browser daemon + MCP client wiring for the agent
Adds a digest-pinned headless-shell Chrome DevTools Protocol daemon as a
boot-persistent quadlet unit (chrome-devtools-protocol.container). The
entrypoint override drops the image's socat front so the CDP endpoint binds
loopback-only on 127.0.0.1:9222 in the host network namespace; only the two
host-network consumers (Signal gateway, webui server) can drive it.

hermes-webui flips Network=dankclaw_default -> Network=host so its agent
process shares the daemon's namespace (0.0.0.0:8787 bind is LAN-facing as
before; no exposure change). deploy_hermes installs the new unit and starts
it if inactive without restarting in-flight browser sessions.
2026-08-31 16:25:28 -07:00
Frank f1dd586fbb refactor(caddy): retire decommissioned vhosts, rename chat->ai and jellyfin->jelly
DNS at Porkbun was renamed (chat->ai, jellyfin->jelly) and the qbittorrent,
*arr-stack, comfyui, hermes, dankclaw, and dankserver public records were
deleted. This brings the Caddy config in lockstep: ai/jelly vhosts now match
the new names; comfyui (guarded), hermes (guarded), and the *arr/qb vhosts
are removed as their DNS is gone. The legacy dankclaw/dankserver redirect
vhosts stay: Pi-hole still answers those names on the LAN.
2026-08-31 14:42:10 -07:00
Frank 44438979b3 feat(hermes-webui): publish webui on LAN interface instead of loopback
LAN clients now connect directly to 192.168.0.143:8787 (password-gated via
HERMES_WEBUI_PASSWORD); the SSH tunnel via port 22 remains the sole
off-network ingress. Recreation also re-reads the rotated password from
dankclaw/.env via the [Container] EnvironmentFile.
2026-08-31 13:13:07 -07:00
Frank ba0345ae7a docs(searxng): record verified agent-API contract under the Anubis guard
Verified live 2026-08-31: guarded path serves the Anubis JS challenge at
HTTP 200 to non-browser API clients (status-only consumers silently get
HTML); direct published port 8081 from pass_ip sources returns real JSON.
Decision: no second agent-only instance — same engines and same
rate-sensitive VPN exit IP would see double request volume for zero gain.
2026-08-31 06:49:35 -07:00
Frank c527f35bd4 docs(hermes): persistent SSH-tunnel ingress design for Hermex (tunnel user + restricted key options)
Server-side implementation landed on Dankclaw: dedicated 'tunnel' account
(nologin shell, password-locked, key-only auth), sshd drop-in
99-tunnel.conf scoping AllowTcpForwarding to that user with PermitTTY off,
and permitopen="localhost:8787" key-option guidance so a leaked tunnel key
can only forward to the webui port. WebUI stays loopback-only published.
2026-08-31 06:23:13 -07:00
Frank 9d678122d7 docs: grafana OAuth2-RP contract + authentik fork quirks (live-verified 2026-08-31)
Token exchange chain verified end-to-end in-process on the live provider
(pk 9): authorize -> ORM-minted code -> form-encoded token exchange with
Basic client auth -> userinfo. Key findings documented:
- Application row + grant_types must exist before authorize can complete
- token endpoint consumes form-encoded bodies only (JSON body => no
  grant_type parsed -> unsupported_grant_type); client auth is Basic-only
- PropertyMappingEvaluator.evaluate(*args,**kwargs) forwards kwargs to
  BaseEvaluator.evaluate(expression_source), so context kwargs become the
  expression source and every evaluation raises a swallowed exception;
  userinfo therefore answers sub-only claims for every provider in this
  fork. Scope granting filter (provider= M2M descriptor) is always empty.
- Grafana identity = sub hash until the evaluator bug is fixed upstream.
2026-08-31 06:06:57 -07:00
Frank 3d64f2ca99 grafana: switch auth_proxy -> OAuth2 relying-party against authentik
The embedded outpost carries no provider token (token=None), so the
auth_proxy identity header was never set and no user could log in. RP
mode is topology-independent: challenge gate stays in front, login runs
inside Grafana via the OAuth2 code flow against auth.franksdank.cloud.

Provider 'grafana' (pk 9, confidential) created via ak shell; secret
written straight into the live .env (never in git). Auth URL uses the
global /application/o/authorize/ path — this fork resolves the provider
by client_id query param; per-slug authorize does not exist.
Caddyfile comment corrected: no identity header is forwarded to Grafana.
2026-08-31 03:32:53 -07:00
Frank ec03929d95 grafana: auth_proxy behind the Authentik guard chain
Grafana leaves the exempt-by-construction set: grafana.franksdank.cloud
now terminates at the Anubis guard (anubis:8923) and authenticated
traffic returns at the internal :8017 listener, where an @grafana Host
handler proxies through to grafana:3000 with the outpost-proxy trust
token (GRAFANA_PROXY_TOKEN = client_id_client_secret of the new
'grafana-proxy' ProxyProvider on the embedded outpost; created via
ak shell before this route flip — provider-first ordering per the
External Exposure Policy).

The Grafana admin account is intentionally kept: auth.proxy in
auto-upsert mode only creates non-admin users, so the local admin
remains the only way to administer Grafana. The old edge-basicauth
wrapper is retired (shared family password, no per-user audit trail).

- Caddyfile: grafana vhost flipped to the guarded chain; @grafana
  handler added at the :8017 return listener.
- compose.yaml: GF_AUTH_PROXY_ENABLED/HEADERS/TOKEN on the grafana
  service (auth_proxy trusted-proxy CIDRs left at the image default —
  the proxying Caddy container is not statically addressable on
  10.89.0.0/24, so Grafana trusts any in-network source and relies on
  the token as the capability).
- .env.example: GRAFANA_PROXY_TOKEN placeholder so test env_consistency
  keeps guarding the compose<->env contract.
2026-08-31 01:48:30 -07:00
Frank c6d404ffde AGENTS.md: External Exposure Policy (MANDATORY); comfyui_rocm seam retargeted
Every Caddy-proxied service is now either behind the auth chain or
explicitly internal-only, with the provider-first flip procedure codified.
The comfyui GPU-access seam test now asserts the deployed contract
(group_add keep-groups + udev MODE 0666 on kfd/renderD*) instead of the
pre-fix 'video' group assumption.
2026-08-30 23:26:18 -07:00
Frank a382a3b883 caddy: put loki.franksdank.cloud behind the Anubis+Authentik guard chain
Loki's public vhost had zero auth — any host that can resolve DNS could
query all logs via LogQL. The vhost now terminates at anubis:8923 and
authenticated traffic returns at the internal :8017 listener, where a new
@loki host handler routes to loki:3100. The outpost proxy provider
'loki-proxy' (external_host https://loki.franksdank.cloud/, internal_host
http://caddy:8017) was created before this deploy — provider-first
ordering so authenticated traffic never hits the outpost error page.
Ingestion is unaffected: Alloy pushes to loki:3100 on the compose network.
2026-08-30 23:26:16 -07:00
Frank 246ba7737c caddy: strip stray colon prefix from comfyui guard comment
The flip hunk's first comment line was written with a literal ':' prefix
(edit-tool auto-prefix artifact). Caddyfile parses ':# ...' as a matcher token,
which made the following site block an unrecognized directive and failed
config validation — that is why the earlier deploy validated, failed, and
skipped the reload, leaving the live config pre-flip (comfyui still direct).
2026-08-30 19:06:36 -07:00
Frank 055fafc233 udev: match kfd by name only — misc-class devices have no udev subsystem
The first revision guarded the kfd line with SUBSYSTEM=="misc", which never
matches (misc-class devices carry no subsystem for udev matching), so the rule
was read but never fired and /dev/kfd stayed 0660 root:render. Name-only match
applies 0666 on creation and on trigger.

Also fixes test-changed.sh to exit 0 when changed paths map to zero tests
(udev rules are mapped-but-untestable) instead of invoking bats with an empty
selection.
2026-08-30 18:37:33 -07:00
Frank 28eb7531e5 udev: world-writable compute nodes for spawn-independent GPU access
The comfyui container is spawned by a systemd user unit whose spawn context
carries no supplementary groups, so render-group access to /dev/kfd and
renderD128 was structurally unreachable (keep-groups preserved an empty set;
named group_add 'render' fails name lookup inside the userns). World-mode on
the compute nodes is the only spawn-context-independent grant; display cards
keep their modes. Apply: install to /etc/udev/rules.d, udevadm control
--reload-rules, then trigger by subsystem to re-apply modes to live nodes.

Also maps dankclaw/udev/* in the focused-test selector (not bats-testable).
2026-08-30 18:30:34 -07:00
Frank fc4c521fb4 comfyui: use keep-groups instead of a named render group
Rootless podman cannot resolve the literal group name 'render' inside the
container user namespace and fails the start with 'unable to find group
render'. keep-groups preserves the launching user's real supplementary
groups (dank is in render on this host), which is the canonical rootless
ROCm device-access recipe.
2026-08-30 18:13:53 -07:00
Frank 14d99a8a17 comfyui: grant the render group so ROCm can open /dev/kfd
/dev/kfd and /dev/dri/renderD128 are root:render 0660 on this host. The
container passed the device nodes but only joined group video(44), so torch's
HIP init failed with 'No HIP GPUs are available' and main.py never bound
:8188 — every proxy hop to the app returned 502. Group membership is a
create-time property, so this deploy recreates the container.
2026-08-30 18:12:00 -07:00
Frank 5f4377276e caddy: move ComfyUI behind the Anubis + Authentik guard chain
comfyui.franksdank.cloud was exempt (direct reverse_proxy to comfyui:8188).
The comfyui-proxy proxy provider was created on the embedded outpost first
(internal_host http://caddy:8017, flows copied from hermes-proxy), then the
vhost flips onto the guard chain and authenticated traffic routes back via a
@comfy host match. ComfyUI has no auth of its own; this closes the last
unguarded admin surface on the internal hosts.
2026-08-30 17:35:49 -07:00
Frank 75e7217f4d authentik: fix mangled pg_isready health probe
The quadlet generator space-splits HealthCmd into the healthcheck argv, so the
quoted /bin/sh -c form arrived mangled and failed with exit 1 forever (FailingStreak
569) while the DB itself accepted connections. Bare argv survives both exec forms.
2026-08-30 17:35:47 -07:00
Frank 9ef034e5e6 sightsound: move FLM NPU endpoint port 52626 -> 7771
Env file is the source of truth (unit ExecStart runs the serve script which
sources it); serve-script default and the deployer health-gate URL flipped in
lockstep so the post-restart health gate polls the new port. Docs, fleet table,
and both index bullets updated to match.
2026-08-30 14:06:54 -07:00
Frank 9b9f0f9051 docs(sightsound): correct unknown-model-tag contract to live-probed behavior
Prior docs claimed unknown tags silently serve llama3.2:1b. Live probes on the
live endpoint disprove it: /v1/chat/completions answers HTTP 200 with a flat
{"error":"Failed to load <tag> model!"} body and no choices; /v1/completions
answers a nested OpenAI-shaped server_error (code 500) under HTTP 200. Valid
tags route per-request to the named model (response echoes the requested tag);
no restart needed to switch between registry tags. Corrected in the runbook,
the AGENTS.md runtime section, the serve-script header comment, and the
historical FastFlowLM incident note.
2026-08-30 11:41:15 -07:00
Frank 150412bbca docs(sightsound): NPU sight+sound runbook, fleet table, IOMMU/SVA root cause
frank-default-sightsound (FLM v1.0.1, XDNA2 NPU, port 52626) is live on
Dankclaw. Documents the first-deploy crash-loop root cause: iommu=off on the
kernel cmdline breaks the XDNA2 SVA bind (amdxdna_drm_open ret -19), so every
/dev/accel/accel0 open fails with ENODEV; fixed with iommu=pt + reboot.
Whole-registry single-port serving with per-request routing by exact FLM tag;
unknown tags fall back to llama3.2:1b (no 404). Health = GET /v1/version.
Vision + audio towers proven live (image_url color probe; audio control-pair
token-count probe). Updates AGENTS.md fleet table + runtime section, both
index pages, and the change log.
2026-08-30 09:05:22 -07:00
Frank 443adb04a7 hermes: drop the stale NetworkMode key from the gateway unit
The v1 quadlet generator skips the whole unit when [Container] holds an
unsupported key; the stale key was a leftover of a draft edit. Network=host is
the only host-networking key this generator version accepts.
2026-08-30 09:00:14 -07:00
Frank 39f0712746 hermes: Network= is the quadlet v1 key; NetworkMode= is not
The v1 generator on this host skips a unit whose [Container] section holds an
unknown key, so the deploy-time regeneration dropped hermes.service entirely
while the container kept running unmanaged. Network=host generates
--network host verbatim (v1 passes extension-less values through).
2026-08-30 08:39:53 -07:00
Frank e062fdfeff hermes: gateway dials the signal-cli daemon over loopback on host networking
The gateway unit ran on dankclaw_default and could not reach the host
daemon: from that network only DNAT'd published ports accept connections to
the LAN address. The compose era ran the gateway with network_mode: host, so
the daemon was reachable; the unit silently changed topology at takeover and
broke the adapter. Host networking + a loopback dial removes the dependency
entirely — the gateway is an outbound-only client and publishes nothing.
2026-08-30 07:42:07 -07:00
Frank 915d49d663 hermes: boot-persistent quadlet units for the gateway, dashboard, and webui
The trio ran as bare compose containers and died silently at the Aug 26
reboot — nothing restarts compose containers at boot. Each now has a
boot-persistent unit (WantedBy=default.target; the v1 quadlet generator on
this host cannot enable generated units). The deploy handler retires the
compose-era containers only while the units are not yet active, then
(re)starts each unit.

Units run the image under a localhost/hermes-agent:latest alias tag (the
quadlet create path on this host cannot resolve registry-prefixed refs from
local storage); the deploy handler tags first. The gateway's :8090 publish
is dropped — nothing consumes it; the public vhost now routes to the
dashboard's login-gated UI on 9119.
2026-08-30 07:22:20 -07:00
Frank 56763e014e fix(hermes): point the signal adapter at the verified alias path and route hermes.franksdank.cloud to the dashboard
The gateway's SIGNAL_HTTP_URL pointed at the host LAN IP. From container
space on netavark networks only DNAT'd published ports accept connections
to that address; :8080 has no forward, so every connection was refused
and the Signal adapter stayed disconnected since the Aug 26 reboot.
host.containers.internal is the verified working path (probed live from a
probe container on dankclaw_default).

The public hostname also routed to hermes:8090, which serves nothing —
the gateway has no HTTP listener. It now routes to the dashboard's login-
gated admin UI on :9119, behind the existing Anubis+Authentik guard.
2026-08-30 04:43:15 -07:00
Frank cf0c541cc9 deploy-remote: allow frank-default-sightsound on the dankclaw target
The first deploy attempt pulled c3ed3a6 on the target but the remote runner
rejected the explicit --service selection because service_is_allowed() keeps
its own per-target allowlist; add the new LLM service to it.
2026-08-30 04:40:57 -07:00
Frank c3ed3a6e12 sightsound: new FLM NPU sight+sound service on XDNA2 (gemma4-it:e4b)
New Dankclaw service frank-default-sightsound: FLM 1.0.1 serving the
Gemma4-E4B-IT-NPU2 pack (vision+audio+reasoning, 131072 ctx) on the XDNA2
NPU at port 52626. Model choice rationale: gemma4-it is the only NPU2 model
family with BOTH image and audio towers; the uncensored candidate qwythos:9b
is text-only, so sight+sound wins over uncensored here.

Deployer wiring: planner maps env/unit/serve files to the new service name;
deploy-remote gains deploy_llm_sightsound (relink + daemon-reload + enable +
restart + health gate on /v1/version — FLM has no /health route). Unlike the
retired frank-default-npu relink-only path, this unit is boot-enabled.
2026-08-30 04:37:42 -07:00
Frank 0937cfb047 docs: record fleet double swap (large -> kingjones STRIX on pinned fork, small -> Huihui FP8 on FreeToken)
- kingjones-strix-rocmfp4 reactivated as the ACTIVE large runbook:
  runtime build recipe (WEBUI=OFF gotcha), deployed serving profile,
  fa-on-works-unpatched evidence, MTP heads documented unloadable,
  swap procedure + 2026-08-30 validation record
- agentionai-fast-imatrix marked RETIRED (rollback record kept)
- freetoken-frank-default-small: model/lineage/template sections now
  Huihui abliterated FP8; new operational quirk: chat API 422 without
  explicit model field
- LLM index + AGENTS fleet table/runtime sections current; both
  services' history chains fixed (small was still Tiel in AGENTS.md)
- worklog entry added; models.json contextWindow for large corrected
  to the real per-slot 131072 (llama clamps n_ctx_train/parallel)
2026-08-30 02:35:38 -07:00
Frank aa9c1d065a frank-default-small: swap to batsclamp Huihui-Qwen3.6-35B-A3B-abliterated-FP8 on FreeToken
- same qwen3_5_moe arch and native block-fp8 format (e4m3, 128x128
  weight_block_size, un-fused per-expert layout) as the official
  Qwen FP8 checkpoint: identical FreeToken loader path, pool numbers
  unchanged (2048 MoE slots / 453005 KV tokens / 4 requests)
- checkpoint downloaded to /home/dank/models/huihui-qwen36-35b-a3b-abliterated-fp8
  (26 shards, ~35G); official checkpoint kept for rollback
- ships froggeric fixed Qwen3.6 chat template, read from checkpoint
- also refresh both .service Descriptions (large still said STRIX_LEAN)
2026-08-30 02:26:49 -07:00
Frank 3066d810ee frank-default-large: swap to kingjones STRIX model on card-pinned kingjones30/ROCmFPX runtime
- runtime: charlie build-qwen38 -> kingjones30/ROCmFPX (card recipe
  build, LLAMA_BUILD_WEBUI=OFF since npm/HF-bucket provisioning fails;
  all 35 of our serving flags verified present in the tree)
- model: agentionai FAST imatrix -> kingjones777 STRIX single GGUF
  (on-host copy sha256 == HF LFS oid c6770d74...49fa verified)
- args unchanged from our validated profile (401408x2, b4096/ub512,
  t16/tb16, f16 KV, fa on, fit off); mmap stays default per card
  (PLE streams via page cache; --no-mmap = silent cgroup OOM)
2026-08-30 02:05:03 -07:00
Frank f69efcdde6 fix serve script: restore : (not ::) for default-value assignments
The edit tool mangled : to :: on 4 lines. Bash requires : for default
value assignment (:: is not a valid command). Fixes exit code 127.
2026-08-30 01:34:21 -07:00