@jungjaehoon/mama-core 1.4.1 → 1.5.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.
Files changed (120) hide show
  1. package/db/migrations/026-create-canonical-entity-tables.sql +99 -0
  2. package/db/migrations/027-create-entity-review-support.sql +44 -0
  3. package/db/migrations/028-create-entity-audit-tables.sql +45 -0
  4. package/db/migrations/029-extend-entity-observations-observation-type.sql +60 -0
  5. package/db/migrations/030-case-first-memory-substrate.sql +901 -0
  6. package/db/migrations/031-wiki-page-index-provenance-columns.sql +2 -0
  7. package/dist/canonicalize.d.ts +38 -0
  8. package/dist/canonicalize.js +106 -0
  9. package/dist/cases/case-links.d.ts +116 -0
  10. package/dist/cases/case-links.js +794 -0
  11. package/dist/cases/composition-overrides.d.ts +90 -0
  12. package/dist/cases/composition-overrides.js +724 -0
  13. package/dist/cases/corrections.d.ts +156 -0
  14. package/dist/cases/corrections.js +1045 -0
  15. package/dist/cases/freshness.d.ts +57 -0
  16. package/dist/cases/freshness.js +283 -0
  17. package/dist/cases/live-state.d.ts +48 -0
  18. package/dist/cases/live-state.js +256 -0
  19. package/dist/cases/membership-explain.d.ts +56 -0
  20. package/dist/cases/membership-explain.js +140 -0
  21. package/dist/cases/membership-matcher.d.ts +23 -0
  22. package/dist/cases/membership-matcher.js +193 -0
  23. package/dist/cases/merge-split.d.ts +61 -0
  24. package/dist/cases/merge-split.js +368 -0
  25. package/dist/cases/role-inference.d.ts +10 -0
  26. package/dist/cases/role-inference.js +85 -0
  27. package/dist/cases/search-rollup.d.ts +23 -0
  28. package/dist/cases/search-rollup.js +225 -0
  29. package/dist/cases/sqlite-transaction.d.ts +10 -0
  30. package/dist/cases/sqlite-transaction.js +62 -0
  31. package/dist/cases/store.d.ts +74 -0
  32. package/dist/cases/store.js +816 -0
  33. package/dist/cases/target-ref.d.ts +25 -0
  34. package/dist/cases/target-ref.js +22 -0
  35. package/dist/cases/timeline-range.d.ts +6 -0
  36. package/dist/cases/timeline-range.js +322 -0
  37. package/dist/cases/tombstone-sweeper.d.ts +13 -0
  38. package/dist/cases/tombstone-sweeper.js +128 -0
  39. package/dist/cases/types.d.ts +244 -0
  40. package/dist/cases/types.js +47 -0
  41. package/dist/cases/wiki-page-index.d.ts +50 -0
  42. package/dist/cases/wiki-page-index.js +350 -0
  43. package/dist/config-loader.d.ts +1 -0
  44. package/dist/config-loader.js +43 -0
  45. package/dist/connectors/event-index.d.ts +44 -0
  46. package/dist/connectors/event-index.js +366 -0
  47. package/dist/connectors/types.d.ts +69 -0
  48. package/dist/connectors/types.js +3 -0
  49. package/dist/db-manager.d.ts +4 -0
  50. package/dist/db-manager.js +10 -3
  51. package/dist/decision-formatter.d.ts +2 -0
  52. package/dist/decision-formatter.js +11 -8
  53. package/dist/embedding-server/mobile/daemon.d.ts +1 -0
  54. package/dist/embedding-server/mobile/daemon.js +11 -1
  55. package/dist/entities/audit-metrics.d.ts +73 -0
  56. package/dist/entities/audit-metrics.js +128 -0
  57. package/dist/entities/candidate-generator.d.ts +9 -0
  58. package/dist/entities/candidate-generator.js +436 -0
  59. package/dist/entities/entity-impact.d.ts +41 -0
  60. package/dist/entities/entity-impact.js +140 -0
  61. package/dist/entities/entity-linked-decision-counts.d.ts +2 -0
  62. package/dist/entities/entity-linked-decision-counts.js +29 -0
  63. package/dist/entities/entity-list.d.ts +23 -0
  64. package/dist/entities/entity-list.js +99 -0
  65. package/dist/entities/entity-orphan-list.d.ts +26 -0
  66. package/dist/entities/entity-orphan-list.js +91 -0
  67. package/dist/entities/entity-search.d.ts +21 -0
  68. package/dist/entities/entity-search.js +150 -0
  69. package/dist/entities/errors.d.ts +65 -0
  70. package/dist/entities/errors.js +124 -0
  71. package/dist/entities/exact-merge-backfill.d.ts +11 -0
  72. package/dist/entities/exact-merge-backfill.js +161 -0
  73. package/dist/entities/lineage-backfill.d.ts +12 -0
  74. package/dist/entities/lineage-backfill.js +101 -0
  75. package/dist/entities/lineage-store.d.ts +51 -0
  76. package/dist/entities/lineage-store.js +308 -0
  77. package/dist/entities/normalization.d.ts +14 -0
  78. package/dist/entities/normalization.js +63 -0
  79. package/dist/entities/policy-store.d.ts +17 -0
  80. package/dist/entities/policy-store.js +263 -0
  81. package/dist/entities/policy-types.d.ts +72 -0
  82. package/dist/entities/policy-types.js +59 -0
  83. package/dist/entities/projection.d.ts +8 -0
  84. package/dist/entities/projection.js +82 -0
  85. package/dist/entities/provenance-query.d.ts +33 -0
  86. package/dist/entities/provenance-query.js +167 -0
  87. package/dist/entities/read-identity.d.ts +31 -0
  88. package/dist/entities/read-identity.js +264 -0
  89. package/dist/entities/recall-bridge.d.ts +5 -0
  90. package/dist/entities/recall-bridge.js +171 -0
  91. package/dist/entities/resolution-engine.d.ts +15 -0
  92. package/dist/entities/resolution-engine.js +69 -0
  93. package/dist/entities/rollback-preview.d.ts +39 -0
  94. package/dist/entities/rollback-preview.js +235 -0
  95. package/dist/entities/source-locator.d.ts +3 -0
  96. package/dist/entities/source-locator.js +32 -0
  97. package/dist/entities/store.d.ts +75 -0
  98. package/dist/entities/store.js +465 -0
  99. package/dist/entities/types.d.ts +162 -0
  100. package/dist/entities/types.js +30 -0
  101. package/dist/index.d.ts +47 -2
  102. package/dist/index.js +66 -25
  103. package/dist/mama-api.d.ts +22 -1
  104. package/dist/mama-api.js +272 -64
  105. package/dist/memory/api.d.ts +28 -1
  106. package/dist/memory/api.js +293 -31
  107. package/dist/memory/types.d.ts +11 -2
  108. package/dist/search/feedback-store.d.ts +59 -0
  109. package/dist/search/feedback-store.js +211 -0
  110. package/dist/search/question-type.d.ts +5 -0
  111. package/dist/search/question-type.js +41 -0
  112. package/dist/search/ranker-features.d.ts +23 -0
  113. package/dist/search/ranker-features.js +104 -0
  114. package/dist/search/ranker-rescore.d.ts +31 -0
  115. package/dist/search/ranker-rescore.js +226 -0
  116. package/dist/search/ranker-trainer.d.ts +94 -0
  117. package/dist/search/ranker-trainer.js +860 -0
  118. package/dist/test-utils.d.ts +14 -0
  119. package/dist/test-utils.js +52 -0
  120. package/package.json +21 -3
