@jungjaehoon/mama-core 1.9.0 → 2.1.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 (139) hide show
  1. package/db/migrations/043-add-tool-trace-failure-code.sql +11 -0
  2. package/dist/agent-graph/alias-write.js +3 -0
  3. package/dist/agent-graph/entity-resolve.js +3 -7
  4. package/dist/agent-graph/graph-query.js +5 -4
  5. package/dist/agent-graph/types.d.ts +30 -0
  6. package/dist/cases/store.d.ts +0 -4
  7. package/dist/cases/store.js +0 -66
  8. package/dist/cases/wiki-page-index.d.ts +0 -13
  9. package/dist/cases/wiki-page-index.js +0 -153
  10. package/dist/connectors/event-index.d.ts +1 -22
  11. package/dist/connectors/event-index.js +0 -157
  12. package/dist/context-compile/channel-grant.d.ts +46 -0
  13. package/dist/context-compile/channel-grant.js +66 -0
  14. package/dist/context-compile/compiler.js +5 -2
  15. package/dist/context-compile/index.d.ts +1 -0
  16. package/dist/context-compile/index.js +1 -0
  17. package/dist/context-compile/packet-store.d.ts +0 -1
  18. package/dist/context-compile/packet-store.js +0 -16
  19. package/dist/context-compile/source-readers.d.ts +1 -0
  20. package/dist/context-compile/source-readers.js +156 -23
  21. package/dist/context-compile/types.d.ts +17 -0
  22. package/dist/context-compile/visibility.js +28 -4
  23. package/dist/db-adapter/node-sqlite-adapter.js +4 -0
  24. package/dist/db-manager.d.ts +0 -13
  25. package/dist/db-manager.js +0 -66
  26. package/dist/decision-formatter.d.ts +0 -11
  27. package/dist/decision-formatter.js +0 -122
  28. package/dist/decision-tracker.d.ts +0 -12
  29. package/dist/decision-tracker.js +0 -50
  30. package/dist/edges/ref-validation.d.ts +1 -2
  31. package/dist/edges/ref-validation.js +33 -13
  32. package/dist/edges/store.d.ts +1 -3
  33. package/dist/edges/store.js +0 -214
  34. package/dist/edges/types.d.ts +10 -0
  35. package/dist/embedding-client.d.ts +0 -17
  36. package/dist/embedding-client.js +0 -80
  37. package/dist/embedding-server/mobile/auth.d.ts +1 -10
  38. package/dist/embedding-server/mobile/auth.js +0 -15
  39. package/dist/embeddings.d.ts +0 -12
  40. package/dist/embeddings.js +0 -68
  41. package/dist/entities/audit-metrics.d.ts +0 -5
  42. package/dist/entities/audit-metrics.js +0 -4
  43. package/dist/entities/candidate-generator.d.ts +1 -2
  44. package/dist/entities/candidate-generator.js +0 -412
  45. package/dist/entities/entity-list.d.ts +0 -1
  46. package/dist/entities/entity-list.js +0 -96
  47. package/dist/entities/entity-orphan-list.d.ts +0 -9
  48. package/dist/entities/entity-orphan-list.js +0 -88
  49. package/dist/entities/entity-search.d.ts +0 -1
  50. package/dist/entities/entity-search.js +0 -147
  51. package/dist/entities/errors.d.ts +0 -10
  52. package/dist/entities/errors.js +1 -25
  53. package/dist/entities/lineage-store.d.ts +0 -23
  54. package/dist/entities/lineage-store.js +0 -104
  55. package/dist/entities/policy-store.d.ts +0 -9
  56. package/dist/entities/policy-store.js +0 -188
  57. package/dist/entities/provenance-query.d.ts +0 -1
  58. package/dist/entities/provenance-query.js +0 -164
  59. package/dist/entities/resolution-engine.d.ts +1 -8
  60. package/dist/entities/resolution-engine.js +0 -66
  61. package/dist/entities/rollback-preview.d.ts +0 -4
  62. package/dist/entities/rollback-preview.js +0 -232
  63. package/dist/entities/store.d.ts +1 -10
  64. package/dist/entities/store.js +0 -49
  65. package/dist/index.d.ts +15 -31
  66. package/dist/index.js +4 -46
  67. package/dist/mama-api.d.ts +19 -1
  68. package/dist/mama-api.js +97 -2
  69. package/dist/memory/api.d.ts +8 -0
  70. package/dist/memory/api.js +55 -2
  71. package/dist/memory/event-store.d.ts +0 -1
  72. package/dist/memory/event-store.js +0 -15
  73. package/dist/memory/finding-store.d.ts +0 -1
  74. package/dist/memory/finding-store.js +0 -12
  75. package/dist/memory/scope-backfill.d.ts +0 -3
  76. package/dist/memory/scope-backfill.js +0 -74
  77. package/dist/memory/scope-store.d.ts +0 -1
  78. package/dist/memory/scope-store.js +0 -4
  79. package/dist/memory/truth-store.d.ts +0 -3
  80. package/dist/memory/truth-store.js +0 -22
  81. package/dist/memory/types.d.ts +0 -1
  82. package/dist/memory/types.js +0 -13
  83. package/dist/memory-store.d.ts +0 -16
  84. package/dist/memory-store.js +0 -51
  85. package/dist/model-runs/tool-trace-store.js +9 -5
  86. package/dist/model-runs/types.d.ts +3 -0
  87. package/dist/ollama-client.d.ts +0 -9
  88. package/dist/ollama-client.js +0 -125
  89. package/dist/outcome-tracker.d.ts +0 -14
  90. package/dist/outcome-tracker.js +0 -44
  91. package/dist/progress-indicator.d.ts +0 -4
  92. package/dist/progress-indicator.js +0 -7
  93. package/dist/provenance/source-ref.d.ts +0 -9
  94. package/dist/provenance/source-ref.js +0 -145
  95. package/dist/query-intent.d.ts +0 -4
  96. package/dist/query-intent.js +0 -30
  97. package/dist/relevance-scorer.d.ts +0 -9
  98. package/dist/relevance-scorer.js +0 -81
  99. package/dist/search/feedback-store.d.ts +0 -1
  100. package/dist/search/feedback-store.js +0 -4
  101. package/dist/search/ranker-rescore.d.ts +0 -3
  102. package/dist/search/ranker-rescore.js +0 -27
  103. package/dist/search/ranker-trainer.d.ts +0 -8
  104. package/dist/search/ranker-trainer.js +0 -376
  105. package/dist/tier-validator.d.ts +0 -12
  106. package/dist/tier-validator.js +0 -56
  107. package/package.json +1 -10
  108. package/dist/cases/case-links.d.ts +0 -116
  109. package/dist/cases/case-links.js +0 -794
  110. package/dist/cases/composition-overrides.d.ts +0 -90
  111. package/dist/cases/composition-overrides.js +0 -724
  112. package/dist/cases/corrections.d.ts +0 -156
  113. package/dist/cases/corrections.js +0 -1045
  114. package/dist/cases/freshness.d.ts +0 -57
  115. package/dist/cases/freshness.js +0 -283
  116. package/dist/cases/live-state.d.ts +0 -48
  117. package/dist/cases/live-state.js +0 -256
  118. package/dist/cases/membership-explain.d.ts +0 -56
  119. package/dist/cases/membership-explain.js +0 -140
  120. package/dist/cases/membership-matcher.d.ts +0 -23
  121. package/dist/cases/membership-matcher.js +0 -193
  122. package/dist/cases/merge-split.d.ts +0 -61
  123. package/dist/cases/merge-split.js +0 -368
  124. package/dist/cases/role-inference.d.ts +0 -10
  125. package/dist/cases/role-inference.js +0 -85
  126. package/dist/cases/sqlite-transaction.d.ts +0 -10
  127. package/dist/cases/sqlite-transaction.js +0 -62
  128. package/dist/cases/target-ref.d.ts +0 -25
  129. package/dist/cases/target-ref.js +0 -22
  130. package/dist/cases/tombstone-sweeper.d.ts +0 -13
  131. package/dist/cases/tombstone-sweeper.js +0 -128
  132. package/dist/entities/entity-impact.d.ts +0 -41
  133. package/dist/entities/entity-impact.js +0 -140
  134. package/dist/entities/exact-merge-backfill.d.ts +0 -11
  135. package/dist/entities/exact-merge-backfill.js +0 -161
  136. package/dist/entities/lineage-backfill.d.ts +0 -12
  137. package/dist/entities/lineage-backfill.js +0 -101
  138. package/dist/memory-inject.d.ts +0 -24
  139. package/dist/memory-inject.js +0 -116
