Skip to content

Latest commit

 

History

919 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

SPOKE

CI License Version Last commit Greptile: The War on Bugs

中文 · Concepts · Strategy · Contributing

Standardized Programmable Ontology Knowledge Engine — a protocol of JSON Schema wire contracts for narrative KnowledgeEntry data and ops. Independent products exchange consistency-check and context-assembly I/O through these shapes.

Includes:

  • Data-layer schemas: KnowledgeEntry, Relation, SourceAnchor, Finding, AssemblePacket, HostCapabilityManifest, Rule, TimelineEvent, MindState
  • Ops-layer schemas: upsert, extract→promote, relate, check, assemble; optional project / compute under l2-computable
  • Generated TypeScript (@42ch/spoke-schemas) and Rust (spoke-schemas, spoke-operations)
  • Pure lifecycle helpers plus adapter ports and injection orchestration (@42ch/spoke-operations / spoke-operations)
  • Opt-in Connect for signed cross-process interaction (@42ch/spoke-connect / spoke-connect, plus native bindings, including C and C++)
  • Protocol conformance fixtures and reference ToyWorldAdapter (fixtures/toy-world/)

Packages

Published consumer packages share one lockstep SemVer.

Package Registry Role
@42ch/spoke-schemas npm Generated TypeScript wire types — what crosses the wire
@42ch/spoke-operations npm Pure helpers, adapter ports, and orchestration over those types
@42ch/spoke-connect npm Opt-in connect client — identity, hello auth, session core, WebSocket transport
spoke-schemas crates.io Generated Rust wire types
spoke-operations crates.io Pure helpers, adapter ports, and orchestration — parity with @42ch/spoke-operations
spoke-connect crates.io Opt-in connect reference — libp2p transport, session core, uniffi binding surface

Product-specific payloads live under extensions.<namespace> (namespace keys are product-chosen ids). Cross-product functional dialects shared by narrative hosts (lore activation, knowledge packs, assemble placement) live under modules.* — an optional, capability-flagged bag on KnowledgeEntry, AssemblePacket, and TimelineEvent. See Data model.

Install pins and package roles: Package quick-start.

Install

TypeScript (npm)

pnpm add @42ch/spoke-schemas @42ch/spoke-operations
# Pin both to the same lockstep SemVer, e.g. @X.Y.Z

@42ch/spoke-schemas — import generated wire types:

import type {
  KnowledgeEntry,
  TimelineEvent,
  PromoteRequest,
  AssemblePacket,
  HostCapabilityManifest,
} from "@42ch/spoke-schemas";

@42ch/spoke-operations — implement capability-sliced ports on one adapter, then call orchestrate*:

import type { PromoteRequest, UpsertRequest } from "@42ch/spoke-schemas";
import {
  orchestrateUpsert,
  orchestratePromote,
  orchestrateCheck,
  orchestrateAssemble,
  type BaselineAdapter,
} from "@42ch/spoke-operations";

declare const adapter: BaselineAdapter; // product implements BaselineAdapter / FullAdapter
declare const upsertRequest: UpsertRequest;
declare const promoteRequest: PromoteRequest;

async function runBaseline() {
  const upserted = await orchestrateUpsert(adapter, upsertRequest);
  const promoted = await orchestratePromote(adapter, promoteRequest);
}

Optional capabilities use ComputableAdapter / ForkAdapter (or FullAdapter) with orchestrateProject, orchestrateCompute, orchestrateForkCheck, and orchestrateForkAssemble. Pure helpers (validatePromoteRequest, mergeExtensionMaps, buildAssemblePacket, …) remain available for focused gates.

Rust (crates.io)

cargo add spoke-schemas spoke-operations
# Pin both to the same lockstep SemVer, e.g. X.Y.Z
# Cargo.toml
[dependencies]
spoke-schemas = "X.Y.Z"
spoke-operations = "X.Y.Z"

spoke-schemas — wire types from the same JSON Schema SSOT:

use spoke_schemas::{KnowledgeEntry, HostCapabilityManifest, PromoteRequest, TimelineEvent};

