pi-gsd 1.3.0 → 1.3.2
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/.gsd/extensions/gsd-hooks.ts +94 -13
- package/README.md +6 -8
- package/package.json +1 -1
|
@@ -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
|
-
|
|
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
|
-
|
|
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/README.md
CHANGED
|
@@ -133,14 +133,12 @@ Switch profile: `/gsd-set-profile <profile>`
|
|
|
133
133
|
| `[-o\|--output] [toon\|json]` output | ❌ | ⚡ | Token-efficient toon renderer output (or json, if LLM absolutely needs it...) |
|
|
134
134
|
| `[-p\|--pick] {JSONPath}` extraction | ❌ | ⚡ | Field extraction from CLI output |
|
|
135
135
|
| TypeScript source | ❌ | ⚡ | Full TS port of gsd-tools (~9k lines) |
|
|
136
|
-
| Compile-time type safety | ❌ |
|
|
137
|
-
| Runtime validation (Zod) | ❌ |
|
|
138
|
-
| Smarter `--repair` | ❌ |
|
|
139
|
-
| Instant commands (no LLM cost) | ❌ | ✔️ | `/gsd-progress`, `/gsd-stats`, `/gsd-health`, `/gsd-help` —
|
|
140
|
-
|
|
|
141
|
-
|
|
142
|
-
<!-- | Pi harness config entry | ❌ | ✔️ | `HARNESS_CONFIG` pi entry - generates `AGENTS.md` via `/gsd-profile-user` | -->
|
|
143
|
-
<!-- | Toon output in skills | ❌ | ✔️ | `gsd-progress`, `gsd-stats`, `gsd-health` use `--output toon` | -->
|
|
136
|
+
| Compile-time type safety | ❌ | ⚠️ | Zod schemas defined; ~25 loose `any` casts remain in lib modules |
|
|
137
|
+
| Runtime validation (Zod) | ❌ | ⚠️ | Zod schemas for all `.planning/` types; wired to `config.json` + `validate health` — full coverage in progress |
|
|
138
|
+
| Smarter `--repair` | ❌ | ❌ | Schema-driven repair not yet implemented |
|
|
139
|
+
| Instant commands (no LLM cost) | ❌ | ✔️ | `/gsd-progress`, `/gsd-stats`, `/gsd-health`, `/gsd-help`, `/gsd-next` — zero LLM, editor pivot |
|
|
140
|
+
| `/gsd-next` auto-advance | ❌ | ✔️ | Deterministic phase routing, pre-fills editor with the correct next command |
|
|
141
|
+
| Prompt-dispatch for all skills | ❌ | ✔️ | 54 pi prompt templates — clean autocomplete, arg hints, direct workflow dispatch |
|
|
144
142
|
|
|
145
143
|
---
|
|
146
144
|
|