rrce-workflow 0.2.63 → 0.2.65

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
@@ -98,11 +98,13 @@ Add to `~/.config/claude/claude_desktop_config.json`:
98
98
  RRCE-Workflow supports two ways to store your agent workflow data (`knowledge/`, `tasks/`, `refs/`).
99
99
 
100
100
  ### 1. Global Mode (Default & Recommended)
101
- Stores configuration and knowledge outside your project directory in `~/.rrce-workflow/workspaces/<project-name>`.
101
+ Stores configuration and knowledge outside your project directory in `~/.rrce-workflow/workspaces/<project-name>` (or a custom path you configure).
102
102
 
103
103
  * **✅ Pros**: Keeps your repo clean, easy cross-project linking, no `.gitignore` pollution.
104
104
  * **❌ Cons**: Knowledge isn't checked into your project's git repo (unless you manually sync/backup).
105
105
 
106
+ **Custom Global Path**: When running the wizard, you can choose a custom location instead of `~/.rrce-workflow/`. Your preference is saved and automatically used for future projects.
107
+
106
108
  ### 2. Workspace Mode (Alternative)
107
109
  Stores everything in a `.rrce-workflow` folder inside your project root.
108
110
 
@@ -125,6 +127,7 @@ Once installed, you gain access to powerful agent workflows. Invoke them using y
125
127
  | **Execute** | **Implementation** | The "coding" phase. Implements the plan created by the Planning agent. |
126
128
  | **Docs** | **Documentation** | Generates tailored docs (API refs, guides) from code. |
127
129
  | **Sync** | **Knowledge Maintenance** | Scans code changes to update the `knowledge/` folder. |
130
+ | **Doctor** | **Health Analysis** | Analyzes codebase for issues, tech debt, and improvement opportunities. |
128
131
 
129
132
  ### Recommended Workflow
130
133
  1. **`/init`**: "Analyze this codebase." -> Creates `project-context.md`.
@@ -145,7 +148,7 @@ RAG is enabled by default in Express Setup. You can toggle it per-project in the
145
148
 
146
149
  ---
147
150
 
148
- ## requirements
151
+ ## Requirements
149
152
 
150
153
  - **Node.js 18+**
151
154
  - **Git**
@@ -18,13 +18,19 @@ auto-identity:
18
18
 
19
19
  You are the Project Doctor for RRCE-Workflow. Operate like a senior technical consultant performing a health check on the codebase to identify issues, technical debt, and improvement opportunities.
20
20
 
21
- **⚠️ FIRST STEP (MANDATORY)**
22
- Before doing ANY work, read `.rrce-workflow/config.yaml` (if it exists) and resolve these variables:
23
- ```
24
- RRCE_HOME = config.storage.globalPath OR "~/.rrce-workflow"
25
- RRCE_DATA = (config.storage.mode == "workspace") ? ".rrce-workflow/" : "${RRCE_HOME}/workspaces/${config.project.name}/"
26
- ```
27
- If config doesn't exist, use defaults: `RRCE_HOME=~/.rrce-workflow`, `RRCE_DATA=.rrce-workflow/`
21
+ **⚠️ FIRST STEP (MANDATORY) - Path Resolution**
22
+ Check if the system has pre-resolved paths for you. Look for a "System Resolved Paths" section at the start of this prompt context. If present, use those values directly:
23
+ - `RRCE_DATA` = Pre-resolved data path (where knowledge, tasks, refs are stored)
24
+ - `RRCE_HOME` = Pre-resolved global home
25
+ - `WORKSPACE_ROOT` = Pre-resolved source code location
26
+
27
+ **Only if no pre-resolved paths are present**, fall back to manual resolution by reading config.
28
+
29
+ Path Variables Reference:
30
+ - `{{RRCE_DATA}}` = Primary data path (knowledge, tasks, refs storage)
31
+ - `{{RRCE_HOME}}` = Global RRCE home directory
32
+ - `{{WORKSPACE_ROOT}}` = Source code directory
33
+ - `{{WORKSPACE_NAME}}` = Project name
28
34
 
29
35
  ## Pipeline Position
30
36
  - **Input**: Can be triggered at any time for project health analysis.
@@ -20,13 +20,13 @@ auto-identity:
20
20
 
21
21
  You are the Documentation Lead for the project. Operate like a senior engineering manager responsible for synthesizing knowledge and preparing smooth handovers.
22
22
 
23
- **⚠️ FIRST STEP (MANDATORY)**
24
- Before doing ANY work, read `.rrce-workflow/config.yaml` and resolve these variables:
25
- ```
26
- RRCE_HOME = config.storage.globalPath OR "~/.rrce-workflow"
27
- RRCE_DATA = (config.storage.mode == "workspace") ? ".rrce-workflow/" : "${RRCE_HOME}/workspaces/${config.project.name}/"
28
- ```
29
- Use these resolved paths for ALL subsequent file operations.
23
+ **⚠️ FIRST STEP (MANDATORY) - Path Resolution**
24
+ Check if the system has pre-resolved paths for you. Look for a "System Resolved Paths" section at the start of this prompt context. If present, use those values directly:
25
+ - `RRCE_DATA` = Pre-resolved data path (where knowledge, tasks, refs are stored)
26
+ - `RRCE_HOME` = Pre-resolved global home
27
+ - `WORKSPACE_ROOT` = Pre-resolved source code location
28
+
29
+ **Only if no pre-resolved paths are present**, fall back to manual resolution by reading config.
30
30
 
31
31
  Pipeline Position
32
32
  - **Optional**: Documentation can be run at any point, but is most valuable after Execution.
@@ -55,14 +55,11 @@ Non-Negotiables
55
55
  5. Store persistent insights back into `{{RRCE_DATA}}/knowledge` when they apply beyond the immediate deliverable.
56
56
  6. Close the loop in `meta.json` when working within a task by setting `agents.documentation.status`, refreshing `checklist`, and updating overall `status`.
57
57
 
58
- Path Resolution
59
- **Config file**: `.rrce-workflow/config.yaml` - Read this first.
60
-
61
- **How to resolve `{{RRCE_DATA}}`**:
62
- 1. Read `config.yaml` get `storage.mode` and `project.name`
63
- 2. Resolve: `workspace` → `.rrce-workflow/` | `global` → `{{RRCE_HOME}}/workspaces/<name>/`
64
-
65
- **How to resolve `{{RRCE_HOME}}`**: `config.yaml` → `storage.globalPath` or default `~/.rrce-workflow`
58
+ Path Variables Reference
59
+ - `{{RRCE_DATA}}` = Primary data path (knowledge, tasks, refs storage)
60
+ - `{{RRCE_HOME}}` = Global RRCE home directory
61
+ - `{{WORKSPACE_ROOT}}` = Source code directory
62
+ - `{{WORKSPACE_NAME}}` = Project name
66
63
 
67
64
  Cross-Project References
68
65
  - Reference another project's context: `{{RRCE_HOME}}/workspaces/<other-project>/knowledge/`
@@ -16,13 +16,13 @@ auto-identity:
16
16
 
17
17
  You are the Executor for the project. Operate like a senior individual contributor who ships clean, well-tested code aligned with the orchestrated plan.
18
18
 
19
- **⚠️ FIRST STEP (MANDATORY)**
20
- Before doing ANY work, read `.rrce-workflow/config.yaml` and resolve these variables:
21
- ```
22
- RRCE_HOME = config.storage.globalPath OR "~/.rrce-workflow"
23
- RRCE_DATA = (config.storage.mode == "workspace") ? ".rrce-workflow/" : "${RRCE_HOME}/workspaces/${config.project.name}/"
24
- ```
25
- Use these resolved paths for ALL subsequent file operations.
19
+ **⚠️ FIRST STEP (MANDATORY) - Path Resolution**
20
+ Check if the system has pre-resolved paths for you. Look for a "System Resolved Paths" section at the start of this prompt context. If present, use those values directly:
21
+ - `RRCE_DATA` = Pre-resolved data path (where knowledge, tasks, refs are stored)
22
+ - `RRCE_HOME` = Pre-resolved global home
23
+ - `WORKSPACE_ROOT` = Pre-resolved source code location
24
+
25
+ **Only if no pre-resolved paths are present**, fall back to manual resolution by reading config.
26
26
 
27
27
  Pipeline Position
28
28
  - **Requires**: Planning phase must be complete before execution can begin.
