@kaelio/ktx 0.1.0 → 0.1.1

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 (63) hide show
  1. package/assets/python/{kaelio_ktx-0.1.0-py3-none-any.whl → kaelio_ktx-0.1.1-py3-none-any.whl} +0 -0
  2. package/assets/python/manifest.json +4 -4
  3. package/dist/commands/setup-commands.js +14 -26
  4. package/dist/doctor.test.js +3 -4
  5. package/dist/index.test.js +26 -10
  6. package/dist/ingest-depth.js +0 -1
  7. package/dist/ingest.test-utils.js +2 -2
  8. package/dist/ingest.test.js +4 -4
  9. package/dist/managed-local-embeddings.d.ts +2 -0
  10. package/dist/managed-local-embeddings.js +2 -0
  11. package/dist/managed-local-embeddings.test.js +2 -0
  12. package/dist/managed-mcp-daemon.js +3 -2
  13. package/dist/managed-mcp-daemon.test.js +25 -0
  14. package/dist/managed-python-command.test.js +1 -0
  15. package/dist/managed-python-daemon.js +3 -2
  16. package/dist/managed-python-daemon.test.js +20 -0
  17. package/dist/managed-python-runtime.d.ts +4 -0
  18. package/dist/managed-python-runtime.js +47 -3
  19. package/dist/managed-python-runtime.test.js +51 -21
  20. package/dist/proxy-env.d.ts +1 -0
  21. package/dist/proxy-env.js +23 -0
  22. package/dist/proxy-env.test.d.ts +1 -0
  23. package/dist/proxy-env.test.js +17 -0
  24. package/dist/runtime.test.js +1 -0
  25. package/dist/setup-agents.js +3 -1
  26. package/dist/setup-agents.test.js +34 -0
  27. package/dist/setup-embeddings.d.ts +1 -0
  28. package/dist/setup-embeddings.js +28 -6
  29. package/dist/setup-embeddings.test.js +46 -4
  30. package/dist/setup-models.d.ts +0 -1
  31. package/dist/setup-models.js +2 -3
  32. package/dist/setup-models.test.js +8 -10
  33. package/dist/setup-project.d.ts +9 -1
  34. package/dist/setup-project.js +52 -25
  35. package/dist/setup-project.test.js +8 -8
  36. package/dist/setup-runtime.test.js +2 -0
  37. package/dist/setup.d.ts +1 -2
  38. package/dist/setup.js +21 -5
  39. package/dist/setup.test.js +160 -43
  40. package/dist/sl.test.js +2 -1
  41. package/dist/standalone-smoke.test.js +2 -3
  42. package/dist/status-project.js +1 -10
  43. package/node_modules/@ktx/context/dist/ingest/adapters/historic-sql/local-ingest-acceptance.test.js +1 -1
  44. package/node_modules/@ktx/context/dist/ingest/local-bundle-ingest.test.js +8 -8
  45. package/node_modules/@ktx/context/dist/ingest/local-bundle-runtime.js +1 -1
  46. package/node_modules/@ktx/context/dist/ingest/local-bundle-runtime.test.js +3 -3
  47. package/node_modules/@ktx/context/dist/ingest/local-embedding-provider.integration.test.js +9 -10
  48. package/node_modules/@ktx/context/dist/llm/local-config.js +2 -15
  49. package/node_modules/@ktx/context/dist/llm/local-config.test.js +3 -7
  50. package/node_modules/@ktx/context/dist/project/config.d.ts +0 -5
  51. package/node_modules/@ktx/context/dist/project/config.js +5 -5
  52. package/node_modules/@ktx/context/dist/project/config.test.js +4 -7
  53. package/node_modules/@ktx/context/dist/scan/enrichment-state.test.js +4 -4
  54. package/node_modules/@ktx/context/dist/scan/index.d.ts +1 -1
  55. package/node_modules/@ktx/context/dist/scan/local-enrichment.d.ts +2 -6
  56. package/node_modules/@ktx/context/dist/scan/local-enrichment.js +31 -47
  57. package/node_modules/@ktx/context/dist/scan/local-enrichment.test.js +35 -18
  58. package/node_modules/@ktx/context/dist/scan/local-scan.test.js +2 -3
  59. package/node_modules/@ktx/llm/dist/embedding-provider.d.ts +0 -7
  60. package/node_modules/@ktx/llm/dist/embedding-provider.js +12 -138
  61. package/node_modules/@ktx/llm/dist/embedding-provider.test.js +10 -25
  62. package/node_modules/@ktx/llm/dist/types.d.ts +1 -1
  63. package/package.json +1 -1
