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
This commit is contained in:
parent
bb38050574
commit
a4e161d485
@ -85,6 +85,56 @@ VERIFY EACH CLAIM WITH YOUR OWN TOOL CALLS.
|
|||||||
Static analysis CANNOT catch: visual bugs, animation issues, user flow breakages, integration problems.
|
Static analysis CANNOT catch: visual bugs, animation issues, user flow breakages, integration problems.
|
||||||
**FAILURE TO DO HANDS-ON QA = INCOMPLETE WORK.**`
|
**FAILURE TO DO HANDS-ON QA = INCOMPLETE WORK.**`
|
||||||
|
|
||||||
|
const ORCHESTRATOR_DELEGATION_REQUIRED = `
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
⚠️⚠️⚠️ [CRITICAL SYSTEM DIRECTIVE - DELEGATION REQUIRED] ⚠️⚠️⚠️
|
||||||
|
|
||||||
|
**STOP. YOU ARE VIOLATING ORCHESTRATOR PROTOCOL.**
|
||||||
|
|
||||||
|
You (orchestrator-sisyphus) are attempting to directly modify a file outside \`.sisyphus/\`.
|
||||||
|
|
||||||
|
**Path attempted:** $FILE_PATH
|
||||||
|
|
||||||
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||||
|
|
||||||
|
🚫 **THIS IS FORBIDDEN** (except for VERIFICATION purposes)
|
||||||
|
|
||||||
|
As an ORCHESTRATOR, you MUST:
|
||||||
|
1. **DELEGATE** all implementation work via \`sisyphus_task\`
|
||||||
|
2. **VERIFY** the work done by subagents (reading files is OK)
|
||||||
|
3. **COORDINATE** - you orchestrate, you don't implement
|
||||||
|
|
||||||
|
**ALLOWED direct file operations:**
|
||||||
|
- Files inside \`.sisyphus/\` (plans, notepads, drafts)
|
||||||
|
- Reading files for verification
|
||||||
|
- Running diagnostics/tests
|
||||||
|
|
||||||
|
**FORBIDDEN direct file operations:**
|
||||||
|
- Writing/editing source code
|
||||||
|
- Creating new files outside \`.sisyphus/\`
|
||||||
|
- Any implementation work
|
||||||
|
|
||||||
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||||
|
|
||||||
|
**IF THIS IS FOR VERIFICATION:**
|
||||||
|
Proceed if you are verifying subagent work by making a small fix.
|
||||||
|
But for any substantial changes, USE \`sisyphus_task\`.
|
||||||
|
|
||||||
|
**CORRECT APPROACH:**
|
||||||
|
\`\`\`
|
||||||
|
sisyphus_task(
|
||||||
|
category="...",
|
||||||
|
prompt="[specific single task with clear acceptance criteria]"
|
||||||
|
)
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
⚠️⚠️⚠️ DELEGATE. DON'T IMPLEMENT. ⚠️⚠️⚠️
|
||||||
|
|
||||||
|
---
|
||||||
|
`
|
||||||
|
|
||||||
const SINGLE_TASK_DIRECTIVE = `
|
const SINGLE_TASK_DIRECTIVE = `
|
||||||
|
|
||||||
[SYSTEM DIRECTIVE - SINGLE TASK ONLY]
|
[SYSTEM DIRECTIVE - SINGLE TASK ONLY]
|
||||||
@ -322,6 +372,7 @@ export function createSisyphusOrchestratorHook(
|
|||||||
) {
|
) {
|
||||||
const backgroundManager = options?.backgroundManager
|
const backgroundManager = options?.backgroundManager
|
||||||
const sessions = new Map<string, SessionState>()
|
const sessions = new Map<string, SessionState>()
|
||||||
|
const pendingFilePaths = new Map<string, string>()
|
||||||
|
|
||||||
function getState(sessionID: string): SessionState {
|
function getState(sessionID: string): SessionState {
|
||||||
let state = sessions.get(sessionID)
|
let state = sessions.get(sessionID)
|
||||||
@ -491,14 +542,31 @@ export function createSisyphusOrchestratorHook(
|
|||||||
input: { tool: string; sessionID?: string; callID?: string },
|
input: { tool: string; sessionID?: string; callID?: string },
|
||||||
output: { args: Record<string, unknown>; message?: string }
|
output: { args: Record<string, unknown>; message?: string }
|
||||||
): Promise<void> => {
|
): Promise<void> => {
|
||||||
if (input.tool !== "sisyphus_task") {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isCallerOrchestrator(input.sessionID)) {
|
if (!isCallerOrchestrator(input.sessionID)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check Write/Edit tools for orchestrator - inject strong warning
|
||||||
|
if (WRITE_EDIT_TOOLS.includes(input.tool)) {
|
||||||
|
const filePath = (output.args.filePath ?? output.args.path ?? output.args.file) as string | undefined
|
||||||
|
if (filePath && !filePath.includes(ALLOWED_PATH_PREFIX)) {
|
||||||
|
// Store filePath for use in tool.execute.after
|
||||||
|
if (input.callID) {
|
||||||
|
pendingFilePaths.set(input.callID, filePath)
|
||||||
|
}
|
||||||
|
const warning = ORCHESTRATOR_DELEGATION_REQUIRED.replace("$FILE_PATH", filePath)
|
||||||
|
output.message = (output.message || "") + warning
|
||||||
|
log(`[${HOOK_NAME}] Injected delegation warning for direct file modification`, {
|
||||||
|
sessionID: input.sessionID,
|
||||||
|
tool: input.tool,
|
||||||
|
filePath,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check sisyphus_task - inject single-task directive
|
||||||
|
if (input.tool === "sisyphus_task") {
|
||||||
const prompt = output.args.prompt as string | undefined
|
const prompt = output.args.prompt as string | undefined
|
||||||
if (prompt && !prompt.includes("[SYSTEM DIRECTIVE - SINGLE TASK ONLY]")) {
|
if (prompt && !prompt.includes("[SYSTEM DIRECTIVE - SINGLE TASK ONLY]")) {
|
||||||
output.args.prompt = prompt + `\n<system-reminder>${SINGLE_TASK_DIRECTIVE}</system-reminder>`
|
output.args.prompt = prompt + `\n<system-reminder>${SINGLE_TASK_DIRECTIVE}</system-reminder>`
|
||||||
@ -506,6 +574,7 @@ export function createSisyphusOrchestratorHook(
|
|||||||
sessionID: input.sessionID,
|
sessionID: input.sessionID,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
"tool.execute.after": async (
|
"tool.execute.after": async (
|
||||||
@ -517,7 +586,10 @@ export function createSisyphusOrchestratorHook(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (WRITE_EDIT_TOOLS.includes(input.tool)) {
|
if (WRITE_EDIT_TOOLS.includes(input.tool)) {
|
||||||
const filePath = output.metadata?.filePath as string | undefined
|
const filePath = input.callID ? pendingFilePaths.get(input.callID) : undefined
|
||||||
|
if (input.callID) {
|
||||||
|
pendingFilePaths.delete(input.callID)
|
||||||
|
}
|
||||||
if (filePath && !filePath.includes(ALLOWED_PATH_PREFIX)) {
|
if (filePath && !filePath.includes(ALLOWED_PATH_PREFIX)) {
|
||||||
output.output = (output.output || "") + DIRECT_WORK_REMINDER
|
output.output = (output.output || "") + DIRECT_WORK_REMINDER
|
||||||
log(`[${HOOK_NAME}] Direct work reminder appended`, {
|
log(`[${HOOK_NAME}] Direct work reminder appended`, {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user