@sashabogi/foundation 2.0.1 → 2.2.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 (57) hide show
  1. package/README.md +3 -158
  2. package/dist/cli.js +363 -255
  3. package/dist/cli.js.map +1 -1
  4. package/dist/providers/anthropic.d.ts +2 -2
  5. package/dist/providers/anthropic.d.ts.map +1 -1
  6. package/dist/providers/anthropic.js +2 -2
  7. package/dist/providers/anthropic.js.map +1 -1
  8. package/dist/providers/types.d.ts +1 -1
  9. package/dist/providers/types.d.ts.map +1 -1
  10. package/dist/providers/zai.d.ts +17 -8
  11. package/dist/providers/zai.d.ts.map +1 -1
  12. package/dist/providers/zai.js +34 -13
  13. package/dist/providers/zai.js.map +1 -1
  14. package/dist/services/config.service.d.ts +1 -5
  15. package/dist/services/config.service.d.ts.map +1 -1
  16. package/dist/services/config.service.js +0 -20
  17. package/dist/services/config.service.js.map +1 -1
  18. package/dist/services/git.service.d.ts +0 -4
  19. package/dist/services/git.service.d.ts.map +1 -1
  20. package/dist/services/git.service.js +0 -30
  21. package/dist/services/git.service.js.map +1 -1
  22. package/dist/services/storage.service.d.ts +1 -24
  23. package/dist/services/storage.service.d.ts.map +1 -1
  24. package/dist/services/storage.service.js +0 -108
  25. package/dist/services/storage.service.js.map +1 -1
  26. package/dist/tools/gaia/index.d.ts +5 -8
  27. package/dist/tools/gaia/index.d.ts.map +1 -1
  28. package/dist/tools/gaia/index.js +16 -115
  29. package/dist/tools/gaia/index.js.map +1 -1
  30. package/dist/tools/gaia/storage.d.ts +15 -0
  31. package/dist/tools/gaia/storage.d.ts.map +1 -1
  32. package/dist/tools/gaia/storage.js +296 -1
  33. package/dist/tools/gaia/storage.js.map +1 -1
  34. package/dist/tools/seldon/index.d.ts +1 -12
  35. package/dist/tools/seldon/index.d.ts.map +1 -1
  36. package/dist/tools/seldon/index.js +1 -183
  37. package/dist/tools/seldon/index.js.map +1 -1
  38. package/dist/types/index.d.ts +0 -78
  39. package/dist/types/index.d.ts.map +1 -1
  40. package/dist/vault/dashboard.d.ts +10 -0
  41. package/dist/vault/dashboard.d.ts.map +1 -0
  42. package/dist/vault/dashboard.js +145 -0
  43. package/dist/vault/dashboard.js.map +1 -0
  44. package/dist/vault/sync.d.ts +64 -0
  45. package/dist/vault/sync.d.ts.map +1 -0
  46. package/dist/vault/sync.js +360 -0
  47. package/dist/vault/sync.js.map +1 -0
  48. package/dist/vault/transform.d.ts +25 -0
  49. package/dist/vault/transform.d.ts.map +1 -0
  50. package/dist/vault/transform.js +155 -0
  51. package/dist/vault/transform.js.map +1 -0
  52. package/package.json +1 -1
  53. package/packages/ui/dist/assets/index-BCBAHIpG.css +1 -0
  54. package/packages/ui/dist/assets/index-CxRK0aqp.js +387 -0
  55. package/packages/ui/dist/index.html +2 -2
  56. package/packages/ui/dist/assets/index-oiJTDMJ1.css +0 -1
  57. package/packages/ui/dist/assets/index-oivszLTx.js +0 -352
