50c 3.7.0 → 3.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bin/50c.js CHANGED
@@ -126,6 +126,14 @@ const TOOL_COMMANDS = {
126
126
  'invent': { tool: 'auto_invent', special: 'invent', cost: '$2.00' },
127
127
  'invent-ui': { tool: 'auto_invent', special: 'invent-ui', cost: '$2.00' },
128
128
  'tv': { tool: null, special: 'mcp-tv', cost: 'FREE' },
129
+ 'adopt': { tool: 'adoption_calc', special: 'adopt', cost: 'FREE' },
130
+ 'adopt-dx': { tool: 'adoption_diagnose', special: 'adopt-dx', cost: 'FREE' },
131
+ 'adopt-sim': { tool: 'adoption_simulate', special: 'adopt-sim', cost: 'FREE' },
132
+ 'team': { tool: null, special: 'team', cost: 'FREE' },
133
+ 'team-create': { tool: null, special: 'team-create', cost: 'FREE' },
134
+ 'team-mint': { tool: null, special: 'team-mint', cost: 'FREE' },
135
+ 'team-recall': { tool: null, special: 'team-recall', cost: 'FREE' },
136
+ 'team-analytics': { tool: null, special: 'team-analytics', cost: 'FREE' },
129
137
  };
130
138
 
131
139
  // Route command
@@ -249,6 +257,9 @@ function searchPacks(query) {
249
257
  { pack: 'beacon', tool: 'checkpoint', desc: 'Save state', cost: '$0.02' },
250
258
  { pack: 'router', tool: 'compare', desc: 'Multi-model compare', cost: '$0.05' },
251
259
  { pack: 'router', tool: 'battle', desc: 'Model battle', cost: '$0.10' },
260
+ { pack: 'adoption', tool: 'adoption_calc', desc: 'P(adopt) calculator', cost: 'FREE' },
261
+ { pack: 'adoption', tool: 'adoption_diagnose', desc: 'Bottleneck diagnosis', cost: 'FREE' },
262
+ { pack: 'adoption', tool: 'adoption_simulate', desc: 'Time-series ODE sim', cost: 'FREE' },
252
263
  ];
253
264
 
