Jev Router
How Maestro's router uses TypeSafe Jev for main-turn downgrades and subagent worker classes, and how it fails open.
The Jev Router is the one part of Maestro its author wrote: an omp extension (extensions/jev-router.ts) that asks TypeSafe Jev how much model each piece of work actually needs, before any tokens are spent on it.
Two routers in one extension
| Aspect | Main turns | Subagents |
|---|---|---|
| Decides | @smol or @default for the turn you just started | Which jev-* worker role runs each proposed task — or whether it runs at all |
| Hook | before_agent_start | tool_call (task) → before_subagent_spawn |
| Default posture | Stay on the lead unless every gate passes | Smallest class that can reliably do the task; route up when unsure |
Main-turn routing
Before each prompt runs in an interactive session, the router decides whether the turn can run on @smol. It only acts while the session is on @default or @smol — a model you picked by hand is left alone (recorded as a “skip”).
When a turn did run on @smol, the router moves the session back to @default when the agent finishes or the session stops — unless you switched models yourself in the meantime.
Layer 0 guards
Deterministic checks that run before anything is spent on Jev. Each one can only route up, to @default:
- The prompt has an image attached.
- The prompt is longer than 12,000 characters.
- The prompt contains a high-impact keyword (case-insensitive, whole words):
ultrathinksecurityauthenticationauthorizationpermissions(s)database migrationschema migrationproduction incidentdata lossrace conditionconcurrencydeadlockcryptograph…credentials(s)secrets(s)payments(s)rollback
A false positive here costs money, never quality — which is the trade the router is designed to make.
The @smol gates
If Layer 0 passes, Jev answers five questions about the prompt: the capability tier (economy, standard, difficult), a complexity score from 0 to 4, whether a weaker model could handle it safely, whether a mistake would have a high blast radius, and whether it needs fresh web information (logged only). The turn runs on @smol only if all six gates pass:
| Gate | Passes when |
|---|---|
| Tier | economy |
| Tier confidence | ≥ 0.88 |
| Complexity | ≤ 1.25 |
| Complexity confidence | ≥ 0.65 |
| Safe downgrade | ≥ 0.9 |
| Blast radius | ≤ 0.15 |
One failed gate keeps the turn on @default, and the reason lists every gate that failed — e.g. @default safety gates: tier=standard, safeDowngrade=0.41. Judgments are cached for 30 seconds per prompt and working directory.
Subagent routing
When the lead calls the task tool, every proposed task — single or batched — is classified by Jev before omp runs it. Jev is told to judge the child task itself, not the size of the parent project: an inventory task inside a security project is still mechanical.
| Class | For | Runs on |
|---|---|---|
| mechanical | Enumerate, list, grep, search, count, locate references, extract facts | @jev-mechanical |
| bounded | Focused analysis or a small, well-scoped change inside one subsystem | @jev-bounded |
| reasoning | Tracing behaviour across components, debugging interactions, non-trivial judgment | @jev-reasoning |
| architecture | Cross-cutting design, migrations, security boundaries, concurrency, rollback strategy | @jev-architecture |
- If Jev's confidence in the class is below 0.65, the task goes to the safe middle tier,
reasoning. - If the probability that the task should be delegated is below 0.3, it stays with the parent. In a batch, the accepted tasks run and the lead is told which ones to do itself; if none are accepted, the whole call is blocked with the same instruction.
- The chosen role's model and its fallback chain become the child's model list, applied when omp spawns it.
The architecture floor
Risky changes are floored to architecture regardless of what Jev says. The floor needs both a change verb (design, migrate, replace, implement, modify, change, deploy, write, delete, rotate, revoke, alter, refactor, cutover, rollback) and a high-risk domain (security, authentication, authorization, permissions, database, schema, production, credentials, secrets, payments, concurrency, race condition, data loss) within 160 characters of each other. Merely reading auth code isn't enough.
"Rotate the production credentials" → architecture (floor)"List every file that imports the auth module" → whatever Jev decides"Implement a Badge component" → whatever Jev decidesFailing open
The router never makes things worse by failing. Every failure path falls back to plain omp behaviour:
| Situation | What happens |
|---|---|
No TYPESAFE_API_KEY | Turns stay on @default; tasks use omp's normal roles. Status line: jev: NO KEY. |
| Jev takes longer than 1,800 ms | Same — no retries, no waiting. |
| Any Jev or network error | Same. The error is counted in /jev-route status. |
@default or @smol can't be resolved | The router shows an error and leaves the turn alone. |
A jev-* role isn't configured | The child keeps omp's normal model. |
Tuning thresholds
All thresholds live in the CONFIG block at the top of the extension. To change them, fork the repository and edit the values:
const CONFIG = { timeoutMs: 1_800, maxPromptChars: 12_000, economyChoiceConfidenceMin: 0.88, safeDowngradeMin: 0.9, complexityMaxForSmol: 1.25, complexityConfidenceMin: 0.65, highImpactMaxForSmol: 0.15, needsWebThreshold: 0.65, cacheTtlMs: 30_000, subagentClassConfidenceMin: 0.65, subagentDelegateMin: 0.3,} as const;| Setting | Default | Meaning |
|---|---|---|
timeoutMs | 1800 | Give up on Jev after this many milliseconds and fail open. |
maxPromptChars | 12000 | Longer main-turn prompts skip Jev and stay on @default. Subagent tasks are truncated to this length before judging. |
economyChoiceConfidenceMin | 0.88 | Confidence Jev needs in the “economy” tier. |
safeDowngradeMin | 0.9 | Probability that a weaker model is safe for this task. |
complexityMaxForSmol | 1.25 | Highest complexity score (0–4) allowed on @smol. |
complexityConfidenceMin | 0.65 | Confidence Jev needs in its complexity score. |
highImpactMaxForSmol | 0.15 | Highest blast-radius probability allowed on @smol. |
needsWebThreshold | 0.65 | Logged only — not used for routing yet. |
cacheTtlMs | 30000 | How long a main-turn judgment is reused for the same prompt in the same directory. |
subagentClassConfidenceMin | 0.65 | Below this, a subagent goes to jev-reasoning. |
subagentDelegateMin | 0.3 | Below this probability of “delegate”, the work stays in the parent. |
Lower thresholds route down more often
Loosening a gate makes more turns run on the small model. The defaults are deliberately strict; change them one at a time.
Status and telemetry
/jev-route status prints whether routing is enabled, whether a key is present, counters for each route (smol, default, skip, judge errors), per-class subagent counters including parent vetoes, and the last decision with its scores. Each main-turn decision is also written to the session as a com.omp.jev-router.route entry, with a hash of the prompt rather than the prompt itself.
Dry-run either router with /jev-route test <prompt> and /jev-route test-task <task>. See all router commands.