omp-llm-role 1.0.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +202 -12
- package/agents/designer.md +4 -3
- package/docs/dev/README.md +44 -7
- package/docs/dev/agent-authoring.md +59 -1
- package/docs/dev/architecture.md +106 -28
- package/docs/dev/ci.md +163 -0
- package/docs/dev/current-state.md +364 -24
- package/docs/dev/data-sources.md +231 -38
- package/docs/dev/explorer.md +175 -46
- package/docs/dev/quirks.md +77 -4
- package/docs/dev/releasing.md +130 -17
- package/docs/dev/scoring.md +851 -27
- package/docs/dev/testing.md +253 -0
- package/docs/dev/writes-and-state.md +232 -28
- package/docs/llm-role-rankings.md +149 -148
- package/package.json +814 -80
- package/skills/omp-llm-role-create-agent/SKILL.md +7 -1
- package/src/agent-architect.ts +148 -19
- package/src/agent-create.ts +800 -40
- package/src/agent-file.ts +2 -5
- package/src/architect-provenance.ts +16 -0
- package/src/availability.ts +191 -15
- package/src/benchmark-author.ts +9 -4
- package/src/benchmark-sources.ts +283 -18
- package/src/cli/create-role.ts +29 -1
- package/src/cli/llm-role-rank.ts +40 -1
- package/src/config-edit.ts +207 -80
- package/src/engine.ts +519 -75
- package/src/error-report.ts +562 -0
- package/src/explorer/boot.ts +36 -24
- package/src/explorer/explain.ts +128 -13
- package/src/explorer/scopes.ts +110 -0
- package/src/explorer/server.ts +126 -33
- package/src/extension.ts +464 -48
- package/src/features.ts +105 -0
- package/src/project-registry.ts +65 -0
- package/src/project-setup.ts +382 -0
- package/src/prompts/agent-creation-architect.md +2 -0
- package/src/prompts/project-profile-architect.md +33 -0
- package/src/prompts/project-profile-user.md +8 -0
- package/src/provider-display.ts +67 -0
- package/src/role-archetypes.ts +12 -2
- package/src/role-settings.ts +22 -0
- package/src/settings.ts +211 -24
- package/src/state.ts +1 -1
- package/src/updater.ts +234 -37
- package/web/app.js +434 -12
- package/web/index.html +1 -0
- package/web/style.css +44 -1
- package/docs/dev/spec.md +0 -633
package/README.md
CHANGED
|
@@ -48,6 +48,16 @@ omp plugin install omp-llm-role@gott50-plugins
|
|
|
48
48
|
session actually booted on the previous `default` selector (an explicit
|
|
49
49
|
`omp --model X` is never clobbered), and only on a real change. Disable with
|
|
50
50
|
`activateDefaultOnEmptySession=false`.
|
|
51
|
+
- **Provider in the model display.** When the live session model carries a
|
|
52
|
+
provider pin — a hand-set `providerPin`, or the automatic pin the
|
|
53
|
+
`providerPinning` capability writes — the status line's model segment shows
|
|
54
|
+
the route next to the model name, e.g. `DeepSeek V4.1 Flash @coreweave/fp8`.
|
|
55
|
+
The suffix is applied on session start, refreshed when a fallback switches the
|
|
56
|
+
model, and re-derived at the start of every turn, so it self-heals after omp
|
|
57
|
+
silently restores the primary model following a fallback cooldown. An unpinned
|
|
58
|
+
model's display is unchanged, and the suffix is display-only: it rides the
|
|
59
|
+
model object's `name`, so attribution, usage recording and model comparison
|
|
60
|
+
are unaffected.
|
|
51
61
|
- **Surgical writes.** Only managed role lines, managed chain keys, and the
|
|
52
62
|
plugin-managed `task.disabledAgents` names change; comments, blank lines and
|
|
53
63
|
unknown keys stay byte-identical, and a no-change run writes nothing.
|
|
@@ -62,7 +72,7 @@ omp plugin install omp-llm-role@gott50-plugins
|
|
|
62
72
|
| `smol` | Fast lightweight model: cheap and quick, still competent |
|
|
63
73
|
| `slow` | Most capable model for hard problems; cost and speed as tiebreakers |
|
|
64
74
|
| `vision` | Image understanding: vision index dominates |
|
|
65
|
-
| `plan` | Planning: reasoning
|
|
75
|
+
| `plan` | Planning: reasoning and long-context coherence, priced so the cheapest capable planner wins |
|
|
66
76
|
| `commit` | Commit messages: cheap and fast with decent general quality |
|
|
67
77
|
| `tiny` | Background tasks (titles, memory): cheapest and fastest wins |
|
|
68
78
|
| `task` | Subagents: agentic + tool calling, moderate cost sensitivity |
|
|
@@ -110,6 +120,7 @@ Global knobs:
|
|
|
110
120
|
| `writeFallbackChains` | `true` | Write per-role fallback chains into `config.yml` |
|
|
111
121
|
| `fallbackChainDepth` | `2` | Fallback models per role chain |
|
|
112
122
|
| `activateDefaultOnEmptySession` | `true` | Reapply the new `default` selector to an empty session's active model |
|
|
123
|
+
| `errorReporting` | `off` | Opt-in reporting of **unexpected** plugin errors as GitHub issues on `Gott50/omp-llm-role`; one of `off`, `ask`, `auto` (see below) |
|
|
113
124
|
|
|
114
125
|
Per-role knobs (`roles.<name>.*`):
|
|
115
126
|
|
|
@@ -120,10 +131,100 @@ Per-role knobs (`roles.<name>.*`):
|
|
|
120
131
|
| `weights` | shipped set | Metric weights; must sum to 1.0 ± 0.01 |
|
|
121
132
|
| `required` | shipped set | Eligibility gate (metrics a model must have); independent of weights |
|
|
122
133
|
| `filters.image` | `false` (`vision`/`designer`: `true`) | Restrict the pool to image-capable models |
|
|
134
|
+
| `filters.tools` | `false` | Restrict the pool to models with a tool-capable route |
|
|
135
|
+
| `filters.minContextTokens` | `0` (off) | Drop routes whose endpoint context is below this (tokens) |
|
|
136
|
+
| `filters.minOutputTokens` | `0` (off) | Drop routes whose endpoint output ceiling is below this (tokens) |
|
|
137
|
+
| `filters.maxPriceUsdPerM` | `0` (off) | Drop a model whose thinking-adjusted blend exceeds this ($/M) |
|
|
123
138
|
| `thinking` | shipped level | Thinking level appended to the selector (`off`…`max`, `auto`) |
|
|
139
|
+
| `providerPin` | `""` (unset) | Pin the role's requests to one OpenRouter provider route (`@<slug>`, may be tiered like `deepinfra/fp8`). The role is then priced and gated by that route — its billed price and p50 throughput, not the `1/price²` blend — and a model with no matching route is ineligible. A manual pin **overrides** the automatic pin the `providerPinning` capability would write |
|
|
140
|
+
| `cacheHitRate` | `0` (off) | Assumed cache-hit rate (0–1) for the role's input tokens; each route's effective input price becomes `h·cacheRead + (1−h)·input` before the 3:1 billed blend and the thinking factor. The `1/price²` weight basis stays the **listed** input price (the router's sort key), so a cheap cache on a lightly-weighted route cannot dominate; a route with no cache-read price keeps its full input price. `0`/absent = off (byte-identical ranking) |
|
|
124
141
|
| `lambda` | derived | Explicit λ ($ per quality point) override |
|
|
125
142
|
| `locked` | `false` | Leave the role alone: rank it but never rewrite its selector or chain (explorer toggle) |
|
|
126
143
|
|
|
144
|
+
**Capability flags** (`features.<id>` global, `roles.<role>.features.<id>` per
|
|
145
|
+
role). One named flag per opt-in capability; turning it on applies the plugin's
|
|
146
|
+
recommended settings for that capability to the role. Every individual knob
|
|
147
|
+
stays settable, and an explicit knob always beats the flag. **Every flag ships
|
|
148
|
+
OFF** — with no flags set, the resolved roles are byte-identical to the shipped
|
|
149
|
+
defaults.
|
|
150
|
+
|
|
151
|
+
| Flag | Recommended settings | What it buys |
|
|
152
|
+
|---|---|---|
|
|
153
|
+
| `endpointCeilings` | `filters.tools: true`, `filters.minOutputTokens: 16384` | Routes that cannot call tools and routes whose output ceiling is below 16 384 tokens leave the pool — a reasoning model is not cut off mid-thought |
|
|
154
|
+
| `cachePricing` | `cacheHitRate: 0.5` | The role is priced on a cache-heavy agent loop's invoice (the endpoint's `cacheReadPrice` blended in) rather than the sticker price |
|
|
155
|
+
| `providerPinning` | `preferOwnProvider: true`, `filters.preferredMinThroughput: 50` | Each request is bound to the model's **best provider route** — the max-value-for-money route (the `vfm` score, with a soft 50 tok/s floor that deprioritizes a pathologically slow route without dropping it) — the selector gains `@<slug>` — and the fallback chain carries the primary model on every gate-passing route except the pinned best, then each fallback model on every gate-passing route, so a down provider fails over to another provider of the same model before the chain switches models. The model is priced **and measured** on that route (its billed price and p50 throughput, so `q` moves too), falling back to the default blend only when it has no candidate route |
|
|
156
|
+
| `costCap` | `filters.maxPriceUsdPerM: 10` | The priciest tail of the eligible pool leaves it, so the pick cannot be an expensive outlier |
|
|
157
|
+
|
|
158
|
+
Precedence is one rule:
|
|
159
|
+
|
|
160
|
+
```
|
|
161
|
+
effective def = shipped default ⊕ preset(enabled flags) ⊕ explicit user keys
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
A flag is on when `roles.<role>.features.<id>` is present (it wins either way)
|
|
165
|
+
and otherwise when the global `features.<id>` is `true` — so a per-role `false`
|
|
166
|
+
beats a global `true`. The preset fills only knobs the role does not already
|
|
167
|
+
set, and an explicit key is merged last, so it always wins. `providerPinning`'s
|
|
168
|
+
recommended setting is a **soft per-model policy** (`preferOwnProvider`), not a
|
|
169
|
+
hard `providerPin`: it prices a model on its **best route** (the max-`vfm` route
|
|
170
|
+
— the value-for-money score, with the soft 50 tok/s floor — among the
|
|
171
|
+
filter-passing, non-degraded, priced routes the account's
|
|
172
|
+
allowed-providers whitelist permits) — the route's billed price
|
|
173
|
+
**and** its p50 throughput, so `q` moves as well as `priceEff` — and never makes
|
|
174
|
+
a model ineligible (the hard `providerPin` stays available by hand, and overrides
|
|
175
|
+
the automatic choice). `minContextTokens` is deliberately **not** part of `endpointCeilings` —
|
|
176
|
+
the complaint it would answer is an endpoint advertising a *fraction of the
|
|
177
|
+
model's own window*, which an absolute token floor cannot express, so it stays a
|
|
178
|
+
hand-set knob.
|
|
179
|
+
|
|
180
|
+
The flags are settable from every role-authoring surface: `--feature <id,...>`
|
|
181
|
+
(comma-separated) on `node src/cli/create-role.ts`, `/create-agent` and
|
|
182
|
+
`/project-roles` (`--list-features` lists them on the first two), plus the
|
|
183
|
+
explorer's Features panel. An
|
|
184
|
+
unknown flag id or a non-boolean value aborts the run with the offending key and
|
|
185
|
+
no write.
|
|
186
|
+
|
|
187
|
+
**Error reporting (`errorReporting`).** This knob ships **`off`** — installing
|
|
188
|
+
or upgrading the plugin never starts uploading anything. When something
|
|
189
|
+
*genuinely unexpected* happens (a `/refresh-roles` or authoring command throws,
|
|
190
|
+
or the updater hits an internal error), the plugin can file one structured
|
|
191
|
+
report — the plugin version, runtime, platform, the command that failed, the
|
|
192
|
+
error name/message/stack and a timestamp — as a GitHub issue on
|
|
193
|
+
`Gott50/omp-llm-role`. The three values:
|
|
194
|
+
|
|
195
|
+
- **`off`** — never files; behaviour is exactly today's (one warning line).
|
|
196
|
+
- **`ask`** — shows you the exact text and files it only if you confirm. In a
|
|
197
|
+
session with no UI (`omp -p`, RPC, a subagent) it never uploads: it notifies a
|
|
198
|
+
prefilled new-issue URL instead, so you can submit it yourself.
|
|
199
|
+
- **`auto`** — files without asking.
|
|
200
|
+
|
|
201
|
+
The payload is redacted before it leaves the machine (your home directory → `~`,
|
|
202
|
+
token-shaped strings → `<redacted>`) and carries **no** config contents, model
|
|
203
|
+
selectors, prompts or history rows. Filing goes through the GitHub API when a
|
|
204
|
+
token is available (`GITHUB_TOKEN` → `GH_TOKEN` → `gh auth token` — the token is
|
|
205
|
+
never stored in a settings file); a token that cannot write issues here, or no
|
|
206
|
+
token at all, falls through to a prefilled `…/issues/new` URL (opened in your
|
|
207
|
+
browser, or printed). A repeated crash comments on the existing open issue
|
|
208
|
+
instead of opening a new one, and the path is capped (one open issue per
|
|
209
|
+
fingerprint, one creation per fingerprint per UTC day, 3 per day) so a crash
|
|
210
|
+
loop cannot spam the tracker. Reporting is **best-effort**: a failure in it only
|
|
211
|
+
adds one notification line and never affects the run it reports on. Expected
|
|
212
|
+
environment conditions (no key budget, a concurrent refresh holding the lock,
|
|
213
|
+
write conflicts, unavailable ranking data, invalid settings) are **never**
|
|
214
|
+
reported. In project mode the project lock file's value applies.
|
|
215
|
+
|
|
216
|
+
**Validation.** A run aborts (notify, no write) on: a weight ≤ 0, or a role's
|
|
217
|
+
weights not summing to 1.0 ± 0.01; a `required` entry or a weighted metric
|
|
218
|
+
outside the known-metric set; a `thinking` level outside
|
|
219
|
+
`off|minimal|low|medium|high|xhigh|max|auto`; `switchMargin`/`priceSwitchFraction`
|
|
220
|
+
outside `[0, 1]`; a non-boolean `enabled`; a `cacheHitRate` outside `[0, 1]`; a
|
|
221
|
+
`providerPin` that is empty or
|
|
222
|
+
contains `@`/`:` (the selector's own delimiters); an unknown capability id
|
|
223
|
+
(global or per-role) or a non-boolean flag value; a non-boolean
|
|
224
|
+
`preferOwnProvider`. `weights: null` opts a role out;
|
|
225
|
+
the legacy `suffixes.*` keys are rejected with a migration hint (moved into
|
|
226
|
+
`roles.<role>.thinking`).
|
|
227
|
+
|
|
127
228
|
**Typed writes.** `omp plugin config set <plugin> <key> <value>` stores every
|
|
128
229
|
value as a **string**, which the validator rejects for numbers/arrays/booleans,
|
|
129
230
|
so it is only usable for string-valued keys. Write typed role defs with
|
|
@@ -144,10 +245,11 @@ with the offending role/key and no write.
|
|
|
144
245
|
/create-agent <request> [options] # agent + role + wiring (free text or flags)
|
|
145
246
|
/create-agent --name <n> --purpose <text> [options] # agent + role + wiring
|
|
146
247
|
/remove-agent --name <n> [--scope user|project] [--lock PATH] [--yes] [--dry-run] # delete an agent and its role
|
|
248
|
+
/project-roles [--purpose <text>] [--roles <spec>] [--feature <id,...>] [--force] [--yes] [--dry-run] [--json] # project-scoped role set
|
|
147
249
|
|
|
148
250
|
# CLI
|
|
149
251
|
node src/cli/llm-role-rank.ts [--top N] [--json] [--out FILE] [--refresh] [--all] [--url URL]
|
|
150
|
-
node src/cli/create-role.ts --name <role> --weights m=w,... [--required m,...] [--thinking <level>] [--description <text>] [--image] [--lambda N] [--lock PATH] [--dry-run] [--json]
|
|
252
|
+
node src/cli/create-role.ts --name <role> --weights m=w,... [--required m,...] [--thinking <level>] [--description <text>] [--image] [--lambda N] [--feature <id,...>] [--list-features] [--lock PATH] [--dry-run] [--json]
|
|
151
253
|
node --test tests/
|
|
152
254
|
```
|
|
153
255
|
|
|
@@ -161,6 +263,9 @@ node --test tests/
|
|
|
161
263
|
- `/remove-agent` — the inverse of `/create-agent`: deletes the agent `.md` and
|
|
162
264
|
its role, then runs the updater in-process so `modelRoles.<n>` is dropped;
|
|
163
265
|
refuses shipped default roles (see *Remove a specialist agent*).
|
|
266
|
+
- `/project-roles` — discover the project's usecase from its own artifacts and
|
|
267
|
+
apply a project-scoped role set to `<cwd>/.omp/config.yml` (see *Project
|
|
268
|
+
roles*).
|
|
164
269
|
- `src/cli/llm-role-rank.ts` — markdown report to stdout (per-role tables + suggested
|
|
165
270
|
`modelRoles`). `--top N` rows per role (default 10); `--json` machine payload;
|
|
166
271
|
`--out FILE` write instead of stdout; `--refresh` bypass both caches; `--all`
|
|
@@ -193,6 +298,25 @@ agent is ranked on WritingBench, Creative Writing v3, COLLIE and the other
|
|
|
193
298
|
writing benchmarks, not just the one you named. Discovery is non-fatal and
|
|
194
299
|
skippable with `--no-discover`; an explicit `--benchmarks` list wins over it.
|
|
195
300
|
|
|
301
|
+
Discovery is **quality-gated**: each candidate is assessed on nine axes —
|
|
302
|
+
coverage (share of the field carrying the metric), dispersion (does it separate
|
|
303
|
+
models), provider composition, freshness, trust (the share of the payload's
|
|
304
|
+
entries that are self-reported, so a mostly vendor-submitted source is flagged),
|
|
305
|
+
modality (the catalog row's modality and the payload's multimodal share — an
|
|
306
|
+
annotation, never a gate), maintenance (the catalog row's dataset age against
|
|
307
|
+
a 12-month bar — an annotation, never a gate), provenance (the benchmark's
|
|
308
|
+
owner and the source's own per-entry org mix, cross-checked against the
|
|
309
|
+
composition axis — an annotation, never a gate) and cross-source (the zeroeval
|
|
310
|
+
per-entry price/context against the plugin's own, flagging a divergence past a
|
|
311
|
+
tolerance — an annotation, never a gate, and never a change to the `1/price²`
|
|
312
|
+
blend) — and a discovered benchmark that
|
|
313
|
+
fails a gating axis is dropped rather than folded in (a benchmark you name yourself is
|
|
314
|
+
never dropped, only warned). The focus set is capped at three benchmarks so one
|
|
315
|
+
keeps a decisive share. The report prints the nine signals and warns per below-bar
|
|
316
|
+
axis, and warns when the new role's top pick is the same as the `default` role's
|
|
317
|
+
(the role adds nothing). The agent file is written before the role, so a partial
|
|
318
|
+
failure never leaves a dangling role.
|
|
319
|
+
|
|
196
320
|
The flag form is equivalent and gives you the name explicitly:
|
|
197
321
|
|
|
198
322
|
```sh
|
|
@@ -206,7 +330,9 @@ validated role into the settings lock file, and runs the updater in-process so
|
|
|
206
330
|
`modelRoles.review` lands in `config.yml` — nothing to remember. Options:
|
|
207
331
|
`--archetype <id>`, `--weights m=w,...`, `--required`, `--thinking`, `--tools`,
|
|
208
332
|
`--benchmarks m,...` (extra metrics to fold in; `--list-benchmarks` prints the
|
|
209
|
-
weightable set, including any external benchmark in use), `--
|
|
333
|
+
weightable set, including any external benchmark in use), `--feature <id,...>`
|
|
334
|
+
(comma-separated capability flags; `--list-features` prints the capability set),
|
|
335
|
+
`--scope user|project`,
|
|
210
336
|
`--body`/`--body-file`, `--force` (overwrite an existing agent file), `--yes`
|
|
211
337
|
(accept a proposed benchmark source without prompting), `--no-discover` (skip
|
|
212
338
|
catalog discovery), `--dry-run`, `--json`. In
|
|
@@ -253,6 +379,32 @@ By hand, the same two artifacts:
|
|
|
253
379
|
2. Delete the agent file: `rm ~/.omp/agent/agents/review.md`.
|
|
254
380
|
3. Wire it: `/refresh-roles` in a session.
|
|
255
381
|
|
|
382
|
+
## Project roles
|
|
383
|
+
|
|
384
|
+
`/project-roles` discovers a project's usecase from its own artifacts (README,
|
|
385
|
+
package.json, AGENTS.md, docs listing, git log, file tree) and applies a
|
|
386
|
+
**project-scoped** role set — the roles the project needs, with agents authored
|
|
387
|
+
for the new ones — to `<cwd>/.omp/config.yml`:
|
|
388
|
+
|
|
389
|
+
```sh
|
|
390
|
+
/project-roles
|
|
391
|
+
/project-roles --purpose "a Python data pipeline repo" --dry-run
|
|
392
|
+
/project-roles --roles "data=build pipelines,-vision,default"
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
It prints the plan (kept / dropped / added roles, each new role's archetype,
|
|
396
|
+
weights, focus benchmarks and top pick) before writing. `--purpose` overrides the
|
|
397
|
+
discovered usecase; `--roles` overrides the role set (`-name` drops a shipped
|
|
398
|
+
role, `name` keeps or adds one, `name=purpose` adds a new role); `--dry-run`
|
|
399
|
+
writes nothing; without `--force` an existing project role config is refused.
|
|
400
|
+
|
|
401
|
+
When a project carries its own `omp-llm-role` settings entry, the updater scopes
|
|
402
|
+
the whole run to `<cwd>/.omp` — the config, the state/history/lock files and the
|
|
403
|
+
day gate — so the project's `modelRoles` are refreshed independently of the
|
|
404
|
+
global `~/.omp/agent/config.yml`, which is never written in project mode. A
|
|
405
|
+
successful apply registers the project, so the explorer's **scope switcher**
|
|
406
|
+
lists it (see below).
|
|
407
|
+
|
|
256
408
|
## Explorer
|
|
257
409
|
|
|
258
410
|
`/explore-roles` in omp boots a loopback-only web UI
|
|
@@ -260,6 +412,15 @@ By hand, the same two artifacts:
|
|
|
260
412
|
`@slow`?" and "what happens if I care more about price than agents?" without
|
|
261
413
|
editing source and re-running the CLI.
|
|
262
414
|
|
|
415
|
+
- **Scope switcher** — the header lists every role-config source: the
|
|
416
|
+
**user-level** scope, plus every project where `/project-roles` was used (the
|
|
417
|
+
plugin records each project root in a small global registry, and the current
|
|
418
|
+
session's project is listed immediately). The explorer opens on the session's
|
|
419
|
+
project when the cwd has a project role config, else user-level. Switching
|
|
420
|
+
re-reads that scope's roles and universe from disk and points **Export** at
|
|
421
|
+
that scope's lock file — a project scope resolves as the project lock merged
|
|
422
|
+
over the user-level lock, exactly what the updater ranks. A project whose lock
|
|
423
|
+
file is gone is shown disabled. Switching with unsaved edits asks first.
|
|
263
424
|
- **Role tabs** — every role the plugin knows: the nine omp built-in roles, the
|
|
264
425
|
shipped opt-in `designer`, and any role present only in the lock file. Each
|
|
265
426
|
tab is tinted by provenance — `default` (omp built-in), `plugin` (shipped but
|
|
@@ -307,12 +468,30 @@ The plugin keeps only models the OpenRouter key can actually run:
|
|
|
307
468
|
- **Tier/budget gate** — paid keys with budget get billed variants, free or
|
|
308
469
|
exhausted keys get `:free` variants, `:batch` never. Every candidate must
|
|
309
470
|
resolve in omp's catalog.
|
|
310
|
-
- **
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
471
|
+
- **Keyed-catalog fast path** — when the account's OpenRouter setting **"Filter the
|
|
472
|
+
model catalog for API keys"** is on, the key-authenticated `GET /api/v1/models` is a
|
|
473
|
+
per-key allowlist: allowed candidates skip the probe and key-blocked candidates are
|
|
474
|
+
pruned from the walk. With the setting off (or the fetch failing) the plugin falls
|
|
475
|
+
back to the probe walk below — no abort.
|
|
476
|
+
- **Probe verification** — the fallback: every candidate is verified with a one-token
|
|
477
|
+
completion probe, because the account's OpenRouter **allowed-providers privacy
|
|
478
|
+
whitelist** is invisible to the key endpoint and the unauthenticated catalog, and a
|
|
479
|
+
real request's 404 is the only reliable signal. Blocked candidates are excluded from
|
|
480
|
+
selection and chains; a role with no clean candidate is left untouched.
|
|
481
|
+
- **Allowed-providers whitelist** — the account's OpenRouter **allowed-providers
|
|
482
|
+
privacy whitelist** (openrouter.ai/settings/privacy) is learned once per run (a
|
|
483
|
+
canary request that bills no tokens) and every model's route pool is narrowed to
|
|
484
|
+
allowed providers before ranking, so a pin or a fallback hop is never written on a
|
|
485
|
+
provider the account cannot use. The run notes `OpenRouter allowed-providers
|
|
486
|
+
whitelist active — N providers; M routes pruned` (or `… whitelist: no whitelist`).
|
|
487
|
+
With no whitelist set — or when the harvest fails — nothing changes.
|
|
488
|
+
- **Explorer key marking** — the explorer overlays every ranked model with a
|
|
489
|
+
**usable** / **key-blocked** / **unknown** badge derived from the
|
|
490
|
+
key-authenticated `GET /api/v1/models` (the account setting **"Filter the model
|
|
491
|
+
catalog for API keys"** makes it a per-key allowlist). A **hide key-blocked**
|
|
492
|
+
toggle drops blocked rows, and when the setting is off every badge reads
|
|
493
|
+
*unknown* with a hint naming the OpenRouter setting. The mark is read-only: it
|
|
494
|
+
never edits roles, reorders ranks or changes an Export.
|
|
316
495
|
|
|
317
496
|
## Caveats
|
|
318
497
|
|
|
@@ -320,10 +499,21 @@ The plugin keeps only models the OpenRouter key can actually run:
|
|
|
320
499
|
occupying its share of the denominator, so weight sparse metrics as
|
|
321
500
|
differentiators, never as `required` gates. `website`, `writing` and
|
|
322
501
|
`long_context` are capability-filled (0.195) instead, so absence is not a
|
|
323
|
-
penalty for them
|
|
502
|
+
penalty for them — with one residual inversion: the fill sits above the bottom
|
|
503
|
+
of the covered field, so a covered model in the bottom of the field can still
|
|
504
|
+
score below a model with no data (see
|
|
505
|
+
[docs/dev/quirks.md](docs/dev/quirks.md)).
|
|
324
506
|
- **Provider whitelist.** The account's allowed-providers whitelist blocks many
|
|
325
507
|
models, so the report's #1 and the written selector can differ — judge weights
|
|
326
|
-
on the reachable pool.
|
|
508
|
+
on the reachable pool. The updater prunes *routes* to the whitelist (see
|
|
509
|
+
Availability), but the report has no token and is not whitelist-aware.
|
|
510
|
+
- **Provider pinning opts out of auto-Exacto.** A `providerPin` — or the
|
|
511
|
+
automatic pin the `providerPinning` capability writes — puts a trailing
|
|
512
|
+
`@<slug>` on the selector, which omp applies as OpenRouter
|
|
513
|
+
`provider: { only: [slug] }` routing. `only` is exclusive, so a pinned role's
|
|
514
|
+
requests bypass OpenRouter's automatic Exacto tool routing (which routes tool
|
|
515
|
+
calls by tool-call correctness) and run on the pinned route. Pin only where you
|
|
516
|
+
know the endpoint you want; leave tool-heavy roles on the default routing.
|
|
327
517
|
- **Model concentration.** The cheapest pick concentrates on one vendor; the
|
|
328
518
|
fallback chains mitigate it.
|
|
329
519
|
|
|
@@ -334,6 +524,6 @@ MIT — see [LICENSE](LICENSE).
|
|
|
334
524
|
## Documentation
|
|
335
525
|
|
|
336
526
|
Maintainer docs (architecture, data sources, scoring, writes/state, explorer
|
|
337
|
-
internals, releasing, agent authoring,
|
|
527
|
+
internals, releasing, agent authoring, testing) live in
|
|
338
528
|
[docs/dev/README.md](docs/dev/README.md); release history is in
|
|
339
529
|
[CHANGELOG.md](CHANGELOG.md).
|
package/agents/designer.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: designer
|
|
3
|
-
description: UI/UX
|
|
3
|
+
description: MUST be used for UI/UX design implementation, review, and visual refinement.
|
|
4
4
|
model: "@designer, @default"
|
|
5
|
-
tools: [read,
|
|
5
|
+
tools: [read, grep, glob, find, edit, write, bash, ast_grep, ast_edit, eval, lsp, web_search, ask, todo, task, wait, checkpoint, rewind]
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
Implement/review UI designs; edit files, create components, run commands as needed.
|
|
@@ -30,6 +30,7 @@ Design system: foundation; UI without one becomes inconsistent. Four phases, in
|
|
|
30
30
|
3. Implement states: loading, empty, error, disabled, hover, focus.
|
|
31
31
|
4. Verify accessibility: contrast, focus rings, semantic HTML.
|
|
32
32
|
5. Test responsive behavior.
|
|
33
|
+
6. Render and inspect: start the project's dev server (or open the built page), open the route in the browser via `eval` (`browser.open`), `screenshot` it, and check the project's actual breakpoints, both light and dark themes, and focus states. The `browser` facade is an Eval prelude, not an agent tool, so it cannot appear in `tools:` — the instruction lives here in the body.
|
|
33
34
|
|
|
34
35
|
## Review
|
|
35
36
|
1. Read reviewed files.
|
|
@@ -56,7 +57,7 @@ Design system: foundation; UI without one becomes inconsistent. Four phases, in
|
|
|
56
57
|
- Same spacing everywhere: no rhythm; monotony
|
|
57
58
|
- Center-aligning everything: left alignment with asymmetry feels more designed
|
|
58
59
|
- Modals for everything: lazy, rarely best
|
|
59
|
-
- Overused fonts: Inter, Roboto, Open Sans, system defaults
|
|
60
|
+
- Overused fonts when the project has no type system: Inter, Roboto, Open Sans, system defaults.
|
|
60
61
|
- Pure black (`#000`) or white (`#fff`): ALWAYS tint neutrals
|
|
61
62
|
- Gray text on colored backgrounds: use a background shade instead
|
|
62
63
|
- Bounce/elastic easing: dated, tacky; use exponential easing (`ease-out-quart`/`expo`)
|
package/docs/dev/README.md
CHANGED
|
@@ -4,6 +4,18 @@ Maintainer docs for the omp-llm-role plugin. `README.md` is for people *using*
|
|
|
4
4
|
the plugin; everything here is for people *changing* it. A fact has exactly one
|
|
5
5
|
home — if it is here, it is not in the README.
|
|
6
6
|
|
|
7
|
+
## Development setup
|
|
8
|
+
|
|
9
|
+
Clone, then install the dev dependency and wire the commit gate:
|
|
10
|
+
|
|
11
|
+
```sh
|
|
12
|
+
npm install
|
|
13
|
+
git config core.hooksPath .githooks
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
`.githooks/pre-commit` refuses staged `cache/` paths (daily UTC caches,
|
|
17
|
+
regenerated on every run) and runs the test suite (`node --test tests/`).
|
|
18
|
+
|
|
7
19
|
## Where to start
|
|
8
20
|
|
|
9
21
|
| If you are changing… | Read |
|
|
@@ -14,9 +26,10 @@ home — if it is here, it is not in the README.
|
|
|
14
26
|
| a config write, the state/history/lock files, or the write gate | [writes-and-state.md](writes-and-state.md) |
|
|
15
27
|
| the explorer surface (server, explain layer, SPA) | [explorer.md](explorer.md) |
|
|
16
28
|
| the dated numbers (matched/priced/eligible counts, per-role leaders) | [current-state.md](current-state.md) |
|
|
17
|
-
| a release (version bump, npm/git/marketplace channels) | [releasing.md](releasing.md) |
|
|
29
|
+
| a release (version bump, SemVer, CHANGELOG rules, npm/git/marketplace channels) | [releasing.md](releasing.md) |
|
|
30
|
+
| the CI workflow, the release script, or the tag→publish contract | [ci.md](ci.md) |
|
|
18
31
|
| the agent `.md` contract (frontmatter, routing, read-only rules) | [agent-authoring.md](agent-authoring.md) |
|
|
19
|
-
|
|
|
32
|
+
| the test suite or a verification scenario | [testing.md](testing.md) |
|
|
20
33
|
| a debugging-only oddity (a quirk, not a contract) | [quirks.md](quirks.md) |
|
|
21
34
|
|
|
22
35
|
## The docs
|
|
@@ -41,14 +54,38 @@ home — if it is here, it is not in the README.
|
|
|
41
54
|
- **[current-state.md](current-state.md)** — the dated snapshot:
|
|
42
55
|
matched/priced/eligible counts, per-role leaders, and the open defects.
|
|
43
56
|
Refresh it with each run.
|
|
44
|
-
- **[releasing.md](releasing.md)** — the
|
|
45
|
-
`
|
|
46
|
-
|
|
57
|
+
- **[releasing.md](releasing.md)** — when and how to bump the version (the
|
|
58
|
+
`package.json` release switch, the SemVer surface), how to cut a release,
|
|
59
|
+
the CHANGELOG entry rules, the npm/git/marketplace channels, the tarball
|
|
60
|
+
`files` whitelist, and the install-route verification.
|
|
61
|
+
- **[ci.md](ci.md)** — the GitHub Actions pipeline: the `test`/`release` jobs
|
|
62
|
+
and their triggers, the tag→publish contract, the one-time trusted-publisher
|
|
63
|
+
registration, the `scripts/release.ts` subcommands and refusals, and how to
|
|
64
|
+
verify the pipeline.
|
|
47
65
|
- **[agent-authoring.md](agent-authoring.md)** — the agent `.md` contract:
|
|
48
66
|
frontmatter (`model: "@<role>, @default"`, `tools:`), the routing
|
|
49
67
|
description, read-only classification, and where agents are discovered.
|
|
50
|
-
- **[
|
|
51
|
-
|
|
68
|
+
- **[testing.md](testing.md)** — the test-suite seam map (which test file covers
|
|
69
|
+
which scenario) and the live checks that need a real omp session.
|
|
52
70
|
- **[quirks.md](quirks.md)** — debugging-only oddities and gotchas that are not
|
|
53
71
|
contracts (e.g. Node type-stripping not typechecking, stale in-process plugin
|
|
54
72
|
code).
|
|
73
|
+
|
|
74
|
+
## Research notes
|
|
75
|
+
|
|
76
|
+
External material that informs (but does not bind) the design. Not contracts.
|
|
77
|
+
|
|
78
|
+
- **[../research/agentic-engineering-benchmarks.md](../research/agentic-engineering-benchmarks.md)**
|
|
79
|
+
— IndyDevDan's "top 5 agentic-engineering benchmarks" video, mapped onto the
|
|
80
|
+
project's coverage/collinearity rules; records the two axes the project lacks
|
|
81
|
+
(guardrails, hallucination), the missing agentic categories, and the
|
|
82
|
+
per-task-vs-$/M cost gap. Source transcript alongside it
|
|
83
|
+
(`agentic-engineering-benchmarks.transcript.txt`).
|
|
84
|
+
- **[../research/openrouter-endpoint-routing.md](../research/openrouter-endpoint-routing.md)**
|
|
85
|
+
— Kai's "OpenRouter is quietly giving nerfed AI models" video, mapped onto the
|
|
86
|
+
project's OpenRouter data model; confirms the `1/price²` blend, argues
|
|
87
|
+
quantization labels are not a quality signal, and records the per-endpoint
|
|
88
|
+
capability ceilings (context, max output, tool support) the project now uses as
|
|
89
|
+
role filters (issue #18), the opt-in cache-read pricing (issue #30) and
|
|
90
|
+
provider pinning, and the remaining declared-rate-vs-measured-hit gap. Source
|
|
91
|
+
transcript alongside it (`openrouter-endpoint-routing.transcript.txt`).
|
|
@@ -128,10 +128,68 @@ effect on the next session.
|
|
|
128
128
|
`src/benchmark-discovery.ts`) and folds them in. The resolved benchmark
|
|
129
129
|
labels are given to the architect (and, on the template path, listed in the
|
|
130
130
|
body's `<criteria>`), so the agent's rubric names the benchmark its model was
|
|
131
|
-
chosen on.
|
|
131
|
+
chosen on. Discovery is **quality-gated**: the pre-fetch catalog gate is
|
|
132
|
+
count-only, and the handler then probe-fetches each selected candidate's source
|
|
133
|
+
and assesses the joined pool on nine axes (`assessFocusMetric`: coverage,
|
|
134
|
+
dispersion, composition, freshness, trust, modality, maintenance, provenance,
|
|
135
|
+
cross-source — see scoring.md). A
|
|
136
|
+
**discovered** candidate below-bar on any gating axis is dropped non-fatally
|
|
137
|
+
with a reason naming the axis; a **user-named** metric is never dropped — it is
|
|
138
|
+
annotated and warned. The
|
|
139
|
+
focus set is capped at `FOCUS_METRIC_CAP` (3) so one benchmark keeps a decisive
|
|
140
|
+
share. The report prints the nine signals and warns per below-bar axis;
|
|
141
|
+
`--dry-run` and `--json` carry the same signal. The agent file is written **before** the role,
|
|
142
|
+
so a partial failure leaves a harmless agent (its `@<name>, @default` chain
|
|
143
|
+
falls back to `@default`) rather than a dangling role; a failed role write
|
|
144
|
+
rolls the agent file back — restoring the prior file on a `--force` re-create,
|
|
145
|
+
else removing the new one — so a retry needs no `--force` and the user's prior
|
|
146
|
+
agent is never destroyed. A malformed architect response is retried once (a
|
|
147
|
+
parse failure only — a `run()` failure propagates immediately, since a second
|
|
148
|
+
session would fail the same way), and the final error carries the raw architect
|
|
149
|
+
output so the failure surfaces what the architect actually said. The step-3
|
|
150
|
+
benchmark prompt previews the request's
|
|
151
|
+
resolved weights (`resolveRole`), so the "already in this role's weights"
|
|
152
|
+
marker appears live.
|
|
153
|
+
- **Capability flags on `/create-agent`.** `--feature <id,...>` (comma-separated)
|
|
154
|
+
sets the new role's `features.<id>` so it starts from the plugin's recommended
|
|
155
|
+
settings for that capability; `--list-features` prints each capability id, the
|
|
156
|
+
settings it applies and what it buys, without creating anything. An unknown id
|
|
157
|
+
fails with a non-zero exit and no write. The archetype table
|
|
158
|
+
(`src/role-archetypes.ts`) carries an optional `features` list the architect
|
|
159
|
+
may *propose*, but **no archetype auto-applies a flag** — a role gets a flag
|
|
160
|
+
only when the user asks for it. `create-role.ts` exposes the same
|
|
161
|
+
`--feature`/`--list-features` surfaces, and `/project-roles` takes `--feature`
|
|
162
|
+
(its help points at `/create-agent --list-features`).
|
|
163
|
+
- **`/project-roles`** (in-session) discovers the project's usecase from its own
|
|
164
|
+
artifacts through the profile architect, then authors an agent per new role
|
|
165
|
+
**into the project scope** (`<cwd>/.omp/agents/`) and writes the project's
|
|
166
|
+
`modelRoles` to `<cwd>/.omp/config.yml`. The agents are ordinary `.md` files
|
|
167
|
+
under the project dir, discovered by omp's nearest-project lookup (project >
|
|
168
|
+
user > plugin) and by `discoverAgentPins`.
|
|
132
169
|
- **The shipped skill** — the hand-driven workflow, for bodies that need real
|
|
133
170
|
authoring rather than the archetype scaffold.
|
|
134
171
|
|
|
172
|
+
### The vendored architect prompt
|
|
173
|
+
|
|
174
|
+
`src/prompts/agent-creation-architect.md` is copied verbatim from omp 18.4.8's
|
|
175
|
+
`/agents` hub prompt (the SDK subpath it lives under does not resolve from the
|
|
176
|
+
extension loader, so the plugin ships its own copy). Its first line carries the
|
|
177
|
+
source version, and `ARCHITECT_PROMPT_VERSION` (`src/architect-provenance.ts`,
|
|
178
|
+
re-exported by `src/agent-architect.ts`) holds the same value. `tests/architect-provenance.test.ts`
|
|
179
|
+
asserts the two agree and that this document names the same version, so an omp
|
|
180
|
+
upgrade that changes the prompt surfaces as a test failure rather than silent
|
|
181
|
+
drift.
|
|
182
|
+
|
|
183
|
+
**Re-sync procedure** (after an omp upgrade):
|
|
184
|
+
|
|
185
|
+
1. Read the installed omp's agent-creation architect prompt (the `/agents` hub's
|
|
186
|
+
system prompt) and diff it against `src/prompts/agent-creation-architect.md`.
|
|
187
|
+
2. If it changed, replace the body of the asset, keeping the header comment's
|
|
188
|
+
version current.
|
|
189
|
+
3. Bump `ARCHITECT_PROMPT_VERSION` to the new omp version.
|
|
190
|
+
4. Update the version named in this section.
|
|
191
|
+
5. Run `node --test tests/architect-provenance.test.ts`.
|
|
192
|
+
|
|
135
193
|
## Removal
|
|
136
194
|
|
|
137
195
|
The `/remove-agent` command deletes an agent **and** its role definition:
|