ralphctl 0.5.0 → 0.6.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 (58) hide show
  1. package/README.md +29 -16
  2. package/dist/absolute-path-WUTZQ37D.mjs +8 -0
  3. package/dist/chunk-6RDMCLWU.mjs +108 -0
  4. package/dist/chunk-HIU74KTO.mjs +1046 -0
  5. package/dist/chunk-S3PTDH57.mjs +78 -0
  6. package/dist/chunk-WV4D2CPG.mjs +26 -0
  7. package/dist/cli.mjs +22413 -717
  8. package/dist/manifest.json +24 -0
  9. package/dist/prompt-adapter-JQICGVX7.mjs +7 -0
  10. package/dist/prompts/ideate.md +3 -1
  11. package/dist/prompts/plan-auto.md +23 -8
  12. package/dist/prompts/plan-common-examples.md +3 -3
  13. package/dist/prompts/plan-common.md +6 -5
  14. package/dist/prompts/plan-interactive.md +30 -7
  15. package/dist/prompts/repo-onboard.md +154 -64
  16. package/dist/prompts/signals-task.md +3 -0
  17. package/dist/prompts/sprint-feedback.md +3 -0
  18. package/dist/prompts/task-evaluation.md +74 -53
  19. package/dist/prompts/task-execution.md +65 -21
  20. package/dist/prompts/ticket-refine.md +11 -8
  21. package/dist/prompts/validation-checklist.md +3 -2
  22. package/dist/skills/default/abstraction-first/SKILL.md +45 -0
  23. package/dist/skills/default/alignment/SKILL.md +46 -0
  24. package/dist/skills/default/iterative-review/SKILL.md +48 -0
  25. package/dist/skills/exec/.gitkeep +0 -0
  26. package/dist/skills/plan/.gitkeep +0 -0
  27. package/dist/skills/refine/.gitkeep +0 -0
  28. package/dist/storage-paths-IPNZZM5D.mjs +15 -0
  29. package/dist/validation-error-QT6Q7FYU.mjs +7 -0
  30. package/package.json +9 -4
  31. package/dist/add-67UFUI54.mjs +0 -17
  32. package/dist/add-DVPVHENV.mjs +0 -18
  33. package/dist/bootstrap-FMHG6DRY.mjs +0 -11
  34. package/dist/chunk-62HYDA7L.mjs +0 -1128
  35. package/dist/chunk-747KW2RW.mjs +0 -24
  36. package/dist/chunk-BSB4EDGR.mjs +0 -260
  37. package/dist/chunk-BT5FKIZX.mjs +0 -787
  38. package/dist/chunk-CBMFRQ4Y.mjs +0 -441
  39. package/dist/chunk-CFUVE2BP.mjs +0 -16
  40. package/dist/chunk-D6QZNEYN.mjs +0 -5520
  41. package/dist/chunk-FNAAA32W.mjs +0 -103
  42. package/dist/chunk-GQ2WFKBN.mjs +0 -269
  43. package/dist/chunk-IWXBJD2D.mjs +0 -27
  44. package/dist/chunk-OGEXYSFS.mjs +0 -228
  45. package/dist/chunk-VAZ3LJBI.mjs +0 -179
  46. package/dist/chunk-WDMLPXOD.mjs +0 -363
  47. package/dist/chunk-XN2UIHBY.mjs +0 -589
  48. package/dist/chunk-ZE2BRQA2.mjs +0 -5542
  49. package/dist/create-Z635FQKO.mjs +0 -15
  50. package/dist/handle-23EFF3BE.mjs +0 -22
  51. package/dist/mount-NCYR22SN.mjs +0 -7434
  52. package/dist/project-DQHF4ISP.mjs +0 -34
  53. package/dist/prompts/check-script-discover.md +0 -69
  54. package/dist/prompts/ideate-auto.md +0 -195
  55. package/dist/prompts/task-evaluation-resume.md +0 -41
  56. package/dist/resolver-OVPYVW6Q.mjs +0 -163
  57. package/dist/sprint-4E26AB5F.mjs +0 -38
  58. package/dist/start-T34NI3LF.mjs +0 -19