@@ -60,14 +60,11 @@ Non-Negotiables
60
60
  5. Keep execution notes under 500 lines, logging command outputs succinctly rather than verbatim dumps.
61
61
  6. Update `meta.json` as you proceed so statuses stay accurate.
62
62
 
63
- Path Resolution
64
- **Config file**: `.rrce-workflow/config.yaml` - Read this first.
65
-
66
- **How to resolve `{{RRCE_DATA}}`**:
67
- 1. Read `config.yaml` get `storage.mode` and `project.name`
68
- 2. Resolve: `workspace` → `.rrce-workflow/` | `global` → `{{RRCE_HOME}}/workspaces/<name>/`
69
-
70
- **How to resolve `{{RRCE_HOME}}`**: `config.yaml` → `storage.globalPath` or default `~/.rrce-workflow`
63
+ Path Variables Reference
64
+ - `{{RRCE_DATA}}` = Primary data path (knowledge, tasks, refs storage)
65
+ - `{{RRCE_HOME}}` = Global RRCE home directory
66
+ - `{{WORKSPACE_ROOT}}` = Source code directory
67
+ - `{{WORKSPACE_NAME}}` = Project name
71
68
 
72
69
  Cross-Project References
73
70
  - Reference another project's context: `{{RRCE_HOME}}/workspaces/<other-project>/knowledge/`
@@ -15,13 +15,16 @@ auto-identity:
15
15
 
16
16
  You are the Project Initializer for RRCE-Workflow. Operate like a senior architect performing a comprehensive codebase audit to establish foundational context for all downstream agents.
17
17
 
18
- **⚠️ FIRST STEP (MANDATORY)**
19
- Before doing ANY work, read `.rrce-workflow/config.yaml` (if it exists) and resolve these variables:
20
- ```
21
- RRCE_HOME = config.storage.globalPath OR "~/.rrce-workflow"
22
- RRCE_DATA = (config.storage.mode == "workspace") ? ".rrce-workflow/" : "${RRCE_HOME}/workspaces/${config.project.name}/"
23
- ```
24
- If config doesn't exist yet (new project), use defaults: `RRCE_HOME=~/.rrce-workflow`, `RRCE_DATA=.rrce-workflow/`
18
+ **⚠️ FIRST STEP (MANDATORY) - Path Resolution**
19
+ Check if the system has pre-resolved paths for you. Look for a "System Resolved Paths" section at the start of this prompt context. If present, use those values directly:
20
+ - `RRCE_DATA` = Pre-resolved data path (where knowledge, tasks, refs are stored)
21
+ - `RRCE_HOME` = Pre-resolved global home
22
+ - `WORKSPACE_ROOT` = Pre-resolved source code location
23
+
24
+ **Only if no pre-resolved paths are present**, fall back to manual resolution by reading config:
25
+ 1. Check `.rrce-workflow/config.yaml` (workspace mode) OR `{{RRCE_HOME}}/workspaces/<project>/config.yaml` (global mode)
26
+ 2. Resolve: `RRCE_DATA = (mode == "workspace") ? ".rrce-workflow/" : "${RRCE_HOME}/workspaces/${project.name}/"`
27
+ 3. Default if no config: `RRCE_HOME=~/.rrce-workflow`, `RRCE_DATA=.rrce-workflow/`
25
28
 
26
29
  Pipeline Position
27
30
  - **Entry Point**: Init can be run at any time to establish or update project context.
@@ -41,29 +44,17 @@ Non-Negotiables
41
44
  5. Never assume; if information is ambiguous, note it as requiring clarification.
42
45
  6. Keep output actionable and scannable; use structured sections.
43
46
 
44
- Path Resolution
45
- **Config file**: `.rrce-workflow/config.yaml` - Read this first to resolve all paths.
46
-
47
- **How to resolve `{{RRCE_DATA}}`** (primary data path):
48
- 1. Read `.rrce-workflow/config.yaml`
49
- 2. Get `storage.mode` (default: `global`) and `project.name`
50
- 3. Resolve based on mode:
51
- - `workspace` → `<workspace>/.rrce-workflow/`
52
- - `global` → `{{RRCE_HOME}}/workspaces/<project.name>/`
53
-
54
- **How to resolve `{{RRCE_HOME}}`** (global home):
55
- 1. Read `.rrce-workflow/config.yaml`
56
- 2. If `storage.globalPath` exists, use that value
57
- 3. Otherwise, default to `~/.rrce-workflow`
58
-
59
- **Other variables:**
60
- - `{{WORKSPACE_ROOT}}` = Current workspace directory
61
- - `{{WORKSPACE_NAME}}` = `config.yaml` → `project.name`
47
+ Path Variables Reference
48
+ - `{{RRCE_DATA}}` = Primary data path (knowledge, tasks, refs storage)
49
+ - `{{RRCE_HOME}}` = Global RRCE home directory
50
+ - `{{WORKSPACE_ROOT}}` = Source code directory
51
+ - `{{WORKSPACE_NAME}}` = Project name
62
52
 
63
53
  Cross-Project References
64
54
  - To reference another project's context: `{{RRCE_HOME}}/workspaces/<other-project-name>/knowledge/`
65
55
  - Example: FE project can reference BE project via `{{RRCE_HOME}}/workspaces/my-backend/knowledge/project-context.md`
66
56
 
57
+
67
58
  Discovery Workflow
68
59
  1. **Project Identity**
69
60
  - Detect project name from manifests or directory name
@@ -13,13 +13,13 @@ auto-identity:
13
13
 
14
14
  You are the Planning & Task Orchestrator for the project. Operate like an engineering manager with deep scoped knowledge of this codebase.
15
15
 
16
- **⚠️ FIRST STEP (MANDATORY)**
17
- Before doing ANY work, read `.rrce-workflow/config.yaml` and resolve these variables:
18
- ```
19
- RRCE_HOME = config.storage.globalPath OR "~/.rrce-workflow"
20
- RRCE_DATA = (config.storage.mode == "workspace") ? ".rrce-workflow/" : "${RRCE_HOME}/workspaces/${config.project.name}/"
21
- ```
22
- Use these resolved paths for ALL subsequent file operations.
16
+ **⚠️ FIRST STEP (MANDATORY) - Path Resolution**
17
+ Check if the system has pre-resolved paths for you. Look for a "System Resolved Paths" section at the start of this prompt context. If present, use those values directly:
18
+ - `RRCE_DATA` = Pre-resolved data path (where knowledge, tasks, refs are stored)
19
+ - `RRCE_HOME` = Pre-resolved global home
20
+ - `WORKSPACE_ROOT` = Pre-resolved source code location
21
+
22
+ **Only if no pre-resolved paths are present**, fall back to manual resolution by reading config.
23
23
 
24
24
  Pipeline Position
25
25
  - **Requires**: Research phase must be complete before planning can begin.
@@ -52,14 +52,11 @@ Non-Negotiables
52
52
  5. Track how each task ties back to product goals, risks, and testing strategy.
53
53
  6. Keep the written plan under 500 lines and reference supporting materials explicitly.
54
54
 
55
- Path Resolution
56
- **Config file**: `.rrce-workflow/config.yaml` - Read this first.
57
-
58
- **How to resolve `{{RRCE_DATA}}`**:
59
- 1. Read `config.yaml` get `storage.mode` and `project.name`
60
- 2. Resolve: `workspace` → `.rrce-workflow/` | `global` → `{{RRCE_HOME}}/workspaces/<name>/`
61
-
62
- **How to resolve `{{RRCE_HOME}}`**: `config.yaml` → `storage.globalPath` or default `~/.rrce-workflow`
55
+ Path Variables Reference
56
+ - `{{RRCE_DATA}}` = Primary data path (knowledge, tasks, refs storage)
57
+ - `{{RRCE_HOME}}` = Global RRCE home directory
58
+ - `{{WORKSPACE_ROOT}}` = Source code directory
59
+ - `{{WORKSPACE_NAME}}` = Project name
63
60
 
64
61
  Cross-Project References
65
62
  - Reference another project's context: `{{RRCE_HOME}}/workspaces/<other-project>/knowledge/`
@@ -20,13 +20,13 @@ auto-identity:
20
20
 
21
21
  You are the Research & Discussion Lead for the project. Operate like a staff-level tech lead who owns broad project awareness.
22
22
 
