80 lines
5.9 KiB
Markdown
80 lines
5.9 KiB
Markdown
# Feature Specification: Add Knip Unused Code Detection
|
|
|
|
**Feature Branch**: `007-add-knip`
|
|
**Created**: 2026-03-05
|
|
**Status**: Draft
|
|
**Input**: User description: "Add Knip to the project to detect unused files, exports, dependencies, devDependencies, and types across the pnpm workspace and enforce it as part of the quality gate."
|
|
|
|
## User Scenarios & Testing *(mandatory)*
|
|
|
|
### User Story 1 - Detect Unused Code on Commit (Priority: P1)
|
|
|
|
As a developer, I want unused files, exports, dependencies, devDependencies, and types to be automatically detected when I commit, so that dead code never accumulates in the codebase.
|
|
|
|
**Why this priority**: This is the core value proposition — catching unused code as part of the existing quality gate ensures every commit keeps the codebase clean without requiring manual effort.
|
|
|
|
**Independent Test**: Can be fully tested by introducing an unused export into any workspace package and running the quality gate; the gate should fail with a clear report identifying the unused export.
|
|
|
|
**Acceptance Scenarios**:
|
|
|
|
1. **Given** the quality gate is run, **When** all files, exports, dependencies, and types are in use, **Then** the unused-code check passes successfully.
|
|
2. **Given** a file contains an unused export, **When** the quality gate is run, **Then** the check fails and reports the specific unused export and its file location.
|
|
3. **Given** a workspace package lists a dependency that is never imported, **When** the quality gate is run, **Then** the check fails and reports the unused dependency and the package it belongs to.
|
|
4. **Given** a file exists that is not imported or referenced anywhere, **When** the quality gate is run, **Then** the check fails and reports the unused file.
|
|
5. **Given** a type or interface is exported but never imported elsewhere, **When** the quality gate is run, **Then** the check fails and reports the unused type.
|
|
|
|
---
|
|
|
|
### User Story 2 - Run Unused-Code Check Independently (Priority: P2)
|
|
|
|
As a developer, I want to run the unused-code detection as a standalone command, so that I can inspect and fix issues before committing.
|
|
|
|
**Why this priority**: Developers need a fast feedback loop to discover and address unused code during development, not just at commit time.
|
|
|
|
**Independent Test**: Can be tested by running a dedicated command from the workspace root and verifying it produces output listing any unused items found across all workspace packages.
|
|
|
|
**Acceptance Scenarios**:
|
|
|
|
1. **Given** the developer is at the workspace root, **When** they run the standalone unused-code command, **Then** it analyzes all workspace packages and reports results.
|
|
2. **Given** unused items exist across multiple workspace packages, **When** the standalone command is run, **Then** all unused items are reported with their package and file location.
|
|
|
|
---
|
|
|
|
### Edge Cases
|
|
|
|
- What happens when a file is only used as an entry point (e.g., `main` or `exports` field in `package.json`)? It must not be falsely reported as unused.
|
|
- What happens when test files import modules only used in tests? Test-only dependencies and test utilities must not be flagged.
|
|
- What happens when configuration files (e.g., `vite.config.ts`, `vitest.config.ts`) reference plugins or packages? These must not be flagged as unused.
|
|
- What happens when workspace packages cross-reference each other via the `workspace:*` protocol? Internal workspace dependencies must be recognized.
|
|
- What happens when a type is re-exported from a barrel file? The re-export chain must be traced correctly.
|
|
|
|
## Requirements *(mandatory)*
|
|
|
|
### Functional Requirements
|
|
|
|
- **FR-001**: The system MUST detect unused files across all workspace packages (`packages/domain`, `packages/application`, `apps/web`).
|
|
- **FR-002**: The system MUST detect unused exports (functions, constants, types, interfaces) across all workspace packages.
|
|
- **FR-003**: The system MUST detect unused `dependencies` and `devDependencies` listed in each workspace package's `package.json`.
|
|
- **FR-004**: The system MUST be integrated into the existing quality gate (`pnpm check`) so that any unused code causes the gate to fail.
|
|
- **FR-005**: The system MUST provide a standalone command runnable from the workspace root to check for unused code independently of the full quality gate.
|
|
- **FR-006**: The system MUST correctly recognize entry points defined in each package's `package.json` (`main`, `exports`, `types` fields) and not flag them as unused.
|
|
- **FR-007**: The system MUST correctly handle pnpm workspace cross-references (`workspace:*` protocol) and not flag internal workspace dependencies as unused.
|
|
- **FR-008**: The system MUST correctly recognize test file patterns and not flag test-only utilities or test dependencies as unused when they are consumed by tests.
|
|
- **FR-009**: The system MUST correctly recognize configuration files and their plugin/dependency references.
|
|
|
|
## Success Criteria *(mandatory)*
|
|
|
|
### Measurable Outcomes
|
|
|
|
- **SC-001**: The quality gate fails when any unused file, export, dependency, or type is present, with zero false negatives for straightforward unused items.
|
|
- **SC-002**: The quality gate passes on the current codebase without false positives (no legitimate code is flagged as unused).
|
|
- **SC-003**: A developer can run the standalone unused-code check and receive results covering all workspace packages.
|
|
- **SC-004**: The unused-code report identifies the specific item (file, export name, dependency name) and its location (package and file path) for each finding.
|
|
|
|
## Assumptions
|
|
|
|
- Knip is the chosen tool for unused-code detection as specified by the user.
|
|
- The tool will be added as a root-level development dependency since it analyzes the entire workspace.
|
|
- Knip's built-in support for pnpm workspaces, TypeScript, Vitest, React, and Vite will handle most configuration automatically with minimal manual setup.
|
|
- The existing Lefthook pre-commit hook runs `pnpm check`, so adding the unused-code check to `pnpm check` automatically enforces it on every commit.
|