Skip to content

Donor lineage

Donor lineage

SOMA is a fork-and-evolve project. Three open-source codebases provided the load-bearing patterns; one provided the harness template. All MIT-licensed. This page is the source of truth for who contributed what — useful when reviewing a port commit, when checking whether a behaviour is original-to-cortextOS or new-to-SOMA, or when deciding which donor to consult for a future feature.

At a glance

DonorAuthorRoleLicenseStatus in SOMA
cortextOSgrandameniumSubstrate (daemon, PTY, file bus, dashboard)MITForked; still upstream-trackable via git fetch upstream
gbrainGarry TanMinions queue + tool runtime + memory primitivesMITQueue + handlers ported in Phase 1; memory deferred to Phase 6
gstackGarry TanSubprocess pattern + worktree isolation + skill formatMITSubprocess pattern ported in Phase 1; worktrees deferred to Phase 2; skill format adopted Phase 5
graphifySafi ShamsiCodebase enrichment (tree-sitter AST + clustering)MITAdopted as enrichment pipeline; lands Phase 6
claudecode-harnessanothervibecoder-sCLAUDE.md templateMITAdopted verbatim as the SOMA CLAUDE.md (ADR-013)

Donor repos:


cortextOS — substrate (still active)

What we got from cortextOS and kept verbatim. Most of src/ outside src/minions/ is upstream-original.

SubsystemPathPurpose
Daemonsrc/daemon/Long-running supervisor process. Holds the agent registry, restarts dead PTYs, polls Telegram, runs cron, handles IPC over a Unix socket.
Agent PTYsrc/pty/agent-pty.tsSpawns claude CLI through node-pty. Reads OAuth from macOS Keychain (or CLAUDE_CODE_OAUTH_TOKEN for headless). Env-allowlisted to prevent secret leakage into the subprocess.
File bussrc/bus/Atomic-write filesystem-backed message bus. Carries events, heartbeats, telegram messages, and approvals between agents.
CLIsrc/cli/cortextos init / add-agent / start / status / dashboard / ecosystem / install / doctor. Adopted; soma jobs ... (added in Phase 1) follows the same Commander pattern.
Dashboard runtimedashboard/Next.js 16 + React 19 + Tailwind v4 + shadcn + @base-ui/react. Auth gate, sidebar, monochrome theme (post ADR-010).
PM2 ecosystem generatorsrc/cli/ecosystem.tsAuto-generates ecosystem.config.js from current org + agent set.
Templatestemplates/Per-agent markdown scaffolds (IDENTITY / SOUL / GOALS / SKILLS / GUARDRAILS). Used by soma add-agent.

What we changed in upstream code:

  • Display rebrand: cortextOSSOMA across user-visible prose, dashboard UI, docs, package metadata. (ADR-015 Tier A.)
  • State-dir rename: ~/.cortextos/~/.soma/ with backward-compat symlink. (ADR-015 Tier B.)
  • PM2 app names: cortextos-daemonsoma-daemon, etc. (ADR-015 Tier C.)
  • soma bin alias added alongside cortextos.

What we did NOT change (and why):

  • The daemon itself, agent PTY, and file bus internals — they work, they’re upstream-mergeable, and the queue layers on top rather than replacing them.
  • Org template schema — Phase 5 will revisit when we unify with gstack’s SKILL.md format.

gbrain — Minions queue + tool runtime (Phase 1 ported)

The big port. gbrain’s src/core/minions/ is what makes SOMA durable.

File in donorLOCStatusSOMA destination
minions/queue.ts1152Portedsrc/minions/queue.ts (~1380 LOC after attachment + protected-name + subagent-persistence helpers)
minions/worker.ts415Portedsrc/minions/worker.ts (~440 LOC after subagent ctx wiring)
minions/types.ts287Adaptedsrc/minions/types.ts (Postgres types → SQLite affinities; subagent persistence types added)
minions/backoff.ts34Verbatimsrc/minions/backoff.ts
minions/stagger.ts33Verbatimsrc/minions/stagger.ts
minions/quiet-hours.ts86Verbatimsrc/minions/quiet-hours.ts
minions/attachments.ts110Verbatimsrc/minions/attachments.ts
minions/protected-names.ts28Verbatimsrc/minions/protected-names.ts
minions/handlers/shell.ts311Portedsrc/minions/handlers/shell.ts (env-gate renamed; otherwise unchanged)
minions/handlers/subagent.ts710Ported + abstractedsrc/minions/handlers/engines/api/loop.ts + providers/anthropic.ts (Provider seam added; subagent_rate_leases table replaced by SOMA’s engine.acquireLock)
minions/tools/brain-allowlist.tsDeferredPhase 6 (brain-derived tool registry); SOMA Phase 1 ships 3 minimal queue-internal tools instead
core/cycle.tsDeferredPhase 6 (runCycle maintenance primitive)
core/fail-improve.tsDeferredPhase 7 (self-improvement retros)
core/memory.tsDeferredPhase 6 (markdown-first memory)

Adaptations from gbrain Postgres → SOMA SQLite

