@harness-engineering/cli 1.8.0 → 1.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agents/skills/claude-code/harness-autopilot/SKILL.md +2 -2
- package/dist/agents/skills/claude-code/harness-brainstorming/SKILL.md +5 -7
- package/dist/agents/skills/claude-code/harness-code-review/SKILL.md +2 -2
- package/dist/agents/skills/claude-code/harness-planning/SKILL.md +2 -2
- package/dist/agents/skills/claude-code/harness-roadmap/SKILL.md +4 -5
- package/dist/agents/skills/gemini-cli/add-harness-component/SKILL.md +192 -0
- package/dist/agents/skills/gemini-cli/add-harness-component/skill.yaml +32 -0
- package/dist/agents/skills/gemini-cli/align-documentation/SKILL.md +213 -0
- package/dist/agents/skills/gemini-cli/align-documentation/skill.yaml +31 -0
- package/dist/agents/skills/gemini-cli/check-mechanical-constraints/SKILL.md +191 -0
- package/dist/agents/skills/gemini-cli/check-mechanical-constraints/skill.yaml +32 -0
- package/dist/agents/skills/gemini-cli/cleanup-dead-code/SKILL.md +245 -0
- package/dist/agents/skills/gemini-cli/cleanup-dead-code/skill.yaml +33 -0
- package/dist/agents/skills/gemini-cli/detect-doc-drift/SKILL.md +179 -0
- package/dist/agents/skills/gemini-cli/detect-doc-drift/skill.yaml +30 -0
- package/dist/agents/skills/gemini-cli/enforce-architecture/SKILL.md +240 -0
- package/dist/agents/skills/gemini-cli/enforce-architecture/skill.yaml +34 -0
- package/dist/agents/skills/gemini-cli/harness-architecture-advisor/SKILL.md +397 -0
- package/dist/agents/skills/gemini-cli/harness-architecture-advisor/skill.yaml +48 -0
- package/dist/agents/skills/gemini-cli/harness-autopilot/SKILL.md +2 -2
- package/dist/agents/skills/gemini-cli/harness-brainstorming/SKILL.md +317 -0
- package/dist/agents/skills/gemini-cli/harness-brainstorming/skill.yaml +49 -0
- package/dist/agents/skills/gemini-cli/harness-code-review/SKILL.md +681 -0
- package/dist/agents/skills/gemini-cli/harness-code-review/skill.yaml +45 -0
- package/dist/agents/skills/gemini-cli/harness-debugging/SKILL.md +366 -0
- package/dist/agents/skills/gemini-cli/harness-debugging/skill.yaml +47 -0
- package/dist/agents/skills/gemini-cli/harness-diagnostics/SKILL.md +318 -0
- package/dist/agents/skills/gemini-cli/harness-diagnostics/skill.yaml +50 -0
- package/dist/agents/skills/gemini-cli/harness-execution/SKILL.md +382 -0
- package/dist/agents/skills/gemini-cli/harness-execution/skill.yaml +51 -0
- package/dist/agents/skills/gemini-cli/harness-git-workflow/SKILL.md +268 -0
- package/dist/agents/skills/gemini-cli/harness-git-workflow/skill.yaml +31 -0
- package/dist/agents/skills/gemini-cli/harness-integrity/SKILL.md +167 -0
- package/dist/agents/skills/gemini-cli/harness-integrity/skill.yaml +47 -0
- package/dist/agents/skills/gemini-cli/harness-onboarding/SKILL.md +288 -0
- package/dist/agents/skills/gemini-cli/harness-onboarding/skill.yaml +30 -0
- package/dist/agents/skills/gemini-cli/harness-parallel-agents/SKILL.md +171 -0
- package/dist/agents/skills/gemini-cli/harness-parallel-agents/skill.yaml +33 -0
- package/dist/agents/skills/gemini-cli/harness-planning/SKILL.md +389 -0
- package/dist/agents/skills/gemini-cli/harness-planning/skill.yaml +49 -0
- package/dist/agents/skills/gemini-cli/harness-pre-commit-review/SKILL.md +262 -0
- package/dist/agents/skills/gemini-cli/harness-pre-commit-review/skill.yaml +33 -0
- package/dist/agents/skills/gemini-cli/harness-refactoring/SKILL.md +169 -0
- package/dist/agents/skills/gemini-cli/harness-refactoring/skill.yaml +33 -0
- package/dist/agents/skills/gemini-cli/harness-roadmap/SKILL.md +4 -5
- package/dist/agents/skills/gemini-cli/harness-skill-authoring/SKILL.md +292 -0
- package/dist/agents/skills/gemini-cli/harness-skill-authoring/skill.yaml +32 -0
- package/dist/agents/skills/gemini-cli/harness-state-management/SKILL.md +309 -0
- package/dist/agents/skills/gemini-cli/harness-state-management/skill.yaml +32 -0
- package/dist/agents/skills/gemini-cli/harness-tdd/SKILL.md +177 -0
- package/dist/agents/skills/gemini-cli/harness-tdd/skill.yaml +48 -0
- package/dist/agents/skills/gemini-cli/harness-verification/SKILL.md +328 -0
- package/dist/agents/skills/gemini-cli/harness-verification/skill.yaml +42 -0
- package/dist/agents/skills/gemini-cli/harness-verify/SKILL.md +159 -0
- package/dist/agents/skills/gemini-cli/harness-verify/skill.yaml +40 -0
- package/dist/agents/skills/gemini-cli/initialize-harness-project/SKILL.md +224 -0
- package/dist/agents/skills/gemini-cli/initialize-harness-project/skill.yaml +31 -0
- package/dist/agents/skills/gemini-cli/validate-context-engineering/SKILL.md +150 -0
- package/dist/agents/skills/gemini-cli/validate-context-engineering/skill.yaml +31 -0
- package/dist/bin/harness.js +3 -3
- package/dist/{chunk-SJECMKSS.js → chunk-E2RTDBMG.js} +25 -13
- package/dist/{chunk-LNI4T7R6.js → chunk-KJANDVVC.js} +20 -18
- package/dist/{chunk-3JWCBVUZ.js → chunk-RT2LYQHF.js} +1 -1
- package/dist/{dist-NT3GXHQZ.js → dist-CCM3L3UE.js} +1 -1
- package/dist/{dist-BDO5GFEM.js → dist-K6KTTN3I.js} +3 -3
- package/dist/index.js +3 -3
- package/dist/validate-cross-check-ZGKFQY57.js +7 -0
- package/package.json +6 -6
- package/dist/agents/skills/node_modules/.bin/glob +0 -17
- package/dist/agents/skills/node_modules/.bin/vitest +0 -17
- package/dist/agents/skills/node_modules/.bin/yaml +0 -17
- package/dist/templates/advanced/docs/specs/.gitkeep +0 -0
- package/dist/templates/intermediate/docs/specs/.gitkeep +0 -0
- package/dist/validate-cross-check-2OPGCGGU.js +0 -7
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
# Check Mechanical Constraints
|
|
2
|
+
|
|
3
|
+
> Run all mechanical constraint checks: linter rules, boundary schemas, and forbidden imports. These are automated, enforceable rules — if it can be checked by a machine, it must be.
|
|
4
|
+
|
|
5
|
+
## When to Use
|
|
6
|
+
|
|
7
|
+
- Before every commit (ideally via pre-commit hook)
|
|
8
|
+
- Before submitting a pull request for review
|
|
9
|
+
- After any code generation or automated refactoring
|
|
10
|
+
- When `on_pre_commit` or `on_validate` triggers fire
|
|
11
|
+
- After resolving merge conflicts (constraints may have been silently violated)
|
|
12
|
+
- NOT as a substitute for code review — mechanical constraints catch structural issues, not logic errors
|
|
13
|
+
- NOT when only editing non-code files (docs, config) unless those files have their own schema constraints
|
|
14
|
+
|
|
15
|
+
## Process
|
|
16
|
+
|
|
17
|
+
### Phase 1: Run All Checks
|
|
18
|
+
|
|
19
|
+
1. **Run `harness validate`** to check project-wide constraints: file structure, naming conventions, required files, and configuration validity.
|
|
20
|
+
|
|
21
|
+
2. **Run `harness linter validate`** to check all linter rules: code style, import restrictions, forbidden patterns, and boundary schemas.
|
|
22
|
+
|
|
23
|
+
3. **Run `harness check-deps`** to check architectural layer boundaries. This is included here because dependency violations are mechanical — they can be detected purely from import statements and the constraint config.
|
|
24
|
+
|
|
25
|
+
4. **Capture all output.** Combine results from all three commands into a single violation list for triage.
|
|
26
|
+
|
|
27
|
+
### Phase 2: Categorize Violations by Severity
|
|
28
|
+
|
|
29
|
+
Organize violations into three tiers:
|
|
30
|
+
|
|
31
|
+
**Tier 1 — Errors (must fix before commit):**
|
|
32
|
+
|
|
33
|
+
- Forbidden imports (importing banned modules)
|
|
34
|
+
- Layer boundary violations (importing across architectural boundaries)
|
|
35
|
+
- Schema violations (config files that do not match required schema)
|
|
36
|
+
- Missing required files (every package must have index.ts, etc.)
|
|
37
|
+
|
|
38
|
+
**Tier 2 — Warnings (must fix before merge):**
|
|
39
|
+
|
|
40
|
+
- Naming convention violations (wrong casing, wrong prefix)
|
|
41
|
+
- Import ordering issues
|
|
42
|
+
- Unused exports detected by linter
|
|
43
|
+
- Documentation file references that do not resolve
|
|
44
|
+
|
|
45
|
+
**Tier 3 — Info (fix when convenient):**
|
|
46
|
+
|
|
47
|
+
- Style suggestions (formatting that does not affect behavior)
|
|
48
|
+
- Complexity warnings (functions exceeding thresholds)
|
|
49
|
+
- Minor inconsistencies with project conventions
|
|
50
|
+
|
|
51
|
+
### Phase 3: Auto-Fix Where Safe
|
|
52
|
+
|
|
53
|
+
Some violations can be fixed automatically without risk:
|
|
54
|
+
|
|
55
|
+
- **Import ordering** — reorder imports to match the configured convention. This never changes behavior.
|
|
56
|
+
- **Formatting** — apply the project's formatter (prettier, etc.). Pure whitespace and style changes.
|
|
57
|
+
- **Simple forbidden imports** — when a forbidden import has a known replacement (e.g., `import lodash` to `import lodash-es`), apply the substitution.
|
|
58
|
+
- **Missing trailing commas, semicolons** — mechanical formatting fixes.
|
|
59
|
+
|
|
60
|
+
**Rules for auto-fix:**
|
|
61
|
+
|
|
62
|
+
- ONLY auto-fix violations that cannot change runtime behavior
|
|
63
|
+
- Run the test suite after auto-fixing to confirm nothing broke
|
|
64
|
+
- Present the auto-fix diff to the user for awareness (do not silently change code)
|
|
65
|
+
- If unsure whether a fix is safe, do NOT auto-fix — report it for manual resolution
|
|
66
|
+
|
|
67
|
+
### Phase 4: Report Remaining Violations
|
|
68
|
+
|
|
69
|
+
For each violation that was not auto-fixed, report:
|
|
70
|
+
|
|
71
|
+
1. **File and line number** — exact location of the violation
|
|
72
|
+
2. **Rule name** — which constraint was violated
|
|
73
|
+
3. **What it protects against** — why this rule exists (see reference below)
|
|
74
|
+
4. **How to fix** — specific guidance for resolving this type of violation
|
|
75
|
+
5. **Severity tier** — whether it blocks commit, merge, or is informational
|
|
76
|
+
|
|
77
|
+
## What Each Constraint Type Protects Against
|
|
78
|
+
|
|
79
|
+
### Forbidden Imports
|
|
80
|
+
|
|
81
|
+
**Protects against:** Implementation detail leakage and unwanted coupling. When a library is forbidden in a layer, it is because using it there would create a dependency that makes the layer harder to test, replace, or maintain. Example: forbidding `fs` in the UI layer ensures UI code never directly accesses the filesystem.
|
|
82
|
+
|
|
83
|
+
### Layer Boundaries
|
|
84
|
+
|
|
85
|
+
**Protects against:** Architectural erosion. Without enforced boundaries, codebases gradually become a tangle where everything depends on everything. Layer boundaries ensure changes in one area do not ripple unpredictably through the whole system.
|
|
86
|
+
|
|
87
|
+
### Boundary Schemas
|
|
88
|
+
|
|
89
|
+
**Protects against:** Configuration drift and invalid state. When config files must match a schema, you catch invalid configurations at lint time rather than at runtime. This prevents deployment failures and hard-to-debug runtime errors.
|
|
90
|
+
|
|
91
|
+
### Naming Conventions
|
|
92
|
+
|
|
93
|
+
**Protects against:** Cognitive overhead and inconsistency. Consistent naming means developers (human and AI) can predict file locations, function names, and module structure without searching. It also ensures automated tools that rely on naming patterns continue to work.
|
|
94
|
+
|
|
95
|
+
### Required File Rules
|
|
96
|
+
|
|
97
|
+
**Protects against:** Incomplete modules. When every package must have an `index.ts` or every component must have a test file, you ensure that the project structure remains complete and navigable.
|
|
98
|
+
|
|
99
|
+
### Import Ordering
|
|
100
|
+
|
|
101
|
+
**Protects against:** Merge conflicts and readability issues. Consistent import ordering reduces git conflicts when multiple developers add imports to the same file. It also makes imports scannable at a glance.
|
|
102
|
+
|
|
103
|
+
## Harness Integration
|
|
104
|
+
|
|
105
|
+
- **`harness validate`** — Project-wide structural validation. Checks file structure, naming conventions, required files, and configuration schemas.
|
|
106
|
+
- **`harness validate --json`** — Machine-readable output for parsing and categorization.
|
|
107
|
+
- **`harness linter validate`** — Runs all configured linter rules. Checks code patterns, import restrictions, and style conventions.
|
|
108
|
+
- **`harness check-deps`** — Architectural boundary enforcement. Checks all imports against the layer model.
|
|
109
|
+
- **`harness check-deps --json`** — Machine-readable dependency check output.
|
|
110
|
+
|
|
111
|
+
## Success Criteria
|
|
112
|
+
|
|
113
|
+
- All three commands (`harness validate`, `harness linter validate`, `harness check-deps`) pass with zero errors
|
|
114
|
+
- All Tier 1 violations are resolved before any commit
|
|
115
|
+
- All Tier 2 violations are resolved before any merge to main
|
|
116
|
+
- Auto-fixed changes are verified by running the test suite
|
|
117
|
+
- No violations are suppressed without explicit team approval and a documented reason
|
|
118
|
+
|
|
119
|
+
## Examples
|
|
120
|
+
|
|
121
|
+
### Example: Forbidden import detected
|
|
122
|
+
|
|
123
|
+
**Violation:**
|
|
124
|
+
|
|
125
|
+
```
|
|
126
|
+
ERROR [forbidden-import] src/components/Dashboard.tsx:3
|
|
127
|
+
Import 'pg' is forbidden in layer 'ui'
|
|
128
|
+
Rule: ui layer must not import database drivers
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
**What it protects against:** The UI layer importing a PostgreSQL driver means UI code could execute raw SQL queries, bypassing the service and repository layers entirely. This breaks testability (tests need a real database) and security (SQL injection risk from UI layer).
|
|
132
|
+
|
|
133
|
+
**Fix:** Remove the direct database call. Add the needed query to the appropriate repository, expose it through the service layer, and call the service from the UI component.
|
|
134
|
+
|
|
135
|
+
### Example: Auto-fixable import ordering
|
|
136
|
+
|
|
137
|
+
**Violation:**
|
|
138
|
+
|
|
139
|
+
```
|
|
140
|
+
WARNING [import-order] src/services/auth-service.ts:1-8
|
|
141
|
+
Imports are not in the configured order
|
|
142
|
+
Expected: builtin -> external -> internal -> relative
|
|
143
|
+
Found: relative -> external -> builtin
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
**Auto-fix applied:**
|
|
147
|
+
|
|
148
|
+
```typescript
|
|
149
|
+
// BEFORE
|
|
150
|
+
import { hashPassword } from './utils';
|
|
151
|
+
import bcrypt from 'bcrypt';
|
|
152
|
+
import { createHash } from 'crypto';
|
|
153
|
+
|
|
154
|
+
// AFTER (auto-fixed)
|
|
155
|
+
import { createHash } from 'crypto';
|
|
156
|
+
import bcrypt from 'bcrypt';
|
|
157
|
+
import { hashPassword } from './utils';
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
Tests re-run: all passing. No behavioral change.
|
|
161
|
+
|
|
162
|
+
### Example: Schema violation in config
|
|
163
|
+
|
|
164
|
+
**Violation:**
|
|
165
|
+
|
|
166
|
+
```
|
|
167
|
+
ERROR [schema-violation] harness.config.json:24
|
|
168
|
+
Property 'layers[2].allowedImports' must be an array of strings
|
|
169
|
+
Found: number (42)
|
|
170
|
+
Schema: harness-config-schema.json#/properties/layers/items/properties/allowedImports
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
**What it protects against:** An invalid config means `harness check-deps` will either crash or silently skip validation. The layer constraints would not be enforced, allowing violations to slip through undetected.
|
|
174
|
+
|
|
175
|
+
**Fix:** Correct the config value to be a valid string array: `"allowedImports": ["@shared/types", "@shared/utils"]`.
|
|
176
|
+
|
|
177
|
+
## Gates
|
|
178
|
+
|
|
179
|
+
These are hard stops. Mechanical constraints are non-negotiable.
|
|
180
|
+
|
|
181
|
+
- **No commits with Tier 1 violations.** Errors must be resolved before the code is committed. No exceptions.
|
|
182
|
+
- **No merges with Tier 2 violations.** Warnings must be resolved before merging to the main branch.
|
|
183
|
+
- **No suppressing rules without documentation.** If a rule must be disabled for a specific line or file, the suppression comment must explain WHY (not just disable the rule).
|
|
184
|
+
- **No auto-fix without test verification.** Every auto-fix must be followed by a test run to confirm no behavioral change.
|
|
185
|
+
|
|
186
|
+
## Escalation
|
|
187
|
+
|
|
188
|
+
- **When a rule seems wrong for the project:** Rules are configured in `harness.config.json` and linter configs. If a rule does not fit, propose a config change with justification. Do not disable the rule inline.
|
|
189
|
+
- **When a violation cannot be fixed without a larger refactor:** Document the violation, create a task for the refactor, and get team approval for a temporary inline suppression with a TODO linking to the task.
|
|
190
|
+
- **When auto-fix produces unexpected changes:** Undo the auto-fix, report the issue, and fix manually. Auto-fix tools are not infallible.
|
|
191
|
+
- **When multiple constraints conflict:** The stricter constraint wins. If `harness validate` says a file is required but `harness linter validate` says its contents violate a rule, fix the contents to satisfy both. Escalate if truly irreconcilable.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
name: check-mechanical-constraints
|
|
2
|
+
version: "1.0.0"
|
|
3
|
+
description: Run all mechanical constraint checks (context validation + architecture)
|
|
4
|
+
cognitive_mode: meticulous-verifier
|
|
5
|
+
triggers:
|
|
6
|
+
- manual
|
|
7
|
+
- on_pr
|
|
8
|
+
platforms:
|
|
9
|
+
- claude-code
|
|
10
|
+
- gemini-cli
|
|
11
|
+
tools:
|
|
12
|
+
- Bash
|
|
13
|
+
- Read
|
|
14
|
+
- Glob
|
|
15
|
+
cli:
|
|
16
|
+
command: harness skill run check-mechanical-constraints
|
|
17
|
+
args:
|
|
18
|
+
- name: path
|
|
19
|
+
description: Project root path
|
|
20
|
+
required: false
|
|
21
|
+
mcp:
|
|
22
|
+
tool: run_skill
|
|
23
|
+
input:
|
|
24
|
+
skill: check-mechanical-constraints
|
|
25
|
+
path: string
|
|
26
|
+
type: rigid
|
|
27
|
+
state:
|
|
28
|
+
persistent: false
|
|
29
|
+
files: []
|
|
30
|
+
depends_on:
|
|
31
|
+
- validate-context-engineering
|
|
32
|
+
- enforce-architecture
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
# Cleanup Dead Code
|
|
2
|
+
|
|
3
|
+
> Entropy analysis and safe cleanup. Find unused exports, dead files, and pattern violations — then remove them without breaking anything.
|
|
4
|
+
|
|
5
|
+
## When to Use
|
|
6
|
+
|
|
7
|
+
- After a major refactoring or feature removal
|
|
8
|
+
- When the codebase feels "heavy" — too many files, unclear what is used
|
|
9
|
+
- As a periodic hygiene task (monthly or per-quarter)
|
|
10
|
+
- When `on_entropy_check` triggers fire
|
|
11
|
+
- After deleting a feature flag and its associated code paths
|
|
12
|
+
- When `harness cleanup` reports growing entropy in the project health dashboard
|
|
13
|
+
- NOT during active feature development — dead code cleanup is a separate, focused task
|
|
14
|
+
- NOT when tests are failing — fix tests first, then clean up
|
|
15
|
+
- NOT under time pressure — dead code removal requires careful verification
|
|
16
|
+
|
|
17
|
+
## Process
|
|
18
|
+
|
|
19
|
+
### Phase 1: Analyze — Run Entropy Report
|
|
20
|
+
|
|
21
|
+
1. **Run `harness cleanup`** to generate a full entropy report. This analyzes:
|
|
22
|
+
- **Dead exports** — functions, classes, and constants that are exported but never imported anywhere
|
|
23
|
+
- **Unused files** — files that are not imported by any other file in the project
|
|
24
|
+
- **Pattern violations** — code that violates established project patterns (e.g., a service file without a corresponding test file)
|
|
25
|
+
- **Orphaned dependencies** — npm packages listed in package.json but never imported
|
|
26
|
+
|
|
27
|
+
2. **Run `harness cleanup --type dead-code --json`** for machine-readable output focused specifically on unused code.
|
|
28
|
+
|
|
29
|
+
3. **Review the report summary.** Note the total count and distribution. A few dead exports are normal; dozens suggest accumulated entropy from incomplete refactorings.
|
|
30
|
+
|
|
31
|
+
### Graph-Enhanced Context (when available)
|
|
32
|
+
|
|
33
|
+
When a knowledge graph exists at `.harness/graph/`, use graph queries for faster, more accurate dead code detection:
|
|
34
|
+
|
|
35
|
+
- `query_graph` — perform graph reachability analysis from entry point nodes to identify truly unreachable code
|
|
36
|
+
- `get_relationships` — distinguish dynamic imports from genuinely unused code by checking edge types
|
|
37
|
+
|
|
38
|
+
Graph reachability reduces false positives compared to static analysis alone, since it traces the full transitive import graph including re-exports. Fall back to file-based commands if no graph is available.
|
|
39
|
+
|
|
40
|
+
### Phase 2: Categorize — Safe vs. Needs Review
|
|
41
|
+
|
|
42
|
+
**Safe to auto-fix (remove without further analysis):**
|
|
43
|
+
|
|
44
|
+
- Exports that are not imported anywhere AND not referenced in any config file
|
|
45
|
+
- Files that are not imported anywhere AND have no side effects (no top-level execution)
|
|
46
|
+
- Dead exports (non-public, zero importers) -- remove `export` keyword or delete entirely if zero internal callers
|
|
47
|
+
- Commented-out code blocks -- delete commented block (dead by definition, code is in git history)
|
|
48
|
+
- Orphaned npm dependencies -- remove from package.json (probably safe; needs install+test verification)
|
|
49
|
+
- Unused local variables and imports within a file (linter can catch these)
|
|
50
|
+
|
|
51
|
+
**Needs human review before removal:**
|
|
52
|
+
|
|
53
|
+
- Exports that APPEAR unused but might be consumed dynamically (see "What NOT to Delete" below)
|
|
54
|
+
- Files that appear unused but are entry points (CLI scripts, test fixtures, config files)
|
|
55
|
+
- Code that is only used in specific build configurations or environments
|
|
56
|
+
- Exports from a public package — external consumers may depend on them
|
|
57
|
+
|
|
58
|
+
### Phase 3: Apply Safe Fixes
|
|
59
|
+
|
|
60
|
+
For each item categorized as safe:
|
|
61
|
+
|
|
62
|
+
1. **Remove the dead code.** Delete the export, function, file, or import.
|
|
63
|
+
|
|
64
|
+
2. **Run `harness fix-drift`** to update any documentation references that pointed to the deleted code.
|
|
65
|
+
|
|
66
|
+
3. **Run the full test suite.** All tests must pass. If any test fails:
|
|
67
|
+
- **STOP.** The code was not actually dead — something depends on it.
|
|
68
|
+
- **Undo the deletion immediately.**
|
|
69
|
+
- **Reclassify** the item as "needs human review" and investigate the hidden dependency.
|
|
70
|
+
|
|
71
|
+
4. **Run `harness validate` and `harness check-deps`.** Both must pass.
|
|
72
|
+
|
|
73
|
+
5. **Commit the cleanup.** Group related removals into logical commits (e.g., "remove unused shipping utilities" not "delete dead code").
|
|
74
|
+
|
|
75
|
+
**New fix types:**
|
|
76
|
+
|
|
77
|
+
- **Dead exports (non-public):** Use `apply_fixes` with `fixTypes: ['dead-exports']`. The tool removes the `export` keyword. If the function/class has zero internal callers too, delete the entire declaration.
|
|
78
|
+
- **Commented-out code:** Use `apply_fixes` with `fixTypes: ['commented-code']`. The tool deletes commented-out code blocks. This is cosmetic and only needs lint verification.
|
|
79
|
+
- **Orphaned dependencies:** Use `apply_fixes` with `fixTypes: ['orphaned-deps']`. The tool removes the dep from package.json. **Must run `pnpm install && pnpm test` after** to verify nothing breaks.
|
|
80
|
+
|
|
81
|
+
### Phase 3.5: Convergence Loop (Standalone)
|
|
82
|
+
|
|
83
|
+
When running standalone (not through the orchestrator), apply a single-concern convergence loop:
|
|
84
|
+
|
|
85
|
+
1. **Re-run detection.** After applying all safe fixes, run `harness cleanup --type dead-code` again.
|
|
86
|
+
2. **Check if issue count decreased.** Compare the new count to the previous count.
|
|
87
|
+
3. **If decreased: loop.** New dead code may have been exposed by the fixes (e.g., removing a dead export made a file fully unused). Go back to Phase 2 (Categorize) with the new report.
|
|
88
|
+
4. **If unchanged: stop.** No more cascading fixes are possible. Proceed to Phase 4 (Report).
|
|
89
|
+
5. **Maximum iterations: 5.** To prevent infinite loops, stop after 5 convergence cycles regardless.
|
|
90
|
+
|
|
91
|
+
**Why convergence matters:** Removing dead code can create more dead code. For example:
|
|
92
|
+
|
|
93
|
+
- Removing a dead export may make all remaining exports in a file dead, making the file itself dead.
|
|
94
|
+
- Removing a dead file removes its imports, which may make other files' exports dead.
|
|
95
|
+
- Removing an orphaned dep may cause lint warnings that reveal unused imports.
|
|
96
|
+
|
|
97
|
+
### Phase 4: Report Remaining Items
|
|
98
|
+
|
|
99
|
+
### Graph Refresh
|
|
100
|
+
|
|
101
|
+
If a knowledge graph exists at `.harness/graph/`, refresh it after code changes to keep graph queries accurate:
|
|
102
|
+
|
|
103
|
+
```
|
|
104
|
+
harness scan [path]
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Dead code removal changes graph topology — skipping this step means subsequent graph queries (impact analysis, dependency health, test advisor) may return stale results.
|
|
108
|
+
|
|
109
|
+
For items that need human review, report:
|
|
110
|
+
|
|
111
|
+
1. **What it is** — file path, export name, what it does
|
|
112
|
+
2. **Why it appears dead** — no static imports found
|
|
113
|
+
3. **Why it might not be dead** — dynamic import patterns, external consumers, test utilities
|
|
114
|
+
4. **Recommended action** — delete with confidence, delete with caution, or keep
|
|
115
|
+
|
|
116
|
+
## What NOT to Delete
|
|
117
|
+
|
|
118
|
+
These patterns make code APPEAR dead when it is actually in use:
|
|
119
|
+
|
|
120
|
+
### Dynamically imported modules
|
|
121
|
+
|
|
122
|
+
```typescript
|
|
123
|
+
// This import won't show up in static analysis
|
|
124
|
+
const module = await import(`./plugins/${pluginName}`);
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Files in a `plugins/` directory may appear unused but are loaded dynamically at runtime. Check for `import()` calls, `require()` with variables, and glob-based loading patterns.
|
|
128
|
+
|
|
129
|
+
### Test utilities and fixtures
|
|
130
|
+
|
|
131
|
+
```typescript
|
|
132
|
+
// test-helpers.ts — only imported by test files
|
|
133
|
+
export function createMockUser() { ... }
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
Test utility files may appear unused if the analysis excludes test files. Verify that `harness cleanup` includes test files in its import graph.
|
|
137
|
+
|
|
138
|
+
### Type-only exports
|
|
139
|
+
|
|
140
|
+
```typescript
|
|
141
|
+
// Only used as a type, never as a value
|
|
142
|
+
export interface UserConfig { ... }
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Some analysis tools miss type-only imports (`import type { UserConfig }`). Verify before deleting any exported interface or type alias.
|
|
146
|
+
|
|
147
|
+
### Package entry points
|
|
148
|
+
|
|
149
|
+
```typescript
|
|
150
|
+
// index.ts — re-exports for external consumers
|
|
151
|
+
export { createClient } from './client';
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
The entry point of a package re-exports things for external consumers. These exports may have zero internal imports but are the public API.
|
|
155
|
+
|
|
156
|
+
### Side-effect files
|
|
157
|
+
|
|
158
|
+
```typescript
|
|
159
|
+
// polyfills.ts — imported for side effects, not for exports
|
|
160
|
+
import './polyfills';
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
Some files are imported for their side effects (polyfills, global registrations, CSS). They have no exports but are not dead.
|
|
164
|
+
|
|
165
|
+
### Environment-specific code
|
|
166
|
+
|
|
167
|
+
```typescript
|
|
168
|
+
// Only used when FEATURE_FLAG_X is enabled
|
|
169
|
+
if (process.env.FEATURE_FLAG_X) {
|
|
170
|
+
const handler = require('./experimental-handler');
|
|
171
|
+
}
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
Code behind feature flags or environment checks may appear dead in the default configuration.
|
|
175
|
+
|
|
176
|
+
## Harness Integration
|
|
177
|
+
|
|
178
|
+
- **`harness cleanup`** — Full entropy analysis. Reports dead exports, unused files, pattern violations, and orphaned dependencies.
|
|
179
|
+
- **`harness cleanup --type dead-code`** — Focused analysis on unused code specifically.
|
|
180
|
+
- **`harness cleanup --type dead-code --json`** — Machine-readable output for automation.
|
|
181
|
+
- **`harness fix-drift`** — Update documentation after removing dead code. Ensures deleted items are not still referenced in docs.
|
|
182
|
+
- **`harness validate`** — Run after cleanup to verify project structure remains valid.
|
|
183
|
+
- **`harness check-deps`** — Run after cleanup to verify no dependency violations were introduced.
|
|
184
|
+
|
|
185
|
+
## Success Criteria
|
|
186
|
+
|
|
187
|
+
- `harness cleanup` reports zero dead exports and zero unused files (or all remaining items are documented as intentional)
|
|
188
|
+
- All tests pass after every deletion
|
|
189
|
+
- `harness validate` and `harness check-deps` pass after cleanup
|
|
190
|
+
- Documentation references to deleted code are updated or removed
|
|
191
|
+
- No dynamically-imported, type-only, or side-effect code was accidentally deleted
|
|
192
|
+
- Each cleanup commit is atomic and has a descriptive message explaining what was removed and why
|
|
193
|
+
|
|
194
|
+
## Examples
|
|
195
|
+
|
|
196
|
+
### Example: Removing unused utility functions
|
|
197
|
+
|
|
198
|
+
**Entropy report:**
|
|
199
|
+
|
|
200
|
+
```
|
|
201
|
+
DEAD EXPORT: src/utils/string-helpers.ts
|
|
202
|
+
- capitalizeFirst() — 0 imports found
|
|
203
|
+
- truncateWithEllipsis() — 0 imports found
|
|
204
|
+
- slugify() — 3 imports found (ACTIVE, not dead)
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
**Action:** Remove `capitalizeFirst` and `truncateWithEllipsis` from the file. Keep `slugify`. Run tests — all pass. Commit: "remove unused capitalizeFirst and truncateWithEllipsis from string-helpers"
|
|
208
|
+
|
|
209
|
+
### Example: Detecting a false positive
|
|
210
|
+
|
|
211
|
+
**Entropy report:**
|
|
212
|
+
|
|
213
|
+
```
|
|
214
|
+
UNUSED FILE: src/plugins/markdown-renderer.ts
|
|
215
|
+
- 0 static imports found
|
|
216
|
+
- File contains: export default class MarkdownRenderer
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
**Investigation:** Check for dynamic imports:
|
|
220
|
+
|
|
221
|
+
```typescript
|
|
222
|
+
// src/plugins/index.ts
|
|
223
|
+
const renderer = await import(`./${format}-renderer`);
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
**Result:** False positive. The file is loaded dynamically based on the `format` variable. Mark as intentional and add a comment in the file explaining the dynamic loading pattern.
|
|
227
|
+
|
|
228
|
+
### Example: Orphaned npm dependency
|
|
229
|
+
|
|
230
|
+
**Entropy report:**
|
|
231
|
+
|
|
232
|
+
```
|
|
233
|
+
ORPHANED DEPENDENCY: moment (package.json)
|
|
234
|
+
- 0 imports of 'moment' found in src/
|
|
235
|
+
- Last imported in commit abc123 (removed 3 months ago)
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
**Action:** Remove `moment` from package.json dependencies. Run `npm install` to update lockfile. Run tests — all pass. Commit: "remove unused moment dependency"
|
|
239
|
+
|
|
240
|
+
## Escalation
|
|
241
|
+
|
|
242
|
+
- **When removing code causes unexpected test failures:** The code has a hidden dependency. Undo the deletion, investigate the dependency chain, and document the finding. The code is not dead — it is just hard to trace.
|
|
243
|
+
- **When the entropy report is very large (>50 items):** Do not attempt to clean everything at once. Pick the highest-confidence dead code (files with zero imports, no dynamic patterns) and clean those first. Schedule the rest across multiple sessions.
|
|
244
|
+
- **When you are unsure if an export is used externally:** Check if the code is in a published package. If so, removing an export is a breaking change. Deprecate first, then remove in a major version.
|
|
245
|
+
- **When dead code is tangled with live code in the same file:** Extract the live code first (using harness-refactoring), then delete the remaining dead code. Do not try to surgically remove dead code from a complex file in one step.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
name: cleanup-dead-code
|
|
2
|
+
version: "1.1.0"
|
|
3
|
+
description: Detect and auto-fix dead code including dead exports, commented-out code, and orphaned dependencies
|
|
4
|
+
cognitive_mode: diagnostic-investigator
|
|
5
|
+
triggers:
|
|
6
|
+
- manual
|
|
7
|
+
platforms:
|
|
8
|
+
- claude-code
|
|
9
|
+
- gemini-cli
|
|
10
|
+
tools:
|
|
11
|
+
- Bash
|
|
12
|
+
- Read
|
|
13
|
+
- Glob
|
|
14
|
+
- Grep
|
|
15
|
+
cli:
|
|
16
|
+
command: harness skill run cleanup-dead-code
|
|
17
|
+
args:
|
|
18
|
+
- name: path
|
|
19
|
+
description: Project root path
|
|
20
|
+
required: false
|
|
21
|
+
- name: fix
|
|
22
|
+
description: Enable auto-fix with convergence loop
|
|
23
|
+
required: false
|
|
24
|
+
mcp:
|
|
25
|
+
tool: run_skill
|
|
26
|
+
input:
|
|
27
|
+
skill: cleanup-dead-code
|
|
28
|
+
path: string
|
|
29
|
+
type: flexible
|
|
30
|
+
state:
|
|
31
|
+
persistent: false
|
|
32
|
+
files: []
|
|
33
|
+
depends_on: []
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
# Detect Doc Drift
|
|
2
|
+
|
|
3
|
+
> Detect documentation that has drifted from code. Find stale docs before they mislead developers and AI agents.
|
|
4
|
+
|
|
5
|
+
## When to Use
|
|
6
|
+
|
|
7
|
+
- After completing a feature, bug fix, or refactoring
|
|
8
|
+
- During code review — check if the changed files have associated docs that need updating
|
|
9
|
+
- As a periodic hygiene check (weekly or per-sprint)
|
|
10
|
+
- When `on_post_feature` or `on_doc_check` triggers fire
|
|
11
|
+
- When onboarding reveals confusion caused by outdated documentation
|
|
12
|
+
- NOT during active development — wait until the code is stable before checking docs
|
|
13
|
+
- NOT for writing new documentation from scratch (use align-documentation instead)
|
|
14
|
+
|
|
15
|
+
## Process
|
|
16
|
+
|
|
17
|
+
### Phase 1: Scan — Run Drift Detection
|
|
18
|
+
|
|
19
|
+
1. **Run `harness check-docs`** to identify all documentation issues. Capture the full output.
|
|
20
|
+
|
|
21
|
+
2. **Run `harness cleanup --type drift`** for a deeper analysis that cross-references code changes against documentation references.
|
|
22
|
+
|
|
23
|
+
3. **Optionally, run `git diff` against a baseline** (last release, last sprint, etc.) to identify which code files changed. This helps prioritize — docs for recently changed files are most likely to be drifted.
|
|
24
|
+
|
|
25
|
+
### Graph-Enhanced Context (when available)
|
|
26
|
+
|
|
27
|
+
When a knowledge graph exists at `.harness/graph/`, use graph queries for faster, more accurate drift detection:
|
|
28
|
+
|
|
29
|
+
- `query_graph` — find `documents` edges where the target code node has changed since the doc node was last updated
|
|
30
|
+
|
|
31
|
+
When a graph is available, drift is simply stale edges: doc-to-code edges where the code side has been modified more recently than the doc side. This replaces regex pattern matching and catches semantic drift that text search misses. Fall back to file-based commands if no graph is available.
|
|
32
|
+
|
|
33
|
+
### Pipeline Context (when orchestrated)
|
|
34
|
+
|
|
35
|
+
When invoked by `harness-docs-pipeline`, check for a `pipeline` field in `.harness/handoff.json`:
|
|
36
|
+
|
|
37
|
+
- If `pipeline` field exists: read `DocPipelineContext` from it
|
|
38
|
+
- Use `pipeline.exclusions` to skip findings that were already addressed in a previous phase
|
|
39
|
+
- Write `DriftFinding[]` results back to `pipeline.driftFindings` in handoff.json
|
|
40
|
+
- This enables the orchestrator to track findings across phases and avoid double-counting
|
|
41
|
+
- If `pipeline` field does not exist: behave exactly as today (standalone mode)
|
|
42
|
+
|
|
43
|
+
No changes to the skill's interface or output format — the pipeline field is purely additive.
|
|
44
|
+
|
|
45
|
+
### Phase 2: Identify — Classify Drift Types
|
|
46
|
+
|
|
47
|
+
Categorize each finding into one of these drift types:
|
|
48
|
+
|
|
49
|
+
**Renamed but not updated:**
|
|
50
|
+
A function, class, variable, or file was renamed in code, but documentation still references the old name. This is the most common type of drift.
|
|
51
|
+
|
|
52
|
+
- Example: `calculateShipping()` was renamed to `computeShippingCost()`, but AGENTS.md and three inline comments still say `calculateShipping`.
|
|
53
|
+
|
|
54
|
+
**New code with no docs:**
|
|
55
|
+
A new module, function, or API was added but no documentation entry exists. This is not "drift" in the strict sense but a gap that grows into drift over time.
|
|
56
|
+
|
|
57
|
+
- Example: `src/services/notification-service.ts` was added two sprints ago. It has 5 public exports. No AGENTS.md section, no doc page, no inline doc comments beyond basic JSDoc.
|
|
58
|
+
|
|
59
|
+
**Deleted code still referenced:**
|
|
60
|
+
A file, function, or feature was removed, but documentation still describes it as if it exists. This actively misleads readers.
|
|
61
|
+
|
|
62
|
+
- Example: `src/utils/legacy-parser.ts` was deleted. The architecture doc still includes it in the data flow diagram. AGENTS.md still warns about its quirks.
|
|
63
|
+
|
|
64
|
+
**Changed behavior not reflected:**
|
|
65
|
+
A function's signature, return type, error handling, or side effects changed, but the documentation describes the old behavior.
|
|
66
|
+
|
|
67
|
+
- Example: `createUser()` now throws `ValidationError` instead of returning `null` on invalid input. The API docs still say "returns null if validation fails."
|
|
68
|
+
|
|
69
|
+
**Moved code with stale paths:**
|
|
70
|
+
A file or module was moved to a different directory, but documentation references the old path.
|
|
71
|
+
|
|
72
|
+
- Example: `src/helpers/format.ts` was moved to `src/utils/format.ts`. Three doc files and AGENTS.md reference the old path.
|
|
73
|
+
|
|
74
|
+
### Phase 3: Prioritize — Rank by Impact
|
|
75
|
+
|
|
76
|
+
Not all drift is equally harmful. Prioritize fixes:
|
|
77
|
+
|
|
78
|
+
**Critical (fix immediately):**
|
|
79
|
+
|
|
80
|
+
- Public API documentation that describes wrong behavior — external consumers will write broken code
|
|
81
|
+
- AGENTS.md sections that reference deleted files — AI agents will hallucinate about non-existent code
|
|
82
|
+
- README getting-started guides with wrong commands — new developers cannot onboard
|
|
83
|
+
|
|
84
|
+
**High (fix before next release):**
|
|
85
|
+
|
|
86
|
+
- Internal API docs with wrong signatures — developers waste time debugging
|
|
87
|
+
- Architecture docs with stale diagrams — wrong mental models lead to wrong decisions
|
|
88
|
+
- Frequently accessed docs with broken links — high-traffic pages with dead ends
|
|
89
|
+
|
|
90
|
+
**Medium (fix in next sprint):**
|
|
91
|
+
|
|
92
|
+
- Internal docs for stable code — low change rate means low confusion rate
|
|
93
|
+
- Comments in rarely modified files — few people read them
|
|
94
|
+
- Edge case documentation — affects few users
|
|
95
|
+
|
|
96
|
+
**Low (fix when convenient):**
|
|
97
|
+
|
|
98
|
+
- Stylistic inconsistencies in docs (capitalization, formatting)
|
|
99
|
+
- Redundant documentation that says the same thing in multiple places
|
|
100
|
+
- Historical notes that are outdated but clearly marked as historical
|
|
101
|
+
|
|
102
|
+
### Phase 4: Report — Generate Actionable Output
|
|
103
|
+
|
|
104
|
+
For each drift finding, provide:
|
|
105
|
+
|
|
106
|
+
1. **File and line number** of the drifted documentation
|
|
107
|
+
2. **The specific stale content** (quote the exact text that is wrong)
|
|
108
|
+
3. **What changed in code** (the commit, file, and nature of the change)
|
|
109
|
+
4. **Suggested fix** (the replacement text or action needed)
|
|
110
|
+
5. **Priority tier** (Critical / High / Medium / Low)
|
|
111
|
+
|
|
112
|
+
Group findings by documentation file so that fixes can be applied file-by-file.
|
|
113
|
+
|
|
114
|
+
## Harness Integration
|
|
115
|
+
|
|
116
|
+
- **`harness check-docs`** — Primary tool. Scans all documentation files for broken references, stale paths, and missing entries.
|
|
117
|
+
- **`harness cleanup --type drift`** — Deeper analysis that cross-references git history with documentation references to detect semantic drift.
|
|
118
|
+
- **`harness cleanup --type drift --json`** — Machine-readable output for automated pipelines.
|
|
119
|
+
- **`harness fix-drift`** — Auto-fix simple drift issues after review (use align-documentation skill for applying fixes).
|
|
120
|
+
|
|
121
|
+
## Success Criteria
|
|
122
|
+
|
|
123
|
+
- `harness check-docs` reports zero errors
|
|
124
|
+
- All file paths referenced in documentation resolve to existing files
|
|
125
|
+
- All function/class names referenced in documentation match current code
|
|
126
|
+
- All API documentation matches current function signatures and behavior
|
|
127
|
+
- No documentation references deleted files, functions, or features
|
|
128
|
+
- Drift findings are prioritized and assigned to the appropriate fix cycle
|
|
129
|
+
|
|
130
|
+
## Examples
|
|
131
|
+
|
|
132
|
+
### Example: Renamed function detected
|
|
133
|
+
|
|
134
|
+
**Drift finding:**
|
|
135
|
+
|
|
136
|
+
```
|
|
137
|
+
DRIFT: Renamed reference detected
|
|
138
|
+
Doc: AGENTS.md:47
|
|
139
|
+
Stale text: "Use `calculateShipping()` to compute shipping costs"
|
|
140
|
+
Code change: calculateShipping renamed to computeShippingCost (commit a1b2c3d)
|
|
141
|
+
File: src/services/shipping.ts:24
|
|
142
|
+
Priority: High
|
|
143
|
+
Suggested fix: Replace `calculateShipping()` with `computeShippingCost()`
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### Example: Deleted file still documented
|
|
147
|
+
|
|
148
|
+
**Drift finding:**
|
|
149
|
+
|
|
150
|
+
```
|
|
151
|
+
DRIFT: Reference to deleted file
|
|
152
|
+
Doc: docs/architecture.md:112
|
|
153
|
+
Stale text: "The legacy parser (src/utils/legacy-parser.ts) handles XML input"
|
|
154
|
+
Code change: File deleted in commit d4e5f6g, functionality merged into unified-parser.ts
|
|
155
|
+
Priority: Critical
|
|
156
|
+
Suggested fix: Update section to reference unified-parser.ts, remove legacy parser description
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### Example: New module with no documentation
|
|
160
|
+
|
|
161
|
+
**Drift finding:**
|
|
162
|
+
|
|
163
|
+
```
|
|
164
|
+
GAP: Undocumented module
|
|
165
|
+
File: src/services/notification-service.ts
|
|
166
|
+
Created: commit h7i8j9k (3 weeks ago)
|
|
167
|
+
Public exports: NotificationService, NotificationType, sendNotification
|
|
168
|
+
Imported by: 4 modules
|
|
169
|
+
Documentation references: 0
|
|
170
|
+
Priority: High
|
|
171
|
+
Suggested fix: Add AGENTS.md section describing purpose, constraints, and public API
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
## Escalation
|
|
175
|
+
|
|
176
|
+
- **When drift is extensive (>30 findings):** Do not try to fix everything. Focus on Critical and High priority items. Create a tracking issue for the remaining items and schedule them across sprints.
|
|
177
|
+
- **When you cannot determine the correct replacement text:** The code change may have been complex. Check the commit message and PR description for context. If still unclear, flag the finding for the original author to resolve.
|
|
178
|
+
- **When documentation is in a format you cannot parse:** Some docs may be in wiki pages, Confluence, or other external systems. Report the finding with a link and flag it for manual review.
|
|
179
|
+
- **When drift reveals a deeper problem (code changed but nobody knew):** This suggests a process gap. Recommend adding `harness check-docs` to the CI pipeline or pre-merge hooks to catch drift at the source.
|