rrce-workflow 0.2.81 → 0.2.83

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.
@@ -24,6 +24,10 @@ You are the Documentation Lead for the project. Operate like a senior engineerin
24
24
  Use the pre-resolved paths from the "System Resolved Paths" table in the context preamble.
25
25
  For details, see: `{{RRCE_DATA}}/docs/path-resolution.md`
26
26
 
27
+ ### Tool Usage Guidance
28
+ - **search_knowledge**: PREFER this tool for finding concepts, logic flow, or documentation. It uses semantic search (RAG) to find relevant code even without exact keyword matches.
29
+ - **grep**: Use ONLY when searching for exact string patterns (e.g., specific function names, error codes).
30
+
27
31
  ## Supported DOC_TYPE Values
28
32
 
29
33
  | Type | Purpose | Audience |
@@ -20,6 +20,10 @@ You are the Executor for RRCE-Workflow. You are the **ONLY agent in the pipeline
20
20
  Use the pre-resolved paths from the "System Resolved Paths" table in the context preamble.
21
21
  For details, see: `{{RRCE_DATA}}/docs/path-resolution.md`
22
22
 
23
+ ### Tool Usage Guidance
24
+ - **search_knowledge**: PREFER this tool for finding concepts, logic flow, or documentation. It uses semantic search (RAG) to find relevant code even without exact keyword matches.
25
+ - **grep**: Use ONLY when searching for exact string patterns (e.g., specific function names, error codes).
26
+
23
27
  ## Pipeline Position
24
28
  - **Requires**: Both Research AND Planning phases must be complete before execution
25
29
  - **Input**: Execution plan from `/plan` agent
@@ -19,6 +19,10 @@ You are the Project Initializer for RRCE-Workflow. Your mission: create a compre
19
19
  Use the pre-resolved paths from the "System Resolved Paths" table in the context preamble.
20
20
  For details, see: `{{RRCE_DATA}}/docs/path-resolution.md`
21
21
 
22
+ ### Tool Usage Guidance
23
+ - **search_knowledge**: PREFER this tool for finding concepts, logic flow, or documentation. It uses semantic search (RAG) to find relevant code even without exact keyword matches.
24
+ - **grep**: Use ONLY when searching for exact string patterns (e.g., specific function names, error codes).
25
+
22
26
  ## Pipeline Position
23
27
  - **Entry Point**: Run before any other agent for new projects
24
28
  - **Output**: `{{RRCE_DATA}}/knowledge/project-context.md` + semantic search index
@@ -17,6 +17,10 @@ You are the Planning & Task Orchestrator for RRCE-Workflow. Your mission: transf
17
17
  Use the pre-resolved paths from the "System Resolved Paths" table in the context preamble.
18
18
  For details, see: `{{RRCE_DATA}}/docs/path-resolution.md`
19
19
 
20
+ ### Tool Usage Guidance
21
+ - **search_knowledge**: PREFER this tool for finding concepts, logic flow, or documentation. It uses semantic search (RAG) to find relevant code even without exact keyword matches.
22
+ - **grep**: Use ONLY when searching for exact string patterns (e.g., specific function names, error codes).
23
+
20
24
  ## Pipeline Position
21
25
  - **Requires**: Research phase must be complete before planning can begin
22
26
  - **Input**: Research brief from `/research` agent
@@ -24,6 +24,10 @@ You are the Research & Discussion Lead for RRCE-Workflow. Your mission: achieve
24
24
  Use the pre-resolved paths from the "System Resolved Paths" table in the context preamble.
25
25
  For details, see: `{{RRCE_DATA}}/docs/path-resolution.md`
26
26
 
27
+ ### Tool Usage Guidance
28
+ - **search_knowledge**: PREFER this tool for finding concepts, logic flow, or documentation. It uses semantic search (RAG) to find relevant code even without exact keyword matches.
29
+ - **grep**: Use ONLY when searching for exact string patterns (e.g., specific function names, error codes).
30
+
27
31
  ## Pipeline Position
28
32
  - **Entry Point**: First agent invoked for new tasks (after optional `/init`)
29
33
  - **Output**: Research brief document ready for Planning agent
