create-byan-agent 2.0.1 → 2.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (240) hide show
  1. package/API-BYAN-V2.md +741 -0
  2. package/BMAD-QUICK-REFERENCE.md +370 -0
  3. package/CHANGELOG-v2.1.0.md +371 -0
  4. package/LICENSE +1 -1
  5. package/MIGRATION-v2.0-to-v2.1.md +430 -0
  6. package/README-BYAN-V2.md +446 -0
  7. package/README.md +264 -201
  8. package/install/.eslintrc.js +20 -0
  9. package/install/.prettierrc +7 -0
  10. package/install/BUGFIX-CHALK.md +173 -0
  11. package/install/BUGFIX-DOCUMENTATION-INDEX.md +299 -0
  12. package/install/BUGFIX-PATH-RESOLUTION.md +293 -0
  13. package/install/BUGFIX-QUICKSTART.md +184 -0
  14. package/install/BUGFIX-SUMMARY.txt +91 -0
  15. package/install/BUGFIX-VISUAL-SUMMARY.md +253 -0
  16. package/install/DEPLOYMENT-GUIDE-V2.md +431 -0
  17. package/install/DOCS-INDEX.md +261 -0
  18. package/install/GUIDE-INSTALLATION-BYAN-SIMPLE.md +1083 -0
  19. package/install/INSTALLER-V2-CHANGES.md +472 -0
  20. package/install/LICENSE +21 -0
  21. package/install/PUBLICATION-CHECKLIST.md +265 -0
  22. package/install/PUBLISH-GUIDE.md +190 -0
  23. package/install/QUICKSTART.md +311 -0
  24. package/install/README-NPM-PUBLISH.md +298 -0
  25. package/install/README-NPM-SHORT.md +298 -0
  26. package/install/README-NPM.md +433 -0
  27. package/install/README-RACHID.md +302 -0
  28. package/install/README-V2-INDEX.md +306 -0
  29. package/install/README.md +298 -0
  30. package/install/RESUME-EXECUTIF-YAN.md +408 -0
  31. package/install/UPDATE-SUMMARY.md +205 -0
  32. package/install/__tests__/integration/detection-flow.test.js +154 -0
  33. package/install/__tests__/platforms/claude-code.test.js +175 -0
  34. package/install/__tests__/platforms/codex.test.js +80 -0
  35. package/install/__tests__/platforms/copilot-cli.test.js +118 -0
  36. package/install/__tests__/platforms/vscode.test.js +67 -0
  37. package/install/__tests__/utils/file-utils.test.js +87 -0
  38. package/install/__tests__/utils/git-detector.test.js +80 -0
  39. package/install/__tests__/utils/logger.test.js +83 -0
  40. package/install/__tests__/utils/node-detector.test.js +71 -0
  41. package/install/__tests__/utils/os-detector.test.js +63 -0
  42. package/install/__tests__/utils/yaml-utils.test.js +85 -0
  43. package/install/__tests__/yanstaller/detector.test.js +210 -0
  44. package/install/coverage/clover.xml +219 -0
  45. package/install/coverage/coverage-final.json +13 -0
  46. package/install/coverage/lcov-report/base.css +224 -0
  47. package/install/coverage/lcov-report/block-navigation.js +87 -0
  48. package/install/coverage/lcov-report/favicon.png +0 -0
  49. package/install/coverage/lcov-report/index.html +146 -0
  50. package/install/coverage/lcov-report/lib/errors.js.html +268 -0
  51. package/install/coverage/lcov-report/lib/exit-codes.js.html +247 -0
  52. package/install/coverage/lcov-report/lib/index.html +131 -0
  53. package/install/coverage/lcov-report/lib/platforms/claude-code.js.html +343 -0
  54. package/install/coverage/lcov-report/lib/platforms/codex.js.html +361 -0
  55. package/install/coverage/lcov-report/lib/platforms/copilot-cli.js.html +454 -0
  56. package/install/coverage/lcov-report/lib/platforms/index.html +176 -0
  57. package/install/coverage/lcov-report/lib/platforms/index.js.html +127 -0
  58. package/install/coverage/lcov-report/lib/platforms/vscode.js.html +238 -0
  59. package/install/coverage/lcov-report/lib/utils/config-loader.js.html +322 -0
  60. package/install/coverage/lcov-report/lib/utils/file-utils.js.html +397 -0
  61. package/install/coverage/lcov-report/lib/utils/git-detector.js.html +190 -0
  62. package/install/coverage/lcov-report/lib/utils/index.html +206 -0
  63. package/install/coverage/lcov-report/lib/utils/logger.js.html +277 -0
  64. package/install/coverage/lcov-report/lib/utils/node-detector.js.html +259 -0
  65. package/install/coverage/lcov-report/lib/utils/os-detector.js.html +307 -0
  66. package/install/coverage/lcov-report/lib/utils/yaml-utils.js.html +346 -0
  67. package/install/coverage/lcov-report/lib/yanstaller/backuper.js.html +409 -0
  68. package/install/coverage/lcov-report/lib/yanstaller/detector.js.html +508 -0
  69. package/install/coverage/lcov-report/lib/yanstaller/index.html +236 -0
  70. package/install/coverage/lcov-report/lib/yanstaller/index.js.html +364 -0
  71. package/install/coverage/lcov-report/lib/yanstaller/installer.js.html +505 -0
  72. package/install/coverage/lcov-report/lib/yanstaller/interviewer.js.html +349 -0
  73. package/install/coverage/lcov-report/lib/yanstaller/recommender.js.html +379 -0
  74. package/install/coverage/lcov-report/lib/yanstaller/troubleshooter.js.html +352 -0
  75. package/install/coverage/lcov-report/lib/yanstaller/validator.js.html +679 -0
  76. package/install/coverage/lcov-report/lib/yanstaller/wizard.js.html +412 -0
  77. package/install/coverage/lcov-report/platforms/claude-code.js.html +343 -0
  78. package/install/coverage/lcov-report/platforms/codex.js.html +361 -0
  79. package/install/coverage/lcov-report/platforms/copilot-cli.js.html +454 -0
  80. package/install/coverage/lcov-report/platforms/index.html +176 -0
  81. package/install/coverage/lcov-report/platforms/index.js.html +127 -0
  82. package/install/coverage/lcov-report/platforms/vscode.js.html +238 -0
  83. package/install/coverage/lcov-report/prettify.css +1 -0
  84. package/install/coverage/lcov-report/prettify.js +2 -0
  85. package/install/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  86. package/install/coverage/lcov-report/sorter.js +210 -0
  87. package/install/coverage/lcov-report/utils/file-utils.js.html +397 -0
  88. package/install/coverage/lcov-report/utils/git-detector.js.html +190 -0
  89. package/install/coverage/lcov-report/utils/index.html +191 -0
  90. package/install/coverage/lcov-report/utils/logger.js.html +277 -0
  91. package/install/coverage/lcov-report/utils/node-detector.js.html +259 -0
  92. package/install/coverage/lcov-report/utils/os-detector.js.html +307 -0
  93. package/install/coverage/lcov-report/utils/yaml-utils.js.html +346 -0
  94. package/install/coverage/lcov-report/yanstaller/detector.js.html +508 -0
  95. package/install/coverage/lcov-report/yanstaller/index.html +116 -0
  96. package/install/coverage/lcov.info +414 -0
  97. package/install/install.sh +239 -0
  98. package/install/jest.config.js +33 -0
  99. package/install/lib/errors.js +61 -0
  100. package/install/lib/exit-codes.js +54 -0
  101. package/install/lib/platforms/claude-code.js +86 -0
  102. package/install/lib/platforms/codex.js +92 -0
  103. package/install/lib/platforms/copilot-cli.js +123 -0
  104. package/install/lib/platforms/index.js +14 -0
  105. package/install/lib/platforms/vscode.js +51 -0
  106. package/install/lib/utils/config-loader.js +79 -0
  107. package/install/lib/utils/file-utils.js +104 -0
  108. package/install/lib/utils/git-detector.js +35 -0
  109. package/install/lib/utils/logger.js +64 -0
  110. package/install/lib/utils/node-detector.js +58 -0
  111. package/install/lib/utils/os-detector.js +74 -0
  112. package/install/lib/utils/yaml-utils.js +87 -0
  113. package/install/lib/yanstaller/backuper.js +108 -0
  114. package/install/lib/yanstaller/detector.js +141 -0
  115. package/install/lib/yanstaller/index.js +93 -0
  116. package/install/lib/yanstaller/installer.js +140 -0
  117. package/install/lib/yanstaller/interviewer.js +88 -0
  118. package/install/lib/yanstaller/recommender.js +98 -0
  119. package/install/lib/yanstaller/troubleshooter.js +89 -0
  120. package/install/lib/yanstaller/validator.js +198 -0
  121. package/install/lib/yanstaller/wizard.js +109 -0
  122. package/install/package-npm.json +55 -0
  123. package/install/package.json +63 -0
  124. package/install/src/byan-v2/context/copilot-context.js +79 -0
  125. package/install/src/byan-v2/context/session-state.js +98 -0
  126. package/install/src/byan-v2/dispatcher/complexity-scorer.js +232 -0
  127. package/install/src/byan-v2/dispatcher/local-executor.js +221 -0
  128. package/install/src/byan-v2/dispatcher/task-router.js +122 -0
  129. package/install/src/byan-v2/dispatcher/task-tool-interface-mock.js +134 -0
  130. package/install/src/byan-v2/dispatcher/task-tool-interface.js +123 -0
  131. package/install/src/byan-v2/generation/agent-profile-validator.js +113 -0
  132. package/install/src/byan-v2/generation/profile-template.js +113 -0
  133. package/install/src/byan-v2/generation/templates/default-agent.md +49 -0
  134. package/install/src/byan-v2/generation/templates/test-template.md +1 -0
  135. package/install/src/byan-v2/index.js +199 -0
  136. package/install/src/byan-v2/observability/error-tracker.js +105 -0
  137. package/install/src/byan-v2/observability/logger.js +154 -0
  138. package/install/src/byan-v2/observability/metrics-collector.js +194 -0
  139. package/install/src/byan-v2/orchestrator/analysis-state.js +268 -0
  140. package/install/src/byan-v2/orchestrator/generation-state.js +340 -0
  141. package/install/src/byan-v2/orchestrator/interview-state.js +271 -0
  142. package/install/src/byan-v2/orchestrator/state-machine.js +204 -0
  143. package/install/src/core/cache/cache.js +126 -0
  144. package/install/src/core/context/context.js +86 -0
  145. package/install/src/core/dispatcher/dispatcher.js +135 -0
  146. package/install/src/core/worker-pool/worker-pool.js +194 -0
  147. package/install/src/core/workflow/workflow-executor.js +220 -0
  148. package/install/src/index.js +139 -0
  149. package/install/src/observability/dashboard/dashboard.js +191 -0
  150. package/install/src/observability/logger/structured-logger.js +254 -0
  151. package/install/src/observability/metrics/metrics-collector.js +325 -0
  152. package/install/switch-to-v2.sh +126 -0
  153. package/install/test-chalk-fix.sh +210 -0
  154. package/install/test-installer-v2.sh +204 -0
  155. package/install/test-path-resolution.sh +200 -0
  156. package/package.json +53 -33
  157. package/src/byan-v2/context/copilot-context.js +79 -0
  158. package/src/byan-v2/context/session-state.js +98 -0
  159. package/src/byan-v2/data/mantras.json +852 -0
  160. package/src/byan-v2/dispatcher/complexity-scorer.js +232 -0
  161. package/src/byan-v2/dispatcher/five-whys-analyzer.js +310 -0
  162. package/src/byan-v2/dispatcher/local-executor.js +221 -0
  163. package/src/byan-v2/dispatcher/task-router.js +122 -0
  164. package/src/byan-v2/dispatcher/task-tool-interface-mock.js +134 -0
  165. package/src/byan-v2/dispatcher/task-tool-interface.js +123 -0
  166. package/src/byan-v2/generation/agent-profile-validator.js +113 -0
  167. package/src/byan-v2/generation/mantra-validator.js +416 -0
  168. package/src/byan-v2/generation/profile-template.js +113 -0
  169. package/src/byan-v2/generation/templates/default-agent.md +49 -0
  170. package/src/byan-v2/generation/templates/test-template.md +1 -0
  171. package/src/byan-v2/index.js +652 -0
  172. package/src/byan-v2/integration/voice-integration.js +295 -0
  173. package/src/byan-v2/observability/error-tracker.js +105 -0
  174. package/src/byan-v2/observability/logger.js +154 -0
  175. package/src/byan-v2/observability/metrics-collector.js +194 -0
  176. package/src/byan-v2/orchestrator/active-listener.js +541 -0
  177. package/src/byan-v2/orchestrator/analysis-state.js +268 -0
  178. package/src/byan-v2/orchestrator/generation-state.js +340 -0
  179. package/src/byan-v2/orchestrator/glossary-builder.js +431 -0
  180. package/src/byan-v2/orchestrator/interview-state.js +353 -0
  181. package/src/byan-v2/orchestrator/state-machine.js +253 -0
  182. package/src/core/cache/cache.js +126 -0
  183. package/src/core/context/context.js +86 -0
  184. package/src/core/dispatcher/dispatcher.js +135 -0
  185. package/src/core/worker-pool/worker-pool.js +194 -0
  186. package/src/core/workflow/workflow-executor.js +220 -0
  187. package/src/index.js +139 -0
  188. package/src/observability/dashboard/dashboard.js +191 -0
  189. package/src/observability/logger/structured-logger.js +254 -0
  190. package/src/observability/metrics/metrics-collector.js +325 -0
  191. package/templates/.github/agents/bmad-agent-test-dynamic.md +0 -21
  192. package/templates/.github/agents/franck.md +0 -379
  193. /package/{CHANGELOG.md → install/CHANGELOG.md} +0 -0
  194. /package/{bin → install/bin}/create-byan-agent-backup.js +0 -0
  195. /package/{bin → install/bin}/create-byan-agent-fixed.js +0 -0
  196. /package/{bin → install/bin}/create-byan-agent-v2.js +0 -0
  197. /package/{bin → install/bin}/create-byan-agent.js +0 -0
  198. /package/{templates → install/templates}/.github/agents/bmad-agent-bmad-master.md +0 -0
  199. /package/{templates → install/templates}/.github/agents/bmad-agent-bmb-agent-builder.md +0 -0
  200. /package/{templates → install/templates}/.github/agents/bmad-agent-bmb-module-builder.md +0 -0
  201. /package/{templates → install/templates}/.github/agents/bmad-agent-bmb-workflow-builder.md +0 -0
  202. /package/{templates → install/templates}/.github/agents/bmad-agent-bmm-analyst.md +0 -0
  203. /package/{templates → install/templates}/.github/agents/bmad-agent-bmm-architect.md +0 -0
  204. /package/{templates → install/templates}/.github/agents/bmad-agent-bmm-dev.md +0 -0
  205. /package/{templates → install/templates}/.github/agents/bmad-agent-bmm-pm.md +0 -0
  206. /package/{templates → install/templates}/.github/agents/bmad-agent-bmm-quick-flow-solo-dev.md +0 -0
  207. /package/{templates → install/templates}/.github/agents/bmad-agent-bmm-quinn.md +0 -0
  208. /package/{templates → install/templates}/.github/agents/bmad-agent-bmm-sm.md +0 -0
  209. /package/{templates → install/templates}/.github/agents/bmad-agent-bmm-tech-writer.md +0 -0
  210. /package/{templates → install/templates}/.github/agents/bmad-agent-bmm-ux-designer.md +0 -0
  211. /package/{templates → install/templates}/.github/agents/bmad-agent-byan-test.md +0 -0
  212. /package/{templates → install/templates}/.github/agents/bmad-agent-byan.md +0 -0
  213. /package/{templates → install/templates}/.github/agents/bmad-agent-carmack.md +0 -0
  214. /package/{templates → install/templates}/.github/agents/bmad-agent-cis-brainstorming-coach.md +0 -0
  215. /package/{templates → install/templates}/.github/agents/bmad-agent-cis-creative-problem-solver.md +0 -0
  216. /package/{templates → install/templates}/.github/agents/bmad-agent-cis-design-thinking-coach.md +0 -0
  217. /package/{templates → install/templates}/.github/agents/bmad-agent-cis-innovation-strategist.md +0 -0
  218. /package/{templates → install/templates}/.github/agents/bmad-agent-cis-presentation-master.md +0 -0
  219. /package/{templates → install/templates}/.github/agents/bmad-agent-cis-storyteller.md +0 -0
  220. /package/{templates → install/templates}/.github/agents/bmad-agent-marc.md +0 -0
  221. /package/{templates → install/templates}/.github/agents/bmad-agent-patnote.md +0 -0
  222. /package/{templates → install/templates}/.github/agents/bmad-agent-rachid.md +0 -0
  223. /package/{templates → install/templates}/.github/agents/bmad-agent-tea-tea.md +0 -0
  224. /package/{templates → install/templates}/_bmad/bmb/agents/agent-builder.md +0 -0
  225. /package/{templates → install/templates}/_bmad/bmb/agents/byan-test.md +0 -0
  226. /package/{templates → install/templates}/_bmad/bmb/agents/byan.md +0 -0
  227. /package/{templates → install/templates}/_bmad/bmb/agents/marc.md +0 -0
  228. /package/{templates → install/templates}/_bmad/bmb/agents/module-builder.md +0 -0
  229. /package/{templates → install/templates}/_bmad/bmb/agents/patnote.md +0 -0
  230. /package/{templates → install/templates}/_bmad/bmb/agents/rachid.md +0 -0
  231. /package/{templates → install/templates}/_bmad/bmb/agents/workflow-builder.md +0 -0
  232. /package/{templates → install/templates}/_bmad/bmb/workflows/byan/data/mantras.yaml +0 -0
  233. /package/{templates → install/templates}/_bmad/bmb/workflows/byan/data/templates.yaml +0 -0
  234. /package/{templates → install/templates}/_bmad/bmb/workflows/byan/delete-agent-workflow.md +0 -0
  235. /package/{templates → install/templates}/_bmad/bmb/workflows/byan/edit-agent-workflow.md +0 -0
  236. /package/{templates → install/templates}/_bmad/bmb/workflows/byan/interview-workflow.md +0 -0
  237. /package/{templates → install/templates}/_bmad/bmb/workflows/byan/quick-create-workflow.md +0 -0
  238. /package/{templates → install/templates}/_bmad/bmb/workflows/byan/templates/base-agent-template.md +0 -0
  239. /package/{templates → install/templates}/_bmad/bmb/workflows/byan/validate-agent-workflow.md +0 -0
  240. /package/{templates → install/templates}/_bmad/core/agents/carmack.md +0 -0
