sdd-cli 0.1.15 → 0.1.17

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
@@ -112,6 +112,10 @@ Then:
112
112
  ```
113
113
  sdd-cli hello
114
114
  ```
115
+ Or run a zero-friction demo:
116
+ ```
117
+ sdd-cli quickstart --example saas
118
+ ```
115
119
 
116
120
  Package name on npm is `sdd-cli` (CLI commands remain `sdd-cli` and `sdd`).
117
121
 
@@ -149,8 +153,10 @@ Use `--questions` when you want the manual question-by-question flow.
149
153
 
150
154
  ### Core
151
155
  - `sdd-cli hello` -- interactive session, project picker, full guided flow
156
+ - `sdd-cli quickstart` -- one-command demo flow with built-in examples
152
157
  - `sdd-cli init` -- create SDD workspace and config
153
158
  - `sdd-cli list` -- list flows, router flows, templates, prompt packs, and projects
159
+ - `sdd-cli status --next` -- show current project state and exact next command
154
160
  - `sdd-cli doctor` -- validate completeness and consistency
155
161
 
156
162
  ### Router
@@ -187,6 +193,9 @@ Use `--questions` when you want the manual question-by-question flow.
187
193
  - `--parallel` -- generate in parallel
188
194
  - `--questions` -- use manual question-driven discovery flow
189
195
  - `--non-interactive` -- run without confirmations (script/CI friendly)
196
+ - `--beginner` -- show extra step-by-step explanations during hello autopilot
197
+ - `--dry-run` -- preview autopilot stages without writing artifacts
198
+ - `--from-step` -- resume autopilot from `create|plan|start|test|finish`
190
199
  - `--alias sdd` -- optional alias to run as `sdd`
191
200
 
192
201
  ## Beginner quickstart
@@ -215,6 +224,11 @@ sdd-cli hello "I want a simple booking system for appointments"
215
224
  - Preview autopilot steps without writing files:
216
225
  `sdd-cli --dry-run hello "<your intent>"`
217
226
 
227
+ ## Execution tracking
228
+
229
+ - Adoption execution tracker: `AGENTS.md`
230
+ - 90-day roadmap: `docs/ADOPTION_ROADMAP_90D.md`
231
+
218
232
  ## Where files are stored (clean repos)
219
233
 
220
234
  By default, the tool writes to a dedicated workspace, not into your repo:
package/dist/cli.js CHANGED
@@ -44,6 +44,8 @@ const hello_1 = require("./commands/hello");
44
44
  const init_1 = require("./commands/init");
45
45
  const route_1 = require("./commands/route");
46
46
  const doctor_1 = require("./commands/doctor");
47
+ const quickstart_1 = require("./commands/quickstart");
48
+ const status_1 = require("./commands/status");
47
49
  const paths_1 = require("./paths");
48
50
  const flags_1 = require("./context/flags");
49
51
  const prompt_1 = require("./ui/prompt");
@@ -67,6 +69,7 @@ program
67
69
  .option("--parallel", "Generate in parallel when supported")
68
70
  .option("--non-interactive", "Run with defaults and without prompt confirmations")
69
71
  .option("--dry-run", "Preview autopilot steps without writing artifacts")
72
+ .option("--beginner", "Enable extra step-by-step guidance in hello flow")
70
73
  .option("--from-step <step>", "Resume or start autopilot from step: create|plan|start|test|finish")
71
74
  .option("--project <name>", "Select or name the project")
72
75
  .option("--output <path>", "Override workspace output root");
@@ -78,6 +81,7 @@ program.hook("preAction", (thisCommand, actionCommand) => {
78
81
  parallel: Boolean(opts.parallel),
79
82
  nonInteractive: Boolean(opts.nonInteractive),
80
83
  dryRun: Boolean(opts.dryRun),
84
+ beginner: Boolean(opts.beginner),
81
85
  fromStep: typeof opts.fromStep === "string" ? opts.fromStep : undefined,
82
86
  project: typeof opts.project === "string" ? opts.project : undefined,
83
87
  output: typeof opts.output === "string" ? opts.output : undefined
@@ -97,6 +101,12 @@ program
97
101
  .command("init")
98
102
  .description("Initialize workspace and config")
99
103
  .action(() => (0, init_1.runInit)());
104
+ program
105
+ .command("quickstart")
106
+ .description("Run a zero-friction autopilot demo flow")
107
+ .option("--example <name>", "Example prompt: saas|bugfix|api|ecommerce|mobile")
108
+ .option("--list-examples", "List available example prompts")
109
+ .action((options) => (0, quickstart_1.runQuickstart)(options.example, options.listExamples));
100
110
  program
101
111
  .command("list")
102
112
  .description("List flows, templates, and projects")
@@ -104,6 +114,11 @@ program
104
114
  const { runList } = await Promise.resolve().then(() => __importStar(require("./commands/list")));
105
115
  runList();
106
116
  });
