ralphctl 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (130) hide show
  1. package/README.md +58 -24
  2. package/dist/add-HGJCLWED.mjs +14 -0
  3. package/dist/add-MRGCS3US.mjs +14 -0
  4. package/dist/chunk-6PYTKGB5.mjs +316 -0
  5. package/dist/chunk-7TG3EAQ2.mjs +20 -0
  6. package/dist/chunk-EKMZZRWI.mjs +521 -0
  7. package/dist/chunk-JON4GCLR.mjs +59 -0
  8. package/dist/chunk-LOR7QBXX.mjs +3683 -0
  9. package/dist/chunk-MNMQC36F.mjs +556 -0
  10. package/dist/chunk-MRKOFVTM.mjs +537 -0
  11. package/dist/chunk-NTWO2LXB.mjs +52 -0
  12. package/dist/chunk-QBXHAXHI.mjs +562 -0
  13. package/dist/chunk-WGHJI3OI.mjs +214 -0
  14. package/dist/cli.mjs +4245 -0
  15. package/dist/create-MG7E7PLQ.mjs +10 -0
  16. package/dist/handle-UG5M2OON.mjs +22 -0
  17. package/dist/multiline-OHSNFCRG.mjs +40 -0
  18. package/dist/project-NT3L4FTB.mjs +28 -0
  19. package/dist/resolver-WSFWKACM.mjs +153 -0
  20. package/dist/sprint-4VHDLGFN.mjs +37 -0
  21. package/dist/wizard-LRELAN2J.mjs +196 -0
  22. package/package.json +19 -28
  23. package/CHANGELOG.md +0 -94
  24. package/bin/ralphctl +0 -13
  25. package/src/ai/executor.ts +0 -973
  26. package/src/ai/lifecycle.ts +0 -45
  27. package/src/ai/parser.ts +0 -40
  28. package/src/ai/permissions.ts +0 -207
  29. package/src/ai/process-manager.ts +0 -248
  30. package/src/ai/prompts/index.ts +0 -89
  31. package/src/ai/rate-limiter.ts +0 -89
  32. package/src/ai/runner.ts +0 -478
  33. package/src/ai/session.ts +0 -319
  34. package/src/ai/task-context.ts +0 -270
  35. package/src/cli-metadata.ts +0 -7
  36. package/src/cli.ts +0 -65
  37. package/src/commands/completion/index.ts +0 -33
  38. package/src/commands/config/config.ts +0 -58
  39. package/src/commands/config/index.ts +0 -33
  40. package/src/commands/dashboard/dashboard.ts +0 -5
  41. package/src/commands/dashboard/index.ts +0 -6
  42. package/src/commands/doctor/doctor.ts +0 -271
  43. package/src/commands/doctor/index.ts +0 -25
  44. package/src/commands/progress/index.ts +0 -25
  45. package/src/commands/progress/log.ts +0 -64
  46. package/src/commands/progress/show.ts +0 -14
  47. package/src/commands/project/add.ts +0 -336
  48. package/src/commands/project/index.ts +0 -104
  49. package/src/commands/project/list.ts +0 -31
  50. package/src/commands/project/remove.ts +0 -43
  51. package/src/commands/project/repo.ts +0 -118
  52. package/src/commands/project/show.ts +0 -49
  53. package/src/commands/sprint/close.ts +0 -180
  54. package/src/commands/sprint/context.ts +0 -109
  55. package/src/commands/sprint/create.ts +0 -60
  56. package/src/commands/sprint/current.ts +0 -75
  57. package/src/commands/sprint/delete.ts +0 -72
  58. package/src/commands/sprint/health.ts +0 -229
  59. package/src/commands/sprint/ideate.ts +0 -496
  60. package/src/commands/sprint/index.ts +0 -226
  61. package/src/commands/sprint/list.ts +0 -86
  62. package/src/commands/sprint/plan-utils.ts +0 -207
  63. package/src/commands/sprint/plan.ts +0 -549
  64. package/src/commands/sprint/refine.ts +0 -359
  65. package/src/commands/sprint/requirements.ts +0 -58
  66. package/src/commands/sprint/show.ts +0 -140
  67. package/src/commands/sprint/start.ts +0 -119
  68. package/src/commands/sprint/switch.ts +0 -20
  69. package/src/commands/task/add.ts +0 -316
  70. package/src/commands/task/import.ts +0 -150
  71. package/src/commands/task/index.ts +0 -123
  72. package/src/commands/task/list.ts +0 -145
  73. package/src/commands/task/next.ts +0 -45
  74. package/src/commands/task/remove.ts +0 -47
  75. package/src/commands/task/reorder.ts +0 -45
  76. package/src/commands/task/show.ts +0 -111
  77. package/src/commands/task/status.ts +0 -99
  78. package/src/commands/ticket/add.ts +0 -265
  79. package/src/commands/ticket/edit.ts +0 -166
  80. package/src/commands/ticket/index.ts +0 -114
  81. package/src/commands/ticket/list.ts +0 -128
  82. package/src/commands/ticket/refine-utils.ts +0 -89
  83. package/src/commands/ticket/refine.ts +0 -268
  84. package/src/commands/ticket/remove.ts +0 -48
  85. package/src/commands/ticket/show.ts +0 -74
  86. package/src/completion/handle.ts +0 -30
  87. package/src/completion/resolver.ts +0 -241
  88. package/src/interactive/dashboard.ts +0 -268
  89. package/src/interactive/escapable.ts +0 -81
  90. package/src/interactive/file-browser.ts +0 -153
  91. package/src/interactive/index.ts +0 -429
  92. package/src/interactive/menu.ts +0 -403
  93. package/src/interactive/selectors.ts +0 -273
  94. package/src/interactive/wizard.ts +0 -221
  95. package/src/providers/claude.ts +0 -53
  96. package/src/providers/copilot.ts +0 -86
  97. package/src/providers/index.ts +0 -43
  98. package/src/providers/types.ts +0 -85
  99. package/src/schemas/index.ts +0 -130
  100. package/src/store/config.ts +0 -74
  101. package/src/store/progress.ts +0 -230
  102. package/src/store/project.ts +0 -276
  103. package/src/store/sprint.ts +0 -229
  104. package/src/store/task.ts +0 -443
  105. package/src/store/ticket.ts +0 -178
  106. package/src/theme/index.ts +0 -215
  107. package/src/theme/ui.ts +0 -872
  108. package/src/utils/detect-scripts.ts +0 -247
  109. package/src/utils/editor-input.ts +0 -41
  110. package/src/utils/editor.ts +0 -37
  111. package/src/utils/exit-codes.ts +0 -27
  112. package/src/utils/file-lock.ts +0 -135
  113. package/src/utils/git.ts +0 -185
  114. package/src/utils/ids.ts +0 -37
  115. package/src/utils/issue-fetch.ts +0 -244
  116. package/src/utils/json-extract.ts +0 -62
  117. package/src/utils/multiline.ts +0 -61
  118. package/src/utils/path-selector.ts +0 -236
  119. package/src/utils/paths.ts +0 -108
  120. package/src/utils/provider.ts +0 -34
  121. package/src/utils/requirements-export.ts +0 -63
  122. package/src/utils/storage.ts +0 -107
  123. package/tsconfig.json +0 -25
  124. /package/{src/ai → dist}/prompts/ideate-auto.md +0 -0
  125. /package/{src/ai → dist}/prompts/ideate.md +0 -0
  126. /package/{src/ai → dist}/prompts/plan-auto.md +0 -0
  127. /package/{src/ai → dist}/prompts/plan-common.md +0 -0
  128. /package/{src/ai → dist}/prompts/plan-interactive.md +0 -0
  129. /package/{src/ai → dist}/prompts/task-execution.md +0 -0
  130. /package/{src/ai → dist}/prompts/ticket-refine.md +0 -0
