diff --git a/packages/cli/src/managed-python-runtime.test.ts b/packages/cli/src/managed-python-runtime.test.ts index 35691e51..b63b6c19 100644 --- a/packages/cli/src/managed-python-runtime.test.ts +++ b/packages/cli/src/managed-python-runtime.test.ts @@ -70,6 +70,19 @@ describe('managedPythonRuntimeLayout', () => { expect(layout.assetManifestPath).toBe('/repo/packages/cli/assets/python/manifest.json'); }); + it('honors KTX_RUNTIME_ROOT before platform defaults', () => { + const layout = managedPythonRuntimeLayout({ + cliVersion: '0.2.0', + platform: 'darwin', + env: { KTX_RUNTIME_ROOT: '/tmp/ktx-runtime' }, + homeDir: '/Users/alex', + assetDir: '/repo/packages/cli/assets/python', + }); + + expect(layout.runtimeRoot).toBe('/tmp/ktx-runtime'); + expect(layout.versionDir).toBe('/tmp/ktx-runtime/0.2.0'); + }); + it('honors XDG_DATA_HOME on Linux', () => { const layout = managedPythonRuntimeLayout({ cliVersion: '0.2.0', diff --git a/packages/cli/src/managed-python-runtime.ts b/packages/cli/src/managed-python-runtime.ts index 155b44e4..e78e8a76 100644 --- a/packages/cli/src/managed-python-runtime.ts +++ b/packages/cli/src/managed-python-runtime.ts @@ -119,6 +119,9 @@ function defaultAssetDir(): string { } function runtimeRootFor(input: Required>): string { + if (input.env.KTX_RUNTIME_ROOT) { + return input.env.KTX_RUNTIME_ROOT; + } if (input.platform === 'darwin') { return join(input.homeDir, 'Library', 'Application Support', 'kaelio', 'ktx', 'runtime'); } diff --git a/scripts/package-artifacts.mjs b/scripts/package-artifacts.mjs index c3a339a1..8f38cf0b 100644 --- a/scripts/package-artifacts.mjs +++ b/scripts/package-artifacts.mjs @@ -569,6 +569,9 @@ export function npmSmokePackageJson(layout) { dependencies: { '@kaelio/ktx': `file:${layout.cliTarball}`, }, + devDependencies: { + 'better-sqlite3': '^12.6.2', + }, pnpm: { onlyBuiltDependencies: ['better-sqlite3'], }, @@ -927,7 +930,7 @@ try { requireSuccessWithStderr( 'ktx sl query first managed runtime install', slQuery, - /Installing KTX Python runtime \(core\) with uv[\\s\\S]*KTX Python runtime ready:/, + /Installing KTX Python runtime \\(core\\) with uv[\\s\\S]*KTX Python runtime ready:/, ); requireOutput('ktx sl query first managed runtime install', slQuery, /"mode": "compile_only"/); requireOutput('ktx sl query first managed runtime install', slQuery, /orders/); diff --git a/scripts/package-artifacts.test.mjs b/scripts/package-artifacts.test.mjs index ef168a54..c4b36b09 100644 --- a/scripts/package-artifacts.test.mjs +++ b/scripts/package-artifacts.test.mjs @@ -513,9 +513,13 @@ describe('verification snippets', () => { it('pins the smoke project to the public package artifact', () => { const layout = packageArtifactLayout('/repo/ktx'); - assert.deepEqual(npmSmokePackageJson(layout).dependencies, { + const packageJson = npmSmokePackageJson(layout); + assert.deepEqual(packageJson.dependencies, { '@kaelio/ktx': `file:${layout.cliTarball}`, }); + assert.deepEqual(packageJson.devDependencies, { + 'better-sqlite3': '^12.6.2', + }); }); it('exposes manifest verification as a package artifact command', async () => { @@ -568,7 +572,7 @@ describe('verification snippets', () => { assert.match(source, /managed-runtime/); assert.match(source, /ktx runtime status missing/); assert.match(source, /runtimeStatusBefore\.kind, 'missing'/); - assert.match(source, /Installing KTX Python runtime \(core\) with uv/); + assert.ok(source.includes(String.raw`Installing KTX Python runtime \(core\) with uv`)); assert.match(source, /KTX Python runtime ready:/); assert.match(source, /ktx runtime status ready/); assert.match(source, /runtimeStatusAfter\.kind, 'ready'/);