5-phase-workflow 1.0.0

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.
Files changed (33) hide show
  1. package/README.md +332 -0
  2. package/bin/install.js +408 -0
  3. package/docs/workflow-guide.md +1024 -0
  4. package/package.json +34 -0
  5. package/src/agents/integration-agent.md +219 -0
  6. package/src/agents/review-processor.md +160 -0
  7. package/src/agents/step-executor.md +108 -0
  8. package/src/agents/step-fixer.md +132 -0
  9. package/src/agents/step-verifier.md +125 -0
  10. package/src/agents/verification-agent.md +411 -0
  11. package/src/commands/5/configure.md +309 -0
  12. package/src/commands/5/discuss-feature.md +393 -0
  13. package/src/commands/5/implement-feature.md +502 -0
  14. package/src/commands/5/plan-feature.md +285 -0
  15. package/src/commands/5/plan-implementation.md +376 -0
  16. package/src/commands/5/quick-implement.md +263 -0
  17. package/src/commands/5/review-code.md +583 -0
  18. package/src/commands/5/verify-implementation.md +277 -0
  19. package/src/hooks/statusline.js +53 -0
  20. package/src/settings.json +6 -0
  21. package/src/skills/build-project/SKILL.md +277 -0
  22. package/src/skills/configure-project/SKILL.md +355 -0
  23. package/src/skills/generate-readme/EXAMPLES.md +168 -0
  24. package/src/skills/generate-readme/SKILL.md +123 -0
  25. package/src/skills/generate-readme/TEMPLATE.md +141 -0
  26. package/src/skills/run-tests/SKILL.md +365 -0
  27. package/src/templates/ARCHITECTURE.md +64 -0
  28. package/src/templates/CONCERNS.md +75 -0
  29. package/src/templates/CONVENTIONS.md +75 -0
  30. package/src/templates/INTEGRATIONS.md +65 -0
  31. package/src/templates/STACK.md +60 -0
  32. package/src/templates/STRUCTURE.md +60 -0
  33. package/src/templates/TESTING.md +107 -0
