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 +6 -0
- package/package.json +2 -2
- package/rrr/lib/install-roots.js +9 -14
- package/scripts/doctor-rrr.js +19 -11
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.
|
|
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
|
|
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",
|
package/rrr/lib/install-roots.js
CHANGED
|
@@ -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
|
package/scripts/doctor-rrr.js
CHANGED
|
@@ -173,10 +173,13 @@ function findCandidateRoots(baseDir, options = {}) {
|
|
|
173
173
|
}
|
|
174
174
|
}
|
|
175
175
|
|
|
176
|
-
// Continue scanning subdirectories (skip hidden and
|
|
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
|
-
|
|
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 +=
|
|
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:
|
|
266
|
-
shouldQuarantineParent:
|
|
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
|
-
//
|
|
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:
|
|
279
|
+
quarantinePath: normalized,
|
|
273
280
|
shouldQuarantineParent: false,
|
|
274
|
-
description: '~/.claude/commands (
|
|
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, '
|
|
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) {
|