5-phase-workflow 1.4.4 → 1.5.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 CHANGED
@@ -126,10 +126,11 @@ All commands are available under the `/5:` namespace:
126
126
  | `/5:verify-implementation` | 4 | Verify completeness and correctness |
127
127
  | `/5:review-code` | 5 | AI-powered code review (CodeRabbit) |
128
128
  | `/5:quick-implement` | Fast | Streamlined workflow for small tasks |
129
+ | `/5:unlock` | Utility | Remove planning guard lock |
129
130
 
130
131
  ## Configuration
131
132
 
132
- The workflow is configured via `.claude/.5/config.json`. Here's an example:
133
+ The workflow is configured via `.5/config.json`. Here's an example:
133
134
 
134
135
  ```json
135
136
  {
@@ -181,7 +182,7 @@ Claude asks 5-10 clarifying questions to understand your requirements:
181
182
  - How will we verify it works?
182
183
  - Are there simpler alternatives?
183
184
 
184
- The output is a comprehensive feature spec at `.claude/.features/{ticket-id}.md`.
185
+ The output is a comprehensive feature spec at `.5/features/{ticket-id}/feature.md`.
185
186
 
186
187
  ### Phase 2: Implementation Planning
187
188
 
@@ -207,7 +208,7 @@ Claude executes the plan using specialized agents:
207
208
  - **step-verifier**: Compiles and checks for errors after each step
208
209
  - **integration-agent**: Wires components and registers routes
209
210
 
210
- State is tracked in `.claude/.implementations/state/{ticket-id}.json` for resumability.
211
+ State is tracked in `.5/features/{ticket-id}/state.json` for resumability.
211
212
 
212
213
  ### Phase 4: Verify Implementation
213
214
 
@@ -234,9 +235,12 @@ Automated review using CodeRabbit (if installed):
234
235
  After installation, your `.claude/` directory will contain:
235
236
 
236
237
  ```
238
+ .5/
239
+ ├── config.json # Project configuration
240
+ ├── version.json # Version tracking
241
+ └── features/ # Feature tracking
242
+
237
243
  .claude/
238
- ├── .5/
239
- │ └── config.json # Project configuration
240
244
  ├── commands/5/ # Workflow commands
241
245
  │ ├── plan-feature.md
242
246
  │ ├── plan-implementation.md
@@ -245,13 +249,17 @@ After installation, your `.claude/` directory will contain:
245
249
  │ ├── review-code.md
246
250
  │ ├── discuss-feature.md
247
251
  │ ├── quick-implement.md
248
- └── configure.md
252
+ ├── configure.md
253
+ │ └── unlock.md
249
254
  ├── skills/ # Atomic operations
250
255
  │ ├── build-project/
251
256
  │ ├── run-tests/
252
257
  │ └── generate-readme/
253
258
  ├── hooks/
254
- └── statusline.js # Status line integration
259
+ ├── statusline.js # Status line integration
260
+ │ ├── check-updates.js # Update notifications
261
+ │ ├── plan-guard.js # Planning phase edit guard
262
+ │ └── config-guard.js # Configuration guard
255
263
  └── settings.json # Claude Code settings
256
264
  ```
257
265
 
@@ -293,7 +301,7 @@ After installation, your `.claude/` directory will contain:
293
301
 
294
302
  1. Run `/5:configure` to verify configuration
295
303
  2. Test commands manually in terminal
296
- 3. Update `.claude/.5/config.json` with correct commands
304
+ 3. Update `.5/config.json` with correct commands
297
305
 
298
306
  ### "Cannot find project type"
299
307
 
@@ -303,7 +311,7 @@ The auto-detection failed. Run `/5:configure` and manually select your project t
303
311
 
304
312
  If implementation gets stuck:
305
313
 
306
- 1. Check `.claude/.implementations/state/{ticket-id}.json`
314
+ 1. Check `.5/features/{ticket-id}/state.json`
307
315
  2. Note the `currentStep` value
308
316
  3. Run `/5:implement-feature` again - it will resume from that step
309
317
 
@@ -338,7 +346,7 @@ npx 5-phase-workflow
338
346
  ```
339
347
 
340
348
  **Note:** During updates:
341
- - Config files in `.claude/.5/` are preserved
349
+ - Config files in `.5/` are preserved
342
350
  - User-created commands, agents, skills, hooks, and templates are preserved
343
351
  - Only workflow-managed files are updated
344
352
 
package/bin/install.js CHANGED
@@ -35,8 +35,8 @@ function compareVersions(v1, v2) {
35
35
  }
36
36
 
37
37
  // Get installed version from .5/version.json
