gsd-pi 2.75.0-dev.b6ad8c5f7 → 2.75.0-dev.e41b70b10

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.
Files changed (181) hide show
  1. package/dist/resources/extensions/gsd/auto/phases.js +2 -0
  2. package/dist/resources/extensions/gsd/auto-dashboard.js +22 -1
  3. package/dist/resources/extensions/gsd/auto-direct-dispatch.js +8 -2
  4. package/dist/resources/extensions/gsd/auto-dispatch.js +11 -11
  5. package/dist/resources/extensions/gsd/auto-model-selection.js +3 -1
  6. package/dist/resources/extensions/gsd/auto-prompts.js +19 -9
  7. package/dist/resources/extensions/gsd/auto-worktree.js +16 -1
  8. package/dist/resources/extensions/gsd/bootstrap/memory-tools.js +128 -0
  9. package/dist/resources/extensions/gsd/bootstrap/register-extension.js +2 -0
  10. package/dist/resources/extensions/gsd/bootstrap/system-context.js +17 -4
  11. package/dist/resources/extensions/gsd/commands/handlers/onboarding.js +52 -92
  12. package/dist/resources/extensions/gsd/commands/handlers/ops.js +5 -0
  13. package/dist/resources/extensions/gsd/commands-memory.js +462 -0
  14. package/dist/resources/extensions/gsd/doctor-git-checks.js +22 -2
  15. package/dist/resources/extensions/gsd/gsd-db.js +237 -4
  16. package/dist/resources/extensions/gsd/memory-embeddings.js +219 -0
  17. package/dist/resources/extensions/gsd/memory-extractor.js +78 -27
  18. package/dist/resources/extensions/gsd/memory-ingest.js +218 -0
  19. package/dist/resources/extensions/gsd/memory-relations.js +189 -0
  20. package/dist/resources/extensions/gsd/memory-source-store.js +113 -0
  21. package/dist/resources/extensions/gsd/memory-store.js +299 -6
  22. package/dist/resources/extensions/gsd/pre-execution-checks.js +12 -8
  23. package/dist/resources/extensions/gsd/prompts/add-tests.md +1 -0
  24. package/dist/resources/extensions/gsd/prompts/execute-task.md +1 -1
  25. package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -0
  26. package/dist/resources/extensions/gsd/tools/memory-tools.js +306 -0
  27. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +14 -0
  28. package/dist/resources/extensions/search-the-web/command-search-provider.js +4 -1
  29. package/dist/resources/extensions/search-the-web/native-search.js +13 -2
  30. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  31. package/dist/web/standalone/.next/BUILD_ID +1 -1
  32. package/dist/web/standalone/.next/app-path-routes-manifest.json +10 -10
  33. package/dist/web/standalone/.next/build-manifest.json +2 -2
  34. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  35. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  36. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  37. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  38. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  39. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  40. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  41. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  42. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  43. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  44. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  45. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  46. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  47. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  48. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  49. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  50. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  51. package/dist/web/standalone/.next/server/app/index.html +1 -1
  52. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  53. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  54. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  55. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  56. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  57. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  58. package/dist/web/standalone/.next/server/app-paths-manifest.json +10 -10
  59. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  60. package/dist/web/standalone/.next/server/middleware-manifest.json +5 -5
  61. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  62. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  63. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  64. package/package.json +1 -1
  65. package/packages/mcp-server/dist/server.d.ts.map +1 -1
  66. package/packages/mcp-server/dist/server.js +12 -10
  67. package/packages/mcp-server/dist/server.js.map +1 -1
  68. package/packages/mcp-server/dist/session-manager.d.ts.map +1 -1
  69. package/packages/mcp-server/dist/session-manager.js +8 -1
  70. package/packages/mcp-server/dist/session-manager.js.map +1 -1
  71. package/packages/mcp-server/dist/workflow-tools.d.ts +1 -0
  72. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  73. package/packages/mcp-server/dist/workflow-tools.js +207 -71
  74. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  75. package/packages/mcp-server/src/mcp-server.test.ts +40 -4
  76. package/packages/mcp-server/src/server.ts +12 -10
  77. package/packages/mcp-server/src/session-manager.ts +10 -3
  78. package/packages/mcp-server/src/workflow-tools.test.ts +346 -1
  79. package/packages/mcp-server/src/workflow-tools.ts +228 -75
  80. package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
  81. package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
  82. package/packages/pi-ai/dist/index.d.ts +1 -0
  83. package/packages/pi-ai/dist/index.d.ts.map +1 -1
  84. package/packages/pi-ai/dist/index.js +1 -0
  85. package/packages/pi-ai/dist/index.js.map +1 -1
  86. package/packages/pi-ai/dist/providers/api-family.d.ts +27 -0
  87. package/packages/pi-ai/dist/providers/api-family.d.ts.map +1 -0
  88. package/packages/pi-ai/dist/providers/api-family.js +47 -0
  89. package/packages/pi-ai/dist/providers/api-family.js.map +1 -0
  90. package/packages/pi-ai/dist/providers/api-family.test.d.ts +2 -0
  91. package/packages/pi-ai/dist/providers/api-family.test.d.ts.map +1 -0
  92. package/packages/pi-ai/dist/providers/api-family.test.js +101 -0
  93. package/packages/pi-ai/dist/providers/api-family.test.js.map +1 -0
  94. package/packages/pi-ai/src/index.ts +1 -0
  95. package/packages/pi-ai/src/providers/api-family.test.ts +129 -0
  96. package/packages/pi-ai/src/providers/api-family.ts +57 -0
  97. package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
  98. package/packages/pi-coding-agent/dist/cli/args.d.ts +6 -0
  99. package/packages/pi-coding-agent/dist/cli/args.d.ts.map +1 -1
  100. package/packages/pi-coding-agent/dist/cli/args.js +14 -4
  101. package/packages/pi-coding-agent/dist/cli/args.js.map +1 -1
  102. package/packages/pi-coding-agent/dist/cli/args.test.d.ts +2 -0
  103. package/packages/pi-coding-agent/dist/cli/args.test.d.ts.map +1 -0
  104. package/packages/pi-coding-agent/dist/cli/args.test.js +38 -0
  105. package/packages/pi-coding-agent/dist/cli/args.test.js.map +1 -0
  106. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts +1 -0
  107. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts.map +1 -1
  108. package/packages/pi-coding-agent/dist/core/extensions/runner.js.map +1 -1
  109. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +2 -1
  110. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
  111. package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
  112. package/packages/pi-coding-agent/dist/core/retry-handler.d.ts.map +1 -1
  113. package/packages/pi-coding-agent/dist/core/retry-handler.js +4 -1
  114. package/packages/pi-coding-agent/dist/core/retry-handler.js.map +1 -1
  115. package/packages/pi-coding-agent/dist/core/sdk.d.ts +10 -0
  116. package/packages/pi-coding-agent/dist/core/sdk.d.ts.map +1 -1
  117. package/packages/pi-coding-agent/dist/core/sdk.js +7 -1
  118. package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
  119. package/packages/pi-coding-agent/dist/main.d.ts.map +1 -1
  120. package/packages/pi-coding-agent/dist/main.js +3 -0
  121. package/packages/pi-coding-agent/dist/main.js.map +1 -1
  122. package/packages/pi-coding-agent/src/cli/args.test.ts +44 -0
  123. package/packages/pi-coding-agent/src/cli/args.ts +21 -6
  124. package/packages/pi-coding-agent/src/core/extensions/runner.ts +4 -1
  125. package/packages/pi-coding-agent/src/core/extensions/types.ts +2 -2
  126. package/packages/pi-coding-agent/src/core/retry-handler.ts +4 -1
  127. package/packages/pi-coding-agent/src/core/sdk.ts +17 -1
  128. package/packages/pi-coding-agent/src/main.ts +4 -0
  129. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
  130. package/src/resources/extensions/gsd/auto/loop-deps.ts +2 -10
  131. package/src/resources/extensions/gsd/auto/phases.ts +3 -0
  132. package/src/resources/extensions/gsd/auto-dashboard.ts +25 -1
  133. package/src/resources/extensions/gsd/auto-direct-dispatch.ts +15 -2
  134. package/src/resources/extensions/gsd/auto-dispatch.ts +21 -7
  135. package/src/resources/extensions/gsd/auto-model-selection.ts +3 -1
  136. package/src/resources/extensions/gsd/auto-prompts.ts +33 -9
  137. package/src/resources/extensions/gsd/auto-worktree.ts +16 -1
  138. package/src/resources/extensions/gsd/bootstrap/memory-tools.ts +158 -0
  139. package/src/resources/extensions/gsd/bootstrap/register-extension.ts +2 -0
  140. package/src/resources/extensions/gsd/bootstrap/system-context.ts +20 -4
  141. package/src/resources/extensions/gsd/commands/handlers/onboarding.ts +65 -131
  142. package/src/resources/extensions/gsd/commands/handlers/ops.ts +5 -0
  143. package/src/resources/extensions/gsd/commands-memory.ts +551 -0
  144. package/src/resources/extensions/gsd/doctor-git-checks.ts +23 -2
  145. package/src/resources/extensions/gsd/gsd-db.ts +273 -4
  146. package/src/resources/extensions/gsd/memory-embeddings.ts +235 -0
  147. package/src/resources/extensions/gsd/memory-extractor.ts +100 -34
  148. package/src/resources/extensions/gsd/memory-ingest.ts +286 -0
  149. package/src/resources/extensions/gsd/memory-relations.ts +240 -0
  150. package/src/resources/extensions/gsd/memory-source-store.ts +138 -0
  151. package/src/resources/extensions/gsd/memory-store.ts +351 -7
  152. package/src/resources/extensions/gsd/pre-execution-checks.ts +12 -8
  153. package/src/resources/extensions/gsd/prompts/add-tests.md +1 -0
  154. package/src/resources/extensions/gsd/prompts/execute-task.md +1 -1
  155. package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -0
  156. package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +49 -0
  157. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +2 -2
  158. package/src/resources/extensions/gsd/tests/complete-task.test.ts +2 -2
  159. package/src/resources/extensions/gsd/tests/escalation.test.ts +2 -2
  160. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +1 -1
  161. package/src/resources/extensions/gsd/tests/integration/doctor-git-symlink-cwd.test.ts +79 -0
  162. package/src/resources/extensions/gsd/tests/md-importer.test.ts +1 -1
  163. package/src/resources/extensions/gsd/tests/memory-embeddings.test.ts +213 -0
  164. package/src/resources/extensions/gsd/tests/memory-ingest.test.ts +153 -0
  165. package/src/resources/extensions/gsd/tests/memory-maintenance.test.ts +107 -0
  166. package/src/resources/extensions/gsd/tests/memory-relations.test.ts +175 -0
  167. package/src/resources/extensions/gsd/tests/memory-store.test.ts +2 -2
  168. package/src/resources/extensions/gsd/tests/memory-tools.test.ts +295 -0
  169. package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +66 -0
  170. package/src/resources/extensions/gsd/tests/prompt-budget-enforcement.test.ts +132 -8
  171. package/src/resources/extensions/gsd/tests/prompts-no-gitignored-test-refs.test.ts +56 -0
  172. package/src/resources/extensions/gsd/tests/stash-queued-context-files.test.ts +54 -0
  173. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +97 -0
  174. package/src/resources/extensions/gsd/tools/memory-tools.ts +380 -0
  175. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +14 -0
  176. package/src/resources/extensions/gsd/workflow-logger.ts +3 -1
  177. package/src/resources/extensions/search-the-web/command-search-provider.ts +4 -1
  178. package/src/resources/extensions/search-the-web/native-search.ts +13 -3
  179. package/src/resources/extensions/gsd/tests/onboarding-handler-loader.test.ts +0 -41
  180. /package/dist/web/standalone/.next/static/{J2z3GMC9QtSLr7gyoM38c → By_yegSJ-AA1OP0QjYbSl}/_buildManifest.js +0 -0
  181. /package/dist/web/standalone/.next/static/{J2z3GMC9QtSLr7gyoM38c → By_yegSJ-AA1OP0QjYbSl}/_ssgManifest.js +0 -0
