devflow-kit 1.4.0 → 1.5.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 (45) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +2 -1
  3. package/dist/commands/init.js +29 -0
  4. package/dist/commands/list.d.ts +21 -0
  5. package/dist/commands/list.js +71 -3
  6. package/dist/plugins.js +1 -1
  7. package/dist/utils/manifest.d.ts +45 -0
  8. package/dist/utils/manifest.js +100 -0
  9. package/package.json +1 -1
  10. package/plugins/devflow-accessibility/.claude-plugin/plugin.json +1 -1
  11. package/plugins/devflow-ambient/.claude-plugin/plugin.json +1 -1
  12. package/plugins/devflow-ambient/skills/ambient-router/SKILL.md +1 -1
  13. package/plugins/devflow-ambient/skills/ambient-router/references/skill-catalog.md +1 -0
  14. package/plugins/devflow-audit-claude/.claude-plugin/plugin.json +1 -1
  15. package/plugins/devflow-code-review/.claude-plugin/plugin.json +1 -1
  16. package/plugins/devflow-code-review/agents/reviewer.md +42 -5
  17. package/plugins/devflow-code-review/agents/synthesizer.md +12 -5
  18. package/plugins/devflow-code-review/commands/code-review.md +4 -1
  19. package/plugins/devflow-core-skills/.claude-plugin/plugin.json +2 -1
  20. package/plugins/devflow-core-skills/skills/search-first/SKILL.md +133 -0
  21. package/plugins/devflow-core-skills/skills/search-first/references/evaluation-criteria.md +101 -0
  22. package/plugins/devflow-debug/.claude-plugin/plugin.json +1 -1
  23. package/plugins/devflow-frontend-design/.claude-plugin/plugin.json +1 -1
  24. package/plugins/devflow-go/.claude-plugin/plugin.json +1 -1
  25. package/plugins/devflow-implement/.claude-plugin/plugin.json +1 -1
  26. package/plugins/devflow-implement/agents/coder.md +16 -13
  27. package/plugins/devflow-implement/agents/synthesizer.md +12 -5
  28. package/plugins/devflow-implement/commands/implement-teams.md +1 -5
  29. package/plugins/devflow-implement/commands/implement.md +1 -5
  30. package/plugins/devflow-java/.claude-plugin/plugin.json +1 -1
  31. package/plugins/devflow-python/.claude-plugin/plugin.json +1 -1
  32. package/plugins/devflow-react/.claude-plugin/plugin.json +1 -1
  33. package/plugins/devflow-resolve/.claude-plugin/plugin.json +1 -1
  34. package/plugins/devflow-rust/.claude-plugin/plugin.json +1 -1
  35. package/plugins/devflow-self-review/.claude-plugin/plugin.json +1 -1
  36. package/plugins/devflow-specify/.claude-plugin/plugin.json +1 -1
  37. package/plugins/devflow-specify/agents/synthesizer.md +12 -5
  38. package/plugins/devflow-typescript/.claude-plugin/plugin.json +1 -1
  39. package/shared/agents/coder.md +16 -13
  40. package/shared/agents/reviewer.md +42 -5
  41. package/shared/agents/synthesizer.md +12 -5
  42. package/shared/skills/ambient-router/SKILL.md +1 -1
  43. package/shared/skills/ambient-router/references/skill-catalog.md +1 -0
  44. package/shared/skills/search-first/SKILL.md +133 -0
  45. package/shared/skills/search-first/references/evaluation-criteria.md +101 -0
