Skip to content

feat(miner-discovery): pure opportunity-ranker in packages/gittensory-engine (#2302) - #2378

Merged
JSONbored merged 4 commits into
JSONbored:mainfrom
nickmopen:feat/opportunity-ranker
Jul 2, 2026
Merged

feat(miner-discovery): pure opportunity-ranker in packages/gittensory-engine (#2302)#2378
JSONbored merged 4 commits into
JSONbored:mainfrom
nickmopen:feat/opportunity-ranker

Conversation

@nickmopen

@nickmopen nickmopen commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Closes #2302.

Implements the core Phase-1 miner-discovery ranker: a pure, deterministic function that composes five already-normalized [0,1] signals into one ordinal opportunity score, so a later gittensory_find_opportunities tool has something deterministic to sort by. No IO, no Date, no random — following the src/signals/duplicate-winner.ts PURE-module convention.

Deliverables (per the issue)

  • packages/gittensory-engine/lib/opportunity-ranker.ts
    • OpportunityRankInput — the five 0-1 signals (potential, feasibility, laneFit, freshness, dupRisk).
    • rankOpportunityScore(input) = potential * feasibility * laneFit * freshness * (1 - dupRisk), clamping every field to [0,1] first so a malformed upstream signal (negative, >1, NaN, ±Infinity) degrades toward 0 instead of inverting the sign or overflowing the product.
    • rankOpportunities(candidates)stable descending sort by score, annotating each with rankScore; equal scores keep input order (mirrors the tie-break intent of isDuplicateClusterWinnerByClaim, src/signals/duplicate-winner.ts:43). Returns a new array; input is not mutated.
    • Doc-comment carries the signal-source map (feasibility ← issue-quality.ts; laneFit ← MinerGoalSpec.preferredLanes; freshness/dupRisk ← reward-risk.ts + duplicate-winner.ts).

Packaging

Builds on the now-merged #2357 scaffold: adds the ranker under the package's src/ layout and exports it from the barrel. Its own node:test suite compiles to dist-test/ and runs in isolation (the validate-code job skips the package). As a member of the root packages/* workspaces glob it is registered in the root package-lock.json; broader CI build wiring remains deferred to #2297.

Validation

npm test in packages/gittensory-engine (tsc build + node --test):

ℹ tests 10
ℹ pass 10
ℹ fail 0

Covered: max inputs → 1; product composition; each of the five factors at 0 collapses to 0; dupRisk of exactly 1 zeroes; out-of-range (negative/>1) clamped not passed through; non-finite (NaN/Infinity) degrades to 0; descending sort with rankScore; stable tie-break; input not mutated; empty list → empty list. tsc is clean under strict + noUncheckedIndexedAccess + exactOptionalPropertyTypes.

@codecov

codecov Bot commented Jul 1, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 95.80%. Comparing base (d4957ed) to head (02b784f).
⚠️ Report is 48 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #2378   +/-   ##
=======================================
  Coverage   95.80%   95.80%           
=======================================
  Files         224      224           
  Lines       24970    24970           
  Branches     9075     9075           
=======================================
  Hits        23922    23922           
  Misses        428      428           
  Partials      620      620           
🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@loopover-orb

loopover-orb Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Warning

🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨

⏸️ Gittensory review result - manual review recommended

Review updated: 2026-07-02 04:27:49 UTC

8 files · 1 AI reviewer · no blockers · readiness 55/100 · CI green · clean

⏸️ Suggested Action - Manual Review

Review summary
The change adds a pure deterministic opportunity scorer plus a stable ordered-list helper, exports it through the package barrel, and covers the formula, clamping behavior, tie handling, and non-mutation contract. The implementation matches the documented product formula and the package test setup exercises the built public entrypoint. No must-fix correctness defects are visible in the provided diff.

Nits — 5 non-blocking
  • nit: packages/gittensory-engine/src/opportunity-ranker.ts:1 carries a long issue-specific header that mostly duplicates the README/API comments; keeping the source comment shorter would make the exported behavior easier to scan.
  • nit: packages/gittensory-engine/test/opportunity-ranker.test.ts:99 uses JSON serialization for the immutability snapshot, which is fine for this fixture but would silently hide non-JSON fields if the sample grows.
  • packages/gittensory-engine/src/opportunity-ranker.ts:24 could export or rename the clamp helpers only if future engine modules need the exact same normalization semantics; otherwise keeping them private is the right boundary.
  • packages/gittensory-engine/test/opportunity-ranker.test.ts:91 add a distinct assertion that the returned element is a new object reference, since the contract says elements are not mutated and the current deep-equality snapshot only proves the source shape stayed unchanged.
  • Readiness score is below the configured threshold — Use the readiness panel as advisory maintainer context; the score does not block this PR.
Signal Result Evidence
Code review ✅ No blockers 1 reviewer
Linked issue ✅ Linked #2302
Related work ⚠️ 3 scoped overlaps Top overlaps are listed below; lower-confidence bulk is hidden.
Change scope ❌ 8/20 High review scope from cached public metadata (size label size:L; 1 linked issue).
Validation posture ❌ 5/25 Preflight is holding this PR: the review lane is unavailable, so it is not ready for automated review.
Contributor workload ✅ 10/10 Author activity: 97 registered-repo PR(s), 64 merged, 1 issue(s).
Contributor context ✅ Confirmed Gittensor contributor nickmopen; Gittensor profile; 97 PR(s), 1 issue(s).
Gate result ✅ Passing No configured blocker found.
Review context
Contributor next steps
  • Review top overlaps.
  • Add a concise scope and risk note.
  • Await review-lane availability.
  • Triage stale or unlinked PRs.
  • Refresh registry data or choose a registered active repo.
  • Check active issues and PRs before submitting.
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.

🟩 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 Gittensory, a quiet PR intelligence layer for OSS maintainers.

  • Re-run Gittensory review

…-engine (JSONbored#2302)

Adds the core Phase-1 miner-discovery ranker on top of the merged JSONbored#2357 scaffold:
a PURE, deterministic function composing five already-normalized [0,1] signals
into one ordinal opportunity score, so a later gittensory_find_opportunities tool
has something deterministic to sort by. No IO, no Date, no random — following the
src/signals/duplicate-winner.ts convention.

- src/opportunity-ranker.ts:
  - rankOpportunityScore(input) = potential * feasibility * laneFit * freshness *
    (1 - dupRisk), with every field clamped to [0,1] first. Positive factors clamp
    a non-finite value to 0; dupRisk FAILS CLOSED (non-finite → 1 → max risk), so a
    broken contention signal collapses the score instead of masking it as safe.
  - rankOpportunities(candidates): descending sort annotating each with rankScore,
    with an explicit index tie-break so equal scores keep input order by contract.
- src/index.ts: export the ranker from the previously-empty barrel.
- test/ + tsconfig.test.json: node:test suite compiled to dist-test/ (no
  experimental flags, so it runs across the whole engines range). Adds @types/node
  and typescript devDeps; registers them in the root lockfile.

npm test: 11/11 pass.
…ONbored#2302)

Import through ../dist/index.js instead of the impl file so the package's
export contract is covered, and add a barrel smoke test asserting the named
exports are present.
…ed#2302)

clampRisk previously failed closed only on non-finite dupRisk; a negative
value clamped to 0 (no penalty), letting a malformed contention signal
masquerade as a safe opportunity. Now ANY dupRisk outside [0,1] — non-finite,
negative, or above 1 — fails closed to max risk (1), so (1 - risk) = 0 and the
score collapses. Makes the fail-closed contract uniform in both directions.

- clampRisk: return 1 for anything not in [0,1]; pass through in-range values.
- Tests: negative dupRisk now asserts a 0 score (folded into the out-of-range
  fail-closed table).
- README + doc-comment: document below-range fail-closed handling.
- Drop the drift-prone "~lines 88-93" reward-risk.ts line reference.

npm test: 12/12 pass.
…non-finite (JSONbored#2302)

Aligns dupRisk with the documented "every field clamped to [0,1]" contract:
a FINITE out-of-range dupRisk is now clamped like the other fields (-0.1 -> 0
= no contention, 1.4 -> 1 = full contention) instead of failing closed. Only a
NON-finite dupRisk (NaN/±Infinity), which genuinely can't be clamped, fails
closed to max risk (1) — keeping the original guarantee that a broken signal
never masquerades as a safe opportunity. Docs (module header, clampRisk,
formula) now match this exactly.

Also type rankOpportunities' result as Omit<T, "rankScore"> & ... & { rankScore }
so the computed annotation cleanly replaces any rankScore a caller already
carries, instead of producing an awkward intersection.

npm test: 12/12 pass.
@dosubot dosubot Bot added the lgtm label Jul 2, 2026
@JSONbored
JSONbored merged commit d166678 into JSONbored:main Jul 2, 2026
10 checks passed
@github-project-automation github-project-automation Bot moved this from Todo to Done in gittensory - v1 roadmap Jul 2, 2026
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

No open projects
Status: Done

Development

Successfully merging this pull request may close these issues.

feat(miner-discovery): pure ranker function — potential x feasibility x laneFit x freshness x (1-dupRisk)

2 participants