package/bin/install.js ADDED
@@ -0,0 +1,408 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+ const readline = require('readline');
6
+
7
+ // ANSI colors for terminal output
8
+ const colors = {
9
+ reset: '\x1b[0m',
10
+ bright: '\x1b[1m',
11
+ green: '\x1b[32m',
12
+ yellow: '\x1b[33m',
13
+ blue: '\x1b[34m',
14
+ red: '\x1b[31m'
15
+ };
16
+
17
+ const log = {
18
+ info: (msg) => console.log(`${colors.blue}ℹ${colors.reset} ${msg}`),
19
+ success: (msg) => console.log(`${colors.green}✓${colors.reset} ${msg}`),
20
+ warn: (msg) => console.log(`${colors.yellow}⚠${colors.reset} ${msg}`),
21
+ error: (msg) => console.log(`${colors.red}✗${colors.reset} ${msg}`),
22
+ header: (msg) => console.log(`\n${colors.bright}${msg}${colors.reset}\n`)
23
+ };
24
+
25
+ // Parse CLI arguments
26
+ function parseArgs() {
27
+ const args = process.argv.slice(2);
28
+ const options = {
29
+ global: false,
30
+ local: false,
31
+ uninstall: false,
32
+ help: false
33
+ };
34
+
35
+ for (const arg of args) {
36
+ if (arg === '--global' || arg === '-g') options.global = true;
37
+ else if (arg === '--local' || arg === '-l') options.local = true;
38
+ else if (arg === '--uninstall' || arg === '-u') options.uninstall = true;
39
+ else if (arg === '--help' || arg === '-h') options.help = true;
40
+ }
41
+
42
+ // Default to local if neither specified
43
+ if (!options.global && !options.local && !options.uninstall) {
44
+ options.local = true;
45
+ }
46
+
47
+ return options;
48
+ }
49
+
50
+ // Show help message
51
+ function showHelp() {
52
+ console.log(`
53
+ ${colors.bright}5-Phase Workflow Installer${colors.reset}
54
+
55
+ Usage: npx 5-phase-workflow [options]
56
+
57
+ Options:
58
+ --global, -g Install to ~/.claude/ (available across all projects)
59
+ --local, -l Install to ./.claude/ (project-specific, default)
60
+ --uninstall, -u Remove installation from current directory
61
+ --help, -h Show this help message
62
+
63
+ Examples:
64
+ npx 5-phase-workflow # Install locally
65
+ npx 5-phase-workflow --global # Install globally
66
+ npx 5-phase-workflow --uninstall # Remove from current directory
67
+ `);
68
+ }
69
+
70
+ // Get installation target path
71
+ function getTargetPath(isGlobal) {
72
+ if (isGlobal) {
73
+ const homeDir = process.env.HOME || process.env.USERPROFILE;
74
+ return path.join(homeDir, '.claude');
75
+ }
76
+ return path.join(process.cwd(), '.claude');
77
+ }
78
+
79
+ // Get source path (package installation directory)
80
+ function getSourcePath() {
81
+ // When installed via npm, __dirname is <install-location>/bin
82
+ // Source files are in <install-location>/src
83
+ return path.join(__dirname, '..', 'src');
84
+ }
85
+
86
+ // Copy directory recursively
87
+ function copyDir(src, dest) {
88
+ if (!fs.existsSync(dest)) {
89
+ fs.mkdirSync(dest, { recursive: true });
90
+ }
91
+
92
+ const entries = fs.readdirSync(src, { withFileTypes: true });
93
+
94
+ for (const entry of entries) {
95
+ const srcPath = path.join(src, entry.name);
96
+ const destPath = path.join(dest, entry.name);
97
+
98
+ if (entry.isDirectory()) {
99
+ copyDir(srcPath, destPath);
100
+ } else {
101
+ fs.copyFileSync(srcPath, destPath);
102
+ }
103
+ }
104
+ }
105
+
106
+ // Remove directory recursively
107
+ function removeDir(dir) {
108
+ if (fs.existsSync(dir)) {
109
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
110
+
111
+ for (const entry of entries) {
112
+ const fullPath = path.join(dir, entry.name);
113
+
114
+ if (entry.isDirectory()) {
115
+ removeDir(fullPath);
116
+ } else {
117
+ fs.unlinkSync(fullPath);
118
+ }
119
+ }
120
+
121
+ fs.rmdirSync(dir);
122
+ }
123
+ }
124
+
125
+ // Detect project type by examining files in current directory
126
+ function detectProjectType() {
127
+ const cwd = process.cwd();
128
+
129
+ if (fs.existsSync(path.join(cwd, 'package.json'))) {
130
+ const pkg = JSON.parse(fs.readFileSync(path.join(cwd, 'package.json'), 'utf8'));
131
+ if (pkg.dependencies?.['next'] || pkg.devDependencies?.['next']) return 'nextjs';
132
+ if (pkg.dependencies?.['express'] || pkg.devDependencies?.['express']) return 'express';
133
+ if (pkg.dependencies?.['@nestjs/core']) return 'nestjs';
134
+ return 'javascript';
135
+ }
136
+
137
+ if (fs.existsSync(path.join(cwd, 'build.gradle')) || fs.existsSync(path.join(cwd, 'build.gradle.kts'))) {
138
+ return 'gradle-java';
139
+ }
140
+
141
+ if (fs.existsSync(path.join(cwd, 'pom.xml'))) {
142
+ return 'maven-java';
143
+ }
144
+
145
+ if (fs.existsSync(path.join(cwd, 'Cargo.toml'))) {
146
+ return 'rust';
147
+ }
148
+
149
+ if (fs.existsSync(path.join(cwd, 'go.mod'))) {
150
+ return 'go';
151
+ }
152
+
153
+ if (fs.existsSync(path.join(cwd, 'requirements.txt')) || fs.existsSync(path.join(cwd, 'pyproject.toml'))) {
154
+ const hasDjango = fs.existsSync(path.join(cwd, 'manage.py'));
155
+ const hasFlask = fs.existsSync(path.join(cwd, 'app.py')) || fs.existsSync(path.join(cwd, 'wsgi.py'));
156
+ if (hasDjango) return 'django';
157
+ if (hasFlask) return 'flask';
158
+ return 'python';
159
+ }
160
+
161
+ return 'unknown';
162
+ }
163
+
164
+ // Get default config based on project type
165
+ function getDefaultConfig(projectType) {
166
+ const baseConfig = {
167
+ ticket: {
168
+ pattern: '[A-Z]+-\\d+',
169
+ extractFromBranch: true
170
+ },
171
+ build: {
172
+ command: 'auto',
173
+ testCommand: 'auto'
174
+ },
175
+ reviewTool: 'auto'
176
+ };
177
+
178
+ // Project-specific overrides
179
+ const overrides = {
180
+ 'gradle-java': {
181
+ build: {
182
+ command: './gradlew build -x test -x javadoc --offline',
183
+ testCommand: './gradlew test --offline'
184
+ }
185
+ },
186
+ 'maven-java': {
187
+ build: {
188
+ command: 'mvn compile',
189
+ testCommand: 'mvn test'
190
+ }
191
+ },
192
+ 'javascript': {
193
+ build: {
194
+ command: 'npm run build',
195
+ testCommand: 'npm test'
196
+ }
197
+ },
198
+ 'nextjs': {
199
+ build: {
200
+ command: 'npm run build',
201
+ testCommand: 'npm test'
202
+ }
203
+ },
204
+ 'express': {
205
+ build: {
206
+ command: 'npm run build || tsc',
207
+ testCommand: 'npm test'
208
+ }
209
+ },
210
+ 'nestjs': {
211
+ build: {
212
+ command: 'npm run build',
213
+ testCommand: 'npm test'
214
+ }
215
+ },
216
+ 'rust': {
217
+ build: {
218
+ command: 'cargo build',
219
+ testCommand: 'cargo test'
220
+ }
221
+ },
222
+ 'go': {
223
+ build: {
224
+ command: 'go build ./...',
225
+ testCommand: 'go test ./...'
226
+ }
227
+ },
228
+ 'python': {
229
+ build: {
230
+ command: 'python -m py_compile **/*.py',
231
+ testCommand: 'pytest'
232
+ }
233
+ },
234
+ 'django': {
235
+ build: {
236
+ command: 'python manage.py check',
237
+ testCommand: 'python manage.py test'
238
+ }
239
+ },
240
+ 'flask': {
241
+ build: {
242
+ command: 'python -m py_compile **/*.py',
243
+ testCommand: 'pytest'
244
+ }
245
+ }
246
+ };
247
+
248
+ return {
249
+ ...baseConfig,
250
+ ...(overrides[projectType] || {}),
251
+ projectType
252
+ };
253
+ }
254
+
255
+ // Initialize config file
256
+ function initializeConfig(targetPath) {
257
+ const configDir = path.join(targetPath, '.5');
258
+ const configFile = path.join(configDir, 'config.json');
259
+
260
+ if (fs.existsSync(configFile)) {
261
+ log.info('Config file already exists, skipping initialization');
262
+ return;
263
+ }
264
+
265
+ if (!fs.existsSync(configDir)) {
266
+ fs.mkdirSync(configDir, { recursive: true });
267
+ }
268
+
269
+ const projectType = detectProjectType();
270
+ const config = getDefaultConfig(projectType);
271
+
272
+ fs.writeFileSync(configFile, JSON.stringify(config, null, 2));
273
+ log.success(`Created config file with detected project type: ${projectType}`);
274
+ }
275
+
276
+ // Merge settings.json into existing
277
+ function mergeSettings(targetPath, sourcePath) {
278
+ const targetSettings = path.join(targetPath, 'settings.json');
279
+ const sourceSettings = path.join(sourcePath, 'settings.json');
280
+
281
+ if (!fs.existsSync(sourceSettings)) {
282
+ return;
283
+ }
284
+
285
+ const newSettings = JSON.parse(fs.readFileSync(sourceSettings, 'utf8'));
286
+
287
+ if (fs.existsSync(targetSettings)) {
288
+ const existingSettings = JSON.parse(fs.readFileSync(targetSettings, 'utf8'));
289
+ const merged = { ...newSettings, ...existingSettings };
290
+ fs.writeFileSync(targetSettings, JSON.stringify(merged, null, 2));
291
+ log.info('Merged settings with existing configuration');
292
+ } else {
293
+ fs.copyFileSync(sourceSettings, targetSettings);
294
+ log.success('Installed settings.json');
295
+ }
296
+ }
297
+
298
+ // Check if installation exists
299
+ function checkExistingInstallation(targetPath) {
300
+ const markerFile = path.join(targetPath, 'commands', '5', 'plan-feature.md');
301
+ return fs.existsSync(markerFile);
302
+ }
303
+
304
+ // Perform installation
305
+ function install(isGlobal) {
306
+ const targetPath = getTargetPath(isGlobal);
307
+ const sourcePath = getSourcePath();
308
+
309
+ log.header('5-Phase Workflow Installation');
310
+ log.info(`Target: ${targetPath}`);
311
+ log.info(`Source: ${sourcePath}`);
312
+
313
+ // Check if already installed
314
+ const exists = checkExistingInstallation(targetPath);
315
+ if (exists) {
316
+ log.warn('Installation already exists at this location');
317
+ log.info('To upgrade, run with --uninstall first, then reinstall');
318
+ return;
319
+ }
320
+
321
+ // Create target directory if it doesn't exist
322
+ if (!fs.existsSync(targetPath)) {
323
+ fs.mkdirSync(targetPath, { recursive: true });
324
+ log.success(`Created ${targetPath}`);
325
+ }
326
+
327
+ // Copy directories
328
+ const dirs = ['commands', 'agents', 'skills', 'hooks', 'templates'];
329
+ for (const dir of dirs) {
330
+ const src = path.join(sourcePath, dir);
331
+ const dest = path.join(targetPath, dir);
332
+
333
+ if (fs.existsSync(src)) {
334
+ copyDir(src, dest);
335
+ log.success(`Installed ${dir}/`);
336
+ }
337
+ }
338
+
339
+ // Merge settings
340
+ mergeSettings(targetPath, sourcePath);
341
+
342
+ // Initialize config
343
+ if (!isGlobal) {
344
+ initializeConfig(targetPath);
345
+ }
346
+
347
+ log.header('Installation Complete!');
348
+ log.info('Available commands:');
349
+ log.info(' /5:plan-feature - Start feature planning (Phase 1)');
350
+ log.info(' /5:plan-implementation - Create implementation plan (Phase 2)');
351
+ log.info(' /5:implement-feature - Execute implementation (Phase 3)');
352
+ log.info(' /5:verify-implementation - Verify implementation (Phase 4)');
353
+ log.info(' /5:review-code - Code review (Phase 5)');
354
+ log.info(' /5:configure - Interactive project setup');
355
+ log.info('');
356
+ log.info(`Config file: ${path.join(targetPath, '.5', 'config.json')}`);
357
+ }
358
+
359
+ // Perform uninstallation
360
+ function uninstall() {
361
+ const targetPath = getTargetPath(false); // Always local for uninstall
362
+
363
+ log.header('5-Phase Workflow Uninstallation');
364
+ log.info(`Target: ${targetPath}`);
365
+
366
+ if (!checkExistingInstallation(targetPath)) {
367
+ log.warn('No installation found at this location');
368
+ return;
369
+ }
370
+
371
+ // Remove directories
372
+ const dirs = ['commands/5', 'agents', 'skills', 'hooks', 'templates'];
373
+ for (const dir of dirs) {
374
+ const fullPath = path.join(targetPath, dir);
375
+ if (fs.existsSync(fullPath)) {
376
+ removeDir(fullPath);
377
+ log.success(`Removed ${dir}`);
378
+ }
379
+ }
380
+
381
+ // Remove config
382
+ const configDir = path.join(targetPath, '.5');
383
+ if (fs.existsSync(configDir)) {
384
+ removeDir(configDir);
385
+ log.success('Removed .5/ config directory');
386
+ }
387
+
388
+ log.header('Uninstallation Complete!');
389
+ }
390
+
391
+ // Main
392
+ function main() {
393
+ const options = parseArgs();
394
+
395
+ if (options.help) {
396
+ showHelp();
397
+ return;
398
+ }
399
+
400
+ if (options.uninstall) {
401
+ uninstall();
402
+ return;
403
+ }
404
+
405
+ install(options.global);
406
+ }
407
+
408
+ main();