@@ -1,55 +1,26 @@
1
- // GSD — /gsd onboarding command handler (re-entry, --resume, --reset, --step)
1
+ // GSD — /gsd onboarding command handler (re-entry hub)
2
2
  //
3
- // Provides the discoverable re-entry point for the onboarding wizard. The
4
- // first-run wizard in src/onboarding.ts is hidden behind shouldRunOnboarding;
5
- // this handler lets users re-launch it on demand.
6
- import { AuthStorage } from "@gsd/pi-coding-agent";
7
- import { homedir } from "node:os";
8
- import { dirname, join, resolve } from "node:path";
9
- import { pathToFileURL } from "node:url";
10
- import { ONBOARDING_STEPS, isValidStepId, nearestResumeStep, } from "../../setup-catalog.js";
3
+ // The first-run wizard in src/onboarding.ts uses @clack/prompts and takes over
4
+ // raw stdin. Running it from inside the pi-coding-agent TUI wedges the TUI
5
+ // (clack leaves stdin paused + cooked, pi-tui's data handler then receives no
6
+ // keypresses). So re-entry cannot replay the clack wizard — instead it routes
7
+ // to a setup hub built from ctx.ui.select, which the TUI owns.
8
+ //
9
+ // Clack-only steps (llm/search/remote/tool-keys via the first-run wizard) are
10
+ // surfaced as notifications pointing the user at the canonical per-step
11
+ // commands (/login, /gsd keys, /gsd remote) that are already ctx.ui-safe.
12
+ import { ONBOARDING_STEPS, isValidStepId, } from "../../setup-catalog.js";
11
13
  import { isOnboardingComplete, readOnboardingRecord, resetOnboarding, } from "../../onboarding-state.js";
