@ak--47/dungeon-master 1.0.0 → 1.2.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.
Files changed (104) hide show
  1. package/README.md +7 -7
  2. package/dungeons/technical/ad-spend-schema.json +128 -0
  3. package/dungeons/technical/ad-spend.js +116 -0
  4. package/dungeons/technical/anonymous-users-schema.json +92 -0
  5. package/dungeons/technical/anonymous-users.js +102 -0
  6. package/dungeons/technical/array-of-object-lookup-schema.json +191 -0
  7. package/dungeons/{array-of-object-lookup.js → technical/array-of-object-lookup.js} +12 -5
  8. package/dungeons/technical/experiments-schema.json +203 -0
  9. package/dungeons/technical/experiments.js +168 -0
  10. package/dungeons/technical/foobar-schema.json +362 -0
  11. package/dungeons/{foobar.js → technical/foobar.js} +3 -3
  12. package/dungeons/technical/group-analytics-schema.json +241 -0
  13. package/dungeons/technical/group-analytics.js +151 -0
  14. package/dungeons/technical/mirror-strategies-schema.json +84 -0
  15. package/dungeons/technical/mirror-strategies.js +126 -0
  16. package/dungeons/technical/nested-objects-schema.json +145 -0
  17. package/dungeons/technical/nested-objects.js +207 -0
  18. package/dungeons/technical/retention-cadence-schema.json +37 -0
  19. package/dungeons/{retention-cadence.js → technical/retention-cadence.js} +2 -3
  20. package/dungeons/technical/sanity-schema.json +185 -0
  21. package/dungeons/{sanity.js → technical/sanity.js} +4 -2
  22. package/dungeons/technical/scale-test-schema.json +70 -0
  23. package/dungeons/technical/scale-test.js +90 -0
  24. package/dungeons/technical/scd-schema.json +467 -0
  25. package/dungeons/{scd.js → technical/scd.js} +20 -10
  26. package/dungeons/technical/simple-schema.json +362 -0
  27. package/dungeons/{simple.js → technical/simple.js} +7 -7
  28. package/dungeons/technical/simplest-schema.json +724 -0
  29. package/dungeons/{simplest.js → technical/simplest.js} +7 -7
  30. package/dungeons/technical/text-generation-schema.json +1062 -0
  31. package/dungeons/{text-generation.js → technical/text-generation.js} +24 -11
  32. package/dungeons/vertical/community-schema.json +579 -0
  33. package/dungeons/vertical/community.js +794 -0
  34. package/dungeons/vertical/devtools-schema.json +601 -0
  35. package/dungeons/vertical/devtools.js +843 -0
  36. package/dungeons/vertical/ecommerce-schema.json +604 -0
  37. package/dungeons/{ecommerce.js → vertical/ecommerce.js} +43 -5
  38. package/dungeons/vertical/education-schema.json +5686 -0
  39. package/dungeons/{education.js → vertical/education.js} +70 -39
  40. package/dungeons/vertical/fintech-schema.json +630 -0
  41. package/dungeons/{fintech.js → vertical/fintech.js} +107 -56
  42. package/dungeons/vertical/fitness-schema.json +530 -0
  43. package/dungeons/vertical/fitness.js +808 -0
  44. package/dungeons/vertical/food-delivery-schema.json +36728 -0
  45. package/dungeons/{food.js → vertical/food-delivery.js} +67 -26
  46. package/dungeons/vertical/gaming-schema.json +438 -0
  47. package/dungeons/{gaming.js → vertical/gaming.js} +29 -16
  48. package/dungeons/vertical/healthcare-schema.json +549 -0
  49. package/dungeons/vertical/healthcare.js +775 -0
  50. package/dungeons/vertical/insurance-application-schema.json +485 -0
  51. package/dungeons/{insurance-application.js → vertical/insurance-application.js} +41 -31
  52. package/dungeons/vertical/logistics-schema.json +574 -0
  53. package/dungeons/vertical/logistics.js +799 -0
  54. package/dungeons/vertical/marketplace-schema.json +533 -0
  55. package/dungeons/vertical/marketplace.js +850 -0
  56. package/dungeons/vertical/media-schema.json +4749 -0
  57. package/dungeons/{media.js → vertical/media.js} +103 -19
  58. package/dungeons/vertical/rpg-schema.json +2491 -0
  59. package/dungeons/{rpg.js → vertical/rpg.js} +87 -60
  60. package/dungeons/vertical/sass-schema.json +3128 -0
  61. package/dungeons/{sass.js → vertical/sass.js} +65 -26
  62. package/dungeons/vertical/social-schema.json +620 -0
  63. package/dungeons/{social.js → vertical/social.js} +76 -17
  64. package/dungeons/vertical/travel-schema.json +580 -0
  65. package/dungeons/vertical/travel.js +742 -0
  66. package/index.js +20 -16
  67. package/lib/core/config-validator.js +286 -1
  68. package/lib/core/context.js +16 -5
  69. package/lib/core/storage.js +2 -0
  70. package/lib/generators/adspend.js +3 -3
  71. package/lib/generators/events.js +141 -14
  72. package/lib/generators/funnels.js +67 -7
  73. package/lib/generators/text.js +2 -2
  74. package/lib/orchestrators/user-loop.js +444 -22
  75. package/lib/templates/soup-presets.js +2 -2
  76. package/lib/utils/utils.js +4 -5
  77. package/package.json +4 -3
  78. package/scripts/dungeon-to-json.mjs +163 -0
  79. package/scripts/extract-dungeon-schema.mjs +343 -0
  80. package/scripts/json-to-dungeon.mjs +200 -0
  81. package/scripts/run-dungeon.mjs +76 -0
  82. package/scripts/run-many.mjs +118 -0
  83. package/scripts/verify-runner.mjs +42 -0
  84. package/types.d.ts +316 -1
  85. package/dungeons/array-of-object-lookup-schema.json +0 -327
  86. package/dungeons/ecommerce-schema.json +0 -462
  87. package/dungeons/education-schema.json +0 -2409
  88. package/dungeons/fintech-schema.json +0 -14034
  89. package/dungeons/foobar-schema.json +0 -403
  90. package/dungeons/food-delivery-schema.json +0 -192
  91. package/dungeons/food-delivery.js +0 -602
  92. package/dungeons/food-schema.json +0 -1152
  93. package/dungeons/gaming-schema.json +0 -1270
  94. package/dungeons/insurance-application-schema.json +0 -204
  95. package/dungeons/media-schema.json +0 -906
  96. package/dungeons/retention-cadence-schema.json +0 -78
  97. package/dungeons/rpg-schema.json +0 -4526
  98. package/dungeons/sanity-schema.json +0 -255
  99. package/dungeons/sass-schema.json +0 -1291
  100. package/dungeons/scd-schema.json +0 -919
  101. package/dungeons/simple-schema.json +0 -608
  102. package/dungeons/simplest-schema.json +0 -1418
  103. package/dungeons/social-schema.json +0 -1118
  104. package/dungeons/text-generation-schema.json +0 -3096
