@higher.archi/boe 1.0.9 → 1.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/dist/core/memory/working-memory.d.ts +2 -2
  2. package/dist/core/memory/working-memory.d.ts.map +1 -1
  3. package/dist/core/memory/working-memory.interface.d.ts +2 -2
  4. package/dist/core/memory/working-memory.interface.d.ts.map +1 -1
  5. package/dist/core/memory/working-memory.js +2 -2
  6. package/dist/core/memory/working-memory.js.map +1 -1
  7. package/dist/core/types/fact.d.ts +4 -4
  8. package/dist/core/types/fact.d.ts.map +1 -1
  9. package/dist/engines/backward/engine.d.ts +2 -2
  10. package/dist/engines/backward/engine.d.ts.map +1 -1
  11. package/dist/engines/backward/engine.js.map +1 -1
  12. package/dist/engines/bayesian/engine.d.ts +2 -2
  13. package/dist/engines/bayesian/engine.d.ts.map +1 -1
  14. package/dist/engines/bayesian/engine.js.map +1 -1
  15. package/dist/engines/constraint/engine.d.ts +2 -2
  16. package/dist/engines/constraint/engine.d.ts.map +1 -1
  17. package/dist/engines/constraint/engine.js.map +1 -1
  18. package/dist/engines/defeasible/engine.d.ts +2 -2
  19. package/dist/engines/defeasible/engine.d.ts.map +1 -1
  20. package/dist/engines/defeasible/engine.js.map +1 -1
  21. package/dist/engines/expert/engine.d.ts +2 -2
  22. package/dist/engines/expert/engine.d.ts.map +1 -1
  23. package/dist/engines/expert/engine.js.map +1 -1
  24. package/dist/engines/forward/engine.d.ts +2 -2
  25. package/dist/engines/forward/engine.d.ts.map +1 -1
  26. package/dist/engines/forward/engine.js.map +1 -1
  27. package/dist/engines/fuzzy/engine.d.ts +2 -2
  28. package/dist/engines/fuzzy/engine.d.ts.map +1 -1
  29. package/dist/engines/fuzzy/engine.js.map +1 -1
  30. package/dist/engines/monte-carlo/engine.d.ts +2 -2
  31. package/dist/engines/monte-carlo/engine.d.ts.map +1 -1
  32. package/dist/engines/monte-carlo/engine.js.map +1 -1
  33. package/dist/engines/scoring/compiler.d.ts.map +1 -1
  34. package/dist/engines/scoring/compiler.js +1 -0
  35. package/dist/engines/scoring/compiler.js.map +1 -1
  36. package/dist/engines/scoring/engine.d.ts +2 -2
  37. package/dist/engines/scoring/engine.d.ts.map +1 -1
  38. package/dist/engines/scoring/engine.js.map +1 -1
  39. package/dist/engines/scoring/index.d.ts +1 -1
  40. package/dist/engines/scoring/index.d.ts.map +1 -1
  41. package/dist/engines/scoring/index.js +4 -1
  42. package/dist/engines/scoring/index.js.map +1 -1
  43. package/dist/engines/scoring/strategy.d.ts.map +1 -1
  44. package/dist/engines/scoring/strategy.js +26 -0
  45. package/dist/engines/scoring/strategy.js.map +1 -1
  46. package/dist/engines/scoring/types.d.ts +43 -4
  47. package/dist/engines/scoring/types.d.ts.map +1 -1
  48. package/dist/engines/scoring/types.js +19 -0
  49. package/dist/engines/scoring/types.js.map +1 -1
  50. package/dist/engines/sequential/engine.d.ts +2 -2
  51. package/dist/engines/sequential/engine.d.ts.map +1 -1
  52. package/dist/engines/sequential/engine.js.map +1 -1
  53. package/dist/engines/utility/engine.d.ts +2 -2
  54. package/dist/engines/utility/engine.d.ts.map +1 -1
  55. package/dist/engines/utility/engine.js.map +1 -1
  56. package/dist/index.d.ts +2 -2
  57. package/dist/index.d.ts.map +1 -1
  58. package/dist/index.js +3 -2
  59. package/dist/index.js.map +1 -1
  60. package/package.json +1 -1
  61. package/src/core/memory/working-memory.interface.ts +2 -2
  62. package/src/core/memory/working-memory.ts +12 -12
  63. package/src/core/types/fact.ts +4 -4
  64. package/src/engines/backward/engine.ts +2 -2
  65. package/src/engines/bayesian/engine.ts +2 -2
  66. package/src/engines/constraint/engine.ts +2 -2
  67. package/src/engines/defeasible/engine.ts +2 -2
  68. package/src/engines/expert/engine.ts +2 -2
  69. package/src/engines/forward/engine.ts +2 -2
  70. package/src/engines/fuzzy/engine.ts +2 -2
  71. package/src/engines/monte-carlo/engine.ts +2 -2
  72. package/src/engines/scoring/compiler.ts +1 -0
  73. package/src/engines/scoring/engine.ts +2 -2
  74. package/src/engines/scoring/index.ts +5 -1
  75. package/src/engines/scoring/strategy.ts +32 -0
  76. package/src/engines/scoring/types.ts +49 -4
  77. package/src/engines/sequential/engine.ts +2 -2
  78. package/src/engines/utility/engine.ts +2 -2
  79. package/src/index.ts +5 -1
