sdd-cli 0.1.12 → 0.1.14

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 CHANGED
@@ -119,6 +119,7 @@ Project names must use letters, numbers, spaces, `-` or `_`, and cannot include
119
119
 
120
120
  The `hello` command is the entry point: it connects to AI, lists active projects, and offers to create a new one or continue.
121
121
  Default behavior is now a guided autopilot from discovery to completion with minimal prompts.
122
+ When you pass direct intent text (`sdd-cli hello "..."`), hello uses auto-guided defaults and minimizes confirmations.
122
123
  Use `--questions` when you want the manual question-by-question flow.
123
124
 
124
125
  ## The happy path (end-to-end flow)
@@ -203,6 +204,17 @@ sdd-cli hello "I want a simple booking system for appointments"
203
204
  5) Check output in:
204
205
  `<workspace>/<project>/requirements/done/<REQ-ID>/`
205
206
 
207
+ ## Recovery quick commands
208
+
209
+ - Continue an existing project:
210
+ `sdd-cli --project <project-name> hello "continue"`
211
+ - Resume from a specific stage:
212
+ `sdd-cli --project <project-name> --from-step test hello "resume"`
213
+ - Script-safe full default run:
214
+ `sdd-cli --non-interactive hello "<your intent>"`
215
+ - Preview autopilot steps without writing files:
216
+ `sdd-cli --dry-run hello "<your intent>"`
217
+
206
218
  ## Where files are stored (clean repos)
207
219
 
208
220
  By default, the tool writes to a dedicated workspace, not into your repo:
package/dist/cli.js CHANGED
@@ -66,6 +66,7 @@ program
66
66
  .option("--improve", "Trigger self-audit and regenerate")
67
67
  .option("--parallel", "Generate in parallel when supported")
68
68
  .option("--non-interactive", "Run with defaults and without prompt confirmations")
69
+ .option("--dry-run", "Preview autopilot steps without writing artifacts")
69
70
  .option("--from-step <step>", "Resume or start autopilot from step: create|plan|start|test|finish")
70
71
  .option("--project <name>", "Select or name the project")
71
72
  .option("--output <path>", "Override workspace output root");
