Foundational ontology layer for the Medicine Wheel Developer Suite. It defines the closed core node vocabulary, first-class relations, governed kinship edges, ceremony and narrative types, runtime validation, directional constants, semantic queries, and additive domain kinds that ride existing nodes rather than widening the ontology casually.
Version: 0.6.3
Package: @medicine-wheel/ontology-core
Document ID: rispec-ontology-core-v2
Parity Baseline: 2026-08-19
Section revised: Structural Tension Model, against 0.23.0 on 2026-10-20, against 0.24.0 the same day (AgentSessionRef.trace and rehydrate_with), and against 0.26.0 on 2026-10-25 (DelayedResolution.follow_up_prompt), from Miadi Chronicle Episode 297 (miadi-chronicle://297, design delayed-resolution-design-261019.md). The rest of this document keeps its 2026-08-19 baseline.
Users create relationally accountable software systems through one shared ontological foundation that:
Desired state: many Medicine Wheel packages can describe different worlds while still sharing one relational grammar.
Current pressure: every new domain naturally wants its own entity classes and bespoke schema, while an over-expanded core enum would make the ontology brittle and force every consumer to change.
Natural resolution: keep NodeType closed (six foundational kinds, widened only by ontology revision: circle 0.14.0, agent 0.17.0), then express domain-specific kinds through typed metadata.kind discriminators and specialized relation/facet contracts. Relations remain first-class and may additionally reference a governed kinship edge.
type DirectionName = 'east' | 'south' | 'west' | 'north';
Direction carries ceremonial teaching data including Ojibwe name, season, color, life stage, medicines, teachings, and practices.
Directional vocabularies exist at different altitudes, and they disagree: the life-cycle teachings place reflection in the west, the RSIS focus labels place it in the north (#113). DIRECTION_VOCABULARIES names each one, and none is the default:
| Vocabulary id | Source in the suite | West | North |
|---|---|---|---|
life-cycle-teachings |
DIRECTIONS |
Fall: Reflection, Truth, Introspection, Emotional processing | Winter: Wisdom, Completion, Ancestral knowledge, Generosity |
rsis-focus |
DIRECTION_INFO |
Implementation, creation, manifestation | Reflection, integration, wisdom |
ceremony-phases |
CEREMONY_PHASES |
integration | closure |
narrative-cadence |
narrative-engine directionToPhase |
integrating | closing |
decomposition |
prompt-decomposition | Validation | Action |
Every entry’s provenance is unattributed: no source, tradition or steward is recorded in this repository. Recording one is a knowledge holder’s decision (#113, #125).
Rule for consumers and agents: name the vocabulary you mean, directionMeaning('rsis-focus', 'north'), and do not write your own direction strings. A new vocabulary is added here, with its provenance, before any package uses it.
type NodeType =
| 'human'
| 'land'
| 'spirit'
| 'ancestor'
| 'future'
| 'knowledge'
| 'circle' // revision of 2026-09-18 (0.14.0)
| 'agent'; // revision of 2026-09-30 (0.17.0), jgwill/medicine-wheel#152
interface RelationalNode {
id: string;
name: string;
type: NodeType;
direction?: DirectionName;
metadata: Record<string, unknown>;
created_at: string;
updated_at: string;
}
The NodeType union is intentionally closed. New application domains normally ride these nodes through a typed metadata.kind discriminator rather than widening the union. It has been widened twice, each time by an explicit revision naming a being no existing type could hold without distorting it.
circle (2026-09-18, 0.14.0). A circle of people who hold ceremony together. It is a relation between people rather than one of them, and it holds membership edges and ceremonies.agent (2026-09-30, 0.17.0, jgwill/medicine-wheel#152). A being that holds a seat through software and speaks in ceremony, accountable to the people it serves (Mia, Miette, a companion). Before this revision an agent could hold a seat only as a human node, so the wheel recorded every seat-holder as a human, and nothing downstream could tell a person’s word from an agent’s. No existing type could hold an agent: knowledge would make a seat-holder an object, and spirit, ancestor and future name other relations. Guillaume, 2026-09-30: “just Guillaume on the wheel is human”. A seat-holder (metadata.kind: "person" with a role, @medicine-wheel/community-identity) is a human or an agent node. The role says what the seat may do, never what holds it. Ids minted before the revision keep their node:human: prefix, since ids are never rewritten.A simple RelationalEdge remains available for compatibility and lightweight graph operations. The richer Relation is the relational-first entity.
interface Relation {
id: string;
from_id: string;
to_id: string;
relationship_type: string;
kinship_type?: KinshipEdgeName;
strength: number;
direction?: DirectionName;
ceremony_context?: {
ceremony_id?: string;
ceremony_type?: CeremonyType;
ceremony_honored: boolean;
};
obligations: RelationalObligation[];
ocap: OcapFlags;
accountability: AccountabilityTracking;
context?: RelationContext;
metadata: Record<string, unknown>;
created_at: string;
updated_at: string;
}
relationship_type remains free-form for compatibility. kinship_type optionally points into the governed kinship registry so software can reason about symmetry, inverse direction, and default obligations without turning kinship into a class hierarchy.
interface RelationContext {
authorized_by?: string;
active_context?: string;
valid_when?: string;
forbidden_when?: string;
authorized_kin?: string[];
}
Context answers a different question from edge identity: where, when, and for whom does this relation hold? Protocol guards may use this information to permit, refuse, or escalate traversal.
Kinship edges are data in a registry, not subclasses. Named edges include vocabulary such as tends-to, speaks-with, holds-responsibility-for, and co-emerges-with, plus RSIS relation verbs.
The registry supports:
This lets the graph remain non-hierarchical while still providing semantic discipline.
interface OcapFlags {
ownership: string;
control: string;
access: 'community' | 'researchers' | 'public' | 'restricted';
possession: 'on-premise' | 'community-server' | 'cloud-sovereign' | 'cloud-shared';
compliant: boolean;
steward?: string;
consent_given?: boolean;
consent_scope?: string;
consent_state?: 'active' | 'withdrawn' | 'expired' | 'pending';
consent_last_affirmed?: string;
}
Consent is therefore not represented only as a historical boolean. The ontology can carry its current state and the last affirmation time while preserving earlier compatibility fields.
interface AccountabilityTracking {
respect: number;
reciprocity: number;
responsibility: number;
wilson_alignment: number;
relations_honored: string[];
last_ceremony_id?: string;
notes?: string;
}
Scores are bounded from 0 to 1 at validated boundaries. Query helpers can compute and aggregate Wilson alignment and surface accountability gaps.
type CeremonyType =
| 'smudging'
| 'talking_circle'
| 'spirit_feeding'
| 'opening'
| 'closing';
CeremonyLog records direction, participants, medicines, intentions, timestamp, optional research context, honored relations, and optional OCAP governance.
This ceremony vocabulary is distinct from the RSIS four-phase CeremonyPhase vocabulary (opening, council, integration, closure) and from the five ceremonial-diary phases owned by the persistence/domain layer. Similar words do not make these phase systems interchangeable.
A narrative beat now carries both story content and lineage/provenance.
interface NarrativeBeat {
id: string;
direction: DirectionName;
title: string;
description: string;
prose?: string;
ceremonies: string[];
learnings: string[];
timestamp: string;
act: number;
relations_honored: string[];
cycle_id?: string;
parent_beat_id?: string;
sub_beats?: string[];
origin?: BeatOrigin;
}
interface BeatOrigin {
producer: string;
source_ref?: string;
method?: string;
}
Beat telescoping can therefore preserve parent/sub-beat relations, and generated or witnessed beats can identify how they entered the wheel.
type TensionPhase = 'germination' | 'assimilation' | 'completion';
StructuralTensionChart holds desired outcome, current reality, action steps, phase, optional direction, and timestamps. Since 0.22.0 and 0.23.0 it also carries, all optional:
due_date: when the desired outcome is wanted (ISO), and due_date_history: each move of that date as { from, to, at }, oldest first;github_issue: { ref, owner, repo, number, url }, where ref is always the full owner/repo#number;status: active, paused, resolved or archived;parent_chart_id, parent_action_step_id, and level (a top-level chart is 0).An ActionStep carries an optional direction and due_date, and the fields the MCP’s structural tension tools write: status, progress, current_reality, sub_chart_id, completed_at, ceremonies_honored, relations_honored.
type ActionStepStatus = 'pending' | 'in_progress' | 'completed' | 'delayed';
delayed means someone strategically chose to delay the step’s resolution in favour of a longer-term choice. The step then holds the choice itself:
delayed_resolution: a DelayedResolution (chosen_at, chosen_by, resolve_by, reason, optional primary_choice, wake_on[], session, and since 0.26.0 follow_up_prompt; and when it ends, ended_at, ended_by, outcome of rehydrated, released or resolved, end_note);delayed_resolution_history: earlier records, oldest first, so a new delay never overwrites an old one;session: an AgentSessionRef (session_id, and optional agent, host, cwd, tmux, resume_command, inventory_record, and since 0.24.0 trace and rehydrate_with), the agent session to rehydrate when the delay ends. trace is the session’s LLMOps record and rehydrate_with the pinned prompt version that rehydrates it, as @miadi/llmops 0.1.0 prints them; AgentSessionRefSchema accepts each only as a string beginning with miadi-.follow_up_prompt (0.26.0): a FollowUpPrompt (address, optional text, composed_at, optional composed_by), the follow-up prompt composed when the delay was chosen. At the date a talking circle takes it up: what is rehydrated is this prompt, potentially with the session. address (e.g. miadi-prompt:ceremony/<name>@<v>) is stored as given; FollowUpPromptSchema accepts it only as a string beginning with miadi-. composed_at is the delay’s chosen_at, set by the tool.Zod schemas exist for each: ActionStepStatusSchema, AgentSessionRefSchema, FollowUpPromptSchema, DelayedResolutionSchema, and the widened ActionStepSchema and StructuralTensionChartSchema (the github_issue.ref is checked against owner/repo#number). The rules for choosing, listing and ending a delay belong to the MCP tools and are specified in delayed-resolution.spec.md.
type EpistemicSource = 'land' | 'dream' | 'code' | 'vision';
type AxiologicalPillar = 'ontology' | 'epistemology' | 'methodology' | 'axiology';
These types give other packages a shared vocabulary for the relational origin of knowledge and Wilson’s four research-paradigm elements (ontology, epistemology, methodology, axiology), which he draws as a circle, each informing the others (2008, p. 108). The type name AxiologicalPillar is kept for compatibility.
The ontology includes additive relation subtypes that preserve the first-class Relation contract:
LandRelation — land kinship, teaching, and stewardship;AncestorRelation — ancestor teaching, obligation, and lineage;FutureRelation — future obligation, gift, and teaching;CosmicRelation — cosmic/spirit kinship, teaching, and reciprocity;ProductionRelation — film/media relationships such as shot-of, rush-of, sequence-of, witnessed-by, directed-by, and sounds-in;AcademicRelation — academic relationships including researches-in, appointed-at, supervises-in, field-aligns-with, profiled-in, and corresponds-with.DeveloperRelation — repository relationships: forked-from, grew-into, provides, realizes, consumes, and field-aligns-with.Specialization adds domain meaning without replacing the relational obligations, OCAP data, accountability, and context inherited from Relation.
type ProductionEntityKind =
| 'shot'
| 'rush'
| 'sequence'
| 'scene'
| 'recording'
| 'collaborator'
| 'edit-brief';
Production entities ride knowledge/other existing nodes as appropriate; they do not become new NodeType values.
type InfraEntityKind = 'host' | 'tenant' | 'service';
Canonical binding:
land, no imposed direction;human, south;knowledge, west.The binding is a typed constant so a future change to the closed NodeType union cannot drift silently from infrastructure semantics.
type AcademicEntityKind =
| 'faculty'
| 'research-field'
| 'program'
| 'institution';
Canonical binding:
human, south;knowledge, east;knowledge, south;land, no imposed direction.Academic appointment state includes full-time, part-time, tenure-track, tenured, affiliated, emeritus, and the explicit epistemic value unverified.
A claim that has not earned a stronger status must remain unverified; absence of proof is not silently upgraded.
type DeveloperEntityKind = 'repository' | 'feature' | 'capability';
Canonical binding:
knowledge, no imposed direction (the ground its features stand on);knowledge, no direction yet (assigning one is an ontology revision with its own issue);knowledge, west (what executes and is offered).DeveloperRelation names forked-from, grew-into, provides, realizes, consumes and field-aligns-with. The first five are governed kinship edges (inverses forked-into, grew-from, provided-by, realized-by, consumed-by). Facets live in @medicine-wheel/capabilities and @medicine-wheel/developer-repository-mapping; see rispecs/developer-suite/repository-mapping/.
Zod schemas validate the boundary-critical ontology, including:
The specification does not claim that every TypeScript interface has a one-to-one Zod schema. Validation coverage is an explicit boundary contract, not a slogan.
Pure helpers operate over in-memory collections and do not own persistence.
They include:
Persistence belongs outside ontology-core.
The kinship graph is primary. RDF/OWL remains an optional serialization and interoperability adapter, not the ontology backbone.
Medicine Wheel domain namespaces include mw:, cer:, ocap:, rel:, ids:, and beat:. Standard semantic-web namespaces and IRI utilities are exposed through the RDF interop adapter, with compatibility exports retained at the package root.
Desired Outcome: Represent a host, tenant, and service without creating a parallel machine ontology.
Current Reality: Machine details need typed meaning, but the core node union is intentionally small.
Natural Progression: Bind infrastructure kinds onto existing land/human/knowledge nodes and let the infrastructure package hold machine facets keyed by node id.
Resolution: Infrastructure becomes queryable relationally without widening NodeType.
Desired Outcome: Traverse a relationship only where its authorization holds.
Current Reality: Edge identity alone cannot express who authorized it or where it is valid.
Natural Progression: Attach RelationContext; a protocol guard evaluates active/forbidden context and authorized kin.
Resolution: The same graph can preserve a relation without pretending it is universally traversable.
Desired Outcome: Represent a faculty relationship without turning an uncertain appointment into a fact.
Current Reality: A profile may establish identity and field alignment while appointment status remains unclear.
Natural Progression: Register the academic entity and relation with grounding; retain appointment as unverified until evidence supports a stronger value.
Resolution: The wheel can hold the relationship and its uncertainty at the same time.
NodeType union (eight values since the agent revision) remains the foundational node ontology unless an explicit ontology revision changes it.Relation preserves obligations, OCAP governance, accountability, and optional authorization context.This appendix keeps parity auditable while the normative sections remain re-implementable.
src/ontology-core/src/types.tssrc/ontology-core/src/schemas.tssrc/ontology-core/src/kinship.tssrc/ontology-core/src/constants.tssrc/ontology-core/src/queries.tssrc/ontology-core/src/rdf-interop.tssrc/ontology-core/package.json