5-phase-workflow 1.5.4 → 1.6.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/bin/install.js CHANGED
@@ -273,6 +273,7 @@ function getWorkflowManagedFiles() {
273
273
  hooks: [
274
274
  'statusline.js',
275
275
  'check-updates.js',
276
+ 'check-reconfig.js',
276
277
  'plan-guard.js',
277
278
  'config-guard.js'
278
279
  ],
@@ -491,6 +492,7 @@ function showCommandsHelp(isGlobal) {
491
492
  log.info(' /5:verify-implementation - Verify implementation (Phase 4)');
492
493
  log.info(' /5:review-code - Code review (Phase 5)');
493
494
  log.info(' /5:configure - Interactive project setup');
495
+ log.info(' /5:reconfigure - Refresh docs/skills (no Q&A)');
494
496
  log.info(' /5:unlock - Remove planning guard lock');
495
497
  log.info('');
496
498
  log.info(`Config file: ${path.join(getDataPath(isGlobal), 'config.json')}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "5-phase-workflow",
3
- "version": "1.5.4",
3
+ "version": "1.6.0",
4
4
  "description": "A 5-phase feature development workflow for Claude Code",
5
5
  "bin": {
6
6
  "5-phase-workflow": "bin/install.js"
@@ -279,6 +279,12 @@ If no patterns/commands detected:
279
279
  - Inform user: "No common patterns detected. Would you like to specify patterns manually?"
280
280
  - Allow manual entry of pattern names/locations or command names
281
281
 
282
+ **2l. Git-ignore `.5/features/` folder:**
283
+ - "The `.5/features/` folder will contain feature specs, implementation plans, and state files. Would you like to add it to `.gitignore`?"
284
+ - Options:
285
+ 1. "Yes, add to .gitignore (recommended)" — workflow artifacts stay local, not tracked in version control
286
+ 2. "No, track in git" — useful if you want to share specs and plans with your team
287
+
282
288
  ### Step 2.5: Write config.json
283
289
 
284
290
  Using the values gathered from Steps 1 and 2, write `.5/config.json` directly.
@@ -330,12 +336,37 @@ mkdir -p .5
330
336
  "commitMessage": {
331
337
  "pattern": "{ticket-id} {short-description}"
332
338
  }
339
+ },
340
+ "dotFiveFolder": {
341
+ "gitignore": true
333
342
  }
334
343
  }
335
344
  ```
336
345
 
337
346
  Fill all values from user responses. Write with pretty-printed JSON. Read back to verify correctness.
338
347
 
348
+ **Update `.5/version.json` with configure timestamp:**
349
+
350
+ After writing config.json, update `.5/version.json` so the reconfigure reminder can track staleness:
351
+ 1. Read `.5/version.json` (if it exists)
352
+ 2. Set `configuredAt` to the current ISO timestamp (`new Date().toISOString()`)
353
+ 3. Set `configuredAtCommit` to the current short commit hash (run `git rev-parse --short HEAD`)
354
+ 4. Write back `.5/version.json` preserving all other fields
355
+
356
+ **Apply `.gitignore` if selected:**
357
+
358
+ If the user chose to gitignore the `.5/features/` folder:
359
+ 1. Check if `.gitignore` exists in the project root
360
+ 2. If it exists, check if `.5/features/` is already listed — if not, append `.5/features/` on a new line
361
+ 3. If `.gitignore` does not exist, create it with `.5/features/` as the first entry
362
+ 4. Inform the user: "Added `.5/features/` to `.gitignore`"
363
+
364
+ **Always gitignore `.5/.reconfig-reminder`:**
365
+
366
+ Ensure `.5/.reconfig-reminder` is gitignored (it's a transient runtime flag that should never be committed):
367
+ 1. Check if `.gitignore` exists in the project root — create it if not
368
+ 2. Check if `.5/.reconfig-reminder` is already listed — if not, append `.5/.reconfig-reminder` on a new line
369
+
339
370
  ### Step 3: Create Feature Spec
340
371
 
341
372
  Write `.5/features/CONFIGURE/feature.md` containing all gathered data:
@@ -0,0 +1,155 @@
1
+ ---
2
+ name: 5:reconfigure
3
+ description: Lightweight refresh of project documentation and skills without full Q&A. Re-detects codebase changes, regenerates .5/*.md docs, updates CLAUDE.md, and refreshes all skills.
4
+ allowed-tools: Read, Write, Bash, Glob, Grep, Task, AskUserQuestion
5
+ context: fork
6
+ user-invocable: true
7
+ ---
8
+
9
+ # Reconfigure (Lightweight Refresh)
10
+
11
+ ## Overview
12
+
13
+ Single-command refresh that skips the full Q&A of `/5:configure`. Re-detects codebase state, regenerates documentation and skills based on existing `config.json` preferences.
14
+
15
+ **When to use which:**
16
+
17
+ | Scenario | Command |
18
+ |----------|---------|
19
+ | First-time setup | `/5:configure` |
20
+ | Change preferences (ticket pattern, review tool, etc.) | `/5:configure` |
21
+ | Codebase evolved, refresh docs/skills | **`/5:reconfigure`** |
22
+ | Add new skill patterns | `/5:configure` |
23
+
24
+ ## ⚠️ CRITICAL SCOPE CONSTRAINT
25
+
26
+ **THIS COMMAND REGENERATES DOCS AND SKILLS. IT DOES NOT CHANGE USER PREFERENCES.**
27
+
28
+ Your job:
29
+ ✅ Validate that config.json exists
30
+ ✅ Re-detect codebase patterns and commands (same as configure Steps 1b-1h)
31
+ ✅ Compare detected state with config.json skill selections
32
+ ✅ Show summary and ask for confirmation
33
+ ✅ Invoke configure-project skill in refresh mode
34
+ ✅ Update version.json with artifacts and timestamps
35
+ ✅ Clean up .reconfig-reminder flag
36
+ ✅ Report what was updated
37
+
38
+ Your job is NOT:
39
+ ❌ Ask preference questions (ticket pattern, branch convention, review tool, etc.)
40
+ ❌ Modify config.json preferences (only the `skills` section may be updated if user confirms new patterns)
41
+ ❌ Skip confirmation — always show what will be regenerated
42
+
43
+ ## Process
44
+
45
+ ### Step 1: Validate Config
46
+
47
+ Read `.5/config.json`. If it does not exist:
48
+ - Tell the user: "No configuration found. Please run `/5:configure` first to set up your project."
49
+ - **EXIT IMMEDIATELY**
50
+
51
+ Read `.5/version.json` for current state (configuredAt, configuredAtCommit).
52
+
53
+ ### Step 2: Re-detect Codebase State
54
+
55
+ Perform the same detection as configure Steps 1b-1h:
56
+
57
+ **2a. Detect project type** — same table as configure Step 1b (package.json deps, build files, etc.)
58
+
59
+ **2b. Detect build/test commands** — same as configure Step 1c
60
+
61
+ **2c. Detect codebase patterns** — same as configure Step 1g:
62
+ - Scan for architectural patterns (Controllers, Services, Components, etc.)
63
+ - Use both suffix-based and directory-based globs
64
+ - For each pattern: count files, identify location, sample filename
65
+
66
+ **2d. Detect runnable commands** — same as configure Step 1h:
67
+ - Scan package.json scripts, Makefile targets, etc.
68
+ - Categorize: Build, Test, Lint, Format, Type Check, etc.
69
+
70
+ **2e. Scan existing skills** — list ALL skills in `.claude/skills/`:
71
+ - Read each skill's SKILL.md frontmatter
72
+ - Categorize as workflow-generated (create-*, run-*) or user-created
73
+
74
+ ### Step 3: Compare and Prepare Summary
75
+
76
+ Use the existing skills in `.claude/skills/` (from Step 2e) as the source of truth — not config.json. Compare what's installed with what's detected in the codebase:
77
+
78
+ - **Existing `create-*` skills** — extract the pattern name from each (e.g., `create-controller` → `controller`)
79
+ - **Existing `run-*` skills** — extract the command name from each (e.g., `run-tests` → `tests`)
80
+ - **New patterns**: detected in codebase (Step 2c) but no matching `create-*` skill exists → offer to create
81
+ - **Stale patterns**: a `create-*` skill exists but the pattern is no longer detected in the codebase → offer to remove or keep
82
+ - **New commands**: detected (Step 2d) but no matching `run-*` skill exists → offer to create
83
+ - **Stale commands**: a `run-*` skill exists but the command is no longer detected → offer to remove or keep
84
+ - **User-created skills** (not matching `create-*` or `run-*` naming) → always refresh with current conventions, never remove
85
+
86
+ ### Step 4: Confirm with User
87
+
88
+ Use `AskUserQuestion` to show a summary and get confirmation. Present:
89
+
90
+ 1. **Documentation files that will be rewritten** — list all 7 `.5/*.md` files + CLAUDE.md
91
+ 2. **Skills that will be refreshed** — list ALL skills found in `.claude/skills/` (both workflow-generated and user-created)
92
+ 3. **New patterns detected** (if any) — "These patterns were found in your codebase but don't have skills yet: [list]. Create skills for them?"
93
+ 4. **Stale patterns** (if any) — "These patterns are in your config but weren't found in the codebase: [list]. Remove them?"
94
+
95
+ Options:
96
+ - "Proceed with refresh" — regenerate everything as shown
97
+ - "Cancel" — exit without changes
98
+
99
+ If there are new or stale patterns, use additional `AskUserQuestion` calls with multiSelect to let the user pick which new patterns to add and which stale patterns to remove.
100
+
101
+ New skills will be created and stale skills removed based on the user's choices.
102
+
103
+ ### Step 5: Regenerate
104
+
105
+ Invoke the `configure-project` skill in **refresh mode** via the Task tool:
106
+
107
+ ```
108
+ Task prompt: "Run configure-project skill in REFRESH MODE.
109
+
110
+ Refresh ALL existing skills in .claude/skills/:
111
+ - Existing create-* skills: [list from Step 2e]
112
+ - Existing run-* skills: [list from Step 2e]
113
+ - User-created skills: [list from Step 2e]
114
+ - New skills to create: [list from user confirmation, if any]
115
+ - Skills to remove: [list from user confirmation, if any]
116
+
117
+ Re-analyze the entire codebase (A1 analysis) and:
118
+ 1. Rewrite all 7 .5/*.md documentation files
119
+ 2. Update CLAUDE.md (preserve user-written sections)
120
+ 3. Refresh ALL skills in .claude/skills/ — read current conventions from codebase and update each skill
121
+ 4. Create new skills for newly-added patterns
122
+ 5. Remove skills the user chose to drop"
123
+ ```
124
+
125
+ Use `subagent_type: "general-purpose"` for the Task.
126
+
127
+ ### Step 6: Track
128
+
129
+ After the skill completes, update `.5/version.json`:
130
+
131
+ 1. Read current version.json
132
+ 2. Set `configuredAt` to current ISO timestamp
133
+ 3. Set `configuredAtCommit` to current short commit hash (`git rev-parse --short HEAD`)
134
+ 4. Write back version.json preserving all other fields
135
+
136
+ ### Step 7: Clean Up
137
+
138
+ Remove the `.5/.reconfig-reminder` flag file if it exists:
139
+ ```bash
140
+ rm -f .5/.reconfig-reminder
141
+ ```
142
+
143
+ ### Step 8: Report
144
+
145
+ Show the user a summary:
146
+ - List of documentation files updated
147
+ - List of skills refreshed
148
+ - List of new skills created (if any)
149
+ - List of skills removed (if any)
150
+ - Timestamp of reconfiguration
151
+ - Suggest running `/clear` to reset context
152
+
153
+ ## Related Documentation
154
+ - [configure command](./configure.md) — full Q&A configuration
155
+ - [configure-project skill](../../skills/configure-project/SKILL.md) — the skill that does the heavy lifting
@@ -0,0 +1,88 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+ const { execSync } = require('child_process');
6
+
7
+ // Read JSON from stdin
8
+ let input = '';
9
+ process.stdin.setEncoding('utf8');
10
+ process.stdin.on('data', chunk => input += chunk);
11
+ process.stdin.on('end', () => {
12
+ try {
13
+ let workspaceDir = process.cwd();
14
+ if (input.trim()) {
15
+ const data = JSON.parse(input);
16
+ workspaceDir = data.cwd || data.workspace?.current_dir || workspaceDir;
17
+ }
18
+
19
+ checkReconfigure(workspaceDir);
20
+ } catch (e) {
21
+ // Silent failure - don't block on errors
22
+ process.exit(0);
23
+ }
24
+ });
25
+
26
+ function checkReconfigure(workspaceDir) {
27
+ const versionFile = path.join(workspaceDir, '.5', 'version.json');
28
+ const flagFile = path.join(workspaceDir, '.5', '.reconfig-reminder');
29
+
30
+ if (!fs.existsSync(versionFile)) {
31
+ process.exit(0);
32
+ }
33
+
34
+ let versionData;
35
+ try {
36
+ versionData = JSON.parse(fs.readFileSync(versionFile, 'utf8'));
37
+ } catch (e) {
38
+ process.exit(0);
39
+ }
40
+
41
+ const { configuredAt, configuredAtCommit } = versionData;
42
+
43
+ // No configure data yet - skip (user hasn't run /5:configure)
44
+ if (!configuredAt) {
45
+ process.exit(0);
46
+ }
47
+
48
+ // Calculate days elapsed
49
+ let daysElapsed = 0;
50
+ try {
51
+ daysElapsed = Math.floor((Date.now() - new Date(configuredAt).getTime()) / (1000 * 60 * 60 * 24));
52
+ } catch (e) {
53
+ process.exit(0);
54
+ }
55
+
56
+ // Count commits since configured
57
+ let commitCount = 0;
58
+ if (configuredAtCommit) {
59
+ try {
60
+ const result = execSync(`git rev-list --count ${configuredAtCommit}..HEAD`, {
61
+ cwd: workspaceDir,
62
+ timeout: 3000,
63
+ encoding: 'utf8',
64
+ stdio: ['pipe', 'pipe', 'pipe']
65
+ });
66
+ commitCount = parseInt(result.trim(), 10) || 0;
67
+ } catch (e) {
68
+ // Git command failed (commit not found, not a repo, etc.) - skip
69
+ }
70
+ }
71
+
72
+ // Write or remove temp flag file (never touches version.json)
73
+ const COMMIT_THRESHOLD = 50;
74
+ const DAYS_THRESHOLD = 30;
75
+ const shouldRemind = daysElapsed >= DAYS_THRESHOLD || commitCount >= COMMIT_THRESHOLD;
76
+
77
+ try {
78
+ if (shouldRemind) {
79
+ fs.writeFileSync(flagFile, '1');
80
+ } else if (fs.existsSync(flagFile)) {
81
+ fs.unlinkSync(flagFile);
82
+ }
83
+ } catch (e) {
84
+ // Can't write/delete temp file - skip
85
+ }
86
+
87
+ process.exit(0);
88
+ }
@@ -43,22 +43,31 @@ process.stdin.on('end', () => {
43
43
  // Shorten directory path for display
44
44
  const shortDir = dir.replace(os.homedir(), '~');
45
45
 
46
- // Check for available update
46
+ // Check for available update and reconfigure reminder
47
47
  let updateIndicator = '';
48
+ let reconfigIndicator = '';
48
49
  try {
49
50
  const versionFile = path.join(dir, '.5', 'version.json');
50
51
  const versionData = JSON.parse(fs.readFileSync(versionFile, 'utf8'));
52
+
53
+ // Update check
51
54
  const latest = versionData.latestAvailableVersion;
52
55
  const installed = versionData.installedVersion;
53
56
  if (latest && installed && compareVersions(installed, latest) < 0) {
54
57
  updateIndicator = ` | \x1b[33m↑${latest} → /5:update\x1b[0m`;
55
58
  }
59
+
60
+ // Reconfigure check (reads flag file in .5/, gitignored)
61
+ const flagFile = path.join(dir, '.5', '.reconfig-reminder');
62
+ if (fs.existsSync(flagFile)) {
63
+ reconfigIndicator = ` | \x1b[35m↻ /5:reconfigure\x1b[0m`;
64
+ }
56
65
  } catch (e) {
57
66
  // No version file or parse error — no indicator
58
67
  }
59
68
 
60
- // Build and output statusline: model | directory | context | update
61
- const statusline = `\x1b[36m${model}\x1b[0m | \x1b[90m${shortDir}\x1b[0m${ctx}${updateIndicator}`;
69
+ // Build and output statusline: model | directory | context | update | reconfig
70
+ const statusline = `\x1b[36m${model}\x1b[0m | \x1b[90m${shortDir}\x1b[0m${ctx}${updateIndicator}${reconfigIndicator}`;
62
71
  process.stdout.write(statusline);
63
72
 
64
73
  } catch (e) {
package/src/settings.json CHANGED
@@ -14,6 +14,16 @@
14
14
  "timeout": 10
15
15
  }
16
16
  ]
17
+ },
18
+ {
19
+ "matcher": "startup",
20
+ "hooks": [
21
+ {
22
+ "type": "command",
23
+ "command": "node .claude/hooks/check-reconfig.js",
24
+ "timeout": 10
25
+ }
26
+ ]
17
27
  }
18
28
  ],
19
29
  "PreToolUse": [
@@ -22,6 +22,29 @@ Note: config.json is written directly by `/5:configure` during the Q&A phase.
22
22
 
23
23
  ---
24
24
 
25
+ ## Modes
26
+
27
+ This skill supports two modes. The analysis (A1), template filling (A2-A3), CLAUDE.md update (A4-A5), and skill generation (B) logic is the same in both modes — only the **input source** changes.
28
+
29
+ ### Full Mode (default)
30
+
31
+ Used by `/5:configure` → `/5:implement-feature CONFIGURE` flow.
32
+
33
+ - **Input:** Pattern/command selections from feature spec (`.5/features/CONFIGURE/feature.md`)
34
+ - **Behavior:** Creates everything from scratch based on feature spec requirements
35
+
36
+ ### Refresh Mode
37
+
38
+ Used by `/5:reconfigure` for lightweight refresh.
39
+
40
+ - **Input:** The Task prompt lists which skills to refresh, create, and remove (determined by `/5:reconfigure` after scanning `.claude/skills/` and comparing with detected codebase patterns)
41
+ - **Behavior:** Re-analyzes codebase, overwrites docs and refreshes/creates/removes skills as specified
42
+ - **Trigger:** Task prompt includes "REFRESH MODE"
43
+
44
+ In both modes, the analysis and generation logic is identical — only where the skill list comes from differs.
45
+
46
+ ---
47
+
25
48
  ## A. Analyze Codebase and Create/Update CLAUDE.md
26
49
 
27
50
  **Process:**