@bitcobblers/wod-wiki-lang 0.46.2168 → 0.47.2170

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.
@@ -847,6 +847,176 @@ interface CalculationDefinition {
847
847
  };
848
848
  }
849
849
 
850
+ /**
851
+ * Dimension-aware value model for calc evaluation.
852
+ *
853
+ * Numbers carry a dimension vector and (optionally) the unit they were
854
+ * measured in; arithmetic tracks vectors per spec §5.1. `absent` is the
855
+ * missing-data value: it propagates through arithmetic, reads as `false` in
856
+ * predicates (applicability decision, #848), and is what `has()` probes.
857
+ */
858
+
859
+ type Val = {
860
+ kind: 'number';
861
+ value: number;
862
+ dim: DimVector;
863
+ unit?: string;
864
+ } | {
865
+ kind: 'string';
866
+ value: string;
867
+ } | {
868
+ kind: 'series';
869
+ points: Map<number, number>;
870
+ dim: DimVector;
871
+ unit?: string;
872
+ } | {
873
+ kind: 'period';
874
+ days: number;
875
+ } | {
876
+ kind: 'absent';
877
+ };
878
+ declare const ABSENT: Val;
879
+ declare function num(value: number, dim?: DimVector, unit?: string): Val;
880
+ declare function str(value: string): Val;
881
+ /** Predicate truthiness: absent → false; numbers → ≠ 0; strings → non-empty. */
882
+ declare function truthy(v: Val): boolean;
883
+
884
+ /**
885
+ * Expression evaluator for the composed calculations layer.
886
+ *
887
+ * The core owns arithmetic, comparison/logic, and the scalar function table
888
+ * (min, max, abs, round, floor, ceil, clamp, convert, has). Everything
889
+ * scope-dependent — metric refs, context nodes, stream aggregates, lookup(),
890
+ * WQL atoms — resolves through the EvalContext, so the same evaluator serves
891
+ * segment, workout, and store scopes (spec §3.1).
892
+ */
893
+
894
+ declare class CalcEvalError extends Error {
895
+ constructor(message: string);
896
+ }
897
+ interface EvalContext {
898
+ /** Resolve a ref atom (metric, context node, library node). ABSENT when missing. */
899
+ resolveRef(name: string): Val;
900
+ /**
901
+ * Extension functions (stream aggregates, lookup). Receives evaluated args
902
+ * plus the raw arg nodes (aggregates need the filter node unevaluated).
903
+ * Return undefined to signal "not mine" → CalcEvalError.
904
+ */
905
+ callFunction?(name: string, args: Val[], rawArgs: ExprNode[]): Val | undefined;
906
+ /** Store-scope WQL selections (QueryService). Store scope only. */
907
+ resolveWql?(node: Extract<ExprNode, {
908
+ kind: 'wql';
909
+ }>): Val;
910
+ }
911
+ declare function evaluate(node: ExprNode, ctx: EvalContext): Val;
912
+
913
+ /**
914
+ * Lookup table registry (spec §4).
915
+ *
916
+ * Tables are adapters over heterogeneous sources (effort resolver, static
917
+ * maps, user profile) exposing a uniform single-row lookup contract:
918
+ * `lookup("table", keyExpr, "field")`. Registration is layered —
919
+ * bundled → dialect → user — with later layers replacing earlier ones
920
+ * (mirrors the Dialect Stack's personal-overrides-last rule). Miss behavior
921
+ * is per-table: `absent` yields the absent value; `default-row` yields a
922
+ * synthetic row so calcs never see a miss.
923
+ */
924
+
925
+ interface LookupFieldDef {
926
+ dimension: DimVector;
927
+ type: 'number' | 'string';
928
+ }
929
+ interface ILookupTable {
930
+ readonly id: string;
931
+ readonly fields: Record<string, LookupFieldDef>;
932
+ readonly missPolicy: 'absent' | 'default-row';
933
+ /** Single-row lookup. `absent` tables return undefined on a miss. */
934
+ get(key: string, field: string): Val | undefined;
935
+ }
936
+ type LookupLayer = 'bundled' | 'dialect' | 'user';
937
+ declare class LookupRegistry {
938
+ private readonly tables;
939
+ /** Register a table; a later-or-equal layer replaces the existing entry. */
940
+ register(table: ILookupTable, layer?: LookupLayer): void;
941
+ get(tableId: string): ILookupTable | undefined;
942
+ /** Field dimension for static checking; undefined when table/field unknown. */
943
+ fieldDim(tableId: string, field: string): DimVector | undefined;
944
+ /** Runtime lookup honoring the table's miss policy. */
945
+ lookup(tableId: string, key: string, field: string): Val;
946
+ /**
947
+ * EvalContext `callFunction` implementation for `lookup("table", key, "field")`.
948
+ * Compose with other extension functions (aggregates) at the engine layer.
949
+ */
950
+ readonly callFunction: EvalContext['callFunction'];
951
+ }
952
+
953
+ /**
954
+ * MetricShakeOutQueue — Two-stage dependency-ordered metric evaluation module.
955
+ *
956
+ * Collects static Metrics and statement-level Metric Equations (`metrics:`)
957
+ * plus workout/query Summary Metrics (`summaries:`) across stacked Property
958
+ * Notes in specificity precedence:
959
+ * Statement/Runtime > Inline Tag > Effort > Equipment > Note Frontmatter > Tag Category
960
+ *
961
+ * Stage 1 (`plan`): resolves static metrics and compile-time equations in
962
+ * topological waves, injects compiler hints, and defers equations whose
963
+ * required inputs depend on runtime-only atoms (`elapsed`, `spans`, etc.).
964
+ *
965
+ * Stage 2 (`log`): resolves all remaining equations against the executed
966
+ * statement metrics and emits a structured Skipped-Dependency Diagnostic
967
+ * metric (`origin: 'diagnostic'`, `type: MetricType.Diagnostic`) for any
968
+ * equation whose required inputs remain absent after the fixed-point pass.
969
+ */
970
+
971
+ type PropertySourceLayer = 'statement' | 'tag' | 'effort' | 'equipment' | 'note' | 'category';
972
+ interface PropertyRuleInput {
973
+ readonly layer: Exclude<PropertySourceLayer, 'statement'>;
974
+ readonly sourceSlug: string;
975
+ readonly metrics?: Readonly<Record<string, string | number | readonly string[]>>;
976
+ readonly summaries?: Readonly<Record<string, string>>;
977
+ readonly hints?: Readonly<Record<string, unknown>>;
978
+ }
979
+ interface SkippedDependencyDiagnostic {
980
+ readonly target: string;
981
+ readonly expression: string;
982
+ readonly sourceLayer: Exclude<PropertySourceLayer, 'statement'>;
983
+ readonly sourceSlug: string;
984
+ readonly missing: readonly string[];
985
+ }
986
+ interface ShakeOutResult {
987
+ readonly resolved: readonly string[];
988
+ readonly deferredRuntime: readonly string[];
989
+ readonly diagnostics: readonly SkippedDependencyDiagnostic[];
990
+ readonly inferredDims: Readonly<Record<string, DimVector>>;
991
+ }
992
+ interface ShakeOutQueueOptions {
993
+ readonly stage: 'plan' | 'log';
994
+ readonly sources: readonly PropertyRuleInput[];
995
+ readonly lookups?: LookupRegistry;
996
+ readonly lastEffortSlug?: string;
997
+ }
998
+ /**
999
+ * Extract `metrics:` and `summaries:` maps from a parsed frontmatter record
1000
+ * (supporting both flat `metrics.foo` / `summaries.bar` keys and nested maps).
1001
+ */
1002
+ declare function extractPropertyRulesFromMeta(meta: Readonly<Record<string, unknown>>, layer: Exclude<PropertySourceLayer, 'statement'>, sourceSlug: string): PropertyRuleInput;
1003
+ /**
1004
+ * Extract `PropertyRuleInput` records from a `TagIndex` for the given tag slugs.
1005
+ * Supports both statement-level `metrics` (static or equation) and workout-level
1006
+ * `summaries.<key>` contributions on tags (including nested tags).
1007
+ */
1008
+ declare function extractTagPropertyRules(tags: TagIndex | undefined, slugs: readonly string[]): PropertyRuleInput[];
1009
+ /**
1010
+ * Compile `summaries:` equations across stacked Property Notes into workout-scope
1011
+ * `CalculationDefinition` records. Higher-precedence layers shadow lower layers
1012
+ * when both define the same summary key.
1013
+ */
1014
+ declare function compilePropertySummaryCalcs(sources: readonly PropertyRuleInput[]): CalculationDefinition[];
1015
+ /**
1016
+ * Run the two-stage Metric Shake-Out Queue on a statement's MetricContainer.
1017
+ */
1018
+ declare function runMetricShakeOutQueue(container: MetricContainer, options: ShakeOutQueueOptions): ShakeOutResult;
1019
+
850
1020
  /**
851
1021
  * Factory function type for wrapping blocks in debug mode.
852
1022
  * Receives the original block and returns a wrapped version.
@@ -948,6 +1118,8 @@ interface RuntimeStackOptions extends IRuntimeOptions {
948
1118
  * bundle a profile applies.
949
1119
  */
