Skip to content

feat(api): add a REST route + CLI mirror for loopover_check_test_evidence#6810

Merged
loopover-orb[bot] merged 1 commit into
JSONbored:mainfrom
davion-knight:feat-test-evidence-mirror-v2
Jul 17, 2026
Merged

feat(api): add a REST route + CLI mirror for loopover_check_test_evidence#6810
loopover-orb[bot] merged 1 commit into
JSONbored:mainfrom
davion-knight:feat-test-evidence-mirror-v2

Conversation

@davion-knight

Copy link
Copy Markdown
Contributor

What & why

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.

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 as buildTestEvidenceReport, 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, proven by the existing MCP tool tests passing 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 its check_slop_risk sibling 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 armabsent, 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 an absent verdict, 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.

Fixes from the #6807 review

The reviewer was right on all counts, and the root cause was mine: I wrote the mirror schemas from assumption instead of reading checkTestEvidenceShape.

  • Blocker — type mismatch (test-evidence.ts:143). I'd typed the builder's tests as string, but the MCP tool's shape declares tests: z.array(z.string().max(400)).max(2000).optional() — an array. hasLocalTestEvidence wants mutable string[]. Fixed: the builder now takes readonly string[] and copies into hasLocalTestEvidence's mutable params. This also means my REST/CLI schemas were wrong in a way that broke the very parity the issue asks for — both now mirror checkTestEvidenceShape verbatim (same bounds, same optionality), including accepting an empty changedPaths exactly like the tool does.
  • Nit — fragile .length-on-string. Gone; the array typing makes the intent explicit rather than relying on string and array both having .length (which is precisely why my tests passed while the types were wrong).
  • Nit — parity tests prove wiring, not correctness. Fair. Added test/unit/test-evidence-report.test.ts, a standalone suite pinning the builder independently of both consumers: exact classifications at and around both ratio boundaries (0.4 strong, 0.2 adequate), the free-text credit rule, guidance arms, and readonly-input safety.