38
- function getInstalledVersion(targetPath) {
39
- const versionFile = path.join(targetPath, '.5', 'version.json');
38
+ function getInstalledVersion(isGlobal) {
39
+ const versionFile = path.join(getDataPath(isGlobal), 'version.json');
40
40
  if (!fs.existsSync(versionFile)) return null;
41
41
 
42
42
  try {
@@ -55,13 +55,13 @@ function getPackageVersion() {
55
55
  }
56
56
 
57
57
  // Get full version info
58
- function getVersionInfo(targetPath) {
58
+ function getVersionInfo(targetPath, isGlobal) {
59
59
  const exists = checkExistingInstallation(targetPath);
60
60
  if (!exists) {
61
61
  return { exists: false };
62
62
  }
63
63
 
64
- const installed = getInstalledVersion(targetPath);
64
+ const installed = getInstalledVersion(isGlobal);
65
65
  const available = getPackageVersion();
66
66
 
67
67
  if (!installed) {
@@ -139,7 +139,7 @@ Examples:
139
139
  `);
140
140
  }
141
141
 
142
- // Get installation target path
142
+ // Get installation target path (.claude/ directory)
143
143
  function getTargetPath(isGlobal) {
144
144
  if (isGlobal) {
145
145
  const homeDir = process.env.HOME || process.env.USERPROFILE;
@@ -148,6 +148,60 @@ function getTargetPath(isGlobal) {
148
148
  return path.join(process.cwd(), '.claude');
149
149
  }
150
150
 
151
+ // Get data path (.5/ directory for config, version, features)
152
+ // Local installs: <project>/.5 (project root)
153
+ // Global installs: ~/.claude/.5 (alongside global install)
154
+ function getDataPath(isGlobal) {
155
+ if (isGlobal) {
156
+ return path.join(getTargetPath(true), '.5');
157
+ }
158
+ return path.join(process.cwd(), '.5');
159
+ }
160
+
161
+ // Migrate data from old .claude/.5/ to new .5/ location (local installs only)
162
+ // This runs during upgrades so existing users don't lose config/features/version data.
163
+ function migrateDataDir(isGlobal) {
164
+ // Global installs: old and new paths are both ~/.claude/.5 — no migration needed
165
+ if (isGlobal) return;
166
+
167
+ const oldDir = path.join(process.cwd(), '.claude', '.5');
168
+ const newDir = getDataPath(false); // <project>/.5
169
+
170
+ if (!fs.existsSync(oldDir)) return;
171
+
172
+ // If new dir doesn't exist, move everything over
173
+ if (!fs.existsSync(newDir)) {
174
+ fs.mkdirSync(newDir, { recursive: true });
175
+ }
176
+
177
+ // Copy all files/dirs from old to new (skip files that already exist in new)
178
+ copyDirMerge(oldDir, newDir);
179
+
180
+ // Remove old directory
181
+ removeDir(oldDir);
182
+ log.success('Migrated .claude/.5/ → .5/');
183
+ }
184
+
185
+ // Copy directory recursively, skipping files that already exist at destination
186
+ function copyDirMerge(src, dest) {
187
+ if (!fs.existsSync(dest)) {
188
+ fs.mkdirSync(dest, { recursive: true });
189
+ }
190
+
191
+ const entries = fs.readdirSync(src, { withFileTypes: true });
192
+
193
+ for (const entry of entries) {
194
+ const srcPath = path.join(src, entry.name);
195
+ const destPath = path.join(dest, entry.name);
196
+
197
+ if (entry.isDirectory()) {
198
+ copyDirMerge(srcPath, destPath);
199
+ } else if (!fs.existsSync(destPath)) {
200
+ fs.copyFileSync(srcPath, destPath);
201
+ }
202
+ }
203
+ }
204
+
151
205
  // Get source path (package installation directory)
152
206
  function getSourcePath() {
153
207
  // When installed via npm, __dirname is <install-location>/bin
@@ -328,12 +382,12 @@ function selectiveUpdate(targetPath, sourcePath) {
328
382
  }
329
383
 
330
384
  // Initialize version.json after successful install
331
- function initializeVersionJson(targetPath, isGlobal) {
332
- const configDir = path.join(targetPath, '.5');
333
- const versionFile = path.join(configDir, 'version.json');
385
+ function initializeVersionJson(isGlobal) {
386
+ const dataDir = getDataPath(isGlobal);
387
+ const versionFile = path.join(dataDir, 'version.json');
334
388
 
335
- if (!fs.existsSync(configDir)) {
336
- fs.mkdirSync(configDir, { recursive: true });
389
+ if (!fs.existsSync(dataDir)) {
390
+ fs.mkdirSync(dataDir, { recursive: true });
337
391
  }
338
392
 
339
393
  const version = getPackageVersion();
@@ -427,7 +481,7 @@ function checkExistingInstallation(targetPath) {
427
481
  }
428
482
 
429
483
  // Helper to show commands
430
- function showCommandsHelp(targetPath) {
484
+ function showCommandsHelp(isGlobal) {
431
485
  log.info('Available commands:');
432
486
  log.info(' /5:plan-feature - Start feature planning (Phase 1)');
433
487
  log.info(' /5:plan-implementation - Create implementation plan (Phase 2)');
@@ -435,8 +489,9 @@ function showCommandsHelp(targetPath) {
435
489
  log.info(' /5:verify-implementation - Verify implementation (Phase 4)');
436
490
  log.info(' /5:review-code - Code review (Phase 5)');
437
491
  log.info(' /5:configure - Interactive project setup');
492
+ log.info(' /5:unlock - Remove planning guard lock');
438
493
  log.info('');
439
- log.info(`Config file: ${path.join(targetPath, '.5', 'config.json')}`);
494
+ log.info(`Config file: ${path.join(getDataPath(isGlobal), 'config.json')}`);
440
495
  }
441
496
 
442
497
  // Fresh installation
@@ -463,7 +518,7 @@ function performFreshInstall(targetPath, sourcePath, isGlobal) {
463
518
  mergeSettings(targetPath, sourcePath);
464
519
 
465
520
  // Initialize version tracking
466
- initializeVersionJson(targetPath, isGlobal);
521
+ initializeVersionJson(isGlobal);
467
522
 
468
523
  log.header('Installation Complete!');
469
524
  log.info('');
@@ -477,10 +532,10 @@ function performFreshInstall(targetPath, sourcePath, isGlobal) {
477
532
  log.info(' • Create project-specific skills');
478
533
  log.info('');
479
534
 
480
- showCommandsHelp(targetPath);
535
+ showCommandsHelp(isGlobal);
481
536
  }
482
537
 
483
- // Perform update (preserves .5/ directory and user-created files)
538
+ // Perform update (preserves user-created files, updates .5/ data directory)
484
539
  function performUpdate(targetPath, sourcePath, isGlobal, versionInfo) {
485
540
  log.header(`Updating from ${versionInfo.installed || 'legacy'} to ${versionInfo.available}`);
486
541
  log.info('Preserving user-created commands, agents, skills, and hooks');
@@ -492,8 +547,8 @@ function performUpdate(targetPath, sourcePath, isGlobal, versionInfo) {
492
547
  mergeSettings(targetPath, sourcePath);
493
548
 
494
549
  // Update version.json
495
- const configDir = path.join(targetPath, '.5');
496
- const versionFile = path.join(configDir, 'version.json');
550
+ const dataDir = getDataPath(isGlobal);
551
+ const versionFile = path.join(dataDir, 'version.json');
497
552
 
498
553
  let versionData;
499
554
  if (fs.existsSync(versionFile)) {
@@ -511,22 +566,22 @@ function performUpdate(targetPath, sourcePath, isGlobal, versionInfo) {
511
566
  versionData.installedVersion = versionInfo.available;
512
567
  versionData.lastUpdated = new Date().toISOString();
513
568
 
514
- if (!fs.existsSync(configDir)) {
515
- fs.mkdirSync(configDir, { recursive: true });
569
+ if (!fs.existsSync(dataDir)) {
570
+ fs.mkdirSync(dataDir, { recursive: true });
516
571
  }
517
572
  fs.writeFileSync(versionFile, JSON.stringify(versionData, null, 2));
518
573
 
519
574
  // Create features directory if it doesn't exist
520
- const featuresDir = path.join(configDir, 'features');
575
+ const featuresDir = path.join(dataDir, 'features');
521
576
  if (!fs.existsSync(featuresDir)) {
522
577
  fs.mkdirSync(featuresDir, { recursive: true });
523
- log.info('📁 Feature folders now nest under .5/features/');
524
- log.info('📋 See RELEASE_NOTES.md for migration if you have in-progress features');
578
+ log.info('Feature folders nest under .5/features/');
579
+ log.info('See RELEASE_NOTES.md for migration if you have in-progress features');
525
580
  }
526
581
 
527
582
  log.header('Update Complete!');
528
583
  log.success(`Now running version ${versionInfo.available}`);
529
- showCommandsHelp(targetPath);
584
+ showCommandsHelp(isGlobal);
530
585
  }
531
586
 
532
587
  // Perform installation
@@ -538,8 +593,11 @@ function install(isGlobal, forceUpgrade = false) {
538
593
  log.info(`Target: ${targetPath}`);
539
594
  log.info(`Source: ${sourcePath}`);
540
595
 
596
+ // Migrate data from old .claude/.5/ to new .5/ location
597
+ migrateDataDir(isGlobal);
598
+
541
599
  // Check for existing installation and version
542
- const versionInfo = getVersionInfo(targetPath);
600
+ const versionInfo = getVersionInfo(targetPath, isGlobal);
543
601
 
544
602
  if (versionInfo.exists) {
545
603
  if (versionInfo.legacy) {
@@ -630,11 +688,18 @@ function uninstall() {
630
688
  }
631
689
  log.success('Removed workflow templates (preserved user-created templates)');
632
690
 
633
- // Remove config
634
- const configDir = path.join(targetPath, '.5');
635
- if (fs.existsSync(configDir)) {
636
- removeDir(configDir);
637
- log.success('Removed .5/ config directory');
691
+ // Remove data directory (.5/)
692
+ const dataDir = getDataPath(false);
693
+ if (fs.existsSync(dataDir)) {
694
+ removeDir(dataDir);
695
+ log.success('Removed .5/ data directory');
696
+ }
697
+
698
+ // Also clean up old .claude/.5/ if it still exists
699
+ const oldDataDir = path.join(targetPath, '.5');
700
+ if (fs.existsSync(oldDataDir)) {
701
+ removeDir(oldDataDir);
702
+ log.success('Removed legacy .claude/.5/ directory');
638
703
  }
639
704
 
640
705
  log.header('Uninstallation Complete!');
@@ -651,7 +716,8 @@ function main() {
651
716
 
652
717
  if (options.check) {
653
718
  const targetPath = getTargetPath(options.global);
654
- const versionInfo = getVersionInfo(targetPath);
719
+ migrateDataDir(options.global);
720
+ const versionInfo = getVersionInfo(targetPath, options.global);
655
721
 
656
722
  if (!versionInfo.exists) {
657
723
  log.info('Not installed');
@@ -72,7 +72,7 @@ The installer copies workflow files to `.claude/` directory. **It does NOT creat
72
72
  4. **Phase 4** (`/5:verify-implementation`): Verifies configuration
73
73
 
74
74
  After completing these steps, you have:
75
- - `.claude/.5/config.json` with your project settings
75
+ - `.5/config.json` with your project settings
76
76
  - `CLAUDE.md` with comprehensive project documentation
77
77
  - `.5/STRUCTURE.md`, `.5/STACK.md`, etc. with modular documentation
78
78
  - Project-specific skills in `.claude/skills/`
@@ -295,7 +295,7 @@ Map feature requirements to technical components, skills, and dependency steps.
295
295
  - **Step 2 (Logic)**: Business logic, services, handlers (sequential if needed)
296
296
  - **Step 3 (Integration)**: API routes, wiring, tests (sequential for integration)
297
297
 
298
- Note: Step count and organization is configurable in `.claude/.5/config.json`
298
+ Note: Step count and organization is configurable in `.5/config.json`
299
299
 
300
300
  6. **Implementation Plan Creation**: Claude writes an **atomic plan structure** to:
301
301
  ```
@@ -997,7 +997,7 @@ If working on multiple features:
997
997
 
998
998
  ## Configuring for Different Tech Stacks
999
999
 
1000
- The 5-phase workflow is designed to work with any technology stack. Configuration is stored in `.claude/.5/config.json` and can be customized using the `/5:configure` command.
1000
+ The 5-phase workflow is designed to work with any technology stack. Configuration is stored in `.5/config.json` and can be customized using the `/5:configure` command.
1001
1001
 
1002
1002
  ### Quick Setup
1003
1003
 
@@ -1096,7 +1096,7 @@ You can override auto-detected values in the config file.
1096
1096
 
1097
1097
  ### Further Customization
1098
1098
 
1099
- See the `/5:configure` command for interactive configuration, or manually edit `.claude/.5/config.json` to customize:
1099
+ See the `/5:configure` command for interactive configuration, or manually edit `.5/config.json` to customize:
1100
1100
  - Ticket ID patterns
1101
1101
  - Branch naming conventions
1102
1102
  - Build and test commands
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "5-phase-workflow",
3
- "version": "1.4.4",
3
+ "version": "1.5.0",
4
4
  "description": "A 5-phase feature development workflow for Claude Code",
5
5
  "bin": {
6
6
  "5-phase-workflow": "bin/install.js"
@@ -26,7 +26,7 @@ After running this command, proceed through the standard phases:
26
26
  Your job in this command:
27
27
  ✅ Analyze project (detect type, build commands, etc.)
28
28
  ✅ Gather user preferences via questions
29
- ✅ Write `.claude/.5/config.json` directly
29
+ ✅ Write `.5/config.json` directly
30
30
  ✅ Create feature spec at `.5/features/CONFIGURE/feature.md` for remaining work
31
31
  ✅ Tell user to run /5:plan-implementation CONFIGURE
32
32
 
@@ -49,7 +49,7 @@ Perform all detection silently, collecting results for Step 2.
49
49
 
50
50
  **1a. Check for existing config:**
51
51
  ```bash
52
- if [ -f ".claude/.5/config.json" ]; then
52
+ if [ -f ".5/config.json" ]; then
53
53
  # Config exists - will ask user in Step 2 what to do
54
54
  config_exists=true
55
55
  else
@@ -155,7 +155,7 @@ For each command found: record exact syntax, note variants (e.g., `test:unit`, `
155
155
 
156
156
  If "Start fresh" selected:
157
157
  - Confirm: "This will delete existing config. Are you sure?"
158
- - If confirmed: delete .claude/.5/config.json
158
+ - If confirmed: delete .5/config.json
159
159
  - Proceed to detection and questions
160
160
 
161
161
  If "Update existing configuration":
@@ -281,14 +281,14 @@ If no patterns/commands detected:
281
281
 
282
282
  ### Step 2.5: Write config.json
283
283
 
284
- Using the values gathered from Steps 1 and 2, write `.claude/.5/config.json` directly.
284
+ Using the values gathered from Steps 1 and 2, write `.5/config.json` directly.
285
285
 
286
286
  **If "Update existing" flow:** Read current config, merge updated values.
287
287
  **If "Start fresh" or new install:** Write new config.
288
288
 
289
289
  **Ensure directory exists:**
290
290
  ```bash
291
- mkdir -p .claude/.5
291
+ mkdir -p .5
292
292
  ```
293
293
 
294
294
  **Schema:**
@@ -413,7 +413,7 @@ Include only patterns/commands where user selected "Generate".
413
413
 
414
414
  Tell the user:
415
415
 
416
- 1. "Configuration saved to `.claude/.5/config.json`"
416
+ 1. "Configuration saved to `.5/config.json`"
417
417
  2. "Configuration feature planned at `.5/features/CONFIGURE/feature.md`"
418
418
  3. "Next steps:"
419
419
  - "Run `/clear` to reset context"
@@ -39,7 +39,7 @@ Parse:
39
39
 
40
40
  If the plan doesn't exist, tell the user to run `/5:plan-implementation` first.
41
41
 
42
- Also read `.claude/.5/config.json` and extract:
42
+ Also read `.5/config.json` and extract:
43
43
  - `git.autoCommit` (boolean, default `false`)
44
44
  - `git.commitMessage.pattern` (string, default `{ticket-id} {short-description}`)
45
45
 
@@ -59,6 +59,12 @@ Create `.5/features/{feature-name}/state.json`:
59
59
  }
60
60
  ```
61
61
 
62
+ Then remove the planning guard marker (planning is over, implementation is starting):
63
+
64
+ ```bash
65
+ rm -f .5/.planning-active
66
+ ```
67
+
62
68
  ### Step 3: Execute Steps
63
69
 
64
70
  Group components by step number from the plan. For each step:
@@ -37,6 +37,19 @@ After creating the spec, you are DONE.
37
37
 
38
38
  ## Process
39
39
 
40
+ ### Step 0: Activate Planning Guard
41
+
42
+ Write the planning guard marker to `.5/.planning-active` using the Write tool:
43
+
44
+ ```json
45
+ {
46
+ "phase": "plan-feature",
47
+ "startedAt": "{ISO-timestamp}"
48
+ }
49
+ ```
50
+
51
+ This activates the plan-guard hook which prevents accidental source file edits during planning. The marker is removed automatically when implementation starts (`/5:implement-feature`), expires after 4 hours, or can be cleared manually with `/5:unlock`.
52
+
40
53
  ### Step 1: Gather Feature Description
41
54
 
42
55
  Ask the developer for the feature description using AskUserQuestion:
@@ -66,6 +66,20 @@ Add emergency schedule tracking to products with date validation.
66
66
 
67
67
  ## Process
68
68
 
69
+ ### Step 0: Activate Planning Guard
70
+
71
+ Write (or refresh) the planning guard marker to `.5/.planning-active` using the Write tool:
72
+
73
+ ```json
74
+ {
75
+ "phase": "plan-implementation",
76
+ "feature": "{feature-name}",
77
+ "startedAt": "{ISO-timestamp}"
78
+ }
79
+ ```
80
+
81
+ This activates (or refreshes) the plan-guard hook which prevents accidental source file edits during planning. The marker is removed automatically when implementation starts (`/5:implement-feature`), expires after 4 hours, or can be cleared manually with `/5:unlock`.
82
+
69
83
  ### Step 1: Load Feature Spec
70
84
 
71
85
  Read `.5/features/{feature-name}/feature.md` (where `{feature-name}` is the argument provided).
@@ -51,7 +51,7 @@ Extract ticket ID using configurable pattern from config (e.g., `PROJ-\d+` or `\
51
51
 
52
52
  **Sanitize the ticket ID:** Only allow alphanumeric characters, dashes (`-`), and underscores (`_`). Strip any other characters (especially `/`, `..`, `~`, spaces). If the sanitized result is empty, ask the user for a valid ticket ID.
53
53
 
54
- Also read `.claude/.5/config.json` and extract:
54
+ Also read `.5/config.json` and extract:
55
55
  - `git.autoCommit` (boolean, default `false`)
56
56
  - `git.commitMessage.pattern` (string, default `{ticket-id} {short-description}`)
57
57
 
@@ -128,6 +128,12 @@ Create state file at `.5/features/${feature_name}/state.json` with fields: `tick
128
128
 
129
129
  Verify the file was written correctly with Read tool. If creation fails, stop and report error.
130
130
 
131
+ Then remove the planning guard marker (implementation is starting):
132
+
133
+ ```bash
134
+ rm -f .5/.planning-active
135
+ ```
136
+
131
137
  ### Step 8: Execute Implementation
132
138
 
133
139
  **Decision criteria for execution approach:**
@@ -20,7 +20,7 @@ After saving the review report, you are DONE.
20
20
 
21
21
  ## Review Tools
22
22
 
23
- Two review tools are supported (configured in `.claude/.5/config.json` field `reviewTool`):
23
+ Two review tools are supported (configured in `.5/config.json` field `reviewTool`):
24
24
 
25
25
  - **Claude** (default) — Built-in, zero setup. A fresh-context agent reviews code blind.
26
26
  - **CodeRabbit** — External CLI. Requires `coderabbit` installed and authenticated.
@@ -31,7 +31,7 @@ Both produce the same structured output format.
31
31
 
32
32
  ### Step 1: Determine Review Tool
33
33
 
34
- Read `.claude/.5/config.json` and check the `reviewTool` field.
34
+ Read `.5/config.json` and check the `reviewTool` field.
35
35
 
36
36
  - If not set or missing, default to `"claude"`
37
37
  - If `"none"`, inform user that automated review is disabled and STOP
@@ -0,0 +1,23 @@
1
+ ---
2
+ name: 5:unlock
3
+ description: Remove the planning guard lock to allow edits outside the workflow
4
+ allowed-tools: Bash
5
+ context: inherit
6
+ user-invocable: true
7
+ ---
8
+
9
+ # Unlock Planning Guard
10
+
11
+ Remove the `.planning-active` marker file that restricts Write/Edit operations during planning phases.
12
+
13
+ ## Process
14
+
15
+ Run this bash command to check and remove the marker in one step:
16
+
17
+ ```bash
18
+ if [ -f .5/.planning-active ]; then rm .5/.planning-active && echo "REMOVED"; else echo "ABSENT"; fi
19
+ ```
20
+
21
+ Based on the output, confirm to the user:
22
+ - If output contains "REMOVED": "Planning guard removed. You can now edit files freely."
23
+ - If output contains "ABSENT": "No planning guard was active. You're already free to edit files."
@@ -1,17 +1,54 @@
1
1
  ---
2
2
  name: 5:update
3
3
  description: Update the 5-Phase Workflow to the latest version
4
- allowed-tools: Bash
4
+ allowed-tools: Bash, Read, AskUserQuestion
5
5
  context: inherit
6
6
  user-invocable: true
7
7
  ---
8
8
 
9
9
  # Update 5-Phase Workflow
10
10
 
11
- Run the upgrade command to update to the latest version:
11
+ ## Step 1: Check Current Version
12
+
13
+ Read `.5/version.json` and note the current `installedVersion`.
14
+
15
+ ## Step 2: Run Upgrade
12
16
 
13
17
  ```bash
14
- npx 5-phase-workflow --upgrade
18
+ npx 5-phase-workflow@latest --upgrade
15
19
  ```
16
20
 
17
- After the upgrade completes, confirm the new version was installed by checking `.claude/.5/version.json`.
21
+ ## Step 3: Confirm Upgrade
22
+
23
+ Read `.5/version.json` again. Compare the new `installedVersion` to the previous one.
24
+
25
+ - If the version **did not change**: tell the user they're already on the latest version. Stop here.
26
+ - If the version **changed**: continue to Step 4.
27
+
28
+ ## Step 4: Show What Changed
29
+
30
+ Run `git status` to show the files modified by the upgrade. Summarize the changes for the user (e.g., "Updated 12 files in `.claude/commands/5/`, `.claude/skills/`, `.claude/hooks/`").
31
+
32
+ ## Step 5: Ask to Commit
33
+
34
+ Ask the user: "Would you like to commit the upgraded workflow files?"
35
+
36
+ Options:
37
+ 1. **Yes** - commit the changes
38
+ 2. **No** - leave changes uncommitted
39
+
40
+ If the user chooses **No**, stop here.
41
+
42
+ ## Step 6: Commit
43
+
44
+ Read `.5/config.json` if it exists and extract `git.commitMessage.pattern` (default: `{ticket-id} {short-description}`).
45
+
46
+ Build the commit message by applying the pattern:
47
+ - Replace `{ticket-id}` with an empty string (no ticket for upgrades) and trim any leading/trailing whitespace
48
+ - Replace `{short-description}` with `update 5-Phase Workflow to {new-version}`
49
+ - If the pattern is the conventional format (`feat({ticket-id}): {short-description}`), use: `chore: update 5-Phase Workflow to {new-version}`
50
+ - If no config or no pattern, use: `update 5-Phase Workflow to {new-version}`
51
+
52
+ Stage **only** the workflow-managed files shown in `git status` (inside `.claude/commands/5/`, `.claude/skills/`, `.claude/hooks/`, `.claude/templates/`, `.claude/settings.json`, and `.5/version.json`). Never use `git add .` or `git add -A`.
53
+
54
+ Create the commit. Report success to the user.
@@ -49,7 +49,7 @@ Note: feature.md not found — skipping feature completeness checks.
49
49
  This is normal for quick-implement workflows. Infrastructure and quality checks will still run.
50
50
  ```
51
51
 
52
- Also read `.claude/.5/config.json` and extract:
52
+ Also read `.5/config.json` and extract:
53
53
  - `git.autoCommit` (boolean, default `false`)
54
54
  - `git.commitMessage.pattern` (string, default `{ticket-id} {short-description}`)
55
55
 
@@ -70,7 +70,7 @@ For each component in the plan:
70
70
 
71
71
  #### 2b. Run Build
72
72
 
73
- Execute the build command from the plan (or auto-detect from `.claude/.5/config.json`):
73
+ Execute the build command from the plan (or auto-detect from `.5/config.json`):
74
74
 
75
75
  ```bash
76
76
  {build-command}
@@ -23,7 +23,7 @@ process.stdin.on('end', () => {
23
23
  });
24
24
 
25
25
  async function checkForUpdates(workspaceDir) {
26
- const versionFile = path.join(workspaceDir, '.claude', '.5', 'version.json');
26
+ const versionFile = path.join(workspaceDir, '.5', 'version.json');
27
27
 
28
28
  // Check if version.json exists
29
29
  if (!fs.existsSync(versionFile)) {
@@ -9,7 +9,7 @@ process.stdin.on('end', () => {
9
9
  try {
10
10
  const data = JSON.parse(input);
11
11
  const cwd = data.cwd || process.cwd();
12
- const configFile = path.join(cwd, '.claude', '.5', 'config.json');
12
+ const configFile = path.join(cwd, '.5', 'config.json');
13
13
 
14
14
  if (fs.existsSync(configFile)) {
15
15
  process.exit(0);
@@ -26,6 +26,12 @@ process.stdin.on('end', () => {
26
26
  }
27
27
 
28
28
  const workspaceDir = data.cwd || data.workspace?.current_dir || process.cwd();
29
+
30
+ // If no planning phase is active, allow all tools
31
+ if (!isPlanningActive(workspaceDir)) {
32
+ process.exit(0);
33
+ }
34
+
29
35
  const toolInput = data.tool_input || {};
30
36
 
31
37
  // Determine which feature is being targeted and check its state
@@ -41,7 +47,8 @@ process.stdin.on('end', () => {
41
47
  process.stderr.write(
42
48
  `BLOCKED: Only Explore agents are allowed during planning phases. ` +
43
49
  `Attempted: subagent_type="${agentType}". ` +
44
- `To use other agent types, start implementation with /5:implement-feature.`
50
+ `To use other agent types, start implementation with /5:implement-feature. ` +
51
+ `If you're not in a planning phase, run /5:unlock to clear the planning lock.`
45
52
  );
46
53
  process.exit(2);
47
54
  }
@@ -54,7 +61,8 @@ process.stdin.on('end', () => {
54
61
  `BLOCKED: ${toolName} outside .5/ is not allowed during planning phases. ` +
55
62
  `Attempted: "${filePath}". ` +
56
63
  `Planning commands may only write to .5/features/. ` +
57
- `To modify source files, start implementation with /5:implement-feature.`
64
+ `To modify source files, start implementation with /5:implement-feature. ` +
65
+ `If you're not in a planning phase, run /5:unlock to clear the planning lock.`
58
66
  );
59
67
  process.exit(2);
60
68
  }
@@ -70,23 +78,20 @@ process.stdin.on('end', () => {
70
78
  function isInsideDotFive(filePath, workspaceDir) {
71
79
  const resolved = path.resolve(workspaceDir, filePath);
72
80
  const dotFiveDir = path.join(workspaceDir, '.5');
73
- const claudeDotFiveDir = path.join(workspaceDir, '.claude', '.5');
74
81
  return resolved.startsWith(dotFiveDir + path.sep) ||
75
- resolved.startsWith(claudeDotFiveDir + path.sep) ||
76
- resolved === dotFiveDir ||
77
- resolved === claudeDotFiveDir;
82
+ resolved === dotFiveDir;
78
83
  }
79
84
 
80
85
  function getTargetFeature(toolName, toolInput, workspaceDir) {
81
86
  // Extract the feature name from the tool input context
82
- const featuresDir = path.join(workspaceDir, '.claude', '.5', 'features');
87
+ const featuresDir = path.join(workspaceDir, '.5', 'features');
83
88
 
84
89
  if (toolName === 'Write' || toolName === 'Edit') {
85
90
  // Check if the file path is inside a feature directory
86
91
  const filePath = toolInput.file_path || '';
87
92
  const resolved = path.resolve(workspaceDir, filePath);
88
93
  if (resolved.startsWith(featuresDir + path.sep)) {
89
- // Extract feature name: .claude/.5/features/{feature-name}/...
94
+ // Extract feature name: .5/features/{feature-name}/...
90
95
  const relative = resolved.slice(featuresDir.length + 1);
91
96
  const featureName = relative.split(path.sep)[0];
92
97
  if (featureName) return featureName;
@@ -118,10 +123,28 @@ function getTargetFeature(toolName, toolInput, workspaceDir) {
118
123
  return null;
119
124
  }
120
125
 
126
+ function isPlanningActive(workspaceDir) {
127
+ const markerPath = path.join(workspaceDir, '.5', '.planning-active');
128
+ if (!fs.existsSync(markerPath)) return false;
129
+ try {
130
+ const marker = JSON.parse(fs.readFileSync(markerPath, 'utf8'));
131
+ if (marker.startedAt) {
132
+ const elapsed = Date.now() - new Date(marker.startedAt).getTime();
133
+ if (elapsed > 4 * 60 * 60 * 1000) {
134
+ try { fs.unlinkSync(markerPath); } catch (e) {}
135
+ return false;
136
+ }
137
+ }
138
+ return true;
139
+ } catch (e) {
140
+ return true; // Unreadable marker → fail-safe, assume active
141
+ }
142
+ }
143
+
121
144
  function isFeatureInImplementationMode(workspaceDir, featureName) {
122
145
  // Check if this specific feature has a state.json (created in Phase 3)
123
146
  const stateFile = path.join(
124
- workspaceDir, '.claude', '.5', 'features', featureName, 'state.json'
147
+ workspaceDir, '.5', 'features', featureName, 'state.json'
125
148
  );
126
149
  return fs.existsSync(stateFile);
127
150
  }
@@ -46,7 +46,7 @@ process.stdin.on('end', () => {
46
46
  // Check for available update
47
47
  let updateIndicator = '';
48
48
  try {
49
- const versionFile = path.join(dir, '.claude', '.5', 'version.json');
49
+ const versionFile = path.join(dir, '.5', 'version.json');
50
50
  const versionData = JSON.parse(fs.readFileSync(versionFile, 'utf8'));
51
51
  const latest = versionData.latestAvailableVersion;
52
52
  const installed = versionData.installedVersion;
@@ -17,7 +17,7 @@ This skill executes build tasks with auto-detection of the build system and suff
17
17
 
18
18
  The skill automatically detects the build system using:
19
19
 
20
- 1. **Config file** (`.claude/.5/config.json`) - if `build.command` is specified
20
+ 1. **Config file** (`.5/config.json`) - if `build.command` is specified
21
21
  2. **Auto-detection** - by examining project files:
22
22
  - `package.json` → npm/yarn/pnpm
23
23
  - `build.gradle` or `build.gradle.kts` → Gradle
@@ -46,7 +46,7 @@ When invoked, the skill expects:
46
46
 
47
47
  ### 1. Load Configuration
48
48
 
49
- Read `.claude/.5/config.json` if it exists:
49
+ Read `.5/config.json` if it exists:
50
50
 
51
51
  ```json
52
52
  {
@@ -17,7 +17,7 @@ This skill executes test tasks with auto-detection of the test runner and suffic
17
17
 
18
18
  The skill automatically detects the test runner using:
19
19
 
20
- 1. **Config file** (`.claude/.5/config.json`) - if `build.testCommand` is specified
20
+ 1. **Config file** (`.5/config.json`) - if `build.testCommand` is specified
21
21
  2. **Auto-detection** - by examining project files and package.json scripts:
22
22
  - `package.json` with jest/vitest/mocha → npm test
23
23
  - `pytest.ini` or test files → pytest
@@ -49,7 +49,7 @@ When invoked, the skill expects:
49
49
 
50
50
  ### 1. Load Configuration
51
51
 
52
- Read `.claude/.5/config.json` if it exists:
52
+ Read `.5/config.json` if it exists:
53
53
 
54
54
  ```json
55
55
  {