refactor: enforce ktx naming and AGENTS.md compliance sweep (#289)

Align the tree with AGENTS.md/CLAUDE.md conventions:

- Rewrite user-facing strings, docs, and tests to lowercase `ktx`
  (no bare uppercase `KTX` tokens remain outside literal identifiers).
- Drop the legacy `historicSql` migration path and its now-unused
  helpers, per the no-backward-compat rule.
- Remove `as unknown as` / `any` casts: narrow `BaseTool` generics to
  `z.ZodObject`, add a typed `createLookerClient`, and delete the dead
  `getParametersSchema`/`toAnthropicFormat` pre-AI-SDK helpers.
- Use `InvalidArgumentError` for Commander parse failures.
- Finish the adapter→connector prose conversion in the `ktx.yaml` docs
  while keeping the literal `adapters` config key.
This commit is contained in:
Andrey Avtomonov 2026-06-11 13:49:45 +02:00 committed by GitHub
parent 005c5fc860
commit 00cdf2de90
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
237 changed files with 844 additions and 974 deletions

View file

@ -165,7 +165,7 @@ async function writeHistoricSqlProject(project: KtxLocalProject): Promise<KtxLoc
' state: sqlite',
' search: sqlite-fts5',
' git:',
' author: KTX Test <system@ktx.local>',
' author: ktx Test <system@ktx.local>',
'',
].join('\n'),
'utf-8',
@ -193,7 +193,7 @@ async function writeHistoricSqlProject(project: KtxLocalProject): Promise<KtxLoc
},
},
}),
'KTX Test',
'ktx Test',
'system@ktx.local',
'Seed schema shard',
);

View file

