@bitcobblers/wod-wiki-lang 0.37.2137 → 0.37.2140

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.
@@ -1,49 +1,4 @@
1
- import { ICodeStatement, ParseError, MetricContainer, IMetric, BlockKey, TimeSpan as TimeSpan$1, OutputStatementType, MetricType, IOutputStatement, MetricOrigin } from '@bitcobblers/wod-wiki-core';
2
-
3
- interface IScript {
4
- source: string;
5
- statements: ICodeStatement[];
6
- errors?: ParseError[] | undefined;
7
- getIds(ids: number[]): ICodeStatement[];
8
- getId(id: number): ICodeStatement | undefined;
9
- getAt(index: number): ICodeStatement | undefined;
10
- }
11
- declare class WhiteboardScript implements IScript {
12
- source: string;
13
- statements: ICodeStatement[];
14
- errors: ParseError[] | undefined;
15
- private _idMap?;
16
- constructor(source: string, statements: ICodeStatement[], errors?: ParseError[]);
17
- /**
18
- * Gets the ID-to-statement Map, building it lazily on first access.
19
- * Provides O(1) lookups instead of O(n) find() calls.
20
- */
21
- private getIdMap;
22
- /**
23
- * Resolves multiple statement IDs to statements.
24
- * Uses cached Map for O(n) performance instead of O(n²).
25
- */
26
- getIds(ids: number[]): ICodeStatement[];
27
- /**
28
- * Resolves a single statement ID to a statement.
29
- * Uses cached Map for O(1) performance instead of O(n).
30
- */
31
- getId(id: number): ICodeStatement | undefined;
32
- /**
33
- * Gets a statement by its array index.
34
- */
35
- getAt(index: number): ICodeStatement | undefined;
36
- /**
37
- * Flattens grouped children (number[][]) and resolves to statements.
38
- * Convenience wrapper for getIds(children.flat()).
39
- */
40
- getFlatChildren(children: number[][]): ICodeStatement[];
41
- /**
42
- * Resolves grouped children while preserving group structure.
43
- * Maps each number[] group to ICodeStatement[] group.
44
- */
45
- getChildGroups(children: number[][]): ICodeStatement[][];
46
- }
1
+ import { ReferenceMatchKind, ReferenceRef, ReferenceDiagnostic, ICodeStatement, ParseError, MetricContainer, IMetric, BlockKey, TimeSpan as TimeSpan$1, OutputStatementType, MetricType, IOutputStatement, MetricOrigin } from '@bitcobblers/wod-wiki-core';
47
2
 
48
3
  /**
49
4
  * Canonical discipline vocabulary — the single source of truth for effort
@@ -82,6 +37,30 @@ type EffortRegistrySource = 'bundled' | 'user' | 'synthetic-unresolved';
82
37
  /** Origins that hold real registry records (synthetic-unresolved entries are
83
38
  * resolver phantoms, never listed) — the WQL `origin:` filter vocabulary. */
84
39
  declare const EFFORT_REGISTRY_ORIGINS: readonly ["bundled", "user"];
40
+ /**
41
+ * Precedence tiers for resolving collisions across seed catalogs and local edits.
42
+ * Order: core (0) < community (1) < imported (2) < user (3).
43
+ */
44
+ type CatalogPrecedenceTier = 'core' | 'community' | 'imported' | 'user';
45
+ declare const CATALOG_PRECEDENCE_RANK: Readonly<Record<CatalogPrecedenceTier, number>>;
46
+ /** Resolve the precedence tier for a seed source id or checkpoint key (`seed:<id>`). */
47
+ declare function resolveSourceTier(sourceIdOrMetaKey?: string | null, explicitTier?: CatalogPrecedenceTier): CatalogPrecedenceTier;
48
+ declare function resolveSourceRank(sourceIdOrMetaKey?: string | null, explicitTier?: CatalogPrecedenceTier): number;
49
+ /** Resolve the precedence tier of an effort/equipment definition record. */
50
+ declare function resolveEntityTier(entity: {
51
+ registrySource?: string;
52
+ sourceId?: string | null;
53
+ }): CatalogPrecedenceTier;
54
+ declare function resolveEntityRank(entity: {
55
+ registrySource?: string;
56
+ sourceId?: string | null;
57
+ }): number;
58
+ /** Deduplicate definition entities by slug, retaining the highest-precedence record per slug. */
59
+ declare function dedupeEntitiesByPrecedence<T extends {
60
+ slug: string;
61
+ registrySource?: string;
62
+ sourceId?: string | null;
63
+ }>(entities: readonly T[]): T[];
85
64
  /** Intensity tiers, low → high — the WQL `intensity:` filter vocabulary. */
86
65
  declare const INTENSITY_TIERS: readonly ["low", "moderate", "high"];
87
66
  type IntensityTier = (typeof INTENSITY_TIERS)[number];
