Commit Graph
100 Commits
Author SHA1 Message Date
Frank 4e8ea24b2f Record complete 32K ubatch benchmark findings 2026-08-25 18:40:32 -07:00
Frank 929796352a Research llama.cpp runtimes + SGLang; fix AGENTS.md OKF spec link
Fan out subagents to compare mainline llama.cpp, charlie12345/ROCmFPX,
and ik_llama.cpp, then add their findings to the project knowledge base:
- docs/Research/Llama Cpp Runtimes.md  (positioning + quantization + server fit)
- docs/Research/Llama Cpp Code Diff.md (code-level quant diff, table, recommendations)
- docs/Research/SGLang.md              (what SGLang is, comparison, our-boxes fit)
- docs/Research/index.md               (Research progressive-disclosure index)
Cross-linked from docs/index.md (root) and docs/LLM/index.md.

AGENTS.md:
- Add Documentation Authoring section: docs/ is an OKF bundle; point doc authors
  at the canonical spec in the system-config knowledge base
  (~/.pi/agent/docs/references/okf-spec.md), not the orphaned
  docs/references/okf-spec.md; consolidate read-index/one-concept-per-file/
  progressive-disclosure/citation rules.
- Map AGENTS.md to docs_completeness.bats in the focused pre-commit hook (it was
  last committed before the hook existed and had no mapping).
2026-08-25 18:23:19 -07:00
Frank 2693259227 configure anonymous SearXNG provider defaults 2026-08-25 17:58:22 -07:00
Frank e6670f914f docs: record live SearXNG provider baseline 2026-08-25 17:58:22 -07:00
Frank a05584b155 tune SearXNG VPN request timeouts and retries 2026-08-25 17:58:22 -07:00
Frank e1f05bd3c2 Configure Hermes access to small LLM 2026-08-25 17:55:52 -07:00
Frank 96f5ae6fe1 Raise ubatch benchmark context to 32K 2026-08-25 17:44:45 -07:00
Frank 4cb67d7b33 Set ubatch sweep context and batch to 16K 2026-08-25 17:32:12 -07:00
Frank babc823f11 Avoid shell variable collision in bench parser 2026-08-25 17:26:32 -07:00
Frank 56ee7cca45 Pass run number into ubatch benchmark parser 2026-08-25 17:12:51 -07:00
Frank c072c75fa9 Make ubatch benchmark cleanup failure safe 2026-08-25 17:11:42 -07:00
Frank 119ca2493f feat: add tmux session snapshot and restore utility 2026-08-25 17:04:15 -07:00
Frank a8e0b88d99 Parse current llama timing output in ubatch bench 2026-08-25 16:57:02 -07:00
Frank 835996a67b Keep deployment moving when Caddy restart is blocked 2026-08-25 16:55:10 -07:00
Frank eae5bc2565 Continue LLM deployment when compose restart fails 2026-08-25 16:54:18 -07:00
Frank c7a72b465e Fix privileged shared config deployment 2026-08-25 16:53:13 -07:00
Frank d6ea71b9a4 Configure DeepSeek reasoning and large-model ubatch sweep 2026-08-25 16:52:45 -07:00
Frank 8c8c3f7cd0 Enable focused tests as repository pre-commit hook 2026-08-25 16:18:01 -07:00
Frank 63ff1b6b43 Add focused changed-path test wrapper 2026-08-25 16:05:59 -07:00
Frank 7a0feb39aa Add CLI helper for entropy volume 2026-08-25 15:38:57 -07:00
Frank 6ee195dd8f Restore historical Q6 large model runtime 2026-08-25 14:23:47 -07:00
Frank ddfc64013f Fix Q6 AGENT projector path 2026-08-25 13:58:50 -07:00
Frank 86d5f38142 Restore Q6 AGENT large model 2026-08-25 13:36:07 -07:00
Frank 205b11aae4 Clarify historical ROCmFPX payload sizes 2026-08-25 13:28:38 -07:00
Frank 6c9e71efd2 Document Q8 AGENT set_rows serving blocker 2026-08-25 12:16:47 -07:00
Frank 54b2d84613 Upgrade frank-default-large to kingjones Q8_0 AGENT at full 262144 context
frank-default-large now serves the kingjones Qwen3.8-27B-ROCmFPX-Q8_0-AGENT
model with a standalone MTP draft head (Q4_0), f16 K + TurboQuant V KV cache,
and the Sharp chat template. Context is maxed to 262144 (one slot); reasoning
is on with preserve_thinking + preserve_reasoning in the chat kwargs.

- frank-default-large.env: Q8_0 AGENT model paths, CTX_SIZE=262144, REASONING=on,
  REASONING_FORMAT=none, CHAT_TEMPLATE_KWARGS {enable_thinking, preserve_thinking,
  preserve_reasoning}
- serve-frank-large.sh: standalone draft-mtp profile (already switched off the
  Kairic/PromptForge path)
- download-q8agent.sh: reproducible HF fetch of the three payload files
- docs/LLM/kingjones-q8agent-rocmfpx.md: Q8_0 AGENT runbook
- AGENTS.md: topology + ACTIVE runtime section + TTM/GTT load note
- qwen3.8-strix-optimizations, Dankclaw Improvements: TTM pages_limit now 114 GiB
  (applied 2026-08-25), full 262k KV + Q8 payload fit in one slot
- frank_large_config.bats: assert 262144 context, reasoning + preserve_* enabled