12
- // Inline auth path (mirrors src/app-paths.ts) — keep this module rootDir-clean
13
- // for the resources tsconfig. Importing from src/ pulls files outside
14
- // src/resources and breaks the build.
15
- const AUTH_FILE_PATH = join(process.env.GSD_CODING_AGENT_DIR ||
16
- join(process.env.GSD_HOME || join(homedir(), ".gsd"), "agent"), "auth.json");
17
- async function loadFirstRunWizard() {
18
- const candidates = [];
19
- // Primary deployed path: loader sets GSD_PKG_ROOT (gsd package root).
20
- if (process.env.GSD_PKG_ROOT) {
21
- candidates.push(pathToFileURL(join(process.env.GSD_PKG_ROOT, "dist", "onboarding.js")).href);
22
- }
23
- // Fallback: derive package root from process entry (typically dist/loader.js).
24
- // This keeps /gsd onboarding resilient if GSD_PKG_ROOT is absent.
25
- const argvEntry = process.argv[1];
26
- if (argvEntry) {
27
- const pkgRootFromArgv = resolve(dirname(argvEntry), "..");
28
- candidates.push(pathToFileURL(join(pkgRootFromArgv, "dist", "onboarding.js")).href);
29
- }
30
- // Source-tree/dev fallback (works in dist/resources/... and ts test loaders).
31
- candidates.push("../../../../../onboarding.js");
32
- let lastError = null;
33
- for (const specifier of candidates) {
34
- try {
35
- return (await import(/* @vite-ignore */ specifier));
36
- }
37
- catch (err) {
38
- lastError = err;
39
- }
40
- }
41
- const reason = lastError instanceof Error ? lastError.message : String(lastError);
42
- throw new Error(`[gsd] Failed to load onboarding wizard module. Tried: ${candidates.join(", ")}. Last error: ${reason}`);
43
- }
44
14
  function parseArgs(raw) {
45
15
  const tokens = raw.split(/\s+/).filter(Boolean);
46
- const out = { resume: false, reset: false, step: null, stepValid: null };
16
+ const out = { reset: false, step: null, stepValid: null };
47
17
  for (let i = 0; i < tokens.length; i++) {
48
18
  const t = tokens[i];
49
- if (t === "--resume" || t === "resume")
50
- out.resume = true;
51
- else if (t === "--reset" || t === "reset")
19
+ if (t === "--reset" || t === "reset")
52
20
  out.reset = true;
21
+ else if (t === "--resume" || t === "resume") {
22
+ // Re-entry no longer replays the wizard; --resume collapses into the hub.
23
+ }
53
24
  else if (t === "--step" || t === "step") {
54
25
  const next = tokens[i + 1];
55
26
  if (next) {
@@ -66,46 +37,26 @@ function parseArgs(raw) {
66
37
  }
67
38
  return out;
68
39
  }
69
- async function getAuthStorage() {
70
- return AuthStorage.create(AUTH_FILE_PATH);
71
- }
72
- async function runWholeWizard(ctx, fromStep) {
73
- const authStorage = await getAuthStorage();
74
- // The first-run wizard ignores the resume hint today — it always walks the
75
- // full sequence with skip prompts. We still mark completion at the end and
76
- // record the resume hint for next time. This keeps the wizard linear and
77
- // simple; per-step jump support comes via --step.
78
- if (fromStep) {
79
- ctx.ui.notify(`Resuming from step: ${fromStep}. The wizard runs all remaining steps; press skip on any you've already configured.`, "info");
80
- }
81
- const { runOnboarding } = await loadFirstRunWizard();
82
- await runOnboarding(authStorage, { showIntro: false });
83
- }
84
- async function runSingleStep(ctx, stepId) {
85
- const authStorage = await getAuthStorage();
86
- const ob = await loadFirstRunWizard();
87
- // Lazy-load clack + chalk via the same path the wizard uses
88
- const p = await import("@clack/prompts");
89
- const { default: chalk } = await import("chalk");
90
- const pc = {
91
- cyan: chalk.cyan, green: chalk.green, yellow: chalk.yellow,
92
- dim: chalk.dim, bold: chalk.bold, red: chalk.red, reset: chalk.reset,
93
- };
40
+ // ─── Per-step routing ────────────────────────────────────────────────────────
41
+ //
42
+ // Clack-based steps are surfaced as notifications — running them inline from
43
+ // the TUI would wedge stdin (see header comment). Everything else routes to an
44
+ // existing ctx.ui-safe handler.
45
+ async function runStep(ctx, stepId) {
94
46
  switch (stepId) {
95
47
  case "llm":
96
- await ob.runLlmStep(p, pc, authStorage);
48
+ ctx.ui.notify("LLM provider setup: run /login to sign in via OAuth, or /gsd keys add to paste an API key.", "info");
97
49
  return;
98
50
  case "search":
99
- await ob.runWebSearchStep(p, pc, authStorage, false);
51
+ ctx.ui.notify("Web search setup: run /gsd keys add and pick a search provider (brave, tavily, etc.).", "info");
100
52
  return;
101
53
  case "remote":
102
- await ob.runRemoteQuestionsStep(p, pc, authStorage);
54
+ ctx.ui.notify("Remote questions setup: run /gsd remote to configure Discord / Slack / Telegram notifications.", "info");
103
55
  return;
104
56
  case "tool-keys":
105
- await ob.runToolKeysStep(p, pc, authStorage);
57
+ ctx.ui.notify("Tool keys setup: run /gsd keys add to save API keys for Context7, Jina, Groq voice, etc.", "info");
106
58
  return;
107
59
  case "model": {
108
- // Delegate to /gsd model picker
109
60
  const { handleCoreCommand } = await import("./core.js");
110
61
  await handleCoreCommand("model", ctx);
111
62
  return;
@@ -118,7 +69,6 @@ async function runSingleStep(ctx, stepId) {
118
69
  return;
119
70
  }
120
71
  case "doctor": {
121
- // Best-effort: surface provider doctor results inline
122
72
  try {
123
73
  const { runProviderDoctor } = await import("../../doctor-providers.js");
124
74
  if (typeof runProviderDoctor === "function") {
@@ -130,10 +80,9 @@ async function runSingleStep(ctx, stepId) {
130
80
  ctx.ui.notify("Run /gsd doctor to validate your setup.", "info");
131
81
  return;
132
82
  }
133
- case "skills": {
134
- ctx.ui.notify("Skill install runs automatically during /gsd init. Use /gsd init or /skill manage.", "info");
83
+ case "skills":
84
+ ctx.ui.notify("Skill install runs during /gsd init. Use /gsd init or /skill manage.", "info");
135
85
  return;
136
- }
137
86
  case "project": {
138
87
  const { handleCoreCommand } = await import("./core.js");
139
88
  await handleCoreCommand("init", ctx);
@@ -141,6 +90,25 @@ async function runSingleStep(ctx, stepId) {
141
90
  }
142
91
  }
143
92
  }
93
+ // ─── Setup hub ───────────────────────────────────────────────────────────────
94
+ async function renderSetupHub(ctx) {
95
+ const record = readOnboardingRecord();
96
+ const completed = new Set(record.completedSteps);
97
+ const skipped = new Set(record.skippedSteps);
98
+ const labels = ONBOARDING_STEPS.map(step => {
99
+ const mark = completed.has(step.id) ? "✓" : skipped.has(step.id) ? "↷" : "○";
100
+ const req = step.required ? " (required)" : "";
101
+ return `${mark} ${step.label}${req} — ${step.hint}`;
102
+ });
103
+ const labelToStep = new Map(labels.map((label, i) => [label, ONBOARDING_STEPS[i].id]));
104
+ const choice = await ctx.ui.select("GSD Setup — pick a step to configure", labels);
105
+ if (typeof choice !== "string")
106
+ return;
107
+ const stepId = labelToStep.get(choice);
108
+ if (!stepId)
109
+ return;
110
+ await runStep(ctx, stepId);
111
+ }
144
112
  function renderStatus() {
145
113
  const r = readOnboardingRecord();
146
114
  const lines = ["GSD Onboarding\n"];
@@ -173,27 +141,19 @@ export async function handleOnboarding(rawArgs, ctx) {
173
141
  ctx.ui.notify(`Unknown step "${args.step}". Valid: ${validIds}`, "warning");
174
142
  return;
175
143
  }
176
- await runSingleStep(ctx, args.step);
144
+ await runStep(ctx, args.step);
177
145
  return;
178
146
  }
179
147
  if (args.reset) {
180
148
  resetOnboarding();
181
- ctx.ui.notify("Onboarding reset. Existing API keys/credentials are unchanged — manage them with /gsd keys.", "info");
182
- await runWholeWizard(ctx);
183
- return;
184
- }
185
- if (args.resume) {
186
- const r = readOnboardingRecord();
187
- const next = nearestResumeStep(r.lastResumePoint, r.completedSteps);
188
- await runWholeWizard(ctx, next);
149
+ ctx.ui.notify("Onboarding state cleared. API keys/credentials are unchanged — manage them with /gsd keys. Restart GSD to re-run the first-run wizard, or pick a step below.", "info");
150
+ await renderSetupHub(ctx);
189
151
  return;
190
152
  }
191
- // No flags. If already complete, show status + offer choice.
153
+ // No flags (or --resume). Show status if complete, then open the hub.
192
154
  if (isOnboardingComplete()) {
193
155
  ctx.ui.notify(renderStatus(), "info");
194
- ctx.ui.notify("Onboarding already complete. Use /gsd onboarding --reset to start over, or --step <name> to redo one section.", "info");
195
- return;
196
156
  }
197
- await runWholeWizard(ctx);
157
+ await renderSetupHub(ctx);
198
158
  }
199
159
  export { renderStatus as renderOnboardingStatus };
@@ -248,6 +248,11 @@ Examples:
248
248
  await handleExtractLearnings(trimmed.replace(/^extract-learnings\s*/, "").trim(), ctx, pi);
249
249
  return true;
250
250
  }
251
+ if (trimmed === "memory" || trimmed.startsWith("memory ") || trimmed === "memory help") {
252
+ const { handleMemory } = await import("../../commands-memory.js");
253
+ await handleMemory(trimmed.replace(/^memory\s*/, "").trim(), ctx, pi);
254
+ return true;
255
+ }
251
256
  if (trimmed === "scan" || trimmed.startsWith("scan ")) {
252
257
  const { handleScan } = await import("../../commands-scan.js");
253
258
  // \s* (not \s+) is intentional: handles both /gsd scan (no args) and /gsd scan --focus X