ralphctl 0.2.5 → 0.3.0

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 (55) hide show
  1. package/dist/add-GX7P7XTT.mjs +16 -0
  2. package/dist/add-JGUOR4Z5.mjs +18 -0
  3. package/dist/bootstrap-FMHG6DRY.mjs +11 -0
  4. package/dist/chunk-3QBEBKMZ.mjs +103 -0
  5. package/dist/chunk-4GHVNKLV.mjs +5088 -0
  6. package/dist/{chunk-EDJX7TT6.mjs → chunk-57UWLHRH.mjs} +22 -2
  7. package/dist/chunk-747KW2RW.mjs +24 -0
  8. package/dist/chunk-CDOPLXFK.mjs +5485 -0
  9. package/dist/{chunk-7TG3EAQ2.mjs → chunk-CFUVE2BP.mjs} +1 -5
  10. package/dist/{chunk-IB6OCKZW.mjs → chunk-CTP2A436.mjs} +60 -55
  11. package/dist/{chunk-UBPZHHCD.mjs → chunk-D2YGPLIV.mjs} +84 -41
  12. package/dist/{chunk-QBXHAXHI.mjs → chunk-FKMKOWLA.mjs} +154 -208
  13. package/dist/chunk-HL4ZMHCQ.mjs +261 -0
  14. package/dist/{chunk-OEUJDSHY.mjs → chunk-IWXBJD2D.mjs} +1 -1
  15. package/dist/chunk-JXMHLW42.mjs +227 -0
  16. package/dist/{chunk-EUNAUHC3.mjs → chunk-NUYQK5MN.mjs} +80 -29
  17. package/dist/{chunk-JRFOUFD3.mjs → chunk-YCDUVPRT.mjs} +32 -52
  18. package/dist/cli.mjs +168 -3995
  19. package/dist/create-7WFSCMP4.mjs +15 -0
  20. package/dist/{handle-TA4MYNQJ.mjs → handle-BBAZJ44Y.mjs} +2 -2
  21. package/dist/mount-XZPBDRPZ.mjs +6751 -0
  22. package/dist/{project-YONEJICR.mjs → project-2IE7VWDB.mjs} +9 -5
  23. package/dist/prompts/harness-context.md +3 -3
  24. package/dist/prompts/ideate-auto.md +8 -10
  25. package/dist/prompts/ideate.md +3 -2
  26. package/dist/prompts/plan-auto.md +12 -12
  27. package/dist/prompts/plan-common.md +24 -15
  28. package/dist/prompts/plan-interactive.md +8 -8
  29. package/dist/prompts/signals-evaluation.md +1 -1
  30. package/dist/prompts/sprint-feedback.md +48 -0
  31. package/dist/prompts/task-evaluation-resume.md +7 -5
  32. package/dist/prompts/task-evaluation.md +37 -33
  33. package/dist/prompts/task-execution.md +33 -24
  34. package/dist/prompts/ticket-refine.md +6 -5
  35. package/dist/prompts/validation-checklist.md +10 -10
  36. package/dist/{resolver-RXEY6EJE.mjs → resolver-EOE5WUMV.mjs} +5 -5
  37. package/dist/{sprint-FGLWYWKX.mjs → sprint-OGOFEJJH.mjs} +7 -9
  38. package/dist/start-MMWC7QLI.mjs +17 -0
  39. package/package.json +15 -13
  40. package/dist/add-3T225IX5.mjs +0 -16
  41. package/dist/add-6A5432U2.mjs +0 -16
  42. package/dist/chunk-742XQ7FL.mjs +0 -551
  43. package/dist/chunk-7LZ6GOGN.mjs +0 -53
  44. package/dist/chunk-CSICORGV.mjs +0 -4333
  45. package/dist/chunk-DUU5346E.mjs +0 -59
  46. package/dist/create-MYGOWO2F.mjs +0 -12
  47. package/dist/multiline-OHSNFCRG.mjs +0 -40
  48. package/dist/wizard-XZ7OGBCJ.mjs +0 -193
  49. package/schemas/config.schema.json +0 -30
  50. package/schemas/ideate-output.schema.json +0 -22
  51. package/schemas/projects.schema.json +0 -58
  52. package/schemas/requirements-output.schema.json +0 -24
  53. package/schemas/sprint.schema.json +0 -109
  54. package/schemas/task-import.schema.json +0 -56
  55. package/schemas/tasks.schema.json +0 -98
