opencode-conductor-plugin 1.23.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 +10 -6
- package/dist/tools/commands.js +63 -80
- package/dist/tools/commands.test.d.ts +1 -0
- package/dist/tools/commands.test.js +151 -0
- package/dist/utils/commandFactory.d.ts +10 -0
- package/dist/utils/commandFactory.js +47 -0
- 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.
|