@@ -140,7 +140,7 @@ Top ${full.length} Most Relevant Decisions:
140
140
  `.trim();
141
141
  for (let i = 0; i < full.length; i++) {
142
142
  const d = full[i];
143
- const duration = calculateDuration(d.created_at);
143
+ const duration = calculateDuration(getDecisionTimestamp(d));
144
144
  const outcomeEmoji = getOutcomeEmoji(d.outcome ?? null);
145
145
  const relevancePercent = Math.round((d.relevanceScore || 0) * 100);
146
146
  context += `\n\n${i + 1}. ${d.decision} (${duration}, relevance: ${relevancePercent}%) ${outcomeEmoji}`;
@@ -166,7 +166,7 @@ Top ${full.length} Most Relevant Decisions:
166
166
  * Format small decision history (3 or fewer)
167
167
  */
168
168
  function formatSmallHistory(current, history) {
169
- const duration = calculateDuration(current.created_at);
169
+ const duration = calculateDuration(getDecisionTimestamp(current));
170
170
  let context = `
171
171
  🧠 DECISION HISTORY: ${current.topic}
172
172
 
@@ -284,6 +284,9 @@ function calculateDuration(timestamp) {
284
284
  }
285
285
  return `${diffDays} day${diffDays !== 1 ? 's' : ''} ago`;