@@ -51,7 +51,7 @@ export class FuzzyEngine implements IRuleEngine<CompiledFuzzyRuleSet, FuzzyOptio
51
51
  // IWorkingMemory Implementation
52
52
  // ========================================
53
53
 
54
- add(input: FactInput): Fact {
54
+ add<T = Record<string, any>>(input: FactInput<T>): Fact<T> {
55
55
  return this.wm.add(input);
56
56
  }
57
57
 
@@ -59,7 +59,7 @@ export class FuzzyEngine implements IRuleEngine<CompiledFuzzyRuleSet, FuzzyOptio
59
59
  return this.wm.remove(factId);
60
60
  }
61
61
 
62
- update(input: FactInput): Fact {
62
+ update<T = Record<string, any>>(input: FactInput<T>): Fact<T> {
63
63
  return this.wm.update(input);
64
64
  }
65
65
 
@@ -55,7 +55,7 @@ export class MonteCarloEngine implements IRuleEngine<CompiledMonteCarloRuleSet,
55
55
  // IWorkingMemory Implementation
56
56
  // ========================================
57
57
 
58
- add(input: FactInput): Fact {
58
+ add<T = Record<string, any>>(input: FactInput<T>): Fact<T> {
59
59
  return this.wm.add(input);
60
60
  }
61
61
 
@@ -63,7 +63,7 @@ export class MonteCarloEngine implements IRuleEngine<CompiledMonteCarloRuleSet,
63
63
  return this.wm.remove(factId);
64
64
  }
65
65
 
66
- update(input: FactInput): Fact {
66
+ update<T = Record<string, any>>(input: FactInput<T>): Fact<T> {
67
67
  return this.wm.update(input);
68
68
  }
69
69
 
@@ -216,6 +216,7 @@ export function compileScoringRuleSet(ruleSet: ScoringRuleSet): CompiledScoringR
216
216
  categories,
217
217
  overrides,
218
218
  nullHandling: ruleSet.config?.nullHandling,
219
+ confidenceConfig: ruleSet.config?.confidenceConfig,
219
220
  decay: ruleSet.config?.decay
220
221
  };
221
222
 
@@ -49,7 +49,7 @@ export class ScoringEngine implements IRuleEngine<CompiledScoringRuleSet, Scorin
49
49
  // IWorkingMemory Implementation
50
50
  // ========================================
51
51
 
52
- add(input: FactInput): Fact {
52
+ add<T = Record<string, any>>(input: FactInput<T>): Fact<T> {
53
53
  return this.wm.add(input);
54
54
  }
55
55
 
@@ -57,7 +57,7 @@ export class ScoringEngine implements IRuleEngine<CompiledScoringRuleSet, Scorin
57
57
  return this.wm.remove(factId);
58
58
  }
59
59
 
60
- update(input: FactInput): Fact {
60
+ update<T = Record<string, any>>(input: FactInput<T>): Fact<T> {
61
61
  return this.wm.update(input);
62
62
  }
63
63
 
@@ -40,11 +40,15 @@ export {
40
40
  CompiledScoringAction,
41
41
  CompiledScoringRule,
42
42
  CompiledScoringRuleSet,
43
+ // Confidence types
44
+ ConfidenceConfig,
45
+ ConfidenceBreakdown,
43
46
  // Runtime types
44
47
  ScoreFunction,
45
48
  ScoreFunctionRegistry,
46
49
  ScoringOptions,
47
- ScoringResult
50
+ ScoringResult,
51
+ createScoreFunction
48
52
  } from './types';
49
53
 
50
54
  // Compiler
@@ -26,6 +26,7 @@ import {
26
26
  ScoringTierMatch,
27
27
  OverrideResult,
28
28
  CategoryResult,
29
+ ConfidenceBreakdown,
29
30
  TierDefinition,
30
31
  OutputBounds
31
32
  } from './types';
@@ -257,6 +258,35 @@ export class ScoringStrategy {
257
258
  confidence = allWeight > 0 ? firedWeight / allWeight : 0;
258
259
  }
259
260
 
261
+ // Phase 2.8: Composite confidence (when confidenceConfig provided)
262
+ let confidenceBreakdown: ConfidenceBreakdown | undefined;
263
+
264
+ if (config.confidenceConfig) {
265
+ const scW = config.confidenceConfig.signalCoverageWeight ?? 1.0;
266
+ const dfW = config.confidenceConfig.dataFreshnessWeight ?? 0;
267
+ const totalW = scW + dfW;
268
+ const signalCoverage = confidence; // from Phase 2.75
269
+
270
+ // dataFreshness = average decay multiplier across fired rules (1.0 if no decay)
271
+ let dataFreshness = 1.0;
272
+ if (fired.length > 0 && hasDecay) {
273
+ let sum = 0;
274
+ for (const ruleId of fired) {
275
+ sum += (decayMultipliers[ruleId] ?? 1.0);
276
+ }
277
+ dataFreshness = sum / fired.length;
278
+ }
279
+
280
+ if (totalW > 0) {
281
+ confidence = (signalCoverage * scW + dataFreshness * dfW) / totalW;
282
+ }
283
+
284
+ confidenceBreakdown = {
285
+ signalCoverage, dataFreshness,
286
+ weights: { signalCoverage: scW, dataFreshness: dfW }
287
+ };
288
+ }
289
+
260
290
  // Phase 3: Apply global strategies
261
291
  let categoryBreakdown: CategoryResult[] | undefined;
262
292
 
@@ -502,6 +532,7 @@ export class ScoringStrategy {
502
532
  applied: true
503
533
  },
504
534
  categoryBreakdown,
535
+ confidenceBreakdown,
505
536
  executionTimeMs
506
537
  };
507
538
  }
