refactor(hooks): rename sisyphus-orchestrator to atlas

Hook name is now 'atlas' (not 'atlas-orchestrator'). Directory renamed to src/hooks/atlas/. All references updated.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
justsisyphus 2026-01-20 15:52:13 +09:00
parent 96bcd9788a
commit c4b862cbc4
5 changed files with 93 additions and 89 deletions

View File

@ -12,8 +12,8 @@ import type { BoulderState } from "../../features/boulder-state"
import { MESSAGE_STORAGE } from "../../features/hook-message-injector" import { MESSAGE_STORAGE } from "../../features/hook-message-injector"
describe("sisyphus-orchestrator hook", () => { describe("atlas hook", () => {
const TEST_DIR = join(tmpdir(), "sisyphus-orchestrator-test-" + Date.now()) const TEST_DIR = join(tmpdir(), "atlas-test-" + Date.now())
const SISYPHUS_DIR = join(TEST_DIR, ".sisyphus") const SISYPHUS_DIR = join(TEST_DIR, ".sisyphus")
function createMockPluginInput(overrides?: { promptMock?: ReturnType<typeof mock> }) { function createMockPluginInput(overrides?: { promptMock?: ReturnType<typeof mock> }) {
@ -85,8 +85,8 @@ describe("sisyphus-orchestrator hook", () => {
expect(output.output).toBe("Original output") expect(output.output).toBe("Original output")
}) })
test("should not transform when caller is not orchestrator-sisyphus", async () => { test("should not transform when caller is not atlas", async () => {
// #given - boulder state exists but caller agent in message storage is not orchestrator // #given - boulder state exists but caller agent in message storage is not atlas
const sessionID = "session-non-orchestrator-test" const sessionID = "session-non-orchestrator-test"
setupMessageStorage(sessionID, "other-agent") setupMessageStorage(sessionID, "other-agent")
@ -120,10 +120,10 @@ describe("sisyphus-orchestrator hook", () => {
cleanupMessageStorage(sessionID) cleanupMessageStorage(sessionID)
}) })
test("should append standalone verification when no boulder state but caller is orchestrator", async () => { test("should append standalone verification when no boulder state but caller is atlas", async () => {
// #given - no boulder state, but caller is orchestrator // #given - no boulder state, but caller is atlas
const sessionID = "session-no-boulder-test" const sessionID = "session-no-boulder-test"
setupMessageStorage(sessionID, "orchestrator-sisyphus") setupMessageStorage(sessionID, "atlas")
const hook = createSisyphusOrchestratorHook(createMockPluginInput()) const hook = createSisyphusOrchestratorHook(createMockPluginInput())
const output = { const output = {
@ -146,10 +146,10 @@ describe("sisyphus-orchestrator hook", () => {
cleanupMessageStorage(sessionID) cleanupMessageStorage(sessionID)
}) })
test("should transform output when caller is orchestrator-sisyphus with boulder state", async () => { test("should transform output when caller is atlas with boulder state", async () => {
// #given - orchestrator-sisyphus caller with boulder state // #given - atlas caller with boulder state
const sessionID = "session-transform-test" const sessionID = "session-transform-test"
setupMessageStorage(sessionID, "orchestrator-sisyphus") setupMessageStorage(sessionID, "atlas")
const planPath = join(TEST_DIR, "test-plan.md") const planPath = join(TEST_DIR, "test-plan.md")
writeFileSync(planPath, "# Plan\n- [ ] Task 1\n- [x] Task 2") writeFileSync(planPath, "# Plan\n- [ ] Task 1\n- [x] Task 2")
@ -186,9 +186,9 @@ describe("sisyphus-orchestrator hook", () => {
}) })
test("should still transform when plan is complete (shows progress)", async () => { test("should still transform when plan is complete (shows progress)", async () => {
// #given - boulder state with complete plan, orchestrator caller // #given - boulder state with complete plan, atlas caller
const sessionID = "session-complete-plan-test" const sessionID = "session-complete-plan-test"
setupMessageStorage(sessionID, "orchestrator-sisyphus") setupMessageStorage(sessionID, "atlas")
const planPath = join(TEST_DIR, "complete-plan.md") const planPath = join(TEST_DIR, "complete-plan.md")
writeFileSync(planPath, "# Plan\n- [x] Task 1\n- [x] Task 2") writeFileSync(planPath, "# Plan\n- [x] Task 1\n- [x] Task 2")
@ -223,9 +223,9 @@ describe("sisyphus-orchestrator hook", () => {
}) })
test("should append session ID to boulder state if not present", async () => { test("should append session ID to boulder state if not present", async () => {
// #given - boulder state without session-append-test, orchestrator caller // #given - boulder state without session-append-test, atlas caller
const sessionID = "session-append-test" const sessionID = "session-append-test"
setupMessageStorage(sessionID, "orchestrator-sisyphus") setupMessageStorage(sessionID, "atlas")
const planPath = join(TEST_DIR, "test-plan.md") const planPath = join(TEST_DIR, "test-plan.md")
writeFileSync(planPath, "# Plan\n- [ ] Task 1") writeFileSync(planPath, "# Plan\n- [ ] Task 1")
@ -259,9 +259,9 @@ describe("sisyphus-orchestrator hook", () => {
}) })
test("should not duplicate existing session ID", async () => { test("should not duplicate existing session ID", async () => {
// #given - boulder state already has session-dup-test, orchestrator caller // #given - boulder state already has session-dup-test, atlas caller
const sessionID = "session-dup-test" const sessionID = "session-dup-test"
setupMessageStorage(sessionID, "orchestrator-sisyphus") setupMessageStorage(sessionID, "atlas")
const planPath = join(TEST_DIR, "test-plan.md") const planPath = join(TEST_DIR, "test-plan.md")
writeFileSync(planPath, "# Plan\n- [ ] Task 1") writeFileSync(planPath, "# Plan\n- [ ] Task 1")
@ -296,9 +296,9 @@ describe("sisyphus-orchestrator hook", () => {
}) })
test("should include boulder.json path and notepad path in transformed output", async () => { test("should include boulder.json path and notepad path in transformed output", async () => {
// #given - boulder state, orchestrator caller // #given - boulder state, atlas caller
const sessionID = "session-path-test" const sessionID = "session-path-test"
setupMessageStorage(sessionID, "orchestrator-sisyphus") setupMessageStorage(sessionID, "atlas")
const planPath = join(TEST_DIR, "my-feature.md") const planPath = join(TEST_DIR, "my-feature.md")
writeFileSync(planPath, "# Plan\n- [ ] Task 1\n- [ ] Task 2\n- [x] Task 3") writeFileSync(planPath, "# Plan\n- [ ] Task 1\n- [ ] Task 2\n- [x] Task 3")
@ -333,9 +333,9 @@ describe("sisyphus-orchestrator hook", () => {
}) })
test("should include resume and checkbox instructions in reminder", async () => { test("should include resume and checkbox instructions in reminder", async () => {
// #given - boulder state, orchestrator caller // #given - boulder state, atlas caller
const sessionID = "session-resume-test" const sessionID = "session-resume-test"
setupMessageStorage(sessionID, "orchestrator-sisyphus") setupMessageStorage(sessionID, "atlas")
const planPath = join(TEST_DIR, "test-plan.md") const planPath = join(TEST_DIR, "test-plan.md")
writeFileSync(planPath, "# Plan\n- [ ] Task 1") writeFileSync(planPath, "# Plan\n- [ ] Task 1")
@ -373,7 +373,7 @@ describe("sisyphus-orchestrator hook", () => {
const ORCHESTRATOR_SESSION = "orchestrator-write-test" const ORCHESTRATOR_SESSION = "orchestrator-write-test"
beforeEach(() => { beforeEach(() => {
setupMessageStorage(ORCHESTRATOR_SESSION, "orchestrator-sisyphus") setupMessageStorage(ORCHESTRATOR_SESSION, "atlas")
}) })
afterEach(() => { afterEach(() => {
@ -601,7 +601,7 @@ describe("sisyphus-orchestrator hook", () => {
getMainSessionID: () => MAIN_SESSION_ID, getMainSessionID: () => MAIN_SESSION_ID,
subagentSessions: new Set<string>(), subagentSessions: new Set<string>(),
})) }))
setupMessageStorage(MAIN_SESSION_ID, "orchestrator-sisyphus") setupMessageStorage(MAIN_SESSION_ID, "atlas")
}) })
afterEach(() => { afterEach(() => {
@ -830,8 +830,8 @@ describe("sisyphus-orchestrator hook", () => {
expect(callArgs.body.parts[0].text).toContain("2 remaining") expect(callArgs.body.parts[0].text).toContain("2 remaining")
}) })
test("should not inject when last agent is not orchestrator-sisyphus", async () => { test("should not inject when last agent is not atlas", async () => {
// #given - boulder state with incomplete plan, but last agent is NOT orchestrator-sisyphus // #given - boulder state with incomplete plan, but last agent is NOT atlas
const planPath = join(TEST_DIR, "test-plan.md") const planPath = join(TEST_DIR, "test-plan.md")
writeFileSync(planPath, "# Plan\n- [ ] Task 1\n- [ ] Task 2") writeFileSync(planPath, "# Plan\n- [ ] Task 1\n- [ ] Task 2")
@ -843,7 +843,7 @@ describe("sisyphus-orchestrator hook", () => {
} }
writeBoulderState(TEST_DIR, state) writeBoulderState(TEST_DIR, state)
// #given - last agent is NOT orchestrator-sisyphus // #given - last agent is NOT atlas
cleanupMessageStorage(MAIN_SESSION_ID) cleanupMessageStorage(MAIN_SESSION_ID)
setupMessageStorage(MAIN_SESSION_ID, "Sisyphus") setupMessageStorage(MAIN_SESSION_ID, "Sisyphus")
@ -858,7 +858,7 @@ describe("sisyphus-orchestrator hook", () => {
}, },
}) })
// #then - should NOT call prompt because agent is not orchestrator-sisyphus // #then - should NOT call prompt because agent is not atlas
expect(mockInput._promptMock).not.toHaveBeenCalled() expect(mockInput._promptMock).not.toHaveBeenCalled()
}) })

View File

@ -13,7 +13,7 @@ import { log } from "../../shared/logger"
import { createSystemDirective, SYSTEM_DIRECTIVE_PREFIX, SystemDirectiveTypes } from "../../shared/system-directive" import { createSystemDirective, SYSTEM_DIRECTIVE_PREFIX, SystemDirectiveTypes } from "../../shared/system-directive"
import type { BackgroundManager } from "../../features/background-agent" import type { BackgroundManager } from "../../features/background-agent"
export const HOOK_NAME = "sisyphus-orchestrator" export const HOOK_NAME = "atlas"
/** /**
* Cross-platform check if a path is inside .sisyphus/ directory. * Cross-platform check if a path is inside .sisyphus/ directory.
@ -111,7 +111,7 @@ const ORCHESTRATOR_DELEGATION_REQUIRED = `
**STOP. YOU ARE VIOLATING ORCHESTRATOR PROTOCOL.** **STOP. YOU ARE VIOLATING ORCHESTRATOR PROTOCOL.**
You (orchestrator-sisyphus) are attempting to directly modify a file outside \`.sisyphus/\`. You (atlas) are attempting to directly modify a file outside \`.sisyphus/\`.
**Path attempted:** $FILE_PATH **Path attempted:** $FILE_PATH
@ -397,7 +397,7 @@ function isCallerOrchestrator(sessionID?: string): boolean {
const messageDir = getMessageDir(sessionID) const messageDir = getMessageDir(sessionID)
if (!messageDir) return false if (!messageDir) return false
const nearest = findNearestMessageWithFields(messageDir) const nearest = findNearestMessageWithFields(messageDir)
return nearest?.agent === "orchestrator-sisyphus" return nearest?.agent === "atlas"
} }
interface SessionState { interface SessionState {
@ -496,7 +496,7 @@ export function createSisyphusOrchestratorHook(
await ctx.client.session.prompt({ await ctx.client.session.prompt({
path: { id: sessionID }, path: { id: sessionID },
body: { body: {
agent: "orchestrator-sisyphus", agent: "atlas",
...(model !== undefined ? { model } : {}), ...(model !== undefined ? { model } : {}),
parts: [{ type: "text", text: prompt }], parts: [{ type: "text", text: prompt }],
}, },

View File

@ -28,5 +28,5 @@ export { createEditErrorRecoveryHook } from "./edit-error-recovery";
export { createPrometheusMdOnlyHook } from "./prometheus-md-only"; export { createPrometheusMdOnlyHook } from "./prometheus-md-only";
export { createTaskResumeInfoHook } from "./task-resume-info"; export { createTaskResumeInfoHook } from "./task-resume-info";
export { createStartWorkHook } from "./start-work"; export { createStartWorkHook } from "./start-work";
export { createSisyphusOrchestratorHook } from "./sisyphus-orchestrator"; export { createSisyphusOrchestratorHook } from "./atlas";
export { createDelegateTaskRetryHook } from "./delegate-task-retry"; export { createDelegateTaskRetryHook } from "./delegate-task-retry";

View File

@ -207,6 +207,10 @@ export const DEFAULT_CATEGORIES: Record<string, CategoryConfig> = {
}, },
} }
export const CATEGORY_MODEL_CATALOG: Record<string, { model: string; variant?: string }> = {
ultrabrain: { model: "openai/gpt-5.2-codex", variant: "xhigh" },
}
export const CATEGORY_PROMPT_APPENDS: Record<string, string> = { export const CATEGORY_PROMPT_APPENDS: Record<string, string> = {
"visual-engineering": VISUAL_CATEGORY_PROMPT_APPEND, "visual-engineering": VISUAL_CATEGORY_PROMPT_APPEND,
ultrabrain: STRATEGIC_CATEGORY_PROMPT_APPEND, ultrabrain: STRATEGIC_CATEGORY_PROMPT_APPEND,

View File

@ -4,7 +4,7 @@ import { join } from "node:path"
import type { BackgroundManager } from "../../features/background-agent" import type { BackgroundManager } from "../../features/background-agent"
import type { DelegateTaskArgs } from "./types" import type { DelegateTaskArgs } from "./types"
import type { CategoryConfig, CategoriesConfig, GitMasterConfig } from "../../config/schema" import type { CategoryConfig, CategoriesConfig, GitMasterConfig } from "../../config/schema"
import { DELEGATE_TASK_DESCRIPTION, DEFAULT_CATEGORIES, CATEGORY_PROMPT_APPENDS } from "./constants" import { DELEGATE_TASK_DESCRIPTION, DEFAULT_CATEGORIES, CATEGORY_PROMPT_APPENDS, CATEGORY_MODEL_CATALOG } from "./constants"
import { findNearestMessageWithFields, findFirstMessageWithAgent, MESSAGE_STORAGE } from "../../features/hook-message-injector" import { findNearestMessageWithFields, findFirstMessageWithAgent, MESSAGE_STORAGE } from "../../features/hook-message-injector"
import { resolveMultipleSkillsAsync } from "../../features/opencode-skill-loader/skill-content" import { resolveMultipleSkillsAsync } from "../../features/opencode-skill-loader/skill-content"
import { discoverSkills } from "../../features/opencode-skill-loader" import { discoverSkills } from "../../features/opencode-skill-loader"