skills/structural-review/SKILL.md
Perform a structural and maintainability review of a PR or codebase diff — covering file-size blockers, abstraction quality, layer violations, type structural discipline, spaghetti branching, non-atomic mutations, stack-specific hygiene (Bun, Tailwind v4, Next.js 16, shadcn/ui), design purity (code-judo), and directness over magic (no speculative generality). Use when asked to review code quality, maintainability, structural health, or architecture of a change. Orthogonal to /code-review (which owns correctness bugs and repo rule compliance) — run after correctness passes or in parallel when a thorough PR review is requested.
npx skillsauth add shipshitdev/library structural-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.
Opinionated structural and maintainability review rubric. Report-only — this skill produces findings; it does not mutate files or open PRs.
Every structural finding must answer: "What exactly should the author delete, collapse, or rename — and which specific file/line is the canonical landing zone?" Vague nits ("this could be cleaner") are noise. High-conviction, actionable findings only.
This rubric is explicitly complementary to /code-review. Do not re-flag correctness bugs or repo instruction-file rule violations already covered there. Own the orthogonal structural/maintainability/devex dimensions.
Ask these first, before scanning for individual issues:
unknown, and as X casts hiding future breakage, and are interfaces inlined where they should be in *.types.ts?npm invocations, raw HTML in a shadcn project, middleware.ts in a Next.js 16 app — these are regressions, not style notes.A file crossing ~1000 lines is a presumptive blocker. It is not a hard numeric law but a strong prior that the module has taken on too many responsibilities.
Flag when:
Preferred remedy: Split into colocated slices — *.service.ts, *.queries.ts, *.types.ts, *.hooks.ts — before the PR lands. Not after.
Phrase: "File is now 1 180 lines. Split the query layer into *.queries.ts before this ships — the 1 000-line rule exists exactly for PRs like this one."
Severity: Blocker.
Every new function, hook, class, or file must justify its existence. Thin wrappers, identity helpers, and passthrough re-exports fail this test unconditionally.
Flag when:
useState with no co-located logic.Preferred remedy: Delete the abstraction; inline the real symbol at the call site. Bun + TS path aliases make the original easy to reach.
Phrase: "This helper is an identity function over formatDate — inline it and delete the file. Code-judo."
Severity: Request Changes.
Ad-hoc forks bolted onto existing flows are the primary mechanism by which a clean codebase becomes unmaintainable.
Flag when:
if (isAdmin) / if (featureFlag) / if (isPremium) fork appears in 2+ files changed by this PR.Preferred remedy: Collapse all branches into one canonical decision point — a hook for client state, a server action or domain service for mutations. Branches then disappear from the components.
Phrase: "Three if (isAdmin) forks scattered across the render tree. Collapse the decision into one hook or server action; the branches can then disappear from the component."
Severity: Request Changes.
In this stack, logic belongs in a specific layer. Violating the layer model is a structural defect, not a preference.
Layer map:
<form onSubmit>, not in useEffect.packages/ui components. Not raw <button>, <input>, <dialog>.proxy.ts. Not middleware.ts (Next.js 16).Flag when:
packages/ui or shadcn.Phrase: "<button onClick={...}> in a component that already imports Button from packages/ui — swap it; raw HTML is a regression in this codebase."
Severity: Request Changes; Blocker when the element is a raw interactive element in a shadcn/packages/ui project.
This axis covers structural placement and shape issues — not any existence, which is owned by the /code-review harness.
Violations (flag all):
unknown without an adjacent type guard — this is deferred any, structurally equivalent to leaving the shape unresolved.as X casts without a comment explaining why the type system cannot infer the narrowing.*.types.ts or packages/types.Preferred remedy: Define the shape in *.types.ts. Add the type guard at the boundary where the unknown enters.
Phrase: "Bare unknown without a type guard is deferred any. Define the shape in *.types.ts or add the guard here."
Severity: Bare unknown without guard → Blocker. Inline interface → Request Changes. as X without comment → Minor.
Sequential await calls that each write to the database are a correctness-adjacent structural defect. A crash between writes leaves the system in a half-written state.
Flag when:
await db.update() / await db.insert() calls appear in the same function without a wrapping transaction.Preferred remedy: Wrap in a DB transaction or model as a single atomic write. If the external call cannot be inside a transaction, add explicit compensation logic.
Phrase: "These two await db.update() calls are non-atomic. A failure between them leaves the row in an invalid state — wrap in a transaction or model as a single atomic write."
Severity: Blocker.
Functions that orchestrate 5+ sequential steps with no intermediate abstraction are a future maintenance hazard. They are hard to test, hard to reuse, and hard to understand in isolation.
Flag when:
await calls with no intermediate named steps or helper functions.Preferred remedy: Extract named phases. Each phase is testable in isolation. The orchestrator becomes a readable list of intents.
Severity: Request Changes.
These are not style notes — they are regressions introduced by the PR that must be fixed before merge.
| Issue | Rule | Phrase |
|---|---|---|
| middleware.ts created or left in place | Next.js 16 renamed the entry point to proxy.ts; the old name is silently ignored | "This is middleware.ts. Rename to proxy.ts — Next.js 16 renamed the entry point." |
| tailwind.config.ts or tailwind.config.js added | v4 uses CSS-based config (@theme in CSS); JS config is v3 | "tailwind.config.ts created by this PR — that's v3. Delete it and move the theme tokens into the CSS @theme block per v4." |
| @apply directive or bg-opacity-* class added | v3 patterns; must migrate to v4 slash syntax | Cite the exact line and the v4 equivalent. |
| npm run, npx, yarn add, pnpm exec in scripts, CI YAML, or docs | Bun is the only package manager; replace with bun run / bunx / bun add | "npx prisma migrate two lines below must be bunx prisma migrate." |
Severity: All Blocker.
The sharpest structural question is not "is this correct?" but "could this same behavior be expressed with materially less structure?" A change that ships the right behavior on top of avoidable complexity is a missed simplification, and missed simplifications compound.
Flag when:
Preferred remedy: Reframe the state model. Collapse the special case into a default. Deletion and collapse beat polishing — "code-judo" the complexity category out of existence rather than tidying it.
Phrase: "This three-state flag collapses to one derived boolean — the same behavior with a whole branch deleted. Reframe rather than polish."
Severity: Request Changes (Blocker when the simpler form also removes a correctness footgun).
Prefer the obvious mechanism over the clever one. Over-generic abstractions, hidden assumptions, and indirection that hides control flow cost more to read than they save to write.
Flag when:
Preferred remedy: Inline to the direct form for the one real caller. Make the assumption explicit at the boundary, or remove the magic.
Phrase: "Generic registry for a single handler — delete it, call the handler directly. Add the abstraction back when the second caller actually arrives."
Severity: Request Changes.
/code-review./security-audit.Order findings by severity:
## Structural Review
### Blockers (must fix before merge)
[File-size violations, non-atomic mutations, stack regressions (middleware.ts, tailwind config, npm/yarn usage), bare unknown without guard, design-purity simplifications that also remove a correctness footgun]
### Request Changes (significant structural debt)
[Abstraction-earns-keep failures, canonical-layer violations, spaghetti branching, sequential orchestration smells, inline interfaces, missed design-purity simplifications, speculative generality / magic indirection]
### Minor (low-debt, flag for awareness)
[as X casts without comments, small layer suggestions with obvious inlines]
### Approved Axes
[Axes with no findings — confirm clean]
Include for each finding:
Blocker and request-changes criteria are embedded in each axis above. When ambiguous, default to Request Changes — the ambiguity tax is paid by the author, not the codebase.
development
TypeScript refactoring and modernization guidelines from a principal specialist perspective. This skill should be used when refactoring, reviewing, or modernizing TypeScript code to ensure type safety, compiler performance, and idiomatic patterns. Triggers on tasks involving TypeScript type architecture, narrowing, generics, error handling, or migration to modern TypeScript features.
tools
Resolves TypeScript and JavaScript problems across type-level programming, performance, monorepo management, migration, and modern tooling. Invoke when diagnosing "type instantiation excessively deep" errors, migrating JS to TS, configuring strict tsconfig, debugging module resolution, or choosing between Biome/ESLint/Turborepo/Nx.
tools
Turborepo monorepo build system guidance. Triggers on: `turbo.json`, task pipelines, `dependsOn`, caching, remote cache, the `turbo` CLI, `--filter`, `--affected`, CI optimization, environment variables, internal packages, monorepo structure, and package boundaries. Use when the user configures tasks or workflows, creates packages, sets up a monorepo, shares code between apps, runs changed packages, debugs cache behavior, or works in an `apps/` plus `packages/` workspace.
tools
Provides Tailwind CSS v4 performance optimization and best practices guidelines. Triggers when writing, reviewing, or refactoring Tailwind CSS v4 code; when working with Tailwind configuration, @theme directive, utility classes, responsive design, dark mode, container queries, or CSS generation optimization.