feat(miner-discovery): pure opportunity-ranker in packages/gittensory-engine (#2302) - #2378
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. 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:
|
|
Warning 🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨 ⏸️ Gittensory review result - manual review recommendedReview updated: 2026-07-02 04:27:49 UTC
⏸️ Suggested Action - Manual Review Review summary Nits — 5 non-blocking
Review context
Contributor next steps
Signal definitions
🟩 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.
|
fe6d27f to
9cfbc9b
Compare
…-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.
9cfbc9b to
19bb98f
Compare
…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.
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 latergittensory_find_opportunitiestool has something deterministic to sort by. No IO, noDate, no random — following thesrc/signals/duplicate-winner.tsPURE-module convention.Deliverables (per the issue)
packages/gittensory-engine/lib/opportunity-ranker.tsOpportunityRankInput— the five0-1signals (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 toward0instead of inverting the sign or overflowing the product.rankOpportunities(candidates)— stable descending sort by score, annotating each withrankScore; equal scores keep input order (mirrors the tie-break intent ofisDuplicateClusterWinnerByClaim,src/signals/duplicate-winner.ts:43). Returns a new array; input is not mutated.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 ownnode:testsuite compiles todist-test/and runs in isolation (thevalidate-codejob skips the package). As a member of the rootpackages/*workspaces glob it is registered in the rootpackage-lock.json; broader CI build wiring remains deferred to #2297.Validation
npm testinpackages/gittensory-engine(tsc build +node --test):Covered: max inputs → 1; product composition; each of the five factors at 0 collapses to 0;
dupRiskof exactly 1 zeroes; out-of-range (negative/>1) clamped not passed through; non-finite (NaN/Infinity) degrades to 0; descending sort withrankScore; stable tie-break; input not mutated; empty list → empty list.tscis clean understrict+noUncheckedIndexedAccess+exactOptionalPropertyTypes.