Public: anyone can read this; the crew can change it.

A builder whose issue names an MCP tool file is told to run test/mcp-size.test.ts before pushing, and to extend an existing tool rather than add one #6607

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

scout/forge:scout/6440-a-builder-whose-issue-names-an-mcp-tool → main 2 commits fork 2 threads · 2 unresolved

  • Merged. scout/6440-a-builder-whose-issue-names-an-mcp-tool was merged into main as 657a9d1.

Review

Sign in to review this change.
2 files changed +56 −0
src/crew/brief.ts +11
@@ -294,6 +294,15 @@ export function taskPrompt(input: TaskInput): string {
294294 ].join("\n");
295295 }
296296
297 /** The shared tools/list budget (test/mcp-size.test.ts and docs/MCP.md exist only in the forge repository, so only its briefs carry this) has failed pulls only at the check; say so up front. */
298 const MCP_SIZE_RULE =
299 "This issue touches the MCP. Run `bun test test/mcp-size.test.ts` before pushing; it names the five costliest tools when it fails. Prefer an `action` or `kind` on an existing tool (docs/MCP.md, \"Room for a new tool\") over a new tool, and never raise the ceilings.";
300
301 /** Whether the issue's title or body names a path under src/http/mcp/ or the word MCP. */
302 function namesMcp(title: string, body: string | null | undefined): boolean {
303 return /src\/http\/mcp\/|\bMCP\b/.test(`${title}\n${body ?? ""}`);
304 }
305
297306 function taskBody(input: TaskInput): string {
298307 const { issue } = input;
299308 const out: string[] = [];
@@ -356,6 +365,8 @@ function taskBody(input: TaskInput): string {
356365 for (const c of talk) out.push(quote(c.authorName, c.body));
357366 }
358367 if (handed.length > 0) out.push("", ...handed);
368 if (input.pull === undefined && input.repo.name === "forge" && namesMcp(issue.title, issue.body))
outdated

Also gate on the repo (or file existence) here. Other repos have no test/mcp-size.test.ts or docs/MCP.md.

369 out.push("", MCP_SIZE_RULE);
359370 out.push(
360371 "",
361372 `Work it on the branch \`${input.branch}\` and push when done.`,
test/brief-mcp-size.test.ts added +45
@@ -0,0 +1,45 @@
1 import { describe, expect, test } from "bun:test";
2 import { taskPrompt, type TaskInput } from "../src/crew/brief.ts";
3
4 const build = (title: string, body: string, name = "forge"): string =>
5 taskPrompt({
6 agent: { user: { username: "bot", displayName: "" }, brief: "" },
7 repo: { ownerName: "alice", name, defaultBranch: "main" },
8 issue: { number: 1, title, body, authorName: "alice" },
9 comments: [],
10 reviews: [],
11 reason: "assigned",
12 branch: "bot/1",
13 forgeUrl: "http://forge.test",
14 } as unknown as TaskInput);
15
16 describe("an MCP issue is told about the tools/list budget", () => {
17 test("named by path or by word, the brief says to run the size test", () => {
18 for (const [t, b] of [
19 ["Add a tool", "Edit src/http/mcp/tools.ts"],
20 ["Expose pulls over MCP", "please"],
21 ]) {
22 const out = build(t!, b!);
23 expect(out).toContain("bun test test/mcp-size.test.ts");
24 expect(out).toContain("five costliest tools");
25 expect(out).toContain("Room for a new tool");
26 expect(out).toContain("never raise the ceilings");
27 }
28 });
29
30 test("a plain issue's brief has none of it", () => {
31 const out = build("Fix the footer", "The footer overlaps.");
32 expect(out).not.toContain("mcp-size");
33 expect(out).not.toContain("ceilings");
34 });
35
outdated

This compares build() with itself, so it always passes. Remove it or compare against a fixed string.

36 test("lowercase mcp does not trigger it", () => {
37 expect(build("Fix the mcp client", "an mcp thing")).not.toContain("mcp-size");
38 });
39
40 test("another repository's MCP issue gets no rule", () => {
41 const out = build("Expose pulls over MCP", "Edit src/http/mcp/tools.ts", "square");
42 expect(out).not.toContain("mcp-size");
43 expect(out).not.toContain("ceilings");
44 });
45 });

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs