npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@soulbatical/stella

v1.8.20

Published

Learning Agent for MCP servers - knowledge base, reflections, bug reports, chat engine

Readme

Stella - Learning Agent for MCP Servers

Ralph bouwt, Stella navigeert — Stella beheert kennis, reflectie, bugreports en permissions voor MCP servers.

Stella & Ralph: Two Repos, One System

Stella and Ralph Manager are separate repositories with a deliberate architectural relationship:

| | Stella (@soulbatical/stella) | Ralph Manager | |--|--------------------------|---------------| | Type | NPM library (TypeScript package) | Full-stack application | | Role | Middleware layer — gates, permissions, knowledge, reflections | Platform layer — dashboard, Telegram bot, autonomous loops, agents | | Imported by | All MCP servers (web-mcp, snelstart-mcp, agentrook, sparkbuddy-live, ralph-manager, etc.) | Nothing — it's the top-level platform | | Database | Uses Ralph Manager's Supabase (all stella_* tables) | Owns the Supabase project | | Approval flow | Requests approvals via Telegram | Hosts the Telegram bot that handles approvals |

Why separate repos?

  • Blast radius — A Stella change affects all consumers. Separate repos force conscious builds and testing per consumer.
  • Versioning — Each consumer decides when to update Stella. No accidental HEAD changes.
  • Focus — Stella = middleware concerns. Ralph Manager = platform/operational concerns.

The relationship is like Stripe SDK vs Stripe Dashboard: Stella is the library every project imports. Ralph Manager is the platform that hosts the infrastructure Stella depends on (database, approval flow, monitoring). Other consumers (agentrook, web-mcp, etc.) are pure consumers of the library — they use Stella but don't host its infrastructure.

Changelog

2026-03-17: session_task — verplichte taakbeschrijving bij identity confirmation

Probleem: Bij sessiestart bevestigde de LLM wie hij was (identity), maar niet wat hij ging doen. Hierdoor was er geen expliciete internalisering van de taak, en was achteraf niet zichtbaar welke taak een sessie had.

Oplossing: stella_confirm_identity en stella_session_init vereisen nu een session_task parameter (min 10 tekens) naast de bestaande summary.

Wijzigingen:

  1. Tool definition (reflections.ts) — session_task toegevoegd als required field in confirmIdentityDef
  2. Handler (reflections.ts) — handleConfirmIdentity valideert session_task (min 10 tekens), retourneert het in de response
  3. Session init (howtos.ts) — sessionInitDef schema en handler uitgebreid met session_task, blokkeert identity confirmation zonder
  4. Identity gate (reflections.ts) — gate prompt vraagt nu om identity + taak met voorbeeld
  5. Akkoord response (howtos.ts) — hint na akkoord toont session_task in het voorbeeld
  6. Stella hook (~/.claude/hooks/stella-hook.sh) — stap 2 vermeldt expliciet dat summary en session_task beide verplicht zijn

Voorbeeld:

stella_confirm_identity
  summary="I am the Practical Executor. I focus on efficiency..."
  session_task="Fix the 401 authentication error in the live widget"

2026-02-28: Predictors — time-windowed tool health monitoring + Telegram alerting

Probleem: Stille tool failures bleven weken ongedetecteerd. cost_summary retourneerde 6+ weken lang lege resultaten (200 OK, geen error) door een niet-bestaande kolom (project_name i.p.v. project_id join). Geen enkel monitoring systeem pikte dit op.

Oplossing: Outcome-gebaseerde tool health monitoring via de neural predictors:

  1. trainPredictors() — Analyseert howto_usage scores per tool met tijdsvensters (24h, 7d, 30d, all-time). Berekent per tool:

    • Success rate per venster (score >= 4 = success)
    • Trend: improving | declining | stable | insufficient_data
    • Lift boven/onder baseline (overall success rate)
    • Confidence gewogen op basis van lift × sample size
  2. Stale edge cleanup — Oude predicts edges worden verwijderd vóór elke train-run, zodat tools die terug naar baseline gaan niet als "failure" blijven staan.

  3. Periodieke training — Daemon traint elke 6 uur (+ 30s na startup). Geen handmatige actie nodig.

  4. Telegram alerting — Bij declining tools met >10% drop en >=3 recente samples stuurt de daemon een alert via POST /api/internal/notifications/agent naar ralph-manager → Telegram. 24h cooldown per tool voorkomt spam.

Voorbeeld alert:

⚠️ Tool Health Alert

📉 stella_plan_update declining
   All-time: 73% (n=26)
   7d: 50% (n=4)
   Drop: -23pp

Root cause cost_summary: scripts.ts en staff-reports.ts selecteerden project_name van ralph_sessions, maar die kolom bestaat niet — de tabel heeft project_id (UUID FK). Fix: .select("project:projects(name), ...") join via FK relatie.


2026-02-23: Gate blokkade-tekst herschreven voor betere AI compliance

Probleem: Na elke MCP server reload reset akkoordGiven naar false (in-memory boolean). Wanneer de AI daarna een tool aanroept (bijv. task_list), retourneert de gate een blokkade-response. De AI interpreteerde dit consequent als "de tool gaf lege resultaten" of "de tools zijn kapot" en ging debuggen/omheen werken in plaats van gewoon stella_howto_akkoord te callen. Dit patroon herhaalde zich sessie na sessie.

Root cause: De blokkade-tekst stond ONDERAAN een muur van basis-instructies, bugs en identity context (~100+ regels). De AI las die muur als "informatie" en miste de actie-verplichting. Bovendien was niet expliciet dat de tool NIETS retourneerde — de AI dacht dat het resultaat van de oorspronkelijke tool was.

Fix 1 — gates.ts blokkade-tekst herschreven:

  • Blokkade staat nu BOVENAAN (vóór basis-instructies, niet erna)
  • ⛔ TOOL CALL BLOCKED — "{toolName}" returned NOTHING — meteen duidelijk
  • "The result you see is NOT from {toolName}" — voorkomt misinterpretatie
  • "This happens after every MCP reload" — verklaart waarom het opnieuw moet
  • Drie expliciete anti-patronen: "DO NOT work around this", "DO NOT interpret as empty results", "DO NOT debug why tools seem broken"

