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 +12 -0
- package/dist/cli.js +2 -0
- package/dist/commands/hello.js +70 -24
- package/dist/context/flags.d.ts +1 -0
- package/dist/context/flags.js +4 -0
- package/package.json +1 -1
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
|
package/dist/commands/hello.js
CHANGED
|
@@ -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
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
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
|
-
|
|
124
|
-
|
|
125
|
-
|
|
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(
|
|
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
|
-
|
|
215
|
-
|
|
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);
|
package/dist/context/flags.d.ts
CHANGED
package/dist/context/flags.js
CHANGED
|
@@ -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
|
}
|