bobs-workshop 0.3.2 → 3.1.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 (200) hide show
  1. package/LICENSE +2 -2
  2. package/README.md +199 -210
  3. package/bin/bobs-workshop.js +109 -0
  4. package/config/agents.json +27 -0
  5. package/dist/plugins/bobs-workshop.js +34 -0
  6. package/dist/tools/background-agent/cancel.d.ts +3 -0
  7. package/dist/tools/background-agent/cancel.d.ts.map +1 -0
  8. package/dist/tools/background-agent/cancel.js +52 -0
  9. package/dist/tools/background-agent/concurrency.d.ts +15 -0
  10. package/dist/tools/background-agent/concurrency.d.ts.map +1 -0
  11. package/dist/tools/background-agent/concurrency.js +61 -0
  12. package/dist/tools/background-agent/index.d.ts +8 -0
  13. package/dist/tools/background-agent/index.d.ts.map +1 -0
  14. package/dist/tools/background-agent/index.js +7 -0
  15. package/dist/tools/background-agent/launch.d.ts +6 -0
  16. package/dist/tools/background-agent/launch.d.ts.map +1 -0
  17. package/dist/tools/background-agent/launch.js +33 -0
  18. package/dist/tools/background-agent/list.d.ts +7 -0
  19. package/dist/tools/background-agent/list.d.ts.map +1 -0
  20. package/dist/tools/background-agent/list.js +40 -0
  21. package/dist/tools/background-agent/manager.d.ts +29 -0
  22. package/dist/tools/background-agent/manager.d.ts.map +1 -0
  23. package/dist/tools/background-agent/manager.js +377 -0
  24. package/dist/tools/background-agent/output.d.ts +3 -0
  25. package/dist/tools/background-agent/output.d.ts.map +1 -0
  26. package/dist/tools/background-agent/output.js +41 -0
  27. package/dist/tools/background-agent/types.d.ts +46 -0
  28. package/dist/tools/background-agent/types.d.ts.map +1 -0
  29. package/dist/tools/background-agent/types.js +1 -0
  30. package/dist/tools/index.d.ts +9 -0
  31. package/dist/tools/index.d.ts.map +1 -0
  32. package/dist/tools/index.js +8 -0
  33. package/dist/tools/manual/index.d.ts +3 -0
  34. package/dist/tools/manual/index.d.ts.map +1 -0
  35. package/dist/tools/manual/index.js +2 -0
  36. package/dist/tools/manual/manual-update.d.ts +4 -0
  37. package/dist/tools/manual/manual-update.d.ts.map +1 -0
  38. package/dist/tools/manual/manual-update.js +190 -0
  39. package/dist/tools/manual/verify-manual.d.ts +4 -0
  40. package/dist/tools/manual/verify-manual.d.ts.map +1 -0
  41. package/dist/tools/manual/verify-manual.js +46 -0
  42. package/package.json +35 -67
  43. package/postinstall.js +190 -0
  44. package/src/agents/alice.md +466 -0
  45. package/src/agents/bob-rev.md +493 -0
  46. package/src/agents/bob-send.md +277 -0
  47. package/src/agents/bob.md +442 -0
  48. package/src/agents/trace.md +451 -0
  49. package/src/plugins/bobs-workshop.ts +45 -0
  50. package/src/skills/api-patterns/SKILL.md +376 -0
  51. package/src/skills/architecture/SKILL.md +271 -0
  52. package/src/skills/bobs-workshop/performance/icon.svg +3 -0
  53. package/src/skills/brainstorming/SKILL.md +210 -0
  54. package/src/skills/clean-code/SKILL.md +151 -0
  55. package/src/skills/code-review-checklist/SKILL.md +220 -0
  56. package/src/skills/database-design/SKILL.md +271 -0
  57. package/src/skills/exploration/SKILL.md +257 -0
  58. package/src/skills/frontend-ui-ux/SKILL.md +78 -0
  59. package/src/skills/git-master/SKILL.md +1105 -0
  60. package/src/skills/performance/SKILL.md +144 -0
  61. package/src/skills/performance/icon.svg +3 -0
  62. package/src/skills/plan-writing/SKILL.md +225 -0
  63. package/src/skills/security/SKILL.md +410 -0
  64. package/src/skills/simplification/SKILL.md +238 -0
  65. package/src/skills/systematic-debugging/SKILL.md +175 -0
  66. package/src/skills/testing-patterns/SKILL.md +305 -0
  67. package/src/skills/verification/SKILL.md +286 -0
  68. package/src/tools/background-agent/cancel.ts +67 -0
  69. package/src/tools/background-agent/concurrency.ts +71 -0
  70. package/src/tools/background-agent/index.ts +7 -0
  71. package/src/tools/background-agent/launch.ts +39 -0
  72. package/src/tools/background-agent/list.ts +50 -0
  73. package/src/tools/background-agent/manager.ts +455 -0
  74. package/src/tools/background-agent/output.ts +57 -0
  75. package/src/tools/background-agent/types.ts +55 -0
  76. package/src/tools/index.ts +8 -0
  77. package/src/tools/manual/index.ts +2 -0
  78. package/src/tools/manual/manual-update.ts +197 -0
  79. package/src/tools/manual/verify-manual.ts +55 -0
  80. package/uninstall.js +64 -0
  81. package/Claude.md +0 -162
  82. package/bin/bobs-mcp-server.js +0 -11
  83. package/bin/bobs-mcp.js +0 -130
  84. package/dist/api/taskLogger.js +0 -106
  85. package/dist/api/taskLogger.js.map +0 -1
  86. package/dist/cli/checker.js +0 -401
  87. package/dist/cli/checker.js.map +0 -1
  88. package/dist/cli/cleanup.js +0 -131
  89. package/dist/cli/cleanup.js.map +0 -1
  90. package/dist/cli/debug.js +0 -157
  91. package/dist/cli/debug.js.map +0 -1
  92. package/dist/cli/health.js +0 -97
  93. package/dist/cli/health.js.map +0 -1
  94. package/dist/cli/setup.js +0 -81
  95. package/dist/cli/setup.js.map +0 -1
  96. package/dist/cli/workshop.js +0 -42
  97. package/dist/cli/workshop.js.map +0 -1
  98. package/dist/dashboard/server.js +0 -1203
  99. package/dist/dashboard/server.js.map +0 -1
  100. package/dist/index.js +0 -960
  101. package/dist/index.js.map +0 -1
  102. package/dist/prompts/architect.js +0 -221
  103. package/dist/prompts/architect.js.map +0 -1
  104. package/dist/prompts/debugger.js +0 -257
  105. package/dist/prompts/debugger.js.map +0 -1
  106. package/dist/prompts/engineer.js +0 -249
  107. package/dist/prompts/engineer.js.map +0 -1
  108. package/dist/prompts/orchestrator.js +0 -304
  109. package/dist/prompts/orchestrator.js.map +0 -1
  110. package/dist/prompts/reviewer.js +0 -289
  111. package/dist/prompts/reviewer.js.map +0 -1
  112. package/dist/services/activitySummarizer.js +0 -388
  113. package/dist/services/activitySummarizer.js.map +0 -1
  114. package/dist/services/changeValidator.js +0 -396
  115. package/dist/services/changeValidator.js.map +0 -1
  116. package/dist/services/claudeOrchestrator.js +0 -343
  117. package/dist/services/claudeOrchestrator.js.map +0 -1
  118. package/dist/services/fileMonitor.js +0 -250
  119. package/dist/services/fileMonitor.js.map +0 -1
  120. package/dist/services/implementationSummarizer.js +0 -306
  121. package/dist/services/implementationSummarizer.js.map +0 -1
  122. package/dist/services/liveMonitor.js +0 -315
  123. package/dist/services/liveMonitor.js.map +0 -1
  124. package/dist/services/mcpAuditLogger.js +0 -104
  125. package/dist/services/mcpAuditLogger.js.map +0 -1
  126. package/dist/services/mcpLogger.js +0 -223
  127. package/dist/services/mcpLogger.js.map +0 -1
  128. package/dist/services/tmuxManager.js +0 -541
  129. package/dist/services/tmuxManager.js.map +0 -1
  130. package/dist/tools/approvalTools.js +0 -244
  131. package/dist/tools/approvalTools.js.map +0 -1
  132. package/dist/tools/autoDebugger.js +0 -147
  133. package/dist/tools/autoDebugger.js.map +0 -1
  134. package/dist/tools/cleanupService.js +0 -221
  135. package/dist/tools/cleanupService.js.map +0 -1
  136. package/dist/tools/dashboardTools.js +0 -342
  137. package/dist/tools/dashboardTools.js.map +0 -1
  138. package/dist/tools/developmentNudges.js +0 -336
  139. package/dist/tools/developmentNudges.js.map +0 -1
  140. package/dist/tools/gitTools.js +0 -741
  141. package/dist/tools/gitTools.js.map +0 -1
  142. package/dist/tools/orchestratorTools.js +0 -832
  143. package/dist/tools/orchestratorTools.js.map +0 -1
  144. package/dist/tools/searchCache.js +0 -64
  145. package/dist/tools/searchCache.js.map +0 -1
  146. package/dist/tools/searchTools.js +0 -1107
  147. package/dist/tools/searchTools.js.map +0 -1
  148. package/dist/tools/semgrep-patterns.js +0 -296
  149. package/dist/tools/semgrep-patterns.js.map +0 -1
  150. package/dist/tools/specTools.js +0 -332
  151. package/dist/tools/specTools.js.map +0 -1
  152. package/dist/tools/structural/__tests__/orchestrator.test.js +0 -61
  153. package/dist/tools/structural/__tests__/orchestrator.test.js.map +0 -1
  154. package/dist/tools/structural/cache.js +0 -226
  155. package/dist/tools/structural/cache.js.map +0 -1
  156. package/dist/tools/structural/engines/python/index.js +0 -118
  157. package/dist/tools/structural/engines/python/index.js.map +0 -1
  158. package/dist/tools/structural/engines/typescript/__tests__/typescript-engine.test.js +0 -97
  159. package/dist/tools/structural/engines/typescript/__tests__/typescript-engine.test.js.map +0 -1
  160. package/dist/tools/structural/engines/typescript/analyzer.js +0 -433
  161. package/dist/tools/structural/engines/typescript/analyzer.js.map +0 -1
  162. package/dist/tools/structural/engines/typescript/index.js +0 -381
  163. package/dist/tools/structural/engines/typescript/index.js.map +0 -1
  164. package/dist/tools/structural/engines/typescript/utils.js +0 -279
  165. package/dist/tools/structural/engines/typescript/utils.js.map +0 -1
  166. package/dist/tools/structural/index.js +0 -248
  167. package/dist/tools/structural/index.js.map +0 -1
  168. package/dist/tools/structural/types.js +0 -18
  169. package/dist/tools/structural/types.js.map +0 -1
  170. package/dist/tools/tmuxTools.js +0 -100
  171. package/dist/tools/tmuxTools.js.map +0 -1
  172. package/dist/tools/workRecorder.js +0 -215
  173. package/dist/tools/workRecorder.js.map +0 -1
  174. package/dist/tools/worktreeTools.js +0 -705
  175. package/dist/tools/worktreeTools.js.map +0 -1
  176. package/dist/utils/__tests__/integration.test.js +0 -57
  177. package/dist/utils/__tests__/integration.test.js.map +0 -1
  178. package/dist/utils/__tests__/serverDetection.test.js +0 -151
  179. package/dist/utils/__tests__/serverDetection.test.js.map +0 -1
  180. package/dist/utils/errorHandling.js +0 -336
  181. package/dist/utils/errorHandling.js.map +0 -1
  182. package/dist/utils/processManager.js +0 -172
  183. package/dist/utils/processManager.js.map +0 -1
  184. package/dist/utils/reliability.js +0 -263
  185. package/dist/utils/reliability.js.map +0 -1
  186. package/dist/utils/responseFormatter.js +0 -250
  187. package/dist/utils/responseFormatter.js.map +0 -1
  188. package/dist/utils/serverDetection.js +0 -133
  189. package/dist/utils/serverDetection.js.map +0 -1
  190. package/dist/utils/specMigration.js +0 -105
  191. package/dist/utils/specMigration.js.map +0 -1
  192. package/dist/validation/schemas.js +0 -299
  193. package/dist/validation/schemas.js.map +0 -1
  194. package/public/.well-known/mcp/manifest.json +0 -473
  195. package/public/index.html +0 -3157
  196. package/public/index.html.backup +0 -2805
  197. package/public/index.html.backup2 +0 -1292
  198. package/scripts/cleanup-system-logs.ts +0 -121
  199. package/scripts/init-workspace.js +0 -63
  200. package/scripts/install-search-tools.js +0 -116
@@ -1,832 +0,0 @@
1
- import { z } from "zod";
2
- import { specCreateHandler, specGetHandler, specListHandler } from "./specTools.js";
3
- import { dashboardLaunchHandler, dashboardUpdateHandler } from "./dashboardTools.js";
4
- import { mcpLogger } from "../services/mcpLogger.js";
5
- import { validateGate1, validateGate2, validateGate3, validateEnhancedStateTransition } from "../validation/schemas.js";
6
- export const WorkshopInput = z.object({
7
- problem: z.string().describe("Problem statement or task description"),
8
- mode: z.enum(["architect", "engineer", "debugger", "reviewer"]).optional().describe("Preferred mode (optional - will be auto-determined)"),
9
- spec_id: z.string().optional().describe("Continue existing SPEC (optional)"),
10
- clarifications: z.record(z.string()).optional().describe("Answers to previous clarifying questions"),
11
- user_approval: z.boolean().optional().describe("User approval for spec or implementation"),
12
- user_satisfaction: z.boolean().optional().describe("User satisfaction with completed work")
13
- });
14
- export const WorkshopOutput = z.object({
15
- spec_id: z.string(),
16
- action: z.enum(["clarify", "route", "continue", "await_approval", "proceed", "complete"]),
17
- clarify_questions: z.array(z.string()).optional(),
18
- next_mode: z.string().optional(),
19
- dashboard_url: z.string().optional(),
20
- prompt_context: z.string().optional(),
21
- workflow_step: z.enum([
22
- "questioning", "spec_review", "approved", "implementation",
23
- "user_review", "completed", "routed_to_architect", "routed_to_engineer",
24
- "routed_to_debugger", "routed_to_reviewer"
25
- ]).optional(),
26
- requires_user_input: z.boolean().optional(),
27
- approval_message: z.string().optional(),
28
- confidence_score: z.number().optional().describe("Confidence level in problem understanding (0-1)")
29
- });
30
- export async function workshopHandler(input) {
31
- console.log("bob.workshop orchestrator called with:", input);
32
- const validated = WorkshopInput.parse(input);
33
- // Step 1: Analyze the problem statement
34
- const analysis = analyzeProblem(validated.problem, validated.clarifications);
35
- // Step 2: Handle existing SPEC continuation
36
- if (validated.spec_id) {
37
- return await continueExistingSpec(validated.spec_id, analysis, validated.mode);
38
- }
39
- // Step 3: Check for existing related SPECs
40
- const existingSpecs = await findRelatedSpecs(validated.problem);
41
- // Step 4: Decide if we need clarification (enhanced threshold and logic)
42
- if (analysis.confidence < 0.95 && !validated.clarifications && analysis.questions.length > 0) {
43
- return {
44
- spec_id: "",
45
- action: "clarify",
46
- clarify_questions: analysis.questions,
47
- next_mode: analysis.suggestedMode,
48
- dashboard_url: undefined,
49
- prompt_context: undefined,
50
- workflow_step: "questioning",
51
- requires_user_input: true,
52
- approval_message: `I need to ask ${analysis.questions.length} clarifying question${analysis.questions.length > 1 ? 's' : ''} before proceeding. Please provide answers to ensure accurate implementation.`,
53
- confidence_score: analysis.confidence
54
- };
55
- }
56
- // Step 5: Create new SPEC for new features with parallel dashboard update
57
- let specId = "";
58
- if (analysis.category === "feature" || analysis.category === "research") {
59
- // Create SPEC and send dashboard update in parallel
60
- const [newSpec] = await Promise.allSettled([
61
- specCreateHandler({
62
- title: extractTitle(validated.problem),
63
- author: "AI Orchestrator",
64
- category: mapCategoryToSpecCategory(analysis.category),
65
- priority: mapComplexityToPriority(analysis.complexity),
66
- tags: extractTags(validated.problem),
67
- initial_state: "draft"
68
- }),
69
- sendDashboardUpdate("", "orchestrator_started", {
70
- action: "spec_creation",
71
- problem: validated.problem,
72
- analysis: {
73
- category: analysis.category,
74
- complexity: analysis.complexity,
75
- confidence: analysis.confidence
76
- }
77
- })
78
- ]);
79
- if (newSpec.status === 'fulfilled') {
80
- specId = newSpec.value.spec_id;
81
- // Send spec creation notification
82
- await sendDashboardUpdate(specId, "spec_created", {
83
- title: extractTitle(validated.problem),
84
- category: analysis.category,
85
- complexity: analysis.complexity
86
- });
87
- }
88
- else {
89
- throw new Error(`Failed to create SPEC: ${newSpec.reason}`);
90
- }
91
- }
92
- else if (existingSpecs.length > 0) {
93
- // Use most recent existing SPEC for non-feature work
94
- specId = existingSpecs[0].spec_id;
95
- // Notify about continuing existing SPEC
96
- await sendDashboardUpdate(specId, "spec_continued", {
97
- problem: validated.problem,
98
- analysis: {
99
- category: analysis.category,
100
- complexity: analysis.complexity
101
- }
102
- });
103
- }
104
- // Step 6: Launch dashboard for new feature work with parallel notification
105
- let dashboardUrl = "";
106
- if (analysis.category === "feature" && analysis.suggestedMode === "architect") {
107
- const [dashboardResult] = await Promise.allSettled([
108
- dashboardLaunchHandler(),
109
- sendDashboardUpdate(specId, "dashboard_launch_requested", {
110
- mode: analysis.suggestedMode,
111
- reason: "new feature development"
112
- })
113
- ]);
114
- if (dashboardResult.status === 'fulfilled') {
115
- dashboardUrl = "http://localhost:4577";
116
- // Notify dashboard is ready
117
- await sendDashboardUpdate(specId, "dashboard_launched", {
118
- url: dashboardUrl,
119
- status: dashboardResult.value?.status || "launched"
120
- });
121
- }
122
- }
123
- // Step 7: Determine final mode (respect explicit preference)
124
- const finalMode = validated.mode || analysis.suggestedMode;
125
- // Log role transition from orchestrator to target mode
126
- await mcpLogger.logRoleTransition('orchestrator', finalMode, specId, `Problem classified as ${analysis.category} (confidence: ${Math.round(analysis.confidence * 100)}%)`);
127
- // Step 8: Create context for the target mode
128
- const promptContext = await createModeContext(finalMode, validated.problem, specId, analysis);
129
- // Step 9: Send final mode switching notification in parallel with return
130
- const result = {
131
- spec_id: specId,
132
- action: "route",
133
- clarify_questions: undefined,
134
- next_mode: finalMode,
135
- dashboard_url: dashboardUrl || undefined,
136
- prompt_context: promptContext,
137
- workflow_step: `routed_to_${finalMode}`,
138
- requires_user_input: false,
139
- approval_message: undefined,
140
- confidence_score: analysis.confidence
141
- };
142
- // Send mode switching notification without blocking return
143
- sendDashboardUpdate(specId, "orchestrator_mode_switch", {
144
- target_mode: finalMode,
145
- workflow_step: `switching_to_${finalMode}`,
146
- dashboard_available: !!dashboardUrl,
147
- execution_note: `YOU are now switching to ${finalMode} mode - execute ${finalMode.toUpperCase()}_PROMPT steps directly`
148
- }).catch(error => {
149
- console.log('Dashboard mode switch notification failed (non-blocking):', error);
150
- });
151
- return result;
152
- }
153
- function analyzeProblem(problem, clarifications) {
154
- const lowerProblem = problem.toLowerCase();
155
- // Simple keyword-based analysis (can be enhanced with more sophisticated NLP)
156
- let category = "feature";
157
- let suggestedMode = "architect";
158
- let confidence = 0.8; // Base confidence
159
- const questions = [];
160
- // Detect category and mode with priority order (most specific first)
161
- if (lowerProblem.includes("review") || lowerProblem.includes("audit") || lowerProblem.includes("check") || lowerProblem.includes("vulnerabilities")) {
162
- category = "review";
163
- suggestedMode = "reviewer";
164
- confidence += 0.2;
165
- }
166
- else if (lowerProblem.includes("bug") || lowerProblem.includes("fix") || lowerProblem.includes("error") || lowerProblem.includes("broken")) {
167
- category = "bug";
168
- suggestedMode = "debugger";
169
- confidence += 0.2;
170
- }
171
- else if (lowerProblem.includes("implement") || lowerProblem.includes("develop") || (lowerProblem.includes("according") && lowerProblem.includes("spec"))) {
172
- category = "implementation";
173
- suggestedMode = "engineer";
174
- confidence += 0.2;
175
- }
176
- else if (lowerProblem.includes("add") || lowerProblem.includes("create") || lowerProblem.includes("build") || lowerProblem.includes("new") || lowerProblem.includes("dashboard") || lowerProblem.includes("feature") || lowerProblem.includes("library") || lowerProblem.includes("make me")) {
177
- category = "feature";
178
- suggestedMode = "architect";
179
- confidence += 0.15;
180
- }
181
- // Assess complexity
182
- let complexity = "medium";
183
- if (lowerProblem.length < 50 || lowerProblem.split(" ").length < 8) {
184
- complexity = "simple";
185
- confidence -= 0.1;
186
- }
187
- else if (lowerProblem.length > 200 || lowerProblem.includes("system") || lowerProblem.includes("architecture")) {
188
- complexity = "complex";
189
- confidence += 0.05;
190
- }
191
- // Final category adjustment based on strong indicators (only for ambiguous cases)
192
- if (category === "feature" && (lowerProblem.includes("dashboard") || lowerProblem.includes("comprehensive") || lowerProblem.includes("components"))) {
193
- confidence = 0.9; // High confidence for clear feature descriptions
194
- }
195
- // Enhanced question generation with more sophisticated probing
196
- if (!clarifications) {
197
- // Feature category questions
198
- if (category === "feature") {
199
- // Core architecture questions
200
- if (!lowerProblem.includes("user") && !lowerProblem.includes("api") && !lowerProblem.includes("frontend") && !lowerProblem.includes("backend")) {
201
- questions.push("Is this a user-facing feature, internal API, or full-stack component?");
202
- confidence -= 0.08;
203
- }
204
- // Data persistence questions
205
- if (!lowerProblem.includes("database") && !lowerProblem.includes("storage") && !lowerProblem.includes("persist") && complexity !== "simple") {
206
- questions.push("Does this feature need to store/persist data? If so, what type of data?");
207
- confidence -= 0.06;
208
- }
209
- // Security and access control
210
- if (!lowerProblem.includes("authentication") && !lowerProblem.includes("permission") && !lowerProblem.includes("role") && lowerProblem.includes("user")) {
211
- questions.push("What are the authentication and authorization requirements? Who can access this feature?");
212
- confidence -= 0.06;
213
- }
214
- // Integration and dependencies
215
- if (!lowerProblem.includes("integrate") && !lowerProblem.includes("external") && !lowerProblem.includes("api") && complexity === "complex") {
216
- questions.push("Does this feature integrate with external services or existing systems?");
217
- confidence -= 0.04;
218
- }
219
- // Performance and scale
220
- if (!lowerProblem.includes("performance") && !lowerProblem.includes("scale") && !lowerProblem.includes("users") && complexity !== "simple") {
221
- questions.push("What are the expected performance requirements and user scale?");
222
- confidence -= 0.04;
223
- }
224
- // UI/UX considerations
225
- if (lowerProblem.includes("user") && !lowerProblem.includes("interface") && !lowerProblem.includes("ui") && !lowerProblem.includes("design")) {
226
- questions.push("Do you have specific UI/UX requirements or design preferences?");
227
- confidence -= 0.03;
228
- }
229
- // Testing strategy
230
- if (!lowerProblem.includes("test") && !lowerProblem.includes("quality") && complexity !== "simple") {
231
- questions.push("What level of testing is required (unit, integration, e2e)?");
232
- confidence -= 0.03;
233
- }
234
- }
235
- else if (category === "bug") {
236
- // Reproduction steps
237
- if (!lowerProblem.includes("reproduce") && !lowerProblem.includes("steps") && !lowerProblem.includes("when")) {
238
- questions.push("Can you provide detailed steps to reproduce this issue?");
239
- confidence -= 0.08;
240
- }
241
- // Expected vs actual behavior
242
- if (!lowerProblem.includes("expect") && !lowerProblem.includes("should") && !lowerProblem.includes("supposed")) {
243
- questions.push("What is the expected behavior vs. what you're actually seeing?");
244
- confidence -= 0.07;
245
- }
246
- // Environment and context
247
- if (!lowerProblem.includes("environment") && !lowerProblem.includes("browser") && !lowerProblem.includes("version")) {
248
- questions.push("In what environment does this occur (browser, OS, version, etc.)?");
249
- confidence -= 0.06;
250
- }
251
- // Frequency and impact
252
- if (!lowerProblem.includes("always") && !lowerProblem.includes("sometimes") && !lowerProblem.includes("critical")) {
253
- questions.push("How frequently does this occur and what's the business impact?");
254
- confidence -= 0.05;
255
- }
256
- // Error messages and logs
257
- if (!lowerProblem.includes("error") && !lowerProblem.includes("log") && !lowerProblem.includes("message")) {
258
- questions.push("Are there any error messages, console logs, or stack traces?");
259
- confidence -= 0.05;
260
- }
261
- }
262
- else if (category === "implementation") {
263
- // Existing specifications
264
- if (!lowerProblem.includes("spec") && !lowerProblem.includes("requirement") && !lowerProblem.includes("design")) {
265
- questions.push("Do you have existing specifications, designs, or requirements documents?");
266
- confidence -= 0.07;
267
- }
268
- // Technical constraints
269
- if (!lowerProblem.includes("constraint") && !lowerProblem.includes("limitation") && !lowerProblem.includes("technology")) {
270
- questions.push("Are there any technical constraints or preferred technologies to use?");
271
- confidence -= 0.06;
272
- }
273
- // Timeline and priority
274
- if (!lowerProblem.includes("deadline") && !lowerProblem.includes("urgent") && !lowerProblem.includes("priority")) {
275
- questions.push("What's the timeline and priority level for this implementation?");
276
- confidence -= 0.04;
277
- }
278
- }
279
- else if (category === "review") {
280
- // Scope of review
281
- if (!lowerProblem.includes("component") && !lowerProblem.includes("module") && !lowerProblem.includes("file")) {
282
- questions.push("What specific components, modules, or files should be reviewed?");
283
- confidence -= 0.08;
284
- }
285
- // Review focus areas
286
- if (!lowerProblem.includes("security") && !lowerProblem.includes("performance") && !lowerProblem.includes("quality")) {
287
- questions.push("What should the review focus on: security, performance, code quality, or all?");
288
- confidence -= 0.06;
289
- }
290
- // Standards and guidelines
291
- if (!lowerProblem.includes("standard") && !lowerProblem.includes("guideline") && !lowerProblem.includes("compliance")) {
292
- questions.push("Are there specific coding standards or compliance requirements to check against?");
293
- confidence -= 0.05;
294
- }
295
- }
296
- else if (category === "research") {
297
- // Research scope
298
- if (!lowerProblem.includes("scope") && !lowerProblem.includes("depth") && !lowerProblem.includes("focus")) {
299
- questions.push("What's the scope and depth of research needed? Any specific focus areas?");
300
- confidence -= 0.07;
301
- }
302
- // Deliverables
303
- if (!lowerProblem.includes("report") && !lowerProblem.includes("document") && !lowerProblem.includes("summary")) {
304
- questions.push("What deliverables are expected: summary, detailed report, recommendations?");
305
- confidence -= 0.06;
306
- }
307
- }
308
- // Universal questions for ambiguous or short descriptions
309
- if (problem.length < 30) {
310
- questions.push("Could you provide more details about what you're trying to accomplish?");
311
- confidence -= 0.1;
312
- }
313
- if (complexity === "simple" && questions.length === 0 && confidence < 0.9) {
314
- questions.push("Are there any specific requirements or constraints I should be aware of?");
315
- confidence -= 0.05;
316
- }
317
- // Limit to maximum 3 most important questions to avoid overwhelming user
318
- if (questions.length > 3) {
319
- questions.splice(3);
320
- }
321
- }
322
- return {
323
- confidence: Math.max(0.5, Math.min(1.0, confidence)),
324
- category,
325
- complexity,
326
- suggestedMode,
327
- questions
328
- };
329
- }
330
- async function continueExistingSpec(specId, analysis, preferredMode) {
331
- try {
332
- const spec = await specGetHandler({ spec_id: specId });
333
- const mode = preferredMode || analysis.suggestedMode;
334
- // Log role transition for existing spec continuation
335
- await mcpLogger.logRoleTransition('orchestrator', mode, specId, `Continuing existing SPEC work, transitioning to ${mode} mode`);
336
- const promptContext = await createModeContext(mode, "", specId, analysis);
337
- // Send dashboard notification about continuing existing SPEC
338
- sendDashboardUpdate(specId, "spec_continuation", {
339
- mode,
340
- analysis: {
341
- category: analysis.category,
342
- complexity: analysis.complexity,
343
- confidence: analysis.confidence
344
- },
345
- spec_title: spec.title
346
- }).catch(error => {
347
- console.log('Dashboard continuation notification failed (non-blocking):', error);
348
- });
349
- return {
350
- spec_id: specId,
351
- action: "continue",
352
- clarify_questions: undefined,
353
- next_mode: mode,
354
- dashboard_url: undefined,
355
- prompt_context: promptContext,
356
- workflow_step: `continuing_with_${mode}`
357
- };
358
- }
359
- catch (error) {
360
- throw new Error(`Cannot continue SPEC ${specId}: ${error}`);
361
- }
362
- }
363
- async function findRelatedSpecs(problem) {
364
- try {
365
- const allSpecs = await specListHandler({});
366
- const keywords = extractKeywords(problem);
367
- return allSpecs.specs.filter((spec) => {
368
- const specText = (spec.title + " " + spec.category).toLowerCase();
369
- return keywords.some(keyword => specText.includes(keyword));
370
- }).slice(0, 3); // Return top 3 matches
371
- }
372
- catch (error) {
373
- return [];
374
- }
375
- }
376
- function extractTitle(problem) {
377
- // Extract a concise title from the problem statement
378
- const words = problem.split(" ").slice(0, 8);
379
- return words.join(" ").replace(/[^\w\s-]/g, "").trim();
380
- }
381
- function extractKeywords(text) {
382
- const stopWords = ["the", "a", "an", "and", "or", "but", "in", "on", "at", "to", "for", "of", "with", "by"];
383
- return text.toLowerCase()
384
- .split(/\s+/)
385
- .filter(word => word.length > 2 && !stopWords.includes(word))
386
- .slice(0, 5);
387
- }
388
- function extractTags(problem) {
389
- const lowerProblem = problem.toLowerCase();
390
- const tags = [];
391
- // Common technology/domain tags
392
- const tagMap = {
393
- "react": ["frontend", "react"],
394
- "api": ["backend", "api"],
395
- "database": ["backend", "database"],
396
- "auth": ["security", "authentication"],
397
- "user": ["frontend", "ux"],
398
- "mobile": ["mobile", "responsive"],
399
- "test": ["testing", "qa"],
400
- "performance": ["performance", "optimization"]
401
- };
402
- Object.entries(tagMap).forEach(([keyword, tagList]) => {
403
- if (lowerProblem.includes(keyword)) {
404
- tags.push(...tagList);
405
- }
406
- });
407
- return [...new Set(tags)]; // Remove duplicates
408
- }
409
- function mapCategoryToSpecCategory(category) {
410
- const mapping = {
411
- "feature": "fullstack",
412
- "bug": "general",
413
- "review": "general",
414
- "implementation": "backend",
415
- "research": "general"
416
- };
417
- return mapping[category];
418
- }
419
- function mapComplexityToPriority(complexity) {
420
- const mapping = {
421
- "simple": "low",
422
- "medium": "medium",
423
- "complex": "high"
424
- };
425
- return mapping[complexity];
426
- }
427
- async function createModeContext(mode, problem, specId, analysis) {
428
- let context = `MODE SWITCH DIRECTIVE:\n`;
429
- context += `⚠️ YOU are now switching to ${mode.toUpperCase()} mode.\n`;
430
- context += `⚠️ Read the ${mode.toUpperCase()}_PROMPT and execute those steps directly.\n`;
431
- context += `⚠️ There is NO delegation - YOU ARE the ${mode} executing these tasks.\n\n`;
432
- context += `CONTEXT PROVIDED BY ORCHESTRATOR:\n`;
433
- context += `- Problem: ${problem}\n`;
434
- context += `- SPEC ID: ${specId}\n`;
435
- context += `- Category: ${analysis.category}\n`;
436
- context += `- Complexity: ${analysis.complexity}\n`;
437
- context += `- Confidence: ${(analysis.confidence * 100).toFixed(1)}%\n\n`;
438
- // Add mode-specific first steps
439
- switch (mode) {
440
- case "architect":
441
- context += `YOUR FIRST STEPS AS ARCHITECT:\n`;
442
- context += `1. Call bob.code.search with phase: "architect" to research existing codebase patterns\n`;
443
- context += `2. Call bob.workflow.start to create manual + worktree + launch dashboard\n`;
444
- context += `3. Use bob.manual.update to build all required SPEC sections\n`;
445
- context += `4. Focus on technical architecture and implementation plan\n`;
446
- break;
447
- case "engineer":
448
- context += `YOUR FIRST STEPS AS ENGINEER:\n`;
449
- context += `1. Call bob.manual.get to load the SPEC for implementation guidance\n`;
450
- context += `2. Extract implementation plan and update your TODO list\n`;
451
- context += `3. Use bob.code.search with phase: "engineer" to find affected files\n`;
452
- context += `4. Follow implementation plan and log progress with bob.manual.update\n`;
453
- break;
454
- case "debugger":
455
- context += `YOUR FIRST STEPS AS DEBUGGER:\n`;
456
- context += `1. Call bob.code.search with phase: "debugger" to analyze the issue\n`;
457
- context += `2. Research existing codebase for similar patterns and bugs\n`;
458
- context += `3. Apply minimal, safe fixes with user validation\n`;
459
- context += `4. Document findings with bob.manual.update (debug_log parameter)\n`;
460
- break;
461
- case "reviewer":
462
- context += `YOUR FIRST STEPS AS REVIEWER:\n`;
463
- context += `1. Call bob.code.search with phase: "reviewer" for vulnerability detection\n`;
464
- context += `2. Analyze security, performance, and quality issues\n`;
465
- context += `3. Create review manual with improvement recommendations\n`;
466
- context += `4. Provide severity-based findings and validation requirements\n`;
467
- break;
468
- }
469
- return context;
470
- }
471
- // Helper function to format role directive for Claude (Option A: Enhanced Tool Response)
472
- // Based on proven pattern from workflows-mcp-server (350+ GitHub stars)
473
- export function formatRoleDirective(mode, context) {
474
- const roleMap = {
475
- architect: {
476
- emoji: '📐',
477
- actions: [
478
- 'Call bob.code.search({ query: "...", phase: "architect" }) to research existing patterns',
479
- 'Build manual sections: executive_summary, product_specifications, architecture_analysis, implementation_plan, testing',
480
- 'Call bob.approval.request(spec_id, "spec_approval", ...) when ready for user review'
481
- ]
482
- },
483
- debugger: {
484
- emoji: '🐛',
485
- actions: [
486
- 'Call bob.code.search({ query: "...", phase: "debugger" }) - MANDATORY before diagnosis',
487
- 'Reproduce and analyze the issue systematically',
488
- 'Apply minimal, safe fix that addresses root cause',
489
- 'Update bob.manual.update with debug_log documenting findings'
490
- ]
491
- },
492
- engineer: {
493
- emoji: '⚙️',
494
- actions: [
495
- 'Call bob.manual.get(spec_id) to load the implementation plan',
496
- 'Create worktree if needed using bob.workflow.start',
497
- 'Implement tasks from plan sequentially (database → backend → frontend → integration)',
498
- 'Run tests and call bob.workflow.deploy when complete'
499
- ]
500
- },
501
- reviewer: {
502
- emoji: '🔍',
503
- actions: [
504
- 'Load context and code to review',
505
- 'Perform security, performance, and quality audit',
506
- 'Document findings in bob.manual.update with severity levels',
507
- 'Provide actionable recommendations'
508
- ]
509
- }
510
- };
511
- const role = roleMap[mode];
512
- if (!role) {
513
- return `Role ${mode} not recognized. Please use architect, engineer, debugger, or reviewer.`;
514
- }
515
- const problemText = context.problem ? context.problem.substring(0, 100) : 'See spec for details';
516
- const specText = context.spec_id || 'Will be created';
517
- const confidenceText = context.confidence ? Math.round(context.confidence * 100) : 0;
518
- return `
519
- ${role.emoji} ROLE ASSIGNMENT: ${mode.toUpperCase()}
520
-
521
- YOU are now executing as the ${mode.toUpperCase()} role. This is not routing to another agent - YOU must perform these actions:
522
-
523
- IMMEDIATE ACTIONS REQUIRED:
524
- ${role.actions.map((a, i) => `${i + 1}. ${a}`).join('\n')}
525
-
526
- CONTEXT:
527
- - Spec ID: ${specText}
528
- - Problem: ${problemText}
529
- - Confidence: ${confidenceText}%
530
-
531
- ⚠️ DO NOT wait for another agent. YOU are the ${mode}. Start with step 1 now.
532
- `.trim();
533
- }
534
- // Helper function to send dashboard updates without blocking main workflow
535
- async function sendDashboardUpdate(specId, event, data) {
536
- try {
537
- await dashboardUpdateHandler({
538
- spec_id: specId,
539
- event,
540
- data
541
- });
542
- }
543
- catch (error) {
544
- // Don't let dashboard update failures break the main workflow
545
- console.log(`Dashboard update failed (non-blocking): [${specId}] ${event}`, error instanceof Error ? error.message : String(error));
546
- }
547
- }
548
- // Search enforcement functions for Debugger
549
- function countSearchToolUsage(specId) {
550
- let searchCount = 0;
551
- // Check active operations for search tool calls
552
- const activeOps = mcpLogger.getActiveOperationsForSpec(specId);
553
- for (const operationId of activeOps) {
554
- const operation = mcpLogger.activeOperations.get(operationId);
555
- if (operation && operation.details.tool_name === 'bob.code.search') {
556
- searchCount++;
557
- }
558
- }
559
- // Also check completed tool calls in the log buffer (for recent completions)
560
- const logBuffer = mcpLogger.logBuffer || [];
561
- for (const entry of logBuffer) {
562
- if (entry.data &&
563
- entry.data.tool_name === 'bob.code.search' &&
564
- entry.data.spec_id === specId &&
565
- entry.data.event_type === 'tool_call_completed') {
566
- searchCount++;
567
- }
568
- }
569
- return searchCount;
570
- }
571
- export function validateDebuggerSearchUsage(specId, operation) {
572
- // Only enforce for debug operations (commits and debug_log updates)
573
- const debugOperations = ['debug_log', 'commit', 'fix_implementation'];
574
- if (!debugOperations.some(op => operation.toLowerCase().includes(op))) {
575
- return { valid: true };
576
- }
577
- const searchCount = countSearchToolUsage(specId);
578
- if (searchCount < 1) {
579
- return {
580
- valid: false,
581
- error: `Debugger must call bob.code.search at least once before ${operation}. Current search calls: ${searchCount}. Please perform search to understand the codebase before proceeding.`
582
- };
583
- }
584
- return { valid: true };
585
- }
586
- // 3-Gate Approval System Implementation
587
- export async function processApprovalGate(specId, gateNumber, context) {
588
- try {
589
- let approved = false;
590
- let nextStep = "";
591
- let message = "";
592
- let blockingReason;
593
- switch (gateNumber) {
594
- case 1: // Q&A Clarification Gate
595
- approved = validateGate1(context.confidence || 0, context.questions || []);
596
- if (approved) {
597
- nextStep = "spec_review";
598
- message = "Confidence threshold met (≥95%). Proceeding to architecture planning.";
599
- // Validate state transition
600
- await validateEnhancedStateTransition({ from: "questioning", to: "spec_review", spec_id: specId }, { confidence_threshold: true });
601
- }
602
- else {
603
- nextStep = "questioning";
604
- blockingReason = `Confidence too low (${Math.round((context.confidence || 0) * 100)}%) or questions remain`;
605
- message = `Gate 1 blocked: ${blockingReason}. Please provide clarifications.`;
606
- }
607
- break;
608
- case 2: // Spec Approval Gate
609
- approved = validateGate2(context.userApproval || false, context.sectionsComplete || []);
610
- if (approved) {
611
- nextStep = "approved";
612
- message = "Specification approved. Ready for implementation.";
613
- // Validate state transition
614
- await validateEnhancedStateTransition({ from: "spec_review", to: "approved", spec_id: specId }, { confidence_threshold: true, user_approval: true });
615
- }
616
- else {
617
- nextStep = "spec_review";
618
- blockingReason = "Specification not approved or missing required sections";
619
- message = `Gate 2 blocked: ${blockingReason}. Please complete spec and get approval.`;
620
- }
621
- break;
622
- case 3: // Implementation Approval Gate (with mandatory Reviewer)
623
- approved = validateGate3(context.testsPass || false, context.reviewerComplete || false, context.userApproval || false);
624
- if (approved) {
625
- nextStep = "completed";
626
- message = "Implementation approved after testing and review. Ready for deployment.";
627
- // Validate state transition
628
- await validateEnhancedStateTransition({ from: "user_review", to: "completed", spec_id: specId }, {
629
- confidence_threshold: true,
630
- reviewer_completed: true,
631
- user_approval: true
632
- });
633
- }
634
- else {
635
- nextStep = "user_review";
636
- const reasons = [];
637
- if (!context.testsPass)
638
- reasons.push("tests not passing");
639
- if (!context.reviewerComplete)
640
- reasons.push("reviewer not completed");
641
- if (!context.userApproval)
642
- reasons.push("user approval pending");
643
- blockingReason = reasons.join(", ");
644
- message = `Gate 3 blocked: ${blockingReason}. Please address issues before proceeding.`;
645
- }
646
- break;
647
- }
648
- // Log gate processing
649
- await mcpLogger.info(`Gate ${gateNumber} processed for ${specId}`, {
650
- approved,
651
- nextStep,
652
- blockingReason,
653
- gateNumber,
654
- spec_id: specId
655
- });
656
- return { approved, nextStep, message, blockingReason };
657
- }
658
- catch (error) {
659
- const errorMessage = `Gate ${gateNumber} validation failed: ${error instanceof Error ? error.message : String(error)}`;
660
- await mcpLogger.error(errorMessage, { specId, gateNumber, error });
661
- return {
662
- approved: false,
663
- nextStep: "error",
664
- message: errorMessage,
665
- blockingReason: "Validation error"
666
- };
667
- }
668
- }
669
- // Enhanced workflow router with 3-gate integration
670
- export async function routeWithApprovalGates(specId, currentState, context) {
671
- // Determine which gate to process based on current state
672
- let gateNumber = null;
673
- if (currentState === "questioning" && context.confidence >= 0.95) {
674
- gateNumber = 1;
675
- }
676
- else if (currentState === "spec_review" && context.requestingApproval) {
677
- gateNumber = 2;
678
- }
679
- else if (currentState === "implementation" && context.implementationComplete) {
680
- gateNumber = 3;
681
- }
682
- if (gateNumber) {
683
- const gateResult = await processApprovalGate(specId, gateNumber, context);
684
- if (gateResult.approved) {
685
- return {
686
- action: "proceed",
687
- nextMode: getNextMode(gateResult.nextStep),
688
- gateResult
689
- };
690
- }
691
- else {
692
- return {
693
- action: "await_approval",
694
- gateResult
695
- };
696
- }
697
- }
698
- // No gate processing needed, continue with normal routing
699
- return {
700
- action: "route",
701
- nextMode: context.suggestedMode
702
- };
703
- }
704
- function getNextMode(nextStep) {
705
- const modeMap = {
706
- "spec_review": "architect",
707
- "approved": "engineer",
708
- "user_review": "reviewer",
709
- "completed": "none"
710
- };
711
- return modeMap[nextStep] || "architect";
712
- }
713
- // Mandatory Reviewer Integration (TASK-006)
714
- export async function enforceReviewerBeforeGate3(specId, context) {
715
- // Check if implementation is complete and ready for Gate 3
716
- if (!context.implementationComplete) {
717
- return {
718
- requiresReviewer: false,
719
- reviewerComplete: false,
720
- nextAction: "continue_implementation"
721
- };
722
- }
723
- // Check if tests are passing (required before reviewer)
724
- if (!context.testsPass) {
725
- return {
726
- requiresReviewer: false,
727
- reviewerComplete: false,
728
- nextAction: "fix_tests_first"
729
- };
730
- }
731
- // Check if reviewer has already completed their work
732
- const reviewerComplete = await checkReviewerCompletion(specId);
733
- if (!reviewerComplete) {
734
- // Auto-route to Reviewer with context
735
- await mcpLogger.info(`Auto-routing to Reviewer before Gate 3 for ${specId}`, {
736
- spec_id: specId,
737
- reason: "mandatory_review_before_gate3",
738
- tests_passing: context.testsPass
739
- });
740
- // Send dashboard update
741
- await sendDashboardUpdate(specId, "auto_routing_reviewer", {
742
- reason: "Gate 3 requires review",
743
- tests_status: "passing"
744
- });
745
- return {
746
- requiresReviewer: true,
747
- reviewerComplete: false,
748
- nextAction: "route_to_reviewer"
749
- };
750
- }
751
- // Reviewer is complete, ready for Gate 3
752
- return {
753
- requiresReviewer: false,
754
- reviewerComplete: true,
755
- nextAction: "proceed_to_gate3"
756
- };
757
- }
758
- async function checkReviewerCompletion(specId) {
759
- try {
760
- // Check for reviewer completion in the spec logs
761
- const spec = await specGetHandler({ spec_id: specId });
762
- // Look for reviewer completion in execution logs
763
- const reviewerLogs = spec.execution_logs?.filter((log) => log.engineer?.includes("REVIEWER") || log.action?.includes("review")) || [];
764
- // Also check debug logs for review findings
765
- const reviewFindings = spec.debug_logs?.filter((log) => log.issue?.includes("review") || log.root_cause?.includes("review")) || [];
766
- return reviewerLogs.length > 0 || reviewFindings.length > 0;
767
- }
768
- catch (error) {
769
- await mcpLogger.warning(`Failed to check reviewer completion for ${specId}`, { error });
770
- // Default to requiring review if we can't determine completion
771
- return false;
772
- }
773
- }
774
- // Enhanced implementation complete handler with reviewer enforcement
775
- export async function handleImplementationComplete(specId, context) {
776
- // Step 1: Check if tests are passing
777
- if (!context.testsPass) {
778
- return {
779
- action: "fix_tests",
780
- message: "Tests must pass before proceeding to review and approval. Please fix failing tests.",
781
- };
782
- }
783
- // Step 2: Start dev server (moved from workflow.start)
784
- if (!context.devServerStarted) {
785
- await mcpLogger.info(`Starting dev server after tests pass for ${specId}`, { spec_id: specId });
786
- // This would integrate with the server startup logic that was removed from workflow.start
787
- await sendDashboardUpdate(specId, "starting_preview_server", {
788
- reason: "tests_passed",
789
- next_step: "review_and_approval"
790
- });
791
- return {
792
- action: "start_server",
793
- message: "Tests passed! Starting preview server before review and approval.",
794
- };
795
- }
796
- // Step 3: Enforce mandatory reviewer
797
- const reviewerCheck = await enforceReviewerBeforeGate3(specId, context);
798
- if (reviewerCheck.requiresReviewer) {
799
- return {
800
- action: "route",
801
- nextMode: "reviewer",
802
- message: "Implementation complete and tests passing. Routing to Reviewer for mandatory review before final approval.",
803
- };
804
- }
805
- if (reviewerCheck.nextAction === "fix_tests_first") {
806
- return {
807
- action: "fix_tests",
808
- message: "Please ensure all tests are passing before proceeding to review.",
809
- };
810
- }
811
- // Step 4: Process Gate 3 (all requirements met)
812
- const gateResult = await processApprovalGate(specId, 3, {
813
- ...context,
814
- reviewerComplete: reviewerCheck.reviewerComplete
815
- });
816
- if (gateResult.approved) {
817
- return {
818
- action: "complete",
819
- message: "Implementation approved! Ready for deployment.",
820
- gateResult
821
- };
822
- }
823
- else {
824
- return {
825
- action: "await_approval",
826
- message: gateResult.message,
827
- requiresApproval: true,
828
- gateResult
829
- };
830
- }
831
- }
832
- //# sourceMappingURL=orchestratorTools.js.map