Pipeline advice follows the main wallet's buyer count (what the contract pays on); card states the linked-positions rule; chatbot knows it

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
martbost
2026-09-15 12:26:02 -05:00
parent 560d758ed9
commit 8ca019a5b3
2 changed files with 8 additions and 6 deletions
+1 -1
View File
@@ -84,7 +84,7 @@ FACTS:
- ACHIEVEMENT BADGES ON TELEGRAM (2026-09-13): when a member unlocks Spark/Surge/Circuit/Nexus, their personalised badge image (username on the ribbon) is posted automatically to the team's Telegram payments topic and the main group, once per badge; members cannot trigger posts themselves (the 'Post to Telegram' button is admin-only); 'Share' opens a picker (X, Facebook, Telegram, WhatsApp, LinkedIn, Massifly (copies the post and opens the feed composer), the phone's own share menu, copy link, save image) that shares the member's public badge page instantadpay.com/b/<username>/<badge>, which shows the badge and their join link. - ACHIEVEMENT BADGES ON TELEGRAM (2026-09-13): when a member unlocks Spark/Surge/Circuit/Nexus, their personalised badge image (username on the ribbon) is posted automatically to the team's Telegram payments topic and the main group, once per badge; members cannot trigger posts themselves (the 'Post to Telegram' button is admin-only); 'Share' opens a picker (X, Facebook, Telegram, WhatsApp, LinkedIn, Massifly (copies the post and opens the feed composer), the phone's own share menu, copy link, save image) that shares the member's public badge page instantadpay.com/b/<username>/<badge>, which shows the badge and their join link.
- PROMO TOOLKIT BY BADGE + AI COPY ENGINE (2026-09-14): Promo tools > AI Copy Engine shows the ladder: Free (links, posts, swipes, banners, wall, objections, shorts, badge pages), Spark (payouts on: one-tap campaign templates aimed at the member's link, printable handout with their QR at /handout/<username>), Surge (first qualifying buyer; the AI Copy Engine is live: posts, DMs, follow-ups, objection replies, emails, story posts, team broadcasts in the member's name with their link, honesty rules built in; 20 free generations a month), Circuit (60 free; Video Maker renders every promo video and short with the member's own end card and QR, hosted for download; split tester compares join angles by views, joins, buyers), Nexus (150 free; Leader Ops: three-level team triage with stalled flags and one-click nudges, AI-drafted team broadcasts, credit grants from the leader's earned pool to anyone in their line, co-branded join page showing the sponsor's bio, and the member's own partner code: welcome credits funded from the leader's pool at each redemption, plus a partner kit page /partners?ref=<username>&promo=CODE). After the free allowance each generation costs 10 ad credits from the earned pool. Credits are advertising, never money. - PROMO TOOLKIT BY BADGE + AI COPY ENGINE (2026-09-14): Promo tools > AI Copy Engine shows the ladder: Free (links, posts, swipes, banners, wall, objections, shorts, badge pages), Spark (payouts on: one-tap campaign templates aimed at the member's link, printable handout with their QR at /handout/<username>), Surge (first qualifying buyer; the AI Copy Engine is live: posts, DMs, follow-ups, objection replies, emails, story posts, team broadcasts in the member's name with their link, honesty rules built in; 20 free generations a month), Circuit (60 free; Video Maker renders every promo video and short with the member's own end card and QR, hosted for download; split tester compares join angles by views, joins, buyers), Nexus (150 free; Leader Ops: three-level team triage with stalled flags and one-click nudges, AI-drafted team broadcasts, credit grants from the leader's earned pool to anyone in their line, co-branded join page showing the sponsor's bio, and the member's own partner code: welcome credits funded from the leader's pool at each redemption, plus a partner kit page /partners?ref=<username>&promo=CODE). After the free allowance each generation costs 10 ad credits from the earned pool. Credits are advertising, never money.
- MEMBER UPDATE EMAILS (2026-09-14, admin only): Admin > Releases > Email an update to members: pick release notes, add an intro, choose an audience (newsletter opt-ins, opt-ins active in the last 30 days, or everyone including those who declined), preview, send a test to the admin, then send; plain text from no-reply@instantadpay.com with an opt-out link; the log shows sent/opted out/failed. - MEMBER UPDATE EMAILS (2026-09-14, admin only): Admin > Releases > Email an update to members: pick release notes, add an intro, choose an audience (newsletter opt-ins, opt-ins active in the last 30 days, or everyone including those who declined), preview, send a test to the admin, then send; plain text from no-reply@instantadpay.com with an opt-out link; the log shows sent/opted out/failed.
- LINKED POSITIONS AND BADGES (2026-09-14): qualifying buyers on a member's linked positions count toward their achievement badges (Spark/Surge/Circuit/Nexus) and light their chip on their sponsor's line, and a badge once earned never regresses. The contract still pays levels 2 and 3 to each position based on that position's OWN qualifying buyers, so the Qualifying buyers tile shows the main position's count with the linked positions' count underneath. - LINKED POSITIONS AND BADGES (2026-09-14): qualifying buyers on a member's linked positions count toward their achievement badges (Spark/Surge/Circuit/Nexus) and light their chip on their sponsor's line, and a badge once earned never regresses. CONTRACT RULE: levels 2 and 3 are paid to the MAIN wallet only when that wallet's own count of qualifying buyers reaches 2 and 5; buyers registered under a linked position count for that position, not the main wallet. Qualified Start positions buy UNDER the main wallet, so those buys raise the main count; a member whose old wallet was swapped out (its buyers stay with the old position) needs new $20+ buyers under the current main wallet before level 2 pays it. The contract still pays levels 2 and 3 to each position based on that position's OWN qualifying buyers, so the Qualifying buyers tile shows the main position's count with the linked positions' count underneath.
- PIPELINE (coming soon, built 2026-09-15; opens when the site setting pipelineMode is on): a follow-up board on the dashboard, tab 'Pipeline' between My line and Buy packages. Columns: Talking to, Joined, Wallet linked, Payouts on, Bought, Building, Later. Prospects (from the My line prospect list) and directs are placed automatically from what they have actually done (coaching rung, on-chain buys); nobody drags cards. The sponsor adds a note, a follow-up date and a tag (hot, later, no response, not interested); a 'Follow up today' strip lists due cards; stalled cards (quiet 3+ days) are flagged; each card carries the message for its exact stage with 'Open chat with this message' (member chat) or copy. Until it opens, the tab shows a coming-soon card with the roadmap date. - PIPELINE (coming soon, built 2026-09-15; opens when the site setting pipelineMode is on): a follow-up board on the dashboard, tab 'Pipeline' between My line and Buy packages. Columns: Talking to, Joined, Wallet linked, Payouts on, Bought, Building, Later. Prospects (from the My line prospect list) and directs are placed automatically from what they have actually done (coaching rung, on-chain buys); nobody drags cards. The sponsor adds a note, a follow-up date and a tag (hot, later, no response, not interested); a 'Follow up today' strip lists due cards; stalled cards (quiet 3+ days) are flagged; each card carries the message for its exact stage with 'Open chat with this message' (member chat) or copy. Until it opens, the tab shows a coming-soon card with the roadmap date.
- PAYMENT + MISSED-PAYMENT NOTICES (2026-09-15): every payout that lands (who bought, level, share in POL and dollars, transaction link) and every missed payout is delivered BOTH by email and as an on-site inbox message from the company account, shown in the login pop-up and the Messages card, so it is waiting when the member signs in. MISSED-PAYOUT detail: when a level-2 or level-3 share passes a member by because that level is not open on their account, the member gets an email the same minute: who bought, the POL and dollar amount they missed, how many qualifying buyers they have versus the 2 or 5 needed, and the two ways to close the gap (bring buyers, or Qualified Start). Qualified members whose wallet rejected a transfer get a different email telling them to link a regular wallet. - PAYMENT + MISSED-PAYMENT NOTICES (2026-09-15): every payout that lands (who bought, level, share in POL and dollars, transaction link) and every missed payout is delivered BOTH by email and as an on-site inbox message from the company account, shown in the login pop-up and the Messages card, so it is waiting when the member signs in. MISSED-PAYOUT detail: when a level-2 or level-3 share passes a member by because that level is not open on their account, the member gets an email the same minute: who bought, the POL and dollar amount they missed, how many qualifying buyers they have versus the 2 or 5 needed, and the two ways to close the gap (bring buyers, or Qualified Start). Qualified members whose wallet rejected a transfer get a different email telling them to link a regular wallet.
- LAUNCH WEEK SWIPES (2026-09-15): the founding-week checklist page (/launch) ends with four promoter emails members send to their OWN lists, one a day toward Monday's opening, with the member's invite link and the FOUNDER code (500 credits for anyone who joins before Mon 2026-09-21 9 AM Central) filled in, each with a Copy button. These are swipes for members, not emails the site sends. - LAUNCH WEEK SWIPES (2026-09-15): the founding-week checklist page (/launch) ends with four promoter emails members send to their OWN lists, one a day toward Monday's opening, with the member's invite link and the FOUNDER code (500 credits for anyone who joins before Mon 2026-09-21 9 AM Central) filled in, each with a Copy button. These are swipes for members, not emails the site sends.
+7 -5
View File
@@ -10,8 +10,9 @@ const path = require('path');
const db = require('./db'); const db = require('./db');
let DATA_DIR = null, accounts = null, coach = null, chain = null; let DATA_DIR = null, accounts = null, coach = null, chain = null;
// linked positions (Qualified Start) belong to the member: their buyers count toward the account, the same way // linked positions (Qualified Start) belong to the member and their buyers count toward badges, but the contract
// My line chips and the badges count them (Jim's card showed 1 buyer while his badge said Circuit, 2026-09-15) // pays level 2 and 3 to the MAIN wallet only when that wallet's own buyerCount reaches 2 and 5. The card shows both
// numbers; the stage and the advice follow the main wallet, because that is what gets paid (Marty's audit, 2026-09-15)
const posCache = new Map(); const posCache = new Map();
async function positionBuyers(email) { async function positionBuyers(email) {
let ids = []; try { ids = (await accounts.positions(email)).map(p => p.memberId).filter(Boolean); } catch (e) {} let ids = []; try { ids = (await accounts.positions(email)).map(p => p.memberId).filter(Boolean); } catch (e) {}
@@ -23,7 +24,6 @@ async function positionBuyers(email) {
} }
return { count: n, positions: ids.length }; return { count: n, positions: ids.length };
} }
function rungForTotal(rung, total) { if (rung < 3) return rung; return total === 0 ? 3 : total === 1 ? 4 : total < 5 ? 5 : 6; }
const DAY = 86400000; const DAY = 86400000;
// columns, in order. Prospects live in the first and last; directs land by coaching rung. // columns, in order. Prospects live in the first and last; directs land by coaching rung.
@@ -95,14 +95,16 @@ async function board(email) {
const n = notes[m.email] || {}; const n = notes[m.email] || {};
const pb = c && c.rung >= 3 ? await positionBuyers(m.email) : { count: 0, positions: 0 }; const pb = c && c.rung >= 3 ? await positionBuyers(m.email) : { count: 0, positions: 0 };
const buyersMain = c ? c.buyerCount || 0 : 0, buyersAll = buyersMain + pb.count; const buyersMain = c ? c.buyerCount || 0 : 0, buyersAll = buyersMain + pb.count;
const rung = c ? rungForTotal(c.rung, buyersAll) : 0; const rung = c ? c.rung : 0;
const RR = coach.RUNGS[rung]; const RR = coach.RUNGS[rung];
// when positions carry buyers the main wallet does not, say exactly what the contract needs
const gap = pb.count && rung >= 3 && rung < 6 ? ' The contract pays level ' + (buyersMain < 2 ? '2' : '3') + ' to their main wallet only when that wallet has ' + (buyersMain < 2 ? 2 : 5) + ' qualifying buyers of its own: ' + buyersMain + ' now, plus ' + pb.count + ' on linked positions that count for badges only.' : '';
const stage = PARKED.has(n.tag) && rung < 3 ? 'later' : RUNG_STAGE[rung] || 'joined'; const stage = PARKED.has(n.tag) && rung < 3 ? 'later' : RUNG_STAGE[rung] || 'joined';
cards.push({ key: m.email, kind: 'member', email: m.email, name: m.username ? '@' + m.username : (m.memberId ? 'member #' + m.memberId : 'member'), cards.push({ key: m.email, kind: 'member', email: m.email, name: m.username ? '@' + m.username : (m.memberId ? 'member #' + m.memberId : 'member'),
memberId: m.memberId || 0, stage, rung, rungLabel: RR.label, since: m.created || now, memberId: m.memberId || 0, stage, rung, rungLabel: RR.label, since: m.created || now,
lastSeen: m.lastSeen || 0, quietDays: c ? c.quietDays : 0, stalled: !!(c && c.stalled && rung < 6), lastSeen: m.lastSeen || 0, quietDays: c ? c.quietDays : 0, stalled: !!(c && c.stalled && rung < 6),
buyers: buyersAll, buyersMain, buyersPositions: pb.count, positions: pb.positions, bought: !!(c && c.counted), buyers: buyersAll, buyersMain, buyersPositions: pb.count, positions: pb.positions, bought: !!(c && c.counted),
next: RR.next, say: RR.say.replace('{{name}}', m.username || 'there'), next: RR.next + gap, say: RR.say.replace('{{name}}', m.username || 'there'),
note: n.note || '', followUp: n.followUp || null, tag: n.tag || '' }); note: n.note || '', followUp: n.followUp || null, tag: n.tag || '' });
} }
const due = cards.filter(c => c.followUp && c.followUp <= eod.getTime()).sort((a, b) => a.followUp - b.followUp); const due = cards.filter(c => c.followUp && c.followUp <= eod.getTime()).sort((a, b) => a.followUp - b.followUp);