rrce-workflow 0.2.78 → 0.2.80

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.
@@ -18,48 +18,150 @@
18
18
  - {{date}}: ISO date (YYYY-MM-DD)
19
19
  - {{source}}: URL or reference to original request
20
20
  - {{workspace_name}}: Project name
21
+
22
+ NOTE: This document is the output of an interactive research session.
23
+ The Research agent engaged in constructive dialogue with the user to
24
+ achieve 100% understanding before this brief was generated.
21
25
  -->
22
26
  # Research Brief – {{task_title}}
23
27
 
24
- - Task ID: `{{task_id}}`
25
- - Task Slug: `{{task_slug}}`
26
- - Author: `{{author}}`
27
- - Date: `{{date}}`
28
- - Source Request / Conversation URL: `{{source}}`
29
- - Workspace: `{{workspace_name}}`
28
+ | Field | Value |
29
+ |-------|-------|
30
+ | Task ID | `{{task_id}}` |
31
+ | Task Slug | `{{task_slug}}` |
32
+ | Author | `{{author}}` |
33
+ | Date | `{{date}}` |
34
+ | Source Request | `{{source}}` |
35
+ | Workspace | `{{workspace_name}}` |
36
+
37
+ ---
30
38
 
31
39
  ## 1. Request Summary
32
- - Concise restatement of the user's ask.
33
- - Highlight explicit goals, constraints, and success metrics.
34
40
 