117
+ program
118
+ .command("status")
119
+ .description("Show project requirement counts and next recommended command")
120
+ .option("--next", "Print exact next command to run")
121
+ .action((options) => (0, status_1.runStatus)(Boolean(options.next)));
107
122
  const req = program.command("req").description("Requirement lifecycle commands");
108
123
  req
109
124
  .command("create")
@@ -23,6 +23,12 @@ function printWhy(message) {
23
23
  function printRecoveryNext(project, step, hint) {
24
24
  console.log(`Next command: sdd-cli --project "${project}" --from-step ${step} hello "${hint}"`);
25
25
  }
26
+ function printBeginnerTip(enabled, tip) {
27
+ if (!enabled) {
28
+ return;
29
+ }
30
+ console.log(` [Beginner] ${tip}`);
31
+ }
26
32
  function deriveProjectName(input, flow) {
27
33
  const seed = input
28
34
  .trim()
@@ -107,8 +113,12 @@ async function runHello(input, runQuestions) {
107
113
  const shouldRunQuestions = runQuestions === true;
108
114
  const autoGuidedMode = !shouldRunQuestions && (runtimeFlags.nonInteractive || hasDirectIntent);
109
115
  const dryRun = runtimeFlags.dryRun;
116
+ const beginnerMode = runtimeFlags.beginner;
110
117
  console.log("Hello from sdd-cli.");
111
118
  console.log(`Workspace: ${workspace.root}`);
119
+ if (beginnerMode) {
120
+ printBeginnerTip(true, "I will explain each step and tell you what happens next.");
121
+ }
112
122
  if (autoGuidedMode) {
113
123
  printWhy("Auto-guided mode active: using current workspace defaults.");
114
124
  }
@@ -193,6 +203,7 @@ async function runHello(input, runQuestions) {
193
203
  console.log(`Detected intent: ${intent.intent} -> ${intent.flow}`);
194
204
  printStep("Step 1/7", "Intent detected");
195
205
  printWhy("I classified your goal and selected the best starting flow.");
206
+ printBeginnerTip(beginnerMode, "Intent helps me pick the right workflow and defaults.");
196
207
  const showRoute = runQuestions === true ? await (0, prompt_1.confirm)("View route details now? (y/n) ") : false;
197
208
  if (showRoute && runQuestions === true) {
198
209
  (0, route_1.runRoute)(text);
@@ -202,6 +213,7 @@ async function runHello(input, runQuestions) {
202
213
  }
203
214
  printStep("Step 2/7", "Requirement setup");
204
215
  printWhy("I will gather enough context to generate a valid first draft.");
216
+ printBeginnerTip(beginnerMode, "A requirement draft defines scope, acceptance criteria, and constraints.");
205
217
  if (shouldRunQuestions) {
206
218
  const packs = (0, prompt_packs_1.loadPromptPacks)();
207
219
  const packIds = intent_1.FLOW_PROMPT_PACKS[intent.flow] ?? [];
@@ -277,6 +289,7 @@ async function runHello(input, runQuestions) {
277
289
  const stepIndex = autopilot_checkpoint_1.AUTOPILOT_STEPS.indexOf(startStep);
278
290
  if (dryRun) {
279
291
  printWhy("Dry run active: previewing autopilot plan without writing files.");
292
+ printBeginnerTip(beginnerMode, "Dry run is safe: it shows plan only and does not change files.");
280
293
  for (let i = stepIndex; i < autopilot_checkpoint_1.AUTOPILOT_STEPS.length; i += 1) {
281
294
  const step = autopilot_checkpoint_1.AUTOPILOT_STEPS[i];
282
295
  console.log(`Would run step: ${step}`);
@@ -289,6 +302,7 @@ async function runHello(input, runQuestions) {
289
302
  if (step === "create") {
290
303
  printStep("Step 3/7", "Creating requirement draft automatically");
291
304
  printWhy("This creates your baseline scope, acceptance criteria, and NFRs.");
305
+ printBeginnerTip(beginnerMode, "After this, your requirement is ready for planning artifacts.");
292
306
  const created = await (0, req_create_1.runReqCreate)(draft, { autofill: true });
293
307
  if (!created) {
294
308
  console.log("Autopilot stopped at requirement creation.");
@@ -300,6 +314,7 @@ async function runHello(input, runQuestions) {
300
314
  if (step === "plan") {
301
315
  printStep("Step 4/7", `Planning requirement ${reqId}`);
302
316
  printWhy("I am generating functional, technical, architecture, and test artifacts.");
317
+ printBeginnerTip(beginnerMode, "Planning creates the blueprint before implementation.");
303
318
  const planned = await (0, req_plan_1.runReqPlan)({
304
319
  projectName: activeProject,
305
320
  reqId,
@@ -315,6 +330,7 @@ async function runHello(input, runQuestions) {
315
330
  if (step === "start") {
316
331
  printStep("Step 5/7", `Preparing implementation plan for ${reqId}`);
317
332
  printWhy("This stage defines milestones, tasks, quality thresholds, and decisions.");
333
+ printBeginnerTip(beginnerMode, "Start phase prepares execution details and quality guardrails.");
318
334
  const started = await (0, req_start_1.runReqStart)({
319
335
  projectName: activeProject,
320
336
  reqId,
@@ -330,6 +346,7 @@ async function runHello(input, runQuestions) {
330
346
  if (step === "test") {
331
347
  printStep("Step 6/7", `Updating test plan for ${reqId}`);
332
348
  printWhy("I am ensuring critical paths, edge cases, and regression tests are documented.");
349
+ printBeginnerTip(beginnerMode, "Testing focus reduces regressions before delivery.");
333
350
  const tested = await (0, test_plan_1.runTestPlan)({
334
351
  projectName: activeProject,
335
352
  reqId,
@@ -345,6 +362,7 @@ async function runHello(input, runQuestions) {
345
362
  if (step === "finish") {
346
363
  printStep("Step 7/7", `Finalizing requirement ${reqId}`);
347
364
  printWhy("I will move artifacts to done state and generate project-level summary files.");
365
+ printBeginnerTip(beginnerMode, "Finish locks outputs and leaves a reusable delivery record.");
348
366
  const finished = await (0, req_finish_1.runReqFinish)({
349
367
  projectName: activeProject,
350
368
  reqId,
@@ -0,0 +1 @@
1
+ export declare function runQuickstart(example?: string, listExamples?: boolean): Promise<void>;
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.runQuickstart = runQuickstart;
4
+ const flags_1 = require("../context/flags");
5
+ const hello_1 = require("./hello");
6
+ const QUICKSTART_EXAMPLES = {
7
+ saas: "Build a SaaS onboarding workflow for first-time users",
8
+ bugfix: "Fix a high-priority login failure with reproducible steps and tests",
9
+ api: "Design a REST API for order management with validation and error handling",
10
+ ecommerce: "Create an ecommerce checkout flow with payments and order confirmation",
11
+ mobile: "Plan a mobile app feature for push notifications and user preferences"
12
+ };
13
+ function normalizeExample(example) {
14
+ const value = (example || "saas").trim().toLowerCase();
15
+ return QUICKSTART_EXAMPLES[value] ? value : "saas";
16
+ }
17
+ async function runQuickstart(example, listExamples) {
18
+ if (listExamples) {
19
+ console.log("Quickstart examples:");
20
+ Object.entries(QUICKSTART_EXAMPLES).forEach(([key, prompt]) => {
21
+ console.log(`- ${key}: ${prompt}`);
22
+ });
23
+ return;
24
+ }
25
+ const selected = normalizeExample(example);
26
+ const seed = QUICKSTART_EXAMPLES[selected];
27
+ console.log(`Running quickstart example: ${selected}`);
28
+ (0, flags_1.setFlags)({ nonInteractive: true });
29
+ await (0, hello_1.runHello)(seed, false);
30
+ }
@@ -0,0 +1 @@
1
+ export declare function runStatus(showNext?: boolean): void;
@@ -0,0 +1,97 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.runStatus = runStatus;
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const path_1 = __importDefault(require("path"));
9
+ const flags_1 = require("../context/flags");
10
+ const index_1 = require("../workspace/index");
11
+ const REQUIREMENT_STATUSES = ["backlog", "wip", "in-progress", "done", "archived"];
12
+ function listRequirementIds(projectRoot, status) {
13
+ const dir = path_1.default.join(projectRoot, "requirements", status);
14
+ if (!fs_1.default.existsSync(dir)) {
15
+ return [];
16
+ }
17
+ return fs_1.default
18
+ .readdirSync(dir, { withFileTypes: true })
19
+ .filter((entry) => entry.isDirectory())
20
+ .map((entry) => entry.name)
21
+ .sort();
22
+ }
23
+ function latestId(ids) {
24
+ if (ids.length === 0) {
25
+ return null;
26
+ }
27
+ return ids[ids.length - 1];
28
+ }
29
+ function recommendNext(projectName, counts, ids) {
30
+ const nextInProgress = latestId(ids["in-progress"]);
31
+ if (nextInProgress) {
32
+ return `sdd-cli --project "${projectName}" req finish # then enter ${nextInProgress} when prompted`;
33
+ }
34
+ const nextWip = latestId(ids.wip);
35
+ if (nextWip) {
36
+ return `sdd-cli --project "${projectName}" req start # then enter ${nextWip} when prompted`;
37
+ }
38
+ const nextBacklog = latestId(ids.backlog);
39
+ if (nextBacklog) {
40
+ return `sdd-cli --project "${projectName}" req plan # then enter ${nextBacklog} when prompted`;
41
+ }
42
+ if (counts.done > 0 && counts.archived === 0) {
43
+ return `sdd-cli --project "${projectName}" hello "start next requirement"`;
44
+ }
45
+ return `sdd-cli --project "${projectName}" hello "continue"`;
46
+ }
47
+ function runStatus(showNext) {
48
+ const workspace = (0, index_1.getWorkspaceInfo)();
49
+ (0, index_1.ensureWorkspace)(workspace);
50
+ const projects = (0, index_1.listProjects)(workspace);
51
+ const flags = (0, flags_1.getFlags)();
52
+ const selectedName = flags.project && flags.project.trim().length > 0 ? flags.project.trim() : projects[0]?.name;
53
+ if (!selectedName) {
54
+ console.log("No projects found.");
55
+ if (showNext) {
56
+ console.log('Next command: sdd-cli quickstart --example saas');
57
+ }
58
+ return;
59
+ }
60
+ let project;
61
+ try {
62
+ project = (0, index_1.getProjectInfo)(workspace, selectedName);
63
+ }
64
+ catch (error) {
65
+ console.log(error.message);
66
+ return;
67
+ }
68
+ if (!fs_1.default.existsSync(project.root)) {
69
+ console.log("No projects found.");
70
+ if (showNext) {
71
+ console.log('Next command: sdd-cli quickstart --example saas');
72
+ }
73
+ return;
74
+ }
75
+ const ids = {
76
+ backlog: listRequirementIds(project.root, "backlog"),
77
+ wip: listRequirementIds(project.root, "wip"),
78
+ "in-progress": listRequirementIds(project.root, "in-progress"),
79
+ done: listRequirementIds(project.root, "done"),
80
+ archived: listRequirementIds(project.root, "archived")
81
+ };
82
+ const counts = {
83
+ backlog: ids.backlog.length,
84
+ wip: ids.wip.length,
85
+ "in-progress": ids["in-progress"].length,
86
+ done: ids.done.length,
87
+ archived: ids.archived.length
88
+ };
89
+ console.log(`Project: ${project.name}`);
90
+ REQUIREMENT_STATUSES.forEach((status) => {
91
+ console.log(`- ${status}: ${counts[status]}`);
92
+ });
93
+ if (showNext) {
94
+ const recommendation = recommendNext(project.name, counts, ids);
95
+ console.log(`Next command: ${recommendation}`);
96
+ }
97
+ }
@@ -4,6 +4,7 @@ export type RuntimeFlags = {
4
4
  parallel: boolean;
5
5
  nonInteractive: boolean;
6
6
  dryRun: boolean;
7
+ beginner: boolean;
7
8
  fromStep?: string;
8
9
  project?: string;
9
10
  output?: string;
@@ -8,6 +8,7 @@ const flags = {
8
8
  parallel: false,
9
9
  nonInteractive: false,
10
10
  dryRun: false,
11
+ beginner: false,
11
12
  fromStep: undefined,
12
13
  project: undefined,
13
14
  output: undefined
@@ -28,6 +29,9 @@ function setFlags(next) {
28
29
  if ("dryRun" in next) {
29
30
  flags.dryRun = Boolean(next.dryRun);
30
31
  }
32
+ if ("beginner" in next) {
33
+ flags.beginner = Boolean(next.beginner);
34
+ }
31
35
  if ("fromStep" in next) {
32
36
  flags.fromStep = typeof next.fromStep === "string" ? next.fromStep : undefined;
33
37
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sdd-cli",
3
- "version": "0.1.15",
3
+ "version": "0.1.17",
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": {