@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
@@ -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
  import * as v from "ak-tools";
6
6
 
7
7
  const SEED = "harness-sass";
@@ -10,7 +10,7 @@ const chance = u.initChance(SEED);
10
10
  const num_users = 5_000;
11
11
  const days = 100;
12
12
 
13
- /** @typedef {import("../types.js").Dungeon} Config */
13
+ /** @typedef {import("../../types").Dungeon} Config */
14
14
 
15
15
  /*
16
16
  * ═══════════════════════════════════════════════════════════════════════════════
@@ -268,10 +268,23 @@ const config = {
268
268
  hasAdSpend: false,
269
269
  percentUsersBornInDataset: 50,
270
270
  hasAvatar: true,
271
- batchSize: 2_500_000,
272
271
  concurrency: 1,
273
272
  writeToDisk: false,
274
- scdProps: {},
273
+ scdProps: {
274
+ primary_role: {
275
+ values: ["viewer", "editor", "admin", "owner"],
276
+ frequency: "month",
277
+ timing: "fuzzy",
278
+ max: 6
279
+ },
280
+ plan_tier: {
281
+ values: ["starter", "growth", "enterprise", "scale"],
282
+ frequency: "month",
283
+ timing: "fixed",
284
+ max: 6,
285
+ type: "company_id"
286
+ }
287
+ },
275
288
 
276
289
  funnels: [
277
290
  {
@@ -345,10 +358,11 @@ const config = {
345
358
  event: "service deployed",
346
359
  weight: 10,
347
360
  properties: {
348
- service_id: u.pickAWinner(serviceIds),
361
+ service_id: serviceIds,
349
362
  service_type: ["web_app", "api", "database", "cache", "queue", "ml_model"],
350
363
  environment: ["production", "staging", "dev"],
351
364
  cloud_provider: ["aws", "gcp", "azure"],
365
+ docs_informed: [false],
352
366
  }
353
367
  },
354
368
  {
@@ -363,49 +377,66 @@ const config = {
363
377
  event: "alert triggered",
364
378
  weight: 12,
365
379
  properties: {
366
- alert_id: u.pickAWinner(alertIds),
380
+ alert_id: alertIds,
367
381
  severity: ["info", "warning", "critical", "emergency"],
368
382
  alert_type: ["cpu", "memory", "latency", "error_rate", "disk", "network"],
369
- service_id: u.pickAWinner(serviceIds),
383
+ service_id: serviceIds,
384
+ }
385
+ },
386
+ {
387
+ event: "incident created",
388
+ weight: 1,
389
+ properties: {
390
+ escalation_level: ["P1", "P2"],
391
+ teams_paged: u.weighNumRange(1, 5),
392
+ incident_id: () => `inc_${v.uid(8)}`,
393
+ original_severity: ["critical", "emergency"],
394
+ original_alert_type: ["cpu", "memory", "latency", "error_rate", "disk", "network"],
395
+ service_id: serviceIds,
396
+ auto_escalated: [true],
370
397
  }
371
398
  },
372
399
  {
373
400
  event: "alert acknowledged",
374
401
  weight: 8,
375
402
  properties: {
376
- alert_id: u.pickAWinner(alertIds),
403
+ alert_id: alertIds,
377
404
  response_time_mins: u.weighNumRange(1, 120),
378
405
  acknowledged_by_role: ["engineer", "sre", "manager", "oncall"],
406
+ integrated_team: [false],
379
407
  }
380
408
  },
381
409
  {
382
410
  event: "alert resolved",
383
411
  weight: 7,
384
412
  properties: {
385
- alert_id: u.pickAWinner(alertIds),
413
+ alert_id: alertIds,
386
414
  resolution_time_mins: u.weighNumRange(5, 1440),
387
415
  root_cause: ["config_change", "capacity", "bug", "dependency", "network"],
416
+ integrated_team: [false],
388
417
  }
389
418
  },
390
419
  {
391
420
  event: "deployment pipeline run",
392
421
  weight: 9,
393
422
  properties: {
394
- pipeline_id: u.pickAWinner(pipelineIds),
423
+ pipeline_id: pipelineIds,
395
424
  status: ["success", "failed", "cancelled"],
396
425
  duration_sec: u.weighNumRange(30, 1800),
397
426
  commit_count: u.weighNumRange(1, 20),
427
+ recovery_deployment: [false],
398
428
  }
399
429
  },
400
430
  {
401
431
  event: "infrastructure scaled",
402
432
  weight: 5,
403
433
  properties: {
404
- service_id: u.pickAWinner(serviceIds),
405
- scale_direction: u.pickAWinner(["up", "down"], 0.15),
434
+ service_id: serviceIds,
435
+ scale_direction: ["down", "down", "down", "down", "down", "down", "up"],
406
436
  previous_capacity: u.weighNumRange(1, 100),
407
437
  new_capacity: u.weighNumRange(1, 100),
408
- auto_scaled: u.pickAWinner([true, false], 0.15),
438
+ auto_scaled: [false, false, false, false, false, false, true],
439
+ cost_reaction: [false],
409
440
  }
410
441
  },
411
442
  {
@@ -415,6 +446,8 @@ const config = {
415
446
  report_period: ["daily", "weekly", "monthly"],
416
447
  total_cost: u.weighNumRange(100, 50000),
417
448
  cost_change_percent: u.weighNumRange(-30, 50),
449
+ cost_alert: [false],
450
+ budget_exceeded: [false],
418
451
  }
419
452
  },
420
453
  {
@@ -423,6 +456,8 @@ const config = {
423
456
  properties: {
424
457
  role: ["admin", "editor", "viewer", "billing"],
425
458
  invitation_method: ["email", "sso", "slack"],
459
+ quarter_end_push: [false],
460
+ duplicate_invite: [false],
426
461
  }
427
462
  },
428
463
  {
@@ -446,9 +481,9 @@ const config = {
446
481
  event: "runbook executed",
447
482
  weight: 3,
448
483
  properties: {
449
- runbook_id: u.pickAWinner(runbookIds),
484
+ runbook_id: runbookIds,
450
485
  trigger: ["manual", "automated", "alert_triggered"],
451
- success: u.pickAWinner([true, false], 0.15),
486
+ success: [false, false, false, false, false, false, true],
452
487
  }
453
488
  },
454
489
  {
@@ -457,6 +492,7 @@ const config = {
457
492
  properties: {
458
493
  event_type: ["invoice_generated", "payment_received", "payment_failed", "plan_upgraded", "plan_downgraded"],
459
494
  amount: u.weighNumRange(99, 25000),
495
+ quarter_end_push: [false],
460
496
  }
461
497
  },
462
498
  {
@@ -475,7 +511,7 @@ const config = {
475
511
  endpoint: ["/deploy", "/status", "/metrics", "/alerts", "/config", "/billing"],
476
512
  method: ["GET", "POST", "PUT", "DELETE"],
477
513
  response_time_ms: u.weighNumRange(10, 5000),
478
- status_code: u.pickAWinner([200, 201, 400, 401, 403, 500, 503]),
514
+ status_code: [200, 201, 400, 401, 403, 500, 503],
479
515
  }
480
516
  },
481
517
  {
@@ -491,21 +527,26 @@ const config = {
491
527
  weight: 4,
492
528
  properties: {
493
529
  flag_name: () => `flag_${chance.word()}`,
494
- new_state: u.pickAWinner(["enabled", "disabled"], 0.15),
530
+ new_state: ["disabled", "disabled", "disabled", "disabled", "disabled", "disabled", "enabled"],
495
531
  environment: ["production", "staging", "dev"],
496
532
  }
497
533
  },
498
534
  ],
499
535
 
500
536
  superProps: {
501
- plan_tier: u.pickAWinner(["free", "free", "team", "team", "business", "enterprise"]),
537
+ plan_tier: ["free", "free", "team", "team", "business", "enterprise"],
502
538
  cloud_provider: ["aws", "gcp", "azure", "multi_cloud"],
503
539
  },
504
540
 
505
541
  userProps: {
506
- company_size: u.pickAWinner(["startup", "startup", "smb", "mid_market", "enterprise"]),
542
+ company_size: ["startup", "startup", "smb", "mid_market", "enterprise"],
507
543
  primary_role: ["engineer", "sre", "devops", "manager", "executive"],
508
544
  team_name: ["Platform", "Backend", "Frontend", "Data", "Security", "Infrastructure"],
545
+ churned_account: [false],
546
+ seat_count: [1],
547
+ annual_contract_value: [0],
548
+ customer_success_manager: [false],
549
+ customer_health_score: u.weighNumRange(1, 100),
509
550
  },
510
551
 
511
552
  groupKeys: [
@@ -564,9 +605,8 @@ const config = {
564
605
  // 50% of the time duplicate the invite event (hiring push)
565
606
  if (chance.bool({ likelihood: 50 })) {
566
607
  return {
567
- event: "team member invited",
608
+ ...record,
568
609
  time: EVENT_TIME.add(chance.integer({ min: 1, max: 60 }), "minutes").toISOString(),
569
- user_id: record.user_id,
570
610
  role: chance.pickone(["editor", "viewer"]),
571
611
  invitation_method: chance.pickone(["email", "sso", "slack"]),
572
612
  quarter_end_push: true,
@@ -589,15 +629,13 @@ const config = {
589
629
  if ((severity === "critical" || severity === "emergency") && chance.bool({ likelihood: 30 })) {
590
630
  // REPLACE the event entirely with an "incident created" event
591
631
  return {
632
+ ...record,
592
633
  event: "incident created",
593
- time: record.time,
594
- user_id: record.user_id,
595
634
  escalation_level: chance.pickone(["P1", "P2"]),
596
635
  teams_paged: chance.integer({ min: 1, max: 5 }),
597
636
  incident_id: `inc_${v.uid(8)}`,
598
637
  original_severity: severity,
599
638
  original_alert_type: record.alert_type,
600
- service_id: record.service_id,
601
639
  auto_escalated: true,
602
640
  };
603
641
  }
@@ -738,10 +776,11 @@ const config = {
738
776
  if (bestPracticesCount >= 3) {
739
777
  const extraDeploys = chance.integer({ min: 2, max: 3 });
740
778
  const lastEvent = userEvents[userEvents.length - 1];
741
- if (lastEvent) {
779
+ const deployTemplate = userEvents.find(e => e.event === "service deployed");
780
+ if (lastEvent && deployTemplate) {
742
781
  for (let i = 0; i < extraDeploys; i++) {
743
782
  const deployEvent = {
744
- event: "service deployed",
783
+ ...deployTemplate,
745
784
  time: dayjs(lastEvent.time).add(chance.integer({ min: 1, max: 48 }), "hours").toISOString(),
746
785
  user_id: lastEvent.user_id,
747
786
  service_id: chance.pickone(serviceIds),