@@ -122,6 +101,14 @@ interface IEffort {
122
101
  baseAttributes: EffortBaseAttributes;
123
102
  /** Where this record came from */
124
103
  registrySource: EffortRegistrySource;
104
+ /** Canonical equipment slugs this effort is typically performed with (ordered, deduped). */
105
+ equipment?: string[];
106
+ /** Owning note in the content store, when this record is a note projection. */
107
+ ownerNoteId?: string;
108
+ /** Seed/source collection this record was imported from. */
109
+ sourceId?: string;
110
+ /** Source file path within the originating collection. */
111
+ sourcePath?: string;
125
112
  /** Clone-based derivation metadata (user efforts only) */
126
113
  derivation?: EffortDerivation;
127
114
  /** ISO timestamp */
@@ -158,6 +145,56 @@ interface EffortStorageAdapter {
158
145
  save(effort: IEffort): Promise<void>;
159
146
  delete(slug: string): Promise<void>;
160
147
  }
148
+ /**
149
+ * Canonical equipment entity (dumbbell, rower, kettlebell…).
150
+ *
151
+ * Same durable-identity rule as efforts: references point at the slug.
152
+ * No synthetic tier — unknown equipment stays authored source + diagnostics.
153
+ */
154
+ interface IEquipment {
155
+ /** UUID */
156
+ id: string;
157
+ /** Canonical identifier — unique, lowercase, hyphenated */
158
+ slug: string;
159
+ /** Primary human-readable name */
160
+ label: string;
161
+ /** Alternative names for exact matching */
162
+ aliases: string[];
163
+ /** Where this record came from */
164
+ registrySource: 'bundled' | 'user';
165
+ /** Free-form markdown description / notes */
166
+ body?: string;
167
+ /** Owning note in the content store, when this record is a note projection. */
168
+ ownerNoteId?: string;
169
+ /** Seed/source collection this record was imported from. */
170
+ sourceId?: string;
171
+ /** Source file path within the originating collection. */
172
+ sourcePath?: string;
173
+ /** ISO timestamp */
174
+ createdAt?: string;
175
+ /** ISO timestamp */
176
+ updatedAt?: string;
177
+ }
178
+ /** Read/write registry surface for equipment definitions (mirrors IEffortRegistry). */
179
+ interface IEquipmentRegistry {
180
+ resolve(slug: string): IEquipment | null;
181
+ resolveByAlias(label: string): IEquipment | null;
182
+ list(): readonly IEquipment[];
183
+ listByOrigin(origin: 'bundled' | 'user'): readonly IEquipment[];
184
+ upsert(equipment: IEquipment): Promise<void>;
185
+ delete(slug: string): Promise<void>;
186
+ loadBundled(): Promise<void>;
187
+ isInitialized(): boolean;
188
+ }
189
+ /**
190
+ * Pluggable asynchronous persistence adapter for user-defined equipment.
191
+ * Implemented by host environments (e.g. IndexedDB in browser, filesystem in CLI).
192
+ */
193
+ interface EquipmentStorageAdapter {
194
+ load(): Promise<IEquipment[]>;
195
+ save(equipment: IEquipment): Promise<void>;
196
+ delete(slug: string): Promise<void>;
197
+ }
161
198
  interface EffortResolutionOptions {
162
199
  /** Attribute metrics from /effort/:slug query params or logged execution metrics. */
163
200
  modifiers?: Record<string, string>;
@@ -215,6 +252,124 @@ interface EffortResolverOptions {
215
252
  }
216
253
  declare const DEFAULT_RESOLVER_OPTIONS: Required<EffortResolverOptions>;
217
254
 
255
+ /**
256
+ * Shared exact reference resolver — the single door for authored-label →
257
+ * canonical effort/equipment resolution used by the parser, editor preview,
258
+ * runtime enrichment, and seed/local indexing.
259
+ *
260
+ * Precedence (accepted proposal): explicit JSON ref > exact equipment word
261
+ * prefix + remaining effort (both must resolve uniquely) > whole-label exact
262
+ * (slug/alias) > note defaults (empty-movement fill only) > effort-definition
263
+ * equipment. Fuzzy matching never produces a canonical reference here —
264
+ * unknown/ambiguous/invalid values retain the authored source and carry a
265
+ * visible diagnostic instead of falling back.
266
+ *
267
+ * The index is built once per catalog (hydration), never per statement.
268
+ */
269
+
270
+ /** Catalog collections the resolver resolves against (hydrated from storage/seed). */
271
+ interface ReferenceCatalog {
272
+ efforts: readonly IEffort[];
273
+ equipment: readonly IEquipment[];
274
+ }
275
+ /** Note/workout-level reference defaults (`metrics.*` frontmatter). */
276
+ interface ReferenceResolutionDefaults {
277
+ /** Default effort slug applied when a statement's movement is otherwise missing. */
278
+ effort?: string;
279
+ /** Default equipment slugs applied when the line and effort define none. */
280
+ equipment?: readonly string[];
281
+ }
282
+ /** Result of resolving one authored label. */
283
+ interface ResolvedReferences {
284
+ matched: ReferenceMatchKind;
285
+ /** Full authored label — never rewritten. */
286
+ label: string;
287
+ /** Materialized effort, or null when unresolved. */
288
+ effort: ResolvedEffort | null;
289
+ /** Canonical effort ref, or null. */
290
+ effortRef: ReferenceRef | null;
291
+ /** Ordered deduplicated canonical equipment refs. */
292
+ equipment: ReferenceRef[];
293
+ /** Remaining movement text after the equipment prefix strip (split path). */
294
+ remaining: string;
295
+ /** Unknown/ambiguous/invalid findings — never silently dropped. */
296
+ diagnostics: ReferenceDiagnostic[];
297
+ }
298
+ /** Materialize an effort definition (MET/derivation math) — pass the legacy EffortResolver in hosts. */
299
+ type EffortMaterializer = (effort: IEffort) => ResolvedEffort;
300
+ interface ReferenceIndex {
301
+ /** Resolve an authored movement label (statement effort text or frontmatter value). */
302
+ resolve(label: string, defaults?: ReferenceResolutionDefaults): ResolvedReferences;
303
+ /** Exact slug/alias effort lookup — no fuzzy, never synthetic. */
304
+ resolveEffort(slugOrAlias: string): IEffort | null;
305
+ /** Exact slug/alias equipment lookup — no fuzzy. */
306
+ resolveEquipment(slugOrAlias: string): IEquipment | null;
307
+ /** Materialize a resolved definition (wraps the legacy resolver when provided). */
308
+ materialize(effort: IEffort): ResolvedEffort;
309
+ }
310
+ declare function createReferenceIndex(catalog: ReferenceCatalog, materialize?: EffortMaterializer): ReferenceIndex;
311
+ /**
312
+ * Canonical statement refs for index/analytics projection — the single shared
313
+ * replacement for the per-host `extractEffortSlugs` copies.
314
+ *
315
+ * ONLY validated durable refs are returned: canonical slugs carried on the
316
+ * statement's effort/equipment metrics by the shared resolver at parse time.
317
+ * Unresolved labels yield nothing here (their authored source and diagnostics
318
+ * stay on the statement) — resolve authored labels through
319
+ * `ReferenceIndex.resolve` when projecting un-parsed text.
320
+ */
321
+ declare function extractStatementRefs(statements: readonly ICodeStatement[]): {
322
+ efforts: string[];
323
+ equipment: string[];
324
+ };
325
+ /** Canonical slugify for label→candidate-slug hygiene in host projection code. */
326
+ declare function slugifyRefLabel(label: string): string;
327
+
328
+ interface IScript {
329
+ source: string;
330
+ statements: ICodeStatement[];
331
+ errors?: ParseError[] | undefined;
332
+ getIds(ids: number[]): ICodeStatement[];
333
+ getId(id: number): ICodeStatement | undefined;
334
+ getAt(index: number): ICodeStatement | undefined;
335
+ }
336
+ declare class WhiteboardScript implements IScript {
337
+ source: string;
338
+ statements: ICodeStatement[];
339
+ errors: ParseError[] | undefined;
340
+ private _idMap?;
341
+ constructor(source: string, statements: ICodeStatement[], errors?: ParseError[]);
342
+ /**
343
+ * Gets the ID-to-statement Map, building it lazily on first access.
344
+ * Provides O(1) lookups instead of O(n) find() calls.
345
+ */
346
+ private getIdMap;
347
+ /**
348
+ * Resolves multiple statement IDs to statements.
349
+ * Uses cached Map for O(n) performance instead of O(n²).
350
+ */
351
+ getIds(ids: number[]): ICodeStatement[];
352
+ /**
353
+ * Resolves a single statement ID to a statement.
354
+ * Uses cached Map for O(1) performance instead of O(n).
355
+ */
356
+ getId(id: number): ICodeStatement | undefined;
357
+ /**
358
+ * Gets a statement by its array index.
359
+ */
360
+ getAt(index: number): ICodeStatement | undefined;
361
+ /**
362
+ * Flattens grouped children (number[][]) and resolves to statements.
363
+ * Convenience wrapper for getIds(children.flat()).
364
+ */
365
+ getFlatChildren(children: number[][]): ICodeStatement[];
366
+ /**
367
+ * Resolves grouped children while preserving group structure.
368
+ * Maps each number[] group to ICodeStatement[] group.
369
+ */
370
+ getChildGroups(children: number[][]): ICodeStatement[][];
371
+ }
372
+
218
373
  /**
219
374
  * Minimal executable runtime action shape.
220
375
  *
@@ -514,6 +669,7 @@ interface RuntimeStackOptions extends IRuntimeOptions {
514
669
  hooks?: RuntimeStackHooks;
515
670
  analyticsOptions?: {
516
671
  effortResolver?: IEffortResolver;
672
+ references?: ReferenceIndex;
517
673
  userProfile?: {
518
674
  vo2max?: number;
519
675
  };
@@ -1936,6 +2092,8 @@ interface IAnalyticsEngine {
1936
2092
  interface AnalyticsContext {
1937
2093
  /** Effort resolver for canonical slug and fuzzy alias matching. */
1938
2094
  effortResolver: IEffortResolver;
2095
+ /** Shared reference index for canonical effort/equipment resolution. */
2096
+ references?: ReferenceIndex;
1939
2097
  }
1940
2098
 
1941
2099
  interface IJitCompiler {
@@ -2363,4 +2521,4 @@ declare function getRuntimeNowMs(): number;
2363
2521
  /** Creates an INowProvider that reads the browser sender-clock when available. */
2364
2522
  declare function createBrowserRuntimeNow(): INowProvider;
2365
2523
 
2366
- export { type IRuntimeOptions as $, type AnalyticsContext as A, type BehaviorEventType as B, type CompletionDecision as C, type IRuntimeMemory as D, type EffortResolverOptions as E, TypedMemoryReference as F, type MemorySearchCriteria as G, type IMemoryReference as H, type IEffortResolver as I, type RuntimeStackLogger as J, type StackObserver as K, type StackSnapshot as L, type MemoryTag as M, type StackListener as N, type OutputListener as O, MemoryTypeEnum as P, type IAnchorValue as Q, type ResolvedEffort as R, type SubscribeOptions as S, TimeSpan as T, type Unsubscribe as U, type ButtonConfig as V, WhiteboardScript as W, type IEventHandler as X, type HandlerScope as Y, type IScriptRuntime as Z, type TestableBlockConfig as _, type IEffortRegistry as a, ScriptRuntime as a0, type EventHandlerOptions as a1, type EventCallback as a2, type TimerState as a3, type IRealtimeProcessor as a4, type ISummaryProcessor as a5, type ProjectionResult as a6, type ButtonVariant as a7, type ButtonsState as a8, type ChildrenStatusState as a9, type StackEvent as aA, type TimerDirection as aB, VISIBILITY_ICONS as aC, VISIBILITY_LABELS as aD, createBrowserRuntimeNow as aE, disciplineFactorFor as aF, filterTagsByVisibility as aG, frozenNow as aH, getMetricVisibility as aI, getRuntimeNowMs as aJ, isEffortDiscipline as aK, isFragmentTag as aL, wallClockNow as aM, type CompletionState as aa, DEFAULT_RESOLVER_OPTIONS as ab, DEFAULT_RUNTIME_OPTIONS as ac, DISCIPLINE_FACTORS as ad, type DisplayState as ae, EFFORT_DISCIPLINES as af, EFFORT_REGISTRY_ORIGINS as ag, type EffortBaseAttributes as ah, type EffortDerivation as ai, type EffortDiscipline as aj, type EffortResolvedFrom as ak, type FenceDialect as al, type FragmentDisplayState as am, type FragmentState as an, type IAnalyticsProcessorDescriptor as ao, INTENSITY_TIERS as ap, type IScript as aq, type IntensityTier as ar, type InterceptMode as as, MemoryLocation as at, type MemoryType as au, type MemoryTypeMap as av, type MemoryValueOf as aw, type RoundState as ax, type RuntimeState as ay, type ScriptRuntimeDependencies as az, type IEffort as b, type EffortResolutionOptions as c, type EffortRegistrySource as d, type EffortStorageAdapter as e, type IRuntimeActionable as f, type IEventBus as g, type IRuntimeStack as h, type IRuntimeClock as i, type IJitCompiler as j, type INowProvider as k, type RuntimeStackOptions as l, type RuntimeError as m, type IEvent as n, type IRuntimeAction as o, type IAnalyticsEngine as p, type IRuntimeBlock as q, type IBehaviorContext as r, type BehaviorEventListener as s, type Unsubscribe$1 as t, type OutputOptions as u, type IMemoryLocation as v, type IRuntimeBehavior as w, type IBlockContext as x, type MetricVisibility as y, type BlockLifecycleOptions as z };
2524
+ export { type HandlerScope as $, type AnalyticsContext as A, type BehaviorEventType as B, type IBlockContext as C, type MetricVisibility as D, type EffortResolverOptions as E, type BlockLifecycleOptions as F, type CompletionDecision as G, type IRuntimeMemory as H, type IEquipment as I, TypedMemoryReference as J, type MemorySearchCriteria as K, type IMemoryReference as L, type MemoryTag as M, type RuntimeStackLogger as N, type OutputListener as O, type StackObserver as P, type StackSnapshot as Q, type ReferenceIndex as R, type SubscribeOptions as S, TimeSpan as T, type Unsubscribe as U, type StackListener as V, WhiteboardScript as W, MemoryTypeEnum as X, type IAnchorValue as Y, type ButtonConfig as Z, type IEventHandler as _, type ReferenceResolutionDefaults as a, resolveSourceRank as a$, type IScriptRuntime as a0, type TestableBlockConfig as a1, type IRuntimeOptions as a2, ScriptRuntime as a3, type EventHandlerOptions as a4, type EventCallback as a5, type TimerState as a6, type IRealtimeProcessor as a7, type ISummaryProcessor as a8, type ProjectionResult as a9, type InterceptMode as aA, MemoryLocation as aB, type MemoryType as aC, type MemoryTypeMap as aD, type MemoryValueOf as aE, type ReferenceCatalog as aF, type ResolvedReferences as aG, type RoundState as aH, type RuntimeState as aI, type ScriptRuntimeDependencies as aJ, type StackEvent as aK, type TimerDirection as aL, VISIBILITY_ICONS as aM, VISIBILITY_LABELS as aN, createBrowserRuntimeNow as aO, createReferenceIndex as aP, dedupeEntitiesByPrecedence as aQ, disciplineFactorFor as aR, extractStatementRefs as aS, filterTagsByVisibility as aT, frozenNow as aU, getMetricVisibility as aV, getRuntimeNowMs as aW, isEffortDiscipline as aX, isFragmentTag as aY, resolveEntityRank as aZ, resolveEntityTier as a_, type ButtonVariant as aa, type ButtonsState as ab, CATALOG_PRECEDENCE_RANK as ac, type CatalogPrecedenceTier as ad, type ChildrenStatusState as ae, type CompletionState as af, DEFAULT_RESOLVER_OPTIONS as ag, DEFAULT_RUNTIME_OPTIONS as ah, DISCIPLINE_FACTORS as ai, type DisplayState as aj, EFFORT_DISCIPLINES as ak, EFFORT_REGISTRY_ORIGINS as al, type EffortBaseAttributes as am, type EffortDerivation as an, type EffortDiscipline as ao, type EffortMaterializer as ap, type EffortResolvedFrom as aq, type EquipmentStorageAdapter as ar, type FenceDialect as as, type FragmentDisplayState as at, type FragmentState as au, type IAnalyticsProcessorDescriptor as av, type IEquipmentRegistry as aw, INTENSITY_TIERS as ax, type IScript as ay, type IntensityTier as az, type IEffort as b, resolveSourceTier as b0, slugifyRefLabel as b1, wallClockNow as b2, type IEffortResolver as c, type IEffortRegistry as d, type EffortResolutionOptions as e, type ResolvedEffort as f, type EffortRegistrySource as g, type EffortStorageAdapter as h, type IRuntimeActionable as i, type IEventBus as j, type IRuntimeStack as k, type IRuntimeClock as l, type IJitCompiler as m, type INowProvider as n, type RuntimeStackOptions as o, type RuntimeError as p, type IEvent as q, type IRuntimeAction as r, type IAnalyticsEngine as s, type IRuntimeBlock as t, type IBehaviorContext as u, type BehaviorEventListener as v, type Unsubscribe$1 as w, type OutputOptions as x, type IMemoryLocation as y, type IRuntimeBehavior as z };
@@ -1,49 +1,4 @@
1
- import { ICodeStatement, ParseError, MetricContainer, IMetric, BlockKey, TimeSpan as TimeSpan$1, OutputStatementType, MetricType, IOutputStatement, MetricOrigin } from '@bitcobblers/wod-wiki-core';
2
-
3
- interface IScript {
4
- source: string;
5
- statements: ICodeStatement[];
6
- errors?: ParseError[] | undefined;
7
- getIds(ids: number[]): ICodeStatement[];
8
- getId(id: number): ICodeStatement | undefined;
9
- getAt(index: number): ICodeStatement | undefined;
10
- }
11
- declare class WhiteboardScript implements IScript {
12
- source: string;
13
- statements: ICodeStatement[];
14
- errors: ParseError[] | undefined;
15
- private _idMap?;
16
- constructor(source: string, statements: ICodeStatement[], errors?: ParseError[]);
17
- /**
18
- * Gets the ID-to-statement Map, building it lazily on first access.
19
- * Provides O(1) lookups instead of O(n) find() calls.
20
- */
21
- private getIdMap;
22
- /**
23
- * Resolves multiple statement IDs to statements.
24
- * Uses cached Map for O(n) performance instead of O(n²).
25
- */
26
- getIds(ids: number[]): ICodeStatement[];
27
- /**
28
- * Resolves a single statement ID to a statement.
29
- * Uses cached Map for O(1) performance instead of O(n).
30
- */
31
- getId(id: number): ICodeStatement | undefined;
32
- /**
33
- * Gets a statement by its array index.
34
- */
35
- getAt(index: number): ICodeStatement | undefined;
36
- /**
37
- * Flattens grouped children (number[][]) and resolves to statements.
38
- * Convenience wrapper for getIds(children.flat()).
39
- */
40
- getFlatChildren(children: number[][]): ICodeStatement[];
41
- /**
42
- * Resolves grouped children while preserving group structure.
43
- * Maps each number[] group to ICodeStatement[] group.
44
- */
45
- getChildGroups(children: number[][]): ICodeStatement[][];
46
- }
1
+ import { ReferenceMatchKind, ReferenceRef, ReferenceDiagnostic, ICodeStatement, ParseError, MetricContainer, IMetric, BlockKey, TimeSpan as TimeSpan$1, OutputStatementType, MetricType, IOutputStatement, MetricOrigin } from '@bitcobblers/wod-wiki-core';
47
2
 
48
3
  /**
49
4
  * Canonical discipline vocabulary — the single source of truth for effort
@@ -82,6 +37,30 @@ type EffortRegistrySource = 'bundled' | 'user' | 'synthetic-unresolved';
82
37
  /** Origins that hold real registry records (synthetic-unresolved entries are
83
38
  * resolver phantoms, never listed) — the WQL `origin:` filter vocabulary. */
84
39
  declare const EFFORT_REGISTRY_ORIGINS: readonly ["bundled", "user"];
40
+ /**
41
+ * Precedence tiers for resolving collisions across seed catalogs and local edits.
42
+ * Order: core (0) < community (1) < imported (2) < user (3).
43
+ */
44
+ type CatalogPrecedenceTier = 'core' | 'community' | 'imported' | 'user';
45
+ declare const CATALOG_PRECEDENCE_RANK: Readonly<Record<CatalogPrecedenceTier, number>>;
46
+ /** Resolve the precedence tier for a seed source id or checkpoint key (`seed:<id>`). */
47
+ declare function resolveSourceTier(sourceIdOrMetaKey?: string | null, explicitTier?: CatalogPrecedenceTier): CatalogPrecedenceTier;
48
+ declare function resolveSourceRank(sourceIdOrMetaKey?: string | null, explicitTier?: CatalogPrecedenceTier): number;
49
+ /** Resolve the precedence tier of an effort/equipment definition record. */
50
+ declare function resolveEntityTier(entity: {
51
+ registrySource?: string;
52
+ sourceId?: string | null;
53
+ }): CatalogPrecedenceTier;
54
+ declare function resolveEntityRank(entity: {
55
+ registrySource?: string;
56
+ sourceId?: string | null;
57
+ }): number;
58
+ /** Deduplicate definition entities by slug, retaining the highest-precedence record per slug. */
59
+ declare function dedupeEntitiesByPrecedence<T extends {
60
+ slug: string;
61
+ registrySource?: string;
62
+ sourceId?: string | null;
63
+ }>(entities: readonly T[]): T[];
85
64
  /** Intensity tiers, low → high — the WQL `intensity:` filter vocabulary. */
86
65
  declare const INTENSITY_TIERS: readonly ["low", "moderate", "high"];
87
66
  type IntensityTier = (typeof INTENSITY_TIERS)[number];
@@ -122,6 +101,14 @@ interface IEffort {
122
101
  baseAttributes: EffortBaseAttributes;
123
102
  /** Where this record came from */
124
103
  registrySource: EffortRegistrySource;
104
+ /** Canonical equipment slugs this effort is typically performed with (ordered, deduped). */
105
+ equipment?: string[];
106
+ /** Owning note in the content store, when this record is a note projection. */
107
+ ownerNoteId?: string;
108
+ /** Seed/source collection this record was imported from. */
109
+ sourceId?: string;
110
+ /** Source file path within the originating collection. */
111
+ sourcePath?: string;
125
112
  /** Clone-based derivation metadata (user efforts only) */
126
113
  derivation?: EffortDerivation;
127
114
  /** ISO timestamp */
@@ -158,6 +145,56 @@ interface EffortStorageAdapter {
158
145
  save(effort: IEffort): Promise<void>;
159
146
  delete(slug: string): Promise<void>;
160
147
  }
148
+ /**
149
+ * Canonical equipment entity (dumbbell, rower, kettlebell…).
150
+ *
151
+ * Same durable-identity rule as efforts: references point at the slug.
152
+ * No synthetic tier — unknown equipment stays authored source + diagnostics.
153
+ */
154
+ interface IEquipment {
155
+ /** UUID */
156
+ id: string;
157
+ /** Canonical identifier — unique, lowercase, hyphenated */
158
+ slug: string;
159
+ /** Primary human-readable name */
160
+ label: string;
161
+ /** Alternative names for exact matching */
162
+ aliases: string[];
163
+ /** Where this record came from */
164
+ registrySource: 'bundled' | 'user';
165
+ /** Free-form markdown description / notes */
166
+ body?: string;
167
+ /** Owning note in the content store, when this record is a note projection. */
168
+ ownerNoteId?: string;
169
+ /** Seed/source collection this record was imported from. */
170
+ sourceId?: string;
171
+ /** Source file path within the originating collection. */
172
+ sourcePath?: string;
173
+ /** ISO timestamp */
174
+ createdAt?: string;
175
+ /** ISO timestamp */
176
+ updatedAt?: string;
177
+ }
178
+ /** Read/write registry surface for equipment definitions (mirrors IEffortRegistry). */
179
+ interface IEquipmentRegistry {
180
+ resolve(slug: string): IEquipment | null;
181
+ resolveByAlias(label: string): IEquipment | null;
182
+ list(): readonly IEquipment[];
183
+ listByOrigin(origin: 'bundled' | 'user'): readonly IEquipment[];
184
+ upsert(equipment: IEquipment): Promise<void>;
185
+ delete(slug: string): Promise<void>;
186
+ loadBundled(): Promise<void>;
187
+ isInitialized(): boolean;
188
+ }
189
+ /**
190
+ * Pluggable asynchronous persistence adapter for user-defined equipment.
191
+ * Implemented by host environments (e.g. IndexedDB in browser, filesystem in CLI).
192
+ */
193
+ interface EquipmentStorageAdapter {
194
+ load(): Promise<IEquipment[]>;
195
+ save(equipment: IEquipment): Promise<void>;
196
+ delete(slug: string): Promise<void>;
197
+ }
161
198
  interface EffortResolutionOptions {
162
199
  /** Attribute metrics from /effort/:slug query params or logged execution metrics. */
163
200
  modifiers?: Record<string, string>;
@@ -215,6 +252,124 @@ interface EffortResolverOptions {
215
252
  }
216
253
  declare const DEFAULT_RESOLVER_OPTIONS: Required<EffortResolverOptions>;
217
254
 
255
+ /**
256
+ * Shared exact reference resolver — the single door for authored-label →
257
+ * canonical effort/equipment resolution used by the parser, editor preview,
258
+ * runtime enrichment, and seed/local indexing.
259
+ *
260
+ * Precedence (accepted proposal): explicit JSON ref > exact equipment word
261
+ * prefix + remaining effort (both must resolve uniquely) > whole-label exact
262
+ * (slug/alias) > note defaults (empty-movement fill only) > effort-definition
263
+ * equipment. Fuzzy matching never produces a canonical reference here —
264
+ * unknown/ambiguous/invalid values retain the authored source and carry a
265
+ * visible diagnostic instead of falling back.
266
+ *
267
+ * The index is built once per catalog (hydration), never per statement.
268
+ */
269
+
270
+ /** Catalog collections the resolver resolves against (hydrated from storage/seed). */
271
+ interface ReferenceCatalog {
272
+ efforts: readonly IEffort[];
273
+ equipment: readonly IEquipment[];
274
+ }
275
+ /** Note/workout-level reference defaults (`metrics.*` frontmatter). */
276
+ interface ReferenceResolutionDefaults {
277
+ /** Default effort slug applied when a statement's movement is otherwise missing. */
278
+ effort?: string;
279
+ /** Default equipment slugs applied when the line and effort define none. */
280
+ equipment?: readonly string[];
281
+ }
282
+ /** Result of resolving one authored label. */
283
+ interface ResolvedReferences {
284
+ matched: ReferenceMatchKind;
285
+ /** Full authored label — never rewritten. */
286
+ label: string;
287
+ /** Materialized effort, or null when unresolved. */
288
+ effort: ResolvedEffort | null;
289
+ /** Canonical effort ref, or null. */
290
+ effortRef: ReferenceRef | null;
291
+ /** Ordered deduplicated canonical equipment refs. */
292
+ equipment: ReferenceRef[];
293
+ /** Remaining movement text after the equipment prefix strip (split path). */
294
+ remaining: string;
295
+ /** Unknown/ambiguous/invalid findings — never silently dropped. */
296
+ diagnostics: ReferenceDiagnostic[];
297
+ }
298
+ /** Materialize an effort definition (MET/derivation math) — pass the legacy EffortResolver in hosts. */
299
+ type EffortMaterializer = (effort: IEffort) => ResolvedEffort;
300
+ interface ReferenceIndex {
301
+ /** Resolve an authored movement label (statement effort text or frontmatter value). */
302
+ resolve(label: string, defaults?: ReferenceResolutionDefaults): ResolvedReferences;
303
+ /** Exact slug/alias effort lookup — no fuzzy, never synthetic. */
304
+ resolveEffort(slugOrAlias: string): IEffort | null;
305
+ /** Exact slug/alias equipment lookup — no fuzzy. */
306
+ resolveEquipment(slugOrAlias: string): IEquipment | null;
307
+ /** Materialize a resolved definition (wraps the legacy resolver when provided). */
308
+ materialize(effort: IEffort): ResolvedEffort;
309
+ }
310
+ declare function createReferenceIndex(catalog: ReferenceCatalog, materialize?: EffortMaterializer): ReferenceIndex;
311
+ /**
312
+ * Canonical statement refs for index/analytics projection — the single shared
313
+ * replacement for the per-host `extractEffortSlugs` copies.
314
+ *
315
+ * ONLY validated durable refs are returned: canonical slugs carried on the
316
+ * statement's effort/equipment metrics by the shared resolver at parse time.
317
+ * Unresolved labels yield nothing here (their authored source and diagnostics
318
+ * stay on the statement) — resolve authored labels through
319
+ * `ReferenceIndex.resolve` when projecting un-parsed text.
320
+ */
321
+ declare function extractStatementRefs(statements: readonly ICodeStatement[]): {
322
+ efforts: string[];
323
+ equipment: string[];
324
+ };
325
+ /** Canonical slugify for label→candidate-slug hygiene in host projection code. */
326
+ declare function slugifyRefLabel(label: string): string;
327
+
328
+ interface IScript {
329
+ source: string;
330
+ statements: ICodeStatement[];
331
+ errors?: ParseError[] | undefined;
332
+ getIds(ids: number[]): ICodeStatement[];
333
+ getId(id: number): ICodeStatement | undefined;
334
+ getAt(index: number): ICodeStatement | undefined;
335
+ }
336
+ declare class WhiteboardScript implements IScript {
337
+ source: string;
338
+ statements: ICodeStatement[];
339
+ errors: ParseError[] | undefined;
340
+ private _idMap?;
341
+ constructor(source: string, statements: ICodeStatement[], errors?: ParseError[]);
342
+ /**
343
+ * Gets the ID-to-statement Map, building it lazily on first access.
344
+ * Provides O(1) lookups instead of O(n) find() calls.
345
+ */
346
+ private getIdMap;
347
+ /**
348
+ * Resolves multiple statement IDs to statements.
349
+ * Uses cached Map for O(n) performance instead of O(n²).
350
+ */
351
+ getIds(ids: number[]): ICodeStatement[];
352
+ /**
353
+ * Resolves a single statement ID to a statement.
354
+ * Uses cached Map for O(1) performance instead of O(n).
355
+ */
356
+ getId(id: number): ICodeStatement | undefined;
357
+ /**
358
+ * Gets a statement by its array index.
359
+ */
360
+ getAt(index: number): ICodeStatement | undefined;
361
+ /**
362
+ * Flattens grouped children (number[][]) and resolves to statements.
363
+ * Convenience wrapper for getIds(children.flat()).
364
+ */
365
+ getFlatChildren(children: number[][]): ICodeStatement[];
366
+ /**
367
+ * Resolves grouped children while preserving group structure.
368
+ * Maps each number[] group to ICodeStatement[] group.
369
+ */
370
+ getChildGroups(children: number[][]): ICodeStatement[][];
371
+ }
372
+
218
373
  /**
219
374
  * Minimal executable runtime action shape.
220
375
  *
@@ -514,6 +669,7 @@ interface RuntimeStackOptions extends IRuntimeOptions {
514
669
  hooks?: RuntimeStackHooks;
515
670
  analyticsOptions?: {
516
671
  effortResolver?: IEffortResolver;
672
+ references?: ReferenceIndex;
517
673
  userProfile?: {
518
674
  vo2max?: number;
519
675
  };
@@ -1936,6 +2092,8 @@ interface IAnalyticsEngine {
1936
2092
  interface AnalyticsContext {
1937
2093
  /** Effort resolver for canonical slug and fuzzy alias matching. */
1938
2094
  effortResolver: IEffortResolver;
2095
+ /** Shared reference index for canonical effort/equipment resolution. */
2096
+ references?: ReferenceIndex;
1939
2097
  }
1940
2098
 
1941
2099
  interface IJitCompiler {
@@ -2363,4 +2521,4 @@ declare function getRuntimeNowMs(): number;
2363
2521
  /** Creates an INowProvider that reads the browser sender-clock when available. */
2364
2522
  declare function createBrowserRuntimeNow(): INowProvider;
2365
2523
 
2366
- export { type IRuntimeOptions as $, type AnalyticsContext as A, type BehaviorEventType as B, type CompletionDecision as C, type IRuntimeMemory as D, type EffortResolverOptions as E, TypedMemoryReference as F, type MemorySearchCriteria as G, type IMemoryReference as H, type IEffortResolver as I, type RuntimeStackLogger as J, type StackObserver as K, type StackSnapshot as L, type MemoryTag as M, type StackListener as N, type OutputListener as O, MemoryTypeEnum as P, type IAnchorValue as Q, type ResolvedEffort as R, type SubscribeOptions as S, TimeSpan as T, type Unsubscribe as U, type ButtonConfig as V, WhiteboardScript as W, type IEventHandler as X, type HandlerScope as Y, type IScriptRuntime as Z, type TestableBlockConfig as _, type IEffortRegistry as a, ScriptRuntime as a0, type EventHandlerOptions as a1, type EventCallback as a2, type TimerState as a3, type IRealtimeProcessor as a4, type ISummaryProcessor as a5, type ProjectionResult as a6, type ButtonVariant as a7, type ButtonsState as a8, type ChildrenStatusState as a9, type StackEvent as aA, type TimerDirection as aB, VISIBILITY_ICONS as aC, VISIBILITY_LABELS as aD, createBrowserRuntimeNow as aE, disciplineFactorFor as aF, filterTagsByVisibility as aG, frozenNow as aH, getMetricVisibility as aI, getRuntimeNowMs as aJ, isEffortDiscipline as aK, isFragmentTag as aL, wallClockNow as aM, type CompletionState as aa, DEFAULT_RESOLVER_OPTIONS as ab, DEFAULT_RUNTIME_OPTIONS as ac, DISCIPLINE_FACTORS as ad, type DisplayState as ae, EFFORT_DISCIPLINES as af, EFFORT_REGISTRY_ORIGINS as ag, type EffortBaseAttributes as ah, type EffortDerivation as ai, type EffortDiscipline as aj, type EffortResolvedFrom as ak, type FenceDialect as al, type FragmentDisplayState as am, type FragmentState as an, type IAnalyticsProcessorDescriptor as ao, INTENSITY_TIERS as ap, type IScript as aq, type IntensityTier as ar, type InterceptMode as as, MemoryLocation as at, type MemoryType as au, type MemoryTypeMap as av, type MemoryValueOf as aw, type RoundState as ax, type RuntimeState as ay, type ScriptRuntimeDependencies as az, type IEffort as b, type EffortResolutionOptions as c, type EffortRegistrySource as d, type EffortStorageAdapter as e, type IRuntimeActionable as f, type IEventBus as g, type IRuntimeStack as h, type IRuntimeClock as i, type IJitCompiler as j, type INowProvider as k, type RuntimeStackOptions as l, type RuntimeError as m, type IEvent as n, type IRuntimeAction as o, type IAnalyticsEngine as p, type IRuntimeBlock as q, type IBehaviorContext as r, type BehaviorEventListener as s, type Unsubscribe$1 as t, type OutputOptions as u, type IMemoryLocation as v, type IRuntimeBehavior as w, type IBlockContext as x, type MetricVisibility as y, type BlockLifecycleOptions as z };
2524
+ export { type HandlerScope as $, type AnalyticsContext as A, type BehaviorEventType as B, type IBlockContext as C, type MetricVisibility as D, type EffortResolverOptions as E, type BlockLifecycleOptions as F, type CompletionDecision as G, type IRuntimeMemory as H, type IEquipment as I, TypedMemoryReference as J, type MemorySearchCriteria as K, type IMemoryReference as L, type MemoryTag as M, type RuntimeStackLogger as N, type OutputListener as O, type StackObserver as P, type StackSnapshot as Q, type ReferenceIndex as R, type SubscribeOptions as S, TimeSpan as T, type Unsubscribe as U, type StackListener as V, WhiteboardScript as W, MemoryTypeEnum as X, type IAnchorValue as Y, type ButtonConfig as Z, type IEventHandler as _, type ReferenceResolutionDefaults as a, resolveSourceRank as a$, type IScriptRuntime as a0, type TestableBlockConfig as a1, type IRuntimeOptions as a2, ScriptRuntime as a3, type EventHandlerOptions as a4, type EventCallback as a5, type TimerState as a6, type IRealtimeProcessor as a7, type ISummaryProcessor as a8, type ProjectionResult as a9, type InterceptMode as aA, MemoryLocation as aB, type MemoryType as aC, type MemoryTypeMap as aD, type MemoryValueOf as aE, type ReferenceCatalog as aF, type ResolvedReferences as aG, type RoundState as aH, type RuntimeState as aI, type ScriptRuntimeDependencies as aJ, type StackEvent as aK, type TimerDirection as aL, VISIBILITY_ICONS as aM, VISIBILITY_LABELS as aN, createBrowserRuntimeNow as aO, createReferenceIndex as aP, dedupeEntitiesByPrecedence as aQ, disciplineFactorFor as aR, extractStatementRefs as aS, filterTagsByVisibility as aT, frozenNow as aU, getMetricVisibility as aV, getRuntimeNowMs as aW, isEffortDiscipline as aX, isFragmentTag as aY, resolveEntityRank as aZ, resolveEntityTier as a_, type ButtonVariant as aa, type ButtonsState as ab, CATALOG_PRECEDENCE_RANK as ac, type CatalogPrecedenceTier as ad, type ChildrenStatusState as ae, type CompletionState as af, DEFAULT_RESOLVER_OPTIONS as ag, DEFAULT_RUNTIME_OPTIONS as ah, DISCIPLINE_FACTORS as ai, type DisplayState as aj, EFFORT_DISCIPLINES as ak, EFFORT_REGISTRY_ORIGINS as al, type EffortBaseAttributes as am, type EffortDerivation as an, type EffortDiscipline as ao, type EffortMaterializer as ap, type EffortResolvedFrom as aq, type EquipmentStorageAdapter as ar, type FenceDialect as as, type FragmentDisplayState as at, type FragmentState as au, type IAnalyticsProcessorDescriptor as av, type IEquipmentRegistry as aw, INTENSITY_TIERS as ax, type IScript as ay, type IntensityTier as az, type IEffort as b, resolveSourceTier as b0, slugifyRefLabel as b1, wallClockNow as b2, type IEffortResolver as c, type IEffortRegistry as d, type EffortResolutionOptions as e, type ResolvedEffort as f, type EffortRegistrySource as g, type EffortStorageAdapter as h, type IRuntimeActionable as i, type IEventBus as j, type IRuntimeStack as k, type IRuntimeClock as l, type IJitCompiler as m, type INowProvider as n, type RuntimeStackOptions as o, type RuntimeError as p, type IEvent as q, type IRuntimeAction as r, type IAnalyticsEngine as s, type IRuntimeBlock as t, type IBehaviorContext as u, type BehaviorEventListener as v, type Unsubscribe$1 as w, type OutputOptions as x, type IMemoryLocation as y, type IRuntimeBehavior as z };