The TTM/GTT was raised to 114 GiB (29,883,536 pages) to hold the full 262k KV.
2026-08-25 07:12:02 -07:00
Frank 24efa98d56 docs: add SearXNG providers guide for unblocking Google behind Gluetun VPN
SearXNG queries all ~50 upstream engines from one Gluetun VPN exit IP, so
rate-sensitive engines (Google, DuckDuckGo) answer with reCAPTCHA/429 and
SearXNG suspends the offending engine for hours-to-days, showing up as
"unavailable". Add docs/Dankclaw/SearXNG Providers.md covering: the
suspension model, the two failure modes (CAPTCHA vs selector drift), engine
config (settings.yml engines: list — duplicate google, timeout,
retry_on_http_error, JSON feed), request tuning (outgoing block, UA rotation,
suspended_times — correcting the old rate_limit/useragents blog myths),
routing/proxies (per-engine proxies, dedicated 2nd Gluetun, dedicated IP), and
verification (/json, /config, check.searx.space). Crosslink into SearXNG.md
and index.md.
2026-08-25 06:22:57 -07:00
Frank b457457bfe Switch large service to Kairic Edge v1.2 2026-08-25 04:41:04 -07:00
Frank f86ed70c71 Use conservative four-token MTP drafts 2026-08-25 04:20:15 -07:00
Frank 3cf6353050 Reduce large model context to 64K 2026-08-25 04:13:00 -07:00
Frank b0eb571321 Reduce large model context to 128K 2026-08-25 04:09:12 -07:00
Frank ee3c3de750 Reduce frank-default-large context for KV headroom 2026-08-25 04:05:33 -07:00
Frank 7ca9dc248e frank-default-large: swap to caf-eemin Qwen3.8-27B ROCmI4 embedded-MTP
Replace the retired kingjones ROCmFP4 STRIX MTP payload on Dankclaw with
cafonz/Qwen3.8-27B-ROCmI4-MTP-GGUF (eemin namespace, public), served by the
charlie12345/ROCmFPX llama.cpp build (ROCmI4 W4A4, c49ebdbd) on the Strix Halo
iGPU. Q4_0_ROCMI4 with an embedded NextN/MTP head (no separate draft file);
strict-Qwen MTP n16/p0.60/backend sampling on ROCm0. Binary
/home/dank/rocmi4-qwen38/ROCmFPX/build-rocmi4-w4a4/bin/llama-server; model dir
/home/dank/models/eemin-Qwen3.8-27B-ROCMI4-MTP. Updated serve script + env,
ubatch bench, large-config bats test, docs, AGENTS.md.
2026-08-25 03:33:29 -07:00
Frank 7a8500f6fa Tune frank-default-large params
- frank-default-large.env: CTX_SIZE 262144 -> 196608 (192K context),
  BATCH_SIZE/UBATCH_SIZE 4096 -> 8192, CTX_CHECKPOINTS 16 -> 32, add
  preserve_thinking:true to chat_template_kwargs
- kingjones-strix-mtp.md: sync launch excerpt + note on preserve_thinking
  and the peg-native/deepseek chat_format pairing
2026-08-25 02:30:25 -07:00
Frank cd14d7bf68 Use ngram-mod and prioritize attention experts 2026-08-25 01:40:06 -07:00
Frank 37fb420fcd Record no-spec ubatch benchmark 2026-08-25 01:29:49 -07:00
Frank f13124f977 Select hybrid expert placement from benchmark 2026-08-25 01:08:00 -07:00
Frank 339325719e Reduce small model context and rebalance GPU layers 2026-08-25 00:59:41 -07:00
Frank 7a17984dbc Tune small model expert placement 2026-08-25 00:31:05 -07:00
Frank af6ffeeb64 Switch frank-default-small to Ornith Q6_K 2026-08-25 00:29:14 -07:00
Frank 3cc99d81cc Authentik SSO + homepage naked domain
Auth layer (Authentik 2026.8.0):
- compose: 3-service stack (authentik-postgres, authentik-server, authentik-worker),
  postgres health-gated, bind mounts under /home/dank/authentik
- Caddyfile: auth.franksdank.cloud vhost; forward_auth on the no-auth vhosts
  (homepage, SearXNG, Hermes, Prometheus, RomM, Copyparty); outpost path
  proxied first in a route block
- .env.example: AUTHENTIK_PG_PASS + AUTHENTIK_SECRET_KEY
- deploy.sh: render only CADDY_BASICAUTH_HASH (the homepage per-user hashes
  are retired; grafana + pihole keep basicauth)
- tests/authentik.bats (new) + updated homepage/caddyfile/pihole seams
- docs: Authentik.md + per-service pages; Caddy.md + Homepage.md updated

Homepage (naked domain):
- Caddyfile: dankclaw.franksdank.cloud -> franksdank.cloud www.franksdank.cloud;
  dankclaw + dankserver redirect to it; bare-IP catch-all updated
- addn-hosts: A records for the naked domain, www, and auth (all -> 143)
- tests/pihole.bats: vhost_names handles multi-address blocks; TLD check
  allows the naked domain