950
1120
  activeTags?: readonly string[];
1121
+ /** Property Note metric/summary rules active for this run or block. */
1122
+ propertySources?: readonly PropertyRuleInput[];
951
1123
  };
952
1124
  /**
953
1125
  * Sound configuration for this run.
@@ -2819,4 +2991,4 @@ declare function getRuntimeNowMs(): number;
2819
2991
  /** Creates an INowProvider that reads the browser sender-clock when available. */
2820
2992
  declare function createBrowserRuntimeNow(): INowProvider;
2821
2993
 
2822
- export { type SoundProfile as $, type AnalyticsContext as A, type BehaviorEventType as B, type IMemoryLocation as C, type IRuntimeBehavior as D, type EffortResolverOptions as E, type IBlockContext as F, type MetricVisibility as G, type BlockLifecycleOptions as H, type IEquipment as I, type CompletionDecision as J, type IRuntimeMemory as K, TypedMemoryReference as L, type MemoryTag as M, type MemorySearchCriteria as N, type OutputListener as O, type IMemoryReference as P, type RuntimeStackLogger as Q, type ReferenceIndex as R, type SubscribeOptions as S, TimeSpan as T, type Unsubscribe as U, type StackObserver as V, WhiteboardScript as W, type StackSnapshot as X, type StackListener as Y, MemoryTypeEnum as Z, type IAnchorValue as _, type ReferenceResolutionDefaults as a, type SeedPrecedenceTier as a$, type ButtonConfig as a0, type IEventHandler as a1, type HandlerScope as a2, type IScriptRuntime as a3, type TestableBlockConfig as a4, type IRuntimeOptions as a5, ScriptRuntime as a6, type EventHandlerOptions as a7, type EventCallback as a8, type TimerState as a9, type DisplayState as aA, EFFORT_DISCIPLINES as aB, EFFORT_REGISTRY_ORIGINS as aC, type EffortBaseAttributes as aD, type EffortDerivation as aE, type EffortDiscipline as aF, type EffortMaterializer as aG, type EffortResolvedFrom as aH, type FenceDialect as aI, type FragmentDisplayState as aJ, type FragmentState as aK, type IAnalyticsProcessorDescriptor as aL, INTENSITY_TIERS as aM, type IScript as aN, type IntensityTier as aO, type InterceptMode as aP, MemoryLocation as aQ, type MemoryType as aR, type MemoryTypeMap as aS, type MemoryValueOf as aT, NAMED_COMPOUNDS as aU, type ReferenceCatalog as aV, type ResolvedReferences as aW, type RoundState as aX, type RuntimeState as aY, SEED_PRECEDENCE_RANK as aZ, type ScriptRuntimeDependencies as a_, type DimVector as aa, type ExprNode as ab, type CalculationDefinition as ac, type IRealtimeProcessor as ad, type ISummaryProcessor as ae, type CalcLine as af, type CalcScope as ag, type ProjectionResult as ah, type BinaryOp as ai, type ButtonVariant as aj, type ButtonsState as ak, type CalcNode as al, type CalcOrigin as am, type CalcVariant as an, type ChildrenStatusState as ao, type CompletionState as ap, DEFAULT_RESOLVER_OPTIONS as aq, DEFAULT_RUNTIME_OPTIONS as ar, DEFAULT_SOUND_PROFILE as as, DIM_COUNT as at, DIM_ENERGY as au, DIM_LENGTH as av, DIM_MASS as aw, DIM_TIME as ax, DIM_ZERO as ay, DISCIPLINE_FACTORS as az, type IEffort as b, type SoundRule as b0, type SoundTriggerAnchor as b1, type SoundTriggerPoint as b2, type StackEvent as b3, type TimerDirection as b4, VISIBILITY_ICONS as b5, VISIBILITY_LABELS as b6, addDim as b7, compoundName as b8, createBrowserRuntimeNow as b9, createReferenceIndex as ba, dedupeEntitiesByPrecedence as bb, dimEquals as bc, disciplineFactorFor as bd, extractStatementRefs as be, filterTagsByVisibility as bf, formatDim as bg, formatSoundTrigger as bh, frozenNow as bi, getMetricVisibility as bj, getRuntimeNowMs as bk, isDimensionless as bl, isEffortDiscipline as bm, isFragmentTag as bn, parseSoundTrigger as bo, resolveEntityRank as bp, resolveEntityTier as bq, resolveProfileRules as br, resolveSourceRank as bs, resolveSourceTier as bt, slugifyRefLabel as bu, subDim as bv, wallClockNow as bw, type IEffortResolver as c, type IEffortRegistry as d, type EffortResolutionOptions as e, type ResolvedEffort as f, type EffortRegistrySource as g, type IEquipmentRegistry as h, type EquipmentStorageAdapter as i, type EffortStorageAdapter as j, type IRuntimeActionable as k, type IEventBus as l, type IRuntimeStack as m, type IRuntimeClock as n, type IJitCompiler as o, type INowProvider as p, type RuntimeStackOptions as q, type RuntimeError as r, type IEvent as s, type IRuntimeAction as t, type IAnalyticsEngine as u, type IRuntimeBlock as v, type IBehaviorContext as w, type BehaviorEventListener as x, type Unsubscribe$1 as y, type OutputOptions as z };
2994
+ export { type SoundProfile as $, type AnalyticsContext as A, type BehaviorEventType as B, type IMemoryLocation as C, type IRuntimeBehavior as D, type EffortResolverOptions as E, type IBlockContext as F, type MetricVisibility as G, type BlockLifecycleOptions as H, type IEquipment as I, type CompletionDecision as J, type IRuntimeMemory as K, TypedMemoryReference as L, type MemoryTag as M, type MemorySearchCriteria as N, type OutputListener as O, type IMemoryReference as P, type RuntimeStackLogger as Q, type ReferenceIndex as R, type SubscribeOptions as S, TimeSpan as T, type Unsubscribe as U, type StackObserver as V, WhiteboardScript as W, type StackSnapshot as X, type StackListener as Y, MemoryTypeEnum as Z, type IAnchorValue as _, type ReferenceResolutionDefaults as a, type MemoryValueOf as a$, type ButtonConfig as a0, type IEventHandler as a1, type HandlerScope as a2, type IScriptRuntime as a3, type TestableBlockConfig as a4, type IRuntimeOptions as a5, ScriptRuntime as a6, type EventHandlerOptions as a7, type EventCallback as a8, type TimerState as a9, DIM_LENGTH as aA, DIM_MASS as aB, DIM_TIME as aC, DIM_ZERO as aD, DISCIPLINE_FACTORS as aE, type DisplayState as aF, EFFORT_DISCIPLINES as aG, EFFORT_REGISTRY_ORIGINS as aH, type EffortBaseAttributes as aI, type EffortDerivation as aJ, type EffortDiscipline as aK, type EffortMaterializer as aL, type EffortResolvedFrom as aM, type EvalContext as aN, type FenceDialect as aO, type FragmentDisplayState as aP, type FragmentState as aQ, type IAnalyticsProcessorDescriptor as aR, INTENSITY_TIERS as aS, type IScript as aT, type IntensityTier as aU, type InterceptMode as aV, type LookupFieldDef as aW, type LookupLayer as aX, MemoryLocation as aY, type MemoryType as aZ, type MemoryTypeMap as a_, type CalculationDefinition as aa, type PropertyRuleInput as ab, type IRealtimeProcessor as ac, type ISummaryProcessor as ad, type DimVector as ae, type CalcLine as af, type ExprNode as ag, type CalcScope as ah, type ILookupTable as ai, LookupRegistry as aj, type ProjectionResult as ak, ABSENT as al, type BinaryOp as am, type ButtonVariant as an, type ButtonsState as ao, CalcEvalError as ap, type CalcNode as aq, type CalcOrigin as ar, type CalcVariant as as, type ChildrenStatusState as at, type CompletionState as au, DEFAULT_RESOLVER_OPTIONS as av, DEFAULT_RUNTIME_OPTIONS as aw, DEFAULT_SOUND_PROFILE as ax, DIM_COUNT as ay, DIM_ENERGY as az, type IEffort as b, NAMED_COMPOUNDS as b0, type PropertySourceLayer as b1, type ReferenceCatalog as b2, type ResolvedReferences as b3, type RoundState as b4, type RuntimeState as b5, SEED_PRECEDENCE_RANK as b6, type ScriptRuntimeDependencies as b7, type SeedPrecedenceTier as b8, type ShakeOutQueueOptions as b9, getMetricVisibility as bA, getRuntimeNowMs as bB, isDimensionless as bC, isEffortDiscipline as bD, isFragmentTag as bE, num as bF, parseSoundTrigger as bG, resolveEntityRank as bH, resolveEntityTier as bI, resolveProfileRules as bJ, resolveSourceRank as bK, resolveSourceTier as bL, runMetricShakeOutQueue as bM, slugifyRefLabel as bN, str as bO, subDim as bP, truthy as bQ, wallClockNow as bR, type ShakeOutResult as ba, type SkippedDependencyDiagnostic as bb, type SoundRule as bc, type SoundTriggerAnchor as bd, type SoundTriggerPoint as be, type StackEvent as bf, type TimerDirection as bg, VISIBILITY_ICONS as bh, VISIBILITY_LABELS as bi, type Val as bj, addDim as bk, compilePropertySummaryCalcs as bl, compoundName as bm, createBrowserRuntimeNow as bn, createReferenceIndex as bo, dedupeEntitiesByPrecedence as bp, dimEquals as bq, disciplineFactorFor as br, evaluate as bs, extractPropertyRulesFromMeta as bt, extractStatementRefs as bu, extractTagPropertyRules as bv, filterTagsByVisibility as bw, formatDim as bx, formatSoundTrigger as by, frozenNow as bz, type IEffortResolver as c, type IEffortRegistry as d, type EffortResolutionOptions as e, type ResolvedEffort as f, type EffortRegistrySource as g, type IEquipmentRegistry as h, type EquipmentStorageAdapter as i, type EffortStorageAdapter as j, type IRuntimeActionable as k, type IEventBus as l, type IRuntimeStack as m, type IRuntimeClock as n, type IJitCompiler as o, type INowProvider as p, type RuntimeStackOptions as q, type RuntimeError as r, type IEvent as s, type IRuntimeAction as t, type IAnalyticsEngine as u, type IRuntimeBlock as v, type IBehaviorContext as w, type BehaviorEventListener as x, type Unsubscribe$1 as y, type OutputOptions as z };
@@ -847,6 +847,176 @@ interface CalculationDefinition {
847
847
  };
