Skip to content

moooon

Motir

Vibe your whole project. Bring an idea — Motir's three AI layers plan it, track it, and ship it, end to end. You're looking at Motir, built in Motir.

  • Vibe Project
  • Open Source
  • AI Agent
  • AI Loop
1
requests
0
upvotes
145
planned
1,361
shipped

Motir · Work items

MOTIR-2648Done

(motir-core) The fixed-window alignment class survives in two more suites — `surfaceGuards.test.ts` (37 unpinned budgets) and `api-coding-convention-route.test.ts` — because the guard's file list is ENUMERATED, not derived

Repo: motir-core. One PR. Found by the motir run of MOTIR-2647 (2026-08-11) while sweeping for that card's defect, and logged rather than absorbed (notes.html #27) — 2647 is scoped to tests/mcp/rate-limit-gate.test.ts and this is a different, larger surface.

This is the fifth and sixth occurrence of the class MOTIR-2101MOTIR-2224MOTIR-2598MOTIR-2647 have each fixed one file of: a test that pins a rate-limit BUDGET, makes more than one counted call, and leaves the WINDOW at the shipped 60 s default, so the calls straddle an epoch-aligned boundary and the one expected to be refused is served.

The two survivors, grepped on origin/main

Sweep used (a file that assigns a *_RATE_LIMIT env, counted against the *_RATE_LIMIT_WINDOW_MS assignments in the same file):

filebudget assignmentswindow pinsimports the helper
tests/rateLimit/surfaceGuards.test.ts370no
tests/api-coding-convention-route.test.ts10no
every other budget-setting suite1–3≥1yes (or single-call)
  • tests/rateLimit/surfaceGuards.test.ts — the largest instance in the tree. Its ENVS array at :36–50 lists all six *_WINDOW_MS names for cleanup and the file sets none of them: the same "cleans up a knob it never sets" tell MOTIR-2647 was filed on, at six times the scale. Confirmed accumulating cases include :292 (generation takes its OWN budget — spend 1, expect the 2nd refused), :302, :313, :322 (a DEFAULT_AI_GENERATE_RATE_LIMIT-long loop, then one more), :347, :356, :364. All run against the real Postgres store through enforceAiRateLimit / enforceInternalServiceRateLimitconsumeSharedRateLimit, i.e. the same epoch-aligned bucket.
  • tests/api-coding-convention-route.test.ts:212refuses the over-budget re-audit with a 429 BEFORE it submits: budget 1, a 202 then an expected 429, no pin. A straddle serves the second request, so expect(refused.status).toBe(429) sees 202 and toHaveBeenCalledTimes(1) sees 2.

The reason it keeps surviving — fix THIS, not only the two files

tests/api/v1/rate-limit-window-alignment.test.ts already exists as the anti-recurrence guard, and it has two halves:

  1. a derived half — no file under tests/ may compute a window phase (Date.now() %) except the shared helper. Total, and it works.
  2. an enumerated half — an it.each([...]) naming the files that must import the helper. Hand-maintained. A file joins it when whoever fixed that file remembered to add it, which is precisely the step that has now been missed four times in a row.

So the guard is a list of the fires already put out. Replace the enumeration with a derivation over the same tree the first half already walks: a test file that assigns a *_RATE_LIMIT env must either pin the matching *_RATE_LIMIT_WINDOW_MS or import waitForWindowBoundary — with an explicit, commented allow-list for the genuinely single-call suites, so an exemption is a decision on the record rather than an omission.

Acceptance criteria

  1. tests/rateLimit/surfaceGuards.test.ts pins the window on every case that sets a budget and makes more than one counted call, via ALIGNED_WINDOW_MS + waitForWindowBoundary from tests/helpers/rateLimitWindow.ts — no second copy of the arithmetic. Ordered before AC 3 so the derived guard is written against a tree that already passes it.
  2. tests/api-coding-convention-route.test.ts:212 does the same.
  3. rate-limit-window-alignment.test.ts's it.each file list is DERIVED from the test tree rather than enumerated: any file assigning a *_RATE_LIMIT env fails unless it pins the matching window or imports the helper. Every exemption is named with the reason it is one.
  4. The derived guard is proven by DELIBERATELY introducing the violation — a fixture string (or a temporary file) that assigns a budget without a pin makes it fail — mirroring the the guard actually fires on a hand-rolled copy case already in that suite. A guard nobody has watched fail is indistinguishable from no guard.
  5. surfaceGuards.test.ts's added wall-clock cost is stated in the PR body. At 37 sites an unconditional align would add ~37 s; pin the window on every case and align only the ones whose outcome depends on the ACCUMULATED count.

Out of scope

tests/mcp/rate-limit-gate.test.ts (fixed by MOTIR-2647, which also adds itself to the enumerated list this card replaces), and the limiter's fail-open store-deadline arm (lib/rateLimit/limiter.ts:77) — a different bug if it ever fires, and one that produces a byte-identical symptom, so keep them apart. No production code changes.

Context refs

  • tests/rateLimit/surfaceGuards.test.ts · tests/api-coding-convention-route.test.ts — the two survivors.
  • tests/api/v1/rate-limit-window-alignment.test.ts — the guard, and the it.each to derive.
  • tests/helpers/rateLimitWindow.tsALIGNED_WINDOW_MS, waitForWindowBoundary, and the header explaining the class.
  • lib/rateLimit/limiter.ts:67 · lib/rateLimit/budgets.ts — the epoch-aligned bucket and the 60 s defaults.