@jungjaehoon/mama-core 1.4.2 → 1.6.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 (181) hide show
  1. package/README.md +48 -10
  2. package/db/migrations/026-create-canonical-entity-tables.sql +99 -0
  3. package/db/migrations/027-create-entity-review-support.sql +44 -0
  4. package/db/migrations/028-create-entity-audit-tables.sql +45 -0
  5. package/db/migrations/029-extend-entity-observations-observation-type.sql +60 -0
  6. package/db/migrations/030-case-first-memory-substrate.sql +901 -0
  7. package/db/migrations/031-wiki-page-index-provenance-columns.sql +2 -0
  8. package/db/migrations/032-add-memory-provenance-columns.sql +21 -0
  9. package/db/migrations/033-create-model-runs-and-tool-traces.sql +53 -0
  10. package/db/migrations/034-add-connector-event-scope-columns.sql +14 -0
  11. package/db/migrations/035-create-twin-edges.sql +63 -0
  12. package/db/migrations/036-create-agent-situation-packets.sql +61 -0
  13. package/dist/agent-graph/alias-write.d.ts +3 -0
  14. package/dist/agent-graph/alias-write.js +231 -0
  15. package/dist/agent-graph/entity-resolve.d.ts +3 -0
  16. package/dist/agent-graph/entity-resolve.js +275 -0
  17. package/dist/agent-graph/errors.d.ts +4 -0
  18. package/dist/agent-graph/errors.js +11 -0
  19. package/dist/agent-graph/graph-query.d.ts +5 -0
  20. package/dist/agent-graph/graph-query.js +359 -0
  21. package/dist/agent-graph/index.d.ts +6 -0
  22. package/dist/agent-graph/index.js +22 -0
  23. package/dist/agent-graph/types.d.ts +162 -0
  24. package/dist/agent-graph/types.js +3 -0
  25. package/dist/agent-situation/builder.d.ts +8 -0
  26. package/dist/agent-situation/builder.js +239 -0
  27. package/dist/agent-situation/cache-key.d.ts +4 -0
  28. package/dist/agent-situation/cache-key.js +64 -0
  29. package/dist/agent-situation/index.d.ts +7 -0
  30. package/dist/agent-situation/index.js +28 -0
  31. package/dist/agent-situation/packet-store.d.ts +27 -0
  32. package/dist/agent-situation/packet-store.js +228 -0
  33. package/dist/agent-situation/ranking-policy.d.ts +18 -0
  34. package/dist/agent-situation/ranking-policy.js +75 -0
  35. package/dist/agent-situation/source-readers.d.ts +52 -0
  36. package/dist/agent-situation/source-readers.js +300 -0
  37. package/dist/agent-situation/types.d.ts +195 -0
  38. package/dist/agent-situation/types.js +3 -0
  39. package/dist/canonicalize.d.ts +38 -0
  40. package/dist/canonicalize.js +106 -0
  41. package/dist/cases/case-links.d.ts +116 -0
  42. package/dist/cases/case-links.js +794 -0
  43. package/dist/cases/composition-overrides.d.ts +90 -0
  44. package/dist/cases/composition-overrides.js +724 -0
  45. package/dist/cases/corrections.d.ts +156 -0
  46. package/dist/cases/corrections.js +1045 -0
  47. package/dist/cases/freshness.d.ts +57 -0
  48. package/dist/cases/freshness.js +283 -0
  49. package/dist/cases/live-state.d.ts +48 -0
  50. package/dist/cases/live-state.js +256 -0
  51. package/dist/cases/membership-explain.d.ts +56 -0
  52. package/dist/cases/membership-explain.js +140 -0
  53. package/dist/cases/membership-matcher.d.ts +23 -0
  54. package/dist/cases/membership-matcher.js +193 -0
  55. package/dist/cases/merge-split.d.ts +61 -0
  56. package/dist/cases/merge-split.js +368 -0
  57. package/dist/cases/role-inference.d.ts +10 -0
  58. package/dist/cases/role-inference.js +85 -0
  59. package/dist/cases/search-rollup.d.ts +27 -0
  60. package/dist/cases/search-rollup.js +309 -0
  61. package/dist/cases/sqlite-transaction.d.ts +10 -0
  62. package/dist/cases/sqlite-transaction.js +62 -0
  63. package/dist/cases/store.d.ts +74 -0
  64. package/dist/cases/store.js +816 -0
  65. package/dist/cases/target-ref.d.ts +25 -0
  66. package/dist/cases/target-ref.js +22 -0
  67. package/dist/cases/timeline-range.d.ts +6 -0
  68. package/dist/cases/timeline-range.js +322 -0
  69. package/dist/cases/tombstone-sweeper.d.ts +13 -0
  70. package/dist/cases/tombstone-sweeper.js +128 -0
  71. package/dist/cases/types.d.ts +244 -0
  72. package/dist/cases/types.js +47 -0
  73. package/dist/cases/wiki-page-index.d.ts +50 -0
  74. package/dist/cases/wiki-page-index.js +350 -0
  75. package/dist/connectors/event-index.d.ts +45 -0
  76. package/dist/connectors/event-index.js +381 -0
  77. package/dist/connectors/raw-query.d.ts +18 -0
  78. package/dist/connectors/raw-query.js +305 -0
  79. package/dist/connectors/types.d.ts +109 -0
  80. package/dist/connectors/types.js +3 -0
  81. package/dist/db-adapter/node-sqlite-adapter.d.ts +6 -0
  82. package/dist/db-adapter/node-sqlite-adapter.js +131 -0
  83. package/dist/db-manager.d.ts +12 -1
  84. package/dist/db-manager.js +60 -5
  85. package/dist/decision-formatter.d.ts +2 -0
  86. package/dist/decision-formatter.js +11 -8
  87. package/dist/edges/ref-validation.d.ts +8 -0
  88. package/dist/edges/ref-validation.js +262 -0
  89. package/dist/edges/store.d.ts +10 -0
  90. package/dist/edges/store.js +343 -0
  91. package/dist/edges/types.d.ts +86 -0
  92. package/dist/edges/types.js +18 -0
  93. package/dist/embedding-server/mobile/daemon.d.ts +1 -0
  94. package/dist/embedding-server/mobile/daemon.js +11 -1
  95. package/dist/embeddings.js +13 -0
  96. package/dist/entities/audit-metrics.d.ts +73 -0
  97. package/dist/entities/audit-metrics.js +128 -0
  98. package/dist/entities/candidate-generator.d.ts +9 -0
  99. package/dist/entities/candidate-generator.js +436 -0
  100. package/dist/entities/entity-impact.d.ts +41 -0
  101. package/dist/entities/entity-impact.js +140 -0
  102. package/dist/entities/entity-linked-decision-counts.d.ts +2 -0
  103. package/dist/entities/entity-linked-decision-counts.js +29 -0
  104. package/dist/entities/entity-list.d.ts +23 -0
  105. package/dist/entities/entity-list.js +99 -0
  106. package/dist/entities/entity-orphan-list.d.ts +26 -0
  107. package/dist/entities/entity-orphan-list.js +91 -0
  108. package/dist/entities/entity-search.d.ts +21 -0
  109. package/dist/entities/entity-search.js +150 -0
  110. package/dist/entities/errors.d.ts +65 -0
  111. package/dist/entities/errors.js +124 -0
  112. package/dist/entities/exact-merge-backfill.d.ts +11 -0
  113. package/dist/entities/exact-merge-backfill.js +161 -0
  114. package/dist/entities/lineage-backfill.d.ts +12 -0
  115. package/dist/entities/lineage-backfill.js +101 -0
  116. package/dist/entities/lineage-store.d.ts +51 -0
  117. package/dist/entities/lineage-store.js +308 -0
  118. package/dist/entities/normalization.d.ts +14 -0
  119. package/dist/entities/normalization.js +63 -0
  120. package/dist/entities/policy-store.d.ts +17 -0
  121. package/dist/entities/policy-store.js +263 -0
  122. package/dist/entities/policy-types.d.ts +72 -0
  123. package/dist/entities/policy-types.js +59 -0
  124. package/dist/entities/projection.d.ts +8 -0
  125. package/dist/entities/projection.js +82 -0
  126. package/dist/entities/provenance-query.d.ts +33 -0
  127. package/dist/entities/provenance-query.js +167 -0
  128. package/dist/entities/read-identity.d.ts +31 -0
  129. package/dist/entities/read-identity.js +264 -0
  130. package/dist/entities/recall-bridge.d.ts +5 -0
  131. package/dist/entities/recall-bridge.js +171 -0
  132. package/dist/entities/resolution-engine.d.ts +15 -0
  133. package/dist/entities/resolution-engine.js +69 -0
  134. package/dist/entities/rollback-preview.d.ts +39 -0
  135. package/dist/entities/rollback-preview.js +235 -0
  136. package/dist/entities/source-locator.d.ts +3 -0
  137. package/dist/entities/source-locator.js +32 -0
  138. package/dist/entities/store.d.ts +75 -0
  139. package/dist/entities/store.js +465 -0
  140. package/dist/entities/types.d.ts +162 -0
  141. package/dist/entities/types.js +30 -0
  142. package/dist/index.d.ts +62 -3
  143. package/dist/index.js +116 -26
  144. package/dist/mama-api.d.ts +53 -35
  145. package/dist/mama-api.js +437 -78
  146. package/dist/memory/api.d.ts +26 -38
  147. package/dist/memory/api.js +772 -68
  148. package/dist/memory/event-store.d.ts +3 -0
  149. package/dist/memory/event-store.js +21 -2
  150. package/dist/memory/provenance-audit.d.ts +22 -0
  151. package/dist/memory/provenance-audit.js +112 -0
  152. package/dist/memory/provenance-query.d.ts +11 -0
  153. package/dist/memory/provenance-query.js +193 -0
  154. package/dist/memory/provenance.d.ts +29 -0
  155. package/dist/memory/provenance.js +136 -0
  156. package/dist/memory/scope-backfill.d.ts +17 -0
  157. package/dist/memory/scope-backfill.js +77 -0
  158. package/dist/memory/types.d.ts +97 -16
  159. package/dist/model-runs/store.d.ts +13 -0
  160. package/dist/model-runs/store.js +457 -0
  161. package/dist/model-runs/tool-trace-store.d.ts +4 -0
  162. package/dist/model-runs/tool-trace-store.js +114 -0
  163. package/dist/model-runs/types.d.ts +69 -0
  164. package/dist/model-runs/types.js +5 -0
  165. package/dist/runtime/trusted-provenance.d.ts +3 -0
  166. package/dist/runtime/trusted-provenance.js +6 -0
  167. package/dist/search/feedback-store.d.ts +59 -0
  168. package/dist/search/feedback-store.js +211 -0
  169. package/dist/search/question-type.d.ts +5 -0
  170. package/dist/search/question-type.js +41 -0
  171. package/dist/search/ranker-features.d.ts +23 -0
  172. package/dist/search/ranker-features.js +104 -0
  173. package/dist/search/ranker-rescore.d.ts +31 -0
  174. package/dist/search/ranker-rescore.js +226 -0
  175. package/dist/search/ranker-trainer.d.ts +94 -0
  176. package/dist/search/ranker-trainer.js +860 -0
  177. package/dist/search/search-quality.d.ts +36 -0
  178. package/dist/search/search-quality.js +29 -0
  179. package/dist/test-utils.d.ts +14 -0
  180. package/dist/test-utils.js +52 -0
  181. package/package.json +28 -3