286
286
  }
287
+ function getDecisionTimestamp(decision) {
288
+ return decision.event_datetime ?? decision.created_at;
289
+ }
287
290
  /**
288
291
  * Calculate duration between two timestamps in days
289
292
  */
@@ -560,7 +563,7 @@ function formatTeaserList(decisions, topN = 3) {
560
563
  output += `\n "${preview}"`;
561
564
  // Recency metadata (NEW - Gaussian Decay)
562
565
  if (d.recency_age_days !== undefined && d.created_at) {
563
- const timeAgo = calculateDuration(d.created_at);
566
+ const timeAgo = calculateDuration(getDecisionTimestamp(d));
564
567
  const recencyScore = d.recency_score ? Math.round(d.recency_score * 100) : null;
565
568
  const finalScore = d.final_score ? Math.round(d.final_score * 100) : null;
566
569
  output += `\n ⏰ ${timeAgo}`;
@@ -582,7 +585,7 @@ function formatTeaser(decision) {
582
585
  if (!decision) {
583
586
  return null;
584
587
  }
585
- const timeAgo = calculateDuration(decision.created_at);
588
+ const timeAgo = calculateDuration(getDecisionTimestamp(decision));
586
589
  // Extract preview (first 60 chars)
587
590
  const preview = decision.decision.length > 60 ? decision.decision.substring(0, 60) + '...' : decision.decision;
588
591
  // Extract files from trust_context or show generic
@@ -633,7 +636,7 @@ function formatRecall(decisions, semanticEdges = null) {
633
636
  * Format single decision with full detail
634
637
  */
635
638
  function formatSingleDecision(decision) {
636
- const timeAgo = calculateDuration(decision.created_at);
639
+ const timeAgo = calculateDuration(getDecisionTimestamp(decision));
637
640
  const confidencePercent = Math.round((decision.confidence || 0) * 100);
638
641
  const outcomeEmoji = getOutcomeEmoji(decision.outcome ?? null);
639
642
  const outcomeText = decision.outcome || 'Not yet tracked';
@@ -725,7 +728,7 @@ function formatDecisionHistory(decisions, semanticEdges = null) {
725
728
  📋 Decision History: ${topic}
726
729
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
727
730
 
728
- Latest Decision (${calculateDuration(latest.created_at)}):
731
+ Latest Decision (${calculateDuration(getDecisionTimestamp(latest))}):
729
732
  ${latest.decision}
730
733
  `.trim();
731
734
  // Show brief reasoning if available
@@ -777,7 +780,7 @@ ${latest.decision}
777
780
  output += `\nPrevious Decisions (${older.length}):\n`;
778
781
  for (let i = 0; i < Math.min(older.length, 5); i++) {
779
782
  const d = older[i];
780
- const timeAgo = calculateDuration(d.created_at);
783
+ const timeAgo = calculateDuration(getDecisionTimestamp(d));
781
784
  const emoji = getOutcomeEmoji(d.outcome ?? null);
782
785
  output += `\n${i + 2}. ${d.decision} (${timeAgo}) ${emoji}`;
783
786
  if (d.outcome === 'FAILED' && d.failure_reason) {
@@ -876,7 +879,7 @@ function formatList(decisions, options = {}) {
876
879
  output += '━'.repeat(60) + '\n';
877
880
  for (let i = 0; i < items.length; i++) {
878
881
  const d = items[i];
879
- const timeAgo = calculateDuration(d.created_at);
882
+ const timeAgo = calculateDuration(getDecisionTimestamp(d));
880
883
  const type = d.user_involvement === 'approved' ? '👤 User' : '🤖 Assistant';
881
884
  const status = d.outcome ? getOutcomeEmoji(d.outcome) + ' ' + d.outcome : '⏳ Pending';
882
885
  const confidence = Math.round((d.confidence || 0) * 100);
@@ -83,6 +83,7 @@ export declare class ClaudeDaemon extends EventEmitter {
83
83
  private _pid;
84
84
  private _isRunning;
85
85
  private buffer;
86
+ private cliSessionId;
86
87
  /**
87
88
  * Create a new ClaudeDaemon instance
88
89
  * @param projectDir - Working directory for Claude Code
@@ -17,6 +17,7 @@
17
17
  Object.defineProperty(exports, "__esModule", { value: true });
18
18
  exports.ClaudeDaemon = exports.ANSI_REGEX = void 0;
19
19
  const events_1 = require("events");
20
+ const crypto_1 = require("crypto");
20
21
  const child_process_1 = require("child_process");
21
22
  /**
22
23
  * ANSI escape code regex pattern
@@ -38,6 +39,7 @@ class ClaudeDaemon extends events_1.EventEmitter {
38
39
  _pid;
39
40
  _isRunning;
40
41
  buffer;
42
+ cliSessionId;
41
43
  /**
42
44
  * Create a new ClaudeDaemon instance
43
45
  * @param projectDir - Working directory for Claude Code
@@ -51,6 +53,7 @@ class ClaudeDaemon extends events_1.EventEmitter {
51
53
  this._pid = null;
52
54
  this._isRunning = false;
53
55
  this.buffer = '';
56
+ this.cliSessionId = (0, crypto_1.randomUUID)();
54
57
  }
55
58
  /**
56
59
  * Check if the daemon is currently running
@@ -76,13 +79,20 @@ class ClaudeDaemon extends events_1.EventEmitter {
76
79
  return new Promise((resolve, reject) => {
77
80
  let settled = false;
78
81
  try {
79
- // Use stream-json mode for bidirectional JSON communication
82
+ // Requires a modern Claude CLI build with stream-json support
83
+ // for --print/--verbose/--session-id/--setting-sources.
80
84
  const args = [
85
+ '--print',
86
+ '--verbose',
81
87
  '--dangerously-skip-permissions',
82
88
  '--input-format',
83
89
  'stream-json',
84
90
  '--output-format',
85
91
  'stream-json',
92
+ '--session-id',
93
+ this.cliSessionId,
94
+ '--setting-sources',
95
+ 'project,local',
86
96
  ];
87
97
  // Spawn Claude Code CLI
88
98
  this.process = (0, child_process_1.spawn)('claude', args, {
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Entity audit metric helpers.
3
+ *
4
+ * Pure functions — no DB, no embeddings. The audit queue assembles the
5
+ * snapshot from live tables and fixtures, then hands it to these helpers
6
+ * for deterministic metric calculation + baseline classification.
7
+ */
8
+ export declare const FALSE_MERGE_HARD_CEILING = 0.02;
9
+ export type EntityAuditClassification = 'improved' | 'stable' | 'regressed' | 'inconclusive';
10
+ export interface AuditCandidateSnapshot {
11
+ id: string;
12
+ status: 'pending' | 'auto_merged' | 'approved' | 'rejected' | 'deferred';
13
+ score_total: number;
14
+ left_canonical_id: string | null;
15
+ right_canonical_id: string | null;
16
+ left_kind: string | null;
17
+ right_kind: string | null;
18
+ }
19
+ export interface AuditGoldPair {
20
+ canonical_id: string;
21
+ left_obs_id: string;
22
+ right_obs_id: string;
23
+ }
24
+ export interface AuditCandidateGoldLink {
25
+ candidate_id: string;
26
+ matched_pair_key: string;
27
+ score_total: number;
28
+ }
29
+ export interface AuditSnapshot {
30
+ candidates: AuditCandidateSnapshot[];
31
+ gold_pairs: AuditGoldPair[];
32
+ candidate_gold_matches: AuditCandidateGoldLink[];
33
+ gold_canonical_projection_counts: Record<string, number>;
34
+ }
35
+ export interface AuditMetricSummary {
36
+ false_merge_rate: number;
37
+ false_merge_numerator: number;
38
+ false_merge_denominator: number;
39
+ cross_language_candidate_recall_at_10: number;
40
+ cross_language_recall_numerator: number;
41
+ cross_language_recall_denominator: number;
42
+ ontology_violation_count: number;
43
+ projection_fragmentation_rate: number;
44
+ }
45
+ export interface AuditRunClassificationInput {
46
+ current: AuditMetricSummary;
47
+ baseline: AuditMetricSummary | null;
48
+ }
49
+ export declare function computeFalseMergeRate(candidates: AuditCandidateSnapshot[]): {
50
+ rate: number;
51
+ numerator: number;
52
+ denominator: number;
53
+ };
54
+ export declare function computeCrossLanguageRecallAtK(goldPairs: AuditGoldPair[], matches: AuditCandidateGoldLink[], k: number): {
55
+ recall: number;
56
+ numerator: number;
57
+ denominator: number;
58
+ };
59
+ export declare function computeCrossLanguageRecallAt5(goldPairs: AuditGoldPair[], matches: AuditCandidateGoldLink[]): {
60
+ recall: number;
61
+ numerator: number;
62
+ denominator: number;
63
+ };
64
+ export declare function computeCrossLanguageRecallAt10(goldPairs: AuditGoldPair[], matches: AuditCandidateGoldLink[]): {
65
+ recall: number;
66
+ numerator: number;
67
+ denominator: number;
68
+ };
69
+ export declare function computeOntologyViolationCount(candidates: AuditCandidateSnapshot[]): number;
70
+ export declare function computeProjectionFragmentationRate(counts: Record<string, number>): number;
71
+ export declare function computeAuditMetrics(snapshot: AuditSnapshot): AuditMetricSummary;
72
+ export declare function classifyAuditRun(input: AuditRunClassificationInput): EntityAuditClassification;
73
+ //# sourceMappingURL=audit-metrics.d.ts.map
@@ -0,0 +1,128 @@
1
+ "use strict";
2
+ /**
3
+ * Entity audit metric helpers.
4
+ *
5
+ * Pure functions — no DB, no embeddings. The audit queue assembles the
6
+ * snapshot from live tables and fixtures, then hands it to these helpers
7
+ * for deterministic metric calculation + baseline classification.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.FALSE_MERGE_HARD_CEILING = void 0;
11
+ exports.computeFalseMergeRate = computeFalseMergeRate;
12
+ exports.computeCrossLanguageRecallAtK = computeCrossLanguageRecallAtK;
13
+ exports.computeCrossLanguageRecallAt5 = computeCrossLanguageRecallAt5;
14
+ exports.computeCrossLanguageRecallAt10 = computeCrossLanguageRecallAt10;
15
+ exports.computeOntologyViolationCount = computeOntologyViolationCount;
16
+ exports.computeProjectionFragmentationRate = computeProjectionFragmentationRate;
17
+ exports.computeAuditMetrics = computeAuditMetrics;
18
+ exports.classifyAuditRun = classifyAuditRun;
19
+ exports.FALSE_MERGE_HARD_CEILING = 0.02;
20
+ const RESOLVED_MERGE_STATUSES = new Set([
21
+ 'auto_merged',
22
+ 'approved',
23
+ ]);
24
+ function computeFalseMergeRate(candidates) {
25
+ let denominator = 0;
26
+ let numerator = 0;
27
+ for (const candidate of candidates) {
28
+ if (!RESOLVED_MERGE_STATUSES.has(candidate.status))
29
+ continue;
30
+ denominator += 1;
31
+ if (candidate.left_canonical_id &&
32
+ candidate.right_canonical_id &&
33
+ candidate.left_canonical_id !== candidate.right_canonical_id) {
34
+ numerator += 1;
35
+ }
36
+ }
37
+ const rate = denominator === 0 ? 0 : numerator / denominator;
38
+ return { rate, numerator, denominator };
39
+ }
40
+ function computeCrossLanguageRecallAtK(goldPairs, matches, k) {
41
+ const denominator = goldPairs.length;
42
+ if (denominator === 0) {
43
+ return { recall: 0, numerator: 0, denominator: 0 };
44
+ }
45
+ const topRanked = [...matches]
46
+ .sort((a, b) => b.score_total - a.score_total)
47
+ .slice(0, Math.max(0, k))
48
+ .map((m) => m.matched_pair_key);
49
+ const matched = new Set(topRanked);
50
+ let numerator = 0;
51
+ for (const pair of goldPairs) {
52
+ const key = `${pair.canonical_id}:${pair.left_obs_id}:${pair.right_obs_id}`;
53
+ if (matched.has(key)) {
54
+ numerator += 1;
55
+ }
56
+ }
57
+ return { recall: numerator / denominator, numerator, denominator };
58
+ }
59
+ function computeCrossLanguageRecallAt5(goldPairs, matches) {
60
+ return computeCrossLanguageRecallAtK(goldPairs, matches, 5);
61
+ }
62
+ function computeCrossLanguageRecallAt10(goldPairs, matches) {
63
+ return computeCrossLanguageRecallAtK(goldPairs, matches, 10);
64
+ }
65
+ function computeOntologyViolationCount(candidates) {
66
+ let count = 0;
67
+ for (const candidate of candidates) {
68
+ if (candidate.left_kind &&
69
+ candidate.right_kind &&
70
+ candidate.left_kind !== candidate.right_kind) {
71
+ count += 1;
72
+ }
73
+ }
74
+ return count;
75
+ }
76
+ function computeProjectionFragmentationRate(counts) {
77
+ const keys = Object.keys(counts);
78
+ if (keys.length === 0)
79
+ return 0;
80
+ let fragmented = 0;
81
+ for (const key of keys) {
82
+ if ((counts[key] ?? 0) > 1)
83
+ fragmented += 1;
84
+ }
85
+ return fragmented / keys.length;
86
+ }
87
+ function computeAuditMetrics(snapshot) {
88
+ const falseMerge = computeFalseMergeRate(snapshot.candidates);
89
+ const recall = computeCrossLanguageRecallAt10(snapshot.gold_pairs, snapshot.candidate_gold_matches);
90
+ const ontology = computeOntologyViolationCount(snapshot.candidates);
91
+ const fragmentation = computeProjectionFragmentationRate(snapshot.gold_canonical_projection_counts);
92
+ return {
93
+ false_merge_rate: falseMerge.rate,
94
+ false_merge_numerator: falseMerge.numerator,
95
+ false_merge_denominator: falseMerge.denominator,
96
+ cross_language_candidate_recall_at_10: recall.recall,
97
+ cross_language_recall_numerator: recall.numerator,
98
+ cross_language_recall_denominator: recall.denominator,
99
+ ontology_violation_count: ontology,
100
+ projection_fragmentation_rate: fragmentation,
101
+ };
102
+ }
103
+ function classifyAuditRun(input) {
104
+ const { current, baseline } = input;
105
+ if (current.false_merge_rate > exports.FALSE_MERGE_HARD_CEILING) {
106
+ return 'regressed';
107
+ }
108
+ if (!baseline) {
109
+ return 'inconclusive';
110
+ }
111
+ if (current.false_merge_rate > baseline.false_merge_rate) {
112
+ return 'regressed';
113
+ }
114
+ const recallUp = current.cross_language_candidate_recall_at_10 > baseline.cross_language_candidate_recall_at_10;
115
+ const fragmentationDown = current.projection_fragmentation_rate < baseline.projection_fragmentation_rate;
116
+ const ontologyDown = current.ontology_violation_count < baseline.ontology_violation_count;
117
+ if (recallUp || fragmentationDown || ontologyDown) {
118
+ const anyRegression = current.cross_language_candidate_recall_at_10 <
119
+ baseline.cross_language_candidate_recall_at_10 ||
120
+ current.projection_fragmentation_rate > baseline.projection_fragmentation_rate ||
121
+ current.ontology_violation_count > baseline.ontology_violation_count;
122
+ if (anyRegression)
123
+ return 'stable';
124
+ return 'improved';
125
+ }
126
+ return 'stable';
127
+ }
128
+ //# sourceMappingURL=audit-metrics.js.map
@@ -0,0 +1,9 @@
1
+ import type { EntityObservation, EntityResolutionCandidate } from './types.js';
2
+ export declare const ENTITY_EMBEDDING_TOPN = 50;
3
+ export interface CandidateGeneratorOptions {
4
+ embeddingScorer?: (left: EntityObservation, right: EntityObservation) => Promise<number>;
5
+ topN?: number;
6
+ }
7
+ export declare function dedupeObservationsBySource(observations: EntityObservation[]): EntityObservation[];
8
+ export declare function generateResolutionCandidates(observations: EntityObservation[], options?: CandidateGeneratorOptions): Promise<EntityResolutionCandidate[]>;
9
+ //# sourceMappingURL=candidate-generator.d.ts.map