@ak--47/dungeon-master 1.5.3 → 1.6.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 (146) hide show
  1. package/.claude/skills/analyze-soup/SKILL.md +21 -12
  2. package/.claude/skills/create-dungeon/SKILL.md +65 -5
  3. package/.claude/skills/create-project/SKILL.md +96 -0
  4. package/.claude/skills/create-project/provision.mjs +336 -0
  5. package/.claude/skills/verify-dungeon/SKILL.md +56 -25
  6. package/.claude/skills/verify-dungeon/references/counting-semantics.md +26 -6
  7. package/.claude/skills/verify-dungeon/references/report-format.md +14 -8
  8. package/.claude/skills/write-hooks/SKILL.md +156 -18
  9. package/CHANGELOG.md +211 -0
  10. package/HOOKS.md +566 -112
  11. package/README.md +28 -9
  12. package/docs/guides/1.3.0-upgrade-guide.md +262 -0
  13. package/docs/guides/1.3.1-upgrade-guide.md +328 -0
  14. package/docs/guides/1.4.0-upgrade-guide.md +130 -0
  15. package/docs/guides/1.4.1-upgrade-guide.md +125 -0
  16. package/docs/guides/1.4.3-upgrade-guide.md +200 -0
  17. package/docs/guides/1.4.4-upgrade-guide.md +95 -0
  18. package/docs/guides/1.5.0-upgrade-guide.md +426 -0
  19. package/docs/guides/1.5.1-upgrade-guide.md +178 -0
  20. package/docs/guides/1.5.3-upgrade-guide.md +117 -0
  21. package/docs/guides/1.6.0-upgrade-guide.md +204 -0
  22. package/dungeons/technical/stories-verify.js +152 -0
  23. package/dungeons/vertical/README.md +154 -0
  24. package/dungeons/vertical/ai-platform/ai-platform.js +1424 -0
  25. package/dungeons/vertical/ai-platform/ai-platform.sql +184 -0
  26. package/dungeons/vertical/ai-platform/ai-platform.verify.mjs +71 -0
  27. package/dungeons/vertical/community/community.js +1589 -0
  28. package/dungeons/vertical/community/community.sql +216 -0
  29. package/dungeons/vertical/community/community.verify.mjs +72 -0
  30. package/dungeons/vertical/crypto/crypto.js +1483 -0
  31. package/dungeons/vertical/crypto/crypto.sql +194 -0
  32. package/dungeons/vertical/crypto/crypto.verify.mjs +78 -0
  33. package/dungeons/vertical/dating/dating.js +1540 -0
  34. package/dungeons/vertical/dating/dating.sql +288 -0
  35. package/dungeons/vertical/dating/dating.verify.mjs +72 -0
  36. package/dungeons/vertical/devtools/devtools.js +1524 -0
  37. package/dungeons/vertical/devtools/devtools.sql +161 -0
  38. package/dungeons/vertical/devtools/devtools.verify.mjs +73 -0
  39. package/dungeons/vertical/ecommerce/ecommerce.js +1480 -0
  40. package/dungeons/vertical/ecommerce/ecommerce.sql +218 -0
  41. package/dungeons/vertical/ecommerce/ecommerce.verify.mjs +70 -0
  42. package/dungeons/vertical/education/education.js +1763 -0
  43. package/dungeons/vertical/education/education.sql +243 -0
  44. package/dungeons/vertical/education/education.verify.mjs +75 -0
  45. package/dungeons/vertical/fintech/fintech.js +1410 -0
  46. package/dungeons/vertical/fintech/fintech.sql +175 -0
  47. package/dungeons/vertical/fintech/fintech.verify.mjs +70 -0
  48. package/dungeons/vertical/fitness/fitness.js +1495 -0
  49. package/dungeons/vertical/fitness/fitness.sql +206 -0
  50. package/dungeons/vertical/fitness/fitness.verify.mjs +71 -0
  51. package/dungeons/vertical/food-delivery/food-delivery.js +1641 -0
  52. package/dungeons/vertical/food-delivery/food-delivery.sql +183 -0
  53. package/dungeons/vertical/food-delivery/food-delivery.verify.mjs +75 -0
  54. package/dungeons/vertical/gaming/gaming.js +1741 -0
  55. package/dungeons/vertical/gaming/gaming.sql +249 -0
  56. package/dungeons/vertical/gaming/gaming.verify.mjs +70 -0
  57. package/dungeons/vertical/healthcare/healthcare.js +1488 -0
  58. package/dungeons/vertical/healthcare/healthcare.sql +193 -0
  59. package/dungeons/vertical/healthcare/healthcare.verify.mjs +72 -0
  60. package/dungeons/vertical/insurance-application/insurance-application.js +1852 -0
  61. package/dungeons/vertical/insurance-application/insurance-application.sql +174 -0
  62. package/dungeons/vertical/insurance-application/insurance-application.verify.mjs +74 -0
  63. package/dungeons/vertical/logistics/logistics.js +1541 -0
  64. package/dungeons/vertical/logistics/logistics.sql +205 -0
  65. package/dungeons/vertical/logistics/logistics.verify.mjs +73 -0
  66. package/dungeons/vertical/marketplace/marketplace.js +1438 -0
  67. package/dungeons/vertical/marketplace/marketplace.sql +148 -0
  68. package/dungeons/vertical/marketplace/marketplace.verify.mjs +74 -0
  69. package/dungeons/vertical/{media.js → media/media.js} +557 -58
  70. package/dungeons/vertical/media/media.sql +173 -0
  71. package/dungeons/vertical/media/media.verify.mjs +74 -0
  72. package/dungeons/vertical/real-estate/real-estate.js +1629 -0
  73. package/dungeons/vertical/real-estate/real-estate.sql +167 -0
  74. package/dungeons/vertical/real-estate/real-estate.verify.mjs +75 -0
  75. package/dungeons/vertical/sass/sass.js +1733 -0
  76. package/dungeons/vertical/sass/sass.sql +173 -0
  77. package/dungeons/vertical/sass/sass.verify.mjs +74 -0
  78. package/dungeons/vertical/social/social.js +1456 -0
  79. package/dungeons/vertical/social/social.sql +160 -0
  80. package/dungeons/vertical/social/social.verify.mjs +76 -0
  81. package/dungeons/vertical/streaming/streaming.js +677 -0
  82. package/dungeons/vertical/streaming/streaming.sql +101 -0
  83. package/dungeons/vertical/streaming/streaming.verify.mjs +75 -0
  84. package/dungeons/vertical/support-desk/support-desk.js +741 -0
  85. package/dungeons/vertical/support-desk/support-desk.sql +137 -0
  86. package/dungeons/vertical/support-desk/support-desk.verify.mjs +75 -0
  87. package/dungeons/vertical/travel/travel.js +1603 -0
  88. package/dungeons/vertical/travel/travel.sql +236 -0
  89. package/dungeons/vertical/travel/travel.verify.mjs +72 -0
  90. package/index.js +2 -2
  91. package/lib/core/config-validator.js +37 -2
  92. package/lib/core/context.js +4 -2
  93. package/lib/core/dungeon-loader.js +20 -15
  94. package/lib/core/dungeon-to-json.js +22 -4
  95. package/lib/core/storage.js +3 -3
  96. package/lib/generators/funnels.js +36 -9
  97. package/lib/hook-helpers/cohort.js +53 -0
  98. package/lib/hook-helpers/index.js +8 -0
  99. package/lib/hook-helpers/mutate.js +1 -1
  100. package/lib/hook-helpers/shape.js +319 -0
  101. package/lib/hook-patterns/aggregate-per-user-by-bin.js +13 -5
  102. package/lib/hook-patterns/attributed-by-source.js +60 -58
  103. package/lib/hook-patterns/frequency-by-frequency.js +14 -4
  104. package/lib/hook-patterns/funnel-frequency-breakdown.js +24 -12
  105. package/lib/hook-patterns/index.js +1 -1
  106. package/lib/hook-patterns/time-to-convert-by-segment.js +75 -13
  107. package/lib/orchestrators/user-loop.js +41 -0
  108. package/lib/templates/story-spec.schema.json +175 -0
  109. package/lib/utils/json-evaluator.js +1 -1
  110. package/lib/utils/utils.js +5 -4
  111. package/lib/verify/coerce.js +186 -0
  112. package/lib/verify/counting.js +270 -32
  113. package/lib/verify/emulate-breakdown.js +1285 -203
  114. package/lib/verify/first-time.js +89 -0
  115. package/lib/verify/flows.js +679 -0
  116. package/lib/verify/formula.js +259 -0
  117. package/lib/verify/funnel-engine.js +697 -113
  118. package/lib/verify/index.js +32 -4
  119. package/lib/verify/sessionize.js +275 -0
  120. package/lib/verify/story-runner.js +483 -0
  121. package/lib/verify/verify-dungeon.js +59 -37
  122. package/package.json +3 -2
  123. package/scripts/extract-dungeon-schema.mjs +2 -2
  124. package/scripts/run-many.mjs +2 -2
  125. package/scripts/verify-runner.mjs +2 -2
  126. package/scripts/verify-stories.mjs +244 -0
  127. package/types.d.ts +296 -30
  128. package/dungeons/vertical/ai-platform.js +0 -818
  129. package/dungeons/vertical/community.js +0 -966
  130. package/dungeons/vertical/crypto.js +0 -895
  131. package/dungeons/vertical/dating.js +0 -830
  132. package/dungeons/vertical/devtools.js +0 -1050
  133. package/dungeons/vertical/ecommerce.js +0 -811
  134. package/dungeons/vertical/education.js +0 -964
  135. package/dungeons/vertical/fintech.js +0 -946
  136. package/dungeons/vertical/fitness.js +0 -935
  137. package/dungeons/vertical/food-delivery.js +0 -934
  138. package/dungeons/vertical/gaming.js +0 -1120
  139. package/dungeons/vertical/healthcare.js +0 -945
  140. package/dungeons/vertical/insurance-application.js +0 -1039
  141. package/dungeons/vertical/logistics.js +0 -986
  142. package/dungeons/vertical/marketplace.js +0 -1019
  143. package/dungeons/vertical/real-estate.js +0 -872
  144. package/dungeons/vertical/sass.js +0 -995
  145. package/dungeons/vertical/social.js +0 -904
  146. package/dungeons/vertical/travel.js +0 -930
