37 KiB
AGENTS.md — AI Coding Agent Instructions
For: Claude Code, OpenAI Codex, Cursor, GitHub Copilot, Windsurf Cascade, and any AI coding agent. Repo:
learning_ai_common_plat— Shared platform packages + microservices for the ByteLyst ecosystem. See also:README.mdfor quick start,docs/ECOSYSTEM_ARCHITECTURE.mdfor full architecture.
1. Project Identity
| Key | Value |
|---|---|
| Root package | @bytelyst/root |
| Library scope | @bytelyst/* (packages/) |
| Service scope | @lysnrai/* (services/) |
| Product consumers | LysnrAI, MindLyst, ChronoMind, JarvisJr, NomGap, PeakPulse |
| Product-agnostic | Yes — every Cosmos doc includes productId |
| Runtime | Node.js (ESM), TypeScript 5.7+ |
| Package manager | pnpm (workspace) |
| Test runner | Vitest |
| Prototype stack | Docker Compose with Cosmos emulator, Azurite, Mailpit, Traefik, Loki, and Grafana |
2. Monorepo Layout
learning_ai_common_plat/
├── packages/ # @bytelyst/* shared libraries
│ ├── errors/ # Typed HTTP service errors (400–429)
│ ├── cosmos/ # Azure Cosmos DB client singleton + container registry
│ ├── config/ # Zod-based env loader + product identity + AKV resolver
│ ├── auth/ # JWT utilities, auth middleware, password hashing
│ ├── api-client/ # Configurable fetch wrapper with auth token injection
│ ├── fastify-core/ # createServiceApp() factory + startService() helper
│ ├── react-auth/ # React auth context factory (typed provider + hook)
│ ├── logger/ # Structured logging wrapper (pino-based)
│ ├── testing/ # Shared test mocks, fixtures, Fastify inject helpers
│ ├── blob/ # Azure Blob Storage client + SAS token helpers
│ ├── extraction/ # createExtractionClient(), shared types for extraction consumers
│ ├── monitoring/ # Health-check utilities, Loki/Grafana helpers
│ ├── llm-router/ # Deterministic LLM router: provider/model selection, fallback, health
│ └── design-tokens/ # Cross-platform tokens (JSON → CSS/TS/Kotlin/Swift)
│ ├── tokens/bytelyst.tokens.json # ← CANONICAL SOURCE
│ ├── scripts/generate.ts # Token generator
│ └── generated/ # Output: tokens.css, tokens.ts, MindLystTokens.kt, MindLystTheme.swift
├── dashboards/ # Product-agnostic web dashboards (Next.js)
│ ├── admin-web/ # Platform admin console (port 3001)
│ └── tracker-web/ # Issue tracker + public roadmap (port 3003)
├── services/ # @lysnrai/* product-agnostic microservices
│ ├── platform-service/ # Product-agnostic platform: auth, audit, flags, notifications, blob,
│ │ # invitations, referrals, promos, subscriptions, usage, plans,
│ │ # licenses, stripe, items, comments, votes, public (port 4003)
│ │ # NOTE: Product-specific modules migrated to product repos' backend/
│ ├── extraction-service/ # LangExtract text extraction + Python sidecar (port 4005)
│ └── monitoring/ # Loki + Grafana config, health-check script
├── docs/ # Architecture docs, roadmap, analysis
├── package.json # Root scripts: build, test, typecheck, clean, prototype:self-test
├── pnpm-workspace.yaml # Workspace: packages/* + services/* + dashboards/*
├── tsconfig.base.json # Shared TS config (ES2022, NodeNext, strict)
├── vitest.config.ts # Root vitest config (passWithNoTests)
├── docker-compose.yml # Prototype stack: services + Cosmos emulator + Azurite + Mailpit + monitoring
├── .env.example # Required env vars template
└── .editorconfig # Editor settings
2A. Prototype Runtime Conventions
- The current single-host prototype is defined by
docker-compose.yml. - Prototype state currently lives in:
- Cosmos DB Emulator
- Azurite blob storage
- Mailpit SMTP sandbox
- Reuse the existing prototype diagnostics instead of adding parallel health endpoints:
GET /healthGET /api/health/dependenciesGET /api/self-testGET /api/self-test.json
- The canonical host-side smoke test command is
pnpm prototype:self-test. - The underlying implementation is
scripts/prototype-self-test.sh. Extend it instead of creating duplicate one-off prototype scripts. - If you change prototype infra, also update:
README.mddocs/PROTOTYPE_DEPLOYMENT.mddocker-compose.yml.env.examplewhen tracked defaults change
Current local prototype endpoints
platform-service:http://localhost:4003extraction-service:http://localhost:4005mcp-server:http://localhost:4007- Cosmos Data Explorer:
http://localhost:1234 - Azurite blob endpoint:
http://localhost:10000 - Mailpit SMTP:
localhost:1025 - Mailpit inbox UI:
http://localhost:8025
3. Tech Stack Rules
TypeScript (all packages + services)
- Module system: ESM (
"type": "module"everywhere) - TS target: ES2022,
moduleResolution: NodeNext - Base config: All packages/services extend
../../tsconfig.base.json - Builds:
tsc— outputs todist/ - Tests: Vitest with
passWithNoTests: trueat root
Service framework (Fastify)
- Framework: Fastify 5 with Zod validation
- Module pattern:
types.ts→repository.ts→routes.tsper module - Auth: JWT via
jose— platform-service issues, all others validate - Database: Azure Cosmos DB via
@azure/cosmos - Logging: Fastify built-in
req.log/app.log(neverconsole.log) - Health: Every service exposes
GET /health→{ status: "ok", service, requestId } - Request tracing:
x-request-idheader propagated across all services - Dev mode:
tsx watch src/server.ts
Package conventions
- All packages export from
src/index.ts→dist/index.js - Use
exportsfield inpackage.json(not justmain) - Peer dependencies for heavy/shared deps (
@azure/cosmos,jose,bcryptjs,react,zod) - Workspace deps:
"@bytelyst/errors": "workspace:*" - If a dashboard or app consumes a local package outside the pnpm workspace, build the package first and import from
dist/, not rawsrc/
4. Coding Conventions
MUST follow
- Every Cosmos document MUST include a
productIdfield - Every REST endpoint MUST validate input with Zod schemas
- Every service MUST propagate
x-request-idheaders - Prototype infra changes MUST preserve
pnpm prototype:self-test - Prototype dependency checks belong in the shared status/self-test surfaces, not ad hoc endpoints
- Use
PRODUCT_IDfrom@bytelyst/config(loadProductIdentity()) — never hardcode - Services use self-contained Zod config schemas in
src/lib/config.ts(avoids zod version mismatch with shared packages) - Services re-export from
@bytelyst/*in theirsrc/lib/files (errors.ts,cosmos.ts,product-config.ts) - For LLM routing, prefer
@bytelyst/llm-routeras the source of truth; do not introduce parallel routing logic unless explicitly required __LOCAL_LLMs/dashboarduses server-side routing insrc/app/api/ollama/chat/route.ts; preserve that pattern and keep the UI as a thin client- Commit messages:
type(scope): description— types:feat,fix,docs,refactor,test,chore
MUST NOT do
- Never use
console.login production code — usereq.logorapp.login Fastify - Never use
anytype — use Zod inference or explicit types - Never hardcode secrets or API keys
- Secret guardrails: Husky runs
scripts/secret-scan-staged.sh(pre-commit) andscripts/secret-scan-repo.sh(pre-push). Seedocs/WINDSURF/CODEX_SESSION_SUMMARY_AND_PLAYBOOK.md. - Never commit real emulator keys or blob account keys in tracked files; keep placeholders in
.env.example - Never modify tests to make them pass — fix the actual code
- Never delete existing comments or documentation unless explicitly asked
- Never add emojis to code unless explicitly asked
5. Design System (Critical)
NEVER hardcode colors
All colors MUST come from @bytelyst/design-tokens. Hardcoded hex values create inconsistency and maintenance debt.
| Platform | ❌ DON'T | ✅ DO |
|---|---|---|
| Web | color: '#5A8CFF' |
color: var(--ml-accent-primary) |
| Web (Tailwind) | bg-[#5A8CFF] |
bg-[var(--ml-accent-primary)] |
| iOS | Color(hex: 0x5A8CFF) |
MindLystColors.darkAccentPrimary |
| Android/KMP | Color(0xFF5A8CFF) |
Color(MindLystTokens.Dark.ACCENT_PRIMARY) |
| React Native | backgroundColor: '#5A8CFF' |
tokens.colors.accentPrimary |
Token file locations
packages/design-tokens/
├── tokens/bytelyst.tokens.json # ← CANONICAL SOURCE (edit this)
├── generated/
│ ├── tokens.css # Web: CSS custom properties
│ ├── tokens.ts # TypeScript constants
│ ├── MindLystTokens.kt # Kotlin/KMP/Android
│ ├── MindLystTheme.swift # Swift/iOS
│ └── react-native/tokens.ts # React Native
└── scripts/
├── generate.ts # Main generator
├── generate-react-native.ts # RN generator
├── validate-tokens.cjs # Validation script
└── token-coverage.cjs # Coverage report
How to update tokens
- Edit
packages/design-tokens/tokens/bytelyst.tokens.json - Run
pnpm --filter @bytelyst/design-tokens generate - Copy generated files to consumer repos (see per-repo AGENTS.md)
- Commit both the JSON source AND generated files
Product-specific token sections
Each product has a dedicated section in bytelyst.tokens.json:
| Product | Token Section | Example |
|---|---|---|
| MindLyst | color.brain |
BRAIN_WORK, BRAIN_HOME |
| JarvisJr | color.jarvisjr |
AGENT_COACH, AGENT_LINGUA |
| PeakPulse | color.peakpulse |
ACTIVITY_HIKE, SPEED_ZONE_FAST |
| ChronoMind | color.chronomind |
URGENCY_CRITICAL, FOCUS_MODE |
| NomGap | color.nomgap |
STAGE_KETOSIS, AUTOPHAGY_METER |
| LysnrAI | color.lysnrai |
RECORDING_ACTIVE, DICTATION_MODE |
Validation
Check for hardcoded colors before committing:
# In any product repo
node ../learning_ai_common_plat/packages/design-tokens/scripts/validate-tokens.cjs src/
# Get coverage report
node ../learning_ai_common_plat/packages/design-tokens/scripts/token-coverage.cjs src/
CI Integration: All PRs should run the validation script and fail if new hardcoded colors are introduced.
Current adoption status (2026-03-03)
| Product | Token Adoption | Status |
|---|---|---|
| MindLyst iOS | 100% | ✅ Good |
| MindLyst Android | 100% | ✅ Good |
| ChronoMind Web | 0% | ❌ Critical |
| ChronoMind iOS | 0% | ❌ Critical |
| PeakPulse iOS | 0% | ❌ Needs tokens |
| NomGap | 0% | ❌ Critical (466 hardcoded) |
| LysnrAI iOS | 0% | ❌ Critical |
| JarvisJr iOS | 0% | ❌ Critical |
See full audit: docs/design-system/DESIGN_SYSTEM_AUDIT_2026-03-03.md
6. File Ownership Map
| Domain | Location | Key Files |
|---|---|---|
| Errors | packages/errors/ |
src/index.ts — BadRequestError, UnauthorizedError, ForbiddenError, NotFoundError, ConflictError, RateLimitError |
| Cosmos client | packages/cosmos/ |
src/index.ts — getCosmosClient(), getContainer(), container registry |
| Config / Product ID | packages/config/ |
src/index.ts — loadEnvConfig(), loadProductIdentity(), getProductId() |
| JWT / Auth | packages/auth/ |
src/index.ts — signJwt(), verifyJwt(), hashPassword(), verifyPassword(), auth middleware |
| API client | packages/api-client/ |
src/index.ts — createApiClient() with token injection |
| React auth | packages/react-auth/ |
src/index.ts — createAuthContext() factory (provider + hook) |
| LLM router | packages/llm-router/ |
src/router.ts — route/plan/fallback, src/registry.ts — providers incl. local Ollama |
| Design tokens | packages/design-tokens/ |
tokens/bytelyst.tokens.json (source), scripts/generate.ts (generator), generated/ (output) |
| Auth / JWT issue | services/platform-service/ |
src/modules/auth/ |
| Feature flags | services/platform-service/ |
src/modules/flags/ — FNV-1a hash for deterministic rollout |
| Blob storage | services/platform-service/ |
src/modules/blob/, src/lib/blob.ts — SAS tokens, CRUD |
| Prototype status | services/platform-service/ |
src/modules/status/ — dependency health JSON, self-test JSON, self-test HTML |
| Delivery / SMTP | services/platform-service/ |
src/modules/delivery/ — SMTP delivery, Mailpit-backed prototype email flows |
| Audit log | services/platform-service/ |
src/modules/audit/ |
| Notifications | services/platform-service/ |
src/modules/notifications/ |
| Rate limiting | services/platform-service/ |
src/modules/rate-limit/ |
| Subscriptions | services/platform-service/ |
src/modules/subscriptions/ |
| Stripe webhooks | services/platform-service/ |
src/modules/stripe/ |
| Usage tracking | services/platform-service/ |
src/modules/usage/ |
| Plans | services/platform-service/ |
src/modules/plans/ |
| Licenses | services/platform-service/ |
src/modules/licenses/ |
| Invitations | services/platform-service/ |
src/modules/invitations/ |
| Referrals | services/platform-service/ |
src/modules/referrals/ |
| Promos | services/platform-service/ |
src/modules/promos/ |
| Tracker items | services/platform-service/ |
src/modules/items/ |
| Public roadmap | services/platform-service/ |
src/modules/public/ |
| Tracker comments | services/platform-service/ |
src/modules/comments/ |
| Tracker votes | services/platform-service/ |
src/modules/votes/ |
| Extraction routes | services/extraction-service/ |
src/modules/extract/ — POST /extract, /extract/batch, /extract/jobs, /extract/models |
| Extraction tasks | services/extraction-service/ |
src/modules/tasks/ — predefined task library (triage, transcript, memory-insight, etc.) |
| Extraction Python | services/extraction-service/ |
python/src/ — LangExtract sidecar (FastAPI :4006), extractor, task registry, language detection |
| Extraction package | packages/extraction/ |
src/index.ts — createExtractionClient(), shared types for consumers |
| Monitoring | services/monitoring/ |
health-check.ts, loki/, grafana/ |
| Local LLM dashboard | __LOCAL_LLMs/dashboard/ |
src/app/api/ollama/chat/route.ts — shared router + Ollama bridge, src/app/lib/llm-router.ts — built package re-export |
Dashboard Consumers (via file: refs)
The following dashboards consume @bytelyst/* packages:
| Dashboard | Location | Packages Used |
|---|---|---|
admin-web |
dashboards/admin-web/ (this repo) |
api-client, auth, config, cosmos, errors, logger, react-auth |
user-dashboard-web |
../learning_voice_ai_agent/ |
api-client, auth, config, cosmos, errors, logger, react-auth |
tracker-web |
dashboards/tracker-web/ (this repo) |
api-client, config, cosmos, errors |
Prerequisite: Run pnpm build in this repo before running npm install in any dashboard.
Local Mission Control Dashboard
__LOCAL_LLMs/dashboard/ is a standalone Next.js app for local Ollama usage. It is not part of the pnpm workspace, but it consumes @bytelyst/llm-router.
- Build source of truth:
packages/llm-router/ - Dashboard bridge:
__LOCAL_LLMs/dashboard/src/app/lib/llm-router.ts - Chat routing path:
__LOCAL_LLMs/dashboard/src/app/api/ollama/chat/route.ts - The dashboard must consume the built package output from
packages/llm-router/dist/ __LOCAL_LLMs/dashboard/package.jsonrunspredevandprebuildhooks to build@bytelyst/llm-routerautomatically- Auto model selection should happen on the server route, not in the React client
6. How to Run Things
# ── Install ────────────────────────────────────────
pnpm install
# ── Build all packages + services ──────────────────
pnpm build
# ── Run all tests ────────────────────────────────
pnpm test
# ── Type-check everything ──────────────────────────
pnpm typecheck
# ── Clean dist/ in all packages ────────────────────
pnpm clean
# ── Run a specific service in dev mode ─────────────
pnpm --filter @lysnrai/platform-service dev # port 4003
pnpm --filter @lysnrai/extraction-service dev # port 4005
# ── Run tests for one workspace ────────────────────
pnpm --filter @lysnrai/platform-service test
pnpm --filter @bytelyst/errors test
pnpm --filter @bytelyst/llm-router test
# ── Generate design tokens ─────────────────────────
pnpm --filter @bytelyst/design-tokens generate
# ── Local LLM dashboard ────────────────────────────
cd __LOCAL_LLMs/dashboard && npm run dev # predev builds @bytelyst/llm-router first
cd __LOCAL_LLMs/dashboard && npm run build # prebuild builds @bytelyst/llm-router first
# ── Docker Compose (all services + monitoring) ─────
docker compose up -d
docker compose down
pnpm prototype:self-test
# ── Portable builds for consumer repos ────────────
# Pack @bytelyst/* tarballs so Docker/CI builds don't need this sibling repo
./scripts/prep-consumer.sh /path/to/consumer-dir # pack + rewrite
./scripts/prep-consumer.sh /path/to/consumer-dir --restore # undo
# ── Health check all services ──────────────────────
pnpm --filter @lysnrai/monitoring check
7. Common Patterns
Adding a new Fastify module
- Create
services/<service>/src/modules/<name>/types.ts— Zod schemas + TS interfaces - Create
services/<service>/src/modules/<name>/repository.ts— Cosmos CRUD - Create
services/<service>/src/modules/<name>/routes.ts— REST endpoints - Register in
services/<service>/src/server.ts:await app.register(routes, { prefix: "/api" }) - Add tests:
services/<service>/src/modules/<name>/<name>.test.ts
Adding a new shared package
- Create
packages/<name>/withpackage.json(name: "@bytelyst/<name>") - Add
src/index.tswith exports - Add
tsconfig.jsonextending../../tsconfig.base.json - Heavy deps go in
peerDependencies, notdependencies - Consumer services add
"@bytelyst/<name>": "workspace:*"to theirdependencies
Using shared packages in services
Services re-export from @bytelyst/* in src/lib/ for clean internal imports:
// src/lib/errors.ts
export { BadRequestError, NotFoundError, ConflictError } from '@bytelyst/errors';
// src/lib/cosmos.ts
export { getCosmosClient, getContainer } from '@bytelyst/cosmos';
// src/lib/product-config.ts
import { loadProductIdentity } from '@bytelyst/config';
const identity = loadProductIdentity();
export const PRODUCT_ID = identity.productId;
Design token workflow
- Edit
packages/design-tokens/tokens/bytelyst.tokens.json - Run
pnpm --filter @bytelyst/design-tokens generate - Copy generated files to consumer repos:
MindLystTokens.kt→mindlyst-native/shared/.../theme/MindLystTheme.swift→mindlyst-native/iosApp/- Token CSS →
design-system/web/mindlyst.css(token section only)
8. Environment Variables
Required by all services (see .env.example):
COSMOS_ENDPOINT=https://<account>.documents.azure.com:443/
COSMOS_KEY=<primary-key>
COSMOS_DATABASE=lysnrai
JWT_SECRET=<shared-secret>
Prototype Docker defaults differ from production:
COSMOS_ENDPOINT=http://cosmos-emulator:8081STORAGE_PROVIDER=azurewith Azurite-backed blob configEMAIL_PROVIDER=smtpwithSMTP_HOST=mailpit- Use placeholders in tracked files; keep real local values in
.env
Additional per-service:
# platform-service
STRIPE_SECRET_KEY=<stripe-key>
STRIPE_WEBHOOK_SECRET=<webhook-secret>
# platform-service (blob storage)
AZURE_BLOB_CONNECTION_STRING=<connection-string>
AZURE_BLOB_ACCOUNT_NAME=bytelystblobs
AZURE_BLOB_ACCOUNT_KEY=<account-key>
# All services
DEFAULT_PRODUCT_ID=lysnrai
9. Corporate Network / Proxy Setup
Development happens on a corporate network with a TLS-intercepting proxy. The NETWORK env var controls all proxy behavior — no manual toggling needed.
Quick Reference
| Tool | Corporate proxy mechanism | Config location |
|---|---|---|
| npm / pnpm | NPM_CONFIG_REGISTRY → JFrog proxy, NPM_CONFIG_STRICT_SSL=false |
switch-network.sh |
| Node.js | NODE_TLS_REJECT_UNAUTHORIZED=0 |
switch-network.sh |
| Python (pip) | PIP_TRUSTED_HOST, http_proxy/https_proxy |
switch-network.sh |
| Gradle / Android / KMP | Custom JVM truststore with corporate CA cert | ~/.gradle/gradle.properties + GRADLE_OPTS |
| curl / general HTTP | http_proxy/https_proxy → cso.proxy.att.com:8080 |
switch-network.sh |
How it works
~/.zshrcsetsexport NETWORK=corp(orhome)~/.zshrcsourcesscripts/switch-network.shfrom this repo- The script conditionally sets/unsets all proxy env vars based on
NETWORK - On new shell:
🏢 NETWORK=corp — proxy activeor🏠 NETWORK=home — direct internet
Key files
| File | Purpose |
|---|---|
scripts/switch-network.sh |
Central network switch — sets all proxy vars |
~/.gradle/gradle.properties |
Gradle daemon JVM args (truststore) + HTTP proxy host/port |
~/.gradle/ssl/gradle-cacerts.jks |
Java truststore = default cacerts + ATT CSO proxy CA cert |
Gradle SSL (TLS interception)
The corporate proxy (cso.proxy.att.com) does TLS interception — it replaces upstream TLS certificates with its own, signed by the ATTINTERNALROOTv2 CA. Gradle's JVM doesn't trust this CA by default.
Solution: A custom Java truststore (~/.gradle/ssl/gradle-cacerts.jks) that includes:
- All default Java CA certificates (from
$JAVA_HOME/lib/security/cacerts) - The AT&T CSO proxy CA certificate
The truststore is passed to Gradle via:
GRADLE_OPTSenv var (set byswitch-network.shwhenNETWORK=corp) — for the wrapper bootstrap JVMorg.gradle.jvmargsin~/.gradle/gradle.properties— for the daemon JVM
Recreate truststore (needed after Java updates):
mkdir -p ~/.gradle/ssl
JAVA_HOME=$(/usr/libexec/java_home)
cp "$JAVA_HOME/lib/security/cacerts" ~/.gradle/ssl/gradle-cacerts.jks
echo | openssl s_client -connect services.gradle.org:443 \
-proxy cso.proxy.att.com:8080 -showcerts 2>/dev/null \
| awk 'BEGIN{c=0} /BEGIN CERT/{c++} c==2{print} /END CERT/&&c==2{exit}' \
> /tmp/corp-ca.pem
keytool -importcert -noprompt -trustcacerts -alias att-cso-proxy \
-file /tmp/corp-ca.pem \
-keystore ~/.gradle/ssl/gradle-cacerts.jks -storepass changeit
MUST follow (network-related)
- Always use
NETWORKenv var — never hardcode proxy URLs in app code - Gradle builds require
GRADLE_OPTSwith truststore when on corp network (handled automatically byswitch-network.sh) - If a Gradle build fails with SSL errors, verify
echo $GRADLE_OPTSshows the truststore path - If adding a new tool that fetches from the internet, add its proxy config to
switch-network.sh ~/.gradle/gradle.propertiesis a local-only file — never commit it to any repo
Kotlin Platform SDK (packages/kotlin-platform-sdk/)
The shared Kotlin SDK is consumed by Android apps as a composite build via includeBuild() in each product's settings.gradle.kts. Key details:
settings.gradle.ktsdeclarespluginManagementanddependencyResolutionManagementrepos (required for composite builds to resolve their own deps)build.gradle.ktsuses the Compose compiler plugin for UI components (SurveyUI,InAppMessageUI)- Uses
kotlinOptions { jvmTarget = "17" }(notcompilerOptions {}) for compatibility
10. Dependency Graph
@bytelyst/errors ← no deps (foundation)
@bytelyst/cosmos ← peers: @azure/cosmos
@bytelyst/config ← peers: zod; includes AKV resolver (resolveKeyVaultSecrets)
@bytelyst/auth ← peers: jose, bcryptjs
@bytelyst/api-client ← no deps
@bytelyst/react-auth ← deps: @bytelyst/api-client; peers: react
@bytelyst/blob ← peers: @azure/storage-blob
@bytelyst/extraction ← no deps (types + client factory)
@bytelyst/monitoring ← no deps (health-check utilities)
@bytelyst/llm-router ← no deps (deterministic provider/model router + local Ollama plan support)
@bytelyst/fastify-core ← deps: fastify; createServiceApp() + startService()
@bytelyst/logger ← deps: pino
@bytelyst/testing ← deps: vitest; shared mocks + Fastify inject helpers
@bytelyst/design-tokens ← no deps (standalone generator)
@lysnrai/platform-service ← @bytelyst/{fastify-core, config, cosmos, errors, auth, blob}
@lysnrai/extraction-service ← @bytelyst/{fastify-core, config, cosmos, errors, auth}
Build order: packages first (they have no inter-deps), then services. pnpm build handles this automatically via workspace topology.
11. Key Documents
| When you need to... | Read this |
|---|---|
| Understand the full architecture | docs/ECOSYSTEM_ARCHITECTURE.md |
| See the extraction roadmap | docs/ROADMAP.md |
| Understand why this repo exists | docs/COMMON_PLATFORM_ANALYSIS.md |
| Quick start / consuming packages | README.md |
| LysnrAI product repo conventions | ../learning_voice_ai_agent/AGENTS.md |
| MindLyst native repo conventions | ../learning_multimodal_memory_agents/AGENTS.md |
12. Service Test Counts
| Service / Package | Tests | Runner |
|---|---|---|
| platform-service | 800 | vitest |
| extraction-service | 46 | vitest |
| packages (various) | ~30 | vitest |
| Total | 876+ |
Note: billing-service, growth-service, and tracker-service were consolidated into platform-service (Feb 2026). Product-specific modules migrated to product repo backends (see below).
13. Product-Specific Backends
Product-specific API modules have been migrated from platform-service into each product repo's backend/ directory:
| Product | Repo | Port | Modules | Tests |
|---|---|---|---|---|
| PeakPulse | ../learning_ai_peakpulse/backend/ |
4010 | peak-sessions, peak-routes | 32 |
| ChronoMind | ../learning_ai_clock/backend/ |
4011 | timers, routines, households, shared-timers | 130 |
| JarvisJr | ../learning_ai_jarvis_jr/backend/ |
4012 | jarvis-agents, jarvis-sessions, jarvis-memory, jarvis-teams, marketplace | 198 |
| NomGap | ../learning_ai_fastgap/backend/ |
4013 | fasting-sessions, fasting-protocols, body-stages, social-fasting, meal-log, push-triggers | 152 |
| MindLyst | ../learning_multimodal_memory_agents/backend/ |
4014 | brains, memory, reflections, daily-briefs, streaks | 59 |
Each product backend uses @bytelyst/* packages via file: refs and follows the same Fastify module pattern.
14. Common Pitfalls
- Don't import
zodfrom@bytelyst/configin services — services bundle their own zod version. Use self-contained Zod schemas insrc/lib/config.ts. - Don't forget
productId— every Cosmos document must include it. - Don't use
dependenciesfor heavy libs in packages — usepeerDependenciesso consumers control the version. - Don't mix up package scopes — libraries are
@bytelyst/*, services are@lysnrai/*. - Don't run
npmcommands — this is a pnpm workspace. Always usepnpm. Exception:__LOCAL_LLMs/dashboard/is intentionally npm-managed and may usenpm run dev/build/start. - Don't modify generated files directly — edit
bytelyst.tokens.jsonand re-run the generator. - Build packages before testing services or non-workspace dashboards — service tests and
__LOCAL_LLMs/dashboardmay import from@bytelyst/*dist/. Runpnpm buildfirst if you get import errors. - Don't duplicate LLM routing logic — update
@bytelyst/llm-routerfirst, then have consumers call it.