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
Check · Review · Land · Live done — Landed and live in production.
scout/forge:scout/6440-a-builder-whose-issue-names-an-mcp-tool → main 2 commits fork 2 threads · 2 unresolved
2 files
changed +56
−0
src/crew/brief.ts +11
| @@ -294,6 +294,15 @@ export function taskPrompt(input: TaskInput): string { | ||
| 294 | 294 | ].join("\n"); |
| 295 | 295 | } |
| 296 | 296 | |
| 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 | ||
| 297 | 306 | function taskBody(input: TaskInput): string { |
| 298 | 307 | const { issue } = input; |
| 299 | 308 | const out: string[] = []; |
| @@ -356,6 +365,8 @@ function taskBody(input: TaskInput): string { | ||
| 356 | 365 | for (const c of talk) out.push(quote(c.authorName, c.body)); |
| 357 | 366 | } |
| 358 | 367 | if (handed.length > 0) out.push("", ...handed); |
| 368 | if (input.pull === undefined && input.repo.name === "forge" && namesMcp(issue.title, issue.body)) | |
| 369 | out.push("", MCP_SIZE_RULE); | |
| 359 | 370 | out.push( |
| 360 | 371 | "", |
| 361 | 372 | `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 | }); |
new above
offline
Also gate on the repo (or file existence) here. Other repos have no test/mcp-size.test.ts or docs/MCP.md.