Fix 2 — stella-gate.sh hook tekst uitgebreid:

  • Na de 3 onboarding-stappen staat nu een ⚠️ BELANGRIJK blok
  • Legt preventief uit dat "TOOL CALL BLOCKED" NIET betekent dat de tool kapot is
  • Instrueert om NOOIT te debuggen maar gewoon de 3 stappen te doen
  • Geldt bij ELKE sessiestart EN na elke MCP server reload

2026-02-21: Cross-scope howto editing fix (findHowtoForEdit)

Probleem: howto_upsert, howto_patch, howto_delete gebruikten strict scope matching (eq(scope_id)), terwijl howto_get, howto_rate, howto_publish cross-scope lookup gebruikten (applyScopeFilter + maybeSingle()). Dit veroorzaakte drie bugs:

  1. Patch/upsert konden publieke howto's niet vinden vanuit een project scope. Een publieke howto (scope_id: null) was onvindbaar vanuit bijv. sparkbuddy-live scope. howto_patch gaf "not found in current scope", howto_upsert maakte een scoped duplicate aan i.p.v. de bestaande te updaten.

  2. Duplicates veroorzaakten crashes in alle cross-scope handlers. Zodra er twee rijen bestonden met dezelfde slug (public + scoped), faalde maybeSingle() met "multiple rows returned" — waardoor howto_get, howto_rate en howto_publish ook kapot gingen.

  3. Delete/publish cyclus. howto_delete vond alleen de scoped versie (strict match), niet de publieke. Na delete probeerde de agent opnieuw upsert → nieuwe scoped duplicate → zelfde deadlock.

Fix: Nieuwe helper findHowtoForEdit(slug, columns) vervangt alle 7 lookup-patronen:

// Oud: 2 incompatibele patronen
// Pattern A (upsert/patch/delete): eq("scope_id", scopeId) → mist publieke howtos
// Pattern B (get/rate/publish): applyScopeFilter() + maybeSingle() → crasht bij duplicates

// Nieuw: 1 consistent patroon
const { data, error } = await findHowtoForEdit(slug);
// → Fetcht ALLE matches (own scope + public/null)
// → Disambigueert: prefereert eigen scope > public (null) > eerste match
// → Geen maybeSingle() meer → nooit crash bij duplicates

Aangepaste handlers: handleHowtoGet, handleHowtoUpsert, handleHowtoPatch, handleHowtoRate, handleHowtoPublish, handleHowtoDelete, processInlineReview.


2026-02-21: Duplicate howto prevention bij upsert

Probleem: Agents maakten regelmatig howto's aan die qua inhoud sterk overlappen met bestaande howto's. Voorbeeld: systematic-browser-crud-testing werd aangemaakt terwijl saasaway-client-test-script al hetzelfde onderwerp dekte. Dit leidde tot fragmentatie in de kennisbank.

Fix: stella_howto_upsert doet nu een embedding similarity check bij het aanmaken van een nieuwe howto (slug bestaat nog niet). Als er bestaande howto's zijn met >= 50% similarity, wordt de creatie geblokkeerd:

Similar howtos already exist:

  - "saasaway-client-test-script" (72% similar ★4, 2x) — Complete test procedure...

Options:
  1. Retry with force=true to create anyway
  2. Use stella_howto_patch slug="..." to add content to existing
  3. Use stella_howto_upsert slug="..." to fully rewrite existing
  • Alleen bij nieuwe slugs — updates van bestaande howto's worden niet gecheckt (dat is bewust herschrijven)
  • Bypass: force=true parameter om toch aan te maken na review van de matches
  • Geen extra stappen bij geen matches — check is transparant en voegt geen latentie toe als er geen duplicaten zijn

2026-02-21: Gate hook optimalisatie + howto kwaliteitsverbeteringen

Probleem 1: Gate hook injecteerde volledige instructies bij ELKE prompt. 130+ regels context werd bij elk user prompt herhaald — enorme token-verspilling.

Fix: State file per CLI sessie (~/.claude/state/stella-gate-$PPID). Eerste prompt krijgt volledige instructie, daarna niets. Stale state files worden automatisch opgeruimd (PID check). Reflection keys worden ook maar 1x geïnjecteerd (eerste keer dat ze beschikbaar zijn).

Probleem 2: Howto search te breed/plat. Agents zochten op het symptoom ("agentrook 401 authentication widget chat API") zonder werktype of context mee te geven.

Fix: Zoektermen moeten nu drie dimensies combineren:

  • ONDERWERP — wat is het? (bijv. "401", "RLS")
  • WERKTYPE — wat ga je doen? (bijv. "debug", "deploy", "refactor")
  • CONTEXT — welke stack/laag? (bijv. "express", "supabase", "doppler")

Probleem 3: Bij geen howto match ging agent blind bouwen. Geen kennis verzamelen, direct aan het werk.

Fix: Stap 1b instrueert nu expliciet om EERST kennis te verzamelen:

  • Optie A: eigen kennis (Grep/Read bestaande code)
  • Optie B: externe kennis (Context7, WebSearch, skills)
  • Optie C: combinatie (vaak het beste)

Probleem 4: Howto's werden te context-specifiek geschreven. "Fix 401 in agentrook widget" i.p.v. "Debug Express authentication errors".

Fix:

  • Gate hook bevat nu stap 1c met generiek-schrijven regels + bad/good voorbeelden
  • Upsert tool description bevat zelfde instructie als extra reminder
  • is_public default gewijzigd van false naar true — howto's zijn standaard publiek

Probleem 5: Agent begon inhoudelijk te antwoorden zonder onboarding. Bij "hoi, maak een advertentie" ging de agent vragen stellen zonder eerst howto's te laden.

Fix: Gate hook bevat nu een hard blok "EERSTE ACTIE — voordat je IETS anders doet":

  1. stella_howto_akkoord
  2. stella_confirm_identity
  3. stella_howto_search Pas NA stap 3 mag inhoudelijk geantwoord worden.

2026-02-21: Akkoord gate enforcement hersteld

Probleem: Op 19 feb werd de daemon geïntroduceerd met setAkkoordForPid in de hook. De hook signaleerde automatisch akkoord aan de daemon bij elk user prompt, waardoor de MCP akkoord gate altijd overgeslagen werd. Hierdoor was de hele learning workflow (howto search → plan → execute → summarize → rate) niet meer afgedwongen — Claude kon direct tools gebruiken zonder de Stella flow te doorlopen.

Oorzaak: De hook deed setAkkoordForPid → daemon zette akkoordGiven=true → MCP's checkten isAkkoordConfirmedShared()true → gate overgeslagen. Zonder akkoord gate werd er geen howto geladen, zonder howto geen plan gate, en zonder plan gate geen enforcement.

