Rotation queue: reconcile against live chain directs in normalizeStatuses - never activate a sponsor the chain says is already 2/2 qualified (also syncs stale direct counts upward)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -667,6 +667,13 @@ function getOrgShare(rootId) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Live direct count from the index (null when unknown) — used by the rotation
|
||||||
|
// queue to reconcile against chain reality before activating a sponsor.
|
||||||
|
function liveDirects(id) {
|
||||||
|
if (!state || !state.members[id]) return null;
|
||||||
|
return state.members[id].directCount || 0;
|
||||||
|
}
|
||||||
|
|
||||||
// Wallet address -> position id (for wallet-verified messaging sign-in).
|
// Wallet address -> position id (for wallet-verified messaging sign-in).
|
||||||
// One position per address by contract design.
|
// One position per address by contract design.
|
||||||
function memberIdByAccount(address) {
|
function memberIdByAccount(address) {
|
||||||
@@ -744,4 +751,4 @@ async function getIncome(id) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = { startIndexer, getPayoutsPublic, verifyMember, memberLookup, memberPublic, getIncome, getOwnerUpgradeNeeds, getOrgRouting, getOrgShare, getCoachingScan, getMatrixTree, isInTeam, nextOpenPosition, memberIdByAccount, balanceOf, CONTRACT };
|
module.exports = { startIndexer, getPayoutsPublic, verifyMember, memberLookup, memberPublic, getIncome, getOwnerUpgradeNeeds, getOrgRouting, getOrgShare, getCoachingScan, getMatrixTree, isInTeam, nextOpenPosition, memberIdByAccount, liveDirects, balanceOf, CONTRACT };
|
||||||
|
|||||||
@@ -316,6 +316,17 @@ function recordEvent(event, source) {
|
|||||||
writeJson(ANALYTICS_FILE, a);
|
writeJson(ANALYTICS_FILE, a);
|
||||||
}
|
}
|
||||||
function normalizeStatuses(sponsors, preferredActiveId=null) {
|
function normalizeStatuses(sponsors, preferredActiveId=null) {
|
||||||
|
// Chain reconciliation: queue members can qualify through leg activity long
|
||||||
|
// BEFORE their rotation turn, and the event-driven auto-counter never sees
|
||||||
|
// it (bit us twice on 2026-08-19: #41, then #46 activated while already
|
||||||
|
// 2/2 on-chain). Never activate someone the chain says is qualified.
|
||||||
|
sponsors=sponsors.map(s=>{
|
||||||
|
if(s.status==='qualified')return s;
|
||||||
|
const dc=chain.liveDirects(Number(s.id));
|
||||||
|
if(dc!=null&&dc>=2)return {...s,directs:2,status:'qualified'};
|
||||||
|
if(dc!=null&&dc>(Number(s.directs)||0))return {...s,directs:dc};
|
||||||
|
return s;
|
||||||
|
});
|
||||||
const eligible=sponsors.filter(s=>s.status!=='qualified');
|
const eligible=sponsors.filter(s=>s.status!=='qualified');
|
||||||
let activeId=preferredActiveId;
|
let activeId=preferredActiveId;
|
||||||
if(!activeId || !eligible.some(s=>s.id===activeId)){
|
if(!activeId || !eligible.some(s=>s.id===activeId)){
|
||||||
|
|||||||
Reference in New Issue
Block a user