@ -29,7 +29,7 @@ function sdk(): LookerSdkPort {
}
describe('DefaultLookerConnectionClientFactory', () => {
it('resolves credentials by Looker connection id and creates a KTX Looker client', async () => {
it('resolves credentials by Looker connection id and creates a ktx Looker client', async () => {
const fakeSdk = sdk();
const resolver: LookerCredentialResolver = {
resolve: vi.fn().mockResolvedValue({

View file

@ -69,7 +69,7 @@ describe('discoverLookerConnections', () => {
});
describe('looker dialect and target validation helpers', () => {
it('maps Looker dialect names to KTX connection types', () => {
it('maps Looker dialect names to ktx connection types', () => {
expect(lookerDialectToConnectionType('bigquery_standard_sql')).toBe('BIGQUERY');
expect(lookerDialectToConnectionType('postgres')).toBe('POSTGRESQL');
expect(lookerDialectToConnectionType('mssql')).toBeNull();
@ -224,7 +224,7 @@ describe('computeLookerMappingDrift and validateLookerMappings', () => {
).toEqual({
ok: false,
errors: [
{ key: 'b2b_sandbox_bq', reason: 'KTX connection missing does not exist' },
{ key: 'b2b_sandbox_bq', reason: 'ktx connection missing does not exist' },
{
key: 'pg_runtime',
reason: 'Connection type LOOKER cannot be used as a Looker warehouse mapping target',
@ -259,7 +259,7 @@ describe('collectExploreParseItems and projectParsedIdentifier', () => {
});
});
it('projects successful and failed parser rows into KTX parsed target tables', () => {
it('projects successful and failed parser rows into ktx parsed target tables', () => {
expect(
projectParsedIdentifier({
ok: true,

View file

@ -255,7 +255,7 @@ describe('Looker staged runtime schemas', () => {
});
});
it('accepts slug-shaped connection ids inside KTX Looker runtime schemas', () => {
it('accepts slug-shaped connection ids inside ktx Looker runtime schemas', () => {
const parsedTargetTable = {
ok: true as const,
catalog: 'proj',
@ -313,7 +313,7 @@ describe('Looker staged runtime schemas', () => {
});
});
it('rejects unsafe KTX Looker connection ids', () => {
it('rejects unsafe ktx Looker connection ids', () => {
expect(() =>
parseLookerPullConfig({
lookerConnectionId: '../prod-looker',

View file

@ -9,8 +9,8 @@ async function readMetabaseFile(name: string): Promise<string> {
return readFile(join(metabaseDir, name), 'utf-8');
}
describe('KTX Metabase client boundary', () => {
it('keeps NestJS, server data-source base classes, and server-relative imports out of the KTX client', async () => {
describe('ktx Metabase client boundary', () => {
it('keeps NestJS, server data-source base classes, and server-relative imports out of the ktx client', async () => {
const client = await readMetabaseFile('client.ts');
expect(client).not.toContain(`@${'nestjs'}`);
expect(client).not.toContain(`DataSource${'Client'}`);
@ -19,7 +19,7 @@ describe('KTX Metabase client boundary', () => {
expect(client).not.toContain('../../types/brand');
});
it('keeps proxy implementation code out of the KTX v1 client', async () => {
it('keeps proxy implementation code out of the ktx v1 client', async () => {
const client = await readMetabaseFile('client.ts');
expect(client).not.toContain(`network-${'proxy'}`);
expect(client).not.toContain(`ssh${'2'}`);

View file

@ -232,7 +232,7 @@ describe('MetabaseClient admin auth helpers', () => {
);
await expect(client.getPermissionGroups()).resolves.toEqual([{ id: 2, name: 'Administrators' }]);
await expect(client.createApiKey({ name: 'KTX CLI test', groupId: 2 })).resolves.toBe(mintedMetabaseCredential);
await expect(client.createApiKey({ name: 'ktx CLI test', groupId: 2 })).resolves.toBe(mintedMetabaseCredential);
expect(fetchMock).toHaveBeenNthCalledWith(
1,
@ -247,7 +247,7 @@ describe('MetabaseClient admin auth helpers', () => {
'https://metabase.example.test/api/api-key',
expect.objectContaining({
method: 'POST',
body: JSON.stringify({ name: 'KTX CLI test', group_id: 2 }),
body: JSON.stringify({ name: 'ktx CLI test', group_id: 2 }),
}),
);
});

View file

@ -57,7 +57,7 @@ describe('metabaseRuntimeConfigFromLocalConnection', () => {
};
expect(() => metabaseRuntimeConfigFromLocalConnection('prod-metabase', connection)).toThrow(
'Standalone KTX does not support proxy-bearing Metabase connections yet',
'Standalone ktx does not support proxy-bearing Metabase connections yet',
);
});

View file

@ -87,7 +87,7 @@ describe('validateMetabaseMappings', () => {
}),
).toEqual({
ok: false,
errors: [{ key: '2', reason: 'KTX connection missing-target does not exist' }],
errors: [{ key: '2', reason: 'ktx connection missing-target does not exist' }],
});
});
});
@ -149,7 +149,7 @@ describe('validateMappingPhysicalMatch', () => {
).toBeNull();
});
it('returns null for unknown engines because KTX cannot validate them', () => {
it('returns null for unknown engines because ktx cannot validate them', () => {
expect(
validateMappingPhysicalMatch(
{ metabaseEngine: 'unknown-engine', metabaseDbName: 'X', metabaseHost: 'host' },
@ -177,7 +177,7 @@ describe('computeMetabaseMappingPhysicalMismatches', () => {
).toEqual([
{
mappingId: 'mapping-bad',
reason: "Metabase database 'app' does not match KTX connection database 'other_app'",
reason: "Metabase database 'app' does not match ktx connection database 'other_app'",
},
]);
});
@ -216,7 +216,7 @@ describe('refreshMetabaseMapping', () => {
physicalMismatches: [
{
mappingId: '2',
reason: "Metabase database 'analytics' does not match KTX connection database 'wrong_database'",
reason: "Metabase database 'analytics' does not match ktx connection database 'wrong_database'",
},
],
});
@ -282,7 +282,7 @@ describe('findBestMatch', () => {
});
describe('METABASE_ENGINE_TO_CONNECTION_TYPE', () => {
it('keeps the server-supported Metabase engine table in KTX', () => {
it('keeps the server-supported Metabase engine table in ktx', () => {
expect(METABASE_ENGINE_TO_CONNECTION_TYPE).toMatchObject({
postgres: 'POSTGRESQL',
bigquery: 'BIGQUERY',

View file

@ -213,7 +213,7 @@ function makeDeps(
lockingService: { withLock: vi.fn(async (_key, fn) => fn()) },
storage: {
homeDir: join(runtime.configDir, '.ktx'),
systemGitAuthor: { name: 'KTX Test', email: 'system@ktx.local' },
systemGitAuthor: { name: 'ktx Test', email: 'system@ktx.local' },
resolveUploadDir: (id) => join(runtime.homeDir, 'upload', id),
resolvePullDir: (id) => join(runtime.homeDir, 'pull', id),
resolveTranscriptDir: (id) => join(runtime.configDir, '.ktx/ingest-transcripts', id),
@ -308,7 +308,7 @@ describe('IngestBundleRunner isolated diff path', () => {
await currentSession.gitService.commitFiles(
['wiki/global/custom-isolated.md'],
'custom wiki',
'KTX Test',
'ktx Test',
'system@ktx.local',
);
return { stopReason: 'natural' };
@ -395,7 +395,7 @@ describe('IngestBundleRunner isolated diff path', () => {
await currentSession.gitService.commitFiles(
['wiki/global/legacy-isolated.md'],
'legacy isolated wiki',
'KTX Test',
'ktx Test',
'system@ktx.local',
);
return { stopReason: 'natural' };
@ -486,7 +486,7 @@ describe('IngestBundleRunner isolated diff path', () => {
await currentSession.gitService.commitFiles(
['semantic-layer/warehouse/good.yaml'],
'test: add good source',
'KTX Test',
'ktx Test',
'system@ktx.local',
);
}
@ -504,7 +504,7 @@ describe('IngestBundleRunner isolated diff path', () => {
await currentSession.gitService.commitFiles(
['semantic-layer/warehouse/bad.yaml'],
'test: add bad source',
'KTX Test',
'ktx Test',
'system@ktx.local',
);
}
@ -606,7 +606,7 @@ describe('IngestBundleRunner isolated diff path', () => {
await currentSession.gitService.commitFiles(
[`wiki/global/${sourceKey}-isolated.md`],
`${sourceKey} wiki`,
'KTX Test',
'ktx Test',
'system@ktx.local',
);
return { stopReason: 'natural' };
@ -682,7 +682,7 @@ describe('IngestBundleRunner isolated diff path', () => {
'---\nsummary: Account segments\nusage_mode: auto\nsl_refs:\n - mart_account_segments\n---\n\nARR is `mart_account_segments.total_contract_arr_cents`.\n',
);
currentSession.actions.push({ target: 'wiki', type: 'created', key: 'account-segments', detail: 'Account segments' });
await currentSession.gitService.commitFiles(['wiki/global/account-segments.md'], 'wu wiki', 'KTX Test', 'system@ktx.local');
await currentSession.gitService.commitFiles(['wiki/global/account-segments.md'], 'wu wiki', 'ktx Test', 'system@ktx.local');
}
if (params.telemetryTags.unitKey === 'card-source') {
await writeFile(
@ -697,7 +697,7 @@ describe('IngestBundleRunner isolated diff path', () => {
detail: 'Dollar measure',
targetConnectionId: 'warehouse',
});
await currentSession.gitService.commitFiles(['semantic-layer/warehouse/mart_account_segments.yaml'], 'wu source', 'KTX Test', 'system@ktx.local');
await currentSession.gitService.commitFiles(['semantic-layer/warehouse/mart_account_segments.yaml'], 'wu source', 'ktx Test', 'system@ktx.local');
}
return { stopReason: 'natural' };
}) as never;
@ -740,7 +740,7 @@ describe('IngestBundleRunner isolated diff path', () => {
await runtime.git.commitFiles(
['semantic-layer/warehouse/mart_account_segments.yaml', 'wiki/global/account-segments.md'],
'seed existing wiki body ref',
'KTX Test',
'ktx Test',
'system@ktx.local',
);
const preRunHead = await runtime.git.revParseHead();
@ -773,7 +773,7 @@ describe('IngestBundleRunner isolated diff path', () => {
await currentSession.gitService.commitFiles(
['semantic-layer/warehouse/mart_account_segments.yaml'],
'wu source rename',
'KTX Test',
'ktx Test',
'system@ktx.local',
);
return { stopReason: 'natural' };
@ -903,7 +903,7 @@ describe('IngestBundleRunner isolated diff path', () => {
await mkdir(join(root, 'wiki/global'), { recursive: true });
await writeFile(join(root, `wiki/global/${unitKey}.md`), `---\nsummary: ${unitKey}\nusage_mode: auto\n---\n\n${unitKey}\n`);
currentSession.actions.push({ target: 'wiki', type: 'created', key: unitKey, detail: unitKey });
await currentSession.gitService.commitFiles([`wiki/global/${unitKey}.md`], `wu ${unitKey}`, 'KTX Test', 'system@ktx.local');
await currentSession.gitService.commitFiles([`wiki/global/${unitKey}.md`], `wu ${unitKey}`, 'ktx Test', 'system@ktx.local');
return { stopReason: 'natural' };
}) as never;
const runner = new IngestBundleRunner(deps);
@ -950,7 +950,7 @@ describe('IngestBundleRunner isolated diff path', () => {
);
addTouchedSlSource(currentSession.touchedSlSources, 'warehouse', 'orders');
currentSession.actions.push({ target: 'sl', type: 'updated', key: 'orders', detail: suffix, targetConnectionId: 'warehouse' });
await currentSession.gitService.commitFiles(['semantic-layer/warehouse/orders.yaml'], `wu ${suffix}`, 'KTX Test', 'system@ktx.local');
await currentSession.gitService.commitFiles(['semantic-layer/warehouse/orders.yaml'], `wu ${suffix}`, 'ktx Test', 'system@ktx.local');
return { stopReason: 'natural' };
}) as never;
const runner = new IngestBundleRunner(deps);
@ -1006,7 +1006,7 @@ describe('IngestBundleRunner isolated diff path', () => {
'---\nsummary: Projected orders\nusage_mode: auto\nsl_refs:\n - mart_account_segments\n---\n\nARR `mart_account_segments.total_contract_arr`.\n',
);
currentSession.actions.push({ target: 'wiki', type: 'created', key: 'projected-orders', detail: 'Projected orders' });
await currentSession.gitService.commitFiles(['wiki/global/projected-orders.md'], 'wu projected wiki', 'KTX Test', 'system@ktx.local');
await currentSession.gitService.commitFiles(['wiki/global/projected-orders.md'], 'wu projected wiki', 'ktx Test', 'system@ktx.local');
return { stopReason: 'natural' };
}) as never;
const runner = new IngestBundleRunner(deps);
@ -1042,7 +1042,7 @@ describe('IngestBundleRunner isolated diff path', () => {
await mkdir(join(root, 'wiki/global'), { recursive: true });
await writeFile(join(root, 'wiki/global/notion-page.md'), '---\nsummary: Notion page\nusage_mode: auto\nsl_refs:\n - missing_source\n---\n\nBody\n');
currentSession.actions.push({ target: 'wiki', type: 'created', key: 'notion-page', detail: 'Notion page' });
await currentSession.gitService.commitFiles(['wiki/global/notion-page.md'], 'wu notion', 'KTX Test', 'system@ktx.local');
await currentSession.gitService.commitFiles(['wiki/global/notion-page.md'], 'wu notion', 'ktx Test', 'system@ktx.local');
return { stopReason: 'natural' };
}) as never;
const runner = new IngestBundleRunner(deps);
@ -1088,7 +1088,7 @@ describe('IngestBundleRunner isolated diff path', () => {
await currentSession.gitService.commitFiles(
['semantic-layer/warehouse/mart_account_segments.yaml'],
'wu source',
'KTX Test',
'ktx Test',
'system@ktx.local',
);
} else {
@ -1104,7 +1104,7 @@ describe('IngestBundleRunner isolated diff path', () => {
detail: 'Stale reconcile wiki page',
rawPaths: ['cards/source.json'],
});
await currentSession.gitService.commitFiles(['wiki/global/account-segments.md'], 'reconcile wiki', 'KTX Test', 'system@ktx.local');
await currentSession.gitService.commitFiles(['wiki/global/account-segments.md'], 'reconcile wiki', 'ktx Test', 'system@ktx.local');
}
return { stopReason: 'natural' };
}) as never;
@ -1167,7 +1167,7 @@ describe('IngestBundleRunner isolated diff path', () => {
detail: 'Account segments',
rawPaths: ['cards/wiki.json'],
});
await currentSession.gitService.commitFiles(['wiki/global/account-segments.md'], 'wu wiki', 'KTX Test', 'system@ktx.local');
await currentSession.gitService.commitFiles(['wiki/global/account-segments.md'], 'wu wiki', 'ktx Test', 'system@ktx.local');
}
if (params.telemetryTags.unitKey === 'card-source') {
await mkdir(join(root, 'semantic-layer/warehouse'), { recursive: true });
@ -1187,7 +1187,7 @@ describe('IngestBundleRunner isolated diff path', () => {
await currentSession.gitService.commitFiles(
['semantic-layer/warehouse/mart_account_segments.yaml'],
'wu source',
'KTX Test',
'ktx Test',
'system@ktx.local',
);
}
@ -1302,7 +1302,7 @@ describe('IngestBundleRunner isolated diff path', () => {
await currentSession.gitService.commitFiles(
['semantic-layer/warehouse/mart_account_segments.yaml', 'wiki/global/account-segments.md'],
'valid artifacts with invalid provenance',
'KTX Test',
'ktx Test',
'system@ktx.local',
);
return { stopReason: 'natural' };
@ -1444,7 +1444,7 @@ describe('IngestBundleRunner isolated diff path', () => {
'name: orders\ngrain: [id]\ncolumns: [{name: id, type: string}]\njoins: []\nmeasures: []\n',
);
currentSession.actions.push({ target: 'sl', type: 'created', key: 'orders', detail: 'forbidden', targetConnectionId: 'warehouse' });
await currentSession.gitService.commitFiles(['semantic-layer/warehouse/orders.yaml'], 'forbidden sl', 'KTX Test', 'system@ktx.local');
await currentSession.gitService.commitFiles(['semantic-layer/warehouse/orders.yaml'], 'forbidden sl', 'ktx Test', 'system@ktx.local');
return { stopReason: 'natural' };
}) as never;
const runner = new IngestBundleRunner(deps);
@ -1469,7 +1469,7 @@ describe('IngestBundleRunner isolated diff path', () => {
join(runtime.configDir, 'wiki/global/source-page.md'),
'---\nsummary: Source page\nusage_mode: auto\n---\n\nSource page\n',
);
await runtime.git.commitFiles(['wiki/global/source-page.md'], 'seed source page', 'KTX Test', 'system@ktx.local');
await runtime.git.commitFiles(['wiki/global/source-page.md'], 'seed source page', 'ktx Test', 'system@ktx.local');
const preRunHead = await runtime.git.revParseHead();
const { deps, adapter } = makeDeps(runtime);
adapter.chunk.mockResolvedValue({
@ -1501,7 +1501,7 @@ describe('IngestBundleRunner isolated diff path', () => {
await currentSession.gitService.commitFiles(
['wiki/global/account-segments.md'],
'wu page ref',
'KTX Test',
'ktx Test',
'system@ktx.local',
);
}
@ -1517,7 +1517,7 @@ describe('IngestBundleRunner isolated diff path', () => {
await currentSession.gitService.commitFiles(
['wiki/global/source-page.md'],
'wu delete source page',
'KTX Test',
'ktx Test',
'system@ktx.local',
);
}
@ -1582,7 +1582,7 @@ describe('IngestBundleRunner isolated diff path', () => {
await runtime.git.commitFiles(
['wiki/global/source-page.md', 'wiki/global/account-segments.md'],
'seed inbound wiki refs',
'KTX Test',
'ktx Test',
'system@ktx.local',
);
const preRunHead = await runtime.git.revParseHead();
@ -1613,7 +1613,7 @@ describe('IngestBundleRunner isolated diff path', () => {
await currentSession.gitService.commitFiles(
['wiki/global/source-page.md'],
'wu delete target page',
'KTX Test',
'ktx Test',
'system@ktx.local',
);
return { stopReason: 'natural' };
@ -1751,7 +1751,7 @@ describe('IngestBundleRunner isolated diff path', () => {
await currentSession.gitService.commitFiles(
['semantic-layer/finance/orders.yaml'],
'wu unauthorized target',
'KTX Test',
'ktx Test',
'system@ktx.local',
);
return { stopReason: 'natural' };
@ -1822,7 +1822,7 @@ describe('IngestBundleRunner isolated diff path', () => {
detail: 'Valid page',
rawPaths: ['pages/source.json'],
});
await currentSession.gitService.commitFiles(['wiki/global/valid-page.md'], 'wu valid page', 'KTX Test', 'system@ktx.local');
await currentSession.gitService.commitFiles(['wiki/global/valid-page.md'], 'wu valid page', 'ktx Test', 'system@ktx.local');
} else {
await mkdir(join(root, 'semantic-layer/finance'), { recursive: true });
await writeFile(
@ -1841,7 +1841,7 @@ describe('IngestBundleRunner isolated diff path', () => {
await currentSession.gitService.commitFiles(
['semantic-layer/finance/reconcile_orders.yaml'],
'reconcile unauthorized target',
'KTX Test',
'ktx Test',
'system@ktx.local',
);
}
@ -1959,7 +1959,7 @@ describe('IngestBundleRunner isolated diff path', () => {
await currentSession.gitService.commitFiles(
['semantic-layer/warehouse/mart_account_segments.yaml'],
`wu ${params.telemetryTags.unitKey}`,
'KTX Test',
'ktx Test',
'system@ktx.local',
);
return { stopReason: 'natural' };
@ -2025,7 +2025,7 @@ describe('IngestBundleRunner isolated diff path', () => {
await runtime.git.commitFiles(
['semantic-layer/warehouse/mart_account_segments.yaml', 'wiki/global/account-segments.md'],
'seed stale wiki body ref',
'KTX Test',
'ktx Test',
'system@ktx.local',
);
@ -2073,7 +2073,7 @@ describe('IngestBundleRunner isolated diff path', () => {
await currentSession.gitService.commitFiles(
['semantic-layer/warehouse/mart_account_segments.yaml'],
'wu source rename',
'KTX Test',
'ktx Test',
'system@ktx.local',
);
return { stopReason: 'natural' as const };
@ -2128,7 +2128,7 @@ describe('IngestBundleRunner isolated diff path', () => {
await runtime.git.commitFiles(
['semantic-layer/warehouse/mart_account_segments.yaml', 'wiki/global/account-segments.md'],
'seed stale wiki body ref',
'KTX Test',
'ktx Test',
'system@ktx.local',
);
const preRunHead = await runtime.git.revParseHead();
@ -2168,7 +2168,7 @@ describe('IngestBundleRunner isolated diff path', () => {
await currentSession.gitService.commitFiles(
['semantic-layer/warehouse/mart_account_segments.yaml'],
'wu source rename',
'KTX Test',
'ktx Test',
'system@ktx.local',
);
return { stopReason: 'natural' as const };
@ -2302,7 +2302,7 @@ describe('IngestBundleRunner isolated diff path', () => {
await currentSession.gitService.commitFiles(
['wiki/global/orders.md'],
'wu orders',
'KTX Test',
'ktx Test',
'system@ktx.local',
);
return { stopReason: 'natural' as const };

View file

@ -261,7 +261,7 @@ const buildRunner = (deps: ReturnType<typeof makeDeps> = makeDeps(), overrides:
lockingService: deps.lockingService as any,
storage: {
homeDir: '/tmp/ktx-test',
systemGitAuthor: { name: 'KTX Test', email: 'system@ktx.local' },
systemGitAuthor: { name: 'ktx Test', email: 'system@ktx.local' },
resolveUploadDir: (uploadId) => `/tmp/ktx-test/ingest-uploads/${uploadId}`,
resolvePullDir: (jobId) => `/tmp/ktx-test/ingest-pulls/${jobId}`,
resolveTranscriptDir: (jobId) => `/tmp/ktx-test/run/wu-transcripts/${jobId}`,
@ -1518,7 +1518,7 @@ describe('IngestBundleRunner — Stages 1 → 7', () => {
...(buildRunner(deps) as any).deps,
storage: {
homeDir: tempRoot,
systemGitAuthor: { name: 'KTX Test', email: 'system@ktx.local' },
systemGitAuthor: { name: 'ktx Test', email: 'system@ktx.local' },
resolveUploadDir: (uploadId: string) => join(tempRoot, 'ingest-uploads', uploadId),
resolvePullDir: (jobId: string) => join(tempRoot, 'ingest-pulls', jobId),
resolveTranscriptDir: (jobId: string) => join(tempRoot, 'run', 'wu-transcripts', jobId),

View file

@ -18,14 +18,14 @@ describe('ingest prompt assets', () => {
expect(prompt).toContain('Do not create a duplicate contested artifact');
});
it('uses product-neutral KTX runtime wording', async () => {
it('uses product-neutral ktx runtime wording', async () => {
const prompt = await readFile(
new URL('../../../src/prompts/memory_agent_bundle_ingest_work_unit.md', import.meta.url),
'utf-8',
);
expect(prompt).toContain('KTX semantic-layer sources and/or knowledge wiki pages');
expect(prompt).toContain('maps cleanly to KTX');
expect(prompt).toContain('ktx semantic-layer sources and/or knowledge wiki pages');
expect(prompt).toContain('maps cleanly to ktx');
expect(prompt).not.toMatch(forbiddenProductPattern());
});

View file

@ -34,7 +34,7 @@ function forbiddenProductPattern() {
}
describe('ingest runtime assets', () => {
it('resolves every reusable ingest skill from packaged KTX assets without server fallback', async () => {
it('resolves every reusable ingest skill from packaged ktx assets without server fallback', async () => {
const registry = new SkillsRegistryService({ skillsDir });
const expected = [...new Set([...adapterSkillNames, ...adapterReconcileSkillNames])].sort();
@ -48,7 +48,7 @@ describe('ingest runtime assets', () => {
}
});
it('loads page-triage and light-extraction prompts from packaged KTX prompt assets', async () => {
it('loads page-triage and light-extraction prompts from packaged ktx prompt assets', async () => {
const prompts = new PromptService({ promptsDir, partials: [] });
for (const promptName of pageTriagePromptNames) {
@ -61,7 +61,7 @@ describe('ingest runtime assets', () => {
await expect(prompts.loadPrompt('skills/light_extraction')).resolves.toContain('# Light Context Extraction');
});
it('packages historic-SQL table digest guidance from KTX assets', async () => {
it('packages historic-SQL table digest guidance from ktx assets', async () => {
const registry = new SkillsRegistryService({ skillsDir });
const skills = await registry.listSkills(['historic_sql_table_digest'], 'memory_agent');
@ -77,7 +77,7 @@ describe('ingest runtime assets', () => {
expect(body).not.toMatch(forbiddenProductPattern());
});
it('packages historic-SQL patterns guidance from KTX assets', async () => {
it('packages historic-SQL patterns guidance from ktx assets', async () => {
const registry = new SkillsRegistryService({ skillsDir });
const skills = await registry.listSkills(['historic_sql_patterns'], 'memory_agent');

View file

@ -49,7 +49,7 @@ describe('integrateWorkUnitPatch', () => {
patchPath,
integrationGit: git,
trace,
author: { name: 'KTX Test', email: 'system@ktx.local' },
author: { name: 'ktx Test', email: 'system@ktx.local' },
validateAppliedTree: vi.fn().mockResolvedValue(undefined),
slDisallowed: false,
allowedTargetConnectionIds: new Set(['c1']),
@ -82,7 +82,7 @@ describe('integrateWorkUnitPatch', () => {
patchPath,
integrationGit: git,
trace,
author: { name: 'KTX Test', email: 'system@ktx.local' },
author: { name: 'ktx Test', email: 'system@ktx.local' },
validateAppliedTree: vi.fn().mockRejectedValue(new Error('final artifact gates failed')),
slDisallowed: false,
allowedTargetConnectionIds: new Set(['c1']),
@ -117,7 +117,7 @@ describe('integrateWorkUnitPatch', () => {
patchPath,
integrationGit: git,
trace,
author: { name: 'KTX Test', email: 'system@ktx.local' },
author: { name: 'ktx Test', email: 'system@ktx.local' },
validateAppliedTree: vi.fn().mockResolvedValue(undefined),
slDisallowed: true,
allowedTargetConnectionIds: new Set(['c1']),
@ -158,7 +158,7 @@ describe('integrateWorkUnitPatch', () => {
patchPath,
integrationGit: git,
trace,
author: { name: 'KTX Test', email: 'system@ktx.local' },
author: { name: 'ktx Test', email: 'system@ktx.local' },
validateAppliedTree: vi.fn().mockResolvedValue(undefined),
slDisallowed: false,
allowedTargetConnectionIds: new Set(['warehouse']),
@ -325,7 +325,7 @@ describe('integrateWorkUnitPatch', () => {
patchPath,
integrationGit: git,
trace,
author: { name: 'KTX Test', email: 'system@ktx.local' },
author: { name: 'ktx Test', email: 'system@ktx.local' },
validateAppliedTree,
slDisallowed: false,
allowedTargetConnectionIds: new Set(['c1']),
@ -380,7 +380,7 @@ describe('integrateWorkUnitPatch', () => {
patchPath,
integrationGit: git,
trace,
author: { name: 'KTX Test', email: 'system@ktx.local' },
author: { name: 'ktx Test', email: 'system@ktx.local' },
validateAppliedTree: vi.fn().mockRejectedValue(new Error('final artifact gates failed')),
slDisallowed: false,
allowedTargetConnectionIds: new Set(['c1']),

View file

@ -65,7 +65,7 @@ describe('runIsolatedWorkUnit', () => {
run: async (child) => {
await mkdir(join(child.workdir, 'wiki/global'), { recursive: true });
await writeFile(join(child.workdir, 'wiki/global/a.md'), '---\nsummary: A\nusage_mode: auto\n---\n\nBody\n');
await child.git.commitFiles(['wiki/global/a.md'], 'test: write wiki', 'KTX Test', 'system@ktx.local');
await child.git.commitFiles(['wiki/global/a.md'], 'test: write wiki', 'ktx Test', 'system@ktx.local');
return {
unitKey: 'wu-1',
status: 'success',

View file

@ -521,7 +521,7 @@ describe('canonical local ingest', () => {
' state: sqlite',
' search: sqlite-fts5',
' git:',
' author: KTX Test <system@ktx.local>',
' author: ktx Test <system@ktx.local>',
'',
].join('\n'),
'utf-8',
@ -530,7 +530,7 @@ describe('canonical local ingest', () => {
await historicProject.fileStore.writeFile(
'semantic-layer/warehouse/_schema/public.yaml',
YAML.stringify({ tables: { orders: { table: 'public.orders', columns: [{ name: 'id', type: 'string' }] } } }),
'KTX Test',
'ktx Test',
'system@ktx.local',
'Seed schema shard',
);
@ -682,7 +682,7 @@ describe('canonical local ingest', () => {
' state: sqlite',
' search: sqlite-fts5',
' git:',
' author: KTX Test <system@ktx.local>',
' author: ktx Test <system@ktx.local>',
'',
].join('\n'),
'utf-8',
@ -765,7 +765,7 @@ describe('canonical local ingest', () => {
' state: sqlite',
' search: sqlite-fts5',
' git:',
' author: KTX Test <system@ktx.local>',
' author: ktx Test <system@ktx.local>',
'',
].join('\n'),
'utf-8',
@ -808,7 +808,7 @@ describe('canonical local ingest', () => {
' state: sqlite',
' search: sqlite-fts5',
' git:',
' author: KTX Test <system@ktx.local>',
' author: ktx Test <system@ktx.local>',
'',
].join('\n'),
'utf-8',

View file

@ -596,7 +596,7 @@ describe('local ingest', () => {
});
});
it('includes upload-capable KTX adapters in default local ingest adapters', () => {
it('includes upload-capable ktx adapters in default local ingest adapters', () => {
expect(createDefaultLocalIngestAdapters(project).map((adapter) => adapter.source)).toEqual(
expect.arrayContaining(['dbt', 'metricflow', 'notion']),
);

View file

@ -17,7 +17,7 @@ describe('memory-flow acceptance scenarios', () => {
it('renders a completed replay with a clear saved-memory completion line', () => {
const output = renderScenario(successfulReplayScenario());
expect(output).toContain('KTX memory flow warehouse/metricflow done');
expect(output).toContain('ktx memory flow warehouse/metricflow done');
expect(output).toContain('Saved 3 memories from 4 raw files: 2 wiki pages, 1 SL updates.');
expect(output).toContain('Commit: abc12345 Run: run-success Report: ingest-report.json');
});
@ -48,7 +48,7 @@ describe('memory-flow acceptance scenarios', () => {
it('renders no ANSI color codes in the text fallback for terminals without color support', () => {
const output = renderScenario(successfulReplayScenario(), 80);
expect(output).toContain('KTX memory flow warehouse/metricflow done');
expect(output).toContain('ktx memory flow warehouse/metricflow done');
expect(output).not.toMatch(/\u001b\[[0-9;]*m/);
});

View file

@ -13,7 +13,7 @@ import type { MemoryFlowInteractionState, MemoryFlowViewModel } from '../../../.
function view(): MemoryFlowViewModel {
return {
title: 'KTX memory flow warehouse/metricflow running',
title: 'ktx memory flow warehouse/metricflow running',
subtitle: 'Run run-1 Sync sync-1',
status: 'running',
activeLine: 'active: WorkUnit orders step 2/4',

View file

@ -5,7 +5,7 @@ import type { MemoryFlowViewModel } from '../../../../src/context/ingest/memory-
function view(): MemoryFlowViewModel {
return {
title: 'KTX memory flow warehouse/metricflow done',
title: 'ktx memory flow warehouse/metricflow done',
subtitle: 'Run run-1 Sync sync-1',
status: 'done',
activeLine: 'active: complete',
@ -128,7 +128,7 @@ describe('renderMemoryFlowInteractive', () => {
const output = renderMemoryFlowInteractive(view(), state, { terminalWidth: 140 });
expect(output).toContain('KTX memory flow warehouse/metricflow done');
expect(output).toContain('ktx memory flow warehouse/metricflow done');
expect(output).toContain('OK SOURCE -> OK CHUNKS -> !! WORKUNITS -> OK ACTIONS -> !! GATES -> OK SAVED');
expect(output).toContain('[WORKUNITS]');
expect(output).toContain('> orders');

View file

@ -4,7 +4,7 @@ import { renderMemoryFlowReplay } from '../../../../src/context/ingest/memory-fl
function view(): MemoryFlowViewModel {
return {
title: 'KTX memory flow warehouse/metricflow done',
title: 'ktx memory flow warehouse/metricflow done',
subtitle: 'Run run-1 Sync sync-1',
status: 'done',
activeLine: 'active: complete',
@ -79,7 +79,7 @@ describe('renderMemoryFlowReplay', () => {
'OK SOURCE -> OK CHUNKS -> !! WORKUNITS -> OK ACTIONS -> !! GATES -> OK SAVED',
);
expect(renderMemoryFlowReplay(view(), { terminalWidth: 140 })).toMatchInlineSnapshot(`
"KTX memory flow warehouse/metricflow done
"ktx memory flow warehouse/metricflow done
active: complete
Run run-1 Sync sync-1
OK SOURCE -> OK CHUNKS -> !! WORKUNITS -> OK ACTIONS -> !! GATES -> OK SAVED

View file

@ -93,7 +93,7 @@ describe('buildMemoryFlowViewModel', () => {
it('builds six readable columns from replay events', () => {
const view = buildMemoryFlowViewModel(replayInput());
expect(view.title).toBe('KTX memory flow warehouse/metricflow done');
expect(view.title).toBe('ktx memory flow warehouse/metricflow done');
expect(view.activeLine).toBe('active: complete');
expect(view.columns.map((column) => column.id)).toEqual([
'source',
@ -179,7 +179,7 @@ describe('buildMemoryFlowViewModel', () => {
details: { actions: [], provenance: [], transcripts: [] },
});
expect(view.title).toBe('KTX memory flow Warehouse + dbt + BI + Docs done');
expect(view.title).toBe('ktx memory flow Warehouse + dbt + BI + Docs done');
expect(view.columns.find((column) => column.id === 'source')?.counters[0]).toBe('Warehouse, dbt, BI, Docs');
expect(view.completionLine).toContain('Saved 16 memories from 29 raw files');
});

View file

@ -11,7 +11,7 @@ function viewWithStatuses(statuses: Array<'waiting' | 'active' | 'complete' | 'w
const ids = ['source', 'chunks', 'workUnits', 'actions', 'gates', 'saved'] as const;
return {
title: 'KTX memory flow warehouse/metricflow running',
title: 'ktx memory flow warehouse/metricflow running',
subtitle: 'Run run-1 Sync sync-1',
status: 'running',
activeLine: 'active: WorkUnit orders',

View file

@ -198,7 +198,7 @@ describe('PageTriageService', () => {
'Reusable outbound sequence:',
'',
'- Ask about current customer success expansion workflow.',
'- Position KTX as AI search visibility for CS teams.',
'- Position ktx as AI search visibility for CS teams.',
'- Close with a discovery call request.',
].join('\n'),
'utf-8',
@ -233,7 +233,7 @@ describe('PageTriageService', () => {
{
candidateKey: 'cold-call-script',
topic: 'Cold Call Script',
assertion: 'Cold call outreach should position KTX around AI search visibility for CS teams.',
assertion: 'Cold call outreach should position ktx around AI search visibility for CS teams.',
rationale: 'The script gives a reusable outbound call sequence and positioning language.',
evidenceChunkIds: ['00000000-0000-0000-0000-000000000101'],
suggestedPageKey: 'cold-call-script',

View file

@ -106,7 +106,7 @@ describe('repo-fetch', () => {
const cacheGit = createSimpleGit(cacheDir);
await cacheGit.addConfig('user.email', 'test@ktx.local');
await cacheGit.addConfig('user.name', 'KTX Test');
await cacheGit.addConfig('user.name', 'ktx Test');
await writeFile(join(cacheDir, 'local-only.txt'), 'local commit\n', 'utf-8');
await cacheGit.add('.');
await cacheGit.commit('local-only divergent commit');