@jev-harness/omp0.7.0
OMP-native adapter: Jev (System One) tools and opt-in auto-hooks for Oh My Pi.
Built for omp
The author tagged this package oh-my-pi.
Reports 0
No reports yet.
Readme
@jev-harness/omp — Jev tools + auto-hooks for Oh My Pi
OMP-native adapter over @jev-harness/core (TypeSafe's Jev / System One).
Registers ONE advisory tool (jev, three modes) and 4 opt-in automatic
hooks (5 handler registrations: the skill router uses input to observe the
prompt and before_agent_start to deliver its hint; tool_result pruning is
opt-in separately — it does NOT join OMP_JEV_AUTO).
Install
# from the harness repo
npm run build --workspace @jev-harness/omp
omp plugin install ./packages/omp
Or copy the built entry into your agent dir so OMP loads it as an extension:
cp packages/omp/bundle/extension.js ~/.omp/agent/extensions/jev-tools.js
The package.json omp.extensions field points at ./bundle/extension.js.
Tools (always registered)
| Tool | loadMode |
What it does |
|---|---|---|
jev |
discoverable |
One advisory tool, mode selects the pattern. route_skills ranks skill names against a task (or abstains); browse_action picks the next browser operation from a snapshot; pick_tool picks one tool for a task and flags whether it needs confirmation. Every mode returns a decision and executes nothing — validate it against the live snapshot or roster before acting. |
The jev tool also serves mode: "savings", which reports what the gate SKIPPED versus what it JUDGED for this session, straight from the decision log and spending no request. It separates MEASURED figures (latency of calls that ran, blocks) from ESTIMATED ones (dollars and milliseconds avoided, priced at the measured mean), because mixing the two is how a savings dashboard becomes fiction.
loadMode: "discoverable" is deliberate: OMP mounts a discoverable tool under
xd:// or BM25 search instead of the top-level schema, so the large
three-mode schema stays off every request. Nothing here duplicates OMP's own
tooling — the previous jev_ask re-implemented the native judge() /
judge_batch() prelude available inside eval, and jev_models duplicated
omp models typesafe, so both were removed.
Hooks (all opt-in)
| Hook | Switch | Behavior |
|---|---|---|
tool_call destructive gate |
OMP_JEV_GATE=0 |
Dual gate via judgeDestructiveDual: one noul (P(destructive)) plus one choice over what the call actually does. block only when the score clears 0.5 and the category is destructive with confidence ≥ 0.5; confirm when the score is high but the category disagrees, abstains, or is unsure — that returns a block whose reason tells the model to re-issue the same call once the user confirms it explicitly, instead of a bare refusal with no way forward. Records every refusal in a refusal ledger. Fail-open, twice over: every path including the logger resolves without throwing, and the judgment is bounded by an 8 s self-deadline combined with the host's abort signal, so the handler always settles before the host's 30 s toolCallTimeoutMs (which maps a timeout to { block: true }). |
input + before_agent_start skill router |
OMP_JEV_SKILL_ROUTER=0 |
Reads the skill roster from disk (the same skills/ roots OMP's discovery scans: .omp/skills, ~/.omp/agent/skills, ~/.agents/skills) and narrows it with kit's lexicalShortlist, then ranks the shortlist with routeSkill, promoting only at confidence ≥ 0.5 and only when the user has not already named a skill. One request in flight (a burst is serialized, never stacked), a superseded answer is discarded rather than delivered, and answers are cached per prompt. Prompts arriving inside a ~250 ms window are coalesced; a lone prompt is never delayed, because the host awaits this hook before submitting the message. The hint is delivered as a one-shot custom message on the next before_agent_start, which the host converts into a developer message — the system prompt is never rewritten, so the provider prompt-cache prefix is untouched. |
session_before_compact verbatim compaction |
OMP_JEV_CONTEXT=0 |
Two noul questions per tool call (keep the call / keep its result verbatim), batched in parallel. Keeps bytes identical; a dropped result keeps its head verbatim plus a note naming the omitted size and how to recover it. Returns { compaction: { summary, shortSummary, firstKeptEntryId, tokensBefore, details } } or undefined to fall back to native compaction. Fail-open, and it never hooks the per-request context event. |
session_stop verification gate |
OMP_JEV_STOP=1 |
Fires when the turn is about to settle. A DETERMINISTIC rule reads the session's own tool calls: if something changed and no check (test/build/lint/type-check) has PASSED since the last change, the settle is refused with { decision: "block" } naming the changed files and the last check. Only after that rule already says block is Jev asked ONE question (needs_check), and its answer may only LOOSEN the verdict — a docs-only or formatting-only change lifts the block. A probability can never invent a block. If the exemption call fails, the deterministic block stands rather than being silently granted. Off by default even with OMP_JEV_AUTO=1: a hook that can refuse a settle must be asked for. |
tool_result bulky-result pruning |
OMP_JEV_PRUNE=1 |
Opt-in SEPARATELY from the master switch (see below): a hook on every tool result that replaces a bulky one with a verbatim head + provenance note, so the model never reads the full text. Fail-open — keep/deferred/throw all return undefined and the host keeps the original. Zero work and zero Jev calls unless the env var is exactly 1. |
Read-only pre-filter: before any request is spent, a strictly closed-form allowlist (gate-prefilter.ts) recognises bash commands that are provably non-mutating — plain reads (ls, cat, grep, head), listing subcommands (git log, gh api, npm ls), and only the read-shaped arguments of multi-purpose commands (certutil -hashfile, sort without -o). A match skips the request; the skip means "do not judge", never "approve" — it returns the same allowance as a tool it does not adjudicate, so OMP's normal flow is unchanged. The allowlist is an allowlist by construction: anything unrecognised, ambiguous, or even arguably mutating still reaches Jev, because the residue is the semantic work. It was measured at 28% of real bash calls absorbed with zero false positives, and each skip is logged with its rule id (action: "skip:<rule>") so the list's own decisions are auditable.
tool_result pruning (default off — OMP_JEV_PRUNE=1 to enable)
This hook is deliberately OUTSIDE OMP_JEV_AUTO: enabling the master switch
does not arm it, and disabling pruning never touches the other hooks.
- Why default-off — prompt-cache invalidation. Every replacement rewrites that tool result from the point it appears, invalidating the provider's prompt-cache prefix from there on. Each scored result then costs +200-400 ms to re-cache on every later turn that re-sends it — and the hook spends one Jev call per bulky result even when the verdict is "keep". Opt in only if bulky outputs are a real, recurring cost in your sessions.
- Latency. Disabled: zero work, zero calls. Enabled, per qualifying result:
no call under 2000 chars; one Jev
noulcall for a bulky result, bounded by an 8 s self-deadline combined with the host's abort signal — far below the host's 30 stool_resulthandler budget, so a slow Jev call can never stall the turn. - Hard-cap fallback. Text over 200_000 chars is capped LOCALLY (head +
tail plus a
[locally capped …]note) and never sent to Jev — an oversize state makes Jev answer HTTP 400, and no request is worth a guaranteed 400. A capped result carries the same idempotency marker, so it is never pruned or capped twice. - Recovery. The host retains the ORIGINAL content in all cases: the hook
only ever returns a replacement string (verbatim head + a note naming the
omitted size). Every note names the result it came from:
id=<toolCallId>(for core drops,id=is the candidate id passed topruneContext, i.e. the sametoolCallId), so the original is recoverable from the session transcript or tool log by that id. - Errors. A failed tool (
isError: true) is judged under the stricter error drop bar — live error output is dropped only when Jev reads it as fully spent. Any throw — transport, timeout, missing key — returnsundefinedand recordsprune:output/prune:errorin the refusal ledger (packages/omp/src/prune.test.tspins this).
Environment variables
| Var | Default | Meaning |
|---|---|---|
TYPESAFE_API_KEY |
(required) | System One API key. Read from the environment only — never hardcoded, never logged. |
TYPESAFE_BASE_URL |
https://api.typesafe.ai |
Endpoint override. |
TYPESAFE_DEFAULT_MODEL |
jev-latest |
Model override (per-call model param wins). |
JEV_TIMEOUT_MS |
15000 |
Per-request timeout in ms. |
OMP_JEV_AUTO |
off | Master switch: set to 1 to enable all auto hooks. |
OMP_JEV_GATE |
on (when auto) | Set to 0 to disable the tool_call gate. |
OMP_JEV_SKILL_ROUTER |
on (when auto) | Set to 0 to disable skill routing (input + before_agent_start). |
OMP_JEV_CONTEXT |
on (when auto) | Set to 0 to disable verbatim compaction. |
OMP_JEV_PRUNE |
off | 1 enables tool_result bulky-result pruning. Independent of OMP_JEV_AUTO — see the pruning section. |
OMP_JEV_KEEP_THRESHOLD |
0.2 |
Keep probability threshold for compaction. |
OMP_JEV_MAX_STATE_TOKENS |
25000 |
Compaction state budget; larger histories defer to native compaction. |
OMP_JEV_MAX_REQUEST_TOKENS |
30000 |
Compaction per-request budget (drives batching). |
OMP_JEV_TRUNCATE_HEAD |
300 |
Kept head chars for truncated tool results. |
OMP_JEV_MIN_REDUCTION |
0.25 |
Minimum saved/total char ratio before returning a compaction. |
OMP_JEV_MAX_CALLS_PER_MIN |
120 |
Rolling per-minute cap on Jev requests, shared by tools and hooks. 0 disables the cap. |
OMP_JEV_CACHE_DIR |
~/.omp/cache/jev-harness |
Directory for the cross-session judgment cache. |
OMP_JEV_CACHE_TTL_MS |
86400000 (1 day) |
How long a cached judgment stays valid. |
OMP_JEV_DECISION_LOG |
unset (in-memory only) | Path to a JSONL file; every gate decision is appended there for offline review. |
OMP_JEV_REDACT |
unset | 1 redacts secrets in ALL state; 0 disables redaction everywhere. Unset redacts hooks only — tools send full fidelity because the model chose that state. |
Resilience
- Budget guard.
OMP_JEV_MAX_CALLS_PER_MINcaps runaway loops; the cap is shared by every tool and hook. - Persistent cache. Identical judgments are free hits across sessions
(
OMP_JEV_CACHE_DIR,OMP_JEV_CACHE_TTL_MS). - Failure taxonomy. A transport failure is classified
(
classifyJevFailure) and handled by policy (policyForFailure) rather than swallowed: anauthormodelfailure disables Jev for the session — every later call would fail identically while burning a host handler's latency budget —rate_limitbacks off,networkstays quiet, and anything else is surfaced in the logs. - Degraded routing. When the Jev routing call fails — not when it
abstains — the hook reroutes locally with core's
localRouteSkilland promotes a match only at overlap ≥ 0.2 (LOCAL_ROUTE_MIN_SCORE, on that router's ownhits / sqrt(|message| × |name+description|)scale). The floor is deliberately stricter than core's 0.05 plausibility floor: one incidental shared word scores ~0.08 and would send the model after the wrong skill, while two content words over short descriptions score ~0.29 and are kept. Below the floor, no hint is produced at all — a wrong hint costs more than none. - Refusal ledger. Gate blocks, routing abstains, compaction deferrals, prune failures
(
prune:output/prune:error), and local fallbacks (match or no-match) are recorded with their reason, so a declined action leaves a trace instead of vanishing. - Fail-open. Apart from an explicit destructive
block, no Jev failure ever stops the agent.
Layout
src/extension.ts— default-export factory(pi: ExtensionAPI) => void; all tools + hooks.src/prune.ts—tool_resultpruning hook body: env gate, idempotency, local hard cap,pruneContextcall, fail-open catch (src/prune.test.ts).src/compact.ts— pure verbatim-compaction planning + rendering (no host, no network).src/router.ts— pure skill-roster loading, the single-flight, cached ranked-merge router, and the conservative local router used on the degraded path.src/failure.ts— the one place a Jev transport failure becomes a decision.src/config.ts— env parsing, thresholds re-exported from core, deadline helper.src/index.ts— re-exports the factory.