@@ -1,229 +0,0 @@
1
- import { getCurrentSprintOrThrow } from '@src/store/sprint.ts';
2
- import { getTasks } from '@src/store/task.ts';
3
- import { colors, getQuoteForContext } from '@src/theme/index.ts';
4
- import { icons, log, printHeader, progressBar, renderCard, showError } from '@src/theme/ui.ts';
5
- import type { Sprint, Task } from '@src/schemas/index.ts';
6
- import { getCurrentBranch } from '@src/utils/git.ts';
7
-
8
- // ============================================================================
9
- // Health Check Types
10
- // ============================================================================
11
-
12
- interface HealthCheck {
13
- name: string;
14
- status: 'pass' | 'warn' | 'fail';
15
- items: string[];
16
- }
17
-
18
- // ============================================================================
19
- // Health Check Runners
20
- // ============================================================================
21
-
22
- function checkBlockers(tasks: Task[]): HealthCheck {
23
- const doneTasks = new Set(tasks.filter((t) => t.status === 'done').map((t) => t.id));
24
- const allTaskIds = new Set(tasks.map((t) => t.id));
25
-
26
- const blocked: string[] = [];
27
- for (const task of tasks) {
28
- if (task.status === 'done') continue;
29
- const unresolvedDeps = task.blockedBy.filter((depId) => allTaskIds.has(depId) && !doneTasks.has(depId));
30
- if (unresolvedDeps.length > 0) {
31
- blocked.push(`${task.name} ${colors.muted(`(${task.id})`)} blocked by ${unresolvedDeps.join(', ')}`);
32
- }
33
- }
34
-
35
- return {
36
- name: 'Blockers',
37
- status: blocked.length > 0 ? 'fail' : 'pass',
38
- items: blocked,
39
- };
40
- }
41
-
42
- function checkStaleTasks(tasks: Task[]): HealthCheck {
43
- const stale = tasks.filter((t) => t.status === 'in_progress');
44
- const items = stale.map((t) => `${t.name} ${colors.muted(`(${t.id})`)}`);
45
-
46
- return {
47
- name: 'Stale Tasks',
48
- status: items.length > 0 ? 'warn' : 'pass',
49
- items,
50
- };
51
- }
52
-
53
- function checkOrphanedDeps(tasks: Task[]): HealthCheck {
54
- const allTaskIds = new Set(tasks.map((t) => t.id));
55
- const orphaned: string[] = [];
56
-
57
- for (const task of tasks) {
58
- const missingDeps = task.blockedBy.filter((depId) => !allTaskIds.has(depId));
59
- if (missingDeps.length > 0) {
60
- orphaned.push(`${task.name} ${colors.muted(`(${task.id})`)} references missing: ${missingDeps.join(', ')}`);
61
- }
62
- }
63
-
64
- return {
65
- name: 'Orphaned Dependencies',
66
- status: orphaned.length > 0 ? 'fail' : 'pass',
67
- items: orphaned,
68
- };
69
- }
70
-
71
- function checkTicketsWithoutTasks(sprint: Sprint, tasks: Task[]): HealthCheck {
72
- const ticketIdsWithTasks = new Set(tasks.map((t) => t.ticketId).filter(Boolean));
73
- const orphanedTickets = sprint.tickets.filter((t) => !ticketIdsWithTasks.has(t.id));
74
- const items = orphanedTickets.map((t) => `${t.title} ${colors.muted(`(${t.id})`)}`);
75
-
76
- return {
77
- name: 'Tickets Without Tasks',
78
- status: items.length > 0 ? 'warn' : 'pass',
79
- items,
80
- };
81
- }
82
-
83
- function checkDuplicateOrders(tasks: Task[]): HealthCheck {
84
- const orderCounts = new Map<number, string[]>();
85
- for (const task of tasks) {
86
- const existing = orderCounts.get(task.order) ?? [];
87
- existing.push(`${task.name} ${colors.muted(`(${task.id})`)}`);
88
- orderCounts.set(task.order, existing);
89
- }
90
-
91
- const items: string[] = [];
92
- for (const [order, taskNames] of orderCounts) {
93
- if (taskNames.length > 1) {
94
- items.push(`Order ${String(order)}: ${taskNames.join(', ')}`);
95
- }
96
- }
97
-
98
- return {
99
- name: 'Duplicate Task Orders',
100
- status: items.length > 0 ? 'warn' : 'pass',
101
- items,
102
- };
103
- }
104
-
105
- function checkPendingRequirementsOnActive(sprint: Sprint): HealthCheck {
106
- if (sprint.status !== 'active') {
107
- return { name: 'Pending Requirements', status: 'pass', items: [] };
108
- }
109
-
110
- const pending = sprint.tickets.filter((t) => t.requirementStatus === 'pending');
111
- const items = pending.map((t) => `${t.title} ${colors.muted(`(${t.id})`)} — refine before planning`);
112
-
113
- return {
114
- name: 'Pending Requirements',
115
- status: items.length > 0 ? 'warn' : 'pass',
116
- items,
117
- };
118
- }
119
-
120
- function checkBranchConsistency(sprint: Sprint, tasks: Task[]): HealthCheck {
121
- if (!sprint.branch) {
122
- return { name: 'Branch Consistency', status: 'pass', items: [] };
123
- }
124
-
125
- const remainingTasks = tasks.filter((t) => t.status !== 'done');
126
- const uniquePaths = [...new Set(remainingTasks.map((t) => t.projectPath))];
127
- const items: string[] = [];
128
-
129
- for (const projectPath of uniquePaths) {
130
- try {
131
- const current = getCurrentBranch(projectPath);
132
- if (current !== sprint.branch) {
133
- items.push(`${projectPath} — on '${current}', expected '${sprint.branch}'`);
134
- }
135
- } catch {
136
- items.push(`${projectPath} — unable to determine branch`);
137
- }
138
- }
139
-
140
- return {
141
- name: 'Branch Consistency',
142
- status: items.length > 0 ? 'warn' : 'pass',
143
- items,
144
- };
145
- }
146
-
147
- function checkTasksWithoutSteps(tasks: Task[]): HealthCheck {
148
- const empty = tasks.filter((t) => t.steps.length === 0);
149
- const items = empty.map((t) => `${t.name} ${colors.muted(`(${t.id})`)}`);
150
-
151
- return {
152
- name: 'Tasks Without Steps',
153
- status: items.length > 0 ? 'warn' : 'pass',
154
- items,
155
- };
156
- }
157
-
158
- // ============================================================================
159
- // Card Rendering
160
- // ============================================================================
161
-
162
- function renderCheckCard(check: HealthCheck): string {
163
- const colorFn = check.status === 'pass' ? colors.success : check.status === 'warn' ? colors.warning : colors.error;
164
-
165
- const statusIcon = check.status === 'pass' ? icons.success : check.status === 'warn' ? icons.warning : icons.error;
166
-
167
- const lines: string[] = [];
168
-
169
- if (check.items.length === 0) {
170
- lines.push(colors.success(`${icons.success} No issues found`));
171
- } else {
172
- for (const item of check.items) {
173
- lines.push(`${colorFn(statusIcon)} ${item}`);
174
- }
175
- }
176
-
177
- return renderCard(check.name, lines, { colorFn });
178
- }
179
-
180
- // ============================================================================
181
- // Main Command
182
- // ============================================================================
183
-
184
- export async function sprintHealthCommand(): Promise<void> {
185
- let sprint: Sprint;
186
- try {
187
- sprint = await getCurrentSprintOrThrow();
188
- } catch (err) {
189
- if (err instanceof Error) {
190
- showError(err.message);
191
- } else {
192
- showError('Unknown error');
193
- }
194
- return;
195
- }
196
-
197
- const tasks = await getTasks(sprint.id);
198
-
199
- printHeader(`Sprint Health: ${sprint.name}`, icons.sprint);
200
-
201
- const checks: HealthCheck[] = [
202
- checkBlockers(tasks),
203
- checkStaleTasks(tasks),
204
- checkOrphanedDeps(tasks),
205
- checkTicketsWithoutTasks(sprint, tasks),
206
- checkTasksWithoutSteps(tasks),
207
- checkDuplicateOrders(tasks),
208
- checkPendingRequirementsOnActive(sprint),
209
- checkBranchConsistency(sprint, tasks),
210
- ];
211
-
212
- for (const check of checks) {
213
- console.log(renderCheckCard(check));
214
- log.newline();
215
- }
216
-
217
- // Health score
218
- const passing = checks.filter((c) => c.status === 'pass').length;
219
- const total = checks.length;
220
- const bar = progressBar(passing, total);
221
- log.info(`Health Score: ${bar} ${colors.muted(`${String(passing)}/${String(total)} checks passing`)}`);
222
-
223
- // Ralph quote
224
- log.newline();
225
- const category = passing === total ? 'success' : 'error';
226
- const quote = getQuoteForContext(category);
227
- console.log(colors.muted(` "${quote}"`));
228
- log.newline();
229
- }