agileflow 2.78.0 → 2.80.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.
- package/README.md +6 -6
- package/package.json +1 -1
- package/scripts/agileflow-configure.js +126 -17
- package/scripts/agileflow-welcome.js +77 -98
- package/scripts/auto-self-improve.js +23 -45
- package/scripts/check-update.js +35 -42
- package/scripts/damage-control/bash-tool-damage-control.js +258 -0
- package/scripts/damage-control/edit-tool-damage-control.js +259 -0
- package/scripts/damage-control/patterns.yaml +227 -0
- package/scripts/damage-control/write-tool-damage-control.js +254 -0
- package/scripts/damage-control-bash.js +28 -22
- package/scripts/damage-control-edit.js +6 -12
- package/scripts/damage-control-write.js +6 -12
- package/scripts/get-env.js +6 -6
- package/scripts/obtain-context.js +67 -37
- package/scripts/ralph-loop.js +199 -63
- package/scripts/screenshot-verifier.js +215 -0
- package/scripts/session-manager.js +12 -33
- package/src/core/agents/configuration-damage-control.md +248 -0
- package/src/core/commands/babysit.md +30 -2
- package/src/core/commands/configure.md +46 -9
- package/src/core/commands/setup/visual-e2e.md +462 -0
- package/src/core/experts/documentation/expertise.yaml +25 -0
- package/src/core/skills/_learnings/code-review.yaml +118 -0
- package/src/core/skills/_learnings/story-writer.yaml +71 -0
- package/tools/cli/commands/start.js +19 -21
- package/tools/cli/installers/ide/claude-code.js +140 -0
- package/tools/cli/tui/Dashboard.js +3 -4
- package/tools/postinstall.js +1 -9
|
@@ -10,25 +10,13 @@
|
|
|
10
10
|
|
|
11
11
|
const path = require('path');
|
|
12
12
|
const fs = require('fs');
|
|
13
|
-
|
|
14
|
-
// ANSI color codes
|
|
15
|
-
const colors = {
|
|
16
|
-
reset: '\x1b[0m',
|
|
17
|
-
bold: '\x1b[1m',
|
|
18
|
-
dim: '\x1b[2m',
|
|
19
|
-
yellow: '\x1b[33m',
|
|
20
|
-
red: '\x1b[31m',
|
|
21
|
-
green: '\x1b[32m',
|
|
22
|
-
cyan: '\x1b[36m',
|
|
23
|
-
magenta: '\x1b[35m',
|
|
24
|
-
orange: '\x1b[38;2;232;104;58m',
|
|
25
|
-
bgYellow: '\x1b[43m',
|
|
26
|
-
bgRed: '\x1b[41m',
|
|
27
|
-
};
|
|
13
|
+
const { c: colors } = require('../../../lib/colors');
|
|
28
14
|
|
|
29
15
|
function showBetaWarning() {
|
|
30
16
|
console.log('');
|
|
31
|
-
console.log(
|
|
17
|
+
console.log(
|
|
18
|
+
`${colors.bgYellow}${colors.bold} BETA ${colors.reset} ${colors.yellow}This feature is in beta and not yet stable${colors.reset}`
|
|
19
|
+
);
|
|
32
20
|
console.log(`${colors.dim} Expect bugs and incomplete features${colors.reset}`);
|
|
33
21
|
console.log('');
|
|
34
22
|
}
|
|
@@ -91,13 +79,17 @@ async function showDashboard() {
|
|
|
91
79
|
const status = await loadStatus();
|
|
92
80
|
|
|
93
81
|
if (!status) {
|
|
94
|
-
console.log(
|
|
82
|
+
console.log(
|
|
83
|
+
`${colors.dim} No status.json found. Run /agileflow:story to create stories.${colors.reset}`
|
|
84
|
+
);
|
|
95
85
|
console.log('');
|
|
96
86
|
return;
|
|
97
87
|
}
|
|
98
88
|
|
|
99
89
|
// Count stories by status
|
|
100
|
-
const stories = Object.values(status).filter(
|
|
90
|
+
const stories = Object.values(status).filter(
|
|
91
|
+
s => s && typeof s === 'object' && (s.id || s.story_id)
|
|
92
|
+
);
|
|
101
93
|
const counts = {
|
|
102
94
|
in_progress: stories.filter(s => ['in_progress', 'in-progress'].includes(s.status)).length,
|
|
103
95
|
blocked: stories.filter(s => s.status === 'blocked').length,
|
|
@@ -111,7 +103,9 @@ async function showDashboard() {
|
|
|
111
103
|
// Summary
|
|
112
104
|
console.log(`${colors.bold} Summary${colors.reset}`);
|
|
113
105
|
console.log(` ────────────────────────────────────────────`);
|
|
114
|
-
console.log(
|
|
106
|
+
console.log(
|
|
107
|
+
` ${colors.yellow}In Progress:${colors.reset} ${counts.in_progress} ${colors.red}Blocked:${colors.reset} ${counts.blocked} ${colors.cyan}Ready:${colors.reset} ${counts.ready} ${colors.green}Done:${colors.reset} ${counts.completed}`
|
|
108
|
+
);
|
|
115
109
|
console.log(` ${colors.dim}Completion: ${completionPct}%${colors.reset}`);
|
|
116
110
|
console.log('');
|
|
117
111
|
|
|
@@ -140,7 +134,9 @@ async function showDashboard() {
|
|
|
140
134
|
// Ready Stories (up to 5)
|
|
141
135
|
const readyStories = stories.filter(s => s.status === 'ready').slice(0, 5);
|
|
142
136
|
if (readyStories.length > 0) {
|
|
143
|
-
console.log(
|
|
137
|
+
console.log(
|
|
138
|
+
`${colors.bold} ${colors.cyan}Ready for Work${colors.reset} ${colors.dim}(showing ${readyStories.length} of ${counts.ready})${colors.reset}`
|
|
139
|
+
);
|
|
144
140
|
console.log(` ────────────────────────────────────────────`);
|
|
145
141
|
readyStories.forEach(story => {
|
|
146
142
|
console.log(formatStory(story));
|
|
@@ -165,7 +161,9 @@ async function main() {
|
|
|
165
161
|
console.log(' npx agileflow start Show dashboard');
|
|
166
162
|
console.log(' npx agileflow start --help Show this help');
|
|
167
163
|
console.log('');
|
|
168
|
-
console.log(
|
|
164
|
+
console.log(
|
|
165
|
+
`${colors.dim}This is a beta feature. For stable commands, use Claude Code slash commands.${colors.reset}`
|
|
166
|
+
);
|
|
169
167
|
return;
|
|
170
168
|
}
|
|
171
169
|
|
|
@@ -69,6 +69,9 @@ class ClaudeCodeSetup extends BaseIdeSetup {
|
|
|
69
69
|
await this.ensureDir(skillsTargetDir);
|
|
70
70
|
console.log(chalk.dim(` - Skills directory: .claude/skills/ (for user-generated skills)`));
|
|
71
71
|
|
|
72
|
+
// Setup damage control hooks
|
|
73
|
+
await this.setupDamageControl(projectDir, agileflowDir, claudeDir, options);
|
|
74
|
+
|
|
72
75
|
const totalCommands = commandResult.commands + agentResult.commands;
|
|
73
76
|
const totalSubdirs =
|
|
74
77
|
commandResult.subdirs + (agentResult.commands > 0 ? 1 : 0) + agentResult.subdirs;
|
|
@@ -86,6 +89,143 @@ class ClaudeCodeSetup extends BaseIdeSetup {
|
|
|
86
89
|
subdirs: totalSubdirs,
|
|
87
90
|
};
|
|
88
91
|
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Setup damage control hooks
|
|
95
|
+
* @param {string} projectDir - Project directory
|
|
96
|
+
* @param {string} agileflowDir - AgileFlow installation directory
|
|
97
|
+
* @param {string} claudeDir - .claude directory path
|
|
98
|
+
* @param {Object} options - Setup options
|
|
99
|
+
*/
|
|
100
|
+
async setupDamageControl(projectDir, agileflowDir, claudeDir, options = {}) {
|
|
101
|
+
const damageControlSource = path.join(agileflowDir, 'scripts', 'damage-control');
|
|
102
|
+
const damageControlTarget = path.join(claudeDir, 'hooks', 'damage-control');
|
|
103
|
+
|
|
104
|
+
// Check if source exists
|
|
105
|
+
if (!fs.existsSync(damageControlSource)) {
|
|
106
|
+
console.log(chalk.dim(` - Damage control: source not found, skipping`));
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Create hooks directory
|
|
111
|
+
await this.ensureDir(damageControlTarget);
|
|
112
|
+
|
|
113
|
+
// Copy hook scripts
|
|
114
|
+
const scripts = [
|
|
115
|
+
'bash-tool-damage-control.js',
|
|
116
|
+
'edit-tool-damage-control.js',
|
|
117
|
+
'write-tool-damage-control.js',
|
|
118
|
+
];
|
|
119
|
+
for (const script of scripts) {
|
|
120
|
+
const src = path.join(damageControlSource, script);
|
|
121
|
+
const dest = path.join(damageControlTarget, script);
|
|
122
|
+
if (fs.existsSync(src)) {
|
|
123
|
+
await fs.copy(src, dest);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Copy patterns.yaml (preserve existing)
|
|
128
|
+
const patternsSource = path.join(damageControlSource, 'patterns.yaml');
|
|
129
|
+
const patternsTarget = path.join(damageControlTarget, 'patterns.yaml');
|
|
130
|
+
if (fs.existsSync(patternsSource) && !fs.existsSync(patternsTarget)) {
|
|
131
|
+
await fs.copy(patternsSource, patternsTarget);
|
|
132
|
+
console.log(chalk.dim(` - Damage control: patterns.yaml created`));
|
|
133
|
+
} else if (fs.existsSync(patternsTarget)) {
|
|
134
|
+
console.log(chalk.dim(` - Damage control: patterns.yaml preserved`));
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Setup hooks in settings.json (unless disabled)
|
|
138
|
+
if (!options.skipDamageControl) {
|
|
139
|
+
await this.setupDamageControlHooks(claudeDir);
|
|
140
|
+
console.log(chalk.dim(` - Damage control: hooks enabled`));
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Add PreToolUse hooks to settings.json
|
|
146
|
+
* @param {string} claudeDir - .claude directory path
|
|
147
|
+
*/
|
|
148
|
+
async setupDamageControlHooks(claudeDir) {
|
|
149
|
+
const settingsPath = path.join(claudeDir, 'settings.json');
|
|
150
|
+
let settings = {};
|
|
151
|
+
|
|
152
|
+
// Load existing settings
|
|
153
|
+
if (fs.existsSync(settingsPath)) {
|
|
154
|
+
try {
|
|
155
|
+
settings = JSON.parse(fs.readFileSync(settingsPath, 'utf8'));
|
|
156
|
+
} catch (e) {
|
|
157
|
+
settings = {};
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Initialize hooks structure
|
|
162
|
+
if (!settings.hooks) settings.hooks = {};
|
|
163
|
+
if (!settings.hooks.PreToolUse) settings.hooks.PreToolUse = [];
|
|
164
|
+
|
|
165
|
+
// Define damage control hooks
|
|
166
|
+
const damageControlHooks = [
|
|
167
|
+
{
|
|
168
|
+
matcher: 'Bash',
|
|
169
|
+
hooks: [
|
|
170
|
+
{
|
|
171
|
+
type: 'command',
|
|
172
|
+
command:
|
|
173
|
+
'node $CLAUDE_PROJECT_DIR/.claude/hooks/damage-control/bash-tool-damage-control.js',
|
|
174
|
+
timeout: 5000,
|
|
175
|
+
},
|
|
176
|
+
],
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
matcher: 'Edit',
|
|
180
|
+
hooks: [
|
|
181
|
+
{
|
|
182
|
+
type: 'command',
|
|
183
|
+
command:
|
|
184
|
+
'node $CLAUDE_PROJECT_DIR/.claude/hooks/damage-control/edit-tool-damage-control.js',
|
|
185
|
+
timeout: 5000,
|
|
186
|
+
},
|
|
187
|
+
],
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
matcher: 'Write',
|
|
191
|
+
hooks: [
|
|
192
|
+
{
|
|
193
|
+
type: 'command',
|
|
194
|
+
command:
|
|
195
|
+
'node $CLAUDE_PROJECT_DIR/.claude/hooks/damage-control/write-tool-damage-control.js',
|
|
196
|
+
timeout: 5000,
|
|
197
|
+
},
|
|
198
|
+
],
|
|
199
|
+
},
|
|
200
|
+
];
|
|
201
|
+
|
|
202
|
+
// Merge with existing hooks (don't duplicate)
|
|
203
|
+
for (const newHook of damageControlHooks) {
|
|
204
|
+
const existingIdx = settings.hooks.PreToolUse.findIndex(h => h.matcher === newHook.matcher);
|
|
205
|
+
if (existingIdx === -1) {
|
|
206
|
+
// No existing matcher, add new
|
|
207
|
+
settings.hooks.PreToolUse.push(newHook);
|
|
208
|
+
} else {
|
|
209
|
+
// Existing matcher, merge hooks array
|
|
210
|
+
const existing = settings.hooks.PreToolUse[existingIdx];
|
|
211
|
+
if (!existing.hooks) existing.hooks = [];
|
|
212
|
+
|
|
213
|
+
// Check if damage control hook already exists
|
|
214
|
+
const dcHook = newHook.hooks[0];
|
|
215
|
+
const hasDcHook = existing.hooks.some(
|
|
216
|
+
h => h.type === 'command' && h.command && h.command.includes('damage-control')
|
|
217
|
+
);
|
|
218
|
+
|
|
219
|
+
if (!hasDcHook) {
|
|
220
|
+
// Add at beginning for priority
|
|
221
|
+
existing.hooks.unshift(dcHook);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// Write settings
|
|
227
|
+
await fs.writeFile(settingsPath, JSON.stringify(settings, null, 2));
|
|
228
|
+
}
|
|
89
229
|
}
|
|
90
230
|
|
|
91
231
|
module.exports = { ClaudeCodeSetup };
|
|
@@ -9,7 +9,8 @@ const fs = require('fs');
|
|
|
9
9
|
|
|
10
10
|
class Dashboard {
|
|
11
11
|
constructor(options = {}) {
|
|
12
|
-
this.statusPath =
|
|
12
|
+
this.statusPath =
|
|
13
|
+
options.statusPath || path.join(process.cwd(), 'docs', '09-agents', 'status.json');
|
|
13
14
|
this.data = null;
|
|
14
15
|
}
|
|
15
16
|
|
|
@@ -29,9 +30,7 @@ class Dashboard {
|
|
|
29
30
|
|
|
30
31
|
getStories() {
|
|
31
32
|
if (!this.data) return [];
|
|
32
|
-
return Object.values(this.data).filter(
|
|
33
|
-
s => s && typeof s === 'object' && (s.id || s.story_id)
|
|
34
|
-
);
|
|
33
|
+
return Object.values(this.data).filter(s => s && typeof s === 'object' && (s.id || s.story_id));
|
|
35
34
|
}
|
|
36
35
|
|
|
37
36
|
getStats() {
|
package/tools/postinstall.js
CHANGED
|
@@ -10,15 +10,7 @@
|
|
|
10
10
|
const { execSync } = require('node:child_process');
|
|
11
11
|
const path = require('node:path');
|
|
12
12
|
const fs = require('node:fs');
|
|
13
|
-
|
|
14
|
-
// ANSI color codes for terminal output
|
|
15
|
-
const colors = {
|
|
16
|
-
green: '\x1b[32m',
|
|
17
|
-
yellow: '\x1b[33m',
|
|
18
|
-
blue: '\x1b[36m',
|
|
19
|
-
dim: '\x1b[2m',
|
|
20
|
-
reset: '\x1b[0m',
|
|
21
|
-
};
|
|
13
|
+
const { c: colors } = require('../lib/colors');
|
|
22
14
|
|
|
23
15
|
function log(message, color = 'reset') {
|
|
24
16
|
console.log(`${colors[color]}${message}${colors.reset}`);
|