DeepReinforce Ornith-1.0 (dense 9B on Qwen 3.5, Q5_K_M, MIT), an
agentic-coding model. Tool-calls + <think> work under --jinja; native
256k so no YaRN. Loads at ~7.7GB VRAM @ 64k.
Benchmark (docs/2026-06-27-ornith-9b-benchmark.md): quality ties
gpt-oss-20b but gen is ~2.5-3x slower (dense 9B active vs gpt-oss MoE
3.6B active on the compute-bound P100). Default stays gpt-oss-20b;
ornith kept as a coding specialist in the menu.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add hermes-motif (skill discovery; complementary to curator, not a rival),
hermes-web-search-plus (mature multi-provider search, pairs with camofox),
optional llmtrim/rtk context efficiency, and the claude/codex/cursor/antigravity
delegation fabric. Record that Claude Code + Codex are now installed on valhalla.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
UI: trial hermes-ui + hermes-workspace in parallel, keep winner (new Task 9).
Curator stays report-only. eagle-eye trial confirmed (only direct skill-router
in the ecosystem; llmtrim noted as complementary). camofox minimal 2-tool skill.
All phases now ungated.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Research + fit analysis for hermes-agent-acp-skill, hermes-curator-evolver,
eagle-eye, camofox-browser, hermes-ui, hermes-workspace, mission-control.
Phased rollout; open decisions flagged for review.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Portainer's git checkout auto-creates a relative repo-file bind as a directory,
breaking the /app/config.yaml mount. Use the absolute host path like the share
stack; repo copy stays canonical, mirrored to /config/llm on deploy.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Replace single llama-server with llama-swap so all benchmarked models are
selectable from Hermes' menu and hot-swapped on the one P100. Menu: gpt-oss-20b
(default, ~45s cold start), gemma-4-26b-a4b (MoE), gemma-4-12b, gemma-4-e4b.
qwen3-30b-a3b excluded (OOMs at 64k in 16GB). All 64k, q8/q8 KV, --parallel 1.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The q4_0 V-cache + flash-attention path is pathological on the GP100: 1.28
tok/s generation at 5-8% GPU util. q8_0 V-cache gives 9.2 tok/s and still fits
64k context in 16GB (15.3GB used, ~950MB free).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
llama-server caps the slot to the GGUF training context (32768) and ignores the
YaRN-extended size, leaving per-seq context at 32k. Raise qwen2.context_length
metadata to 65536 so the full window is served per request.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
With the default 4 slots, llama-server splits ctx into 32k per sequence, which
fails Hermes' 64K minimum. One slot serves the full 65536 per request (serial
agent use; concurrent calls queue).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Hermes Agent rejects models with <64K context. Qwen2.5-14B is 32k native, so
enable YaRN rope-scaling (2x → 65536) and drop the V-cache to q4_0 for VRAM
headroom on the 16GB P100.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The server-cuda image parses -fa as --flash-attn [on|off|auto], so a bare -fa
swallowed the following --cache-type-k as its value and crash-looped.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
New stacks/llm/ serves Qwen2.5-14B-Instruct (Q4_K_M GGUF) via llama.cpp's
OpenAI-compatible server on the Tesla P100 (CDI nvidia.com/gpu=0), published on
172.20.0.1:8090 for the host-side Hermes agent. vLLM was rejected: the P100
(cc 6.0) lacks the DP4A INT8 instructions its AWQ/GPTQ kernels need.
Includes design spec and implementation plan under docs/superpowers/.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
SameSite=Strict caused Safari and Firefox to drop the freshly-set cookie on
the immediate same-site redirect when the top-level navigation originated
from an external app (Discord). SameSite=Lax explicitly permits the cookie
on same-site redirects regardless of the initiating context.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
{env.SHARE_KEY} is not resolved by Caddy's query matcher or CEL expression at
request time — the literal placeholder string was compared against the URL key,
causing every external request to fall through to 403. {$SHARE_KEY} is
substituted by the Caddyfile adapter at reload/start, baking the literal key
value into the compiled config.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
sonarr/radarr/prowlarr/whisparr/bazarr were hitting the default Docker
nofile limit of 1024, causing EMFILE errors and excessive virtiofsd FD
churn on the /storage1 virtiofs mount.
Capability-URL snippet: external users visit ?k=SHARE_KEY once, Caddy
sets a 30-day HttpOnly cookie and redirects to the clean path. Subsequent
visits check the cookie only. Internal IPs and tailnet pass through
unconditionally. Applied to roms.ginnoir.com and romhacks.ginnoir.com.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The previous commit used `hbbs -R 192.168.1.69` (uppercase -R sets
rendezvous/cluster servers), so hbbs advertised an empty relay list and
clients failed with "failed to connect to relay server". Lowercase -r is
the relay-server flag; hbbs now advertises 192.168.1.69 and LAN clients
relay correctly.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The save-sync (/api/sync/*) and raw content_hash fixes that forced the
beta pin shipped in stable 4.9.x (now 4.9.2). Return to the watchtower-
tracked :4 tag per the original design.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
R510 -> R730XD/Proxmox migration helpers (consistent DB dumps, B2/Kopia snapshot refresh, cutover final backup) plus the previously-untracked gitea-portainer-registry cutover plan under docs/.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
grant_types must be set explicitly ([] = all auth rejected). Scope PKs
were truncated placeholders — replaced with actual UUIDs from this
Authentik instance. Signing key was already correct.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Switch files.ginnoir.com from ownCloud to Nextcloud (internal-only).
Fix Authentik scope PKs in CLAUDE.md — the last UUID segments were
wrong and would have caused provider creation failures.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replaces ownCloud with Nextcloud (postgres + redis) and adds OnlyOffice
Document Server for Google Docs-style editing. Migration is staged:
nextcloud.ginnoir.com for testing, files.ginnoir.com still points at
ownCloud until cutover is verified.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Pattern A (native OAuth2) is preferred — create provider + app in
Authentik, configure service with discovery URL. Pattern B (Caddy
forward_auth) is the fallback for services with no native auth.
Reusable Authentik flow/scope PKs pinned so they don't need re-deriving.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
New services: all in except TB-020 Mealie (deferred to famapp).
Active interest: TB-015 Vault, TB-027 Jellyfin, TB-028 HA, TB-031 Pingvin.
Dropped: TB-017 MinIO consolidation, TB-018 Plane, TB-029 Firefly III,
TB-030 AdGuard (handled at router), TB-032 Wiki.js (using BookStack).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Image moved from ghcr.io/jorenn92/maintainerr to ghcr.io/maintainerr/maintainerr
with the v3.x release series. v3 runs its own DB migrations on startup.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace sctx/overseerr:latest with ghcr.io/seerr-team/seerr:latest.
Same port (5055), same config volume (/config/overseerr:/app/config) —
Seerr auto-migrates the DB on first boot. Add init: true as required.
Rename container overseerr → seerr; update Caddy upstream to match.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Mount /config/maintainerr to /opt/data (actual DB location, not /opt/maintainerr/data)
- Add NODE_TLS_REJECT_UNAUTHORIZED=0 so Node.js accepts Plex's self-signed cert
- Mark TB-007/008/009/012/013/016 tasks as done/dropped in improvement plan
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Switch CLAUDE.md and AGENTS.md to Gitea-primary language. Remove
github-runner from the management plane now that Gitea Actions handles
Caddy reloads and famapp builds. Disable GitHub deploy workflow.
Update apply-compose.ps1 status text.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Switch famapp container from ghcr.io/ginnoir/famapp:latest to
registry.ginnoir.com/ginnoir/famapp:latest.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Portainer go-git resolves gitea.ginnoir.com inside Docker. Alias was on
the gitea container → port 443 refused. Moved alias to Caddy so go-git
reaches Caddy:443 (TLS ok) → proxies to gitea:3000.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Intermediate step on the way to 2026.5.2 — Authentik requires passing
through the latest 2025 release before jumping to 2026.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
TB-006 forward_auth blocks machine clients with HTML/302; route /api on *arr
sites and /api plus socket.io on uptime (LAN/tailnet only) before forward_auth.
Also add Cursor interview-first rule and small Authentik/FreshRSS debug helpers.
Adds a named matcher @plane_api that matches /api/* requests carrying
X-API-Key, routing them directly to plane_api:8000 without hitting the
Authentik outpost. Browser/UI sessions still go through forward_auth.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add Recyclarr to the media stack, pin database/object-store/Caddy/Vault images with Watchtower disabled, expose JDownloader at jd.ginnoir.com, and restrict minio/homarr/docs to internal_only. Mark TB-002–004 and TB-033 complete; bundle batch-3 OIDC env for FreshRSS, ownCloud, and Reactive Resume.
Media sites get Caddy forward_auth; Authentik scripts cover all proxy providers. BookStack OIDC and Plane admin routing fixes included, plus ops scripts for external auth on valhalla.
Native OAuth/OIDC for Homarr, BookStack, Gitea, and MinIO console; forward_auth with local auth disabled for code-server, uptime, and kopia; Caddy and Authentik scripts updated to match.
Homarr-labs stores state under /appdata; the old compose mapped empty paths and lost the dashboard on redeploy. TB-006 batch 1 adds Caddy forward_auth for 12 admin UIs with API and webhook bypasses.
Newer hashicorp/vault:latest mlocks more memory than docker's default
64KB memlock ulimit allows; vault crash-looped for ~5900 restarts with
'Failed to lock memory: cannot allocate memory' despite cap_add IPC_LOCK.
Deployed via apply-compose.ps1 -Portainer (mgmt plane, not a git stack).
Every service now reads stack.env via env_file with container-exact var
names — no ${VAR} parse-time interpolation, no Portainer UI env vars
(except stacks/dev, kept on UI-env interpolation as documented exception).
- media: drop PUID/PGID/TZ env lines (env_file covers); resolve ${ROOT}
- foundry: secrets via env_file; FOUNDRY_PATCH_URLS -> CONTAINER_PATCH_URLS
- monitoring: HOMARR_SECRET_ENCRYPTION_KEY -> SECRET_ENCRYPTION_KEY
- notify: FRESHRSS_USER composed in stack.env; TZ via env_file
- owncloud: container-exact OWNCLOUD_*/MYSQL_* keys; runtime $$ healthcheck
- resume/famapp: composites (DATABASE_URL etc.) written out in stack.env
- authentik: container-exact keys; image tag pinned in compose
- notes: couchdb creds via env_file
- remote: gains stack.env (no secrets; convention completeness)
- CLAUDE.md: env convention, valhalla-lab registration-only note, correct
on-host Portainer working-copy path (/config/portainer/compose/<id>)
Validated with docker compose config on valhalla for all 15 stacks.
handoff.json lists files captured at routing time, but the
extraction-cruft cleanup later removes files extracted out of a kept
archive. The Caddy file_server can only serve real files (not archive
interiors), so existence-filter the art + guide rel-paths against
library/<slug>/ before embedding/linking them — dropping phantom
entries that would 404.
handoff.py classifies completed downloads (console rom vs RPG-Maker fangame vs
patch, via bsdtar archive peek incl. RAR5), copies console roms into
Emulation/roms/<platform> for RomM, moves the full folder (rom + guides) into
the library archive, and renders note.md + handoff.json per hack for the
Obsidian publish step. Wired into the cycle; single /data mount keeps moves as
fast renames. Validated on 4 real games.
process_file now marks messages processed only after a real crawljob write, so
DRY_RUN no longer poisons the state and link-less posts get re-checked after the
host filter widens. State file reset alongside this so the arm cycle re-enqueues
all threads.
The tyrrrz/discordchatexporter image is Alpine, not Debian, and ships DCE as a
self-contained executable (no dotnet on PATH). Use apk for python3 and invoke
/opt/app/DiscordChatExporter.Cli directly.
Inert by default: empty token keeps the orchestrator idle and DRY_RUN=true
suppresses downloads. Orchestrator exports per-generation forum threads via
DiscordChatExporter, extracts download links + art, stages metadata, and writes
JDownloader crawljobs. Armed here with an alt account token and all 11 romhack
forums, still in DRY_RUN pending first-cycle validation.
scripts/deck-sgdb-art.py — runs on Deck; fetches hero, wide capsule,
and portrait/poster art from SGDB for all RomM-synced shortcuts.
scripts/deck-sgdb-art.ps1 — Windows wrapper; handles SSH ASKPASS
upload and execution.
.claude/skills/deck-sgdb/ — Claude skill documenting invocation,
file naming conventions, appid formula, and known gotchas.
External access for a trusted friend now goes through the share stack's
Tailscale serve node (roms-share.<tailnet>.ts.net), so roms.ginnoir.com
no longer needs public exposure. Add import internal_only (LAN + tailnet).