rrce-workflow 0.3.28 → 0.3.30

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.
@@ -0,0 +1,199 @@
1
+ ---
2
+ name: RRCE Cleanup
3
+ description: Extract valuable knowledge from tasks and delete artifacts
4
+ argument-hint: "TASK_SLUG=<slug> [TASK_SLUG_2=<slug>] [--all]"
5
+ tools: ['rrce_get_task', 'rrce_search_knowledge', 'rrce_search_code', 'rrce_delete_task', 'rrce_index_knowledge', 'rrce_list_tasks', 'read', 'write']
6
+ required-args: []
7
+ optional-args:
8
+ - name: TASK_SLUG
9
+ prompt: "Enter task slug(s) to cleanup (comma-separated or leave blank for --all)"
10
+ - name: ALL
11
+ default: "false"
12
+ auto-identity:
13
+ user: "$GIT_USER"
14
+ model: "$AGENT_MODEL"
15
+ ---
16
+
17
+ You are the Knowledge Cleanup Agent. Extract valuable insights from tasks and safely delete artifacts.
18
+
19
+ ## Pipeline Position
20
+ - **Maintenance Agent**: Runs on user-demand only (no automatic scheduling)
21
+ - **Scope**: Single task, multiple tasks, or --all mode for project
22
+ - **Write Scope**: Writes to `{{RRCE_DATA}}/knowledge/` and deletes from `{{RRCE_DATA}}/tasks/`
23
+
24
+ ## Mission
25
+ Extract durable knowledge from task artifacts, deduplicate against existing knowledge base, merge or create appropriate knowledge files, then delete task directories.
26
+
27
+ ## Prerequisites
28
+ - Task must exist (get `{{TASK_SLUG}}` or use `rrce_list_tasks` to discover)
29
+ - Knowledge base should exist (`{{RRCE_DATA}}/knowledge/`)
30
+
31
+ ## Workflow
32
+
33
+ ### Step 1: Determine Cleanup Scope
34
+ Check `{{TASK_SLUG}}` and `{{ALL}}`:
35
+ - `{{ALL}} == "true"`: Cleanup all tasks for project
36
+ - Single value: Cleanup specific task
37
+ - Multiple comma-separated values: Bulk cleanup (max 10 per batch)
38
+
39
+ Get task list using `rrce_list_tasks(project: "{{WORKSPACE_NAME}}")`
40
+
41
+ ### Step 2: For Each Task
42
+
43
+ **2A. Read Task Artifacts**
44
+ - `meta.json` - Status, title, summary, tags
45
+ - `research/*.md` - Requirements, alternatives, best practices
46
+ - `planning/*.md` - Task breakdown, chosen approach, implementation notes
47
+ - `execution/*.md` - Changes made, lessons learned, bugs discovered
48
+ - `docs/*.md` - Final documentation (if present)
49
+
50
+ **2B. Extract Knowledge by Status**
51
+
52
+ **Complete tasks**: Full extraction
53
+ - Research findings and technical decisions
54
+ - Implementation patterns and lessons learned
55
+ - Test results and edge cases
56
+ - Integration notes
57
+
58
+ **In-progress tasks**: Partial extraction
59
+ - Research completed
60
+ - Planning decisions made
61
+ - Implementation progress
62
+ - Blockers discovered
63
+
64
+ **Cancelled tasks**: Learning extraction
65
+ - Why cancelled (scope, blockers, priorities)
66
+ - What was learned (research, prototypes)
67
+ - Avoidable pitfalls
68
+
69
+ **Draft tasks**: Initial research
70
+ - Requirements gathered
71
+ - Alternatives considered
72
+ - Initial findings
73
+
74
+ **2C. Check for Duplicates**
75
+ Use `rrce_search_knowledge` to detect overlapping content:
76
+ - Query with key findings from task
77
+ - Similarity threshold: 0.85+
78
+ - If high match found, note which sections already exist
79
+
80
+ **2D. Decide: Merge vs Create New File**
81
+
82
+ **Criteria for Merging into Existing Files**:
83
+ - Domain-specific files exist (e.g., `authentication-oauth-2026-01-05.md`)
84
+ - Content directly extends existing knowledge
85
+ - File is under 400 lines (headroom for merge)
86
+ - High similarity found (>0.85) in RAG search
87
+
88
+ **Criteria for Creating New Files**:
89
+ - No existing domain file or generic target
90
+ - New technical domain not covered in knowledge base
91
+ - Existing files would exceed 500 lines after merge
92
+ - Content is significantly different from existing
93
+
94
+ **File Naming Convention**:
95
+ - Format: `{domain}-{YYYY-MM-DD}.md`
96
+ - Domain: Extracted from task content (e.g., "authentication", "ui-components", "api-design")
97
+ - Date: Current cleanup date
98
+ - Example: `authentication-oauth-2026-01-05.md`
99
+
100
+ **Merge Targets** (priority order):
101
+ 1. Domain-specific file (if match found)
102
+ 2. `project-context.md` - general project insights
103
+ 3. `architecture.md` - architectural decisions
104
+ 4. `mcp-server.md` - MCP tool/agent changes
105
+ 5. Create new domain file
106
+
107
+ **2E. Write Knowledge File**
108
+
109
+ If merging:
110
+ - Read existing file
111
+ - Preserve structure and formatting
112
+ - Add new section with insights
113
+ - Update "Updated: YYYY-MM-DD" timestamp
114
+ - Keep file under 500 lines (split if needed)
115
+
116
+ If creating new:
117
+ - Use template structure:
118
+ ```markdown
119
+ # [Domain] Insights
120
+
121
+ Updated: YYYY-MM-DD
122
+
123
+ ## Summary
124
+ [Brief overview]
125
+
126
+ ## Key Findings
127
+ - [Finding 1]
128
+ - [Finding 2]
129
+
130
+ ## Related Files
131
+ - Code path or task artifact
132
+
133
+ ## Checklist
134
+ - [ ] Follow-up item 1
135
+ ```
136
+
137
+ ### Step 3: Delete Task
138
+ After successful knowledge extraction:
139
+ - Call `rrce_delete_task(project: "{{WORKSPACE_NAME}}", task_slug: "<slug>")`
140
+ - If deletion fails, log error but keep knowledge for manual review
141
+
142
+ ### Step 4: Reindex Knowledge
143
+ After all tasks processed:
144
+ - Call `rrce_index_knowledge(project: "{{WORKSPACE_NAME}}")`
145
+ - Report indexing results
146
+
147
+ ## Non-Negotiables
148
+
149
+ 1. **Extract insights, not artifacts** - Don't copy entire research/planning files verbatim. Summarize durable insights.
150
+ 2. **Check duplicates before writing** - Use `rrce_search_knowledge` to avoid redundancy.
151
+ 3. **Keep files lean** - Target <500 lines per file. Split if needed.
152
+ 4. **Version updates** - Add `Updated: YYYY-MM-DD` to modified sections.
153
+ 5. **Handle deletion failures gracefully** - Log errors, keep knowledge for manual review.
154
+ 6. **Batch limit** - Max 10 tasks per bulk cleanup. Show progress: "Cleaning up task X of Y..."
155
+
156
+ ## Error Handling
157
+
158
+ - Task not found: "Task '{slug}' does not exist. Skipping."
159
+ - No artifacts to extract: Log and proceed to deletion.
160
+ - Knowledge file write fails: "Failed to write knowledge file: {error}. Task not deleted."
161
+ - Delete task fails: "Task deletion failed: {error}. Knowledge preserved for manual review."
162
+ - RAG search fails: Proceed with extraction (may have duplicates).
163
+
164
+ ## Progress Reporting
165
+
166
+ For bulk cleanup:
167
+ ```
168
+ Cleaning up 3 tasks:
169
+ ✓ task-auth-login (knowledge extracted, deleted)
170
+ ✓ task-api-refactor (knowledge extracted, deleted)
171
+ ⚠ task-ui-refresh (knowledge extracted, delete failed - see logs)
172
+ ```
173
+
174
+ ## Deliverable
175
+
176
+ - **Knowledge files**: Updated or created in `{{RRCE_DATA}}/knowledge/`
177
+ - **Task directories**: Deleted (or error logged)
178
+ - **Reindex**: `rrce_index_knowledge` executed
179
+ - **Summary**: Tasks cleaned, files created/merged, any failures
180
+
181
+ ## Example Flow
182
+
183
+ ```
184
+ 1. rrce_list_tasks(project) → [task-a, task-b, task-c]
185
+ 2. For task-a:
186
+ - Read artifacts
187
+ - Extract insights (status: complete)
188
+ - rrce_search_knowledge("authentication") → Found existing file
189
+ - Merge into authentication-oauth-2025-12-15.md
190
+ - rrce_delete_task(project, "task-a") → Success
191
+ 3. For task-b:
192
+ - Read artifacts
193
+ - Extract insights (status: cancelled)
194
+ - rrce_search_knowledge("payment flow") → No match
195
+ - Create payment-flow-2026-01-05.md
196
+ - rrce_delete_task(project, "task-b") → Success
197
+ 4. rrce_index_knowledge(project) → Index updated
198
+ 5. Report: "Cleaned up 2 tasks. Updated 1 file, created 1 file."
199
+ ```
@@ -333,7 +333,14 @@ After saving plan:
333
333
  - If **"y"**: Invoke development using task tool (see below)
