diff --git a/AGENTS.md b/AGENTS.md index ffe324bb..20f9bcdf 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -64,25 +64,6 @@ When rules conflict, follow this order: 4. Code quality: types, readable boundaries, focused modules 5. Performance where it matters -## Opinionated Product Defaults - -- **MUST**: Prefer one canonical behavior over configurable alternatives. A new - flag, config field, environment variable, mode, strategy option, adapter hook, - or fallback path is a product feature and must be justified by an explicit - user request or a real correctness requirement. -- **MUST NOT**: Add speculative flexibility for imagined users, migrations, - review preferences, local workflows, or "just in case" scenarios. If the - requested behavior can work with one solid default, implement that default. -- **MUST NOT**: Add boolean switches that create two runtime paths unless both - paths are essential and the user explicitly asked for the choice. Boolean - policy knobs are especially suspect because they double the state space and - test surface. -- **MUST**: When a design seems to need a new option, first try to remove the - need by choosing the stronger default, tightening the invariant, or failing - clearly. Ask the user before adding the option if it still seems necessary. -- **MUST**: Delete obsolete branches, tests, docs, and config when removing a - behavior. Do not preserve dormant compatibility paths. - ## Repository Shape **ktx** is a pnpm + uv workspace. @@ -211,19 +192,6 @@ autonomously — without being asked the leading question — is the bar. next stack. The only acceptable static patterns are genuinely universal invariants (e.g. DB-engine system catalogs) and ktx's own self-emitted signatures. -- **MUST**: Give each capability one implementation and route every caller - through it. When some behavior — running a query, resolving a credential or - config reference, authenticating, selecting a dialect, loading config — - already has a working implementation that some call sites use, make new or - divergent call sites depend on that path instead of standing up a second one. - Parallel implementations of one capability drift apart silently: a fix, a - newly supported input, or an added case lands on one path and not the other, - so one entry point (a CLI command, an MCP tool, an ingest stage) succeeds - while another fails on the same input. When two paths already do the same - job, collapse onto the shared one and delete the duplicate instead of - keeping both. When fixing a defect that lives on one path, fix the shared - implementation; do not patch the symptom on a forked branch, which preserves - the divergence you set out to remove. - **SHOULD**: Before inventing an abstraction or hand-rolling structural logic, search for what already exists and reuse it — the codebase's canonical representation (a structured ref/key type) instead of a parallel string scheme, @@ -244,25 +212,12 @@ Before presenting a design, answer these explicitly: instead of building or parsing my own? 5. Am I discarding the better option on a weak or misapplied constraint (one-time vs recurring cost, "more surface area", "more work now")? -6. Does another entry point already perform this operation through a shared - implementation? If so, am I routing through that path instead of forking a - parallel one — and if I'm fixing a bug, am I fixing the shared layer rather - than one branch? -7. Am I adding a user-visible option or alternate runtime path that the user did - not ask for? If yes, can one opinionated default solve the problem instead? -8. Does this option multiply behavior by caller path, config value, or local - state? If yes, remove it unless it is explicitly required. A user question that nudges toward an alternative ("would X help?", "should I always do Y?", "will you hardcode Z?") is a signal that a better option exists. Investigate the implied direction and reason it through *before* defending the original proposal — and prefer to have asked yourself the question first. -Example: If generated context changes should be saved, choose one save policy -and route ingest, setup, memory, indexing, and docs through it. Do not add an -`auto_commit`-style switch unless the user explicitly asks for staged-only runs -and accepts the extra runtime path. - ## TypeScript Standards - Use Node 22+ and pnpm workspace commands. @@ -382,8 +337,7 @@ use `PascalCase` without the suffix. ## Telemetry -**ktx** ships PostHog usage telemetry. Catalog telemetry events use strict -schemas. When adding commands or events: +**ktx** ships PostHog usage telemetry. When adding commands or events: - **MUST NOT**: Add fields that carry user data — file paths, hostnames, environment values, SQL text, schema/table/column names, error messages, @@ -400,24 +354,6 @@ schemas. When adding commands or events: of collected data changes. Adding another event with no new field types needs no docs change. -### Error reports - -**ktx** also sends PostHog Error Tracking `$exception` events when telemetry is -enabled. This channel is separate from the strict catalog event schema and is -used only for exception diagnostics. - -`$exception` events may include stack frames, error class names, raw error -messages, cause chains, `source`, `handled`, `fatal`, runtime version fields, -OS/runtime fields, and the hashed `projectId` when known. Stack frames may -include local file paths and the local username when those appear in paths. - -`$exception` events must never intentionally include secrets, credentials, -database URLs, auth headers, raw argv, raw environment values, SQL text, -schema/table/column names as explicit properties, customer row data, user prompt -text, or raw MCP arguments. Reporters must redact call-site-provided secret -snapshots and common static credential patterns before the SDK serializes the -exception. - ## Documentation and Specs - Keep public documentation in `README.md`, package READMEs, example READMEs, diff --git a/README.md b/README.md index 3f704f04..2c433e0d 100644 --- a/README.md +++ b/README.md @@ -13,20 +13,16 @@ Documentation Join the ktx Slack community License - Y Combinator P25 + Y Combinator P25

