agent: repoint FLM-NPU model roles off the retired provider; sync memory/skills
config.yml: vision -> llamacpp (dankclaw)/frank-large:auto, tiny -> llamacpp (dankserver)/frank-small:off, task -> llamacpp (dankclaw)/frank-large:medium (was flm dankclaw-npu), matching the flm (dankclaw-npu) provider removal in models.yml. Memories/managed skills: rollouts and learned notes from the frank-large KV-pool + sampler work and the noctalia recolor; merged the duplicate noctalia-palette-recolor skill into noctalia-custom-palette-recolor (adds the dotfiles-tracking step and the +show-config delta gotcha) and dropped the superseded legacy memory skills whose ghostty USR1 reload recipe is wrong for this fleet.
This commit is contained in:
+3
-3
@@ -26,12 +26,12 @@ providers:
|
||||
modelRoles:
|
||||
smol: llamacpp (dankserver)/frank-small:off
|
||||
slow: llamacpp (dankclaw)/frank-large:medium
|
||||
vision: flm (dankclaw-npu)/nuextract3:4b:auto
|
||||
vision: llamacpp (dankclaw)/frank-large:auto
|
||||
plan: llamacpp (dankclaw)/frank-large:medium
|
||||
designer: llamacpp (dankclaw)/frank-large:medium
|
||||
commit: llamacpp (dankserver)/frank-small:medium
|
||||
tiny: flm (dankclaw-npu)/gemma4-it:e4b:off
|
||||
task: flm (dankclaw-npu)/gemma4-it:e4b:off
|
||||
tiny: llamacpp (dankserver)/frank-small:off
|
||||
task: llamacpp (dankclaw)/frank-large:medium
|
||||
advisor: llamacpp (dankclaw)/frank-large:medium
|
||||
default: llamacpp (dankserver)/frank-small:medium
|
||||
symbolPreset: nerd
|
||||
|
||||
@@ -3,88 +3,24 @@ name: halogen-kv-pool-fit
|
||||
description: "Resize halogen-flash-server's KV pool or prefill arena without getting silently clamped or OOMing the boot: pool, arena and vision share one device budget, HALOGEN_HOST_RESERVE_GIB only scales the fit-check ceiling and is NOT an allocation, HALOGEN_KV_POOL_FIT only ever lowers, and the sizing warning prints only when a clamp happened."
|
||||
---
|
||||
|
||||
# Sizing a halogen-flash-server KV pool
|
||||
# halogen-flash-server KV pool / arena resizing
|
||||
|
||||
`HALOGEN_KV_POOL_FIT=1` (default) computes a device budget at startup and **only ever lowers** the configured `HALOGEN_KV_POOL_POSITIONS`. It never raises it, and never below the context.
|
||||
One device budget covers KV pool + prefill arena + vision tower:
|
||||
|
||||
```
|
||||
device budget = host RAM - resident weights - HALOGEN_HOST_RESERVE_GIB
|
||||
fit check = needs budget >= (KV + arena + vision) + 1.5 GiB margin
|
||||
KV = 28 KiB/position
|
||||
arena = 3.80 GiB + 8.40 GiB x (HALOGEN_MAX_TOK / 16384) # measured, linear
|
||||
vision = 1.97 GiB when HALOGEN_VISION_TOWER=1
|
||||
budget = host RAM (121.2) - resident weights (67.7) - HALOGEN_HOST_RESERVE_GIB
|
||||
need = KV (~28 KiB/position, ~11.0 GiB at 401408 as reserved) + arena + vision (1.97)
|
||||
arena = 3.80 GiB + 8.40 GiB x (HALOGEN_MAX_TOK / 16384)
|
||||
```
|
||||
|
||||
Prefer the engine's printed requirement over the model: a clamped boot states
|
||||
it directly, e.g. `524288 positions need ~35.0 GiB (plus 1.5 of margin)`.
|
||||
Measured ledger (Dankclaw, engine's own startup print): 262144/32768/r24 → 96.3 held, 12.1 left, 2081 blocks; 524288/16384/r24 → 94.6/13.8/3742; 524288/32768/r15 → 103.5/7.1/310 (stall NOTE prints); 524288/32768/r16 → identical (reserve is NOT an allocation); **401408/32768/r15 (deployed 2026-09-13) → 100.0/9.1/1396, NOTE gone**.
|
||||
|
||||
## The reserve is NOT an allocation
|
||||
Procedure:
|
||||
1. Edit `HALOGEN_KV_POOL_POSITIONS` / `HALOGEN_MAX_TOK` in `dankclaw/frank-large/quadlet/frank-large.container` only. Never raise `HALOGEN_HOST_RESERVE_GIB` — it only moves the fit-check ceiling (at 524288 the ceiling was 16; engine needs budget ≥ 36.5 there; 18 clamps to 262144).
|
||||
2. Over budget → `HALOGEN_KV_POOL_FIT` silently LOWERS the pool and deploy still reports healthy. Way over → arena alone OOMs the boot while the unit still reads ACTIVE (max_tok 65536 did this). Always `podman logs frank-large | grep 'kv pool:'` and match the reserved count to the requested one; /health proves nothing about pool size.
|
||||
3. Under budget → nothing prints; absence of WARNING is not evidence of headroom.
|
||||
4. After restart, FIRST request can silence the engine ~45-60 s ("has not answered PING", /health engine_unresponsive) — one-time pool first-touch, self-recovers; HealthStartPeriod=300s covers it. Do not restart the unit. A completion retried after that window succeeds instantly.
|
||||
|
||||
`HALOGEN_HOST_RESERVE_GIB` is a term in the fit-check inequality, nothing more. Proved by A/B: reserve 15 and reserve 16 both held **103.5 GiB** with **7.1 GiB left for everything else** — identical footprint. Actual footprint is `weights + KV + arena + vision`, none of which the reserve touches.
|
||||
To free host memory: cut the pool (262144 hands back ~3.6 from 401408) or the arena (MAX_TOK 16384 = 8.4). Host-left gain comes in below the KV delta (engine keeps freed space as working slack): the 401408 trim modelled +3.4, measured +2.0 GiB but 4.5x contiguous blocks.
|
||||
|
||||
So the knob has only two regimes: below the pool's requirement it changes nothing observable; above it, it silently deletes the pool. **Raising the reserve can never give memory back to co-tenants.** To free host RAM, cut the pool or the arena:
|
||||
|
||||
| change | RAM handed back |
|
||||
|---|---|
|
||||
| `HALOGEN_KV_POOL_POSITIONS` 524288 → 262144 | 7.2 GiB |
|
||||
| `HALOGEN_MAX_TOK` 32768 → 16384 | 8.4 GiB |
|
||||
|
||||
Lowering the reserve DOES work — it buys fit margin for a bigger pool or arena. On a 121.2 GiB host with 67.7 GiB weights, for 524288 + max_tok 32768 (needs 36.5):
|
||||
|
||||
| reserve | budget | vs 36.5 | outcome |
|
||||
|---|---|---|---|
|
||||
| 24 | 29.5 | −7.0 | clamps |
|
||||
| **18** | **35.5** | **−1.0** | **clamps — looks like a healthy deploy** |
|
||||
| 17 | 36.5 | +0.02 | knife edge, inside the noise of the weights term |
|
||||
| 16 | 37.5 | +1.0 | fits, zero benefit over 15 |
|
||||
| **15** | **38.5** | +2.0 | **deployed** |
|
||||
|
||||
Ceiling here is 16; pick the lowest reserve that fits, not the highest.
|
||||
|
||||
## Gotchas
|
||||
|
||||
- **The sizing block and its `WARNING` print ONLY after a clamp.** A fitting boot prints no `kv pool:` lines at all, so absence of a warning in old logs is NOT evidence of headroom.
|
||||
- **`deploy.sh` health-passes a clamped pool.** Container `active`, `/health` 200, in ~12 s. Only the ledger proves the pool size.
|
||||
- **Beware the false positive when grepping for a clamp**: the NOTE line contains the sentence "Lowering HALOGEN_KV_POOL_POSITIONS gives some back", which matches `LOWERING` case-insensitively. Grep `LOWERING THE POOL` / `cannot spare it`.
|
||||
- **`free`/`MemAvailable` cannot see this server.** Weights are pinned and the kernel counts locked pages as reclaimable page cache — `MemAvailable` read ~74 GiB while the engine held 103.5 of 121.2 GiB. Read the engine's lines instead.
|
||||
- **Host RAM is rounded DOWN when displayed.** `121` is `MemTotal 127104060 kB` = `121.2159`; subtracting displayed figures gives 29.3 instead of the true 29.5.
|
||||
- **Vendor "on the device" figures are pool + arena totals, not pool.** Reading them as pool-only makes a doubling look affordable.
|
||||
- **A 2.0 GiB firmware iGPU carve-out** is reported by the ledger and is not free memory.
|
||||
- `HALOGEN_MAX_TOK` is the arena / per-request generation budget (thinking included) — do not conflate with `HALOGEN_CTX` or the pool. `HALOGEN_KV_SLOTS` costs only ~111 MiB/slot, irrelevant to sizing.
|
||||
|
||||
## Three failure modes, worst last
|
||||
|
||||
1. **Silent clamp** — need exceeds budget; pool drops to the floor, service healthy. Caught only in the ledger.
|
||||
2. **Boot OOM** — enough `HALOGEN_MAX_TOK` and the arena alone beats the budget: `dmalloc: FAILED requesting 0.250 GiB after 39.970 GiB in 566 allocations (out of memory)`. Container stays `active / Up (starting)` forever; health never passes.
|
||||
3. **Minutes-long stall** — reserve cut so far that the engine holds most of a shared host. It prints its own note: neighbours and this server "can stall for minutes at a time at full CPU with no disk activity and no output, which is not a crash and needs no restart." Looks like a hang, invisible to `free`, hits co-tenants too.
|
||||
|
||||
## Verify
|
||||
|
||||
```
|
||||
podman logs frank-large 2>&1 | grep -aiE 'for the device|reserving the KV|ONE pool of|memory: [0-9.]+ GiB of weights|left for everything|LOWERING THE POOL|cannot spare it|listening on 127'
|
||||
```
|
||||
|
||||
Expect the budget line, `reserving the KV pool, <N> positions`, `ONE pool of <N> positions`, zero clamp matches, a `host memory left for everything else` figure, then `listening on 127.0.0.1:8730`. (A failing 7770 publish on restart is a stale-netns race — self-heals; `podman network reload --all` forces it.)
|
||||
|
||||
Then a real completion — `/health` 200 alone proves nothing:
|
||||
|
||||
```
|
||||
curl -s http://127.0.0.1:7770/v1/chat/completions -H 'Content-Type: application/json' -d '{"model":"frank-large","messages":[{"role":"user","content":"Reply with exactly: OK"}],"max_tokens":48,"reasoning_effort":"low"}'
|
||||
```
|
||||
|
||||
Expect `finish_reason: stop`. A silent client decodes **greedy** — this server ships no sampler defaults.
|
||||
|
||||
## Reference points (121.2 GiB host, 67.7 GiB weights, vision on)
|
||||
|
||||
| pool | max_tok | reserve | need | budget | outcome |
|
||||
|---|---|---|---|---|---|
|
||||
| 262144 | 32768 | 24 | 29.8 | 29.5 | boots (0.3 over), no sizing lines |
|
||||
| 524288 | 16384 | 24 | 28.6 | 29.5 | fits clean |
|
||||
| 524288 | 32768 | 24 | 37.0 | 29.5 | clamped, deploy green |
|
||||
| 524288 | 65536 | 24 | 46.5 | 29.5 | OOM, will not boot |
|
||||
| 524288 | 32768 | 15 | 37.0 | 38.5 | **both features, deployed** |
|
||||
| 524288 | 32768 | 16 | 37.0 | 37.5 | fits, footprint identical |
|
||||
|
||||
## Procedure
|
||||
|
||||
Compute `need` vs `budget` with unrounded RAM, then confirm against the engine's own printed requirement. After each deploy read the ledger for actual pool, clamp matches, **and the host-left line** — and A/B it: if two settings report the same `held`, the knob you turned doesn't do what its name says. Keep reserve and pool documented as a matched pair. Roll back with `git revert` (never `--no-verify`).
|
||||
Omp client config on blankpad: frank-large `maxTokens` must be ≤ 65536 (server 400s above the cap) and prompt+max_tokens must fit the pool or the request queues 3600 s then 503s.
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
---
|
||||
name: noctalia-custom-palette-recolor
|
||||
description: "Recolor a live Noctalia desktop (accent, terminal palette, terminal foreground) by cutting over to a custom palette instead of editing the community-palette cache, then re-rendering and reloading templates."
|
||||
---
|
||||
|
||||
# Noctalia custom-palette recolor
|
||||
|
||||
Recolor the running Noctalia shell + all themed apps without restarting the session.
|
||||
|
||||
## Why custom, never the community cache
|
||||
- `~/.local/state/noctalia/community-palettes/*.json` is a **sync cache**. `~/.local/state/noctalia/community-palettes/.catalog/palettes.json` carries an `md5` per palette and noctalia re-fetches from `https://api.noctalia.dev/palettes`. Edits there get reverted.
|
||||
- Custom palettes live at `~/.config/noctalia/palettes/<Name>.json` (`NOCTALIA_CONFIG_HOME` then `XDG_CONFIG_HOME` honored) and are never synced. Missing/invalid file → silent fallback to the builtin palette.
|
||||
- Palette JSON shape = the community file's shape: `dark`/`light` maps of `mPrimary`, `mOnPrimary`, `mSecondary`, `mTertiary`, `mError`, `mSurface`, `mSurfaceVariant`, `mOutline`, `mShadow`, `mHover` plus a `terminal` block (`foreground`, `background`, `normal.{black..white}`, `bright.{...}`, `cursor`, `cursorText`, `selectionFg`, `selectionBg`). NOTE: `noctalia theme -o` emits M3 snake_case tokens (`on_primary_container`, …) — that is the *generator* format, not this one. Copy an existing community JSON and mutate it with `jq`.
|
||||
|
||||
## Procedure
|
||||
1. Read the live scheme first — never assume: `noctalia msg color-scheme-get` → e.g. `community Gruber Darker`; `noctalia msg theme-mode-get`.
|
||||
2. Back up settings: `cp -a ~/.local/state/noctalia/settings.toml /tmp/noctalia-settings-backup-$(date +%s).toml`.
|
||||
3. Build the palette from the current one (jq keeps structure; no hand-editing 2 KB of JSON):
|
||||
```sh
|
||||
mkdir -p ~/.config/noctalia/palettes
|
||||
jq '.dark.mPrimary = "#f43841"
|
||||
| .dark.terminal.normal.yellow = "#f43841"
|
||||
| .dark.terminal.bright.yellow = "#ff4f58"
|
||||
| .dark.terminal.foreground = "#f43841"' \
|
||||
"$HOME/.local/state/noctalia/community-palettes/Gruber%20Darker.json" \
|
||||
> ~/.config/noctalia/palettes/"Gruber Red.json"
|
||||
```
|
||||
Prefer a hex already present in the palette (its own `mError` red / accent) so the theme stays internally consistent. Set BOTH `normal` and `bright` variants, and both `dark` and `light` if the user toggles modes.
|
||||
4. Switch (persists `theme.source = custom` + `theme.custom_palette`):
|
||||
`noctalia msg color-scheme-set custom "Gruber Red"` → `ok`; confirm with `noctalia msg color-scheme-get`.
|
||||
5. Re-render every configured template: `noctalia msg templates-apply`. Regenerates `~/.config/ghostty/themes/noctalia`, `~/.config/gtk-{3,4}.0/noctalia.css`, kcolorscheme, foot, wezterm, starship, etc. Some of those paths are symlinked into the dotfiles repo → they show up as modified files worth committing.
|
||||
6. Reload surfaces:
|
||||
- Compositor (focus border, `noctalia.kdl`): `niri msg action load-config-file`. `reload-config` is NOT a valid niri subcommand.
|
||||
- Ghostty: see the reload trap below.
|
||||
|
||||
## Verification
|
||||
- `ghostty +show-config | grep -E '^(foreground|palette)'` — proves the theme file resolves into the config (e.g. `foreground = #f43841`, `palette 3/11` red).
|
||||
- `noctalia config validate` → `✓ Config is valid`.
|
||||
- Visual: `noctalia msg screenshot-fullscreen` saves to `~/Pictures/screenshot_<ts>.png` (it ALSO overwrites the clipboard with the PNG — warn the user). `read` that PNG to confirm accent/toggle/border color.
|
||||
- `grep -c <old-hex> ~/.config/noctalia/palettes/*.json` → 0 for no leftovers.
|
||||
|
||||
## Track it in the dotfiles repo (command-center `~/.omp`)
|
||||
`scripts/deploy.sh` is a stow-equivalent: packages are home-relative trees under
|
||||
`dotfiles/<pkg>/`, and deploying replaces live files with symlinks into the repo. Mirror that
|
||||
shape for the new palette so `git pull` + `deploy.sh` is the whole propagation story:
|
||||
```sh
|
||||
mkdir -p ~/.omp/dotfiles/noctalia/.config/noctalia/palettes
|
||||
mv ~/.config/noctalia/palettes/"<Name>.json" ~/.omp/dotfiles/noctalia/.config/noctalia/palettes/
|
||||
ln -s "$HOME/.omp/dotfiles/noctalia/.config/noctalia/palettes/<Name>.json" \
|
||||
~/.config/noctalia/palettes/"<Name>.json"
|
||||
noctalia msg color-scheme-set custom "<Name>" # re-reads through the symlink; expect ok
|
||||
```
|
||||
Do the link by hand for one file instead of running `deploy.sh` — sync mode quarantines and
|
||||
replaces every divergent live file, which is broader than a single-palette change.
|
||||
|
||||
## Traps
|
||||
- **NEVER `kill -USR1` ghostty** to reload. It does not reload config on this fleet — it kills/respawns the terminal (took out Frank's window 2026-09-13; he said "stop killing the terminal"). Correct: the default keybind `ctrl+shift+,` = `reload_config`, per `ghostty +show-config --default`. Existing windows keep old colors until reloaded; new windows inherit immediately.
|
||||
- Palette hex values are NOT a proxy for what the user sees: in `Gruber Darker` the *accent* (`mPrimary`) is yellow `#ffdd33`, so "change the yellow" means the accent too, not just terminal index 3.
|
||||
- Terminal text turned into a saturated color makes ANSI 1/9 indistinguishable from default text (grep highlights flatten) — flag it and offer a lighter red.
|
||||
- Contrast sanity: `#f43841` on `#181818` ≈ 4.6:1 (dark-on-color beats white-on-color here, ~3.9:1, so keep `mOnPrimary` dark).
|
||||
- Revert = `noctalia msg color-scheme-set community "<original name>"`; the community cache is untouched by this whole flow.
|
||||
- `ghostty +show-config` prints only the delta from Ghostty defaults — a key whose value equals
|
||||
the default (e.g. `font-size = 12`) simply does not appear. Cross-check with
|
||||
`ghostty +show-config --default` before concluding a key is unset.
|
||||
- Generated theme files that are symlinked into the dotfiles repo (`gtk-3.0`/`gtk-4.0`
|
||||
`noctalia.css`, ghostty theme) show up as tracked modifications after `templates-apply`;
|
||||
commit them together with the new palette JSON so every machine gets the same recolor.
|
||||
@@ -0,0 +1,60 @@
|
||||
---
|
||||
name: omp-per-model-sampler-config
|
||||
description: "Set per-model sampler params and preserve_thinking in OMP's models.yml via compat.extraBody, and verify the exact wire body with an echo-capture profile."
|
||||
---
|
||||
|
||||
# OMP Per-Model Sampler Config (`compat.extraBody`)
|
||||
|
||||
`~/.omp/agent/models.yml` has **no per-model sampler keys**. Sampling is global (`config.yml`: `temperature`, `topP`, `topK`, `minP`, `presencePenalty`, `repetitionPenalty`; default `-1` = **not sent**). The per-model hook is `compat.extraBody`.
|
||||
|
||||
## Why it works
|
||||
`applyOpenAIExtraBody` runs **last** in the openai-completions builder — after `applyChatCompletionsCompatPolicy` — via `Object.assign(params, extraBody)`. So extraBody overrides global settings and compat-policy output.
|
||||
|
||||
## Recipe
|
||||
Use **wire names**, not OMP camelCase:
|
||||
|
||||
```yaml
|
||||
- id: frank-large
|
||||
compat:
|
||||
reasoningEffortMap:
|
||||
max: xhigh
|
||||
extraBody:
|
||||
temperature: 1.0
|
||||
top_p: 0.95
|
||||
top_k: 20
|
||||
min_p: 0.0
|
||||
presence_penalty: 0.0
|
||||
repetition_penalty: 1.0
|
||||
preserve_thinking: true
|
||||
```
|
||||
|
||||
## Two traps
|
||||
|
||||
1. **`preserve_thinking` is not user-settable.** `qwenPreserveThinking` is auto-derived in `buildOpenAICompat` from the *auto-detected* `thinkingFormat` + local baseUrl, **before** `applyCompatOverrides`. Setting `compat.thinkingFormat: qwen` in models.yml does **not** enable it. Custom-named models (`frank-large`) match no Qwen id pattern → use `extraBody: {preserve_thinking: true}`.
|
||||
2. **Never put `chat_template_kwargs` in `extraBody`.** `Object.assign` is shallow — it replaces the whole object and silently drops the `reasoning_effort` kwarg the compat policy set. Top-level `preserve_thinking` is honoured by halogen; use that.
|
||||
|
||||
## Gotcha: silent greedy decode
|
||||
halogen-flash-server has **no server-side sampler defaults** — `temperature` absent or `0` = greedy. If OMP sends nothing, the endpoint decodes greedy while looking configured.
|
||||
|
||||
## Verify the exact wire body (echo-capture)
|
||||
Don't trust the YAML — capture what OMP actually emits.
|
||||
|
||||
1. Echo server on `127.0.0.1:18099` that dumps the JSON body to a file and returns a canned `chat.completion` (include `reasoning_content` so thinking paths exercise).
|
||||
2. Copy the **real** models.yml into a throwaway profile with only the baseUrl swapped:
|
||||
```bash
|
||||
sed 's|http://<host>:7770/v1|http://127.0.0.1:18099/v1|' \
|
||||
~/.omp/agent/models.yml > ~/.omp/profiles/wiretest/agent/models.yml
|
||||
```
|
||||
3. Run and inspect:
|
||||
```bash
|
||||
omp --profile wiretest --model "<provider>/<model>" -p "hi" \
|
||||
--no-tools --no-session --no-extensions --no-skills --no-rules
|
||||
jq 'del(.messages, .tools)' last-body.json
|
||||
```
|
||||
Confirm every intended field is present with the right value.
|
||||
|
||||
## Verify a field is *honoured*, not just accepted
|
||||
Unknown fields often return 200 anyway. Prove behavior with a **prompt-token delta**: replay an assistant turn carrying a long `reasoning_content`, then compare `usage.prompt_tokens` with the flag true vs false. A large delta means the field changed template rendering; zero delta means it was ignored.
|
||||
|
||||
## Cleanup
|
||||
Trash the probe profile and echo server (`profiles/.AGENTTRASH`), never `rm`.
|
||||
@@ -1,35 +1,22 @@
|
||||
# Consolidated Memory
|
||||
## System & Desktop Environment
|
||||
- **Noctalia (Niri) DE**: Bin `/usr/bin/noctalia`. Configs: `~/.config/noctalia/config.toml`, `noctalia.kdl`. IPC: `noctalia msg <cmd>` (replaces `qs -c noctalia-shell ipc`). Key cmds: `panel-toggle`, `session`, `lock`, `launcher`. App templates: `/usr/share/noctalia/assets/templates/`. Palette gen: `noctalia theme [image]`. GTK accent: `#b267e4`.
|
||||
- **Fonts & AA**: Ghostty (`font-subpixel-render=off`), Alacritty (`font.antialias=false`). Ghostty fix: replace `font-hinting = hinting` with `freetype-load-flags = hinting,light` (line 10).
|
||||
- **Frank Desktop**: Cursor size 36 (`gsettings`, `settings.ini`, `XCURSOR_SIZE=36`). Theme: `capitaine-cursors`.
|
||||
- **Authenik (2026.8)**: Outpost caches claims per session (1-24h TTL). Pitfall: silent 403s post-group-add despite correct membership.
|
||||
|
||||
## OMP Harness & Server App Config
|
||||
- **Location**: `~/.omp` (config/dotfiles), `~/Projects/serverAppConfig` (cloned).
|
||||
- **Repository Details**: Remote repo `serverAppConfigs` (plural), local dir `serverAppConfig` (singular). Head `701ab14` on `main` (tracks `origin/main`). HTTP transport with embedded dank token, no SSH keys.
|
||||
- **Structure** (308 files, 4.2 MB):
|
||||
- `dankclaw/`: Dankclaw stack definitions.
|
||||
- `dankserver/`: Inference backend config.
|
||||
- `frankbook-pro/`: 7 quadlet units (sonarr, radarr, lidarr, readarr, prowlarr, qbittorrent, gluetun).
|
||||
- `shared/`: Homepage (html/css/js + services.json), alloy, loki, prometheus, searxng.
|
||||
- `tests/`: 47 files, E2E suite.
|
||||
- `serverAppConfigs-docs/`: 115 files, Architecture KB (deployment flow, network/storage/testing policy, container netns, Dankclaw service pages).
|
||||
- `old/`, `report/`, `scripts/`, `.githooks/`, `AGENTS.md`: Legacy, reports, tooling, hooks.
|
||||
- **Recent Commits**: Observability quadlet cutover (loki/alloy/comfyui images, grafana OAuth secret per-service env seeding, docs commit recording exposure posture + unconfigured state).
|
||||
## Inference & Runtime
|
||||
- **Frank-Large**: Sampler defaults overridden from halogen/greedy: `temp=1.0, top_p=0.95, top_k=20, min_p=0.0, presence_penalty=0.0, repetition_penalty=1.0`. Added `preserve_thinking=true` (retains thinking blocks across turns). Config: `agent/models.yml`. Deployed to `dank/command-center` (dankclaw). Live effect on next config read (no restart).
|
||||
- **Frank-Small**: Uses checkpoint's fixed Qwen3.6 template. `deploy-plan.py` mapping is vestigial.
|
||||
- **Halogen Runtime**: Baked-in chat template (no file swap). Accepts `chat_template_kwargs`: `enable_thinking`, `preserve_thinking`, `reasoning_effort`.
|
||||
- **FLM NPU (Dankclaw)**: `gemma4-it:e4b` on port 7771. FIFO queue (~7-11s switch). Supports PNG/JPEG; rejects WebP (convert first). Requires `thinkingLevelMap` in `models.json`. Pitfall: missing `.xclbin` symlinks under `~/.config/flm/xclbins/`.
|
||||
|
||||
## Dotfiles & Git Workflow
|
||||
- **State Inspection**: `git status --short | git branch --show-current | git log --oneline HEAD..@{u}`. Untracked dirs: `.pre-pull-backup/`, `home/`.
|
||||
- **Modified Configs**: `alacritty.toml`, `config.ghostty`, `noctalia.css` (gtk3/4), niri `.kdl` files. Shift to noctalia theme.
|
||||
- **Ghostty Fix**: Replace `font-hinting = hinting` with `freetype-load-flags = hinting,light` (line 10).
|
||||
- **Commit/Push Pattern**: `git add <file> && git commit -m "<msg>" && git push`. Mitigate LFS lock warnings via `git config lfs.http://<repo>/info/lfs.locksverify true`.
|
||||
- **Process Reload**: Ghostty reload via USR1: `pgrep ghostty | while read pid; do /usr/bin/kill -USR1 "$pid"; done`.
|
||||
## Configuration & Repository
|
||||
- **OMP Harness**: Repo at `~/.omp`. Cloned `serverAppConfig` to `~/Projects/serverAppConfig` (local singular vs remote plural `serverAppConfigs`). HTTP transport with embedded dank token (no SSH keys). HEAD: 701ab14 (main tracks origin/main).
|
||||
- **Structure**: 308 files, 4.2 MB. Includes `dankclaw/`, `dankserver/`, `frankbook-pro/` (7 quadlets), `shared/` (Homepage, alloy, loki, prometheus, searxng), `tests/` (47 E2E), `serverAppConfigs-docs/` (115). Legacy: `old/`, `report/`, `scripts/`, `.githooks/`, `AGENTS.md`.
|
||||
- **Recent**: Observability quadlet cutover (loki/alloy/comfyui images, grafana OAuth secret per-service env seeding).
|
||||
- **Git Workflow**: Branch `main`. Untracked: `.pre-pull-backup/`, `home/`. LFS locking notice is advisory. Mitigate via `git config lfs.http://<repo>/info/lfs.locksverify true`. Pattern: `git add <file> && git commit -m "<msg>" && git push`.
|
||||
|
||||
## Handy Application Lifecycle
|
||||
- **Binary**: `/usr/bin/handy`.
|
||||
- **Kill**: `pkill -f handy`.
|
||||
- **Start**: `hub op=start, application=/usr/bin/handy, pty=true, persist=true, ready={log:'.*', timeout:10}`.
|
||||
- **Status**: Persistent daemon running. 69 catalog models seeded.
|
||||
|
||||
## Device & Input Permissions
|
||||
- **Issue**: `Platform error: permission denied opening 16 device node(s) under /dev/input` causing keyboard listener failure.
|
||||
- **Diagnosis**: `/dev/input/*` owned by `root:input` with `crw-rw----` (660). User `blank` was missing the `input` group.
|
||||
- **Resolution**: `sudo usermod -aG input blank`.
|
||||
- **Pitfalls**:
|
||||
1. `usermod` without `sudo` fails to lock `/etc/passwd`.
|
||||
2. `sudo` password entry in CLI environment requires PTY for reliable input.
|
||||
## Operations & Services
|
||||
- **Handy App**: Binary `/usr/bin/handy`. Kill: `pkill -f handy`. Start: `hub op=start, application=/usr/bin/handy, pty=true, persist=true, ready={log:'.*', timeout:10}`. Status: Up, 69 catalog models seeded.
|
||||
- **Device Permissions**: `/dev/input/*` are `root:input` (660). User `blank` must be in `input` group (`sudo usermod -aG input blank`). Pitfall: `usermod` without sudo fails to lock `/etc/passwd`; `sudo` password entry in this CLI environment requires PTY.
|
||||
- **Ghostty Reload**: `pgrep ghostty | while read pid; do /usr/bin/kill -USR1 "$pid"; done`.
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
- Frank's frank-large ceiling is now 200,000 context in ~/.omp/agent/models.yml (provider llamacpp (dankclaw), committed 60dc0bb to dank/command-center 2026-09-13), while halogen on 192.168.0.143:7770 still serves context=262144 — a deliberate under-serve, not drift. Convention when changing any contextWindow there: read the served value from curl baseUrl/health (it reports context, model, vision.enabled) and check KV-pool admission before/after — admission reserves prompt + max_tokens against the pool (401,408 positions since 2026-09-13), so contextWindow + maxTokens must stay under it or the request hangs the full 3600 s queue timeout before a 503. maxTokens stays pinned at 65536 because HALOGEN_MAX_TOKENS_CAP 400s anything larger. Also: OMP reads models.yml only at startup, so a running session keeps the old ceiling; tell the user new omp invocations pick up the change.
|
||||
- Frank's terminal font stack on Dankware: package ttf-terminus-nerd (Arch, group nerd-fonts), which provides the TERMINESS outline derivative — families "Terminess Nerd Font" / " Mono" / " Propo". The bitmap original terminus-font is NOT installed, so classic-Terminus crispness depends entirely on 1-bit hinted rendering. Crisp/bitmap look = freetype-load-flags = hinting,monochrome (monochrome = 1-bit, disables AA; the light flag stays in the resolved value but is inert once monochrome is on, per ghostty.5.md). Sizing rule that matters: pixel cell = pt × (96/72) × monitor_scale, and the crisp sweet spot is when that lands on Terminus' native bitmap heights (8x16, 9x18, 10x20, 11x22, 12x24). On Frank's eDP-1 (1920x1080 @ scale 1.25) font-size 12 → 20px → exactly the 10x20 grid; 14pt → 23.3px, fractional and blurry regardless of flags. Check scale with niri msg outputs. Also: ghostty +show-config prints only values differing from default, and Ghostty's default font-size IS 12 — so a 12pt setting vanishes from the diff output; confirm against +show-config --default before concluding the key was ignored.
|
||||
- NEVER send SIGUSR1 to ghostty on Frank's workstations — it does not reload the config, it kills/respawns the terminal (observed 2026-09-13: PID churn, Frank said "stop killing the terminal"). The old recipe in agent/memories/--home-blank-.omp--/MEMORY.md and skills/dotfiles_git/scripts/reload_ghostty.sh ("pgrep ghostty | while read pid; do kill -USR1 $pid; done") is WRONG for ghostty 1.3.1. Correct way to apply a changed ghostty theme/config without losing shells: press the default keybind ctrl+shift+, (action reload_config) in each window — confirmed as the default in ghostty +show-config --default. For applying theme changes desktop-wide without touching terminals: noctalia msg templates-apply regenerates rendered theme files, and niri msg action load-config-file reloads the compositor (reload-config is NOT a valid niri subcommand). Custom noctalia palettes live at ~/.config/noctalia/palettes/Name.json and are selected with noctalia msg color-scheme-set custom "Name"; that source is immune to the community-palette catalog/md5 sync, unlike editing the cache in ~/.local/state/noctalia/community-palettes/. Also: noctalia msg screenshot-fullscreen saves to ~/Pictures (no need to scrape the PNG out of the clipboard with wl-paste).
|
||||
- In OMP's ~/.omp/agent/models.yml there are NO per-model sampler keys. Sampling params (temperature, topP, topK, minP, presencePenalty, repetitionPenalty) are GLOBAL settings in config.yml, each defaulting to -1 = "do not send". The only per-model hook is compat.extraBody — a Recordstring, unknown of extra top-level fields merged into every request body. It is applied LAST in the openai-completions builder (applyOpenAIExtraBody runs after applyChatCompletionsCompatPolicy, via Object.assign), so extraBody wins over anything the compat policy or global settings set. Use wire names (top_p, top_k, min_p, presence_penalty, repetition_penalty), not OMP's camelCase setting names. Two traps that cost real debugging time: 1. preserve_thinking is NOT user-settable in models.yml. qwenPreserveThinking is auto-derived inside buildOpenAICompat from the AUTO-DETECTED thinkingFormat plus a local (loopback/RFC1918) baseUrl — and that derivation happens BEFORE applyCompatOverrides. So writing compat.thinkingFormat: qwen in models.yml does NOT turn on preserve_thinking. For a custom-named model (e.g. frank-large, which matches no Qwen id pattern) the only path is extraBody: { preserve_thinking: true }. 2. NEVER put chat_template_kwargs inside extraBody. Object.assign is shallow, so it replaces the whole chat_template_kwargs object and silently drops the reasoning_effort kwarg the compat policy already put there. Top-level preserve_thinking is honoured by halogen-flash-server (its own 400 message says the field "may also be sent as top-level fields"), so top-level is both sufficient and safe. Why it mattered: halogen-flash-server has no server-side sampler defaults — temperature absent or 0 is greedy decode. OMP sent nothing (global -1), so the endpoint was decoding greedy while appearing configured. _(context: Verified 2026-09-13 on the Dank fleet while pinning Qwen3.8-Flash-Next recommended sampling (temp 1.0 / top_p 0.95 / top_k 20 / min_p 0.0 / presence_penalty 0.0 / repetition_penalty 1.0) plus preserve_thinking onto frank-large. Ground truth read from the installed bundle: pi-ai/src/providers/openai-completions.ts (applyOpenAIExtraBody applied last), pi-ai/src/providers/openai-shared.ts (applyChatC)_
|
||||
- Frank's Gitea lives on Dankclaw at http://192.168.0.143:3000, single org/user dank. Repo inventory (verified 2026-09-12 via /api/v1/user/repos): agent (default master), command-center (main — this is the ~/.omp dotfiles/KB repo), frank-llm-bench (main), serverAppConfigs (main), vllmScripts (main). LESSON — never clone from a repo name Frank states verbally; resolve the exact full_name via the Gitea API first. He said "serverAppConfig"; the real repo is serverAppConfigs (plural). Cloning the guessed name would 404 with no useful signal. Working procedure: read the dank HTTP token from the existing origin URL in ~/.omp (git remote -v) — do NOT copy that token into memory, docs, or skills; reference its location only. Then GET /api/v1/user/repos and match on the real name/case/plurality before cloning. Local-vs-remote naming: the clone was placed at ~/Projects/serverAppConfig (singular, as Frank explicitly requested) while origin points at the plural repo. The path mismatch is intentional, not drift — pull/push work normally. Repo layout: dankclaw/, dankserver/, frankbook-pro/ (7 quadlet units: sonarr, radarr, lidarr, readarr, prowlarr, qbittorrent, gluetun), shared/ (homepage, alloy, loki, prometheus, searxng), tests/ (47-file E2E suite), serverAppConfigs-docs/ (115-file KB — read its index.md before touching the stack). _(context: Frank asked to "pull my serverAppConfig repository into ~/Projects/serverAppConfig"; Gitea API revealed the plural name. Credential handling: token reused from existing ~/.omp remote, deliberately not persisted here.)_
|
||||
- Ghostty 1.3.1 (and the 1.3.x line) has NO font-hinting and NO font-subpixel-render config key. The only font-smoothing key is freetype-load-flags, a comma-separated list: hinting, force-autohint, monochrome, autohint, light (each default-enabled except monochrome/force-autohint; prefix no- to disable). Ground truth: /usr/share/ghostty/doc/ghostty.5.md:598-628. To actually DISABLE anti-aliasing you need freetype-load-flags = hinting,monochrome (docs line 617: monochrome = 1-bit rendering, disables AA). Note hinting,light is a NO-OP — both are already Ghostty defaults. Verification workflow before editing any ghostty key: ghostty +validate-config (exit 0 = valid) plus grep the manpage for the key name; an unknown key silently does nothing useful and +validate-config is the authoritative gate. This matters because a poisoned memory claim about font-subpixel-render/font-hinting caused 3 wasted commits (4c84f02, df33310, 268dcbd) editing a nonexistent key on 2026-09-11. _(context: Verified 2026-09-12 against ghostty 1.3.1-arch2.2 manpage and ghostty +validate-config on Dankware. Corrects contradictory entries in agent/memories/--home-blank-.omp--/learned.md (line 2 asserts font-subpixel-render is the key; it is not).)_
|
||||
- Ghostty's font antialiasing is controlled by font-hinting = no-hinting in the config file, not font-subpixel-render = off as the Noctalia reference skill states. When editing ghostty config, check /usr/share/ghostty/doc/ghostty.5.md or src/config/Config.zig — ghostty's --help confirms this. Invalid field causes font-subpixel-render: unknown field on restart. _(context: Discovered when user reported "font-subpixel-render: unknown field" after my initial edit to ghostty config)_
|
||||
|
||||
@@ -1 +1 @@
|
||||
Current state: OMP harness at ~/.omp, serverAppConfig cloned to ~/Projects (HTTP/dank token, head 701ab14). Git workflow relies on state inspection, USR1 ghostty reloads, and LFS lock mitigation. Handy runs as persistent hub daemon (69 models). Input permissions fixed for user 'blank' (root:input group, 660 perms). Dotfiles shifted to noctalia theme with Ghostty font-hinting adjustment. Reference consolidated details for repo structure, commit patterns, and CLI sudo/PTY pitfalls.
|
||||
Context: OMP repo at ~/.omp with serverAppConfig (local) <-> serverAppConfigs (remote). Frank-large uses temp=1.0, preserve_thinking=true; frank-small uses Qwen3.6. FLM NPU (port 7771) needs .xclbin symlinks and WebP conversion. Authenik caches claims (1-24h), watch for post-group-add 403s. Handy daemon runs via hub (pty:true); ensure user 'blank' is in 'input' group for /dev/input access. Git LFS locks are advisory; use USR1 for Ghostty reload. Current shift: noctalia theme & font-hinting fixes.
|
||||
|
||||
@@ -1,5 +1,16 @@
|
||||
# Raw Memories
|
||||
|
||||
## 01a0993b-f83f-7331-9cad-fff3fc7f3070
|
||||
updated_at: 1789286338
|
||||
Target: agent/models.yml (frank-large entry). Sampler defaults overridden from halogen/greedy to temp=1.0, top_p=0.95, top_k=20, min_p=0.0, presence_penalty=0.0, repetition_penalty=1.0. Added preserve_thinking=true to retain thinking blocks across turns. Deployed to dank/command-center on dankclaw. Live effect triggers on next config read; no container restart required. Git LFS locking notice is advisory, does not block pushes. Repo path: ~/.omp.
|
||||
|
||||
## 01a096d7-c1b8-7291-b467-a8521fe9c3c6
|
||||
updated_at: 1789267061
|
||||
Noctalia DE (Niri-based): bin /usr/bin/noctalia; configs ~/.config/noctalia/config.toml + noctalia.kdl. IPC via noctalia msg <cmd> (replaces qs -c noctalia-shell ipc call). Key cmds: panel-toggle, session, lock, launcher. App templates /usr/share/noctalia/assets/templates/. Palette gen noctalia theme [image]. GTK accent #b267e4. Text AA: Ghostty font-subpixel-render=off, Alacritty font.antialias=false.
|
||||
FLM NPU (Dankclaw): gemma4-it:e4b, port 7771. Supports PNG/JPEG; rejects WebP (convert first). Requires thinkingLevelMap in models.json. FIFO queue, ~7-11s model switch. Pitfall: missing .xclbin symlinks under ~/.config/flm/xclbins/ cause failures.
|
||||
Frank desktop: cursor 36 (gsettings org.gnome.desktop.interface cursor-size, GTK settings.ini, XCURSOR_SIZE=36), theme capitaine-cursors. Authenik 2026.8 outpost caches claims per session (1-24h TTL), causes silent 403s post-group-add despite correct membership.
|
||||
Halogen runtime (frank-large): baked-in chat template, no file swap. Accepts chat_template_kwargs (enable_thinking, preserve_thinking, reasoning_effort). frank-small uses checkpoint's fixed Qwen3.6 template; deploy-plan.py mapping is vestigial.
|
||||
|
||||
## 01a09618-6a77-71d5-a5b2-36e82045b695
|
||||
updated_at: 1789227719
|
||||
OMP harness config/dotfiles repo located at ~/.omp.
|
||||
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
thread_id: 01a096d7-c1b8-7291-b467-a8521fe9c3c6
|
||||
updated_at: 1789267061
|
||||
|
||||
Noctalia (Niri) DE config & IPC patterns, FLM NPU constraints & WebP pitfall, Frank's desktop settings & cursor sizing, Authenik session claim caching, Halogen runtime baked-in template handling.
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
thread_id: 01a0993b-f83f-7331-9cad-fff3fc7f3070
|
||||
updated_at: 1789286338
|
||||
|
||||
Pinned frank-large sampler settings (temp=1.0, top_p=0.95, top_k=20, min_p=0.0, presence_penalty=0.0, repetition_penalty=1.0) + preserve_thinking=true in agent/models.yml. Pushed to dank/command-center (Gitea, 192.168.0.143:3000). Applies on next config read without service restart.
|
||||
@@ -0,0 +1 @@
|
||||
Standardized workflow for dotfile configuration management, Git state verification, LFS-aware pushing, and application reloading.
|
||||
+1
@@ -0,0 +1 @@
|
||||
Updated niri layouts to match noctalia palette and IPC commands.
|
||||
+1
@@ -0,0 +1 @@
|
||||
git add $1 && git commit -m "$2" && git push
|
||||
+1
@@ -0,0 +1 @@
|
||||
pgrep ghostty | while read pid; do /usr/bin/kill -USR1 "$pid"; done
|
||||
+1
@@ -0,0 +1 @@
|
||||
freetype-load-flags = hinting,light
|
||||
+1
@@ -0,0 +1 @@
|
||||
:root { --accent: #b267e4; }
|
||||
@@ -1 +0,0 @@
|
||||
Workflow for managing dotfiles and serverAppConfig repos. Includes state inspection, targeted config edits, commit/push with LFS awareness, and USR1 process reloads.
|
||||
@@ -1 +0,0 @@
|
||||
Fix Ghostty font rendering by replacing 'font-hinting = hinting' with 'freetype-load-flags = hinting,light' at line 10 of config.ghostty.
|
||||
@@ -1,4 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Checks git status, branch, and unpushed logs
|
||||
# Outputs short status, current branch, and HEAD vs upstream diff
|
||||
git status --short | git branch --show-current | git log --oneline HEAD..@{u}
|
||||
@@ -1,3 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Sends USR1 signal to reload Ghostty config
|
||||
grep ghostty | while read pid; do /usr/bin/kill -USR1 "$pid"; done
|
||||
@@ -1,4 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Standard commit/push pattern with LFS lock mitigation
|
||||
LFS_VERIFY=true git config lfs.http://$(git remote get-url origin)/info/lfs.locksverify true
|
||||
git add "$1" && git commit -m "$2" && git push
|
||||
@@ -0,0 +1 @@
|
||||
Lifecycle and dependency management for the handy daemon, covering hub deployment, model seeding, and /dev/input permission fixes.
|
||||
+1
@@ -0,0 +1 @@
|
||||
Resolved 'permission denied opening device node(s)' by adding user to 'input' group (660 perms). Sudo requires PTY.
|
||||
+1
@@ -0,0 +1 @@
|
||||
sudo usermod -aG input blank
|
||||
+1
@@ -0,0 +1 @@
|
||||
pkill -f handy; hub op=start, application=/usr/bin/handy, pty=true, persist=true, ready={log:'.*', timeout:10}
|
||||
+1
@@ -0,0 +1 @@
|
||||
application: /usr/bin/handy\npty: true\npersist: true\nready: {log: '.*', timeout: 10}
|
||||
@@ -1 +0,0 @@
|
||||
Manage the handy application daemon. Covers binary paths, pkill termination, hub startup with persistent/PTY settings, and readiness timeout.
|
||||
@@ -1 +0,0 @@
|
||||
Status: Up. Catalog models seeded: 69. Persistent daemon. Ready timeout: 10s.
|
||||
@@ -1,3 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Gracefully terminates handy process
|
||||
pkill -f handy
|
||||
@@ -1,3 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Starts handy via hub with PTY and persistence
|
||||
hub op=start, application=/usr/bin/handy, pty=true, persist=true, ready={log:'.*', timeout:10}
|
||||
@@ -0,0 +1 @@
|
||||
Manages frank-large/small inference routing, FLM NPU constraints, and Halogen runtime kwargs for thinking block preservation.
|
||||
+1
@@ -0,0 +1 @@
|
||||
Pinned sampler: temp=1.0, top_p=0.95, top_k=20. Live config read on next cycle.
|
||||
+1
@@ -0,0 +1 @@
|
||||
ls -l ~/.config/flm/xclbins/ | grep -E '\.xclbin' || echo 'Missing symlinks'
|
||||
+1
@@ -0,0 +1 @@
|
||||
curl -s localhost:7771/status | jq .queue
|
||||
+1
@@ -0,0 +1 @@
|
||||
enable_thinking: true\npreserve_thinking: true\nreasoning_effort: medium
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"thinkingLevelMap": true, "gemma4-it": "e4b"}
|
||||
@@ -1 +0,0 @@
|
||||
Resolve /dev/input permission denied errors. Targets root:input group assignment (660 permissions), sudo/PTY requirements, and /etc/passwd locking.
|
||||
-2
@@ -1,2 +0,0 @@
|
||||
1. usermod without sudo fails to lock /etc/passwd.
|
||||
2. sudo password entry in CLI requires PTY for reliable input.
|
||||
@@ -1,3 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Adds user to input group, requires sudo to lock /etc/passwd and PTY for CLI password
|
||||
sudo usermod -aG input $USER
|
||||
-3
@@ -1,3 +0,0 @@
|
||||
Diagnose /dev/input/* nodes: ls -la /dev/input
|
||||
Check groups: groups $USER
|
||||
Expected: root:input with crw-rw---- (660)
|
||||
@@ -1,10 +1,22 @@
|
||||
SERVICE: frank-large (rootless Quadlet, boot-persistent) on dankclaw.
|
||||
Unit: frank-large.service | Container: frank-large.
|
||||
# dankclaw Deployment & Model Services
|
||||
|
||||
PORTS: Engine :8730 (container loopback, unauth), Front-end :8731, Published :7770.
|
||||
## frank-large (Quadlet Service)
|
||||
Deployed as a rootless Quadlet service (`frank-large.service`) on dankclaw. Hosts ~68 GiB weights and a 524,288-position KV pool (~14.4 GiB). HALOGEN_KV_SLOTS reduced to 3, stabilizing total memory at ~103.4 GiB within the 121 GiB budget. Admission is pool-bound, capping at 3 simultaneous full-length requests.
|
||||
|
||||
CONSTRAINTS: Weights pinned (~68 GiB). Env vars to avoid naming: TEMP, HOST, GPU_MAX_HEAP_SIZE (HIP runtime reads bare TEMP for JIT cache path).
|
||||
### Ports & Logging
|
||||
- Engine: :8730 (loopback), Front-end: :8731, Published: :7770
|
||||
- Logging: `podman logs frank-large` (full/filtered), `journalctl --user -u frank-large`
|
||||
- Env Vars: Avoid `TEMP`, `HOST`, `GPU_MAX_HEAP_SIZE` (HIP runtime reads bare `TEMP`).
|
||||
|
||||
TEST_ENV: pyyaml missing for test suite (uv available, pip missing on system python3). Most suite failures are pre-existing environment issues, not commit regressions.
|
||||
### Sampling & API Quirks
|
||||
- `frank-large` defaults to greedy; `frank-small` defaults to sampling (temp=1.0, top_k=20, top_p=0.95). Force small determinism via `temperature: 0` or `--sampling-defaults none`.
|
||||
- `preserve_thinking` is per-request (client-side `chat_template_kwargs`), not controlled by HALOGEN_* env vars.
|
||||
- `max_tokens: 200` with empty content indicates thinking consumed budget. frank-small returns 200 for unknown fields. File-cache shortage causes uninterruptible sleep, not OOM. `host_reserve_gib=24` protects n-gram table.
|
||||
- Tests: 285/286 pass (test 73 pre-existing comfyui selector bug). `pyyaml` missing on system python3; `uv` available.
|
||||
|
||||
LOG_RETRIEVAL: podman logs frank-large (full); podman logs frank-large 2>&1 | grep -E '^(dmalloc|kv pool):' (filtered); journalctl --user -u frank-large (journald).
|
||||
## Marreta & Authentik Guard Chain
|
||||
Deployed via podman compose, sharing gluetun egress with searxng. Caddy TLS edge routes through Anubis (:8923) → Authentik outpost → internal :8017 → marreta upstream.
|
||||
- Auth Flow: Provider-first creation → route flip (vhost `reverse_proxy anubis:8923`) → deploy.
|
||||
- Resolved Login-Wall: Null `ProxyProvider.application` and missing auth/authz/invalidation flows crashed the Rust outpost. Fix: populated flows, linked `Application(slug=marreta)`, restarted services.
|
||||
- Pitfalls: Host probe (`localhost:8017`) returns HTTP 000 due to Caddy netns; probe internally or grep config. Non-browser clients fail JS challenges. Audit service-to-service traffic for backend URLs hitting guarded hostnames. IdP, Gitea (git smart-HTTP), and self-auth services are exempt.
|
||||
- Verification: E2E test (`tests/e2e/specs/16-marreta.spec.ts`) validates homepage tile routing.
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
- frank-large (halogen-flash-server, Dankclaw) pool history and post-restart behavior, measured 2026-09-13: pool trimmed 524288 → 401408 (deployed, repo commits 91406af + 27e6335) to restore co-tenant headroom. Measured boot ledger at 401408/MAX_TOK=32768/reserve 15: 68.0 weights + 11.0 KV + 21.0 working = 100.0 GiB held, host left 9.1 GiB / 1396 contiguous 2 MiB blocks (vs 7.1 / 310 at 524288), engine printed need ~31.5 GiB vs modelled ~33.4, and the co-tenant stall NOTE no longer prints (threshold is somewhere below 9.1 GiB / 1396 blocks). TWO new facts: (1) On the FIRST request after any (re)start the engine can go silent ~45-60 s — /health flips to engine_unresponsive "no PONG within 30s" and the front-end 503s, then self-recovers. Do not restart the unit over it; the quadlet HealthStartPeriod=300s covers it. First completion attempt timed out during this window; a retry 20 s later returned instantly. (2) Host-left gain (+2.0 GiB) came in below the modelled +3.4 because the engine holds freed KV space as working slack (working 21.0 at 401k vs 20.6-ish at 524k with arena). The omp models.yml on blankpad (/home/blank/.omp/agent/models.yml) had frank-large maxTokens: 262144 — above halogen's 65536 cap and a 503-queue hazard after the pool cut; fixed to 65536, and the stale flm (dankclaw-npu) provider + its modelRoles (vision/tiny/task) were removed per the AGENTS.md route map (vision→frank-large, tiny→frank-small, task→frank-large:medium). _(context: frank-large KV pool trim to 401408 on Dankclaw, 2026-09-13, followed by OMP models.yml/config.yml cleanup on blankpad.)_
|
||||
- Dankclaw host swap (as of 2026-09-12): 64 GiB file at /swap.img, ext4 on /dev/nvme0n1p2, fallocated hole-free, driven by /etc/fstab line 12 (/swap.img none swap sw 0 0) which generates the swap.img.swap systemd unit — fstab is the only control point, there is no hand-written unit and no repo file, so deploy.sh cannot see swap state. vm.swappiness=60 (distro default, UNTESTED against this workload), zswap disabled. Raised from 8 GiB; 748 GiB still free on /. The old 8.1 GiB file is staged at dankclaw:~/.AGENTTRASH/20260912-swapfile-8g/swap.img awaiting Frank's approval to purge. Important framing: swap on this host protects the ~28 co-tenant containers, NOT frank-large — its ~68 GiB of pinned weights are not relieved by swap, and paging the KV pool (which IS anonymous) would be worse than the OOM kill it prevents, so if the box thrashes the knob is lower swappiness or a cgroup cap, not more swap. _(context: Raised swap on Dankclaw 2026-09-12 after the frank-large reserve-15 config left only ~7.1 GiB for co-tenants. Documented in serverAppConfigs-docs/Dankclaw/Swap Configuration.md and AGENTS.md memory-model section.)_
|
||||
- In the serverAppConfig repo, ./tests/run.sh exits 1 on a **clean tree** because of one pre-existing failure: tests/comfyui_rocm.bats test 73 "comfyui Containerfile is based on the gfx1151 torch image". It is a test-side selector bug, not a product regression — its find ... | head -1 picks dankclaw/alloy/Containerfile instead of the ComfyUI one, so the assertion reads the wrong file. Verify before blaming your own change: a good run reports 285 ok plus this single not ok 73. Confirmed present at HEAD across several sessions (2026-09-12 frank-large work), independent of frank-large/Caddy/quadlet edits. Do NOT treat a green deploy as blocked by it, and do NOT "fix" it by weakening the assertion — the correct fix is to target the actual ComfyUI Containerfile path. Note deploy.sh gates on its own per-service health plus the Playwright e2e suite, not on tests/run.sh, so this failure does not block deploys. _(context: Every ./tests/run.sh run during the 2026-09-12 frank-large KV-pool/reserve work returned exit=1 with exactly not ok 73 comfyui Containerfile is based on the gfx1151 torch image while 285 tests passed, including on commits where nothing ComfyUI-related changed.)_
|
||||
- Frank resolves contested tuning calls by **running the experiment**, not by reading the argument. On 2026-09-12 he overruled documentation-based pushback twice in a row with "lets just try it". Working with this, rather than against it: when he pushes back on a knob, state the prediction numerically up front, then run it and report measured vs predicted — he engages with that and it twice produced a better model than the docs (the arena linearity, and the vision-tower term). Corollaries: (1) get the rollback staged and named BEFORE the risky deploy, because the experiment may take production down — the 65536 trial OOMed frank-large for ~2 minutes; (2) use deploy.sh --skip-e2e for risky single-service experiments so the 4-minute e2e gate is not sitting on top of an outage; (3) after a failure, git revert sha + redeploy restores in ~10s, because the weights are already page-cached. Also learned the hard way: when a config experiment ends in a state that quietly reverses the user's original request (32768 + KV_POOL_FIT clamp meant the pool stayed 262144, i.e. the doubling never happened), say so plainly — do not let a green health check imply the goal was met. Separately, on log forensics: journalctl --user -u frank-large.service did NOT reach back to the 2026-09-11 boot even when asked with --since 2026-09-11 (rootless user journal retention is short). To compare against a container's ORIGINAL startup ledger, capture podman logs BEFORE the first deploy of the session — that is the only reliable copy of pre-change boot state. _(context: frank-large KV-pool doubling work on 2026-09-12: Frank overruled doc-based pushback twice ("let's just try it") — once raising HALOGEN_MAX_TOK to 65536 (OOMed the production service for ~2 min) and once back to 32768, which quietly un-did the doubling he had originally asked for. Also: journalctl --user retention for frank-large.service did not cover the 2026-09-11 boot even when queried with --si)_
|
||||
|
||||
@@ -1 +1 @@
|
||||
Frank-large rootless Quadlet service on dankclaw. Ports 7770/8731/8730. Weights ~68 GiB. Avoid TEMP/HOST/GPU_MAX_HEAP_SIZE env vars. Logs via podman/journalctl.
|
||||
dankclaw hosts frank-large (rootless Quadlet, 103.4 GiB RAM, 3 KV slots, greedy default) and marreta (podman compose, Caddy/Anubis/Authentik guard chain). Key ops: probe marreta internally to avoid netns HTTP 000; set temperature: 0 on frank-small for determinism; preserve_thinking is client-side per-request. Watch for file-cache uninterruptible sleep and missing pyyaml on system python3. Authentik flows must link Application(slug=marreta) to prevent Rust outpost crashes.
|
||||
|
||||
@@ -1,5 +1,31 @@
|
||||
# Raw Memories
|
||||
|
||||
## 01a09835-91cf-72e7-8ece-e5316d4de48b
|
||||
updated_at: 1789286336
|
||||
Expanded frank-large KV pool from 262144 to 524288 positions (~14.4 GiB). Reduced HALOGEN_KV_SLOTS from 4 to 3 (~111 MiB freed per slot). Held memory stable at 103.4 GiB (68 weights + 14.4 KV pool + 21 working) within 121 GiB host budget. Admission is pool-bound, not slot-bound; caps at 3 simultaneous full-length requests.
|
||||
|
||||
frank-small defaults to sampling (checkpoint values: do_sample=true, temperature=1.0, top_k=20, top_p=0.95), creating asymmetry with frank-large which defaults to greedy. To force determinism on frank-small: send temperature: 0 per request or relaunch with --sampling-defaults none.
|
||||
|
||||
preserve_thinking cannot be set server-side. Enumerated 156 HALOGEN_* env vars; none control thinking/preserve. Must be sent per-request in chat_template_kwargs by the client.
|
||||
|
||||
API/Host quirks: frank-small returns 200 for unknown fields (200 proves nothing). max_tokens: 200 with empty content indicates thinking consumed budget. host_reserve_gib=24 protects n-gram table; file-cache shortage causes uninterruptible sleep, not OOM.
|
||||
|
||||
Tests: 285/286 pass (test 73 comfyui pre-existing selector bug).
|
||||
|
||||
## 01a09648-8eb8-7093-876a-116b11d4c5fb
|
||||
updated_at: 1789246675
|
||||
Deployment Stack: Podman compose on dankclaw. Marreta shares gluetun egress with searxng. Caddy TLS edge routes to Anubis (:8923) -> Authentik embedded outpost -> internal :8017 listener -> marreta upstream.
|
||||
|
||||
Auth Chain Workflow: Provider-first creation -> Route flip (vhost becomes reverse_proxy anubis:8923, internal @svc handler) -> Deploy. Verified via unauthenticated challenge probe, post-auth config grep, outpost DNS reachability.
|
||||
|
||||
Resolved Failure: Marreta login-wall due to ProxyProvider.application = None on marreta-proxy. Null invalidation_flow crashed Rust outpost serde. Null auth/authz flows compounded issue.
|
||||
|
||||
Fix Applied: Populated invalidation_flow, authentication_flow, authorization_flow + linked Application(name=Marreta, slug=marreta, provider=marreta-proxy). Restarted authentik-server + authentik-outpost.
|
||||
|
||||
Pitfalls & Constraints: Probe http://localhost:8017/ from host returns HTTP 000 (listener in Caddy netns); probe inside netns or grep config. Non-browser clients cannot solve JS challenge; audit service-to-service traffic for backend datasource URLs hitting public guarded hostnames. Exempt-by-construction: IdP (auth.), git smart-HTTP (Gitea), self-auth services. Authentik providers/applications are live-only (ak shell); no repo blueprint (captured in authentik-proxy-provider-app-link skill).
|
||||
|
||||
Verification: E2E regression test (tests/e2e/specs/16-marreta.spec.ts) asserts homepage tile passes through guard chain to Marreta app title, avoiding login-wall parking.
|
||||
|
||||
## 01a09686-789e-7042-8774-55507faa78b2
|
||||
updated_at: 1789232480
|
||||
SERVICE: frank-large (rootless Quadlet, boot-persistent) on dankclaw. Unit: frank-large.service | Container: frank-large.
|
||||
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
thread_id: 01a09648-8eb8-7093-876a-116b11d4c5fb
|
||||
updated_at: 1789246675
|
||||
|
||||
Deployed marreta on dankclaw via podman behind the Anubis+Authentik guard chain, sharing gluetun egress with searxng. Resolved login-wall caused by missing Application link in Authentik ProxyProvider (null flows crashing Rust outpost). Implemented provider-first route flip, netns-aware probing, and e2e regression test.
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
thread_id: 01a09835-91cf-72e7-8ece-e5316d4de48b
|
||||
updated_at: 1789286336
|
||||
|
||||
Expanded frank-large KV pool to 524288 positions (~14.4 GiB) and reduced slots from 4 to 3. frank-large defaults to greedy; frank-small defaults to sampling (1.0 temp, top_k 20, top_p 0.95). preserve_thinking is per-request only. 285/286 tests pass.
|
||||
@@ -0,0 +1,17 @@
|
||||
# frank-large Operations
|
||||
Deployed as rootless Quadlet on dankclaw. ~68 GiB weights + 14.4 GiB KV pool (524k positions, 3 slots). Total ~103.4 GiB.
|
||||
## Ports
|
||||
- Engine: :8730 (loopback)
|
||||
- Front-end: :8731
|
||||
- Published: :7770
|
||||
## Logging & Env
|
||||
- `podman logs frank-large` / `journalctl --user -u frank-large`
|
||||
- Avoid `TEMP`, `HOST`, `GPU_MAX_HEAP_SIZE` (HIP bare TEMP)
|
||||
## Sampling & API
|
||||
- Large: greedy | Small: sampling (temp=1.0, top_k=20, top_p=0.95)
|
||||
- Small determinism: `temperature: 0` or `--sampling-defaults none`
|
||||
- `preserve_thinking`: client-side per-request (`chat_template_kwargs`)
|
||||
- `max_tokens: 200` w/ empty content = thinking consumed budget
|
||||
- File-cache shortage → uninterruptible sleep. `host_reserve_gib=24` protects n-gram table.
|
||||
## Tests
|
||||
- 285/286 pass (test 73 comfyui bug). `pyyaml` missing on system py3; `uv` available.
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"model": "frank-small",
|
||||
"temperature": 0,
|
||||
"chat_template_kwargs": {"preserve_thinking": true}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
#!/bin/bash
|
||||
# Verify KV pool slots and memory stability
|
||||
docker inspect frank-large --format '{{.Config.Env}}'
|
||||
podman logs frank-large 2>&1 | grep -E '^(dmalloc|kv pool):'
|
||||
echo "Slots: HALOGEN_KV_SLOTS"
|
||||
echo "Memory: ~103.4 GiB (68W + 14.4KV + 21W)"
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
[Service]
|
||||
ExecStart=/usr/bin/podman run ...
|
||||
Environment=TEMP=...
|
||||
Environment=HALOGEN_KV_SLOTS=3
|
||||
[Install]
|
||||
WantedBy=default.target
|
||||
-17
@@ -1,17 +0,0 @@
|
||||
Rootless Quadlet service 'frank-large' on dankclaw.
|
||||
|
||||
Ports:
|
||||
- Engine: :8730 (loopback, unauth)
|
||||
- Front-end: :8731
|
||||
- Published: :7770
|
||||
|
||||
Constraints:
|
||||
- Weights: Pinned (~68 GiB)
|
||||
- Env Vars: Avoid TEMP, HOST, GPU_MAX_HEAP_SIZE (HIP runtime issue)
|
||||
|
||||
Logging:
|
||||
- Use podman logs or journalctl.
|
||||
|
||||
Test Env:
|
||||
- pyyaml missing, uv available, pip missing.
|
||||
- Failures likely pre-existing.
|
||||
-11
@@ -1,11 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Retrieve logs for frank-large service
|
||||
|
||||
# Full logs
|
||||
podman logs frank-large
|
||||
|
||||
# Filtered logs
|
||||
podman logs frank-large 2>&1 | grep -E '^(dmalloc|kv pool):'
|
||||
|
||||
# Journald logs
|
||||
journalctl --user -u frank-large
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
# Marreta & Authentik Deployment
|
||||
Podman compose on dankclaw. Shares gluetun egress with searxng.
|
||||
## Guard Chain
|
||||
Caddy TLS → Anubis (:8923) → Authentik outpost → internal :8017 → marreta
|
||||
## Auth Fix & Pitfalls
|
||||
- Login-wall caused by null `ProxyProvider.application` & flows crashing Rust outpost.
|
||||
- Fix: Link `Application(slug=marreta)`, populate auth/authz/invalidation flows.
|
||||
- Probe: `localhost:8017` returns HTTP 000 (Caddy netns). Use internal probe or grep config.
|
||||
- Non-browser clients fail JS challenges. Audit service-to-service URLs for public guarded hostnames.
|
||||
- Exempt: IdP, Gitea (git smart-HTTP), self-auth services.
|
||||
## Verification
|
||||
- E2E: `tests/e2e/specs/16-marreta.spec.ts` asserts homepage tile passes guard chain.
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
Run: npx playwright test tests/e2e/specs/16-marreta.spec.ts
|
||||
Assert: Homepage tile passes Anubis/ProxyProvider guard chain without login-wall parking.
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
#!/bin/bash
|
||||
# Health check through netns
|
||||
podman exec marreta_caddy wget -qO- http://localhost:8017/ || echo "HTTP 000 expected"
|
||||
# Grep config for route flip
|
||||
cat /etc/caddy/config.json | grep "reverse_proxy"
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
application:
|
||||
name: Marreta
|
||||
slug: marreta
|
||||
provider: marreta-proxy
|
||||
flows:
|
||||
authentication: enabled
|
||||
authorization: enabled
|
||||
invalidation: enabled
|
||||
Reference in New Issue
Block a user