@@ -76,6 +77,7 @@ program.hook("preAction", (thisCommand, actionCommand) => {
76
77
  improve: Boolean(opts.improve),
77
78
  parallel: Boolean(opts.parallel),
78
79
  nonInteractive: Boolean(opts.nonInteractive),
80
+ dryRun: Boolean(opts.dryRun),
79
81
  fromStep: typeof opts.fromStep === "string" ? opts.fromStep : undefined,
80
82
  project: typeof opts.project === "string" ? opts.project : undefined,
81
83
  output: typeof opts.output === "string" ? opts.output : undefined
@@ -20,6 +20,9 @@ function printStep(step, description) {
20
20
  function printWhy(message) {
21
21
  console.log(` -> ${message}`);
22
22
  }
23
+ function printRecoveryNext(project, step, hint) {
24
+ console.log(`Next command: sdd-cli --project "${project}" --from-step ${step} hello "${hint}"`);
25
+ }
23
26
  function deriveProjectName(input, flow) {
24
27
  const seed = input
25
28
  .trim()
@@ -99,35 +102,39 @@ async function runHello(input, runQuestions) {
99
102
  return { workspace, projects };
100
103
  }
101
104
  let { workspace, projects } = loadWorkspace();
105
+ const runtimeFlags = (0, flags_1.getFlags)();
106
+ const hasDirectIntent = input.trim().length > 0;
107
+ const shouldRunQuestions = runQuestions === true;
108
+ const autoGuidedMode = !shouldRunQuestions && (runtimeFlags.nonInteractive || hasDirectIntent);
109
+ const dryRun = runtimeFlags.dryRun;
102
110
  console.log("Hello from sdd-cli.");
103
111
  console.log(`Workspace: ${workspace.root}`);
104
- const useWorkspace = await (0, prompt_1.confirm)("Use this workspace path? (y/n) ");
105
- if (!useWorkspace) {
106
- const nextPath = await (0, prompt_1.ask)("Workspace path to use (blank to exit): ");
107
- if (!nextPath) {
108
- console.log("Run again from the desired folder or pass --output <path>.");
109
- return;
112
+ if (autoGuidedMode) {
113
+ printWhy("Auto-guided mode active: using current workspace defaults.");
114
+ }
115
+ else {
116
+ const useWorkspace = await (0, prompt_1.confirm)("Use this workspace path? (y/n) ");
117
+ if (!useWorkspace) {
118
+ const nextPath = await (0, prompt_1.ask)("Workspace path to use (blank to exit): ");
119
+ if (!nextPath) {
120
+ console.log("Run again from the desired folder or pass --output <path>.");
121
+ return;
122
+ }
123
+ (0, flags_1.setFlags)({ output: nextPath });
124
+ const reloaded = loadWorkspace();
125
+ workspace = reloaded.workspace;
126
+ projects = reloaded.projects;
127
+ console.log(`Workspace updated: ${workspace.root}`);
110
128
  }
111
- (0, flags_1.setFlags)({ output: nextPath });
112
- const reloaded = loadWorkspace();
113
- workspace = reloaded.workspace;
114
- projects = reloaded.projects;
115
- console.log(`Workspace updated: ${workspace.root}`);
116
129
  }
117
- const runtimeFlags = (0, flags_1.getFlags)();
118
130
  if (projects.length > 0) {
119
131
  console.log("Active projects:");
120
132
  projects.forEach((project) => {
121
133
  console.log(`- ${project.name} (${project.status})`);
122
134
  });
123
- const choice = await (0, prompt_1.ask)("Start new or continue? (new/continue) ");
124
- const normalized = choice.trim().toLowerCase();
125
- if (normalized === "continue") {
126
- const selected = runtimeFlags.project || (await (0, prompt_1.ask)("Project to continue: "));
127
- if (!selected) {
128
- console.log("No project selected. Continuing with new flow.");
129
- }
130
- else if (!projects.find((project) => project.name === selected)) {
135
+ if (runtimeFlags.project) {
136
+ const selected = runtimeFlags.project.trim();
137
+ if (!projects.find((project) => project.name === selected)) {
131
138
  console.log(`Project not found: ${selected}. Continuing with new flow.`);
132
139
  }
133
140
  else {
@@ -135,15 +142,34 @@ async function runHello(input, runQuestions) {
135
142
  console.log(`Continuing: ${selected}`);
136
143
  }
137
144
  }
145
+ else if (!autoGuidedMode) {
146
+ const choice = await (0, prompt_1.ask)("Start new or continue? (new/continue) ");
147
+ const normalized = choice.trim().toLowerCase();
148
+ if (normalized === "continue") {
149
+ const selected = await (0, prompt_1.ask)("Project to continue: ");
150
+ if (!selected) {
151
+ console.log("No project selected. Continuing with new flow.");
152
+ }
153
+ else if (!projects.find((project) => project.name === selected)) {
154
+ console.log(`Project not found: ${selected}. Continuing with new flow.`);
155
+ }
156
+ else {
157
+ (0, flags_1.setFlags)({ project: selected });
158
+ console.log(`Continuing: ${selected}`);
159
+ }
160
+ }
161
+ else {
162
+ console.log(`Selected: ${choice || "new"}`);
163
+ }
164
+ }
138
165
  else {
139
- console.log(`Selected: ${choice || "new"}`);
166
+ console.log("Auto-selected: new flow.");
140
167
  }
141
168
  }
142
169
  else {
143
170
  console.log("No active projects found.");
144
171
  }
145
172
  let text = input || (await (0, prompt_1.ask)("Describe what you want to do: "));
146
- const shouldRunQuestions = runQuestions === true;
147
173
  let checkpoint = null;
148
174
  let fromStep = (0, autopilot_checkpoint_1.normalizeStep)(runtimeFlags.fromStep);
149
175
  let activeProjectForCheckpoint = runtimeFlags.project;
@@ -211,8 +237,13 @@ async function runHello(input, runQuestions) {
211
237
  else {
212
238
  let activeProject = (0, flags_1.getFlags)().project;
213
239
  if (!activeProject) {
214
- const quickProject = await (0, prompt_1.ask)("Project name (optional, press Enter to auto-generate): ");
215
- activeProject = quickProject || deriveProjectName(text, intent.flow);
240
+ if (autoGuidedMode) {
241
+ activeProject = deriveProjectName(text, intent.flow);
242
+ }
243
+ else {
244
+ const quickProject = await (0, prompt_1.ask)("Project name (optional, press Enter to auto-generate): ");
245
+ activeProject = quickProject || deriveProjectName(text, intent.flow);
246
+ }
216
247
  }
217
248
  if (!activeProject) {
218
249
  console.log("Project name is required to run autopilot.");
@@ -237,12 +268,22 @@ async function runHello(input, runQuestions) {
237
268
  const startStep = fromStep ?? "create";
238
269
  if (startStep !== "create" && !reqId) {
239
270
  console.log("No checkpoint found for resume. Run full autopilot first or use --from-step create.");
271
+ printRecoveryNext(activeProject, "create", text);
240
272
  return;
241
273
  }
242
274
  if (fromStep) {
243
275
  printWhy(`Resuming autopilot from step: ${fromStep}`);
244
276
  }
245
277
  const stepIndex = autopilot_checkpoint_1.AUTOPILOT_STEPS.indexOf(startStep);
278
+ if (dryRun) {
279
+ printWhy("Dry run active: previewing autopilot plan without writing files.");
280
+ for (let i = stepIndex; i < autopilot_checkpoint_1.AUTOPILOT_STEPS.length; i += 1) {
281
+ const step = autopilot_checkpoint_1.AUTOPILOT_STEPS[i];
282
+ console.log(`Would run step: ${step}`);
283
+ }
284
+ console.log(`To execute for real: sdd-cli --project "${activeProject}" hello "${text}"`);
285
+ return;
286
+ }
246
287
  for (let i = stepIndex; i < autopilot_checkpoint_1.AUTOPILOT_STEPS.length; i += 1) {
247
288
  const step = autopilot_checkpoint_1.AUTOPILOT_STEPS[i];
248
289
  if (step === "create") {
@@ -251,6 +292,7 @@ async function runHello(input, runQuestions) {
251
292
  const created = await (0, req_create_1.runReqCreate)(draft, { autofill: true });
252
293
  if (!created) {
253
294
  console.log("Autopilot stopped at requirement creation.");
295
+ printRecoveryNext(activeProject, "create", text);
254
296
  return;
255
297
  }
256
298
  reqId = created.reqId;
@@ -266,6 +308,7 @@ async function runHello(input, runQuestions) {
266
308
  });
267
309
  if (!planned) {
268
310
  console.log("Autopilot stopped at planning.");
311
+ printRecoveryNext(activeProject, "plan", text);
269
312
  return;
270
313
  }
271
314
  }
@@ -280,6 +323,7 @@ async function runHello(input, runQuestions) {
280
323
  });
281
324
  if (!started) {
282
325
  console.log("Autopilot stopped at start phase.");
326
+ printRecoveryNext(activeProject, "start", text);
283
327
  return;
284
328
  }
285
329
  }
@@ -294,6 +338,7 @@ async function runHello(input, runQuestions) {
294
338
  });
295
339
  if (!tested) {
296
340
  console.log("Autopilot stopped at test planning.");
341
+ printRecoveryNext(activeProject, "test", text);
297
342
  return;
298
343
  }
299
344
  }
@@ -308,6 +353,7 @@ async function runHello(input, runQuestions) {
308
353
  });
309
354
  if (!finished) {
310
355
  console.log("Autopilot stopped at finish phase.");
356
+ printRecoveryNext(activeProject, "finish", text);
311
357
  return;
312
358
  }
313
359
  (0, autopilot_checkpoint_1.clearCheckpoint)(activeProject);
@@ -3,6 +3,7 @@ export type RuntimeFlags = {
3
3
  improve: boolean;
4
4
  parallel: boolean;
5
5
  nonInteractive: boolean;
6
+ dryRun: boolean;
6
7
  fromStep?: string;
7
8
  project?: string;
8
9
  output?: string;
@@ -7,6 +7,7 @@ const flags = {
7
7
  improve: false,
8
8
  parallel: false,
9
9
  nonInteractive: false,
10
+ dryRun: false,
10
11
  fromStep: undefined,
11
12
  project: undefined,
12
13
  output: undefined
@@ -24,6 +25,9 @@ function setFlags(next) {
24
25
  if ("nonInteractive" in next) {
25
26
  flags.nonInteractive = Boolean(next.nonInteractive);
26
27
  }
28
+ if ("dryRun" in next) {
29
+ flags.dryRun = Boolean(next.dryRun);
30
+ }
27
31
  if ("fromStep" in next) {
28
32
  flags.fromStep = typeof next.fromStep === "string" ? next.fromStep : undefined;
29
33
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sdd-cli",
3
- "version": "0.1.12",
3
+ "version": "0.1.14",
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": {