diff --git a/packages/harness-omp/README.md b/packages/harness-omp/README.md index 52c8073..be49e79 100644 --- a/packages/harness-omp/README.md +++ b/packages/harness-omp/README.md @@ -82,6 +82,14 @@ configuration for gateway/frontier models (delete the file or flip ignored, as are unknown keys (`generate_image` has no toggle and ships ~505 tokens regardless). +**`config/config.gateway-slim.yml`** — the measured middle ground (OPS-481, +docs/eval/2026-07-09-code-mode-vs-omp-discovery.md): full default tool harness +for gateway/frontier models, skills pinned to the shared allowlist. ~28.9k est +tokens vs ~47k ambient (-38%); the skills block is the profile's only +organically-growing cost (+1.7k/day observed from plugin sprawl). Regression +gate: `tools/measure-context.sh --budget 31000 --settings +config/config.gateway-slim.yml`. + **`tools/measure-context.sh`** measures the real footprint: it runs `omp -p` against a localhost capture sink under a throwaway profile and prints the system/tools/skills breakdown. Run it on every pin bump diff --git a/packages/harness-omp/config/config.gateway-slim.yml b/packages/harness-omp/config/config.gateway-slim.yml new file mode 100644 index 0000000..f0ec28f --- /dev/null +++ b/packages/harness-omp/config/config.gateway-slim.yml @@ -0,0 +1,32 @@ +# omp gateway-slim profile — full default TOOL harness, TRIMMED skill discovery. +# +# The measured middle ground (docs/eval/2026-07-09-code-mode-vs-omp-discovery.md, +# OPS-481, row D): the gateway/frontier profile's skill auto-discovery block is +# its largest and only ORGANICALLY-GROWING context cost (~16.5k est tokens and +# +1.7k in a single day from ambient plugin growth). Pinning skills to the +# shared allowlist — and nothing else — cut a live gateway profile from +# ~47.0k to ~28.9k est tokens (-38%) with zero tool-availability change. +# +# vs the other presets: +# config.local.yml — 32k-local-model profile: slims tools AND skills (~13k) +# this file — gateway models (200k ctx): full tools, slim skills (~29k) +# no settings file — omp defaults: full tools, ambient skills (~45k and growing) +# +# Install: copy to ~/.omp/agent/config.yml (never clobber live config). +# Keys are NESTED maps — dotted keys are silently ignored (verified live). +# The allowlist is CI-synced against packages/skills/ (tests/preset.test.ts). + +# --- role -> model mapping --------------------------------------------------- +modelRoles: + default: llm/zai/GLM-5.2 + +# --- skill discovery scoping (the ~16.5k lever; tools deliberately untouched) - +skills: + includeSkills: [local-model-triage] + enablePiUser: true # ~/.omp/agent/skills (omp-native user dir) + enablePiProject: true # .omp/skills in-repo + enableClaudeUser: false + enableClaudeProject: false + enableCodexUser: false + enableAgentsUser: false + enableAgentsProject: false diff --git a/packages/harness-omp/tests/preset.test.ts b/packages/harness-omp/tests/preset.test.ts index 6513e4b..5a41390 100644 --- a/packages/harness-omp/tests/preset.test.ts +++ b/packages/harness-omp/tests/preset.test.ts @@ -85,10 +85,41 @@ describe("config.local.yml", () => { }); }); +describe("config.gateway-slim.yml", () => { + const GATEWAY_SLIM = readFileSync(join(PKG, "config/config.gateway-slim.yml"), "utf8"); + const doc = Bun.YAML.parse(GATEWAY_SLIM) as Record; + + test("tools deliberately untouched (full gateway harness)", () => { + expect(doc.tools).toBeUndefined(); + }); + + test("includeSkills allowlist stays in sync with packages/skills", () => { + const skillsDir = join(PKG, "../skills"); + const shared = readdirSync(skillsDir, { withFileTypes: true }) + .filter((e) => e.isDirectory() && existsSync(join(skillsDir, e.name, "SKILL.md"))) + .map((e) => e.name) + .sort(); + const allowlist = ([...(doc.skills?.includeSkills ?? [])] as string[]).sort(); + expect(allowlist).toEqual(shared); + }); + + test("modelRoles point at models declared in models.yml", () => { + const models = Bun.YAML.parse(MODELS) as Record; + const declared = new Set(); + for (const [prov, p] of Object.entries(models.providers)) { + for (const m of p.models ?? []) declared.add(`${prov}/${m.id}`); + } + for (const [role, id] of Object.entries(doc.modelRoles ?? {})) { + expect(declared.has(id), `${role}: ${id}`).toBeTrue(); + } + }); +}); + describe("secretlessness", () => { test.each([ ["models.yml", MODELS], ["config.local.yml", SETTINGS], + ["config.gateway-slim.yml", readFileSync(join(PKG, "config/config.gateway-slim.yml"), "utf8")], ])("%s carries no secret-shaped strings", (_name, text) => { for (const needle of SECRETY) expect(text).not.toInclude(needle); });