diff --git a/packages/cli/src/setup-databases.ts b/packages/cli/src/setup-databases.ts index 4014d689..eb364228 100644 --- a/packages/cli/src/setup-databases.ts +++ b/packages/cli/src/setup-databases.ts @@ -40,6 +40,7 @@ import { } from './setup-prompts.js'; const HISTORIC_SQL_WORK_UNIT_MAX_CONCURRENCY = 6; +const KTX_QUICKSTART_URL = 'https://docs.kaelio.com/ktx/docs/getting-started/quickstart'; const execFileAsync = promisify(execFileCallback); export type KtxSetupDatabaseDriver = @@ -1782,7 +1783,7 @@ async function chooseDrivers( } const initialValues = unique(options?.initialDrivers ?? []); createKtxSetupUiAdapter().note( - 'Get demo credentials at https://kaelio.com/start', + `Get demo credentials from the Quickstart: ${KTX_QUICKSTART_URL}`, '🎁 Need a warehouse to play with?', io, ); diff --git a/packages/cli/src/setup.ts b/packages/cli/src/setup.ts index 9c523902..6b3442ca 100644 --- a/packages/cli/src/setup.ts +++ b/packages/cli/src/setup.ts @@ -170,6 +170,7 @@ export interface KtxSetupDeps { } const SOURCE_DRIVERS = new Set(['dbt', 'metricflow', 'metabase', 'looker', 'lookml', 'notion']); +const KTX_DOCS_URL = 'https://docs.kaelio.com/ktx'; type KtxSetupEntryAction = 'setup' | 'new-project' | 'agents' | 'status' | 'demo' | 'exit'; type KtxSetupFlowStep = 'models' | 'embeddings' | 'databases' | 'sources' | 'runtime' | 'context' | 'agents'; @@ -586,7 +587,7 @@ export async function runKtxSetup(args: KtxSetupArgs, io: KtxCliIo, deps: KtxSet async function runKtxSetupInner(args: KtxSetupArgs, io: KtxCliIo, deps: KtxSetupDeps = {}): Promise { const setupUi = deps.setupUi ?? createKtxSetupUiAdapter(); setupUi.intro('KTX setup', io); - setupUi.note('https://docs.kaelio.com/ktx', '📚 Docs', io); + setupUi.note(KTX_DOCS_URL, '📚 Docs', io); let entryAction: KtxSetupEntryAction | undefined; let projectResult: Awaited>; let agentNextActions: string | undefined; diff --git a/scripts/check-boundaries.mjs b/scripts/check-boundaries.mjs index 97ffef64..b47d0db0 100644 --- a/scripts/check-boundaries.mjs +++ b/scripts/check-boundaries.mjs @@ -5,15 +5,6 @@ import path from 'node:path'; import { fileURLToPath, pathToFileURL } from 'node:url'; const codeExtensions = new Set(['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs', '.py']); -const runtimeAssetPatterns = [/^packages\/cli\/src\/prompts\/.+\.md$/, /^packages\/cli\/src\/skills\/.+\.md$/]; -const identifierSkipPrefixes = ['docs/', 'docs-site/', 'examples/', 'python/ktx-sl/plans/', 'python/ktx-sl/openspec/']; -const identifierAllowPatterns = [ - /^packages\/cli\/src\/(?:index|managed-local-embeddings|managed-python-command|managed-python-daemon|managed-python-runtime|release-version|runtime)(?:\.test)?\.ts$/, - /^python\/ktx-daemon\/src\/ktx_daemon\/__init__\.py$/, - /^scripts\/(?:build-python-runtime-wheel|local-embeddings-runtime-smoke|package-artifacts|public-npm-release-metadata|published-package-smoke|release-readiness)(?:\.test)?\.mjs$/, - /^scripts\/semantic-release-config\.cjs$/, -]; -const forbiddenIdentifierTerms = ['kae' + 'lio', 'Kae' + 'lio', 'KAE' + 'LIO_']; const appImportPatterns = [ { @@ -83,10 +74,6 @@ function isCodeSource(relativePath) { return codeExtensions.has(path.extname(relativePath)); } -function isRuntimeAsset(relativePath) { - return runtimeAssetPatterns.some((pattern) => pattern.test(relativePath)); -} - function scansForAppImports(relativePath) { return isCodeSource(relativePath); } @@ -113,18 +100,6 @@ function scansForConcreteDialectImportBoundaries(relativePath) { ); } -function scansForForbiddenIdentifiers(relativePath) { - return (isCodeSource(relativePath) && !isTestSource(relativePath)) || isRuntimeAsset(relativePath); -} - -function skipsIdentifierScan(relativePath) { - return identifierSkipPrefixes.some((prefix) => relativePath.startsWith(prefix)); -} - -function allowsForbiddenIdentifier(relativePath) { - return identifierAllowPatterns.some((pattern) => pattern.test(relativePath)); -} - export function scanFileContent(relativePath, content) { const normalizedPath = normalizePath(relativePath); const violations = []; @@ -178,22 +153,6 @@ export function scanFileContent(relativePath, content) { } } - if ( - scansForForbiddenIdentifiers(normalizedPath) && - !skipsIdentifierScan(normalizedPath) && - !allowsForbiddenIdentifier(normalizedPath) - ) { - for (const term of forbiddenIdentifierTerms) { - if (content.includes(term)) { - violations.push({ - file: normalizedPath, - kind: 'identifier', - message: `Forbidden product identifier "${term}"`, - }); - } - } - } - return violations; } diff --git a/scripts/check-boundaries.test.mjs b/scripts/check-boundaries.test.mjs index f279313d..e6dd4bb8 100644 --- a/scripts/check-boundaries.test.mjs +++ b/scripts/check-boundaries.test.mjs @@ -3,14 +3,6 @@ import { describe, it } from 'node:test'; import { scanFileContent } from './check-boundaries.mjs'; -function productName() { - return ['Kae', 'lio'].join(''); -} - -function lowerProductName() { - return ['kae', 'lio'].join(''); -} - describe('scanFileContent', () => { it('rejects source imports from application directories', () => { const serverAlias = '@' + 'server/contracts'; @@ -27,64 +19,6 @@ describe('scanFileContent', () => { ); }); - it('rejects forbidden product identifiers in code source files', () => { - const violations = scanFileContent('packages/cli/src/context/index.ts', `export const owner = '${lowerProductName()}';`); - - assert.equal(violations.length, 1); - assert.equal(violations[0]?.kind, 'identifier'); - }); - - it('rejects forbidden product identifiers in shipped runtime prompt assets', () => { - const violations = scanFileContent( - 'packages/cli/src/prompts/memory_agent_bundle_ingest_work_unit.md', - `Write output for ${productName()}.`, - ); - - assert.equal(violations.length, 1); - assert.equal(violations[0]?.kind, 'identifier'); - assert.equal(violations[0]?.file, 'packages/cli/src/prompts/memory_agent_bundle_ingest_work_unit.md'); - }); - - it('rejects forbidden product identifiers in shipped runtime skill assets', () => { - const violations = scanFileContent( - 'packages/cli/src/skills/metabase_ingest/SKILL.md', - `Use ${productName()} project conventions.`, - ); - - assert.equal(violations.length, 1); - assert.equal(violations[0]?.kind, 'identifier'); - assert.equal(violations[0]?.file, 'packages/cli/src/skills/metabase_ingest/SKILL.md'); - }); - - it('allows product identifiers in docs, examples, and transition metadata', () => { - const name = productName(); - - assert.equal(scanFileContent('docs/transition.md', name).length, 0); - assert.equal(scanFileContent('examples/transition.md', name).length, 0); - assert.equal(scanFileContent('python/ktx-sl/plans/brainstorm.md', name).length, 0); - assert.equal(scanFileContent('python/ktx-sl/openspec/specs/semantic-layer/spec.md', name).length, 0); - }); - - it('allows product identifiers in test fixtures', () => { - const name = lowerProductName(); - - assert.equal(scanFileContent('packages/cli/test/setup.test.ts', `project: ${name}-dev`).length, 0); - assert.equal(scanFileContent('packages/cli/test/context/ingest/importer.test.ts', `email: system@${name}.dev`).length, 0); - assert.equal(scanFileContent('python/ktx-daemon/tests/test_package.py', `${name}-ktx`).length, 0); - }); - - it('allows public package identifiers in release packaging and managed runtime source', () => { - const name = lowerProductName(); - - assert.equal(scanFileContent('scripts/local-embeddings-runtime-smoke.mjs', `@${name}/ktx`).length, 0); - assert.equal(scanFileContent('scripts/package-artifacts.test.mjs', `${name}-ktx`).length, 0); - assert.equal(scanFileContent('scripts/public-npm-release-metadata.mjs', `@${name}/ktx`).length, 0); - assert.equal(scanFileContent('scripts/semantic-release-config.cjs', `${name}-ktx-`).length, 0); - assert.equal(scanFileContent('packages/cli/src/release-version.ts', `@${name}/ktx`).length, 0); - assert.equal(scanFileContent('packages/cli/src/managed-python-runtime.ts', `${name}_ktx`).length, 0); - assert.equal(scanFileContent('python/ktx-daemon/src/ktx_daemon/__init__.py', `${name}-ktx`).length, 0); - }); - it('allows clean source files and clean runtime prompt assets', () => { assert.deepEqual( scanFileContent('packages/cli/src/context/index.ts', "export const packageName = 'ktx';"), diff --git a/scripts/examples-docs.test.mjs b/scripts/examples-docs.test.mjs index 53413ea5..b196aaa1 100644 --- a/scripts/examples-docs.test.mjs +++ b/scripts/examples-docs.test.mjs @@ -255,7 +255,8 @@ describe('standalone example docs', () => { assert.match(reviewingContext, /ktx ingest --all --no-input/); assert.match(quickstart, /schema context/); assert.match(primarySources, /context:\n queryHistory:/); - assert.match(rootReadme, /`ktx ingest ` \| Build context for one connection/); + assert.match(rootReadme, /`ktx ingest` \| Build context for every configured connection/); + assert.doesNotMatch(rootReadme, /`ktx ingest `/); assert.match(quickstart, /Databases:\n warehouse: deep context complete/); assert.match(quickstart, /Databases configured: yes \(warehouse\)/); assert.match(setupReference, /Databases configured: yes \(postgres-warehouse\)/);