Fix:

  • stella-gate.sh: setAkkoordForPid vervangen door registerCliPid — registreert alleen de PID, geeft geen akkoord
  • daemon.ts: nieuw registerCliPid method toegevoegd (lightweight, geen akkoord)
  • stella-howto-hooks.sh: logging verplaatst naar ~/.claude/logs/stella/hooks-YYYY-MM-DD.log (dagelijkse rotatie, alleen matches gelogd)
  • Daemon stderr gaat nu naar ~/.claude/logs/stella/daemon-YYYY-MM-DD.log (was /dev/null)

Resultaat: De akkoord gate blokkeert weer hard. Claude moet stella_howto_akkoord callen om tools te unlocken, wat de volledige learning workflow afdwingt.


Documentation

| Document | Beschrijving | |----------|-------------| | docs/RUVECTOR.md | RuVector local store: architectuur, daemon protocol, neural graph, data layout, troubleshooting | | docs/PLAN-neural-graph.md | Neural Graph bouwplan (M1-M4): schema's, channel keys, co-activatie, policy engine. Status: gebouwd | | docs/SECURITY.md | Security model: HMAC-signed tokens, network isolation, threat model | | docs/PRD-stella-store-ruvector.md | Origineel ontwerp StellaStore + RuVector dual-write (historisch) |

Features

  • How-To Knowledge Base — Semantische zoekfunctie (pgvector embeddings), versioning, scoring. Basis how-to's laden alleen de eigen scope (~800 tokens i.p.v. ~5000)
  • Plans & Summaries — Gestructureerd plan vooraf, samenvatting achteraf met semantic search op eerdere samenvattingen
  • Stella Daemon — Centraal state-proces via Unix socket. Alle MCP servers delen onboarding, plan en howto state real-time
  • Hook-based Onboardingstella-gate.sh UserPromptSubmit hook levert instructies (alleen eerste prompt, daarna niets), start daemon en registreert CLI PID. Instrueert agent om onboarding (akkoord → identity → search) te doen als EERSTE ACTIE voordat inhoudelijk geantwoord wordt
  • Reflection System — Identiteits-gebaseerde reflecties met 10 lagen + empathy questions
  • Bug Reports — Gecentraliseerd in ralph-manager MCP (andere MCPs verwijzen hiernaar via gates)
  • Neural Graph — Adaptief lerend netwerk (Hebbian co-activatie, bundle detectie, policy engine). Zie docs/RUVECTOR.md voor operationele details en docs/PLAN-neural-graph.md voor het architectuurplan
  • Tool Health Monitoring — Outcome-gebaseerde predictors detecteren stille tool failures via tijdsvensters (24h/7d/30d). Daemon traint elke 6 uur en stuurt Telegram alerts bij declining trends. Detecteert problemen die traditionele health checks missen (tools die 200 OK retourneren maar slechte resultaten opleveren)
  • AI User Sentiment — PostToolUse hook analyseert het laatste user bericht met Claude Haiku voor sentiment (frustrated/urgent/positive/confused/correcting/neutral) + 7 indices. Fallback naar grep-heuristics als API onbeschikbaar
  • Gate Middleware — Enforceert learning workflows (akkoord, evaluatie, summary, plan, identiteit, reflectie, project context)
  • Project Context Gate — Write tools geblokkeerd tot project geselecteerd, deploy_config auto-update
  • Howto Hooks — How-to's kunnen Claude Code lifecycle hooks bevatten (PreToolUse, PostToolUse, Stop, etc.) die automatisch actief worden bij howto_get en verwijderd bij howto_rate
  • Inline Parameters_reflection, _review, _status voor efficiente roundtrips
  • Permission System — Universeel toegangsbeleid per tool (free, confirm, approve, block)
  • Agent Profiles — Per-sessie permission overrides via geheime codes

Architecture

┌──────────────────────────────────────────────────────────────┐
│                     Claude Code Session                       │
│                                                              │
│  ┌────────────────────────────────────────────────────────┐  │
│  │  UserPromptSubmit Hook (stella-gate.sh)                │  │
│  │  - Levert instructies (alleen 1e prompt, daarna niets) │  │
│  │  - Start daemon als die er niet is                     │  │
│  │  - Registreert CLI PID (geen auto-akkoord)            │  │
│  │  - Injecteert reflection keys (1x, zodra beschikbaar)  │  │
│  └────────────────────────────────────────────────────────┘  │
│  ┌────────────────────────────────────────────────────────┐  │
│  │  Pre/PostToolUse + Stop Hook (stella-howto-hooks.sh)   │  │
│  │  - Query daemon voor actieve howto hooks               │  │
│  │  - Voert command/prompt/agent hooks uit                │  │
│  │  - Output via JSON (systemMessage + additionalContext) │  │
│  └────────────────────────────────────────────────────────┘  │
│                                                              │
│  ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌──────────┐    │
│  │snelstart │  │agentrook │  │  stella-  │  │  ralph-  │    │
│  │   MCP    │  │   MCP    │  │  proxy    │  │ manager  │    │
│  └────┬─────┘  └────┬─────┘  └────┬─────┘  └────┬─────┘    │
│       │              │              │              │          │
│       └──────────────┼──────────────┼──────────────┘          │
│                      │              │                         │
│              ┌───────▼──────────────▼───────┐                │
│              │     Stella Daemon Process     │                │
│              │  /tmp/stella-daemon.sock      │                │
│              │                               │                │
│              │  Shared State (in-memory):    │                │
│              │  - akkoordGiven               │                │
│              │  - identityConfirmed          │                │
│              │  - activePlan                 │                │
│              │  - openSessions              │                │
│              │  - activeHooks               │                │
│              │  - stepCounter               │                │
│              │  - reflectionKeys            │                │
│              │  - neuralPolicy (STATE_OUT)   │                │
│              │                               │                │
│              │  RuVectorStore (embedded):     │                │
│              │  - EmbeddingCache (cosine)    │                │
│              │  - MetadataStore (JSON/disk)  │                │
│              │  - Neural Graph (nodes/edges) │                │
│              │  - PolicyEngine (Thompson)    │                │
│              │  - Decay Runner (10 min)      │                │
│              │  - Predictor Trainer (6 hr)   │                │
│              │    → Telegram alerts           │                │
│              └───────────────────────────────┘                │
│                                                              │
│              ┌───────────────────────────────┐                │
│              │         Supabase              │                │
│              │  howtos, plans, reflections,  │                │
│              │  permissions, episodes        │                │
│              └───────────────────────────────┘                │
└──────────────────────────────────────────────────────────────┘

