Files
serverAppConfigs/serverAppConfigs-docs/Agent/OMP Harness.md
T
Frank 6bdfd2853e docs(vault): service and infrastructure pages stop restating endpoint facts
18 pages cut their per-endpoint shape, payload, port and window claims and
link [[frank-archon]] / [[frank-dragoon]] / [[frank-zealot]] instead. Several
of the cut claims had already drifted -- the stack page still described the
kingjones ROCmFP4 era on ROCmFPX, OpenWebUI carried the 27B/3-slot bench
narrative, Hermes named a retired max_model_len and the old service name, and
the OMP harness page's live-window block had drifted off frank-zealot's real
262,144 (it is now labelled a dated worked example whose authority is the
endpoint page).

Two facts gain a single owner instead of two: the up{job=~"frank-.*"} scope
lives in Infrastructure/Prometheus.md, and the blackbox/Anubis probe form in
Architecture/Stale Signal Audit.md, each cited from the other page.

Voice Packs and Frank TTS carried live-state claims that contradicted the
engine page's 2026-10-18 deploy record (nothing listening on 7772/8880, model
dir absent); they now point at the pages that own host state.
2026-10-19 00:56:02 -07:00

309 lines
16 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.
---
type: reference
title: OMP Harness
description: 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.
tags: [omp, harness, compaction, models-yml, context, samplers]
timestamp: 2026-10-18T00:00:00Z
---
# 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), `frank-dragoon` and
`frank-zealot` (Dankclaw) — engine, port and card behind each id live on
[[frank-archon]], [[frank-dragoon]] and [[frank-zealot]] — 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]]
note on the endpoint echoing the requested name).
Verified 2026-10-18: `/v1/models` on 192.168.0.235:7770, 192.168.0.143:7770 and
192.168.0.143:7771 each answer with the unit name (`frank-archon`,
`frank-dragoon`, `frank-zealot`).
## 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:
`http://192.168.0.143:7771/v1/chat/completions`, `config.yml:76`),
`methodOrder` (`shake → snapcompact → soft → handoff → remote`,
`config.yml:77-82`), `thresholdPercent` (**95**, `config.yml:84`), idle
settings (`idleEnabled`, `idleThresholdTokens: 100000`)
- `~/.omp/agent/models.yml` → per-model `contextWindow`, `maxTokens`,
`compactionModel` references
- Implementation: omp plugin
`~/.omp/plugins/node_modules/@earendil-works/pi-coding-agent/dist/core/compaction/compaction.js`
The arithmetic (the coupled contract every endpoint's maxTokens comment
encodes). The authoritative `contextWindow`/`maxTokens` pair per model is on the
endpoint page ([[frank-archon]], [[frank-dragoon]], [[frank-zealot]]); what
follows is a **worked example** recomputed from the live files on 2026-10-18 —
a snapshot, not fleet state — with windows 200,000 / 155,648 / 200,704 and
maxTokens 16,384 / 45,056 / 16,384 (archon / dragoon / zealot):
1. **Source trigger** = `thresholdPercent × source contextWindow`; at the live
95 % that is 190,000 (archon), 147,866 (dragoon), 190,669 (zealot). The
bundle clamps the percentage to 1–99 and converts it to a token threshold.
2. **Output budget** = capped at the target model's `maxTokens` — every role
here compacts to frank-zealot, so the budget is its 16,384.
3. **REQUIREMENT**: prompt (≤ trigger) + budget ≤ the target's per-slot
window. **At 95 % this no longer holds**: 190,000 + 16,384 = 206,384 >
200,704. The registry's own comments design around an 85 % trigger (archon:
170,000 est × 1.03 + 16,384 ≈ 191,500 ≤ 200,704, `models.yml:49-56`), which
does hold. While `config.yml` and those comments disagree, treat 85 % as the
design point and re-run this arithmetic after ANY window change — a 400 from
the compaction target mid-conversation is the symptom.
(Historic 2026-10-05 pairs, at `thresholdPercent: 70`: 140,492 + 36,864 =
177,356 ≤ 200,704 archon; 140,490 + 57,344 ≤ 200,700 dragoon; 140,492 +
32,768 ≤ 200,704 zealot.)
Procedure (recompute from the LIVE files every time — windows rotate with
every swap; the block above is the 2026-10-18 state):
1. Read the `config.yml` compaction block + `models.yml` entries for source
and target. Every endpoint's `contextWindow` comment carries its own
arithmetic — read them.
2. Read the target checkpoint's `max_position_embeddings` (native window) —
the served window may be a concurrency contract, not the native limit
(`--parallel N` DIVIDES the pool; the per-slot number is the contract).
3. 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; check `nvidia-smi` headroom — expect ~0.8 GB workspace margin).
4. Changes: host env (CONTEXT_LENGTH-style env tunables) via git →
`./tests/run.sh` → deploy; harness `models.yml` directly (no repo copy).
5. Verify: `/health` 200, 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.** A fresh instance of the same trap is
open 2026-10-18: every `maxTokens` comment still says "compaction fires at
85 % of the window" while `config.yml:84` sets `thresholdPercent: 95`.
`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**. The global knobs are
`config.yml`'s `temperature`, `topP`, `topK`, `minP`, `presencePenalty`,
`repetitionPenalty`, and a knob reaches the wire only when it is set — the
bundle guards each one with `!== void 0` (e.g. `minP!==void 0)e.min_p=t.minP`),
and this workstation's `config.yml` sets **none** of them. The 2026-10-05 note
that the unset default is `-1`/"not sent" is retired: there is no `-1`
sentinel, an unset key is simply absent. 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.
```yaml
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:
1. **`preserve_thinking` is not user-settable as a compat key.**
`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-dragoon`)
match no Qwen id pattern → use `extraBody: {preserve_thinking: true}`.
2. **Never put `chat_template_kwargs` in `extraBody`** where a compat policy
also sets it — `Object.assign` is shallow and replaces the whole object,
silently dropping the `reasoning_effort` kwarg the compat policy set.
Top-level `preserve_thinking` is honoured by frank-dragoon
([[frank-dragoon]]). Live state 2026-10-18: frank-archon's `extraBody`
carries `chat_template_kwargs: {enable_thinking, preserve_thinking}`
(`models.yml:89-91`) and nothing else sets that object at that endpoint, so
the shallow-merge hazard is latent rather than firing.
**Gotcha (retired 2026-10-17): silent greedy decode.** Earlier frank-dragoon
builds carried **no server-side sampler defaults**, so an absent
`temperature` decoded greedy while the endpoint looked configured. That era is
over — the endpoint now ships its own defaults ([[frank-dragoon]]), so an
absent temperature is no longer greedy. frank-dragoon's `extraBody` still
carries the same trio — consistent, not load-bearing. Treat any older "do not
drop it or you get greedy" wording as history.
**Reasoning-effort folding.** The set `reasoning_effort` accepts is a property
of the endpoint, not of the harness: [[frank-dragoon]] and [[frank-zealot]]
raise on anything outside `xhigh|medium|low`, while [[frank-archon]] does not
gate the set. Every endpoint's `reasoningEffortMap` folds all harness levels
onto whichever set that endpoint ships; 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:
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`.
## Static-preamble audit ("the context feels bloated")
What loads statically every session (measure each, don't guess):
1. Repo rules file — `wc -c AGENTS.md` (baseline 2026-10-05: 72,179 B, ~18k
tokens — historically the largest block; re-measured 2026-10-18: 89,723 B).
2. Skill index — only names+descriptions load; bodies are on-demand. Sum
description bytes across all SKILL.md frontmatter:
```bash
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
```
Baseline 2026-10-05: 171 managed skills / ~38 KB descriptions + 9 user
skills. Re-measured 2026-10-18 with the same glob: **87** managed
`SKILL.md` + 9 user skills — the dedupe happened.
3. Memory lessons — `find ~/.omp/agent/memories -name 'MEMORY.md' -o -name
'memory_summary.md' | xargs wc -c`. The injected block ≈ the largest
MEMORY.md.
4. 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 |
Re-measured 2026-10-18: the skill library is down to 87 managed skills, but
`AGENTS.md` has grown to 89,723 B — the dedupe landed, the slimming did not.
Audit procedure:
1. Build an inventory: per skill, name, mtime, body word count, description,
first 12 headings (one pass, out to a file; read in pages).
2. 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.
3. Read full bodies of every merge candidate before proposing a merge;
description alone proves overlap only for exact dupes.
4. Present A/B/C/D verdicts for user approval. NEVER execute before the
discussion concludes — the user gates execution explicitly.
5. On approval: stage everything to trash first
(`~/.AGENTTRASH/YYYYMMDD-<topic>/`), never rm. After merging: recreate
the surviving skill via `manage_skill` update 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 `~/.omp` repo 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