I also fixed my own process gap: tsc --noEmit is clean this time (I'd skipped it, which is exactly why a type error reached CI).

Closes #6749

…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 as a private method in src/mcp/server.ts, so mirroring it by
copy would have created a second, drifting implementation. It is extracted verbatim into the engine as
buildTestEvidenceReport, beside the classifyTestCoverage/hasLocalTestEvidence/isCodeFile/isTestPath
primitives it already uses. All three surfaces 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, 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.

Both new input schemas mirror the MCP tool's checkTestEvidenceShape VERBATIM -- same bounds, same
optionality, and `tests` as an array of strings (not free text) -- so no surface can accept an input
another would reject. buildTestEvidenceReport takes readonly arrays and copies them into
hasLocalTestEvidence's mutable parameters rather than passing them through.

test/unit/test-evidence-report.test.ts pins the builder's own classification independently of its
consumers, at and around both ratio boundaries (0.4 strong, 0.2 adequate), plus the free-text credit
rule (it may only ever LIFT an absent verdict, never loosen a real one) and readonly-input safety. The
route and CLI suites then assert each surface returns exactly what the builder returns; the CLI runs
against a black-holed API URL, proving no round-trip. 100% line and branch coverage on every changed
line across routes.ts, server.ts, and the engine builder.

Closes JSONbored#6749
@davion-knight
davion-knight requested a review from JSONbored as a code owner July 17, 2026 07:43
@superagent-security

Copy link
Copy Markdown
Contributor

Superagent didn't find any vulnerabilities or security issues in this PR.

@codecov

codecov Bot commented Jul 17, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 93.63%. Comparing base (8e2f967) to head (839c5e7).
⚠️ Report is 3 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #6810   +/-   ##
=======================================
  Coverage   93.63%   93.63%           
=======================================
  Files         683      683           
  Lines       68154    68163    +9     
  Branches    18704    18706    +2     
=======================================
+ Hits        63818    63827    +9     
  Misses       3350     3350           
  Partials      986      986           
Flag Coverage Δ
shard-1 43.69% <92.59%> (+0.03%) ⬆️
shard-2 36.86% <85.18%> (+0.02%) ⬆️
shard-3 32.81% <7.40%> (+0.14%) ⬆️
shard-4 34.67% <7.40%> (+0.46%) ⬆️
shard-5 31.78% <7.40%> (+0.22%) ⬆️
shard-6 45.46% <77.77%> (-0.28%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
...kages/loopover-engine/src/signals/test-evidence.ts 100.00% <100.00%> (ø)
src/api/routes.ts 94.69% <100.00%> (+0.01%) ⬆️
src/mcp/server.ts 96.30% <100.00%> (-0.07%) ⬇️

@loopover-orb loopover-orb Bot added the gittensor:feature Gittensor-scored feature linked to a feature issue — scores a 0.25x multiplier. label Jul 17, 2026
@loopover-orb

loopover-orb Bot commented Jul 17, 2026

Copy link
Copy Markdown

Tip

✅ LoopOver review result - approve/merge recommended

Review updated: 2026-07-17 07:54:35 UTC

8 files · 1 AI reviewer · no blockers · readiness 82/100 · CI green · clean

✅ Suggested Action - Approve/Merge

  • safe to merge

Review summary
This extracts the private checkTestEvidence logic in src/mcp/server.ts into a pure buildTestEvidenceReport in the engine, then wires it identically into a new POST /v1/lint/test-evidence route and an in-process CLI stdio tool, giving loopover_check_test_evidence the same three-surface parity its sibling slop-risk tool already has. The zod shapes across server.ts, routes.ts, and the CLI are kept literally identical (min/max bounds match), and the extraction is a verbatim behavior-preserving move confirmed by the diff on server.ts (old inline logic deleted, replaced by a single delegating call). Tests assert parity across all three surfaces for every classification arm plus the free-text-credit edge cases, which is exactly what the issue calls for.

Nits — 4 non-blocking
  • The size-smell/deep-nesting/magic-number flags from the external brief (long files, REST + CLI mirror for loopover_check_test_evidence #6749 issue-number literal, depth-5 branch chain in buildTestEvidenceReport) are pre-existing patterns in this codebase's conventions, not new problems introduced by this diff's structure — but the if/else-if chain in buildTestEvidenceReport (test-evidence.ts) could be flattened slightly for readability.
  • packages/loopover-mcp/bin/loopover-mcp.js:550-552 and src/api/routes.ts:495-497 duplicate the same zod shape as three separate literals instead of importing a shared schema — consider extracting a shared Zod schema/const if this trio needs to change bounds again, to avoid the three copies silently drifting.
  • Consider a single shared zod schema (e.g. exported from the engine or a shared schema module) for checkTestEvidenceShape/testEvidenceSchema instead of three independently-maintained copies, since a future bound change to one could be missed on the others despite the current tests catching drift only via behavior, not schema equality.
  • The PR description says it closes/relates to issue REST + CLI mirror for loopover_check_test_evidence #6749 (referenced throughout code comments) — worth confirming that issue number is the correct one being closed, since the external brief notes only partial linked-issue coverage.

Decision drivers

  • ✅ Code review — No blockers (1 reviewer)
  • ✅ Gate result — Passing (No configured blocker found.)
Context & advisory signals — never blocks the verdict
Signal Result Evidence
Linked issue ✅ Linked #6749
Related work ⚠️ 3 scoped overlaps Top overlaps are listed below; lower-confidence bulk is hidden.
Change scope ❌ 8/20 High review scope from cached public metadata (1 linked issue).
Validation posture ✅ 25/25 PR body includes validation/test evidence.
Contributor workload ✅ 10/10 Author activity: 178 registered-repo PR(s), 112 merged, 0 issue(s).
Contributor context ✅ Confirmed Gittensor contributor davion-knight; Gittensor profile; 178 PR(s), 0 issue(s).
Improvement ✅ Minor risk: clean · value: minor · LLM: moderate
Linked issue satisfaction

Partially addressed
The PR delivers the REST route (POST /v1/lint/test-evidence) with strong parity tests, and adds an in-process stdio MCP tool mirror plus extensive unit tests, but the issue explicitly asks for a 'test-evidence CLI subcommand' analogous to slopRiskCli, and the diff shows only a stdio MCP tool registration in loopover-mcp.js rather than a CLI subcommand (e.g. `loopover-mcp test-evidence`) invokable

Review context
  • Author: davion-knight
  • Role context: outside_contributor
  • Public audience mode: oss maintainer
  • Lane context: Repository is configured for direct PR review.
  • Public profile languages: Rust
  • Official Gittensor activity: 178 PR(s), 0 issue(s).
  • Related work: Titles/paths share 8 meaningful terms. (issue #6744, issue #6748)
  • Related work: Titles/paths share 8 meaningful terms. (issue #6744, issue #6749)
  • Related work: Titles/paths share 8 meaningful terms. (issue #6747, issue #6748)
  • Additional title-only matches omitted; title-only overlap does not block.
Contributor next steps
  • Start here: Review top overlaps.
  • Then work through the remaining 2 steps in the Signals table above.
Signal definitions
  • Related work = same linked issue, overlapping active PRs, or title/path similarity.
  • Change scope = cached public metadata such as size labels, draft state, and review-burden hints.
  • Validation posture = whether the PR provides enough public validation/test evidence for maintainer review.
  • Contributor workload = public contributor activity and cleanup pressure, not a repo-wide quality failure.
  • Contributor context = public GitHub/Gittensor identity context; non-Gittensor status is not a blocker.
🧪 Chat with LoopOver

Ask 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.

  • @loopover ask &lt;question&gt; answers contribution-quality Q&A with source citations and freshness.
  • @loopover chat &lt;question&gt; answers in natural prose from cached decision-pack facts via local inference (maintainer/collaborator; read-only).
  • A plain-language @loopover mention with a real question is routed to the closest matching read-only command automatically — no exact syntax required.

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.

  • Re-run LoopOver review

@loopover-orb loopover-orb Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LoopOver approves — the gate is satisfied and CI is green.

@loopover-orb
loopover-orb Bot merged commit d45d8fd into JSONbored:main Jul 17, 2026
16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gittensor:feature Gittensor-scored feature linked to a feature issue — scores a 0.25x multiplier.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

REST + CLI mirror for loopover_check_test_evidence

1 participant