35
- ## Checklist
36
- - [ ] Replace with concrete clarification or validation step.
37
- - [ ] Replace with next ready-to-run action.
41
+ > **Original Request**: [Quote the user's initial request]
42
+
43
+ **Refined Understanding** (after clarification):
44
+ - [Clear, specific statement of what needs to be built]
45
+ - [Why it needs to be built - problem/opportunity]
46
+
47
+ ---
48
+
49
+ ## 2. Clarification Summary
50
+
51
+ The following was clarified through interactive dialogue:
52
+
53
+ | Topic | Question Asked | User Response | Impact on Scope |
54
+ |-------|----------------|---------------|-----------------|
55
+ | Intent | | | |
56
+ | Constraints | | | |
57
+ | Success Criteria | | | |
58
+ | Edge Cases | | | |
59
+
60
+ **Key Decisions Made**:
61
+ - [Decision 1 and rationale]
62
+ - [Decision 2 and rationale]
63
+
64
+ ---
65
+
66
+ ## 3. Current Knowledge Snapshot
67
+
68
+ Relevant prior work and context from project knowledge:
69
+
70
+ | Source | Relevance |
71
+ |--------|-----------|
72
+ | `{{RRCE_DATA}}/knowledge/...` | [How it applies] |
73
+ | [Search result] | [How it applies] |
74
+
75
+ **Patterns to Follow**:
76
+ - [Existing pattern 1 from codebase]
77
+ - [Existing pattern 2 from codebase]
78
+
79
+ ---
80
+
81
+ ## 4. Requirements
82
+
83
+ ### Functional Requirements
84
+ - [ ] [FR-1]: [Requirement description]
85
+ - [ ] [FR-2]: [Requirement description]
86
+ - [ ] [FR-3]: [Requirement description]
87
+
88
+ ### Non-Functional Requirements
89
+ - [ ] [NFR-1]: [Performance/Security/etc. requirement]
90
+ - [ ] [NFR-2]: [Requirement description]
91
+
92
+ ### Success Criteria
93
+ How we'll know this is done:
94
+ 1. [Measurable outcome 1]
95
+ 2. [Measurable outcome 2]
96
+ 3. [Measurable outcome 3]
97
+
98
+ ---
99
+
100
+ ## 5. Scope Boundaries
101
+
102
+ ### In Scope
103
+ - [Explicit inclusion 1]
104
+ - [Explicit inclusion 2]
105
+
106
+ ### Out of Scope
107
+ - [Explicit exclusion 1]
108
+ - [Explicit exclusion 2]
109
+
110
+ ### Constraints
111
+ - [Hard constraint 1 - e.g., timeline, tech, resources]
112
+ - [Hard constraint 2]
113
+
114
+ ---
115
+
116
+ ## 6. Assumptions & Risks
117
+
118
+ ### Assumptions
119
+ | ID | Assumption | Confidence | Validation Needed |
120
+ |----|------------|------------|-------------------|
121
+ | A1 | [Assumption] | High/Medium/Low | [How to validate] |
122
+ | A2 | [Assumption] | High/Medium/Low | [How to validate] |
123
+
124
+ ### Risks
125
+ | ID | Risk | Impact | Likelihood | Mitigation |
126
+ |----|------|--------|------------|------------|
127
+ | R1 | [Risk description] | High/Medium/Low | High/Medium/Low | [Mitigation] |
128
+ | R2 | [Risk description] | High/Medium/Low | High/Medium/Low | [Mitigation] |
129
+
130
+ ---
131
+
132
+ ## 7. Opportunity & Alternative Approaches
133
+
134
+ Approaches considered during research:
135
+
136
+ | Approach | Pros | Cons | Recommendation |
137
+ |----------|------|------|----------------|
138
+ | [Approach A] | | | Chosen / Rejected |
139
+ | [Approach B] | | | Chosen / Rejected |
140
+
141
+ **Rationale for chosen approach**: [Explanation]
142
+
143
+ ---
38
144
 
39
- ## 2. Current Knowledge Snapshot
40
- - Relevant prior work or documents from `{{RRCE_DATA}}/knowledge` or workspace.
41
- - Key facts that shape feasibility or scope.
145
+ ## 8. Hand-off Notes for Planning
42
146
 
43
- ## 3. Clarifications & Responses
44
- | Question | Answer | Status (answered/pending) | Reference |
45
- | --- | --- | --- | --- |
46
- | | | | |
147
+ ### Ready for Planning
148
+ - [ ] Core requirements are clear and specific
149
+ - [ ] Success criteria are measurable
150
+ - [ ] Scope boundaries are explicit
151
+ - [ ] No blocking open questions remain
47
152
 
48
- ## 4. Assumptions & Risks
49
- - Explicit assumptions that require validation.
50
- - Risks or edge cases that need attention.
153
+ ### Context for Planning Agent
154
+ - [Important context the planner needs to know]
155
+ - [Technical considerations for task breakdown]
51
156
 
52
- ## 5. Opportunity & Alternative Approaches
53
- - Potential strategies worth evaluating.
54
- - Trade-offs or spikes recommended before execution.
157
+ ### Open Questions (Non-Blocking)
158
+ - [Question that can be resolved during planning or execution]
55
159
 
56
- ## 6. Raw Requirement Draft
57
- - Bullet the functional outcomes and non-functional requirements as currently understood.
58
- - Note acceptance signals or metrics where available.
160
+ ### References Added to meta.json
161
+ - [List of knowledge files referenced]
59
162
 
60
- ## 7. Hand-off Notes
61
- - Immediate next steps for Planning.
62
- - Pending clarifications or decisions to resolve.
63
- - References added to `meta.json`.
163
+ ---
64
164
 
65
- > Keep this document under 500 lines. Replace placeholders with concise entries and trim empty sections if unnecessary.
165
+ > **Next Step**: `/plan TASK_SLUG={{task_slug}}`
166
+ >
167
+ > Keep this document under 500 lines. Replace placeholders with concise entries and trim empty sections.
package/dist/index.js CHANGED
@@ -1260,27 +1260,24 @@ function copyPromptsToDir(prompts, targetDir, extension) {
1260
1260
  fs7.writeFileSync(targetPath, content);
1261
1261
  }
1262
1262
  }
