@ak--47/dungeon-master 1.2.3 → 1.3.1

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.
Files changed (89) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/README.md +51 -13
  3. package/dungeons/technical/ad-spend.js +2 -2
  4. package/dungeons/technical/anonymous-users.js +2 -2
  5. package/dungeons/technical/array-of-object-lookup.js +2 -4
  6. package/dungeons/technical/experiments.js +2 -2
  7. package/dungeons/technical/foobar.js +2 -2
  8. package/dungeons/technical/group-analytics.js +2 -2
  9. package/dungeons/technical/mirror-strategies.js +2 -2
  10. package/dungeons/technical/nested-objects.js +2 -2
  11. package/dungeons/technical/retention-cadence.js +2 -3
  12. package/dungeons/technical/sanity.js +2 -2
  13. package/dungeons/technical/scale-test.js +2 -2
  14. package/dungeons/technical/scd.js +2 -2
  15. package/dungeons/technical/simple.js +5 -6
  16. package/dungeons/technical/simplest-schema.json +5 -0
  17. package/dungeons/technical/simplest.js +2 -2
  18. package/dungeons/technical/text-generation.js +3 -3
  19. package/dungeons/vertical/ai-platform.js +858 -0
  20. package/dungeons/vertical/community.js +84 -40
  21. package/dungeons/vertical/crypto.js +830 -0
  22. package/dungeons/vertical/dating.js +744 -0
  23. package/dungeons/vertical/devtools.js +175 -69
  24. package/dungeons/vertical/ecommerce.js +242 -94
  25. package/dungeons/vertical/education.js +330 -313
  26. package/dungeons/vertical/fintech.js +442 -313
  27. package/dungeons/vertical/fitness.js +143 -61
  28. package/dungeons/vertical/food-delivery.js +327 -353
  29. package/dungeons/vertical/gaming.js +912 -382
  30. package/dungeons/vertical/healthcare.js +142 -63
  31. package/dungeons/vertical/insurance-application.js +170 -76
  32. package/dungeons/vertical/logistics.js +115 -20
  33. package/dungeons/vertical/marketplace.js +152 -58
  34. package/dungeons/vertical/media.js +248 -384
  35. package/dungeons/vertical/real-estate.js +781 -0
  36. package/dungeons/vertical/sass.js +255 -266
  37. package/dungeons/vertical/social.js +264 -206
  38. package/dungeons/vertical/travel.js +117 -41
  39. package/index.js +17 -17
  40. package/lib/core/config-validator.js +159 -31
  41. package/lib/core/context.js +10 -24
  42. package/lib/core/storage.js +6 -1
  43. package/lib/generators/events.js +11 -14
  44. package/lib/generators/funnels.js +12 -4
  45. package/lib/generators/mirror.js +3 -2
  46. package/lib/generators/product-names.js +1 -1
  47. package/lib/generators/scd.js +2 -1
  48. package/lib/generators/text.js +1 -1
  49. package/lib/orchestrators/user-loop.js +81 -47
  50. package/lib/templates/macro-presets.js +111 -0
  51. package/lib/templates/soup-presets.js +19 -36
  52. package/lib/utils/utils.js +71 -39
  53. package/package.json +8 -2
  54. package/scripts/smoke-test-all.mjs +162 -0
  55. package/scripts/verify-runner.mjs +72 -24
  56. package/types.d.ts +251 -51
  57. package/dungeons/technical/ad-spend-schema.json +0 -128
  58. package/dungeons/technical/anonymous-users-schema.json +0 -92
  59. package/dungeons/technical/array-of-object-lookup-schema.json +0 -191
  60. package/dungeons/technical/experiments-schema.json +0 -203
  61. package/dungeons/technical/foobar-schema.json +0 -362
  62. package/dungeons/technical/group-analytics-schema.json +0 -241
  63. package/dungeons/technical/mirror-strategies-schema.json +0 -84
  64. package/dungeons/technical/nested-objects-schema.json +0 -145
  65. package/dungeons/technical/retention-cadence-schema.json +0 -37
  66. package/dungeons/technical/sanity-schema.json +0 -185
  67. package/dungeons/technical/scale-test-schema.json +0 -70
  68. package/dungeons/technical/scd-schema.json +0 -467
  69. package/dungeons/technical/simple-schema.json +0 -362
  70. package/dungeons/technical/text-generation-schema.json +0 -1062
  71. package/dungeons/user/.gitkeep +0 -0
  72. package/dungeons/vertical/community-schema.json +0 -579
  73. package/dungeons/vertical/devtools-schema.json +0 -601
  74. package/dungeons/vertical/ecommerce-schema.json +0 -604
  75. package/dungeons/vertical/education-schema.json +0 -5686
  76. package/dungeons/vertical/fintech-schema.json +0 -630
  77. package/dungeons/vertical/fitness-schema.json +0 -530
  78. package/dungeons/vertical/food-delivery-schema.json +0 -36728
  79. package/dungeons/vertical/gaming-schema.json +0 -438
  80. package/dungeons/vertical/healthcare-schema.json +0 -549
  81. package/dungeons/vertical/insurance-application-schema.json +0 -485
  82. package/dungeons/vertical/logistics-schema.json +0 -574
  83. package/dungeons/vertical/marketplace-schema.json +0 -533
  84. package/dungeons/vertical/media-schema.json +0 -4749
  85. package/dungeons/vertical/rpg-schema.json +0 -2491
  86. package/dungeons/vertical/rpg.js +0 -976
  87. package/dungeons/vertical/sass-schema.json +0 -3128
  88. package/dungeons/vertical/social-schema.json +0 -620
  89. package/dungeons/vertical/travel-schema.json +0 -580
