forked from laurentenhoor/devclaw
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbootstrap.e2e.test.ts
More file actions
233 lines (199 loc) · 7.96 KB
/
bootstrap.e2e.test.ts
File metadata and controls
233 lines (199 loc) · 7.96 KB
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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
/**
* E2E bootstrap tests — verifies role instructions reach workers via extraSystemPrompt:
* dispatchTask() → loadRoleInstructions() → gateway agent call includes extraSystemPrompt
*
* Also tests that the agent:bootstrap hook strips AGENTS.md from worker sessions.
*
* Run: npx tsx --test lib/services/bootstrap.e2e.test.ts
*/
import { describe, it, afterEach } from "node:test";
import assert from "node:assert";
import { createTestHarness, type TestHarness } from "../testing/index.js";
import { dispatchTask } from "../dispatch/index.js";
describe("E2E bootstrap — extraSystemPrompt injection", () => {
let h: TestHarness;
afterEach(async () => {
if (h) await h.cleanup();
});
it("should inject project-specific instructions via extraSystemPrompt", async () => {
h = await createTestHarness({ projectName: "my-app" });
h.provider.seedIssue({ iid: 1, title: "Add feature", labels: ["To Do"] });
// Write both default and project-specific prompts
await h.writePrompt("developer", "# Default Developer\nGeneric instructions.");
await h.writePrompt("developer", "# My App Developer\nUse React. Follow our design system.", "my-app");
await dispatchTask({
workspaceDir: h.workspaceDir,
agentId: "main",
project: h.project,
issueId: 1,
issueTitle: "Add feature",
issueDescription: "",
issueUrl: "https://example.com/issues/1",
role: "developer",
level: "medior",
fromLabel: "To Do",
toLabel: "Doing",
provider: h.provider,
runCommand: h.runCommand,
});
// Verify extraSystemPrompt in the gateway agent call
const prompts = h.commands.extraSystemPrompts();
assert.strictEqual(prompts.length, 1, `Expected 1 extraSystemPrompt, got ${prompts.length}`);
assert.ok(prompts[0].includes("My App Developer"), `Got: ${prompts[0]}`);
assert.ok(prompts[0].includes("Use React"));
assert.ok(!prompts[0].includes("Generic instructions"));
});
it("should fall back to default instructions when no project override exists", async () => {
h = await createTestHarness({ projectName: "other-app" });
h.provider.seedIssue({ iid: 2, title: "Fix bug", labels: ["To Do"] });
// Only write default prompt — no project-specific
await h.writePrompt("developer", "# Default Developer\nFollow coding standards.");
await dispatchTask({
workspaceDir: h.workspaceDir,
agentId: "main",
project: h.project,
issueId: 2,
issueTitle: "Fix bug",
issueDescription: "",
issueUrl: "https://example.com/issues/2",
role: "developer",
level: "junior",
fromLabel: "To Do",
toLabel: "Doing",
provider: h.provider,
runCommand: h.runCommand,
});
const prompts = h.commands.extraSystemPrompts();
assert.strictEqual(prompts.length, 1);
assert.ok(prompts[0].includes("Default Developer"));
assert.ok(prompts[0].includes("Follow coding standards"));
});
it("should inject scaffolded default instructions when no overrides exist", async () => {
h = await createTestHarness({ projectName: "bare-app" });
h.provider.seedIssue({ iid: 3, title: "Chore", labels: ["To Do"] });
// Don't write any custom prompts — ensureWorkspaceMigrated scaffolds defaults
await dispatchTask({
workspaceDir: h.workspaceDir,
agentId: "main",
project: h.project,
issueId: 3,
issueTitle: "Chore",
issueDescription: "",
issueUrl: "https://example.com/issues/3",
role: "developer",
level: "medior",
fromLabel: "To Do",
toLabel: "Doing",
provider: h.provider,
runCommand: h.runCommand,
});
const prompts = h.commands.extraSystemPrompts();
// No prompt files exist in this temp workspace — extraSystemPrompt should be absent
assert.strictEqual(prompts.length, 0, "No extraSystemPrompt when no prompt files exist");
});
it("should resolve tester instructions independently from developer", async () => {
h = await createTestHarness({ projectName: "multi-role" });
h.provider.seedIssue({ iid: 4, title: "Test thing", labels: ["To Test"] });
// Write project-specific for developer, default for tester
await h.writePrompt("developer", "# Dev for multi-role\nSpecific dev rules.", "multi-role");
await h.writePrompt("tester", "# Default Tester\nRun integration tests.");
// Dispatch as tester
await dispatchTask({
workspaceDir: h.workspaceDir,
agentId: "main",
project: h.project,
issueId: 4,
issueTitle: "Test thing",
issueDescription: "",
issueUrl: "https://example.com/issues/4",
role: "tester",
level: "medior",
fromLabel: "To Test",
toLabel: "Testing",
provider: h.provider,
runCommand: h.runCommand,
});
const prompts = h.commands.extraSystemPrompts();
assert.strictEqual(prompts.length, 1);
assert.ok(prompts[0].includes("Default Tester"));
assert.ok(!prompts[0].includes("Dev for multi-role"));
});
it("should handle project names with hyphens correctly", async () => {
h = await createTestHarness({ projectName: "my-cool-project" });
h.provider.seedIssue({ iid: 5, title: "Hyphen test", labels: ["To Do"] });
await h.writePrompt(
"developer",
"# Hyphenated Project\nThis project has hyphens in the name.",
"my-cool-project",
);
await dispatchTask({
workspaceDir: h.workspaceDir,
agentId: "main",
project: h.project,
issueId: 5,
issueTitle: "Hyphen test",
issueDescription: "",
issueUrl: "https://example.com/issues/5",
role: "developer",
level: "senior",
fromLabel: "To Do",
toLabel: "Doing",
provider: h.provider,
runCommand: h.runCommand,
});
const prompts = h.commands.extraSystemPrompts();
assert.strictEqual(prompts.length, 1);
assert.ok(prompts[0].includes("Hyphenated Project"));
});
it("should resolve architect instructions with project override", async () => {
h = await createTestHarness({ projectName: "arch-proj" });
h.provider.seedIssue({ iid: 6, title: "Design API", labels: ["Planning"] });
await h.writePrompt("architect", "# Default Architect\nGeneral design guidelines.");
await h.writePrompt("architect", "# Arch Proj Architect\nUse event-driven architecture.", "arch-proj");
await dispatchTask({
workspaceDir: h.workspaceDir,
agentId: "main",
project: h.project,
issueId: 6,
issueTitle: "Design API",
issueDescription: "",
issueUrl: "https://example.com/issues/6",
role: "architect",
level: "senior",
fromLabel: "Planning",
toLabel: "Planning",
provider: h.provider,
runCommand: h.runCommand,
});
const prompts = h.commands.extraSystemPrompts();
assert.strictEqual(prompts.length, 1);
assert.ok(prompts[0].includes("Arch Proj Architect"));
assert.ok(prompts[0].includes("event-driven"));
assert.ok(!prompts[0].includes("General design guidelines"));
});
});
describe("E2E bootstrap — agent:bootstrap hook (AGENTS.md stripping)", () => {
let h: TestHarness;
afterEach(async () => {
if (h) await h.cleanup();
});
it("should strip AGENTS.md for DevClaw worker sessions", async () => {
h = await createTestHarness({ projectName: "my-app" });
const result = await h.simulateBootstrap(
"agent:main:subagent:my-app-developer-medior-Ada",
);
assert.strictEqual(result.agentsMdStripped, true);
});
it("should NOT strip AGENTS.md for non-DevClaw sessions", async () => {
h = await createTestHarness();
const result = await h.simulateBootstrap("agent:main:orchestrator");
assert.strictEqual(result.agentsMdStripped, false);
});
it("should NOT strip AGENTS.md for unknown roles", async () => {
h = await createTestHarness({ projectName: "custom-app" });
const result = await h.simulateBootstrap(
"agent:main:subagent:custom-app-investigator-medior",
);
assert.strictEqual(result.agentsMdStripped, false);
});
});