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.
This commit is contained in:
YeonGyu-Kim
2026-05-22 00:05:42 +09:00
parent beed9e8906
commit bc0da0fad3
10 changed files with 55 additions and 41 deletions
+1
View File
@@ -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", () => {
@@ -45,7 +45,7 @@ describe("resolveCallerTeamLead", () => {
// then
expect(result).toEqual({
agentTypeId: "sisyphus",
displayName: "Sisyphus - Ultraworker",
displayName: "Sisyphus - ultraworker",
isEligibleForTeamLead: true,
})
})
@@ -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 {
@@ -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,
@@ -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)")
})
})
+5 -5
View File
@@ -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")
})
})
+10 -10
View File
@@ -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" }
@@ -1,3 +1,5 @@
/// <reference types="bun-types" />
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 () => {
+2 -2
View File
@@ -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)
@@ -1,3 +1,5 @@
/// <reference types="bun-types" />
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 () => {