Skip to content
Merged
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
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v5

- name: Setup Bun
uses: oven-sh/setup-bun@v2
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/deploy-schema.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:
url: ${{ steps.deployment.outputs.page_url }}
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v5

- name: Configure Pages
uses: actions/configure-pages@v5
Expand Down
96 changes: 96 additions & 0 deletions .planning/00-START-HERE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# Predicate Semantics — Start Here

**What this is:** a proposal to add a small set of machine-readable fields to our predicate specs
(`packages/predicates`) so the Intuition knowledge graph can render itself, query across relationship
hierarchies, synthesize reverse edges, and price disagreement. Grounded in 30 years of knowledge-graph
research, pruned hard to stay simple.

**Status:** Draft for team review · **Date:** 2026-06-30 · **Owner:** Architecture

---

## TL;DR — what we're proposing

Add **9 new fields** to `PredicateSpec` (flat, all optional, additive/non-breaking), plus two soft-ships
(`claimType`, `supersededBy`), plus the existing `marketPattern`:

| Field | Type | What it unlocks |
|---|---|---|
| `objectKind` | `entity \| claim \| literal` | frontend renders any edge with no per-predicate code; makes reification visible |
| `literalType` *(audit)* | `url \| image \| date \| number \| text` | completes the rendering contract for literals (RDF typed-literals lesson) |
| `polarity` | `positive \| negative \| neutral` | one signed reputation score across all predicates; sentiment-colored UI |
| `inverse` | `PredicateKey` | store one edge, serve both directions (different reverse predicate) — with a **canonical direction** per pair |
| `isSymmetric` | `boolean` | store one edge, serve both directions (same predicate) — with **mint-time canonical ordering** |
| `temporalNature` | `permanent \| state \| event` | freshness model — which edges rot, which are forever |
| `contradicts` | `PredicateKey[]` | detect & price disagreement (trust ⊥ distrust, **same subject/object pair**) — the differentiator |
| `isTransitive` | `boolean` | closure/reachability queries (containment trees, org charts) — never sentiment |
| `specializes` | `readonly PredicateKey[]` | roll-up queries & reputation (employedBy ⊑ affiliatedWith); DAG, not tree |
| `claimType` *(soft-ship)* | `factual \| evaluative` | fact-vs-opinion market & UI semantics |
| `supersededBy` *(soft-ship, audit)* | `PredicateKey` | deprecation forwarding — pickers redirect, old edges stay legible |
| `marketPattern` *(exists)* | `depositional \| attributive \| comparative` | per-predicate market mechanics |

**Deliberately deferred or cut** (no consumer yet / redundant): `isAsymmetric`, `isFunctional`,
`isInverseFunctional`, `isReflexive`/`isIrreflexive`, `equivalentTo`, `verifiability`, property chains,
`isHierarchical`. See `predicate-fields/deferred-and-cut.md`.

**Guiding rule:** a field ships only if it names a *consumer that exists today* (frontend, indexer) or an
*emerging* one (reputation/markets). We deliberately stay inside the cheap, forward-chainable **OWL 2 RL**
reasoning profile and don't encode inference we can't compute at scale.

---

## Reading order

1. **`00-START-HERE.md`** (this file) — the summary and reading order.
2. **`predicate-spec-decisions.md`** — ⭐ *canonical.* The pruned field set, flat-vs-nested decision, the
final `PredicateSpec`, pros/cons, and what we're explicitly not doing.
✅ Read together with **`predicate-spec-audit.md`** — the adversarial review pass, **all findings now
folded into the docs** (2026-07-01). It confirmed the overall shape and drove: mint-time
canonicalization for symmetric/inverse triples (§5.2 — the blocking economic fix), the precise
pair-level definition of `contradicts` (P3), the `literalType` + `supersededBy` fields, `specializes`
widened to an array, the complete 14-rule validation set (§5.1), and the normative OWL/RDF
serialization table (§5.3).
3. **`predicate-fields/`** — one document per field with multiple use cases and a confidence score
(see `predicate-fields/README.md` for the rubric and the score table). This is where each field earns
its place; the scoring overturned one earlier decision (`isAsymmetric`).
4. **`predicate-semantics.md`** — the original full brainstorm / map of everything possible. Background;
its §5 schema sketch is superseded by #2.
5. **`predicate-semantics-foundations.md`** — the research grounding: OWL/RDF property characteristics in
depth and 30 years of KG lineage. Read for the "why these and not others."
6. **`predicate-backend-integration.md`** — how the backend (`alpha/backend`) consumes these fields:
schema, indexing, query optimization, performance. **Headline:** `kg.predicates` already has dormant
slots for `is_symmetric`/`is_transitive`/`inverse_predicate_id`/`metadata`, and `kg.triples` already
has `inferred`/`confidence` for synthesized edges — so this is mostly *activation*, not construction.
Three gaps: seed real metadata, add the missing columns, build the consumers.
7. **`predicate-backend-implementation-plan.md`** — the ticket-ready build plan: 7 workstreams
(package → schema → seed → query features → API → consumers → tests), phased P0–P5 with dependencies,
acceptance criteria, and rough sizing. Start here when we're ready to execute.
8. **`predicate-query-optimization-spec.md`** — deep dive on the hardest read path: gathering metadata &
resolving identity by traversing connected triples from a root item (the Spotify→Apple Music case).
Predicate registry/parsing, the exact `kg.triples` indexes, the equivalence-class engine (query-time
vs materialized union-find), and the batched gather algorithm. **Headline:** identity/metadata is
moving from embedded JSON-LD (`data_resolved.sameAs`) to triple-native edges; this makes that fast.

