Skip to content

[ecr] add Jev selective verification - #78

Draft
LipLoody wants to merge 2 commits into
mainfrom
jev-shadow-evaluation
Draft

LipLoody wants to merge 2 commits into
mainfrom
jev-shadow-evaluation

Conversation

@LipLoody

@LipLoody LipLoody commented Sep 21, 2026 •

Copy link
Copy Markdown
Contributor

Why

Jev can cheaply decide narrow local support questions, but it cannot replace open-ended or multi-step code review.

How

Use Jev as an active first-stage verifier that keeps clear support, drops clear ordinary contradictions, and defers uncertainty plus protected findings to the existing reasoning verifier.

Test Plan

  • bun test
  • bun run typecheck
  • bun run lint
  • bun run llp:check
  • bun run build
  • After merge, configured reviews use Jev directly; missing credentials or failed calls follow the prior verification path.

@LipLoody LipLoody changed the title [ecr] add Jev shadow evaluation Add Jev shadow evaluation Sep 21, 2026
@github-actions

github-actions Bot commented Sep 21, 2026 •

Copy link
Copy Markdown

🤖 AI code review

Decision: Ready for human review (with comments)

Overall PR risk: Medium. The change modifies the verification pipeline to add an optional Jev classifier that can keep or drop findings before the reasoning verifier runs. It is gated behind a root-only jev config block and absent by default, but the PR adds this block to the repository's own config, so the cascade is active once TYPESAFE_API_KEY is set. Four warnings identify issues with documentation and code: the workflow comment contradicts the actual Jev behavior and does not disclose that source is sent to TypeSafe, the template comment omits the same disclosure, code can wrongly drop findings that have no readable source, and a Jev model substitution is misreported to the user as an OpenCode fallback.

🔗 Review setup:

  • This PR changes code the reviewer prompts cite (src, src/tests, src/config/load.ts, src/config/schema.ts, src/core/auth.ts, and 4 more). Check that the guidance quoting it is still correct.