package/CHANGELOG.md CHANGED
@@ -5,6 +5,18 @@ All notable changes to DevFlow will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [1.5.0] - 2026-03-13
9
+
10
+ ### Added
11
+ - **Search-first skill** (#111) — New skill enforcing research before building custom utility code. 4-phase loop: Need Analysis → Search (via Explore subagent) → Evaluate → Decide (Adopt/Extend/Compose/Build)
12
+ - **Reviewer confidence thresholds** (#113) — Each review finding now includes a visible confidence score (0-100%). Only ≥80% findings appear in main sections; lower-confidence items go to a capped Suggestions section. Adds consolidation rules to group similar issues and skip stylistic preferences
13
+ - **Version manifest** (#91) — Tracks installed version, plugins, and features in `manifest.json`. Enables upgrade detection during `devflow init` and shows install status in `devflow list`
14
+
15
+ ### Fixed
16
+ - **Synthesizer review glob** — Fixed `${REVIEW_BASE_DIR}/*-report.*.md` glob that matched zero reviewer files; now uses `${REVIEW_BASE_DIR}/*.md` with self-exclusion
17
+
18
+ ---
19
+
8
20
  ## [1.4.0] - 2026-03-09
9
21
 
10
22
  ### Added
@@ -853,6 +865,8 @@ devflow init
853
865
 
854
866
  ---
855
867
 
868
+ [Unreleased]: https://github.com/dean0x/devflow/compare/v1.4.0...HEAD
869
+ [1.5.0]: https://github.com/dean0x/devflow/compare/v1.4.0...v1.5.0
856
870
  [1.4.0]: https://github.com/dean0x/devflow/compare/v1.3.3...v1.4.0
857
871
  [1.3.3]: https://github.com/dean0x/devflow/compare/v1.3.2...v1.3.3
858
872
  [1.3.2]: https://github.com/dean0x/devflow/compare/v1.3.1...v1.3.2
package/README.md CHANGED
@@ -24,7 +24,7 @@ DevFlow adds structured commands that handle the full lifecycle: specify feature
24
24
  - **Full-lifecycle implementation** — spec, explore, plan, code, validate, refine in one command
25
25
  - **Automatic session memory** — survives restarts, `/clear`, and context compaction
26
26
  - **Parallel debugging** — competing hypotheses investigated simultaneously
27
- - **30 quality skills** — 8 auto-activating core, 8 optional language/ecosystem, plus specialized review and agent skills
27
+ - **31 quality skills** — 9 auto-activating core, 8 optional language/ecosystem, plus specialized review and agent skills
28
28
 
29
29
  ## Quick Start
30
30
 
@@ -120,6 +120,7 @@ The `devflow-core-skills` plugin provides quality enforcement skills that activa
120
120
  | `test-driven-development` | Implementing new features (RED-GREEN-REFACTOR) |
121
121
  | `test-patterns` | Writing or modifying tests |
122
122
  | `input-validation` | Creating API endpoints |
123
+ | `search-first` | Adding utilities, helpers, or infrastructure code |
123
124
 
124
125
  ## Language & Ecosystem Plugins
125
126
 
@@ -15,6 +15,7 @@ import { detectPlatform, detectShell, getProfilePath, getSafeDeleteInfo, hasSafe
15
15
  import { generateSafeDeleteBlock, installToProfile, removeFromProfile, getInstalledVersion, SAFE_DELETE_BLOCK_VERSION } from '../utils/safe-delete-install.js';
16
16
  import { addAmbientHook } from './ambient.js';
17
17
  import { addMemoryHooks, removeMemoryHooks } from './memory.js';
18
+ import { readManifest, writeManifest, resolvePluginList, detectUpgrade } from '../utils/manifest.js';
18
19
  // Re-export pure functions for tests (canonical source is post-install.ts)
19
20
  export { substituteSettingsTemplate, computeGitignoreAppend, applyTeamsConfig, stripTeamsConfig, mergeDenyList } from '../utils/post-install.js';
20
21
  export { addAmbientHook, removeAmbientHook, hasAmbientHook } from './ambient.js';
@@ -238,6 +239,17 @@ export const initCommand = new Command('init')
238
239
  p.log.error(`Path configuration error: ${error instanceof Error ? error.message : error}`);
239
240
  process.exit(1);
240
241
  }
242
+ // Check existing manifest for upgrade detection
243
+ const existingManifest = await readManifest(devflowDir);
244
+ if (existingManifest) {
245
+ const upgrade = detectUpgrade(version, existingManifest.version);
246
+ if (upgrade.isUpgrade) {
247
+ s.message(`Upgrading from v${upgrade.previousVersion} to v${version}`);
248
+ }
249
+ else if (upgrade.isSameVersion) {
250
+ s.message('Reinstalling same version');
251
+ }
252
+ }
241
253
  // Validate target directory
242
254
  s.message('Validating target directory');
243
255
  if (scope === 'local') {
@@ -519,6 +531,23 @@ export const initCommand = new Command('init')
519
531
  p.log.info(`Deduplication: ${skillsMap.size} unique skills (from ${totalSkillDeclarations} declarations)`);
520
532
  p.log.info(`Deduplication: ${agentsMap.size} unique agents (from ${totalAgentDeclarations} declarations)`);
521
533
  }
534
+ // Write installation manifest for upgrade tracking (non-fatal — install already succeeded)
535
+ const installedPluginNames = pluginsToInstall.map(pl => pl.name);
536
+ const now = new Date().toISOString();
537
+ const manifestData = {
538
+ version,
539
+ plugins: resolvePluginList(installedPluginNames, existingManifest, !!options.plugin),
540
+ scope,
541
+ features: { teams: teamsEnabled, ambient: ambientEnabled, memory: memoryEnabled },
542
+ installedAt: existingManifest?.installedAt ?? now,
543
+ updatedAt: now,
544
+ };
545
+ try {
546
+ await writeManifest(devflowDir, manifestData);
547
+ }
548
+ catch (error) {
549
+ p.log.warn(`Failed to write installation manifest (install succeeded): ${error instanceof Error ? error.message : error}`);
550
+ }
522
551
  p.outro(color.green('Ready! Run any command in Claude Code to get started.'));
523
552
  });
524
553
  //# sourceMappingURL=init.js.map
@@ -1,3 +1,24 @@
1
1
  import { Command } from 'commander';
2
+ import { type ManifestData } from '../utils/manifest.js';
3
+ /**
4
+ * Format manifest feature flags into a human-readable comma-separated string.
5
+ * Returns 'none' when no features are enabled.
6
+ */
7
+ export declare function formatFeatures(features: ManifestData['features']): string;
8
+ /**
9
+ * Determine effective installation scope based on which manifest was found.
10
+ * Local scope takes precedence when a local manifest exists.
11
+ */
12
+ export declare function resolveScope(localManifest: ManifestData | null): 'user' | 'local';
13
+ /**
14
+ * Compute the install status indicator for a plugin.
15
+ * Returns 'installed', 'not_installed', or 'unknown' (when no manifest exists).
16
+ */
17
+ export declare function getPluginInstallStatus(pluginName: string, installedPlugins: ReadonlySet<string>, hasManifest: boolean): 'installed' | 'not_installed' | 'unknown';
18
+ /**
19
+ * Format the commands portion of a plugin entry.
20
+ * Returns the comma-separated command list or '(skills only)' for skill-only plugins.
21
+ */
22
+ export declare function formatPluginCommands(commands: string[]): string;
2
23
  export declare const listCommand: Command;
3
24
  //# sourceMappingURL=list.d.ts.map
@@ -2,19 +2,87 @@ import { Command } from 'commander';
2
2
  import * as p from '@clack/prompts';
3
3
  import color from 'picocolors';
4
4
  import { DEVFLOW_PLUGINS } from '../plugins.js';
5
+ import { getDevFlowDirectory } from '../utils/paths.js';
6
+ import { getGitRoot } from '../utils/git.js';
7
+ import { readManifest } from '../utils/manifest.js';
8
+ import * as path from 'path';
9
+ /**
10
+ * Format manifest feature flags into a human-readable comma-separated string.
11
+ * Returns 'none' when no features are enabled.
12
+ */
13
+ export function formatFeatures(features) {
14
+ return [
15
+ features.teams ? 'teams' : null,
16
+ features.ambient ? 'ambient' : null,
17
+ features.memory ? 'memory' : null,
18
+ ].filter(Boolean).join(', ') || 'none';
19
+ }
20
+ /**
21
+ * Determine effective installation scope based on which manifest was found.
22
+ * Local scope takes precedence when a local manifest exists.
23
+ */
24
+ export function resolveScope(localManifest) {
25
+ return localManifest ? 'local' : 'user';
26
+ }
27
+ /**
28
+ * Compute the install status indicator for a plugin.
29
+ * Returns 'installed', 'not_installed', or 'unknown' (when no manifest exists).
30
+ */
31
+ export function getPluginInstallStatus(pluginName, installedPlugins, hasManifest) {
32
+ if (!hasManifest)
33
+ return 'unknown';
34
+ return installedPlugins.has(pluginName) ? 'installed' : 'not_installed';
35
+ }
36
+ /**
37
+ * Format the commands portion of a plugin entry.
38
+ * Returns the comma-separated command list or '(skills only)' for skill-only plugins.
39
+ */
40
+ export function formatPluginCommands(commands) {
41
+ return commands.length > 0 ? commands.join(', ') : '(skills only)';
42
+ }
5
43
  export const listCommand = new Command('list')
6
44
  .description('List available DevFlow plugins')
7
- .action(() => {
45
+ .action(async () => {
8
46
  p.intro(color.bgCyan(color.black(' DevFlow Plugins ')));
47
+ // Resolve user manifest and git root in parallel (independent I/O)
48
+ const userDevflowDir = getDevFlowDirectory();
49
+ const [gitRoot, userManifest] = await Promise.all([
50
+ getGitRoot(),
51
+ readManifest(userDevflowDir),
52
+ ]);
53
+ const localDevflowDir = gitRoot ? path.join(gitRoot, '.devflow') : null;
54
+ const localManifest = localDevflowDir ? await readManifest(localDevflowDir) : null;
55
+ const manifest = localManifest ?? userManifest;
56
+ // Show install status if manifest exists
57
+ if (manifest) {
58
+ const installedAt = new Date(manifest.installedAt).toLocaleDateString();
59
+ const updatedAt = new Date(manifest.updatedAt).toLocaleDateString();
60
+ const scope = resolveScope(localManifest);
61
+ const features = formatFeatures(manifest.features);
62
+ p.note(`${color.dim('Version:')} ${color.cyan(`v${manifest.version}`)}\n` +
63
+ `${color.dim('Scope:')} ${scope}\n` +
64
+ `${color.dim('Features:')} ${features}\n` +
65
+ `${color.dim('Installed:')} ${installedAt}` +
66
+ (installedAt !== updatedAt ? ` ${color.dim('Updated:')} ${updatedAt}` : ''), 'Installation');
67
+ }
68
+ const installedPlugins = new Set(manifest?.plugins ?? []);
69
+ const hasManifest = manifest !== null;
9
70
  const maxNameLen = Math.max(...DEVFLOW_PLUGINS.map(p => p.name.length));
10
71
  const pluginList = DEVFLOW_PLUGINS
11
72
  .map(plugin => {
12
- const cmds = plugin.commands.length > 0 ? plugin.commands.join(', ') : '(skills only)';
73
+ const cmds = formatPluginCommands(plugin.commands);
13
74
  const optionalTag = plugin.optional ? color.dim(' (optional)') : '';
14
- return `${color.cyan(plugin.name.padEnd(maxNameLen + 2))}${color.dim(plugin.description)}${optionalTag}\n${' '.repeat(maxNameLen + 2)}${color.yellow(cmds)}`;
75
+ const status = getPluginInstallStatus(plugin.name, installedPlugins, hasManifest);
76
+ const installedTag = status === 'installed' ? color.green(' ✓')
77
+ : status === 'not_installed' ? color.dim(' ✗')
78
+ : '';
79
+ return `${color.cyan(plugin.name.padEnd(maxNameLen + 2))}${color.dim(plugin.description)}${optionalTag}${installedTag}\n${' '.repeat(maxNameLen + 2)}${color.yellow(cmds)}`;
15
80
  })
16
81
  .join('\n\n');
17
82
  p.note(pluginList, 'Available plugins');
83
+ if (!manifest) {
84
+ p.log.info(color.dim('Run `devflow init` for install tracking'));
85
+ }
18
86
  p.outro(color.dim('Install with: npx devflow-kit init --plugin=<name>'));
19
87
  });
20
88
  //# sourceMappingURL=list.js.map
package/dist/plugins.js CHANGED
@@ -10,7 +10,7 @@ export const DEVFLOW_PLUGINS = [
10
10
  description: 'Auto-activating quality enforcement (foundation layer)',
11
11
  commands: [],
12
12
  agents: [],
13
- skills: ['core-patterns', 'docs-framework', 'git-safety', 'git-workflow', 'github-patterns', 'input-validation', 'test-driven-development', 'test-patterns'],
13
+ skills: ['core-patterns', 'docs-framework', 'git-safety', 'git-workflow', 'github-patterns', 'input-validation', 'search-first', 'test-driven-development', 'test-patterns'],
14
14
  },
15
15
  {
16
16
  name: 'devflow-specify',
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Manifest data tracked for each DevFlow installation.
3
+ */
4
+ export interface ManifestData {
5
+ version: string;
6
+ plugins: string[];
7
+ scope: 'user' | 'local';
8
+ features: {
9
+ teams: boolean;
10
+ ambient: boolean;
11
+ memory: boolean;
12
+ };
13
+ installedAt: string;
14
+ updatedAt: string;
15
+ }
16
+ /**
17
+ * Read and parse the manifest file. Returns null if missing or corrupt.
18
+ */
19
+ export declare function readManifest(devflowDir: string): Promise<ManifestData | null>;
20
+ /**
21
+ * Write manifest to disk. Creates parent directory if needed.
22
+ */
23
+ export declare function writeManifest(devflowDir: string, data: ManifestData): Promise<void>;
24
+ /**
25
+ * Merge new plugins into existing plugin list (union, no duplicates).
26
+ * Preserves order: existing plugins first, then new ones appended.
27
+ */
28
+ export declare function mergeManifestPlugins(existing: string[], newPlugins: string[]): string[];
29
+ /**
30
+ * Detect upgrade/downgrade/same version status.
31
+ */
32
+ export interface UpgradeInfo {
33
+ isUpgrade: boolean;
34
+ isDowngrade: boolean;
35
+ isSameVersion: boolean;
36
+ previousVersion: string | null;
37
+ }
38
+ /**
39
+ * Resolve the final plugin list for a manifest write.
40
+ * On partial installs (--plugin flag), merge newly installed plugins into
41
+ * the existing manifest's plugin list. On full installs, replace entirely.
42
+ */
43
+ export declare function resolvePluginList(installedPluginNames: string[], existingManifest: ManifestData | null, isPartialInstall: boolean): string[];
44
+ export declare function detectUpgrade(currentVersion: string, installedVersion: string | null): UpgradeInfo;
45
+ //# sourceMappingURL=manifest.d.ts.map
@@ -0,0 +1,100 @@
1
+ import { promises as fs } from 'fs';
2
+ import * as path from 'path';
3
+ /**
4
+ * Read and parse the manifest file. Returns null if missing or corrupt.
5
+ */
6
+ export async function readManifest(devflowDir) {
7
+ const manifestPath = path.join(devflowDir, 'manifest.json');
8
+ try {
9
+ const content = await fs.readFile(manifestPath, 'utf-8');
10
+ const data = JSON.parse(content);
11
+ if (!data.version ||
12
+ !Array.isArray(data.plugins) ||
13
+ !data.scope ||
14
+ typeof data.features !== 'object' ||
15
+ data.features === null ||
16
+ typeof data.features.teams !== 'boolean' ||
17
+ typeof data.features.ambient !== 'boolean' ||
18
+ typeof data.features.memory !== 'boolean' ||
19
+ typeof data.installedAt !== 'string' ||
20
+ typeof data.updatedAt !== 'string') {
21
+ return null;
22
+ }
23
+ return data;
24
+ }
25
+ catch {
26
+ return null;
27
+ }
28
+ }
29
+ /**
30
+ * Write manifest to disk. Creates parent directory if needed.
31
+ */
32
+ export async function writeManifest(devflowDir, data) {
33
+ await fs.mkdir(devflowDir, { recursive: true });
34
+ const manifestPath = path.join(devflowDir, 'manifest.json');
35
+ await fs.writeFile(manifestPath, JSON.stringify(data, null, 2) + '\n', 'utf-8');
36
+ }
37
+ /**
38
+ * Merge new plugins into existing plugin list (union, no duplicates).
39
+ * Preserves order: existing plugins first, then new ones appended.
40
+ */
41
+ export function mergeManifestPlugins(existing, newPlugins) {
42
+ const merged = [...existing];
43
+ for (const plugin of newPlugins) {
44
+ if (!merged.includes(plugin)) {
45
+ merged.push(plugin);
46
+ }
47
+ }
48
+ return merged;
49
+ }
50
+ /**
51
+ * Compare two semver strings. Returns -1, 0, or 1.
52
+ * Handles simple x.y.z versions; returns null for unparseable input.
53
+ *
54
+ * Note: Pre-release suffixes (e.g., `-beta.1`, `-rc.2`) are silently ignored.
55
+ * `1.0.0-beta.1` and `1.0.0` compare as equal. Build metadata is also ignored.
56
+ */
57
+ function compareSemver(a, b) {
58
+ const parse = (v) => {
59
+ const match = v.match(/^v?(\d+)\.(\d+)\.(\d+)/);
60
+ return match ? [Number(match[1]), Number(match[2]), Number(match[3])] : [];
61
+ };
62
+ const pa = parse(a);
63
+ const pb = parse(b);
64
+ if (pa.length === 0 || pb.length === 0)
65
+ return null;
66
+ for (let i = 0; i < 3; i++) {
67
+ if (pa[i] > pb[i])
68
+ return 1;
69
+ if (pa[i] < pb[i])
70
+ return -1;
71
+ }
72
+ return 0;
73
+ }
74
+ /**
75
+ * Resolve the final plugin list for a manifest write.
76
+ * On partial installs (--plugin flag), merge newly installed plugins into
77
+ * the existing manifest's plugin list. On full installs, replace entirely.
78
+ */
79
+ export function resolvePluginList(installedPluginNames, existingManifest, isPartialInstall) {
80
+ if (existingManifest && isPartialInstall) {
81
+ return mergeManifestPlugins(existingManifest.plugins, installedPluginNames);
82
+ }
83
+ return installedPluginNames;
84
+ }
85
+ export function detectUpgrade(currentVersion, installedVersion) {
86
+ if (!installedVersion) {
87
+ return { isUpgrade: false, isDowngrade: false, isSameVersion: false, previousVersion: null };
88
+ }
89
+ const cmp = compareSemver(currentVersion, installedVersion);
90
+ if (cmp === null) {
91
+ return { isUpgrade: false, isDowngrade: false, isSameVersion: false, previousVersion: installedVersion };
92
+ }
93
+ return {
94
+ isUpgrade: cmp > 0,
95
+ isDowngrade: cmp < 0,
96
+ isSameVersion: cmp === 0,
97
+ previousVersion: installedVersion,
98
+ };
99
+ }
100
+ //# sourceMappingURL=manifest.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "devflow-kit",
3
- "version": "1.4.0",
3
+ "version": "1.5.0",
4
4
  "description": "Agentic Development Toolkit for Claude Code - Enhance AI-assisted development with intelligent commands and workflows",
5
5
  "type": "module",
6
6
  "bin": {
@@ -4,7 +4,7 @@
4
4
  "author": {
5
5
  "name": "Dean0x"
6
6
  },
7
- "version": "1.4.0",
7
+ "version": "1.5.0",
8
8
  "homepage": "https://github.com/dean0x/devflow",
9
9
  "repository": "https://github.com/dean0x/devflow",
10
10
  "license": "MIT",
@@ -4,7 +4,7 @@
4
4
  "author": {
5
5
  "name": "Dean0x"
6
6
  },
7
- "version": "1.4.0",
7
+ "version": "1.5.0",
8
8
  "agents": [],
9
9
  "skills": [
10
10
  "ambient-router"
@@ -54,7 +54,7 @@ Based on classified intent, read the following skills to inform your response.
54
54
 
55
55
  | Intent | Primary Skills | Secondary (if file type matches) |
56
56
  |--------|---------------|----------------------------------|
57
- | **BUILD** | test-driven-development, implementation-patterns | typescript (.ts), react (.tsx/.jsx), go (.go), java (.java), python (.py), rust (.rs), frontend-design (CSS/UI), input-validation (forms/API), security-patterns (auth/crypto) |
57
+ | **BUILD** | test-driven-development, implementation-patterns, search-first | typescript (.ts), react (.tsx/.jsx), go (.go), java (.java), python (.py), rust (.rs), frontend-design (CSS/UI), input-validation (forms/API), security-patterns (auth/crypto) |
58
58
  | **DEBUG** | test-patterns, core-patterns | git-safety (if git operations involved) |
59
59
  | **REVIEW** | self-review, core-patterns | test-patterns |
60
60
  | **PLAN** | implementation-patterns | core-patterns |
@@ -12,6 +12,7 @@ These skills may be loaded during GUIDED-depth ambient routing.
12
12
  |-------|-------------|---------------|
13
13
  | test-driven-development | Always for BUILD | `*.ts`, `*.tsx`, `*.js`, `*.jsx`, `*.py` |
14
14
  | implementation-patterns | Always for BUILD | Any code file |
15
+ | search-first | Always for BUILD | Any code file |
15
16
  | typescript | TypeScript files in scope | `*.ts`, `*.tsx` |
16
17
  | react | React components in scope | `*.tsx`, `*.jsx` |
17
18
  | frontend-design | UI/styling work | `*.css`, `*.scss`, `*.tsx` with styling keywords |
@@ -4,7 +4,7 @@
4
4
  "author": {
5
5
  "name": "Dean0x"
6
6
  },
7
- "version": "1.4.0",
7
+ "version": "1.5.0",
8
8
  "agents": [],
9
9
  "skills": []
10
10
  }
@@ -4,7 +4,7 @@
4
4
  "author": {
5
5
  "name": "Dean0x"
6
6
  },
7
- "version": "1.4.0",
7
+ "version": "1.5.0",
8
8
  "homepage": "https://github.com/dean0x/devflow",
9
9
  "repository": "https://github.com/dean0x/devflow",
10
10
  "license": "MIT",
@@ -46,8 +46,33 @@ The orchestrator provides:
46
46
  3. **Apply 3-category classification** - Sort issues by where they occur
47
47
  4. **Apply focus-specific analysis** - Use pattern skill detection rules from the loaded skill file
48
48
  5. **Assign severity** - CRITICAL, HIGH, MEDIUM, LOW based on impact
49
- 6. **Generate report** - File:line references with suggested fixes
50
- 7. **Determine merge recommendation** - Based on blocking issues
49
+ 6. **Assess confidence** - Assign 0-100% confidence to each finding (see Confidence Scale below)
50
+ 7. **Filter by confidence** - Only report findings ≥80% in main sections; lower-confidence items go to Suggestions
51
+ 8. **Consolidate similar issues** - Group related findings to reduce noise (see Consolidation Rules)
52
+ 9. **Generate report** - File:line references with suggested fixes
53
+ 10. **Determine merge recommendation** - Based on blocking issues
54
+
55
+ ## Confidence Scale
56
+
57
+ Assess how certain you are that each finding is a real issue (not a false positive):
58
+
59
+ | Range | Label | Meaning |
60
+ |-------|-------|---------|
61
+ | 90-100% | Certain | Clearly a bug, vulnerability, or violation — no ambiguity |
62
+ | 80-89% | High | Very likely an issue, but minor chance of false positive |
63
+ | 60-79% | Medium | Plausible issue, but depends on context you may not fully see |
64
+ | < 60% | Low | Possible concern, but likely a matter of style or interpretation |
65
+
66
+ <!-- Confidence threshold also in: shared/agents/synthesizer.md, plugins/devflow-code-review/commands/code-review.md -->
67
+ **Threshold**: Only report findings with ≥80% confidence in Blocking, Should-Fix, and Pre-existing sections. Findings with 60-79% confidence go to the Suggestions section. Findings < 60% are dropped entirely.
68
+
69
+ ## Consolidation Rules
70
+
71
+ Before writing your report, apply these noise reduction rules:
72
+
73
+ 1. **Group similar issues** — If 3+ instances of the same pattern appear (e.g., "missing error handling" in multiple functions), consolidate into 1 finding listing all locations rather than N separate findings
74
+ 2. **Skip stylistic preferences** — Do not flag formatting, naming style, or code organization choices unless they violate explicit project conventions found in CLAUDE.md, .editorconfig, or linter configs
75
+ 3. **Skip issues in unchanged code** — Pre-existing issues in lines you did NOT change should only be reported if CRITICAL severity (security vulnerabilities, data loss risks)
51
76
 
52
77
  ## Issue Categories (from review-methodology)
53
78
 
@@ -76,17 +101,29 @@ Report format for `{output_path}`:
76
101
 
77
102
  ### CRITICAL
78
103
  **{Issue}** - `file.ts:123`
104
+ **Confidence**: {n}%
79
105
  - Problem: {description}
80
106
  - Fix: {suggestion with code}
81
107
 
108
+ **{Issue Title} ({N} occurrences)** — Confidence: {n}%
109
+ - `file1.ts:12`, `file2.ts:45`, `file3.ts:89`
110
+ - Problem: {description of the shared pattern}
111
+ - Fix: {suggestion that applies to all occurrences}
112
+
82
113
  ### HIGH
83
- {issues...}
114
+ {issues with **Confidence**: {n}% each...}
84
115
 
85
116
  ## Issues in Code You Touched (Should Fix)
86
- {issues with file:line...}
117
+ {issues with file:line and **Confidence**: {n}% each...}
87
118
 
88
119
  ## Pre-existing Issues (Not Blocking)
89
- {informational issues...}
120
+ {informational issues with **Confidence**: {n}% each...}
121
+
122
+ ## Suggestions (Lower Confidence)
123
+
124
+ {Max 3 items with 60-79% confidence. Brief description only — no code fixes.}
125
+
126
+ - **{Issue}** - `file.ts:456` (Confidence: {n}%) — {brief description}
90
127
 
91
128
  ## Summary
92
129
  | Category | CRITICAL | HIGH | MEDIUM | LOW |
@@ -128,10 +128,14 @@ Analyze 3 axes to determine strategy:
128
128
  Synthesize outputs from multiple Reviewer agents. Apply strict merge rules.
129
129
 
130
130
  **Process:**
131
- 1. Read all review reports from `${REVIEW_BASE_DIR}/*-report.*.md`
132
- 2. Categorize issues into 3 buckets (from review-methodology)
133
- 3. Count by severity (CRITICAL, HIGH, MEDIUM, LOW)
134
- 4. Determine merge recommendation based on blocking issues
131
+ 1. Read all review reports from `${REVIEW_BASE_DIR}/*.md` (exclude your own output `review-summary.*.md`)
132
+ 2. Extract confidence percentages from each finding
133
+ 3. Apply confidence-aware aggregation: when multiple reviewers flag the same file:line, boost confidence by 10% per additional reviewer (cap at 100%)
134
+ <!-- Confidence threshold also in: shared/agents/reviewer.md, plugins/devflow-code-review/commands/code-review.md -->
135
+ 4. Maintain ≥80% confidence threshold in final output
136
+ 5. Categorize issues into 3 buckets (from review-methodology)
137
+ 6. Count by severity (CRITICAL, HIGH, MEDIUM, LOW)
138
+ 7. Determine merge recommendation based on blocking issues
135
139
 
136
140
  **Issue Categories:**
137
141
  - **Blocking** (Category 1): Issues in YOUR changes - CRITICAL/HIGH must block
@@ -172,7 +176,10 @@ Report format:
172
176
  | Pre-existing | - | - | {n} | {n} | {n} |
173
177
 
174
178
  ## Blocking Issues
175
- {List with file:line and suggested fix}
179
+ {List with file:line, confidence %, and suggested fix}
180
+
181
+ ## Suggestions (Lower Confidence)
182
+ {Max 5 items across all reviewers with 60-79% confidence. Brief descriptions only.}
176
183
 
177
184
  ## Action Plan
178
185
  1. {Priority fix}
@@ -95,7 +95,10 @@ IMPORTANT: Write report to .docs/reviews/{branch-slug}/{focus}.md using Write to
95
95
  Task(subagent_type="Git", run_in_background=false):
96
96
  "OPERATION: comment-pr
97
97
  Read reviews from .docs/reviews/{branch-slug}/
98
- Create inline PR comments, deduplicate, consolidate skipped into summary"
98
+ <!-- Confidence threshold also in: shared/agents/reviewer.md, shared/agents/synthesizer.md -->
99
+ Create inline PR comments for findings with ≥80% confidence only.
100
+ Lower-confidence suggestions (60-79%) go in the summary comment, not as inline comments.
101
+ Deduplicate findings across reviewers, consolidate skipped into summary."
99
102
  ```
100
103
 
101
104
  **Synthesizer Agent**:
@@ -4,7 +4,7 @@
4
4
  "author": {
5
5
  "name": "Dean0x"
6
6
  },
7
- "version": "1.4.0",
7
+ "version": "1.5.0",
8
8
  "homepage": "https://github.com/dean0x/devflow",
9
9
  "repository": "https://github.com/dean0x/devflow",
10
10
  "license": "MIT",
@@ -24,6 +24,7 @@
24
24
  "git-workflow",
25
25
  "github-patterns",
26
26
  "input-validation",
27
+ "search-first",
27
28
  "test-driven-development",
28
29
  "test-patterns"
29
30
  ]