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
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* screenshot-verifier.js - Verify all screenshots have been reviewed
|
|
5
|
+
*
|
|
6
|
+
* Part of Visual Mode for UI development. This script checks that all
|
|
7
|
+
* screenshots in a directory have been prefixed with "verified-" to
|
|
8
|
+
* confirm Claude has visually reviewed each one.
|
|
9
|
+
*
|
|
10
|
+
* Usage:
|
|
11
|
+
* node scripts/screenshot-verifier.js # Default: ./screenshots
|
|
12
|
+
* node scripts/screenshot-verifier.js --path ./e2e/shots # Custom path
|
|
13
|
+
* node scripts/screenshot-verifier.js --help # Show help
|
|
14
|
+
*
|
|
15
|
+
* Exit codes:
|
|
16
|
+
* 0 - All screenshots verified (or no screenshots found)
|
|
17
|
+
* 1 - Some screenshots missing verified- prefix
|
|
18
|
+
* 2 - Error (directory not found, etc.)
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
const fs = require('fs');
|
|
22
|
+
const path = require('path');
|
|
23
|
+
|
|
24
|
+
// Shared utilities
|
|
25
|
+
const { c } = require('../lib/colors');
|
|
26
|
+
|
|
27
|
+
// Parse command line arguments
|
|
28
|
+
function parseArgs() {
|
|
29
|
+
const args = process.argv.slice(2);
|
|
30
|
+
const options = {
|
|
31
|
+
path: './screenshots',
|
|
32
|
+
help: false,
|
|
33
|
+
quiet: false,
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
for (let i = 0; i < args.length; i++) {
|
|
37
|
+
const arg = args[i];
|
|
38
|
+
|
|
39
|
+
if (arg === '--help' || arg === '-h') {
|
|
40
|
+
options.help = true;
|
|
41
|
+
} else if (arg === '--quiet' || arg === '-q') {
|
|
42
|
+
options.quiet = true;
|
|
43
|
+
} else if (arg === '--path' || arg === '-p') {
|
|
44
|
+
if (args[i + 1]) {
|
|
45
|
+
options.path = args[i + 1];
|
|
46
|
+
i++;
|
|
47
|
+
}
|
|
48
|
+
} else if (!arg.startsWith('-')) {
|
|
49
|
+
// Positional argument - treat as path
|
|
50
|
+
options.path = arg;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return options;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Show help message
|
|
58
|
+
function showHelp() {
|
|
59
|
+
console.log(`
|
|
60
|
+
${c.brand}${c.bold}screenshot-verifier${c.reset} - Verify all screenshots have been reviewed
|
|
61
|
+
|
|
62
|
+
${c.bold}USAGE${c.reset}
|
|
63
|
+
node screenshot-verifier.js [OPTIONS] [PATH]
|
|
64
|
+
|
|
65
|
+
${c.bold}OPTIONS${c.reset}
|
|
66
|
+
--path, -p <dir> Directory containing screenshots (default: ./screenshots)
|
|
67
|
+
--quiet, -q Only output on failure
|
|
68
|
+
--help, -h Show this help message
|
|
69
|
+
|
|
70
|
+
${c.bold}EXAMPLES${c.reset}
|
|
71
|
+
node screenshot-verifier.js # Check ./screenshots
|
|
72
|
+
node screenshot-verifier.js ./tests/e2e/shots # Check custom path
|
|
73
|
+
node screenshot-verifier.js --path ./shots -q # Quiet mode
|
|
74
|
+
|
|
75
|
+
${c.bold}EXIT CODES${c.reset}
|
|
76
|
+
0 - All screenshots verified (or no screenshots found)
|
|
77
|
+
1 - Some screenshots missing 'verified-' prefix
|
|
78
|
+
2 - Error (directory not found, etc.)
|
|
79
|
+
|
|
80
|
+
${c.bold}VISUAL MODE${c.reset}
|
|
81
|
+
This script is part of AgileFlow's Visual Mode for UI development.
|
|
82
|
+
|
|
83
|
+
Workflow:
|
|
84
|
+
1. Playwright tests create screenshots in the target directory
|
|
85
|
+
2. Claude reviews each screenshot visually
|
|
86
|
+
3. Claude renames verified screenshots with 'verified-' prefix
|
|
87
|
+
4. This script confirms all screenshots have been reviewed
|
|
88
|
+
|
|
89
|
+
The 'verified-' prefix ensures Claude actually looked at each image
|
|
90
|
+
rather than declaring completion prematurely.
|
|
91
|
+
`);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Get all image files in directory
|
|
95
|
+
function getImageFiles(dir) {
|
|
96
|
+
const imageExtensions = ['.png', '.jpg', '.jpeg', '.webp', '.gif'];
|
|
97
|
+
|
|
98
|
+
try {
|
|
99
|
+
const files = fs.readdirSync(dir);
|
|
100
|
+
return files.filter(file => {
|
|
101
|
+
const ext = path.extname(file).toLowerCase();
|
|
102
|
+
return imageExtensions.includes(ext);
|
|
103
|
+
});
|
|
104
|
+
} catch (err) {
|
|
105
|
+
if (err.code === 'ENOENT') {
|
|
106
|
+
return null; // Directory doesn't exist
|
|
107
|
+
}
|
|
108
|
+
throw err;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Main verification logic
|
|
113
|
+
function verifyScreenshots(options) {
|
|
114
|
+
const dir = path.resolve(options.path);
|
|
115
|
+
|
|
116
|
+
// Check if directory exists
|
|
117
|
+
if (!fs.existsSync(dir)) {
|
|
118
|
+
if (!options.quiet) {
|
|
119
|
+
console.log(`${c.yellow}No screenshots directory found at: ${dir}${c.reset}`);
|
|
120
|
+
console.log(`${c.dim}Create the directory or run tests to generate screenshots.${c.reset}`);
|
|
121
|
+
}
|
|
122
|
+
return { success: true, total: 0, verified: 0, unverified: [] };
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Get all image files
|
|
126
|
+
const files = getImageFiles(dir);
|
|
127
|
+
|
|
128
|
+
if (files === null) {
|
|
129
|
+
console.error(`${c.red}Error: Could not read directory: ${dir}${c.reset}`);
|
|
130
|
+
process.exit(2);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (files.length === 0) {
|
|
134
|
+
if (!options.quiet) {
|
|
135
|
+
console.log(`${c.yellow}No screenshots found in: ${dir}${c.reset}`);
|
|
136
|
+
}
|
|
137
|
+
return { success: true, total: 0, verified: 0, unverified: [] };
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Check each file for verified- prefix
|
|
141
|
+
const verified = [];
|
|
142
|
+
const unverified = [];
|
|
143
|
+
|
|
144
|
+
for (const file of files) {
|
|
145
|
+
if (file.startsWith('verified-')) {
|
|
146
|
+
verified.push(file);
|
|
147
|
+
} else {
|
|
148
|
+
unverified.push(file);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
return {
|
|
153
|
+
success: unverified.length === 0,
|
|
154
|
+
total: files.length,
|
|
155
|
+
verified: verified.length,
|
|
156
|
+
unverified,
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Format result output
|
|
161
|
+
function formatResult(result, options) {
|
|
162
|
+
if (options.quiet && result.success) {
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
console.log('');
|
|
167
|
+
|
|
168
|
+
if (result.total === 0) {
|
|
169
|
+
console.log(`${c.yellow}No screenshots to verify${c.reset}`);
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if (result.success) {
|
|
174
|
+
console.log(`${c.green}${c.bold}All screenshots verified${c.reset}`);
|
|
175
|
+
console.log(
|
|
176
|
+
`${c.dim}${result.verified}/${result.total} screenshots have 'verified-' prefix${c.reset}`
|
|
177
|
+
);
|
|
178
|
+
} else {
|
|
179
|
+
console.log(`${c.red}${c.bold}Unverified screenshots found${c.reset}`);
|
|
180
|
+
console.log(`${c.dim}${result.verified}/${result.total} verified${c.reset}`);
|
|
181
|
+
console.log('');
|
|
182
|
+
console.log(`${c.yellow}Missing 'verified-' prefix:${c.reset}`);
|
|
183
|
+
for (const file of result.unverified) {
|
|
184
|
+
console.log(` ${c.red}- ${file}${c.reset}`);
|
|
185
|
+
}
|
|
186
|
+
console.log('');
|
|
187
|
+
console.log(`${c.cyan}To verify: Review each screenshot visually, then rename:${c.reset}`);
|
|
188
|
+
console.log(`${c.dim} mv screenshots/example.png screenshots/verified-example.png${c.reset}`);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
console.log('');
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// Main entry point
|
|
195
|
+
function main() {
|
|
196
|
+
const options = parseArgs();
|
|
197
|
+
|
|
198
|
+
if (options.help) {
|
|
199
|
+
showHelp();
|
|
200
|
+
process.exit(0);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
const result = verifyScreenshots(options);
|
|
204
|
+
formatResult(result, options);
|
|
205
|
+
|
|
206
|
+
process.exit(result.success ? 0 : 1);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// Run if called directly
|
|
210
|
+
if (require.main === module) {
|
|
211
|
+
main();
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// Export for testing
|
|
215
|
+
module.exports = { verifyScreenshots, getImageFiles };
|
|
@@ -13,30 +13,10 @@ const fs = require('fs');
|
|
|
13
13
|
const path = require('path');
|
|
14
14
|
const { execSync, spawnSync } = require('child_process');
|
|
15
15
|
|
|
16
|
-
//
|
|
17
|
-
const c =
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
dim: '\x1b[2m',
|
|
21
|
-
red: '\x1b[31m',
|
|
22
|
-
green: '\x1b[32m',
|
|
23
|
-
yellow: '\x1b[33m',
|
|
24
|
-
blue: '\x1b[34m',
|
|
25
|
-
cyan: '\x1b[36m',
|
|
26
|
-
brand: '\x1b[38;2;232;104;58m',
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
// Find project root (has .agileflow or .git)
|
|
30
|
-
function getProjectRoot() {
|
|
31
|
-
let dir = process.cwd();
|
|
32
|
-
while (dir !== '/') {
|
|
33
|
-
if (fs.existsSync(path.join(dir, '.agileflow')) || fs.existsSync(path.join(dir, '.git'))) {
|
|
34
|
-
return dir;
|
|
35
|
-
}
|
|
36
|
-
dir = path.dirname(dir);
|
|
37
|
-
}
|
|
38
|
-
return process.cwd();
|
|
39
|
-
}
|
|
16
|
+
// Shared utilities
|
|
17
|
+
const { c } = require('../lib/colors');
|
|
18
|
+
const { getProjectRoot } = require('../lib/paths');
|
|
19
|
+
const { safeReadJSON } = require('../lib/errors');
|
|
40
20
|
|
|
41
21
|
const ROOT = getProjectRoot();
|
|
42
22
|
const SESSIONS_DIR = path.join(ROOT, '.agileflow', 'sessions');
|
|
@@ -162,17 +142,16 @@ function getCurrentBranch() {
|
|
|
162
142
|
|
|
163
143
|
// Get current story from status.json
|
|
164
144
|
function getCurrentStory() {
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
if (!fs.existsSync(statusPath)) return null;
|
|
145
|
+
const statusPath = path.join(ROOT, 'docs', '09-agents', 'status.json');
|
|
146
|
+
const result = safeReadJSON(statusPath, { defaultValue: null });
|
|
168
147
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
}
|
|
148
|
+
if (!result.ok || !result.data) return null;
|
|
149
|
+
|
|
150
|
+
for (const [id, story] of Object.entries(result.data.stories || {})) {
|
|
151
|
+
if (story.status === 'in_progress') {
|
|
152
|
+
return { id, title: story.title };
|
|
174
153
|
}
|
|
175
|
-
}
|
|
154
|
+
}
|
|
176
155
|
return null;
|
|
177
156
|
}
|
|
178
157
|
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: configuration-damage-control
|
|
3
|
+
description: Configure AgileFlow damage control to protect against destructive commands
|
|
4
|
+
tools: Read, Write, Edit, Bash, Glob, Grep
|
|
5
|
+
model: haiku
|
|
6
|
+
compact_context:
|
|
7
|
+
priority: high
|
|
8
|
+
preserve_rules:
|
|
9
|
+
- "Use AskUserQuestion for all configuration choices"
|
|
10
|
+
- "Copy hook scripts to .claude/hooks/damage-control/"
|
|
11
|
+
- "Create patterns.yaml if not exists, PRESERVE if exists"
|
|
12
|
+
- "Write PreToolUse hooks to .claude/settings.json"
|
|
13
|
+
- "Never overwrite existing patterns without confirmation"
|
|
14
|
+
state_fields:
|
|
15
|
+
- damage_control_enabled
|
|
16
|
+
- protection_level
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
# Configuration: Damage Control
|
|
20
|
+
|
|
21
|
+
Set up damage control protection to block destructive commands and protect sensitive paths.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## What This Does
|
|
26
|
+
|
|
27
|
+
Damage control protects your codebase from destructive agent commands through PreToolUse hooks:
|
|
28
|
+
|
|
29
|
+
1. **Bash Command Validation** - Blocks dangerous commands like `rm -rf`, `DROP TABLE`, force pushes
|
|
30
|
+
2. **Path Protection** - Prevents access to sensitive files (`.env`, `~/.ssh/`, etc.)
|
|
31
|
+
3. **Ask Confirmation** - Prompts before risky-but-valid operations
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Configuration Steps
|
|
36
|
+
|
|
37
|
+
### Step 1: Ask User to Enable
|
|
38
|
+
|
|
39
|
+
```xml
|
|
40
|
+
<invoke name="AskUserQuestion">
|
|
41
|
+
<parameter name="questions">[{
|
|
42
|
+
"question": "Enable damage control to protect against destructive commands?",
|
|
43
|
+
"header": "Damage Control",
|
|
44
|
+
"multiSelect": false,
|
|
45
|
+
"options": [
|
|
46
|
+
{"label": "Enable (Recommended)", "description": "Block dangerous commands and protect sensitive paths"},
|
|
47
|
+
{"label": "Skip", "description": "No damage control (not recommended)"}
|
|
48
|
+
]
|
|
49
|
+
}]</parameter>
|
|
50
|
+
</invoke>
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
If user selects "Skip", exit with message: "Damage control not enabled. Run /agileflow:configure to enable later."
|
|
54
|
+
|
|
55
|
+
### Step 2: Ask Protection Level
|
|
56
|
+
|
|
57
|
+
```xml
|
|
58
|
+
<invoke name="AskUserQuestion">
|
|
59
|
+
<parameter name="questions">[{
|
|
60
|
+
"question": "Choose protection level:",
|
|
61
|
+
"header": "Protection Level",
|
|
62
|
+
"multiSelect": false,
|
|
63
|
+
"options": [
|
|
64
|
+
{"label": "Standard (Recommended)", "description": "Deterministic pattern matching - fast, no AI calls"},
|
|
65
|
+
{"label": "Enhanced", "description": "Standard + AI prompt hook for unknown threats (slower)"}
|
|
66
|
+
]
|
|
67
|
+
}]</parameter>
|
|
68
|
+
</invoke>
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Step 3: Create Hooks Directory
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
mkdir -p .claude/hooks/damage-control
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Step 4: Copy Hook Scripts
|
|
78
|
+
|
|
79
|
+
Copy the following scripts from AgileFlow installation:
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
# Source: .agileflow/scripts/damage-control/
|
|
83
|
+
# Destination: .claude/hooks/damage-control/
|
|
84
|
+
|
|
85
|
+
cp .agileflow/scripts/damage-control/bash-tool-damage-control.js .claude/hooks/damage-control/
|
|
86
|
+
cp .agileflow/scripts/damage-control/edit-tool-damage-control.js .claude/hooks/damage-control/
|
|
87
|
+
cp .agileflow/scripts/damage-control/write-tool-damage-control.js .claude/hooks/damage-control/
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### Step 5: Create or Preserve patterns.yaml
|
|
91
|
+
|
|
92
|
+
**If patterns.yaml does NOT exist**, copy the default:
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
cp .agileflow/scripts/damage-control/patterns.yaml .claude/hooks/damage-control/
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
**If patterns.yaml ALREADY exists**, preserve it (do not overwrite):
|
|
99
|
+
|
|
100
|
+
```
|
|
101
|
+
patterns.yaml already exists - preserving existing rules.
|
|
102
|
+
To update patterns, edit .claude/hooks/damage-control/patterns.yaml
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Step 6: Update settings.json
|
|
106
|
+
|
|
107
|
+
Add PreToolUse hooks to `.claude/settings.json`:
|
|
108
|
+
|
|
109
|
+
**For Standard protection:**
|
|
110
|
+
|
|
111
|
+
```json
|
|
112
|
+
{
|
|
113
|
+
"hooks": {
|
|
114
|
+
"PreToolUse": [
|
|
115
|
+
{
|
|
116
|
+
"matcher": "Bash",
|
|
117
|
+
"hooks": [{
|
|
118
|
+
"type": "command",
|
|
119
|
+
"command": "node $CLAUDE_PROJECT_DIR/.claude/hooks/damage-control/bash-tool-damage-control.js",
|
|
120
|
+
"timeout": 5000
|
|
121
|
+
}]
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
"matcher": "Edit",
|
|
125
|
+
"hooks": [{
|
|
126
|
+
"type": "command",
|
|
127
|
+
"command": "node $CLAUDE_PROJECT_DIR/.claude/hooks/damage-control/edit-tool-damage-control.js",
|
|
128
|
+
"timeout": 5000
|
|
129
|
+
}]
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
"matcher": "Write",
|
|
133
|
+
"hooks": [{
|
|
134
|
+
"type": "command",
|
|
135
|
+
"command": "node $CLAUDE_PROJECT_DIR/.claude/hooks/damage-control/write-tool-damage-control.js",
|
|
136
|
+
"timeout": 5000
|
|
137
|
+
}]
|
|
138
|
+
}
|
|
139
|
+
]
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
**For Enhanced protection (adds prompt hook):**
|
|
145
|
+
|
|
146
|
+
Add to the Bash matcher:
|
|
147
|
+
|
|
148
|
+
```json
|
|
149
|
+
{
|
|
150
|
+
"matcher": "Bash",
|
|
151
|
+
"hooks": [
|
|
152
|
+
{
|
|
153
|
+
"type": "command",
|
|
154
|
+
"command": "node $CLAUDE_PROJECT_DIR/.claude/hooks/damage-control/bash-tool-damage-control.js",
|
|
155
|
+
"timeout": 5000
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
"type": "prompt",
|
|
159
|
+
"prompt": "Evaluate if this bash command is destructive or could cause irreversible damage. Consider: Does it delete files recursively? Does it modify system files? Could it expose secrets? Block if dangerous."
|
|
160
|
+
}
|
|
161
|
+
]
|
|
162
|
+
}
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### Step 7: Merge with Existing Hooks
|
|
166
|
+
|
|
167
|
+
**IMPORTANT**: If PreToolUse hooks already exist in settings.json, MERGE the new hooks with existing ones. Do NOT replace existing hooks.
|
|
168
|
+
|
|
169
|
+
Check for existing hooks:
|
|
170
|
+
```javascript
|
|
171
|
+
// If settings.hooks.PreToolUse exists, append to it
|
|
172
|
+
// If a matcher (Bash, Edit, Write) already exists, merge hooks array
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### Step 8: Show Completion Summary
|
|
176
|
+
|
|
177
|
+
```
|
|
178
|
+
Damage Control Enabled
|
|
179
|
+
|
|
180
|
+
Protection level: Standard (or Enhanced)
|
|
181
|
+
|
|
182
|
+
Protected against:
|
|
183
|
+
- Destructive bash commands (rm -rf, DROP TABLE, etc.)
|
|
184
|
+
- Access to sensitive paths (~/.ssh, .env, etc.)
|
|
185
|
+
- Force pushes and hard resets
|
|
186
|
+
|
|
187
|
+
Configuration:
|
|
188
|
+
- Hook scripts: .claude/hooks/damage-control/
|
|
189
|
+
- Patterns file: .claude/hooks/damage-control/patterns.yaml
|
|
190
|
+
- Settings: .claude/settings.json
|
|
191
|
+
|
|
192
|
+
To customize blocked patterns, edit:
|
|
193
|
+
.claude/hooks/damage-control/patterns.yaml
|
|
194
|
+
|
|
195
|
+
Restart Claude Code for hooks to take effect.
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
---
|
|
199
|
+
|
|
200
|
+
## Patterns.yaml Reference
|
|
201
|
+
|
|
202
|
+
```yaml
|
|
203
|
+
# Block dangerous bash commands
|
|
204
|
+
bashToolPatterns:
|
|
205
|
+
- pattern: '\brm\s+-[rRf]'
|
|
206
|
+
reason: "rm with recursive or force flags"
|
|
207
|
+
|
|
208
|
+
# Commands requiring confirmation
|
|
209
|
+
askPatterns:
|
|
210
|
+
- pattern: 'git\s+push\s+.*--force'
|
|
211
|
+
reason: "Force push overwrites history"
|
|
212
|
+
|
|
213
|
+
# Path protection levels
|
|
214
|
+
zeroAccessPaths: # Cannot read, write, edit, delete
|
|
215
|
+
- ~/.ssh/
|
|
216
|
+
- .env
|
|
217
|
+
|
|
218
|
+
readOnlyPaths: # Can read, cannot modify
|
|
219
|
+
- /etc/
|
|
220
|
+
- package-lock.json
|
|
221
|
+
|
|
222
|
+
noDeletePaths: # Can modify, cannot delete
|
|
223
|
+
- .agileflow/
|
|
224
|
+
- .claude/
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
---
|
|
228
|
+
|
|
229
|
+
## Troubleshooting
|
|
230
|
+
|
|
231
|
+
**Hooks not working after enabling:**
|
|
232
|
+
- Restart Claude Code - hooks only load on startup
|
|
233
|
+
|
|
234
|
+
**Command blocked that should be allowed:**
|
|
235
|
+
- Edit patterns.yaml to remove or adjust the pattern
|
|
236
|
+
- Use `ask: true` instead of blocking
|
|
237
|
+
|
|
238
|
+
**Need to disable damage control:**
|
|
239
|
+
- Remove PreToolUse hooks from .claude/settings.json
|
|
240
|
+
- Or delete .claude/hooks/damage-control/ directory
|
|
241
|
+
|
|
242
|
+
---
|
|
243
|
+
|
|
244
|
+
## Related
|
|
245
|
+
|
|
246
|
+
- Research: `docs/10-research/20260106-claude-code-damage-control-hooks.md`
|
|
247
|
+
- Patterns file: `.claude/hooks/damage-control/patterns.yaml`
|
|
248
|
+
- Hook scripts: `.claude/hooks/damage-control/*.js`
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: Interactive mentor for end-to-end feature implementation
|
|
3
|
-
argument-hint: "[EPIC=<id>] [MODE=loop] [MAX=<iterations>]"
|
|
3
|
+
argument-hint: "[EPIC=<id>] [MODE=loop] [MAX=<iterations>] [VISUAL=true]"
|
|
4
4
|
compact_context:
|
|
5
5
|
priority: critical
|
|
6
6
|
preserve_rules:
|
|
@@ -61,6 +61,7 @@ When invoked with `MODE=loop`, babysit runs autonomously through an epic's stori
|
|
|
61
61
|
| `EPIC` | Yes | Epic ID to process (e.g., EP-0042) |
|
|
62
62
|
| `MODE` | Yes | Must be `loop` for autonomous mode |
|
|
63
63
|
| `MAX` | No | Max iterations (default: 20) |
|
|
64
|
+
| `VISUAL` | No | Enable Visual Mode for UI development (screenshot verification) |
|
|
64
65
|
|
|
65
66
|
### To Start Loop Mode
|
|
66
67
|
|
|
@@ -69,6 +70,9 @@ After running the context script, if EPIC and MODE=loop are specified:
|
|
|
69
70
|
```bash
|
|
70
71
|
# Initialize the loop
|
|
71
72
|
node scripts/ralph-loop.js --init --epic=EP-0042 --max=20
|
|
73
|
+
|
|
74
|
+
# With Visual Mode for UI development
|
|
75
|
+
node scripts/ralph-loop.js --init --epic=EP-0042 --max=20 --visual
|
|
72
76
|
```
|
|
73
77
|
|
|
74
78
|
Or manually write to session-state.json:
|
|
@@ -80,11 +84,35 @@ Or manually write to session-state.json:
|
|
|
80
84
|
"epic": "EP-0042",
|
|
81
85
|
"current_story": "US-0015",
|
|
82
86
|
"iteration": 0,
|
|
83
|
-
"max_iterations": 20
|
|
87
|
+
"max_iterations": 20,
|
|
88
|
+
"visual_mode": false,
|
|
89
|
+
"screenshots_verified": false
|
|
84
90
|
}
|
|
85
91
|
}
|
|
86
92
|
```
|
|
87
93
|
|
|
94
|
+
### Visual Mode
|
|
95
|
+
|
|
96
|
+
When `VISUAL=true` is specified, the loop adds screenshot verification:
|
|
97
|
+
|
|
98
|
+
```
|
|
99
|
+
/agileflow:babysit EPIC=EP-0042 MODE=loop VISUAL=true
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
**Visual Mode behavior:**
|
|
103
|
+
1. After tests pass, runs `screenshot-verifier.js`
|
|
104
|
+
2. Checks all screenshots in `screenshots/` have `verified-` prefix
|
|
105
|
+
3. Requires minimum 2 iterations before completion
|
|
106
|
+
4. Prevents premature completion for UI work
|
|
107
|
+
|
|
108
|
+
**When to use Visual Mode:**
|
|
109
|
+
- UI-focused epics (components, styling, layouts)
|
|
110
|
+
- Shadcn/UI development
|
|
111
|
+
- Any work where visual appearance matters
|
|
112
|
+
|
|
113
|
+
**Setup requirement:**
|
|
114
|
+
Run `/agileflow:setup:visual-e2e` first to install Playwright and create e2e tests.
|
|
115
|
+
|
|
88
116
|
### Loop Control Commands
|
|
89
117
|
|
|
90
118
|
```bash
|
|
@@ -10,7 +10,7 @@ compact_context:
|
|
|
10
10
|
- "CRITICAL: If 🔄 OUTDATED shown → offer --upgrade to re-deploy latest scripts"
|
|
11
11
|
- "MUST backup created on migrate: .claude/settings.json.backup"
|
|
12
12
|
- "MUST show RED RESTART banner after ANY changes (quit, wait 5s, restart)"
|
|
13
|
-
- "Features: sessionstart, precompact, ralphloop, selfimprove, archival, statusline, autoupdate"
|
|
13
|
+
- "Features: sessionstart, precompact, ralphloop, selfimprove, archival, statusline, autoupdate, askuserquestion"
|
|
14
14
|
- "Stop hooks (ralphloop, selfimprove) run when Claude completes or pauses"
|
|
15
15
|
state_fields:
|
|
16
16
|
- detection_status
|
|
@@ -52,7 +52,7 @@ node .agileflow/scripts/agileflow-configure.js --repair=statusline # Fix specif
|
|
|
52
52
|
|
|
53
53
|
### Features
|
|
54
54
|
|
|
55
|
-
`sessionstart`, `precompact`, `ralphloop`, `selfimprove`, `archival`, `statusline`, `autoupdate`
|
|
55
|
+
`sessionstart`, `precompact`, `ralphloop`, `selfimprove`, `archival`, `statusline`, `autoupdate`, `askuserquestion`
|
|
56
56
|
|
|
57
57
|
**Stop hooks** (ralphloop, selfimprove) run when Claude completes or pauses work.
|
|
58
58
|
|
|
@@ -180,12 +180,12 @@ node .agileflow/scripts/agileflow-configure.js --enable=archival --archival-days
|
|
|
180
180
|
|
|
181
181
|
## Profile Details
|
|
182
182
|
|
|
183
|
-
| Profile | SessionStart | PreCompact | RalphLoop | SelfImprove | Archival | StatusLine |
|
|
184
|
-
|
|
185
|
-
| `full` | ✅ | ✅ | ✅ | ✅ | ✅ 30 days | ✅ |
|
|
186
|
-
| `basic` | ✅ | ✅ | ❌ | ❌ | ✅ 30 days | ❌ |
|
|
187
|
-
| `minimal` | ✅ | ❌ | ❌ | ❌ | ✅ 30 days | ❌ |
|
|
188
|
-
| `none` | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
|
|
183
|
+
| Profile | SessionStart | PreCompact | RalphLoop | SelfImprove | Archival | StatusLine | AskUserQuestion |
|
|
184
|
+
|---------|-------------|------------|-----------|-------------|----------|------------|-----------------|
|
|
185
|
+
| `full` | ✅ | ✅ | ✅ | ✅ | ✅ 30 days | ✅ | ✅ |
|
|
186
|
+
| `basic` | ✅ | ✅ | ❌ | ❌ | ✅ 30 days | ❌ | ✅ |
|
|
187
|
+
| `minimal` | ✅ | ❌ | ❌ | ❌ | ✅ 30 days | ❌ | ❌ |
|
|
188
|
+
| `none` | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
|
|
189
189
|
|
|
190
190
|
## Interactive Mode (via /configure command)
|
|
191
191
|
|
|
@@ -226,7 +226,8 @@ Based on selection, run appropriate command.
|
|
|
226
226
|
{"label": "SelfImprove (Stop Hook)", "description": "Auto-update agent expertise from work"},
|
|
227
227
|
{"label": "Archival", "description": "Auto-archive old completed stories"},
|
|
228
228
|
{"label": "Status Line", "description": "Custom status bar"},
|
|
229
|
-
{"label": "Auto-Update", "description": "Automatically update AgileFlow on session start"}
|
|
229
|
+
{"label": "Auto-Update", "description": "Automatically update AgileFlow on session start"},
|
|
230
|
+
{"label": "AskUserQuestion Mode", "description": "End all responses with AskUserQuestion tool for guided interaction"}
|
|
230
231
|
]
|
|
231
232
|
}]</parameter>
|
|
232
233
|
</invoke>
|
|
@@ -240,6 +241,7 @@ Map selections:
|
|
|
240
241
|
- "Archival" → `archival`
|
|
241
242
|
- "Status Line" → `statusline`
|
|
242
243
|
- "Auto-Update" → `autoupdate`
|
|
244
|
+
- "AskUserQuestion Mode" → `askuserquestion`
|
|
243
245
|
|
|
244
246
|
## Auto-Update Configuration
|
|
245
247
|
|
|
@@ -263,6 +265,41 @@ node .agileflow/scripts/agileflow-configure.js --enable=autoupdate
|
|
|
263
265
|
|
|
264
266
|
**Check frequencies:** `hourly`, `daily`, `weekly`, `never`
|
|
265
267
|
|
|
268
|
+
## AskUserQuestion Mode
|
|
269
|
+
|
|
270
|
+
Enable AskUserQuestion to have all commands end with guided options:
|
|
271
|
+
|
|
272
|
+
```bash
|
|
273
|
+
# Enable AskUserQuestion mode
|
|
274
|
+
node .agileflow/scripts/agileflow-configure.js --enable=askuserquestion
|
|
275
|
+
|
|
276
|
+
# Disable AskUserQuestion mode
|
|
277
|
+
node .agileflow/scripts/agileflow-configure.js --disable=askuserquestion
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
**What it does:**
|
|
281
|
+
- When enabled: All commands end with AskUserQuestion tool call (guided options)
|
|
282
|
+
- When disabled: Commands can end with natural text questions
|
|
283
|
+
|
|
284
|
+
**Storage in metadata:**
|
|
285
|
+
```json
|
|
286
|
+
{
|
|
287
|
+
"features": {
|
|
288
|
+
"askUserQuestion": {
|
|
289
|
+
"enabled": true,
|
|
290
|
+
"mode": "all"
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
**Modes:**
|
|
297
|
+
- `all`: All commands use AskUserQuestion (default)
|
|
298
|
+
- `interactive`: Only interactive commands (babysit, mentor, configure, epic-planner)
|
|
299
|
+
- `none`: Disabled
|
|
300
|
+
|
|
301
|
+
The guidance is injected via `obtain-context.js` when commands run.
|
|
302
|
+
|
|
266
303
|
## Stop Hook Features
|
|
267
304
|
|
|
268
305
|
Stop hooks run when Claude completes a task or pauses for user input. These enable autonomous workflows.
|