Skip to content

fix(engine): inject nowMs for deterministic PR staleness classification - #8973

Merged
loopover-orb[bot] merged 1 commit into
JSONbored:mainfrom
jeffrey701:fix-8872-classify-pr-staleness-nowms-v2
Jul 26, 2026
Merged

fix(engine): inject nowMs for deterministic PR staleness classification#8973
loopover-orb[bot] merged 1 commit into
JSONbored:mainfrom
jeffrey701:fix-8872-classify-pr-staleness-nowms-v2

Conversation

@jeffrey701

Copy link
Copy Markdown
Contributor

What

pending-pr-scenarios.ts's daysSince called Date.now() directly, so
classifyOpenPullRequest's 14-day staleness split (merge_ready vs stale_likely_close) was
non-deterministic — identical PR records classified differently purely based on when the function
ran, and the boundary was untestable without live time. The file's own header claims "pure
classification/detection logic," and its sibling modules (opportunity-freshness.ts /
opportunity-metadata.ts) already inject nowMs "so the miner engine stays pure and testable."

Change

Add an optional nowMs to daysSince (defaulting to Date.now() only at that call boundary) and
thread it through classifyOpenPullRequest's args. When a caller omits it, behavior is unchanged
(the default fires); a caller can now inject a fixed clock for deterministic classification.

Validation

  • New frozen-time test in test/unit/pending-pr-scenarios.test.ts (imports the engine source, so
    Codecov grades it): with an injected nowMs, an approved/passing PR at exactly 14 days old
    classifies stale_likely_close, and one millisecond short of 14 days classifies merge_ready
    pinning the exact boundary.
  • npx vitest run test/unit/pending-pr-scenarios.test.ts → 19/19 pass; 100% line+branch coverage on
    every changed line (both sides of the nowMs = Date.now() default).

Closes #8872

@jeffrey701
jeffrey701 requested a review from JSONbored as a code owner July 26, 2026 14:41
@superagent-security

Copy link
Copy Markdown
Contributor

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

@codecov

codecov Bot commented Jul 26, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 93.86%. Comparing base (bda83ca) to head (ec4b871).
⚠️ Report is 7 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #8973      +/-   ##
==========================================
- Coverage   93.87%   93.86%   -0.01%     
==========================================
  Files         807      807              
  Lines       80356    80357       +1     
  Branches    24354    24354              
==========================================
- Hits        75434    75431       -3     
  Misses       3561     3561              
- Partials     1361     1365       +4     
Flag Coverage Δ
backend 95.15% <100.00%> (-0.01%) ⬇️

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

Files with missing lines Coverage Δ
...oopover-engine/src/scoring/pending-pr-scenarios.ts 100.00% <100.00%> (ø)

... and 1 file with indirect coverage changes

@loopover-orb loopover-orb Bot added the gittensor:bug Gittensor-scored bug fix — scores a 0.05x multiplier. label Jul 26, 2026
@loopover-orb

loopover-orb Bot commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

Tip

✅ LoopOver review result - approve/merge recommended

Review updated: 2026-07-26 15:06:57 UTC

2 files · 1 AI reviewer · no blockers · readiness 93/100 · CI green · clean

✅ Suggested Action - Approve/Merge

  • safe to merge

Review summary
This PR threads an optional `nowMs` through `daysSince`/`classifyOpenPullRequest`, defaulting to `Date.now()` only at the call boundary, which is a clean and minimally invasive way to make staleness classification deterministic and testable without changing any behavior for existing callers. The new test pins the exact 14-day boundary with a frozen `nowMs`, and detectPendingPrScenario callers that don't pass `nowMs` are unaffected since the parameter is optional. The `86_400_000` literal flagged in the brief is pre-existing (already present on the line being modified, not introduced by this diff), so that's a non-issue.

Nits — 3 non-blocking
  • `daysSince`'s `nowMs = Date.now()` default and the `86_400_000` day-in-ms literal predate this diff (only the injection is new); consider a named `MS_PER_DAY` constant while touching this line, though it's pre-existing style.
  • `detectPendingPrScenario` (pending-pr-scenarios.ts) doesn't thread `nowMs` through to its internal `classifyOpenPullRequest` calls, so only direct callers of `classifyOpenPullRequest` get deterministic behavior — worth confirming that's intentional given the PR's stated goal of full determinism for the module.
  • If full pure/deterministic coverage of the module is the goal (per the file's own header comment), thread `nowMs` through `detectPendingPrScenario`'s args as well so both entry points support frozen-clock testing.

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 #8872
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: 80 registered-repo PR(s), 36 merged, 18 issue(s).
Contributor context ✅ Confirmed Gittensor contributor jeffrey701; Gittensor profile; 80 PR(s), 18 issue(s).
Improvement ✅ Minor risk: clean · value: minor · LLM: minor
Linked issue satisfaction

Addressed
The diff adds an optional nowMs parameter to daysSince and threads it through classifyOpenPullRequest, defaulting to Date.now() only at the call boundary as requested, and includes a new frozen-time test pinning the exact 14-day merge_ready/stale_likely_close boundary using an injected nowMs.

Review context
  • Author: jeffrey701
  • Role context: outside_contributor
  • Public audience mode: oss maintainer
  • Lane context: Repository is configured for direct PR review.
  • Public profile languages: Rust, TypeScript, Clojure, JavaScript
  • Official Gittensor activity: 80 PR(s), 18 issue(s).
  • PR-specific overlap: none found.
Contributor next steps
  • Start here: Triage stale or unlinked PRs.
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://loopover.ai/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 904aeb9 into JSONbored:main Jul 26, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gittensor:bug Gittensor-scored bug fix — scores a 0.05x multiplier.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(engine): classifyOpenPullRequest's staleness check reads the wall clock, breaking the module's own "pure/deterministic" contract

1 participant