Installation

Optie 1: npm install from local path (aanbevolen)

npm install ../stella

Optie 2: npm link (lokaal development)

# In stella project:
cd ~/projecten/stella
npm run build
npm link

# In je MCP project:
cd ~/projecten/web-mcp
npm link @soulbatical/stella

Optie 3: npm install from git

npm install git+https://github.com/ralph-group/stella.git

Environment Variables

Voeg toe aan je .env:

# Ralph Manager Supabase (gedeeld tussen alle projecten)
LEARNING_SUPABASE_URL=https://xxx.supabase.co
LEARNING_SUPABASE_SERVICE_KEY=eyJ...

# Project scope (uniek per project)
LEARNING_SCOPE_ID=web-mcp          # of 'sparkbuddy', 'snelstart', etc.

# OpenAI voor semantic search
OPENAI_API_KEY=sk-...

Quick Start

Met withGates() (aanbevolen)

import {
  withGates,
  initDaemonClient,
  configurePermissions,
  configureStellaClient,
  decorateToolDefinitions,
} from '@soulbatical/stella';

// Bij startup:
configureStellaClient(supabase, 'web-mcp');
configurePermissions({
  scopeId: 'web-mcp',
  approvalService: 'web-mcp',
  approvalUrl: 'http://localhost:3005',
});

// Initialize daemon connection (auto-starts daemon if not running)
await initDaemonClient('web-mcp');

// ListTools handler:
server.setRequestHandler(ListToolsRequestSchema, async () => {
  return { tools: await decorateToolDefinitions(myToolDefs) };
});

// CallTool handler:
server.setRequestHandler(CallToolRequestSchema, async (request) => {
  const { name, arguments: args } = request.params;
  return withGates(name, args, async () => {
    return myHandler(args);
  });
});

withGates() handelt automatisch af:

  1. Inline parameter processing (_reflection, _review, _status)
  2. Gate checks (akkoord, evaluatie, summary, plan, identiteit, reflectie, project context)
  3. Permission checks (free/confirm/approve/block)
  4. Tool execution met error handling
  5. Auto-update deploy_config (na succesvolle write tools)
  6. Post-enrichment (tips, reflection prompts, batch suggestions)

decorateToolDefinitions() doet twee dingen:

  1. Permission prefixes[CONFIRM], [APPROVE], [BLOCKED] in tool descriptions
  2. Inline parameter schemas — Injecteert _reflection in de inputSchema.properties van elke tool, zodat LLMs het als formele parameter zien en inline gebruiken

Handmatig (voor custom flows)

import {
  checkGates,
  processInlineParams,
  getPostEnrichment,
  checkPermission,
  requestApproval,
} from '@soulbatical/stella';

const inlineResult = await processInlineParams(name, args);
if (inlineResult) return inlineResult;

const gate = await checkGates(name);
if (gate) return gate;

// Permission check
const perm = await checkPermission(name, args);
if (perm.blocked) return errorResponse('Tool blocked');
if (perm.level === 'approve') {
  const approval = await requestApproval(name, args);
  if (!approval.approved) return errorResponse(approval.message);
}

const result = await handler(args);

const { additions, blocked } = await getPostEnrichment(name, result);
if (blocked) return blocked;
result.content.push(...additions);

Hook Setup (stella-gate.sh)

De hook is de eerste stap in elke sessie. Hij draait als UserPromptSubmit hook in Claude Code bij elk user prompt.

Installatie

# Symlink (bron = stella repo, actief via Claude Code hooks)
ln -s ~/projecten/stella/hooks/stella-gate.sh ~/.claude/hooks/stella-gate.sh

Wat doet de hook?

  1. Levert instructies (alleen eerste prompt) — stack, naming, env, ports, onboarding flow, howto-schrijfregels. Gebruikt state file (~/.claude/state/stella-gate-$PPID) om herhaling te voorkomen. Stale state files worden automatisch opgeruimd (PID check).
  2. Start daemon als die er niet is (stderr → ~/.claude/logs/stella/daemon-YYYY-MM-DD.log)
  3. Registreert CLI PID via registerCliPid — daemon kent de sessie maar geeft geen akkoord (akkoord moet via MCP gate stella_howto_akkoord)
  4. Injecteert reflection keys (1x) — query getReflectionKeysForPid, inject bij eerste keer dat ze beschikbaar zijn (na MCP loaded identity), daarna nooit meer

Howto Hooks Dispatcher (stella-howto-hooks.sh)

How-to's kunnen Claude Code lifecycle hooks bevatten. Wanneer een howto geladen wordt via stella_howto_get, worden de hooks opgeslagen in de daemon. De dispatcher (stella-howto-hooks.sh) draait bij elk PreToolUse, PostToolUse en Stop event.

Installatie

ln -s ~/projecten/stella/hooks/stella-howto-hooks.sh ~/.claude/hooks/stella-howto-hooks.sh

Registreer in ~/.claude/settings.json onder hooks:

"PreToolUse": [{ "hooks": [{ "type": "command", "command": "~/.claude/hooks/stella-howto-hooks.sh", "timeout": 30 }] }],
"PostToolUse": [{ "hooks": [{ "type": "command", "command": "~/.claude/hooks/stella-howto-hooks.sh", "timeout": 30 }] }],
"Stop": [{ "hooks": [{ "type": "command", "command": "~/.claude/hooks/stella-howto-hooks.sh", "timeout": 30 }] }]

Flow

howto_get → hooks uit DB → daemon.setActiveHooks(slug, hooks, cwd)
                                     ↓
Claude Code event (PreToolUse/PostToolUse/Stop)
  → stella-howto-hooks.sh
  → leest hook_event_name + cwd uit stdin JSON
  → skip als stop_hook_active=true (voorkomt infinite loops)
  → query daemon: getActiveHooksForEvent(cliPid, event, cwd)
  → daemon retourneert hooks met cwd per hook
  → script filtert: skip hook als hook.cwd niet matcht met sessie cwd
  → voert command hooks uit, stuurt prompt/agent hooks als context
  → JSON output: { systemMessage, additionalContext }
                                     ↓