package/CHANGELOG.md CHANGED
@@ -2,6 +2,217 @@
2
2
 
3
3
  All notable changes to `@ak--47/dungeon-master`.
4
4
 
5
+ ## 1.6.0 — 2026-07-04
6
+
7
+ ### Added
8
+
9
+ - **Emulator: five new analysis types + retention completion**
10
+ (`emulateBreakdown`, all ARB-cited):
11
+ - `eventBreakdown` — Insights "Total" broken down by a property, with
12
+ Mixpanel's exact segment coercion (list fan-out, `$empty_list`,
13
+ `undefined` bucket, case-sensitive type-tagged segments, topN 250);
14
+ `countType: 'unique' | 'sessions'`, `firstTimeOnly` compose;
15
+ unrecognized `countType` values throw (same strict-option rule as
16
+ retention keys).
17
+ - `uniques` — per-interval independent dedup, rolling XAU windows,
18
+ cumulative running distinct; `countType: 'sessions'`, `firstTimeOnly`.
19
+ - `lifecycle` — Lifecycle Cohort Analysis board-template classification
20
+ (new / retained / resurrected / dormant) on a value-moment event, 7- or
21
+ 30-day periods.
22
+ - `topPaths` — Flows: next-anchor-only matching, forward/reverse capacity
23
+ rings, per-level top-N pruning into `$mp_uncommon_flows_events`,
24
+ `hiddenEvents` / `visibleEvents`, `countType: 'general' | 'unique' |
25
+ 'sessions'`.
26
+ - `distinctCount` — distinct values of a property + top-N value counts.
27
+ - `retention` completion — `compounded`, `birthCanRetain`,
28
+ `carryForward` / `carryBack` / `consecutiveForward`, `calendarStart`,
29
+ `cohortWindow`, `segmentOn: 'return'`, internal-event ignore list.
30
+ - **Funnel evaluator upgrades**: session-count conversion windows,
31
+ `countMode: 'sessions'`, ARB-exact exclusion handling, any-order step
32
+ blocks, step-0-anchored trends under `timeBucket`.
33
+ - **New verify primitives**: `sessionize()` (query-time sessions — 30-min
34
+ gap / 24h max / UTC-day triggers, synthetic `$session_start`/`$session_end`),
35
+ `filterFirstTimeEver()`, `evaluateFormula()` (ARB formula grammar),
36
+ `extractFlows` / `aggregateFlows`, breakdown-key coercion
37
+ (`lib/verify/coerce.js`), `frequencyHistogram`, null-aware avg/sum
38
+ `{ flatten: true }`, `attributedBy` per-conversion output.
39
+ - **Hook atoms**: `hashCohort` (seed-stable cohort assignment),
40
+ `applyLifecycleWave`, `applyPathBias`, `applySessionShape`; pattern
41
+ `applyTTCBySegmentV2` (see Deprecated).
42
+ - **Experiments: `sticky` knob** (`ExperimentConfig.sticky`, default
43
+ `true`). Sticky bucketing — the pre-1.6 per-user hash — is now explicit
44
+ and opt-out-able: `sticky: false` re-rolls the variant on every funnel
45
+ pass via the seeded RNG. Default preserves byte-identical output for
46
+ existing dungeons.
47
+ - **Story layer**: `stories` named export on dungeons — one machine-checkable
48
+ story per hook (`DungeonStory` typedef,
49
+ `lib/templates/story-spec.schema.json`) — and the
50
+ `scripts/verify-stories.mjs` runner: mechanical five-tier verdicts
51
+ (NAILED / STRONG / WEAK / NONE / INVERSE), population floors (`minCohort`),
52
+ hook-coverage discipline, disk + in-memory modes, `--json`.
53
+ - **Verticals**: `dungeons/vertical/` restructured to one folder per vertical
54
+ (`<name>/<name>.js` + `<name>.verify.mjs` + `<name>.sql`); `stories`
55
+ exports and rebuilt hooks across all verticals; two new showcase dungeons —
56
+ `streaming` (lifecycle) and `support-desk` (flows + sessions).
57
+ - **Skills**: `/write-hooks` authors the stories export; `/verify-dungeon`
58
+ runs the story runner first and investigates only failures;
59
+ `/create-dungeon` designs analysis-friendly vocabularies (session
60
+ fan-out, value moment, hidden-event hygiene); `/analyze-soup` queries in
61
+ UTC; `/create-project` builds business context from the stories export.
62
+ - **Docs**: HOOKS.md §2.12–2.17 (event breakdown coercion, uniques/XAU,
63
+ formulas, first-time-ever, lifecycle, flows, sessions), recipes 4.29–4.31,
64
+ atom/helper reference sections.
65
+
66
+ ### Behavior changes
67
+
68
+ - **Retention option keys are strict** (P1.5). Unknown keys in a `retention`
69
+ emulator config now throw instead of being silently ignored — a typo'd
70
+ option previously ran with defaults and produced plausible-but-wrong
71
+ numbers. `carry_forward: true` is kept as a deprecated alias for
72
+ `unbounded: 'carryForward'`.
73
+ - **Funnel exclusions no longer fire before step 0** (P1.6.4).
74
+ `evaluateFunnel`'s `exclusionSteps` previously defaulted `afterStep` to
75
+ −Infinity, so an exclusion event could condemn an attempt before the first
76
+ step was ever reached. ARB has no exclusion gaps before the first step: a
77
+ pre-step-0 exclusion event now only matters inside the 2-second grace rule
78
+ at step 0 (condemns with `excludedAtStep`), otherwise the attempt proceeds.
79
+ - **Non-sequential funnel orders verify with full ARB semantics** (P1.6.6).
80
+ `first-fixed` / `last-fixed` / `first-and-last-fixed` / `outside-in` /
81
+ `random` previously verified via set-membership ("fired all step events,
82
+ any order", `verificationKind: 'partial'`); they now route through
83
+ any-order step blocks with full conversion-window / 2-second-rule /
84
+ exclusion / anchor-ordering semantics. Users that passed the loose check
85
+ but violate window or anchor ordering no longer convert. `middle-fixed`
86
+ keeps set-membership (its scrambled slots are non-contiguous).
87
+ - **`sessionMetrics` defaults to query-time derived sessions** (P1.7.2). New
88
+ `source: 'derived' | 'stamped'` option, default `'derived'`: sessions are
89
+ re-derived from raw timestamps via `sessionize()` — what Mixpanel actually
90
+ computes — instead of reading the generator's pre-stamped `session_id`.
91
+ The stamped path remains via `source: 'stamped'`, and the per-row
92
+ `stampedDivergence` count audits the gap between the two.
93
+ - **`$experiment_started` is pinned to funnel-pass start** (P4.2 engine fix,
94
+ pre-existing since 1.4.0). For experiment funnels with a non-`sequential`
95
+ `order` (`last-fixed`, `random`, `first-fixed`, ...), `applyOrderingStrategy`
96
+ shuffled the synthetic exposure event into the funnel body — the exposure
97
+ landed mid-pass at a uniform position, so exposure→conversion TTC read ~58%
98
+ of `timeToConvert`, and any exposure-anchored conversion measurement (the
99
+ Mixpanel Experiments report, ordered-funnel pairing from
100
+ `$experiment_started`) undercounted variant lift. The ordering strategy now
101
+ shuffles only the real steps; `$experiment_started` stays at execution index
102
+ 0 (offset 0), and `first-fixed`/`first-and-last-fixed` pin the true first
103
+ step instead of the exposure marker. Output changes (event order + RNG
104
+ stream) for experiment funnels with shuffle orders; `sequential` experiment
105
+ funnels are unaffected.
106
+ - **Session IDs are re-derived after the `everything` hook** (P2.1). The first
107
+ `assignSessionIds` pass still runs before hooks (hooks may read
108
+ `session_id`), but a second pass now relabels on the FINAL event set — after
109
+ the `everything` hook, auto-sort, and the future-time guard. Time-mutating
110
+ hooks (TTC scaling, injected bursts) previously left stale session ids that
111
+ disagreed with what Mixpanel derives from timestamps at query time. Session
112
+ ids hash from (user key + first event time of the session), so sessions
113
+ whose events did not move keep their exact ids. The per-session sticky-device
114
+ rewrite is NOT re-run — relabeling never mutates identity fields. Behavior
115
+ change only for dungeons whose hooks mutate event times; their stamped
116
+ `session_id` values now match query-time derivation
117
+ (`stampedDivergence === 0`).
118
+ - **Churn is now a hard activity boundary** (P2.2). `isChurnEvent` broke the
119
+ budget loop (stopping generation), but already-generated events carry
120
+ independent timestamps — uniform TimeSoup draws on the legacy path, a
121
+ shuffled active-day plan under `avgActiveDaysPerUser`/`retentionCurve` — so
122
+ churned users kept events DATED after their churn event. Churned users'
123
+ events are now truncated at the churn event's timestamp (the churn event
124
+ itself survives). Affects only dungeons using `isChurnEvent`; users who
125
+ return (`returnLikelihood` roll succeeds) are untouched. `simplest.js` has
126
+ no churn events, so the engine-shape canary and sweep are unaffected.
127
+ - **Bin-based patterns bin by distinct days by default** (P2.4).
128
+ `applyFrequencyByFrequency`, `applyFunnelFrequencyBreakdown`, and
129
+ `applyAggregateByBin` gain `binBy: 'events' | 'distinctDays'` (default
130
+ `'distinctDays'`, via `binByDistinctPeriods`). Mixpanel's frequency reports
131
+ — and the local emulator — bucket users by distinct calendar days, so the
132
+ old total-event-count axis could put a user in a different cohort than the
133
+ report bucket their data lands in, diluting engineered signal. Pass
134
+ `binBy: 'events'` to restore the pre-1.6 axis (also the right choice for
135
+ `applyFunnelFrequencyBreakdown`'s funnelEvents fallback, where one funnel
136
+ run rarely spans two days).
137
+ - **`applyAttributedBySource` rewritten to overwrite engine-stamped touches**
138
+ (P2.4, HOOKS.md recipe 4.26 as code). New opts:
139
+ `{ weights, property = 'utm_source', model = 'firstTouch'|'lastTouch'|'both' }`;
140
+ returns `{ overwritten, touches }`. The old copy-source-to-conversion
141
+ mechanism stamped fresh values, which under the v1.5 touchpoint cap land
142
+ outside Mixpanel's lookback and never move the attribution report. The
143
+ pattern now overwrites the value on the touch the chosen model reads and
144
+ never adds the property to unstamped events.
145
+
146
+ ### Changed
147
+
148
+ - **Shipped vertical dungeons: hook fixes that change generated output**
149
+ (P4.2 rebuild — same seeds, different data where noted):
150
+ - **media**: H10 applied the plan-tier factor to `watch_duration_min` in
151
+ two separate blocks — the engineered free/premium ratio compounded to
152
+ ~4.4x instead of the documented 2.09x. Single application now; the
153
+ duplicate block is deleted (no RNG-stream impact).
154
+ - **marketplace**: H9 funnel-post TTC scaling is restricted to the
155
+ Browse-to-Purchase funnel (it previously scaled all five; Buyer
156
+ Onboarding shares the search→view→cart prefix, so first-occurrence
157
+ funnel evaluation assembled chains across unscaled instances and the
158
+ engineered ratio never reached the report). H10 redesigned from a
159
+ windowed message-cohort purchase-drop to a total-message-count cohort
160
+ with property-only `offer_amount` effects.
161
+ - **sass**: H9 TTC scaling moved from one stitched whole-history
162
+ sequence (everything hook) to per-instance funnel-post gap scaling
163
+ gated on the `alert triggered` funnel — the old single scaled sequence
164
+ was diluted by the user's unscaled instances and never survived to the
165
+ funnel report.
166
+ - **crypto**: all hook day-boundary math converted from local-time dayjs
167
+ to UTC (dataset timestamps are UTC; boundaries previously shifted by
168
+ the host's UTC offset). H9 TTC scaling restricted to the onboarding
169
+ funnel (same cross-instance dilution class as marketplace). H6 churn
170
+ no longer erases a user's first 24 hours — the old absolute-day cutoff
171
+ shredded late-born users' signup/onboarding/auth events under the
172
+ growth macro.
173
+
174
+ ### Deprecated
175
+
176
+ - **`applyTTCBySegment`** (P2.4) — the funnel-post variant scales one run's
177
+ internal gaps, but Mixpanel's TTC measures the FIRST occurrence of each
178
+ step per user, so the scaling only reaches the report for `isFirstFunnel`
179
+ runs. Still functional; warns once. Use **`applyTTCBySegmentV2`** (new,
180
+ `everything` hook) — finds the greedy first sequence via
181
+ `findFirstSequence` and scales it with `scaleFunnelTTC`.
182
+ - **`Persona.churnRate`, `Persona.activeWindow`, `Persona.soupOverride`**
183
+ (P2.5) — declared config surface that was never implemented: nothing in
184
+ lib/ reads them after validation. Marked `@deprecated` in types.d.ts; the
185
+ validator warns once per process when a dungeon sets any of them. Not
186
+ removed (declared surface) and not implemented (config-shape freeze).
187
+
188
+ ## 1.5.4 — 2026-06-04
189
+
190
+ Patch. Import-phase progress now reaches `onProgress` consumers.
191
+
192
+ ### Changed
193
+
194
+ - **Bumped `mixpanel-import` to `^3.3.2`.** It now fires `progressCallback`
195
+ independently of `verbose` / `showProgress`. Previously the import callbacks
196
+ wired up in `mixpanel-sender.js` never fired in non-verbose runs because the
197
+ importer only invoked them when its stdout progress bar was enabled.
198
+
199
+ ### Fixed
200
+
201
+ - **Import progress reaches `onProgress`** (requires `mixpanel-import >= 3.3.2`).
202
+ Every import call (events, user profiles, ad spend, group profiles, group
203
+ events, SCD) already passed a `progressCallback`; with the dependency bump
204
+ those now emit `{ phase: "import", recordType, processed, total, eps,
205
+ bytesProcessed }` to the consumer's `onProgress` during the import phase.
206
+ `showProgress: !!verbose` is unchanged — it still gates only the importer's
207
+ stdout bar, so non-verbose runs stay quiet while the callback fires.
208
+
209
+ ### Why
210
+
211
+ Consumers (e.g. DM4) already handle `update.phase === 'import'` to render an
212
+ import progress bar; the callbacks simply weren't firing. This is a dependency
213
+ bump plus a regression test — no DM API change. Consumers pick it up via their
214
+ normal upgrade flow with no code change.
215
+
5
216
  ## 1.5.3 — 2026-06-04
6
217
 
7
218
  Adds two JSON/source interop helpers to the public API. No breaking changes —