agileflow 2.94.1 → 2.95.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 (73) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/lib/colors.generated.js +117 -0
  3. package/lib/colors.js +59 -109
  4. package/lib/generator-factory.js +333 -0
  5. package/lib/path-utils.js +49 -0
  6. package/lib/session-registry.js +25 -15
  7. package/lib/smart-json-file.js +40 -32
  8. package/lib/state-machine.js +286 -0
  9. package/package.json +1 -1
  10. package/scripts/agileflow-configure.js +7 -6
  11. package/scripts/archive-completed-stories.sh +86 -11
  12. package/scripts/babysit-context-restore.js +89 -0
  13. package/scripts/claude-tmux.sh +111 -5
  14. package/scripts/damage-control/bash-tool-damage-control.js +11 -247
  15. package/scripts/damage-control/edit-tool-damage-control.js +9 -249
  16. package/scripts/damage-control/write-tool-damage-control.js +9 -244
  17. package/scripts/generate-colors.js +314 -0
  18. package/scripts/lib/colors.generated.sh +82 -0
  19. package/scripts/lib/colors.sh +10 -70
  20. package/scripts/lib/configure-features.js +401 -0
  21. package/scripts/lib/context-loader.js +181 -52
  22. package/scripts/precompact-context.sh +54 -17
  23. package/scripts/session-coordinator.sh +2 -2
  24. package/scripts/session-manager.js +653 -10
  25. package/src/core/commands/audit.md +93 -0
  26. package/src/core/commands/auto.md +73 -0
  27. package/src/core/commands/babysit.md +169 -13
  28. package/src/core/commands/baseline.md +73 -0
  29. package/src/core/commands/batch.md +64 -0
  30. package/src/core/commands/blockers.md +60 -0
  31. package/src/core/commands/board.md +66 -0
  32. package/src/core/commands/choose.md +77 -0
  33. package/src/core/commands/ci.md +77 -0
  34. package/src/core/commands/compress.md +27 -1
  35. package/src/core/commands/configure.md +126 -10
  36. package/src/core/commands/council.md +74 -0
  37. package/src/core/commands/debt.md +72 -0
  38. package/src/core/commands/deploy.md +73 -0
  39. package/src/core/commands/deps.md +68 -0
  40. package/src/core/commands/docs.md +60 -0
  41. package/src/core/commands/feedback.md +68 -0
  42. package/src/core/commands/ideate.md +74 -0
  43. package/src/core/commands/impact.md +74 -0
  44. package/src/core/commands/install.md +529 -0
  45. package/src/core/commands/maintain.md +558 -0
  46. package/src/core/commands/metrics.md +75 -0
  47. package/src/core/commands/multi-expert.md +74 -0
  48. package/src/core/commands/packages.md +69 -0
  49. package/src/core/commands/readme-sync.md +64 -0
  50. package/src/core/commands/research/analyze.md +285 -121
  51. package/src/core/commands/research/import.md +281 -109
  52. package/src/core/commands/retro.md +76 -0
  53. package/src/core/commands/review.md +72 -0
  54. package/src/core/commands/rlm.md +83 -0
  55. package/src/core/commands/rpi.md +90 -0
  56. package/src/core/commands/session/cleanup.md +214 -12
  57. package/src/core/commands/session/end.md +155 -17
  58. package/src/core/commands/sprint.md +72 -0
  59. package/src/core/commands/story-validate.md +68 -0
  60. package/src/core/commands/template.md +69 -0
  61. package/src/core/commands/tests.md +83 -0
  62. package/src/core/commands/update.md +59 -0
  63. package/src/core/commands/validate-expertise.md +76 -0
  64. package/src/core/commands/velocity.md +74 -0
  65. package/src/core/commands/verify.md +91 -0
  66. package/src/core/commands/whats-new.md +69 -0
  67. package/src/core/commands/workflow.md +88 -0
  68. package/src/core/templates/command-documentation.md +187 -0
  69. package/tools/cli/commands/session.js +1171 -0
  70. package/tools/cli/commands/setup.js +2 -81
  71. package/tools/cli/installers/core/installer.js +0 -5
  72. package/tools/cli/installers/ide/claude-code.js +6 -0
  73. package/tools/cli/lib/config-manager.js +42 -5
