chore: add TypeScript dead-code checks (#60)

* chore: add TypeScript dead-code checks

* chore: trim stale Knip ignores

* Fix CI smoke and artifact checks
This commit is contained in:
Andrey Avtomonov 2026-05-13 13:33:28 +02:00 committed by GitHub
parent 721f1a998f
commit bcb0d2f8f7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
29 changed files with 818 additions and 220 deletions

View file

@ -37,6 +37,9 @@ jobs:
- name: Install TypeScript dependencies
run: pnpm install --frozen-lockfile
- name: Run TypeScript dead-code checks
run: pnpm run dead-code
- name: Run TypeScript checks
run: pnpm run check

View file

@ -33,6 +33,19 @@ repos:
name: ruff format (python)
files: ^python/
- repo: local
hooks:
- id: biome-dead-code
name: biome dead-code check
entry: pnpm exec biome ci . --formatter-enabled=false --assist-enabled=false
language: system
pass_filenames: false
- id: knip-dead-code
name: knip dead-code check
entry: pnpm exec knip --reporter compact
language: system
pass_filenames: false
- repo: https://github.com/Yelp/detect-secrets
rev: v1.5.0
hooks:

View file

@ -86,6 +86,7 @@ pnpm run build
pnpm run type-check
pnpm run test
pnpm run check
pnpm run dead-code
pnpm --filter @ktx/cli run smoke
pnpm --filter './packages/*' run build
pnpm --filter './packages/*' run test
@ -127,6 +128,7 @@ shared contracts or package exports are affected.
- Build/export changes: `pnpm run build`
- Workspace scripts: `node --test scripts/*.test.mjs` or the specific script
test file
- TypeScript dead-code tooling/config changes: `pnpm run dead-code`
- Python semantic layer: `uv run pytest python/ktx-sl/tests -q`
- Python daemon: `uv run pytest python/ktx-daemon/tests -q`
- Python files: also run `uv run pre-commit run --files [FILES]` when
@ -156,6 +158,23 @@ pnpm run test 2>&1 | tee /tmp/ktx-test-output.log
- Do not manually edit generated or built output under `dist/`; edit source and
rebuild.
### Dead TypeScript Code Checks
KTX uses Biome for local unused-code linting and Knip for workspace graph
analysis. These checks are intentionally part of CI and pre-commit because the
normal development workflow is agent-based.
- Run `pnpm run dead-code` after TypeScript changes.
- Treat Knip findings as investigation prompts, not automatic deletion orders.
- Remove private dead code when you confirm there are no imports, dynamic
references, generated references, or tests that still need it.
- Preserve public package exports unless the task explicitly includes API
pruning.
- Add narrow `knip.json` ignores only for intentional dynamic or public cases.
Do not add broad package-level ignores to silence unrelated findings.
- Update `knip.json` when adding dynamic entrypoints, generated files, package
exports, CLI bins, or framework files that Knip cannot infer.
### CLI Standards
- Use Commander for CLI command trees, arguments, options, help text, custom

36
biome.json Normal file
View file

@ -0,0 +1,36 @@
{
"$schema": "https://biomejs.dev/schemas/2.4.15/schema.json",
"assist": {
"enabled": false
},
"formatter": {
"enabled": false
},
"files": {
"includes": [
"scripts/**/*.mjs",
"packages/**/*.ts",
"packages/**/*.tsx",
"docs-site/**/*.ts",
"docs-site/**/*.tsx",
"docs-site/**/*.mjs",
"!**/dist/**",
"!**/coverage/**",
"!**/.next/**",
"!**/node_modules/**",
"!**/*.gen.ts",
"!**/*.generated.ts"
]
},
"linter": {
"enabled": true,
"rules": {
"recommended": false,
"correctness": {
"noUnusedImports": "error",
"noUnusedVariables": "error",
"noUnusedPrivateClassMembers": "error"
}
}
}
}

114
knip.json Normal file
View file

@ -0,0 +1,114 @@
{
"$schema": "https://unpkg.com/knip@6/schema.json",
"workspaces": {
".": {
"entry": ["scripts/**/*.mjs"],
"project": ["scripts/**/*.mjs"]
},
"packages/cli": {
"entry": [
"src/index.ts",
"src/bin.ts",
"src/**/*.test.ts",
"src/**/*.test.tsx",
"scripts/**/*.mjs"
],
"project": ["src/**/*.{ts,tsx}", "scripts/**/*.mjs", "vitest.config.ts"]
},
"packages/context": {
"entry": [
"src/index.ts",
"src/agent/index.ts",
"src/core/index.ts",
"src/connections/index.ts",
"src/daemon/index.ts",
"src/ingest/index.ts",
"src/ingest/memory-flow/index.ts",
"src/ingest/metabase-mapping.ts",
"src/scan/index.ts",
"src/search/index.ts",
"src/sql-analysis/index.ts",
"src/memory/index.ts",
"src/mcp/index.ts",
"src/project/index.ts",
"src/prompts/index.ts",
"src/skills/index.ts",
"src/sl/index.ts",
"src/sl/descriptions.ts",
"src/tools/index.ts",
"src/wiki/index.ts",
"src/**/*.test.ts",
"scripts/**/*.mjs"
],
"project": ["src/**/*.ts", "scripts/**/*.mjs", "vitest.config.ts"]
},
"packages/llm": {
"entry": ["src/index.ts", "src/**/*.test.ts"],
"project": ["src/**/*.ts", "vitest.config.ts"]
},
"packages/connector-*": {
"entry": ["src/index.ts", "src/**/*.test.ts"],
"project": ["src/**/*.ts"]
},
"docs-site": {
"entry": [
"app/**/*.{ts,tsx}",
"components/**/*.{ts,tsx}",
"lib/**/*.{ts,tsx}",
"middleware.ts",
"next.config.mjs",
"source.config.ts",
"tests/**/*.mjs"
],
"project": [
"app/**/*.{ts,tsx}",
"components/**/*.{ts,tsx}",
"lib/**/*.{ts,tsx}",
"*.ts",
"*.mjs",
"tests/**/*.mjs"
],
"ignoreDependencies": ["tailwindcss"]
}
},
"ignore": [
"**/dist/**",
"**/coverage/**",
"**/.next/**",
"**/node_modules/**",
"**/*.gen.ts",
"**/*.generated.ts"
],
"ignoreIssues": {
"packages/cli/src/clack.ts": ["exports"],
"packages/cli/src/commands/connection-metabase-setup.ts": ["exports", "types"],
"packages/cli/src/ingest.test-utils.ts": ["exports"],
"packages/cli/src/io/symbols.ts": ["exports"],
"packages/cli/src/managed-python-command.ts": ["types"],
"packages/cli/src/managed-python-daemon.ts": ["types"],
"packages/cli/src/managed-python-http.ts": ["exports", "types"],
"packages/cli/src/managed-python-runtime.ts": ["types"],
"packages/cli/src/memory-flow-tui.tsx": ["types"],
"packages/cli/src/next-steps.ts": ["exports"],
"packages/cli/src/print-command-tree.ts": ["exports"],
"packages/cli/src/setup-agents.ts": ["exports", "types"],
"packages/cli/src/setup-context.ts": ["types"],
"packages/cli/src/setup-demo-tour.ts": ["exports"],
"packages/cli/src/setup-models.ts": ["exports"],
"packages/cli/src/setup-project.ts": ["types"],
"packages/cli/src/setup-ready-menu.ts": ["types"],
"packages/cli/src/setup-sources.ts": ["types"],
"packages/context/src/ingest/adapters/historic-sql/pattern-inputs.ts": ["exports", "types"],
"packages/context/src/ingest/adapters/lookml/pull-config.ts": ["exports"],
"packages/context/src/ingest/adapters/metabase/serialize-card.ts": ["types"],
"packages/context/src/ingest/adapters/metabase/types.ts": ["exports"],
"packages/context/src/ingest/adapters/metricflow/parse.ts": ["types"],
"packages/context/src/ingest/ports.ts": ["types"],
"packages/context/src/ingest/stages/stage-3-work-units.ts": ["types"],
"packages/context/src/ingest/stages/stage-index.types.ts": ["types"],
"packages/context/src/project/config.ts": ["types"],
"packages/context/src/scan/relationship-candidates.ts": ["types"],
"packages/context/src/scan/relationship-diagnostics.ts": ["types"],
"packages/context/src/tools/context-evidence-tool-store.ts": ["types"]
}
}

View file

@ -18,6 +18,10 @@
"artifacts:verify-manifest": "node scripts/package-artifacts.mjs verify-manifest",
"build": "pnpm --filter './packages/*' run build",
"check": "node scripts/check-boundaries.mjs && node --test scripts/*.test.mjs && pnpm --filter './packages/*' run build && pnpm --filter './packages/*' run test",
"dead-code": "pnpm run dead-code:biome && pnpm run dead-code:knip",
"dead-code:biome": "biome ci . --formatter-enabled=false --assist-enabled=false",
"dead-code:fix": "biome check . --formatter-enabled=false --assist-enabled=false --write && knip --fix --format",
"dead-code:knip": "knip --reporter compact",
"ktx": "node scripts/run-ktx.mjs",
"link:dev": "node scripts/link-dev-cli.mjs",
"native:rebuild": "pnpm -r rebuild better-sqlite3",
@ -36,9 +40,12 @@
"type-check": "pnpm --filter './packages/*' run type-check"
},
"devDependencies": {
"@biomejs/biome": "^2.4.15",
"@types/node": "^25.7.0",
"better-sqlite3": "^12.10.0",
"knip": "^6.12.2",
"typescript": "^6.0.3",
"vitest": "^4.1.6"
"yaml": "^2.9.0"
},
"pnpm": {
"onlyBuiltDependencies": [

View file

@ -188,7 +188,7 @@ export function registerConnectionCommands(program: Command, context: KtxCliComm
registerConnectionNotionCommands(connection, context);
}
export function registerConnectionMappingCommands(connection: Command, context: KtxCliCommandContext): void {
function registerConnectionMappingCommands(connection: Command, context: KtxCliCommandContext): void {
const mapping = connection
.command('mapping')
.description('Manage Metabase warehouse mappings')

View file

@ -369,14 +369,6 @@ function setExpanded(state: PickerState, nodeId: string, value: boolean | 'toggl
return cloneState(state, { expanded });
}
function expandPath(state: PickerState, nodeId: string): PickerState {
const expanded = new Set(state.expanded);
for (const ancestorId of ancestorsOf(nodeId, state.byId)) {
expanded.add(ancestorId);
}
return cloneState(state, { expanded });
}
export function moveCursor(state: PickerState, dir: 'up' | 'down' | 'left' | 'right'): PickerState {
const node = state.byId.get(state.cursorId);
if (!node) {

View file

@ -1,6 +1,6 @@
/* @jsxImportSource react */
import { render as renderInkTest } from 'ink-testing-library';
import React, { act, type ReactNode } from 'react';
import { act, type ReactNode } from 'react';
import { afterEach, describe, expect, it, vi } from 'vitest';
import { buildInitialState, buildPickerTree, type NotionPickerPageInput } from './connection-notion-tree.js';
import {

View file

@ -1,6 +1,6 @@
/* @jsxImportSource react */
import { Box, Text, render as renderInkRuntime, useApp, useInput } from 'ink';
import React, { type ReactNode, useEffect, useMemo, useRef, useState } from 'react';
import { type ReactNode, useEffect, useMemo, useRef, useState } from 'react';
import {
filterTree,
flattenSelection,

View file

@ -1,4 +1,4 @@
import { mkdtemp, readFile, rm, writeFile } from 'node:fs/promises';
import { mkdtemp, rm } from 'node:fs/promises';
import { createRequire } from 'node:module';
import { tmpdir } from 'node:os';
import { join } from 'node:path';

View file

@ -1,10 +1,8 @@
import { EventEmitter } from 'node:events';
import { access, mkdir, mkdtemp, readFile, rm, writeFile } from 'node:fs/promises';
import { tmpdir } from 'node:os';
import { mkdir, writeFile } from 'node:fs/promises';
import { join } from 'node:path';
import { AgentRunnerService, type RunLoopParams } from '@ktx/context/agent';
import {
LocalLookerRuntimeStore,
LocalMetabaseSourceStateReader,
MetabaseSourceAdapter,
getLocalIngestStatus,
@ -12,12 +10,10 @@ import {
type FetchContext,
type IngestReportSnapshot,
type LocalIngestResult,
type LocalMetabaseFanoutProgress,
type LookerMappingClient,
type LookerRuntimeClient,
type LookerTableIdentifierParser,
type MemoryFlowEventSink,
type MemoryFlowReplayInput,
type MetabaseCard,
type MetabaseCardSummary,
type MetabaseClientFactory,
@ -28,7 +24,7 @@ import {
} from '@ktx/context/ingest';
import { ktxLocalStateDbPath, loadKtxProject } from '@ktx/context/project';
import { expect, vi } from 'vitest';
import { type KtxIngestArgs, runKtxIngest } from './ingest.js';
import { runKtxIngest } from './ingest.js';
export function makeIo(
options: {

View file

@ -4,10 +4,8 @@ import { join } from 'node:path';
import {
LocalLookerRuntimeStore,
LocalMetabaseSourceStateReader,
getLocalIngestStatus,
type LocalIngestResult,
type LocalMetabaseFanoutProgress,
type MemoryFlowReplayInput,
type RunLocalIngestOptions,
type SourceAdapter,
} from '@ktx/context/ingest';
@ -20,7 +18,6 @@ import {
CliMetabaseAgentRunner,
CliMetabaseSourceAdapter,
completedLocalBundleRun,
emitLiveLocalMemoryFlow,
failedLocalBundleRun,
localFakeBundleReport,
makeCliLookerParser,
@ -28,7 +25,6 @@ import {
makeIo,
persistLocalBundleReport,
runPublicMetabaseSyncModeCase,
writeBundleReportFile,
writeMetabaseConfig,
writeWarehouseConfig,
} from './ingest.test-utils.js';

View file

@ -1,7 +1,7 @@
/* @jsxImportSource react */
import type { MemoryFlowEvent, MemoryFlowReplayInput } from '@ktx/context/ingest/memory-flow';
import { Box, Text } from 'ink';
import React, { type ReactNode } from 'react';
import { type ReactNode } from 'react';
import { buildDemoMetrics, formatCost, formatDuration } from './demo-metrics.js';
import { formatNextStepLines } from './next-steps.js';
import { profileMark } from './startup-profile.js';
@ -38,45 +38,6 @@ function isPrepopulatedDemoReplay(input: MemoryFlowReplayInput): boolean {
return input.metadata?.origin === 'packaged' || input.metadata?.timing === 'prebuilt';
}
function flowLine(width: number, frame: number, active: boolean): string {
if (!active) return '━'.repeat(width);
const pulse = ['░', '▒', '▓', '█', '█', '█', '▓', '▒', '░'];
const pw = pulse.length;
const chars: string[] = [];
const offset = (frame * 2) % (width + pw);
for (let i = 0; i < width; i += 1) {
const p = i - offset + pw;
chars.push(p >= 0 && p < pw ? (pulse[p] ?? '━') : '━');
}
return chars.join('');
}
function brailleFlow(width: number, frame: number): string {
// Braille unicode: U+2800 + dot bitmask
// Dots: 1=0x01 2=0x02 3=0x04 4=0x08 5=0x10 6=0x20 7=0x40 8=0x80
// Layout: col0=[1,2,3,7] col1=[4,5,6,8]
const chars: string[] = [];
for (let i = 0; i < width; i += 1) {
const density = (i + 1) / width;
const phase = (i * 3 + frame * 2) % 12;
let dots = 0;
// Sparse diagonal streams on the left, dense on the right
// Each "stream" is a diagonal line of dots moving rightward
if ((phase + 0) % 4 < density * 4) dots |= 0x01; // dot 1
if ((phase + 1) % 5 < density * 4) dots |= 0x08; // dot 4
if ((phase + 2) % 4 < density * 3) dots |= 0x02; // dot 2
if ((phase + 3) % 5 < density * 3) dots |= 0x10; // dot 5
if ((phase + 4) % 4 < density * 2.5) dots |= 0x04; // dot 3
if ((phase + 5) % 5 < density * 2.5) dots |= 0x20; // dot 6
if ((phase + 1) % 6 < density * 2) dots |= 0x40; // dot 7
if ((phase + 3) % 6 < density * 2) dots |= 0x80; // dot 8
chars.push(String.fromCharCode(0x2800 + dots));
}
return chars.join('');
}
function progressBarOverall(
finishedCount: number,
activeCount: number,
@ -104,43 +65,6 @@ function progressBarOverall(
return finished + activeChars.join('') + '░'.repeat(queuedWidth);
}
function sparkleWipe(width: number, frame: number, row: number): string {
const chars: string[] = [];
const sweepPos = (frame * 2 + row * 6) % (width + 8);
const sparkles = ['✨', '✦', '✧', '·'];
for (let i = 0; i < width; i += 1) {
const dist = i - sweepPos;
if (dist < -6) {
const t = (i * 11 + row * 5 + frame * 3) % 10;
chars.push(t === 0 ? sparkles[0]! : t === 3 ? sparkles[1]! : t === 7 ? sparkles[2]! : ' ');
} else if (dist < -3) {
const t = (i + frame) % 3;
chars.push(t === 0 ? sparkles[1]! : t === 1 ? sparkles[2]! : sparkles[3]!);
} else if (dist <= 0) {
const gradient = ['░', '▒', '▓', '█'];
chars.push(gradient[Math.min(3, dist + 3)] ?? '█');
} else if (dist <= 2) {
chars.push(dist === 1 ? '▓' : '▒');
} else {
const noise = (i * 31 + row * 17 + frame * 3) % 5;
const messy = ['░', '▒', '▓', '▒', '░'];
chars.push(messy[noise] ?? '▒');
}
}
return chars.join('');
}
function activityWave(width: number, frame: number, offset: number): string {
const heights = ['▁', '▂', '▃', '▄', '▅', '▆', '▇', '█'];
const chars: string[] = [];
for (let i = 0; i < width; i += 1) {
const wave = Math.sin(((i * 2 + frame + offset * 5) * Math.PI) / 6);
const idx = Math.round(((wave + 1) / 2) * (heights.length - 1));
chars.push(heights[idx] ?? '▁');
}
return chars.join('');
}
function topicName(key: string): string {
return (key.split('/').pop()?.replace(/\.md$/, '') ?? key).replace(/[_-]/g, ' ');
}
@ -155,18 +79,9 @@ function humanizeInsight(key: string, target: 'sl' | 'wiki', summary: string | u
return target === 'sl' ? `Query definition: ${name}` : `Knowledge page: ${name}`;
}
const ADAPTER_PREFIXES = ['live_database_', 'metabase_', 'looker_', 'lookml_', 'metricflow_', 'notion_', 'historic_sql_', 'dbt_descriptions_'];
const INTERNAL_DEMO_CONNECTION_ID = 'orbit_demo';
const PUBLIC_DEMO_SOURCE_LABEL = 'Orbit Demo';
function humanizeUnitKey(unitKey: string): string {
let key = unitKey.replace(/-/g, '_');
for (const prefix of ADAPTER_PREFIXES) {
if (key.startsWith(prefix)) { key = key.slice(prefix.length); break; }
}
return key.replace(/_/g, ' ');
}
interface SourceInfo {
type: string;
name: string;
@ -224,13 +139,6 @@ function sourceDescription(input: MemoryFlowReplayInput): SourceInfo {
return { type: info.type, name: conn, sourceCount: count, itemNounPlural: info.plural, readingVerb: info.verb, ingestDescription: info.description };
}
function activeWorkUnit(
input: MemoryFlowReplayInput,
): { unitKey: string; stepIndex: number; stepBudget: number } | null {
const units = activeWorkUnits(input);
return units.at(-1) ?? null;
}
function activeWorkUnits(
input: MemoryFlowReplayInput,
): Array<{ unitKey: string; stepIndex: number; stepBudget: number }> {
@ -299,22 +207,6 @@ function finishedUnits(input: MemoryFlowReplayInput): Array<{ unitKey: string; a
return units;
}
function artifactCounts(input: MemoryFlowReplayInput): { sl: number; wiki: number } {
let sl = 0;
let wiki = 0;
for (const e of input.events) {
if (e.type === 'candidate_action') {
if (e.target === 'sl') sl++;
else wiki++;
}
}
return { sl, wiki };
}
function pad(str: string, width: number): string {
return str.length >= width ? str : str + ' '.repeat(width - str.length);
}
const KTX_LOGO_SMALL = [
'██╗ ██╗████████╗██╗ ██╗',
'██║ ██╔╝╚══██╔══╝╚██╗██╔╝',
@ -344,12 +236,7 @@ export function Hud(props: {
width: number;
now?: () => number;
}): ReactNode {
const isRunning = props.input.status === 'running';
const isDone = props.input.status === 'done';
const isFlowing = isRunning && hasWorkStarted(props.input);
const src = sourceDescription(props.input);
const counts = artifactCounts(props.input);
const metrics = buildDemoMetrics(props.input, props.now ? { now: props.now } : {});
const workStarted = hasWorkStarted(props.input);
@ -358,11 +245,6 @@ export function Hud(props: {
const innerWidth = Math.max(60, props.width - 6);
const actives = activeWorkUnits(props.input);
const reconEvent = props.input.events.find((e) => e.type === 'reconciliation_finished');
const allAnalyzed = isFlowing && actives.length === 0;
const isReconciling = allAnalyzed && !reconEvent && !isDone;
const hLine = '─'.repeat(innerWidth);
const elapsed = formatDuration(metrics.elapsedMs);
@ -429,7 +311,6 @@ export function ActivityFeed(props: {
const workStarted = hasWorkStarted(props.input);
const totalChunks = planEvent?.chunkCount ?? 0;
const finishedWithArtifacts = finished.filter((u) => u.artifactCount > 0);
const finishedAreas = totalChunks > 0 ? Math.min(finished.length, totalChunks) : finished.length;
const allWorkDone = workStarted && actives.length === 0 && queued.length === 0;
const isReconciling = allWorkDone && !reconEvent && !isDone && !isError;

View file

@ -11,7 +11,6 @@ import {
startLiveMemoryFlowTui,
type KtxMemoryFlowTuiIo,
type MemoryFlowInkInstance,
type MemoryFlowInkRenderOptions,
} from './memory-flow-tui.js';
function replayInput(): MemoryFlowReplayInput {

View file

@ -1,7 +1,6 @@
/* @jsxImportSource react */
import {
buildMemoryFlowViewModel,
buildMemoryFlowVisualModel,
createInitialMemoryFlowInteractionState,
findMemoryFlowSearchMatches,
type MemoryFlowColumnId,
@ -14,8 +13,7 @@ import {
selectedMemoryFlowDetails,
} from '@ktx/context/ingest';
import { Box, Text, render as renderInkRuntime, useApp, useInput } from 'ink';
import React, { type ReactNode, useEffect, useMemo, useRef, useState } from 'react';
import { buildDemoMetrics } from './demo-metrics.js';
import { type ReactNode, useEffect, useMemo, useRef, useState } from 'react';
import {
ActivityFeed,
Hud,
@ -201,14 +199,6 @@ function stageLabel(columnId: MemoryFlowColumnId): string {
return STAGE_LABELS[columnId];
}
function statusLabel(status: string): 'OK' | 'RUN' | 'WARN' | 'FAIL' | 'WAIT' {
if (status === 'complete') return 'OK';
if (status === 'active') return 'RUN';
if (status === 'warning') return 'WARN';
if (status === 'failed') return 'FAIL';
return 'WAIT';
}
function filterLabel(filter: MemoryFlowInteractionState['filter']): string {
return filter === 'failed_or_flagged' ? 'issues' : 'all';
}
@ -325,7 +315,6 @@ export function MemoryFlowTuiApp(props: MemoryFlowTuiAppProps): ReactNode {
const view = useMemo(() => buildMemoryFlowViewModel(pacedInput), [pacedInput]);
const [state, setState] = useState<MemoryFlowInteractionState>(() => createInitialMemoryFlowInteractionState(view));
const [frame, setFrame] = useState(0);
const [thoughtFrame, setThoughtFrame] = useState(0);
const [completionFrame, setCompletionFrame] = useState(0);
const [holdComplete, setHoldComplete] = useState(false);
const [userHasNavigated, setUserHasNavigated] = useState(false);
@ -346,7 +335,6 @@ export function MemoryFlowTuiApp(props: MemoryFlowTuiAppProps): ReactNode {
useEffect(() => {
const timer = setInterval(() => {
setFrame((current) => current + 1);
setThoughtFrame((current) => current + 1);
}, props.frameMs ?? DEFAULT_TUI_TIMING.frameMs);
return () => clearInterval(timer);
}, [props.frameMs]);
@ -354,7 +342,6 @@ export function MemoryFlowTuiApp(props: MemoryFlowTuiAppProps): ReactNode {
useEffect(() => {
if (lastEventCountRef.current !== pacedInput.events.length) {
lastEventCountRef.current = pacedInput.events.length;
setThoughtFrame(0);
}
}, [pacedInput.events.length]);
@ -409,10 +396,6 @@ export function MemoryFlowTuiApp(props: MemoryFlowTuiAppProps): ReactNode {
});
const isComplete = pacedInput.status === 'done' || pacedInput.status === 'error';
const completionMetrics = useMemo(
() => buildDemoMetrics(pacedInput, pacedNow ? { now: pacedNow } : {}),
[pacedInput, pacedNow],
);
const termWidth = props.terminalWidth ?? 80;

View file

@ -1,5 +0,0 @@
import { resolve } from 'node:path';
export function resolveProjectDir(projectDir?: string, fallback = '.'): string {
return resolve(projectDir ?? fallback);
}

View file

@ -6,9 +6,9 @@ import { profileMark } from './startup-profile.js';
profileMark('module:public-ingest');
export type KtxPublicIngestStepName = 'scan' | 'source-ingest' | 'enrich' | 'memory-update';
export type KtxPublicIngestStepStatus = 'done' | 'skipped' | 'failed' | 'not-run';
export type KtxPublicIngestInputMode = 'auto' | 'disabled';
type KtxPublicIngestStepName = 'scan' | 'source-ingest' | 'enrich' | 'memory-update';
type KtxPublicIngestStepStatus = 'done' | 'skipped' | 'failed' | 'not-run';
type KtxPublicIngestInputMode = 'auto' | 'disabled';
export type KtxPublicIngestArgs =
| {

View file

@ -474,16 +474,6 @@ async function markContextComplete(projectDir: string): Promise<void> {
await markKtxSetupStateStepComplete(projectDir, 'context');
}
function writeBuildHeader(projectDir: string, runId: string, io: KtxCliIo): void {
const commands = contextBuildCommands(projectDir, runId);
io.stdout.write('\nKTX context build\n');
io.stdout.write(`Run: ${runId}\n`);
io.stdout.write(`Project: ${resolve(projectDir)}\n\n`);
io.stdout.write('Detach: press d to leave this running.\n');
io.stdout.write(`Resume: ${commands.watch}\n`);
io.stdout.write(`Status: ${commands.status}\n\n`);
}
function writeMissingCapabilities(missing: string[], io: KtxCliIo): void {
io.stderr.write('KTX cannot build agent-ready context yet.\n\n');
io.stderr.write('Missing:\n');

View file

@ -126,10 +126,6 @@ async function writeSqliteScanConfig(projectDir: string, dbPath: string, enrich
);
}
function parseJsonOutput<T>(stdout: string): T {
return JSON.parse(stdout) as T;
}
function expectProjectStderr(result: CliResult, projectDir: string): void {
expect(result).toMatchObject({ code: 0, stderr: `Project: ${projectDir}\n` });
}

View file

@ -53,7 +53,6 @@ function fixSuggestions(input: MemoryFlowReplayInput): string[] {
export function formatMemoryFlowFinalSummary(input: MemoryFlowReplayInput): string {
const sources = eventsOf(input.events, 'source_acquired');
const source = sources.at(-1);
const totalFiles = sources.reduce((sum, s) => sum + s.fileCount, 0);
const saved = latest(input.events, 'saved');
const provenance = latest(input.events, 'provenance_recorded');

View file

@ -68,15 +68,6 @@ export interface KtxDescriptionUpdate {
columnDescriptions?: Record<string, string | null>;
}
const PREFERRED_METADATA_FIELD_NAMES = [
'tags',
'constraints',
'enum_values',
'freshness',
'tests',
'lineage',
] as const;
export interface KtxMetadataUpdate {
connectionId: string;
table: KtxTableRef;

611
pnpm-lock.yaml generated
View file

@ -12,15 +12,24 @@ importers:
.:
devDependencies:
'@biomejs/biome':
specifier: ^2.4.15
version: 2.4.15
'@types/node':
specifier: ^24.3.0
version: 24.12.2
better-sqlite3:
specifier: ^12.10.0
version: 12.10.0
knip:
specifier: ^6.12.2
version: 6.12.2(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)
typescript:
specifier: ^6.0.3
version: 6.0.3
vitest:
specifier: ^4.1.6
version: 4.1.6(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(vite@8.0.10(@types/node@24.12.2)(esbuild@0.28.0)(jiti@2.7.0)(yaml@2.9.0))
yaml:
specifier: ^2.9.0
version: 2.9.0
docs-site:
dependencies:
@ -741,6 +750,63 @@ packages:
resolution: {integrity: sha512-SriLPKezypIsiZ+TtlFfE46uuBIap2HeaQVS78e1P7rz5OSbq0rsd52WE1mC5f7vAeLiXqv7I7oRhL3WFZEw3Q==}
engines: {node: '>=18.0.0'}
'@biomejs/biome@2.4.15':
resolution: {integrity: sha512-j5VH3a/h/HXTKBM50MDMxRCzkeLv9S2XJcW2WgnZT1+xyisi+0bISrXR82gCX+8S9lvK0skEvHJRN+3Ktr2hlw==}
engines: {node: '>=14.21.3'}
hasBin: true
'@biomejs/cli-darwin-arm64@2.4.15':
resolution: {integrity: sha512-rF3PPqLq1yoST79zaQbDjVJwsuIeci/O+9bgNmC5QpgOqz6aqYuzA4abyAGx+mgyiDXn4A049xAN8gijbuR1Qg==}
engines: {node: '>=14.21.3'}
cpu: [arm64]
os: [darwin]
'@biomejs/cli-darwin-x64@2.4.15':
resolution: {integrity: sha512-/5KHXYMfSJs1fNXiX30xFtI8JcCFV6zaVVLxOa0M2sfqBKHkpQhRTv94yxQWxeTY2lzo2OuTlNvPC+hDQt2wcQ==}
engines: {node: '>=14.21.3'}
cpu: [x64]
os: [darwin]
'@biomejs/cli-linux-arm64-musl@2.4.15':
resolution: {integrity: sha512-ZPcxznxm0pogHBLZhYntyR3sR+MrZjqJIKEr7ZqVen0Rl+P/4upVmfYXjftizi9RoqZntg33fv/1fbdhbYXpEQ==}
engines: {node: '>=14.21.3'}
cpu: [arm64]
os: [linux]
libc: [musl]
'@biomejs/cli-linux-arm64@2.4.15':
resolution: {integrity: sha512-owaAMZD/T4LrD0ELNCk0Km3qrRHuM0X6EAyVE1FSqGY0rbLoiDLrO4Us2tllm6cAeB2Ioa9C2C08NZPdr8+0Ug==}
engines: {node: '>=14.21.3'}
cpu: [arm64]
os: [linux]
libc: [glibc]
'@biomejs/cli-linux-x64-musl@2.4.15':
resolution: {integrity: sha512-CNq/9W38SYSH023lfcQ4KKU8K0YX8T//FZUhcgtMMRABDojx5XsMV7jlweAvGSl389wJQB29Qo6Zb/a+jdvt+w==}
engines: {node: '>=14.21.3'}
cpu: [x64]
os: [linux]
libc: [musl]
'@biomejs/cli-linux-x64@2.4.15':
resolution: {integrity: sha512-0jj7THz12GbUOLmMibktK6DZjqz2zV64KFxyBtcFTKPiiOIY0a7vns1elpO1dERvxpsZ5ik0oFfz0oGwFde1+g==}
engines: {node: '>=14.21.3'}
cpu: [x64]
os: [linux]
libc: [glibc]
'@biomejs/cli-win32-arm64@2.4.15':
resolution: {integrity: sha512-ouhkYdlhp/1GghEJPdWwD/Vi3gQ1nFxuSpMolWsbq3Lsq3QUR4jl6UdhhscdCugKU5vOEuMiJhvKj66O0OCq+w==}
engines: {node: '>=14.21.3'}
cpu: [arm64]
os: [win32]
'@biomejs/cli-win32-x64@2.4.15':
resolution: {integrity: sha512-zBrGq5mx5wwpnow4+2BxUvleDM+GNd4sLbPaMapsSLQLD0NGRCquqPBTgN+7XkUteHvj7M+BstuI8tmnV7+HgQ==}
engines: {node: '>=14.21.3'}
cpu: [x64]
os: [win32]
'@clack/core@1.3.1':
resolution: {integrity: sha512-fT1qHVGAag4IEkrupZ6lRRbNCs1vS9P01KB/sG8zKgvUztbYtFBtQpjSITNwooDZ83tpsPzP0mRNs1/KVszCRA==}
engines: {node: '>= 20.12.0'}
@ -1317,9 +1383,247 @@ packages:
resolution: {integrity: sha512-a61ljmRVVyG5MC/698C8/FfFDw5a8LOIvyOLW5fztgUXqUpc1jOfQzOitSCbge657OgXXThmY3Tk8fpiDb4UcA==}
engines: {node: '>= 20.0.0'}
'@oxc-parser/binding-android-arm-eabi@0.128.0':
resolution: {integrity: sha512-aca6ZvzmCBUGOANQRiRQRZuRKYI3ENhcit6GisnknOOmcezfQc7xJ4dxlPU7MV7mOvrC7RNR1u3LAD7xyaiCxA==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm]
os: [android]
'@oxc-parser/binding-android-arm64@0.128.0':
resolution: {integrity: sha512-BbeDmuohoJ7Rz/it5wnkj69i/OsCPS3Z51nLEzwO/Y6YshtC4JU+15oNwhY8v4LRKRYclRc7ggOikwrsJ/eOEQ==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64]
os: [android]
'@oxc-parser/binding-darwin-arm64@0.128.0':
resolution: {integrity: sha512-tRUHPt80417QmvNpoSslJT1VY8NUbWdrWR+L14Zn+RbOTcaqB8E6PYE/ZGN8jjWBzqporiA/H4MfO50ew/NCNA==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64]
os: [darwin]
'@oxc-parser/binding-darwin-x64@0.128.0':
resolution: {integrity: sha512-rWI2Hb1Nt3U/vKsjyNvZzDC8i/l144U20DKjhzaTmwIhIiSRGeroPWWiImwypmKLqrw8GuIixbWJkpGWLbkzrQ==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64]
os: [darwin]
'@oxc-parser/binding-freebsd-x64@0.128.0':
resolution: {integrity: sha512-hhpdVMaNCLgQxjgNPeeFzSeJMmZPc5lKfv0NGSI3egZq9EdnEGqeC8JsYsQjK7PoQgbvZ17xlj0SO5ziH5Obkg==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64]
os: [freebsd]
'@oxc-parser/binding-linux-arm-gnueabihf@0.128.0':
resolution: {integrity: sha512-093zNw0zZ/e/obML+rhlSdmnzR0mVZluPcAkxunEc5E3F0yBVsFn24Y1ILfsEte11Ud041qn/gp2OJ1jxNqUng==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm]
os: [linux]
'@oxc-parser/binding-linux-arm-musleabihf@0.128.0':
resolution: {integrity: sha512-fq7DmKmfC+dvD97IXrgbph6Jzwe0EDu+PYMofmzZ6fv5X1k9vtaqLpDGMuICO9MmUnyKAQmVl+wIv2RNy4Dz8g==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm]
os: [linux]
'@oxc-parser/binding-linux-arm64-gnu@0.128.0':
resolution: {integrity: sha512-Xvm48jJah8TlIrURIjNOP/gNiGe6aKvCB+r06VliflFo8Kq7VOLE8PxtgShJzZIqubrgdMdYfvuPPozn7F6MbQ==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64]
os: [linux]
libc: [glibc]
'@oxc-parser/binding-linux-arm64-musl@0.128.0':
resolution: {integrity: sha512-M7iwBGmYJTx+pKOYFjI0buop4gJvlmcVzFGaXPt21DKpQkbQZG1f63Yg7LloIYT/t9yLxCw0Lhfx/RFlAlMSjA==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64]
os: [linux]
libc: [musl]
'@oxc-parser/binding-linux-ppc64-gnu@0.128.0':
resolution: {integrity: sha512-21LGNIZb1Pcfk5/EGsqabrxv4yqQOWis1407JJrClS7XpFCrbvr74YAB1V+m54cYbwvO6UWwQqS4WecxiyfCRg==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [ppc64]
os: [linux]
libc: [glibc]
'@oxc-parser/binding-linux-riscv64-gnu@0.128.0':
resolution: {integrity: sha512-gyHjOTFpg9bTTYjxPmQirvufb89+VdZwVfcMtAUyPr6F5H8ZswvCQshK4qOW+Q+2Xyb33hduRgY/eFHJQjU/vQ==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [riscv64]
os: [linux]
libc: [glibc]
'@oxc-parser/binding-linux-riscv64-musl@0.128.0':
resolution: {integrity: sha512-X6Q2oKUrP5GyDd2xniuEBLk6aFQCZ97W2+aVXGgJXdjx5t4/oFuA9ri0wLOUrBIX+qdSuK581snMBio4z910eA==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [riscv64]
os: [linux]
libc: [musl]
'@oxc-parser/binding-linux-s390x-gnu@0.128.0':
resolution: {integrity: sha512-BdzTmqxfxoYkpgokoLaSnOX6T+R3/goL42klre2tnG+kHbG2TXS0VN+P5BPofH1axdKOHy5ei4ENZrjmCOt2lA==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [s390x]
os: [linux]
libc: [glibc]
'@oxc-parser/binding-linux-x64-gnu@0.128.0':
resolution: {integrity: sha512-OO1nW2Q7sSYYvJZpDHdvyFSdRaVcQqRijZSSmWVMqFxPYy8cEF45zJ9fcdIYuzIT3jYq6YRhEFm/VMWNWhE22Q==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64]
os: [linux]
libc: [glibc]
'@oxc-parser/binding-linux-x64-musl@0.128.0':
resolution: {integrity: sha512-4NehAe404MRdoZVS9DW8C5XbJwbXIc/KfVlYdpi5vE4081zc9Y0YzKVqyOYj/Puye7/Do+ohaONBFWlEHYl9hw==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64]
os: [linux]
libc: [musl]
'@oxc-parser/binding-openharmony-arm64@0.128.0':
resolution: {integrity: sha512-kVbqgW9xLL8bh8oc7aYOJilRKXE5G33+tE0jan+duo/9OriaFRpijcCwT2waWs2oqYROYq0GlE7/p3ywoshVeg==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64]
os: [openharmony]
'@oxc-parser/binding-wasm32-wasi@0.128.0':
resolution: {integrity: sha512-L38ojghJYHmgiz6fJd7jwLB/ESDBpB02NdFxh+smqVM6P2anCEvHn0jhaSrt5eVNR1Ak8+moOeftUlofeyvniA==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [wasm32]
'@oxc-parser/binding-win32-arm64-msvc@0.128.0':
resolution: {integrity: sha512-xgvO35GyHBtjlQ5AEpaYr7Rll1rvY7zqIhT6ty8E3ezBW2J1SFLjIDEvI/tcgDg6oaseDAqVcM+jU1HuCekgZw==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64]
os: [win32]
'@oxc-parser/binding-win32-ia32-msvc@0.128.0':
resolution: {integrity: sha512-OY+3eM2SN72prHKRB22mPz8o5A/7dJ+f5DFLBVvggyZhEaNDAH9IB+ElMjmOkOIwf5MDCUAowCK7pAncNxzpBA==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [ia32]
os: [win32]
'@oxc-parser/binding-win32-x64-msvc@0.128.0':
resolution: {integrity: sha512-NE9ny+cPUCCObXa0IKLfj0tCdPd7pe/dz9ZpkxpUOymB3miNeMPybdlYYTBSGJUalMWeBM85/4JcCErCNTqOXw==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64]
os: [win32]
'@oxc-project/types@0.127.0':
resolution: {integrity: sha512-aIYXQBo4lCbO4z0R3FHeucQHpF46l2LbMdxRvqvuRuW2OxdnSkcng5B8+K12spgLDj93rtN3+J2Vac/TIO+ciQ==}
'@oxc-project/types@0.128.0':
resolution: {integrity: sha512-huv1Y/LzBJkBVHt3OlC7u0zHBW9qXf1FdD7sGmc1rXc2P1mTwHssYv7jyGx5KAACSCH+9B3Bhn6Z9luHRvf7pQ==}
'@oxc-resolver/binding-android-arm-eabi@11.19.1':
resolution: {integrity: sha512-aUs47y+xyXHUKlbhqHUjBABjvycq6YSD7bpxSW7vplUmdzAlJ93yXY6ZR0c1o1x5A/QKbENCvs3+NlY8IpIVzg==}
cpu: [arm]
os: [android]
'@oxc-resolver/binding-android-arm64@11.19.1':
resolution: {integrity: sha512-oolbkRX+m7Pq2LNjr/kKgYeC7bRDMVTWPgxBGMjSpZi/+UskVo4jsMU3MLheZV55jL6c3rNelPl4oD60ggYmqA==}
cpu: [arm64]
os: [android]
'@oxc-resolver/binding-darwin-arm64@11.19.1':
resolution: {integrity: sha512-nUC6d2i3R5B12sUW4O646qD5cnMXf2oBGPLIIeaRfU9doJRORAbE2SGv4eW6rMqhD+G7nf2Y8TTJTLiiO3Q/dQ==}
cpu: [arm64]
os: [darwin]
'@oxc-resolver/binding-darwin-x64@11.19.1':
resolution: {integrity: sha512-cV50vE5+uAgNcFa3QY1JOeKDSkM/9ReIcc/9wn4TavhW/itkDGrXhw9jaKnkQnGbjJ198Yh5nbX/Gr2mr4Z5jQ==}
cpu: [x64]
os: [darwin]
'@oxc-resolver/binding-freebsd-x64@11.19.1':
resolution: {integrity: sha512-xZOQiYGFxtk48PBKff+Zwoym7ScPAIVp4c14lfLxizO2LTTTJe5sx9vQNGrBymrf/vatSPNMD4FgsaaRigPkqw==}
cpu: [x64]
os: [freebsd]
'@oxc-resolver/binding-linux-arm-gnueabihf@11.19.1':
resolution: {integrity: sha512-lXZYWAC6kaGe/ky2su94e9jN9t6M0/6c+GrSlCqL//XO1cxi5lpAhnJYdyrKfm0ZEr/c7RNyAx3P7FSBcBd5+A==}
cpu: [arm]
os: [linux]
'@oxc-resolver/binding-linux-arm-musleabihf@11.19.1':
resolution: {integrity: sha512-veG1kKsuK5+t2IsO9q0DErYVSw2azvCVvWHnfTOS73WE0STdLLB7Q1bB9WR+yHPQM76ASkFyRbogWo1GR1+WbQ==}
cpu: [arm]
os: [linux]
'@oxc-resolver/binding-linux-arm64-gnu@11.19.1':
resolution: {integrity: sha512-heV2+jmXyYnUrpUXSPugqWDRpnsQcDm2AX4wzTuvgdlZfoNYO0O3W2AVpJYaDn9AG4JdM6Kxom8+foE7/BcSig==}
cpu: [arm64]
os: [linux]
libc: [glibc]
'@oxc-resolver/binding-linux-arm64-musl@11.19.1':
resolution: {integrity: sha512-jvo2Pjs1c9KPxMuMPIeQsgu0mOJF9rEb3y3TdpsrqwxRM+AN6/nDDwv45n5ZrUnQMsdBy5gIabioMKnQfWo9ew==}
cpu: [arm64]
os: [linux]
libc: [musl]
'@oxc-resolver/binding-linux-ppc64-gnu@11.19.1':
resolution: {integrity: sha512-vLmdNxWCdN7Uo5suays6A/+ywBby2PWBBPXctWPg5V0+eVuzsJxgAn6MMB4mPlshskYbppjpN2Zg83ArHze9gQ==}
cpu: [ppc64]
os: [linux]
libc: [glibc]
'@oxc-resolver/binding-linux-riscv64-gnu@11.19.1':
resolution: {integrity: sha512-/b+WgR+VTSBxzgOhDO7TlMXC1ufPIMR6Vj1zN+/x+MnyXGW7prTLzU9eW85Aj7Th7CCEG9ArCbTeqxCzFWdg2w==}
cpu: [riscv64]
os: [linux]
libc: [glibc]
'@oxc-resolver/binding-linux-riscv64-musl@11.19.1':
resolution: {integrity: sha512-YlRdeWb9j42p29ROh+h4eg/OQ3dTJlpHSa+84pUM9+p6i3djtPz1q55yLJhgW9XfDch7FN1pQ/Vd6YP+xfRIuw==}
cpu: [riscv64]
os: [linux]
libc: [musl]
'@oxc-resolver/binding-linux-s390x-gnu@11.19.1':
resolution: {integrity: sha512-EDpafVOQWF8/MJynsjOGFThcqhRHy417sRyLfQmeiamJ8qVhSKAn2Dn2VVKUGCjVB9C46VGjhNo7nOPUi1x6uA==}
cpu: [s390x]
os: [linux]
libc: [glibc]
'@oxc-resolver/binding-linux-x64-gnu@11.19.1':
resolution: {integrity: sha512-NxjZe+rqWhr+RT8/Ik+5ptA3oz7tUw361Wa5RWQXKnfqwSSHdHyrw6IdcTfYuml9dM856AlKWZIUXDmA9kkiBQ==}
cpu: [x64]
os: [linux]
libc: [glibc]
'@oxc-resolver/binding-linux-x64-musl@11.19.1':
resolution: {integrity: sha512-cM/hQwsO3ReJg5kR+SpI69DMfvNCp+A/eVR4b4YClE5bVZwz8rh2Nh05InhwI5HR/9cArbEkzMjcKgTHS6UaNw==}
cpu: [x64]
os: [linux]
libc: [musl]
'@oxc-resolver/binding-openharmony-arm64@11.19.1':
resolution: {integrity: sha512-QF080IowFB0+9Rh6RcD19bdgh49BpQHUW5TajG1qvWHvmrQznTZZjYlgE2ltLXyKY+qs4F/v5xuX1XS7Is+3qA==}
cpu: [arm64]
os: [openharmony]
'@oxc-resolver/binding-wasm32-wasi@11.19.1':
resolution: {integrity: sha512-w8UCKhX826cP/ZLokXDS6+milN8y4X7zidsAttEdWlVoamTNf6lhBJldaWr3ukTDiye7s4HRcuPEPOXNC432Vg==}
engines: {node: '>=14.0.0'}
cpu: [wasm32]
'@oxc-resolver/binding-win32-arm64-msvc@11.19.1':
resolution: {integrity: sha512-nJ4AsUVZrVKwnU/QRdzPCCrO0TrabBqgJ8pJhXITdZGYOV28TIYystV1VFLbQ7DtAcaBHpocT5/ZJnF78YJPtQ==}
cpu: [arm64]
os: [win32]
'@oxc-resolver/binding-win32-ia32-msvc@11.19.1':
resolution: {integrity: sha512-EW+ND5q2Tl+a3pH81l1QbfgbF3HmqgwLfDfVithRFheac8OTcnbXt/JxqD2GbDkb7xYEqy1zNaVFRr3oeG8npA==}
cpu: [ia32]
os: [win32]
'@oxc-resolver/binding-win32-x64-msvc@11.19.1':
resolution: {integrity: sha512-6hIU3RQu45B+VNTY4Ru8ppFwjVS/S5qwYyGhBotmjxfEKk41I2DlGtRfGJndZ5+6lneE2pwloqunlOyZuX/XAw==}
cpu: [x64]
os: [win32]
'@radix-ui/number@1.1.1':
resolution: {integrity: sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g==}
@ -2799,6 +3103,9 @@ packages:
resolution: {integrity: sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==}
engines: {node: '>= 4.9.1'}
fd-package-json@2.0.0:
resolution: {integrity: sha512-jKmm9YtsNXN789RS/0mSzOC1NUq9mkVd65vbSSVsKdjGvYXBuE4oWe2QOEoFeRmJg+lPuZxpmrfFclNhoRMneQ==}
fdir@6.5.0:
resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==}
engines: {node: '>=12.0.0'}
@ -2838,6 +3145,11 @@ packages:
resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==}
engines: {node: '>= 6'}
formatly@0.3.0:
resolution: {integrity: sha512-9XNj/o4wrRFyhSMJOvsuyMwy8aUfBaZ1VrqHVfohyXf0Sw0e+yfKG+xZaY3arGCOMdwFsqObtzVOc1gU9KiT9w==}
engines: {node: '>=18.3.0'}
hasBin: true
formdata-polyfill@4.0.10:
resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==}
engines: {node: '>=12.20.0'}
@ -3019,6 +3331,9 @@ packages:
resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==}
engines: {node: '>= 0.4'}
get-tsconfig@4.14.0:
resolution: {integrity: sha512-yTb+8DXzDREzgvYmh6s9vHsSVCHeC0G3PI5bEXNBHtmshPnO+S5O7qgLEOn0I5QvMy6kpZN8K1NKGyilLb93wA==}
github-from-package@0.0.0:
resolution: {integrity: sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==}
@ -3269,6 +3584,11 @@ packages:
jws@4.0.1:
resolution: {integrity: sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==}
knip@6.12.2:
resolution: {integrity: sha512-RcZpT1sVziKZgDk1F0hAcp+bq71VJAF8vg1Y9ZLXc1+UXQaMm1rjiUqpJQTIj+lqwmiBQT19/u7ikgazs23cvA==}
engines: {node: ^20.19.0 || >=22.12.0}
hasBin: true
kuler@2.0.0:
resolution: {integrity: sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==}
@ -3766,6 +4086,13 @@ packages:
zod:
optional: true
oxc-parser@0.128.0:
resolution: {integrity: sha512-XkOw3eiIxAgQ19WRew/Bq9wc5Ga/guaWIzDBzq80z1PyuDNGvWBpPby9k6YGwV8A8uMw+Nlq3xqlzuDYmUFYUw==}
engines: {node: ^20.19.0 || >=22.12.0}
oxc-resolver@11.19.1:
resolution: {integrity: sha512-qE/CIg/spwrTBFt5aKmwe3ifeDdLfA2NESN30E42X/lII5ClF8V7Wt6WIJhcGZjp0/Q+nQ+9vgxGk//xZNX2hg==}
p-limit@7.3.0:
resolution: {integrity: sha512-7cIXg/Z0M5WZRblrsOla88S4wAK+zOQQWeBYfV3qJuJXMr+LnbYjaadrFaS0JILfEDPVqHyKnZ1Z/1d6J9VVUw==}
engines: {node: '>=20'}
@ -4028,6 +4355,9 @@ packages:
resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==}
engines: {node: '>=0.10.0'}
resolve-pkg-maps@1.0.0:
resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==}
restore-cursor@4.0.0:
resolution: {integrity: sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
@ -4138,6 +4468,10 @@ packages:
resolution: {integrity: sha512-SO/3iYL5S3W57LLEniscOGPZgOqZUPCx6d3dB+52B80yJ0XstzsC/eV8gnA4tM3MHDrKz+OCFSLNjswdSC+/bA==}
engines: {node: '>=22'}
smol-toml@1.6.1:
resolution: {integrity: sha512-dWUG8F5sIIARXih1DTaQAX4SsiTXhInKf1buxdY9DIg4ZYPZK5nGM1VRIYmEbDbsHt7USo99xSLFu5Q1IqTmsg==}
engines: {node: '>= 18'}
snowflake-sdk@2.4.1:
resolution: {integrity: sha512-JIdqz9ed2FzkU8oEstf06hTJRoX9+PRRG9LJT1vfGTXN3A52kGxhGoWzmK0GtFTUnxTMxMoMYgD5QdoQbckyag==}
engines: {node: '>=18'}
@ -4211,6 +4545,10 @@ packages:
resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==}
engines: {node: '>=0.10.0'}
strip-json-comments@5.0.3:
resolution: {integrity: sha512-1tB5mhVo7U+ETBKNf92xT4hrQa3pm0MZ0PQvuDnWgAAGHDsfp4lPSpiS6psrSiet87wyGPh9ft6wmhOMQ0hDiw==}
engines: {node: '>=14.16'}
strnum@2.2.3:
resolution: {integrity: sha512-oKx6RUCuHfT3oyVjtnrmn19H1SiCqgJSg+54XqURKp5aCMbrXrhLjRN9TjuwMjiYstZ0MzDrHqkGZ5dFTKd+zg==}
@ -4336,6 +4674,10 @@ packages:
engines: {node: '>=0.8.0'}
hasBin: true
unbash@3.0.0:
resolution: {integrity: sha512-FeFPZ/WFT0mbRCuydiZzpPFlrYN8ZUpphQKoq4EeElVIYjYyGzPMxQR/simUwCOJIyVhpFk4RbtyO7RuMpMnHA==}
engines: {node: '>=14'}
undici-types@7.16.0:
resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==}
@ -4487,6 +4829,10 @@ packages:
jsdom:
optional: true
walk-up-path@4.0.0:
resolution: {integrity: sha512-3hu+tD8YzSLGuFYtPRb48vdhKMi0KQV5sn+uWr8+7dMEq/2G/dtLrdDinkLjqq5TIbIBjYJ4Ax/n3YiaW7QM8A==}
engines: {node: 20 || >=22}
web-namespaces@2.0.1:
resolution: {integrity: sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==}
@ -5546,6 +5892,41 @@ snapshots:
transitivePeerDependencies:
- supports-color
'@biomejs/biome@2.4.15':
optionalDependencies:
'@biomejs/cli-darwin-arm64': 2.4.15
'@biomejs/cli-darwin-x64': 2.4.15
'@biomejs/cli-linux-arm64': 2.4.15
'@biomejs/cli-linux-arm64-musl': 2.4.15
'@biomejs/cli-linux-x64': 2.4.15
'@biomejs/cli-linux-x64-musl': 2.4.15
'@biomejs/cli-win32-arm64': 2.4.15
'@biomejs/cli-win32-x64': 2.4.15
'@biomejs/cli-darwin-arm64@2.4.15':
optional: true
'@biomejs/cli-darwin-x64@2.4.15':
optional: true
'@biomejs/cli-linux-arm64-musl@2.4.15':
optional: true
'@biomejs/cli-linux-arm64@2.4.15':
optional: true
'@biomejs/cli-linux-x64-musl@2.4.15':
optional: true
'@biomejs/cli-linux-x64@2.4.15':
optional: true
'@biomejs/cli-win32-arm64@2.4.15':
optional: true
'@biomejs/cli-win32-x64@2.4.15':
optional: true
'@clack/core@1.3.1':
dependencies:
fast-wrap-ansi: 0.2.0
@ -6130,8 +6511,139 @@ snapshots:
'@orama/orama@3.1.18': {}
'@oxc-parser/binding-android-arm-eabi@0.128.0':
optional: true
'@oxc-parser/binding-android-arm64@0.128.0':
optional: true
'@oxc-parser/binding-darwin-arm64@0.128.0':
optional: true
'@oxc-parser/binding-darwin-x64@0.128.0':
optional: true
'@oxc-parser/binding-freebsd-x64@0.128.0':
optional: true
'@oxc-parser/binding-linux-arm-gnueabihf@0.128.0':
optional: true
'@oxc-parser/binding-linux-arm-musleabihf@0.128.0':
optional: true
'@oxc-parser/binding-linux-arm64-gnu@0.128.0':
optional: true
'@oxc-parser/binding-linux-arm64-musl@0.128.0':
optional: true
'@oxc-parser/binding-linux-ppc64-gnu@0.128.0':
optional: true
'@oxc-parser/binding-linux-riscv64-gnu@0.128.0':
optional: true
'@oxc-parser/binding-linux-riscv64-musl@0.128.0':
optional: true
'@oxc-parser/binding-linux-s390x-gnu@0.128.0':
optional: true
'@oxc-parser/binding-linux-x64-gnu@0.128.0':
optional: true
'@oxc-parser/binding-linux-x64-musl@0.128.0':
optional: true
'@oxc-parser/binding-openharmony-arm64@0.128.0':
optional: true
'@oxc-parser/binding-wasm32-wasi@0.128.0':
dependencies:
'@emnapi/core': 1.10.0
'@emnapi/runtime': 1.10.0
'@napi-rs/wasm-runtime': 1.1.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)
optional: true
'@oxc-parser/binding-win32-arm64-msvc@0.128.0':
optional: true
'@oxc-parser/binding-win32-ia32-msvc@0.128.0':
optional: true
'@oxc-parser/binding-win32-x64-msvc@0.128.0':
optional: true
'@oxc-project/types@0.127.0': {}
'@oxc-project/types@0.128.0': {}
'@oxc-resolver/binding-android-arm-eabi@11.19.1':
optional: true
'@oxc-resolver/binding-android-arm64@11.19.1':
optional: true
'@oxc-resolver/binding-darwin-arm64@11.19.1':
optional: true
'@oxc-resolver/binding-darwin-x64@11.19.1':
optional: true
'@oxc-resolver/binding-freebsd-x64@11.19.1':
optional: true
'@oxc-resolver/binding-linux-arm-gnueabihf@11.19.1':
optional: true
'@oxc-resolver/binding-linux-arm-musleabihf@11.19.1':
optional: true
'@oxc-resolver/binding-linux-arm64-gnu@11.19.1':
optional: true
'@oxc-resolver/binding-linux-arm64-musl@11.19.1':
optional: true
'@oxc-resolver/binding-linux-ppc64-gnu@11.19.1':
optional: true
'@oxc-resolver/binding-linux-riscv64-gnu@11.19.1':
optional: true
'@oxc-resolver/binding-linux-riscv64-musl@11.19.1':
optional: true
'@oxc-resolver/binding-linux-s390x-gnu@11.19.1':
optional: true
'@oxc-resolver/binding-linux-x64-gnu@11.19.1':
optional: true
'@oxc-resolver/binding-linux-x64-musl@11.19.1':
optional: true
'@oxc-resolver/binding-openharmony-arm64@11.19.1':
optional: true
'@oxc-resolver/binding-wasm32-wasi@11.19.1(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)':
dependencies:
'@napi-rs/wasm-runtime': 1.1.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)
transitivePeerDependencies:
- '@emnapi/core'
- '@emnapi/runtime'
optional: true
'@oxc-resolver/binding-win32-arm64-msvc@11.19.1':
optional: true
'@oxc-resolver/binding-win32-ia32-msvc@11.19.1':
optional: true
'@oxc-resolver/binding-win32-x64-msvc@11.19.1':
optional: true
'@radix-ui/number@1.1.1': {}
'@radix-ui/primitive@1.1.3': {}
@ -7691,6 +8203,10 @@ snapshots:
fastest-levenshtein@1.0.16: {}
fd-package-json@2.0.0:
dependencies:
walk-up-path: 4.0.0
fdir@6.5.0(picomatch@4.0.4):
optionalDependencies:
picomatch: 4.0.4
@ -7727,6 +8243,10 @@ snapshots:
hasown: 2.0.3
mime-types: 2.1.35
formatly@0.3.0:
dependencies:
fd-package-json: 2.0.0
formdata-polyfill@4.0.10:
dependencies:
fetch-blob: 3.2.0
@ -7895,6 +8415,10 @@ snapshots:
dunder-proto: 1.0.1
es-object-atoms: 1.1.1
get-tsconfig@4.14.0:
dependencies:
resolve-pkg-maps: 1.0.0
github-from-package@0.0.0: {}
github-slugger@2.0.0: {}
@ -8234,6 +8758,26 @@ snapshots:
jwa: 2.0.1
safe-buffer: 5.2.1
knip@6.12.2(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0):
dependencies:
fdir: 6.5.0(picomatch@4.0.4)
formatly: 0.3.0
get-tsconfig: 4.14.0
jiti: 2.7.0
minimist: 1.2.8
oxc-parser: 0.128.0
oxc-resolver: 11.19.1(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)
picomatch: 4.0.4
smol-toml: 1.6.1
strip-json-comments: 5.0.3
tinyglobby: 0.2.16
unbash: 3.0.0
yaml: 2.9.0
zod: 4.4.3
transitivePeerDependencies:
- '@emnapi/core'
- '@emnapi/runtime'
kuler@2.0.0: {}
lightningcss-android-arm64@1.32.0:
@ -8963,6 +9507,57 @@ snapshots:
optionalDependencies:
zod: 4.4.3
oxc-parser@0.128.0:
dependencies:
'@oxc-project/types': 0.128.0
optionalDependencies:
'@oxc-parser/binding-android-arm-eabi': 0.128.0
'@oxc-parser/binding-android-arm64': 0.128.0
'@oxc-parser/binding-darwin-arm64': 0.128.0
'@oxc-parser/binding-darwin-x64': 0.128.0
'@oxc-parser/binding-freebsd-x64': 0.128.0
'@oxc-parser/binding-linux-arm-gnueabihf': 0.128.0
'@oxc-parser/binding-linux-arm-musleabihf': 0.128.0
'@oxc-parser/binding-linux-arm64-gnu': 0.128.0
'@oxc-parser/binding-linux-arm64-musl': 0.128.0
'@oxc-parser/binding-linux-ppc64-gnu': 0.128.0
'@oxc-parser/binding-linux-riscv64-gnu': 0.128.0
'@oxc-parser/binding-linux-riscv64-musl': 0.128.0
'@oxc-parser/binding-linux-s390x-gnu': 0.128.0
'@oxc-parser/binding-linux-x64-gnu': 0.128.0
'@oxc-parser/binding-linux-x64-musl': 0.128.0
'@oxc-parser/binding-openharmony-arm64': 0.128.0
'@oxc-parser/binding-wasm32-wasi': 0.128.0
'@oxc-parser/binding-win32-arm64-msvc': 0.128.0
'@oxc-parser/binding-win32-ia32-msvc': 0.128.0
'@oxc-parser/binding-win32-x64-msvc': 0.128.0
oxc-resolver@11.19.1(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0):
optionalDependencies:
'@oxc-resolver/binding-android-arm-eabi': 11.19.1
'@oxc-resolver/binding-android-arm64': 11.19.1
'@oxc-resolver/binding-darwin-arm64': 11.19.1
'@oxc-resolver/binding-darwin-x64': 11.19.1
'@oxc-resolver/binding-freebsd-x64': 11.19.1
'@oxc-resolver/binding-linux-arm-gnueabihf': 11.19.1
'@oxc-resolver/binding-linux-arm-musleabihf': 11.19.1
'@oxc-resolver/binding-linux-arm64-gnu': 11.19.1
'@oxc-resolver/binding-linux-arm64-musl': 11.19.1
'@oxc-resolver/binding-linux-ppc64-gnu': 11.19.1
'@oxc-resolver/binding-linux-riscv64-gnu': 11.19.1
'@oxc-resolver/binding-linux-riscv64-musl': 11.19.1
'@oxc-resolver/binding-linux-s390x-gnu': 11.19.1
'@oxc-resolver/binding-linux-x64-gnu': 11.19.1
'@oxc-resolver/binding-linux-x64-musl': 11.19.1
'@oxc-resolver/binding-openharmony-arm64': 11.19.1
'@oxc-resolver/binding-wasm32-wasi': 11.19.1(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)
'@oxc-resolver/binding-win32-arm64-msvc': 11.19.1
'@oxc-resolver/binding-win32-ia32-msvc': 11.19.1
'@oxc-resolver/binding-win32-x64-msvc': 11.19.1
transitivePeerDependencies:
- '@emnapi/core'
- '@emnapi/runtime'
p-limit@7.3.0:
dependencies:
yocto-queue: 1.2.2
@ -9273,6 +9868,8 @@ snapshots:
require-from-string@2.0.2: {}
resolve-pkg-maps@1.0.0: {}
restore-cursor@4.0.0:
dependencies:
onetime: 5.1.2
@ -9467,6 +10064,8 @@ snapshots:
ansi-styles: 6.2.3
is-fullwidth-code-point: 5.1.0
smol-toml@1.6.1: {}
snowflake-sdk@2.4.1(asn1.js@5.4.1):
dependencies:
'@aws-crypto/sha256-js': 5.2.0
@ -9558,6 +10157,8 @@ snapshots:
strip-json-comments@2.0.1: {}
strip-json-comments@5.0.3: {}
strnum@2.2.3: {}
stubs@3.0.0: {}
@ -9689,6 +10290,8 @@ snapshots:
uglify-js@3.19.3:
optional: true
unbash@3.0.0: {}
undici-types@7.16.0: {}
unified@11.0.5:
@ -9811,6 +10414,8 @@ snapshots:
transitivePeerDependencies:
- msw
walk-up-path@4.0.0: {}
web-namespaces@2.0.1: {}
web-streams-polyfill@3.3.3: {}

View file

@ -151,10 +151,6 @@ export function publicNpmPackageJson(cliPackageJson, dependencies, version = PUB
}
function bundledWorkspacePackageJson(packageJson) {
const dependencies = Object.fromEntries(
Object.entries(packageJson.dependencies ?? {}).filter(([name]) => !isWorkspacePackageName(name)),
);
return {
name: packageJson.name,
version: packageJson.version ?? PUBLIC_NPM_PACKAGE_VERSION,
@ -164,7 +160,6 @@ function bundledWorkspacePackageJson(packageJson) {
types: packageJson.types,
exports: packageJson.exports,
files: packageJson.files,
dependencies: sortedObject(Object.entries(dependencies)),
license: packageJson.license ?? 'Apache-2.0',
};
}

View file

@ -250,7 +250,7 @@ describe('createPublicNpmPackageTree', () => {
await readFile(join(layout.packRoot, 'node_modules', '@ktx', 'context', 'package.json'), 'utf8'),
);
assert.equal(bundledContextJson.private, true);
assert.deepEqual(bundledContextJson.dependencies, { yaml: '^2.8.2' });
assert.equal(bundledContextJson.dependencies, undefined);
} finally {
await rm(root, { recursive: true, force: true });
}

View file

@ -22,10 +22,6 @@ function publicPackagePattern(text) {
return new RegExp(text.replaceAll('{package}', escapeRegExp(publicNpmPackageName())));
}
function runtimeWheelPackagePattern(text) {
return new RegExp(text.replaceAll('{package}', escapeRegExp(runtimeWheelPackageName())));
}
describe('standalone example docs', () => {
it('documents the local warehouse example from the examples index', async () => {
const examples = await readText('examples/README.md');

View file

@ -459,9 +459,6 @@ export function npmSmokePackageJson(layout) {
dependencies: {
'@kaelio/ktx': `file:${layout.cliTarball}`,
},
devDependencies: {
'better-sqlite3': '^12.6.2',
},
};
}
@ -485,11 +482,11 @@ if (typeof cli.runKtxCli !== 'function') {
export function npmRuntimeSmokeSource() {
return `
import assert from 'node:assert/strict';
import Database from 'better-sqlite3';
import { execFile } from 'node:child_process';
import { access, mkdir, mkdtemp, rm, writeFile } from 'node:fs/promises';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
import { DatabaseSync } from 'node:sqlite';
import { promisify } from 'node:util';
const execFileAsync = promisify(execFile);
@ -569,7 +566,7 @@ function getRunId(stdout) {
}
async function writeSqliteWarehouse(projectDir) {
const database = new Database(join(projectDir, 'warehouse.db'));
const database = new DatabaseSync(join(projectDir, 'warehouse.db'));
try {
database.exec(\`
DROP TABLE IF EXISTS orders;

View file

@ -27,8 +27,6 @@ import {
writeArtifactManifest,
} from './package-artifacts.mjs';
const STALE_METABASE_UNSUPPORTED = ['Standalone Metabase scheduled fetch', 'is intentionally unsupported'].join(' ');
async function writeJson(path, value) {
await writeFile(path, `${JSON.stringify(value, null, 2)}\n`);
}
@ -420,9 +418,7 @@ describe('verification snippets', () => {
assert.deepEqual(packageJson.dependencies, {
'@kaelio/ktx': `file:${layout.cliTarball}`,
});
assert.deepEqual(packageJson.devDependencies, {
'better-sqlite3': '^12.6.2',
});
assert.equal(packageJson.devDependencies, undefined);
assert.equal(
npmSmokePnpmWorkspaceYaml(),
['packages:', ' - "."', 'allowBuilds:', ' better-sqlite3: true', ''].join('\n'),
@ -465,7 +461,7 @@ describe('verification snippets', () => {
assert.match(source, /semantic-layer', 'warehouse', 'orders\.yaml'/);
assert.match(source, /run\('pnpm', \[\s*'exec',\s*'ktx',\s*'sl',\s*'list'/);
assert.match(source, /orders\.order_count/);
assert.match(source, /sqlite3/);
assert.match(source, /node:sqlite/);
assert.match(source, /driver: sqlite/);
assert.match(source, /path: warehouse\.db/);
assert.match(source, /live-database/);
@ -473,7 +469,7 @@ describe('verification snippets', () => {
assert.match(source, /"mode": "compile_only"/);
assert.match(source, /"mode": "executed"/);
assert.match(source, /ktx sl query sqlite execute/);
assert.match(source, /import Database from 'better-sqlite3'/);
assert.match(source, /import \{ DatabaseSync \} from 'node:sqlite'/);
assert.doesNotMatch(source, /run\('python'/);
assert.match(source, /KTX_RUNTIME_ROOT/);
assert.match(source, /managed-runtime/);

View file

@ -9,7 +9,6 @@ import { runWorkspaceKtx } from './run-ktx.mjs';
const scriptDir = dirname(fileURLToPath(import.meta.url));
const ktxRootDir = resolve(scriptDir, '..');
const repoRootDir = resolve(ktxRootDir, '..');
const defaultProjectDir = resolve(ktxRootDir, 'examples/orbit-relationship-verification');
const defaultReportPath = resolve(
ktxRootDir,