ai-sdlc 0.1.0-alpha.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.
Files changed (96) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +847 -0
  3. package/dist/agents/implementation.d.ts +11 -0
  4. package/dist/agents/implementation.d.ts.map +1 -0
  5. package/dist/agents/implementation.js +123 -0
  6. package/dist/agents/implementation.js.map +1 -0
  7. package/dist/agents/index.d.ts +7 -0
  8. package/dist/agents/index.d.ts.map +1 -0
  9. package/dist/agents/index.js +8 -0
  10. package/dist/agents/index.js.map +1 -0
  11. package/dist/agents/planning.d.ts +9 -0
  12. package/dist/agents/planning.d.ts.map +1 -0
  13. package/dist/agents/planning.js +84 -0
  14. package/dist/agents/planning.js.map +1 -0
  15. package/dist/agents/refinement.d.ts +10 -0
  16. package/dist/agents/refinement.d.ts.map +1 -0
  17. package/dist/agents/refinement.js +98 -0
  18. package/dist/agents/refinement.js.map +1 -0
  19. package/dist/agents/research.d.ts +16 -0
  20. package/dist/agents/research.d.ts.map +1 -0
  21. package/dist/agents/research.js +141 -0
  22. package/dist/agents/research.js.map +1 -0
  23. package/dist/agents/review.d.ts +24 -0
  24. package/dist/agents/review.d.ts.map +1 -0
  25. package/dist/agents/review.js +740 -0
  26. package/dist/agents/review.js.map +1 -0
  27. package/dist/agents/rework.d.ts +17 -0
  28. package/dist/agents/rework.d.ts.map +1 -0
  29. package/dist/agents/rework.js +139 -0
  30. package/dist/agents/rework.js.map +1 -0
  31. package/dist/agents/state-assessor.d.ts +21 -0
  32. package/dist/agents/state-assessor.d.ts.map +1 -0
  33. package/dist/agents/state-assessor.js +29 -0
  34. package/dist/agents/state-assessor.js.map +1 -0
  35. package/dist/cli/commands.d.ts +87 -0
  36. package/dist/cli/commands.d.ts.map +1 -0
  37. package/dist/cli/commands.js +1183 -0
  38. package/dist/cli/commands.js.map +1 -0
  39. package/dist/cli/formatting.d.ts +68 -0
  40. package/dist/cli/formatting.d.ts.map +1 -0
  41. package/dist/cli/formatting.js +194 -0
  42. package/dist/cli/formatting.js.map +1 -0
  43. package/dist/cli/runner.d.ts +57 -0
  44. package/dist/cli/runner.d.ts.map +1 -0
  45. package/dist/cli/runner.js +272 -0
  46. package/dist/cli/runner.js.map +1 -0
  47. package/dist/cli/story-utils.d.ts +19 -0
  48. package/dist/cli/story-utils.d.ts.map +1 -0
  49. package/dist/cli/story-utils.js +44 -0
  50. package/dist/cli/story-utils.js.map +1 -0
  51. package/dist/cli/table-renderer.d.ts +22 -0
  52. package/dist/cli/table-renderer.d.ts.map +1 -0
  53. package/dist/cli/table-renderer.js +159 -0
  54. package/dist/cli/table-renderer.js.map +1 -0
  55. package/dist/core/auth.d.ts +39 -0
  56. package/dist/core/auth.d.ts.map +1 -0
  57. package/dist/core/auth.js +128 -0
  58. package/dist/core/auth.js.map +1 -0
  59. package/dist/core/client.d.ts +73 -0
  60. package/dist/core/client.d.ts.map +1 -0
  61. package/dist/core/client.js +140 -0
  62. package/dist/core/client.js.map +1 -0
  63. package/dist/core/config.d.ts +48 -0
  64. package/dist/core/config.d.ts.map +1 -0
  65. package/dist/core/config.js +330 -0
  66. package/dist/core/config.js.map +1 -0
  67. package/dist/core/kanban.d.ts +34 -0
  68. package/dist/core/kanban.d.ts.map +1 -0
  69. package/dist/core/kanban.js +253 -0
  70. package/dist/core/kanban.js.map +1 -0
  71. package/dist/core/story.d.ts +91 -0
  72. package/dist/core/story.d.ts.map +1 -0
  73. package/dist/core/story.js +349 -0
  74. package/dist/core/story.js.map +1 -0
  75. package/dist/core/theme.d.ts +17 -0
  76. package/dist/core/theme.d.ts.map +1 -0
  77. package/dist/core/theme.js +136 -0
  78. package/dist/core/theme.js.map +1 -0
  79. package/dist/core/workflow-state.d.ts +56 -0
  80. package/dist/core/workflow-state.d.ts.map +1 -0
  81. package/dist/core/workflow-state.js +162 -0
  82. package/dist/core/workflow-state.js.map +1 -0
  83. package/dist/index.d.ts +3 -0
  84. package/dist/index.d.ts.map +1 -0
  85. package/dist/index.js +103 -0
  86. package/dist/index.js.map +1 -0
  87. package/dist/types/index.d.ts +228 -0
  88. package/dist/types/index.d.ts.map +1 -0
  89. package/dist/types/index.js +38 -0
  90. package/dist/types/index.js.map +1 -0
  91. package/dist/types/workflow-state.d.ts +54 -0
  92. package/dist/types/workflow-state.d.ts.map +1 -0
  93. package/dist/types/workflow-state.js +5 -0
  94. package/dist/types/workflow-state.js.map +1 -0
  95. package/package.json +71 -0
  96. package/templates/story.md +35 -0
