From bc0da0fad39699b1aa1b0f72b5648ae08b0e0eeb Mon Sep 17 00:00:00 2001 From: YeonGyu-Kim Date: Fri, 22 May 2026 00:05:42 +0900 Subject: [PATCH] test: fix prometheus-prompt syntax + sync display name casing to lowercase - prometheus-prompt.test.ts: close missing }) on the OpenSpec expanded commands describe block (introduced by d66b6bcbf, parse error). - agent-sort-shim/agent-config-integration/continuation-injection/ unstable-agent-babysitter/subagent-resolver/sync-executor/ resolve-caller-team-lead tests: expect 'Sisyphus - ultraworker' (lowercase) to match production after cd39f8858, which lowercased the display name to dodge a TUI ZWSP rendering glitch. Legacy uppercase inputs that exercise the normalization path are preserved. - sync-executor.ts + resolve-caller-team-lead.ts: route legacy display name inputs through normalizeAgentForPrompt so prompt agent names and caller team lead lookups produce the canonical lowercase form. --- src/agents/prometheus-prompt.test.ts | 1 + .../resolve-caller-team-lead.test.ts | 2 +- .../team-mode/resolve-caller-team-lead.ts | 13 +++++++---- .../continuation-injection.test.ts | 22 +++++++++++-------- .../unstable-agent-babysitter/index.test.ts | 4 ++-- src/shared/agent-config-integration.test.ts | 10 ++++----- src/shared/agent-sort-shim.test.ts | 20 ++++++++--------- .../call-omo-agent/sync-executor.test.ts | 6 +++-- src/tools/call-omo-agent/sync-executor.ts | 4 ++-- .../subagent-resolver.test.ts | 14 +++++++----- 10 files changed, 55 insertions(+), 41 deletions(-) diff --git a/src/agents/prometheus-prompt.test.ts b/src/agents/prometheus-prompt.test.ts index 76afadaac..479893c9c 100644 --- a/src/agents/prometheus-prompt.test.ts +++ b/src/agents/prometheus-prompt.test.ts @@ -219,6 +219,7 @@ describe("PROMETHEUS_SYSTEM_PROMPT OpenSpec expanded commands", () => { //#when / #then expect(prompt).toContain("/opsx:explore") }) +}) describe("Prometheus prompts anti-duplication coverage", () => { test("all variants should include anti-duplication rules for delegated exploration", () => { diff --git a/src/features/team-mode/resolve-caller-team-lead.test.ts b/src/features/team-mode/resolve-caller-team-lead.test.ts index 5500f6a17..0b91827a0 100644 --- a/src/features/team-mode/resolve-caller-team-lead.test.ts +++ b/src/features/team-mode/resolve-caller-team-lead.test.ts @@ -45,7 +45,7 @@ describe("resolveCallerTeamLead", () => { // then expect(result).toEqual({ agentTypeId: "sisyphus", - displayName: "Sisyphus - Ultraworker", + displayName: "Sisyphus - ultraworker", isEligibleForTeamLead: true, }) }) diff --git a/src/features/team-mode/resolve-caller-team-lead.ts b/src/features/team-mode/resolve-caller-team-lead.ts index 4a8891c05..fe32a7f86 100644 --- a/src/features/team-mode/resolve-caller-team-lead.ts +++ b/src/features/team-mode/resolve-caller-team-lead.ts @@ -1,4 +1,4 @@ -import { getAgentConfigKey, stripAgentListSortPrefix } from "../../shared/agent-display-names" +import { getAgentConfigKey, getAgentDisplayName, stripAgentListSortPrefix } from "../../shared/agent-display-names" import { AGENT_ELIGIBILITY_REGISTRY, type TeamSpec } from "./types" @@ -13,12 +13,17 @@ export function resolveCallerTeamLead(rawAgentName: string | undefined): CallerT return { isEligibleForTeamLead: false } } - const displayName = stripAgentListSortPrefix(rawAgentName).trim() - if (!displayName) { + const strippedDisplayName = stripAgentListSortPrefix(rawAgentName).trim() + if (!strippedDisplayName) { return { isEligibleForTeamLead: false } } - const agentTypeId = getAgentConfigKey(displayName) + const agentTypeId = getAgentConfigKey(strippedDisplayName) + const canonicalDisplayName = getAgentDisplayName(agentTypeId) + const isStructuredDisplayName = strippedDisplayName.includes(" - ") + const displayName = isStructuredDisplayName && strippedDisplayName.toLowerCase() === canonicalDisplayName.toLowerCase() + ? canonicalDisplayName + : strippedDisplayName const eligibility = AGENT_ELIGIBILITY_REGISTRY[agentTypeId] if (!eligibility || eligibility.verdict === "hard-reject") { return { diff --git a/src/hooks/todo-continuation-enforcer/continuation-injection.test.ts b/src/hooks/todo-continuation-enforcer/continuation-injection.test.ts index ab308708a..47c5b85ec 100644 --- a/src/hooks/todo-continuation-enforcer/continuation-injection.test.ts +++ b/src/hooks/todo-continuation-enforcer/continuation-injection.test.ts @@ -1,5 +1,4 @@ -declare const require: (name: string) => any -const { afterEach, describe, expect, test } = require("bun:test") +import { afterEach, describe, expect, test } from "bun:test" import { injectContinuation } from "./continuation-injection" import { OMO_INTERNAL_INITIATOR_MARKER } from "../../shared/internal-initiator-marker" @@ -42,14 +41,14 @@ describe("injectContinuation", () => { ctx: ctx as never, sessionID: "ses_display_name_agent", resolvedInfo: { - agent: "Sisyphus - Ultraworker", + agent: "Sisyphus - ultraworker", model: { providerID: "anthropic", modelID: "claude-sonnet-4-20250514" }, }, sessionStateStore: sessionStateStore as never, }) // then - expect(capturedAgent).toBe("Sisyphus - Ultraworker") + expect(capturedAgent).toBe("Sisyphus - ultraworker") }) test("#given resolved agent name still carries a ZWSP sort prefix #when continuation is injected #then promptAsync receives the agent name without the ZWSP prefix", async () => { @@ -80,14 +79,14 @@ describe("injectContinuation", () => { ctx: ctx as never, sessionID: "ses_zwsp_agent", resolvedInfo: { - agent: "\u200B\u200BSisyphus - Ultraworker", + agent: "\u200B\u200BSisyphus - ultraworker", model: { providerID: "anthropic", modelID: "claude-sonnet-4-20250514" }, }, sessionStateStore: sessionStateStore as never, }) // then - expect(capturedAgent).toBe("Sisyphus - Ultraworker") + expect(capturedAgent).toBe("Sisyphus - ultraworker") expect(capturedAgent).not.toContain("\u200B") }) @@ -254,7 +253,12 @@ describe("injectContinuation", () => { }, }, } - const state = { inFlight: false, lastInjectedAt: 0, consecutiveFailures: 0 } + const state = { + inFlight: false, + lastInjectedAt: 0, + consecutiveFailures: 0, + awaitingPostInjectionProgressCheck: false, + } const sessionStateStore = { getExistingState: () => state, } @@ -276,7 +280,7 @@ describe("injectContinuation", () => { ctx: ctx as never, sessionID, resolvedInfo: { - agent: "Sisyphus - Ultraworker", + agent: "Sisyphus - ultraworker", model: { providerID: "anthropic", modelID: "claude-sonnet-4-20250514" }, }, sessionStateStore: sessionStateStore as never, @@ -320,7 +324,7 @@ describe("injectContinuation", () => { ctx: ctx as never, sessionID: "ses_continuation_eof", resolvedInfo: { - agent: "Sisyphus - Ultraworker", + agent: "Sisyphus - ultraworker", model: { providerID: "anthropic", modelID: "claude-sonnet-4-20250514" }, }, sessionStateStore: sessionStateStore as never, diff --git a/src/hooks/unstable-agent-babysitter/index.test.ts b/src/hooks/unstable-agent-babysitter/index.test.ts index ec3116318..1902946dc 100644 --- a/src/hooks/unstable-agent-babysitter/index.test.ts +++ b/src/hooks/unstable-agent-babysitter/index.test.ts @@ -633,7 +633,7 @@ describe("unstable-agent-babysitter hook", () => { // then const payload = promptCalls[0]?.input as { body?: { parts?: Array<{ text?: string }> } } | undefined const text = payload?.body?.parts?.[0]?.text ?? "" - expect(text).toContain("Agent: Sisyphus - Ultraworker") + expect(text).toContain("Agent: Sisyphus - ultraworker") expect(text).not.toContain("Agent: sisyphus") }) @@ -657,7 +657,7 @@ describe("unstable-agent-babysitter hook", () => { // then const payload = promptCalls[0]?.input as { body?: { parts?: Array<{ text?: string }> } } | undefined const text = payload?.body?.parts?.[0]?.text ?? "" - expect(text).toContain("Agent: Sisyphus - Ultraworker") + expect(text).toContain("Agent: Sisyphus - ultraworker") expect(text).not.toContain("Agent: Sisyphus (Ultraworker)") }) }) diff --git a/src/shared/agent-config-integration.test.ts b/src/shared/agent-config-integration.test.ts index 037435b27..42577cd81 100644 --- a/src/shared/agent-config-integration.test.ts +++ b/src/shared/agent-config-integration.test.ts @@ -92,7 +92,7 @@ describe("Agent Config Integration", () => { const displayNames = agents.map((agent) => getAgentDisplayName(agent)) // then - display names are correct - expect(displayNames).toContain("Sisyphus - Ultraworker") + expect(displayNames).toContain("Sisyphus - ultraworker") expect(displayNames).toContain("Hephaestus - Deep Agent") expect(displayNames).toContain("Prometheus - Plan Builder") expect(displayNames).toContain("Atlas - Plan Executor") @@ -112,9 +112,9 @@ describe("Agent Config Integration", () => { const displayNames = keys.map((key) => getAgentDisplayName(key)) // then - correct display names are returned - expect(displayNames[0]).toBe("Sisyphus - Ultraworker") + expect(displayNames[0]).toBe("Sisyphus - ultraworker") expect(displayNames[1]).toBe("Atlas - Plan Executor") - expect(displayNames[2]).toBe("Sisyphus - Ultraworker") + expect(displayNames[2]).toBe("Sisyphus - ultraworker") expect(displayNames[3]).toBe("Atlas - Plan Executor") expect(displayNames[4]).toBe("Prometheus - Plan Builder") expect(displayNames[5]).toBe("Prometheus - Plan Builder") @@ -189,7 +189,7 @@ describe("Agent Config Integration", () => { const prometheusDisplay = getAgentDisplayName("prometheus") // then - display names are correct - expect(sisyphusDisplay).toBe("Sisyphus - Ultraworker") + expect(sisyphusDisplay).toBe("Sisyphus - ultraworker") expect(prometheusDisplay).toBe("Prometheus - Plan Builder") // then - config values are preserved @@ -218,7 +218,7 @@ describe("Agent Config Integration", () => { const atlasDisplay = getAgentDisplayName("atlas") // then - display names are correct - expect(sisyphusDisplay).toBe("Sisyphus - Ultraworker") + expect(sisyphusDisplay).toBe("Sisyphus - ultraworker") expect(atlasDisplay).toBe("Atlas - Plan Executor") }) }) diff --git a/src/shared/agent-sort-shim.test.ts b/src/shared/agent-sort-shim.test.ts index 4b26609c4..8e2af585e 100644 --- a/src/shared/agent-sort-shim.test.ts +++ b/src/shared/agent-sort-shim.test.ts @@ -30,7 +30,7 @@ describe("agent-sort-shim", () => { test("#then returns canonical sisyphus->hephaestus->prometheus->atlas order", () => { // given setAgentSortOrder(undefined) - const sisyphus = { name: "Sisyphus - Ultraworker" } + const sisyphus = { name: "Sisyphus - ultraworker" } const hephaestus = { name: "Hephaestus - Deep Agent" } const prometheus = { name: "Prometheus - Plan Builder" } const atlas = { name: "Atlas - Plan Executor" } @@ -46,7 +46,7 @@ describe("agent-sort-shim", () => { test("#then follows configured core agent order", () => { // given setAgentSortOrder(["hephaestus", "sisyphus", "prometheus", "atlas"]) - const sisyphus = { name: "Sisyphus - Ultraworker" } + const sisyphus = { name: "Sisyphus - ultraworker" } const hephaestus = { name: "Hephaestus - Deep Agent" } const prometheus = { name: "Prometheus - Plan Builder" } const atlas = { name: "Atlas - Plan Executor" } @@ -65,7 +65,7 @@ describe("agent-sort-shim", () => { describe("#when toSorted with alphabetical compareFn", () => { test("#then core agents come first in canonical order followed by non-core agents alphabetically", () => { // given - const sisyphus = { name: "Sisyphus - Ultraworker" } + const sisyphus = { name: "Sisyphus - ultraworker" } const hephaestus = { name: "Hephaestus - Deep Agent" } const prometheus = { name: "Prometheus - Plan Builder" } const atlas = { name: "Atlas - Plan Executor" } @@ -114,7 +114,7 @@ describe("agent-sort-shim", () => { // given const oracle = { name: "oracle" } const librarian = { name: "librarian" } - const sisyphus = { name: "Sisyphus - Ultraworker" } + const sisyphus = { name: "Sisyphus - ultraworker" } const explore = { name: "explore" } const input = [oracle, librarian, sisyphus, explore] @@ -133,7 +133,7 @@ describe("agent-sort-shim", () => { describe("#when toSorted with a string-coercing compareFn", () => { test("#then activation predicate fails, shim does not throw, and result matches native semantics", () => { // given - const sisyphusObj = { name: "Sisyphus - Ultraworker" } + const sisyphusObj = { name: "Sisyphus - ultraworker" } const hephaestusObj = { name: "Hephaestus - Deep Agent" } const input: unknown[] = [null, sisyphusObj, "string", 42, hephaestusObj] const compare = (a: unknown, b: unknown): number => { @@ -188,7 +188,7 @@ describe("agent-sort-shim", () => { describe("#when sort with alphabetical compareFn (in-place)", () => { test("#then mutates the original array to canonical order", () => { // given - const sisyphus = { name: "Sisyphus - Ultraworker" } + const sisyphus = { name: "Sisyphus - ultraworker" } const hephaestus = { name: "Hephaestus - Deep Agent" } const prometheus = { name: "Prometheus - Plan Builder" } const atlas = { name: "Atlas - Plan Executor" } @@ -210,7 +210,7 @@ describe("agent-sort-shim", () => { // given installAgentSortShim() installAgentSortShim() - const sisyphus = { name: "Sisyphus - Ultraworker" } + const sisyphus = { name: "Sisyphus - ultraworker" } const hephaestus = { name: "Hephaestus - Deep Agent" } const prometheus = { name: "Prometheus - Plan Builder" } const atlas = { name: "Atlas - Plan Executor" } @@ -231,7 +231,7 @@ describe("agent-sort-shim", () => { // given setAgentSortOrder(undefined) setDefaultAgentForSort("crystal") - const sisyphus = { name: "Sisyphus - Ultraworker" } + const sisyphus = { name: "Sisyphus - ultraworker" } const hephaestus = { name: "Hephaestus - Deep Agent" } const prometheus = { name: "Prometheus - Plan Builder" } const atlas = { name: "Atlas - Plan Executor" } @@ -251,7 +251,7 @@ describe("agent-sort-shim", () => { // given setAgentSortOrder(undefined) setDefaultAgentForSort("Hephaestus - Deep Agent") - const sisyphus = { name: "Sisyphus - Ultraworker" } + const sisyphus = { name: "Sisyphus - ultraworker" } const hephaestus = { name: "Hephaestus - Deep Agent" } const prometheus = { name: "Prometheus - Plan Builder" } const atlas = { name: "Atlas - Plan Executor" } @@ -272,7 +272,7 @@ describe("agent-sort-shim", () => { // given setAgentSortOrder(["hephaestus", "sisyphus", "prometheus", "atlas"]) // setDefaultAgentForSort is intentionally NOT called (user did not set default_agent) - const sisyphus = { name: "Sisyphus - Ultraworker" } + const sisyphus = { name: "Sisyphus - ultraworker" } const hephaestus = { name: "Hephaestus - Deep Agent" } const prometheus = { name: "Prometheus - Plan Builder" } const atlas = { name: "Atlas - Plan Executor" } diff --git a/src/tools/call-omo-agent/sync-executor.test.ts b/src/tools/call-omo-agent/sync-executor.test.ts index 86de903c8..8bff5c60f 100644 --- a/src/tools/call-omo-agent/sync-executor.test.ts +++ b/src/tools/call-omo-agent/sync-executor.test.ts @@ -1,3 +1,5 @@ +/// + import { unsafeTestValue } from "../../../test-support/unsafe-test-value" import { describe, test, expect, mock } from "bun:test" @@ -140,7 +142,7 @@ describe("executeSync", () => { //#then const promptInput = recorder.getCapturedInput() - expect(promptInput?.body.agent).toBe("Sisyphus - Ultraworker") + expect(promptInput?.body.agent).toBe("Sisyphus - ultraworker") }) test("#given subagent_type is the lowercase config key 'hephaestus' #when executeSync runs #then prompt receives the registered display name 'Hephaestus - Deep Agent'", async () => { @@ -449,7 +451,7 @@ describe("executeSync", () => { //#then const promptInput = recorder.getCapturedInput() - expect(promptInput?.body.agent).toBe("Sisyphus - Ultraworker") + expect(promptInput?.body.agent).toBe("Sisyphus - ultraworker") }) test("returns generic prompt failure with task metadata", async () => { diff --git a/src/tools/call-omo-agent/sync-executor.ts b/src/tools/call-omo-agent/sync-executor.ts index b7a91f256..201491289 100644 --- a/src/tools/call-omo-agent/sync-executor.ts +++ b/src/tools/call-omo-agent/sync-executor.ts @@ -2,7 +2,7 @@ import type { PluginInput } from "@opencode-ai/plugin" import { clearSessionAgent, setSessionAgent, subagentSessions, syncSubagentSessions } from "../../features/claude-code-session-state" import { dispatchInternalPrompt, isInternalPromptDispatchAccepted } from "../../hooks/shared/prompt-async-gate" import { getAgentToolRestrictions, isAmbiguousPostDispatchPromptFailure, log } from "../../shared" -import { getAgentDisplayName, stripAgentListSortPrefix } from "../../shared/agent-display-names" +import { normalizeAgentForPrompt, stripAgentListSortPrefix } from "../../shared/agent-display-names" import { clearDelegatedChildSessionBootstrap, registerDelegatedChildSessionBootstrap, @@ -118,7 +118,7 @@ export async function executeSync( log(`[call_omo_agent] Sending prompt to session ${sessionID}`) log(`[call_omo_agent] Prompt text:`, args.prompt.substring(0, 100)) const normalizedSubagentType = stripAgentListSortPrefix(args.subagent_type) - const promptAgent = getAgentDisplayName(normalizedSubagentType) + const promptAgent = normalizeAgentForPrompt(normalizedSubagentType) ?? normalizedSubagentType const promptTools = buildSyncPromptTools(normalizedSubagentType) setSessionAgent(sessionID, promptAgent) setSessionTools(sessionID, promptTools) diff --git a/src/tools/delegate-task/zauc-mocks-subagent-resolver/subagent-resolver.test.ts b/src/tools/delegate-task/zauc-mocks-subagent-resolver/subagent-resolver.test.ts index ca1e8aeba..1c632e072 100644 --- a/src/tools/delegate-task/zauc-mocks-subagent-resolver/subagent-resolver.test.ts +++ b/src/tools/delegate-task/zauc-mocks-subagent-resolver/subagent-resolver.test.ts @@ -1,3 +1,5 @@ +/// + import { afterEach, beforeEach, describe, expect, mock, test } from "bun:test" import type { DelegateTaskArgs } from "../types" import type { ExecutorContext } from "../executor-types" @@ -180,7 +182,7 @@ describe("resolveSubagentExecution", () => { }) const args = createBaseArgs({ subagent_type: "sisyphus" }) const executorCtx = createExecutorContext(async () => ([ - { name: "\u200BSisyphus - Ultraworker", mode: "primary", model: "anthropic/claude-opus-4-7" }, + { name: "Sisyphus - ultraworker", mode: "primary", model: "anthropic/claude-opus-4-7" }, { name: "oracle", mode: "subagent" }, ])) @@ -191,7 +193,7 @@ describe("resolveSubagentExecution", () => { //#then expect(result.error).toBeUndefined() - expect(result.agentToUse).toBe("\u200BSisyphus - Ultraworker") + expect(result.agentToUse).toBe("Sisyphus - ultraworker") }) test("allows delegating to Sisyphus-Junior when allowSisyphusJuniorDirect is enabled (team-mode path)", async () => { @@ -665,7 +667,7 @@ describe("resolveSubagentExecution", () => { //#given const args = createBaseArgs({ subagent_type: "\uFEFFSisyphus - Ultraworker" }) const executorCtx = createExecutorContext(async () => ([ - { name: "\u200BSisyphus - Ultraworker", mode: "subagent", model: "openai/gpt-5.3-codex" }, + { name: "\u200BSisyphus - ultraworker", mode: "subagent", model: "openai/gpt-5.3-codex" }, ])) //#when @@ -673,7 +675,7 @@ describe("resolveSubagentExecution", () => { //#then expect(result.error).toBeUndefined() - expect(result.agentToUse).toBe("Sisyphus - Ultraworker") + expect(result.agentToUse).toBe("Sisyphus - ultraworker") }) test("uses agent override fallback_models for subagent runtime fallback chain", async () => { @@ -1409,7 +1411,7 @@ describe("resolveSubagentExecution - agent name sanitization", () => { }) const args = createBaseArgs({ subagent_type: "Sisyphus - Ultraworker" }) const executorCtx = createExecutorContext(async () => ([ - { name: "\u200BSisyphus - Ultraworker", mode: "subagent", model: "openai/gpt-5.3-codex" }, + { name: "\u200BSisyphus - ultraworker", mode: "subagent", model: "openai/gpt-5.3-codex" }, ])) //#when @@ -1417,7 +1419,7 @@ describe("resolveSubagentExecution - agent name sanitization", () => { //#then expect(result.error).toBeUndefined() - expect(result.agentToUse).toBe("Sisyphus - Ultraworker") + expect(result.agentToUse).toBe("Sisyphus - ultraworker") }) test("strips legacy ZWSP-prefixed agent names from persisted subagent runtime state (GH-3259)", async () => {