@@ -18,6 +18,10 @@ You are the Knowledge Sync Lead. Act like a senior architect charged with keepin
18
18
  Use the pre-resolved paths from the "System Resolved Paths" table in the context preamble.
19
19
  For details, see: `{{RRCE_DATA}}/docs/path-resolution.md`
20
20
 
21
+ ### Tool Usage Guidance
22
+ - **search_knowledge**: PREFER this tool for finding concepts, logic flow, or documentation. It uses semantic search (RAG) to find relevant code even without exact keyword matches.
23
+ - **grep**: Use ONLY when searching for exact string patterns (e.g., specific function names, error codes).
24
+
21
25
  Pipeline Position
22
26
  - **Maintenance Agent**: Sync runs periodically or after significant codebase changes to keep knowledge current.
23
27
  - **Requires**: Init must have been run at least once (project-context.md must exist).
package/dist/index.js CHANGED
@@ -1997,17 +1997,17 @@ var init_rag = __esm({
1997
1997
  if (_RAGService.activeModelName === this.modelName && _RAGService.loadPromise) {
1998
1998
  return _RAGService.loadPromise;
1999
1999
  }
2000
- logger.info(`RAG: Initializing model ${this.modelName}...`);
2000
+ logger.info(`[RAG] Initializing model ${this.modelName}...`);
2001
2001
  _RAGService.activeModelName = this.modelName;
2002
2002
  _RAGService.loadPromise = (async () => {
2003
2003
  try {
2004
2004
  const { pipeline } = await import("@xenova/transformers");
2005
2005
  const pipe = await pipeline("feature-extraction", this.modelName);
2006
2006
  _RAGService.pipelineInstance = pipe;
2007
- logger.info(`RAG: Model ${this.modelName} initialized successfully.`);
2007
+ logger.info(`[RAG] Model ${this.modelName} initialized successfully.`);
2008
2008
  return pipe;
2009
2009
  } catch (error) {
2010
- logger.error(`RAG: Failed to initialize model ${this.modelName}`, error);
2010
+ logger.error(`[RAG] Failed to initialize model ${this.modelName}`, error);
2011
2011
  _RAGService.pipelineInstance = null;
2012
2012
  _RAGService.activeModelName = null;
2013
2013
  _RAGService.loadPromise = null;
@@ -2025,9 +2025,9 @@ var init_rag = __esm({
2025
2025
  try {
2026
2026
  const data = fs13.readFileSync(this.indexPath, "utf-8");
2027
2027
  this.index = JSON.parse(data);
2028
- logger.info(`RAG: Loaded index from ${this.indexPath} with ${this.index?.chunks.length} chunks.`);
2028
+ logger.info(`[RAG] Loaded index from ${this.indexPath} with ${this.index?.chunks.length} chunks.`);
2029
2029
  } catch (error) {
2030
- logger.error(`RAG: Failed to load index from ${this.indexPath}`, error);
2030
+ logger.error(`[RAG] Failed to load index from ${this.indexPath}`, error);
2031
2031
  this.index = {
2032
2032
  version: INDEX_VERSION,
2033
2033
  baseModel: this.modelName,
@@ -2040,7 +2040,7 @@ var init_rag = __esm({
2040
2040
  baseModel: this.modelName,
2041
2041
  chunks: []
2042
2042
  };
2043
- logger.info(`RAG: Created new empty index at ${this.indexPath}`);
2043
+ logger.info(`[RAG] Created new empty index at ${this.indexPath}`);
2044
2044
  }
2045
2045
  }
2046
2046
  /**
@@ -2054,9 +2054,9 @@ var init_rag = __esm({
2054
2054
  fs13.mkdirSync(dir, { recursive: true });
2055
2055
  }
2056
2056
  fs13.writeFileSync(this.indexPath, JSON.stringify(this.index, null, 2));
2057
- logger.info(`RAG: Saved index to ${this.indexPath} with ${this.index.chunks.length} chunks.`);
2057
+ logger.info(`[RAG] Saved index to ${this.indexPath} with ${this.index.chunks.length} chunks.`);
2058
2058
  } catch (error) {
2059
- logger.error(`RAG: Failed to save index to ${this.indexPath}`, error);
2059
+ logger.error(`[RAG] Failed to save index to ${this.indexPath}`, error);
2060
2060
  }
2061
2061
  }
2062
2062
  /**
@@ -2068,7 +2068,7 @@ var init_rag = __esm({
2068
2068
  const output = await pipe(text2, { pooling: "mean", normalize: true });
2069
2069
  return Array.from(output.data);
2070
2070
  } catch (error) {
2071
- logger.error("RAG: Error generating embedding", error);
2071
+ logger.error("[RAG] Error generating embedding", error);
2072
2072
  throw error;
2073
2073
  }
2074
2074
  }
@@ -2088,11 +2088,11 @@ var init_rag = __esm({
2088
2088
  if (mtime !== void 0 && this.index.fileMetadata[filePath]) {
2089
2089
  const existingMeta = this.index.fileMetadata[filePath];
2090
2090
  if (existingMeta.mtime === mtime) {
2091
- logger.debug(`RAG: Skipping unchanged file ${filePath}`);
2091
+ logger.debug(`[RAG] Skipping unchanged file ${filePath}`);
2092
2092
  return false;
2093
2093
  }
2094
2094
  }
2095
- logger.info(`RAG: Indexing file ${filePath}`);
2095
+ logger.info(`[RAG] Indexing file ${filePath}`);
2096
2096
  this.index.chunks = this.index.chunks.filter((c) => c.filePath !== filePath);
2097
2097
  const chunks = this.chunkContent(content);
2098
2098
  for (const chunkText of chunks) {
@@ -2124,7 +2124,7 @@ var init_rag = __esm({
2124
2124
  delete this.index.fileMetadata[filePath];
2125
2125
  }
2126
2126
  if (this.index.chunks.length !== initialCount) {
2127
- logger.info(`RAG: Removed file ${filePath} from index (${initialCount - this.index.chunks.length} chunks removed)`);
2127
+ logger.info(`[RAG] Removed file ${filePath} from index (${initialCount - this.index.chunks.length} chunks removed)`);
2128
2128
  this.saveIndex();
2129
2129
  }
2130
2130
  }
@@ -2156,10 +2156,10 @@ var init_rag = __esm({
2156
2156
  async search(query, limit = 5) {
2157
2157
  this.loadIndex();
2158
2158
  if (!this.index || this.index.chunks.length === 0) {
2159
- logger.warn("RAG: Search called on empty index");
2159
+ logger.warn("[RAG] Search called on empty index");
2160
2160
  return [];
2161
2161
  }
2162
- logger.info(`RAG: Searching for "${query}" (limit: ${limit})`);
2162
+ logger.info(`[RAG] Searching for "${query}" (limit: ${limit})`);
2163
2163
  const queryEmbedding = await this.generateEmbedding(query);
2164
2164
  const results = this.index.chunks.map((chunk) => {
2165
2165
  const score = this.cosineSimilarity(queryEmbedding, chunk.embedding);
@@ -2167,7 +2167,7 @@ var init_rag = __esm({
2167
2167
  });
2168
2168
  results.sort((a, b) => b.score - a.score);
2169
2169
  const topResults = results.slice(0, limit);
2170
- logger.info(`RAG: Search returned ${topResults.length} matches. Top score: ${topResults[0]?.score.toFixed(4)}`);
2170
+ logger.info(`[RAG] Search returned ${topResults.length} matches. Top score: ${topResults[0]?.score.toFixed(4)}`);
2171
2171
  return topResults;
2172
2172
  }
2173
2173
  /**
@@ -2260,7 +2260,7 @@ function getExposedProjects() {
2260
2260
  }
2261
2261
  }
2262
2262
  }
2263
- return potentialProjects.filter((project) => isProjectExposed(config, project.name, project.path));
2263
+ return potentialProjects.filter((project) => isProjectExposed(config, project.name, project.sourcePath || project.path));
2264
2264
  }
2265
2265
  function getRAGIndexPath(project) {
2266
2266
  const scanRoot = project.path || project.dataPath;
@@ -2272,18 +2272,18 @@ function detectActiveProject(knownProjects) {
2272
2272
  const config = loadMCPConfig();
2273
2273
  const knownPaths = config.projects.map((p) => p.path).filter((p) => !!p);
2274
2274
  const all = projectService.scan({ knownPaths });
2275
- scanList = all.filter((project) => isProjectExposed(config, project.name, project.path));
2275
+ scanList = all.filter((project) => isProjectExposed(config, project.name, project.sourcePath || project.path));
2276
2276
  }
2277
2277
  return findClosestProject(scanList);
2278
2278
  }
2279
2279
  function getProjectContext(projectName) {
2280
2280
  const config = loadMCPConfig();
2281
2281
  const projects = projectService.scan();
2282
- const project = projects.find((p) => p.name === projectName && isProjectExposed(config, p.name, p.path));
2282
+ const project = projects.find((p) => p.name === projectName && isProjectExposed(config, p.name, p.sourcePath || p.path));
2283
2283
  if (!project) {
2284
2284
  return null;
2285
2285
  }
2286
- const permissions = getProjectPermissions(config, projectName, project.path);
2286
+ const permissions = getProjectPermissions(config, projectName, project.sourcePath || project.path);
2287
2287
  if (!permissions.knowledge) {
2288
2288
  return null;
2289
2289
  }
@@ -2299,11 +2299,11 @@ function getProjectContext(projectName) {
2299
2299
  function getProjectTasks(projectName) {
2300
2300
  const config = loadMCPConfig();
2301
2301
  const projects = projectService.scan();
2302
- const project = projects.find((p) => p.name === projectName && isProjectExposed(config, p.name, p.path));
2302
+ const project = projects.find((p) => p.name === projectName && isProjectExposed(config, p.name, p.sourcePath || p.path));
2303
2303
  if (!project) {
2304
2304
  return [];
2305
2305
  }
2306
- const permissions = getProjectPermissions(config, projectName, project.path);
2306
+ const permissions = getProjectPermissions(config, projectName, project.sourcePath || project.path);
2307
2307
  if (!permissions.tasks) {
2308
2308
  return [];
2309
2309
  }
@@ -2335,13 +2335,14 @@ async function searchKnowledge(query, projectFilter) {
2335
2335
  const queryLower = query.toLowerCase();
2336
2336
  for (const project of projects) {
2337
2337
  if (projectFilter && project.name !== projectFilter) continue;
2338
- const permissions = getProjectPermissions(config, project.name, project.path);
2338
+ const permissions = getProjectPermissions(config, project.name, project.sourcePath || project.path);
2339
2339
  if (!permissions.knowledge || !project.knowledgePath) continue;
2340
2340
  const projConfig = config.projects.find(
2341
- (p) => p.path && normalizeProjectPath(p.path) === normalizeProjectPath(project.path) || !p.path && p.name === project.name
2341
+ (p) => p.path && normalizeProjectPath(p.path) === normalizeProjectPath(project.sourcePath || project.path) || !p.path && p.name === project.name
2342
2342
  );
2343
2343
  const useRAG = projConfig?.semanticSearch?.enabled;
2344
2344
  if (useRAG) {
2345
+ logger.info(`[RAG] Using semantic search for project '${project.name}'`);
2345
2346
  try {
2346
2347
  const indexPath = path16.join(project.knowledgePath, "embeddings.json");
2347
2348
  const rag = new RAGService(indexPath, projConfig?.semanticSearch?.model);
@@ -2355,9 +2356,10 @@ async function searchKnowledge(query, projectFilter) {
2355
2356
  score: r.score
2356
2357
  });
2357
2358
  }
2359
+ continue;
2358
2360
  } catch (e) {
2361
+ logger.error(`[RAG] Semantic search failed for project '${project.name}', falling back to text search`, e);
2359
2362
  }
2360
- continue;
2361
2363
  }
2362
2364
  try {
2363
2365
  const files = fs14.readdirSync(project.knowledgePath);
@@ -2394,7 +2396,7 @@ async function indexKnowledge(projectName, force = false) {
2394
2396
  return { success: false, message: `Project '${projectName}' not found`, filesIndexed: 0, filesSkipped: 0 };
2395
2397
  }
2396
2398
  const projConfig = config.projects.find(
2397
- (p) => p.path && normalizeProjectPath(p.path) === normalizeProjectPath(project.path) || !p.path && p.name === project.name
2399
+ (p) => p.path && normalizeProjectPath(p.path) === normalizeProjectPath(project.sourcePath || project.path) || !p.path && p.name === project.name
2398
2400
  ) || (project.source === "global" ? { semanticSearch: { enabled: true, model: "Xenova/all-MiniLM-L6-v2" } } : void 0);
2399
2401
  const isEnabled = projConfig?.semanticSearch?.enabled || project.semanticSearchEnabled;
2400
2402
  if (!isEnabled) {
@@ -2540,7 +2542,7 @@ All file operations should be relative to WORKSPACE_ROOT shown above.
2540
2542
  function getTask(projectName, taskSlug) {
2541
2543
  const config = loadMCPConfig();
2542
2544
  const projects = projectService.scan();
2543
- const project = projects.find((p) => p.name === projectName && isProjectExposed(config, p.name, p.path));
2545
+ const project = projects.find((p) => p.name === projectName && isProjectExposed(config, p.name, p.sourcePath || p.path));
2544
2546
  if (!project || !project.tasksPath) return null;
2545
2547
  const metaPath = path16.join(project.tasksPath, taskSlug, "meta.json");
2546
2548
  if (!fs14.existsSync(metaPath)) return null;
@@ -2553,7 +2555,7 @@ function getTask(projectName, taskSlug) {
2553
2555
  async function createTask(projectName, taskSlug, taskData) {
2554
2556
  const config = loadMCPConfig();
2555
2557
  const projects = projectService.scan();
2556
- const project = projects.find((p) => p.name === projectName && isProjectExposed(config, p.name, p.path));
2558
+ const project = projects.find((p) => p.name === projectName && isProjectExposed(config, p.name, p.sourcePath || p.path));
2557
2559
  if (!project || !project.tasksPath) {
2558
2560
  throw new Error(`Project '${projectName}' not found or not configured with a tasks path.`);
2559
2561
  }
@@ -2608,7 +2610,7 @@ async function updateTask(projectName, taskSlug, taskData) {
2608
2610
  };
2609
2611
  const config = loadMCPConfig();
2610
2612
  const projects = projectService.scan();
2611
- const project = projects.find((p) => p.name === projectName && isProjectExposed(config, p.name, p.path));
2613
+ const project = projects.find((p) => p.name === projectName && isProjectExposed(config, p.name, p.sourcePath || p.path));
2612
2614
  if (!project || !project.tasksPath) return null;
2613
2615
  const metaPath = path16.join(project.tasksPath, taskSlug, "meta.json");
2614
2616
  fs14.writeFileSync(metaPath, JSON.stringify(updatedMeta, null, 2));
@@ -2617,7 +2619,7 @@ async function updateTask(projectName, taskSlug, taskData) {
2617
2619
  function deleteTask(projectName, taskSlug) {
2618
2620
  const config = loadMCPConfig();
2619
2621
  const projects = projectService.scan();
2620
- const project = projects.find((p) => p.name === projectName && isProjectExposed(config, p.name, p.path));
2622
+ const project = projects.find((p) => p.name === projectName && isProjectExposed(config, p.name, p.sourcePath || p.path));
2621
2623
  if (!project || !project.tasksPath) return false;
2622
2624
  const taskDir = path16.join(project.tasksPath, taskSlug);
2623
2625
  if (!fs14.existsSync(taskDir)) return false;
@@ -3805,6 +3807,7 @@ var init_LogViewer = __esm({
3805
3807
  const emptyLines = Math.max(0, height - visibleLogs.length);
3806
3808
  const padding = Array(emptyLines).fill("");
3807
3809
  const formatLog = (log) => {
3810
+ if (log.includes("[RAG]")) return /* @__PURE__ */ jsx7(Text7, { color: "cyan", children: log });
3808
3811
  if (log.includes("[ERROR]")) return /* @__PURE__ */ jsx7(Text7, { color: "red", children: log });
3809
3812
  if (log.includes("[WARN]")) return /* @__PURE__ */ jsx7(Text7, { color: "yellow", children: log });
3810
3813
  if (log.includes("[INFO]")) return /* @__PURE__ */ jsx7(Text7, { color: "green", children: log });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rrce-workflow",
3
- "version": "0.2.81",
3
+ "version": "0.2.83",
4
4
  "description": "RRCE-Workflow TUI - Agentic code workflow generator for AI-assisted development",
5
5
  "author": "RRCE Team",
6
6
  "license": "MIT",