@@ -59,6 +59,8 @@ export interface SpawnOptions {
5959 worktree ?: string ;
6060 baseBranch ?: string ;
6161 prd ?: string ;
62+ /** Explicit constraints to prevent eager refactoring */
63+ hardRules ?: string [ ] ;
6264 interactive ?: boolean ;
6365 redis ?: RedisConfig ;
6466 enableHeartbeat ?: boolean ;
@@ -160,7 +162,8 @@ function buildCommand(
160162 redisConfig ?: RedisConfig ,
161163 sessionId ?: string ,
162164 parentSessionId ?: string ,
163- model ?: string
165+ model ?: string ,
166+ hardRules ?: string [ ]
164167) : string {
165168 const envVars : string [ ] = [ ] ;
166169
@@ -184,9 +187,13 @@ function buildCommand(
184187 envVars . push ( `REDIS_URL="${ redisConfig . url } "` ) ;
185188 }
186189
190+ if ( hardRules && hardRules . length > 0 ) {
191+ envVars . push ( `CODERS_HARD_RULES="${ hardRules . join ( '\n- ' ) } "` ) ;
192+ }
193+
187194 const env = envVars . length > 0 ? envVars . join ( ' ' ) + ' ' : '' ;
188195 const modelArg = model ? ` --model "${ model } "` : '' ;
189-
196+
190197 if ( tool === 'claude' || tool === 'claude-code' ) {
191198 return `${ env } claude --dangerously-spawn-permission${ modelArg } -f "${ promptFile } "` ;
192199 } else if ( tool === 'gemini' ) {
@@ -201,19 +208,46 @@ function buildCommand(
201208
202209/**
203210 * Generate a prompt file with task, context, and pane ID injection
211+ * Uses the proven delegation template from multi-agent research
204212 */
205213function createPrompt ( task : string , contextFiles ?: string [ ] , paneId ?: string , redisConfig ?: RedisConfig ) : string {
206214 let prompt = '' ;
207-
215+
208216 // Inject pane ID context if provided
209217 if ( paneId ) {
210218 prompt += injectPaneIdContext ( '' , paneId ) ;
211219 }
212-
213- prompt += `TASK: ${ task } \n\n` ;
214-
220+
221+ prompt += `TASK: ${ task }
222+
223+ REPO: ${ getGitRoot ( ) }
224+ BRANCH: ${ getCurrentBranch ( ) }
225+
226+ CONTEXT:
227+ - Complete the task above
228+ - Inspect the codebase to understand the structure before making changes
229+ - Preserve existing code patterns and conventions
230+ - Only modify files necessary for the task
231+
232+ WHAT NOT TO TOUCH:
233+ - ${ process . env . CODERS_HARD_RULES || 'Leave unrelated modules unchanged' }
234+ - Do NOT refactor code outside the task scope
235+ - Do NOT add new dependencies without explicit approval
236+ - Do NOT modify configuration files unless required
237+
238+ HARD RULES:
239+ - Write tests to verify your implementation
240+ - If stuck: stop and report, do not improvise
241+ - If ambiguous: ask, do not assume
242+ - "Done" means tests pass, not just code written
243+
244+ TEST:
245+ Run the test suite and paste the output. Show your work.
246+
247+ ` ;
248+
215249 if ( contextFiles && contextFiles . length > 0 ) {
216- prompt += 'CONTEXT: \n' ;
250+ prompt += '--- PRD / SPECIFICATIONS --- \n' ;
217251 contextFiles . forEach ( file => {
218252 const content = readFile ( file ) ;
219253 if ( content ) {
@@ -222,7 +256,7 @@ function createPrompt(task: string, contextFiles?: string[], paneId?: string, re
222256 } ) ;
223257 prompt += '\n' ;
224258 }
225-
259+
226260 // Add Redis info to prompt if configured
227261 if ( redisConfig ?. url ) {
228262 prompt += `
@@ -241,7 +275,7 @@ Heartbeat format:
241275Publish to Redis channel: ${ HEARTBEAT_CHANNEL }
242276` ;
243277 }
244-
278+
245279 return prompt ;
246280}
247281
@@ -256,6 +290,7 @@ export async function spawn(options: SpawnOptions): Promise<string> {
256290 worktree,
257291 baseBranch = 'main' ,
258292 prd,
293+ hardRules,
259294 interactive = true ,
260295 redis : redisConfig ,
261296 enableHeartbeat = ! ! redisConfig ?. url ,
@@ -316,7 +351,7 @@ export async function spawn(options: SpawnOptions): Promise<string> {
316351 fs . writeFileSync ( promptFile , prompt ) ;
317352
318353 // Build command with environment variables (use effectiveCwd for WORKSPACE_DIR)
319- const cmd = buildCommand ( tool , promptFile , effectiveCwd , paneId , redisConfig , sessionId , parentSessionId , model ) ;
354+ const cmd = buildCommand ( tool , promptFile , effectiveCwd , paneId , redisConfig , sessionId , parentSessionId , model , hardRules ) ;
320355
321356 try {
322357 // Clean up existing session if any
@@ -415,6 +450,7 @@ export async function claude(
415450 model ?: string ;
416451 worktree ?: string ;
417452 prd ?: string ;
453+ hardRules ?: string [ ] ;
418454 redis ?: RedisConfig ;
419455 enableHeartbeat ?: boolean ;
420456 cwd ?: string ;
@@ -430,6 +466,7 @@ export async function gemini(
430466 model ?: string ;
431467 worktree ?: string ;
432468 prd ?: string ;
469+ hardRules ?: string [ ] ;
433470 redis ?: RedisConfig ;
434471 enableHeartbeat ?: boolean ;
435472 cwd ?: string ;
@@ -445,6 +482,7 @@ export async function codex(
445482 model ?: string ;
446483 worktree ?: string ;
447484 prd ?: string ;
485+ hardRules ?: string [ ] ;
448486 redis ?: RedisConfig ;
449487 enableHeartbeat ?: boolean ;
450488 cwd ?: string ;
@@ -460,6 +498,7 @@ export async function opencode(
460498 model ?: string ;
461499 worktree ?: string ;
462500 prd ?: string ;
501+ hardRules ?: string [ ] ;
463502 redis ?: RedisConfig ;
464503 enableHeartbeat ?: boolean ;
465504 cwd ?: string ;
@@ -478,6 +517,7 @@ export async function worktree(
478517 tool ?: 'claude' | 'gemini' | 'codex' | 'opencode' ;
479518 model ?: string ;
480519 prd ?: string ;
520+ hardRules ?: string [ ] ;
481521 redis ?: RedisConfig ;
482522 enableHeartbeat ?: boolean ;
483523 cwd ?: string ;
@@ -489,6 +529,7 @@ export async function worktree(
489529 worktree : branchName ,
490530 model : options ?. model ,
491531 prd : options ?. prd ,
532+ hardRules : options ?. hardRules ,
492533 redis : options ?. redis ,
493534 enableHeartbeat : options ?. enableHeartbeat ,
494535 cwd : options ?. cwd
0 commit comments