agileflow 3.1.0 → 3.2.1

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 (106) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/README.md +57 -85
  3. package/lib/dashboard-automations.js +130 -0
  4. package/lib/dashboard-git.js +254 -0
  5. package/lib/dashboard-inbox.js +64 -0
  6. package/lib/dashboard-protocol.js +1 -0
  7. package/lib/dashboard-server.js +114 -924
  8. package/lib/dashboard-session.js +136 -0
  9. package/lib/dashboard-status.js +72 -0
  10. package/lib/dashboard-terminal.js +354 -0
  11. package/lib/dashboard-websocket.js +88 -0
  12. package/lib/drivers/codex-driver.ts +4 -4
  13. package/lib/logger.js +106 -0
  14. package/package.json +4 -2
  15. package/scripts/agileflow-configure.js +2 -2
  16. package/scripts/agileflow-welcome.js +409 -434
  17. package/scripts/claude-tmux.sh +80 -2
  18. package/scripts/context-loader.js +4 -9
  19. package/scripts/lib/browser-qa-evidence.js +409 -0
  20. package/scripts/lib/browser-qa-status.js +192 -0
  21. package/scripts/lib/command-prereqs.js +280 -0
  22. package/scripts/lib/configure-detect.js +92 -2
  23. package/scripts/lib/configure-features.js +295 -1
  24. package/scripts/lib/context-formatter.js +468 -233
  25. package/scripts/lib/context-loader.js +27 -15
  26. package/scripts/lib/damage-control-utils.js +8 -1
  27. package/scripts/lib/feature-catalog.js +321 -0
  28. package/scripts/lib/portable-tasks-cli.js +274 -0
  29. package/scripts/lib/portable-tasks.js +479 -0
  30. package/scripts/lib/signal-detectors.js +1 -1
  31. package/scripts/lib/team-events.js +86 -1
  32. package/scripts/obtain-context.js +28 -4
  33. package/scripts/smart-detect.js +17 -0
  34. package/scripts/strip-ai-attribution.js +63 -0
  35. package/scripts/team-manager.js +7 -2
  36. package/scripts/welcome-deferred.js +437 -0
  37. package/src/core/agents/browser-qa.md +328 -0
  38. package/src/core/agents/perf-analyzer-assets.md +174 -0
  39. package/src/core/agents/perf-analyzer-bundle.md +165 -0
  40. package/src/core/agents/perf-analyzer-caching.md +160 -0
  41. package/src/core/agents/perf-analyzer-compute.md +165 -0
  42. package/src/core/agents/perf-analyzer-memory.md +182 -0
  43. package/src/core/agents/perf-analyzer-network.md +157 -0
  44. package/src/core/agents/perf-analyzer-queries.md +155 -0
  45. package/src/core/agents/perf-analyzer-rendering.md +156 -0
  46. package/src/core/agents/perf-consensus.md +280 -0
  47. package/src/core/agents/security-analyzer-api.md +199 -0
  48. package/src/core/agents/security-analyzer-auth.md +160 -0
  49. package/src/core/agents/security-analyzer-authz.md +168 -0
  50. package/src/core/agents/security-analyzer-deps.md +147 -0
  51. package/src/core/agents/security-analyzer-infra.md +176 -0
  52. package/src/core/agents/security-analyzer-injection.md +148 -0
  53. package/src/core/agents/security-analyzer-input.md +191 -0
  54. package/src/core/agents/security-analyzer-secrets.md +175 -0
  55. package/src/core/agents/security-consensus.md +276 -0
  56. package/src/core/agents/test-analyzer-assertions.md +181 -0
  57. package/src/core/agents/test-analyzer-coverage.md +183 -0
  58. package/src/core/agents/test-analyzer-fragility.md +185 -0
  59. package/src/core/agents/test-analyzer-integration.md +155 -0
  60. package/src/core/agents/test-analyzer-maintenance.md +173 -0
  61. package/src/core/agents/test-analyzer-mocking.md +178 -0
  62. package/src/core/agents/test-analyzer-patterns.md +189 -0
  63. package/src/core/agents/test-analyzer-structure.md +177 -0
  64. package/src/core/agents/test-consensus.md +294 -0
  65. package/src/core/commands/{legal/audit.md → audit/legal.md} +13 -13
  66. package/src/core/commands/{logic/audit.md → audit/logic.md} +12 -12
  67. package/src/core/commands/audit/performance.md +443 -0
  68. package/src/core/commands/audit/security.md +443 -0
  69. package/src/core/commands/audit/test.md +442 -0
  70. package/src/core/commands/babysit.md +505 -463
  71. package/src/core/commands/browser-qa.md +240 -0
  72. package/src/core/commands/configure.md +8 -8
  73. package/src/core/commands/research/ask.md +42 -9
  74. package/src/core/commands/research/import.md +14 -8
  75. package/src/core/commands/research/list.md +17 -16
  76. package/src/core/commands/research/synthesize.md +8 -8
  77. package/src/core/commands/research/view.md +28 -4
  78. package/src/core/commands/whats-new.md +2 -2
  79. package/src/core/experts/devops/expertise.yaml +13 -2
  80. package/src/core/experts/documentation/expertise.yaml +26 -4
  81. package/src/core/profiles/COMPARISON.md +170 -0
  82. package/src/core/profiles/README.md +178 -0
  83. package/src/core/profiles/claude-code.yaml +111 -0
  84. package/src/core/profiles/codex.yaml +103 -0
  85. package/src/core/profiles/cursor.yaml +134 -0
  86. package/src/core/profiles/examples.js +250 -0
  87. package/src/core/profiles/loader.js +235 -0
  88. package/src/core/profiles/windsurf.yaml +159 -0
  89. package/src/core/teams/logic-audit.json +6 -0
  90. package/src/core/teams/perf-audit.json +71 -0
  91. package/src/core/teams/security-audit.json +71 -0
  92. package/src/core/teams/test-audit.json +71 -0
  93. package/src/core/templates/browser-qa-spec.yaml +94 -0
  94. package/src/core/templates/command-prerequisites.yaml +169 -0
  95. package/src/core/templates/damage-control-patterns.yaml +9 -0
  96. package/tools/cli/installers/ide/_base-ide.js +33 -3
  97. package/tools/cli/installers/ide/claude-code.js +2 -69
  98. package/tools/cli/installers/ide/codex.js +9 -9
  99. package/tools/cli/installers/ide/cursor.js +165 -4
  100. package/tools/cli/installers/ide/windsurf.js +237 -6
  101. package/tools/cli/lib/content-transformer.js +234 -9
  102. package/tools/cli/lib/docs-setup.js +1 -1
  103. package/tools/cli/lib/ide-generator.js +357 -0
  104. package/tools/cli/lib/ide-registry.js +2 -2
  105. package/scripts/tmux-task-name.sh +0 -105
  106. package/scripts/tmux-task-watcher.sh +0 -344
