Skip to content

types(mcp): finish the option-plumbing sweep, and cover both arms of every fallback (#9824) - #9826

Merged
JSONbored merged 1 commit into
mainfrom
types/cli-option-sweep-9824
Jul 29, 2026
Merged

types(mcp): finish the option-plumbing sweep, and cover both arms of every fallback (#9824)#9826
JSONbored merged 1 commit into
mainfrom
types/cli-option-sweep-9824

Conversation

@JSONbored

Copy link
Copy Markdown
Owner

Closes #9824. Follow-up to #9785 — the review of that PR caught one site the sweep missed, and it turned out to be the visible end of a family.

The seven that were left

Invocation Was
analyze-branch --login boolean true sent to /v1/local/branch-analysis as the contributor login
review-pr --login same
login --github-token true is truthy, so the token branch ran with true as the token instead of falling through to the device flow
maintain selftune-audit --limit Number(true) is 1 — the audit silently capped at one row instead of the server default
maintain precision --window-days same, a one-day window
maintain audit-feed --since String(true) sent ?since=true, which the route reads as a cursor
validate-config --file !options.file passed (a bare flag is true, which is truthy) and the manifest was read from the path ""

Fewer copies, not more narrowing calls

Rather than add an eighth copy of each chain, the duplicated ones became single helpers:

  • resolveLogin — flag → profile session → LOOPOVER_LOGINGITHUB_LOGIN, previously written out at 14 call sites. That duplication is precisely how two of them ended up different from the other twelve.
  • readOptionalTextFile — replaces three copies of readCliTextFile(optionText(x) ?? "", …), which read the path "" for a valueless flag.
  • issueNumbersOption — replaces three copies of the array/scalar/absent dance, two of which still carried (value: any) annotations.

optionalInteger and optionalNumber lose their any parameters — the annotation this issue exists to remove — and a named CliOptionValue states the union once instead of four times.

An enum the CLI was restating

branchEligibilityFromOptions hand-copied the route's two vocabularies and silently dropped anything it did not recognise, so a status the route accepts could be discarded by the CLI with no error. It parses against the route's own schema now. branchEligibilitySchema is a zod pipe (it transforms), so its members were unreachable through it — the contract exports the pre-transform object branchEligibilityFields for the purpose, which is also the honest fix for anyone else who needs those fields.

Coverage: 100% of the diff, lines and branches

Measured on the changed file:

uncovered lines: [] | partial-branch lines: 0

Every fallback is exercised from both sides in test/unit/mcp-cli-option-resolution.test.ts (24 cases), driven in-process. That is not a style preference: the rest of the CLI suite spawns the compiled dist/ through a subprocess harness, which v8 cannot instrument, so a path covered only there reads as uncovered — which is how a regression in one of these arms would land unnoticed, and why codecov/patch on #9785 saw branch gaps that the passing subprocess tests did nothing to close.

One dead branch is removed rather than covered: ensureProfile's options: CliOptions = {} default had a single call site that always passes options.

Validation

  • npx vitest run --changed=origin/main: 2207 passed, 154 files. tsc --noEmit clean.
  • Every fixed invocation has a regression case named for what it did before.

@loopover-orb

loopover-orb Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Caution

🛑 LoopOver review result - fixes required

Review updated: 2026-07-29 12:51:45 UTC

4 files · 1 AI reviewer · no blockers · CI failing · unstable

🛑 Suggested Action - Manual Review

Review summary
This PR finishes the #9773/#9824 option-plumbing sweep: it fixes the seven remaining sites where a valueless flag (parsed as boolean `true`) leaked into a login, token, limit, since/pull query, or file path, consolidates 14 duplicated login-resolution call sites into `resolveLogin`, replaces three duplicated file-read/issue-array patterns with `readOptionalTextFile`/`issueNumbersOption`, and moves `branchEligibilityFromOptions` onto the route's own `branchEligibilityFields` zod schema instead of two hand-copied enum lists. The diff is narrow, closes the linked issue, and each fixed call site is traced to the exact bug described in the PR body (e.g. `Number(true) === 1` silently capping `--limit`, `String(true)` sending `?since=true`). The new test files (`mcp-cli-option-resolution.test.ts` and the `mcp-cli-bool-flag-parsing.test.ts` additions) drive the real CLI dispatcher in-process and assert on the actual outgoing request/URL, exercising both the flag-present and flag-absent arms for every fixed site rather than fabricating unreachable states.

Nits — 5 non-blocking
  • packages/loopover-mcp/bin/loopover-mcp.ts:5269 — `ensureProfile`'s `options: CliOptions = {}` default was removed in favor of a required parameter; confirm every call site in the (not fully shown) file still passes an explicit `options` argument so this doesn't become a compile break.
  • The CI checks `validate-tests` and `validate` failed with no detail provided; given this branch is 1 commit behind the default branch, that's a plausible cause worth ruling out with a rebase before assuming a content defect.
  • packages/loopover-contract/src/api-requests.ts — `branchEligibilityFields` and `branchEligibilitySchema` are now two exports where there was one; a short doc-comment cross-reference (already present) is good, but consider a meta-test pinning that the two never drift the way the file's existing convention does for other split schemas.
  • Consider adding a one-line JSDoc example to `resolveLogin`'s `{ fromProfile }` option showing which commands pass `false` vs the default, since the distinction is easy to get backwards when adding a new login-taking command.
  • PR author also opened the linked issue — Link an issue that was opened by a different contributor, or provide a rationale for why this self-authored issue represents genuine discovery work.

CI checks failing

  • codecov/patch — 96.42% of diff hit (target 99.00%)

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 #9824
Related work ✅ No active overlap found No same-issue or scoped active PR overlap found.
Change scope ✅ 20/20 Low 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: 14 registered-repo PR(s), 13 merged, 345 issue(s).
Contributor context ✅ Confirmed Gittensor contributor JSONbored; Gittensor profile; 14 PR(s), 345 issue(s).
Improvement ✅ Minor risk: clean · value: minor
Linked issue satisfaction

Addressed
The diff narrows all seven listed raw reads (login on analyze-branch/review-pr, github-token, limit, window-days, since, file), introduces the resolveLogin/readOptionalTextFile/issueNumbersOption helpers replacing the duplicated chains, makes branchEligibilityFromOptions parse against the exported branchEligibilityFields schema, and removes `any` from optionalInteger/optionalNumber with a named Cl

Review context
  • Author: JSONbored
  • Role context: owner (maintainer lane)
  • Public audience mode: oss maintainer
  • Lane context: Repository is registered but has no active allocation in the current snapshot.
  • Public profile languages: not available
  • Official Gittensor activity: 14 PR(s), 345 issue(s).
  • PR-specific overlap: none found.
Contributor next steps
  • Start here: Treat this as maintainer-lane context rather than normal contributor-lane activity.
  • Then work through the remaining 1 step 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 <question> answers contribution-quality Q&A with source citations and freshness.
  • @loopover chat <question> 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.

Decision record
  • action: hold · clause: success
  • config: 97c5a8a1cb45148876d75f5ecb6c89412a3bb68cb11b47c9ffced814b23b6c43 · pack: oss-anti-slop · ci: failed
  • record: 2890bb63f2d67fdfedb115ac441d0ed8ca9c9ae9ba0088504346c761999b89b9 (schema v5, head 31bdcbb)

🟩 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

@superagent-security

Copy link
Copy Markdown
Contributor

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

@JSONbored JSONbored self-assigned this Jul 29, 2026
@codecov

codecov Bot commented Jul 29, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 96.42857% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 91.64%. Comparing base (9d7f567) to head (31bdcbb).
⚠️ Report is 4 commits behind head on main.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
packages/loopover-contract/src/api-requests.ts 66.66% 0 Missing and 1 partial ⚠️
packages/loopover-mcp/bin/loopover-mcp.ts 98.11% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #9826      +/-   ##
==========================================
+ Coverage   91.59%   91.64%   +0.04%     
==========================================
  Files         915      915              
  Lines      112700   112710      +10     
  Branches    27077    27067      -10     
==========================================
+ Hits       103229   103288      +59     
+ Misses       8144     8129      -15     
+ Partials     1327     1293      -34     
Flag Coverage Δ
backend 95.66% <96.42%> (+0.07%) ⬆️

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

Files with missing lines Coverage Δ
packages/loopover-contract/src/api-requests.ts 98.63% <66.66%> (+0.01%) ⬆️
packages/loopover-mcp/bin/loopover-mcp.ts 69.95% <98.11%> (+2.53%) ⬆️

... and 1 file with indirect coverage changes

@loopover-orb loopover-orb Bot added the manual-review Gittensor contributor context label Jul 29, 2026
…every fallback (#9824)

The review found `explainReviewRiskCli` reading `options.login` raw. That one was the visible end of a
family -- seven more sites read an option without narrowing it, each reachable by an ordinary typo:

- `analyze-branch --login` and `review-pr --login` sent boolean `true` as the contributor login.
- `login --github-token` with no value took the token branch with `true` as the token, instead of
  falling through to the device flow.
- `Number(options.limit)` on a bare `--limit` is 1, so the flag silently capped an audit at one row
  rather than leaving the server's default in place. Same for `--window-days`.
- `String(options.since)` sent `?since=true`, which the route reads as a cursor.
- `validate-config --file` passed a `!options.file` guard (a bare flag is `true`, which is truthy)
  and then read the manifest from the path "".

Rather than add an eighth copy of each chain, the duplicated ones are now single helpers --
`resolveLogin` (flag, profile session, then two env vars, at 14 call sites), `readOptionalTextFile`
and `issueNumbersOption` -- so there is one place to get it right and one place to test.
`optionalInteger` and `optionalNumber` lose their `any` parameters, which is this issue's subject.

`branchEligibilityFromOptions` restated the route's two enums by hand and dropped anything it did not
recognise. It parses against `branchEligibilityFields` now, exported from the contract for the
purpose: the schema was a pipe, so its members were unreachable through it.

Coverage: the diff is at 100% of lines AND branches in the CLI. Every fallback is exercised from both
sides in `test/unit/mcp-cli-option-resolution.test.ts`, in-process -- the subprocess harness the rest
of the CLI suite uses runs the compiled `dist/`, which v8 cannot instrument, so a path covered only
there reads as uncovered and a regression in one of these arms would land unnoticed.
@JSONbored
JSONbored force-pushed the types/cli-option-sweep-9824 branch from 4ed62fa to 31bdcbb Compare July 29, 2026 12:29
@JSONbored
JSONbored merged commit 503eb0c into main Jul 29, 2026
7 of 8 checks passed
@JSONbored
JSONbored deleted the types/cli-option-sweep-9824 branch July 29, 2026 12:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

manual-review Gittensor contributor context

Projects

None yet

Development

Successfully merging this pull request may close these issues.

types(mcp): the option-plumbing sweep left seven raw reads, and the CLI restates two route enums by hand

1 participant