engineering-best-practices-enforcer
Engineering Best Practices Enforcer
Use this skill to run large, staged code quality reviews and refactors that stay aligned with the existing monorepo architecture.
Priority Model
Use this order for decisions:
- Repo context and established patterns (
AGENTS.md,.agent/rules/*, local module conventions) - Official framework/library guidance
- Design principles (SOLID, clean code heuristics)
If guidance conflicts, document the trade-off explicitly and choose the lower-risk path for current architecture.
When to Use
- Reviewing a feature, workspace, or the full monorepo for refactor opportunities
- Planning progressive cleanups without destabilizing production behavior
- Creating actionable, severity-ordered engineering findings with clear file references
- Standardizing review output so multiple engineers can follow the same process
Workflow
- Identify scope (
single feature,workspace,cross-workspace). - Load relevant skills from
.agent/skills/*for affected layer(s). - Read local implementation patterns in the target area before proposing changes.
- Run the quality signal scanner:
bash .agent/skills/engineering-best-practices-enforcer/scripts/scan-quality-signals.sh
- Perform impact and risk assessment before editing (required):
- List impacted entry points (routes/pages/controllers/jobs)
- List shared components/hooks/libs touched by those entry points
- List likely dependents (imports + reuse in sibling features)
- Classify change type:
behavior-preserving refactorbehavior-adjacent refactor(possible runtime impact)behavior-changing refactor
- Assign risk tier:
low: local, strongly typed, no shared component contract changesmedium: shared hook/component logic, state/data-flow rewiringhigh: cross-workspace contracts, API shape, persistence or auth paths
- Produce findings:
- Order by severity (high -> medium -> low)
- Include absolute file references
- Separate correctness issues from structural/style issues
- For each proposed refactor, provide:
- Why: risk or maintainability gain
- Evidence: local pattern + official docs reference
- Cost: low/medium/high effort and blast radius
- Execute small safe batches first, then verify each changed workspace:
pnpm --filter <workspace> lintpnpm --filter <workspace> typecheckpnpm --filter <workspace> testpnpm --filter <workspace> build(only when package wiring/build behavior changed)
Documentation Lifecycle and Placement (Repository Convention)
Use this convention when creating or refactoring docs in any app/package:
docs/root contains implemented/canonical documentation only.- architecture overviews
- current feature behavior
- runbooks/playbooks that match shipped behavior
docs/design/contains unimplemented or partially implemented artifacts.- design proposals
- implementation plans
- TODO/follow-up requirements
docs/README.mdis the index and source of truth for status.- each document listed with explicit status (
implemented,in progress,planned,deprecated) - do not leave design docs in root once a
docs/design/structure exists
- each document listed with explicit status (
- When a feature is implemented:
- move/merge relevant content from
docs/design/*into canonicaldocs/*files - either delete stale design docs or keep them with explicit archival/deprecated note
- move/merge relevant content from
- Apply the same pattern consistently across
apps/*andpackages/*where docs exist.
Review Gate for Documentation Changes
For design-heavy feature work, include this gate in review:
- Is this describing current behavior? -> place in
docs/root. - Is this proposing future behavior or outstanding TODOs? -> place in
docs/design/. - Is status discoverable from
docs/README.md? -> required before merge.
Refactor Impact Protocol (Mandatory)
Before implementation:
- Define explicit refactor boundary:
- in-scope files
- out-of-scope files
- expected invariants that must not change (UI behavior, API contracts, side effects)
- Create a mini risk register for the batch:
- risk
- trigger condition
- mitigation
- detection method (test, typecheck, smoke path)
- Prefer smallest viable batch that can be reverted independently.
During implementation:
- Refactor one axis at a time (state, data, rendering, side effects), not all at once.
- Preserve external contracts first; improve internal structure second.
- If shared component behavior is touched, add/adjust tests in the same batch.
After implementation:
- Run verification matrix for impacted workspace(s):
- lint
- typecheck
- test
- build (for bundling/wiring confidence)
- Execute runtime smoke checks for affected entry points:
- open primary page/route
- open each dialog/sheet touched by the batch
- execute key action path once (save/update/delete)
- Confirm no new warnings/errors in browser console for touched flows.
Output Contract
For every review batch, output:
- Findings first (severity ordered, with file refs)
- Open questions and assumptions
- Impact summary:
- impacted entry points
- impacted shared modules
- risk tier and rationale
- Refactor plan (incremental batches)
- Verification commands run and outcomes
- Residual risk + rollback unit:
- smallest commit(s) to revert safely
- any untested edge paths
Implementation Micro-Decisions
useCallback Decision Rule
Default to not using useCallback for small local handlers.
Reason this is often overkill:
- Inline handlers are usually clearer and easier to maintain.
- Stable function identity does not improve performance unless a downstream consumer depends on it.
useCallbackadds dependency-array overhead and can introduce stale-closure bugs during refactors.
Use useCallback only when at least one condition is true:
- Callback is passed to a memoized child (
React.memo) where unstable references cause measurable re-renders. - Callback is part of hook dependency semantics (
useEffect,useMemo, custom hook API) and stability is required for correctness or churn control. - Callback is reused in multiple places and extracting/memoizing improves readability more than inline lambdas.
Review expectation:
- If adding
useCallback, state why identity stability matters in that exact call path. - If not adding
useCallback, treat this as the preferred baseline, not a missed optimization.
Derived Table State Memoization Rule
Default to not memoizing small derived table state objects (for example tablePagination, filters, sorting model) in route/page components.
Reason:
- These values are cheap to recompute and are already derived from current render state.
- Unnecessary
useMemointroduces dependency-array coupling and increases stale-state risk during refactors. - In table-heavy UIs, stale memoized objects can desynchronize advanced filters/pagination from live URL/query state.
Use useMemo for derived table state only when at least one condition is true:
- The derivation is computationally expensive (not simple object shaping).
- A memoized downstream consumer has proven churn issues tied to unstable references.
- You can demonstrate complete dependency coverage and add a regression test for stale-state behavior.
Review expectation:
- If
useMemowraps simple pagination/filter object shaping, challenge it by default. - Prefer plain inline derivation unless there is measured performance evidence or correctness need.
- For advanced filter flows, treat stale-state risk as higher priority than theoretical render micro-optimizations.
Null-Safety Guard Rule (Shared Components)
For shared components (dialogs, sheets, reusable form controls), treat nullable props as hostile inputs.
Required rule:
- Never rely on optional-chain equality checks (
a?.x === b?.y) as a guard before dereferencing one side (a.x). - First establish an explicit non-null object guard (
if (!task) return ...), then dereference. - Helper functions that accept nullable entities must return safely on
null/undefinedbefore reading nested fields. - If the component can render before data hydration (query + initial null state), test that open/render paths do not crash.
Known anti-pattern (causes runtime crashes):
if (draft?.taskId === task?.id) return draft.value;- When both sides are
undefined, branch passes and dereferencesdraftwhiledraftis null.
Review expectation:
- For each nullable prop path, verify the first dereference is dominated by a concrete non-null guard.
- Prefer defensive fallback values at boundaries (
'',[],null) over conditional dereference chains deep in render logic.
References
Load these only when needed:
- Official guidance index: references/official-docs.md