JEV Gate

September 21, 2026 ยท View on GitHub

JEV Gate is a review companion for GitHub and coding agents. It identifies changes that deserve another look and supplies their locations and verification steps. Each result records the exact input, effective policy, and review coverage.

Sensitive changes request review by default. A finding is a candidate for verification; it is not proof of a defect. Required blocking is an explicit repository policy.

Local use

Build this checkout with Node 26 and npm 12. The bundled CLI runs on Node 20 or later:

npm ci
npm run build
export TYPESAFE_API_KEY=...
node dist/bundle/cli.cjs review --base main
node dist/bundle/cli.cjs review --base main --json

To install the built CLI, run npm install -g .. The bundled executable also works without installing dependencies in the repository being reviewed:

cd /path/to/your/project
node /path/to/jev-gate/dist/bundle/cli.cjs review --base origin/main --json

The CLI discovers .jev-gate.yml at the Git repository root, including when called from a subdirectory. It includes branch commits, staged and unstaged edits, and untracked files. The .jev-gate/ metadata directory is excluded. Keep it in your project's .gitignore. Collection limits and unavailable binary patches appear as coverage gaps.

jev-gate review --diff change.diff --json
jev-gate review --diff - --json < change.diff
jev-gate snapshot --base main --json > /tmp/review-snapshot.json
jev-gate review --snapshot /tmp/review-snapshot.json --json
jev-gate review --base main --policy-source base --json

Snapshots contain source code and effective configuration. Store them privately. Snapshot review validates the captured identity against the installed rules and local dispositions. Base policy reads the configuration at the merge-base commit. Local authoring uses working-tree policy by default; GitHub uses the PR base commit. The result names the policy source so this difference is visible.

Exit codes:

CodeMeaning
0Complete advisory review, or a complete required review with no blocking findings.
1An open finding exceeds an enabled gate in required mode.
2Incomplete or unavailable review, or invalid input/configuration.

--no-gate suppresses exit 1 only. It does not hide review errors. Empty reviews still return JSON. A complete review can have findings; read status as well as health.

GitHub

Copy examples/caller.yml, replace its commit placeholder with a reviewed release commit, and add TYPESAFE_API_KEY as a repository secret. Version 0.2 uses the schema described here; pin a commit containing this implementation rather than assuming an older moving tag has it.

The Action reads PR data through GitHub's API. It does not check out or execute PR code. Configuration comes from the base commit. It verifies base and head revisions after collection and before publication, and updates only the expected GitHub Actions bot's sticky comment. When GitHub omits or truncates a patch, the Action reads the file at the PR head and merge base and reconstructs the diff with Git. It does not check out PR code. Recovery attempts at most 100 files, reads at most 2 MiB per file and 16 MiB of file content in total, and starts no more reads after two minutes. Each request also has a timeout. A pinned Git tree verifies that each path is a regular file; symlinks and submodules are not followed. Tree metadata is capped at 8 MiB per revision. Ignored current and previous paths are not fetched for recovery. Binary files, unsupported metadata-only changes, unavailable content, and exceeded limits remain explicit coverage gaps. The runner must have Git installed.

The caller workflow cancels superseded runs. GitHub comments do not provide an atomic compare-and-update operation, so the revision in each result remains the authority.

For manual reruns, add a workflow_dispatch PR-number input to the caller and pass it to the Action as pull-request. The Action validates that the PR is open and reads its current revision. Do not override GitHub's reserved event variables.

Fork PRs do not receive provider secrets under pull_request. Their review will report unavailable. To review forks, use pull_request_target, pin the Action to a reviewed commit, and retain this workflow's API-only design. Never add execution of fork code to that job.

The comment groups findings into review topics. Expand a row to see what to verify, the evidence, and links to every location. Small gauges show the peak model estimate beside its configured review threshold. Percentages answer a review question; they are not calibrated defect probabilities. Credential pattern matches show counts. The file map, coverage notes, and run metadata expand below the table. A review with no findings stays short. The full workflow report includes every model observation.

The gauges use generic SVGs shipped in assets/review/v1, served from this project's public repository. Image URLs contain only a color and an integer from 0 to 100; no source paths, credentials, or review text are sent to an image service. Alt text preserves the estimate when images are unavailable. Regenerate the artwork with node scripts/review-assets.mjs; use a new version directory to change published art.

Oversized reports go to the workflow summary and result output. Outputs include health, status, passed, failed-gates, and the complete JSON result. The result-path output points to the same JSON under RUNNER_TEMP. Upload that file as a workflow artifact to preserve large assessments without putting report contents into a shell command or environment variable. passed is unavailable when review did not complete. Provider failures exit nonzero and update the comment when the PR revision remains current.

Policy

provider: typesafe
model: jev-1.13.0
mode: advisory
maxStateTokens: 24000
maxRequests: 64
borderlineMargin: 0
comment: true
rules:
  danger-sensitive-area:
    gate: false
  breaking-change:
    threshold: 0.8