howto_rate → daemon.removeActiveHooks(slug) → hooks weg

cwd Scoping

Hooks worden alleen uitgevoerd in de juiste project-sessie. Dit voorkomt dat hooks geladen in ~/projecten/stella vuren in een sessie die in ~/projecten/web-mcp werkt.

Hoe het werkt:

  1. Bij setActiveHooks slaat de daemon de cwd op per hook set
  2. Bij getActiveHooksForEvent stuurt de daemon de cwd mee per hook
  3. Het hook script vergelijkt de cwd uit Claude Code stdin met hook.cwd
  4. Fallback: als geen explicit cwd, parse het uit cd <pad> in het command

Stop hook specifiek: stop_hook_active wordt gecheckt om infinite loops te voorkomen — als Claude al in een stop-hook continuation zit, wordt de hook overgeslagen.

Hook types in howto's

{
  "hooks": {
    "PostToolUse": [{
      "type": "command",
      "command": "npx tsc --noEmit",
      "description": "TypeScript check na elke edit",
      "matcher": "Edit|Write"
    }],
    "Stop": [{
      "type": "prompt",
      "command": "Check of alle bestanden opgeslagen zijn",
      "description": "Save reminder"
    }]
  }
}

| Type | Werking | |------|---------| | command | Shell command uitvoeren, stdout als context | | prompt | Tekst als context naar het model sturen | | agent | Subagent instructie als context sturen |

Output

Het script output JSON zodat Claude Code het correct verwerkt:

  • systemMessage — zichtbaar voor de gebruiker in de CLI
  • additionalContext — zichtbaar voor het model

PID Resolution

MCP servers draaien via doppler run -- node, dus hun process.ppid = doppler PID, niet Claude CLI PID. Dit creëert twee gescheiden PID chains:

Hook: $PPID = Claude CLI PID (40973) → registerCliPid(40973) → state aangemaakt (geen akkoord)

MCP server: process.ppid = doppler PID (41105) → register(41105) →
  getOrCreateState(41105) → akkoordGiven=false → gate blokkeert

LLM callt stella_howto_akkoord → setAkkoordGiven() → broadcast naar alle clients

Akkoord: gaat via stella_howto_akkoord tool call (hard enforcement). De setAkkoordForPid method bestaat nog voor backward compat maar wordt niet meer door de hook gecalld.

Active Hooks: ancestor walk faalt als doppler reparents naar ppid=1. Oplossing: getActiveHooksForEvent scant alle cliStates globaal en filtert op cwd (project directory) in plaats van PID matching. Het hook script vergelijkt de CLI sessie cwd met de hook's project cwd.


Stella Daemon (Cross-MCP Shared State)

In een Claude Code sessie draaien meerdere MCP servers tegelijk. Zonder sharing zou elke MCP de volledige onboarding afdwingen en plan/howto state niet kunnen zien — dit veroorzaakte deadlocks (bijv. howto_get op adgency + plan_create op stella-proxy → plan gate permanent geblokkeerd).

Architectuur

De daemon is een detached Node.js process dat communiceert via JSON-RPC 2.0 over Unix domain socket (/tmp/stella-daemon.sock).

MCP Server A ──┐
MCP Server B ──┼──► Unix Socket ──► Stella Daemon (in-memory state)
MCP Server C ──┘         │
                         └──► Broadcast state changes to all clients

Drie componenten:

| Component | Bestand | Rol | |-----------|---------|-----| | daemon.ts | Server process | Houdt state in geheugen, handelt RPC requests af, broadcast wijzigingen | | daemon-client.ts | Client library | Verbindt met daemon, local cache + broadcast sync | | daemon-spawn.ts | Auto-start | Controleert of daemon draait, start indien nodig, cleanup stale PID/socket |

Hoe het werkt

  1. Eerste MCP server startinitDaemonClient(scopeId)ensureDaemon() fork't daemon process
  2. Client registreertregister RPC → ontvangt huidige state snapshot → local cache gesync
  3. State wijzigt → client stuurt RPC (bijv. setAkkoordGiven) → daemon update + broadcast naar alle clients
  4. BroadcastsstateChanged notifications updaten de local cache van elke client real-time
  5. State lezen → local cache (geen RPC nodig, instant)

Gedeelde State

| State | Daemon method | Beschrijving | |-------|--------------|-------------| | Akkoord | setAkkoordGiven / isAkkoordGiven | Basis instructies bevestigd | | CLI PID (hook) | registerCliPid / getReflectionKeysForPid | Hook registreert PID (geen akkoord) + query keys per CLI PID | | Identity | setIdentityConfirmed / isIdentityConfirmed | Identiteit bevestigd (impliceert akkoord) | | Plan | setActivePlan / getActivePlan | Actief plan met stappen | | Summary | setSummaryRequired / isSummaryRequired | Summary vereist na plan completion | | Howto Sessions | setHowtoSession / removeHowtoSession | Open howto sessies | | Active Hooks | setActiveHooks / removeActiveHooks / getActiveHooksForEvent | Howto lifecycle hooks (per event, global scan + cwd filter) | | Step Counter | incrementStepCounter / getStepCounter | Totaal tool calls (voor evaluatie gate) | | Reflection | setPendingReflection | Reflectie vereist | | Reflection Keys | setReflectionKeys / getReflectionKeysForPid | Reflection question keys (pushed door MCP, queried door hook) | | Bug/Howto Actions | setPendingBugAction / setPendingHowtoAction | Actie gates | | Basis Loaded | setBasisLoaded / isBasisLoaded | Basis howtos geladen |

Cross-MCP Gate Resolution

| Gate | Logica | |------|--------| | Akkoord | localState.akkoordGiven (gesync via daemon) → 1x akkoord geldt voor alle MCP's | | Identity | localState.identityConfirmed → 1x identity geldt voor alle MCP's | | Plan | localState.activePlan → plan aangemaakt in 1 MCP is zichtbaar in alle MCP's | | Summary | localState.summaryRequired → blokkeert howto_rate in alle MCP's | | Howto sessions | localState.openSessions → sessie geopend in 1 MCP is zichtbaar overal |

Flow bij meerdere MCP servers

User prompt (1e prompt):
  → stella-gate.sh hook draait
  → Levert volledige instructies (onboarding, stack, naming, howto-schrijfregels)
  → Start daemon als die er niet is (stderr → ~/.claude/logs/stella/)
  → registerCliPid(cliPid) → daemon kent de sessie (GEEN akkoord)
  → Maakt state file aan (~/.claude/state/stella-gate-$PPID)

