rrce-workflow 0.2.95 → 0.2.97

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
@@ -18,65 +18,67 @@ RRCE-Workflow transforms your AI coding assistant (GitHub Copilot, OpenCode, Cla
18
18
 
19
19
  ## 🚀 Quick Start
20
20
 
21
- ### 1. The MCP Dashboard (TUI)
21
+ ### 1. Run the Wizard (Project Setup)
22
22
 
23
- The central command center for RRCE-Workflow is the **MCP Dashboard**. It lets you manage your projects, server status, and IDE integrations.
23
+ From the project you want to work on:
24
24
 
25
25
  ```bash
26
- npx rrce-workflow mcp
26
+ cd your-project
27
+ npx rrce-workflow
27
28
  ```
28
29
 
29
- From this dashboard, you can:
30
- - **Manage Projects**: Toggle which projects are exposed to your AI agents.
31
- - **Monitor Status**: See the health of the MCP server and RAG indexing.
32
- - **Install to IDE**: Automatically configure **VSCode**, **Claude Desktop**, **Antigravity IDE**, or **OpenCode** to use the RRCE MCP server.
33
- - **View Logs**: Debug agent interactions in real-time.
30
+ This launches the setup wizard and can:
31
+ - Create the `.rrce-workflow/` structure (workspace mode) or initialize global storage (global mode)
32
+ - Install IDE integrations (VSCode / Claude Desktop / OpenCode / Antigravity)
33
+ - Optionally expose the project to MCP and enable semantic search indexing
34
34
 
35
- ### 2. Setting Up a Project
35
+ ### 2. Launch the MCP Dashboard (TUI)
36
36
 
37
- To enable agent workflows for your current project, run the setup wizard:
37
+ The **MCP Dashboard** lets you manage exposed projects, indexing jobs, IDE integrations, and view logs.
38
38
 
39
39
  ```bash
40
- cd your-project
41
- npx rrce-workflow
40
+ npx rrce-workflow mcp
42
41
  ```
43
42
 
44
- You can choose between:
43
+ ### 3. Run the MCP Server (for IDE integrations)
44
+
45
+ When an IDE connects via MCP, it launches the server in non-interactive mode:
46
+
47
+ ```bash
48
+ npx rrce-workflow mcp start
49
+ ```
45
50
 
46
- * **⚡ Express Setup**: Configures the project using recommended defaults:
47
- * **Global Storage**: Keeps your project directory clean; config lives in `~/.rrce-workflow/`.
48
- * **MCP Enabled**: Exposes the project to your AI tools via the local server.
49
- * **RAG Enabled**: Indexes your code for semantic search.
50
-
51
- * **⚙️ Custom Setup**: Full control over storage location (Global vs Workspace), tool selection, and more.
51
+ Note: `mcp start` is intended for stdio-based MCP clients (it only auto-starts when `stdout` is not a TTY).
52
52
 
53
53
  ---
54
54
 
55
55
  ## 🧠 Model Context Protocol (MCP)
56
56
 
57
- RRCE-Workflow uses the [Model Context Protocol](https://modelcontextprotocol.io/) to bridge your codebase with AI models. This allows your AI assistant to "see" your project context without needing to manually copy-paste files.
57
+ RRCE-Workflow uses the [Model Context Protocol](https://modelcontextprotocol.io/) to bridge your codebase with AI models. This allows your AI assistant to access project context and knowledge without copy/paste.
58
58
 
59
59
  ### Features
60
60
  * **Universal Context**: Access your project's `project-context.md`, architecture docs, and task history from *any* MCP-enabled tool.
61
61
  * **Cross-Project References**: Your AI can read documentation from Project A while working on Project B (perfect for monorepos or microservices).
62
- * **12 MCP Tools**: Including `search_knowledge`, `get_project_context`, `resolve_path`, task CRUD operations, and more.
62
+ * **MCP Tools**: Includes `search_knowledge`, `search_code`, `find_related_files`, `get_project_context`, `resolve_path`, task CRUD operations, and more.
63
63
 
64
64
  ### MCP Tools Reference
65
65
 
66
66
  | Tool | Description |
67
67
  |------|-------------|
68
- | `resolve_path` | Resolve RRCE configuration paths (RRCE_DATA, WORKSPACE_ROOT, etc.) for a project |
69
- | `list_projects` | List all projects exposed via MCP |
70
- | `get_project_context` | Get the project-context.md for a specific project |
71
- | `search_knowledge` | Semantic search (RAG) across project knowledge bases |
72
- | `index_knowledge` | Update the semantic search index for a project |
68
+ | `resolve_path` | Resolve configuration paths (`RRCE_DATA`, `WORKSPACE_ROOT`, etc.) for a project |
69
+ | `list_projects` | List projects exposed via MCP |
70
+ | `get_project_context` | Get the project context/architecture for a specific project |
71
+ | `search_knowledge` | Semantic search across project knowledge bases |
72
+ | `search_code` | Semantic search across code files (snippets + line numbers + context) |
73
+ | `find_related_files` | Find imports/imported-by relationships for a file |
74
+ | `index_knowledge` | Start (or query) the semantic indexing job for a project |
73
75
  | `list_agents` | List available RRCE agents and their arguments |
74
- | `get_agent_prompt` | Get the system prompt for a specific agent with context injection |
76
+ | `get_agent_prompt` | Get the system prompt for a specific agent (with context injection) |
75
77
  | `list_tasks` | List all tasks for a project |
76
- | `get_task` | Get details of a specific task |
77
- | `create_task` | Create a new task in the project |
78
- | `update_task` | Update an existing task's meta.json |
79
- | `delete_task` | Delete a task from the project |
78
+ | `get_task` | Get details of a task |
79
+ | `create_task` | Create a task |
80
+ | `update_task` | Update a task (`meta.json`) |
81
+ | `delete_task` | Delete a task |
80
82
 
81
83
  ### Connecting Your IDE
82
84
 
package/dist/index.js CHANGED
@@ -1718,6 +1718,14 @@ var init_rag = __esm({
1718
1718
  this.maybeSaveIndex(true);
1719
1719
  }
1720
1720
  }
1721
+ /**
1722
+ * Get current indexed file paths
1723
+ */
1724
+ getIndexedFiles() {
1725
+ this.loadIndex();
1726
+ if (!this.index || !this.index.fileMetadata) return [];
1727
+ return Object.keys(this.index.fileMetadata);
1728
+ }
1721
1729
  /**
1722
1730
  * Get index statistics
1723
1731
  */
@@ -2354,6 +2362,7 @@ import * as fs15 from "fs";
2354
2362
  import * as path17 from "path";
2355
2363
  import * as os2 from "os";
2356
2364
  import * as crypto from "crypto";
2365
+ import ignore from "ignore";
2357
2366
  function resolveProjectPaths(project, pathInput) {
2358
2367
  const config = loadMCPConfig();
2359
2368
  let workspaceRoot = pathInput;
@@ -2737,6 +2746,33 @@ async function indexKnowledge(projectName, force = false) {
2737
2746
  ".sql"
2738
2747
  ];
2739
2748
  const SKIP_DIRS = ["node_modules", ".git", "dist", "build", ".next", "__pycache__", "venv", ".venv", "target", "vendor"];
2749
+ const gitignorePath = path17.join(scanRoot, ".gitignore");
2750
+ const ig = fs15.existsSync(gitignorePath) ? ignore().add(fs15.readFileSync(gitignorePath, "utf-8")) : null;
2751
+ const toPosixRelativePath = (absolutePath) => {
2752
+ const rel = path17.relative(scanRoot, absolutePath);
2753
+ return rel.split(path17.sep).join("/");
2754
+ };
2755
+ const isUnderGitDir = (absolutePath) => {
2756
+ const rel = toPosixRelativePath(absolutePath);
2757
+ return rel === ".git" || rel.startsWith(".git/");
2758
+ };
2759
+ const isIgnoredByGitignore = (absolutePath, isDir) => {
2760
+ if (!ig) return false;
2761
+ const rel = toPosixRelativePath(absolutePath);
2762
+ return ig.ignores(isDir ? `${rel}/` : rel);
2763
+ };
2764
+ const shouldSkipEntryDir = (absolutePath) => {
2765
+ const dirName = path17.basename(absolutePath);
2766
+ if (dirName === ".git") return true;
2767
+ if (SKIP_DIRS.includes(dirName)) return true;
2768
+ if (isIgnoredByGitignore(absolutePath, true)) return true;
2769
+ return false;
2770
+ };
2771
+ const shouldSkipEntryFile = (absolutePath) => {
2772
+ if (isUnderGitDir(absolutePath)) return true;
2773
+ if (isIgnoredByGitignore(absolutePath, false)) return true;
2774
+ return false;
2775
+ };
2740
2776
  const runIndexing = async () => {
2741
2777
  const indexPath = path17.join(project.knowledgePath || path17.join(scanRoot, ".rrce-workflow", "knowledge"), "embeddings.json");
2742
2778
  const codeIndexPath = path17.join(project.knowledgePath || path17.join(scanRoot, ".rrce-workflow", "knowledge"), "code-embeddings.json");
@@ -2748,29 +2784,45 @@ async function indexKnowledge(projectName, force = false) {
2748
2784
  let skipped = 0;
2749
2785
  let itemsTotal = 0;
2750
2786
  let itemsDone = 0;
2751
- const shouldSkipDir = (dirName) => SKIP_DIRS.includes(dirName) || dirName.startsWith(".");
2752
2787
  const preCount = (dir) => {
2753
2788
  const entries = fs15.readdirSync(dir, { withFileTypes: true });
2754
2789
  for (const entry of entries) {
2755
2790
  const fullPath = path17.join(dir, entry.name);
2756
2791
  if (entry.isDirectory()) {
2757
- if (shouldSkipDir(entry.name)) continue;
2792
+ if (shouldSkipEntryDir(fullPath)) continue;
2758
2793
  preCount(fullPath);
2759
2794
  } else if (entry.isFile()) {
2760
2795
  const ext = path17.extname(entry.name).toLowerCase();
2761
2796
  if (!INDEXABLE_EXTENSIONS.includes(ext)) continue;
2797
+ if (shouldSkipEntryFile(fullPath)) continue;
2762
2798
  itemsTotal++;
2763
2799
  }
2764
2800
  }
2765
2801
  };
2766
2802
  preCount(scanRoot);
2767
2803
  indexingJobs.update(project.name, { itemsTotal });
2804
+ const cleanupIgnoredFiles = async () => {
2805
+ const indexedFiles = [...rag.getIndexedFiles(), ...codeRag.getIndexedFiles()];
2806
+ const unique = Array.from(new Set(indexedFiles));
2807
+ for (const filePath of unique) {
2808
+ if (!path17.isAbsolute(filePath)) continue;
2809
+ const relFilePath = filePath.split(path17.sep).join("/");
2810
+ const relScanRoot = scanRoot.split(path17.sep).join("/");
2811
+ const isInScanRoot = relFilePath === relScanRoot || relFilePath.startsWith(`${relScanRoot}/`);
2812
+ if (!isInScanRoot) continue;
2813
+ if (shouldSkipEntryFile(filePath)) {
2814
+ await rag.removeFile(filePath);
2815
+ await codeRag.removeFile(filePath);
2816
+ }
2817
+ }
2818
+ };
2819
+ await cleanupIgnoredFiles();
2768
2820
  const scanDir = async (dir) => {
2769
2821
  const entries = fs15.readdirSync(dir, { withFileTypes: true });
2770
2822
  for (const entry of entries) {
2771
2823
  const fullPath = path17.join(dir, entry.name);
2772
2824
  if (entry.isDirectory()) {
2773
- if (shouldSkipDir(entry.name)) {
2825
+ if (shouldSkipEntryDir(fullPath)) {
2774
2826
  continue;
2775
2827
  }
2776
2828
  await scanDir(fullPath);
@@ -2779,6 +2831,9 @@ async function indexKnowledge(projectName, force = false) {
2779
2831
  if (!INDEXABLE_EXTENSIONS.includes(ext)) {
2780
2832
  continue;
2781
2833
  }
2834
+ if (shouldSkipEntryFile(fullPath)) {
2835
+ continue;
2836
+ }
2782
2837
  try {
2783
2838
  indexingJobs.update(project.name, { currentItem: fullPath, itemsDone });
2784
2839
  const stat = fs15.statSync(fullPath);
@@ -5271,9 +5326,10 @@ function convertToOpenCodeAgent(prompt, useFileReference = false, promptFilePath
5271
5326
  }
5272
5327
  }
5273
5328
  tools["webfetch"] = true;
5329
+ const invocationHint = " (Invoke via @rrce_*)";
5274
5330
  return {
5275
- description: frontmatter.description,
5276
- mode: "primary",
5331
+ description: `${frontmatter.description}${invocationHint}`,
5332
+ mode: "subagent",
5277
5333
  prompt: useFileReference && promptFilePath ? `{file:${promptFilePath}}` : content,
5278
5334
  tools
5279
5335
  };
@@ -5428,11 +5484,12 @@ async function installAgentPrompts(config, workspacePath, dataPaths) {
5428
5484
  if (!opencodeConfig.agent) opencodeConfig.agent = {};
5429
5485
  for (const prompt of prompts) {
5430
5486
  const baseName = path12.basename(prompt.filePath, ".md");
5487
+ const agentId = `rrce_${baseName}`;
5431
5488
  const promptFileName = `rrce-${baseName}.md`;
5432
5489
  const promptFilePath = path12.join(promptsDir, promptFileName);
5433
5490
  fs10.writeFileSync(promptFilePath, prompt.content);
5434
5491
  const agentConfig = convertToOpenCodeAgent(prompt, true, `./prompts/${promptFileName}`);
5435
- opencodeConfig.agent[baseName] = agentConfig;
5492
+ opencodeConfig.agent[agentId] = agentConfig;
5436
5493
  }
5437
5494
  fs10.writeFileSync(OPENCODE_CONFIG, JSON.stringify(opencodeConfig, null, 2) + "\n");
5438
5495
  } catch (e) {
@@ -5443,6 +5500,7 @@ async function installAgentPrompts(config, workspacePath, dataPaths) {
5443
5500
  ensureDir(opencodeBaseDir);
5444
5501
  for (const prompt of prompts) {
5445
5502
  const baseName = path12.basename(prompt.filePath, ".md");
5503
+ const agentId = `rrce_${baseName}`;
5446
5504
  const agentConfig = convertToOpenCodeAgent(prompt);
5447
5505
  const content = `---
5448
5506
  ${stringify2({
@@ -5451,7 +5509,7 @@ ${stringify2({
5451
5509
  tools: agentConfig.tools
5452
5510
  })}---
5453
5511
  ${agentConfig.prompt}`;
5454
- fs10.writeFileSync(path12.join(opencodeBaseDir, `${baseName}.md`), content);
5512
+ fs10.writeFileSync(path12.join(opencodeBaseDir, `${agentId}.md`), content);
5455
5513
  }
5456
5514
  }
5457
5515
  }
@@ -6048,15 +6106,17 @@ function updateOpenCodeAgents(prompts, mode, primaryDataPath) {
6048
6106
  opencodeConfig = JSON.parse(fs21.readFileSync(OPENCODE_CONFIG, "utf-8"));
6049
6107
  }
6050
6108
  if (!opencodeConfig.agent) opencodeConfig.agent = {};
6051
- const currentAgentNames = prompts.map((p) => path21.basename(p.filePath, ".md"));
6109
+ const currentAgentBaseNames = prompts.map((p) => path21.basename(p.filePath, ".md"));
6110
+ const currentAgentIds = new Set(currentAgentBaseNames.map((base) => `rrce_${base}`));
6052
6111
  const existingAgentNames = Object.keys(opencodeConfig.agent);
6053
- const rrceAgentPrefixes = ["init", "research", "planning", "executor", "doctor", "documentation", "sync"];
6054
6112
  for (const existingName of existingAgentNames) {
6055
- const isRrceAgent = rrceAgentPrefixes.some((prefix) => existingName.startsWith(prefix));
6056
- const stillExists = currentAgentNames.includes(existingName);
6057
- if (isRrceAgent && !stillExists) {
6113
+ const isLegacyBaseName = currentAgentBaseNames.includes(existingName);
6114
+ const isRrcePrefixed = existingName.startsWith("rrce_");
6115
+ const isStaleRrcePrefixed = isRrcePrefixed && !currentAgentIds.has(existingName);
6116
+ if (isLegacyBaseName || isStaleRrcePrefixed) {
6058
6117
  delete opencodeConfig.agent[existingName];
6059
- const oldPromptFile = path21.join(promptsDir, `rrce-${existingName}.md`);
6118
+ const legacyBaseName = isLegacyBaseName ? existingName : existingName.replace(/^rrce_/, "");
6119
+ const oldPromptFile = path21.join(promptsDir, `rrce-${legacyBaseName}.md`);
6060
6120
  if (fs21.existsSync(oldPromptFile)) {
6061
6121
  fs21.unlinkSync(oldPromptFile);
6062
6122
  }
@@ -6064,11 +6124,12 @@ function updateOpenCodeAgents(prompts, mode, primaryDataPath) {
6064
6124
  }
6065
6125
  for (const prompt of prompts) {
6066
6126
  const baseName = path21.basename(prompt.filePath, ".md");
6127
+ const agentId = `rrce_${baseName}`;
6067
6128
  const promptFileName = `rrce-${baseName}.md`;
6068
6129
  const promptFilePath = path21.join(promptsDir, promptFileName);
6069
6130
  fs21.writeFileSync(promptFilePath, prompt.content);
6070
6131
  const agentConfig = convertToOpenCodeAgent(prompt, true, `./prompts/${promptFileName}`);
6071
- opencodeConfig.agent[baseName] = agentConfig;
6132
+ opencodeConfig.agent[agentId] = agentConfig;
6072
6133
  }
6073
6134
  fs21.writeFileSync(OPENCODE_CONFIG, JSON.stringify(opencodeConfig, null, 2) + "\n");
6074
6135
  } catch (e) {
@@ -6080,6 +6141,7 @@ function updateOpenCodeAgents(prompts, mode, primaryDataPath) {
6080
6141
  clearDirectory(opencodeBaseDir);
6081
6142
  for (const prompt of prompts) {
6082
6143
  const baseName = path21.basename(prompt.filePath, ".md");
6144
+ const agentId = `rrce_${baseName}`;
6083
6145
  const agentConfig = convertToOpenCodeAgent(prompt);
6084
6146
  const content = `---
6085
6147
  ${stringify3({
@@ -6088,7 +6150,7 @@ ${stringify3({
6088
6150
  tools: agentConfig.tools
6089
6151
  })}---
6090
6152
  ${agentConfig.prompt}`;
6091
- fs21.writeFileSync(path21.join(opencodeBaseDir, `${baseName}.md`), content);
6153
+ fs21.writeFileSync(path21.join(opencodeBaseDir, `${agentId}.md`), content);
6092
6154
  }
6093
6155
  }
6094
6156
  }
@@ -2,18 +2,18 @@
2
2
 
3
3
  > RR Context Engineering Workflow - A selection-agnostic agentic workflow system
4
4
  >
5
- > **Version**: 0.2.91 | **Last Updated**: 2025-12-31
5
+ > **Version**: 0.2.96 | **Last Updated**: 2026-01-02
6
6
 
7
7
  ## Overview
8
8
 
9
9
  RRCE-Workflow is a TUI-based agentic code workflow generator designed to work seamlessly across:
10
- - **OpenCode** (Native agentic TUI environment with custom Primary Agents)
10
+ - **OpenCode** (Native agentic TUI environment; RRCE installs subagents invoked via `@rrce_<agent>`)
11
11
  - **GitHub Copilot** (VSCode with MCP extension)
12
12
  - **Antigravity IDE** (Google's agentic coding environment)
13
13
  - **Claude Desktop** (MCP Server integration)
14
14
  - **Any MCP-compatible client**
15
15
 
16
- The system provides a structured multi-agent pipeline (7 agents) for software development tasks, with persistent knowledge caching, semantic search (RAG), and workspace-aware context management.
16
+ The system provides a structured multi-agent pipeline (7 agents) for software development tasks, with persistent knowledge caching, semantic search (RAG) across knowledge and code, and workspace-aware context management.
17
17
 
18
18
  ## Core Principles
19
19
 
@@ -355,7 +355,7 @@ RRCE-Workflow prompts are designed to work across multiple AI coding tools via M
355
355
 
356
356
  | Tool | MCP Config Location | Agent Location | Notes |
357
357
  |------|---------------------|----------------|-------|
358
- | **OpenCode** | `~/.config/opencode/opencode.json` | `.opencode/agent/rrce-*.md` | Custom Primary Agents (Tab to switch) |
358
+ | **OpenCode** | `~/.config/opencode/opencode.json` | `.opencode/agent/rrce_*.md` | Custom subagents (invoke via `@rrce_*`) |
359
359
  | **Antigravity IDE** | `~/.gemini/antigravity/mcp_config.json` | `.agent/workflows/*.md` | Native workflow support |
360
360
  | **GitHub Copilot (VSCode)** | `.vscode/mcp.json` or global settings | `.github/prompts/*.prompt.md` | Custom agents format |
361
361
  | **Claude Desktop** | `~/.config/claude/claude_desktop_config.json` | N/A | MCP Server only |
@@ -363,25 +363,26 @@ RRCE-Workflow prompts are designed to work across multiple AI coding tools via M
363
363
  ### OpenCode Agent Transformation
364
364
 
365
365
  When generating agents for OpenCode (`src/commands/wizard/utils.ts`):
366
- - **Mode**: Set to `primary` (enables Tab cycling in TUI)
367
- - **Tools**:
366
+ - **Mode**: Set to `subagent` (not tab-switchable; invoke via mention)
367
+ - **Invoke**: Use `@rrce_<agent>` (e.g., `@rrce_init`)
368
+ - **Tools**:
368
369
  - Host tools (`read`, `write`, `edit`, `bash`, `grep`, `glob`, `webfetch`) pass through as-is
369
370
  - MCP tools are prefixed with `rrce_` (e.g., `rrce_search_knowledge`)
370
371
  - Tool list respects per-agent frontmatter restrictions
371
- - **Naming**: Agents prefixed with `rrce-` to avoid collisions
372
+ - **Naming**: Agent IDs are prefixed with `rrce_` (underscore) to avoid collisions
372
373
 
373
374
  ### Generated Files
374
375
 
375
376
  **For OpenCode:**
376
377
  ```
377
378
  .opencode/agent/
378
- ├── rrce-init.md
379
- ├── rrce-research.md
380
- ├── rrce-planning.md
381
- ├── rrce-executor.md
382
- ├── rrce-documentation.md
383
- ├── rrce-sync.md
384
- └── rrce-doctor.md
379
+ ├── rrce_init.md
380
+ ├── rrce_research.md
381
+ ├── rrce_planning.md
382
+ ├── rrce_executor.md
383
+ ├── rrce_documentation.md
384
+ ├── rrce_sync.md
385
+ └── rrce_doctor.md
385
386
  ```
386
387
 
387
388
  **For Antigravity IDE:**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rrce-workflow",
3
- "version": "0.2.95",
3
+ "version": "0.2.97",
4
4
  "description": "RRCE-Workflow TUI - Agentic code workflow generator for AI-assisted development",
5
5
  "author": "RRCE Team",
6
6
  "license": "MIT",
@@ -53,6 +53,7 @@
53
53
  "@modelcontextprotocol/sdk": "^1.25.1",
54
54
  "@xenova/transformers": "^2.17.2",
55
55
  "gray-matter": "^4.0.3",
56
+ "ignore": "^5.3.2",
56
57
  "ink": "^6.6.0",
57
58
  "ink-link": "^5.0.0",
58
59
  "ink-spinner": "^5.0.0",