# 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.md`](README.md) for quick start, [`docs/ECOSYSTEM_ARCHITECTURE.md`](docs/ECOSYSTEM_ARCHITECTURE.md) for full architecture. --- ## 1. Project Identity | Key | Value | | --------------------- | --------------------------------------------------------------------------------------- | | **Root package** | `@bytelyst/root` | | **Library scope** | `@bytelyst/*` (packages/) | | **Service scope** | `@lysnrai/*` (services/) | | **Product consumers** | [LysnrAI](../learning_voice_ai_agent), [MindLyst](../learning_multimodal_memory_agents) | | **Product-agnostic** | Yes — every Cosmos doc includes `productId` | | **Runtime** | Node.js (ESM), TypeScript 5.7+ | | **Package manager** | pnpm (workspace) | | **Test runner** | Vitest | ## 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 (loadProductIdentity) │ ├── 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 │ ├── testing/ # Shared test mocks, fixtures, Fastify inject helpers │ └── 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 ├── services/ # @lysnrai/* product-agnostic microservices │ ├── platform-service/ # Consolidated: auth, audit, flags, notifications, blob, │ │ # invitations, referrals, promos, subscriptions, usage, │ │ # plans, licenses, stripe, items, comments, votes, public (port 4003) │ ├── 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 ├── pnpm-workspace.yaml # Workspace: packages/* + services/* ├── tsconfig.base.json # Shared TS config (ES2022, NodeNext, strict) ├── vitest.config.ts # Root vitest config (passWithNoTests) ├── docker-compose.yml # Full service stack + Loki + Grafana + Traefik ├── .env.example # Required env vars template └── .editorconfig # Editor settings ``` ## 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 to `dist/` - **Tests:** Vitest with `passWithNoTests: true` at root ### Service framework (Fastify) - **Framework:** Fastify 5 with Zod validation - **Module pattern:** `types.ts` → `repository.ts` → `routes.ts` per 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` (never `console.log`) - **Health:** Every service exposes `GET /health` → `{ status: "ok", service, requestId }` - **Request tracing:** `x-request-id` header propagated across all services - **Dev mode:** `tsx watch src/server.ts` ### Package conventions - All packages export from `src/index.ts` → `dist/index.js` - Use `exports` field in `package.json` (not just `main`) - Peer dependencies for heavy/shared deps (`@azure/cosmos`, `jose`, `bcryptjs`, `react`, `zod`) - Workspace deps: `"@bytelyst/errors": "workspace:*"` ## 4. Coding Conventions ### MUST follow - Every Cosmos document MUST include a `productId` field - Every REST endpoint MUST validate input with Zod schemas - Every service MUST propagate `x-request-id` headers - Use `PRODUCT_ID` from `@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 their `src/lib/` files (`errors.ts`, `cosmos.ts`, `product-config.ts`) - Commit messages: `type(scope): description` — types: `feat`, `fix`, `docs`, `refactor`, `test`, `chore` ### MUST NOT do - Never use `console.log` in production code — use `req.log` or `app.log` in Fastify - Never use `any` type — use Zod inference or explicit types - Never hardcode secrets or API keys - Secret guardrails: Husky runs `scripts/secret-scan-staged.sh` (pre-commit) and `scripts/secret-scan-repo.sh` (pre-push). See `docs/WINDSURF/CODEX_SESSION_SUMMARY_AND_PLAYBOOK.md`. - 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. 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) | | **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 | | **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/` | ### Dashboard Consumers (via `file:` refs) The following dashboards in `../learning_voice_ai_agent/` consume `@bytelyst/*` packages: | Dashboard | Packages Used | | ----------------------- | ------------------------------------------------------------ | | `admin-dashboard-web` | api-client, auth, config, cosmos, errors, logger, react-auth | | `user-dashboard-web` | api-client, auth, config, cosmos, errors, logger, react-auth | | `tracker-dashboard-web` | api-client, config, cosmos, errors | **Prerequisite:** Run `pnpm build` in this repo before running `npm install` in any dashboard. ## 6. How to Run Things ```bash # ── Install ──────────────────────────────────────── pnpm install # ── Build all packages + services ────────────────── pnpm build # ── Run all tests (277 tests across all workspaces) ─ 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 pnpm --filter @lysnrai/billing-service dev pnpm --filter @lysnrai/growth-service dev pnpm --filter @lysnrai/tracker-service dev # ── Run tests for one workspace ──────────────────── pnpm --filter @lysnrai/platform-service test pnpm --filter @bytelyst/errors test # ── Generate design tokens ───────────────────────── pnpm --filter @bytelyst/design-tokens generate # ── Docker Compose (all services + monitoring) ───── docker compose up -d docker compose down # ── Health check all services ────────────────────── pnpm --filter @lysnrai/monitoring check ``` ## 7. Common Patterns ### Adding a new Fastify module 1. Create `services//src/modules//types.ts` — Zod schemas + TS interfaces 2. Create `services//src/modules//repository.ts` — Cosmos CRUD 3. Create `services//src/modules//routes.ts` — REST endpoints 4. Register in `services//src/server.ts`: `await app.register(routes, { prefix: "/api" })` 5. Add tests: `services//src/modules//.test.ts` ### Adding a new shared package 1. Create `packages//` with `package.json` (`name: "@bytelyst/"`) 2. Add `src/index.ts` with exports 3. Add `tsconfig.json` extending `../../tsconfig.base.json` 4. Heavy deps go in `peerDependencies`, not `dependencies` 5. Consumer services add `"@bytelyst/": "workspace:*"` to their `dependencies` ### Using shared packages in services Services re-export from `@bytelyst/*` in `src/lib/` for clean internal imports: ```typescript // 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 1. Edit `packages/design-tokens/tokens/bytelyst.tokens.json` 2. Run `pnpm --filter @bytelyst/design-tokens generate` 3. 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://.documents.azure.com:443/ COSMOS_KEY= COSMOS_DATABASE=lysnrai JWT_SECRET= ``` Additional per-service: ``` # billing-service + growth-service STRIPE_SECRET_KEY= STRIPE_WEBHOOK_SECRET= # platform-service (blob storage) AZURE_BLOB_CONNECTION_STRING= AZURE_BLOB_ACCOUNT_NAME=bytelystblobs AZURE_BLOB_ACCOUNT_KEY= # All services DEFAULT_PRODUCT_ID=lysnrai ``` ## 9. Dependency Graph ``` @bytelyst/errors ← no deps (foundation) @bytelyst/cosmos ← peers: @azure/cosmos @bytelyst/config ← peers: zod @bytelyst/auth ← peers: jose, bcryptjs @bytelyst/api-client ← no deps @bytelyst/react-auth ← deps: @bytelyst/api-client; peers: react @bytelyst/design-tokens ← no deps (standalone generator) @lysnrai/platform-service ← @bytelyst/{config, cosmos, errors} @lysnrai/billing-service ← @bytelyst/{config, cosmos, errors} @lysnrai/growth-service ← @bytelyst/{config, cosmos, errors} @lysnrai/tracker-service ← @bytelyst/{config, cosmos, errors} @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. ## 10. Key Documents | When you need to... | Read this | | -------------------------------- | -------------------------------------------------------------------------------------------------- | | Understand the full architecture | [`docs/ECOSYSTEM_ARCHITECTURE.md`](docs/ECOSYSTEM_ARCHITECTURE.md) | | See the extraction roadmap | [`docs/ROADMAP.md`](docs/ROADMAP.md) | | Understand why this repo exists | [`docs/COMMON_PLATFORM_ANALYSIS.md`](docs/COMMON_PLATFORM_ANALYSIS.md) | | Quick start / consuming packages | [`README.md`](README.md) | | LysnrAI product repo conventions | [`../learning_voice_ai_agent/AGENTS.md`](../learning_voice_ai_agent/AGENTS.md) | | MindLyst native repo conventions | [`../learning_multimodal_memory_agents/AGENTS.md`](../learning_multimodal_memory_agents/AGENTS.md) | ## 11. Service Test Counts | Service / Package | Tests | Runner | | ------------------ | -------- | ------ | | platform-service | 55 | vitest | | tracker-service | 45 | vitest | | extraction-service | 46 | vitest | | growth-service | 33 | vitest | | billing-service | 32 | vitest | | **Total** | **211+** | | ## 12. Common Pitfalls 1. **Don't import `zod` from `@bytelyst/config` in services** — services bundle their own zod version. Use self-contained Zod schemas in `src/lib/config.ts`. 2. **Don't forget `productId`** — every Cosmos document must include it. 3. **Don't use `dependencies` for heavy libs in packages** — use `peerDependencies` so consumers control the version. 4. **Don't mix up package scopes** — libraries are `@bytelyst/*`, services are `@lysnrai/*`. 5. **Don't run `npm` commands** — this is a pnpm workspace. Always use `pnpm`. 6. **Don't modify generated files directly** — edit `bytelyst.tokens.json` and re-run the generator. 7. **Build packages before testing services** — service tests may import from `@bytelyst/*` dist. Run `pnpm build` first if you get import errors.