848
848
  }
849
849
 
850
+ /**
851
+ * Dimension-aware value model for calc evaluation.
852
+ *
853
+ * Numbers carry a dimension vector and (optionally) the unit they were
854
+ * measured in; arithmetic tracks vectors per spec §5.1. `absent` is the
855
+ * missing-data value: it propagates through arithmetic, reads as `false` in
856
+ * predicates (applicability decision, #848), and is what `has()` probes.
857
+ */
858
+
859
+ type Val = {
860
+ kind: 'number';
861
+ value: number;
862
+ dim: DimVector;
863
+ unit?: string;
864
+ } | {
865
+ kind: 'string';
866
+ value: string;
867
+ } | {
868
+ kind: 'series';
869
+ points: Map<number, number>;
870
+ dim: DimVector;
871
+ unit?: string;
872
+ } | {
873
+ kind: 'period';
874
+ days: number;
875
+ } | {
876
+ kind: 'absent';
877
+ };
878
+ declare const ABSENT: Val;
879
+ declare function num(value: number, dim?: DimVector, unit?: string): Val;
880
+ declare function str(value: string): Val;
881
+ /** Predicate truthiness: absent → false; numbers → ≠ 0; strings → non-empty. */
882
+ declare function truthy(v: Val): boolean;
883
+
884
+ /**
885
+ * Expression evaluator for the composed calculations layer.
886
+ *
887
+ * The core owns arithmetic, comparison/logic, and the scalar function table
888
+ * (min, max, abs, round, floor, ceil, clamp, convert, has). Everything
889
+ * scope-dependent — metric refs, context nodes, stream aggregates, lookup(),
890
+ * WQL atoms — resolves through the EvalContext, so the same evaluator serves
891
+ * segment, workout, and store scopes (spec §3.1).
892
+ */
893
+
894
+ declare class CalcEvalError extends Error {
895
+ constructor(message: string);
896
+ }
897
+ interface EvalContext {
898
+ /** Resolve a ref atom (metric, context node, library node). ABSENT when missing. */
899
+ resolveRef(name: string): Val;
900
+ /**
901
+ * Extension functions (stream aggregates, lookup). Receives evaluated args
902
+ * plus the raw arg nodes (aggregates need the filter node unevaluated).
903
+ * Return undefined to signal "not mine" → CalcEvalError.
904
+ */
905
+ callFunction?(name: string, args: Val[], rawArgs: ExprNode[]): Val | undefined;
906
+ /** Store-scope WQL selections (QueryService). Store scope only. */
907
+ resolveWql?(node: Extract<ExprNode, {
908
+ kind: 'wql';
909
+ }>): Val;
910
+ }
911
+ declare function evaluate(node: ExprNode, ctx: EvalContext): Val;
912
+
913
+ /**
914
+ * Lookup table registry (spec §4).
915
+ *
916
+ * Tables are adapters over heterogeneous sources (effort resolver, static
917
+ * maps, user profile) exposing a uniform single-row lookup contract:
918
+ * `lookup("table", keyExpr, "field")`. Registration is layered —
919
+ * bundled → dialect → user — with later layers replacing earlier ones
920
+ * (mirrors the Dialect Stack's personal-overrides-last rule). Miss behavior
921
+ * is per-table: `absent` yields the absent value; `default-row` yields a
922
+ * synthetic row so calcs never see a miss.
923
+ */
924
+
925
+ interface LookupFieldDef {
926
+ dimension: DimVector;
927
+ type: 'number' | 'string';
928
+ }
929
+ interface ILookupTable {
930
+ readonly id: string;
931
+ readonly fields: Record<string, LookupFieldDef>;
932
+ readonly missPolicy: 'absent' | 'default-row';
933
+ /** Single-row lookup. `absent` tables return undefined on a miss. */
934
+ get(key: string, field: string): Val | undefined;
935
+ }
936
+ type LookupLayer = 'bundled' | 'dialect' | 'user';
937
+ declare class LookupRegistry {
938
+ private readonly tables;
939
+ /** Register a table; a later-or-equal layer replaces the existing entry. */
940
+ register(table: ILookupTable, layer?: LookupLayer): void;
941
+ get(tableId: string): ILookupTable | undefined;
942
+ /** Field dimension for static checking; undefined when table/field unknown. */
943
+ fieldDim(tableId: string, field: string): DimVector | undefined;
944
+ /** Runtime lookup honoring the table's miss policy. */
945
+ lookup(tableId: string, key: string, field: string): Val;
946
+ /**
947
+ * EvalContext `callFunction` implementation for `lookup("table", key, "field")`.
948
+ * Compose with other extension functions (aggregates) at the engine layer.
949
+ */
950
+ readonly callFunction: EvalContext['callFunction'];
951
+ }
952
+
953
+ /**
954
+ * MetricShakeOutQueue — Two-stage dependency-ordered metric evaluation module.
955
+ *
956
+ * Collects static Metrics and statement-level Metric Equations (`metrics:`)
957
+ * plus workout/query Summary Metrics (`summaries:`) across stacked Property
958
+ * Notes in specificity precedence:
959
+ * Statement/Runtime > Inline Tag > Effort > Equipment > Note Frontmatter > Tag Category
960
+ *
961
+ * Stage 1 (`plan`): resolves static metrics and compile-time equations in
962
+ * topological waves, injects compiler hints, and defers equations whose
963
+ * required inputs depend on runtime-only atoms (`elapsed`, `spans`, etc.).
964
+ *
965
+ * Stage 2 (`log`): resolves all remaining equations against the executed
966
+ * statement metrics and emits a structured Skipped-Dependency Diagnostic
967
+ * metric (`origin: 'diagnostic'`, `type: MetricType.Diagnostic`) for any
968
+ * equation whose required inputs remain absent after the fixed-point pass.
969
+ */
970
+
971
+ type PropertySourceLayer = 'statement' | 'tag' | 'effort' | 'equipment' | 'note' | 'category';
972
+ interface PropertyRuleInput {
973
+ readonly layer: Exclude<PropertySourceLayer, 'statement'>;
974
+ readonly sourceSlug: string;
975
+ readonly metrics?: Readonly<Record<string, string | number | readonly string[]>>;
976
+ readonly summaries?: Readonly<Record<string, string>>;
977
+ readonly hints?: Readonly<Record<string, unknown>>;
978
+ }
979
+ interface SkippedDependencyDiagnostic {
980
+ readonly target: string;
981
+ readonly expression: string;
982
+ readonly sourceLayer: Exclude<PropertySourceLayer, 'statement'>;
983
+ readonly sourceSlug: string;
984
+ readonly missing: readonly string[];
985
+ }
986
+ interface ShakeOutResult {
987
+ readonly resolved: readonly string[];
988
+ readonly deferredRuntime: readonly string[];
989
+ readonly diagnostics: readonly SkippedDependencyDiagnostic[];
990
+ readonly inferredDims: Readonly<Record<string, DimVector>>;
991
+ }
992
+ interface ShakeOutQueueOptions {
993
+ readonly stage: 'plan' | 'log';
994
+ readonly sources: readonly PropertyRuleInput[];
995
+ readonly lookups?: LookupRegistry;
996
+ readonly lastEffortSlug?: string;
997
+ }
998
+ /**
999
+ * Extract `metrics:` and `summaries:` maps from a parsed frontmatter record
1000
+ * (supporting both flat `metrics.foo` / `summaries.bar` keys and nested maps).
1001
+ */
1002
+ declare function extractPropertyRulesFromMeta(meta: Readonly<Record<string, unknown>>, layer: Exclude<PropertySourceLayer, 'statement'>, sourceSlug: string): PropertyRuleInput;
1003
+ /**
1004
+ * Extract `PropertyRuleInput` records from a `TagIndex` for the given tag slugs.
1005
+ * Supports both statement-level `metrics` (static or equation) and workout-level
1006
+ * `summaries.<key>` contributions on tags (including nested tags).
1007
+ */
1008
+ declare function extractTagPropertyRules(tags: TagIndex | undefined, slugs: readonly string[]): PropertyRuleInput[];
1009
+ /**
1010
+ * Compile `summaries:` equations across stacked Property Notes into workout-scope
1011
+ * `CalculationDefinition` records. Higher-precedence layers shadow lower layers
1012
+ * when both define the same summary key.
1013
+ */
1014
+ declare function compilePropertySummaryCalcs(sources: readonly PropertyRuleInput[]): CalculationDefinition[];
1015
+ /**
1016
+ * Run the two-stage Metric Shake-Out Queue on a statement's MetricContainer.
1017
+ */
1018
+ declare function runMetricShakeOutQueue(container: MetricContainer, options: ShakeOutQueueOptions): ShakeOutResult;
1019
+
850
1020
  /**
851
1021
  * Factory function type for wrapping blocks in debug mode.
852
1022
  * Receives the original block and returns a wrapped version.
@@ -948,6 +1118,8 @@ interface RuntimeStackOptions extends IRuntimeOptions {
948
1118
  * bundle a profile applies.
949
1119
  */
