diff --git a/CHANGELOG.md b/CHANGELOG.md index 15fd0fa93..207be5ffe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,12 @@ All notable changes to GBrain will be documented in this file. +## [0.9.2] - 2026-04-12 + +### Fixed + +- **Fresh local installs initialize cleanly again.** `gbrain init` now creates the local PGLite data directory before taking its advisory lock, so first-run setup no longer misreports a missing directory as a lock timeout. + ## [0.9.1] - 2026-04-11 ### Fixed diff --git a/VERSION b/VERSION index f374f6662..2003b639c 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.9.1 +0.9.2 diff --git a/package.json b/package.json index 532e59068..1acb742e0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gbrain", - "version": "0.9.1", + "version": "0.9.2", "description": "Postgres-native personal knowledge brain with hybrid RAG search", "type": "module", "main": "src/core/index.ts", diff --git a/src/core/pglite-lock.ts b/src/core/pglite-lock.ts index cd6b94a1c..440e4304f 100644 --- a/src/core/pglite-lock.ts +++ b/src/core/pglite-lock.ts @@ -59,6 +59,8 @@ export async function acquireLock(dataDir: string | undefined, opts?: { timeoutM return { lockDir: '', acquired: true }; } + mkdirSync(dataDir, { recursive: true }); + const timeoutMs = opts?.timeoutMs ?? 30_000; // 30 second default timeout const startTime = Date.now(); diff --git a/test/pglite-lock.test.ts b/test/pglite-lock.test.ts index d4acffe68..3253aa41b 100644 --- a/test/pglite-lock.test.ts +++ b/test/pglite-lock.test.ts @@ -26,6 +26,18 @@ describe('pglite-lock', () => { expect(existsSync(join(TEST_DIR, '.gbrain-lock'))).toBe(false); }); + test('creates missing data directory before acquiring lock', async () => { + const missingDataDir = join(TEST_DIR, 'missing-data-dir'); + + const lock = await acquireLock(missingDataDir); + expect(lock.acquired).toBe(true); + expect(existsSync(missingDataDir)).toBe(true); + expect(existsSync(join(missingDataDir, '.gbrain-lock'))).toBe(true); + + await releaseLock(lock); + expect(existsSync(join(missingDataDir, '.gbrain-lock'))).toBe(false); + }); + test('prevents concurrent lock acquisition', async () => { const lock1 = await acquireLock(TEST_DIR, { timeoutMs: 2000 }); expect(lock1.acquired).toBe(true);