spoke-operations — port traits plus orchestrate_* (also re-exports spoke_schemas):

use spoke_operations::{
    orchestrate_promote, orchestrate_upsert, BaselineAdapter,
};
use spoke_operations::spoke_schemas::{PromoteRequest, UpsertRequest};

async fn run_baseline(adapter: &impl BaselineAdapter, upsert: UpsertRequest, promote: PromoteRequest) {
    let _ = orchestrate_upsert(adapter, upsert).await;
    let _ = orchestrate_promote(adapter, promote).await;
}

Connect (optional)

Declare the spoke-connect capability when hosts need signed cross-process interaction (hello, session, invoke, auth envelopes).

TypeScript — npm client with WebSocket transport:

pnpm add @42ch/spoke-connect
# Pin to the same lockstep SemVer as schemas / operations

Rust — crates.io reference with libp2p transport and a uniffi binding surface for other host languages:

cargo add spoke-connect

C and C++ — git-based from the release tag: check out vX.Y.Z and take crates/spoke-connect/bindings/cpp/include/spoke_connect.h (hand-written C ABI header), crates/spoke-connect/bindings/cpp/include/spoke_connect.hpp (C++17 header-only convenience layer), and the committed carrier for your target — crates/spoke-connect/bindings/cpp/native/osx-arm64/libspoke_connect_capi.dylib for macOS arm64 or crates/spoke-connect/bindings/cpp/native/win-x64/spoke_connect_capi.dll for Windows x64. Both carrier libraries are Git LFS objects, so run git lfs install once and git lfs pull in an existing clone before linking.

git clone --branch vX.Y.Z --depth 1 https://github.com/42ch-dev/spoke.git

Connect is multi-language: a language-native TypeScript client on npm, a Rust reference on crates.io (libp2p + uniffi binding surface), and native bindings — registry-backed for C# (GitHub Packages NuGet), Kotlin (GitHub Packages Maven), and Python (PyPI), git-based for Swift, Go, and C/C++ (committed headers and platform carriers). Guides: TypeScript client, native bindings, and Connect from C and C++.

Version and pinning

Pin every consumer surface to the same SemVer (X.Y.Z) on npm and crates.io:

pnpm add @42ch/spoke-schemas@X.Y.Z @42ch/spoke-operations@X.Y.Z
cargo add spoke-schemas@X.Y.Z spoke-operations@X.Y.Z

Annotated git tags vX.Y.Z match that lockstep version. Release notes: CHANGELOG.md and GitHub Releases. Pinning guide: Version & release.

Quick start

Implement the port families for the capabilities you claim on one adapter type, then call orchestrate* from @42ch/spoke-operations (Rust: orchestrate_*).

import type { KnowledgeEntry, PromoteRequest } from "@42ch/spoke-schemas";
import {
  orchestratePromote,
  type BaselineAdapter,
} from "@42ch/spoke-operations";

// Product adapter implements BaselineAdapter.
// Reference FullAdapter: fixtures/toy-world ToyWorldAdapter
declare const adapter: BaselineAdapter;

const candidate: KnowledgeEntry = {
  schema_version: 1,
  entry_id: "kb_01",
  entry_type: "character",
  canonical_name: "Aria",
  status: "provisional",
  body: { summary: "A reluctant scout." },
  extensions: {},
};

const request: PromoteRequest = { candidate };

async function promote() {
  const result = await orchestratePromote(adapter, request);

  if (result.ok) {
    // Confirmed entry persisted through adapter OCC ports
  } else {
    console.error(result.code, result.message);
  }
}

Reference FullAdapter and the committed “Mira at Harbor” graph: fixtures/toy-world/. Step-by-step package path: Package quick-start.

Core concepts

