@ryuenn3123/agentic-senior-core 2.5.22 → 3.0.0
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/.agent-context/prompts/init-project.md +5 -5
- package/.agent-context/prompts/refactor.md +2 -1
- package/.agent-context/prompts/review-code.md +3 -2
- package/.agent-context/review-checklists/pr-checklist.md +8 -1
- package/.agent-context/rules/architecture.md +11 -0
- package/.agent-context/rules/frontend-architecture.md +2 -2
- package/.agent-context/state/architecture-map.md +1 -1
- package/.agent-context/state/memory-continuity-benchmark.json +1 -1
- package/.agents/workflows/init-project.md +3 -3
- package/.agents/workflows/refactor.md +1 -1
- package/.agents/workflows/review-code.md +4 -5
- package/.cursorrules +27 -71
- package/.gemini/instructions.md +6 -7
- package/.github/copilot-instructions.md +5 -6
- package/.windsurfrules +27 -71
- package/AGENTS.md +7 -9
- package/CONTRIBUTING.md +18 -31
- package/README.md +21 -4
- package/bin/agentic-senior-core.js +0 -6
- package/lib/cli/commands/init.mjs +113 -650
- package/lib/cli/commands/launch.mjs +1 -23
- package/lib/cli/commands/rollback.mjs +1 -1
- package/lib/cli/commands/upgrade.mjs +1 -23
- package/lib/cli/compiler.mjs +77 -72
- package/lib/cli/constants.mjs +84 -26
- package/lib/cli/init-architecture-flow.mjs +231 -0
- package/lib/cli/init-detection-flow.mjs +123 -0
- package/lib/cli/init-options.mjs +344 -0
- package/lib/cli/init-selection.mjs +100 -0
- package/lib/cli/preflight.mjs +1 -1
- package/lib/cli/profile-packs.mjs +15 -1
- package/lib/cli/project-scaffolder.mjs +18 -154
- package/lib/cli/utils.mjs +16 -12
- package/mcp.json +19 -19
- package/package.json +5 -2
- package/scripts/context-triggered-audit.mjs +18 -18
- package/scripts/documentation-boundary-audit.mjs +92 -5
- package/scripts/forbidden-content-check.mjs +1 -1
- package/scripts/frontend-usability-audit.mjs +21 -28
- package/scripts/governance-weekly-report.mjs +29 -15
- package/scripts/llm-judge.mjs +2 -5
- package/scripts/mcp-server.mjs +389 -5
- package/scripts/release-gate.mjs +121 -145
- package/scripts/sync-thin-adapters.mjs +161 -0
- package/scripts/v3-purge-audit.mjs +231 -0
- package/scripts/validate-evidence-bundle.mjs +1 -1
- package/scripts/validate.mjs +224 -272
- package/.agent-context/blueprints/api-nextjs.md +0 -184
- package/.agent-context/blueprints/aspnet-api.md +0 -247
- package/.agent-context/blueprints/ci-github-actions.md +0 -226
- package/.agent-context/blueprints/ci-gitlab.md +0 -200
- package/.agent-context/blueprints/fastapi-service.md +0 -210
- package/.agent-context/blueprints/go-service.md +0 -217
- package/.agent-context/blueprints/graphql-grpc-api.md +0 -51
- package/.agent-context/blueprints/infrastructure-as-code.md +0 -62
- package/.agent-context/blueprints/kubernetes-manifests.md +0 -76
- package/.agent-context/blueprints/laravel-api.md +0 -233
- package/.agent-context/blueprints/mobile-app.md +0 -91
- package/.agent-context/blueprints/nestjs-logic.md +0 -247
- package/.agent-context/blueprints/observability.md +0 -227
- package/.agent-context/blueprints/spring-boot-api.md +0 -218
- package/.agent-context/profiles/platform.md +0 -13
- package/.agent-context/profiles/regulated.md +0 -13
- package/.agent-context/profiles/startup.md +0 -13
- package/.agent-context/review-checklists/frontend-excellence-rubric.md +0 -73
- package/.agent-context/review-checklists/frontend-skill-parity.md +0 -29
- package/.agent-context/review-checklists/frontend-usability.md +0 -35
- package/.agent-context/review-checklists/marketplace-acceptance.md +0 -60
- package/.agent-context/review-checklists/performance-audit.md +0 -71
- package/.agent-context/review-checklists/release-operations.md +0 -33
- package/.agent-context/review-checklists/security-audit.md +0 -119
- package/.agent-context/skills/README.md +0 -63
- package/.agent-context/skills/backend/README.md +0 -68
- package/.agent-context/skills/backend/architecture.md +0 -361
- package/.agent-context/skills/backend/compatibility-manifest.json +0 -8
- package/.agent-context/skills/backend/data-access.md +0 -231
- package/.agent-context/skills/backend/errors.md +0 -138
- package/.agent-context/skills/backend/validation.md +0 -117
- package/.agent-context/skills/backend.md +0 -29
- package/.agent-context/skills/cli/.evidence/compatibility-manifest.json +0 -5
- package/.agent-context/skills/cli/.evidence/sbom-excerpt.json +0 -10
- package/.agent-context/skills/cli/.evidence/test-report.json +0 -8
- package/.agent-context/skills/cli/CHANGELOG.md +0 -6
- package/.agent-context/skills/cli/README.md +0 -56
- package/.agent-context/skills/cli/compatibility-manifest.json +0 -8
- package/.agent-context/skills/cli/init.md +0 -38
- package/.agent-context/skills/cli/output.md +0 -36
- package/.agent-context/skills/cli/package.json +0 -5
- package/.agent-context/skills/cli/safety-telemetry.md +0 -39
- package/.agent-context/skills/cli/tests/.gitkeep +0 -1
- package/.agent-context/skills/cli/upgrade.md +0 -38
- package/.agent-context/skills/cli.md +0 -32
- package/.agent-context/skills/distribution/.evidence/compatibility-manifest.json +0 -9
- package/.agent-context/skills/distribution/.evidence/sbom-excerpt.json +0 -6
- package/.agent-context/skills/distribution/.evidence/test-report.json +0 -8
- package/.agent-context/skills/distribution/CHANGELOG.md +0 -7
- package/.agent-context/skills/distribution/README.md +0 -27
- package/.agent-context/skills/distribution/compatibility-manifest.json +0 -8
- package/.agent-context/skills/distribution/compatibility.md +0 -32
- package/.agent-context/skills/distribution/package.json +0 -5
- package/.agent-context/skills/distribution/provenance-attestation.md +0 -47
- package/.agent-context/skills/distribution/publish.md +0 -37
- package/.agent-context/skills/distribution/rollback.md +0 -32
- package/.agent-context/skills/distribution/tests/.gitkeep +0 -1
- package/.agent-context/skills/distribution.md +0 -32
- package/.agent-context/skills/frontend/.evidence/compatibility-manifest.json +0 -9
- package/.agent-context/skills/frontend/.evidence/sbom-excerpt.json +0 -6
- package/.agent-context/skills/frontend/.evidence/test-report.json +0 -8
- package/.agent-context/skills/frontend/CHANGELOG.md +0 -7
- package/.agent-context/skills/frontend/README.md +0 -50
- package/.agent-context/skills/frontend/accessibility.md +0 -107
- package/.agent-context/skills/frontend/compatibility-manifest.json +0 -8
- package/.agent-context/skills/frontend/conversion-clarity.md +0 -51
- package/.agent-context/skills/frontend/motion.md +0 -67
- package/.agent-context/skills/frontend/package.json +0 -5
- package/.agent-context/skills/frontend/performance.md +0 -63
- package/.agent-context/skills/frontend/responsive-delivery.md +0 -41
- package/.agent-context/skills/frontend/tests/.gitkeep +0 -1
- package/.agent-context/skills/frontend/ui-architecture.md +0 -128
- package/.agent-context/skills/frontend.md +0 -40
- package/.agent-context/skills/fullstack/.evidence/compatibility-manifest.json +0 -9
- package/.agent-context/skills/fullstack/.evidence/sbom-excerpt.json +0 -6
- package/.agent-context/skills/fullstack/.evidence/test-report.json +0 -8
- package/.agent-context/skills/fullstack/CHANGELOG.md +0 -7
- package/.agent-context/skills/fullstack/README.md +0 -27
- package/.agent-context/skills/fullstack/compatibility-manifest.json +0 -8
- package/.agent-context/skills/fullstack/contracts.md +0 -53
- package/.agent-context/skills/fullstack/end-to-end.md +0 -42
- package/.agent-context/skills/fullstack/feature-slicing.md +0 -65
- package/.agent-context/skills/fullstack/package.json +0 -5
- package/.agent-context/skills/fullstack/release-coordination.md +0 -51
- package/.agent-context/skills/fullstack/tests/.gitkeep +0 -1
- package/.agent-context/skills/fullstack.md +0 -30
- package/.agent-context/skills/index.json +0 -107
- package/.agent-context/skills/review-quality/.evidence/compatibility-manifest.json +0 -9
- package/.agent-context/skills/review-quality/.evidence/sbom-excerpt.json +0 -6
- package/.agent-context/skills/review-quality/.evidence/test-report.json +0 -8
- package/.agent-context/skills/review-quality/CHANGELOG.md +0 -7
- package/.agent-context/skills/review-quality/README.md +0 -27
- package/.agent-context/skills/review-quality/benchmark.md +0 -30
- package/.agent-context/skills/review-quality/compatibility-manifest.json +0 -8
- package/.agent-context/skills/review-quality/package.json +0 -5
- package/.agent-context/skills/review-quality/planning.md +0 -38
- package/.agent-context/skills/review-quality/release-decision.md +0 -49
- package/.agent-context/skills/review-quality/security.md +0 -34
- package/.agent-context/skills/review-quality/tests/.gitkeep +0 -1
- package/.agent-context/skills/review-quality.md +0 -34
- package/.agent-context/stacks/csharp.md +0 -149
- package/.agent-context/stacks/flutter.md +0 -16
- package/.agent-context/stacks/go.md +0 -181
- package/.agent-context/stacks/java.md +0 -135
- package/.agent-context/stacks/php.md +0 -192
- package/.agent-context/stacks/python.md +0 -153
- package/.agent-context/stacks/react-native.md +0 -16
- package/.agent-context/stacks/ruby.md +0 -80
- package/.agent-context/stacks/rust.md +0 -86
- package/.agent-context/stacks/typescript.md +0 -317
- package/.agent-context/state/skill-platform.json +0 -38
- package/lib/cli/skill-selector.mjs +0 -232
- package/lib/cli/templates/api-contract.md.id.tmpl +0 -143
- package/lib/cli/templates/api-contract.md.tmpl +0 -143
- package/lib/cli/templates/architecture-decision-record.md.id.tmpl +0 -106
- package/lib/cli/templates/architecture-decision-record.md.tmpl +0 -145
- package/lib/cli/templates/database-schema.md.id.tmpl +0 -74
- package/lib/cli/templates/database-schema.md.tmpl +0 -74
- package/lib/cli/templates/flow-overview.md.id.tmpl +0 -118
- package/lib/cli/templates/flow-overview.md.tmpl +0 -131
- package/lib/cli/templates/project-brief.md.id.tmpl +0 -55
- package/lib/cli/templates/project-brief.md.tmpl +0 -79
- package/scripts/init-project.ps1 +0 -105
- package/scripts/init-project.sh +0 -131
- package/scripts/skill-tier-policy.mjs +0 -76
- package/scripts/trust-scorer.mjs +0 -119
|
@@ -1,317 +0,0 @@
|
|
|
1
|
-
# TypeScript Stack Profile — The "Galak" Standard
|
|
2
|
-
|
|
3
|
-
> TypeScript is not JavaScript with optional types.
|
|
4
|
-
> It is a contract system. Use it like one.
|
|
5
|
-
|
|
6
|
-
## Compiler Configuration (Non-Negotiable)
|
|
7
|
-
|
|
8
|
-
### tsconfig.json Strict Settings
|
|
9
|
-
```json
|
|
10
|
-
{
|
|
11
|
-
"compilerOptions": {
|
|
12
|
-
"strict": true,
|
|
13
|
-
"noUncheckedIndexedAccess": true,
|
|
14
|
-
"noImplicitReturns": true,
|
|
15
|
-
"noFallthroughCasesInSwitch": true,
|
|
16
|
-
"noUnusedLocals": true,
|
|
17
|
-
"noUnusedParameters": true,
|
|
18
|
-
"exactOptionalPropertyTypes": true,
|
|
19
|
-
"forceConsistentCasingInFileNames": true,
|
|
20
|
-
"isolatedModules": true,
|
|
21
|
-
"esModuleInterop": true,
|
|
22
|
-
"resolveJsonModule": true,
|
|
23
|
-
"moduleResolution": "bundler",
|
|
24
|
-
"module": "ESNext",
|
|
25
|
-
"target": "ES2022",
|
|
26
|
-
"skipLibCheck": true,
|
|
27
|
-
"paths": {
|
|
28
|
-
"@/*": ["./src/*"]
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
**Rule:** `"strict": true` is mandatory. If a project has `"strict": false`, fix it before writing any new code.
|
|
35
|
-
|
|
36
|
-
---
|
|
37
|
-
|
|
38
|
-
## The `any` Ban (Zero Tolerance)
|
|
39
|
-
|
|
40
|
-
### Rule: `any` is BANNED. No exceptions.
|
|
41
|
-
|
|
42
|
-
```typescript
|
|
43
|
-
// ❌ INSTANT REJECTION
|
|
44
|
-
function processData(data: any) { ... }
|
|
45
|
-
const result = response.json() as any;
|
|
46
|
-
// @ts-ignore
|
|
47
|
-
// @ts-expect-error — only allowed with a comment explaining WHY and a linked issue
|
|
48
|
-
|
|
49
|
-
// ✅ REQUIRED: Use `unknown` with type narrowing
|
|
50
|
-
function processData(data: unknown) {
|
|
51
|
-
const parsed = DataSchema.parse(data); // Zod validates and narrows
|
|
52
|
-
// `parsed` is now fully typed
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// ✅ REQUIRED: Use generics when the type varies
|
|
56
|
-
function getFirstItem<T>(items: T[]): T | undefined {
|
|
57
|
-
return items[0];
|
|
58
|
-
}
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
### What to Use Instead of `any`
|
|
62
|
-
| Situation | Instead of `any`, Use |
|
|
63
|
-
|-----------|----------------------|
|
|
64
|
-
| Unknown external data | `unknown` + Zod parsing |
|
|
65
|
-
| Generic container | `T` (generic type parameter) |
|
|
66
|
-
| Object with unknown keys | `Record<string, unknown>` |
|
|
67
|
-
| Function argument you'll refine | `unknown` + type guard |
|
|
68
|
-
| Library with bad types | Write a `.d.ts` override or `unknown` wrapper |
|
|
69
|
-
| Event handlers | The specific event type (`MouseEvent`, `ChangeEvent<HTMLInputElement>`) |
|
|
70
|
-
|
|
71
|
-
---
|
|
72
|
-
|
|
73
|
-
## Zod at Boundaries (Mandatory)
|
|
74
|
-
|
|
75
|
-
### Rule: ALL External Data MUST Pass Through Zod
|
|
76
|
-
|
|
77
|
-
```typescript
|
|
78
|
-
// ❌ BANNED: Trusting external data
|
|
79
|
-
app.post('/users', async (req, res) => {
|
|
80
|
-
const { name, email, age } = req.body; // Could be anything!
|
|
81
|
-
await userService.create({ name, email, age });
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
// ✅ REQUIRED: Validate with Zod at the boundary
|
|
85
|
-
import { z } from 'zod';
|
|
86
|
-
|
|
87
|
-
const CreateUserSchema = z.object({
|
|
88
|
-
name: z.string().min(1).max(100).trim(),
|
|
89
|
-
email: z.string().email().toLowerCase(),
|
|
90
|
-
age: z.number().int().min(13).max(150),
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
type CreateUserDto = z.infer<typeof CreateUserSchema>;
|
|
94
|
-
|
|
95
|
-
app.post('/users', async (req, res) => {
|
|
96
|
-
const parsed = CreateUserSchema.safeParse(req.body);
|
|
97
|
-
if (!parsed.success) {
|
|
98
|
-
return res.status(400).json({ errors: parsed.error.flatten() });
|
|
99
|
-
}
|
|
100
|
-
// `parsed.data` is fully typed and validated
|
|
101
|
-
await userService.create(parsed.data);
|
|
102
|
-
});
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
### Where Zod is MANDATORY
|
|
106
|
-
- API request bodies (POST, PUT, PATCH)
|
|
107
|
-
- Query parameters and path parameters
|
|
108
|
-
- WebSocket incoming messages
|
|
109
|
-
- Queue/event payloads from external systems
|
|
110
|
-
- Environment variables at startup
|
|
111
|
-
- Third-party API responses (trust but verify)
|
|
112
|
-
- File upload metadata
|
|
113
|
-
|
|
114
|
-
### Zod Best Practices
|
|
115
|
-
```typescript
|
|
116
|
-
// ✅ Reuse schemas — define once, use everywhere
|
|
117
|
-
// src/modules/user/user.schema.ts
|
|
118
|
-
export const UserSchema = z.object({
|
|
119
|
-
id: z.string().uuid(),
|
|
120
|
-
email: z.string().email(),
|
|
121
|
-
name: z.string().min(1).max(100),
|
|
122
|
-
role: z.enum(['user', 'admin', 'moderator']),
|
|
123
|
-
createdAt: z.coerce.date(),
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
export const CreateUserSchema = UserSchema.omit({ id: true, createdAt: true });
|
|
127
|
-
export const UpdateUserSchema = CreateUserSchema.partial();
|
|
128
|
-
|
|
129
|
-
// Types derived from schemas — single source of truth
|
|
130
|
-
export type User = z.infer<typeof UserSchema>;
|
|
131
|
-
export type CreateUserDto = z.infer<typeof CreateUserSchema>;
|
|
132
|
-
export type UpdateUserDto = z.infer<typeof UpdateUserSchema>;
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
---
|
|
136
|
-
|
|
137
|
-
## API Documentation (Mandatory)
|
|
138
|
-
|
|
139
|
-
### Rule: No API Endpoint Exists Without Documentation
|
|
140
|
-
|
|
141
|
-
Every API endpoint MUST have corresponding documentation. When creating or modifying an endpoint, you MUST simultaneously update the API documentation.
|
|
142
|
-
|
|
143
|
-
### Preferred Approach: OpenAPI (Swagger)
|
|
144
|
-
|
|
145
|
-
```typescript
|
|
146
|
-
// Option 1: Code-first with decorators (NestJS)
|
|
147
|
-
@ApiOperation({ summary: 'Create a new user' })
|
|
148
|
-
@ApiBody({ type: CreateUserDto })
|
|
149
|
-
@ApiResponse({ status: 201, description: 'User created', type: UserResponseDto })
|
|
150
|
-
@ApiResponse({ status: 400, description: 'Validation error' })
|
|
151
|
-
@ApiResponse({ status: 409, description: 'Email already exists' })
|
|
152
|
-
@Post()
|
|
153
|
-
async createUser(@Body() dto: CreateUserDto): Promise<UserResponseDto> { ... }
|
|
154
|
-
|
|
155
|
-
// Option 2: Schema-first with Zod + zod-to-openapi
|
|
156
|
-
import { extendZodWithOpenApi } from '@asteasolutions/zod-to-openapi';
|
|
157
|
-
extendZodWithOpenApi(z);
|
|
158
|
-
|
|
159
|
-
const CreateUserSchema = z.object({
|
|
160
|
-
name: z.string().min(1).openapi({ example: 'John Doe' }),
|
|
161
|
-
email: z.string().email().openapi({ example: 'john@example.com' }),
|
|
162
|
-
}).openapi('CreateUserRequest');
|
|
163
|
-
```
|
|
164
|
-
|
|
165
|
-
### Documentation Checklist (Per Endpoint)
|
|
166
|
-
- [ ] HTTP method and path
|
|
167
|
-
- [ ] Request body schema (with examples)
|
|
168
|
-
- [ ] Query/path parameter descriptions
|
|
169
|
-
- [ ] All possible response codes with schemas
|
|
170
|
-
- [ ] Authentication requirements
|
|
171
|
-
- [ ] Rate limiting information (if applicable)
|
|
172
|
-
|
|
173
|
-
### Documentation Must Stay in Sync
|
|
174
|
-
```
|
|
175
|
-
❌ BANNED:
|
|
176
|
-
// Endpoint accepts `role` field but docs don't mention it
|
|
177
|
-
// Endpoint returns 422 but docs only show 400
|
|
178
|
-
|
|
179
|
-
✅ REQUIRED:
|
|
180
|
-
// When you change an endpoint → update the schema/docs in the SAME commit
|
|
181
|
-
// Use code-first tools so docs are generated from the actual types
|
|
182
|
-
```
|
|
183
|
-
|
|
184
|
-
---
|
|
185
|
-
|
|
186
|
-
## Import Style
|
|
187
|
-
|
|
188
|
-
### Path Aliases (Required)
|
|
189
|
-
```typescript
|
|
190
|
-
// ❌ BANNED: Deep relative imports
|
|
191
|
-
import { UserService } from '../../../modules/user/user.service';
|
|
192
|
-
import { AppError } from '../../../../shared/errors/app-error';
|
|
193
|
-
|
|
194
|
-
// ✅ REQUIRED: Path aliases
|
|
195
|
-
import { UserService } from '@/modules/user/user.service';
|
|
196
|
-
import { AppError } from '@/shared/errors/app-error';
|
|
197
|
-
```
|
|
198
|
-
|
|
199
|
-
### Import Order (Enforced by ESLint)
|
|
200
|
-
```typescript
|
|
201
|
-
// 1. Node built-ins
|
|
202
|
-
import { readFile } from 'node:fs/promises';
|
|
203
|
-
import { join } from 'node:path';
|
|
204
|
-
|
|
205
|
-
// 2. External packages
|
|
206
|
-
import { z } from 'zod';
|
|
207
|
-
import { PrismaClient } from '@prisma/client';
|
|
208
|
-
|
|
209
|
-
// 3. Internal modules (path aliases)
|
|
210
|
-
import { UserService } from '@/modules/user/user.service';
|
|
211
|
-
import { AppError } from '@/shared/errors/app-error';
|
|
212
|
-
|
|
213
|
-
// 4. Relative imports (same module only)
|
|
214
|
-
import { CreateUserDto } from './user.dto';
|
|
215
|
-
import { UserRepository } from './user.repository';
|
|
216
|
-
```
|
|
217
|
-
|
|
218
|
-
---
|
|
219
|
-
|
|
220
|
-
## Async Patterns
|
|
221
|
-
|
|
222
|
-
### Rule: Prefer async/await Over Raw Promises
|
|
223
|
-
```typescript
|
|
224
|
-
// ❌ BANNED: Promise chain hell
|
|
225
|
-
function getUser(id: string) {
|
|
226
|
-
return userRepo.findById(id)
|
|
227
|
-
.then(user => {
|
|
228
|
-
if (!user) throw new NotFoundError('User', id);
|
|
229
|
-
return orderRepo.findByUserId(user.id);
|
|
230
|
-
})
|
|
231
|
-
.then(orders => ({ ...user, orders }))
|
|
232
|
-
.catch(err => { throw err; });
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
// ✅ REQUIRED: Clean async/await
|
|
236
|
-
async function getUser(id: string): Promise<UserWithOrders> {
|
|
237
|
-
const user = await userRepo.findById(id);
|
|
238
|
-
if (!user) throw new NotFoundError('User', id);
|
|
239
|
-
|
|
240
|
-
const orders = await orderRepo.findByUserId(user.id);
|
|
241
|
-
return { ...user, orders };
|
|
242
|
-
}
|
|
243
|
-
```
|
|
244
|
-
|
|
245
|
-
### Parallel Execution
|
|
246
|
-
```typescript
|
|
247
|
-
// ❌ SLOW: Sequential when operations are independent
|
|
248
|
-
const user = await getUser(id);
|
|
249
|
-
const orders = await getOrders(id);
|
|
250
|
-
const preferences = await getPreferences(id);
|
|
251
|
-
|
|
252
|
-
// ✅ FAST: Parallel independent operations
|
|
253
|
-
const [user, orders, preferences] = await Promise.all([
|
|
254
|
-
getUser(id),
|
|
255
|
-
getOrders(id),
|
|
256
|
-
getPreferences(id),
|
|
257
|
-
]);
|
|
258
|
-
```
|
|
259
|
-
|
|
260
|
-
---
|
|
261
|
-
|
|
262
|
-
## Enum and Union Types
|
|
263
|
-
|
|
264
|
-
### Prefer `as const` Unions Over Enums
|
|
265
|
-
```typescript
|
|
266
|
-
// ⚠️ ACCEPTABLE but verbose:
|
|
267
|
-
enum OrderStatus {
|
|
268
|
-
PENDING = 'pending',
|
|
269
|
-
CONFIRMED = 'confirmed',
|
|
270
|
-
SHIPPED = 'shipped',
|
|
271
|
-
DELIVERED = 'delivered',
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
// ✅ PREFERRED: const assertion + union type
|
|
275
|
-
const ORDER_STATUSES = ['pending', 'confirmed', 'shipped', 'delivered'] as const;
|
|
276
|
-
type OrderStatus = (typeof ORDER_STATUSES)[number];
|
|
277
|
-
// OrderStatus = 'pending' | 'confirmed' | 'shipped' | 'delivered'
|
|
278
|
-
|
|
279
|
-
// Works perfectly with Zod:
|
|
280
|
-
const OrderStatusSchema = z.enum(ORDER_STATUSES);
|
|
281
|
-
```
|
|
282
|
-
|
|
283
|
-
---
|
|
284
|
-
|
|
285
|
-
## Preferred Libraries (V1.0 — 2025)
|
|
286
|
-
|
|
287
|
-
| Need | Library | Why |
|
|
288
|
-
|------|---------|-----|
|
|
289
|
-
| Runtime | Bun / Node 20+ | ESM native, fast, batteries-included |
|
|
290
|
-
| Validation | `zod` | 0 deps, type inference, composable |
|
|
291
|
-
| ORM | `prisma` or `drizzle-orm` | Type-safe queries, migration support |
|
|
292
|
-
| HTTP framework | `hono` / `fastify` / Next.js | Lightweight, modern, tree-shakeable |
|
|
293
|
-
| Testing | `vitest` | Vite-native, Jest-compatible API, fast |
|
|
294
|
-
| Linting | `eslint` + `@typescript-eslint` | Community standard |
|
|
295
|
-
| Formatting | `prettier` | Community standard |
|
|
296
|
-
| Date | `date-fns` or `Temporal` (when stable) | Tree-shakeable, immutable |
|
|
297
|
-
| HTTP client | `ky` / `ofetch` / built-in `fetch` | Lightweight, modern |
|
|
298
|
-
| Password | `bcrypt` / `argon2` | Proven, secure |
|
|
299
|
-
| Logger | `pino` | Fastest JSON logger for Node.js |
|
|
300
|
-
| Env | `@t3-oss/env-core` + Zod | Type-safe env validation |
|
|
301
|
-
|
|
302
|
-
---
|
|
303
|
-
|
|
304
|
-
## Banned Patterns
|
|
305
|
-
|
|
306
|
-
| Pattern | Why | Alternative |
|
|
307
|
-
|---------|-----|-------------|
|
|
308
|
-
| `any` type | Defeats TypeScript's purpose | `unknown` + narrowing |
|
|
309
|
-
| `// @ts-ignore` | Hides real type errors | Fix the type or `@ts-expect-error` with comment |
|
|
310
|
-
| `var` keyword | Function scoping bugs | `const` (default) or `let` |
|
|
311
|
-
| `==` loose equality | Type coercion surprises | `===` always |
|
|
312
|
-
| `console.log` in production | Not structured, not configurable | Use `pino` or structured logger |
|
|
313
|
-
| `new Date()` without timezone | Timezone bugs | Explicit UTC or use date-fns |
|
|
314
|
-
| Default exports | Naming inconsistency across imports | Named exports only |
|
|
315
|
-
| Barrel re-exports (`index.ts`) | Circular dependency magnets | Direct imports or module public API only |
|
|
316
|
-
| `moment.js` | Deprecated, massive bundle | `date-fns` or `dayjs` |
|
|
317
|
-
| `class` with inheritance (deep chains) | Fragile hierarchies | Composition + interfaces |
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"defaultTier": "advance",
|
|
3
|
-
"tiers": [
|
|
4
|
-
{
|
|
5
|
-
"name": "standard",
|
|
6
|
-
"role": "compatibility",
|
|
7
|
-
"description": "Minimal fallback mode for legacy support"
|
|
8
|
-
},
|
|
9
|
-
{
|
|
10
|
-
"name": "advance",
|
|
11
|
-
"role": "default",
|
|
12
|
-
"description": "Efficient, opinionated, production-aware baseline"
|
|
13
|
-
},
|
|
14
|
-
{
|
|
15
|
-
"name": "expert",
|
|
16
|
-
"role": "complexity",
|
|
17
|
-
"description": "For advanced integration, architecture, and critical refactors"
|
|
18
|
-
},
|
|
19
|
-
{
|
|
20
|
-
"name": "above",
|
|
21
|
-
"role": "governance",
|
|
22
|
-
"description": "For release-critical and enterprise control-plane work"
|
|
23
|
-
}
|
|
24
|
-
],
|
|
25
|
-
"domains": [
|
|
26
|
-
"frontend",
|
|
27
|
-
"backend",
|
|
28
|
-
"fullstack",
|
|
29
|
-
"cli",
|
|
30
|
-
"distribution",
|
|
31
|
-
"review-quality"
|
|
32
|
-
],
|
|
33
|
-
"benchmarkSources": [
|
|
34
|
-
"sickn33/antigravity-awesome-skills",
|
|
35
|
-
"github/awesome-copilot",
|
|
36
|
-
"MiniMax-AI/skills"
|
|
37
|
-
]
|
|
38
|
-
}
|
|
@@ -1,232 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Skill Selector — Skill platform interaction and domain inference.
|
|
3
|
-
* Depends on: constants.mjs, utils.mjs
|
|
4
|
-
*/
|
|
5
|
-
import fs from 'node:fs/promises';
|
|
6
|
-
import path from 'node:path';
|
|
7
|
-
|
|
8
|
-
import {
|
|
9
|
-
SKILL_PLATFORM_DIRECTORY,
|
|
10
|
-
SKILL_PLATFORM_INDEX_PATH,
|
|
11
|
-
} from './constants.mjs';
|
|
12
|
-
|
|
13
|
-
import { normalizeChoiceInput } from './utils.mjs';
|
|
14
|
-
|
|
15
|
-
export async function loadSkillPlatformIndex() {
|
|
16
|
-
const skillPlatformIndexContent = await fs.readFile(SKILL_PLATFORM_INDEX_PATH, 'utf8');
|
|
17
|
-
return JSON.parse(skillPlatformIndexContent);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export function normalizeSkillTierInput(rawTierInput) {
|
|
21
|
-
const normalizedTierInput = normalizeChoiceInput(rawTierInput);
|
|
22
|
-
const allowedTierNames = new Set(['standard', 'advance', 'expert', 'above']);
|
|
23
|
-
|
|
24
|
-
if (!allowedTierNames.has(normalizedTierInput)) {
|
|
25
|
-
return null;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
return normalizedTierInput;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export function findSkillDomainByInput(skillDomainInput, skillDomainEntries) {
|
|
32
|
-
const normalizedSkillDomainInput = normalizeChoiceInput(skillDomainInput);
|
|
33
|
-
|
|
34
|
-
return skillDomainEntries.find((skillDomainEntry) => {
|
|
35
|
-
const normalizedDomainName = normalizeChoiceInput(skillDomainEntry.name);
|
|
36
|
-
const normalizedDisplayName = normalizeChoiceInput(skillDomainEntry.displayName);
|
|
37
|
-
|
|
38
|
-
return normalizedSkillDomainInput === normalizedDomainName || normalizedSkillDomainInput === normalizedDisplayName;
|
|
39
|
-
}) || null;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export function formatSkillTierList(skillPlatformIndex) {
|
|
43
|
-
return skillPlatformIndex.tiers.map((tierDefinition) => `${tierDefinition.name} (${tierDefinition.description})`).join('\n');
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export function inferSkillDomainNamesFromSelection(
|
|
47
|
-
selectedStackFileName,
|
|
48
|
-
selectedBlueprintFileName,
|
|
49
|
-
additionalStackFileNames = [],
|
|
50
|
-
additionalBlueprintFileNames = []
|
|
51
|
-
) {
|
|
52
|
-
const inferredDomainNames = new Set();
|
|
53
|
-
|
|
54
|
-
function applyStackSignals(stackFileName) {
|
|
55
|
-
if (stackFileName === 'typescript.md') {
|
|
56
|
-
inferredDomainNames.add('frontend');
|
|
57
|
-
inferredDomainNames.add('cli');
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
if (stackFileName === 'go.md'
|
|
61
|
-
|| stackFileName === 'java.md'
|
|
62
|
-
|| stackFileName === 'php.md'
|
|
63
|
-
|| stackFileName === 'csharp.md'
|
|
64
|
-
|| stackFileName === 'python.md'
|
|
65
|
-
|| stackFileName === 'ruby.md'
|
|
66
|
-
|| stackFileName === 'rust.md') {
|
|
67
|
-
inferredDomainNames.add('backend');
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
if (stackFileName === 'react-native.md' || stackFileName === 'flutter.md') {
|
|
71
|
-
inferredDomainNames.add('frontend');
|
|
72
|
-
inferredDomainNames.add('fullstack');
|
|
73
|
-
inferredDomainNames.add('cli');
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
function applyBlueprintSignals(blueprintFileName) {
|
|
78
|
-
if (blueprintFileName === 'api-nextjs.md' || blueprintFileName === 'fastapi-service.md') {
|
|
79
|
-
inferredDomainNames.add('frontend');
|
|
80
|
-
inferredDomainNames.add('fullstack');
|
|
81
|
-
inferredDomainNames.add('cli');
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
if (blueprintFileName === 'go-service.md'
|
|
85
|
-
|| blueprintFileName === 'spring-boot-api.md'
|
|
86
|
-
|| blueprintFileName === 'laravel-api.md'
|
|
87
|
-
|| blueprintFileName === 'aspnet-api.md'
|
|
88
|
-
|| blueprintFileName === 'nestjs-logic.md'
|
|
89
|
-
|| blueprintFileName === 'graphql-grpc-api.md') {
|
|
90
|
-
inferredDomainNames.add('backend');
|
|
91
|
-
inferredDomainNames.add('fullstack');
|
|
92
|
-
inferredDomainNames.add('cli');
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
if (blueprintFileName === 'mobile-app.md') {
|
|
96
|
-
inferredDomainNames.add('frontend');
|
|
97
|
-
inferredDomainNames.add('fullstack');
|
|
98
|
-
inferredDomainNames.add('cli');
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
if (blueprintFileName === 'observability.md') {
|
|
102
|
-
inferredDomainNames.add('backend');
|
|
103
|
-
inferredDomainNames.add('fullstack');
|
|
104
|
-
inferredDomainNames.add('cli');
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
applyBlueprintSignals(selectedBlueprintFileName);
|
|
109
|
-
|
|
110
|
-
applyStackSignals(selectedStackFileName);
|
|
111
|
-
for (const additionalStackFileName of additionalStackFileNames) {
|
|
112
|
-
applyStackSignals(additionalStackFileName);
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
for (const additionalBlueprintFileName of additionalBlueprintFileNames) {
|
|
116
|
-
applyBlueprintSignals(additionalBlueprintFileName);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
if (inferredDomainNames.size === 0) {
|
|
120
|
-
inferredDomainNames.add('fullstack');
|
|
121
|
-
inferredDomainNames.add('cli');
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
return Array.from(inferredDomainNames);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
export async function buildSkillPackSection(skillDomainEntry, selectedTierName) {
|
|
128
|
-
const resolvedPackFileName = skillDomainEntry.tierToPackFileNames?.[selectedTierName]
|
|
129
|
-
|| skillDomainEntry.tierToPackFileNames?.[skillDomainEntry.defaultTier]
|
|
130
|
-
|| skillDomainEntry.defaultPackFileName;
|
|
131
|
-
const skillPackFilePath = path.join(SKILL_PLATFORM_DIRECTORY, resolvedPackFileName);
|
|
132
|
-
const skillPackContent = await fs.readFile(skillPackFilePath, 'utf8');
|
|
133
|
-
|
|
134
|
-
return [
|
|
135
|
-
`## SKILL PACK: ${skillDomainEntry.displayName}`,
|
|
136
|
-
`Source: .agent-context/skills/${resolvedPackFileName}`,
|
|
137
|
-
`Default tier: ${skillDomainEntry.defaultTier}`,
|
|
138
|
-
`Selected tier: ${selectedTierName}`,
|
|
139
|
-
`Evidence: ${skillDomainEntry.evidence}`,
|
|
140
|
-
'',
|
|
141
|
-
skillPackContent.trim(),
|
|
142
|
-
'',
|
|
143
|
-
].join('\n');
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
export async function runSkillCommand(commandArguments) {
|
|
147
|
-
const parsedSkillOptions = {
|
|
148
|
-
domain: null,
|
|
149
|
-
tier: null,
|
|
150
|
-
tierProvided: false,
|
|
151
|
-
json: false,
|
|
152
|
-
};
|
|
153
|
-
|
|
154
|
-
for (let argumentIndex = 0; argumentIndex < commandArguments.length; argumentIndex++) {
|
|
155
|
-
const currentArgument = commandArguments[argumentIndex];
|
|
156
|
-
|
|
157
|
-
if (!currentArgument.startsWith('--')) {
|
|
158
|
-
parsedSkillOptions.domain = currentArgument;
|
|
159
|
-
continue;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
if (currentArgument === '--tier') {
|
|
163
|
-
parsedSkillOptions.tier = normalizeSkillTierInput(commandArguments[argumentIndex + 1] || '');
|
|
164
|
-
parsedSkillOptions.tierProvided = true;
|
|
165
|
-
argumentIndex += 1;
|
|
166
|
-
continue;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
if (currentArgument.startsWith('--tier=')) {
|
|
170
|
-
parsedSkillOptions.tier = normalizeSkillTierInput(currentArgument.split('=')[1]);
|
|
171
|
-
parsedSkillOptions.tierProvided = true;
|
|
172
|
-
continue;
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
if (currentArgument === '--json') {
|
|
176
|
-
parsedSkillOptions.json = true;
|
|
177
|
-
continue;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
throw new Error(`Unknown option: ${currentArgument}`);
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
const skillPlatformIndex = await loadSkillPlatformIndex();
|
|
184
|
-
const skillDomainEntries = Object.values(skillPlatformIndex.domains || {});
|
|
185
|
-
const selectedSkillDomain = parsedSkillOptions.domain
|
|
186
|
-
? findSkillDomainByInput(parsedSkillOptions.domain, skillDomainEntries)
|
|
187
|
-
: null;
|
|
188
|
-
|
|
189
|
-
if (parsedSkillOptions.domain && !selectedSkillDomain) {
|
|
190
|
-
throw new Error(`Unknown skill domain: ${parsedSkillOptions.domain}`);
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
if (parsedSkillOptions.tierProvided && !parsedSkillOptions.tier) {
|
|
194
|
-
throw new Error(`Unknown skill tier: ${commandArguments.join(' ')}`);
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
const selectedTierName = parsedSkillOptions.tier || skillPlatformIndex.defaultTier || 'advance';
|
|
198
|
-
const recommendedPackFileName = selectedSkillDomain
|
|
199
|
-
? selectedSkillDomain.tierToPackFileNames?.[selectedTierName]
|
|
200
|
-
|| selectedSkillDomain.tierToPackFileNames?.[selectedSkillDomain.defaultTier]
|
|
201
|
-
|| selectedSkillDomain.defaultPackFileName
|
|
202
|
-
|| null
|
|
203
|
-
: null;
|
|
204
|
-
|
|
205
|
-
if (parsedSkillOptions.json) {
|
|
206
|
-
console.log(JSON.stringify({
|
|
207
|
-
defaultTier: skillPlatformIndex.defaultTier,
|
|
208
|
-
selectedTier: selectedTierName,
|
|
209
|
-
selectedDomain: selectedSkillDomain,
|
|
210
|
-
recommendedPackFileName,
|
|
211
|
-
}, null, 2));
|
|
212
|
-
return;
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
console.log('Skill platform selector');
|
|
216
|
-
console.log(`Default tier: ${skillPlatformIndex.defaultTier}`);
|
|
217
|
-
console.log(`Available tiers:\n${formatSkillTierList(skillPlatformIndex)}`);
|
|
218
|
-
|
|
219
|
-
if (!selectedSkillDomain) {
|
|
220
|
-
console.log('\nAvailable domains:');
|
|
221
|
-
for (const skillDomainEntry of skillDomainEntries) {
|
|
222
|
-
console.log(`- ${skillDomainEntry.name}: ${skillDomainEntry.description}`);
|
|
223
|
-
}
|
|
224
|
-
return;
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
console.log(`\nSelected domain: ${selectedSkillDomain.displayName}`);
|
|
228
|
-
console.log(`Selected tier: ${selectedTierName}`);
|
|
229
|
-
console.log(`Recommended pack: ${recommendedPackFileName}`);
|
|
230
|
-
console.log(`Purpose: ${selectedSkillDomain.description}`);
|
|
231
|
-
console.log(`Evidence: ${selectedSkillDomain.evidence}`);
|
|
232
|
-
}
|