gbrain (Postgres)SOMA (SQLite)Why
BIGSERIAL PKINTEGER PRIMARY KEYSQLite rowid alias; same auto-increment semantics
TIMESTAMPTZINTEGER (Unix ms)SQLite has no native timezone-aware time; centralise on Unix-ms-as-number throughout
JSONBTEXT (JSON-encoded)App-side JSON.stringify on write, JSON.parse on read at the row-mapper boundary
now() SQLengine.now() JSCentralised clock so tests can inject
FOR UPDATE SKIP LOCKEDdropped — BEGIN IMMEDIATE serialises writersSingle-writer SOMA preserves correctness; Postgres engine (Phase 7) restores SKIP LOCKED
pg_advisory_xact_locksentinel-row pattern in minion_rate_leasesPostgres engine (Phase 7) restores pg_advisory_xact_lock
count(*) FILTER (WHERE cond)SUM(CASE WHEN cond THEN 1 ELSE 0 END)Same semantics, broader compatibility
to_jsonb($x::text) || stacktraceJS-side read-parse-push-write inside BEGIN IMMEDIATE txSQLite has no JSONB append operator
Anthropic-specific subagent rate-leases tablereused engine.acquireLock(...) over minion_rate_leasesAvoid two parallel rate-lease implementations (ADR-012)

Every deviation is annotated // SOMA: inline at the call site.


gstack — subprocess pattern (Phase 1 partial; worktrees Phase 2)

File in donorStatusSOMA destination
test/helpers/session-runner.ts (NDJSON spawn)Ported (adapted)src/minions/handlers/engines/subscription.tsspawn('claude', ['-p', '--output-format', 'stream-json', ...]), pure ingestNDJSONLine parser, kill ladder on both ctx.signal and ctx.shutdownSignal
lib/worktree.ts (WorktreeManager)Pending Phase 2Will live at src/minions/worktrees/ — per-job git worktree create/cleanup hooks around handler invoke
autoplan/SKILL.md (skill format)Pending Phase 5Will become the canonical SOMA skill format (gstack/gbrain converge on the same shape)
lib/gen-skill-docs.tsPending Phase 5Skill catalog generation
ETHOS.mdReference onlyInformed CLAUDE.md and ADR-011 wording

What gstack contributed conceptually:

  • The “claude as subprocess” pattern. Rather than embedding the model in your process, you spawn the CLI, hand it a prompt over stdin, parse NDJSON from stdout. Easier to kill, easier to compose, easier to switch to a different binary.
  • The kill ladder discipline (SIGTERM → grace period → SIGKILL) wired to both timeout-style and shutdown-style abort signals. Lifted into the shell handler and subscription engine.
  • The worktree-per-job invariant for parallel safety. Not yet shipped — Phase 2.

graphify — enrichment pipeline (Phase 6 pending)

What we’ll adopt from graphify when the brain layer lands:

CapabilitySource pathUse in SOMA
Tree-sitter AST extraction (25 languages)graphify/extract/Brain-enricher: index codebases into typed-edge graph
Leiden clustering on the graphgraphify/build/Cluster related concepts for retrieval
Multimodal ingest (PDF/audio/video transcription)graphify/ingest/Optional skill-driven ingestion paths
God-node analyticsgraphify/serve/Identify central concepts during summarisation

What we will NOT adopt:

  • Graphify as the memory backend itself. SOMA stores memory in markdown + the brain graph (typed edges over rows in minion_jobs.result + a future learnings table). Graphify enriches; gbrain-style storage is canonical.

claudecode-harness — CLAUDE.md template (adopted)

anothervibecoder-s/claudecode-harness provides the 10-section CLAUDE.md template structure (Platform & Mission / Ownership / Hard Limits / Local-First / Data Discipline / Env & Security / Hub-Spoke / Memory & Retros / DB Rules / ADR Habit). SOMA adopted it verbatim as CLAUDE.md and filled it in for our stack. See ADR-013 for context.


What Phase 1 effectively accomplished from this lineage

Reading the rows above as a delta:

  • From cortextOS: the daemon + PTY + file bus + dashboard remain intact and upstream-mergeable. We rebranded display surfaces and migrated state dirs but did not rewrite the runtime.
  • From gbrain: the entire Minions queue + worker + attachment + protected-names runtime + the full subagent loop with crash-resumable replay. The 710-LOC subagent handler was abstracted behind a Provider seam so OpenAI / OpenAI-compat / custom HTTP endpoints drop in without code changes.
  • From gstack: the claude -p NDJSON subprocess pattern with kill ladders. The WorktreeManager is staged for Phase 2.
  • From graphify: nothing yet — staged for Phase 6.
  • From claudecode-harness: the CLAUDE.md template that runs the dev loop in this very repo.

The mechanical sum: ~3000 LOC ported (gbrain queue + handlers + subagent), ~500 LOC adapted (gstack subprocess pattern), ~150 LOC of new abstraction (Provider seam + tool registry + ctx.subagent), ~430 LOC of UI (submit page + intent parser + API routes). All under MIT, all runnable today.

Next reading: architecture.md for how these pieces fit together at runtime.