diff --git a/src/agents/sisyphus-junior.ts b/src/agents/sisyphus-junior.ts
deleted file mode 100644
index 4bb419df..00000000
--- a/src/agents/sisyphus-junior.ts
+++ /dev/null
@@ -1,134 +0,0 @@
-import type { AgentConfig } from "@opencode-ai/sdk"
-import type { AgentMode } from "./types"
-import { isGptModel } from "./types"
-import type { AgentOverrideConfig } from "../config/schema"
-import {
- createAgentToolRestrictions,
- type PermissionValue,
-} from "../shared/permission-compat"
-
-const MODE: AgentMode = "subagent"
-
-function buildTodoDisciplineSection(useTaskSystem: boolean): string {
- if (useTaskSystem) {
- return `
-TASK OBSESSION (NON-NEGOTIABLE):
-- 2+ steps → TaskCreate FIRST, atomic breakdown
-- TaskUpdate(status="in_progress") before starting (ONE at a time)
-- TaskUpdate(status="completed") IMMEDIATELY after each step
-- NEVER batch completions
-
-No tasks on multi-step work = INCOMPLETE WORK.
-`
- }
-
- return `
-TODO OBSESSION (NON-NEGOTIABLE):
-- 2+ steps → todowrite FIRST, atomic breakdown
-- Mark in_progress before starting (ONE at a time)
-- Mark completed IMMEDIATELY after each step
-- NEVER batch completions
-
-No todos on multi-step work = INCOMPLETE WORK.
-`
-}
-
-function buildSisyphusJuniorPrompt(useTaskSystem: boolean, promptAppend?: string): string {
- const todoDiscipline = buildTodoDisciplineSection(useTaskSystem)
- const verificationText = useTaskSystem ? "All tasks marked completed" : "All todos marked completed"
-
- const prompt = `
-Sisyphus-Junior - Focused executor from OhMyOpenCode.
-Execute tasks directly. NEVER delegate or spawn other agents.
-
-
-
-BLOCKED ACTIONS (will fail if attempted):
-- task tool: BLOCKED
-- delegate_task tool: BLOCKED
-
-ALLOWED: call_omo_agent - You CAN spawn explore/librarian agents for research.
-You work ALONE for implementation. No delegation of implementation tasks.
-
-
-${todoDiscipline}
-
-
-Task NOT complete without:
-- lsp_diagnostics clean on changed files
-- Build passes (if applicable)
-- ${verificationText}
-
-
-`
-
- if (!promptAppend) return prompt
- return prompt + "\n\n" + promptAppend
-}
-
-// Core tools that Sisyphus-Junior must NEVER have access to
-// Note: call_omo_agent is ALLOWED so subagents can spawn explore/librarian
-const BLOCKED_TOOLS = ["task", "delegate_task"]
-
-export const SISYPHUS_JUNIOR_DEFAULTS = {
- model: "anthropic/claude-sonnet-4-5",
- temperature: 0.1,
-} as const
-
-export function createSisyphusJuniorAgentWithOverrides(
- override: AgentOverrideConfig | undefined,
- systemDefaultModel?: string,
- useTaskSystem = false
-): AgentConfig {
- if (override?.disable) {
- override = undefined
- }
-
- const model = override?.model ?? systemDefaultModel ?? SISYPHUS_JUNIOR_DEFAULTS.model
- const temperature = override?.temperature ?? SISYPHUS_JUNIOR_DEFAULTS.temperature
-
- const promptAppend = override?.prompt_append
- const prompt = buildSisyphusJuniorPrompt(useTaskSystem, promptAppend)
-
- const baseRestrictions = createAgentToolRestrictions(BLOCKED_TOOLS)
-
- const userPermission = (override?.permission ?? {}) as Record
- const basePermission = baseRestrictions.permission
- const merged: Record = { ...userPermission }
- for (const tool of BLOCKED_TOOLS) {
- merged[tool] = "deny"
- }
- merged.call_omo_agent = "allow"
- const toolsConfig = { permission: { ...merged, ...basePermission } }
-
- const base: AgentConfig = {
- description: override?.description ??
- "Focused task executor. Same discipline, no delegation. (Sisyphus-Junior - OhMyOpenCode)",
- mode: MODE,
- model,
- temperature,
- maxTokens: 64000,
- prompt,
- color: override?.color ?? "#20B2AA",
- ...toolsConfig,
- }
-
- if (override?.top_p !== undefined) {
- base.top_p = override.top_p
- }
-
- if (isGptModel(model)) {
- return { ...base, reasoningEffort: "medium" } as AgentConfig
- }
-
- return {
- ...base,
- thinking: { type: "enabled", budgetTokens: 32000 },
- } as AgentConfig
-}
-
-createSisyphusJuniorAgentWithOverrides.mode = MODE
diff --git a/src/agents/sisyphus-junior/default.ts b/src/agents/sisyphus-junior/default.ts
new file mode 100644
index 00000000..a234a021
--- /dev/null
+++ b/src/agents/sisyphus-junior/default.ts
@@ -0,0 +1,74 @@
+/**
+ * Default Sisyphus-Junior system prompt optimized for Claude series models.
+ *
+ * Key characteristics:
+ * - Optimized for Claude's tendency to be "helpful" by forcing explicit constraints
+ * - Strong emphasis on blocking delegation attempts
+ * - Extended reasoning context for complex tasks
+ */
+
+export function buildDefaultSisyphusJuniorPrompt(
+ useTaskSystem: boolean,
+ promptAppend?: string
+): string {
+ const todoDiscipline = buildTodoDisciplineSection(useTaskSystem)
+ const verificationText = useTaskSystem
+ ? "All tasks marked completed"
+ : "All todos marked completed"
+
+ const prompt = `
+Sisyphus-Junior - Focused executor from OhMyOpenCode.
+Execute tasks directly. NEVER delegate or spawn other agents.
+
+
+
+BLOCKED ACTIONS (will fail if attempted):
+- task tool: BLOCKED
+- delegate_task tool: BLOCKED
+
+ALLOWED: call_omo_agent - You CAN spawn explore/librarian agents for research.
+You work ALONE for implementation. No delegation of implementation tasks.
+
+
+${todoDiscipline}
+
+
+Task NOT complete without:
+- lsp_diagnostics clean on changed files
+- Build passes (if applicable)
+- ${verificationText}
+
+
+`
+
+ if (!promptAppend) return prompt
+ return prompt + "\n\n" + promptAppend
+}
+
+function buildTodoDisciplineSection(useTaskSystem: boolean): string {
+ if (useTaskSystem) {
+ return `
+TASK OBSESSION (NON-NEGOTIABLE):
+- 2+ steps → TaskCreate FIRST, atomic breakdown
+- TaskUpdate(status="in_progress") before starting (ONE at a time)
+- TaskUpdate(status="completed") IMMEDIATELY after each step
+- NEVER batch completions
+
+No tasks on multi-step work = INCOMPLETE WORK.
+`
+ }
+
+ return `
+TODO OBSESSION (NON-NEGOTIABLE):
+- 2+ steps → todowrite FIRST, atomic breakdown
+- Mark in_progress before starting (ONE at a time)
+- Mark completed IMMEDIATELY after each step
+- NEVER batch completions
+
+No todos on multi-step work = INCOMPLETE WORK.
+`
+}
diff --git a/src/agents/sisyphus-junior/gpt.ts b/src/agents/sisyphus-junior/gpt.ts
new file mode 100644
index 00000000..0a26b222
--- /dev/null
+++ b/src/agents/sisyphus-junior/gpt.ts
@@ -0,0 +1,129 @@
+/**
+ * GPT-5.2 Optimized Sisyphus-Junior System Prompt
+ *
+ * Restructured following OpenAI's GPT-5.2 Prompting Guide principles:
+ * - Explicit verbosity constraints (2-4 sentences for updates)
+ * - Scope discipline (no extra features, implement exactly what's specified)
+ * - Tool usage rules (prefer tools over internal knowledge)
+ * - Uncertainty handling (ask clarifying questions)
+ * - Compact, direct instructions
+ * - XML-style section tags for clear structure
+ *
+ * Key characteristics (from GPT 5.2 Prompting Guide):
+ * - "Stronger instruction adherence" - follows instructions more literally
+ * - "Conservative grounding bias" - prefers correctness over speed
+ * - "More deliberate scaffolding" - builds clearer plans by default
+ * - Explicit decision criteria needed (model won't infer)
+ */
+
+export function buildGptSisyphusJuniorPrompt(
+ useTaskSystem: boolean,
+ promptAppend?: string
+): string {
+ const taskDiscipline = buildGptTaskDisciplineSection(useTaskSystem)
+ const verificationText = useTaskSystem
+ ? "All tasks marked completed"
+ : "All todos marked completed"
+
+ const prompt = `
+You are Sisyphus-Junior - Focused task executor from OhMyOpenCode.
+Role: Execute tasks directly. You work ALONE.
+
+
+
+- Default: 2-4 sentences for status updates.
+- For progress: 1 sentence + current step.
+- AVOID long explanations; prefer compact bullets.
+- Do NOT rephrase the task unless semantics change.
+
+
+
+- Implement EXACTLY and ONLY what is requested.
+- No extra features, no UX embellishments, no scope creep.
+- If any instruction is ambiguous, choose the simplest valid interpretation OR ask.
+- Do NOT invent new requirements.
+- Do NOT expand task boundaries beyond what's written.
+
+
+
+BLOCKED (will fail if attempted):
+| Tool | Status |
+|------|--------|
+| task | BLOCKED |
+| delegate_task | BLOCKED |
+
+ALLOWED:
+| Tool | Usage |
+|------|-------|
+| call_omo_agent | Spawn explore/librarian for research ONLY |
+
+You work ALONE for implementation. No delegation.
+
+
+
+- If a task is ambiguous or underspecified:
+ - Ask 1-2 precise clarifying questions, OR
+ - State your interpretation explicitly and proceed with the simplest approach.
+- Never fabricate file paths, requirements, or behavior.
+- Prefer language like "Based on the request..." instead of absolute claims.
+
+
+
+- ALWAYS use tools over internal knowledge for:
+ - File contents (use Read, not memory)
+ - Current project state (use lsp_diagnostics, glob)
+ - Verification (use Bash for tests/build)
+- Parallelize independent tool calls when possible.
+
+
+${taskDiscipline}
+
+
+Task NOT complete without evidence:
+| Check | Tool | Expected |
+|-------|------|----------|
+| Diagnostics | lsp_diagnostics | ZERO errors on changed files |
+| Build | Bash | Exit code 0 (if applicable) |
+| Tracking | ${useTaskSystem ? "TaskUpdate" : "todowrite"} | ${verificationText} |
+
+**No evidence = not complete.**
+
+
+
+- Start immediately. No acknowledgments ("I'll...", "Let me...").
+- Match user's communication style.
+- Dense > verbose.
+- Use structured output (bullets, tables) over prose.
+`
+
+ if (!promptAppend) return prompt
+ return prompt + "\n\n" + promptAppend
+}
+
+function buildGptTaskDisciplineSection(useTaskSystem: boolean): string {
+ if (useTaskSystem) {
+ return `
+TASK TRACKING (NON-NEGOTIABLE):
+| Trigger | Action |
+|---------|--------|
+| 2+ steps | TaskCreate FIRST, atomic breakdown |
+| Starting step | TaskUpdate(status="in_progress") - ONE at a time |
+| Completing step | TaskUpdate(status="completed") IMMEDIATELY |
+| Batching | NEVER batch completions |
+
+No tasks on multi-step work = INCOMPLETE WORK.
+`
+ }
+
+ return `
+TODO TRACKING (NON-NEGOTIABLE):
+| Trigger | Action |
+|---------|--------|
+| 2+ steps | todowrite FIRST, atomic breakdown |
+| Starting step | Mark in_progress - ONE at a time |
+| Completing step | Mark completed IMMEDIATELY |
+| Batching | NEVER batch completions |
+
+No todos on multi-step work = INCOMPLETE WORK.
+`
+}
diff --git a/src/agents/sisyphus-junior.test.ts b/src/agents/sisyphus-junior/index.test.ts
similarity index 66%
rename from src/agents/sisyphus-junior.test.ts
rename to src/agents/sisyphus-junior/index.test.ts
index 49f0ea08..7b9128a5 100644
--- a/src/agents/sisyphus-junior.test.ts
+++ b/src/agents/sisyphus-junior/index.test.ts
@@ -1,5 +1,10 @@
import { describe, expect, test } from "bun:test"
-import { createSisyphusJuniorAgentWithOverrides, SISYPHUS_JUNIOR_DEFAULTS } from "./sisyphus-junior"
+import {
+ createSisyphusJuniorAgentWithOverrides,
+ SISYPHUS_JUNIOR_DEFAULTS,
+ getSisyphusJuniorPromptSource,
+ buildSisyphusJuniorPrompt,
+} from "./index"
describe("createSisyphusJuniorAgentWithOverrides", () => {
describe("honored fields", () => {
@@ -212,7 +217,31 @@ describe("createSisyphusJuniorAgentWithOverrides", () => {
// then
expect(result.prompt).toContain("Sisyphus-Junior")
expect(result.prompt).toContain("You work ALONE")
+ })
+
+ test("Claude model uses default prompt with BLOCKED ACTIONS section", () => {
+ // given
+ const override = { model: "anthropic/claude-sonnet-4-5" }
+
+ // when
+ const result = createSisyphusJuniorAgentWithOverrides(override)
+
+ // then
expect(result.prompt).toContain("BLOCKED ACTIONS")
+ expect(result.prompt).not.toContain("")
+ })
+
+ test("GPT model uses GPT-optimized prompt with blocked_actions section", () => {
+ // given
+ const override = { model: "openai/gpt-5.2" }
+
+ // when
+ const result = createSisyphusJuniorAgentWithOverrides(override)
+
+ // then
+ expect(result.prompt).toContain("")
+ expect(result.prompt).toContain("")
+ expect(result.prompt).toContain("")
})
test("prompt_append is added after base prompt", () => {
@@ -225,8 +254,107 @@ describe("createSisyphusJuniorAgentWithOverrides", () => {
// then
const baseEndIndex = result.prompt!.indexOf("Dense > verbose.")
const appendIndex = result.prompt!.indexOf("CUSTOM_MARKER_FOR_TEST")
- expect(baseEndIndex).not.toBe(-1) // Guard: anchor text must exist in base prompt
+ expect(baseEndIndex).not.toBe(-1)
expect(appendIndex).toBeGreaterThan(baseEndIndex)
})
})
})
+
+describe("getSisyphusJuniorPromptSource", () => {
+ test("returns 'gpt' for OpenAI models", () => {
+ // given
+ const model = "openai/gpt-5.2"
+
+ // when
+ const source = getSisyphusJuniorPromptSource(model)
+
+ // then
+ expect(source).toBe("gpt")
+ })
+
+ test("returns 'gpt' for GitHub Copilot GPT models", () => {
+ // given
+ const model = "github-copilot/gpt-4o"
+
+ // when
+ const source = getSisyphusJuniorPromptSource(model)
+
+ // then
+ expect(source).toBe("gpt")
+ })
+
+ test("returns 'default' for Claude models", () => {
+ // given
+ const model = "anthropic/claude-sonnet-4-5"
+
+ // when
+ const source = getSisyphusJuniorPromptSource(model)
+
+ // then
+ expect(source).toBe("default")
+ })
+
+ test("returns 'default' for undefined model", () => {
+ // given
+ const model = undefined
+
+ // when
+ const source = getSisyphusJuniorPromptSource(model)
+
+ // then
+ expect(source).toBe("default")
+ })
+})
+
+describe("buildSisyphusJuniorPrompt", () => {
+ test("GPT model prompt contains GPT-5.2 specific sections", () => {
+ // given
+ const model = "openai/gpt-5.2"
+
+ // when
+ const prompt = buildSisyphusJuniorPrompt(model, false)
+
+ // then
+ expect(prompt).toContain("")
+ expect(prompt).toContain("")
+ expect(prompt).toContain("")
+ expect(prompt).toContain("")
+ })
+
+ test("Claude model prompt contains Claude-specific sections", () => {
+ // given
+ const model = "anthropic/claude-sonnet-4-5"
+
+ // when
+ const prompt = buildSisyphusJuniorPrompt(model, false)
+
+ // then
+ expect(prompt).toContain("")
+ expect(prompt).toContain("")
+ expect(prompt).toContain("BLOCKED ACTIONS")
+ })
+
+ test("useTaskSystem=true includes Task_Discipline for GPT", () => {
+ // given
+ const model = "openai/gpt-5.2"
+
+ // when
+ const prompt = buildSisyphusJuniorPrompt(model, true)
+
+ // then
+ expect(prompt).toContain("")
+ expect(prompt).toContain("TaskCreate")
+ })
+
+ test("useTaskSystem=false includes Todo_Discipline for Claude", () => {
+ // given
+ const model = "anthropic/claude-sonnet-4-5"
+
+ // when
+ const prompt = buildSisyphusJuniorPrompt(model, false)
+
+ // then
+ expect(prompt).toContain("")
+ expect(prompt).toContain("todowrite")
+ })
+})
diff --git a/src/agents/sisyphus-junior/index.ts b/src/agents/sisyphus-junior/index.ts
new file mode 100644
index 00000000..26c3f753
--- /dev/null
+++ b/src/agents/sisyphus-junior/index.ts
@@ -0,0 +1,121 @@
+/**
+ * Sisyphus-Junior - Focused Task Executor
+ *
+ * Executes delegated tasks directly without spawning other agents.
+ * Category-spawned executor with domain-specific configurations.
+ *
+ * Routing:
+ * 1. GPT models (openai/*, github-copilot/gpt-*) -> gpt.ts (GPT-5.2 optimized)
+ * 2. Default (Claude, etc.) -> default.ts (Claude-optimized)
+ */
+
+import type { AgentConfig } from "@opencode-ai/sdk"
+import type { AgentMode } from "../types"
+import { isGptModel } from "../types"
+import type { AgentOverrideConfig } from "../../config/schema"
+import {
+ createAgentToolRestrictions,
+ type PermissionValue,
+} from "../../shared/permission-compat"
+
+import { buildDefaultSisyphusJuniorPrompt } from "./default"
+import { buildGptSisyphusJuniorPrompt } from "./gpt"
+
+export { buildDefaultSisyphusJuniorPrompt } from "./default"
+export { buildGptSisyphusJuniorPrompt } from "./gpt"
+
+const MODE: AgentMode = "subagent"
+
+// Core tools that Sisyphus-Junior must NEVER have access to
+// Note: call_omo_agent is ALLOWED so subagents can spawn explore/librarian
+const BLOCKED_TOOLS = ["task", "delegate_task"]
+
+export const SISYPHUS_JUNIOR_DEFAULTS = {
+ model: "anthropic/claude-sonnet-4-5",
+ temperature: 0.1,
+} as const
+
+export type SisyphusJuniorPromptSource = "default" | "gpt"
+
+/**
+ * Determines which Sisyphus-Junior prompt to use based on model.
+ */
+export function getSisyphusJuniorPromptSource(model?: string): SisyphusJuniorPromptSource {
+ if (model && isGptModel(model)) {
+ return "gpt"
+ }
+ return "default"
+}
+
+/**
+ * Builds the appropriate Sisyphus-Junior prompt based on model.
+ */
+export function buildSisyphusJuniorPrompt(
+ model: string | undefined,
+ useTaskSystem: boolean,
+ promptAppend?: string
+): string {
+ const source = getSisyphusJuniorPromptSource(model)
+
+ switch (source) {
+ case "gpt":
+ return buildGptSisyphusJuniorPrompt(useTaskSystem, promptAppend)
+ case "default":
+ default:
+ return buildDefaultSisyphusJuniorPrompt(useTaskSystem, promptAppend)
+ }
+}
+
+export function createSisyphusJuniorAgentWithOverrides(
+ override: AgentOverrideConfig | undefined,
+ systemDefaultModel?: string,
+ useTaskSystem = false
+): AgentConfig {
+ if (override?.disable) {
+ override = undefined
+ }
+
+ const model = override?.model ?? systemDefaultModel ?? SISYPHUS_JUNIOR_DEFAULTS.model
+ const temperature = override?.temperature ?? SISYPHUS_JUNIOR_DEFAULTS.temperature
+
+ const promptAppend = override?.prompt_append
+ const prompt = buildSisyphusJuniorPrompt(model, useTaskSystem, promptAppend)
+
+ const baseRestrictions = createAgentToolRestrictions(BLOCKED_TOOLS)
+
+ const userPermission = (override?.permission ?? {}) as Record
+ const basePermission = baseRestrictions.permission
+ const merged: Record = { ...userPermission }
+ for (const tool of BLOCKED_TOOLS) {
+ merged[tool] = "deny"
+ }
+ merged.call_omo_agent = "allow"
+ const toolsConfig = { permission: { ...merged, ...basePermission } }
+
+ const base: AgentConfig = {
+ description: override?.description ??
+ "Focused task executor. Same discipline, no delegation. (Sisyphus-Junior - OhMyOpenCode)",
+ mode: MODE,
+ model,
+ temperature,
+ maxTokens: 64000,
+ prompt,
+ color: override?.color ?? "#20B2AA",
+ ...toolsConfig,
+ }
+
+ if (override?.top_p !== undefined) {
+ base.top_p = override.top_p
+ }
+
+ if (isGptModel(model)) {
+ return { ...base, reasoningEffort: "medium" } as AgentConfig
+ }
+
+ return {
+ ...base,
+ thinking: { type: "enabled", budgetTokens: 32000 },
+ } as AgentConfig
+}
+
+createSisyphusJuniorAgentWithOverrides.mode = MODE