feat(api): add a REST route + CLI mirror for loopover_check_test_evidence#6807
feat(api): add a REST route + CLI mirror for loopover_check_test_evidence#6807davion-knight wants to merge 1 commit into
Conversation
…ence loopover_check_test_evidence had neither a REST route nor a CLI mirror, unlike its same-tier deterministic-lint sibling loopover_check_slop_risk, which already has full parity (POST /v1/lint/slop-risk + an in-process stdio tool). Both are rate-limit-only, pure, path-metadata computations, so the asymmetry was arbitrary. The classification/guidance logic lived inside src/mcp/server.ts as a private method, so mirroring it by copy would have created a second, drifting implementation. Instead it is extracted verbatim into the engine as buildTestEvidenceReport (packages/loopover-engine/src/signals/test-evidence.ts, alongside the classifyTestCoverage/hasLocalTestEvidence/isCodeFile/isTestPath primitives it already uses). All THREE surfaces now derive their verdict from that one function: - src/mcp/server.ts's checkTestEvidence delegates to it (behaviour-preserving; the existing MCP tool tests pass unchanged). - POST /v1/lint/test-evidence, placed beside /v1/lint/slop-risk and structured identically. - The loopover_check_test_evidence stdio tool, computed IN-PROCESS like the check_slop_risk sibling rather than proxying over HTTP, so coverage self-checks work fully offline. Parity is therefore true by construction, and the tests pin it: for every arm (absent, free-text credit, docs-only, strong, adequate, weak) the route and the stdio tool each return exactly what the shared builder returns. The CLI test runs against a black-holed API URL, proving no round-trip. Plus zod/400 rejection on both surfaces. 100% line and branch coverage on every changed line across routes.ts, server.ts, and the engine builder. Closes JSONbored#6749
|
Superagent didn't find any vulnerabilities or security issues in this PR. |
|
|
Caution 🛑 LoopOver review result - reject/close recommendedReview updated: 2026-07-17 07:28:48 UTC
Review summary Blockers
Nits — 4 non-blocking
Why this is blocked
📋 Copy for AI agents — paste into your coding agentCI checks failing
Decision drivers
Context & advisory signals — never blocks the verdict
Linked issue satisfactionPartially addressed Review context
Contributor next steps
Signal definitions
🧪 Chat with LoopOverAsk LoopOver a question about this PR directly in a comment — grounded only in the same cached, public-safe facts shown above, never a new claim.
Full command reference: https://loopover.ai/docs/loopover-commands 🧪 Experimental — new and may change. 🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed 💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →. Checked by LoopOver, a quiet PR intelligence layer for OSS maintainers.
|
|
LoopOver is closing this pull request on the maintainer's behalf (CI is failing (validate, validate-tests (3), validate-tests (1), validate-tests (6), validate-tests (4), validate-tests (5), validate-tests (2), validate-code, Build UI preview artifact); AI reviewers agree on a likely critical defect: packages/loopover-engine/src/signals/test-evidence.ts:143 — buildTestEvidenceReport calls `hasLocalTestEvidence({ tests: input.tests, testFiles: input.testFiles })` where `input.tests` is typed `string | undefined` and `input.testFiles` is `readonly string[] | undefined`, but `hasLocalTestEvidence` (same file, unchanged) requires `tests?: string[] | undefined` and a mutable `testFiles?: string[] | undefined` — this is a real type-signature mismatch on newly-added code, not a pre-existing untouched line, and should fail typecheck.). This is an automated maintenance action — to pursue this change, please open a new pull request with the issues resolved. Closed PRs may be analyzed later to improve review accuracy, but they are not automatically reopened or re-reviewed. |
What & why
loopover_check_test_evidencehad neither a REST route nor a CLI mirror — unlike its same-tier deterministic-lint siblingloopover_check_slop_risk, which already has full parity (POST /v1/lint/slop-risk+ an in-process stdio tool). Both are rate-limit-only, pure, path-metadata computations, so the asymmetry was arbitrary.One implementation, three surfaces
The classification/guidance logic lived as a private method inside
src/mcp/server.ts. Mirroring it by copy would have created a second, drifting implementation — so it's extracted verbatim into the engine asbuildTestEvidenceReport, alongside theclassifyTestCoverage/hasLocalTestEvidence/isCodeFile/isTestPathprimitives it already uses.All three surfaces now derive their verdict from that one function:
src/mcp/server.ts'scheckTestEvidencedelegates to it — behaviour-preserving, proven by the existing MCP tool tests passing unchanged.POST /v1/lint/test-evidence, placed beside/v1/lint/slop-riskand structured identically.loopover_check_test_evidencestdio tool, computed in-process like itscheck_slop_risksibling rather than proxying over HTTP — so coverage self-checks work fully offline.Parity is therefore true by construction, not by convention.
Tests
The issue asks for "a test asserting output parity between the mirrored surfaces for identical input", so that's the backbone: for every arm —
absent, free-text credit, docs-only,strong,adequate,weak— the route and the stdio tool each return exactly what the shared builder returns. The free-text credit rule is pinned specifically (it may only ever lift anabsentverdict, never loosen a real one). The CLI test runs against a black-holed API URL (http://127.0.0.1:1), proving the in-process claim. Plus zod/400 rejection on both surfaces.100% line and branch coverage on every changed line across
routes.ts,server.ts, and the engine builder — measured against the changed-line set.Closes #6749