1263
- function convertToOpenCodeAgent(prompt) {
1263
+ function convertToOpenCodeAgent(prompt, useFileReference = false, promptFilePath) {
1264
1264
  const { frontmatter, content } = prompt;
1265
- const tools = {
1266
- // Enable standard host tools by default
1267
- "read": true,
1268
- "write": true,
1269
- "edit": true,
1270
- "bash": true,
1271
- "grep": true,
1272
- "glob": true,
1273
- "webfetch": true
1274
- };
1265
+ const tools = {};
1266
+ const hostTools = ["read", "write", "edit", "bash", "grep", "glob", "webfetch", "terminalLastCommand"];
1275
1267
  if (frontmatter.tools) {
1276
1268
  for (const tool of frontmatter.tools) {
1277
- tools[`rrce_${tool}`] = true;
1269
+ if (hostTools.includes(tool)) {
1270
+ tools[tool] = true;
1271
+ } else {
1272
+ tools[`rrce_${tool}`] = true;
1273
+ }
1278
1274
  }
1279
1275
  }
1276
+ tools["webfetch"] = true;
1280
1277
  return {
1281
1278
  description: frontmatter.description,
1282
1279
  mode: "primary",
1283
- prompt: content,
1280
+ prompt: useFileReference && promptFilePath ? `{file:${promptFilePath}}` : content,
1284
1281
  tools
1285
1282
  };
1286
1283
  }
@@ -1697,6 +1694,8 @@ async function installAgentPrompts(config, workspacePath, dataPaths) {
1697
1694
  if (primaryDataPath) {
1698
1695
  if (config.storageMode === "global") {
1699
1696
  try {
1697
+ const promptsDir = path12.join(path12.dirname(OPENCODE_CONFIG), "prompts");
1698
+ ensureDir(promptsDir);
1700
1699
  let opencodeConfig = { $schema: "https://opencode.ai/config.json" };
1701
1700
  if (fs10.existsSync(OPENCODE_CONFIG)) {
1702
1701
  opencodeConfig = JSON.parse(fs10.readFileSync(OPENCODE_CONFIG, "utf-8"));
@@ -1704,7 +1703,10 @@ async function installAgentPrompts(config, workspacePath, dataPaths) {
1704
1703
  if (!opencodeConfig.agent) opencodeConfig.agent = {};
1705
1704
  for (const prompt of prompts) {
1706
1705
  const baseName = path12.basename(prompt.filePath, ".md");
1707
- const agentConfig = convertToOpenCodeAgent(prompt);
1706
+ const promptFileName = `rrce-${baseName}.md`;
1707
+ const promptFilePath = path12.join(promptsDir, promptFileName);
1708
+ fs10.writeFileSync(promptFilePath, prompt.content);
1709
+ const agentConfig = convertToOpenCodeAgent(prompt, true, `./prompts/${promptFileName}`);
1708
1710
  opencodeConfig.agent[baseName] = agentConfig;
1709
1711
  }
1710
1712
  fs10.writeFileSync(OPENCODE_CONFIG, JSON.stringify(opencodeConfig, null, 2) + "\n");
@@ -2214,6 +2216,7 @@ var init_rag = __esm({
2214
2216
  // src/mcp/resources.ts
2215
2217
  import * as fs14 from "fs";
2216
2218
  import * as path16 from "path";
2219
+ import * as crypto from "crypto";
2217
2220
  function getExposedProjects() {
2218
2221
  const config = loadMCPConfig();
2219
2222
  const knownPaths = config.projects.map((p) => p.path).filter((p) => !!p);
@@ -2534,9 +2537,101 @@ All file operations should be relative to WORKSPACE_ROOT shown above.
2534
2537
  `;
2535
2538
  return contextPreamble;
2536
2539
  }
2540
+ function getTask(projectName, taskSlug) {
2541
+ const config = loadMCPConfig();
2542
+ const projects = projectService.scan();
2543
+ const project = projects.find((p) => p.name === projectName && isProjectExposed(config, p.name, p.path));
2544
+ if (!project || !project.tasksPath) return null;
2545
+ const metaPath = path16.join(project.tasksPath, taskSlug, "meta.json");
2546
+ if (!fs14.existsSync(metaPath)) return null;
2547
+ try {
2548
+ return JSON.parse(fs14.readFileSync(metaPath, "utf-8"));
2549
+ } catch {
2550
+ return null;
2551
+ }
2552
+ }
2553
+ async function createTask(projectName, taskSlug, taskData) {
2554
+ const config = loadMCPConfig();
2555
+ const projects = projectService.scan();
2556
+ const project = projects.find((p) => p.name === projectName && isProjectExposed(config, p.name, p.path));
2557
+ if (!project || !project.tasksPath) {
2558
+ throw new Error(`Project '${projectName}' not found or not configured with a tasks path.`);
2559
+ }
2560
+ const taskDir = path16.join(project.tasksPath, taskSlug);
2561
+ if (fs14.existsSync(taskDir)) {
2562
+ throw new Error(`Task with slug '${taskSlug}' already exists.`);
2563
+ }
2564
+ fs14.mkdirSync(taskDir, { recursive: true });
2565
+ fs14.mkdirSync(path16.join(taskDir, "research"), { recursive: true });
2566
+ fs14.mkdirSync(path16.join(taskDir, "planning"), { recursive: true });
2567
+ fs14.mkdirSync(path16.join(taskDir, "execution"), { recursive: true });
2568
+ fs14.mkdirSync(path16.join(taskDir, "docs"), { recursive: true });
2569
+ const rrceHome = process.env.RRCE_HOME || path16.join(__require("os").homedir(), ".rrce-workflow");
2570
+ const templatePath = path16.join(rrceHome, "templates", "meta.template.json");
2571
+ let meta = {
2572
+ task_id: crypto.randomUUID(),
2573
+ task_slug: taskSlug,
2574
+ status: "draft",
2575
+ agents: {}
2576
+ };
2577
+ if (fs14.existsSync(templatePath)) {
2578
+ try {
2579
+ const template = JSON.parse(fs14.readFileSync(templatePath, "utf-8"));
2580
+ meta = { ...template, ...meta };
2581
+ } catch (e) {
2582
+ logger.error("Failed to load meta template", e);
2583
+ }
2584
+ }
2585
+ meta.created_at = (/* @__PURE__ */ new Date()).toISOString();
2586
+ meta.updated_at = meta.created_at;
2587
+ meta.workspace = {
2588
+ name: project.name,
2589
+ path: project.path || project.dataPath,
2590
+ hash: project.name
2591
+ };
2592
+ Object.assign(meta, taskData);
2593
+ const metaPath = path16.join(taskDir, "meta.json");
2594
+ fs14.writeFileSync(metaPath, JSON.stringify(meta, null, 2));
2595
+ return meta;
2596
+ }
2597
+ async function updateTask(projectName, taskSlug, taskData) {
2598
+ const meta = getTask(projectName, taskSlug);
2599
+ if (!meta) throw new Error(`Task '${taskSlug}' not found.`);
2600
+ const updatedMeta = {
2601
+ ...meta,
2602
+ ...taskData,
2603
+ updated_at: (/* @__PURE__ */ new Date()).toISOString(),
2604
+ // Ensure nested objects are merged if they exist in taskData
2605
+ agents: taskData.agents ? { ...meta.agents, ...taskData.agents } : meta.agents,
2606
+ workspace: meta.workspace
2607
+ // Protect workspace metadata
2608
+ };
2609
+ const config = loadMCPConfig();
2610
+ const projects = projectService.scan();
2611
+ const project = projects.find((p) => p.name === projectName && isProjectExposed(config, p.name, p.path));
2612
+ if (!project || !project.tasksPath) return null;
2613
+ const metaPath = path16.join(project.tasksPath, taskSlug, "meta.json");
2614
+ fs14.writeFileSync(metaPath, JSON.stringify(updatedMeta, null, 2));
2615
+ return updatedMeta;
2616
+ }
2617
+ function deleteTask(projectName, taskSlug) {
2618
+ const config = loadMCPConfig();
2619
+ const projects = projectService.scan();
2620
+ const project = projects.find((p) => p.name === projectName && isProjectExposed(config, p.name, p.path));
2621
+ if (!project || !project.tasksPath) return false;
2622
+ const taskDir = path16.join(project.tasksPath, taskSlug);
2623
+ if (!fs14.existsSync(taskDir)) return false;
2624
+ if (fs14.rmSync) {
2625
+ fs14.rmSync(taskDir, { recursive: true, force: true });
2626
+ } else {
2627
+ fs14.rmdirSync(taskDir, { recursive: true });
2628
+ }
2629
+ return true;
2630
+ }
2537
2631
  var init_resources = __esm({
2538
2632
  "src/mcp/resources.ts"() {
2539
2633
  "use strict";
2634
+ init_logger();
2540
2635
  init_config();
2541
2636
  init_config_utils();
2542
2637
  init_detection();
@@ -2779,6 +2874,66 @@ function registerToolHandlers(server) {
2779
2874
  },
2780
2875
  required: ["agent"]
2781
2876
  }
2877
+ },
2878
+ {
2879
+ name: "list_tasks",
2880
+ description: "List all tasks for a project",
2881
+ inputSchema: {
2882
+ type: "object",
2883
+ properties: { project: { type: "string", description: "Name of the project" } },
2884
+ required: ["project"]
2885
+ }
2886
+ },
2887
+ {
2888
+ name: "get_task",
2889
+ description: "Get details of a specific task",
2890
+ inputSchema: {
2891
+ type: "object",
2892
+ properties: {
2893
+ project: { type: "string", description: "Name of the project" },
2894
+ task_slug: { type: "string", description: "The slug of the task" }
2895
+ },
2896
+ required: ["project", "task_slug"]
2897
+ }
2898
+ },
2899
+ {
2900
+ name: "create_task",
2901
+ description: "Create a new task in the project",
2902
+ inputSchema: {
2903
+ type: "object",
2904
+ properties: {
2905
+ project: { type: "string", description: "Name of the project" },
2906
+ task_slug: { type: "string", description: "The slug for the new task (kebab-case)" },
2907
+ title: { type: "string", description: "The title of the task" },
2908
+ summary: { type: "string", description: "Brief summary of the task" }
2909
+ },
2910
+ required: ["project", "task_slug"]
2911
+ }
2912
+ },
2913
+ {
2914
+ name: "update_task",
2915
+ description: "Update an existing task",
2916
+ inputSchema: {
2917
+ type: "object",
2918
+ properties: {
2919
+ project: { type: "string", description: "Name of the project" },
2920
+ task_slug: { type: "string", description: "The slug of the task" },
2921
+ updates: { type: "object", description: "The fields to update in meta.json", additionalProperties: true }
2922
+ },
2923
+ required: ["project", "task_slug", "updates"]
2924
+ }
2925
+ },
2926
+ {
2927
+ name: "delete_task",
2928
+ description: "Delete a task from the project",
2929
+ inputSchema: {
2930
+ type: "object",
2931
+ properties: {
2932
+ project: { type: "string", description: "Name of the project" },
2933
+ task_slug: { type: "string", description: "The slug of the task to delete" }
2934
+ },
2935
+ required: ["project", "task_slug"]
2936
+ }
2782
2937
  }
2783
2938
  ];
2784
2939
  const projects = getExposedProjects();
@@ -2866,6 +3021,38 @@ The system has pre-resolved the configuration for this project. Use these values
2866
3021
  `;
2867
3022
  return { content: [{ type: "text", text: contextPreamble + rendered }] };
2868
3023
  }
3024
+ case "list_tasks": {
3025
+ const params = args;
3026
+ const tasks = getProjectTasks(params.project);
3027
+ return { content: [{ type: "text", text: JSON.stringify(tasks, null, 2) }] };
3028
+ }
3029
+ case "get_task": {
3030
+ const params = args;
3031
+ const task = getTask(params.project, params.task_slug);
3032
+ if (!task) {
3033
+ return { content: [{ type: "text", text: `Task '${params.task_slug}' not found in project '${params.project}'.` }], isError: true };
3034
+ }
3035
+ return { content: [{ type: "text", text: JSON.stringify(task, null, 2) }] };
3036
+ }
3037
+ case "create_task": {
3038
+ const params = args;
3039
+ const taskData = {
3040
+ title: params.title || params.task_slug,
3041
+ summary: params.summary || ""
3042
+ };
3043
+ const task = await createTask(params.project, params.task_slug, taskData);
3044
+ return { content: [{ type: "text", text: JSON.stringify(task, null, 2) }] };
3045
+ }
3046
+ case "update_task": {
3047
+ const params = args;
3048
+ const task = await updateTask(params.project, params.task_slug, params.updates);
3049
+ return { content: [{ type: "text", text: JSON.stringify(task, null, 2) }] };
3050
+ }
3051
+ case "delete_task": {
3052
+ const params = args;
3053
+ const success = deleteTask(params.project, params.task_slug);
3054
+ return { content: [{ type: "text", text: success ? `Task '${params.task_slug}' deleted.` : `Failed to delete task '${params.task_slug}'.` }] };
3055
+ }
2869
3056
  case "help_setup": {
2870
3057
  const msg = `
2871
3058
  RRCE MCP Server is running, but no projects are configured/exposed.
@@ -4729,6 +4916,7 @@ import { confirm as confirm9, spinner as spinner6, note as note12, outro as outr
4729
4916
  import pc14 from "picocolors";
4730
4917
  import * as fs18 from "fs";
4731
4918
  import * as path19 from "path";
4919
+ import { stringify as stringify3 } from "yaml";
4732
4920
  async function runUpdateFlow(workspacePath, workspaceName, currentStorageMode) {
4733
4921
  const s = spinner6();
4734
4922
  s.start("Checking for updates");
@@ -4739,10 +4927,25 @@ async function runUpdateFlow(workspacePath, workspaceName, currentStorageMode) {
4739
4927
  const customGlobalPath = getEffectiveRRCEHome(workspacePath);
4740
4928
  const dataPaths = resolveAllDataPathsWithCustomGlobal(mode, workspaceName, workspacePath, customGlobalPath);
4741
4929
  s.stop("Updates found");
4930
+ const updateTargets = [
4931
+ ` \u2022 prompts/ (${prompts.length} agent prompts)`,
4932
+ ` \u2022 templates/ (output templates)`,
4933
+ ` \u2022 docs/ (documentation)`
4934
+ ];
4935
+ const configFilePath = getConfigPath(workspacePath);
4936
+ const ideTargets = [];
4937
+ if (fs18.existsSync(configFilePath)) {
4938
+ const configContent = fs18.readFileSync(configFilePath, "utf-8");
4939
+ if (configContent.includes("opencode: true")) ideTargets.push("OpenCode agents");
4940
+ if (configContent.includes("copilot: true")) ideTargets.push("GitHub Copilot");
4941
+ if (configContent.includes("antigravity: true")) ideTargets.push("Antigravity");
4942
+ }
4943
+ if (ideTargets.length > 0) {
4944
+ updateTargets.push(` \u2022 IDE integrations: ${ideTargets.join(", ")}`);
4945
+ }
4742
4946
  note12(
4743
4947
  `The following will be updated from the package:
4744
- \u2022 prompts/ (${prompts.length} agent prompts)
4745
- \u2022 templates/ (output templates)
4948
+ ${updateTargets.join("\n")}
4746
4949
 
4747
4950
  Target locations:
4748
4951
  ${dataPaths.map((p) => ` \u2022 ${p}`).join("\n")}`,
@@ -4759,29 +4962,51 @@ ${dataPaths.map((p) => ` \u2022 ${p}`).join("\n")}`,
4759
4962
  s.start("Updating from package");
4760
4963
  for (const dataPath of dataPaths) {
4761
4964
  copyDirToAllStoragePaths(path19.join(agentCoreDir, "templates"), "templates", [dataPath]);
4965
+ copyDirToAllStoragePaths(path19.join(agentCoreDir, "prompts"), "prompts", [dataPath]);
4966
+ copyDirToAllStoragePaths(path19.join(agentCoreDir, "docs"), "docs", [dataPath]);
4762
4967
  }
4763
- const configFilePath = getConfigPath(workspacePath);
4968
+ const rrceHome = customGlobalPath || getDefaultRRCEHome2();
4969
+ ensureDir(path19.join(rrceHome, "templates"));
4970
+ ensureDir(path19.join(rrceHome, "docs"));
4971
+ copyDirRecursive(path19.join(agentCoreDir, "templates"), path19.join(rrceHome, "templates"));
4972
+ copyDirRecursive(path19.join(agentCoreDir, "docs"), path19.join(rrceHome, "docs"));
4764
4973
  if (fs18.existsSync(configFilePath)) {
4765
4974
  const configContent = fs18.readFileSync(configFilePath, "utf-8");
4766
4975
  if (configContent.includes("copilot: true")) {
4767
4976
  const copilotPath = getAgentPromptPath(workspacePath, "copilot");
4768
4977
  ensureDir(copilotPath);
4978
+ clearDirectory(copilotPath);
4769
4979
  copyPromptsToDir(prompts, copilotPath, ".agent.md");
4770
4980
  }
4771
4981
  if (configContent.includes("antigravity: true")) {
4772
4982
  const antigravityPath = getAgentPromptPath(workspacePath, "antigravity");
4773
4983
  ensureDir(antigravityPath);
4984
+ clearDirectory(antigravityPath);
4774
4985
  copyPromptsToDir(prompts, antigravityPath, ".md");
4775
4986
  }
4987
+ if (configContent.includes("opencode: true")) {
4988
+ const primaryDataPath = dataPaths[0];
4989
+ if (primaryDataPath) {
4990
+ updateOpenCodeAgents(prompts, mode, primaryDataPath);
4991
+ }
4992
+ }
4776
4993
  }
4777
4994
  s.stop("Update complete");
4778
4995
  const summary = [
4779
4996
  `Updated:`,
4780
4997
  ` \u2713 ${prompts.length} agent prompts`,
4781
4998
  ` \u2713 Output templates`,
4782
- ``,
4783
- `Your configuration and knowledge files were preserved.`
4999
+ ` \u2713 Documentation`
4784
5000
  ];
5001
+ if (ideTargets.length > 0) {
5002
+ summary.push(` \u2713 IDE integrations: ${ideTargets.join(", ")}`);
5003
+ }
5004
+ summary.push(
5005
+ ``,
5006
+ `Your configuration and knowledge files were preserved.`,
5007
+ ``,
5008
+ pc14.dim(`\u{1F4A1} If using OpenCode, you may need to reload for changes to take effect.`)
5009
+ );
4785
5010
  note12(summary.join("\n"), "Update Summary");
4786
5011
  outro5(pc14.green("\u2713 Successfully updated from package!"));
4787
5012
  } catch (error) {
@@ -4790,6 +5015,69 @@ ${dataPaths.map((p) => ` \u2022 ${p}`).join("\n")}`,
4790
5015
  process.exit(1);
4791
5016
  }
4792
5017
  }
5018
+ function updateOpenCodeAgents(prompts, mode, primaryDataPath) {
5019
+ if (mode === "global") {
5020
+ try {
5021
+ const promptsDir = path19.join(path19.dirname(OPENCODE_CONFIG), "prompts");
5022
+ ensureDir(promptsDir);
5023
+ let opencodeConfig = { $schema: "https://opencode.ai/config.json" };
5024
+ if (fs18.existsSync(OPENCODE_CONFIG)) {
5025
+ opencodeConfig = JSON.parse(fs18.readFileSync(OPENCODE_CONFIG, "utf-8"));
5026
+ }
5027
+ if (!opencodeConfig.agent) opencodeConfig.agent = {};
5028
+ const currentAgentNames = prompts.map((p) => path19.basename(p.filePath, ".md"));
5029
+ const existingAgentNames = Object.keys(opencodeConfig.agent);
5030
+ const rrceAgentPrefixes = ["init", "research", "planning", "executor", "doctor", "documentation", "sync"];
5031
+ for (const existingName of existingAgentNames) {
5032
+ const isRrceAgent = rrceAgentPrefixes.some((prefix) => existingName.startsWith(prefix));
5033
+ const stillExists = currentAgentNames.includes(existingName);
5034
+ if (isRrceAgent && !stillExists) {
5035
+ delete opencodeConfig.agent[existingName];
5036
+ const oldPromptFile = path19.join(promptsDir, `rrce-${existingName}.md`);
5037
+ if (fs18.existsSync(oldPromptFile)) {
5038
+ fs18.unlinkSync(oldPromptFile);
5039
+ }
5040
+ }
5041
+ }
5042
+ for (const prompt of prompts) {
5043
+ const baseName = path19.basename(prompt.filePath, ".md");
5044
+ const promptFileName = `rrce-${baseName}.md`;
5045
+ const promptFilePath = path19.join(promptsDir, promptFileName);
5046
+ fs18.writeFileSync(promptFilePath, prompt.content);
5047
+ const agentConfig = convertToOpenCodeAgent(prompt, true, `./prompts/${promptFileName}`);
5048
+ opencodeConfig.agent[baseName] = agentConfig;
5049
+ }
5050
+ fs18.writeFileSync(OPENCODE_CONFIG, JSON.stringify(opencodeConfig, null, 2) + "\n");
5051
+ } catch (e) {
5052
+ console.error("Failed to update global OpenCode config with agents:", e);
5053
+ }
5054
+ } else {
5055
+ const opencodeBaseDir = path19.join(primaryDataPath, ".opencode", "agent");
5056
+ ensureDir(opencodeBaseDir);
5057
+ clearDirectory(opencodeBaseDir);
5058
+ for (const prompt of prompts) {
5059
+ const baseName = path19.basename(prompt.filePath, ".md");
5060
+ const agentConfig = convertToOpenCodeAgent(prompt);
5061
+ const content = `---
5062
+ ${stringify3({
5063
+ description: agentConfig.description,
5064
+ mode: agentConfig.mode,
5065
+ tools: agentConfig.tools
5066
+ })}---
5067
+ ${agentConfig.prompt}`;
5068
+ fs18.writeFileSync(path19.join(opencodeBaseDir, `${baseName}.md`), content);
5069
+ }
5070
+ }
5071
+ }
5072
+ function clearDirectory(dirPath) {
5073
+ if (!fs18.existsSync(dirPath)) return;
5074
+ const entries = fs18.readdirSync(dirPath, { withFileTypes: true });
5075
+ for (const entry of entries) {
5076
+ if (entry.isFile()) {
5077
+ fs18.unlinkSync(path19.join(dirPath, entry.name));
5078
+ }
5079
+ }
5080
+ }
4793
5081
  function resolveAllDataPathsWithCustomGlobal(mode, workspaceName, workspaceRoot, customGlobalPath) {
4794
5082
  const globalPath = path19.join(customGlobalPath, "workspaces", workspaceName);
4795
5083
  const workspacePath = path19.join(workspaceRoot, ".rrce-workflow");
@@ -4808,6 +5096,7 @@ var init_update_flow = __esm({
4808
5096
  init_paths();
4809
5097
  init_prompts();
4810
5098
  init_utils();
5099
+ init_install();
4811
5100
  }
4812
5101
  });
4813
5102
 
@@ -7,7 +7,9 @@
7
7
  RRCE-Workflow is a TUI-based agentic code workflow generator designed to work seamlessly across:
8
8
  - **GitHub Copilot CLI**
9
9
  - **Antigravity IDE** (Google's agentic coding environment)
10
+ - **OpenCode** (Native agentic TUI environment)
10
11
  - **VS Code** (with Copilot and other AI extensions)
12
+ - **Claude Desktop**
11
13
 
12
14
  The system provides a structured multi-agent pipeline for software development tasks, with persistent knowledge caching and workspace-aware context management.
13
15
 
@@ -243,6 +245,7 @@ RRCE-Workflow prompts are designed to work across multiple AI coding tools:
243
245
  | Tool | Prompt Location | Extension | Notes |
244
246
  |------|----------------|-----------|-------|
245
247
  | **Antigravity IDE** | `.agent/workflows/` | `.md` | Native workflow support |
248
+ | **OpenCode** | `.opencode/agent/` | `.md` | Custom Primary Agents |
246
249
  | **GitHub Copilot (VSCode)** | `.github/agents/` | `.agent.md` | Custom agents format |
247
250
  | **Copilot CLI** | Any location | `.md` | Reference via file path |
248
251
 
@@ -298,6 +301,17 @@ When you run `rrce-workflow wizard`, it creates:
298
301
  └── sync.md
299
302
  ```
300
303
 
304
+ **For OpenCode:**
305
+ ```
306
+ .opencode/agent/
307
+ ├── rrce-init.md
308
+ ├── rrce-research.md
309
+ ├── rrce-planning.md
310
+ ├── rrce-executor.md
311
+ ├── rrce-documentation.md
312
+ └── rrce-sync.md
313
+ ```
314
+
301
315
  ### Copilot-Specific Features
302
316
 
303
317
  Our prompts include Copilot-compatible frontmatter:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rrce-workflow",
3
- "version": "0.2.78",
3
+ "version": "0.2.80",
4
4
  "description": "RRCE-Workflow TUI - Agentic code workflow generator for AI-assisted development",
5
5
  "author": "RRCE Team",
6
6
  "license": "MIT",