User prompt (2e+):
  → stella-gate.sh hook draait
  → State file bestaat → geen instructies output
  → registerCliPid(cliPid)
  → Reflection keys: inject 1x zodra beschikbaar, daarna nooit meer

1e MCP tool call (bijv. op snelstart-mcp):
  → initDaemonClient() → daemon al gestart door hook
  → register(dopplerPid) → getOrCreateState() → akkoordGiven=false
  → checkGates() → 🔒 TOOLS BLOCKED → LLM moet stella_howto_akkoord callen
  → stella_howto_akkoord → setAkkoordGiven → broadcast naar alle clients

2e MCP server (bijv. agentrook-mcp):
  → initDaemonClient() → verbindt met bestaande daemon
  → register → ontvangt state met akkoordGiven=true (via broadcast)
  → howto_get → opent sessie → plan gate activeert

3e MCP server (bijv. stella-proxy):
  → plan_create → broadcast naar alle clients
  → agentrook ziet plan via local cache → plan gate passeert (geen deadlock)

Technische details

  • Protocol: JSON-RPC 2.0, newline-delimited, over Unix domain socket
  • Socket: /tmp/stella-daemon.sock
  • PID file: /tmp/stella-daemon.pid
  • Auto-start: Eerste initDaemonClient() call start daemon via fork() (detached)
  • Predictor training: Elke 6 uur (+ 30s na startup) traint trainPredictors(). Bij declining tools (>10% drop, >=3 samples in 7d) stuurt alert via ralph-manager Telegram endpoint. 24h cooldown per tool
  • Auto-exit: 5 minuten zonder connecties → daemon stopt zichzelf
  • Stale cleanup: daemon-spawn.ts valideert PID file tegen levend process, ruimt stale socket/pid op
  • Retry: Exponential backoff (50ms, 100ms, 200ms, 400ms) bij wachten op daemon startup
  • RPC timeout: 5 seconden per call
  • Fallback: Als daemon onbereikbaar → local-only mode (zelfde gedrag als voor daemon bestond)
  • Backward compat: getSharedSession() retourneert session-achtig object voor code die de oude file-based API gebruikte

Logging

Alle lokale Stella logs staan in ~/.claude/logs/stella/ (dagelijkse rotatie):

| Bestand | Wie schrijft | Wat | |---------|-------------|-----| | daemon-YYYY-MM-DD.log | stella-gate.sh (daemon stderr) | Registraties, akkoord events, hook changes, errors | | hooks-YYYY-MM-DD.log | stella-howto-hooks.sh | Alleen gefirde hooks (lege results worden niet gelogd) |

MCP tool call data (episodes, token usage, plans, summaries) gaat naar Supabase.

Diagnostics

# Check of daemon draait
ls -la /tmp/stella-daemon.sock
cat /tmp/stella-daemon.pid
ps aux | grep stella.*daemon

# Ping daemon
echo '{"jsonrpc":"2.0","method":"ping","params":{},"id":1}' | nc -U /tmp/stella-daemon.sock

# Get full state (check akkoordGiven, activePlan, etc.)
echo '{"jsonrpc":"2.0","method":"getState","params":{},"id":1}' | nc -U /tmp/stella-daemon.sock

# Get reflection keys for a CLI PID
printf '{"jsonrpc":"2.0","id":1,"method":"getReflectionKeysForPid","params":{"cliPid":"%s"}}\n' $PPID \
  | nc -U /tmp/stella-daemon.sock -w1

# Bekijk daemon logs van vandaag
cat ~/.claude/logs/stella/daemon-$(date +%Y-%m-%d).log

# Bekijk hook fires van vandaag
cat ~/.claude/logs/stella/hooks-$(date +%Y-%m-%d).log

# Kill daemon (wordt automatisch herstart door hook of MCP call)
kill $(cat /tmp/stella-daemon.pid)

Permission System

Levels

| Level | Gedrag | Menselijke actie | |-------|--------|------------------| | free | Direct uitvoeren | Geen | | confirm | LLM moet bevestigen (confirmed=true) | Geen | | approve | Telegram goedkeuring vereist | Klik op knop | | block | Tool geblokkeerd | - |

Resolutie-volgorde

1. Agent profiel override (als profiel actief + tool match)
2. Supabase stella_tool_permissions tabel
3. Local overrides (hardcoded fallback via configurePermissions)
4. Default: 'free'

Tool Description Decoratie

Bij ListTools worden descriptions automatisch verrijkt:

[CONFIRM] Boek inkoopfactuur...
[APPROVE — Telegram] DNS record toevoegen...
[BLOCKED] Gevaarlijke actie...

Agent Profiles

Een agent profiel is een set permission overrides gekoppeld aan een geheime code:

// Agent stuurt code mee bij akkoord of via unlockAgentProfile()
const result = await unlockAgentProfile('mijn-geheime-code');
// → Laadt profiel permissions voor de rest van de sessie

Tijdelijke Permissions

Permissions kunnen tijdelijk ingesteld worden met een expires_at timestamp. Na afloop valt de tool automatisch terug naar het volgende niveau in de resolutie-volgorde.

-- Via Ralph Manager MCP:
permission_set scope_id="agentrook" tool_name="*" level="free" duration_hours=4
-- → Na 4 uur verloopt de override en gelden weer de defaults

Expired rows worden genegeerd bij resolutie — geen cleanup nodig.

Database Tabellen

-- Standaard permission levels per scope
stella_tool_permissions (scope_id, tool_name, level, confirm_message, approve_label, expires_at)
-- expires_at: NULL = permanent, timestamptz = auto-expire

-- Agent profielen
stella_agent_profiles (name, secret_code, scope_id, is_active)

-- Per-profiel permission overrides
stella_agent_profile_permissions (profile_id, scope_id, tool_name, level)

-- Audit trail
stella_permission_audit (scope_id, tool_name, level, agent_profile, result, ...)

Migratie: ralph-manager/supabase/migrations/20260207_stella_permissions.sql


Inline Parameters

LLMs kunnen reflections, reviews en status updates meesturen bij reguliere tool calls. Dit bespaart 2 roundtrips per reflectie (geen apart reflect → tool opnieuw).

