pi-gsd 1.3.0 → 1.3.1

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.
@@ -254,18 +254,15 @@ export default function (pi: ExtensionAPI) {
254
254
  return lines;
255
255
  };
256
256
 
257
- const formatProgress = (cwd: string): string => {
257
+ const formatProgress = (cwd: string): { text: string; data: GsdProgress | null } => {
258
258
  const data = runJson<GsdProgress>("progress json", cwd);
259
259
  if (!data)
260
- return "❌ No GSD project found. Run /gsd-new-project to initialise.";
260
+ return { text: "❌ No GSD project found. Run /gsd-new-project to initialise.", data: null };
261
261
 
262
- const phasePct = data.percent ?? 0;
263
- const planPct =
264
- data.total_plans > 0
265
- ? Math.round((data.total_summaries / data.total_plans) * 100)
266
- : 0;
267
262
  const done = data.phases.filter((p) => p.status === "Complete").length;
268
263
  const total = data.phases.length;
264
+ const phasePct = total > 0 ? Math.round((done / total) * 100) : 0;
265
+ const planPct =
269
266
 
270
267
  const lines = [
271
268
  `━━ GSD Progress ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━`,
@@ -279,13 +276,13 @@ export default function (pi: ExtensionAPI) {
279
276
  ``,
280
277
  `━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━`,
281
278
  ];
282
- return lines.join("\n");
279
+ return { text: lines.join("\n"), data };
283
280
  };
284
281
 
285
- const formatStats = (cwd: string): string => {
282
+ const formatStats = (cwd: string): { text: string; data: GsdStats | null } => {
286
283
  const data = runJson<GsdStats>("stats json", cwd);
287
284
  if (!data)
288
- return "❌ No GSD project found. Run /gsd-new-project to initialise.";
285
+ return { text: "❌ No GSD project found. Run /gsd-new-project to initialise.", data: null };
289
286
 
290
287
  const reqPct =
291
288
  data.requirements_total > 0
@@ -311,7 +308,7 @@ export default function (pi: ExtensionAPI) {
311
308
  ``,
312
309
  `━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━`,
313
310
  ];
314
- return lines.join("\n");
311
+ return { text: lines.join("\n"), data };
315
312
  };
316
313
 
317
314
  const formatHealth = (cwd: string, repair: boolean): string => {
@@ -349,17 +346,40 @@ export default function (pi: ExtensionAPI) {
349
346
  return lines.join("\n");
350
347
  };
351
348
 
349
+ /** Derive the suggested next command string from phase data. */
350
+ const nextCommand = (phases: GsdPhase[]): string | null => {
351
+ const pending = phases.filter((p) => p.status !== "Complete");
352
+ if (pending.length === 0) return "/gsd-audit-milestone";
353
+ const next = pending[0];
354
+ const n = next.number;
355
+ if (next.plans === 0) return `/gsd-discuss-phase ${n}`;
356
+ if (next.summaries < next.plans) return `/gsd-execute-phase ${n}`;
357
+ return `/gsd-verify-work ${n}`;
358
+ };
359
+
352
360
  pi.registerCommand("gsd-progress", {
353
361
  description: "Show project progress with next steps (instant)",
354
362
  handler: async (_args, ctx) => {
355
- ctx.ui.notify(formatProgress(ctx.cwd), "info");
363
+ const { text, data } = formatProgress(ctx.cwd);
364
+ ctx.ui.notify(text, "info");
365
+ // Pivot affordance: pre-fill the editor with the most relevant next action
366
+ // so the user can run it, modify it, or just type something else entirely
367
+ if (data) {
368
+ const cmd = nextCommand(data.phases);
369
+ if (cmd) ctx.ui.setEditorText(cmd);
370
+ }
356
371
  },
357
372
  });
358
373
 
359
374
  pi.registerCommand("gsd-stats", {
360
375
  description: "Show project statistics (instant)",
361
376
  handler: async (_args, ctx) => {
362
- ctx.ui.notify(formatStats(ctx.cwd), "info");
377
+ const { text, data } = formatStats(ctx.cwd);
378
+ ctx.ui.notify(text, "info");
379
+ if (data) {
380
+ const cmd = nextCommand(data.phases);
381
+ if (cmd) ctx.ui.setEditorText(cmd);
382
+ }
363
383
  },
364
384
  });
365
385
 
@@ -374,6 +394,67 @@ export default function (pi: ExtensionAPI) {
374
394
  },
375
395
  });
376
396
 
397
+ pi.registerCommand("gsd-next", {
398
+ description: "Auto-advance to the next GSD action (instant, no LLM)",
399
+ handler: async (_args, ctx) => {
400
+ const data = runJson<GsdProgress>("progress json", ctx.cwd);
401
+ if (!data) {
402
+ ctx.ui.notify(
403
+ "❌ No GSD project found. Run /gsd-new-project to initialise.",
404
+ "error",
405
+ );
406
+ ctx.ui.setEditorText("/gsd-new-project");
407
+ return;
408
+ }
409
+
410
+ const pending = data.phases.filter((p) => p.status !== "Complete");
411
+
412
+ if (pending.length === 0) {
413
+ ctx.ui.notify(
414
+ [
415
+ `━━ GSD Next ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━`,
416
+ `✅ All phases complete!`,
417
+ `→ /gsd-audit-milestone`,
418
+ `━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━`,
419
+ ].join("\n"),
420
+ "info",
421
+ );
422
+ ctx.ui.setEditorText("/gsd-audit-milestone");
423
+ return;
424
+ }
425
+
426
+ const next = pending[0];
427
+ const n = next.number;
428
+ let action: string;
429
+ let reason: string;
430
+
431
+ if (next.plans === 0) {
432
+ action = `/gsd-discuss-phase ${n}`;
433
+ reason = `Phase ${n} has no plans yet — start with discussion`;
434
+ } else if (next.summaries < next.plans) {
435
+ action = `/gsd-execute-phase ${n}`;
436
+ reason = `Phase ${n}: ${next.summaries}/${next.plans} plans done — continue execution`;
437
+ } else {
438
+ action = `/gsd-verify-work ${n}`;
439
+ reason = `Phase ${n}: all plans done — verify UAT`;
440
+ }
441
+
442
+ ctx.ui.notify(
443
+ [
444
+ `━━ GSD Next ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━`,
445
+ `⏩ ${reason}`,
446
+ `→ ${action}`,
447
+ ...(pending.length > 1
448
+ ? [` (${pending.length - 1} more phase${pending.length > 2 ? "s" : ""} pending after this)`]
449
+ : []),
450
+ `━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━`,
451
+ ].join("\n"),
452
+ "info",
453
+ );
454
+ ctx.ui.setEditorText(action);
455
+ },
456
+ });
457
+
377
458
  pi.registerCommand("gsd-help", {
378
459
  description: "List all GSD commands (instant)",
379
460
  handler: async (_args, ctx) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-gsd",
3
- "version": "1.3.0",
3
+ "version": "1.3.1",
4
4
  "description": "Get Shit Done - Unofficial port of the renowned AI-native project-planning spec-driven toolkit",
5
5
  "main": "dist/pi-gsd-tools.js",
6
6
  "bin": {