From 1611d0398708467e75404ddcbb569171b1431276 Mon Sep 17 00:00:00 2001 From: Ben Jacobson Date: Thu, 8 Oct 2026 04:48:39 +0000 Subject: [PATCH] docs: complete WorldVM rollout guidance and llms checks --- AGENTS.md | 62 +++++++++++++++++++++++++++++++++++++++++ README.md | 2 ++ docs/.vitepress/llms.ts | 6 ++-- e2e/docs-home.spec.ts | 1 + package.json | 2 +- scripts/check-llms.mjs | 49 ++++++++++++++++++++++++++++++++ 6 files changed, 118 insertions(+), 4 deletions(-) create mode 100644 AGENTS.md create mode 100644 scripts/check-llms.mjs diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..e6d9726 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,62 @@ +# Working on Triplex + +Triplex is a pre-1.0, Effect-native fact database for TypeScript. Read +[CONTRIBUTING.md](CONTRIBUTING.md), [ARCHITECTURE.md](ARCHITECTURE.md), and +[Current state](docs/current-state.md) before changing its contracts. The +[modeling guide](docs/agents.md) covers building applications with Triplex. + +## Setup and checks + +Use Node.js 22 or newer and the pinned pnpm 10.11.0: + +```sh +corepack enable +pnpm install --frozen-lockfile +pnpm check +``` + +`pnpm check` is the single root check: formatting (oxfmt), linting (oxlint), +TypeScript, checked Markdown examples and generated example outputs, unit and +SQLite/workerd integration tests, package builds, and the VitePress docs build. +The docs build also checks the generated `dist/llms.txt` structure and local links. + +Run `pnpm pack:check` after package changes to verify tarballs and a clean consumer. +PostgreSQL and FoundationDB integrations require external services or native +libraries and are opt-in with `pnpm test:postgres:integration` and +`pnpm test:foundationdb:integration`. Follow CONTRIBUTING.md for changes that +require these suites. Browser tests use `pnpm test:e2e` after installing Chromium +with `pnpm exec playwright install chromium`. Stress tests are opt-in with +`pnpm --filter triplex-stress stress-test`. + +## Repository layout + +- `packages/core`: browser-safe model, Effect services, KV storage, Datalog, + configuration, derivations, and public runtime composition. +- `packages/sql`, `packages/sqlite`, `packages/postgres`, `packages/cloudflare`, + `packages/foundationdb`: shared SQL and backend implementations. +- `packages/host`, `packages/http`, `packages/cli`, `packages/dashboard`, + `packages/testkit`: hosting contracts, HTTP, tools, and reusable conformance tests. +- `examples/`: runnable demos and reference hosts. +- `test/integration`, `test/stress`, `e2e/`: cross-package, stress, and browser tests. +- `docs/`: VitePress pages and checked snippets; `docs/.vitepress/llms.ts` + generates `llms.txt`, `llms-full.txt`, and Markdown page variants into `dist/`. +- `scripts/`: documentation and package checks. +- `.github/workflows/`: CI, docs deployment, and Changesets releases; + `alchemy.run.ts` defines the Cloudflare documentation site. + +## Conventions and boundaries + +- Use ESM and TypeScript with Effect. Pin external dependencies in the root pnpm + catalog and use workspace packages through their public exports. +- Preserve the one-way graph in ARCHITECTURE.md: core must not depend on backends + or Node-only APIs; SQL and backend packages build on core. +- Public exports point to generated `dist` files. Add a Changeset for a + publishable package change; keep private packages out of its frontmatter. +- Mark self-contained documentation examples with `ts check` fences; use ordinary + `ts` fences for fragments. Keep generated outputs in sync with `pnpm docs:outputs`. +- Keep maturity claims accurate: KV and SQLite are supported, PostgreSQL is a + pre-1.0 production candidate, and Cloudflare and FoundationDB are experimental. +- Do not edit generated `dist` files, import sibling project source, or bypass + public package boundaries. Do not deploy manually, publish packages, or merge + without explicit authorization; the existing workflows handle deployment and + releases. diff --git a/README.md b/README.md index 8b53d73..6d2cbff 100644 --- a/README.md +++ b/README.md @@ -614,6 +614,8 @@ pnpm test:foundationdb:integration See [CONTRIBUTING.md](CONTRIBUTING.md) for the complete contribution contract. +Part of the [WorldVM](https://worldvm.com) family of experiments. + ## License MIT © 2026 Ben Jacobson. diff --git a/docs/.vitepress/llms.ts b/docs/.vitepress/llms.ts index 0cf73c5..0017d87 100644 --- a/docs/.vitepress/llms.ts +++ b/docs/.vitepress/llms.ts @@ -20,10 +20,10 @@ export const siteUrl = "https://triplex.build"; const summary = "The database that remembers why: an embedded fact database for TypeScript back-office " + "systems. Every write records who made it, which versioned rules governed it, and when it was " + - "true, so audit questions and open work become queries."; + "true, so audit questions and open work become queries. Triplex is pre-1.0; install with " + + "`npm install @triplex-build/triplex effect@4.0.0-rc.112`."; -const keyFacts = `Install with \`npm install @triplex-build/triplex effect@4.0.0-rc.112\`. Triplex is pre-1.0, -requires Effect 4 (\`effect@4.0.0-rc.112\`; Effect 3 is not compatible), is ESM-only, and targets +const keyFacts = `Triplex requires Effect 4 (\`effect@4.0.0-rc.112\`; Effect 3 is not compatible), is ESM-only, and targets Node.js 22+ plus modern browsers and edge runtimes for the core. In-memory and SQLite storage are supported, PostgreSQL is a production candidate, and Cloudflare and FoundationDB are experimental. diff --git a/e2e/docs-home.spec.ts b/e2e/docs-home.spec.ts index f37b1f7..88445c2 100644 --- a/e2e/docs-home.spec.ts +++ b/e2e/docs-home.spec.ts @@ -81,6 +81,7 @@ test("decision receipt preserves its rules while switching recorded knowledge", test("agent-readable documentation is served as plain text", async ({ request }) => { const index = await request.get("/llms.txt"); expect(index.ok()).toBe(true); + expect(index.headers()["content-type"]).toContain("text/plain"); const body = await index.text(); expect(body).toMatch(/^# Triplex\n\n> The database that remembers why/); expect(body).toContain("(https://triplex.build/agents.md)"); diff --git a/package.json b/package.json index 4f8a65f..37f5cb4 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "clean": "turbo run clean", "check": "pnpm format:check && pnpm lint && pnpm typecheck && pnpm docs:check && pnpm test && pnpm build", "dev": "turbo watch build", - "docs:build": "vitepress build docs", + "docs:build": "vitepress build docs && node scripts/check-llms.mjs", "docs:check": "node scripts/check-markdown-code.mjs && tsc --noEmit -p docs/snippets/tsconfig.json && pnpm docs:outputs --check", "docs:outputs": "tsx --tsconfig docs/snippets/tsconfig.json docs/snippets/home/site-safety/run.ts", "docs:deploy": "alchemy deploy --stage prod", diff --git a/scripts/check-llms.mjs b/scripts/check-llms.mjs new file mode 100644 index 0000000..484a338 --- /dev/null +++ b/scripts/check-llms.mjs @@ -0,0 +1,49 @@ +import assert from "node:assert/strict"; +import { readFile, stat } from "node:fs/promises"; +import { dirname, resolve, sep } from "node:path"; +import { fileURLToPath } from "node:url"; + +const outDir = resolve(dirname(fileURLToPath(import.meta.url)), "../dist"); +const siteUrl = new URL("https://triplex.build"); +const index = await readFile(resolve(outDir, "llms.txt"), "utf8"); + +assert.match(index, /^# Triplex\n\n> \S[^\n]+\n/, "llms.txt needs an H1 and summary"); +const summary = index.split("\n")[2]; +assert.match(summary, /pre-1\.0/, "The summary must state maturity"); +assert.match( + summary, + /npm install @triplex-build\/triplex/, + "The summary must explain installation", +); +assert.doesNotMatch(index, / 0, "llms.txt needs sections"); +for (const section of sections) { + const entries = section.split("\n").filter((line) => line.startsWith("- ")); + assert.ok(entries.length > 0, "Each section needs documentation links"); + for (const entry of entries) { + assert.match(entry, /^- \[[^\]]+\]\([^)]+\): \S/, "Links need titles and notes"); + } +} + +let localLinks = 0; +for (const [, href] of index.matchAll(/\[[^\]]+\]\(([^)]+)\)/g)) { + const url = new URL(href); + assert.equal(url.protocol, "https:", `Use absolute HTTPS links: ${href}`); + if (url.origin !== siteUrl.origin) continue; + + const pathname = decodeURIComponent(url.pathname); + const file = resolve(outDir, `.${pathname}`); + assert.ok(file.startsWith(`${outDir}${sep}`), `Link leaves the docs output: ${href}`); + assert.ok((await stat(file)).isFile(), `Missing built page: ${href}`); + // Check the actual asset, so an HTTP fallback cannot mask a missing page. + if (/\.(md|txt)$/.test(pathname)) { + const content = await readFile(file, "utf8"); + assert.ok(content.trim().length > 0, `Empty documentation: ${href}`); + assert.doesNotMatch(content, / 0, "llms.txt must link to local documentation"); +console.log(`Verified llms.txt structure and ${localLinks} local documentation links.`);