@@ -0,0 +1,145 @@
1
+ /**
2
+ * Vault Dashboard Generator
3
+ *
4
+ * Generates an Obsidian-compatible markdown file with Dataview plugin queries.
5
+ * The resulting file is written to Foundation/_dashboard.md inside the vault.
6
+ * Dataview handles all dynamic querying at render time — this function only
7
+ * produces the static template with embedded query blocks.
8
+ */
9
+ // =============================================================================
10
+ // Dashboard Generator
11
+ // =============================================================================
12
+ export function generateDashboard() {
13
+ const timestamp = new Date().toISOString();
14
+ return `# Foundation Memory Dashboard
15
+ > Auto-generated by \`foundation vault sync\`. Do not edit manually.
16
+ > Last sync: ${timestamp}
17
+
18
+ ---
19
+
20
+ ## Overview Stats
21
+
22
+ \`\`\`dataviewjs
23
+ const pages = dv.pages('"Foundation"').where(p => p.tier);
24
+ const tiers = ["session", "project", "global", "note", "observation"];
25
+
26
+ const rows = tiers.map(tier => {
27
+ const matches = pages.where(p => p.tier === tier);
28
+ const latest = matches.sort(p => p.created, "desc").first();
29
+ return [
30
+ tier,
31
+ matches.length,
32
+ latest ? latest.created : "—"
33
+ ];
34
+ }).filter(r => r[1] > 0);
35
+
36
+ dv.table(["Tier", "Count", "Latest Memory"], rows);
37
+ \`\`\`
38
+
39
+ ---
40
+
41
+ ## Recently Accessed
42
+
43
+ \`\`\`dataview
44
+ TABLE tier, tags, accessed, access_count
45
+ FROM "Foundation"
46
+ WHERE accessed != null
47
+ SORT accessed DESC
48
+ LIMIT 15
49
+ \`\`\`
50
+
51
+ ---
52
+
53
+ ## Most Connected
54
+
55
+ \`\`\`dataviewjs
56
+ const pages = dv.pages('"Foundation"');
57
+
58
+ const rows = pages
59
+ .map(p => {
60
+ const content = p.file.content ?? "";
61
+ const linkCount = (content.match(/\[\[/g) ?? []).length;
62
+ return [p.file.link, p.tier ?? "—", linkCount];
63
+ })
64
+ .sort(r => r[2], "desc")
65
+ .slice(0, 20);
66
+
67
+ dv.table(["Memory", "Tier", "Link Count"], rows);
68
+ \`\`\`
69
+
70
+ ---
71
+
72
+ ## Contradictions & Reverts
73
+
74
+ > Memories flagged with **contradicts** or **reverts** links — require human review.
75
+
76
+ \`\`\`dataviewjs
77
+ const pages = dv.pages('"Foundation"');
78
+
79
+ const flagged = pages.filter(p => {
80
+ const content = p.file.content ?? "";
81
+ return content.includes("**contradicts**") || content.includes("**reverts**");
82
+ });
83
+
84
+ if (flagged.length === 0) {
85
+ dv.paragraph("No contradictions or reverts detected.");
86
+ } else {
87
+ dv.list(flagged.map(p => p.file.link));
88
+ }
89
+ \`\`\`
90
+
91
+ ---
92
+
93
+ ## By Project
94
+
95
+ \`\`\`dataview
96
+ TABLE rows.file.link AS "Memories", length(rows) AS "Count"
97
+ FROM "Foundation"
98
+ WHERE project != null
99
+ GROUP BY project
100
+ SORT length(rows) DESC
101
+ \`\`\`
102
+
103
+ ---
104
+
105
+ ## Tag Cloud
106
+
107
+ \`\`\`dataviewjs
108
+ const pages = dv.pages('"Foundation"');
109
+
110
+ const tagCounts = {};
111
+ for (const page of pages) {
112
+ for (const tag of (page.tags ?? [])) {
113
+ tagCounts[tag] = (tagCounts[tag] ?? 0) + 1;
114
+ }
115
+ }
116
+
117
+ const sorted = Object.entries(tagCounts)
118
+ .sort((a, b) => b[1] - a[1]);
119
+
120
+ dv.list(sorted.map(([tag, count]) => \`\${tag} — \${count}\`));
121
+ \`\`\`
122
+
123
+ ---
124
+
125
+ ## Recent Sessions
126
+
127
+ \`\`\`dataview
128
+ TABLE tier, tags, created, access_count
129
+ FROM "Foundation/Sessions"
130
+ SORT created DESC
131
+ LIMIT 20
132
+ \`\`\`
133
+
134
+ ---
135
+
136
+ ## Knowledge Base
137
+
138
+ \`\`\`dataview
139
+ TABLE type, description
140
+ FROM "Knowledge"
141
+ SORT file.name ASC
142
+ \`\`\`
143
+ `;
144
+ }
145
+ //# sourceMappingURL=dashboard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dashboard.js","sourceRoot":"","sources":["../../src/vault/dashboard.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,gFAAgF;AAChF,sBAAsB;AACtB,gFAAgF;AAEhF,MAAM,UAAU,iBAAiB;IAC/B,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAE3C,OAAO;;eAEM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+HvB,CAAC;AACF,CAAC"}
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Vault Sync Engine
3
+ *
4
+ * Syncs Gaia memories from SQLite to an Obsidian vault as interlinked
5
+ * markdown files. Supports full and incremental sync, Claude Code memory
6
+ * file ingestion, and orphan cleanup.
7
+ */
8
+ export interface VaultConfig {
9
+ /** Absolute path to the Obsidian vault root. */
10
+ vaultPath: string;
11
+ /** Absolute path to the Gaia SQLite database. */
12
+ gaiaDbPath: string;
13
+ /** Absolute path to the sync state JSON file. */
14
+ syncStatePath: string;
15
+ /** Optional path to Claude Code memory directory (e.g. ~/.claude/projects/.../memory/). */
16
+ claudeMemoryPath?: string;
17
+ }
18
+ export interface SyncState {
19
+ vault_path: string;
20
+ last_full_sync: string;
21
+ synced_memories: Record<string, string>;
22
+ }
23
+ export interface SyncResult {
24
+ created: number;
25
+ updated: number;
26
+ deleted: number;
27
+ skipped: number;
28
+ errors: string[];
29
+ }
30
+ export declare class VaultSync {
31
+ private config;
32
+ constructor(config: VaultConfig);
33
+ /**
34
+ * Create the required folder structure in the vault and write an initial
35
+ * dashboard index file.
36
+ */
37
+ init(): Promise<void>;
38
+ /**
39
+ * Full sync: reads ALL memories from Gaia DB, transforms and writes every
40
+ * file, updates sync state. Also syncs Claude Code memory files if
41
+ * claudeMemoryPath is configured.
42
+ */
43
+ sync(): Promise<SyncResult>;
44
+ /**
45
+ * Incremental sync: only writes memories whose rendered content has changed
46
+ * since the last sync (detected via MD5 hash comparison).
47
+ */
48
+ syncIncremental(): Promise<SyncResult>;
49
+ /**
50
+ * Returns the current sync state, or null if no sync has run yet.
51
+ */
52
+ getStatus(): SyncState | null;
53
+ private loadSyncState;
54
+ private saveSyncState;
55
+ private hashContent;
56
+ private syncGaiaMemories;
57
+ private syncClaudeMemories;
58
+ /**
59
+ * Walk Foundation/ in the vault and remove .md files whose memory id is no
60
+ * longer in currentIds. Returns the number of files deleted.
61
+ */
62
+ private cleanOrphans;
63
+ }
64
+ //# sourceMappingURL=sync.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../src/vault/sync.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AA0BH,MAAM,WAAW,WAAW;IAC1B,gDAAgD;IAChD,SAAS,EAAE,MAAM,CAAC;IAClB,iDAAiD;IACjD,UAAU,EAAE,MAAM,CAAC;IACnB,iDAAiD;IACjD,aAAa,EAAE,MAAM,CAAC;IACtB,2FAA2F;IAC3F,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,SAAS;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACzC;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAoBD,qBAAa,SAAS;IACpB,OAAO,CAAC,MAAM,CAAc;gBAEhB,MAAM,EAAE,WAAW;IAQ/B;;;OAGG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAc3B;;;;OAIG;IACG,IAAI,IAAI,OAAO,CAAC,UAAU,CAAC;IAajC;;;OAGG;IACG,eAAe,IAAI,OAAO,CAAC,UAAU,CAAC;IAa5C;;OAEG;IACH,SAAS,IAAI,SAAS,GAAG,IAAI;IAa7B,OAAO,CAAC,aAAa;IAWrB,OAAO,CAAC,aAAa;IAarB,OAAO,CAAC,WAAW;YAQL,gBAAgB;YAwFhB,kBAAkB;IAoEhC;;;OAGG;IACH,OAAO,CAAC,YAAY;CAgDrB"}
@@ -0,0 +1,360 @@
1
+ /**
2
+ * Vault Sync Engine
3
+ *
4
+ * Syncs Gaia memories from SQLite to an Obsidian vault as interlinked
5
+ * markdown files. Supports full and incremental sync, Claude Code memory
6
+ * file ingestion, and orphan cleanup.
7
+ */
8
+ import { existsSync, mkdirSync, writeFileSync, readFileSync, readdirSync, unlinkSync, statSync, } from 'fs';
9
+ import { join } from 'path';
10
+ import { createHash } from 'crypto';
11
+ import { parse as parseYaml } from 'yaml';
12
+ import { MemoriaStorage } from '../tools/gaia/storage.js';
13
+ import { transformMemory, memoryToFilename, memoryToFolderPath, } from './transform.js';
14
+ import { generateDashboard } from './dashboard.js';
15
+ // =============================================================================
16
+ // Folder Scaffold
17
+ // =============================================================================
18
+ const VAULT_FOLDERS = [
19
+ 'Foundation',
20
+ 'Foundation/Global',
21
+ 'Foundation/Projects',
22
+ 'Foundation/Sessions',
23
+ 'Foundation/Notes',
24
+ 'Foundation/Observations',
25
+ 'Knowledge',
26
+ ];
27
+ // =============================================================================
28
+ // VaultSync
29
+ // =============================================================================
30
+ export class VaultSync {
31
+ config;
32
+ constructor(config) {
33
+ this.config = config;
34
+ }
35
+ // ---------------------------------------------------------------------------
36
+ // Public API
37
+ // ---------------------------------------------------------------------------
38
+ /**
39
+ * Create the required folder structure in the vault and write an initial
40
+ * dashboard index file.
41
+ */
42
+ async init() {
43
+ for (const folder of VAULT_FOLDERS) {
44
+ const fullPath = join(this.config.vaultPath, folder);
45
+ if (!existsSync(fullPath)) {
46
+ mkdirSync(fullPath, { recursive: true });
47
+ }
48
+ }
49
+ const dashboardPath = join(this.config.vaultPath, 'Foundation', '_dashboard.md');
50
+ if (!existsSync(dashboardPath)) {
51
+ writeFileSync(dashboardPath, generateDashboard(), 'utf8');
52
+ }
53
+ }
54
+ /**
55
+ * Full sync: reads ALL memories from Gaia DB, transforms and writes every
56
+ * file, updates sync state. Also syncs Claude Code memory files if
57
+ * claudeMemoryPath is configured.
58
+ */
59
+ async sync() {
60
+ await this.init();
61
+ const gaiaResult = await this.syncGaiaMemories(false);
62
+ let claudeResult = { created: 0, updated: 0, deleted: 0, skipped: 0, errors: [] };
63
+ if (this.config.claudeMemoryPath) {
64
+ claudeResult = await this.syncClaudeMemories();
65
+ }
66
+ return mergeResults(gaiaResult, claudeResult);
67
+ }
68
+ /**
69
+ * Incremental sync: only writes memories whose rendered content has changed
70
+ * since the last sync (detected via MD5 hash comparison).
71
+ */
72
+ async syncIncremental() {
73
+ await this.init();
74
+ const gaiaResult = await this.syncGaiaMemories(true);
75
+ let claudeResult = { created: 0, updated: 0, deleted: 0, skipped: 0, errors: [] };
76
+ if (this.config.claudeMemoryPath) {
77
+ claudeResult = await this.syncClaudeMemories();
78
+ }
79
+ return mergeResults(gaiaResult, claudeResult);
80
+ }
81
+ /**
82
+ * Returns the current sync state, or null if no sync has run yet.
83
+ */
84
+ getStatus() {
85
+ if (!existsSync(this.config.syncStatePath))
86
+ return null;
87
+ try {
88
+ return JSON.parse(readFileSync(this.config.syncStatePath, 'utf8'));
89
+ }
90
+ catch {
91
+ return null;
92
+ }
93
+ }
94
+ // ---------------------------------------------------------------------------
95
+ // Private: State Management
96
+ // ---------------------------------------------------------------------------
97
+ loadSyncState() {
98
+ const existing = this.getStatus();
99
+ if (existing)
100
+ return existing;
101
+ return {
102
+ vault_path: this.config.vaultPath,
103
+ last_full_sync: new Date(0).toISOString(),
104
+ synced_memories: {},
105
+ };
106
+ }
107
+ saveSyncState(state) {
108
+ const dir = join(this.config.syncStatePath, '..');
109
+ // syncStatePath may point to a file whose parent dir doesn't exist yet
110
+ if (!existsSync(dir)) {
111
+ mkdirSync(dir, { recursive: true });
112
+ }
113
+ writeFileSync(this.config.syncStatePath, JSON.stringify(state, null, 2), 'utf8');
114
+ }
115
+ // ---------------------------------------------------------------------------
116
+ // Private: Hashing
117
+ // ---------------------------------------------------------------------------
118
+ hashContent(content) {
119
+ return createHash('md5').update(content).digest('hex');
120
+ }
121
+ // ---------------------------------------------------------------------------
122
+ // Private: Gaia Sync
123
+ // ---------------------------------------------------------------------------
124
+ async syncGaiaMemories(incremental) {
125
+ const result = { created: 0, updated: 0, deleted: 0, skipped: 0, errors: [] };
126
+ const state = this.loadSyncState();
127
+ let storage = null;
128
+ try {
129
+ storage = new MemoriaStorage(this.config.gaiaDbPath);
130
+ const memories = storage.getAllMemories();
131
+ const links = storage.getAllLinks();
132
+ // Build lookup maps
133
+ const memoryMap = new Map(memories.map(m => [m.id, m]));
134
+ const linksBySource = new Map();
135
+ for (const link of links) {
136
+ const bucket = linksBySource.get(link.from_memory_id) ?? [];
137
+ bucket.push(link);
138
+ linksBySource.set(link.from_memory_id, bucket);
139
+ }
140
+ const currentIds = new Set();
141
+ for (const memory of memories) {
142
+ currentIds.add(memory.id);
143
+ try {
144
+ const memLinks = linksBySource.get(memory.id) ?? [];
145
+ const markdown = transformMemory(memory, memLinks, memoryMap);
146
+ const hash = this.hashContent(markdown);
147
+ // In incremental mode, skip if content unchanged
148
+ if (incremental && state.synced_memories[memory.id] === hash) {
149
+ result.skipped++;
150
+ continue;
151
+ }
152
+ const folderPath = memoryToFolderPath(memory, this.config.vaultPath);
153
+ const filename = memoryToFilename(memory);
154
+ const filePath = join(folderPath, filename);
155
+ if (!existsSync(folderPath)) {
156
+ mkdirSync(folderPath, { recursive: true });
157
+ }
158
+ const isNew = !state.synced_memories[memory.id];
159
+ writeFileSync(filePath, markdown, 'utf8');
160
+ state.synced_memories[memory.id] = hash;
161
+ if (isNew) {
162
+ result.created++;
163
+ }
164
+ else {
165
+ result.updated++;
166
+ }
167
+ }
168
+ catch (err) {
169
+ const msg = err instanceof Error ? err.message : String(err);
170
+ result.errors.push(`[${memory.id}] ${msg}`);
171
+ }
172
+ }
173
+ // Clean up orphaned vault files for deleted memories
174
+ result.deleted = this.cleanOrphans(currentIds, state);
175
+ // Prune deleted memory ids from state
176
+ for (const id of Object.keys(state.synced_memories)) {
177
+ if (!currentIds.has(id)) {
178
+ delete state.synced_memories[id];
179
+ }
180
+ }
181
+ state.last_full_sync = new Date().toISOString();
182
+ this.saveSyncState(state);
183
+ }
184
+ catch (err) {
185
+ const msg = err instanceof Error ? err.message : String(err);
186
+ result.errors.push(`[fatal] ${msg}`);
187
+ }
188
+ finally {
189
+ storage?.close();
190
+ }
191
+ return result;
192
+ }
193
+ // ---------------------------------------------------------------------------
194
+ // Private: Claude Code Memory Sync
195
+ // ---------------------------------------------------------------------------
196
+ async syncClaudeMemories() {
197
+ const result = { created: 0, updated: 0, deleted: 0, skipped: 0, errors: [] };
198
+ const claudeMemoryPath = this.config.claudeMemoryPath;
199
+ if (!claudeMemoryPath || !existsSync(claudeMemoryPath)) {
200
+ return result;
201
+ }
202
+ let files;
203
+ try {
204
+ files = readdirSync(claudeMemoryPath).filter(f => f.endsWith('.md'));
205
+ }
206
+ catch (err) {
207
+ const msg = err instanceof Error ? err.message : String(err);
208
+ result.errors.push(`[claude-memory] Failed to read directory: ${msg}`);
209
+ return result;
210
+ }
211
+ for (const filename of files) {
212
+ try {
213
+ const sourcePath = join(claudeMemoryPath, filename);
214
+ const rawContent = readFileSync(sourcePath, 'utf8');
215
+ // Parse YAML frontmatter to extract type for folder routing
216
+ const { frontmatter, body } = extractFrontmatter(rawContent);
217
+ let type = 'general';
218
+ if (frontmatter) {
219
+ try {
220
+ const parsed = parseYaml(frontmatter);
221
+ if (typeof parsed['type'] === 'string') {
222
+ type = parsed['type'];
223
+ }
224
+ }
225
+ catch {
226
+ // Unparseable frontmatter — fall back to default type
227
+ }
228
+ }
229
+ // Build enhanced markdown with source field injected into frontmatter
230
+ const enhanced = injectFrontmatterField(rawContent, 'source', 'claude-code');
231
+ const targetDir = join(this.config.vaultPath, 'Knowledge', type);
232
+ if (!existsSync(targetDir)) {
233
+ mkdirSync(targetDir, { recursive: true });
234
+ }
235
+ const targetPath = join(targetDir, filename);
236
+ const existed = existsSync(targetPath);
237
+ writeFileSync(targetPath, enhanced, 'utf8');
238
+ if (existed) {
239
+ result.updated++;
240
+ }
241
+ else {
242
+ result.created++;
243
+ }
244
+ }
245
+ catch (err) {
246
+ const msg = err instanceof Error ? err.message : String(err);
247
+ result.errors.push(`[claude-memory/${filename}] ${msg}`);
248
+ }
249
+ }
250
+ return result;
251
+ }
252
+ // ---------------------------------------------------------------------------
253
+ // Private: Orphan Cleanup
254
+ // ---------------------------------------------------------------------------
255
+ /**
256
+ * Walk Foundation/ in the vault and remove .md files whose memory id is no
257
+ * longer in currentIds. Returns the number of files deleted.
258
+ */
259
+ cleanOrphans(currentIds, state) {
260
+ let deleted = 0;
261
+ const foundationRoot = join(this.config.vaultPath, 'Foundation');
262
+ if (!existsSync(foundationRoot))
263
+ return 0;
264
+ const walkAndClean = (dir) => {
265
+ let entries;
266
+ try {
267
+ entries = readdirSync(dir);
268
+ }
269
+ catch {
270
+ return;
271
+ }
272
+ for (const entry of entries) {
273
+ const fullPath = join(dir, entry);
274
+ let isDir = false;
275
+ try {
276
+ isDir = statSync(fullPath).isDirectory();
277
+ }
278
+ catch {
279
+ continue;
280
+ }
281
+ if (isDir) {
282
+ walkAndClean(fullPath);
283
+ }
284
+ else if (entry.endsWith('.md')) {
285
+ // Extract memory id from filename: e.g. mem_abc123-some-slug.md
286
+ const match = entry.match(/^(mem_[A-Za-z0-9_-]+?)(?:-|\.md)/);
287
+ if (match) {
288
+ const id = match[1];
289
+ if (id && !currentIds.has(id)) {
290
+ try {
291
+ unlinkSync(fullPath);
292
+ deleted++;
293
+ }
294
+ catch {
295
+ // File may have already been removed — ignore
296
+ }
297
+ }
298
+ }
299
+ }
300
+ }
301
+ };
302
+ walkAndClean(foundationRoot);
303
+ return deleted;
304
+ }
305
+ }
306
+ // =============================================================================
307
+ // Utility Functions
308
+ // =============================================================================
309
+ function mergeResults(a, b) {
310
+ return {
311
+ created: a.created + b.created,
312
+ updated: a.updated + b.updated,
313
+ deleted: a.deleted + b.deleted,
314
+ skipped: a.skipped + b.skipped,
315
+ errors: [...a.errors, ...b.errors],
316
+ };
317
+ }
318
+ /**
319
+ * Split a markdown file into its YAML frontmatter block and body.
320
+ * Returns { frontmatter: string | null, body: string }.
321
+ */
322
+ function extractFrontmatter(content) {
323
+ if (!content.startsWith('---')) {
324
+ return { frontmatter: null, body: content };
325
+ }
326
+ const end = content.indexOf('\n---', 3);
327
+ if (end === -1) {
328
+ return { frontmatter: null, body: content };
329
+ }
330
+ const frontmatter = content.slice(4, end).trim();
331
+ const body = content.slice(end + 4).trimStart();
332
+ return { frontmatter, body };
333
+ }
334
+ /**
335
+ * Inject a key: value pair into a markdown file's YAML frontmatter.
336
+ * If no frontmatter exists, one is created. If the key already exists,
337
+ * it is left unchanged.
338
+ */
339
+ function injectFrontmatterField(content, key, value) {
340
+ if (!content.startsWith('---')) {
341
+ // No frontmatter — prepend one
342
+ return `---\n${key}: ${value}\n---\n\n${content}`;
343
+ }
344
+ const end = content.indexOf('\n---', 3);
345
+ if (end === -1) {
346
+ return `---\n${key}: ${value}\n---\n\n${content}`;
347
+ }
348
+ const frontmatterBlock = content.slice(0, end + 4);
349
+ const rest = content.slice(end + 4);
350
+ // Only inject if key is absent
351
+ if (new RegExp(`^${key}:`, 'm').test(frontmatterBlock)) {
352
+ return content;
353
+ }
354
+ // Insert before closing ---
355
+ const insertionPoint = end;
356
+ return (content.slice(0, insertionPoint) +
357
+ `\n${key}: ${value}` +
358
+ content.slice(insertionPoint));
359
+ }
360
+ //# sourceMappingURL=sync.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync.js","sourceRoot":"","sources":["../../src/vault/sync.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Vault Transform Layer
3
+ *
4
+ * Converts Gaia Memory objects into Obsidian-compatible markdown files
5
+ * with YAML frontmatter and [[wikilink]] cross-references.
6
+ */
7
+ import type { Memory, MemoryLink } from '../tools/gaia/storage.js';
8
+ /**
9
+ * Returns a filesystem-safe filename for a memory.
10
+ * Format: `<id>-<slug>.md`
11
+ */
12
+ export declare function memoryToFilename(memory: Memory): string;
13
+ /**
14
+ * Returns the target folder path in the vault for a given memory, based on tier.
15
+ */
16
+ export declare function memoryToFolderPath(memory: Memory, vaultRoot: string): string;
17
+ /**
18
+ * Transforms a Memory and its links into a full Obsidian markdown string.
19
+ *
20
+ * @param memory The memory to transform
21
+ * @param links All MemoryLink rows where from_memory_id === memory.id
22
+ * @param allMemories Map of id → Memory for resolving link targets
23
+ */
24
+ export declare function transformMemory(memory: Memory, links: MemoryLink[], allMemories: Map<string, Memory>): string;
25
+ //# sourceMappingURL=transform.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transform.d.ts","sourceRoot":"","sources":["../../src/vault/transform.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAiDnE;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAOvD;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAyB5E;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,UAAU,EAAE,EACnB,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B,MAAM,CA4ER"}