@@ -16,183 +16,82 @@
---
KTX turns warehouse metadata, semantic definitions, and business knowledge into
-reviewable project files that agents can use while planning, querying, and
-updating analytics work.
-
-A KTX project is a directory of plain files - YAML semantic sources, Markdown
-wiki pages, and SQLite state - that you commit to git and review in PRs,
-just like dbt models.
-
-## Who KTX is for
-
-KTX is built for analytics engineers and data teams who want data agents to
-work on real analytics systems - not just generate one-off SQL.
+reviewable project files that agents can use to plan, query, and update
+analytics work.
Use KTX when you want agents to:
-- **Generate SQL** from approved measures and joins
-- **Repair semantic definitions** through reviewable diffs
-- **Explain metric provenance** with warehouse evidence
-- **Work alongside** dbt, LookML, MetricFlow, Looker, Metabase, and modern BI
- platforms
+- Generate SQL from approved measures and joins
+- Repair semantic definitions through reviewable diffs
+- Explain metric provenance with warehouse evidence
+- Work alongside dbt, MetricFlow, LookML, Looker, Metabase, and Notion
-Works with PostgreSQL, Snowflake, BigQuery, ClickHouse, MySQL, SQL Server, and
+Supports PostgreSQL, Snowflake, BigQuery, ClickHouse, MySQL, SQL Server, and
SQLite.
-## Quick start
-
-Install the CLI and run the setup wizard:
+## Quick Start
```bash
-npm install @kaelio/ktx
-npm install -g @kaelio/ktx
+pnpm add --global @kaelio/ktx
ktx setup
-```
-
-The wizard walks through six steps: configuring your LLM provider, setting up
-embeddings, connecting your database, adding context sources (dbt, LookML,
-Metabase, Looker, Notion), building context, and installing agent integration.
-
-If it exits before completion, rerun `ktx setup` to resume where you left off.
-
-Check your project status:
-
-```bash
ktx status
```
-```
-KTX project: /home/user/analytics
-Project ready: yes
-LLM ready: yes (claude-sonnet-4-6)
-Embeddings ready: yes (text-embedding-3-small)
-Databases configured: yes (postgres-warehouse)
-Context sources configured: yes (dbt-main)
-KTX context built: yes
-Agent integration ready: yes (claude-code:project)
-```
+`ktx setup` creates or resumes a local KTX project, configures providers and
+connections, builds context, and installs agent integration.
-Generate SQL from a semantic-layer source:
+## Common Commands
-```bash
-npx @kaelio/ktx sl query --project-dir "$PROJECT_DIR" \
- --connection-id warehouse \
- --measure accounts.account_count \
- --dimension accounts.segment \
- --format sql
-```
+| Command | Purpose |
+|---------|---------|
+| `ktx setup` | Create, resume, or update a KTX project |
+| `ktx status` | Check project readiness |
+| `ktx connection list` | List configured connections |
+| `ktx connection test ` | Test one connection |
+| `ktx ingest ` | Build context for one connection |
+| `ktx ingest --all` | Build context for every configured connection |
+| `ktx ingest text ` | Capture free-form notes into memory |
+| `ktx sl list` | List semantic-layer sources |
+| `ktx sl search "revenue"` | Search semantic-layer sources |
+| `ktx sl validate --connection-id ` | Validate a semantic source |
+| `ktx sl query --measure --format sql` | Compile semantic-layer SQL |
+| `ktx wiki search "revenue definition"` | Search local wiki context |
+| `ktx mcp start` | Start the local MCP server for agent clients |
-List and test a configured warehouse connection:
+Project resolution defaults to `KTX_PROJECT_DIR`, then the nearest `ktx.yaml`,
+then the current directory. Pass `--project-dir ` when scripting.
-```bash
-ktx connection list --project-dir "$PROJECT_DIR"
-ktx connection test warehouse --project-dir "$PROJECT_DIR"
-```
-
-The connection test prints the configured driver and connector-specific status:
+## Project Layout
```text
-Connection test passed: warehouse
-Driver: sqlite
-Status: ok
-```
-
-## What's in a project
-
-```
my-project/
-├── ktx.yaml # Project configuration
-├── semantic-layer/
-│ └── warehouse/
-│ ├── orders.yaml # Semantic source definitions
-│ ├── customers.yaml
-│ └── order_items.yaml
-├── wiki/
-│ ├── global/
-│ │ ├── revenue.md # Business definitions and rules
-│ │ └── segment-classification.md
-│ └── user/
-│ └── local/
-├── raw-sources/
-│ └── warehouse/
-│ └── / # Database ingest artifacts and reports
-└── .ktx/
- └── db.sqlite # Local state (git-ignored)
+├── ktx.yaml # Project configuration
+├── semantic-layer// # YAML semantic sources
+├── wiki/global/ # Shared business context
+├── wiki/user// # User-scoped notes
+├── raw-sources// # Ingest artifacts and reports
+└── .ktx/ # Local state and secrets, git-ignored
```
-Semantic sources and wiki pages are committed to git. The `.ktx/` directory
-holds ephemeral state and is git-ignored - delete it and KTX rebuilds on the
-next run.
+Commit `ktx.yaml`, `semantic-layer/`, and `wiki/`. Keep `.ktx/` local.
-### Build demo warehouse context
+## Agent Usage
-Database ingest artifacts are written under `raw-sources/warehouse//`
-in the project directory.
+Setup can install KTX instructions for Claude Code, Codex, Cursor, OpenCode,
+and universal `.agents` clients:
```bash
-ktx ingest warehouse --project-dir "$PROJECT_DIR" --fast
-ktx status --project-dir "$PROJECT_DIR"
+ktx setup --agents --target codex
```
-For non-SQLite drivers, prefer credential references such as `--url env:NAME`
-or `--url file:PATH` over literal credential URLs.
-
-## Managed Python runtime
-
-KTX installs its Python runtime only when a Python-backed command needs it.
-The runtime lives outside the npm cache, is versioned by the installed CLI
-version, and is managed by `ktx dev runtime` commands.
-
-KTX requires `uv` on `PATH` to create the managed runtime. Install `uv` with
-your system package manager or the official installer before running Python-
-backed KTX commands. KTX doesn't download `uv` automatically; run
-`ktx dev runtime status` if runtime installation fails:
+Agent-facing workflows typically start with:
```bash
-ktx dev runtime install --yes
-ktx dev runtime status
-ktx dev runtime start
-ktx dev runtime stop
+ktx sl search "revenue" --json
+ktx wiki search "refund policy" --json
+ktx sl query --connection-id warehouse --measure orders.revenue --format sql
```
-The release artifact manifest contains the public npm tarball and the bundled `kaelio-ktx`
-runtime wheel. The `python/ktx-sl` and `python/ktx-daemon` directories remain
-source packages for development, not public release artifacts.
-
-## Use KTX with agents
-
-KTX integrates with coding agents through CLI skills. The setup wizard
-configures this automatically.
-
-**CLI skills** - the agent calls `ktx` commands directly through a skill file
-installed in your agent's config (e.g., `.claude/skills/ktx/SKILL.md`):
-
-```bash
-ktx sl query --measure orders.revenue --dimension orders.status --format sql
-ktx wiki search "revenue definition"
-ktx sl validate orders
-```
-
-Supported agents: Claude Code, Codex, Cursor, OpenCode, and any agent that
-reads `.agents/` skills.
-
-## Workspace packages
-
-| Package | Purpose |
-|---------|---------|
-| `packages/cli` | CLI entry point |
-| `packages/context` | Core context engine |
-| `packages/llm` | LLM and embedding providers |
-| `packages/connector-bigquery` | BigQuery scan connector |
-| `packages/connector-clickhouse` | ClickHouse scan connector |
-| `packages/connector-mysql` | MySQL scan connector |
-| `packages/connector-postgres` | Postgres scan connector |
-| `packages/connector-snowflake` | Snowflake scan connector |
-| `packages/connector-sqlite` | SQLite scan connector |
-| `packages/connector-sqlserver` | SQL Server scan connector |
-| `python/ktx-sl` | Semantic-layer query planning |
-| `python/ktx-daemon` | Portable compute service |
-
## Development
```bash
@@ -204,7 +103,7 @@ pnpm run build
pnpm run check
```
-Use the development CLI for local testing:
+Use the development CLI locally:
```bash
pnpm run setup:dev
@@ -212,30 +111,28 @@ pnpm run link:dev
ktx-dev --help
```
-### Debug LLM traces
+KTX is a pnpm + uv workspace:
-KTX can capture local AI SDK DevTools traces for LLM calls that run through the
-KTX provider. Enable it with an environment flag when running an LLM-backed
-command:
+- TypeScript packages live in `packages/*`
+- CLI source lives in `packages/cli`
+- Python runtime source lives in `python/ktx-sl` and `python/ktx-daemon`
+- Public docs live in `docs-site/content/docs`
+
+Useful checks:
```bash
-KTX_AI_DEVTOOLS_ENABLED=true ktx ingest warehouse --project-dir "$PROJECT_DIR" --deep
+pnpm run type-check
+pnpm run test
+pnpm run dead-code
+uv run pytest -q
```
-Traces are written to `.devtools/generations.json` under the current working
-directory. To inspect them, run:
+## Docs
-```bash
-pnpm dlx @ai-sdk/devtools
-```
-
-Then open `http://localhost:4983`. These traces are local-development-only and
-store prompts, model outputs, tool arguments/results, and raw provider payloads
-in plain text. Do not enable this in production or for sensitive runs.
-
-The repository uses `pnpm` for TypeScript packages and `uv` for Python
-packages. See [Contributing](docs-site/content/docs/community/contributing.mdx)
-for full development setup, testing, and PR guidelines.
+- [Quickstart](docs-site/content/docs/getting-started/quickstart.mdx)
+- [CLI Reference](docs-site/content/docs/cli-reference/index.mdx)
+- [Building Context](docs-site/content/docs/guides/building-context.mdx)
+- [Contributing](docs-site/content/docs/community/contributing.mdx)
## License
diff --git a/docs-site/app/docs/[[...slug]]/page.tsx b/docs-site/app/docs/[[...slug]]/page.tsx
index d1ae21d4..dd5d944c 100644
--- a/docs-site/app/docs/[[...slug]]/page.tsx
+++ b/docs-site/app/docs/[[...slug]]/page.tsx
@@ -39,20 +39,29 @@ export default async function Page(props: {
const hero = isHeroPage(params.slug);
return (
-
+
{!hero && (
<>
-
+
{page.data.title}
- {page.data.description}
+
+ {page.data.description}
+
>
)}
-
+
diff --git a/docs-site/app/layout.tsx b/docs-site/app/layout.tsx
index 35a4b1fa..48e12a3f 100644
--- a/docs-site/app/layout.tsx
+++ b/docs-site/app/layout.tsx
@@ -27,6 +27,10 @@ export const metadata: Metadata = {
},
description:
"Open-source context infrastructure that makes agentic analytics reliable.",
+ icons: {
+ icon: "/brand/ktx-mascot.svg",
+ shortcut: "/brand/ktx-mascot.svg",
+ },
};
export default function RootLayout({ children }: { children: ReactNode }) {
diff --git a/docs-site/components/product-mechanics.tsx b/docs-site/components/product-mechanics.tsx
new file mode 100644
index 00000000..7f551450
--- /dev/null
+++ b/docs-site/components/product-mechanics.tsx
@@ -0,0 +1,402 @@
+import type { ReactNode } from "react";
+
+const sourceInputs = [
+ {
+ name: "Warehouse schema",
+ detail: "tables, columns, types, constraints, row counts",
+ signal: "grounds definitions in live database structure",
+ accent: "border-fd-primary",
+ },
+ {
+ name: "Metabase and query history",
+ detail: "historic SQL, questions, dashboards, usage patterns",
+ signal: "extracts joins, filters, grain, and trusted examples",
+ accent: "border-orange-500",
+ },
+ {
+ name: "dbt, MetricFlow, LookML",
+ detail: "models, metrics, dimensions, explores, joins",
+ signal: "maps existing modeling logic into semantic entities",
+ accent: "border-amber-500",
+ },
+ {
+ name: "Company documentation",
+ detail: "Notion pages, policies, caveats, analyst notes",
+ signal: "links business language back to semantic references",
+ accent: "border-slate-500 dark:border-cyan-200",
+ },
+];
+
+const ingestSteps = [
+ {
+ title: "extract evidence",
+ body: "Pull structured facts from schemas, SQL, BI metadata, and docs.",
+ },
+ {
+ title: "reconcile entities",
+ body: "Merge names, measures, joins, and caveats into one project model.",
+ },
+ {
+ title: "validate references",
+ body: "Check semantic fields and joins against database context before agents use them.",
+ },
+];
+
+const artifacts = [
+ {
+ path: "semantic-layer/*.yaml",
+ title: "Typed query model",
+ body: "sources, grain, joins, dimensions, measures, filters, segments",
+ },
+ {
+ path: "wiki/*.md",
+ title: "Business context",
+ body: "rules and caveats with sl_refs back to semantic-layer entities",
+ },
+ {
+ path: "raw-sources/",
+ title: "Evidence trail",
+ body: "scan artifacts, extracted metadata, relationship evidence",
+ },
+ {
+ path: ".ktx/",
+ title: "Local indexes",
+ body: "embeddings and search indexes, not the source of truth",
+ },
+];
+
+const runtimeSteps = [
+ {
+ title: "Search wiki",
+ body: "Find business rules, caveats, synonyms, and sl_refs.",
+ },
+ {
+ title: "Resolve semantic refs",
+ body: "Map measure and dimension names to approved entities.",
+ },
+ {
+ title: "Validate fields",
+ body: "Check source, columns, joins, grain, filters, and segments.",
+ },
+ {
+ title: "Build query plan",
+ body: "Create a semantic query plan before SQL is generated.",
+ },
+ {
+ title: "Compile dialect SQL",
+ body: "Generate warehouse-shaped SQL instead of copying examples.",
+ },
+ {
+ title: "Execute with bounds",
+ body: "Optionally run with bounded rows and return provenance.",
+ },
+];
+
+export function ProductMechanics() {
+ return (
+
+
+
+ Product mechanics
+
+
+ A semantic compiler for analytics agents
+
+
+ KTX builds typed semantic files, links wiki context back to those
+ entities, validates the model against database evidence, then compiles
+ agent requests into executable SQL.
+
+ );
+}
diff --git a/docs-site/content/docs/cli-reference/index.mdx b/docs-site/content/docs/cli-reference/index.mdx
index c4ef07db..065339ca 100644
--- a/docs-site/content/docs/cli-reference/index.mdx
+++ b/docs-site/content/docs/cli-reference/index.mdx
@@ -4,8 +4,8 @@ description: "Command map and shared options for the KTX CLI."
---
The `ktx` CLI sets up local projects, builds agent-ready context, checks
-connections, queries semantic-layer sources, searches wiki pages, and manages
-the bundled Python runtime.
+connections, queries semantic-layer sources, searches wiki pages, runs the MCP
+server, and manages the bundled Python runtime.
## Command Map
@@ -26,6 +26,11 @@ ktx
validate
query
status
+ mcp
+ start
+ stop
+ status
+ logs
dev
init [directory]
schema
@@ -73,4 +78,7 @@ ktx ingest --all
# Search semantic-layer sources and wiki pages
ktx sl search "revenue"
ktx wiki search "revenue recognition"
+
+# Start the local MCP server for agent clients
+ktx mcp start
```
diff --git a/docs-site/content/docs/cli-reference/ktx-ingest.mdx b/docs-site/content/docs/cli-reference/ktx-ingest.mdx
index a0bca58f..ab907992 100644
--- a/docs-site/content/docs/cli-reference/ktx-ingest.mdx
+++ b/docs-site/content/docs/cli-reference/ktx-ingest.mdx
@@ -29,14 +29,16 @@ connections when you use `--all`.
| `--deep` | Use AI-enriched database ingest | Stored connection default, or `fast` |
| `--query-history` | Include database query-history usage patterns | Stored connection default |
| `--no-query-history` | Skip database query-history usage patterns for this run | Stored connection default |
-| `--query-history-window-days ` | Query-history lookback window for this run | Stored connection default |
+| `--query-history-window-days ` | BigQuery/Snowflake query-history lookback window for this run | Stored connection default |
| `--plain` | Print plain text output | `true` |
| `--json` | Print JSON output | `false` |
| `--no-input` | Disable interactive terminal input | — |
`--fast` and `--deep` are mutually exclusive. Depth flags apply only to
database connections. Query-history flags apply only to database connections
-that support query history. Query-history ingest runs after schema ingest and
+that support query history. The window flag applies to BigQuery and Snowflake;
+Postgres reads the current `pg_stat_statements` aggregate data instead of a
+time-windowed history table. Query-history ingest runs after schema ingest and
requires deep ingest readiness.
When `--all` selects both databases and context sources, database ingest runs
@@ -70,6 +72,7 @@ ktx ingest warehouse --deep
# Include query-history usage patterns
ktx ingest warehouse --deep --query-history
+# Set the lookback window for BigQuery or Snowflake query history
ktx ingest warehouse --query-history-window-days 30
# Build a source connection
diff --git a/docs-site/content/docs/cli-reference/ktx-mcp.mdx b/docs-site/content/docs/cli-reference/ktx-mcp.mdx
new file mode 100644
index 00000000..9f0dd189
--- /dev/null
+++ b/docs-site/content/docs/cli-reference/ktx-mcp.mdx
@@ -0,0 +1,70 @@
+---
+title: "ktx mcp"
+description: "Run the KTX MCP HTTP server for agent clients."
+---
+
+`ktx mcp` starts, stops, inspects, and tails the local KTX MCP server for a KTX
+project. Use it when an agent client connects through MCP instead of generated
+CLI instructions.
+
+## Command signature
+
+```bash
+ktx mcp [options]
+```
+
+## Subcommands
+
+| Subcommand | Description |
+|-----------|-------------|
+| `start` | Start the KTX MCP HTTP server |
+| `stop` | Stop the KTX MCP daemon |
+| `status` | Show daemon status, URL, PID, token mode, and project path |
+| `logs` | Print the daemon log |
+
+## `mcp start` Options
+
+| Flag | Description | Default |
+|------|-------------|---------|
+| `--host ` | Host to bind | `127.0.0.1` |
+| `--port ` | Port to bind | `7878` |
+| `--token ` | Bearer token for non-loopback binding | `KTX_MCP_TOKEN` |
+| `--foreground` | Run the server in the foreground | `false` |
+| `--allowed-host ` | Additional allowed Host header; repeatable | - |
+| `--allowed-origin ` | Allowed browser Origin header; repeatable | - |
+
+## `mcp logs` Options
+
+| Flag | Description | Default |
+|------|-------------|---------|
+| `--follow` | Follow log output | `false` |
+
+## Examples
+
+```bash
+# Start the daemon on localhost
+ktx mcp start
+
+# Check status
+ktx mcp status
+
+# Tail logs
+ktx mcp logs --follow
+
+# Run in the foreground on a custom port
+ktx mcp start --port 8787 --foreground
+```
+
+## Security notes
+
+The default host is loopback-only. If you bind to a non-loopback host, configure
+a bearer token with `--token ` or `KTX_MCP_TOKEN` and restrict allowed
+hosts and origins for browser clients.
+
+## Common errors
+
+| Error | Cause | Recovery |
+|-------|-------|----------|
+| No KTX project found | Current directory has no `ktx.yaml` and `KTX_PROJECT_DIR` is unset | Run from a KTX project or pass `--project-dir ` |
+| Non-loopback host rejected | The server needs token auth before binding beyond localhost | Pass `--token ` or set `KTX_MCP_TOKEN` |
+| Client cannot connect | Host, port, token, allowed host, or allowed origin does not match the client | Check `ktx mcp status`, then restart with explicit `--host`, `--port`, `--allowed-host`, and `--allowed-origin` values |
diff --git a/docs-site/content/docs/cli-reference/ktx-setup.mdx b/docs-site/content/docs/cli-reference/ktx-setup.mdx
index 1bc623a9..a6f2d588 100644
--- a/docs-site/content/docs/cli-reference/ktx-setup.mdx
+++ b/docs-site/content/docs/cli-reference/ktx-setup.mdx
@@ -98,13 +98,16 @@ incomplete.
|------|-------------|
| `--enable-query-history` | Enable query-history ingest when the selected database supports it |
| `--disable-query-history` | Disable query-history ingest for the selected database |
-| `--query-history-window-days ` | Query-history lookback window |
+| `--query-history-window-days ` | BigQuery/Snowflake query-history lookback window |
| `--query-history-min-executions ` | Minimum executions for a query-history template |
| `--query-history-service-account-pattern ` | Query-history service-account regex; repeatable |
| `--query-history-redaction-pattern ` | Query-history SQL-literal redaction regex; repeatable |
-Query history setup is supported for Postgres, BigQuery, and Snowflake. Enabling
-query history makes deep ingest readiness matter for later `ktx ingest` runs.
+Query history setup is supported for Postgres, BigQuery, and Snowflake. The
+window flag applies to BigQuery and Snowflake; Postgres reads the current
+`pg_stat_statements` aggregate data instead of a time-windowed history table.
+Enabling query history makes deep ingest readiness matter for later
+`ktx ingest` runs.
### Context Sources
diff --git a/docs-site/content/docs/cli-reference/meta.json b/docs-site/content/docs/cli-reference/meta.json
index 46aafb4c..4103c025 100644
--- a/docs-site/content/docs/cli-reference/meta.json
+++ b/docs-site/content/docs/cli-reference/meta.json
@@ -9,6 +9,7 @@
"ktx-sl",
"ktx-wiki",
"ktx-status",
+ "ktx-mcp",
"ktx-dev"
]
}
diff --git a/docs-site/content/docs/concepts/meta.json b/docs-site/content/docs/concepts/meta.json
index e1749365..72c0a407 100644
--- a/docs-site/content/docs/concepts/meta.json
+++ b/docs-site/content/docs/concepts/meta.json
@@ -1,5 +1,5 @@
{
"title": "Concepts",
"defaultOpen": true,
- "pages": ["the-context-layer", "context-as-code"]
+ "pages": ["the-context-layer", "semantic-layer-internals", "context-as-code"]
}
diff --git a/docs-site/content/docs/concepts/semantic-layer-internals.mdx b/docs-site/content/docs/concepts/semantic-layer-internals.mdx
new file mode 100644
index 00000000..c48428e6
--- /dev/null
+++ b/docs-site/content/docs/concepts/semantic-layer-internals.mdx
@@ -0,0 +1,398 @@
+---
+title: Semantic Layer Internals
+description: How KTX uses join graphs, grain, and relationship metadata to turn context into safe SQL.
+---
+
+KTX is a context layer for agents. This page focuses on one internal subsystem:
+the semantic execution layer that turns reviewed context into safe SQL.
+
+The semantic layer is important, but it is not the whole product. KTX also
+handles schema evidence, wiki context, provenance, validation, and agent
+workflows around those files.
+
+Read the page as a pipeline:
+
+- context inputs feed the semantic engine;
+- evidence becomes a join graph with grain and relationship metadata;
+- review and corrections keep that graph current;
+- the execution engine uses the graph to avoid fan-out and ambiguous joins.
+
+## Where the semantic layer fits
+
+The semantic layer is not a separate product category inside KTX. It is the
+engine that makes the rest of the context actionable for SQL generation.
+
+
+
+
+
+ {"Context inputs"}
+
+
+
+
semantic-layer/
+
+ {"source YAML, measures, joins, grain"}
+
+
+
+
wiki/
+
+ {"business rules, definitions, caveats"}
+
+
+
+
raw-sources/
+
+ {"schema scans, keys, imported metadata"}
+
+
+
+
provenance
+
+ {"ingest decisions and review history"}
+
+
+
+
+
+
+
+
+
+
+
+
+ {"Semantic layer engine"}
+
+
+
+
Join graph
+
+ {"sources as nodes, joins as typed edges"}
+
+
+
+
Grain
+
+ {"row identity before aggregation"}
+
+
+
+
Measures
+
+ {"verified formulas and filters"}
+
+
+
+
Relationships
+
+ {"many_to_one, one_to_many, one_to_one"}
+
+
+
+
+ {"Safe query planning before SQL is generated."}
+
+
+
+
+
+
+
+
+
+ {"Agent workflows"}
+
+
+
+ {"Search sources and wiki pages"}
+
+
+ {"Compile trusted SQL"}
+
+
+ {"Explain metrics and provenance"}
+
+
+ {"Patch files and validate review"}
+
+
+
+
+
+
+## The join graph KTX builds
+
+A semantic source is a node. A join is an edge with a join condition and a
+relationship type. The graph lets KTX choose valid paths, reject unsafe paths,
+and reason about whether a join preserves or multiplies rows before SQL is
+generated.
+
+- `many_to_one` paths are usually safe for adding dimensions.
+- `one_to_many` paths can multiply fact rows and trigger fan-out handling.
+- Equal-cost paths can be ambiguous, so aliases and explicit joins matter.
+
+
+
+
+
customers
+
grain: customer_id
+
+
+
orders
+
grain: order_id
+
+
+
order_items
+
grain: order_id, line_id
+
+
+
+
orders -> customers: many_to_one
+
orders -> order_items: one_to_many
+
+
+ {"Example: "}
+ {"refunds joins to orders. Used carefully, it explains net revenue. Joined naively, it can duplicate order-level measures."}
+
+
+
+The graph is bidirectional for planning. If `orders -> customers` is
+`many_to_one`, the reverse path is `one_to_many`; KTX keeps that distinction
+instead of treating every join as a neutral edge.
+
+## How KTX builds the graph
+
+KTX starts from evidence, not a blank modeling canvas. Database scans and
+analytics-tool imports create source definitions that an analyst can review.
+
+| Evidence | What it contributes |
+|---|---|
+| Declared primary keys | Initial row grain for each source |
+| Declared foreign keys | Formal join candidates and relationship direction |
+| Inferred relationships | Useful edges when warehouses lack constraints |
+| dbt, MetricFlow, and LookML imports | Existing metrics, dimensions, entities, explores, and joins |
+| Query history | Real join and filter patterns agents should respect |
+| Analyst review | The final authority before context is merged |
+
+Generated YAML is intentionally reviewable. KTX can draft joins and measures,
+but the accepted semantic layer is still the plain-file diff your team approves.
+
+## How KTX keeps the graph current
+
+The semantic layer changes as schemas, metrics, and business rules change. KTX
+keeps that loop explicit instead of hiding it behind a remote runtime.
+
+
+
+
+ {"Semantic maintenance loop"}
+
+
+ {"Every accepted correction becomes input to the next graph build."}
+
+
+
+
+
+
+
+
+
+ {"reviewed context"}
+
+
+ {"The accepted graph becomes the starting point for the next build."}
+
+
+
+
+
+ {"Step 1"}
+
+
{"ingest evidence"}
+
+ {"scan schemas, imports, and accepted files"}
+
+
+
+
+ {"Step 2"}
+
+
{"YAML diff"}
+
+ {"draft source, join, grain, and measure changes"}
+
+
+
+
+ {"Step 3"}
+
+
{"validation"}
+
+ {"check relationships, syntax, and unsafe query shapes"}
+
+
+
+
+ {"Step 4"}
+
+
{"analyst review"}
+
+ {"accept, edit, or reject generated context"}
+
+
+
+
+ {"Step 5"}
+
+
{"agent use"}
+
+ {"serve context to search, explain, and query"}
+
+
+
+
+ {"Step 6"}
+
+
{"corrections"}
+
+ {"agent and analyst fixes become new evidence"}
+
+
+
+
+
+
+
+This matters because semantic correctness is not static. If a source gains a
+new key, a metric changes definition, or an analyst corrects a relationship,
+the next agent gets that reviewed context.
+
+## The modeling problem the graph solves
+
+Fan-out is the classic failure mode. If an order-level measure is joined to
+line-item rows before aggregation, one order can become many rows and revenue
+can be counted more than once.
+
+| Problem | What happens | How KTX avoids it |
+|---|---|---|
+| Order measure joins to `order_items` | `orders.revenue` repeats once per item | Detect the `one_to_many` path and pre-aggregate the order measure |
+| Two independent fact sources share `customers` | Measures from each fact table multiply across the shared dimension | Treat it as a chasm trap and use aggregate-locality planning |
+| Filter lives only across a `one_to_many` path | Filtering after the join changes the measure grain | Reject or localize the filter instead of silently producing unsafe SQL |
+| Multiple equal-cost paths connect the same sources | The join path is ambiguous | Prefer safer paths and use aliases to disambiguate repeated joins |
+
+Many-to-many questions usually show up as multiple one-to-many paths or
+independent fact sources. KTX treats those shapes as fan-out or chasm risks
+unless the query can be planned at a safe grain.
+
+## How the execution engine uses the graph
+
+The planner resolves the sources in a semantic query, chooses a join tree, and
+checks whether any requested dimension or filter crosses a row-multiplying
+edge. The SQL generator then chooses the simple path or the aggregate-locality
+path.
+
+| Naive SQL shape | Semantic-layer SQL shape |
+|---|---|
+| Join facts and dimensions first, then aggregate | Aggregate each fact source at its own grain, then join the results |
+| Put every filter in one outer `WHERE` clause | Keep measure filters with the measure source when locality is needed |
+| Trust the shortest textual join path | Prefer safe relationship paths and reject disconnected sources |
+| Let dimension grain differ across facts | Raise when asymmetric dimensions would fan out another measure |
+
+
+ {"The order measure is exposed to line-item fan-out before aggregation."}
+
+
+
+
+ {"KTX shape"}
+
+
+{`orders_agg as (
+ select customer_id, sum(amount) revenue
+ from orders
+ group by customer_id
+)
+select customers.segment, sum(revenue)
+from orders_agg
+join customers`}
+
+
+ {"KTX pre-aggregates fact measures at their own grain before joining dimensions."}
+
+
+
+
+
+The result is not magic. It is structured planning: validated sources, typed
+relationships, graph search, fan-out detection, aggregate locality, and final
+dialect transpilation.
+
+## What this means for agents
+
+KTX gives agents a semantic surface they can inspect and improve, not just a
+folder of notes.
+
+- Search semantic sources and related wiki pages before writing SQL.
+- Compile SQL through `ktx sl query` instead of guessing joins.
+- Validate semantic-layer changes before review.
+- Patch YAML and Markdown files in git.
+- Explain metric meaning and provenance from the same accepted context.
+
+Next, read [Writing Context](/docs/guides/writing-context) for the YAML editing
+workflow or [ktx sl](/docs/cli-reference/ktx-sl) for the command reference.
diff --git a/docs-site/content/docs/concepts/the-context-layer.mdx b/docs-site/content/docs/concepts/the-context-layer.mdx
index cb03b7c0..ba7ee3f3 100644
--- a/docs-site/content/docs/concepts/the-context-layer.mdx
+++ b/docs-site/content/docs/concepts/the-context-layer.mdx
@@ -191,7 +191,18 @@ KTX organizes context into four pillars:
Each pillar covers a different kind of context agents need before they can safely write SQL, update semantic definitions, or explain an analytics result.
-**Semantic sources** are YAML definitions that describe your data in terms agents can reason about. Each source maps to a table or SQL query, declares its grain, defines typed columns, specifies valid joins, and exposes named measures with optional filters. This is where "revenue means `sum(amount)` excluding refunds" lives.
+**Semantic sources** are YAML definitions that describe your data in terms
+agents can reason about:
+
+- source tables or SQL queries;
+- row grain;
+- typed columns;
+- valid joins;
+- named measures, filters, and segments.
+
+This is where "revenue means `sum(amount)` excluding refunds" lives. For the
+join graph, fan-out protections, and execution mechanics, read
+[Semantic Layer Internals](/docs/concepts/semantic-layer-internals).
```yaml
name: orders
@@ -289,7 +300,7 @@ my-project/
│ └── data-quality-notes.md
├── raw-sources/
│ └── warehouse/
-│ └── database-ingest/ # Schema ingest artifacts and reports
+│ └── live-database/ # Schema ingest artifacts and reports
└── .ktx/
├── db.sqlite # Local state (git-ignored)
└── cache/ # Runtime cache (git-ignored)
diff --git a/docs-site/content/docs/getting-started/introduction.mdx b/docs-site/content/docs/getting-started/introduction.mdx
index cb8ac0dd..7a6c9b3e 100644
--- a/docs-site/content/docs/getting-started/introduction.mdx
+++ b/docs-site/content/docs/getting-started/introduction.mdx
@@ -3,10 +3,12 @@ title: Introduction
description: How KTX gives analytics agents trusted context for warehouse work.
---
-
-
+import { ProductMechanics } from "@/components/product-mechanics";
+
+
+
- Make analytics context{'\n'}usable by agents
+ Make analytics context usable by agents
-
- KTX turns warehouse metadata, semantic definitions, and business knowledge
- into reviewable project files that agents can use while planning, querying,
- and updating analytics work.
+
+ {'KTX turns warehouse metadata, semantic definitions, and business knowledge into reviewable project files that agents can use while planning, querying, and updating analytics work.'}