@@ -1,20 +1,16 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- // src/utils/exit-codes.ts
4
- var EXIT_SUCCESS = 0;
3
+ // src/domain/exit-codes.ts
5
4
  var EXIT_ERROR = 1;
6
5
  var EXIT_NO_TASKS = 2;
7
- var EXIT_ALL_BLOCKED = 3;
8
6
  var EXIT_INTERRUPTED = 130;
9
7
  function exitWithCode(code) {
10
8
  process.exit(code);
11
9
  }
12
10
 
13
11
  export {
14
- EXIT_SUCCESS,
15
12
  EXIT_ERROR,
16
13
  EXIT_NO_TASKS,
17
- EXIT_ALL_BLOCKED,
18
14
  EXIT_INTERRUPTED,
19
15
  exitWithCode
20
16
  };
@@ -3,27 +3,13 @@ import {
3
3
  IOError,
4
4
  StorageError,
5
5
  ValidationError
6
- } from "./chunk-EDJX7TT6.mjs";
6
+ } from "./chunk-57UWLHRH.mjs";
7
7
 
8
- // src/utils/paths.ts
9
- import { fileURLToPath } from "url";
10
- import { dirname, isAbsolute, join, resolve, sep } from "path";
11
- import { existsSync } from "fs";
8
+ // src/integration/persistence/paths.ts
9
+ import { isAbsolute, join, resolve, sep } from "path";
12
10
  import { homedir } from "os";
13
11
  import { lstat, realpath, stat } from "fs/promises";
14
12
  import { Result } from "typescript-result";
15
- var __filename = fileURLToPath(import.meta.url);
16
- var __dirname = dirname(__filename);
17
- function getRepoRoot() {
18
- let dir = __dirname;
19
- while (dir !== dirname(dir)) {
20
- if (existsSync(join(dir, "package.json"))) {
21
- return dir;
22
- }
23
- dir = dirname(dir);
24
- }
25
- return join(__dirname, "..", "..");
26
- }
27
13
  function getDataDir() {
28
14
  return process.env["RALPHCTL_ROOT"] ?? join(homedir(), ".ralphctl");
29
15
  }
