diff --git a/src/resources/extensions/gsd/auto-prompts.ts b/src/resources/extensions/gsd/auto-prompts.ts index 5e1984c56..1ea0e3366 100644 --- a/src/resources/extensions/gsd/auto-prompts.ts +++ b/src/resources/extensions/gsd/auto-prompts.ts @@ -87,6 +87,11 @@ function buildSourceFilePaths( paths.push(`- **Decisions**: \`${relGsdRootFile("DECISIONS")}\``); } + const queuePath = resolveGsdRootFile(base, "QUEUE"); + if (existsSync(queuePath)) { + paths.push(`- **Queue**: \`${relGsdRootFile("QUEUE")}\``); + } + const contextPath = resolveMilestoneFile(base, mid, "CONTEXT"); if (contextPath) { paths.push(`- **Milestone Context**: \`${relMilestoneFile(base, mid, "CONTEXT")}\``); @@ -915,6 +920,16 @@ export async function buildPlanMilestonePrompt(mid: string, midTitle: string, ba const decisionsInline = await inlineDecisionsFromDb(base, mid, undefined, inlineLevel); if (decisionsInline) inlined.push(decisionsInline); } + const queuePath = resolveGsdRootFile(base, "QUEUE"); + if (existsSync(queuePath)) { + const queueInline = await inlineFileSmart( + queuePath, + relGsdRootFile("QUEUE"), + "Project Queue", + `${mid} ${midTitle}`, + ); + inlined.push(queueInline); + } const knowledgeInlinePM = await inlineGsdRootFile(base, "knowledge.md", "Project Knowledge"); if (knowledgeInlinePM) inlined.push(knowledgeInlinePM); inlined.push(inlineTemplate("roadmap", "Roadmap")); diff --git a/src/resources/extensions/gsd/tests/plan-milestone-queue-context.test.ts b/src/resources/extensions/gsd/tests/plan-milestone-queue-context.test.ts new file mode 100644 index 000000000..83a2f955d --- /dev/null +++ b/src/resources/extensions/gsd/tests/plan-milestone-queue-context.test.ts @@ -0,0 +1,48 @@ +import { describe, test } from "node:test"; +import assert from "node:assert/strict"; +import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from "node:fs"; +import { join } from "node:path"; +import { tmpdir } from "node:os"; + +import { buildPlanMilestonePrompt } from "../auto-prompts.ts"; + +function createBase(): string { + const base = mkdtempSync(join(tmpdir(), "gsd-plan-queue-")); + mkdirSync(join(base, ".gsd", "milestones", "M010"), { recursive: true }); + return base; +} + +function cleanup(base: string): void { + rmSync(base, { recursive: true, force: true }); +} + +describe("plan-milestone queue context", () => { + test("includes queue brief when planning milestone without roadmap context", async () => { + const base = createBase(); + try { + writeFileSync( + join(base, ".gsd", "QUEUE.md"), + [ + "# Queue", + "", + "### M010: Analytics Dashboard — Interactivity, Intelligence & Demo Readiness", + "**Vision:** Ship a polished analytics dashboard with drilldowns and AI assistance.", + "", + "## Scope", + "- Interactivity", + "- Intelligence", + "- Demo readiness", + "", + ].join("\n"), + ); + + const prompt = await buildPlanMilestonePrompt("M010", "M010", base); + + assert.match(prompt, /Source: `\.gsd\/QUEUE\.md`/); + assert.match(prompt, /Analytics Dashboard — Interactivity, Intelligence & Demo Readiness/); + assert.match(prompt, /Ship a polished analytics dashboard/); + } finally { + cleanup(base); + } + }); +});