Skip to content

4 repo-picker panels have no stale-response guard - free-text keystrokes race each other #7784

Description

@JSONbored

Context

4 components bind a free-text <input value={repoFullName} onChange={...setRepoFullName}> directly to a useCallback(async () => { ...await apiFetch...; setState(...) }, [repoFullName]) + useEffect(() => { void load(); }, [load]):

  • apps/loopover-ui/src/components/site/app-panels/ams-miner-cohort-card.tsx:101-126
  • apps/loopover-ui/src/components/site/app-panels/ai-review-settings.tsx:64-93
  • apps/loopover-ui/src/components/site/app-panels/activation-preview.tsx:68-92
  • apps/loopover-ui/src/components/site/app-panels/maintainer-settings.tsx:148-174 and :523-538 (FocusManifestEditor)

Since splitRepoFullName (see the companion issue on that function) accepts any non-empty owner/repo pair, every keystroke past the first / produces a new valid repoFullName and fires a new fetch, with no cancellation/ticket/generation guard. If an earlier (shorter, partially-typed) request resolves after a later one, its response silently overwrites comparison/preview/settings/keyStatus state - e.g. ai-review-settings.tsx would show the wrong repo's BYOK key status and AI-review mode after the user finishes typing a different repo name. This is the same bug class as the already-fixed AuditFeed "Load more" out-of-order-response issue, just triggered by keystrokes instead of pagination.

maintainer-panel.tsx's runPreview (line 528) uses the same shape but is button-triggered rather than auto-fetch-on-keystroke, so it's lower risk and is not included as a required fix site here.

Requirements

⚠️ Required pattern - reuse one of the two already-proven guards in this codebase, do not invent a third: either the cancelled-flag idiom from apps/loopover-miner-ui/src/lib/use-polled-fetch.ts:44,53,64 (set in the effect cleanup, checked before every setResult), or the explicit stale-response-generation guard already shipped in apps/loopover-ui/src/components/site/audit-feed.tsx:134. Apply the same guard shape to all 4 components/5 load functions listed above.

Deliverables

  • ams-miner-cohort-card.tsx's load function ignores a response that resolves after a newer request was issued for a different repoFullName.
  • ai-review-settings.tsx's load function has the same guard.
  • activation-preview.tsx's load function has the same guard.
  • maintainer-settings.tsx's load function AND FocusManifestEditor's load function both have the same guard.
  • A regression test (at least for one representative component) simulating an out-of-order response resolution and asserting the stale response is ignored.

Test Coverage Requirements

apps/loopover-ui is not covered by the src/** 99% patch gate - the new regression test(s) are this issue's own coverage deliverable.

Expected Outcome

Typing a new repo name into any of these 4 panels never has an earlier, now-stale request's response silently overwrite the state for the repo the user actually finished typing.

Links & Resources

apps/loopover-ui/src/lib/use-polled-fetch.ts:44,53,64 and apps/loopover-ui/src/components/site/audit-feed.tsx:134 (the two existing guard patterns to reuse); the 4 affected components listed above

Metadata

Metadata

Assignees

No one assigned

    Labels

    gittensor:bugGittensor-scored bug fix — scores a 0.05x multiplier.help wantedExtra attention is needed

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions