Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -572,6 +572,16 @@ compose storage and query layers with a validated database scope and explicit ca
`@triplex-build/triplex/internal` remains unstable implementation support for legacy adapter code.
Public exports resolve only to built `dist` files.

## Triplex and WorldVM

Triplex is a standalone database: it has no dependency on WorldVM, and you do not need WorldVM to
use it. It is also the temporal fact store in [WorldVM](https://worldvm.com), a TypeScript runtime
and standard library for software that models the world, reasons about it, and acts on it. There,
Triplex answers one question: what is true, and what was true? Triplex owns facts, time, the
journal, configuration, and provenance; WorldVM owns actors, permissions, programs, threads, and
external effects. WorldVM's `@worldvm/*` packages are not published yet. See
[Triplex and WorldVM](docs/worldvm.md) for the exact boundary.

## Documentation

| Document | Purpose |
Expand All @@ -592,6 +602,7 @@ Public exports resolve only to built `dist` files.
| [Custom runtimes](docs/custom-runtimes.md) | Public runtime builders, capabilities, and backend contracts |
| [Architecture](ARCHITECTURE.md) | Package boundaries and dependency direction |
| [Roadmap](docs/roadmap.md) | Release gates and future work |
| [Triplex and WorldVM](docs/worldvm.md) | Relationship to WorldVM and the API boundary |
| [Source provenance](docs/provenance.md) | Imported repository history |

The focused configuration explorer remains under [`examples/config-explorer`](examples/config-explorer),
Expand Down
1 change: 1 addition & 0 deletions docs/.vitepress/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ const sidebar: DefaultTheme.SidebarItem[] = [
items: [
{ text: "Custom runtimes", link: "/custom-runtimes" },
{ text: "Roadmap", link: "/roadmap" },
{ text: "Triplex and WorldVM", link: "/worldvm" },
],
},
];
Expand Down
4 changes: 2 additions & 2 deletions docs/datalog-performance.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,8 @@ for facts whose `value_type` is `number` or `datetime`. It matches the compiler'
expression: both storage types compare numerically, and equal numeric values still collapse in
Datalog projections. The existing number-only index remains available for typed storage reads.