@@ -1,5 +1,5 @@
1
1
  import { execFile } from 'node:child_process';
2
- import { mkdir, mkdtemp, readFile, rm, stat, writeFile } from 'node:fs/promises';
2
+ import { mkdir, mkdtemp, readFile, readdir, rm, stat, writeFile } from 'node:fs/promises';
3
3
  import { tmpdir } from 'node:os';
4
4
  import { join } from 'node:path';
5
5
  import { promisify } from 'node:util';
@@ -88,7 +88,7 @@ describe('setup status', () => {
88
88
  agents: [],
89
89
  });
90
90
  });
91
- it('reports deterministic default embeddings as not setup-ready', async () => {
91
+ it('reports disabled default embeddings as not setup-ready', async () => {
92
92
  await mkdir(tempDir, { recursive: true });
93
93
  await writeFile(join(tempDir, 'ktx.yaml'), [
94
94
  'llm:',
@@ -100,15 +100,14 @@ describe('setup status', () => {
100
100
  ' default: claude-sonnet-4-6',
101
101
  'ingest:',
102
102
  ' embeddings:',
103
- ' backend: deterministic',
104
- ' model: deterministic',
103
+ ' backend: none',
105
104
  ' dimensions: 8',
106
105
  'connections: {}',
107
106
  ].join('\n'), 'utf-8');
108
107
  await expect(readKtxSetupStatus(tempDir)).resolves.toMatchObject({
109
108
  project: { path: tempDir, ready: true },
110
109
  llm: { backend: 'anthropic', ready: true, model: 'claude-sonnet-4-6' },
111
- embeddings: { backend: 'deterministic', ready: false, model: 'deterministic', dimensions: 8 },
110
+ embeddings: { backend: 'none', ready: false, dimensions: 8 },
112
111
  });
113
112
  });
114
113
  it.each([
@@ -299,8 +298,7 @@ describe('setup status', () => {
299
298
  ' default: claude-sonnet-4-6',
300
299
  'ingest:',
301
300
  ' embeddings:',
302
- ' backend: deterministic',
303
- ' model: deterministic',
301
+ ' backend: none',
304
302
  ' dimensions: 8',
305
303
  '',
306
304
  ].join('\n'), 'utf-8');
@@ -387,7 +385,7 @@ describe('setup status', () => {
387
385
  await expect(runKtxSetup({
388
386
  command: 'run',
389
387
  projectDir: tempDir,
390
- mode: 'new',
388
+ mode: 'auto',
391
389
  agents: false,
392
390
  target: 'claude-code',
393
391
  skipAgents: false,
@@ -456,6 +454,85 @@ describe('setup status', () => {
456
454
  expect(testIo.stdout()).not.toContain('Optional MCP:');
457
455
  expect(testIo.stderr()).toBe('');
458
456
  });
457
+ it('removes a newly created missing project directory when a later runtime step fails', async () => {
458
+ const projectDir = join(tempDir, 'missing-project');
459
+ const testIo = makeIo();
460
+ await expect(runKtxSetup({
461
+ command: 'run',
462
+ projectDir,
463
+ mode: 'auto',
464
+ agents: false,
465
+ skipAgents: true,
466
+ inputMode: 'disabled',
467
+ yes: true,
468
+ cliVersion: '0.2.0',
469
+ skipLlm: true,
470
+ skipEmbeddings: true,
471
+ databaseSchemas: [],
472
+ skipDatabases: true,
473
+ skipSources: true,
474
+ }, testIo.io, {
475
+ model: async () => ({ status: 'skipped', projectDir }),
476
+ embeddings: async () => ({ status: 'skipped', projectDir }),
477
+ databases: async () => ({ status: 'skipped', projectDir }),
478
+ sources: async () => ({ status: 'skipped', projectDir }),
479
+ runtime: async () => ({ status: 'failed', projectDir, requirements: { features: ['core'], requirements: [] } }),
480
+ })).resolves.toBe(1);
481
+ await expect(stat(projectDir)).rejects.toThrow();
482
+ });
483
+ it('removes KTX scaffold files from an initially empty project directory when runtime setup fails', async () => {
484
+ const testIo = makeIo();
485
+ await expect(runKtxSetup({
486
+ command: 'run',
487
+ projectDir: tempDir,
488
+ mode: 'auto',
489
+ agents: false,
490
+ skipAgents: true,
491
+ inputMode: 'disabled',
492
+ yes: true,
493
+ cliVersion: '0.2.0',
494
+ skipLlm: true,
495
+ skipEmbeddings: true,
496
+ databaseSchemas: [],
497
+ skipDatabases: true,
498
+ skipSources: true,
499
+ }, testIo.io, {
500
+ model: async () => ({ status: 'skipped', projectDir: tempDir }),
501
+ embeddings: async () => ({ status: 'skipped', projectDir: tempDir }),
502
+ databases: async () => ({ status: 'skipped', projectDir: tempDir }),
503
+ sources: async () => ({ status: 'skipped', projectDir: tempDir }),
504
+ runtime: async () => ({ status: 'failed', projectDir: tempDir, requirements: { features: ['core'], requirements: [] } }),
505
+ })).resolves.toBe(1);
506
+ await expect(stat(tempDir)).resolves.toBeDefined();
507
+ expect(await readdir(tempDir)).toEqual([]);
508
+ });
509
+ it('preserves a pre-existing non-empty project directory when runtime setup fails', async () => {
510
+ await writeFile(join(tempDir, 'notes.txt'), 'keep me\n', 'utf-8');
511
+ const testIo = makeIo();
512
+ await expect(runKtxSetup({
513
+ command: 'run',
514
+ projectDir: tempDir,
515
+ mode: 'auto',
516
+ agents: false,
517
+ skipAgents: true,
518
+ inputMode: 'disabled',
519
+ yes: true,
520
+ cliVersion: '0.2.0',
521
+ skipLlm: true,
522
+ skipEmbeddings: true,
523
+ databaseSchemas: [],
524
+ skipDatabases: true,
525
+ skipSources: true,
526
+ }, testIo.io, {
527
+ model: async () => ({ status: 'skipped', projectDir: tempDir }),
528
+ embeddings: async () => ({ status: 'skipped', projectDir: tempDir }),
529
+ databases: async () => ({ status: 'skipped', projectDir: tempDir }),
530
+ sources: async () => ({ status: 'skipped', projectDir: tempDir }),
531
+ runtime: async () => ({ status: 'failed', projectDir: tempDir, requirements: { features: ['core'], requirements: [] } }),
532
+ })).resolves.toBe(1);
533
+ await expect(readFile(join(tempDir, 'notes.txt'), 'utf-8')).resolves.toBe('keep me\n');
534
+ await expect(stat(join(tempDir, 'ktx.yaml'))).resolves.toBeDefined();
535
+ });
459
536
  it('shows demo near the bottom of the first setup intent menu before project creation', async () => {
460
537
  const testIo = makeIo();
461
538
  const select = vi.fn(async (options) => {
@@ -750,16 +827,16 @@ describe('setup status', () => {
750
827
  }, testIo.io, { entryMenuDeps: { prompts: { select: vi.fn(async () => 'demo'), cancel: vi.fn() } } })).resolves.toBe(0);
751
828
  expect(runDemoTour).toHaveBeenCalledWith({ inputMode: 'auto' }, testIo.io, expect.objectContaining({}));
752
829
  });
753
- it('creates a project through run mode when --new is selected', async () => {
830
+ it('creates a project through run mode when --yes is selected', async () => {
754
831
  const testIo = makeIo();
755
832
  await expect(runKtxSetup({
756
833
  command: 'run',
757
834
  projectDir: tempDir,
758
- mode: 'new',
835
+ mode: 'auto',
759
836
  agents: false,
760
837
  skipAgents: true,
761
838
  inputMode: 'disabled',
762
- yes: false,
839
+ yes: true,
763
840
  cliVersion: '0.2.0',
764
841
  skipLlm: true,
765
842
  skipEmbeddings: true,
@@ -821,14 +898,14 @@ describe('setup status', () => {
821
898
  await expect(runKtxSetup({
822
899
  command: 'run',
823
900
  projectDir: tempDir,
824
- mode: 'new',
901
+ mode: 'auto',
825
902
  agents: false,
826
903
  skipAgents: true,
827
904
  inputMode: 'disabled',
828
- yes: false,
905
+ yes: true,
829
906
  cliVersion: '0.2.0',
830
907
  anthropicApiKeyEnv: 'ANTHROPIC_API_KEY', // pragma: allowlist secret
831
- anthropicModel: 'claude-sonnet-4-6',
908
+ llmModel: 'claude-sonnet-4-6',
832
909
  skipLlm: false,
833
910
  skipEmbeddings: true,
834
911
  databaseSchemas: [],
@@ -839,7 +916,7 @@ describe('setup status', () => {
839
916
  projectDir: tempDir,
840
917
  inputMode: 'disabled',
841
918
  anthropicApiKeyEnv: 'ANTHROPIC_API_KEY', // pragma: allowlist secret
842
- anthropicModel: 'claude-sonnet-4-6',
919
+ llmModel: 'claude-sonnet-4-6',
843
920
  skipLlm: false,
844
921
  }), testIo.io);
845
922
  });
@@ -849,16 +926,16 @@ describe('setup status', () => {
849
926
  await expect(runKtxSetup({
850
927
  command: 'run',
851
928
  projectDir: tempDir,
852
- mode: 'new',
929
+ mode: 'auto',
853
930
  agents: false,
854
931
  skipAgents: true,
855
932
  inputMode: 'disabled',
856
- yes: false,
933
+ yes: true,
857
934
  cliVersion: '0.2.0',
858
935
  llmBackend: 'vertex',
859
936
  vertexProject: 'local-gcp-project',
860
937
  vertexLocation: 'us-east5',
861
- anthropicModel: 'claude-sonnet-4-6',
938
+ llmModel: 'claude-sonnet-4-6',
862
939
  skipLlm: false,
863
940
  skipEmbeddings: true,
864
941
  databaseSchemas: [],
@@ -871,7 +948,7 @@ describe('setup status', () => {
871
948
  llmBackend: 'vertex',
872
949
  vertexProject: 'local-gcp-project',
873
950
  vertexLocation: 'us-east5',
874
- anthropicModel: 'claude-sonnet-4-6',
951
+ llmModel: 'claude-sonnet-4-6',
875
952
  skipLlm: false,
876
953
  }), testIo.io);
877
954
  });
@@ -882,14 +959,14 @@ describe('setup status', () => {
882
959
  await expect(runKtxSetup({
883
960
  command: 'run',
884
961
  projectDir: tempDir,
885
- mode: 'new',
962
+ mode: 'auto',
886
963
  agents: false,
887
964
  skipAgents: true,
888
965
  inputMode: 'disabled',
889
966
  yes: true,
890
967
  cliVersion: '0.2.0',
891
968
  anthropicApiKeyEnv: 'ANTHROPIC_API_KEY', // pragma: allowlist secret
892
- anthropicModel: 'claude-sonnet-4-6',
969
+ llmModel: 'claude-sonnet-4-6',
893
970
  skipLlm: false,
894
971
  embeddingBackend: 'openai',
895
972
  embeddingApiKeyEnv: 'OPENAI_API_KEY', // pragma: allowlist secret
@@ -911,10 +988,11 @@ describe('setup status', () => {
911
988
  it('passes no-input runtime policy to the embeddings step', async () => {
912
989
  const io = makeIo();
913
990
  const embeddings = vi.fn(async () => ({ status: 'failed', projectDir: tempDir }));
991
+ await writeFile(join(tempDir, 'ktx.yaml'), 'connections: {}\n', 'utf-8');
914
992
  await expect(runKtxSetup({
915
993
  command: 'run',
916
994
  projectDir: tempDir,
917
- mode: 'new',
995
+ mode: 'auto',
918
996
  agents: false,
919
997
  agentScope: 'project',
920
998
  skipAgents: true,
@@ -936,10 +1014,11 @@ describe('setup status', () => {
936
1014
  const io = makeIo();
937
1015
  const embeddings = vi.fn(async () => ({ status: 'ready', projectDir: tempDir }));
938
1016
  const context = vi.fn(async () => ({ status: 'failed', projectDir: tempDir }));
1017
+ await writeFile(join(tempDir, 'ktx.yaml'), 'connections: {}\n', 'utf-8');
939
1018
  await expect(runKtxSetup({
940
1019
  command: 'run',
941
1020
  projectDir: tempDir,
942
- mode: 'new',
1021
+ mode: 'auto',
943
1022
  agents: false,
944
1023
  agentScope: 'project',
945
1024
  skipAgents: true,
@@ -966,6 +1045,7 @@ describe('setup status', () => {
966
1045
  });
967
1046
  it('lets Back from embedding setup return to the model step instead of exiting', async () => {
968
1047
  const testIo = makeIo();
1048
+ await writeFile(join(tempDir, 'ktx.yaml'), 'connections: {}\n', 'utf-8');
969
1049
  const modelResults = [
970
1050
  { status: 'ready', projectDir: tempDir },
971
1051
  { status: 'back', projectDir: tempDir },
@@ -975,7 +1055,7 @@ describe('setup status', () => {
975
1055
  await expect(runKtxSetup({
976
1056
  command: 'run',
977
1057
  projectDir: tempDir,
978
- mode: 'new',
1058
+ mode: 'auto',
979
1059
  agents: false,
980
1060
  skipAgents: true,
981
1061
  inputMode: 'auto',
@@ -993,6 +1073,7 @@ describe('setup status', () => {
993
1073
  });
994
1074
  it('lets Back from database selection return to embedding setup', async () => {
995
1075
  const testIo = makeIo();
1076
+ await writeFile(join(tempDir, 'ktx.yaml'), 'connections: {}\n', 'utf-8');
996
1077
  const modelResults = [
997
1078
  { status: 'ready', projectDir: tempDir },
998
1079
  { status: 'back', projectDir: tempDir },
@@ -1013,11 +1094,11 @@ describe('setup status', () => {
1013
1094
  await expect(runKtxSetup({
1014
1095
  command: 'run',
1015
1096
  projectDir: tempDir,
1016
- mode: 'new',
1097
+ mode: 'auto',
1017
1098
  agents: false,
1018
1099
  skipAgents: true,
1019
1100
  inputMode: 'auto',
1020
- yes: false,
1101
+ yes: true,
1021
1102
  cliVersion: '0.2.0',
1022
1103
  skipLlm: false,
1023
1104
  skipEmbeddings: false,
@@ -1050,7 +1131,7 @@ describe('setup status', () => {
1050
1131
  agents: false,
1051
1132
  skipAgents: true,
1052
1133
  inputMode: 'auto',
1053
- yes: false,
1134
+ yes: true,
1054
1135
  cliVersion: '0.2.0',
1055
1136
  skipLlm: false,
1056
1137
  skipEmbeddings: true,
@@ -1078,14 +1159,14 @@ describe('setup status', () => {
1078
1159
  await expect(runKtxSetup({
1079
1160
  command: 'run',
1080
1161
  projectDir: tempDir,
1081
- mode: 'new',
1162
+ mode: 'auto',
1082
1163
  agents: false,
1083
1164
  skipAgents: true,
1084
1165
  inputMode: 'disabled',
1085
- yes: false,
1166
+ yes: true,
1086
1167
  cliVersion: '0.2.0',
1087
1168
  anthropicApiKeyEnv: 'ANTHROPIC_API_KEY', // pragma: allowlist secret
1088
- anthropicModel: 'claude-sonnet-4-6',
1169
+ llmModel: 'claude-sonnet-4-6',
1089
1170
  skipLlm: false,
1090
1171
  embeddingBackend: 'openai',
1091
1172
  embeddingApiKeyEnv: 'OPENAI_API_KEY', // pragma: allowlist secret
@@ -1124,7 +1205,7 @@ describe('setup status', () => {
1124
1205
  await expect(runKtxSetup({
1125
1206
  command: 'run',
1126
1207
  projectDir: tempDir,
1127
- mode: 'existing',
1208
+ mode: 'auto',
1128
1209
  agents: false,
1129
1210
  skipAgents: true,
1130
1211
  inputMode: 'disabled',
@@ -1187,7 +1268,7 @@ describe('setup status', () => {
1187
1268
  await expect(runKtxSetup({
1188
1269
  command: 'run',
1189
1270
  projectDir: tempDir,
1190
- mode: 'existing',
1271
+ mode: 'auto',
1191
1272
  agents: false,
1192
1273
  skipAgents: true,
1193
1274
  inputMode: 'disabled',
@@ -1224,7 +1305,7 @@ describe('setup status', () => {
1224
1305
  await expect(runKtxSetup({
1225
1306
  command: 'run',
1226
1307
  projectDir: tempDir,
1227
- mode: 'existing',
1308
+ mode: 'auto',
1228
1309
  agents: false,
1229
1310
  skipAgents: true,
1230
1311
  inputMode: 'disabled',
@@ -1263,7 +1344,7 @@ describe('setup status', () => {
1263
1344
  await expect(runKtxSetup({
1264
1345
  command: 'run',
1265
1346
  projectDir: tempDir,
1266
- mode: 'existing',
1347
+ mode: 'auto',
1267
1348
  agents: false,
1268
1349
  inputMode: 'disabled',
1269
1350
  yes: true,
@@ -1315,7 +1396,7 @@ describe('setup status', () => {
1315
1396
  await expect(runKtxSetup({
1316
1397
  command: 'run',
1317
1398
  projectDir: tempDir,
1318
- mode: 'new',
1399
+ mode: 'auto',
1319
1400
  agents: false,
1320
1401
  inputMode: 'disabled',
1321
1402
  yes: true,
@@ -1356,7 +1437,7 @@ describe('setup status', () => {
1356
1437
  await expect(runKtxSetup({
1357
1438
  command: 'run',
1358
1439
  projectDir: tempDir,
1359
- mode: 'existing',
1440
+ mode: 'auto',
1360
1441
  agents: true,
1361
1442
  target: 'codex',
1362
1443
  agentScope: 'project',
@@ -1406,7 +1487,7 @@ describe('setup status', () => {
1406
1487
  await expect(runKtxSetup({
1407
1488
  command: 'run',
1408
1489
  projectDir: tempDir,
1409
- mode: 'existing',
1490
+ mode: 'auto',
1410
1491
  agents: true,
1411
1492
  target: 'codex',
1412
1493
  agentScope: 'project',
@@ -1429,6 +1510,41 @@ describe('setup status', () => {
1429
1510
  expect(agents).toHaveBeenCalledTimes(1);
1430
1511
  expect(io.stderr()).not.toContain('KTX context is not ready for agents.');
1431
1512
  });
1513
+ it('runs non-TTY --agents with a target without requiring --no-input or --yes', async () => {
1514
+ const io = makeIo();
1515
+ const agents = vi.fn(async () => ({
1516
+ status: 'ready',
1517
+ projectDir: tempDir,
1518
+ installs: [{ target: 'claude-code', scope: 'project', mode: 'mcp' }],
1519
+ }));
1520
+ await writeFile(join(tempDir, 'ktx.yaml'), ['connections: {}', ''].join('\n'), 'utf-8');
1521
+ await expect(runKtxSetup({
1522
+ command: 'run',
1523
+ projectDir: tempDir,
1524
+ mode: 'auto',
1525
+ agents: true,
1526
+ target: 'claude-code',
1527
+ agentScope: 'project',
1528
+ inputMode: 'auto',
1529
+ yes: false,
1530
+ cliVersion: '0.2.0',
1531
+ skipLlm: false,
1532
+ skipEmbeddings: false,
1533
+ skipDatabases: false,
1534
+ skipSources: false,
1535
+ skipAgents: false,
1536
+ databaseSchemas: [],
1537
+ }, io.io, { agents })).resolves.toBe(0);
1538
+ expect(agents).toHaveBeenCalledWith(expect.objectContaining({
1539
+ inputMode: 'disabled',
1540
+ yes: false,
1541
+ agents: true,
1542
+ target: 'claude-code',
1543
+ scope: 'project',
1544
+ mode: 'mcp',
1545
+ }), io.io);
1546
+ expect(io.stderr()).not.toContain('Interactive setup requires a terminal');
1547
+ });
1432
1548
  it('routes a ready project menu selection to agent setup', async () => {
1433
1549
  const calls = [];
1434
1550
  const io = makeIo();
@@ -1478,7 +1594,7 @@ describe('setup status', () => {
1478
1594
  await expect(runKtxSetup({
1479
1595
  command: 'run',
1480
1596
  projectDir: tempDir,
1481
- mode: 'existing',
1597
+ mode: 'auto',
1482
1598
  agents: false,
1483
1599
  inputMode: 'auto',
1484
1600
  yes: false,
@@ -1570,7 +1686,7 @@ describe('setup status', () => {
1570
1686
  await expect(runKtxSetup({
1571
1687
  command: 'run',
1572
1688
  projectDir: tempDir,
1573
- mode: 'existing',
1689
+ mode: 'auto',
1574
1690
  agents: false,
1575
1691
  inputMode: 'auto',
1576
1692
  yes: false,
@@ -1627,7 +1743,7 @@ describe('setup status', () => {
1627
1743
  await expect(runKtxSetup({
1628
1744
  command: 'run',
1629
1745
  projectDir: tempDir,
1630
- mode: 'new',
1746
+ mode: 'auto',
1631
1747
  agents: true,
1632
1748
  target: 'universal',
1633
1749
  agentScope: 'project',
@@ -1659,19 +1775,20 @@ describe('setup status', () => {
1659
1775
  await expect(runKtxSetup({
1660
1776
  command: 'run',
1661
1777
  projectDir: tempDir,
1662
- mode: 'new',
1778
+ mode: 'auto',
1663
1779
  agents: false,
1664
1780
  skipAgents: true,
1665
1781
  inputMode: 'disabled',
1666
- yes: false,
1782
+ yes: true,
1667
1783
  cliVersion: '0.2.0',
1668
1784
  anthropicApiKeyEnv: 'ANTHROPIC_API_KEY', // pragma: allowlist secret
1669
- anthropicModel: 'claude-sonnet-4-6',
1785
+ llmModel: 'claude-sonnet-4-6',
1670
1786
  skipLlm: false,
1671
1787
  skipEmbeddings: false,
1672
1788
  databaseSchemas: [],
1673
1789
  skipDatabases: true,
1674
1790
  }, testIo.io, { model, embeddings })).resolves.toBe(1);
1791
+ expect(model).toHaveBeenCalledTimes(1);
1675
1792
  expect(embeddings).not.toHaveBeenCalled();
1676
1793
  });
1677
1794
  });
package/dist/sl.test.js CHANGED
@@ -89,7 +89,8 @@ describe('runKtxSl', () => {
89
89
  yaml: [
90
90
  'name: orders',
91
91
  'table: public.orders',
92
- 'description: Paid order facts',
92
+ 'descriptions:',
93
+ ' user: Paid order facts',
93
94
  'grain: [order_id]',
94
95
  'columns:',
95
96
  ' - name: order_id',
@@ -76,7 +76,7 @@ async function writeSqliteScanConfig(projectDir, dbPath, enrich = false) {
76
76
  ' enrichment:',
77
77
  ' mode: deterministic',
78
78
  ' embeddings:',
79
- ' backend: deterministic',
79
+ ' backend: none',
80
80
  ' dimensions: 6',
81
81
  ]
82
82
  : []),
@@ -94,7 +94,6 @@ async function runSetupNewProject(projectDir) {
94
94
  'setup',
95
95
  '--project-dir',
96
96
  projectDir,
97
- '--new',
98
97
  '--no-input',
99
98
  '--yes',
100
99
  '--skip-llm',
@@ -135,7 +134,7 @@ describe('standalone built ktx CLI smoke', () => {
135
134
  expect(result.stderr).toContain("unknown command 'agent'");
136
135
  });
137
136
  it('runs status setup checks through the built binary', async () => {
138
- const result = await runBuiltCli(['status', '--verbose', '--no-input']);
137
+ const result = await runBuiltCli(['status', '--verbose', '--no-input'], { cwd: tempDir });
139
138
  expect(result.stdout).toMatch(/KTX status/);
140
139
  if (result.stdout.includes('No project here yet.')) {
141
140
  expect(result.stdout).toContain('ktx setup');
@@ -120,15 +120,6 @@ function buildEmbeddingsStatus(config, env) {
120
120
  detail: 'disabled — semantic search will be skipped',
121
121
  };
122
122
  }
123
- if (backend === 'deterministic') {
124
- return {
125
- backend,
126
- model,
127
- dimensions,
128
- status: 'warn',
129
- detail: 'deterministic — semantic search degraded (lexical/dictionary lanes still work)',
130
- };
131
- }
132
123
  if (backend === 'openai') {
133
124
  const ref = config.openai?.api_key;
134
125
  const resolved = resolveRef(ref, env);
@@ -469,7 +460,7 @@ function buildVerdict(llm, embeddings, connections, queryHistory, warnings) {
469
460
  if (llm.status === 'warn')
470
461
  reasons.push('LLM credentials missing');
471
462
  if (embeddings.status === 'warn') {
472
- if (embeddings.backend === 'deterministic' || embeddings.backend === 'none') {
463
+ if (embeddings.backend === 'none') {
473
464
  reasons.push('semantic search disabled');
474
465
  }
475
466
  else {
@@ -132,7 +132,7 @@ async function writeHistoricSqlProject(project) {
132
132
  ' adapters:',
133
133
  ' - historic-sql',
134
134
  ' embeddings:',
135
- ' backend: deterministic',
135
+ ' backend: none',
136
136
  'storage:',
137
137
  ' state: sqlite',
138
138
  ' search: sqlite-fts5',
@@ -262,7 +262,7 @@ describe('canonical local ingest', () => {
262
262
  ' adapters:',
263
263
  ' - fake',
264
264
  ' embeddings:',
265
- ' backend: deterministic',
265
+ ' backend: none',
266
266
  '',
267
267
  ].join('\n'), 'utf-8');
268
268
  project = await loadKtxProject({ projectDir });
@@ -348,9 +348,9 @@ describe('canonical local ingest', () => {
348
348
  expect(result.result.failedWorkUnits).toEqual([]);
349
349
  const db = new Database(join(project.projectDir, '.ktx', 'db.sqlite'), { readonly: true });
350
350
  try {
351
- expect(db.prepare('SELECT key, summary, embedding_json IS NOT NULL AS has_embedding FROM knowledge_pages ORDER BY key').all()).toEqual([
352
- { key: 'orders_context', summary: 'Orders source context', has_embedding: 1 },
353
- ]);
351
+ expect(db
352
+ .prepare('SELECT key, summary, embedding_json IS NOT NULL AS has_embedding FROM knowledge_pages ORDER BY key')
353
+ .all()).toEqual([{ key: 'orders_context', summary: 'Orders source context', has_embedding: 0 }]);
354
354
  }
355
355
  finally {
356
356
  db.close();
@@ -437,7 +437,7 @@ describe('canonical local ingest', () => {
437
437
  ' adapters:',
438
438
  ' - historic-sql',
439
439
  ' embeddings:',
440
- ' backend: deterministic',
440
+ ' backend: none',
441
441
  'storage:',
442
442
  ' state: sqlite',
443
443
  ' search: sqlite-fts5',
@@ -496,7 +496,7 @@ describe('canonical local ingest', () => {
496
496
  ' adapters:',
497
497
  ' - metabase',
498
498
  ' embeddings:',
499
- ' backend: deterministic',
499
+ ' backend: none',
500
500
  '',
501
501
  ].join('\n'), 'utf-8');
502
502
  const metabaseProject = await loadKtxProject({ projectDir });
@@ -556,7 +556,7 @@ describe('canonical local ingest', () => {
556
556
  ' adapters:',
557
557
  ' - metricflow',
558
558
  ' embeddings:',
559
- ' backend: deterministic',
559
+ ' backend: none',
560
560
  'storage:',
561
561
  ' state: sqlite',
562
562
  ' search: sqlite-fts5',
@@ -656,7 +656,7 @@ describe('canonical local ingest', () => {
656
656
  ' adapters:',
657
657
  ' - looker',
658
658
  ' embeddings:',
659
- ' backend: deterministic',
659
+ ' backend: none',
660
660
  'storage:',
661
661
  ' state: sqlite',
662
662
  ' search: sqlite-fts5',
@@ -461,7 +461,7 @@ function localIngestLlmProviderGuardMessage(projectDir) {
461
461
  'ktx ingest requires llm.provider.backend: anthropic, vertex, gateway, or claude-code, or an injected agentRunner.',
462
462
  'Configure a local Claude Code session or API-backed LLM, then rerun ingest:',
463
463
  ` ktx setup --project-dir ${projectDir} --llm-backend claude-code --no-input`,
464
- ` ktx setup --project-dir ${projectDir} --llm-backend anthropic --anthropic-api-key-env ANTHROPIC_API_KEY --anthropic-model claude-sonnet-4-6 --no-input`,
464
+ ` ktx setup --project-dir ${projectDir} --llm-backend anthropic --anthropic-api-key-env ANTHROPIC_API_KEY --llm-model claude-sonnet-4-6 --no-input`,
465
465
  ].join('\n');
466
466
  }
467
467
  function resolveAgentRunner(options) {
@@ -23,7 +23,7 @@ describe('createLocalBundleIngestRuntime', () => {
23
23
  ' adapters:',
24
24
  ' - fake',
25
25
  ' embeddings:',
26
- ' backend: deterministic',
26
+ ' backend: none',
27
27
  '',
28
28
  ].join('\n'), 'utf-8');
29
29
  project = await loadKtxProject({ projectDir });
@@ -39,7 +39,7 @@ describe('createLocalBundleIngestRuntime', () => {
39
39
  'ktx ingest requires llm.provider.backend: anthropic, vertex, gateway, or claude-code, or an injected agentRunner.',
40
40
  'Configure a local Claude Code session or API-backed LLM, then rerun ingest:',
41
41
  ` ktx setup --project-dir ${project.projectDir} --llm-backend claude-code --no-input`,
42
- ` ktx setup --project-dir ${project.projectDir} --llm-backend anthropic --anthropic-api-key-env ANTHROPIC_API_KEY --anthropic-model claude-sonnet-4-6 --no-input`,
42
+ ` ktx setup --project-dir ${project.projectDir} --llm-backend anthropic --anthropic-api-key-env ANTHROPIC_API_KEY --llm-model claude-sonnet-4-6 --no-input`,
43
43
  ].join('\n'));
44
44
  });
45
45
  it('uses a runtime-backed agent runner when claude-code is configured', () => {
@@ -211,7 +211,7 @@ describe('createLocalBundleIngestRuntime', () => {
211
211
  ' adapters:',
212
212
  ' - fake',
213
213
  ' embeddings:',
214
- ' backend: deterministic',
214
+ ' backend: none',
215
215
  '',
216
216
  ].join('\n'), 'utf-8');
217
217
  project = await loadKtxProject({ projectDir: project.projectDir });