Skip to content

Commit 4037f58

Browse files
authored
chore: sync public mirror from internal
2 parents ba79e83 + 3e35b50 commit 4037f58

5 files changed

Lines changed: 86 additions & 3 deletions

File tree

src/agent/swarm/executor.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ import type {
8181
SwarmTeammate,
8282
TeammateStatus,
8383
} from "./types.js";
84+
import { buildSwarmValidationDirective } from "./validation-directive.js";
8485

8586
const logger = createLogger("agent:swarm:executor");
8687

@@ -1290,8 +1291,7 @@ export class SwarmExecutor {
12901291
evidence: task.files?.length
12911292
? task.files.map((file) => `Relevant file: ${file}`)
12921293
: [],
1293-
validation:
1294-
"Make the requested changes directly, add or update focused tests when behavior changes, and run the relevant verification before finishing.",
1294+
validation: buildSwarmValidationDirective(task.mocksAllowed),
12951295
stoppingCondition:
12961296
"Stop when the assigned task is complete and report what changed, what you verified, and any blockers. Do not broaden into unrelated tasks.",
12971297
};

src/agent/swarm/types.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,12 @@ export interface SwarmTask {
4141
a2aSkillId?: string;
4242
/** Optional durable specialist profile to prepend to the teammate prompt. */
4343
specialistProfile?: string;
44+
/**
45+
* Explicit opt-out of the end-to-end validation default. When true, the
46+
* teammate may use mocks/stubs for unavailable integrations; otherwise the
47+
* worker must validate against real integrations before reporting done.
48+
*/
49+
mocksAllowed?: boolean;
4450
/** Priority (higher = earlier execution when no dependencies) */
4551
priority?: number;
4652
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/**
2+
* Swarm validation directive
3+
*
4+
* Builds the "## Validation" section handed to every swarm teammate. The
5+
* default posture is end-to-end validation against real integrations: a worker
6+
* may not declare a task done on the strength of a mocked path. Mocks/stubs are
7+
* an explicit per-task opt-out (`SwarmTask.mocksAllowed`), not the baseline.
8+
*
9+
* This mirrors the orchestrator discipline that high-end coding agents apply at
10+
* the mission level, pushed down to the per-worker delegation prompt so the
11+
* default holds even for a single delegated task.
12+
*/
13+
14+
const REAL_INTEGRATION_DIRECTIVE =
15+
"Validate end-to-end against real integrations. The default is that every change is exercised through its real execution path — real services, real data, real auth — before you finish. Do not introduce mocks or stubs to make a check pass. Add or update focused tests when behavior changes, and run the relevant verification (build, lint, the touched tests, and the real end-to-end path) before reporting completion. If an integration genuinely cannot be exercised in this environment, stop and report it as a blocker rather than claiming success — never report that something works on the strength of a mocked path alone.";
16+
17+
const MOCKS_ALLOWED_DIRECTIVE =
18+
"This task is explicitly approved to use mocks or stubs where a real integration is unavailable. Prefer the real execution path wherever it exists; where you fall back to a mock, say so explicitly and name exactly what was not exercised for real. Add or update focused tests when behavior changes, and run the relevant verification before reporting completion.";
19+
20+
/**
21+
* Returns the validation directive for a swarm task.
22+
*
23+
* @param mocksAllowed When true, the task has explicitly opted out of the
24+
* real-integration default and may use mocks/stubs for unavailable
25+
* dependencies.
26+
*/
27+
export function buildSwarmValidationDirective(mocksAllowed?: boolean): string {
28+
return mocksAllowed ? MOCKS_ALLOWED_DIRECTIVE : REAL_INTEGRATION_DIRECTIVE;
29+
}

test/agent/swarm-executor.test.ts

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -315,7 +315,10 @@ describe("SwarmExecutor", () => {
315315
expect(prompt).toContain("## Context\nYou are teammate");
316316
expect(prompt).toContain("## Task\nUpdate the implementation");
317317
expect(prompt).toContain(
318-
"## Validation\nMake the requested changes directly",
318+
"## Validation\nValidate end-to-end against real integrations",
319+
);
320+
expect(prompt).toContain(
321+
"never report that something works on the strength of a mocked path alone",
319322
);
320323
expect(prompt).toContain(
321324
"## Stopping Condition\nStop when the assigned task is complete",
@@ -341,6 +344,24 @@ describe("SwarmExecutor", () => {
341344
expect(recordSubagentDispatchMock).not.toHaveBeenCalled();
342345
});
343346

347+
it("passes the mocks-allowed validation directive into spawned teammate prompts", async () => {
348+
let prompt = "";
349+
spawnMock.mockImplementation((_command: string, args: string[]) => {
350+
prompt = readFileSync(args.at(-1)!, "utf-8");
351+
return createMockChildProcess("done");
352+
});
353+
354+
const executor = new SwarmExecutor(createConfig({ mocksAllowed: true }));
355+
void executor.execute();
356+
await waitForSpawn();
357+
358+
expect(prompt).toContain(
359+
"## Validation\nThis task is explicitly approved to use mocks or stubs",
360+
);
361+
expect(prompt).toContain("name exactly what was not exercised for real");
362+
expect(prompt).not.toContain("Do not introduce mocks or stubs");
363+
});
364+
344365
it("marks spawned teammates as mission workers", async () => {
345366
spawnMock.mockImplementation(() => createMockChildProcess("done"));
346367
vi.stubEnv("MAESTRO_MISSION_ROLE", "orchestrator");
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { describe, expect, it } from "vitest";
2+
import { buildSwarmValidationDirective } from "../../src/agent/swarm/validation-directive.js";
3+
4+
describe("buildSwarmValidationDirective", () => {
5+
it("defaults to end-to-end validation against real integrations", () => {
6+
const directive = buildSwarmValidationDirective();
7+
expect(directive).toContain(
8+
"Validate end-to-end against real integrations",
9+
);
10+
expect(directive).toContain("Do not introduce mocks or stubs");
11+
expect(directive).toContain("report it as a blocker");
12+
expect(directive).not.toContain("explicitly approved to use mocks");
13+
});
14+
15+
it("treats an undefined flag the same as the strict default", () => {
16+
expect(buildSwarmValidationDirective(undefined)).toBe(
17+
buildSwarmValidationDirective(false),
18+
);
19+
});
20+
21+
it("relaxes to a mocks-allowed directive only on explicit opt-out", () => {
22+
const directive = buildSwarmValidationDirective(true);
23+
expect(directive).toContain("explicitly approved to use mocks");
24+
expect(directive).toContain("name exactly what was not exercised for real");
25+
expect(directive).not.toContain("Do not introduce mocks or stubs");
26+
});
27+
});

0 commit comments

Comments
 (0)