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

@ -9,7 +9,7 @@ import {
} from '../../../src/context/scan/credentials.js';
import type { KtxCredentialEnvelope, KtxScanReport, KtxScanWarning } from '../../../src/context/scan/types.js';
describe('KTX scan credential redaction', () => {
describe('ktx scan credential redaction', () => {
it('keeps credential references inspectable', () => {
const envReference: KtxCredentialEnvelope = { kind: 'env', name: 'DATABASE_URL' };
const fileReference: KtxCredentialEnvelope = { kind: 'file', path: '~/.config/ktx/warehouse' };

View file

@ -7,7 +7,7 @@ import {
const defaultPatterns = defaultKtxDataDictionarySettings.excludePatterns;
describe('KTX scan data dictionary policy', () => {
describe('ktx scan data dictionary policy', () => {
it('includes text-like and boolean categorical types', () => {
expect(isKtxDataDictionaryCandidate('varchar(50)', 'status', defaultPatterns)).toBe(true);
expect(isKtxDataDictionaryCandidate('VARCHAR', 'category', defaultPatterns)).toBe(true);

View file

@ -90,7 +90,7 @@ function createConnector(): KtxScanConnector {
};
}
describe('KTX description prompt builders', () => {
describe('ktx description prompt builders', () => {
it('builds column prompts with sample values, source descriptions, and nested BigQuery guidance', () => {
const { system, user } = buildKtxColumnDescriptionPrompt({
columnName: 'payload',

View file

@ -1,7 +1,7 @@
import { describe, expect, it } from 'vitest';
import { buildKtxColumnEmbeddingText } from '../../../src/context/scan/embedding-text.js';
describe('KTX scan embedding text', () => {
describe('ktx scan embedding text', () => {
it('builds column embedding text with table, description, FK, and sample-value context', () => {
expect(
buildKtxColumnEmbeddingText({

View file

@ -5,7 +5,7 @@ import {
skippedKtxScanEnrichmentSummary,
} from '../../../src/context/scan/enrichment-summary.js';
describe('KTX scan enrichment summaries', () => {
describe('ktx scan enrichment summaries', () => {
it('keeps structural scans skipped when no enrichment was requested', () => {
expect(failedKtxScanEnrichmentSummary('structural', false)).toEqual(skippedKtxScanEnrichmentSummary);
});

View file

@ -11,7 +11,7 @@ import type {
KtxStructuralSyncPlan,
} from '../../../src/context/scan/enrichment-types.js';
describe('KTX scan enrichment contracts', () => {
describe('ktx scan enrichment contracts', () => {
it('models an enriched schema with reusable table, column, and relationship metadata', () => {
const schema: KtxEnrichedSchema = {
connectionId: 'warehouse',

View file

@ -373,7 +373,7 @@ describe('local scan enrichment', () => {
expect(result.summary.statisticalValidation).toBe('skipped');
expect(result.warnings).toContainEqual({
code: 'relationship_validation_failed',
message: 'KTX scan connector advertises readOnlySql but does not expose executeReadOnly',
message: 'ktx scan connector advertises readOnlySql but does not expose executeReadOnly',
recoverable: true,
metadata: { capability: 'readOnlySql' },
});

View file

@ -1644,7 +1644,7 @@ describe('local scan', () => {
expect(result.report.warnings).toEqual([
{
code: 'enrichment_failed',
message: 'KTX scan enrichment failed after structural scan completed: embedding service timed out',
message: 'ktx scan enrichment failed after structural scan completed: embedding service timed out',
recoverable: true,
metadata: {
mode: 'enriched',

View file

@ -258,7 +258,7 @@ describe('relationship benchmark report', () => {
}),
);
expect(markdown).toContain('# KTX Relationship Discovery Benchmark Evidence');
expect(markdown).toContain('# ktx Relationship Discovery Benchmark Evidence');
expect(markdown).toContain(
'| demo_b2b_no_declared_constraints | smoke | declared_pks_and_declared_fks_removed | run | no | 0.500 | 0.000 | 0.000 | 0 |',
);

View file

@ -279,7 +279,7 @@ describe('relationship diagnostics artifacts', () => {
warnings: [
{
code: 'connector_capability_missing',
message: 'KTX scan connector cannot run standalone statistical relationship validation',
message: 'ktx scan connector cannot run standalone statistical relationship validation',
recoverable: true,
metadata: { capability: 'readOnlySql' },
},

View file

@ -449,7 +449,7 @@ describe('production relationship discovery', () => {
});
expect(result.warnings).toContainEqual({
code: 'connector_capability_missing',
message: 'KTX scan connector cannot run read-only SQL relationship validation',
message: 'ktx scan connector cannot run read-only SQL relationship validation',
recoverable: true,
metadata: { capability: 'readOnlySql' },
});

View file

@ -146,12 +146,12 @@ describe('relationship LLM proposals', () => {
expect(runtime.generateObject).toHaveBeenCalledWith(
expect.objectContaining({
role: 'candidateExtraction',
system: expect.stringContaining('You are helping KTX review possible SQL relationships'),
system: expect.stringContaining('You are helping ktx review possible SQL relationships'),
prompt: expect.stringContaining('"tables"'),
}),
);
const call = vi.mocked(runtime.generateObject).mock.calls[0]?.[0];
expect(call?.prompt).not.toContain('You are helping KTX review possible SQL relationships');
expect(call?.prompt).not.toContain('You are helping ktx review possible SQL relationships');
});
it('skips when no runtime is configured', async () => {
@ -207,7 +207,7 @@ describe('relationship LLM proposals', () => {
expect(failed).toMatchObject({ candidates: [], llmCalls: 1, summary: 'failed' });
expect(failed.warnings[0]).toMatchObject({
code: 'relationship_llm_proposal_failed',
message: 'KTX relationship LLM proposal failed: model unavailable',
message: 'ktx relationship LLM proposal failed: model unavailable',
recoverable: true,
});
});

View file

@ -1,7 +1,7 @@
import { describe, expect, it } from 'vitest';
import { inferKtxDimensionType, ktxColumnTypeMappingFromNative, normalizeKtxNativeType } from '../../../src/context/scan/type-normalization.js';
describe('KTX scan type normalization', () => {
describe('ktx scan type normalization', () => {
it('normalizes native database type strings', () => {
expect(normalizeKtxNativeType(' NUMERIC(12, 2) ')).toBe('numeric');
expect(normalizeKtxNativeType('TIMESTAMP WITH TIME ZONE')).toBe('timestamp with time zone');

View file

@ -17,7 +17,7 @@ import {
type KtxSchemaSnapshot,
} from '../../../src/context/scan/types.js';
describe('KTX scan contract types', () => {
describe('ktx scan contract types', () => {
it('defaults to structural-only connector capabilities', () => {
expect(createKtxConnectorCapabilities()).toEqual({
structuralIntrospection: true,