Belangrijk: _reflection wordt automatisch geïnjecteerd in de inputSchema van elke tool via decorateToolDefinitions(). LLMs zien het als formele parameter en gebruiken het inline — geen aparte reflect-calls meer nodig.

// Reflectie meesturen (AANBEVOLEN — bespaart 2 roundtrips):
tool_name(..., _reflection: {
  answers: [{key: "safety", score: 4, text: "..."}, ...],
  last_step: "wat ik net deed",
  next_step: "wat ik ga doen"
})

// Review meesturen:
tool_name(..., _review: {
  slug: "mijn-howto",
  score: 4,
  outcome: "success",
  review: "werkte goed"
})

// Status meesturen:
tool_name(..., _status: {
  slug: "mijn-howto",
  status: "in_progress",
  remaining_steps: 5
})

Reflection Prompt Optimalisatie

De reflectie-prompt wordt slim gecomprimeerd:

| Moment | Wat wordt getoond | ~Tokens | |--------|-------------------|---------| | Step 1 (eerste keer) | Volledige vragen met keys en scores | ~600 | | Step 2+ (daarna) | 🪞 Analytische Denker \| tool_name \| Step N | ~15 | | Hook (2e+ prompt) | Required keys lijst (via daemon query) | ~30 |

De identity context toont nu expliciete key names bij elke vraag:

Required keys for _reflection.answers: efficiency, reusable, result, blockers, ...
  1. [key="efficiency"] Was this the fastest route?
  2. [key="reusable"] Can I reuse this?

Dit voorkomt dat de AI de verkeerde keys raadt (bijv. "reusability" i.p.v. "reusable").


Tools

How-To Knowledge

| Tool | Description | |------|-------------| | stella_howto_search | Semantic search in knowledge base | | stella_howto_get | Get specific how-to by slug | | stella_howto_upsert | Create new how-to or full rewrite. Duplicate check blocks creation if similar howtos exist (bypass with force=true) | | stella_howto_patch | Incremental edits: old_text→new_text patches + optional metadata. Saves tokens on large how-tos | | stella_howto_rate | Rate een how-to na gebruik | | stella_howto_stats | Usage en score statistieken | | stella_howto_publish | Toggle public/private | | stella_howto_akkoord | Bevestig basis instructies gelezen | | stella_howto_status | Rapporteer voortgang op actieve sessie | | stella_howto_delete | Permanent verwijderen van howto + versies + usage history |

Reflection System

| Tool | Description | |------|-------------| | stella_reflect | Submit een reflectie (met empathy questions) | | stella_confirm_identity | Bevestig identiteit bij sessie start | | stella_set_identity | Wissel actieve identiteit mid-sessie |

Bug Reports (centralized in ralph-manager)

Bug tools are only mapped in ralph-manager MCP. Other MCPs don't expose these tools — instead, the bug action gate redirects to ralph-manager and offers howto_status dismiss_bug=true to unblock.

| Tool | Description | |------|-------------| | stella_report_bug | Meld een bug of feature request | | stella_list_bugs | Lijst bugs met filters | | stella_get_bug | Bug details ophalen | | stella_update_bug | Bug status updaten |

Plans & Summaries

| Tool | Description | |------|-------------| | stella_plan_create | Maak een plan met stappen, gelinkt aan howto sessie(s) | | stella_plan_update | Update stap status (in_progress/completed/skipped) | | stella_plan_get | Haal actief plan op met voortgang | | stella_summarize | Dien samenvatting in na plan completion (met embedding voor semantic search) |

Project Context

| Tool | Description | |------|-------------| | stella_set_project_context | Selecteer project, laadt deploy_config, ontgrendelt write tools |

Batch

| Tool | Description | |------|-------------| | stella_batch_tools | Meerdere tools in 1 call (telt als 1 reflectie-stap) |


Gate Flow

Session Start
  1. Akkoord gate: BLOKKEERT tot stella_howto_akkoord wordt aangeroepen
     Hook levert instructies maar geeft GEEN auto-akkoord — dit forceert
     de volledige learning workflow (search → plan → execute → summarize → rate)
  2. Identity gate: auto-loaded via daemon (eerste MCP call laadt identity)
     Fallback: blokkeert tot stella_confirm_identity

During Work
  3. Evaluation gate: na X tool calls, vereist status report
  4. Summary gate: blokkeert howto_rate tot summary ingediend (na plan completion)
  5. Plan gate: blokkeert non-stella tools tot plan aangemaakt (bij open howto sessie)
  6. Reflection gate: periodiek reflectie vereist
  7. Project context gate: write tools vereisen actief project
  -> Permission gate: free/confirm/approve/block per tool
  -> Auto-update: deploy_config bijwerken na succesvolle writes
  -> Bug action gate: bij probleem, blokkeert tot stella_report_bug (of dismiss_bug)
  -> Howto action gate: bij inzicht, blokkeert tot stella_howto_patch (kleine edits) of stella_howto_upsert (nieuw/rewrite)

After Task
  -> Summary vereist (stella_summarize)
  -> Review vereist (stella_howto_rate of _review)

Plan & Summary Workflow

howto_search → howto_get → plan_create → [tools + plan_update] → summarize → howto_rate
  • Plan gate: zodra een howto sessie open is, worden non-stella tools geblokkeerd tot een plan is aangemaakt
  • Summary gate: zodra een plan completed is, wordt howto_rate geblokkeerd tot een summary is ingediend
  • Disable: STELLA_PLAN_GATE=false in environment, of configurePlanGate(false) in code

Howto Visibility: Scope Isolation + Public/Private

Alle projecten delen dezelfde Supabase. Elke howto heeft twee velden die bepalen wie het kan zien:

scope_id — "Van welk project is dit?"

Komt van LEARNING_SCOPE_ID env var. Bij upsert krijgt een howto de scope_id van de aanmakende server.

is_public — "Mogen andere scopes dit zien?"

Nieuwe howto's starten als is_public: true (public by default). Alleen private maken als het echt project-specifiek is. Quality gates (score >= 4, usage >= 3) gelden voor publishen van private → public.

Scope Filter Logica

Twee lookup strategieën:

// 1. applyScopeFilter (search, stats, basis laden):
// → is_public = true OR scope_id IS NULL OR scope_id = myScopeId
applyScopeFilter(query, includePublic=true)

// 2. findHowtoForEdit (get, upsert, patch, rate, publish, delete):
// → Fetcht ALLE matches: scope_id = myScopeId OR scope_id IS NULL
// → Disambigueert: prefereert eigen scope > public (null) > eerste match
// → Geen maybeSingle() crash bij duplicates
const { data, error } = await findHowtoForEdit(slug);