@@ -1,179 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- // src/domain/errors.ts
4
- var DomainError = class extends Error {
5
- cause;
6
- constructor(message, cause) {
7
- super(message, cause ? { cause } : void 0);
8
- this.name = this.constructor.name;
9
- this.cause = cause;
10
- }
11
- };
12
- var IOError = class extends DomainError {
13
- code = "IO_ERROR";
14
- };
15
- var StorageError = class extends DomainError {
16
- code = "STORAGE_ERROR";
17
- };
18
- var LockError = class extends DomainError {
19
- code = "LOCK_ERROR";
20
- lockPath;
21
- constructor(message, lockPath, cause) {
22
- super(message, cause);
23
- this.lockPath = lockPath;
24
- }
25
- };
26
- var ParseError = class extends DomainError {
27
- code = "PARSE_ERROR";
28
- };
29
- var ValidationError = class extends DomainError {
30
- code = "VALIDATION_ERROR";
31
- path;
32
- constructor(message, path, cause) {
33
- super(message, cause);
34
- this.path = path;
35
- }
36
- };
37
- function detectSpawnRateLimit(stderr) {
38
- const patterns = [/rate.?limit/i, /\b429\b/, /too many requests/i, /overloaded/i, /\b529\b/];
39
- const isRateLimited = patterns.some((p) => p.test(stderr));
40
- if (!isRateLimited) return { rateLimited: false, retryAfterMs: null };
41
- const retryMatch = /retry.?after:?\s*(\d+)/i.exec(stderr);
42
- const retryAfterMs = retryMatch?.[1] ? parseInt(retryMatch[1], 10) * 1e3 : null;
43
- return { rateLimited: true, retryAfterMs };
44
- }
45
- var SpawnError = class extends DomainError {
46
- code = "SPAWN_ERROR";
47
- stderr;
48
- exitCode;
49
- rateLimited;
50
- retryAfterMs;
51
- sessionId;
52
- constructor(message, stderr, exitCode, sessionId, cause) {
53
- super(message, cause);
54
- this.stderr = stderr;
55
- this.exitCode = exitCode;
56
- this.sessionId = sessionId ?? null;
57
- const rl = detectSpawnRateLimit(stderr);
58
- this.rateLimited = rl.rateLimited;
59
- this.retryAfterMs = rl.retryAfterMs;
60
- }
61
- };
62
- var SprintNotFoundError = class extends DomainError {
63
- code = "SPRINT_NOT_FOUND";
64
- sprintId;
65
- constructor(sprintId) {
66
- super(`Sprint not found: ${sprintId}`);
67
- this.sprintId = sprintId;
68
- }
69
- };
70
- var TaskNotFoundError = class extends DomainError {
71
- code = "TASK_NOT_FOUND";
72
- taskId;
73
- constructor(taskId) {
74
- super(`Task not found: ${taskId}`);
75
- this.taskId = taskId;
76
- }
77
- };
78
- var TicketNotFoundError = class extends DomainError {
79
- code = "TICKET_NOT_FOUND";
80
- ticketId;
81
- constructor(ticketId) {
82
- super(`Ticket not found: ${ticketId}`);
83
- this.ticketId = ticketId;
84
- }
85
- };
86
- var ProjectNotFoundError = class extends DomainError {
87
- code = "PROJECT_NOT_FOUND";
88
- projectName;
89
- constructor(projectName) {
90
- super(`Project not found: ${projectName}`);
91
- this.projectName = projectName;
92
- }
93
- };
94
- var ProjectExistsError = class extends DomainError {
95
- code = "PROJECT_EXISTS";
96
- projectName;
97
- constructor(projectName) {
98
- super(`Project already exists: ${projectName}`);
99
- this.projectName = projectName;
100
- }
101
- };
102
- var StatusError = class extends DomainError {
103
- code = "STATUS_ERROR";
104
- };
105
- var SprintStatusError = class extends StatusError {
106
- currentStatus;
107
- operation;
108
- constructor(message, currentStatus, operation) {
109
- super(message);
110
- this.currentStatus = currentStatus;
111
- this.operation = operation;
112
- }
113
- };
114
- var NoCurrentSprintError = class extends StatusError {
115
- constructor() {
116
- super("No sprint specified and no current sprint set.");
117
- }
118
- };
119
- var DependencyCycleError = class extends DomainError {
120
- code = "DEPENDENCY_CYCLE";
121
- cycle;
122
- constructor(cycle) {
123
- super(`Dependency cycle detected: ${cycle.join(" \u2192 ")}`);
124
- this.cycle = cycle;
125
- }
126
- };
127
- var IssueFetchError = class extends DomainError {
128
- code = "ISSUE_FETCH_ERROR";
129
- };
130
- var StepError = class extends DomainError {
131
- code = "STEP_ERROR";
132
- stepName;
133
- constructor(message, stepName, cause) {
134
- super(message, cause);
135
- this.stepName = stepName;
136
- }
137
- };
138
- var BranchPreflightError = class extends DomainError {
139
- code = "BRANCH_PREFLIGHT_ERROR";
140
- projectPath;
141
- expectedBranch;
142
- constructor(projectPath, expectedBranch, cause) {
143
- super(`Branch verification failed: expected '${expectedBranch}' in ${projectPath}`, cause);
144
- this.projectPath = projectPath;
145
- this.expectedBranch = expectedBranch;
146
- }
147
- };
148
- var ExecutionAlreadyRunningError = class extends DomainError {
149
- code = "EXECUTION_ALREADY_RUNNING";
150
- projectName;
151
- existingExecutionId;
152
- constructor(projectName, existingExecutionId) {
153
- super(`An execution is already running for project '${projectName}' (id: ${existingExecutionId}).`);
154
- this.projectName = projectName;
155
- this.existingExecutionId = existingExecutionId;
156
- }
157
- };
158
-
159
- export {
160
- DomainError,
161
- IOError,
162
- StorageError,
163
- LockError,
164
- ParseError,
165
- ValidationError,
166
- SpawnError,
167
- SprintNotFoundError,
168
- TaskNotFoundError,
169
- TicketNotFoundError,
170
- ProjectNotFoundError,
171
- ProjectExistsError,
172
- SprintStatusError,
173
- NoCurrentSprintError,
174
- DependencyCycleError,
175
- IssueFetchError,
176
- StepError,
177
- BranchPreflightError,
178
- ExecutionAlreadyRunningError
179
- };
@@ -1,363 +0,0 @@
1
- #!/usr/bin/env node
2
- import {
3
- IOError,
4
- StorageError,
5
- ValidationError
6
- } from "./chunk-VAZ3LJBI.mjs";
7
-
8
- // src/integration/persistence/paths.ts
9
- import { isAbsolute, join, resolve, sep } from "path";
10
- import { homedir } from "os";
11
- import { lstat, realpath, stat } from "fs/promises";
12
- import { Result } from "typescript-result";
13
- function getDataDir() {
14
- return process.env["RALPHCTL_ROOT"] ?? join(homedir(), ".ralphctl");
15
- }
16
- function getConfigPath() {
17
- return join(getDataDir(), "config.json");
18
- }
19
- function getProjectsFilePath() {
20
- return join(getDataDir(), "projects.json");
21
- }
22
- function getSprintsDir() {
23
- return join(getDataDir(), "sprints");
24
- }
25
- function getSprintDir(sprintId) {
26
- const sprintsDir = getSprintsDir();
27
- const resolved = resolve(sprintsDir, sprintId);
28
- if (!resolved.startsWith(sprintsDir + sep) && resolved !== sprintsDir) {
29
- throw new Error(`Path traversal detected in sprint ID: ${sprintId}`);
30
- }
31
- return resolved;
32
- }
33
- function getSprintFilePath(sprintId) {
34
- return join(getSprintDir(sprintId), "sprint.json");
35
- }
36
- function getTasksFilePath(sprintId) {
37
- return join(getSprintDir(sprintId), "tasks.json");
38
- }
39
- function getProgressFilePath(sprintId) {
40
- return join(getSprintDir(sprintId), "progress.md");
41
- }
42
- function getEvaluationsDir(sprintId) {
43
- return join(getSprintDir(sprintId), "evaluations");
44
- }
45
- function getEvaluationFilePath(sprintId, taskId) {
46
- assertSafeSegment(taskId, "task ID");
47
- return join(getEvaluationsDir(sprintId), `${taskId}.md`);
48
- }
49
- function assertSafeSegment(segment, label) {
50
- if (!segment || segment.includes("/") || segment.includes("\\") || segment.includes("..") || segment.includes("\0")) {
51
- throw new Error(`Path traversal detected in ${label}: ${segment}`);
52
- }
53
- }
54
- function getRefinementDir(sprintId, ticketId) {
55
- assertSafeSegment(ticketId, "ticket ID");
56
- return join(getSprintDir(sprintId), "refinement", ticketId);
57
- }
58
- function getPlanningDir(sprintId) {
59
- return join(getSprintDir(sprintId), "planning");
60
- }
61
- function getIdeationDir(sprintId, ticketId) {
62
- assertSafeSegment(ticketId, "ticket ID");
63
- return join(getSprintDir(sprintId), "ideation", ticketId);
64
- }
65
- function assertSafeCwd(path) {
66
- if (!path || path.includes("\0") || path.includes("\n") || path.includes("\r")) {
67
- throw new Error("Unsafe path for cwd: contains null bytes or newlines");
68
- }
69
- if (!isAbsolute(path)) {
70
- throw new Error(`Unsafe path for cwd: must be absolute, got: ${path}`);
71
- }
72
- }
73
- function expandTilde(path) {
74
- if (path === "~") return homedir();
75
- if (path.startsWith("~/")) return homedir() + path.slice(1);
76
- return path;
77
- }
78
- async function validateProjectPath(path) {
79
- try {
80
- const resolved = resolve(expandTilde(path));
81
- const lstats = await lstat(resolved);
82
- if (lstats.isSymbolicLink()) {
83
- const realPath = await realpath(resolved);
84
- const realStats = await stat(realPath);
85
- if (!realStats.isDirectory()) {
86
- return Result.error(new IOError("Symlink target is not a directory"));
87
- }
88
- return Result.ok(true);
89
- }
90
- if (!lstats.isDirectory()) {
91
- return Result.error(new IOError("Path is not a directory"));
92
- }
93
- return Result.ok(true);
94
- } catch (err) {
95
- const code = err.code;
96
- const message = code === "EACCES" ? "Permission denied" : "Directory does not exist";
97
- return Result.error(new IOError(message, err instanceof Error ? err : void 0));
98
- }
99
- }
100
-
101
- // src/integration/persistence/storage.ts
102
- import { access, appendFile, mkdir, readdir, readFile, rm, writeFile } from "fs/promises";
103
- import { dirname } from "path";
104
- import { Result as Result2 } from "typescript-result";
105
- async function ensureDir(dirPath) {
106
- await mkdir(dirPath, { recursive: true });
107
- }
108
- async function removeDir(dirPath) {
109
- await rm(dirPath, { recursive: true, force: true });
110
- }
111
- async function fileExists(filePath) {
112
- try {
113
- await access(filePath);
114
- return true;
115
- } catch {
116
- return false;
117
- }
118
- }
119
- async function listDirs(dirPath) {
120
- try {
121
- const entries = await readdir(dirPath, { withFileTypes: true });
122
- return entries.filter((e) => e.isDirectory()).map((e) => e.name);
123
- } catch {
124
- return [];
125
- }
126
- }
127
- async function readValidatedJson(filePath, schema) {
128
- let content;
129
- try {
130
- content = await readFile(filePath, "utf-8");
131
- } catch (err) {
132
- if (err instanceof Error && "code" in err && err.code === "ENOENT") {
133
- return Result2.error(new StorageError(`File not found: ${filePath}`, err instanceof Error ? err : void 0));
134
- }
135
- return Result2.error(new StorageError(`Failed to read ${filePath}`, err instanceof Error ? err : void 0));
136
- }
137
- let data;
138
- try {
139
- data = JSON.parse(content);
140
- } catch (err) {
141
- return Result2.error(
142
- new ValidationError(`Invalid JSON in ${filePath}`, filePath, err instanceof Error ? err : void 0)
143
- );
144
- }
145
- const result = schema.safeParse(data);
146
- if (!result.success) {
147
- const issues = result.error.issues.map((i) => ` - ${i.path.join(".")}: ${i.message}`).join("\n");
148
- return Result2.error(new ValidationError(`Validation failed for ${filePath}:
149
- ${issues}`, filePath, result.error));
150
- }
151
- return Result2.ok(result.data);
152
- }
153
- async function writeValidatedJson(filePath, data, schema) {
154
- const result = schema.safeParse(data);
155
- if (!result.success) {
156
- const issues = result.error.issues.map((i) => ` - ${i.path.join(".")}: ${i.message}`).join("\n");
157
- return Result2.error(
158
- new ValidationError(`Validation failed before writing to ${filePath}:
159
- ${issues}`, filePath, result.error)
160
- );
161
- }
162
- try {
163
- await ensureDir(dirname(filePath));
164
- await writeFile(filePath, JSON.stringify(result.data, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
165
- } catch (err) {
166
- return Result2.error(new StorageError(`Failed to write ${filePath}`, err instanceof Error ? err : void 0));
167
- }
168
- return Result2.ok(void 0);
169
- }
170
- async function appendToFile(filePath, content) {
171
- try {
172
- await ensureDir(dirname(filePath));
173
- await appendFile(filePath, content, { encoding: "utf-8", mode: 384 });
174
- return Result2.ok(void 0);
175
- } catch (err) {
176
- return Result2.error(new StorageError(`Failed to append to ${filePath}`, err instanceof Error ? err : void 0));
177
- }
178
- }
179
- async function readTextFile(filePath) {
180
- try {
181
- const content = await readFile(filePath, "utf-8");
182
- return Result2.ok(content);
183
- } catch (err) {
184
- if (err instanceof Error && "code" in err && err.code === "ENOENT") {
185
- return Result2.error(new StorageError(`File not found: ${filePath}`, err instanceof Error ? err : void 0));
186
- }
187
- return Result2.error(new StorageError(`Failed to read ${filePath}`, err instanceof Error ? err : void 0));
188
- }
189
- }
190
-
191
- // src/domain/models.ts
192
- import { z } from "zod";
193
- var SprintStatusSchema = z.enum(["draft", "active", "closed"]);
194
- var TaskStatusSchema = z.enum(["todo", "in_progress", "done", "cancelled"]);
195
- var RequirementStatusSchema = z.enum(["pending", "approved"]);
196
- var EvaluationStatusSchema = z.enum(["passed", "failed", "malformed", "plateau"]);
197
- var IdSchema = z.string().min(1);
198
- var CURRENT_ONBOARDING_VERSION = 1;
199
- var RepositorySchema = z.object({
200
- id: IdSchema,
201
- // UUID8, stable across renames
202
- name: z.string().min(1),
203
- // Auto-derived from basename(path)
204
- path: z.string().min(1),
205
- // Absolute path
206
- checkScript: z.string().optional(),
207
- // e.g., "pnpm install && pnpm typecheck && pnpm lint && pnpm test"
208
- checkTimeout: z.number().positive().optional(),
209
- // Per-repo timeout in ms (overrides RALPHCTL_SETUP_TIMEOUT_MS)
210
- // Stamped by `project onboard` on success. Absence means the repo was never
211
- // onboarded; `doctor` surfaces a hint. A value < CURRENT_ONBOARDING_VERSION
212
- // means the contract has drifted and re-onboarding is recommended.
213
- onboardingVersion: z.number().int().nonnegative().optional()
214
- });
215
- var ProjectSchema = z.object({
216
- id: IdSchema,
217
- name: z.string().min(1).regex(/^[a-z0-9-]+$/, "Project name must be a slug (lowercase, numbers, hyphens only)"),
218
- displayName: z.string().min(1),
219
- repositories: z.array(RepositorySchema).min(1),
220
- description: z.string().optional()
221
- });
222
- var ProjectsSchema = z.array(ProjectSchema);
223
- var TicketSchema = z.object({
224
- id: IdSchema,
225
- // UUID8
226
- title: z.string().min(1),
227
- description: z.string().optional(),
228
- link: z.url().optional(),
229
- affectedRepoIds: z.array(IdSchema).optional(),
230
- // Subset of sprint's project's repos
231
- requirementStatus: RequirementStatusSchema.default("pending"),
232
- requirements: z.string().optional()
233
- // Set during sprint refine
234
- });
235
- var TaskSchema = z.object({
236
- id: IdSchema,
237
- // UUID8
238
- name: z.string().min(1),
239
- description: z.string().optional(),
240
- steps: z.array(z.string()).default([]),
241
- verificationCriteria: z.array(z.string()).default([]),
242
- status: TaskStatusSchema.default("todo"),
243
- order: z.number().int().positive(),
244
- ticketId: IdSchema.optional(),
245
- blockedBy: z.array(IdSchema).default([]),
246
- repoId: IdSchema,
247
- // Required — resolves to an absolute path at runtime
248
- verified: z.boolean().default(false),
249
- verificationOutput: z.string().optional(),
250
- evaluated: z.boolean().default(false),
251
- evaluationOutput: z.string().optional(),
252
- evaluationStatus: EvaluationStatusSchema.optional(),
253
- evaluationFile: z.string().optional(),
254
- // Planner-emitted extra evaluator dimensions; floor-only when undefined.
255
- extraDimensions: z.array(z.string().min(1)).optional()
256
- });
257
- var TasksSchema = z.array(TaskSchema);
258
- var ImportTaskSchema = z.object({
259
- id: z.string().optional(),
260
- // Local ID for referencing in blockedBy
261
- name: z.string().min(1),
262
- description: z.string().optional(),
263
- steps: z.array(z.string()).optional(),
264
- verificationCriteria: z.array(z.string()).optional(),
265
- ticketId: z.string().optional(),
266
- blockedBy: z.array(z.string()).optional(),
267
- repoId: IdSchema,
268
- extraDimensions: z.array(z.string().min(1)).optional()
269
- });
270
- var ImportTasksSchema = z.array(ImportTaskSchema);
271
- var RefinedRequirementSchema = z.object({
272
- ref: z.string().min(1),
273
- requirements: z.string().min(1)
274
- });
275
- var RefinedRequirementsSchema = z.array(RefinedRequirementSchema);
276
- var IdeateOutputSchema = z.object({
277
- requirements: z.string().min(1),
278
- tasks: ImportTasksSchema
279
- });
280
- var SprintSchema = z.object({
281
- id: z.string().regex(/^\d{8}-\d{6}-[a-z0-9-]+$/, "Invalid sprint ID format"),
282
- name: z.string().min(1),
283
- projectId: IdSchema,
284
- // Every sprint belongs to exactly one project
285
- status: SprintStatusSchema.default("draft"),
286
- createdAt: z.iso.datetime(),
287
- activatedAt: z.iso.datetime().nullable().default(null),
288
- closedAt: z.iso.datetime().nullable().default(null),
289
- tickets: z.array(TicketSchema).default([]),
290
- checkRanAt: z.record(IdSchema, z.iso.datetime()).default({}),
291
- branch: z.string().nullable().default(null)
292
- });
293
- var AiProviderSchema = z.enum(["claude", "copilot"]);
294
- var ConfigSchema = z.object({
295
- currentSprint: z.string().nullable().default(null),
296
- aiProvider: AiProviderSchema.nullable().default(null),
297
- editor: z.string().nullable().default(null),
298
- evaluationIterations: z.number().int().min(0).optional(),
299
- aiCheckScriptDiscovery: z.boolean().optional()
300
- });
301
- function getRequirementsOutputJsonSchema() {
302
- return JSON.stringify(z.toJSONSchema(RefinedRequirementsSchema), null, 2);
303
- }
304
- function getTaskImportJsonSchema() {
305
- return JSON.stringify(z.toJSONSchema(ImportTasksSchema), null, 2);
306
- }
307
-
308
- // src/domain/ids.ts
309
- import { randomBytes } from "crypto";
310
- function generateUuid8() {
311
- return randomBytes(4).toString("hex");
312
- }
313
- function slugify(input, maxLength = 40) {
314
- return input.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").replace(/-{2,}/g, "-").slice(0, maxLength).replace(/-$/, "");
315
- }
316
- function generateSprintId(name) {
317
- const now = /* @__PURE__ */ new Date();
318
- const date = now.toISOString().slice(0, 10).replace(/-/g, "");
319
- const time = now.toISOString().slice(11, 19).replace(/:/g, "");
320
- const slug = name ? slugify(name) : generateUuid8();
321
- return `${date}-${time}-${slug || generateUuid8()}`;
322
- }
323
-
324
- export {
325
- getDataDir,
326
- getConfigPath,
327
- getProjectsFilePath,
328
- getSprintsDir,
329
- getSprintDir,
330
- getSprintFilePath,
331
- getTasksFilePath,
332
- getProgressFilePath,
333
- getEvaluationFilePath,
334
- getRefinementDir,
335
- getPlanningDir,
336
- getIdeationDir,
337
- assertSafeCwd,
338
- expandTilde,
339
- validateProjectPath,
340
- ensureDir,
341
- removeDir,
342
- fileExists,
343
- listDirs,
344
- readValidatedJson,
345
- writeValidatedJson,
346
- appendToFile,
347
- readTextFile,
348
- SprintStatusSchema,
349
- TaskStatusSchema,
350
- RequirementStatusSchema,
351
- CURRENT_ONBOARDING_VERSION,
352
- ProjectsSchema,
353
- TasksSchema,
354
- ImportTasksSchema,
355
- RefinedRequirementsSchema,
356
- IdeateOutputSchema,
357
- SprintSchema,
358
- ConfigSchema,
359
- getRequirementsOutputJsonSchema,
360
- getTaskImportJsonSchema,
361
- generateUuid8,
362
- generateSprintId
363
- };