@doingdev/opencode-claude-manager-plugin 0.1.42 → 0.1.43

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.
@@ -21,6 +21,7 @@ export declare class PersistentManager {
21
21
  model?: string;
22
22
  effort?: 'low' | 'medium' | 'high' | 'max';
23
23
  mode?: 'plan' | 'free';
24
+ sessionSystemPrompt?: string;
24
25
  abortSignal?: AbortSignal;
25
26
  }, onEvent?: ClaudeSessionEventHandler): Promise<{
26
27
  sessionId: string | undefined;
@@ -66,7 +67,7 @@ export declare class PersistentManager {
66
67
  /**
67
68
  * Clear the active session. Next send creates a fresh one.
68
69
  */
69
- clearSession(cwd: string): Promise<string | null>;
70
+ clearSession(): Promise<string | null>;
70
71
  /**
71
72
  * Compact the current session to free context.
72
73
  */
@@ -85,7 +86,7 @@ export declare class PersistentManager {
85
86
  /**
86
87
  * Try to restore session state from disk on startup.
87
88
  */
88
- tryRestore(cwd: string): Promise<boolean>;
89
+ tryRestore(): Promise<boolean>;
89
90
  listRuns(cwd: string): Promise<PersistentRunRecord[]>;
90
91
  getRun(cwd: string, runId: string): Promise<PersistentRunRecord | null>;
91
92
  }
@@ -17,7 +17,7 @@ export class PersistentManager {
17
17
  * Creates a new session if none exists.
18
18
  */
19
19
  async sendMessage(cwd, message, options, onEvent) {
20
- const result = await this.sessionController.sendMessage(cwd, message, options, onEvent);
20
+ const result = await this.sessionController.sendMessage(message, options, onEvent);
21
21
  if (result.sessionId && result.events.length > 0) {
22
22
  await this.transcriptStore.appendEvents(cwd, result.sessionId, result.events);
23
23
  }
@@ -71,14 +71,14 @@ export class PersistentManager {
71
71
  /**
72
72
  * Clear the active session. Next send creates a fresh one.
73
73
  */
74
- async clearSession(cwd) {
75
- return this.sessionController.clearSession(cwd);
74
+ async clearSession() {
75
+ return this.sessionController.clearSession();
76
76
  }
77
77
  /**
78
78
  * Compact the current session to free context.
79
79
  */
80
80
  async compactSession(cwd, onEvent) {
81
- const result = await this.sessionController.compactSession(cwd, onEvent);
81
+ const result = await this.sessionController.compactSession(onEvent);
82
82
  if (result.sessionId && result.events.length > 0) {
83
83
  await this.transcriptStore.appendEvents(cwd, result.sessionId, result.events);
84
84
  }
@@ -120,7 +120,7 @@ export class PersistentManager {
120
120
  await this.stateStore.saveRun(runRecord);
121
121
  await onProgress?.(runRecord);
122
122
  try {
123
- const result = await this.sessionController.sendMessage(cwd, task, options, async (event) => {
123
+ const result = await this.sessionController.sendMessage(task, options, async (event) => {
124
124
  // Update run record with progress events
125
125
  const currentRun = await this.stateStore.getRun(cwd, runId);
126
126
  if (currentRun) {
@@ -170,8 +170,8 @@ export class PersistentManager {
170
170
  /**
171
171
  * Try to restore session state from disk on startup.
172
172
  */
173
- async tryRestore(cwd) {
174
- return this.sessionController.tryRestore(cwd);
173
+ async tryRestore() {
174
+ return this.sessionController.tryRestore();
175
175
  }
176
176
  listRuns(cwd) {
177
177
  return this.stateStore.listRuns(cwd);
@@ -5,9 +5,11 @@ export declare class SessionController {
5
5
  private readonly sdkAdapter;
6
6
  private readonly contextTracker;
7
7
  private readonly sessionPrompt;
8
+ private readonly wrapperType;
9
+ private readonly worktree;
8
10
  private readonly modePrefixes;
9
11
  private activeSessionId;
10
- constructor(sdkAdapter: ClaudeAgentSdkAdapter, contextTracker: ContextTracker, sessionPrompt: string, modePrefixes?: {
12
+ constructor(sdkAdapter: ClaudeAgentSdkAdapter, contextTracker: ContextTracker, sessionPrompt: string | undefined, wrapperType: string, worktree: string, modePrefixes?: {
11
13
  plan: string;
12
14
  free: string;
13
15
  });
@@ -17,20 +19,21 @@ export declare class SessionController {
17
19
  * Send a message to the persistent session. Creates one if none exists.
18
20
  * Returns the session result including usage data.
19
21
  */
20
- sendMessage(cwd: string, message: string, options?: {
22
+ sendMessage(message: string, options?: {
21
23
  model?: string;
22
24
  effort?: 'low' | 'medium' | 'high' | 'max';
23
25
  mode?: SessionMode;
26
+ sessionSystemPrompt?: string;
24
27
  abortSignal?: AbortSignal;
25
28
  }, onEvent?: ClaudeSessionEventHandler): Promise<ClaudeSessionRunResult>;
26
29
  /**
27
30
  * Send /compact to the current session to compress context.
28
31
  */
29
- compactSession(cwd: string, onEvent?: ClaudeSessionEventHandler): Promise<ClaudeSessionRunResult>;
32
+ compactSession(onEvent?: ClaudeSessionEventHandler): Promise<ClaudeSessionRunResult>;
30
33
  /**
31
34
  * Clear the current session. The next sendMessage will create a fresh one.
32
35
  */
33
- clearSession(cwd: string): Promise<string | null>;
36
+ clearSession(): Promise<string | null>;
34
37
  /**
35
38
  * Get current context tracking snapshot.
36
39
  */
@@ -38,7 +41,7 @@ export declare class SessionController {
38
41
  /**
39
42
  * Try to restore active session from persisted state on startup.
40
43
  */
41
- tryRestore(cwd: string): Promise<boolean>;
44
+ tryRestore(): Promise<boolean>;
42
45
  private persistActiveSession;
43
46
  private removeActiveSession;
44
47
  }
@@ -1,19 +1,25 @@
1
1
  import { mkdir, readFile, writeFile } from 'node:fs/promises';
2
- import { dirname, join } from 'node:path';
3
- const ACTIVE_SESSION_FILE = '.claude-manager/active-session.json';
2
+ import { dirname } from 'node:path';
3
+ function activeSessionFile(_wrapperType) {
4
+ return `.claude-manager/active-session.json`;
5
+ }
4
6
  export class SessionController {
5
7
  sdkAdapter;
6
8
  contextTracker;
7
9
  sessionPrompt;
10
+ wrapperType;
11
+ worktree;
8
12
  modePrefixes;
9
13
  activeSessionId = null;
10
- constructor(sdkAdapter, contextTracker, sessionPrompt, modePrefixes = {
14
+ constructor(sdkAdapter, contextTracker, sessionPrompt, wrapperType, worktree, modePrefixes = {
11
15
  plan: '',
12
16
  free: '',
13
17
  }) {
14
18
  this.sdkAdapter = sdkAdapter;
15
19
  this.contextTracker = contextTracker;
16
20
  this.sessionPrompt = sessionPrompt;
21
+ this.wrapperType = wrapperType;
22
+ this.worktree = worktree;
17
23
  this.modePrefixes = modePrefixes;
18
24
  }
19
25
  get isActive() {
@@ -26,12 +32,12 @@ export class SessionController {
26
32
  * Send a message to the persistent session. Creates one if none exists.
27
33
  * Returns the session result including usage data.
28
34
  */
29
- async sendMessage(cwd, message, options, onEvent) {
35
+ async sendMessage(message, options, onEvent) {
30
36
  const mode = options?.mode ?? 'free';
31
37
  const prefix = this.modePrefixes[mode];
32
38
  const prompt = prefix ? `${prefix}\n\n${message}` : message;
33
39
  const input = {
34
- cwd,
40
+ cwd: this.worktree,
35
41
  prompt,
36
42
  persistSession: true,
37
43
  permissionMode: mode === 'plan' ? 'plan' : 'acceptEdits',
@@ -46,8 +52,8 @@ export class SessionController {
46
52
  input.resumeSessionId = this.activeSessionId;
47
53
  }
48
54
  else {
49
- // New session — use the base session prompt (project context is in the wrapper)
50
- input.systemPrompt = this.sessionPrompt;
55
+ // New session — prefer dynamically constructed prompt from wrapper, fall back to static default
56
+ input.systemPrompt = options?.sessionSystemPrompt ?? this.sessionPrompt;
51
57
  input.model ??= 'claude-opus-4-6';
52
58
  input.effort ??= 'high';
53
59
  }
@@ -66,28 +72,28 @@ export class SessionController {
66
72
  contextWindowSize: result.contextWindowSize,
67
73
  });
68
74
  // Persist active session state
69
- await this.persistActiveSession(cwd);
75
+ await this.persistActiveSession();
70
76
  return result;
71
77
  }
72
78
  /**
73
79
  * Send /compact to the current session to compress context.
74
80
  */
75
- async compactSession(cwd, onEvent) {
81
+ async compactSession(onEvent) {
76
82
  if (!this.activeSessionId) {
77
83
  throw new Error('No active session to compact');
78
84
  }
79
- const result = await this.sendMessage(cwd, '/compact', undefined, onEvent);
85
+ const result = await this.sendMessage('/compact', undefined, onEvent);
80
86
  this.contextTracker.recordCompaction();
81
87
  return result;
82
88
  }
83
89
  /**
84
90
  * Clear the current session. The next sendMessage will create a fresh one.
85
91
  */
86
- async clearSession(cwd) {
92
+ async clearSession() {
87
93
  const clearedId = this.activeSessionId;
88
94
  this.activeSessionId = null;
89
95
  this.contextTracker.reset();
90
- await this.removeActiveSession(cwd);
96
+ await this.removeActiveSession();
91
97
  return clearedId;
92
98
  }
93
99
  /**
@@ -99,12 +105,12 @@ export class SessionController {
99
105
  /**
100
106
  * Try to restore active session from persisted state on startup.
101
107
  */
102
- async tryRestore(cwd) {
103
- const filePath = join(cwd, ACTIVE_SESSION_FILE);
108
+ async tryRestore() {
109
+ const filePath = activeSessionFile(this.wrapperType);
104
110
  try {
105
111
  const raw = await readFile(filePath, 'utf-8');
106
112
  const state = JSON.parse(raw);
107
- if (state.sessionId && state.cwd === cwd) {
113
+ if (state.sessionId) {
108
114
  this.activeSessionId = state.sessionId;
109
115
  this.contextTracker.restore(state);
110
116
  return true;
@@ -115,14 +121,13 @@ export class SessionController {
115
121
  }
116
122
  return false;
117
123
  }
118
- async persistActiveSession(cwd) {
124
+ async persistActiveSession() {
119
125
  if (!this.activeSessionId) {
120
126
  return;
121
127
  }
122
128
  const snap = this.contextTracker.snapshot();
123
129
  const state = {
124
130
  sessionId: this.activeSessionId,
125
- cwd,
126
131
  startedAt: new Date().toISOString(),
127
132
  totalTurns: snap.totalTurns,
128
133
  totalCostUsd: snap.totalCostUsd,
@@ -130,12 +135,12 @@ export class SessionController {
130
135
  contextWindowSize: snap.contextWindowSize,
131
136
  latestInputTokens: snap.latestInputTokens,
132
137
  };
133
- const filePath = join(cwd, ACTIVE_SESSION_FILE);
138
+ const filePath = activeSessionFile(this.wrapperType);
134
139
  await mkdir(dirname(filePath), { recursive: true });
135
140
  await writeFile(filePath, JSON.stringify(state, null, 2));
136
141
  }
137
- async removeActiveSession(cwd) {
138
- const filePath = join(cwd, ACTIVE_SESSION_FILE);
142
+ async removeActiveSession() {
143
+ const filePath = activeSessionFile(this.wrapperType);
139
144
  try {
140
145
  const { unlink } = await import('node:fs/promises');
141
146
  await unlink(filePath);
@@ -1,15 +1,15 @@
1
1
  /**
2
2
  * Agent hierarchy configuration for the CTO + Engineer Wrapper architecture.
3
3
  *
4
- * CTO (cto) — pure orchestrator, spawns engineers, reviews diffs, commits
5
- * Engineer Plan (engineer_plan) — manages a Claude Code session for read-only investigation
6
- * Engineer Build (engineer_build) — manages a Claude Code session for implementation
7
- * Claude Code session — the underlying AI session (prompt only, no OpenCode agent)
4
+ * CTO (cto) — pure orchestrator, spawns engineers, reviews diffs, commits
5
+ * Engineer Explore (engineer_explore) — manages a Claude Code session for read-only investigation
6
+ * Engineer Implement (engineer_implement) — manages a Claude Code session for implementation
7
+ * Claude Code session — the underlying AI session (prompt only, no OpenCode agent)
8
8
  */
9
9
  import type { ManagerPromptRegistry } from '../types/contracts.js';
10
10
  export declare const AGENT_CTO = "cto";
11
- export declare const AGENT_ENGINEER_PLAN = "engineer_plan";
12
- export declare const AGENT_ENGINEER_BUILD = "engineer_build";
11
+ export declare const AGENT_ENGINEER_EXPLORE = "engineer_explore";
12
+ export declare const AGENT_ENGINEER_IMPLEMENT = "engineer_implement";
13
13
  /** All restricted tool IDs (union of all domain groups) */
14
14
  export declare const ALL_RESTRICTED_TOOL_IDS: readonly ["explore", "implement", "compact_context", "clear_session", "session_health", "list_transcripts", "list_history", "git_diff", "git_commit", "git_reset", "git_status", "git_log", "approval_policy", "approval_decisions", "approval_update"];
15
15
  type ToolPermission = 'allow' | 'ask' | 'deny';
@@ -41,14 +41,14 @@ export declare function buildCtoAgentConfig(prompts: ManagerPromptRegistry): {
41
41
  permission: AgentPermission;
42
42
  prompt: string;
43
43
  };
44
- export declare function buildEngineerPlanAgentConfig(prompts: ManagerPromptRegistry): {
44
+ export declare function buildEngineerExploreAgentConfig(prompts: ManagerPromptRegistry): {
45
45
  description: string;
46
46
  mode: "subagent";
47
47
  color: string;
48
48
  permission: AgentPermission;
49
49
  prompt: string;
50
50
  };
51
- export declare function buildEngineerBuildAgentConfig(prompts: ManagerPromptRegistry): {
51
+ export declare function buildEngineerImplementAgentConfig(prompts: ManagerPromptRegistry): {
52
52
  description: string;
53
53
  mode: "subagent";
54
54
  color: string;
@@ -1,17 +1,17 @@
1
1
  /**
2
2
  * Agent hierarchy configuration for the CTO + Engineer Wrapper architecture.
3
3
  *
4
- * CTO (cto) — pure orchestrator, spawns engineers, reviews diffs, commits
5
- * Engineer Plan (engineer_plan) — manages a Claude Code session for read-only investigation
6
- * Engineer Build (engineer_build) — manages a Claude Code session for implementation
7
- * Claude Code session — the underlying AI session (prompt only, no OpenCode agent)
4
+ * CTO (cto) — pure orchestrator, spawns engineers, reviews diffs, commits
5
+ * Engineer Explore (engineer_explore) — manages a Claude Code session for read-only investigation
6
+ * Engineer Implement (engineer_implement) — manages a Claude Code session for implementation
7
+ * Claude Code session — the underlying AI session (prompt only, no OpenCode agent)
8
8
  */
9
9
  // ---------------------------------------------------------------------------
10
10
  // Agent names
11
11
  // ---------------------------------------------------------------------------
12
12
  export const AGENT_CTO = 'cto';
13
- export const AGENT_ENGINEER_PLAN = 'engineer_plan';
14
- export const AGENT_ENGINEER_BUILD = 'engineer_build';
13
+ export const AGENT_ENGINEER_EXPLORE = 'engineer_explore';
14
+ export const AGENT_ENGINEER_IMPLEMENT = 'engineer_implement';
15
15
  // ---------------------------------------------------------------------------
16
16
  // Tool IDs — grouped by domain
17
17
  // ---------------------------------------------------------------------------
@@ -25,10 +25,10 @@ const ENGINEER_SHARED_TOOL_IDS = [
25
25
  ];
26
26
  /** All engineer tools — mode-locked sends + shared session tools */
27
27
  const ENGINEER_TOOL_IDS = ['explore', 'implement', ...ENGINEER_SHARED_TOOL_IDS];
28
- /** Tools for the engineer_plan wrapper (plan-mode send + shared) */
29
- const ENGINEER_PLAN_TOOL_IDS = ['explore', ...ENGINEER_SHARED_TOOL_IDS];
30
- /** Tools for the engineer_build wrapper (build-mode send + shared) */
31
- const ENGINEER_BUILD_TOOL_IDS = ['implement', ...ENGINEER_SHARED_TOOL_IDS];
28
+ /** Tools for the engineer_explore wrapper (explore-mode send + shared) */
29
+ const ENGINEER_EXPLORE_TOOL_IDS = ['explore', ...ENGINEER_SHARED_TOOL_IDS];
30
+ /** Tools for the engineer_implement wrapper (implement-mode send + shared) */
31
+ const ENGINEER_IMPLEMENT_TOOL_IDS = ['implement', ...ENGINEER_SHARED_TOOL_IDS];
32
32
  /** Git tools — owned by CTO */
33
33
  const GIT_TOOL_IDS = ['git_diff', 'git_commit', 'git_reset', 'git_status', 'git_log'];
34
34
  /** Approval tools — owned by CTO */
@@ -77,19 +77,19 @@ function buildCtoPermissions() {
77
77
  ...allowed,
78
78
  task: {
79
79
  '*': 'deny',
80
- [AGENT_ENGINEER_PLAN]: 'allow',
81
- [AGENT_ENGINEER_BUILD]: 'allow',
80
+ [AGENT_ENGINEER_EXPLORE]: 'allow',
81
+ [AGENT_ENGINEER_IMPLEMENT]: 'allow',
82
82
  },
83
83
  };
84
84
  }
85
- /** Engineer plan wrapper: read-only investigation + explore + shared session tools. */
86
- function buildEngineerPlanPermissions() {
85
+ /** Engineer explore wrapper: read-only investigation + explore + shared session tools. */
86
+ function buildEngineerExplorePermissions() {
87
87
  const denied = {};
88
88
  for (const toolId of ALL_RESTRICTED_TOOL_IDS) {
89
89
  denied[toolId] = 'deny';
90
90
  }
91
91
  const allowed = {};
92
- for (const toolId of ENGINEER_PLAN_TOOL_IDS) {
92
+ for (const toolId of ENGINEER_EXPLORE_TOOL_IDS) {
93
93
  allowed[toolId] = 'allow';
94
94
  }
95
95
  return {
@@ -99,14 +99,14 @@ function buildEngineerPlanPermissions() {
99
99
  ...allowed,
100
100
  };
101
101
  }
102
- /** Engineer build wrapper: read-only investigation + implement + shared session tools. */
103
- function buildEngineerBuildPermissions() {
102
+ /** Engineer implement wrapper: read-only investigation + implement + shared session tools. */
103
+ function buildEngineerImplementPermissions() {
104
104
  const denied = {};
105
105
  for (const toolId of ALL_RESTRICTED_TOOL_IDS) {
106
106
  denied[toolId] = 'deny';
107
107
  }
108
108
  const allowed = {};
109
- for (const toolId of ENGINEER_BUILD_TOOL_IDS) {
109
+ for (const toolId of ENGINEER_IMPLEMENT_TOOL_IDS) {
110
110
  allowed[toolId] = 'allow';
111
111
  }
112
112
  return {
@@ -128,22 +128,22 @@ export function buildCtoAgentConfig(prompts) {
128
128
  prompt: prompts.ctoSystemPrompt,
129
129
  };
130
130
  }
131
- export function buildEngineerPlanAgentConfig(prompts) {
131
+ export function buildEngineerExploreAgentConfig(prompts) {
132
132
  return {
133
133
  description: 'Thin high-judgment wrapper that frames work quickly and dispatches to Claude Code in plan mode for read-only investigation.',
134
134
  mode: 'subagent',
135
135
  color: '#D97757',
136
- permission: buildEngineerPlanPermissions(),
137
- prompt: prompts.engineerPlanPrompt,
136
+ permission: buildEngineerExplorePermissions(),
137
+ prompt: prompts.engineerExplorePrompt,
138
138
  };
139
139
  }
140
- export function buildEngineerBuildAgentConfig(prompts) {
140
+ export function buildEngineerImplementAgentConfig(prompts) {
141
141
  return {
142
142
  description: 'Thin high-judgment wrapper that frames work quickly and dispatches to Claude Code in free mode for implementation.',
143
143
  mode: 'subagent',
144
144
  color: '#D97757',
145
- permission: buildEngineerBuildPermissions(),
146
- prompt: prompts.engineerBuildPrompt,
145
+ permission: buildEngineerImplementPermissions(),
146
+ prompt: prompts.engineerImplementPrompt,
147
147
  };
148
148
  }
149
149
  // ---------------------------------------------------------------------------
@@ -1,16 +1,16 @@
1
1
  import { tool } from '@opencode-ai/plugin';
2
2
  import { composeWrapperPrompt, managerPromptRegistry } from '../prompts/registry.js';
3
3
  import { discoverProjectClaudeFiles } from '../util/project-context.js';
4
- import { AGENT_CTO, AGENT_ENGINEER_BUILD, AGENT_ENGINEER_PLAN, buildCtoAgentConfig, buildEngineerBuildAgentConfig, buildEngineerPlanAgentConfig, denyRestrictedToolsGlobally, } from './agent-hierarchy.js';
4
+ import { AGENT_CTO, AGENT_ENGINEER_EXPLORE, AGENT_ENGINEER_IMPLEMENT, buildCtoAgentConfig, buildEngineerExploreAgentConfig, buildEngineerImplementAgentConfig, denyRestrictedToolsGlobally, } from './agent-hierarchy.js';
5
5
  import { getOrCreatePluginServices } from './service-factory.js';
6
6
  export const ClaudeManagerPlugin = async ({ worktree }) => {
7
7
  const services = getOrCreatePluginServices(worktree);
8
8
  async function executeDelegate(args, context) {
9
- const cwd = args.cwd ?? context.worktree;
9
+ const wrapperServices = getOrCreatePluginServices(context.worktree);
10
10
  if (args.freshSession) {
11
- await services.manager.clearSession(cwd);
11
+ await wrapperServices.manager.clearSession();
12
12
  }
13
- const hasActiveSession = services.manager.getStatus().sessionId !== null;
13
+ const hasActiveSession = wrapperServices.manager.getStatus().sessionId !== null;
14
14
  const promptPreview = args.message.length > 100 ? args.message.slice(0, 100) + '...' : args.message;
15
15
  context.metadata({
16
16
  title: hasActiveSession
@@ -18,16 +18,17 @@ export const ClaudeManagerPlugin = async ({ worktree }) => {
18
18
  : '⚡ Claude Code: Initializing...',
19
19
  metadata: {
20
20
  status: 'running',
21
- sessionId: services.manager.getStatus().sessionId,
21
+ sessionId: wrapperServices.manager.getStatus().sessionId,
22
22
  prompt: promptPreview,
23
23
  },
24
24
  });
25
25
  let turnsSoFar;
26
26
  let costSoFar;
27
- const result = await services.manager.sendMessage(cwd, args.message, {
27
+ const result = await wrapperServices.manager.sendMessage(context.worktree, args.message, {
28
28
  model: args.model,
29
29
  effort: args.effort,
30
30
  mode: args.mode,
31
+ sessionSystemPrompt: args.sessionSystemPrompt,
31
32
  abortSignal: context.abort,
32
33
  }, (event) => {
33
34
  if (event.turns !== undefined) {
@@ -182,7 +183,7 @@ export const ClaudeManagerPlugin = async ({ worktree }) => {
182
183
  let toolOutputs = [];
183
184
  if (result.sessionId) {
184
185
  try {
185
- toolOutputs = await services.liveTailer.getToolOutputPreview(result.sessionId, cwd, 3);
186
+ toolOutputs = await wrapperServices.liveTailer.getToolOutputPreview(result.sessionId, context.worktree, 3);
186
187
  }
187
188
  catch {
188
189
  // Non-critical — the JSONL file may not exist yet.
@@ -210,12 +211,12 @@ export const ClaudeManagerPlugin = async ({ worktree }) => {
210
211
  const claudeFiles = await discoverProjectClaudeFiles(worktree);
211
212
  const derivedPrompts = {
212
213
  ...managerPromptRegistry,
213
- engineerPlanPrompt: composeWrapperPrompt(managerPromptRegistry.engineerPlanPrompt, claudeFiles),
214
- engineerBuildPrompt: composeWrapperPrompt(managerPromptRegistry.engineerBuildPrompt, claudeFiles),
214
+ engineerExplorePrompt: composeWrapperPrompt(managerPromptRegistry.engineerExplorePrompt, claudeFiles),
215
+ engineerImplementPrompt: composeWrapperPrompt(managerPromptRegistry.engineerImplementPrompt, claudeFiles),
215
216
  };
216
217
  config.agent[AGENT_CTO] ??= buildCtoAgentConfig(managerPromptRegistry);
217
- config.agent[AGENT_ENGINEER_PLAN] ??= buildEngineerPlanAgentConfig(derivedPrompts);
218
- config.agent[AGENT_ENGINEER_BUILD] ??= buildEngineerBuildAgentConfig(derivedPrompts);
218
+ config.agent[AGENT_ENGINEER_EXPLORE] ??= buildEngineerExploreAgentConfig(derivedPrompts);
219
+ config.agent[AGENT_ENGINEER_IMPLEMENT] ??= buildEngineerImplementAgentConfig(derivedPrompts);
219
220
  },
220
221
  tool: {
221
222
  explore: tool({
@@ -225,14 +226,14 @@ export const ClaudeManagerPlugin = async ({ worktree }) => {
225
226
  args: {
226
227
  message: tool.schema.string().min(1),
227
228
  model: tool.schema
228
- .enum(['claude-opus-4-6', 'claude-sonnet-4-6', 'claude-sonnet-4-5'])
229
+ .enum(['claude-opus-4-6', 'claude-sonnet-4-6'])
229
230
  .optional(),
230
- effort: tool.schema.enum(['low', 'medium', 'high', 'max']).default('high'),
231
+ effort: tool.schema.enum(['medium', 'high', 'max']).default('high'),
231
232
  freshSession: tool.schema.boolean().default(false),
232
- cwd: tool.schema.string().optional(),
233
+ sessionSystemPrompt: tool.schema.string().optional(),
233
234
  },
234
235
  async execute(args, context) {
235
- return executeDelegate({ ...args, mode: 'plan' }, context);
236
+ return executeDelegate({ ...args, mode: 'plan', wrapperType: 'explore' }, context);
236
237
  },
237
238
  }),
238
239
  implement: tool({
@@ -241,27 +242,27 @@ export const ClaudeManagerPlugin = async ({ worktree }) => {
241
242
  args: {
242
243
  message: tool.schema.string().min(1),
243
244
  model: tool.schema
244
- .enum(['claude-opus-4-6', 'claude-sonnet-4-6', 'claude-sonnet-4-5'])
245
+ .enum(['claude-opus-4-6', 'claude-sonnet-4-6'])
245
246
  .optional(),
246
- effort: tool.schema.enum(['low', 'medium', 'high', 'max']).default('high'),
247
+ effort: tool.schema.enum(['medium', 'high', 'max']).default('high'),
247
248
  freshSession: tool.schema.boolean().default(false),
248
- cwd: tool.schema.string().optional(),
249
+ sessionSystemPrompt: tool.schema.string().optional(),
249
250
  },
250
251
  async execute(args, context) {
251
- return executeDelegate({ ...args, mode: 'free' }, context);
252
+ return executeDelegate({ ...args, mode: 'free', wrapperType: 'implement' }, context);
252
253
  },
253
254
  }),
254
255
  compact_context: tool({
255
256
  description: 'Compress session history to reclaim context window space. ' +
256
257
  'Preserves state while reducing token usage.',
257
258
  args: {
258
- cwd: tool.schema.string().optional(),
259
+ wrapperType: tool.schema.string().optional(),
259
260
  },
260
261
  async execute(args, context) {
261
- const cwd = args.cwd ?? context.worktree;
262
+ const wrapperServices = getOrCreatePluginServices(context.worktree);
262
263
  annotateToolRun(context, 'Compacting session', {});
263
- const result = await services.manager.compactSession(cwd);
264
- const snap = services.manager.getStatus();
264
+ const result = await wrapperServices.manager.compactSession(context.worktree);
265
+ const snap = wrapperServices.manager.getStatus();
265
266
  const contextWarning = formatContextWarning(snap);
266
267
  context.metadata({
267
268
  title: contextWarning
@@ -355,25 +356,27 @@ export const ClaudeManagerPlugin = async ({ worktree }) => {
355
356
  description: 'Clear the active session to start fresh. ' +
356
357
  'Use when context is full or starting a new task.',
357
358
  args: {
358
- cwd: tool.schema.string().optional(),
359
+ wrapperType: tool.schema.string().optional(),
359
360
  reason: tool.schema.string().optional(),
360
361
  },
361
362
  async execute(args, context) {
363
+ const wrapperServices = getOrCreatePluginServices(context.worktree);
362
364
  annotateToolRun(context, 'Clearing session', {
363
365
  reason: args.reason,
364
366
  });
365
- const clearedId = await services.manager.clearSession(args.cwd ?? context.worktree);
367
+ const clearedId = await wrapperServices.manager.clearSession();
366
368
  return JSON.stringify({ clearedSessionId: clearedId });
367
369
  },
368
370
  }),
369
371
  session_health: tool({
370
372
  description: 'Check session health metrics: context usage %, turn count, cost, and session ID.',
371
373
  args: {
372
- cwd: tool.schema.string().optional(),
374
+ wrapperType: tool.schema.string().optional(),
373
375
  },
374
- async execute(_args, context) {
376
+ async execute(args, context) {
377
+ const wrapperServices = getOrCreatePluginServices(context.worktree);
375
378
  annotateToolRun(context, 'Checking session status', {});
376
- const status = services.manager.getStatus();
379
+ const status = wrapperServices.manager.getStatus();
377
380
  return JSON.stringify({
378
381
  ...status,
379
382
  transcriptFile: status.sessionId
@@ -386,39 +389,40 @@ export const ClaudeManagerPlugin = async ({ worktree }) => {
386
389
  list_transcripts: tool({
387
390
  description: 'List available session transcripts or inspect a specific transcript by ID.',
388
391
  args: {
389
- cwd: tool.schema.string().optional(),
392
+ wrapperType: tool.schema.string().optional(),
390
393
  sessionId: tool.schema.string().optional(),
391
394
  },
392
395
  async execute(args, context) {
396
+ const wrapperServices = getOrCreatePluginServices(context.worktree);
393
397
  annotateToolRun(context, 'Inspecting Claude session history', {});
394
- const cwd = args.cwd ?? context.worktree;
395
398
  if (args.sessionId) {
396
399
  const [sdkTranscript, localEvents] = await Promise.all([
397
- services.sessions.getTranscript(args.sessionId, cwd),
398
- services.manager.getTranscriptEvents(cwd, args.sessionId),
400
+ wrapperServices.sessions.getTranscript(args.sessionId, context.worktree),
401
+ wrapperServices.manager.getTranscriptEvents(context.worktree, args.sessionId),
399
402
  ]);
400
403
  return JSON.stringify({
401
404
  sdkTranscript,
402
405
  localEvents: localEvents.length > 0 ? localEvents : undefined,
403
406
  }, null, 2);
404
407
  }
405
- const sessions = await services.sessions.listSessions(cwd);
408
+ const sessions = await wrapperServices.sessions.listSessions(context.worktree);
406
409
  return JSON.stringify(sessions, null, 2);
407
410
  },
408
411
  }),
409
412
  list_history: tool({
410
413
  description: 'List persistent run records from the manager or inspect a specific run.',
411
414
  args: {
412
- cwd: tool.schema.string().optional(),
415
+ wrapperType: tool.schema.string().optional(),
413
416
  runId: tool.schema.string().optional(),
414
417
  },
415
418
  async execute(args, context) {
419
+ const wrapperServices = getOrCreatePluginServices(context.worktree);
416
420
  annotateToolRun(context, 'Reading manager run state', {});
417
421
  if (args.runId) {
418
- const run = await services.manager.getRun(args.cwd ?? context.worktree, args.runId);
422
+ const run = await wrapperServices.manager.getRun(context.worktree, args.runId);
419
423
  return JSON.stringify(run, null, 2);
420
424
  }
421
- const runs = await services.manager.listRuns(args.cwd ?? context.worktree);
425
+ const runs = await wrapperServices.manager.listRuns(context.worktree);
422
426
  return JSON.stringify(runs, null, 2);
423
427
  },
424
428
  }),
@@ -9,23 +9,19 @@ import { GitOperations } from '../manager/git-operations.js';
9
9
  import { SessionController } from '../manager/session-controller.js';
10
10
  import { PersistentManager } from '../manager/persistent-manager.js';
11
11
  import { managerPromptRegistry } from '../prompts/registry.js';
12
- const serviceCache = new Map();
13
12
  export function getOrCreatePluginServices(worktree) {
14
- const cachedServices = serviceCache.get(worktree);
15
- if (cachedServices) {
16
- return cachedServices;
17
- }
18
13
  const approvalManager = new ToolApprovalManager();
19
14
  const sdkAdapter = new ClaudeAgentSdkAdapter(undefined, approvalManager);
20
15
  const sessionService = new ClaudeSessionService(sdkAdapter);
21
16
  const contextTracker = new ContextTracker();
22
- const sessionController = new SessionController(sdkAdapter, contextTracker, managerPromptRegistry.engineerSessionPrompt, managerPromptRegistry.modePrefixes);
17
+ const sessionController = new SessionController(sdkAdapter, contextTracker, undefined, // session prompt is now constructed dynamically by the wrapper
18
+ 'default', worktree, managerPromptRegistry.modePrefixes);
23
19
  const gitOps = new GitOperations(worktree);
24
20
  const stateStore = new FileRunStateStore();
25
21
  const transcriptStore = new TranscriptStore();
26
22
  const manager = new PersistentManager(sessionController, gitOps, stateStore, contextTracker, transcriptStore);
27
23
  // Try to restore active session state (fire and forget)
28
- manager.tryRestore(worktree).catch(() => { });
24
+ manager.tryRestore().catch(() => { });
29
25
  const liveTailer = new SessionLiveTailer();
30
26
  const services = {
31
27
  manager,
@@ -33,6 +29,5 @@ export function getOrCreatePluginServices(worktree) {
33
29
  approvalManager,
34
30
  liveTailer,
35
31
  };
36
- serviceCache.set(worktree, services);
37
32
  return services;
38
33
  }
@@ -13,6 +13,66 @@ export function composeWrapperPrompt(basePrompt, claudeFiles) {
13
13
  const sections = claudeFiles.map((f) => `### ${f.relativePath}\n${f.content}`).join('\n\n');
14
14
  return `${basePrompt}\n\n## Project Claude Files\nThe following project-level instructions were discovered from the repository.\n\n${sections}`;
15
15
  }
16
+ /**
17
+ * Build an engineer wrapper prompt from shared sections plus mode-specific overrides.
18
+ */
19
+ function buildEngineerWrapperPrompt(opts) {
20
+ return [
21
+ `You are a staff engineer managing a Claude Code session for ${opts.purpose}.`,
22
+ 'You are not a forwarding layer — interpret the task in repo context before delegating.',
23
+ '',
24
+ '## Staff-level framing',
25
+ '- Identify the real problem, not just the stated request.',
26
+ '- Look for missing architecture, ownership, or precedence issues before delegating.',
27
+ '- Rewrite weak or underspecified requests into precise prompts for the engineer.',
28
+ '- For medium+ tasks, determine: the actual problem, the cleanest architecture,',
29
+ ' and what needs clarification before work begins.',
30
+ '- Ask ONE clarification first if it materially improves architecture.',
31
+ '',
32
+ '## Repo-context investigation',
33
+ '- Use read/grep/glob sparingly — only for spot-checks to sharpen a delegation.',
34
+ '- Do NOT implement changes yourself — investigation only.',
35
+ '',
36
+ '## Behavior',
37
+ `- Send the objective to the engineer using ${opts.toolName}.`,
38
+ "- Return the engineer's response verbatim. Do not summarize.",
39
+ `- Use freshSession:true on ${opts.toolName} when the task is unrelated to prior work.`,
40
+ '',
41
+ '## Constructing the engineer session prompt',
42
+ `When you call \`${opts.toolName}\`, you MUST include a \`sessionSystemPrompt\` argument.`,
43
+ 'This becomes the system prompt for the underlying Claude Code session.',
44
+ 'Build it as a self-contained description that equips the engineer to execute precisely.',
45
+ '',
46
+ 'Structure it as:',
47
+ `1. **Role**: "${opts.roleDescription}"`,
48
+ '2. **Project rules**: Extract only the rules from the Project Claude Files below that',
49
+ ' are relevant to this specific task. Synthesize — do not dump everything.',
50
+ ' Cite file paths when the source matters (e.g. "per packages/core/CLAUDE.md").',
51
+ '3. **Verification**: How to verify the work (tests, lint, typecheck, expected behavior).',
52
+ '',
53
+ 'Keep it concise: 3-6 sentences for role + relevant rules + verification.',
54
+ 'The task itself goes in `message`, not in `sessionSystemPrompt`.',
55
+ '',
56
+ '## Context management',
57
+ '- Check session_health before sending.',
58
+ '- Under 50%: proceed. Over 70%: compact_context. Over 85%: clear_session.',
59
+ '',
60
+ '## Model selection',
61
+ ...opts.modelDefaults,
62
+ '',
63
+ '## Using appended Project Claude Files',
64
+ '- Treat appended Project Claude Files as project guidance for the engineer.',
65
+ '- Extract only the rules relevant to the current task when constructing sessionSystemPrompt.',
66
+ '- Prefer guidance from more specific/nested paths over root-level guidance on conflict.',
67
+ '- Direct user instructions override Claude-file guidance.',
68
+ '- Keep delegated instructions tight; do not dump the full file corpus unless needed.',
69
+ '- Cite file paths (e.g. "per packages/core/CLAUDE.md") when the source matters.',
70
+ '',
71
+ '## What you must NOT do',
72
+ '- Do NOT call git_*, approval_*, or any non-engineer tools.',
73
+ '- Do NOT add commentary to the engineer response.',
74
+ ].join('\n');
75
+ }
16
76
  export const managerPromptRegistry = {
17
77
  ctoSystemPrompt: [
18
78
  'You are a staff+ technical owner who uses Claude Code better than anyone.',
@@ -25,7 +85,7 @@ export const managerPromptRegistry = {
25
85
  '- Verifying a result after an engineer returns.',
26
86
  '- Resolving one high-leverage ambiguity before dispatching.',
27
87
  'If you need more than 2 direct read/grep/glob lookups, stop and delegate',
28
- 'the investigation to `engineer_plan` instead.',
88
+ 'the investigation to `engineer_explore` instead.',
29
89
  '',
30
90
  '## Core principle: technical ownership',
31
91
  'You are not a ticket-taker. Before acting, look for:',
@@ -51,12 +111,12 @@ export const managerPromptRegistry = {
51
111
  ' 2. What is underspecified or conflicting.',
52
112
  ' 3. What the cleanest architecture is.',
53
113
  ' 4. What should be clarified before proceeding.',
54
- ' Prefer spawning `engineer_plan` for repo exploration rather than reading',
114
+ ' Prefer spawning `engineer_explore` for repo exploration rather than reading',
55
115
  ' code yourself. Use at most 1-2 spot-check reads to sharpen the delegation.',
56
116
  ' Then delegate with file paths, line numbers, patterns, and verification.',
57
117
  '',
58
118
  '**Complex tasks** (multi-file feature, large refactor):',
59
- ' 1. Spawn `engineer_plan` to explore the repo, map dependencies, and analyze impact.',
119
+ ' 1. Spawn `engineer_explore` to explore the repo, map dependencies, and analyze impact.',
60
120
  ' 2. If requirements are unclear, ask the user ONE high-leverage question —',
61
121
  ' only when it materially changes architecture, ownership, or destructive behavior.',
62
122
  ' Prefer the question tool when discrete options exist.',
@@ -92,20 +152,20 @@ export const managerPromptRegistry = {
92
152
  ' style violations.',
93
153
  '2. git_status — check what files changed (quick overview)',
94
154
  '3. git_log -n 5 — see recent commits (understand context)',
95
- '4. If correct: spawn `engineer_build` to run tests/lint/typecheck.',
155
+ '4. If correct: spawn `engineer_implement` to run tests/lint/typecheck.',
96
156
  '5. If tests pass: git_commit to checkpoint.',
97
- '6. If wrong: spawn `engineer_build` with a specific correction.',
157
+ '6. If wrong: spawn `engineer_implement` with a specific correction.',
98
158
  ' On second failure: git_reset and rewrite the prompt from scratch.',
99
159
  ' Never send three corrections for the same problem.',
100
160
  '',
101
161
  '## Engineers (via the Task tool)',
102
- '- `engineer_plan` — read-only investigation. Use for: exploring unfamiliar code,',
162
+ '- `engineer_explore` — read-only investigation. Use for: exploring unfamiliar code,',
103
163
  ' mapping dependencies, analyzing impact, asking "how does X work?"',
104
- '- `engineer_build` — implementation. Use for: all code changes, test runs, fixes.',
164
+ '- `engineer_implement` — implementation. Use for: all code changes, test runs, fixes.',
105
165
  '- If steps are independent, spawn multiple engineers in parallel.',
106
166
  '',
107
167
  '## Context efficiency',
108
- '- Use `engineer_plan` for broad exploration so your own context stays clean.',
168
+ '- Use `engineer_explore` for broad exploration so your own context stays clean.',
109
169
  '- When spawning engineers for unrelated tasks, tell them to use freshSession:true.',
110
170
  '- Keep delegations focused — one concern per engineer invocation.',
111
171
  '',
@@ -134,106 +194,40 @@ export const managerPromptRegistry = {
134
194
  '- Destructive actions on shared state (deploy, publish, force-push).',
135
195
  'State the blocker, what you need, and a concrete suggestion to unblock.',
136
196
  ].join('\n'),
137
- engineerPlanPrompt: [
138
- 'You are a staff engineer managing a Claude Code session for read-only investigation.',
139
- 'You are not a forwarding layer — interpret the task in repo context before delegating.',
140
- '',
141
- '## Staff-level framing',
142
- '- Identify the real problem, not just the stated request.',
143
- '- Look for missing architecture, ownership, or precedence issues before delegating.',
144
- '- Rewrite weak or underspecified requests into precise prompts for the engineer.',
145
- '- For medium+ tasks, determine: the actual problem, the cleanest architecture,',
146
- ' and what needs clarification before work begins.',
147
- '- Ask ONE clarification first if it materially improves architecture.',
148
- '',
149
- '## Repo-context investigation',
150
- '- Use read/grep/glob sparingly — only for spot-checks to sharpen a delegation.',
151
- '- If more than 2 lookups are needed, send the investigation to the engineer.',
152
- '- Do NOT implement changes yourself investigation only.',
153
- '',
154
- '## Behavior',
155
- '- Send the objective to the engineer using explore.',
156
- "- Return the engineer's response verbatim. Do not summarize.",
157
- '- Use freshSession:true on explore when the task is unrelated to prior work.',
158
- '',
159
- '## Context management',
160
- '- Check session_health before sending.',
161
- '- Under 50%: proceed. Over 70%: compact_context. Over 85%: clear_session.',
162
- '',
163
- '## Model selection',
164
- '- claude-opus-4-6 + high: complex analysis (default).',
165
- '- claude-sonnet-4-6: lighter analysis.',
166
- '- effort "medium": simple lookups.',
167
- '',
168
- '## Using appended Project Claude Files',
169
- '- Treat appended Project Claude Files as project guidance for the engineer.',
170
- '- Extract only the rules relevant to the current task when delegating.',
171
- '- Prefer guidance from more specific/nested paths over root-level guidance on conflict.',
172
- '- Direct user instructions override Claude-file guidance.',
173
- '- Keep delegated instructions tight; do not dump the full file corpus unless needed.',
174
- '- Cite file paths (e.g. "per packages/core/CLAUDE.md") when the source matters.',
175
- '',
176
- '## What you must NOT do',
177
- '- Do NOT call git_*, approval_*, or any non-engineer tools.',
178
- '- Do NOT add commentary to the engineer response.',
179
- ].join('\n'),
180
- engineerBuildPrompt: [
181
- 'You are a staff engineer managing a Claude Code session for implementation.',
182
- 'You are not a forwarding layer — interpret the task in repo context before delegating.',
183
- '',
184
- '## Staff-level framing',
185
- '- Identify the real problem, not just the stated request.',
186
- '- Look for missing architecture, ownership, or precedence issues before delegating.',
187
- '- Rewrite weak or underspecified requests into precise prompts for the engineer.',
188
- '- For medium+ tasks, determine: the actual problem, the cleanest architecture,',
189
- ' and what needs clarification before work begins.',
190
- '- Ask ONE clarification first if it materially improves architecture.',
191
- '',
192
- '## Repo-context investigation',
193
- '- Use read/grep/glob sparingly — only for spot-checks to sharpen a delegation.',
194
- '- If more than 2 lookups are needed, send the investigation to the engineer.',
195
- '- Do NOT implement changes yourself — investigation only.',
196
- '',
197
- '## Behavior',
198
- '- Send the objective to the engineer using implement.',
199
- "- Return the engineer's response verbatim. Do not summarize.",
200
- '- Use freshSession:true on implement when the task is unrelated to prior work.',
201
- '',
202
- '## Context management',
203
- '- Check session_health before sending.',
204
- '- Under 50%: proceed. Over 70%: compact_context. Over 85%: clear_session.',
205
- '',
206
- '## Model selection',
207
- '- claude-opus-4-6 + high: most coding tasks (default).',
208
- '- claude-sonnet-4-6: simple renames, formatting, scaffolding.',
209
- '- effort "max": complex refactors, subtle bugs, cross-cutting changes.',
210
- '',
211
- '## Using appended Project Claude Files',
212
- '- Treat appended Project Claude Files as project guidance for the engineer.',
213
- '- Extract only the rules relevant to the current task when delegating.',
214
- '- Prefer guidance from more specific/nested paths over root-level guidance on conflict.',
215
- '- Direct user instructions override Claude-file guidance.',
216
- '- Keep delegated instructions tight; do not dump the full file corpus unless needed.',
217
- '- Cite file paths (e.g. "per packages/core/CLAUDE.md") when the source matters.',
218
- '',
219
- '## What you must NOT do',
220
- '- Do NOT call git_*, approval_*, or any non-engineer tools.',
221
- '- Do NOT add commentary to the engineer response.',
222
- ].join('\n'),
197
+ engineerExplorePrompt: buildEngineerWrapperPrompt({
198
+ purpose: 'read-only investigation',
199
+ toolName: 'explore',
200
+ roleDescription: 'You are an expert engineer performing read-only investigation. ' +
201
+ 'Execute directly. No preamble. Follow existing repo conventions.',
202
+ modelDefaults: [
203
+ '- claude-opus-4-6 + high: complex analysis (default).',
204
+ '- claude-sonnet-4-6: lighter analysis.',
205
+ '- effort "medium": simple lookups.',
206
+ ],
207
+ }),
208
+ engineerImplementPrompt: buildEngineerWrapperPrompt({
209
+ purpose: 'implementation',
210
+ toolName: 'implement',
211
+ roleDescription: 'You are an expert engineer implementing changes. ' +
212
+ 'Execute directly. No preamble. Follow existing repo conventions. ' +
213
+ 'Do not run git commit, git push, git reset, git checkout, or git stash — git operations are handled externally.',
214
+ modelDefaults: [
215
+ '- claude-opus-4-6 + high: most coding tasks (default).',
216
+ '- claude-sonnet-4-6: simple renames, formatting, scaffolding.',
217
+ '- effort "max": complex refactors, subtle bugs, cross-cutting changes.',
218
+ ],
219
+ }),
223
220
  engineerSessionPrompt: [
224
221
  'You are an expert engineer. Execute instructions precisely.',
225
222
  '',
226
223
  '## Rules',
227
224
  '- Execute directly. No preamble, no restating the task.',
228
- '- Prefer targeted file reads over reading entire files.',
229
- '- Use subagents for independent parallel work.',
230
- '- Follow existing repo conventions (naming, style, patterns).',
225
+ '- Follow existing repo conventions.',
226
+ '- Report exact output on failure.',
231
227
  '',
232
228
  '## Verification',
233
229
  '- Always verify your own work before reporting done.',
234
- '- Run tests, lint, or typecheck when the instruction says to.',
235
230
  '- If no verification was specified, still run relevant tests if they exist.',
236
- '- Report exact output on failure.',
237
231
  '',
238
232
  '## Git boundary — do NOT run:',
239
233
  'git commit, git push, git reset, git checkout, git stash.',
@@ -241,8 +235,7 @@ export const managerPromptRegistry = {
241
235
  '',
242
236
  '## Reporting',
243
237
  '- End with: what was done, what was verified, what passed/failed.',
244
- '- Report blockers immediately with specifics: file, line, error.',
245
- '- If partially complete, state exactly what remains.',
238
+ '- Report blockers immediately with specifics.',
246
239
  ].join('\n'),
247
240
  modePrefixes: {
248
241
  plan: [
@@ -1,7 +1,7 @@
1
1
  export interface ManagerPromptRegistry {
2
2
  ctoSystemPrompt: string;
3
- engineerPlanPrompt: string;
4
- engineerBuildPrompt: string;
3
+ engineerExplorePrompt: string;
4
+ engineerImplementPrompt: string;
5
5
  engineerSessionPrompt: string;
6
6
  modePrefixes: {
7
7
  plan: string;
@@ -113,7 +113,6 @@ export interface GitOperationResult {
113
113
  }
114
114
  export interface ActiveSessionState {
115
115
  sessionId: string;
116
- cwd: string;
117
116
  startedAt: string;
118
117
  totalTurns: number;
119
118
  totalCostUsd: number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@doingdev/opencode-claude-manager-plugin",
3
- "version": "0.1.42",
3
+ "version": "0.1.43",
4
4
  "description": "OpenCode plugin that orchestrates Claude Code sessions.",
5
5
  "keywords": [
6
6
  "opencode",