workspace-maxxing 0.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 (198) hide show
  1. package/.agents/skills/workspace-maxxing/.workspace-templates/CONTEXT.md +44 -0
  2. package/.agents/skills/workspace-maxxing/.workspace-templates/SYSTEM.md +44 -0
  3. package/.agents/skills/workspace-maxxing/.workspace-templates/references/anti-patterns.md +16 -0
  4. package/.agents/skills/workspace-maxxing/.workspace-templates/references/iron-laws.md +26 -0
  5. package/.agents/skills/workspace-maxxing/.workspace-templates/references/reporting-format.md +52 -0
  6. package/.agents/skills/workspace-maxxing/.workspace-templates/scripts/benchmark.ts +171 -0
  7. package/.agents/skills/workspace-maxxing/.workspace-templates/scripts/dispatch.ts +473 -0
  8. package/.agents/skills/workspace-maxxing/.workspace-templates/scripts/generate-tests.ts +158 -0
  9. package/.agents/skills/workspace-maxxing/.workspace-templates/scripts/install-tool.ts +82 -0
  10. package/.agents/skills/workspace-maxxing/.workspace-templates/scripts/iterate.ts +265 -0
  11. package/.agents/skills/workspace-maxxing/.workspace-templates/scripts/orchestrator.ts +539 -0
  12. package/.agents/skills/workspace-maxxing/.workspace-templates/scripts/scaffold.ts +282 -0
  13. package/.agents/skills/workspace-maxxing/.workspace-templates/scripts/validate.ts +452 -0
  14. package/.agents/skills/workspace-maxxing/.workspace-templates/skills/architecture/SKILL.md +95 -0
  15. package/.agents/skills/workspace-maxxing/.workspace-templates/skills/fixer/SKILL.md +109 -0
  16. package/.agents/skills/workspace-maxxing/.workspace-templates/skills/iteration/SKILL.md +89 -0
  17. package/.agents/skills/workspace-maxxing/.workspace-templates/skills/prompt-engineering/SKILL.md +87 -0
  18. package/.agents/skills/workspace-maxxing/.workspace-templates/skills/research/SKILL.md +94 -0
  19. package/.agents/skills/workspace-maxxing/.workspace-templates/skills/testing/SKILL.md +89 -0
  20. package/.agents/skills/workspace-maxxing/.workspace-templates/skills/tooling/SKILL.md +87 -0
  21. package/.agents/skills/workspace-maxxing/.workspace-templates/skills/validation/SKILL.md +103 -0
  22. package/.agents/skills/workspace-maxxing/.workspace-templates/skills/worker/SKILL.md +79 -0
  23. package/.agents/skills/workspace-maxxing/.workspace-templates/workspace/00-meta/CONTEXT.md +6 -0
  24. package/.agents/skills/workspace-maxxing/.workspace-templates/workspace/00-meta/execution-log.md +27 -0
  25. package/.agents/skills/workspace-maxxing/.workspace-templates/workspace/01-input/CONTEXT.md +29 -0
  26. package/.agents/skills/workspace-maxxing/.workspace-templates/workspace/02-process/CONTEXT.md +29 -0
  27. package/.agents/skills/workspace-maxxing/.workspace-templates/workspace/03-output/CONTEXT.md +29 -0
  28. package/.agents/skills/workspace-maxxing/.workspace-templates/workspace/README.md +14 -0
  29. package/.agents/skills/workspace-maxxing/SKILL.md +312 -0
  30. package/.agents/skills/workspace-maxxing/scripts/benchmark.ts +171 -0
  31. package/.agents/skills/workspace-maxxing/scripts/dispatch.ts +473 -0
  32. package/.agents/skills/workspace-maxxing/scripts/generate-tests.ts +158 -0
  33. package/.agents/skills/workspace-maxxing/scripts/install-tool.ts +82 -0
  34. package/.agents/skills/workspace-maxxing/scripts/iterate.ts +265 -0
  35. package/.agents/skills/workspace-maxxing/scripts/orchestrator.ts +539 -0
  36. package/.agents/skills/workspace-maxxing/scripts/scaffold.ts +282 -0
  37. package/.agents/skills/workspace-maxxing/scripts/validate.ts +452 -0
  38. package/README.md +144 -0
  39. package/dist/agent-creator.d.ts +9 -0
  40. package/dist/agent-creator.d.ts.map +1 -0
  41. package/dist/agent-creator.js +199 -0
  42. package/dist/agent-creator.js.map +1 -0
  43. package/dist/agent-iterator.d.ts +38 -0
  44. package/dist/agent-iterator.d.ts.map +1 -0
  45. package/dist/agent-iterator.js +327 -0
  46. package/dist/agent-iterator.js.map +1 -0
  47. package/dist/index.d.ts +3 -0
  48. package/dist/index.d.ts.map +1 -0
  49. package/dist/index.js +197 -0
  50. package/dist/index.js.map +1 -0
  51. package/dist/install.d.ts +18 -0
  52. package/dist/install.d.ts.map +1 -0
  53. package/dist/install.js +117 -0
  54. package/dist/install.js.map +1 -0
  55. package/dist/platforms/claude.d.ts +7 -0
  56. package/dist/platforms/claude.d.ts.map +1 -0
  57. package/dist/platforms/claude.js +70 -0
  58. package/dist/platforms/claude.js.map +1 -0
  59. package/dist/platforms/copilot.d.ts +7 -0
  60. package/dist/platforms/copilot.d.ts.map +1 -0
  61. package/dist/platforms/copilot.js +75 -0
  62. package/dist/platforms/copilot.js.map +1 -0
  63. package/dist/platforms/gemini.d.ts +7 -0
  64. package/dist/platforms/gemini.d.ts.map +1 -0
  65. package/dist/platforms/gemini.js +81 -0
  66. package/dist/platforms/gemini.js.map +1 -0
  67. package/dist/platforms/index.d.ts +8 -0
  68. package/dist/platforms/index.d.ts.map +1 -0
  69. package/dist/platforms/index.js +41 -0
  70. package/dist/platforms/index.js.map +1 -0
  71. package/dist/platforms/opencode.d.ts +7 -0
  72. package/dist/platforms/opencode.d.ts.map +1 -0
  73. package/dist/platforms/opencode.js +70 -0
  74. package/dist/platforms/opencode.js.map +1 -0
  75. package/dist/scripts/benchmark.d.ts +20 -0
  76. package/dist/scripts/benchmark.d.ts.map +1 -0
  77. package/dist/scripts/benchmark.js +170 -0
  78. package/dist/scripts/benchmark.js.map +1 -0
  79. package/dist/scripts/dispatch.d.ts +32 -0
  80. package/dist/scripts/dispatch.d.ts.map +1 -0
  81. package/dist/scripts/dispatch.js +386 -0
  82. package/dist/scripts/dispatch.js.map +1 -0
  83. package/dist/scripts/generate-tests.d.ts +11 -0
  84. package/dist/scripts/generate-tests.d.ts.map +1 -0
  85. package/dist/scripts/generate-tests.js +118 -0
  86. package/dist/scripts/generate-tests.js.map +1 -0
  87. package/dist/scripts/install-tool.d.ts +8 -0
  88. package/dist/scripts/install-tool.d.ts.map +1 -0
  89. package/dist/scripts/install-tool.js +98 -0
  90. package/dist/scripts/install-tool.js.map +1 -0
  91. package/dist/scripts/iterate.d.ts +44 -0
  92. package/dist/scripts/iterate.d.ts.map +1 -0
  93. package/dist/scripts/iterate.js +260 -0
  94. package/dist/scripts/iterate.js.map +1 -0
  95. package/dist/scripts/orchestrator.d.ts +40 -0
  96. package/dist/scripts/orchestrator.d.ts.map +1 -0
  97. package/dist/scripts/orchestrator.js +378 -0
  98. package/dist/scripts/orchestrator.js.map +1 -0
  99. package/dist/scripts/scaffold.d.ts +8 -0
  100. package/dist/scripts/scaffold.d.ts.map +1 -0
  101. package/dist/scripts/scaffold.js +279 -0
  102. package/dist/scripts/scaffold.js.map +1 -0
  103. package/dist/scripts/validate.d.ts +11 -0
  104. package/dist/scripts/validate.d.ts.map +1 -0
  105. package/dist/scripts/validate.js +472 -0
  106. package/dist/scripts/validate.js.map +1 -0
  107. package/docs/superpowers/plans/2026-04-07-autonomous-iteration-plan.md +1123 -0
  108. package/docs/superpowers/plans/2026-04-07-autonomous-iteration-sub-agent-batches.md +1923 -0
  109. package/docs/superpowers/plans/2026-04-07-autonomous-workflow-sub-skill-plan.md +1505 -0
  110. package/docs/superpowers/plans/2026-04-07-benchmarking-multi-agent-plan.md +854 -0
  111. package/docs/superpowers/plans/2026-04-07-workspace-builder-logic-plan.md +1426 -0
  112. package/docs/superpowers/plans/2026-04-07-workspace-maxxing-plan.md +1299 -0
  113. package/docs/superpowers/plans/2026-04-08-session-294c-subagent-invocation-plan.md +320 -0
  114. package/docs/superpowers/plans/2026-04-08-workflow-prompt-hardening-plan.md +1025 -0
  115. package/docs/superpowers/plans/2026-04-12-workspace-agent-creation-plan.md +992 -0
  116. package/docs/superpowers/specs/2026-04-07-autonomous-iteration-design.md +214 -0
  117. package/docs/superpowers/specs/2026-04-07-autonomous-iteration-sub-agent-batches-design.md +188 -0
  118. package/docs/superpowers/specs/2026-04-07-autonomous-workflow-sub-skill-design.md +137 -0
  119. package/docs/superpowers/specs/2026-04-07-benchmarking-multi-agent-design.md +105 -0
  120. package/docs/superpowers/specs/2026-04-07-workspace-builder-logic-design.md +179 -0
  121. package/docs/superpowers/specs/2026-04-07-workspace-maxxing-design.md +227 -0
  122. package/docs/superpowers/specs/2026-04-08-session-294c-subagent-invocation-design.md +265 -0
  123. package/docs/superpowers/specs/2026-04-08-workflow-prompt-hardening-design.md +146 -0
  124. package/docs/superpowers/specs/2026-04-12-workspace-agent-creation-design.md +239 -0
  125. package/jest.config.js +8 -0
  126. package/package.json +32 -0
  127. package/src/agent-creator.ts +180 -0
  128. package/src/agent-iterator.ts +397 -0
  129. package/src/index.ts +189 -0
  130. package/src/install.ts +105 -0
  131. package/src/platforms/claude.ts +40 -0
  132. package/src/platforms/copilot.ts +50 -0
  133. package/src/platforms/gemini.ts +55 -0
  134. package/src/platforms/index.ts +45 -0
  135. package/src/platforms/opencode.ts +41 -0
  136. package/src/scripts/benchmark.ts +171 -0
  137. package/src/scripts/dispatch.ts +473 -0
  138. package/src/scripts/generate-tests.ts +112 -0
  139. package/src/scripts/install-tool.ts +82 -0
  140. package/src/scripts/iterate.ts +271 -0
  141. package/src/scripts/orchestrator.ts +539 -0
  142. package/src/scripts/scaffold.ts +282 -0
  143. package/src/scripts/validate.ts +516 -0
  144. package/templates/.workspace-templates/CONTEXT.md +44 -0
  145. package/templates/.workspace-templates/SYSTEM.md +44 -0
  146. package/templates/.workspace-templates/references/anti-patterns.md +16 -0
  147. package/templates/.workspace-templates/references/iron-laws.md +26 -0
  148. package/templates/.workspace-templates/references/reporting-format.md +52 -0
  149. package/templates/.workspace-templates/scripts/benchmark.ts +171 -0
  150. package/templates/.workspace-templates/scripts/dispatch.ts +473 -0
  151. package/templates/.workspace-templates/scripts/generate-tests.ts +158 -0
  152. package/templates/.workspace-templates/scripts/install-tool.ts +82 -0
  153. package/templates/.workspace-templates/scripts/iterate.ts +265 -0
  154. package/templates/.workspace-templates/scripts/orchestrator.ts +539 -0
  155. package/templates/.workspace-templates/scripts/scaffold.ts +282 -0
  156. package/templates/.workspace-templates/scripts/validate.ts +452 -0
  157. package/templates/.workspace-templates/skills/architecture/SKILL.md +95 -0
  158. package/templates/.workspace-templates/skills/fixer/SKILL.md +109 -0
  159. package/templates/.workspace-templates/skills/iteration/SKILL.md +89 -0
  160. package/templates/.workspace-templates/skills/prompt-engineering/SKILL.md +87 -0
  161. package/templates/.workspace-templates/skills/research/SKILL.md +94 -0
  162. package/templates/.workspace-templates/skills/testing/SKILL.md +89 -0
  163. package/templates/.workspace-templates/skills/tooling/SKILL.md +87 -0
  164. package/templates/.workspace-templates/skills/validation/SKILL.md +103 -0
  165. package/templates/.workspace-templates/skills/worker/SKILL.md +79 -0
  166. package/templates/.workspace-templates/workspace/00-meta/CONTEXT.md +6 -0
  167. package/templates/.workspace-templates/workspace/00-meta/execution-log.md +27 -0
  168. package/templates/.workspace-templates/workspace/01-input/CONTEXT.md +29 -0
  169. package/templates/.workspace-templates/workspace/02-process/CONTEXT.md +29 -0
  170. package/templates/.workspace-templates/workspace/03-output/CONTEXT.md +29 -0
  171. package/templates/.workspace-templates/workspace/README.md +14 -0
  172. package/templates/SKILL.md +347 -0
  173. package/tests/benchmark.test.ts +158 -0
  174. package/tests/cli.test.ts +109 -0
  175. package/tests/dispatch-parallel.test.ts +124 -0
  176. package/tests/dispatch.test.ts +218 -0
  177. package/tests/fixer-skill.test.ts +203 -0
  178. package/tests/generate-tests.test.ts +101 -0
  179. package/tests/install-tool.test.ts +141 -0
  180. package/tests/install.test.ts +144 -0
  181. package/tests/integration.test.ts +324 -0
  182. package/tests/iterate.test.ts +219 -0
  183. package/tests/orchestrator.test.ts +710 -0
  184. package/tests/scaffold.test.ts +238 -0
  185. package/tests/templates-enhanced.test.ts +208 -0
  186. package/tests/templates.test.ts +219 -0
  187. package/tests/validate.test.ts +421 -0
  188. package/tests/validation-enhanced.test.ts +303 -0
  189. package/tests/worker-skill.test.ts +88 -0
  190. package/tsconfig.json +19 -0
  191. package/workspace/00-meta/CONTEXT.md +3 -0
  192. package/workspace/00-meta/execution-log.md +17 -0
  193. package/workspace/00-meta/tools.md +11 -0
  194. package/workspace/01-input/CONTEXT.md +27 -0
  195. package/workspace/CONTEXT.md +35 -0
  196. package/workspace/README.md +14 -0
  197. package/workspace/SYSTEM.md +36 -0
  198. package/workspace-maxxing-0.1.0.tgz +0 -0
