@gravirei/reis 2.6.0 → 2.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,55 @@
1
1
  # Changelog
2
2
 
3
+ ## [2.6.2] - 2026-01-26
4
+
5
+ ### 🐛 Critical Bug Fix
6
+
7
+ #### Subagents Not Installed/Updated on `npm install`
8
+ - **Added `postinstall` script** to automatically install REIS files when package is installed
9
+ - **Subagents now always update** to latest version (previously skipped if files existed)
10
+ - **Fixed missing `reis_plan_reviewer.md`** subagent not being installed
11
+ - Added `--silent` flag support for clean postinstall output
12
+
13
+ ### 📦 What Changed
14
+
15
+ - `npm install -g @gravirei/reis` now automatically installs all subagents
16
+ - Subagent files are always overwritten to stay in sync with package version
17
+ - Silent mode: no output during `npm install` (cleaner experience)
18
+
19
+ ---
20
+
21
+ ## [2.6.1] - 2026-01-26
22
+
23
+ ### 🐛 Bug Fixes
24
+
25
+ #### Fixed `reis update` Command
26
+ - **Fixed crash** when a new version was available (missing `showWarning` function)
27
+ - Command now works correctly for all scenarios
28
+
29
+ ### ✨ UI Improvements
30
+
31
+ #### Redesigned `reis update` Command
32
+ - Added welcome banner (consistent with `reis help`)
33
+ - Shows current version first, then checks for updates
34
+ - Beautiful bordered info boxes for status display
35
+ - **User confirmation prompt** before downloading updates
36
+ - Clear success/error messages with helpful instructions
37
+ - Non-interactive mode fallback with manual instructions
38
+
39
+ #### Redesigned `reis whats-new` Command
40
+ - Added welcome banner (consistent with `reis help`)
41
+ - **Now parses actual `CHANGELOG.md`** instead of hardcoded content
42
+ - Shows up to 3 major sections with smart truncation
43
+ - Displays bullet points, headers, and code examples nicely
44
+ - Fallback message if version not found in changelog
45
+ - Links to full changelog and documentation
46
+
47
+ ### 🔧 Internal Changes
48
+
49
+ - Added `showWarning` function to `lib/utils/command-helpers.js`
50
+
51
+ ---
52
+
3
53
  ## [2.6.0] - 2026-01-26
4
54
 
5
55
  ### 🎯 Major Features
@@ -1,5 +1,6 @@
1
- const { showInfo, showSuccess, showError, showWarning, getVersion } = require('../utils/command-helpers.js');
1
+ const chalk = require('chalk');
2
2
  const { execSync } = require('child_process');
3
+ const { getVersion } = require('../utils/command-helpers.js');
3
4
 
