Jev Issue Radar

September 20, 2026 · View on GitHub

Jev Issue Radar: less duplication, more context

Jev Issue Radar

Find likely duplicate GitHub issues, with the evidence side by side.

A read-only triage dashboard powered by TypeSafe Jev through OpenRouter.

CI Listed on Awesome Jev

Try the public demo → · Run locally · Real-case checks · Contributing

15-second tour of the public sample: filter duplicates, compare evidence, inspect related and sparse reports, and switch themes

No signup, installation, or API key needed for the public sample. It contains four synthetic reports and clearly labeled, hand-authored decisions. Use the local app to retrieve real public GitHub issues and opt into paid Jev comparisons. Static screenshot · What the demo does


Why this exists

Two people can report the same bug using completely different words. Two reports can also share an error message while describing different defects.

Issue Radar retrieves a small candidate set, asks Jev to classify each pair, and puts the selected passages side by side. The model selects a relationship and evidence IDs; the maintainer makes the final call. It never closes issues, adds labels, or posts comments.

Issue URL → retrieve candidates → Jev Choice → inspect original evidence

Status: experimental MVP. The integration works; duplicate-detection quality on real repositories has not been established. In the initial four-pair synthetic smoke test, two relationships matched the author's expected labels. See the full results and limitations.

In a later check of three preselected public duplicate pairs, 0/3 canonical issues reached the top five: all were outside the recent-300-item scan. This is a documented retrieval limit, not a Jev classification result. Cases, source references, and reproducible results.

Stack

LayerTechnologyWhy
RuntimeNode.js 22+, built-in HTTP and fetchNo production dependencies or build step.
UIHTML, CSS, vanilla JavaScriptA small dashboard you can run locally.
RetrievalTitle-weighted lexical overlapInspect candidates before paying for inference.
DecisionJev 1.13, four Choice questionsBounded relationship, reason, and evidence selections.
Testsnode:test; optional PlaywrightSeparate application correctness from model quality.

How it works

flowchart LR
  A[Public GitHub issue] --> B[Up to 300 recently updated items]
  B --> C[Exclude PRs and the source issue]
  C --> D[Rank up to 5 candidates]
  D --> E[Preview original reports]
  E --> F[Jev chooses relation and evidence]
  F --> G[Validate choices and show passages]
flowchart LR
  UI[Local browser] --> S[Loopback Node server]
  S --> GH[GitHub REST: read only]
  S --> OR[OpenRouter Decisions API]
  KEY[Server environment variable] --> S
  S --> UI

Each candidate is classified as likely duplicate, related, distinct, or insufficient info. Two further choices select passages from the original reports; a fourth selects a reason category.

A duplicate is displayed only when both evidence IDs exist, its reason is compatible, the input was not truncated, and model confidence is at least 0.8. This is a conservative product rule, not a calibrated accuracy guarantee. A valid quote does not prove that the model interpreted it correctly.

Example

Source: pressing Enter during Korean IME composition duplicates the final character.

Candidate: “Korean IME commits the final character twice on Enter.”

Radar shows the selected reproduction and behavior passages from both reports.

Interactive issue comparison dashboard

The English demo contains synthetic issues and hand-authored decisions. Its confidence values are illustrative, not measured model outputs. Current evaluation fixtures use English; immutable links to the original measured inputs are in the provenance notes.

Features

FeatureBehavior
Public issue URLsValidates the host and issue path; rejects pull requests.
Free candidate previewFetches GitHub reports without invoking Jev.
Four relationship labelsKeeps “related” and “insufficient” separate from duplicates.
Side-by-side evidenceShows selected source passages, with stable line IDs.
Conservative duplicate displayDowngrades unsupported or inconsistent duplicate judgments.
Filters and full reportsInspect any candidate and its model metadata.
JSON exportExport reports, decisions, scan coverage, latency, and reported cost.
Public no-key demoExplore the sample in your browser without installation, credentials, or paid calls.
Responsive themesLight and dark layouts for desktop and mobile.
Repeat-request protectionReuses completed results for the same preview ID for up to 10 minutes.

Design decisions

Evidence selection instead of generated explanations

Jev chooses original line IDs. Unknown IDs and malformed choices are rejected. The application copies the corresponding text verbatim instead of asking a model to invent an explanation. Semantic relevance still needs review.

Retrieval scores are not duplicate probabilities

Lexical overlap only selects candidates. A differently worded or cross-language duplicate may never reach Jev. Retrieval recall and pair-classification quality must be evaluated separately.

Raw decisions remain inspectable

Both the raw model relationship and the displayed relationship are retained. Missing evidence, inconsistent reasons, low confidence, or truncated input prevent a strong duplicate label.

Errors remain errors

Timeouts, provider failures, and invalid responses are not silently labeled “distinct.” Successful candidates remain available if another comparison fails. There are no automatic paid retries.

One preview, one analysis

The server assigns a snapshot ID, serializes requests, and reuses completed results for that ID. A session call cap bounds the number of requests; it is not a dollar budget.

Credentials stay on the local server

The UI and exports never receive the API key. The server binds to loopback and checks Host, Origin, and a request token. GitHub is accessed without an authentication token.

Project structure

