bobs-workshop 0.3.3 → 3.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 (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 +388 -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 +51 -0
  42. package/package.json +34 -66
  43. package/postinstall.js +193 -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 +466 -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 +60 -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
@@ -0,0 +1,190 @@
1
+ import { tool } from "@opencode-ai/plugin/tool";
2
+ const MANUAL_TEMPLATE = `# 📘 MANUAL: [Feature Name]
3
+
4
+ > Created: MAN-YYMMDD-[feature-name].md
5
+
6
+ ## 📊 Executive Summary
7
+
8
+ High-level overview of what we're building and why.
9
+
10
+ **Example:**
11
+ - What problem does this solve?
12
+ - Who are the users?
13
+ - What's the success criteria?
14
+ - What are the core features?
15
+
16
+ ---
17
+
18
+ ## 📝 Product Specifications
19
+
20
+ Detailed requirements and acceptance criteria.
21
+
22
+ **Example:**
23
+ - User stories / Use cases
24
+ - Functional requirements
25
+ - Non-functional requirements (performance, security, etc.)
26
+ - Edge cases and error handling
27
+ - Success metrics
28
+
29
+ ---
30
+
31
+ ## đŸ—ī¸ Architecture Analysis
32
+
33
+ Technical design decisions and system architecture.
34
+
35
+ **Example:**
36
+ - System diagram / architecture overview
37
+ - Data models and schemas
38
+ - API endpoints and contracts
39
+ - Database design (indexes, relationships)
40
+ - Authentication/authorization approach
41
+ - Technology choices and trade-offs
42
+ - Security considerations
43
+
44
+ ---
45
+
46
+ ## 🚀 Implementation Plan
47
+
48
+ Breakdown of tasks with dependencies.
49
+
50
+ **Example:**
51
+ 1. Setup and scaffolding
52
+ 2. Database schema migrations
53
+ 3. Core business logic
54
+ 4. API endpoint implementation
55
+ 5. Frontend components
56
+ 6. Integration testing
57
+ 7. Documentation
58
+
59
+ Mark completed tasks with ✅, in-progress with 🔄, blocked with đŸšĢ
60
+
61
+ ---
62
+
63
+ ## 📈 Execution Logs
64
+
65
+ Chronological progress as tasks are completed.
66
+
67
+ **Format:**
68
+ \`\`\`
69
+ [YYYY-MM-DD HH:MM] - Agent: task description
70
+ - Output: results / artifacts
71
+ - Files modified: list of files
72
+ - Dependencies: what blocked this or what it enables
73
+ \`\`\`
74
+
75
+ ---
76
+
77
+ ## 🔍 Review Notes
78
+
79
+ Findings from code reviews, architectural reviews, or peer reviews.
80
+
81
+ **Example:**
82
+ - Code quality observations
83
+ - Performance concerns
84
+ - Security vulnerabilities
85
+ - Suggestions for improvements
86
+ - Action items from reviews
87
+
88
+ ---
89
+
90
+ ## 🐛 Debug Logs
91
+
92
+ Troubleshooting sessions and root cause analysis.
93
+
94
+ **Format:**
95
+ \`\`\`
96
+ [YYYY-MM-DD HH:MM] - Issue description
97
+ - Symptoms: what went wrong
98
+ - Investigation: steps taken
99
+ - Root cause: underlying problem
100
+ - Resolution: fix applied
101
+ - Prevention: how to avoid recurrence
102
+ \`\`\`
103
+
104
+ ---
105
+
106
+ ## ✅ Verification Logs
107
+
108
+ Test results and quality assurance checks.
109
+
110
+ **Example:**
111
+ - Unit test results
112
+ - Integration test results
113
+ - E2E test results
114
+ - Performance benchmarks
115
+ - Security scan results
116
+ - Manual QA checklists
117
+
118
+ Each verification should include:
119
+ - PASS/FAIL status
120
+ - Evidence (screenshots, logs, metrics)
121
+ - Coverage percentage
122
+ - Blockers for release
123
+
124
+ ---
125
+
126
+ ## 🤝 Agent Handoffs
127
+
128
+ Context transfers between different agents.
129
+
130
+ **Format:**
131
+ \`\`\`
132
+ [YYYY-MM-DD HH:MM] - alice → bob
133
+ - Context: architectural decisions, design docs
134
+ - Artifacts: MAN-xxx.md, schema.sql
135
+ - Next steps: implement authentication flow
136
+ \`\`\`
137
+
138
+ This ensures smooth handoffs between agents and maintains continuity across sessions.
139
+ `;
140
+ const ManualUpdateTool = tool({
141
+ description: "Update a specific section in a MANUAL file. Creates file/section if missing.",
142
+ args: {
143
+ manual_path: tool.schema.string().describe("Path to MANUAL file (e.g., manuals/MAN-260127-auth.md)"),
144
+ section: tool.schema.string().describe("Section header to update (e.g., '📊 Executive Summary', '📈 Execution Logs')"),
145
+ content: tool.schema.string().describe("Content to append to the section"),
146
+ create_if_missing: tool.schema.boolean().default(true)
147
+ .describe("Create section if it doesn't exist (default: true)"),
148
+ },
149
+ async execute(args) {
150
+ const { readFileSync, writeFileSync, existsSync, mkdirSync } = await import("node:fs");
151
+ const { dirname } = await import("node:path");
152
+ const manualPath = args.manual_path;
153
+ if (!manualPath.match(/^manuals\/MAN-\d{6}-.+\.md$/)) {
154
+ return `❌ Invalid path. Expected format: manuals/MAN-YYMMDD-<feature>.md`;
155
+ }
156
+ const manualsDir = dirname(manualPath);
157
+ if (!existsSync(manualsDir)) {
158
+ mkdirSync(manualsDir, { recursive: true });
159
+ }
160
+ let content = "";
161
+ if (existsSync(manualPath)) {
162
+ content = readFileSync(manualPath, "utf8");
163
+ }
164
+ else {
165
+ content = MANUAL_TEMPLATE;
166
+ writeFileSync(manualPath, content, "utf8");
167
+ }
168
+ const lines = content.split('\n');
169
+ let sectionIndex = lines.findIndex(l => l.trim() === args.section);
170
+ if (sectionIndex === -1) {
171
+ if (!args.create_if_missing) {
172
+ return `❌ Section '${args.section}' not found in ${manualPath}`;
173
+ }
174
+ content = `${content}\n${args.section}\n${args.content}\n`;
175
+ }
176
+ else {
177
+ const insertPosition = sectionIndex + 1;
178
+ if (lines[insertPosition] && !lines[insertPosition].startsWith('##')) {
179
+ lines[insertPosition] = `${lines[insertPosition]}\n${args.content}`;
180
+ }
181
+ else {
182
+ lines.splice(insertPosition, 0, args.content);
183
+ }
184
+ content = lines.join('\n');
185
+ }
186
+ writeFileSync(manualPath, content, "utf8");
187
+ return `✅ Updated section '${args.section}' in ${manualPath}`;
188
+ },
189
+ });
190
+ export default ManualUpdateTool;
@@ -0,0 +1,4 @@
1
+ import { type ToolDefinition } from "@opencode-ai/plugin/tool";
2
+ declare const VerifyManualTool: ToolDefinition;
3
+ export default VerifyManualTool;
4
+ //# sourceMappingURL=verify-manual.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verify-manual.d.ts","sourceRoot":"","sources":["../../../src/tools/manual/verify-manual.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,KAAK,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAErE,QAAA,MAAM,gBAAgB,EAAE,cAuDtB,CAAC;AAEH,eAAe,gBAAgB,CAAC"}
@@ -0,0 +1,51 @@
1
+ import { tool } from "@opencode-ai/plugin/tool";
2
+ const VerifyManualTool = tool({
3
+ description: "Run bob-rev verification in background for a MANUAL",
4
+ args: {
5
+ manual_path: tool.schema.string().describe("Path to MANUAL file (e.g., manuals/MAN-260127-auth.md)"),
6
+ },
7
+ async execute(args, context) {
8
+ const { client, directory, sessionID } = context;
9
+ const createResult = await client.session.create({
10
+ body: {
11
+ parentID: sessionID,
12
+ title: `Verification: ${args.manual_path.split('/').pop()}`,
13
+ },
14
+ query: { directory },
15
+ });
16
+ const createData = createResult;
17
+ if (createData.error) {
18
+ throw new Error(`Failed to create verification session: ${createData.error}`);
19
+ }
20
+ const { readFileSync, existsSync } = await import("node:fs");
21
+ const { join } = await import("node:path");
22
+ let manualContent = "";
23
+ if (existsSync(args.manual_path)) {
24
+ manualContent = readFileSync(args.manual_path, "utf8");
25
+ // Sanitize content to prevent JSON parsing issues with kimi model
26
+ manualContent = manualContent
27
+ .replace(/[\x00-\x08\x0B-\x0C\x0E-\x1F]/g, '') // Remove control chars except \n, \r, \t
28
+ .replace(/\u2028/g, '\n') // Replace line separator with newline
29
+ .replace(/\u2029/g, '\n'); // Replace paragraph separator with newline
30
+ }
31
+ const skillPath = join(directory, ".opencode", "agent", "bobs-workshop", "bob-rev.md");
32
+ let agentPrompt = "You are bob-rev, a reviewer agent that verifies implementation against MANUAL requirements.";
33
+ if (existsSync(skillPath)) {
34
+ agentPrompt = readFileSync(skillPath, "utf8");
35
+ }
36
+ await client.session.prompt({
37
+ path: { id: createData.data.id },
38
+ body: {
39
+ agent: "bob-rev",
40
+ system: `${agentPrompt}\n\n## MANUAL to Verify:\n${manualContent}`,
41
+ tools: {
42
+ task: false,
43
+ delegate_task: false,
44
+ },
45
+ parts: [{ type: "text", text: "Verify this MANUAL and provide PASS/FAIL decision with reasoning." }],
46
+ },
47
+ });
48
+ return `✅ Started verification for ${args.manual_path} in session ${createData.data.id}`;
49
+ },
50
+ });
51
+ export default VerifyManualTool;
package/package.json CHANGED
@@ -1,86 +1,54 @@
1
1
  {
2
2
  "name": "bobs-workshop",
3
- "version": "0.3.3",
4
- "description": "Bob's Workshop — agentic development helper with observability, guard rails, research, and review capabilities",
3
+ "version": "3.1.1",
4
+ "description": "MANUAL-driven development with background agents for OpenCode",
5
5
  "type": "module",
6
- "main": "dist/index.js",
6
+ "main": "./dist/plugins/bobs-workshop.js",
7
+ "types": "./dist/plugins/bobs-workshop.d.ts",
8
+ "files": [
9
+ "src/agents",
10
+ "src/skills",
11
+ "src/tools",
12
+ "src/plugins",
13
+ "dist/tools",
14
+ "dist/plugins",
15
+ "config",
16
+ "postinstall.js",
17
+ "uninstall.js"
18
+ ],
7
19
  "bin": {
8
- "bobs-mcp": "dist/index.js",
9
- "bobs": "bin/bobs-mcp.js"
20
+ "bobs-workshop": "bin/bobs-workshop.js"
10
21
  },
11
22
  "scripts": {
12
- "dev": "tsx src/index.ts",
13
- "build": "tsc",
14
- "start": "node dist/index.js",
15
- "test": "jest",
16
- "lint": "eslint src --ext .ts",
17
- "dashboard": "node dist/dashboard/server.js",
18
- "postinstall": "node scripts/install-search-tools.js && node scripts/init-workspace.js",
19
- "install-search-tools": "node scripts/install-search-tools.js",
20
- "cleanup:system-logs": "tsx scripts/cleanup-system-logs.ts"
23
+ "build": "tsc && node scripts/copy-plugin.js",
24
+ "prepublishOnly": "node scripts/prepublish.js",
25
+ "postinstall": "node postinstall.js",
26
+ "test": "bun test",
27
+ "test:watch": "bun test --watch"
21
28
  },
22
29
  "dependencies": {
23
- "@modelcontextprotocol/sdk": "^1.0.0",
24
- "@types/multer": "^2.0.0",
25
- "bobs-workshop": "^0.2.0",
26
- "chokidar": "^4.0.3",
27
- "express": "^4.x",
28
- "fs-extra": "^11.x",
29
- "glob": "^10.3.10",
30
- "lru-cache": "^10.1.0",
31
- "minimatch": "^9.0.3",
32
- "multer": "^2.0.2",
33
- "simple-git": "^3.x",
34
- "ts-morph": "^23.0.0",
35
- "uuid": "^9.x",
36
- "zod": "^3.x",
37
- "@vscode/ripgrep": "^1.15.14"
30
+ "@opencode-ai/plugin": "^1.1.36",
31
+ "jsonc-parser": "^3.2.1"
38
32
  },
39
33
  "devDependencies": {
40
- "@types/chokidar": "^1.7.5",
41
- "@types/express": "^5.0.3",
42
- "@types/fs-extra": "^11.0.4",
43
- "@types/jest": "^29.x",
44
- "@types/node": "^20.x",
45
- "@types/uuid": "^10.0.0",
46
- "eslint": "^8.x",
47
- "jest": "^29.x",
48
- "ts-jest": "^29.x",
49
- "tsx": "^4.x",
50
- "typescript": "^5.x"
34
+ "@types/node": "^20.0.0",
35
+ "typescript": "^5.7.2"
51
36
  },
52
37
  "keywords": [
53
- "mcp",
54
- "model-context-protocol",
55
- "developer-tools",
56
- "workshop",
57
- "cli",
58
- "dashboard",
59
- "spec-driven",
60
- "development",
61
- "typescript",
62
- "developer-experience"
38
+ "opencode",
39
+ "plugin",
40
+ "agents",
41
+ "manual-driven",
42
+ "background-tasks"
63
43
  ],
64
- "author": "Bob's Workshop Contributors",
44
+ "author": "pwnk77",
65
45
  "license": "MIT",
66
46
  "repository": {
67
47
  "type": "git",
68
- "url": "git+https://github.com/your-org/bobs-workshop.git"
48
+ "url": "git+https://github.com/pwnk77/bobs-workshop.git"
69
49
  },
70
- "homepage": "https://github.com/your-org/bobs-workshop#readme",
71
50
  "bugs": {
72
- "url": "https://github.com/your-org/bobs-workshop/issues"
51
+ "url": "https://github.com/pwnk77/bobs-workshop/issues"
73
52
  },
74
- "engines": {
75
- "node": ">=18.0.0"
76
- },
77
- "files": [
78
- "dist/**/*",
79
- "bin/**/*",
80
- "scripts/**/*",
81
- "public/**/*",
82
- "README.md",
83
- "LICENSE",
84
- "Claude.md"
85
- ]
53
+ "homepage": "https://github.com/pwnk77/bobs-workshop#readme"
86
54
  }
package/postinstall.js ADDED
@@ -0,0 +1,193 @@
1
+ /**
2
+ * postinstall.js — runs only when this package is installed as a dependency in a repo.
3
+ * Skips when: npm install inside bobs-workshop itself, or global npm update (e.g. npm update -g @opencode/cli).
4
+ */
5
+ import jsonc, { parse } from 'jsonc-parser';
6
+ import { readFileSync, writeFileSync, existsSync, mkdirSync, copyFileSync, cpSync, readdirSync } from 'fs';
7
+ import { dirname, join } from 'path';
8
+ import { fileURLToPath } from 'url';
9
+
10
+ const __dirname = dirname(fileURLToPath(import.meta.url));
11
+
12
+ const PACKAGE_NAME = 'bobs-workshop';
13
+
14
+ /**
15
+ * Only run when bobs-workshop is installed as a dependency in this repo (npm install at repo level).
16
+ * Skip when: global npm update, or running from within bobs-workshop repo itself.
17
+ */
18
+ function isInstalledAsDependencyInThisRepo() {
19
+ // Use INIT_CWD which npm sets to the directory where 'npm install' was invoked
20
+ // process.cwd() returns the package directory (node_modules/bobs-workshop/) during postinstall
21
+ const projectRoot = process.env.INIT_CWD || process.cwd();
22
+ const pkgPath = join(projectRoot, 'package.json');
23
+ if (!existsSync(pkgPath)) return false;
24
+ let pkg;
25
+ try {
26
+ pkg = JSON.parse(readFileSync(pkgPath, 'utf8'));
27
+ } catch {
28
+ return false;
29
+ }
30
+ const deps = { ...pkg.dependencies, ...pkg.devDependencies };
31
+ return typeof deps[PACKAGE_NAME] === 'string';
32
+ }
33
+
34
+ function checkConflicts(opencodeDir) {
35
+ const conflicts = [];
36
+
37
+ const agentsDir = join(opencodeDir, 'agents');
38
+ if (existsSync(agentsDir)) {
39
+ const ourAgents = ['alice.md', 'bob.md', 'bob-rev.md', 'trace.md', 'bob-send.md'];
40
+ const existingAgents = readdirSync(agentsDir).filter(f => f.endsWith('.md'));
41
+
42
+ existingAgents.forEach(agent => {
43
+ if (ourAgents.includes(agent)) {
44
+ conflicts.push({ path: join(agentsDir, agent), type: 'agent' });
45
+ }
46
+ });
47
+ }
48
+
49
+ const skillsDir = join(opencodeDir, 'skills');
50
+ if (existsSync(skillsDir)) {
51
+ const skillNames = ['architecture', 'exploration', 'api-patterns',
52
+ 'brainstorming', 'clean-code', 'code-review-checklist',
53
+ 'database-design', 'frontend-ui-ux', 'git-master',
54
+ 'performance', 'plan-writing', 'security', 'simplification',
55
+ 'systematic-debugging', 'testing-patterns', 'verification'];
56
+
57
+ skillNames.forEach(skill => {
58
+ const skillPath = join(skillsDir, skill);
59
+ if (existsSync(skillPath)) {
60
+ conflicts.push({ path: skillPath, type: 'skill' });
61
+ }
62
+ });
63
+ }
64
+
65
+ return conflicts;
66
+ }
67
+
68
+ function postinstall() {
69
+ if (!isInstalledAsDependencyInThisRepo()) {
70
+ return; // Not a repo that depends on bobs-workshop (e.g. global update or bobs-workshop repo itself)
71
+ }
72
+
73
+ // Use INIT_CWD to get the actual project directory where npm install was run
74
+ const projectRoot = process.env.INIT_CWD || process.cwd();
75
+ const opencodeDir = join(projectRoot, '.opencode');
76
+
77
+ console.log('🔧 Installing bobs-workshop...');
78
+
79
+ const conflicts = checkConflicts(opencodeDir);
80
+ if (conflicts.length > 0) {
81
+ console.error('❌ Installation aborted: Conflicts detected');
82
+ console.error('');
83
+ console.error('The following items already exist and would be overwritten:');
84
+ conflicts.forEach(c => console.error(` - ${c.path} (${c.type})`));
85
+ console.error('');
86
+ console.error('Please rename these items to resolve conflicts:');
87
+ console.error(' Agents: Rename .opencode/agents/<name>.md files');
88
+ console.error(' Skills: Rename .opencode/skills/<name>/SKILL.md directories');
89
+ console.error('');
90
+ console.error('Run npm install again after resolving conflicts.');
91
+ process.exit(1);
92
+ }
93
+
94
+ const dirsToCreate = [
95
+ join(opencodeDir, 'plugins/bobs-workshop'),
96
+ join(opencodeDir, 'agents'),
97
+ join(opencodeDir, 'tools/bobs-workshop'),
98
+ join(projectRoot, 'manuals')
99
+ ];
100
+
101
+ dirsToCreate.forEach(dir => {
102
+ if (!existsSync(dir)) {
103
+ mkdirSync(dir, { recursive: true });
104
+ console.log(`✅ Created: ${dir}`);
105
+ }
106
+ });
107
+
108
+ const pluginSrc = join(__dirname, 'dist/plugins/bobs-workshop.js');
109
+ const pluginDest = join(opencodeDir, 'plugins/bobs-workshop/plugin.js');
110
+
111
+ if (existsSync(pluginSrc)) {
112
+ copyFileSync(pluginSrc, pluginDest);
113
+ console.log(`✅ Copied plugin to: ${pluginDest}`);
114
+ } else {
115
+ console.warn('âš ī¸ Plugin file not found. Did you run npm run build?');
116
+ }
117
+
118
+ const agentSrcDir = join(__dirname, 'src/agents');
119
+ const agentDestDir = join(opencodeDir, 'agents');
120
+
121
+ if (existsSync(agentSrcDir)) {
122
+ cpSync(agentSrcDir, agentDestDir, { recursive: true });
123
+ console.log('✅ Copied agent definitions');
124
+ }
125
+
126
+ const skillSrcDir = join(__dirname, 'src/skills');
127
+ const skillDestDir = join(opencodeDir, 'skills');
128
+
129
+ if (existsSync(skillSrcDir)) {
130
+ cpSync(skillSrcDir, skillDestDir, { recursive: true });
131
+ console.log('✅ Copied skill definitions');
132
+ }
133
+
134
+ const toolsSrcDir = join(__dirname, 'dist/tools');
135
+ const toolsDestDir = join(opencodeDir, 'tools/bobs-workshop');
136
+
137
+ if (existsSync(toolsSrcDir)) {
138
+ cpSync(toolsSrcDir, toolsDestDir, { recursive: true });
139
+ console.log('✅ Copied tool definitions');
140
+ }
141
+
142
+ const configPath = join(opencodeDir, 'opencode.jsonc');
143
+ const configContent = existsSync(configPath)
144
+ ? readFileSync(configPath, 'utf8')
145
+ : '{}';
146
+
147
+ let config;
148
+ try {
149
+ config = parse(configContent, { allowTrailingComma: true });
150
+ } catch (err) {
151
+ console.warn(`âš ī¸ Could not parse opencode.jsonc: ${err.message}`);
152
+ config = {};
153
+ }
154
+
155
+ const agentsConfig = JSON.parse(readFileSync(
156
+ join(__dirname, 'config/agents.json'), 'utf8'
157
+ ));
158
+
159
+ if (!config.agent) config.agent = {};
160
+ let agentsAdded = 0;
161
+
162
+ Object.entries(agentsConfig).forEach(([name, agentDef]) => {
163
+ if (!config.agent[name]) {
164
+ config.agent[name] = agentDef;
165
+ console.log(`✅ Added agent: ${name}`);
166
+ agentsAdded++;
167
+ } else {
168
+ console.log(`â­ī¸ Agent ${name} already exists, skipping`);
169
+ }
170
+ });
171
+
172
+ if (agentsAdded === 0) {
173
+ console.log('â„šī¸ All agents already configured');
174
+ }
175
+
176
+ const newConfig = JSON.stringify(config, null, 2);
177
+ writeFileSync(configPath, newConfig);
178
+
179
+ console.log('✅ bobs-workshop installed successfully!');
180
+ console.log('');
181
+ console.log('Next steps:');
182
+ console.log(' 1. Review your agents in .opencode/opencode.jsonc');
183
+ console.log(' 2. Create your first MANUAL: manuals/MAN-260128-feature.md');
184
+ console.log(' 3. Start using background_agent, manual_update, verify_manual tools');
185
+ }
186
+
187
+ try {
188
+ postinstall();
189
+ } catch (error) {
190
+ console.error('❌ Installation failed:', error.message);
191
+ console.error(error.stack);
192
+ process.exit(1);
193
+ }