claude-flow 2.7.31 → 2.7.33

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 (29) hide show
  1. package/.claude/skills/agentic-jujutsu/SKILL.md +645 -0
  2. package/CHANGELOG.md +19 -0
  3. package/bin/claude-flow +1 -1
  4. package/dist/src/cli/simple-cli.js +173 -79
  5. package/dist/src/cli/simple-cli.js.map +1 -1
  6. package/dist/src/cli/simple-commands/init/agent-copier.js +3 -9
  7. package/dist/src/cli/simple-commands/init/agent-copier.js.map +1 -1
  8. package/dist/src/cli/simple-commands/memory.js +67 -17
  9. package/dist/src/cli/simple-commands/memory.js.map +1 -1
  10. package/dist/src/core/version.js +1 -1
  11. package/dist/src/core/version.js.map +1 -1
  12. package/dist/src/utils/key-redactor.js.map +1 -1
  13. package/docs/AGENT_FOLDER_STRUCTURE_FIX.md +192 -0
  14. package/docs/BUG_REPORT_MEMORY_STATS.md +355 -0
  15. package/docs/FIX_VERIFICATION_MEMORY_STATS.md +235 -0
  16. package/docs/RECENT_RELEASES_SUMMARY.md +375 -0
  17. package/docs/V2.7.31_RELEASE_NOTES.md +375 -0
  18. package/package.json +2 -1
  19. package/src/cli/simple-commands/init/agent-copier.js +5 -10
  20. package/src/cli/simple-commands/memory.js +93 -19
  21. /package/.claude/agents/analysis/{code-review/analyze-code-quality.md → analyze-code-quality.md} +0 -0
  22. /package/.claude/agents/architecture/{system-design/arch-system-design.md → arch-system-design.md} +0 -0
  23. /package/.claude/agents/data/{ml/data-ml-model.md → data-ml-model.md} +0 -0
  24. /package/.claude/agents/development/{backend/dev-backend-api.md → dev-backend-api.md} +0 -0
  25. /package/.claude/agents/devops/{ci-cd/ops-cicd-github.md → ops-cicd-github.md} +0 -0
  26. /package/.claude/agents/documentation/{api-docs/docs-api-openapi.md → docs-api-openapi.md} +0 -0
  27. /package/.claude/agents/specialized/{mobile/spec-mobile-react-native.md → spec-mobile-react-native.md} +0 -0
  28. /package/.claude/agents/testing/{validation/production-validator.md → production-validator.md} +0 -0
  29. /package/.claude/agents/testing/{unit/tdd-london-swarm.md → tdd-london-swarm.md} +0 -0
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/utils/key-redactor.js"],"sourcesContent":["/**\n * API Key Redaction Utility\n * Prevents sensitive data from leaking into logs, memory, or git commits\n */\n\nexport class KeyRedactor {\n static API_KEY_PATTERNS = [\n // Anthropic API keys\n /sk-ant-[a-zA-Z0-9_-]{95,}/gi,\n\n // OpenRouter API keys\n /sk-or-[a-zA-Z0-9_-]{32,}/gi,\n\n // Google/Gemini API keys\n /AIza[a-zA-Z0-9_-]{35}/gi,\n\n // Generic API keys\n /[a-zA-Z0-9_-]{20,}API[a-zA-Z0-9_-]{20,}/gi,\n\n // Bearer tokens\n /Bearer\\s+[a-zA-Z0-9_\\-\\.]{20,}/gi,\n\n // Environment variable format\n /([A-Z_]+_API_KEY|[A-Z_]+_TOKEN|[A-Z_]+_SECRET)=[\"']?([^\"'\\s]+)[\"']?/gi,\n\n // Supabase keys\n /eyJ[a-zA-Z0-9_-]*\\.eyJ[a-zA-Z0-9_-]*\\.[a-zA-Z0-9_-]*/gi,\n ];\n\n static SENSITIVE_FIELDS = [\n 'apiKey',\n 'api_key',\n 'token',\n 'secret',\n 'password',\n 'private_key',\n 'privateKey',\n 'accessToken',\n 'access_token',\n 'refreshToken',\n 'refresh_token',\n ];\n\n /**\n * Redact API keys and sensitive data from text\n */\n static redact(text, showPrefix = true) {\n if (!text) return text;\n\n let redacted = text;\n\n // Redact using patterns\n this.API_KEY_PATTERNS.forEach(pattern => {\n redacted = redacted.replace(pattern, (match) => {\n if (showPrefix && match.length > 8) {\n const prefix = match.substring(0, 8);\n return `${prefix}...[REDACTED]`;\n }\n return '[REDACTED_API_KEY]';\n });\n });\n\n return redacted;\n }\n\n /**\n * Redact sensitive fields in objects\n */\n static redactObject(obj, deep = true) {\n if (!obj || typeof obj !== 'object') return obj;\n\n const redacted = { ...obj };\n\n Object.keys(redacted).forEach(key => {\n const lowerKey = key.toLowerCase();\n\n // Check if field name is sensitive\n const isSensitive = this.SENSITIVE_FIELDS.some(field =>\n lowerKey.includes(field)\n );\n\n if (isSensitive && typeof redacted[key] === 'string') {\n const value = redacted[key];\n if (value && value.length > 8) {\n redacted[key] = `${value.substring(0, 4)}...[REDACTED]`;\n } else {\n redacted[key] = '[REDACTED]';\n }\n } else if (deep && typeof redacted[key] === 'object' && redacted[key] !== null) {\n redacted[key] = this.redactObject(redacted[key], deep);\n } else if (typeof redacted[key] === 'string') {\n // Redact any API keys in string values\n redacted[key] = this.redact(redacted[key]);\n }\n });\n\n return redacted;\n }\n\n /**\n * Sanitize text for safe logging\n */\n static sanitize(text) {\n return this.redact(text, true);\n }\n\n /**\n * Sanitize command arguments\n */\n static sanitizeArgs(args) {\n return args.map(arg => {\n // Check if arg is a flag value pair\n if (arg.includes('key') || arg.includes('token') || arg.includes('secret')) {\n return this.redact(arg);\n }\n return arg;\n });\n }\n\n /**\n * Check if text contains unredacted sensitive data\n */\n static containsSensitiveData(text) {\n return this.API_KEY_PATTERNS.some(pattern => pattern.test(text));\n }\n\n /**\n * Validate that text is safe for logging/storage\n */\n static validate(text) {\n const warnings = [];\n\n this.API_KEY_PATTERNS.forEach((pattern, index) => {\n if (pattern.test(text)) {\n warnings.push(`Potential API key detected (pattern ${index + 1})`);\n }\n });\n\n return {\n safe: warnings.length === 0,\n warnings,\n };\n }\n\n /**\n * Redact environment variables\n */\n static redactEnv(env) {\n const redacted = {};\n\n Object.keys(env).forEach(key => {\n const value = env[key];\n if (!value) {\n redacted[key] = '';\n return;\n }\n\n const lowerKey = key.toLowerCase();\n const isSensitive = lowerKey.includes('key') ||\n lowerKey.includes('token') ||\n lowerKey.includes('secret') ||\n lowerKey.includes('password');\n\n if (isSensitive) {\n redacted[key] = value.length > 8\n ? `${value.substring(0, 4)}...[REDACTED]`\n : '[REDACTED]';\n } else {\n redacted[key] = value;\n }\n });\n\n return redacted;\n }\n}\n\n// Export singleton instance\nexport const redactor = KeyRedactor;\n"],"names":["KeyRedactor","API_KEY_PATTERNS","SENSITIVE_FIELDS","redact","text","showPrefix","redacted","forEach","pattern","replace","match","length","prefix","substring","redactObject","obj","deep","Object","keys","key","lowerKey","toLowerCase","isSensitive","some","field","includes","value","sanitize","sanitizeArgs","args","map","arg","containsSensitiveData","test","validate","warnings","index","push","safe","redactEnv","env","redactor"],"mappings":"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"},GAAG,CAACrB,IAAI;YACtB,IAAI,CAACO,OAAO;gBACVpB,QAAQ,CAACa,IAAI,GAAG;gBAChB;YACF;YAEA,MAAMC,WAAWD,IAAIE,WAAW;YAChC,MAAMC,cAAcF,SAASK,QAAQ,CAAC,UACnBL,SAASK,QAAQ,CAAC,YAClBL,SAASK,QAAQ,CAAC,aAClBL,SAASK,QAAQ,CAAC;YAErC,IAAIH,aAAa;gBACfhB,QAAQ,CAACa,IAAI,GAAGO,MAAMf,MAAM,GAAG,IAC3B,GAAGe,MAAMb,SAAS,CAAC,GAAG,GAAG,aAAa,CAAC,GACvC;YACN,OAAO;gBACLP,QAAQ,CAACa,IAAI,GAAGO;YAClB;QACF;QAEA,OAAOpB;IACT;AACF;AAGA,OAAO,MAAMmC,WAAWzC,YAAY"}
1
+ {"version":3,"sources":["../../../src/utils/key-redactor.ts"],"sourcesContent":["/**\n * API Key Redaction Utility\n * Prevents sensitive data from leaking into logs, memory, or git commits\n */\n\nexport interface RedactionConfig {\n patterns: RegExp[];\n replacement: string;\n maskLength: number;\n}\n\nexport class KeyRedactor {\n private static readonly API_KEY_PATTERNS = [\n // Anthropic API keys\n /sk-ant-[a-zA-Z0-9_-]{95,}/gi,\n\n // OpenRouter API keys\n /sk-or-[a-zA-Z0-9_-]{32,}/gi,\n\n // Google/Gemini API keys\n /AIza[a-zA-Z0-9_-]{35}/gi,\n\n // Generic API keys\n /[a-zA-Z0-9_-]{20,}API[a-zA-Z0-9_-]{20,}/gi,\n\n // Bearer tokens\n /Bearer\\s+[a-zA-Z0-9_\\-\\.]{20,}/gi,\n\n // Environment variable format\n /([A-Z_]+_API_KEY|[A-Z_]+_TOKEN|[A-Z_]+_SECRET)=[\"']?([^\"'\\s]+)[\"']?/gi,\n\n // Supabase keys\n /eyJ[a-zA-Z0-9_-]*\\.eyJ[a-zA-Z0-9_-]*\\.[a-zA-Z0-9_-]*/gi,\n ];\n\n private static readonly SENSITIVE_FIELDS = [\n 'apiKey',\n 'api_key',\n 'token',\n 'secret',\n 'password',\n 'private_key',\n 'privateKey',\n 'accessToken',\n 'access_token',\n 'refreshToken',\n 'refresh_token',\n ];\n\n /**\n * Redact API keys and sensitive data from text\n */\n static redact(text: string, showPrefix = true): string {\n if (!text) return text;\n\n let redacted = text;\n\n // Redact using patterns\n this.API_KEY_PATTERNS.forEach(pattern => {\n redacted = redacted.replace(pattern, (match) => {\n if (showPrefix && match.length > 8) {\n const prefix = match.substring(0, 8);\n return `${prefix}...[REDACTED]`;\n }\n return '[REDACTED_API_KEY]';\n });\n });\n\n return redacted;\n }\n\n /**\n * Redact sensitive fields in objects\n */\n static redactObject<T extends Record<string, any>>(obj: T, deep = true): T {\n if (!obj || typeof obj !== 'object') return obj;\n\n const redacted = { ...obj };\n\n Object.keys(redacted).forEach(key => {\n const lowerKey = key.toLowerCase();\n\n // Check if field name is sensitive\n const isSensitive = this.SENSITIVE_FIELDS.some(field =>\n lowerKey.includes(field)\n );\n\n if (isSensitive && typeof redacted[key] === 'string') {\n const value = redacted[key] as string;\n if (value && value.length > 8) {\n redacted[key] = `${value.substring(0, 4)}...[REDACTED]` as any;\n } else {\n redacted[key] = '[REDACTED]' as any;\n }\n } else if (deep && typeof redacted[key] === 'object' && redacted[key] !== null) {\n redacted[key] = this.redactObject(redacted[key], deep);\n } else if (typeof redacted[key] === 'string') {\n // Redact any API keys in string values\n redacted[key] = this.redact(redacted[key]) as any;\n }\n });\n\n return redacted;\n }\n\n /**\n * Sanitize text for safe logging\n */\n static sanitize(text: string): string {\n return this.redact(text, true);\n }\n\n /**\n * Sanitize command arguments\n */\n static sanitizeArgs(args: string[]): string[] {\n return args.map(arg => {\n // Check if arg is a flag value pair\n if (arg.includes('key') || arg.includes('token') || arg.includes('secret')) {\n return this.redact(arg);\n }\n return arg;\n });\n }\n\n /**\n * Check if text contains unredacted sensitive data\n */\n static containsSensitiveData(text: string): boolean {\n return this.API_KEY_PATTERNS.some(pattern => pattern.test(text));\n }\n\n /**\n * Validate that text is safe for logging/storage\n */\n static validate(text: string): { safe: boolean; warnings: string[] } {\n const warnings: string[] = [];\n\n this.API_KEY_PATTERNS.forEach((pattern, index) => {\n if (pattern.test(text)) {\n warnings.push(`Potential API key detected (pattern ${index + 1})`);\n }\n });\n\n return {\n safe: warnings.length === 0,\n warnings,\n };\n }\n\n /**\n * Redact environment variables\n */\n static redactEnv(env: Record<string, string | undefined>): Record<string, string> {\n const redacted: Record<string, string> = {};\n\n Object.keys(env).forEach(key => {\n const value = env[key];\n if (!value) {\n redacted[key] = '';\n return;\n }\n\n const lowerKey = key.toLowerCase();\n const isSensitive = lowerKey.includes('key') ||\n lowerKey.includes('token') ||\n lowerKey.includes('secret') ||\n lowerKey.includes('password');\n\n if (isSensitive) {\n redacted[key] = value.length > 8\n ? `${value.substring(0, 4)}...[REDACTED]`\n : '[REDACTED]';\n } else {\n redacted[key] = value;\n }\n });\n\n return redacted;\n }\n}\n\n// Export singleton instance\nexport const redactor = KeyRedactor;\n"],"names":["KeyRedactor","API_KEY_PATTERNS","SENSITIVE_FIELDS","redact","text","showPrefix","redacted","forEach","pattern","replace","match","length","prefix","substring","redactObject","obj","deep","Object","keys","key","lowerKey","toLowerCase","isSensitive","some","field","includes","value","sanitize","sanitizeArgs","args","map","arg","containsSensitiveData","test","validate","warnings","index","push","safe","redactEnv","env","redactor"],"mappings":"AAWA,OAAO,MAAMA;IACX,OAAwBC,mBAAmB;QAEzC;QAGA;QAGA;QAGA;QAGA;QAGA;QAGA;KACD,CAAC;IAEF,OAAwBC,mBAAmB;QACzC;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;KACD,CAAC;IAKF,OAAOC,OAAOC,IAAY,EAAEC,aAAa,IAAI,EAAU;QACrD,IAAI,CAACD,MAAM,OAAOA;QAElB,IAAIE,WAAWF;QAGf,IAAI,CAACH,gBAAgB,CAACM,OAAO,CAACC,CAAAA;YAC5BF,WAAWA,SAASG,OAAO,CAACD,SAAS,CAACE;gBACpC,IAAIL,cAAcK,MAAMC,MAAM,GAAG,GAAG;oBAClC,MAAMC,SAASF,MAAMG,SAAS,CAAC,GAAG;oBAClC,OAAO,GAAGD,OAAO,aAAa,CAAC;gBACjC;gBACA,OAAO;YACT;QACF;QAEA,OAAON;IACT;IAKA,OAAOQ,aAA4CC,GAAM,EAAEC,OAAO,IAAI,EAAK;QACzE,IAAI,CAACD,OAAO,OAAOA,QAAQ,UAAU,OAAOA;QAE5C,MAAMT,WAAW;YAAE,GAAGS,GAAG;QAAC;QAE1BE,OAAOC,IAAI,CAACZ,UAAUC,OAAO,CAACY,CAAAA;YAC5B,MAAMC,WAAWD,IAAIE,WAAW;YAGhC,MAAMC,cAAc,IAAI,CAACpB,gBAAgB,CAACqB,IAAI,CAACC,CAAAA,QAC7CJ,SAASK,QAAQ,CAACD;YAGpB,IAAIF,eAAe,OAAOhB,QAAQ,CAACa,IAAI,KAAK,UAAU;gBACpD,MAAMO,QAAQpB,QAAQ,CAACa,IAAI;gBAC3B,IAAIO,SAASA,MAAMf,MAAM,GAAG,GAAG;oBAC7BL,QAAQ,CAACa,IAAI,GAAG,GAAGO,MAAMb,SAAS,CAAC,GAAG,GAAG,aAAa,CAAC;gBACzD,OAAO;oBACLP,QAAQ,CAACa,IAAI,GAAG;gBAClB;YACF,OAAO,IAAIH,QAAQ,OAAOV,QAAQ,CAACa,IAAI,KAAK,YAAYb,QAAQ,CAACa,IAAI,KAAK,MAAM;gBAC9Eb,QAAQ,CAACa,IAAI,GAAG,IAAI,CAACL,YAAY,CAACR,QAAQ,CAACa,IAAI,EAAEH;YACnD,OAAO,IAAI,OAAOV,QAAQ,CAACa,IAAI,KAAK,UAAU;gBAE5Cb,QAAQ,CAACa,IAAI,GAAG,IAAI,CAAChB,MAAM,CAACG,QAAQ,CAACa,IAAI;YAC3C;QACF;QAEA,OAAOb;IACT;IAKA,OAAOqB,SAASvB,IAAY,EAAU;QACpC,OAAO,IAAI,CAACD,MAAM,CAACC,MAAM;IAC3B;IAKA,OAAOwB,aAAaC,IAAc,EAAY;QAC5C,OAAOA,KAAKC,GAAG,CAACC,CAAAA;YAEd,IAAIA,IAAIN,QAAQ,CAAC,UAAUM,IAAIN,QAAQ,CAAC,YAAYM,IAAIN,QAAQ,CAAC,WAAW;gBAC1E,OAAO,IAAI,CAACtB,MAAM,CAAC4B;YACrB;YACA,OAAOA;QACT;IACF;IAKA,OAAOC,sBAAsB5B,IAAY,EAAW;QAClD,OAAO,IAAI,CAACH,gBAAgB,CAACsB,IAAI,CAACf,CAAAA,UAAWA,QAAQyB,IAAI,CAAC7B;IAC5D;IAKA,OAAO8B,SAAS9B,IAAY,EAAyC;QACnE,MAAM+B,WAAqB,EAAE;QAE7B,IAAI,CAAClC,gBAAgB,CAACM,OAAO,CAAC,CAACC,SAAS4B;YACtC,IAAI5B,QAAQyB,IAAI,CAAC7B,OAAO;gBACtB+B,SAASE,IAAI,CAAC,CAAC,oCAAoC,EAAED,QAAQ,EAAE,CAAC,CAAC;YACnE;QACF;QAEA,OAAO;YACLE,MAAMH,SAASxB,MAAM,KAAK;YAC1BwB;QACF;IACF;IAKA,OAAOI,UAAUC,GAAuC,EAA0B;QAChF,MAAMlC,WAAmC,CAAC;QAE1CW,OAAOC,IAAI,CAACsB,KAAKjC,OAAO,CAACY,CAAAA;YACvB,MAAMO,QAAQc,GAAG,CAACrB,IAAI;YACtB,IAAI,CAACO,OAAO;gBACVpB,QAAQ,CAACa,IAAI,GAAG;gBAChB;YACF;YAEA,MAAMC,WAAWD,IAAIE,WAAW;YAChC,MAAMC,cAAcF,SAASK,QAAQ,CAAC,UACnBL,SAASK,QAAQ,CAAC,YAClBL,SAASK,QAAQ,CAAC,aAClBL,SAASK,QAAQ,CAAC;YAErC,IAAIH,aAAa;gBACfhB,QAAQ,CAACa,IAAI,GAAGO,MAAMf,MAAM,GAAG,IAC3B,GAAGe,MAAMb,SAAS,CAAC,GAAG,GAAG,aAAa,CAAC,GACvC;YACN,OAAO;gBACLP,QAAQ,CAACa,IAAI,GAAGO;YAClB;QACF;QAEA,OAAOpB;IACT;AACF;AAGA,OAAO,MAAMmC,WAAWzC,YAAY"}
@@ -0,0 +1,192 @@
1
+ # Agent Folder Structure Fix
2
+
3
+ ## Issue
4
+
5
+ The `.claude/agents` folder was being generated with unnecessary nested subdirectories (e.g., `.claude/agents/analysis/code-review/`, `.claude/agents/architecture/system-design/`), creating too many hierarchy levels.
6
+
7
+ ## Required Structure
8
+
9
+ All agent `.md` files should be directly in their category folders:
10
+ - ✅ `.claude/agents/analysis/code-analyzer.md`
11
+ - ✅ `.claude/agents/architecture/arch-system-design.md`
12
+ - ✅ `.claude/agents/development/dev-backend-api.md`
13
+ - ❌ ~~`.claude/agents/analysis/code-review/analyze-code-quality.md`~~ (too nested)
14
+
15
+ ## Fix Applied
16
+
17
+ **File**: `src/cli/simple-commands/init/agent-copier.js`
18
+
19
+ **Function**: `createAgentDirectories()` (lines 137-164)
20
+
21
+ ### Changes Made
22
+
23
+ Removed nested subdirectories from the `agentDirs` array:
24
+
25
+ ```diff
26
+ const agentDirs = [
27
+ '.claude',
28
+ '.claude/agents',
29
+ '.claude/agents/core',
30
+ '.claude/agents/swarm',
31
+ '.claude/agents/hive-mind',
32
+ '.claude/agents/consensus',
33
+ '.claude/agents/optimization',
34
+ '.claude/agents/github',
35
+ '.claude/agents/sparc',
36
+ '.claude/agents/testing',
37
+ - '.claude/agents/testing/unit',
38
+ - '.claude/agents/testing/validation',
39
+ '.claude/agents/templates',
40
+ '.claude/agents/analysis',
41
+ - '.claude/agents/analysis/code-review',
42
+ '.claude/agents/architecture',
43
+ - '.claude/agents/architecture/system-design',
44
+ '.claude/agents/data',
45
+ - '.claude/agents/data/ml',
46
+ '.claude/agents/development',
47
+ - '.claude/agents/development/backend',
48
+ '.claude/agents/devops',
49
+ - '.claude/agents/devops/ci-cd',
50
+ '.claude/agents/documentation',
51
+ - '.claude/agents/documentation/api-docs',
52
+ '.claude/agents/specialized',
53
+ - '.claude/agents/specialized/mobile',
54
+ '.claude/agents/flow-nexus',
55
+ + '.claude/agents/goal',
56
+ + '.claude/agents/neural',
57
+ + '.claude/agents/reasoning',
58
+ '.claude/commands',
59
+ '.claude/commands/flow-nexus'
60
+ ];
61
+ ```
62
+
63
+ ### Changes Summary
64
+
65
+ **Removed** (11 nested directories):
66
+ - `.claude/agents/testing/unit`
67
+ - `.claude/agents/testing/validation`
68
+ - `.claude/agents/analysis/code-review`
69
+ - `.claude/agents/architecture/system-design`
70
+ - `.claude/agents/data/ml`
71
+ - `.claude/agents/development/backend`
72
+ - `.claude/agents/devops/ci-cd`
73
+ - `.claude/agents/documentation/api-docs`
74
+ - `.claude/agents/specialized/mobile`
75
+
76
+ **Added** (3 missing categories):
77
+ - `.claude/agents/goal`
78
+ - `.claude/agents/neural`
79
+ - `.claude/agents/reasoning`
80
+
81
+ **Total directories**: Reduced from 30 to 24 (flat structure)
82
+
83
+ ## Test Results
84
+
85
+ ### Test Execution
86
+
87
+ ```bash
88
+ $ node -e "import { createAgentDirectories, copyAgentFiles } from './dist/src/cli/simple-commands/init/agent-copier.js';
89
+ async function test() {
90
+ const targetDir = 'tests/agent-structure-test';
91
+ await createAgentDirectories(targetDir, false);
92
+ await copyAgentFiles(targetDir, { force: true });
93
+ }
94
+ test().catch(console.error);"
95
+ ```
96
+
97
+ ### Verification
98
+
99
+ ```bash
100
+ # Count nested directories (should be 0)
101
+ $ find tests/agent-structure-test/.claude/agents -type d -mindepth 2 | wc -l
102
+ 0
103
+
104
+ # Verify files copied correctly
105
+ $ find tests/agent-structure-test/.claude/agents -type f -name "*.md" | wc -l
106
+ 76
107
+
108
+ # Check category structure
109
+ $ find tests/agent-structure-test/.claude/agents -type d | wc -l
110
+ 22 # 1 base + 21 categories = 22 total
111
+ ```
112
+
113
+ ### Verified Folder Contents
114
+
115
+ ✅ **Analysis** (flat):
116
+ - `analyze-code-quality.md`
117
+ - `code-analyzer.md`
118
+
119
+ ✅ **Architecture** (flat):
120
+ - `arch-system-design.md`
121
+
122
+ ✅ **Development** (flat):
123
+ - `dev-backend-api.md`
124
+
125
+ ✅ **Testing** (flat):
126
+ - `production-validator.md`
127
+ - `tdd-london-swarm.md`
128
+
129
+ ## Impact
130
+
131
+ ### Before Fix ❌
132
+ ```
133
+ .claude/agents/
134
+ ├── analysis/
135
+ │ ├── code-review/ # ❌ Unnecessary nesting
136
+ │ │ └── analyze-code-quality.md
137
+ │ └── code-analyzer.md
138
+ ├── architecture/
139
+ │ ├── system-design/ # ❌ Unnecessary nesting
140
+ │ │ └── arch-system-design.md
141
+ └── development/
142
+ └── backend/ # ❌ Unnecessary nesting
143
+ └── dev-backend-api.md
144
+ ```
145
+
146
+ ### After Fix ✅
147
+ ```
148
+ .claude/agents/
149
+ ├── analysis/
150
+ │ ├── analyze-code-quality.md # ✅ Flat structure
151
+ │ └── code-analyzer.md # ✅ Flat structure
152
+ ├── architecture/
153
+ │ └── arch-system-design.md # ✅ Flat structure
154
+ └── development/
155
+ └── dev-backend-api.md # ✅ Flat structure
156
+ ```
157
+
158
+ ## Benefits
159
+
160
+ 1. **Simpler Structure**: Reduced nesting depth from 3-4 levels to 2 levels
161
+ 2. **Easier Navigation**: All agents in a category are immediately visible
162
+ 3. **Consistent Naming**: Agent files can be found at predictable paths
163
+ 4. **Better Organization**: Clear separation between categories without over-structuring
164
+ 5. **Maintenance**: Easier to add/remove agents without managing subdirectories
165
+
166
+ ## Backward Compatibility
167
+
168
+ ✅ **No Breaking Changes**
169
+ - The `copyRecursive()` function preserves the existing source structure
170
+ - Agent files are copied exactly as they exist in source
171
+ - Only the directory creation is affected
172
+ - Users with existing `.claude/agents` folders are unaffected
173
+
174
+ ## Files Modified
175
+
176
+ - `src/cli/simple-commands/init/agent-copier.js` (lines 137-164)
177
+
178
+ ## Testing
179
+
180
+ **Test Directory**: `tests/agent-structure-test/`
181
+
182
+ **Status**: ✅ All tests passed
183
+ - 0 nested subdirectories created
184
+ - 76 agent files copied successfully
185
+ - 21 category folders created
186
+ - All files in correct flat structure
187
+
188
+ ---
189
+
190
+ **Status**: ✅ **FIXED AND VERIFIED**
191
+
192
+ **Ready for**: Next release (v2.7.33 or patch)
@@ -0,0 +1,355 @@
1
+ # Bug Report: `memory stats` Command Returns Zero for ReasoningBank Data
2
+
3
+ ## Executive Summary
4
+
5
+ The `memory stats` command always returns zero entries/namespaces/size, even when ReasoningBank contains data. This is caused by the command exclusively reading from the legacy JSON file (`./memory/memory-store.json`) instead of querying the active ReasoningBank SQLite database.
6
+
7
+ ## Bug Details
8
+
9
+ ### Issue
10
+ - **Command**: `npx claude-flow@alpha memory stats`
11
+ - **Expected**: Shows statistics for ReasoningBank database (19 entries found via direct SQL query)
12
+ - **Actual**: Returns all zeros (0 entries, 0 namespaces, 0.00 KB)
13
+ - **Severity**: High - Users cannot see their stored data statistics
14
+ - **Affected Versions**: v2.7.30 and likely earlier
15
+
16
+ ### Evidence
17
+
18
+ ```bash
19
+ # Command returns zeros
20
+ $ npx claude-flow@alpha memory stats
21
+ ✅ Memory Bank Statistics:
22
+ Total Entries: 0
23
+ Namespaces: 0
24
+ Size: 0.00 KB
25
+
26
+ # But ReasoningBank list shows 10+ entries
27
+ $ npx claude-flow@alpha memory list --reasoningbank
28
+ ✅ ReasoningBank memories (10 shown):
29
+ 📌 test-key
30
+ 📌 test-sqlite
31
+ 📌 api-design
32
+ [... 16 more entries]
33
+
34
+ # Direct SQL query confirms 19 entries exist
35
+ $ sqlite3 .swarm/memory.db "SELECT COUNT(*) FROM patterns WHERE type = 'reasoning_memory';"
36
+ 19
37
+
38
+ # ReasoningBank status confirms data exists
39
+ $ npx claude-flow@alpha memory status --reasoningbank
40
+ ✅ 📊 ReasoningBank Status:
41
+ Total memories: 19
42
+ Average confidence: 80.0%
43
+ Embeddings: 19
44
+ Trajectories: 0
45
+ ```
46
+
47
+ ## Root Cause Analysis
48
+
49
+ ### Code Analysis (src/cli/simple-commands/memory.js)
50
+
51
+ **Problem Location**: Lines 217-244
52
+
53
+ ```javascript
54
+ async function showMemoryStats(loadMemory) {
55
+ try {
56
+ const data = await loadMemory(); // ❌ Only reads JSON file
57
+ let totalEntries = 0;
58
+ const namespaceStats = {};
59
+
60
+ for (const [namespace, entries] of Object.entries(data)) {
61
+ namespaceStats[namespace] = entries.length;
62
+ totalEntries += entries.length;
63
+ }
64
+
65
+ printSuccess('Memory Bank Statistics:');
66
+ console.log(` Total Entries: ${totalEntries}`);
67
+ console.log(` Namespaces: ${Object.keys(data).length}`);
68
+ console.log(` Size: ${(new TextEncoder().encode(JSON.stringify(data)).length / 1024).toFixed(2)} KB`);
69
+ // ...
70
+ }
71
+ }
72
+ ```
73
+
74
+ **The `loadMemory()` function** (line 26-33):
75
+ ```javascript
76
+ async function loadMemory() {
77
+ try {
78
+ const content = await fs.readFile(memoryStore, 'utf8'); // hardcoded JSON path
79
+ return JSON.parse(content);
80
+ } catch {
81
+ return {};
82
+ }
83
+ }
84
+ ```
85
+
86
+ Where `memoryStore = './memory/memory-store.json'` (line 14)
87
+
88
+ ### Why It's Broken
89
+
90
+ 1. **Hardcoded JSON File**: `showMemoryStats()` only reads from `./memory/memory-store.json`
91
+ 2. **No Mode Detection**: Unlike other commands (`store`, `query`, `list`), `stats` doesn't call `detectMemoryMode()` (line 23)
92
+ 3. **No ReasoningBank Support**: The switch statement (lines 56-87) routes `stats` directly to `showMemoryStats()` without checking if ReasoningBank is active
93
+ 4. **Inconsistent with Other Commands**: `store`, `query`, and `list` all support `--reasoningbank` flag via `handleReasoningBankCommand()`, but `stats` doesn't
94
+
95
+ ### Working Commands for Comparison
96
+
97
+ ```javascript
98
+ // ✅ These commands properly detect mode and support ReasoningBank
99
+ case 'store':
100
+ await storeMemory(subArgs, loadMemory, saveMemory, namespace, enableRedaction);
101
+ break;
102
+
103
+ case 'query':
104
+ await queryMemory(subArgs, loadMemory, namespace, enableRedaction);
105
+ break;
106
+
107
+ case 'list':
108
+ await listNamespaces(loadMemory);
109
+ break;
110
+
111
+ // ❌ This command ignores mode detection
112
+ case 'stats':
113
+ await showMemoryStats(loadMemory); // Never checks ReasoningBank!
114
+ break;
115
+ ```
116
+
117
+ ## Expected Behavior
118
+
119
+ The `memory stats` command should:
120
+
121
+ 1. **Detect the active memory mode** (basic JSON vs ReasoningBank SQLite)
122
+ 2. **Show appropriate statistics** based on the active mode:
123
+ - **ReasoningBank mode**: Query SQLite database for accurate counts
124
+ - **Basic mode**: Read JSON file (current behavior)
125
+ - **Auto mode**: Check both and show combined statistics
126
+ 3. **Support `--reasoningbank` flag** to force ReasoningBank stats
127
+ 4. **Display backend information**: Show which storage backend is being used
128
+
129
+ ### Proposed Output
130
+
131
+ ```bash
132
+ # Auto mode (should detect ReasoningBank if initialized)
133
+ $ npx claude-flow@alpha memory stats
134
+ ✅ Memory Bank Statistics:
135
+ Storage Backend: ReasoningBank (SQLite)
136
+ Total Entries: 19
137
+ Namespaces: 3
138
+ Size: 9.14 MB
139
+
140
+ 📁 Namespace Breakdown:
141
+ default: 12 entries
142
+ test-namespace: 5 entries
143
+ api: 2 entries
144
+
145
+ 💡 Use 'memory stats --basic' for JSON statistics
146
+
147
+ # Force ReasoningBank mode
148
+ $ npx claude-flow@alpha memory stats --reasoningbank
149
+ ✅ ReasoningBank Statistics:
150
+ Database: .swarm/memory.db
151
+ Total Memories: 19
152
+ Total Embeddings: 19
153
+ Average Confidence: 80.0%
154
+ Trajectories: 0
155
+ Links: 0
156
+ Database Size: 9.14 MB
157
+
158
+ # Force basic mode
159
+ $ npx claude-flow@alpha memory stats --basic
160
+ ✅ JSON Memory Statistics:
161
+ Total Entries: 0
162
+ Namespaces: 0
163
+ Size: 0.00 KB
164
+ ⚠️ Consider migrating to ReasoningBank for better performance
165
+ ```
166
+
167
+ ## Proposed Solution
168
+
169
+ ### Option 1: Add ReasoningBank Support to stats (Recommended)
170
+
171
+ Modify `src/cli/simple-commands/memory.js`:
172
+
173
+ ```javascript
174
+ // Line 65-67: Add mode detection to stats case
175
+ case 'stats':
176
+ if (mode === 'reasoningbank') {
177
+ await handleReasoningBankStats(getStatus);
178
+ } else {
179
+ await showMemoryStats(loadMemory);
180
+ }
181
+ break;
182
+
183
+ // Add new handler function (around line 718)
184
+ async function handleReasoningBankStats(getStatus) {
185
+ try {
186
+ const stats = await getStatus();
187
+
188
+ printSuccess('ReasoningBank Statistics:');
189
+ console.log(` Database: ${stats.database_path || '.swarm/memory.db'}`);
190
+ console.log(` Total Memories: ${stats.total_memories}`);
191
+ console.log(` Total Categories: ${stats.total_categories}`);
192
+ console.log(` Average Confidence: ${(stats.avg_confidence * 100).toFixed(1)}%`);
193
+ console.log(` Embeddings: ${stats.total_embeddings}`);
194
+ console.log(` Trajectories: ${stats.total_trajectories}`);
195
+ console.log(` Links: ${stats.total_links || 0}`);
196
+ console.log(` Storage Backend: ${stats.storage_backend}`);
197
+
198
+ if (stats.database_path) {
199
+ const dbSize = await getFileSize(stats.database_path);
200
+ console.log(` Database Size: ${(dbSize / 1024 / 1024).toFixed(2)} MB`);
201
+ }
202
+ } catch (error) {
203
+ printError(`Failed to get ReasoningBank stats: ${error.message}`);
204
+ }
205
+ }
206
+
207
+ // Helper function
208
+ async function getFileSize(path) {
209
+ try {
210
+ const stats = await fs.stat(path);
211
+ return stats.size;
212
+ } catch {
213
+ return 0;
214
+ }
215
+ }
216
+ ```
217
+
218
+ ### Option 2: Create Unified Stats Command
219
+
220
+ Show both JSON and ReasoningBank statistics in one output:
221
+
222
+ ```javascript
223
+ async function showMemoryStats(loadMemory, mode) {
224
+ const rbInitialized = await isReasoningBankInitialized();
225
+
226
+ printSuccess('Memory Bank Statistics:\n');
227
+
228
+ // Show JSON stats
229
+ const jsonData = await loadMemory();
230
+ let totalEntries = Object.values(jsonData).reduce((sum, arr) => sum + arr.length, 0);
231
+
232
+ console.log('📁 JSON Storage (./memory/memory-store.json):');
233
+ console.log(` Total Entries: ${totalEntries}`);
234
+ console.log(` Namespaces: ${Object.keys(jsonData).length}`);
235
+ console.log(` Size: ${(new TextEncoder().encode(JSON.stringify(jsonData)).length / 1024).toFixed(2)} KB`);
236
+
237
+ // Show ReasoningBank stats if initialized
238
+ if (rbInitialized) {
239
+ const { getStatus } = await import('../../reasoningbank/reasoningbank-adapter.js');
240
+ const rbStats = await getStatus();
241
+
242
+ console.log('\n🧠 ReasoningBank Storage (.swarm/memory.db):');
243
+ console.log(` Total Memories: ${rbStats.total_memories}`);
244
+ console.log(` Categories: ${rbStats.total_categories}`);
245
+ console.log(` Average Confidence: ${(rbStats.avg_confidence * 100).toFixed(1)}%`);
246
+ console.log(` Embeddings: ${rbStats.total_embeddings}`);
247
+
248
+ console.log('\n💡 Active Mode: ReasoningBank (auto-selected)');
249
+ } else {
250
+ console.log('\n⚠️ ReasoningBank not initialized (using JSON storage)');
251
+ console.log(' Run "memory init --reasoningbank" to enable AI features');
252
+ }
253
+ }
254
+ ```
255
+
256
+ ## Testing Plan
257
+
258
+ ### Test Cases
259
+
260
+ 1. **Test with empty JSON, empty ReasoningBank**
261
+ ```bash
262
+ rm -rf memory/ .swarm/
263
+ npx claude-flow@alpha memory stats
264
+ # Expected: Show zeros for both backends
265
+ ```
266
+
267
+ 2. **Test with data in ReasoningBank only**
268
+ ```bash
269
+ npx claude-flow@alpha memory store "test" "value" --reasoningbank
270
+ npx claude-flow@alpha memory stats
271
+ # Expected: Show ReasoningBank stats with 1 entry
272
+ ```
273
+
274
+ 3. **Test with data in JSON only**
275
+ ```bash
276
+ npx claude-flow@alpha memory store "test" "value" --basic
277
+ npx claude-flow@alpha memory stats
278
+ # Expected: Show JSON stats with 1 entry
279
+ ```
280
+
281
+ 4. **Test with data in both backends**
282
+ ```bash
283
+ npx claude-flow@alpha memory store "json-key" "json-value" --basic
284
+ npx claude-flow@alpha memory store "rb-key" "rb-value" --reasoningbank
285
+ npx claude-flow@alpha memory stats
286
+ # Expected: Show stats for both backends
287
+ ```
288
+
289
+ 5. **Test with flags**
290
+ ```bash
291
+ npx claude-flow@alpha memory stats --reasoningbank
292
+ npx claude-flow@alpha memory stats --basic
293
+ npx claude-flow@alpha memory stats --auto
294
+ # Expected: Respect mode flags
295
+ ```
296
+
297
+ ## Impact Assessment
298
+
299
+ ### User Impact: High
300
+ - Users relying on `memory stats` are seeing incorrect information
301
+ - New users testing ReasoningBank features think it's not working
302
+ - Migration from JSON to ReasoningBank appears unsuccessful
303
+
304
+ ### Workarounds
305
+ Users can check ReasoningBank data using:
306
+ 1. `memory status --reasoningbank` - Shows basic stats
307
+ 2. `memory list --reasoningbank` - Lists all entries
308
+ 3. Direct SQLite query: `sqlite3 .swarm/memory.db "SELECT COUNT(*) FROM patterns;"`
309
+
310
+ ## Related Issues
311
+
312
+ - Memory mode detection works correctly for `store`, `query`, `list` commands
313
+ - The `status --reasoningbank` command works and shows accurate statistics
314
+ - This bug affects only the `stats` command (without flags)
315
+
316
+ ## Files to Modify
317
+
318
+ 1. **src/cli/simple-commands/memory.js**
319
+ - Lines 65-67: Add mode detection to `stats` case
320
+ - Lines 217-244: Modify `showMemoryStats()` to support ReasoningBank
321
+ - Add new `handleReasoningBankStats()` function (around line 718)
322
+
323
+ ## Backward Compatibility
324
+
325
+ ✅ No breaking changes - existing JSON-based stats will continue to work
326
+ ✅ New flag `--reasoningbank` is optional
327
+ ✅ Auto mode will fall back to JSON if ReasoningBank not initialized
328
+
329
+ ## Priority Recommendation
330
+
331
+ **Priority: High** - This is a user-facing bug that makes a primary feature (statistics) non-functional for ReasoningBank users.
332
+
333
+ **Suggested for**: v2.7.31 hotfix
334
+
335
+ ---
336
+
337
+ ## Additional Context
338
+
339
+ ### System Information
340
+ - Version: v2.7.30 (and likely earlier)
341
+ - Database: SQLite 3.x at `.swarm/memory.db`
342
+ - ReasoningBank: Initialized and contains 19 entries
343
+ - JSON Storage: Empty (0 entries)
344
+
345
+ ### Reproduction Steps
346
+ 1. Initialize ReasoningBank: `npx claude-flow@alpha memory init --reasoningbank`
347
+ 2. Store data: `npx claude-flow@alpha memory store test-key "test value" --reasoningbank`
348
+ 3. Verify storage: `npx claude-flow@alpha memory list --reasoningbank` (shows data)
349
+ 4. Run stats: `npx claude-flow@alpha memory stats` (shows zeros ❌)
350
+
351
+ ### Related Files
352
+ - `/workspaces/claude-code-flow/src/cli/simple-commands/memory.js` (main bug location)
353
+ - `/workspaces/claude-code-flow/src/reasoningbank/reasoningbank-adapter.js` (working `getStatus()` function)
354
+ - `.swarm/memory.db` (SQLite database with 19 entries)
355
+ - `./memory/memory-store.json` (empty JSON file)