This covers [Runfold PR #4](https://github.com/bjacobso/runfold/pull/4)'s `src/actor.ts` due-work
query without an application index declaration or per-actor DDL:
This covers the actor due-work query in Runfold, the engine that runs [WorldVM](/worldvm) programs,
without an application index declaration or per-actor DDL:

```ts check
import { Effect } from "effect";
Expand Down
6 changes: 3 additions & 3 deletions docs/host-integration.md
Original file line number Diff line number Diff line change
Expand Up @@ -165,9 +165,9 @@ transaction, verify that the index is valid, then run the migration to record it
`IF NOT EXISTS` checks the name, not the definition or validity: reserve `idx_attr_numeric` for
Triplex and resolve any conflicting or invalid index before migrating.

Runfold can remove its `runfold_actor_due` DDL after deploying this Triplex version and applying
the migration to every database. Triplex does not drop that host-owned index; dropping an existing
redundant index is a separate host migration. Older binaries can read the additive schema, but
Hosts that added an equivalent index, such as Runfold's `runfold_actor_due`, can remove that DDL
after deploying this Triplex version and applying the migration to every database. Triplex does
not drop that host-owned index; dropping an existing redundant index is a separate host migration. Older binaries can read the additive schema, but
old SQLite bulk-loading code that drops/rebuilds only its known indexes cannot suspend maintenance
of the new index. Deploy the migration and updated runtime together when using bulk loading.
See [numeric query plans and indexing scope](/datalog-performance#numeric-ranges-and-actor-due-work).
Expand Down
87 changes: 87 additions & 0 deletions docs/worldvm.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# Triplex and WorldVM

Triplex is a standalone database. It has no dependency on WorldVM, and you do not need WorldVM to
use it. It is also the temporal fact store in [WorldVM](https://worldvm.com), a TypeScript runtime
and standard library for software that models the world, reasons about it, and acts on it.

This page describes that relationship and the contract between the two projects. WorldVM's
`@worldvm/*` packages are not published yet; anything here that names them describes planned work.

## What does not change

- Triplex keeps its name, the `@triplex-build` npm scope, its MIT license, and this site.
- The [maturity contract](/current-state) belongs to Triplex. Using Triplex through WorldVM adds
no guarantee beyond it: a WorldVM deployment is only as durable as the Triplex backend it runs on.
- Triplex's public API has no WorldVM-specific surface. When WorldVM needs something from storage,
it lands here as a general, backend-neutral Triplex feature with its own documentation and
conformance tests. The [numeric range index](/datalog-performance#numeric-ranges-and-actor-due-work)
began as a Runfold due-work query and shipped as an ordinary Datalog improvement.

## The question Triplex answers

WorldVM divides a system into concepts that each answer one question. Triplex answers one of them:
**what is true, and what was true?**

| Concept | Question | Relationship to Triplex |
| ------------- | --------------------------------- | ---------------------------------------------------------------------------- |
| Open Ontology | What exists? | A separate project; its runtime adapter stores and queries models in Triplex |
| Triplex | What is/was true? | Bitemporal facts, the causal journal, and versioned configuration |
| Query | What do I know? | A WorldVM concept; Triplex Datalog evaluates queries over facts |
| Program | What could happen? | A WorldVM concept; its engine stores definitions and run facts in Triplex |
| Change | What would change? | A WorldVM concept; Triplex overlays preview hypothetical facts |
| Policy | What is allowed? | A WorldVM concept; Triplex records which release governed a write |
| Thread | What is happening? | A WorldVM concept |
| Event | What happened? | A WorldVM concept; the Triplex journal records every commit |
| Connection | How do I reach the outside world? | A WorldVM concept |

WorldVM is what makes those concepts one system. Within it:

- **Open Ontology** is WorldVM's world model.
- **Triplex** is WorldVM's temporal fact store.
- **Runfold** is the engine that runs WorldVM programs. Developers use the planned
`@worldvm/program` package; Runfold is the interpreter underneath it, not a separate product.

## The boundary

To Triplex, WorldVM is a host application. The responsibility split in
[Core concepts](/concepts#constraints-and-responsibility-boundaries) and
[Host integration](/host-integration) applies unchanged: Triplex records and explains state; the
host decides who may act, what work to do, and how to reach the outside world.

### What WorldVM relies on

WorldVM uses only Triplex's public entrypoints. This is the surface its runtime builds on:

| Area | Triplex surface | What WorldVM uses it for |
| ---------- | ------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------- |
| Facts | `Triples.transact`, `entity`, `match`, `history`; `EntityId`, `ref`, and typed values | Storing entities, facts, and relations as attributed assertions |
| Time | The `{ recordedAt, validAt }` read basis, `validFrom`/`validTo`, `currentPosition` | As-of reads, future-effective facts, and expiring evidence |
| Query | `query`, `queryPage`, `queryAll` | Evaluating fact queries at one coherent basis |
| Journal | `transactions`, `transactionsForEntity`, `transactionByCommand`, `ConsumerCheckpoint` | Command receipts, safe retries, entity timelines, and worker catch-up |
| Config | `ConfigStore` (`commit`, `resolveRef`, `snapshotById`), `Attribute`, `EntityType`, `GraphConstraint` | Publishing versioned definitions and enforcing them atomically |
| Provenance | Transaction `meta`: `actor`, `commandId`, `correlationId`, `causationId`, `configSnapshot`, `enforce`; `ContentId` | Recording who acted, under which release, and in response to what |
| Storage | `KvTriples`, `SqliteTriples`, `PgTriples.layerFromSqlClient`, and the `runtime` subpath | Choosing a backend and sharing a host SQL transaction |

Changes to this surface follow Triplex's normal release process and changesets. Nothing on it is
reserved for WorldVM.

### What WorldVM owns

- **Actors and capabilities.** Triplex records the `actor` a host supplies; it does not
authenticate anyone or decide who may act.
- **Programs, threads, and timers.** A derivation reports its next temporal boundary; WorldVM
schedules the wakeup, runs the work, and retries it.
- **Events.** The Triplex journal records commits. Domain events such as `member.invited` are
WorldVM vocabulary, recorded through those commits.
- **Connections and external effects.** Triplex never sends an email, calls a webhook, or charges a
card.
- **Standard library types.** Organization, User, Membership, Subscription, and similar types are
WorldVM types stored as Triplex facts. Triplex has no built-in notion of them.

### Ground rules

- WorldVM imports public entrypoints only, never `@triplex-build/triplex/internal`.
- `_triplex/*` entities and `:triplex/*` attributes stay reserved for Triplex. WorldVM uses its own
namespaces.
- A WorldVM need that Triplex's public API cannot meet becomes a Triplex proposal, specified
without reference to WorldVM and tested on every supported backend.
Loading