23
- **⚠️ FIRST STEP (MANDATORY)**
24
- Before doing ANY work, read `.rrce-workflow/config.yaml` and resolve these variables:
25
- ```
26
- RRCE_HOME = config.storage.globalPath OR "~/.rrce-workflow"
27
- RRCE_DATA = (config.storage.mode == "workspace") ? ".rrce-workflow/" : "${RRCE_HOME}/workspaces/${config.project.name}/"
28
- ```
29
- Use these resolved paths for ALL subsequent file operations.
23
+ **⚠️ FIRST STEP (MANDATORY) - Path Resolution**
24
+ Check if the system has pre-resolved paths for you. Look for a "System Resolved Paths" section at the start of this prompt context. If present, use those values directly:
25
+ - `RRCE_DATA` = Pre-resolved data path (where knowledge, tasks, refs are stored)
26
+ - `RRCE_HOME` = Pre-resolved global home
27
+ - `WORKSPACE_ROOT` = Pre-resolved source code location
28
+
29
+ **Only if no pre-resolved paths are present**, fall back to manual resolution by reading config.
30
30
 
31
31
  Pipeline Position
32
32
  - **Entry Point**: Research can be the first agent invoked for a new task.
@@ -45,14 +45,11 @@ Non-Negotiables
45
45
  5. Do not hand off to Planning until answers are captured or explicitly marked as pending for follow-up.
46
46
  6. Keep the final brief under 500 lines and reference concrete sources whenever possible.
47
47
 
48
- Path Resolution
49
- **Config file**: `.rrce-workflow/config.yaml` - Read this first.
50
-
51
- **How to resolve `{{RRCE_DATA}}`**:
52
- 1. Read `config.yaml` get `storage.mode` and `project.name`
53
- 2. Resolve: `workspace` → `.rrce-workflow/` | `global` → `{{RRCE_HOME}}/workspaces/<name>/`
54
-
55
- **How to resolve `{{RRCE_HOME}}`**: `config.yaml` → `storage.globalPath` or default `~/.rrce-workflow`
48
+ Path Variables Reference
49
+ - `{{RRCE_DATA}}` = Primary data path (knowledge, tasks, refs storage)
50
+ - `{{RRCE_HOME}}` = Global RRCE home directory
51
+ - `{{WORKSPACE_ROOT}}` = Source code directory
52
+ - `{{WORKSPACE_NAME}}` = Project name
56
53
 
57
54
  Cross-Project References
58
55
  - Reference another project's context: `{{RRCE_HOME}}/workspaces/<other-project>/knowledge/`
@@ -14,13 +14,13 @@ auto-identity:
14
14
 
15
15
  You are the Knowledge Sync Lead. Act like a senior architect charged with keeping the RRCE knowledge cache authoritative and current.
16
16
 
17
- **⚠️ FIRST STEP (MANDATORY)**
18
- Before doing ANY work, read `.rrce-workflow/config.yaml` and resolve these variables:
19
- ```
20
- RRCE_HOME = config.storage.globalPath OR "~/.rrce-workflow"
21
- RRCE_DATA = (config.storage.mode == "workspace") ? ".rrce-workflow/" : "${RRCE_HOME}/workspaces/${config.project.name}/"
22
- ```
23
- Use these resolved paths for ALL subsequent file operations.
17
+ **⚠️ FIRST STEP (MANDATORY) - Path Resolution**
18
+ Check if the system has pre-resolved paths for you. Look for a "System Resolved Paths" section at the start of this prompt context. If present, use those values directly:
19
+ - `RRCE_DATA` = Pre-resolved data path (where knowledge, tasks, refs are stored)
20
+ - `RRCE_HOME` = Pre-resolved global home
21
+ - `WORKSPACE_ROOT` = Pre-resolved source code location
22
+
23
+ **Only if no pre-resolved paths are present**, fall back to manual resolution by reading config.
24
24
 
25
25
  Pipeline Position
26
26
  - **Maintenance Agent**: Sync runs periodically or after significant codebase changes to keep knowledge current.
@@ -45,14 +45,11 @@ Non-Negotiables
45
45
  4. Keep all knowledge files lean (<500 lines each) and focused on durable insights, linking to code paths or task artifacts instead of duplicating detail.
46
46
  5. Record gaps or follow-up items in a checklist inside the file you touched so future runs can close them.
47
47
 
48
- Path Resolution
49
- **Config file**: `.rrce-workflow/config.yaml` - Read this first.
50
-
51
- **How to resolve `{{RRCE_DATA}}`**:
52
- 1. Read `config.yaml` get `storage.mode` and `project.name`
53
- 2. Resolve: `workspace` → `.rrce-workflow/` | `global` → `{{RRCE_HOME}}/workspaces/<name>/`
54
-
55
- **How to resolve `{{RRCE_HOME}}`**: `config.yaml` → `storage.globalPath` or default `~/.rrce-workflow`
48
+ Path Variables Reference
49
+ - `{{RRCE_DATA}}` = Primary data path (knowledge, tasks, refs storage)
50
+ - `{{RRCE_HOME}}` = Global RRCE home directory
51
+ - `{{WORKSPACE_ROOT}}` = Source code directory
52
+ - `{{WORKSPACE_NAME}}` = Project name
56
53
 
57
54
  Cross-Project References
58
55
  - Reference another project's context: `{{RRCE_HOME}}/workspaces/<other-project>/knowledge/`
package/dist/index.js CHANGED
@@ -24,46 +24,86 @@ var init_git = __esm({
24
24
  }
25
25
  });
26
26
 
27
- // src/lib/paths.ts
27
+ // src/lib/preferences.ts
28
28
  import * as fs from "fs";
29
29
  import * as path from "path";
30
+ function getPreferencesPath() {
31
+ const home = process.env.HOME || "~";
32
+ return path.join(home, ".rrce-workflow", "preferences.json");
33
+ }
34
+ function loadUserPreferences() {
35
+ const prefPath = getPreferencesPath();
36
+ if (!fs.existsSync(prefPath)) {
37
+ return {};
38
+ }
39
+ try {
40
+ return JSON.parse(fs.readFileSync(prefPath, "utf-8"));
41
+ } catch {
42
+ return {};
43
+ }
44
+ }
45
+ function saveUserPreferences(prefs) {
46
+ const prefPath = getPreferencesPath();
47
+ ensureDir(path.dirname(prefPath));
48
+ const current = loadUserPreferences();
49
+ const refined = { ...current, ...prefs };
50
+ fs.writeFileSync(prefPath, JSON.stringify(refined, null, 2));
51
+ }
52
+ var init_preferences = __esm({
53
+ "src/lib/preferences.ts"() {
54
+ "use strict";
55
+ init_paths();
56
+ }
57
+ });
58
+
59
+ // src/lib/paths.ts
60
+ import * as fs2 from "fs";
61
+ import * as path2 from "path";
62
+ function getEffectiveGlobalPath() {
63
+ const prefs = loadUserPreferences();
64
+ if (prefs.useCustomGlobalPath && prefs.defaultGlobalPath) {
65
+ return prefs.defaultGlobalPath;
66
+ }
67
+ return RRCE_HOME;
68
+ }
30
69
  function detectWorkspaceRoot() {
31
70
  if (RRCE_WORKSPACE) {
32
71
  return RRCE_WORKSPACE;
33
72
  }
34
73
  let current = process.cwd();
35
74
  while (current !== "/") {
36
- if (fs.existsSync(path.join(current, ".git")) || fs.existsSync(path.join(current, ".rrce-workflow", "config.yaml")) || fs.existsSync(path.join(current, ".rrce-workflow.yaml"))) {
75
+ if (fs2.existsSync(path2.join(current, ".git")) || fs2.existsSync(path2.join(current, ".rrce-workflow", "config.yaml")) || fs2.existsSync(path2.join(current, ".rrce-workflow.yaml"))) {
37
76
  return current;
38
77
  }
39
- current = path.dirname(current);
78
+ current = path2.dirname(current);
40
79
  }
41
80
  return process.cwd();
42
81
  }
43
82
  function getConfigPath(workspaceRoot) {
44
- const newPath = path.join(workspaceRoot, ".rrce-workflow", "config.yaml");
45
- const legacyPath = path.join(workspaceRoot, ".rrce-workflow.yaml");
46
- if (fs.existsSync(newPath)) {
83
+ const newPath = path2.join(workspaceRoot, ".rrce-workflow", "config.yaml");
84
+ const legacyPath = path2.join(workspaceRoot, ".rrce-workflow.yaml");
85
+ if (fs2.existsSync(newPath)) {
47
86
  return newPath;
48
87
  }
49
- if (fs.existsSync(legacyPath)) {
88
+ if (fs2.existsSync(legacyPath)) {
50
89
  return legacyPath;
51
90
  }
52
91
  try {
53
- const rrceHome = getDefaultRRCEHome();
54
- const mcpConfigPath = path.join(rrceHome, "mcp.yaml");
55
- if (fs.existsSync(mcpConfigPath)) {
56
- const mcpContent = fs.readFileSync(mcpConfigPath, "utf-8");
92
+ const rrceHome = getDefaultRRCEHome2();
93
+ const mcpConfigPath = path2.join(rrceHome, "mcp.yaml");
94
+ if (fs2.existsSync(mcpConfigPath)) {
95
+ const mcpContent = fs2.readFileSync(mcpConfigPath, "utf-8");
57
96
  const lines = mcpContent.split("\n");
58
97
  let currentName = "";
59
98
  for (let i = 0; i < lines.length; i++) {
60
- const line = lines[i].trim();
99
+ const line = lines[i]?.trim();
100
+ if (!line) continue;
61
101
  if (line.startsWith("- name:")) {
62
102
  currentName = line.replace("- name:", "").trim();
63
103
  } else if (line.startsWith("path:")) {
64
104
  const p = line.replace("path:", "").trim();
65
105
  if (p === workspaceRoot || p === `"${workspaceRoot}"` || p === `'${workspaceRoot}'`) {
66
- return path.join(rrceHome, "workspaces", currentName, "config.yaml");
106
+ return path2.join(rrceHome, "workspaces", currentName, "config.yaml");
67
107
  }
68
108
  }
69
109
  }
@@ -73,42 +113,42 @@ function getConfigPath(workspaceRoot) {
73
113
  return newPath;
74
114
  }
75
115
  function getWorkspaceName(workspaceRoot) {
76
- return path.basename(workspaceRoot);
116
+ return path2.basename(workspaceRoot);
77
117
  }
78
118
  function getRRCEHome() {
79
119
  return RRCE_HOME;
80
120
  }
81
121
  function getLocalWorkspacePath(workspaceRoot) {
82
- return path.join(workspaceRoot, ".rrce-workflow");
122
+ return path2.join(workspaceRoot, ".rrce-workflow");
83
123
  }
84
124
  function ensureDir(dirPath) {
85
- if (!fs.existsSync(dirPath)) {
86
- fs.mkdirSync(dirPath, { recursive: true });
125
+ if (!fs2.existsSync(dirPath)) {
126
+ fs2.mkdirSync(dirPath, { recursive: true });
87
127
  }
88
128
  }
89
129
  function getAgentPromptPath(workspaceRoot, tool) {
90
130
  if (tool === "copilot") {
91
- return path.join(workspaceRoot, ".github", "agents");
131
+ return path2.join(workspaceRoot, ".github", "agents");
92
132
  } else {
93
- return path.join(workspaceRoot, ".agent", "workflows");
133
+ return path2.join(workspaceRoot, ".agent", "workflows");
94
134
  }
95
135
  }
96
136
  function copyToAllStoragePaths(sourceFile, relativePath, dataPaths) {
97
- const content = fs.readFileSync(sourceFile);
137
+ const content = fs2.readFileSync(sourceFile);
98
138
  for (const dataPath of dataPaths) {
99
- const targetPath = path.join(dataPath, relativePath);
100
- ensureDir(path.dirname(targetPath));
101
- fs.writeFileSync(targetPath, content);
139
+ const targetPath = path2.join(dataPath, relativePath);
140
+ ensureDir(path2.dirname(targetPath));
141
+ fs2.writeFileSync(targetPath, content);
102
142
  }
103
143
  }
104
144
  function copyDirToAllStoragePaths(sourceDir, relativeDir, dataPaths) {
105
- if (!fs.existsSync(sourceDir)) {
145
+ if (!fs2.existsSync(sourceDir)) {
106
146
  return;
107
147
  }
108
- const entries = fs.readdirSync(sourceDir, { withFileTypes: true });
148
+ const entries = fs2.readdirSync(sourceDir, { withFileTypes: true });
109
149
  for (const entry of entries) {
110
- const sourcePath = path.join(sourceDir, entry.name);
111
- const relativePath = path.join(relativeDir, entry.name);
150
+ const sourcePath = path2.join(sourceDir, entry.name);
151
+ const relativePath = path2.join(relativeDir, entry.name);
112
152
  if (entry.isDirectory()) {
113
153
  copyDirToAllStoragePaths(sourcePath, relativePath, dataPaths);
114
154
  } else {
@@ -119,38 +159,38 @@ function copyDirToAllStoragePaths(sourceDir, relativeDir, dataPaths) {
119
159
  function syncMetadataToAll(agentCorePath, dataPaths) {
120
160
  const metadataDirs = ["knowledge", "refs", "tasks"];
121
161
  for (const dir of metadataDirs) {
122
- const sourceDir = path.join(agentCorePath, dir);
162
+ const sourceDir = path2.join(agentCorePath, dir);
123
163
  copyDirToAllStoragePaths(sourceDir, dir, dataPaths);
124
164
  }
125
165
  }
126
166
  function checkWriteAccess(dirPath) {
127
- const testFile = path.join(dirPath, ".rrce-write-test");
167
+ const testFile = path2.join(dirPath, ".rrce-write-test");
128
168
  try {
129
- if (!fs.existsSync(dirPath)) {
130
- fs.mkdirSync(dirPath, { recursive: true });
169
+ if (!fs2.existsSync(dirPath)) {
170
+ fs2.mkdirSync(dirPath, { recursive: true });
131
171
  }
132
- fs.writeFileSync(testFile, "write-test");
133
- fs.unlinkSync(testFile);
172
+ fs2.writeFileSync(testFile, "write-test");
173
+ fs2.unlinkSync(testFile);
134
174
  return true;
135
175
  } catch {
136
176
  try {
137
- if (fs.existsSync(testFile)) {
138
- fs.unlinkSync(testFile);
177
+ if (fs2.existsSync(testFile)) {
178
+ fs2.unlinkSync(testFile);
139
179
  }
140
180
  } catch {
141
181
  }
142
182
  return false;
143
183
  }
144
184
  }
145
- function getDefaultRRCEHome() {
146
- return process.env.RRCE_HOME || path.join(process.env.HOME || "~", ".rrce-workflow");
185
+ function getDefaultRRCEHome2() {
186
+ return process.env.RRCE_HOME || path2.join(process.env.HOME || "~", ".rrce-workflow");
147
187
  }
148
188
  function getEffectiveRRCEHome(workspaceRoot) {
149
189
  if (workspaceRoot) {
150
190
  const configPath = getConfigPath(workspaceRoot);
151
- if (fs.existsSync(configPath)) {
191
+ if (fs2.existsSync(configPath)) {
152
192
  try {
153
- const content = fs.readFileSync(configPath, "utf-8");
193
+ const content = fs2.readFileSync(configPath, "utf-8");
154
194
  const globalPathMatch = content.match(/globalPath:\s*["']?([^"'\n]+)["']?/);
155
195
  if (globalPathMatch?.[1]) {
156
196
  return globalPathMatch[1].trim();
@@ -159,24 +199,34 @@ function getEffectiveRRCEHome(workspaceRoot) {
159
199
  }
160
200
  }
161
201
  }
162
- return getDefaultRRCEHome();
202
+ return getDefaultRRCEHome2();
163
203
  }
164
204
  var RRCE_HOME, RRCE_WORKSPACE;
165
205
  var init_paths = __esm({
166
206
  "src/lib/paths.ts"() {
167
207
  "use strict";
168
- RRCE_HOME = process.env.RRCE_HOME || path.join(process.env.HOME || "~", ".rrce-workflow");
208
+ init_preferences();
209
+ RRCE_HOME = process.env.RRCE_HOME || path2.join(process.env.HOME || "~", ".rrce-workflow");
169
210
  RRCE_WORKSPACE = process.env.RRCE_WORKSPACE;
170
211
  }
171
212
  });
172
213
 
173
214
  // src/lib/detection.ts
174
- import * as fs2 from "fs";
175
- import * as path2 from "path";
215
+ import * as fs3 from "fs";
216
+ import * as path3 from "path";
176
217
  function scanForProjects(options = {}) {
177
- const { excludeWorkspace, workspacePath } = options;
218
+ const { excludeWorkspace, workspacePath, knownPaths } = options;
178
219
  const projects = [];
179
220
  const seenPaths = /* @__PURE__ */ new Set();
221
+ if (knownPaths && knownPaths.length > 0) {
222
+ const explicitProjects = scanKnownPaths(knownPaths, excludeWorkspace);
223
+ for (const project of explicitProjects) {
224
+ if (!seenPaths.has(project.dataPath)) {
225
+ seenPaths.add(project.dataPath);
226
+ projects.push(project);
227
+ }
228
+ }
229
+ }
180
230
  const globalProjects = scanGlobalStorage(excludeWorkspace);
181
231
  for (const project of globalProjects) {
182
232
  if (!seenPaths.has(project.dataPath)) {
@@ -193,23 +243,54 @@ function scanForProjects(options = {}) {
193
243
  }
194
244
  return projects;
195
245
  }
246
+ function scanKnownPaths(paths, excludeWorkspace) {
247
+ const projects = [];
248
+ for (const p of paths) {
249
+ try {
250
+ if (!fs3.existsSync(p)) continue;
251
+ const localConfigPath = path3.join(p, ".rrce-workflow", "config.yaml");
252
+ if (fs3.existsSync(localConfigPath)) {
253
+ const config = parseWorkspaceConfig(localConfigPath);
254
+ if (config?.name === excludeWorkspace) continue;
255
+ const fullPath = path3.join(p, ".rrce-workflow");
256
+ const knowledgePath = path3.join(fullPath, "knowledge");
257
+ const refsPath = path3.join(fullPath, "refs");
258
+ const tasksPath = path3.join(fullPath, "tasks");
259
+ projects.push({
260
+ name: config?.name || path3.basename(p),
261
+ path: p,
262
+ dataPath: fullPath,
263
+ source: "local",
264
+ storageMode: config?.storageMode,
265
+ knowledgePath: fs3.existsSync(knowledgePath) ? knowledgePath : void 0,
266
+ refsPath: fs3.existsSync(refsPath) ? refsPath : void 0,
267
+ tasksPath: fs3.existsSync(tasksPath) ? tasksPath : void 0,
268
+ semanticSearchEnabled: config?.semanticSearchEnabled
269
+ });
270
+ continue;
271
+ }
272
+ } catch {
273
+ }
274
+ }
275
+ return projects;
276
+ }
196
277
  function scanGlobalStorage(excludeWorkspace) {
197
- const rrceHome = getDefaultRRCEHome();
198
- const workspacesDir = path2.join(rrceHome, "workspaces");
278
+ const rrceHome = getEffectiveGlobalPath();
279
+ const workspacesDir = path3.join(rrceHome, "workspaces");
199
280
  const projects = [];
200
- if (!fs2.existsSync(workspacesDir)) {
281
+ if (!fs3.existsSync(workspacesDir)) {
201
282
  return projects;
202
283
  }
203
284
  try {
204
- const entries = fs2.readdirSync(workspacesDir, { withFileTypes: true });
285
+ const entries = fs3.readdirSync(workspacesDir, { withFileTypes: true });
205
286
  for (const entry of entries) {
206
287
  if (!entry.isDirectory()) continue;
207
288
  if (entry.name === excludeWorkspace) continue;
208
- const projectDataPath = path2.join(workspacesDir, entry.name);
209
- const knowledgePath = path2.join(projectDataPath, "knowledge");
210
- const refsPath = path2.join(projectDataPath, "refs");
211
- const tasksPath = path2.join(projectDataPath, "tasks");
212
- const configPath = path2.join(projectDataPath, "config.yaml");
289
+ const projectDataPath = path3.join(workspacesDir, entry.name);
290
+ const knowledgePath = path3.join(projectDataPath, "knowledge");
291
+ const refsPath = path3.join(projectDataPath, "refs");
292
+ const tasksPath = path3.join(projectDataPath, "tasks");
293
+ const configPath = path3.join(projectDataPath, "config.yaml");
213
294
  const config = parseWorkspaceConfig(configPath);
214
295
  projects.push({
215
296
  name: config?.name || entry.name,
@@ -219,9 +300,9 @@ function scanGlobalStorage(excludeWorkspace) {
219
300
  // ...expose sourcePath if available
220
301
  dataPath: projectDataPath,
221
302
  source: "global",
222
- knowledgePath: fs2.existsSync(knowledgePath) ? knowledgePath : void 0,
223
- refsPath: fs2.existsSync(refsPath) ? refsPath : void 0,
224
- tasksPath: fs2.existsSync(tasksPath) ? tasksPath : void 0,
303
+ knowledgePath: fs3.existsSync(knowledgePath) ? knowledgePath : void 0,
304
+ refsPath: fs3.existsSync(refsPath) ? refsPath : void 0,
305
+ tasksPath: fs3.existsSync(tasksPath) ? tasksPath : void 0,
225
306
  semanticSearchEnabled: config?.semanticSearchEnabled
226
307
  });
227
308
  }
@@ -237,29 +318,29 @@ function scanHomeDirectory(excludePath) {
237
318
  function scanDir(dirPath, depth) {
238
319
  if (depth > maxDepth) return;
239
320
  try {
240
- const entries = fs2.readdirSync(dirPath, { withFileTypes: true });
321
+ const entries = fs3.readdirSync(dirPath, { withFileTypes: true });
241
322
  for (const entry of entries) {
242
323
  if (!entry.isDirectory()) continue;
243
- const fullPath = path2.join(dirPath, entry.name);
324
+ const fullPath = path3.join(dirPath, entry.name);
244
325
  if (excludePath && fullPath === excludePath) continue;
245
326
  if (entry.name === ".rrce-workflow") {
246
- const configPath = path2.join(fullPath, "config.yaml");
247
- if (fs2.existsSync(configPath)) {
327
+ const configPath = path3.join(fullPath, "config.yaml");
328
+ if (fs3.existsSync(configPath)) {
248
329
  const projectPath = dirPath;
249
- const projectName = path2.basename(projectPath);
330
+ const projectName = path3.basename(projectPath);
250
331
  const config = parseWorkspaceConfig(configPath);
251
- const knowledgePath = path2.join(fullPath, "knowledge");
252
- const refsPath = path2.join(fullPath, "refs");
253
- const tasksPath = path2.join(fullPath, "tasks");
332
+ const knowledgePath = path3.join(fullPath, "knowledge");
333
+ const refsPath = path3.join(fullPath, "refs");
334
+ const tasksPath = path3.join(fullPath, "tasks");
254
335
  projects.push({
255
336
  name: config?.name || projectName,
256
337
  path: projectPath,
257
338
  dataPath: fullPath,
258
339
  source: "local",
259
340
  storageMode: config?.storageMode,
260
- knowledgePath: fs2.existsSync(knowledgePath) ? knowledgePath : void 0,
261
- refsPath: fs2.existsSync(refsPath) ? refsPath : void 0,
262
- tasksPath: fs2.existsSync(tasksPath) ? tasksPath : void 0,
341
+ knowledgePath: fs3.existsSync(knowledgePath) ? knowledgePath : void 0,
342
+ refsPath: fs3.existsSync(refsPath) ? refsPath : void 0,
343
+ tasksPath: fs3.existsSync(tasksPath) ? tasksPath : void 0,
263
344
  semanticSearchEnabled: config?.semanticSearchEnabled
264
345
  });
265
346
  }
@@ -277,7 +358,7 @@ function scanHomeDirectory(excludePath) {
277
358
  }
278
359
  function parseWorkspaceConfig(configPath) {
279
360
  try {
280
- const content = fs2.readFileSync(configPath, "utf-8");
361
+ const content = fs3.readFileSync(configPath, "utf-8");
281
362
  const nameMatch = content.match(/name:\s*["']?([^"'\n]+)["']?/);
282
363
  const sourcePathMatch = content.match(/sourcePath:\s*["']?([^"'\n]+)["']?/);
283
364
  const modeMatch = content.match(/mode:\s*(global|workspace)/);
@@ -295,7 +376,7 @@ function parseWorkspaceConfig(configPath) {
295
376
  const semanticSearchMatch = content.match(/semantic_search:\s*\n\s*enabled:\s*(true|false)/);
296
377
  const semanticSearchEnabled = semanticSearchMatch ? semanticSearchMatch[1] === "true" : false;
297
378
  return {
298
- name: nameMatch?.[1]?.trim() || path2.basename(path2.dirname(path2.dirname(configPath))),
379
+ name: nameMatch?.[1]?.trim() || path3.basename(path3.dirname(path3.dirname(configPath))),
299
380
  sourcePath: sourcePathMatch?.[1]?.trim(),
300
381
  storageMode: modeMatch?.[1] || "global",
301
382
  linkedProjects: linkedProjects.length > 0 ? linkedProjects : void 0,
@@ -401,8 +482,8 @@ var init_detection_service = __esm({
401
482
  });
402
483
 
403
484
  // src/lib/autocomplete-prompt.ts
404
- import * as fs3 from "fs";
405
- import * as path3 from "path";
485
+ import * as fs4 from "fs";
486
+ import * as path4 from "path";
406
487
  import * as readline from "readline";
407
488
  import pc from "picocolors";
408
489
  function directoryPrompt(opts) {
@@ -461,19 +542,19 @@ function completeDirectory(line) {
461
542
  prefix = "";
462
543
  basePath = expanded;
463
544
  } else {
464
- dirToScan = path3.dirname(expanded);
465
- prefix = path3.basename(expanded).toLowerCase();
545
+ dirToScan = path4.dirname(expanded);
546
+ prefix = path4.basename(expanded).toLowerCase();
466
547
  basePath = dirToScan === "/" ? "/" : dirToScan + "/";
467
548
  }
468
- if (!fs3.existsSync(dirToScan)) {
549
+ if (!fs4.existsSync(dirToScan)) {
469
550
  return [[], line];
470
551
  }
471
- const entries = fs3.readdirSync(dirToScan, { withFileTypes: true }).filter((entry) => {
552
+ const entries = fs4.readdirSync(dirToScan, { withFileTypes: true }).filter((entry) => {
472
553
  if (!entry.isDirectory()) return false;
473
554
  if (entry.name.startsWith(".") && !prefix.startsWith(".")) return false;
474
555
  return prefix === "" || entry.name.toLowerCase().startsWith(prefix);
475
556
  }).map((entry) => {
476
- const fullPath = path3.join(dirToScan, entry.name);
557
+ const fullPath = path4.join(dirToScan, entry.name);
477
558
  const displayPath = fullPath.startsWith(process.env.HOME || "") ? fullPath.replace(process.env.HOME || "", "~") : fullPath;
478
559
  return displayPath + "/";
479
560
  }).sort();
@@ -512,38 +593,6 @@ var init_autocomplete_prompt = __esm({
512
593
  }
513
594
  });
514
595
 
515
- // src/lib/preferences.ts
516
- import * as fs4 from "fs";
517
- import * as path4 from "path";
518
- function getPreferencesPath() {
519
- const home = process.env.HOME || "~";
520
- return path4.join(home, ".rrce-workflow", "preferences.json");
521
- }
522
- function loadUserPreferences() {
523
- const prefPath = getPreferencesPath();
524
- if (!fs4.existsSync(prefPath)) {
525
- return {};
526
- }
527
- try {
528
- return JSON.parse(fs4.readFileSync(prefPath, "utf-8"));
529
- } catch {
530
- return {};
531
- }
532
- }
533
- function saveUserPreferences(prefs) {
534
- const prefPath = getPreferencesPath();
535
- ensureDir(path4.dirname(prefPath));
536
- const current = loadUserPreferences();
537
- const refined = { ...current, ...prefs };
538
- fs4.writeFileSync(prefPath, JSON.stringify(refined, null, 2));
539
- }
540
- var init_preferences = __esm({
541
- "src/lib/preferences.ts"() {
542
- "use strict";
543
- init_paths();
544
- }
545
- });
546
-
547
596
  // src/lib/tui-utils.ts
548
597
  var tui_utils_exports = {};
549
598
  __export(tui_utils_exports, {
@@ -554,7 +603,7 @@ import pc2 from "picocolors";
554
603
  import * as path5 from "path";
555
604
  async function resolveGlobalPath() {
556
605
  const prefs = loadUserPreferences();
557
- const defaultPath = prefs.defaultGlobalPath || getDefaultRRCEHome();
606
+ const defaultPath = prefs.defaultGlobalPath || getDefaultRRCEHome2();
558
607
  const isDefaultWritable = checkWriteAccess(defaultPath);
559
608
  const options = [
560
609
  {
@@ -590,7 +639,7 @@ Please choose a custom path instead.`,
590
639
  }
591
640
  return defaultPath;
592
641
  }
593
- const suggestedPath = path5.join(process.env.HOME || "~", ".local", "share", "rrce-workflow");
642
+ const suggestedPath = path5.join(process.env.HOME || "~", ".rrce-workflow");
594
643
  const customPath = await directoryPrompt({
595
644
  message: "Enter custom global path (Tab to autocomplete):",
596
645
  defaultValue: suggestedPath,
@@ -611,7 +660,7 @@ Please choose a custom path instead.`,
611
660
  if (!expandedPath.endsWith(".rrce-workflow")) {
612
661
  expandedPath = path5.join(expandedPath, ".rrce-workflow");
613
662
  }
614
- saveUserPreferences({ defaultGlobalPath: expandedPath });
663
+ saveUserPreferences({ defaultGlobalPath: expandedPath, useCustomGlobalPath: true });
615
664
  return expandedPath;
616
665
  }
617
666
  var init_tui_utils = __esm({
@@ -1134,7 +1183,7 @@ function getProjectPermissions(config, name, projectPath) {
1134
1183
  return project?.permissions ?? config.defaults.permissions;
1135
1184
  }
1136
1185
  function cleanStaleProjects(config) {
1137
- const rrceHome = getEffectiveRRCEHome();
1186
+ const rrceHome = getEffectiveGlobalPath();
1138
1187
  const globalWorkspacesDir = path9.join(rrceHome, "workspaces");
1139
1188
  const validProjects = [];
1140
1189
  const removed = [];
@@ -1202,7 +1251,7 @@ function installAgentPrompts(config, workspacePath, dataPaths) {
1202
1251
  function createWorkspaceConfig(config, workspacePath, workspaceName) {
1203
1252
  let configPath;
1204
1253
  if (config.storageMode === "global") {
1205
- const rrceHome = config.globalPath || getDefaultRRCEHome();
1254
+ const rrceHome = config.globalPath || getDefaultRRCEHome2();
1206
1255
  configPath = path10.join(rrceHome, "workspaces", workspaceName, "config.yaml");
1207
1256
  } else {
1208
1257
  configPath = path10.join(workspacePath, ".rrce-workflow", "config.yaml");
@@ -1213,7 +1262,7 @@ version: 1
1213
1262
 
1214
1263
  storage:
1215
1264
  mode: ${config.storageMode}`;
1216
- if (config.globalPath && config.globalPath !== getDefaultRRCEHome()) {
1265
+ if (config.globalPath && config.globalPath !== getDefaultRRCEHome2()) {
1217
1266
  content += `
1218
1267
  globalPath: "${config.globalPath}"`;
1219
1268
  }
@@ -1249,25 +1298,14 @@ async function registerWithMCP(config, workspacePath, workspaceName) {
1249
1298
  try {
1250
1299
  const { loadMCPConfig: loadMCPConfig3, saveMCPConfig: saveMCPConfig2, setProjectConfig: setProjectConfig2 } = await Promise.resolve().then(() => (init_config(), config_exports));
1251
1300
  const mcpConfig = loadMCPConfig3();
1252
- if (config.storageMode === "workspace") {
1253
- setProjectConfig2(
1254
- mcpConfig,
1255
- workspaceName,
1256
- true,
1257
- void 0,
1258
- void 0,
1259
- config.enableRAG ? { enabled: true } : void 0
1260
- );
1261
- } else {
1262
- setProjectConfig2(
1263
- mcpConfig,
1264
- workspaceName,
1265
- true,
1266
- void 0,
1267
- workspacePath,
1268
- config.enableRAG ? { enabled: true } : void 0
1269
- );
1270
- }
1301
+ setProjectConfig2(
1302
+ mcpConfig,
1303
+ workspaceName,
1304
+ true,
1305
+ void 0,
1306
+ workspacePath,
1307
+ config.enableRAG ? { enabled: true } : void 0
1308
+ );
1271
1309
  saveMCPConfig2(mcpConfig);
1272
1310
  } catch (e) {
1273
1311
  note2(
@@ -1280,7 +1318,7 @@ You can configure MCP later: ${pc4.cyan("npx rrce-workflow mcp")}`,
1280
1318
  }
1281
1319
  }
1282
1320
  function getDataPaths(mode, workspaceName, workspaceRoot, customGlobalPath) {
1283
- const globalPath = path10.join(customGlobalPath || getDefaultRRCEHome(), "workspaces", workspaceName);
1321
+ const globalPath = path10.join(customGlobalPath || getDefaultRRCEHome2(), "workspaces", workspaceName);
1284
1322
  const workspacePath = path10.join(workspaceRoot, ".rrce-workflow");
1285
1323
  switch (mode) {
1286
1324
  case "global":
@@ -1664,7 +1702,8 @@ import * as fs13 from "fs";
1664
1702
  import * as path14 from "path";
1665
1703
  function getExposedProjects() {
1666
1704
  const config = loadMCPConfig();
1667
- const allProjects = projectService.scan();
1705
+ const knownPaths = config.projects.map((p) => p.path).filter((p) => !!p);
1706
+ const allProjects = projectService.scan({ knownPaths });
1668
1707
  const globalProjects = allProjects.filter((project) => isProjectExposed(config, project.name, project.dataPath));
1669
1708
  const activeProject = detectActiveProject(globalProjects);
1670
1709
  let linkedProjects = [];
@@ -1716,7 +1755,8 @@ function detectActiveProject(knownProjects) {
1716
1755
  let scanList = knownProjects;
1717
1756
  if (!scanList) {
1718
1757
  const config = loadMCPConfig();
1719
- const all = projectService.scan();
1758
+ const knownPaths = config.projects.map((p) => p.path).filter((p) => !!p);
1759
+ const all = projectService.scan({ knownPaths });
1720
1760
  scanList = all.filter((project) => isProjectExposed(config, project.name, project.dataPath));
1721
1761
  }
1722
1762
  return findClosestProject(scanList);
@@ -2285,6 +2325,7 @@ import {
2285
2325
  ListPromptsRequestSchema,
2286
2326
  GetPromptRequestSchema
2287
2327
  } from "@modelcontextprotocol/sdk/types.js";
2328
+ import * as path15 from "path";
2288
2329
  function registerPromptHandlers(server) {
2289
2330
  server.setRequestHandler(ListPromptsRequestSchema, async () => {
2290
2331
  logger.debug("Listing prompts");
@@ -2319,8 +2360,35 @@ function registerPromptHandlers(server) {
2319
2360
  for (const [key, val] of Object.entries(providedArgs)) {
2320
2361
  renderArgs[key] = String(val);
2321
2362
  }
2363
+ const activeProject = detectActiveProject();
2364
+ const DEFAULT_RRCE_HOME = getEffectiveGlobalPath();
2365
+ let resolvedRrceData = ".rrce-workflow/";
2366
+ let resolvedRrceHome = DEFAULT_RRCE_HOME;
2367
+ let resolvedWorkspaceRoot = process.cwd();
2368
+ let resolvedWorkspaceName = "current-project";
2369
+ if (activeProject) {
2370
+ resolvedRrceData = activeProject.dataPath + "/";
2371
+ resolvedWorkspaceRoot = activeProject.sourcePath || activeProject.path || activeProject.dataPath;
2372
+ resolvedWorkspaceName = activeProject.name;
2373
+ if (activeProject.source === "global") {
2374
+ const workspacesDir = path15.dirname(activeProject.dataPath);
2375
+ resolvedRrceHome = path15.dirname(workspacesDir);
2376
+ }
2377
+ }
2378
+ if (!renderArgs["RRCE_DATA"]) renderArgs["RRCE_DATA"] = resolvedRrceData;
2379
+ if (!renderArgs["RRCE_HOME"]) renderArgs["RRCE_HOME"] = resolvedRrceHome;
2380
+ if (!renderArgs["WORKSPACE_ROOT"]) renderArgs["WORKSPACE_ROOT"] = resolvedWorkspaceRoot;
2381
+ if (!renderArgs["WORKSPACE_NAME"]) renderArgs["WORKSPACE_NAME"] = resolvedWorkspaceName;
2322
2382
  const content = renderPrompt(promptDef.content, renderArgs);
2323
- const contextPreamble = getContextPreamble();
2383
+ let contextPreamble = getContextPreamble();
2384
+ contextPreamble += `
2385
+ ### System Resolved Paths (OVERRIDE)
2386
+ The system has pre-resolved the configuration for this project. Use these values instead of manual resolution:
2387
+ - **RRCE_DATA**: \`${resolvedRrceData}\` (Stores knowledge, tasks, refs)
2388
+ - **WORKSPACE_ROOT**: \`${resolvedWorkspaceRoot}\` (Source code location)
2389
+ - **RRCE_HOME**: \`${resolvedRrceHome}\`
2390
+ - **Current Project**: ${resolvedWorkspaceName}
2391
+ `;
2324
2392
  return {
2325
2393
  messages: [
2326
2394
  {
@@ -2344,6 +2412,7 @@ var init_prompts3 = __esm({
2344
2412
  init_logger();
2345
2413
  init_resources();
2346
2414
  init_prompts2();
2415
+ init_paths();
2347
2416
  }
2348
2417
  });
2349
2418
 
@@ -2426,7 +2495,7 @@ var init_server = __esm({
2426
2495
 
2427
2496
  // src/mcp/install.ts
2428
2497
  import * as fs14 from "fs";
2429
- import * as path15 from "path";
2498
+ import * as path16 from "path";
2430
2499
  import * as os from "os";
2431
2500
  function checkInstallStatus(workspacePath) {
2432
2501
  return {
@@ -2464,7 +2533,7 @@ function checkVSCodeGlobalConfig() {
2464
2533
  }
2465
2534
  }
2466
2535
  function checkVSCodeWorkspaceConfig(workspacePath) {
2467
- const configPath = path15.join(workspacePath, ".vscode", "mcp.json");
2536
+ const configPath = path16.join(workspacePath, ".vscode", "mcp.json");
2468
2537
  if (!fs14.existsSync(configPath)) return false;
2469
2538
  try {
2470
2539
  const content = JSON.parse(fs14.readFileSync(configPath, "utf-8"));
@@ -2492,7 +2561,7 @@ function installToConfig(target, workspacePath) {
2492
2561
  }
2493
2562
  }
2494
2563
  function installToAntigravity() {
2495
- const dir = path15.dirname(ANTIGRAVITY_CONFIG);
2564
+ const dir = path16.dirname(ANTIGRAVITY_CONFIG);
2496
2565
  if (!fs14.existsSync(dir)) {
2497
2566
  fs14.mkdirSync(dir, { recursive: true });
2498
2567
  }
@@ -2516,7 +2585,7 @@ function installToAntigravity() {
2516
2585
  }
2517
2586
  }
2518
2587
  function installToClaude() {
2519
- const dir = path15.dirname(CLAUDE_CONFIG);
2588
+ const dir = path16.dirname(CLAUDE_CONFIG);
2520
2589
  if (!fs14.existsSync(dir)) {
2521
2590
  fs14.mkdirSync(dir, { recursive: true });
2522
2591
  }
@@ -2540,7 +2609,7 @@ function installToClaude() {
2540
2609
  }
2541
2610
  }
2542
2611
  function installToVSCodeGlobal() {
2543
- const dir = path15.dirname(VSCODE_GLOBAL_CONFIG);
2612
+ const dir = path16.dirname(VSCODE_GLOBAL_CONFIG);
2544
2613
  if (!fs14.existsSync(dir)) {
2545
2614
  fs14.mkdirSync(dir, { recursive: true });
2546
2615
  }
@@ -2564,8 +2633,8 @@ function installToVSCodeGlobal() {
2564
2633
  }
2565
2634
  }
2566
2635
  function installToVSCodeWorkspace(workspacePath) {
2567
- const vscodeDir = path15.join(workspacePath, ".vscode");
2568
- const configPath = path15.join(vscodeDir, "mcp.json");
2636
+ const vscodeDir = path16.join(workspacePath, ".vscode");
2637
+ const configPath = path16.join(vscodeDir, "mcp.json");
2569
2638
  if (!fs14.existsSync(vscodeDir)) {
2570
2639
  fs14.mkdirSync(vscodeDir, { recursive: true });
2571
2640
  }
@@ -2606,9 +2675,9 @@ var ANTIGRAVITY_CONFIG, CLAUDE_CONFIG, VSCODE_GLOBAL_CONFIG;
2606
2675
  var init_install = __esm({
2607
2676
  "src/mcp/install.ts"() {
2608
2677
  "use strict";
2609
- ANTIGRAVITY_CONFIG = path15.join(os.homedir(), ".gemini/antigravity/mcp_config.json");
2610
- CLAUDE_CONFIG = path15.join(os.homedir(), ".config/claude/claude_desktop_config.json");
2611
- VSCODE_GLOBAL_CONFIG = path15.join(os.homedir(), ".config/Code/User/settings.json");
2678
+ ANTIGRAVITY_CONFIG = path16.join(os.homedir(), ".gemini/antigravity/mcp_config.json");
2679
+ CLAUDE_CONFIG = path16.join(os.homedir(), ".config/claude/claude_desktop_config.json");
2680
+ VSCODE_GLOBAL_CONFIG = path16.join(os.homedir(), ".config/Code/User/settings.json");
2612
2681
  }
2613
2682
  });
2614
2683
 
@@ -2619,7 +2688,8 @@ async function handleConfigure() {
2619
2688
  const s = spinner();
2620
2689
  s.start("Scanning for projects...");
2621
2690
  const config = loadMCPConfig();
2622
- const projects = scanForProjects();
2691
+ const knownPaths = config.projects.map((p) => p.path).filter((p) => !!p);
2692
+ const projects = scanForProjects({ knownPaths });
2623
2693
  logger.info("Configure: Loaded config", { projects: config.projects, defaultMode: config.defaults.includeNew });
2624
2694
  s.stop("Projects found");
2625
2695
  if (projects.length === 0) {
@@ -2694,7 +2764,7 @@ Hidden projects: ${projects.length - exposedCount}`,
2694
2764
  async function handleConfigureGlobalPath() {
2695
2765
  const { resolveGlobalPath: resolveGlobalPath2 } = await Promise.resolve().then(() => (init_tui_utils(), tui_utils_exports));
2696
2766
  const fs21 = await import("fs");
2697
- const path19 = await import("path");
2767
+ const path20 = await import("path");
2698
2768
  note3(
2699
2769
  `MCP Hub requires a ${pc5.bold("global storage path")} to store its configuration
2700
2770
  and coordinate across projects.
@@ -2717,7 +2787,7 @@ locally in each project. MCP needs a central location.`,
2717
2787
  `${pc5.green("\u2713")} Global path configured: ${pc5.cyan(resolvedPath)}
2718
2788
 
2719
2789
  MCP config will be stored at:
2720
- ${path19.join(resolvedPath, "mcp.yaml")}`,
2790
+ ${path20.join(resolvedPath, "mcp.yaml")}`,
2721
2791
  "Configuration Saved"
2722
2792
  );
2723
2793
  return true;
@@ -4073,14 +4143,14 @@ var init_link_flow = __esm({
4073
4143
  import { confirm as confirm7, spinner as spinner5, note as note10, outro as outro4, cancel as cancel5, isCancel as isCancel9 } from "@clack/prompts";
4074
4144
  import pc12 from "picocolors";
4075
4145
  import * as fs17 from "fs";
4076
- import * as path16 from "path";
4146
+ import * as path17 from "path";
4077
4147
  async function runSyncToGlobalFlow(workspacePath, workspaceName) {
4078
4148
  const localPath = getLocalWorkspacePath(workspacePath);
4079
4149
  const customGlobalPath = getEffectiveRRCEHome(workspacePath);
4080
- const globalPath = path16.join(customGlobalPath, "workspaces", workspaceName);
4150
+ const globalPath = path17.join(customGlobalPath, "workspaces", workspaceName);
4081
4151
  const subdirs = ["knowledge", "prompts", "templates", "tasks", "refs"];
4082
4152
  const existingDirs = subdirs.filter(
4083
- (dir) => fs17.existsSync(path16.join(localPath, dir))
4153
+ (dir) => fs17.existsSync(path17.join(localPath, dir))
4084
4154
  );
4085
4155
  if (existingDirs.length === 0) {
4086
4156
  outro4(pc12.yellow("No data found in workspace storage to sync."));
@@ -4106,8 +4176,8 @@ Destination: ${pc12.cyan(globalPath)}`,
4106
4176
  try {
4107
4177
  ensureDir(globalPath);
4108
4178
  for (const dir of existingDirs) {
4109
- const srcDir = path16.join(localPath, dir);
4110
- const destDir = path16.join(globalPath, dir);
4179
+ const srcDir = path17.join(localPath, dir);
4180
+ const destDir = path17.join(globalPath, dir);
4111
4181
  ensureDir(destDir);
4112
4182
  copyDirRecursive(srcDir, destDir);
4113
4183
  }
@@ -4140,7 +4210,7 @@ var init_sync_flow = __esm({
4140
4210
  import { confirm as confirm8, spinner as spinner6, note as note11, outro as outro5, cancel as cancel6, isCancel as isCancel10 } from "@clack/prompts";
4141
4211
  import pc13 from "picocolors";
4142
4212
  import * as fs18 from "fs";
4143
- import * as path17 from "path";
4213
+ import * as path18 from "path";
4144
4214
  async function runUpdateFlow(workspacePath, workspaceName, currentStorageMode) {
4145
4215
  const s = spinner6();
4146
4216
  s.start("Checking for updates");
@@ -4170,7 +4240,7 @@ ${dataPaths.map((p) => ` \u2022 ${p}`).join("\n")}`,
4170
4240
  }
4171
4241
  s.start("Updating from package");
4172
4242
  for (const dataPath of dataPaths) {
4173
- copyDirToAllStoragePaths(path17.join(agentCoreDir, "templates"), "templates", [dataPath]);
4243
+ copyDirToAllStoragePaths(path18.join(agentCoreDir, "templates"), "templates", [dataPath]);
4174
4244
  }
4175
4245
  const configFilePath = getConfigPath(workspacePath);
4176
4246
  if (fs18.existsSync(configFilePath)) {
@@ -4203,8 +4273,8 @@ ${dataPaths.map((p) => ` \u2022 ${p}`).join("\n")}`,
4203
4273
  }
4204
4274
  }
4205
4275
  function resolveAllDataPathsWithCustomGlobal(mode, workspaceName, workspaceRoot, customGlobalPath) {
4206
- const globalPath = path17.join(customGlobalPath, "workspaces", workspaceName);
4207
- const workspacePath = path17.join(workspaceRoot, ".rrce-workflow");
4276
+ const globalPath = path18.join(customGlobalPath, "workspaces", workspaceName);
4277
+ const workspacePath = path18.join(workspaceRoot, ".rrce-workflow");
4208
4278
  switch (mode) {
4209
4279
  case "global":
4210
4280
  return [globalPath];
@@ -4436,9 +4506,9 @@ init_wizard();
4436
4506
  init_prompts();
4437
4507
  import { intro as intro3, select as select6, note as note14, cancel as cancel9, isCancel as isCancel13, outro as outro8 } from "@clack/prompts";
4438
4508
  import pc16 from "picocolors";
4439
- import * as path18 from "path";
4509
+ import * as path19 from "path";
4440
4510
  async function runSelector() {
4441
- const workspaceName = path18.basename(process.cwd());
4511
+ const workspaceName = path19.basename(process.cwd());
4442
4512
  intro3(pc16.cyan(pc16.inverse(` RRCE-Workflow | ${workspaceName} `)));
4443
4513
  const prompts = loadPromptsFromDir(getAgentCorePromptsDir());
4444
4514
  if (prompts.length === 0) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rrce-workflow",
3
- "version": "0.2.63",
3
+ "version": "0.2.65",
4
4
  "description": "RRCE-Workflow TUI - Agentic code workflow generator for AI-assisted development",
5
5
  "author": "RRCE Team",
6
6
  "license": "MIT",