Term In SPOKE
KnowledgeEntry Atomic narrative knowledge unit on the wire (entry_id, entry_type, status, body, extensions)
Relation Directed edge between KnowledgeEntries (or KnowledgeEntry ↔ source)
SourceAnchor Provenance pointer to a manuscript span or external locator
Finding Checker output for consistency, style, or analysis
Rule Declarative constraint input to check (L6)
TimelineEvent First-class temporal object on the when-axis (L5)
MindState First-class temporal mental-state record on the when-axis (L5, optional l5-mind)
AssemblePacket Wire context-assembly payload (slim entries for downstream LLM prompts)
HostCapabilityManifest Host roles, capabilities, and owned namespaces[] for in-process collaboration
Extensions Product-specific bag on every data object (extensions.<namespace>)
Modules Optional cross-product functional-dialect bag on KnowledgeEntry, AssemblePacket, and TimelineEvent (capability-flagged narrative-modules)
Adapter ports Injected read/write surfaces (KnowledgeEntryPort, HostManifestPort, …) that own persistence
Orchestration orchestrate* / orchestrate_* sequences that load scope, apply gates, and persist via ports

Vocabulary and positioning: CONCEPTS.md, STRATEGY.md, and Concepts.

Optional capabilities

Products that need programmable KnowledgeEntry body state may declare l2-computable:

  • body.state — static durable computable values
  • body.computable — dynamic Session-scoped projection
  • TimelineEvent.computable_logs — Moment-scale field-change presentation
  • project / compute ops — init/projection and apply/settle I/O envelopes

Products that need fork-scoped timeline queries may declare l5-fork. Products that exchange cross-product functional dialects (lore activation, knowledge packs, assemble placement / activation trace) may declare narrative-modules: an optional modules (ModuleMap) bag on KnowledgeEntry, AssemblePacket, and TimelineEvent carries these dialects, and adapters round-trip unknown module namespaces verbatim. Domain Profile handbooks define the inner shapes.

Products that interchange "who believes / wants / feels what at time t" may declare l5-mind: an optional MindState temporal record (snapshot / delta over the when-axis) and modules.observation on TimelineEvent.modules. The settled home of mental fields and belief labels is the holder KnowledgeEntry modules.mental / modules.belief (narrative-modules bag); MindState is strictly derivative, never a second authority. Mental-state engines stay product-owned. Opt-in, not spoke-baseline.

Products that need signed cross-process interaction may declare spoke-connect. Composed adapter aliases: BaselineAdapter, ComputableAdapter, ForkAdapter, FullAdapter.

Baseline integrators use core schemas; optional capabilities are opt-in. Detail: Concepts.

Operations

@42ch/spoke-operations / spoke-operations provide pure helpers and port-injected orchestration:

  • Baseline orchestrators: orchestrateUpsert, orchestratePromote, orchestrateRelate, orchestrateCheck, orchestrateAssemble
  • Optional orchestrators: orchestrateProject, orchestrateCompute, orchestrateForkCheck, orchestrateForkAssemble
  • Capability-sliced ports and composed aliases (BaselineAdapter … FullAdapter)
  • Extension and module map merge and round-trip preservation (mergeExtensionMaps / mergeModuleMaps, preserveExtensionMaps / preserveModuleMaps)
  • Finding / KnowledgeEntry status transition helpers
  • Promote acceptance, upsert/relate, and MindState wire-shape validators (validateMindState / validate_mind_state)
  • AssemblePacket builders from KnowledgeEntries
  • Unified SpokeResult / SpokeRejectCode on reject paths

Reference FullAdapter (baseline + l2-computable + l5-fork, including HostCapabilityManifest peers): fixtures/toy-world/ — TypeScript ToyWorldAdapter, Rust crate spoke-fixture-toy-world.

Detail: Orchestrate operations.

Further reading

Topic Guide
Protocol umbrella Protocol
Nine layers and capability levels Concepts
Data objects and open vocabulary Data model
MindState MindState reference
Ops request/response envelopes Ops wire
Operations library behavior Orchestrate operations
Core / modules / extensions Data model
Connect envelopes and bindings Connect
Domain Profiles Domain profiles
JSON Schema SSOT schemas/
Reference adapters and sample graph fixtures/toy-world/

Contributing

Local development, CI gates, and release procedure: CONTRIBUTING.md.

About

Standardized Programmable Ontology Knowledge Engine

Resources

Contributing

Stars

5 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages