agileflow 2.86.0 → 2.87.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
+ ## [2.87.0] - 2026-01-13
11
+
12
+ ### Added
13
+ - Multi-session visibility with cleanup notifications and status line indicators
14
+
10
15
  ## [2.86.0] - 2026-01-13
11
16
 
12
17
  ### Added
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agileflow",
3
- "version": "2.86.0",
3
+ "version": "2.87.0",
4
4
  "description": "AI-driven agile development system for Claude Code, Cursor, Windsurf, and more",
5
5
  "keywords": [
6
6
  "agile",
@@ -510,8 +510,9 @@ fi
510
510
  # ============================================================================
511
511
  # Session Info (Multi-session awareness)
512
512
  # ============================================================================
513
- # Show current session if in a non-main session
513
+ # Show current session info for ALL sessions (main and non-main)
514
514
  SESSION_INFO=""
515
+ OTHER_SESSIONS=""
515
516
  SHOW_SESSION=true # New component - default enabled
516
517
 
517
518
  # Check component setting
@@ -531,17 +532,28 @@ if [ "$SHOW_SESSION" = "true" ]; then
531
532
  {id: .key, nickname: .value.nickname, is_main: .value.is_main}
532
533
  ' "$REGISTRY_FILE" 2>/dev/null)
533
534
 
535
+ # Count total sessions and other active sessions (sessions with lock files)
536
+ TOTAL_SESSIONS=$(jq '.sessions | length' "$REGISTRY_FILE" 2>/dev/null)
537
+
534
538
  if [ -n "$SESSION_DATA" ]; then
535
539
  SESSION_NUM=$(echo "$SESSION_DATA" | jq -r '.id')
536
540
  SESSION_NICK=$(echo "$SESSION_DATA" | jq -r '.nickname // empty')
537
541
  IS_MAIN=$(echo "$SESSION_DATA" | jq -r '.is_main // false')
538
542
 
539
- # Only show for non-main sessions
540
- if [ "$IS_MAIN" != "true" ] && [ -n "$SESSION_NUM" ]; then
543
+ # Only show session info for non-main sessions (main is default, no need to show)
544
+ if [ -n "$SESSION_NUM" ] && [ "$IS_MAIN" != "true" ]; then
541
545
  if [ -n "$SESSION_NICK" ] && [ "$SESSION_NICK" != "null" ]; then
542
- SESSION_INFO="${DIM}[${RESET}${MAGENTA}S${SESSION_NUM}${RESET}${DIM}:${RESET}${SESSION_NICK}${DIM}]${RESET}"
546
+ # With nickname
547
+ SESSION_INFO="${DIM}⎇${RESET} ${MAGENTA}Session ${SESSION_NUM}${RESET}${DIM}:${RESET}${SESSION_NICK}"
543
548
  else
544
- SESSION_INFO="${DIM}[${RESET}${MAGENTA}S${SESSION_NUM}${RESET}${DIM}]${RESET}"
549
+ # Without nickname - show simple
550
+ SESSION_INFO="${DIM}⎇${RESET} ${MAGENTA}Session ${SESSION_NUM}${RESET}"
551
+ fi
552
+
553
+ # Show other sessions count if > 1 (only relevant for non-main)
554
+ if [ -n "$TOTAL_SESSIONS" ] && [ "$TOTAL_SESSIONS" -gt 1 ] 2>/dev/null; then
555
+ OTHER_COUNT=$((TOTAL_SESSIONS - 1))
556
+ OTHER_SESSIONS="${DIM} +${OTHER_COUNT}${RESET}"
545
557
  fi
546
558
  fi
547
559
  fi
@@ -561,10 +573,14 @@ if [ "$SHOW_AGILEFLOW" = "true" ] && [ -n "$AGILEFLOW_DISPLAY" ]; then
561
573
  OUTPUT="${AGILEFLOW_DISPLAY}"
562
574
  fi
563
575
 
564
- # Session info (if in a non-main session)
576
+ # Session info (always show when available, with other sessions count)
565
577
  if [ "$SHOW_SESSION" = "true" ] && [ -n "$SESSION_INFO" ]; then
566
578
  [ -n "$OUTPUT" ] && OUTPUT="${OUTPUT}${SEP}"
567
579
  OUTPUT="${OUTPUT}${SESSION_INFO}"
580
+ # Append other sessions count if there are parallel sessions
581
+ if [ -n "$OTHER_SESSIONS" ]; then
582
+ OUTPUT="${OUTPUT}${OTHER_SESSIONS}"
583
+ fi
568
584
  fi
569
585
 
570
586
  # Model with subtle styling (if enabled and available)
@@ -341,6 +341,7 @@ function checkParallelSessions(rootDir) {
341
341
  otherActive: 0,
342
342
  currentId: null,
343
343
  cleaned: 0,
344
+ cleanedSessions: [], // Detailed info about cleaned sessions
344
345
  // Extended session info for non-main sessions
345
346
  isMain: true,
346
347
  nickname: null,
@@ -374,6 +375,7 @@ function checkParallelSessions(rootDir) {
374
375
  result.currentId = data.id;
375
376
  result.otherActive = data.otherActive || 0;
376
377
  result.cleaned = data.cleaned || 0;
378
+ result.cleanedSessions = data.cleanedSessions || [];
377
379
 
378
380
  if (data.current) {
379
381
  result.isMain = data.current.is_main === true;
@@ -1277,6 +1279,18 @@ async function main() {
1277
1279
  );
1278
1280
  }
1279
1281
 
1282
+ // Show detailed message if sessions were cleaned (VISIBLE - not hidden!)
1283
+ if (parallelSessions.cleaned > 0 && parallelSessions.cleanedSessions) {
1284
+ console.log('');
1285
+ console.log(`${c.amber}📋 Cleaned ${parallelSessions.cleaned} inactive session(s):${c.reset}`);
1286
+ parallelSessions.cleanedSessions.forEach((sess) => {
1287
+ const name = sess.nickname ? `${sess.id} "${sess.nickname}"` : `Session ${sess.id}`;
1288
+ const reason = sess.reason === 'pid_dead' ? 'process ended' : sess.reason;
1289
+ console.log(` ${c.dim}└─ ${name} (${reason}, PID ${sess.pid})${c.reset}`);
1290
+ });
1291
+ console.log(` ${c.slate}Sessions are cleaned when their Claude Code process is no longer running.${c.reset}`);
1292
+ }
1293
+
1280
1294
  // Story claiming: cleanup stale claims and show warnings
1281
1295
  if (storyClaiming) {
1282
1296
  try {
@@ -386,6 +386,67 @@ function generateFullContent() {
386
386
  content += `${C.lavender}${C.bold}${title}${C.reset}\n`;
387
387
  content += `${C.dim}Generated: ${new Date().toISOString()}${C.reset}\n`;
388
388
 
389
+ // 0.5 SESSION CONTEXT BANNER (FIRST - before everything else)
390
+ // This is critical for multi-session awareness - agents need to know which session they're in
391
+ const sessionManagerPath = path.join(__dirname, 'session-manager.js');
392
+ const altSessionManagerPath = '.agileflow/scripts/session-manager.js';
393
+
394
+ if (fs.existsSync(sessionManagerPath) || fs.existsSync(altSessionManagerPath)) {
395
+ const managerPath = fs.existsSync(sessionManagerPath)
396
+ ? sessionManagerPath
397
+ : altSessionManagerPath;
398
+ const sessionStatus = safeExec(`node "${managerPath}" status`);
399
+
400
+ if (sessionStatus) {
401
+ try {
402
+ const statusData = JSON.parse(sessionStatus);
403
+ if (statusData.current) {
404
+ const session = statusData.current;
405
+ const isMain = session.is_main === true;
406
+ const sessionName = session.nickname
407
+ ? `Session ${session.id} "${session.nickname}"`
408
+ : `Session ${session.id}`;
409
+
410
+ content += `\n${C.teal}${C.bold}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${C.reset}\n`;
411
+ content += `${C.teal}${C.bold}📍 SESSION CONTEXT${C.reset}\n`;
412
+ content += `${C.teal}${C.bold}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${C.reset}\n`;
413
+
414
+ if (isMain) {
415
+ content += `${C.mintGreen}${C.bold}${sessionName}${C.reset} ${C.dim}(main project)${C.reset}\n`;
416
+ } else {
417
+ content += `${C.peach}${C.bold}🔀 ${sessionName}${C.reset} ${C.dim}(worktree)${C.reset}\n`;
418
+ content += `Branch: ${C.skyBlue}${session.branch || 'unknown'}${C.reset}\n`;
419
+ content += `${C.dim}Path: ${session.path || process.cwd()}${C.reset}\n`;
420
+ }
421
+
422
+ // Show other active sessions prominently
423
+ if (statusData.otherActive > 0) {
424
+ content += `${C.amber}⚠️ ${statusData.otherActive} other active session(s)${C.reset} - check story claims below\n`;
425
+ }
426
+
427
+ content += `${C.teal}${C.bold}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${C.reset}\n\n`;
428
+ }
429
+ } catch (e) {
430
+ // Silently ignore session parse errors - will still show detailed session context later
431
+ }
432
+ }
433
+ }
434
+
435
+ // 0.7 INTERACTION MODE (AskUserQuestion) - EARLY for visibility
436
+ // This MUST appear before other content to ensure Claude sees it
437
+ const earlyMetadata = safeReadJSON('docs/00-meta/agileflow-metadata.json');
438
+ const askUserQuestionConfig = earlyMetadata?.features?.askUserQuestion;
439
+
440
+ if (askUserQuestionConfig?.enabled) {
441
+ content += `${C.coral}${C.bold}┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓${C.reset}\n`;
442
+ content += `${C.coral}${C.bold}┃ 🔔 MANDATORY: AskUserQuestion After EVERY Response ┃${C.reset}\n`;
443
+ content += `${C.coral}${C.bold}┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛${C.reset}\n`;
444
+ content += `${C.bold}After completing ANY task${C.reset} (implementation, fix, etc.):\n`;
445
+ content += `${C.mintGreen}→ ALWAYS${C.reset} call ${C.skyBlue}AskUserQuestion${C.reset} tool to offer next steps\n`;
446
+ content += `${C.coral}→ NEVER${C.reset} end with text like "Done!" or "What's next?"\n\n`;
447
+ content += `${C.dim}Balance: Use at natural pause points. Don't ask permission for routine work.${C.reset}\n\n`;
448
+ }
449
+
389
450
  // 0. PROGRESSIVE DISCLOSURE (section activation)
390
451
  if (activeSections.length > 0) {
391
452
  content += `\n${C.cyan}${C.bold}═══ 📖 Progressive Disclosure: Active Sections ═══${C.reset}\n`;
@@ -490,58 +551,35 @@ function generateFullContent() {
490
551
  content += `${C.dim}No session-state.json found${C.reset}\n`;
491
552
  }
492
553
 
493
- // 4. SESSION CONTEXT (multi-session awareness)
494
- content += `\n${C.skyBlue}${C.bold}═══ Session Context ═══${C.reset}\n`;
495
- const sessionManagerPath = path.join(__dirname, 'session-manager.js');
496
- const altSessionManagerPath = '.agileflow/scripts/session-manager.js';
554
+ // 4. SESSION CONTEXT (details - banner shown above)
555
+ // Note: Prominent SESSION CONTEXT banner is shown at the top of output
556
+ // This section provides additional details for non-main sessions
557
+ const sessionMgrPath = path.join(__dirname, 'session-manager.js');
558
+ const altSessionMgrPath = '.agileflow/scripts/session-manager.js';
497
559
 
498
- if (fs.existsSync(sessionManagerPath) || fs.existsSync(altSessionManagerPath)) {
499
- const managerPath = fs.existsSync(sessionManagerPath)
500
- ? sessionManagerPath
501
- : altSessionManagerPath;
502
- const sessionStatus = safeExec(`node "${managerPath}" status`);
560
+ if (fs.existsSync(sessionMgrPath) || fs.existsSync(altSessionMgrPath)) {
561
+ const mgrPath = fs.existsSync(sessionMgrPath) ? sessionMgrPath : altSessionMgrPath;
562
+ const sessionStatusStr = safeExec(`node "${mgrPath}" status`);
503
563
 
504
- if (sessionStatus) {
564
+ if (sessionStatusStr) {
505
565
  try {
506
- const statusData = JSON.parse(sessionStatus);
507
- if (statusData.current) {
566
+ const statusData = JSON.parse(sessionStatusStr);
567
+ if (statusData.current && !statusData.current.is_main) {
568
+ // Only show additional details for non-main sessions
569
+ content += `\n${C.skyBlue}${C.bold}═══ Session Details ═══${C.reset}\n`;
508
570
  const session = statusData.current;
509
- const isMain = session.is_main === true;
510
571
 
511
- if (isMain) {
512
- content += `Session: ${C.mintGreen}Main project${C.reset} (Session ${session.id || 1})\n`;
513
- } else {
514
- // NON-MAIN SESSION - Show prominent banner
515
- const sessionName = session.nickname
516
- ? `${session.id} "${session.nickname}"`
517
- : `${session.id}`;
518
- content += `${C.teal}${C.bold}🔀 SESSION ${sessionName} (worktree)${C.reset}\n`;
519
- content += `Branch: ${C.skyBlue}${session.branch || 'unknown'}${C.reset}\n`;
520
- content += `Path: ${C.dim}${session.path || process.cwd()}${C.reset}\n`;
521
-
522
- // Calculate relative path to main
523
- const mainPath = process.cwd().replace(/-[^/]+$/, ''); // Heuristic: strip session suffix
524
- content += `Main project: ${C.dim}${mainPath}${C.reset}\n`;
525
-
526
- // Remind about merge flow
527
- content += `${C.lavender}💡 When done: /agileflow:session:end → merge to main${C.reset}\n`;
528
- }
572
+ // Calculate relative path to main
573
+ const mainPath = process.cwd().replace(/-[^/]+$/, ''); // Heuristic: strip session suffix
574
+ content += `Main project: ${C.dim}${mainPath}${C.reset}\n`;
529
575
 
530
- // Show other active sessions
531
- if (statusData.otherActive > 0) {
532
- content += `${C.peach}⚠️ ${statusData.otherActive} other session(s) active${C.reset}\n`;
533
- }
534
- } else {
535
- content += `${C.dim}No session registered${C.reset}\n`;
576
+ // Remind about merge flow
577
+ content += `${C.lavender}💡 When done: /agileflow:session:end → merge to main${C.reset}\n`;
536
578
  }
537
579
  } catch (e) {
538
- content += `${C.dim}Session manager available but status parse failed${C.reset}\n`;
580
+ // Silently ignore - banner above has basic info
539
581
  }
540
- } else {
541
- content += `${C.dim}Session manager available${C.reset}\n`;
542
582
  }
543
- } else {
544
- content += `${C.dim}Multi-session not configured${C.reset}\n`;
545
583
  }
546
584
 
547
585
  // 5. STORY CLAIMS (inter-session coordination)
@@ -662,35 +700,7 @@ function generateFullContent() {
662
700
  content += `${C.dim} /agileflow:configure → Visual E2E testing${C.reset}\n\n`;
663
701
  }
664
702
 
665
- // 6. INTERACTION MODE (AskUserQuestion guidance)
666
- const askUserQuestionConfig = metadata?.features?.askUserQuestion;
667
-
668
- if (askUserQuestionConfig?.enabled) {
669
- content += `\n${C.brand}${C.bold}═══ ⚡ INTERACTION MODE: AskUserQuestion ENABLED ═══${C.reset}\n`;
670
- content += `${C.dim}${'─'.repeat(60)}${C.reset}\n`;
671
- content += `${C.bold}CRITICAL RULE:${C.reset} End ${C.skyBlue}EVERY${C.reset} response with the AskUserQuestion tool.\n\n`;
672
- content += `${C.mintGreen}✓ CORRECT:${C.reset} Call the actual AskUserQuestion tool\n`;
673
- content += `${C.coral}✗ WRONG:${C.reset} Text like "Want me to continue?" or "What's next?"\n\n`;
674
- content += `${C.lavender}Required format:${C.reset}\n`;
675
- content += `${C.dim}\`\`\`xml
676
- <invoke name="AskUserQuestion">
677
- <parameter name="questions">[{
678
- "question": "What would you like to do next?",
679
- "header": "Next step",
680
- "multiSelect": false,
681
- "options": [
682
- {"label": "Option A (Recommended)", "description": "Why this is best"},
683
- {"label": "Option B", "description": "Alternative approach"},
684
- {"label": "Pause", "description": "Stop here for now"}
685
- ]
686
- }]</parameter>
687
- </invoke>
688
- \`\`\`${C.reset}\n`;
689
- content += `${C.dim}${'─'.repeat(60)}${C.reset}\n`;
690
- content += `${C.dim}Mode: ${askUserQuestionConfig.mode || 'all'} | Configure: /agileflow:configure${C.reset}\n\n`;
691
- }
692
-
693
- // 5. DOCS STRUCTURE (using vibrant 256-color palette)
703
+ // DOCS STRUCTURE (using vibrant 256-color palette)
694
704
  content += `\n${C.skyBlue}${C.bold}═══ Documentation ═══${C.reset}\n`;
695
705
  const docsDir = 'docs';
696
706
  const docFolders = safeLs(docsDir).filter(f => {
@@ -117,19 +117,39 @@ function isSessionActive(sessionId) {
117
117
  return isPidAlive(parseInt(lock.pid, 10));
118
118
  }
119
119
 
120
- // Clean up stale locks
121
- function cleanupStaleLocks(registry) {
120
+ // Clean up stale locks (with detailed tracking)
121
+ function cleanupStaleLocks(registry, options = {}) {
122
+ const { verbose = false, dryRun = false } = options;
122
123
  let cleaned = 0;
124
+ const cleanedSessions = [];
123
125
 
124
126
  for (const [id, session] of Object.entries(registry.sessions)) {
125
127
  const lock = readLock(id);
126
- if (lock && !isPidAlive(parseInt(lock.pid, 10))) {
127
- removeLock(id);
128
- cleaned++;
128
+ if (lock) {
129
+ const pid = parseInt(lock.pid, 10);
130
+ const isAlive = isPidAlive(pid);
131
+
132
+ if (!isAlive) {
133
+ // Track what we're cleaning and why
134
+ cleanedSessions.push({
135
+ id,
136
+ nickname: session.nickname,
137
+ branch: session.branch,
138
+ pid,
139
+ reason: 'pid_dead',
140
+ path: session.path,
141
+ });
142
+
143
+ if (!dryRun) {
144
+ removeLock(id);
145
+ }
146
+ cleaned++;
147
+ }
129
148
  }
130
149
  }
131
150
 
132
- return cleaned;
151
+ // Return detailed info for display
152
+ return { count: cleaned, sessions: cleanedSessions };
133
153
  }
134
154
 
135
155
  // Get current git branch
@@ -342,7 +362,7 @@ function createSession(options = {}) {
342
362
  // Get all sessions with status
343
363
  function getSessions() {
344
364
  const registry = loadRegistry();
345
- const cleaned = cleanupStaleLocks(registry);
365
+ const cleanupResult = cleanupStaleLocks(registry);
346
366
 
347
367
  const sessions = [];
348
368
  for (const [id, session] of Object.entries(registry.sessions)) {
@@ -357,7 +377,12 @@ function getSessions() {
357
377
  // Sort by ID (numeric)
358
378
  sessions.sort((a, b) => parseInt(a.id) - parseInt(b.id));
359
379
 
360
- return { sessions, cleaned };
380
+ // Return count for backward compat, plus detailed info
381
+ return {
382
+ sessions,
383
+ cleaned: cleanupResult.count,
384
+ cleanedSessions: cleanupResult.sessions,
385
+ };
361
386
  }
362
387
 
363
388
  // Get count of active sessions (excluding current)
@@ -989,7 +1014,7 @@ function main() {
989
1014
 
990
1015
  // Register in single pass (combines register + count + status)
991
1016
  const registry = loadRegistry();
992
- const cleaned = cleanupStaleLocks(registry);
1017
+ const cleanupResult = cleanupStaleLocks(registry);
993
1018
  const branch = getCurrentBranch();
994
1019
  const story = getCurrentStory();
995
1020
  const pid = process.ppid || process.pid;
@@ -1055,7 +1080,8 @@ function main() {
1055
1080
  current,
1056
1081
  otherActive,
1057
1082
  total: sessions.length,
1058
- cleaned,
1083
+ cleaned: cleanupResult.count,
1084
+ cleanedSessions: cleanupResult.sessions,
1059
1085
  })
1060
1086
  );
1061
1087
  break;
@@ -5,16 +5,21 @@ compact_context:
5
5
  priority: critical
6
6
  preserve_rules:
7
7
  - "ACTIVE COMMAND: /agileflow-babysit - Mentor mode with expert delegation"
8
+ - "🔔 MANDATORY: Call AskUserQuestion tool at END of EVERY response - especially after completing tasks"
9
+ - "NEVER end with text like 'Done!' or 'What's next?' - ALWAYS use AskUserQuestion tool instead"
8
10
  - "MUST use EnterPlanMode FIRST for ANY non-trivial task (explore codebase, design approach, get approval)"
9
11
  - "MUST delegate complex work to domain experts (don't do everything yourself)"
10
- - "MUST use AskUserQuestion for decisions, TodoWrite for tracking"
11
12
  - "Simple task → do yourself | Complex single-domain → spawn expert | Multi-domain → spawn orchestrator"
12
13
  - "STUCK DETECTION: If same error 2+ times, suggest /agileflow:research:ask with 200+ line detailed prompt"
13
14
  - "Research prompts MUST include: 50+ lines actual code, exact error, what was tried, 3+ specific questions"
15
+ - "STORY CLAIMING: Run 'node .agileflow/scripts/lib/story-claiming.js claim <id>' IMMEDIATELY after user selects story"
16
+ - "STORY CLAIMING: Run 'node .agileflow/scripts/lib/story-claiming.js others' BEFORE suggesting stories, exclude 🔒 claimed"
17
+ - "STORY CLAIMING: Run 'node .agileflow/scripts/lib/story-claiming.js release <id>' when story marked done"
14
18
  state_fields:
15
19
  - current_story
16
20
  - current_epic
17
21
  - delegation_mode
22
+ - claimed_story_id
18
23
  ---
19
24
 
20
25
  # /agileflow-babysit
@@ -224,6 +229,17 @@ node scripts/ralph-loop.js --reset # Reset loop state
224
229
 
225
230
  **EVERY response MUST end with the AskUserQuestion tool.** Not text like "Want me to...?" - the ACTUAL TOOL CALL.
226
231
 
232
+ **This applies (natural pause points):**
233
+ - ✅ After completing a task (ESPECIALLY important - don't leave user hanging)
234
+ - ✅ After spawning an agent and receiving results
235
+ - ✅ When presenting options or decisions
236
+ - ✅ Even when you think you're "done" - ask what's next
237
+
238
+ **Don't be annoying - DON'T ask for:**
239
+ - ❌ Permission to read files, spawn experts, or do routine work
240
+ - ❌ Confirmation of obvious next steps you should just do
241
+ - ❌ Every micro-step in a workflow
242
+
227
243
  **Required format:**
228
244
  ```xml
229
245
  <function_calls>
@@ -242,8 +258,8 @@ node scripts/ralph-loop.js --reset # Reset loop state
242
258
  </function_calls>
243
259
  ```
244
260
 
245
- **❌ WRONG:** "Want me to continue?" / "Should I proceed?" / "Let me know what you think"
246
- **✅ RIGHT:** Call the AskUserQuestion tool with actual options
261
+ **❌ WRONG:** "Want me to continue?" / "Should I proceed?" / "Done! Let me know what's next"
262
+ **✅ RIGHT:** Call the AskUserQuestion tool with actual options - NEVER end without it
247
263
 
248
264
  ---
249
265
 
@@ -320,23 +336,32 @@ Use TodoWrite for any task with 3+ steps. Update status as you complete each ste
320
336
 
321
337
  **Phase 1: Context & Task Selection**
322
338
  1. Run context script (obtain-context.js babysit)
323
- 2. Present task options using AskUserQuestion
324
- 3. User selects task
339
+ 2. Check for stories claimed by OTHER sessions (filter from suggestions)
340
+ 3. Present task options using AskUserQuestion (with 🔒 badges for claimed)
341
+ 4. User selects task
342
+ 5. **CLAIM THE STORY immediately after selection:**
343
+ ```bash
344
+ node .agileflow/scripts/lib/story-claiming.js claim <story-id>
345
+ ```
325
346
 
326
347
  **Phase 2: Plan Mode (for non-trivial tasks)**
327
- 4. Call `EnterPlanMode` tool
328
- 5. Explore codebase with Glob, Grep, Read
329
- 6. Design approach, write to plan file
330
- 7. Call `ExitPlanMode` for user approval
348
+ 6. Call `EnterPlanMode` tool
349
+ 7. Explore codebase with Glob, Grep, Read
350
+ 8. Design approach, write to plan file
351
+ 9. Call `ExitPlanMode` for user approval
331
352
 
332
353
  **Phase 3: Execution**
333
- 8. Delegate to experts based on scope
334
- 9. Collect results if async (TaskOutput)
335
- 10. Verify tests pass
354
+ 10. Delegate to experts based on scope
355
+ 11. Collect results if async (TaskOutput)
356
+ 12. Verify tests pass
336
357
 
337
358
  **Phase 4: Completion**
338
- 11. Update status.json
339
- 12. Present next steps via AskUserQuestion
359
+ 13. Update status.json (mark story done)
360
+ 14. **RELEASE THE STORY claim:**
361
+ ```bash
362
+ node .agileflow/scripts/lib/story-claiming.js release <story-id>
363
+ ```
364
+ 15. Present next steps via AskUserQuestion
340
365
 
341
366
  ---
342
367
 
@@ -352,12 +377,35 @@ Use TodoWrite for any task with 3+ steps. Update status as you complete each ste
352
377
 
353
378
  ### SUGGESTIONS PRIORITY (for task selection)
354
379
 
380
+ **BEFORE suggesting stories, check for claims:**
381
+ ```bash
382
+ node .agileflow/scripts/lib/story-claiming.js others
383
+ ```
384
+
385
+ **Story badges in suggestions:**
386
+ | Badge | Meaning | Include in suggestions? |
387
+ |-------|---------|------------------------|
388
+ | ⭐ | Ready, available | YES - prioritize these |
389
+ | 🔒 | Claimed by other session | NO - exclude or show disabled |
390
+ | ✓ | Claimed by this session | YES - show as "continue" |
391
+
392
+ **Priority order (for unclaimed stories):**
355
393
  1. ⭐ READY stories (all AC complete, no blockers)
356
394
  2. Blocked with simple unblock
357
395
  3. Near-complete epics (80%+ done)
358
396
  4. README TODOs
359
397
  5. New features
360
398
 
399
+ **Example with claim filtering:**
400
+ ```json
401
+ [
402
+ {"label": "US-0042: Auth API ⭐ (Recommended)", "description": "Ready to implement"},
403
+ {"label": "US-0038: User Profile ✓", "description": "Continue your work"},
404
+ {"label": "US-0041: Settings 🔒", "description": "Claimed by Session 2 - skip"},
405
+ {"label": "Other", "description": "Tell me what you want"}
406
+ ]
407
+ ```
408
+
361
409
  Present top 3-5 via AskUserQuestion, always include "Other" option.
362
410
 
363
411
  ---
@@ -377,12 +425,17 @@ Present top 3-5 via AskUserQuestion, always include "Other" option.
377
425
  ### REMEMBER AFTER COMPACTION
378
426
 
379
427
  - `/agileflow:babysit` IS ACTIVE - follow these rules
380
- - ALWAYS end with AskUserQuestion tool (not text questions)
428
+ - **🔔 AskUserQuestion AFTER EVERY RESPONSE** - especially after task completion!
429
+ - Don't say "Done!" and stop - call AskUserQuestion with next step options
430
+ - Don't leave user waiting - proactively suggest what to do next
381
431
  - Plan mode FIRST for non-trivial tasks
382
432
  - Delegate complex work to experts
383
433
  - If stuck 2+ times → research prompt
384
434
  - Use state narration markers (📍🔀🔄⚠️✅) for visibility
385
- - **STORY CLAIMING**: Claim stories before working, skip 🔒 claimed stories in suggestions
435
+ - **STORY CLAIMING - CRITICAL:**
436
+ 1. BEFORE suggesting: `node .agileflow/scripts/lib/story-claiming.js others` → exclude 🔒
437
+ 2. AFTER user selects: `node .agileflow/scripts/lib/story-claiming.js claim <id>`
438
+ 3. WHEN done: `node .agileflow/scripts/lib/story-claiming.js release <id>`
386
439
 
387
440
  <!-- COMPACT_SUMMARY_END -->
388
441
 
@@ -795,12 +848,19 @@ User: "Fix the typo in README"
795
848
  - Initial task selection
796
849
  - Choosing between approaches
797
850
  - Architectural decisions
798
- - End of every response
799
-
800
- **DON'T use for:**
801
- - Routine operations (just do them)
802
- - Spawning experts (just spawn)
803
- - Obvious next steps
851
+ - End of every response (to keep user engaged)
852
+ - After completing a task (offer next steps)
853
+
854
+ **DON'T use for (avoid being annoying):**
855
+ - Routine operations ("Can I read this file?" → just read it)
856
+ - Spawning experts ("Should I spawn the API expert?" → just spawn it)
857
+ - Obvious next steps that don't need confirmation
858
+ - Asking the same question repeatedly
859
+ - Interrupting workflow when you already know what to do
860
+ - Asking permission for every small action
861
+
862
+ **Balance:**
863
+ Use AskUserQuestion at natural pause points (task completion, decision needed) but NOT for every micro-step. If you know the next action, do it. Ask only when user input genuinely helps.
804
864
 
805
865
  **Format:**
806
866
  ```xml