5-phase-workflow 1.0.1 → 1.1.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.
- package/README.md +62 -6
- package/bin/install.js +375 -29
- package/docs/workflow-guide.md +34 -7
- package/package.json +5 -1
- package/src/agents/integration-agent.md +1 -0
- package/src/agents/review-processor.md +1 -0
- package/src/agents/step-executor.md +1 -0
- package/src/agents/step-fixer.md +1 -0
- package/src/agents/step-verifier.md +1 -0
- package/src/agents/verification-agent.md +47 -13
- package/src/commands/5/configure.md +5 -3
- package/src/commands/5/discuss-feature.md +4 -4
- package/src/commands/5/implement-feature.md +65 -19
- package/src/commands/5/plan-feature.md +5 -3
- package/src/commands/5/plan-implementation.md +115 -52
- package/src/commands/5/quick-implement.md +4 -0
- package/src/commands/5/review-code.md +4 -3
- package/src/commands/5/verify-implementation.md +43 -13
- package/src/hooks/check-updates.js +105 -0
- package/src/settings.json +3 -0
package/README.md
CHANGED
|
@@ -176,7 +176,12 @@ Claude maps your feature to technical components:
|
|
|
176
176
|
- Maps components to implementation steps
|
|
177
177
|
- Creates dependency graph
|
|
178
178
|
|
|
179
|
-
The output is
|
|
179
|
+
The output is an **atomic plan structure** at `.5/{ticket-id}/plan/`:
|
|
180
|
+
- `meta.md` - Feature metadata and risks
|
|
181
|
+
- `step-1.md`, `step-2.md`, ... - Per-step components with pre-built prompts (YAML format)
|
|
182
|
+
- `verification.md` - Build/test configuration
|
|
183
|
+
|
|
184
|
+
Each step file is self-contained and independently loadable, making large plans manageable and improving agent efficiency.
|
|
180
185
|
|
|
181
186
|
### Phase 3: Orchestrated Implementation
|
|
182
187
|
|
|
@@ -300,17 +305,68 @@ If implementation gets stuck:
|
|
|
300
305
|
|
|
301
306
|
## Updating
|
|
302
307
|
|
|
303
|
-
|
|
308
|
+
The workflow automatically detects when a new version is available.
|
|
309
|
+
|
|
310
|
+
### Automatic Update (Recommended)
|
|
304
311
|
|
|
305
312
|
```bash
|
|
306
|
-
#
|
|
307
|
-
npx 5-phase-workflow
|
|
313
|
+
# Interactive upgrade (shows prompt)
|
|
314
|
+
npx 5-phase-workflow
|
|
315
|
+
|
|
316
|
+
# Force upgrade (no prompts)
|
|
317
|
+
npx 5-phase-workflow --upgrade
|
|
318
|
+
|
|
319
|
+
# Check version without updating
|
|
320
|
+
npx 5-phase-workflow --check
|
|
321
|
+
```
|
|
308
322
|
|
|
309
|
-
|
|
323
|
+
### Legacy Upgrade Method
|
|
324
|
+
|
|
325
|
+
```bash
|
|
326
|
+
npx 5-phase-workflow --uninstall
|
|
310
327
|
npx 5-phase-workflow
|
|
311
328
|
```
|
|
312
329
|
|
|
313
|
-
|
|
330
|
+
**Note:** During updates:
|
|
331
|
+
- Config files in `.claude/.5/` are preserved
|
|
332
|
+
- User-created commands, agents, skills, hooks, and templates are preserved
|
|
333
|
+
- Only workflow-managed files are updated
|
|
334
|
+
|
|
335
|
+
## Development
|
|
336
|
+
|
|
337
|
+
### Running Tests
|
|
338
|
+
|
|
339
|
+
The project includes automated verification to ensure all workflow files are properly configured:
|
|
340
|
+
|
|
341
|
+
```bash
|
|
342
|
+
# Run verification tests
|
|
343
|
+
npm test
|
|
344
|
+
|
|
345
|
+
# Or run directly
|
|
346
|
+
bash test/verify-install-js.sh
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
This verifies that all workflow files (commands, agents, skills, hooks, templates) are properly listed in `bin/install.js` for selective updates.
|
|
350
|
+
|
|
351
|
+
### Continuous Integration
|
|
352
|
+
|
|
353
|
+
A GitHub Actions workflow runs on every push to verify the install.js configuration. The workflow:
|
|
354
|
+
- Checks that all workflow files are listed in `getWorkflowManagedFiles()`
|
|
355
|
+
- Ensures selective updates will work correctly
|
|
356
|
+
- Prevents accidental omissions that could break user upgrades
|
|
357
|
+
|
|
358
|
+
See `.github/workflows/test.yml` for details.
|
|
359
|
+
|
|
360
|
+
### Adding New Workflow Files
|
|
361
|
+
|
|
362
|
+
When adding new commands, agents, skills, hooks, or templates:
|
|
363
|
+
|
|
364
|
+
1. Create the file in the appropriate `src/` directory
|
|
365
|
+
2. **Update `bin/install.js`** - Add the file to `getWorkflowManagedFiles()`
|
|
366
|
+
3. Run `npm test` to verify
|
|
367
|
+
4. Commit only if tests pass
|
|
368
|
+
|
|
369
|
+
See `CLAUDE.md` for detailed development guidelines.
|
|
314
370
|
|
|
315
371
|
## Contributing
|
|
316
372
|
|
package/bin/install.js
CHANGED
|
@@ -22,6 +22,68 @@ const log = {
|
|
|
22
22
|
header: (msg) => console.log(`\n${colors.bright}${msg}${colors.reset}\n`)
|
|
23
23
|
};
|
|
24
24
|
|
|
25
|
+
// Version comparison (semver)
|
|
26
|
+
function compareVersions(v1, v2) {
|
|
27
|
+
const parts1 = v1.split('.').map(Number);
|
|
28
|
+
const parts2 = v2.split('.').map(Number);
|
|
29
|
+
for (let i = 0; i < 3; i++) {
|
|
30
|
+
if (parts1[i] > parts2[i]) return 1;
|
|
31
|
+
if (parts1[i] < parts2[i]) return -1;
|
|
32
|
+
}
|
|
33
|
+
return 0;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Get installed version from .5/version.json
|
|
37
|
+
function getInstalledVersion(targetPath) {
|
|
38
|
+
const versionFile = path.join(targetPath, '.5', 'version.json');
|
|
39
|
+
if (!fs.existsSync(versionFile)) return null;
|
|
40
|
+
|
|
41
|
+
try {
|
|
42
|
+
const data = JSON.parse(fs.readFileSync(versionFile, 'utf8'));
|
|
43
|
+
return data.installedVersion;
|
|
44
|
+
} catch (e) {
|
|
45
|
+
return null; // Corrupted file, treat as missing
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Get package version from package.json
|
|
50
|
+
function getPackageVersion() {
|
|
51
|
+
const pkgPath = path.join(__dirname, '..', 'package.json');
|
|
52
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
|
|
53
|
+
return pkg.version;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Get full version info
|
|
57
|
+
function getVersionInfo(targetPath) {
|
|
58
|
+
const exists = checkExistingInstallation(targetPath);
|
|
59
|
+
if (!exists) {
|
|
60
|
+
return { exists: false };
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const installed = getInstalledVersion(targetPath);
|
|
64
|
+
const available = getPackageVersion();
|
|
65
|
+
|
|
66
|
+
if (!installed) {
|
|
67
|
+
// Legacy install without version.json
|
|
68
|
+
return {
|
|
69
|
+
exists: true,
|
|
70
|
+
installed: null,
|
|
71
|
+
available,
|
|
72
|
+
needsUpdate: true,
|
|
73
|
+
legacy: true
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const needsUpdate = compareVersions(installed, available) < 0;
|
|
78
|
+
|
|
79
|
+
return {
|
|
80
|
+
exists: true,
|
|
81
|
+
installed,
|
|
82
|
+
available,
|
|
83
|
+
needsUpdate
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
|
|
25
87
|
// Parse CLI arguments
|
|
26
88
|
function parseArgs() {
|
|
27
89
|
const args = process.argv.slice(2);
|
|
@@ -29,6 +91,8 @@ function parseArgs() {
|
|
|
29
91
|
global: false,
|
|
30
92
|
local: false,
|
|
31
93
|
uninstall: false,
|
|
94
|
+
upgrade: false,
|
|
95
|
+
check: false,
|
|
32
96
|
help: false
|
|
33
97
|
};
|
|
34
98
|
|
|
@@ -36,6 +100,8 @@ function parseArgs() {
|
|
|
36
100
|
if (arg === '--global' || arg === '-g') options.global = true;
|
|
37
101
|
else if (arg === '--local' || arg === '-l') options.local = true;
|
|
38
102
|
else if (arg === '--uninstall' || arg === '-u') options.uninstall = true;
|
|
103
|
+
else if (arg === '--upgrade' || arg === '--force' || arg === '-U') options.upgrade = true;
|
|
104
|
+
else if (arg === '--check') options.check = true;
|
|
39
105
|
else if (arg === '--help' || arg === '-h') options.help = true;
|
|
40
106
|
}
|
|
41
107
|
|
|
@@ -57,12 +123,17 @@ Usage: npx 5-phase-workflow [options]
|
|
|
57
123
|
Options:
|
|
58
124
|
--global, -g Install to ~/.claude/ (available across all projects)
|
|
59
125
|
--local, -l Install to ./.claude/ (project-specific, default)
|
|
126
|
+
--upgrade, -U Upgrade to latest version (auto-update, no prompt)
|
|
127
|
+
--force Alias for --upgrade
|
|
128
|
+
--check Check installed version and available updates
|
|
60
129
|
--uninstall, -u Remove installation from current directory
|
|
61
130
|
--help, -h Show this help message
|
|
62
131
|
|
|
63
132
|
Examples:
|
|
64
|
-
npx 5-phase-workflow # Install locally
|
|
133
|
+
npx 5-phase-workflow # Install locally or prompt for update
|
|
65
134
|
npx 5-phase-workflow --global # Install globally
|
|
135
|
+
npx 5-phase-workflow --upgrade # Auto-update to latest version
|
|
136
|
+
npx 5-phase-workflow --check # Check version without updating
|
|
66
137
|
npx 5-phase-workflow --uninstall # Remove from current directory
|
|
67
138
|
`);
|
|
68
139
|
}
|
|
@@ -122,6 +193,128 @@ function removeDir(dir) {
|
|
|
122
193
|
}
|
|
123
194
|
}
|
|
124
195
|
|
|
196
|
+
// Get list of workflow-owned files/directories (not user-created)
|
|
197
|
+
function getWorkflowManagedFiles() {
|
|
198
|
+
return {
|
|
199
|
+
// Commands: only the 5/ namespace
|
|
200
|
+
commands: ['5'],
|
|
201
|
+
|
|
202
|
+
// Agents: specific agent files
|
|
203
|
+
agents: [
|
|
204
|
+
'step-executor.md',
|
|
205
|
+
'step-verifier.md',
|
|
206
|
+
'integration-agent.md',
|
|
207
|
+
'verification-agent.md',
|
|
208
|
+
'review-processor.md',
|
|
209
|
+
'step-fixer.md'
|
|
210
|
+
],
|
|
211
|
+
|
|
212
|
+
// Skills: specific skill directories
|
|
213
|
+
skills: [
|
|
214
|
+
'build-project',
|
|
215
|
+
'run-tests',
|
|
216
|
+
'configure-project',
|
|
217
|
+
'generate-readme'
|
|
218
|
+
],
|
|
219
|
+
|
|
220
|
+
// Hooks: specific hook files
|
|
221
|
+
hooks: [
|
|
222
|
+
'statusline.js',
|
|
223
|
+
'check-updates.js'
|
|
224
|
+
],
|
|
225
|
+
|
|
226
|
+
// Templates: specific template files
|
|
227
|
+
templates: [
|
|
228
|
+
'ARCHITECTURE.md',
|
|
229
|
+
'CONCERNS.md',
|
|
230
|
+
'CONVENTIONS.md',
|
|
231
|
+
'INTEGRATIONS.md',
|
|
232
|
+
'STACK.md',
|
|
233
|
+
'STRUCTURE.md',
|
|
234
|
+
'TESTING.md'
|
|
235
|
+
]
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// Selectively update only workflow-managed files, preserve user content
|
|
240
|
+
function selectiveUpdate(targetPath, sourcePath) {
|
|
241
|
+
const managed = getWorkflowManagedFiles();
|
|
242
|
+
|
|
243
|
+
// Update commands/5/ only
|
|
244
|
+
const commandsSrc = path.join(sourcePath, 'commands', '5');
|
|
245
|
+
const commandsDest = path.join(targetPath, 'commands', '5');
|
|
246
|
+
if (fs.existsSync(commandsSrc)) {
|
|
247
|
+
if (fs.existsSync(commandsDest)) {
|
|
248
|
+
removeDir(commandsDest);
|
|
249
|
+
}
|
|
250
|
+
copyDir(commandsSrc, commandsDest);
|
|
251
|
+
log.success('Updated commands/5/');
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// Update specific agents
|
|
255
|
+
const agentsSrc = path.join(sourcePath, 'agents');
|
|
256
|
+
const agentsDest = path.join(targetPath, 'agents');
|
|
257
|
+
if (!fs.existsSync(agentsDest)) {
|
|
258
|
+
fs.mkdirSync(agentsDest, { recursive: true });
|
|
259
|
+
}
|
|
260
|
+
for (const agent of managed.agents) {
|
|
261
|
+
const src = path.join(agentsSrc, agent);
|
|
262
|
+
const dest = path.join(agentsDest, agent);
|
|
263
|
+
if (fs.existsSync(src)) {
|
|
264
|
+
fs.copyFileSync(src, dest);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
log.success('Updated agents/ (workflow files only)');
|
|
268
|
+
|
|
269
|
+
// Update specific skills
|
|
270
|
+
const skillsSrc = path.join(sourcePath, 'skills');
|
|
271
|
+
const skillsDest = path.join(targetPath, 'skills');
|
|
272
|
+
if (!fs.existsSync(skillsDest)) {
|
|
273
|
+
fs.mkdirSync(skillsDest, { recursive: true });
|
|
274
|
+
}
|
|
275
|
+
for (const skill of managed.skills) {
|
|
276
|
+
const src = path.join(skillsSrc, skill);
|
|
277
|
+
const dest = path.join(skillsDest, skill);
|
|
278
|
+
if (fs.existsSync(src)) {
|
|
279
|
+
if (fs.existsSync(dest)) {
|
|
280
|
+
removeDir(dest);
|
|
281
|
+
}
|
|
282
|
+
copyDir(src, dest);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
log.success('Updated skills/ (workflow skills only)');
|
|
286
|
+
|
|
287
|
+
// Update specific hooks
|
|
288
|
+
const hooksSrc = path.join(sourcePath, 'hooks');
|
|
289
|
+
const hooksDest = path.join(targetPath, 'hooks');
|
|
290
|
+
if (!fs.existsSync(hooksDest)) {
|
|
291
|
+
fs.mkdirSync(hooksDest, { recursive: true });
|
|
292
|
+
}
|
|
293
|
+
for (const hook of managed.hooks) {
|
|
294
|
+
const src = path.join(hooksSrc, hook);
|
|
295
|
+
const dest = path.join(hooksDest, hook);
|
|
296
|
+
if (fs.existsSync(src)) {
|
|
297
|
+
fs.copyFileSync(src, dest);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
log.success('Updated hooks/ (workflow files only)');
|
|
301
|
+
|
|
302
|
+
// Update specific templates
|
|
303
|
+
const templatesSrc = path.join(sourcePath, 'templates');
|
|
304
|
+
const templatesDest = path.join(targetPath, 'templates');
|
|
305
|
+
if (!fs.existsSync(templatesDest)) {
|
|
306
|
+
fs.mkdirSync(templatesDest, { recursive: true });
|
|
307
|
+
}
|
|
308
|
+
for (const template of managed.templates) {
|
|
309
|
+
const src = path.join(templatesSrc, template);
|
|
310
|
+
const dest = path.join(templatesDest, template);
|
|
311
|
+
if (fs.existsSync(src)) {
|
|
312
|
+
fs.copyFileSync(src, dest);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
log.success('Updated templates/ (workflow files only)');
|
|
316
|
+
}
|
|
317
|
+
|
|
125
318
|
// Detect project type by examining files in current directory
|
|
126
319
|
function detectProjectType() {
|
|
127
320
|
const cwd = process.cwd();
|
|
@@ -273,6 +466,51 @@ function initializeConfig(targetPath) {
|
|
|
273
466
|
log.success(`Created config file with detected project type: ${projectType}`);
|
|
274
467
|
}
|
|
275
468
|
|
|
469
|
+
// Initialize version.json after successful install
|
|
470
|
+
function initializeVersionJson(targetPath, isGlobal) {
|
|
471
|
+
const configDir = path.join(targetPath, '.5');
|
|
472
|
+
const versionFile = path.join(configDir, 'version.json');
|
|
473
|
+
|
|
474
|
+
if (!fs.existsSync(configDir)) {
|
|
475
|
+
fs.mkdirSync(configDir, { recursive: true });
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
const version = getPackageVersion();
|
|
479
|
+
const now = new Date().toISOString();
|
|
480
|
+
|
|
481
|
+
const versionData = {
|
|
482
|
+
packageVersion: version,
|
|
483
|
+
installedVersion: version,
|
|
484
|
+
installedAt: now,
|
|
485
|
+
lastUpdated: now,
|
|
486
|
+
installationType: isGlobal ? 'global' : 'local',
|
|
487
|
+
updateCheckLastRun: null,
|
|
488
|
+
updateCheckFrequency: 86400 // 24 hours in seconds
|
|
489
|
+
};
|
|
490
|
+
|
|
491
|
+
fs.writeFileSync(versionFile, JSON.stringify(versionData, null, 2));
|
|
492
|
+
log.success('Initialized version tracking');
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
// Deep merge for settings.json
|
|
496
|
+
function deepMerge(target, source) {
|
|
497
|
+
const result = { ...target };
|
|
498
|
+
|
|
499
|
+
for (const key in source) {
|
|
500
|
+
if (source[key] !== null && typeof source[key] === 'object' && !Array.isArray(source[key])) {
|
|
501
|
+
// Recursively merge nested objects
|
|
502
|
+
result[key] = deepMerge(result[key] || {}, source[key]);
|
|
503
|
+
} else {
|
|
504
|
+
// For primitives and arrays: use source if target doesn't have it
|
|
505
|
+
if (!(key in result)) {
|
|
506
|
+
result[key] = source[key];
|
|
507
|
+
}
|
|
508
|
+
// User's existing value takes precedence if it exists
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
return result;
|
|
512
|
+
}
|
|
513
|
+
|
|
276
514
|
// Merge settings.json into existing
|
|
277
515
|
function mergeSettings(targetPath, sourcePath) {
|
|
278
516
|
const targetSettings = path.join(targetPath, 'settings.json');
|
|
@@ -286,7 +524,7 @@ function mergeSettings(targetPath, sourcePath) {
|
|
|
286
524
|
|
|
287
525
|
if (fs.existsSync(targetSettings)) {
|
|
288
526
|
const existingSettings = JSON.parse(fs.readFileSync(targetSettings, 'utf8'));
|
|
289
|
-
const merged =
|
|
527
|
+
const merged = deepMerge(newSettings, existingSettings);
|
|
290
528
|
fs.writeFileSync(targetSettings, JSON.stringify(merged, null, 2));
|
|
291
529
|
log.info('Merged settings with existing configuration');
|
|
292
530
|
} else {
|
|
@@ -301,23 +539,21 @@ function checkExistingInstallation(targetPath) {
|
|
|
301
539
|
return fs.existsSync(markerFile);
|
|
302
540
|
}
|
|
303
541
|
|
|
304
|
-
//
|
|
305
|
-
function
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
log.
|
|
310
|
-
log.info(
|
|
311
|
-
log.info(
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
log.warn('Installation already exists at this location');
|
|
317
|
-
log.info('To upgrade, run with --uninstall first, then reinstall');
|
|
318
|
-
return;
|
|
319
|
-
}
|
|
542
|
+
// Helper to show commands
|
|
543
|
+
function showCommandsHelp(targetPath) {
|
|
544
|
+
log.info('Available commands:');
|
|
545
|
+
log.info(' /5:plan-feature - Start feature planning (Phase 1)');
|
|
546
|
+
log.info(' /5:plan-implementation - Create implementation plan (Phase 2)');
|
|
547
|
+
log.info(' /5:implement-feature - Execute implementation (Phase 3)');
|
|
548
|
+
log.info(' /5:verify-implementation - Verify implementation (Phase 4)');
|
|
549
|
+
log.info(' /5:review-code - Code review (Phase 5)');
|
|
550
|
+
log.info(' /5:configure - Interactive project setup');
|
|
551
|
+
log.info('');
|
|
552
|
+
log.info(`Config file: ${path.join(targetPath, '.5', 'config.json')}`);
|
|
553
|
+
}
|
|
320
554
|
|
|
555
|
+
// Fresh installation
|
|
556
|
+
function performFreshInstall(targetPath, sourcePath, isGlobal) {
|
|
321
557
|
// Create target directory if it doesn't exist
|
|
322
558
|
if (!fs.existsSync(targetPath)) {
|
|
323
559
|
fs.mkdirSync(targetPath, { recursive: true });
|
|
@@ -339,21 +575,110 @@ function install(isGlobal) {
|
|
|
339
575
|
// Merge settings
|
|
340
576
|
mergeSettings(targetPath, sourcePath);
|
|
341
577
|
|
|
342
|
-
// Initialize config
|
|
578
|
+
// Initialize config (local only)
|
|
343
579
|
if (!isGlobal) {
|
|
344
580
|
initializeConfig(targetPath);
|
|
345
581
|
}
|
|
346
582
|
|
|
583
|
+
// Initialize version tracking
|
|
584
|
+
initializeVersionJson(targetPath, isGlobal);
|
|
585
|
+
|
|
347
586
|
log.header('Installation Complete!');
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
log.
|
|
354
|
-
log.info('
|
|
355
|
-
|
|
356
|
-
|
|
587
|
+
showCommandsHelp(targetPath);
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
// Perform update (preserves .5/ directory and user-created files)
|
|
591
|
+
function performUpdate(targetPath, sourcePath, isGlobal, versionInfo) {
|
|
592
|
+
log.header(`Updating from ${versionInfo.installed || 'legacy'} to ${versionInfo.available}`);
|
|
593
|
+
log.info('Preserving user-created commands, agents, skills, and hooks');
|
|
594
|
+
|
|
595
|
+
// Selectively update only workflow-managed files (preserves user content)
|
|
596
|
+
selectiveUpdate(targetPath, sourcePath);
|
|
597
|
+
|
|
598
|
+
// Merge settings (deep merge preserves user customizations)
|
|
599
|
+
mergeSettings(targetPath, sourcePath);
|
|
600
|
+
|
|
601
|
+
// Update version.json
|
|
602
|
+
const configDir = path.join(targetPath, '.5');
|
|
603
|
+
const versionFile = path.join(configDir, 'version.json');
|
|
604
|
+
|
|
605
|
+
let versionData;
|
|
606
|
+
if (fs.existsSync(versionFile)) {
|
|
607
|
+
versionData = JSON.parse(fs.readFileSync(versionFile, 'utf8'));
|
|
608
|
+
} else {
|
|
609
|
+
// Legacy install, create version.json
|
|
610
|
+
versionData = {
|
|
611
|
+
installedAt: new Date().toISOString(),
|
|
612
|
+
installationType: isGlobal ? 'global' : 'local',
|
|
613
|
+
updateCheckFrequency: 86400
|
|
614
|
+
};
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
versionData.packageVersion = versionInfo.available;
|
|
618
|
+
versionData.installedVersion = versionInfo.available;
|
|
619
|
+
versionData.lastUpdated = new Date().toISOString();
|
|
620
|
+
|
|
621
|
+
if (!fs.existsSync(configDir)) {
|
|
622
|
+
fs.mkdirSync(configDir, { recursive: true });
|
|
623
|
+
}
|
|
624
|
+
fs.writeFileSync(versionFile, JSON.stringify(versionData, null, 2));
|
|
625
|
+
|
|
626
|
+
log.header('Update Complete!');
|
|
627
|
+
log.success(`Now running version ${versionInfo.available}`);
|
|
628
|
+
showCommandsHelp(targetPath);
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
// Perform installation
|
|
632
|
+
function install(isGlobal, forceUpgrade = false) {
|
|
633
|
+
const targetPath = getTargetPath(isGlobal);
|
|
634
|
+
const sourcePath = getSourcePath();
|
|
635
|
+
|
|
636
|
+
log.header('5-Phase Workflow Installation');
|
|
637
|
+
log.info(`Target: ${targetPath}`);
|
|
638
|
+
log.info(`Source: ${sourcePath}`);
|
|
639
|
+
|
|
640
|
+
// Check for existing installation and version
|
|
641
|
+
const versionInfo = getVersionInfo(targetPath);
|
|
642
|
+
|
|
643
|
+
if (versionInfo.exists) {
|
|
644
|
+
if (versionInfo.legacy) {
|
|
645
|
+
log.warn('Detected legacy installation (no version tracking)');
|
|
646
|
+
log.info(`Upgrading from legacy install to ${versionInfo.available}`);
|
|
647
|
+
performUpdate(targetPath, sourcePath, isGlobal, versionInfo);
|
|
648
|
+
return;
|
|
649
|
+
} else if (versionInfo.needsUpdate) {
|
|
650
|
+
log.info(`Installed: ${versionInfo.installed}`);
|
|
651
|
+
log.info(`Available: ${versionInfo.available}`);
|
|
652
|
+
|
|
653
|
+
if (!forceUpgrade) {
|
|
654
|
+
// Prompt user for confirmation
|
|
655
|
+
const rl = readline.createInterface({
|
|
656
|
+
input: process.stdin,
|
|
657
|
+
output: process.stdout
|
|
658
|
+
});
|
|
659
|
+
|
|
660
|
+
rl.question('Update to latest version? (Y/n): ', (answer) => {
|
|
661
|
+
rl.close();
|
|
662
|
+
if (answer.toLowerCase() === 'n' || answer.toLowerCase() === 'no') {
|
|
663
|
+
log.info('Update cancelled');
|
|
664
|
+
return;
|
|
665
|
+
}
|
|
666
|
+
performUpdate(targetPath, sourcePath, isGlobal, versionInfo);
|
|
667
|
+
});
|
|
668
|
+
return; // Wait for user input
|
|
669
|
+
}
|
|
670
|
+
// Force upgrade, no prompt
|
|
671
|
+
performUpdate(targetPath, sourcePath, isGlobal, versionInfo);
|
|
672
|
+
return;
|
|
673
|
+
} else {
|
|
674
|
+
// Same version
|
|
675
|
+
log.success(`Already installed (version ${versionInfo.installed})`);
|
|
676
|
+
return;
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
// Fresh install (no existing installation)
|
|
681
|
+
performFreshInstall(targetPath, sourcePath, isGlobal);
|
|
357
682
|
}
|
|
358
683
|
|
|
359
684
|
// Perform uninstallation
|
|
@@ -397,12 +722,33 @@ function main() {
|
|
|
397
722
|
return;
|
|
398
723
|
}
|
|
399
724
|
|
|
725
|
+
if (options.check) {
|
|
726
|
+
const targetPath = getTargetPath(options.global);
|
|
727
|
+
const versionInfo = getVersionInfo(targetPath);
|
|
728
|
+
|
|
729
|
+
if (!versionInfo.exists) {
|
|
730
|
+
log.info('Not installed');
|
|
731
|
+
return;
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
log.info(`Installed: ${versionInfo.installed || 'legacy (no version)'}`);
|
|
735
|
+
log.info(`Available: ${versionInfo.available}`);
|
|
736
|
+
|
|
737
|
+
if (versionInfo.needsUpdate) {
|
|
738
|
+
log.warn('Update available');
|
|
739
|
+
log.info('Run: npx 5-phase-workflow --upgrade');
|
|
740
|
+
} else {
|
|
741
|
+
log.success('Up to date');
|
|
742
|
+
}
|
|
743
|
+
return;
|
|
744
|
+
}
|
|
745
|
+
|
|
400
746
|
if (options.uninstall) {
|
|
401
747
|
uninstall();
|
|
402
748
|
return;
|
|
403
749
|
}
|
|
404
750
|
|
|
405
|
-
install(options.global);
|
|
751
|
+
install(options.global, options.upgrade);
|
|
406
752
|
}
|
|
407
753
|
|
|
408
754
|
main();
|
package/docs/workflow-guide.md
CHANGED
|
@@ -120,7 +120,8 @@ Commands used to call skills directly, consuming main context for heavy operatio
|
|
|
120
120
|
| |
|
|
121
121
|
| Developer: /plan-implementation {TICKET-ID}-{description} |
|
|
122
122
|
| Claude: Maps to modules, skills, dependency steps |
|
|
123
|
-
| Output: .5/{ticket}/plan
|
|
123
|
+
| Output: .5/{ticket}/plan/ (atomic structure) |
|
|
124
|
+
| - meta.md, step-N.md files, verification.md |
|
|
124
125
|
| Developer: Reviews technical approach |
|
|
125
126
|
+-----------------------------+-------------------------------------+
|
|
126
127
|
|
|
|
@@ -255,11 +256,27 @@ Map feature requirements to technical components, skills, and dependency steps.
|
|
|
255
256
|
|
|
256
257
|
Note: Step count and organization is configurable in `.claude/.5/config.json`
|
|
257
258
|
|
|
258
|
-
6. **Implementation Plan Creation**: Claude writes plan to:
|
|
259
|
+
6. **Implementation Plan Creation**: Claude writes an **atomic plan structure** to:
|
|
259
260
|
```
|
|
260
|
-
.5/{TICKET-ID}-{description}/plan
|
|
261
|
+
.5/{TICKET-ID}-{description}/plan/
|
|
262
|
+
├── meta.md # Feature metadata and risks
|
|
263
|
+
├── step-1.md # Step 1 components (YAML format)
|
|
264
|
+
├── step-2.md # Step 2 components
|
|
265
|
+
├── step-N.md # Step N components
|
|
266
|
+
└── verification.md # Build/test configuration
|
|
261
267
|
```
|
|
262
268
|
|
|
269
|
+
**Atomic Plan Structure (Format Version 2.0):**
|
|
270
|
+
- Each step is in a separate file for modularity
|
|
271
|
+
- Components are stored in YAML format for easy parsing
|
|
272
|
+
- Metadata and verification config are separated
|
|
273
|
+
- Benefits: scalability, navigation, agent efficiency, version control
|
|
274
|
+
|
|
275
|
+
**File Formats:**
|
|
276
|
+
- `meta.md`: YAML frontmatter (feature, ticket, totals) + risks section
|
|
277
|
+
- `step-N.md`: YAML frontmatter (step, name, mode) + components YAML block + expected outputs
|
|
278
|
+
- `verification.md`: Build/test commands and expected file lists
|
|
279
|
+
|
|
263
280
|
### Your Role
|
|
264
281
|
|
|
265
282
|
1. **Answer technical questions**: Clarify implementation details
|
|
@@ -291,7 +308,10 @@ Execute the implementation plan with state tracking, using agents in forked cont
|
|
|
291
308
|
|
|
292
309
|
### What Happens
|
|
293
310
|
|
|
294
|
-
1. **Load Implementation Plan**: Command reads the approved plan
|
|
311
|
+
1. **Load Implementation Plan**: Command reads the approved atomic plan
|
|
312
|
+
- Reads `plan/meta.md` for feature metadata and total steps count
|
|
313
|
+
- Loads each `plan/step-N.md` on-demand during execution
|
|
314
|
+
- Parses YAML components from each step file
|
|
295
315
|
|
|
296
316
|
2. **Initialize State File**: Creates tracking file
|
|
297
317
|
```
|
|
@@ -551,7 +571,14 @@ Claude: Let me ask a few technical questions...
|
|
|
551
571
|
You: [Answer technical questions]
|
|
552
572
|
|
|
553
573
|
Claude: Implementation plan created at
|
|
554
|
-
.5/PROJ-1234-add-user-profile/plan
|
|
574
|
+
.5/PROJ-1234-add-user-profile/plan/
|
|
575
|
+
|
|
576
|
+
Atomic plan structure:
|
|
577
|
+
- meta.md: Feature metadata, 3 steps, 6 components
|
|
578
|
+
- step-1.md: Foundation (2 components, parallel)
|
|
579
|
+
- step-2.md: Logic (2 components, sequential)
|
|
580
|
+
- step-3.md: Integration (2 components, sequential)
|
|
581
|
+
- verification.md: Build/test configuration
|
|
555
582
|
|
|
556
583
|
Module Impact:
|
|
557
584
|
- src/models: 1 update (User model)
|
|
@@ -564,7 +591,7 @@ Step 1 (Foundation): User model update, ProfileValidator
|
|
|
564
591
|
Step 2 (Logic): ProfileService with business logic
|
|
565
592
|
Step 3 (Integration): API route registration, tests
|
|
566
593
|
|
|
567
|
-
Please review and then run: /implement-feature PROJ-1234-add-user-profile
|
|
594
|
+
Please review the plan files and then run: /implement-feature PROJ-1234-add-user-profile
|
|
568
595
|
```
|
|
569
596
|
|
|
570
597
|
### Step 4: Start Implementation (with Agents)
|
|
@@ -877,7 +904,7 @@ If working on multiple features:
|
|
|
877
904
|
| File | Purpose | Committed? |
|
|
878
905
|
|------|---------|------------|
|
|
879
906
|
| `.5/{ticket}/feature.md` | Feature spec | Yes (after approval) |
|
|
880
|
-
| `.5/{ticket}/plan
|
|
907
|
+
| `.5/{ticket}/plan/` | Atomic implementation plan (meta.md, step-N.md, verification.md) | Yes (after approval) |
|
|
881
908
|
| `.5/{ticket}/state.json` | Progress tracking | No (gitignored) |
|
|
882
909
|
| `.5/{ticket}/verification.md` | Verification report | No (gitignored) |
|
|
883
910
|
| `.5/{ticket}/review-{timestamp}.md` | CodeRabbit review report | No (gitignored) |
|
package/package.json
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "5-phase-workflow",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "A 5-phase feature development workflow for Claude Code",
|
|
5
5
|
"bin": {
|
|
6
6
|
"5-phase-workflow": "bin/install.js"
|
|
7
7
|
},
|
|
8
|
+
"scripts": {
|
|
9
|
+
"test": "bash test/verify-install-js.sh",
|
|
10
|
+
"verify": "bash test/verify-install-js.sh"
|
|
11
|
+
},
|
|
8
12
|
"files": [
|
|
9
13
|
"bin",
|
|
10
14
|
"src",
|
|
@@ -3,6 +3,7 @@ name: integration-agent
|
|
|
3
3
|
description: Integrates new components into the application by following existing project patterns. Wires components, registers endpoints/routes, and runs final build and tests. Runs in forked context.
|
|
4
4
|
tools: Read, Edit, Bash, Glob, Grep, Skill, mcp__jetbrains__get_file_problems, mcp__jetbrains__rename_refactoring
|
|
5
5
|
model: sonnet
|
|
6
|
+
color: blue
|
|
6
7
|
---
|
|
7
8
|
|
|
8
9
|
# Integration Agent
|
|
@@ -3,6 +3,7 @@ name: review-processor
|
|
|
3
3
|
description: Runs CodeRabbit CLI, parses output, and categorizes findings into fixable issues, questions, and manual review items. Runs in forked context.
|
|
4
4
|
tools: Bash, Read, Glob, Grep
|
|
5
5
|
model: sonnet
|
|
6
|
+
color: magenta
|
|
6
7
|
---
|
|
7
8
|
|
|
8
9
|
# Review Processor Agent
|