Skip to content

Commit a4e161d

Browse files
committed
fix(sisyphus-orchestrator): inject delegation warning before Write/Edit outside .sisyphus
- Add ORCHESTRATOR_DELEGATION_REQUIRED strong warning in tool.execute.before - Fix tool.execute.after filePath detection using pendingFilePaths Map - before stores filePath by callID, after retrieves and deletes it - Fixes bug where output.metadata.filePath was undefined
1 parent bb38050 commit a4e161d

File tree

1 file changed

+81
-9
lines changed

1 file changed

+81
-9
lines changed

src/hooks/sisyphus-orchestrator/index.ts

Lines changed: 81 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,56 @@ VERIFY EACH CLAIM WITH YOUR OWN TOOL CALLS.
8585
Static analysis CANNOT catch: visual bugs, animation issues, user flow breakages, integration problems.
8686
**FAILURE TO DO HANDS-ON QA = INCOMPLETE WORK.**`
8787

88+
const ORCHESTRATOR_DELEGATION_REQUIRED = `
89+
90+
---
91+
92+
⚠️⚠️⚠️ [CRITICAL SYSTEM DIRECTIVE - DELEGATION REQUIRED] ⚠️⚠️⚠️
93+
94+
**STOP. YOU ARE VIOLATING ORCHESTRATOR PROTOCOL.**
95+
96+
You (orchestrator-sisyphus) are attempting to directly modify a file outside \`.sisyphus/\`.
97+
98+
**Path attempted:** $FILE_PATH
99+
100+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
101+
102+
🚫 **THIS IS FORBIDDEN** (except for VERIFICATION purposes)
103+
104+
As an ORCHESTRATOR, you MUST:
105+
1. **DELEGATE** all implementation work via \`sisyphus_task\`
106+
2. **VERIFY** the work done by subagents (reading files is OK)
107+
3. **COORDINATE** - you orchestrate, you don't implement
108+
109+
**ALLOWED direct file operations:**
110+
- Files inside \`.sisyphus/\` (plans, notepads, drafts)
111+
- Reading files for verification
112+
- Running diagnostics/tests
113+
114+
**FORBIDDEN direct file operations:**
115+
- Writing/editing source code
116+
- Creating new files outside \`.sisyphus/\`
117+
- Any implementation work
118+
119+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
120+
121+
**IF THIS IS FOR VERIFICATION:**
122+
Proceed if you are verifying subagent work by making a small fix.
123+
But for any substantial changes, USE \`sisyphus_task\`.
124+
125+
**CORRECT APPROACH:**
126+
\`\`\`
127+
sisyphus_task(
128+
category="...",
129+
prompt="[specific single task with clear acceptance criteria]"
130+
)
131+
\`\`\`
132+
133+
⚠️⚠️⚠️ DELEGATE. DON'T IMPLEMENT. ⚠️⚠️⚠️
134+
135+
---
136+
`
137+
88138
const SINGLE_TASK_DIRECTIVE = `
89139
90140
[SYSTEM DIRECTIVE - SINGLE TASK ONLY]
@@ -322,6 +372,7 @@ export function createSisyphusOrchestratorHook(
322372
) {
323373
const backgroundManager = options?.backgroundManager
324374
const sessions = new Map<string, SessionState>()
375+
const pendingFilePaths = new Map<string, string>()
325376

326377
function getState(sessionID: string): SessionState {
327378
let state = sessions.get(sessionID)
@@ -491,20 +542,38 @@ export function createSisyphusOrchestratorHook(
491542
input: { tool: string; sessionID?: string; callID?: string },
492543
output: { args: Record<string, unknown>; message?: string }
493544
): Promise<void> => {
494-
if (input.tool !== "sisyphus_task") {
545+
if (!isCallerOrchestrator(input.sessionID)) {
495546
return
496547
}
497548

498-
if (!isCallerOrchestrator(input.sessionID)) {
549+
// Check Write/Edit tools for orchestrator - inject strong warning
550+
if (WRITE_EDIT_TOOLS.includes(input.tool)) {
551+
const filePath = (output.args.filePath ?? output.args.path ?? output.args.file) as string | undefined
552+
if (filePath && !filePath.includes(ALLOWED_PATH_PREFIX)) {
553+
// Store filePath for use in tool.execute.after
554+
if (input.callID) {
555+
pendingFilePaths.set(input.callID, filePath)
556+
}
557+
const warning = ORCHESTRATOR_DELEGATION_REQUIRED.replace("$FILE_PATH", filePath)
558+
output.message = (output.message || "") + warning
559+
log(`[${HOOK_NAME}] Injected delegation warning for direct file modification`, {
560+
sessionID: input.sessionID,
561+
tool: input.tool,
562+
filePath,
563+
})
564+
}
499565
return
500566
}
501567

502-
const prompt = output.args.prompt as string | undefined
503-
if (prompt && !prompt.includes("[SYSTEM DIRECTIVE - SINGLE TASK ONLY]")) {
504-
output.args.prompt = prompt + `\n<system-reminder>${SINGLE_TASK_DIRECTIVE}</system-reminder>`
505-
log(`[${HOOK_NAME}] Injected single-task directive to sisyphus_task`, {
506-
sessionID: input.sessionID,
507-
})
568+
// Check sisyphus_task - inject single-task directive
569+
if (input.tool === "sisyphus_task") {
570+
const prompt = output.args.prompt as string | undefined
571+
if (prompt && !prompt.includes("[SYSTEM DIRECTIVE - SINGLE TASK ONLY]")) {
572+
output.args.prompt = prompt + `\n<system-reminder>${SINGLE_TASK_DIRECTIVE}</system-reminder>`
573+
log(`[${HOOK_NAME}] Injected single-task directive to sisyphus_task`, {
574+
sessionID: input.sessionID,
575+
})
576+
}
508577
}
509578
},
510579

@@ -517,7 +586,10 @@ export function createSisyphusOrchestratorHook(
517586
}
518587

519588
if (WRITE_EDIT_TOOLS.includes(input.tool)) {
520-
const filePath = output.metadata?.filePath as string | undefined
589+
const filePath = input.callID ? pendingFilePaths.get(input.callID) : undefined
590+
if (input.callID) {
591+
pendingFilePaths.delete(input.callID)
592+
}
521593
if (filePath && !filePath.includes(ALLOWED_PATH_PREFIX)) {
522594
output.output = (output.output || "") + DIRECT_WORK_REMINDER
523595
log(`[${HOOK_NAME}] Direct work reminder appended`, {

0 commit comments

Comments
 (0)