sdd-cli 0.1.2 → 0.1.3

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.
Files changed (66) hide show
  1. package/README.md +126 -89
  2. package/dist/cli.js +7 -3
  3. package/dist/commands/doctor.js +11 -2
  4. package/dist/commands/gen-architecture.js +14 -4
  5. package/dist/commands/gen-best-practices.js +12 -2
  6. package/dist/commands/gen-functional-spec.js +13 -3
  7. package/dist/commands/gen-project-readme.js +15 -5
  8. package/dist/commands/gen-technical-spec.js +13 -3
  9. package/dist/commands/gen-utils.js +9 -1
  10. package/dist/commands/hello.js +21 -3
  11. package/dist/commands/learn-deliver.js +17 -3
  12. package/dist/commands/learn-refine.js +32 -11
  13. package/dist/commands/learn-start.js +9 -2
  14. package/dist/commands/learn-utils.js +7 -4
  15. package/dist/commands/pr-audit.js +17 -3
  16. package/dist/commands/pr-finish.js +17 -3
  17. package/dist/commands/pr-report.js +17 -3
  18. package/dist/commands/pr-respond.js +17 -3
  19. package/dist/commands/pr-start.js +9 -2
  20. package/dist/commands/pr-utils.js +8 -5
  21. package/dist/commands/req-archive.js +14 -6
  22. package/dist/commands/req-create.js +71 -14
  23. package/dist/commands/req-export.js +11 -3
  24. package/dist/commands/req-finish.js +28 -13
  25. package/dist/commands/req-lint.js +10 -2
  26. package/dist/commands/req-list.js +10 -2
  27. package/dist/commands/req-plan.js +34 -12
  28. package/dist/commands/req-refine.js +54 -5
  29. package/dist/commands/req-report.js +10 -2
  30. package/dist/commands/req-start.js +29 -12
  31. package/dist/commands/req-status.js +10 -2
  32. package/dist/commands/test-plan.js +13 -5
  33. package/dist/context/flags.d.ts +2 -0
  34. package/dist/context/flags.js +5 -1
  35. package/dist/providers/codex.js +2 -2
  36. package/dist/router/prompt-map.js +17 -5
  37. package/dist/ui/prompt.d.ts +1 -0
  38. package/dist/ui/prompt.js +8 -0
  39. package/dist/validation/gates.d.ts +19 -0
  40. package/dist/validation/gates.js +41 -0
  41. package/dist/validation/validate.js +24 -4
  42. package/dist/workspace/index.d.ts +6 -0
  43. package/dist/workspace/index.js +41 -10
  44. package/flows/ADMISSIONS_ADMIN.md +34 -33
  45. package/flows/ART.md +34 -33
  46. package/flows/COURT_SYSTEM.md +34 -33
  47. package/flows/DATA_SCIENTIST.md +34 -33
  48. package/flows/ECOMMERCE.md +34 -33
  49. package/flows/ECONOMICS.md +34 -33
  50. package/flows/GRAPHIC_DESIGN.md +34 -33
  51. package/flows/HISTORY.md +34 -33
  52. package/flows/LAWYER.md +35 -34
  53. package/flows/PROGRAMMER.md +34 -33
  54. package/flows/RETAIL_STORE.md +34 -33
  55. package/flows/SOCIOLOGY.md +34 -33
  56. package/flows/STATE_ADMIN.md +34 -33
  57. package/flows/STUDENT_UNIVERSITY.md +34 -33
  58. package/flows/TAXES_ADMIN.md +34 -33
  59. package/flows/TEACHER.md +34 -33
  60. package/package.json +13 -3
  61. package/router/BUSINESS.flow.md +58 -57
  62. package/router/DATA_SCIENCE.flow.md +59 -58
  63. package/router/DESIGN.flow.md +59 -58
  64. package/router/HUMANITIES.flow.md +59 -58
  65. package/router/LEGAL.flow.md +59 -58
  66. package/router/SOFTWARE_FEATURE.flow.md +60 -59
@@ -10,12 +10,19 @@ const prompt_1 = require("../ui/prompt");
10
10
  const list_1 = require("../utils/list");
11
11
  const learn_utils_1 = require("./learn-utils");