950
1120
  activeTags?: readonly string[];
1121
+ /** Property Note metric/summary rules active for this run or block. */
1122
+ propertySources?: readonly PropertyRuleInput[];
951
1123
  };
952
1124
  /**
953
1125
  * Sound configuration for this run.
@@ -2819,4 +2991,4 @@ declare function getRuntimeNowMs(): number;
2819
2991
  /** Creates an INowProvider that reads the browser sender-clock when available. */
2820
2992
  declare function createBrowserRuntimeNow(): INowProvider;
2821
2993
 
2822
- export { type SoundProfile as $, type AnalyticsContext as A, type BehaviorEventType as B, type IMemoryLocation as C, type IRuntimeBehavior as D, type EffortResolverOptions as E, type IBlockContext as F, type MetricVisibility as G, type BlockLifecycleOptions as H, type IEquipment as I, type CompletionDecision as J, type IRuntimeMemory as K, TypedMemoryReference as L, type MemoryTag as M, type MemorySearchCriteria as N, type OutputListener as O, type IMemoryReference as P, type RuntimeStackLogger as Q, type ReferenceIndex as R, type SubscribeOptions as S, TimeSpan as T, type Unsubscribe as U, type StackObserver as V, WhiteboardScript as W, type StackSnapshot as X, type StackListener as Y, MemoryTypeEnum as Z, type IAnchorValue as _, type ReferenceResolutionDefaults as a, type SeedPrecedenceTier as a$, type ButtonConfig as a0, type IEventHandler as a1, type HandlerScope as a2, type IScriptRuntime as a3, type TestableBlockConfig as a4, type IRuntimeOptions as a5, ScriptRuntime as a6, type EventHandlerOptions as a7, type EventCallback as a8, type TimerState as a9, type DisplayState as aA, EFFORT_DISCIPLINES as aB, EFFORT_REGISTRY_ORIGINS as aC, type EffortBaseAttributes as aD, type EffortDerivation as aE, type EffortDiscipline as aF, type EffortMaterializer as aG, type EffortResolvedFrom as aH, type FenceDialect as aI, type FragmentDisplayState as aJ, type FragmentState as aK, type IAnalyticsProcessorDescriptor as aL, INTENSITY_TIERS as aM, type IScript as aN, type IntensityTier as aO, type InterceptMode as aP, MemoryLocation as aQ, type MemoryType as aR, type MemoryTypeMap as aS, type MemoryValueOf as aT, NAMED_COMPOUNDS as aU, type ReferenceCatalog as aV, type ResolvedReferences as aW, type RoundState as aX, type RuntimeState as aY, SEED_PRECEDENCE_RANK as aZ, type ScriptRuntimeDependencies as a_, type DimVector as aa, type ExprNode as ab, type CalculationDefinition as ac, type IRealtimeProcessor as ad, type ISummaryProcessor as ae, type CalcLine as af, type CalcScope as ag, type ProjectionResult as ah, type BinaryOp as ai, type ButtonVariant as aj, type ButtonsState as ak, type CalcNode as al, type CalcOrigin as am, type CalcVariant as an, type ChildrenStatusState as ao, type CompletionState as ap, DEFAULT_RESOLVER_OPTIONS as aq, DEFAULT_RUNTIME_OPTIONS as ar, DEFAULT_SOUND_PROFILE as as, DIM_COUNT as at, DIM_ENERGY as au, DIM_LENGTH as av, DIM_MASS as aw, DIM_TIME as ax, DIM_ZERO as ay, DISCIPLINE_FACTORS as az, type IEffort as b, type SoundRule as b0, type SoundTriggerAnchor as b1, type SoundTriggerPoint as b2, type StackEvent as b3, type TimerDirection as b4, VISIBILITY_ICONS as b5, VISIBILITY_LABELS as b6, addDim as b7, compoundName as b8, createBrowserRuntimeNow as b9, createReferenceIndex as ba, dedupeEntitiesByPrecedence as bb, dimEquals as bc, disciplineFactorFor as bd, extractStatementRefs as be, filterTagsByVisibility as bf, formatDim as bg, formatSoundTrigger as bh, frozenNow as bi, getMetricVisibility as bj, getRuntimeNowMs as bk, isDimensionless as bl, isEffortDiscipline as bm, isFragmentTag as bn, parseSoundTrigger as bo, resolveEntityRank as bp, resolveEntityTier as bq, resolveProfileRules as br, resolveSourceRank as bs, resolveSourceTier as bt, slugifyRefLabel as bu, subDim as bv, wallClockNow as bw, type IEffortResolver as c, type IEffortRegistry as d, type EffortResolutionOptions as e, type ResolvedEffort as f, type EffortRegistrySource as g, type IEquipmentRegistry as h, type EquipmentStorageAdapter as i, type EffortStorageAdapter as j, type IRuntimeActionable as k, type IEventBus as l, type IRuntimeStack as m, type IRuntimeClock as n, type IJitCompiler as o, type INowProvider as p, type RuntimeStackOptions as q, type RuntimeError as r, type IEvent as s, type IRuntimeAction as t, type IAnalyticsEngine as u, type IRuntimeBlock as v, type IBehaviorContext as w, type BehaviorEventListener as x, type Unsubscribe$1 as y, type OutputOptions as z };
2994
+ export { type SoundProfile as $, type AnalyticsContext as A, type BehaviorEventType as B, type IMemoryLocation as C, type IRuntimeBehavior as D, type EffortResolverOptions as E, type IBlockContext as F, type MetricVisibility as G, type BlockLifecycleOptions as H, type IEquipment as I, type CompletionDecision as J, type IRuntimeMemory as K, TypedMemoryReference as L, type MemoryTag as M, type MemorySearchCriteria as N, type OutputListener as O, type IMemoryReference as P, type RuntimeStackLogger as Q, type ReferenceIndex as R, type SubscribeOptions as S, TimeSpan as T, type Unsubscribe as U, type StackObserver as V, WhiteboardScript as W, type StackSnapshot as X, type StackListener as Y, MemoryTypeEnum as Z, type IAnchorValue as _, type ReferenceResolutionDefaults as a, type MemoryValueOf as a$, type ButtonConfig as a0, type IEventHandler as a1, type HandlerScope as a2, type IScriptRuntime as a3, type TestableBlockConfig as a4, type IRuntimeOptions as a5, ScriptRuntime as a6, type EventHandlerOptions as a7, type EventCallback as a8, type TimerState as a9, DIM_LENGTH as aA, DIM_MASS as aB, DIM_TIME as aC, DIM_ZERO as aD, DISCIPLINE_FACTORS as aE, type DisplayState as aF, EFFORT_DISCIPLINES as aG, EFFORT_REGISTRY_ORIGINS as aH, type EffortBaseAttributes as aI, type EffortDerivation as aJ, type EffortDiscipline as aK, type EffortMaterializer as aL, type EffortResolvedFrom as aM, type EvalContext as aN, type FenceDialect as aO, type FragmentDisplayState as aP, type FragmentState as aQ, type IAnalyticsProcessorDescriptor as aR, INTENSITY_TIERS as aS, type IScript as aT, type IntensityTier as aU, type InterceptMode as aV, type LookupFieldDef as aW, type LookupLayer as aX, MemoryLocation as aY, type MemoryType as aZ, type MemoryTypeMap as a_, type CalculationDefinition as aa, type PropertyRuleInput as ab, type IRealtimeProcessor as ac, type ISummaryProcessor as ad, type DimVector as ae, type CalcLine as af, type ExprNode as ag, type CalcScope as ah, type ILookupTable as ai, LookupRegistry as aj, type ProjectionResult as ak, ABSENT as al, type BinaryOp as am, type ButtonVariant as an, type ButtonsState as ao, CalcEvalError as ap, type CalcNode as aq, type CalcOrigin as ar, type CalcVariant as as, type ChildrenStatusState as at, type CompletionState as au, DEFAULT_RESOLVER_OPTIONS as av, DEFAULT_RUNTIME_OPTIONS as aw, DEFAULT_SOUND_PROFILE as ax, DIM_COUNT as ay, DIM_ENERGY as az, type IEffort as b, NAMED_COMPOUNDS as b0, type PropertySourceLayer as b1, type ReferenceCatalog as b2, type ResolvedReferences as b3, type RoundState as b4, type RuntimeState as b5, SEED_PRECEDENCE_RANK as b6, type ScriptRuntimeDependencies as b7, type SeedPrecedenceTier as b8, type ShakeOutQueueOptions as b9, getMetricVisibility as bA, getRuntimeNowMs as bB, isDimensionless as bC, isEffortDiscipline as bD, isFragmentTag as bE, num as bF, parseSoundTrigger as bG, resolveEntityRank as bH, resolveEntityTier as bI, resolveProfileRules as bJ, resolveSourceRank as bK, resolveSourceTier as bL, runMetricShakeOutQueue as bM, slugifyRefLabel as bN, str as bO, subDim as bP, truthy as bQ, wallClockNow as bR, type ShakeOutResult as ba, type SkippedDependencyDiagnostic as bb, type SoundRule as bc, type SoundTriggerAnchor as bd, type SoundTriggerPoint as be, type StackEvent as bf, type TimerDirection as bg, VISIBILITY_ICONS as bh, VISIBILITY_LABELS as bi, type Val as bj, addDim as bk, compilePropertySummaryCalcs as bl, compoundName as bm, createBrowserRuntimeNow as bn, createReferenceIndex as bo, dedupeEntitiesByPrecedence as bp, dimEquals as bq, disciplineFactorFor as br, evaluate as bs, extractPropertyRulesFromMeta as bt, extractStatementRefs as bu, extractTagPropertyRules as bv, filterTagsByVisibility as bw, formatDim as bx, formatSoundTrigger as by, frozenNow as bz, type IEffortResolver as c, type IEffortRegistry as d, type EffortResolutionOptions as e, type ResolvedEffort as f, type EffortRegistrySource as g, type IEquipmentRegistry as h, type EquipmentStorageAdapter as i, type EffortStorageAdapter as j, type IRuntimeActionable as k, type IEventBus as l, type IRuntimeStack as m, type IRuntimeClock as n, type IJitCompiler as o, type INowProvider as p, type RuntimeStackOptions as q, type RuntimeError as r, type IEvent as s, type IRuntimeAction as t, type IAnalyticsEngine as u, type IRuntimeBlock as v, type IBehaviorContext as w, type BehaviorEventListener as x, type Unsubscribe$1 as y, type OutputOptions as z };
package/dist/index.cjs CHANGED
@@ -416,12 +416,20 @@ function tagMarkerSlugs(metrics) {
416
416
  }
