Menu
popagent
publicLatest change b98b249dccb19f6e251a0ca2fd866028a959ea3d - fix: remove Titan agent routing by AkurAI Build
import { describe, expect, test } from "bun:test";
import type {
AgentSchedule,
AgentSettings,
AgentWorkspace,
AutonomySettings,
} from "./api-types";
import {
BUILD_MAINTENANCE_MODEL,
BUILD_MAINTENANCE_PROMPT,
BUILD_MAINTENANCE_SCHEDULE_NAME,
SELF_UPDATE_MODEL,
SELF_UPDATE_PROMPT,
SELF_UPDATE_SCHEDULE_NAME,
SelfUpdateScheduler,
} from "./self-update-scheduler";
test("system schedules use the configured cloud model instead of Titan-local inference", () => {
expect(SELF_UPDATE_MODEL).toBe("codex/gpt-5.6-luna-medium");
expect(BUILD_MAINTENANCE_MODEL).toBe("codex/gpt-5.6-luna-medium");
});
function autonomy(overrides: Partial<AutonomySettings> = {}): AutonomySettings {
return {
enabled: true,
reflectionIntervalMs: 3_600_000,
batchSize: 10,
maxAttempts: 3,
autoApplyStrategies: false,
autoCreateSkills: false,
autoRetainFacts: false,
selfUpdateEnabled: true,
selfUpdateCron: "0 3 * * *",
idleImprovementEnabled: false,
idleDeploymentEnabled: false,
idleWorkspaceIds: [],
updatedAt: new Date(0).toISOString(),
...overrides,
};
}
function workspace(id: string): AgentWorkspace {
return {
id,
name: id,
repositoryPath: id,
createdAt: new Date(0).toISOString(),
updatedAt: new Date(0).toISOString(),
};
}
function schedule(
workspaceId: string,
overrides: Partial<AgentSchedule> = {},
): AgentSchedule {
return {
id: crypto.randomUUID(),
sessionId: null,
source: "self-update",
workspaceId,
name: SELF_UPDATE_SCHEDULE_NAME,
prompt: SELF_UPDATE_PROMPT,
model: "test/model",
maxAttempts: 3,
cron: "0 3 * * *",
timezone: "UTC",
enabled: true,
nextRunAt: new Date().toISOString(),
lastRunAt: null,
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
...overrides,
};
}
class FakeAutonomySettings {
listeners = new Set<(settings: AutonomySettings) => void>();
constructor(public current: AutonomySettings) {}
async get(): Promise<AutonomySettings> {
return this.current;
}
subscribe(listener: (settings: AutonomySettings) => void): () => void {
this.listeners.add(listener);
return () => this.listeners.delete(listener);
}
}
class FakeTaskSchedules {
schedules: AgentSchedule[] = [];
upsertCalls = 0;
async upsertSelfUpdateSchedule(input: {
workspaceId: string;
name: string;
prompt: string;
model: string;
maxAttempts: number;
cron: string;
enabled: boolean;
}): Promise<AgentSchedule> {
this.upsertCalls++;
const index = this.schedules.findIndex((item) =>
item.source === "self-update" && item.workspaceId === input.workspaceId
);
if (index < 0) {
const created = schedule(input.workspaceId, input);
this.schedules.push(created);
return created;
}
return this.schedules[index]!;
}
async upsertBuildMaintenanceSchedule(input: {
workspaceId: string;
name: string;
prompt: string;
model: string;
maxAttempts: number;
cron: string;
enabled: boolean;
}): Promise<AgentSchedule> {
const index = this.schedules.findIndex((item) =>
item.source === "build-maintenance" && item.workspaceId === input.workspaceId
);
if (index < 0) {
const created = schedule(input.workspaceId, { ...input, source: "build-maintenance" });
this.schedules.push(created);
return created;
}
return this.schedules[index]!;
}
async disableBuildMaintenanceSchedules(exceptWorkspaceIds: string[] = []): Promise<void> {
for (const item of this.schedules) {
if (item.source === "build-maintenance" && !exceptWorkspaceIds.includes(item.workspaceId)) {
item.enabled = false;
item.nextRunAt = null;
}
}
}
async disableSelfUpdateSchedules(exceptWorkspaceIds: string[] = []): Promise<void> {
for (const item of this.schedules) {
if (item.source === "self-update" && !exceptWorkspaceIds.includes(item.workspaceId)) {
item.enabled = false;
item.nextRunAt = null;
}
}
}
}
const writableAgents = {
async get(): Promise<Pick<AgentSettings, "workspaceAccess" | "delegationEnabled">> {
return { workspaceAccess: "read-write", delegationEnabled: true };
},
};
describe("SelfUpdateScheduler", () => {
test("creates one default autonomous schedule and preserves operator timing", async () => {
const tasks = new FakeTaskSchedules();
const settings = new FakeAutonomySettings(autonomy({ idleImprovementEnabled: true, idleWorkspaceIds: ["writable"] }));
const workspaces = {
async list() { return [workspace("writable")]; },
async resolveRepository(id: string) { return { workspace: workspace(id), path: `/registered/${id}` }; },
};
const scheduler = new SelfUpdateScheduler({
tasks,
settings,
workspaces,
agents: writableAgents,
isWritableRepository: async () => true,
});
await Promise.all([scheduler.reconcile(), scheduler.reconcile()]);
expect(tasks.schedules).toHaveLength(1);
expect(tasks.schedules[0]).toEqual(expect.objectContaining({
source: "self-update",
workspaceId: "writable",
name: SELF_UPDATE_SCHEDULE_NAME,
cron: "0 3 * * *",
maxAttempts: 3,
enabled: true,
}));
const stableId = tasks.schedules[0]!.id;
settings.current = autonomy({ maxAttempts: 5, selfUpdateCron: "30 4 * * 1", idleImprovementEnabled: true, idleWorkspaceIds: ["writable"] });
await scheduler.reconcile();
expect(tasks.schedules).toHaveLength(1);
expect(tasks.schedules[0]).toEqual(expect.objectContaining({
id: stableId,
cron: "0 3 * * *",
maxAttempts: 3,
}));
});
test("does not claim a user schedule with the reserved display name", async () => {
const tasks = new FakeTaskSchedules();
const userSchedule = schedule("writable", { source: "user" });
tasks.schedules.push(userSchedule);
const scheduler = new SelfUpdateScheduler({
tasks,
settings: new FakeAutonomySettings(autonomy({ idleImprovementEnabled: true, idleWorkspaceIds: ["writable"] })),
workspaces: {
async list() { return [workspace("writable")]; },
async resolveRepository(id: string) { return { workspace: workspace(id), path: `/registered/${id}` }; },
},
agents: writableAgents,
isWritableRepository: async () => true,
});
await scheduler.reconcile();
expect(tasks.schedules).toHaveLength(2);
expect(tasks.schedules.find((item) => item.id === userSchedule.id)).toEqual(userSchedule);
expect(tasks.schedules.filter((item) => item.source === "self-update")).toHaveLength(1);
});
test("skips read-only and invalid registered workspaces", async () => {
const tasks = new FakeTaskSchedules();
tasks.schedules.push(schedule("read-only"), schedule("invalid"));
const workspaces = {
async list() { return [workspace("writable"), workspace("read-only"), workspace("invalid")]; },
async resolveRepository(id: string) {
if (id === "invalid") throw new Error("invalid workspace");
return { workspace: workspace(id), path: `/registered/${id}` };
},
};
const scheduler = new SelfUpdateScheduler({
tasks,
settings: new FakeAutonomySettings(autonomy({ idleImprovementEnabled: true, idleWorkspaceIds: ["writable", "read-only", "invalid"] })),
workspaces,
agents: writableAgents,
isWritableRepository: async (path) => path.endsWith("/writable"),
});
await scheduler.reconcile();
expect(tasks.schedules.filter((item) => item.enabled).map((item) => item.workspaceId)).toEqual(["writable"]);
expect(tasks.schedules).toHaveLength(3);
});
test("disabling autonomy disables only self-update-owned schedules", async () => {
const tasks = new FakeTaskSchedules();
tasks.schedules.push(
schedule("writable"),
schedule("writable", { source: "user" }),
);
const scheduler = new SelfUpdateScheduler({
tasks,
settings: new FakeAutonomySettings(autonomy({ selfUpdateEnabled: false })),
workspaces: {
async list() { return [workspace("writable")]; },
async resolveRepository(id: string) { return { workspace: workspace(id), path: `/registered/${id}` }; },
},
agents: writableAgents,
isWritableRepository: async () => true,
});
await scheduler.reconcile();
expect(tasks.schedules.find((item) => item.source === "self-update")?.enabled).toBe(false);
expect(tasks.schedules.find((item) => item.source === "user")?.enabled).toBe(true);
});
test("requires writable supervisor and implementer plus an eligible reviewer", async () => {
const tasks = new FakeTaskSchedules();
const scheduler = new SelfUpdateScheduler({
tasks,
settings: new FakeAutonomySettings(autonomy({ idleImprovementEnabled: true, idleWorkspaceIds: ["writable"] })),
workspaces: {
async list() { return [workspace("writable")]; },
async resolveRepository(id: string) { return { workspace: workspace(id), path: `/registered/${id}` }; },
},
agents: {
async get(id) {
return id === "reviewer"
? { workspaceAccess: "read-only" as const, delegationEnabled: false }
: { workspaceAccess: "read-write" as const, delegationEnabled: true };
},
},
isWritableRepository: async () => true,
});
await scheduler.reconcile();
expect(tasks.schedules).toHaveLength(0);
});
test("serializes concurrent starts and stop during the initial reconcile", async () => {
const gate = Promise.withResolvers<void>();
let gets = 0;
const settings = new FakeAutonomySettings(autonomy());
settings.get = async () => {
gets++;
await gate.promise;
return settings.current;
};
const tasks = new FakeTaskSchedules();
const scheduler = new SelfUpdateScheduler({
tasks,
settings,
workspaces: {
async list() { return [workspace("writable")]; },
async resolveRepository(id: string) { return { workspace: workspace(id), path: `/registered/${id}` }; },
},
agents: writableAgents,
reconcileIntervalMs: 60_000,
isWritableRepository: async () => true,
});
const firstStart = scheduler.start();
const secondStart = scheduler.start();
expect(firstStart).toBe(secondStart);
await Promise.resolve();
const stopping = scheduler.stop();
gate.resolve();
await Promise.all([firstStart, secondStart, stopping]);
expect(gets).toBe(1);
expect(settings.listeners.size).toBe(0);
await scheduler.start();
expect(gets).toBe(2);
expect(settings.listeners.size).toBe(1);
await scheduler.stop();
expect(settings.listeners.size).toBe(0);
});
test("keeps a stable Build maintenance schedule beside self-update schedules", async () => {
const tasks = new FakeTaskSchedules();
const settings = new FakeAutonomySettings(autonomy({
idleImprovementEnabled: true,
idleWorkspaceIds: ["build"],
}));
const buildWorkspace = { ...workspace("build"), name: "AkurAI-Build", repositoryPath: "akurai-build" };
const scheduler = new SelfUpdateScheduler({
tasks,
settings,
workspaces: {
async list() { return [buildWorkspace]; },
async resolveRepository() { return { workspace: buildWorkspace, path: "/registered/akurai-build" }; },
},
agents: writableAgents,
isWritableRepository: async () => true,
});
await scheduler.reconcile();
const first = tasks.schedules.find((item) => item.source === "build-maintenance");
expect(first).toEqual(expect.objectContaining({
source: "build-maintenance",
workspaceId: "build",
name: BUILD_MAINTENANCE_SCHEDULE_NAME,
prompt: BUILD_MAINTENANCE_PROMPT,
}));
expect(tasks.schedules.filter((item) => item.source === "self-update")).toHaveLength(1);
await scheduler.reconcile();
expect(tasks.schedules.filter((item) => item.source === "build-maintenance")).toHaveLength(1);
expect(tasks.schedules.find((item) => item.source === "build-maintenance")?.id).toBe(first?.id);
});
test("requires concrete inspection evidence before a generated no-op", () => {
expect(SELF_UPDATE_PROMPT).toContain("Delegate independent verification");
expect(SELF_UPDATE_PROMPT).toContain("prepared autonomous/self-update branch");
expect(SELF_UPDATE_PROMPT).toContain("Never acquire credentials");
expect(SELF_UPDATE_PROMPT).toContain("A clean checkout alone is never sufficient no-op evidence");
expect(SELF_UPDATE_PROMPT).toContain("paths and symbols inspected");
expect(SELF_UPDATE_PROMPT).toContain("candidates considered");
expect(SELF_UPDATE_PROMPT).toContain("Delegate bounded inspection to the Researcher");
expect(SELF_UPDATE_PROMPT).toContain("Server-owned policy performs optional publish and deployment");
expect(BUILD_MAINTENANCE_PROMPT).toContain("Build Maintainer");
expect(BUILD_MAINTENANCE_PROMPT).toContain("autonomous/build-maintenance/");
expect(BUILD_MAINTENANCE_PROMPT).toContain("Never advance main");
});
});