@@ -0,0 +1,232 @@
1
+ /**
2
+ * ComplexityScorer - Calculate task complexity score (0-100)
3
+ *
4
+ * Scoring factors:
5
+ * - Factor 1: Token count (max 30 points)
6
+ * - Factor 2: Task type (max 80 points)
7
+ * - Factor 3: Context size (max 20 points)
8
+ * - Factor 4: Keywords (max 25 points)
9
+ *
10
+ * Total score is capped at 100 points.
11
+ */
12
+
13
+ class ComplexityScorer {
14
+ constructor() {
15
+ // Task type patterns with base scores
16
+ this.taskTypePatterns = {
17
+ exploration: {
18
+ keywords: ['explore', 'find', 'list', 'show', 'search', 'get', 'read', 'view', 'display', 'check'],
19
+ baseScore: 15
20
+ },
21
+ implementation: {
22
+ keywords: ['implement', 'create', 'build', 'write', 'develop', 'code', 'add', 'generate'],
23
+ baseScore: 45
24
+ },
25
+ analysis: {
26
+ keywords: ['analyze', 'design', 'architect', 'evaluate', 'review', 'assess', 'plan', 'strategy'],
27
+ baseScore: 75
28
+ }
29
+ };
30
+
31
+ // Keyword complexity weights
32
+ this.keywordWeights = {
33
+ simple: {
34
+ keywords: ['list', 'show', 'find', 'get', 'read', 'basic', 'simple'],
35
+ score: 7
36
+ },
37
+ medium: {
38
+ keywords: ['refactor', 'optimize', 'implement', 'integrate', 'update', 'modify'],
39
+ score: 17
40
+ },
41
+ critical: {
42
+ keywords: ['security', 'performance', 'architecture', 'scalability', 'critical', 'mission-critical'],
43
+ score: 25
44
+ }
45
+ };
46
+ }
47
+
48
+ /**
49
+ * Calculate overall complexity score for a task
50
+ * @param {Object} task - Task object with prompt and context
51
+ * @returns {number} - Complexity score (0-100)
52
+ */
53
+ calculateComplexity(task) {
54
+ if (!task || !task.prompt || task.prompt.trim() === '') {
55
+ throw new Error('prompt is required');
56
+ }
57
+
58
+ const tokenScore = this._calculateTokenScore(task.prompt);
59
+ const taskTypeScore = this._calculateTaskTypeScore(task);
60
+ const contextScore = this._calculateContextScore(task.context || {});
61
+ const keywordScore = this._calculateKeywordScore(task.prompt);
62
+
63
+ // Combine scores (token + type + context + keyword)
64
+ // Note: These can theoretically exceed 100, so we cap it
65
+ const totalScore = tokenScore + taskTypeScore + contextScore + keywordScore;
66
+
67
+ return Math.min(100, Math.max(0, totalScore));
68
+ }
69
+
70
+ /**
71
+ * Factor 1: Token count scoring (max 30 points)
72
+ * < 10 tokens: 0 points
73
+ * 10-200 tokens: scale linearly 0-30
74
+ * > 200 tokens: 30 points
75
+ */
76
+ _calculateTokenScore(prompt) {
77
+ const tokenCount = this._estimateTokenCount(prompt);
78
+
79
+ if (tokenCount < 10) return 0;
80
+ if (tokenCount >= 200) return 30;
81
+
82
+ // Linear scaling between 10 and 200 tokens
83
+ return Math.round((tokenCount - 10) / 190 * 30);
84
+ }
85
+
86
+ /**
87
+ * Estimate token count (simple word-based approximation)
88
+ */
89
+ _estimateTokenCount(text) {
90
+ return text.trim().split(/\s+/).length;
91
+ }
92
+
93
+ /**
94
+ * Factor 2: Task type scoring (max 80 points)
95
+ */
96
+ _calculateTaskTypeScore(task) {
97
+ const prompt = task.prompt.toLowerCase();
98
+
99
+ // Check explicit type if provided
100
+ if (task.type) {
101
+ const typeMap = {
102
+ 'exploration': 15,
103
+ 'implementation': 45,
104
+ 'analysis': 75
105
+ };
106
+ return typeMap[task.type] || 45;
107
+ }
108
+
109
+ // Infer type from keywords
110
+ for (const [typeName, typeData] of Object.entries(this.taskTypePatterns)) {
111
+ const hasKeyword = typeData.keywords.some(keyword => {
112
+ const regex = new RegExp(`\\b${keyword}\\b`, 'i');
113
+ return regex.test(prompt);
114
+ });
115
+
116
+ if (hasKeyword) {
117
+ return typeData.baseScore;
118
+ }
119
+ }
120
+
121
+ // Default to medium complexity if no pattern matches
122
+ return 45;
123
+ }
124
+
125
+ /**
126
+ * Factor 3: Context size scoring (max 20 points)
127
+ */
128
+ _calculateContextScore(context) {
129
+ if (!context || Object.keys(context).length === 0) {
130
+ return 0;
131
+ }
132
+
133
+ // Calculate context complexity based on:
134
+ // - Number of top-level keys
135
+ // - Depth of nesting
136
+ // - Total property count
137
+
138
+ const propertyCount = this._countProperties(context);
139
+ const nestingDepth = this._calculateNestingDepth(context);
140
+ const topLevelKeys = Object.keys(context).length;
141
+
142
+ // Scoring formula:
143
+ // - Small context (< 5 properties): 5-10 points
144
+ // - Medium context (5-15 properties): 10-15 points
145
+ // - Large context (> 15 properties): 15-20 points
146
+
147
+ let score = 0;
148
+
149
+ if (propertyCount < 5) {
150
+ score = 7;
151
+ } else if (propertyCount < 15) {
152
+ score = 12;
153
+ } else {
154
+ score = 17;
155
+ }
156
+
157
+ // Add bonus for deep nesting (max +3)
158
+ if (nestingDepth > 2) {
159
+ score += Math.min(3, nestingDepth - 2);
160
+ }
161
+
162
+ return Math.min(20, score);
163
+ }
164
+
165
+ /**
166
+ * Count total properties in an object (including nested)
167
+ */
168
+ _countProperties(obj, visited = new Set()) {
169
+ if (!obj || typeof obj !== 'object' || visited.has(obj)) {
170
+ return 0;
171
+ }
172
+
173
+ visited.add(obj);
174
+ let count = 0;
175
+
176
+ for (const key in obj) {
177
+ if (obj.hasOwnProperty(key)) {
178
+ count++;
179
+ if (typeof obj[key] === 'object' && obj[key] !== null) {
180
+ count += this._countProperties(obj[key], visited);
181
+ }
182
+ }
183
+ }
184
+
185
+ return count;
186
+ }
187
+
188
+ /**
189
+ * Calculate maximum nesting depth of an object
190
+ */
191
+ _calculateNestingDepth(obj, visited = new Set()) {
192
+ if (!obj || typeof obj !== 'object' || visited.has(obj)) {
193
+ return 0;
194
+ }
195
+
196
+ visited.add(obj);
197
+ let maxDepth = 0;
198
+
199
+ for (const key in obj) {
200
+ if (obj.hasOwnProperty(key) && typeof obj[key] === 'object' && obj[key] !== null) {
201
+ const depth = this._calculateNestingDepth(obj[key], visited);
202
+ maxDepth = Math.max(maxDepth, depth);
203
+ }
204
+ }
205
+
206
+ return maxDepth + 1;
207
+ }
208
+
209
+ /**
210
+ * Factor 4: Keyword scoring (max 25 points)
211
+ */
212
+ _calculateKeywordScore(prompt) {
213
+ const promptLower = prompt.toLowerCase();
214
+ let maxScore = 0;
215
+
216
+ // Check each keyword category (take highest matching score)
217
+ for (const [category, data] of Object.entries(this.keywordWeights)) {
218
+ const hasKeyword = data.keywords.some(keyword => {
219
+ const regex = new RegExp(`\\b${keyword}\\b`, 'i');
220
+ return regex.test(promptLower);
221
+ });
222
+
223
+ if (hasKeyword) {
224
+ maxScore = Math.max(maxScore, data.score);
225
+ }
226
+ }
227
+
228
+ return maxScore;
229
+ }
230
+ }
231
+
232
+ module.exports = ComplexityScorer;
@@ -0,0 +1,310 @@
1
+ /**
2
+ * FiveWhysAnalyzer - Root cause analysis through 5 WHYs technique
3
+ *
4
+ * MANTRAS: KISS, DRY, SOLID, Zero Emoji (IA-23)
5
+ *
6
+ * Features:
7
+ * - Pain point detection in user responses
8
+ * - Sequential WHY questioning (1-5 depth)
9
+ * - Root cause extraction
10
+ * - Analysis export with metadata
11
+ */
12
+
13
+ const Logger = require('../observability/logger');
14
+
15
+ class FiveWhysAnalyzer {
16
+ constructor(sessionState, logger) {
17
+ this.sessionState = sessionState;
18
+ this.logger = logger || new Logger({ logDir: 'logs', logFile: 'five-whys.log' });
19
+
20
+ this.depth = 0;
21
+ this.maxDepth = 5;
22
+ this.responses = [];
23
+ this.painPoints = [];
24
+ this.rootCause = null;
25
+ this.active = false;
26
+
27
+ this.painKeywords = [
28
+ 'problem', 'issue', 'challenge', 'difficult', 'slow', 'complex',
29
+ 'error', 'fail', 'break', 'bug', 'struggle', 'hard', 'confusing',
30
+ 'frustrating', 'annoying', 'painful', 'blocking', 'stuck'
31
+ ];
32
+ }
33
+
34
+ start(initialResponse) {
35
+ if (!initialResponse || typeof initialResponse !== 'string') {
36
+ return { needsWhys: false, reason: 'Invalid response' };
37
+ }
38
+
39
+ const detected = this._detectPainPoints(initialResponse);
40
+
41
+ if (!detected.hasPainPoints) {
42
+ this.logger.info('No pain points detected', { response: initialResponse.substring(0, 100) });
43
+ return { needsWhys: false, reason: 'No pain points detected' };
44
+ }
45
+
46
+ this.active = true;
47
+ this.painPoints = detected.painPoints;
48
+ this.responses.push({
49
+ depth: 0,
50
+ question: 'initial',
51
+ answer: initialResponse,
52
+ painPoints: detected.painPoints
53
+ });
54
+
55
+ this.logger.info('5 Whys started', { painPoints: detected.painPoints });
56
+
57
+ return {
58
+ needsWhys: true,
59
+ painPoints: detected.painPoints,
60
+ firstQuestion: this.askNext()
61
+ };
62
+ }
63
+
64
+ _detectPainPoints(text) {
65
+ const lowerText = text.toLowerCase();
66
+ const foundPoints = [];
67
+
68
+ for (const keyword of this.painKeywords) {
69
+ if (lowerText.includes(keyword)) {
70
+ const index = lowerText.indexOf(keyword);
71
+ const context = text.substring(Math.max(0, index - 20), Math.min(text.length, index + 50));
72
+ foundPoints.push({ keyword, context: context.trim() });
73
+ }
74
+ }
75
+
76
+ return {
77
+ hasPainPoints: foundPoints.length > 0,
78
+ painPoints: foundPoints,
79
+ confidence: Math.min(1.0, foundPoints.length / 3)
80
+ };
81
+ }
82
+
83
+ askNext() {
84
+ if (!this.active) {
85
+ return null;
86
+ }
87
+
88
+ if (this.depth >= this.maxDepth) {
89
+ return null;
90
+ }
91
+
92
+ this.depth++;
93
+
94
+ const questions = [
95
+ 'Why is this a problem for you?',
96
+ 'Why does this happen?',
97
+ 'Why is that the case?',
98
+ 'Why does that matter?',
99
+ 'What is the underlying reason?'
100
+ ];
101
+
102
+ const question = this.depth === 1
103
+ ? 'Why is this a problem for you?'
104
+ : questions[Math.min(this.depth - 1, questions.length - 1)];
105
+
106
+ return {
107
+ depth: this.depth,
108
+ question,
109
+ prompt: `${question} (${this.depth}/5)`
110
+ };
111
+ }
112
+
113
+ processAnswer(answer) {
114
+ if (!this.active) {
115
+ return { valid: false, reason: 'Analyzer not active' };
116
+ }
117
+
118
+ if (!answer || typeof answer !== 'string' || answer.trim().length < 10) {
119
+ return { valid: false, reason: 'Answer too short or invalid' };
120
+ }
121
+
122
+ this.responses.push({
123
+ depth: this.depth,
124
+ question: `Why #${this.depth}`,
125
+ answer: answer.trim(),
126
+ timestamp: new Date().toISOString()
127
+ });
128
+
129
+ const rootCauseAnalysis = this._analyzeForRootCause(answer);
130
+
131
+ if (rootCauseAnalysis.isRootCause && this.depth >= 3) {
132
+ this.rootCause = rootCauseAnalysis;
133
+ this.active = false;
134
+ this.logger.info('Root cause identified early', {
135
+ depth: this.depth,
136
+ rootCause: rootCauseAnalysis.statement
137
+ });
138
+
139
+ return {
140
+ valid: true,
141
+ rootCauseFound: true,
142
+ analysis: rootCauseAnalysis,
143
+ nextQuestion: null
144
+ };
145
+ }
146
+
147
+ if (this.depth >= this.maxDepth) {
148
+ this.rootCause = this._extractRootCause();
149
+ this.active = false;
150
+ this.logger.info('5 Whys completed', {
151
+ depth: this.depth,
152
+ rootCause: this.rootCause.statement
153
+ });
154
+
155
+ return {
156
+ valid: true,
157
+ completed: true,
158
+ rootCause: this.rootCause,
159
+ nextQuestion: null
160
+ };
161
+ }
162
+
163
+ return {
164
+ valid: true,
165
+ nextQuestion: this.askNext()
166
+ };
167
+ }
168
+
169
+ _analyzeForRootCause(answer) {
170
+ const lowerAnswer = answer.toLowerCase();
171
+
172
+ const rootCauseIndicators = [
173
+ 'because', 'fundamental', 'core', 'underlying', 'root',
174
+ 'lack of', 'missing', 'no process', 'no system', 'unclear',
175
+ 'not defined', 'never', 'always', 'since beginning'
176
+ ];
177
+
178
+ let indicatorCount = 0;
179
+ for (const indicator of rootCauseIndicators) {
180
+ if (lowerAnswer.includes(indicator)) {
181
+ indicatorCount++;
182
+ }
183
+ }
184
+
185
+ const isRootCause = indicatorCount >= 2 || (indicatorCount >= 1 && answer.length > 100);
186
+ const confidence = Math.min(1.0, (indicatorCount * 0.3) + (answer.length / 500));
187
+
188
+ return {
189
+ isRootCause,
190
+ confidence,
191
+ statement: answer.trim(),
192
+ depth: this.depth,
193
+ indicators: indicatorCount
194
+ };
195
+ }
196
+
197
+ _extractRootCause() {
198
+ if (this.responses.length < 2) {
199
+ return {
200
+ statement: 'Insufficient data for root cause analysis',
201
+ confidence: 0.0,
202
+ category: 'unknown',
203
+ actionItems: []
204
+ };
205
+ }
206
+
207
+ const lastResponses = this.responses.slice(-2);
208
+ const deepestAnswer = lastResponses[lastResponses.length - 1].answer;
209
+
210
+ const category = this._categorizeRootCause(deepestAnswer);
211
+ const actionItems = this._extractActionItems(deepestAnswer);
212
+ const confidence = this._calculateConfidence(this.depth, deepestAnswer);
213
+
214
+ return {
215
+ statement: deepestAnswer,
216
+ confidence,
217
+ category,
218
+ actionItems,
219
+ depth: this.depth
220
+ };
221
+ }
222
+
223
+ _categorizeRootCause(statement) {
224
+ const lowerStatement = statement.toLowerCase();
225
+
226
+ const categories = {
227
+ technical: ['code', 'system', 'software', 'hardware', 'infrastructure', 'api', 'database'],
228
+ process: ['process', 'workflow', 'procedure', 'method', 'approach', 'way we'],
229
+ resource: ['time', 'money', 'budget', 'people', 'team', 'resource', 'capacity'],
230
+ knowledge: ['know', 'understand', 'learn', 'training', 'documentation', 'experience', 'skill']
231
+ };
232
+
233
+ for (const [category, keywords] of Object.entries(categories)) {
234
+ for (const keyword of keywords) {
235
+ if (lowerStatement.includes(keyword)) {
236
+ return category;
237
+ }
238
+ }
239
+ }
240
+
241
+ return 'general';
242
+ }
243
+
244
+ _extractActionItems(statement) {
245
+ const actionKeywords = [
246
+ 'need to', 'should', 'must', 'have to', 'require',
247
+ 'implement', 'create', 'build', 'fix', 'improve'
248
+ ];
249
+
250
+ const sentences = statement.split(/[.!?]+/).filter(s => s.trim().length > 0);
251
+ const actions = [];
252
+
253
+ for (const sentence of sentences) {
254
+ const lowerSentence = sentence.toLowerCase();
255
+ for (const keyword of actionKeywords) {
256
+ if (lowerSentence.includes(keyword)) {
257
+ actions.push(sentence.trim());
258
+ break;
259
+ }
260
+ }
261
+ }
262
+
263
+ return actions.slice(0, 3);
264
+ }
265
+
266
+ _calculateConfidence(depth, statement) {
267
+ let confidence = 0.5;
268
+
269
+ confidence += (depth / this.maxDepth) * 0.3;
270
+
271
+ if (statement.length > 50) confidence += 0.1;
272
+ if (statement.length > 100) confidence += 0.1;
273
+
274
+ return Math.min(1.0, confidence);
275
+ }
276
+
277
+ isComplete() {
278
+ return !this.active;
279
+ }
280
+
281
+ getRootCause() {
282
+ return this.rootCause;
283
+ }
284
+
285
+ getDepth() {
286
+ return this.depth;
287
+ }
288
+
289
+ getResponses() {
290
+ return [...this.responses];
291
+ }
292
+
293
+ export() {
294
+ return {
295
+ version: '1.0.0',
296
+ createdAt: new Date().toISOString(),
297
+ painPoints: this.painPoints,
298
+ depth: this.depth,
299
+ responses: this.responses,
300
+ rootCause: this.rootCause,
301
+ metadata: {
302
+ completed: this.isComplete(),
303
+ maxDepth: this.maxDepth,
304
+ responseCount: this.responses.length
305
+ }
306
+ };
307
+ }
308
+ }
309
+
310
+ module.exports = FiveWhysAnalyzer;