@@ -0,0 +1,195 @@
1
+ import type { MemoryScopeRef } from '../memory/types.js';
2
+ import type { TwinRef } from '../edges/types.js';
3
+ export type SituationFocus = 'decisions' | 'risks' | 'open_questions' | 'cases' | 'raw';
4
+ export type SituationRefKind = TwinRef['kind'] | 'memory';
5
+ export interface SituationRef {
6
+ kind: SituationRefKind;
7
+ id: string;
8
+ }
9
+ export interface SituationProjectRef {
10
+ kind: 'project';
11
+ id: string;
12
+ }
13
+ export interface AgentSituationEffectiveFilters {
14
+ scopes: MemoryScopeRef[];
15
+ connectors: string[];
16
+ project_refs: SituationProjectRef[];
17
+ tenant_id: string;
18
+ as_of?: string | null;
19
+ }
20
+ export interface AgentSituationCacheKeyInput extends AgentSituationEffectiveFilters {
21
+ range_start_ms: number;
22
+ range_end_ms: number;
23
+ focus: SituationFocus[];
24
+ limit: number;
25
+ ranking_policy_version: string;
26
+ }
27
+ export interface AgentSituationCacheKeyResult {
28
+ cacheKey: string;
29
+ canonicalInput: AgentSituationCacheKeyInput;
30
+ canonicalJson: string;
31
+ filtersHash: string;
32
+ scopeHash: string;
33
+ }
34
+ export type SituationCaveatCode = 'connector_stale' | 'some_sources_unavailable' | 'low_confidence_visible_memory' | 'graph_api_unavailable_until_m6' | 'case_visibility_incomplete' | 'no_visible_sources';
35
+ export interface SituationSourceCoverage {
36
+ connector?: string;
37
+ channel_id?: string | null;
38
+ memory_scope?: MemoryScopeRef;
39
+ raw_count: number;
40
+ memory_count: number;
41
+ case_count: number;
42
+ edge_count: number;
43
+ last_seen: string | null;
44
+ stale: boolean;
45
+ }
46
+ export interface SituationBriefing {
47
+ decisions: string[];
48
+ facts: string[];
49
+ open_questions: string[];
50
+ risks: string[];
51
+ }
52
+ export interface SituationRankedItem {
53
+ ref: SituationRef;
54
+ kind: string;
55
+ score: number;
56
+ reasons: string[];
57
+ caveats: string[];
58
+ }
59
+ export interface SituationPendingHumanQuestion {
60
+ memory_id: string;
61
+ title: string;
62
+ summary: string;
63
+ }
64
+ export interface SituationEntityCluster {
65
+ label: string;
66
+ entity_refs: Array<{
67
+ kind: 'entity';
68
+ id: string;
69
+ }>;
70
+ source_refs: Array<{
71
+ kind: 'raw' | 'memory' | 'case';
72
+ id: string;
73
+ }>;
74
+ caveats: string[];
75
+ }
76
+ export interface SituationRecommendedTool {
77
+ tool: 'raw.search' | 'raw.searchAll' | 'raw.window' | 'memory.recall' | 'graph.neighborhood';
78
+ args: Record<string, unknown>;
79
+ reason: string;
80
+ expected_refs: SituationRef[];
81
+ }
82
+ export interface AgentSituationPacket {
83
+ packet_id: string;
84
+ scope: MemoryScopeRef[];
85
+ range_start: string;
86
+ range_end: string;
87
+ generated_at: string;
88
+ freshness: Record<string, unknown>;
89
+ source_coverage: SituationSourceCoverage[];
90
+ briefing: SituationBriefing;
91
+ ranked_items: SituationRankedItem[];
92
+ top_memory_refs: string[];
93
+ pending_human_questions: SituationPendingHumanQuestion[];
94
+ entity_clusters: SituationEntityCluster[];
95
+ recommended_next_tools: SituationRecommendedTool[];
96
+ ranking_policy_version: string;
97
+ ttl_seconds: number;
98
+ generated_from_slice_ids: string[];
99
+ caveats: string[];
100
+ cache: {
101
+ hit: boolean;
102
+ cache_key: string;
103
+ expires_at: string;
104
+ };
105
+ }
106
+ export interface AgentSituationInput {
107
+ scope: MemoryScopeRef[];
108
+ range_start_ms: number;
109
+ range_end_ms: number;
110
+ focus: SituationFocus[];
111
+ limit: number;
112
+ effective_filters: AgentSituationEffectiveFilters;
113
+ envelope_hash: string;
114
+ agent_id: string;
115
+ model_run_id: string;
116
+ ranking_policy_version?: string;
117
+ refresh?: boolean;
118
+ now_ms?: number;
119
+ }
120
+ export interface AgentSituationPacketRecord {
121
+ packet_id: string;
122
+ cache_key: string;
123
+ scope_json: string;
124
+ scope: MemoryScopeRef[];
125
+ scope_hash: string;
126
+ range_start_ms: number;
127
+ range_end_ms: number;
128
+ focus_json: string;
129
+ focus: SituationFocus[];
130
+ envelope_hash: string;
131
+ envelope_effective_filters_json: string;
132
+ envelope_effective_filters: AgentSituationEffectiveFilters;
133
+ envelope_effective_filters_hash: string;
134
+ ranking_policy_version: string;
135
+ generated_at: number;
136
+ expires_at: number;
137
+ ttl_seconds: number;
138
+ freshness_json: string;
139
+ freshness: Record<string, unknown>;
140
+ source_coverage_json: string;
141
+ source_coverage: SituationSourceCoverage[];
142
+ briefing_json: string;
143
+ briefing: SituationBriefing;
144
+ ranked_items_json: string;
145
+ ranked_items: SituationRankedItem[];
146
+ top_memory_refs_json: string;
147
+ top_memory_refs: string[];
148
+ pending_human_questions_json: string;
149
+ pending_human_questions: SituationPendingHumanQuestion[];
150
+ entity_clusters_json: string;
151
+ entity_clusters: SituationEntityCluster[];
152
+ recommended_next_tools_json: string;
153
+ recommended_next_tools: SituationRecommendedTool[];
154
+ generated_from_slice_ids_json: string;
155
+ generated_from_slice_ids: string[];
156
+ caveats_json: string;
157
+ caveats: string[];
158
+ agent_id: string;
159
+ model_run_id: string;
160
+ input_snapshot_ref: string;
161
+ source_refs_json: string;
162
+ source_refs: SituationRef[];
163
+ tenant_id: string;
164
+ project_id: string;
165
+ memory_scope_kind: MemoryScopeRef['kind'];
166
+ memory_scope_id: string;
167
+ created_at: number;
168
+ }
169
+ export interface AgentSituationLease {
170
+ cache_key: string;
171
+ ranking_policy_version: string;
172
+ lease_owner: string;
173
+ lease_expires_at: number;
174
+ created_at: number;
175
+ }
176
+ export interface AgentSituationCandidate {
177
+ ref: SituationRef;
178
+ kind: string;
179
+ title: string;
180
+ summary: string;
181
+ timestamp_ms: number;
182
+ confidence?: number | null;
183
+ status?: string | null;
184
+ is_open_question?: boolean;
185
+ has_debate_edge?: boolean;
186
+ connector?: string | null;
187
+ channel_id?: string | null;
188
+ scope?: MemoryScopeRef | null;
189
+ }
190
+ export interface SituationScore {
191
+ score: number;
192
+ reasons: string[];
193
+ caveats: string[];
194
+ }
195
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Canonical JSON serializer + SHA-256 hash for `case_corrections.target_ref`.
3
+ *
4
+ * Phase 1 of MAMA Case-First Memory System (spec §5.4 Option C).
5
+ *
6
+ * Behavior:
7
+ * - recursively sort object keys in lexicographic UTF-8 order
8
+ * - preserve array order (semantic)
9
+ * - reject undefined values with typed error code `canonicalize.undefined_value`
10
+ * - reject function values with typed error code `canonicalize.function_value`
11
+ * - reject non-finite numbers (NaN, +/- Infinity) with `canonicalize.non_finite_number`
12
+ * - serialize normalized value via JSON.stringify (after normalization)
13
+ * - hash canonical JSON string with SHA-256 over UTF-8 bytes → 32-byte Buffer
14
+ *
15
+ * No top-level await. No ESM-only runtime dependency. Safe for CJS consumers
16
+ * (mcp-server, claude-code-plugin) via package export `./canonicalize`.
17
+ *
18
+ * @module canonicalize
19
+ */
20
+ export type CanonicalizeErrorCode = 'canonicalize.undefined_value' | 'canonicalize.function_value' | 'canonicalize.non_finite_number';
21
+ export declare class CanonicalizeError extends Error {
22
+ readonly code: CanonicalizeErrorCode;
23
+ constructor(code: CanonicalizeErrorCode, message: string);
24
+ }
25
+ /**
26
+ * Produce a canonical JSON string for `value`.
27
+ *
28
+ * Two calls with semantically equivalent input produce byte-identical output.
29
+ */
30
+ export declare function canonicalizeJSON(value: unknown): string;
31
+ /**
32
+ * Produce the 32-byte SHA-256 digest of the canonical JSON form of `value`.
33
+ *
34
+ * Invariant: `targetRefHash(obj)` === `targetRefHash(canonicalizeJSON(obj))`.
35
+ */
36
+ export declare function targetRefHash(value: unknown): Buffer;
37
+ export declare function targetRefHashCanonicalJSON(canonicalJson: string): Buffer;
38
+ //# sourceMappingURL=canonicalize.d.ts.map
@@ -0,0 +1,106 @@
1
+ "use strict";
2
+ /**
3
+ * Canonical JSON serializer + SHA-256 hash for `case_corrections.target_ref`.
4
+ *
5
+ * Phase 1 of MAMA Case-First Memory System (spec §5.4 Option C).
6
+ *
7
+ * Behavior:
8
+ * - recursively sort object keys in lexicographic UTF-8 order
9
+ * - preserve array order (semantic)
10
+ * - reject undefined values with typed error code `canonicalize.undefined_value`
11
+ * - reject function values with typed error code `canonicalize.function_value`
12
+ * - reject non-finite numbers (NaN, +/- Infinity) with `canonicalize.non_finite_number`
13
+ * - serialize normalized value via JSON.stringify (after normalization)
14
+ * - hash canonical JSON string with SHA-256 over UTF-8 bytes → 32-byte Buffer
15
+ *
16
+ * No top-level await. No ESM-only runtime dependency. Safe for CJS consumers
17
+ * (mcp-server, claude-code-plugin) via package export `./canonicalize`.
18
+ *
19
+ * @module canonicalize
20
+ */
21
+ Object.defineProperty(exports, "__esModule", { value: true });
22
+ exports.CanonicalizeError = void 0;
23
+ exports.canonicalizeJSON = canonicalizeJSON;
24
+ exports.targetRefHash = targetRefHash;
25
+ exports.targetRefHashCanonicalJSON = targetRefHashCanonicalJSON;
26
+ const node_crypto_1 = require("node:crypto");
27
+ class CanonicalizeError extends Error {
28
+ code;
29
+ constructor(code, message) {
30
+ super(message);
31
+ this.name = 'CanonicalizeError';
32
+ this.code = code;
33
+ }
34
+ }
35
+ exports.CanonicalizeError = CanonicalizeError;
36
+ function normalize(value, path = '$') {
37
+ if (value === null)
38
+ return null;
39
+ const type = typeof value;
40
+ if (type === 'undefined') {
41
+ throw new CanonicalizeError('canonicalize.undefined_value', `undefined is not serializable (at ${path})`);
42
+ }
43
+ if (type === 'function') {
44
+ throw new CanonicalizeError('canonicalize.function_value', `functions are not serializable (at ${path})`);
45
+ }
46
+ if (type === 'number') {
47
+ const n = value;
48
+ if (!Number.isFinite(n)) {
49
+ throw new CanonicalizeError('canonicalize.non_finite_number', `non-finite number ${String(n)} is not serializable (at ${path})`);
50
+ }
51
+ return n;
52
+ }
53
+ if (type === 'bigint') {
54
+ return value.toString();
55
+ }
56
+ if (type === 'string' || type === 'boolean') {
57
+ return value;
58
+ }
59
+ if (Array.isArray(value)) {
60
+ return value.map((item, idx) => normalize(item, `${path}[${idx}]`));
61
+ }
62
+ if (type === 'object') {
63
+ const obj = value;
64
+ const sortedKeys = Object.keys(obj).sort();
65
+ const out = {};
66
+ for (const key of sortedKeys) {
67
+ out[key] = normalize(obj[key], `${path}.${key}`);
68
+ }
69
+ return out;
70
+ }
71
+ return value;
72
+ }
73
+ /**
74
+ * Produce a canonical JSON string for `value`.
75
+ *
76
+ * Two calls with semantically equivalent input produce byte-identical output.
77
+ */
78
+ function canonicalizeJSON(value) {
79
+ return JSON.stringify(normalize(value));
80
+ }
81
+ /**
82
+ * Produce the 32-byte SHA-256 digest of the canonical JSON form of `value`.
83
+ *
84
+ * Invariant: `targetRefHash(obj)` === `targetRefHash(canonicalizeJSON(obj))`.
85
+ */
86
+ function targetRefHash(value) {
87
+ if (typeof value === 'string') {
88
+ try {
89
+ const parsed = JSON.parse(value);
90
+ const canonicalJson = canonicalizeJSON(parsed);
91
+ if (canonicalJson === value) {
92
+ return targetRefHashCanonicalJSON(value);
93
+ }
94
+ }
95
+ catch {
96
+ // Raw strings are canonicalized below.
97
+ }
98
+ }
99
+ const json = canonicalizeJSON(value);
100
+ return targetRefHashCanonicalJSON(json);
101
+ }
102
+ function targetRefHashCanonicalJSON(canonicalJson) {
103
+ const json = canonicalJson;
104
+ return (0, node_crypto_1.createHash)('sha256').update(json, 'utf8').digest();
105
+ }
106
+ //# sourceMappingURL=canonicalize.js.map
@@ -0,0 +1,116 @@
1
+ import type { DatabaseAdapter } from '../db-manager.js';
2
+ import { type ImmediateTransactionAdapter } from './sqlite-transaction.js';
3
+ export type CaseLinkType = 'related' | 'supersedes-case' | 'subcase-of' | 'blocked-by' | 'duplicate-of';
4
+ export type CaseLinkSourceKind = 'manual' | 'wiki_compiler' | 'hitl_correction' | 'system_backfill';
5
+ export interface CaseLinkRecord {
6
+ link_id: string;
7
+ case_id_from: string;
8
+ case_id_to: string;
9
+ link_type: CaseLinkType;
10
+ created_at: string;
11
+ created_by: string;
12
+ confidence: number | null;
13
+ reason_json: string | null;
14
+ source_kind: CaseLinkSourceKind;
15
+ source_ref: string | null;
16
+ source_ref_fingerprint: Buffer | null;
17
+ source_ref_fingerprint_hex: string | null;
18
+ revoked_at: string | null;
19
+ revoked_by: string | null;
20
+ revoke_reason: string | null;
21
+ }
22
+ export interface CaseLinkCreateInput {
23
+ link_id?: string;
24
+ case_id_from: string;
25
+ case_id_to: string;
26
+ link_type: CaseLinkType;
27
+ created_by: string;
28
+ confidence?: number | null;
29
+ reason_json?: string | Record<string, unknown> | null;
30
+ source_kind?: CaseLinkSourceKind;
31
+ source_ref?: string | null;
32
+ source_ref_fingerprint?: Buffer | Uint8Array | null;
33
+ unsuppress_wiki_tombstone?: boolean;
34
+ expected_current_value_json?: string | null;
35
+ reconfirm_token?: string | null;
36
+ session_id?: string | null;
37
+ now?: string;
38
+ }
39
+ export interface CaseLinkRevokeInput {
40
+ link_id: string;
41
+ revoked_by: string;
42
+ revoke_reason: string;
43
+ expected_current_value_json?: string | null;
44
+ reconfirm_token?: string | null;
45
+ session_id?: string | null;
46
+ now?: string;
47
+ }
48
+ export interface CaseLinkRequiresReconfirmResult {
49
+ kind: 'requires_reconfirm';
50
+ code: 'case.correction_requires_reconfirm';
51
+ case_id: string;
52
+ target_kind: 'case_link';
53
+ target_ref_json: string;
54
+ current_value_json: string;
55
+ old_value_json: string | null;
56
+ proposed_new_value_json: string;
57
+ reconfirm_token: string;
58
+ reconfirm_token_expires_at: string;
59
+ message: string;
60
+ }
61
+ export type CaseLinkCreateResult = {
62
+ kind: 'created';
63
+ link_id: string;
64
+ source_ref_fingerprint_hex: string;
65
+ } | CaseLinkRequiresReconfirmResult | {
66
+ kind: 'rejected';
67
+ code: 'case.precompile_gap' | 'case.terminal_status' | 'case.self_link' | 'case.wiki_tombstone_conflict' | 'case.correction_active_conflict' | 'case.reconfirm_token_replayed';
68
+ message: string;
69
+ case_id?: string;
70
+ };
71
+ export type CaseLinkRevokeResult = {
72
+ kind: 'revoked';
73
+ link_id: string;
74
+ } | CaseLinkRequiresReconfirmResult | {
75
+ kind: 'rejected';
76
+ code: 'case.case_link_not_found' | 'case.wiki_tombstone_fingerprint_missing' | 'case.reconfirm_token_replayed';
77
+ message: string;
78
+ link_id?: string;
79
+ };
80
+ export interface ListActiveCaseLinksResult {
81
+ terminal_case_id: string;
82
+ resolved_via_case_id: string | null;
83
+ chain: string[];
84
+ links: CaseLinkRecord[];
85
+ }
86
+ export interface BackfillStructuralLinksResult {
87
+ duplicate_of_inserted: number;
88
+ subcase_of_inserted: number;
89
+ }
90
+ type CaseLinkAdapter = Pick<DatabaseAdapter, 'prepare' | 'transaction'> & Partial<Pick<ImmediateTransactionAdapter, 'exec'>>;
91
+ export declare function sha256TombstoneFingerprint(input: {
92
+ source_case_id: string;
93
+ target_case_id: string;
94
+ link_type: CaseLinkType;
95
+ }): Buffer;
96
+ export declare function createCaseLink(adapter: DatabaseAdapter, input: CaseLinkCreateInput): CaseLinkCreateResult;
97
+ export declare function revokeCaseLink(adapter: DatabaseAdapter, input: CaseLinkRevokeInput): CaseLinkRevokeResult;
98
+ export declare function listActiveCaseLinks(adapter: DatabaseAdapter, caseId: string): ListActiveCaseLinksResult;
99
+ export declare function isWikiTombstoneActive(adapter: DatabaseAdapter | CaseLinkAdapter, input: {
100
+ source_case_id: string;
101
+ target_case_id: string;
102
+ link_type: CaseLinkType;
103
+ }): boolean;
104
+ export declare function unsuppressWikiTombstone(adapter: DatabaseAdapter, input: {
105
+ source_case_id: string;
106
+ target_case_id: string;
107
+ link_type: CaseLinkType;
108
+ unsuppressed_by: string;
109
+ now?: string;
110
+ }): {
111
+ kind: 'unsuppressed';
112
+ unsuppressed_count: number;
113
+ };
114
+ export declare function backfillStructuralLinks(adapter: DatabaseAdapter): BackfillStructuralLinksResult;
115
+ export {};
116
+ //# sourceMappingURL=case-links.d.ts.map