agileflow 3.2.1 → 3.4.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.
Files changed (134) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/README.md +6 -6
  3. package/lib/feature-flags.js +32 -4
  4. package/lib/skill-loader.js +0 -1
  5. package/package.json +1 -1
  6. package/scripts/agileflow-statusline.sh +81 -0
  7. package/scripts/babysit-clear-restore.js +154 -0
  8. package/scripts/claude-tmux.sh +120 -24
  9. package/scripts/claude-watchdog.sh +225 -0
  10. package/scripts/generators/agent-registry.js +14 -1
  11. package/scripts/generators/inject-babysit.js +22 -9
  12. package/scripts/generators/inject-help.js +19 -9
  13. package/scripts/lib/README-portable-tasks.md +424 -0
  14. package/scripts/lib/audit-cleanup.js +250 -0
  15. package/scripts/lib/audit-registry.js +248 -0
  16. package/scripts/lib/configure-detect.js +20 -0
  17. package/scripts/lib/feature-catalog.js +13 -2
  18. package/scripts/lib/gate-enforcer.js +295 -0
  19. package/scripts/lib/model-profiles.js +98 -0
  20. package/scripts/lib/signal-detectors.js +1 -1
  21. package/scripts/lib/skill-catalog.js +557 -0
  22. package/scripts/lib/skill-recommender.js +311 -0
  23. package/scripts/lib/tdd-phase-manager.js +455 -0
  24. package/scripts/lib/team-events.js +76 -8
  25. package/scripts/lib/tmux-group-colors.js +113 -0
  26. package/scripts/messaging-bridge.js +209 -1
  27. package/scripts/spawn-audit-sessions.js +549 -0
  28. package/scripts/team-manager.js +37 -16
  29. package/scripts/tmux-close-windows.sh +180 -0
  30. package/scripts/tmux-restore-window.sh +67 -0
  31. package/scripts/tmux-save-closed-window.sh +35 -0
  32. package/src/core/agents/ads-audit-budget.md +181 -0
  33. package/src/core/agents/ads-audit-compliance.md +169 -0
  34. package/src/core/agents/ads-audit-creative.md +164 -0
  35. package/src/core/agents/ads-audit-google.md +226 -0
  36. package/src/core/agents/ads-audit-meta.md +183 -0
  37. package/src/core/agents/ads-audit-tracking.md +197 -0
  38. package/src/core/agents/ads-consensus.md +322 -0
  39. package/src/core/agents/brainstorm-analyzer-features.md +169 -0
  40. package/src/core/agents/brainstorm-analyzer-growth.md +161 -0
  41. package/src/core/agents/brainstorm-analyzer-integration.md +172 -0
  42. package/src/core/agents/brainstorm-analyzer-market.md +147 -0
  43. package/src/core/agents/brainstorm-analyzer-ux.md +167 -0
  44. package/src/core/agents/brainstorm-consensus.md +237 -0
  45. package/src/core/agents/completeness-analyzer-api.md +190 -0
  46. package/src/core/agents/completeness-analyzer-conditional.md +201 -0
  47. package/src/core/agents/completeness-analyzer-handlers.md +159 -0
  48. package/src/core/agents/completeness-analyzer-imports.md +159 -0
  49. package/src/core/agents/completeness-analyzer-routes.md +182 -0
  50. package/src/core/agents/completeness-analyzer-state.md +188 -0
  51. package/src/core/agents/completeness-analyzer-stubs.md +198 -0
  52. package/src/core/agents/completeness-consensus.md +286 -0
  53. package/src/core/agents/perf-consensus.md +2 -2
  54. package/src/core/agents/security-consensus.md +2 -2
  55. package/src/core/agents/seo-analyzer-content.md +167 -0
  56. package/src/core/agents/seo-analyzer-images.md +187 -0
  57. package/src/core/agents/seo-analyzer-performance.md +206 -0
  58. package/src/core/agents/seo-analyzer-schema.md +176 -0
  59. package/src/core/agents/seo-analyzer-sitemap.md +172 -0
  60. package/src/core/agents/seo-analyzer-technical.md +144 -0
  61. package/src/core/agents/seo-consensus.md +289 -0
  62. package/src/core/agents/test-consensus.md +2 -2
  63. package/src/core/commands/ads/audit.md +375 -0
  64. package/src/core/commands/ads/budget.md +97 -0
  65. package/src/core/commands/ads/competitor.md +112 -0
  66. package/src/core/commands/ads/creative.md +85 -0
  67. package/src/core/commands/ads/google.md +112 -0
  68. package/src/core/commands/ads/landing.md +119 -0
  69. package/src/core/commands/ads/linkedin.md +112 -0
  70. package/src/core/commands/ads/meta.md +91 -0
  71. package/src/core/commands/ads/microsoft.md +115 -0
  72. package/src/core/commands/ads/plan.md +321 -0
  73. package/src/core/commands/ads/tiktok.md +129 -0
  74. package/src/core/commands/ads/youtube.md +124 -0
  75. package/src/core/commands/ads.md +128 -0
  76. package/src/core/commands/babysit.md +250 -1344
  77. package/src/core/commands/code/completeness.md +466 -0
  78. package/src/core/commands/{audit → code}/legal.md +26 -16
  79. package/src/core/commands/{audit → code}/logic.md +27 -16
  80. package/src/core/commands/{audit → code}/performance.md +30 -20
  81. package/src/core/commands/{audit → code}/security.md +32 -19
  82. package/src/core/commands/{audit → code}/test.md +30 -20
  83. package/src/core/commands/{discovery → ideate}/brief.md +12 -12
  84. package/src/core/commands/{discovery/new.md → ideate/discover.md} +13 -13
  85. package/src/core/commands/ideate/features.md +435 -0
  86. package/src/core/commands/seo/audit.md +373 -0
  87. package/src/core/commands/seo/competitor.md +174 -0
  88. package/src/core/commands/seo/content.md +107 -0
  89. package/src/core/commands/seo/geo.md +229 -0
  90. package/src/core/commands/seo/hreflang.md +140 -0
  91. package/src/core/commands/seo/images.md +96 -0
  92. package/src/core/commands/seo/page.md +198 -0
  93. package/src/core/commands/seo/plan.md +163 -0
  94. package/src/core/commands/seo/programmatic.md +131 -0
  95. package/src/core/commands/seo/references/cwv-thresholds.md +64 -0
  96. package/src/core/commands/seo/references/eeat-framework.md +110 -0
  97. package/src/core/commands/seo/references/quality-gates.md +91 -0
  98. package/src/core/commands/seo/references/schema-types.md +102 -0
  99. package/src/core/commands/seo/schema.md +183 -0
  100. package/src/core/commands/seo/sitemap.md +97 -0
  101. package/src/core/commands/seo/technical.md +100 -0
  102. package/src/core/commands/seo.md +107 -0
  103. package/src/core/commands/skill/list.md +68 -212
  104. package/src/core/commands/skill/recommend.md +216 -0
  105. package/src/core/commands/tdd-next.md +238 -0
  106. package/src/core/commands/tdd.md +210 -0
  107. package/src/core/experts/_core-expertise.yaml +105 -0
  108. package/src/core/experts/analytics/expertise.yaml +5 -99
  109. package/src/core/experts/codebase-query/expertise.yaml +3 -72
  110. package/src/core/experts/compliance/expertise.yaml +6 -72
  111. package/src/core/experts/database/expertise.yaml +9 -52
  112. package/src/core/experts/documentation/expertise.yaml +7 -140
  113. package/src/core/experts/integrations/expertise.yaml +7 -127
  114. package/src/core/experts/mentor/expertise.yaml +8 -35
  115. package/src/core/experts/monitoring/expertise.yaml +7 -49
  116. package/src/core/experts/performance/expertise.yaml +1 -26
  117. package/src/core/experts/security/expertise.yaml +9 -34
  118. package/src/core/experts/ui/expertise.yaml +6 -36
  119. package/src/core/knowledge/ads/ad-audit-checklist-scoring.md +424 -0
  120. package/src/core/knowledge/ads/ad-optimization-logic.md +590 -0
  121. package/src/core/knowledge/ads/ad-technical-specifications.md +385 -0
  122. package/src/core/knowledge/ads/definitive-advertising-reference-2026.md +506 -0
  123. package/src/core/knowledge/ads/paid-advertising-research-2026.md +445 -0
  124. package/src/core/templates/agileflow-metadata.json +15 -1
  125. package/tools/cli/installers/ide/_base-ide.js +42 -5
  126. package/tools/cli/installers/ide/claude-code.js +13 -4
  127. package/tools/cli/lib/content-injector.js +160 -12
  128. package/tools/cli/lib/docs-setup.js +1 -1
  129. package/src/core/commands/skill/create.md +0 -698
  130. package/src/core/commands/skill/delete.md +0 -316
  131. package/src/core/commands/skill/edit.md +0 -359
  132. package/src/core/commands/skill/test.md +0 -394
  133. package/src/core/commands/skill/upgrade.md +0 -552
  134. package/src/core/templates/skill-template.md +0 -117
