sdd-cli 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/README.md +566 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +308 -0
- package/dist/commands/ai-exec.d.ts +1 -0
- package/dist/commands/ai-exec.js +18 -0
- package/dist/commands/ai-status.d.ts +1 -0
- package/dist/commands/ai-status.js +12 -0
- package/dist/commands/doctor.d.ts +1 -0
- package/dist/commands/doctor.js +101 -0
- package/dist/commands/gen-architecture.d.ts +1 -0
- package/dist/commands/gen-architecture.js +61 -0
- package/dist/commands/gen-best-practices.d.ts +1 -0
- package/dist/commands/gen-best-practices.js +64 -0
- package/dist/commands/gen-functional-spec.d.ts +1 -0
- package/dist/commands/gen-functional-spec.js +67 -0
- package/dist/commands/gen-project-readme.d.ts +1 -0
- package/dist/commands/gen-project-readme.js +72 -0
- package/dist/commands/gen-requirements.d.ts +1 -0
- package/dist/commands/gen-requirements.js +7 -0
- package/dist/commands/gen-technical-spec.d.ts +1 -0
- package/dist/commands/gen-technical-spec.js +67 -0
- package/dist/commands/gen-utils.d.ts +4 -0
- package/dist/commands/gen-utils.js +44 -0
- package/dist/commands/hello.d.ts +1 -0
- package/dist/commands/hello.js +63 -0
- package/dist/commands/init.d.ts +1 -0
- package/dist/commands/init.js +9 -0
- package/dist/commands/learn-deliver.d.ts +1 -0
- package/dist/commands/learn-deliver.js +55 -0
- package/dist/commands/learn-refine.d.ts +1 -0
- package/dist/commands/learn-refine.js +71 -0
- package/dist/commands/learn-start.d.ts +1 -0
- package/dist/commands/learn-start.js +63 -0
- package/dist/commands/learn-utils.d.ts +22 -0
- package/dist/commands/learn-utils.js +78 -0
- package/dist/commands/list.d.ts +1 -0
- package/dist/commands/list.js +69 -0
- package/dist/commands/pr-audit.d.ts +1 -0
- package/dist/commands/pr-audit.js +59 -0
- package/dist/commands/pr-finish.d.ts +1 -0
- package/dist/commands/pr-finish.js +51 -0
- package/dist/commands/pr-report.d.ts +1 -0
- package/dist/commands/pr-report.js +59 -0
- package/dist/commands/pr-respond.d.ts +1 -0
- package/dist/commands/pr-respond.js +65 -0
- package/dist/commands/pr-start.d.ts +1 -0
- package/dist/commands/pr-start.js +79 -0
- package/dist/commands/pr-utils.d.ts +8 -0
- package/dist/commands/pr-utils.js +54 -0
- package/dist/commands/req-archive.d.ts +1 -0
- package/dist/commands/req-archive.js +33 -0
- package/dist/commands/req-create.d.ts +10 -0
- package/dist/commands/req-create.js +94 -0
- package/dist/commands/req-export.d.ts +1 -0
- package/dist/commands/req-export.js +37 -0
- package/dist/commands/req-finish.d.ts +1 -0
- package/dist/commands/req-finish.js +120 -0
- package/dist/commands/req-lint.d.ts +1 -0
- package/dist/commands/req-lint.js +58 -0
- package/dist/commands/req-list.d.ts +1 -0
- package/dist/commands/req-list.js +36 -0
- package/dist/commands/req-plan.d.ts +1 -0
- package/dist/commands/req-plan.js +200 -0
- package/dist/commands/req-refine.d.ts +1 -0
- package/dist/commands/req-refine.js +108 -0
- package/dist/commands/req-report.d.ts +1 -0
- package/dist/commands/req-report.js +44 -0
- package/dist/commands/req-start.d.ts +1 -0
- package/dist/commands/req-start.js +131 -0
- package/dist/commands/req-status.d.ts +1 -0
- package/dist/commands/req-status.js +29 -0
- package/dist/commands/route.d.ts +1 -0
- package/dist/commands/route.js +30 -0
- package/dist/commands/test-plan.d.ts +1 -0
- package/dist/commands/test-plan.js +81 -0
- package/dist/context/flags.d.ts +7 -0
- package/dist/context/flags.js +17 -0
- package/dist/paths.d.ts +1 -0
- package/dist/paths.js +10 -0
- package/dist/providers/codex.d.ts +7 -0
- package/dist/providers/codex.js +19 -0
- package/dist/router/flow.d.ts +1 -0
- package/dist/router/flow.js +17 -0
- package/dist/router/intent.d.ts +3 -0
- package/dist/router/intent.js +69 -0
- package/dist/router/prompt-map.d.ts +1 -0
- package/dist/router/prompt-map.js +20 -0
- package/dist/router/prompt-packs.d.ts +8 -0
- package/dist/router/prompt-packs.js +20 -0
- package/dist/router/validate-prompt-packs.d.ts +4 -0
- package/dist/router/validate-prompt-packs.js +16 -0
- package/dist/templates/render.d.ts +2 -0
- package/dist/templates/render.js +25 -0
- package/dist/templates/validate.d.ts +4 -0
- package/dist/templates/validate.js +58 -0
- package/dist/types.d.ts +7 -0
- package/dist/types.js +2 -0
- package/dist/ui/prompt.d.ts +2 -0
- package/dist/ui/prompt.js +49 -0
- package/dist/utils/list.d.ts +2 -0
- package/dist/utils/list.js +20 -0
- package/dist/validation/validate.d.ts +4 -0
- package/dist/validation/validate.js +20 -0
- package/dist/workspace/index.d.ts +21 -0
- package/dist/workspace/index.js +103 -0
- package/flows/ADMISSIONS_ADMIN.md +33 -0
- package/flows/ART.md +33 -0
- package/flows/BUG_FIX.md +32 -0
- package/flows/COURT_SYSTEM.md +33 -0
- package/flows/DATA_SCIENTIST.md +33 -0
- package/flows/ECOMMERCE.md +33 -0
- package/flows/ECONOMICS.md +33 -0
- package/flows/GRAPHIC_DESIGN.md +33 -0
- package/flows/HISTORY.md +33 -0
- package/flows/LAWYER.md +34 -0
- package/flows/PROGRAMMER.md +33 -0
- package/flows/PR_REVIEW.md +33 -0
- package/flows/README.md +29 -0
- package/flows/RETAIL_STORE.md +33 -0
- package/flows/SOCIOLOGY.md +33 -0
- package/flows/STATE_ADMIN.md +33 -0
- package/flows/STUDENT_UNIVERSITY.md +33 -0
- package/flows/TAXES_ADMIN.md +33 -0
- package/flows/TEACHER.md +33 -0
- package/package.json +32 -0
- package/router/BUG_FIX.flow.md +63 -0
- package/router/BUSINESS.flow.md +57 -0
- package/router/DATA_SCIENCE.flow.md +58 -0
- package/router/DESIGN.flow.md +58 -0
- package/router/FLOW_TEMPLATE.md +26 -0
- package/router/GENERIC.flow.md +37 -0
- package/router/HUMANITIES.flow.md +58 -0
- package/router/LEARN.flow.md +52 -0
- package/router/LEGAL.flow.md +58 -0
- package/router/PR_REVIEW.flow.md +55 -0
- package/router/README.md +23 -0
- package/router/SOFTWARE_FEATURE.flow.md +59 -0
- package/schemas/architecture.schema.json +13 -0
- package/schemas/decision-log.schema.json +16 -0
- package/schemas/diagram.schema.json +11 -0
- package/schemas/domain.schema.json +20 -0
- package/schemas/functional-spec.schema.json +15 -0
- package/schemas/gate.schema.json +10 -0
- package/schemas/learn-session.schema.json +15 -0
- package/schemas/pr-review.schema.json +20 -0
- package/schemas/progress-log.schema.json +21 -0
- package/schemas/project-readme.schema.json +23 -0
- package/schemas/project.schema.json +16 -0
- package/schemas/prompt-pack.schema.json +12 -0
- package/schemas/quality.schema.json +23 -0
- package/schemas/requirement.schema.json +34 -0
- package/schemas/role.schema.json +17 -0
- package/schemas/router-flow.schema.json +15 -0
- package/schemas/router-intent.schema.json +13 -0
- package/schemas/technical-spec.schema.json +15 -0
- package/schemas/template.schema.json +10 -0
- package/schemas/test-plan.schema.json +13 -0
- package/schemas/workspace.schema.json +12 -0
- package/templates/architecture.md +16 -0
- package/templates/changelog.md +3 -0
- package/templates/ci-checklist.md +14 -0
- package/templates/decision-log.md +16 -0
- package/templates/diagrams/component.mmd +3 -0
- package/templates/diagrams/container.mmd +3 -0
- package/templates/diagrams/context.mmd +3 -0
- package/templates/functional-spec.md +22 -0
- package/templates/gate-index.json +20 -0
- package/templates/implementation-plan.md +13 -0
- package/templates/pr-comment-audit.md +19 -0
- package/templates/pr-comment-lifecycle.md +11 -0
- package/templates/pr-comment-severity.md +13 -0
- package/templates/pr-dispute-resolution.md +16 -0
- package/templates/pr-metrics.md +10 -0
- package/templates/pr-response-generator.md +11 -0
- package/templates/pr-response-style.md +13 -0
- package/templates/pr-review-report.md +22 -0
- package/templates/pr-review-summary.md +16 -0
- package/templates/progress-log.md +6 -0
- package/templates/project-readme.md +19 -0
- package/templates/prompt-pack-index.json +127 -0
- package/templates/quality.yml +17 -0
- package/templates/requirement.md +33 -0
- package/templates/summary.md +10 -0
- package/templates/technical-spec.md +22 -0
- package/templates/template-index.json +212 -0
- package/templates/test-plan.md +16 -0
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.runReqFinish = runReqFinish;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const prompt_1 = require("../ui/prompt");
|
|
10
|
+
const index_1 = require("../workspace/index");
|
|
11
|
+
const render_1 = require("../templates/render");
|
|
12
|
+
const validate_1 = require("../validation/validate");
|
|
13
|
+
function findRequirementDir(workspaceRoot, project, reqId) {
|
|
14
|
+
const backlog = path_1.default.join(workspaceRoot, project, "requirements", "backlog", reqId);
|
|
15
|
+
const wip = path_1.default.join(workspaceRoot, project, "requirements", "wip", reqId);
|
|
16
|
+
const inProgress = path_1.default.join(workspaceRoot, project, "requirements", "in-progress", reqId);
|
|
17
|
+
if (fs_1.default.existsSync(backlog))
|
|
18
|
+
return backlog;
|
|
19
|
+
if (fs_1.default.existsSync(wip))
|
|
20
|
+
return wip;
|
|
21
|
+
if (fs_1.default.existsSync(inProgress))
|
|
22
|
+
return inProgress;
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
async function runReqFinish() {
|
|
26
|
+
const projectName = await (0, prompt_1.ask)("Project name: ");
|
|
27
|
+
const reqId = await (0, prompt_1.ask)("Requirement ID (REQ-...): ");
|
|
28
|
+
if (!projectName || !reqId) {
|
|
29
|
+
console.log("Project name and requirement ID are required.");
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
const workspace = (0, index_1.getWorkspaceInfo)();
|
|
33
|
+
const requirementDir = findRequirementDir(workspace.root, projectName, reqId);
|
|
34
|
+
if (!requirementDir) {
|
|
35
|
+
console.log("Requirement not found.");
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
const jsonFiles = fs_1.default.readdirSync(requirementDir).filter((file) => file.endsWith(".json"));
|
|
39
|
+
const schemaMap = {
|
|
40
|
+
"requirement.json": "requirement.schema.json",
|
|
41
|
+
"functional-spec.json": "functional-spec.schema.json",
|
|
42
|
+
"technical-spec.json": "technical-spec.schema.json",
|
|
43
|
+
"architecture.json": "architecture.schema.json",
|
|
44
|
+
"test-plan.json": "test-plan.schema.json",
|
|
45
|
+
"quality.json": "quality.schema.json"
|
|
46
|
+
};
|
|
47
|
+
for (const file of jsonFiles) {
|
|
48
|
+
const schema = schemaMap[file];
|
|
49
|
+
if (!schema)
|
|
50
|
+
continue;
|
|
51
|
+
const data = JSON.parse(fs_1.default.readFileSync(path_1.default.join(requirementDir, file), "utf-8"));
|
|
52
|
+
const result = (0, validate_1.validateJson)(schema, data);
|
|
53
|
+
if (!result.valid) {
|
|
54
|
+
console.log(`Validation failed for ${file}:`);
|
|
55
|
+
result.errors.forEach((error) => console.log(`- ${error}`));
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
const doneDir = path_1.default.join(workspace.root, projectName, "requirements", "done", reqId);
|
|
60
|
+
fs_1.default.mkdirSync(path_1.default.dirname(doneDir), { recursive: true });
|
|
61
|
+
fs_1.default.renameSync(requirementDir, doneDir);
|
|
62
|
+
(0, index_1.updateProjectStatus)(workspace, projectName, "done");
|
|
63
|
+
const overview = await (0, prompt_1.ask)("Project overview (for README): ");
|
|
64
|
+
const howToRun = await (0, prompt_1.ask)("How to run (for README): ");
|
|
65
|
+
const archSummary = await (0, prompt_1.ask)("Architecture summary (for README): ");
|
|
66
|
+
const testingNotes = await (0, prompt_1.ask)("Testing notes (for README): ");
|
|
67
|
+
const readmeTemplate = (0, render_1.loadTemplate)("project-readme");
|
|
68
|
+
const readmeRendered = (0, render_1.renderTemplate)(readmeTemplate, {
|
|
69
|
+
project_name: projectName,
|
|
70
|
+
overview: overview || "N/A",
|
|
71
|
+
how_to_run: howToRun || "N/A",
|
|
72
|
+
architecture_summary: archSummary || "N/A",
|
|
73
|
+
requirements_link: `requirements/done/${reqId}/requirement.md`,
|
|
74
|
+
functional_spec_link: `requirements/done/${reqId}/functional-spec.md`,
|
|
75
|
+
technical_spec_link: `requirements/done/${reqId}/technical-spec.md`,
|
|
76
|
+
architecture_link: `requirements/done/${reqId}/architecture.md`,
|
|
77
|
+
testing_notes: testingNotes || "N/A"
|
|
78
|
+
});
|
|
79
|
+
const readmeJson = {
|
|
80
|
+
projectName,
|
|
81
|
+
overview: overview || "N/A",
|
|
82
|
+
howToRun: howToRun || "N/A",
|
|
83
|
+
architectureSummary: archSummary || "N/A",
|
|
84
|
+
specs: {
|
|
85
|
+
requirements: `requirements/done/${reqId}/requirement.md`,
|
|
86
|
+
functionalSpec: `requirements/done/${reqId}/functional-spec.md`,
|
|
87
|
+
technicalSpec: `requirements/done/${reqId}/technical-spec.md`,
|
|
88
|
+
architecture: `requirements/done/${reqId}/architecture.md`
|
|
89
|
+
},
|
|
90
|
+
testingNotes: testingNotes || "N/A"
|
|
91
|
+
};
|
|
92
|
+
const readmeValidation = (0, validate_1.validateJson)("project-readme.schema.json", readmeJson);
|
|
93
|
+
if (!readmeValidation.valid) {
|
|
94
|
+
console.log("Project README validation failed:");
|
|
95
|
+
readmeValidation.errors.forEach((error) => console.log(`- ${error}`));
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
const projectRoot = path_1.default.join(workspace.root, projectName);
|
|
99
|
+
fs_1.default.writeFileSync(path_1.default.join(projectRoot, "project-readme.md"), readmeRendered, "utf-8");
|
|
100
|
+
fs_1.default.writeFileSync(path_1.default.join(projectRoot, "project-readme.json"), JSON.stringify(readmeJson, null, 2), "utf-8");
|
|
101
|
+
const decisionLog = path_1.default.join(doneDir, "decision-log");
|
|
102
|
+
if (fs_1.default.existsSync(decisionLog)) {
|
|
103
|
+
const archiveRoot = path_1.default.join(projectRoot, "decision-log", reqId);
|
|
104
|
+
fs_1.default.mkdirSync(path_1.default.dirname(archiveRoot), { recursive: true });
|
|
105
|
+
fs_1.default.renameSync(decisionLog, archiveRoot);
|
|
106
|
+
}
|
|
107
|
+
const progressLog = path_1.default.join(doneDir, "progress-log.md");
|
|
108
|
+
if (!fs_1.default.existsSync(progressLog)) {
|
|
109
|
+
fs_1.default.writeFileSync(progressLog, "# Progress Log\n\n", "utf-8");
|
|
110
|
+
}
|
|
111
|
+
const logEntry = `\n- ${new Date().toISOString()} finished requirement ${reqId}\n`;
|
|
112
|
+
fs_1.default.appendFileSync(progressLog, logEntry, "utf-8");
|
|
113
|
+
const changelog = path_1.default.join(doneDir, "changelog.md");
|
|
114
|
+
if (!fs_1.default.existsSync(changelog)) {
|
|
115
|
+
fs_1.default.writeFileSync(changelog, "# Changelog\n\n", "utf-8");
|
|
116
|
+
}
|
|
117
|
+
const changeEntry = `\n- ${new Date().toISOString()} finished requirement ${reqId}\n`;
|
|
118
|
+
fs_1.default.appendFileSync(changelog, changeEntry, "utf-8");
|
|
119
|
+
console.log(`Moved requirement to ${doneDir}`);
|
|
120
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function runReqLint(): Promise<void>;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.runReqLint = runReqLint;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const prompt_1 = require("../ui/prompt");
|
|
10
|
+
const index_1 = require("../workspace/index");
|
|
11
|
+
const validate_1 = require("../validation/validate");
|
|
12
|
+
async function runReqLint() {
|
|
13
|
+
const projectName = await (0, prompt_1.ask)("Project name: ");
|
|
14
|
+
const reqId = await (0, prompt_1.ask)("Requirement ID (REQ-...): ");
|
|
15
|
+
if (!projectName || !reqId) {
|
|
16
|
+
console.log("Project name and requirement ID are required.");
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
const workspace = (0, index_1.getWorkspaceInfo)();
|
|
20
|
+
const base = path_1.default.join(workspace.root, projectName, "requirements");
|
|
21
|
+
const locations = ["backlog", "wip", "in-progress", "done", "archived"];
|
|
22
|
+
const dir = locations
|
|
23
|
+
.map((status) => path_1.default.join(base, status, reqId))
|
|
24
|
+
.find((candidate) => fs_1.default.existsSync(candidate));
|
|
25
|
+
if (!dir) {
|
|
26
|
+
console.log("Requirement not found.");
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
const schemaMap = {
|
|
30
|
+
"requirement.json": "requirement.schema.json",
|
|
31
|
+
"functional-spec.json": "functional-spec.schema.json",
|
|
32
|
+
"technical-spec.json": "technical-spec.schema.json",
|
|
33
|
+
"architecture.json": "architecture.schema.json",
|
|
34
|
+
"test-plan.json": "test-plan.schema.json",
|
|
35
|
+
"quality.json": "quality.schema.json",
|
|
36
|
+
"project-readme.json": "project-readme.schema.json"
|
|
37
|
+
};
|
|
38
|
+
let failures = 0;
|
|
39
|
+
for (const [file, schema] of Object.entries(schemaMap)) {
|
|
40
|
+
const filePath = path_1.default.join(dir, file);
|
|
41
|
+
if (!fs_1.default.existsSync(filePath)) {
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
const data = JSON.parse(fs_1.default.readFileSync(filePath, "utf-8"));
|
|
45
|
+
const result = (0, validate_1.validateJson)(schema, data);
|
|
46
|
+
if (!result.valid) {
|
|
47
|
+
failures += 1;
|
|
48
|
+
console.log(`Invalid: ${file}`);
|
|
49
|
+
result.errors.forEach((error) => console.log(`- ${error}`));
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
console.log(`Valid: ${file}`);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
if (failures === 0) {
|
|
56
|
+
console.log("All artifacts valid for this requirement.");
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function runReqList(statusFilter?: string): Promise<void>;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.runReqList = runReqList;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const prompt_1 = require("../ui/prompt");
|
|
10
|
+
const index_1 = require("../workspace/index");
|
|
11
|
+
const STATUSES = ["backlog", "wip", "in-progress", "done", "archived"];
|
|
12
|
+
async function runReqList(statusFilter) {
|
|
13
|
+
const projectName = await (0, prompt_1.ask)("Project name: ");
|
|
14
|
+
if (!projectName) {
|
|
15
|
+
console.log("Project name is required.");
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
const workspace = (0, index_1.getWorkspaceInfo)();
|
|
19
|
+
const base = path_1.default.join(workspace.root, projectName, "requirements");
|
|
20
|
+
if (!fs_1.default.existsSync(base)) {
|
|
21
|
+
console.log("No requirements found for this project.");
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
const statuses = statusFilter ? STATUSES.filter((status) => status === statusFilter) : STATUSES;
|
|
25
|
+
for (const status of statuses) {
|
|
26
|
+
const dir = path_1.default.join(base, status);
|
|
27
|
+
if (!fs_1.default.existsSync(dir)) {
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
const items = fs_1.default.readdirSync(dir).filter((entry) => fs_1.default.statSync(path_1.default.join(dir, entry)).isDirectory());
|
|
31
|
+
if (items.length > 0) {
|
|
32
|
+
console.log(`${status}:`);
|
|
33
|
+
items.forEach((item) => console.log(`- ${item}`));
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function runReqPlan(): Promise<void>;
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.runReqPlan = runReqPlan;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const prompt_1 = require("../ui/prompt");
|
|
10
|
+
const flags_1 = require("../context/flags");
|
|
11
|
+
const index_1 = require("../workspace/index");
|
|
12
|
+
const render_1 = require("../templates/render");
|
|
13
|
+
const list_1 = require("../utils/list");
|
|
14
|
+
const validate_1 = require("../validation/validate");
|
|
15
|
+
function findRequirementDir(workspaceRoot, project, reqId) {
|
|
16
|
+
const backlog = path_1.default.join(workspaceRoot, project, "requirements", "backlog", reqId);
|
|
17
|
+
const wip = path_1.default.join(workspaceRoot, project, "requirements", "wip", reqId);
|
|
18
|
+
if (fs_1.default.existsSync(backlog))
|
|
19
|
+
return backlog;
|
|
20
|
+
if (fs_1.default.existsSync(wip))
|
|
21
|
+
return wip;
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
async function runReqPlan() {
|
|
25
|
+
const projectName = await (0, prompt_1.ask)("Project name: ");
|
|
26
|
+
const reqId = await (0, prompt_1.ask)("Requirement ID (REQ-...): ");
|
|
27
|
+
if (!projectName || !reqId) {
|
|
28
|
+
console.log("Project name and requirement ID are required.");
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
const workspace = (0, index_1.getWorkspaceInfo)();
|
|
32
|
+
const requirementDir = findRequirementDir(workspace.root, projectName, reqId);
|
|
33
|
+
if (!requirementDir) {
|
|
34
|
+
console.log("Requirement not found in backlog or wip.");
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
const requirementJsonPath = path_1.default.join(requirementDir, "requirement.json");
|
|
38
|
+
if (!fs_1.default.existsSync(requirementJsonPath)) {
|
|
39
|
+
console.log("Missing requirement.json. Run `req create` first.");
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
const requirementJson = JSON.parse(fs_1.default.readFileSync(requirementJsonPath, "utf-8"));
|
|
43
|
+
const requirementValidation = (0, validate_1.validateJson)("requirement.schema.json", requirementJson);
|
|
44
|
+
if (!requirementValidation.valid) {
|
|
45
|
+
console.log("Requirement validation failed:");
|
|
46
|
+
requirementValidation.errors.forEach((error) => console.log(`- ${error}`));
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
const wipDir = path_1.default.join(workspace.root, projectName, "requirements", "wip", reqId);
|
|
50
|
+
if (requirementDir.includes(path_1.default.join("requirements", "backlog"))) {
|
|
51
|
+
fs_1.default.mkdirSync(path_1.default.dirname(wipDir), { recursive: true });
|
|
52
|
+
fs_1.default.renameSync(requirementDir, wipDir);
|
|
53
|
+
(0, index_1.updateProjectStatus)(workspace, projectName, "wip");
|
|
54
|
+
}
|
|
55
|
+
const targetDir = fs_1.default.existsSync(wipDir) ? wipDir : requirementDir;
|
|
56
|
+
const overview = await (0, prompt_1.ask)("Functional overview: ");
|
|
57
|
+
const actors = await (0, prompt_1.ask)("Actors - comma separated: ");
|
|
58
|
+
const useCases = await (0, prompt_1.ask)("Use cases - comma separated: ");
|
|
59
|
+
const flows = await (0, prompt_1.ask)("Flows - comma separated: ");
|
|
60
|
+
const rules = await (0, prompt_1.ask)("Business rules - comma separated: ");
|
|
61
|
+
const errors = await (0, prompt_1.ask)("Errors - comma separated: ");
|
|
62
|
+
const acceptance = await (0, prompt_1.ask)("Acceptance criteria - comma separated: ");
|
|
63
|
+
const stack = await (0, prompt_1.ask)("Tech stack - comma separated: ");
|
|
64
|
+
const interfaces = await (0, prompt_1.ask)("Interfaces - comma separated: ");
|
|
65
|
+
const dataModel = await (0, prompt_1.ask)("Data model - comma separated: ");
|
|
66
|
+
const security = await (0, prompt_1.ask)("Security - comma separated: ");
|
|
67
|
+
const techErrors = await (0, prompt_1.ask)("Error handling - comma separated: ");
|
|
68
|
+
const performance = await (0, prompt_1.ask)("Performance - comma separated: ");
|
|
69
|
+
const observability = await (0, prompt_1.ask)("Observability - comma separated: ");
|
|
70
|
+
const context = await (0, prompt_1.ask)("Architecture context: ");
|
|
71
|
+
const containers = await (0, prompt_1.ask)("Containers - comma separated: ");
|
|
72
|
+
const components = await (0, prompt_1.ask)("Components - comma separated: ");
|
|
73
|
+
const deployment = await (0, prompt_1.ask)("Deployment - comma separated: ");
|
|
74
|
+
const diagrams = await (0, prompt_1.ask)("Diagrams - comma separated: ");
|
|
75
|
+
const criticalPaths = await (0, prompt_1.ask)("Test critical paths - comma separated: ");
|
|
76
|
+
const edgeCases = await (0, prompt_1.ask)("Test edge cases - comma separated: ");
|
|
77
|
+
const acceptanceTests = await (0, prompt_1.ask)("Acceptance tests - comma separated: ");
|
|
78
|
+
const regressions = await (0, prompt_1.ask)("Regression tests - comma separated: ");
|
|
79
|
+
const coverageTarget = await (0, prompt_1.ask)("Coverage target: ");
|
|
80
|
+
const flags = (0, flags_1.getFlags)();
|
|
81
|
+
const improveNote = flags.improve ? await (0, prompt_1.ask)("Improve focus (optional): ") : "";
|
|
82
|
+
const functionalJson = {
|
|
83
|
+
overview: overview || "N/A",
|
|
84
|
+
actors: (0, list_1.parseList)(actors),
|
|
85
|
+
useCases: (0, list_1.parseList)(useCases),
|
|
86
|
+
flows: (0, list_1.parseList)(flows),
|
|
87
|
+
rules: (0, list_1.parseList)(rules),
|
|
88
|
+
errors: (0, list_1.parseList)(errors),
|
|
89
|
+
acceptanceCriteria: (0, list_1.parseList)(acceptance)
|
|
90
|
+
};
|
|
91
|
+
const technicalJson = {
|
|
92
|
+
stack: (0, list_1.parseList)(stack),
|
|
93
|
+
interfaces: (0, list_1.parseList)(interfaces),
|
|
94
|
+
dataModel: (0, list_1.parseList)(dataModel),
|
|
95
|
+
security: (0, list_1.parseList)(security),
|
|
96
|
+
errors: (0, list_1.parseList)(techErrors),
|
|
97
|
+
performance: (0, list_1.parseList)(performance),
|
|
98
|
+
observability: (0, list_1.parseList)(observability)
|
|
99
|
+
};
|
|
100
|
+
const architectureJson = {
|
|
101
|
+
context: context || "N/A",
|
|
102
|
+
containers: (0, list_1.parseList)(containers),
|
|
103
|
+
components: (0, list_1.parseList)(components),
|
|
104
|
+
deployment: (0, list_1.parseList)(deployment),
|
|
105
|
+
diagrams: (0, list_1.parseList)(diagrams)
|
|
106
|
+
};
|
|
107
|
+
const testPlanJson = {
|
|
108
|
+
criticalPaths: (0, list_1.parseList)(criticalPaths),
|
|
109
|
+
edgeCases: (0, list_1.parseList)(edgeCases),
|
|
110
|
+
coverageTarget: coverageTarget || "N/A",
|
|
111
|
+
acceptanceTests: (0, list_1.parseList)(acceptanceTests),
|
|
112
|
+
regressions: (0, list_1.parseList)(regressions)
|
|
113
|
+
};
|
|
114
|
+
const validations = [
|
|
115
|
+
(0, validate_1.validateJson)("functional-spec.schema.json", functionalJson),
|
|
116
|
+
(0, validate_1.validateJson)("technical-spec.schema.json", technicalJson),
|
|
117
|
+
(0, validate_1.validateJson)("architecture.schema.json", architectureJson),
|
|
118
|
+
(0, validate_1.validateJson)("test-plan.schema.json", testPlanJson)
|
|
119
|
+
];
|
|
120
|
+
const failures = validations.flatMap((result) => result.errors);
|
|
121
|
+
if (failures.length > 0) {
|
|
122
|
+
console.log("Spec validation failed:");
|
|
123
|
+
failures.forEach((error) => console.log(`- ${error}`));
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
console.log("Spec validation passed.");
|
|
127
|
+
const functionalTemplate = (0, render_1.loadTemplate)("functional-spec");
|
|
128
|
+
const technicalTemplate = (0, render_1.loadTemplate)("technical-spec");
|
|
129
|
+
const architectureTemplate = (0, render_1.loadTemplate)("architecture");
|
|
130
|
+
const testPlanTemplate = (0, render_1.loadTemplate)("test-plan");
|
|
131
|
+
const functionalRendered = (0, render_1.renderTemplate)(functionalTemplate, {
|
|
132
|
+
title: projectName,
|
|
133
|
+
overview: overview || "N/A",
|
|
134
|
+
actors: (0, list_1.formatList)(actors),
|
|
135
|
+
use_cases: (0, list_1.formatList)(useCases),
|
|
136
|
+
flows: (0, list_1.formatList)(flows),
|
|
137
|
+
rules: (0, list_1.formatList)(rules),
|
|
138
|
+
errors: (0, list_1.formatList)(errors),
|
|
139
|
+
acceptance_criteria: (0, list_1.formatList)(acceptance)
|
|
140
|
+
});
|
|
141
|
+
const technicalRendered = (0, render_1.renderTemplate)(technicalTemplate, {
|
|
142
|
+
title: projectName,
|
|
143
|
+
stack: (0, list_1.formatList)(stack),
|
|
144
|
+
interfaces: (0, list_1.formatList)(interfaces),
|
|
145
|
+
data_model: (0, list_1.formatList)(dataModel),
|
|
146
|
+
security: (0, list_1.formatList)(security),
|
|
147
|
+
errors: (0, list_1.formatList)(techErrors),
|
|
148
|
+
performance: (0, list_1.formatList)(performance),
|
|
149
|
+
observability: (0, list_1.formatList)(observability)
|
|
150
|
+
});
|
|
151
|
+
const architectureRendered = (0, render_1.renderTemplate)(architectureTemplate, {
|
|
152
|
+
title: projectName,
|
|
153
|
+
context: context || "N/A",
|
|
154
|
+
containers: (0, list_1.formatList)(containers),
|
|
155
|
+
components: (0, list_1.formatList)(components),
|
|
156
|
+
deployment: (0, list_1.formatList)(deployment),
|
|
157
|
+
diagrams: (0, list_1.formatList)(diagrams)
|
|
158
|
+
});
|
|
159
|
+
const testPlanRendered = (0, render_1.renderTemplate)(testPlanTemplate, {
|
|
160
|
+
title: projectName,
|
|
161
|
+
critical_paths: (0, list_1.formatList)(criticalPaths),
|
|
162
|
+
edge_cases: (0, list_1.formatList)(edgeCases),
|
|
163
|
+
acceptance_tests: (0, list_1.formatList)(acceptanceTests),
|
|
164
|
+
regressions: (0, list_1.formatList)(regressions),
|
|
165
|
+
coverage_target: coverageTarget || "N/A"
|
|
166
|
+
});
|
|
167
|
+
const writes = [
|
|
168
|
+
[path_1.default.join(targetDir, "functional-spec.md"), functionalRendered],
|
|
169
|
+
[path_1.default.join(targetDir, "functional-spec.json"), JSON.stringify(functionalJson, null, 2)],
|
|
170
|
+
[path_1.default.join(targetDir, "technical-spec.md"), technicalRendered],
|
|
171
|
+
[path_1.default.join(targetDir, "technical-spec.json"), JSON.stringify(technicalJson, null, 2)],
|
|
172
|
+
[path_1.default.join(targetDir, "architecture.md"), architectureRendered],
|
|
173
|
+
[path_1.default.join(targetDir, "architecture.json"), JSON.stringify(architectureJson, null, 2)],
|
|
174
|
+
[path_1.default.join(targetDir, "test-plan.md"), testPlanRendered],
|
|
175
|
+
[path_1.default.join(targetDir, "test-plan.json"), JSON.stringify(testPlanJson, null, 2)]
|
|
176
|
+
];
|
|
177
|
+
if (flags.parallel) {
|
|
178
|
+
await Promise.all(writes.map(([filePath, content]) => fs_1.default.promises.writeFile(filePath, content, "utf-8")));
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
writes.forEach(([filePath, content]) => fs_1.default.writeFileSync(filePath, content, "utf-8"));
|
|
182
|
+
}
|
|
183
|
+
const progressLog = path_1.default.join(targetDir, "progress-log.md");
|
|
184
|
+
if (!fs_1.default.existsSync(progressLog)) {
|
|
185
|
+
fs_1.default.writeFileSync(progressLog, "# Progress Log\n\n", "utf-8");
|
|
186
|
+
}
|
|
187
|
+
const logEntry = `\n- ${new Date().toISOString()} generated specs for ${reqId}\n`;
|
|
188
|
+
fs_1.default.appendFileSync(progressLog, logEntry, "utf-8");
|
|
189
|
+
if (flags.improve) {
|
|
190
|
+
const improveEntry = `\n- ${new Date().toISOString()} improve: ${improveNote || "refinement requested"}\n`;
|
|
191
|
+
fs_1.default.appendFileSync(progressLog, improveEntry, "utf-8");
|
|
192
|
+
}
|
|
193
|
+
const changelog = path_1.default.join(targetDir, "changelog.md");
|
|
194
|
+
if (!fs_1.default.existsSync(changelog)) {
|
|
195
|
+
fs_1.default.writeFileSync(changelog, "# Changelog\n\n", "utf-8");
|
|
196
|
+
}
|
|
197
|
+
const changeEntry = `\n- ${new Date().toISOString()} planned requirement ${reqId}\n`;
|
|
198
|
+
fs_1.default.appendFileSync(changelog, changeEntry, "utf-8");
|
|
199
|
+
console.log(`Generated specs in ${targetDir}`);
|
|
200
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function runReqRefine(): Promise<void>;
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.runReqRefine = runReqRefine;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const prompt_1 = require("../ui/prompt");
|
|
10
|
+
const flags_1 = require("../context/flags");
|
|
11
|
+
const index_1 = require("../workspace/index");
|
|
12
|
+
const render_1 = require("../templates/render");
|
|
13
|
+
const list_1 = require("../utils/list");
|
|
14
|
+
const validate_1 = require("../validation/validate");
|
|
15
|
+
function findRequirementFile(workspaceRoot, project, reqId) {
|
|
16
|
+
const base = path_1.default.join(workspaceRoot, project, "requirements");
|
|
17
|
+
const candidates = [
|
|
18
|
+
path_1.default.join(base, "backlog", reqId, "requirement.json"),
|
|
19
|
+
path_1.default.join(base, "wip", reqId, "requirement.json"),
|
|
20
|
+
path_1.default.join(base, "in-progress", reqId, "requirement.json"),
|
|
21
|
+
path_1.default.join(base, "done", reqId, "requirement.json")
|
|
22
|
+
];
|
|
23
|
+
return candidates.find((candidate) => fs_1.default.existsSync(candidate)) ?? null;
|
|
24
|
+
}
|
|
25
|
+
async function runReqRefine() {
|
|
26
|
+
const projectName = await (0, prompt_1.ask)("Project name: ");
|
|
27
|
+
const reqId = await (0, prompt_1.ask)("Requirement ID (REQ-...): ");
|
|
28
|
+
if (!projectName || !reqId) {
|
|
29
|
+
console.log("Project name and requirement ID are required.");
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
const workspace = (0, index_1.getWorkspaceInfo)();
|
|
33
|
+
const reqPath = findRequirementFile(workspace.root, projectName, reqId);
|
|
34
|
+
if (!reqPath) {
|
|
35
|
+
console.log("Requirement not found.");
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
const raw = JSON.parse(fs_1.default.readFileSync(reqPath, "utf-8"));
|
|
39
|
+
const objective = await (0, prompt_1.ask)(`Objective (${raw.objective}): `);
|
|
40
|
+
const actors = await (0, prompt_1.ask)("Actors - comma separated: ");
|
|
41
|
+
const scopeIn = await (0, prompt_1.ask)("Scope (in) - comma separated: ");
|
|
42
|
+
const scopeOut = await (0, prompt_1.ask)("Scope (out) - comma separated: ");
|
|
43
|
+
const acceptance = await (0, prompt_1.ask)("Acceptance criteria - comma separated: ");
|
|
44
|
+
const nfrSecurity = await (0, prompt_1.ask)("NFR security: ");
|
|
45
|
+
const nfrPerformance = await (0, prompt_1.ask)("NFR performance: ");
|
|
46
|
+
const nfrAvailability = await (0, prompt_1.ask)("NFR availability: ");
|
|
47
|
+
const constraints = await (0, prompt_1.ask)("Constraints - comma separated: ");
|
|
48
|
+
const risks = await (0, prompt_1.ask)("Risks - comma separated: ");
|
|
49
|
+
const links = await (0, prompt_1.ask)("Links - comma separated: ");
|
|
50
|
+
const flags = (0, flags_1.getFlags)();
|
|
51
|
+
const improveNote = flags.improve ? await (0, prompt_1.ask)("Improve focus (optional): ") : "";
|
|
52
|
+
const updated = {
|
|
53
|
+
...raw,
|
|
54
|
+
objective: objective || raw.objective,
|
|
55
|
+
actors: actors ? (0, list_1.parseList)(actors) : raw.actors,
|
|
56
|
+
scope: {
|
|
57
|
+
in: scopeIn ? (0, list_1.parseList)(scopeIn) : raw.scope.in,
|
|
58
|
+
out: scopeOut ? (0, list_1.parseList)(scopeOut) : raw.scope.out
|
|
59
|
+
},
|
|
60
|
+
acceptanceCriteria: acceptance ? (0, list_1.parseList)(acceptance) : raw.acceptanceCriteria,
|
|
61
|
+
nfrs: {
|
|
62
|
+
security: nfrSecurity || raw.nfrs.security,
|
|
63
|
+
performance: nfrPerformance || raw.nfrs.performance,
|
|
64
|
+
availability: nfrAvailability || raw.nfrs.availability
|
|
65
|
+
},
|
|
66
|
+
constraints: constraints ? (0, list_1.parseList)(constraints) : raw.constraints,
|
|
67
|
+
risks: risks ? (0, list_1.parseList)(risks) : raw.risks,
|
|
68
|
+
links: links ? (0, list_1.parseList)(links) : raw.links,
|
|
69
|
+
updatedAt: new Date().toISOString()
|
|
70
|
+
};
|
|
71
|
+
const validation = (0, validate_1.validateJson)("requirement.schema.json", updated);
|
|
72
|
+
if (!validation.valid) {
|
|
73
|
+
console.log("Requirement validation failed:");
|
|
74
|
+
validation.errors.forEach((error) => console.log(`- ${error}`));
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
fs_1.default.writeFileSync(reqPath, JSON.stringify(updated, null, 2), "utf-8");
|
|
78
|
+
const template = (0, render_1.loadTemplate)("requirement");
|
|
79
|
+
const rendered = (0, render_1.renderTemplate)(template, {
|
|
80
|
+
title: updated.title,
|
|
81
|
+
id: updated.id,
|
|
82
|
+
objective: updated.objective,
|
|
83
|
+
actors: (0, list_1.formatList)((updated.actors ?? []).join(", ")),
|
|
84
|
+
scope_in: (0, list_1.formatList)(updated.scope.in.join(", ")),
|
|
85
|
+
scope_out: (0, list_1.formatList)(updated.scope.out.join(", ")),
|
|
86
|
+
acceptance_criteria: (0, list_1.formatList)(updated.acceptanceCriteria.join(", ")),
|
|
87
|
+
nfr_security: updated.nfrs.security,
|
|
88
|
+
nfr_performance: updated.nfrs.performance,
|
|
89
|
+
nfr_availability: updated.nfrs.availability,
|
|
90
|
+
constraints: (0, list_1.formatList)((updated.constraints ?? []).join(", ")),
|
|
91
|
+
risks: (0, list_1.formatList)((updated.risks ?? []).join(", ")),
|
|
92
|
+
links: (0, list_1.formatList)((updated.links ?? []).join(", "))
|
|
93
|
+
});
|
|
94
|
+
const mdPath = reqPath.replace("requirement.json", "requirement.md");
|
|
95
|
+
fs_1.default.writeFileSync(mdPath, rendered, "utf-8");
|
|
96
|
+
const changelogPath = path_1.default.join(path_1.default.dirname(reqPath), "changelog.md");
|
|
97
|
+
const logEntry = `\n- ${new Date().toISOString()} refined requirement ${updated.id}\n`;
|
|
98
|
+
fs_1.default.appendFileSync(changelogPath, logEntry, "utf-8");
|
|
99
|
+
if (flags.improve) {
|
|
100
|
+
const progressLog = path_1.default.join(path_1.default.dirname(reqPath), "progress-log.md");
|
|
101
|
+
if (!fs_1.default.existsSync(progressLog)) {
|
|
102
|
+
fs_1.default.writeFileSync(progressLog, "# Progress Log\n\n", "utf-8");
|
|
103
|
+
}
|
|
104
|
+
const improveEntry = `\n- ${new Date().toISOString()} improve: ${improveNote || "refinement requested"}\n`;
|
|
105
|
+
fs_1.default.appendFileSync(progressLog, improveEntry, "utf-8");
|
|
106
|
+
}
|
|
107
|
+
console.log(`Requirement updated at ${mdPath}`);
|
|
108
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function runReqReport(): Promise<void>;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.runReqReport = runReqReport;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const prompt_1 = require("../ui/prompt");
|
|
10
|
+
const index_1 = require("../workspace/index");
|
|
11
|
+
const REQUIRED_FILES = [
|
|
12
|
+
"requirement.json",
|
|
13
|
+
"functional-spec.json",
|
|
14
|
+
"technical-spec.json",
|
|
15
|
+
"architecture.json",
|
|
16
|
+
"test-plan.json",
|
|
17
|
+
"quality.json",
|
|
18
|
+
"project-readme.json"
|
|
19
|
+
];
|
|
20
|
+
async function runReqReport() {
|
|
21
|
+
const projectName = await (0, prompt_1.ask)("Project name: ");
|
|
22
|
+
const reqId = await (0, prompt_1.ask)("Requirement ID (REQ-...): ");
|
|
23
|
+
if (!projectName || !reqId) {
|
|
24
|
+
console.log("Project name and requirement ID are required.");
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
const workspace = (0, index_1.getWorkspaceInfo)();
|
|
28
|
+
const base = path_1.default.join(workspace.root, projectName, "requirements");
|
|
29
|
+
const statuses = ["backlog", "wip", "in-progress", "done", "archived"];
|
|
30
|
+
const dir = statuses.map((status) => path_1.default.join(base, status, reqId)).find((candidate) => fs_1.default.existsSync(candidate));
|
|
31
|
+
if (!dir) {
|
|
32
|
+
console.log("Requirement not found.");
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
console.log(`Requirement report: ${reqId}`);
|
|
36
|
+
let missing = 0;
|
|
37
|
+
for (const file of REQUIRED_FILES) {
|
|
38
|
+
const exists = fs_1.default.existsSync(path_1.default.join(dir, file));
|
|
39
|
+
console.log(`${exists ? "OK" : "MISSING"}: ${file}`);
|
|
40
|
+
if (!exists)
|
|
41
|
+
missing += 1;
|
|
42
|
+
}
|
|
43
|
+
console.log(`Missing files: ${missing}`);
|
|
44
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function runReqStart(): Promise<void>;
|