wogiflow 2.4.2 → 2.4.4

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 (210) hide show
  1. package/.claude/commands/wogi-start.md +124 -0
  2. package/.claude/docs/claude-code-compatibility.md +51 -0
  3. package/.claude/docs/explore-agents.md +11 -0
  4. package/.claude/settings.json +12 -1
  5. package/.workflow/models/registry.json +1 -1
  6. package/bin/flow +11 -1
  7. package/lib/workspace-contracts.js +599 -0
  8. package/lib/workspace-intelligence.js +600 -0
  9. package/lib/workspace-messages.js +441 -0
  10. package/lib/workspace-routing.js +485 -0
  11. package/lib/workspace-sync.js +339 -0
  12. package/lib/workspace.js +1073 -0
  13. package/package.json +4 -4
  14. package/scripts/MEMORY-ARCHITECTURE.md +1 -1
  15. package/scripts/base-workflow-step.js +136 -0
  16. package/scripts/flow-adaptive-learning.js +8 -9
  17. package/scripts/flow-aggregate.js +11 -6
  18. package/scripts/flow-api-index.js +4 -6
  19. package/scripts/flow-assumption-detector.js +0 -2
  20. package/scripts/flow-audit.js +15 -2
  21. package/scripts/flow-auto-context.js +8 -12
  22. package/scripts/flow-auto-learn.js +49 -49
  23. package/scripts/flow-background.js +5 -6
  24. package/scripts/flow-bridge-state.js +8 -10
  25. package/scripts/flow-bulk-loop.js +1 -3
  26. package/scripts/flow-bulk-orchestrator.js +1 -3
  27. package/scripts/flow-cascade-completion.js +0 -2
  28. package/scripts/flow-cascade.js +4 -4
  29. package/scripts/flow-checkpoint.js +10 -13
  30. package/scripts/flow-code-intelligence.js +10 -12
  31. package/scripts/flow-community-sync.js +4 -4
  32. package/scripts/flow-community.js +12 -20
  33. package/scripts/flow-config-defaults.js +28 -2
  34. package/scripts/flow-config-interactive.js +9 -5
  35. package/scripts/flow-config-loader.js +49 -92
  36. package/scripts/flow-config-substitution.js +0 -2
  37. package/scripts/flow-context-estimator.js +4 -4
  38. package/scripts/flow-context-init.js +10 -12
  39. package/scripts/flow-context-manager.js +0 -2
  40. package/scripts/flow-context-scoring.js +2 -2
  41. package/scripts/flow-contract-scan.js +6 -9
  42. package/scripts/flow-correct.js +29 -27
  43. package/scripts/flow-correction-detector.js +5 -1
  44. package/scripts/flow-damage-control.js +47 -54
  45. package/scripts/flow-decisions-merge.js +4 -14
  46. package/scripts/flow-diff.js +5 -8
  47. package/scripts/flow-done-gates.js +786 -0
  48. package/scripts/flow-done-report.js +123 -0
  49. package/scripts/flow-done.js +71 -717
  50. package/scripts/flow-entropy-monitor.js +1 -3
  51. package/scripts/flow-eval-calibration.js +257 -0
  52. package/scripts/flow-eval-judge.js +10 -1
  53. package/scripts/flow-eval.js +14 -5
  54. package/scripts/flow-extraction-review.js +1 -0
  55. package/scripts/flow-failure-categories.js +0 -2
  56. package/scripts/flow-figma-confirm.js +5 -9
  57. package/scripts/flow-figma-generate.js +8 -10
  58. package/scripts/flow-figma-index.js +8 -10
  59. package/scripts/flow-figma-match.js +3 -5
  60. package/scripts/flow-figma-mcp-server.js +2 -4
  61. package/scripts/flow-figma-orchestrator.js +2 -3
  62. package/scripts/flow-figma-registry.js +2 -3
  63. package/scripts/flow-framework-resolver.js +0 -2
  64. package/scripts/flow-function-index.js +4 -6
  65. package/scripts/flow-gate-confidence.js +2 -2
  66. package/scripts/flow-gitignore.js +0 -2
  67. package/scripts/flow-guided-edit.js +5 -6
  68. package/scripts/flow-health.js +5 -6
  69. package/scripts/flow-hook-errors.js +6 -0
  70. package/scripts/flow-hook-status.js +263 -0
  71. package/scripts/flow-hooks.js +17 -29
  72. package/scripts/flow-http-client.js +9 -8
  73. package/scripts/flow-hybrid-interactive.js +7 -12
  74. package/scripts/flow-hybrid-test.js +12 -13
  75. package/scripts/flow-instruction-richness.js +1 -1
  76. package/scripts/flow-io.js +21 -4
  77. package/scripts/flow-knowledge-router.js +9 -3
  78. package/scripts/flow-learning-orchestrator.js +318 -13
  79. package/scripts/flow-links.js +5 -7
  80. package/scripts/flow-long-input-association.js +275 -0
  81. package/scripts/flow-long-input-chunking.js +1 -0
  82. package/scripts/flow-long-input-cli.js +0 -2
  83. package/scripts/flow-long-input-complexity.js +0 -2
  84. package/scripts/flow-long-input-constants.js +0 -2
  85. package/scripts/flow-long-input-contradictions.js +351 -0
  86. package/scripts/flow-long-input-detection.js +0 -2
  87. package/scripts/flow-long-input-passes.js +885 -0
  88. package/scripts/flow-long-input-stories.js +1 -1
  89. package/scripts/flow-long-input-voice.js +0 -2
  90. package/scripts/flow-long-input.js +425 -3005
  91. package/scripts/flow-loop-retry-learning.js +2 -3
  92. package/scripts/flow-lsp.js +3 -3
  93. package/scripts/flow-mcp-docs.js +3 -4
  94. package/scripts/flow-memory-db.js +6 -8
  95. package/scripts/flow-memory-sync.js +18 -11
  96. package/scripts/flow-metrics.js +1 -2
  97. package/scripts/flow-model-adapter.js +2 -3
  98. package/scripts/flow-model-config.js +72 -104
  99. package/scripts/flow-model-router.js +2 -2
  100. package/scripts/flow-model-types.js +0 -2
  101. package/scripts/flow-multi-approach.js +5 -6
  102. package/scripts/flow-orchestrate-context.js +3 -7
  103. package/scripts/flow-orchestrate-rollback.js +3 -8
  104. package/scripts/flow-orchestrate-state.js +8 -14
  105. package/scripts/flow-orchestrate-templates.js +2 -6
  106. package/scripts/flow-orchestrate-validator.js +5 -9
  107. package/scripts/flow-orchestrate.js +126 -103
  108. package/scripts/flow-output.js +0 -2
  109. package/scripts/flow-parallel.js +1 -1
  110. package/scripts/flow-paths.js +23 -2
  111. package/scripts/flow-pattern-enforcer.js +30 -28
  112. package/scripts/flow-pattern-extractor.js +3 -4
  113. package/scripts/flow-pending.js +0 -2
  114. package/scripts/flow-permissions.js +2 -3
  115. package/scripts/flow-plugin-registry.js +10 -12
  116. package/scripts/flow-prd-manager.js +1 -1
  117. package/scripts/flow-progress.js +7 -9
  118. package/scripts/flow-prompt-composer.js +3 -3
  119. package/scripts/flow-prompt-template.js +2 -2
  120. package/scripts/flow-providers.js +7 -4
  121. package/scripts/flow-registry-manager.js +7 -12
  122. package/scripts/flow-regression.js +9 -11
  123. package/scripts/flow-roadmap.js +2 -2
  124. package/scripts/flow-run-trace.js +16 -15
  125. package/scripts/flow-safety.js +2 -5
  126. package/scripts/flow-scanner-base.js +5 -7
  127. package/scripts/flow-scenario-engine.js +1 -5
  128. package/scripts/flow-security.js +29 -0
  129. package/scripts/flow-session-end.js +32 -41
  130. package/scripts/flow-session-learning.js +53 -49
  131. package/scripts/flow-setup-hooks.js +2 -3
  132. package/scripts/flow-skill-create.js +7 -12
  133. package/scripts/flow-skill-generator.js +12 -16
  134. package/scripts/flow-skill-learn.js +17 -8
  135. package/scripts/flow-skill-matcher.js +1 -2
  136. package/scripts/flow-spec-generator.js +2 -4
  137. package/scripts/flow-stack-wizard.js +5 -7
  138. package/scripts/flow-standards-learner.js +35 -16
  139. package/scripts/flow-start.js +2 -0
  140. package/scripts/flow-stats-collector.js +2 -2
  141. package/scripts/flow-status.js +10 -10
  142. package/scripts/flow-statusline-setup.js +2 -2
  143. package/scripts/flow-step-changelog.js +2 -3
  144. package/scripts/flow-step-comments.js +66 -81
  145. package/scripts/flow-step-complexity.js +50 -70
  146. package/scripts/flow-step-coverage.js +3 -5
  147. package/scripts/flow-step-knowledge.js +2 -3
  148. package/scripts/flow-step-pr-tests.js +64 -74
  149. package/scripts/flow-step-regression.js +3 -5
  150. package/scripts/flow-step-review.js +86 -103
  151. package/scripts/flow-step-security.js +111 -121
  152. package/scripts/flow-step-silent-failures.js +56 -83
  153. package/scripts/flow-step-simplifier.js +52 -70
  154. package/scripts/flow-story.js +4 -7
  155. package/scripts/flow-strict-adherence.js +3 -4
  156. package/scripts/flow-task-checkpoint.js +36 -5
  157. package/scripts/flow-task-enforcer.js +2 -24
  158. package/scripts/flow-tech-debt.js +1 -1
  159. package/scripts/flow-template-extractor.js +1 -0
  160. package/scripts/flow-templates.js +11 -13
  161. package/scripts/flow-test-api.js +9 -13
  162. package/scripts/flow-test-discovery.js +1 -1
  163. package/scripts/flow-test-generate.js +5 -9
  164. package/scripts/flow-test-integrity.js +3 -7
  165. package/scripts/flow-test-ui.js +5 -9
  166. package/scripts/flow-testing-deps.js +1 -3
  167. package/scripts/flow-tiered-learning.js +4 -4
  168. package/scripts/flow-todowrite-sync.js +1 -1
  169. package/scripts/flow-tokens.js +0 -2
  170. package/scripts/flow-verification-profile.js +6 -10
  171. package/scripts/flow-verify.js +12 -16
  172. package/scripts/flow-version-check.js +4 -12
  173. package/scripts/flow-webmcp-generator.js +3 -5
  174. package/scripts/flow-workflow-steps.js +0 -2
  175. package/scripts/flow-workflow.js +9 -11
  176. package/scripts/hooks/adapters/claude-code.js +31 -0
  177. package/scripts/hooks/core/config-change.js +1 -0
  178. package/scripts/hooks/core/extension-registry.js +0 -2
  179. package/scripts/hooks/core/instructions-loaded.js +1 -1
  180. package/scripts/hooks/core/observation-capture.js +5 -5
  181. package/scripts/hooks/core/phase-gate.js +5 -0
  182. package/scripts/hooks/core/post-compact.js +1 -12
  183. package/scripts/hooks/core/research-gate.js +2 -12
  184. package/scripts/hooks/core/routing-gate.js +6 -0
  185. package/scripts/hooks/core/task-completed.js +12 -0
  186. package/scripts/hooks/core/task-created.js +83 -0
  187. package/scripts/hooks/core/worktree-lifecycle.js +1 -1
  188. package/scripts/hooks/entry/claude-code/config-change.js +6 -29
  189. package/scripts/hooks/entry/claude-code/instructions-loaded.js +5 -30
  190. package/scripts/hooks/entry/claude-code/post-compact.js +4 -31
  191. package/scripts/hooks/entry/claude-code/post-tool-use.js +121 -172
  192. package/scripts/hooks/entry/claude-code/pre-tool-use.js +260 -361
  193. package/scripts/hooks/entry/claude-code/session-end.js +4 -28
  194. package/scripts/hooks/entry/claude-code/session-start.js +205 -243
  195. package/scripts/hooks/entry/claude-code/setup.js +8 -49
  196. package/scripts/hooks/entry/claude-code/stop.js +40 -72
  197. package/scripts/hooks/entry/claude-code/task-completed.js +4 -28
  198. package/scripts/hooks/entry/claude-code/task-created.js +15 -0
  199. package/scripts/hooks/entry/claude-code/user-prompt-submit.js +113 -195
  200. package/scripts/hooks/entry/claude-code/worktree-create.js +6 -25
  201. package/scripts/hooks/entry/claude-code/worktree-remove.js +6 -25
  202. package/scripts/hooks/entry/shared/hook-runner.js +99 -0
  203. package/scripts/hooks/entry/shared/read-stdin.js +0 -2
  204. package/scripts/postinstall.js +2 -0
  205. package/scripts/registries/api-registry.js +0 -2
  206. package/scripts/registries/component-registry.js +5 -9
  207. package/scripts/registries/contract-scanner.js +2 -9
  208. package/scripts/registries/function-registry.js +0 -2
  209. package/scripts/registries/schema-registry.js +14 -18
  210. package/scripts/registries/service-registry.js +23 -27