@@ -0,0 +1,113 @@
1
+ /**
2
+ * tmux-group-colors.js - Color palette for tmux tab groups
3
+ *
4
+ * Provides a curated palette of 8 colors optimized for dark terminal
5
+ * backgrounds (Tokyo Night compatible). Supports color assignment by
6
+ * audit type and random selection with avoidance of in-use colors.
7
+ *
8
+ * Usage:
9
+ * const { getColorForAudit, pickGroupColor } = require('./tmux-group-colors');
10
+ * const color = getColorForAudit('security'); // '#f7768e'
11
+ * const random = pickGroupColor(['#f7768e']); // random excluding coral
12
+ */
13
+
14
+ /**
15
+ * Curated palette for dark backgrounds.
16
+ * Each color has sufficient contrast against #1a1b26 (Tokyo Night bg)
17
+ * and #2d2f3a (tab bg).
18
+ */
19
+ const GROUP_PALETTE = [
20
+ { name: 'coral', hex: '#f7768e', audit: 'security' },
21
+ { name: 'sky', hex: '#7aa2f7', audit: 'logic' },
22
+ { name: 'mint', hex: '#73daca', audit: 'performance' },
23
+ { name: 'amber', hex: '#e0af68', audit: 'test' },
24
+ { name: 'violet', hex: '#bb9af7', audit: 'completeness' },
25
+ { name: 'lime', hex: '#9ece6a', audit: 'legal' },
26
+ { name: 'rose', hex: '#ff9e64', audit: null },
27
+ { name: 'ice', hex: '#89ddff', audit: null },
28
+ ];
29
+
30
+ /**
31
+ * Map audit type to its assigned color.
32
+ */
33
+ const AUDIT_COLOR_MAP = {};
34
+ for (const entry of GROUP_PALETTE) {
35
+ if (entry.audit) {
36
+ AUDIT_COLOR_MAP[entry.audit] = entry.hex;
37
+ }
38
+ }
39
+
40
+ /**
41
+ * Get the assigned color for an audit type.
42
+ *
43
+ * @param {string} auditType - Audit type key (security, logic, etc.)
44
+ * @returns {string} Hex color string
45
+ */
46
+ function getColorForAudit(auditType) {
47
+ return AUDIT_COLOR_MAP[auditType] || pickGroupColor([]);
48
+ }
49
+
50
+ /**
51
+ * Pick a group color, avoiding colors currently in use.
52
+ *
53
+ * @param {string[]} [inUseColors] - Array of hex colors currently in use
54
+ * @returns {string} Hex color string not in the in-use list
55
+ */
56
+ function pickGroupColor(inUseColors) {
57
+ const avoid = new Set((inUseColors || []).map(c => c.toLowerCase()));
58
+ const available = GROUP_PALETTE.filter(entry => !avoid.has(entry.hex.toLowerCase()));
59
+
60
+ if (available.length === 0) {
61
+ // All colors in use, pick first from full palette
62
+ return GROUP_PALETTE[0].hex;
63
+ }
64
+
65
+ // Deterministic pick: first available for consistency
66
+ return available[0].hex;
67
+ }
68
+
69
+ /**
70
+ * Get a palette entry by name.
71
+ *
72
+ * @param {string} name - Color name (e.g. 'coral', 'sky')
73
+ * @returns {object|null} Palette entry or null
74
+ */
75
+ function getColorByName(name) {
76
+ return GROUP_PALETTE.find(entry => entry.name === name) || null;
77
+ }
78
+
79
+ /**
80
+ * Build tmux window format string with group color.
81
+ *
82
+ * @param {string} groupColor - Hex color for the group
83
+ * @param {string} prefix - Short prefix (e.g. 'Sec', 'Logic')
84
+ * @param {boolean} [isActive=false] - Whether this is the active window
85
+ * @returns {string} tmux format string
86
+ */
87
+ function buildGroupWindowFormat(groupColor, prefix, isActive) {
88
+ if (isActive) {
89
+ // Active: colored bg for index, dark bg for name
90
+ return `#[fg=#1a1b26 bg=${groupColor} bold] #I #[fg=${groupColor} bg=#2d2f3a]#[fg=#e0e0e0] ${prefix}:#{window_name} #[bg=#1a1b26 fg=#2d2f3a]`;
91
+ }
92
+ // Inactive: colored dot prefix + gray text
93
+ return `#[fg=${groupColor}]#[fg=#8a8a8a] #I:${prefix}:#{window_name} `;
94
+ }
95
+
96
+ /**
97
+ * Get all palette colors.
98
+ *
99
+ * @returns {Array<{ name: string, hex: string, audit: string|null }>}
100
+ */
101
+ function getAllColors() {
102
+ return [...GROUP_PALETTE];
103
+ }
104
+
105
+ module.exports = {
106
+ GROUP_PALETTE,
107
+ AUDIT_COLOR_MAP,
108
+ getColorForAudit,
109
+ pickGroupColor,
110
+ getColorByName,
111
+ buildGroupWindowFormat,
112
+ getAllColors,
113
+ };
@@ -49,6 +49,18 @@ function getFeatureFlags() {
49
49
  return _featureFlags;
50
50
  }
