mirror of
https://github.com/merlinhu1/codex-game-studio.git
synced 2026-08-25 07:54:34 +02:00
* feat: add deterministic model tier routing Define Sol, Terra, and Luna policies with fixed fallbacks, explicit surface assignments, runtime precedence, and Luna escalation. Validate generated metadata and expose tier overrides across role, task, and orchestration commands. * fix: infer model tiers from surface models * fix: rebalance prompt model routing * fix: decouple prompt effort routing --------- Co-authored-by: MerlinH <merlinh221@gmail.com>
63 lines
3.6 KiB
TypeScript
63 lines
3.6 KiB
TypeScript
import { existsSync, mkdtempSync, readdirSync, readFileSync } from "node:fs";
|
|
import { tmpdir } from "node:os";
|
|
import path from "node:path";
|
|
import { describe, test } from "node:test";
|
|
import { expect } from "expect";
|
|
import { initProject } from "../src/projects.js";
|
|
import { createTask, executeTaskRun } from "../src/tasks.js";
|
|
|
|
describe("tasks", () => {
|
|
test("task creation requires a valid Codex studio project", () => {
|
|
const projectRoot = mkdtempSync(path.join(tmpdir(), "ogs-task-"));
|
|
|
|
expect(() => createTask(projectRoot, { title: "Implement jump", role: "gameplay-programmer" })).toThrow();
|
|
expect(existsSync(path.join(projectRoot, ".codex", "tasks.json"))).toBe(false);
|
|
});
|
|
|
|
test("strict studio blocks unapproved task runs before run metadata writes or task mutation", async () => {
|
|
const cwd = mkdtempSync(path.join(tmpdir(), "ogs-task-strict-"));
|
|
const { projectRoot } = initProject({ name: "Strict Task Game", engine: "godot", mode: "prototype", studioMode: "strict-studio", nonInteractive: true }, cwd);
|
|
const task = createTask(projectRoot, { title: "Implement jump", role: "gameplay-programmer", files: ["design/gdd.md"] });
|
|
const beforeStore = readFileSync(path.join(projectRoot, ".codex", "tasks.json"), "utf8");
|
|
const beforeRuns = readdirSync(path.join(projectRoot, ".codex", "runs"));
|
|
|
|
await expect(executeTaskRun(projectRoot, task.id, { codexBin: path.join(cwd, "missing-codex") })).rejects.toThrow(/matching approval/i);
|
|
|
|
expect(readFileSync(path.join(projectRoot, ".codex", "tasks.json"), "utf8")).toBe(beforeStore);
|
|
expect(readdirSync(path.join(projectRoot, ".codex", "runs"))).toEqual(beforeRuns);
|
|
});
|
|
|
|
test("guided task run override shares eligibility metadata without approval", async () => {
|
|
const cwd = mkdtempSync(path.join(tmpdir(), "ogs-task-guided-"));
|
|
const { projectRoot } = initProject({ name: "Guided Task Game", engine: "godot", mode: "prototype", studioMode: "guided-studio", nonInteractive: true }, cwd);
|
|
const task = createTask(projectRoot, { title: "Implement jump", role: "gameplay-programmer" });
|
|
|
|
const result = await executeTaskRun(projectRoot, task.id, { dryRun: true, approvedByUser: true });
|
|
|
|
expect(result.prepared.eligibility).toMatchObject({
|
|
allowed: true,
|
|
writePolicy: "override-write",
|
|
codexSandbox: "danger-full-access",
|
|
metadata: { provenance: "override", approvedByUser: true }
|
|
});
|
|
expect(result.prepared.output).toContain("Write policy: override-write");
|
|
});
|
|
|
|
test("task overrides take precedence over the workflow model-derived tier", async () => {
|
|
const cwd = mkdtempSync(path.join(tmpdir(), "ogs-task-model-tier-"));
|
|
const { projectRoot } = initProject({ name: "Tiered Task Game", engine: "godot", mode: "prototype", studioMode: "fast-prototype", nonInteractive: true }, cwd);
|
|
const workflowTask = createTask(projectRoot, { title: "Format sprint status", role: "producer", workflowId: "sprint-status" });
|
|
const taskOverride = createTask(projectRoot, { title: "Review sprint status", role: "producer", workflowId: "sprint-status", runPolicy: { modelTier: "terra" } });
|
|
|
|
const workflowRun = await executeTaskRun(projectRoot, workflowTask.id, { dryRun: true });
|
|
expect(workflowRun.prepared.selectedModelTier).toBe("luna");
|
|
expect(workflowRun.prepared.modelSelectionSource).toBe("surface");
|
|
|
|
const taskRun = await executeTaskRun(projectRoot, taskOverride.id, { dryRun: true });
|
|
expect(taskRun.prepared.selectedModelTier).toBe("terra");
|
|
|
|
const userOverride = await executeTaskRun(projectRoot, taskOverride.id, { dryRun: true, modelTier: "sol" });
|
|
expect(userOverride.prepared.selectedModelTier).toBe("sol");
|
|
});
|
|
});
|