llmbic 1.7.0 → 1.8.0

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/CHANGELOG.md CHANGED
@@ -5,6 +5,21 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [1.8.0] - 2026-05-27
9
+
10
+ Non-breaking. New `merge.reconcile` primitive: the N-ary generalization of `merge.field`. Where `merge.field` fuses a fixed (rule, llm) pair, `merge.reconcile` fuses any number of candidate sources - several rules, an LLM, external services, manual overrides - under a single policy. Agreement detection becomes cardinal (two or more concurring candidates raise confidence), and a `priority` field replaces the hard-coded rule/llm asymmetry. `merge.field` is now a thin binary adapter over `merge.reconcile`, with identical behavior.
11
+
12
+ ### Added
13
+
14
+ - `merge.reconcile<T>(field, candidates, policy?)` - reconciles N `Candidate<T>` (`{ value, confidence, source, priority? }`) into a `ReconcileResult<T>` (`{ value, confidence, source, conflicts }`). `source` records the winning candidate, the candidates that agreed, and those that dissented.
15
+ - `ReconcileStrategy`: `'highest-priority'`, `'highest-confidence'`, `'cascade'`, `'flag-on-conflict'`, `'prefer-when-confident'`. The legacy binary strategies map onto these (e.g. `'prefer-llm'` = `'highest-priority'` with the LLM ranked first; `'flag'` = `'flag-on-conflict'`).
16
+ - `merge.defaultReconcilePolicy` - library defaults for `merge.reconcile` (strategy `'flag-on-conflict'`, `agreementConfidence` `1`, `conflictConfidence` `0.3`, `confidentThreshold` `1`, case-insensitive `compare`).
17
+ - New exported types: `Candidate`, `ReconcilePolicy`, `ReconcileStrategy`, `ReconcileSource`, `ReconcileSourceKind`, `ReconcileConflict`, `ReconcileResult`.
18
+
19
+ ### Changed
20
+
21
+ - `merge.field` is re-implemented as a binary adapter over `merge.reconcile`. Behavior, return shape, and `FieldSource` resolution are unchanged (full parity covered by the existing field tests).
22
+
8
23
  ## [1.7.0] - 2026-05-18
9
24
 
10
25
  Non-breaking. New conflict strategy `'prefer-rule-when-confident'` lets a rule win over the LLM only when its confidence clears a configurable threshold (default `1`), otherwise the LLM wins. Designed for fields where a perfectly-canonical regex outranks a noisy LLM extraction, while weaker rule hints still defer to the LLM. Closes the gap between `'prefer-rule'` (always trust the rule) and `'prefer-llm'` (always trust the LLM).
