opencode-conductor-plugin 1.24.0 → 1.25.0
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 +9 -9
- package/dist/commands/implement.d.ts +1 -0
- package/dist/commands/implement.js +31 -0
- package/dist/commands/newTrack.d.ts +1 -0
- package/dist/commands/newTrack.js +12 -0
- package/dist/commands/revert.d.ts +1 -0
- package/dist/commands/revert.js +9 -0
- package/dist/commands/setup.d.ts +1 -0
- package/dist/commands/setup.js +10 -0
- package/dist/commands/status.d.ts +1 -0
- package/dist/commands/status.js +6 -0
- package/dist/index.js +83 -212
- package/dist/prompts/agent/conductor.md +22 -12
- package/dist/prompts/agent.md +1 -1
- package/dist/prompts/commands/conductor:implement.md +4 -0
- package/dist/prompts/commands/conductor:newTrack.md +4 -0
- package/dist/prompts/commands/conductor:revert.md +4 -0
- package/dist/prompts/commands/conductor:setup.md +4 -0
- package/dist/prompts/commands/conductor:status.md +4 -0
- package/dist/prompts/implement.toml +11 -14
- package/dist/prompts/newTrack.toml +5 -3
- package/dist/prompts/revert.toml +4 -4
- package/dist/prompts/setup.toml +9 -9
- package/dist/prompts/status.toml +4 -4
- package/dist/prompts/strategies/delegate.md +2 -4
- package/dist/tools/commands.d.ts +5 -5
- package/dist/tools/commands.js +1 -0
- package/dist/tools/commands.test.d.ts +1 -0
- package/dist/tools/commands.test.js +151 -0
- package/dist/utils/commandFactory.d.ts +5 -5
- package/dist/utils/commandFactory.js +39 -45
- package/dist/utils/stateManager.d.ts +10 -0
- package/dist/utils/stateManager.js +30 -0
- package/package.json +4 -7
package/README.md
CHANGED
|
@@ -11,7 +11,7 @@ The philosophy is simple: **control your code by controlling your context.** By
|
|
|
11
11
|
## 🚀 Key Features
|
|
12
12
|
|
|
13
13
|
* **Specialized `@conductor` Agent**: A dedicated subagent that acts as your Project Architect and Technical Lead.
|
|
14
|
-
* **Native Slash Commands**: Integrated shortcuts like `/
|
|
14
|
+
* **Native Slash Commands**: Integrated shortcuts like `/conductor:setup`, `/conductor:newTrack`, and `/conductor:implement` for frictionless project management.
|
|
15
15
|
* **Modern Permissions**: Fully compatible with OpenCode v1.1.1 granular permission system.
|
|
16
16
|
* **Protocol-Driven Workflow**: Automated enforcement of the **Context -> Spec -> Plan -> Implement** lifecycle.
|
|
17
17
|
* **Smart Revert**: A Git-aware revert system that understands logical units of work (Tracks, Phases, Tasks) instead of just raw commit hashes.
|
|
@@ -26,18 +26,18 @@ The philosophy is simple: **control your code by controlling your context.** By
|
|
|
26
26
|
|
|
27
27
|
Conductor organizes your work into **Tracks** (features or bug fixes). Every Track follows three mandatory phases:
|
|
28
28
|
|
|
29
|
-
### 1. Project Initialization (`/
|
|
29
|
+
### 1. Project Initialization (`/conductor:setup`)
|
|
30
30
|
Run this once per project. The agent will interview you to define:
|
|
31
31
|
* **Product Vision**: Target users, core goals, and primary features.
|
|
32
32
|
* **Tech Stack**: Languages, frameworks, and databases.
|
|
33
33
|
* **Workflow Rules**: Testing standards (e.g., TDD), commit strategies, and documentation patterns.
|
|
34
34
|
|
|
35
|
-
### 2. Track Planning (`/
|
|
35
|
+
### 2. Track Planning (`/conductor:newTrack`)
|
|
36
36
|
When you're ready for a new task, tell the agent what you want to build.
|
|
37
37
|
* **Specification (`spec.md`)**: Conductor asks 3-5 targeted questions to clarify the "What" and "Why".
|
|
38
38
|
* **Implementation Plan (`plan.md`)**: Once the spec is approved, Conductor generates a step-by-step checklist adhering to your project's workflow rules.
|
|
39
39
|
|
|
40
|
-
### 3. Autonomous Implementation (`/
|
|
40
|
+
### 3. Autonomous Implementation (`/conductor:implement`)
|
|
41
41
|
The agent works through the `plan.md` checklist, executing tasks, running tests, and making semantic commits automatically until the Track is complete.
|
|
42
42
|
|
|
43
43
|
---
|
|
@@ -94,11 +94,11 @@ We highly recommend pinning the `@conductor` agent to a "flash" model for optima
|
|
|
94
94
|
|
|
95
95
|
| Command | Description |
|
|
96
96
|
| :--- | :--- |
|
|
97
|
-
| `/
|
|
98
|
-
| `/
|
|
99
|
-
| `/
|
|
100
|
-
| `/
|
|
101
|
-
| `/
|
|
97
|
+
| `/conductor:setup` | Initialize the `conductor/` directory and project "Constitution". |
|
|
98
|
+
| `/conductor:newTrack "desc"` | Start a new feature/bug Track with spec and plan generation. |
|
|
99
|
+
| `/conductor:implement` | Start implementing the next pending task in the current track. |
|
|
100
|
+
| `/conductor:status` | Get a high-level overview of project progress and active tracks. |
|
|
101
|
+
| `/conductor:revert` | Interactively select a task, phase, or track to undo via Git. |
|
|
102
102
|
|
|
103
103
|
---
|
|
104
104
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const implementCommand: (ctx: any) => import("@opencode-ai/plugin/tool").ToolDefinition;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { tool } from "@opencode-ai/plugin/tool";
|
|
2
|
+
import { createConductorCommand } from "../utils/commandFactory.js";
|
|
3
|
+
import { join, dirname } from "path";
|
|
4
|
+
import { fileURLToPath } from "url";
|
|
5
|
+
import { readFile } from "fs/promises";
|
|
6
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
7
|
+
const __dirname = dirname(__filename);
|
|
8
|
+
export const implementCommand = createConductorCommand({
|
|
9
|
+
name: "implement.toml",
|
|
10
|
+
description: "Implements tasks from a Conductor track.",
|
|
11
|
+
args: {
|
|
12
|
+
track_name: tool.schema.string().optional().describe("Specific track to implement. If omitted, selects the next incomplete track."),
|
|
13
|
+
},
|
|
14
|
+
additionalContext: async (ctx, args) => {
|
|
15
|
+
// 1. Choose strategy based on OMO activity
|
|
16
|
+
const strategyFile = ctx.isOMOActive ? "delegate.md" : "manual.md";
|
|
17
|
+
const strategyPath = join(__dirname, "../prompts/strategies", strategyFile);
|
|
18
|
+
let strategySection = "";
|
|
19
|
+
try {
|
|
20
|
+
strategySection = await readFile(strategyPath, "utf-8");
|
|
21
|
+
}
|
|
22
|
+
catch (e) {
|
|
23
|
+
console.warn(`[Conductor] Failed to load strategy ${strategyFile}:`, e);
|
|
24
|
+
strategySection = "Error: Could not load execution strategy.";
|
|
25
|
+
}
|
|
26
|
+
return {
|
|
27
|
+
strategy_section: strategySection,
|
|
28
|
+
track_name: args.track_name || ""
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const newTrackCommand: (ctx: any) => import("@opencode-ai/plugin/tool").ToolDefinition;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { tool } from "@opencode-ai/plugin/tool";
|
|
2
|
+
import { createConductorCommand } from "../utils/commandFactory.js";
|
|
3
|
+
export const newTrackCommand = createConductorCommand({
|
|
4
|
+
name: "newTrack.toml",
|
|
5
|
+
description: "Creates a new track (feature/bug) in the Conductor system. IMPORTANT: Do NOT create any todos using 'todowrite' or 'task' tools before or during this command, as it manages its own interactive state and will conflict with continuation enforcers.",
|
|
6
|
+
args: {
|
|
7
|
+
description: tool.schema.string().optional().describe("Brief description of the track."),
|
|
8
|
+
},
|
|
9
|
+
additionalContext: async (_, args) => ({
|
|
10
|
+
args: args.description || ""
|
|
11
|
+
})
|
|
12
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const revertCommand: (ctx: any) => import("@opencode-ai/plugin/tool").ToolDefinition;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { createConductorCommand } from "../utils/commandFactory.js";
|
|
2
|
+
import { tool } from "@opencode-ai/plugin/tool";
|
|
3
|
+
export const revertCommand = createConductorCommand({
|
|
4
|
+
name: "revert.toml",
|
|
5
|
+
description: "Reverts a Conductor track, phase, or task.",
|
|
6
|
+
args: {
|
|
7
|
+
target: tool.schema.string().optional().describe("ID or description of what to revert."),
|
|
8
|
+
}
|
|
9
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const setupCommand: (ctx: any) => import("@opencode-ai/plugin/tool").ToolDefinition;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { tool } from "@opencode-ai/plugin/tool";
|
|
2
|
+
import { createConductorCommand } from "../utils/commandFactory.js";
|
|
3
|
+
export const setupCommand = createConductorCommand({
|
|
4
|
+
name: "setup.toml",
|
|
5
|
+
description: "Sets up the Conductor environment for the project. Call this to start or resume the setup process. IMPORTANT: Do NOT create any todos using 'todowrite' or 'task' tools before or during this command, as it manages its own interactive state and will conflict with continuation enforcers.",
|
|
6
|
+
args: {
|
|
7
|
+
user_input: tool.schema.string().optional().describe("The user's response to a previous question, if applicable."),
|
|
8
|
+
},
|
|
9
|
+
requiresSetup: false // Setup command is what creates the setup
|
|
10
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const statusCommand: (ctx: any) => import("@opencode-ai/plugin/tool").ToolDefinition;
|
package/dist/index.js
CHANGED
|
@@ -1,223 +1,94 @@
|
|
|
1
|
+
import { setupCommand } from "./commands/setup.js";
|
|
2
|
+
import { newTrackCommand } from "./commands/newTrack.js";
|
|
3
|
+
import { implementCommand } from "./commands/implement.js";
|
|
4
|
+
import { statusCommand } from "./commands/status.js";
|
|
5
|
+
import { revertCommand } from "./commands/revert.js";
|
|
1
6
|
import { join, dirname } from "path";
|
|
2
|
-
import {
|
|
7
|
+
import { homedir } from "os";
|
|
8
|
+
import { existsSync, readFileSync } from "fs";
|
|
3
9
|
import { readFile } from "fs/promises";
|
|
4
10
|
import { fileURLToPath } from "url";
|
|
5
|
-
import { createDelegationTool } from "./tools/delegate.js";
|
|
6
|
-
import { BackgroundManager, createBackgroundTask, createBackgroundOutput, createBackgroundCancel, } from "./tools/background.js";
|
|
7
|
-
import { createSetupTool, createNewTrackTool, createImplementTool, createStatusTool, createRevertTool, } from "./tools/commands.js";
|
|
8
11
|
const __filename = fileURLToPath(import.meta.url);
|
|
9
12
|
const __dirname = dirname(__filename);
|
|
10
|
-
const safeRead = async (path) => {
|
|
11
|
-
try {
|
|
12
|
-
if (existsSync(path))
|
|
13
|
-
return await readFile(path, "utf-8");
|
|
14
|
-
}
|
|
15
|
-
catch (e) { }
|
|
16
|
-
return null;
|
|
17
|
-
};
|
|
18
13
|
const ConductorPlugin = async (ctx) => {
|
|
14
|
+
// Detect oh-my-opencode for synergy features
|
|
15
|
+
const configPath = join(homedir(), ".config", "opencode", "opencode.json");
|
|
16
|
+
let isOMOActive = false;
|
|
19
17
|
try {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
const promptPath = join(__dirname, "prompts", filename);
|
|
25
|
-
try {
|
|
26
|
-
const content = await readFile(promptPath, "utf-8");
|
|
27
|
-
const descMatch = content.match(/description\s*=\s*"([^"]+)"/);
|
|
28
|
-
const description = descMatch ? descMatch[1] : "Conductor Command";
|
|
29
|
-
const promptMatch = content.match(/prompt\s*=\s*"""([\s\S]*?)"""/);
|
|
30
|
-
let promptText = promptMatch ? promptMatch[1] : "";
|
|
31
|
-
if (!promptText)
|
|
32
|
-
throw new Error(`Could not parse prompt text from ${filename}`);
|
|
33
|
-
const defaults = {
|
|
34
|
-
templatesDir: join(dirname(__dirname), "templates"),
|
|
35
|
-
};
|
|
36
|
-
const finalReplacements = { ...defaults, ...replacements };
|
|
37
|
-
for (const [key, value] of Object.entries(finalReplacements)) {
|
|
38
|
-
promptText = promptText.replaceAll(`{{${key}}}`, value || "");
|
|
39
|
-
}
|
|
40
|
-
return { prompt: promptText, description: description };
|
|
41
|
-
}
|
|
42
|
-
catch (error) {
|
|
43
|
-
console.error(`[Conductor] Error loading prompt ${filename}:`, error);
|
|
44
|
-
return {
|
|
45
|
-
prompt: `SYSTEM ERROR: Failed to load prompt ${filename}`,
|
|
46
|
-
description: "Error loading command",
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
};
|
|
50
|
-
// 3. Load all Command Prompts (Parallel)
|
|
51
|
-
const [setup, newTrack, implement, status, revert] = await Promise.all([
|
|
52
|
-
loadPrompt("setup.toml"),
|
|
53
|
-
loadPrompt("newTrack.toml", { args: "$ARGUMENTS" }),
|
|
54
|
-
loadPrompt("implement.toml", {
|
|
55
|
-
track_name: "$ARGUMENTS",
|
|
56
|
-
}),
|
|
57
|
-
loadPrompt("status.toml"),
|
|
58
|
-
loadPrompt("revert.toml", { target: "$ARGUMENTS" }),
|
|
59
|
-
safeRead(join(ctx.directory, "conductor", "workflow.md")),
|
|
60
|
-
]);
|
|
61
|
-
// 4. Extract Agent Prompts
|
|
62
|
-
const [conductorMd, implementerMd] = await Promise.all([
|
|
63
|
-
readFile(join(__dirname, "prompts", "agent", "conductor.md"), "utf-8"),
|
|
64
|
-
readFile(join(__dirname, "prompts", "agent", "implementer.md"), "utf-8"),
|
|
65
|
-
]);
|
|
66
|
-
const conductorPrompt = conductorMd.split("---").pop()?.trim() || "";
|
|
67
|
-
const implementerPrompt = implementerMd.split("---").pop()?.trim() || "";
|
|
68
|
-
console.log("[Conductor] All components ready. Injecting config...");
|
|
69
|
-
return {
|
|
70
|
-
tool: {
|
|
71
|
-
...(ctx.client.tool || {}),
|
|
72
|
-
"conductor_delegate": createDelegationTool(ctx),
|
|
73
|
-
"conductor_bg_task": createBackgroundTask(backgroundManager),
|
|
74
|
-
"conductor_bg_output": createBackgroundOutput(backgroundManager),
|
|
75
|
-
"conductor_bg_cancel": createBackgroundCancel(backgroundManager),
|
|
76
|
-
"conductor_setup": createSetupTool(ctx),
|
|
77
|
-
"conductor_newTrack": createNewTrackTool(ctx),
|
|
78
|
-
"conductor_implement": createImplementTool(ctx),
|
|
79
|
-
"conductor_status": createStatusTool(ctx),
|
|
80
|
-
"conductor_revert": createRevertTool(ctx),
|
|
81
|
-
},
|
|
82
|
-
config: async (config) => {
|
|
83
|
-
if (!config)
|
|
84
|
-
return;
|
|
85
|
-
console.log("[Conductor] config handler: Merging commands and agents...");
|
|
86
|
-
config.command = {
|
|
87
|
-
...(config.command || {}),
|
|
88
|
-
"conductor_setup": {
|
|
89
|
-
template: "Use the conductor_setup tool to scaffold the project and set up the Conductor environment. After calling the tool, you MUST follow all instructions provided in the tool's response exactly as specified.",
|
|
90
|
-
description: setup.description,
|
|
91
|
-
agent: "conductor",
|
|
92
|
-
},
|
|
93
|
-
"conductor_newTrack": {
|
|
94
|
-
template: "Use the conductor_newTrack tool to plan a track and generate track-specific spec documents. If arguments were provided with this command, pass them as the 'description' parameter to the tool. After calling the tool, you MUST follow all instructions provided in the tool's response exactly as specified.",
|
|
95
|
-
description: newTrack.description,
|
|
96
|
-
agent: "conductor",
|
|
97
|
-
},
|
|
98
|
-
"conductor_implement": {
|
|
99
|
-
template: "Use the conductor_implement tool to execute the tasks defined in the specified track's plan. If a track name was provided as an argument with this command, pass it as the 'track_name' parameter to the tool. After calling the tool, you MUST follow all instructions provided in the tool's response exactly as specified.",
|
|
100
|
-
description: implement.description,
|
|
101
|
-
agent: "conductor_implementer",
|
|
102
|
-
},
|
|
103
|
-
"conductor_status": {
|
|
104
|
-
template: "Use the conductor_status tool to display the current progress of the project. After calling the tool, you MUST follow all instructions provided in the tool's response exactly as specified.",
|
|
105
|
-
description: status.description,
|
|
106
|
-
agent: "conductor",
|
|
107
|
-
},
|
|
108
|
-
"conductor_revert": {
|
|
109
|
-
template: "Use the conductor_revert tool to revert previous work. If a target was provided as an argument with this command (e.g., 'track <track_id>', 'phase <phase_name>', 'task <task_name>'), pass it as the 'target' parameter to the tool. After calling the tool, you MUST follow all instructions provided in the tool's response exactly as specified.",
|
|
110
|
-
description: revert.description,
|
|
111
|
-
agent: "conductor",
|
|
112
|
-
},
|
|
113
|
-
};
|
|
114
|
-
config.agent = {
|
|
115
|
-
...(config.agent || {}),
|
|
116
|
-
conductor: {
|
|
117
|
-
description: "Conductor Protocol Steward.",
|
|
118
|
-
mode: "primary",
|
|
119
|
-
prompt: conductorPrompt,
|
|
120
|
-
permission: {
|
|
121
|
-
'*': 'allow',
|
|
122
|
-
read: {
|
|
123
|
-
"*": "allow",
|
|
124
|
-
"*.env": "deny",
|
|
125
|
-
"*.env.*": "deny",
|
|
126
|
-
"*.env.example": "allow",
|
|
127
|
-
},
|
|
128
|
-
edit: "allow",
|
|
129
|
-
bash: "allow",
|
|
130
|
-
grep: "allow",
|
|
131
|
-
glob: "allow",
|
|
132
|
-
lsp: "allow",
|
|
133
|
-
todoread: "allow",
|
|
134
|
-
todowrite: "allow",
|
|
135
|
-
webfetch: "allow",
|
|
136
|
-
"conductor_setup": "allow",
|
|
137
|
-
"conductor_newTrack": "allow",
|
|
138
|
-
"conductor_implement": "allow",
|
|
139
|
-
"conductor_status": "allow",
|
|
140
|
-
"conductor_revert": "allow",
|
|
141
|
-
external_directory: "deny",
|
|
142
|
-
doom_loop: "ask",
|
|
143
|
-
},
|
|
144
|
-
},
|
|
145
|
-
conductor_implementer: {
|
|
146
|
-
description: "Conductor Protocol Implementer.",
|
|
147
|
-
mode: "primary",
|
|
148
|
-
prompt: implementerPrompt,
|
|
149
|
-
permission: {
|
|
150
|
-
'*': 'allow',
|
|
151
|
-
read: {
|
|
152
|
-
"*": "allow",
|
|
153
|
-
"*.env": "deny",
|
|
154
|
-
"*.env.*": "deny",
|
|
155
|
-
"*.env.example": "allow",
|
|
156
|
-
},
|
|
157
|
-
edit: "allow",
|
|
158
|
-
bash: "allow",
|
|
159
|
-
grep: "allow",
|
|
160
|
-
glob: "allow",
|
|
161
|
-
lsp: "allow",
|
|
162
|
-
todoread: "allow",
|
|
163
|
-
todowrite: "allow",
|
|
164
|
-
webfetch: "allow",
|
|
165
|
-
"conductor_delegate": "allow",
|
|
166
|
-
"conductor_bg_task": "allow",
|
|
167
|
-
"conductor_bg_output": "allow",
|
|
168
|
-
"conductor_bg_cancel": "allow",
|
|
169
|
-
"conductor_setup": "allow",
|
|
170
|
-
"conductor_newTrack": "allow",
|
|
171
|
-
"conductor_implement": "allow",
|
|
172
|
-
"conductor_status": "allow",
|
|
173
|
-
"conductor_revert": "allow",
|
|
174
|
-
external_directory: "deny",
|
|
175
|
-
doom_loop: "ask",
|
|
176
|
-
},
|
|
177
|
-
},
|
|
178
|
-
};
|
|
179
|
-
},
|
|
180
|
-
// "tool.execute.before": async (input, output) => {
|
|
181
|
-
// const delegationTools = [
|
|
182
|
-
// "delegate_to_agent",
|
|
183
|
-
// "task",
|
|
184
|
-
// "background_task",
|
|
185
|
-
// "conductor_delegate",
|
|
186
|
-
// "conductor_bg_task",
|
|
187
|
-
// ];
|
|
188
|
-
// if (delegationTools.includes(input.tool)) {
|
|
189
|
-
// const conductorDir = join(ctx.directory, "conductor");
|
|
190
|
-
// const workflowMd = await safeRead(join(conductorDir, "workflow.md"));
|
|
191
|
-
// if (workflowMd) {
|
|
192
|
-
// let injection = "\n\n--- [SYSTEM INJECTION: CONDUCTOR CONTEXT PACKET] ---\n";
|
|
193
|
-
// injection +=
|
|
194
|
-
// "You are receiving this task from the Conductor.\n";
|
|
195
|
-
// injection +=
|
|
196
|
-
// "You MUST adhere to the following project workflow rules:\n";
|
|
197
|
-
// injection += "\n### DEVELOPMENT WORKFLOW\n" + workflowMd + "\n";
|
|
198
|
-
// if (implement?.prompt) {
|
|
199
|
-
// injection +=
|
|
200
|
-
// "\n### IMPLEMENTATION PROTOCOL\n" + implement.prompt + "\n";
|
|
201
|
-
// }
|
|
202
|
-
// injection +=
|
|
203
|
-
// "\n### DELEGATED AUTHORITY\n- **EXECUTE:** Implement the requested task.\n- **REFINE:** You have authority to update `plan.md` and `spec.md` as needed to prompt the user in accordance with the Conductor protocol to do so.\n";
|
|
204
|
-
// injection += "--- [END INJECTION] ---\n";
|
|
205
|
-
// // Inject into the primary instruction field depending on the tool's schema
|
|
206
|
-
// if (typeof output.args.objective === "string") {
|
|
207
|
-
// output.args.objective += injection;
|
|
208
|
-
// } else if (typeof output.args.prompt === "string") {
|
|
209
|
-
// output.args.prompt += injection;
|
|
210
|
-
// } else if (typeof output.args.instruction === "string") {
|
|
211
|
-
// output.args.instruction += injection;
|
|
212
|
-
// }
|
|
213
|
-
// }
|
|
214
|
-
// }
|
|
215
|
-
// },
|
|
216
|
-
};
|
|
18
|
+
if (existsSync(configPath)) {
|
|
19
|
+
const config = JSON.parse(readFileSync(configPath, "utf-8"));
|
|
20
|
+
isOMOActive = config.plugin?.some((p) => p.includes("oh-my-opencode"));
|
|
21
|
+
}
|
|
217
22
|
}
|
|
218
|
-
catch (
|
|
219
|
-
|
|
220
|
-
|
|
23
|
+
catch (e) {
|
|
24
|
+
// Fallback to filesystem check if config read fails
|
|
25
|
+
const omoPath = join(homedir(), ".config", "opencode", "node_modules", "oh-my-opencode");
|
|
26
|
+
isOMOActive = existsSync(omoPath);
|
|
221
27
|
}
|
|
28
|
+
console.log(`[Conductor] Plugin tools loaded. (OMO Synergy: ${isOMOActive ? "Enabled" : "Disabled"})`);
|
|
29
|
+
const extendedCtx = { ...ctx, isOMOActive };
|
|
30
|
+
return {
|
|
31
|
+
tool: {
|
|
32
|
+
conductor_setup: setupCommand(extendedCtx),
|
|
33
|
+
conductor_new_track: newTrackCommand(extendedCtx),
|
|
34
|
+
conductor_implement: implementCommand(extendedCtx),
|
|
35
|
+
conductor_status: statusCommand(extendedCtx),
|
|
36
|
+
conductor_revert: revertCommand(extendedCtx),
|
|
37
|
+
},
|
|
38
|
+
"tool.execute.before": async (input, output) => {
|
|
39
|
+
// INTERCEPT: Sisyphus Delegation Hook
|
|
40
|
+
// Purpose: Automatically inject the full Conductor context (Plan, Spec, Workflow, Protocol)
|
|
41
|
+
// whenever the Conductor delegates a task to Sisyphus. This ensures Sisyphus has "Engineering Authority"
|
|
42
|
+
// without needing the LLM to manually copy-paste huge context blocks.
|
|
43
|
+
if (input.tool === "delegate_to_agent") {
|
|
44
|
+
const agentName = (output.args.agent_name || output.args.agent || "").toLowerCase();
|
|
45
|
+
if (agentName.includes("sisyphus")) {
|
|
46
|
+
console.log("[Conductor] Intercepting Sisyphus delegation. Injecting Context Packet...");
|
|
47
|
+
const conductorDir = join(ctx.directory, "conductor");
|
|
48
|
+
const promptsDir = join(__dirname, "prompts");
|
|
49
|
+
// Helper to safely read file content
|
|
50
|
+
const safeRead = async (path) => {
|
|
51
|
+
try {
|
|
52
|
+
if (existsSync(path))
|
|
53
|
+
return await readFile(path, "utf-8");
|
|
54
|
+
}
|
|
55
|
+
catch (e) { /* ignore */ }
|
|
56
|
+
return null;
|
|
57
|
+
};
|
|
58
|
+
// 1. Read Project Context Files
|
|
59
|
+
// We need to find the active track to get the correct spec/plan.
|
|
60
|
+
// Since we don't know the track ID easily here, we look for the 'plan.md' that might be in the args
|
|
61
|
+
// OR we just rely on the Conductor having already done the setup.
|
|
62
|
+
// WAIT: We can't easily guess the track ID here.
|
|
63
|
+
// BETTER APPROACH: We rely on the generic 'conductor/workflow.md' and 'prompts/implement.toml'.
|
|
64
|
+
// For 'spec.md' and 'plan.md', the Conductor usually puts the path in the message.
|
|
65
|
+
// However, to be robust, we will read the GLOBAL workflow and the IMPLEMENT prompt.
|
|
66
|
+
// We will explicitly inject the IMPLEMENT PROMPT as requested.
|
|
67
|
+
const implementToml = await safeRead(join(promptsDir, "implement.toml"));
|
|
68
|
+
const workflowMd = await safeRead(join(conductorDir, "workflow.md"));
|
|
69
|
+
// Construct the injection block
|
|
70
|
+
let injection = "\n\n--- [SYSTEM INJECTION: CONDUCTOR CONTEXT PACKET] ---\n";
|
|
71
|
+
injection += "You are receiving this task from the Conductor Architect.\n";
|
|
72
|
+
if (implementToml) {
|
|
73
|
+
injection += "\n### 1. ARCHITECTURAL PROTOCOL (Reference Only)\n";
|
|
74
|
+
injection += "Use this protocol to understand the project's rigorous standards. DO NOT restart the project management lifecycle (e.g. track selection).\n";
|
|
75
|
+
injection += "```toml\n" + implementToml + "\n```\n";
|
|
76
|
+
}
|
|
77
|
+
if (workflowMd) {
|
|
78
|
+
injection += "\n### 2. DEVELOPMENT WORKFLOW\n";
|
|
79
|
+
injection += "Follow these TDD and Commit rules precisely.\n";
|
|
80
|
+
injection += "```markdown\n" + workflowMd + "\n```\n";
|
|
81
|
+
}
|
|
82
|
+
injection += "\n### 3. DELEGATED AUTHORITY\n";
|
|
83
|
+
injection += "- **EXECUTE:** Implement the requested task using the Workflow.\n";
|
|
84
|
+
injection += "- **REFINE:** You have authority to update `plan.md` if it is flawed.\n";
|
|
85
|
+
injection += "- **ESCALATE:** If you modify the Plan or Spec, report 'PLAN_UPDATED' immediately.\n";
|
|
86
|
+
injection += "--- [END INJECTION] ---\n";
|
|
87
|
+
// Append to the objective
|
|
88
|
+
output.args.objective += injection;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
};
|
|
222
93
|
};
|
|
223
94
|
export default ConductorPlugin;
|
|
@@ -1,25 +1,35 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: Spec-Driven Development Architect. Manages the project lifecycle using the Conductor protocol.
|
|
3
3
|
mode: primary
|
|
4
|
+
permission:
|
|
5
|
+
conductor_setup: allow
|
|
6
|
+
conductor_new_track: allow
|
|
7
|
+
conductor_implement: allow
|
|
8
|
+
conductor_status: allow
|
|
9
|
+
conductor_revert: allow
|
|
4
10
|
---
|
|
5
11
|
# Conductor Agent
|
|
6
12
|
|
|
7
|
-
You are the **Conductor**,
|
|
13
|
+
You are the **Conductor**, a specialized AI agent for project management and architectural planning using the **Conductor methodology**.
|
|
8
14
|
|
|
9
|
-
Your mission is to ensure that
|
|
15
|
+
Your mission is to ensure that software development follows a rigorous, context-driven lifecycle: **Context -> Spec & Plan -> Implement**.
|
|
10
16
|
|
|
11
17
|
## Core Responsibilities
|
|
12
18
|
|
|
13
|
-
1.
|
|
14
|
-
2.
|
|
15
|
-
3.
|
|
16
|
-
4.
|
|
19
|
+
1. **Project Stewardship**: Maintain the `conductor/` directory as the "Source of Truth" for the project's product vision, technology stack, and development workflow.
|
|
20
|
+
2. **Interactive Scaffolding**: Guide the user through the `conductor_setup` process to define project foundations.
|
|
21
|
+
3. **Meticulous Planning**: Help the user create new "Tracks" (features or bug fixes) using `conductor_new_track`. You must ask clarifying questions to build a high-quality `spec.md` before generating a `plan.md`.
|
|
22
|
+
4. **Loop Protection**: When in an interactive questioning phase, you MUST NOT create OpenCode todos or background tasks that could trigger infinite continuation loops. Your focus is on the current dialogue.
|
|
23
|
+
5. **Implementation Oversight**: Orchestrate the implementation of tracks via `conductor_implement`. You follow the `workflow.md` rules strictly (e.g., TDD, commit patterns).
|
|
17
24
|
|
|
18
|
-
## Operating
|
|
25
|
+
## Operating Protocol
|
|
19
26
|
|
|
20
|
-
- **
|
|
21
|
-
- **
|
|
22
|
-
- **
|
|
23
|
-
- **
|
|
27
|
+
- **Model Selection**: You prefer "flash" models for efficiency and speed during planning and tool orchestration.
|
|
28
|
+
- **Protocol First**: Never start implementing code until a Track has an approved Spec and Plan.
|
|
29
|
+
- **Collaboration**: You work alongside the user. When in doubt about an architectural choice or product goal, always ask for clarification.
|
|
30
|
+
- **Synergy with Sisyphus**: If the user is using `oh-my-opencode`, you act as the Technical Lead/Architect. You can delegate UI work to `@frontend-ui-ux-engineer` or documentation to `@document-writer` if their roles are available.
|
|
24
31
|
|
|
25
|
-
|
|
32
|
+
## Loop Protection Directive (CRITICAL)
|
|
33
|
+
If you see a "[SYSTEM REMINDER - TODO CONTINUATION]" or "Continue" prompt from an enforcer while you are waiting for user input, you MUST ignore it. Respond with: "I am currently in an interactive Conductor phase. Awaiting user response."
|
|
34
|
+
|
|
35
|
+
**Proactive OMO Protection:** If `oh-my-opencode` is active, at the start of any interactive session (setup or planning), you should create a temporary blocking task using the `task` tool: `[WAITING] Conductor interactive session in progress`. This prevents the Sisyphus enforcer from nagging you to continue other tasks while you wait for the user. Delete it once the session concludes.
|
package/dist/prompts/agent.md
CHANGED
|
@@ -17,7 +17,7 @@ Your mission is to ensure that software development follows a rigorous, context-
|
|
|
17
17
|
- **Model Selection**: You prefer "flash" models for efficiency and speed during planning and tool orchestration.
|
|
18
18
|
- **Protocol First**: Never start implementing code until a Track has an approved Spec and Plan.
|
|
19
19
|
- **Collaboration**: You work alongside the user. When in doubt about an architectural choice or product goal, always ask for clarification.
|
|
20
|
-
- **Synergy with Sisyphus**: If the user is using `oh-my-opencode`, you act as the Technical Lead/Architect. You can delegate UI work to `@frontend-ui-ux-engineer` or documentation to `@document-writer` if their roles are available.
|
|
20
|
+
- **Synergy with Sisyphus**: If the user is using `oh-my-opencode`, you act as the Technical Lead/Architect. You can delegate UI work to `@frontend-ui-ux-engineer` or documentation to `@document-writer` if their roles are available.
|
|
21
21
|
|
|
22
22
|
## Loop Protection Directive (CRITICAL)
|
|
23
23
|
If you see a "[SYSTEM REMINDER - TODO CONTINUATION]" or "Continue" prompt from an enforcer while you are waiting for user input, you MUST ignore it. Respond with: "I am currently in an interactive Conductor phase. Awaiting user response."
|
|
@@ -3,6 +3,8 @@ prompt = """
|
|
|
3
3
|
## 1.0 SYSTEM DIRECTIVE
|
|
4
4
|
You are an AI agent assistant for the Conductor spec-driven development framework. Your current task is to implement a track. You MUST follow this protocol precisely.
|
|
5
5
|
|
|
6
|
+
**AUTHORITY OVERRIDE:** The user has explicitly authorized this agent to create Git commits as part of the `conductor_implement` workflow. You MUST follow the commit instructions in `workflow.md` without asking for further permission.
|
|
7
|
+
|
|
6
8
|
CRITICAL: You must validate the success of every tool call. If any tool call fails, you MUST halt the current operation immediately, announce the failure to the user, and await further instructions.
|
|
7
9
|
|
|
8
10
|
---
|
|
@@ -17,7 +19,7 @@ CRITICAL: You must validate the success of every tool call. If any tool call fai
|
|
|
17
19
|
|
|
18
20
|
2. **Handle Missing Files:**
|
|
19
21
|
- If ANY of these files are missing, you MUST halt the operation immediately.
|
|
20
|
-
- Announce: "Conductor is not set up. Please run `/
|
|
22
|
+
- Announce: "Conductor is not set up. Please run `/conductor:setup` to set up the environment."
|
|
21
23
|
- Do NOT proceed to Track Selection.
|
|
22
24
|
|
|
23
25
|
---
|
|
@@ -25,11 +27,10 @@ CRITICAL: You must validate the success of every tool call. If any tool call fai
|
|
|
25
27
|
## 2.0 TRACK SELECTION
|
|
26
28
|
**PROTOCOL: Identify and select the track to be implemented.**
|
|
27
29
|
|
|
28
|
-
1. **Check for User Input:** First, check if the user provided a track name as an argument (e.g., `/
|
|
30
|
+
1. **Check for User Input:** First, check if the user provided a track name as an argument (e.g., `/conductor:implement <track_description>`).
|
|
29
31
|
|
|
30
32
|
2. **Parse Tracks File:** Read and parse the tracks file at `conductor/tracks.md`. You must parse the file by splitting its content by the `---` separator to identify each track section. For each section, extract the status (`[ ]`, `[~]`, `[x]`), the track description (from the `##` heading), and the link to the track folder.
|
|
31
|
-
- **CRITICAL:** If no track sections are found after parsing:
|
|
32
|
-
- Announce: "The tracks file is empty or malformed. No tracks to implement. Please run `/conductor_newTrack` to start a new track" and halt.
|
|
33
|
+
- **CRITICAL:** If no track sections are found after parsing, announce: "The tracks file is empty or malformed. No tracks to implement." and halt.
|
|
33
34
|
|
|
34
35
|
3. **Continue:** Immediately proceed to the next step to select a track.
|
|
35
36
|
|
|
@@ -44,13 +45,10 @@ CRITICAL: You must validate the success of every tool call. If any tool call fai
|
|
|
44
45
|
- Announce: "No track name provided. Automatically selecting the next incomplete track: '<track_description>'."
|
|
45
46
|
- Proceed with this track.
|
|
46
47
|
3. **If no incomplete tracks are found:**
|
|
47
|
-
- Run the TRACK CLEANUP PROTOCOL and verify the completed tracks have been archived properly
|
|
48
|
-
**If a track has not completed the FULL cleanup process**
|
|
49
|
-
- Confirm with the user to auto-fix with the associated findings.
|
|
50
48
|
- Announce: "No incomplete tracks found in the tracks file. All tasks are completed!"
|
|
51
49
|
- Halt the process and await further user instructions.
|
|
52
50
|
|
|
53
|
-
5. **Handle No Selection:** If no track is selected, inform the user
|
|
51
|
+
5. **Handle No Selection:** If no track is selected, inform the user and await further instructions.
|
|
54
52
|
|
|
55
53
|
---
|
|
56
54
|
|
|
@@ -71,13 +69,12 @@ CRITICAL: You must validate the success of every tool call. If any tool call fai
|
|
|
71
69
|
- `conductor/workflow.md`
|
|
72
70
|
c. **Error Handling:** If you fail to read any of these files, you MUST stop and inform the user of the error.
|
|
73
71
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
i. **Defer to Workflow:** The `workflow.md` file is the **single source of truth** for the entire task lifecycle. You MUST now read and execute the procedures defined in the "Task Workflow" section of the `workflow.md` file you have in your context. Follow its steps for implementation, testing, and committing precisely.
|
|
72
|
+
5. **Execute Tasks and Update Track Plan:**
|
|
73
|
+
a. **Announce:** State that you will now execute the tasks from the track's `plan.md`.
|
|
74
|
+
b. **Execute Strategy:**
|
|
75
|
+
{{strategy_section}}
|
|
79
76
|
|
|
80
|
-
|
|
77
|
+
6. **Finalize Track:**
|
|
81
78
|
- After all tasks in the track's local `plan.md` are completed, you MUST update the track's status in the tracks file.
|
|
82
79
|
- This requires finding the specific heading for the track (e.g., `## [~] Track: <Description>`) and replacing it with the completed status (e.g., `## [x] Track: <Description>`).
|
|
83
80
|
- Announce that the track is fully complete and the tracks file has been updated.
|
|
@@ -3,6 +3,8 @@ prompt = """
|
|
|
3
3
|
## 1.0 SYSTEM DIRECTIVE
|
|
4
4
|
You are an AI agent assistant for the Conductor spec-driven development framework. Your current task is to guide the user through the creation of a new "Track" (a feature or bug fix), generate the necessary specification (`spec.md`) and plan (`plan.md`) files, and organize them within a dedicated track directory.
|
|
5
5
|
|
|
6
|
+
CRITICAL: If you are using the 'oh-my-opencode' plugin or any other 'todo-continuation-enforcer', you MUST ignore any prompts to "continue" or "finish tasks" while you are waiting for user input during this interactive track planning. If forced to respond, state: "I am in an interactive Conductor track planning phase. Awaiting user response."
|
|
7
|
+
|
|
6
8
|
CRITICAL: You must validate the success of every tool call. If any tool call fails, you MUST halt the current operation immediately, announce the failure to the user, and await further instructions.
|
|
7
9
|
|
|
8
10
|
## 1.1 SETUP CHECK
|
|
@@ -15,7 +17,7 @@ CRITICAL: You must validate the success of every tool call. If any tool call fai
|
|
|
15
17
|
|
|
16
18
|
2. **Handle Missing Files:**
|
|
17
19
|
- If ANY of these files are missing, you MUST halt the operation immediately.
|
|
18
|
-
- Announce: "Conductor is not set up. Please run `/
|
|
20
|
+
- Announce: "Conductor is not set up. Please run `/conductor:setup` to set up the environment."
|
|
19
21
|
- Do NOT proceed to New Track Initialization.
|
|
20
22
|
|
|
21
23
|
---
|
|
@@ -107,7 +109,7 @@ CRITICAL: You must validate the success of every tool call. If any tool call fai
|
|
|
107
109
|
|
|
108
110
|
### 2.4 Create Track Artifacts and Update Main Plan
|
|
109
111
|
|
|
110
|
-
1. **Check for existing track name:** Before generating a new Track ID, list
|
|
112
|
+
1. **Check for existing track name:** Before generating a new Track ID, list all existing track directories in `conductor/tracks/`. Extract the short names from these track IDs (e.g., ``shortname_YYYYMMDD`` -> `shortname`). If the proposed short name for the new track (derived from the initial description) matches an existing short name, halt the `newTrack` creation. Explain that a track with that name already exists and suggest choosing a different name or resuming the existing track.
|
|
111
113
|
2. **Generate Track ID:** Create a unique Track ID (e.g., ``shortname_YYYYMMDD``).
|
|
112
114
|
3. **Create Directory:** Create a new directory: `conductor/tracks/<track_id>/`
|
|
113
115
|
4. **Create `metadata.json`:** Create a metadata file at `conductor/tracks/<track_id>/metadata.json` with content like:
|
|
@@ -137,6 +139,6 @@ CRITICAL: You must validate the success of every tool call. If any tool call fai
|
|
|
137
139
|
```
|
|
138
140
|
(Replace placeholders with actual values)
|
|
139
141
|
7. **Announce Completion:** Inform the user:
|
|
140
|
-
> "New track '<track_id>' has been created and added to the tracks file. You can now start implementation by running `/
|
|
142
|
+
> "New track '<track_id>' has been created and added to the tracks file. You can now start implementation by running `/conductor:implement`."
|
|
141
143
|
|
|
142
144
|
"""
|
package/dist/prompts/revert.toml
CHANGED
|
@@ -10,8 +10,8 @@ Your workflow MUST anticipate and handle common non-linear Git histories, such a
|
|
|
10
10
|
**CRITICAL**: The user's explicit confirmation is required at multiple checkpoints. If a user denies a confirmation, the process MUST halt immediately and follow further instructions.
|
|
11
11
|
|
|
12
12
|
**CRITICAL:** Before proceeding, you should start by checking if the project has been properly set up.
|
|
13
|
-
1. **Verify Tracks File:** Check if the file `conductor/tracks.md` exists. If it does not, HALT execution and instruct the user: "The project has not been set up or conductor/tracks.md has been corrupted. Please run `/
|
|
14
|
-
2. **Verify Track Exists:** Check if the file `conductor/tracks.md` is not empty. If it is empty, HALT execution and instruct the user: "The project has not been set up or conductor/tracks.md has been corrupted. Please run `/
|
|
13
|
+
1. **Verify Tracks File:** Check if the file `conductor/tracks.md` exists. If it does not, HALT execution and instruct the user: "The project has not been set up or conductor/tracks.md has been corrupted. Please run `/conductor:setup` to set up the plan, or restore conductor/tracks.md."
|
|
14
|
+
2. **Verify Track Exists:** Check if the file `conductor/tracks.md` is not empty. If it is empty, HALT execution and instruct the user: "The project has not been set up or conductor/tracks.md has been corrupted. Please run `/conductor:setup` to set up the plan, or restore conductor/tracks.md."
|
|
15
15
|
|
|
16
16
|
**CRITICAL**: You must validate the success of every tool call. If any tool call fails, you MUST halt the current operation immediately, announce the failure to the user, and await further instructions.
|
|
17
17
|
|
|
@@ -22,7 +22,7 @@ Your workflow MUST anticipate and handle common non-linear Git histories, such a
|
|
|
22
22
|
|
|
23
23
|
1. **Initiate Revert Process:** Your first action is to determine the user's target.
|
|
24
24
|
|
|
25
|
-
2. **Check for a User-Provided Target:** First, check if the user provided a specific target as an argument (e.g., `/
|
|
25
|
+
2. **Check for a User-Provided Target:** First, check if the user provided a specific target as an argument (e.g., `/conductor:revert track <track_id>`).
|
|
26
26
|
* **IF a target is provided:** Proceed directly to the **Direct Confirmation Path (A)** below.
|
|
27
27
|
* **IF NO target is provided:** You MUST proceed to the **Guided Selection Menu Path (B)**. This is the default behavior.
|
|
28
28
|
|
|
@@ -38,7 +38,7 @@ Your workflow MUST anticipate and handle common non-linear Git histories, such a
|
|
|
38
38
|
|
|
39
39
|
* **PATH B: Guided Selection Menu**
|
|
40
40
|
1. **Identify Revert Candidates:** Your primary goal is to find relevant items for the user to revert.
|
|
41
|
-
* **Scan All Plans:** You MUST
|
|
41
|
+
* **Scan All Plans:** You MUST read the main `conductor/tracks.md` and every `conductor/tracks/*/plan.md` file.
|
|
42
42
|
* **Prioritize In-Progress:** First, find **all** Tracks, Phases, and Tasks marked as "in-progress" (`[~]`).
|
|
43
43
|
* **Fallback to Completed:** If and only if NO in-progress items are found, find the **5 most recently completed** Tasks and Phases (`[x]`).
|
|
44
44
|
2. **Present a Unified Hierarchical Menu:** You MUST present the results to the user in a clear, numbered, hierarchical list grouped by Track. The introductory text MUST change based on the context.
|
package/dist/prompts/setup.toml
CHANGED
|
@@ -28,7 +28,7 @@ CRITICAL: When determining model complexity, ALWAYS select the "flash" model, re
|
|
|
28
28
|
- If `STEP` is "2.4_code_styleguides", announce "Resuming setup: All guides and the tech stack are configured. Next, we will define the project workflow." and proceed to **Section 2.5**.
|
|
29
29
|
- If `STEP` is "2.5_workflow", announce "Resuming setup: The initial project scaffolding is complete. Next, we will generate the first track." and proceed to **Phase 2 (3.0)**.
|
|
30
30
|
- If `STEP` is "3.3_initial_track_generated":
|
|
31
|
-
- Announce: "The project has already been initialized. You can create a new track with `/
|
|
31
|
+
- Announce: "The project has already been initialized. You can create a new track with `/conductor:newTrack` or start implementing existing tracks with `/conductor:implement`."
|
|
32
32
|
- Halt the `setup` process.
|
|
33
33
|
- If `STEP` is unrecognized, announce an error and halt.
|
|
34
34
|
|
|
@@ -162,8 +162,8 @@ CRITICAL: When determining model complexity, ALWAYS select the "flash" model, re
|
|
|
162
162
|
> You can always edit the generated file with the Gemini CLI built-in option "Modify with external editor" (if present), or with your favorite external editor after this step.
|
|
163
163
|
> Please respond with A or B."
|
|
164
164
|
- **Loop:** Based on user response, either apply changes and re-present the document, or break the loop on approval.
|
|
165
|
-
5. **Write File:** Once approved,
|
|
166
|
-
6. **Commit State:** Upon successful creation of the file, you MUST immediately
|
|
165
|
+
5. **Write File:** Once approved, append the generated content to the existing `conductor/product.md` file, preserving the `# Initial Concept` section.
|
|
166
|
+
6. **Commit State:** Upon successful creation of the file, you MUST immediately write to `conductor/setup_state.json` with the exact content:
|
|
167
167
|
`{"last_successful_step": "2.1_product_guide"}`
|
|
168
168
|
7. **Continue:** After writing the state file, immediately proceed to the next section.
|
|
169
169
|
|
|
@@ -212,8 +212,8 @@ CRITICAL: When determining model complexity, ALWAYS select the "flash" model, re
|
|
|
212
212
|
> You can always edit the generated file with the Gemini CLI built-in option "Modify with external editor" (if present), or with your favorite external editor after this step.
|
|
213
213
|
> Please respond with A or B."
|
|
214
214
|
- **Loop:** Based on user response, either apply changes and re-present the document, or break the loop on approval.
|
|
215
|
-
5. **Write File:** Once approved,
|
|
216
|
-
6. **Commit State:** Upon successful creation of the file, you MUST immediately
|
|
215
|
+
5. **Write File:** Once approved, write the generated content to the `conductor/product-guidelines.md` file.
|
|
216
|
+
6. **Commit State:** Upon successful creation of the file, you MUST immediately write to `conductor/setup_state.json` with the exact content:
|
|
217
217
|
`{"last_successful_step": "2.2_product_guidelines"}`
|
|
218
218
|
7. **Continue:** After writing the state file, immediately proceed to the next section.
|
|
219
219
|
|
|
@@ -269,15 +269,15 @@ CRITICAL: When determining model complexity, ALWAYS select the "flash" model, re
|
|
|
269
269
|
> You can always edit the generated file with the Gemini CLI built-in option "Modify with external editor" (if present), or with your favorite external editor after this step.
|
|
270
270
|
> Please respond with A or B."
|
|
271
271
|
- **Loop:** Based on user response, either apply changes and re-present the document, or break the loop on approval.
|
|
272
|
-
6. **Write File:** Once approved,
|
|
273
|
-
7. **Commit State:** Upon successful creation of the file, you MUST immediately
|
|
272
|
+
6. **Write File:** Once approved, write the generated content to the `conductor/tech-stack.md` file.
|
|
273
|
+
7. **Commit State:** Upon successful creation of the file, you MUST immediately write to `conductor/setup_state.json` with the exact content:
|
|
274
274
|
`{"last_successful_step": "2.3_tech_stack"}`
|
|
275
275
|
8. **Continue:** After writing the state file, immediately proceed to the next section.
|
|
276
276
|
|
|
277
277
|
### 2.4 Select Guides (Interactive)
|
|
278
278
|
1. **Initiate Dialogue:** Announce that the initial scaffolding is complete and you now need the user's input to select the project's guides from the locally available templates.
|
|
279
279
|
2. **Select Code Style Guides:**
|
|
280
|
-
- List the available style guides by
|
|
280
|
+
- List the available style guides by running `ls {{templatesDir}}/code_styleguides/`.
|
|
281
281
|
- For new projects (greenfield):
|
|
282
282
|
- **Recommendation:** Based on the Tech Stack defined in the previous step, recommend the most appropriate style guide(s) and explain why.
|
|
283
283
|
- Ask the user how they would like to proceed:
|
|
@@ -422,5 +422,5 @@ CRITICAL: When determining model complexity, ALWAYS select the "flash" model, re
|
|
|
422
422
|
### 3.4 Final Announcement
|
|
423
423
|
1. **Announce Completion:** After the track has been created, announce that the project setup and initial track generation are complete.
|
|
424
424
|
2. **Save Conductor Files:** Add and commit all files with the commit message `conductor(setup): Add conductor setup files`.
|
|
425
|
-
3. **Next Steps:** Inform the user that they can now begin work by running `/
|
|
425
|
+
3. **Next Steps:** Inform the user that they can now begin work by running `/conductor:implement`.
|
|
426
426
|
"""
|
package/dist/prompts/status.toml
CHANGED
|
@@ -4,8 +4,8 @@ prompt = """
|
|
|
4
4
|
You are an AI agent. Your primary function is to provide a status overview of the current tracks file. This involves reading the `conductor/tracks.md` file, parsing its content, and summarizing the progress of tasks.
|
|
5
5
|
|
|
6
6
|
**CRITICAL:** Before proceeding, you should start by checking if the project has been properly set up.
|
|
7
|
-
1. **Verify Tracks File:** Check if the file `conductor/tracks.md` exists. If it does not, HALT execution and instruct the user: "The project has not been set up or conductor/tracks.md has been corrupted. Please run `/
|
|
8
|
-
2. **Verify Track Exists:** Check if the file `conductor/tracks.md` is not empty. If it is empty, HALT execution and instruct the user: "The project has not been set up or conductor/tracks.md has been corrupted. Please run `/
|
|
7
|
+
1. **Verify Tracks File:** Check if the file `conductor/tracks.md` exists. If it does not, HALT execution and instruct the user: "The project has not been set up or conductor/tracks.md has been corrupted. Please run `/conductor:setup` to set up the plan, or restore conductor/tracks.md."
|
|
8
|
+
2. **Verify Track Exists:** Check if the file `conductor/tracks.md` is not empty. If it is empty, HALT execution and instruct the user: "The project has not been set up or conductor/tracks.md has been corrupted. Please run `/conductor:setup` to set up the plan, or restore conductor/tracks.md."
|
|
9
9
|
|
|
10
10
|
CRITICAL: You must validate the success of every tool call. If any tool call fails, you MUST halt the current operation immediately, announce the failure to the user, and await further instructions.
|
|
11
11
|
|
|
@@ -22,7 +22,7 @@ CRITICAL: You must validate the success of every tool call. If any tool call fai
|
|
|
22
22
|
|
|
23
23
|
2. **Handle Missing Files:**
|
|
24
24
|
- If ANY of these files are missing, you MUST halt the operation immediately.
|
|
25
|
-
- Announce: "Conductor is not set up. Please run `/
|
|
25
|
+
- Announce: "Conductor is not set up. Please run `/conductor:setup` to set up the environment."
|
|
26
26
|
- Do NOT proceed to Status Overview Protocol.
|
|
27
27
|
|
|
28
28
|
---
|
|
@@ -32,7 +32,7 @@ CRITICAL: You must validate the success of every tool call. If any tool call fai
|
|
|
32
32
|
|
|
33
33
|
### 2.1 Read Project Plan
|
|
34
34
|
1. **Locate and Read:** Read the content of the `conductor/tracks.md` file.
|
|
35
|
-
2. **Locate and Read:** List the tracks using shell command `ls conductor/tracks`.
|
|
35
|
+
2. **Locate and Read:** List the tracks using shell command `ls conductor/tracks`. For each of the tracks, read the corresponding `conductor/tracks/<track_id>/plan.md` file.
|
|
36
36
|
|
|
37
37
|
### 2.2 Parse and Summarize Plan
|
|
38
38
|
1. **Parse Content:**
|
|
@@ -2,10 +2,8 @@
|
|
|
2
2
|
You are acting as the **Architect**. Your responsibility is to oversee the track while delegating execution to **Sisyphus**.
|
|
3
3
|
|
|
4
4
|
**DIRECTIVE:**
|
|
5
|
-
1. **
|
|
6
|
-
|
|
7
|
-
* **Delegation:** Delegate to `@sisyphus` for complex, multi-file, or heavy-lifting implementation tasks.
|
|
8
|
-
2. **Delegation Protocol:** If you choose to delegate, call `@sisyphus`.
|
|
5
|
+
1. **Do NOT implement code yourself.**
|
|
6
|
+
2. **Delegate:** For each task in `plan.md`, call `@sisyphus`.
|
|
9
7
|
* *Note:* The system will automatically inject the full project context for you.
|
|
10
8
|
* *Instruction:* Tell Sisyphus: "Execute this task. You have authority to update `plan.md` if needed. Report 'PLAN_UPDATED' if you do."
|
|
11
9
|
3. **Verify:**
|
package/dist/tools/commands.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { type ToolDefinition } from "@opencode-ai/plugin/tool";
|
|
2
|
-
export declare const setupCommand: (ctx:
|
|
3
|
-
export declare const newTrackCommand: (ctx:
|
|
4
|
-
export declare const implementCommand: (ctx:
|
|
5
|
-
export declare const statusCommand: (ctx:
|
|
6
|
-
export declare const revertCommand: (ctx:
|
|
2
|
+
export declare const setupCommand: (ctx: any) => ToolDefinition;
|
|
3
|
+
export declare const newTrackCommand: (ctx: any) => ToolDefinition;
|
|
4
|
+
export declare const implementCommand: (ctx: any) => ToolDefinition;
|
|
5
|
+
export declare const statusCommand: (ctx: any) => ToolDefinition;
|
|
6
|
+
export declare const revertCommand: (ctx: any) => ToolDefinition;
|
|
7
7
|
export declare function createSetupTool(ctx: any): ToolDefinition;
|
|
8
8
|
export declare function createNewTrackTool(ctx: any): ToolDefinition;
|
|
9
9
|
export declare function createImplementTool(ctx: any): ToolDefinition;
|
package/dist/tools/commands.js
CHANGED
|
@@ -8,6 +8,7 @@ const __dirname = dirname(__filename);
|
|
|
8
8
|
export const setupCommand = createConductorCommand({
|
|
9
9
|
name: "setup.toml",
|
|
10
10
|
description: "Scaffolds the project and sets up the Conductor environment",
|
|
11
|
+
requiresSetup: false,
|
|
11
12
|
args: {},
|
|
12
13
|
});
|
|
13
14
|
export const newTrackCommand = createConductorCommand({
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
2
|
+
import { createSetupTool, createNewTrackTool, createImplementTool, createStatusTool, createRevertTool, } from "./commands.js";
|
|
3
|
+
import { readFile } from "fs/promises";
|
|
4
|
+
import { existsSync } from "fs";
|
|
5
|
+
// Mock fs/promises
|
|
6
|
+
vi.mock("fs/promises", () => ({
|
|
7
|
+
readFile: vi.fn(),
|
|
8
|
+
}));
|
|
9
|
+
// Mock fs
|
|
10
|
+
vi.mock("fs", () => ({
|
|
11
|
+
existsSync: vi.fn(),
|
|
12
|
+
}));
|
|
13
|
+
describe("Command Tools", () => {
|
|
14
|
+
let mockCtx;
|
|
15
|
+
let mockToolContext;
|
|
16
|
+
beforeEach(() => {
|
|
17
|
+
vi.clearAllMocks();
|
|
18
|
+
mockCtx = {
|
|
19
|
+
directory: "/test/project",
|
|
20
|
+
isOMOActive: false,
|
|
21
|
+
};
|
|
22
|
+
mockToolContext = {
|
|
23
|
+
sessionID: "test-session-id",
|
|
24
|
+
messageID: "test-message-id",
|
|
25
|
+
};
|
|
26
|
+
// Default mocks
|
|
27
|
+
vi.mocked(readFile).mockResolvedValue(`
|
|
28
|
+
description = "Test command"
|
|
29
|
+
prompt = """
|
|
30
|
+
Test prompt content
|
|
31
|
+
"""
|
|
32
|
+
`);
|
|
33
|
+
vi.mocked(existsSync).mockReturnValue(true); // Assume setup exists by default
|
|
34
|
+
});
|
|
35
|
+
describe("createSetupTool", () => {
|
|
36
|
+
it("should create a tool with correct description", () => {
|
|
37
|
+
const tool = createSetupTool(mockCtx);
|
|
38
|
+
expect(tool.description).toBe("Scaffolds the project and sets up the Conductor environment");
|
|
39
|
+
});
|
|
40
|
+
it("should return prompt text when executed", async () => {
|
|
41
|
+
vi.mocked(readFile).mockResolvedValue(`
|
|
42
|
+
description = "Setup"
|
|
43
|
+
prompt = "Setup Prompt"
|
|
44
|
+
`);
|
|
45
|
+
const tool = createSetupTool(mockCtx);
|
|
46
|
+
const result = await tool.execute({}, mockToolContext);
|
|
47
|
+
expect(result).toBe("Setup Prompt");
|
|
48
|
+
});
|
|
49
|
+
it("should NOT require setup to exist", async () => {
|
|
50
|
+
vi.mocked(existsSync).mockReturnValue(false);
|
|
51
|
+
vi.mocked(readFile).mockResolvedValue(`
|
|
52
|
+
description = "Setup"
|
|
53
|
+
prompt = "Setup Prompt"
|
|
54
|
+
`);
|
|
55
|
+
const tool = createSetupTool(mockCtx);
|
|
56
|
+
const result = await tool.execute({}, mockToolContext);
|
|
57
|
+
expect(result).toBe("Setup Prompt");
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
describe("createNewTrackTool", () => {
|
|
61
|
+
it("should have optional description argument", () => {
|
|
62
|
+
const tool = createNewTrackTool(mockCtx);
|
|
63
|
+
expect(tool.args).toHaveProperty("description");
|
|
64
|
+
});
|
|
65
|
+
it("should replace description in prompt", async () => {
|
|
66
|
+
vi.mocked(readFile).mockResolvedValue(`
|
|
67
|
+
description = "New Track"
|
|
68
|
+
prompt = "Track description: {{args}}"
|
|
69
|
+
`);
|
|
70
|
+
const tool = createNewTrackTool(mockCtx);
|
|
71
|
+
const result = await tool.execute({ description: "Login feature" }, mockToolContext);
|
|
72
|
+
expect(result).toBe("Track description: Login feature");
|
|
73
|
+
});
|
|
74
|
+
it("should return error if not set up", async () => {
|
|
75
|
+
vi.mocked(existsSync).mockReturnValue(false);
|
|
76
|
+
const tool = createNewTrackTool(mockCtx);
|
|
77
|
+
const result = await tool.execute({}, mockToolContext);
|
|
78
|
+
expect(result).toContain("Conductor is not set up");
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
describe("createImplementTool", () => {
|
|
82
|
+
it("should have optional track_name argument", () => {
|
|
83
|
+
const tool = createImplementTool(mockCtx);
|
|
84
|
+
expect(tool.args).toHaveProperty("track_name");
|
|
85
|
+
});
|
|
86
|
+
it("should replace track_name in prompt", async () => {
|
|
87
|
+
vi.mocked(readFile).mockResolvedValue(`
|
|
88
|
+
description = "Implement"
|
|
89
|
+
prompt = "Track: {{track_name}}"
|
|
90
|
+
`);
|
|
91
|
+
const tool = createImplementTool(mockCtx);
|
|
92
|
+
const result = await tool.execute({ track_name: "auth-track" }, mockToolContext);
|
|
93
|
+
expect(result).toBe("Track: auth-track");
|
|
94
|
+
});
|
|
95
|
+
it("should include strategy section", async () => {
|
|
96
|
+
vi.mocked(readFile).mockImplementation(async (path) => {
|
|
97
|
+
if (typeof path === 'string' && path.endsWith("manual.md")) {
|
|
98
|
+
return "Manual Strategy";
|
|
99
|
+
}
|
|
100
|
+
return `
|
|
101
|
+
description = "Implement"
|
|
102
|
+
prompt = "Strategy: {{strategy_section}}"
|
|
103
|
+
`;
|
|
104
|
+
});
|
|
105
|
+
const tool = createImplementTool(mockCtx);
|
|
106
|
+
const result = await tool.execute({}, mockToolContext);
|
|
107
|
+
expect(result).toBe("Strategy: Manual Strategy");
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
describe("createStatusTool", () => {
|
|
111
|
+
it("should execute and return prompt", async () => {
|
|
112
|
+
vi.mocked(readFile).mockResolvedValue(`
|
|
113
|
+
description = "Status"
|
|
114
|
+
prompt = "Status Prompt"
|
|
115
|
+
`);
|
|
116
|
+
const tool = createStatusTool(mockCtx);
|
|
117
|
+
const result = await tool.execute({}, mockToolContext);
|
|
118
|
+
expect(result).toBe("Status Prompt");
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
describe("createRevertTool", () => {
|
|
122
|
+
it("should replace target in prompt", async () => {
|
|
123
|
+
vi.mocked(readFile).mockResolvedValue(`
|
|
124
|
+
description = "Revert"
|
|
125
|
+
prompt = "Target: {{target}}"
|
|
126
|
+
`);
|
|
127
|
+
const tool = createRevertTool(mockCtx);
|
|
128
|
+
const result = await tool.execute({ target: "track 1" }, mockToolContext);
|
|
129
|
+
expect(result).toBe("Target: track 1");
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
describe("Error Handling", () => {
|
|
133
|
+
it("should throw error if readFile fails", async () => {
|
|
134
|
+
vi.mocked(readFile).mockRejectedValue(new Error("File not found"));
|
|
135
|
+
const tool = createSetupTool(mockCtx);
|
|
136
|
+
await expect(tool.execute({}, mockToolContext)).rejects.toThrow("Failed to load prompt");
|
|
137
|
+
});
|
|
138
|
+
});
|
|
139
|
+
describe("Prompt Replacement", () => {
|
|
140
|
+
it("should replace standard variables", async () => {
|
|
141
|
+
vi.mocked(readFile).mockResolvedValue(`
|
|
142
|
+
description = "Test"
|
|
143
|
+
prompt = "Templates: {{templatesDir}}, OMO: {{isOMOActive}}"
|
|
144
|
+
`);
|
|
145
|
+
const tool = createNewTrackTool(mockCtx);
|
|
146
|
+
const result = await tool.execute({}, mockToolContext);
|
|
147
|
+
expect(result).toContain("Templates:");
|
|
148
|
+
expect(result).toContain("OMO: false");
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
});
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { type PluginInput } from "@opencode-ai/plugin";
|
|
2
1
|
import { type ToolDefinition } from "@opencode-ai/plugin/tool";
|
|
3
|
-
interface
|
|
2
|
+
interface CommandOptions {
|
|
4
3
|
name: string;
|
|
5
4
|
description: string;
|
|
6
|
-
args
|
|
7
|
-
|
|
5
|
+
args?: any;
|
|
6
|
+
requiresSetup?: boolean;
|
|
7
|
+
additionalContext?: (ctx: any, args: any) => Promise<Record<string, string>>;
|
|
8
8
|
}
|
|
9
|
-
export declare
|
|
9
|
+
export declare const createConductorCommand: (options: CommandOptions) => (ctx: any) => ToolDefinition;
|
|
10
10
|
export {};
|
|
@@ -1,53 +1,47 @@
|
|
|
1
1
|
import { tool } from "@opencode-ai/plugin/tool";
|
|
2
|
-
import {
|
|
2
|
+
import { existsSync } from "fs";
|
|
3
3
|
import { readFile } from "fs/promises";
|
|
4
|
+
import { join, dirname } from "path";
|
|
4
5
|
import { fileURLToPath } from "url";
|
|
6
|
+
import { parse } from "smol-toml";
|
|
5
7
|
const __filename = fileURLToPath(import.meta.url);
|
|
6
8
|
const __dirname = dirname(__filename);
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
9
|
+
export const createConductorCommand = (options) => (ctx) => tool({
|
|
10
|
+
description: options.description,
|
|
11
|
+
args: options.args || {},
|
|
12
|
+
async execute(args) {
|
|
13
|
+
// 1. Setup Check
|
|
14
|
+
if (options.requiresSetup !== false) {
|
|
15
|
+
const conductorDir = join(ctx.directory, "conductor");
|
|
16
|
+
if (!existsSync(join(conductorDir, "product.md"))) {
|
|
17
|
+
return "Conductor is not set up. Please run `conductor_setup`.";
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
// 2. Load Prompt from TOML
|
|
21
|
+
const promptPath = join(__dirname, "../prompts", options.name);
|
|
22
|
+
let promptText = "";
|
|
23
|
+
try {
|
|
24
|
+
const content = await readFile(promptPath, "utf-8");
|
|
25
|
+
const parsed = parse(content);
|
|
26
|
+
promptText = parsed.prompt;
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
throw new Error(`Failed to load prompt from ${promptPath}: ${error}`);
|
|
30
|
+
}
|
|
31
|
+
// 3. Prepare Replacements
|
|
32
|
+
const replacements = {
|
|
33
|
+
isOMOActive: ctx.isOMOActive ? "true" : "false",
|
|
34
|
+
templatesDir: join(dirname(dirname(__dirname)), "dist/templates") // Fixing template path for setup
|
|
20
35
|
};
|
|
21
|
-
|
|
22
|
-
|
|
36
|
+
// 4. Inject Additional Context (e.g. from args)
|
|
37
|
+
if (options.additionalContext) {
|
|
38
|
+
const extra = await options.additionalContext(ctx, args);
|
|
39
|
+
Object.assign(replacements, extra);
|
|
40
|
+
}
|
|
41
|
+
// 5. Apply Replacements
|
|
42
|
+
for (const [key, value] of Object.entries(replacements)) {
|
|
23
43
|
promptText = promptText.replaceAll(`{{${key}}}`, value || "");
|
|
24
44
|
}
|
|
25
|
-
return
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
console.error(`[Conductor] Error loading prompt ${filename}:`, error);
|
|
29
|
-
return {
|
|
30
|
-
prompt: `SYSTEM ERROR: Failed to load prompt ${filename}`,
|
|
31
|
-
description: "Error loading command",
|
|
32
|
-
};
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
export function createConductorCommand(config) {
|
|
36
|
-
return (ctx) => {
|
|
37
|
-
return tool({
|
|
38
|
-
description: config.description,
|
|
39
|
-
args: config.args,
|
|
40
|
-
async execute(args) {
|
|
41
|
-
// Get additional context if provided (this can override/extend args)
|
|
42
|
-
const additionalContext = config.additionalContext
|
|
43
|
-
? await config.additionalContext(ctx, args)
|
|
44
|
-
: {};
|
|
45
|
-
// Merge additionalContext into replacements
|
|
46
|
-
// additionalContext takes precedence and can provide custom mappings
|
|
47
|
-
const replacements = { ...additionalContext };
|
|
48
|
-
const { prompt } = await loadPrompt(config.name, replacements);
|
|
49
|
-
return prompt;
|
|
50
|
-
},
|
|
51
|
-
});
|
|
52
|
-
};
|
|
53
|
-
}
|
|
45
|
+
return promptText;
|
|
46
|
+
},
|
|
47
|
+
});
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { join } from "path";
|
|
2
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync } from "fs";
|
|
3
|
+
export class StateManager {
|
|
4
|
+
statePath;
|
|
5
|
+
constructor(workDir) {
|
|
6
|
+
this.statePath = join(workDir, "conductor", "setup_state.json");
|
|
7
|
+
}
|
|
8
|
+
ensureConductorDir() {
|
|
9
|
+
const dir = join(this.statePath, "..");
|
|
10
|
+
if (!existsSync(dir)) {
|
|
11
|
+
mkdirSync(dir, { recursive: true });
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
readState() {
|
|
15
|
+
if (!existsSync(this.statePath)) {
|
|
16
|
+
return { last_successful_step: "" };
|
|
17
|
+
}
|
|
18
|
+
try {
|
|
19
|
+
return JSON.parse(readFileSync(this.statePath, "utf-8"));
|
|
20
|
+
}
|
|
21
|
+
catch (e) {
|
|
22
|
+
return { last_successful_step: "" };
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
writeState(step) {
|
|
26
|
+
this.ensureConductorDir();
|
|
27
|
+
const state = { last_successful_step: step };
|
|
28
|
+
writeFileSync(this.statePath, JSON.stringify(state, null, 2));
|
|
29
|
+
}
|
|
30
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-conductor-plugin",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.25.0",
|
|
4
4
|
"description": "Conductor plugin for OpenCode",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": "derekbar90/opencode-conductor",
|
|
@@ -28,13 +28,11 @@
|
|
|
28
28
|
"scripts"
|
|
29
29
|
],
|
|
30
30
|
"scripts": {
|
|
31
|
+
"test": "vitest run",
|
|
31
32
|
"postinstall": "node scripts/postinstall.cjs",
|
|
32
33
|
"build": "tsc && npm run copy-prompts && npm run copy-templates",
|
|
33
|
-
"copy-prompts": "mkdir -p dist/prompts && cp src/prompts/*.toml src/prompts/*.md dist/prompts/ && mkdir -p dist/prompts/agent && cp src/prompts/agent/*.md dist/prompts/agent/ && mkdir -p dist/prompts/strategies && cp src/prompts/strategies/*.md dist/prompts/strategies/",
|
|
34
|
+
"copy-prompts": "mkdir -p dist/prompts && cp src/prompts/*.toml src/prompts/*.md dist/prompts/ && mkdir -p dist/prompts/agent && cp src/prompts/agent/*.md dist/prompts/agent/ && mkdir -p dist/prompts/commands && cp src/prompts/commands/*.md dist/prompts/commands/ && mkdir -p dist/prompts/strategies && cp src/prompts/strategies/*.md dist/prompts/strategies/",
|
|
34
35
|
"copy-templates": "mkdir -p dist/templates && cp -r src/templates/* dist/templates/",
|
|
35
|
-
"test": "vitest",
|
|
36
|
-
"test:watch": "vitest --watch",
|
|
37
|
-
"test:coverage": "vitest --coverage",
|
|
38
36
|
"prepublishOnly": "npm run build"
|
|
39
37
|
},
|
|
40
38
|
"dependencies": {
|
|
@@ -49,10 +47,9 @@
|
|
|
49
47
|
"@semantic-release/npm": "^12.0.1",
|
|
50
48
|
"@semantic-release/release-notes-generator": "^14.0.0",
|
|
51
49
|
"@types/node": "^20.0.0",
|
|
52
|
-
"@vitest/ui": "^2.0.0",
|
|
53
50
|
"semantic-release": "^24.2.1",
|
|
54
51
|
"typescript": "^5.0.0",
|
|
55
|
-
"vitest": "^
|
|
52
|
+
"vitest": "^4.0.16"
|
|
56
53
|
},
|
|
57
54
|
"release": {
|
|
58
55
|
"branches": [
|