@revealui/harnesses 0.1.0 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,2537 @@
1
+ // src/content/index.ts
2
+ import { readFileSync } from "fs";
3
+ import { join, resolve } from "path";
4
+
5
+ // src/content/definitions/agents/builder.ts
6
+ var builderAgent = {
7
+ id: "builder",
8
+ tier: "oss",
9
+ name: "Builder",
10
+ description: "Builds and typechecks packages in isolation",
11
+ isolation: "worktree",
12
+ tools: [],
13
+ content: `You are a build agent for the RevealUI monorepo.
14
+
15
+ ## Setup
16
+ Run \`pnpm install\` first to establish symlinks in this worktree.
17
+
18
+ ## Tasks
19
+ - Build specified package(s): \`pnpm --filter <package> build\`
20
+ - Typecheck specified package(s): \`pnpm --filter <package> typecheck\`
21
+ - Full build: \`pnpm build\`
22
+ - Full typecheck: \`pnpm typecheck:all\`
23
+
24
+ ## Rules
25
+ - Report errors clearly with file paths and line numbers
26
+ - Do NOT modify source code \u2014 only build and report
27
+ - If a build fails, identify the root cause and report it`
28
+ };
29
+
30
+ // src/content/definitions/agents/docs-sync.ts
31
+ var docsSyncAgent = {
32
+ id: "docs-sync",
33
+ tier: "pro",
34
+ name: "Docs Sync",
35
+ description: "Checks documentation freshness against code changes to prevent doc drift",
36
+ isolation: "worktree",
37
+ tools: [],
38
+ content: `You are a documentation sync checker for the RevealUI monorepo.
39
+
40
+ ## Purpose
41
+
42
+ Detect documentation drift \u2014 places where code has changed but docs haven't been updated.
43
+
44
+ ## Checks
45
+
46
+ ### 1. API Route \u2194 OpenAPI Spec
47
+ - Compare \`apps/api/src/routes/\` route handlers against \`packages/openapi/\` spec
48
+ - Flag routes that exist in code but not in spec (or vice versa)
49
+ - Check that request/response schemas match \`@revealui/contracts\`
50
+
51
+ ### 2. Package Exports \u2194 Docs Site
52
+ - Compare \`packages/*/src/index.ts\` exports against \`apps/docs/\` documentation
53
+ - Flag exported functions/types that have no corresponding doc page
54
+ - Check that documented APIs still exist in the package
55
+
56
+ ### 3. CLI Commands \u2194 CLI Docs
57
+ - Compare \`packages/cli/src/\` commands against docs site CLI reference
58
+ - Flag undocumented commands or removed commands still in docs
59
+
60
+ ### 4. Collection Fields \u2194 CMS Docs
61
+ - Compare \`apps/cms/src/collections/\` field definitions against any collection docs
62
+ - Flag field additions/removals not reflected in documentation
63
+
64
+ ### 5. Environment Variables
65
+ - Compare env vars used in code (\`process.env.*\`, \`config.*\`) against:
66
+ - \`.env.example\` files
67
+ - Setup documentation
68
+ - Deployment docs
69
+
70
+ ### 6. CLAUDE.md Accuracy
71
+ - Verify package counts, table counts, and other metrics in CLAUDE.md
72
+ - Check that listed commands still work
73
+ - Verify port numbers match actual app configs
74
+
75
+ ## Output Format
76
+
77
+ Report findings as a table:
78
+
79
+ | Priority | Area | Issue | File(s) |
80
+ |----------|------|-------|---------|
81
+ | HIGH | API routes | POST /api/tickets not in OpenAPI spec | apps/api/src/routes/tickets.ts |
82
+ | MEDIUM | Package exports | \`createSession\` exported but undocumented | packages/auth/src/index.ts |
83
+
84
+ ## Rules
85
+ - Do NOT modify any files \u2014 report only
86
+ - Focus on high-priority drift (new features, changed APIs)
87
+ - Ignore internal/private APIs not intended for external docs
88
+ - Check git log for recently changed files to prioritise review`
89
+ };
90
+
91
+ // src/content/definitions/agents/gate-runner.ts
92
+ var gateRunnerAgent = {
93
+ id: "gate-runner",
94
+ tier: "pro",
95
+ name: "Gate Runner",
96
+ description: "Runs the full CI gate in isolation",
97
+ isolation: "worktree",
98
+ tools: [],
99
+ content: `You are a CI gate agent for the RevealUI monorepo.
100
+
101
+ ## Setup
102
+ Run \`pnpm install\` first to establish symlinks in this worktree.
103
+
104
+ ## Tasks
105
+ - Full gate: \`pnpm gate\`
106
+ - Quick gate (phase 1 only): \`pnpm gate:quick\`
107
+ - Gate without build: \`pnpm gate --no-build\`
108
+
109
+ ## Gate Phases
110
+ 1. **Quality** (parallel): Biome lint (hard fail), audits (warn)
111
+ 2. **Type checking** (serial): \`pnpm -r typecheck\` across all packages
112
+ 3. **Test + Build** (parallel): Vitest (warn), turbo build (hard fail)
113
+
114
+ ## Rules
115
+ - Report which phase failed and the specific error(s)
116
+ - Biome, typecheck, and build are hard failures \u2014 must be fixed
117
+ - Tests are warn-only \u2014 report but don't block
118
+ - Do NOT modify source code \u2014 only run the gate and report`
119
+ };
120
+
121
+ // src/content/definitions/agents/linter.ts
122
+ var linterAgent = {
123
+ id: "linter",
124
+ tier: "oss",
125
+ name: "Linter",
126
+ description: "Lint and format code in isolation",
127
+ isolation: "worktree",
128
+ tools: [],
129
+ content: `You are a lint/format agent for the RevealUI monorepo.
130
+
131
+ ## Setup
132
+ Run \`pnpm install\` first to establish symlinks in this worktree.
133
+
134
+ ## Tasks
135
+ - Biome check: \`biome check .\`
136
+ - Biome fix: \`biome check --write .\`
137
+ - Full lint: \`pnpm lint\`
138
+ - Auto-fix: \`pnpm lint:fix\`
139
+ - Format: \`pnpm format\`
140
+
141
+ ## Rules
142
+ - Biome is the sole linter \u2014 fix all Biome errors
143
+ - Follow the unused declarations policy in \`.claude/rules/unused-declarations.md\`
144
+ - Report remaining warnings that cannot be auto-fixed
145
+ - Do NOT suppress lint rules without justification`
146
+ };
147
+
148
+ // src/content/definitions/agents/security-reviewer.ts
149
+ var securityReviewerAgent = {
150
+ id: "security-reviewer",
151
+ tier: "pro",
152
+ name: "Security Reviewer",
153
+ description: "Reviews code for security vulnerabilities, hardcoded secrets, and auth issues",
154
+ isolation: "worktree",
155
+ tools: [],
156
+ content: `You are a security reviewer for the RevealUI monorepo (Business Operating System Software).
157
+
158
+ ## Scope
159
+
160
+ Audit the codebase for security issues across these categories:
161
+
162
+ ### 1. Hardcoded Secrets
163
+ - API keys, tokens, passwords in source code (not .env files)
164
+ - Credentials in test fixtures that look production-like
165
+ - Base64-encoded secrets or obfuscated credentials
166
+
167
+ ### 2. Auth & Session Security
168
+ - Session cookie configuration (httpOnly, secure, sameSite, domain)
169
+ - Password hashing (must use bcrypt, never plaintext)
170
+ - Rate limiting on auth endpoints
171
+ - Brute force protection bypass paths
172
+
173
+ ### 3. Input Validation
174
+ - SQL injection via raw queries (should use Drizzle ORM parameterised queries)
175
+ - XSS in rendered content (especially Lexical rich text output)
176
+ - Path traversal in file upload/serve paths
177
+ - SSRF in user-provided URLs
178
+
179
+ ### 4. RBAC/ABAC Policy
180
+ - Missing access control checks on API routes
181
+ - Privilege escalation paths (user \u2192 admin)
182
+ - Tenant isolation (multi-site data leakage)
183
+
184
+ ### 5. CSP & Headers
185
+ - Content-Security-Policy completeness
186
+ - CORS misconfiguration (check allowed origins)
187
+ - Missing security headers (HSTS, X-Frame-Options, etc.)
188
+
189
+ ### 6. Dependency Security
190
+ - Known vulnerabilities in direct dependencies
191
+ - Supabase boundary violations (imports outside permitted paths)
192
+
193
+ ## Architecture Context
194
+
195
+ - **Auth**: Session-only (no JWT). \`revealui-session\` cookie across \`.revealui.com\`.
196
+ - **Dual-DB**: NeonDB (REST content) + Supabase (vectors/auth). Strict import boundary.
197
+ - **Tiers**: free, pro, max, enterprise. License checks via \`isLicensed()\`.
198
+ - **API**: Hono on port 3004. CMS calls API cross-origin (CORS configured).
199
+
200
+ ## Rules
201
+ - Use AST-based analysis over regex for code-shape checks (see .claude/rules/code-analysis-policy.md)
202
+ - Report findings with severity (critical/high/medium/low), file path, and line number
203
+ - Suggest specific fixes, not just descriptions
204
+ - Do NOT modify source code \u2014 report only
205
+ - Prioritise critical and high severity findings`
206
+ };
207
+
208
+ // src/content/definitions/agents/tester.ts
209
+ var testerAgent = {
210
+ id: "tester",
211
+ tier: "oss",
212
+ name: "Tester",
213
+ description: "Runs tests for packages in isolation",
214
+ isolation: "worktree",
215
+ tools: [],
216
+ content: `You are a test agent for the RevealUI monorepo.
217
+
218
+ ## Setup
219
+ Run \`pnpm install\` first to establish symlinks in this worktree.
220
+
221
+ ## Tasks
222
+ - Test specified package(s): \`pnpm --filter <package> test\`
223
+ - Test with coverage: \`pnpm --filter <package> test:coverage\`
224
+ - Full test suite: \`pnpm test\`
225
+ - Integration tests: \`pnpm test:integration\`
226
+
227
+ ## Rules
228
+ - Report test failures with file paths, test names, and error messages
229
+ - Do NOT modify source code \u2014 only test and report
230
+ - If tests fail, identify the root cause and suggest fixes
231
+ - Report coverage numbers when running with coverage`
232
+ };
233
+
234
+ // src/content/definitions/agents/index.ts
235
+ var agents = [
236
+ builderAgent,
237
+ docsSyncAgent,
238
+ gateRunnerAgent,
239
+ linterAgent,
240
+ securityReviewerAgent,
241
+ testerAgent
242
+ ];
243
+
244
+ // src/content/definitions/commands/audit.ts
245
+ var auditCommand = {
246
+ id: "audit",
247
+ tier: "oss",
248
+ name: "Audit",
249
+ description: "Audit the codebase for avoidable `any` types and production console statements. Use when asked to check code quality, before a release, or after a large refactor.",
250
+ disableModelInvocation: false,
251
+ content: `Run code quality audits on the RevealUI monorepo.
252
+
253
+ Execute these audit commands in sequence:
254
+
255
+ 1. \`pnpm audit:any\` \u2014 Find avoidable \`any\` types across the codebase
256
+ 2. \`pnpm audit:console\` \u2014 Find production \`console.*\` statements that should use the logger
257
+
258
+ Report findings as a summary table with package name and count. If issues are found, suggest fixes.
259
+
260
+ Target: 0 avoidable \`any\` types, 0 production console statements.`
261
+ };
262
+
263
+ // src/content/definitions/commands/gate.ts
264
+ var gateCommand = {
265
+ id: "gate",
266
+ tier: "oss",
267
+ name: "Gate",
268
+ description: "Run the full CI gate (Biome lint, typecheck, Vitest, turbo build) before pushing. Only invoke when explicitly asked to run the gate or verify before a push.",
269
+ disableModelInvocation: true,
270
+ content: `Run the CI gate to validate the monorepo before pushing.
271
+
272
+ Execute \`pnpm gate\` in the RevealUI monorepo root. This runs the full CI pipeline:
273
+ 1. Biome lint check
274
+ 2. TypeScript type checking across all packages
275
+ 3. Vitest test suite
276
+ 4. Turbo build
277
+
278
+ If the full gate takes too long, run \`pnpm gate:quick\` for phase 1 only (lint + typecheck).
279
+
280
+ Report any failures with the specific package and error details.`
281
+ };
282
+
283
+ // src/content/definitions/commands/new-package.ts
284
+ var newPackageCommand = {
285
+ id: "new-package",
286
+ tier: "oss",
287
+ name: "New Package",
288
+ description: "Scaffold a new @revealui/* package with package.json, tsconfig.json, tsup.config.ts, and src/index.ts. Only invoke when explicitly asked to create a new package.",
289
+ disableModelInvocation: true,
290
+ argumentHint: "<package-name>",
291
+ content: `Scaffold a new package in the RevealUI monorepo.
292
+
293
+ Arguments: $ARGUMENTS (package name, e.g., "analytics")
294
+
295
+ Create the following structure at \`packages/<name>/\`:
296
+
297
+ 1. \`package.json\` with:
298
+ - name: \`@revealui/<name>\`
299
+ - version: \`0.1.0\`
300
+ - type: \`module\`
301
+ - exports, main, types pointing to \`dist/\`
302
+ - scripts: build, dev, lint, test, typecheck
303
+ - publishConfig.access: \`public\` (or \`"private": true\` for Pro packages)
304
+ - engines.node: \`>=24.13.0\`
305
+
306
+ 2. \`tsconfig.json\` extending \`@revealui/dev/tsconfig\`
307
+
308
+ 3. \`tsup.config.ts\` with entry \`src/index.ts\`, dts, format esm
309
+
310
+ 4. \`src/index.ts\` with a placeholder export
311
+
312
+ 5. \`README.md\` with package name and description
313
+
314
+ After scaffolding, remind the user to:
315
+ - Run \`pnpm install\` to link the new package
316
+ - Add \`workspace:*\` references from consuming packages
317
+ - Create a changeset with \`pnpm changeset\``
318
+ };
319
+
320
+ // src/content/definitions/commands/stripe-best-practices.ts
321
+ var stripeBestPracticesCommand = {
322
+ id: "stripe-best-practices",
323
+ tier: "pro",
324
+ name: "Stripe Best Practices",
325
+ description: "Apply when working on Stripe billing, payments, webhooks, subscriptions, or checkout flows (apps/api/src/routes/billing.ts, packages/services).",
326
+ disableModelInvocation: false,
327
+ content: `Apply Stripe best practices when implementing or reviewing payment code in this project:
328
+
329
+ ## Webhook Handling
330
+ - Always verify webhook signatures using \`stripe.webhooks.constructEvent()\` with the raw request body (never parsed JSON)
331
+ - Use idempotency keys for all mutating API calls (charges, subscriptions, refunds)
332
+ - Return 200 immediately after signature verification; process asynchronously if needed
333
+ - Handle all relevant events: \`checkout.session.completed\`, \`customer.subscription.deleted\`, \`customer.subscription.updated\`, \`invoice.payment_failed\`
334
+
335
+ ## Subscription Management
336
+ - Store \`customer.id\`, \`subscription.id\`, and \`subscription.status\` in your DB \u2014 not just price/product IDs
337
+ - Use \`subscription.status\` to gate access: only \`active\` and \`trialing\` grant access
338
+ - Handle \`past_due\` gracefully \u2014 show dunning UI, don't immediately revoke access
339
+ - Use \`cancel_at_period_end: true\` for user-initiated cancellations (preserves access until period end)
340
+
341
+ ## Checkout & Billing Portal
342
+ - Use \`metadata\` on checkout sessions to pass internal IDs (userId, planId) through to webhooks
343
+ - Always set \`client_reference_id\` to your internal user ID
344
+ - Use Stripe Billing Portal for plan changes and cancellations \u2014 don't build your own
345
+
346
+ ## Security
347
+ - Never log full Stripe objects \u2014 they may contain PII
348
+ - Never expose secret keys client-side; all Stripe API calls must be server-side
349
+ - Use restricted API keys scoped to minimum permissions for each service
350
+ - Validate that webhook events reference resources owned by your users before acting
351
+
352
+ ## Error Handling
353
+ - Retry on \`rate_limit_error\` and network errors with exponential backoff
354
+ - On \`card_error\` and \`invalid_request_error\`, surface Stripe's \`message\` to the user (it's user-safe)
355
+ - Log \`stripe_error\` codes for debugging; never expose raw error objects to clients
356
+
357
+ ## RevealUI-Specific
358
+ - Webhook endpoint: \`apps/cms\` at \`/api/webhooks/stripe\` (NOT the API endpoint)
359
+ - Stripe service: \`packages/services/src/stripe/\`
360
+ - Billing routes: \`apps/api/src/routes/billing.ts\`
361
+ - Price IDs are managed via \`pnpm stripe:seed\` \u2014 see \`scripts/setup/seed-stripe.ts\``
362
+ };
363
+
364
+ // src/content/definitions/commands/index.ts
365
+ var commands = [
366
+ auditCommand,
367
+ gateCommand,
368
+ newPackageCommand,
369
+ stripeBestPracticesCommand
370
+ ];
371
+
372
+ // src/content/definitions/preambles/index.ts
373
+ var preambles = [
374
+ {
375
+ tier: 1,
376
+ name: "Identity",
377
+ description: "Always injected \u2014 core project identity and structure",
378
+ ruleIds: ["monorepo"]
379
+ },
380
+ {
381
+ tier: 2,
382
+ name: "Architecture",
383
+ description: "Project-wide technical context \u2014 database, styling, formatting, config patterns",
384
+ ruleIds: ["database", "biome", "tailwind", "parameterization"]
385
+ },
386
+ {
387
+ tier: 3,
388
+ name: "Domain",
389
+ description: "Feature-area specific policies \u2014 analysis standards, code hygiene",
390
+ ruleIds: ["code-analysis-policy", "unused-declarations"]
391
+ },
392
+ {
393
+ tier: 4,
394
+ name: "Task",
395
+ description: "Injected per-operation \u2014 skill routing, agent dispatch",
396
+ ruleIds: ["skills-usage", "agent-dispatch"]
397
+ }
398
+ ];
399
+
400
+ // src/content/definitions/rules/agent-dispatch.ts
401
+ var agentDispatchRule = {
402
+ id: "agent-dispatch",
403
+ tier: "pro",
404
+ name: "Agent Profile Dispatch",
405
+ description: "When to spawn specialized agent profiles from .claude/agents/",
406
+ scope: "project",
407
+ preambleTier: 4,
408
+ tags: ["agents", "coordination"],
409
+ content: `# Agent Profile Dispatch
410
+
411
+ Profiles live in \`.claude/agents/\`. Spawn them via the Agent tool when a task is
412
+ too large or specialized for the current session.
413
+
414
+ ## Profiles
415
+
416
+ | Profile | When to spawn |
417
+ |---------|--------------|
418
+ | \`gate-runner\` | Running the full CI gate (\`pnpm gate\`), verifying the repo is clean before a push or release |
419
+ | \`security-reviewer\` | Auditing auth flows, reviewing security-sensitive PRs, checking new API routes for vulnerabilities |
420
+ | \`builder\` | Large feature implementation spanning multiple packages that would pollute the current session context |
421
+ | \`tester\` | Writing test suites, achieving coverage targets, fixing batches of failing tests |
422
+ | \`docs-sync\` | Updating public docs, syncing API reference, writing changelogs, keeping MASTER_PLAN in sync |
423
+ | \`linter\` | Bulk lint fixes, unused declaration sweeps, \`any\` type removal, Biome cleanup across the monorepo |
424
+
425
+ ## Rules
426
+
427
+ 1. Don't spawn a profile for work that takes under 15 minutes in the current session.
428
+ 2. Check the workboard before spawning \u2014 another agent may already own that area.
429
+ 3. Always give spawned agents:
430
+ - Current phase from \`~/projects/revealui-jv/docs/MASTER_PLAN.md\`
431
+ - Relevant workboard state
432
+ - The specific task and acceptance criteria
433
+ 4. Spawned agents report findings back to the parent. Only the parent updates MASTER_PLAN.md.
434
+ 5. Spawned agents must not create plan files outside MASTER_PLAN.md (see \`planning.md\`).`
435
+ };
436
+
437
+ // src/content/definitions/rules/biome.ts
438
+ var biomeRule = {
439
+ id: "biome",
440
+ tier: "oss",
441
+ name: "Biome Conventions",
442
+ description: "Biome 2 linter/formatter rules and suppression protocol",
443
+ scope: "project",
444
+ preambleTier: 2,
445
+ tags: ["lint", "format", "quality"],
446
+ content: `# Biome Conventions
447
+
448
+ ## Overview
449
+
450
+ Biome 2 is the sole linter and formatter for this monorepo.
451
+
452
+ ## Commands
453
+
454
+ - \`pnpm lint\` \u2014 check all files with Biome (\`biome check .\`)
455
+ - \`pnpm format\` \u2014 format all files with Biome (\`biome format --write .\`)
456
+ - \`pnpm lint:fix\` \u2014 auto-fix with Biome (\`biome check --write .\`)
457
+ - \`biome check .\` \u2014 lint + format check (per-package)
458
+ - \`biome check --write .\` \u2014 auto-fix (used by lint-staged)
459
+
460
+ ## Lint-Staged
461
+
462
+ Pre-commit hook runs \`biome check --write\` on staged \`*.{ts,tsx,js,jsx}\` files via Husky + lint-staged.
463
+
464
+ ## Key Rules
465
+
466
+ - No unused variables or imports (auto-removed on format)
467
+ - No \`console.*\` in production code (use \`@revealui/utils\` logger instead)
468
+ - No \`any\` types (use \`unknown\` + type guards)
469
+ - Consistent import ordering (auto-sorted)
470
+ - Single quotes for strings
471
+ - Trailing commas
472
+ - Semicolons always
473
+ - 2-space indentation (tabs in Biome config, spaces in output)
474
+
475
+ ## Suppressing Rules
476
+
477
+ - Use \`// biome-ignore <rule>: <reason>\` for specific lines
478
+ - Avoid blanket suppressions \u2014 prefer fixing the code
479
+ - Document why a suppression is needed in the comment
480
+
481
+ ## Unused Variables \u2014 Special Protocol
482
+
483
+ **Before suppressing any unused variable or import warning, read \`.claude/rules/unused-declarations.md\`.**
484
+
485
+ The mandatory decision tree there must be followed. Unused declarations frequently indicate incomplete implementations that need to be finished, not suppressed. Silencing the warning without completing the code creates permanent dead stubs.
486
+
487
+ TL;DR: implement first, suppress only as a last resort.`
488
+ };
489
+
490
+ // src/content/definitions/rules/code-analysis-policy.ts
491
+ var codeAnalysisPolicyRule = {
492
+ id: "code-analysis-policy",
493
+ tier: "oss",
494
+ name: "Code Analysis Policy",
495
+ description: "Prefer AST-based analysis over regex for security and architecture checks",
496
+ scope: "project",
497
+ preambleTier: 3,
498
+ tags: ["security", "analysis"],
499
+ content: `# Code Analysis Policy
500
+
501
+ Use AST-based or structural analysis for code-policy and security checks whenever the rule depends on syntax, identifiers, or code shape.
502
+
503
+ ## Prefer AST-Based Analysis For
504
+
505
+ - security gate checks over application code
506
+ - architecture and boundary rules
507
+ - auth/password handling checks
508
+ - response/body serialization checks
509
+ - import-policy enforcement beyond simple path inventory
510
+
511
+ ## Regex Is Acceptable Only For
512
+
513
+ - broad inventory scans over raw text
514
+ - committed secret patterns
515
+ - literal token/URL/key detection
516
+ - quick warning-level heuristics that are explicitly marked approximate
517
+
518
+ ## Do Not Use Regex As Source Of Truth For
519
+
520
+ - whether a value is stored in plaintext
521
+ - whether a secret is hardcoded in executable code
522
+ - whether a boundary rule is violated by code structure
523
+ - whether a security-sensitive value reaches a sink
524
+
525
+ ## Working Rule
526
+
527
+ If a check can be expressed against the TypeScript/JavaScript AST with reasonable effort, use AST analysis first.
528
+
529
+ If regex is still used:
530
+
531
+ - document it as heuristic-only
532
+ - keep it warning-level unless independently verified
533
+ - add a follow-up to migrate it to AST/structural analysis`
534
+ };
535
+
536
+ // src/content/definitions/rules/database.ts
537
+ var databaseRule = {
538
+ id: "database",
539
+ tier: "oss",
540
+ name: "Database Conventions",
541
+ description: "Dual-database architecture (NeonDB + Supabase) boundaries and query patterns",
542
+ scope: "project",
543
+ preambleTier: 2,
544
+ tags: ["database", "architecture", "drizzle"],
545
+ content: `# Database Conventions
546
+
547
+ ## Dual-Database Architecture
548
+
549
+ RevealUI uses **two databases with strictly separated responsibilities**:
550
+
551
+ | Database | Client | Purpose |
552
+ |----------|--------|---------|
553
+ | **NeonDB** (PostgreSQL) | \`@neondatabase/serverless\` | REST content: collections, users, sessions, orders, products |
554
+ | **Supabase** | \`@supabase/supabase-js\` | Vector embeddings, real-time auth, AI memory storage |
555
+
556
+ ## Boundary Rule
557
+
558
+ **\`@supabase/supabase-js\` must only be imported inside designated vector/auth modules:**
559
+
560
+ ### Allowed paths for Supabase imports
561
+ - \`packages/db/src/vector/\` \u2014 vector schema and queries
562
+ - \`packages/db/src/auth/\` \u2014 Supabase auth helpers
563
+ - \`packages/auth/src/\` \u2014 authentication implementation
564
+ - \`packages/ai/src/\` \u2014 AI memory and embedding storage
565
+ - \`packages/services/src/supabase/\` \u2014 Supabase service integrations
566
+ - \`apps/*/src/lib/supabase/\` \u2014 app-level Supabase utilities
567
+
568
+ ### Forbidden: Supabase imports in
569
+ - \`packages/core/\` \u2014 CMS engine must be DB-agnostic
570
+ - \`packages/contracts/\` \u2014 contracts are schema-only
571
+ - \`packages/config/\` \u2014 config must not hardcode DB client
572
+ - \`apps/cms/src/collections/\` \u2014 collection hooks use Drizzle/Neon only
573
+ - \`apps/cms/src/routes/\` \u2014 REST routes use Neon only
574
+
575
+ ## Schema Organization
576
+
577
+ \`\`\`
578
+ packages/db/src/schema/
579
+ \u251C\u2500\u2500 accounts.ts # NeonDB: user accounts
580
+ \u251C\u2500\u2500 agents.ts # NeonDB: AI agent definitions
581
+ \u251C\u2500\u2500 api-keys.ts # NeonDB: API key management
582
+ \u251C\u2500\u2500 cms.ts # NeonDB: CMS collections, media
583
+ \u251C\u2500\u2500 gdpr.ts # NeonDB: GDPR consent, deletion
584
+ \u251C\u2500\u2500 licenses.ts # NeonDB: license keys, tiers
585
+ \u251C\u2500\u2500 pages.ts # NeonDB: pages, navigation
586
+ \u251C\u2500\u2500 sites.ts # NeonDB: multi-tenant sites
587
+ \u251C\u2500\u2500 tickets.ts # NeonDB: support tickets
588
+ \u251C\u2500\u2500 users.ts # NeonDB: user management, sessions
589
+ \u251C\u2500\u2500 vector.ts # Supabase: embeddings, AI memory
590
+ \u251C\u2500\u2500 rest.ts # NeonDB: REST schema barrel
591
+ \u251C\u2500\u2500 index.ts # Combined schema export
592
+ \u2514\u2500\u2500 ... # 30+ schema files total
593
+ \`\`\`
594
+
595
+ ## Query Patterns
596
+
597
+ ### NeonDB (Drizzle ORM)
598
+ \`\`\`ts
599
+ import { db } from '@revealui/db'
600
+ import { posts } from '@revealui/db/schema'
601
+
602
+ const results = await db.select().from(posts).where(eq(posts.status, 'published'))
603
+ \`\`\`
604
+
605
+ ### Supabase (vector/auth only)
606
+ \`\`\`ts
607
+ // Only in designated modules (packages/db/src/vector/, packages/ai/src/)
608
+ import { createSupabaseClient } from '@revealui/db/vector'
609
+
610
+ const { data } = await supabase.rpc('match_documents', { query_embedding: embedding })
611
+ \`\`\`
612
+
613
+ ## Enforcement
614
+
615
+ The \`pnpm validate:structure\` script checks for Supabase imports outside permitted paths.
616
+ CI runs this as part of phase 1 (warn-only \u2014 violations are flagged but don't block builds).
617
+
618
+ To check locally:
619
+ \`\`\`bash
620
+ pnpm validate:structure
621
+ \`\`\`
622
+
623
+ ## Migration Guidance
624
+
625
+ When adding new features:
626
+ 1. **Content/REST data** \u2192 add to \`packages/db/src/schema/\` + use Drizzle
627
+ 2. **AI/vector data** \u2192 add to \`packages/db/src/vector/\` + use Supabase client
628
+ 3. **Never mix** both DB clients in the same module`
629
+ };
630
+
631
+ // src/content/definitions/rules/monorepo.ts
632
+ var monorepoRule = {
633
+ id: "monorepo",
634
+ tier: "oss",
635
+ name: "Monorepo Conventions",
636
+ description: "pnpm workspace, Turborepo, package structure, and publishing conventions",
637
+ scope: "project",
638
+ preambleTier: 1,
639
+ tags: ["monorepo", "pnpm", "turborepo"],
640
+ content: `# Monorepo Conventions
641
+
642
+ ## Structure
643
+ - Apps live in \`apps/\` \u2014 deployable services (Next.js, Hono, Vite)
644
+ - Packages live in \`packages/\` \u2014 shared libraries consumed by apps
645
+ - Scripts live in \`scripts/\` \u2014 CLI tools, automation, CI gates
646
+
647
+ ## Package Manager
648
+ - pnpm 10 with workspace protocol
649
+ - Internal deps use \`workspace:*\` (never hardcoded versions)
650
+ - Run \`pnpm install:clean\` (suppresses Node deprecation warnings)
651
+ - \`preinstall\` script enforces pnpm-only (\`npx only-allow pnpm\`)
652
+
653
+ ## Turborepo
654
+ - \`turbo run build --parallel\` for parallel builds
655
+ - \`turbo run test --concurrency=15\` for parallel tests
656
+ - Package-level \`turbo.json\` for task overrides (rare)
657
+ - Cache stored in \`.turbo/\` (gitignored)
658
+
659
+ ## Package Conventions
660
+ - Every package has: \`build\`, \`dev\`, \`lint\`, \`test\`, \`typecheck\` scripts
661
+ - Build output goes to \`dist/\` via tsup
662
+ - Source in \`src/\`, tests in \`src/__tests__/\` or \`__tests__/\`
663
+ - Entry point: \`src/index.ts\` \u2192 \`dist/index.js\`
664
+ - Use \`exports\` field in package.json for subpath exports
665
+ - Include \`files: ["dist", "README.md"]\` for publishing
666
+
667
+ ## Dependency Rules
668
+ - Use \`syncpack\` for version alignment (\`pnpm deps:check\`, \`pnpm deps:fix\`)
669
+ - Use \`catalog:\` for shared devDependencies (e.g., \`"zod": "catalog:"\`)
670
+ - pnpm overrides in root package.json for security patches
671
+ - \`onlyBuiltDependencies\` whitelist for native modules
672
+
673
+ ## CI Gate
674
+ - \`pnpm gate\` runs the full CI pipeline locally: lint \u2192 typecheck \u2192 test \u2192 build
675
+ - \`pnpm gate:quick\` runs phase 1 only (fast feedback)
676
+ - Must pass before pushing (enforced by Husky pre-push hook)
677
+
678
+ ## Adding a New Package
679
+ 1. Create \`packages/<name>/\` with package.json, tsconfig.json, tsup.config.ts
680
+ 2. Name: \`@revealui/<name>\`
681
+ 3. Add \`workspace:*\` references from consuming packages
682
+ 4. Register in turbo pipeline (automatic via conventions)
683
+ 5. Add to CI if needed
684
+
685
+ ## Publishing
686
+ - OSS packages: \`publishConfig.access: "public"\`, MIT license
687
+ - Pro packages: \`publishConfig.access: "public"\`, commercial license (source-available on npm)
688
+ - Use changesets for versioning: \`pnpm changeset\` \u2192 \`pnpm changeset:version\` \u2192 \`pnpm changeset:publish\`
689
+
690
+ ## Import Conventions
691
+ - Use package names (\`@revealui/core\`) not relative paths between packages
692
+ - Use \`~/\` alias within apps (maps to \`src/*\`)
693
+ - Use ES Modules (\`import\`/\`export\`) everywhere`
694
+ };
695
+
696
+ // src/content/definitions/rules/parameterization.ts
697
+ var parameterizationRule = {
698
+ id: "parameterization",
699
+ tier: "oss",
700
+ name: "Parameterization Conventions",
701
+ description: "Never hardcode config values \u2014 extract, type, default, and make overridable",
702
+ scope: "project",
703
+ preambleTier: 2,
704
+ tags: ["config", "patterns"],
705
+ content: `# Parameterization Conventions
706
+
707
+ ## Core Rule
708
+
709
+ **Never hardcode configuration values inline.** All tunable constants (TTLs, limits, lengths, thresholds, intervals) must be:
710
+
711
+ 1. **Extracted** into a named config object or constant at module scope
712
+ 2. **Typed** with an explicit interface
713
+ 3. **Defaulted** with sensible production values
714
+ 4. **Overridable** via an exported \`configure*()\` function or constructor parameter
715
+
716
+ ## Pattern
717
+
718
+ \`\`\`ts
719
+ export interface ModuleConfig {
720
+ /** TTL in milliseconds (default: 5 minutes) */
721
+ ttlMs: number
722
+ /** Max entries before forced cleanup (default: 10_000) */
723
+ maxEntries: number
724
+ }
725
+
726
+ const DEFAULT_CONFIG: ModuleConfig = {
727
+ ttlMs: 5 * 60 * 1000,
728
+ maxEntries: 10_000,
729
+ }
730
+
731
+ let config: ModuleConfig = { ...DEFAULT_CONFIG }
732
+
733
+ export function configureModule(overrides: Partial<ModuleConfig>): void {
734
+ config = { ...DEFAULT_CONFIG, ...overrides }
735
+ }
736
+ \`\`\`
737
+
738
+ ## Why
739
+
740
+ - Tests need fast TTLs and small limits
741
+ - Deployments may need different thresholds than development
742
+ - \`Math.random()\` is not cryptographically secure \u2014 use \`crypto.randomInt()\` for security-sensitive values (OTPs, tokens, nonces)
743
+
744
+ ## Applies To
745
+
746
+ - Rate limit windows and thresholds
747
+ - Cache TTLs and max sizes
748
+ - OTP/token lengths and expiry times
749
+ - Retry counts and backoff intervals
750
+ - Batch sizes and concurrency limits
751
+
752
+ ## Does NOT Apply To
753
+
754
+ - Structural constants (HTTP status codes, header names, URL paths)
755
+ - Type discriminants and enum values
756
+ - Schema definitions (use contracts)`
757
+ };
758
+
759
+ // src/content/definitions/rules/skills-usage.ts
760
+ var skillsUsageRule = {
761
+ id: "skills-usage",
762
+ tier: "pro",
763
+ name: "Skill Auto-Use Guidelines",
764
+ description: "When to proactively invoke skills vs wait for explicit user request",
765
+ scope: "project",
766
+ preambleTier: 4,
767
+ tags: ["skills", "automation"],
768
+ content: `# Skill Auto-Use Guidelines
769
+
770
+ When the Skill tool is available, proactively invoke the following skills in these situations:
771
+
772
+ ## Always invoke automatically (no user prompt needed)
773
+
774
+ - \`/vercel-react-best-practices\` \u2014 before completing any PR that touches React components or hooks
775
+ - \`/stripe-best-practices\` \u2014 any time you write or modify billing, payment, webhook, or Stripe code
776
+ - \`/next-best-practices\` \u2014 when implementing features in apps/cms or apps/marketing
777
+ - \`/next-cache-components\` \u2014 when adding 'use cache', cache profiles, or PPR to a Next.js route
778
+ - \`/vercel-composition-patterns\` \u2014 when adding new components to @revealui/presentation
779
+ - \`/web-design-guidelines\` \u2014 when asked to review a UI, page, or component for quality
780
+ - \`/review\` \u2014 when the user asks for a code review, asks to "check" or "look at" code
781
+ - \`/add-tests\` \u2014 when the user asks to write tests or add coverage for a specific file
782
+ - \`/audit\` \u2014 before any release or after a large refactor touching multiple packages
783
+ - \`/turborepo\` \u2014 when modifying turbo.json, pipeline configuration, or monorepo task dependencies
784
+
785
+ ## Only invoke on explicit user request (disable-model-invocation: true)
786
+
787
+ - \`/gate\` \u2014 user must explicitly ask to run the gate
788
+ - \`/sync-lts\` \u2014 user must explicitly ask to sync or backup
789
+ - \`/new-package\` \u2014 user must explicitly ask to scaffold a package
790
+ - \`/new-professional-project\` \u2014 user must explicitly ask to create a project
791
+ - \`/vercel-deploy\` \u2014 user must explicitly ask to deploy
792
+ - \`/deploy-check\` \u2014 user must explicitly ask for pre-deploy check
793
+ - \`/db-migrate\` \u2014 user must explicitly ask to create or apply database migrations
794
+ - \`/preflight\` \u2014 user must explicitly ask to run the preflight checklist
795
+
796
+ ## When in doubt
797
+
798
+ If a skill's description matches the current task, prefer invoking it over not invoking it.
799
+ The overhead of loading a skill is low; missing relevant guidance has higher cost.`
800
+ };
801
+
802
+ // src/content/definitions/rules/tailwind.ts
803
+ var tailwindRule = {
804
+ id: "tailwind",
805
+ tier: "oss",
806
+ name: "Tailwind CSS v4 Conventions",
807
+ description: "Tailwind v4 syntax rules, v3\u2192v4 migration gotchas, and shared config patterns",
808
+ scope: "project",
809
+ preambleTier: 2,
810
+ tags: ["css", "tailwind", "styling"],
811
+ content: `# Tailwind CSS v4 Conventions
812
+
813
+ ## Version
814
+
815
+ RevealUI uses **Tailwind CSS v4** (\`^4.1.18\`). All new code must use v4 patterns.
816
+
817
+ ## Current State
818
+
819
+ The shared config in \`packages/dev/src/tailwind/\` uses a **v3 compatibility pattern** (JS config file + JS plugins). This works because Tailwind v4 auto-detects \`tailwind.config.ts\` and falls back to v3 behavior. Migration to native v4 CSS config is deferred to Phase 2.
820
+
821
+ ## v4 Gotchas (Must Know)
822
+
823
+ ### Import Syntax
824
+ \`\`\`css
825
+ /* CORRECT (v4) */
826
+ @import "tailwindcss";
827
+
828
+ /* WRONG (v3 \u2014 deprecated) */
829
+ @tailwind base;
830
+ @tailwind components;
831
+ @tailwind utilities;
832
+ \`\`\`
833
+
834
+ ### Custom Utilities
835
+ \`\`\`css
836
+ /* CORRECT (v4) */
837
+ @utility my-util {
838
+ /* styles */
839
+ }
840
+
841
+ /* WRONG (v3) */
842
+ @layer utilities {
843
+ .my-util { /* styles */ }
844
+ }
845
+ @layer components {
846
+ .my-component { /* styles */ }
847
+ }
848
+ \`\`\`
849
+
850
+ ### CSS Variable Syntax
851
+ \`\`\`html
852
+ <!-- CORRECT (v4) \u2014 parentheses -->
853
+ <div class="bg-(--brand-color)">
854
+
855
+ <!-- WRONG (v3) \u2014 square brackets -->
856
+ <div class="bg-[--brand-color]">
857
+ \`\`\`
858
+
859
+ ### Important Modifier
860
+ \`\`\`html
861
+ <!-- CORRECT (v4) \u2014 at the end -->
862
+ <div class="bg-red-500!">
863
+
864
+ <!-- WRONG (v3) \u2014 at the start -->
865
+ <div class="bg-!red-500">
866
+ \`\`\`
867
+
868
+ ### Default Behavior Changes
869
+ - **Border/ring color**: now \`currentColor\` (was \`gray-200\` in v3)
870
+ - **Ring width**: default is \`1px\` (was \`3px\` in v3)
871
+ - **\`hover:\`**: only applies on devices that support hover (no-touch)
872
+ - **Stacked variants**: apply left-to-right (reversed from v3)
873
+ - **\`space-*\` / \`divide-*\`**: selectors changed \u2014 prefer \`gap\` with flex/grid
874
+
875
+ ### Transform Utilities
876
+ \`\`\`html
877
+ <!-- CORRECT (v4) -->
878
+ <div class="scale-none rotate-none translate-none">
879
+
880
+ <!-- WRONG (v3) -->
881
+ <div class="transform-none">
882
+ \`\`\`
883
+
884
+ ### Prefix Syntax
885
+ \`\`\`css
886
+ /* v4 prefix */
887
+ @import "tailwindcss" prefix(tw);
888
+ /* Classes use tw:bg-red-500 */
889
+ \`\`\`
890
+
891
+ ### CSS Modules / Component Styles
892
+ Use \`@reference\` to access theme variables in CSS modules or component \`<style>\` blocks.
893
+
894
+ ### PostCSS Plugin
895
+ \`\`\`js
896
+ // v4 \u2014 new package name
897
+ { plugins: { '@tailwindcss/postcss': {} } }
898
+
899
+ // v3 \u2014 old (still works but deprecated)
900
+ { plugins: { tailwindcss: {} } }
901
+ \`\`\`
902
+
903
+ ### Vite Plugin (preferred over PostCSS for Vite apps)
904
+ \`\`\`js
905
+ import tailwindcss from '@tailwindcss/vite'
906
+ export default { plugins: [tailwindcss()] }
907
+ \`\`\`
908
+
909
+ ## Theme Configuration (v4 native)
910
+
911
+ In v4, theme tokens go in CSS, not JS:
912
+
913
+ \`\`\`css
914
+ @import "tailwindcss";
915
+
916
+ @theme {
917
+ --color-brand: #ea580c;
918
+ --font-sans: "Inter", sans-serif;
919
+ --breakpoint-xs: 475px;
920
+ --breakpoint-3xl: 1920px;
921
+ }
922
+ \`\`\`
923
+
924
+ ## RevealUI Shared Config
925
+
926
+ | File | Purpose |
927
+ |------|---------|
928
+ | \`packages/dev/src/tailwind/tailwind.config.ts\` | Shared v3-compat config (fonts, plugins, screens) |
929
+ | \`packages/dev/src/tailwind/create-config.ts\` | Helper to merge shared + app configs |
930
+ | \`packages/dev/src/tailwind/postcss.config.ts\` | PostCSS config with \`@tailwindcss/postcss\` |
931
+ | \`packages/dev/src/tailwind/styles.css\` | Base CSS (\`@import "tailwindcss"\`) |
932
+
933
+ ### Consumer Pattern (current \u2014 v3 compat)
934
+ \`\`\`ts
935
+ // apps/cms/tailwind.config.ts
936
+ import { createTailwindConfig } from 'dev/tailwind/create-config'
937
+ export default createTailwindConfig({
938
+ content: ['./src/**/*.{ts,tsx}'],
939
+ // app-specific overrides
940
+ })
941
+ \`\`\`
942
+
943
+ ## Rules for New Code
944
+
945
+ 1. **Never use \`@tailwind\` directives** \u2014 use \`@import "tailwindcss"\` instead
946
+ 2. **Never use \`@layer utilities\` or \`@layer components\`** for custom utilities \u2014 use \`@utility\`
947
+ 3. **Use \`bg-(--var)\` syntax** for CSS variables, not \`bg-[--var]\`
948
+ 4. **Important goes at the end**: \`bg-red-500!\` not \`!bg-red-500\`
949
+ 5. **Prefer \`gap\`** over \`space-*\` / \`divide-*\` for spacing in flex/grid
950
+ 6. **No \`transform-none\`** \u2014 use \`scale-none\`, \`rotate-none\`, \`translate-none\`
951
+ 7. **Don't add new v3 JS plugins** \u2014 if a v4 CSS equivalent exists, use that
952
+ 8. **Content paths are auto-detected** in v4 \u2014 only add manual paths for edge cases`
953
+ };
954
+
955
+ // src/content/definitions/rules/unused-declarations.ts
956
+ var unusedDeclarationsRule = {
957
+ id: "unused-declarations",
958
+ tier: "oss",
959
+ name: "Unused Declarations Policy",
960
+ description: "Never suppress unused warnings without determining if code is incomplete \u2014 implement first",
961
+ scope: "project",
962
+ preambleTier: 3,
963
+ tags: ["lint", "quality", "policy"],
964
+ content: `# Unused Declarations Policy
965
+
966
+ ## Core Rule
967
+
968
+ **NEVER suppress an unused variable/import warning without first determining if the code is incomplete.**
969
+
970
+ Unused declarations in this codebase frequently signal incomplete implementations \u2014 stubs, scaffolded functions, planned integrations \u2014 not dead code. Suppressing the warning without completing the code leads to permanent placeholders that silently rot.
971
+
972
+ ---
973
+
974
+ ## Mandatory Decision Tree
975
+
976
+ When you encounter an \`no-unused-vars\`, \`noUnusedVariables\`, or \`noUnusedFunctionParameters\` warning, you MUST follow this decision tree **before taking any action**:
977
+
978
+ \`\`\`
979
+ 1. Is the declaration a stub or placeholder?
980
+ \u2514\u2500 Signs: empty function body, \`// TODO\`, \`throw new Error('not implemented')\`,
981
+ adjacent commented-out code, file has <10 lines of real logic,
982
+ variable name matches a feature that exists elsewhere in the codebase
983
+ \u2514\u2500 Action: IMPLEMENT the missing functionality. Do not suppress.
984
+
985
+ 2. Is the declaration an intentionally-created side-effect resource?
986
+ \u2514\u2500 Signs: infrastructure-as-code (Pulumi/CDK), event listener registration,
987
+ DB migration runner, resource that must exist but isn't referenced
988
+ \u2514\u2500 Action: Rename with \`_\` prefix to signal intentional non-use.
989
+ Add a comment explaining WHY it exists.
990
+
991
+ 3. Is the import used only as a type (TypeScript)?
992
+ \u2514\u2500 Signs: import is from a types package, used only in \`type X = ...\` expressions
993
+ \u2514\u2500 Action: Change to \`import type { ... }\` \u2014 Biome will no longer flag it.
994
+
995
+ 4. Is the parameter required by a callback signature you don't control?
996
+ \u2514\u2500 Signs: Express/Hono middleware \`(req, res, next)\`, event handler \`(event, context)\`,
997
+ interface implementation where all params are mandated
998
+ \u2514\u2500 Action: Prefix with \`_\` (e.g. \`_req\`, \`_event\`). Add a comment if non-obvious.
999
+
1000
+ 5. Is it genuinely dead code with no planned use?
1001
+ \u2514\u2500 Signs: feature was removed, import was replaced, duplicate of another symbol
1002
+ \u2514\u2500 Action: DELETE the declaration entirely. Per the Legacy Code Removal Policy,
1003
+ no grace periods \u2014 remove it and all call sites in the same change.
1004
+ \`\`\`
1005
+
1006
+ ---
1007
+
1008
+ ## What "Implement" Means
1009
+
1010
+ When you determine a declaration is incomplete (case 1), the required steps are:
1011
+
1012
+ 1. **Search the codebase** for related implementations, types, interfaces, and tests that reveal intent.
1013
+ 2. **Check the plan file** at \`~/.claude/plans/\` for any documented phase covering this feature.
1014
+ 3. **Check for contracts** in \`packages/contracts/src/\` \u2014 the schema often describes the expected behavior.
1015
+ 4. **Implement the function/class/module** based on what the surrounding code expects.
1016
+ 5. **Run \`pnpm gate:quick\`** after implementing to verify no new errors were introduced.
1017
+
1018
+ Do NOT:
1019
+ - Add \`// biome-ignore lint/correctness/noUnusedVariables: TODO implement\`
1020
+ - Rename to \`_variable\` just to silence the warning when the variable should be used
1021
+ - Delete a stub that represents planned functionality without implementing it first
1022
+
1023
+ ---
1024
+
1025
+ ## Examples
1026
+
1027
+ ### Wrong \u2014 suppressing an incomplete stub
1028
+ \`\`\`ts
1029
+ // biome-ignore lint/correctness/noUnusedVariables: TODO
1030
+ const semanticMemory = new SemanticMemory()
1031
+ \`\`\`
1032
+
1033
+ ### Right \u2014 implement it
1034
+ \`\`\`ts
1035
+ const semanticMemory = new SemanticMemory()
1036
+ await semanticMemory.store('key', content, embedding)
1037
+ \`\`\`
1038
+
1039
+ ---
1040
+
1041
+ ### Wrong \u2014 deleting a planned integration
1042
+ \`\`\`ts
1043
+ // Was: import { ProceduralMemory } from './procedural-memory.js'
1044
+ // Deleted because "unused"
1045
+ \`\`\`
1046
+
1047
+ ### Right \u2014 implement the module it was waiting for
1048
+ \`\`\`ts
1049
+ // packages/ai/src/memory/memory/procedural-memory.ts
1050
+ export class ProceduralMemory { ... }
1051
+ // Then use it where the original import was
1052
+ \`\`\`
1053
+
1054
+ ---
1055
+
1056
+ ### Wrong \u2014 renaming away the signal
1057
+ \`\`\`ts
1058
+ // Original: const routeTableAssoc = new aws.ec2.RouteTableAssociation(...)
1059
+ // "Fixed": const _routeTableAssoc = new aws.ec2.RouteTableAssociation(...)
1060
+ // No comment explaining why
1061
+ \`\`\`
1062
+
1063
+ ### Right \u2014 rename AND document
1064
+ \`\`\`ts
1065
+ // Route table association must exist for subnet routing to function.
1066
+ // The variable is not referenced after creation; AWS manages the association.
1067
+ const _routeTableAssoc = new aws.ec2.RouteTableAssociation(...)
1068
+ \`\`\`
1069
+
1070
+ ---
1071
+
1072
+ ## Verification Step After Any Lint Fix
1073
+
1074
+ After resolving any unused declaration warning, run:
1075
+
1076
+ \`\`\`bash
1077
+ # Confirm the fix compiles
1078
+ pnpm --filter <package> typecheck
1079
+
1080
+ # Confirm Biome is clean on the changed file
1081
+ node_modules/.bin/biome check <file>
1082
+
1083
+ # If the declaration was a stub that you implemented, run the tests
1084
+ pnpm --filter <package> test
1085
+ \`\`\`
1086
+
1087
+ Never move to the next task without completing this verification.
1088
+
1089
+ ---
1090
+
1091
+ ## Relationship to Gate Verification Rule
1092
+
1093
+ This policy works in conjunction with the gate verification rule: complete the implementation \u2192 verify with lint/type/test \u2192 then move on. The gate catches regressions; this policy prevents incomplete code from silently accumulating.`
1094
+ };
1095
+
1096
+ // src/content/definitions/rules/index.ts
1097
+ var rules = [
1098
+ agentDispatchRule,
1099
+ biomeRule,
1100
+ codeAnalysisPolicyRule,
1101
+ databaseRule,
1102
+ monorepoRule,
1103
+ parameterizationRule,
1104
+ skillsUsageRule,
1105
+ tailwindRule,
1106
+ unusedDeclarationsRule
1107
+ ];
1108
+
1109
+ // src/content/definitions/skills/db-migrate.ts
1110
+ var dbMigrateSkill = {
1111
+ id: "db-migrate",
1112
+ tier: "pro",
1113
+ name: "Database Migration",
1114
+ description: "Create and apply Drizzle ORM migrations with dual-DB boundary checks (NeonDB vs Supabase)",
1115
+ disableModelInvocation: true,
1116
+ skipFrontmatter: false,
1117
+ filePatterns: [],
1118
+ bashPatterns: [],
1119
+ references: {},
1120
+ content: `# Database Migration Workflow
1121
+
1122
+ Guide for creating and applying Drizzle ORM migrations in the RevealUI dual-database architecture.
1123
+
1124
+ ## Pre-Flight Checks
1125
+
1126
+ Before creating a migration:
1127
+
1128
+ 1. **Identify the target database**:
1129
+ - **NeonDB** (REST content): users, sessions, collections, products, orders, licenses, pages, sites, tickets, agents, api-keys, GDPR
1130
+ - **Supabase** (vectors/auth): embeddings, AI memory storage, real-time auth
1131
+ - If unsure, check \`packages/db/src/schema/rest.ts\` (NeonDB) vs \`packages/db/src/schema/vector.ts\` (Supabase)
1132
+
1133
+ 2. **Check existing schema** for conflicts:
1134
+ \`\`\`bash
1135
+ # View current schema files
1136
+ ls packages/db/src/schema/
1137
+
1138
+ # Check for table name conflicts
1139
+ grep -r "export const.*pgTable" packages/db/src/schema/
1140
+ \`\`\`
1141
+
1142
+ 3. **Verify contracts alignment** \u2014 new tables/columns should have corresponding Zod schemas:
1143
+ \`\`\`bash
1144
+ ls packages/contracts/src/
1145
+ \`\`\`
1146
+
1147
+ ## Migration Steps
1148
+
1149
+ ### Step 1: Modify Schema
1150
+
1151
+ Edit the appropriate schema file in \`packages/db/src/schema/\`:
1152
+
1153
+ - Follow existing patterns (see adjacent schema files)
1154
+ - Use Drizzle's \`pgTable\`, column types, and relations
1155
+ - Add indexes for frequently queried columns
1156
+ - Add \`createdAt\`/\`updatedAt\` timestamps with defaults
1157
+
1158
+ ### Step 2: Generate Migration
1159
+
1160
+ \`\`\`bash
1161
+ cd packages/db
1162
+ pnpm drizzle-kit generate
1163
+ \`\`\`
1164
+
1165
+ Review the generated SQL in \`packages/db/drizzle/\` \u2014 check for:
1166
+ - Destructive changes (DROP TABLE, DROP COLUMN)
1167
+ - Data loss risks (column type changes without USING clause)
1168
+ - Missing indexes on foreign keys
1169
+
1170
+ ### Step 3: Apply Migration (Development Only)
1171
+
1172
+ \`\`\`bash
1173
+ # Development database ONLY \u2014 never production
1174
+ pnpm db:migrate
1175
+ \`\`\`
1176
+
1177
+ **NEVER run \`drizzle-kit push\`** \u2014 always use \`drizzle-kit migrate\` (the PreToolUse hook blocks \`push\`).
1178
+
1179
+ ### Step 4: Verify
1180
+
1181
+ \`\`\`bash
1182
+ # Typecheck the db package
1183
+ pnpm --filter @revealui/db typecheck
1184
+
1185
+ # Run db tests
1186
+ pnpm --filter @revealui/db test
1187
+
1188
+ # If schema changes affect contracts, update and test those too
1189
+ pnpm --filter @revealui/contracts typecheck
1190
+ pnpm --filter @revealui/contracts test
1191
+ \`\`\`
1192
+
1193
+ ### Step 5: Update Contracts (if needed)
1194
+
1195
+ If you added new tables or columns that are exposed via the API:
1196
+
1197
+ 1. Add/update Zod schema in \`packages/contracts/src/\`
1198
+ 2. Export from \`packages/contracts/src/index.ts\`
1199
+ 3. Update any API routes that use the new schema
1200
+
1201
+ ## Dual-DB Boundary Rules
1202
+
1203
+ | If your change touches... | Put it in... | Client |
1204
+ |---------------------------|-------------|--------|
1205
+ | Content, users, sessions, products, orders | \`packages/db/src/schema/\` (NeonDB barrel) | Drizzle ORM |
1206
+ | Vector embeddings, AI memory | \`packages/db/src/schema/vector.ts\` | Supabase client |
1207
+ | Real-time auth helpers | \`packages/db/src/auth/\` | Supabase client |
1208
+
1209
+ **Never mix** NeonDB and Supabase operations in the same module.
1210
+
1211
+ ## Rollback
1212
+
1213
+ If a migration needs to be reverted:
1214
+
1215
+ 1. Create a new migration that undoes the changes (Drizzle doesn't have built-in rollback)
1216
+ 2. Never manually edit the migration journal (\`_journal.json\`)
1217
+ 3. Document the rollback reason in the migration file comment`
1218
+ };
1219
+
1220
+ // src/content/definitions/skills/preflight.ts
1221
+ var preflightSkill = {
1222
+ id: "preflight",
1223
+ tier: "oss",
1224
+ name: "Preflight Check",
1225
+ description: "Run the 15-check pre-launch preflight and interpret results with context-aware fix suggestions",
1226
+ disableModelInvocation: true,
1227
+ skipFrontmatter: false,
1228
+ filePatterns: [],
1229
+ bashPatterns: [],
1230
+ references: {},
1231
+ content: `# Preflight Check
1232
+
1233
+ Run the full pre-launch preflight checklist and interpret results.
1234
+
1235
+ ## Run
1236
+
1237
+ \`\`\`bash
1238
+ pnpm preflight
1239
+ \`\`\`
1240
+
1241
+ This runs 15 checks covering lint, types, tests, build, security, and structure.
1242
+
1243
+ ## Interpreting Results
1244
+
1245
+ ### Hard Failures (must fix before launch)
1246
+
1247
+ | Check | What It Means | Common Fix |
1248
+ |-------|--------------|------------|
1249
+ | **Biome lint** | Code style or correctness violation | \`pnpm lint:fix\` then review remaining |
1250
+ | **TypeScript** | Type errors across workspaces | \`pnpm typecheck:all\` to see full list |
1251
+ | **Build** | Compilation failure in one or more packages | Check \`dist/\` output, tsup config |
1252
+ | **Tests** | Unit/integration test failures | \`pnpm test\` to see which tests fail |
1253
+
1254
+ ### Warn-Only (should fix, won't block)
1255
+
1256
+ | Check | What It Means | Common Fix |
1257
+ |-------|--------------|------------|
1258
+ | **\`any\` audit** | Avoidable \`any\` types found | \`pnpm audit:any\` \u2014 use \`unknown\` + type guards |
1259
+ | **Console audit** | \`console.*\` in production code | \`pnpm audit:console\` \u2014 use \`@revealui/utils\` logger |
1260
+ | **Structure** | Supabase boundary violations or package issues | \`pnpm validate:structure\` |
1261
+ | **Security** | CSP, CORS, or header issues | Check \`packages/security/\` |
1262
+ | **Dependencies** | Version mismatches across workspaces | \`pnpm deps:check\` then \`pnpm deps:fix\` |
1263
+
1264
+ ## After Preflight
1265
+
1266
+ If all hard checks pass:
1267
+
1268
+ 1. Run \`pnpm gate\` for the full CI gate (superset of preflight)
1269
+ 2. Check for uncommitted changes: \`git status\`
1270
+ 3. Review the deployment checklist: \`/deploy-check\`
1271
+
1272
+ If checks fail, fix in priority order:
1273
+ 1. Build failures (blocks everything)
1274
+ 2. Type errors (blocks CI)
1275
+ 3. Test failures (blocks confidence)
1276
+ 4. Lint issues (blocks merge)
1277
+ 5. Warn-only items (fix before release)`
1278
+ };
1279
+
1280
+ // src/content/definitions/skills/revealui-conventions.ts
1281
+ var revealuiConventionsSkill = {
1282
+ id: "revealui-conventions",
1283
+ tier: "oss",
1284
+ name: "RevealUI Conventions",
1285
+ description: "RevealUI coding conventions for any code task \u2014 writing, editing, reviewing, creating,\nfixing, refactoring, changing, adding, or updating TypeScript, React, CSS, or config files.\nCovers TypeScript strict mode, ES Modules, Biome formatting, Tailwind v4 syntax,\nconventional commits, monorepo workspace protocol, feature gating, parameterization,\nand unused declaration policy.",
1286
+ disableModelInvocation: false,
1287
+ skipFrontmatter: false,
1288
+ filePatterns: [],
1289
+ bashPatterns: [],
1290
+ references: {},
1291
+ content: `# RevealUI Conventions
1292
+
1293
+ Follow these conventions for ALL code in the RevealUI monorepo.
1294
+
1295
+ ## TypeScript
1296
+
1297
+ - Always use strict mode (\`strict: true\` in tsconfig)
1298
+ - Use ES Modules (\`import\`/\`export\`), never CommonJS (\`require\`)
1299
+ - Prefer \`interface\` over \`type\` for object shapes (unless union/intersection needed)
1300
+ - Use explicit return types on exported functions
1301
+ - Avoid \`any\` \u2014 use \`unknown\` and narrow with type guards
1302
+ - Use \`as const\` for literal objects and arrays when appropriate
1303
+ - Prefer \`satisfies\` over \`as\` for type assertions when possible
1304
+ - Use optional chaining (\`?.\`) and nullish coalescing (\`??\`) over manual checks
1305
+ - Async/await over \`.then()\` chains
1306
+
1307
+ ## Git
1308
+
1309
+ ### Commit Messages
1310
+ - Use conventional commits: \`type(scope): description\`
1311
+ - Types: feat, fix, refactor, docs, test, chore, ci, perf
1312
+ - Scope is optional, use package name for monorepos (e.g., \`feat(core): add parser\`)
1313
+ - Description in imperative mood, lowercase, no period
1314
+ - Keep subject line under 72 characters
1315
+
1316
+ ### Branch Naming
1317
+ - Feature: \`feat/<short-description>\`
1318
+ - Bugfix: \`fix/<short-description>\`
1319
+ - Chore: \`chore/<short-description>\`
1320
+
1321
+ ### Identity
1322
+ - RevealUI Studio <founder@revealui.com>
1323
+
1324
+ ## Monorepo
1325
+
1326
+ ### Structure
1327
+ - Apps live in \`apps/\` \u2014 deployable services (Next.js, Hono, Vite)
1328
+ - Packages live in \`packages/\` \u2014 shared libraries consumed by apps
1329
+ - Scripts live in \`scripts/\` \u2014 CLI tools, automation, CI gates
1330
+
1331
+ ### Package Manager
1332
+ - pnpm 10 with workspace protocol
1333
+ - Internal deps use \`workspace:*\` (never hardcoded versions)
1334
+ - Run \`pnpm install:clean\` (suppresses Node deprecation warnings)
1335
+ - \`preinstall\` script enforces pnpm-only (\`npx only-allow pnpm\`)
1336
+
1337
+ ### Turborepo
1338
+ - \`turbo run build --parallel\` for parallel builds
1339
+ - \`turbo run test --concurrency=15\` for parallel tests
1340
+ - Package-level \`turbo.json\` for task overrides (rare)
1341
+ - Cache stored in \`.turbo/\` (gitignored)
1342
+
1343
+ ### Package Conventions
1344
+ - Every package has: \`build\`, \`dev\`, \`lint\`, \`test\`, \`typecheck\` scripts
1345
+ - Build output goes to \`dist/\` via tsup
1346
+ - Source in \`src/\`, tests in \`src/__tests__/\` or \`__tests__/\`
1347
+ - Entry point: \`src/index.ts\` \u2192 \`dist/index.js\`
1348
+ - Use \`exports\` field in package.json for subpath exports
1349
+ - Include \`files: ["dist", "README.md"]\` for publishing
1350
+
1351
+ ### Dependency Rules
1352
+ - Use \`syncpack\` for version alignment (\`pnpm deps:check\`, \`pnpm deps:fix\`)
1353
+ - Use \`catalog:\` for shared devDependencies (e.g., \`"zod": "catalog:"\`)
1354
+ - pnpm overrides in root package.json for security patches
1355
+
1356
+ ### CI Gate
1357
+ - \`pnpm gate\` runs the full CI pipeline locally: lint \u2192 typecheck \u2192 test \u2192 build
1358
+ - \`pnpm gate:quick\` runs phase 1 only (fast feedback)
1359
+ - Must pass before pushing (enforced by Husky pre-push hook)
1360
+
1361
+ ### Adding a New Package
1362
+ 1. Create \`packages/<name>/\` with package.json, tsconfig.json, tsup.config.ts
1363
+ 2. Name: \`@revealui/<name>\`
1364
+ 3. Add \`workspace:*\` references from consuming packages
1365
+ 4. Register in turbo pipeline (automatic via conventions)
1366
+
1367
+ ### Publishing
1368
+ - OSS packages: \`publishConfig.access: "public"\`, MIT license
1369
+ - Pro packages: \`"private": true\` (not published to npm)
1370
+ - Use changesets for versioning: \`pnpm changeset\` \u2192 \`pnpm changeset:version\` \u2192 \`pnpm changeset:publish\`
1371
+
1372
+ ### Import Conventions
1373
+ - Use package names (\`@revealui/core\`) not relative paths between packages
1374
+ - Use \`~/\` alias within apps (maps to \`src/*\`)
1375
+ - Use ES Modules (\`import\`/\`export\`) everywhere
1376
+
1377
+ ## Biome
1378
+
1379
+ Biome 2 is the sole linter and formatter for this monorepo.
1380
+
1381
+ ### Commands
1382
+ - \`pnpm lint\` \u2014 check all files (\`biome check .\`)
1383
+ - \`pnpm format\` \u2014 format all files (\`biome format --write .\`)
1384
+ - \`pnpm lint:fix\` \u2014 auto-fix (\`biome check --write .\`)
1385
+
1386
+ ### Key Rules
1387
+ - No unused variables or imports (auto-removed on format)
1388
+ - No \`console.*\` in production code (use \`@revealui/utils\` logger)
1389
+ - No \`any\` types (use \`unknown\` + type guards)
1390
+ - Consistent import ordering (auto-sorted)
1391
+ - Single quotes for strings
1392
+ - Trailing commas
1393
+ - Semicolons always
1394
+ - 2-space indentation
1395
+
1396
+ ### Suppressing Rules
1397
+ - Use \`// biome-ignore <rule>: <reason>\` for specific lines
1398
+ - Avoid blanket suppressions \u2014 prefer fixing the code
1399
+ - Document why a suppression is needed
1400
+
1401
+ ## Tailwind v4
1402
+
1403
+ RevealUI uses **Tailwind CSS v4** (\`^4.1.18\`). Key syntax changes from v3:
1404
+
1405
+ ### Must-Know Gotchas
1406
+
1407
+ \`\`\`css
1408
+ /* CORRECT (v4) */
1409
+ @import "tailwindcss";
1410
+
1411
+ /* WRONG (v3) */
1412
+ @tailwind base;
1413
+ @tailwind components;
1414
+ @tailwind utilities;
1415
+ \`\`\`
1416
+
1417
+ \`\`\`css
1418
+ /* CORRECT (v4) */
1419
+ @utility my-util { /* styles */ }
1420
+
1421
+ /* WRONG (v3) */
1422
+ @layer utilities { .my-util { /* styles */ } }
1423
+ \`\`\`
1424
+
1425
+ \`\`\`html
1426
+ <!-- CORRECT (v4) \u2014 parentheses for CSS vars -->
1427
+ <div class="bg-(--brand-color)">
1428
+
1429
+ <!-- WRONG (v3) \u2014 square brackets -->
1430
+ <div class="bg-[--brand-color]">
1431
+ \`\`\`
1432
+
1433
+ \`\`\`html
1434
+ <!-- CORRECT (v4) \u2014 important at the end -->
1435
+ <div class="bg-red-500!">
1436
+
1437
+ <!-- WRONG (v3) \u2014 important at the start -->
1438
+ <div class="bg-!red-500">
1439
+ \`\`\`
1440
+
1441
+ ### Rules for New Code
1442
+ 1. Never use \`@tailwind\` directives \u2014 use \`@import "tailwindcss"\`
1443
+ 2. Never use \`@layer utilities\` or \`@layer components\` \u2014 use \`@utility\`
1444
+ 3. Use \`bg-(--var)\` syntax for CSS variables, not \`bg-[--var]\`
1445
+ 4. Important goes at the end: \`bg-red-500!\` not \`!bg-red-500\`
1446
+ 5. Prefer \`gap\` over \`space-*\` / \`divide-*\` for spacing in flex/grid
1447
+ 6. No \`transform-none\` \u2014 use \`scale-none\`, \`rotate-none\`, \`translate-none\`
1448
+
1449
+ ## Parameterization
1450
+
1451
+ **Never hardcode configuration values inline.** All tunable constants (TTLs, limits, lengths, thresholds, intervals) must be:
1452
+
1453
+ 1. **Extracted** into a named config object or constant at module scope
1454
+ 2. **Typed** with an explicit interface
1455
+ 3. **Defaulted** with sensible production values
1456
+ 4. **Overridable** via an exported \`configure*()\` function or constructor parameter
1457
+
1458
+ ### Pattern
1459
+
1460
+ \`\`\`ts
1461
+ export interface ModuleConfig {
1462
+ /** TTL in milliseconds (default: 5 minutes) */
1463
+ ttlMs: number
1464
+ /** Max entries before forced cleanup (default: 10_000) */
1465
+ maxEntries: number
1466
+ }
1467
+
1468
+ const DEFAULT_CONFIG: ModuleConfig = {
1469
+ ttlMs: 5 * 60 * 1000,
1470
+ maxEntries: 10_000,
1471
+ }
1472
+
1473
+ let config: ModuleConfig = { ...DEFAULT_CONFIG }
1474
+
1475
+ export function configureModule(overrides: Partial<ModuleConfig>): void {
1476
+ config = { ...DEFAULT_CONFIG, ...overrides }
1477
+ }
1478
+ \`\`\`
1479
+
1480
+ ### Applies To
1481
+ - Rate limit windows and thresholds
1482
+ - Cache TTLs and max sizes
1483
+ - OTP/token lengths and expiry times
1484
+ - Retry counts and backoff intervals
1485
+ - Batch sizes and concurrency limits
1486
+
1487
+ ### Does NOT Apply To
1488
+ - Structural constants (HTTP status codes, header names, URL paths)
1489
+ - Type discriminants and enum values
1490
+ - Schema definitions (use contracts)
1491
+
1492
+ ## Unused Declarations
1493
+
1494
+ **NEVER suppress an unused variable/import warning without first determining if the code is incomplete.**
1495
+
1496
+ ### Mandatory Decision Tree
1497
+
1498
+ \`\`\`
1499
+ 1. Stub or placeholder?
1500
+ \u2192 IMPLEMENT the missing functionality. Do not suppress.
1501
+
1502
+ 2. Intentional side-effect resource?
1503
+ \u2192 Rename with \`_\` prefix. Add a comment explaining WHY.
1504
+
1505
+ 3. Type-only import?
1506
+ \u2192 Change to \`import type { ... }\`.
1507
+
1508
+ 4. Required callback parameter?
1509
+ \u2192 Prefix with \`_\` (e.g. \`_req\`). Comment if non-obvious.
1510
+
1511
+ 5. Genuinely dead code?
1512
+ \u2192 DELETE entirely. No grace periods.
1513
+ \`\`\`
1514
+
1515
+ ### Verification After Any Lint Fix
1516
+
1517
+ \`\`\`bash
1518
+ pnpm --filter <package> typecheck
1519
+ node_modules/.bin/biome check <file>
1520
+ pnpm --filter <package> test # if you implemented a stub
1521
+ \`\`\`
1522
+
1523
+ ## Feature Gating
1524
+
1525
+ ### Tier Model
1526
+
1527
+ | Tier | Code String | Distribution |
1528
+ |------|-------------|-------------|
1529
+ | Free | \`'free'\` | MIT, open source |
1530
+ | Pro | \`'pro'\` | Source-available, commercially licensed |
1531
+ | Max | \`'max'\` | Extended Pro features |
1532
+ | Enterprise (Forge) | \`'enterprise'\` | White-label, multi-tenant, self-hosted |
1533
+
1534
+ ### Runtime Checks
1535
+
1536
+ \`\`\`ts
1537
+ import { isLicensed, isFeatureEnabled } from '@revealui/core'
1538
+
1539
+ if (isLicensed('pro')) { /* Pro+ feature */ }
1540
+ if (isFeatureEnabled('ai')) { /* AI feature (requires Pro) */ }
1541
+ \`\`\`
1542
+
1543
+ ### Package Boundaries
1544
+ - **OSS**: \`@revealui/core\`, \`contracts\`, \`db\`, \`auth\`, \`presentation\`, \`router\`, \`config\`, \`utils\`, \`cli\`, \`setup\`, \`sync\`, \`dev\`, \`test\`
1545
+ - **Pro**: \`@revealui/ai\`, \`mcp\`, \`editors\`, \`services\`, \`harnesses\`
1546
+
1547
+ ### Rules
1548
+ 1. OSS packages must never import from Pro packages
1549
+ 2. Pro packages may import from OSS packages
1550
+ 3. Public tests must not hard-require Pro package source paths
1551
+ 4. Feature gates use \`isLicensed()\` / \`isFeatureEnabled()\`, not environment variables`
1552
+ };
1553
+
1554
+ // src/content/definitions/skills/revealui-db.ts
1555
+ var revealuiDbSkill = {
1556
+ id: "revealui-db",
1557
+ tier: "pro",
1558
+ name: "RevealUI Database",
1559
+ description: "RevealUI database conventions for any task involving database, schema, query, migration,\nDrizzle ORM, Supabase, NeonDB, PostgreSQL, vectors, embeddings, or data modeling.\nEnforces dual-database architecture boundaries and import restrictions.",
1560
+ disableModelInvocation: false,
1561
+ skipFrontmatter: false,
1562
+ filePatterns: [],
1563
+ bashPatterns: [],
1564
+ references: {},
1565
+ content: `# Database Conventions
1566
+
1567
+ ## Dual-Database Architecture
1568
+
1569
+ RevealUI uses **two databases with strictly separated responsibilities**:
1570
+
1571
+ | Database | Client | Purpose |
1572
+ |----------|--------|---------|
1573
+ | **NeonDB** (PostgreSQL) | \`@neondatabase/serverless\` | REST content: collections, users, sessions, orders, products |
1574
+ | **Supabase** | \`@supabase/supabase-js\` | Vector embeddings, real-time auth, AI memory storage |
1575
+
1576
+ ## Boundary Rule
1577
+
1578
+ **\`@supabase/supabase-js\` must only be imported inside designated vector/auth modules:**
1579
+
1580
+ ### Allowed paths for Supabase imports
1581
+ - \`packages/db/src/vector/\` \u2014 vector schema and queries
1582
+ - \`packages/db/src/auth/\` \u2014 Supabase auth helpers
1583
+ - \`packages/auth/src/\` \u2014 authentication implementation
1584
+ - \`packages/ai/src/\` \u2014 AI memory and embedding storage
1585
+ - \`packages/services/src/supabase/\` \u2014 Supabase service integrations
1586
+ - \`apps/*/src/lib/supabase/\` \u2014 app-level Supabase utilities
1587
+
1588
+ ### Forbidden: Supabase imports in
1589
+ - \`packages/core/\` \u2014 CMS engine must be DB-agnostic
1590
+ - \`packages/contracts/\` \u2014 contracts are schema-only
1591
+ - \`packages/config/\` \u2014 config must not hardcode DB client
1592
+ - \`apps/cms/src/collections/\` \u2014 collection hooks use Drizzle/Neon only
1593
+ - \`apps/cms/src/routes/\` \u2014 REST routes use Neon only
1594
+
1595
+ ## Schema Organization
1596
+
1597
+ \`\`\`
1598
+ packages/db/src/schema/
1599
+ \u251C\u2500\u2500 collections/ # NeonDB: content collections
1600
+ \u251C\u2500\u2500 users/ # NeonDB: user management
1601
+ \u251C\u2500\u2500 commerce/ # NeonDB: products, orders, pricing
1602
+ \u251C\u2500\u2500 sessions/ # NeonDB: auth sessions
1603
+ \u251C\u2500\u2500 vector/ # Supabase: embeddings, similarity search
1604
+ \u2514\u2500\u2500 auth/ # Supabase: auth state
1605
+ \`\`\`
1606
+
1607
+ ## Query Patterns
1608
+
1609
+ ### NeonDB (Drizzle ORM)
1610
+ \`\`\`ts
1611
+ import { db } from '@revealui/db'
1612
+ import { posts } from '@revealui/db/schema'
1613
+
1614
+ const results = await db.select().from(posts).where(eq(posts.status, 'published'))
1615
+ \`\`\`
1616
+
1617
+ ### Supabase (vector/auth only)
1618
+ \`\`\`ts
1619
+ // Only in designated modules (packages/db/src/vector/, packages/ai/src/)
1620
+ import { createSupabaseClient } from '@revealui/db/vector'
1621
+
1622
+ const { data } = await supabase.rpc('match_documents', { query_embedding: embedding })
1623
+ \`\`\`
1624
+
1625
+ ## Enforcement
1626
+
1627
+ The \`pnpm validate:structure\` script checks for Supabase imports outside permitted paths.
1628
+ CI runs this as part of phase 1 (warn-only \u2014 violations are flagged but don't block builds).
1629
+
1630
+ To check locally:
1631
+ \`\`\`bash
1632
+ pnpm validate:structure
1633
+ \`\`\`
1634
+
1635
+ ## Migration Guidance
1636
+
1637
+ When adding new features:
1638
+ 1. **Content/REST data** \u2192 add to \`packages/db/src/schema/\` + use Drizzle
1639
+ 2. **AI/vector data** \u2192 add to \`packages/db/src/vector/\` + use Supabase client
1640
+ 3. **Never mix** both DB clients in the same module`
1641
+ };
1642
+
1643
+ // src/content/definitions/skills/revealui-debugging.ts
1644
+ var revealuiDebuggingSkill = {
1645
+ id: "revealui-debugging",
1646
+ tier: "pro",
1647
+ name: "RevealUI Debugging",
1648
+ description: "Systematic debugging workflow for RevealUI. Use when encountering any bug, test failure,\nunexpected behavior, error, or broken functionality. Prevents shotgun debugging.",
1649
+ disableModelInvocation: false,
1650
+ skipFrontmatter: false,
1651
+ filePatterns: [],
1652
+ bashPatterns: [],
1653
+ references: {},
1654
+ content: `# RevealUI Debugging Workflow
1655
+
1656
+ When something breaks, follow this process. Do not skip steps.
1657
+
1658
+ ## The Process
1659
+
1660
+ ### 1. Reproduce
1661
+
1662
+ - Get the exact error message, stack trace, or unexpected output
1663
+ - Find the minimal reproduction case
1664
+ - Confirm it reproduces consistently (not flaky)
1665
+ - If it only fails under \`turbo run test\`, see \`$revealui-testing\` for concurrency triage
1666
+
1667
+ ### 2. Hypothesize
1668
+
1669
+ - Form ONE specific hypothesis about the root cause
1670
+ - Write it down before changing any code
1671
+ - Base it on evidence (error message, stack trace, git blame), not intuition
1672
+
1673
+ ### 3. Validate
1674
+
1675
+ - Design a test or check that confirms/refutes your hypothesis
1676
+ - Run it
1677
+ - If refuted, form a new hypothesis \u2014 do not stack unrelated fixes
1678
+
1679
+ ### 4. Fix Narrowly
1680
+
1681
+ - Change the minimum code to fix the root cause
1682
+ - Do not refactor surrounding code
1683
+ - Do not fix adjacent issues you noticed along the way (file them separately)
1684
+
1685
+ ### 5. Verify
1686
+
1687
+ - Run the original failing test/scenario
1688
+ - Run \`pnpm --filter <package> test\` to check for regressions
1689
+ - Run \`npx biome check --write <file>\` on changed files
1690
+
1691
+ ### 6. Commit
1692
+
1693
+ - One commit for the fix
1694
+ - Format: \`fix(scope): description of what was broken\`
1695
+
1696
+ ## Anti-Patterns
1697
+
1698
+ - Changing multiple things at once ("shotgun debugging")
1699
+ - Fixing symptoms instead of root causes
1700
+ - Adding try/catch blocks to silence errors
1701
+ - Increasing timeouts to hide race conditions
1702
+ - Reverting to "known good" without understanding what broke
1703
+ - Asking "does this fix it?" without a hypothesis
1704
+
1705
+ ## Common RevealUI Debugging Paths
1706
+
1707
+ | Symptom | First Check |
1708
+ |---------|------------|
1709
+ | Import error | Package built? \`pnpm --filter <pkg> build\` |
1710
+ | Type error across packages | \`pnpm typecheck:all\` \u2014 check \`workspace:*\` versions |
1711
+ | Test passes alone, fails in gate | Concurrency pressure \u2014 see \`$revealui-testing\` |
1712
+ | Supabase error in unexpected path | Import boundary violation \u2014 see \`$revealui-db\` |
1713
+ | Biome error after edit | Run \`npx biome check --write <file>\` |`
1714
+ };
1715
+
1716
+ // src/content/definitions/skills/revealui-review.ts
1717
+ var revealuiReviewSkill = {
1718
+ id: "revealui-review",
1719
+ tier: "pro",
1720
+ name: "RevealUI Code Review",
1721
+ description: "Code review checklist for RevealUI. Use when reviewing code, completing a feature,\nchecking quality, or before committing. Invoke explicitly with $revealui-review.",
1722
+ disableModelInvocation: true,
1723
+ skipFrontmatter: false,
1724
+ filePatterns: [],
1725
+ bashPatterns: [],
1726
+ references: {},
1727
+ content: `# RevealUI Code Review
1728
+
1729
+ Run this checklist before committing or claiming work is complete.
1730
+
1731
+ ## Automated Checks
1732
+
1733
+ Run each command and confirm clean output:
1734
+
1735
+ \`\`\`bash
1736
+ # 1. Biome lint + format
1737
+ pnpm lint
1738
+
1739
+ # 2. TypeScript \u2014 all packages
1740
+ pnpm typecheck:all
1741
+
1742
+ # 3. Tests \u2014 affected packages
1743
+ pnpm --filter <package> test
1744
+
1745
+ # 4. Quick gate (lint + typecheck + structure)
1746
+ pnpm gate:quick
1747
+ \`\`\`
1748
+
1749
+ ## Manual Checks
1750
+
1751
+ ### Type Safety
1752
+ - [ ] No \`any\` types (use \`unknown\` + type guards)
1753
+ - [ ] No \`as\` casts where \`satisfies\` works
1754
+ - [ ] Exported functions have explicit return types
1755
+ - [ ] \`import type\` used for type-only imports
1756
+
1757
+ ### Code Quality
1758
+ - [ ] No \`console.*\` in production code (use \`@revealui/utils\` logger)
1759
+ - [ ] No hardcoded config values (use parameterization pattern)
1760
+ - [ ] No unused variables/imports (follow decision tree if flagged)
1761
+ - [ ] Single responsibility \u2014 each file does one thing
1762
+
1763
+ ### Architecture
1764
+ - [ ] No Supabase imports outside permitted paths
1765
+ - [ ] No cross-package relative imports (use \`@revealui/<name>\`)
1766
+ - [ ] Internal deps use \`workspace:*\`
1767
+ - [ ] OSS packages don't import from Pro packages
1768
+
1769
+ ### Tailwind v4
1770
+ - [ ] \`bg-(--var)\` not \`bg-[--var]\` for CSS variables
1771
+ - [ ] \`bg-red-500!\` not \`!bg-red-500\` for important
1772
+ - [ ] \`@import "tailwindcss"\` not \`@tailwind\`
1773
+ - [ ] \`@utility\` not \`@layer utilities\`
1774
+ - [ ] \`gap\` preferred over \`space-*\`
1775
+
1776
+ ### Git
1777
+ - [ ] Conventional commit: \`type(scope): description\`
1778
+ - [ ] Subject under 72 characters, imperative mood
1779
+ - [ ] Identity: RevealUI Studio <founder@revealui.com>
1780
+ - [ ] No secrets in committed files`
1781
+ };
1782
+
1783
+ // src/content/definitions/skills/revealui-safety.ts
1784
+ var revealuiSafetySkill = {
1785
+ id: "revealui-safety",
1786
+ tier: "oss",
1787
+ name: "RevealUI Safety",
1788
+ description: "RevealUI safety guardrails for any code task \u2014 editing, writing, creating, fixing,\nrefactoring, changing, adding, updating, or removing files. Protects credentials,\nenforces import boundaries, ensures code quality, and verifies work before completion.",
1789
+ disableModelInvocation: false,
1790
+ skipFrontmatter: false,
1791
+ filePatterns: [],
1792
+ bashPatterns: [],
1793
+ references: {},
1794
+ content: `# RevealUI Safety
1795
+
1796
+ Follow these rules for ALL code changes in the RevealUI monorepo.
1797
+
1798
+ ## Protected Files \u2014 Ask Before Editing
1799
+
1800
+ - \`.env*\` files (\`.env\`, \`.env.local\`, \`.env.production\`, etc.)
1801
+ - Lock files: \`pnpm-lock.yaml\`, \`package-lock.json\`, \`yarn.lock\`
1802
+ - Database schema files in \`packages/db/src/schema/\` \u2014 changes require migration planning
1803
+
1804
+ ## Protected Paths \u2014 Never Edit
1805
+
1806
+ - \`/mnt/c/\`, \`/mnt/e/\` \u2014 Windows mounts (read-only)
1807
+ - System/credential directories: \`/etc/\`, \`~/.ssh/\`, \`~/.gnupg/\`, \`~/.aws/\`
1808
+
1809
+ ## Import Boundaries
1810
+
1811
+ \`@supabase/supabase-js\` is ONLY allowed in:
1812
+
1813
+ - \`packages/db/src/vector/\`, \`packages/db/src/auth/\`
1814
+ - \`packages/auth/src/\`, \`packages/ai/src/\`
1815
+ - \`packages/services/src/supabase/\`
1816
+ - \`apps/*/src/lib/supabase/\`
1817
+
1818
+ FORBIDDEN in: \`packages/core/\`, \`packages/contracts/\`, \`packages/config/\`, \`apps/cms/src/collections/\`, \`apps/cms/src/routes/\`
1819
+
1820
+ ## Code Quality
1821
+
1822
+ - Never use \`any\` \u2014 use \`unknown\` + type guards
1823
+ - Never add \`console.*\` in production code \u2014 use \`@revealui/utils\` logger
1824
+ - Never hardcode API keys, tokens, passwords, or secrets
1825
+ - Use \`crypto.randomInt()\` for security-sensitive values, not \`Math.random()\`
1826
+
1827
+ ## Static Analysis
1828
+
1829
+ - For security and architecture validation scripts, prefer AST-based analysis over regex when the rule depends on syntax or code shape
1830
+ - Use regex only for heuristic inventory scans (for example obvious secret patterns), not as the source of truth for code-security conclusions
1831
+
1832
+ ## After Every Edit
1833
+
1834
+ Run \`npx biome check --write <file>\` on each file you edit before moving on.
1835
+
1836
+ ## Before Claiming Done
1837
+
1838
+ 1. Run \`pnpm gate:quick\` and confirm no new errors
1839
+ 2. Review \`git diff\` for unintended changes
1840
+ 3. Ensure conventional commit format: \`type(scope): description\`
1841
+ 4. Git identity: RevealUI Studio <founder@revealui.com>
1842
+
1843
+ ## Known Limitation
1844
+
1845
+ These rules are advisory. Unlike Claude Code (which enforces via lifecycle hooks), Codex has no hook system. If working on sensitive files, explicitly invoke \`$revealui-safety\` to load these rules.`
1846
+ };
1847
+
1848
+ // src/content/definitions/skills/revealui-tdd.ts
1849
+ var revealuiTddSkill = {
1850
+ id: "revealui-tdd",
1851
+ tier: "pro",
1852
+ name: "RevealUI TDD",
1853
+ description: "Test-driven development workflow for RevealUI. Use when implementing any feature,\nfixing bugs, adding functionality, or writing new code. Enforces write-test-first,\nred-green-refactor cycle. Works with Vitest and React Testing Library.",
1854
+ disableModelInvocation: false,
1855
+ skipFrontmatter: false,
1856
+ filePatterns: [],
1857
+ bashPatterns: [],
1858
+ references: {},
1859
+ content: `# RevealUI TDD Workflow
1860
+
1861
+ Follow this cycle for every code change. No exceptions.
1862
+
1863
+ ## The Cycle
1864
+
1865
+ 1. **Write a failing test** \u2014 describe the expected behavior
1866
+ 2. **Run it** \u2014 confirm it fails for the right reason
1867
+ 3. **Write minimal implementation** \u2014 just enough to pass
1868
+ 4. **Run it** \u2014 confirm it passes
1869
+ 5. **Refactor** \u2014 clean up, then run tests again
1870
+ 6. **Commit** \u2014 one commit per cycle
1871
+
1872
+ ## Commands
1873
+
1874
+ \`\`\`bash
1875
+ # Run tests for a specific package
1876
+ pnpm --filter @revealui/<package> test
1877
+
1878
+ # Run a specific test file
1879
+ pnpm --filter @revealui/<package> test -- <file>
1880
+
1881
+ # Run with coverage
1882
+ pnpm --filter @revealui/<package> test -- --coverage
1883
+ \`\`\`
1884
+
1885
+ ## Test File Conventions
1886
+
1887
+ - Unit/integration: \`*.test.ts\` in \`src/__tests__/\` or adjacent to source
1888
+ - E2E: \`*.e2e.ts\` in \`packages/test/\`
1889
+ - Use \`@revealui/test\` for shared fixtures, mocks, and utilities
1890
+
1891
+ ## What to Test
1892
+
1893
+ - Public API surface of each module
1894
+ - Error paths and edge cases
1895
+ - Integration points between packages
1896
+
1897
+ ## What NOT to Test
1898
+
1899
+ - Private implementation details
1900
+ - Third-party library internals
1901
+ - Type-only code (interfaces, type aliases)
1902
+
1903
+ ## Repo-Specific Patterns
1904
+
1905
+ For concurrency tuning, flaky test triage, and Pro/OSS test boundaries, see the \`$revealui-testing\` skill.
1906
+
1907
+ ## Anti-Patterns
1908
+
1909
+ - Writing implementation before the test
1910
+ - Writing tests that pass immediately (test must fail first)
1911
+ - Testing implementation details instead of behavior
1912
+ - Skipping the refactor step
1913
+ - Large commits with multiple features`
1914
+ };
1915
+
1916
+ // src/content/definitions/skills/revealui-testing.ts
1917
+ var revealuiTestingSkill = {
1918
+ id: "revealui-testing",
1919
+ tier: "oss",
1920
+ name: "RevealUI Testing",
1921
+ description: "RevealUI monorepo testing rules and failure-triage guidance. Use when changing tests,\nfixing flaky suites, adjusting Vitest config, debugging Turbo test failures, handling\nReact Testing Library warnings, or deciding between scoped timeouts, worker limits,\nand test refactors in this repo.",
1922
+ disableModelInvocation: false,
1923
+ skipFrontmatter: false,
1924
+ filePatterns: [],
1925
+ bashPatterns: [],
1926
+ references: {},
1927
+ content: `# RevealUI Testing
1928
+
1929
+ Use this skill after the generic \`vitest\` and \`react-testing-library\` skills when the work is specific to this monorepo.
1930
+
1931
+ ## Use This For
1932
+
1933
+ - \`pnpm test\` or \`pnpm gate --phase=3 --no-build\` failures
1934
+ - Turbo fan-out flakiness that does not reproduce in isolated package runs
1935
+ - Vitest worker/concurrency tuning in \`packages/*\` or \`apps/*\`
1936
+ - React Testing Library \`act(...)\` warnings in this repo
1937
+ - optional Pro package boundaries in tests
1938
+ - deciding whether a failure is a real regression, test debt, or runner pressure
1939
+
1940
+ ## Repo Rules
1941
+
1942
+ ### 1. Prefer Narrow Fixes
1943
+
1944
+ Default order:
1945
+
1946
+ 1. fix the test or component contract if behavior is actually wrong
1947
+ 2. fix stale selectors, bad async assertions, or missing \`await\`
1948
+ 3. add a scoped timeout to the single slow test or suite
1949
+ 4. cap workers for the package if the failure only happens under Turbo fan-out
1950
+ 5. only then consider broader runner changes
1951
+
1952
+ Do not raise global Vitest timeouts just to get green runs.
1953
+
1954
+ ### 2. Treat \u201CPasses Alone, Fails Under Turbo\u201D as Concurrency Pressure First
1955
+
1956
+ If a package passes in isolation but flakes during \`turbo run test\`, assume resource pressure before assuming product logic broke.
1957
+
1958
+ Preferred fix order:
1959
+
1960
+ - specific test timeout for known cold imports or expensive setup
1961
+ - package-level \`fileParallelism: false\` and \`maxWorkers: 1\` for packages with heavy imports, database mocks, or expensive startup
1962
+ - lower Turbo concurrency in the gate if the machine is getting killed or saturated
1963
+
1964
+ This repo already needed that pattern in packages like \`packages/test\` and \`packages/db\`.
1965
+
1966
+ ### 3. Package-Level Vitest Caps Are Acceptable Here
1967
+
1968
+ If a package repeatedly flakes only under monorepo fan-out, it is acceptable to cap that package\u2019s internal Vitest concurrency.
1969
+
1970
+ Typical pattern:
1971
+
1972
+ \`\`\`ts
1973
+ test: {
1974
+ fileParallelism: false,
1975
+ maxWorkers: 1,
1976
+ }
1977
+ \`\`\`
1978
+
1979
+ Use this for:
1980
+
1981
+ - import-smoke suites
1982
+ - packages with heavy module initialization
1983
+ - DB/client/process orchestration tests
1984
+
1985
+ Do not apply it repo-wide by default.
1986
+
1987
+ ### 4. Fix \`act(...)\` Warnings, Don\u2019t Ignore Them
1988
+
1989
+ Common fixes in this repo:
1990
+
1991
+ - use \`await user.click(...)\` instead of \`fireEvent.click(...)\` when the interaction is user-level
1992
+ - use \`findBy*\` or \`waitFor\` when the click triggers async state
1993
+ - assert on the post-update UI state, not just the callback
1994
+ - wrap hook state updates in \`act(...)\` only when there is no better user-facing path
1995
+
1996
+ If a warning remains, explain why the pattern is intentional before adding an ignore.
1997
+
1998
+ ### 5. Prefer \`userEvent\`, Use \`fireEvent\` Sparingly
1999
+
2000
+ Default to \`@testing-library/user-event\` for:
2001
+
2002
+ - clicks
2003
+ - typing
2004
+ - keyboard navigation
2005
+ - focus/blur behavior
2006
+
2007
+ Keep \`fireEvent\` for narrow low-level cases like synthetic events or very small DOM-only transitions.
2008
+
2009
+ ### 6. Optional Pro Packages Must Stay Optional in Public Tests
2010
+
2011
+ Public repo tests must not hard-require private sibling source trees or Pro package source paths.
2012
+
2013
+ Allowed patterns:
2014
+
2015
+ - dynamic import with graceful skip/fallback
2016
+ - separate Pro-only test config/suite
2017
+ - package docs that clearly mark Pro-only flows
2018
+
2019
+ Disallowed patterns:
2020
+
2021
+ - static imports to missing Pro source
2022
+ - default OSS test runs that silently depend on adjacent private repos
2023
+
2024
+ ### 7. Keep OSS and Pro Test Surfaces Honest
2025
+
2026
+ If a test is Pro-only:
2027
+
2028
+ - move it into a Pro-specific directory or config
2029
+ - exclude it from default OSS test runs
2030
+ - do not leave it mixed into the default suite with hidden assumptions
2031
+
2032
+ ### 8. Distinguish Noise from Failure
2033
+
2034
+ Not all stderr is actionable failure in this repo.
2035
+
2036
+ Usually acceptable:
2037
+
2038
+ - intentional error-path logs in tests exercising failure branches
2039
+ - expected jsdom limitations
2040
+ - known parser warnings from fixture-driven negative tests
2041
+
2042
+ Actionable:
2043
+
2044
+ - \`act(...)\` warnings
2045
+ - \`MaxListenersExceededWarning\`
2046
+ - timeouts that only vanish with broad global increases
2047
+ - tests that only pass because of local private package availability
2048
+
2049
+ ## Working Pattern
2050
+
2051
+ When triaging a red test lane:
2052
+
2053
+ 1. rerun the failing package or file directly
2054
+ 2. decide whether it is reproducible in isolation
2055
+ 3. if yes, fix the test/component/implementation
2056
+ 4. if no, treat it as concurrency pressure and tune narrowly
2057
+ 5. rerun the package
2058
+ 6. rerun the gate phase that exposed it
2059
+
2060
+ Do not keep stacking unrelated fixes without re-verifying the exact failing lane.
2061
+
2062
+ ## Gate-Specific Guidance
2063
+
2064
+ - \`pnpm gate --phase=3 --no-build\` is the fastest useful repro for test/build instability
2065
+ - if a gate hang appears, inspect shared process helpers before changing many tests
2066
+ - Turbo warnings about missing outputs are configuration debt, not test correctness
2067
+ - a warning-level test check in the gate still deserves cleanup if it hides real regressions
2068
+
2069
+ ## What Not To Do
2070
+
2071
+ - don\u2019t inflate all test timeouts
2072
+ - don\u2019t disable assertions just to remove flakes
2073
+ - don\u2019t mix Pro-only tests back into OSS-default suites
2074
+ - don\u2019t silence \`act(...)\` or listener warnings when the underlying fix is small
2075
+ - don\u2019t assume a package is stable because it passed alone once`
2076
+ };
2077
+
2078
+ // src/content/definitions/skills/tailwind-4-docs.ts
2079
+ var tailwind4DocsSkill = {
2080
+ id: "tailwind-4-docs",
2081
+ tier: "oss",
2082
+ name: "Tailwind CSS v4 Documentation",
2083
+ description: "Agent-optimized access to Tailwind CSS v4 documentation for answering questions, selecting utilities/variants, configuring Tailwind v4, and avoiding v3\u2192v4 migration pitfalls.",
2084
+ disableModelInvocation: false,
2085
+ skipFrontmatter: true,
2086
+ filePatterns: [],
2087
+ bashPatterns: [],
2088
+ references: {
2089
+ gotchas: `# Tailwind CSS v4 Gotchas (Quick Scan)
2090
+
2091
+ - Browser support is modern-only: Safari 16.4+, Chrome 111+, Firefox 128+.
2092
+ - PostCSS plugin moved to \`@tailwindcss/postcss\`.
2093
+ - CLI moved to \`@tailwindcss/cli\`.
2094
+ - Vite plugin \`@tailwindcss/vite\` is recommended.
2095
+ - Import Tailwind with \`@import "tailwindcss";\` (no \`@tailwind\` directives).
2096
+ - Prefix syntax is \`@import "tailwindcss" prefix(tw);\` and classes use \`tw:\` at the start.
2097
+ - Important modifier goes at the end: \`bg-red-500!\`.
2098
+ - Utility renames and removals: see \`references/docs/upgrade-guide.mdx\` for the full list.
2099
+ - Default border and ring color now use \`currentColor\`; ring width default is 1px.
2100
+ - \`space-*\` and \`divide-*\` selectors changed; use flex/grid with \`gap\` if layouts break.
2101
+ - Custom utilities should use \`@utility\` instead of \`@layer utilities\` or \`@layer components\`.
2102
+ - Stacked variants apply left-to-right (reverse order from v3).
2103
+ - Arbitrary CSS variable syntax is \`bg-(--brand-color)\` (not \`bg-[--brand-color]\`).
2104
+ - Transform reset uses \`scale-none\`, \`rotate-none\`, \`translate-none\` (not \`transform-none\`).
2105
+ - \`hover:\` now only applies on devices that support hover; override if needed.
2106
+ - CSS modules and component \`<style>\` blocks need \`@reference\` to access theme vars.`
2107
+ },
2108
+ content: `# Tailwind CSS v4 Documentation Skill
2109
+
2110
+ ## Purpose
2111
+
2112
+ Agent-optimized access to Tailwind CSS v4 documentation for answering questions, selecting utilities/variants, configuring Tailwind v4, and avoiding v3\u2192v4 migration pitfalls.
2113
+
2114
+ ## Quick Start
2115
+
2116
+ 1. Check if docs snapshot exists: \`references/docs/\` should contain ~194 MDX files
2117
+ 2. If missing or stale, initialize: \`python3 scripts/sync_tailwind_docs.py --accept-docs-license\`
2118
+ 3. Identify the topic category from \`references/docs-index.tsx\`
2119
+ 4. Load the relevant MDX file from \`references/docs/\`
2120
+ 5. Always cross-check against \`references/gotchas.md\` for breaking changes
2121
+
2122
+ ## References
2123
+
2124
+ | Path | Description |
2125
+ |------|-------------|
2126
+ | \`references/docs/\` | Generated MDX docs snapshot (gitignored) |
2127
+ | \`references/docs-index.tsx\` | Category and slug mapping (gitignored) |
2128
+ | \`references/docs-source.txt\` | Upstream repo, commit, and date (gitignored) |
2129
+ | \`references/gotchas.md\` | v4 migration pitfalls and breaking changes (committed) |
2130
+
2131
+ ## MDX Handling
2132
+
2133
+ - Treat \`export const\` statements as metadata
2134
+ - Treat JSX callouts (\`<TipInfo>\`, \`<TipBad>\`, \`<TipGood>\`) as guidance
2135
+ - Code blocks contain working examples
2136
+
2137
+ ## Common Entry Points
2138
+
2139
+ | Topic | File |
2140
+ |-------|------|
2141
+ | Migration from v3 | \`upgrade-guide.mdx\` |
2142
+ | Configuration | \`adding-custom-styles.mdx\` |
2143
+ | Theme | \`theme.mdx\` |
2144
+ | Dark mode | \`dark-mode.mdx\` |
2145
+ | Responsive | \`responsive-design.mdx\` |
2146
+ | Hover/focus/state | \`hover-focus-and-other-states.mdx\` |
2147
+
2148
+ ## Sync Command
2149
+
2150
+ \`\`\`bash
2151
+ python3 .claude/skills/tailwind-4-docs/scripts/sync_tailwind_docs.py --accept-docs-license
2152
+ \`\`\`
2153
+
2154
+ Based on [Lombiq/Tailwind-Agent-Skills](https://github.com/Lombiq/Tailwind-Agent-Skills) (BSD-3-Clause).`
2155
+ };
2156
+
2157
+ // src/content/definitions/skills/index.ts
2158
+ var skills = [
2159
+ dbMigrateSkill,
2160
+ preflightSkill,
2161
+ revealuiConventionsSkill,
2162
+ revealuiDbSkill,
2163
+ revealuiDebuggingSkill,
2164
+ revealuiReviewSkill,
2165
+ revealuiSafetySkill,
2166
+ revealuiTddSkill,
2167
+ revealuiTestingSkill,
2168
+ tailwind4DocsSkill
2169
+ ];
2170
+
2171
+ // src/content/definitions/index.ts
2172
+ function buildManifest() {
2173
+ return {
2174
+ version: 1,
2175
+ generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
2176
+ rules,
2177
+ commands,
2178
+ agents,
2179
+ skills,
2180
+ preambles
2181
+ };
2182
+ }
2183
+
2184
+ // src/content/resolvers/environment.ts
2185
+ var NODE_VERSION = (ctx) => ctx.nodeVersion ?? "24";
2186
+ var PACKAGE_MANAGER = (ctx) => ctx.packageManager ?? "pnpm 10";
2187
+ var STACK = () => "React 19, Next.js 16, Node 24, TypeScript 5.9, Drizzle ORM, Hono, Tailwind v4";
2188
+
2189
+ // src/content/resolvers/project.ts
2190
+ var PROJECT_NAME = (ctx) => ctx.projectName ?? "RevealUI";
2191
+ var PHASE = (ctx) => ctx.phase ?? "Phase 3 \u2014 Launch Preparation";
2192
+ var BRANCH_PIPELINE = () => "feature/* \u2192 develop \u2192 test \u2192 main (production)";
2193
+ var LICENSE_TIERS = () => "free | pro | max | enterprise";
2194
+
2195
+ // src/content/resolvers/index.ts
2196
+ var registry = /* @__PURE__ */ new Map([
2197
+ ["PROJECT_NAME", PROJECT_NAME],
2198
+ ["PHASE", PHASE],
2199
+ ["BRANCH_PIPELINE", BRANCH_PIPELINE],
2200
+ ["LICENSE_TIERS", LICENSE_TIERS],
2201
+ ["NODE_VERSION", NODE_VERSION],
2202
+ ["PACKAGE_MANAGER", PACKAGE_MANAGER],
2203
+ ["STACK", STACK]
2204
+ ]);
2205
+ function registerResolver(key, fn) {
2206
+ registry.set(key, fn);
2207
+ }
2208
+ function resolveTemplate(template, ctx) {
2209
+ return template.replace(/\{\{(\w+)\}\}/g, (_match, key) => {
2210
+ const fn = registry.get(key);
2211
+ return fn ? fn(ctx) : `{{${key}}}`;
2212
+ });
2213
+ }
2214
+ function listResolvers() {
2215
+ return [...registry.keys()];
2216
+ }
2217
+
2218
+ // src/content/generators/claude.ts
2219
+ function buildFrontmatter(fields) {
2220
+ const lines = ["---"];
2221
+ for (const [key, value] of Object.entries(fields)) {
2222
+ if (value === void 0) continue;
2223
+ if (typeof value === "boolean") {
2224
+ lines.push(`${key}: ${value}`);
2225
+ } else if (value.includes("\n")) {
2226
+ lines.push(`${key}: |`);
2227
+ for (const line of value.split("\n")) {
2228
+ lines.push(` ${line}`);
2229
+ }
2230
+ } else {
2231
+ lines.push(`${key}: ${value}`);
2232
+ }
2233
+ }
2234
+ lines.push("---");
2235
+ return lines.join("\n");
2236
+ }
2237
+ var ClaudeCodeGenerator = class {
2238
+ id = "claude-code";
2239
+ outputDir = ".claude";
2240
+ generateRule(rule, ctx) {
2241
+ const content = resolveTemplate(rule.content, ctx);
2242
+ return [
2243
+ {
2244
+ relativePath: `.claude/rules/${rule.id}.md`,
2245
+ content: `${content}
2246
+ `
2247
+ }
2248
+ ];
2249
+ }
2250
+ generateCommand(cmd, ctx) {
2251
+ const content = resolveTemplate(cmd.content, ctx);
2252
+ const frontmatter = buildFrontmatter({
2253
+ description: cmd.description,
2254
+ "disable-model-invocation": cmd.disableModelInvocation || void 0,
2255
+ "argument-hint": cmd.argumentHint
2256
+ });
2257
+ return [
2258
+ {
2259
+ relativePath: `.claude/commands/${cmd.id}.md`,
2260
+ content: `${frontmatter}
2261
+
2262
+ ${content}
2263
+ `
2264
+ }
2265
+ ];
2266
+ }
2267
+ generateAgent(agent, ctx) {
2268
+ const content = resolveTemplate(agent.content, ctx);
2269
+ const frontmatter = buildFrontmatter({
2270
+ name: agent.id,
2271
+ description: agent.description,
2272
+ isolation: agent.isolation === "none" ? void 0 : agent.isolation
2273
+ });
2274
+ return [
2275
+ {
2276
+ relativePath: `.claude/agents/${agent.id}.md`,
2277
+ content: `${frontmatter}
2278
+
2279
+ ${content}
2280
+ `
2281
+ }
2282
+ ];
2283
+ }
2284
+ generateSkill(skill, ctx) {
2285
+ const content = resolveTemplate(skill.content, ctx);
2286
+ const files = [];
2287
+ if (skill.skipFrontmatter) {
2288
+ files.push({
2289
+ relativePath: `.claude/skills/${skill.id}/SKILL.md`,
2290
+ content: `${content}
2291
+ `
2292
+ });
2293
+ } else {
2294
+ const frontmatter = buildFrontmatter({
2295
+ name: skill.id,
2296
+ description: skill.description,
2297
+ "disable-model-invocation": skill.disableModelInvocation || void 0
2298
+ });
2299
+ files.push({
2300
+ relativePath: `.claude/skills/${skill.id}/SKILL.md`,
2301
+ content: `${frontmatter}
2302
+
2303
+ ${content}
2304
+ `
2305
+ });
2306
+ }
2307
+ for (const [name, refContent] of Object.entries(skill.references)) {
2308
+ files.push({
2309
+ relativePath: `.claude/skills/${skill.id}/references/${name}.md`,
2310
+ content: `${resolveTemplate(refContent, ctx)}
2311
+ `
2312
+ });
2313
+ }
2314
+ return files;
2315
+ }
2316
+ generateAll(manifest, ctx) {
2317
+ const files = [];
2318
+ for (const rule of manifest.rules) {
2319
+ files.push(...this.generateRule(rule, ctx));
2320
+ }
2321
+ for (const cmd of manifest.commands) {
2322
+ files.push(...this.generateCommand(cmd, ctx));
2323
+ }
2324
+ for (const agent of manifest.agents) {
2325
+ files.push(...this.generateAgent(agent, ctx));
2326
+ }
2327
+ for (const skill of manifest.skills) {
2328
+ files.push(...this.generateSkill(skill, ctx));
2329
+ }
2330
+ return files;
2331
+ }
2332
+ };
2333
+
2334
+ // src/content/generators/cursor.ts
2335
+ var CursorGenerator = class {
2336
+ id = "cursor";
2337
+ outputDir = ".cursor";
2338
+ generateRule(rule, ctx) {
2339
+ const content = resolveTemplate(rule.content, ctx);
2340
+ return [
2341
+ {
2342
+ relativePath: `.cursor/rules/${rule.id}.mdc`,
2343
+ content: `---
2344
+ description: ${rule.description}
2345
+ ---
2346
+
2347
+ ${content}
2348
+ `
2349
+ }
2350
+ ];
2351
+ }
2352
+ generateCommand(_cmd, _ctx) {
2353
+ return [];
2354
+ }
2355
+ generateAgent(_agent, _ctx) {
2356
+ return [];
2357
+ }
2358
+ generateSkill(_skill, _ctx) {
2359
+ return [];
2360
+ }
2361
+ generateAll(manifest, ctx) {
2362
+ const files = [];
2363
+ for (const rule of manifest.rules) {
2364
+ files.push(...this.generateRule(rule, ctx));
2365
+ }
2366
+ return files;
2367
+ }
2368
+ };
2369
+
2370
+ // src/content/generators/index.ts
2371
+ var generators = /* @__PURE__ */ new Map([
2372
+ ["claude-code", new ClaudeCodeGenerator()],
2373
+ ["cursor", new CursorGenerator()]
2374
+ ]);
2375
+ function getGenerator(id) {
2376
+ return generators.get(id);
2377
+ }
2378
+ function registerGenerator(generator) {
2379
+ generators.set(generator.id, generator);
2380
+ }
2381
+ function listGenerators() {
2382
+ return [...generators.keys()];
2383
+ }
2384
+
2385
+ // src/content/schemas/manifest.ts
2386
+ import { z as z6 } from "zod";
2387
+
2388
+ // src/content/schemas/agent.ts
2389
+ import { z } from "zod";
2390
+ var AgentSchema = z.object({
2391
+ id: z.string().min(1),
2392
+ name: z.string().min(1),
2393
+ description: z.string().min(1),
2394
+ tier: z.enum(["oss", "pro"]).default("oss"),
2395
+ isolation: z.enum(["worktree", "none"]).default("none"),
2396
+ tools: z.array(z.string()).default([]),
2397
+ content: z.string().min(1)
2398
+ });
2399
+
2400
+ // src/content/schemas/command.ts
2401
+ import { z as z2 } from "zod";
2402
+ var CommandSchema = z2.object({
2403
+ id: z2.string().min(1),
2404
+ name: z2.string().min(1),
2405
+ description: z2.string().min(1),
2406
+ tier: z2.enum(["oss", "pro"]).default("oss"),
2407
+ disableModelInvocation: z2.boolean().default(false),
2408
+ argumentHint: z2.string().optional(),
2409
+ content: z2.string().min(1)
2410
+ });
2411
+
2412
+ // src/content/schemas/preamble.ts
2413
+ import { z as z3 } from "zod";
2414
+ var PreambleTierSchema = z3.object({
2415
+ tier: z3.number().int().min(1).max(4),
2416
+ name: z3.string().min(1),
2417
+ description: z3.string().min(1),
2418
+ ruleIds: z3.array(z3.string())
2419
+ });
2420
+
2421
+ // src/content/schemas/rule.ts
2422
+ import { z as z4 } from "zod";
2423
+ var RuleSchema = z4.object({
2424
+ id: z4.string().min(1),
2425
+ name: z4.string().min(1),
2426
+ description: z4.string().min(1),
2427
+ scope: z4.enum(["global", "project"]),
2428
+ preambleTier: z4.number().int().min(1).max(4).default(2),
2429
+ tier: z4.enum(["oss", "pro"]).default("oss"),
2430
+ tags: z4.array(z4.string()).default([]),
2431
+ content: z4.string().min(1)
2432
+ });
2433
+
2434
+ // src/content/schemas/skill.ts
2435
+ import { z as z5 } from "zod";
2436
+ var SkillSchema = z5.object({
2437
+ id: z5.string().min(1),
2438
+ name: z5.string().min(1),
2439
+ description: z5.string().min(1),
2440
+ tier: z5.enum(["oss", "pro"]).default("oss"),
2441
+ disableModelInvocation: z5.boolean().default(false),
2442
+ /** When true, the generator omits YAML frontmatter — the content IS the entire file. */
2443
+ skipFrontmatter: z5.boolean().default(false),
2444
+ filePatterns: z5.array(z5.string()).default([]),
2445
+ bashPatterns: z5.array(z5.string()).default([]),
2446
+ references: z5.record(z5.string(), z5.string()).default({}),
2447
+ content: z5.string().min(1)
2448
+ });
2449
+
2450
+ // src/content/schemas/manifest.ts
2451
+ var ManifestSchema = z6.object({
2452
+ version: z6.literal(1),
2453
+ generatedAt: z6.string().datetime(),
2454
+ rules: z6.array(RuleSchema),
2455
+ commands: z6.array(CommandSchema),
2456
+ agents: z6.array(AgentSchema),
2457
+ skills: z6.array(SkillSchema),
2458
+ preambles: z6.array(PreambleTierSchema)
2459
+ });
2460
+
2461
+ // src/content/index.ts
2462
+ function validateManifest(manifest) {
2463
+ const result = ManifestSchema.safeParse(manifest);
2464
+ if (result.success) {
2465
+ return { valid: true, errors: [] };
2466
+ }
2467
+ return {
2468
+ valid: false,
2469
+ errors: result.error.issues.map((issue) => `${issue.path.join(".")}: ${issue.message}`)
2470
+ };
2471
+ }
2472
+ function generateContent(generatorId, manifest, ctx) {
2473
+ const generator = getGenerator(generatorId);
2474
+ if (!generator) {
2475
+ throw new Error(
2476
+ `Unknown generator "${generatorId}". Available: ${listGenerators().join(", ")}`
2477
+ );
2478
+ }
2479
+ return generator.generateAll(manifest, ctx);
2480
+ }
2481
+ function diffContent(generatorId, manifest, ctx, projectRoot) {
2482
+ const files = generateContent(generatorId, manifest, ctx);
2483
+ const entries = [];
2484
+ for (const file of files) {
2485
+ const absolutePath = resolve(join(projectRoot, file.relativePath));
2486
+ let actual;
2487
+ try {
2488
+ actual = readFileSync(absolutePath, "utf-8");
2489
+ } catch {
2490
+ }
2491
+ if (actual === void 0) {
2492
+ entries.push({ relativePath: file.relativePath, status: "added", expected: file.content });
2493
+ } else if (actual === file.content) {
2494
+ entries.push({ relativePath: file.relativePath, status: "unchanged" });
2495
+ } else {
2496
+ entries.push({
2497
+ relativePath: file.relativePath,
2498
+ status: "modified",
2499
+ expected: file.content,
2500
+ actual
2501
+ });
2502
+ }
2503
+ }
2504
+ return entries;
2505
+ }
2506
+ function listContent(manifest) {
2507
+ const m = manifest ?? buildManifest();
2508
+ return {
2509
+ rules: m.rules.length,
2510
+ commands: m.commands.length,
2511
+ agents: m.agents.length,
2512
+ skills: m.skills.length,
2513
+ preambles: m.preambles.length,
2514
+ total: m.rules.length + m.commands.length + m.agents.length + m.skills.length
2515
+ };
2516
+ }
2517
+
2518
+ export {
2519
+ buildManifest,
2520
+ registerResolver,
2521
+ resolveTemplate,
2522
+ listResolvers,
2523
+ getGenerator,
2524
+ registerGenerator,
2525
+ listGenerators,
2526
+ AgentSchema,
2527
+ CommandSchema,
2528
+ PreambleTierSchema,
2529
+ RuleSchema,
2530
+ SkillSchema,
2531
+ ManifestSchema,
2532
+ validateManifest,
2533
+ generateContent,
2534
+ diffContent,
2535
+ listContent
2536
+ };
2537
+ //# sourceMappingURL=chunk-JDI6B2IB.js.map