@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.
- package/LICENSE.commercial +2 -3
- package/README.md +3 -0
- package/dist/chunk-DGUM43GV.js +11 -0
- package/dist/{chunk-PG4RAOWS.js → chunk-FJGN6DTH.js} +202 -66
- package/dist/chunk-FJGN6DTH.js.map +1 -0
- package/dist/chunk-HH2PJYQN.js +1158 -0
- package/dist/chunk-HH2PJYQN.js.map +1 -0
- package/dist/chunk-JDI6B2IB.js +2537 -0
- package/dist/chunk-JDI6B2IB.js.map +1 -0
- package/dist/cli.js +367 -24
- package/dist/cli.js.map +1 -1
- package/dist/content/index.d.ts +231 -0
- package/dist/content/index.js +40 -0
- package/dist/content/index.js.map +1 -0
- package/dist/index.d.ts +51 -144
- package/dist/index.js +41 -26
- package/dist/index.js.map +1 -1
- package/dist/types/index.d.ts +151 -0
- package/dist/types/index.js +1 -0
- package/dist/types/index.js.map +1 -0
- package/dist/workboard/index.d.ts +44 -3
- package/dist/workboard/index.js +16 -4
- package/package.json +32 -17
- package/dist/chunk-BDA7D725.js +0 -595
- package/dist/chunk-BDA7D725.js.map +0 -1
- package/dist/chunk-JUNNIQS3.js +0 -1
- package/dist/chunk-PG4RAOWS.js.map +0 -1
- /package/dist/{chunk-JUNNIQS3.js.map → chunk-DGUM43GV.js.map} +0 -0
|
@@ -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
|