51
51
 
52
+ let _teamEvents;
53
+ function getTeamEvents() {
54
+ if (!_teamEvents) {
55
+ try {
56
+ _teamEvents = require('./lib/team-events');
57
+ } catch (e) {
58
+ return null;
59
+ }
60
+ }
61
+ return _teamEvents;
62
+ }
63
+
52
64
  let _busUtils;
53
65
  function getBusUtils() {
54
66
  if (!_busUtils) {
@@ -277,6 +289,168 @@ function sendPlanDecision(rootDir, from, to, taskId, approved, reason, traceId)
277
289
  return sendMessage(rootDir, msg);
278
290
  }
279
291
 
292
+ /**
293
+ * Send an inter-agent team message to the JSONL bus.
294
+ * Logs communication between teammates with optional trace_id for correlation.
295
+ *
296
+ * @param {string} rootDir - Project root
297
+ * @param {string} from - Sending agent name
298
+ * @param {string} to - Receiving agent name
299
+ * @param {string} content - Message content
300
+ * @param {string} [traceId] - Trace ID for team lifecycle correlation
301
+ * @returns {{ ok: boolean, native?: boolean }}
302
+ */
303
+ function sendTeamMessage(rootDir, from, to, content, traceId) {
304
+ const msg = { from, to, type: 'team_message', content };
305
+ if (traceId) msg.trace_id = traceId;
306
+ const result = sendMessage(rootDir, msg);
307
+
308
+ // Always track in session-state for observability parity (both native and subagent modes)
309
+ try {
310
+ const teamEvents = getTeamEvents();
311
+ if (teamEvents) {
312
+ teamEvents.trackEvent(rootDir, 'team_message', {
313
+ from,
314
+ to,
315
+ trace_id: traceId,
316
+ });
317
+ }
318
+ } catch (e) {
319
+ // Non-critical
320
+ }
321
+
322
+ return result;
323
+ }
324
+
325
+ /**
326
+ * Send a team_completed event to the JSONL bus.
327
+ * Signals that a team run has finished all work.
328
+ *
329
+ * @param {string} rootDir - Project root
330
+ * @param {string} templateName - Team template name
331
+ * @param {string} [traceId] - Trace ID for team lifecycle correlation
332
+ * @param {object} [summary] - Optional summary data (duration_ms, tasks_completed, etc.)
333
+ * @returns {{ ok: boolean, native?: boolean }}
334
+ */
335
+ function sendTeamCompleted(rootDir, templateName, traceId, summary) {
336
+ const msg = {
337
+ from: 'team-manager',
338
+ to: 'system',
339
+ type: 'team_completed',
340
+ template: templateName,
341
+ ...summary,
342
+ };
343
+ if (traceId) msg.trace_id = traceId;
344
+ return sendMessage(rootDir, msg);
345
+ }
346
+
347
+ /**
348
+ * Log a native SendMessage tool call to the JSONL bus.
349
+ * Used by agents to record native API calls for observability parity.
350
+ *
351
+ * @param {string} rootDir - Project root
352
+ * @param {string} from - Sending agent name
353
+ * @param {string} to - Receiving agent name
354
+ * @param {string} content - Message content
355
+ * @param {string} [traceId] - Trace ID for correlation
356
+ * @returns {{ ok: boolean }}
357
+ */
358
+ function logNativeSend(rootDir, from, to, content, traceId) {
359
+ const msg = { from, to, type: 'native_send', content };
360
+ if (traceId) msg.trace_id = traceId;
361
+ const result = sendMessage(rootDir, msg);
362
+
363
+ try {
364
+ const teamEvents = getTeamEvents();
365
+ if (teamEvents) {
366
+ teamEvents.trackEvent(rootDir, 'team_message', {
367
+ from,
368
+ to,
369
+ trace_id: traceId,
370
+ native: true,
371
+ });
372
+ }
373
+ } catch (e) {
374
+ // Non-critical
375
+ }
376
+
377
+ return { ok: result.ok };
378
+ }
379
+
380
+ /**
381
+ * Log a native TeamCreate tool call to the JSONL bus.
382
+ *
383
+ * @param {string} rootDir - Project root
384
+ * @param {string} templateName - Team template name
385
+ * @param {string} [traceId] - Trace ID for correlation
386
+ * @param {number} [teammateCount] - Number of teammates created
387
+ * @returns {{ ok: boolean }}
388
+ */
389
+ function logNativeTeamCreate(rootDir, templateName, traceId, teammateCount) {
390
+ const msg = {
391
+ from: 'team-manager',
392
+ to: 'system',
393
+ type: 'native_team_create',
394
+ template: templateName,
395
+ };
396
+ if (traceId) msg.trace_id = traceId;
397
+ if (typeof teammateCount === 'number') msg.teammate_count = teammateCount;
398
+ const result = sendMessage(rootDir, msg);
399
+
400
+ try {
401
+ const teamEvents = getTeamEvents();
402
+ if (teamEvents) {
403
+ teamEvents.trackEvent(rootDir, 'team_created', {
404
+ template: templateName,
405
+ trace_id: traceId,
406
+ teammate_count: teammateCount,
407
+ native: true,
408
+ });
409
+ }
410
+ } catch (e) {
411
+ // Non-critical
412
+ }
413
+
414
+ return { ok: result.ok };
415
+ }
416
+
417
+ /**
418
+ * Log a native team completion to the JSONL bus.
419
+ *
420
+ * @param {string} rootDir - Project root
421
+ * @param {string} templateName - Team template name
422
+ * @param {string} [traceId] - Trace ID for correlation
423
+ * @param {string} [summary] - Summary of completed work
424
+ * @returns {{ ok: boolean }}
425
+ */
426
+ function logNativeTeamCompleted(rootDir, templateName, traceId, summary) {
427
+ const msg = {
428
+ from: 'team-manager',
429
+ to: 'system',
430
+ type: 'native_team_completed',
431
+ template: templateName,
432
+ };
433
+ if (traceId) msg.trace_id = traceId;
434
+ if (summary) msg.summary = summary;
435
+ const result = sendMessage(rootDir, msg);
436
+
437
+ try {
438
+ const teamEvents = getTeamEvents();
439
+ if (teamEvents) {
440
+ teamEvents.trackEvent(rootDir, 'team_completed', {
441
+ template: templateName,
442
+ trace_id: traceId,
443
+ summary,
444
+ native: true,
445
+ });
446
+ }
447
+ } catch (e) {
448
+ // Non-critical
449
+ }
450
+
451
+ return { ok: result.ok };
452
+ }
453
+
280
454
  /**
281
455
  * Send a validation result message.
282
456
  */
@@ -324,10 +498,39 @@ function main() {
324
498
  break;
325
499
  }
326
500
 
501
+ case 'log-native-send': {
502
+ const [, from, to, ...contentParts] = args;
503
+ const content = contentParts.filter(p => !p.startsWith('--')).join(' ');
504
+ const traceArg = args.find(a => a.startsWith('--trace-id='));
505
+ const traceId = traceArg ? traceArg.slice(11) : undefined;
506
+ result = logNativeSend(rootDir, from, to, content, traceId);
507
+ break;
508
+ }
509
+
510
+ case 'log-native-create': {
511
+ const [, templateName] = args;
512
+ const traceArg = args.find(a => a.startsWith('--trace-id='));
513
+ const traceId = traceArg ? traceArg.slice(11) : undefined;
514
+ const countArg = args.find(a => a.startsWith('--count='));
515
+ const teammateCount = countArg ? parseInt(countArg.slice(8), 10) : undefined;
516
+ result = logNativeTeamCreate(rootDir, templateName, traceId, teammateCount);
517
+ break;
518
+ }
519
+
520
+ case 'log-native-completed': {
521
+ const [, templateName] = args;
522
+ const traceArg = args.find(a => a.startsWith('--trace-id='));
523
+ const traceId = traceArg ? traceArg.slice(11) : undefined;
524
+ const summaryArg = args.find(a => a.startsWith('--summary='));
525
+ const summary = summaryArg ? summaryArg.slice(10) : undefined;
526
+ result = logNativeTeamCompleted(rootDir, templateName, traceId, summary);
527
+ break;
528
+ }
529
+
327
530
  default:
328
531
  result = {
329
532
  ok: false,
330
- error: `Unknown command: ${command}\nUsage: messaging-bridge.js <send|read|context>`,
533
+ error: `Unknown command: ${command}\nUsage: messaging-bridge.js <send|read|context|log-native-send|log-native-create|log-native-completed>`,
331
534
  };
332
535
  }
333
536
 
@@ -343,7 +546,12 @@ module.exports = {
343
546
  sendTaskAssignment,
344
547
  sendPlanProposal,
345
548
  sendPlanDecision,
549
+ sendTeamMessage,
550
+ sendTeamCompleted,
346
551
  sendValidationResult,
552
+ logNativeSend,
553
+ logNativeTeamCreate,
554
+ logNativeTeamCompleted,
347
555
  getBusLogPath,
348
556
  formatForNative,
349
557
  };