agileflow 2.78.0 → 2.79.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-welcome.js +31 -84
- package/scripts/auto-self-improve.js +23 -45
- package/scripts/check-update.js +35 -42
- package/scripts/damage-control/bash-tool-damage-control.js +257 -0
- package/scripts/damage-control/edit-tool-damage-control.js +279 -0
- package/scripts/damage-control/patterns.yaml +227 -0
- package/scripts/damage-control/write-tool-damage-control.js +274 -0
- package/scripts/obtain-context.js +22 -3
- package/scripts/ralph-loop.js +191 -63
- package/scripts/screenshot-verifier.js +213 -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/setup/visual-e2e.md +462 -0
- package/src/core/skills/_learnings/code-review.yaml +118 -0
- package/src/core/skills/_learnings/story-writer.yaml +71 -0
- package/tools/cli/installers/ide/claude-code.js +127 -0
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* edit-tool-damage-control.js - Enforce path protection for Edit tool
|
|
5
|
+
*
|
|
6
|
+
* This PreToolUse hook runs before every Edit tool execution.
|
|
7
|
+
* It checks the file path against patterns.yaml to block edits
|
|
8
|
+
* to protected paths.
|
|
9
|
+
*
|
|
10
|
+
* Path protection levels:
|
|
11
|
+
* zeroAccessPaths: Cannot read, write, edit, or delete
|
|
12
|
+
* readOnlyPaths: Can read, cannot modify or delete
|
|
13
|
+
* noDeletePaths: Can read and modify, cannot delete (Edit is allowed)
|
|
14
|
+
*
|
|
15
|
+
* Exit codes:
|
|
16
|
+
* 0 = Allow edit to proceed
|
|
17
|
+
* 2 = Block edit
|
|
18
|
+
*
|
|
19
|
+
* Usage (as PreToolUse hook):
|
|
20
|
+
* node .claude/hooks/damage-control/edit-tool-damage-control.js
|
|
21
|
+
*
|
|
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
|
|
69
|
+
*/
|
|
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: [
|
|
118
|
+
'~/.ssh/',
|
|
119
|
+
'~/.aws/credentials',
|
|
120
|
+
'.env',
|
|
121
|
+
'.env.local',
|
|
122
|
+
'.env.production',
|
|
123
|
+
],
|
|
124
|
+
readOnlyPaths: [
|
|
125
|
+
'/etc/',
|
|
126
|
+
'~/.bashrc',
|
|
127
|
+
'~/.zshrc',
|
|
128
|
+
'package-lock.json',
|
|
129
|
+
'yarn.lock',
|
|
130
|
+
'.git/',
|
|
131
|
+
],
|
|
132
|
+
noDeletePaths: [
|
|
133
|
+
'.agileflow/',
|
|
134
|
+
'.claude/',
|
|
135
|
+
'docs/09-agents/status.json',
|
|
136
|
+
'CLAUDE.md',
|
|
137
|
+
],
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Expand home directory in path
|
|
143
|
+
*/
|
|
144
|
+
function expandHome(filePath) {
|
|
145
|
+
if (filePath.startsWith('~/')) {
|
|
146
|
+
return path.join(process.env.HOME || '', filePath.slice(2));
|
|
147
|
+
}
|
|
148
|
+
return filePath;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Check if a file path matches a pattern
|
|
153
|
+
* Supports:
|
|
154
|
+
* - Exact paths
|
|
155
|
+
* - Directory prefixes (ending with /)
|
|
156
|
+
* - Glob wildcards (**)
|
|
157
|
+
*/
|
|
158
|
+
function pathMatches(filePath, pattern) {
|
|
159
|
+
const expandedPattern = expandHome(pattern);
|
|
160
|
+
const normalizedFile = path.normalize(filePath);
|
|
161
|
+
const normalizedPattern = path.normalize(expandedPattern);
|
|
162
|
+
|
|
163
|
+
// Exact match
|
|
164
|
+
if (normalizedFile === normalizedPattern) return true;
|
|
165
|
+
|
|
166
|
+
// Directory prefix match (pattern ends with /)
|
|
167
|
+
if (pattern.endsWith('/')) {
|
|
168
|
+
if (normalizedFile.startsWith(normalizedPattern)) return true;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// Glob pattern (**/)
|
|
172
|
+
if (pattern.includes('**/')) {
|
|
173
|
+
const globPart = pattern.split('**/')[1];
|
|
174
|
+
if (normalizedFile.includes(globPart)) return true;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// Simple wildcard at end
|
|
178
|
+
if (pattern.endsWith('*')) {
|
|
179
|
+
const prefix = normalizedPattern.slice(0, -1);
|
|
180
|
+
if (normalizedFile.startsWith(prefix)) return true;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// Basename match (for patterns like .env)
|
|
184
|
+
if (!pattern.includes('/') && !pattern.includes(path.sep)) {
|
|
185
|
+
const basename = path.basename(normalizedFile);
|
|
186
|
+
if (basename === pattern) return true;
|
|
187
|
+
// Pattern like .env* matching .env.local
|
|
188
|
+
if (pattern.endsWith('*')) {
|
|
189
|
+
const patternBase = pattern.slice(0, -1);
|
|
190
|
+
if (basename.startsWith(patternBase)) return true;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
return false;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Check if file path is protected
|
|
199
|
+
* Returns: { blocked: boolean, reason: string, level: string }
|
|
200
|
+
*/
|
|
201
|
+
function checkPath(filePath, rules) {
|
|
202
|
+
// Check zero access paths (blocked completely)
|
|
203
|
+
for (const pattern of rules.zeroAccessPaths) {
|
|
204
|
+
if (pathMatches(filePath, pattern)) {
|
|
205
|
+
return {
|
|
206
|
+
blocked: true,
|
|
207
|
+
reason: `Path is in zero-access protected list: ${pattern}`,
|
|
208
|
+
level: 'zero-access',
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// Check read-only paths (cannot edit)
|
|
214
|
+
for (const pattern of rules.readOnlyPaths) {
|
|
215
|
+
if (pathMatches(filePath, pattern)) {
|
|
216
|
+
return {
|
|
217
|
+
blocked: true,
|
|
218
|
+
reason: `Path is read-only: ${pattern}`,
|
|
219
|
+
level: 'read-only',
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// noDeletePaths allows editing, so we don't block here
|
|
225
|
+
// (deletion is handled by a different mechanism or file watcher)
|
|
226
|
+
|
|
227
|
+
return { blocked: false, reason: null, level: null };
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Main entry point
|
|
232
|
+
*/
|
|
233
|
+
function main() {
|
|
234
|
+
const toolInput = process.env.CLAUDE_TOOL_INPUT;
|
|
235
|
+
const projectDir = process.env.CLAUDE_PROJECT_DIR || process.cwd();
|
|
236
|
+
|
|
237
|
+
if (!toolInput) {
|
|
238
|
+
process.exit(EXIT_ALLOW);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
let input;
|
|
242
|
+
try {
|
|
243
|
+
input = JSON.parse(toolInput);
|
|
244
|
+
} catch (e) {
|
|
245
|
+
console.error('Error parsing CLAUDE_TOOL_INPUT:', e.message);
|
|
246
|
+
process.exit(EXIT_ALLOW);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
const filePath = input.file_path;
|
|
250
|
+
if (!filePath) {
|
|
251
|
+
process.exit(EXIT_ALLOW);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// Resolve to absolute path
|
|
255
|
+
const absolutePath = path.isAbsolute(filePath)
|
|
256
|
+
? filePath
|
|
257
|
+
: path.join(projectDir, filePath);
|
|
258
|
+
|
|
259
|
+
// Load rules
|
|
260
|
+
const rules = loadPathRules(projectDir);
|
|
261
|
+
|
|
262
|
+
// Check path
|
|
263
|
+
const result = checkPath(absolutePath, rules);
|
|
264
|
+
|
|
265
|
+
if (result.blocked) {
|
|
266
|
+
console.error(`${c.red}${c.bold}BLOCKED${c.reset}: ${result.reason}`);
|
|
267
|
+
console.error(`${c.yellow}File: ${filePath}${c.reset}`);
|
|
268
|
+
console.error(`${c.cyan}This file is protected by damage control (${result.level}).${c.reset}`);
|
|
269
|
+
process.exit(EXIT_BLOCK);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
process.exit(EXIT_ALLOW);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
if (require.main === module) {
|
|
276
|
+
main();
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
module.exports = { checkPath, loadPathRules, pathMatches };
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
# AgileFlow Damage Control - Security Patterns
|
|
2
|
+
#
|
|
3
|
+
# This file defines patterns for blocking destructive commands and protecting
|
|
4
|
+
# sensitive paths. The damage control hooks read this file to determine
|
|
5
|
+
# whether to allow, block, or ask for confirmation before executing commands.
|
|
6
|
+
#
|
|
7
|
+
# Exit codes from hooks:
|
|
8
|
+
# 0 = Allow command to proceed
|
|
9
|
+
# 2 = Block command (show error to user)
|
|
10
|
+
#
|
|
11
|
+
# To ask for confirmation, hooks output JSON: {"result": "ask", "message": "..."}
|
|
12
|
+
|
|
13
|
+
# ============================================================================
|
|
14
|
+
# BASH TOOL PATTERNS
|
|
15
|
+
# ============================================================================
|
|
16
|
+
# Regex patterns to match against bash commands
|
|
17
|
+
# If matched with ask: false (or no ask key), command is BLOCKED
|
|
18
|
+
# If matched with ask: true, user is asked for confirmation
|
|
19
|
+
|
|
20
|
+
bashToolPatterns:
|
|
21
|
+
# Recursive/force deletion
|
|
22
|
+
- pattern: '\brm\s+-[rRf]'
|
|
23
|
+
reason: "rm with recursive or force flags can destroy entire directories"
|
|
24
|
+
|
|
25
|
+
- pattern: '\brm\s+.*--no-preserve-root'
|
|
26
|
+
reason: "rm with --no-preserve-root is catastrophically dangerous"
|
|
27
|
+
|
|
28
|
+
- pattern: '\brm\s+-rf\s+/'
|
|
29
|
+
reason: "rm -rf on root directory would destroy the entire system"
|
|
30
|
+
|
|
31
|
+
# SQL destructive commands without WHERE clause
|
|
32
|
+
- pattern: 'DELETE\s+FROM\s+\w+\s*;'
|
|
33
|
+
reason: "DELETE without WHERE clause would delete all records"
|
|
34
|
+
|
|
35
|
+
- pattern: 'TRUNCATE\s+(TABLE\s+)?\w+'
|
|
36
|
+
reason: "TRUNCATE removes all data from table"
|
|
37
|
+
|
|
38
|
+
- pattern: 'DROP\s+(TABLE|DATABASE|SCHEMA|INDEX)'
|
|
39
|
+
reason: "DROP commands permanently destroy database objects"
|
|
40
|
+
|
|
41
|
+
# Git force operations
|
|
42
|
+
- pattern: 'git\s+push\s+.*--force'
|
|
43
|
+
reason: "Force push can overwrite remote history"
|
|
44
|
+
ask: true
|
|
45
|
+
|
|
46
|
+
- pattern: 'git\s+push\s+.*-f\b'
|
|
47
|
+
reason: "Force push can overwrite remote history"
|
|
48
|
+
ask: true
|
|
49
|
+
|
|
50
|
+
- pattern: 'git\s+reset\s+--hard'
|
|
51
|
+
reason: "Hard reset discards uncommitted changes"
|
|
52
|
+
ask: true
|
|
53
|
+
|
|
54
|
+
# Format/wipe operations
|
|
55
|
+
- pattern: '\bmkfs\b'
|
|
56
|
+
reason: "mkfs formats filesystems, destroying all data"
|
|
57
|
+
|
|
58
|
+
- pattern: '\bdd\s+.*of=/dev/'
|
|
59
|
+
reason: "dd writing to device can destroy disk data"
|
|
60
|
+
|
|
61
|
+
- pattern: '\bshred\b'
|
|
62
|
+
reason: "shred permanently destroys file data"
|
|
63
|
+
|
|
64
|
+
# Credential/secret exposure
|
|
65
|
+
- pattern: 'cat\s+.*\.env'
|
|
66
|
+
reason: "Displaying .env may expose secrets"
|
|
67
|
+
ask: true
|
|
68
|
+
|
|
69
|
+
- pattern: 'cat\s+.*/\.ssh/'
|
|
70
|
+
reason: "Displaying SSH keys is a security risk"
|
|
71
|
+
|
|
72
|
+
- pattern: 'cat\s+.*/credentials'
|
|
73
|
+
reason: "Displaying credentials files is a security risk"
|
|
74
|
+
|
|
75
|
+
# Cloud CLI destructive operations
|
|
76
|
+
- pattern: 'aws\s+s3\s+rm\s+--recursive'
|
|
77
|
+
reason: "Recursive S3 delete can destroy entire buckets"
|
|
78
|
+
ask: true
|
|
79
|
+
|
|
80
|
+
- pattern: 'aws\s+ec2\s+terminate-instances'
|
|
81
|
+
reason: "Terminating EC2 instances is irreversible"
|
|
82
|
+
ask: true
|
|
83
|
+
|
|
84
|
+
- pattern: 'gcloud\s+.*delete'
|
|
85
|
+
reason: "GCloud delete operations may be destructive"
|
|
86
|
+
ask: true
|
|
87
|
+
|
|
88
|
+
# Docker cleanup commands
|
|
89
|
+
- pattern: 'docker\s+system\s+prune\s+-a'
|
|
90
|
+
reason: "Docker prune -a removes all unused images"
|
|
91
|
+
ask: true
|
|
92
|
+
|
|
93
|
+
- pattern: 'docker\s+volume\s+rm'
|
|
94
|
+
reason: "Docker volume removal may delete persistent data"
|
|
95
|
+
ask: true
|
|
96
|
+
|
|
97
|
+
# npm/package manager dangerous commands
|
|
98
|
+
- pattern: 'npm\s+unpublish'
|
|
99
|
+
reason: "npm unpublish can break dependent packages"
|
|
100
|
+
ask: true
|
|
101
|
+
|
|
102
|
+
- pattern: 'npm\s+deprecate'
|
|
103
|
+
reason: "npm deprecate affects package visibility"
|
|
104
|
+
ask: true
|
|
105
|
+
|
|
106
|
+
# ============================================================================
|
|
107
|
+
# ASK PATTERNS (CONFIRMATION REQUIRED)
|
|
108
|
+
# ============================================================================
|
|
109
|
+
# These patterns trigger a confirmation prompt but don't block by default
|
|
110
|
+
|
|
111
|
+
askPatterns:
|
|
112
|
+
- pattern: 'DELETE\s+FROM\s+\w+\s+WHERE'
|
|
113
|
+
reason: "Deleting specific records - confirm data is correct"
|
|
114
|
+
|
|
115
|
+
- pattern: 'UPDATE\s+\w+\s+SET'
|
|
116
|
+
reason: "Updating records - confirm scope is correct"
|
|
117
|
+
|
|
118
|
+
- pattern: 'npm\s+publish'
|
|
119
|
+
reason: "Publishing to npm is permanent"
|
|
120
|
+
|
|
121
|
+
- pattern: 'git\s+tag\s+-d'
|
|
122
|
+
reason: "Deleting git tags"
|
|
123
|
+
|
|
124
|
+
- pattern: 'kubectl\s+delete'
|
|
125
|
+
reason: "Kubernetes delete operations"
|
|
126
|
+
|
|
127
|
+
# ============================================================================
|
|
128
|
+
# PATH PROTECTION
|
|
129
|
+
# ============================================================================
|
|
130
|
+
# Three protection levels:
|
|
131
|
+
# zeroAccessPaths: Cannot read, write, edit, or delete
|
|
132
|
+
# readOnlyPaths: Can read, cannot modify or delete
|
|
133
|
+
# noDeletePaths: Can read and modify, cannot delete
|
|
134
|
+
|
|
135
|
+
zeroAccessPaths:
|
|
136
|
+
# System credentials
|
|
137
|
+
- ~/.ssh/
|
|
138
|
+
- ~/.gnupg/
|
|
139
|
+
- ~/.aws/credentials
|
|
140
|
+
- ~/.config/gcloud/
|
|
141
|
+
|
|
142
|
+
# Environment secrets
|
|
143
|
+
- .env
|
|
144
|
+
- .env.local
|
|
145
|
+
- .env.production
|
|
146
|
+
- .env.*.local
|
|
147
|
+
|
|
148
|
+
# Secret files
|
|
149
|
+
- '**/secrets/**'
|
|
150
|
+
- '**/credentials/**'
|
|
151
|
+
- '**/*.pem'
|
|
152
|
+
- '**/*.key'
|
|
153
|
+
- '**/id_rsa'
|
|
154
|
+
- '**/id_ed25519'
|
|
155
|
+
|
|
156
|
+
readOnlyPaths:
|
|
157
|
+
# System config
|
|
158
|
+
- /etc/
|
|
159
|
+
- ~/.bashrc
|
|
160
|
+
- ~/.zshrc
|
|
161
|
+
- ~/.profile
|
|
162
|
+
|
|
163
|
+
# Package locks (should use npm install, not edit directly)
|
|
164
|
+
- package-lock.json
|
|
165
|
+
- yarn.lock
|
|
166
|
+
- pnpm-lock.yaml
|
|
167
|
+
|
|
168
|
+
# Git internals
|
|
169
|
+
- .git/
|
|
170
|
+
|
|
171
|
+
noDeletePaths:
|
|
172
|
+
# AgileFlow core
|
|
173
|
+
- .agileflow/
|
|
174
|
+
- .agileflow/config.json
|
|
175
|
+
- .agileflow/scripts/
|
|
176
|
+
|
|
177
|
+
# Claude Code hooks and commands
|
|
178
|
+
- .claude/
|
|
179
|
+
- .claude/hooks/
|
|
180
|
+
- .claude/commands/
|
|
181
|
+
- .claude/settings.json
|
|
182
|
+
|
|
183
|
+
# Project documentation (can edit, can't delete)
|
|
184
|
+
- docs/09-agents/status.json
|
|
185
|
+
- CLAUDE.md
|
|
186
|
+
- AGENTS.md
|
|
187
|
+
|
|
188
|
+
# ============================================================================
|
|
189
|
+
# AGILEFLOW-SPECIFIC PROTECTION
|
|
190
|
+
# ============================================================================
|
|
191
|
+
# Additional patterns specific to AgileFlow projects
|
|
192
|
+
|
|
193
|
+
agileflowPatterns:
|
|
194
|
+
# Protect AgileFlow infrastructure
|
|
195
|
+
- pattern: 'rm.*\.agileflow'
|
|
196
|
+
reason: "Deleting .agileflow would break AgileFlow installation"
|
|
197
|
+
|
|
198
|
+
- pattern: 'rm.*\.claude'
|
|
199
|
+
reason: "Deleting .claude would break Claude Code configuration"
|
|
200
|
+
|
|
201
|
+
- pattern: 'rm.*status\.json'
|
|
202
|
+
reason: "Deleting status.json would lose story tracking data"
|
|
203
|
+
|
|
204
|
+
# Dangerous npm operations in AgileFlow context
|
|
205
|
+
- pattern: 'npm\s+uninstall\s+agileflow'
|
|
206
|
+
reason: "Uninstalling AgileFlow - confirm this is intentional"
|
|
207
|
+
ask: true
|
|
208
|
+
|
|
209
|
+
# ============================================================================
|
|
210
|
+
# CONFIGURATION
|
|
211
|
+
# ============================================================================
|
|
212
|
+
# Settings for the damage control system
|
|
213
|
+
|
|
214
|
+
config:
|
|
215
|
+
# Log blocked commands for pattern refinement
|
|
216
|
+
logBlocked: true
|
|
217
|
+
logPath: .agileflow/logs/damage-control.log
|
|
218
|
+
|
|
219
|
+
# Show detailed reason when blocking
|
|
220
|
+
showBlockReason: true
|
|
221
|
+
|
|
222
|
+
# Timeout for hook execution (seconds)
|
|
223
|
+
hookTimeout: 5
|
|
224
|
+
|
|
225
|
+
# Enable/disable prompt hooks (AI-based evaluation)
|
|
226
|
+
promptHooksEnabled: false
|
|
227
|
+
promptHookMessage: "Evaluate if this command could cause irreversible damage. Block if dangerous."
|