@@ -0,0 +1,485 @@
1
+ {
2
+ "events": [
3
+ {
4
+ "event": "account created",
5
+ "isFirstEvent": true,
6
+ "properties": {
7
+ "signup_source": [
8
+ "web",
9
+ "mobile",
10
+ "agent_referral",
11
+ "partner"
12
+ ],
13
+ "account_type": [
14
+ "individual",
15
+ "family",
16
+ "business"
17
+ ]
18
+ }
19
+ },
20
+ {
21
+ "event": "page viewed",
22
+ "weight": 10,
23
+ "properties": {
24
+ "page_name": [
25
+ "home",
26
+ "quotes",
27
+ "coverage_options",
28
+ "claims",
29
+ "faq",
30
+ "profile",
31
+ "payment",
32
+ "documents"
33
+ ],
34
+ "referrer": [
35
+ "direct",
36
+ "google",
37
+ "email",
38
+ "social_media"
39
+ ]
40
+ }
41
+ },
42
+ {
43
+ "event": "quote requested",
44
+ "weight": 5,
45
+ "properties": {
46
+ "coverage_level": [
47
+ "basic",
48
+ "standard",
49
+ "premium"
50
+ ],
51
+ "deductible": {
52
+ "$range": [
53
+ 443,
54
+ 4473
55
+ ]
56
+ }
57
+ }
58
+ },
59
+ {
60
+ "event": "quote received",
61
+ "weight": 4,
62
+ "properties": {
63
+ "monthly_premium": {
64
+ "$range": [
65
+ 164,
66
+ 651
67
+ ]
68
+ },
69
+ "coverage_amount": {
70
+ "$range": [
71
+ 79151,
72
+ 430388
73
+ ]
74
+ },
75
+ "quote_comparison_count": [
76
+ 2,
77
+ 4
78
+ ]
79
+ }
80
+ },
81
+ {
82
+ "event": "application started",
83
+ "weight": 4,
84
+ "properties": {
85
+ "coverage_level": [
86
+ "basic",
87
+ "standard",
88
+ "premium"
89
+ ],
90
+ "estimated_premium": {
91
+ "$range": [
92
+ 175,
93
+ 646
94
+ ]
95
+ }
96
+ }
97
+ },
98
+ {
99
+ "event": "application step completed",
100
+ "weight": 6,
101
+ "properties": {
102
+ "step_name": [
103
+ "personal_info",
104
+ "coverage_selection",
105
+ "medical_history",
106
+ "vehicle_info",
107
+ "beneficiary",
108
+ "review"
109
+ ],
110
+ "step_number": {
111
+ "$range": [
112
+ 1,
113
+ 5
114
+ ]
115
+ },
116
+ "time_on_step_sec": {
117
+ "$range": [
118
+ 121,
119
+ 491
120
+ ]
121
+ }
122
+ }
123
+ },
124
+ {
125
+ "event": "document uploaded",
126
+ "weight": 3,
127
+ "properties": {
128
+ "document_type": [
129
+ "drivers_license",
130
+ "proof_of_address",
131
+ "vehicle_registration",
132
+ "medical_records",
133
+ "property_photos"
134
+ ],
135
+ "file_size_kb": {
136
+ "$range": [
137
+ 552,
138
+ 4345
139
+ ]
140
+ }
141
+ }
142
+ },
143
+ {
144
+ "event": "application submitted",
145
+ "weight": 3,
146
+ "properties": {
147
+ "documents_attached": [
148
+ 4
149
+ ],
150
+ "application_time_min": {
151
+ "$range": [
152
+ 17,
153
+ 47
154
+ ]
155
+ }
156
+ }
157
+ },
158
+ {
159
+ "event": "application approved",
160
+ "weight": 2,
161
+ "properties": {
162
+ "approved_premium": {
163
+ "$range": [
164
+ 130,
165
+ 648
166
+ ]
167
+ },
168
+ "approval_time_hours": {
169
+ "$range": [
170
+ 8,
171
+ 61
172
+ ]
173
+ }
174
+ }
175
+ },
176
+ {
177
+ "event": "policy activated",
178
+ "weight": 2,
179
+ "properties": {
180
+ "policy_term_months": [
181
+ 6,
182
+ 12,
183
+ 24
184
+ ],
185
+ "effective_date_offset_days": [
186
+ 10,
187
+ 23,
188
+ 21,
189
+ 22,
190
+ 19,
191
+ 14,
192
+ 18
193
+ ]
194
+ }
195
+ },
196
+ {
197
+ "event": "claim filed",
198
+ "weight": 2,
199
+ "properties": {
200
+ "claim_type": [
201
+ "collision",
202
+ "theft",
203
+ "water_damage",
204
+ "fire",
205
+ "medical",
206
+ "liability"
207
+ ],
208
+ "estimated_amount": {
209
+ "$range": [
210
+ 5885,
211
+ 43341
212
+ ]
213
+ }
214
+ }
215
+ },
216
+ {
217
+ "event": "claim status checked",
218
+ "weight": 4,
219
+ "properties": {
220
+ "claim_status": [
221
+ "submitted",
222
+ "under_review",
223
+ "approved",
224
+ "denied",
225
+ "payment_pending"
226
+ ],
227
+ "days_since_filed": [
228
+ 48,
229
+ 20,
230
+ 42,
231
+ 12,
232
+ 35,
233
+ 27,
234
+ 47,
235
+ 21
236
+ ]
237
+ }
238
+ },
239
+ {
240
+ "event": "payment made",
241
+ "weight": 5,
242
+ "properties": {
243
+ "payment_method": [
244
+ "credit_card",
245
+ "bank_transfer",
246
+ "auto_pay",
247
+ "check"
248
+ ],
249
+ "amount": {
250
+ "$range": [
251
+ 181,
252
+ 677
253
+ ]
254
+ },
255
+ "payment_status": [
256
+ "success",
257
+ "failed"
258
+ ]
259
+ }
260
+ },
261
+ {
262
+ "event": "support ticket created",
263
+ "weight": 4,
264
+ "properties": {
265
+ "issue_category": [
266
+ "billing",
267
+ "claims",
268
+ "coverage",
269
+ "technical",
270
+ "policy_change"
271
+ ],
272
+ "priority": [
273
+ "low",
274
+ "medium",
275
+ "high"
276
+ ],
277
+ "channel": [
278
+ "chat",
279
+ "phone",
280
+ "email",
281
+ "web_form"
282
+ ],
283
+ "pre_release_bug": [
284
+ false
285
+ ]
286
+ }
287
+ },
288
+ {
289
+ "event": "support ticket resolved",
290
+ "weight": 3,
291
+ "properties": {
292
+ "resolution_type": [
293
+ "self_service",
294
+ "agent_assisted",
295
+ "escalated",
296
+ "auto_resolved"
297
+ ],
298
+ "satisfaction_score": [
299
+ 3,
300
+ 2,
301
+ 4
302
+ ],
303
+ "resolution_time_hours": [
304
+ 53,
305
+ 50,
306
+ 57,
307
+ 52,
308
+ 20,
309
+ 54,
310
+ 36,
311
+ 17
312
+ ]
313
+ }
314
+ },
315
+ {
316
+ "event": "coverage reviewed",
317
+ "weight": 4,
318
+ "properties": {
319
+ "current_premium": {
320
+ "$range": [
321
+ 183,
322
+ 666
323
+ ]
324
+ },
325
+ "coverage_adequate": [
326
+ true,
327
+ false
328
+ ]
329
+ }
330
+ },
331
+ {
332
+ "event": "profile updated",
333
+ "weight": 2,
334
+ "properties": {
335
+ "field_updated": [
336
+ "address",
337
+ "phone",
338
+ "email",
339
+ "beneficiary",
340
+ "payment_method",
341
+ "vehicle_info"
342
+ ]
343
+ }
344
+ },
345
+ {
346
+ "event": "renewal completed",
347
+ "weight": 2,
348
+ "properties": {
349
+ "renewal_premium": {
350
+ "$range": [
351
+ 162,
352
+ 651
353
+ ]
354
+ },
355
+ "premium_change_pct": [
356
+ 14,
357
+ -4,
358
+ 6
359
+ ],
360
+ "auto_renewed": [
361
+ true,
362
+ false
363
+ ]
364
+ }
365
+ }
366
+ ],
367
+ "funnels": [
368
+ {
369
+ "sequence": [
370
+ "account created",
371
+ "page viewed",
372
+ "quote requested"
373
+ ],
374
+ "name": "Onboarding",
375
+ "isFirstFunnel": true,
376
+ "conversionRate": 85,
377
+ "timeToConvert": 0.5
378
+ },
379
+ {
380
+ "sequence": [
381
+ "application started",
382
+ "application step completed",
383
+ "document uploaded",
384
+ "application submitted"
385
+ ],
386
+ "name": "Application Completion",
387
+ "conversionRate": 60,
388
+ "timeToConvert": 48,
389
+ "weight": 4
390
+ },
391
+ {
392
+ "sequence": [
393
+ "application submitted",
394
+ "application approved",
395
+ "policy activated"
396
+ ],
397
+ "name": "Application Approval",
398
+ "conversionRate": 70,
399
+ "timeToConvert": 72,
400
+ "weight": 3
401
+ },
402
+ {
403
+ "sequence": [
404
+ "claim filed",
405
+ "claim status checked",
406
+ "support ticket created"
407
+ ],
408
+ "name": "Claims Process",
409
+ "conversionRate": 50,
410
+ "timeToConvert": 24,
411
+ "weight": 2
412
+ },
413
+ {
414
+ "sequence": [
415
+ "coverage reviewed",
416
+ "payment made",
417
+ "renewal completed"
418
+ ],
419
+ "name": "Policy Renewal",
420
+ "conversionRate": 65,
421
+ "timeToConvert": 72,
422
+ "weight": 3
423
+ }
424
+ ],
425
+ "superProps": {
426
+ "platform": [
427
+ "web",
428
+ "ios",
429
+ "android"
430
+ ],
431
+ "insurance_type": [
432
+ "auto",
433
+ "home",
434
+ "life",
435
+ "health",
436
+ "renters"
437
+ ],
438
+ "app_version": [
439
+ "2.10"
440
+ ]
441
+ },
442
+ "userProps": {
443
+ "age_range": [
444
+ "18-25",
445
+ "26-35",
446
+ "36-45",
447
+ "46-55",
448
+ "56-65",
449
+ "65+"
450
+ ],
451
+ "risk_profile": [
452
+ "low",
453
+ "medium",
454
+ "high"
455
+ ],
456
+ "policy_count": [
457
+ 3
458
+ ],
459
+ "lifetime_premium": {
460
+ "$range": [
461
+ 8131,
462
+ 43291
463
+ ]
464
+ },
465
+ "preferred_contact": [
466
+ "email",
467
+ "phone",
468
+ "app_notification"
469
+ ]
470
+ },
471
+ "scdProps": {
472
+ "policy_status": {
473
+ "type": "user",
474
+ "frequency": "month",
475
+ "timing": "fuzzy",
476
+ "max": 8,
477
+ "values": [
478
+ "pending",
479
+ "active",
480
+ "lapsed",
481
+ "renewed"
482
+ ]
483
+ }
484
+ }
485
+ }
@@ -1,7 +1,7 @@
1
1
  import dayjs from "dayjs";