@@ -1,167 +1,3 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.queryProvenanceForMemory = queryProvenanceForMemory;
4
- const db_manager_js_1 = require("../db-manager.js");
5
- const source_locator_js_1 = require("./source-locator.js");
6
- function parseSource(trustContext) {
7
- if (typeof trustContext !== 'string' || trustContext.length === 0) {
8
- return { package: 'mama-core', source_type: 'db' };
9
- }
10
- try {
11
- const parsed = JSON.parse(trustContext);
12
- if (parsed?.source && typeof parsed.source === 'object') {
13
- return parsed.source;
14
- }
15
- }
16
- catch {
17
- // ignore malformed trust_context
18
- }
19
- return { package: 'mama-core', source_type: 'db' };
20
- }
21
- function mapMemoryRecord(row, scopes) {
22
- return {
23
- id: row.id,
24
- topic: row.topic,
25
- kind: (row.kind ?? 'decision'),
26
- summary: row.summary ?? row.decision,
27
- details: row.reasoning ?? row.decision,
28
- confidence: row.confidence ?? 0.5,
29
- status: (row.status ?? 'active'),
30
- scopes,
31
- source: parseSource(row.trust_context),
32
- created_at: row.created_at,
33
- updated_at: row.updated_at ?? row.created_at,
34
- event_date: row.event_date,
35
- };
36
- }
37
- function loadScopes(memoryId) {
38
- const adapter = (0, db_manager_js_1.getAdapter)();
39
- const rows = adapter
40
- .prepare(`
41
- SELECT msb.memory_id, ms.kind, ms.external_id
42
- FROM memory_scope_bindings msb
43
- JOIN memory_scopes ms ON ms.id = msb.scope_id
44
- WHERE msb.memory_id = ?
45
- ORDER BY msb.is_primary DESC
46
- `)
47
- .all(memoryId);
48
- return rows.map((row) => ({
49
- kind: row.kind,
50
- id: row.external_id,
51
- }));
52
- }
53
- function loadObservations(memoryId) {
54
- const adapter = (0, db_manager_js_1.getAdapter)();
55
- const rows = adapter
56
- .prepare(`
57
- SELECT
58
- o.id,
59
- o.observation_type,
60
- o.entity_kind_hint,
61
- o.surface_form,
62
- o.normalized_form,
63
- o.lang,
64
- o.script,
65
- o.context_summary,
66
- o.scope_kind,
67
- o.scope_id,
68
- o.extractor_version,
69
- o.embedding_model_version,
70
- o.source_connector,
71
- o.source_locator,
72
- o.source_raw_record_id,
73
- o.created_at
74
- FROM decision_entity_sources des
75
- JOIN entity_observations o ON o.id = des.entity_observation_id
76
- WHERE des.decision_id = ?
77
- ORDER BY des.created_at ASC, o.created_at ASC
78
- `)
79
- .all(memoryId);
80
- return rows.map((row) => ({
81
- id: row.id,
82
- observation_type: row.observation_type,
83
- entity_kind_hint: row.entity_kind_hint,
84
- surface_form: row.surface_form,
85
- normalized_form: row.normalized_form,
86
- lang: row.lang,
87
- script: row.script,
88
- context_summary: row.context_summary,
89
- scope_kind: row.scope_kind,
90
- scope_id: row.scope_id,
91
- extractor_version: row.extractor_version,
92
- embedding_model_version: row.embedding_model_version,
93
- source_connector: row.source_connector,
94
- source_locator: row.source_locator,
95
- source_locator_kind: (0, source_locator_js_1.detectSourceLocatorKind)(row.source_locator),
96
- source_raw_record_id: row.source_raw_record_id,
97
- created_at: row.created_at,
98
- }));
99
- }
100
- function loadProvenanceAudit(memoryId) {
101
- const adapter = (0, db_manager_js_1.getAdapter)();
102
- const row = adapter
103
- .prepare(`
104
- SELECT event_type, reason, created_at
105
- FROM memory_events
106
- WHERE memory_id = ?
107
- AND event_type IN ('provenance.empty_batch', 'provenance.link_write_failed')
108
- ORDER BY created_at DESC
109
- LIMIT 1
110
- `)
111
- .get(memoryId);
112
- if (!row) {
113
- return null;
114
- }
115
- return {
116
- event_type: row.event_type,
117
- reason: row.reason,
118
- created_at: row.created_at,
119
- };
120
- }
121
- async function queryProvenanceForMemory(memoryId) {
122
- await (0, db_manager_js_1.initDB)();
123
- const adapter = (0, db_manager_js_1.getAdapter)();
124
- const row = adapter
125
- .prepare(`
126
- SELECT
127
- id,
128
- topic,
129
- decision,
130
- reasoning,
131
- confidence,
132
- created_at,
133
- updated_at,
134
- trust_context,
135
- kind,
136
- status,
137
- summary,
138
- event_date
139
- FROM decisions
140
- WHERE id = ?
141
- `)
142
- .get(memoryId);
143
- if (!row) {
144
- throw new Error(`Decision not found: ${memoryId}`);
145
- }
146
- const scopes = loadScopes(memoryId);
147
- const memory = mapMemoryRecord(row, scopes);
148
- const observations = loadObservations(memoryId);
149
- const audit = loadProvenanceAudit(memoryId);
150
- let status = 'legacy';
151
- if (observations.length > 0) {
152
- status = 'resolved';
153
- }
154
- else if (audit?.event_type === 'provenance.link_write_failed') {
155
- status = 'dropped';
156
- }
157
- else if (audit?.event_type === 'provenance.empty_batch') {
158
- status = 'manual';
159
- }
160
- return {
161
- status,
162
- memory,
163
- observations,
164
- audit,
165
- };
166
- }
167
3
  //# sourceMappingURL=provenance-query.js.map