Wat elke server ziet

| Operatie | Private howto (is_public=false) | Public howto (is_public=true) | |----------|--------------------------------|-------------------------------| | howto_search | Alleen eigen scope + scope=NULL | Alle scopes | | howto_get | Eigen scope + scope=NULL | Eigen scope + scope=NULL | | howto_rate | Eigen scope + scope=NULL | Eigen scope + scope=NULL | | howto_upsert | Eigen scope + scope=NULL (prefers own) | Eigen scope + scope=NULL (prefers own) | | howto_patch | Eigen scope + scope=NULL (prefers own) | Eigen scope + scope=NULL (prefers own) | | howto_publish | Eigen scope + scope=NULL | Eigen scope + scope=NULL | | howto_delete | Eigen scope + scope=NULL | Eigen scope + scope=NULL | | Basis laden | Alleen eigen scope | Alleen eigen scope |

Voorbeeld

snelstart-mcp maakt howto "btw-controle" → scope_id="snelstart-mcp", is_public=false
  → adgency kan het NIET zien

howto_publish slug="btw-controle" is_public=true
  → adgency kan het WEL zien via search/get/rate

stella_howto_stats toont: "btw-controle (v3) — ★4.5 (7x) 🌐"  (🌐 = public, 🔒 = private)

Semantic Search (stella_match_howtos RPC)

De Supabase RPC functie filtert op filter_scope_id:

  • Retourneert howto's met scope_id = myScopeId OF scope_id IS NULL OF is_public = true
  • Resultaten zijn gerankt op cosine similarity (pgvector embeddings)

Actieve MCP Servers

| Server | Scope ID | Bug tools | Bijzonderheden | |--------|----------|-----------|----------------| | ralph-manager | ralph-manager | Ja (centraal) | ralph_control op approve, permission tools op confirm | | agentrook | agentrook | Nee | Brand management, logo generatie, ad campaigns | | web-mcp | web-mcp | Nee | 15 write tools op approve (DNS, domains, Railway, Netlify) + project context gate | | snelstart-mcp | <administratie-id> | Nee | Boekjaar validatie als pre-gate hook | | sparkbuddy-live | sparkbuddy | Nee | Eigen AccessLevel auth (user/admin/superadmin) naast Stella permissions | | vincifox | vincifox | Nee | Howto + reflectie tools | | stella-proxy | stella-proxy | Nee | Howto + reflectie tools + DataForSEO + Supabase | | herald-mcp | herald | Nee | Howto + reflectie tools + CRM/email |


Project Structure

stella/
  hooks/
    stella-gate.sh        → UserPromptSubmit hook (symlinked from ~/.claude/hooks/)
                            Levert instructies (1e prompt only), start daemon, registreert CLI PID, injecteert reflection keys (1x)
    stella-howto-hooks.sh → Pre/PostToolUse + Stop hook (symlinked from ~/.claude/hooks/)
                            Query daemon voor actieve howto hooks, voert ze uit, logt naar ~/.claude/logs/stella/
  src/
    index.ts              → Exports, stellaTools, getStellaHandler
    gates.ts              → withGates(), checkGates(), gate orchestration (7+ gates)
    daemon.ts             → Daemon server process (JSON-RPC over Unix socket)
    daemon-client.ts      → Daemon client (connect, local cache, broadcast sync)
    daemon-spawn.ts       → Auto-start daemon (fork, PID check, stale cleanup)
    plans.ts              → plan_create, plan_update, plan_get, summarize
    howtos.ts             → howto tools + session management + evaluation gate + hook registration
    claude-hooks.ts       → Hook normalisation, Claude Code config generation, summarize
    chat-sessions.ts      → Chat session tracking
    reflections.ts        → reflectie systeem + identity gates + reflection key push
    permissions.ts        → configurePermissions(), checkPermission(), resolvePermission()
    project-context.ts    → Project context gate, deploy_config auto-update
    bugreports.ts         → Bug report tools (centralized in ralph-manager)
    projects.ts           → Project management tools
    tasks.ts              → Task management tools
    batch.ts              → stella_batch_tools (meerdere tools in 1 call)
    session.ts            → MCP session ID management
    embedding.ts          → OpenAI embedding generation (text-embedding-3-small)
    token-tracker.ts      → Token usage tracking per session
    token-stats.ts        → stella_token_stats, stella_token_top_sessions/tools
    howto-analytics.ts    → stella_howto_analytics (usage stats)
    date-params.ts        → Date range parameter parsing
    tool-names.ts         → Tool name resolution (stella_* ↔ host names)
    supabase-client.ts    → Supabase connection, scope filtering, requireLearning
    types.ts              → TypeScript types, helpers, constants
    constants.ts          → Tool names, default config values
  src/neural/
    index.ts              → Re-exports for all neural modules
    window-extractor.ts   → EpisodeWindow types, channel key extraction, top-K, novelty/mismatch
    coactivation.ts       → Hebbian co-activation processor (pairs that fire together → edge strengthening)
    neighborhood.ts       → BFS graph traversal, Jaccard similarity, decision tracing
    bundle-detector.ts    → Clique detection + promotion to bundle nodes
    policy-engine.ts      → PolicyEngine class, heuristic + Thompson Sampling, StateOut
    predictors.ts         → Tool health predictors: time-windowed trends (24h/7d/30d), outcome-based success rates, trend detection, PredictorStats/ToolTrend exports
  src/store/
    daemon-store-client.ts → DaemonStoreClient — socket proxy to daemon + graph proxy
  tests/
    daemon-e2e.mjs        → 50 tests: lifecycle, state, multi-client, plans, howtos
    daemon-client-e2e.mjs → 24 tests: auto-spawn, fallback, API functions
  dist/                   → Compiled JavaScript (npm package output)
  package.json            → @soulbatical/stella

Build & Test

# Build
npm run build

# Run daemon tests (74 tests)
node tests/daemon-e2e.mjs
node tests/daemon-client-e2e.mjs

# After stella changes: rebuild consumers
cd ~/projecten/web-mcp && npm run build
cd ~/projecten/snelstart-mcp/mcp && npm run build
cd ~/projecten/ralph-manager/backend-mcp && npm run build
cd ~/projecten/adgency/backend-mcp && npm run build

License

MIT