Help us improve
Share bugs, ideas, or general feedback.
From plan-workflow
Audits codebases for dead imports, unused parameters, schema gaps, and stale docs after refactoring. Runs six checks to catch cascade effects missed by planning.
npx claudepluginhub minhthang1009/dotclaude --plugin plan-workflowHow this skill is triggered — by the user, by Claude, or both
Slash command
/plan-workflow:audit-deadThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Run after completing any implementation plan to find cascade effects that planning cannot predict (P5). Implementation changes the code; the changed code has properties — newly dead dependencies, newly broken contracts, newly inconsistent parallel paths — that no pre-implementation analysis could have foreseen.
Guides technical evaluation of code review feedback: read fully, restate for understanding, verify against codebase, respond with reasoning or pushback before implementing.
Share bugs, ideas, or general feedback.
Run after completing any implementation plan to find cascade effects that planning cannot predict (P5). Implementation changes the code; the changed code has properties — newly dead dependencies, newly broken contracts, newly inconsistent parallel paths — that no pre-implementation analysis could have foreseen.
/plan-refactor workflow, after all implementation phases passRun all six checks in order. Report all findings before suggesting fixes.
For each file in scope:
require() / import statements.DEAD_IMPORT.Verification requirement: Verify every candidate manually — do not trust automated scan output. Read the relevant lines. Automated dead-import scripts have high false positive rates because they cannot distinguish between code usage, comment mentions, and string literals.
False positive traps — do NOT flag these:
describe()/it() block → behavior description, not a variable referenceobj[varName] or template literal → alive but invisible to grepExample: After renaming parseAIResponse → parseLLMOutput, the old import const { parseAIResponse } = require(...) may still exist in a file that was missed by the rename plan. This is a genuine DEAD_IMPORT — the symbol is imported but never called because all call sites now use the new name.
For every function/method that had a parameter removed or made unused in this change:
Report the full chain: A collects X → passes to B → passes to C (param removed) → X is now dead in A and B.
Mid-implementation emergence: A parameter may be alive when the plan is written but become dead mid-implementation. For example, if Phase 1 removes a parameter from function C, and function B only collected that value to pass to C, then B's parameter became dead — but this was not in the original plan because B's parameter was alive at planning time. Check after each implementation phase, not only at the end.
YAGNI antipattern: Any parameter documented as "not currently used, kept for future extension" is a YAGNI violation. It will never be filled in. Remove it and trace the cascade upward. This is a common source of dead parameter chains that grow over time.
Example: Removing context from buildAugmentedPrompt(msg, products, context) made context in augmentAndGenerate(msg, products, context, history) dead (it was only collected to pass downstream). And context in handleMessage(msg, userId, sessionId, context) was only collected to pass to augmentAndGenerate. Full cascade: 3 functions cleaned.
Identify all functions that return the same logical type (e.g., "product card", "search result", "API response", "chat reply"). These are the most dangerous gaps because parallel paths are developed and maintained independently.
Common parallel path pairs:
For each group:
SCHEMA_GAP.The missing field causes a silent bug that only appears when the happy path fails — which is exactly when reliability matters most. Unit tests typically only cover the happy path.
Example: response-parser.js returns { id, name, slug, price, stockQuantity, ... } but keyword-fallback.js returns { id, name, slug, price, ... } — missing stockQuantity. Frontend code accessing product.stockQuantity gets undefined only when LLM is down.
Search explicitly for stale references — do not rely on having updated documentation during implementation:
grep -r "OldConcept" --include="*.md" # CLAUDE.md, README
grep -r "OldConcept" --include="*.[ext]" # JSDoc in source files
Specific patterns to check:
@param tags referencing a parameter that was removed → STALE_DOCSTALE_DOCSTALE_DOCSTALE_DOCJSDoc block integrity: When updating JSDoc, read the full surrounding context as a unit — do not edit just one @param line in isolation. Adjacent methods' JSDoc blocks can appear interleaved (one method's closing */ immediately followed by another method's /**). A partial read will miss this and editing the wrong block corrupts both.
Not all misplaced code is dead code. A function can be correctly used and referenced yet placed at the wrong structural level:
static method on the class. It passes all dead-code checks but has wrong structural ownership.For each module-level function in the changed files: check whether all its callers are within a single class. If yes, flag as MISPLACED_FUNCTION and propose converting to a class static method.
Example: buildEmbeddingText(product) defined at module level in vector-store.js but only called by HybridVectorStore.upsertProduct() → moved to static buildEmbeddingText(product) inside the class.
For each file changed, look for:
return / throw / continue / break in the same branch → UNREACHABLEtry/catch blocks where the guarded code cannot actually throw the caught exception typecontinue statements that appear reachable but are actually dead because a prior return already exits the function in all casesFor finding type definitions, see the "Finding Type Reference" table below.
[FILE:LINE] TYPE | Description | Confidence (HIGH/MED/LOW)
Types: DEAD_IMPORT · DEAD_VAR · DEAD_PARAM · DEAD_CASCADE · YAGNI_PARAM · SCHEMA_GAP · MISPLACED_FUNCTION · STALE_DOC · UNREACHABLE
Report findings at all confidence levels — HIGH/MED directly, LOW prefixed with (needs-verify) — and let the user decide. (This is a single-pass finder feeding HUMAN GATE 3 with no automated verifier downstream, so surface everything rather than self-filtering.)
End with:
Confirmed issues: N
Needs verification: N
Clean: YES / NO
★ HUMAN GATE 3: Present the above summary to the user before signing off. Include: (1) what was in the original plan and is now complete, (2) what this audit found that was NOT in the plan, (3) current test count vs BASELINE. Wait for the user to decide whether any findings require additional action before the workflow closes.
| Type | Description | Example |
|---|---|---|
DEAD_IMPORT | Imported symbol with no usage in file body | const { X } = require(...) but X never called |
DEAD_VAR | Declared variable never read after assignment | const x = compute(); // x never used |
DEAD_PARAM | Function parameter never used inside function | function f(a, b) { return a; } // b unused |
DEAD_CASCADE | Param/var dead because downstream consumer removed | A passes X to B; B's param removed → X dead in A |
YAGNI_PARAM | Param documented as "not used yet, kept for future" | YAGNI violation — remove and trace cascade |
SCHEMA_GAP | Field present in some execution paths but not others | LLM path returns stockQuantity, fallback doesn't |
MISPLACED_FUNCTION | Module-level function belonging as class static method | Function only called from within one class |
STALE_DOC | CLAUDE.md or JSDoc referencing old/removed symbol | @param context for a removed parameter |
UNREACHABLE | Code after unconditional return/throw | return x; doSomething(); // never reached |
| Pattern | Why it's NOT dead |
|---|---|
Symbol in JSDoc @param comment | Documentation, not dead code |
Symbol in test describe()/it() string | Behavior description |
| Symbol used only in test files | Tests are callers — alive |
| Symbol in log/error message string | Runtime usage — alive |
| Same name in different file/scope | Different entity entirely |
Symbol accessed via obj[varName] | Dynamic reference invisible to grep |