12
12
  async function runLearnDeliver() {
13
- const projectName = await (0, prompt_1.ask)("Project name: ");
13
+ const projectName = await (0, prompt_1.askProjectName)();
14
14
  if (!projectName) {
15
15
  console.log("Project name is required.");
16
16
  return;
17
17
  }
18
- const sessions = (0, learn_utils_1.listLearnSessions)(projectName);
18
+ let sessions = [];
19
+ try {
20
+ sessions = (0, learn_utils_1.listLearnSessions)(projectName);
21
+ }
22
+ catch (error) {
23
+ console.log(error.message);
24
+ return;
25
+ }
19
26
  if (sessions.length > 0) {
20
27
  console.log("Available sessions:");
21
28
  sessions.forEach((session) => console.log(`- ${session}`));
@@ -25,7 +32,14 @@ async function runLearnDeliver() {
25
32
  console.log("Session ID is required.");
26
33
  return;
27
34
  }
28
- const loaded = (0, learn_utils_1.loadLearnSession)(projectName, sessionId);
35
+ let loaded;
36
+ try {
37
+ loaded = (0, learn_utils_1.loadLearnSession)(projectName, sessionId);
38
+ }
39
+ catch (error) {
40
+ console.log(error.message);
41
+ return;
42
+ }
29
43
  if (!loaded) {
30
44
  console.log("Learning session not found.");
31
45
  return;
@@ -10,12 +10,19 @@ const prompt_1 = require("../ui/prompt");
10
10
  const list_1 = require("../utils/list");
11
11
  const learn_utils_1 = require("./learn-utils");
12
12
  async function runLearnRefine() {
13
- const projectName = await (0, prompt_1.ask)("Project name: ");
13
+ const projectName = await (0, prompt_1.askProjectName)();
14
14
  if (!projectName) {
15
15
  console.log("Project name is required.");
16
16
  return;
17
17
  }
18
- const sessions = (0, learn_utils_1.listLearnSessions)(projectName);
18
+ let sessions = [];
19
+ try {
20
+ sessions = (0, learn_utils_1.listLearnSessions)(projectName);
21
+ }
22
+ catch (error) {
23
+ console.log(error.message);
24
+ return;
25
+ }
19
26
  if (sessions.length > 0) {
20
27
  console.log("Available sessions:");
21
28
  sessions.forEach((session) => console.log(`- ${session}`));
@@ -25,7 +32,14 @@ async function runLearnRefine() {
25
32
  console.log("Session ID is required.");
26
33
  return;
27
34
  }
28
- const loaded = (0, learn_utils_1.loadLearnSession)(projectName, sessionId);
35
+ let loaded;
36
+ try {
37
+ loaded = (0, learn_utils_1.loadLearnSession)(projectName, sessionId);
38
+ }
39
+ catch (error) {
40
+ console.log(error.message);
41
+ return;
42
+ }
29
43
  if (!loaded) {
30
44
  console.log("Learning session not found.");
31
45
  return;
@@ -36,14 +50,21 @@ async function runLearnRefine() {
36
50
  const focusAreas = await (0, prompt_1.ask)("Focus areas - comma separated: ");
37
51
  const timeAvailable = await (0, prompt_1.ask)(`Time available (${loaded.session.timeAvailable}): `);
38
52
  const constraints = await (0, prompt_1.ask)("Constraints - comma separated: ");
39
- const updated = (0, learn_utils_1.updateLearnSession)(projectName, sessionId, {
40
- purpose: purpose || loaded.session.purpose,
41
- depth: depth || loaded.session.depth,
42
- format: format || loaded.session.format,
43
- focusAreas: focusAreas ? (0, list_1.parseList)(focusAreas) : loaded.session.focusAreas,
44
- timeAvailable: timeAvailable || loaded.session.timeAvailable,
45
- constraints: constraints ? (0, list_1.parseList)(constraints) : loaded.session.constraints
46
- });
53
+ let updated;
54
+ try {
55
+ updated = (0, learn_utils_1.updateLearnSession)(projectName, sessionId, {
56
+ purpose: purpose || loaded.session.purpose,
57
+ depth: depth || loaded.session.depth,
58
+ format: format || loaded.session.format,
59
+ focusAreas: focusAreas ? (0, list_1.parseList)(focusAreas) : loaded.session.focusAreas,
60
+ timeAvailable: timeAvailable || loaded.session.timeAvailable,
61
+ constraints: constraints ? (0, list_1.parseList)(constraints) : loaded.session.constraints
62
+ });
63
+ }
64
+ catch (error) {
65
+ console.log(error.message);
66
+ return;
67
+ }
47
68
  if (!updated) {
48
69
  console.log("Failed to update session.");
49
70
  return;
@@ -10,7 +10,7 @@ const prompt_1 = require("../ui/prompt");
10
10
  const list_1 = require("../utils/list");
11
11
  const learn_utils_1 = require("./learn-utils");
12
12
  async function runLearnStart() {
13
- const projectName = await (0, prompt_1.ask)("Project name: ");
13
+ const projectName = await (0, prompt_1.askProjectName)();
14
14
  const topic = await (0, prompt_1.ask)("Topic to learn: ");
15
15
  if (!projectName || !topic) {
16
16
  console.log("Project name and topic are required.");
@@ -22,7 +22,14 @@ async function runLearnStart() {
22
22
  const focusAreas = await (0, prompt_1.ask)("Focus areas - comma separated: ");
23
23
  const timeAvailable = await (0, prompt_1.ask)("Time available: ");
24
24
  const constraints = await (0, prompt_1.ask)("Constraints - comma separated: ");
25
- const created = (0, learn_utils_1.createLearnSession)(projectName, topic, "learning");
25
+ let created;
26
+ try {
27
+ created = (0, learn_utils_1.createLearnSession)(projectName, topic, "learning");
28
+ }
29
+ catch (error) {
30
+ console.log(error.message);
31
+ return;
32
+ }
26
33
  (0, learn_utils_1.updateLearnSession)(projectName, created.session.id, {
27
34
  purpose: purpose || "N/A",
28
35
  depth: depth || "N/A",
@@ -20,7 +20,8 @@ function sanitizeId(value) {
20
20
  }
21
21
  function createLearnSession(projectName, topic, domain = "learning") {
22
22
  const workspace = (0, index_1.getWorkspaceInfo)();
23
- (0, index_1.ensureProject)(workspace, projectName, domain);
23
+ const project = (0, index_1.getProjectInfo)(workspace, projectName);
24
+ (0, index_1.ensureProject)(workspace, project.name, domain);
24
25
  const stamp = new Date().toISOString().replace(/[:.]/g, "").slice(0, 13);
25
26
  const id = `LEARN-${sanitizeId(topic)}-${stamp}`;
26
27
  const now = new Date().toISOString();
@@ -36,14 +37,15 @@ function createLearnSession(projectName, topic, domain = "learning") {
36
37
  createdAt: now,
37
38
  updatedAt: now
38
39
  };
39
- const sessionDir = path_1.default.join(workspace.root, projectName, "learning", id);
40
+ const sessionDir = path_1.default.join(project.root, "learning", id);
40
41
  fs_1.default.mkdirSync(sessionDir, { recursive: true });
41
42
  fs_1.default.writeFileSync(path_1.default.join(sessionDir, "session.json"), JSON.stringify(session, null, 2), "utf-8");
42
43
  return { session, dir: sessionDir };
43
44
  }
44
45
  function loadLearnSession(projectName, sessionId) {
45
46
  const workspace = (0, index_1.getWorkspaceInfo)();
46
- const sessionDir = path_1.default.join(workspace.root, projectName, "learning", sessionId);
47
+ const project = (0, index_1.getProjectInfo)(workspace, projectName);
48
+ const sessionDir = path_1.default.join(project.root, "learning", sessionId);
47
49
  const sessionPath = path_1.default.join(sessionDir, "session.json");
48
50
  if (!fs_1.default.existsSync(sessionPath)) {
49
51
  return null;
@@ -53,7 +55,8 @@ function loadLearnSession(projectName, sessionId) {
53
55
  }
54
56
  function listLearnSessions(projectName) {
55
57
  const workspace = (0, index_1.getWorkspaceInfo)();
56
- const root = path_1.default.join(workspace.root, projectName, "learning");
58
+ const project = (0, index_1.getProjectInfo)(workspace, projectName);
59
+ const root = path_1.default.join(project.root, "learning");
57
60
  if (!fs_1.default.existsSync(root)) {
58
61
  return [];
59
62
  }
@@ -11,12 +11,19 @@ const render_1 = require("../templates/render");
11
11
  const list_1 = require("../utils/list");
12
12
  const pr_utils_1 = require("./pr-utils");
13
13
  async function runPrAudit() {
14
- const projectName = await (0, prompt_1.ask)("Project name: ");
14
+ const projectName = await (0, prompt_1.askProjectName)();
15
15
  if (!projectName) {
16
16
  console.log("Project name is required.");
17
17
  return;
18
18
  }
19
- const available = (0, pr_utils_1.listPrReviews)(projectName);
19
+ let available = [];
20
+ try {
21
+ available = (0, pr_utils_1.listPrReviews)(projectName);
22
+ }
23
+ catch (error) {
24
+ console.log(error.message);
25
+ return;
26
+ }
20
27
  if (available.length > 0) {
21
28
  console.log("Available PR reviews:");
22
29
  available.forEach((item) => console.log(`- ${item}`));
@@ -26,7 +33,14 @@ async function runPrAudit() {
26
33
  console.log("PR ID is required.");
27
34
  return;
28
35
  }
29
- const prDir = (0, pr_utils_1.resolvePrDir)(projectName, prId);
36
+ let prDir;
37
+ try {
38
+ prDir = (0, pr_utils_1.resolvePrDir)(projectName, prId);
39
+ }
40
+ catch (error) {
41
+ console.log(error.message);
42
+ return;
43
+ }
30
44
  if (!fs_1.default.existsSync(prDir)) {
31
45
  console.log(`PR review not found at ${prDir}`);
32
46
  return;
@@ -11,12 +11,19 @@ const render_1 = require("../templates/render");
11
11
  const list_1 = require("../utils/list");
12
12
  const pr_utils_1 = require("./pr-utils");
13
13
  async function runPrFinish() {
14
- const projectName = await (0, prompt_1.ask)("Project name: ");
14
+ const projectName = await (0, prompt_1.askProjectName)();
15
15
  if (!projectName) {
16
16
  console.log("Project name is required.");
17
17
  return;
18
18
  }
19
- const available = (0, pr_utils_1.listPrReviews)(projectName);
19
+ let available = [];
20
+ try {
21
+ available = (0, pr_utils_1.listPrReviews)(projectName);
22
+ }
23
+ catch (error) {
24
+ console.log(error.message);
25
+ return;
26
+ }
20
27
  if (available.length > 0) {
21
28
  console.log("Available PR reviews:");
22
29
  available.forEach((item) => console.log(`- ${item}`));
@@ -26,7 +33,14 @@ async function runPrFinish() {
26
33
  console.log("PR ID is required.");
27
34
  return;
28
35
  }
29
- const prDir = (0, pr_utils_1.resolvePrDir)(projectName, prId);
36
+ let prDir;
37
+ try {
38
+ prDir = (0, pr_utils_1.resolvePrDir)(projectName, prId);
39
+ }
40
+ catch (error) {
41
+ console.log(error.message);
42
+ return;
43
+ }
30
44
  if (!fs_1.default.existsSync(prDir)) {
31
45
  console.log(`PR review not found at ${prDir}`);
32
46
  return;
@@ -11,12 +11,19 @@ const render_1 = require("../templates/render");
11
11
  const list_1 = require("../utils/list");
12
12
  const pr_utils_1 = require("./pr-utils");
13
13
  async function runPrReport() {
14
- const projectName = await (0, prompt_1.ask)("Project name: ");
14
+ const projectName = await (0, prompt_1.askProjectName)();
15
15
  if (!projectName) {
16
16
  console.log("Project name is required.");
17
17
  return;
18
18
  }
19
- const available = (0, pr_utils_1.listPrReviews)(projectName);
19
+ let available = [];
20
+ try {
21
+ available = (0, pr_utils_1.listPrReviews)(projectName);
22
+ }
23
+ catch (error) {
24
+ console.log(error.message);
25
+ return;
26
+ }
20
27
  if (available.length > 0) {
21
28
  console.log("Available PR reviews:");
22
29
  available.forEach((item) => console.log(`- ${item}`));
@@ -26,7 +33,14 @@ async function runPrReport() {
26
33
  console.log("PR ID is required.");
27
34
  return;
28
35
  }
29
- const prDir = (0, pr_utils_1.resolvePrDir)(projectName, prId);
36
+ let prDir;
37
+ try {
38
+ prDir = (0, pr_utils_1.resolvePrDir)(projectName, prId);
39
+ }
40
+ catch (error) {
41
+ console.log(error.message);
42
+ return;
43
+ }
30
44
  if (!fs_1.default.existsSync(prDir)) {
31
45
  console.log(`PR review not found at ${prDir}`);
32
46
  return;
@@ -18,12 +18,19 @@ function sanitizeId(value) {
18
18
  .replace(/^-|-$/g, "");
19
19
  }
20
20
  async function runPrRespond() {
21
- const projectName = await (0, prompt_1.ask)("Project name: ");
21
+ const projectName = await (0, prompt_1.askProjectName)();
22
22
  if (!projectName) {
23
23
  console.log("Project name is required.");
24
24
  return;
25
25
  }
26
- const available = (0, pr_utils_1.listPrReviews)(projectName);
26
+ let available = [];
27
+ try {
28
+ available = (0, pr_utils_1.listPrReviews)(projectName);
29
+ }
30
+ catch (error) {
31
+ console.log(error.message);
32
+ return;
33
+ }
27
34
  if (available.length > 0) {
28
35
  console.log("Available PR reviews:");
29
36
  available.forEach((item) => console.log(`- ${item}`));
@@ -33,7 +40,14 @@ async function runPrRespond() {
33
40
  console.log("PR ID is required.");
34
41
  return;
35
42
  }
36
- const prDir = (0, pr_utils_1.resolvePrDir)(projectName, prId);
43
+ let prDir;
44
+ try {
45
+ prDir = (0, pr_utils_1.resolvePrDir)(projectName, prId);
46
+ }
47
+ catch (error) {
48
+ console.log(error.message);
49
+ return;
50
+ }
37
51
  if (!fs_1.default.existsSync(prDir)) {
38
52
  console.log(`PR review not found at ${prDir}`);
39
53
  return;
@@ -11,7 +11,7 @@ const render_1 = require("../templates/render");
11
11
  const list_1 = require("../utils/list");
12
12
  const pr_utils_1 = require("./pr-utils");
13
13
  async function runPrStart() {
14
- const projectName = await (0, prompt_1.ask)("Project name: ");
14
+ const projectName = await (0, prompt_1.askProjectName)();
15
15
  if (!projectName) {
16
16
  console.log("Project name is required.");
17
17
  return;
@@ -35,7 +35,14 @@ async function runPrStart() {
35
35
  const avgTime = await (0, prompt_1.ask)("Avg time to resolve: ");
36
36
  const testsRun = await (0, prompt_1.ask)("Tests run: ");
37
37
  const notes = await (0, prompt_1.ask)("Notes - comma separated: ");
38
- const context = (0, pr_utils_1.ensurePrReviewDir)(projectName, prLink, prIdInput);
38
+ let context;
39
+ try {
40
+ context = (0, pr_utils_1.ensurePrReviewDir)(projectName, prLink, prIdInput);
41
+ }
42
+ catch (error) {
43
+ console.log(error.message);
44
+ return;
45
+ }
39
46
  const reviewMeta = {
40
47
  id: context.prId,
41
48
  link: prLink,
@@ -26,23 +26,26 @@ function sanitizeId(value) {
26
26
  }
27
27
  function ensurePrReviewDir(projectName, prLink, prIdInput) {
28
28
  const workspace = (0, index_1.getWorkspaceInfo)();
29
- (0, index_1.ensureProject)(workspace, projectName, "software");
29
+ const project = (0, index_1.getProjectInfo)(workspace, projectName);
30
+ (0, index_1.ensureProject)(workspace, project.name, "software");
30
31
  const derived = extractPrId(prLink);
31
32
  const rawId = prIdInput?.trim() || derived || `PR-${Date.now()}`;
32
33
  const prId = sanitizeId(rawId);
33
- const prDir = path_1.default.join(workspace.root, projectName, "pr-reviews", prId);
34
+ const prDir = path_1.default.join(project.root, "pr-reviews", prId);
34
35
  if (!fs_1.default.existsSync(prDir)) {
35
36
  fs_1.default.mkdirSync(prDir, { recursive: true });
36
37
  }
37
- return { projectName, prId, prDir };
38
+ return { projectName: project.name, prId, prDir };
38
39
  }
39
40
  function resolvePrDir(projectName, prId) {
40
41
  const workspace = (0, index_1.getWorkspaceInfo)();
41
- return path_1.default.join(workspace.root, projectName, "pr-reviews", prId);
42
+ const project = (0, index_1.getProjectInfo)(workspace, projectName);
43
+ return path_1.default.join(project.root, "pr-reviews", prId);
42
44
  }
43
45
  function listPrReviews(projectName) {
44
46
  const workspace = (0, index_1.getWorkspaceInfo)();
45
- const root = path_1.default.join(workspace.root, projectName, "pr-reviews");
47
+ const project = (0, index_1.getProjectInfo)(workspace, projectName);
48
+ const root = path_1.default.join(project.root, "pr-reviews");
46
49
  if (!fs_1.default.existsSync(root)) {
47
50
  return [];
48
51
  }
@@ -8,26 +8,34 @@ const fs_1 = __importDefault(require("fs"));
8
8
  const path_1 = __importDefault(require("path"));
9
9
  const prompt_1 = require("../ui/prompt");
10
10
  const index_1 = require("../workspace/index");
11
- function findDoneRequirement(workspaceRoot, project, reqId) {
12
- const done = path_1.default.join(workspaceRoot, project, "requirements", "done", reqId);
11
+ function findDoneRequirement(projectRoot, reqId) {
12
+ const done = path_1.default.join(projectRoot, "requirements", "done", reqId);
13
13
  return fs_1.default.existsSync(done) ? done : null;
14
14
  }
15
15
  async function runReqArchive() {
16
- const projectName = await (0, prompt_1.ask)("Project name: ");
16
+ const projectName = await (0, prompt_1.askProjectName)();
17
17
  const reqId = await (0, prompt_1.ask)("Requirement ID (REQ-...): ");
18
18
  if (!projectName || !reqId) {
19
19
  console.log("Project name and requirement ID are required.");
20
20
  return;
21
21
  }
22
22
  const workspace = (0, index_1.getWorkspaceInfo)();
23
- const doneDir = findDoneRequirement(workspace.root, projectName, reqId);
23
+ let project;
24
+ try {
25
+ project = (0, index_1.getProjectInfo)(workspace, projectName);
26
+ }
27
+ catch (error) {
28
+ console.log(error.message);
29
+ return;
30
+ }
31
+ const doneDir = findDoneRequirement(project.root, reqId);
24
32
  if (!doneDir) {
25
33
  console.log("Requirement not found in done.");
26
34
  return;
27
35
  }
28
- const archiveDir = path_1.default.join(workspace.root, projectName, "requirements", "archived", reqId);
36
+ const archiveDir = path_1.default.join(project.root, "requirements", "archived", reqId);
29
37
  fs_1.default.mkdirSync(path_1.default.dirname(archiveDir), { recursive: true });
30
38
  fs_1.default.renameSync(doneDir, archiveDir);
31
- (0, index_1.updateProjectStatus)(workspace, projectName, "archived");
39
+ (0, index_1.updateProjectStatus)(workspace, project.name, "archived");
32
40
  console.log(`Archived requirement in ${archiveDir}`);
33
41
  }
@@ -10,6 +10,7 @@ const prompt_1 = require("../ui/prompt");
10
10
  const index_1 = require("../workspace/index");
11
11
  const render_1 = require("../templates/render");
12
12
  const list_1 = require("../utils/list");
13
+ const gates_1 = require("../validation/gates");
13
14
  const validate_1 = require("../validation/validate");
14
15
  function generateId() {
15
16
  const now = new Date();
@@ -17,26 +18,34 @@ function generateId() {
17
18
  return `REQ-${stamp}`;
18
19
  }
19
20
  async function runReqCreate(draft) {
20
- const projectName = await (0, prompt_1.ask)("Project name: ");
21
+ const projectName = await (0, prompt_1.askProjectName)();
21
22
  const domain = await (0, prompt_1.ask)("Domain (software, legal, design, learning, etc): ");
22
23
  const actors = await (0, prompt_1.ask)("Actors - comma separated: ");
23
- const objective = draft?.objective ?? (await (0, prompt_1.ask)("Objective: "));
24
- const scopeIn = draft?.scope_in ?? (await (0, prompt_1.ask)("Scope (in) - comma separated: "));
25
- const scopeOut = draft?.scope_out ?? (await (0, prompt_1.ask)("Scope (out) - comma separated: "));
26
- const acceptance = draft?.acceptance_criteria ?? (await (0, prompt_1.ask)("Acceptance criteria - comma separated: "));
27
- const nfrSecurity = draft?.nfr_security ?? (await (0, prompt_1.ask)("NFR security: "));
28
- const nfrPerformance = draft?.nfr_performance ?? (await (0, prompt_1.ask)("NFR performance: "));
29
- const nfrAvailability = draft?.nfr_availability ?? (await (0, prompt_1.ask)("NFR availability: "));
24
+ let objective = draft?.objective ?? (await (0, prompt_1.ask)("Objective: "));
25
+ let scopeIn = draft?.scope_in ?? (await (0, prompt_1.ask)("Scope (in) - comma separated: "));
26
+ let scopeOut = draft?.scope_out ?? (await (0, prompt_1.ask)("Scope (out) - comma separated: "));
27
+ let acceptance = draft?.acceptance_criteria ?? (await (0, prompt_1.ask)("Acceptance criteria - comma separated: "));
28
+ let nfrSecurity = draft?.nfr_security ?? (await (0, prompt_1.ask)("NFR security: "));
29
+ let nfrPerformance = draft?.nfr_performance ?? (await (0, prompt_1.ask)("NFR performance: "));
30
+ let nfrAvailability = draft?.nfr_availability ?? (await (0, prompt_1.ask)("NFR availability: "));
30
31
  const constraints = await (0, prompt_1.ask)("Constraints - comma separated: ");
31
32
  const risks = await (0, prompt_1.ask)("Risks - comma separated: ");
32
33
  const links = await (0, prompt_1.ask)("Links - comma separated: ");
33
34
  const workspace = (0, index_1.getWorkspaceInfo)();
34
- const metadata = (0, index_1.createProject)(workspace, projectName, domain || "software");
35
+ let project;
36
+ try {
37
+ project = (0, index_1.getProjectInfo)(workspace, projectName);
38
+ }
39
+ catch (error) {
40
+ console.log(error.message);
41
+ return;
42
+ }
43
+ const metadata = (0, index_1.createProject)(workspace, project.name, domain || "software");
35
44
  const reqId = generateId();
36
45
  const status = "backlog";
37
- const requirementJson = {
46
+ let requirementJson = {
38
47
  id: reqId,
39
- title: projectName,
48
+ title: project.name,
40
49
  objective: objective || "N/A",
41
50
  status,
42
51
  actors: (0, list_1.parseList)(actors),
@@ -55,17 +64,58 @@ async function runReqCreate(draft) {
55
64
  links: (0, list_1.parseList)(links),
56
65
  updatedAt: new Date().toISOString()
57
66
  };
67
+ let gates = (0, gates_1.checkRequirementGates)(requirementJson);
68
+ if (!gates.ok) {
69
+ console.log("Requirement gates failed. Please provide missing fields:");
70
+ for (const field of gates.missing) {
71
+ if (field === "objective")
72
+ objective = await (0, prompt_1.ask)("Objective: ");
73
+ if (field === "scope.in")
74
+ scopeIn = await (0, prompt_1.ask)("Scope (in) - comma separated: ");
75
+ if (field === "scope.out")
76
+ scopeOut = await (0, prompt_1.ask)("Scope (out) - comma separated: ");
77
+ if (field === "acceptanceCriteria")
78
+ acceptance = await (0, prompt_1.ask)("Acceptance criteria - comma separated: ");
79
+ if (field === "nfrs.security")
80
+ nfrSecurity = await (0, prompt_1.ask)("NFR security: ");
81
+ if (field === "nfrs.performance")
82
+ nfrPerformance = await (0, prompt_1.ask)("NFR performance: ");
83
+ if (field === "nfrs.availability")
84
+ nfrAvailability = await (0, prompt_1.ask)("NFR availability: ");
85
+ }
86
+ requirementJson = {
87
+ ...requirementJson,
88
+ objective: objective || "N/A",
89
+ scope: {
90
+ in: (0, list_1.parseList)(scopeIn),
91
+ out: (0, list_1.parseList)(scopeOut)
92
+ },
93
+ acceptanceCriteria: (0, list_1.parseList)(acceptance),
94
+ nfrs: {
95
+ security: nfrSecurity || "N/A",
96
+ performance: nfrPerformance || "N/A",
97
+ availability: nfrAvailability || "N/A"
98
+ },
99
+ updatedAt: new Date().toISOString()
100
+ };
101
+ gates = (0, gates_1.checkRequirementGates)(requirementJson);
102
+ if (!gates.ok) {
103
+ console.log("Requirement gates still failing. Missing:");
104
+ gates.missing.forEach((field) => console.log(`- ${field}`));
105
+ return;
106
+ }
107
+ }
58
108
  const validation = (0, validate_1.validateJson)("requirement.schema.json", requirementJson);
59
109
  if (!validation.valid) {
60
110
  console.log("Requirement validation failed:");
61
111
  validation.errors.forEach((error) => console.log(`- ${error}`));
62
112
  return;
63
113
  }
64
- const requirementDir = path_1.default.join(workspace.root, projectName, "requirements", "backlog", reqId);
114
+ const requirementDir = path_1.default.join(project.root, "requirements", "backlog", reqId);
65
115
  fs_1.default.mkdirSync(requirementDir, { recursive: true });
66
116
  const template = (0, render_1.loadTemplate)("requirement");
67
117
  const rendered = (0, render_1.renderTemplate)(template, {
68
- title: projectName,
118
+ title: project.name,
69
119
  id: reqId,
70
120
  objective: objective || "N/A",
71
121
  actors: (0, list_1.formatList)(actors),
@@ -81,6 +131,13 @@ async function runReqCreate(draft) {
81
131
  });
82
132
  fs_1.default.writeFileSync(path_1.default.join(requirementDir, "requirement.md"), rendered, "utf-8");
83
133
  fs_1.default.writeFileSync(path_1.default.join(requirementDir, "requirement.json"), JSON.stringify(requirementJson, null, 2), "utf-8");
134
+ const summaryTemplate = (0, render_1.loadTemplate)("summary");
135
+ const summary = (0, render_1.renderTemplate)(summaryTemplate, {
136
+ objective: objective || "N/A",
137
+ decisions: "TBD",
138
+ open_questions: "TBD"
139
+ });
140
+ fs_1.default.writeFileSync(path_1.default.join(requirementDir, "summary.md"), summary, "utf-8");
84
141
  const changelogTemplate = (0, render_1.loadTemplate)("changelog");
85
142
  const changelog = (0, render_1.renderTemplate)(changelogTemplate, { date: new Date().toISOString() });
86
143
  fs_1.default.writeFileSync(path_1.default.join(requirementDir, "changelog.md"), changelog, "utf-8");
@@ -89,6 +146,6 @@ async function runReqCreate(draft) {
89
146
  fs_1.default.writeFileSync(progressLogPath, "# Progress Log\n\n", "utf-8");
90
147
  }
91
148
  console.log(`Created requirement in ${requirementDir}`);
92
- console.log(`Project metadata stored in ${path_1.default.join(workspace.root, projectName, "metadata.json")}`);
149
+ console.log(`Project metadata stored in ${path_1.default.join(project.root, "metadata.json")}`);
93
150
  console.log(`Project status: ${metadata.status}`);
94
151
  }
@@ -9,7 +9,7 @@ const path_1 = __importDefault(require("path"));
9
9
  const prompt_1 = require("../ui/prompt");
10
10
  const index_1 = require("../workspace/index");
11
11
  async function runReqExport() {
12
- const projectName = await (0, prompt_1.ask)("Project name: ");
12
+ const projectName = await (0, prompt_1.askProjectName)();
13
13
  const reqId = await (0, prompt_1.ask)("Requirement ID (REQ-...): ");
14
14
  const outputDir = await (0, prompt_1.ask)("Output directory: ");
15
15
  if (!projectName || !reqId || !outputDir) {
@@ -17,14 +17,22 @@ async function runReqExport() {
17
17
  return;
18
18
  }
19
19
  const workspace = (0, index_1.getWorkspaceInfo)();
20
- const base = path_1.default.join(workspace.root, projectName, "requirements");
20
+ let project;
21
+ try {
22
+ project = (0, index_1.getProjectInfo)(workspace, projectName);
23
+ }
24
+ catch (error) {
25
+ console.log(error.message);
26
+ return;
27
+ }
28
+ const base = path_1.default.join(project.root, "requirements");
21
29
  const statuses = ["backlog", "wip", "in-progress", "done", "archived"];
22
30
  const sourceDir = statuses.map((status) => path_1.default.join(base, status, reqId)).find((candidate) => fs_1.default.existsSync(candidate));
23
31
  if (!sourceDir) {
24
32
  console.log("Requirement not found.");
25
33
  return;
26
34
  }
27
- const targetDir = path_1.default.join(outputDir, `${projectName}-${reqId}`);
35
+ const targetDir = path_1.default.join(outputDir, `${project.name}-${reqId}`);
28
36
  fs_1.default.mkdirSync(targetDir, { recursive: true });
29
37
  for (const entry of fs_1.default.readdirSync(sourceDir)) {
30
38
  const srcPath = path_1.default.join(sourceDir, entry);