417
417
  return slugs;
418
418
  }
419
+ function isEquationMetricValue(value) {
420
+ if (typeof value !== "string") return false;
421
+ const trimmed = value.trim();
422
+ if (!trimmed) return false;
423
+ if (/^[+-]?\d+(?:\.\d+)?(?:\s*[A-Za-z%/][\w%/.-]*)?$/.test(trimmed)) return false;
424
+ if (/^[a-zA-Z0-9_]+(?:-[a-zA-Z0-9_]+)*$/.test(trimmed)) return false;
425
+ return /[*/+()]|\s-\s|->|\b(?:convert|sum|avg|min|max|count|last|round|floor|ceil|abs|clamp|lookup|when|and|or)\b/.test(trimmed);
426
+ }
419
427
  function tagContributionMetrics(contributions, origin = "parser") {
420
- return contributions.map((contribution) => ({
428
+ return contributions.filter((c) => !c.type.trim().startsWith("summaries.") && !isEquationMetricValue(c.value)).map((contribution) => ({
421
429
  type: contribution.type,
422
430
  value: contribution.value,
423
431
  origin,
424
- image: String(contribution.value),
432
+ image: contribution.unit ? `${String(contribution.value)} ${contribution.unit}` : String(contribution.value),
425
433
  ...contribution.unit ? { unit: contribution.unit } : {}
426
434
  }));
427
435
  }
@@ -9662,6 +9670,37 @@ function isSupportedMetricValue(val) {
9662
9670
  function isPlainObject(val) {
9663
9671
  return Boolean(val) && typeof val === "object" && !Array.isArray(val);
9664
9672
  }
9673
+ function extractTagPropertyRules(tags2, slugs) {
9674
+ if (!tags2 || slugs.length === 0) return [];
9675
+ const rules = [];
9676
+ for (const slug of slugs) {
9677
+ const resolved = resolveTagContributions(tags2, slug);
9678
+ if (resolved.metrics.length === 0) continue;
9679
+ const metrics = {};
9680
+ const summaries = {};
9681
+ for (const m of resolved.metrics) {
9682
+ const key = m.type.trim();
9683
+ if (!key) continue;
9684
+ if (key.startsWith("summaries.")) {
9685
+ const subKey = key.slice("summaries.".length).trim();
9686
+ if (subKey && !(subKey in summaries)) {
9687
+ summaries[subKey] = String(m.value);
9688
+ }
9689
+ } else if (!(key in metrics)) {
9690
+ metrics[key] = m.unit ? `${String(m.value)} ${m.unit}` : m.value === null || typeof m.value === "boolean" ? String(m.value) : m.value;
9691
+ }
9692
+ }
9693
+ if (Object.keys(metrics).length > 0 || Object.keys(summaries).length > 0) {
9694
+ rules.push({
9695
+ layer: "tag",
9696
+ sourceSlug: slug,
9697
+ metrics,
9698
+ summaries
9699
+ });
9700
+ }
9701
+ }
9702
+ return rules;
9703
+ }
9665
9704
  function compilePropertySummaryCalcs(sources) {
9666
9705
  const ordered = [...sources].sort(
9667
9706
  (a, b) => LAYER_PRECEDENCE[b.layer] - LAYER_PRECEDENCE[a.layer]
@@ -12352,9 +12391,24 @@ var CalcEngine = class {
12352
12391
  const fenced = (d) => !d.fences || d.fences.includes(deps.dialect);
12353
12392
  this.segmentCalcs = registry.byScope("segment").filter(fenced);
12354
12393
  this.workoutCalcs = registry.byScope("workout").filter(fenced);
12394
+ const noteDefinedSummaries = /* @__PURE__ */ new Set();
12395
+ for (const src of deps.propertySources ?? []) {
12396
+ for (const k of Object.keys(src.summaries ?? {})) {
12397
+ noteDefinedSummaries.add(k.trim());
12398
+ }
12399
+ }
12355
12400
  for (const tag of deps.tags?.list() ?? []) {
12356
12401
  const resolved = resolveTagContributions(deps.tags, tag.slug);
12357
- for (const name2 of resolved.functions) {
12402
+ const carriedNames = [...resolved.functions];
12403
+ for (const m of resolved.metrics) {
12404
+ if (m.type.trim().startsWith("summaries.")) {
12405
+ const summaryId = m.type.trim().slice("summaries.".length).trim();
12406
+ if (summaryId && !noteDefinedSummaries.has(summaryId)) {
12407
+ carriedNames.push(summaryId);
12408
+ }
12409
+ }
12410
+ }
12411
+ for (const name2 of carriedNames) {
12358
12412
  const carriers = this.tagCarriedFunctions.get(name2);
12359
12413
  if (carriers) carriers.add(tag.slug);
12360
12414
  else this.tagCarriedFunctions.set(name2, /* @__PURE__ */ new Set([tag.slug]));
@@ -12417,10 +12471,13 @@ var CalcEngine = class {
12417
12471
  if (output.outputType !== "segment" || !output.isLeaf) return output;
12418
12472
  const effortData = extractEffortData(output.metrics.rawMetrics);
12419
12473
  if (effortData) this.lastSegmentEffort = effortData.resolved.slug;
12420
- if (this.deps.propertySources && this.deps.propertySources.length > 0) {
12474
+ const appliedTags = this.appliedTags(output);
12475
+ const tagSources = extractTagPropertyRules(this.deps.tags, appliedTags);
12476
+ const allSources = [...tagSources, ...this.deps.propertySources ?? []];
12477
+ if (allSources.length > 0) {
12421
12478
  runMetricShakeOutQueue(output.metrics, {
12422
12479
  stage: "log",
12423
- sources: this.deps.propertySources,
12480
+ sources: allSources,
12424
12481
  lookups: this.deps.lookups,
12425
12482
  lastEffortSlug: this.lastSegmentEffort
12426
12483
  });
@@ -12439,7 +12496,6 @@ var CalcEngine = class {
12439
12496
  if (climbGrade && typeof climbGrade === "object" && "raw" in climbGrade) {
12440
12497
  effortTags.grade = String(climbGrade.raw);
12441
12498
  }
12442
- const appliedTags = this.appliedTags(output);
12443
12499
  for (const def of this.segmentCalcs) {
12444
12500
  if (!this.isActive(def, appliedTags)) continue;
12445
12501
  const ctx = this.makeContext(atoms);
@@ -13659,8 +13715,11 @@ function createCalcStack(options) {
13659
13715
  const registry = new CalculationRegistry(lookups);
13660
13716
  for (const def of BUILTIN_CALCS) registry.register(def);
13661
13717
  for (const def of options.calcs ?? []) registry.register(def);
13662
- if (options.propertySources && options.propertySources.length > 0) {
13663
- for (const def of compilePropertySummaryCalcs(options.propertySources)) {
13718
+ const allTagSlugs = (options.tags?.list() ?? []).map((t2) => t2.slug);
13719
+ const tagRules = extractTagPropertyRules(options.tags, allTagSlugs);
13720
+ const combinedSources = [...options.propertySources ?? [], ...tagRules];
13721
+ if (combinedSources.length > 0) {
13722
+ for (const def of compilePropertySummaryCalcs(combinedSources)) {
13664
13723
  registry.register(def);
13665
13724
  }
13666
13725
  }
@@ -15978,6 +16037,7 @@ exports.extractStatementRefs = extractStatementRefs;
15978
16037
  exports.extractStatements = extractStatements;
15979
16038
  exports.extractStatementsRaw = extractStatementsRaw;
15980
16039
  exports.extractSyntaxFacts = extractSyntaxFacts;
16040
+ exports.extractTagPropertyRules = extractTagPropertyRules;
15981
16041
  exports.filterTagsByVisibility = filterTagsByVisibility;
15982
16042
  exports.findBestFuzzyMatch = findBestFuzzyMatch;
15983
16043
  exports.findTagContributionCycles = findTagContributionCycles;