package/README.md CHANGED
@@ -246,6 +246,40 @@ const extractor = createExtractor({
246
246
 
247
247
  You can override any subset of `FieldMergePolicy` per field - strategy, confidences, even the `compare` callback (e.g. fuzzy equality for free-form strings). TypeScript validates field names against your schema, so typos surface at compile time.
248
248
 
249
+ ### Reconciling N sources
250
+
251
+ `merge.field` fuses exactly two candidates (a rule and the LLM). When a field is fed by **more than two** sources - several rules, the LLM, an external service, a manual override - reach for `merge.reconcile`, the N-ary generalization. `merge.field` is itself a thin binary adapter over it.
252
+
253
+ ```typescript
254
+ import { merge } from 'llmbic';
255
+
256
+ const result = merge.reconcile<number>('total', [
257
+ { value: 1250, confidence: 1, source: 'rule:invoice-line' },
258
+ { value: 1250, confidence: 0.8, source: 'llm' },
259
+ { value: 1300, confidence: 0.6, source: 'ocr' },
260
+ ], { strategy: 'highest-priority' });
261
+
262
+ // result.value -> 1250
263
+ // result.confidence -> 1 (agreementConfidence: two sources agree)
264
+ // result.source -> { kind: 'agreement', winner: 'rule:invoice-line',
265
+ // agreedBy: ['rule:invoice-line', 'llm'], dissentedBy: ['ocr'] }
266
+ // result.conflicts -> [{ field: 'total', winner: {...}, dissenter: { source: 'ocr', value: 1300, ... } }]
267
+ ```
268
+
269
+ Each `Candidate<T>` carries a `value`, a `confidence`, a `source` id, and an optional `priority` (higher wins; defaults to array order, earlier ranks higher). Agreement is **cardinal**: two or more candidates sharing the kept value (per `compare`) raise the confidence to `agreementConfidence`, whatever the strategy, and every dissenter is reported in `conflicts`.
270
+
271
+ Five strategies decide which single candidate wins:
272
+
273
+ | Strategy | Keeps |
274
+ |---|---|
275
+ | `'highest-priority'` | the most authoritative candidate (ties broken by confidence) |
276
+ | `'highest-confidence'` | the most confident candidate (ties broken by priority) |
277
+ | `'cascade'` | the first candidate, in array order, whose confidence clears `confidentThreshold`; `null` if none do |
278
+ | `'flag-on-conflict'` | the most authoritative candidate, lowering confidence to `conflictConfidence` and marking `source.kind: 'conflict'` when any candidate disagrees |
279
+ | `'prefer-when-confident'` | the highest-priority candidate clearing `confidentThreshold`, else the lowest-priority fallback |
280
+
281
+ Omitted policy fields fall back to `merge.defaultReconcilePolicy`.
282
+
249
283
  ### Cross-check mode
250
284
 
251
285
  Switch the LLM call from fill-gaps (ask only about missing fields) to cross-check (ask about every schema field, whether the rules resolved it or not):
package/dist/index.d.ts CHANGED
@@ -21,4 +21,5 @@ export type { LlmProvider } from './types/provider.types.js';
21
21
  export type { Logger } from './types/logger.types.js';
22
22
  export type { Severity, Violation, Validator, } from './types/validate.types.js';
23
23
  export type { Conflict, ConflictStrategy, ExtractedData, ExtractionMeta, ExtractionResult, FieldCompare, FieldMergePolicy, FieldMergeResult, FieldSource, LlmResult, MergeApplyOptions, Normalizer, NormalizerMutation, ValidationResult, } from './types/merge.types.js';
24
+ export type { Candidate, ReconcilePolicy, ReconcileStrategy, ReconcileSource, ReconcileSourceKind, ReconcileConflict, ReconcileResult, } from './types/reconcile.types.js';
24
25
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAClC,OAAO,EAAE,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AACrD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAE1C,YAAY,EACV,cAAc,EACd,SAAS,EACT,WAAW,GACZ,MAAM,uBAAuB,CAAC;AAE/B,YAAY,EACV,SAAS,EACT,eAAe,EACf,kBAAkB,GACnB,MAAM,4BAA4B,CAAC;AAEpC,YAAY,EACV,eAAe,EACf,UAAU,EACV,eAAe,EACf,kBAAkB,GACnB,MAAM,yBAAyB,CAAC;AACjC,YAAY,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAC7D,YAAY,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AAEtD,YAAY,EACV,QAAQ,EACR,SAAS,EACT,SAAS,GACV,MAAM,2BAA2B,CAAC;AAEnC,YAAY,EACV,QAAQ,EACR,gBAAgB,EAChB,aAAa,EACb,cAAc,EACd,gBAAgB,EAChB,YAAY,EACZ,gBAAgB,EAChB,gBAAgB,EAChB,WAAW,EACX,SAAS,EACT,iBAAiB,EACjB,UAAU,EACV,kBAAkB,EAClB,gBAAgB,GACjB,MAAM,wBAAwB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAClC,OAAO,EAAE,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AACrD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAE1C,YAAY,EACV,cAAc,EACd,SAAS,EACT,WAAW,GACZ,MAAM,uBAAuB,CAAC;AAE/B,YAAY,EACV,SAAS,EACT,eAAe,EACf,kBAAkB,GACnB,MAAM,4BAA4B,CAAC;AAEpC,YAAY,EACV,eAAe,EACf,UAAU,EACV,eAAe,EACf,kBAAkB,GACnB,MAAM,yBAAyB,CAAC;AACjC,YAAY,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAC7D,YAAY,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AAEtD,YAAY,EACV,QAAQ,EACR,SAAS,EACT,SAAS,GACV,MAAM,2BAA2B,CAAC;AAEnC,YAAY,EACV,QAAQ,EACR,gBAAgB,EAChB,aAAa,EACb,cAAc,EACd,gBAAgB,EAChB,YAAY,EACZ,gBAAgB,EAChB,gBAAgB,EAChB,WAAW,EACX,SAAS,EACT,iBAAiB,EACjB,UAAU,EACV,kBAAkB,EAClB,gBAAgB,GACjB,MAAM,wBAAwB,CAAC;AAEhC,YAAY,EACV,SAAS,EACT,eAAe,EACf,iBAAiB,EACjB,eAAe,EACf,mBAAmB,EACnB,iBAAiB,EACjB,eAAe,GAChB,MAAM,4BAA4B,CAAC"}
package/dist/merge.d.ts CHANGED
@@ -2,6 +2,7 @@ import type { z } from 'zod';
2
2
  import type { Logger } from './types/logger.types.js';
3
3
  import type { RuleMatch, RulesResult } from './types/rule.types.js';
4
4
  import type { ExtractionResult, FieldMergePolicy, FieldMergeResult, LlmResult, MergeApplyOptions, Normalizer } from './types/merge.types.js';
5
+ import type { Candidate, ReconcilePolicy, ReconcileResult } from './types/reconcile.types.js';
5
6
  /**
6
7
  * Field-level and object-level merge primitives.
7
8
  *
@@ -30,6 +31,44 @@ export declare const merge: {
30
31
  /** See {@link FieldMergePolicy.ruleConfidenceThreshold}. */
31
32
  ruleConfidenceThreshold: number;
32
33
  };
34
+ /**
35
+ * Library defaults applied by {@link merge.reconcile} when the caller omits
36
+ * one or more policy fields. Mirrors {@link merge.defaultFieldPolicy}: the
37
+ * default `'flag-on-conflict'` strategy keeps the most authoritative
38
+ * candidate while surfacing disagreements, and agreement boosts confidence
39
+ * to `1`.
40
+ *
41
+ * See {@link ReconcilePolicy} for the meaning of each field.
42
+ */
43
+ defaultReconcilePolicy: {
44
+ strategy: "flag-on-conflict";
45
+ compare: (a: unknown, b: unknown) => boolean;
46
+ agreementConfidence: number;
47
+ conflictConfidence: number;
48
+ confidentThreshold: number;
49
+ };
50
+ /**
51
+ * Reconcile N candidate values for a single field into one kept value, its
52
+ * confidence, and its provenance. The N-ary generalization of
53
+ * {@link merge.field}: instead of a fixed (rule, llm) pair, any number of
54
+ * sources - rules, an LLM, external services, human overrides - compete
55
+ * under a {@link ReconcilePolicy}.
56
+ *
57
+ * Agreement is cardinal: two or more candidates sharing the kept value (per
58
+ * `compare`) raise the confidence to `agreementConfidence`, whatever the
59
+ * strategy. Every dissenting candidate is reported in `conflicts` for
60
+ * observability; `source.kind` records whether the value stands alone, on an
61
+ * agreement, despite a conflict, or after a cascade fall-through.
62
+ *
63
+ * Any policy field omitted from `policy` falls back to
64
+ * {@link merge.defaultReconcilePolicy}.
65
+ *
66
+ * @typeParam T - Type of the candidate values.
67
+ * @param field - Name of the field being reconciled (echoed into conflicts).
68
+ * @param candidates - One entry per source; `null`/`undefined` values are absent.
69
+ * @param policy - Optional strategy and confidence overrides.
70
+ */
71
+ reconcile<T>(field: string, candidates: Candidate<T>[], policy?: Partial<ReconcilePolicy>): ReconcileResult<T>;
33
72
  /**
34
73
  * Fuse a rule match and an LLM value for a single field, following the
35
74
  * provided policy. Returns the kept value, its confidence, and a conflict
@@ -38,8 +77,10 @@ export declare const merge: {
38
77
  * Any policy field omitted from `policy` falls back to
39
78
  * {@link merge.defaultFieldPolicy}.
40
79
  *
41
- * Decision table (in order): rule-only, llm-only, both-null, agree,
42
- * prefer-rule, prefer-llm, flag (default fallback).
80
+ * Thin binary adapter over {@link merge.reconcile}: the rule and the LLM
81
+ * become two candidates, the conflict strategy maps to a reconcile strategy
82
+ * plus a priority order, and the result is projected back onto the binary
83
+ * contract (rule value kept on agreement, conflict recorded only on flag).
43
84
  *
44
85
  * @typeParam T - Type of the rule value.
45
86
  * @param field - Name of the field being merged.
@@ -1 +1 @@
1
- {"version":3,"file":"merge.d.ts","sourceRoot":"","sources":["../src/merge.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAC7B,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAEpE,OAAO,KAAK,EAGV,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAEhB,SAAS,EACT,iBAAiB,EACjB,UAAU,EAEX,MAAM,wBAAwB,CAAC;AA+MhC;;;;;GAKG;AACH,eAAO,MAAM,KAAK;IAChB;;;;;;OAMG;;QAED,6CAA6C;;QAE7C,yDAAyD;;QAEzD,sDAAsD;;QAEtD,wDAAwD;;QAExD,qGAAqG;qBACxF,OAAO,KAAK,OAAO,KAAG,OAAO;QAM1C,4DAA4D;;;IAI9D;;;;;;;;;;;;;;;;;;;;OAoBG;UACG,CAAC,SACE,MAAM,aACF,SAAS,CAAC,CAAC,CAAC,GAAG,IAAI,YACpB,OAAO,WACR,OAAO,CAAC,gBAAgB,CAAC,WACzB,MAAM,GACd,gBAAgB,CAAC,CAAC,CAAC;IA8EtB;;;;;;;;;;;;;;;;;;;;;;;OAuBG;UACG,CAAC,SAAS,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,EAAE,QAAQ,oBAC1C,CAAC,eACI,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,aACzB,SAAS,GAAG,IAAI,WAClB,MAAM,YACL,iBAAiB,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,YACvC,QAAQ,GACjB,gBAAgB,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;CA2ChC,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,QAAQ,GAAG,OAAO,EACpD,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,UAAU,CAAC,CAAC,EAAE,QAAQ,CAAC,GAC7B,UAAU,CAAC,CAAC,EAAE,QAAQ,CAAC,CAIzB"}
1
+ {"version":3,"file":"merge.d.ts","sourceRoot":"","sources":["../src/merge.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAC7B,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAEpE,OAAO,KAAK,EAGV,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAEhB,SAAS,EACT,iBAAiB,EACjB,UAAU,EAEX,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EACV,SAAS,EAET,eAAe,EACf,eAAe,EAIhB,MAAM,4BAA4B,CAAC;AA6QpC;;;;;GAKG;AACH,eAAO,MAAM,KAAK;IAChB;;;;;;OAMG;;QAED,6CAA6C;;QAE7C,yDAAyD;;QAEzD,sDAAsD;;QAEtD,wDAAwD;;QAExD,qGAAqG;qBA3R9E,OAAO,KAAK,OAAO,KAAG,OAAO;QA6RpD,4DAA4D;;;IAI9D;;;;;;;;OAQG;;;qBAzSsB,OAAO,KAAK,OAAO,KAAG,OAAO;;;;;IAkTtD;;;;;;;;;;;;;;;;;;;;OAoBG;cACO,CAAC,SACF,MAAM,cACD,SAAS,CAAC,CAAC,CAAC,EAAE,WACjB,OAAO,CAAC,eAAe,CAAC,GAChC,eAAe,CAAC,CAAC,CAAC;IAmErB;;;;;;;;;;;;;;;;;;;;;;OAsBG;UACG,CAAC,SACE,MAAM,aACF,SAAS,CAAC,CAAC,CAAC,GAAG,IAAI,YACpB,OAAO,WACR,OAAO,CAAC,gBAAgB,CAAC,WACzB,MAAM,GACd,gBAAgB,CAAC,CAAC,CAAC;IA0EtB;;;;;;;;;;;;;;;;;;;;;;;OAuBG;UACG,CAAC,SAAS,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,EAAE,QAAQ,oBAC1C,CAAC,eACI,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,aACzB,SAAS,GAAG,IAAI,WAClB,MAAM,YACL,iBAAiB,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,YACvC,QAAQ,GACjB,gBAAgB,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;CA2ChC,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,QAAQ,GAAG,OAAO,EACpD,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,UAAU,CAAC,CAAC,EAAE,QAAQ,CAAC,GAC7B,UAAU,CAAC,CAAC,EAAE,QAAQ,CAAC,CAIzB"}
package/dist/merge.js CHANGED
@@ -1,5 +1,45 @@
1
1
  import { valueEquals } from './utils/value-equals.js';
2
2
  import { resolveNormalizerId } from './utils/normalizer-id.js';
3
+ /**
4
+ * Default equality: case-insensitive for strings, strict otherwise. Shared by
5
+ * {@link merge.defaultFieldPolicy} and {@link merge.defaultReconcilePolicy} so
6
+ * the binary and N-ary merges agree on what "the same value" means.
7
+ */
8
+ const defaultCompare = (a, b) => {
9
+ if (typeof a === 'string' && typeof b === 'string') {
10
+ return a.toLowerCase() === b.toLowerCase();
11
+ }
12
+ return a === b;
13
+ };
14
+ /** Order by priority desc, then confidence desc, then original position asc. */
15
+ function byAuthority(a, b) {
16
+ return (b.priority - a.priority ||
17
+ b.candidate.confidence - a.candidate.confidence ||
18
+ a.index - b.index);
19
+ }
20
+ /**
21
+ * Pick the winning candidate per strategy. Returns `null` only for `'cascade'`
22
+ * when no tier clears the threshold. `present` is non-empty and in input order.
23
+ */
24
+ function selectWinner(present, policy) {
25
+ switch (policy.strategy) {
26
+ case 'highest-confidence':
27
+ return [...present].sort((a, b) => b.candidate.confidence - a.candidate.confidence ||
28
+ b.priority - a.priority ||
29
+ a.index - b.index)[0];
30
+ case 'cascade':
31
+ return present.find((e) => e.candidate.confidence >= policy.confidentThreshold) ?? null;
32
+ case 'prefer-when-confident': {
33
+ const ranked = [...present].sort(byAuthority);
34
+ return (ranked.find((e) => e.candidate.confidence >= policy.confidentThreshold) ??
35
+ ranked[ranked.length - 1]);
36
+ }
37
+ case 'highest-priority':
38
+ case 'flag-on-conflict':
39
+ default:
40
+ return [...present].sort(byAuthority)[0];
41
+ }
42
+ }
3
43
  /**
4
44
  * Walk every schema field, build the {@link RuleMatch} if rules produced a
5
45
  * value, fuse it with the LLM candidate via {@link merge.field}, and collect
@@ -181,15 +221,105 @@ export const merge = {
181
221
  /** See {@link FieldMergePolicy.agreementConfidence}. */
182
222
  agreementConfidence: 1.0,
183
223
  /** See {@link FieldMergePolicy.compare}. Case-insensitive for strings, strict equality otherwise. */
184
- compare: (a, b) => {
185
- if (typeof a === 'string' && typeof b === 'string') {
186
- return a.toLowerCase() === b.toLowerCase();
187
- }
188
- return a === b;
189
- },
224
+ compare: defaultCompare,
190
225
  /** See {@link FieldMergePolicy.ruleConfidenceThreshold}. */
191
226
  ruleConfidenceThreshold: 1,
192
227
  },