@@ -1,15 +1,8 @@
1
- import type { EntityMergeAction, EntityObservation, EntityResolutionCandidate } from './types.js';
1
+ import type { EntityMergeAction, EntityResolutionCandidate } from './types.js';
2
2
  export interface ResolutionDecision {
3
3
  candidate: EntityResolutionCandidate;
4
4
  decision: 'auto_merge' | 'review';
5
5
  reason: string;
6
6
  actions: EntityMergeAction[];
7
7
  }
8
- export declare function shouldAutoMerge(result: ResolutionDecision): boolean;
9
- export declare function buildReviewReason(result: ResolutionDecision): string;
10
- export declare function evaluateResolutionCandidate(input: {
11
- candidate: EntityResolutionCandidate;
12
- left: EntityObservation;
13
- right: EntityObservation;
14
- }): ResolutionDecision;
15
8
  //# sourceMappingURL=resolution-engine.d.ts.map
@@ -1,69 +1,3 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.shouldAutoMerge = shouldAutoMerge;
4
- exports.buildReviewReason = buildReviewReason;
5
- exports.evaluateResolutionCandidate = evaluateResolutionCandidate;
6
- const errors_js_1 = require("./errors.js");
7
- function isCrossLanguage(left, right) {
8
- return Boolean(left.lang && right.lang && left.lang !== right.lang);
9
- }
10
- function shouldAutoMerge(result) {
11
- return result.decision === 'auto_merge';
12
- }
13
- function buildReviewReason(result) {
14
- return result.reason;
15
- }
16
- function evaluateResolutionCandidate(input) {
17
- const { candidate, left, right } = input;
18
- if (left.entity_kind_hint &&
19
- right.entity_kind_hint &&
20
- left.entity_kind_hint !== right.entity_kind_hint) {
21
- throw new errors_js_1.OntologyViolationError({
22
- left_entity_kind: left.entity_kind_hint,
23
- right_entity_kind: right.entity_kind_hint,
24
- candidate_id: candidate.id,
25
- });
26
- }
27
- const sameNormalized = left.normalized_form === right.normalized_form;
28
- const exactStructural = candidate.score_structural >= 1 && sameNormalized;
29
- const crossLanguage = isCrossLanguage(left, right);
30
- if (exactStructural && !crossLanguage) {
31
- return {
32
- candidate,
33
- decision: 'auto_merge',
34
- reason: 'Exact structural match with no cross-language ambiguity.',
35
- actions: [
36
- {
37
- id: `merge_${candidate.id}`,
38
- action_type: 'merge',
39
- source_entity_id: candidate.left_ref,
40
- target_entity_id: candidate.right_ref,
41
- candidate_id: candidate.id,
42
- actor_type: 'system',
43
- actor_id: 'resolution-engine',
44
- reason: 'Exact structural match with no cross-language ambiguity.',
45
- evidence_json: JSON.stringify({
46
- score_structural: candidate.score_structural,
47
- normalized_form: left.normalized_form,
48
- }),
49
- created_at: Date.now(),
50
- },
51
- ],
52
- };
53
- }
54
- if (crossLanguage && candidate.score_embedding > 0) {
55
- return {
56
- candidate,
57
- decision: 'review',
58
- reason: 'High-similarity cross-language candidate requires human review.',
59
- actions: [],
60
- };
61
- }
62
- return {
63
- candidate,
64
- decision: 'review',
65
- reason: 'Candidate requires manual review before merge.',
66
- actions: [],
67
- };
68
- }
69
3
  //# sourceMappingURL=resolution-engine.js.map
