tsunami-memory 1.0.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 (54) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +501 -0
  3. package/README.zh-CN.md +485 -0
  4. package/package.json +46 -0
  5. package/server/api.ts +125 -0
  6. package/server/mcp.ts +221 -0
  7. package/src/bun_memory_store.ts +340 -0
  8. package/src/classifier_keywords.ts +115 -0
  9. package/src/core/project_state.ts +88 -0
  10. package/src/index.ts +54 -0
  11. package/src/legacy_compat/tsunami_compat.ts +22 -0
  12. package/src/legacy_compat/tsunami_legacy_identity.ts +13 -0
  13. package/src/legacy_compat/tsunami_legacy_taxonomy.ts +197 -0
  14. package/src/memory_audit.ts +32 -0
  15. package/src/memory_conflict_resolver.ts +14 -0
  16. package/src/memory_fabric.ts +31 -0
  17. package/src/memory_manager.ts +10 -0
  18. package/src/memory_promotion.ts +22 -0
  19. package/src/memory_recovery.ts +14 -0
  20. package/src/memory_runtime.ts +7 -0
  21. package/src/migration.ts +163 -0
  22. package/src/provider.ts +68 -0
  23. package/src/runtime/checkpoints/durable_recovery.ts +24 -0
  24. package/src/runtime/paths.ts +11 -0
  25. package/src/storm/basins.ts +57 -0
  26. package/src/storm/boundary.ts +52 -0
  27. package/src/storm/budget.ts +42 -0
  28. package/src/storm/center.ts +396 -0
  29. package/src/storm/confidence.ts +88 -0
  30. package/src/storm/coverage.ts +44 -0
  31. package/src/storm/directive.ts +94 -0
  32. package/src/storm/gate.ts +43 -0
  33. package/src/storm/helpers.ts +172 -0
  34. package/src/storm/horizon.ts +52 -0
  35. package/src/storm/intake.ts +80 -0
  36. package/src/storm/mode.ts +21 -0
  37. package/src/storm/pressure.ts +56 -0
  38. package/src/storm/readiness.ts +29 -0
  39. package/src/storm/saturation.ts +45 -0
  40. package/src/storm/selection.ts +49 -0
  41. package/src/storm/signals.ts +105 -0
  42. package/src/storm/types.ts +216 -0
  43. package/src/tsunami_bun_backend.ts +705 -0
  44. package/src/tsunami_chinese_dialect.ts +19 -0
  45. package/src/tsunami_classifier.ts +137 -0
  46. package/src/tsunami_client.ts +710 -0
  47. package/src/tsunami_execution_gate.ts +232 -0
  48. package/src/tsunami_graph_runtime.ts +359 -0
  49. package/src/tsunami_identity.ts +35 -0
  50. package/src/tsunami_routing.ts +169 -0
  51. package/src/tsunami_runtime_graph_sync.ts +17 -0
  52. package/src/tsunami_schema.ts +403 -0
  53. package/src/tsunami_storage_paths.ts +8 -0
  54. package/src/tsunami_storm_center.ts +53 -0