2
2
  import utc from "dayjs/plugin/utc.js";
3
3
  import "dotenv/config";
4
- import * as u from "../lib/utils/utils.js";
4
+ import * as u from "../../lib/utils/utils.js";
5
5
 
6
6
  const SEED = "dm4-insurance";
7
7
  dayjs.extend(utc);
@@ -9,7 +9,7 @@ const chance = u.initChance(SEED);
9
9
  const num_users = 5_000;
10
10
  const days = 100;
11
11
 
12
- /** @typedef {import("../types").Dungeon} Config */
12
+ /** @typedef {import("../../types").Dungeon} Config */
13
13
 
14
14
  /*
15
15
  * ===================================================================
@@ -49,9 +49,11 @@ const days = 100;
49
49
  * ===================================================================
50
50
  *
51
51
  * -------------------------------------------------------------------
52
- * 1. VERSION STAMPING (event hook)
52
+ * 1. VERSION STAMPING (everything hook)
53
53
  * -------------------------------------------------------------------
54
- * Every event gets a deterministic app_version based on its timestamp.
54
+ * Every event gets a deterministic app_version based on its final
55
+ * timestamp. Uses the everything hook (not event hook) because funnel
56
+ * events adjust their time AFTER the event hook runs.
55
57
  * All users shift simultaneously on release dates:
56
58
  * - Days 0-30: v2.10
57
59
  * - Days 30-60: v2.11
@@ -151,11 +153,17 @@ const config = {
151
153
  hasAdSpend: false,
152
154
  percentUsersBornInDataset: 35,
153
155
  hasAvatar: true,
154
- batchSize: 2_500_000,
155
156
  concurrency: 1,
156
157
  writeToDisk: false,
157
158
 
158
- scdProps: {},
159
+ scdProps: {
160
+ policy_status: {
161
+ values: ["pending", "active", "lapsed", "renewed"],
162
+ frequency: "month",
163
+ timing: "fuzzy",
164
+ max: 8
165
+ }
166
+ },
159
167
  mirrorProps: {},
160
168
  lookupTables: [],
161
169
 
@@ -317,6 +325,7 @@ const config = {
317
325
  ],
318
326
  priority: ["low", "medium", "medium", "high"],
319
327
  channel: ["chat", "phone", "email", "web_form"],
328
+ pre_release_bug: [false],
320
329
  },
321
330
  },
322
331
  {
@@ -424,6 +433,7 @@ const config = {
424
433
  superProps: {
425
434
  platform: ["web", "ios", "android"],
426
435
  insurance_type: ["auto", "home", "life", "health", "renters"],
436
+ app_version: ["2.10"],
427
437
  },
428
438
 
429
439
  // ── User Props (set once per user) ──
@@ -441,9 +451,11 @@ const config = {
441
451
  *
442
452
  * This hook function creates 3 deliberate patterns in the data:
443
453
  *
444
- * 1. VERSION STAMPING (event): Every event gets a deterministic app_version
445
- * based on its timestamp. v2.10 → v2.11 → v2.12 → v2.13.
446
- * All users shift simultaneously on release dates.
454
+ * 1. VERSION STAMPING (everything): Every event gets a deterministic app_version
455
+ * based on its final timestamp. v2.10 → v2.11 → v2.12 → v2.13.
456
+ * All users shift simultaneously on release dates. Uses the everything
457
+ * hook (not event hook) because funnel events adjust time after the
458
+ * event hook runs.
447
459
  *
448
460
  * 2. SUPPORT TICKET VOLUME (everything): Pre-v2.13 period has inflated
449
461
  * support ticket volume (2-3 extra tickets per user with bug-related
@@ -457,32 +469,30 @@ const config = {
457
469
  */
