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,101 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ import * as os from 'os';
4
+ import { generateTestCases, TestCase } from '../src/scripts/generate-tests';
5
+
6
+ describe('generate-tests', () => {
7
+ let tempDir: string;
8
+
9
+ beforeEach(() => {
10
+ tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'generate-tests-'));
11
+ });
12
+
13
+ afterEach(() => {
14
+ fs.rmSync(tempDir, { recursive: true, force: true });
15
+ });
16
+
17
+ function createWorkspaceWithStages(stageNames: string[]): string {
18
+ const ws = path.join(tempDir, 'workspace');
19
+ fs.mkdirSync(ws, { recursive: true });
20
+ fs.writeFileSync(path.join(ws, 'SYSTEM.md'), `# Test\n\n## Folder Map\n\n${stageNames.map((s) => `- \`${s}/\``).join('\n')}\n`);
21
+ fs.writeFileSync(path.join(ws, 'CONTEXT.md'), `# Router\n\n## Routing Table\n\n${stageNames.map((s) => `- \`${s}/\``).join('\n')}\n`);
22
+
23
+ for (const stage of stageNames) {
24
+ const stageDir = path.join(ws, stage);
25
+ fs.mkdirSync(stageDir, { recursive: true });
26
+ fs.writeFileSync(path.join(stageDir, 'CONTEXT.md'), `# ${stage}\n\n## Purpose\nTest stage\n\n## Inputs\nRaw data\n\n## Outputs\nProcessed data\n\n## Dependencies\nNone\n`);
27
+ }
28
+
29
+ return ws;
30
+ }
31
+
32
+ describe('generateTestCases', () => {
33
+ it('generates test cases for each stage', () => {
34
+ const ws = createWorkspaceWithStages(['01-input', '02-process', '03-output']);
35
+ const result = generateTestCases(ws);
36
+
37
+ const stages = [...new Set(result.testCases.map((tc) => tc.stage))];
38
+ expect(stages).toContain('01-input');
39
+ expect(stages).toContain('02-process');
40
+ expect(stages).toContain('03-output');
41
+ });
42
+
43
+ it('generates 2-3 test cases per stage', () => {
44
+ const ws = createWorkspaceWithStages(['01-input', '02-process']);
45
+ const result = generateTestCases(ws);
46
+
47
+ const inputCases = result.testCases.filter((tc) => tc.stage === '01-input');
48
+ const processCases = result.testCases.filter((tc) => tc.stage === '02-process');
49
+
50
+ expect(inputCases.length).toBeGreaterThanOrEqual(2);
51
+ expect(inputCases.length).toBeLessThanOrEqual(3);
52
+ expect(processCases.length).toBeGreaterThanOrEqual(2);
53
+ expect(processCases.length).toBeLessThanOrEqual(3);
54
+ });
55
+
56
+ it('includes sample, edge-case, and empty test types', () => {
57
+ const ws = createWorkspaceWithStages(['01-input']);
58
+ const result = generateTestCases(ws);
59
+
60
+ const types = result.testCases.map((tc) => tc.type);
61
+ expect(types).toContain('sample');
62
+ expect(types).toContain('edge-case');
63
+ expect(types).toContain('empty');
64
+ });
65
+
66
+ it('returns empty test cases for workspace with no stages', () => {
67
+ const ws = path.join(tempDir, 'workspace');
68
+ fs.mkdirSync(ws, { recursive: true });
69
+ fs.writeFileSync(path.join(ws, 'SYSTEM.md'), '# Test\n');
70
+ fs.writeFileSync(path.join(ws, 'CONTEXT.md'), '# Router\n');
71
+
72
+ const result = generateTestCases(ws);
73
+
74
+ expect(result.testCases).toHaveLength(0);
75
+ });
76
+
77
+ it('each test case has required fields', () => {
78
+ const ws = createWorkspaceWithStages(['01-input']);
79
+ const result = generateTestCases(ws);
80
+
81
+ for (const tc of result.testCases) {
82
+ expect(tc).toHaveProperty('stage');
83
+ expect(tc).toHaveProperty('type');
84
+ expect(tc).toHaveProperty('input');
85
+ expect(tc).toHaveProperty('expected');
86
+ }
87
+ });
88
+
89
+ it('writes valid JSON to output file', () => {
90
+ const ws = createWorkspaceWithStages(['01-input', '02-output']);
91
+ const outputPath = path.join(tempDir, 'tests.json');
92
+
93
+ generateTestCases(ws, outputPath);
94
+
95
+ const content = fs.readFileSync(outputPath, 'utf-8');
96
+ const parsed = JSON.parse(content);
97
+ expect(parsed).toHaveProperty('testCases');
98
+ expect(Array.isArray(parsed.testCases)).toBe(true);
99
+ });
100
+ });
101
+ });
@@ -0,0 +1,141 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ import * as os from 'os';
4
+ import { installTool, InstallToolOptions } from '../src/scripts/install-tool';
5
+
6
+ jest.mock('child_process', () => ({
7
+ execSync: jest.fn(),
8
+ }));
9
+
10
+ const { execSync } = require('child_process');
11
+
12
+ describe('install-tool', () => {
13
+ let tempDir: string;
14
+
15
+ beforeEach(() => {
16
+ tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'install-tool-test-'));
17
+ const metaDir = path.join(tempDir, '00-meta');
18
+ fs.mkdirSync(metaDir, { recursive: true });
19
+ fs.writeFileSync(
20
+ path.join(metaDir, 'tools.md'),
21
+ '# Tool Inventory\n\n## Installed Tools\n\n| Tool | Version | Manager | Installed |\n|------|---------|---------|-----------|\n| — | — | — | — |\n',
22
+ );
23
+ });
24
+
25
+ afterEach(() => {
26
+ fs.rmSync(tempDir, { recursive: true, force: true });
27
+ jest.clearAllMocks();
28
+ });
29
+
30
+ describe('installTool', () => {
31
+ it('runs correct npm install command', () => {
32
+ (execSync as jest.Mock).mockReturnValue('');
33
+
34
+ const options: InstallToolOptions = {
35
+ tool: 'pdf-lib',
36
+ manager: 'npm',
37
+ workspace: tempDir,
38
+ };
39
+
40
+ installTool(options);
41
+
42
+ expect(execSync).toHaveBeenCalledWith(
43
+ 'npm install pdf-lib',
44
+ expect.objectContaining({ cwd: tempDir, stdio: 'inherit' }),
45
+ );
46
+ });
47
+
48
+ it('runs correct pip install command', () => {
49
+ (execSync as jest.Mock).mockReturnValue('');
50
+
51
+ const options: InstallToolOptions = {
52
+ tool: 'requests',
53
+ manager: 'pip',
54
+ workspace: tempDir,
55
+ };
56
+
57
+ installTool(options);
58
+
59
+ expect(execSync).toHaveBeenCalledWith(
60
+ 'pip install requests',
61
+ expect.objectContaining({ cwd: tempDir, stdio: 'inherit' }),
62
+ );
63
+ });
64
+
65
+ it('runs correct npx install command', () => {
66
+ (execSync as jest.Mock).mockReturnValue('');
67
+
68
+ const options: InstallToolOptions = {
69
+ tool: 'create-next-app',
70
+ manager: 'npx',
71
+ workspace: tempDir,
72
+ };
73
+
74
+ installTool(options);
75
+
76
+ expect(execSync).toHaveBeenCalledWith(
77
+ 'npx create-next-app',
78
+ expect.objectContaining({ cwd: tempDir, stdio: 'inherit' }),
79
+ );
80
+ });
81
+
82
+ it('runs correct brew install command', () => {
83
+ (execSync as jest.Mock).mockReturnValue('');
84
+
85
+ const options: InstallToolOptions = {
86
+ tool: 'ffmpeg',
87
+ manager: 'brew',
88
+ workspace: tempDir,
89
+ };
90
+
91
+ installTool(options);
92
+
93
+ expect(execSync).toHaveBeenCalledWith(
94
+ 'brew install ffmpeg',
95
+ expect.objectContaining({ cwd: tempDir, stdio: 'inherit' }),
96
+ );
97
+ });
98
+
99
+ it('updates tools.md with installed tool', () => {
100
+ (execSync as jest.Mock).mockReturnValue('');
101
+
102
+ const options: InstallToolOptions = {
103
+ tool: 'pdf-lib',
104
+ manager: 'npm',
105
+ workspace: tempDir,
106
+ };
107
+
108
+ installTool(options);
109
+
110
+ const toolsMd = fs.readFileSync(path.join(tempDir, '00-meta', 'tools.md'), 'utf-8');
111
+ expect(toolsMd).toContain('pdf-lib');
112
+ expect(toolsMd).toContain('npm');
113
+ });
114
+
115
+ it('throws if install command fails', () => {
116
+ (execSync as jest.Mock).mockImplementation(() => {
117
+ const err = new Error('Command failed');
118
+ (err as any).status = 1;
119
+ throw err;
120
+ });
121
+
122
+ const options: InstallToolOptions = {
123
+ tool: 'nonexistent-package',
124
+ manager: 'npm',
125
+ workspace: tempDir,
126
+ };
127
+
128
+ expect(() => installTool(options)).toThrow('Command failed');
129
+ });
130
+
131
+ it('throws for unsupported manager', () => {
132
+ const options: InstallToolOptions = {
133
+ tool: 'something',
134
+ manager: 'unknown' as any,
135
+ workspace: tempDir,
136
+ };
137
+
138
+ expect(() => installTool(options)).toThrow('Unsupported package manager');
139
+ });
140
+ });
141
+ });
@@ -0,0 +1,144 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ import * as os from 'os';
4
+ import { installSkill, detectProjectRoot, getAgentTargetPath } from '../src/install';
5
+
6
+ describe('install', () => {
7
+ let tempDir: string;
8
+
9
+ beforeEach(() => {
10
+ tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'workspace-maxxing-test-'));
11
+ });
12
+
13
+ afterEach(() => {
14
+ fs.rmSync(tempDir, { recursive: true, force: true });
15
+ });
16
+
17
+ describe('detectProjectRoot', () => {
18
+ it('returns the directory containing package.json', () => {
19
+ const projectDir = path.join(tempDir, 'my-project');
20
+ fs.mkdirSync(projectDir, { recursive: true });
21
+ fs.writeFileSync(path.join(projectDir, 'package.json'), '{}');
22
+
23
+ const result = detectProjectRoot(projectDir);
24
+ expect(result).toBe(projectDir);
25
+ });
26
+
27
+ it('returns the directory containing .git', () => {
28
+ const projectDir = path.join(tempDir, 'my-project');
29
+ fs.mkdirSync(path.join(projectDir, '.git'), { recursive: true });
30
+
31
+ const result = detectProjectRoot(projectDir);
32
+ expect(result).toBe(projectDir);
33
+ });
34
+
35
+ it('returns current directory if no marker found', () => {
36
+ const result = detectProjectRoot(tempDir);
37
+ expect(result).toBe(tempDir);
38
+ });
39
+
40
+ it('walks up parent directories to find marker', () => {
41
+ const projectDir = path.join(tempDir, 'my-project');
42
+ const nestedDir = path.join(projectDir, 'src', 'utils');
43
+ fs.mkdirSync(nestedDir, { recursive: true });
44
+ fs.writeFileSync(path.join(projectDir, 'package.json'), '{}');
45
+
46
+ const result = detectProjectRoot(nestedDir);
47
+ expect(result).toBe(projectDir);
48
+ });
49
+ });
50
+
51
+ describe('installSkill', () => {
52
+ it('creates the skill directory structure', async () => {
53
+ const projectDir = path.join(tempDir, 'my-project');
54
+ fs.mkdirSync(projectDir, { recursive: true });
55
+ fs.writeFileSync(path.join(projectDir, 'package.json'), '{}');
56
+
57
+ const templatesDir = path.join(__dirname, '..', 'templates');
58
+ const result = await installSkill(projectDir, templatesDir);
59
+
60
+ expect(result.success).toBe(true);
61
+ expect(fs.existsSync(path.join(projectDir, '.agents', 'skills', 'workspace-maxxing'))).toBe(true);
62
+ });
63
+
64
+ it('copies SKILL.md to the skill directory', async () => {
65
+ const projectDir = path.join(tempDir, 'my-project');
66
+ fs.mkdirSync(projectDir, { recursive: true });
67
+ fs.writeFileSync(path.join(projectDir, 'package.json'), '{}');
68
+
69
+ const templatesDir = path.join(__dirname, '..', 'templates');
70
+ await installSkill(projectDir, templatesDir);
71
+
72
+ const skillPath = path.join(projectDir, '.agents', 'skills', 'workspace-maxxing', 'SKILL.md');
73
+ expect(fs.existsSync(skillPath)).toBe(true);
74
+ });
75
+
76
+ it('copies workspace templates', async () => {
77
+ const projectDir = path.join(tempDir, 'my-project');
78
+ fs.mkdirSync(projectDir, { recursive: true });
79
+ fs.writeFileSync(path.join(projectDir, 'package.json'), '{}');
80
+
81
+ const templatesDir = path.join(__dirname, '..', 'templates');
82
+ await installSkill(projectDir, templatesDir);
83
+
84
+ const systemMd = path.join(projectDir, '.agents', 'skills', 'workspace-maxxing', '.workspace-templates', 'SYSTEM.md');
85
+ const contextMd = path.join(projectDir, '.agents', 'skills', 'workspace-maxxing', '.workspace-templates', 'CONTEXT.md');
86
+ expect(fs.existsSync(systemMd)).toBe(true);
87
+ expect(fs.existsSync(contextMd)).toBe(true);
88
+ });
89
+
90
+ it('is idempotent — running twice produces same result', async () => {
91
+ const projectDir = path.join(tempDir, 'my-project');
92
+ fs.mkdirSync(projectDir, { recursive: true });
93
+ fs.writeFileSync(path.join(projectDir, 'package.json'), '{}');
94
+
95
+ const templatesDir = path.join(__dirname, '..', 'templates');
96
+ await installSkill(projectDir, templatesDir);
97
+ const result2 = await installSkill(projectDir, templatesDir);
98
+
99
+ expect(result2.success).toBe(true);
100
+ const skillPath = path.join(projectDir, '.agents', 'skills', 'workspace-maxxing', 'SKILL.md');
101
+ expect(fs.existsSync(skillPath)).toBe(true);
102
+ });
103
+ });
104
+
105
+ describe('getAgentTargetPath', () => {
106
+ it('returns default path for no agent', () => {
107
+ const result = getAgentTargetPath('/project-root', undefined);
108
+ expect(result).toBe(path.join('/project-root', '.agents', 'skills', 'workspace-maxxing'));
109
+ });
110
+
111
+ it('returns opencode path for --opencode flag', () => {
112
+ const result = getAgentTargetPath('/project-root', 'opencode');
113
+ expect(result).toBe(path.join('/project-root', '.agents', 'skills', 'workspace-maxxing'));
114
+ });
115
+
116
+ it('returns claude path for --claude flag', () => {
117
+ const result = getAgentTargetPath('/project-root', 'claude');
118
+ expect(result).toBe(path.join('/project-root', '.claude', 'skills'));
119
+ });
120
+
121
+ it('returns copilot path for --copilot flag', () => {
122
+ const result = getAgentTargetPath('/project-root', 'copilot');
123
+ expect(result).toBe(path.join('/project-root', '.github', 'copilot-instructions'));
124
+ });
125
+
126
+ it('returns gemini path for --gemini flag', () => {
127
+ const result = getAgentTargetPath('/project-root', 'gemini');
128
+ expect(result).toBe(path.join('/project-root', '.gemini', 'skills'));
129
+ });
130
+
131
+ it('installs to claude path when agent is claude', async () => {
132
+ const projectDir = path.join(tempDir, 'my-project');
133
+ fs.mkdirSync(projectDir, { recursive: true });
134
+ fs.writeFileSync(path.join(projectDir, 'package.json'), '{}');
135
+
136
+ const templatesDir = path.join(__dirname, '..', 'templates');
137
+ const result = await installSkill(projectDir, templatesDir, 'claude');
138
+
139
+ expect(result.success).toBe(true);
140
+ expect(result.skillPath).toContain('.claude');
141
+ expect(fs.existsSync(path.join(projectDir, '.claude', 'skills', 'SKILL.md'))).toBe(true);
142
+ });
143
+ });
144
+ });