The 2026-10-09 wire aliases become the service names everywhere: systemd units, serve scripts, env files and FRANK_* variables, deploy-plan/deploy-remote service keys, container names, Prometheus job names + alert rules, Grafana dashboard queries, bats seams, runbook filenames, homepage/AGENTS lore, and historical prose. Rollback tags renamed in lockstep. Residue in the tree: zero. Retired frank-medium/small/npu names are history and stay. Known casualty: scripts/patches/*.patch context lines were rewritten; those retired-era vLLM-fork patches no longer apply byte-exact.
13 KiB
type, title, description, tags, timestamp
| type | title | description | tags | timestamp | ||||||
|---|---|---|---|---|---|---|---|---|---|---|
| reference | OMP Harness | The omp agent harness as configured on this fleet — compaction chain arithmetic, per-model sampler routing via compat.extraBody, and the static-preamble/skill-library audits that keep session context lean. |
|
2026-10-05T00:00:00-07:00 |
OMP Harness
The harness reaches the fleet through ~/.omp/agent/models.yml (model
registry; single source of truth — there is no copy on the servers) and
~/.omp/agent/config.yml (roles, compaction, global samplers). Nothing in
this file is repo-managed; edits are harness-side only.
Model ids are the StarCraft unit names (official 2026-10-08, on the wire
since 2026-10-09): frank-archon (dankserver :7770, radiance),
frank-dragoon (dankclaw :7770, flash-server), frank-zealot (dankclaw
:7771, the 3090 compaction hub) — formerly frank-archon, frank-dragoon,
frank-zealot. The SERVICES keep the old names (units, scripts, env
files, runbook pages); pages written in the old era name the service,
the harness names the model. The wire now matches: each endpoint's
/v1/models answers with the Protoss name, so models.yml, the OpenWebUI
picker/grants, the homepage docs and the raw API all use one id per model
(see OpenWebUI for the grant re-key and the frank-archon-radiance-swift15-w4dn8
note on radiance echoing the requested name).
Compaction chain arithmetic (verify before ANY window change)
When a fleet endpoint's context grows past its harness-declared window, OMP
compacts by sending the conversation to a designated target model. Before
changing any contextWindow/maxTokens, verify the chain arithmetically —
a target whose window is smaller than the source's trigger point silently
breaks compaction.
Where the contract lives:
~/.omp/agent/config.yml→compaction.remoteEndpoint(target URL),methodOrder,thresholdPercent(70), idle settings~/.omp/agent/models.yml→ per-modelcontextWindow,maxTokens,compactionModelreferences- Implementation: omp plugin
dist/core/compaction/compaction.js
The arithmetic (the coupled contract every endpoint's maxTokens comment encodes):
- Source trigger =
thresholdPercent × source contextWindow(0.70 × 200,704 = 140,492 for frank-archon on the current shape) - Output budget = capped at the target model's
maxTokens(32,768 for frank-zealot; 36,864 frank-archon; 57,344 frank-dragoon — the largest, because halogen'sHALOGEN_MAX_TOKENS_CAPmust stay ≥ it) - REQUIREMENT: prompt (≤ trigger) + budget ≤ the target's per-slot window. Worked pairs from the live registry: 140,492 + 36,864 = 177,356 ≤ 200,704 (frank-archon); 140,490 + 57,344 = 197,834 ≤ 200,700 (frank-dragoon); 140,492 + 32,768 = 173,260 ≤ 200,704 (frank-zealot).
Procedure (recompute from the LIVE files every time — windows rotate with every swap; the numbers above are the 2026-10-05 state):
- Read the
config.ymlcompaction block +models.ymlentries for source and target. Every endpoint'scontextWindowcomment carries its own arithmetic — read them. - Read the target checkpoint's
max_position_embeddings(native window) — the served window may be a concurrency contract, not the native limit (--parallel NDIVIDES the pool; the per-slot number is the contract). - If native ≥ trigger + budget, reslice the pinned pool:
MAX_RUNNING × CONTEXT_LENGTH ≤ MAX_TOTAL_TOKENS(the pin exists because the runtime's autofit leaves too little for deferred loads + prefill workspace; checknvidia-smiheadroom — expect ~0.8 GB workspace margin). - Changes: host env (CONTEXT_LENGTH-style env tunables) via git →
./tests/run.sh→ deploy; harnessmodels.ymldirectly (no repo copy). - Verify:
/health200, boot log's pool line, then a long-prompt probe at ≥ trigger height (the compaction-fit guarantee), then concurrent requests.
Known reconciliation trap: comments in models.yml have described compaction
as running "on the dankserver endpoint" while remoteEndpoint pointed at
dankclaw — the comment/config disagreed. The comments now name the real
target (compaction.remoteEndpoint = dankclaw :7771). The config is
truth; fix comments in the same change. maxTokens never changes for a
reslice — it caps output; contextWindow caps input. Boot-shape OOM
laddering is a different problem (Llama Cpp Serving Sizing).
Per-model sampler config (compat.extraBody)
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.
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
Use wire names, not OMP camelCase. Two traps:
preserve_thinkingis not user-settable as a compat key.qwenPreserveThinkingis auto-derived inbuildOpenAICompatfrom the auto-detectedthinkingFormat+ local baseUrl, beforeapplyCompatOverrides. Settingcompat.thinkingFormat: qwenin models.yml does not enable it. Custom-named models (frank-dragoon) match no Qwen id pattern → useextraBody: {preserve_thinking: true}.- Never put
chat_template_kwargsinextraBodywhere a compat policy also sets it —Object.assignis shallow and replaces the whole object, silently dropping thereasoning_effortkwarg the compat policy set. Top-levelpreserve_thinkingis honoured by halogen. (frank-archon's FreeToken entry currently carries achat_template_kwargsextraBody with a comment asking to verify-and-prune — the exact trap to check at that endpoint's next swap.)
Gotcha: silent greedy decode. halogen has no server-side sampler
defaults — temperature absent or 0 = greedy. If OMP sends nothing, the
endpoint decodes greedy while looking configured. This is why frank-dragoon's
entry carries the recipe on the wire and a comment saying "do not drop it".
Reasoning-effort folding. Qwen3.8's template accepts only
{xhigh (default), medium, low} for reasoning_effort and 400s on anything
else ("Unexpected reasoning effort high"). Every endpoint's
reasoningEffortMap folds all harness levels onto that set; a role whose
level is unmapped fails on its FIRST request, and the failure names Jinja,
not the model.
Verify the exact wire body (echo-capture)
Don't trust the YAML — capture what OMP actually emits:
- Echo server on
127.0.0.1:18099that dumps the JSON body to a file and returns a cannedchat.completion(includereasoning_contentso thinking paths exercise). - Copy the real models.yml into a throwaway profile with only the
baseUrl swapped:
sed 's|http://<host>:7770/v1|http://127.0.0.1:18099/v1|' \ ~/.omp/agent/models.yml > ~/.omp/profiles/wiretest/agent/models.yml - Run and inspect:
Confirm every intended field is present with the right value.
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
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.
Static-preamble audit ("the context feels bloated")
What loads statically every session (measure each, don't guess):
- Repo rules file —
wc -c AGENTS.md(baseline 2026-10-05: 72,179 B, ~18k tokens — historically the largest block). - Skill index — only names+descriptions load; bodies are on-demand. Sum
description bytes across all SKILL.md frontmatter:
Baseline 2026-10-05: 171 managed skills / ~38 KB descriptions + 9 user skills.
python3 - <<'EOF' import glob, re, os for root in [os.path.expanduser("~/.omp/agent/managed-skills"), os.path.expanduser("~/.omp/agent/skills"), ".omp/skills"]: n=tot=0 for sk in glob.glob(root+"/*/SKILL.md"): fm=re.search(r'^---.*?---', open(sk, encoding="utf-8", errors="replace").read(), re.S) d=re.search(r'description:\s*(.*(?:\n(?:\s{2,}.*)*)?)', fm.group(0) if fm else "") n+=1; tot+=len(d.group(1)) if d else 0 print(root, n, tot) EOF - Memory lessons —
find ~/.omp/agent/memories -name 'MEMORY.md' -o -name 'memory_summary.md' | xargs wc -c. The injected block ≈ the largest MEMORY.md. - Harness/system prompt + tool schemas + CLI persona: fixed cost, ~20 KB; not prunable.
Known rot patterns:
- Near-duplicate auto-captures of the same lesson (three "authentik ORM"
entries, the freetoken-build pair, the three job-runner skills) — dedupe
via
manage_skill delete/update. - Corrupted captures containing stray CJK characters (
一团ly,等方法) mid-sentence — a known defect of the auto-capture path; delete the corrupt copy, keep the clean one. - Stale host/service names in consolidated memory (pre-rename
frank-default-large) — the repo's AGENTS.md topology table is ground truth.
Fix strategy: AGENTS.md prose (measured runbook narratives) → move to
serverAppConfigs-docs/LLM/ runbooks, keep laws + tables in AGENTS.md (the
repo's own docs-tree rule mandates this). Managed skills live in
~/.omp/agent/managed-skills (safe to edit); user-authored skills in
~/.omp/agent/skills are NEVER touched by tooling. Memory store edits:
stage removed captures to trash first (~/.AGENTTRASH/YYYYMMDD-topic).
Baseline to beat (2026-10-05): ~35–40k tokens of preamble — AGENTS.md ~18k, skill index ~10k, lessons ~3.5k, harness ~6k. Proposed reductions: −12k (AGENTS.md slimming), −3k (skill dedupe).
Managed-skill library hygiene
Use when auditing, pruning, or consolidating ~/.omp/agent/managed-skills
(the auto-captured skill store; the full index is injected into EVERY
session's context, so dead or duplicate entries are a permanent tax).
The static-context budget (measured 2026-10-05):
| Block | Size | Notes |
|---|---|---|
AGENTS.md (repo) |
72,179 B ≈ 18k tok | biggest single item |
| Skill index (~173 skills) | ~40 KB ≈ 10k tok | names+descriptions only |
| Learned-lessons block | ~14 KB | can contain corrupted/duplicate captures |
| Harness system prompt + tool schemas | ~23 KB | fixed |
Audit procedure:
- Build an inventory: per skill, name, mtime, body word count, description, first 12 headings (one pass, out to a file; read in pages).
- Group into: retired-runtime (host/service gone; its runbook already lives
in
serverAppConfigs-docs/LLM/), verbatim-duplicate pairs/triples (same lesson captured twice — often the SAME DAY), same-lesson families (N skills = one procedure), keep. - Read full bodies of every merge candidate before proposing a merge; description alone proves overlap only for exact dupes.
- Present A/B/C/D verdicts for user approval. NEVER execute before the discussion concludes — the user gates execution explicitly.
- On approval: stage everything to trash first
(
~/.AGENTTRASH/YYYYMMDD-<topic>/), never rm. After merging: recreate the surviving skill viamanage_skillupdate with body = superset, delete absorbed ones.
Known rot classes (this library, 2026-10-05):
- Same-day duplicate captures (freetoken-build-dankclaw vs freetoken-dankclaw-build; the three job-runner skills).
- CUDA-skill vs its self-declared HIP twin (pcie-link-capability-probe vs pcie-link-probe-hip-rdna4) → merge.
- Era ghosts: skills naming retired runtimes (freetoken, lucebox, r9v/ radiance, old halogen-flash-server image, ik_llama, GLM-5.3 experiment).
- Skills contradicting user standing orders (live-bench-dashboard vs the 2026-09-29 delete-dashboards order) — flag for user, don't assume.
- Memory store: corrupted captures with CJK noise from broken ssh commands; stale host/service renames.
Sizing verdicts that worked: bench family → 2 skills (harness vs discipline), not one mega-skill; keep profiler/kernel-time attribution standalone; fold go/no-go arithmetic skills into their probe skill (heterogeneous-accelerator-split-triage → PCIe probe).
Related
- Agent Docs and Edits — editing vault docs and hashline targets safely
- Command Center Dotfiles — the
~/.omprepo deploy this config rides - Llama Cpp Serving Sizing — the engine-side sizing the chain must fit
- LLM Bench Windows and Measurement — measuring the endpoints this config routes