All 146 tests pass.
2026-08-24 23:48:27 -07:00
Frank 7ba1acdbc5 frank-default-small: lower context by 32k per stream for cache headroom
3 slots x 229376 (262144 - 32768) = 688128 total context. Updates the
.env, models.json (contextWindow/maxTokens 229376 per slot), and the
index/deployment/ornith runbook references.
2026-08-24 21:50:54 -07:00
Frank 4462aa992c Swap LLM fleet to Ornith CRACK (small) and kingjones ROCmFP4 STRIX MTP (large); apply Qwen-Sharp chat template
- frank-default-small (Dankserver): Ornith-1.5-35B-A3B-CRACK Q8_0, bundled
  native draft-mtp (n_max 4), MoE expert FFN tensors pinned to CPU via an
  explicit --override-tensor \.ffn_(up|down|gate|gate_up)_(ch|)exps=CPU
  (replaces --n-cpu-moe), Qwen-Sharp chat template.
- frank-default-large (Dankclaw): kingjones Qwen3.8-27B-Uncensored-Q6_0
  ROCmFP4 AGENT dense GGUF, standalone mtp-Qwen3.8-27B-Q4_0 draft head
  (--model-draft, draft-mtp n_max 4), Qwen-Sharp chat template. Drop the
  retired PromptForge .pfs sidecar lanes.
- Track scripts/chat-template.jinja (v22.4.0 Sharp) and apply via
  --chat-template-file on both services.
- Docs: new kingjones-strix-mtp and dealign-ornith-crack runbook pages;
  update index, deployment, and both system specs; models.json names.

Smoke-tested both models on the real hardware on scratch ports before
commit: model loads, MTP draft attaches, Sharp template applies, chat
completion returns.
2026-08-24 21:35:11 -07:00
Frank 189934af15 Caddyfile: remove basicauth from chat.franksdank.cloud (OpenWebUI has its own auth) 2026-08-24 18:15:45 -07:00
Frank 35c3fc9ff5 Pi-hole records: mount addn-hosts into FTL hostsdir, not dnsmasq.d
FTL's generated dnsmasq.conf has no conf-dir: /etc/dnsmasq.d/ is never
read (the 2026-08-24 scratch-name test proved the file was inert; names
only resolved from the query cache). The only file-based local-record
mechanism is hostsdir=/etc/pihole/hosts. Mount the record file there.
Doc: record the pitfall in Pi-hole.md.
2026-08-24 14:26:58 -07:00
Frank 0f59316be9 docs: Pi-hole KB page + dnsmasq retirement across the vault
- new docs/Infrastructure/Pi-hole.md (quadlet, records, upstream, web UI,
  failure modes incl. the rootless /etc/hosts single-label echo)
- LAN-DNS.md: Pi-hole quadlet section, router hand-off, host DNS
- Network Architecture / Caddy / Homepage / index / AGENTS.md: name swap
2026-08-24 13:54:35 -07:00
Frank bb96fc55f7 Pi-hole swap: quadlet + env + records + Caddy vhost (retires dnsmasq)
- dankclaw/pihole/: pihole.container (quadlet, slirp4netns, 53+8083),
  env.example (ServerIP/TZ/DNS1/DNS2/WEBPASSWORD placeholders), addn-hosts
  (moved from dankclaw/dnsmasq/, + pihole.franksdank.cloud record)
- Caddyfile: pihole.franksdank.cloud vhost (family basicauth -> 8083)
- scripts/deploy-pihole-quadlet.sh: idempotent quadlet installer
- tests/pihole.bats replaces tests/dnsmasq.bats (same record validation
  + cross-checks, new quadlet/env seams); retired files in .AGENTTRASH/
2026-08-24 13:54:35 -07:00
Frank cf3da02af7 Add weekend report + doc-audit HTML (report/doc-audit-2026-08-23.html) 2026-08-24 01:22:43 -07:00
Frank 90c4ac69a7 Doc audit: fix all broken links + correct stale facts across the KB
Fanned out 5 read-only doc-auditor subagents (one per service group) that
fact-checked the knowledge base against the live system + repo config,
researched official setup docs online, and verified progress. Applied:
- All 34 broken links fixed (real pages / external URLs / correct relative
  paths); 0 broken links remain. No .AGENTTRASH links (the 4 mentions are
  accurate descriptive text, not links).
- Fact-check fixes: Readarr retired (May 2026), Radarr v4->v6, Calibre
  9.2.1 live, Calibre-Web 0.6.25 live, Copyparty v1.20.21, LLM index
  ncmoe 38 + 786432 ctx, frank-default-small active (not frank-pp-worker),
  Hermes/SearXNG/Grafana hostnames, Loki/Alloy local images, Observability
  diagram (Promtail->Alloy), VLLM retired note, DFlash status, benchmark
  live-drift notes, Homepage test count 116.
