skills/arc-code-review/SKILL.md
Audit a client codebase that has @classytic/arc installed for gaps in arc-convention adoption. Surfaces hand-rolled CRUD/auth/query/cache code that should be one defineResource() call, Mongoose models that should use @classytic/mongokit, manual JSON Schema that should be fieldRules, bypassed RequestScope, missing presets, and other patterns that defeat arc's "less code, more maintainability" promise. Produces a prioritized migration report with before/after recipes. Use when reviewing/auditing a downstream project that depends on @classytic/arc, when the user asks for an "arc audit", "arc gap analysis", "arc migration plan", "why isn't arc helping us", or when refactoring a Fastify/Express service to arc conventions. Triggers: arc audit, arc review, arc gap, arc migration, arc convention check, arc compliance, classytic audit, defineResource refactor, mongoose to mongokit, hand-rolled crud to arc, arc adoption, arc lint, arc smell, arc anti-pattern.
npx skillsauth add classytic/arc arc-code-reviewInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Audit skill for client projects that depend on @classytic/arc. Detects places where the team is writing code arc would have generated, then emits a prioritized migration plan with concrete before/after diffs.
Invoke when:
dependsOn @classytic/arc (or @classytic/mongokit) and the conversation is about refactoring, code-review, or onboarding.req.user access, manual Model.find() in route handlers, or hand-written OpenAPI alongside arc.Do NOT use for arc framework development itself — that's the arc skill in skills/arc/. This skill audits consumers of arc.
One defineResource() call replaces all of these in a typical Fastify service:
| Hand-rolled today | Arc capability that subsumes it | Reference |
|---|---|---|
| 5 × fastify.get/post/patch/delete per resource | CRUD auto-generation | arc-cheatsheet.md |
| if (req.user.role !== 'admin') inside handler | permissions: { create: requireRoles(['admin']) } | anti-patterns.md §4 |
| Manual req.query.filter parsing, $or/$and building | ArcQueryParser / mongokit QueryParser | anti-patterns.md §1 |
| Hand-written schema: { body, response } per route | schemaOptions.fieldRules | anti-patterns.md §2 |
| schema.set('toJSON', { transform }) to strip password/__v | fieldRules: { password: { hidden: true } } | anti-patterns.md §5 |
| Hand-maintained openapi.yaml / swagger.json | arc docs ./openapi.json | anti-patterns.md §6 |
| eventBus.emit('product.created', ...) in handler | events: { created: {} } (auto-emitted) | anti-patterns.md §7 |
| cache.del('products-*') after mutation | cache: { tags: ['catalog'] } (auto-invalidated) | anti-patterns.md §8 |
| req.user._id, req.user.orgId direct access | getUserId(scope), getOrgId(scope) from @classytic/arc/scope | anti-patterns.md §9 |
| import mongoose from 'mongoose' in route/service files | Adapter-only via createMongooseAdapter | anti-patterns.md §10 |
| Soft-delete: /deleted route + deletedAt field + restore handler | presets: ['softDelete'] | anti-patterns.md §14 |
| class UserRepository { async create() { Model.create() } } | new Repository(Model) (mongokit) | mongokit-migration.md |
| Per-schema schema.pre('save', ...) for timestamps/validation | timestampPlugin(), validationChainPlugin() | mongokit-migration.md |
| Hand-written name === 'admin' MCP tool handlers | mcpPlugin({ resources }) (auto-generated) | anti-patterns.md §15 |
package.json. Note @classytic/arc, @classytic/mongokit, @classytic/repo-core, @classytic/sqlitekit versions. If arc is absent, this skill doesn't apply — recommend npx @classytic/arc init instead.createApp( or defineResource( to see what arc surface is already in use. Note auth, runtime, arcPlugins, presets config.defineResource() call: list name, permissions, presets, cache, schemaOptions, custom routes/actions. Compare to what's used.src/ (excluding node_modules, dist, test*). Record file:line of each hit.mongoose is a direct dep but @classytic/mongokit is not, every model is a candidate for migration. Use mongokit-migration.md..arcrc, arc generate resource output structure ({name}.model.ts, {name}.repository.ts, {name}.resource.ts). Mismatch = team is hand-creating files. See scaffolding.md.# Arc Convention Audit — <project-name>
**Arc version:** 2.16.x · **Mongokit:** <version or "not installed"> · **Sqlitekit:** <version or "n/a"> · **Date:** <YYYY-MM-DD>
**Files scanned:** <N> · **Findings:** <N critical · <N high · <N medium · <N low>
## Executive summary
- <1-2 sentences: how much manual code could be deleted, biggest single risk>
- Estimated LOC removable: ~<N> lines across <N> files
- Estimated effort: <S/M/L> per resource (<N> resources affected)
## Critical findings
### C1. <short title> (<N occurrences>)
**Pattern:** <what's wrong, in 1 sentence>
**Locations:** `src/foo/bar.ts:42`, `src/foo/baz.ts:118`, ...
**Why it matters:** <security / drift / maintainability impact>
**Fix:** <link to migration recipe>
## High / Medium / Low findings
(same shape)
## Migration plan (recommended order)
1. <Step 1 — usually scope/permissions because they're security-critical>
2. <Step 2 — usually CRUD consolidation>
3. ...
## Per-resource scorecard
| Resource | defineResource? | presets used | permissions | cache | events | mongokit | Score |
|---|---|---|---|---|---|---|---|
| product | ✅ | softDelete | ✅ | ❌ | manual | ❌ | 6/10 |
hidden, hand-rolled idempotency that diverges from arc's behavior under load.console.log, any), naming conventions, missing displayName/module metadata.Full rubric → severity.md.
requireRoles(['admin']) from @classytic/arc, not "use arc's role helper").arcPlugins.queryCache: false, don't suggest cache tags — recommend enabling it first.init, generate resource, docs, introspect, doctor), .arcrc, file conventionstools
@classytic/arc — Resource-oriented backend framework for Fastify. Use when building REST APIs with Fastify, resource CRUD, defineResource, createApp, permissions, presets, database adapters, hooks, events, QueryCache, authentication, multi-tenant SaaS, OpenAPI, job queues, WebSocket, MCP tools, or production deployment. Triggers: arc, fastify resource, defineResource, createApp, BaseController, arc preset, arc auth, arc events, arc jobs, arc websocket, arc mcp, arc plugin, arc testing, arc cli, arc permissions, arc hooks, arc factory, arc cache.
tools
A brief description of what this skill does
tools
Use when work should span one or more detached tasks but still behave like one job with a single owner context. TaskFlow is the durable flow substrate under authoring layers like Lobster, ACPX, plugins, or plain code. Keep conditional logic in the caller; use TaskFlow for flow identity, child-task linkage, waiting state, revision-checked mutations, and user-facing emergence.
tools
# Lobster Lobster executes multi-step workflows with approval checkpoints. Use it when: - User wants a repeatable automation (triage, monitor, sync) - Actions need human approval before executing (send, post, delete) - Multiple tool calls should run as one deterministic operation ## When to use Lobster | User intent | Use Lobster? | | ------------------------------------------------------ | --------------------------