fix(athena): harden council members — compaction recovery, block TodoWrite, analysis mode
- Add session.compacted handler in BackgroundManager to prevent premature task completion after compaction (defer first post-compaction idle) - Explicitly block TodoWrite/TodoRead for council members in all sync points (AgentConfig permission + session tools + prompt instructions) - Add council member prefix check to todo-continuation-enforcer skip list to prevent infinite continuation loops on completed council members - Add optional analysis mode (solo/delegation) question to Athena setup: solo = thorough but heavier, delegation = fast via explore/librarian - Allow call_omo_agent in council member allow-list for delegation mode - Update COUNCIL_MEMBER_PROMPT with TodoWrite prohibition and delegation addendum for when delegation mode is selected - Update prepare_council_prompt tool with mode parameter
This commit is contained in:
@@ -3,7 +3,7 @@ import { randomUUID } from "node:crypto"
|
||||
import { writeFile, unlink, mkdir } from "node:fs/promises"
|
||||
import { join } from "node:path"
|
||||
import { log } from "../../shared/logger"
|
||||
import { COUNCIL_MEMBER_PROMPT } from "../../agents/athena/council-member-agent"
|
||||
import { COUNCIL_MEMBER_PROMPT, COUNCIL_DELEGATION_ADDENDUM } from "../../agents/athena/council-member-agent"
|
||||
|
||||
const CLEANUP_DELAY_MS = 30 * 60 * 1000
|
||||
const COUNCIL_TMP_DIR = ".sisyphus/tmp"
|
||||
@@ -15,25 +15,32 @@ Athena-only tool. Saves the prompt once, then each council member task() call us
|
||||
"Read <path>" instruction instead of repeating the full question. This keeps task() calls
|
||||
fast and small.
|
||||
|
||||
The "mode" parameter controls whether council members can delegate exploration to subagents:
|
||||
- "solo" (default): Members do all exploration themselves. More thorough but uses more tokens.
|
||||
- "delegation": Members can delegate to explore/librarian agents. Faster, lighter context.
|
||||
|
||||
Returns the file path to reference in subsequent task() calls.`
|
||||
|
||||
return tool({
|
||||
description,
|
||||
args: {
|
||||
prompt: tool.schema.string().describe("The full analysis prompt/question for council members"),
|
||||
mode: tool.schema.string().optional().describe('Analysis mode: "solo" (default) or "delegation"'),
|
||||
},
|
||||
async execute(args: { prompt: string }) {
|
||||
async execute(args: { prompt: string; mode?: string }) {
|
||||
if (!args.prompt?.trim()) {
|
||||
return "Prompt cannot be empty."
|
||||
}
|
||||
|
||||
const mode = args.mode === "delegation" ? "delegation" : "solo"
|
||||
const tmpDir = join(directory, COUNCIL_TMP_DIR)
|
||||
await mkdir(tmpDir, { recursive: true })
|
||||
|
||||
const filename = `athena-council-${randomUUID().slice(0, 8)}.md`
|
||||
const filePath = join(tmpDir, filename)
|
||||
|
||||
const content = `${COUNCIL_MEMBER_PROMPT}
|
||||
const delegationSection = mode === "delegation" ? `\n${COUNCIL_DELEGATION_ADDENDUM}` : ""
|
||||
const content = `${COUNCIL_MEMBER_PROMPT}${delegationSection}
|
||||
|
||||
## Analysis Question
|
||||
|
||||
@@ -45,9 +52,9 @@ ${args.prompt}`
|
||||
unlink(filePath).catch(() => {})
|
||||
}, CLEANUP_DELAY_MS)
|
||||
|
||||
log("[prepare-council-prompt] Saved prompt", { filePath, length: args.prompt.length })
|
||||
log("[prepare-council-prompt] Saved prompt", { filePath, length: args.prompt.length, mode })
|
||||
|
||||
return `Council prompt saved to: ${filePath}
|
||||
return `Council prompt saved to: ${filePath} (mode: ${mode})
|
||||
|
||||
Use this path in each council member's task() call:
|
||||
- prompt: "Read ${filePath} for your instructions."
|
||||
|
||||
Reference in New Issue
Block a user