sdd-cli 0.1.19 → 0.1.21

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 (60) hide show
  1. package/README.md +41 -0
  2. package/dist/cli.js +58 -3
  3. package/dist/commands/ai-exec.js +3 -2
  4. package/dist/commands/ai-status.js +2 -1
  5. package/dist/commands/doctor.d.ts +1 -1
  6. package/dist/commands/doctor.js +218 -10
  7. package/dist/commands/gen-architecture.js +6 -5
  8. package/dist/commands/gen-best-practices.js +6 -5
  9. package/dist/commands/gen-functional-spec.js +6 -5
  10. package/dist/commands/gen-project-readme.js +6 -5
  11. package/dist/commands/gen-technical-spec.js +6 -5
  12. package/dist/commands/gen-utils.js +2 -1
  13. package/dist/commands/hello.js +27 -9
  14. package/dist/commands/import-issue.js +3 -2
  15. package/dist/commands/import-jira.d.ts +1 -0
  16. package/dist/commands/import-jira.js +127 -0
  17. package/dist/commands/learn-deliver.js +6 -5
  18. package/dist/commands/learn-refine.js +8 -7
  19. package/dist/commands/learn-start.js +3 -2
  20. package/dist/commands/list.js +19 -4
  21. package/dist/commands/pr-audit.js +6 -5
  22. package/dist/commands/pr-bridge-check.d.ts +1 -0
  23. package/dist/commands/pr-bridge-check.js +88 -0
  24. package/dist/commands/pr-bridge.d.ts +1 -0
  25. package/dist/commands/pr-bridge.js +124 -0
  26. package/dist/commands/pr-finish.js +6 -5
  27. package/dist/commands/pr-report.js +6 -5
  28. package/dist/commands/pr-respond.js +7 -6
  29. package/dist/commands/pr-risk.d.ts +1 -0
  30. package/dist/commands/pr-risk.js +112 -0
  31. package/dist/commands/pr-start.js +4 -3
  32. package/dist/commands/quickstart.js +10 -1
  33. package/dist/commands/req-archive.js +4 -3
  34. package/dist/commands/req-create.js +8 -7
  35. package/dist/commands/req-export.js +4 -3
  36. package/dist/commands/req-finish.js +9 -8
  37. package/dist/commands/req-lint.js +16 -6
  38. package/dist/commands/req-list.js +4 -3
  39. package/dist/commands/req-plan.js +12 -11
  40. package/dist/commands/req-refine.js +9 -8
  41. package/dist/commands/req-report.js +10 -9
  42. package/dist/commands/req-start.js +10 -9
  43. package/dist/commands/req-status.js +4 -3
  44. package/dist/commands/route.js +19 -4
  45. package/dist/commands/scope-list.d.ts +1 -0
  46. package/dist/commands/scope-list.js +16 -0
  47. package/dist/commands/scope-status.d.ts +1 -0
  48. package/dist/commands/scope-status.js +33 -0
  49. package/dist/commands/status.js +16 -7
  50. package/dist/commands/test-plan.js +6 -5
  51. package/dist/context/flags.d.ts +2 -0
  52. package/dist/context/flags.js +9 -1
  53. package/dist/errors.d.ts +2 -0
  54. package/dist/errors.js +10 -0
  55. package/dist/paths.js +4 -0
  56. package/dist/telemetry/local-metrics.d.ts +2 -0
  57. package/dist/telemetry/local-metrics.js +85 -0
  58. package/dist/workspace/index.d.ts +4 -0
  59. package/dist/workspace/index.js +129 -27
  60. package/package.json +24 -2
@@ -9,11 +9,12 @@ const path_1 = __importDefault(require("path"));
9
9
  const prompt_1 = require("../ui/prompt");
10
10
  const index_1 = require("../workspace/index");
11
11
  const validate_1 = require("../validation/validate");
