name: fix-jscpd description: Decision framework for fixing jscpd (copy-paste detector) errors. Use when asked to fix jscpd issues, copy-paste errors, clones or COPYPASTE lint failures. user-invocable: false
Fixing jscpd / Copy-Paste Issues
When jscpd reports a clone, decide between factorization and ignore comments based on these criteria.
Decision Criteria
Factorize when
- The duplicate logic is semantically identical and would not diverge (same intent, same data shape).
- Extracting it produces a clean, named helper with a clear single responsibility.
- The helper is small (under ~15 lines) and self-contained.
- The duplication is within the same file or a closely related module.
Examples in this project: buildPersonaCols(n) in profiles-extract.ts, formatLimitLine(limit) in limits.ts.
Ignore with /* jscpd:ignore-start */ / /* jscpd:ignore-end */ when
- The clones are in separate, unrelated command files (each command is a standalone unit).
- The structure is the same but the data shapes or intent diverge (e.g., different result fields in different audit commands).
- The duplication is unavoidable boilerplate (standard flags:
agent,debug,websocket,skipauth). - Extracting would add indirection with no real benefit (e.g.,
buildInitialMarkdownLinesin different DocBuilder subclasses).
Ignore Comment Placement
Place /* jscpd:ignore-start */ on the line before the first duplicate line, and /* jscpd:ignore-end */ on the line after the last duplicate line. Keep the comments on their own lines, indented to match the surrounding code.
/* jscpd:ignore-start */
for (const catcher of catchers) {
const results = await catchMatches(catcher, file, fileText, this);
this.matchResults.push(...results);
}
/* jscpd:ignore-end */
Factorization Pattern
Add a private (or private static) helper method to the enclosing class, or a module-level function if the logic is pure and stateless.
private static formatLimitLine(limit: any): string {
return `• ${limit.name}: *${limit.percentUsed}%* used (${limit.used}/${limit.max})`;
}
Then replace the duplicate .map(...) blocks with .map(MyClass.formatLimitLine).
Standard Flag Boilerplate
The agent, debug, websocket, and skipauth flags appear in every command. These are always intentional duplicates - wrap them with jscpd:ignore rather than abstracting.