agileflow 3.2.1 → 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 CHANGED
@@ -7,6 +7,11 @@ 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
+
10
15
  ## [3.2.1] - 2026-02-21
11
16
 
12
17
  ### Added
package/README.md CHANGED
@@ -3,8 +3,8 @@
3
3
  </p>
4
4
 
5
5
  [![npm version](https://img.shields.io/npm/v/agileflow?color=brightgreen)](https://www.npmjs.com/package/agileflow)
6
- [![Commands](https://img.shields.io/badge/commands-98-blue)](https://docs.agileflow.projectquestorg.com/docs/commands)
7
- [![Agents/Experts](https://img.shields.io/badge/agents%2Fexperts-83-orange)](https://docs.agileflow.projectquestorg.com/docs/agents)
6
+ [![Commands](https://img.shields.io/badge/commands-99-blue)](https://docs.agileflow.projectquestorg.com/docs/commands)
7
+ [![Agents/Experts](https://img.shields.io/badge/agents%2Fexperts-91-orange)](https://docs.agileflow.projectquestorg.com/docs/agents)
8
8
  [![Skills](https://img.shields.io/badge/skills-dynamic-purple)](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) | 98 | Slash commands for agile workflows |
58
- | [Agents/Experts](https://docs.agileflow.projectquestorg.com/docs/agents) | 83 | Specialized agents with self-improving knowledge bases |
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
  ---
@@ -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({ ...options, metadata }),
83
- agentTeamsMode: getAgentTeamsMode({ ...options, metadata }),
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: 'ENABLED (native)',
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agileflow",
3
- "version": "3.2.1",
3
+ "version": "3.3.0",
4
4
  "description": "AI-driven agile development system for Claude Code, Cursor, Windsurf, and more",
5
5
  "keywords": [
6
6
  "agile",
@@ -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);
@@ -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 (with confirmation)
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 30 "\
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';\