🟡 Warning (4)

  • Workflow comment misstates Jev activation and disclosure posture — .github/workflows/expo-code-review.yml:93 (security) · id:1eb70fb05e22
    Confidence: High — the config, schema, and docs changed in this PR all agree Jev has no enabled flag and is active once configured.
    Impact if shipped: Medium — maintainers reading this comment will wrongly believe Jev is inactive while source is being sent to TypeSafe.
    Suggested remediation: Update the comment to disclose actual behavior: "Optional Jev verification credential; active once the root config declares a jev block. Enabling it sends bounded file source to TypeSafe. No shadow mode, no enabled flag."

    Evidence and reasoning

    The comment claims the Jev evaluator is "Shadow-only" and "unused while config.jev.enabled is false." No enabled field exists in the jev schema; src/config/schema.ts defines only model, minConfidence, timeoutMs, and maxContextChars. The README added in this PR states: "There is no shadow mode or separate enabled flag." llp/0014-jev-selective-verification.explainer.md confirms "There is no separate enabled flag and no shadow phase."

    The same PR adds a populated jev block to .expo-agents/code-review/config.jsonc, so Jev is active in this repository once TYPESAFE_API_KEY is set. Yet the comment sits next to the secret mapping and claims it stays "shadow-only" and "unused" — the opposite of shipped behavior.

    Moreover, the comment fails to disclose that enabling Jev sends up to 30000 characters of repository source per finding to api.typesafe.ai, a provider separate from the model provider. The config schema documents this reason ("ROOT-ONLY because it sends bounded source context to a separate provider"), but the workflow comment omits it entirely.

    A maintainer could enable the secret believing the cascade is inert, not realizing it immediately changes verification behavior and sends repository source to an external provider.

  • Scaffolded jev block does not disclose that repository source leaves the repo — templates/config.jsonc:51 (security) · id:0cb0a185ac92
    Confidence: High — traced buildJevState back to inspectEvidence, which returns whole file contents up to maxContextChars.
    Impact if shipped: Medium — an adopter can enable jev and send private repository source to api.typesafe.ai without a warning in the template.
    Suggested remediation: Add a disclosure line: "Enabling this sends bounded repository SOURCE (up to maxContextChars per finding) to api.typesafe.ai, a provider separate from your model provider. Enable it only where that source may be shared."

    Evidence and reasoning

    This template scaffolds into every adopting repo. Adopters read the comments to decide if the block is safe to enable.

    The data path: verifyFindings calls inspectEvidence, which returns file text as sourceContext. verifyFindings passes that to evaluateFindingsWithJev. buildJevState bounds it to maxContextChars (default 30000) and sends it to https://api.typesafe.ai, a provider separate from the model provider.

    So enabling jev sends up to 30000 characters of repository source per finding to a third party. The comment block does not disclose this. It only names the credential.

    The repo's own convention requires this disclosure. The adjacent research block explicitly warns about sharing search terms with "Brave and the documentation providers." The schema records the reason: "ROOT-ONLY because it sends bounded source context to a separate provider." The template drops that disclosure.

  • Jev can drop a finding when no source context was read — src/core/verify.ts:182 (correctness) · id:1869ac49106d
    Confidence: High — inspectEvidence returns empty sourceContext for unreadable or out-of-tree files, and verifyFindings passes them to Jev.
    Impact if shipped: Medium — a real finding can be dropped with no source evidence behind the drop.
    Suggested remediation: Only build a Jev candidate when presence !== "unknown" and sourceContext is non-empty. Findings with no readable source must keep the pre-Jev path.

    Evidence and reasoning

    inspectEvidence returns { presence: "unknown", sourceContext: "" } when the resolved path fails pathInside or readFile throws. verifyFindings maps every checked finding into the Jev candidate list without filtering on presence or empty sourceContext. If Jev answers contradicted, jevDisposition returns "drop" for any ordinary finding, and the reasoning verifier never runs.

    This is reachable. scrubAmbientRuntimeConfig deletes AGENTS.md, CLAUDE.md, .claude, and .env* from the review tree, so readFile fails for findings about those files. Previously such a finding took the else branch and was kept as "non-critical." Now it can be suppressed by Jev with no source at all. LLP 0014 states that missing context must defer, but the code does not enforce that precondition.

  • Jev model substitution is misreported as an OpenCode fallback — src/core/review.ts:1121 (correctness) · id:57cd5da39bbd
    Confidence: High — direct trace through trackModel and the coverage-note builder.
    Impact if shipped: Medium — a user gets wrong diagnosis and wrong fix steps when the Jev provider changes its model id.
    Suggested remediation: Give the jev-verifier bucket its own substitution branch instead of falling through the engineOf[bucket] ?? "opencode" default, so the coverage note names TypeSafe/Jev, not OpenCode.

    Evidence and reasoning

    trackModel("jev-verifier", verification.jev.configuredModel, verification.jev.actualModel) reuses substitution logic built for the two reviewer engines. If TypeSafe returns an actualModel differing from the configured jev.model alias, trackModel adds "jev-verifier" to substitutedBuckets.

    At src/core/review.ts:975, the code maps each substituted bucket to an engine with engineOf[bucket] ?? "opencode". engineOf is built only from reviewer-agent ids; "jev-verifier" is never a key, so the fallback always resolves to "opencode". This makes subEngines.has("opencode") true, which appends guidance about OpenCode fallbacks to the coverage note. That guidance is wrong: Jev never runs through OpenCode, and the named settings (agents' model, coordinator.model, REVIEWER_MODEL) do not affect it. A maintainer debugging the warning would investigate the wrong subsystem.


This review is advisory — it never blocks a merge and never auto-approves.

@LipLoody LipLoody changed the title Add Jev shadow evaluation [ecr] add Jev selective verification Sep 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant