(motir-core) `main` is RED on the coverage gate — MOTIR-2648 removed the window nondeterminism that was accidentally covering `mcpGuard.ts`'s plural-seconds branch
Repo: motir-core. One PR. Found by the motir run of MOTIR-2646 (2026-08-11) when that PR's CI went red on a gate its diff cannot reach, and logged rather than absorbed (notes.html #27).
main itself is red, and every open PR inherits it
ERROR: Coverage for branches (75%) does not meet "lib/rateLimit/mcpGuard.ts" threshold (90%)
mcpGuard.ts | 100 | 75 | 100 | 100 | 87
| commit | CI |
|---|---|
b05d10dc (MOTIR-2645, #2034) | success |
28d0cb00 (MOTIR-2648, #2035) | failure — run 31500892820, job Vitest coverage |
PR CI checks out the branch merged with main, so this red-lights every open PR's CI complete regardless of its diff. It is doing so on PR #2036 right now, whose diff touches only tests/e2e/_helpers/**, a vitest.config.ts COMMENT, and a decision doc.
⚠️ #2035's own check shows pass — it ran against the pre-merge composition. This is the MOTIR-2572-era shape again: green on the branch, red once merged.
The mechanism — the coverage was an artifact of the flake that was just fixed
lib/rateLimit/mcpGuard.ts:87 is the only uncovered branch:
message: `Too many requests. Retry in ${retryAfter} second${retryAfter === 1 ? '' : 's'}.`,
Nothing asserts the plural arm on purpose. tests/rateLimit/surfaceGuards.test.ts:586 asserts the singular one verbatim ('Too many requests. Retry in 1 second.'), and :507 accepts either via /Retry in \d+ seconds?\./.
Before #2035 those suites left the window at the shipped 60 s default, so retryAfterSeconds(decision) landed wherever the epoch-aligned bucket happened to be — frequently > 1, which took the 's' arm and coloured the branch green. #2035 pinned the window (correctly — that is the whole point of MOTIR-2648), retryAfter became deterministically 1, and the plural arm stopped executing.
So the gate is not lying and #2035 is not wrong. The branch was never deliberately covered; its coverage was a side effect of the nondeterminism MOTIR-2648 removed. The gate is reporting a real, pre-existing hole that the flake had been hiding.
Acceptance criteria
- A DETERMINISTIC unit test covers the plural arm of
mcpRateLimitedResponse— construct aRateLimitDecisionwhoseresetAtis more than one second out and assert the message endsseconds.. No database, no window, no wall-clock wait: the bug this closes is that the only previous coverage came from a race. - The singular arm keeps a deliberate assertion too, so neither arm can silently revert to being covered by accident.
lib/rateLimit/mcpGuard.tsreports ≥90 % branches underpnpm test:coverage, and the number is quoted in the PR body.- The identical pluralisation at
lib/rateLimit/guard.ts:75andlib/api/v1/rateLimit.ts:66is checked for the same hole; each is either already covered (say so, with its number) or given the same two-arm test. This class does not get fixed one file at a time again — that is exactly the lesson MOTIR-2648 was filed on. mainis green onVitest coverageafter the merge.
Out of scope
- Lowering the 90 % threshold. The hole is real; the gate found it.
- Reverting or weakening any window pin from #2035.
- The rest of
lib/rateLimit/**(at 98.33 % branches overall).
Context refs
lib/rateLimit/mcpGuard.ts:80-88—mcpRateLimitedResponseand the uncovered ternary.lib/api/v1/rateLimit.ts—retryAfterSeconds, which now returns a pinned value.tests/rateLimit/surfaceGuards.test.ts:507,586— the two existing assertions.vitest.config.ts— thelib/rateLimit/**include and its 90 % threshold.- MOTIR-2648 / PR #2035 — the merge that surfaced this.