#12374·oh-my-pi

Follow-up TypeSafe Jev use cases after core skill suggestion

Author: kvnlooCreated Sep 17, 2026Updated Sep 17, 2026

Tracking issue. Do not implement independently while #12372 / #12373 is in flight. This is the leftover surface from the TypeSafe cookbook and public Jev usage, not a rewrite of call 1.

Depends on: #12372 (core), #12363 (example). Related-but-different from #9429 (skill_search / allowlist — not TypeSafe).

Already shipped or in review

Path Status
TypeSafe as judgment backend (auto-thinking, unexpected-stop, git AI staging, eval judge()) In core today
Cookbook call 1: one choice over the roster + three gate nouls, gate 0.30, inject <skill_relevance>, fail-open 2.5s, no tiny/smol fallback #12373
Copy-paste examples/extensions/typesafe-jev.ts #12364
/jev status / auto / typesafe / off #12373
Jev as /model Never. Max output tokens is 0.

Call 1 is the published recipe for an omp-sized roster (~40 skills, Choice cap 255). Live check on this machine: p50 ~330ms, p95 ~372ms, 0/6 over 2.5s, jev-1.13.0.

Follow-ups (priority order)

1. Cookbook call 2 — rerank the top 3 with SKILL.md excerpts

Official recipe: Skill suggestion, Step 4.

After call 1 names a shortlist, a second POST /v1/systemone:

  • which = Choice over the top 3, criteria = longer description + ~700 chars of each SKILL.md
  • fits::{name} = one noul per candidate (“does this skill actually do the thing asked?”)
  • Drop the shortlist if the best fits noul is < 0.30 (FITS_THRESHOLD)
  • Still fail-open; still not a chat model

When to turn it on (not by default):

  • Roster grows past ~100, or hits the 255-choice cap
  • Two visible skills have colliding names/descriptions (lookalikes)
  • Call 1 injects but the chat model then ignores / misreads the skill

mizchi/jev-playground reproduced this cookbook shape (no none_of_these on call 1; inject as advice). Hermes injects the same <skill_relevance> line into the user message to keep the prompt-cache prefix byte-stable; OMP should stay on the per-turn system prompt override (same as pirate.ts / #12373).

Budget: a second ~300ms round trip. Keep the 2.5s wall for the pair, or skip call 2 when call 1 already has high gate + high p. pi-fabric does not auto-retry — a late inject is worse than none.

2. Tournament / chunking past the Choice cap

GodsBoy/jev-agent-skill-router runs a tournament for huge catalogs (~1.3s). Overkill for 40 skills. Worth it only if:

  • loadSkills() returns more than 255 visible (non-hide) skills, or
  • call 1 has to drop names because of MAX_CHOICES

Shape: chunk the roster, run call 1 per chunk in parallel (cookbook notes extra questions barely change latency; extra requests do), then call 2 on the winners. Still TypeSafe-only — do not fall back to tiny/smol to “finish” a tournament.

3. Optional autoload instead of a hint

#12373 appends a <skill_relevance> line and trusts the chat model to Read the skill. Subagents already have autoloadSkills / sendCustomMessage (same mechanic as /skill:<name>).

A later flag, e.g. skills.suggestion.autoload: off | hint | load:

  • hint (default, current behavior)
  • load = actually inject the skill body the way /skill: does, only when gate and p are both high (stricter than 0.30 — maybe 0.6+) so a wrong pick does not burn context

Do not autoload on a gate miss or a colliding shortlist; fall back to hint or quiet.

4. Collision / lookalike detector on small rosters

Even at 40 skills, systematic-debugging vs recurring-operational-root-cause style pairs confuse call 1. Trigger call 2 (or stay quiet) when the top-2 choice probabilities are within ~0.1 of each other, regardless of roster size. Cheap; no tournament.

5. Observability (not a new backend)

/jev status already prints last name / gate / ms once #12373 lands. Follow-ups if people cannot tell whether Jev ran:

  • Session ledger usage with purpose: "skill-suggestion" (parity with auto-thinking’s onUsage)
  • One debug log line is already there; do not add a chat-visible banner on every turn (quiet on hey is a feature)

6. Explicitly never

Idea Why not
/model jev Max output tokens 0; it only answers typed questions
resolveJudge / tiny/smol fallback on this path A wrong skill name is worse than none. Other judgment features may fall back; this must not. pi-fabric: no auto-retry
Raising TypeSafeJudge’s 3× / 10s retry for skill suggestion Auto-thinking can wait 4s. Skill inject has a 2.5s abort on purpose
Replacing #9429 skill_search with Jev Different product: deterministic search vs calibrated suggestion
Shipping GodsBoy as the default 1.3s on every turn for ~40 skills

Public usage this is based on

  • TypeSafe cookbook: two-stage, gate 0.30, fits 0.30, inject in the system prompt, extra questions in the same POST are cheap
  • elizaOS/eliza, Vercel typesafe-ai, LangChain langchain_typesafe: native POST /v1/systemone, jev-latest, not a chat model
  • monotykamary/pi-fabric: same endpoint, no automatic retry
  • y0usaf/pi-jev: Pi extension, fail-open, several questions in one ~300ms call
  • GodsBoy/jev-agent-skill-router: tournament for huge catalogs
  • mizchi/jev-playground: cookbook reproduction

Suggested split

  • Keep #12373 as call 1 only.
  • A later PR can add suggestSkillRerank(...) next to suggestSkill, gated by skills.suggestion.rerank: off | auto (auto = call 2 when roster > 100 or top-2 probabilities are tied).
  • Tournament is a third PR, only after someone actually hits 255 visible skills.