2026-08-24 01:10:44 -07:00
Frank ac7c8ee442 Caddyfile: point the shared family login at dankuser too
The other vhosts (gitea, grafana, search, ...) now use username 'dankuser'
with CADDY_BASICAUTH_HASH, which is set to the same hash as the homepage
(dankpassword.123). So the whole protected surface logs in as
dankuser / dankpassword.123; the operator /admin/ page still uses frank.
Updated the two tests that asserted the old 'dank' username.
2026-08-23 22:26:46 -07:00
Frank c58dab0a89 Homepage: give the user page its own login (dankuser)
The homepage user page + shared data now use a dedicated CADDY_HOMEPAGE_HASH
(username dankuser), separate from the shared family password (CADDY_BASICAUTH_HASH,
username dank, still used by the other vhosts) and the operator password
(CADDY_ADMIN_HASH, username frank, the /admin/ page). This lets the homepage be
re-logged independently without touching the other sites. deploy.sh renders the
new placeholder; the .env.example documents all three hashes.
2026-08-23 21:08:21 -07:00
Frank 677046768b docs: record the deployed homepage + the Caddyfile handle design
The homepage is live on Dankclaw. Update the Status (deployed) and the Auth
section (the handle-block design, the Caddyfile directive-sorting pitfall, the
host /srv/homepage mount, and the container-recreate note). Cross-reference the
agent KB Caddyfile syntax page.
2026-08-23 20:07:52 -07:00
Frank 5e6ba222cb compose: point caddy's /srv/homepage at the host dir, not the repo
The caddy container mounted the repo's shared/homepage (the static source) to
/srv/homepage. But the deploy writes the generated files (status.json from the
status checker, deployed.js from the deploy) to the host's /srv/homepage. So
the container served the static files (200) but 404'd the generated ones.
Mount the host's /srv/homepage instead, which holds both the static files (the
deploy copies them) and the generated ones.
2026-08-23 19:18:41 -07:00
Frank c7ced90aca Caddyfile: serve the homepage via handle blocks (fix the /admin/ 401)
Caddy SORTS top-level directives, so a 'rewrite' runs before 'basicauth'.
The rewrite changed /admin/ to /admin.html, and the path-based auth matchers
then saw /admin.html (which matched the family 'not path /admin/*' block, not
the operator '/admin/*' block) — so the operator password was checked against
the family hash and 401'd.

Serve each page from its own 'handle' block (which preserves order, so the
auth is checked on the original path before any file rewrite):
- handle /admin* : operator (frank) only, try_files /admin.html
- handle @data   : shared data + assets, family (dank) OR operator (frank), so
  the admin page's fetches of services.json/status.json reuse the operator
  credential