254
265
  return all.filter(t =>
@@ -266,7 +277,7 @@ async function cmdAdd(args) {
266
277
  process.exit(1);
267
278
  }
268
279
 
269
- const valid = ['core', 'labs', 'beacon', 'router'];
280
+ const valid = ['core', 'labs', 'beacon', 'router', 'adoption'];
270
281
  if (!valid.includes(pack)) {
271
282
  console.error(`Unknown pack: ${pack}`);
272
283
  console.error('Available: ' + valid.join(', '));
@@ -658,6 +669,188 @@ async function runToolCommand(cmd, args) {
658
669
  return;
659
670
  }
660
671
 
672
+ // ADOPTION EQUATION TOOLS (FREE, local compute)
673
+ if (spec.special === 'adopt') {
674
+ // 50c adopt 2.0 0.3 0.8 [churn] [lambda]
675
+ const R = parseFloat(args[0]);
676
+ const N = parseFloat(args[1]);
677
+ const W = parseFloat(args[2]);
678
+ const churn = parseFloat(args[3]) || 0;
679
+ const lambda = parseFloat(args[4]) || 1.0;
680
+
681
+ if (isNaN(R) || isNaN(N) || isNaN(W)) {
682
+ console.error('Usage: 50c adopt <reward> <network> <window> [churn] [lambda]');
683
+ console.error('Example: 50c adopt 2.0 0.3 0.8');
684
+ process.exit(1);
685
+ }
686
+
687
+ const result = adoptionCalc({ reward: R, network: N, window: W, churn, lambda });
688
+ console.log('\n=== ADOPTION PROBABILITY ===');
689
+ console.log(`P(adopt) = ${(result.probability * 100).toFixed(2)}%`);
690
+ console.log(`Equation: ${result.equation}`);
691
+ console.log(`\nTerms:`);
692
+ console.log(` Reward: ${(result.reward_term * 100).toFixed(1)}%`);
693
+ console.log(` Network: ${(result.network_effect * 100).toFixed(1)}%`);
694
+ console.log(` Window: ${(result.upheaval_window * 100).toFixed(1)}%`);
695
+ console.log(`\nDiagnosis: ${result.diagnosis}`);
696
+ console.log(`Bottleneck: ${result.bottleneck} (${(result.bottleneck_value * 100).toFixed(1)}%)`);
697
+ if (result.threshold_R_for_50pct !== 'impossible') {
698
+ console.log(`R needed for 50%: ${result.threshold_R_for_50pct}`);
699
+ }
700
+ console.log(`Past bifurcation (viral threshold): ${result.past_bifurcation ? 'YES' : 'NO'}`);
701
+ return;
702
+ }
703
+
704
+ if (spec.special === 'adopt-dx') {
705
+ // 50c adopt-dx 2.0 0.3 0.8
706
+ const R = parseFloat(args[0]);
707
+ const N = parseFloat(args[1]);
708
+ const W = parseFloat(args[2]);
709
+
710
+ if (isNaN(R) || isNaN(N) || isNaN(W)) {
711
+ console.error('Usage: 50c adopt-dx <reward> <network> <window>');
712
+ process.exit(1);
713
+ }
714
+
715
+ const result = adoptionDiagnose({ reward: R, network: N, window: W });
716
+ console.log('\n=== ADOPTION DIAGNOSIS ===');
717
+ console.log(`P(adopt) = ${(result.probability * 100).toFixed(2)}%`);
718
+ console.log(`\nDiagnosis: ${result.diagnosis.toUpperCase()}`);
719
+ console.log(`Priority: ${result.prescription.priority}`);
720
+ console.log(`\nProblem: ${result.prescription.problem}`);
721
+ console.log(`Fix: ${result.prescription.fix}`);
722
+ if (result.kill_switches.length > 0) {
723
+ console.log('\n⚠️ KILL SWITCHES:');
724
+ result.kill_switches.forEach(k => console.log(` ${k}`));
725
+ }
726
+ console.log(`\nInsight: ${result.insight}`);
727
+ return;
728
+ }
729
+
730
+ if (spec.special === 'adopt-sim') {
731
+ // 50c adopt-sim 2.0 [steps]
732
+ const R = parseFloat(args[0]) || 2.0;
733
+ const steps = parseInt(args[1]) || 100;
734
+
735
+ const result = adoptionSimulate({ reward: R, steps });
736
+ console.log('\n=== ADOPTION SIMULATION ===');
737
+ console.log(`Initial: R=${R}, N0=0.1, W0=0.9, alpha=1.5, churn=0.05`);
738
+ console.log(`\nTrajectory:`);
739
+ result.series.forEach(p => {
740
+ const bar = '█'.repeat(Math.round(p.P * 40));
741
+ console.log(`t=${p.t.toFixed(1).padStart(4)}: ${(p.P * 100).toFixed(1).padStart(5)}% ${bar}`);
742
+ });
743
+ console.log(`\nFinal P: ${(result.summary.final_adoption * 100).toFixed(2)}%`);
744
+ console.log(`Peak P: ${(result.summary.peak_adoption * 100).toFixed(2)}% at t=${result.summary.peak_time}`);
745
+ console.log(`Tipped viral: ${result.summary.tipped_at !== 'never' ? 'YES at t=' + result.summary.tipped_at : 'NO'}`);
746
+ console.log(`Trajectory: ${result.summary.trajectory}`);
747
+ return;
748
+ }
749
+
750
+ // TEAM COMMANDS (FREE, uses API)
751
+ if (spec.special === 'team') {
752
+ const res = await fetch('https://api.50c.ai/v1/team/info', {
753
+ method: 'POST',
754
+ headers: { 'Authorization': `Bearer ${API_KEY}`, 'Content-Type': 'application/json' },
755
+ body: '{}'
756
+ });
757
+ const data = await res.json();
758
+ if (data.error === 'Not in a team') {
759
+ console.log('\n=== NO TEAM ===');
760
+ console.log('You are not in a team yet.');
761
+ console.log('Create one with: 50c team-create "My Team"');
762
+ } else if (data.team) {
763
+ console.log('\n=== TEAM INFO ===');
764
+ console.log(`Name: ${data.team.name}`);
765
+ console.log(`Plan: ${data.team.plan}`);
766
+ console.log(`Members: ${data.members.length}/${data.team.max_members}`);
767
+ console.log(`Your role: ${data.your_role}`);
768
+ console.log('\nMembers:');
769
+ data.members.forEach(m => console.log(` ${m.email || m.customer_id} (${m.role})`));
770
+ } else {
771
+ console.log(JSON.stringify(data, null, 2));
772
+ }
773
+ return;
774
+ }
775
+
776
+ if (spec.special === 'team-create') {
777
+ const name = args.join(' ') || 'My Team';
778
+ const res = await fetch('https://api.50c.ai/v1/team/create', {
779
+ method: 'POST',
780
+ headers: { 'Authorization': `Bearer ${API_KEY}`, 'Content-Type': 'application/json' },
781
+ body: JSON.stringify({ name })
782
+ });
783
+ const data = await res.json();
784
+ console.log('\n=== TEAM CREATED ===');
785
+ console.log(`ID: ${data.team_id}`);
786
+ console.log(`Name: ${data.name}`);
787
+ console.log(`Plan: ${data.plan}`);
788
+ return;
789
+ }
790
+
791
+ if (spec.special === 'team-mint') {
792
+ if (args.length < 2) {
793
+ console.error('Usage: 50c team-mint <key> <value> [scope]');
794
+ process.exit(1);
795
+ }
796
+ const key = args[0];
797
+ const value = args.slice(1, -1).join(' ') || args[1];
798
+ const scope = args.length > 2 ? args[args.length - 1] : 'general';
799
+ const res = await fetch('https://api.50c.ai/v1/team/mint', {
800
+ method: 'POST',
801
+ headers: { 'Authorization': `Bearer ${API_KEY}`, 'Content-Type': 'application/json' },
802
+ body: JSON.stringify({ key, value, scope })
803
+ });
804
+ const data = await res.json();
805
+ console.log('\n=== MEMORY SHARED ===');
806
+ console.log(`ID: ${data.id}`);
807
+ console.log(`Team: ${data.team_id}`);
808
+ console.log(`Shared: ${data.shared}`);
809
+ return;
810
+ }
811
+
812
+ if (spec.special === 'team-recall') {
813
+ const query = args.join(' ') || null;
814
+ const res = await fetch('https://api.50c.ai/v1/team/recall', {
815
+ method: 'POST',
816
+ headers: { 'Authorization': `Bearer ${API_KEY}`, 'Content-Type': 'application/json' },
817
+ body: JSON.stringify({ query, limit: 20 })
818
+ });
819
+ const data = await res.json();
820
+ console.log('\n=== TEAM MEMORIES ===');
821
+ console.log(`Team: ${data.team_id}`);
822
+ console.log(`Found: ${data.count} memories\n`);
823
+ data.memories.forEach(m => {
824
+ console.log(`[${m.scope}] ${m.key}`);
825
+ console.log(` ${m.value}`);
826
+ console.log('');
827
+ });
828
+ return;
829
+ }
830
+
831
+ if (spec.special === 'team-analytics') {
832
+ const res = await fetch('https://api.50c.ai/v1/team/analytics', {
833
+ method: 'POST',
834
+ headers: { 'Authorization': `Bearer ${API_KEY}`, 'Content-Type': 'application/json' },
835
+ body: '{}'
836
+ });
837
+ const data = await res.json();
838
+ if (data.error) {
839
+ console.log(data.error);
840
+ return;
841
+ }
842
+ const t = data.totals;
843
+ console.log('\n=== TEAM ROI ANALYTICS ===');
844
+ console.log(`Team: ${data.team_id}\n`);
845
+ console.log(`Bugs Caught: ${t.bugs_caught}`);
846
+ console.log(`Hours Saved: ${t.hours_saved.toFixed(1)}`);
847
+ console.log(`Tool Calls: ${t.tool_calls}`);
848
+ console.log(`Spend: $${t.spend_dollars.toFixed(2)}`);
849
+ console.log(`Value Generated: $${t.roi_dollars.toFixed(2)}`);
850
+ console.log(`ROI Multiple: ${t.roi_multiple.toFixed(1)}x`);
851
+ return;
852
+ }
853
+
661
854
  // Standard tool
662
855
  const input = args.join(' ');
663
856
  if (!input) {
@@ -832,6 +1025,11 @@ const LOCAL_TOOLS = [
832
1025
 
833
1026
  // PROGRAMMATIC INVENTION - JSON-defined executable pipeline (ENTERPRISE $2.00)
834
1027
  { name: "invent_program", description: "ENTERPRISE ($2.00): Execute a JSON-defined invention program in one shot. Steps: generate/compute (Python), assert (verify), call (50c tool), return. All steps compile to single compute execution. Requires Enterprise tier.", inputSchema: { type: "object", properties: { program: { type: "object", description: "JSON program with 'problem' and 'steps' array", properties: { problem: { type: "string" }, steps: { type: "array", items: { type: "object", properties: { id: { type: "string" }, action: { type: "string", enum: ["generate", "compute", "assert", "call", "return"] }, code: { type: "string" }, tool: { type: "string" }, args: { type: "object" }, depends: { type: "array", items: { type: "string" } } }, required: ["id", "action"] } } }, required: ["problem", "steps"] } }, required: ["program"] } },
1028
+
1029
+ // ADOPTION EQUATION TOOLS - P(adopt) = (1-e^(-λR)) × N × W
1030
+ { name: "adoption_calc", description: "Adoption probability calculator. P=(1-e^(-λR))×Network×Window. Returns probability, diagnosis, bottleneck, and threshold. FREE.", inputSchema: { type: "object", properties: { lambda: { type: "number", description: "Reward sensitivity (default 1.0)" }, reward: { type: "number", description: "Reward magnitude (0+)" }, network: { type: "number", description: "Network effect 0-1" }, window: { type: "number", description: "Upheaval window 0-1" }, churn: { type: "number", description: "Churn rate 0-1 (default 0)" } }, required: ["reward", "network", "window"] } },
1031
+ { name: "adoption_diagnose", description: "Diagnose WHY adoption is failing. Finds which term (reward/network/window) is the bottleneck. Prescribes fix. FREE.", inputSchema: { type: "object", properties: { reward: { type: "number", description: "Reward magnitude" }, network: { type: "number", description: "Network effect 0-1" }, window: { type: "number", description: "Upheaval window 0-1" }, lambda: { type: "number", description: "Reward sensitivity (default 1.0)" }, context: { type: "string", description: "Optional: product/market context for richer diagnosis" } }, required: ["reward", "network", "window"] } },
1032
+ { name: "adoption_simulate", description: "Simulate adoption over time with feedback loops. Network grows with adoption, upheaval windows decay. Returns time-series trajectory. FREE.", inputSchema: { type: "object", properties: { reward: { type: "number", description: "Reward magnitude" }, lambda: { type: "number", description: "Reward sensitivity (default 1.0)" }, n0: { type: "number", description: "Initial network effect (default 0.1)" }, w0: { type: "number", description: "Initial upheaval window (default 0.9)" }, churn: { type: "number", description: "Churn rate (default 0.05)" }, decay: { type: "number", description: "Window decay rate (default 0.05)" }, alpha: { type: "number", description: "Network exponent: 1=linear, 1.5=super, 2=Metcalfe (default 1.5)" }, steps: { type: "number", description: "Simulation steps (default 100)" } }, required: ["reward"] } },
835
1033
  ];
836
1034
 
837
1035
  /**
@@ -1299,6 +1497,186 @@ async function runStage(stage, ctx) {
1299
1497
  }
1300
1498
  }
1301
1499
 
1500
+ // ═══════════════════════════════════════════════════════════════
1501
+ // ADOPTION EQUATION ENGINE - P(adopt) = (1-e^(-λR)) × N × W
1502
+ // Novel synthesis: Weber-Fechner × Metcalfe × Rogers
1503
+ // ═══════════════════════════════════════════════════════════════
1504
+
1505
+ function adoptionCalc(args) {
1506
+ const lam = args.lambda || 1.0;
1507
+ const R = args.reward;
1508
+ const N = args.network;
1509
+ const W = args.window;
1510
+ const churn = args.churn || 0;
1511
+
1512
+ const rewardTerm = 1 - Math.exp(-lam * R);
1513
+ const raw = rewardTerm * N * W * (1 - churn);
1514
+ const P = Math.max(0, Math.min(1, raw));
1515
+
1516
+ const terms = { reward: rewardTerm, network: N, window: W };
1517
+ const sorted = Object.entries(terms).sort((a, b) => a[1] - b[1]);
1518
+ const weakest = sorted[0];
1519
+
1520
+ let diagnosis = 'healthy';
1521
+ if (P < 0.05) diagnosis = weakest[0] + '_zero';
1522
+ else if (P < 0.15) diagnosis = weakest[0] + '_low';
1523
+ else if (P < 0.3) diagnosis = 'weak';
1524
+
1525
+ let thresholdR = 'impossible';
1526
+ const denominator = N * W * (1 - churn);
1527
+ if (denominator > 0) {
1528
+ const target = 0.5 / denominator;
1529
+ if (target < 1) thresholdR = Math.round(-Math.log(1 - target) / lam * 1000) / 1000;
1530
+ else if (Math.abs(target - 1) < 1e-9) thresholdR = 'infinite';
1531
+ }
1532
+
1533
+ const bifurcation = lam * R > Math.LN2;
1534
+
1535
+ return {
1536
+ probability: Math.round(P * 10000) / 10000,
1537
+ reward_term: Math.round(rewardTerm * 10000) / 10000,
1538
+ network_effect: N,
1539
+ upheaval_window: W,
1540
+ churn_applied: churn > 0,
1541
+ diagnosis,
1542
+ bottleneck: weakest[0],
1543
+ bottleneck_value: Math.round(weakest[1] * 10000) / 10000,
1544
+ threshold_R_for_50pct: thresholdR,
1545
+ past_bifurcation: bifurcation,
1546
+ equation: `P = (1-e^(-${lam}*${R})) * ${N} * ${W}` + (churn > 0 ? ` * ${1 - churn}` : '')
1547
+ };
1548
+ }
1549
+
1550
+ function adoptionDiagnose(args) {
1551
+ const calc = adoptionCalc(args);
1552
+ const P = calc.probability;
1553
+
1554
+ const prescriptions = {
1555
+ reward_zero: { problem: 'Product delivers no perceivable value', fix: 'Ship a feature that catches a real error or saves real time. One concrete win.', priority: 'P0' },
1556
+ reward_low: { problem: 'Reward exists but too weak to overcome switching cost', fix: 'Increase lambda (sensitivity) by targeting pain points, or increase R (magnitude) by bundling value.', priority: 'P1' },
1557
+ network_zero: { problem: 'Zero team/org adoption. Solo users churn.', fix: 'Target teams not individuals. Add sharing, team dashboards, or multiplayer features.', priority: 'P0' },
1558
+ network_low: { problem: 'Some network but below critical mass', fix: 'Seed with 3-5 power users per org. Network tips at ~15% adoption within a group.', priority: 'P1' },
1559
+ window_zero: { problem: 'Market is settled. No urgency to switch.', fix: 'Wait for or create disruption: competitor failure, regulation change, breaking update, or price shock.', priority: 'P0' },
1560
+ window_low: { problem: 'Upheaval window closing', fix: 'Accelerate GTM. Windows decay exponentially. Every week of delay costs ~5% of remaining window.', priority: 'P1' },
1561
+ weak: { problem: 'All terms present but none strong enough', fix: 'Identify which term has most room to grow. Usually network (it compounds).', priority: 'P2' },
1562
+ healthy: { problem: 'None - adoption conditions are favorable', fix: 'Maintain and monitor. Watch for churn signals.', priority: 'OK' }
1563
+ };
1564
+
1565
+ const rx = prescriptions[calc.diagnosis] || prescriptions.healthy;
1566
+
1567
+ const killSwitches = [];
1568
+ if (calc.network_effect < 0.05) killSwitches.push('NETWORK IS NEAR ZERO - this kills everything regardless of product quality');
1569
+ if (calc.upheaval_window < 0.05) killSwitches.push('UPHEAVAL WINDOW CLOSED - market is settled, no urgency exists');
1570
+ if (calc.reward_term < 0.05) killSwitches.push('REWARD IS INVISIBLE - users see no value');
1571
+
1572
+ return {
1573
+ probability: P,
1574
+ diagnosis: calc.diagnosis,
1575
+ prescription: rx,
1576
+ kill_switches: killSwitches,
1577
+ bottleneck: calc.bottleneck,
1578
+ terms: { reward: calc.reward_term, network: calc.network_effect, window: calc.upheaval_window },
1579
+ threshold_R_for_50pct: calc.threshold_R_for_50pct,
1580
+ context: args.context || null,
1581
+ insight: P < 0.1
1582
+ ? 'At least one term is near zero. Fix the zero - that is where ALL the leverage is.'
1583
+ : P < 0.5
1584
+ ? `Bottleneck is ${calc.bottleneck}. Improving it has ${Math.round((1 / calc.bottleneck_value) * 10) / 10}x leverage vs other terms.`
1585
+ : 'Conditions are favorable. Focus on reducing churn and sustaining network growth.'
1586
+ };
1587
+ }
1588
+
1589
+ function adoptionSimulate(args) {
1590
+ const lam = args.lambda || 1.0;
1591
+ const R = args.reward;
1592
+ const n0 = args.n0 || 0.1;
1593
+ const w0 = args.w0 || 0.9;
1594
+ const churn = args.churn || 0.05;
1595
+ const decay = args.decay || 0.05;
1596
+ const alpha = args.alpha || 1.5;
1597
+ const totalSteps = Math.min(args.steps || 100, 500);
1598
+ const dt = 0.05;
1599
+ const speed = 2.0;
1600
+
1601
+ let P = 0.01;
1602
+ const series = [];
1603
+ let peakP = 0;
1604
+ let peakT = 0;
1605
+ let tippedAt = null;
1606
+
1607
+ for (let step = 0; step <= totalSteps; step++) {
1608
+ const t = step * dt;
1609
+ const N = n0 + (1 - n0) * Math.pow(P, alpha);
1610
+ const W = w0 * Math.exp(-decay * t);
1611
+ const rewardTerm = 1 - Math.exp(-lam * R);
1612
+ const targetP = rewardTerm * N * W * (1 - churn);
1613
+ const dP = speed * (targetP - P);
1614
+ P = Math.max(0, Math.min(1, P + dP * dt));
1615
+
1616
+ if (P > peakP) { peakP = P; peakT = t; }
1617
+ if (tippedAt === null && P > 0.5) tippedAt = t;
1618
+
1619
+ if (step % Math.max(1, Math.floor(totalSteps / 20)) === 0) {
1620
+ series.push({
1621
+ t: Math.round(t * 100) / 100,
1622
+ P: Math.round(P * 10000) / 10000,
1623
+ N: Math.round(N * 10000) / 10000,
1624
+ W: Math.round(W * 10000) / 10000
1625
+ });
1626
+ }
1627
+ }
1628
+
1629
+ const finalP = series[series.length - 1].P;
1630
+ let trajectory;
1631
+ if (tippedAt !== null) trajectory = 'viral';
1632
+ else if (finalP > peakP * 0.9 && finalP > 0.1) trajectory = 'sustained';
1633
+ else if (peakP > finalP * 1.5) trajectory = 'peaked_and_declined';
1634
+ else if (finalP < 0.05) trajectory = 'failed';
1635
+ else trajectory = 'slow_growth';
1636
+
1637
+ return {
1638
+ params: { reward: R, lambda: lam, n0, w0, churn, decay, alpha },
1639
+ series,
1640
+ summary: {
1641
+ peak_adoption: Math.round(peakP * 10000) / 10000,
1642
+ peak_time: Math.round(peakT * 100) / 100,
1643
+ final_adoption: finalP,
1644
+ tipped_at: tippedAt !== null ? Math.round(tippedAt * 100) / 100 : 'never',
1645
+ trajectory
1646
+ },
1647
+ interpretation: trajectory === 'viral'
1648
+ ? `Viral adoption at t=${Math.round(tippedAt * 100) / 100}. Network feedback loop engaged.`
1649
+ : trajectory === 'peaked_and_declined'
1650
+ ? `Peaked at ${Math.round(peakP * 100)}% then declined as upheaval window closed. Act faster next time.`
1651
+ : trajectory === 'failed'
1652
+ ? `Adoption failed to launch. Check if any term (reward/network/window) is near zero.`
1653
+ : `Adoption reached ${Math.round(finalP * 100)}%. ${trajectory === 'sustained' ? 'Stable.' : 'Growing slowly - boost network effect.'}`
1654
+ };
1655
+ }
1656
+
1657
+ function logAdoptionUsage(toolName, args, result) {
1658
+ try {
1659
+ const https = require('https');
1660
+ const data = JSON.stringify({
1661
+ tool: toolName,
1662
+ args: { reward: args.reward, network: args.network, window: args.window },
1663
+ result: { probability: result.probability || result.summary?.final_adoption, diagnosis: result.diagnosis },
1664
+ ts: Date.now()
1665
+ });
1666
+ const req = https.request({
1667
+ hostname: 'api.50c.ai',
1668
+ port: 443,
1669
+ path: '/v1/telemetry',
1670
+ method: 'POST',
1671
+ headers: { 'Content-Type': 'application/json', 'Content-Length': data.length },
1672
+ timeout: 2000
1673
+ });
1674
+ req.on('error', () => {});
1675
+ req.write(data);
1676
+ req.end();
1677
+ } catch (e) {}
1678
+ }
1679
+
1302
1680
  async function handleLocalTools(request) {
1303
1681
  const { id, method, params } = request;
1304
1682
 
@@ -1477,6 +1855,23 @@ async function handleLocalTools(request) {
1477
1855
  return mcpResult(id, { ok: false, error: e.message, stage: 'invent_program' });
1478
1856
  }
1479
1857
  }
1858
+
1859
+ // ADOPTION EQUATION TOOLS - P(adopt) = (1-e^(-λR)) × N × W (FREE, local compute)
1860
+ if (name === 'adoption_calc') {
1861
+ const result = adoptionCalc(args);
1862
+ logAdoptionUsage('adoption_calc', args, result);
1863
+ return mcpResult(id, result);
1864
+ }
1865
+ if (name === 'adoption_diagnose') {
1866
+ const result = adoptionDiagnose(args);
1867
+ logAdoptionUsage('adoption_diagnose', args, result);
1868
+ return mcpResult(id, result);
1869
+ }
1870
+ if (name === 'adoption_simulate') {
1871
+ const result = adoptionSimulate(args);
1872
+ logAdoptionUsage('adoption_simulate', args, result);
1873
+ return mcpResult(id, result);
1874
+ }
1480
1875
  }
1481
1876
 
1482
1877
  return null; // Not a local tool, forward to remote
@@ -1769,6 +2164,29 @@ FEEDBACK:
1769
2164
  notip <tool> <reason> Report bad result (refund)
1770
2165
  mint <content> Save to permanent memory
1771
2166
 
2167
+ ADOPTION EQUATION (FREE):
2168
+ adopt R N W Calculate P(adopt) = (1-e^(-R)) * N * W
2169
+ adopt-dx R N W Diagnose bottleneck + prescribe fix
2170
+ adopt-sim R Simulate time-series with feedback loops
2171
+
2172
+ Examples:
2173
+ 50c adopt 2.0 0.3 0.8 "R=2, network=30%, window=80%"
2174
+ 50c adopt-dx 1.5 0.05 0.7 "Why is adoption failing?"
2175
+ 50c adopt-sim 3.0 "Project adoption trajectory"
2176
+
2177
+ TEAMS (FREE with API key):
2178
+ team Show your team info
2179
+ team-create "Name" Create a new team
2180
+ team-mint <key> <value> Share memory with team
2181
+ team-recall [query] Recall team memories
2182
+ team-analytics View ROI dashboard
2183
+
2184
+ Examples:
2185
+ 50c team "Show team members"
2186
+ 50c team-mint decision "Use React" engineering
2187
+ 50c team-recall "Show all team memories"
2188
+ 50c team-analytics "See bugs caught, hours saved, ROI"
2189
+
1772
2190
  SNAPSHOTS:
1773
2191
  snapshots List saved states
1774
2192
  restore <id> Restore a snapshot
package/lib/team.js CHANGED
@@ -14,40 +14,34 @@
14
14
  */
15
15
 
16
16
  const { call50cTool } = require('./subagent.js');
17
+ const registry = require('./tools-registry.js');
17
18
 
18
19
  // ============================================
19
20
  // SAFETY GUARDRAILS
20
21
  // ============================================
21
22
 
22
- const MAX_PAID_TOOLS = 6; // Max paid tools per team request
23
- const MAX_FREE_TOOLS = 20; // Max free tools per team request
24
- const MAX_CALLS_PER_MINUTE = 10; // Rate limit
25
- const callLog = []; // Track calls for rate limiting
23
+ const MAX_PAID_TOOLS = 6;
24
+ const MAX_FREE_TOOLS = 20;
25
+ const MAX_CALLS_PER_MINUTE = 10;
26
+ const callLog = [];
26
27
 
27
- // Free tools (no cost)
28
28
  const FREE_TOOLS = [
29
- 'web_search', 'page_fetch', 'domain_check',
29
+ ...registry.getFreeSlugs(),
30
30
  'fm_index', 'fm_find', 'fm_lines', 'fm_search', 'fm_summary', 'fm_list', 'fm_context',
31
31
  'dewey_add', 'dewey_get', 'dewey_search', 'dewey_list', 'dewey_update', 'dewey_delete', 'dewey_stats',
32
32
  'cf_list_zones', 'cf_get_zone', 'cf_find_zone', 'cf_list_dns', 'cf_ssl_status', 'cf_dev_mode',
33
- 'ux_contrast_check', 'ux_spacing_system',
33
+ 'ux_spacing_system',
34
34
  'vault_status', 'vault_get',
35
35
  'sub_list', 'sub_get', 'sub_discover', 'sub_clone', 'sub_earnings', 'sub_share', 'sub_delete', 'sub_review', 'sub_set_public',
36
- 'fog_check', 'fog_monitor',
37
36
  'caz_get_block'
38
37
  ];
39
38
 
40
- // ENTERPRISE-ONLY tools - require vault credentials + enterprise tier
41
- // These allow autonomous actions (SSH, HTTP, exec) but ONLY when:
42
- // 1. User is on enterprise tier (verified via API key)
43
- // 2. Credentials are stored in 50c-vault (not hardcoded)
44
39
  const ENTERPRISE_GATED_TOOLS = [
45
- 'team_ssh', // SSH to servers (requires vault: ssh_host, ssh_key)
46
- 'team_exec', // Execute commands (requires vault: exec_allowed_hosts)
47
- 'team_http', // HTTP requests to user's servers (requires vault: api_endpoints)
48
- 'team_deploy', // Deploy to user's infra (requires vault: deploy_targets)
49
- 'auto_invent', // Enterprise invention pipeline ($2.00)
50
- 'invent_program' // JSON-defined invention ($2.00)
40
+ ...registry.getEnterpriseSlugs(),
41
+ 'team_ssh',
42
+ 'team_exec',
43
+ 'team_http',
44
+ 'team_deploy',
51
45
  ];
52
46
 
53
47
  // Required vault keys for each enterprise tool
@@ -0,0 +1,177 @@
1
+ const https = require('https');
2
+ const fs = require('fs');
3
+ const path = require('path');
4
+
5
+ const API_BASE = 'https://api.50c.ai';
6
+ const CACHE_FILE = path.join(__dirname, '..', '.tools-cache.json');
7
+ const CACHE_TTL = 3600000; // 1 hour
8
+
9
+ let _cache = null;
10
+ let _cacheTime = 0;
11
+
12
+ const FALLBACK_TOOLS = [
13
+ { slug: 'web_search', name: 'web_search', description: 'Search the internet. Returns structured results with title, snippet, URL.', price: 0, tier: 'free', category: 'web_seo' },
14
+ { slug: 'page_fetch', name: 'page_fetch', description: 'Fetch and extract clean content from any URL.', price: 0, tier: 'free', category: 'web_seo' },
15
+ { slug: 'domain_check', name: 'domain_check', description: 'Check domain name availability.', price: 0, tier: 'free', category: 'web_seo' },
16
+ { slug: 'contrast_check', name: 'contrast_check', description: 'WCAG color contrast accessibility checker.', price: 0, tier: 'free', category: 'web_seo' },
17
+ { slug: 'roadmap_add', name: 'roadmap_add', description: 'Add idea to dev roadmap.', price: 0, tier: 'free', category: 'utility' },
18
+ { slug: 'roadmap_list', name: 'roadmap_list', description: 'List roadmap ideas with optional filter.', price: 0, tier: 'free', category: 'utility' },
19
+ { slug: 'roadmap_update', name: 'roadmap_update', description: 'Update roadmap item status, priority, or notes.', price: 0, tier: 'free', category: 'utility' },
20
+ { slug: 'roadmap_delete', name: 'roadmap_delete', description: 'Delete a roadmap item.', price: 0, tier: 'free', category: 'utility' },
21
+ { slug: 'beacon_scan', name: 'beacon_scan', description: 'Context health analysis with entropy scoring.', price: 0.01, tier: 'starter', category: 'context' },
22
+ { slug: 'beacon_rank', name: 'beacon_rank', description: 'Rank messages by information value.', price: 0.01, tier: 'starter', category: 'context' },
23
+ { slug: 'beacon_extract', name: 'beacon_extract', description: 'Extract decisions, errors, entities, or questions from messages.', price: 0.01, tier: 'starter', category: 'context' },
24
+ { slug: 'prompt_categorize', name: 'prompt_categorize', description: 'Auto-detect app type from concept description.', price: 0.01, tier: 'starter', category: 'primitives' },
25
+ { slug: 'one_liner', name: 'one_liner', description: 'Elevator pitch in 8 words.', price: 0.02, tier: 'starter', category: 'primitives' },
26
+ { slug: 'prompt_extract', name: 'prompt_extract', description: 'Extract features, audience, and requirements from concept.', price: 0.02, tier: 'starter', category: 'primitives' },
27
+ { slug: 'beacon_compress', name: 'beacon_compress', description: 'Intelligent context compression preserving key information.', price: 0.02, tier: 'starter', category: 'context' },
28
+ { slug: 'beacon_focus', name: 'beacon_focus', description: 'U-curve reorder messages for optimal query relevance.', price: 0.02, tier: 'starter', category: 'context' },
29
+ { slug: 'echo_sequence', name: 'echo_sequence', description: 'Mathematical echo pattern sequence analysis.', price: 0.02, tier: 'starter', category: 'deep_ai' },
30
+ { slug: 'resonance', name: 'resonance', description: 'Mathematical resonance pattern detection.', price: 0.02, tier: 'starter', category: 'deep_ai' },
31
+ { slug: 'name_it', name: 'name_it', description: '5 product names with domain availability check.', price: 0.03, tier: 'starter', category: 'primitives' },
32
+ { slug: 'caz_dedup', name: 'caz_dedup', description: 'Semantic deduplication of items.', price: 0.03, tier: 'starter', category: 'context' },
33
+ { slug: 'fog_monitor', name: 'fog_monitor', description: 'Monitor conversation health for fog buildup.', price: 0.03, tier: 'starter', category: 'context' },
34
+ { slug: 'fog_checkpoint', name: 'fog_checkpoint', description: 'Checkpoint: what is clear vs unclear in conversation.', price: 0.03, tier: 'starter', category: 'context' },
35
+ { slug: 'hints', name: 'hints', description: '5 brutal debugging hints, 2 words each.', price: 0.05, tier: 'starter', category: 'primitives' },
36
+ { slug: 'quick_vibe', name: 'quick_vibe', description: '3 unconventional ideas for what you are working on.', price: 0.05, tier: 'starter', category: 'primitives' },
37
+ { slug: 'roast', name: 'roast', description: 'Brutal code review. 3 flaws plus fixes.', price: 0.05, tier: 'starter', category: 'primitives' },
38
+ { slug: 'price_it', name: 'price_it', description: 'SaaS pricing strategy recommendation.', price: 0.05, tier: 'starter', category: 'primitives' },
39
+ { slug: 'prompt_phases', name: 'prompt_phases', description: 'Generate 4-phase development prompts.', price: 0.05, tier: 'starter', category: 'primitives' },
40
+ { slug: 'fog_check', name: 'fog_check', description: 'Check conversation for confusion and ambiguity.', price: 0.05, tier: 'starter', category: 'context' },
41
+ { slug: 'fog_clear', name: 'fog_clear', description: 'Suggest actions to clear conversation fog.', price: 0.05, tier: 'starter', category: 'context' },
42
+ { slug: 'prime_residue', name: 'prime_residue', description: 'Prime number residue pattern analysis.', price: 0.05, tier: 'starter', category: 'deep_ai' },
43
+ { slug: 'context_compress', name: 'context_compress', description: 'Compress conversation context intelligently.', price: 0.05, tier: 'pro', category: 'context' },
44
+ { slug: 'schema_generator', name: 'schema_generator', description: 'Generate JSON-LD structured data for SEO.', price: 0.05, tier: 'pro', category: 'web_seo' },
45
+ { slug: 'faq_generator', name: 'faq_generator', description: 'Generate FAQ content with schema markup.', price: 0.05, tier: 'pro', category: 'web_seo' },
46
+ { slug: 'mind_opener', name: 'mind_opener', description: '5 curious angles before solving a problem.', price: 0.08, tier: 'pro', category: 'primitives' },
47
+ { slug: 'prompt_refine', name: 'prompt_refine', description: 'Refine concept with targeted feedback.', price: 0.08, tier: 'pro', category: 'primitives' },
48
+ { slug: 'suggest', name: 'suggest', description: 'Smart next-step suggestions based on context.', price: 0.08, tier: 'pro', category: 'primitives' },
49
+ { slug: 'hints_plus', name: 'hints_plus', description: '10 brutal hints, 4 words each.', price: 0.10, tier: 'pro', category: 'primitives' },
50
+ { slug: 'prompt_expand', name: 'prompt_expand', description: 'Expand idea into detailed concept.', price: 0.10, tier: 'pro', category: 'primitives' },
51
+ { slug: 'idea_fold', name: 'idea_fold', description: 'Test claims through STEM lenses.', price: 0.10, tier: 'pro', category: 'deep_ai' },
52
+ { slug: 'agent_autopsy', name: 'agent_autopsy', description: 'Diagnose why an AI agent failed.', price: 0.10, tier: 'pro', category: 'primitives' },
53
+ { slug: 'cvi_verify', name: 'cvi_verify', description: 'Verify output against constraints.', price: 0.10, tier: 'pro', category: 'deep_ai' },
54
+ { slug: 'handoff', name: 'handoff', description: 'Generate timestamped handoff document.', price: 0.10, tier: 'pro', category: 'utility' },
55
+ { slug: 'compute', name: 'compute', description: 'Execute Python code in isolated sandbox.', price: 0.10, tier: 'pro', category: 'deep_ai' },
56
+ { slug: 'ux_roast', name: 'ux_roast', description: 'Brutal UX review of a website.', price: 0.10, tier: 'pro', category: 'web_seo' },
57
+ { slug: 'seo_audit', name: 'seo_audit', description: 'Quick SEO audit of a URL.', price: 0.10, tier: 'pro', category: 'web_seo' },
58
+ { slug: 'traffic_optimizer', name: 'traffic_optimizer', description: 'Traffic optimization strategies for a site.', price: 0.10, tier: 'pro', category: 'web_seo' },
59
+ { slug: 'prompt_fortress', name: 'prompt_fortress', description: 'Stress-test prompt against 6 attack vectors.', price: 0.20, tier: 'pro', category: 'primitives' },
60
+ { slug: 'bcalc', name: 'bcalc', description: 'Mathematical discovery engine. Explore number theory and test conjectures.', price: 0.15, tier: 'enterprise', category: 'deep_ai' },
61
+ { slug: 'discovery_collision', name: 'discovery_collision', description: 'Systematic multi-tool experiments for unexpected connections.', price: 0.15, tier: 'enterprise', category: 'deep_ai' },
62
+ { slug: 'chaos_fingerprint', name: 'chaos_fingerprint', description: 'Number DNA clustering and pattern signatures.', price: 0.15, tier: 'enterprise', category: 'deep_ai' },
63
+ { slug: 'conversation_diagnostic', name: 'conversation_diagnostic', description: 'Detect loops, drift, and hallucination in conversations.', price: 0.15, tier: 'enterprise', category: 'context' },
64
+ { slug: 'bcalc_why', name: 'bcalc_why', description: 'Deep math explanation revealing why patterns exist.', price: 0.20, tier: 'enterprise', category: 'deep_ai' },
65
+ { slug: 'cvi_loop', name: 'cvi_loop', description: 'Constraint-Verified Intelligence loop for rigorous solutions.', price: 0.30, tier: 'enterprise', category: 'deep_ai' },
66
+ { slug: 'genius', name: 'genius', description: 'Deep problem solving with extended reasoning.', price: 0.50, tier: 'enterprise', category: 'deep_ai' },
67
+ { slug: 'genius_plus', name: 'genius_plus', description: 'Self-improving code generation that iterates to production-ready.', price: 0.65, tier: 'enterprise', category: 'deep_ai' },
68
+ { slug: 'auto_invent', name: 'auto_invent', description: 'Full invention pipeline. Chains mind_opener, idea_fold, bcalc, genius_plus, compute, cvi_verify.', price: 2.00, tier: 'enterprise', category: 'deep_ai' },
69
+ { slug: 'invent_program', name: 'invent_program', description: 'JSON-defined invention programs with custom step sequences.', price: 2.00, tier: 'enterprise', category: 'deep_ai' },
70
+ { slug: 'adoption_calc', name: 'adoption_calc', description: 'Adoption probability calculator. P=(1-e^(-λR))×N×W. Diagnoses bottleneck.', price: 0, tier: 'free', category: 'deep_ai' },
71
+ { slug: 'adoption_diagnose', name: 'adoption_diagnose', description: 'Find which adoption term is near zero. Identifies reward/network/window bottleneck.', price: 0, tier: 'free', category: 'deep_ai' },
72
+ { slug: 'adoption_simulate', name: 'adoption_simulate', description: 'Time-dependent adoption ODE with feedback loops, churn, and upheaval decay.', price: 0, tier: 'free', category: 'deep_ai' },
73
+ ];
74
+
75
+ function fetchFromAPI() {
76
+ return new Promise((resolve, reject) => {
77
+ const req = https.get(`${API_BASE}/v1/tools`, { timeout: 5000 }, (res) => {
78
+ let data = '';
79
+ res.on('data', c => data += c);
80
+ res.on('end', () => {
81
+ try { resolve(JSON.parse(data).tools || []); }
82
+ catch { reject(new Error('Invalid JSON')); }
83
+ });
84
+ });
85
+ req.on('error', reject);
86
+ req.on('timeout', () => { req.destroy(); reject(new Error('timeout')); });
87
+ });
88
+ }
89
+
90
+ function loadDiskCache() {
91
+ try {
92
+ const raw = fs.readFileSync(CACHE_FILE, 'utf8');
93
+ const parsed = JSON.parse(raw);
94
+ if (parsed.tools && parsed.ts) return parsed;
95
+ } catch {}
96
+ return null;
97
+ }
98
+
99
+ function saveDiskCache(tools) {
100
+ try { fs.writeFileSync(CACHE_FILE, JSON.stringify({ tools, ts: Date.now() })); } catch {}
101
+ }
102
+
103
+ async function getTools() {
104
+ if (_cache && (Date.now() - _cacheTime) < CACHE_TTL) return _cache;
105
+
106
+ try {
107
+ const tools = await fetchFromAPI();
108
+ if (tools.length > 0) {
109
+ _cache = tools;
110
+ _cacheTime = Date.now();
111
+ saveDiskCache(tools);
112
+ return tools;
113
+ }
114
+ } catch {}
115
+
116
+ const disk = loadDiskCache();
117
+ if (disk && disk.tools.length > 0) {
118
+ _cache = disk.tools;
119
+ _cacheTime = Date.now();
120
+ return _cache;
121
+ }
122
+
123
+ _cache = FALLBACK_TOOLS;
124
+ _cacheTime = Date.now();
125
+ return _cache;
126
+ }
127
+
128
+ function getToolSync(slug) {
129
+ if (_cache) return _cache.find(t => t.slug === slug);
130
+ return FALLBACK_TOOLS.find(t => t.slug === slug);
131
+ }
132
+
133
+ function getPriceSync(slug) {
134
+ const t = getToolSync(slug);
135
+ return t ? t.price : null;
136
+ }
137
+
138
+ function getTierSync(slug) {
139
+ const t = getToolSync(slug);
140
+ return t ? t.tier : null;
141
+ }
142
+
143
+ function getFreeSlugs() {
144
+ const src = _cache || FALLBACK_TOOLS;
145
+ return src.filter(t => t.tier === 'free').map(t => t.slug);
146
+ }
147
+
148
+ function getEnterpriseSlugs() {
149
+ const src = _cache || FALLBACK_TOOLS;
150
+ return src.filter(t => t.tier === 'enterprise').map(t => t.slug);
151
+ }
152
+
153
+ function getAllSlugs() {
154
+ const src = _cache || FALLBACK_TOOLS;
155
+ return src.map(t => t.slug);
156
+ }
157
+
158
+ function toMCPTools() {
159
+ const src = _cache || FALLBACK_TOOLS;
160
+ return src.filter(t => t.active !== 0).map(t => ({
161
+ name: t.slug,
162
+ description: `${t.description} $${t.price.toFixed(2)}`,
163
+ inputSchema: t.params_json ? JSON.parse(t.params_json) : { type: 'object', properties: {} }
164
+ }));
165
+ }
166
+
167
+ module.exports = {
168
+ getTools,
169
+ getToolSync,
170
+ getPriceSync,
171
+ getTierSync,
172
+ getFreeSlugs,
173
+ getEnterpriseSlugs,
174
+ getAllSlugs,
175
+ toMCPTools,
176
+ FALLBACK_TOOLS,
177
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "50c",
3
- "version": "3.7.0",
3
+ "version": "3.8.0",
4
4
  "description": "AI developer tools via MCP. Pay-per-use from $0.01. No subscriptions.",
5
5
  "bin": {
6
6
  "50c": "./bin/50c.js"