If you read only one: **`predicate-spec-decisions.md`**.

---

## Open questions for the team

1. **`claimType`** — soft-ship now (define + populate where obvious), or hold entirely until a market
branches on it?
2. **`polarity`** — keep an explicit `neutral` value (for `neutralOn`) distinct from "absent," or collapse?
3. **`isInverseFunctional`** — pull forward to *start collecting* dedup/identity data before the resolution
engine exists (data only, no auto-merge)?
4. **`marketPattern`** — its three values lack an external anchor and overlap conceptually with `claimType`;
does it need its own semantics-clarification doc before we lean on it for market mechanics?
5. **`contradicts`** — hard contradiction only (trust/distrust), or do we also model soft *tension*
(skepticalOf/trust) as a separate relation?

---

## The one-sentence pitch

*Every predicate carries just enough machine-readable structure that the graph can render itself, query
across relationship hierarchies, synthesize reverse edges, and price disagreement — using the proven flat
vocabulary of 30 years of knowledge-graph research, and nothing more than that.*
166 changes: 166 additions & 0 deletions .planning/forum-post-intro.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
# Build the knowledge graph off-chain first: an intro to the Intuition packages (and where they're heading)

*Draft forum post — for the Intuition community forum. Written developer-to-developer.*

---

Hey everyone 👋

I want to introduce something we've been building that I think changes how you'll build on Intuition: a
set of focused TypeScript packages that let you **model the entire knowledge graph off-chain first**, for
free, and only settle on-chain when it actually matters.

This post is a proper introduction — what the packages are, the concepts behind them, how to think about
them — plus a peek at where we're taking them next. It's long-ish because there's a real mental model here,
but each piece is simple on its own. Grab a coffee.

One thing up front so nobody's surprised: what's out today is the *packages* — the client-side TypeScript
layer you build against. The backend that indexes and serves the graph isn't open source yet. It's coming,
and soon, but I didn't want to bury it: everything I describe below runs without it, which is kind of the
whole point.

## The shift: off-chain first

If you've built on-chain before, you know the tax: **every piece of data costs a transaction.** Put a fact
on the graph? Pay. Connect two things? Pay again. That model quietly kills experimentation — you don't
prototype freely when every idea has a gas bill attached.

The packages flip this. You can define atoms, wire up relationships, compute IDs, build whole creation
flows and UIs — **entirely off-chain, entirely free** — and bring things on-chain only when they're worth
settling. The official quickstart is dry-run by design: no wallet, no API key, no live submission needed.

```bash
cd examples/hackathon-quickstart
bun run dev
```

Off-chain to move fast. On-chain when it counts. Everything below serves that idea.

## The core concepts (the whole graph in three words)

Intuition's knowledge graph is built from a tiny, composable vocabulary:

- **Atoms** — the nouns. A person, a song, an org, a URL, a concept. Anything you can point at.
- **Predicates** — the verbs / relationships. `member of`, `authored by`, `same as`, `trusts`.
- **Triples** — a statement made of the two: **subject → predicate → object.**
`Alice → member of → Acme`. That's an edge in the graph.

Two more ideas that matter a lot:

- **Deterministic IDs.** Every atom, predicate, and triple has a **content-addressable ID** you can compute
*before* anything touches a chain. Same content → same ID, everywhere, forever. This is the part that
quietly makes everything else work: your off-chain graph and the eventual on-chain graph speak the same
identifiers, so there's no "import/sync" cliff later. You're always building the real thing.
- **`sameAs` identity.** Different atoms can point at the same real-world thing (the same song on Spotify
and Apple Music, the same person across two profiles). `sameAs` links them so the graph can treat them as
one identity without forcing everyone to agree on a single canonical atom up front.

If you internalize atoms / predicates / triples / deterministic IDs / sameAs, you understand Intuition.

## The packages, by layer

We split everything into small, ESM-only packages so you install **only the layer you need** while
converging on shared vocabulary and IDs. Here's the map and how to think about each:

### 🧩 Semantic / data modeling — *what things are and how they relate*