228
+ /**
229
+ * Library defaults applied by {@link merge.reconcile} when the caller omits
230
+ * one or more policy fields. Mirrors {@link merge.defaultFieldPolicy}: the
231
+ * default `'flag-on-conflict'` strategy keeps the most authoritative
232
+ * candidate while surfacing disagreements, and agreement boosts confidence
233
+ * to `1`.
234
+ *
235
+ * See {@link ReconcilePolicy} for the meaning of each field.
236
+ */
237
+ defaultReconcilePolicy: {
238
+ strategy: 'flag-on-conflict',
239
+ compare: defaultCompare,
240
+ agreementConfidence: 1.0,
241
+ conflictConfidence: 0.3,
242
+ confidentThreshold: 1,
243
+ },
244
+ /**
245
+ * Reconcile N candidate values for a single field into one kept value, its
246
+ * confidence, and its provenance. The N-ary generalization of
247
+ * {@link merge.field}: instead of a fixed (rule, llm) pair, any number of
248
+ * sources - rules, an LLM, external services, human overrides - compete
249
+ * under a {@link ReconcilePolicy}.
250
+ *
251
+ * Agreement is cardinal: two or more candidates sharing the kept value (per
252
+ * `compare`) raise the confidence to `agreementConfidence`, whatever the
253
+ * strategy. Every dissenting candidate is reported in `conflicts` for
254
+ * observability; `source.kind` records whether the value stands alone, on an
255
+ * agreement, despite a conflict, or after a cascade fall-through.
256
+ *
257
+ * Any policy field omitted from `policy` falls back to
258
+ * {@link merge.defaultReconcilePolicy}.
259
+ *
260
+ * @typeParam T - Type of the candidate values.
261
+ * @param field - Name of the field being reconciled (echoed into conflicts).
262
+ * @param candidates - One entry per source; `null`/`undefined` values are absent.
263
+ * @param policy - Optional strategy and confidence overrides.
264
+ */
265
+ reconcile(field, candidates, policy) {
266
+ const fullPolicy = { ...merge.defaultReconcilePolicy, ...policy };
267
+ const total = candidates.length;
268
+ const present = candidates
269
+ .map((candidate, index) => ({
270
+ candidate,
271
+ index,
272
+ priority: candidate.priority ?? total - index,
273
+ }))
274
+ .filter((e) => e.candidate.value !== null && e.candidate.value !== undefined);
275
+ if (present.length === 0) {
276
+ return { value: null, confidence: null, source: null, conflicts: [] };
277
+ }
278
+ const winner = selectWinner(present, fullPolicy);
279
+ if (winner === null) {
280
+ return { value: null, confidence: null, source: null, conflicts: [] };
281
+ }
282
+ const agreed = present.filter((e) => fullPolicy.compare(e.candidate.value, winner.candidate.value));
283
+ const dissenters = present.filter((e) => !fullPolicy.compare(e.candidate.value, winner.candidate.value));
284
+ let kind;
285
+ let confidence;
286
+ if (agreed.length >= 2) {
287
+ kind = 'agreement';
288
+ confidence = fullPolicy.agreementConfidence;
289
+ }
290
+ else if (fullPolicy.strategy === 'flag-on-conflict' && dissenters.length > 0) {
291
+ kind = 'conflict';
292
+ confidence = fullPolicy.conflictConfidence;
293
+ }
294
+ else if (fullPolicy.strategy === 'cascade' && winner.index !== present[0].index) {
295
+ kind = 'cascade';
296
+ confidence = winner.candidate.confidence;
297
+ }
298
+ else {
299
+ kind = 'single';
300
+ confidence = winner.candidate.confidence;
301
+ }
302
+ const conflicts = dissenters.map((d) => ({
303
+ field,
304
+ winner: {
305
+ source: winner.candidate.source,
306
+ value: winner.candidate.value,
307
+ confidence: winner.candidate.confidence,
308
+ },
309
+ dissenter: {
310
+ source: d.candidate.source,
311
+ value: d.candidate.value,
312
+ confidence: d.candidate.confidence,
313
+ },
314
+ }));
315
+ const source = {
316
+ kind,
317
+ winner: winner.candidate.source,
318
+ agreedBy: agreed.map((e) => e.candidate.source),
319
+ dissentedBy: dissenters.map((e) => e.candidate.source),
320
+ };
321
+ return { value: winner.candidate.value, confidence, source, conflicts };
322
+ },
193
323
  /**
194
324
  * Fuse a rule match and an LLM value for a single field, following the
195
325
  * provided policy. Returns the kept value, its confidence, and a conflict
@@ -198,8 +328,10 @@ export const merge = {
198
328
  * Any policy field omitted from `policy` falls back to
199
329
  * {@link merge.defaultFieldPolicy}.
200
330
  *
201
- * Decision table (in order): rule-only, llm-only, both-null, agree,
202
- * prefer-rule, prefer-llm, flag (default fallback).
331
+ * Thin binary adapter over {@link merge.reconcile}: the rule and the LLM
332
+ * become two candidates, the conflict strategy maps to a reconcile strategy
333
+ * plus a priority order, and the result is projected back onto the binary
334
+ * contract (rule value kept on agreement, conflict recorded only on flag).
203
335
  *
204
336
  * @typeParam T - Type of the rule value.
205
337
  * @param field - Name of the field being merged.
@@ -214,74 +346,65 @@ export const merge = {
214
346
  field(field, ruleMatch, llmValue, policy, logger) {
215
347
  const fullPolicy = { ...merge.defaultFieldPolicy, ...policy };
216
348
  const normalizedLlm = llmValue ?? null;
217
- if (ruleMatch !== null && normalizedLlm === null) {
218
- return {
219
- value: ruleMatch.value,
220
- confidence: ruleMatch.confidence,
221
- conflict: undefined,
222
- };
223
- }
224
- if (ruleMatch === null && normalizedLlm !== null) {
225
- return {
226
- value: normalizedLlm,
227
- confidence: fullPolicy.defaultLlmConfidence,
228
- conflict: undefined,
229
- };
230
- }
231
- if (ruleMatch === null || normalizedLlm === null) {
232
- return { value: null, confidence: null, conflict: undefined };
233
- }
234
- if (fullPolicy.compare(ruleMatch.value, normalizedLlm)) {
235
- return {
236
- value: ruleMatch.value,
237
- confidence: fullPolicy.agreementConfidence,
238
- conflict: undefined,
239
- };
240
- }
241
- if (fullPolicy.strategy === 'prefer-rule') {
242
- return {
243
- value: ruleMatch.value,
244
- confidence: ruleMatch.confidence,
245
- conflict: undefined,
246
- };
247
- }
248
- if (fullPolicy.strategy === 'prefer-llm') {
249
- return {
250
- value: normalizedLlm,
251
- confidence: fullPolicy.defaultLlmConfidence,
252
- conflict: undefined,
253
- };
254
- }
255
- if (fullPolicy.strategy === 'prefer-rule-when-confident') {
256
- if (ruleMatch.confidence >= fullPolicy.ruleConfidenceThreshold) {
257
- return {
258
- value: ruleMatch.value,
259
- confidence: ruleMatch.confidence,
260
- conflict: undefined,
261
- };
262
- }
263
- return {
264
- value: normalizedLlm,
265
- confidence: fullPolicy.defaultLlmConfidence,
266
- conflict: undefined,
267
- };
268
- }
269
- if (fullPolicy.strategy !== 'flag') {
270
- logger?.warn('unknown conflict strategy, falling back to flag', {
271
- strategy: fullPolicy.strategy,
272
- field,
273
- });
349
+ // Map the binary (rule, llm) policy onto the N-ary reconcile engine: the
350
+ // two roles become two candidates, and the conflict strategy becomes a
351
+ // reconcile strategy plus a priority order (which side outranks the other).
352
+ let strategy;
353
+ let ruleOutranksLlm = true;
354
+ switch (fullPolicy.strategy) {
355
+ case 'prefer-rule':
356
+ strategy = 'highest-priority';
357
+ break;
358
+ case 'prefer-llm':
359
+ strategy = 'highest-priority';
360
+ ruleOutranksLlm = false;
361
+ break;
362
+ case 'prefer-rule-when-confident':
363
+ strategy = 'prefer-when-confident';
364
+ break;
365
+ case 'flag':
366
+ strategy = 'flag-on-conflict';
367
+ break;
368
+ default:
369
+ logger?.warn('unknown conflict strategy, falling back to flag', {
370
+ strategy: fullPolicy.strategy,
371
+ field,
372
+ });
373
+ strategy = 'flag-on-conflict';
274
374
  }
275
- return {
276
- value: ruleMatch.value,
277
- confidence: fullPolicy.flaggedConfidence,
278
- conflict: {
375
+ const ruleCandidate = ruleMatch !== null
376
+ ? { value: ruleMatch.value, confidence: ruleMatch.confidence, source: 'rule' }
377
+ : null;
378
+ const llmCandidate = normalizedLlm !== null
379
+ ? { value: normalizedLlm, confidence: fullPolicy.defaultLlmConfidence, source: 'llm' }
380
+ : null;
381
+ // Array order sets the default priority (earlier ranks higher), so the
382
+ // outranking side goes first.
383
+ const ordered = ruleOutranksLlm
384
+ ? [ruleCandidate, llmCandidate]
385
+ : [llmCandidate, ruleCandidate];
386
+ const candidates = ordered.filter((c) => c !== null);
387
+ const result = merge.reconcile(field, candidates, {
388
+ strategy,
389
+ compare: fullPolicy.compare,
390
+ agreementConfidence: fullPolicy.agreementConfidence,
391
+ conflictConfidence: fullPolicy.flaggedConfidence,
392
+ confidentThreshold: fullPolicy.ruleConfidenceThreshold,
393
+ });
394
+ // Preserve the binary contract: on agreement the rule value is the kept
395
+ // representation (the reconcile winner may be the LLM candidate but carries
396
+ // the same value per `compare`), and a conflict record is produced only
397
+ // when a disagreement was flagged.
398
+ const value = result.source?.kind === 'agreement' && ruleMatch !== null ? ruleMatch.value : result.value;
399
+ const conflict = result.source?.kind === 'conflict' && ruleMatch !== null
400
+ ? {
279
401
  field,
280
402
  ruleValue: ruleMatch.value,
281
403
  ruleConfidence: ruleMatch.confidence,
282
404
  llmValue: normalizedLlm,
283
- },
284
- };
405
+ }
406
+ : undefined;
407
+ return { value, confidence: result.confidence, conflict };
285
408
  },
286
409
  /**
287
410
  * Walk every field of `schema`, fuse the rules pass result with the LLM
package/dist/merge.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"merge.js","sourceRoot":"","sources":["../src/merge.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"merge.js","sourceRoot":"","sources":["../src/merge.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,131 @@
1
+ import type { FieldCompare } from './merge.types.js';
2
+ /**
3
+ * One proposed value for a field, coming from a single source, with the
4
+ * confidence that source has in it. The N-ary generalization of the
5
+ * (rule, llm) pair consumed by {@link merge.field}: any number of sources -
6
+ * deterministic rules, an LLM, external services, manual overrides - can be
7
+ * reconciled through {@link merge.reconcile}.
8
+ *
9
+ * @typeParam T - Type of the proposed value.
10
+ */
11
+ export type Candidate<T> = {
12
+ /** The proposed value, or `null`/`undefined` when this source had nothing. */
13
+ value: T | null | undefined;
14
+ /** Confidence this source has in `value`, in `[0, 1]`. */
15
+ confidence: number;
16
+ /**
17
+ * Stable source identifier surfaced in {@link ReconcileSource}
18
+ * (e.g. `'rule:price'`, `'llm'`, `'service'`).
19
+ */
20
+ source: string;
21
+ /**
22
+ * Authority of the source: a higher number wins ties and conflicts. When
23
+ * omitted, the candidate's position in the array decides - earlier entries
24
+ * rank higher - so `[authoritative, fallback]` works without explicit
25
+ * priorities.
26
+ */
27
+ priority?: number;
28
+ };
29
+ /**
30
+ * How {@link merge.reconcile} picks the kept value among the present
31
+ * candidates. Agreement detection and conflict reporting run on top of every
32
+ * strategy; the strategy only decides which single candidate wins.
33
+ *
34
+ * - `'highest-priority'` - keep the highest-priority candidate. The legacy
35
+ * `'prefer-rule'`/`'prefer-llm'` strategies are this strategy with the
36
+ * winning source ranked first.
37
+ * - `'highest-confidence'` - keep the most-confident candidate, priority
38
+ * breaking ties.
39
+ * - `'cascade'` - walk candidates in array order and keep the first whose
40
+ * confidence is at or above {@link ReconcilePolicy.confidentThreshold};
41
+ * an ordered list of fallback sources. Yields `null` when none clear the bar.
42
+ * - `'flag-on-conflict'` - keep the highest-priority candidate but, when any
43
+ * present candidate disagrees, lower the confidence to
44
+ * {@link ReconcilePolicy.conflictConfidence} and mark the source
45
+ * `'conflict'`. The N-ary form of the legacy `'flag'` strategy.
46
+ * - `'prefer-when-confident'` - walk candidates by priority and keep the first
47
+ * whose confidence is at or above the threshold; if none qualify, the
48
+ * lowest-priority candidate is the final fallback. The N-ary form of
49
+ * `'prefer-rule-when-confident'`.
50
+ */
51
+ export type ReconcileStrategy = 'highest-priority' | 'highest-confidence' | 'cascade' | 'flag-on-conflict' | 'prefer-when-confident';
52
+ /**
53
+ * Behaviour overrides for {@link merge.reconcile}. Every field is optional and
54
+ * falls back to {@link merge.defaultReconcilePolicy}.
55
+ */
56
+ export type ReconcilePolicy = {
57
+ /** How to pick the kept value among present candidates. */
58
+ strategy: ReconcileStrategy;
59
+ /** Equality (or tolerance) check used to detect agreement between candidates. */
60
+ compare: FieldCompare;
61
+ /** Confidence assigned when two or more candidates agree on the kept value. */
62
+ agreementConfidence: number;
63
+ /**
64
+ * Confidence assigned when `'flag-on-conflict'` keeps a value despite a
65
+ * disagreement.
66
+ */
67
+ conflictConfidence: number;
68
+ /**
69
+ * Threshold consulted by `'cascade'` (minimum acceptable confidence) and by
70
+ * `'prefer-when-confident'`. Default `1`.
71
+ */
72
+ confidentThreshold: number;
73
+ };
74
+ /**
75
+ * Why {@link merge.reconcile} kept the value it kept.
76
+ *
77
+ * - `'single'` - one candidate carried the day with no peer agreeing.
78
+ * - `'agreement'` - two or more candidates agreed on the kept value.
79
+ * - `'conflict'` - the value was kept despite a disagreement (`'flag-on-conflict'`).
80
+ * - `'cascade'` - a later tier won after earlier tiers fell through.
81
+ */
82
+ export type ReconcileSourceKind = 'single' | 'agreement' | 'conflict' | 'cascade';
83
+ /**
84
+ * Provenance of a reconciled value: the winning source, the sources that
85
+ * agreed with it (including the winner), and the sources that dissented.
86
+ */
87
+ export type ReconcileSource = {
88
+ kind: ReconcileSourceKind;
89
+ /** Source id of the winning candidate. */
90
+ winner: string;
91
+ /** Source ids whose value agreed with the winner (winner included). */
92
+ agreedBy: string[];
93
+ /** Source ids whose value disagreed with the winner. */
94
+ dissentedBy: string[];
95
+ };
96
+ /**
97
+ * A disagreement between the kept value and one dissenting candidate, surfaced
98
+ * by {@link merge.reconcile} for observability regardless of the strategy.
99
+ */
100
+ export type ReconcileConflict = {
101
+ /** Name of the field being reconciled. */
102
+ field: string;
103
+ /** The candidate that won. */
104
+ winner: {
105
+ source: string;
106
+ value: unknown;
107
+ confidence: number;
108
+ };
109
+ /** A candidate whose value disagreed with the winner. */
110
+ dissenter: {
111
+ source: string;
112
+ value: unknown;
113
+ confidence: number;
114
+ };
115
+ };
116
+ /**
117
+ * Outcome of reconciling N candidates for a single field.
118
+ *
119
+ * @typeParam T - Type of the reconciled value.
120
+ */
121
+ export type ReconcileResult<T> = {
122
+ /** The value kept, or `null` if no candidate provided one. */
123
+ value: T | null;
124
+ /** Confidence associated with `value`, in `[0, 1]`, or `null` if absent. */
125
+ confidence: number | null;
126
+ /** Provenance of the kept value, or `null` when no candidate had a value. */
127
+ source: ReconcileSource | null;
128
+ /** One entry per dissenting candidate; empty when all present candidates agree. */
129
+ conflicts: ReconcileConflict[];
130
+ };
131
+ //# sourceMappingURL=reconcile.types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reconcile.types.d.ts","sourceRoot":"","sources":["../../src/types/reconcile.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAErD;;;;;;;;GAQG;AACH,MAAM,MAAM,SAAS,CAAC,CAAC,IAAI;IACzB,8EAA8E;IAC9E,KAAK,EAAE,CAAC,GAAG,IAAI,GAAG,SAAS,CAAC;IAC5B,0DAA0D;IAC1D,UAAU,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,MAAM,EAAE,MAAM,CAAC;IACf;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,MAAM,iBAAiB,GACzB,kBAAkB,GAClB,oBAAoB,GACpB,SAAS,GACT,kBAAkB,GAClB,uBAAuB,CAAC;AAE5B;;;GAGG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B,2DAA2D;IAC3D,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,iFAAiF;IACjF,OAAO,EAAE,YAAY,CAAC;IACtB,+EAA+E;IAC/E,mBAAmB,EAAE,MAAM,CAAC;IAC5B;;;OAGG;IACH,kBAAkB,EAAE,MAAM,CAAC;IAC3B;;;OAGG;IACH,kBAAkB,EAAE,MAAM,CAAC;CAC5B,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,MAAM,mBAAmB,GAAG,QAAQ,GAAG,WAAW,GAAG,UAAU,GAAG,SAAS,CAAC;AAElF;;;GAGG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,mBAAmB,CAAC;IAC1B,0CAA0C;IAC1C,MAAM,EAAE,MAAM,CAAC;IACf,uEAAuE;IACvE,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,wDAAwD;IACxD,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,0CAA0C;IAC1C,KAAK,EAAE,MAAM,CAAC;IACd,8BAA8B;IAC9B,MAAM,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,OAAO,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/D,yDAAyD;IACzD,SAAS,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,OAAO,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;CACnE,CAAC;AAEF;;;;GAIG;AACH,MAAM,MAAM,eAAe,CAAC,CAAC,IAAI;IAC/B,8DAA8D;IAC9D,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC;IAChB,4EAA4E;IAC5E,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,6EAA6E;IAC7E,MAAM,EAAE,eAAe,GAAG,IAAI,CAAC;IAC/B,mFAAmF;IACnF,SAAS,EAAE,iBAAiB,EAAE,CAAC;CAChC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=reconcile.types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reconcile.types.js","sourceRoot":"","sources":["../../src/types/reconcile.types.ts"],"names":[],"mappings":""}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "llmbic",
3
- "version": "1.7.0",
3
+ "version": "1.8.0",
4
4
  "description": "Hybrid data extraction — deterministic rules + LLM fallback, with per-field confidence scoring.",
5
5
  "type": "module",
6
6
  "license": "MIT",