awesome-slash 2.4.2
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/.claude-plugin/marketplace.json +54 -0
- package/.claude-plugin/plugin.json +11 -0
- package/.mcp.json +8 -0
- package/CHANGELOG.md +261 -0
- package/LICENSE +21 -0
- package/README.md +363 -0
- package/SECURITY.md +101 -0
- package/adapters/README.md +256 -0
- package/adapters/codex/README.md +272 -0
- package/adapters/codex/install.sh +179 -0
- package/adapters/opencode/README.md +301 -0
- package/adapters/opencode/install.sh +223 -0
- package/lib/patterns/review-patterns.js +511 -0
- package/lib/patterns/slop-patterns.js +647 -0
- package/lib/platform/detect-platform.js +535 -0
- package/lib/platform/verify-tools.js +235 -0
- package/lib/state/workflow-state.js +635 -0
- package/lib/state/workflow-state.schema.json +282 -0
- package/lib/utils/context-optimizer.js +227 -0
- package/mcp-server/index.js +303 -0
- package/mcp-server/package.json +23 -0
- package/package.json +63 -0
- package/plugins/deslop-around/.claude-plugin/plugin.json +20 -0
- package/plugins/deslop-around/commands/deslop-around.md +220 -0
- package/plugins/deslop-around/lib/patterns/review-patterns.js +511 -0
- package/plugins/deslop-around/lib/patterns/slop-patterns.js +641 -0
- package/plugins/deslop-around/lib/platform/detect-platform.js +514 -0
- package/plugins/deslop-around/lib/platform/verify-tools.js +235 -0
- package/plugins/deslop-around/lib/state/workflow-state.js +635 -0
- package/plugins/deslop-around/lib/state/workflow-state.schema.json +282 -0
- package/plugins/deslop-around/lib/utils/context-optimizer.js +222 -0
- package/plugins/next-task/.claude-plugin/plugin.json +24 -0
- package/plugins/next-task/agents/ci-fixer.md +236 -0
- package/plugins/next-task/agents/ci-monitor.md +291 -0
- package/plugins/next-task/agents/delivery-validator.md +451 -0
- package/plugins/next-task/agents/deslop-work.md +272 -0
- package/plugins/next-task/agents/docs-updater.md +506 -0
- package/plugins/next-task/agents/exploration-agent.md +277 -0
- package/plugins/next-task/agents/implementation-agent.md +427 -0
- package/plugins/next-task/agents/planning-agent.md +236 -0
- package/plugins/next-task/agents/policy-selector.md +248 -0
- package/plugins/next-task/agents/review-orchestrator.md +521 -0
- package/plugins/next-task/agents/simple-fixer.md +136 -0
- package/plugins/next-task/agents/task-discoverer.md +357 -0
- package/plugins/next-task/agents/test-coverage-checker.md +447 -0
- package/plugins/next-task/agents/worktree-manager.md +419 -0
- package/plugins/next-task/commands/delivery-approval.md +331 -0
- package/plugins/next-task/commands/next-task.md +627 -0
- package/plugins/next-task/commands/update-docs-around.md +418 -0
- package/plugins/next-task/hooks/hooks.json +14 -0
- package/plugins/next-task/lib/patterns/review-patterns.js +511 -0
- package/plugins/next-task/lib/patterns/slop-patterns.js +641 -0
- package/plugins/next-task/lib/platform/detect-platform.js +514 -0
- package/plugins/next-task/lib/platform/verify-tools.js +235 -0
- package/plugins/next-task/lib/state/tasks-registry.schema.json +85 -0
- package/plugins/next-task/lib/state/workflow-state.js +635 -0
- package/plugins/next-task/lib/state/workflow-state.schema.json +282 -0
- package/plugins/next-task/lib/state/worktree-status.schema.json +219 -0
- package/plugins/next-task/lib/utils/context-optimizer.js +222 -0
- package/plugins/project-review/.claude-plugin/plugin.json +20 -0
- package/plugins/project-review/commands/project-review-agents.md +286 -0
- package/plugins/project-review/commands/project-review-github.md +142 -0
- package/plugins/project-review/commands/project-review.md +273 -0
- package/plugins/project-review/lib/patterns/review-patterns.js +511 -0
- package/plugins/project-review/lib/patterns/slop-patterns.js +641 -0
- package/plugins/project-review/lib/platform/detect-platform.js +514 -0
- package/plugins/project-review/lib/platform/verify-tools.js +235 -0
- package/plugins/project-review/lib/state/workflow-state.js +635 -0
- package/plugins/project-review/lib/state/workflow-state.schema.json +282 -0
- package/plugins/project-review/lib/utils/context-optimizer.js +222 -0
- package/plugins/reality-check/.claude-plugin/plugin.json +23 -0
- package/plugins/reality-check/README.md +156 -0
- package/plugins/reality-check/agents/code-explorer.md +353 -0
- package/plugins/reality-check/agents/doc-analyzer.md +337 -0
- package/plugins/reality-check/agents/issue-scanner.md +231 -0
- package/plugins/reality-check/agents/plan-synthesizer.md +479 -0
- package/plugins/reality-check/commands/scan.md +242 -0
- package/plugins/reality-check/commands/set.md +203 -0
- package/plugins/reality-check/lib/state/reality-check-state.js +509 -0
- package/plugins/reality-check/skills/reality-analysis/SKILL.md +317 -0
- package/plugins/ship/.claude-plugin/plugin.json +21 -0
- package/plugins/ship/commands/ship-ci-review-loop.md +443 -0
- package/plugins/ship/commands/ship-deployment.md +330 -0
- package/plugins/ship/commands/ship-error-handling.md +254 -0
- package/plugins/ship/commands/ship.md +370 -0
- package/plugins/ship/lib/patterns/review-patterns.js +511 -0
- package/plugins/ship/lib/patterns/slop-patterns.js +641 -0
- package/plugins/ship/lib/platform/detect-platform.js +514 -0
- package/plugins/ship/lib/platform/verify-tools.js +235 -0
- package/plugins/ship/lib/state/workflow-state.js +635 -0
- package/plugins/ship/lib/state/workflow-state.schema.json +282 -0
- package/plugins/ship/lib/utils/context-optimizer.js +222 -0
- package/scripts/install/claude.sh +50 -0
- package/scripts/install/codex.sh +181 -0
- package/scripts/install/opencode.sh +211 -0
|
@@ -0,0 +1,353 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: code-explorer
|
|
3
|
+
description: Deep codebase exploration to understand actual implementation state. Use this agent as part of the reality-check parallel scan to gather code-based context.
|
|
4
|
+
tools: Read, Glob, Grep, Bash(git:*)
|
|
5
|
+
model: sonnet
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Code Explorer Agent
|
|
9
|
+
|
|
10
|
+
You perform deep codebase exploration to understand the actual implementation state, architecture, and what features are truly implemented.
|
|
11
|
+
|
|
12
|
+
## Phase 1: Load Configuration
|
|
13
|
+
|
|
14
|
+
```javascript
|
|
15
|
+
const rcState = require('${CLAUDE_PLUGIN_ROOT}/lib/state/reality-check-state.js');
|
|
16
|
+
const settings = rcState.readSettings();
|
|
17
|
+
|
|
18
|
+
console.log("Starting codebase exploration...");
|
|
19
|
+
console.log(`Exclusions: ${settings.exclusions.paths.join(', ')}`);
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Phase 2: Map Project Structure
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
# Get directory structure (excluding common non-source dirs)
|
|
26
|
+
find . -type d -not -path '*/node_modules/*' -not -path '*/.git/*' -not -path '*/dist/*' -not -path '*/build/*' -not -path '*/.next/*' | head -50
|
|
27
|
+
|
|
28
|
+
# Count files by type
|
|
29
|
+
find . -type f -name "*.ts" -not -path '*/node_modules/*' | wc -l
|
|
30
|
+
find . -type f -name "*.js" -not -path '*/node_modules/*' | wc -l
|
|
31
|
+
find . -type f -name "*.tsx" -not -path '*/node_modules/*' | wc -l
|
|
32
|
+
find . -type f -name "*.py" -not -path '*/node_modules/*' | wc -l
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Phase 3: Identify Entry Points
|
|
36
|
+
|
|
37
|
+
```javascript
|
|
38
|
+
// Find main entry points
|
|
39
|
+
const entryPoints = await Glob({ pattern: '{src,lib,app}/index.{ts,js,tsx}' });
|
|
40
|
+
const mainFiles = await Glob({ pattern: '{main,app,server,index}.{ts,js}' });
|
|
41
|
+
|
|
42
|
+
// Read package.json for entry points
|
|
43
|
+
const packageJson = await Read({ file_path: 'package.json' });
|
|
44
|
+
const pkg = JSON.parse(packageJson);
|
|
45
|
+
|
|
46
|
+
const definedEntries = {
|
|
47
|
+
main: pkg.main,
|
|
48
|
+
module: pkg.module,
|
|
49
|
+
exports: pkg.exports,
|
|
50
|
+
bin: pkg.bin,
|
|
51
|
+
scripts: Object.keys(pkg.scripts || {})
|
|
52
|
+
};
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Phase 4: Extract Exports and Public API
|
|
56
|
+
|
|
57
|
+
```javascript
|
|
58
|
+
// Find all exports
|
|
59
|
+
const exportPatterns = [
|
|
60
|
+
'export default',
|
|
61
|
+
'export const',
|
|
62
|
+
'export function',
|
|
63
|
+
'export class',
|
|
64
|
+
'export interface',
|
|
65
|
+
'export type',
|
|
66
|
+
'module.exports'
|
|
67
|
+
];
|
|
68
|
+
|
|
69
|
+
// Search for exports in source files
|
|
70
|
+
const exports = await Grep({
|
|
71
|
+
pattern: 'export (default|const|function|class|interface|type)',
|
|
72
|
+
glob: '*.{ts,tsx,js}',
|
|
73
|
+
path: 'src/'
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
function extractPublicApi(files) {
|
|
77
|
+
const api = {};
|
|
78
|
+
|
|
79
|
+
for (const file of files) {
|
|
80
|
+
const exports = file.content.match(/export\s+(default\s+)?(const|function|class|interface|type)\s+(\w+)/g) || [];
|
|
81
|
+
api[file.path] = exports.map(e => {
|
|
82
|
+
const match = e.match(/export\s+(default\s+)?(const|function|class|interface|type)\s+(\w+)/);
|
|
83
|
+
return {
|
|
84
|
+
type: match[2],
|
|
85
|
+
name: match[3],
|
|
86
|
+
isDefault: !!match[1]
|
|
87
|
+
};
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return api;
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Phase 5: Analyze Implementation Patterns
|
|
96
|
+
|
|
97
|
+
```javascript
|
|
98
|
+
// Detect common patterns
|
|
99
|
+
const patterns = {
|
|
100
|
+
hasTests: false,
|
|
101
|
+
testFramework: null,
|
|
102
|
+
hasTypeScript: false,
|
|
103
|
+
framework: null,
|
|
104
|
+
stateManagement: null,
|
|
105
|
+
apiStyle: null
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
// Check for tests
|
|
109
|
+
const testFiles = await Glob({ pattern: '**/*.{test,spec}.{ts,js,tsx}' });
|
|
110
|
+
patterns.hasTests = testFiles.length > 0;
|
|
111
|
+
|
|
112
|
+
// Detect test framework
|
|
113
|
+
if (await fileExists('jest.config.js') || await fileExists('jest.config.ts')) {
|
|
114
|
+
patterns.testFramework = 'jest';
|
|
115
|
+
} else if (await fileExists('vitest.config.ts')) {
|
|
116
|
+
patterns.testFramework = 'vitest';
|
|
117
|
+
} else if (await fileExists('mocha.opts') || await fileExists('.mocharc.json')) {
|
|
118
|
+
patterns.testFramework = 'mocha';
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Detect framework
|
|
122
|
+
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
123
|
+
if (deps['next']) patterns.framework = 'next.js';
|
|
124
|
+
else if (deps['react']) patterns.framework = 'react';
|
|
125
|
+
else if (deps['vue']) patterns.framework = 'vue';
|
|
126
|
+
else if (deps['express']) patterns.framework = 'express';
|
|
127
|
+
else if (deps['fastify']) patterns.framework = 'fastify';
|
|
128
|
+
|
|
129
|
+
// Detect state management
|
|
130
|
+
if (deps['redux'] || deps['@reduxjs/toolkit']) patterns.stateManagement = 'redux';
|
|
131
|
+
else if (deps['zustand']) patterns.stateManagement = 'zustand';
|
|
132
|
+
else if (deps['jotai']) patterns.stateManagement = 'jotai';
|
|
133
|
+
else if (deps['mobx']) patterns.stateManagement = 'mobx';
|
|
134
|
+
|
|
135
|
+
// Check TypeScript
|
|
136
|
+
patterns.hasTypeScript = await fileExists('tsconfig.json');
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## Phase 6: Find Implemented Features
|
|
140
|
+
|
|
141
|
+
```javascript
|
|
142
|
+
// Look for feature indicators in code
|
|
143
|
+
async function findImplementedFeatures() {
|
|
144
|
+
const features = [];
|
|
145
|
+
|
|
146
|
+
// API endpoints
|
|
147
|
+
const routeFiles = await Glob({ pattern: '**/{routes,api,pages/api}/**/*.{ts,js}' });
|
|
148
|
+
const endpoints = [];
|
|
149
|
+
for (const file of routeFiles) {
|
|
150
|
+
const content = await Read({ file_path: file });
|
|
151
|
+
const methods = content.match(/(get|post|put|delete|patch)\s*\(/gi) || [];
|
|
152
|
+
if (methods.length > 0) {
|
|
153
|
+
endpoints.push({ file, methods: methods.length });
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
if (endpoints.length > 0) {
|
|
157
|
+
features.push({ type: 'api-endpoints', count: endpoints.length, details: endpoints });
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Database models
|
|
161
|
+
const modelFiles = await Glob({ pattern: '**/{models,entities,schemas}/**/*.{ts,js}' });
|
|
162
|
+
if (modelFiles.length > 0) {
|
|
163
|
+
features.push({ type: 'database-models', count: modelFiles.length, files: modelFiles });
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// UI Components
|
|
167
|
+
const componentFiles = await Glob({ pattern: '**/{components,views,pages}/**/*.{tsx,jsx,vue}' });
|
|
168
|
+
if (componentFiles.length > 0) {
|
|
169
|
+
features.push({ type: 'ui-components', count: componentFiles.length });
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Authentication
|
|
173
|
+
const authFiles = await Grep({ pattern: 'auth|login|session|jwt|oauth', glob: '*.{ts,js,tsx}' });
|
|
174
|
+
if (authFiles.length > 0) {
|
|
175
|
+
features.push({ type: 'authentication', implemented: true, files: authFiles.slice(0, 5) });
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// Caching
|
|
179
|
+
const cacheFiles = await Grep({ pattern: 'cache|redis|memcache', glob: '*.{ts,js}' });
|
|
180
|
+
if (cacheFiles.length > 0) {
|
|
181
|
+
features.push({ type: 'caching', implemented: true });
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
return features;
|
|
185
|
+
}
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## Phase 7: Analyze Code Health
|
|
189
|
+
|
|
190
|
+
```javascript
|
|
191
|
+
// Check for code health indicators
|
|
192
|
+
async function analyzeCodeHealth() {
|
|
193
|
+
const health = {
|
|
194
|
+
hasLinting: await fileExists('.eslintrc') || await fileExists('.eslintrc.js') || await fileExists('eslint.config.js'),
|
|
195
|
+
hasFormatting: await fileExists('.prettierrc') || await fileExists('prettier.config.js'),
|
|
196
|
+
hasCI: await fileExists('.github/workflows') || await fileExists('.gitlab-ci.yml'),
|
|
197
|
+
hasDockerfile: await fileExists('Dockerfile'),
|
|
198
|
+
hasEnvExample: await fileExists('.env.example'),
|
|
199
|
+
todoCount: 0,
|
|
200
|
+
fixmeCount: 0
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
// Count TODOs and FIXMEs
|
|
204
|
+
const todos = await Grep({ pattern: 'TODO|FIXME|HACK|XXX', glob: '*.{ts,js,tsx,jsx}' });
|
|
205
|
+
health.todoCount = todos.filter(t => t.includes('TODO')).length;
|
|
206
|
+
health.fixmeCount = todos.filter(t => t.includes('FIXME')).length;
|
|
207
|
+
|
|
208
|
+
return health;
|
|
209
|
+
}
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
## Phase 8: Check Git Activity
|
|
213
|
+
|
|
214
|
+
```bash
|
|
215
|
+
# Recent activity by directory
|
|
216
|
+
git log --oneline -30 --name-only | grep -E '^\w' | sort | uniq -c | sort -rn | head -20
|
|
217
|
+
|
|
218
|
+
# Most modified files
|
|
219
|
+
git log --oneline -100 --name-only | grep -E '\.(ts|js|tsx|jsx)$' | sort | uniq -c | sort -rn | head -15
|
|
220
|
+
|
|
221
|
+
# Contributors
|
|
222
|
+
git shortlog -sn --all | head -10
|
|
223
|
+
|
|
224
|
+
# Recent commits summary
|
|
225
|
+
git log --oneline -20
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
## Phase 9: Identify Code Gaps
|
|
229
|
+
|
|
230
|
+
```javascript
|
|
231
|
+
function identifyCodeGaps(analysis) {
|
|
232
|
+
const gaps = [];
|
|
233
|
+
|
|
234
|
+
// No tests
|
|
235
|
+
if (!analysis.patterns.hasTests) {
|
|
236
|
+
gaps.push({
|
|
237
|
+
type: 'missing-tests',
|
|
238
|
+
severity: 'high',
|
|
239
|
+
description: 'No test files found'
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// Low test coverage indicators
|
|
244
|
+
if (analysis.patterns.hasTests && analysis.testFiles.length < analysis.sourceFiles.length * 0.3) {
|
|
245
|
+
gaps.push({
|
|
246
|
+
type: 'low-test-coverage',
|
|
247
|
+
severity: 'medium',
|
|
248
|
+
description: `Only ${analysis.testFiles.length} test files for ${analysis.sourceFiles.length} source files`
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// No TypeScript types
|
|
253
|
+
if (!analysis.patterns.hasTypeScript && analysis.sourceFiles.some(f => f.endsWith('.js'))) {
|
|
254
|
+
gaps.push({
|
|
255
|
+
type: 'no-types',
|
|
256
|
+
severity: 'low',
|
|
257
|
+
description: 'JavaScript project without TypeScript'
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// Many TODOs
|
|
262
|
+
if (analysis.health.todoCount > 20) {
|
|
263
|
+
gaps.push({
|
|
264
|
+
type: 'many-todos',
|
|
265
|
+
severity: 'medium',
|
|
266
|
+
description: `${analysis.health.todoCount} TODO comments in codebase`
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// No CI
|
|
271
|
+
if (!analysis.health.hasCI) {
|
|
272
|
+
gaps.push({
|
|
273
|
+
type: 'no-ci',
|
|
274
|
+
severity: 'medium',
|
|
275
|
+
description: 'No CI/CD configuration found'
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
return gaps;
|
|
280
|
+
}
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
## Phase 10: Build Output
|
|
284
|
+
|
|
285
|
+
```javascript
|
|
286
|
+
const output = {
|
|
287
|
+
summary: {
|
|
288
|
+
totalSourceFiles: sourceFiles.length,
|
|
289
|
+
totalTestFiles: testFiles.length,
|
|
290
|
+
primaryLanguage: detectPrimaryLanguage(sourceFiles),
|
|
291
|
+
framework: patterns.framework
|
|
292
|
+
},
|
|
293
|
+
structure: {
|
|
294
|
+
directories: directoryStructure,
|
|
295
|
+
entryPoints: definedEntries
|
|
296
|
+
},
|
|
297
|
+
implementedFeatures: features,
|
|
298
|
+
publicApi: publicApi,
|
|
299
|
+
patterns: patterns,
|
|
300
|
+
health: healthAnalysis,
|
|
301
|
+
gaps: codeGaps,
|
|
302
|
+
recentActivity: {
|
|
303
|
+
hotspots: mostModifiedFiles,
|
|
304
|
+
recentCommits: recentCommits
|
|
305
|
+
}
|
|
306
|
+
};
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
## Phase 11: Update State
|
|
310
|
+
|
|
311
|
+
```javascript
|
|
312
|
+
rcState.updateAgentResult('codeExplorer', output);
|
|
313
|
+
|
|
314
|
+
console.log(`
|
|
315
|
+
## Code Exploration Complete
|
|
316
|
+
|
|
317
|
+
**Source Files**: ${output.summary.totalSourceFiles}
|
|
318
|
+
**Test Files**: ${output.summary.totalTestFiles}
|
|
319
|
+
**Framework**: ${output.summary.framework || 'None detected'}
|
|
320
|
+
**Language**: ${output.summary.primaryLanguage}
|
|
321
|
+
|
|
322
|
+
### Implemented Features
|
|
323
|
+
${output.implementedFeatures.map(f => `- ${f.type}: ${f.count || 'Yes'}`).join('\n')}
|
|
324
|
+
|
|
325
|
+
### Code Health
|
|
326
|
+
- Linting: ${output.health.hasLinting ? '✓' : '✗'}
|
|
327
|
+
- CI/CD: ${output.health.hasCI ? '✓' : '✗'}
|
|
328
|
+
- Tests: ${output.patterns.hasTests ? '✓' : '✗'}
|
|
329
|
+
- TODOs: ${output.health.todoCount}
|
|
330
|
+
|
|
331
|
+
### Gaps Found: ${output.gaps.length}
|
|
332
|
+
`);
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
## Output Format
|
|
336
|
+
|
|
337
|
+
Return structured JSON with:
|
|
338
|
+
- Summary of codebase
|
|
339
|
+
- Directory structure
|
|
340
|
+
- Implemented features
|
|
341
|
+
- Public API surface
|
|
342
|
+
- Detected patterns
|
|
343
|
+
- Code health metrics
|
|
344
|
+
- Identified gaps
|
|
345
|
+
- Recent activity hotspots
|
|
346
|
+
|
|
347
|
+
## Model Choice: Sonnet
|
|
348
|
+
|
|
349
|
+
This agent uses **sonnet** because:
|
|
350
|
+
- File pattern matching and analysis
|
|
351
|
+
- Structured data extraction
|
|
352
|
+
- No complex reasoning required
|
|
353
|
+
- Fast parallel execution needed
|
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: doc-analyzer
|
|
3
|
+
description: Analyze documentation files to understand documented plans, roadmaps, and architecture. Use this agent as part of the reality-check parallel scan to gather doc-based context.
|
|
4
|
+
tools: Read, Glob, Grep
|
|
5
|
+
model: sonnet
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Doc Analyzer Agent
|
|
9
|
+
|
|
10
|
+
You analyze documentation files to extract the documented project state, plans, roadmaps, and architecture descriptions.
|
|
11
|
+
|
|
12
|
+
## Phase 1: Load Configuration
|
|
13
|
+
|
|
14
|
+
```javascript
|
|
15
|
+
const rcState = require('${CLAUDE_PLUGIN_ROOT}/lib/state/reality-check-state.js');
|
|
16
|
+
const settings = rcState.readSettings();
|
|
17
|
+
|
|
18
|
+
console.log("Starting documentation analysis...");
|
|
19
|
+
console.log(`Doc paths: ${settings.sources.docs_paths.join(', ')}`);
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Phase 2: Discover Documentation Files
|
|
23
|
+
|
|
24
|
+
```javascript
|
|
25
|
+
// Find all documentation files
|
|
26
|
+
const docPatterns = [
|
|
27
|
+
'README.md',
|
|
28
|
+
'CLAUDE.md',
|
|
29
|
+
'PLAN.md',
|
|
30
|
+
'TODO.md',
|
|
31
|
+
'ROADMAP.md',
|
|
32
|
+
'ARCHITECTURE.md',
|
|
33
|
+
'CONTRIBUTING.md',
|
|
34
|
+
'CHANGELOG.md',
|
|
35
|
+
'docs/**/*.md',
|
|
36
|
+
'.github/**/*.md'
|
|
37
|
+
];
|
|
38
|
+
|
|
39
|
+
// Use Glob to find files
|
|
40
|
+
const docFiles = await Glob({ pattern: '**/*.md' });
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Phase 3: Analyze Key Documents
|
|
44
|
+
|
|
45
|
+
### README Analysis
|
|
46
|
+
|
|
47
|
+
```javascript
|
|
48
|
+
async function analyzeReadme(content) {
|
|
49
|
+
return {
|
|
50
|
+
hasDescription: /^#\s+.+/m.test(content),
|
|
51
|
+
hasInstallation: /install|getting started|setup/i.test(content),
|
|
52
|
+
hasUsage: /usage|how to use|example/i.test(content),
|
|
53
|
+
hasApi: /api|reference|methods/i.test(content),
|
|
54
|
+
features: extractFeatureList(content),
|
|
55
|
+
badges: extractBadges(content),
|
|
56
|
+
lastSection: getLastSection(content)
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function extractFeatureList(content) {
|
|
61
|
+
const featurePatterns = [
|
|
62
|
+
/## Features?\n([\s\S]*?)(?=\n##|$)/i,
|
|
63
|
+
/### Features?\n([\s\S]*?)(?=\n###|$)/i,
|
|
64
|
+
/\*\*Features?\*\*:?\n([\s\S]*?)(?=\n\*\*|$)/i
|
|
65
|
+
];
|
|
66
|
+
|
|
67
|
+
for (const pattern of featurePatterns) {
|
|
68
|
+
const match = content.match(pattern);
|
|
69
|
+
if (match) {
|
|
70
|
+
const items = match[1].match(/^[-*]\s+.+$/gm) || [];
|
|
71
|
+
return items.map(item => item.replace(/^[-*]\s+/, '').trim());
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return [];
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### PLAN/ROADMAP Analysis
|
|
79
|
+
|
|
80
|
+
```javascript
|
|
81
|
+
async function analyzePlan(content, filename) {
|
|
82
|
+
const sections = {
|
|
83
|
+
completed: [],
|
|
84
|
+
inProgress: [],
|
|
85
|
+
planned: [],
|
|
86
|
+
backlog: []
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
// Look for checkbox items
|
|
90
|
+
const checkboxes = content.match(/^[-*]\s+\[([ xX])\]\s+.+$/gm) || [];
|
|
91
|
+
for (const item of checkboxes) {
|
|
92
|
+
const isChecked = /\[x\]/i.test(item);
|
|
93
|
+
const text = item.replace(/^[-*]\s+\[[ xX]\]\s+/, '').trim();
|
|
94
|
+
|
|
95
|
+
if (isChecked) {
|
|
96
|
+
sections.completed.push(text);
|
|
97
|
+
} else {
|
|
98
|
+
sections.planned.push(text);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Look for phase/milestone sections
|
|
103
|
+
const phaseMatches = content.match(/##\s+(Phase|Milestone|Sprint|v?\d+\.\d+)[^\n]*/gi) || [];
|
|
104
|
+
const phases = phaseMatches.map(m => m.replace(/^##\s+/, ''));
|
|
105
|
+
|
|
106
|
+
// Look for status indicators
|
|
107
|
+
const statusPatterns = {
|
|
108
|
+
inProgress: /\b(in progress|wip|current|active)\b/i,
|
|
109
|
+
completed: /\b(done|completed|finished|shipped)\b/i,
|
|
110
|
+
planned: /\b(planned|upcoming|next|future)\b/i
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
return {
|
|
114
|
+
filename,
|
|
115
|
+
checkboxTotal: checkboxes.length,
|
|
116
|
+
completedCount: sections.completed.length,
|
|
117
|
+
plannedCount: sections.planned.length,
|
|
118
|
+
completionRate: checkboxes.length > 0
|
|
119
|
+
? Math.round((sections.completed.length / checkboxes.length) * 100)
|
|
120
|
+
: null,
|
|
121
|
+
phases,
|
|
122
|
+
sections,
|
|
123
|
+
lastModified: null // Will be filled from git
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### CLAUDE.md Analysis
|
|
129
|
+
|
|
130
|
+
```javascript
|
|
131
|
+
async function analyzeClaudeMd(content) {
|
|
132
|
+
return {
|
|
133
|
+
hasProjectContext: /project|overview|about/i.test(content),
|
|
134
|
+
hasCodeStyle: /style|convention|format/i.test(content),
|
|
135
|
+
hasArchitecture: /architecture|structure|pattern/i.test(content),
|
|
136
|
+
hasTesting: /test|spec|coverage/i.test(content),
|
|
137
|
+
hasDeployment: /deploy|release|production/i.test(content),
|
|
138
|
+
mentionedFiles: extractFilePaths(content),
|
|
139
|
+
mentionedCommands: extractCommands(content),
|
|
140
|
+
warnings: extractWarnings(content)
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function extractFilePaths(content) {
|
|
145
|
+
const paths = content.match(/`[^`]*\.(ts|js|json|md|yaml|yml|sh)`/g) || [];
|
|
146
|
+
return [...new Set(paths.map(p => p.replace(/`/g, '')))];
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function extractCommands(content) {
|
|
150
|
+
const commands = content.match(/```(?:bash|sh)?\n([^`]+)```/g) || [];
|
|
151
|
+
return commands.map(c => c.replace(/```(?:bash|sh)?\n|```/g, '').trim());
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function extractWarnings(content) {
|
|
155
|
+
const warnings = [];
|
|
156
|
+
const warningPatterns = [
|
|
157
|
+
/⚠️[^\n]+/g,
|
|
158
|
+
/\*\*Warning\*\*:?[^\n]+/gi,
|
|
159
|
+
/\*\*Important\*\*:?[^\n]+/gi,
|
|
160
|
+
/\*\*Note\*\*:?[^\n]+/gi
|
|
161
|
+
];
|
|
162
|
+
|
|
163
|
+
for (const pattern of warningPatterns) {
|
|
164
|
+
const matches = content.match(pattern) || [];
|
|
165
|
+
warnings.push(...matches);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
return warnings;
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
## Phase 4: Check Document Freshness
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
# Get last modified dates for docs
|
|
176
|
+
git log -1 --format="%ai" -- README.md
|
|
177
|
+
git log -1 --format="%ai" -- CLAUDE.md
|
|
178
|
+
git log -1 --format="%ai" -- docs/
|
|
179
|
+
|
|
180
|
+
# Check if docs were updated with recent code changes
|
|
181
|
+
git log --oneline -20 -- "*.md"
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## Phase 5: Identify Documentation Gaps
|
|
185
|
+
|
|
186
|
+
```javascript
|
|
187
|
+
function identifyDocGaps(analysis) {
|
|
188
|
+
const gaps = [];
|
|
189
|
+
|
|
190
|
+
// Missing essential docs
|
|
191
|
+
if (!analysis.files.readme) {
|
|
192
|
+
gaps.push({ type: 'missing', file: 'README.md', severity: 'high' });
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// Stale documentation
|
|
196
|
+
for (const [file, info] of Object.entries(analysis.files)) {
|
|
197
|
+
if (info.lastModified) {
|
|
198
|
+
const daysSinceUpdate = Math.floor(
|
|
199
|
+
(Date.now() - new Date(info.lastModified)) / (24 * 60 * 60 * 1000)
|
|
200
|
+
);
|
|
201
|
+
if (daysSinceUpdate > 180) {
|
|
202
|
+
gaps.push({
|
|
203
|
+
type: 'stale',
|
|
204
|
+
file,
|
|
205
|
+
severity: 'medium',
|
|
206
|
+
daysSinceUpdate
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// Incomplete plan items
|
|
213
|
+
if (analysis.plan && analysis.plan.plannedCount > 10 && analysis.plan.completionRate < 20) {
|
|
214
|
+
gaps.push({
|
|
215
|
+
type: 'low-progress',
|
|
216
|
+
file: 'PLAN.md',
|
|
217
|
+
severity: 'high',
|
|
218
|
+
description: `Only ${analysis.plan.completionRate}% completion on ${analysis.plan.checkboxTotal} items`
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// Missing sections in README
|
|
223
|
+
if (analysis.readme && !analysis.readme.hasUsage) {
|
|
224
|
+
gaps.push({ type: 'incomplete', file: 'README.md', missing: 'usage section', severity: 'low' });
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
return gaps;
|
|
228
|
+
}
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
## Phase 6: Extract Documented Plans
|
|
232
|
+
|
|
233
|
+
```javascript
|
|
234
|
+
function extractPlannedWork(analysis) {
|
|
235
|
+
const plannedWork = [];
|
|
236
|
+
|
|
237
|
+
// From PLAN.md checkboxes
|
|
238
|
+
if (analysis.plan) {
|
|
239
|
+
for (const item of analysis.plan.sections.planned) {
|
|
240
|
+
plannedWork.push({
|
|
241
|
+
source: 'PLAN.md',
|
|
242
|
+
item,
|
|
243
|
+
status: 'planned'
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// From roadmap phases
|
|
249
|
+
if (analysis.roadmap) {
|
|
250
|
+
for (const phase of analysis.roadmap.phases) {
|
|
251
|
+
plannedWork.push({
|
|
252
|
+
source: 'ROADMAP.md',
|
|
253
|
+
item: phase,
|
|
254
|
+
status: 'phase'
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// From README features that mention "coming soon" or "planned"
|
|
260
|
+
if (analysis.readme) {
|
|
261
|
+
for (const feature of analysis.readme.features) {
|
|
262
|
+
if (/coming soon|planned|future|wip/i.test(feature)) {
|
|
263
|
+
plannedWork.push({
|
|
264
|
+
source: 'README.md',
|
|
265
|
+
item: feature,
|
|
266
|
+
status: 'mentioned'
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
return plannedWork;
|
|
273
|
+
}
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
## Phase 7: Build Output
|
|
277
|
+
|
|
278
|
+
```javascript
|
|
279
|
+
const output = {
|
|
280
|
+
summary: {
|
|
281
|
+
totalDocsFound: docFiles.length,
|
|
282
|
+
keyDocsPresent: {
|
|
283
|
+
readme: !!analysis.readme,
|
|
284
|
+
claudeMd: !!analysis.claudeMd,
|
|
285
|
+
plan: !!analysis.plan,
|
|
286
|
+
roadmap: !!analysis.roadmap,
|
|
287
|
+
changelog: !!analysis.changelog
|
|
288
|
+
}
|
|
289
|
+
},
|
|
290
|
+
analysis: {
|
|
291
|
+
readme: analysis.readme,
|
|
292
|
+
claudeMd: analysis.claudeMd,
|
|
293
|
+
plan: analysis.plan
|
|
294
|
+
},
|
|
295
|
+
plannedWork: extractPlannedWork(analysis),
|
|
296
|
+
documentationGaps: identifyDocGaps(analysis),
|
|
297
|
+
mentionedFiles: allMentionedFiles,
|
|
298
|
+
documentedFeatures: analysis.readme?.features || [],
|
|
299
|
+
staleDocs: staleDocs
|
|
300
|
+
};
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
## Phase 8: Update State
|
|
304
|
+
|
|
305
|
+
```javascript
|
|
306
|
+
rcState.updateAgentResult('docAnalyzer', output);
|
|
307
|
+
|
|
308
|
+
console.log(`
|
|
309
|
+
## Documentation Analysis Complete
|
|
310
|
+
|
|
311
|
+
**Docs Found**: ${output.summary.totalDocsFound}
|
|
312
|
+
**Key Docs**: README(${output.summary.keyDocsPresent.readme ? '✓' : '✗'}) CLAUDE.md(${output.summary.keyDocsPresent.claudeMd ? '✓' : '✗'}) PLAN(${output.summary.keyDocsPresent.plan ? '✓' : '✗'})
|
|
313
|
+
**Planned Items**: ${output.plannedWork.length}
|
|
314
|
+
**Documentation Gaps**: ${output.documentationGaps.length}
|
|
315
|
+
|
|
316
|
+
### Plan Progress
|
|
317
|
+
${output.analysis.plan ? `${output.analysis.plan.completionRate}% complete (${output.analysis.plan.completedCount}/${output.analysis.plan.checkboxTotal})` : 'No plan file found'}
|
|
318
|
+
`);
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
## Output Format
|
|
322
|
+
|
|
323
|
+
Return structured JSON with:
|
|
324
|
+
- Summary of docs found
|
|
325
|
+
- Analysis of each key document
|
|
326
|
+
- Extracted planned work items
|
|
327
|
+
- Documentation gaps
|
|
328
|
+
- Documented features list
|
|
329
|
+
- Stale documentation list
|
|
330
|
+
|
|
331
|
+
## Model Choice: Sonnet
|
|
332
|
+
|
|
333
|
+
This agent uses **sonnet** because:
|
|
334
|
+
- Text extraction and pattern matching
|
|
335
|
+
- Document structure analysis
|
|
336
|
+
- No complex reasoning needed
|
|
337
|
+
- Fast parallel execution required
|