Write canonical Intuition vocabulary + predicate registry candidacy - #18
Open
jeremie-olivier wants to merge 29 commits into
Open
Write canonical Intuition vocabulary + predicate registry candidacy#18jeremie-olivier wants to merge 29 commits into
jeremie-olivier wants to merge 29 commits into
Conversation
- Connect wallet in header, enforce chain 1155 with switch prompt, and document env / Node version requirements.
Show ENS Refactor my first commit
Feat/privy
Feat/sdk integration
rename glossory to protocol ( all terme)
Fix/improvement
improvement searc
Feat/predicate search
Changed additive filter to a funnel
Changed entity relationships
pnpm-workspace.yaml was committed without a `packages:` key, so pnpm treated the repo as a monorepo and aborted with "packages field missing or empty" before resolving any dependencies. This is a single package, not a workspace, so the file is removed; its `allowBuilds` block (which held literal placeholder strings, not booleans) becomes a valid `pnpm.onlyBuiltDependencies` entry in package.json. Also: - drop package-lock.json so the package manager is unambiguous — nixpacks already selects pnpm from pnpm-lock.yaml - pin packageManager to pnpm@9.15.9 to match the deploy image - declare @0xintuition/protocol, which intuition-chain.ts imports but which only resolved transitively Verified with `pnpm i --frozen-lockfile && pnpm build`. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…egistry Claims created in Ontology could not join the shared graph. The app minted predicate atoms by hashing a bare label — createAtomFromString(config, 'created by') — while the canonical registry hashes a JSON-LD DefinedTerm document. Those are different bytes, so they produce different atom ids: every predicate atom this app wrote was invisible to the rest of the ecosystem, and vice versa. The canonical derivation did not exist when Mission 01 was built. This is drift, not a defect in that work. Canonical identity - src/lib/intuition/canonical.ts is the single boundary to the alpha @0xintuition/* packages, so an alpha bump has one blast radius - predicate atoms now carry canonical DefinedTerm bytes - writes preflight the deterministic id against the indexer and reuse the atom instead of minting a duplicate — free, synchronous, no wallet needed - the minted id is asserted against the precomputed one; a mismatch throws rather than silently staking against the wrong atom Vocabulary reconciliation - 56 predicates: 29 direct, 7 direction-flipped, 20 proposal candidates - 39 entity types: 32 direct, 4 renamed upstream, 3 app-local - directions were verified against each canonical predicate's description, not inferred from its name — `founder` reads organization→person, so this app's `founder of` maps to `founded` - flips implement mint-time canonicalisation locally: <A,employs,B> and <B,employedBy,A> are one fact hashing to two vaults, which upstream audit A1 calls economically unsound. Their fix (item A8) has not shipped. The builder discloses the swap before staking. Predicate registry - propose via <candidate> — listedIn → <predicateRegistry>, ranked by net stake - mints the registry atom when absent; it is unminted on both networks today - candidacy is deliberately a different edge from ratified membership, which upstream records as <registry, contain, X>. A proposal is not yet true. Read-only mode - WalletProvider previously rendered ONLY a warning banner when VITE_PRIVY_APP_ID was unset, replacing the entire app. An unconfigured optional integration took down everything that never needed it. - the read stack now sits outside the wallet stack; wallet hooks select an inert implementation at module load from the build-time constant - read-only bundle is 858 kB vs 5.6 MB — Privy and wagmi tree-shake out Bundle - vendor splitting + route-level lazy loading - entry chunk 3,221 kB -> 186 kB Docs - README replaced (was still the Vite template) - .env.example documents that VITE_* are build-time only, with the Coolify build-variable requirement that caused the preview deploy to ship an env-less bundle - plan.md records the analysis and open questions for the Intuition team Verified: tsc clean, new files lint clean, all five routes render headless with no console errors, in both wallet and read-only builds. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
The preview deployment for Ontology is ready. 🟢 Open Preview | Open Build Logs | Open Application Logs Last updated at: 2026-08-05 15:30:25 CET |
The wallet build shipped a blank page:
Uncaught ReferenceError: Cannot access 'wr' before initialization
at /assets/vendor-query-*.js
Splitting vendors by package (vendor-react, vendor-query, vendor-chain, …) cut
chunk boundaries through cyclic imports between those packages. Rollup emitted
chunks whose cross-chunk initialisation order is not satisfiable, so the entry
threw before React mounted.
The failure only reproduced in the wallet build — the read-only build has a
sparse enough dependency graph to avoid the cycle. That is exactly the gap in
how this was verified: the headless smoke test ran against a read-only build,
then a wallet build was shipped untested.
Chunking is now left to Rollup. Route-level lazy() stays, because those
boundaries are derived from real dynamic imports rather than guessed.
Entry chunk is 3,087 kB rather than the 186 kB the broken config produced.
Reducing it further means lazy-loading the Privy subtree behind Suspense, which
is a real change to first paint and belongs in its own PR with its own
verification.
Verified: all five routes render headless with zero uncaught errors in the
wallet build, not just the read-only one.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The three modes were presented as interchangeable data sources. They are stages of one pipeline — try it on Testnet, argue it for real on Mainnet, and if it reaches consensus it is adopted into the @0xIntuition packages, which is what Standard reads. The distinction is load-bearing: the same action costs nothing, costs TRUST, or is impossible, depending on where you are. Modes - ordered Testnet → Mainnet → Standard everywhere, matching the journey - Standard is now the default; a first-time visitor lands on the settled read-only vocabulary rather than a live network where actions cost TRUST - the switcher shows the mode name on the trigger, not just in the menu, and each option carries its step number and purpose. Which mode you are in changes whether an action spends money, so it must never require opening a dropdown to check. - src/lib/wallet/ontology-modes.ts is the single source for order and copy Standard mode now reads the packages, not src/data - Entity Hierarchy: 37 classifications grouped into the package's own 7 categories, with field counts - Entity Schema: field-level spec — labels, types, required flags — plus the schema.org link and recommended predicates - Entity Relationship: typed relationships from the metadata-predicate matrix (`director → person`), falling back to the classification's own metadataPredicates where the matrix has no entry. The two are shown distinctly: an untyped row is a gap in the standard, which is itself worth proposing a fix for. - Predicate Explorer: all 133 predicates by category, filterable by status, showing enshrined vs proposed. Status is the headline — staking on a proposed predicate is a vote about the vocabulary. Nothing above is hardcoded. Bumping the packages and redeploying is the entire update process. Contribution path - each section carries a propose invitation. Standard is read-only by definition, so proposing switches to Mainnet and routes to the right surface (builder, matrix, or registry) rather than dead-ending. - home links to github.com/0xIntuition/packages Verified: tsc clean, new files lint clean, headless render shows 37 types across all 7 categories and "133 predicates — 25 enshrined, 108 proposed", zero uncaught errors. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A proposal fills a hole in a known shape rather than inventing a sentence, and there are only two holes worth arguing about: Person — has type — ? object open: what can be said about a type Person — ? — Company predicate open: how two types connect Candidates compete for the same slot, which is what makes the outcome decidable — stake on them is comparable rather than scattered across unrelated claims. The relationship panel is real package data: it picks the most contested pair for the selected entity and shows the predicates genuinely competing for it today (Person → Company draws member of, employed by, affiliated with). The describe panel's objects are labelled illustrative, because a `has type` object is user-supplied by definition. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A proposal's stake total says how much conviction exists; it does not say whose. For a vocabulary decision that distinction matters — one whale and twelve independent builders are very different signals at the same TRUST amount — so this reads individual positions rather than the aggregate. - overlapping avatar stack answers "is anyone behind this?" without a click, with +N overflow past four - hover, focus or tap opens the full scrollable breakdown: who agrees (positions) and who disagrees (counter-triple positions), each with their stake and a running total - dissent is shown by ring colour in the stack rather than hidden, so a contested proposal is visible while scanning - accounts without an avatar get a colour derived from their address, so the same backer is recognisable across proposals before reading the label - redeemed positions (zero shares) are filtered out — they are no longer backing anything The stack sits outside the DialogClose button: opening the list to read who staked must not count as picking that predicate. Verified against real testnet data (14 slots, 18 proposals with backers); mainnet has no slot proposals yet, so the component renders its empty state there. All routes render headless with zero uncaught errors. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Three additions to the slot proposal dialog, alongside the backer stack. Portal link - opens the nested triple on the Intuition Portal, following the active network: portal.intuition.systems on mainnet, dev.portal on testnet - portal base URLs live in the network definition next to graphqlUrl, so the link can never point at the wrong chain - renders nothing in Standard mode — package data has no on-chain term - this app shows a proposal in ontology terms; the Portal is the canonical place for position history and share price. Link out rather than reimplement. Agree / disagree - thumbs deposit at the protocol's `minDeposit`. This is a signal, not a position size — the Portal link alongside is where real exposure belongs. - disagreeing deposits into the *counter-triple*, a distinct term with its own vault, whose id is read from the contract rather than assumed. Without a first-class dissent action a contested proposal is indistinguishable from an ignored one, which defeats settling vocabulary by stake. - uses multiVaultDeposit directly: the SDK's `deposit` wrapper drops the `value`, so it would deposit nothing - invalidates the backer query on success so the avatars update in place Propose your own - always visible, not only when the slot is empty — adding a predicate is the point of the dialog - prefills the builder with both entity types and an empty predicate, which is precisely the hole being proposed into - from Standard mode it switches to Mainnet first, since there is no builder to land in there, and says so on the button Vote and link handlers stop propagation: the row is a predicate picker, and staking or opening the Portal must not also select it. Verified: tsc and lint clean, all routes render headless with zero uncaught errors. The dialog body itself is portal-mounted on open, so its contents are not covered by the headless DOM check. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The problem
Claims created in Ontology could not join the shared graph.
The app minted predicate atoms by hashing a bare label:
The canonical registry hashes a JSON-LD
DefinedTermdocument:Different bytes → different atom ids. Every predicate atom this app wrote was invisible to
the rest of the ecosystem, and claims from other Intuition apps were invisible here.
The canonical derivation did not exist when Mission 01 (#8) was built. This is drift,
not a defect in that work.
What changed
Canonical identity
src/lib/intuition/canonical.tsis the single boundary to the alpha@0xintuition/*packages — an alpha bump has one blast radius.
DefinedTermbytes.rather than minting a duplicate. Free, synchronous, no wallet required.
silently staking against the wrong atom.
Vocabulary reconciliation
Directions were verified against each canonical predicate's description, not inferred
from its name —
founderreads organization→person, so this app'sfounder ofmaps tofounded, notfounder.The 7 flips implement mint-time canonicalisation locally.
⟨A, employs, B⟩and⟨B, employedBy, A⟩are one fact hashing to two triple ids and therefore two vaults,splitting stake. Upstream audit A1 calls this "economically unsound"; their fix (item A8)
has not shipped. The claim builder discloses the swap before you stake.
Predicate registry
Ranked by net stake, contestable via counter-triples. Mints the registry atom when absent —
it is unminted on both mainnet and testnet today.
Candidacy is deliberately a different edge from ratified membership, which upstream
records as
⟨registry, contain, X⟩. A proposal is not yet true, so it must not be writtenas though it were.
Read-only mode (bug fix)
WalletProviderpreviously rendered only a warning banner whenVITE_PRIVY_APP_IDwasunset — replacing the entire application. An unconfigured optional integration took down
everything that never needed it. This is what the preview deploy was showing.
The read stack now sits outside the wallet stack, and wallet hooks select an inert
implementation at module load from the build-time constant.
Bundle
Vendor splitting plus route-level lazy loading.
Docs
README.mdreplaced — it was still the Vite template..env.exampledocuments thatVITE_*are build-time only, including the Coolifybuild-variable requirement that caused the preview to ship an env-less bundle.
plan.mdrecords the full analysis and open questions for the Intuition team.Verification
tsc -bclean; new files lint clean (one pre-existing error remains inpredicate-select.tsx, untouched here)canonicalKeyreferences and 36 classification slugs validated against theinstalled packages
Not included, deliberately
Minting the 25 enshrined predicate atoms and the registry root. Whoever does that defines
the on-chain root of the shared vocabulary — a decision for the Intuition team, not a
contributor. See
plan.md§9 Q6.🤖 Generated with Claude Code