diff --git a/.actrc b/.actrc new file mode 100644 index 000000000..4a0687d49 --- /dev/null +++ b/.actrc @@ -0,0 +1,4 @@ +-P ubuntu-latest=catthehacker/ubuntu:act-latest +-P ubuntu-22.04=catthehacker/ubuntu:act-22.04 +--container-architecture linux/amd64 +--use-gitignore=false diff --git a/.github/COPILOT_SDLC_SUMMARY.md b/.github/COPILOT_SDLC_SUMMARY.md index cabdbaf9c..c6f52ac92 100644 --- a/.github/COPILOT_SDLC_SUMMARY.md +++ b/.github/COPILOT_SDLC_SUMMARY.md @@ -229,7 +229,7 @@ Copilot generates: **Response:** Context-aware guidance based on: - Copilot Instructions (.github/copilot-instructions.md) -- PRD.md project mission +- docs/getting-started/PRD.md project mission - Existing package structure - Architectural principles @@ -252,12 +252,12 @@ Copilot generates: **Context Files:** - `.github/copilot-instructions.md` - Comprehensive project guidelines -- `PRD.md` - Feature context and project mission +- `docs/getting-started/PRD.md` - Feature context and project mission - `/packages/*/seed/` - Existing patterns to follow - `prisma/schema.prisma` - Database structure **Best Practices:** -- Reference PRD when asking about features +- Reference docs/getting-started/PRD.md when asking about features - Show existing patterns when requesting new code - Ask about architectural decisions before implementing - Request declarative approaches explicitly @@ -342,9 +342,9 @@ Copilot generates: ### 3. Documentation **Files:** - `.github/workflows/README.md` - Workflow documentation -- `PRD.md` - Product requirements -- `SECURITY.md` - Security policies -- `README.md` - Project overview +- `docs/getting-started/PRD.md` - Product requirements +- `docs/security/SECURITY.md` - Security policies +- `docs/README.md` - Project overview --- diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index ce3ab7edf..d8a5249f6 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -10,6 +10,20 @@ MetaBuilder is a **data-driven, multi-tenant platform** with 95% functionality i - **Package System**: Self-contained modules in `/packages/{name}/seed/` with metadata, components, scripts - **Multi-Tenancy**: All data queries filter by `tenantId`; each tenant has isolated configurations +## 0-kickstart Operating Rules + +Follow `.github/prompts/0-kickstart.md` as the current workflow source of truth. Key rules: +- Work through `.github/prompts/` as needed; start with `0-kickstart.md`. +- Commit as you go with descriptive messages; default to trunking on `main`. +- Use `act` to diagnose GitHub workflow issues locally. +- Keep unit tests parameterized; create new test files where possible; use 1:1 source-to-test naming. +- Leave TODO comments for missing functionality. +- Check `docs/todo/` before starting. +- One lambda per file; classes only serve as containers for related lambdas (see `.github/prompts/LAMBDA_PROMPT.md`). +- Route data access through DBAL; treat it as the trusted layer. +- Design for flexibility, modularity, and containerization. +- See `docs/RADIX_TO_MUI_MIGRATION.md` for UI migration guidance. + ## Critical Patterns ### 1. API-First DBAL Development @@ -76,11 +90,43 @@ Always test scripts with `DeclarativeComponentRenderer.executeLuaScript()` ## Code Conventions +### UI Components & Styling + +**⚠️ CRITICAL: This project does NOT use Radix UI or Tailwind CSS** + +- ❌ **NEVER import from `@radix-ui/*`** - These dependencies have been removed +- ❌ **NEVER use Tailwind utility classes** in `className` props +- ✅ **ALWAYS use Material-UI** (`@mui/material`) for UI components +- ✅ **Use MUI's `sx` prop** for inline styles with theme access +- ✅ **Create `.module.scss` files** for component-specific custom styles +- ✅ **Use `@mui/icons-material`** for icons, not lucide-react or heroicons + +```tsx +// ❌ Wrong: Using Radix UI or Tailwind +import { Dialog } from '@radix-ui/react-dialog' + + +// ✅ Right: Using Material-UI +import { Dialog, Button } from '@mui/material' + +Content +``` + +**Component Mapping:** +- Radix Dialog → MUI Dialog +- Radix Select → MUI Select +- Radix Checkbox → MUI Checkbox +- Radix Switch → MUI Switch +- Tailwind classes → MUI `sx` prop or SCSS modules + +**See:** `UI_STANDARDS.md` and `docs/UI_MIGRATION.md` for complete reference + ### TypeScript/React -- Max 150 LOC per component (check `RenderComponent.tsx` ← 221 LOC is exception using recursive pattern) -- Use `@/` absolute paths and shadcn/ui from `@/components/ui` +- One lambda per file; classes are containers for related lambdas. +- Keep files small and focused; split by responsibility when they grow. +- Use `@/` absolute paths - Functional components with hooks; avoid class components -- Test files next to source: `utils.ts` + `utils.test.ts` using parameterized `it.each()` +- Test files next to source with matching names: `utils.ts` + `utils.test.ts`, using parameterized `it.each()` ### Tests All functions need coverage with parameterized tests: @@ -101,25 +147,27 @@ Run `npm run test:coverage:report` to auto-generate coverage markdown. - Queries must include `where('tenantId', currentTenant.id)` for multi-tenancy ### Styling -Tailwind only; theme in `src/index.css` with colors defined in oklch space. Font families: IBM Plex Sans (body), Space Grotesk (headings), JetBrains Mono (code). +Material-UI with SASS; theme in `src/theme/mui-theme.ts` with light/dark mode support. Font families: IBM Plex Sans (body), Space Grotesk (headings), JetBrains Mono (code). Use MUI's `sx` prop for inline styles or create `.module.scss` files for custom component styles. ## Development Checklist -**Before implementing**: Check `docs/` for relevant guides, especially `docs/architecture/5-level-system.md` for permission logic. +**Before implementing**: Check `docs/` and `docs/todo/`, and review `.github/prompts/0-kickstart.md` for current workflow rules. **During implementation**: 1. Define database schema changes first (Prisma) 2. Add seed data to `src/seed-data/` or package `/seed/` 3. Use generic renderers (`RenderComponent`) not hardcoded JSX 4. Add Lua scripts in `src/lib/lua-snippets.ts` or package `/seed/scripts/` -5. Keep components < 150 LOC -6. Add parameterized tests in `.test.ts` files +5. Keep one lambda per file and split as needed +6. Add parameterized tests in `.test.ts` files with matching names **Before commit**: - `npm run lint:fix` (fixes ESLint issues) - `npm test -- --run` (all tests pass) - `npm run test:coverage:report` (verify new functions have tests) - `npm run test:e2e` (critical workflows still work) +- Use `npm run act:diagnose` or `npm run act` when investigating CI/workflow failures +- Commit with a descriptive message on `main` unless a PR workflow is explicitly required ## Multi-Tenant Safety @@ -158,8 +206,9 @@ If fixing a DBAL bug: ❌ **Forgetting tenantId filter** → Breaks multi-tenancy ❌ **Adding fields without Prisma generate** → Type errors in DB helper ❌ **Plain JS loops over Fengari tables** → Use Lua, not TS, for Lua data -❌ **Components > 150 LOC** → Refactor to composition + `RenderComponent` +❌ **Multiple lambdas per file** → Split into single-lambda files and wrap with a class only when needed ❌ **New function without test** → `npm run test:check-functions` will fail +❌ **Missing TODO for unfinished behavior** → Leave a TODO comment where functionality is pending ## Key Files @@ -176,6 +225,6 @@ If fixing a DBAL bug: 2. Could a generic component render this instead of custom TSX? 3. Does this query filter by tenantId? 4. Could Lua handle this without code changes? -5. Is the component < 150 LOC? (If not, refactor) +5. Is this one lambda per file (and test file name matches)? 6. Does this function have a parameterized test? 7. Is this DBAL change reflected in YAML schema first? diff --git a/.github/prompts/0-kickstart.md b/.github/prompts/0-kickstart.md new file mode 100644 index 000000000..9a2690bcb --- /dev/null +++ b/.github/prompts/0-kickstart.md @@ -0,0 +1,71 @@ +# Kickstart + +Use this as the default workflow when starting work in this repo. + +## Workflow +1. Skim `docs/START_HERE.md` (if new), `docs/INDEX.md`, and relevant items in `docs/todo/`. +2. Check for scoped rules in nested `AGENTS.md` files (e.g. `dbal/AGENTS.md`) before editing those areas. +3. Use the prompts in `.github/prompts/` as needed: + - Plan: `1-plan-feature.prompt.md` + - Design: `2-design-component.prompt.md` + - Implement: `3-impl-*.prompt.md` + - Test: `4-test-*.prompt.md` + - Review: `5-review-code.prompt.md` + - Deploy: `6-deploy-*.prompt.md` + - Maintain: `7-maintain-*.prompt.md` + - Docs: `8-docs-feature.prompt.md` +4. Keep changes small and follow existing patterns; avoid dependency churn. + +## Where Work Lives +- Next.js app: `frontends/nextjs/` (source in `src/`, E2E in `e2e/`, local scripts in `scripts/`). +- Component packages: `packages/` (seed JSON under `packages/*/seed/`, optional `static_content/`, schema checks in `packages/*/tests/`). +- DBAL: `dbal/` (TypeScript library in `dbal/ts/`). +- Prisma schema/migrations: `prisma/` (`schema.prisma`, `migrations/`). +- Shared config: `config/` (symlinked into `frontends/nextjs/`). +- Repo utilities: `tools/` (quality checks, workflow helpers, code analysis). + +## Common Commands +Run app workflows from `frontends/nextjs/`: +- Install: `npm ci` (or `npm install`) +- Dev: `npm run dev` +- Build/serve: `npm run build` / `npm run start` +- Lint: `npm run lint` / `npm run lint:fix` +- Typecheck: `npm run typecheck` +- Unit: `npm run test:unit` / `npm run test:coverage` +- Function coverage: `npm run test:check-functions` +- Coverage report: `npm run test:coverage:report` +- E2E: `npm run test:e2e` +- Prisma (schema in `prisma/schema.prisma`, config in `frontends/nextjs/prisma.config.ts`): + - First-time setup: copy `.env.example` to `.env` (or ensure `DATABASE_URL` is set) + - Commands: `npm run db:generate` / `npm run db:push` / `npm run db:migrate` + - Validate: `npx prisma validate` +- Coverage output: `frontends/nextjs/coverage/` + +DBAL workflows live in `dbal/ts/` (`npm run build`, `npm run test:unit`). + +## Source + Tests +- TypeScript + ESM. Prefer `@/…` imports inside `frontends/nextjs/src/`. +- React components: `PascalCase.tsx`; hooks: `useThing.ts`; tests: `*.test.ts(x)`. +- Unit tests: `frontends/nextjs/src/**/*.test.ts(x)` and `packages/*/tests/*.test.ts`; E2E: `frontends/nextjs/e2e/`. +- Prefer one focused function (“lambda”) per file; use classes only as containers for related functions (see `.github/prompts/LAMBDA_PROMPT.md`). +- Add/adjust tests with behavior changes; keep tests deterministic (no network, stable clocks/IDs), and parameterize where it improves coverage (`it.each()`); keep source↔test naming aligned. +- Leave TODOs only when you’re explicitly deferring follow-up work (and include the next step). + +## Git Hygiene +- Commit as you go with descriptive (Conventional Commit-style) messages; default to trunk-based work on `main` unless a PR flow is required. +- If multiple agents are working, merge/rebase carefully and avoid overwriting each other’s changes. +- Before opening a PR, run `npm run lint`, `npm run typecheck`, and the relevant tests (from `frontends/nextjs/`). +- PRs should include: what/why, linked issue (if any), screenshots for UI changes, and notes on DB/schema changes. + +## Architecture Guardrails +- Prefer data-driven config (JSON/Lua) over hard-coded TS/TSX; start with `packages/*/seed/` and `docs/architecture/data-driven-architecture.md`. +- Prefer declarative UI via `RenderComponent` / generic renderers (see `docs/architecture/generic-page-system.md`). +- Route data access through DBAL / the `Database` wrapper (`frontends/nextjs/src/lib/db/` or `@/lib/db`); don’t bypass it. +- Assume multi-tenancy: include `tenantId` filtering and isolate per-tenant data. +- UI uses Material UI (`@mui/*`) and SCSS/modules as needed; don’t introduce Radix UI or Tailwind. See `docs/RADIX_TO_MUI_MIGRATION.md` and `UI_STANDARDS.md`. +- Package metadata: keep `packages/*/seed/metadata.json` `packageId` in `snake_case` and versions semver (e.g. `1.2.3`). + +## CI / Workflows +- Use `act` to reproduce and debug GitHub Actions locally (from `frontends/nextjs/`: `npm run act`, `npm run act:diagnose`; see `docs/guides/ACT_TESTING.md`). + +If you get stuck, see `.github/prompts/EEK-STUCK.md`. diff --git a/.github/prompts/1-plan-feature.prompt.md b/.github/prompts/1-plan-feature.prompt.md new file mode 100644 index 000000000..e04bfd76c --- /dev/null +++ b/.github/prompts/1-plan-feature.prompt.md @@ -0,0 +1,21 @@ +# Plan Feature Implementation + +Before implementing, analyze the feature requirements: + +1. **Check existing docs**: `docs/architecture/` for design patterns +2. **Identify affected areas**: + - Database schema changes? → `prisma/schema.prisma` + - New API/DBAL operations? → `dbal/api/schema/` + - UI components? → Use declarative `RenderComponent` + - Business logic? → Consider Lua script in `packages/*/seed/scripts/` + +3. **Multi-tenant impact**: Does this need `tenantId` filtering? + +4. **Permission level**: Which of the 5 levels can access this? + - Level 1: Public + - Level 2: User + - Level 3: Admin + - Level 4: God + - Level 5: Supergod + +5. **Create implementation checklist** with specific files to modify. diff --git a/.github/prompts/2-design-component.prompt.md b/.github/prompts/2-design-component.prompt.md new file mode 100644 index 000000000..bc58d5efb --- /dev/null +++ b/.github/prompts/2-design-component.prompt.md @@ -0,0 +1,26 @@ +# Design Component Architecture + +Design a new component or feature following MetaBuilder patterns: + +## Questions to Answer +1. Is this better as **declarative JSON** or **React TSX**? + - Prefer declarative for data-driven UIs + - Use TSX only for complex interactions + +2. Can existing packages handle this? + - Check `packages/*/seed/components.json` + +3. What's the data flow? + - Database → `Database` class → Component + - Never bypass the Database wrapper + +## Output a Design With +- Component tree structure +- Props interface +- Data dependencies +- Permission requirements +- Package location (new or existing) + +## Size Constraints +- Components: < 150 LOC +- Split large components using composition diff --git a/.github/prompts/3-impl-component.prompt.md b/.github/prompts/3-impl-component.prompt.md new file mode 100644 index 000000000..d40f93b16 --- /dev/null +++ b/.github/prompts/3-impl-component.prompt.md @@ -0,0 +1,27 @@ +# Add Declarative Component + +Add a new component using the declarative pattern (not hardcoded TSX): + +1. **Define in package** `packages/{pkg}/seed/components.json`: +```json +{ + "type": "MyComponent", + "category": "ui", + "label": "My Component", + "props": [ + { "name": "title", "type": "string", "required": true } + ], + "config": { + "layout": "vertical", + "styling": { "className": "myComponentRoot" } + } +} +``` + +Note: `styling.className` should reference a real CSS class (SCSS/modules), not Tailwind utility classes. + +2. **Register** via `DeclarativeComponentRenderer.registerComponentConfig()` + +3. **Render** using `` + +Keep components under 150 LOC. Use composition for complex UIs. diff --git a/.github/prompts/3-impl-database.prompt.md b/.github/prompts/3-impl-database.prompt.md new file mode 100644 index 000000000..47badbb98 --- /dev/null +++ b/.github/prompts/3-impl-database.prompt.md @@ -0,0 +1,22 @@ +# Database Query Pattern + +Always use the `Database` class wrapper, never raw Prisma: + +Run app commands from `frontends/nextjs/`. + +```typescript +// ✅ Correct - with tenant isolation +const users = await Database.getUsers({ tenantId: user.tenantId }) +await Database.setSchemas(schemas, { tenantId }) + +// ❌ Wrong - raw Prisma, no tenant filter +const users = await prisma.user.findMany() +``` + +After schema changes in `prisma/schema.prisma`: +```bash +npm run db:generate # Regenerate Prisma client +npm run db:push # Push to database +``` + +Key file: `frontends/nextjs/src/lib/database.ts` diff --git a/.github/prompts/3-impl-dbal-entity.prompt.md b/.github/prompts/3-impl-dbal-entity.prompt.md new file mode 100644 index 000000000..c07f6b331 --- /dev/null +++ b/.github/prompts/3-impl-dbal-entity.prompt.md @@ -0,0 +1,26 @@ +# Add DBAL Entity + +Run DBAL commands from `dbal/`. + +Add a new entity to the DBAL following the API-first approach: + +1. **Define entity** in `dbal/api/schema/entities/{name}.yaml`: +```yaml +entity: EntityName +version: "1.0" +fields: + id: { type: uuid, primary: true, generated: true } + # Add fields... +``` + +2. **Define operations** in `dbal/api/schema/operations/{name}.ops.yaml` + +3. **Generate types**: `python tools/codegen/gen_types.py` + +4. **Implement adapters** in both: + - `dbal/ts/src/adapters/` + - `dbal/cpp/src/adapters/` + +5. **Add conformance tests** in `dbal/common/contracts/{name}_tests.yaml` + +6. **Verify**: `python tools/conformance/run_all.py` diff --git a/.github/prompts/3-impl-feature.prompt.md b/.github/prompts/3-impl-feature.prompt.md new file mode 100644 index 000000000..f33dc18a5 --- /dev/null +++ b/.github/prompts/3-impl-feature.prompt.md @@ -0,0 +1,32 @@ +# Implement Feature + +Implement following MetaBuilder conventions: + +Run app commands from `frontends/nextjs/` unless a step says otherwise. + +## Implementation Order +1. **Schema first**: Update `prisma/schema.prisma` if needed + ```bash + npm run db:generate && npm run db:push + ``` + +2. **DBAL contracts**: If new entity/operation, update YAML in `dbal/api/schema/` + +3. **Database layer**: Add methods to `Database` class in `src/lib/database.ts` + +4. **Business logic**: + - Simple validation → Lua script + - Complex logic → TypeScript in `src/lib/` + +5. **UI components**: + - Declarative → `packages/*/seed/components.json` + - React → `src/components/` (< 150 LOC) + +6. **Tests**: Parameterized tests next to source files + +## Checklist +- [ ] tenantId filtering on all queries +- [ ] Permission level check +- [ ] Component under 150 LOC +- [ ] No hardcoded values (use DB/config) +- [ ] Tests with `it.each()` pattern diff --git a/.github/prompts/3-impl-lua-script.prompt.md b/.github/prompts/3-impl-lua-script.prompt.md new file mode 100644 index 000000000..8cffccf7e --- /dev/null +++ b/.github/prompts/3-impl-lua-script.prompt.md @@ -0,0 +1,36 @@ +# Write Lua Business Logic + +Add business logic as a sandboxed Lua script: + +## Create Script +Location: `packages/{pkg}/seed/scripts/` or `src/lib/lua-snippets.ts` + +```lua +-- Sandbox restrictions: NO os, io, require, loadfile +function validateInput(value) + if not value or value == "" then + return false, "Value required" + end + return true, nil +end +``` + +## Register Script +```typescript +renderer.registerLuaScript('validate_input', { + code: luaCode, + parameters: [{ name: 'value', type: 'string' }], + returnType: 'boolean' +}) +``` + +## Execute Script +```typescript +const result = await renderer.executeLuaScript('validate_input', [userInput]) +``` + +## When to Use Lua +- Validation rules +- Data transformation +- Conditional rendering logic +- Business rules that change frequently diff --git a/.github/prompts/3-impl-migration.prompt.md b/.github/prompts/3-impl-migration.prompt.md new file mode 100644 index 000000000..15ca2c898 --- /dev/null +++ b/.github/prompts/3-impl-migration.prompt.md @@ -0,0 +1,39 @@ +# Add Database Migration + +Add or modify database schema: + +Run app commands from `frontends/nextjs/` unless a step says otherwise. + +## 1. Update Schema +Edit `prisma/schema.prisma`: +```prisma +model NewEntity { + id String @id @default(cuid()) + name String + tenantId String // Required for multi-tenancy + tenant Tenant @relation(fields: [tenantId], references: [id]) + createdAt BigInt +} +``` + +## 2. Generate & Apply +```bash +npm run db:generate # Update Prisma client +npm run db:push # Push to dev database +# OR for production: +npx prisma migrate dev --name describe_change +npm run db:migrate # Apply in production +``` + +## 3. Add Database Wrapper Methods +In `src/lib/database.ts`: +```typescript +static async getNewEntities(filter: { tenantId: string }) { + return prisma.newEntity.findMany({ + where: { tenantId: filter.tenantId } + }) +} +``` + +## 4. Update DBAL (if applicable) +Add entity to `dbal/api/schema/entities/` diff --git a/.github/prompts/3-impl-package.prompt.md b/.github/prompts/3-impl-package.prompt.md new file mode 100644 index 000000000..2ddb6be86 --- /dev/null +++ b/.github/prompts/3-impl-package.prompt.md @@ -0,0 +1,28 @@ +# Create New Package + +Create a new MetaBuilder package with the standard structure: + +``` +packages/{name}/ +├── seed/ +│ ├── metadata.json # Package info, version, dependencies +│ ├── components.json # Component definitions +│ └── scripts/ # Lua scripts (optional) +├── static_content/ # Assets (optional) +└── tests/ + └── README.md +``` + +Required metadata.json format: +```json +{ + "packageId": "{name}", + "name": "Display Name", + "version": "1.0.0", + "description": "Package description", + "author": "MetaBuilder", + "category": "ui", + "dependencies": [], + "exports": { "components": [] } +} +``` diff --git a/.github/prompts/4-test-run.prompt.md b/.github/prompts/4-test-run.prompt.md new file mode 100644 index 000000000..8ae7a1174 --- /dev/null +++ b/.github/prompts/4-test-run.prompt.md @@ -0,0 +1,38 @@ +# Run All Tests + +Run app tests from `frontends/nextjs/`. Run DBAL conformance from `dbal/`. + +Execute the full test suite: + +## Unit Tests +```bash +npm run test:unit # Single run +npm run test # Watch mode +npm run test:coverage # With coverage +npm run test:coverage:report # Generate markdown report +``` + +## End-to-End Tests +```bash +npm run test:e2e # Headless +npm run test:e2e:headed # With browser +npm run test:e2e:ui # Interactive UI +``` + +## Full CI Pipeline (Local) +```bash +npm run act # Full pipeline +npm run act:diagnose # Check setup +``` + +## Specific Checks +```bash +npm run lint # ESLint +npm run typecheck # TypeScript +npm run test:check-functions # Function coverage +``` + +## DBAL Conformance (from `dbal/`) +```bash +python tools/conformance/run_all.py +``` diff --git a/.github/prompts/4-test-write.prompt.md b/.github/prompts/4-test-write.prompt.md new file mode 100644 index 000000000..49d0973a7 --- /dev/null +++ b/.github/prompts/4-test-write.prompt.md @@ -0,0 +1,26 @@ +# Write Parameterized Tests + +Run tests from `frontends/nextjs/`. + +Add tests using the parameterized `it.each()` pattern: + +```typescript +import { describe, it, expect } from 'vitest' + +describe('myFunction', () => { + it.each([ + { input: 'case1', expected: 'result1' }, + { input: 'case2', expected: 'result2' }, + { input: 'edge-case', expected: 'handled' }, + ])('should handle $input', ({ input, expected }) => { + expect(myFunction(input)).toBe(expected) + }) +}) +``` + +Place test files next to source: `utils.ts` → `utils.test.ts` + +Run tests: +- `npm test` - Watch mode +- `npm run test:unit` - Single run +- `npm run test:coverage:report` - Generate coverage markdown diff --git a/.github/prompts/5-review-code.prompt.md b/.github/prompts/5-review-code.prompt.md new file mode 100644 index 000000000..909df8cd0 --- /dev/null +++ b/.github/prompts/5-review-code.prompt.md @@ -0,0 +1,35 @@ +# Code Review Checklist + +Review code against MetaBuilder standards: + +Run checks from `frontends/nextjs/`. + +## Architecture +- [ ] No raw Prisma calls - uses `Database` class +- [ ] tenantId filter on all data queries +- [ ] Permission level enforced appropriately +- [ ] DBAL changes follow YAML-first pattern + +## Components +- [ ] Under 150 LOC (exception: recursive renderers) +- [ ] Uses declarative pattern where possible +- [ ] No hardcoded values that belong in DB +- [ ] Uses `@/` absolute imports +- [ ] Uses Material UI (`@mui/*`) and `sx`/SCSS modules (no Radix UI / Tailwind) + +## Testing +- [ ] Parameterized tests with `it.each()` +- [ ] Test file next to source (`*.test.ts`) +- [ ] Edge cases covered + +## Security +- [ ] No credentials in code +- [ ] Input validation present +- [ ] Lua scripts use sandbox (no os/io/require) + +## Run Checks +```bash +npm run lint:fix +npm run test:unit +npm run act +``` diff --git a/.github/prompts/6-deploy-ci-local.prompt.md b/.github/prompts/6-deploy-ci-local.prompt.md new file mode 100644 index 000000000..c13acd47e --- /dev/null +++ b/.github/prompts/6-deploy-ci-local.prompt.md @@ -0,0 +1,17 @@ +# Run GitHub Actions Locally + +Run from `frontends/nextjs/`. + +Run the full CI pipeline locally using act to validate changes before pushing. + +```bash +npm run act +``` + +If specific jobs fail, debug with: +- `npm run act:lint` - ESLint only +- `npm run act:typecheck` - TypeScript validation +- `npm run act:build` - Production build +- `npm run act:e2e` - End-to-end tests + +Use `npm run act:diagnose` to check setup issues without Docker. diff --git a/.github/prompts/6-deploy-production.prompt.md b/.github/prompts/6-deploy-production.prompt.md new file mode 100644 index 000000000..6864f65f4 --- /dev/null +++ b/.github/prompts/6-deploy-production.prompt.md @@ -0,0 +1,35 @@ +# Deploy Application + +Deploy MetaBuilder to production: + +## Pre-Deployment Checks (from `frontends/nextjs/`) +```bash +npm run act # Full CI locally +npm run build # Verify build succeeds +npm run typecheck # No type errors +``` + +## Docker Deployment (from repo root) +```bash +# Development +docker-compose -f deployment/docker-compose.development.yml up + +# Production +docker-compose -f deployment/docker-compose.production.yml up -d +``` + +## Database Migration (from `frontends/nextjs/`) +```bash +npm run db:migrate # Apply migrations +``` + +## Environment Variables +Required in production: +- `DATABASE_URL` - Database connection string +- `NODE_ENV=production` + +## Post-Deployment +1. Verify health endpoints +2. Check logs for errors +3. Test critical user flows +4. Monitor tenant isolation working correctly diff --git a/.github/prompts/7-maintain-debug.prompt.md b/.github/prompts/7-maintain-debug.prompt.md new file mode 100644 index 000000000..3848348df --- /dev/null +++ b/.github/prompts/7-maintain-debug.prompt.md @@ -0,0 +1,44 @@ +# Debug Issue + +Systematic debugging approach for MetaBuilder: + +Run app commands from `frontends/nextjs/`. Run DBAL conformance from `dbal/`. + +## 1. Identify Layer +- **UI**: Check browser console, React DevTools +- **API/Data**: Check `Database` class calls +- **DBAL**: Check YAML schema matches implementation +- **Lua**: Check sandbox execution logs + +## 2. Common Issues + +### "Cannot read property" in component +→ Check if data query includes `tenantId` + +### Type errors after schema change +```bash +npm run db:generate # Regenerate Prisma types +``` + +### DBAL TypeScript/C++ divergence +```bash +python tools/conformance/run_all.py # Find which test fails +``` + +### Lua script fails silently +→ Check for forbidden APIs: `os`, `io`, `require`, `loadfile` + +## 3. Logging +```typescript +// Database queries +console.log('[DB]', query, { tenantId }) + +// Lua execution +const result = await renderer.executeLuaScript(id, params) +console.log('[Lua]', { result, logs: result.logs }) +``` + +## 4. Test in Isolation +```bash +npm run test:unit -- path/to/test.ts +``` diff --git a/.github/prompts/7-maintain-performance.prompt.md b/.github/prompts/7-maintain-performance.prompt.md new file mode 100644 index 000000000..c027a2de4 --- /dev/null +++ b/.github/prompts/7-maintain-performance.prompt.md @@ -0,0 +1,46 @@ +# Performance Optimization + +Optimize MetaBuilder performance: + +Run performance scripts from `frontends/nextjs/` after `npm run build` (requires `tsx` via `npx`). + +## Identify Bottlenecks +```bash +npx tsx ../../tools/analyze-render-performance.ts +npx tsx ../../tools/analyze-bundle-size.ts +npx tsx ../../tools/check-performance-budget.ts +``` + +## Common Optimizations + +### 1. Database Queries +```typescript +// ❌ N+1 query +for (const user of users) { + const tenant = await Database.getTenant(user.tenantId) +} + +// ✅ Batch query +const users = await Database.getUsersWithTenants({ tenantId }) +``` + +### 2. Component Rendering +```tsx +// ❌ Re-renders on every parent render +function List({ items }) { + return items.map(item => ) +} + +// ✅ Memoized +const MemoizedItem = React.memo(Item) +function List({ items }) { + return items.map(item => ) +} +``` + +### 3. Bundle Size +- Use dynamic imports for large components +- Check `docs/reports/size-limits-report.json` + +### 4. Lua Script Caching +Scripts are compiled once - avoid registering repeatedly diff --git a/.github/prompts/7-maintain-refactor.prompt.md b/.github/prompts/7-maintain-refactor.prompt.md new file mode 100644 index 000000000..b09ae4cc1 --- /dev/null +++ b/.github/prompts/7-maintain-refactor.prompt.md @@ -0,0 +1,54 @@ +# Refactor Large Component + +Break down a component exceeding 150 LOC: + +## 1. Identify Split Points +- Separate data fetching from rendering +- Extract repeated patterns into sub-components +- Move business logic to Lua or utility functions + +## 2. Refactoring Patterns + +### Extract Child Components +```tsx +// Before: 200 LOC monolith +function BigComponent() { /* everything */ } + +// After: Composed +function BigComponent() { + return ( + +
+ +