Use when writing acceptance criteria for a task - express each as an observable Given/When/Then that QA can execute, including negative cases
日本語の概要は準備中です。原文の説明を表示しています。
Use when building or extending a TypeScript service on Node.js - Fastify, NestJS, Express or Hono, runtime validation at the boundary, strict types, the repository's ORM and migrations, async error handling, graceful shutdown
インストールする前に、エージェントに与えられる指示の中身を確認できます。
A Node.js service is TypeScript at compile time and untyped JavaScript at run time. Every type at the edge — a request body, a header, an environment variable, a queue message, a row from a raw query — is a claim until something checks it.
Core principle: the repository's framework, package manager, module system and ORM win. Parse input at the boundary into typed values; keep the domain free of the framework.
app.inject() for tests, pino logging built in.| Layer | Responsibility |
|---|---|
| Route / controller | Parse and validate input, call one service, map the result and errors to HTTP |
| Service | Use-case orchestration and business rules; takes plain typed values |
| Domain | Types, invariants, pure functions — no framework import |
| Adapter | Database, outbound HTTP, queues — behind an interface the service depends on |
pnpm-lock.yaml → pnpm, yarn.lock → yarn, package-lock.json → npm; install with the frozen form (pnpm install --frozen-lockfile, npm ci). Node version from .nvmrc, .node-version or engines; a new service targets the current Active LTS.package.json: "type": "module" means ESM (relative imports carry .js under NodeNext); otherwise CommonJS. Never mix them in one package.strict: true. No any; unknown at the boundary, narrowed by a parser. No non-null ! to silence a real undefined.z.infer) so the two cannot drift. Environment variables are parsed once at startup by the same means and the process exits on a bad one.setErrorHandler, a Nest exception filter, Express 5's error middleware) maps domain errors to 400/404/409 problem+json; an unknown error is logged with its stack and answered 500 without it.@typescript-eslint/no-floating-promises catches the rest). An unhandled rejection crashes the process in current Node.fetch(url, { signal: AbortSignal.timeout(5_000) }) or the client's own timeout; retries only for idempotent calls (resilient-io-and-jobs).*Sync file or crypto calls on a request path, no unbounded JSON.parse of a large body, CPU-heavy work in a worker thread or a job.pg — with parameters, never string-built SQL ($queryRawUnsafe and sql.raw with input are bugs). Migrations through that tool (prisma migrate dev --name, drizzle-kit generate), committed with the schema change; postgres-migrations covers safe DDL.nestjs-pino) with structured fields, request id bound per request; no console.log in service code; redact secrets and tokens (redact option).close(), Nest enableShutdownHooks().POST /tasks in Fastify with zod:
const CreateTask = z.object({ title: z.string().trim().min(1).max(200) });
export function taskRoutes(app: FastifyInstance, service: TaskService) {
app.post("/tasks", async (req, reply) => {
const parsed = CreateTask.safeParse(req.body);
if (!parsed.success) {
return reply.code(400).type("application/problem+json").send(problemFrom(parsed.error));
}
const task = await service.create(parsed.data.title, req.user.id);
return reply.code(201).header("location", `/tasks/${task.id}`).send(toResponse(task));
});
}
TaskService.create takes a string and an owner id and knows nothing of Fastify; Task.create enforces the 200-character rule again for callers that are not HTTP.
The repository's scripts first (list_component_checks, package.json, CI): typically npm run typecheck (or tsc --noEmit), npm run lint, npm test, npm run build. For the runtime check build once and run the output — npm run build, then PORT=18080 node dist/main.js in the background with its pid recorded — not a watcher (npm run dev, tsx watch, nodemon), which never exits and restarts under you.
req.body as CreateTaskDto — a cast is not a check.async route handlers in Express 4 without a wrapper: the rejection never reaches the error middleware.for loop where one query or Promise.all with a bound would do — or Promise.all over an unbounded list.process.env.X! scattered through the code instead of one parsed config object.any in a new signature, or // @ts-ignore / @ts-expect-error added to get a build green.console.log of a request body that may hold a token or a password.まだレビューはありません。使ってみた感想をお寄せください。
概要と使いどころ
Use when writing acceptance criteria for a task - express each as an observable Given/When/Then that QA can execute, including negative cases
日本語の概要は準備中です。原文の説明を表示しています。
Use when the diff adds or changes an endpoint, resolver, RPC, job or query that takes an object id, a role check, a request binding or a tenant filter - BOLA/IDOR, function-level authorization, mass assignment and tenant scoping
日本語の概要は準備中です。原文の説明を表示しています。
Use on every UI change - semantic HTML, labels for controls, keyboard-navigable dialogs/menus, visible focus, and never color as the only signal
日本語の概要は準備中です。原文の説明を表示しています。
Use when a task changes any screen, form, dialog, menu or control - Lighthouse/axe scan of the changed screens, a keyboard walk, and the thresholds that fail a task
日本語の概要は準備中です。原文の説明を表示しています。
How to work a task returned with review, QA or UAT findings. Use when a task is in need_revision or PR review comments are in your context.
日本語の概要は準備中です。原文の説明を表示しています。
Use when deciding whether a request needs an analiz task before implementation - the conditions that require the architect's analysis versus going straight to implementation
日本語の概要は準備中です。原文の説明を表示しています。