@@ -0,0 +1,91 @@
1
+ import { Story, StoryFrontmatter, ReviewAttempt, Config } from '../types/index.js';
2
+ /**
3
+ * Parse a story markdown file into a Story object
4
+ */
5
+ export declare function parseStory(filePath: string): Story;
6
+ /**
7
+ * Write a story back to disk
8
+ */
9
+ export declare function writeStory(story: Story): void;
10
+ /**
11
+ * Move a story to a different kanban folder
12
+ */
13
+ export declare function moveStory(story: Story, toFolder: string, sdlcRoot: string): Story;
14
+ /**
15
+ * Generate a unique story ID
16
+ */
17
+ export declare function generateStoryId(): string;
18
+ /**
19
+ * Create a slug from a title
20
+ */
21
+ export declare function slugify(title: string): string;
22
+ /**
23
+ * Create a new story in the backlog
24
+ */
25
+ export declare function createStory(title: string, sdlcRoot: string, options?: Partial<StoryFrontmatter>): Story;
26
+ /**
27
+ * Update story frontmatter field
28
+ */
29
+ export declare function updateStoryField<K extends keyof StoryFrontmatter>(story: Story, field: K, value: StoryFrontmatter[K]): Story;
30
+ /**
31
+ * Append content to a section in the story
32
+ */
33
+ export declare function appendToSection(story: Story, section: string, content: string): Story;
34
+ /**
35
+ * Record a refinement attempt in the story's frontmatter
36
+ */
37
+ export declare function recordRefinementAttempt(story: Story, agentType: string, reviewFeedback: string): Story;
38
+ /**
39
+ * Get the current refinement count for a story
40
+ */
41
+ export declare function getRefinementCount(story: Story): number;
42
+ /**
43
+ * Check if a story can retry refinement based on iteration limit
44
+ */
45
+ export declare function canRetryRefinement(story: Story, maxAttempts: number): boolean;
46
+ /**
47
+ * Reset phase completion flags for rework
48
+ */
49
+ export declare function resetPhaseCompletion(story: Story, phase: 'research' | 'plan' | 'implement'): Story;
50
+ /**
51
+ * Get the latest review feedback from the story content
52
+ */
53
+ export declare function getLatestReviewFeedback(story: Story): string | null;
54
+ /**
55
+ * Append refinement feedback to the story content
56
+ */
57
+ export declare function appendRefinementNote(story: Story, iteration: number, feedback: string): Story;
58
+ /**
59
+ * Get the effective maximum retries for a story (story-specific or config default)
60
+ */
61
+ export declare function getEffectiveMaxRetries(story: Story, config: Config): number;
62
+ /**
63
+ * Check if a story has reached its maximum retry limit
64
+ * @param maxIterationsOverride Optional CLI override for max iterations (takes precedence)
65
+ */
66
+ export declare function isAtMaxRetries(story: Story, config: Config, maxIterationsOverride?: number): boolean;
67
+ /**
68
+ * Increment the retry count for a story
69
+ */
70
+ export declare function incrementRetryCount(story: Story): Story;
71
+ /**
72
+ * Reset RPIV cycle for a story (keep research, reset plan/implementation/reviews)
73
+ */
74
+ export declare function resetRPIVCycle(story: Story, reason: string): Story;
75
+ /**
76
+ * Append a review attempt to the story's review history
77
+ */
78
+ export declare function appendReviewHistory(story: Story, attempt: ReviewAttempt): Story;
79
+ /**
80
+ * Get the latest review attempt from a story's history
81
+ */
82
+ export declare function getLatestReviewAttempt(story: Story): ReviewAttempt | null;
83
+ /**
84
+ * Mark a story as complete (all workflow flags set to true)
85
+ */
86
+ export declare function markStoryComplete(story: Story): Story;
87
+ /**
88
+ * Snapshot max_retries from config to story frontmatter (for mid-cycle config change protection)
89
+ */
90
+ export declare function snapshotMaxRetries(story: Story, config: Config): Story;
91
+ //# sourceMappingURL=story.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"story.d.ts","sourceRoot":"","sources":["../../src/core/story.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,349 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import matter from 'gray-matter';
4
+ import { FOLDER_TO_STATUS } from '../types/index.js';
5
+ /**
6
+ * Parse a story markdown file into a Story object
7
+ */
8
+ export function parseStory(filePath) {
9
+ const content = fs.readFileSync(filePath, 'utf-8');
10
+ const { data, content: body } = matter(content);
11
+ // Extract slug from filename (remove priority prefix and .md extension)
12
+ const filename = path.basename(filePath, '.md');
13
+ const slug = filename.replace(/^\d+-/, '');
14
+ return {
15
+ path: filePath,
16
+ slug,
17
+ frontmatter: data,
18
+ content: body.trim(),
19
+ };
20
+ }
21
+ /**
22
+ * Write a story back to disk
23
+ */
24
+ export function writeStory(story) {
25
+ const content = matter.stringify(story.content, story.frontmatter);
26
+ fs.writeFileSync(story.path, content);
27
+ }
28
+ /**
29
+ * Move a story to a different kanban folder
30
+ */
31
+ export function moveStory(story, toFolder, sdlcRoot) {
32
+ const targetFolder = path.join(sdlcRoot, toFolder);
33
+ // Ensure target folder exists
34
+ if (!fs.existsSync(targetFolder)) {
35
+ fs.mkdirSync(targetFolder, { recursive: true });
36
+ }
37
+ // Get existing stories in target folder to determine priority
38
+ const existingFiles = fs.readdirSync(targetFolder).filter(f => f.endsWith('.md'));
39
+ const newPriority = existingFiles.length + 1;
40
+ // Create new filename with priority
41
+ const newFilename = `${String(newPriority).padStart(2, '0')}-${story.slug}.md`;
42
+ const newPath = path.join(targetFolder, newFilename);
43
+ // Update frontmatter
44
+ story.frontmatter.priority = newPriority;
45
+ story.frontmatter.status = FOLDER_TO_STATUS[toFolder];
46
+ story.frontmatter.updated = new Date().toISOString().split('T')[0];
47
+ // Write to new location
48
+ const oldPath = story.path;
49
+ story.path = newPath;
50
+ writeStory(story);
51
+ // Remove old file
52
+ if (fs.existsSync(oldPath) && oldPath !== newPath) {
53
+ fs.unlinkSync(oldPath);
54
+ }
55
+ return story;
56
+ }
57
+ /**
58
+ * Generate a unique story ID
59
+ */
60
+ export function generateStoryId() {
61
+ const timestamp = Date.now().toString(36);
62
+ const random = Math.random().toString(36).substring(2, 6);
63
+ return `story-${timestamp}-${random}`;
64
+ }
65
+ /**
66
+ * Create a slug from a title
67
+ */
68
+ export function slugify(title) {
69
+ return title
70
+ .toLowerCase()
71
+ .replace(/[^a-z0-9]+/g, '-')
72
+ .replace(/^-|-$/g, '')
73
+ .substring(0, 50);
74
+ }
75
+ /**
76
+ * Create a new story in the backlog
77
+ */
78
+ export function createStory(title, sdlcRoot, options = {}) {
79
+ const backlogFolder = path.join(sdlcRoot, 'backlog');
80
+ // Ensure backlog folder exists
81
+ if (!fs.existsSync(backlogFolder)) {
82
+ fs.mkdirSync(backlogFolder, { recursive: true });
83
+ }
84
+ // Get existing stories to determine priority
85
+ const existingFiles = fs.readdirSync(backlogFolder).filter(f => f.endsWith('.md'));
86
+ const priority = existingFiles.length + 1;
87
+ const slug = slugify(title);
88
+ const filename = `${String(priority).padStart(2, '0')}-${slug}.md`;
89
+ const filePath = path.join(backlogFolder, filename);
90
+ const frontmatter = {
91
+ id: generateStoryId(),
92
+ title,
93
+ priority,
94
+ status: 'backlog',
95
+ type: options.type || 'feature',
96
+ created: new Date().toISOString().split('T')[0],
97
+ labels: options.labels || [],
98
+ research_complete: false,
99
+ plan_complete: false,
100
+ implementation_complete: false,
101
+ reviews_complete: false,
102
+ ...options,
103
+ };
104
+ const content = `# ${title}
105
+
106
+ ## Summary
107
+
108
+ (Describe the feature, bug, or task here)
109
+
110
+ ## Acceptance Criteria
111
+
112
+ - [ ] (Define acceptance criteria)
113
+
114
+ ## Research
115
+
116
+ <!-- Populated by research agent -->
117
+
118
+ ## Implementation Plan
119
+
120
+ <!-- Populated by planning agent -->
121
+
122
+ ## Review Notes
123
+
124
+ <!-- Populated by review agents -->`;
125
+ const story = {
126
+ path: filePath,
127
+ slug,
128
+ frontmatter,
129
+ content,
130
+ };
131
+ writeStory(story);
132
+ return story;
133
+ }
134
+ /**
135
+ * Update story frontmatter field
136
+ */
137
+ export function updateStoryField(story, field, value) {
138
+ story.frontmatter[field] = value;
139
+ story.frontmatter.updated = new Date().toISOString().split('T')[0];
140
+ writeStory(story);
141
+ return story;
142
+ }
143
+ /**
144
+ * Append content to a section in the story
145
+ */
146
+ export function appendToSection(story, section, content) {
147
+ const sectionHeader = `## ${section}`;
148
+ const sectionIndex = story.content.indexOf(sectionHeader);
149
+ if (sectionIndex === -1) {
150
+ // Section doesn't exist, add it at the end
151
+ story.content += `\n\n${sectionHeader}\n\n${content}`;
152
+ }
153
+ else {
154
+ // Find the next section or end of content
155
+ const afterHeader = sectionIndex + sectionHeader.length;
156
+ const nextSectionMatch = story.content.substring(afterHeader).match(/\n## /);
157
+ const insertPoint = nextSectionMatch
158
+ ? afterHeader + nextSectionMatch.index
159
+ : story.content.length;
160
+ // Insert content before next section
161
+ story.content =
162
+ story.content.substring(0, insertPoint).trimEnd() +
163
+ '\n\n' +
164
+ content +
165
+ '\n' +
166
+ story.content.substring(insertPoint);
167
+ }
168
+ story.frontmatter.updated = new Date().toISOString().split('T')[0];
169
+ writeStory(story);
170
+ return story;
171
+ }
172
+ /**
173
+ * Record a refinement attempt in the story's frontmatter
174
+ */
175
+ export function recordRefinementAttempt(story, agentType, reviewFeedback) {
176
+ // Initialize refinement tracking if not present
177
+ if (!story.frontmatter.refinement_iterations) {
178
+ story.frontmatter.refinement_iterations = [];
179
+ story.frontmatter.refinement_count = 0;
180
+ }
181
+ const iteration = (story.frontmatter.refinement_count || 0) + 1;
182
+ const refinementRecord = {
183
+ iteration,
184
+ agentType,
185
+ startedAt: new Date().toISOString(),
186
+ reviewFeedback,
187
+ result: 'in_progress',
188
+ };
189
+ story.frontmatter.refinement_iterations.push(refinementRecord);
190
+ story.frontmatter.refinement_count = iteration;
191
+ story.frontmatter.updated = new Date().toISOString().split('T')[0];
192
+ writeStory(story);
193
+ return story;
194
+ }
195
+ /**
196
+ * Get the current refinement count for a story
197
+ */
198
+ export function getRefinementCount(story) {
199
+ return story.frontmatter.refinement_count || 0;
200
+ }
201
+ /**
202
+ * Check if a story can retry refinement based on iteration limit
203
+ */
204
+ export function canRetryRefinement(story, maxAttempts) {
205
+ const currentCount = getRefinementCount(story);
206
+ const storyMax = story.frontmatter.max_refinement_attempts;
207
+ const effectiveMax = storyMax !== undefined ? storyMax : maxAttempts;
208
+ return currentCount < effectiveMax;
209
+ }
210
+ /**
211
+ * Reset phase completion flags for rework
212
+ */
213
+ export function resetPhaseCompletion(story, phase) {
214
+ switch (phase) {
215
+ case 'research':
216
+ story.frontmatter.research_complete = false;
217
+ break;
218
+ case 'plan':
219
+ story.frontmatter.plan_complete = false;
220
+ break;
221
+ case 'implement':
222
+ story.frontmatter.implementation_complete = false;
223
+ break;
224
+ }
225
+ story.frontmatter.updated = new Date().toISOString().split('T')[0];
226
+ writeStory(story);
227
+ return story;
228
+ }
229
+ /**
230
+ * Get the latest review feedback from the story content
231
+ */
232
+ export function getLatestReviewFeedback(story) {
233
+ const reviewSection = story.content.match(/## Review Notes\n\n([\s\S]*?)(?=\n## |$)/);
234
+ if (!reviewSection) {
235
+ return null;
236
+ }
237
+ // Extract the most recent review (look for latest "### Review" or similar heading)
238
+ const reviews = reviewSection[1].split(/### /);
239
+ return reviews.length > 1 ? reviews[reviews.length - 1].trim() : null;
240
+ }
241
+ /**
242
+ * Append refinement feedback to the story content
243
+ */
244
+ export function appendRefinementNote(story, iteration, feedback) {
245
+ const refinementNote = `### Refinement Iteration ${iteration}\n\n${feedback}`;
246
+ return appendToSection(story, 'Review Notes', refinementNote);
247
+ }
248
+ /**
249
+ * Get the effective maximum retries for a story (story-specific or config default)
250
+ */
251
+ export function getEffectiveMaxRetries(story, config) {
252
+ return story.frontmatter.max_retries !== undefined
253
+ ? story.frontmatter.max_retries
254
+ : config.reviewConfig.maxRetries;
255
+ }
256
+ /**
257
+ * Check if a story has reached its maximum retry limit
258
+ * @param maxIterationsOverride Optional CLI override for max iterations (takes precedence)
259
+ */
260
+ export function isAtMaxRetries(story, config, maxIterationsOverride) {
261
+ const currentRetryCount = story.frontmatter.retry_count || 0;
262
+ // CLI override takes precedence, then story-specific, then config default
263
+ const maxRetries = maxIterationsOverride !== undefined
264
+ ? maxIterationsOverride
265
+ : getEffectiveMaxRetries(story, config);
266
+ // Infinity means no limit
267
+ if (!Number.isFinite(maxRetries)) {
268
+ return false;
269
+ }
270
+ return currentRetryCount >= maxRetries;
271
+ }
272
+ /**
273
+ * Increment the retry count for a story
274
+ */
275
+ export function incrementRetryCount(story) {
276
+ const currentCount = story.frontmatter.retry_count || 0;
277
+ story.frontmatter.retry_count = currentCount + 1;
278
+ story.frontmatter.last_restart_timestamp = new Date().toISOString();
279
+ story.frontmatter.updated = new Date().toISOString().split('T')[0];
280
+ writeStory(story);
281
+ return story;
282
+ }
283
+ /**
284
+ * Reset RPIV cycle for a story (keep research, reset plan/implementation/reviews)
285
+ */
286
+ export function resetRPIVCycle(story, reason) {
287
+ // Keep research_complete as true, reset other flags
288
+ story.frontmatter.plan_complete = false;
289
+ story.frontmatter.implementation_complete = false;
290
+ story.frontmatter.reviews_complete = false;
291
+ story.frontmatter.last_restart_reason = reason;
292
+ story.frontmatter.last_restart_timestamp = new Date().toISOString();
293
+ story.frontmatter.updated = new Date().toISOString().split('T')[0];
294
+ // Increment retry count
295
+ const currentCount = story.frontmatter.retry_count || 0;
296
+ story.frontmatter.retry_count = currentCount + 1;
297
+ writeStory(story);
298
+ return story;
299
+ }
300
+ /**
301
+ * Append a review attempt to the story's review history
302
+ */
303
+ export function appendReviewHistory(story, attempt) {
304
+ if (!story.frontmatter.review_history) {
305
+ story.frontmatter.review_history = [];
306
+ }
307
+ // Add new attempt
308
+ story.frontmatter.review_history.push(attempt);
309
+ // Keep only the last 10 attempts to prevent unbounded growth
310
+ if (story.frontmatter.review_history.length > 10) {
311
+ story.frontmatter.review_history = story.frontmatter.review_history.slice(-10);
312
+ }
313
+ story.frontmatter.updated = new Date().toISOString().split('T')[0];
314
+ writeStory(story);
315
+ return story;
316
+ }
317
+ /**
318
+ * Get the latest review attempt from a story's history
319
+ */
320
+ export function getLatestReviewAttempt(story) {
321
+ if (!story.frontmatter.review_history || story.frontmatter.review_history.length === 0) {
322
+ return null;
323
+ }
324
+ return story.frontmatter.review_history[story.frontmatter.review_history.length - 1];
325
+ }
326
+ /**
327
+ * Mark a story as complete (all workflow flags set to true)
328
+ */
329
+ export function markStoryComplete(story) {
330
+ story.frontmatter.research_complete = true;
331
+ story.frontmatter.plan_complete = true;
332
+ story.frontmatter.implementation_complete = true;
333
+ story.frontmatter.reviews_complete = true;
334
+ story.frontmatter.updated = new Date().toISOString().split('T')[0];
335
+ writeStory(story);
336
+ return story;
337
+ }
338
+ /**
339
+ * Snapshot max_retries from config to story frontmatter (for mid-cycle config change protection)
340
+ */
341
+ export function snapshotMaxRetries(story, config) {
342
+ if (story.frontmatter.max_retries === undefined) {
343
+ story.frontmatter.max_retries = config.reviewConfig.maxRetries;
344
+ story.frontmatter.updated = new Date().toISOString().split('T')[0];
345
+ writeStory(story);
346
+ }
347
+ return story;
348
+ }
349
+ //# sourceMappingURL=story.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"story.js","sourceRoot":"","sources":["../../src/core/story.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import { Config, ThemePreference, ThemeColors } from '../types/index.js';
2
+ /**
3
+ * Detect terminal background theme by checking environment variables
4
+ * Returns 'light' or 'dark' based on terminal settings
5
+ */
6
+ export declare function detectTerminalTheme(): 'light' | 'dark';
7
+ /**
8
+ * Get color scheme for a specific theme preference
9
+ * Returns an object with semantic color methods
10
+ */
11
+ export declare function getThemeColors(preference: ThemePreference): ThemeColors;
12
+ /**
13
+ * Get themed chalk instance based on configuration
14
+ * This is the main function to use in CLI commands
15
+ */
16
+ export declare function getThemedChalk(config?: Config): ThemeColors;
17
+ //# sourceMappingURL=theme.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme.d.ts","sourceRoot":"","sources":["../../src/core/theme.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGzE;;;GAGG;AACH,wBAAgB,mBAAmB,IAAI,OAAO,GAAG,MAAM,CAwCtD;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,UAAU,EAAE,eAAe,GAAG,WAAW,CA8EvE;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,WAAW,CAG3D"}
@@ -0,0 +1,136 @@
1
+ import chalk from 'chalk';
2
+ import { loadConfig } from './config.js';
3
+ /**
4
+ * Detect terminal background theme by checking environment variables
5
+ * Returns 'light' or 'dark' based on terminal settings
6
+ */
7
+ export function detectTerminalTheme() {
8
+ // Check COLORFGBG environment variable
9
+ // Format: "foreground;background" where high values (>7) = light background
10
+ const colorFgBg = process.env.COLORFGBG;
11
+ if (colorFgBg) {
12
+ const parts = colorFgBg.split(';');
13
+ if (parts.length >= 2) {
14
+ const bg = parseInt(parts[1], 10);
15
+ // Background values 0-7 are dark, 8-15 are light (standard ANSI)
16
+ // Security: validate range to prevent unexpected behavior
17
+ if (!isNaN(bg) && bg >= 0 && bg <= 15) {
18
+ // Standard 16-color ANSI palette
19
+ return bg > 7 ? 'light' : 'dark';
20
+ }
21
+ else if (!isNaN(bg) && bg >= 16 && bg <= 231) {
22
+ // 256-color palette: RGB cube (16-231)
23
+ // Calculate luminance approximation from 6x6x6 RGB cube
24
+ const colorIndex = bg - 16;
25
+ const r = Math.floor(colorIndex / 36);
26
+ const g = Math.floor((colorIndex % 36) / 6);
27
+ const b = colorIndex % 6;
28
+ // Simple luminance: if sum > 9 (out of 15), it's light
29
+ return (r + g + b) > 9 ? 'light' : 'dark';
30
+ }
31
+ else if (!isNaN(bg) && bg >= 232 && bg <= 255) {
32
+ // 256-color palette: grayscale ramp (232-255)
33
+ // Values above 243 (midpoint) are light
34
+ return bg > 243 ? 'light' : 'dark';
35
+ }
36
+ }
37
+ }
38
+ // Check TERM_PROGRAM for known terminal types
39
+ const termProgram = process.env.TERM_PROGRAM;
40
+ if (termProgram === 'Apple_Terminal') {
41
+ // macOS Terminal.app defaults to light
42
+ return 'light';
43
+ }
44
+ // Default to dark (safer - bright colors work better on dark backgrounds)
45
+ return 'dark';
46
+ }
47
+ /**
48
+ * Get color scheme for a specific theme preference
49
+ * Returns an object with semantic color methods
50
+ */
51
+ export function getThemeColors(preference) {
52
+ // Handle NO_COLOR environment variable (standard)
53
+ if (process.env.NO_COLOR !== undefined || preference === 'none') {
54
+ return {
55
+ success: (str) => str,
56
+ error: (str) => str,
57
+ warning: (str) => str,
58
+ info: (str) => str,
59
+ dim: (str) => str,
60
+ bold: (str) => str,
61
+ backlog: (str) => str,
62
+ ready: (str) => str,
63
+ inProgress: (str) => str,
64
+ done: (str) => str,
65
+ // RPIV phase colors (no color)
66
+ phaseRefine: (str) => str,
67
+ phaseResearch: (str) => str,
68
+ phasePlan: (str) => str,
69
+ phaseImplement: (str) => str,
70
+ phaseVerify: (str) => str,
71
+ reviewAction: (str) => str,
72
+ phaseComplete: (str) => str,
73
+ };
74
+ }
75
+ // Determine actual theme to use
76
+ let actualTheme;
77
+ if (preference === 'auto') {
78
+ actualTheme = detectTerminalTheme();
79
+ }
80
+ else {
81
+ actualTheme = preference;
82
+ }
83
+ // Light terminal optimized colors (darker, bolder colors)
84
+ if (actualTheme === 'light') {
85
+ return {
86
+ success: chalk.green.bold,
87
+ error: chalk.red.bold,
88
+ warning: chalk.hex('#CC6600'), // Darker orange
89
+ info: chalk.blue.bold,
90
+ dim: chalk.gray,
91
+ bold: chalk.bold,
92
+ backlog: chalk.gray.bold,
93
+ ready: chalk.blue.bold,
94
+ inProgress: chalk.hex('#CC6600'), // Darker orange instead of yellow
95
+ done: chalk.green.bold,
96
+ // RPIV phase colors (darker for light backgrounds)
97
+ phaseRefine: chalk.hex('#9932CC').bold, // Dark purple/magenta
98
+ phaseResearch: chalk.blue.bold, // Blue
99
+ phasePlan: chalk.hex('#008B8B').bold, // Dark cyan
100
+ phaseImplement: chalk.hex('#CC6600').bold, // Dark orange
101
+ phaseVerify: chalk.green.bold, // Green
102
+ reviewAction: chalk.hex('#008B8B').bold, // Distinct cyan with bold
103
+ phaseComplete: chalk.green.bold, // Success green
104
+ };
105
+ }
106
+ // Dark terminal optimized colors (bright, vibrant colors)
107
+ return {
108
+ success: chalk.green,
109
+ error: chalk.red,
110
+ warning: chalk.yellow,
111
+ info: chalk.cyan,
112
+ dim: chalk.dim,
113
+ bold: chalk.bold,
114
+ backlog: chalk.gray,
115
+ ready: chalk.blue,
116
+ inProgress: chalk.yellow,
117
+ done: chalk.green,
118
+ // RPIV phase colors (bright for dark backgrounds)
119
+ phaseRefine: chalk.magenta, // Magenta/purple
120
+ phaseResearch: chalk.blue, // Blue
121
+ phasePlan: chalk.cyan, // Cyan
122
+ phaseImplement: chalk.yellow, // Yellow
123
+ phaseVerify: chalk.green, // Green
124
+ reviewAction: chalk.cyan.bold, // Distinct cyan with bold
125
+ phaseComplete: chalk.green, // Success green
126
+ };
127
+ }
128
+ /**
129
+ * Get themed chalk instance based on configuration
130
+ * This is the main function to use in CLI commands
131
+ */
132
+ export function getThemedChalk(config) {
133
+ const actualConfig = config || loadConfig();
134
+ return getThemeColors(actualConfig.theme);
135
+ }
136
+ //# sourceMappingURL=theme.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme.js","sourceRoot":"","sources":["../../src/core/theme.ts"],"names":[],"mappings":"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"}