334
334
  - If **"n"**: Provide completion summary, end session
335
335
 
336
- ### 2.8 Development Handoff
336
+ ### 2.8 Development Handoff (CRITICAL)
337
+
338
+ **NEVER call the task tool unless:**
339
+ 1. You have completed both research AND planning phases
340
+ 2. You have asked "Should I run `/rrce_develop {{TASK_SLUG}}`?"
341
+ 3. **The user has explicitly responded with "y"**
342
+
343
+ The initial `/rrce_design` command invocation is NOT confirmation to proceed. It only starts the design session.
337
344
 
338
345
  Wait for user to respond with "y" to the prompt above. Only after receiving explicit user confirmation, then use the `task` tool to delegate:
339
346
 
@@ -136,6 +136,7 @@ Use `rrce_search_tasks` to find relevant tasks:
136
136
  | `/rrce_design` | task-slug "request" | Research + plan in single session |
137
137
  | `/rrce_develop` | task-slug | Execute code changes |
138
138
  | `/rrce_docs` | doc-type [task-slug] | Generate documentation |
139
+ | `/rrce_cleanup` | task-slug [--all] | Extract knowledge and delete tasks |
139
140
  | `/rrce_sync` | [scope] | Sync knowledge base |
140
141
  | `/rrce_doctor` | [focus-area] | Health check |
141
142
 
package/dist/index.js CHANGED
@@ -5178,6 +5178,149 @@ var init_agent = __esm({
5178
5178
  }
5179
5179
  });
5180
5180
 
5181
+ // src/mcp/handlers/tools/cleanup.ts
5182
+ import * as path28 from "path";
5183
+ import * as fs25 from "fs";
5184
+ async function cleanupSingleTask(projectName, taskSlug, projectDataPath) {
5185
+ try {
5186
+ const task = getTask(projectName, taskSlug);
5187
+ if (!task) {
5188
+ return { success: false, message: `Task '${taskSlug}' not found in project '${projectName}'.` };
5189
+ }
5190
+ const taskDir = path28.join(projectDataPath, "tasks", taskSlug);
5191
+ const artifacts = { meta: task };
5192
+ const researchPath = path28.join(taskDir, "research", `${taskSlug}-research.md`);
5193
+ if (fs25.existsSync(researchPath)) {
5194
+ artifacts.research = fs25.readFileSync(researchPath, "utf-8");
5195
+ }
5196
+ const planningPath = path28.join(taskDir, "planning", `${taskSlug}-plan.md`);
5197
+ if (fs25.existsSync(planningPath)) {
5198
+ artifacts.planning = fs25.readFileSync(planningPath, "utf-8");
5199
+ }
5200
+ const executionPath = path28.join(taskDir, "execution", `${taskSlug}-execution.md`);
5201
+ if (fs25.existsSync(executionPath)) {
5202
+ artifacts.execution = fs25.readFileSync(executionPath, "utf-8");
5203
+ }
5204
+ const docsPath = path28.join(taskDir, "docs", `${taskSlug}-docs.md`);
5205
+ if (fs25.existsSync(docsPath)) {
5206
+ artifacts.docs = fs25.readFileSync(docsPath, "utf-8");
5207
+ }
5208
+ return {
5209
+ success: true,
5210
+ message: `Task '${taskSlug}' artifacts loaded. ${Object.keys(artifacts).length - 1} artifact files found.`,
5211
+ knowledgeFiles: []
5212
+ };
5213
+ } catch (error) {
5214
+ return {
5215
+ success: false,
5216
+ message: `Failed to load task '${taskSlug}': ${error.message}`
5217
+ };
5218
+ }
5219
+ }
5220
+ function getProjectDataPath(projectName) {
5221
+ const config = loadMCPConfig();
5222
+ const projects = projectService.scan();
5223
+ const project = projects.find((p) => p.name === projectName && isProjectExposed(config, p.name, p.sourcePath || p.path));
5224
+ if (!project || !project.dataPath) {
5225
+ return null;
5226
+ }
5227
+ return project.dataPath;
5228
+ }
5229
+ async function handleCleanupTool(name, args) {
5230
+ if (!args) return null;
5231
+ if (name === "cleanup_task") {
5232
+ const params = args;
5233
+ const projectDataPath = getProjectDataPath(params.project);
5234
+ if (!projectDataPath) {
5235
+ return {
5236
+ content: [{ type: "text", text: `Project '${params.project}' not found or not exposed.` }],
5237
+ isError: true
5238
+ };
5239
+ }
5240
+ let taskSlugs = [];
5241
+ if (params.cleanup_all) {
5242
+ const allTasks = getProjectTasks(params.project);
5243
+ taskSlugs = allTasks.map((t) => t.task_slug);
5244
+ } else if (params.task_slugs && params.task_slugs.length > 0) {
5245
+ taskSlugs = params.task_slugs;
5246
+ } else if (params.task_slug) {
5247
+ taskSlugs = [params.task_slug];
5248
+ }
5249
+ if (taskSlugs.length === 0) {
5250
+ return {
5251
+ content: [{ type: "text", text: "No tasks specified for cleanup. Provide task_slug, task_slugs array, or set cleanup_all=true." }],
5252
+ isError: true
5253
+ };
5254
+ }
5255
+ const MAX_BATCH_SIZE = 10;
5256
+ if (taskSlugs.length > MAX_BATCH_SIZE) {
5257
+ return {
5258
+ content: [{ type: "text", text: `Too many tasks (${taskSlugs.length}). Maximum ${MAX_BATCH_SIZE} tasks per batch.` }],
5259
+ isError: true
5260
+ };
5261
+ }
5262
+ const results = await Promise.all(
5263
+ taskSlugs.map((slug) => cleanupSingleTask(params.project, slug, projectDataPath))
5264
+ );
5265
+ const successCount = results.filter((r) => r.success).length;
5266
+ const failureCount = results.filter((r) => !r.success).length;
5267
+ let responseText = `Loaded ${successCount} task(s) for cleanup.`;
5268
+ if (failureCount > 0) {
5269
+ responseText += ` Failed to load ${failureCount} task(s):
5270
+ `;
5271
+ results.filter((r) => !r.success).forEach((r) => {
5272
+ responseText += ` - ${r.message}
5273
+ `;
5274
+ });
5275
+ }
5276
+ responseText += `
5277
+
5278
+ Task artifacts loaded. The cleanup agent will now:
5279
+ `;
5280
+ responseText += `1. Extract knowledge from each task
5281
+ `;
5282
+ responseText += `2. Check for duplicates in knowledge base
5283
+ `;
5284
+ responseText += `3. Merge or create knowledge files
5285
+ `;
5286
+ responseText += `4. Delete task directories
5287
+ `;
5288
+ responseText += `5. Reindex knowledge
5289
+
5290
+ `;
5291
+ responseText += `Proceeding with cleanup...`;
5292
+ return {
5293
+ content: [{ type: "text", text: responseText }]
5294
+ };
5295
+ }
5296
+ return null;
5297
+ }
5298
+ var cleanupTools;
5299
+ var init_cleanup = __esm({
5300
+ "src/mcp/handlers/tools/cleanup.ts"() {
5301
+ "use strict";
5302
+ init_resources2();
5303
+ init_config();
5304
+ init_detection_service();
5305
+ cleanupTools = [
5306
+ {
5307
+ name: "cleanup_task",
5308
+ description: "Cleanup task(s) by extracting knowledge and deleting artifacts. Supports single task, multiple tasks, or --all mode.",
5309
+ inputSchema: {
5310
+ type: "object",
5311
+ properties: {
5312
+ project: { type: "string", description: "Name of the project" },
5313
+ task_slug: { type: "string", description: "Single task slug to cleanup" },
5314
+ task_slugs: { type: "array", items: { type: "string" }, description: "Multiple task slugs to cleanup" },
5315
+ cleanup_all: { type: "boolean", description: "Cleanup all tasks for project" }
5316
+ },
5317
+ required: ["project"]
5318
+ }
5319
+ }
5320
+ ];
5321
+ }
5322
+ });
5323
+
5181
5324
  // src/mcp/handlers/tools.ts
