@ak--47/dungeon-master 1.7.0 → 1.8.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.
- package/.claude/skills/analyze-soup/SKILL.md +30 -11
- package/.claude/skills/create-dungeon/SKILL.md +84 -44
- package/.claude/skills/create-project/SKILL.md +28 -3
- package/.claude/skills/create-project/context.mjs +89 -0
- package/.claude/skills/create-project/provision.mjs +1 -60
- package/.claude/skills/headless-build/SKILL.md +39 -12
- package/.claude/skills/powertools/SKILL.md +26 -3
- package/.claude/skills/release-check/SKILL.md +124 -0
- package/.claude/skills/verify-dungeon/SKILL.md +103 -29
- package/.claude/skills/verify-dungeon/references/alignment-contract.md +84 -0
- package/.claude/skills/verify-dungeon/references/counting-semantics.md +41 -16
- package/.claude/skills/verify-dungeon/references/report-format.md +41 -10
- package/.claude/skills/verify-dungeon/references/sql-recipes.md +171 -226
- package/.claude/skills/warehouse-metrics/GAPS-template.md +34 -0
- package/.claude/skills/warehouse-metrics/SKILL.md +111 -0
- package/.claude/skills/warehouse-metrics/deploy.mjs +651 -0
- package/.claude/skills/write-hooks/SKILL.md +94 -51
- package/CHANGELOG.md +183 -0
- package/HOOKS.md +165 -18
- package/README.md +265 -1
- package/docs/guides/1.8.0-upgrade-guide.md +151 -0
- package/docs/guides/1.8.1-upgrade-guide.md +153 -0
- package/dungeons/technical/warehouse.js +187 -0
- package/index.js +116 -2
- package/lib/core/config-validator.js +21 -0
- package/lib/core/dungeon-loader.js +1 -1
- package/lib/core/storage.js +51 -3
- package/lib/generators/events.js +6 -0
- package/lib/generators/funnels.js +15 -0
- package/lib/generators/standalone.js +248 -0
- package/lib/generators/warehouse.js +828 -0
- package/lib/hook-helpers/shape.js +73 -17
- package/lib/orchestrators/mixpanel-sender.js +27 -2
- package/lib/orchestrators/user-loop.js +83 -15
- package/lib/templates/story-spec.schema.json +41 -16
- package/lib/utils/utils.js +37 -12
- package/lib/verify/funnel-engine.js +66 -26
- package/lib/verify/index.js +1 -0
- package/lib/verify/story-runner.js +71 -8
- package/lib/verify/warehouse.js +683 -0
- package/package.json +4 -2
- package/scripts/verify-stories.mjs +150 -44
- package/types.d.ts +312 -9
package/types.d.ts
CHANGED
|
@@ -453,6 +453,18 @@ export interface Dungeon {
|
|
|
453
453
|
groupProps?: Record<string, Record<string, ValueValid>>;
|
|
454
454
|
/** Lookup table definitions for dimension tables. */
|
|
455
455
|
lookupTables?: LookupTableSchema[];
|
|
456
|
+
/**
|
|
457
|
+
* v1.8.0 — identity-less metric snapshots. One record per cadence tick per
|
|
458
|
+
* dimension cross-product row, carrying NO `user_id` and NO `device_id`.
|
|
459
|
+
*
|
|
460
|
+
* Use for infrastructure and finance telemetry: daily CDN egress per region,
|
|
461
|
+
* weekly billing rollups per plan tier, hourly queue depth per cluster.
|
|
462
|
+
* `$ad_spend` (`hasAdSpend: true`) is the same idea hard-coded; this is the
|
|
463
|
+
* general form and it does not use a Mixpanel reserved event name.
|
|
464
|
+
*/
|
|
465
|
+
standaloneEvents?: StandaloneEventConfig[];
|
|
466
|
+
/** v1.8.0 — warehouse-backed metric source tables derived from the run's own event stream. */
|
|
467
|
+
warehouseMetrics?: WarehouseMetricConfig[];
|
|
456
468
|
/** TimeSoup configuration: shapes intra-week and intra-day rhythm (peaks, deviation, DOW/HOD weights). Pair with `macro` for big-picture trend control. */
|
|
457
469
|
soup?: soup;
|
|
458
470
|
/** Macro trend shape across the full dataset window: birth distribution + per-user event allocation. Default: "flat". Use "growth"/"viral"/"steady"/"decline" or a custom object. */
|
|
@@ -703,7 +715,7 @@ export interface ResolvedMacro {
|
|
|
703
715
|
* - "everything" — array of ALL events for one user (return array to replace; meta.profile available)
|
|
704
716
|
*
|
|
705
717
|
* Storage-only hooks (fire during hookPush, not in generators):
|
|
706
|
-
* - "ad-spend", "group", "mirror", "lookup"
|
|
718
|
+
* - "ad-spend", "group", "mirror", "lookup", "standalone", "warehouse"
|
|
707
719
|
*/
|
|
708
720
|
export type hookTypes =
|
|
709
721
|
| "event"
|
|
@@ -716,6 +728,8 @@ export type hookTypes =
|
|
|
716
728
|
| "funnel-pre"
|
|
717
729
|
| "funnel-post"
|
|
718
730
|
| "ad-spend"
|
|
731
|
+
| "standalone"
|
|
732
|
+
| "warehouse"
|
|
719
733
|
| "churn"
|
|
720
734
|
| "group-event"
|
|
721
735
|
| "everything"
|
|
@@ -732,7 +746,9 @@ export type hookTypes =
|
|
|
732
746
|
* - "event": return value REPLACES the event (must be the event object).
|
|
733
747
|
* - "everything": return an array to REPLACE the user's event list (filter/inject/dedupe).
|
|
734
748
|
* - "user", "scd-pre", "funnel-pre", "funnel-post": return value is IGNORED — mutate in place.
|
|
735
|
-
* - storage-only ("ad-spend", "group", "mirror", "lookup"): return
|
|
749
|
+
* - storage-only ("ad-spend", "group", "mirror", "lookup", "standalone"): return an object or array of records; undefined drops the record.
|
|
750
|
+
* - "warehouse": return value is IGNORED; mutate the row in place.
|
|
751
|
+
* - "standalone" runs before the user loop; "warehouse" runs after it. Neither receives person metadata or enters "everything".
|
|
736
752
|
*
|
|
737
753
|
* @param record - The data being processed (event, profile, array of events, funnel config, etc.).
|
|
738
754
|
* @param type - Which hook type is firing — see `hookTypes`.
|
|
@@ -908,6 +924,10 @@ export interface hookArrayOptions<T> {
|
|
|
908
924
|
concurrency?: number;
|
|
909
925
|
/** Generation context (config, runtime, defaults). */
|
|
910
926
|
context?: Context;
|
|
927
|
+
/** Warehouse metric name for warehouse containers. */
|
|
928
|
+
metricName?: string;
|
|
929
|
+
/** Fixed CSV column order for warehouse metric tables. */
|
|
930
|
+
fixedColumns?: string[];
|
|
911
931
|
}
|
|
912
932
|
|
|
913
933
|
/**
|
|
@@ -929,6 +949,10 @@ export interface HookedArray<T> extends Array<T> {
|
|
|
929
949
|
getWritePath: () => string;
|
|
930
950
|
/** Returns all file paths written by this container during the current run. */
|
|
931
951
|
getWrittenFiles: () => string[];
|
|
952
|
+
/** Storage hook type this array is configured for. */
|
|
953
|
+
type?: hookTypes | string;
|
|
954
|
+
/** Output serialization format for this array. */
|
|
955
|
+
format?: string;
|
|
932
956
|
/** SCD prop name this array carries (only set on SCD HookedArrays). */
|
|
933
957
|
scdKey?: string;
|
|
934
958
|
/** Entity type for SCDs ("user" or a group key). */
|
|
@@ -937,6 +961,10 @@ export interface HookedArray<T> extends Array<T> {
|
|
|
937
961
|
groupKey?: string;
|
|
938
962
|
/** Lookup table key this array carries (only set on lookup table HookedArrays). */
|
|
939
963
|
lookupKey?: string;
|
|
964
|
+
/** Warehouse metric name this array carries (only set on warehouse HookedArrays). */
|
|
965
|
+
metricName?: string;
|
|
966
|
+
/** Fixed CSV column order for warehouse metric tables. */
|
|
967
|
+
fixedColumns?: string[];
|
|
940
968
|
}
|
|
941
969
|
|
|
942
970
|
export type AllData =
|
|
@@ -954,8 +982,11 @@ export interface Storage {
|
|
|
954
982
|
mirrorEventData?: HookedArray<EventSchema>;
|
|
955
983
|
userProfilesData?: HookedArray<UserProfile>;
|
|
956
984
|
adSpendData?: HookedArray<EventSchema>;
|
|
985
|
+
standaloneEventData?: HookedArray<EventSchema>;
|
|
957
986
|
groupProfilesData?: HookedArray<GroupProfileSchema>[];
|
|
958
987
|
lookupTableData?: HookedArray<LookupTableSchema>[];
|
|
988
|
+
warehouseMetricData?: HookedArray<Record<string, any>>[];
|
|
989
|
+
warehouseManifestFile?: string;
|
|
959
990
|
scdTableData?: HookedArray<SCDSchema>[];
|
|
960
991
|
groupEventData?: HookedArray<EventSchema>;
|
|
961
992
|
}
|
|
@@ -1023,6 +1054,14 @@ export interface Context {
|
|
|
1023
1054
|
FIXED_NOW: number;
|
|
1024
1055
|
/** Start of the resolved dataset window (unix seconds). Equal to the user-supplied `datasetStart`, or fallback `today_start - numDays`. */
|
|
1025
1056
|
FIXED_BEGIN?: number;
|
|
1057
|
+
/** Runtime accumulator for post-loop warehouse metric materialization. */
|
|
1058
|
+
warehouseAccumulator?: {
|
|
1059
|
+
warnings?: string[];
|
|
1060
|
+
ingest: (events: EventSchema[]) => void;
|
|
1061
|
+
getCell: (metricName: string, seriesKey: string, bucketStartSec: number) => any;
|
|
1062
|
+
};
|
|
1063
|
+
/** Manifest describing materialized warehouse tables for downstream tooling. */
|
|
1064
|
+
warehouseManifest?: WarehouseManifest;
|
|
1026
1065
|
/** Alias of `FIXED_BEGIN` — surfaced on hook `meta.datasetStart`. */
|
|
1027
1066
|
DATASET_START_SECONDS: number;
|
|
1028
1067
|
/** Alias of `FIXED_NOW` — surfaced on hook `meta.datasetEnd`. */
|
|
@@ -1596,6 +1635,12 @@ export type Result = {
|
|
|
1596
1635
|
scdTableData: SCDSchema[][];
|
|
1597
1636
|
/** Ad-spend events (only populated when `hasAdSpend: true`). */
|
|
1598
1637
|
adSpendData: EventSchema[];
|
|
1638
|
+
/** Identity-less metric snapshots (only populated when `standaloneEvents` is set). v1.8.0. */
|
|
1639
|
+
standaloneEventData: EventSchema[];
|
|
1640
|
+
/** Materialized warehouse metric tables keyed by metric name. */
|
|
1641
|
+
warehouseMetricData: Record<string, Record<string, any>[]>;
|
|
1642
|
+
/** Warehouse table manifest surfaced whenever `warehouseMetrics` is configured. */
|
|
1643
|
+
warehouseManifest?: WarehouseManifest;
|
|
1599
1644
|
/** Group profiles — one inner array per group key. */
|
|
1600
1645
|
groupProfilesData: GroupProfileSchema[][];
|
|
1601
1646
|
/** Lookup tables — one inner array per table. */
|
|
@@ -2007,9 +2052,10 @@ export interface StoryAssertion {
|
|
|
2007
2052
|
/**
|
|
2008
2053
|
* Byte-compatible with `emulateBreakdown` / `verifyDungeon` args — or the
|
|
2009
2054
|
* `{ type: 'duckdb', sql }` escape hatch (disk mode only; `{{PREFIX}}` in
|
|
2010
|
-
* the SQL is substituted with the run's data prefix path)
|
|
2055
|
+
* the SQL is substituted with the run's data prefix path), or warehouse
|
|
2056
|
+
* verification rows via `{ type: 'warehouse' | 'warehouse-stats', table }`.
|
|
2011
2057
|
*/
|
|
2012
|
-
breakdown: Record<string, unknown> & { type: string; sql?: string };
|
|
2058
|
+
breakdown: Record<string, unknown> & { type: string; sql?: string; table?: string };
|
|
2013
2059
|
select?: StorySelect;
|
|
2014
2060
|
expect?: StoryExpect;
|
|
2015
2061
|
/**
|
|
@@ -2325,13 +2371,266 @@ export interface WritePaths {
|
|
|
2325
2371
|
eventFiles: string[];
|
|
2326
2372
|
userFiles: string[];
|
|
2327
2373
|
adSpendFiles: string[];
|
|
2374
|
+
standaloneFiles: string[];
|
|
2328
2375
|
scdFiles: string[];
|
|
2329
2376
|
mirrorFiles: string[];
|
|
2330
2377
|
groupFiles: string[];
|
|
2331
2378
|
lookupFiles: string[];
|
|
2379
|
+
warehouseFiles: string[];
|
|
2332
2380
|
folder: string;
|
|
2333
2381
|
}
|
|
2334
2382
|
|
|
2383
|
+
// ============= Standalone (identity-less) Events — v1.8.0 =============
|
|
2384
|
+
|
|
2385
|
+
/**
|
|
2386
|
+
* An identity-less metric snapshot stream.
|
|
2387
|
+
*
|
|
2388
|
+
* The engine emits one record per cadence tick per dimension cross-product row.
|
|
2389
|
+
* Records carry `event`, `time`, `insert_id`, `distinct_id`, every dimension as
|
|
2390
|
+
* a flat property, and every resolved entry in `properties`. They never carry
|
|
2391
|
+
* `user_id` or `device_id`, because they describe a system, not a person.
|
|
2392
|
+
*
|
|
2393
|
+
* @example
|
|
2394
|
+
* standaloneEvents: [{
|
|
2395
|
+
* event: 'cdn_egress',
|
|
2396
|
+
* cadence: 'day',
|
|
2397
|
+
* dimensions: { region: ['us-east', 'us-west', 'eu', 'apac'] },
|
|
2398
|
+
* distinctIdFrom: 'region',
|
|
2399
|
+
* properties: {
|
|
2400
|
+
* gb_out: (ctx) => 400 + ctx.tickIndex * 3,
|
|
2401
|
+
* cost_usd: (ctx) => (400 + ctx.tickIndex * 3) * 0.085,
|
|
2402
|
+
* p95_ms: [120, 140, 160],
|
|
2403
|
+
* },
|
|
2404
|
+
* }]
|
|
2405
|
+
*/
|
|
2406
|
+
export interface StandaloneEventConfig {
|
|
2407
|
+
/** Event name as it lands in Mixpanel. Must be unique across `standaloneEvents`. */
|
|
2408
|
+
event: string;
|
|
2409
|
+
/**
|
|
2410
|
+
* How often a snapshot fires. Ticks start at the dataset start and step by
|
|
2411
|
+
* the cadence; the last tick is the final one at or before the dataset end.
|
|
2412
|
+
* Default: `'day'`.
|
|
2413
|
+
*/
|
|
2414
|
+
cadence?: 'hour' | 'day' | 'week';
|
|
2415
|
+
/**
|
|
2416
|
+
* Dimension values to cross-product. Each key becomes a flat property on the
|
|
2417
|
+
* record. `{ region: ['us','eu'], tier: ['a','b'] }` emits 4 records per tick.
|
|
2418
|
+
* Omit for a single record per tick.
|
|
2419
|
+
*/
|
|
2420
|
+
dimensions?: Record<string, any[]>;
|
|
2421
|
+
/**
|
|
2422
|
+
* Which dimension supplies the synthetic `distinct_id`. Must name a declared
|
|
2423
|
+
* dimension. When omitted, `distinct_id` is the event name. The id exists so
|
|
2424
|
+
* Mixpanel accepts the record; it never maps to a person.
|
|
2425
|
+
*/
|
|
2426
|
+
distinctIdFrom?: string;
|
|
2427
|
+
/**
|
|
2428
|
+
* Snapshot metrics. Same `ValueValid` forms as event properties, and value
|
|
2429
|
+
* functions receive a `StandaloneValueContext` so a metric can shape a trend
|
|
2430
|
+
* across the window.
|
|
2431
|
+
*/
|
|
2432
|
+
properties?: Record<string, ValueValid>;
|
|
2433
|
+
}
|
|
2434
|
+
|
|
2435
|
+
/** @internal Normalized `StandaloneEventConfig` produced by the validator. */
|
|
2436
|
+
export interface ResolvedStandaloneEventConfig {
|
|
2437
|
+
event: string;
|
|
2438
|
+
cadence: 'hour' | 'day' | 'week';
|
|
2439
|
+
dimensions: Record<string, any[]>;
|
|
2440
|
+
distinctIdFrom: string | null;
|
|
2441
|
+
properties: Record<string, ValueValid>;
|
|
2442
|
+
}
|
|
2443
|
+
|
|
2444
|
+
/**
|
|
2445
|
+
* Context handed to every standalone property value function.
|
|
2446
|
+
* Shares `time` and `config` with `ValueContext`, so a function written for a
|
|
2447
|
+
* normal event property still works unchanged.
|
|
2448
|
+
*/
|
|
2449
|
+
export interface StandaloneValueContext {
|
|
2450
|
+
/** Tick timestamp in unix MILLISECONDS. */
|
|
2451
|
+
time: number;
|
|
2452
|
+
/** The full validated dungeon config. */
|
|
2453
|
+
config: Dungeon;
|
|
2454
|
+
/** This row's dimension values, e.g. `{ region: 'us-east' }`. */
|
|
2455
|
+
dimensions: Record<string, any>;
|
|
2456
|
+
/** Zero-based index of this tick within the window. Use it to shape a trend. */
|
|
2457
|
+
tickIndex: number;
|
|
2458
|
+
/** Total number of ticks in the window. `tickIndex / (tickCount - 1)` is window progress. */
|
|
2459
|
+
tickCount: number;
|
|
2460
|
+
/** The cadence this stream fires on. */
|
|
2461
|
+
cadence: 'hour' | 'day' | 'week';
|
|
2462
|
+
/** The partially built record (`event`, `time`, `insert_id`, `distinct_id`, dimensions). */
|
|
2463
|
+
event: Record<string, any>;
|
|
2464
|
+
}
|
|
2465
|
+
|
|
2466
|
+
/**
|
|
2467
|
+
* Meta passed to the `"standalone"` hook.
|
|
2468
|
+
*
|
|
2469
|
+
* Storage-only: return the record or an array of records to retain them.
|
|
2470
|
+
* Returning undefined drops the record. Warehouse hooks instead ignore returns.
|
|
2471
|
+
*/
|
|
2472
|
+
export interface HookMetaStandalone extends HookMetaTimeAnchors {
|
|
2473
|
+
/** The resolved config for the stream this record belongs to. */
|
|
2474
|
+
spec: ResolvedStandaloneEventConfig;
|
|
2475
|
+
/** The full validated dungeon config. */
|
|
2476
|
+
config: Dungeon;
|
|
2477
|
+
}
|
|
2478
|
+
|
|
2479
|
+
export interface WarehouseMetricSource {
|
|
2480
|
+
/** Source event names whose bucketed measure contributes positively to the series. */
|
|
2481
|
+
event: string | string[];
|
|
2482
|
+
/** Source event names whose bucketed measure is subtracted from the series. */
|
|
2483
|
+
minus?: string | string[];
|
|
2484
|
+
/** Per-bucket measure. Default: `'count'`. */
|
|
2485
|
+
measure?: 'count' | 'sum' | 'avg' | 'dau' | 'users';
|
|
2486
|
+
/** Required when `measure` is `'sum'` or `'avg'`. */
|
|
2487
|
+
property?: string;
|
|
2488
|
+
/** Optional row filter over flat event records. */
|
|
2489
|
+
where?: ((event: Record<string, any>) => boolean) | null;
|
|
2490
|
+
/** Optional dimension columns copied from source event or super prop keys. */
|
|
2491
|
+
groupBy?: string | string[];
|
|
2492
|
+
}
|
|
2493
|
+
|
|
2494
|
+
export interface WarehouseMetricConfig {
|
|
2495
|
+
/**
|
|
2496
|
+
* @example
|
|
2497
|
+
* warehouseMetrics: [{
|
|
2498
|
+
* name: 'daily_active_subscriptions',
|
|
2499
|
+
* type: 'point-in-time',
|
|
2500
|
+
* source: {
|
|
2501
|
+
* event: 'subscription_started',
|
|
2502
|
+
* minus: 'subscription_cancelled',
|
|
2503
|
+
* measure: 'count',
|
|
2504
|
+
* },
|
|
2505
|
+
* baseline: 40,
|
|
2506
|
+
* timeColumn: 'date',
|
|
2507
|
+
* valueColumn: 'active_subscriptions',
|
|
2508
|
+
* }]
|
|
2509
|
+
*/
|
|
2510
|
+
/** Unique metric/table name. Must match `/^[a-z][a-z0-9_]{0,63}$/`. */
|
|
2511
|
+
name: string;
|
|
2512
|
+
/** Metric family: additive sums per bucket vs point-in-time carried levels. Default: `'additive'`. */
|
|
2513
|
+
type?: 'additive' | 'point-in-time';
|
|
2514
|
+
/** Bucket grain. Default: `'day'`. */
|
|
2515
|
+
grain?: 'day' | 'week' | 'month';
|
|
2516
|
+
/** Point-in-time only: emit only the first bucket and changed values. Default: `false`. */
|
|
2517
|
+
sparse?: boolean;
|
|
2518
|
+
/** Declarative source spec describing how to derive the table from generated events. */
|
|
2519
|
+
source: WarehouseMetricSource;
|
|
2520
|
+
/** Output time column name. Default: `'date'`. */
|
|
2521
|
+
timeColumn?: string;
|
|
2522
|
+
/** Output value column name. Default: `'value'`. */
|
|
2523
|
+
valueColumn?: string;
|
|
2524
|
+
/** Point-in-time starting level at the dataset window start. Default: `0`. */
|
|
2525
|
+
baseline?: number;
|
|
2526
|
+
/** Multiplier applied after bucket aggregation. Default: `1`. */
|
|
2527
|
+
scale?: number;
|
|
2528
|
+
/** Seeded jitter fraction clamped to `[0, 0.5]`. Default: `0`. */
|
|
2529
|
+
noise?: number;
|
|
2530
|
+
/** Grain periods of backfill before the dataset window. Default: `0`. */
|
|
2531
|
+
history?: number;
|
|
2532
|
+
/** Extra declared output columns, preserved in declaration order. */
|
|
2533
|
+
columns?: Record<string, ValueValid | ((ctx: WarehouseValueContext) => ValueValid)>;
|
|
2534
|
+
/** Output file format. Defaults to the dungeon format, else `'csv'`. */
|
|
2535
|
+
format?: 'csv' | 'json';
|
|
2536
|
+
}
|
|
2537
|
+
|
|
2538
|
+
/** @internal Normalized `WarehouseMetricConfig` produced by the validator. */
|
|
2539
|
+
export interface ResolvedWarehouseMetricConfig {
|
|
2540
|
+
name: string;
|
|
2541
|
+
type: 'additive' | 'point-in-time';
|
|
2542
|
+
grain: 'day' | 'week' | 'month';
|
|
2543
|
+
sparse: boolean;
|
|
2544
|
+
source: {
|
|
2545
|
+
event: string[];
|
|
2546
|
+
minus: string[];
|
|
2547
|
+
measure: 'count' | 'sum' | 'avg' | 'dau' | 'users';
|
|
2548
|
+
property: string | null;
|
|
2549
|
+
where: ((event: Record<string, any>) => boolean) | null;
|
|
2550
|
+
groupBy: string[];
|
|
2551
|
+
};
|
|
2552
|
+
timeColumn: string;
|
|
2553
|
+
valueColumn: string;
|
|
2554
|
+
baseline: number;
|
|
2555
|
+
scale: number;
|
|
2556
|
+
noise: number;
|
|
2557
|
+
history: number;
|
|
2558
|
+
columns: Record<string, ValueValid | ((ctx: WarehouseValueContext) => ValueValid)>;
|
|
2559
|
+
format: 'csv' | 'json';
|
|
2560
|
+
}
|
|
2561
|
+
|
|
2562
|
+
export interface WarehouseValueContext {
|
|
2563
|
+
/** Final bucket value after scale and noise. */
|
|
2564
|
+
value: number;
|
|
2565
|
+
/** Partially built row so later columns can depend on earlier ones. */
|
|
2566
|
+
row: Record<string, any>;
|
|
2567
|
+
/** Bucket start in unix milliseconds. */
|
|
2568
|
+
time: number;
|
|
2569
|
+
/** Zero-based chronological bucket index within this series, including backfill buckets and sparse gaps when present. */
|
|
2570
|
+
bucketIndex: number;
|
|
2571
|
+
/** Total chronological buckets in this series, including history buckets even when sparse rows are skipped. */
|
|
2572
|
+
bucketCount: number;
|
|
2573
|
+
/** Bucket grain for this metric. */
|
|
2574
|
+
grain: 'day' | 'week' | 'month';
|
|
2575
|
+
/** True when this row was synthesized before the dataset window by `history`. */
|
|
2576
|
+
isBackfill: boolean;
|
|
2577
|
+
/** Stable joined dimension key for this series. Empty string when undimensioned. */
|
|
2578
|
+
seriesKey: string;
|
|
2579
|
+
/** The resolved metric spec for this table. */
|
|
2580
|
+
spec: ResolvedWarehouseMetricConfig;
|
|
2581
|
+
/** The full validated dungeon config. */
|
|
2582
|
+
config: Dungeon;
|
|
2583
|
+
}
|
|
2584
|
+
|
|
2585
|
+
export interface HookMetaWarehouse extends HookMetaTimeAnchors {
|
|
2586
|
+
/** The resolved config for the metric this row belongs to. */
|
|
2587
|
+
spec: ResolvedWarehouseMetricConfig;
|
|
2588
|
+
/** The full validated dungeon config. */
|
|
2589
|
+
config: Dungeon;
|
|
2590
|
+
/** Metric/table name. */
|
|
2591
|
+
metricName: string;
|
|
2592
|
+
/** Zero-based chronological bucket index within this series, including history buckets and sparse gaps. */
|
|
2593
|
+
bucketIndex: number;
|
|
2594
|
+
/** Total chronological buckets in this series, including history buckets even when sparse rows are skipped. */
|
|
2595
|
+
bucketCount: number;
|
|
2596
|
+
/** Bucket grain for the metric. */
|
|
2597
|
+
grain: 'day' | 'week' | 'month';
|
|
2598
|
+
/** Stable joined dimension key for this series. Empty string when undimensioned. */
|
|
2599
|
+
seriesKey: string;
|
|
2600
|
+
/** True when the row belongs to the `history` backfill before the dataset window. */
|
|
2601
|
+
isBackfill: boolean;
|
|
2602
|
+
/** Raw bucket contributions before scale/noise and before point-in-time carry-forward. */
|
|
2603
|
+
raw: {
|
|
2604
|
+
plus: { count: number; sum: number; users: number };
|
|
2605
|
+
minus: { count: number; sum: number; users: number };
|
|
2606
|
+
};
|
|
2607
|
+
}
|
|
2608
|
+
|
|
2609
|
+
export interface WarehouseManifestColumn {
|
|
2610
|
+
name: string;
|
|
2611
|
+
bqType: 'DATE' | 'FLOAT64' | 'BOOL' | 'STRING';
|
|
2612
|
+
}
|
|
2613
|
+
|
|
2614
|
+
export interface WarehouseManifestTable {
|
|
2615
|
+
table: string;
|
|
2616
|
+
file: string;
|
|
2617
|
+
format: 'csv' | 'json';
|
|
2618
|
+
grain: 'day' | 'week' | 'month';
|
|
2619
|
+
type: 'additive' | 'point-in-time';
|
|
2620
|
+
timeColumn: string;
|
|
2621
|
+
valueColumn: string;
|
|
2622
|
+
dimensionColumns: string[];
|
|
2623
|
+
columns: WarehouseManifestColumn[];
|
|
2624
|
+
recommendedAggregation: 'sum' | 'last value';
|
|
2625
|
+
sql: string;
|
|
2626
|
+
refreshHint: string;
|
|
2627
|
+
}
|
|
2628
|
+
|
|
2629
|
+
export interface WarehouseManifest {
|
|
2630
|
+
configName: string;
|
|
2631
|
+
tables: WarehouseManifestTable[];
|
|
2632
|
+
}
|
|
2633
|
+
|
|
2335
2634
|
/**
|
|
2336
2635
|
* Configuration for TimeSoup time distribution function
|
|
2337
2636
|
*/
|
|
@@ -2384,10 +2683,10 @@ declare module '@ak--47/dungeon-master/hook-helpers' {
|
|
|
2384
2683
|
export function injectOnNewDays(events: EventSchema[], eventName: string, targetDays: number, options?: { timeRange?: 'active'; overrides?: Partial<EventSchema> }): EventSchema[];
|
|
2385
2684
|
/** v1.6.0 — carve a dormant window (drop value moments, or all events with `dropAll`) then append a resurrection burst cloned from the surviving value-moment template. Returns a NEW array. */
|
|
2386
2685
|
export function applyLifecycleWave(events: EventSchema[], uid: string, opts: { dormantFromDay: number; dormantDays: number; valueMomentEvent: string; resurrectBurst?: number; dropAll?: boolean }): EventSchema[];
|
|
2387
|
-
/** v1.6.0 —
|
|
2686
|
+
/** v1.6.0 — append an ordered path after the FIRST chronological anchor for a deterministic `share` of users. Original traffic is untouched and can interrupt the immediate branch; share is an injection gate, not a measured Flows share. */
|
|
2388
2687
|
export function applyPathBias(events: EventSchema[], uid: string, opts: { anchor: string; path: string[]; share: number; gapSeconds?: [number, number] }): EventSchema[];
|
|
2389
|
-
/**
|
|
2390
|
-
export function applySessionShape(events: EventSchema[], uid: string, opts: { sessionsPerWeek: number; eventsPerSession: number; sessionMinutes: number }): EventSchema[];
|
|
2688
|
+
/** Retiming only; preserves every record. Both bounds omitted retain legacy full-UTC-day placement, including nonthrowing overfull requests whose clusters may merge. Optional inclusive bounds accept ISO, unix seconds or milliseconds (hook meta directly); an omitted side uses its original UTC day edge. The helper cannot infer datasetEnd. Explicit-bound mode throws RangeError before mutation for invalid bounds or insufficient per-week 30-minute-session capacity. Pass known metadata bounds to prevent later engine clipping. */
|
|
2689
|
+
export function applySessionShape(events: EventSchema[], uid: string, opts: { sessionsPerWeek: number; eventsPerSession: number; sessionMinutes: number; datasetStart?: string | number; datasetEnd?: string | number }): EventSchema[];
|
|
2391
2690
|
}
|
|
2392
2691
|
|
|
2393
2692
|
declare module '@ak--47/dungeon-master/hook-patterns' {
|
|
@@ -2627,6 +2926,9 @@ declare module '@ak--47/dungeon-master/verify' {
|
|
|
2627
2926
|
*/
|
|
2628
2927
|
conversionWindow?: { unit: 'sessions'; n: number };
|
|
2629
2928
|
graceperiod?: boolean;
|
|
2929
|
+
/** Defaults to false, including totals. Restart after inclusive 2s completion grace;
|
|
2930
|
+
* ordered shared last/first edges restart on the completion event itself.
|
|
2931
|
+
* graceperiod=false disables the wait; window expiry can restart earlier. */
|
|
2630
2932
|
reentry?: boolean;
|
|
2631
2933
|
exclusionSteps?: ExclusionStep[];
|
|
2632
2934
|
trackStepProperties?: boolean | string[];
|
|
@@ -2659,9 +2961,10 @@ declare module '@ak--47/dungeon-master/verify' {
|
|
|
2659
2961
|
}
|
|
2660
2962
|
/** Evaluate a funnel against a user's events. Returns FunnelResult or array (totals mode). */
|
|
2661
2963
|
export function evaluateFunnel(events: Array<Record<string, unknown>>, steps: FunnelStep[], options?: FunnelOptions): FunnelResult | FunnelResult[];
|
|
2662
|
-
/** Hold Property Constant
|
|
2964
|
+
/** Hold Property Constant: parallel sub-funnels per held value; session ordinals use the full user stream. */
|
|
2663
2965
|
export function evaluateFunnelHPC(events: Array<Record<string, unknown>>, steps: FunnelStep[], holdProperty: string, options?: FunnelOptions): Map<string | number, FunnelResult | FunnelResult[]>;
|
|
2664
|
-
/**
|
|
2966
|
+
/** Merge reached snapshots in path order for first/last touch. Undefined and null preserve
|
|
2967
|
+
* defined non-null fallback values. Explicit step selection returns its snapshot unchanged. */
|
|
2665
2968
|
export function resolveFunnelSegment(result: FunnelResult, mode: 'first' | 'last' | { step: number }): Record<string, unknown> | undefined;
|
|
2666
2969
|
/** Normalize a FunnelStep to the `{ event, where? }` canonical shape. */
|
|
2667
2970
|
export function normalizeStep(step: FunnelStep): { event: string; where?: { prop: string; op: string; value: unknown } };
|