agileflow 3.2.0 → 3.3.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 +4 -4
- package/lib/feature-flags.js +32 -4
- package/package.json +1 -1
- package/scripts/babysit-clear-restore.js +154 -0
- package/scripts/claude-tmux.sh +8 -3
- package/scripts/lib/README-portable-tasks.md +424 -0
- package/scripts/lib/browser-qa-evidence.js +409 -0
- package/scripts/lib/browser-qa-status.js +192 -0
- package/scripts/lib/configure-detect.js +20 -0
- package/scripts/lib/feature-catalog.js +11 -0
- package/scripts/lib/team-events.js +42 -5
- package/scripts/tmux-restore-window.sh +67 -0
- package/scripts/tmux-save-closed-window.sh +35 -0
- package/src/core/agents/browser-qa.md +328 -0
- package/src/core/agents/completeness-analyzer-api.md +190 -0
- package/src/core/agents/completeness-analyzer-conditional.md +201 -0
- package/src/core/agents/completeness-analyzer-handlers.md +159 -0
- package/src/core/agents/completeness-analyzer-imports.md +159 -0
- package/src/core/agents/completeness-analyzer-routes.md +182 -0
- package/src/core/agents/completeness-analyzer-state.md +188 -0
- package/src/core/agents/completeness-analyzer-stubs.md +198 -0
- package/src/core/agents/completeness-consensus.md +286 -0
- package/src/core/commands/audit/completeness.md +456 -0
- package/src/core/commands/babysit.md +21 -80
- package/src/core/commands/browser-qa.md +240 -0
- package/src/core/templates/browser-qa-spec.yaml +94 -0
- package/tools/cli/installers/ide/claude-code.js +10 -1
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.3.0] - 2026-02-24
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- Per-agent file tracking, tmux restore, and completeness audit
|
|
14
|
+
|
|
15
|
+
## [3.2.1] - 2026-02-21
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
- Agentic browser QA system with Playwright integration
|
|
19
|
+
|
|
10
20
|
## [3.2.0] - 2026-02-21
|
|
11
21
|
|
|
12
22
|
### Added
|
package/README.md
CHANGED
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
</p>
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/agileflow)
|
|
6
|
-
[](https://docs.agileflow.projectquestorg.com/docs/commands)
|
|
7
|
+
[](https://docs.agileflow.projectquestorg.com/docs/agents)
|
|
8
8
|
[](https://docs.agileflow.projectquestorg.com/docs/features/skills)
|
|
9
9
|
|
|
10
10
|
**AI-driven agile development for Claude Code, Cursor, Windsurf, OpenAI Codex, and more.** Combining Scrum, Kanban, ADRs, and docs-as-code principles into one framework-agnostic system.
|
|
@@ -54,8 +54,8 @@ Traditional project management tools create friction between planning and execut
|
|
|
54
54
|
|
|
55
55
|
| Component | Count | Description |
|
|
56
56
|
|-----------|-------|-------------|
|
|
57
|
-
| [Commands](https://docs.agileflow.projectquestorg.com/docs/commands) |
|
|
58
|
-
| [Agents/Experts](https://docs.agileflow.projectquestorg.com/docs/agents) |
|
|
57
|
+
| [Commands](https://docs.agileflow.projectquestorg.com/docs/commands) | 99 | Slash commands for agile workflows |
|
|
58
|
+
| [Agents/Experts](https://docs.agileflow.projectquestorg.com/docs/agents) | 91 | Specialized agents with self-improving knowledge bases |
|
|
59
59
|
| [Skills](https://docs.agileflow.projectquestorg.com/docs/features/skills) | Dynamic | Generated on-demand with `/agileflow:skill:create` |
|
|
60
60
|
|
|
61
61
|
---
|
package/lib/feature-flags.js
CHANGED
|
@@ -11,6 +11,12 @@
|
|
|
11
11
|
|
|
12
12
|
const fs = require('fs');
|
|
13
13
|
|
|
14
|
+
/**
|
|
15
|
+
* Tools expected to be available when Agent Teams native mode is enabled.
|
|
16
|
+
* Used for feature detection and capability reporting.
|
|
17
|
+
*/
|
|
18
|
+
const AGENT_TEAMS_TOOLS = Object.freeze(['TeamCreate', 'SendMessage', 'ListTeams']);
|
|
19
|
+
|
|
14
20
|
// Lazy-load paths to avoid circular dependency issues
|
|
15
21
|
let _paths;
|
|
16
22
|
function getPaths() {
|
|
@@ -67,6 +73,24 @@ function getAgentTeamsMode(options = {}) {
|
|
|
67
73
|
return 'native';
|
|
68
74
|
}
|
|
69
75
|
|
|
76
|
+
/**
|
|
77
|
+
* Get the list of Agent Teams tools available in the current environment.
|
|
78
|
+
*
|
|
79
|
+
* When Agent Teams is enabled (native mode), returns the expected tool names.
|
|
80
|
+
* When disabled, returns an empty array.
|
|
81
|
+
*
|
|
82
|
+
* @param {object} [options] - Options
|
|
83
|
+
* @param {string} [options.rootDir] - Project root directory
|
|
84
|
+
* @param {object} [options.metadata] - Pre-loaded metadata
|
|
85
|
+
* @returns {string[]} Array of available tool names
|
|
86
|
+
*/
|
|
87
|
+
function getAvailableTools(options = {}) {
|
|
88
|
+
if (!isAgentTeamsEnabled(options)) {
|
|
89
|
+
return [];
|
|
90
|
+
}
|
|
91
|
+
return [...AGENT_TEAMS_TOOLS];
|
|
92
|
+
}
|
|
93
|
+
|
|
70
94
|
/**
|
|
71
95
|
* Get all feature flags as an object.
|
|
72
96
|
*
|
|
@@ -77,10 +101,12 @@ function getAgentTeamsMode(options = {}) {
|
|
|
77
101
|
*/
|
|
78
102
|
function getFeatureFlags(options = {}) {
|
|
79
103
|
const metadata = options.metadata || loadMetadataSafe(options.rootDir);
|
|
104
|
+
const opts = { ...options, metadata };
|
|
80
105
|
|
|
81
106
|
return {
|
|
82
|
-
agentTeams: isAgentTeamsEnabled(
|
|
83
|
-
agentTeamsMode: getAgentTeamsMode(
|
|
107
|
+
agentTeams: isAgentTeamsEnabled(opts),
|
|
108
|
+
agentTeamsMode: getAgentTeamsMode(opts),
|
|
109
|
+
availableTools: getAvailableTools(opts),
|
|
84
110
|
};
|
|
85
111
|
}
|
|
86
112
|
|
|
@@ -93,12 +119,12 @@ function getFeatureFlags(options = {}) {
|
|
|
93
119
|
*/
|
|
94
120
|
function getAgentTeamsDisplayInfo(options = {}) {
|
|
95
121
|
const enabled = isAgentTeamsEnabled(options);
|
|
96
|
-
const mode = getAgentTeamsMode(options);
|
|
97
122
|
|
|
98
123
|
if (enabled) {
|
|
124
|
+
const tools = getAvailableTools(options);
|
|
99
125
|
return {
|
|
100
126
|
label: 'Agent Teams',
|
|
101
|
-
value:
|
|
127
|
+
value: `ENABLED (native, ${tools.length} tools)`,
|
|
102
128
|
status: 'enabled',
|
|
103
129
|
};
|
|
104
130
|
}
|
|
@@ -136,8 +162,10 @@ function loadMetadataSafe(rootDir) {
|
|
|
136
162
|
}
|
|
137
163
|
|
|
138
164
|
module.exports = {
|
|
165
|
+
AGENT_TEAMS_TOOLS,
|
|
139
166
|
isAgentTeamsEnabled,
|
|
140
167
|
getAgentTeamsMode,
|
|
168
|
+
getAvailableTools,
|
|
141
169
|
getFeatureFlags,
|
|
142
170
|
getAgentTeamsDisplayInfo,
|
|
143
171
|
};
|
package/package.json
CHANGED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* babysit-clear-restore.js - SessionStart hook for babysit context preservation
|
|
4
|
+
*
|
|
5
|
+
* When context is cleared (e.g., after plan approval), this hook:
|
|
6
|
+
* 1. Detects source="clear" from Claude Code's SessionStart event
|
|
7
|
+
* 2. Checks if /babysit is active in session-state.json
|
|
8
|
+
* 3. If both, outputs the COMPACT_SUMMARY from the babysit command file
|
|
9
|
+
* 4. Sets last_precompact_at so the welcome script preserves active_commands
|
|
10
|
+
*
|
|
11
|
+
* This eliminates the need to manually embed babysit rules in plan files (Rule #6).
|
|
12
|
+
* The hook automatically injects the rules into the fresh context after clear.
|
|
13
|
+
*
|
|
14
|
+
* Exit codes:
|
|
15
|
+
* 0 = Success (always - SessionStart hooks should never block)
|
|
16
|
+
*
|
|
17
|
+
* Input: JSON on stdin with { source: "startup"|"resume"|"clear"|"compact", ... }
|
|
18
|
+
* Output: Babysit compact summary to stdout (appears as system-reminder)
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
const fs = require('fs');
|
|
22
|
+
const path = require('path');
|
|
23
|
+
|
|
24
|
+
const STDIN_TIMEOUT_MS = 3000;
|
|
25
|
+
|
|
26
|
+
function findProjectRoot() {
|
|
27
|
+
let dir = process.cwd();
|
|
28
|
+
while (dir !== '/') {
|
|
29
|
+
if (fs.existsSync(path.join(dir, '.agileflow'))) return dir;
|
|
30
|
+
if (fs.existsSync(path.join(dir, 'docs', '09-agents'))) return dir;
|
|
31
|
+
dir = path.dirname(dir);
|
|
32
|
+
}
|
|
33
|
+
return process.cwd();
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const ROOT = findProjectRoot();
|
|
37
|
+
|
|
38
|
+
function getSessionState() {
|
|
39
|
+
const statePath = path.join(ROOT, 'docs', '09-agents', 'session-state.json');
|
|
40
|
+
try {
|
|
41
|
+
if (fs.existsSync(statePath)) {
|
|
42
|
+
return JSON.parse(fs.readFileSync(statePath, 'utf8'));
|
|
43
|
+
}
|
|
44
|
+
} catch (e) {
|
|
45
|
+
// Silently fail
|
|
46
|
+
}
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function isBabysitActive(state) {
|
|
51
|
+
if (!state) return false;
|
|
52
|
+
const activeCommands = state.active_commands || [];
|
|
53
|
+
return activeCommands.some(cmd => cmd.name === 'babysit');
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function setPrecompactTimestamp(state) {
|
|
57
|
+
const statePath = path.join(ROOT, 'docs', '09-agents', 'session-state.json');
|
|
58
|
+
try {
|
|
59
|
+
state.last_precompact_at = new Date().toISOString();
|
|
60
|
+
fs.writeFileSync(statePath, JSON.stringify(state, null, 2) + '\n');
|
|
61
|
+
} catch (e) {
|
|
62
|
+
// Silently fail
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function getBabysitCompactSummary() {
|
|
67
|
+
// Search for the babysit command file in known locations
|
|
68
|
+
const locations = [
|
|
69
|
+
path.join(ROOT, 'packages', 'cli', 'src', 'core', 'commands', 'babysit.md'),
|
|
70
|
+
path.join(ROOT, '.agileflow', 'commands', 'babysit.md'),
|
|
71
|
+
path.join(ROOT, '.claude', 'commands', 'agileflow', 'babysit.md'),
|
|
72
|
+
];
|
|
73
|
+
|
|
74
|
+
for (const filePath of locations) {
|
|
75
|
+
try {
|
|
76
|
+
if (!fs.existsSync(filePath)) continue;
|
|
77
|
+
const content = fs.readFileSync(filePath, 'utf8');
|
|
78
|
+
const match = content.match(
|
|
79
|
+
/<!-- COMPACT_SUMMARY_START[\s\S]*?-->([\s\S]*?)<!-- COMPACT_SUMMARY_END -->/
|
|
80
|
+
);
|
|
81
|
+
if (match) {
|
|
82
|
+
return match[1].trim();
|
|
83
|
+
}
|
|
84
|
+
} catch (e) {
|
|
85
|
+
// Try next location
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Read stdin for hook event data
|
|
92
|
+
let inputData = '';
|
|
93
|
+
|
|
94
|
+
process.stdin.setEncoding('utf8');
|
|
95
|
+
|
|
96
|
+
process.stdin.on('data', chunk => {
|
|
97
|
+
inputData += chunk;
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
process.stdin.on('end', () => {
|
|
101
|
+
try {
|
|
102
|
+
const input = JSON.parse(inputData);
|
|
103
|
+
const source = input.source;
|
|
104
|
+
|
|
105
|
+
// Only act on "clear" events (context cleared after plan approval, /clear, etc.)
|
|
106
|
+
if (source !== 'clear') {
|
|
107
|
+
process.exit(0);
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const state = getSessionState();
|
|
112
|
+
if (!isBabysitActive(state)) {
|
|
113
|
+
process.exit(0);
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Set last_precompact_at so the welcome script preserves active_commands
|
|
118
|
+
// instead of clearing them (it checks this timestamp)
|
|
119
|
+
setPrecompactTimestamp(state);
|
|
120
|
+
|
|
121
|
+
// Output the babysit compact summary
|
|
122
|
+
const summary = getBabysitCompactSummary();
|
|
123
|
+
if (summary) {
|
|
124
|
+
console.log('## ACTIVE COMMAND: /agileflow:babysit (restored after context clear)');
|
|
125
|
+
console.log('');
|
|
126
|
+
console.log(summary);
|
|
127
|
+
} else {
|
|
128
|
+
// Fallback: output minimal babysit rules if command file not found
|
|
129
|
+
console.log('## /agileflow:babysit IS ACTIVE (restored after context clear)');
|
|
130
|
+
console.log('');
|
|
131
|
+
console.log('MANDATORY RULES:');
|
|
132
|
+
console.log('1. ALWAYS end responses with AskUserQuestion tool (specific options, not text)');
|
|
133
|
+
console.log('2. Use EnterPlanMode for non-trivial tasks');
|
|
134
|
+
console.log('3. Delegate complex work to domain experts via Task tool');
|
|
135
|
+
console.log('4. Track progress with TaskCreate/TaskUpdate for multi-step work');
|
|
136
|
+
console.log(
|
|
137
|
+
'5. ALWAYS suggest logic audit post-implementation (after tests pass, make Recommended)'
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
} catch (e) {
|
|
141
|
+
// Parse failed or other error - fail open
|
|
142
|
+
}
|
|
143
|
+
process.exit(0);
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
// Handle no stdin (direct invocation or timeout)
|
|
147
|
+
process.stdin.on('error', () => {
|
|
148
|
+
process.exit(0);
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
// Timeout safety - don't hang
|
|
152
|
+
setTimeout(() => {
|
|
153
|
+
process.exit(0);
|
|
154
|
+
}, STDIN_TIMEOUT_MS);
|
package/scripts/claude-tmux.sh
CHANGED
|
@@ -112,6 +112,7 @@ WINDOWS:
|
|
|
112
112
|
Alt+n/p Next/previous window
|
|
113
113
|
Alt+r Rename window
|
|
114
114
|
Alt+w Close window
|
|
115
|
+
Alt+t Reopen closed window
|
|
115
116
|
|
|
116
117
|
PANES:
|
|
117
118
|
Alt+d Split side by side
|
|
@@ -308,8 +309,11 @@ configure_tmux_session() {
|
|
|
308
309
|
# Alt+x to close current pane (with confirmation)
|
|
309
310
|
tmux bind-key -n M-x confirm-before -p "Close pane? (y/n)" kill-pane
|
|
310
311
|
|
|
311
|
-
# Alt+w to close current window (
|
|
312
|
-
tmux bind-key -n M-w confirm-before -p "Close window? (y/n)" kill-window
|
|
312
|
+
# Alt+w to close current window (save state for Alt+T restore, then kill)
|
|
313
|
+
tmux bind-key -n M-w confirm-before -p "Close window? (y/n)" "run-shell '\"\$AGILEFLOW_SCRIPTS/tmux-save-closed-window.sh\"' ; kill-window"
|
|
314
|
+
|
|
315
|
+
# Alt+t to restore the most recently closed window (like Ctrl+Shift+T in browsers)
|
|
316
|
+
tmux bind-key -n M-t run-shell '"$AGILEFLOW_SCRIPTS/tmux-restore-window.sh"'
|
|
313
317
|
|
|
314
318
|
# Alt+n/p for next/previous window
|
|
315
319
|
tmux bind-key -n M-n next-window
|
|
@@ -335,7 +339,7 @@ configure_tmux_session() {
|
|
|
335
339
|
|
|
336
340
|
# ─── Help Panel ──────────────────────────────────────────────────────────
|
|
337
341
|
# Alt+h to show all Alt keybindings in a popup
|
|
338
|
-
tmux bind-key -n M-h display-popup -E -w 52 -h
|
|
342
|
+
tmux bind-key -n M-h display-popup -E -w 52 -h 31 "\
|
|
339
343
|
printf '\\n';\
|
|
340
344
|
printf ' \\033[1;38;5;208mSESSIONS\\033[0m\\n';\
|
|
341
345
|
printf ' Alt+s New Claude session\\n';\
|
|
@@ -348,6 +352,7 @@ configure_tmux_session() {
|
|
|
348
352
|
printf ' Alt+n/p Next / previous window\\n';\
|
|
349
353
|
printf ' Alt+r Rename window\\n';\
|
|
350
354
|
printf ' Alt+w Close window\\n';\
|
|
355
|
+
printf ' Alt+t Reopen closed window\\n';\
|
|
351
356
|
printf '\\n';\
|
|
352
357
|
printf ' \\033[1;38;5;208mPANES\\033[0m\\n';\
|
|
353
358
|
printf ' Alt+d Split side by side\\n';\
|