@@ -62,6 +62,20 @@ const FEATURES = {
62
62
  metadataOnly: false,
63
63
  description: 'Enable Claude Code native Agent Teams (sets env var in .claude/settings.json)',
64
64
  },
65
+ noaiattribution: {
66
+ preToolUseHook: true,
67
+ script: 'strip-ai-attribution.js',
68
+ description: 'Block git commits containing AI attribution (Co-Authored-By, etc.)',
69
+ },
70
+ browserqa: {
71
+ metadataOnly: false,
72
+ description:
73
+ 'Agentic browser testing with Playwright (Bowser four-layer pattern). Screenshot evidence, 80% pass rate threshold.',
74
+ },
75
+ contextverbosity: {
76
+ metadataOnly: true,
77
+ description: 'Control how much context is loaded per command (full/lite/minimal)',
78
+ },
65
79
  };
66
80
 
67
81
  const PROFILES = {
@@ -76,14 +90,23 @@ const PROFILES = {
76
90
  'selfimprove',
77
91
  'askuserquestion',
78
92
  'tmuxautospawn',
93
+ 'noaiattribution',
79
94
  ],
80
95
  archivalDays: 30,
81
96
  },
82
97
  basic: {
83
98
  description: 'Essential hooks + archival (SessionStart + PreCompact + Archival)',
84
- enable: ['sessionstart', 'precompact', 'archival', 'askuserquestion', 'tmuxautospawn'],
99
+ enable: [
100
+ 'sessionstart',
101
+ 'precompact',
102
+ 'archival',
103
+ 'askuserquestion',
104
+ 'tmuxautospawn',
105
+ 'noaiattribution',
106
+ ],
85
107
  disable: ['statusline', 'ralphloop', 'selfimprove'],
86
108
  archivalDays: 30,
109
+ contextVerbosity: 'lite',
87
110
  },