@@ -72,13 +58,10 @@ function getRefinementDir(sprintId, ticketId) {
72
58
  function getPlanningDir(sprintId) {
73
59
  return join(getSprintDir(sprintId), "planning");
74
60
  }
75
- function getIdeateDir(sprintId, ticketId) {
61
+ function getIdeationDir(sprintId, ticketId) {
76
62
  assertSafeSegment(ticketId, "ticket ID");
77
63
  return join(getSprintDir(sprintId), "ideation", ticketId);
78
64
  }
79
- function getSchemaPath(schemaName) {
80
- return join(getRepoRoot(), "schemas", schemaName);
81
- }
82
65
  function assertSafeCwd(path) {
83
66
  if (!path || path.includes("\0") || path.includes("\n") || path.includes("\r")) {
84
67
  throw new Error("Unsafe path for cwd: contains null bytes or newlines");
@@ -115,9 +98,9 @@ async function validateProjectPath(path) {
115
98
  }
116
99
  }
117
100
 
118
- // src/utils/storage.ts
101
+ // src/integration/persistence/storage.ts
119
102
  import { access, appendFile, mkdir, readdir, readFile, rm, writeFile } from "fs/promises";
120
- import { dirname as dirname2 } from "path";
103
+ import { dirname } from "path";
121
104
  import { Result as Result2 } from "typescript-result";
122
105
  async function ensureDir(dirPath) {
123
106
  await mkdir(dirPath, { recursive: true });
@@ -177,7 +160,7 @@ ${issues}`, filePath, result.error)
177
160
  );
178
161
  }
179
162
  try {
180
- await ensureDir(dirname2(filePath));
163
+ await ensureDir(dirname(filePath));
181
164
  await writeFile(filePath, JSON.stringify(result.data, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
182
165
  } catch (err) {
183
166
  return Result2.error(new StorageError(`Failed to write ${filePath}`, err instanceof Error ? err : void 0));
@@ -186,7 +169,7 @@ ${issues}`, filePath, result.error)
186
169
  }
187
170
  async function appendToFile(filePath, content) {
188
171
  try {
189
- await ensureDir(dirname2(filePath));
172
+ await ensureDir(dirname(filePath));
190
173
  await appendFile(filePath, content, { encoding: "utf-8", mode: 384 });
191
174
  return Result2.ok(void 0);
192
175
  } catch (err) {
@@ -205,13 +188,16 @@ async function readTextFile(filePath) {
205
188
  }
206
189
  }
207
190
 
208
- // src/schemas/index.ts
191
+ // src/domain/models.ts
209
192
  import { z } from "zod";
210
193
  var SprintStatusSchema = z.enum(["draft", "active", "closed"]);
211
194
  var TaskStatusSchema = z.enum(["todo", "in_progress", "done"]);
212
195
  var RequirementStatusSchema = z.enum(["pending", "approved"]);
213
- var EvaluationStatusSchema = z.enum(["passed", "failed", "malformed"]);
196
+ var EvaluationStatusSchema = z.enum(["passed", "failed", "malformed", "plateau"]);
197
+ var IdSchema = z.string().min(1);
214
198
  var RepositorySchema = z.object({
199
+ id: IdSchema,
200
+ // UUID8, stable across renames
215
201
  name: z.string().min(1),
216
202
  // Auto-derived from basename(path)
217
203
  path: z.string().min(1),
@@ -222,6 +208,7 @@ var RepositorySchema = z.object({
222
208
  // Per-repo timeout in ms (overrides RALPHCTL_SETUP_TIMEOUT_MS)
223
209
  });
224
210
  var ProjectSchema = z.object({
211
+ id: IdSchema,
225
212
  name: z.string().min(1).regex(/^[a-z0-9-]+$/, "Project name must be a slug (lowercase, numbers, hyphens only)"),
226
213
  displayName: z.string().min(1),
227
214
  repositories: z.array(RepositorySchema).min(1),
@@ -229,21 +216,19 @@ var ProjectSchema = z.object({
229
216
  });
230
217
  var ProjectsSchema = z.array(ProjectSchema);
231
218
  var TicketSchema = z.object({
232
- id: z.string().min(1),
233
- // Internal UUID8 (auto-generated)
219
+ id: IdSchema,
220
+ // UUID8
234
221
  title: z.string().min(1),
235
222
  description: z.string().optional(),
236
223
  link: z.url().optional(),
237
- projectName: z.string().min(1),
238
- // References Project.name
239
- affectedRepositories: z.array(z.string()).optional(),
240
- // Repository paths selected during planning
224
+ affectedRepoIds: z.array(IdSchema).optional(),
225
+ // Subset of sprint's project's repos
241
226
  requirementStatus: RequirementStatusSchema.default("pending"),
242
227
  requirements: z.string().optional()
243
- // Refined requirements (set during sprint refine)
228
+ // Set during sprint refine
244
229
  });
245
230
  var TaskSchema = z.object({
246
- id: z.string().min(1),
231
+ id: IdSchema,
247
232
  // UUID8
248
233
  name: z.string().min(1),
249
234
  description: z.string().optional(),
@@ -251,37 +236,31 @@ var TaskSchema = z.object({
251
236
  verificationCriteria: z.array(z.string()).default([]),
252
237
  status: TaskStatusSchema.default("todo"),
253
238
  order: z.number().int().positive(),
254
- ticketId: z.string().optional(),
255
- // References Ticket.id (internal)
256
- blockedBy: z.array(z.string()).default([]),
257
- projectPath: z.string().min(1),
258
- // Single path for execution
239
+ ticketId: IdSchema.optional(),
240
+ blockedBy: z.array(IdSchema).default([]),
241
+ repoId: IdSchema,
242
+ // Required — resolves to an absolute path at runtime
259
243
  verified: z.boolean().default(false),
260
- // Whether verification passed
261
244
  verificationOutput: z.string().optional(),
262
- // Output from verification run
263
245
  evaluated: z.boolean().default(false),
264
- // Whether evaluation passed
265
246
  evaluationOutput: z.string().optional(),
266
- // Truncated output from evaluation run (full critique lives in evaluationFile)
267
247
  evaluationStatus: EvaluationStatusSchema.optional(),
268
- // Discriminator: 'passed' | 'failed' | 'malformed'
269
- evaluationFile: z.string().optional()
270
- // Sidecar file path containing the full untruncated critique
248
+ evaluationFile: z.string().optional(),
249
+ // Planner-emitted extra evaluator dimensions; floor-only when undefined.
250
+ extraDimensions: z.array(z.string().min(1)).optional()
271
251
  });
272
252
  var TasksSchema = z.array(TaskSchema);
273
253
  var ImportTaskSchema = z.object({
274
254
  id: z.string().optional(),
275
255
  // Local ID for referencing in blockedBy
276
256
  name: z.string().min(1),
277
- // Required
278
257
  description: z.string().optional(),
279
258
  steps: z.array(z.string()).optional(),
280
259
  verificationCriteria: z.array(z.string()).optional(),
281
260
  ticketId: z.string().optional(),
282
261
  blockedBy: z.array(z.string()).optional(),
283
- projectPath: z.string().min(1)
284
- // Required - execution directory
262
+ repoId: IdSchema,
263
+ extraDimensions: z.array(z.string().min(1)).optional()
285
264
  });
286
265
  var ImportTasksSchema = z.array(ImportTaskSchema);
287
266
  var RefinedRequirementSchema = z.object({
@@ -296,12 +275,14 @@ var IdeateOutputSchema = z.object({
296
275
  var SprintSchema = z.object({
297
276
  id: z.string().regex(/^\d{8}-\d{6}-[a-z0-9-]+$/, "Invalid sprint ID format"),
298
277
  name: z.string().min(1),
278
+ projectId: IdSchema,
279
+ // Every sprint belongs to exactly one project
299
280
  status: SprintStatusSchema.default("draft"),
300
281
  createdAt: z.iso.datetime(),
301
282
  activatedAt: z.iso.datetime().nullable().default(null),
302
283
  closedAt: z.iso.datetime().nullable().default(null),
303
284
  tickets: z.array(TicketSchema).default([]),
304
- checkRanAt: z.record(z.string(), z.iso.datetime()).default({}),
285
+ checkRanAt: z.record(IdSchema, z.iso.datetime()).default({}),
305
286
  branch: z.string().nullable().default(null)
306
287
  });
307
288
  var AiProviderSchema = z.enum(["claude", "copilot"]);
@@ -311,6 +292,28 @@ var ConfigSchema = z.object({
311
292
  editor: z.string().nullable().default(null),
312
293
  evaluationIterations: z.number().int().min(0).optional()
313
294
  });
295
+ function getRequirementsOutputJsonSchema() {
296
+ return JSON.stringify(z.toJSONSchema(RefinedRequirementsSchema), null, 2);
297
+ }
298
+ function getTaskImportJsonSchema() {
299
+ return JSON.stringify(z.toJSONSchema(ImportTasksSchema), null, 2);
300
+ }
301
+
302
+ // src/domain/ids.ts
303
+ import { randomBytes } from "crypto";
304
+ function generateUuid8() {
305
+ return randomBytes(4).toString("hex");
306
+ }
307
+ function slugify(input, maxLength = 40) {
308
+ return input.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").replace(/-{2,}/g, "-").slice(0, maxLength).replace(/-$/, "");
309
+ }
310
+ function generateSprintId(name) {
311
+ const now = /* @__PURE__ */ new Date();
312
+ const date = now.toISOString().slice(0, 10).replace(/-/g, "");
313
+ const time = now.toISOString().slice(11, 19).replace(/:/g, "");
314
+ const slug = name ? slugify(name) : generateUuid8();
315
+ return `${date}-${time}-${slug || generateUuid8()}`;
316
+ }
314
317
 
315
318
  export {
316
319
  getDataDir,
@@ -324,8 +327,7 @@ export {
324
327
  getEvaluationFilePath,
325
328
  getRefinementDir,
326
329
  getPlanningDir,
327
- getIdeateDir,
328
- getSchemaPath,
330
+ getIdeationDir,
329
331
  assertSafeCwd,
330
332
  expandTilde,
331
333
  validateProjectPath,
@@ -346,6 +348,9 @@ export {
346
348
  RefinedRequirementsSchema,
347
349
  IdeateOutputSchema,
348
350
  SprintSchema,
349
- AiProviderSchema,
350
- ConfigSchema
351
+ ConfigSchema,
352
+ getRequirementsOutputJsonSchema,
353
+ getTaskImportJsonSchema,
354
+ generateUuid8,
355
+ generateSprintId
351
356
  };
@@ -1,26 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
- escapableSelect
4
- } from "./chunk-7LZ6GOGN.mjs";
3
+ createProject
4
+ } from "./chunk-NUYQK5MN.mjs";
5
5
  import {
6
6
  EXIT_ERROR,
7
7
  exitWithCode
8
- } from "./chunk-7TG3EAQ2.mjs";
9
- import {
10
- createProject
11
- } from "./chunk-EUNAUHC3.mjs";
8
+ } from "./chunk-CFUVE2BP.mjs";
12
9
  import {
13
- ensureError,
14
- wrapAsync
15
- } from "./chunk-OEUJDSHY.mjs";
16
- import {
17
- expandTilde,
18
- validateProjectPath
19
- } from "./chunk-IB6OCKZW.mjs";
20
- import {
21
- IOError,
22
- ProjectExistsError
23
- } from "./chunk-EDJX7TT6.mjs";
10
+ getPrompt
11
+ } from "./chunk-747KW2RW.mjs";
24
12
  import {
25
13
  createSpinner,
26
14
  emoji,
@@ -33,19 +21,74 @@ import {
33
21
  showSuccess,
34
22
  showTip,
35
23
  showWarning
36
- } from "./chunk-QBXHAXHI.mjs";
24
+ } from "./chunk-FKMKOWLA.mjs";
25
+ import {
26
+ ensureError,
27
+ wrapAsync
28
+ } from "./chunk-IWXBJD2D.mjs";
29
+ import {
30
+ expandTilde,
31
+ validateProjectPath
32
+ } from "./chunk-CTP2A436.mjs";
33
+ import {
34
+ IOError,
35
+ ProjectExistsError
36
+ } from "./chunk-57UWLHRH.mjs";
37
37
 
38
- // src/commands/project/add.ts
38
+ // src/integration/cli/commands/project/add.ts
39
39
  import { existsSync as existsSync2, statSync as statSync2 } from "fs";
40
40
  import { basename, join as join3, resolve as resolve2 } from "path";
41
- import { input, select } from "@inquirer/prompts";
42
41
  import { Result as Result3 } from "typescript-result";
43
42
 
44
- // src/interactive/file-browser.ts
43
+ // src/integration/ui/prompts/file-browser-impl.ts
45
44
  import { readdirSync, statSync } from "fs";
46
45
  import { homedir } from "os";
47
46
  import { dirname, join, resolve } from "path";
48
47
  import { Result } from "typescript-result";
48
+
49
+ // src/business/ports/prompt.ts
50
+ var PromptCancelledError = class extends Error {
51
+ constructor(message = "Prompt cancelled by user") {
52
+ super(message);
53
+ this.name = "PromptCancelledError";
54
+ }
55
+ };
56
+
57
+ // src/integration/ui/prompts/escapable.ts
58
+ function isChoice(item) {
59
+ return "value" in item && "name" in item;
60
+ }
61
+ async function escapableSelect(config) {
62
+ const choices = config.choices.map(
63
+ (item) => {
64
+ if (isChoice(item)) {
65
+ return {
66
+ label: item.name,
67
+ value: item.value,
68
+ description: item.description,
69
+ disabled: item.disabled
70
+ };
71
+ }
72
+ return {
73
+ label: item.separator,
74
+ value: void 0,
75
+ disabled: true
76
+ };
77
+ }
78
+ );
79
+ try {
80
+ return await getPrompt().select({
81
+ message: config.message,
82
+ choices,
83
+ default: config.default
84
+ });
85
+ } catch (err) {
86
+ if (err instanceof PromptCancelledError) return null;
87
+ throw err;
88
+ }
89
+ }
90
+
91
+ // src/integration/ui/prompts/file-browser-impl.ts
49
92
  function listDirectories(dirPath) {
50
93
  const r = Result.try(() => readdirSync(dirPath, { withFileTypes: true }));
51
94
  if (!r.ok) return [];
@@ -110,9 +153,7 @@ async function browseDirectory(message = "Browse to directory:", startPath) {
110
153
  () => escapableSelect({
111
154
  message: `${emoji.donut} ${message}
112
155
  ${muted(currentPath)}`,
113
- choices,
114
- pageSize: 15,
115
- loop: false
156
+ choices
116
157
  }),
117
158
  ensureError
118
159
  );
@@ -141,7 +182,7 @@ async function browseDirectory(message = "Browse to directory:", startPath) {
141
182
  }
142
183
  }
143
184
 
144
- // src/utils/detect-scripts.ts
185
+ // src/integration/external/detect-scripts.ts
145
186
  import { existsSync, readFileSync } from "fs";
146
187
  import { join as join2 } from "path";
147
188
  import { Result as Result2 } from "typescript-result";
@@ -287,7 +328,7 @@ function suggestCheckScript(projectPath) {
287
328
  return parts.length > 0 ? parts.join(" && ") : null;
288
329
  }
289
330
 
290
- // src/commands/project/add.ts
331
+ // src/integration/cli/commands/project/add.ts
291
332
  function validateSlug(slug) {
292
333
  return /^[a-z0-9-]+$/.test(slug);
293
334
  }
@@ -306,7 +347,7 @@ async function addCheckScriptToRepository(repo) {
306
347
  log.success(` Detected: ${detectR.value.typeLabel}`);
307
348
  suggested = suggestCheckScript(repo.path);
308
349
  }
309
- const checkInput = await input({
350
+ const checkInput = await getPrompt().input({
310
351
  message: " Check script (optional):",
311
352
  default: suggested ?? void 0
312
353
  });
@@ -366,7 +407,7 @@ async function projectAddCommand(options = {}) {
366
407
  const trimmedDesc = options.description?.trim();
367
408
  description = trimmedDesc === "" ? void 0 : trimmedDesc;
368
409
  } else {
369
- name = await input({
410
+ name = await getPrompt().input({
370
411
  message: "Project name (slug):",
371
412
  default: options.name?.trim(),
372
413
  validate: (v) => {
@@ -377,7 +418,7 @@ async function projectAddCommand(options = {}) {
377
418
  }
378
419
  });
379
420
  name = name.trim();
380
- displayName = await input({
421
+ displayName = await getPrompt().input({
381
422
  message: "Display name:",
382
423
  default: options.displayName?.trim() ?? name,
383
424
  validate: (v) => v.trim().length > 0 ? true : "Display name is required"
@@ -394,12 +435,12 @@ async function projectAddCommand(options = {}) {
394
435
  }
395
436
  }
396
437
  if (repositories.length === 0) {
397
- const pathMethod = await select({
438
+ const pathMethod = await getPrompt().select({
398
439
  message: `${emoji.donut} How to specify repository path?`,
399
440
  choices: [
400
- { name: "Browse filesystem", value: "browse", description: "Navigate from home folder" },
401
- { name: "Use current directory", value: "cwd", description: process.cwd() },
402
- { name: "Type path manually", value: "manual" }
441
+ { label: "Browse filesystem", value: "browse", description: "Navigate from home folder" },
442
+ { label: "Use current directory", value: "cwd", description: process.cwd() },
443
+ { label: "Type path manually", value: "manual" }
403
444
  ]
404
445
  });
405
446
  let firstPath;
@@ -413,7 +454,7 @@ async function projectAddCommand(options = {}) {
413
454
  } else if (pathMethod === "cwd") {
414
455
  firstPath = process.cwd();
415
456
  } else {
416
- firstPath = await input({
457
+ firstPath = await getPrompt().input({
417
458
  message: "Repository path:",
418
459
  default: process.cwd(),
419
460
  validate: async (v) => {
@@ -440,17 +481,17 @@ async function projectAddCommand(options = {}) {
440
481
  showTip("Add CLAUDE.md or .github/copilot-instructions.md for better AI assistance");
441
482
  }
442
483
  log.info(`
443
- Configuring: ${firstRepo.name}`);
484
+ Configuring: ${firstRepo.name ?? basename(firstRepo.path)}`);
444
485
  repositories[0] = await addCheckScriptToRepository(firstRepo);
445
486
  }
446
487
  let addMore = true;
447
488
  while (addMore) {
448
- const addAction = await select({
489
+ const addAction = await getPrompt().select({
449
490
  message: `${emoji.donut} Add another repository?`,
450
491
  choices: [
451
- { name: "No, done adding repositories", value: "done" },
452
- { name: "Browse filesystem", value: "browse" },
453
- { name: "Type path manually", value: "manual" }
492
+ { label: "No, done adding repositories", value: "done" },
493
+ { label: "Browse filesystem", value: "browse" },
494
+ { label: "Type path manually", value: "manual" }
454
495
  ]
455
496
  });
456
497
  if (addAction === "done") {
@@ -470,7 +511,7 @@ Configuring: ${firstRepo.name}`);
470
511
  }
471
512
  }
472
513
  } else {
473
- const additionalPath = await input({
514
+ const additionalPath = await getPrompt().input({
474
515
  message: "Repository path:"
475
516
  });
476
517
  if (additionalPath.trim() === "") {
@@ -489,7 +530,7 @@ Configuring: ${firstRepo.name}`);
489
530
  }
490
531
  }
491
532
  }
492
- description = await input({
533
+ description = await getPrompt().input({
493
534
  message: "Description (optional):",
494
535
  default: options.description?.trim()
495
536
  });
@@ -534,6 +575,8 @@ Configuring: ${firstRepo.name}`);
534
575
  }
535
576
 
536
577
  export {
578
+ PromptCancelledError,
579
+ escapableSelect,
537
580
  addCheckScriptToRepository,
538
581
  projectAddCommand
539
582
  };