1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
|
import { describe, it, expect, afterEach } from "bun:test";
import {
modelForTask,
MODEL_SONNET,
MODEL_HAIKU,
type AiTask,
} from "../lib/ai-client";
const ORIGINAL_FORCE_SONNET = process.env.AI_FORCE_SONNET;
afterEach(() => {
if (ORIGINAL_FORCE_SONNET === undefined) {
delete process.env.AI_FORCE_SONNET;
} else {
process.env.AI_FORCE_SONNET = ORIGINAL_FORCE_SONNET;
}
});
describe("modelForTask — Haiku allowlist", () => {
const haikuTasks: AiTask[] = [
"commit-message",
"issue-triage",
"pr-triage",
"label-suggest",
];
for (const task of haikuTasks) {
it(`routes ${task} to Haiku`, () => {
delete process.env.AI_FORCE_SONNET;
expect(modelForTask(task)).toBe(MODEL_HAIKU);
});
}
});
describe("modelForTask — code-critical and doc tasks stay on Sonnet", () => {
const sonnetTasks: AiTask[] = [
"code-review",
"code-completion",
"spec-to-pr",
"ci-heal",
"pr-summary",
"changelog",
];
for (const task of sonnetTasks) {
it(`routes ${task} to Sonnet`, () => {
delete process.env.AI_FORCE_SONNET;
expect(modelForTask(task)).toBe(MODEL_SONNET);
});
}
it("defaults unknown tasks to Sonnet (never silently downgrades)", () => {
delete process.env.AI_FORCE_SONNET;
expect(modelForTask("some-future-task" as AiTask)).toBe(MODEL_SONNET);
expect(modelForTask("" as AiTask)).toBe(MODEL_SONNET);
});
});
describe("modelForTask — AI_FORCE_SONNET kill-switch", () => {
const allTasks: AiTask[] = [
"commit-message",
"issue-triage",
"pr-triage",
"label-suggest",
"code-review",
"code-completion",
"spec-to-pr",
"ci-heal",
"pr-summary",
"changelog",
];
it("forces Sonnet for every task when AI_FORCE_SONNET=1", () => {
process.env.AI_FORCE_SONNET = "1";
for (const task of allTasks) {
expect(modelForTask(task)).toBe(MODEL_SONNET);
}
});
it("is read at call time — flipping the env var takes effect immediately", () => {
delete process.env.AI_FORCE_SONNET;
expect(modelForTask("commit-message")).toBe(MODEL_HAIKU);
process.env.AI_FORCE_SONNET = "1";
expect(modelForTask("commit-message")).toBe(MODEL_SONNET);
delete process.env.AI_FORCE_SONNET;
expect(modelForTask("commit-message")).toBe(MODEL_HAIKU);
});
it("only the exact value \"1\" activates the kill-switch", () => {
process.env.AI_FORCE_SONNET = "0";
expect(modelForTask("commit-message")).toBe(MODEL_HAIKU);
process.env.AI_FORCE_SONNET = "";
expect(modelForTask("commit-message")).toBe(MODEL_HAIKU);
});
});
|