fix(athena): address 9 council-audit findings — dead code, bugs, and hardening

Fixes from multi-model council audit (7 members, 19 findings, 9 selected):

- Use parseModelString() for cross-provider Anthropic thinking config (#3)
- Update stale AGENTS.md athena directory listing (#4)
- Replace prompt in appendMissingCouncilPrompt instead of appending (#5)
- Extract duplicated session cleanup logic in agent-switch hook (#6)
- Surface skipped council members when >=2 valid members exist (#9)
- Expand fallback handoff regex with negation guards (#11)
- Remove dead council-member agent from agentSources and tests (#12)
- Make runtime council member duplicate check case-insensitive (#14)
- Fix false-positive schema tests by adding required name field (#18)
This commit is contained in:
ismeth
2026-02-20 16:10:08 +01:00
committed by YeonGyu-Kim
parent 4ca623c29c
commit 9f541ed3ee
12 changed files with 99 additions and 46 deletions
@@ -39,14 +39,15 @@ Each member requires \`model\` (\`"provider/model-id"\` format) and \`name\` (di
After informing the user, **end your turn**. Do NOT try to work around this by using generic agents, the council-member agent, or any other fallback.`
/**
* Replaces Athena's prompt with a guard that tells the user to configure council members.
* Replaces Athena's orchestration prompt with a guard that tells the user to configure council members.
* The original prompt is discarded to avoid contradictory instructions.
* Used when Athena is registered but no valid council config exists.
*/
export function appendMissingCouncilPrompt(
athenaConfig: AgentConfig,
skippedMembers?: Array<{ name: string; reason: string }>,
): AgentConfig {
let prompt = (athenaConfig.prompt ?? "") + MISSING_COUNCIL_PROMPT
let prompt = MISSING_COUNCIL_PROMPT
if (skippedMembers && skippedMembers.length > 0) {
const skipDetails = skippedMembers.map((m) => `- **${m.name}**: ${m.reason}`).join("\n")
@@ -27,6 +27,7 @@ export function registerCouncilMemberAgents(
const agents: Record<string, AgentConfig> = {}
const registeredKeys: string[] = []
const skippedMembers: SkippedMember[] = []
const registeredNamesLower = new Set<string>()
for (const member of councilConfig.members) {
const parsed = parseModelString(member.model)
@@ -40,16 +41,16 @@ export function registerCouncilMemberAgents(
}
const key = getCouncilMemberAgentKey(member)
const nameLower = member.name.toLowerCase()
if (agents[key]) {
if (registeredNamesLower.has(nameLower)) {
skippedMembers.push({
name: member.name,
reason: `Duplicate name: '${member.name}' already registered`,
reason: `Duplicate name: '${member.name}' already registered (case-insensitive match)`,
})
log("[council-member-agents] Skipping duplicate council member name", {
name: member.name,
model: member.model,
existingModel: agents[key].model ?? "unknown",
})
continue
}
@@ -66,6 +67,7 @@ export function registerCouncilMemberAgents(
}
registeredKeys.push(key)
registeredNamesLower.add(nameLower)
log("[council-member-agents] Registered council member agent", {
key,