Add universal YAML front-matter header to all synthesis.md outputs (council,
question, date, members, session_ids, mode, intent, responded count).
AUDIT: structured finding format with required fields (severity, confidence,
members reported, evidence, impact, fix direction). New cross-check flow asks
user to verify minority/solo findings via a second council round before
proceeding to findings processing.
Also fix prompt-file cleanup: skip cleanupPromptFile when movePromptFile
already succeeded.
Interactive prompt: Athena now asks the user whether to retry failed members
or skip and synthesize with available results. Recommends based on success ratio.
Non-interactive prompt: always proceeds to synthesis with available results,
sets status to partial/failed accordingly.
Add optional ttl field to BackgroundTask/LaunchInput. Council launcher
passes COUNCIL_MEMBER_TTL_MS (2 hours) per member. Task poller uses
task.ttl ?? TASK_TTL_MS, replacing the blanket TTL_EXEMPT_AGENTS bypass
for council members with a bounded timeout.
Co-authored-by: Vacbo <2445>
Remove blind 30-min setTimeout cleanup from prepare_council_prompt. Prompt
files now stay until council_finalize archives them in a try/finally block.
Extract shared resolvePromptTempFilePath helper used by both movePromptFile
and the new cleanupPromptFile safety net.
Co-authored-by: Vacbo <2445>
Resolve symlinks via realpathSync before checking path policy, preventing
symlink-based escapes from .sisyphus/ sandbox. Walks up to nearest existing
ancestor for new-file writes. Adds 7 tests including real-filesystem symlink
scenarios.
Co-authored-by: Vacbo <2445>
Add 7 guardrails to stop Athena from acting as an implementation
orchestrator when receiving feature requests:
- Role + Tool Firewall: task() exclusively for council, todowrite banned
- Implementation-first pre-check: highest precedence in routing
- Expanded Category B: broader signals (build, make a feature, etc.)
- Strengthened Category F: vague features = ambiguous by default
- Handoff context integrity: no fabricated specs in switch_agent
- Routing read budget: 3-file cap for routing context
- New constraints: task() scope, todowrite ban, drift detection
Fixes bug where Athena created 9 todos and orchestrated implementation
via task() instead of routing to Prometheus/Sisyphus.
- Fix misleading background_wait instructions to show loop pattern with
remaining_task_ids (race semantics, not block-all)
- Fix wrong Gemini model string: gemini-3-pro-preview → gemini-3-pro
- Add getMainSessionID() fallback when input.sessionID is undefined
- Narrow .gitignore packages/ to only ignore built binaries
- Fix contradictory config doc: non_interactive_members 'all' → 'custom'
- Add athena-junior to keyword-detector exclusion check
- Add .trim() before .toUpperCase() in resolveCouncilIntent
- Update snapshots for model string change
Added missing documentation for:
- Council resilience settings (retry_on_fail, stuck_threshold, member_max_running)
- bulk_launch config for launch strategy
- Council tools (prepare_council_prompt, athena_council, council_finalize)
- Council archives (.sisyphus/athena/)
- Force-background and TTL exemption for athena-junior
- Council-member agent overrides and tool allowlist
- How to invoke athena-junior (task() and CLI)
- Updated agent list to include athena and council-member
- Added Athena subsections to table of contents
- Auto-generated schema.json update for bulk_launch field
The background_wait instruction was only shown when the caller passed
run_in_background=false (forced case). But callers passing true also need
the guidance since they were polling background_output instead. Now
athena-junior always gets background_wait instructions regardless of how
it was launched.
When athena-junior is force-backgrounded (caller passed run_in_background=false),
the response now instructs the caller to use background_wait instead of
background_output, preventing repeated polling loops.
Council sessions are long-running: athena-junior launches members then
waits for them via background_wait. Two changes prevent premature kills:
- Force run_in_background=true when subagent_type resolves to athena-junior,
avoiding the 10-minute sync poll timeout (MAX_POLL_TIME_MS)
- Exempt athena-junior from the 30-minute TASK_TTL_MS hard cutoff since
council members have their own independent TTLs
- Fix missing bulk_launch field in AthenaOverrideConfigSchema (type error)
New config: agents.athena.bulk_launch (boolean, default false)
- false: launch members one-by-one via task() for TUI inspectability
- true: launch all members at once via athena_council tool
Prompt uses {BULK_LAUNCH_STEP_5_2} placeholder injected at runtime
based on config value. Schema, caller, and tests updated.
The config.tools boolean false wasn't blocking plugin-registered tools.
Add prepare_council_prompt, council_finalize, athena_council to global
permission deny — same pattern as task: deny. Per-agent allow on
athena/athena-junior overrides the global deny.
Council tools (prepare_council_prompt, council_finalize, athena_council) are
globally disabled and only re-enabled for athena and athena-junior. Athena
was missing athena_council — now both agents have symmetric access.
Also fix parity test to include council_finalize and athena_council in
ATHENA_HANDLER_GRANTS for complete coverage.
Keep the council result JSON lean as a metadata envelope. Full synthesis
is already persisted at {archive_dir}/synthesis.md — duplicating it in
the JSON created noise that obscured structural fields like archive_dir.
Also instructs athena-junior to remind the caller to read the full
synthesis and member responses from the archive directory.
Athena primary should not be routable via switch_agent or appear in the
delegation table. Only athena-junior (subagent) remains delegatable via task().
- Remove athena from ALLOWED_AGENTS and DESCRIPTION in switch-agent tool
- Remove ATHENA_PROMPT_METADATA from agentMetadata, agent.ts, barrel export
- Update switch-agent test to assert athena rejection
- Remove ATHENA_PROMPT_METADATA test block
- Create src/tools/athena-council/ with council-launcher, tool factory, types
- Launch all council members in parallel via BackgroundManager with writeOutputToFile: true
- Wire tool into registry with backgroundManager + councilConfig dependencies
- Grant athena-junior athena_council permission, remove task permission
- Update non-interactive prompt to use athena_council instead of task tool
- Add explicit stop-after-result instruction to prevent post-output text
- 23 tests (14 tool + 9 launcher) using real temp files, no mock.module
Split the Athena council orchestrator into two distinct agents:
- athena: primary mode, interactive prompt with Question tool and switch_agent
- athena-junior: subagent mode, non-interactive prompt with structured JSON output
Key changes:
- Create athena-junior-agent.ts factory (mode=subagent, denies question+call_omo_agent)
- Revert athena agent.ts to primary mode (no env var switching)
- Make buildAthenaRuntimeGuidance mode-aware (strips action_paths for non-interactive)
- Add mode parameter to council_finalize tool
- Register athena-junior in builtin-agents, tool-config, model-requirements
- Replace "athena" with "athena-junior" in call_omo_agent ALLOWED_AGENTS
- Update all tests for new architecture
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Add 4 new .replace() calls for NON_INTERACTIVE_MODE, NON_INTERACTIVE_MEMBERS,
NON_INTERACTIVE_MEMBER_LIST, and BACKGROUND_WAIT_TIMEOUT_MS. Pass athena
non-interactive config from agent-config-handler to createBuiltinAgents.
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
The general-agents.ts isPrimaryAgent check only considered mode=primary,
causing Athena (now mode=all) to lose uiSelectedModel resolution.
Also adds metadata tests for non-interactive triggers.
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Athena misinterpreted generic per-finding option labels as execution agent names. Rewrite Step 3 "Mode: One by one" to use descriptive remediation approach labels derived from synthesis, add instruction block clarifying options vs execution methods, and show all three cases (multiple/single/no fix suggestions) in the example.