- **`@0xintuition/schema-org`** — a pinned [schema.org](https://schema.org) vocabulary (types + properties,
with inherited-property lookup). This is the shared dictionary so a "MusicRecording" means the same thing
in your app and mine.
- **`@0xintuition/classifications`** — Intuition classification specs and **Creation Profiles**: the
recommended fields for a given kind of thing, plus the relationships that make sense for it. This is what
lets you render a correct "create a song" form without hardcoding it.
- **`@0xintuition/predicates`** — the canonical **predicate registry**: the blessed set of relationships,
their deterministic IDs, display helpers, and which predicates suit which entity types. When you need a
relationship, you reach here.

### 🔑 Identity — *stable names for everything*

- **`@0xintuition/ids`** — deterministic, content-addressable IDs for atoms, predicates, triples,
counter-triples, and OAuth atoms. The backbone that makes off-chain-first coherent.

### 🛠️ Builder helpers — *the ergonomic layer*

- **`@0xintuition/primitives`** — high-level builders and validators for atoms, claims, triples, and
discovery. Instead of assembling raw structures, you call `buildTripleByName(...)` and get a validated
result. This is where most app code lives.

### ⚙️ Protocol plumbing — *when you're ready to go on-chain*

- **`@0xintuition/protocol`** — core contract ABIs, event parsers, interaction helpers.
- **`@0xintuition/deployments`** — typed chain metadata and deployment addresses.
- **`@0xintuition/periphery`** — periphery ABIs and bridge/router helpers.
- **`@0xintuition/curves`** — bonding-curve math for the market/staking side.
- **`@0xintuition/react`** — React hooks for the core protocol interactions.

The nice thing about splitting it this way: you can live entirely in the top three layers while prototyping,
and only reach for the protocol layer once your app actually owns a wallet and a submission flow. (Reading
the *global* graph back — everyone's atoms and triples, not just the ones you built locally — is the job of
the indexing backend, which, as mentioned, is still on its way. For now you're modeling and settling; the
querying side lands when that opens up.)

## How they work together (a tiny walkthrough)

Say you're building a music app. Start from a Creation Profile:

```ts
import { musicRecordingCreationProfile } from '@0xintuition/classifications/creation/music-recording'

const fields = musicRecordingCreationProfile.fields // render your atom form
const relationships = musicRecordingCreationProfile.relationships // suggest valid triples
// e.g. MusicRecording -> inPlaylist -> MusicPlaylist
```

Use `fields` to render inputs, `relationships` to suggest predicates, `primitives` to build and validate
the triple, and `ids` to know its ID before you ever sign. Your UI is generated **from the package data**
instead of an app-local shadow copy that drifts. When (and if) you're ready, the protocol layer settles it
on-chain — with the exact same IDs you've been using all along.

That's the loop: **model → validate → (optionally) settle**, with deterministic identity the whole way.

## Where this is heading: predicates that describe themselves

Here's the part I'm most excited to build *with you*.

Right now a predicate's meaning mostly lives in its name and description — great for humans, opaque to
machines. We're exploring giving each predicate a little **machine-readable metadata about how the
relationship behaves**, so the graph can actually reason:

- **Symmetric?** `Acme → partner of → BigCo` implies the reverse automatically.
- **Has an inverse?** `parent org` ⇄ `subsidiary of` — assert one, get the other.
- **Transitive?** venue in district in city ⟹ venue in city, as one query.
- **Carries sentiment?** `endorse` is positive, `distrust` negative — so reputation becomes something the
graph computes instead of every app hardcoding it.
- **What's on the other end?** entity vs. raw value vs. *another claim* — one field that lets a frontend
render any edge with zero custom code.

Circle back to `sameAs`: imagine a song created from a Spotify link, and later someone connects the Apple
Music version **as a real edge**. Now "give me every link for this track," "what does the community know
about it," and "are these two items secretly the same thing?" all become answerable by walking connected
triples. That last one — knowing two nodes are the same reality — is exactly what machine-readable
predicates unlock, and it's everywhere: identity, products, tokens, provenance.

This is grounded in the same ideas 30 years of knowledge-graph work (RDF, OWL, schema.org) landed on — we're
adapting the proven parts and cutting the over-engineered ones. And the vocabulary isn't settled, which is
why I'm posting now.

## Come build with us

An open invitation:

- 🧪 **Prototype something.** Everything's on npm (`@alpha`) and runs off-chain out of the box. Start from
the quickstart, define some atoms and triples, break things, show us.
- 💬 **Bring your use case.** Music, identity, DeFi, social, science, provenance — every domain has
relationships that want to be first-class. Tell us yours and we'll model the predicates together.
- ❓ **Ask hard questions.** Especially "wait, how would this handle…" — those are how we find the gaps.
- 🔧 **Argue the design.** Are `symmetric` / `transitive` / `inverse` the right words or too academic? What
relationship properties are we missing? Where's the line between expressive and over-complicated? Reply and
push on it.

The dream is a knowledge graph you can build for free, that renders itself, queries across relationships
intelligently, knows when two things are the same, and can even represent disagreement — settled on-chain
only when it matters. I think we can get there, and it's more fun to figure out with you.

What would you build first? 👇

— *[your name]*
Loading