sdd-cli 0.1.8 → 0.1.10

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.
@@ -8,7 +8,32 @@ const prompt_packs_1 = require("../router/prompt-packs");
8
8
  const prompt_map_1 = require("../router/prompt-map");
9
9
  const req_create_1 = require("./req-create");
10
10
  const flags_1 = require("../context/flags");
11
+ const req_plan_1 = require("./req-plan");
12
+ const req_start_1 = require("./req-start");
13
+ const req_finish_1 = require("./req-finish");
11
14
  const route_1 = require("./route");
15
+ const test_plan_1 = require("./test-plan");
16
+ function printStep(step, description) {
17
+ console.log(`${step}: ${description}`);
18
+ }
19
+ function printWhy(message) {
20
+ console.log(` -> ${message}`);
21
+ }
22
+ function deriveProjectName(input, flow) {
23
+ const seed = input
24
+ .trim()
25
+ .toLowerCase()
26
+ .replace(/[^a-z0-9 _-]+/g, " ")
27
+ .replace(/\s+/g, " ")
28
+ .trim()
29
+ .split(" ")
30
+ .filter((token) => token.length > 0)
31
+ .slice(0, 4)
32
+ .join("-");
33
+ const date = new Date().toISOString().slice(0, 10).replace(/-/g, "");
34
+ const base = seed.length > 0 ? seed : flow.toLowerCase();
35
+ return `autopilot-${base}-${date}`;
36
+ }
12
37
  function buildAutopilotDraft(input, flow, domain) {
13
38
  const cleanInput = input.trim();
14
39
  const objective = cleanInput.length > 0 ? cleanInput : "Deliver a clear first requirement draft.";
@@ -123,16 +148,18 @@ async function runHello(input, runQuestions) {
123
148
  }
124
149
  const intent = (0, intent_1.classifyIntent)(text);
125
150
  console.log(`Detected intent: ${intent.intent} -> ${intent.flow}`);
126
- console.log("Step 1/3: Intent detected.");
127
- const showRoute = await (0, prompt_1.confirm)("View route details now? (y/n) ");
128
- if (showRoute) {
151
+ printStep("Step 1/7", "Intent detected");
152
+ printWhy("I classified your goal and selected the best starting flow.");
153
+ const showRoute = runQuestions === true ? await (0, prompt_1.confirm)("View route details now? (y/n) ") : false;
154
+ if (showRoute && runQuestions === true) {
129
155
  (0, route_1.runRoute)(text);
130
156
  }
131
157
  else {
132
158
  console.log("Next: run `sdd-cli route <your input>` to view details.");
133
159
  }
134
- const shouldRunQuestions = runQuestions ?? (await (0, prompt_1.confirm)("Run prompt questions now? (y/n) "));
135
- console.log("Step 2/3: Requirement setup.");
160
+ const shouldRunQuestions = runQuestions === true;
161
+ printStep("Step 2/7", "Requirement setup");
162
+ printWhy("I will gather enough context to generate a valid first draft.");
136
163
  if (shouldRunQuestions) {
137
164
  const packs = (0, prompt_packs_1.loadPromptPacks)();
138
165
  const packIds = intent_1.FLOW_PROMPT_PACKS[intent.flow] ?? [];
@@ -159,28 +186,82 @@ async function runHello(input, runQuestions) {
159
186
  if (ok) {
160
187
  const created = await (0, req_create_1.runReqCreate)(mapped, { autofill: true });
161
188
  if (created) {
162
- console.log(`Step 3/3: Draft created (${created.reqId}).`);
189
+ printStep("Step 3/7", `Draft created (${created.reqId})`);
163
190
  console.log("Next suggested command: sdd-cli req refine");
164
191
  }
165
192
  }
166
193
  }
167
194
  }
168
195
  else {
169
- const auto = await (0, prompt_1.confirm)("Create a first requirement draft automatically now? (y/n) ");
170
- if (auto) {
171
- const draft = buildAutopilotDraft(text, intent.flow, intent.domain);
172
- const created = await (0, req_create_1.runReqCreate)(draft, { autofill: true });
173
- if (created) {
174
- console.log(`Step 3/3: Draft created (${created.reqId}).`);
175
- console.log("Next suggested commands:");
176
- console.log("- sdd-cli req refine");
177
- console.log("- sdd-cli req plan");
178
- }
196
+ let activeProject = (0, flags_1.getFlags)().project;
197
+ if (!activeProject) {
198
+ const quickProject = await (0, prompt_1.ask)("Project name (optional, press Enter to auto-generate): ");
199
+ activeProject = quickProject || deriveProjectName(text, intent.flow);
179
200
  }
180
- else {
181
- console.log("\nNext steps:");
182
- console.log("- Run `sdd-cli route \"<your input>\"` to review the flow.");
183
- console.log("- Run `sdd-cli req create` to draft a requirement.");
201
+ if (!activeProject) {
202
+ console.log("Project name is required to run autopilot.");
203
+ return;
204
+ }
205
+ printWhy(`Using project: ${activeProject}`);
206
+ (0, flags_1.setFlags)({ project: activeProject });
207
+ const draft = buildAutopilotDraft(text, intent.flow, intent.domain);
208
+ draft.project_name = activeProject;
209
+ printStep("Step 3/7", "Creating requirement draft automatically");
210
+ printWhy("This creates your baseline scope, acceptance criteria, and NFRs.");
211
+ const created = await (0, req_create_1.runReqCreate)(draft, { autofill: true });
212
+ if (!created) {
213
+ console.log("Autopilot stopped at requirement creation.");
214
+ return;
215
+ }
216
+ printStep("Step 4/7", `Planning requirement ${created.reqId}`);
217
+ printWhy("I am generating functional, technical, architecture, and test artifacts.");
218
+ const planned = await (0, req_plan_1.runReqPlan)({
219
+ projectName: activeProject,
220
+ reqId: created.reqId,
221
+ autofill: true,
222
+ seedText: text
223
+ });
224
+ if (!planned) {
225
+ console.log("Autopilot stopped at planning.");
226
+ return;
227
+ }
228
+ printStep("Step 5/7", `Preparing implementation plan for ${created.reqId}`);
229
+ printWhy("This stage defines milestones, tasks, quality thresholds, and decisions.");
230
+ const started = await (0, req_start_1.runReqStart)({
231
+ projectName: activeProject,
232
+ reqId: created.reqId,
233
+ autofill: true,
234
+ seedText: text
235
+ });
236
+ if (!started) {
237
+ console.log("Autopilot stopped at start phase.");
238
+ return;
239
+ }
240
+ printStep("Step 6/7", `Updating test plan for ${created.reqId}`);
241
+ printWhy("I am ensuring critical paths, edge cases, and regression tests are documented.");
242
+ const tested = await (0, test_plan_1.runTestPlan)({
243
+ projectName: activeProject,
244
+ reqId: created.reqId,
245
+ autofill: true,
246
+ seedText: text
247
+ });
248
+ if (!tested) {
249
+ console.log("Autopilot stopped at test planning.");
250
+ return;
251
+ }
252
+ printStep("Step 7/7", `Finalizing requirement ${created.reqId}`);
253
+ printWhy("I will move artifacts to done state and generate project-level summary files.");
254
+ const finished = await (0, req_finish_1.runReqFinish)({
255
+ projectName: activeProject,
256
+ reqId: created.reqId,
257
+ autofill: true,
258
+ seedText: text
259
+ });
260
+ if (!finished) {
261
+ console.log("Autopilot stopped at finish phase.");
262
+ return;
184
263
  }
264
+ console.log(`Autopilot completed successfully for ${created.reqId}.`);
265
+ console.log(`Artifacts finalized at: ${finished.doneDir}`);
185
266
  }
186
267
  }
@@ -1 +1,11 @@
1
- export declare function runReqFinish(): Promise<void>;
1
+ export declare function runReqFinish(options?: ReqFinishOptions): Promise<ReqFinishResult | null>;
2
+ export type ReqFinishOptions = {
3
+ projectName?: string;
4
+ reqId?: string;
5
+ autofill?: boolean;
6
+ seedText?: string;
7
+ };
8
+ export type ReqFinishResult = {
9
+ reqId: string;
10
+ doneDir: string;
11
+ };
@@ -22,12 +22,13 @@ function findRequirementDir(projectRoot, reqId) {
22
22
  return inProgress;
23
23
  return null;
24
24
  }
25
- async function runReqFinish() {
26
- const projectName = await (0, prompt_1.askProjectName)();
27
- const reqId = await (0, prompt_1.ask)("Requirement ID (REQ-...): ");
25
+ async function runReqFinish(options) {
26
+ const auto = Boolean(options?.autofill);
27
+ const projectName = options?.projectName ?? (await (0, prompt_1.askProjectName)());
28
+ const reqId = options?.reqId ?? (await (0, prompt_1.ask)("Requirement ID (REQ-...): "));
28
29
  if (!projectName || !reqId) {
29
30
  console.log("Project name and requirement ID are required.");
30
- return;
31
+ return null;
31
32
  }
32
33
  const workspace = (0, index_1.getWorkspaceInfo)();
33
34
  let project;
@@ -36,12 +37,12 @@ async function runReqFinish() {
36
37
  }
37
38
  catch (error) {
38
39
  console.log(error.message);
39
- return;
40
+ return null;
40
41
  }
41
42
  const requirementDir = findRequirementDir(project.root, reqId);
42
43
  if (!requirementDir) {
43
44
  console.log("Requirement not found.");
44
- return;
45
+ return null;
45
46
  }
46
47
  const jsonFiles = fs_1.default.readdirSync(requirementDir).filter((file) => file.endsWith(".json"));
47
48
  const schemaMap = {
@@ -61,13 +62,14 @@ async function runReqFinish() {
61
62
  if (!result.valid) {
62
63
  console.log(`Validation failed for ${file}:`);
63
64
  result.errors.forEach((error) => console.log(`- ${error}`));
64
- return;
65
+ return null;
65
66
  }
66
67
  }
67
- const overview = await (0, prompt_1.ask)("Project overview (for README): ");
68
- const howToRun = await (0, prompt_1.ask)("How to run (for README): ");
69
- const archSummary = await (0, prompt_1.ask)("Architecture summary (for README): ");
70
- const testingNotes = await (0, prompt_1.ask)("Testing notes (for README): ");
68
+ const seed = (options?.seedText ?? "").trim() || "initial scope";
69
+ const overview = auto ? `Project delivery for ${seed}` : await (0, prompt_1.ask)("Project overview (for README): ");
70
+ const howToRun = auto ? "Run CLI commands through sdd-cli flow." : await (0, prompt_1.ask)("How to run (for README): ");
71
+ const archSummary = auto ? "CLI + templates + schema validation architecture." : await (0, prompt_1.ask)("Architecture summary (for README): ");
72
+ const testingNotes = auto ? "Validated with unit and integration CLI tests." : await (0, prompt_1.ask)("Testing notes (for README): ");
71
73
  const readmeTemplate = (0, render_1.loadTemplate)("project-readme");
72
74
  const readmeRendered = (0, render_1.renderTemplate)(readmeTemplate, {
73
75
  project_name: project.name,
@@ -97,7 +99,7 @@ async function runReqFinish() {
97
99
  if (!readmeValidation.valid) {
98
100
  console.log("Project README validation failed:");
99
101
  readmeValidation.errors.forEach((error) => console.log(`- ${error}`));
100
- return;
102
+ return null;
101
103
  }
102
104
  const sourceDir = requirementDir;
103
105
  const sourceStatus = path_1.default.basename(path_1.default.dirname(sourceDir));
@@ -147,7 +149,8 @@ async function runReqFinish() {
147
149
  (0, index_1.updateProjectStatus)(workspace, project.name, sourceStatus);
148
150
  }
149
151
  console.log(`Failed to finish requirement: ${error.message}`);
150
- return;
152
+ return null;
151
153
  }
152
154
  console.log(`Moved requirement to ${doneDir}`);
155
+ return { reqId, doneDir };
153
156
  }
@@ -1 +1,11 @@
1
- export declare function runReqPlan(): Promise<void>;
1
+ export type ReqPlanOptions = {
2
+ projectName?: string;
3
+ reqId?: string;
4
+ autofill?: boolean;
5
+ seedText?: string;
6
+ };
7
+ export type ReqPlanResult = {
8
+ reqId: string;
9
+ targetDir: string;
10
+ };
11
+ export declare function runReqPlan(options?: ReqPlanOptions): Promise<ReqPlanResult | null>;
@@ -22,12 +22,17 @@ function findRequirementDir(projectRoot, reqId) {
22
22
  return wip;
23
23
  return null;
24
24
  }
25
- async function runReqPlan() {
26
- const projectName = await (0, prompt_1.askProjectName)();
27
- const reqId = await (0, prompt_1.ask)("Requirement ID (REQ-...): ");
25
+ function defaultSeed(seedText) {
26
+ const text = (seedText ?? "").trim();
27
+ return text.length > 0 ? text : "first delivery";
28
+ }
29
+ async function runReqPlan(options) {
30
+ const auto = Boolean(options?.autofill);
31
+ const projectName = options?.projectName ?? (await (0, prompt_1.askProjectName)());
32
+ const reqId = options?.reqId ?? (await (0, prompt_1.ask)("Requirement ID (REQ-...): "));
28
33
  if (!projectName || !reqId) {
29
34
  console.log("Project name and requirement ID are required.");
30
- return;
35
+ return null;
31
36
  }
32
37
  const workspace = (0, index_1.getWorkspaceInfo)();
33
38
  let project;
@@ -36,17 +41,17 @@ async function runReqPlan() {
36
41
  }
37
42
  catch (error) {
38
43
  console.log(error.message);
39
- return;
44
+ return null;
40
45
  }
41
46
  let requirementDir = findRequirementDir(project.root, reqId);
42
47
  if (!requirementDir) {
43
48
  console.log("Requirement not found in backlog or wip.");
44
- return;
49
+ return null;
45
50
  }
46
51
  const requirementJsonPath = path_1.default.join(requirementDir, "requirement.json");
47
52
  if (!fs_1.default.existsSync(requirementJsonPath)) {
48
53
  console.log("Missing requirement.json. Run `req create` first.");
49
- return;
54
+ return null;
50
55
  }
51
56
  const requirementJson = JSON.parse(fs_1.default.readFileSync(requirementJsonPath, "utf-8"));
52
57
  let gates = (0, gates_1.checkRequirementGates)(requirementJson);
@@ -54,13 +59,13 @@ async function runReqPlan() {
54
59
  console.log("Requirement gates failed. Please update the requirement first:");
55
60
  gates.missing.forEach((field) => console.log(`- ${field}`));
56
61
  console.log("Run `sdd-cli req refine` to complete missing fields.");
57
- return;
62
+ return null;
58
63
  }
59
64
  const requirementValidation = (0, validate_1.validateJson)("requirement.schema.json", requirementJson);
60
65
  if (!requirementValidation.valid) {
61
66
  console.log("Requirement validation failed:");
62
67
  requirementValidation.errors.forEach((error) => console.log(`- ${error}`));
63
- return;
68
+ return null;
64
69
  }
65
70
  const wipDir = path_1.default.join(project.root, "requirements", "wip", reqId);
66
71
  if (requirementDir.includes(path_1.default.join("requirements", "backlog"))) {
@@ -75,32 +80,33 @@ async function runReqPlan() {
75
80
  }
76
81
  requirementJson.updatedAt = new Date().toISOString();
77
82
  fs_1.default.writeFileSync(path_1.default.join(targetDir, "requirement.json"), JSON.stringify(requirementJson, null, 2), "utf-8");
78
- const overview = await (0, prompt_1.ask)("Functional overview: ");
79
- const actors = await (0, prompt_1.ask)("Actors - comma separated: ");
80
- const useCases = await (0, prompt_1.ask)("Use cases - comma separated: ");
81
- const flows = await (0, prompt_1.ask)("Flows - comma separated: ");
82
- const rules = await (0, prompt_1.ask)("Business rules - comma separated: ");
83
- const errors = await (0, prompt_1.ask)("Errors - comma separated: ");
84
- const acceptance = await (0, prompt_1.ask)("Acceptance criteria - comma separated: ");
85
- const stack = await (0, prompt_1.ask)("Tech stack - comma separated: ");
86
- const interfaces = await (0, prompt_1.ask)("Interfaces - comma separated: ");
87
- const dataModel = await (0, prompt_1.ask)("Data model - comma separated: ");
88
- const security = await (0, prompt_1.ask)("Security - comma separated: ");
89
- const techErrors = await (0, prompt_1.ask)("Error handling - comma separated: ");
90
- const performance = await (0, prompt_1.ask)("Performance - comma separated: ");
91
- const observability = await (0, prompt_1.ask)("Observability - comma separated: ");
92
- const context = await (0, prompt_1.ask)("Architecture context: ");
93
- const containers = await (0, prompt_1.ask)("Containers - comma separated: ");
94
- const components = await (0, prompt_1.ask)("Components - comma separated: ");
95
- const deployment = await (0, prompt_1.ask)("Deployment - comma separated: ");
96
- const diagrams = await (0, prompt_1.ask)("Diagrams - comma separated: ");
97
- const criticalPaths = await (0, prompt_1.ask)("Test critical paths - comma separated: ");
98
- const edgeCases = await (0, prompt_1.ask)("Test edge cases - comma separated: ");
99
- const acceptanceTests = await (0, prompt_1.ask)("Acceptance tests - comma separated: ");
100
- const regressions = await (0, prompt_1.ask)("Regression tests - comma separated: ");
101
- const coverageTarget = await (0, prompt_1.ask)("Coverage target: ");
83
+ const seed = defaultSeed(options?.seedText ?? requirementJson.objective);
84
+ const overview = auto ? `Functional overview for ${seed}` : await (0, prompt_1.ask)("Functional overview: ");
85
+ const actors = auto ? "user, system" : await (0, prompt_1.ask)("Actors - comma separated: ");
86
+ const useCases = auto ? `capture need for ${seed}, deliver first iteration` : await (0, prompt_1.ask)("Use cases - comma separated: ");
87
+ const flows = auto ? "discover, plan, implement, validate" : await (0, prompt_1.ask)("Flows - comma separated: ");
88
+ const rules = auto ? "maintain traceability, validate artifacts" : await (0, prompt_1.ask)("Business rules - comma separated: ");
89
+ const errors = auto ? "invalid input, missing artifact" : await (0, prompt_1.ask)("Errors - comma separated: ");
90
+ const acceptance = auto ? "artifacts generated, schemas valid" : await (0, prompt_1.ask)("Acceptance criteria - comma separated: ");
91
+ const stack = auto ? "node, typescript" : await (0, prompt_1.ask)("Tech stack - comma separated: ");
92
+ const interfaces = auto ? "cli commands, markdown artifacts" : await (0, prompt_1.ask)("Interfaces - comma separated: ");
93
+ const dataModel = auto ? "requirement json, spec json" : await (0, prompt_1.ask)("Data model - comma separated: ");
94
+ const security = auto ? "safe defaults, input validation" : await (0, prompt_1.ask)("Security - comma separated: ");
95
+ const techErrors = auto ? "clear cli errors, retry guidance" : await (0, prompt_1.ask)("Error handling - comma separated: ");
96
+ const performance = auto ? "fast local generation" : await (0, prompt_1.ask)("Performance - comma separated: ");
97
+ const observability = auto ? "progress logs, changelog entries" : await (0, prompt_1.ask)("Observability - comma separated: ");
98
+ const context = auto ? "CLI orchestrator with schema validation" : await (0, prompt_1.ask)("Architecture context: ");
99
+ const containers = auto ? "cli runtime, workspace files" : await (0, prompt_1.ask)("Containers - comma separated: ");
100
+ const components = auto ? "router, generators, validators" : await (0, prompt_1.ask)("Components - comma separated: ");
101
+ const deployment = auto ? "local workstation" : await (0, prompt_1.ask)("Deployment - comma separated: ");
102
+ const diagrams = auto ? "context.mmd, container.mmd" : await (0, prompt_1.ask)("Diagrams - comma separated: ");
103
+ const criticalPaths = auto ? "hello to requirement, requirement to plan" : await (0, prompt_1.ask)("Test critical paths - comma separated: ");
104
+ const edgeCases = auto ? "missing fields, invalid schema" : await (0, prompt_1.ask)("Test edge cases - comma separated: ");
105
+ const acceptanceTests = auto ? "generate and validate complete bundle" : await (0, prompt_1.ask)("Acceptance tests - comma separated: ");
106
+ const regressions = auto ? "flags behavior, template loading" : await (0, prompt_1.ask)("Regression tests - comma separated: ");
107
+ const coverageTarget = auto ? "80%" : await (0, prompt_1.ask)("Coverage target: ");
102
108
  const flags = (0, flags_1.getFlags)();
103
- const improveNote = flags.improve ? await (0, prompt_1.ask)("Improve focus (optional): ") : "";
109
+ const improveNote = flags.improve && !auto ? await (0, prompt_1.ask)("Improve focus (optional): ") : "";
104
110
  const functionalJson = {
105
111
  overview: overview || "N/A",
106
112
  actors: (0, list_1.parseList)(actors),
@@ -143,9 +149,8 @@ async function runReqPlan() {
143
149
  if (failures.length > 0) {
144
150
  console.log("Spec validation failed:");
145
151
  failures.forEach((error) => console.log(`- ${error}`));
146
- return;
152
+ return null;
147
153
  }
148
- console.log("Spec validation passed.");
149
154
  const functionalTemplate = (0, render_1.loadTemplate)("functional-spec");
150
155
  const technicalTemplate = (0, render_1.loadTemplate)("technical-spec");
151
156
  const architectureTemplate = (0, render_1.loadTemplate)("architecture");
@@ -219,4 +224,5 @@ async function runReqPlan() {
219
224
  const changeEntry = `\n- ${new Date().toISOString()} planned requirement ${reqId}\n`;
220
225
  fs_1.default.appendFileSync(changelog, changeEntry, "utf-8");
221
226
  console.log(`Generated specs in ${targetDir}`);
227
+ return { reqId, targetDir };
222
228
  }
@@ -1 +1,11 @@
1
- export declare function runReqStart(): Promise<void>;
1
+ export type ReqStartOptions = {
2
+ projectName?: string;
3
+ reqId?: string;
4
+ autofill?: boolean;
5
+ seedText?: string;
6
+ };
7
+ export type ReqStartResult = {
8
+ reqId: string;
9
+ targetDir: string;
10
+ };
11
+ export declare function runReqStart(options?: ReqStartOptions): Promise<ReqStartResult | null>;
@@ -24,12 +24,17 @@ function findRequirementDir(projectRoot, reqId) {
24
24
  return inProgress;
25
25
  return null;
26
26
  }
27
- async function runReqStart() {
28
- const projectName = await (0, prompt_1.askProjectName)();
29
- const reqId = await (0, prompt_1.ask)("Requirement ID (REQ-...): ");
27
+ function defaultSeed(seedText) {
28
+ const text = (seedText ?? "").trim();
29
+ return text.length > 0 ? text : "initial delivery";
30
+ }
31
+ async function runReqStart(options) {
32
+ const auto = Boolean(options?.autofill);
33
+ const projectName = options?.projectName ?? (await (0, prompt_1.askProjectName)());
34
+ const reqId = options?.reqId ?? (await (0, prompt_1.ask)("Requirement ID (REQ-...): "));
30
35
  if (!projectName || !reqId) {
31
36
  console.log("Project name and requirement ID are required.");
32
- return;
37
+ return null;
33
38
  }
34
39
  const workspace = (0, index_1.getWorkspaceInfo)();
35
40
  let project;
@@ -38,12 +43,12 @@ async function runReqStart() {
38
43
  }
39
44
  catch (error) {
40
45
  console.log(error.message);
41
- return;
46
+ return null;
42
47
  }
43
48
  let requirementDir = findRequirementDir(project.root, reqId);
44
49
  if (!requirementDir) {
45
50
  console.log("Requirement not found.");
46
- return;
51
+ return null;
47
52
  }
48
53
  const requirementPath = requirementDir;
49
54
  const requiredSpecs = [
@@ -56,7 +61,7 @@ async function runReqStart() {
56
61
  if (missing.length > 0) {
57
62
  console.log("Cannot start. Missing specs:");
58
63
  missing.forEach((spec) => console.log(`- ${spec.file}`));
59
- return;
64
+ return null;
60
65
  }
61
66
  for (const spec of requiredSpecs) {
62
67
  const data = JSON.parse(fs_1.default.readFileSync(path_1.default.join(requirementPath, spec.file), "utf-8"));
@@ -64,7 +69,7 @@ async function runReqStart() {
64
69
  if (!result.valid) {
65
70
  console.log(`Spec validation failed for ${spec.file}:`);
66
71
  result.errors.forEach((error) => console.log(`- ${error}`));
67
- return;
72
+ return null;
68
73
  }
69
74
  }
70
75
  const inProgressDir = path_1.default.join(project.root, "requirements", "in-progress", reqId);
@@ -82,12 +87,13 @@ async function runReqStart() {
82
87
  requirementJson.updatedAt = new Date().toISOString();
83
88
  fs_1.default.writeFileSync(requirementJsonPath, JSON.stringify(requirementJson, null, 2), "utf-8");
84
89
  }
85
- const milestones = await (0, prompt_1.ask)("Milestones - comma separated: ");
86
- const tasks = await (0, prompt_1.ask)("Tasks - comma separated: ");
87
- const dependencies = await (0, prompt_1.ask)("Dependencies - comma separated: ");
88
- const risks = await (0, prompt_1.ask)("Risks - comma separated: ");
90
+ const seed = defaultSeed(options?.seedText);
91
+ const milestones = auto ? `milestone for ${seed}` : await (0, prompt_1.ask)("Milestones - comma separated: ");
92
+ const tasks = auto ? "implement core flow, validate outputs" : await (0, prompt_1.ask)("Tasks - comma separated: ");
93
+ const dependencies = auto ? "node runtime, templates, schemas" : await (0, prompt_1.ask)("Dependencies - comma separated: ");
94
+ const risks = auto ? "scope drift, missing validation" : await (0, prompt_1.ask)("Risks - comma separated: ");
89
95
  const flags = (0, flags_1.getFlags)();
90
- const improveNote = flags.improve ? await (0, prompt_1.ask)("Improve focus (optional): ") : "";
96
+ const improveNote = flags.improve && !auto ? await (0, prompt_1.ask)("Improve focus (optional): ") : "";
91
97
  const implementationTemplate = (0, render_1.loadTemplate)("implementation-plan");
92
98
  const rendered = (0, render_1.renderTemplate)(implementationTemplate, {
93
99
  title: project.name,
@@ -110,7 +116,7 @@ async function runReqStart() {
110
116
  if (!validation.valid) {
111
117
  console.log("Quality validation failed:");
112
118
  validation.errors.forEach((error) => console.log(`- ${error}`));
113
- return;
119
+ return null;
114
120
  }
115
121
  fs_1.default.writeFileSync(path_1.default.join(targetDir, "implementation-plan.md"), rendered, "utf-8");
116
122
  fs_1.default.writeFileSync(path_1.default.join(targetDir, "quality.json"), JSON.stringify(qualityJson, null, 2), "utf-8");
@@ -145,4 +151,5 @@ async function runReqStart() {
145
151
  fs_1.default.appendFileSync(changelog, changeEntry, "utf-8");
146
152
  console.log(`Implementation plan generated in ${targetDir}`);
147
153
  console.log(`Status updated to in-progress for ${project.name}`);
154
+ return { reqId, targetDir };
148
155
  }
@@ -1 +1,11 @@
1
- export declare function runTestPlan(): Promise<void>;
1
+ export type TestPlanOptions = {
2
+ projectName?: string;
3
+ reqId?: string;
4
+ autofill?: boolean;
5
+ seedText?: string;
6
+ };
7
+ export type TestPlanResult = {
8
+ reqId: string;
9
+ requirementDir: string;
10
+ };
11
+ export declare function runTestPlan(options?: TestPlanOptions): Promise<TestPlanResult | null>;
@@ -23,12 +23,17 @@ function findRequirementDir(projectRoot, reqId) {
23
23
  }
24
24
  return null;
25
25
  }
26
- async function runTestPlan() {
27
- const projectName = await (0, prompt_1.askProjectName)();
28
- const reqId = await (0, prompt_1.ask)("Requirement ID (REQ-...): ");
26
+ function defaultSeed(seedText) {
27
+ const text = (seedText ?? "").trim();
28
+ return text.length > 0 ? text : "initial scope";
29
+ }
30
+ async function runTestPlan(options) {
31
+ const auto = Boolean(options?.autofill);
32
+ const projectName = options?.projectName ?? (await (0, prompt_1.askProjectName)());
33
+ const reqId = options?.reqId ?? (await (0, prompt_1.ask)("Requirement ID (REQ-...): "));
29
34
  if (!projectName || !reqId) {
30
35
  console.log("Project name and requirement ID are required.");
31
- return;
36
+ return null;
32
37
  }
33
38
  const workspace = (0, index_1.getWorkspaceInfo)();
34
39
  let project;
@@ -37,20 +42,21 @@ async function runTestPlan() {
37
42
  }
38
43
  catch (error) {
39
44
  console.log(error.message);
40
- return;
45
+ return null;
41
46
  }
42
47
  const requirementDir = findRequirementDir(project.root, reqId);
43
48
  if (!requirementDir) {
44
49
  console.log("Requirement not found.");
45
- return;
50
+ return null;
46
51
  }
47
- const criticalPaths = await (0, prompt_1.ask)("Test critical paths - comma separated: ");
48
- const edgeCases = await (0, prompt_1.ask)("Test edge cases - comma separated: ");
49
- const acceptanceTests = await (0, prompt_1.ask)("Acceptance tests - comma separated: ");
50
- const regressions = await (0, prompt_1.ask)("Regression tests - comma separated: ");
51
- const coverageTarget = await (0, prompt_1.ask)("Coverage target: ");
52
+ const seed = defaultSeed(options?.seedText);
53
+ const criticalPaths = auto ? `core path for ${seed}` : await (0, prompt_1.ask)("Test critical paths - comma separated: ");
54
+ const edgeCases = auto ? "invalid data, missing inputs" : await (0, prompt_1.ask)("Test edge cases - comma separated: ");
55
+ const acceptanceTests = auto ? "happy path end-to-end generation" : await (0, prompt_1.ask)("Acceptance tests - comma separated: ");
56
+ const regressions = auto ? "existing command behavior remains valid" : await (0, prompt_1.ask)("Regression tests - comma separated: ");
57
+ const coverageTarget = auto ? "80%" : await (0, prompt_1.ask)("Coverage target: ");
52
58
  const flags = (0, flags_1.getFlags)();
53
- const improveNote = flags.improve ? await (0, prompt_1.ask)("Improve focus (optional): ") : "";
59
+ const improveNote = flags.improve && !auto ? await (0, prompt_1.ask)("Improve focus (optional): ") : "";
54
60
  const testPlanJson = {
55
61
  criticalPaths: (0, list_1.parseList)(criticalPaths),
56
62
  edgeCases: (0, list_1.parseList)(edgeCases),
@@ -62,7 +68,7 @@ async function runTestPlan() {
62
68
  if (!validation.valid) {
63
69
  console.log("Test plan validation failed:");
64
70
  validation.errors.forEach((error) => console.log(`- ${error}`));
65
- return;
71
+ return null;
66
72
  }
67
73
  const template = (0, render_1.loadTemplate)("test-plan");
68
74
  const rendered = (0, render_1.renderTemplate)(template, {
@@ -86,4 +92,5 @@ async function runTestPlan() {
86
92
  fs_1.default.appendFileSync(progressLog, improveEntry, "utf-8");
87
93
  }
88
94
  console.log(`Test plan updated in ${requirementDir}`);
95
+ return { reqId, requirementDir };
89
96
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sdd-cli",
3
- "version": "0.1.8",
3
+ "version": "0.1.10",
4
4
  "description": "SDD-first, AI-native CLI for end-to-end delivery.",
5
5
  "homepage": "https://github.com/jdsalasca/sdd-tool#readme",
6
6
  "repository": {