Fast, near-free GitHub issue triage - powered by TypeSafe AI's Jev.
Jev is a System One model: text state in, typed probabilistic decisions out (choice / score / noul), each with a calibrated confidence, in ~70-500 ms at roughly free cost. That combination makes it viable to run on every issue the moment it opens - and to escalate only the ones it's unsure about to a human or a real LLM.
# .github/workflows/triage.yml
on:
issues: { types: [opened, edited, reopened] }
permissions: { issues: write, contents: read }
jobs:
triage:
runs-on: ubuntu-latest
steps:
- uses: cmaintz/jev-triage@v0
with:
jev-api-key: ${{ secrets.JEV_API_KEY }}
cloudflare-account-id: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}--- run summary ---
#142 label=bug, priority:major conf 0.91 ✓ applied
#143 type uncertain conf 0.48 → triage:needs-human
#144 security flagged noul 0.83 ⚠ alerted
1,204 issues triaged this month · $0.11
Existing LLM triage bots are too slow and too expensive to run on every issue, and they hand you prose you still have to parse. Jev returns a typed value your workflow branches on and a confidence you gate on. The result is triage that's cheap enough to always run and honest enough to defer when it isn't sure.
- On a new/edited issue, the title + body become the Jev
state. - Your
.github/jev-triage.ymldefines the questions - one batched call answers them all (adding questions is near-free). - Confident answers become labels / routing; low-confidence answers are never applied - they get
triage:needs-humanor escalate to an LLM. - A run summary reports labels, escalations, tokens and estimated cost.
See examples/jev-triage.yml for the full config surface.
- Backlog sweep - trigger on
workflow_dispatch/scheduleand it map-reduces every open issue (skipping PRs and anything already carrying themarker_label), capped bymax_issues. Sweep a whole backlog for pennies. Seeexamples/backlog-workflow.yml. - LLM escalation cascade - with
on_low_confidence: escalateand anllm-api-key, low-confidence issues are re-classified by an LLM (any OpenAI-compatible endpoint viallm-model/llm-base-url), which then labels and leaves a one-line rationale. Jev is System One; the LLM is System Two - invoked only where Jev is unsure. - Duplicate detection - set
dedupe: true: GitHub search retrieves candidate issues, and Jev picks the duplicate (or "none") from that bounded set. A match gets apossible-duplicatelabel + link (it never auto-closes). Retrieval is code; judgment is Jev.
- A first-pass, not a decision-maker. Jev is ~68% accurate on classification - fast and cheap, not smarter. The confidence gate is the point. It never auto-closes issues.
- Text only. Screenshots and attachments carry no signal to Jev.
- No arithmetic / dates. Those stay in code (e.g. routing is a deterministic map, not a Jev question).
- Needs a Jev key. Sign up at TypeSafe for a first-party key, or use Cloudflare Workers AI (
typesafe/jev). First-party is the default (one secret).
v1.0 - per-issue triage, backlog sweep, LLM escalation cascade, and duplicate detection. Passes the Foundry gate (mise run gate: lint → typecheck → test → audit), 28 unit tests, bundles clean. Verified against the official API reference and Cloudflare's model page, and validated against the real Jev API (a live test classifies a real bug report end-to-end; test/live.test.ts). Contributions welcome. See CHANGELOG.md and the full spec.
Quality is enforced through Foundry's six-verb gate:
mise run gate # lint → typecheck → test (coverage floor) → audit - the oracle
mise run fix # auto-fix (eslint --fix + prune suppressions)
npm run build # bundle dist/index.js (ncc) - commit the resultMIT © Christoffer Maintz