5182
5325
  import "@modelcontextprotocol/sdk/server/index.js";
5183
5326
  import {
@@ -5191,7 +5334,8 @@ function registerToolHandlers(server) {
5191
5334
  ...searchTools,
5192
5335
  ...taskTools,
5193
5336
  ...sessionTools,
5194
- ...agentTools
5337
+ ...agentTools,
5338
+ ...cleanupTools
5195
5339
  ];
5196
5340
  const projects = getExposedProjects();
5197
5341
  if (projects.length === 0) {
@@ -5217,6 +5361,8 @@ function registerToolHandlers(server) {
5217
5361
  if (sessionResult) return sessionResult;
5218
5362
  const agentResult = await handleAgentTool(name, args);
5219
5363
  if (agentResult) return agentResult;
5364
+ const cleanupResult = await handleCleanupTool(name, args);
5365
+ if (cleanupResult) return cleanupResult;
5220
5366
  throw new Error(`Unknown tool: ${name}`);
5221
5367
  } catch (error) {
5222
5368
  logger.error(`Tool execution failed: ${name}`, error);
@@ -5234,6 +5380,7 @@ var init_tools = __esm({
5234
5380
  init_task();
5235
5381
  init_session();
5236
5382
  init_agent();
5383
+ init_cleanup();
5237
5384
  }
5238
5385
  });
5239
5386
 
@@ -5459,8 +5606,8 @@ Hidden projects: ${projects.length - exposedCount}`,
5459
5606
  }
5460
5607
  async function handleConfigureGlobalPath() {
5461
5608
  const { resolveGlobalPath: resolveGlobalPath2 } = await Promise.resolve().then(() => (init_tui_utils(), tui_utils_exports));
5462
- const fs34 = await import("fs");
5463
- const path34 = await import("path");
5609
+ const fs35 = await import("fs");
5610
+ const path35 = await import("path");
5464
5611
  note3(
5465
5612
  `MCP Hub requires a ${pc5.bold("global storage path")} to store its configuration
5466
5613
  and coordinate across projects.
@@ -5474,8 +5621,8 @@ locally in each project. MCP needs a central location.`,
5474
5621
  return false;
5475
5622
  }
5476
5623
  try {
5477
- if (!fs34.existsSync(resolvedPath)) {
5478
- fs34.mkdirSync(resolvedPath, { recursive: true });
5624
+ if (!fs35.existsSync(resolvedPath)) {
5625
+ fs35.mkdirSync(resolvedPath, { recursive: true });
5479
5626
  }
5480
5627
  const config = loadMCPConfig();
5481
5628
  saveMCPConfig(config);
@@ -5483,7 +5630,7 @@ locally in each project. MCP needs a central location.`,
5483
5630
  `${pc5.green("\u2713")} Global path configured: ${pc5.cyan(resolvedPath)}
5484
5631
 
5485
5632
  MCP config will be stored at:
5486
- ${path34.join(resolvedPath, "mcp.yaml")}`,
5633
+ ${path35.join(resolvedPath, "mcp.yaml")}`,
5487
5634
  "Configuration Saved"
5488
5635
  );
5489
5636
  return true;
@@ -5587,15 +5734,15 @@ __export(ConfigContext_exports, {
5587
5734
  useConfig: () => useConfig
5588
5735
  });
5589
5736
  import { createContext, useContext, useState, useCallback, useMemo, useEffect } from "react";
5590
- import * as fs25 from "fs";
5591
- import * as path28 from "path";
5737
+ import * as fs26 from "fs";
5738
+ import * as path29 from "path";
5592
5739
  import { jsx as jsx2 } from "react/jsx-runtime";
5593
5740
  function getPackageVersion() {
5594
5741
  try {
5595
5742
  const agentCoreDir = getAgentCoreDir();
5596
- const packageJsonPath = path28.join(path28.dirname(agentCoreDir), "package.json");
5597
- if (fs25.existsSync(packageJsonPath)) {
5598
- return JSON.parse(fs25.readFileSync(packageJsonPath, "utf8")).version;
5743
+ const packageJsonPath = path29.join(path29.dirname(agentCoreDir), "package.json");
5744
+ if (fs26.existsSync(packageJsonPath)) {
5745
+ return JSON.parse(fs26.readFileSync(packageJsonPath, "utf8")).version;
5599
5746
  }
5600
5747
  } catch (e) {
5601
5748
  }
@@ -5662,16 +5809,16 @@ var init_ConfigContext = __esm({
5662
5809
  });
5663
5810
 
5664
5811
  // src/mcp/ui/lib/tasks-fs.ts
5665
- import * as fs26 from "fs";
5666
- import * as path29 from "path";
5812
+ import * as fs27 from "fs";
5813
+ import * as path30 from "path";
5667
5814
  function readSession(project, taskSlug) {
5668
5815
  const rrceData = getProjectRRCEData(project);
5669
- const sessionPath = path29.join(rrceData, "tasks", taskSlug, "session.json");
5670
- if (!fs26.existsSync(sessionPath)) {
5816
+ const sessionPath = path30.join(rrceData, "tasks", taskSlug, "session.json");
5817
+ if (!fs27.existsSync(sessionPath)) {
5671
5818
  return null;
5672
5819
  }
5673
5820
  try {
5674
- const raw = fs26.readFileSync(sessionPath, "utf-8");
5821
+ const raw = fs27.readFileSync(sessionPath, "utf-8");
5675
5822
  return JSON.parse(raw);
5676
5823
  } catch {
5677
5824
  return null;
@@ -5684,12 +5831,12 @@ function isSessionStale(session, thresholdMs = SESSION_STALE_THRESHOLD_MS) {
5684
5831
  }
5685
5832
  function readAgentTodos(project, taskSlug) {
5686
5833
  const rrceData = getProjectRRCEData(project);
5687
- const todosPath = path29.join(rrceData, "tasks", taskSlug, "agent-todos.json");
5688
- if (!fs26.existsSync(todosPath)) {
5834
+ const todosPath = path30.join(rrceData, "tasks", taskSlug, "agent-todos.json");
5835
+ if (!fs27.existsSync(todosPath)) {
5689
5836
  return null;
5690
5837
  }
5691
5838
  try {
5692
- const raw = fs26.readFileSync(todosPath, "utf-8");
5839
+ const raw = fs27.readFileSync(todosPath, "utf-8");
5693
5840
  return JSON.parse(raw);
5694
5841
  } catch {
5695
5842
  return null;
@@ -5702,8 +5849,8 @@ function detectStorageModeFromConfig(workspaceRoot) {
5702
5849
  if (configPath.startsWith(rrceHome)) {
5703
5850
  return "global";
5704
5851
  }
5705
- if (fs26.existsSync(configPath)) {
5706
- const content = fs26.readFileSync(configPath, "utf-8");
5852
+ if (fs27.existsSync(configPath)) {
5853
+ const content = fs27.readFileSync(configPath, "utf-8");
5707
5854
  if (content.includes("mode: workspace")) return "workspace";
5708
5855
  if (content.includes("mode: global")) return "global";
5709
5856
  }
@@ -5713,7 +5860,7 @@ function detectStorageModeFromConfig(workspaceRoot) {
5713
5860
  }
5714
5861
  function getEffectiveGlobalBase() {
5715
5862
  const dummy = resolveDataPath("global", "__rrce_dummy__", "");
5716
- return path29.dirname(path29.dirname(dummy));
5863
+ return path30.dirname(path30.dirname(dummy));
5717
5864
  }
5718
5865
  function getProjectRRCEData(project) {
5719
5866
  const workspaceRoot = project.sourcePath || project.path;
@@ -5722,19 +5869,19 @@ function getProjectRRCEData(project) {
5722
5869
  }
5723
5870
  function listProjectTasks(project) {
5724
5871
  const rrceData = getProjectRRCEData(project);
5725
- const tasksPath = path29.join(rrceData, "tasks");
5726
- if (!fs26.existsSync(tasksPath)) {
5872
+ const tasksPath = path30.join(rrceData, "tasks");
5873
+ if (!fs27.existsSync(tasksPath)) {
5727
5874
  return { projectName: project.name, tasksPath, tasks: [] };
5728
5875
  }
5729
5876
  const tasks = [];
5730
5877
  try {
5731
- const entries = fs26.readdirSync(tasksPath, { withFileTypes: true });
5878
+ const entries = fs27.readdirSync(tasksPath, { withFileTypes: true });
5732
5879
  for (const entry of entries) {
5733
5880
  if (!entry.isDirectory()) continue;
5734
- const metaPath = path29.join(tasksPath, entry.name, "meta.json");
5735
- if (!fs26.existsSync(metaPath)) continue;
5881
+ const metaPath = path30.join(tasksPath, entry.name, "meta.json");
5882
+ if (!fs27.existsSync(metaPath)) continue;
5736
5883
  try {
5737
- const raw = fs26.readFileSync(metaPath, "utf-8");
5884
+ const raw = fs27.readFileSync(metaPath, "utf-8");
5738
5885
  const meta = JSON.parse(raw);
5739
5886
  if (!meta.task_slug) meta.task_slug = entry.name;
5740
5887
  tasks.push(meta);
@@ -5753,18 +5900,18 @@ function listProjectTasks(project) {
5753
5900
  }
5754
5901
  function updateTaskStatus(project, taskSlug, status) {
5755
5902
  const rrceData = getProjectRRCEData(project);
5756
- const metaPath = path29.join(rrceData, "tasks", taskSlug, "meta.json");
5757
- if (!fs26.existsSync(metaPath)) {
5903
+ const metaPath = path30.join(rrceData, "tasks", taskSlug, "meta.json");
5904
+ if (!fs27.existsSync(metaPath)) {
5758
5905
  return { ok: false, error: `meta.json not found for task '${taskSlug}'` };
5759
5906
  }
5760
5907
  try {
5761
- const meta = JSON.parse(fs26.readFileSync(metaPath, "utf-8"));
5908
+ const meta = JSON.parse(fs27.readFileSync(metaPath, "utf-8"));
5762
5909
  const next = {
5763
5910
  ...meta,
5764
5911
  status,
5765
5912
  updated_at: (/* @__PURE__ */ new Date()).toISOString()
5766
5913
  };
5767
- fs26.writeFileSync(metaPath, JSON.stringify(next, null, 2));
5914
+ fs27.writeFileSync(metaPath, JSON.stringify(next, null, 2));
5768
5915
  return { ok: true, meta: next };
5769
5916
  } catch (e) {
5770
5917
  return { ok: false, error: String(e) };
@@ -6149,27 +6296,27 @@ var init_ProjectViews = __esm({
6149
6296
  });
6150
6297
 
6151
6298
  // src/mcp/ui/lib/projects.ts
6152
- import * as fs27 from "fs";
6153
- import * as path30 from "path";
6299
+ import * as fs28 from "fs";
6300
+ import * as path31 from "path";
6154
6301
  function getIndexStats(project) {
6155
6302
  const stats = { knowledgeCount: 0, codeCount: 0, lastIndexed: null };
6156
6303
  try {
6157
6304
  const knowledgePath = project.knowledgePath;
6158
6305
  if (knowledgePath) {
6159
- const embPath = path30.join(knowledgePath, "embeddings.json");
6160
- const codeEmbPath = path30.join(knowledgePath, "code-embeddings.json");
6161
- if (fs27.existsSync(embPath)) {
6162
- const stat = fs27.statSync(embPath);
6306
+ const embPath = path31.join(knowledgePath, "embeddings.json");
6307
+ const codeEmbPath = path31.join(knowledgePath, "code-embeddings.json");
6308
+ if (fs28.existsSync(embPath)) {
6309
+ const stat = fs28.statSync(embPath);
6163
6310
  stats.lastIndexed = stat.mtime.toISOString();
6164
6311
  try {
6165
- const data = JSON.parse(fs27.readFileSync(embPath, "utf-8"));
6312
+ const data = JSON.parse(fs28.readFileSync(embPath, "utf-8"));
6166
6313
  stats.knowledgeCount = Array.isArray(data) ? data.length : Object.keys(data).length;
6167
6314
  } catch {
6168
6315
  }
6169
6316
  }
6170
- if (fs27.existsSync(codeEmbPath)) {
6317
+ if (fs28.existsSync(codeEmbPath)) {
6171
6318
  try {
6172
- const data = JSON.parse(fs27.readFileSync(codeEmbPath, "utf-8"));
6319
+ const data = JSON.parse(fs28.readFileSync(codeEmbPath, "utf-8"));
6173
6320
  stats.codeCount = Array.isArray(data) ? data.length : Object.keys(data).length;
6174
6321
  } catch {
6175
6322
  }
@@ -6914,7 +7061,7 @@ __export(App_exports, {
6914
7061
  });
6915
7062
  import { useState as useState5, useEffect as useEffect6, useMemo as useMemo5, useCallback as useCallback3 } from "react";
6916
7063
  import { Box as Box14, useInput as useInput5, useApp } from "ink";
6917
- import fs28 from "fs";
7064
+ import fs29 from "fs";
6918
7065
  import { jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
6919
7066
  var App;
6920
7067
  var init_App = __esm({
@@ -6987,18 +7134,18 @@ var init_App = __esm({
6987
7134
  useEffect6(() => {
6988
7135
  const logPath = getLogFilePath();
6989
7136
  let lastSize = 0;
6990
- if (fs28.existsSync(logPath)) {
6991
- const stats = fs28.statSync(logPath);
7137
+ if (fs29.existsSync(logPath)) {
7138
+ const stats = fs29.statSync(logPath);
6992
7139
  lastSize = stats.size;
6993
7140
  }
6994
7141
  const interval = setInterval(() => {
6995
- if (fs28.existsSync(logPath)) {
6996
- const stats = fs28.statSync(logPath);
7142
+ if (fs29.existsSync(logPath)) {
7143
+ const stats = fs29.statSync(logPath);
6997
7144
  if (stats.size > lastSize) {
6998
7145
  const buffer = Buffer.alloc(stats.size - lastSize);
6999
- const fd = fs28.openSync(logPath, "r");
7000
- fs28.readSync(fd, buffer, 0, buffer.length, lastSize);
7001
- fs28.closeSync(fd);
7146
+ const fd = fs29.openSync(logPath, "r");
7147
+ fs29.readSync(fd, buffer, 0, buffer.length, lastSize);
7148
+ fs29.closeSync(fd);
7002
7149
  const newContent = buffer.toString("utf-8");
7003
7150
  const newLines = newContent.split("\n").filter((l) => l.trim());
7004
7151
  setLogs((prev) => {
@@ -7223,15 +7370,15 @@ __export(update_flow_exports, {
7223
7370
  });
7224
7371
  import { confirm as confirm5, spinner as spinner2, note as note6, outro as outro2, cancel as cancel2, isCancel as isCancel7 } from "@clack/prompts";
7225
7372
  import pc8 from "picocolors";
7226
- import * as fs29 from "fs";
7227
- import * as path31 from "path";
7373
+ import * as fs30 from "fs";
7374
+ import * as path32 from "path";
7228
7375
  import { stringify as stringify2, parse } from "yaml";
7229
7376
  function backupFile(filePath) {
7230
- if (!fs29.existsSync(filePath)) return null;
7377
+ if (!fs30.existsSync(filePath)) return null;
7231
7378
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").split("T")[0] + "-" + Date.now();
7232
7379
  const backupPath = `${filePath}.${timestamp}.bak`;
7233
7380
  try {
7234
- fs29.copyFileSync(filePath, backupPath);
7381
+ fs30.copyFileSync(filePath, backupPath);
7235
7382
  return backupPath;
7236
7383
  } catch (e) {
7237
7384
  console.error(`Failed to backup ${filePath}:`, e);
@@ -7241,9 +7388,9 @@ function backupFile(filePath) {
7241
7388
  function getPackageVersion2() {
7242
7389
  try {
7243
7390
  const agentCoreDir = getAgentCoreDir();
7244
- const packageJsonPath = path31.join(path31.dirname(agentCoreDir), "package.json");
7245
- if (fs29.existsSync(packageJsonPath)) {
7246
- return JSON.parse(fs29.readFileSync(packageJsonPath, "utf8")).version;
7391
+ const packageJsonPath = path32.join(path32.dirname(agentCoreDir), "package.json");
7392
+ if (fs30.existsSync(packageJsonPath)) {
7393
+ return JSON.parse(fs30.readFileSync(packageJsonPath, "utf8")).version;
7247
7394
  }
7248
7395
  } catch (e) {
7249
7396
  }
@@ -7258,9 +7405,9 @@ async function performUpdate(workspacePath, workspaceName, currentStorageMode, o
7258
7405
  const dataPaths = resolveAllDataPathsWithCustomGlobal(mode, workspaceName, workspacePath, customGlobalPath);
7259
7406
  const configFilePath = getConfigPath(workspacePath);
7260
7407
  let currentSyncedVersion;
7261
- if (fs29.existsSync(configFilePath)) {
7408
+ if (fs30.existsSync(configFilePath)) {
7262
7409
  try {
7263
- const content = fs29.readFileSync(configFilePath, "utf-8");
7410
+ const content = fs30.readFileSync(configFilePath, "utf-8");
7264
7411
  const config = parse(content);
7265
7412
  currentSyncedVersion = config.last_synced_version;
7266
7413
  } catch (e) {
@@ -7268,8 +7415,8 @@ async function performUpdate(workspacePath, workspaceName, currentStorageMode, o
7268
7415
  }
7269
7416
  const driftReport = DriftService.checkDrift(dataPaths[0], currentSyncedVersion, runningVersion);
7270
7417
  const ideTargets = [];
7271
- if (fs29.existsSync(configFilePath)) {
7272
- const configContent = fs29.readFileSync(configFilePath, "utf-8");
7418
+ if (fs30.existsSync(configFilePath)) {
7419
+ const configContent = fs30.readFileSync(configFilePath, "utf-8");
7273
7420
  if (configContent.includes("opencode: true")) ideTargets.push("OpenCode agents");
7274
7421
  if (configContent.includes("copilot: true")) ideTargets.push("GitHub Copilot");
7275
7422
  if (configContent.includes("antigravity: true")) ideTargets.push("Antigravity");
@@ -7278,14 +7425,14 @@ async function performUpdate(workspacePath, workspaceName, currentStorageMode, o
7278
7425
  const dirs = ["templates", "prompts", "docs"];
7279
7426
  const updatedFiles = [];
7280
7427
  for (const dir of dirs) {
7281
- const srcDir = path31.join(agentCoreDir, dir);
7282
- if (!fs29.existsSync(srcDir)) continue;
7428
+ const srcDir = path32.join(agentCoreDir, dir);
7429
+ if (!fs30.existsSync(srcDir)) continue;
7283
7430
  const syncFiles = (src, rel) => {
7284
- const entries = fs29.readdirSync(src, { withFileTypes: true });
7431
+ const entries = fs30.readdirSync(src, { withFileTypes: true });
7285
7432
  for (const entry of entries) {
7286
- const entrySrc = path31.join(src, entry.name);
7287
- const entryRel = path31.join(rel, entry.name);
7288
- const entryDest = path31.join(dataPath, entryRel);
7433
+ const entrySrc = path32.join(src, entry.name);
7434
+ const entryRel = path32.join(rel, entry.name);
7435
+ const entryDest = path32.join(dataPath, entryRel);
7289
7436
  if (entry.isDirectory()) {
7290
7437
  ensureDir(entryDest);
7291
7438
  syncFiles(entrySrc, entryRel);
@@ -7293,8 +7440,8 @@ async function performUpdate(workspacePath, workspaceName, currentStorageMode, o
7293
7440
  if (driftReport.modifiedFiles.includes(entryRel)) {
7294
7441
  backupFile(entryDest);
7295
7442
  }
7296
- ensureDir(path31.dirname(entryDest));
7297
- fs29.copyFileSync(entrySrc, entryDest);
7443
+ ensureDir(path32.dirname(entryDest));
7444
+ fs30.copyFileSync(entrySrc, entryDest);
7298
7445
  updatedFiles.push(entryRel);
7299
7446
  }
7300
7447
  }
@@ -7305,12 +7452,12 @@ async function performUpdate(workspacePath, workspaceName, currentStorageMode, o
7305
7452
  DriftService.saveManifest(dataPath, manifest);
7306
7453
  }
7307
7454
  const rrceHome = customGlobalPath || getDefaultRRCEHome2();
7308
- ensureDir(path31.join(rrceHome, "templates"));
7309
- ensureDir(path31.join(rrceHome, "docs"));
7310
- copyDirRecursive(path31.join(agentCoreDir, "templates"), path31.join(rrceHome, "templates"));
7311
- copyDirRecursive(path31.join(agentCoreDir, "docs"), path31.join(rrceHome, "docs"));
7312
- if (fs29.existsSync(configFilePath)) {
7313
- const configContent = fs29.readFileSync(configFilePath, "utf-8");
7455
+ ensureDir(path32.join(rrceHome, "templates"));
7456
+ ensureDir(path32.join(rrceHome, "docs"));
7457
+ copyDirRecursive(path32.join(agentCoreDir, "templates"), path32.join(rrceHome, "templates"));
7458
+ copyDirRecursive(path32.join(agentCoreDir, "docs"), path32.join(rrceHome, "docs"));
7459
+ if (fs30.existsSync(configFilePath)) {
7460
+ const configContent = fs30.readFileSync(configFilePath, "utf-8");
7314
7461
  if (configContent.includes("copilot: true")) {
7315
7462
  const copilotPath = getAgentPromptPath(workspacePath, "copilot");
7316
7463
  ensureDir(copilotPath);
@@ -7332,21 +7479,21 @@ async function performUpdate(workspacePath, workspaceName, currentStorageMode, o
7332
7479
  try {
7333
7480
  const yaml = parse(configContent);
7334
7481
  yaml.last_synced_version = runningVersion;
7335
- fs29.writeFileSync(configFilePath, stringify2(yaml));
7482
+ fs30.writeFileSync(configFilePath, stringify2(yaml));
7336
7483
  } catch (e) {
7337
7484
  console.error("Failed to update config.yaml version:", e);
7338
7485
  }
7339
7486
  }
7340
- const mcpPath = path31.join(rrceHome, "mcp.yaml");
7341
- if (fs29.existsSync(mcpPath)) {
7487
+ const mcpPath = path32.join(rrceHome, "mcp.yaml");
7488
+ if (fs30.existsSync(mcpPath)) {
7342
7489
  try {
7343
- const content = fs29.readFileSync(mcpPath, "utf-8");
7490
+ const content = fs30.readFileSync(mcpPath, "utf-8");
7344
7491
  const yaml = parse(content);
7345
7492
  if (yaml.projects) {
7346
7493
  const project = yaml.projects.find((p) => p.name === workspaceName);
7347
7494
  if (project) {
7348
7495
  project.last_synced_version = runningVersion;
7349
- fs29.writeFileSync(mcpPath, stringify2(yaml));
7496
+ fs30.writeFileSync(mcpPath, stringify2(yaml));
7350
7497
  }
7351
7498
  }
7352
7499
  } catch (e) {
@@ -7382,9 +7529,9 @@ async function runUpdateFlow(workspacePath, workspaceName, currentStorageMode) {
7382
7529
  const dataPaths = resolveAllDataPathsWithCustomGlobal(mode, workspaceName, workspacePath, customGlobalPath);
7383
7530
  const configFilePath = getConfigPath(workspacePath);
7384
7531
  let currentSyncedVersion;
7385
- if (fs29.existsSync(configFilePath)) {
7532
+ if (fs30.existsSync(configFilePath)) {
7386
7533
  try {
7387
- const content = fs29.readFileSync(configFilePath, "utf-8");
7534
+ const content = fs30.readFileSync(configFilePath, "utf-8");
7388
7535
  const config = parse(content);
7389
7536
  currentSyncedVersion = config.last_synced_version;
7390
7537
  } catch (e) {
@@ -7408,8 +7555,8 @@ async function runUpdateFlow(workspacePath, workspaceName, currentStorageMode) {
7408
7555
  ` \u2022 docs/ (documentation)`
7409
7556
  ];
7410
7557
  const ideTargets = [];
7411
- if (fs29.existsSync(configFilePath)) {
7412
- const configContent = fs29.readFileSync(configFilePath, "utf-8");
7558
+ if (fs30.existsSync(configFilePath)) {
7559
+ const configContent = fs30.readFileSync(configFilePath, "utf-8");
7413
7560
  if (configContent.includes("opencode: true")) ideTargets.push("OpenCode agents");
7414
7561
  if (configContent.includes("copilot: true")) ideTargets.push("GitHub Copilot");
7415
7562
  if (configContent.includes("antigravity: true")) ideTargets.push("Antigravity");
@@ -7438,14 +7585,14 @@ ${dataPaths.map((p) => ` \u2022 ${p}`).join("\n")}`,
7438
7585
  const dirs = ["templates", "prompts", "docs"];
7439
7586
  const updatedFiles = [];
7440
7587
  for (const dir of dirs) {
7441
- const srcDir = path31.join(agentCoreDir, dir);
7442
- if (!fs29.existsSync(srcDir)) continue;
7588
+ const srcDir = path32.join(agentCoreDir, dir);
7589
+ if (!fs30.existsSync(srcDir)) continue;
7443
7590
  const syncFiles = (src, rel) => {
7444
- const entries = fs29.readdirSync(src, { withFileTypes: true });
7591
+ const entries = fs30.readdirSync(src, { withFileTypes: true });
7445
7592
  for (const entry of entries) {
7446
- const entrySrc = path31.join(src, entry.name);
7447
- const entryRel = path31.join(rel, entry.name);
7448
- const entryDest = path31.join(dataPath, entryRel);
7593
+ const entrySrc = path32.join(src, entry.name);
7594
+ const entryRel = path32.join(rel, entry.name);
7595
+ const entryDest = path32.join(dataPath, entryRel);
7449
7596
  if (entry.isDirectory()) {
7450
7597
  ensureDir(entryDest);
7451
7598
  syncFiles(entrySrc, entryRel);
@@ -7453,8 +7600,8 @@ ${dataPaths.map((p) => ` \u2022 ${p}`).join("\n")}`,
7453
7600
  if (driftReport.modifiedFiles.includes(entryRel)) {
7454
7601
  backupFile(entryDest);
7455
7602
  }
7456
- ensureDir(path31.dirname(entryDest));
7457
- fs29.copyFileSync(entrySrc, entryDest);
7603
+ ensureDir(path32.dirname(entryDest));
7604
+ fs30.copyFileSync(entrySrc, entryDest);
7458
7605
  updatedFiles.push(entryRel);
7459
7606
  }
7460
7607
  }
@@ -7465,12 +7612,12 @@ ${dataPaths.map((p) => ` \u2022 ${p}`).join("\n")}`,
7465
7612
  DriftService.saveManifest(dataPath, manifest);
7466
7613
  }
7467
7614
  const rrceHome = customGlobalPath || getDefaultRRCEHome2();
7468
- ensureDir(path31.join(rrceHome, "templates"));
7469
- ensureDir(path31.join(rrceHome, "docs"));
7470
- copyDirRecursive(path31.join(agentCoreDir, "templates"), path31.join(rrceHome, "templates"));
7471
- copyDirRecursive(path31.join(agentCoreDir, "docs"), path31.join(rrceHome, "docs"));
7472
- if (fs29.existsSync(configFilePath)) {
7473
- const configContent = fs29.readFileSync(configFilePath, "utf-8");
7615
+ ensureDir(path32.join(rrceHome, "templates"));
7616
+ ensureDir(path32.join(rrceHome, "docs"));
7617
+ copyDirRecursive(path32.join(agentCoreDir, "templates"), path32.join(rrceHome, "templates"));
7618
+ copyDirRecursive(path32.join(agentCoreDir, "docs"), path32.join(rrceHome, "docs"));
7619
+ if (fs30.existsSync(configFilePath)) {
7620
+ const configContent = fs30.readFileSync(configFilePath, "utf-8");
7474
7621
  if (configContent.includes("copilot: true")) {
7475
7622
  const copilotPath = getAgentPromptPath(workspacePath, "copilot");
7476
7623
  ensureDir(copilotPath);
@@ -7492,21 +7639,21 @@ ${dataPaths.map((p) => ` \u2022 ${p}`).join("\n")}`,
7492
7639
  try {
7493
7640
  const yaml = parse(configContent);
7494
7641
  yaml.last_synced_version = runningVersion;
7495
- fs29.writeFileSync(configFilePath, stringify2(yaml));
7642
+ fs30.writeFileSync(configFilePath, stringify2(yaml));
7496
7643
  } catch (e) {
7497
7644
  console.error("Failed to update config.yaml version:", e);
7498
7645
  }
7499
7646
  }
7500
- const mcpPath = path31.join(rrceHome, "mcp.yaml");
7501
- if (fs29.existsSync(mcpPath)) {
7647
+ const mcpPath = path32.join(rrceHome, "mcp.yaml");
7648
+ if (fs30.existsSync(mcpPath)) {
7502
7649
  try {
7503
- const content = fs29.readFileSync(mcpPath, "utf-8");
7650
+ const content = fs30.readFileSync(mcpPath, "utf-8");
7504
7651
  const yaml = parse(content);
7505
7652
  if (yaml.projects) {
7506
7653
  const project = yaml.projects.find((p) => p.name === workspaceName);
7507
7654
  if (project) {
7508
7655
  project.last_synced_version = runningVersion;
7509
- fs29.writeFileSync(mcpPath, stringify2(yaml));
7656
+ fs30.writeFileSync(mcpPath, stringify2(yaml));
7510
7657
  }
7511
7658
  }
7512
7659
  } catch (e) {
@@ -7541,8 +7688,8 @@ ${dataPaths.map((p) => ` \u2022 ${p}`).join("\n")}`,
7541
7688
  }
7542
7689
  }
7543
7690
  function resolveAllDataPathsWithCustomGlobal(mode, workspaceName, workspaceRoot, customGlobalPath) {
7544
- const globalPath = path31.join(customGlobalPath, "workspaces", workspaceName);
7545
- const workspacePath = path31.join(workspaceRoot, ".rrce-workflow");
7691
+ const globalPath = path32.join(customGlobalPath, "workspaces", workspaceName);
7692
+ const workspacePath = path32.join(workspaceRoot, ".rrce-workflow");
7546
7693
  switch (mode) {
7547
7694
  case "global":
7548
7695
  return [globalPath];
@@ -7565,8 +7712,8 @@ var init_update_flow = __esm({
7565
7712
  // src/commands/wizard/index.ts
7566
7713
  import { intro as intro2, select as select5, spinner as spinner7, note as note11, outro as outro7, isCancel as isCancel12, confirm as confirm10 } from "@clack/prompts";
7567
7714
  import pc13 from "picocolors";
7568
- import * as fs33 from "fs";
7569
- import * as path33 from "path";
7715
+ import * as fs34 from "fs";
7716
+ import * as path34 from "path";
7570
7717
  import { parse as parse2 } from "yaml";
7571
7718
 
7572
7719
  // src/lib/git.ts
@@ -8243,7 +8390,7 @@ async function handlePostSetup(config, workspacePath, workspaceName, linkedProje
8243
8390
  init_paths();
8244
8391
  import { multiselect as multiselect4, spinner as spinner4, note as note8, outro as outro4, cancel as cancel4, isCancel as isCancel9, confirm as confirm7 } from "@clack/prompts";
8245
8392
  import pc10 from "picocolors";
8246
- import * as fs30 from "fs";
8393
+ import * as fs31 from "fs";
8247
8394
  init_detection();
8248
8395
  async function runLinkProjectsFlow(workspacePath, workspaceName) {
8249
8396
  const projects = scanForProjects({
@@ -8282,7 +8429,7 @@ async function runLinkProjectsFlow(workspacePath, workspaceName) {
8282
8429
  const s = spinner4();
8283
8430
  s.start("Linking projects");
8284
8431
  const configFilePath = getConfigPath(workspacePath);
8285
- let configContent = fs30.readFileSync(configFilePath, "utf-8");
8432
+ let configContent = fs31.readFileSync(configFilePath, "utf-8");
8286
8433
  if (configContent.includes("linked_projects:")) {
8287
8434
  const lines = configContent.split("\n");
8288
8435
  const linkedIndex = lines.findIndex((l) => l.trim() === "linked_projects:");
@@ -8309,7 +8456,7 @@ linked_projects:
8309
8456
  `;
8310
8457
  });
8311
8458
  }
8312
- fs30.writeFileSync(configFilePath, configContent);
8459
+ fs31.writeFileSync(configFilePath, configContent);
8313
8460
  generateVSCodeWorkspace(workspacePath, workspaceName, selectedProjects, customGlobalPath);
8314
8461
  s.stop("Projects linked");
8315
8462
  const workspaceFile = `${workspaceName}.code-workspace`;
@@ -8345,15 +8492,15 @@ init_paths();
8345
8492
  init_utils();
8346
8493
  import { confirm as confirm8, spinner as spinner5, note as note9, outro as outro5, cancel as cancel5, isCancel as isCancel10 } from "@clack/prompts";
8347
8494
  import pc11 from "picocolors";
8348
- import * as fs31 from "fs";
8349
- import * as path32 from "path";
8495
+ import * as fs32 from "fs";
8496
+ import * as path33 from "path";
8350
8497
  async function runSyncToGlobalFlow(workspacePath, workspaceName) {
8351
8498
  const localPath = getLocalWorkspacePath(workspacePath);
8352
8499
  const customGlobalPath = getEffectiveRRCEHome(workspacePath);
8353
- const globalPath = path32.join(customGlobalPath, "workspaces", workspaceName);
8500
+ const globalPath = path33.join(customGlobalPath, "workspaces", workspaceName);
8354
8501
  const subdirs = ["knowledge", "prompts", "templates", "tasks", "refs"];
8355
8502
  const existingDirs = subdirs.filter(
8356
- (dir) => fs31.existsSync(path32.join(localPath, dir))
8503
+ (dir) => fs32.existsSync(path33.join(localPath, dir))
8357
8504
  );
8358
8505
  if (existingDirs.length === 0) {
8359
8506
  outro5(pc11.yellow("No data found in workspace storage to sync."));
@@ -8379,8 +8526,8 @@ Destination: ${pc11.cyan(globalPath)}`,
8379
8526
  try {
8380
8527
  ensureDir(globalPath);
8381
8528
  for (const dir of existingDirs) {
8382
- const srcDir = path32.join(localPath, dir);
8383
- const destDir = path32.join(globalPath, dir);
8529
+ const srcDir = path33.join(localPath, dir);
8530
+ const destDir = path33.join(globalPath, dir);
8384
8531
  ensureDir(destDir);
8385
8532
  copyDirRecursive(srcDir, destDir);
8386
8533
  }
@@ -8408,7 +8555,7 @@ init_update_flow();
8408
8555
  // src/commands/wizard/delete-flow.ts
8409
8556
  import { multiselect as multiselect5, confirm as confirm9, spinner as spinner6, note as note10, cancel as cancel6, isCancel as isCancel11 } from "@clack/prompts";
8410
8557
  import pc12 from "picocolors";
8411
- import * as fs32 from "fs";
8558
+ import * as fs33 from "fs";
8412
8559
  init_detection();
8413
8560
  init_config();
8414
8561
  async function runDeleteGlobalProjectFlow(availableProjects) {
@@ -8452,8 +8599,8 @@ Are you sure?`,
8452
8599
  for (const projectName of projectsToDelete) {
8453
8600
  const project = globalProjects.find((p) => p.name === projectName);
8454
8601
  if (!project) continue;
8455
- if (fs32.existsSync(project.dataPath)) {
8456
- fs32.rmSync(project.dataPath, { recursive: true, force: true });
8602
+ if (fs33.existsSync(project.dataPath)) {
8603
+ fs33.rmSync(project.dataPath, { recursive: true, force: true });
8457
8604
  }
8458
8605
  const newConfig = removeProjectConfig(mcpConfig, projectName);
8459
8606
  configChanged = true;
@@ -8475,9 +8622,9 @@ init_config();
8475
8622
  function getPackageVersion3() {
8476
8623
  try {
8477
8624
  const agentCoreDir = getAgentCoreDir();
8478
- const packageJsonPath = path33.join(path33.dirname(agentCoreDir), "package.json");
8479
- if (fs33.existsSync(packageJsonPath)) {
8480
- return JSON.parse(fs33.readFileSync(packageJsonPath, "utf8")).version;
8625
+ const packageJsonPath = path34.join(path34.dirname(agentCoreDir), "package.json");
8626
+ if (fs34.existsSync(packageJsonPath)) {
8627
+ return JSON.parse(fs34.readFileSync(packageJsonPath, "utf8")).version;
8481
8628
  }
8482
8629
  } catch (e) {
8483
8630
  }
@@ -8485,9 +8632,9 @@ function getPackageVersion3() {
8485
8632
  }
8486
8633
  function getLastSyncedVersion(workspacePath, workspaceName) {
8487
8634
  const configFilePath = getConfigPath(workspacePath);
8488
- if (fs33.existsSync(configFilePath)) {
8635
+ if (fs34.existsSync(configFilePath)) {
8489
8636
  try {
8490
- const content = fs33.readFileSync(configFilePath, "utf-8");
8637
+ const content = fs34.readFileSync(configFilePath, "utf-8");
8491
8638
  const config = parse2(content);
8492
8639
  if (config.last_synced_version) {
8493
8640
  return config.last_synced_version;
@@ -8496,10 +8643,10 @@ function getLastSyncedVersion(workspacePath, workspaceName) {
8496
8643
  }
8497
8644
  }
8498
8645
  const rrceHome = getEffectiveRRCEHome(workspacePath) || getDefaultRRCEHome2();
8499
- const mcpPath = path33.join(rrceHome, "mcp.yaml");
8500
- if (fs33.existsSync(mcpPath)) {
8646
+ const mcpPath = path34.join(rrceHome, "mcp.yaml");
8647
+ if (fs34.existsSync(mcpPath)) {
8501
8648
  try {
8502
- const content = fs33.readFileSync(mcpPath, "utf-8");
8649
+ const content = fs34.readFileSync(mcpPath, "utf-8");
8503
8650
  const config = parse2(content);
8504
8651
  const project = config.projects?.find((p) => p.name === workspaceName);
8505
8652
  if (project?.last_synced_version) {
@@ -8569,11 +8716,11 @@ Workspace: ${pc13.bold(workspaceName)}`,
8569
8716
  workspacePath
8570
8717
  });
8571
8718
  const configFilePath = getConfigPath(workspacePath);
8572
- let isAlreadyConfigured = fs33.existsSync(configFilePath);
8719
+ let isAlreadyConfigured = fs34.existsSync(configFilePath);
8573
8720
  let currentStorageMode = null;
8574
8721
  if (isAlreadyConfigured) {
8575
8722
  try {
8576
- const configContent = fs33.readFileSync(configFilePath, "utf-8");
8723
+ const configContent = fs34.readFileSync(configFilePath, "utf-8");
8577
8724
  const modeMatch = configContent.match(/mode:\s*(global|workspace)/);
8578
8725
  currentStorageMode = modeMatch?.[1] ?? null;
8579
8726
  } catch {
@@ -8590,7 +8737,7 @@ Workspace: ${pc13.bold(workspaceName)}`,
8590
8737
  }
8591
8738
  }
8592
8739
  const localDataPath = getLocalWorkspacePath(workspacePath);
8593
- const hasLocalData = fs33.existsSync(localDataPath);
8740
+ const hasLocalData = fs34.existsSync(localDataPath);
8594
8741
  if (isAlreadyConfigured) {
8595
8742
  const continueToMenu = await checkAndPromptUpdate(workspacePath, workspaceName, currentStorageMode);
8596
8743
  if (!continueToMenu) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rrce-workflow",
3
- "version": "0.3.28",
3
+ "version": "0.3.30",
4
4
  "description": "RRCE-Workflow TUI - Agentic code workflow generator for AI-assisted development",
5
5
  "author": "RRCE Team",
6
6
  "license": "MIT",