@@ -0,0 +1,40 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ import { PlatformInstaller } from './index';
4
+
5
+ export class ClaudeInstaller implements PlatformInstaller {
6
+ install(agentPath: string, targetDir: string): void {
7
+ // Claude Code expects: .claude/skills/<name>/SKILL.md
8
+ // Need to remove @ prefix for directory name
9
+
10
+ const agentName = path.basename(agentPath);
11
+ const cleanName = agentName.startsWith('@') ? agentName.slice(1) : agentName;
12
+ const targetPath = path.join(targetDir, '.claude', 'skills', cleanName);
13
+
14
+ // Ensure target directory exists
15
+ fs.mkdirSync(path.dirname(targetPath), { recursive: true });
16
+
17
+ this.copyDir(agentPath, targetPath);
18
+ console.log(`[Claude] Installed ${cleanName} at: ${targetPath}`);
19
+ }
20
+
21
+ getAgentDir(workspacePath: string): string {
22
+ return path.join(workspacePath, '.claude', 'skills');
23
+ }
24
+
25
+ private copyDir(src: string, dest: string): void {
26
+ fs.mkdirSync(dest, { recursive: true });
27
+ const entries = fs.readdirSync(src, { withFileTypes: true });
28
+
29
+ for (const entry of entries) {
30
+ const srcPath = path.join(src, entry.name);
31
+ const destPath = path.join(dest, entry.name);
32
+
33
+ if (entry.isDirectory()) {
34
+ this.copyDir(srcPath, destPath);
35
+ } else {
36
+ fs.copyFileSync(srcPath, destPath);
37
+ }
38
+ }
39
+ }
40
+ }
@@ -0,0 +1,50 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ import { PlatformInstaller } from './index';
4
+
5
+ export class CopilotInstaller implements PlatformInstaller {
6
+ install(agentPath: string, targetDir: string): void {
7
+ // Copilot expects: .github/copilot-instructions/<name>.md
8
+ // Convert SKILL.md content to markdown instructions
9
+
10
+ const agentName = path.basename(agentPath);
11
+ const cleanName = agentName.startsWith('@') ? agentName.slice(1) : agentName;
12
+ const targetPath = path.join(targetDir, '.github', 'copilot-instructions', `${cleanName}.md`);
13
+
14
+ // Ensure target directory exists
15
+ fs.mkdirSync(path.dirname(targetPath), { recursive: true });
16
+
17
+ // Convert skill to copilot instructions format
18
+ const skillMdPath = path.join(agentPath, 'SKILL.md');
19
+ const skillMd = fs.existsSync(skillMdPath)
20
+ ? fs.readFileSync(skillMdPath, 'utf-8')
21
+ : '# Agent\n\nWorkflow agent';
22
+ const instructions = this.convertToCopilotInstructions(skillMd, cleanName);
23
+
24
+ fs.writeFileSync(targetPath, instructions);
25
+ console.log(`[Copilot] Installed ${cleanName} at: ${targetPath}`);
26
+ }
27
+
28
+ getAgentDir(workspacePath: string): string {
29
+ return path.join(workspacePath, '.github', 'copilot-instructions');
30
+ }
31
+
32
+ private convertToCopilotInstructions(skillMd: string, agentName: string): string {
33
+ // Extract description from SKILL.md
34
+ const descMatch = skillMd.match(/^description:\s*"(.+)"$/m);
35
+ const triggersMatch = skillMd.match(/^triggers:\s*\[(.+)\]/m);
36
+
37
+ const desc = descMatch ? descMatch[1] : 'Workflow agent';
38
+ const triggers = triggersMatch ? triggersMatch[1].replace(/["']/g, '').split(',') : [];
39
+
40
+ let output = `# ${agentName}\n\n${desc}\n\n`;
41
+
42
+ if (triggers.length > 0) {
43
+ output += `## Trigger Phrases\n\n${triggers.map(t => `- ${t.trim()}`).join('\n')}\n\n`;
44
+ }
45
+
46
+ output += `## Usage\n\nUse this agent when working with the workspace workflow. Simply mention @${agentName} or use the trigger phrases above.\n\n## Capabilities\n\n- Execute workflow tasks following ICM stage boundaries\n- Process inputs and generate outputs\n- Produce structured markdown artifacts\n`;
47
+
48
+ return output;
49
+ }
50
+ }
@@ -0,0 +1,55 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ import { PlatformInstaller } from './index';
4
+
5
+ export class GeminiInstaller implements PlatformInstaller {
6
+ install(agentPath: string, targetDir: string): void {
7
+ // Gemini expects: .gemini/skills/<name>/instructions.md
8
+
9
+ const agentName = path.basename(agentPath);
10
+ const cleanName = agentName.startsWith('@') ? agentName.slice(1) : agentName;
11
+ const targetPath = path.join(targetDir, '.gemini', 'skills', cleanName, 'instructions.md');
12
+
13
+ // Ensure target directory exists
14
+ fs.mkdirSync(path.dirname(targetPath), { recursive: true });
15
+
16
+ // Convert SKILL.md to Gemini instructions format
17
+ const skillMdPath = path.join(agentPath, 'SKILL.md');
18
+ const skillMd = fs.existsSync(skillMdPath)
19
+ ? fs.readFileSync(skillMdPath, 'utf-8')
20
+ : '# Agent\n\nWorkflow agent';
21
+ const instructions = this.convertToGeminiInstructions(skillMd);
22
+
23
+ fs.writeFileSync(targetPath, instructions);
24
+ console.log(`[Gemini] Installed ${cleanName} at: ${targetPath}`);
25
+ }
26
+
27
+ getAgentDir(workspacePath: string): string {
28
+ return path.join(workspacePath, '.gemini', 'skills');
29
+ }
30
+
31
+ private convertToGeminiInstructions(skillMd: string): string {
32
+ // Extract key sections from SKILL.md
33
+ const nameMatch = skillMd.match(/^name:\s*(.+)$/m);
34
+ const descMatch = skillMd.match(/^description:\s*"(.+)"$/m);
35
+ const triggersMatch = skillMd.match(/^triggers:\s*\[(.+)\]/m);
36
+
37
+ const name = nameMatch ? nameMatch[1] : 'Agent';
38
+ const desc = descMatch ? descMatch[1] : 'Workflow agent';
39
+ const triggers = triggersMatch
40
+ ? triggersMatch[1].replace(/["']/g, '').split(',').map(t => t.trim())
41
+ : [];
42
+
43
+ let output = `# ${name}\n\n${desc}\n\n## How to Invoke\n\n`;
44
+
45
+ if (triggers.length > 0) {
46
+ output += `Use one of these phrases:\n${triggers.map(t => `- "${t}"`).join('\n')}\n\n`;
47
+ } else {
48
+ output += `Invoke the agent by name.\n\n`;
49
+ }
50
+
51
+ output += `## Capabilities\n\n- Execute workflow tasks\n- Process inputs and generate outputs\n- Follow ICM stage boundaries\n- Produce markdown artifacts\n\n## Workflow Context\n\nWhen activated, this agent operates within the workspace context:\n- Read SYSTEM.md first\n- Load relevant stage CONTEXT.md\n- Execute the requested task\n- Produce outputs in appropriate folders\n`;
52
+
53
+ return output;
54
+ }
55
+ }
@@ -0,0 +1,45 @@
1
+ export type Platform = 'opencode' | 'claude' | 'copilot' | 'gemini';
2
+
3
+ export interface PlatformInstaller {
4
+ install(agentPath: string, targetDir: string): void;
5
+ getAgentDir(workspacePath: string): string;
6
+ }
7
+
8
+ export function detectPlatform(): Platform {
9
+ // Check for platform-specific env vars or files
10
+ if (process.env.OPENCODE_SESSION || process.env.AGENT_MODE === 'opencode') {
11
+ return 'opencode';
12
+ }
13
+ if (process.env.CLAUDE_CODE || process.env.CLAUDE_SESSION) {
14
+ return 'claude';
15
+ }
16
+ if (process.env.COPILOT_AGENT) {
17
+ return 'copilot';
18
+ }
19
+ if (process.env.GEMINI_CLI) {
20
+ return 'gemini';
21
+ }
22
+ // Default to opencode for now
23
+ return 'opencode';
24
+ }
25
+
26
+ export function getPlatformInstaller(platform: Platform): PlatformInstaller {
27
+ switch (platform) {
28
+ case 'opencode':
29
+ return new OpenCodeInstaller();
30
+ case 'claude':
31
+ return new ClaudeInstaller();
32
+ case 'copilot':
33
+ return new CopilotInstaller();
34
+ case 'gemini':
35
+ return new GeminiInstaller();
36
+ default:
37
+ throw new Error(`Unknown platform: ${platform}`);
38
+ }
39
+ }
40
+
41
+ // Import and re-export all platform installers
42
+ import { OpenCodeInstaller } from './opencode';
43
+ import { ClaudeInstaller } from './claude';
44
+ import { CopilotInstaller } from './copilot';
45
+ import { GeminiInstaller } from './gemini';
@@ -0,0 +1,41 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ import { PlatformInstaller } from './index';
4
+
5
+ export class OpenCodeInstaller implements PlatformInstaller {
6
+ install(agentPath: string, targetDir: string): void {
7
+ // OpenCode expects: .agents/skills/@agent-name/SKILL.md
8
+ // Already in correct format from agent-creator
9
+
10
+ const agentName = path.basename(agentPath);
11
+ const targetPath = path.join(targetDir, '.agents', 'skills', agentName);
12
+
13
+ // Ensure target directory exists
14
+ fs.mkdirSync(path.dirname(targetPath), { recursive: true });
15
+
16
+ // Copy entire agent directory
17
+ this.copyDir(agentPath, targetPath);
18
+
19
+ console.log(`[OpenCode] Installed @${agentName} at: ${targetPath}`);
20
+ }
21
+
22
+ getAgentDir(workspacePath: string): string {
23
+ return path.join(workspacePath, '.agents', 'skills');
24
+ }
25
+
26
+ private copyDir(src: string, dest: string): void {
27
+ fs.mkdirSync(dest, { recursive: true });
28
+ const entries = fs.readdirSync(src, { withFileTypes: true });
29
+
30
+ for (const entry of entries) {
31
+ const srcPath = path.join(src, entry.name);
32
+ const destPath = path.join(dest, entry.name);
33
+
34
+ if (entry.isDirectory()) {
35
+ this.copyDir(srcPath, destPath);
36
+ } else {
37
+ fs.copyFileSync(srcPath, destPath);
38
+ }
39
+ }
40
+ }
41
+ }
@@ -0,0 +1,171 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+
4
+ export interface StageBenchmark {
5
+ name: string;
6
+ raw: number;
7
+ weight: number;
8
+ weighted: number;
9
+ }
10
+
11
+ export interface BenchmarkResult {
12
+ workspace: string;
13
+ agent: string;
14
+ timestamp: string;
15
+ rawScore: number;
16
+ weightedScore: number;
17
+ stages: StageBenchmark[];
18
+ fixSuggestions: string[];
19
+ improvementPotential: boolean;
20
+ }
21
+
22
+ const STAGE_WEIGHTS: Record<string, number> = {
23
+ '01-ideation': 1.5,
24
+ '02-research': 1.3,
25
+ '03-architecture': 1.2,
26
+ };
27
+
28
+ const DEFAULT_WEIGHT = 1.0;
29
+ const MAX_RAW_SCORE = 45;
30
+
31
+ export function calculateBenchmark(workspacePath: string): BenchmarkResult {
32
+ const ws = path.resolve(workspacePath);
33
+ const stageFolders = getNumberedFolders(ws);
34
+
35
+ const stages: StageBenchmark[] = [];
36
+ let totalWeighted = 0;
37
+ let totalWeight = 0;
38
+
39
+ for (const folder of stageFolders) {
40
+ const weight = STAGE_WEIGHTS[folder] ?? DEFAULT_WEIGHT;
41
+ const raw = calculateStageRawScore(ws, folder);
42
+ const weighted = (raw / MAX_RAW_SCORE) * 100 * weight;
43
+
44
+ stages.push({ name: folder, raw, weight, weighted });
45
+ totalWeighted += weighted;
46
+ totalWeight += weight;
47
+ }
48
+
49
+ const weightedScore = totalWeight > 0 ? totalWeighted / totalWeight : 0;
50
+ const rawScore = stages.reduce((sum, s) => sum + s.raw, 0);
51
+
52
+ const fixSuggestions = stages
53
+ .filter((s) => s.raw < MAX_RAW_SCORE)
54
+ .map((s) => `Improve ${s.name}: current score ${s.raw}/${MAX_RAW_SCORE}`);
55
+
56
+ return {
57
+ workspace: path.basename(ws),
58
+ agent: 'unknown',
59
+ timestamp: new Date().toISOString(),
60
+ rawScore,
61
+ weightedScore: Math.min(Math.round(weightedScore), 100),
62
+ stages,
63
+ fixSuggestions,
64
+ improvementPotential: stages.some((s) => s.raw < MAX_RAW_SCORE),
65
+ };
66
+ }
67
+
68
+ export function formatBenchmarkTable(data: BenchmarkResult): string {
69
+ const lines: string[] = [];
70
+
71
+ lines.push(`\nBenchmark Report: ${data.workspace}`);
72
+ lines.push(`Agent: ${data.agent} | Timestamp: ${data.timestamp}`);
73
+ lines.push('');
74
+ lines.push(
75
+ padRight('Stage', 20) +
76
+ padRight('Raw', 8) +
77
+ padRight('Weight', 10) +
78
+ padRight('Weighted', 12)
79
+ );
80
+ lines.push('-'.repeat(50));
81
+
82
+ for (const stage of data.stages) {
83
+ lines.push(
84
+ padRight(stage.name, 20) +
85
+ padRight(String(stage.raw), 8) +
86
+ padRight(stage.weight.toFixed(1) + 'x', 10) +
87
+ padRight(stage.weighted.toFixed(1), 12)
88
+ );
89
+ }
90
+
91
+ lines.push('-'.repeat(50));
92
+ lines.push(
93
+ padRight('TOTAL', 20) +
94
+ padRight(String(data.rawScore), 8) +
95
+ padRight('', 10) +
96
+ padRight(data.weightedScore.toFixed(1), 12)
97
+ );
98
+ lines.push('');
99
+
100
+ if (data.fixSuggestions.length > 0) {
101
+ lines.push('Suggestions:');
102
+ for (const suggestion of data.fixSuggestions) {
103
+ lines.push(` - ${suggestion}`);
104
+ }
105
+ lines.push('');
106
+ }
107
+
108
+ return lines.join('\n');
109
+ }
110
+
111
+ export function saveBenchmarkReport(workspacePath: string, data: BenchmarkResult): string {
112
+ const reportDir = path.join(workspacePath, '.workspace-benchmarks');
113
+ fs.mkdirSync(reportDir, { recursive: true });
114
+
115
+ const filename = `${data.workspace}-${data.timestamp.replace(/[:.]/g, '-')}.json`;
116
+ const filePath = path.join(reportDir, filename);
117
+
118
+ fs.writeFileSync(filePath, JSON.stringify(data, null, 2), 'utf-8');
119
+ return filePath;
120
+ }
121
+
122
+ function calculateStageRawScore(ws: string, folder: string): number {
123
+ const stageContextPath = path.join(ws, folder, 'CONTEXT.md');
124
+ let score = 0;
125
+
126
+ if (fs.existsSync(stageContextPath)) {
127
+ const content = fs.readFileSync(stageContextPath, 'utf-8');
128
+ if (content.toLowerCase().includes('purpose') || content.toLowerCase().includes('## purpose')) score += 4;
129
+ if (content.toLowerCase().includes('input')) score += 4;
130
+ if (content.toLowerCase().includes('output')) score += 4;
131
+ if (content.toLowerCase().includes('dependenc')) score += 3;
132
+ if (content.toLowerCase().includes('## success criteria') || content.toLowerCase().includes('success criteria')) score += 5;
133
+ if (content.toLowerCase().includes('## approach') || content.toLowerCase().includes('approach')) score += 5;
134
+ if (content.toLowerCase().includes('## risks') || content.toLowerCase().includes('risks')) score += 5;
135
+ if (content.toLowerCase().includes('## timeline') || content.toLowerCase().includes('timeline')) score += 5;
136
+ if (content.toLowerCase().includes('## resources') || content.toLowerCase().includes('resources')) score += 5;
137
+ if (content.toLowerCase().includes('## validation') || content.toLowerCase().includes('validation')) score += 5;
138
+ }
139
+
140
+ return Math.min(score, MAX_RAW_SCORE);
141
+ }
142
+
143
+ function getNumberedFolders(workspacePath: string): string[] {
144
+ if (!fs.existsSync(workspacePath)) return [];
145
+ const entries = fs.readdirSync(workspacePath, { withFileTypes: true });
146
+ return entries
147
+ .filter((e) => e.isDirectory() && /^\d{2}-/.test(e.name) && e.name !== '00-meta')
148
+ .map((e) => e.name);
149
+ }
150
+
151
+ function padRight(str: string, length: number): string {
152
+ return str.padEnd(length);
153
+ }
154
+
155
+ if (require.main === module) {
156
+ const args = process.argv.slice(2);
157
+ const parseArg = (flag: string): string | undefined => {
158
+ const idx = args.indexOf(flag);
159
+ return idx !== -1 ? args[idx + 1] : undefined;
160
+ };
161
+
162
+ const workspace = parseArg('--workspace');
163
+
164
+ if (!workspace) {
165
+ console.error('Usage: node benchmark.ts --workspace <path>');
166
+ process.exit(1);
167
+ }
168
+
169
+ const result = calculateBenchmark(workspace);
170
+ console.log(formatBenchmarkTable(result));
171
+ }