88
111
  minimal: {
89
112
  description: 'SessionStart + archival only',
@@ -97,6 +120,7 @@ const PROFILES = {
97
120
  'tmuxautospawn',
98
121
  ],
99
122
  archivalDays: 30,
123
+ contextVerbosity: 'lite',
100
124
  },
101
125
  none: {
102
126
  description: 'Disable all AgileFlow features',
@@ -109,6 +133,7 @@ const PROFILES = {
109
133
  'selfimprove',
110
134
  'askuserquestion',
111
135
  'tmuxautospawn',
136
+ 'noaiattribution',
112
137
  ],
113
138
  },
114
139
  experimental: {
@@ -123,6 +148,7 @@ const PROFILES = {
123
148
  'selfimprove',
124
149
  'askuserquestion',
125
150
  'tmuxautospawn',
151
+ 'noaiattribution',
126
152
  ],
127
153
  archivalDays: 30,
128
154
  experimental: {
@@ -454,6 +480,48 @@ function enableFeature(feature, options = {}, version) {
454
480
  return enableDamageControl(settings, options, version);
455
481
  }
456
482
 
483
+ // Handle no AI attribution
484
+ if (feature === 'noaiattribution') {
485
+ return enableNoAiAttribution(settings, version);
486
+ }
487
+
488
+ // Handle browser QA (agentic browser testing)
489
+ if (feature === 'browserqa') {
490
+ return enableBrowserQa(version);
491
+ }
492
+
493
+ // Handle context verbosity (metadata only)
494
+ if (feature === 'contextverbosity') {
495
+ const mode = options.mode || 'lite';
496
+ const validModes = ['full', 'lite', 'minimal'];
497
+ if (!validModes.includes(mode)) {
498
+ error(`Invalid verbosity mode: ${mode}. Valid: ${validModes.join(', ')}`);
499
+ return false;
500
+ }
501
+ updateMetadata(
502
+ {
503
+ features: {
504
+ contextVerbosity: {
505
+ enabled: true,
506
+ mode,
507
+ version,
508
+ at: new Date().toISOString(),
509
+ },
510
+ },
511
+ },
512
+ version
513
+ );
514
+ success(`Context verbosity set to: ${mode}`);
515
+ if (mode === 'lite') {
516
+ info('Lite: summary table + git status + active stories + smart recommendations');
517
+ info('Skips: full file dumps, feature catalog, research content, ideation');
518
+ } else if (mode === 'minimal') {
519
+ info('Minimal: summary table only with story counts');
520
+ info('Skips: everything except compact summary');
521
+ }
522
+ return true;
523
+ }
524
+
457
525
  const featureConfig = FEATURES[feature];
458
526
  const contentHash = featureConfig?.script
459
527
  ? hashFile(path.join(SCRIPTS_DIR, featureConfig.script))
@@ -656,6 +724,70 @@ function enableDamageControl(settings, options, version) {
656
724
  return true;
657
725
  }
658
726
 
727
+ /**
728
+ * Enable no AI attribution feature
729
+ */
730
+ function enableNoAiAttribution(settings, version) {
731
+ const scriptName = 'strip-ai-attribution.js';
732
+
733
+ if (!scriptExists(scriptName)) {
734
+ error(`Script not found: ${getScriptPath(scriptName)}`);
735
+ info('Run "npx agileflow update" to reinstall scripts');
736
+ return false;
737
+ }
738
+
739
+ // Initialize PreToolUse array
740
+ if (!settings.hooks.PreToolUse) {
741
+ settings.hooks.PreToolUse = [];
742
+ }
743
+
744
+ const scriptFullPath = path.join(process.cwd(), '.agileflow', 'scripts', scriptName);
745
+
746
+ // Remove existing hook if any
747
+ for (const entry of settings.hooks.PreToolUse) {
748
+ if (entry.matcher === 'Bash' && Array.isArray(entry.hooks)) {
749
+ entry.hooks = entry.hooks.filter(h => !h.command?.includes('strip-ai-attribution'));
750
+ }
751
+ }
752
+ // Clean up empty entries
753
+ settings.hooks.PreToolUse = settings.hooks.PreToolUse.filter(
754
+ h => Array.isArray(h.hooks) && h.hooks.length > 0
755
+ );
756
+
757
+ // Add to existing Bash matcher or create new one
758
+ const bashEntry = settings.hooks.PreToolUse.find(h => h.matcher === 'Bash');
759
+ if (bashEntry) {
760
+ bashEntry.hooks.push({ type: 'command', command: `node ${scriptFullPath}`, timeout: 5 });
761
+ } else {
762
+ settings.hooks.PreToolUse.push({
763
+ matcher: 'Bash',
764
+ hooks: [{ type: 'command', command: `node ${scriptFullPath}`, timeout: 5 }],
765
+ });
766
+ }
767
+
768
+ const contentHash = hashFile(path.join(SCRIPTS_DIR, scriptName));
769
+ updateMetadata(
770
+ {
771
+ features: {
772
+ noaiattribution: {
773
+ enabled: true,
774
+ version,
775
+ ...(contentHash ? { contentHash } : {}),
776
+ at: new Date().toISOString(),
777
+ },
778
+ },
779
+ },
780
+ version
781
+ );
782
+
783
+ writeJSON('.claude/settings.json', settings);
784
+ updateGitignore();
785
+
786
+ success('AI attribution blocking enabled');
787
+ info('Git commits with AI footers (Co-Authored-By, etc.) will be blocked');
788
+ return true;
789
+ }
790
+
659
791
  // ============================================================================
660
792
  // DISABLE FEATURE
661
793
  // ============================================================================
@@ -925,6 +1057,79 @@ function disableFeature(feature, version) {
925
1057
  return true;
926
1058
  }
927
1059
 
1060
+ // Disable browser QA
1061
+ if (feature === 'browserqa') {
1062
+ updateMetadata(
1063
+ {
1064
+ features: {
1065
+ browserqa: {
1066
+ enabled: false,
1067
+ version,
1068
+ at: new Date().toISOString(),
1069
+ },
1070
+ },
1071
+ },
1072
+ version
1073
+ );
1074
+ success('Browser QA disabled');
1075
+ info('Agentic browser testing deactivated');
1076
+ return true;
1077
+ }
1078
+
1079
+ // Disable context verbosity (reset to full)
1080
+ if (feature === 'contextverbosity') {
1081
+ updateMetadata(
1082
+ {
1083
+ features: {
1084
+ contextVerbosity: {
1085
+ enabled: false,
1086
+ mode: 'full',
1087
+ version,
1088
+ at: new Date().toISOString(),
1089
+ },
1090
+ },
1091
+ },
1092
+ version
1093
+ );
1094
+ success('Context verbosity reset to full');
1095
+ return true;
1096
+ }
1097
+
1098
+ // Disable no AI attribution
1099
+ if (feature === 'noaiattribution') {
1100
+ if (settings.hooks?.PreToolUse && Array.isArray(settings.hooks.PreToolUse)) {
1101
+ for (const entry of settings.hooks.PreToolUse) {
1102
+ if (entry.matcher === 'Bash' && Array.isArray(entry.hooks)) {
1103
+ entry.hooks = entry.hooks.filter(h => !h.command?.includes('strip-ai-attribution'));
1104
+ }
1105
+ }
1106
+ // Clean up empty entries
1107
+ settings.hooks.PreToolUse = settings.hooks.PreToolUse.filter(
1108
+ h => Array.isArray(h.hooks) && h.hooks.length > 0
1109
+ );
1110
+ if (settings.hooks.PreToolUse.length === 0) {
1111
+ delete settings.hooks.PreToolUse;
1112
+ }
1113
+ }
1114
+
1115
+ updateMetadata(
1116
+ {
1117
+ features: {
1118
+ noaiattribution: {
1119
+ enabled: false,
1120
+ version,
1121
+ at: new Date().toISOString(),
1122
+ },
1123
+ },
1124
+ },
1125
+ version
1126
+ );
1127
+
1128
+ writeJSON('.claude/settings.json', settings);
1129
+ success('AI attribution blocking disabled');
1130
+ return true;
1131
+ }
1132
+
928
1133
  writeJSON('.claude/settings.json', settings);
929
1134
  updateMetadata(
930
1135
  { features: { [feature]: { enabled: false, version, at: new Date().toISOString() } } },
@@ -966,6 +1171,11 @@ function applyProfile(profileName, options = {}, version) {
966
1171
  profile.disable.forEach(f => disableFeature(f, version));
967
1172
  }
968
1173
 
1174
+ // Apply context verbosity if specified in profile
1175
+ if (profile.contextVerbosity) {
1176
+ enableFeature('contextverbosity', { mode: profile.contextVerbosity }, version);
1177
+ }
1178
+
969
1179
  // Handle experimental profile settings
970
1180
  if (profile.experimental) {
971
1181
  updateMetadata(
@@ -1481,6 +1691,90 @@ function disableShellAliases() {
1481
1691
  // CLAUDE.MD REINFORCEMENT
1482
1692
  // ============================================================================
1483
1693
 
1694
+ // ============================================================================
1695
+ // BROWSER QA
1696
+ // ============================================================================
1697
+
1698
+ /**
1699
+ * Enable browser QA (agentic browser testing)
1700
+ * Creates evidence directory structure, deploys spec template, updates metadata
1701
+ */
1702
+ function enableBrowserQa(version) {
1703
+ // Create evidence directory structure + screenshots dir for visual verification
1704
+ const dirs = [
1705
+ '.agileflow/ui-review',
1706
+ '.agileflow/ui-review/runs',
1707
+ '.agileflow/ui-review/specs',
1708
+ '.agileflow/ui-review/baselines',
1709
+ 'screenshots',
1710
+ ];
1711
+ for (const dir of dirs) {
1712
+ ensureDir(dir);
1713
+ }
1714
+
1715
+ // Deploy spec template if not exists
1716
+ const templateDest = path.join(
1717
+ process.cwd(),
1718
+ '.agileflow',
1719
+ 'ui-review',
1720
+ 'specs',
1721
+ '_template.yaml'
1722
+ );
1723
+ if (!fs.existsSync(templateDest)) {
1724
+ const templateSrc = path.join(process.cwd(), '.agileflow', 'templates', 'browser-qa-spec.yaml');
1725
+ if (fs.existsSync(templateSrc)) {
1726
+ fs.copyFileSync(templateSrc, templateDest);
1727
+ success('Deployed browser-qa spec template');
1728
+ } else {
1729
+ info('No spec template found - create YAML specs manually in .agileflow/ui-review/specs/');
1730
+ }
1731
+ }
1732
+
1733
+ // Check for Playwright
1734
+ let playwrightAvailable = false;
1735
+ try {
1736
+ require.resolve('playwright');
1737
+ playwrightAvailable = true;
1738
+ } catch {
1739
+ // Not installed
1740
+ }
1741
+
1742
+ if (!playwrightAvailable) {
1743
+ warn('Playwright not found - install for browser automation:');
1744
+ info(' npm install --save-optional playwright');
1745
+ info(' npx playwright install chromium');
1746
+ }
1747
+
1748
+ // Update gitignore - evidence runs should not be committed
1749
+ updateGitignore();
1750
+
1751
+ updateMetadata(
1752
+ {
1753
+ features: {
1754
+ browserqa: {
1755
+ enabled: true,
1756
+ version,
1757
+ at: new Date().toISOString(),
1758
+ playwright_detected: playwrightAvailable,
1759
+ },
1760
+ },
1761
+ },
1762
+ version
1763
+ );
1764
+
1765
+ success('UI Testing enabled (agentic browser testing + visual verification)');
1766
+ info('Evidence directory: .agileflow/ui-review/');
1767
+ info('Screenshots directory: screenshots/ (for visual verification with VISUAL=true)');
1768
+ info('Spec template: .agileflow/ui-review/specs/_template.yaml');
1769
+ info('Agentic testing: /agileflow:browser-qa SCENARIO=<spec.yaml>');
1770
+ info('Visual verification: /agileflow:babysit EPIC=EP-XXXX MODE=loop VISUAL=true');
1771
+ if (playwrightAvailable) {
1772
+ info('Playwright: detected');
1773
+ }
1774
+
1775
+ return true;
1776
+ }
1777
+
1484
1778
  const CLAUDE_MD_MARKER = '<!-- AGILEFLOW_BABYSIT_RULES -->';
1485
1779
  const CLAUDE_MD_CONTENT = `
1486
1780