opencode-andev-rules 1.0.0 → 1.0.2
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 +21 -0
- package/README.md +47 -37
- package/package.json +28 -14
- package/skills/backend/nestJS/SKILL.md +255 -0
- package/skills/backend/nestJS/references/nestjs-module.md +212 -0
- package/skills/backend/nestJS/references/nestjs-testing.md +395 -0
- package/skills/infrastructure/prisma/SKILL.md +65 -0
- package/skills/infrastructure/prisma/references/prisma-queries.md +197 -0
- package/skills/infrastructure/prisma/references/prisma-schema.md +126 -0
- package/skills/registry.json +46 -4
- package/RULES.md +0 -253
- package/plugin.js +0 -96
- /package/skills/{improve-codenase-systems → enhance/improve-codenase-systems}/HTML-REPORT.md +0 -0
- /package/skills/{improve-codenase-systems → enhance/improve-codenase-systems}/SKILL.md +0 -0
- /package/skills/{improve-codenase-systems → enhance/improve-codenase-systems}/agents/openai.yaml +0 -0
- /package/skills/{improve-codenase-systems → enhance/improve-codenase-systems}/meta.json +0 -0
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# Prisma Schema Structure Rules
|
|
2
|
+
|
|
3
|
+
## Layout
|
|
4
|
+
|
|
5
|
+
- Follow this tree exactly — schema, migrations, and seed stay under `prisma/`.
|
|
6
|
+
- Split the schema per domain under `prisma/schema/` — never one giant `schema.prisma`.
|
|
7
|
+
|
|
8
|
+
```
|
|
9
|
+
prisma/
|
|
10
|
+
├── schema/
|
|
11
|
+
│ ├── base.prisma
|
|
12
|
+
│ ├── user.prisma
|
|
13
|
+
│ └── order.prisma
|
|
14
|
+
├── seed.ts
|
|
15
|
+
└── migrations/
|
|
16
|
+
└── 20240101000000_init/
|
|
17
|
+
└── migration.sql
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
- `base.prisma` holds only `generator` + `datasource` — never models or enums in it.
|
|
21
|
+
- One file per domain (`user.prisma`, `order.prisma`, ...) holding its models + enums — never split one model across files.
|
|
22
|
+
- Cross-file relations reference the model by name — Prisma merges all files, no imports needed.
|
|
23
|
+
- One model per table — never two models over the same table.
|
|
24
|
+
|
|
25
|
+
## Models
|
|
26
|
+
|
|
27
|
+
- Model names PascalCase singular with `@@map` to the snake_case table (e.g., `model User ... @@map("users")`).
|
|
28
|
+
- Field names camelCase; map to snake_case columns with `@map` when the database uses snake_case.
|
|
29
|
+
- Every model has a primary key, `createdAt`, and `updatedAt` — never a model without a PK.
|
|
30
|
+
- Primary keys are `String @id @default(uuid())` — never auto-increment ints for IDs.
|
|
31
|
+
- Soft-delete with `deletedAt DateTime?` — always filter it in queries, never return soft-deleted rows by default.
|
|
32
|
+
- Put DB-level defaults in the schema (`@default`, `@updatedAt`) — never rely on application code for timestamps.
|
|
33
|
+
|
|
34
|
+
```prisma
|
|
35
|
+
model User {
|
|
36
|
+
id String @id @default(uuid())
|
|
37
|
+
email String @unique
|
|
38
|
+
name String
|
|
39
|
+
role Role @default(USER)
|
|
40
|
+
createdAt DateTime @default(now())
|
|
41
|
+
updatedAt DateTime @updatedAt
|
|
42
|
+
deletedAt DateTime?
|
|
43
|
+
|
|
44
|
+
@@map("users")
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Enums
|
|
49
|
+
|
|
50
|
+
- Fixed sets (status, role) are Prisma enums — never free strings for status-like fields.
|
|
51
|
+
- Map enum values explicitly when the database stores different labels.
|
|
52
|
+
|
|
53
|
+
```prisma
|
|
54
|
+
enum Role {
|
|
55
|
+
ADMIN
|
|
56
|
+
USER
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Relations
|
|
61
|
+
|
|
62
|
+
- Confirm FK/PK mode first (decision gate in `SKILL.md`) — the rules below assume DB-enforced foreign keys.
|
|
63
|
+
- No-FK mode: skip DB constraints and `onDelete`, enforce integrity in code with existence checks + transactions.
|
|
64
|
+
- Name relations explicitly when two models link more than once — never leave ambiguous relations unnamed.
|
|
65
|
+
- Set `onDelete` deliberately per relation (`Cascade`, `Restrict`, `SetNull`) — never accept the default without thinking; dangerous cascades stay out.
|
|
66
|
+
- Use an explicit relation table for many-to-many that carries extra fields — never overload a pure join with payload columns.
|
|
67
|
+
- Index every foreign key — Prisma does not auto-index all relation columns on every provider.
|
|
68
|
+
|
|
69
|
+
```prisma
|
|
70
|
+
// WITH FK/PK — database enforces the relation
|
|
71
|
+
// schema/user.prisma
|
|
72
|
+
model User {
|
|
73
|
+
id String @id @default(uuid())
|
|
74
|
+
email String @unique
|
|
75
|
+
posts Post[]
|
|
76
|
+
|
|
77
|
+
@@map("users")
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// schema/post.prisma
|
|
81
|
+
model Post {
|
|
82
|
+
id String @id @default(uuid())
|
|
83
|
+
title String
|
|
84
|
+
authorId String
|
|
85
|
+
author User @relation(fields: [authorId], references: [id], onDelete: Cascade)
|
|
86
|
+
|
|
87
|
+
@@index([authorId])
|
|
88
|
+
@@map("posts")
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
```prisma
|
|
93
|
+
// WITHOUT FK/PK — Prisma emulates the relation, DB has no constraints
|
|
94
|
+
// schema/base.prisma
|
|
95
|
+
datasource db {
|
|
96
|
+
provider = "postgresql"
|
|
97
|
+
url = env("DATABASE_URL")
|
|
98
|
+
relationMode = "prisma"
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// schema/post.prisma
|
|
102
|
+
model Post {
|
|
103
|
+
id String @id @default(uuid())
|
|
104
|
+
title String
|
|
105
|
+
authorId String // plain scalar — no FK constraint in the DB
|
|
106
|
+
author User @relation(fields: [authorId], references: [id])
|
|
107
|
+
|
|
108
|
+
@@index([authorId])
|
|
109
|
+
@@map("posts")
|
|
110
|
+
}
|
|
111
|
+
// integrity (author must exist) enforced in code + transactions — see SKILL.md
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## Indexes & Constraints
|
|
115
|
+
|
|
116
|
+
- Add `@@index` for frequently filtered/sorted fields and composite `@@index([a, b])` for common multi-field queries.
|
|
117
|
+
- Add `@@unique` / `@unique` for data that must be unique (email, slug) — enforce in the database, not only in code.
|
|
118
|
+
- Never duplicate or redundant indexes — one index per access pattern.
|
|
119
|
+
- Keep nullable/required aligned across schema, DTO validation, and application types — inconsistent nullability is a bug source.
|
|
120
|
+
|
|
121
|
+
## Migrations
|
|
122
|
+
|
|
123
|
+
- Name migrations after what they do (`add_user_role`, not `update`) — one logical change per migration.
|
|
124
|
+
- Schema changes that need existing rows rewritten ship with a data migration — never lose rows silently.
|
|
125
|
+
- Changing a field type or dropping a column requires a backfill/dual-write plan when the table has data.
|
|
126
|
+
- Never hand-edit `migration.sql` of an applied migration — revert with a new migration instead.
|
package/skills/registry.json
CHANGED
|
@@ -1,15 +1,57 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "andev-skills",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "AI agent skills by thaiannguyen-05",
|
|
5
5
|
"skills": [
|
|
6
6
|
{
|
|
7
7
|
"name": "improve-codenase-systems",
|
|
8
8
|
"description": "Scan codebase for architecture issues and deepening opportunities",
|
|
9
9
|
"version": "1.0.0",
|
|
10
|
-
"tags": [
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
"tags": [
|
|
11
|
+
"architecture",
|
|
12
|
+
"review",
|
|
13
|
+
"nestjs",
|
|
14
|
+
"react",
|
|
15
|
+
"codebase"
|
|
16
|
+
],
|
|
17
|
+
"path": "skills/enhance/improve-codenase-systems",
|
|
18
|
+
"files": [
|
|
19
|
+
"SKILL.md",
|
|
20
|
+
"HTML-REPORT.md",
|
|
21
|
+
"agents/openai.yaml"
|
|
22
|
+
]
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"name": "nestjs",
|
|
26
|
+
"description": "NestJS backend rules — Fastify platform, module structure, zod validation",
|
|
27
|
+
"version": "1.0.0",
|
|
28
|
+
"tags": [
|
|
29
|
+
"nestjs",
|
|
30
|
+
"backend",
|
|
31
|
+
"typescript"
|
|
32
|
+
],
|
|
33
|
+
"path": "skills/backend/nestJS",
|
|
34
|
+
"files": [
|
|
35
|
+
"SKILL.md",
|
|
36
|
+
"references/nestjs-module.md",
|
|
37
|
+
"references/nestjs-testing.md"
|
|
38
|
+
]
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"name": "prisma",
|
|
42
|
+
"description": "Prisma ORM rules — client setup, queries, errors, transactions, migrations",
|
|
43
|
+
"version": "1.0.0",
|
|
44
|
+
"tags": [
|
|
45
|
+
"prisma",
|
|
46
|
+
"database",
|
|
47
|
+
"orm"
|
|
48
|
+
],
|
|
49
|
+
"path": "skills/infrastructure/prisma",
|
|
50
|
+
"files": [
|
|
51
|
+
"SKILL.md",
|
|
52
|
+
"references/prisma-queries.md",
|
|
53
|
+
"references/prisma-schema.md"
|
|
54
|
+
]
|
|
13
55
|
}
|
|
14
56
|
]
|
|
15
57
|
}
|
package/RULES.md
DELETED
|
@@ -1,253 +0,0 @@
|
|
|
1
|
-
# Rules for TypeScript & NestJS
|
|
2
|
-
|
|
3
|
-
## TypeScript
|
|
4
|
-
|
|
5
|
-
- Use `strict: true` in `tsconfig.json`
|
|
6
|
-
- No `any` type — use `unknown` and narrow with type guards
|
|
7
|
-
- Use `interface` for object shapes, `type` for unions/intersections
|
|
8
|
-
- Prefer `readonly` for immutable data
|
|
9
|
-
- Avoid type assertions (`as`) — use type guards or `satisfies` instead
|
|
10
|
-
- Use `!` non-null assertion only when value is guaranteed (add comment why)
|
|
11
|
-
- Export types from barrel files (`index.ts`)
|
|
12
|
-
|
|
13
|
-
## NestJS
|
|
14
|
-
|
|
15
|
-
- Use CLI to generate: `nest g module`, `nest g controller`, `nest g service`
|
|
16
|
-
- One module per feature (e.g., `users/`, `auth/`, `orders/`)
|
|
17
|
-
- Controllers handle HTTP — no business logic in controllers
|
|
18
|
-
- Services handle business logic — no HTTP concerns in services
|
|
19
|
-
- Use `@nestjs/swagger` decorators on DTOs and controllers
|
|
20
|
-
- Inject dependencies via constructor — never instantiate manually
|
|
21
|
-
- Use `@InjectRepository()` for TypeORM/Prisma repositories
|
|
22
|
-
- Use guards for auth (`@UseGuards`), interceptors for logging/transformation
|
|
23
|
-
- Use `ConfigModule` for environment variables — no `process.env` in code
|
|
24
|
-
- Use `@nestjs/schedule` for cron jobs — no `setInterval`
|
|
25
|
-
|
|
26
|
-
## Types
|
|
27
|
-
|
|
28
|
-
- Every module must have a `types.ts` file for module-specific types
|
|
29
|
-
- Export all types from `types.ts` — import from there in other files
|
|
30
|
-
- Use `type.ts` for: enums, interfaces, type aliases, return types
|
|
31
|
-
- Do NOT put types in `dto/` — DTOs are for validation, types are for contracts
|
|
32
|
-
- Import pattern: `import { UserRole } from './types'`
|
|
33
|
-
- Put constants in `types.ts`: event names, URLs, status codes, config values
|
|
34
|
-
- Use `enum` for constants — no hardcoded strings in business logic
|
|
35
|
-
|
|
36
|
-
```typescript
|
|
37
|
-
// types.ts
|
|
38
|
-
export enum EventName {
|
|
39
|
-
CREATED = 'user.created',
|
|
40
|
-
UPDATED = 'user.updated',
|
|
41
|
-
DELETED = 'user.deleted',
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export enum ApiUrl {
|
|
45
|
-
BASE = '/api/v1',
|
|
46
|
-
USERS = '/api/v1/users',
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export interface User { id: string; name: string; }
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
## Validation
|
|
53
|
-
|
|
54
|
-
- Handle ALL validation before controller and service
|
|
55
|
-
- Use global `ValidationPipe` in `main.ts` — reject invalid requests early
|
|
56
|
-
- Use `class-validator` decorators on DTOs
|
|
57
|
-
- Use `class-transformer` with `ValidationPipe` globally
|
|
58
|
-
- Validate nested objects with `@ValidateNested()`
|
|
59
|
-
- Use `@IsString()`, `@IsNumber()`, `@IsEmail()`, `@IsOptional()` etc.
|
|
60
|
-
- Controllers and services receive only valid data — no validation logic inside
|
|
61
|
-
- Use `WhitelistStrategy` + `ForbidNonWhitelisted` to reject unknown fields
|
|
62
|
-
- Use `TransformPipe` to auto-transform payloads to DTO instances
|
|
63
|
-
|
|
64
|
-
```typescript
|
|
65
|
-
// main.ts
|
|
66
|
-
app.useGlobalPipes(
|
|
67
|
-
new ValidationPipe({
|
|
68
|
-
whitelist: true,
|
|
69
|
-
forbidNonWhitelisted: true,
|
|
70
|
-
transform: true,
|
|
71
|
-
}),
|
|
72
|
-
);
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
## Error Handling
|
|
76
|
-
|
|
77
|
-
- Handle errors with exceptions — use custom `AppException` classes
|
|
78
|
-
- Create `src/error/` directory with exception classes and global filter
|
|
79
|
-
- `errorCode` = uppercase snake_case (e.g., `RESOURCE_NOT_FOUND`)
|
|
80
|
-
- Always return consistent JSON: `{ statusCode, timestamp, path, message, errorCode?, details? }`
|
|
81
|
-
- Log unhandled (non-HttpException) errors with logger
|
|
82
|
-
- Create helper files for domain-specific error scenarios
|
|
83
|
-
|
|
84
|
-
```typescript
|
|
85
|
-
// app.exception.ts
|
|
86
|
-
export class AppException extends HttpException {
|
|
87
|
-
constructor(
|
|
88
|
-
message: string,
|
|
89
|
-
statusCode: HttpStatus,
|
|
90
|
-
public readonly errorCode?: string,
|
|
91
|
-
public readonly details?: unknown,
|
|
92
|
-
) {
|
|
93
|
-
super({ message, errorCode, details, timestamp: new Date().toISOString() }, statusCode);
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
export class ResourceNotFoundException extends AppException {
|
|
98
|
-
constructor(resourceType: string, identifier: string | number) {
|
|
99
|
-
super(`${resourceType} with identifier ${identifier} not found`, HttpStatus.NOT_FOUND, 'RESOURCE_NOT_FOUND');
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
```typescript
|
|
105
|
-
// main.ts
|
|
106
|
-
app.useGlobalFilters(new GlobalExceptionFilter(logger));
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
## Database
|
|
110
|
-
|
|
111
|
-
- Use Prisma or TypeORM — pick one, don't mix
|
|
112
|
-
- Keep migrations in `prisma/migrations` or `src/migrations`
|
|
113
|
-
- Use repositories or Prisma client for data access
|
|
114
|
-
- Never write raw SQL unless performance-critical (add comment why)
|
|
115
|
-
- Use `select` when only a subset of fields is required — don't over-fetch
|
|
116
|
-
- Avoid N+1 queries — use `include` or joins, not loops
|
|
117
|
-
- Run independent queries in parallel — don't `await` sequentially
|
|
118
|
-
- Use `findFirst` only when `findUnique` is possible
|
|
119
|
-
- Paginate `findMany` — never return unbounded results
|
|
120
|
-
- Use cursor pagination for large datasets, offset for small
|
|
121
|
-
- Always `orderBy` deterministic fields for pagination
|
|
122
|
-
- Handle Prisma errors — never leak raw Prisma errors to API responses
|
|
123
|
-
- Use transactions for multi-step operations — no partial writes
|
|
124
|
-
- Keep transaction scope small — no external calls inside transactions
|
|
125
|
-
- Race conditions on read-modify-write — use transactions or locks
|
|
126
|
-
- Add unique constraints for data that must be unique
|
|
127
|
-
- Soft-delete: always filter `deletedAt` in queries
|
|
128
|
-
- Avoid `include` for large relation collections — paginate or select
|
|
129
|
-
|
|
130
|
-
## Testing
|
|
131
|
-
|
|
132
|
-
- Use Jest (built into NestJS)
|
|
133
|
-
- Unit tests: `*.spec.ts` next to source files
|
|
134
|
-
- E2E tests: `test/*.e2e-spec.ts`
|
|
135
|
-
- Mock dependencies with `@nestjs/testing` `Test.createTestingModule()`
|
|
136
|
-
- Test controllers and services separately
|
|
137
|
-
- Use `supertest` for HTTP assertions in e2e
|
|
138
|
-
|
|
139
|
-
## Async & Concurrency
|
|
140
|
-
|
|
141
|
-
- Run independent async operations in parallel — don't `await` sequentially
|
|
142
|
-
- Always handle promise rejections — no fire-and-forget without error handling
|
|
143
|
-
- Add timeout for external service calls
|
|
144
|
-
- Use idempotency keys for retryable operations
|
|
145
|
-
- Retry with limits and exponential backoff
|
|
146
|
-
- Never retry non-idempotent operations unsafely
|
|
147
|
-
- Race conditions: use transactions or locks for read-modify-write
|
|
148
|
-
|
|
149
|
-
## Security
|
|
150
|
-
|
|
151
|
-
- Never hardcode secrets or credentials — use `ConfigModule`
|
|
152
|
-
- Never expose sensitive data in API responses
|
|
153
|
-
- Validate and sanitize all user input
|
|
154
|
-
- Prevent IDOR — check resource ownership
|
|
155
|
-
- Use parameterized queries — no raw SQL concatenation
|
|
156
|
-
- Validate file uploads: size, type, content
|
|
157
|
-
- Never trust client-provided file metadata
|
|
158
|
-
- Secure CORS configuration — no wildcard in production
|
|
159
|
-
- Rate limit sensitive endpoints (login, register, password reset)
|
|
160
|
-
- Never log sensitive data (passwords, tokens, PII)
|
|
161
|
-
- Use guards for auth — no manual auth checks in controllers
|
|
162
|
-
|
|
163
|
-
## API Design
|
|
164
|
-
|
|
165
|
-
- Consistent REST naming: plural nouns, HTTP verbs for actions
|
|
166
|
-
- Consistent error response format: `{ statusCode, message, errorCode }`
|
|
167
|
-
- Paginate all list endpoints — no unbounded responses
|
|
168
|
-
- Filter and limit query parameters
|
|
169
|
-
- Version API when making breaking changes
|
|
170
|
-
- Use appropriate HTTP status codes (201 for create, 204 for delete)
|
|
171
|
-
- Never expose internal implementation details in responses
|
|
172
|
-
|
|
173
|
-
## Observability
|
|
174
|
-
|
|
175
|
-
- Use structured logging (nestjs-pino)
|
|
176
|
-
- Never log sensitive data
|
|
177
|
-
- Propagate request/correlation IDs
|
|
178
|
-
- Add health check endpoints for critical dependencies
|
|
179
|
-
- Handle graceful shutdown — clean up connections
|
|
180
|
-
- Clean up timers, listeners, subscriptions
|
|
181
|
-
- Handle background job failures
|
|
182
|
-
|
|
183
|
-
## File Structure
|
|
184
|
-
|
|
185
|
-
```
|
|
186
|
-
andev-skill-agent/
|
|
187
|
-
├── .git/
|
|
188
|
-
├── package.json # @thaiannguyen-05/opencode-rules
|
|
189
|
-
├── plugin.js # trigger detection + GitHub fetch
|
|
190
|
-
├── README.md # usage docs
|
|
191
|
-
└── RULES.md # this file — rules for agents
|
|
192
|
-
```
|
|
193
|
-
|
|
194
|
-
### NestJS Project Structure
|
|
195
|
-
|
|
196
|
-
```
|
|
197
|
-
src/
|
|
198
|
-
├── app.module.ts
|
|
199
|
-
├── main.ts
|
|
200
|
-
├── config/
|
|
201
|
-
│ └── configuration.ts
|
|
202
|
-
├── common/
|
|
203
|
-
│ ├── guards/
|
|
204
|
-
│ ├── interceptors/
|
|
205
|
-
│ ├── pipes/
|
|
206
|
-
│ └── decorators/
|
|
207
|
-
├── error/
|
|
208
|
-
│ ├── app.exception.ts
|
|
209
|
-
│ ├── global.exception.ts
|
|
210
|
-
│ └── [domain]-error.helper.ts
|
|
211
|
-
├── modules/
|
|
212
|
-
│ ├── users/
|
|
213
|
-
│ │ ├── users.module.ts
|
|
214
|
-
│ │ ├── users.controller.ts
|
|
215
|
-
│ │ ├── users.service.ts
|
|
216
|
-
│ │ ├── types.ts
|
|
217
|
-
│ │ ├── dto/
|
|
218
|
-
│ │ └── entities/
|
|
219
|
-
│ ├── auth/
|
|
220
|
-
│ │ ├── auth.module.ts
|
|
221
|
-
│ │ ├── auth.controller.ts
|
|
222
|
-
│ │ ├── auth.service.ts
|
|
223
|
-
│ │ ├── types.ts
|
|
224
|
-
│ │ ├── dto/
|
|
225
|
-
│ │ └── entities/
|
|
226
|
-
│ └── orders/
|
|
227
|
-
│ ├── orders.module.ts
|
|
228
|
-
│ ├── orders.controller.ts
|
|
229
|
-
│ ├── orders.service.ts
|
|
230
|
-
│ ├── types.ts
|
|
231
|
-
│ ├── dto/
|
|
232
|
-
│ └── entities/
|
|
233
|
-
```
|
|
234
|
-
|
|
235
|
-
## Code Style
|
|
236
|
-
|
|
237
|
-
- Use Prettier for formatting
|
|
238
|
-
- Use ESLint with `@typescript-eslint` rules
|
|
239
|
-
- Max 300 lines per file — split if超过
|
|
240
|
-
- One export per file — no barrel exports in middle of file
|
|
241
|
-
- Sort imports: node builtins → external → internal → relative
|
|
242
|
-
- Use `path aliases` (`@/`) for clean imports
|
|
243
|
-
- Prefer `async/await` over `.then()` chains
|
|
244
|
-
- Use `enum` for constants — no hardcoded strings
|
|
245
|
-
|
|
246
|
-
```json
|
|
247
|
-
// .eslintrc
|
|
248
|
-
{
|
|
249
|
-
"rules": {
|
|
250
|
-
"max-lines": ["error", { "max": 300, "skipBlankLines": true, "skipComments": true }]
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
```
|
package/plugin.js
DELETED
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
// @thaiannguyen-05/opencode-rules
|
|
2
|
-
//
|
|
3
|
-
// On-demand rule injection plugin for opencode.
|
|
4
|
-
// When user says "follow the rule of andev" (or similar), fetches RULES.md
|
|
5
|
-
// from GitHub and injects it into the system prompt.
|
|
6
|
-
//
|
|
7
|
-
// Hooks:
|
|
8
|
-
// - chat.message: detect trigger phrase in user input
|
|
9
|
-
// - experimental.chat.system.transform: inject rules into system prompt
|
|
10
|
-
|
|
11
|
-
const RULES_URL = 'https://raw.githubusercontent.com/thaiannguyen-05/rules-for-global-agents/main/RULES.md';
|
|
12
|
-
|
|
13
|
-
// Trigger patterns — case-insensitive
|
|
14
|
-
const TRIGGER_PATTERNS = [
|
|
15
|
-
/follow\s+(the\s+)?rules?\s+of\s+andev/i,
|
|
16
|
-
/follow\s+andev\s+rules?/i,
|
|
17
|
-
/use\s+andev\s+rules?/i,
|
|
18
|
-
/apply\s+andev\s+rules?/i,
|
|
19
|
-
/andev\s+rules/i,
|
|
20
|
-
];
|
|
21
|
-
|
|
22
|
-
// In-memory cache: rules text per session
|
|
23
|
-
let cachedRules = null;
|
|
24
|
-
let fetchFailed = false;
|
|
25
|
-
|
|
26
|
-
function detectTrigger(text) {
|
|
27
|
-
if (!text) return false;
|
|
28
|
-
return TRIGGER_PATTERNS.some((pattern) => pattern.test(text));
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
async function fetchRules() {
|
|
32
|
-
// Return cache if available
|
|
33
|
-
if (cachedRules !== null) return cachedRules;
|
|
34
|
-
|
|
35
|
-
// Don't retry if fetch already failed
|
|
36
|
-
if (fetchFailed) return null;
|
|
37
|
-
|
|
38
|
-
try {
|
|
39
|
-
const response = await fetch(RULES_URL, {
|
|
40
|
-
headers: { Accept: 'text/plain' },
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
if (!response.ok) {
|
|
44
|
-
fetchFailed = true;
|
|
45
|
-
return null;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
const text = await response.text();
|
|
49
|
-
|
|
50
|
-
if (!text || text.trim().length === 0) {
|
|
51
|
-
fetchFailed = true;
|
|
52
|
-
return null;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
cachedRules = text;
|
|
56
|
-
return cachedRules;
|
|
57
|
-
} catch {
|
|
58
|
-
fetchFailed = true;
|
|
59
|
-
return null;
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
export const AndevRulesPlugin = async (_ctx) => {
|
|
64
|
-
let triggerDetected = false;
|
|
65
|
-
|
|
66
|
-
return {
|
|
67
|
-
// Detect trigger phrase in user messages
|
|
68
|
-
'chat.message': async (_input, output) => {
|
|
69
|
-
if (!output || !output.parts) return;
|
|
70
|
-
|
|
71
|
-
for (const part of output.parts) {
|
|
72
|
-
if (part && part.type === 'text' && part.text) {
|
|
73
|
-
if (detectTrigger(part.text)) {
|
|
74
|
-
triggerDetected = true;
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
},
|
|
79
|
-
|
|
80
|
-
// Inject rules into system prompt when trigger was detected
|
|
81
|
-
'experimental.chat.system.transform': async (_input, output) => {
|
|
82
|
-
if (!output || !Array.isArray(output.system)) return;
|
|
83
|
-
if (!triggerDetected) return;
|
|
84
|
-
|
|
85
|
-
const rules = await fetchRules();
|
|
86
|
-
if (rules) {
|
|
87
|
-
output.system.push(`## Rules from andev (follow these rules)\n\n${rules}`);
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
// Reset trigger for next message
|
|
91
|
-
triggerDetected = false;
|
|
92
|
-
},
|
|
93
|
-
};
|
|
94
|
-
};
|
|
95
|
-
|
|
96
|
-
export default AndevRulesPlugin;
|
/package/skills/{improve-codenase-systems → enhance/improve-codenase-systems}/HTML-REPORT.md
RENAMED
|
File without changes
|
|
File without changes
|
/package/skills/{improve-codenase-systems → enhance/improve-codenase-systems}/agents/openai.yaml
RENAMED
|
File without changes
|
|
File without changes
|