12
+ const errors_1 = require("../errors");
12
13
  async function runReqLint() {
13
14
  const projectName = await (0, prompt_1.askProjectName)();
14
15
  const reqId = await (0, prompt_1.ask)("Requirement ID (REQ-...): ");
15
16
  if (!projectName || !reqId) {
16
- console.log("Project name and requirement ID are required.");
17
+ (0, errors_1.printError)("SDD-1247", "Project name and requirement ID are required.");
17
18
  return;
18
19
  }
19
20
  const workspace = (0, index_1.getWorkspaceInfo)();
@@ -22,7 +23,7 @@ async function runReqLint() {
22
23
  project = (0, index_1.getProjectInfo)(workspace, projectName);
23
24
  }
24
25
  catch (error) {
25
- console.log(error.message);
26
+ (0, errors_1.printError)("SDD-1248", error.message);
26
27
  return;
27
28
  }
28
29
  const base = path_1.default.join(project.root, "requirements");
@@ -31,7 +32,7 @@ async function runReqLint() {
31
32
  .map((status) => path_1.default.join(base, status, reqId))
32
33
  .find((candidate) => fs_1.default.existsSync(candidate));
33
34
  if (!dir) {
34
- console.log("Requirement not found.");
35
+ (0, errors_1.printError)("SDD-1249", "Requirement not found.");
35
36
  return;
36
37
  }
37
38
  const schemaMap = {
@@ -49,12 +50,21 @@ async function runReqLint() {
49
50
  if (!fs_1.default.existsSync(filePath)) {
50
51
  continue;
51
52
  }
52
- const data = JSON.parse(fs_1.default.readFileSync(filePath, "utf-8"));
53
+ let data;
54
+ try {
55
+ data = JSON.parse(fs_1.default.readFileSync(filePath, "utf-8"));
56
+ }
57
+ catch (error) {
58
+ failures += 1;
59
+ (0, errors_1.printError)("SDD-1250", `Invalid JSON: ${file}`);
60
+ (0, errors_1.printError)("SDD-1250", error.message);
61
+ continue;
62
+ }
53
63
  const result = (0, validate_1.validateJson)(schema, data);
54
64
  if (!result.valid) {
55
65
  failures += 1;
56
- console.log(`Invalid: ${file}`);
57
- result.errors.forEach((error) => console.log(`- ${error}`));
66
+ (0, errors_1.printError)("SDD-1250", `Invalid: ${file}`);
67
+ result.errors.forEach((error) => (0, errors_1.printError)("SDD-1250", error));
58
68
  }
59
69
  else {
60
70
  console.log(`Valid: ${file}`);
@@ -8,11 +8,12 @@ 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
+ const errors_1 = require("../errors");
11
12
  const STATUSES = ["backlog", "wip", "in-progress", "done", "archived"];
12
13
  async function runReqList(statusFilter) {
13
14
  const projectName = await (0, prompt_1.askProjectName)();
14
15
  if (!projectName) {
15
- console.log("Project name is required.");
16
+ (0, errors_1.printError)("SDD-1251", "Project name is required.");
16
17
  return;
17
18
  }
18
19
  const workspace = (0, index_1.getWorkspaceInfo)();
@@ -21,12 +22,12 @@ async function runReqList(statusFilter) {
21
22
  project = (0, index_1.getProjectInfo)(workspace, projectName);
22
23
  }
23
24
  catch (error) {
24
- console.log(error.message);
25
+ (0, errors_1.printError)("SDD-1252", error.message);
25
26
  return;
26
27
  }
27
28
  const base = path_1.default.join(project.root, "requirements");
28
29
  if (!fs_1.default.existsSync(base)) {
29
- console.log("No requirements found for this project.");
30
+ (0, errors_1.printError)("SDD-1253", "No requirements found for this project.");
30
31
  return;
31
32
  }
32
33
  const statuses = statusFilter ? STATUSES.filter((status) => status === statusFilter) : STATUSES;
@@ -13,6 +13,7 @@ const render_1 = require("../templates/render");
13
13
  const list_1 = require("../utils/list");
14
14
  const gates_1 = require("../validation/gates");
15
15
  const validate_1 = require("../validation/validate");
16
+ const errors_1 = require("../errors");
16
17
  function findRequirementDir(projectRoot, reqId) {
17
18
  const backlog = path_1.default.join(projectRoot, "requirements", "backlog", reqId);
18
19
  const wip = path_1.default.join(projectRoot, "requirements", "wip", reqId);
@@ -31,7 +32,7 @@ async function runReqPlan(options) {
31
32
  const projectName = options?.projectName ?? (await (0, prompt_1.askProjectName)());
32
33
  const reqId = options?.reqId ?? (await (0, prompt_1.ask)("Requirement ID (REQ-...): "));
33
34
  if (!projectName || !reqId) {
34
- console.log("Project name and requirement ID are required.");
35
+ (0, errors_1.printError)("SDD-1211", "Project name and requirement ID are required.");
35
36
  return null;
36
37
  }
37
38
  const workspace = (0, index_1.getWorkspaceInfo)();
@@ -40,31 +41,31 @@ async function runReqPlan(options) {
40
41
  project = (0, index_1.getProjectInfo)(workspace, projectName);
41
42
  }
42
43
  catch (error) {
43
- console.log(error.message);
44
+ (0, errors_1.printError)("SDD-1212", error.message);
44
45
  return null;
45
46
  }
46
47
  let requirementDir = findRequirementDir(project.root, reqId);
47
48
  if (!requirementDir) {
48
- console.log("Requirement not found in backlog or wip.");
49
+ (0, errors_1.printError)("SDD-1213", "Requirement not found in backlog or wip.");
49
50
  return null;
50
51
  }
51
52
  const requirementJsonPath = path_1.default.join(requirementDir, "requirement.json");
52
53
  if (!fs_1.default.existsSync(requirementJsonPath)) {
53
- console.log("Missing requirement.json. Run `req create` first.");
54
+ (0, errors_1.printError)("SDD-1214", "Missing requirement.json. Run `req create` first.");
54
55
  return null;
55
56
  }
56
57
  const requirementJson = JSON.parse(fs_1.default.readFileSync(requirementJsonPath, "utf-8"));
57
58
  let gates = (0, gates_1.checkRequirementGates)(requirementJson);
58
59
  if (!gates.ok) {
59
- console.log("Requirement gates failed. Please update the requirement first:");
60
- gates.missing.forEach((field) => console.log(`- ${field}`));
61
- console.log("Run `sdd-cli req refine` to complete missing fields.");
60
+ (0, errors_1.printError)("SDD-1217", "Requirement gates failed. Please update the requirement first.");
61
+ gates.missing.forEach((field) => (0, errors_1.printError)("SDD-1217", field));
62
+ (0, errors_1.printError)("SDD-1217", "Run `sdd-cli req refine` to complete missing fields.");
62
63
  return null;
63
64
  }
64
65
  const requirementValidation = (0, validate_1.validateJson)("requirement.schema.json", requirementJson);
65
66
  if (!requirementValidation.valid) {
66
- console.log("Requirement validation failed:");
67
- requirementValidation.errors.forEach((error) => console.log(`- ${error}`));
67
+ (0, errors_1.printError)("SDD-1215", "Requirement validation failed.");
68
+ requirementValidation.errors.forEach((error) => (0, errors_1.printError)("SDD-1215", error));
68
69
  return null;
69
70
  }
70
71
  const wipDir = path_1.default.join(project.root, "requirements", "wip", reqId);
@@ -147,8 +148,8 @@ async function runReqPlan(options) {
147
148
  ];
148
149
  const failures = validations.flatMap((result) => result.errors);
149
150
  if (failures.length > 0) {
150
- console.log("Spec validation failed:");
151
- failures.forEach((error) => console.log(`- ${error}`));
151
+ (0, errors_1.printError)("SDD-1216", "Spec validation failed.");
152
+ failures.forEach((error) => (0, errors_1.printError)("SDD-1216", error));
152
153
  return null;
153
154
  }
154
155
  const functionalTemplate = (0, render_1.loadTemplate)("functional-spec");
@@ -13,6 +13,7 @@ const render_1 = require("../templates/render");
13
13
  const list_1 = require("../utils/list");
14
14
  const gates_1 = require("../validation/gates");
15
15
  const validate_1 = require("../validation/validate");
16
+ const errors_1 = require("../errors");
16
17
  function findRequirementFile(projectRoot, reqId) {
17
18
  const base = path_1.default.join(projectRoot, "requirements");
18
19
  const candidates = [
@@ -27,7 +28,7 @@ async function runReqRefine() {
27
28
  const projectName = await (0, prompt_1.askProjectName)();
28
29
  const reqId = await (0, prompt_1.ask)("Requirement ID (REQ-...): ");
29
30
  if (!projectName || !reqId) {
30
- console.log("Project name and requirement ID are required.");
31
+ (0, errors_1.printError)("SDD-1261", "Project name and requirement ID are required.");
31
32
  return;
32
33
  }
33
34
  const workspace = (0, index_1.getWorkspaceInfo)();
@@ -36,12 +37,12 @@ async function runReqRefine() {
36
37
  project = (0, index_1.getProjectInfo)(workspace, projectName);
37
38
  }
38
39
  catch (error) {
39
- console.log(error.message);
40
+ (0, errors_1.printError)("SDD-1262", error.message);
40
41
  return;
41
42
  }
42
43
  const reqPath = findRequirementFile(project.root, reqId);
43
44
  if (!reqPath) {
44
- console.log("Requirement not found.");
45
+ (0, errors_1.printError)("SDD-1263", "Requirement not found.");
45
46
  return;
46
47
  }
47
48
  const raw = JSON.parse(fs_1.default.readFileSync(reqPath, "utf-8"));
@@ -79,7 +80,7 @@ async function runReqRefine() {
79
80
  };
80
81
  let gates = (0, gates_1.checkRequirementGates)(updated);
81
82
  if (!gates.ok) {
82
- console.log("Requirement gates failed. Please provide missing fields:");
83
+ (0, errors_1.printError)("SDD-1264", "Requirement gates failed. Please provide missing fields.");
83
84
  for (const field of gates.missing) {
84
85
  if (field === "objective") {
85
86
  updated.objective = await (0, prompt_1.ask)(`Objective (${updated.objective}): `);
@@ -112,15 +113,15 @@ async function runReqRefine() {
112
113
  updated.updatedAt = new Date().toISOString();
113
114
  gates = (0, gates_1.checkRequirementGates)(updated);
114
115
  if (!gates.ok) {
115
- console.log("Requirement gates still failing. Missing:");
116
- gates.missing.forEach((field) => console.log(`- ${field}`));
116
+ (0, errors_1.printError)("SDD-1265", "Requirement gates still failing.");
117
+ gates.missing.forEach((field) => (0, errors_1.printError)("SDD-1265", field));
117
118
  return;
118
119
  }
119
120
  }
120
121
  const validation = (0, validate_1.validateJson)("requirement.schema.json", updated);
121
122
  if (!validation.valid) {
122
- console.log("Requirement validation failed:");
123
- validation.errors.forEach((error) => console.log(`- ${error}`));
123
+ (0, errors_1.printError)("SDD-1266", "Requirement validation failed.");
124
+ validation.errors.forEach((error) => (0, errors_1.printError)("SDD-1266", error));
124
125
  return;
125
126
  }
126
127
  fs_1.default.writeFileSync(reqPath, JSON.stringify(updated, null, 2), "utf-8");
@@ -8,6 +8,7 @@ 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
+ const errors_1 = require("../errors");
11
12
  const REQUIRED_FILES = [
12
13
  "requirement.json",
13
14
  "functional-spec.json",
@@ -20,7 +21,7 @@ async function runReqReport() {
20
21
  const projectName = await (0, prompt_1.askProjectName)();
21
22
  const reqId = await (0, prompt_1.ask)("Requirement ID (REQ-...): ");
22
23
  if (!projectName || !reqId) {
23
- console.log("Project name and requirement ID are required.");
24
+ (0, errors_1.printError)("SDD-1257", "Project name and requirement ID are required.");
24
25
  return;
25
26
  }
26
27
  const workspace = (0, index_1.getWorkspaceInfo)();
@@ -29,29 +30,29 @@ async function runReqReport() {
29
30
  project = (0, index_1.getProjectInfo)(workspace, projectName);
30
31
  }
31
32
  catch (error) {
32
- console.log(error.message);
33
+ (0, errors_1.printError)("SDD-1258", error.message);
33
34
  return;
34
35
  }
35
36
  const base = path_1.default.join(project.root, "requirements");
36
37
  const statuses = ["backlog", "wip", "in-progress", "done", "archived"];
37
38
  const dir = statuses.map((status) => path_1.default.join(base, status, reqId)).find((candidate) => fs_1.default.existsSync(candidate));
38
39
  if (!dir) {
39
- console.log("Requirement not found.");
40
+ (0, errors_1.printError)("SDD-1259", "Requirement not found.");
40
41
  return;
41
42
  }
42
43
  console.log(`Requirement report: ${reqId}`);
43
- let missing = 0;
44
+ let absentCount = 0;
44
45
  for (const file of REQUIRED_FILES) {
45
46
  const exists = fs_1.default.existsSync(path_1.default.join(dir, file));
46
- console.log(`${exists ? "OK" : "MISSING"}: ${file}`);
47
+ console.log(`${exists ? "OK" : "ABSENT"}: ${file}`);
47
48
  if (!exists)
48
- missing += 1;
49
+ absentCount += 1;
49
50
  }
50
51
  const projectReadmePath = path_1.default.join(project.root, "project-readme.json");
51
52
  const projectReadmeExists = fs_1.default.existsSync(projectReadmePath);
52
- console.log(`${projectReadmeExists ? "OK" : "MISSING"}: ../project-readme.json`);
53
+ console.log(`${projectReadmeExists ? "OK" : "ABSENT"}: ../project-readme.json`);
53
54
  if (!projectReadmeExists) {
54
- missing += 1;
55
+ absentCount += 1;
55
56
  }
56
- console.log(`Missing files: ${missing}`);
57
+ console.log(`Absent files: ${absentCount}`);
57
58
  }
@@ -12,6 +12,7 @@ const index_1 = require("../workspace/index");
12
12
  const render_1 = require("../templates/render");
13
13
  const list_1 = require("../utils/list");
14
14
  const validate_1 = require("../validation/validate");
15
+ const errors_1 = require("../errors");
15
16
  function findRequirementDir(projectRoot, reqId) {
16
17
  const backlog = path_1.default.join(projectRoot, "requirements", "backlog", reqId);
17
18
  const wip = path_1.default.join(projectRoot, "requirements", "wip", reqId);
@@ -33,7 +34,7 @@ async function runReqStart(options) {
33
34
  const projectName = options?.projectName ?? (await (0, prompt_1.askProjectName)());
34
35
  const reqId = options?.reqId ?? (await (0, prompt_1.ask)("Requirement ID (REQ-...): "));
35
36
  if (!projectName || !reqId) {
36
- console.log("Project name and requirement ID are required.");
37
+ (0, errors_1.printError)("SDD-1221", "Project name and requirement ID are required.");
37
38
  return null;
38
39
  }
39
40
  const workspace = (0, index_1.getWorkspaceInfo)();
@@ -42,12 +43,12 @@ async function runReqStart(options) {
42
43
  project = (0, index_1.getProjectInfo)(workspace, projectName);
43
44
  }
44
45
  catch (error) {
45
- console.log(error.message);
46
+ (0, errors_1.printError)("SDD-1222", error.message);
46
47
  return null;
47
48
  }
48
49
  let requirementDir = findRequirementDir(project.root, reqId);
49
50
  if (!requirementDir) {
50
- console.log("Requirement not found.");
51
+ (0, errors_1.printError)("SDD-1223", "Requirement not found.");
51
52
  return null;
52
53
  }
53
54
  const requirementPath = requirementDir;
@@ -59,16 +60,16 @@ async function runReqStart(options) {
59
60
  ];
60
61
  const missing = requiredSpecs.filter((spec) => !fs_1.default.existsSync(path_1.default.join(requirementPath, spec.file)));
61
62
  if (missing.length > 0) {
62
- console.log("Cannot start. Missing specs:");
63
- missing.forEach((spec) => console.log(`- ${spec.file}`));
63
+ (0, errors_1.printError)("SDD-1224", "Cannot start. Missing specs.");
64
+ missing.forEach((spec) => (0, errors_1.printError)("SDD-1224", spec.file));
64
65
  return null;
65
66
  }
66
67
  for (const spec of requiredSpecs) {
67
68
  const data = JSON.parse(fs_1.default.readFileSync(path_1.default.join(requirementPath, spec.file), "utf-8"));
68
69
  const result = (0, validate_1.validateJson)(spec.schema, data);
69
70
  if (!result.valid) {
70
- console.log(`Spec validation failed for ${spec.file}:`);
71
- result.errors.forEach((error) => console.log(`- ${error}`));
71
+ (0, errors_1.printError)("SDD-1225", `Spec validation failed for ${spec.file}.`);
72
+ result.errors.forEach((error) => (0, errors_1.printError)("SDD-1225", error));
72
73
  return null;
73
74
  }
74
75
  }
@@ -114,8 +115,8 @@ async function runReqStart(options) {
114
115
  };
115
116
  const validation = (0, validate_1.validateJson)("quality.schema.json", qualityJson);
116
117
  if (!validation.valid) {
117
- console.log("Quality validation failed:");
118
- validation.errors.forEach((error) => console.log(`- ${error}`));
118
+ (0, errors_1.printError)("SDD-1226", "Quality validation failed.");
119
+ validation.errors.forEach((error) => (0, errors_1.printError)("SDD-1226", error));
119
120
  return null;
120
121
  }
121
122
  fs_1.default.writeFileSync(path_1.default.join(targetDir, "implementation-plan.md"), rendered, "utf-8");
@@ -8,11 +8,12 @@ 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
+ const errors_1 = require("../errors");
11
12
  async function runReqStatus() {
12
13
  const projectName = await (0, prompt_1.askProjectName)();
13
14
  const reqId = await (0, prompt_1.ask)("Requirement ID (REQ-...): ");
14
15
  if (!projectName || !reqId) {
15
- console.log("Project name and requirement ID are required.");
16
+ (0, errors_1.printError)("SDD-1254", "Project name and requirement ID are required.");
16
17
  return;
17
18
  }
18
19
  const workspace = (0, index_1.getWorkspaceInfo)();
@@ -21,7 +22,7 @@ async function runReqStatus() {
21
22
  project = (0, index_1.getProjectInfo)(workspace, projectName);
22
23
  }
23
24
  catch (error) {
24
- console.log(error.message);
25
+ (0, errors_1.printError)("SDD-1255", error.message);
25
26
  return;
26
27
  }
27
28
  const base = path_1.default.join(project.root, "requirements");
@@ -33,5 +34,5 @@ async function runReqStatus() {
33
34
  return;
34
35
  }
35
36
  }
36
- console.log("Requirement not found.");
37
+ (0, errors_1.printError)("SDD-1256", "Requirement not found.");
37
38
  }
@@ -4,10 +4,25 @@ exports.runRoute = runRoute;
4
4
  const intent_1 = require("../router/intent");
5
5
  const flow_1 = require("../router/flow");
6
6
  const prompt_packs_1 = require("../router/prompt-packs");
7
+ const errors_1 = require("../errors");
7
8
  function runRoute(input) {
8
- const intent = (0, intent_1.classifyIntent)(input);
9
- const flow = (0, flow_1.loadFlow)(intent.flow);
10
- const packs = (0, prompt_packs_1.loadPromptPacks)();
9
+ const text = input.trim();
10
+ if (!text) {
11
+ (0, errors_1.printError)("SDD-1423", "Route input is required.");
12
+ return;
13
+ }
14
+ let intent;
15
+ let flow;
16
+ let packs;
17
+ try {
18
+ intent = (0, intent_1.classifyIntent)(text);
19
+ flow = (0, flow_1.loadFlow)(intent.flow);
20
+ packs = (0, prompt_packs_1.loadPromptPacks)();
21
+ }
22
+ catch (error) {
23
+ (0, errors_1.printError)("SDD-1424", `Unable to load route context: ${error.message}`);
24
+ return;
25
+ }
11
26
  const packIds = intent_1.FLOW_PROMPT_PACKS[intent.flow] ?? [];
12
27
  console.log(JSON.stringify(intent, null, 2));
13
28
  if (flow) {
@@ -15,7 +30,7 @@ function runRoute(input) {
15
30
  console.log(flow);
16
31
  }
17
32
  else {
18
- console.log("\nNo flow script found.");
33
+ (0, errors_1.printError)("SDD-1425", `No flow script found for ${intent.flow}.`);
19
34
  }
20
35
  if (packIds.length > 0) {
21
36
  console.log("\n--- Prompt packs ---\n");
@@ -0,0 +1 @@
1
+ export declare function runScopeList(): void;
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.runScopeList = runScopeList;
4
+ const index_1 = require("../workspace/index");
5
+ const errors_1 = require("../errors");
6
+ function runScopeList() {
7
+ const baseRoot = (0, index_1.getWorkspaceBaseRoot)();
8
+ const scopes = (0, index_1.listScopes)(baseRoot);
9
+ if (scopes.length === 0) {
10
+ (0, errors_1.printError)("SDD-1412", "No scopes available in workspace.");
11
+ return;
12
+ }
13
+ console.log(`Workspace base: ${baseRoot}`);
14
+ console.log("Scopes:");
15
+ scopes.forEach((scope) => console.log(`- ${scope}`));
16
+ }
@@ -0,0 +1 @@
1
+ export declare function runScopeStatus(scopeInput?: string): void;
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.runScopeStatus = runScopeStatus;
4
+ const flags_1 = require("../context/flags");
5
+ const index_1 = require("../workspace/index");
6
+ const errors_1 = require("../errors");
7
+ function runScopeStatus(scopeInput) {
8
+ const flags = (0, flags_1.getFlags)();
9
+ const scope = scopeInput?.trim() || flags.scope || "";
10
+ if (!scope) {
11
+ (0, errors_1.printError)("SDD-1411", "Scope is required. Use: sdd-cli scope status <scope-name>");
12
+ return;
13
+ }
14
+ const workspace = (0, index_1.getWorkspaceInfoForScope)(scope);
15
+ (0, index_1.ensureWorkspace)(workspace);
16
+ const projects = (0, index_1.listProjects)(workspace);
17
+ console.log(`Scope: ${scope}`);
18
+ console.log(`Workspace: ${workspace.root}`);
19
+ if (projects.length === 0) {
20
+ console.log("No projects found for scope.");
21
+ return;
22
+ }
23
+ const byStatus = projects.reduce((acc, project) => {
24
+ acc[project.status] = (acc[project.status] || 0) + 1;
25
+ return acc;
26
+ }, {});
27
+ console.log(`Projects: ${projects.length}`);
28
+ Object.keys(byStatus)
29
+ .sort()
30
+ .forEach((status) => {
31
+ console.log(`- ${status}: ${byStatus[status]}`);
32
+ });
33
+ }
@@ -8,6 +8,7 @@ const fs_1 = __importDefault(require("fs"));
8
8
  const path_1 = __importDefault(require("path"));
9
9
  const flags_1 = require("../context/flags");
10
10
  const index_1 = require("../workspace/index");
11
+ const errors_1 = require("../errors");
11
12
  const REQUIREMENT_STATUSES = ["backlog", "wip", "in-progress", "done", "archived"];
12
13
  function listRequirementIds(projectRoot, status) {
13
14
  const dir = path_1.default.join(projectRoot, "requirements", status);
@@ -26,23 +27,28 @@ function latestId(ids) {
26
27
  }
27
28
  return ids[ids.length - 1];
28
29
  }
30
+ function scopePrefix() {
31
+ const flags = (0, flags_1.getFlags)();
32
+ return flags.scope && flags.scope.trim().length > 0 ? `--scope "${flags.scope.trim()}" ` : "";
33
+ }
29
34
  function recommendNext(projectName, counts, ids) {
35
+ const prefix = scopePrefix();
30
36
  const nextInProgress = latestId(ids["in-progress"]);
31
37
  if (nextInProgress) {
32
- return `sdd-cli --project "${projectName}" req finish # then enter ${nextInProgress} when prompted`;
38
+ return `sdd-cli ${prefix}--project "${projectName}" req finish # then enter ${nextInProgress} when prompted`;
33
39
  }
34
40
  const nextWip = latestId(ids.wip);
35
41
  if (nextWip) {
36
- return `sdd-cli --project "${projectName}" req start # then enter ${nextWip} when prompted`;
42
+ return `sdd-cli ${prefix}--project "${projectName}" req start # then enter ${nextWip} when prompted`;
37
43
  }
38
44
  const nextBacklog = latestId(ids.backlog);
39
45
  if (nextBacklog) {
40
- return `sdd-cli --project "${projectName}" req plan # then enter ${nextBacklog} when prompted`;
46
+ return `sdd-cli ${prefix}--project "${projectName}" req plan # then enter ${nextBacklog} when prompted`;
41
47
  }
42
48
  if (counts.done > 0 && counts.archived === 0) {
43
- return `sdd-cli --project "${projectName}" hello "start next requirement"`;
49
+ return `sdd-cli ${prefix}--project "${projectName}" hello "start next requirement"`;
44
50
  }
45
- return `sdd-cli --project "${projectName}" hello "continue"`;
51
+ return `sdd-cli ${prefix}--project "${projectName}" hello "continue"`;
46
52
  }
47
53
  function runStatus(showNext) {
48
54
  const workspace = (0, index_1.getWorkspaceInfo)();
@@ -62,11 +68,11 @@ function runStatus(showNext) {
62
68
  project = (0, index_1.getProjectInfo)(workspace, selectedName);
63
69
  }
64
70
  catch (error) {
65
- console.log(error.message);
71
+ (0, errors_1.printError)("SDD-1401", error.message);
66
72
  return;
67
73
  }
68
74
  if (!fs_1.default.existsSync(project.root)) {
69
- console.log("No projects found.");
75
+ (0, errors_1.printError)("SDD-1402", `Selected project not found in workspace: ${project.name}`);
70
76
  if (showNext) {
71
77
  console.log('Next command: sdd-cli quickstart --example saas');
72
78
  }
@@ -86,6 +92,9 @@ function runStatus(showNext) {
86
92
  done: ids.done.length,
87
93
  archived: ids.archived.length
88
94
  };
95
+ if (flags.scope && flags.scope.trim().length > 0) {
96
+ console.log(`Scope: ${flags.scope.trim()}`);
97
+ }
89
98
  console.log(`Project: ${project.name}`);
90
99
  REQUIREMENT_STATUSES.forEach((status) => {
91
100
  console.log(`- ${status}: ${counts[status]}`);
@@ -12,6 +12,7 @@ const render_1 = require("../templates/render");
12
12
  const list_1 = require("../utils/list");
13
13
  const validate_1 = require("../validation/validate");
14
14
  const flags_1 = require("../context/flags");
15
+ const errors_1 = require("../errors");
15
16
  function findRequirementDir(projectRoot, reqId) {
16
17
  const base = path_1.default.join(projectRoot, "requirements");
17
18
  const statuses = ["backlog", "wip", "in-progress", "done", "archived"];
@@ -32,7 +33,7 @@ async function runTestPlan(options) {
32
33
  const projectName = options?.projectName ?? (await (0, prompt_1.askProjectName)());
33
34
  const reqId = options?.reqId ?? (await (0, prompt_1.ask)("Requirement ID (REQ-...): "));
34
35
  if (!projectName || !reqId) {
35
- console.log("Project name and requirement ID are required.");
36
+ (0, errors_1.printError)("SDD-1271", "Project name and requirement ID are required.");
36
37
  return null;
37
38
  }
38
39
  const workspace = (0, index_1.getWorkspaceInfo)();
@@ -41,12 +42,12 @@ async function runTestPlan(options) {
41
42
  project = (0, index_1.getProjectInfo)(workspace, projectName);
42
43
  }
43
44
  catch (error) {
44
- console.log(error.message);
45
+ (0, errors_1.printError)("SDD-1272", error.message);
45
46
  return null;
46
47
  }
47
48
  const requirementDir = findRequirementDir(project.root, reqId);
48
49
  if (!requirementDir) {
49
- console.log("Requirement not found.");
50
+ (0, errors_1.printError)("SDD-1273", "Requirement not found.");
50
51
  return null;
51
52
  }
52
53
  const seed = defaultSeed(options?.seedText);
@@ -66,8 +67,8 @@ async function runTestPlan(options) {
66
67
  };
67
68
  const validation = (0, validate_1.validateJson)("test-plan.schema.json", testPlanJson);
68
69
  if (!validation.valid) {
69
- console.log("Test plan validation failed:");
70
- validation.errors.forEach((error) => console.log(`- ${error}`));
70
+ (0, errors_1.printError)("SDD-1274", "Test plan validation failed.");
71
+ validation.errors.forEach((error) => (0, errors_1.printError)("SDD-1274", error));
71
72
  return null;
72
73
  }
73
74
  const template = (0, render_1.loadTemplate)("test-plan");
@@ -8,6 +8,8 @@ export type RuntimeFlags = {
8
8
  fromStep?: string;
9
9
  project?: string;
10
10
  output?: string;
11
+ scope?: string;
12
+ metricsLocal?: boolean;
11
13
  };
12
14
  export declare function setFlags(next: Partial<RuntimeFlags>): void;
13
15
  export declare function getFlags(): RuntimeFlags;
@@ -11,7 +11,9 @@ const flags = {
11
11
  beginner: false,
12
12
  fromStep: undefined,
13
13
  project: undefined,
14
- output: undefined
14
+ output: undefined,
15
+ scope: undefined,
16
+ metricsLocal: false
15
17
  };
16
18
  function setFlags(next) {
17
19
  if ("approve" in next) {
@@ -41,6 +43,12 @@ function setFlags(next) {
41
43
  if ("output" in next) {
42
44
  flags.output = typeof next.output === "string" ? next.output : undefined;
43
45
  }
46
+ if ("scope" in next) {
47
+ flags.scope = typeof next.scope === "string" ? next.scope : undefined;
48
+ }
49
+ if ("metricsLocal" in next) {
50
+ flags.metricsLocal = Boolean(next.metricsLocal);
51
+ }
44
52
  }
45
53
  function getFlags() {
46
54
  return { ...flags };
@@ -0,0 +1,2 @@
1
+ export declare function formatError(code: string, message: string): string;
2
+ export declare function printError(code: string, message: string): void;
package/dist/errors.js ADDED
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.formatError = formatError;
4
+ exports.printError = printError;
5
+ function formatError(code, message) {
6
+ return `[${code}] ${message}`;
7
+ }
8
+ function printError(code, message) {
9
+ console.log(formatError(code, message));
10
+ }
package/dist/paths.js CHANGED
@@ -6,5 +6,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.getRepoRoot = getRepoRoot;
7
7
  const path_1 = __importDefault(require("path"));
8
8
  function getRepoRoot() {
9
+ const override = process.env.SDD_REPO_ROOT?.trim();
10
+ if (override) {
11
+ return path_1.default.resolve(override);
12
+ }
9
13
  return path_1.default.resolve(__dirname, "..");
10
14
  }
@@ -0,0 +1,2 @@
1
+ export declare function recordCommandMetric(command: string): void;
2
+ export declare function recordActivationMetric(type: "started" | "completed", data?: Record<string, string | number | boolean>): void;