forge-cc 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.forge.json +5 -0
- package/AGENTS.md +42 -0
- package/README.md +283 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +148 -0
- package/dist/cli.js.map +1 -0
- package/dist/config/loader.d.ts +2 -0
- package/dist/config/loader.js +44 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/config/schema.d.ts +57 -0
- package/dist/config/schema.js +15 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/gates/index.d.ts +11 -0
- package/dist/gates/index.js +106 -0
- package/dist/gates/index.js.map +1 -0
- package/dist/gates/lint-gate.d.ts +2 -0
- package/dist/gates/lint-gate.js +66 -0
- package/dist/gates/lint-gate.js.map +1 -0
- package/dist/gates/prd-gate.d.ts +7 -0
- package/dist/gates/prd-gate.js +193 -0
- package/dist/gates/prd-gate.js.map +1 -0
- package/dist/gates/runtime-gate.d.ts +5 -0
- package/dist/gates/runtime-gate.js +99 -0
- package/dist/gates/runtime-gate.js.map +1 -0
- package/dist/gates/tests-gate.d.ts +2 -0
- package/dist/gates/tests-gate.js +116 -0
- package/dist/gates/tests-gate.js.map +1 -0
- package/dist/gates/types-gate.d.ts +2 -0
- package/dist/gates/types-gate.js +59 -0
- package/dist/gates/types-gate.js.map +1 -0
- package/dist/gates/visual-gate.d.ts +6 -0
- package/dist/gates/visual-gate.js +118 -0
- package/dist/gates/visual-gate.js.map +1 -0
- package/dist/go/auto-chain.d.ts +107 -0
- package/dist/go/auto-chain.js +303 -0
- package/dist/go/auto-chain.js.map +1 -0
- package/dist/go/executor.d.ts +130 -0
- package/dist/go/executor.js +409 -0
- package/dist/go/executor.js.map +1 -0
- package/dist/go/finalize.d.ts +58 -0
- package/dist/go/finalize.js +200 -0
- package/dist/go/finalize.js.map +1 -0
- package/dist/go/linear-sync.d.ts +75 -0
- package/dist/go/linear-sync.js +239 -0
- package/dist/go/linear-sync.js.map +1 -0
- package/dist/go/verify-loop.d.ts +47 -0
- package/dist/go/verify-loop.js +172 -0
- package/dist/go/verify-loop.js.map +1 -0
- package/dist/hooks/pre-commit.d.ts +5 -0
- package/dist/hooks/pre-commit.js +69 -0
- package/dist/hooks/pre-commit.js.map +1 -0
- package/dist/linear/client.d.ts +108 -0
- package/dist/linear/client.js +388 -0
- package/dist/linear/client.js.map +1 -0
- package/dist/linear/issues.d.ts +20 -0
- package/dist/linear/issues.js +39 -0
- package/dist/linear/issues.js.map +1 -0
- package/dist/linear/milestones.d.ts +11 -0
- package/dist/linear/milestones.js +32 -0
- package/dist/linear/milestones.js.map +1 -0
- package/dist/linear/projects.d.ts +16 -0
- package/dist/linear/projects.js +50 -0
- package/dist/linear/projects.js.map +1 -0
- package/dist/reporter/human.d.ts +2 -0
- package/dist/reporter/human.js +63 -0
- package/dist/reporter/human.js.map +1 -0
- package/dist/reporter/json.d.ts +2 -0
- package/dist/reporter/json.js +4 -0
- package/dist/reporter/json.js.map +1 -0
- package/dist/server.d.ts +2 -0
- package/dist/server.js +109 -0
- package/dist/server.js.map +1 -0
- package/dist/spec/generator.d.ts +14 -0
- package/dist/spec/generator.js +206 -0
- package/dist/spec/generator.js.map +1 -0
- package/dist/spec/interview.d.ts +104 -0
- package/dist/spec/interview.js +342 -0
- package/dist/spec/interview.js.map +1 -0
- package/dist/spec/linear-sync.d.ts +48 -0
- package/dist/spec/linear-sync.js +125 -0
- package/dist/spec/linear-sync.js.map +1 -0
- package/dist/spec/scanner.d.ts +45 -0
- package/dist/spec/scanner.js +473 -0
- package/dist/spec/scanner.js.map +1 -0
- package/dist/spec/templates.d.ts +345 -0
- package/dist/spec/templates.js +86 -0
- package/dist/spec/templates.js.map +1 -0
- package/dist/state/reader.d.ts +29 -0
- package/dist/state/reader.js +116 -0
- package/dist/state/reader.js.map +1 -0
- package/dist/state/writer.d.ts +60 -0
- package/dist/state/writer.js +222 -0
- package/dist/state/writer.js.map +1 -0
- package/dist/types.d.ts +64 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/browser.d.ts +10 -0
- package/dist/utils/browser.js +89 -0
- package/dist/utils/browser.js.map +1 -0
- package/hooks/pre-commit-verify.js +103 -0
- package/package.json +68 -0
- package/skills/README.md +33 -0
- package/skills/forge-go.md +332 -0
- package/skills/forge-spec.md +251 -0
- package/skills/forge-triage.md +133 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"human.js","sourceRoot":"","sources":["../../src/reporter/human.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json.js","sourceRoot":"","sources":["../../src/reporter/json.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,gBAAgB,CAAC,MAAsB;IACrD,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AACzC,CAAC"}
|
package/dist/server.d.ts
ADDED
package/dist/server.js
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
import { verifyTypes, verifyLint, verifyTests, verifyVisual, verifyRuntime, verifyPrd, runPipeline, } from "./gates/index.js";
|
|
6
|
+
const server = new McpServer({
|
|
7
|
+
name: "forge-cc",
|
|
8
|
+
version: "0.1.0",
|
|
9
|
+
});
|
|
10
|
+
// Individual gate tools
|
|
11
|
+
// Each handler is wrapped in try-catch to return structured errors instead of crashing the MCP server.
|
|
12
|
+
function errorResponse(err) {
|
|
13
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
14
|
+
return { content: [{ type: "text", text: JSON.stringify({ error: message }) }] };
|
|
15
|
+
}
|
|
16
|
+
server.tool("forge_verify_types", "Run TypeScript type checking (tsc --noEmit)", { projectDir: z.string().describe("Absolute path to project root") }, async ({ projectDir }) => {
|
|
17
|
+
try {
|
|
18
|
+
const result = await verifyTypes(projectDir);
|
|
19
|
+
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
20
|
+
}
|
|
21
|
+
catch (err) {
|
|
22
|
+
return errorResponse(err);
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
server.tool("forge_verify_lint", "Run Biome linting checks", { projectDir: z.string().describe("Absolute path to project root") }, async ({ projectDir }) => {
|
|
26
|
+
try {
|
|
27
|
+
const result = await verifyLint(projectDir);
|
|
28
|
+
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
29
|
+
}
|
|
30
|
+
catch (err) {
|
|
31
|
+
return errorResponse(err);
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
server.tool("forge_verify_tests", "Run project test suite", { projectDir: z.string().describe("Absolute path to project root") }, async ({ projectDir }) => {
|
|
35
|
+
try {
|
|
36
|
+
const result = await verifyTests(projectDir);
|
|
37
|
+
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
38
|
+
}
|
|
39
|
+
catch (err) {
|
|
40
|
+
return errorResponse(err);
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
server.tool("forge_verify_visual", "Take screenshots and check for console errors", {
|
|
44
|
+
projectDir: z.string().describe("Absolute path to project root"),
|
|
45
|
+
pages: z.array(z.string()).default(["/"]).describe("Page paths to check"),
|
|
46
|
+
devServerCommand: z.string().optional().describe("Dev server start command"),
|
|
47
|
+
devServerPort: z.number().optional().describe("Dev server port"),
|
|
48
|
+
}, async ({ projectDir, pages, devServerCommand, devServerPort }) => {
|
|
49
|
+
try {
|
|
50
|
+
const result = await verifyVisual(projectDir, pages, { devServerCommand, devServerPort });
|
|
51
|
+
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
52
|
+
}
|
|
53
|
+
catch (err) {
|
|
54
|
+
return errorResponse(err);
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
server.tool("forge_verify_runtime", "Validate API endpoints return expected responses", {
|
|
58
|
+
projectDir: z.string().describe("Absolute path to project root"),
|
|
59
|
+
endpoints: z.array(z.string()).describe("API endpoints to test (e.g., 'GET /api/health')"),
|
|
60
|
+
devServerCommand: z.string().optional().describe("Dev server start command"),
|
|
61
|
+
devServerPort: z.number().optional().describe("Dev server port"),
|
|
62
|
+
}, async ({ projectDir, endpoints, devServerCommand, devServerPort }) => {
|
|
63
|
+
try {
|
|
64
|
+
const result = await verifyRuntime(projectDir, endpoints, { devServerCommand, devServerPort });
|
|
65
|
+
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
66
|
+
}
|
|
67
|
+
catch (err) {
|
|
68
|
+
return errorResponse(err);
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
server.tool("forge_verify_prd", "Check code changes against PRD acceptance criteria", {
|
|
72
|
+
projectDir: z.string().describe("Absolute path to project root"),
|
|
73
|
+
prdPath: z.string().describe("Path to PRD markdown file"),
|
|
74
|
+
baseBranch: z.string().default("main").describe("Base branch for diff comparison"),
|
|
75
|
+
}, async ({ projectDir, prdPath, baseBranch }) => {
|
|
76
|
+
try {
|
|
77
|
+
const result = await verifyPrd(projectDir, prdPath, baseBranch);
|
|
78
|
+
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
79
|
+
}
|
|
80
|
+
catch (err) {
|
|
81
|
+
return errorResponse(err);
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
server.tool("forge_run_pipeline", "Run full verification pipeline (all configured gates)", {
|
|
85
|
+
projectDir: z.string().describe("Absolute path to project root"),
|
|
86
|
+
gates: z.array(z.string()).optional().describe("Gates to run (default: types,lint,tests)"),
|
|
87
|
+
prdPath: z.string().optional().describe("Path to PRD file"),
|
|
88
|
+
maxIterations: z.number().optional().describe("Max retry iterations"),
|
|
89
|
+
}, async ({ projectDir, gates, prdPath, maxIterations }) => {
|
|
90
|
+
try {
|
|
91
|
+
const result = await runPipeline({
|
|
92
|
+
projectDir,
|
|
93
|
+
gates,
|
|
94
|
+
prdPath,
|
|
95
|
+
maxIterations,
|
|
96
|
+
});
|
|
97
|
+
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
98
|
+
}
|
|
99
|
+
catch (err) {
|
|
100
|
+
return errorResponse(err);
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
// Start server
|
|
104
|
+
async function main() {
|
|
105
|
+
const transport = new StdioServerTransport();
|
|
106
|
+
await server.connect(transport);
|
|
107
|
+
}
|
|
108
|
+
main().catch(console.error);
|
|
109
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { PRDData } from "./templates.js";
|
|
2
|
+
/**
|
|
3
|
+
* Generates a complete PRD markdown document from validated PRD data.
|
|
4
|
+
*/
|
|
5
|
+
export declare function generatePRD(data: PRDData): string;
|
|
6
|
+
/**
|
|
7
|
+
* Generates a partial PRD from incomplete data (for incremental updates during interview).
|
|
8
|
+
* Fills missing fields with placeholders.
|
|
9
|
+
*/
|
|
10
|
+
export declare function generateDraftPRD(data: Partial<PRDData>): string;
|
|
11
|
+
/**
|
|
12
|
+
* Validates PRD data, generates markdown, and writes to disk.
|
|
13
|
+
*/
|
|
14
|
+
export declare function writePRDToFile(data: PRDData, outputPath: string): void;
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import { writeFileSync, mkdirSync } from "node:fs";
|
|
2
|
+
import { dirname } from "node:path";
|
|
3
|
+
import { validatePRD } from "./templates.js";
|
|
4
|
+
// ── Section Generators ───────────────────────────────────────────────
|
|
5
|
+
function renderHeader(data) {
|
|
6
|
+
const lines = [
|
|
7
|
+
`# ${data.project} — Specification`,
|
|
8
|
+
"",
|
|
9
|
+
`**Project:** ${data.project}`,
|
|
10
|
+
`**Status:** ${data.status}`,
|
|
11
|
+
`**Branch:** ${data.branch}`,
|
|
12
|
+
`**Created:** ${data.created}`,
|
|
13
|
+
`**Assigned To:** ${data.assignedTo}`,
|
|
14
|
+
];
|
|
15
|
+
if (data.linearProject) {
|
|
16
|
+
lines.push(`**Linear Project:** ${data.linearProject}`);
|
|
17
|
+
}
|
|
18
|
+
return lines.join("\n");
|
|
19
|
+
}
|
|
20
|
+
function renderOverview(overview) {
|
|
21
|
+
return `## Overview\n\n${overview}`;
|
|
22
|
+
}
|
|
23
|
+
function renderProblemStatement(problemStatement) {
|
|
24
|
+
return `## Problem Statement\n\n${problemStatement}`;
|
|
25
|
+
}
|
|
26
|
+
function renderScope(scope) {
|
|
27
|
+
const sections = ["## Scope"];
|
|
28
|
+
sections.push("\n### In Scope");
|
|
29
|
+
for (const item of scope.inScope) {
|
|
30
|
+
sections.push(`- ${item}`);
|
|
31
|
+
}
|
|
32
|
+
sections.push("\n### Out of Scope");
|
|
33
|
+
for (const item of scope.outOfScope) {
|
|
34
|
+
sections.push(`- ${item}`);
|
|
35
|
+
}
|
|
36
|
+
sections.push("\n### Sacred / Do NOT Touch");
|
|
37
|
+
for (const item of scope.sacred) {
|
|
38
|
+
sections.push(`- ${item}`);
|
|
39
|
+
}
|
|
40
|
+
return sections.join("\n");
|
|
41
|
+
}
|
|
42
|
+
function renderUserStory(story) {
|
|
43
|
+
const lines = [
|
|
44
|
+
`### US-${story.id}: ${story.title}`,
|
|
45
|
+
`**Description:** ${story.description}`,
|
|
46
|
+
"**Acceptance Criteria:**",
|
|
47
|
+
];
|
|
48
|
+
for (const criterion of story.acceptanceCriteria) {
|
|
49
|
+
lines.push(`- [ ] ${criterion}`);
|
|
50
|
+
}
|
|
51
|
+
return lines.join("\n");
|
|
52
|
+
}
|
|
53
|
+
function renderUserStories(stories) {
|
|
54
|
+
const sections = ["## User Stories", ""];
|
|
55
|
+
for (const story of stories) {
|
|
56
|
+
sections.push(renderUserStory(story));
|
|
57
|
+
sections.push("");
|
|
58
|
+
}
|
|
59
|
+
return sections.join("\n").trimEnd();
|
|
60
|
+
}
|
|
61
|
+
function renderTechnicalDesign(design) {
|
|
62
|
+
const sections = ["## Technical Design"];
|
|
63
|
+
if (design.projectStructure) {
|
|
64
|
+
sections.push(`\n### Project Structure\n${design.projectStructure}`);
|
|
65
|
+
}
|
|
66
|
+
if (design.keyTypes) {
|
|
67
|
+
sections.push(`\n### Key Types\n${design.keyTypes}`);
|
|
68
|
+
}
|
|
69
|
+
if (design.dependencies && design.dependencies.length > 0) {
|
|
70
|
+
sections.push("\n### Dependencies");
|
|
71
|
+
for (const dep of design.dependencies) {
|
|
72
|
+
sections.push(`- ${dep}`);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
if (design.existingCode) {
|
|
76
|
+
sections.push(`\n### Existing Code\n${design.existingCode}`);
|
|
77
|
+
}
|
|
78
|
+
return sections.join("\n");
|
|
79
|
+
}
|
|
80
|
+
function renderMilestone(milestone) {
|
|
81
|
+
const lines = [
|
|
82
|
+
`### Milestone ${milestone.number}: ${milestone.name}`,
|
|
83
|
+
`**Assigned To:** ${milestone.assignedTo}`,
|
|
84
|
+
`**Goal:** ${milestone.goal}`,
|
|
85
|
+
"",
|
|
86
|
+
];
|
|
87
|
+
for (const wave of milestone.waves) {
|
|
88
|
+
const agentCount = wave.agents.length;
|
|
89
|
+
lines.push(`**Wave ${wave.waveNumber} (${agentCount} agent${agentCount !== 1 ? "s" : ""} parallel):**`);
|
|
90
|
+
for (let i = 0; i < wave.agents.length; i++) {
|
|
91
|
+
const agent = wave.agents[i];
|
|
92
|
+
lines.push(`${i + 1}. **${agent.name}**: ${agent.task}`);
|
|
93
|
+
if (agent.files.length > 0) {
|
|
94
|
+
lines.push(` - Files: ${agent.files.join(", ")}`);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
lines.push("");
|
|
98
|
+
}
|
|
99
|
+
if (milestone.verificationCommands.length > 0) {
|
|
100
|
+
lines.push("**Verification:**");
|
|
101
|
+
lines.push("```bash");
|
|
102
|
+
for (const cmd of milestone.verificationCommands) {
|
|
103
|
+
lines.push(cmd);
|
|
104
|
+
}
|
|
105
|
+
lines.push("```");
|
|
106
|
+
}
|
|
107
|
+
return lines.join("\n");
|
|
108
|
+
}
|
|
109
|
+
function renderMilestones(milestones) {
|
|
110
|
+
const sections = ["## Implementation Milestones", ""];
|
|
111
|
+
for (const milestone of milestones) {
|
|
112
|
+
sections.push(renderMilestone(milestone));
|
|
113
|
+
sections.push("");
|
|
114
|
+
sections.push("---");
|
|
115
|
+
sections.push("");
|
|
116
|
+
}
|
|
117
|
+
// Remove trailing separator
|
|
118
|
+
if (sections.length > 2) {
|
|
119
|
+
sections.pop(); // empty line
|
|
120
|
+
sections.pop(); // ---
|
|
121
|
+
}
|
|
122
|
+
return sections.join("\n").trimEnd();
|
|
123
|
+
}
|
|
124
|
+
function renderVerification(verification) {
|
|
125
|
+
const sections = ["## Verification"];
|
|
126
|
+
sections.push("\n### Per-Milestone");
|
|
127
|
+
for (const item of verification.perMilestone) {
|
|
128
|
+
sections.push(`- ${item}`);
|
|
129
|
+
}
|
|
130
|
+
sections.push("\n### Overall");
|
|
131
|
+
for (const item of verification.overall) {
|
|
132
|
+
sections.push(`- ${item}`);
|
|
133
|
+
}
|
|
134
|
+
return sections.join("\n");
|
|
135
|
+
}
|
|
136
|
+
// ── Public API ───────────────────────────────────────────────────────
|
|
137
|
+
/**
|
|
138
|
+
* Generates a complete PRD markdown document from validated PRD data.
|
|
139
|
+
*/
|
|
140
|
+
export function generatePRD(data) {
|
|
141
|
+
const sections = [
|
|
142
|
+
renderHeader(data),
|
|
143
|
+
renderOverview(data.overview),
|
|
144
|
+
renderProblemStatement(data.problemStatement),
|
|
145
|
+
renderScope(data.scope),
|
|
146
|
+
renderUserStories(data.userStories),
|
|
147
|
+
renderTechnicalDesign(data.technicalDesign),
|
|
148
|
+
renderMilestones(data.milestones),
|
|
149
|
+
renderVerification(data.verification),
|
|
150
|
+
];
|
|
151
|
+
return sections.join("\n\n") + "\n";
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Generates a partial PRD from incomplete data (for incremental updates during interview).
|
|
155
|
+
* Fills missing fields with placeholders.
|
|
156
|
+
*/
|
|
157
|
+
export function generateDraftPRD(data) {
|
|
158
|
+
const sections = [];
|
|
159
|
+
// Header — always present
|
|
160
|
+
const project = data.project ?? "Untitled Project";
|
|
161
|
+
const headerLines = [
|
|
162
|
+
`# ${project} — Specification`,
|
|
163
|
+
"",
|
|
164
|
+
`**Project:** ${project}`,
|
|
165
|
+
`**Status:** ${data.status ?? "Draft"}`,
|
|
166
|
+
`**Branch:** ${data.branch ?? "TBD"}`,
|
|
167
|
+
`**Created:** ${data.created ?? new Date().toISOString().split("T")[0]}`,
|
|
168
|
+
`**Assigned To:** ${data.assignedTo ?? "TBD"}`,
|
|
169
|
+
];
|
|
170
|
+
if (data.linearProject) {
|
|
171
|
+
headerLines.push(`**Linear Project:** ${data.linearProject}`);
|
|
172
|
+
}
|
|
173
|
+
sections.push(headerLines.join("\n"));
|
|
174
|
+
if (data.overview) {
|
|
175
|
+
sections.push(renderOverview(data.overview));
|
|
176
|
+
}
|
|
177
|
+
if (data.problemStatement) {
|
|
178
|
+
sections.push(renderProblemStatement(data.problemStatement));
|
|
179
|
+
}
|
|
180
|
+
if (data.scope) {
|
|
181
|
+
sections.push(renderScope(data.scope));
|
|
182
|
+
}
|
|
183
|
+
if (data.userStories && data.userStories.length > 0) {
|
|
184
|
+
sections.push(renderUserStories(data.userStories));
|
|
185
|
+
}
|
|
186
|
+
if (data.technicalDesign) {
|
|
187
|
+
sections.push(renderTechnicalDesign(data.technicalDesign));
|
|
188
|
+
}
|
|
189
|
+
if (data.milestones && data.milestones.length > 0) {
|
|
190
|
+
sections.push(renderMilestones(data.milestones));
|
|
191
|
+
}
|
|
192
|
+
if (data.verification) {
|
|
193
|
+
sections.push(renderVerification(data.verification));
|
|
194
|
+
}
|
|
195
|
+
return sections.join("\n\n") + "\n";
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Validates PRD data, generates markdown, and writes to disk.
|
|
199
|
+
*/
|
|
200
|
+
export function writePRDToFile(data, outputPath) {
|
|
201
|
+
const validated = validatePRD(data);
|
|
202
|
+
const markdown = generatePRD(validated);
|
|
203
|
+
mkdirSync(dirname(outputPath), { recursive: true });
|
|
204
|
+
writeFileSync(outputPath, markdown, "utf-8");
|
|
205
|
+
}
|
|
206
|
+
//# sourceMappingURL=generator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generator.js","sourceRoot":"","sources":["../../src/spec/generator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Adaptive interview engine for spec generation.
|
|
3
|
+
*
|
|
4
|
+
* Pure logic — no side effects, no I/O. All state is passed in and returned.
|
|
5
|
+
* The interview leads with recommendations derived from codebase scan results,
|
|
6
|
+
* follows interesting threads based on user responses, and determines when
|
|
7
|
+
* enough info has been gathered for each PRD section.
|
|
8
|
+
*/
|
|
9
|
+
import type { ScanAllResult } from "./scanner.js";
|
|
10
|
+
/** PRD sections in priority order */
|
|
11
|
+
export declare const PRD_SECTIONS: readonly ["problem_and_goals", "user_stories", "technical_approach", "scope", "milestones"];
|
|
12
|
+
export type PRDSection = (typeof PRD_SECTIONS)[number];
|
|
13
|
+
/** Human-readable labels for each section */
|
|
14
|
+
export declare const SECTION_LABELS: Record<PRDSection, string>;
|
|
15
|
+
/** A single interview question */
|
|
16
|
+
export interface InterviewQuestion {
|
|
17
|
+
id: string;
|
|
18
|
+
section: PRDSection;
|
|
19
|
+
text: string;
|
|
20
|
+
/** Recommendation or observation that motivates the question */
|
|
21
|
+
context: string;
|
|
22
|
+
/** Follow-up depth — 0 = top-level, 1+ = follow-up */
|
|
23
|
+
depth: number;
|
|
24
|
+
}
|
|
25
|
+
/** A recorded answer to a question */
|
|
26
|
+
export interface InterviewAnswer {
|
|
27
|
+
questionId: string;
|
|
28
|
+
section: PRDSection;
|
|
29
|
+
answer: string;
|
|
30
|
+
timestamp: number;
|
|
31
|
+
}
|
|
32
|
+
/** Completeness status for a single section */
|
|
33
|
+
export interface SectionStatus {
|
|
34
|
+
section: PRDSection;
|
|
35
|
+
answeredCount: number;
|
|
36
|
+
/** Minimum answers needed before the section is considered covered */
|
|
37
|
+
minRequired: number;
|
|
38
|
+
isComplete: boolean;
|
|
39
|
+
}
|
|
40
|
+
/** Full interview state — serializable, passed in/out of every function */
|
|
41
|
+
export interface InterviewState {
|
|
42
|
+
projectName: string;
|
|
43
|
+
scanResults: ScanAllResult;
|
|
44
|
+
questions: InterviewQuestion[];
|
|
45
|
+
answers: InterviewAnswer[];
|
|
46
|
+
/** Counter used to generate unique question IDs */
|
|
47
|
+
nextQuestionId: number;
|
|
48
|
+
/** Tracks which sections the engine has asked top-level questions for */
|
|
49
|
+
askedSections: PRDSection[];
|
|
50
|
+
/** Number of answers recorded since the last PRD draft update */
|
|
51
|
+
answersSinceLastDraft: number;
|
|
52
|
+
}
|
|
53
|
+
/** Structured summary of gathered info for PRD generation */
|
|
54
|
+
export interface InterviewSummary {
|
|
55
|
+
projectName: string;
|
|
56
|
+
sections: Record<PRDSection, {
|
|
57
|
+
label: string;
|
|
58
|
+
answers: Array<{
|
|
59
|
+
question: string;
|
|
60
|
+
answer: string;
|
|
61
|
+
}>;
|
|
62
|
+
isComplete: boolean;
|
|
63
|
+
}>;
|
|
64
|
+
scanResults: ScanAllResult;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Initialize a new interview with codebase context.
|
|
68
|
+
* The scan results inform the recommendations attached to questions.
|
|
69
|
+
*/
|
|
70
|
+
export declare function createInterview(projectName: string, scanResults: ScanAllResult): InterviewState;
|
|
71
|
+
/**
|
|
72
|
+
* Generate 1-3 next questions based on current state.
|
|
73
|
+
* Prioritizes sections with the most gaps, leads with recommendations.
|
|
74
|
+
* Returns questions and the updated state (with new questions appended).
|
|
75
|
+
*/
|
|
76
|
+
export declare function generateNextQuestions(state: InterviewState): {
|
|
77
|
+
questions: InterviewQuestion[];
|
|
78
|
+
state: InterviewState;
|
|
79
|
+
};
|
|
80
|
+
/**
|
|
81
|
+
* Record the user's answer and return updated state.
|
|
82
|
+
*/
|
|
83
|
+
export declare function recordAnswer(state: InterviewState, questionId: string, answer: string): InterviewState;
|
|
84
|
+
/**
|
|
85
|
+
* Returns true every 2-3 answers (triggers at 2, then every 3).
|
|
86
|
+
* The caller is responsible for resetting the counter after updating the draft.
|
|
87
|
+
*/
|
|
88
|
+
export declare function shouldUpdateDraft(state: InterviewState): boolean;
|
|
89
|
+
/**
|
|
90
|
+
* Reset the draft update counter (call after updating the PRD draft).
|
|
91
|
+
*/
|
|
92
|
+
export declare function markDraftUpdated(state: InterviewState): InterviewState;
|
|
93
|
+
/**
|
|
94
|
+
* Returns true when all sections have met their minimum answer thresholds.
|
|
95
|
+
*/
|
|
96
|
+
export declare function isComplete(state: InterviewState): boolean;
|
|
97
|
+
/**
|
|
98
|
+
* Get the completeness status for all sections.
|
|
99
|
+
*/
|
|
100
|
+
export declare function getSectionStatuses(state: InterviewState): SectionStatus[];
|
|
101
|
+
/**
|
|
102
|
+
* Build a structured summary of everything gathered, for PRD generation.
|
|
103
|
+
*/
|
|
104
|
+
export declare function getInterviewSummary(state: InterviewState): InterviewSummary;
|