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,178 +0,0 @@
1
- import { getSprintFilePath } from '@src/utils/paths.ts';
2
- import { readValidatedJson, writeValidatedJson } from '@src/utils/storage.ts';
3
- import { type Sprint, SprintSchema, type Ticket } from '@src/schemas/index.ts';
4
- import { assertSprintStatus, resolveSprintId } from '@src/store/sprint.ts';
5
- import { generateUuid8 } from '@src/utils/ids.ts';
6
- import { getProject, ProjectNotFoundError } from '@src/store/project.ts';
7
-
8
- export class TicketNotFoundError extends Error {
9
- public readonly ticketId: string;
10
-
11
- constructor(ticketId: string) {
12
- super(`Ticket not found: ${ticketId}`);
13
- this.name = 'TicketNotFoundError';
14
- this.ticketId = ticketId;
15
- }
16
- }
17
-
18
- async function getSprintData(sprintId?: string): Promise<Sprint> {
19
- const id = await resolveSprintId(sprintId);
20
- return readValidatedJson(getSprintFilePath(id), SprintSchema);
21
- }
22
-
23
- async function saveSprintData(sprint: Sprint): Promise<void> {
24
- await writeValidatedJson(getSprintFilePath(sprint.id), sprint, SprintSchema);
25
- }
26
-
27
- export interface AddTicketInput {
28
- title: string;
29
- description?: string;
30
- link?: string;
31
- projectName: string;
32
- }
33
-
34
- export async function addTicket(input: AddTicketInput, sprintId?: string): Promise<Ticket> {
35
- const sprint = await getSprintData(sprintId);
36
-
37
- // Check sprint status - must be draft to add tickets
38
- assertSprintStatus(sprint, ['draft'], 'add tickets');
39
-
40
- // Validate that the project exists
41
- try {
42
- await getProject(input.projectName);
43
- } catch (err) {
44
- if (err instanceof ProjectNotFoundError) {
45
- throw new Error(`Project '${input.projectName}' does not exist. Add it first with 'ralphctl project add'.`, {
46
- cause: err,
47
- });
48
- }
49
- throw err;
50
- }
51
-
52
- const ticket: Ticket = {
53
- id: generateUuid8(),
54
- title: input.title,
55
- description: input.description,
56
- link: input.link,
57
- projectName: input.projectName,
58
- requirementStatus: 'pending',
59
- };
60
-
61
- sprint.tickets.push(ticket);
62
- await saveSprintData(sprint);
63
- return ticket;
64
- }
65
-
66
- export interface UpdateTicketInput {
67
- title?: string;
68
- description?: string;
69
- link?: string;
70
- }
71
-
72
- export async function updateTicket(ticketId: string, updates: UpdateTicketInput, sprintId?: string): Promise<Ticket> {
73
- const sprint = await getSprintData(sprintId);
74
-
75
- // Check sprint status - must be draft to update tickets
76
- assertSprintStatus(sprint, ['draft'], 'update tickets');
77
-
78
- const ticketIdx = sprint.tickets.findIndex((t) => t.id === ticketId);
79
- if (ticketIdx === -1) {
80
- throw new TicketNotFoundError(ticketId);
81
- }
82
-
83
- const ticket = sprint.tickets[ticketIdx];
84
- if (!ticket) {
85
- throw new TicketNotFoundError(ticketId);
86
- }
87
-
88
- // Apply updates
89
- if (updates.title !== undefined) {
90
- ticket.title = updates.title;
91
- }
92
- if (updates.description !== undefined) {
93
- ticket.description = updates.description || undefined;
94
- }
95
- if (updates.link !== undefined) {
96
- ticket.link = updates.link || undefined;
97
- }
98
-
99
- await saveSprintData(sprint);
100
- return ticket;
101
- }
102
-
103
- export async function removeTicket(ticketId: string, sprintId?: string): Promise<void> {
104
- const sprint = await getSprintData(sprintId);
105
-
106
- // Check sprint status - must be draft to remove tickets
107
- assertSprintStatus(sprint, ['draft'], 'remove tickets');
108
-
109
- const index = sprint.tickets.findIndex((t) => t.id === ticketId);
110
- if (index === -1) {
111
- throw new TicketNotFoundError(ticketId);
112
- }
113
- sprint.tickets.splice(index, 1);
114
- await saveSprintData(sprint);
115
- }
116
-
117
- export async function listTickets(sprintId?: string): Promise<Ticket[]> {
118
- const sprint = await getSprintData(sprintId);
119
- return sprint.tickets;
120
- }
121
-
122
- export async function getTicket(ticketId: string, sprintId?: string): Promise<Ticket> {
123
- const sprint = await getSprintData(sprintId);
124
- const ticket = sprint.tickets.find((t) => t.id === ticketId);
125
- if (!ticket) {
126
- throw new TicketNotFoundError(ticketId);
127
- }
128
- return ticket;
129
- }
130
-
131
- /**
132
- * Get a ticket by title (for tickets without an external ID).
133
- */
134
- export async function getTicketByTitle(title: string, sprintId?: string): Promise<Ticket | undefined> {
135
- const sprint = await getSprintData(sprintId);
136
- return sprint.tickets.find((t) => t.title === title);
137
- }
138
-
139
- /**
140
- * Group tickets by their project name.
141
- */
142
- export function groupTicketsByProject(tickets: Ticket[]): Map<string, Ticket[]> {
143
- const grouped = new Map<string, Ticket[]>();
144
- for (const ticket of tickets) {
145
- const existing = grouped.get(ticket.projectName) ?? [];
146
- existing.push(ticket);
147
- grouped.set(ticket.projectName, existing);
148
- }
149
- return grouped;
150
- }
151
-
152
- /**
153
- * Check if all tickets have approved requirements.
154
- */
155
- export function allRequirementsApproved(tickets: Ticket[]): boolean {
156
- return tickets.length > 0 && tickets.every((t) => t.requirementStatus === 'approved');
157
- }
158
-
159
- /**
160
- * Get tickets that still need requirement refinement.
161
- */
162
- export function getPendingRequirements(tickets: Ticket[]): Ticket[] {
163
- return tickets.filter((t) => t.requirementStatus === 'pending');
164
- }
165
-
166
- /**
167
- * Format ticket for display: "[ID] Title"
168
- */
169
- export function formatTicketDisplay(ticket: Ticket): string {
170
- return `[${ticket.id}] ${ticket.title}`;
171
- }
172
-
173
- /**
174
- * Format ticket ID for display.
175
- */
176
- export function formatTicketId(ticket: Ticket): string {
177
- return ticket.id;
178
- }
@@ -1,215 +0,0 @@
1
- import { bold, cyan, dim, gray, green, magenta, red, yellow } from 'colorette';
2
- import gradient from 'gradient-string';
3
-
4
- // Re-export colorette functions for direct usage
5
- export { cyan, green, red, yellow, blue, gray, bold, dim, isColorSupported } from 'colorette';
6
-
7
- // ============================================================================
8
- // COLOR FUNCTIONS
9
- // ============================================================================
10
-
11
- /**
12
- * Color function type (matches colorette signature)
13
- */
14
- export type ColorFn = (text: string | number) => string;
15
-
16
- /**
17
- * Theme color mappings
18
- */
19
- export const colors = {
20
- // Semantic colors
21
- success: green,
22
- error: red,
23
- warning: yellow,
24
- info: cyan,
25
- muted: gray,
26
- highlight: yellow,
27
- accent: bold,
28
- subtle: dim,
29
- // Ralph-specific
30
- primary: yellow,
31
- secondary: magenta,
32
- } as const;
33
-
34
- // Semantic color shortcuts (replaces utils/colors.ts)
35
- export const success = (text: string): string => colors.success(text);
36
- export const error = (text: string): string => colors.error(text);
37
- export const warning = (text: string): string => colors.warning(text);
38
- export const info = (text: string): string => colors.info(text);
39
- export const muted = (text: string): string => colors.muted(text);
40
- export const highlight = (text: string): string => colors.highlight(text);
41
- export const accent = (text: string): string => colors.accent(text);
42
- export const subtle = (text: string): string => colors.subtle(text);
43
- export const primary = (text: string): string => colors.primary(text);
44
- export const secondary = (text: string): string => colors.secondary(text);
45
-
46
- // ============================================================================
47
- // GRADIENT RENDERING (powered by gradient-string)
48
- // ============================================================================
49
-
50
- /**
51
- * Built-in gradient presets for banner/header styling.
52
- * Each gradient is a function: gradients.donut(text) or gradients.donut.multiline(text)
53
- */
54
- export const gradients = {
55
- /** Gold → Orange → Hot Pink → Orchid → Violet (Ralph's signature donut warmth) */
56
- donut: gradient(['#FFD700', '#FFA500', '#FF69B4', '#DA70D6', '#9400D3'], {
57
- interpolation: 'hsv',
58
- hsvSpin: 'short',
59
- }),
60
- /** Green → Dark Cyan (success/completion) */
61
- success: gradient(['#00FF00', '#00CED1']),
62
- /** Orange Red → Gold (warning/attention) */
63
- warning: gradient(['#FF4500', '#FFD700']),
64
- } as const;
65
-
66
- // ============================================================================
67
- // BANNER
68
- // ============================================================================
69
-
70
- const BANNER = `
71
- 🍩 ██████╗ █████╗ ██╗ ██████╗ ██╗ ██╗ ██████╗████████╗██╗ 🍩
72
- ██╔══██╗██╔══██╗██║ ██╔══██╗██║ ██║██╔════╝╚══██╔══╝██║
73
- ██████╔╝███████║██║ ██████╔╝███████║██║ ██║ ██║
74
- ██╔══██╗██╔══██║██║ ██╔═══╝ ██╔══██║██║ ██║ ██║
75
- ██║ ██║██║ ██║███████╗██║ ██║ ██║╚██████╗ ██║ ███████╗
76
- ╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚══════╝
77
- `;
78
-
79
- export const banner = {
80
- art: BANNER,
81
- tagline: "I'm helping with your sprints!",
82
- } as const;
83
-
84
- // ============================================================================
85
- // QUOTES
86
- // ============================================================================
87
-
88
- export const RALPH_QUOTES = [
89
- "I'm helping!",
90
- "Me fail English? That's unpossible!",
91
- 'Go banana!',
92
- 'Hi, Super Nintendo Chalmers!',
93
- 'I bent my wookie.',
94
- "My cat's breath smells like cat food.",
95
- "I'm learnding!",
96
- "The doctor said I wouldn't have so many nose bleeds if I kept my finger outta there.",
97
- 'I found a moonrock in my nose!',
98
- "That's where I saw the leprechaun. He told me to burn things.",
99
- "My daddy's gonna put you in jail!",
100
- "I'm a unitard!",
101
- 'I ate the purple berries...',
102
- 'Tastes like burning!',
103
- "My parents won't let me use scissors.",
104
- 'I dress myself!',
105
- 'Principal Skinner, I got carsick in your office.',
106
- "I'm Idaho!",
107
- 'Mrs. Krabappel and Principal Skinner were in the closet making babies!',
108
- 'Even my boogers are spicy!',
109
- 'It smells like hot dogs.',
110
- 'I sleep in a drawer!',
111
- 'I picked the red one!',
112
- 'The pointy kitty took it!',
113
- 'When I grow up, I want to be a principal or a caterpillar.',
114
- ] as const;
115
-
116
- export function getRandomQuote(): string {
117
- const index = Math.floor(Math.random() * RALPH_QUOTES.length);
118
- return RALPH_QUOTES[index] ?? '';
119
- }
120
-
121
- // ============================================================================
122
- // CONTEXT-SENSITIVE QUOTES
123
- // ============================================================================
124
-
125
- export type QuoteCategory = 'error' | 'success' | 'farewell' | 'idle';
126
-
127
- export const QUOTES_BY_CATEGORY: Record<QuoteCategory, readonly string[]> = {
128
- error: [
129
- 'My tummy hurts!',
130
- 'Tastes like burning!',
131
- 'I ate the purple berries...',
132
- "The doctor said I wouldn't have so many nose bleeds if I kept my finger outta there.",
133
- "My parents won't let me use scissors.",
134
- 'Principal Skinner, I got carsick in your office.',
135
- 'I eated the purple berries. They taste like... burning.',
136
- ],
137
- success: [
138
- "I'm helping!",
139
- 'Go banana!',
140
- "I'm learnding!",
141
- "I'm a unitard!",
142
- 'I dress myself!',
143
- 'I picked the red one!',
144
- 'I found a moonrock in my nose!',
145
- "Yay! I'm a helper!",
146
- ],
147
- farewell: [
148
- "Bye bye! My cat's breath smells like cat food!",
149
- 'When I grow up, I want to be a principal or a caterpillar.',
150
- 'I sleep in a drawer!',
151
- "I'm Idaho!",
152
- 'The pointy kitty took it!',
153
- ],
154
- idle: [
155
- 'Hi, Super Nintendo Chalmers!',
156
- 'I bent my wookie.',
157
- "My cat's breath smells like cat food.",
158
- 'It smells like hot dogs.',
159
- "That's where I saw the leprechaun. He told me to burn things.",
160
- "Me fail English? That's unpossible!",
161
- 'Even my boogers are spicy!',
162
- 'Mrs. Krabappel and Principal Skinner were in the closet making babies!',
163
- ],
164
- } as const;
165
-
166
- /**
167
- * Get a random quote appropriate for the given context category.
168
- */
169
- export function getQuoteForContext(category: QuoteCategory): string {
170
- const quotes = QUOTES_BY_CATEGORY[category];
171
- const index = Math.floor(Math.random() * quotes.length);
172
- return quotes[index] ?? '';
173
- }
174
-
175
- // ============================================================================
176
- // STATUS EMOJI
177
- // ============================================================================
178
-
179
- export const statusEmoji = {
180
- todo: '📝',
181
- in_progress: '🏃',
182
- done: '✅',
183
- blocked: '🚫',
184
- draft: '📋',
185
- active: '🎯',
186
- closed: '🎉',
187
- } as const;
188
-
189
- export function getStatusEmoji(status: string): string {
190
- if (status in statusEmoji) {
191
- return statusEmoji[status as keyof typeof statusEmoji];
192
- }
193
- return status;
194
- }
195
-
196
- // ============================================================================
197
- // MESSAGES
198
- // ============================================================================
199
-
200
- export const messages = {
201
- welcome: "Hi, Super Nintendo Chalmers! I'm ready to help!",
202
- goodbye: "Bye bye! My cat's breath smells like cat food!",
203
- taskComplete: "Yay! I did a task! I'm a unitard!",
204
- sprintCreated: 'I made a sprint! Go banana!',
205
- sprintActivated: "The sprint is awake now! It's unpossible to fail!",
206
- sprintClosed: "We finished! That's where I saw the leprechaun!",
207
- ticketAdded: "I added a ticket! I'm learnding!",
208
- projectAdded: 'I found a project! It smells like hot dogs!',
209
- error: 'My tummy hurts:',
210
- confirm: 'Do you want to? I picked the red one!',
211
- } as const;
212
-
213
- export function getMessage(key: keyof typeof messages): string {
214
- return messages[key];
215
- }