@@ -10,84 +10,73 @@
10
10
 
11
11
  const fs = require('node:fs');
12
12
  const path = require('node:path');
13
- const { getProjectRoot, colors, readJson } = require('./flow-utils');
13
+ const { BaseWorkflowStep } = require('./base-workflow-step');
14
+ const { colors, readJson, PATHS } = require('./flow-utils');
15
+
16
+ class PrTestStep extends BaseWorkflowStep {
17
+ constructor() {
18
+ super('prTestAnalyzer', {
19
+ extensions: ['.js', '.ts', '.jsx', '.tsx'],
20
+ excludeTests: true,
21
+ excludeDts: true,
22
+ });
23
+ }
14
24
 
15
- const PROJECT_ROOT = getProjectRoot();
25
+ // Override filterFiles for PR-test-specific exclusions
26
+ filterFiles(files) {
27
+ return super.filterFiles(files).filter(f =>
28
+ !f.includes('__tests__') && !f.includes('__mocks__')
29
+ );
30
+ }
16
31
 
17
- /**
18
- * Run PR test analysis as a workflow step
19
- *
20
- * @param {object} options
21
- * @param {string[]} options.files - Files modified
22
- * @param {object} options.stepConfig - Step configuration
23
- * @param {string} options.mode - Step mode (block/warn/prompt/auto)
24
- * @returns {object} - { passed: boolean, message: string, details?: object }
25
- */
26
- async function run(options = {}) {
27
- const { files = [], stepConfig = {} } = options;
28
- const checkCoverage = stepConfig.checkCoverage !== false;
29
- const checkQuality = stepConfig.checkQuality !== false;
30
- const minCoverageForModified = stepConfig.minCoverageForModified || 70;
31
-
32
- // Filter to source files (not test files)
33
- const sourceExtensions = ['.js', '.ts', '.jsx', '.tsx'];
34
- const sourceFiles = files.filter(f =>
35
- sourceExtensions.some(ext => f.endsWith(ext)) &&
36
- !f.includes('.test.') &&
37
- !f.includes('.spec.') &&
38
- !f.includes('.d.ts') &&
39
- !f.includes('__tests__') &&
40
- !f.includes('__mocks__')
41
- );
32
+ async execute(sourceFiles, options) {
33
+ const { stepConfig = {} } = options;
34
+ const checkCoverage = stepConfig.checkCoverage !== false;
35
+ const checkQuality = stepConfig.checkQuality !== false;
36
+ const minCoverageForModified = stepConfig.minCoverageForModified || 70;
42
37
 
43
- if (sourceFiles.length === 0) {
44
- return { passed: true, message: 'No source files to analyze' };
45
- }
38
+ // We need the original unfiltered files for test quality analysis
39
+ const allFiles = options.files ?? sourceFiles;
46
40
 
47
- const issues = [];
48
- const coverageReport = {};
49
- const qualityReport = {};
50
-
51
- // Check coverage for modified files
52
- if (checkCoverage) {
53
- const coverageIssues = await analyzeCoverage(sourceFiles, minCoverageForModified);
54
- issues.push(...coverageIssues.issues);
55
- Object.assign(coverageReport, coverageIssues.report);
56
- }
41
+ const issues = [];
42
+ const coverageReport = {};
43
+ const qualityReport = {};
57
44
 
58
- // Check test quality
59
- if (checkQuality) {
60
- const qualityIssues = await analyzeTestQuality(sourceFiles, files);
61
- issues.push(...qualityIssues.issues);
62
- Object.assign(qualityReport, qualityIssues.report);
63
- }
45
+ if (checkCoverage) {
46
+ const coverageIssues = await analyzeCoverage(sourceFiles, minCoverageForModified);
47
+ issues.push(...coverageIssues.issues);
48
+ Object.assign(coverageReport, coverageIssues.report);
49
+ }
50
+
51
+ if (checkQuality) {
52
+ const qualityIssues = await analyzeTestQuality(sourceFiles, allFiles);
53
+ issues.push(...qualityIssues.issues);
54
+ Object.assign(qualityReport, qualityIssues.report);
55
+ }
64
56
 
65
- // Report findings
66
- if (issues.length > 0) {
67
- console.log(colors.yellow + '\n PR Test Analysis Issues:' + colors.reset);
68
- for (const issue of issues) {
69
- const icon = issue.severity === 'high' ? '\u{1F534}' : '\u{1F7E1}';
70
- console.log(` ${icon} ${issue.file}`);
71
- console.log(` ${issue.type}: ${issue.message}`);
72
- if (issue.suggestion) {
73
- console.log(colors.dim + ` \u{2192} ${issue.suggestion}` + colors.reset);
57
+ if (issues.length > 0) {
58
+ console.log(colors.yellow + '\n PR Test Analysis Issues:' + colors.reset);
59
+ for (const issue of issues) {
60
+ const icon = issue.severity === 'high' ? '\u{1F534}' : '\u{1F7E1}';
61
+ console.log(` ${icon} ${issue.file}`);
62
+ console.log(` ${issue.type}: ${issue.message}`);
63
+ if (issue.suggestion) {
64
+ console.log(colors.dim + ` \u{2192} ${issue.suggestion}` + colors.reset);
65
+ }
74
66
  }
75
67
  }
76
- }
77
68
 
78
- const highSeverity = issues.filter(i => i.severity === 'high');
69
+ const highSeverity = issues.filter(i => i.severity === 'high');
79
70
 
80
- return {
81
- passed: highSeverity.length === 0,
82
- message: issues.length === 0
71
+ const message = issues.length === 0
83
72
  ? `Test analysis passed (${sourceFiles.length} files)`
84
- : `${issues.length} issue(s) found (${highSeverity.length} high severity)`,
85
- details: {
86
- issues,
87
- coverage: coverageReport,
88
- quality: qualityReport,
89
- },
90
- };
73
+ : `${issues.length} issue(s) found (${highSeverity.length} high severity)`;
74
+ const details = { issues, coverage: coverageReport, quality: qualityReport };
75
+
76
+ return highSeverity.length === 0
77
+ ? { passed: true, message, details }
78
+ : this.fail(message, details);
79
+ }
91
80
  }
92
81
 
93
82
  /**
@@ -98,7 +87,7 @@ async function analyzeCoverage(sourceFiles, minCoverage) {
98
87
  const report = { checked: [], missing: [], below: [] };
99
88
 
100
89
  // Check if coverage report exists
101
- const coveragePath = path.join(PROJECT_ROOT, 'coverage', 'coverage-summary.json');
90
+ const coveragePath = path.join(PATHS.root, 'coverage', 'coverage-summary.json');
102
91
  let coverageData = null;
103
92
 
104
93
  if (fs.existsSync(coveragePath)) {
@@ -106,7 +95,7 @@ async function analyzeCoverage(sourceFiles, minCoverage) {
106
95
  }
107
96
 
108
97
  for (const file of sourceFiles) {
109
- const filePath = path.join(PROJECT_ROOT, file);
98
+ const filePath = path.join(PATHS.root, file);
110
99
  if (!fs.existsSync(filePath)) continue;
111
100
 
112
101
  // Find corresponding test file
@@ -118,7 +107,7 @@ async function analyzeCoverage(sourceFiles, minCoverage) {
118
107
  ];
119
108
 
120
109
  const hasTest = testPatterns.some(pattern => {
121
- const testPath = path.join(PROJECT_ROOT, pattern);
110
+ const testPath = path.join(PATHS.root, pattern);
122
111
  return fs.existsSync(testPath);
123
112
  });
124
113
 
@@ -144,7 +133,7 @@ async function analyzeCoverage(sourceFiles, minCoverage) {
144
133
 
145
134
  // Check coverage if available
146
135
  if (coverageData) {
147
- const absPath = path.resolve(PROJECT_ROOT, file);
136
+ const absPath = path.resolve(PATHS.root, file);
148
137
  const fileCoverage = coverageData[absPath];
149
138
 
150
139
  if (fileCoverage) {
@@ -182,7 +171,7 @@ async function analyzeTestQuality(sourceFiles, allFiles) {
182
171
  );
183
172
 
184
173
  for (const testFile of testFiles) {
185
- const testPath = path.join(PROJECT_ROOT, testFile);
174
+ const testPath = path.join(PATHS.root, testFile);
186
175
  if (!fs.existsSync(testPath)) continue;
187
176
 
188
177
  try {
@@ -203,7 +192,7 @@ async function analyzeTestQuality(sourceFiles, allFiles) {
203
192
 
204
193
  // Also check source files for testability concerns
205
194
  for (const sourceFile of sourceFiles) {
206
- const sourcePath = path.join(PROJECT_ROOT, sourceFile);
195
+ const sourcePath = path.join(PATHS.root, sourceFile);
207
196
  if (!fs.existsSync(sourcePath)) continue;
208
197
 
209
198
  try {
@@ -357,4 +346,5 @@ function checkTestability(content, fileName) {
357
346
  return issues;
358
347
  }
359
348
 
360
- module.exports = { run, analyzeCoverage, analyzeTestQuality };
349
+ const step = new PrTestStep();
350
+ module.exports = { run: (opts) => step.run(opts), analyzeCoverage, analyzeTestQuality };
@@ -9,9 +9,7 @@
9
9
 
10
10
  const { execSync } = require('node:child_process');
11
11
  const path = require('node:path');
12
- const { getProjectRoot } = require('./flow-utils');
13
-
14
- const PROJECT_ROOT = getProjectRoot();
12
+ const { getProjectRoot, PATHS } = require('./flow-utils');
15
13
 
16
14
  /**
17
15
  * Run regression tests as a workflow step
@@ -28,9 +26,9 @@ async function run(options = {}) {
28
26
 
29
27
  try {
30
28
  // Run regression tests
31
- const regressionScript = path.join(PROJECT_ROOT, 'scripts', 'flow-regression.js');
29
+ const regressionScript = path.join(PATHS.root, 'scripts', 'flow-regression.js');
32
30
  const result = execSync(`node "${regressionScript}" --count ${sampleSize} --json`, {
33
- cwd: PROJECT_ROOT,
31
+ cwd: PATHS.root,
34
32
  encoding: 'utf8',
35
33
  stdio: ['pipe', 'pipe', 'pipe'],
36
34
  });
@@ -14,9 +14,8 @@
14
14
 
15
15
  const fs = require('node:fs');
16
16
  const path = require('node:path');
17
- const { getProjectRoot, colors } = require('./flow-utils');
18
-
19
- const PROJECT_ROOT = getProjectRoot();
17
+ const { BaseWorkflowStep } = require('./base-workflow-step');
18
+ const { colors, PATHS } = require('./flow-utils');
20
19
 
21
20
  // High-risk patterns that trigger multi-agent review
22
21
  const HIGH_RISK_PATTERNS = [
@@ -28,120 +27,103 @@ const HIGH_RISK_PATTERNS = [
28
27
  'database', 'migration', 'schema',
29
28
  ];
30
29
 
31
- /**
32
- * Run code review as a workflow step
33
- *
34
- * @param {object} options
35
- * @param {string[]} options.files - Files modified
36
- * @param {object} options.stepConfig - Step configuration
37
- * @param {string} options.mode - Step mode (block/warn/prompt/auto)
38
- * @param {string} options.taskType - Type of task (feature/bugfix/refactor)
39
- * @returns {object} - { passed: boolean, message: string, details?: object[] }
40
- */
41
- async function run(options = {}) {
42
- const { files = [], stepConfig = {}, taskType } = options;
43
- const multiAgentThreshold = stepConfig.multiAgentThreshold || 5;
44
- const confidenceThreshold = stepConfig.confidenceThreshold || 80;
45
- const highRiskPatterns = stepConfig.highRiskPatterns || HIGH_RISK_PATTERNS;
46
-
47
- // Filter to reviewable files
48
- const reviewableExtensions = ['.js', '.ts', '.jsx', '.tsx', '.py', '.go', '.rs'];
49
- const reviewableFiles = files.filter(f =>
50
- reviewableExtensions.some(ext => f.endsWith(ext)) &&
51
- !f.includes('.test.') &&
52
- !f.includes('.spec.') &&
53
- !f.includes('.d.ts')
54
- );
55
-
56
- if (reviewableFiles.length === 0) {
57
- return { passed: true, message: 'No reviewable files modified' };
30
+ class ReviewStep extends BaseWorkflowStep {
31
+ constructor() {
32
+ super('codeReview', {
33
+ extensions: ['.js', '.ts', '.jsx', '.tsx', '.py', '.go', '.rs'],
34
+ excludeTests: true,
35
+ excludeDts: true,
36
+ });
58
37
  }
59
38
 
60
- // Determine if high-risk
61
- const isHighRisk = taskType === 'refactor' ||
62
- reviewableFiles.some(f => highRiskPatterns.some(p => f.toLowerCase().includes(p)));
39
+ async execute(files, options) {
40
+ const { stepConfig = {}, taskType } = options;
41
+ const multiAgentThreshold = stepConfig.multiAgentThreshold || 5;
42
+ const confidenceThreshold = stepConfig.confidenceThreshold || 80;
43
+ const highRiskPatterns = stepConfig.highRiskPatterns || HIGH_RISK_PATTERNS;
63
44
 
64
- // Choose review mode
65
- const useMultiAgent = reviewableFiles.length > multiAgentThreshold || isHighRisk;
45
+ // Determine if high-risk
46
+ const isHighRisk = taskType === 'refactor' ||
47
+ files.some(f => highRiskPatterns.some(p => f.toLowerCase().includes(p)));
66
48
 
67
- let issues;
68
- if (useMultiAgent) {
69
- console.log(colors.cyan + ' Running multi-agent code review...' + colors.reset);
70
- issues = await runMultiAgentReview(reviewableFiles, stepConfig);
71
- } else {
72
- console.log(colors.cyan + ' Running simple code review...' + colors.reset);
73
- issues = await runSimpleReview(reviewableFiles, stepConfig);
74
- }
49
+ // Choose review mode
50
+ const useMultiAgent = files.length > multiAgentThreshold || isHighRisk;
75
51
 
76
- // Filter by confidence threshold
77
- const reportableIssues = issues.filter(i => i.confidence >= confidenceThreshold);
52
+ let issues;
53
+ if (useMultiAgent) {
54
+ console.log(colors.cyan + ' Running multi-agent code review...' + colors.reset);
55
+ issues = await runMultiAgentReview(files, stepConfig);
56
+ } else {
57
+ console.log(colors.cyan + ' Running simple code review...' + colors.reset);
58
+ issues = await runSimpleReview(files, stepConfig);
59
+ }
78
60
 
79
- if (reportableIssues.length === 0) {
80
- return {
81
- passed: true,
82
- message: useMultiAgent
83
- ? `Multi-agent review passed (${reviewableFiles.length} files)`
84
- : `Simple review passed (${reviewableFiles.length} files)`,
85
- };
86
- }
61
+ // Filter by confidence threshold
62
+ const reportableIssues = issues.filter(i => i.confidence >= confidenceThreshold);
87
63
 
88
- // Report issues
89
- console.log(colors.yellow + '\n Code Review Issues:' + colors.reset);
64
+ if (reportableIssues.length === 0) {
65
+ return this.pass(useMultiAgent
66
+ ? `Multi-agent review passed (${files.length} files)`
67
+ : `Simple review passed (${files.length} files)`);
68
+ }
90
69
 
91
- const criticalIssues = reportableIssues.filter(i => i.severity === 'critical');
92
- const importantIssues = reportableIssues.filter(i => i.severity === 'important');
70
+ // Report issues
71
+ console.log(colors.yellow + '\n Code Review Issues:' + colors.reset);
93
72
 
94
- if (criticalIssues.length > 0) {
95
- console.log(colors.red + ' Critical:' + colors.reset);
96
- for (const issue of criticalIssues) {
97
- printIssue(issue);
98
- }
99
- }
73
+ const criticalIssues = reportableIssues.filter(i => i.severity === 'critical');
74
+ const importantIssues = reportableIssues.filter(i => i.severity === 'important');
100
75
 
101
- if (importantIssues.length > 0) {
102
- console.log(colors.yellow + ' Important:' + colors.reset);
103
- for (const issue of importantIssues) {
104
- printIssue(issue);
76
+ if (criticalIssues.length > 0) {
77
+ console.log(colors.red + ' Critical:' + colors.reset);
78
+ for (const issue of criticalIssues) {
79
+ printIssue(issue);
80
+ }
105
81
  }
106
- }
107
-
108
- // Critical issues block, important issues warn
109
- const hasCritical = criticalIssues.length > 0;
110
82
 
111
- // Auto-capture learnings from issues found
112
- if (reportableIssues.length > 0) {
113
- try {
114
- const { captureFromSessionReview } = require('./flow-auto-learn');
115
- captureFromSessionReview(reportableIssues);
116
- } catch (err) {
117
- // Auto-learn not available or failed - continue silently
83
+ if (importantIssues.length > 0) {
84
+ console.log(colors.yellow + ' Important:' + colors.reset);
85
+ for (const issue of importantIssues) {
86
+ printIssue(issue);
87
+ }
118
88
  }
119
89
 
120
- // Also capture to tech debt ledger for persistent tracking
121
- try {
122
- const { TechDebtManager } = require('./flow-tech-debt');
123
- const debtManager = new TechDebtManager();
124
- const { added, updated } = debtManager.addIssues(reportableIssues.map(issue => ({
125
- file: issue.file,
126
- line: issue.line,
127
- category: issue.perspective || 'code',
128
- severity: issue.severity === 'critical' ? 'critical' : (issue.severity === 'important' ? 'high' : 'medium'),
129
- description: issue.description,
130
- fix: issue.fix || ''
131
- })));
132
- if (added > 0 || updated > 0) {
133
- console.log(colors.dim + ` Tech debt: ${added} new, ${updated} updated` + colors.reset);
90
+ // Auto-capture learnings from issues found
91
+ if (reportableIssues.length > 0) {
92
+ try {
93
+ const { captureFromSessionReview } = require('./flow-auto-learn');
94
+ captureFromSessionReview(reportableIssues);
95
+ } catch (_err) {
96
+ // Auto-learn not available or failed - continue silently
97
+ }
98
+
99
+ try {
100
+ const { TechDebtManager } = require('./flow-tech-debt');
101
+ const debtManager = new TechDebtManager();
102
+ const { added, updated } = debtManager.addIssues(reportableIssues.map(issue => ({
103
+ file: issue.file,
104
+ line: issue.line,
105
+ category: issue.perspective || 'code',
106
+ severity: issue.severity === 'critical' ? 'critical' : (issue.severity === 'important' ? 'high' : 'medium'),
107
+ description: issue.description,
108
+ fix: issue.fix || ''
109
+ })));
110
+ if (added > 0 || updated > 0) {
111
+ console.log(colors.dim + ` Tech debt: ${added} new, ${updated} updated` + colors.reset);
112
+ }
113
+ } catch (_err) {
114
+ // Tech debt manager not available or failed - continue silently
134
115
  }
135
- } catch (err) {
136
- // Tech debt manager not available or failed - continue silently
137
116
  }
138
- }
139
117
 
140
- return {
141
- passed: !hasCritical,
142
- message: `${reportableIssues.length} issue(s) found (${criticalIssues.length} critical, ${importantIssues.length} important)`,
143
- details: reportableIssues,
144
- };
118
+ const hasCritical = criticalIssues.length > 0;
119
+
120
+ return hasCritical
121
+ ? this.fail(
122
+ `${reportableIssues.length} issue(s) found (${criticalIssues.length} critical, ${importantIssues.length} important)`,
123
+ reportableIssues
124
+ )
125
+ : this.pass(`${reportableIssues.length} issue(s) found (${criticalIssues.length} critical, ${importantIssues.length} important)`);
126
+ }
145
127
  }
146
128
 
147
129
  /**
@@ -164,7 +146,7 @@ async function runMultiAgentReview(files, config) {
164
146
  const allIssues = [];
165
147
 
166
148
  for (const file of files) {
167
- const filePath = path.join(PROJECT_ROOT, file);
149
+ const filePath = path.join(PATHS.root, file);
168
150
  if (!fs.existsSync(filePath)) continue;
169
151
 
170
152
  try {
@@ -198,7 +180,7 @@ async function runSimpleReview(files, config) {
198
180
  const allIssues = [];
199
181
 
200
182
  for (const file of files) {
201
- const filePath = path.join(PROJECT_ROOT, file);
183
+ const filePath = path.join(PATHS.root, file);
202
184
  if (!fs.existsSync(filePath)) continue;
203
185
 
204
186
  try {
@@ -532,4 +514,5 @@ function mergeIssues(issues) {
532
514
  return merged;
533
515
  }
534
516
 
535
- module.exports = { run, runMultiAgentReview, runSimpleReview };
517
+ const step = new ReviewStep();
518
+ module.exports = { run: (opts) => step.run(opts), runMultiAgentReview, runSimpleReview };