@@ -2,7 +2,7 @@
2
2
  const SEED = "simple is best";
3
3
  const num_days = 108;
4
4
  const num_users = 50_000;
5
- const avg_events_per_user = 40;
5
+ const avg_events_per_user_per_day = 0.37;
6
6
  let token = "your-mixpanel-token";
7
7
 
8
8
  // ── env overrides ──
@@ -50,47 +50,199 @@ const spiritAnimals = ["duck", "dog", "otter", "penguin", "cat", "elephant", "li
50
50
 
51
51
  /*
52
52
  * ============================================================================
53
- * ANALYTICS HOOKS
53
+ * ANALYTICS HOOKS (7 hooks)
54
+ *
55
+ * Adds 7. SIGNUP FLOW TIME-TO-CONVERT: gold/platinum loyalty 0.71x faster,
56
+ * bronze 1.3x slower (funnel-post). Discover via funnel median time-to-convert
57
+ * by loyalty_tier breakdown.
58
+ * NOTE (funnel-post measurement): visible only via Mixpanel funnel median TTC.
59
+ * Cross-event MIN→MIN SQL queries on raw events do NOT show this.
54
60
  * ============================================================================
55
61
  *
56
- * Hook 1: Signup Flow Improvement
57
- * Type: event + everything (tag-and-filter)
58
- * What: 7 days ago, signup flow switches from "v1" to "v2". Before that date,
59
- * 50% of sign ups are tagged _drop and removed in the everything hook,
60
- * simulating a broken flow that got fixed.
61
- * Mixpanel report:
62
- * - Insights > line chart > "sign up" totaled by day, breakdown by signup_flow
63
- * - Expect: ~2x volume increase in last 7 days; v1 disappears, v2 takes over
64
- *
65
- * Hook 2: Watch Time Inflection
66
- * Type: event
67
- * What: 30 days ago, watch time shifts. Before: watchTimeSec reduced by 25-79%.
68
- * After: increased by 25-79%. Creates a clear before/after inflection.
69
- * Mixpanel report:
70
- * - Insights > line chart > "watch video" with AVG(watchTimeSec) by day
71
- * - Expect: clear upward inflection ~30 days ago; watch time roughly doubles
72
- *
73
- * Hook 3: Toys + Shoes Cart Correlation
74
- * Type: event
75
- * What: Checkout carts with toys get shoes injected (and vice versa). Carts
76
- * with neither toys nor shoes have all item prices discounted to 75-90%.
77
- * Mixpanel report:
78
- * - Insights > bar chart > "checkout" broken down by cart[].category
79
- * - Expect: toys and shoes co-occur at high rate; carts without both have lower values
80
- *
81
- * Hook 4: Quality Watch Time Correlation
82
- * Type: event
83
- * What: Video quality multiplies watchTimeSec: 2160p=1.5x, 1440p=1.4x,
84
- * 1080p=1.3x, 720p=1.15x, 480p=1.0x, 360p=0.85x, 240p=0.7x.
85
- * Mixpanel report:
86
- * - Insights > bar chart > "watch video" with AVG(watchTimeSec), breakdown by quality
87
- * - Expect: monotonic increase from 240p to 2160p
88
- *
89
- * Hook 5: Item Flattening
90
- * Type: event
91
- * What: Events with an item array property get the first item's fields
92
- * flattened onto the event record, making category/amount/slug available
93
- * as top-level properties for easier breakdown in reports.
62
+ * ----------------------------------------------------------------------------
63
+ * Hook 1: Signup Flow Improvement (event + everything)
64
+ * ----------------------------------------------------------------------------
65
+ *
66
+ * PATTERN: 7 days ago, signup_flow switches from "v1" to "v2". Before
67
+ * that date, 50% of sign ups are tagged _drop and removed in the
68
+ * everything hook, simulating a broken flow that got fixed.
69
+ *
70
+ * HOW TO FIND IT IN MIXPANEL:
71
+ *
72
+ * Report 1: Sign Ups by Flow Version
73
+ * - Report type: Insights
74
+ * - Event: "sign up"
75
+ * - Measure: Total
76
+ * - Breakdown: "signup_flow"
77
+ * - Line chart by day
78
+ * - Expected: v1 disappears at day -7; v2 takes over and roughly 2x daily volume
79
+ *
80
+ * Report 2: Pre vs Post Volume
81
+ * - Report type: Insights
82
+ * - Event: "sign up"
83
+ * - Measure: Total
84
+ * - Compare date ranges (last 7 days vs prior 7 days)
85
+ * - Expected: ~ 2x signups in the post-fix window
86
+ *
87
+ * REAL-WORLD ANALOGUE: A broken signup flow silently halved conversions
88
+ * until a release shipped a fix; daily signups roughly doubled overnight.
89
+ *
90
+ * ----------------------------------------------------------------------------
91
+ * Hook 2: Watch Time Inflection (event)
92
+ * ----------------------------------------------------------------------------
93
+ *
94
+ * PATTERN: 30 days ago, watch time shifts. Before that date, watchTimeSec
95
+ * is reduced by 25-79%. After, it is increased by 25-79%. Creates a
96
+ * clear before/after inflection.
97
+ *
98
+ * HOW TO FIND IT IN MIXPANEL:
99
+ *
100
+ * Report 1: Avg Watch Time Over Time
101
+ * - Report type: Insights
102
+ * - Event: "watch video"
103
+ * - Measure: Average of "watchTimeSec"
104
+ * - Line chart by day
105
+ * - Expected: clear upward inflection ~ 30 days ago; watch time ~ doubles
106
+ *
107
+ * Report 2: Watch Time Distribution Pre vs Post
108
+ * - Report type: Insights
109
+ * - Event: "watch video"
110
+ * - Measure: Average of "watchTimeSec"
111
+ * - Compare date ranges (last 30 days vs prior 30 days)
112
+ * - Expected: post-inflection ~ 2x avg watch time
113
+ *
114
+ * REAL-WORLD ANALOGUE: An algorithm or UX change (autoplay, recs)
115
+ * inflects average watch duration sharply on a release date.
116
+ *
117
+ * ----------------------------------------------------------------------------
118
+ * Hook 3: Toys + Shoes Cart Correlation (event)
119
+ * ----------------------------------------------------------------------------
120
+ *
121
+ * PATTERN: Checkout carts with toys get a shoes item injected (and vice
122
+ * versa). Carts with neither toys nor shoes have all item prices
123
+ * discounted to 75-90% of normal.
124
+ *
125
+ * HOW TO FIND IT IN MIXPANEL:
126
+ *
127
+ * Report 1: Cart Category Co-occurrence
128
+ * - Report type: Insights
129
+ * - Event: "checkout"
130
+ * - Measure: Total
131
+ * - Breakdown: "category" (flattened item category)
132
+ * - Expected: toys and shoes appear at high co-occurrence rate
133
+ *
134
+ * Report 2: Cart Value by Category Mix
135
+ * - Report type: Insights
136
+ * - Event: "checkout"
137
+ * - Measure: Average of "amount"
138
+ * - Breakdown: "category"
139
+ * - Expected: carts lacking both toys and shoes have lower avg amount
140
+ *
141
+ * REAL-WORLD ANALOGUE: Family shoppers buying for kids tend to bundle
142
+ * toys with shoes; a market-basket pattern that retailers exploit.
143
+ *
144
+ * ----------------------------------------------------------------------------
145
+ * Hook 4: Quality to Watch Time Correlation (event)
146
+ * ----------------------------------------------------------------------------
147
+ *
148
+ * PATTERN: Video quality multiplies watchTimeSec: 2160p=1.5x, 1440p=1.4x,
149
+ * 1080p=1.3x, 720p=1.15x, 480p=1.0x, 360p=0.85x, 240p=0.7x.
150
+ *
151
+ * HOW TO FIND IT IN MIXPANEL:
152
+ *
153
+ * Report 1: Avg Watch Time by Quality
154
+ * - Report type: Insights
155
+ * - Event: "watch video"
156
+ * - Measure: Average of "watchTimeSec"
157
+ * - Breakdown: "quality"
158
+ * - Expected: monotonic increase from 240p to 2160p
159
+ *
160
+ * Report 2: Quality Distribution
161
+ * - Report type: Insights
162
+ * - Event: "watch video"
163
+ * - Measure: Total
164
+ * - Breakdown: "quality"
165
+ * - Expected: viewers split across all quality tiers; HD tiers earn more time
166
+ *
167
+ * REAL-WORLD ANALOGUE: Higher-resolution streams correlate with longer
168
+ * sessions because they signal a better connection and more invested viewer.
169
+ *
170
+ * ----------------------------------------------------------------------------
171
+ * Hook 5: Item Flattening (event)
172
+ * ----------------------------------------------------------------------------
173
+ *
174
+ * PATTERN: Events with an item array property get the first item's
175
+ * fields (category, amount, slug, etc.) flattened onto the event record
176
+ * as top-level properties — making them available for direct breakdown
177
+ * in reports.
178
+ *
179
+ * HOW TO FIND IT IN MIXPANEL:
180
+ *
181
+ * Report 1: View Items by Category
182
+ * - Report type: Insights
183
+ * - Event: "view item"
184
+ * - Measure: Total
185
+ * - Breakdown: "category"
186
+ * - Expected: clean breakdown across category values without nested-property issues
187
+ *
188
+ * Report 2: Add to Cart Avg Amount by Category
189
+ * - Report type: Insights
190
+ * - Event: "add to cart"
191
+ * - Measure: Average of "amount"
192
+ * - Breakdown: "category"
193
+ * - Expected: per-category averages render correctly off flat properties
194
+ *
195
+ * REAL-WORLD ANALOGUE: Analytics teams routinely flatten nested cart
196
+ * objects onto events so downstream tools can group/filter without joins.
197
+ *
198
+ * ----------------------------------------------------------------------------
199
+ * Hook 6: View-Item Magic Number (everything)
200
+ * ----------------------------------------------------------------------------
201
+ *
202
+ * PATTERN: Users who view 3-8 items in the dataset window are in the
203
+ * "considered buyer" sweet spot — every cart item amount and total_value
204
+ * gets boosted ~25%. Users who view 9 or more items are over-engaged
205
+ * window-shoppers; ~30% of their checkout events are dropped (decision
206
+ * paralysis / browse without buy). No flag is stamped — discoverable
207
+ * only by binning users on view-item COUNT and comparing avg cart total.
208
+ *
209
+ * HOW TO FIND IT IN MIXPANEL:
210
+ *
211
+ * Report 1: Avg Cart Total by View-Item Bucket
212
+ * - Report type: Insights (with cohort)
213
+ * - Cohort A: users with 3-8 "view item" events
214
+ * - Cohort B: users with 0-2 "view item" events
215
+ * - Event: "checkout"
216
+ * - Measure: Average of "amount" (sum across cart items if exposed)
217
+ * - Compare cohort A vs cohort B
218
+ * - Expected: cohort A ~ 1.25x higher cart total than B
219
+ *
220
+ * Report 2: Checkouts per User by Browse Intensity
221
+ * - Report type: Insights (with cohort)
222
+ * - Cohort C: users with >= 9 "view item" events
223
+ * - Cohort A: users with 3-8 "view item" events
224
+ * - Event: "checkout"
225
+ * - Measure: Total events per user
226
+ * - Compare cohort C vs cohort A
227
+ * - Expected: cohort C has ~ 30% fewer checkouts per user
228
+ *
229
+ * REAL-WORLD ANALOGUE: A focused buyer who reviews a handful of items
230
+ * tends to convert at higher cart value; an excessive browser is a
231
+ * tire-kicker who abandons more often.
232
+ *
233
+ * ============================================================================
234
+ * EXPECTED METRICS SUMMARY
235
+ * ============================================================================
236
+ *
237
+ * Hook | Metric | Baseline | Hook Effect | Ratio
238
+ * ---------------------------|-------------------------|------------|-------------|------
239
+ * Signup Flow Improvement | Daily sign ups | 1x | ~ 2x | 2x
240
+ * Watch Time Inflection | Avg watchTimeSec | 1x | ~ 2x | 2x
241
+ * Toys + Shoes Correlation | toys/shoes co-occurrence| ~ 7% | ~ 50%+ | ~ 7x
242
+ * Quality -> Watch Time | Avg watchTimeSec (240p->2160p) | 0.7x | 1.5x | ~ 2.1x
243
+ * Item Flattening | category breakdown | nested | flat | n/a
244
+ * View-Item Magic Number | sweet (3-8) cart total | 1x | ~ 1.25x | 1.25x
245
+ * View-Item Magic Number | over (9+) checkouts/user| 1x | ~ 0.7x | -30%
94
246
  * ============================================================================
95
247
  */
96
248
 
@@ -142,8 +294,10 @@ function makeProducts(maxItems = 5) {
142
294
  const config = {
143
295
  token,
144
296
  seed: SEED,
145
- numDays: num_days,
146
- numEvents: num_users * avg_events_per_user,
297
+ datasetStart: "2026-01-01T00:00:00Z",
298
+ datasetEnd: "2026-04-28T23:59:59Z",
299
+ // numDays: num_days,
300
+ avgEventsPerUserPerDay: avg_events_per_user_per_day,
147
301
  numUsers: num_users,
148
302
  format: 'json', //csv or json
149
303
  region: "US",
@@ -159,7 +313,6 @@ const config = {
159
313
  isAnonymous: false,
160
314
  alsoInferFunnels: false,
161
315
  concurrency: 1,
162
- percentUsersBornInDataset: 25,
163
316
  events: [
164
317
  {
165
318
  event: "checkout",
@@ -167,7 +320,7 @@ const config = {
167
320
  properties: {
168
321
  currency: ["USD", "CAD", "EUR", "BTC", "ETH", "JPY"],
169
322
  coupon: weighChoices(["none", "none", "none", "none", "10%OFF", "20%OFF", "10%OFF", "20%OFF", "30%OFF", "40%OFF", "50%OFF"]),
170
- cart: makeProducts()
323
+ cart: makeProducts(),
171
324
  }
172
325
  },
173
326
  {
@@ -337,10 +490,31 @@ const config = {
337
490
  lookupTables: [],
338
491
  hook: function (record, type, meta) {
339
492
 
493
+ // Hook 7 (T2C): SIGNUP FLOW TIME-TO-CONVERT (funnel-post)
494
+ // Gold/platinum loyalty tier users complete the Signup Flow funnel
495
+ // 1.4x faster (factor 0.71); bronze users 1.3x slower (factor 1.3).
496
+ if (type === "funnel-post") {
497
+ const segment = meta?.profile?.loyalty_tier;
498
+ if (Array.isArray(record) && record.length > 1) {
499
+ const factor = (
500
+ segment === "gold" || segment === "platinum" ? 0.71 :
501
+ segment === "bronze" ? 1.3 :
502
+ 1.0
503
+ );
504
+ if (factor !== 1.0) {
505
+ for (let i = 1; i < record.length; i++) {
506
+ const prev = dayjs(record[i - 1].time);
507
+ const newGap = Math.round(dayjs(record[i].time).diff(prev) * factor);
508
+ record[i].time = prev.add(newGap, "milliseconds").toISOString();
509
+ }
510
+ }
511
+ }
512
+ }
513
+
340
514
  if (type === "event") {
341
- const NOW = dayjs();
342
- const DAY_SIGNUPS_IMPROVED = NOW.subtract(7, 'day');
343
- const DAY_WATCH_TIME_WENT_UP = NOW.subtract(30, 'day');
515
+ const datasetEnd = dayjs.unix(meta.datasetEnd);
516
+ const DAY_SIGNUPS_IMPROVED = datasetEnd.subtract(7, 'day');
517
+ const DAY_WATCH_TIME_WENT_UP = datasetEnd.subtract(30, 'day');
344
518
  const eventTime = dayjs(record.time);
345
519
 
346
520
  // unflattering 'items'
@@ -435,53 +609,27 @@ const config = {
435
609
  e.theme = profile.theme;
436
610
  });
437
611
 
438
- // big themes!
439
-
440
- // users who view items in the home and garden category churn more frequently
441
-
442
-
443
- // dark mode leads to faster purchase conversion
444
-
445
-
446
- // people who pay in bitcoin tend to buy more electronics and gadgets
447
-
448
-
449
- //custom themes purchase more:
450
- // const numCustomMode = record.filter(a => a.theme === 'custom').length;
451
- // const numLightMode = record.filter(a => a.theme === 'light').length;
452
- // const numDarkMode = record.filter(a => a.theme === 'dark').length;
453
- // if (numCustomMode > numLightMode || numCustomMode > numDarkMode) {
454
- // //triple their checkout events
455
- // const checkoutEvents = record.filter(a => a.event === 'checkout');
456
- // const newCheckouts = checkoutEvents.map(a => {
457
- // const randomInt = integer(-48, 48);
458
- // const newCheckout = {
459
- // ...a,
460
- // time: dayjs(a.time).add(randomInt, 'hour').toISOString(),
461
- // event: "checkout",
462
- // amount: a.amount * 2,
463
- // coupon: "50%OFF"
464
- // };
465
- // return newCheckout;
466
- // });
467
- // record.push(...newCheckouts);
468
- // }
469
-
470
- // //users who watch low quality videos churn more:
471
- // const loQuality = ["480p", "360p", "240p"];
472
- // const lowQualityWatches = record.filter(a => a.event === 'watch video' && loQuality.includes(a.quality));
473
- // const highQualityWatches = record.filter(a => a.event === 'watch video' && !loQuality.includes(a.quality));
474
- // if (lowQualityWatches.length > highQualityWatches.length) {
475
- // if (flip()) {
476
- // // find midpoint of records
477
- // const midpoint = Math.floor(record.length / 2);
478
- // record = record.slice(0, midpoint);
479
-
480
- // }
481
- // }
482
-
483
-
484
-
612
+ // Hook 6: View-Item Magic Number (behavioral, no flags)
613
+ // Users in 3-8 view-item sweet spot show ~25% higher cart amounts.
614
+ // Users >=9 are over-engaged window-shoppers; ~30% of their checkouts drop.
615
+ const viewItemCount = record.filter(e => e.event === 'view item').length;
616
+ if (viewItemCount >= 3 && viewItemCount <= 8) {
617
+ record.forEach(e => {
618
+ if (e.event === 'checkout' && Array.isArray(e.cart)) {
619
+ e.cart = e.cart.map(it => ({
620
+ ...it,
621
+ amount: typeof it.amount === 'number' ? Math.round(it.amount * 1.25) : it.amount,
622
+ total_value: typeof it.total_value === 'number' ? Math.round(it.total_value * 1.25) : it.total_value
623
+ }));
624
+ }
625
+ });
626
+ } else if (viewItemCount >= 9) {
627
+ for (let i = record.length - 1; i >= 0; i--) {
628
+ if (record[i].event === 'checkout' && chance.bool({ likelihood: 30 })) {
629
+ record.splice(i, 1);
630
+ }
631
+ }
632
+ }
485
633
 
486
634
  }
487
635