4
5
  /**
5
6
  * Update command - check for and install REIS updates
@@ -8,68 +9,130 @@ const { execSync } = require('child_process');
8
9
  module.exports = async function(args) {
9
10
  const currentVersion = getVersion();
10
11
  const packageName = '@gravirei/reis';
12
+ const w = chalk.bold.white;
13
+ const g = chalk.green;
14
+ const y = chalk.yellow;
15
+ const r = chalk.red;
16
+ const c = chalk.cyan;
17
+
18
+ // ASCII Art Banner
19
+ console.log(w(`
20
+ ██████╗ ███████╗██╗███████╗
21
+ ██╔══██╗██╔════╝██║██╔════╝
22
+ ██████╔╝█████╗ ██║███████╗
23
+ ██╔══██╗██╔══╝ ██║╚════██║
24
+ ██║ ██║███████╗██║███████║
25
+ ╚═╝ ╚═╝╚══════╝╚═╝╚══════╝
26
+ `));
11
27
 
28
+ console.log(w(' REIS - Roadmap Execution & Implementation System'));
29
+ console.log(w(' Specially designed for Atlassian Rovo Dev'));
12
30
  console.log('');
13
- showInfo('🔍 Checking for REIS updates...');
31
+ console.log(w('● Update Manager'));
32
+ console.log(w(' ───────────────'));
14
33
  console.log('');
15
- showInfo(` Current version: v${currentVersion}`);
16
-
34
+ console.log(w(` Current Version: v${currentVersion}`));
35
+ console.log('');
36
+ console.log(c(' 🔍 Checking for updates...'));
37
+ console.log('');
38
+
17
39
  try {
18
40
  // Check latest version from npm
19
41
  const latestVersion = execSync(`npm view ${packageName} version 2>/dev/null`, {
20
42
  encoding: 'utf-8'
21
43
  }).trim();
22
-
23
- showInfo(` Latest version: v${latestVersion}`);
24
- console.log('');
25
-
44
+
26
45
  if (currentVersion === latestVersion) {
27
- showSuccess('✅ You are already on the latest version!');
46
+ // Already up to date
47
+ console.log(w(' ┌──────────────────────────────────────────────────────┐'));
48
+ console.log(w(' │ ') + g('✅ You\'re up to date!') + w(' │'));
49
+ console.log(w(' │ │'));
50
+ console.log(w(' │ Installed: ') + g(`v${currentVersion}`) + w(' (latest)' + ' '.repeat(Math.max(0, 22 - currentVersion.length))) + w('│'));
51
+ console.log(w(' └──────────────────────────────────────────────────────┘'));
28
52
  console.log('');
29
53
  return 0;
30
54
  }
31
-
55
+
32
56
  // New version available
33
- showWarning(`📦 New version available: v${currentVersion} → v${latestVersion}`);
57
+ console.log(w(` Latest Version: v${latestVersion}`));
34
58
  console.log('');
35
- showInfo(' Updating REIS...');
59
+ console.log(w(' ┌──────────────────────────────────────────────────────┐'));
60
+ console.log(w(' │ ') + y('📦 New version available!') + w(' │'));
61
+ console.log(w(' │ │'));
62
+ const versionLine = `v${currentVersion} → v${latestVersion}`;
63
+ const padding = Math.max(0, 38 - versionLine.length);
64
+ console.log(w(' │ ') + c(versionLine) + w(' '.repeat(padding) + '│'));
65
+ console.log(w(' └──────────────────────────────────────────────────────┘'));
36
66
  console.log('');
37
-
67
+
68
+ // Ask user for confirmation
69
+ const inquirer = require('inquirer');
38
70
  try {
39
- // Try global update
40
- execSync(`npm install -g ${packageName}@latest`, {
41
- stdio: 'inherit',
42
- encoding: 'utf-8'
43
- });
44
-
45
- console.log('');
46
- showSuccess(`✅ Successfully updated to v${latestVersion}!`);
47
- console.log('');
48
- showInfo(' Run "reis whats-new" to see what\'s changed.');
71
+ const { confirmUpdate } = await inquirer.prompt([
72
+ {
73
+ type: 'confirm',
74
+ name: 'confirmUpdate',
75
+ message: 'Do you want to update REIS now?',
76
+ default: true
77
+ }
78
+ ]);
79
+
49
80
  console.log('');
50
-
51
- } catch (installError) {
52
- // If global install fails, suggest manual update
81
+
82
+ if (!confirmUpdate) {
83
+ console.log(c(' ℹ Update skipped. Run "reis update" anytime to update.'));
84
+ console.log('');
85
+ return 0;
86
+ }
87
+
88
+ // User confirmed, proceed with update
89
+ console.log(c(` ⏳ Downloading and installing v${latestVersion}...`));
53
90
  console.log('');
54
- showError('❌ Automatic update failed (may need sudo/admin privileges)');
91
+
92
+ try {
93
+ // Try global update
94
+ execSync(`npm install -g ${packageName}@latest`, {
95
+ stdio: 'inherit',
96
+ encoding: 'utf-8'
97
+ });
98
+
99
+ console.log('');
100
+ console.log(g(` ✓ Successfully updated to v${latestVersion}!`));
101
+ console.log('');
102
+ console.log(c(' Run "reis whats-new" to see what\'s changed.'));
103
+ console.log('');
104
+ return 0;
105
+
106
+ } catch (installError) {
107
+ // If global install fails, suggest manual update
108
+ console.log('');
109
+ console.log(r(' ❌ Update failed (may need elevated privileges)'));
110
+ console.log('');
111
+ console.log(w(' Try manually:'));
112
+ console.log(c(` $ sudo npm install -g ${packageName}@latest`));
113
+ console.log('');
114
+ return 1;
115
+ }
116
+
117
+ } catch (promptError) {
118
+ // Non-interactive mode - show manual instructions
119
+ console.log(y(' Non-interactive mode detected.'));
55
120
  console.log('');
56
- showInfo(' Try manually:');
57
- showInfo(` $ sudo npm install -g ${packageName}@latest`);
58
- showInfo(' or');
59
- showInfo(` $ npm install -g ${packageName}@latest --force`);
121
+ console.log(w(' To update manually, run:'));
122
+ console.log(c(` $ npm install -g ${packageName}@latest`));
60
123
  console.log('');
61
- return 1;
124
+ return 0;
62
125
  }
63
-
126
+
64
127
  } catch (error) {
65
- showError('❌ Failed to check for updates');
66
- showInfo(' Check your internet connection and try again.');
128
+ // Network error or npm not available
129
+ console.log(r(' Could not check for updates'));
67
130
  console.log('');
68
- showInfo(' Manual update:');
69
- showInfo(` $ npm install -g ${packageName}@latest`);
131
+ console.log(w(' Please check your internet connection and try again.'));
132
+ console.log('');
133
+ console.log(w(' Manual update:'));
134
+ console.log(c(` $ npm install -g ${packageName}@latest`));
70
135
  console.log('');
71
136
  return 1;
72
137
  }
73
-
74
- return 0;
75
138
  };
@@ -1,4 +1,116 @@
1
- const { showInfo, getVersion } = require('../utils/command-helpers.js');
1
+ const chalk = require('chalk');
2
+ const fs = require('fs');
3
+ const path = require('path');
4
+ const { getVersion } = require('../utils/command-helpers.js');
5
+
6
+ /**
7
+ * Parse CHANGELOG.md and extract changes for a specific version
8
+ * @param {string} version - Version to find (e.g., "2.6.0")
9
+ * @returns {object} - { found: boolean, title: string, sections: [{header, items}] }
10
+ */
11
+ function parseChangelog(version) {
12
+ const changelogPaths = [
13
+ path.join(__dirname, '../../CHANGELOG.md'),
14
+ path.join(process.cwd(), 'CHANGELOG.md')
15
+ ];
16
+
17
+ let changelogContent = null;
18
+ for (const p of changelogPaths) {
19
+ if (fs.existsSync(p)) {
20
+ changelogContent = fs.readFileSync(p, 'utf-8');
21
+ break;
22
+ }
23
+ }
24
+
25
+ if (!changelogContent) {
26
+ return { found: false, title: '', sections: [] };
27
+ }
28
+
29
+ // Find the section for this version
30
+ const versionRegex = new RegExp(`^## \\[${version.replace(/\./g, '\\.')}\\].*$`, 'm');
31
+ const match = changelogContent.match(versionRegex);
32
+
33
+ if (!match) {
34
+ return { found: false, title: '', sections: [] };
35
+ }
36
+
37
+ const startIndex = match.index;
38
+ const title = match[0];
39
+
40
+ // Find the next version section (or end of file)
41
+ const nextVersionRegex = /^## \[/m;
42
+ const afterStart = changelogContent.substring(startIndex + title.length);
43
+ const nextMatch = afterStart.match(nextVersionRegex);
44
+
45
+ const endIndex = nextMatch
46
+ ? startIndex + title.length + nextMatch.index
47
+ : changelogContent.length;
48
+
49
+ const versionContent = changelogContent.substring(startIndex + title.length, endIndex).trim();
50
+
51
+ // Parse sections (### headers)
52
+ const sections = [];
53
+ const sectionRegex = /^### (.+)$/gm;
54
+ let lastIndex = 0;
55
+ let currentSection = null;
56
+ let sectionMatch;
57
+
58
+ while ((sectionMatch = sectionRegex.exec(versionContent)) !== null) {
59
+ if (currentSection) {
60
+ currentSection.content = versionContent.substring(lastIndex, sectionMatch.index).trim();
61
+ sections.push(currentSection);
62
+ }
63
+ currentSection = { header: sectionMatch[1], content: '' };
64
+ lastIndex = sectionMatch.index + sectionMatch[0].length;
65
+ }
66
+
67
+ if (currentSection) {
68
+ currentSection.content = versionContent.substring(lastIndex).trim();
69
+ sections.push(currentSection);
70
+ }
71
+
72
+ // If no ### sections, treat entire content as one section
73
+ if (sections.length === 0 && versionContent) {
74
+ sections.push({ header: 'Changes', content: versionContent });
75
+ }
76
+
77
+ return { found: true, title, sections };
78
+ }
79
+
80
+ /**
81
+ * Format and display a section's content
82
+ * @param {string} content - Section content
83
+ * @param {function} w - White chalk function
84
+ * @param {function} c - Cyan chalk function
85
+ */
86
+ function displaySectionContent(content, w, c) {
87
+ const lines = content.split('\n');
88
+
89
+ for (const line of lines) {
90
+ // Skip code blocks for cleaner display
91
+ if (line.startsWith('```')) continue;
92
+
93
+ // Handle bullet points
94
+ if (line.startsWith('- ') || line.startsWith('* ')) {
95
+ console.log(c(' •') + w(' ' + line.substring(2)));
96
+ }
97
+ // Handle sub-headers (####)
98
+ else if (line.startsWith('#### ')) {
99
+ console.log('');
100
+ console.log(w(' ' + line.substring(5)));
101
+ }
102
+ // Handle code in backticks (command examples)
103
+ else if (line.includes('`') && !line.startsWith('```')) {
104
+ // Display inline code lines
105
+ const formatted = line.replace(/`([^`]+)`/g, chalk.cyan('$1'));
106
+ console.log(w(' ' + formatted));
107
+ }
108
+ // Skip empty lines at start, show others
109
+ else if (line.trim()) {
110
+ console.log(w(' ' + line));
111
+ }
112
+ }
113
+ }
2
114
 
3
115
  /**
4
116
  * Whats-new command - show recent changes and features
@@ -6,14 +118,78 @@ const { showInfo, getVersion } = require('../utils/command-helpers.js');
6
118
  */
7
119
  module.exports = function(args) {
8
120
  const version = getVersion();
121
+ const w = chalk.bold.white;
122
+ const g = chalk.green;
123
+ const c = chalk.cyan;
124
+ const y = chalk.yellow;
125
+
126
+ // ASCII Art Banner
127
+ console.log(w(`
128
+ ██████╗ ███████╗██╗███████╗
129
+ ██╔══██╗██╔════╝██║██╔════╝
130
+ ██████╔╝█████╗ ██║███████╗
131
+ ██╔══██╗██╔══╝ ██║╚════██║
132
+ ██║ ██║███████╗██║███████║
133
+ ╚═╝ ╚═╝╚══════╝╚═╝╚══════╝
134
+ `));
9
135
 
10
- showInfo(`REIS v${version} - What's New`);
11
- showInfo('');
12
- showInfo('• Initial release');
13
- showInfo(' 29 commands for systematic development');
14
- showInfo(' Parallel subagent execution (up to 4 simultaneous)');
15
- showInfo('• Fresh context per task (200k tokens)');
16
- showInfo('• Transformed from GSD for Rovo Dev');
17
- showInfo('');
18
- showInfo('Full documentation: ~/.rovodev/reis/README.md');
136
+ console.log(w(' REIS - Roadmap Execution & Implementation System'));
137
+ console.log(w(' Specially designed for Atlassian Rovo Dev'));
138
+ console.log('');
139
+ console.log(w('● What\'s New in v' + version));
140
+ console.log(w(' ' + '─'.repeat(18 + version.length)));
141
+ console.log('');
142
+
143
+ // Parse changelog for current version
144
+ const changelog = parseChangelog(version);
145
+
146
+ if (!changelog.found) {
147
+ // Fallback if version not found in changelog
148
+ console.log(y(' No changelog entry found for v' + version));
149
+ console.log('');
150
+ console.log(w(' This may be a development version or the changelog'));
151
+ console.log(w(' hasn\'t been updated yet.'));
152
+ console.log('');
153
+ console.log(w(' For full documentation:'));
154
+ console.log(c(' ~/.rovodev/reis/README.md'));
155
+ console.log('');
156
+ return;
157
+ }
158
+
159
+ // Display sections (limit to first 3 major sections for readability)
160
+ const maxSections = 3;
161
+ const displaySections = changelog.sections.slice(0, maxSections);
162
+
163
+ for (const section of displaySections) {
164
+ console.log(g(' ' + section.header));
165
+ console.log('');
166
+
167
+ // Limit content display for very long sections
168
+ const contentLines = section.content.split('\n');
169
+ const maxLines = 20;
170
+ const truncatedContent = contentLines.slice(0, maxLines).join('\n');
171
+
172
+ displaySectionContent(truncatedContent, w, c);
173
+
174
+ if (contentLines.length > maxLines) {
175
+ console.log('');
176
+ console.log(y(' ... and more'));
177
+ }
178
+ console.log('');
179
+ }
180
+
181
+ if (changelog.sections.length > maxSections) {
182
+ console.log(y(` + ${changelog.sections.length - maxSections} more sections`));
183
+ console.log('');
184
+ }
185
+
186
+ // Footer
187
+ console.log(w(' ───────────────────────────────────────────────────────'));
188
+ console.log('');
189
+ console.log(w(' Full changelog:'));
190
+ console.log(c(' ~/.rovodev/reis/CHANGELOG.md'));
191
+ console.log('');
192
+ console.log(w(' Documentation:'));
193
+ console.log(c(' ~/.rovodev/reis/README.md'));
194
+ console.log('');
19
195
  };
package/lib/install.js CHANGED
@@ -19,7 +19,8 @@ ${chalk.white.bold(' ██ ██ ███████ ██ ████
19
19
  `;
20
20
 
21
21
  // Check if running in CI environment or sudo (where stdin is not available)
22
- const isCIEnvironment = process.env.CI === 'true' || process.argv.includes('--silent');
22
+ const isSilentMode = process.argv.includes('--silent');
23
+ const isCIEnvironment = process.env.CI === 'true' || isSilentMode;
23
24
  const isSudo = process.getuid && process.getuid() === 0;
24
25
  // Check if stdin is actually readable (not just isTTY)
25
26
  const hasInteractiveStdin = process.stdin.isTTY && !process.stdin.destroyed && typeof process.stdin.read === 'function';
@@ -28,29 +29,39 @@ const isInteractive = !isCIEnvironment && !isSudo && hasInteractiveStdin;
28
29
  // Main installation function
29
30
  async function install() {
30
31
  try {
31
- // Always show banner
32
- console.log(banner);
32
+ // Show banner unless in silent mode
33
+ if (!isSilentMode) {
34
+ console.log(banner);
35
+ }
33
36
 
34
37
  // Check for non-interactive modes
35
38
  if (isCIEnvironment) {
36
- console.log(chalk.gray('Running in CI mode - installing automatically...\n'));
37
- await performInstallation();
39
+ if (!isSilentMode) {
40
+ console.log(chalk.gray('Running in CI mode - installing automatically...\n'));
41
+ }
42
+ await performInstallation(false, isSilentMode);
38
43
  return;
39
44
  }
40
45
 
41
46
  if (isSudo) {
42
- console.log(chalk.gray('Running with sudo - installing automatically...\n'));
43
- await performInstallation();
47
+ if (!isSilentMode) {
48
+ console.log(chalk.gray('Running with sudo - installing automatically...\n'));
49
+ }
50
+ await performInstallation(false, isSilentMode);
44
51
  return;
45
52
  }
46
53
 
47
54
  // Interactive mode - show prompt
48
- console.log(chalk.white('This will install REIS files to ~/.rovodev/reis/\n'));
55
+ if (!isSilentMode) {
56
+ console.log(chalk.white('This will install REIS files to ~/.rovodev/reis/\n'));
57
+ }
49
58
 
50
59
  // Double-check we can actually prompt
51
60
  if (!isInteractive) {
52
- console.log(chalk.gray('Non-interactive mode detected - installing automatically...\n'));
53
- await performInstallation();
61
+ if (!isSilentMode) {
62
+ console.log(chalk.gray('Non-interactive mode detected - installing automatically...\n'));
63
+ }
64
+ await performInstallation(false, isSilentMode);
54
65
  return;
55
66
  }
56
67
 
@@ -71,11 +82,13 @@ async function install() {
71
82
  }
72
83
 
73
84
  console.log('');
74
- await performInstallation();
85
+ await performInstallation(false, false);
75
86
  } catch (promptError) {
76
87
  // inquirer failed, install anyway
77
- console.log(chalk.gray('Prompt failed - installing automatically...\n'));
78
- await performInstallation();
88
+ if (!isSilentMode) {
89
+ console.log(chalk.gray('Prompt failed - installing automatically...\n'));
90
+ }
91
+ await performInstallation(false, isSilentMode);
79
92
  }
80
93
 
81
94
  } catch (error) {
@@ -124,13 +137,15 @@ async function performInstallation(overwrite = false, silent = false) {
124
137
  }
125
138
 
126
139
  // Copy subagents from subagents/ to ~/.rovodev/subagents/
140
+ // ALWAYS overwrite subagents - they should stay up-to-date with package version
127
141
  const subagentsSourceDir = path.join(packageDir, 'subagents');
128
142
  if (fs.existsSync(subagentsSourceDir)) {
129
143
  const subagentFiles = fs.readdirSync(subagentsSourceDir);
130
144
  subagentFiles.forEach(file => {
131
145
  const src = path.join(subagentsSourceDir, file);
132
146
  const dest = path.join(subagentsDir, file);
133
- if (copyFile(src, dest, overwrite)) {
147
+ // Always overwrite subagent files to ensure they're up-to-date
148
+ if (copyFile(src, dest, true)) {
134
149
  fileCount++;
135
150
  }
136
151
  });
@@ -36,6 +36,14 @@ function showInfo(message) {
36
36
  console.log(chalk.cyan(message));
37
37
  }
38
38
 
39
+ /**
40
+ * Display a warning message
41
+ * @param {string} message - The warning message
42
+ */
43
+ function showWarning(message) {
44
+ console.log(chalk.yellow(`⚠ ${message}`));
45
+ }
46
+
39
47
  /**
40
48
  * Get the package version
41
49
  * @returns {string} - The version string
@@ -77,6 +85,7 @@ module.exports = {
77
85
  showError,
78
86
  showSuccess,
79
87
  showInfo,
88
+ showWarning,
80
89
  getVersion,
81
90
  checkPlanningDir,
82
91
  validatePhaseNumber
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gravirei/reis",
3
- "version": "2.6.0",
3
+ "version": "2.6.2",
4
4
  "description": "Roadmap Execution & Implementation System v2.0 - Wave-based execution with checkpoints, metrics, and visualization for Atlassian Rovo Dev",
5
5
  "main": "lib/index.js",
6
6
  "bin": {
@@ -8,7 +8,8 @@
8
8
  },
9
9
  "scripts": {
10
10
  "test": "mocha test/**/*.test.js --timeout 5000",
11
- "test:watch": "mocha test/**/*.test.js --watch"
11
+ "test:watch": "mocha test/**/*.test.js --watch",
12
+ "postinstall": "node lib/install.js --silent"
12
13
  },
13
14
  "keywords": [
14
15
  "reis",