@@ -1,254 +1,19 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  /**
4
- * write-tool-damage-control.js - Enforce path protection for Write tool
4
+ * write-tool-damage-control.js - PreToolUse hook for Write tool
5
5
  *
6
- * This PreToolUse hook runs before every Write tool execution.
7
- * It checks the file path against patterns.yaml to block writes
8
- * to protected paths.
9
- *
10
- * Path protection levels:
11
- * zeroAccessPaths: Cannot read, write, edit, or delete
12
- * readOnlyPaths: Can read, cannot write or delete
13
- * noDeletePaths: Can read and write, cannot delete (Write is allowed)
6
+ * Validates file paths against access control patterns in damage-control-patterns.yaml
7
+ * before allowing file writes. Part of AgileFlow's damage control system.
14
8
  *
15
9
  * Exit codes:
16
- * 0 = Allow write to proceed
17
- * 2 = Block write
18
- *
19
- * Usage (as PreToolUse hook):
20
- * node .claude/hooks/damage-control/write-tool-damage-control.js
10
+ * 0 - Allow operation
11
+ * 2 - Block operation
21
12
  *
22
- * Environment:
23
- * CLAUDE_TOOL_INPUT - JSON string with tool input (contains "file_path")
24
- * CLAUDE_PROJECT_DIR - Project root directory
25
- */
26
-
27
- const fs = require('fs');
28
- const path = require('path');
29
-
30
- // ANSI colors for output
31
- const c = {
32
- reset: '\x1b[0m',
33
- bold: '\x1b[1m',
34
- red: '\x1b[31m',
35
- yellow: '\x1b[33m',
36
- cyan: '\x1b[36m',
37
- };
38
-
39
- // Exit codes
40
- const EXIT_ALLOW = 0;
41
- const EXIT_BLOCK = 2;
42
-
43
- /**
44
- * Load path protection rules from patterns.yaml
45
- */
46
- function loadPathRules(projectDir) {
47
- const locations = [
48
- path.join(projectDir, '.claude/hooks/damage-control/patterns.yaml'),
49
- path.join(projectDir, '.agileflow/hooks/damage-control/patterns.yaml'),
50
- path.join(projectDir, 'patterns.yaml'),
51
- ];
52
-
53
- for (const loc of locations) {
54
- if (fs.existsSync(loc)) {
55
- try {
56
- const content = fs.readFileSync(loc, 'utf8');
57
- return parsePathRules(content);
58
- } catch (e) {
59
- console.error(`Warning: Could not parse ${loc}: ${e.message}`);
60
- }
61
- }
62
- }
63
-
64
- return getDefaultPathRules();
65
- }
66
-
67
- /**
68
- * Parse path rules from YAML content
13
+ * Usage: Configured as PreToolUse hook in .claude/settings.json
69
14
  */
