For the complete documentation index, see llms.txt. This page is also available as Markdown.

The Shared Core

The shared domain layer that every Holons interface calls into

@holons/core is the heart of the Holons codebase. It owns every piece of domain logicβ€”scoring, tasks, council, DNA, federation, expenses, calendar, users, library, checklists, REA, settings, categories, commandsβ€”and exposes them as independently-callable modules. Every interface in Harvest (web, Telegram, CLI, AI, MCP) calls these modules. They do not duplicate the logic; they consume it.

This page is the architectural overview. For domain detail, jump to the individual pages.

What "shared core" means in practice

One source of truth for Holons domain logic, several UIs sharing it.

A user creating a task in Telegram and a Claude agent calling the MCP task_create tool reach the same function: createDefaultTask in packages/core/src/tasks/creation.ts. The Quest they produce lives in the same lens in HoloSphere. Scoring sees the same event when the Quest completes. Federation propagates the same data.

This is why "compute user score" means the same thing in every UI: there is only one implementation of it.

Domain catalog

Each domain lives at packages/core/src/<domain>/, exposes its public API via index.ts, and is reachable from any consumer with a subpath import.

Domain
What it owns
Page

tasks

Unified Quest model β€” tasks, proposals, events, offers, requests

council

Proposal lifecycle and consent-based voting

scoring

Value-equation evaluation; per-user / per-action / full-holon scores

rea

Resource-Event-Agent event ledger and factory

dna

Holon chromosomes (value / tool / practice) and DNA sequences

library

Shared community library β€” borrow / lend / deposit

federation

Cross-holon publishing via HoloSphere + Nostr

(no page yet)

holosphere

Identity-aware reads/writes against the substrate

expenses

Shared cost logging and splitting

(no page yet)

calendar

Events, recurring events, scheduling

(no page yet)

users

Multi-holon membership and appreciation tracking

(no page yet)

checklists

Recurring and role-based task lists

(no page yet)

shopping

Shared shopping lists

(no page yet)

settings

Per-holon configuration with hex-grid integration

(no page yet)

categories

Taxonomies for items and contributions

(no page yet)

commands

Shared command registry used by Text UI, AI UI, MCP Server

(see UI pages)

The "no page yet" entries are real, working domains; they just don't yet have dedicated docs. The MCP server exposes tools for every one of them.

Conventions

A small set of rules keeps the core stable as it grows.

Subpath imports β€” no central barrel

There is no import { everything } from '@holons/core' barrel that re-exports every domain. The subpath form is mandatory because:

  • It makes domain dependencies explicit in import lines.

  • Tree-shaking works without any bundler magic.

  • New domains land without touching a central re-export file.

  • Two domains can have a function of the same name without colliding.

Subpath exports are configured via a wildcard in packages/core/package.json:

Creating packages/core/src/<new-domain>/index.ts instantly makes @holons/core/<new-domain> importableβ€”no configuration change needed.

TypeScript everywhere

Core is TypeScript. New UIs are TypeScript. The Telegram bot is in a mixed JS+TS state (bootstrap and several modules migrated; the rest still JS, allowed via allowJs). Types are exported alongside functions:

UI-agnostic

Core never imports svelte, telegraf, or any framework. Only import type for shared interface shapes when truly necessary. The list of allowed runtime dependencies is intentionally tiny: holosphere, ical.js. That's it.

Pure vs. impure split

Every domain has the same internal structure:

  • Pure helpers β€” functions that take data and return data. No I/O, no side effects. Used by every UI for live rendering (live tallies, live scores, live previews).

  • Impure helpers β€” functions that read from or write to HoloSphere. Called when the action is committed.

This split is what lets the web dashboard show "if you complete this task, you and Laura each get 2 points" without round-tripping to storage: the same pure function runs in the browser.

One HoloSphere factory

There is exactly one place that instantiates HoloSphere: @holons/core/holosphere. Every UI calls into it for identity-aware writes (writeWithIdentity, canWriteToHolon). This keeps actor resolution, write permissions, and audit attribution consistent regardless of where a call originates.

Tests live next to the code

Every domain ships a vitest spec at packages/core/src/<domain>/<domain>.test.ts. Tests are not in a separate tests/ tree. This keeps each domain self-contained and makes it obvious which test exercises which file.

How a new domain lands

  1. Create packages/core/src/<domain>/{index.ts, types.ts, …}.

  2. Export the public surface from index.ts.

  3. Write a vitest spec: <domain>/<domain>.test.ts.

  4. If the domain has its own MCP tool wrappers, add packages/mcp-ui/src/tools/<domain>.ts and append the domain name to the DOMAINS array in packages/mcp-ui/src/tools/index.ts.

That's it. No central registration, no manifest, no per-UI plumbing. Every UI that imports from the new path automatically gets the new capability.

How a new UI lands

  1. mkdir packages/<my-ui>/src.

  2. Copy packages/text-ui/{package.json,tsconfig.json} as a starting point.

  3. Depend on @holons/core via "@holons/core": "workspace:*".

  4. pnpm install from the repo root.

  5. Implement the renderer / parser / input mode against @holons/core/commands so the new UI invokes the same actions as the others.

The shared command registry is the single integration point a new UI needs to touch. Every existing command becomes available to the new UI for free.

What this architecture buys

  • Consistency. Every interface produces the same data, scores it the same way, federates the same events.

  • Speed. A new feature is one PR, not five.

  • Independence. Each UI can iterate on its presentation without coordinating with the others.

  • Testability. Domain logic is exercised by vitest specs that run in milliseconds, with no UI launched.

  • AI-readiness. Because every operation is a CoreCommand with declared params, exposing it as an MCP tool or Claude tool is a one-line wrapper.

See also

Last updated

Was this helpful?