index.html                    # Dashboard and interactions
server.mjs                    # Local API, snapshots, call limits
lib/core.mjs                  # URL validation, retrieval, evidence rules
lib/github.mjs                # Public GitHub issue reader
lib/jev.mjs                   # Real OpenRouter Jev decision call
data/demo.mjs                 # English UI examples and fixed decisions
data/evaluation-fixtures.mjs   # English fixtures for future approved runs
data/public-cases.json         # Source-linked real duplicate references
tests/check_all.mjs            # Offline logic and local HTTP tests
scripts/check-syntax.mjs       # Module and inline-script syntax checks
scripts/browser-smoke.mjs      # Optional browser interaction checks
scripts/live-smoke.mjs         # Explicitly approved paid smoke test
scripts/build-demo.mjs         # Credential-free static demo artifact
scripts/browser-demo.mjs       # Public demo checks, locally or after deployment
scripts/check-public-cases.mjs # Free, read-only retrieval checks on public cases
docs/                         # Screenshot, measured results, limitations

Quickstart

Just exploring? Open the public sample. The steps below run the full application on your own computer.

Node.js 22 or newer. No npm install required.

git clone https://github.com/Patrick-SCH03/jev-issue-radar.git
cd jev-issue-radar
node server.mjs

After the server starts, open http://127.0.0.1:4318 in your browser and keep the terminal running. This address only works on your own computer while the server is running. The local demo and public GitHub candidate preview work without an OpenRouter key.

To enable real comparisons, set OPENROUTER_API_KEY in your environment, then:

# macOS / Linux
JEV_ENABLE_LIVE=1 node server.mjs
# Windows: reads the existing process or user environment variable
.\run.ps1 -Live
Environment variableDefaultPurpose
OPENROUTER_API_KEYUnsetServer-side credential for paid comparisons.
JEV_ENABLE_LIVEOffSet to 1 to allow paid analysis.
JEV_MODELtypesafe/jev-1.13The version used in the recorded integration check.
JEV_MAX_CALLS20Per-process request cap, integer 1–100; invalid values stop startup. Not a dollar budget.
PORT4318Loopback server port.

You can opt into the moving model alias with JEV_MODEL=~typesafe/jev-latest. Results may change. Environment files are not loaded automatically. Use account-level limits in OpenRouter for a dollar spending cap.

Run the checks:

node --test tests/check_all.mjs
node scripts/check-syntax.mjs
node scripts/check-language.mjs

Optional browser checks require Playwright and an installed browser. PLAYWRIGHT_MODULE can point to a local module; PLAYWRIGHT_CHANNEL=msedge uses installed Edge.

The public sample is built with node scripts/build-demo.mjs and deployed from the generated dist/ directory by GitHub Actions. It contains no backend or API key. See demo development and deployment.

Run node scripts/benchmark.mjs current for a reproducible local workload without external APIs. See the security and performance review for measured results and the security model for operating limits.

API

MethodRoutePurpose
GET/api/statusVersion, enabled capabilities, request token; never the key.
GET/api/demoSynthetic issues and fixed decisions.
POST/api/previewAccepts url; reads the source issue and retrieves candidates.
POST/api/analyzeAccepts a preview id; compares at most five pairs.

POST requests require application/json and the X-Radar-Token returned by /api/status.

The actual provider integration and decision call are in lib/jev.mjs. It sends four Choice questions to POST https://openrouter.ai/api/alpha/decisions, not Chat Completions. The question schema and response policy are in lib/core.mjs.

Results include relation, rawRelation, reason, sourceEvidence, candidateEvidence, confidence, latencyMs, costUsd, and model. Failed comparisons have relation=failed and an explicit error.

Data and limitations

AreaCurrent scopeLimitation
GitHub inputTitles, bodies, issue stateNo comments, attachments, image understanding, or full history.
ScanUp to 3 pages × 100 recently updated itemsOld duplicates may be missed; PRs count toward fetched items.
RetrievalUp to 5 lexical matchesCross-language and synonym recall are unmeasured.
Jev inputFirst 12,000 body characters; up to 60 lines, 360 characters eachTruncation is marked and blocks a strong duplicate label.
ConfidenceModel-returned valueNot calibrated correctness.
DemoHand-authored English examplesNot a model-quality benchmark.

Initial integration measurements

Four original Korean/English synthetic pairs were sent once each to Jev. All calls returned valid structured decisions; 2/4 matched the author's predefined labels.

CaseExpectedReturnedLatency
Same IME reproduction, differently wordedduplicateduplicate460ms
IME composition interrupted by autosaverelateddistinct291ms
Search requests duplicated by two handlersdistinctdistinct296ms
Vague Korean-input complaintinsufficientrelated317ms

Total provider-reported cost: US$0.000294084. No unknown-cost calls. These are small-sample integration observations, not performance promises or an independent evaluation. The related/distinct boundary itself needs a clearer labeling protocol.

Results with English translations and original-source links · Full validation notes

Useful next contributions are independently labeled real issue pairs, recall@5 evaluation, clearer relationship criteria, and retrieval improvements. Please preserve a held-out set rather than fitting prompts to the demo.

Notes

  • Live comparison sends the selected public issue text to OpenRouter and incurs API charges. The local demo does neither.
  • This is an independent project, not an official GitHub, TypeSafe, or OpenRouter product.
  • MIT licensed. See CONTRIBUTING.md for a small, testable contribution workflow.

References: GitHub Issues API, TypeSafe Choice patterns, OpenRouter Jev.