70
- function parsePathRules(content) {
71
- const rules = {
72
- zeroAccessPaths: [],
73
- readOnlyPaths: [],
74
- noDeletePaths: [],
75
- };
76
-
77
- let currentSection = null;
78
-
79
- const lines = content.split('\n');
80
-
81
- for (const line of lines) {
82
- if (line.trim().startsWith('#') || line.trim() === '') continue;
83
-
84
- if (line.match(/^zeroAccessPaths:/)) {
85
- currentSection = 'zeroAccessPaths';
86
- continue;
87
- }
88
- if (line.match(/^readOnlyPaths:/)) {
89
- currentSection = 'readOnlyPaths';
90
- continue;
91
- }
92
- if (line.match(/^noDeletePaths:/)) {
93
- currentSection = 'noDeletePaths';
94
- continue;
95
- }
96
- if (line.match(/^(bashToolPatterns|askPatterns|agileflowPatterns|config):/)) {
97
- currentSection = null;
98
- continue;
99
- }
100
-
101
- if (currentSection && rules[currentSection]) {
102
- const pathMatch = line.match(/^\s+-\s*['"]?(.+?)['"]?\s*$/);
103
- if (pathMatch) {
104
- rules[currentSection].push(pathMatch[1]);
105
- }
106
- }
107
- }
108
-
109
- return rules;
110
- }
111
-
112
- /**
113
- * Default path rules if patterns.yaml not found
114
- */
115
- function getDefaultPathRules() {
116
- return {
117
- zeroAccessPaths: ['~/.ssh/', '~/.aws/credentials', '.env', '.env.local', '.env.production'],
118
- readOnlyPaths: ['/etc/', '~/.bashrc', '~/.zshrc', 'package-lock.json', 'yarn.lock', '.git/'],
119
- noDeletePaths: ['.agileflow/', '.claude/', 'docs/09-agents/status.json', 'CLAUDE.md'],
120
- };
121
- }
122
-
123
- /**
124
- * Expand home directory in path
125
- */
126
- function expandHome(filePath) {
127
- if (filePath.startsWith('~/')) {
128
- return path.join(process.env.HOME || '', filePath.slice(2));
129
- }
130
- return filePath;
131
- }
132
-
133
- /**
134
- * Check if a file path matches a pattern
135
- */
136
- function pathMatches(filePath, pattern) {
137
- const expandedPattern = expandHome(pattern);
138
- const normalizedFile = path.normalize(filePath);
139
- const normalizedPattern = path.normalize(expandedPattern);
140
-
141
- // Exact match
142
- if (normalizedFile === normalizedPattern) return true;
143
-
144
- // Directory prefix match
145
- if (pattern.endsWith('/')) {
146
- if (normalizedFile.startsWith(normalizedPattern)) return true;
147
- }
148
-
149
- // Glob pattern (**)
150
- if (pattern.includes('**/')) {
151
- const globPart = pattern.split('**/')[1];
152
- if (normalizedFile.includes(globPart)) return true;
153
- }
154
-
155
- // Wildcard at end
156
- if (pattern.endsWith('*')) {
157
- const prefix = normalizedPattern.slice(0, -1);
158
- if (normalizedFile.startsWith(prefix)) return true;
159
- }
160
-
161
- // Basename match
162
- if (!pattern.includes('/') && !pattern.includes(path.sep)) {
163
- const basename = path.basename(normalizedFile);
164
- if (basename === pattern) return true;
165
- if (pattern.endsWith('*')) {
166
- const patternBase = pattern.slice(0, -1);
167
- if (basename.startsWith(patternBase)) return true;
168
- }
169
- }
170
-
171
- return false;
172
- }
173
-
174
- /**
175
- * Check if file path is protected for writing
176
- * Returns: { blocked: boolean, reason: string, level: string }
177
- */
178
- function checkPath(filePath, rules) {
179
- // Check zero access paths (blocked completely)
180
- for (const pattern of rules.zeroAccessPaths) {
181
- if (pathMatches(filePath, pattern)) {
182
- return {
183
- blocked: true,
184
- reason: `Path is in zero-access protected list: ${pattern}`,
185
- level: 'zero-access',
186
- };
187
- }
188
- }
189
-
190
- // Check read-only paths (cannot write)
191
- for (const pattern of rules.readOnlyPaths) {
192
- if (pathMatches(filePath, pattern)) {
193
- return {
194
- blocked: true,
195
- reason: `Path is read-only: ${pattern}`,
196
- level: 'read-only',
197
- };
198
- }
199
- }
200
-
201
- // noDeletePaths allows writing, only blocks deletion
202
- // so we don't block writes here
203
-
204
- return { blocked: false, reason: null, level: null };
205
- }
206
-
207
- /**
208
- * Main entry point
209
- */
210
- function main() {
211
- const toolInput = process.env.CLAUDE_TOOL_INPUT;
212
- const projectDir = process.env.CLAUDE_PROJECT_DIR || process.cwd();
213
-
214
- if (!toolInput) {
215
- process.exit(EXIT_ALLOW);
216
- }
217
-
218
- let input;
219
- try {
220
- input = JSON.parse(toolInput);
221
- } catch (e) {
222
- console.error('Error parsing CLAUDE_TOOL_INPUT:', e.message);
223
- process.exit(EXIT_ALLOW);
224
- }
225
-
226
- const filePath = input.file_path;
227
- if (!filePath) {
228
- process.exit(EXIT_ALLOW);
229
- }
230
-
231
- // Resolve to absolute path
232
- const absolutePath = path.isAbsolute(filePath) ? filePath : path.join(projectDir, filePath);
233
-
234
- // Load rules
235
- const rules = loadPathRules(projectDir);
236
-
237
- // Check path
238
- const result = checkPath(absolutePath, rules);
239
-
240
- if (result.blocked) {
241
- console.error(`${c.red}${c.bold}BLOCKED${c.reset}: ${result.reason}`);
242
- console.error(`${c.yellow}File: ${filePath}${c.reset}`);
243
- console.error(`${c.cyan}This file is protected by damage control (${result.level}).${c.reset}`);
244
- process.exit(EXIT_BLOCK);
245
- }
246
-
247
- process.exit(EXIT_ALLOW);
248
- }
249
15
 
250
- if (require.main === module) {
251
- main();
252
- }
16
+ const { createPathHook } = require('../lib/damage-control-utils');
253
17
 
254
- module.exports = { checkPath, loadPathRules, pathMatches };
18
+ // Run the hook using factory
19
+ createPathHook('write')();
@@ -0,0 +1,314 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * generate-colors.js - Generate color files from YAML config
5
+ *
6
+ * Reads config/colors.yaml and generates:
7
+ * - lib/colors.js (JavaScript module)
8
+ * - scripts/lib/colors.sh (Bash script)
9
+ *
10
+ * Usage:
11
+ * node scripts/generate-colors.js
12
+ * node scripts/generate-colors.js --check # Verify files are up-to-date
13
+ *
14
+ * This ensures a single source of truth for all color definitions.
15
+ */
16
+
17
+ const fs = require('fs');
18
+ const path = require('path');
19
+ const { safeLoad } = require('../lib/yaml-utils');
20
+
21
+ const ROOT = path.resolve(__dirname, '..');
22
+ const CONFIG_PATH = path.join(ROOT, 'config', 'colors.yaml');
23
+ const JS_OUTPUT = path.join(ROOT, 'lib', 'colors.generated.js');
24
+ const SH_OUTPUT = path.join(ROOT, 'scripts', 'lib', 'colors.generated.sh');
25
+
26
+ /**
27
+ * Load colors configuration from YAML
28
+ * @returns {Object} Colors configuration
29
+ */
30
+ function loadConfig() {
31
+ const content = fs.readFileSync(CONFIG_PATH, 'utf8');
32
+ return safeLoad(content);
33
+ }
34
+
35
+ /**
36
+ * Generate JavaScript module content
37
+ * @param {Object} config - Colors configuration
38
+ * @returns {string} JavaScript module content
39
+ */
40
+ function generateJS(config) {
41
+ const lines = [
42
+ '/**',
43
+ ' * colors.generated.js - Auto-generated from config/colors.yaml',
44
+ ' *',
45
+ ' * DO NOT EDIT THIS FILE DIRECTLY.',
46
+ ' * Run: node scripts/generate-colors.js',
47
+ ' *',
48
+ ` * Generated: ${new Date().toISOString()}`,
49
+ ' */',
50
+ '',
51
+ "'use strict';",
52
+ '',
53
+ ];
54
+
55
+ // Brand color
56
+ lines.push(`// Brand color`);
57
+ lines.push(`const BRAND_HEX = '${config.brand.hex}';`);
58
+ lines.push('');
59
+
60
+ // Modifiers
61
+ lines.push('// Modifiers');
62
+ lines.push('const modifiers = {');
63
+ for (const [name, code] of Object.entries(config.modifiers)) {
64
+ lines.push(` ${name}: '\\x1b[${code}m',`);
65
+ }
66
+ lines.push('};');
67
+ lines.push('');
68
+
69
+ // Standard colors
70
+ lines.push('// Standard ANSI colors');
71
+ lines.push('const standard = {');
72
+ for (const [name, code] of Object.entries(config.standard)) {
73
+ lines.push(` ${name}: '\\x1b[${code}m',`);
74
+ }
75
+ lines.push('};');
76
+ lines.push('');
77
+
78
+ // Bright colors
79
+ lines.push('// Bright ANSI colors');
80
+ lines.push('const bright = {');
81
+ for (const [name, code] of Object.entries(config.bright)) {
82
+ lines.push(` bright${name.charAt(0).toUpperCase() + name.slice(1)}: '\\x1b[${code}m',`);
83
+ }
84
+ lines.push('};');
85
+ lines.push('');
86
+
87
+ // 256-color palette
88
+ lines.push('// 256-color palette');
89
+ lines.push('const palette256 = {');
90
+ for (const [name, def] of Object.entries(config.palette256)) {
91
+ const comment = def.comment ? ` // ${def.comment}` : '';
92
+ lines.push(` ${name}: '\\x1b[${def.code}m',${comment}`);
93
+ }
94
+ lines.push('};');
95
+ lines.push('');
96
+
97
+ // Background colors
98
+ lines.push('// Background colors');
99
+ lines.push('const backgrounds = {');
100
+ for (const [name, code] of Object.entries(config.backgrounds)) {
101
+ lines.push(` bg${name.charAt(0).toUpperCase() + name.slice(1)}: '\\x1b[${code}m',`);
102
+ }
103
+ lines.push('};');
104
+ lines.push('');
105
+
106
+ // Brand color ANSI
107
+ lines.push('// Brand color ANSI');
108
+ lines.push(`const brand = '\\x1b[${config.brand.ansi}m';`);
109
+ lines.push('');
110
+
111
+ // High contrast colors
112
+ lines.push('// High-contrast mode colors (WCAG AAA)');
113
+ lines.push('const highContrast = {');
114
+ for (const [name, code] of Object.entries(config.highContrast)) {
115
+ lines.push(` ${name}: '\\x1b[${code}m',`);
116
+ }
117
+ lines.push('};');
118
+ lines.push('');
119
+
120
+ // Combined cStandard object (for backward compatibility)
121
+ lines.push('// Combined standard color palette');
122
+ lines.push('const cStandard = {');
123
+ lines.push(' ...modifiers,');
124
+ lines.push(' ...standard,');
125
+ lines.push(' ...bright,');
126
+ lines.push(' ...palette256,');
127
+ lines.push(' ...backgrounds,');
128
+ lines.push(' brand,');
129
+ lines.push(` orange: brand, // Alias`);
130
+ lines.push(' // Semantic aliases');
131
+ for (const [semantic, target] of Object.entries(config.semantic)) {
132
+ lines.push(` ${semantic}: standard.${target},`);
133
+ }
134
+ lines.push('};');
135
+ lines.push('');
136
+
137
+ // Exports
138
+ lines.push('module.exports = {');
139
+ lines.push(' BRAND_HEX,');
140
+ lines.push(' modifiers,');
141
+ lines.push(' standard,');
142
+ lines.push(' bright,');
143
+ lines.push(' palette256,');
144
+ lines.push(' backgrounds,');
145
+ lines.push(' brand,');
146
+ lines.push(' highContrast,');
147
+ lines.push(' cStandard,');
148
+ lines.push('};');
149
+ lines.push('');
150
+
151
+ return lines.join('\n');
152
+ }
153
+
154
+ /**
155
+ * Generate Bash script content
156
+ * @param {Object} config - Colors configuration
157
+ * @returns {string} Bash script content
158
+ */
159
+ function generateSH(config) {
160
+ const lines = [
161
+ '#!/bin/bash',
162
+ '# colors.generated.sh - Auto-generated from config/colors.yaml',
163
+ '#',
164
+ '# DO NOT EDIT THIS FILE DIRECTLY.',
165
+ '# Run: node scripts/generate-colors.js',
166
+ '#',
167
+ `# Generated: ${new Date().toISOString()}`,
168
+ '#',
169
+ '# Usage: source "$(dirname "${BASH_SOURCE[0]}")/colors.generated.sh"',
170
+ '',
171
+ '# ============================================================================',
172
+ '# Modifiers',
173
+ '# ============================================================================',
174
+ ];
175
+
176
+ for (const [name, code] of Object.entries(config.modifiers)) {
177
+ lines.push(`${name.toUpperCase()}="\\033[${code}m"`);
178
+ }
179
+ lines.push('');
180
+
181
+ lines.push('# ============================================================================');
182
+ lines.push('# Standard ANSI Colors');
183
+ lines.push('# ============================================================================');
184
+ for (const [name, code] of Object.entries(config.standard)) {
185
+ lines.push(`${name.toUpperCase()}="\\033[${code}m"`);
186
+ }
187
+ lines.push('');
188
+
189
+ lines.push('# ============================================================================');
190
+ lines.push('# Bright Variants');
191
+ lines.push('# ============================================================================');
192
+ for (const [name, code] of Object.entries(config.bright)) {
193
+ lines.push(`BRIGHT_${name.toUpperCase()}="\\033[${code}m"`);
194
+ }
195
+ lines.push('');
196
+
197
+ lines.push('# ============================================================================');
198
+ lines.push('# Semantic Aliases');
199
+ lines.push('# ============================================================================');
200
+ for (const [semantic, target] of Object.entries(config.semantic)) {
201
+ lines.push(`${semantic.toUpperCase()}="$${target.toUpperCase()}"`);
202
+ }
203
+ lines.push('');
204
+
205
+ lines.push('# ============================================================================');
206
+ lines.push('# 256-Color Palette');
207
+ lines.push('# ============================================================================');
208
+ for (const [name, def] of Object.entries(config.palette256)) {
209
+ const varName = name.replace(/([A-Z])/g, '_$1').toUpperCase();
210
+ const comment = def.comment ? ` # ${def.comment}` : '';
211
+ lines.push(`${varName}="\\033[${def.code}m"${comment}`);
212
+ }
213
+ lines.push('');
214
+
215
+ lines.push('# ============================================================================');
216
+ lines.push('# Brand Color');
217
+ lines.push('# ============================================================================');
218
+ lines.push(`BRAND="\\033[${config.brand.ansi}m"`);
219
+ lines.push('ORANGE="$BRAND" # Alias');
220
+ lines.push('');
221
+
222
+ lines.push('# ============================================================================');
223
+ lines.push('# Background Colors');
224
+ lines.push('# ============================================================================');
225
+ for (const [name, code] of Object.entries(config.backgrounds)) {
226
+ lines.push(`BG_${name.toUpperCase()}="\\033[${code}m"`);
227
+ }
228
+ lines.push('');
229
+
230
+ return lines.join('\n');
231
+ }
232
+
233
+ /**
234
+ * Main function
235
+ */
236
+ function main() {
237
+ const checkMode = process.argv.includes('--check');
238
+
239
+ console.log('🎨 Color Generator');
240
+ console.log('==================');
241
+ console.log(`Config: ${CONFIG_PATH}`);
242
+
243
+ // Load configuration
244
+ const config = loadConfig();
245
+ console.log('✓ Loaded colors.yaml');
246
+
247
+ // Generate content
248
+ const jsContent = generateJS(config);
249
+ const shContent = generateSH(config);
250
+
251
+ if (checkMode) {
252
+ // Check if files are up-to-date
253
+ let upToDate = true;
254
+
255
+ try {
256
+ const existingJS = fs.readFileSync(JS_OUTPUT, 'utf8');
257
+ // Compare without timestamp line
258
+ const normalizeJS = content =>
259
+ content
260
+ .split('\n')
261
+ .filter(line => !line.includes('Generated:'))
262
+ .join('\n');
263
+ if (normalizeJS(existingJS) !== normalizeJS(jsContent)) {
264
+ console.log('✗ lib/colors.generated.js is out of date');
265
+ upToDate = false;
266
+ } else {
267
+ console.log('✓ lib/colors.generated.js is up to date');
268
+ }
269
+ } catch {
270
+ console.log('✗ lib/colors.generated.js does not exist');
271
+ upToDate = false;
272
+ }
273
+
274
+ try {
275
+ const existingSH = fs.readFileSync(SH_OUTPUT, 'utf8');
276
+ const normalizeSH = content =>
277
+ content
278
+ .split('\n')
279
+ .filter(line => !line.includes('Generated:'))
280
+ .join('\n');
281
+ if (normalizeSH(existingSH) !== normalizeSH(shContent)) {
282
+ console.log('✗ scripts/lib/colors.generated.sh is out of date');
283
+ upToDate = false;
284
+ } else {
285
+ console.log('✓ scripts/lib/colors.generated.sh is up to date');
286
+ }
287
+ } catch {
288
+ console.log('✗ scripts/lib/colors.generated.sh does not exist');
289
+ upToDate = false;
290
+ }
291
+
292
+ if (!upToDate) {
293
+ console.log('\nRun: node scripts/generate-colors.js');
294
+ process.exit(1);
295
+ }
296
+ console.log('\n✓ All color files are up to date');
297
+ return;
298
+ }
299
+
300
+ // Write files
301
+ fs.writeFileSync(JS_OUTPUT, jsContent);
302
+ console.log(`✓ Generated ${JS_OUTPUT}`);
303
+
304
+ fs.writeFileSync(SH_OUTPUT, shContent);
305
+ console.log(`✓ Generated ${SH_OUTPUT}`);
306
+
307
+ console.log('\n✓ Color generation complete!');
308
+ }
309
+
310
+ if (require.main === module) {
311
+ main();
312
+ }
313
+
314
+ module.exports = { loadConfig, generateJS, generateSH };
@@ -0,0 +1,82 @@
1
+ #!/bin/bash
2
+ # colors.generated.sh - Auto-generated from config/colors.yaml
3
+ #
4
+ # DO NOT EDIT THIS FILE DIRECTLY.
5
+ # Run: node scripts/generate-colors.js
6
+ #
7
+ # Generated: 2026-01-29T08:28:33.726Z
8
+ #
9
+ # Usage: source "$(dirname "${BASH_SOURCE[0]}")/colors.generated.sh"
10
+
11
+ # ============================================================================
12
+ # Modifiers
13
+ # ============================================================================
14
+ RESET="\033[0m"
15
+ BOLD="\033[1m"
16
+ DIM="\033[2m"
17
+ ITALIC="\033[3m"
18
+ UNDERLINE="\033[4m"
19
+
20
+ # ============================================================================
21
+ # Standard ANSI Colors
22
+ # ============================================================================
23
+ RED="\033[31m"
24
+ GREEN="\033[32m"
25
+ YELLOW="\033[33m"
26
+ BLUE="\033[34m"
27
+ MAGENTA="\033[35m"
28
+ CYAN="\033[36m"
29
+ WHITE="\033[37m"
30
+ BLACK="\033[30m"
31
+
32
+ # ============================================================================
33
+ # Bright Variants
34
+ # ============================================================================
35
+ BRIGHT_RED="\033[91m"
36
+ BRIGHT_GREEN="\033[92m"
37
+ BRIGHT_YELLOW="\033[93m"
38
+ BRIGHT_BLUE="\033[94m"
39
+ BRIGHT_MAGENTA="\033[95m"
40
+ BRIGHT_CYAN="\033[96m"
41
+ BRIGHT_WHITE="\033[97m"
42
+ BRIGHT_BLACK="\033[90m"
43
+
44
+ # ============================================================================
45
+ # Semantic Aliases
46
+ # ============================================================================
47
+ SUCCESS="$GREEN"
48
+ ERROR="$RED"
49
+ WARNING="$YELLOW"
50
+ INFO="$CYAN"
51
+
52
+ # ============================================================================
53
+ # 256-Color Palette
54
+ # ============================================================================
55
+ MINT_GREEN="\033[38;5;158m" # Healthy/success states
56
+ PEACH="\033[38;5;215m" # Warning states
57
+ CORAL="\033[38;5;203m" # Critical/error states
58
+ LIGHT_GREEN="\033[38;5;194m" # Session healthy
59
+ LIGHT_YELLOW="\033[38;5;228m" # Session warning
60
+ LIGHT_PINK="\033[38;5;210m" # Session critical
61
+ SKY_BLUE="\033[38;5;117m" # Directories/paths, ready states
62
+ LAVENDER="\033[38;5;147m" # Model info, story IDs
63
+ SOFT_GOLD="\033[38;5;222m" # Cost/money
64
+ TEAL="\033[38;5;80m" # Pending states
65
+ SLATE="\033[38;5;103m" # Secondary info
66
+ ROSE="\033[38;5;211m" # Blocked/critical accent
67
+ AMBER="\033[38;5;214m" # WIP/in-progress accent
68
+ POWDER="\033[38;5;153m" # Labels/headers
69
+
70
+ # ============================================================================
71
+ # Brand Color
72
+ # ============================================================================
73
+ BRAND="\033[38;2;232;104;58m"
74
+ ORANGE="$BRAND" # Alias
75
+
76
+ # ============================================================================
77
+ # Background Colors
78
+ # ============================================================================
79
+ BG_RED="\033[41m"
80
+ BG_GREEN="\033[42m"
81
+ BG_YELLOW="\033[43m"
82
+ BG_BLUE="\033[44m"