projecta-rrr 1.19.0 → 1.19.1

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
@@ -4,6 +4,12 @@ All notable changes to RRR will be documented in this file.
4
4
 
5
5
  Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
6
6
 
7
+ ## [1.19.1] - 2026-02-11
8
+
9
+ ### Fixed
10
+
11
+ - **Install failure** - Postinstall script referenced wrong path for `register-mcp.js` (`rrr/scripts/` instead of `scripts/`)
12
+
7
13
  ## [1.19.0] - 2026-02-05
8
14
 
9
15
  ### Added
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "projecta-rrr",
3
- "version": "1.19.0",
3
+ "version": "1.19.1",
4
4
  "description": "A meta-prompting, context engineering and spec-driven development system for Claude Code by Projecta.ai",
5
5
  "bin": {
6
6
  "projecta-rrr": "bin/install.js"
7
7
  },
8
8
  "scripts": {
9
- "postinstall": "node bin/install.js --hud-only --global && node rrr/scripts/register-mcp.js",
9
+ "postinstall": "node bin/install.js --hud-only --global && node scripts/register-mcp.js",
10
10
  "watch": "node watcher/index.js",
11
11
  "watch:verbose": "node watcher/index.js --verbose",
12
12
  "watch:claude-code": "node watcher/watchers/claude-code.js --verbose",
@@ -58,33 +58,28 @@ function detectAllCandidateRoots(options = {}) {
58
58
  : path.join(os.homedir(), '.claude');
59
59
 
60
60
  const candidates = [
61
- // Current canonical root
61
+ // Current canonical root (where Claude Code discovers commands)
62
62
  {
63
63
  path: path.join(claudeDir, 'commands', 'rrr'),
64
64
  type: 'canonical',
65
65
  canonical: true
66
66
  },
67
+ // Stale: rrr/commands/rrr (inside RRR skill dir or source repo clone)
68
+ // This is NOT the canonical location - Claude Code does NOT discover commands here
69
+ {
70
+ path: path.join(claudeDir, 'rrr', 'commands', 'rrr'),
71
+ type: 'stale-skill-dir',
72
+ canonical: false
73
+ },
67
74
  // Legacy: nested rrr/rrr/commands/rrr (from older installer)
68
75
  {
69
76
  path: path.join(claudeDir, 'rrr', 'rrr', 'commands', 'rrr'),
70
77
  type: 'legacy-nested',
71
78
  canonical: false
72
- },
73
- // Legacy: commands/rrr at root level (very old installer)
74
- {
75
- path: path.join(claudeDir, 'commands', 'rrr'),
76
- type: 'legacy-root',
77
- canonical: true // Same path as canonical, but conceptually legacy
78
- },
79
+ }
79
80
  // NOTE: We intentionally do NOT check ~/.claude/commands/ as a duplicate candidate.
80
81
  // That's the PARENT directory containing canonical commands/rrr/. Quarantining it
81
82
  // would delete all commands including the canonical ones. See bug fix 2026-01-23.
82
- // Project-local install (if config points to project)
83
- {
84
- path: path.join(claudeDir, 'commands', 'rrr'),
85
- type: 'project-local',
86
- canonical: false
87
- }
88
83
  ];
89
84
 
90
85
  // Filter out duplicates and add actual existence check
@@ -173,10 +173,13 @@ function findCandidateRoots(baseDir, options = {}) {
173
173
  }
174
174
  }
175
175
 
176
- // Continue scanning subdirectories (skip hidden and node_modules)
176
+ // Continue scanning subdirectories (skip hidden, node_modules, and git repos)
177
177
  if (entry.isDirectory() && !entry.name.startsWith('.') && entry.name !== 'node_modules') {
178
178
  // Skip scanning into other .claude directories that aren't under our target
179
179
  if (entry.name === 'claude' && dir !== baseDir) continue;
180
+ // Skip directories that are git repos (source repo clones, not installs)
181
+ // Exception: don't skip the base dir itself
182
+ if (currentDepth > 0 && fs.existsSync(path.join(fullPath, '.git'))) continue;
180
183
  scanDir(fullPath, currentDepth + 1);
181
184
  }
182
185
  }
@@ -200,10 +203,12 @@ function scoreCandidate(candidate) {
200
203
  let versionSource = null;
201
204
 
202
205
  // A) Canonical priority boost
203
- if (rootPath === path.join(CLAUDE_DIR, 'rrr', 'commands', 'rrr')) {
206
+ // ~/.claude/commands/rrr is the TRUE canonical location (where Claude Code discovers commands)
207
+ // ~/.claude/rrr/commands/rrr is inside the RRR library/skill dir and should NOT be preferred
208
+ if (rootPath === path.join(CLAUDE_DIR, 'commands', 'rrr')) {
204
209
  score += 1000;
205
- } else if (rootPath === path.join(CLAUDE_DIR, 'commands', 'rrr')) {
206
- score += 900;
210
+ } else if (rootPath === path.join(CLAUDE_DIR, 'rrr', 'commands', 'rrr')) {
211
+ score += 500; // Inside rrr skill dir - likely a source repo clone, NOT the real canonical
207
212
  } else if (/\/rrr\/rrr\/commands\/rrr/.test(rootPath)) {
208
213
  score += 100;
209
214
  }
@@ -261,17 +266,19 @@ function getParentInstallRoot(candidatePath) {
261
266
  const normalized = path.normalize(candidatePath);
262
267
 
263
268
  if (normalized === path.join(CLAUDE_DIR, 'rrr', 'commands', 'rrr')) {
269
+ // This is inside the RRR skill dir or source repo clone - quarantine just the commands/rrr subdir
264
270
  return {
265
- quarantinePath: path.join(CLAUDE_DIR, 'rrr'),
266
- shouldQuarantineParent: true,
267
- description: '~/.claude/rrr'
271
+ quarantinePath: normalized,
272
+ shouldQuarantineParent: false,
273
+ description: '~/.claude/rrr/commands/rrr (stale skill-dir commands)'
268
274
  };
269
275
  } else if (normalized === path.join(CLAUDE_DIR, 'commands', 'rrr')) {
270
- // Don't quarantine ~/.claude itself, just the commands folder
276
+ // This is the canonical location - should NEVER be quarantined
277
+ // But if it is being quarantined, only quarantine the rrr subdir, not the parent commands/
271
278
  return {
272
- quarantinePath: path.join(CLAUDE_DIR, 'commands'),
279
+ quarantinePath: normalized,
273
280
  shouldQuarantineParent: false,
274
- description: '~/.claude/commands (commands folder only)'
281
+ description: '~/.claude/commands/rrr (canonical)'
275
282
  };
276
283
  } else if (/\/rrr\/rrr\/commands\/rrr/.test(normalized)) {
277
284
  return {
@@ -448,8 +455,9 @@ function runDiagnostics() {
448
455
  const scored = candidates.map(c => scoreCandidate(c));
449
456
 
450
457
  // Apply canonical override rule
458
+ // The TRUE canonical path is ~/.claude/commands/rrr (where Claude Code discovers commands)
451
459
  let selected = null;
452
- const canonicalPath = path.join(CLAUDE_DIR, 'rrr', 'commands', 'rrr');
460
+ const canonicalPath = path.join(CLAUDE_DIR, 'commands', 'rrr');
453
461
  const canonicalExists = scored.find(c => c.path === canonicalPath && isHealthy(c));
454
462
 
455
463
  if (canonicalExists) {