458
470
  hook: function (record, type, meta) {
459
471
  // =============================================================
460
- // Hook #1: VERSION STAMPING (event)
461
- // Deterministic app_version on every event based on timestamp.
462
- // v2.10 (days 0-30) v2.11 (30-60) → v2.12 (60-90) → v2.13 (last 10 days)
463
- // =============================================================
464
- if (type === "event") {
465
- const eventTime = dayjs(record.time);
466
-
467
- if (eventTime.isBefore(V211_DATE)) {
468
- record.app_version = "2.10";
469
- } else if (eventTime.isBefore(V212_DATE)) {
470
- record.app_version = "2.11";
471
- } else if (eventTime.isBefore(V213_DATE)) {
472
- record.app_version = "2.12";
473
- } else {
474
- record.app_version = "2.13";
475
- }
476
- }
477
-
478
- // =============================================================
479
- // Hook #2 & #3: SUPPORT TICKET VOLUME + APPLICATION CONVERSION
480
- // (everything)
472
+ // Hooks #1-#3 all run in the "everything" hook so that version
473
+ // stamping sees final timestamps (funnel events adjust time
474
+ // AFTER the event hook runs).
481
475
  // =============================================================
482
476
  if (type === "everything") {
483
477
  const userEvents = record;
484
478
  if (userEvents.length === 0) return record;
485
479
 
480
+ // ─── Hook #1: VERSION STAMPING ───
481
+ // Deterministic app_version on every event based on its final timestamp.
482
+ // v2.10 (days 0-30) → v2.11 (30-60) → v2.12 (60-90) → v2.13 (last 10 days)
483
+ for (const evt of userEvents) {
484
+ const eventTime = dayjs(evt.time);
485
+ if (eventTime.isBefore(V211_DATE)) {
486
+ evt.app_version = "2.10";
487
+ } else if (eventTime.isBefore(V212_DATE)) {
488
+ evt.app_version = "2.11";
489
+ } else if (eventTime.isBefore(V213_DATE)) {
490
+ evt.app_version = "2.12";
491
+ } else {
492
+ evt.app_version = "2.13";
493
+ }
494
+ }
495
+
486
496
  // Find a user_id from any existing event
487
497
  const userId =
488
498
  userEvents.find((e) => e.user_id)?.user_id ||
@@ -531,7 +541,7 @@ const config = {
531
541
  }
532
542
 
533
543
  userEvents.push({
534
- event: "support ticket created",
544
+ ...sourceTicket,
535
545
  time: newTime.toISOString(),
536
546
  user_id: userId,
537
547
  app_version: injectedVersion,