@higher.archi/boe 1.0.0 → 1.0.2
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/dist/core/operators/examples.d.ts +1 -1
- package/dist/core/operators/examples.js +1 -1
- package/dist/engines/scoring/compiler.d.ts.map +1 -1
- package/dist/engines/scoring/compiler.js +55 -2
- package/dist/engines/scoring/compiler.js.map +1 -1
- package/dist/engines/scoring/index.d.ts +1 -1
- package/dist/engines/scoring/index.d.ts.map +1 -1
- package/dist/engines/scoring/index.js.map +1 -1
- package/dist/engines/scoring/strategy.d.ts.map +1 -1
- package/dist/engines/scoring/strategy.js +216 -3
- package/dist/engines/scoring/strategy.js.map +1 -1
- package/dist/engines/scoring/types.d.ts +142 -1
- package/dist/engines/scoring/types.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/core/operators/examples.ts +1 -1
- package/src/engines/scoring/compiler.ts +76 -3
- package/src/engines/scoring/index.ts +15 -0
- package/src/engines/scoring/strategy.ts +232 -4
- package/src/engines/scoring/types.ts +170 -0
- package/src/index.ts +14 -1
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
CompiledBaseRule,
|
|
9
9
|
CompiledBaseRuleSet,
|
|
10
10
|
CompiledCondition,
|
|
11
|
+
Condition,
|
|
11
12
|
Expression,
|
|
12
13
|
BindingContext
|
|
13
14
|
} from '../../core';
|
|
@@ -93,6 +94,155 @@ export type ScoringTierMatch = {
|
|
|
93
94
|
threshold: number;
|
|
94
95
|
};
|
|
95
96
|
|
|
97
|
+
// ========================================
|
|
98
|
+
// Category Types
|
|
99
|
+
// ========================================
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Category definition for grouping related scoring signals
|
|
103
|
+
*
|
|
104
|
+
* Categories provide a two-level weight hierarchy: category weights
|
|
105
|
+
* control how much each group contributes to the total, and signal
|
|
106
|
+
* weights within each category control relative importance of rules.
|
|
107
|
+
*/
|
|
108
|
+
export type ScoringCategory = {
|
|
109
|
+
id: string;
|
|
110
|
+
name?: string;
|
|
111
|
+
weight: number; // 0-1, normalized internally
|
|
112
|
+
minSignalRatio?: number; // default 0.5 — below this, category is excluded
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Per-category result breakdown showing how each category contributed
|
|
117
|
+
*/
|
|
118
|
+
export type CategoryResult = {
|
|
119
|
+
id: string;
|
|
120
|
+
name?: string;
|
|
121
|
+
weight: number; // original configured weight
|
|
122
|
+
effectiveWeight: number; // after redistribution from excluded categories
|
|
123
|
+
rawScore: number; // weighted avg of signal scores within category
|
|
124
|
+
weightedContribution: number; // effectiveWeight × rawScore
|
|
125
|
+
signalsWithData: string[]; // rule IDs that fired
|
|
126
|
+
signalsMissing: string[]; // rule IDs that didn't fire
|
|
127
|
+
excluded: boolean;
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
// ========================================
|
|
131
|
+
// Override Types
|
|
132
|
+
// ========================================
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Override effect types
|
|
136
|
+
*/
|
|
137
|
+
export type OverrideEffect =
|
|
138
|
+
| 'force_tier'
|
|
139
|
+
| 'floor_tier'
|
|
140
|
+
| 'cap_tier'
|
|
141
|
+
| 'exclude'
|
|
142
|
+
| 'adjust_score'
|
|
143
|
+
| 'clamp_score'
|
|
144
|
+
| 'force_score';
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Base override fields shared by all effects
|
|
148
|
+
*/
|
|
149
|
+
type BaseOverride = {
|
|
150
|
+
id: string;
|
|
151
|
+
condition: Condition;
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Force tier — override to exact tier, optionally replace score
|
|
156
|
+
*/
|
|
157
|
+
export type ForceTierOverride = BaseOverride & {
|
|
158
|
+
effect: 'force_tier';
|
|
159
|
+
targetTier: string;
|
|
160
|
+
score?: number;
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Floor tier — set minimum tier (bump up if below)
|
|
165
|
+
*/
|
|
166
|
+
export type FloorTierOverride = BaseOverride & {
|
|
167
|
+
effect: 'floor_tier';
|
|
168
|
+
targetTier: string;
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Cap tier — set maximum tier (cap down if above)
|
|
173
|
+
*/
|
|
174
|
+
export type CapTierOverride = BaseOverride & {
|
|
175
|
+
effect: 'cap_tier';
|
|
176
|
+
targetTier: string;
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Exclude — nullify the entire scoring result
|
|
181
|
+
*/
|
|
182
|
+
export type ExcludeOverride = BaseOverride & {
|
|
183
|
+
effect: 'exclude';
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Adjust score — add/subtract from total score
|
|
188
|
+
*/
|
|
189
|
+
export type AdjustScoreOverride = BaseOverride & {
|
|
190
|
+
effect: 'adjust_score';
|
|
191
|
+
value: number;
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Clamp score — enforce floor/ceiling on the score
|
|
196
|
+
*/
|
|
197
|
+
export type ClampScoreOverride = BaseOverride & {
|
|
198
|
+
effect: 'clamp_score';
|
|
199
|
+
min?: number;
|
|
200
|
+
max?: number;
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Force score — replace the total score entirely
|
|
205
|
+
*/
|
|
206
|
+
export type ForceScoreOverride = BaseOverride & {
|
|
207
|
+
effect: 'force_score';
|
|
208
|
+
score: number | Expression;
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Discriminated union of all override definitions
|
|
213
|
+
*
|
|
214
|
+
* Overrides are evaluated post-scoring in order — first match wins.
|
|
215
|
+
* Each effect type has its own required fields enforced by TypeScript.
|
|
216
|
+
*
|
|
217
|
+
* @example
|
|
218
|
+
* ```typescript
|
|
219
|
+
* const overrides: OverrideDefinition[] = [
|
|
220
|
+
* { id: 'closed-won', condition: ['equals', '$deal.stage', 'Closed Won'], effect: 'force_tier', targetTier: 'strong', score: 1000 },
|
|
221
|
+
* { id: 'fraud-flag', condition: ['equals', '$app.fraud', true], effect: 'exclude' },
|
|
222
|
+
* { id: 'vip-bonus', condition: ['equals', '$customer.vip', true], effect: 'adjust_score', value: 50 }
|
|
223
|
+
* ];
|
|
224
|
+
* ```
|
|
225
|
+
*/
|
|
226
|
+
export type OverrideDefinition =
|
|
227
|
+
| ForceTierOverride
|
|
228
|
+
| FloorTierOverride
|
|
229
|
+
| CapTierOverride
|
|
230
|
+
| ExcludeOverride
|
|
231
|
+
| AdjustScoreOverride
|
|
232
|
+
| ClampScoreOverride
|
|
233
|
+
| ForceScoreOverride;
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Override result — attached to ScoringResult when an override fires
|
|
237
|
+
*/
|
|
238
|
+
export type OverrideResult = {
|
|
239
|
+
id: string;
|
|
240
|
+
effect: OverrideEffect;
|
|
241
|
+
originalScore: number;
|
|
242
|
+
originalTier?: ScoringTierMatch;
|
|
243
|
+
applied: true;
|
|
244
|
+
};
|
|
245
|
+
|
|
96
246
|
// ========================================
|
|
97
247
|
// Source Types (User-Defined)
|
|
98
248
|
// ========================================
|
|
@@ -111,6 +261,7 @@ export type ScoringAction = {
|
|
|
111
261
|
* Scoring rule - uses 'then' for scoring properties
|
|
112
262
|
*/
|
|
113
263
|
export type ScoringRule = BaseRule & {
|
|
264
|
+
category?: string;
|
|
114
265
|
then: ScoringAction;
|
|
115
266
|
};
|
|
116
267
|
|
|
@@ -133,6 +284,8 @@ export type ScoringConfig = {
|
|
|
133
284
|
outputBounds?: OutputBounds; // Optional output scaling
|
|
134
285
|
baseScore?: number; // Starting score before rule contributions (default: 0)
|
|
135
286
|
tiers?: TierDefinition[]; // Optional tier definitions for score classification
|
|
287
|
+
categories?: ScoringCategory[]; // Optional category grouping for two-level weight hierarchy
|
|
288
|
+
overrides?: OverrideDefinition[]; // Optional post-scoring overrides evaluated in order (first match wins)
|
|
136
289
|
};
|
|
137
290
|
|
|
138
291
|
// ========================================
|
|
@@ -154,9 +307,23 @@ export type CompiledScoringAction = {
|
|
|
154
307
|
* Compiled scoring rule
|
|
155
308
|
*/
|
|
156
309
|
export type CompiledScoringRule = CompiledBaseRule & {
|
|
310
|
+
category?: string;
|
|
157
311
|
action: CompiledScoringAction;
|
|
158
312
|
};
|
|
159
313
|
|
|
314
|
+
/**
|
|
315
|
+
* Compiled override — replaces source Condition with CompiledCondition
|
|
316
|
+
* Each variant preserves its effect-specific fields
|
|
317
|
+
*/
|
|
318
|
+
export type CompiledOverrideDefinition =
|
|
319
|
+
| (Omit<ForceTierOverride, 'condition'> & { condition: CompiledCondition })
|
|
320
|
+
| (Omit<FloorTierOverride, 'condition'> & { condition: CompiledCondition })
|
|
321
|
+
| (Omit<CapTierOverride, 'condition'> & { condition: CompiledCondition })
|
|
322
|
+
| (Omit<ExcludeOverride, 'condition'> & { condition: CompiledCondition })
|
|
323
|
+
| (Omit<AdjustScoreOverride, 'condition'> & { condition: CompiledCondition })
|
|
324
|
+
| (Omit<ClampScoreOverride, 'condition'> & { condition: CompiledCondition })
|
|
325
|
+
| (Omit<ForceScoreOverride, 'condition'> & { condition: CompiledCondition });
|
|
326
|
+
|
|
160
327
|
/**
|
|
161
328
|
* Compiled scoring ruleset
|
|
162
329
|
*/
|
|
@@ -164,6 +331,7 @@ export type CompiledScoringRuleSet = CompiledBaseRuleSet & {
|
|
|
164
331
|
mode: 'scoring';
|
|
165
332
|
rules: CompiledScoringRule[];
|
|
166
333
|
config: ScoringConfig;
|
|
334
|
+
overrides?: CompiledOverrideDefinition[];
|
|
167
335
|
};
|
|
168
336
|
|
|
169
337
|
// ========================================
|
|
@@ -197,5 +365,7 @@ export type ScoringResult = {
|
|
|
197
365
|
fired: string[]; // Rules that matched and contributed
|
|
198
366
|
iterations: 1; // Scoring is always one-pass
|
|
199
367
|
tier?: ScoringTierMatch; // Matched tier (if tiers configured)
|
|
368
|
+
categoryBreakdown?: CategoryResult[]; // Per-category breakdown (if categories configured)
|
|
369
|
+
override?: OverrideResult; // Override that fired (if any)
|
|
200
370
|
executionTimeMs: number; // Processing time in milliseconds
|
|
201
371
|
};
|
package/src/index.ts
CHANGED
|
@@ -92,7 +92,20 @@ export type {
|
|
|
92
92
|
ScoringResult,
|
|
93
93
|
ScoreFunctionRegistry,
|
|
94
94
|
ScoringMethod,
|
|
95
|
-
OutputBounds
|
|
95
|
+
OutputBounds,
|
|
96
|
+
ScoringCategory,
|
|
97
|
+
CategoryResult,
|
|
98
|
+
OverrideEffect,
|
|
99
|
+
OverrideDefinition,
|
|
100
|
+
ForceTierOverride,
|
|
101
|
+
FloorTierOverride,
|
|
102
|
+
CapTierOverride,
|
|
103
|
+
ExcludeOverride,
|
|
104
|
+
AdjustScoreOverride,
|
|
105
|
+
ClampScoreOverride,
|
|
106
|
+
ForceScoreOverride,
|
|
107
|
+
OverrideResult,
|
|
108
|
+
CompiledOverrideDefinition
|
|
96
109
|
} from './engines/scoring';
|
|
97
110
|
|
|
98
111
|
// Sequential
|