debug
npx skills add https://github.com/gemini960114/skills --skill debug
Agent 安装分布
Skill 文档
Debug Skill Instructions
This skill defines a mandatory, systematic code review process to identify and fix bugs before delivery. Apply it whenever code is newly written, significantly modified, or when the user asks for a bug check.
When to Apply This Skill
- After writing or generating new code (proactive audit)
- When the user explicitly asks to “check for bugs”, “review code”, or “debug”
- Before marking a task as complete if the code is non-trivial
- After a significant refactor
Step 1 â Read All Files First
Before making any judgement, read every relevant file in full.
Priority reading order:
- Type / interface definitions
- Core logic / algorithm implementation
- State management hooks / stores
- API route handlers and schemas
- Main entrypoint / app bootstrap
Do NOT skip a file because it “looks simple”. Bugs often hide in helper utilities and type definitions.
Step 2 â Systematic Checklist
Work through each category below. For each item, explicitly confirm â or flag ð´/ð¡.
2-A Types & Interfaces
- Are all interface fields actually used and correctly typed?
- Are there missing fields in interfaces that are referenced in implementation? (e.g. added a field to impl but forgot to update the type)
- Are union types / discriminated unions exhaustively handled?
- Are optional fields (
?) handled safely (null-check before use)?
2-B Logic / Algorithm
- Are loop bounds correct? (off-by-one:
< nvs<= n) - Is integer vs float arithmetic intentional? (
Math.floorwhere needed?) - Are comparisons using correct operators? (
===not==, object reference vs value) - Do recursive / self-referential functions have correct base cases?
- Are formulas correct with respect to domain rules? (e.g. level-up formula does not accidentally include a level multiplier in the divisor)
2-C State Management (React / Frontend)
-
useCallbackâ are all variables captured in the closure listed indeps? -
useEffectâ are all reactive values listed indeps? Are stale closures possible? - Object reference vs value comparison (
!==on objects from spread/new is alwaystrue) - Are timers (
setTimeout,setInterval,requestAnimationFrame) properly cleared on unmount? - Can a state update fire after component unmount (memory leak)?
- Are
useRefvalues mutated correctly without triggering unnecessary re-renders?
2-D Async / Promise
- Are all
awaitcalls insidetry/catch? - Is error state always reset before a new async operation starts?
- Are loading flags set to
falseinfinally(not justthen)? - Can multiple concurrent calls cause a race condition? (debounce / cancel needed?)
2-E Canvas / WebGL Rendering
- Is
ctx.save()/ctx.restore()used when changing global canvas state (globalAlpha,shadowBlur,font,textAlign)? - Is
shadowBlurreset to0andshadowColorreset to'transparent'after use? - Are
globalAlphavalues always reset to1after use? - Does the render loop correctly handle the case when the canvas ref is null?
- Are particle arrays or pools bounded? (prevent unbounded memory growth)
2-F Backend â API & Validation
- Are all input fields validated for type, range, and non-empty?
- Is string input stripped of leading/trailing whitespace before validation?
- Are SQL queries parameterised? (no f-string / string concat with user data)
- Does the error response format match the success response format (consistent envelope)?
- Are HTTP status codes correct? (201 for create, 400 for validation, 404 for not found, 500 for server error)
2-G Backend â Database
- Is the DB connection closed / returned to pool in all code paths (use context manager)?
- Are transactions committed only after the full operation succeeds?
- Are indexes created for columns used in ORDER BY or WHERE clauses?
- Is
lastrowid/RETURNINGused safely after commit?
2-H Dead Code & Unused Imports
- Are there any imports that are never used?
- Are there variables declared but never referenced?
- Are there exported functions that are no longer called anywhere?
- Are there deprecated API usages? (e.g.
@app.on_eventin FastAPI â¥0.93)
2-I Security & Safety
- Is user-supplied data ever rendered as HTML without sanitisation?
- Are CORS origins restricted to known domains (not
*in production)? - Are error messages safe to expose to the client? (no stack traces / DB details)
Step 3 â Classify & Report
For each bug found, classify severity:
| Level | Label | Criteria |
|---|---|---|
| ð´ | Critical | Logic error, data corruption, crash, security hole |
| ð¡ | Medium | Feature defect, performance issue, deprecated API |
| ð¢ | Minor | Dead code, cosmetic, non-functional warning |
Report format:
| # | Severity | File:Line | Description | Fix |
Step 4 â Apply Fixes
Fix bugs in order of severity (Critical first). For each fix:
- Use
replace_file_contentormulti_replace_file_contentâ targeted diffs only, never replace the whole file unnecessarily - After ALL fixes, run TypeScript type check if applicable:
npx tsc --noEmit - If backend was changed, confirm the server reloaded (uvicorn
--reloadauto-detects) - Run a quick smoke test (curl / browser check) to confirm no regression
Step 5 â Final Verification
â
TypeScript: 0 errors
â
All Critical bugs fixed
â
All Medium bugs fixed or explicitly deferred with reason
â
Server responds to /health or equivalent
â
No new warnings introduced
Common Bug Patterns (Quick Reference)
React Hooks â Object Reference vs Value
Anytime state is produced via spread ({ ...prev, x: newX }) or a function that returns a new object,
the resulting reference is always different even if the value is logically the same.
// â WRONG â `newItem` is a new {} every update; reference compare always true
if (next.item !== prev.item) { triggerEffect() }
// â
CORRECT â compare by value (coordinate, counter, id, or JSON)
if (next.item.id !== prev.item.id) { triggerEffect() }
if (next.itemCount > prev.itemCount) { triggerEffect() }
React Hooks â Stale Closure on Recursive useCallback
A useCallback with empty [] deps captures the initial version of every variable.
Recursive calls inside setTimeout / setInterval will always invoke the stale version.
// â WRONG â doWork captures stale deps because deps array is empty
const doWork = useCallback(() => {
setTimeout(() => doWork(), delay) // calls the original stale closure
}, [])
// â
CORRECT â bridge via ref so the latest version is always called
const workRef = useRef<() => void>(() => {})
const doWork = useCallback(() => {
setTimeout(() => workRef.current(), delay) // always latest
}, [delay])
useEffect(() => { workRef.current = doWork }, [doWork])
Canvas â Shadow State Leak
shadowBlur and shadowColor are global canvas state. Resetting only shadowBlur to 0
does NOT stop the GPU from computing shadows â shadowColor must also be cleared.
// â WRONG â shadowColor still active, GPU overhead remains
ctx.shadowBlur = 0
// â
CORRECT
ctx.shadowBlur = 0
ctx.shadowColor = 'transparent'
Best Practice: wrap any shadow/globalAlpha changes in
ctx.save()/ctx.restore()to automatically restore state.
FastAPI â Deprecated Lifecycle Hook
# â WRONG â deprecated since FastAPI 0.93, will be removed
@app.on_event("startup")
def startup(): setup()
# â
CORRECT â use lifespan context manager
from contextlib import asynccontextmanager
@asynccontextmanager
async def lifespan(app: FastAPI):
setup() # startup logic
yield
teardown() # shutdown logic (optional)
app = FastAPI(lifespan=lifespan)
Circular Formula (Score containing a multiplier used in its own divisor)
When a computed value (e.g. score) already embeds a multiplier (e.g. level),
reusing it in the formula that recalculates level creates a circular dependency.
// â WRONG â score = base à level, so score / (base à threshold) cancels level
// â level never increases correctly at higher levels
const newLevel = 1 + Math.floor(score / (BASE_POINTS * THRESHOLD))
// â
CORRECT â track an independent event counter that has no multiplier
const newCount = prevCount + 1
const newLevel = 1 + Math.floor(newCount / THRESHOLD)
const newScore = prevScore + BASE_POINTS * newLevel // apply multiplier after