Skip to content

feat(miner): add bounded retry/backoff to claim-conflict-resolver's post-submission live-state check - #6081

Merged
loopover-orb[bot] merged 1 commit into
JSONbored:mainfrom
jaytbarimbao-collab:feat-claim-conflict-retry-backoff
Jul 15, 2026
Merged

feat(miner): add bounded retry/backoff to claim-conflict-resolver's post-submission live-state check#6081
loopover-orb[bot] merged 1 commit into
JSONbored:mainfrom
jaytbarimbao-collab:feat-claim-conflict-retry-backoff

Conversation

@jaytbarimbao-collab

Copy link
Copy Markdown
Contributor

Fixes #6058.

resolveClaimConflict (post-submission TOCTOU reconciliation, #4848) fetched the live competing-claims snapshot exactly once, so a genuine competing PR that hadn't yet propagated through GitHub's search/GraphQL index in that instant was invisible — a gap the module's own header documented as "its own separate scope."

Wraps the snapshot fetch in a bounded retry-with-backoff following this repo's existing http-retry.js convention: up to maxAttempts (default 3) attempts with exponential backoff (reusing defaultRetryBackoffMs) between them, returning as soon as a competing claim is observed, and otherwise giving a late-propagating competitor time to surface before this miner is declared the winner. Pure over injected sleepFn/backoffMs (no real timers in tests). Scoped to the detection step only — the maintainer-gated write-authorization boundary (#4833) is unchanged.

15 tests pass (3 existing updated for the retry path + 5 new retry-branch tests), 100% branch coverage on the module, caller (attempt-cli) regression green, .d.ts updated, typecheck clean.

…ost-submission live-state check

Fixes JSONbored#6058.

resolveClaimConflict fetched the live competing-claims snapshot exactly once
post-submission, so a genuine competing PR that hadn't yet propagated through
GitHub's search/GraphQL index in that instant was invisible (the module's own
header documented this gap). Wraps the snapshot fetch in a bounded
retry-with-backoff following http-retry.js's convention: up to maxAttempts
(default 3) attempts with exponential backoff between them, returning as soon as
a competing claim is observed and otherwise giving a late-propagating competitor
time to surface. Pure over injected sleepFn/backoffMs (no real timers in tests);
the maintainer-gated write boundary (JSONbored#4833) is unchanged.
@superagent-security

Copy link
Copy Markdown
Contributor

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

@codecov

codecov Bot commented Jul 15, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 95.23%. Comparing base (00db6b7) to head (f3c85a4).
⚠️ Report is 8 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #6081   +/-   ##
=======================================
  Coverage   95.22%   95.23%           
=======================================
  Files         595      595           
  Lines       46998    47023   +25     
  Branches    15015    15015           
=======================================
+ Hits        44756    44781   +25     
  Misses       1493     1493           
  Partials      749      749           
Flag Coverage Δ
shard-1 43.95% <100.00%> (-0.07%) ⬇️
shard-2 36.57% <94.11%> (+0.09%) ⬆️
shard-3 31.88% <0.00%> (-0.07%) ⬇️
shard-4 31.96% <0.00%> (-1.07%) ⬇️
shard-5 32.65% <11.76%> (+1.15%) ⬆️
shard-6 44.67% <11.76%> (+0.02%) ⬆️

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

Files with missing lines Coverage Δ
...ages/loopover-miner/lib/claim-conflict-resolver.js 100.00% <100.00%> (ø)

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

loopover-orb Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Tip

🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩

✅ LoopOver review result - approve/merge recommended

Review updated: 2026-07-15 08:49:27 UTC

3 files · 1 AI reviewer · no blockers · readiness 77/100 · CI green · clean

✅ Suggested Action - Approve/Merge

  • safe to merge

Review summary
This adds a bounded, injectable-clock retry/backoff loop around the post-submission live-state snapshot fetch in resolveClaimConflict, closing the documented eventual-consistency gap (#6058) where a same-instant competing PR wasn't yet indexed by GitHub's search/GraphQL. The loop logic is correct: it keeps the last successfully-fetched snapshot even if a later attempt throws or returns non-object, breaks early as soon as a competitor is observed, and only backs off between attempts (never after the last), preserving the old checked:false/live_state_unavailable contract when every attempt fails. The retry tests genuinely drive the real branches (early-stop, exhaustion, transient-failure-then-success, real setTimeout default path) rather than fabricating unreachable states, and the .d.ts/caller wiring is consistent.

Nits — 4 non-blocking
  • claim-conflict-resolver.js: with no options passed from attempt-cli.js, every real 'submitted' outcome now pays up to two real backoffMs sleeps by default before the CLI can finish — worth confirming the default backoff magnitude (from defaultRetryBackoffMs) is small enough not to noticeably slow down every successful attempt's tail latency.
  • claim-conflict-resolver.js: the JSDoc for resolveClaimConflict doesn't explicitly state that `checked:false` now only happens when *every* attempt fails to return a usable snapshot, which is a slightly different guarantee than the old one-shot version — worth a one-line clarification for future readers.
  • Consider surfacing the number of attempts actually used (or whether a retry occurred) in the result object for observability, since this is exactly the kind of eventual-consistency race that's hard to debug in production logs.
  • If defaultRetryBackoffMs was tuned for HTTP retries elsewhere, double check it's still an appropriate default for this specific index-propagation-lag scenario rather than reusing it purely for convention's sake.
Signal Result Evidence
Code review ✅ No blockers 1 reviewer
Linked issue ✅ Linked #6058
Related work ⚠️ 2 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: 108 registered-repo PR(s), 53 merged, 4 issue(s).
Contributor context ✅ Confirmed Gittensor contributor jaytbarimbao-collab; Gittensor profile; 108 PR(s), 4 issue(s).
Gate result ✅ Passing No configured blocker found.
Improvement ✅ Minor risk: clean · value: minor · LLM: moderate
Linked issue satisfaction

Addressed
The diff wraps the post-submission live-state fetch in a bounded, injectable retry-with-backoff (default 3 attempts, early-return on detected competitor), reuses the existing http-retry.js backoff convention, leaves adjudicateSoftClaim and the result shape untouched, and adds tests covering retry-then-succeed, immediate-detection, retry-exhaustion, and transient-failure-then-success cases.

Review context
Contributor next steps
  • Start here: Review top overlaps.
  • Then work through the remaining 3 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://gittensory.aethereal.dev/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
Contributor

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 d84b879 into JSONbored:main Jul 15, 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.

feat(miner): add retry/backoff to claim-conflict-resolver's post-submission live-state check

1 participant