Files
command-center/agent/memories/--home-blank-.omp--/learned.md
T

27 lines
29 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
- command-center (~/.omp) worktree-clean law, verified 2026-10-09: (1) The secret gate's PEM family regex (BEGIN, a space, a bracketed A-Z star class, PRIVATE KEY) does NOT self-match when the pattern is quoted in brackets form — a SKILL.md documenting the gate verbatim in regex-bracket shape is safe to stage; only the bare quoted literal (e.g. the plain two-word PEM header phrase, the xox[baprs] family prefix followed by 10+ token chars) trips it. Before any commit that stages prose about secrets, pre-scan with the exact gate one-liner: staged=$(git diff --cached --diff-filter=ACM -U0 -- '*.md' '*.yml' '*.yaml' '*.json' '*.toml' '*.sh' '*.ts' '*.js'); printf '%s\n' "$staged" | grep -Eic 'gate patterns' — 0 hits means the gate will pass; redact prose descriptively, never ALLOW_SECRETS. (2) The omp auto-learner mints managed skills under agent/managed-skills/name/ DURING a session — a "clean tree" declared mid-session goes dirty again when capture fires (observed: noctalia-bar-layout-edit appeared between commit and final status). Re-run git status as the LAST command of a cleanup pass. (3) Classification rule that made the tree clean in one pass: agent/memories/*/learned.md and agent/managed-skills/ are config → commit atomically; new top-level runtime dirs (webcache/, reports/, local/, wt/) are state → .gitignore. webcache/ (harness web-fetch cache) is gitignored as of commit 4d2b024.
- Noctalia v5 config layering (verified live on blankpad 2026-10-09): bar widget layout lives in the GUI-override layer ~/.local/state/noctalia/settings.toml under [bar.name] keys start/center/end (defaults: start=["launcher","wallpaper","workspaces"], center=["clock"]); settings.toml loads LAST and wins over ~/.config/noctalia/config.toml. Both layers are watched and hot-reloaded — edit + noctalia config validate + screenshot is the full apply/verify loop (no restart, no reload IPC). Noctalia writes THROUGH symlinks and keeps the link, so keeping settings.toml symlinked from the command-center dotfiles repo is safe. Combine workspace+window indicator: [widget.taskbar] group_by_workspace=true (needs compositor per-window workspace data — niri has it) renders per-workspace capsules with disc labels, workspace_group_content = icons|count|dots (count/dots left-click activates the workspace); the workspaces widget itself has no window-display mode. Applied on blankpad: bar.default start=["launcher","wallpaper","workspaces","taskbar"], center=["cat"] (command-center commits 9255a8b, 0ccdd46). _(context: Blankpad noctalia 5.2.1 bar layout change 2026-10-09: taskbar moved to left section, group_by_workspace identified as the combining widget, verified via config validate + fullscreen screenshot)_
- The command-center (~/.omp) pre-commit secret gate (.githooks/pre-commit, single grep -E of known token regexes) SELF-MATCHES its own documented pattern literals: committing prose that quotes them verbatim (e.g. a quoted PEM private-key header line, the xox[baprs] family prefix, the github-pat prefix, long sk- examples) trips SECRET GATE and blocks the commit (observed twice 2026-10-09 on agent/memories/--home-blank-.omp--/learned.md audit prose). Convention: redact pattern literals descriptively in prose ("PEM private-key headers", "the xox[baprs] family", "ghp 36") instead of setting ALLOW_SECRETS=1; the gate firing on prose is the gate working as designed. Note the gate covers only 10 families — no hf_/npm_/AIza/glpat-short/basic-auth-URL coverage — so clean-gate history is not proof of no leaks.
- niri 26.04 event-stream (niri msg --json event-stream) has NO hotplug event: OutputConfigChanged is only an ACK that an IPC/config output change was Applied (per niri-ipc docs; proven live — mode flips via niri msg output NAME mode WxH@Hz and DPMS off/on emit zero output events). Detect monitor connect/disconnect by diffing the sorted unique set of .WorkspacesChanged.workspaces[].output across events (off/on cycle of eDP-1 emitted exactly WorkspacesChanged 2x). Debounce ~1.5s; OutputConfigChanged events are emitted in bursts on every config reload — ignoring them prevents hotplug-daemon echo loops. Implemented in dank/command-center scripts/desk-autoswitch.sh (blankpad-desk-autoswitch.service). Related trap: niri msg output 26.04 syntax is niri msg output NAME ACTION [args] (mode/off/on), not the old NAME WxH@Hz form.
- On Frank's workstations (Arch, pam_faillock deny=3), subagents MUST NEVER run sudo/yay/pacman: in the harness sudo has no TTY, so every attempt logs 3 pam_unix failures and trips pam_faillock "temporarily locked out" (~600s), which re-arms on every retry and locks out the USER's real interactive sudo — observed 2026-10-09 on blankpad when a Handy-install subagent looped sudo yay -Syu handy-bin for 15 min; the user saw "incorrect password"/lockout and (understandably) suspected his password was changed. Diagnostics that settle it in one step: stat /etc/shadow (unchanged mtime = no password change), journalctl | grep 'sudo\[' (PWD/COMMAND identify the spammer), faillock --user blank. Recovery: kill the loop, then faillock --user self --reset works unprivileged (per-user dir /run/faillock/user is owner-writable); then user runs sudo -v. Any package install requiring root must be handed to the user as exact copy-paste commands, never attempted by an agent.
- Tool traps verified on blankpad 2026-10-09 (niri/noctalia/Handy DE session): (1) niri msg action (and other niri msg subcommands that print help/action lists) write to STDERR — niri msg action 2/dev/null | grep ... yields empty output and looks like "feature missing"; always pipe with 2&1. Confirmed live: niri 26.04 has swap-window-left/right (window walks sideways, entering/leaving columns; column order untouched), move-window-to-monitor-*, focus-window-up/down (tabbed columns navigate with up/down; focus-window-left/right does NOT exist — no gap to fill). (2) frank-zealot (llamacpp dankclaw-3090 :7771) as a subagent model crashed mid-run with invalid string: surrogate U+D800..U+DBFF when a tool-call JSON argument contained many emoji — server-side JSON parse, type=server_error; keep subagent prompt/context payloads ASCII (no emoji) when agents run on fleet llama.cpp/radiance models; the crash is infrastructure, retry after stripping emoji. (3) The failed agent HAD already written its files before crashing (omp-docs/tools/handy.md, noctalia-shell.md rewrite survived; only its cleanup grep died) — after a subagent exit-1, always inspect target files for partial/complete output before respawning; its summary claims are unverified, diff against live truth (it invented a Handy settings JSON shape and flipped post_process_enabled true; live value false, real shape has bindings.transcribe/current_binding). (4) edit tool payload format: every change block MUST start with a PUT N.=M: (or DEL N.=M) hunk header followed by +/- lines; bare N:text + +text lines are rejected with "payload line has no preceding hunk header". (5) blankpad repo fact for pending work: live ~/.config/niri/cfg/{misc,rules}.kdl symlinks point at the GENERIC dotfiles/niri copies, which pin render-node /dev/dri/renderD129 "Intel Arc" — blankpad is single AMD Cezanne (renderD128); the newer dotfiles/zz-blankpad copies (no render-node, cursor 36, blur off, noctalia layer rules) are the correct live files, _(context: Grilling session on blankpad niri 26.04 / noctalia 5.2.1 / Handy 0.9.6 DE config; fact-check sweep + doc rewrites in dank/command-center omp-docs.)_
- Blankpad DE stack, verified 2026-10-09 against live system + upstream (source of truth for future niri/noctalia/handy work; supersedes omp-docs claims): (1) Noctalia is v5 (installed 5.2.1-1.1, native noctalia binary). The v4 Quickshell line is DEAD upstream — repo doc omp-docs/tools/noctalia-shell.md (v4.7.7, qs -c noctalia-shell ipc call …) is stale; correct API is noctalia msg cmd, full list from noctalia msg --help (~110 cmds: screenshot-region/-fullscreen/-annotate, window-switcher, clipboard-*, workspace-alert-*, theme-mode-toggle, session lock-and-suspend, dpms-*, greeter-sync, templates-apply). Noctalia's niri docs (docs.noctalia.dev/noctalia/compositor-settings/niri/): autostart spawn-at-startup "noctalia", lid policy via niri switch-events { lid-close { spawn "noctalia" "msg" "session" "lock-and-suspend"; } }, wallpaper/blur layer-rules, [shell] niri_overview_type_to_launch_enabled. (2) niri 26.04 IS latest (repo moved to niri-wm org). New since docs: mainline blur/xray (background-effect, popups block, layer matcher), include optional=true + ~ expansion, niri msg action load-config-file --path file (live-swap config path — key for dotfiles symlink testing), cast IPC (niri msg casts, stop-cast), screenshot-window show-pointer=true, output options variable-refresh-rate (+on-demand=true), focus-at-startup, backdrop-color, per-output layout{}, mode custom=true/modeline (25.11), Escape cancels drag-and-drop. (3) Handy (cjpais/Handy) 0.9.6 installed via local/handy-bin; latest 0.9.8 (2026-10-03). Upstream LAW: SIGUSR1 handler REMOVED (WebKitGTK owns SIGUSR1; pkill -USR1 handy can crash the app) — toggle is SIGUSR2 or CLI flags handy --toggle-transcription / --toggle-post-process / --cancel; startup flags --start-hidden --no-tray. Wayland: compositor must own global binds (call the CLI flags from niri binds); text input needs wtype/dotool (NOT installed on blankpad; current paste_method=none + copy_to_clipboard, so no tool needed); overlay disabled-by-default up _(context: Fact-check sweep of niri/noctalia/handy docs on blankpad, 2026-10-09, ahead of a pending config-change grilling (Round 1 questions pending user answers))_
- command-center (~/.omp) secret hygiene, audited 2026-10-09 at 79e780f: repo history is CLEAN — no live value (gitea/hf_token/hf_token_write/kagi_api_key) in any of 77 revs / 765 reachable blobs / 2 dangling blobs / 23 git-lfs payloads; the only sk-shaped string is a 35-byte unreachable fixture whose body is the alphabet + 1234. DURABLE GAP: .githooks/pre-commit (core.hooksPath=.githooks) matches only the OpenAI-style 18+ alnum token, ghp 36, github-pat 22+, glpat 20, the xox[baprs] family, AWS key ids, PEM private-key headers, aes 40-char, eyJ….eyJ (JWT). It does NOT match hf 30, npm 30, pypi, AIza 35, Stripe live/test keys, Telegram bot tokens, or a scheme://user:token@host basic-auth URL — the basic-auth shape is exactly what sat in remote.origin.url on both workstation clones until 2026-10-09, so the gate would never have caught it. The gate DID fire correctly on a synthetic token literal quoted in a commit (2026-10-09) AND on the audit prose itself (the gate self-matches its own documented pattern literals — quote them descriptively in docs/memory), so redact literals in docs/commit messages instead of using ALLOW_SECRETS. Live secrets live in ~/.config/secrets/* (dir 0700, files 0600 — hf_token_write was 0644 and was fixed); ~/.cache/huggingface/token duplicates hf_token at 0600 by HF convention.
- Gitea client auth on Frank's workstations (2026-10-09): the HTTP token lives ONLY in ~/.config/secrets/gitea (0600) behind a global helper git config --global credential.helper 'store --file ~/.config/secrets/gitea'. All remote URLs are bare (http://192.168.0.143:3000/dank/repo.git) — a token embedded in remote.origin.url leaks via .git/config, git remote -v, and the git-lfs "Locking support detected on remote" warning, which echoes the full URL on every push (silence it per repo with git config lfs.bare-url/info/lfs.locksverify true). TRAP, measured on git 2.56.0: git credential-store does NOT parse the protocol=/host=/username=/password= block shape in the store file — that shape is only what git credential fill accepts on stdin, and the man page's ~/.git-credentials example is misleading. A block-format file yields a SILENT empty get, git falls through to askpass and dies with "could not read Username for …" (SSH_ASKPASS=/usr/bin/false in the omp harness env). The store file must be one URL per line WITH the port: http://dank:token@192.168.0.143:3000. Verify before trusting it, with prompts disabled so failure is loud: printf 'protocol=http\nhost=192.168.0.143:3000\n\n' | git credential-store --file ~/.config/secrets/gitea get must print username+password; then GIT_TERMINAL_PROMPT=0 git ls-remote --heads origin main and git push --dry-run. Rotation = rewrite that one file, nothing else. Documented in omp-docs/tools/gitea/client-access.md (command-center commit cfed6ef).
- The origin remote of the command-center repo (~/.omp) embeds the Dankclaw Gitea token in plaintext: http://dank:token@192.168.0.143:3000/dank/command-center.git in .git/config. Consequence observed 2026-10-09: git push origin main echoes that URL (the git-lfs "Locking support detected" hint prints the full URL with the token) into stdout, so any transcript/log of a push contains a live credential. Recommended remediation proposed to Frank and NOT yet approved/applied — do not change remote auth unilaterally: git remote set-url origin http://192.168.0.143:3000/dank/command-center.git plus git config credential.helper 'store --file ~/.config/secrets/gitea' (that directory is Frank's existing 600-perm secret convention), and git config lfs.http://192.168.0.143:3000/dank/command-center.git/info/lfs.locksverify true to silence the lock hint. Reuse rule: when a token must be read from this repo, read it from the existing origin URL and reference its location only; never copy it into docs, skills, memory, or commit messages. Repo hooks: core.hooksPath=.githooks → pre-commit secret gate (patterns incl. eyJ… JWT shapes; override ALLOW_SECRETS=1) and pre-push git lfs pre-push, so pushes carry LFS objects.
- Fleet LLM model ids in ~/.omp/agent/models.yml were renamed to the unit-name scheme on 2026-10-08 (committed 0cb021b, pushed 2026-10-09): frank-medium → frank-archon (llamacpp dankserver, 192.168.0.235:7770, ctx 200000 / maxTokens 16384), frank-large → frank-dragoon (dankclaw, 192.168.0.143:7770, 217088 / 45056, text+image), frank-small → frank-zealot (dankclaw-3090, 192.168.0.143:7771, 200704 / 16384). Service/unit/script names are UNCHANGED — /v1/models still advertises frank-primary, frank-large, frank-secondary. LAW (verified live with chat-completion probes on all three): radiance, halogen-flash-server and llama.cpp all accept an arbitrary request model id, so a harness-side id rename needs no endpoint change; the response model field just echoes the served name. Server-side compaction moved from dankserver:7770 to 192.168.0.143:7771 (frank-zealot), thresholdPercent 70 → 85, and every model's compactionModel now points at llamacpp (dankclaw-3090)/frank-zealot so the wire id stays valid at the compaction endpoint. Provider names in models.yml are labels referenced from config.yml (modelRoles, task.agentModelOverrides) and from compactionModel — renaming one requires updating every reference; verify by parsing both YAML files and cross-checking all llamacpp (host)/id tokens (regex must allow the space+parens in the provider label; a naive whitespace split yields false "unresolved" hits). Also: git renders whole-directory renames as mass delete + mass untracked — the 2026-10-09 tree showed 116 D + 73 ?? for the managed-skills consolidation (94 → 25) and the memory-skill re-bucketing (dotfile-git-workflow → ghostty-text-aa + niri-display-rotation + noctalia-theme; handy-service-mgmt → handy-flm-inference; inference-runtime → llama-cpp-parallelism). Nothing was lost: index matched HEAD, so git restore recovers any of it.
- Measuring WHICH card is the bottleneck in a llama.cpp layer-split LLM server on a fleet host (frank-medium, Dankserver 192.168.0.235, 2x R9700 asymmetric PCIe: ROCm0=x16 ~31.5GB/s, ROCm1=x1 ~1.97GB/s) — two traps that produced wrong numbers on 2026-09-18: (1) RUN THE TRANSIENT MEASUREMENT SERVER ON AN ISOLATED PORT, not the production port. If it takes over the prod port (7770), live fleet traffic from other agents hits it and interleaves with your timed request — I measured 35:30 at 2.51 t/s on :7770 vs the true 31.5 t/s; on isolated :7790 (prod stopped to free VRAM, fleet hits the down 7770) it read 31.52 t/s. Override LISTEN_PORT in a temp env copy (sed), point curl at the new port. (2) Use AVERAGE rocm-smi --showuse over a LONG request (2k tokens, ~60s), sampled every 0.5s — PEAK util lies for a layer split because both cards are touched every token and both hit ~100% at peak. Average is the bottleneck indicator. FINDING (durable, specific to frank-medium): the x1 card (ROCm1) is the STRUCTURAL bottleneck at 98% avg util in every config — 35:30/36:29, drafter on ROCm1/ROCm0 all gave util0(x16)=41-43% / util1(x1)=98%, decode ~31.5 t/s in all four. It's COMPUTE-bound, not PCIe-bound (only ~5.2 MB activation crosses the x1 link per 512-token ubatch). The per-step cost is the verify phase (both cards run the full target) + the LOGITS, which are pinned to the card holding the last layers; the MTP drafter is a small nextn head so moving it (SPEC_DRAFT_DEVICE=ROCm0) buys nothing. 35:30 is the optimal split (balanced VRAM 1.27/1.85 GiB free); 36:29 buys 2 util points on the x16 card and erodes its VRAM (fit free 0.45 GiB) for no throughput gain. No llama-server flag moves the lm_head off the last-layer card, so the x1 bottleneck is architectural, not a mis-tune. Recorded in scripts/frank-medium.env (committed 6c6464a).
- placeholder4
- placeholder3
- placeholder2
- placeholder
- frank-medium (Dankserver 192.168.0.235, llama.cpp layer-split 2x R9700 gfx1201) split-balance findings, 2026-09-17: (1) The LAYER SPLIT is NOT a decode-throughput lever at the 393216/MTP shape — 34:31, 35:30 and 36:29 all land in the same ~32 tok/s band (36:29 measured 31.76; 35:30 ~32.4 per env); total work, not imbalance, is the limit. (2) The x1 card (ROCm1, 0b:00.0, Gen4 x1 via B650 chipset ~1.97 GB/s) runs HOT (util ~91-97%) at 35:30 while the x16 card (ROCm0, 03:00.0, Gen4 x16 ~31.5 GB/s) idles (~45%) — because the MTP drafter + output layers + heavier compute buffers are STRUCTURALLY pinned to the card holding the LAST layers, NOT because the PCIe link is the bottleneck (only ~5.2 MB of boundary activation crosses per 512-token ubatch). (3) 36:29 makes the x16 card the utilized worker (util0=42%, util1=3%) at no throughput cost, but spends VRAM headroom (card0 free 0.45 GiB, under the 1.0 GiB floor; 2.22 GiB gap). Frank's standing preference: the card with the FASTEST PCIe lane (x16 = ROCm0) should be the more-utilized card. Deploying 36:29 requires re-fitting the seam test (tests/frank_medium_unit.bats) slack/floor, which currently rejects it.
- niri output config on blankpad (niri 26.04): transform values are COUNTER-CLOCKWISE, so "90" means the panel's top bezel must physically sit on the LEFT ("270" = top bezel right). Two traps when pinning outputs in ~/.config/niri/cfg/display.kdl (symlink into ~/.omp/dotfiles/zz-blankpad/): (1) an output "X" {} block RESETS every property you don't restate to its default — eDP-1 needed scale 1.25 repeated or it would silently drop to 1.0; (2) niri re-runs its auto-layout for any output without a pinned position, so pinning only the externals shoved eDP-1 to the far right (3936,0) — pin eDP-1 at x=0 too if you want the original left-to-right order. Apply with niri validate -c ~/.config/niri/config.kdl then niri msg action load-config-file; confirm with niri msg outputs (shows Logical size swapped to 1200x1920 and "Transform: 90° counter-clockwise"). Live one-off rotation without config: niri msg output NAME transform 90. _(context: Rotated both external PM1601 panels (DP-2, HDMI-A-1) to portrait on blankpad 2026-09-15; verified via niri msg outputs, committed 2baf0c0 to dank/command-center.)_
- 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 the workstation: 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 the workstation. 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)_
- Noctalia is a Niri-based desktop environment at /usr/bin/noctalia. Config: ~/.config/noctalia/config.toml. Provides IPC via 'noctalia msg', launcher, lock screen, session menu, and 19 app templates (GTK, Ghostty, Alacritty, Hyprland, Sway, WezTerm, Helix, Btop, Starship, Qt, KDE, Cava, scroll, mango, umbriel, foot, emacs, kitty, alacritty). Templates under /usr/share/noctalia/assets/templates/. Color palette generator: 'noctalia theme [image]'. Text antialiasing: Ghostty uses 'font-subpixel-render' config key (set to 'off' to disable). Alacritty uses 'font.antialias = false' in alacritty.toml.