ralphctl 0.2.5 → 0.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.
- package/dist/add-CIM72NE3.mjs +18 -0
- package/dist/add-GX7P7XTT.mjs +16 -0
- package/dist/bootstrap-FMHG6DRY.mjs +11 -0
- package/dist/chunk-3QBEBKMZ.mjs +103 -0
- package/dist/{chunk-EDJX7TT6.mjs → chunk-57UWLHRH.mjs} +22 -2
- package/dist/chunk-747KW2RW.mjs +24 -0
- package/dist/chunk-7JLZQICD.mjs +228 -0
- package/dist/{chunk-7TG3EAQ2.mjs → chunk-CFUVE2BP.mjs} +1 -5
- package/dist/chunk-CSC4TBJB.mjs +5546 -0
- package/dist/{chunk-IB6OCKZW.mjs → chunk-CTP2A436.mjs} +60 -55
- package/dist/{chunk-UBPZHHCD.mjs → chunk-D2YGPLIV.mjs} +84 -41
- package/dist/chunk-EPDR6VO5.mjs +5109 -0
- package/dist/{chunk-QBXHAXHI.mjs → chunk-FKMKOWLA.mjs} +154 -208
- package/dist/{chunk-OEUJDSHY.mjs → chunk-IWXBJD2D.mjs} +1 -1
- package/dist/chunk-JOQO4HMM.mjs +269 -0
- package/dist/{chunk-EUNAUHC3.mjs → chunk-NUYQK5MN.mjs} +80 -29
- package/dist/{chunk-JRFOUFD3.mjs → chunk-YCDUVPRT.mjs} +32 -52
- package/dist/cli.mjs +171 -3996
- package/dist/create-7WFSCMP4.mjs +15 -0
- package/dist/{handle-TA4MYNQJ.mjs → handle-BBAZJ44Y.mjs} +2 -2
- package/dist/mount-U7QXVB5Q.mjs +6804 -0
- package/dist/{project-YONEJICR.mjs → project-2IE7VWDB.mjs} +9 -5
- package/dist/prompts/harness-context.md +3 -3
- package/dist/prompts/ideate-auto.md +8 -10
- package/dist/prompts/ideate.md +3 -2
- package/dist/prompts/plan-auto.md +12 -12
- package/dist/prompts/plan-common.md +47 -19
- package/dist/prompts/plan-interactive.md +8 -8
- package/dist/prompts/signals-evaluation.md +1 -1
- package/dist/prompts/sprint-feedback.md +48 -0
- package/dist/prompts/task-evaluation-resume.md +12 -5
- package/dist/prompts/task-evaluation.md +37 -33
- package/dist/prompts/task-execution.md +33 -24
- package/dist/prompts/ticket-refine.md +6 -5
- package/dist/prompts/validation-checklist.md +10 -10
- package/dist/{resolver-RXEY6EJE.mjs → resolver-EOE5WUMV.mjs} +5 -5
- package/dist/{sprint-FGLWYWKX.mjs → sprint-OGOFEJJH.mjs} +7 -9
- package/dist/start-WG7VMEB2.mjs +17 -0
- package/package.json +15 -13
- package/dist/add-3T225IX5.mjs +0 -16
- package/dist/add-6A5432U2.mjs +0 -16
- package/dist/chunk-742XQ7FL.mjs +0 -551
- package/dist/chunk-7LZ6GOGN.mjs +0 -53
- package/dist/chunk-CSICORGV.mjs +0 -4333
- package/dist/chunk-DUU5346E.mjs +0 -59
- package/dist/create-MYGOWO2F.mjs +0 -12
- package/dist/multiline-OHSNFCRG.mjs +0 -40
- package/dist/wizard-XZ7OGBCJ.mjs +0 -193
- package/schemas/config.schema.json +0 -30
- package/schemas/ideate-output.schema.json +0 -22
- package/schemas/projects.schema.json +0 -58
- package/schemas/requirements-output.schema.json +0 -24
- package/schemas/sprint.schema.json +0 -109
- package/schemas/task-import.schema.json +0 -56
- package/schemas/tasks.schema.json +0 -98
|
@@ -3,27 +3,13 @@ import {
|
|
|
3
3
|
IOError,
|
|
4
4
|
StorageError,
|
|
5
5
|
ValidationError
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-57UWLHRH.mjs";
|
|
7
7
|
|
|
8
|
-
// src/
|
|
9
|
-
import {
|
|
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
|
|
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/
|
|
101
|
+
// src/integration/persistence/storage.ts
|
|
119
102
|
import { access, appendFile, mkdir, readdir, readFile, rm, writeFile } from "fs/promises";
|
|
120
|
-
import { dirname
|
|
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(
|
|
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(
|
|
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/
|
|
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:
|
|
233
|
-
//
|
|
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
|
-
|
|
238
|
-
//
|
|
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
|
-
//
|
|
228
|
+
// Set during sprint refine
|
|
244
229
|
});
|
|
245
230
|
var TaskSchema = z.object({
|
|
246
|
-
id:
|
|
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:
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
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
|
-
|
|
269
|
-
|
|
270
|
-
|
|
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
|
-
|
|
284
|
-
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
350
|
-
|
|
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
|
-
|
|
4
|
-
} from "./chunk-
|
|
3
|
+
createProject
|
|
4
|
+
} from "./chunk-NUYQK5MN.mjs";
|
|
5
5
|
import {
|
|
6
6
|
EXIT_ERROR,
|
|
7
7
|
exitWithCode
|
|
8
|
-
} from "./chunk-
|
|
9
|
-
import {
|
|
10
|
-
createProject
|
|
11
|
-
} from "./chunk-EUNAUHC3.mjs";
|
|
8
|
+
} from "./chunk-CFUVE2BP.mjs";
|
|
12
9
|
import {
|
|
13
|
-
|
|
14
|
-
|
|
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-
|
|
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/
|
|
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/
|
|
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
|
-
{
|
|
401
|
-
{
|
|
402
|
-
{
|
|
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
|
-
{
|
|
452
|
-
{
|
|
453
|
-
{
|
|
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
|
};
|