@@ -1,4 +1,3 @@
1
- import { type EntityStoreAdapter } from './store.js';
2
1
  export interface RollbackPreviewInput {
3
2
  entityId: string;
4
3
  mergeActionId?: string;
@@ -33,7 +32,4 @@ export interface RollbackPreviewResult {
33
32
  changed_memories: RollbackPreviewMemoryChange[];
34
33
  metric_movement: RollbackPreviewMetricMovement[];
35
34
  }
36
- export declare function previewEntityRollback(input: RollbackPreviewInput, options?: {
37
- adapter?: EntityStoreAdapter;
38
- }): Promise<RollbackPreviewResult>;
39
35
  //# sourceMappingURL=rollback-preview.d.ts.map
@@ -1,235 +1,3 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.previewEntityRollback = previewEntityRollback;
4
- const db_manager_js_1 = require("../db-manager.js");
5
- const projection_js_1 = require("./projection.js");
6
- const store_js_1 = require("./store.js");
7
- const lineage_store_js_1 = require("./lineage-store.js");
8
- function unavailableResult(entityId, mergeActionId, historyIncomplete) {
9
- return {
10
- entity_id: entityId,
11
- merge_action_id: mergeActionId,
12
- preview_unavailable: true,
13
- history_incomplete: historyIncomplete,
14
- truncated: false,
15
- changed_entities: [],
16
- changed_memories: [],
17
- metric_movement: [],
18
- };
19
- }
20
- function uniqueStrings(values) {
21
- return Array.from(new Set(values.filter((value) => Boolean(value))));
22
- }
23
- function getLatestTimeline(adapter, entityId) {
24
- const row = adapter
25
- .prepare(`
26
- SELECT *
27
- FROM entity_timeline_events
28
- WHERE entity_id = ?
29
- ORDER BY COALESCE(observed_at, created_at) DESC
30
- LIMIT 1
31
- `)
32
- .get(entityId);
33
- if (!row) {
34
- return null;
35
- }
36
- return {
37
- id: String(row.id),
38
- entity_id: String(row.entity_id),
39
- event_type: row.event_type,
40
- role: typeof row.role === 'string' ? row.role : null,
41
- valid_from: typeof row.valid_from === 'number' ? row.valid_from : null,
42
- valid_to: typeof row.valid_to === 'number' ? row.valid_to : null,
43
- observed_at: typeof row.observed_at === 'number' ? row.observed_at : null,
44
- source_ref: typeof row.source_ref === 'string' ? row.source_ref : null,
45
- summary: String(row.summary ?? ''),
46
- details: typeof row.details === 'string' ? row.details : null,
47
- created_at: Number(row.created_at),
48
- };
49
- }
50
- const DEFAULT_MAX_AFFECTED_ROWS = 50;
51
- function normalizeMaxAffectedRows(input) {
52
- return Math.max(1, input.maxAffectedRows ?? DEFAULT_MAX_AFFECTED_ROWS);
53
- }
54
- function projectLabel(adapter, node) {
55
- const summary = (0, projection_js_1.projectEntityToRecallSummary)(node, (0, store_js_1.listEntityAliases)(node.id, adapter), getLatestTimeline(adapter, node.id), { nodeLookup: { [node.id]: node } });
56
- return summary.summary;
57
- }
58
- function loadMergeAction(adapter, entityId, mergeActionId) {
59
- const sql = mergeActionId
60
- ? `
61
- SELECT id, source_entity_id, target_entity_id, created_at
62
- FROM entity_merge_actions
63
- WHERE id = ?
64
- AND (source_entity_id = ? OR target_entity_id = ?)
65
- LIMIT 1
66
- `
67
- : `
68
- SELECT id, source_entity_id, target_entity_id, created_at
69
- FROM entity_merge_actions
70
- WHERE target_entity_id = ?
71
- ORDER BY created_at DESC
72
- LIMIT 1
73
- `;
74
- const row = (mergeActionId
75
- ? adapter.prepare(sql).get(mergeActionId, entityId, entityId)
76
- : adapter.prepare(sql).get(entityId));
77
- return row ?? null;
78
- }
79
- function resolveMergePreviewRows(input) {
80
- let removedRows = input.targetActive.filter((row) => row.source_entity_id === input.sourceEntityId &&
81
- (!input.mergeActionId || row.review_action_id === input.mergeActionId));
82
- const removedObservationIds = new Set(removedRows.map((row) => row.entity_observation_id));
83
- const restoredRows = input.sourceHistory.filter((row) => row.status === 'superseded' &&
84
- (!input.mergeActionId ||
85
- row.review_action_id === input.mergeActionId ||
86
- removedObservationIds.has(row.entity_observation_id)));
87
- if (removedRows.length === 0 && restoredRows.length > 0) {
88
- const restorableObservationIds = new Set(restoredRows.map((row) => row.entity_observation_id));
89
- removedRows = input.targetActive.filter((row) => restorableObservationIds.has(row.entity_observation_id) &&
90
- (!input.mergeActionId || row.review_action_id === input.mergeActionId));
91
- }
92
- return { restoredRows, removedRows };
93
- }
94
- function loadChangedMemories(adapter, observationIds) {
95
- if (observationIds.length === 0) {
96
- return [];
97
- }
98
- const placeholders = observationIds.map(() => '?').join(', ');
99
- const rows = adapter
100
- .prepare(`
101
- SELECT DISTINCT d.id, d.topic, d.summary, d.created_at
102
- FROM decision_entity_sources des
103
- JOIN decisions d ON d.id = des.decision_id
104
- WHERE des.entity_observation_id IN (${placeholders})
105
- ORDER BY d.created_at DESC
106
- `)
107
- .all(...observationIds);
108
- return rows.map((row) => ({
109
- id: row.id,
110
- topic: row.topic,
111
- summary: row.summary ?? row.topic,
112
- created_at: row.created_at,
113
- }));
114
- }
115
- function buildMetricMovement(sourceLabel) {
116
- return [
117
- {
118
- metric: 'false_merge_rate',
119
- direction: 'decrease',
120
- reason: `Splitting ${sourceLabel} back out would likely reduce false merge pressure.`,
121
- },
122
- {
123
- metric: 'projection_fragmentation_rate',
124
- direction: 'increase',
125
- reason: `Reactivating a second canonical entity likely increases projection fragmentation.`,
126
- },
127
- ];
128
- }
129
- async function previewMergeRollback(adapter, input, mergeAction) {
130
- const sourceNode = (0, store_js_1.getEntityNode)(mergeAction.source_entity_id, adapter);
131
- const targetNode = (0, store_js_1.getEntityNode)(mergeAction.target_entity_id, adapter);
132
- if (!sourceNode || !targetNode) {
133
- return unavailableResult(input.entityId, mergeAction.id, true);
134
- }
135
- const sourceHistory = await (0, lineage_store_js_1.listEntityLineageHistory)(sourceNode.id, adapter);
136
- const targetActive = await (0, lineage_store_js_1.listActiveEntityLineage)(targetNode.id, adapter);
137
- const { restoredRows, removedRows } = resolveMergePreviewRows({
138
- sourceHistory,
139
- targetActive,
140
- sourceEntityId: sourceNode.id,
141
- mergeActionId: input.mergeActionId,
142
- });
143
- if (restoredRows.length === 0 || removedRows.length === 0) {
144
- return unavailableResult(input.entityId, mergeAction.id, true);
145
- }
146
- const affectedObservationIds = uniqueStrings([
147
- ...restoredRows.map((row) => row.entity_observation_id),
148
- ...removedRows.map((row) => row.entity_observation_id),
149
- ]);
150
- const allChangedMemories = loadChangedMemories(adapter, affectedObservationIds);
151
- const maxAffectedRows = normalizeMaxAffectedRows(input);
152
- const truncated = allChangedMemories.length > maxAffectedRows;
153
- return {
154
- entity_id: input.entityId,
155
- merge_action_id: mergeAction.id,
156
- preview_unavailable: false,
157
- history_incomplete: false,
158
- truncated,
159
- changed_entities: [
160
- {
161
- entity_id: sourceNode.id,
162
- label: sourceNode.preferred_label,
163
- status_after: 'active',
164
- active_lineage_after: restoredRows.length,
165
- summary: projectLabel(adapter, { ...sourceNode, status: 'active', merged_into: null }),
166
- },
167
- {
168
- entity_id: targetNode.id,
169
- label: targetNode.preferred_label,
170
- status_after: 'active',
171
- active_lineage_after: Math.max(0, targetActive.length - removedRows.length),
172
- summary: projectLabel(adapter, targetNode),
173
- },
174
- ],
175
- changed_memories: allChangedMemories.slice(0, maxAffectedRows),
176
- metric_movement: buildMetricMovement(sourceNode.preferred_label),
177
- };
178
- }
179
- async function previewObservationDetach(adapter, input) {
180
- const activeTarget = await (0, lineage_store_js_1.listActiveEntityLineage)(input.entityId, adapter);
181
- const targetNode = (0, store_js_1.getEntityNode)(input.entityId, adapter);
182
- if (!targetNode) {
183
- return unavailableResult(input.entityId, null, false);
184
- }
185
- const row = activeTarget.find((candidate) => candidate.entity_observation_id === input.observationId);
186
- if (!row) {
187
- return unavailableResult(input.entityId, null, false);
188
- }
189
- const changedMemories = loadChangedMemories(adapter, [row.entity_observation_id]);
190
- const maxAffectedRows = normalizeMaxAffectedRows(input);
191
- return {
192
- entity_id: input.entityId,
193
- merge_action_id: null,
194
- preview_unavailable: false,
195
- history_incomplete: false,
196
- truncated: changedMemories.length > maxAffectedRows,
197
- changed_entities: [
198
- {
199
- entity_id: targetNode.id,
200
- label: targetNode.preferred_label,
201
- status_after: 'active',
202
- active_lineage_after: Math.max(0, activeTarget.length - 1),
203
- summary: projectLabel(adapter, targetNode),
204
- },
205
- ],
206
- changed_memories: changedMemories.slice(0, maxAffectedRows),
207
- metric_movement: [
208
- {
209
- metric: 'false_merge_rate',
210
- direction: 'decrease',
211
- reason: 'Removing one supporting observation may reduce merge confidence for the current entity.',
212
- },
213
- {
214
- metric: 'projection_fragmentation_rate',
215
- direction: 'increase',
216
- reason: 'Detaching one observation may increase fragmentation if it needs a separate entity later.',
217
- },
218
- ],
219
- };
220
- }
221
- async function previewEntityRollback(input, options = {}) {
222
- if (!options.adapter) {
223
- await (0, db_manager_js_1.initDB)();
224
- }
225
- const adapter = options.adapter ?? (0, db_manager_js_1.getAdapter)();
226
- if (input.observationId) {
227
- return previewObservationDetach(adapter, input);
228
- }
229
- const mergeAction = loadMergeAction(adapter, input.entityId, input.mergeActionId);
230
- if (!mergeAction) {
231
- return unavailableResult(input.entityId, input.mergeActionId ?? null, false);
232
- }
233
- return previewMergeRollback(adapter, input, mergeAction);
234
- }
235
3
  //# sourceMappingURL=rollback-preview.js.map
@@ -1,4 +1,4 @@
1
- import { type EntityAlias, type EntityNode, type EntityObservation, type EntityTimelineEvent } from './types.js';
1
+ import { type EntityAlias, type EntityNode, type EntityObservation } from './types.js';
2
2
  export interface EntityStoreAdapter {
3
3
  prepare(sql: string): {
4
4
  run(...params: unknown[]): {
@@ -18,13 +18,6 @@ type CreateEntityNodeInput = Omit<EntityNode, 'created_at' | 'updated_at'>;
18
18
  type AttachEntityAliasInput = Omit<EntityAlias, 'created_at'>;
19
19
  type ObservationContextKeyColumn = (typeof OBSERVATION_CONTEXT_KEY_COLUMNS)[number];
20
20
  type UpsertEntityObservationInput = Omit<EntityObservation, 'created_at'> & Partial<Record<ObservationContextKeyColumn, string | null>>;
21
- type AppendEntityTimelineEventInput = {
22
- event: Omit<EntityTimelineEvent, 'id' | 'created_at'> & {
23
- id?: string;
24
- created_at?: number;
25
- };
26
- adapter?: EntityStoreAdapter;
27
- };
28
21
  export interface UpsertEntityObservationResult {
29
22
  id: string;
30
23
  created: boolean;
@@ -33,12 +26,10 @@ export declare function clearEntityTableColumnCache(adapter: EntityStoreAdapter)
33
26
  export declare function parseObservationRow(row: Record<string, unknown>): EntityObservation;
34
27
  export declare function createEntityNode(input: CreateEntityNodeInput): Promise<EntityNode>;
35
28
  export declare function getEntityNode(id: string, adapter?: EntityStoreAdapter): EntityNode | null;
36
- export declare function listEntityNodes(): EntityNode[];
37
29
  export declare function attachEntityAlias(input: AttachEntityAliasInput): Promise<EntityAlias>;
38
30
  export declare function listEntityAliases(entityId: string, adapter?: EntityStoreAdapter): EntityAlias[];
39
31
  export declare function upsertEntityObservation(input: UpsertEntityObservationInput): Promise<EntityObservation>;
40
32
  export declare function upsertEntityObservations(inputs: UpsertEntityObservationInput[]): Promise<UpsertEntityObservationResult[]>;
41
- export declare function appendEntityTimelineEvent(input: AppendEntityTimelineEventInput): Promise<EntityTimelineEvent>;
42
33
  /**
43
34
  * Walks the `entity_nodes.merged_into` chain from the given id and returns the
44
35
  * terminal (unmerged) entity id. Detects cycles and caps depth. Read-only.
@@ -5,12 +5,10 @@ exports.clearEntityTableColumnCache = clearEntityTableColumnCache;
5
5
  exports.parseObservationRow = parseObservationRow;
6
6
  exports.createEntityNode = createEntityNode;
7
7
  exports.getEntityNode = getEntityNode;
8
- exports.listEntityNodes = listEntityNodes;
9
8
  exports.attachEntityAlias = attachEntityAlias;
10
9
  exports.listEntityAliases = listEntityAliases;
11
10
  exports.upsertEntityObservation = upsertEntityObservation;
12
11
  exports.upsertEntityObservations = upsertEntityObservations;
13
- exports.appendEntityTimelineEvent = appendEntityTimelineEvent;
14
12
  exports.resolveCanonicalEntityId = resolveCanonicalEntityId;
15
13
  exports.mergeEntityNodes = mergeEntityNodes;
16
14
  const node_crypto_1 = require("node:crypto");
@@ -236,23 +234,6 @@ function getEntityNode(id, adapter = (0, db_manager_js_1.getAdapter)()) {
236
234
  updated_at: Number(row.updated_at),
237
235
  };
238
236
  }
239
- function listEntityNodes() {
240
- const adapter = (0, db_manager_js_1.getAdapter)();
241
- const rows = adapter
242
- .prepare('SELECT * FROM entity_nodes ORDER BY created_at DESC')
243
- .all();
244
- return rows.map((row) => ({
245
- id: String(row.id),
246
- kind: row.kind,
247
- preferred_label: String(row.preferred_label),
248
- status: row.status,
249
- scope_kind: typeof row.scope_kind === 'string' ? row.scope_kind : null,
250
- scope_id: typeof row.scope_id === 'string' ? row.scope_id : null,
251
- merged_into: typeof row.merged_into === 'string' ? row.merged_into : null,
252
- created_at: Number(row.created_at),
253
- updated_at: Number(row.updated_at),
254
- }));
255
- }
256
237
  async function attachEntityAlias(input) {
257
238
  await (0, db_manager_js_1.initDB)();
258
239
  const adapter = (0, db_manager_js_1.getAdapter)();
@@ -461,36 +442,6 @@ async function upsertEntityObservations(inputs) {
461
442
  }
462
443
  return observations;
463
444
  }
464
- async function appendEntityTimelineEvent(input) {
465
- if (!input.adapter) {
466
- await (0, db_manager_js_1.initDB)();
467
- }
468
- const adapter = input.adapter ?? (0, db_manager_js_1.getAdapter)();
469
- const eventId = input.event.id ?? `et_${(0, node_crypto_1.randomUUID)()}`;
470
- const createdAt = input.event.created_at ?? now();
471
- adapter
472
- .prepare(`
473
- INSERT INTO entity_timeline_events (
474
- id, entity_id, event_type, role, valid_from, valid_to, observed_at,
475
- source_ref, summary, details, created_at
476
- )
477
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
478
- `)
479
- .run(eventId, input.event.entity_id, input.event.event_type, input.event.role ?? null, input.event.valid_from ?? null, input.event.valid_to ?? null, input.event.observed_at ?? null, input.event.source_ref ?? null, input.event.summary, input.event.details ?? null, createdAt);
480
- return {
481
- id: eventId,
482
- entity_id: input.event.entity_id,
483
- event_type: input.event.event_type,
484
- role: input.event.role ?? null,
485
- valid_from: input.event.valid_from ?? null,
486
- valid_to: input.event.valid_to ?? null,
487
- observed_at: input.event.observed_at ?? null,
488
- source_ref: input.event.source_ref ?? null,
489
- summary: input.event.summary,
490
- details: input.event.details ?? null,
491
- created_at: createdAt,
492
- };
493
- }
494
445
  /**
495
446
  * Walks the `entity_nodes.merged_into` chain from the given id and returns the
496
447
  * terminal (unmerged) entity id. Detects cycles and caps depth. Read-only.