@@ -570,6 +601,7 @@ export class ScoringStrategy {
570
601
  tier,
571
602
  categoryBreakdown,
572
603
  override: overrideResult,
604
+ confidenceBreakdown,
573
605
  ...(hasDecay ? {
574
606
  totalScoreBeforeDecay,
575
607
  contributionsBeforeDecay,
@@ -293,6 +293,26 @@ export type ScoringRuleSet = BaseRuleSet & {
293
293
  config?: Partial<ScoringConfig>;
294
294
  };
295
295
 
296
+ /**
297
+ * Composite confidence configuration
298
+ *
299
+ * Controls how confidence is computed from multiple components.
300
+ * Without this config, confidence = signal coverage (existing behavior).
301
+ */
302
+ export type ConfidenceConfig = {
303
+ signalCoverageWeight?: number; // default: 1.0
304
+ dataFreshnessWeight?: number; // default: 0 (existing behavior)
305
+ };
306
+
307
+ /**
308
+ * Breakdown of composite confidence components
309
+ */
310
+ export type ConfidenceBreakdown = {
311
+ signalCoverage: number;
312
+ dataFreshness: number;
313
+ weights: { signalCoverage: number; dataFreshness: number };
314
+ };
315
+
296
316
  /**
297
317
  * Scoring configuration
298
318
  */
@@ -306,6 +326,7 @@ export type ScoringConfig = {
306
326
  categories?: ScoringCategory[]; // Optional category grouping for two-level weight hierarchy
307
327
  overrides?: OverrideDefinition[]; // Optional post-scoring overrides evaluated in order (first match wins)
308
328
  nullHandling?: NullHandling; // Default null handling for all rules (default: 'exclude')
329
+ confidenceConfig?: ConfidenceConfig; // Optional composite confidence configuration
309
330
  decay?: {
310
331
  timestamp?: string | Expression; // default timestamp path for all rules
311
332
  config: DecayConfig; // engine-level decay config
@@ -370,18 +391,41 @@ export type CompiledScoringRuleSet = CompiledBaseRuleSet & {
370
391
  /**
371
392
  * Score function for dynamic scoring
372
393
  */
373
- export type ScoreFunction = (context: BindingContext) => number;
394
+ export type ScoreFunction<TContext extends BindingContext = BindingContext> =
395
+ (context: TContext) => number;
374
396
 
375
397
  /**
376
398
  * Registry of score functions
377
399
  */
378
- export type ScoreFunctionRegistry = Record<string, ScoreFunction>;
400
+ export type ScoreFunctionRegistry<TContext extends BindingContext = BindingContext> =
401
+ Record<string, ScoreFunction<TContext>>;
402
+
403
+ /**
404
+ * Create a typed score function with autocomplete on context keys.
405
+ *
406
+ * Due to function contravariance, a narrowly-typed `(NarrowCtx) => number` isn't
407
+ * directly assignable to `(BindingContext) => number`. This helper handles the cast
408
+ * safely — rule inputs guarantee the correct facts at runtime.
409
+ *
410
+ * @example
411
+ * ```typescript
412
+ * type MyContext = { applicant: Fact<{ income: number; creditScore: number }> };
413
+ * const myFn = createScoreFunction<MyContext>((ctx) => {
414
+ * return ctx.applicant.data.creditScore / 850 * 100; // fully typed!
415
+ * });
416
+ * ```
417
+ */
418
+ export function createScoreFunction<TContext extends BindingContext = BindingContext>(
419
+ fn: (context: TContext) => number
420
+ ): ScoreFunction {
421
+ return fn as ScoreFunction;
422
+ }
379
423
 
380
424
  /**
381
425
  * Runtime options for scoring execution
382
426
  */
383
- export type ScoringOptions = {
384
- scoreFunctions?: ScoreFunctionRegistry; // Optional dynamic score functions
427
+ export type ScoringOptions<TContext extends BindingContext = BindingContext> = {
428
+ scoreFunctions?: ScoreFunctionRegistry<TContext>; // Optional dynamic score functions
385
429
  onFire?: (ruleId: string, context: BindingContext, score: number) => void;
386
430
  };
387
431
 
@@ -398,6 +442,7 @@ export type ScoringResult = {
398
442
  tier?: ScoringTierMatch; // Matched tier (if tiers configured)
399
443
  categoryBreakdown?: CategoryResult[]; // Per-category breakdown (if categories configured)
400
444
  override?: OverrideResult; // Override that fired (if any)
445
+ confidenceBreakdown?: ConfidenceBreakdown; // composite confidence components (if confidenceConfig set)
401
446
  totalScoreBeforeDecay?: number; // undecayed total for comparison
402
447
  contributionsBeforeDecay?: Record<string, number>; // undecayed per-rule contributions
403
448
  decayInfo?: Record<string, DecayInfo>; // per-rule decay audit
@@ -52,7 +52,7 @@ export class SequentialEngine implements IRuleEngine<CompiledSequentialRuleSet,
52
52
  // IWorkingMemory Implementation
53
53
  // ========================================
54
54
 
55
- add(input: FactInput): Fact {
55
+ add<T = Record<string, any>>(input: FactInput<T>): Fact<T> {
56
56
  return this.wm.add(input);
57
57
  }
58
58
 
@@ -60,7 +60,7 @@ export class SequentialEngine implements IRuleEngine<CompiledSequentialRuleSet,
60
60
  return this.wm.remove(factId);
61
61
  }
62
62
 
63
- update(input: FactInput): Fact {
63
+ update<T = Record<string, any>>(input: FactInput<T>): Fact<T> {
64
64
  return this.wm.update(input);
65
65
  }
66
66
 
@@ -81,7 +81,7 @@ export class UtilityEngine implements IRuleEngine<CompiledUtilityRuleSet, Utilit
81
81
  // IWorkingMemory Implementation
82
82
  // ========================================
83
83
 
84
- add(input: FactInput): Fact {
84
+ add<T = Record<string, any>>(input: FactInput<T>): Fact<T> {
85
85
  return this.wm.add(input);
86
86
  }
87
87
 
@@ -89,7 +89,7 @@ export class UtilityEngine implements IRuleEngine<CompiledUtilityRuleSet, Utilit
89
89
  return this.wm.remove(factId);
90
90
  }
91
91
 
92
- update(input: FactInput): Fact {
92
+ update<T = Record<string, any>>(input: FactInput<T>): Fact<T> {
93
93
  return this.wm.update(input);
94
94
  }
95
95
 
package/src/index.ts CHANGED
@@ -81,7 +81,8 @@ export type {
81
81
  export {
82
82
  ScoringStrategy,
83
83
  compileScoringRuleSet,
84
- scoringStrategy
84
+ scoringStrategy,
85
+ createScoreFunction
85
86
  } from './engines/scoring';
86
87
  export type {
87
88
  ScoringRule,
@@ -90,11 +91,14 @@ export type {
90
91
  CompiledScoringRuleSet,
91
92
  ScoringOptions,
92
93
  ScoringResult,
94
+ ScoreFunction,
93
95
  ScoreFunctionRegistry,
94
96
  ScoringMethod,
95
97
  OutputBounds,
96
98
  ScoringCategory,
97
99
  CategoryResult,
100
+ ConfidenceConfig,
101
+ ConfidenceBreakdown,
98
102
  OverrideEffect,
99
103
  OverrideDefinition,
100
104
  ForceTierOverride,