@@ -0,0 +1,169 @@
1
+ import { TSUNAMI_COMPAT_WRAPPER } from './legacy_compat/tsunami_compat';
2
+
3
+ export type TsunamiMemoryRoutingPolicy = 'bun_native' | 'wrapper_bridge' | 'unknown';
4
+
5
+ export type TsunamiWrapperShellSummary = {
6
+ shell: 'python_wrapper';
7
+ path: string;
8
+ routeMode: 'opt_in_only';
9
+ implementedCount: number;
10
+ implementedCommands: string[];
11
+ defaultRoutedCommands: string[];
12
+ wrapperBridgeCount: number;
13
+ unknownRouteDefault: 'blocked';
14
+ notes: string[];
15
+ };
16
+
17
+ export const TSUNAMI_BUN_NATIVE_CMDS = [
18
+ 'status',
19
+ 'wakeup',
20
+ 'search',
21
+ 'recall',
22
+ 'add',
23
+ 'diary',
24
+ 'mine',
25
+ 'timeline',
26
+ 'list_wings',
27
+ 'list_rooms',
28
+ 'get_taxonomy',
29
+ 'check_duplicate',
30
+ 'delete_drawer',
31
+ 'diary_read',
32
+ 'get_aaak_spec',
33
+ 'classify',
34
+ 'classify_multi',
35
+ 'tsunami_taxonomy',
36
+ 'tsunami_ontology',
37
+ 'normalize_taxonomy',
38
+ 'storm_center',
39
+ 'kg_add',
40
+ 'kg_query',
41
+ 'kg_invalidate',
42
+ 'kg_stats',
43
+ 'kg_timeline',
44
+ 'traverse_graph',
45
+ 'find_tunnels',
46
+ 'graph_stats',
47
+ ] as const;
48
+
49
+ export const TSUNAMI_WRAPPER_BRIDGE_CMDS = [] as const;
50
+
51
+ export const TSUNAMI_WRAPPER_IMPLEMENTED_CMDS = [
52
+ 'wakeup',
53
+ 'search',
54
+ 'recall',
55
+ 'status',
56
+ 'add',
57
+ 'kg_query',
58
+ 'kg_add',
59
+ 'kg_invalidate',
60
+ 'kg_stats',
61
+ 'diary',
62
+ 'list_wings',
63
+ 'list_rooms',
64
+ 'get_taxonomy',
65
+ 'check_duplicate',
66
+ 'delete_drawer',
67
+ 'traverse_graph',
68
+ 'find_tunnels',
69
+ 'graph_stats',
70
+ 'diary_read',
71
+ 'get_aaak_spec',
72
+ 'classify',
73
+ 'mine',
74
+ ] as const;
75
+
76
+ const BUN_NATIVE_SET = new Set<string>(TSUNAMI_BUN_NATIVE_CMDS);
77
+ const WRAPPER_BRIDGE_SET = new Set<string>(TSUNAMI_WRAPPER_BRIDGE_CMDS);
78
+ const WRAPPER_IMPLEMENTED_SET = new Set<string>(TSUNAMI_WRAPPER_IMPLEMENTED_CMDS);
79
+
80
+ export type TsunamiBunCoverageSummary = {
81
+ primary: 'bun_native';
82
+ wrapperSurfaceCount: number;
83
+ bunNativeCount: number;
84
+ wrapperBridgeCount: number;
85
+ wrapperOnlyCount: number;
86
+ wrapperCoveredCount: number;
87
+ coverageRatio: number;
88
+ wrapperOnly: string[];
89
+ hybridBridge: string[];
90
+ bunNativeOnly: string[];
91
+ bunNative: string[];
92
+ wrapperImplemented: string[];
93
+ wrapperBridge: string[];
94
+ notes: string[];
95
+ };
96
+
97
+ export function resolveTsunamiRoutingPolicy(req: Record<string, unknown>): TsunamiMemoryRoutingPolicy {
98
+ const cmd = String(req.cmd ?? '').trim();
99
+ if (!cmd) return 'unknown';
100
+ if (BUN_NATIVE_SET.has(cmd)) return 'bun_native';
101
+ if (WRAPPER_BRIDGE_SET.has(cmd)) return 'wrapper_bridge';
102
+ return 'unknown';
103
+ }
104
+
105
+ export function describeTsunamiRoutingMatrix() {
106
+ return {
107
+ primary: 'bun_native',
108
+ bunNative: [...TSUNAMI_BUN_NATIVE_CMDS],
109
+ wrapperImplemented: [...TSUNAMI_WRAPPER_IMPLEMENTED_CMDS],
110
+ wrapperBridge: [...TSUNAMI_WRAPPER_BRIDGE_CMDS],
111
+ wrapperShell: buildTsunamiWrapperShellSummary(),
112
+ coverage: buildTsunamiBunCoverageSummary(),
113
+ notes: [
114
+ 'delete_drawer now resolves through the Bun-native delete path for both bunmem and legacy fallback ids',
115
+ 'known Bun-native commands should not silently fall through to wrapper',
116
+ 'unknown commands are blocked by default; wrapper shell is opt-in only',
117
+ ],
118
+ };
119
+ }
120
+
121
+ export function buildTsunamiWrapperShellSummary(): TsunamiWrapperShellSummary {
122
+ return {
123
+ shell: 'python_wrapper',
124
+ path: TSUNAMI_COMPAT_WRAPPER,
125
+ routeMode: 'opt_in_only',
126
+ implementedCount: TSUNAMI_WRAPPER_IMPLEMENTED_CMDS.length,
127
+ implementedCommands: [...TSUNAMI_WRAPPER_IMPLEMENTED_CMDS],
128
+ defaultRoutedCommands: [],
129
+ wrapperBridgeCount: TSUNAMI_WRAPPER_BRIDGE_CMDS.length,
130
+ unknownRouteDefault: 'blocked',
131
+ notes: [
132
+ 'the wrapper shell remains on disk as a compatibility shell, not as a default route',
133
+ 'legacy wrapper execution now requires explicit opt-in',
134
+ 'default TSUNAMI routing should stay Bun-native or return unsupported',
135
+ ],
136
+ };
137
+ }
138
+
139
+ export function buildTsunamiBunCoverageSummary(): TsunamiBunCoverageSummary {
140
+ const wrapperImplemented = [...TSUNAMI_WRAPPER_IMPLEMENTED_CMDS];
141
+ const bunNative = [...TSUNAMI_BUN_NATIVE_CMDS];
142
+ const wrapperBridge = [...TSUNAMI_WRAPPER_BRIDGE_CMDS];
143
+ const wrapperOnly = wrapperImplemented.filter((cmd) => !BUN_NATIVE_SET.has(cmd) && !WRAPPER_BRIDGE_SET.has(cmd));
144
+ const hybridBridge = wrapperImplemented.filter((cmd) => BUN_NATIVE_SET.has(cmd) && WRAPPER_BRIDGE_SET.has(cmd));
145
+ const bunNativeOnly = bunNative.filter((cmd) => !WRAPPER_IMPLEMENTED_SET.has(cmd));
146
+ const wrapperCoveredCount = wrapperImplemented.length - wrapperOnly.length;
147
+ return {
148
+ primary: 'bun_native',
149
+ wrapperSurfaceCount: wrapperImplemented.length,
150
+ bunNativeCount: bunNative.length,
151
+ wrapperBridgeCount: wrapperBridge.length,
152
+ wrapperOnlyCount: wrapperOnly.length,
153
+ wrapperCoveredCount,
154
+ coverageRatio: wrapperImplemented.length > 0
155
+ ? Number((wrapperCoveredCount / wrapperImplemented.length).toFixed(3))
156
+ : 1,
157
+ wrapperOnly,
158
+ hybridBridge,
159
+ bunNativeOnly,
160
+ bunNative,
161
+ wrapperImplemented,
162
+ wrapperBridge,
163
+ notes: [
164
+ 'wrapper surface means commands historically implemented in the TSUNAMI legacy compatibility wrapper',
165
+ 'hybridBridge means the command is Bun-native by default but still keeps a narrow wrapper bridge',
166
+ 'wrapperOnly should trend toward zero as TSUNAMI finishes migration',
167
+ ],
168
+ };
169
+ }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * TSUNAMI runtime graph sync stub
3
+ *
4
+ * Provides the sync interface for project-level knowledge graph
5
+ * synchronization. The full implementation uses file-watching and
6
+ * incremental triple extraction; this stub returns empty results.
7
+ */
8
+
9
+ export interface TsunamiRuntimeGraphSyncSummary {
10
+ synced: number;
11
+ conflicts: number;
12
+ errors: string[];
13
+ }
14
+
15
+ export function syncProjectRuntimeGraph(_projectDir: string): TsunamiRuntimeGraphSyncSummary {
16
+ return { synced: 0, conflicts: 0, errors: [] };
17
+ }
@@ -0,0 +1,403 @@
1
+ import {
2
+ TSUNAMI_DEFAULT_LEGACY_ROOM,
3
+ normalizeTsunamiCompatRoom,
4
+ } from './legacy_compat/tsunami_compat';
5
+ import { TSUNAMI_LEGACY_TAXONOMY_ENTRIES } from './legacy_compat/tsunami_legacy_taxonomy';
6
+
7
+ export type TsunamiBasin = 'epicenter' | 'surface' | 'faultline' | 'abyss' | 'surge' | 'harbor';
8
+ export type TsunamiEntityType =
9
+ | 'agent'
10
+ | 'person'
11
+ | 'project'
12
+ | 'task_thread'
13
+ | 'handoff'
14
+ | 'recovery_anchor'
15
+ | 'checkpoint'
16
+ | 'recovery_record'
17
+ | 'memory_issue'
18
+ | 'repair_suggestion'
19
+ | 'wiki_page'
20
+ | 'evidence_snippet'
21
+ | 'memory_fragment'
22
+ | 'basin'
23
+ | 'current'
24
+ | 'decision'
25
+ | 'session_state'
26
+ | 'feature'
27
+ | 'unknown';
28
+
29
+ export type TsunamiCurrent =
30
+ | 'epicenter/signature'
31
+ | 'epicenter/crest'
32
+ | 'epicenter/law'
33
+ | 'surface/bridge'
34
+ | 'surface/helm'
35
+ | 'surface/rigging'
36
+ | 'surface/hull'
37
+ | 'surface/chart'
38
+ | 'surface/echo'
39
+ | 'faultline/choice'
40
+ | 'faultline/course'
41
+ | 'faultline/drift'
42
+ | 'abyss/archive'
43
+ | 'abyss/mesh'
44
+ | 'abyss/wake'
45
+ | 'abyss/anchors'
46
+ | 'abyss/evidence'
47
+ | 'surge/expedition'
48
+ | 'surge/tide'
49
+ | 'surge/queue'
50
+ | 'surge/blockers'
51
+ | 'harbor/crew'
52
+ | 'harbor/research'
53
+ | 'harbor/liu-lie'
54
+ | 'harbor/dandan';
55
+
56
+ type TaxonomyEntry = {
57
+ legacyWing: string;
58
+ legacyRoom: string;
59
+ basin: TsunamiBasin;
60
+ current: TsunamiCurrent;
61
+ description: string;
62
+ };
63
+
64
+ type GraphRelation = {
65
+ predicate: string;
66
+ theme: 'structure' | 'flow' | 'evidence' | 'recovery' | 'drift';
67
+ description: string;
68
+ examples: string[];
69
+ };
70
+
71
+ const ENTITY_TYPES = [
72
+ 'agent',
73
+ 'person',
74
+ 'project',
75
+ 'task_thread',
76
+ 'handoff',
77
+ 'recovery_anchor',
78
+ 'checkpoint',
79
+ 'recovery_record',
80
+ 'memory_issue',
81
+ 'repair_suggestion',
82
+ 'wiki_page',
83
+ 'evidence_snippet',
84
+ 'memory_fragment',
85
+ 'basin',
86
+ 'current',
87
+ 'decision',
88
+ 'session_state',
89
+ 'feature',
90
+ 'unknown',
91
+ ] as const satisfies readonly TsunamiEntityType[];
92
+
93
+ const TAXONOMY_ENTRIES: TaxonomyEntry[] = TSUNAMI_LEGACY_TAXONOMY_ENTRIES.map((entry) => ({
94
+ legacyWing: entry.legacyWing,
95
+ legacyRoom: entry.legacyRoom,
96
+ basin: entry.basin as TsunamiBasin,
97
+ current: entry.current as TsunamiCurrent,
98
+ description: entry.description,
99
+ }));
100
+
101
+ const CURRENT_ALIASES: Record<string, TsunamiCurrent> = {
102
+ signature: 'epicenter/signature',
103
+ crest: 'epicenter/crest',
104
+ law: 'epicenter/law',
105
+ bridge: 'surface/bridge',
106
+ helm: 'surface/helm',
107
+ rigging: 'surface/rigging',
108
+ hull: 'surface/hull',
109
+ chart: 'surface/chart',
110
+ echo: 'surface/echo',
111
+ choice: 'faultline/choice',
112
+ course: 'faultline/course',
113
+ drift: 'faultline/drift',
114
+ archive: 'abyss/archive',
115
+ mesh: 'abyss/mesh',
116
+ wake: 'abyss/wake',
117
+ anchors: 'abyss/anchors',
118
+ evidence: 'abyss/evidence',
119
+ expedition: 'surge/expedition',
120
+ tide: 'surge/tide',
121
+ queue: 'surge/queue',
122
+ blockers: 'surge/blockers',
123
+ crew: 'harbor/crew',
124
+ research: 'harbor/research',
125
+ 'liu-lie': 'harbor/liu-lie',
126
+ dandan: 'harbor/dandan',
127
+ };
128
+
129
+ const LEGACY_BY_ROOM = new Map(TAXONOMY_ENTRIES.map((entry) => [entry.legacyRoom, entry]));
130
+ const TSUNAMI_BY_CURRENT = new Map(TAXONOMY_ENTRIES.map((entry) => [entry.current, entry]));
131
+ const LEGACY_BY_WING = TAXONOMY_ENTRIES.reduce<Map<string, TaxonomyEntry>>((map, entry) => {
132
+ if (!map.has(entry.legacyWing)) {
133
+ map.set(entry.legacyWing, entry);
134
+ }
135
+ return map;
136
+ }, new Map<string, TaxonomyEntry>());
137
+ function canonicalRoom(room: string): string {
138
+ return normalizeTsunamiCompatRoom(room);
139
+ }
140
+
141
+ const DEFAULT_BY_BASIN: Record<TsunamiBasin, TsunamiCurrent> = {
142
+ epicenter: 'epicenter/signature',
143
+ surface: 'surface/bridge',
144
+ faultline: 'faultline/choice',
145
+ abyss: 'abyss/archive',
146
+ surge: 'surge/expedition',
147
+ harbor: 'harbor/crew',
148
+ };
149
+
150
+ const GRAPH_RELATIONS: GraphRelation[] = [
151
+ {
152
+ predicate: 'anchors_to',
153
+ theme: 'structure',
154
+ description: 'Welds handoff, checkpoint, recovery anchor, and task thread into one continuous mainline.',
155
+ examples: ['handoff -> recovery_anchor', 'checkpoint -> task_thread'],
156
+ },
157
+ {
158
+ predicate: 'flows_to',
159
+ theme: 'flow',
160
+ description: 'Describes flow between tasks, steps, status, and next actions.',
161
+ examples: ['task_thread -> next_step', 'decision -> resulting_task'],
162
+ },
163
+ {
164
+ predicate: 'feeds',
165
+ theme: 'evidence',
166
+ description: 'Represents evidence, wiki, and memory fragments feeding into higher-level decisions.',
167
+ examples: ['evidence_snippet -> wiki_page', 'wiki_page -> planner_context'],
168
+ },
169
+ {
170
+ predicate: 'crosscurrents_with',
171
+ theme: 'drift',
172
+ description: 'Indicates drift or conflict between two mainlines, anchors, or handoffs.',
173
+ examples: ['handoff -> anchor', 'feature -> task_thread'],
174
+ },
175
+ {
176
+ predicate: 'surges_from',
177
+ theme: 'flow',
178
+ description: 'Indicates a task surge, behavior, or strategy triggered by a decision or rule.',
179
+ examples: ['task_surge -> decision', 'behavior -> identity_rule'],
180
+ },
181
+ {
182
+ predicate: 'settles_into',
183
+ theme: 'recovery',
184
+ description: 'Represents execution results settling into handoff, archive, or stable state.',
185
+ examples: ['turn_outcome -> handoff', 'active_task -> archive'],
186
+ },
187
+ {
188
+ predicate: 'echoes',
189
+ theme: 'drift',
190
+ description: 'Represents duplicate, near-duplicate, restated, or echo memories.',
191
+ examples: ['memory_fragment -> memory_fragment', 'anchor -> anchor'],
192
+ },
193
+ {
194
+ predicate: 'belongs_to_basin',
195
+ theme: 'structure',
196
+ description: 'Tags memory fragments, currents, wikis, or threads into a TSUNAMI basin.',
197
+ examples: ['memory_fragment -> abyss', 'task_thread -> surge'],
198
+ },
199
+ {
200
+ predicate: 'restored_from',
201
+ theme: 'recovery',
202
+ description: 'Indicates current state was restored from a checkpoint, anchor, or recovery point.',
203
+ examples: ['task_thread -> checkpoint', 'session_state -> recovery_anchor'],
204
+ },
205
+ {
206
+ predicate: 'cites',
207
+ theme: 'evidence',
208
+ description: 'Represents citation relationships from wiki, handoff, or decision to evidence fragments.',
209
+ examples: ['wiki_page -> evidence_snippet', 'handoff -> evidence_snippet'],
210
+ },
211
+ ];
212
+
213
+ export function listTsunamiTaxonomyEntries(): TaxonomyEntry[] {
214
+ return [...TAXONOMY_ENTRIES];
215
+ }
216
+
217
+ export function describeTsunamiTaxonomy() {
218
+ const basins = Array.from(new Set(TAXONOMY_ENTRIES.map((entry) => entry.basin))).map((basin) => ({
219
+ basin,
220
+ defaultCurrent: DEFAULT_BY_BASIN[basin],
221
+ currents: TAXONOMY_ENTRIES.filter((entry) => entry.basin === basin).map((entry) => ({
222
+ current: entry.current,
223
+ legacyWing: entry.legacyWing,
224
+ legacyRoom: entry.legacyRoom,
225
+ description: entry.description,
226
+ })),
227
+ }));
228
+
229
+ return {
230
+ systemName: 'TSUNAMI',
231
+ taxonomyVersion: 'v1',
232
+ primaryNamespace: 'basin/current',
233
+ compatibilityNamespace: 'wing/room',
234
+ basins,
235
+ aliases: TAXONOMY_ENTRIES.map((entry) => ({
236
+ legacyWing: entry.legacyWing,
237
+ legacyRoom: entry.legacyRoom,
238
+ basin: entry.basin,
239
+ current: entry.current,
240
+ })),
241
+ };
242
+ }
243
+
244
+ export function describeTsunamiGraphOntology() {
245
+ return {
246
+ systemName: 'TSUNAMI',
247
+ ontologyVersion: 'v1',
248
+ entityTypes: [...ENTITY_TYPES],
249
+ relationTypes: GRAPH_RELATIONS,
250
+ };
251
+ }
252
+
253
+ export function listTsunamiEntityTypes(): TsunamiEntityType[] {
254
+ return [...ENTITY_TYPES];
255
+ }
256
+
257
+ export function normalizeTsunamiEntityType(value: unknown): TsunamiEntityType {
258
+ const normalized = String(value ?? '').trim().toLowerCase().replace(/\s+/g, '_') as TsunamiEntityType | '';
259
+ if (normalized && ENTITY_TYPES.includes(normalized as TsunamiEntityType)) {
260
+ return normalized as TsunamiEntityType;
261
+ }
262
+ return 'unknown';
263
+ }
264
+
265
+ export function describeTsunamiRelation(predicate: unknown): GraphRelation | null {
266
+ const normalized = String(predicate ?? '').trim().toLowerCase().replace(/\s+/g, '_');
267
+ return GRAPH_RELATIONS.find((item) => item.predicate === normalized) ?? null;
268
+ }
269
+
270
+ export function listTsunamiGraphRelations(): GraphRelation[] {
271
+ return [...GRAPH_RELATIONS];
272
+ }
273
+
274
+ function resolveCurrent(basin?: string, current?: string): TsunamiCurrent | null {
275
+ const basinValue = String(basin ?? '').trim().toLowerCase() as TsunamiBasin | '';
276
+ const currentValue = String(current ?? '').trim().toLowerCase();
277
+ if (currentValue) {
278
+ if (TSUNAMI_BY_CURRENT.has(currentValue as TsunamiCurrent)) {
279
+ return currentValue as TsunamiCurrent;
280
+ }
281
+ const alias = CURRENT_ALIASES[currentValue];
282
+ if (alias) {
283
+ if (!basinValue || alias.startsWith(`${basinValue}/`)) return alias;
284
+ }
285
+ if (basinValue && CURRENT_ALIASES[currentValue] && CURRENT_ALIASES[currentValue].startsWith(`${basinValue}/`)) {
286
+ return CURRENT_ALIASES[currentValue];
287
+ }
288
+ }
289
+ if (basinValue && DEFAULT_BY_BASIN[basinValue]) {
290
+ return DEFAULT_BY_BASIN[basinValue];
291
+ }
292
+ return null;
293
+ }
294
+
295
+ export function normalizeTsunamiTaxonomy(input: {
296
+ wing?: string;
297
+ room?: string;
298
+ basin?: string;
299
+ current?: string;
300
+ }): {
301
+ wing: string;
302
+ room: string;
303
+ basin: TsunamiBasin;
304
+ current: TsunamiCurrent;
305
+ namespace: 'legacy' | 'tsunami' | 'mixed';
306
+ } {
307
+ const wing = String(input.wing ?? '').trim();
308
+ const room = String(input.room ?? '').trim();
309
+ const resolvedRoom = normalizeTsunamiCompatRoom(room);
310
+ const basin = String(input.basin ?? '').trim();
311
+ const current = String(input.current ?? '').trim();
312
+
313
+ if (basin || current) {
314
+ const resolvedCurrent = resolveCurrent(basin, current);
315
+ if (resolvedCurrent) {
316
+ const entry = TSUNAMI_BY_CURRENT.get(resolvedCurrent)!;
317
+ return {
318
+ wing: entry.legacyWing,
319
+ room: canonicalRoom(entry.legacyRoom),
320
+ basin: entry.basin,
321
+ current: entry.current,
322
+ namespace: wing || room ? 'mixed' : 'tsunami',
323
+ };
324
+ }
325
+ }
326
+
327
+ const legacyEntry = LEGACY_BY_ROOM.get(resolvedRoom);
328
+ if (legacyEntry) {
329
+ return {
330
+ wing: legacyEntry.legacyWing,
331
+ room: canonicalRoom(legacyEntry.legacyRoom),
332
+ basin: legacyEntry.basin,
333
+ current: legacyEntry.current,
334
+ namespace: 'legacy',
335
+ };
336
+ }
337
+
338
+ const legacyWingEntry = LEGACY_BY_WING.get(wing);
339
+ if (legacyWingEntry) {
340
+ return {
341
+ wing: legacyWingEntry.legacyWing,
342
+ room: canonicalRoom(legacyWingEntry.legacyRoom),
343
+ basin: legacyWingEntry.basin,
344
+ current: legacyWingEntry.current,
345
+ namespace: 'legacy',
346
+ };
347
+ }
348
+
349
+ return {
350
+ wing: wing || 'ats',
351
+ room: room || TSUNAMI_DEFAULT_LEGACY_ROOM,
352
+ basin: 'surface',
353
+ current: 'surface/bridge',
354
+ namespace: 'legacy',
355
+ };
356
+ }
357
+
358
+ export function formatTsunamiTaxonomyText(): string {
359
+ const taxonomy = describeTsunamiTaxonomy();
360
+ const lines = [
361
+ `TSUNAMI Taxonomy (${taxonomy.taxonomyVersion})`,
362
+ `primary=${taxonomy.primaryNamespace} compatibility=${taxonomy.compatibilityNamespace}`,
363
+ 'bridge: legacy wing/room -> basin/current',
364
+ '',
365
+ ];
366
+ for (const basin of taxonomy.basins) {
367
+ lines.push(`[${basin.basin}] default=${basin.defaultCurrent}`);
368
+ for (const current of basin.currents) {
369
+ lines.push(` - ${current.current} <= ${current.legacyWing}/${canonicalRoom(current.legacyRoom)}`);
370
+ }
371
+ }
372
+ return lines.join('\n');
373
+ }
374
+
375
+ export function formatTsunamiGraphOntologyText(): string {
376
+ const ontology = describeTsunamiGraphOntology();
377
+ const lines = [
378
+ `TSUNAMI Graph Ontology (${ontology.ontologyVersion})`,
379
+ `entities=${ontology.entityTypes.join(', ')}`,
380
+ '',
381
+ 'relations:',
382
+ ];
383
+ for (const relation of ontology.relationTypes) {
384
+ lines.push(`- ${relation.predicate} [${relation.theme}] ${relation.description}`);
385
+ lines.push(` examples: ${relation.examples.join(' | ')}`);
386
+ }
387
+ return lines.join('\n');
388
+ }
389
+
390
+ export function formatTsunamiNormalizationText(input: {
391
+ wing?: string;
392
+ room?: string;
393
+ basin?: string;
394
+ current?: string;
395
+ }): string {
396
+ const normalized = normalizeTsunamiTaxonomy(input);
397
+ return [
398
+ 'TSUNAMI Normalization',
399
+ `namespace=${normalized.namespace}`,
400
+ `legacy=${normalized.wing}/${normalized.room}`,
401
+ `tsunami=${normalized.basin}/${normalized.current}`,
402
+ ].join('\n');
403
+ }
@@ -0,0 +1,8 @@
1
+ import { statePath } from './runtime/paths';
2
+
3
+ export const TSUNAMI_RUNTIME_MEMORY_DIR = statePath('memory');
4
+ export const TSUNAMI_GRAPH_DB_PATH = statePath('memory', 'tsunami_graph.sqlite3');
5
+ export const BUN_MEMORY_DB_PATH = statePath('memory', 'tsunami_memory.sqlite3');
6
+ export const TSUNAMI_IDENTITY_FILE = statePath('memory', 'tsunami_identity.txt');
7
+ export const TSUNAMI_LEGACY_FALLBACK_FILE = statePath('memory', 'legacy_fallback_drawers.json');
8
+ export const TSUNAMI_MIGRATION_DIR = statePath('memory', 'migration');
@@ -0,0 +1,53 @@
1
+ /**
2
+ * TSUNAMI Storm Center — barrel file
3
+ *
4
+ * The storm center has been split into modular components under src/storm/.
5
+ * This file re-exports the public API for backward compatibility.
6
+ *
7
+ * Module map:
8
+ * types.ts — all storm-related types
9
+ * helpers.ts — node builders, clamping, tokenization, fallback docs, retry
10
+ * signals.ts — buildCurrents, buildCurrentMix
11
+ * basins.ts — buildSupportingBasins
12
+ * mode.ts — buildStormMode
13
+ * pressure.ts — buildStormPressure
14
+ * directive.ts — buildStormDirective, buildStormAction
15
+ * readiness.ts — buildStormReadiness
16
+ * boundary.ts — buildStormBoundary
17
+ * horizon.ts — buildStormHorizon
18
+ * confidence.ts — buildStormConfidence
19
+ * gate.ts — buildStormGate
20
+ * budget.ts — buildStormBudget
21
+ * selection.ts — buildStormSelection
22
+ * coverage.ts — buildStormCoverage
23
+ * saturation.ts — buildStormSaturation
24
+ * intake.ts — buildStormIntake
25
+ * center.ts — buildTsunamiStormCenter, formatTsunamiStormCenterText
26
+ */
27
+
28
+ export {
29
+ buildTsunamiStormCenter,
30
+ formatTsunamiStormCenterText,
31
+ isTsunamiStormRetryableError,
32
+ withTsunamiStormRetry,
33
+ } from './storm/center';
34
+
35
+ export type {
36
+ TsunamiStormCenterCurrent,
37
+ TsunamiStormCenterCurrentMix,
38
+ TsunamiStormCenterStormMode,
39
+ TsunamiStormPressure,
40
+ TsunamiStormDirective,
41
+ TsunamiStormAction,
42
+ TsunamiStormReadiness,
43
+ TsunamiStormBoundary,
44
+ TsunamiStormHorizon,
45
+ TsunamiStormConfidence,
46
+ TsunamiStormGate,
47
+ TsunamiStormBudget,
48
+ TsunamiStormSelection,
49
+ TsunamiStormCoverage,
50
+ TsunamiStormSaturation,
51
+ TsunamiStormIntake,
52
+ TsunamiStormCenter,
53
+ } from './storm/types';