- handle         : everything else (the user page), family (dank)
2026-08-23 18:33:54 -07:00
Frank 25af3d9fdf Caddyfile: fix the /admin/ rewrite (matcher follows the directive)
'@admin rewrite ...' is parsed as a one-liner matcher DEFINITION, so it
re-defined @admin and Caddy rejected the config ('matcher is defined more
than once'), crash-looping the container. Per the Caddyfile matcher docs the
matcher token is the first ARGUMENT after the directive: 'rewrite @admin
/admin.html'. The '*' disambiguator is only needed pre-2.8.0. Validated the
rendered config against the porkbun image: 'Valid configuration'.
2026-08-23 17:42:44 -07:00
Frank e7eaba4457 Homepage (TDD slice 7): fix the /admin/ path + status.json perms
Two real bugs found on the first production deploy:
- /admin/ 404'd: file_server looked for /srv/homepage/admin/ (a dir), but the
  page is admin.html. Add '@admin rewrite * /admin.html' so the /admin/ path
  serves admin.html.
- The pages used relative refs (style.css, app.js, services.json, status.json),
  which from /admin/ resolved to /admin/... (404). Add <base href="/"> so all
  refs resolve to the site root on both pages.
- status.json was written 0600 (root); the checker now chmods it 0644 so Caddy
  can serve it regardless of its user.
2026-08-23 16:49:33 -07:00
Frank b485a27784 deploy: run the /srv/homepage steps under sudo
The homepage deploy's mkdir/cp/write of /srv/homepage ran as the deploy user
and hit 'Permission denied' (/srv is root-owned). Prefix them with the sudo
wrapper, write deployed.js via a temp file + sudo cp, and chmod the tree
a+rX so Caddy can serve it. Run the one-off checker as root too (it writes
status.json into /srv/homepage).
2026-08-23 15:44:46 -07:00
Frank f400be76c6 deploy: make the Caddy hash grep defensive under set -e
A missing CADDY_*_HASH in the .env made the 'grep | tail | cut' pipeline
return non-zero, which aborted the deploy under 'set -e' before it could warn
and keep the placeholder. Add '|| true' so an absent hash warns instead of
aborting. (The homepage deploy aborted here because CADDY_ADMIN_HASH was not
in the repo-root .env the deploy reads.)
2026-08-23 15:25:53 -07:00
Frank cc1f421d27 Homepage: record the completed build in the KB
- Homepage.md: status is now 'built, pending deploy' (all assets + checker +
  deploy are in the repo, 112 tests green). To go live: add CADDY_ADMIN_HASH
  to the target .env, then deploy.sh.
- Homepage Design Grilling.md: the build is complete (all 6 slices, full TDD);
  the only remaining step is the operator adding the admin hash + deploying.
- pi log.md: build-complete entry.
2026-08-23 13:06:58 -07:00
Frank 2e6c44f3ba Homepage (TDD slice 6): the git-driven deploy
Red tests first.
- tests/homepage_deploy.bats: the deploy ships the homepage (assets to
  /srv/homepage, the checker timer, both Caddy hashes, deployed.js) and is
  git-driven (pulls main); the checker runs as a systemd timer.
- scripts/homepage-status.service / .timer: the checker as a oneshot service
  + a 3-minute timer (Q2/Q35).
- scripts/deploy.sh: the Caddyfile render now substitutes BOTH hashes
  (REPLACE_WITH_HASH <- CADDY_BASICAUTH_HASH, REPLACE_WITH_ADMIN_HASH <-
  CADDY_ADMIN_HASH). A new homepage step copies the assets to /srv/homepage,
  generates deployed.js from the deployed commit's datetime (Q43), installs
  the checker timer, and runs the checker once so status.json exists at once.
- tests/llm_units.bats: scoped the three LLM-unit tests to
  frank-default-*.service (the homepage unit is a different pattern: it
  installs to /usr/local/bin and runs from /srv at deploy time).
2026-08-23 12:59:56 -07:00
Frank 13ea2d7d3e Homepage (TDD slice 5): the Caddyfile auth split
Red tests first.
- tests/homepage_caddy.bats: the homepage site block carries a root hash and
  a distinct /admin/-scoped admin hash (Q18/Q38), and serves /srv/homepage.
- dankclaw/Caddyfile: the homepage block now uses named matchers -
  @user (not /admin/*) with the shared hash, @admin (/admin/*) with the
  operator-only hash (REPLACE_WITH_ADMIN_HASH, rendered from CADDY_ADMIN_HASH
  at deploy). Both placeholders are distinct.
2026-08-23 12:32:18 -07:00
Frank 01c42202b8 Homepage (TDD slice 4): the pages, theme, and toggle
Red tests first, then the pages.
- tests/homepage_pages.bats: the pages reference the data + theme; no
  auto-refresh (Q41); no cursor alteration (Q28); the styling toggle strips
  to bare HTML (Q27); the footer shows the last master deployment datetime
  (Q43).
- index.html / admin.html: the user and admin pages. A grid of TUI panels,
  a summary line, the bare toggle, the deployed-at footer.
- app.js: reads status.json + services.json once (no auto-refresh), renders
  one panel per service for the page's category, the toggle, the footer.
- style.css: the terminal TUI theme (green-on-black, phosphor palette,
  scanlines) + a ?bare=1 mode that strips to unstyled HTML. No custom cursor.

Functionally verified with a Node DOM shim: 9 user panels, correct summary,
correct footer datetime.
2026-08-23 12:26:31 -07:00
Frank ce55d1dc3a Homepage (TDD slice 3): the real services.json + schema tests
Red tests first (the old services.json was an object, not the new list schema).
- tests/homepage_config.bats: the config is a JSON list; every entry has
  name/category/probe; category is user|admin; method is tcp|http; a
  showLink entry has a url and a status-only entry does not.
- shared/homepage/services.json: the real fleet. User: SearXNG, ComfyUI,
  OpenWebUI, Gitea, Calibre-Web, RomM, Copyparty, Plex, Jellyfin. Admin:
  Hermes, Grafana, Prometheus, Loki, node-exporter, alloy, Caddy, dnsmasq,
  Gluetun (wip - a tunnel has no simple local port), the two LLMs, mariadb,
  valkey, Postgres. Ports confirmed from the repo config (compose/quadlet).
  docs fields are empty for now (the /docs/ workstream fills them as each
  service goes active).
2026-08-23 12:11:21 -07:00
Frank fcb6593afd Homepage (TDD slice 2): the http probe method
Red test first: a raw TCP listener that never speaks HTTP must read down
under an http probe (up under tcp), while a real HTTP server reads up. This
test caught a real hang — the backgrounded listener inherited the test
runner's stdout pipe and held it open; fixed by redirecting its output and
killing both listeners in teardown.

scripts/homepage-status.py: probe() now dispatches on method. http does an
urlopen (any HTTP status = up; no connection = down); tcp connects.

The checker is now complete: tcp + http + wip + atomic write + generated_at.
Remaining slices: services.json schema, the pages + theme + toggle, the
Caddyfile (validate + two hashes), the git-driven deploy.
2026-08-23 11:36:56 -07:00
Frank 05257df8e4 Homepage (TDD slice 1): the status checker core
Full TDD (Q36): red test first, then the minimal implementation.
- tests/homepage_checker.bats: seam = homepage-status.py <services.json>
  <out.json>. Asserts an open port is up, a closed port is down, a wip
  service is wip (not probed), and the output carries generated_at.
- scripts/homepage-status.py: reads the config, probes each backend (tcp,
  5 s timeout), skips wip, writes status.json atomically (temp + rename).

Remaining slices: http probe method, services.json schema, the pages +
theme + toggle, the Caddyfile (validate + two hashes), the git-driven deploy.
2026-08-23 10:42:54 -07:00
Frank e430b6dbad Homepage: record all 38 settled decisions (grilling complete)
- Homepage Design Grilling.md: final decision table (Q1-Q43) + the deltas where
  the operator changed the recommendation (per-service probe method, 5s timeout,
  TUI panels, toggleable styling, no cursor alteration, no auto-refresh, /docs/
  path, user-facing docs, git-driven deploy, full TDD, last-deploy footer).
- Homepage.md: updated to the settled design (per-service probe, 5s, TUI panels,
  styling toggle, no auto-refresh, /docs/ workstream, git-driven deploy, TDD).
- pi log.md: 2026-08-23 entry recording the settled design and build order.

Build order is unblocked. No homepage code built yet.
2026-08-23 10:31:15 -07:00
Frank cdae928f37 Homepage: settle design (grilling Q1-Q5), log open questions Q6-Q43, progress report
- Homepage.md: rewritten to the settled design (single site, user + /admin/
  pages, server-side status.json via a 3-min systemd-timer checker, terminal
  TUI theme). Added mermaid diagrams: site structure, status states, checker
  flow. Recorded the classification (user vs admin; *arr excluded; LLM admin;
  backends status-only) and the documented future shift to client-side probing.
- Homepage Design Grilling.md (new): the decision log — settled Q1-Q5 plus 38
  open questions (Q6-Q43) across 10 categories, each with a recommendation.
- docs/index.md: link the grilling page (satisfies the index-links-every-page test).
- report/homepage-grilling-2026-08-22.html: self-contained terminal-TUI progress
  report (settled decisions, verified stack baseline, overnight processing, work
  threads, the open questions, and how to continue).

Baseline recorded: Dankclaw fully up (10/10); the Dankserver media stack is down
(only Calibre-Web + the LLM are up; no .env on the target) — a separate thread.
No homepage code built yet; the design is pending the operator's answers to Q6-Q43.
2026-08-23 02:59:48 -07:00
Frank 6a9edd4ee0 deploy.sh: keep the relink comment free of a literal loop-var token
The explanatory comment contained an unescaped loop-variable token, which
the local shell (set -u) tried to expand while building the double-quoted
remote script ('unit: unbound variable'). Reword the comment.
2026-08-22 22:36:04 -07:00
Frank 33438f223e deploy.sh: fix LLM unit relink (unquote source path so ${unit} expands on the remote)
The relink loop wrapped the source path in single quotes, which shipped a
literal ${unit} to the remote and created a dangling symlink
(/etc/systemd/system/frank-default-large.service -> .../${unit}.service),
so 'systemctl enable' failed with 'unit does not exist'. The path has no
spaces; unquoting lets ${unit} expand on the remote for both source and
destination.
2026-08-22 22:33:16 -07:00
Frank fbfbc5c6db Move frank-default-large from :52625 to :7770 (dankclaw)
Operator request (2026-08-22): the primary inference server
(frank-default-large, the 27B CIRU model on Dankclaw) moves to the
standard llama.cpp port 7770. Both LLM services now listen on :7770,
distinguished by host (dankserver vs dankclaw).

Functional changes:
- scripts/frank-default-large.env: LISTEN_PORT 52625 -> 7770
- scripts/serve-frank-large.sh: default LISTEN_PORT 52625 -> 7770
- scripts/deploy.sh: LLM_HEALTH[dankclaw] -> :7770
- open-webui quadlet: OPENAI_API_BASE_URL -> 192.168.0.143:7770
  (re-pointed so chat keeps working; data dir preserved)
- scripts/bench-fast-greedy.sh: PORT 52625 -> 7770

Tests updated to the new topology (both LLM endpoints on :7770 by host;
open-webui -> :7770). Docs + pi KB updated; dated historical runbooks
keep their point-in-time ports. models.json (pi client) re-pointed to
:7770 separately, effective on the next client restart.
2026-08-22 22:11:53 -07:00
Frank e367f0f43c docs: one knowledge base for both workloads
- docs/index.md: LLM Fleet section (all 34 pages linked), merge note,
  See Also now internal
- docs/LLM/index.md: retitled, dangling [[Dankserver]]/[[Dankclaw]]
  links fixed, sibling section replaced with internal links
- docs/LLM/deployment.md: rewritten for the unified deploy flow,
  manual-update paths point at the merged checkout, incident history
  kept intact
- Deployment Flow / Dankclaw Stack / Gitea: stale vllmScripts
  references and retired-topology notes updated to the 2026-08-22
  state
- Historical docs (frank-redo, PP deployment, FastFlowLM) keep their
  dated runbook paths as-is (records of retired topologies)
2026-08-22 15:50:39 -07:00
Frank 0461988884 scripts: unified deploy.sh; units + bench point at the merged checkout
deploy.sh now deploys both workloads per target in one run:
push -> pull on /home/dank/serverAppConfigs -> podman stack steps
(dankclaw) -> LLM unit relink + daemon-reload + service restart ->
homepage health + LLM health (up to 20 min model-load wait).
Sudo: plain sudo on the fleet hosts (passwordless verified
2026-08-22); FRANK_SUDO_PW covers headless runs elsewhere. The
vllmScripts deploy.sh is superseded.

Units: frank-default-{small,large,npu}.service now reference
/home/dank/serverAppConfigs/scripts/... (the merged checkout).
bench-spec-stack.sh: env file path updated to the merged checkout.
2026-08-22 15:50:39 -07:00
Frank 2b115ad378 README + .gitignore: one repo, two workloads
README: merged service table (stack + LLM), structure incl. old/ and
docs/LLM/, unified deploy note, merge note.
.gitignore: merged both files; !scripts/*.env exception for the LLM
tunables (paths and numbers, never credentials); .obsidian/,
__pycache__/, .venv/ from the vllmScripts side.
2026-08-22 15:49:44 -07:00
Frank 99c7255db5 AGENTS.md: merge the vllmScripts directives into one rulebook
One repo, one git protocol, one deploy script. Merged from the two
former AGENTS.md files:
- Overview: both workloads, both hosts, the 2026-08-22 merge note,
  current LLM fleet topology (frank-default-small :7770 Dankserver,
  frank-default-large :52625 Dankclaw)
- Git workflow + testing (serverAppConfigs protocol, test step kept)
- Deployment: the unified deploy.sh (stack + LLM per target)
- Secret rules: no passwords in the repo; FRANK_SUDO_PW covers
  headless sudo (the live sudo password is NOT carried forward)
- Deletion & Trash Policy (from the vllmScripts 2026-08-22 commit)
- Benchmarking policy (stop the service before any bench)
- Pi model config, runtime & troubleshooting (v3 CIRU active,
  Kairic/DFlash2/FastMTP retired), HIP env naming rule, crash-loop
  procedure, operational quirks (passwordless sudo verified
  2026-08-22), Dankclaw memory model
2026-08-22 15:49:44 -07:00
Frank 8001132744 tests: LLM unit integrity, sudo-password leak guard, deploy LLM coverage
New seams (written first, red against the pre-merge tree):
- llm_units.bats: every scripts/*.service unit points at files that
  exist in this repo (the merged checkout path), env files included
- llm_secrets.bats: the live sudo password is never tracked (the
  vllmScripts AGENTS.md once documented it)
- deployment_flow.bats: deploy.sh must restart the LLM services on
  both targets and health-check both endpoints (7770, 52625)
- helpers.bash: has_no_leaked_sudo_pw (two-part assembly, same
  pattern as the gitea check)
2026-08-22 15:49:44 -07:00
Frank 02f92386f8 Reorganize: drop llm/ root files (absorbed into repo root in follow-up)
llm/AGENTS.md, llm/README.md, and llm/.gitignore are superseded by the
merged root AGENTS.md, README.md, and .gitignore.
2026-08-22 15:07:31 -07:00
Frank 1f565c08c3 Reorganize: tracked DFlash2 archive files -> .AGENTTRASH (repo root) 2026-08-22 15:07:31 -07:00
Frank aa410f4439 Reorganize: llm/scripts -> scripts (LLM serve scripts, units, env tunables)
The LLM fleet serve scripts, systemd units, env tunables, and bench
harnesses join the deploy scripts. The vllmScripts deploy.sh is
removed here; its functionality is folded into the unified
scripts/deploy.sh in a follow-up commit.

bench-spec-stack.sh gains the executable bit (required by the
scripts_syntax test seam).
2026-08-22 15:07:31 -07:00
Frank 506614525b Reorganize: llm/old -> old (retired PP/NPU-era scripts, reference only) 2026-08-22 15:06:51 -07:00
Frank 017d3704d2 Reorganize: llm/docs -> docs/LLM (LLM fleet knowledge base)
The LLM fleet documentation (deployment runbook, model runbooks,
benchmarks, research archive, retired-topology history) joins the
project knowledge base as docs/LLM/. Wikilinks resolve by filename,
so no link updates are needed for the move.
2026-08-22 15:06:51 -07:00
Frank 918fe4eaec Merge vllmScripts under llm/ (history-preserving import)
The vllmScripts repository (LLM inference fleet: serve scripts, systemd
units, env tunables, deployment runbook, research docs) is merged into
this repository. Its full history is grafted under llm/ with a
two-parent merge commit so no commit is lost.

A follow-up commit reorganizes llm/ into the repo layout:
llm/docs -> docs/LLM, llm/scripts -> scripts, llm/old -> old.
2026-08-22 15:03:03 -07:00
Frank 0746303c33 AGENTS.md: add mandatory Deletion & Trash Policy (mv to ~/.AGENTTRASH, never rm)
Explicit rule: stage deletions in a dated ~/.AGENTTRASH/YYYYMMDD-topic
directory, list sizes, and wait for user approval before purging. rm,
rm -rf, and git clean -f forbidden without explicit permission. Applies
to every host.
2026-08-22 14:38:26 -07:00
Frank c45f40a9b3 docs: reflect rollback to v3 on frank-default-large (Kairic experiment retired)
AGENTS.md topology table + runtime sections, docs/index.md deployment
diagram, docs/kairic-edge.md (retired experiment, perf summary), and
docs/ciru-activefpx-promptforge.md (active again) all restored to the
v3 reality. Remaining Kairic references are inside the retired reference
page itself.
2026-08-22 14:26:32 -07:00
Frank c60156f3c6 rollback frank-default-large to v3 CIRU ActiveFPX PromptForge (operator decision 2026-08-22)
Restores the script pair verbatim from 132e147. v3 settings: PromptForge
m2048_fused_tail1476 full-W8 views, Output-K8 draft proxy, BF16 mmproj
vision, TEMPERATURE 0.7 / TOP_P 0.95, batch 4096/4096, ctxcp 16, reasoning
on/deepseek, no-mmap. Runtime: build-promptforge llama-server + v3 model
files in /home/dank/models/CIRU-Qwen3.8-27B-ActiveFPX-v3. Kairic Edge
files remain on the machine for rollback (docs/kairic-edge.md).
2026-08-22 14:20:11 -07:00
Frank ddcd54e13f Make FASTGREEDY=1 compatible with non-greedy requests (argmax fastpath always off)
LLAMA_TARGET_GREEDY_ARGMAX_FASTPATH=0 unconditionally. FASTGREEDY=1 now
means: reasoning off, deterministic sampler defaults, compatible with
all non-greedy requests (temp != 0, penalties, reasoning budget). This
is the card's 'compatible mode' profile.
2026-08-22 13:45:57 -07:00
Frank c66273033b open-webui: reach the LLM via the host LAN IP, not the bridge gateway
The bridge gateway (10.89.3.1) lives in the rootless netns; llama-server
runs in the host netns, so the gateway refuses. 192.168.0.143:52625
reaches it through the rootless NAT (verified from the container).
Same LAN-IP pattern the doc already prescribes for the Dankserver
backend.
2026-08-22 13:44:48 -07:00
Frank 0951fc165c deploy.sh: restart caddy when the reload cannot be applied
A 'caddy reload' delivered over the admin API cannot apply a config
that disables the admin API -- the fix cannot ride the API it is meant
to enable (2026-08-22: admin off sat in the running config across
deploys). Track the reload result; on failure, restart the container
so it reads the rendered file on start.
2026-08-22 13:35:31 -07:00
Frank fe71f7516d Flip production to FASTGREEDY=1 (operator decision 2026-08-22)
Reasoning off, argmax fastpath on, deterministic sampler. The fast
greedy path rejects non-greedy requests with 400; chat clients must
send temperature 0.
2026-08-22 13:26:52 -07:00
Frank bb1ef9bfb3 caddy: keep admin on for hot reload; deploy.sh reloads after render
The Caddyfile had 'admin off', which disables Caddy's config file
watcher. Rendered Caddyfile changes never loaded until the container
was recreated, so the double-hash basicauth fix sat on disk unapplied
across deploys (2026-08-22). Admin binds to 127.0.0.1:2019 inside the
container and the port is unpublished, so nothing outside reaches it.

deploy.sh now issues an explicit 'caddy reload' (retry loop) after
'up -d', with the file watcher as backstop.
2026-08-22 13:22:01 -07:00
Frank da68b5ce1a fix: basicauth double-prefix render; open-webui off slirp4netns
basicauth (2026-08-22 incident):
- the Caddyfile template carried its own $2a$14$ prefix and deploy.sh
  substituted the full hash (prefix included), rendering an invalid
  double-prefixed hash. Every basicauth vhost rejected every password
  with 401 and Caddy logged nothing.
- template is now a bare REPLACE_WITH_HASH token; tests pin the render
  contract (no prefix in template; rendered line is exactly 'dank <hash>').

open-webui (2026-08-22 incident):
- its slirp4netns helper process died, leaving the container running
  with only 'lo' in its netns: port 3005 accepted TCP and reset every
  request, so chat served empty responses for ~2 days, unlogged.
- move to a pinned bridge network (systemd-open-webui, 10.89.3.0/24,
  gw 10.89.3.1) — no per-container helper to die.
- LLM endpoint reached via the gateway (host.containers.internal is
  slirp-only): OPENAI_API_BASE_URL=http://10.89.3.1:52625.
- add a quadlet healthcheck: /health (app) + non-loopback interface
  (network liveness; the dead-tap state leaves only 'lo').
- deploy script now copies the .network file too.
- docs updated (OpenWebUI History section, Caddy basic-auth contract).
2026-08-22 13:07:43 -07:00
Frank 7f617b9ee6 Add bench-fast-greedy.sh for A/B fast-greedy vs production testing 2026-08-22 13:03:21 -07:00
Frank f347d5336f Set FASTGREEDY=0 default in env; add deployment notes 2026-08-22 12:54:28 -07:00
Frank e0329caef8 Add FASTGREEDY mode to serve script: reasoning off + argmax fastpath on for fast-greedy bench
FASTGREEDY=1 flips the serve script to the card's default profile:
- reasoning off (no logit budget overhead)
- LLAMA_TARGET_GREEDY_ARGMAX_FASTPATH=1 (exact-Q8 GPU argmax)
- deterministic sampler (temp 0, top_p 1, top_k 0, min_p 0)

This mirrors the card's 'fast greedy (default)' benchmark config.
Production (FASTGREEDY=0) unchanged.
2026-08-22 12:54:03 -07:00
Frank 5c9ade4e7a deploy.sh: fix quoting of the cfhash label template 2026-08-22 04:16:18 -07:00
Frank e0a25415a1 deploy.sh: rebuild local images when their Containerfile hash changes
buildah can serve a stale COPY --from layer (cache keyed on stage
name), so a Containerfile edit silently produced an unchanged image.
The image now carries a cfhash label; a mismatch forces a --no-cache
rebuild.
2026-08-22 04:14:43 -07:00
Frank 7d6a285371 copy /bin/busybox.static (the -static package does not overwrite /bin/busybox) 2026-08-22 04:13:55 -07:00
Frank 824d39a29e busybox-static for healthchecks; alloy: rely on the default UI listener
- alpine's /bin/busybox is musl-dynamic and cannot execute in the
  distroless loki image (missing loader); busybox-static links in
- alloy 1.x refuses to configure the ui service from a config block;
  the default UI already listens on 127.0.0.1:12345 where the
  healthcheck probes
2026-08-22 04:09:04 -07:00
Frank dc421efea4 deploy.sh: escape the image-build loop vars for the remote string 2026-08-22 04:04:24 -07:00
Frank 1f4766f233 observability: fix alloy ui component, busybox healthchecks for loki/alloy
- alloy 1.x renamed the server component to ui; the old block failed the
  initial load and the container crash-looped
- grafana/loki is distroless and grafana/alloy lacks wget, so their
  healthchecks could never run; local images add a static busybox from
  alpine for that one command
- deploy.sh builds all three local images if missing
- tests: 3 new seams
2026-08-22 03:59:14 -07:00
Frank 816986139f observability: run as container root 0:0, not 1000:1000
Measured the rootless mapping: container root IS the invoking user
(dank, owner of the /opt data dirs); the images' default users (loki
10001, prometheus nobody, grafana 472) map to subuids that own nothing.
1000:1000 was the wrong direction.
2026-08-22 03:45:06 -07:00