agileflow 3.0.1 → 3.1.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/CHANGELOG.md +10 -0
- package/README.md +8 -8
- package/lib/api-server.js +3 -2
- package/lib/feedback.js +9 -2
- package/lib/flag-detection.js +4 -2
- package/lib/git-operations.js +4 -2
- package/lib/lazy-require.js +59 -0
- package/lib/process-executor.js +24 -9
- package/lib/skill-loader.js +11 -3
- package/package.json +1 -1
- package/scripts/agileflow-configure.js +12 -0
- package/scripts/agileflow-welcome.js +146 -90
- package/scripts/claude-tmux.sh +42 -6
- package/scripts/damage-control-multi-agent.js +14 -10
- package/scripts/lib/bus-utils.js +3 -1
- package/scripts/lib/configure-detect.js +12 -9
- package/scripts/lib/configure-features.js +128 -7
- package/scripts/lib/configure-repair.js +6 -5
- package/scripts/lib/context-formatter.js +13 -3
- package/scripts/lib/damage-control-utils.js +5 -1
- package/scripts/lib/lifecycle-detector.js +5 -3
- package/scripts/lib/process-cleanup.js +8 -4
- package/scripts/lib/scale-detector.js +47 -8
- package/scripts/lib/signal-detectors.js +117 -59
- package/scripts/lib/task-registry.js +5 -1
- package/scripts/lib/team-events.js +4 -4
- package/scripts/messaging-bridge.js +7 -1
- package/scripts/ralph-loop.js +10 -8
- package/scripts/smart-detect.js +32 -11
- package/scripts/team-manager.js +86 -1
- package/scripts/tmux-task-name.sh +105 -0
- package/scripts/tmux-task-watcher.sh +344 -0
- package/src/core/agents/legal-analyzer-a11y.md +110 -0
- package/src/core/agents/legal-analyzer-ai.md +117 -0
- package/src/core/agents/legal-analyzer-consumer.md +108 -0
- package/src/core/agents/legal-analyzer-content.md +113 -0
- package/src/core/agents/legal-analyzer-international.md +115 -0
- package/src/core/agents/legal-analyzer-licensing.md +115 -0
- package/src/core/agents/legal-analyzer-privacy.md +108 -0
- package/src/core/agents/legal-analyzer-security.md +112 -0
- package/src/core/agents/legal-analyzer-terms.md +111 -0
- package/src/core/agents/legal-consensus.md +242 -0
- package/src/core/agents/team-lead.md +50 -13
- package/src/core/commands/babysit.md +75 -42
- package/src/core/commands/blockers.md +7 -7
- package/src/core/commands/configure.md +15 -61
- package/src/core/commands/discovery/brief.md +363 -0
- package/src/core/commands/discovery/new.md +395 -0
- package/src/core/commands/ideate/new.md +5 -5
- package/src/core/commands/legal/audit.md +446 -0
- package/src/core/commands/logic/audit.md +5 -5
- package/src/core/commands/review.md +7 -1
- package/src/core/commands/rpi.md +61 -26
- package/src/core/commands/sprint.md +7 -6
- package/src/core/commands/team/start.md +36 -7
- package/src/core/commands/team/stop.md +5 -2
- package/src/core/templates/product-brief.md +136 -0
- package/tools/cli/installers/ide/claude-code.js +69 -2
- package/src/core/agents/configuration/archival.md +0 -350
- package/src/core/agents/configuration/attribution.md +0 -343
- package/src/core/agents/configuration/ci.md +0 -1103
- package/src/core/agents/configuration/damage-control.md +0 -375
- package/src/core/agents/configuration/git-config.md +0 -537
- package/src/core/agents/configuration/hooks.md +0 -623
- package/src/core/agents/configuration/precompact.md +0 -302
- package/src/core/agents/configuration/status-line.md +0 -557
- package/src/core/agents/configuration/verify.md +0 -618
- package/src/core/agents/configuration-damage-control.md +0 -259
- package/src/core/agents/configuration-visual-e2e.md +0 -339
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [3.1.0] - 2026-02-14
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- Legal audit system, native Agent Teams integration, and startup performance improvements
|
|
14
|
+
|
|
15
|
+
## [3.0.2] - 2026-02-14
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
- Automatic tmux window naming and configuration agent consolidation
|
|
19
|
+
|
|
10
20
|
## [3.0.1] - 2026-02-13
|
|
11
21
|
|
|
12
22
|
### Fixed
|
package/README.md
CHANGED
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
</p>
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/agileflow)
|
|
6
|
-
[](docs/04-architecture/commands.md)
|
|
7
|
+
[](docs/04-architecture/subagents.md)
|
|
8
8
|
[](docs/04-architecture/skills.md)
|
|
9
9
|
|
|
10
10
|
**AI-driven agile development for Claude Code, Cursor, Windsurf, OpenAI Codex CLI, and more.** Combining Scrum, Kanban, ADRs, and docs-as-code principles into one framework-agnostic system.
|
|
@@ -39,9 +39,9 @@ npx agileflow@latest update
|
|
|
39
39
|
| IDE | Status | Config Location |
|
|
40
40
|
|-----|--------|-----------------|
|
|
41
41
|
| Claude Code | Supported | `.claude/commands/agileflow/` |
|
|
42
|
-
| Cursor | Supported | `.cursor/
|
|
42
|
+
| Cursor | Supported | `.cursor/commands/agileflow/` |
|
|
43
43
|
| Windsurf | Supported | `.windsurf/workflows/agileflow/` |
|
|
44
|
-
| OpenAI Codex CLI | Supported | `.codex/skills/` |
|
|
44
|
+
| OpenAI Codex CLI | Supported | `.codex/skills/` and `~/.codex/prompts/` |
|
|
45
45
|
|
|
46
46
|
---
|
|
47
47
|
|
|
@@ -65,8 +65,8 @@ AgileFlow combines three proven methodologies:
|
|
|
65
65
|
|
|
66
66
|
| Component | Count | Description |
|
|
67
67
|
|-----------|-------|-------------|
|
|
68
|
-
| [Commands](docs/04-architecture/commands.md) |
|
|
69
|
-
| [Agents/Experts](docs/04-architecture/subagents.md) |
|
|
68
|
+
| [Commands](docs/04-architecture/commands.md) | 94 | Slash commands for agile workflows |
|
|
69
|
+
| [Agents/Experts](docs/04-architecture/subagents.md) | 55 | Specialized agents with self-improving knowledge bases |
|
|
70
70
|
| [Skills](docs/04-architecture/skills.md) | Dynamic | Generated on-demand with `/agileflow:skill:create` |
|
|
71
71
|
|
|
72
72
|
---
|
|
@@ -76,8 +76,8 @@ AgileFlow combines three proven methodologies:
|
|
|
76
76
|
Full documentation lives in [`docs/04-architecture/`](docs/04-architecture/):
|
|
77
77
|
|
|
78
78
|
### Reference
|
|
79
|
-
- [Commands](docs/04-architecture/commands.md) - All
|
|
80
|
-
- [Agents/Experts](docs/04-architecture/subagents.md) -
|
|
79
|
+
- [Commands](docs/04-architecture/commands.md) - All 94 slash commands
|
|
80
|
+
- [Agents/Experts](docs/04-architecture/subagents.md) - 55 specialized agents with self-improving knowledge
|
|
81
81
|
- [Skills](docs/04-architecture/skills.md) - Dynamic skill generator with MCP integration
|
|
82
82
|
|
|
83
83
|
### Architecture
|
package/lib/api-server.js
CHANGED
|
@@ -71,7 +71,7 @@ class ApiCache {
|
|
|
71
71
|
* @returns {{ server: http.Server, options: Object, cache: ApiCache }}
|
|
72
72
|
*/
|
|
73
73
|
function createApiServer(options = {}) {
|
|
74
|
-
const port = options.port
|
|
74
|
+
const port = options.port != null ? options.port : DEFAULT_PORT;
|
|
75
75
|
const host = options.host || DEFAULT_HOST;
|
|
76
76
|
const rootDir = options.rootDir || getProjectRoot();
|
|
77
77
|
const cacheTTL = options.cacheTTL || 2000;
|
|
@@ -238,7 +238,8 @@ function startApiServer(serverInstance) {
|
|
|
238
238
|
});
|
|
239
239
|
|
|
240
240
|
server.listen(port, host, () => {
|
|
241
|
-
const
|
|
241
|
+
const actualPort = server.address().port;
|
|
242
|
+
const url = `http://${host}:${actualPort}`;
|
|
242
243
|
console.log(`[AgileFlow API] Server running at ${url}`);
|
|
243
244
|
console.log(`[AgileFlow API] Project root: ${options.rootDir}`);
|
|
244
245
|
resolve({
|
package/lib/feedback.js
CHANGED
|
@@ -34,7 +34,14 @@
|
|
|
34
34
|
*/
|
|
35
35
|
|
|
36
36
|
const { c, BRAND_HEX } = require('./colors');
|
|
37
|
-
const
|
|
37
|
+
const { lazyRequire } = require('./lazy-require');
|
|
38
|
+
|
|
39
|
+
// Lazy-load chalk: feedback.js is imported by scripts that run as hooks in
|
|
40
|
+
// user projects (.agileflow/scripts/). If chalk isn't resolvable from the
|
|
41
|
+
// user's node_modules the eager require() would crash every hook that
|
|
42
|
+
// imports feedback. Deferring the require() to the single call-site that
|
|
43
|
+
// actually needs chalk (brand()) avoids the crash entirely.
|
|
44
|
+
const getChalk = lazyRequire('chalk');
|
|
38
45
|
|
|
39
46
|
// Symbols for consistent output
|
|
40
47
|
const SYMBOLS = {
|
|
@@ -182,7 +189,7 @@ class Feedback {
|
|
|
182
189
|
brand(message) {
|
|
183
190
|
if (this.quiet) return this;
|
|
184
191
|
const prefix = this._indent();
|
|
185
|
-
console.log(`${prefix}${
|
|
192
|
+
console.log(`${prefix}${getChalk().hex(BRAND_HEX)(message)}`);
|
|
186
193
|
return this;
|
|
187
194
|
}
|
|
188
195
|
|
package/lib/flag-detection.js
CHANGED
|
@@ -219,7 +219,8 @@ function detectFromPs() {
|
|
|
219
219
|
// Get command line for this PID
|
|
220
220
|
let cmdline;
|
|
221
221
|
const cmdResult = executeCommandSync('ps', ['-p', String(pid), '-o', 'args='], {
|
|
222
|
-
timeout: 1000,
|
|
222
|
+
timeout: 1000,
|
|
223
|
+
fallback: null,
|
|
223
224
|
});
|
|
224
225
|
if (!cmdResult.ok || cmdResult.data === null) break;
|
|
225
226
|
cmdline = cmdResult.data;
|
|
@@ -239,7 +240,8 @@ function detectFromPs() {
|
|
|
239
240
|
|
|
240
241
|
// Get parent PID
|
|
241
242
|
const ppidResult = executeCommandSync('ps', ['-p', String(pid), '-o', 'ppid='], {
|
|
242
|
-
timeout: 1000,
|
|
243
|
+
timeout: 1000,
|
|
244
|
+
fallback: null,
|
|
243
245
|
});
|
|
244
246
|
if (!ppidResult.ok || ppidResult.data === null) break;
|
|
245
247
|
pid = parseInt(ppidResult.data, 10);
|
package/lib/git-operations.js
CHANGED
|
@@ -176,12 +176,14 @@ function getSessionPhase(session) {
|
|
|
176
176
|
try {
|
|
177
177
|
const mainBranch = getMainBranch(sessionPath);
|
|
178
178
|
const commitResult = git(['rev-list', '--count', `${mainBranch}..HEAD`], {
|
|
179
|
-
cwd: sessionPath,
|
|
179
|
+
cwd: sessionPath,
|
|
180
|
+
fallback: '0',
|
|
180
181
|
});
|
|
181
182
|
const commits = parseInt(commitResult.data, 10);
|
|
182
183
|
|
|
183
184
|
const statusResult = git(['status', '--porcelain'], {
|
|
184
|
-
cwd: sessionPath,
|
|
185
|
+
cwd: sessionPath,
|
|
186
|
+
fallback: '',
|
|
185
187
|
});
|
|
186
188
|
const status = statusResult.data;
|
|
187
189
|
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* lazy-require.js - Reusable Lazy-Loading Utility
|
|
3
|
+
*
|
|
4
|
+
* AgileFlow scripts are copied to user projects (.agileflow/scripts/) and run
|
|
5
|
+
* as hooks. When these scripts eagerly require() npm dependencies at module
|
|
6
|
+
* load time, they crash if the dependency isn't resolvable from the user's
|
|
7
|
+
* project directory. This utility standardizes the lazy-loading pattern used
|
|
8
|
+
* ad-hoc in yaml-utils.js and dashboard-server.js.
|
|
9
|
+
*
|
|
10
|
+
* Usage:
|
|
11
|
+
* const { lazyRequire } = require('./lazy-require');
|
|
12
|
+
*
|
|
13
|
+
* // Returns a getter function; require() is deferred until first call
|
|
14
|
+
* const getChalk = lazyRequire('chalk');
|
|
15
|
+
*
|
|
16
|
+
* // With fallback resolution paths
|
|
17
|
+
* const getYaml = lazyRequire('js-yaml',
|
|
18
|
+
* path.join(__dirname, '..', 'node_modules', 'js-yaml')
|
|
19
|
+
* );
|
|
20
|
+
*
|
|
21
|
+
* // Later, when actually needed:
|
|
22
|
+
* const chalk = getChalk();
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
'use strict';
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Create a lazy-loading getter for an npm module.
|
|
29
|
+
*
|
|
30
|
+
* The returned function defers require() until first invocation, then caches
|
|
31
|
+
* the result. Multiple resolution paths are tried in order, so the module can
|
|
32
|
+
* be found from the user's node_modules, AgileFlow's own node_modules, or any
|
|
33
|
+
* other location.
|
|
34
|
+
*
|
|
35
|
+
* @param {string} name - Primary module name (passed to require())
|
|
36
|
+
* @param {...string} fallbackPaths - Additional paths to try if primary fails
|
|
37
|
+
* @returns {function(): any} Getter that returns the loaded module
|
|
38
|
+
*/
|
|
39
|
+
function lazyRequire(name, ...fallbackPaths) {
|
|
40
|
+
let cached = null;
|
|
41
|
+
return () => {
|
|
42
|
+
if (cached) return cached;
|
|
43
|
+
const paths = [name, ...fallbackPaths];
|
|
44
|
+
for (const p of paths) {
|
|
45
|
+
try {
|
|
46
|
+
cached = require(p);
|
|
47
|
+
return cached;
|
|
48
|
+
} catch (_e) {
|
|
49
|
+
// Continue to next path
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
throw new Error(
|
|
53
|
+
`${name} not found. Run: npm install ${name}\n` +
|
|
54
|
+
'Or reinstall AgileFlow: npx agileflow setup --force'
|
|
55
|
+
);
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
module.exports = { lazyRequire };
|
package/lib/process-executor.js
CHANGED
|
@@ -91,13 +91,20 @@ function executeCommand(cmd, args = [], opts = {}) {
|
|
|
91
91
|
let stderr = '';
|
|
92
92
|
let timedOut = false;
|
|
93
93
|
|
|
94
|
-
const timer =
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
94
|
+
const timer =
|
|
95
|
+
timeout > 0
|
|
96
|
+
? setTimeout(() => {
|
|
97
|
+
timedOut = true;
|
|
98
|
+
proc.kill('SIGTERM');
|
|
99
|
+
}, timeout)
|
|
100
|
+
: null;
|
|
101
|
+
|
|
102
|
+
proc.stdout.on('data', chunk => {
|
|
103
|
+
stdout += chunk;
|
|
104
|
+
});
|
|
105
|
+
proc.stderr.on('data', chunk => {
|
|
106
|
+
stderr += chunk;
|
|
107
|
+
});
|
|
101
108
|
|
|
102
109
|
proc.on('error', err => {
|
|
103
110
|
if (timer) clearTimeout(timer);
|
|
@@ -115,7 +122,11 @@ function executeCommand(cmd, args = [], opts = {}) {
|
|
|
115
122
|
if (fallback !== undefined) {
|
|
116
123
|
resolve({ ok: true, data: fallback });
|
|
117
124
|
} else {
|
|
118
|
-
resolve({
|
|
125
|
+
resolve({
|
|
126
|
+
ok: false,
|
|
127
|
+
error: `Command timed out after ${timeout}ms: ${cmd}`,
|
|
128
|
+
exitCode: null,
|
|
129
|
+
});
|
|
119
130
|
}
|
|
120
131
|
return;
|
|
121
132
|
}
|
|
@@ -124,7 +135,11 @@ function executeCommand(cmd, args = [], opts = {}) {
|
|
|
124
135
|
if (fallback !== undefined) {
|
|
125
136
|
resolve({ ok: true, data: fallback });
|
|
126
137
|
} else {
|
|
127
|
-
const result = {
|
|
138
|
+
const result = {
|
|
139
|
+
ok: false,
|
|
140
|
+
error: `Command failed: ${cmd} ${args.join(' ')} (exit ${code})`,
|
|
141
|
+
exitCode: code,
|
|
142
|
+
};
|
|
128
143
|
if (captureStderr) {
|
|
129
144
|
result.stderr = trim ? stderr.trim() : stderr;
|
|
130
145
|
}
|
package/lib/skill-loader.js
CHANGED
|
@@ -57,13 +57,21 @@ function parseSkillFrontmatter(content) {
|
|
|
57
57
|
let value = trimmed.substring(colonIndex + 1).trim();
|
|
58
58
|
|
|
59
59
|
// Remove surrounding quotes
|
|
60
|
-
if (
|
|
61
|
-
|
|
60
|
+
if (
|
|
61
|
+
(value.startsWith('"') && value.endsWith('"')) ||
|
|
62
|
+
(value.startsWith("'") && value.endsWith("'"))
|
|
63
|
+
) {
|
|
62
64
|
value = value.slice(1, -1);
|
|
63
65
|
}
|
|
64
66
|
|
|
65
67
|
// Type coercion for known fields
|
|
66
|
-
if (
|
|
68
|
+
if (
|
|
69
|
+
key === 'version' ||
|
|
70
|
+
key === 'model' ||
|
|
71
|
+
key === 'category' ||
|
|
72
|
+
key === 'name' ||
|
|
73
|
+
key === 'type'
|
|
74
|
+
) {
|
|
67
75
|
result.metadata[key] = value;
|
|
68
76
|
} else if (value === 'true') {
|
|
69
77
|
result.metadata[key] = true;
|
package/package.json
CHANGED
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
* --enable=<features> Enable specific features
|
|
19
19
|
* --disable=<features> Disable specific features
|
|
20
20
|
* --archival-days=<N> Set archival threshold
|
|
21
|
+
* --startup-mode=<MODE> Set default startup mode (atomic)
|
|
21
22
|
* --migrate Fix old formats without changing features
|
|
22
23
|
* --validate Check for issues
|
|
23
24
|
* --detect Show current status
|
|
@@ -42,6 +43,7 @@ const {
|
|
|
42
43
|
listStatuslineComponents,
|
|
43
44
|
migrateSettings,
|
|
44
45
|
upgradeFeatures,
|
|
46
|
+
enableStartupMode,
|
|
45
47
|
} = require('./lib/configure-features');
|
|
46
48
|
const { listScripts, showVersionInfo, repairScripts } = require('./lib/configure-repair');
|
|
47
49
|
const { feedback } = require('../lib/feedback');
|
|
@@ -144,6 +146,7 @@ ${c.cyan}Statusline Components:${c.reset}
|
|
|
144
146
|
|
|
145
147
|
${c.cyan}Settings:${c.reset}
|
|
146
148
|
--archival-days=N Set archival threshold (default: 30)
|
|
149
|
+
--startup-mode=MODE Set default startup mode (skip-permissions, accept-edits, normal, no-claude)
|
|
147
150
|
|
|
148
151
|
${c.cyan}Maintenance:${c.reset}
|
|
149
152
|
--migrate Fix old/invalid formats
|
|
@@ -201,6 +204,7 @@ function main() {
|
|
|
201
204
|
let repairFeature = null;
|
|
202
205
|
let showVersion = false;
|
|
203
206
|
let listScriptsMode = false;
|
|
207
|
+
let startupMode = null;
|
|
204
208
|
|
|
205
209
|
args.forEach(arg => {
|
|
206
210
|
if (arg.startsWith('--profile=')) profile = arg.split('=')[1];
|
|
@@ -237,6 +241,8 @@ function main() {
|
|
|
237
241
|
repairFeature = arg.split('=')[1].trim().toLowerCase();
|
|
238
242
|
} else if (arg === '--version' || arg === '-v') showVersion = true;
|
|
239
243
|
else if (arg === '--list-scripts' || arg === '--scripts') listScriptsMode = true;
|
|
244
|
+
else if (arg.startsWith('--startup-mode='))
|
|
245
|
+
startupMode = arg.split('=')[1].trim().toLowerCase();
|
|
240
246
|
});
|
|
241
247
|
|
|
242
248
|
// Help mode
|
|
@@ -289,6 +295,12 @@ function main() {
|
|
|
289
295
|
spinner.succeed('Configuration detected');
|
|
290
296
|
const { hasIssues, hasOutdated } = printStatus(status);
|
|
291
297
|
|
|
298
|
+
// Startup mode (atomic - sets BOTH metadata AND settings.json)
|
|
299
|
+
if (startupMode) {
|
|
300
|
+
enableStartupMode(startupMode, VERSION);
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
303
|
+
|
|
292
304
|
// Detect only mode
|
|
293
305
|
if (detect && !migrate && !upgrade && !profile && enable.length === 0 && disable.length === 0) {
|
|
294
306
|
return;
|