SettingDefaultBehavior
providertypesafetypesafe or openrouter.
modeljev-1.13.0OpenRouter defaults to typesafe/jev-1.13-20260917. Defaults are pinned.
modeadvisoryrequired enables configured blocking gates. Both modes report review errors.
maxStateTokens24000Conservative UTF-8 byte bound on state, 2000 to 30000.
maxRequests64Maximum logical provider calls per review, 1 to 500, including optional second observations. Provider retries can add network attempts.
borderlineMargin0Optional second observation for gated results near a threshold; 0 to 0.3. This is not independent corroboration.
ignoreGenerated files, dependencies, and lockfilesGlob list replacing the defaults. Exclusions appear in coverage.
commenttruePublish the GitHub comment.
rules.<name>.enabledRule defaultInclude the rule.
rules.<name>.gateRule defaultMake open findings block in required mode.
rules.<name>.thresholdRule defaultNormalized observation threshold between 0 and 1.
openrouter.referer, openrouter.titleNoneOptional provider attribution headers.

OpenRouter reads OPENROUTER_API_KEY. Set provider: openrouter or use --provider openrouter. The Action also accepts provider, model, mode, config-path, max-state-tokens, max-requests, timeout-ms, api-key, github-token, and comment inputs. Unknown configuration keys and invalid CLI flags fail explicitly.

Findings and coverage

RuleObservationGate eligible by default
danger-sensitive-areaA security or data invariant deserves focused review.No
danger-deleted-testsExisting test coverage may have been removed or weakened.Yes
danger-secret-materialAdded content may contain credentials.Yes
breaking-changeA public contract may require migration or compatibility work.Yes
test-meaningfulnessExperimental test-quality rating, disabled by default.No
comment-driftTouched comments may describe old behavior.No
change-hygieneExperimental coherence rating, disabled by default.No

The engine splits textual patches into bounded candidates and reviews every candidate that fits the configured budgets. Related implementation/test changes supply limited context. Later sections also receive up to 1,000 characters from the same file's diff opening, when the state budget permits. This keeps document purpose and module context visible after splitting; the opening is background, not an additional finding location. The candidate-v4 state version invalidates older snapshots and finding IDs, so dispositions for older IDs must be reassessed. Locations identify the reviewed candidate, not an exact causal line. Missing callers and contracts still require a human or a reasoning model to investigate.

Coverage distinguishes reviewed, excluded, partial, and unavailable files. A giant single line, missing patch, exhausted budget, or missing answer cannot silently count as reviewed. Binary probabilities and rubric scores retain distinct display units.

Test-quality scoring is opt-in because live evaluation produced false positives on setup helpers. When enabled, it applies only to recognized test-code paths. Documentation and production files that mention assertions do not make it applicable.

Before provider calls, a local detector redacts recognized credentials and private keys. Added matches produce located findings without revealing values. This is a limited pattern detector; it does not guarantee that all secrets or personal data are removed. Use ignore for content that must not leave the repository. Review state goes to the chosen TypeSafe or OpenRouter endpoint, including PR descriptions and candidate source code after redaction.

Schema 2 JSON contains snapshot and policy identities, resolved model, rule fingerprint, coverage, raw observations, and findings. Findings have stable identities tied to their candidate content and policy. Accept or dismiss a finding locally with a reason:

jev-gate resolve FINDING_ID --status accepted --reason 'Callers migrate in this release'

Dispositions live in .jev-gate/dispositions.jsonl. They do not silently change repository policy or authorize a GitHub merge. A changed candidate or policy creates a new identity. Recording a disposition invalidates cached assessments. Collect a fresh snapshot after changing one. GitHub enforcement overrides follow repository branch-protection rules. Editing policy in the PR does not change the policy used to review that same PR.

Coding agents

Any agent host can call jev-gate review --json after an edit batch or completed tests. Read health before treating results as complete, then inspect each open finding's location and verification. Record a disposition when a finding is intentional. Avoid editing code merely to change a model's score.

The OpenCode adapter calls this same CLI contract. It restores undelivered assessments, retries unavailable reviews, checks freshness before injection, and tracks recipient sessions. It requires no runtime dependency beyond the host and the installed CLI.

Evaluation

jev-gate calibrate --dir samples --split tune --json > /tmp/tune.json
jev-gate calibrate --dir samples --split holdout --json > /tmp/holdout.json

The label manifest records expected directions and separates previously tuned examples from new holdout examples. Each run records content, policy, rule, and model identity plus observations and per-rule precision/recall. Unavailable answers make evaluation invalid and exit 2. --repeat measures variation; --solo evaluates rules independently. Unlabeled axes do not enter metrics. The small synthetic suite does not establish real-world accuracy. Preserve independent data when using results to change rules.

Development

npm ci
npm run typecheck
npm test

Tests include bundled CLI/Action execution and agent-delivery lifecycle checks. dist/ is committed for GitHub Actions. Rebuild it with changes. The OpenCode contract is checked at build time; its runtime adapter imports no OpenCode SDK. JavaScript dependencies must be at least 48 hours old; .npmrc enforces this with npm 12.

MIT licensed.