Quickstart · CLI Reference · - Agent Setup · + Agent Setup · Slack

-

- Built and maintained by Kaelio -

- --- **ktx** is a self-improving context layer that teaches agents how to query your @@ -143,14 +139,6 @@ Agent integration ready: yes (codex:project) > If `ktx status` prints `ktx mcp start --project-dir ...`, run it before > opening your agent client. -## Upgrading - -Re-run the global install with the `@latest` tag: - -```bash -npm install -g @kaelio/ktx@latest -``` - ## First commands | Command | Purpose | @@ -209,7 +197,7 @@ then the current directory. Pass `--project-dir ` when scripting. - [The Context Layer](https://docs.kaelio.com/ktx/docs/concepts/the-context-layer) - [Building Context](https://docs.kaelio.com/ktx/docs/guides/building-context) - [CLI Reference](https://docs.kaelio.com/ktx/docs/cli-reference/ktx) -- [AI Resources](https://docs.kaelio.com/ktx/docs/community/ai-resources) +- [Agent Quickstart](https://docs.kaelio.com/ktx/docs/ai-resources/agent-quickstart) - [Community & Support](https://docs.kaelio.com/ktx/docs/community/support) ## Community @@ -259,17 +247,11 @@ uv run pytest -q ## Telemetry -**ktx** collects privacy-conscious usage telemetry to understand installs and -improve setup, command reliability, and data-agent workflows. Catalog telemetry -events do not record file paths, hostnames, SQL, schema names, table names, -column names, error messages, raw environment values, or argv. Error reports use -PostHog Error Tracking and can include stack frames and raw error messages, -which may contain local file paths or the local username in those paths. -**ktx** redacts secrets, credentials, database URLs, auth headers, argv, raw -environment values, SQL text, row data, and user-typed prompt or MCP argument -text from the explicit `$exception` payload. See -[Telemetry](https://docs.kaelio.com/ktx/docs/community/telemetry) for the event -catalog and opt-out options. +**ktx** collects anonymous usage telemetry from interactive CLI runs to +improve setup, command reliability, and data-agent workflows. No file paths, +hostnames, SQL, schema names, error messages, or argv are recorded. See +[Telemetry](https://docs.kaelio.com/ktx/docs/community/telemetry) for the +event catalog and opt-out options. ## License diff --git a/assets/star-history.svg b/assets/star-history.svg index 8fa7bc08..23016f3e 100644 --- a/assets/star-history.svg +++ b/assets/star-history.svg @@ -1 +1 @@ -star-history.comMay 17May 24May 31Jun 07 200400600800kaelio/ktxStar HistoryDateGitHub Stars +star-history.comMay 17May 24May 31 200400600800kaelio/ktxStar HistoryDateGitHub Stars diff --git a/docs-site/app/docs/layout.tsx b/docs-site/app/docs/layout.tsx index 5f684ea0..ff7d69a9 100644 --- a/docs-site/app/docs/layout.tsx +++ b/docs-site/app/docs/layout.tsx @@ -2,21 +2,10 @@ import { source } from "@/lib/source"; import { DocsLayout } from "fumadocs-ui/layouts/docs"; import type { ReactNode } from "react"; import { baseOptions } from "@/app/layout.config"; -import { GitHubStars } from "@/components/github-stars"; export default function Layout({ children }: { children: ReactNode }) { return ( - - - - ), - }} - > + {children} ); diff --git a/docs-site/app/global.css b/docs-site/app/global.css index d6d9ada6..929e06b4 100644 --- a/docs-site/app/global.css +++ b/docs-site/app/global.css @@ -869,147 +869,6 @@ body::after { 50% { opacity: 0.65; transform: scale(0.9); } } -/* ═══════════════════════════════════════════ - GitHub star widget (navbar) - Split pill: GitHub mark + "Star" │ gold star + count. - ═══════════════════════════════════════════ */ -.ktx-stars { - display: inline-flex; - align-items: stretch; - height: 32px; - border-radius: 999px; - border: 1px solid var(--color-fd-border); - background: color-mix(in oklch, var(--color-fd-card) 72%, transparent); - backdrop-filter: blur(8px); - -webkit-backdrop-filter: blur(8px); - font-family: var(--font-display), var(--font-sans), sans-serif; - font-size: 13px; - line-height: 1; - color: var(--color-fd-foreground); - text-decoration: none; - overflow: hidden; - box-shadow: 0 1px 2px rgba(27, 27, 24, 0.04); - transition: - transform 0.3s var(--ktx-ease), - box-shadow 0.3s var(--ktx-ease), - border-color 0.3s ease; - animation: ktx-stars-in 0.5s var(--ktx-ease) both; -} - -@keyframes ktx-stars-in { - from { opacity: 0; transform: translateY(-4px); } - to { opacity: 1; transform: translateY(0); } -} - -.ktx-stars:hover { - transform: translateY(-1px); - border-color: color-mix(in oklch, var(--color-fd-primary) 45%, var(--color-fd-border)); - box-shadow: - 0 6px 18px -8px rgba(14, 116, 144, 0.28), - 0 1px 2px rgba(27, 27, 24, 0.05); -} - -.ktx-stars:focus-visible { - outline: 2px solid var(--color-fd-ring); - outline-offset: 2px; -} - -.dark .ktx-stars { - background: color-mix(in oklch, var(--color-fd-card) 60%, transparent); - box-shadow: 0 1px 2px rgba(0, 0, 0, 0.25); -} - -.dark .ktx-stars:hover { - border-color: rgba(34, 211, 238, 0.4); - box-shadow: - 0 6px 18px -8px rgba(34, 211, 238, 0.3), - 0 1px 2px rgba(0, 0, 0, 0.3); -} - -.ktx-stars-seg { - display: inline-flex; - align-items: center; - gap: 6px; - padding: 0 11px; -} - -.ktx-stars-seg--count { - border-left: 1px solid var(--color-fd-border); - background: color-mix(in oklch, var(--color-fd-primary) 6%, transparent); - transition: background 0.3s var(--ktx-ease); -} - -.ktx-stars:hover .ktx-stars-seg--count { - background: color-mix(in oklch, var(--color-fd-primary) 12%, transparent); -} - -.ktx-stars-gh { - width: 15px; - height: 15px; - opacity: 0.85; -} - -.ktx-stars-text { - font-weight: 500; - letter-spacing: -0.01em; -} - -.ktx-stars-star { - width: 14px; - height: 14px; - fill: #f5b301; - transition: transform 0.3s var(--ktx-ease), filter 0.3s var(--ktx-ease); -} - -.ktx-stars:hover .ktx-stars-star { - transform: scale(1.18) rotate(-8deg); - filter: drop-shadow(0 1px 4px rgba(245, 179, 1, 0.55)); -} - -.ktx-stars-count { - font-weight: 600; - font-variant-numeric: tabular-nums; - color: var(--color-fd-foreground); -} - -/* Skeleton shown only on the rare cold (uncached) fetch */ -.ktx-stars--skeleton { - animation: none; -} - -.ktx-stars-skeleton-bar { - display: inline-block; - width: 26px; - height: 11px; - border-radius: 4px; - background: linear-gradient( - 90deg, - var(--color-fd-muted) 25%, - color-mix(in oklch, var(--color-fd-muted-foreground) 28%, var(--color-fd-muted)) 50%, - var(--color-fd-muted) 75% - ); - background-size: 200% 100%; - animation: ktx-stars-shimmer 1.4s ease-in-out infinite; -} - -@keyframes ktx-stars-shimmer { - from { background-position: 200% 0; } - to { background-position: -200% 0; } -} - -/* Compact on phones: drop the "Star" word, keep mark + count */ -@media (max-width: 640px) { - .ktx-stars-text { display: none; } - .ktx-stars-seg { padding: 0 9px; } -} - -@media (prefers-reduced-motion: reduce) { - .ktx-stars { animation: none; transition: none; } - .ktx-stars:hover { transform: none; } - .ktx-stars:hover .ktx-stars-star { transform: none; } - .ktx-stars-skeleton-bar { animation: none; } -} - /* Dot grid */ .dot-grid { background-image: radial-gradient( diff --git a/docs-site/app/layout.config.tsx b/docs-site/app/layout.config.tsx index 4e91b559..3245ab09 100644 --- a/docs-site/app/layout.config.tsx +++ b/docs-site/app/layout.config.tsx @@ -1,13 +1,22 @@ import type { BaseLayoutProps } from "fumadocs-ui/layouts/shared"; +import { GitHubIcon } from "@/components/github-icon"; import { Logo } from "@/components/logo"; import { SlackIcon } from "@/components/slack-icon"; export const baseOptions: BaseLayoutProps = { nav: { - title: Logo, + title: , transparentMode: "top", }, links: [ + { + type: "icon", + label: "GitHub", + icon: , + text: "GitHub", + url: "https://github.com/kaelio/ktx", + external: true, + }, { type: "icon", label: "Join the ktx Slack community", diff --git a/docs-site/components/diagram-studio/flows.ts b/docs-site/components/diagram-studio/flows.ts index e63cc512..cddf75cb 100644 --- a/docs-site/components/diagram-studio/flows.ts +++ b/docs-site/components/diagram-studio/flows.ts @@ -305,8 +305,8 @@ export const runtimeEdges: Edge[] = [ sourceHandle: "to-context", target: "context", targetHandle: "in", - type: "smoothstep", - label: "search + read", + type: "default", + label: "search", ...labelBg, style: edgeStyle, markerStart: marker, @@ -318,7 +318,7 @@ export const runtimeEdges: Edge[] = [ sourceHandle: "to-warehouse", target: "warehouse", targetHandle: "in", - type: "smoothstep", + type: "default", label: "read-only", ...labelBg, style: edgeStyle, diff --git a/docs-site/components/github-stars.tsx b/docs-site/components/github-stars.tsx deleted file mode 100644 index d3b328a3..00000000 --- a/docs-site/components/github-stars.tsx +++ /dev/null @@ -1,93 +0,0 @@ -import { Suspense } from "react"; -import { GitHubIcon } from "@/components/github-icon"; - -const REPO = "kaelio/ktx"; -const REPO_URL = `https://github.com/${REPO}`; -const API_URL = `https://api.github.com/repos/${REPO}`; - -async function fetchStarCount(): Promise { - try { - const res = await fetch(API_URL, { - headers: { Accept: "application/vnd.github+json" }, - // Revalidate hourly. GitHub's unauthenticated REST limit is 60 req/h per - // IP, so a single cached server-side fetch keeps the count fresh while - // never exposing visitors to rate limits or layout shift. - next: { revalidate: 3600 }, - }); - if (!res.ok) return null; - const data = (await res.json()) as { stargazers_count?: unknown }; - return typeof data.stargazers_count === "number" - ? data.stargazers_count - : null; - } catch { - return null; - } -} - -/** Compact, GitHub-style count: 847 → "847", 1234 → "1.2k", 12345 → "12.3k". */ -function formatStars(count: number): string { - if (count < 1000) return count.toLocaleString("en-US"); - const thousands = count / 1000; - const rounded = - thousands >= 100 ? Math.round(thousands) : Math.round(thousands * 10) / 10; - return `${rounded}k`; -} - -function StarGlyph() { - return ( - - ); -} - -async function StarsContent() { - const count = await fetchStarCount(); - const label = - count === null - ? "Star ktx on GitHub" - : `Star ktx on GitHub — ${count.toLocaleString("en-US")} stars`; - - return ( - - - - Star - - {count !== null && ( - - - {formatStars(count)} - - )} - - ); -} - -function StarsSkeleton() { - return ( -