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.
- package/.agents/skills/workspace-maxxing/.workspace-templates/CONTEXT.md +44 -0
- package/.agents/skills/workspace-maxxing/.workspace-templates/SYSTEM.md +44 -0
- package/.agents/skills/workspace-maxxing/.workspace-templates/references/anti-patterns.md +16 -0
- package/.agents/skills/workspace-maxxing/.workspace-templates/references/iron-laws.md +26 -0
- package/.agents/skills/workspace-maxxing/.workspace-templates/references/reporting-format.md +52 -0
- package/.agents/skills/workspace-maxxing/.workspace-templates/scripts/benchmark.ts +171 -0
- package/.agents/skills/workspace-maxxing/.workspace-templates/scripts/dispatch.ts +473 -0
- package/.agents/skills/workspace-maxxing/.workspace-templates/scripts/generate-tests.ts +158 -0
- package/.agents/skills/workspace-maxxing/.workspace-templates/scripts/install-tool.ts +82 -0
- package/.agents/skills/workspace-maxxing/.workspace-templates/scripts/iterate.ts +265 -0
- package/.agents/skills/workspace-maxxing/.workspace-templates/scripts/orchestrator.ts +539 -0
- package/.agents/skills/workspace-maxxing/.workspace-templates/scripts/scaffold.ts +282 -0
- package/.agents/skills/workspace-maxxing/.workspace-templates/scripts/validate.ts +452 -0
- package/.agents/skills/workspace-maxxing/.workspace-templates/skills/architecture/SKILL.md +95 -0
- package/.agents/skills/workspace-maxxing/.workspace-templates/skills/fixer/SKILL.md +109 -0
- package/.agents/skills/workspace-maxxing/.workspace-templates/skills/iteration/SKILL.md +89 -0
- package/.agents/skills/workspace-maxxing/.workspace-templates/skills/prompt-engineering/SKILL.md +87 -0
- package/.agents/skills/workspace-maxxing/.workspace-templates/skills/research/SKILL.md +94 -0
- package/.agents/skills/workspace-maxxing/.workspace-templates/skills/testing/SKILL.md +89 -0
- package/.agents/skills/workspace-maxxing/.workspace-templates/skills/tooling/SKILL.md +87 -0
- package/.agents/skills/workspace-maxxing/.workspace-templates/skills/validation/SKILL.md +103 -0
- package/.agents/skills/workspace-maxxing/.workspace-templates/skills/worker/SKILL.md +79 -0
- package/.agents/skills/workspace-maxxing/.workspace-templates/workspace/00-meta/CONTEXT.md +6 -0
- package/.agents/skills/workspace-maxxing/.workspace-templates/workspace/00-meta/execution-log.md +27 -0
- package/.agents/skills/workspace-maxxing/.workspace-templates/workspace/01-input/CONTEXT.md +29 -0
- package/.agents/skills/workspace-maxxing/.workspace-templates/workspace/02-process/CONTEXT.md +29 -0
- package/.agents/skills/workspace-maxxing/.workspace-templates/workspace/03-output/CONTEXT.md +29 -0
- package/.agents/skills/workspace-maxxing/.workspace-templates/workspace/README.md +14 -0
- package/.agents/skills/workspace-maxxing/SKILL.md +312 -0
- package/.agents/skills/workspace-maxxing/scripts/benchmark.ts +171 -0
- package/.agents/skills/workspace-maxxing/scripts/dispatch.ts +473 -0
- package/.agents/skills/workspace-maxxing/scripts/generate-tests.ts +158 -0
- package/.agents/skills/workspace-maxxing/scripts/install-tool.ts +82 -0
- package/.agents/skills/workspace-maxxing/scripts/iterate.ts +265 -0
- package/.agents/skills/workspace-maxxing/scripts/orchestrator.ts +539 -0
- package/.agents/skills/workspace-maxxing/scripts/scaffold.ts +282 -0
- package/.agents/skills/workspace-maxxing/scripts/validate.ts +452 -0
- package/README.md +144 -0
- package/dist/agent-creator.d.ts +9 -0
- package/dist/agent-creator.d.ts.map +1 -0
- package/dist/agent-creator.js +199 -0
- package/dist/agent-creator.js.map +1 -0
- package/dist/agent-iterator.d.ts +38 -0
- package/dist/agent-iterator.d.ts.map +1 -0
- package/dist/agent-iterator.js +327 -0
- package/dist/agent-iterator.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +197 -0
- package/dist/index.js.map +1 -0
- package/dist/install.d.ts +18 -0
- package/dist/install.d.ts.map +1 -0
- package/dist/install.js +117 -0
- package/dist/install.js.map +1 -0
- package/dist/platforms/claude.d.ts +7 -0
- package/dist/platforms/claude.d.ts.map +1 -0
- package/dist/platforms/claude.js +70 -0
- package/dist/platforms/claude.js.map +1 -0
- package/dist/platforms/copilot.d.ts +7 -0
- package/dist/platforms/copilot.d.ts.map +1 -0
- package/dist/platforms/copilot.js +75 -0
- package/dist/platforms/copilot.js.map +1 -0
- package/dist/platforms/gemini.d.ts +7 -0
- package/dist/platforms/gemini.d.ts.map +1 -0
- package/dist/platforms/gemini.js +81 -0
- package/dist/platforms/gemini.js.map +1 -0
- package/dist/platforms/index.d.ts +8 -0
- package/dist/platforms/index.d.ts.map +1 -0
- package/dist/platforms/index.js +41 -0
- package/dist/platforms/index.js.map +1 -0
- package/dist/platforms/opencode.d.ts +7 -0
- package/dist/platforms/opencode.d.ts.map +1 -0
- package/dist/platforms/opencode.js +70 -0
- package/dist/platforms/opencode.js.map +1 -0
- package/dist/scripts/benchmark.d.ts +20 -0
- package/dist/scripts/benchmark.d.ts.map +1 -0
- package/dist/scripts/benchmark.js +170 -0
- package/dist/scripts/benchmark.js.map +1 -0
- package/dist/scripts/dispatch.d.ts +32 -0
- package/dist/scripts/dispatch.d.ts.map +1 -0
- package/dist/scripts/dispatch.js +386 -0
- package/dist/scripts/dispatch.js.map +1 -0
- package/dist/scripts/generate-tests.d.ts +11 -0
- package/dist/scripts/generate-tests.d.ts.map +1 -0
- package/dist/scripts/generate-tests.js +118 -0
- package/dist/scripts/generate-tests.js.map +1 -0
- package/dist/scripts/install-tool.d.ts +8 -0
- package/dist/scripts/install-tool.d.ts.map +1 -0
- package/dist/scripts/install-tool.js +98 -0
- package/dist/scripts/install-tool.js.map +1 -0
- package/dist/scripts/iterate.d.ts +44 -0
- package/dist/scripts/iterate.d.ts.map +1 -0
- package/dist/scripts/iterate.js +260 -0
- package/dist/scripts/iterate.js.map +1 -0
- package/dist/scripts/orchestrator.d.ts +40 -0
- package/dist/scripts/orchestrator.d.ts.map +1 -0
- package/dist/scripts/orchestrator.js +378 -0
- package/dist/scripts/orchestrator.js.map +1 -0
- package/dist/scripts/scaffold.d.ts +8 -0
- package/dist/scripts/scaffold.d.ts.map +1 -0
- package/dist/scripts/scaffold.js +279 -0
- package/dist/scripts/scaffold.js.map +1 -0
- package/dist/scripts/validate.d.ts +11 -0
- package/dist/scripts/validate.d.ts.map +1 -0
- package/dist/scripts/validate.js +472 -0
- package/dist/scripts/validate.js.map +1 -0
- package/docs/superpowers/plans/2026-04-07-autonomous-iteration-plan.md +1123 -0
- package/docs/superpowers/plans/2026-04-07-autonomous-iteration-sub-agent-batches.md +1923 -0
- package/docs/superpowers/plans/2026-04-07-autonomous-workflow-sub-skill-plan.md +1505 -0
- package/docs/superpowers/plans/2026-04-07-benchmarking-multi-agent-plan.md +854 -0
- package/docs/superpowers/plans/2026-04-07-workspace-builder-logic-plan.md +1426 -0
- package/docs/superpowers/plans/2026-04-07-workspace-maxxing-plan.md +1299 -0
- package/docs/superpowers/plans/2026-04-08-session-294c-subagent-invocation-plan.md +320 -0
- package/docs/superpowers/plans/2026-04-08-workflow-prompt-hardening-plan.md +1025 -0
- package/docs/superpowers/plans/2026-04-12-workspace-agent-creation-plan.md +992 -0
- package/docs/superpowers/specs/2026-04-07-autonomous-iteration-design.md +214 -0
- package/docs/superpowers/specs/2026-04-07-autonomous-iteration-sub-agent-batches-design.md +188 -0
- package/docs/superpowers/specs/2026-04-07-autonomous-workflow-sub-skill-design.md +137 -0
- package/docs/superpowers/specs/2026-04-07-benchmarking-multi-agent-design.md +105 -0
- package/docs/superpowers/specs/2026-04-07-workspace-builder-logic-design.md +179 -0
- package/docs/superpowers/specs/2026-04-07-workspace-maxxing-design.md +227 -0
- package/docs/superpowers/specs/2026-04-08-session-294c-subagent-invocation-design.md +265 -0
- package/docs/superpowers/specs/2026-04-08-workflow-prompt-hardening-design.md +146 -0
- package/docs/superpowers/specs/2026-04-12-workspace-agent-creation-design.md +239 -0
- package/jest.config.js +8 -0
- package/package.json +32 -0
- package/src/agent-creator.ts +180 -0
- package/src/agent-iterator.ts +397 -0
- package/src/index.ts +189 -0
- package/src/install.ts +105 -0
- package/src/platforms/claude.ts +40 -0
- package/src/platforms/copilot.ts +50 -0
- package/src/platforms/gemini.ts +55 -0
- package/src/platforms/index.ts +45 -0
- package/src/platforms/opencode.ts +41 -0
- package/src/scripts/benchmark.ts +171 -0
- package/src/scripts/dispatch.ts +473 -0
- package/src/scripts/generate-tests.ts +112 -0
- package/src/scripts/install-tool.ts +82 -0
- package/src/scripts/iterate.ts +271 -0
- package/src/scripts/orchestrator.ts +539 -0
- package/src/scripts/scaffold.ts +282 -0
- package/src/scripts/validate.ts +516 -0
- package/templates/.workspace-templates/CONTEXT.md +44 -0
- package/templates/.workspace-templates/SYSTEM.md +44 -0
- package/templates/.workspace-templates/references/anti-patterns.md +16 -0
- package/templates/.workspace-templates/references/iron-laws.md +26 -0
- package/templates/.workspace-templates/references/reporting-format.md +52 -0
- package/templates/.workspace-templates/scripts/benchmark.ts +171 -0
- package/templates/.workspace-templates/scripts/dispatch.ts +473 -0
- package/templates/.workspace-templates/scripts/generate-tests.ts +158 -0
- package/templates/.workspace-templates/scripts/install-tool.ts +82 -0
- package/templates/.workspace-templates/scripts/iterate.ts +265 -0
- package/templates/.workspace-templates/scripts/orchestrator.ts +539 -0
- package/templates/.workspace-templates/scripts/scaffold.ts +282 -0
- package/templates/.workspace-templates/scripts/validate.ts +452 -0
- package/templates/.workspace-templates/skills/architecture/SKILL.md +95 -0
- package/templates/.workspace-templates/skills/fixer/SKILL.md +109 -0
- package/templates/.workspace-templates/skills/iteration/SKILL.md +89 -0
- package/templates/.workspace-templates/skills/prompt-engineering/SKILL.md +87 -0
- package/templates/.workspace-templates/skills/research/SKILL.md +94 -0
- package/templates/.workspace-templates/skills/testing/SKILL.md +89 -0
- package/templates/.workspace-templates/skills/tooling/SKILL.md +87 -0
- package/templates/.workspace-templates/skills/validation/SKILL.md +103 -0
- package/templates/.workspace-templates/skills/worker/SKILL.md +79 -0
- package/templates/.workspace-templates/workspace/00-meta/CONTEXT.md +6 -0
- package/templates/.workspace-templates/workspace/00-meta/execution-log.md +27 -0
- package/templates/.workspace-templates/workspace/01-input/CONTEXT.md +29 -0
- package/templates/.workspace-templates/workspace/02-process/CONTEXT.md +29 -0
- package/templates/.workspace-templates/workspace/03-output/CONTEXT.md +29 -0
- package/templates/.workspace-templates/workspace/README.md +14 -0
- package/templates/SKILL.md +347 -0
- package/tests/benchmark.test.ts +158 -0
- package/tests/cli.test.ts +109 -0
- package/tests/dispatch-parallel.test.ts +124 -0
- package/tests/dispatch.test.ts +218 -0
- package/tests/fixer-skill.test.ts +203 -0
- package/tests/generate-tests.test.ts +101 -0
- package/tests/install-tool.test.ts +141 -0
- package/tests/install.test.ts +144 -0
- package/tests/integration.test.ts +324 -0
- package/tests/iterate.test.ts +219 -0
- package/tests/orchestrator.test.ts +710 -0
- package/tests/scaffold.test.ts +238 -0
- package/tests/templates-enhanced.test.ts +208 -0
- package/tests/templates.test.ts +219 -0
- package/tests/validate.test.ts +421 -0
- package/tests/validation-enhanced.test.ts +303 -0
- package/tests/worker-skill.test.ts +88 -0
- package/tsconfig.json +19 -0
- package/workspace/00-meta/CONTEXT.md +3 -0
- package/workspace/00-meta/execution-log.md +17 -0
- package/workspace/00-meta/tools.md +11 -0
- package/workspace/01-input/CONTEXT.md +27 -0
- package/workspace/CONTEXT.md +35 -0
- package/workspace/README.md +14 -0
- package/workspace/SYSTEM.md +36 -0
- package/workspace-maxxing-0.1.0.tgz +0 -0
|
@@ -0,0 +1,992 @@
|
|
|
1
|
+
# Workspace-Maxxing Agent Creation Implementation Plan
|
|
2
|
+
|
|
3
|
+
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
|
4
|
+
|
|
5
|
+
**Goal:** Extend workspace-maxxing to create invokable @agent inside the generated workspace, with self-improvement loop during build phase.
|
|
6
|
+
|
|
7
|
+
**Architecture:**
|
|
8
|
+
- `agent-creator.ts` generates agent structure from workspace purpose
|
|
9
|
+
- `agent-iterator.ts` runs test/validate/improve cycles until robustness threshold
|
|
10
|
+
- Agent installed to workspace-local `.agents/skills/@<name>/` for multi-platform invocation
|
|
11
|
+
|
|
12
|
+
**Tech Stack:** TypeScript, Node.js, existing workspace-maxxing scripts
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## File Structure
|
|
17
|
+
|
|
18
|
+
### New Files to Create
|
|
19
|
+
|
|
20
|
+
| File | Purpose |
|
|
21
|
+
|------|---------|
|
|
22
|
+
| `src/agent-creator.ts` | Creates agent structure from workspace purpose |
|
|
23
|
+
| `src/agent-iterator.ts` | Self-improvement loop with test/validate/improve |
|
|
24
|
+
| `src/platforms/opencode.ts` | OpenCode platform agent installer |
|
|
25
|
+
| `src/platforms/claude.ts` | Claude Code platform agent installer |
|
|
26
|
+
| `src/platforms/copilot.ts` | Copilot platform agent installer |
|
|
27
|
+
| `src/platforms/gemini.ts` | Gemini platform agent installer |
|
|
28
|
+
| `src/agent-config.ts` | Agent configuration management |
|
|
29
|
+
| `templates/agent/SKILL.md` | Base agent skill template |
|
|
30
|
+
| `templates/agent/prompts/system.md` | Agent system prompt template |
|
|
31
|
+
| `templates/agent/config.json` | Agent config template |
|
|
32
|
+
|
|
33
|
+
### Files to Modify
|
|
34
|
+
|
|
35
|
+
| File | Changes |
|
|
36
|
+
|------|---------|
|
|
37
|
+
| `SKILL.md` | Add agent creation to workflow, new flags |
|
|
38
|
+
| `src/index.ts` | Add `--with-agent`, `--agent-name` options |
|
|
39
|
+
| `src/install.ts` | Support agent installation |
|
|
40
|
+
| `src/scripts/scaffold.ts` | Add agent creation hook |
|
|
41
|
+
| `package.json` | No changes needed |
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## Task 1: Agent Creator Module
|
|
46
|
+
|
|
47
|
+
**Files:**
|
|
48
|
+
- Create: `src/agent-creator.ts`
|
|
49
|
+
- Test: `tests/agent-creator.test.ts`
|
|
50
|
+
|
|
51
|
+
- [ ] **Step 1: Write the failing test**
|
|
52
|
+
|
|
53
|
+
```typescript
|
|
54
|
+
// tests/agent-creator.test.ts
|
|
55
|
+
import { describe, it, expect, beforeEach } from 'vitest';
|
|
56
|
+
import * as fs from 'fs';
|
|
57
|
+
import * as path from 'path';
|
|
58
|
+
import { createAgent, generateAgentName, AgentOptions } from '../src/agent-creator';
|
|
59
|
+
|
|
60
|
+
describe('agent-creator', () => {
|
|
61
|
+
const tempDir = path.join(__dirname, 'temp-agent-test');
|
|
62
|
+
|
|
63
|
+
beforeEach(() => {
|
|
64
|
+
if (fs.existsSync(tempDir)) {
|
|
65
|
+
fs.rmSync(tempDir, { recursive: true });
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
describe('generateAgentName', () => {
|
|
70
|
+
it('converts "Daily Digest" to @daily-digest', () => {
|
|
71
|
+
expect(generateAgentName('Daily Digest')).toBe('@daily-digest');
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it('converts "AI News Aggregator" to @ai-news-aggregator', () => {
|
|
75
|
+
expect(generateAgentName('AI News Aggregator')).toBe('@ai-news-aggregator');
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it('handles special characters', () => {
|
|
79
|
+
expect(generateAgentName('Project 2026!')).toBe('@project-2026');
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
describe('createAgent', () => {
|
|
84
|
+
it('creates agent directory structure', () => {
|
|
85
|
+
const options: AgentOptions = {
|
|
86
|
+
name: '@daily-digest',
|
|
87
|
+
purpose: 'Create daily AI news digest',
|
|
88
|
+
workspacePath: tempDir,
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
createAgent(options);
|
|
92
|
+
|
|
93
|
+
const agentPath = path.join(tempDir, '.agents', 'skills', '@daily-digest');
|
|
94
|
+
expect(fs.existsSync(path.join(agentPath, 'SKILL.md'))).toBe(true);
|
|
95
|
+
expect(fs.existsSync(path.join(agentPath, 'prompts'))).toBe(true);
|
|
96
|
+
expect(fs.existsSync(path.join(agentPath, 'tools'))).toBe(true);
|
|
97
|
+
expect(fs.existsSync(path.join(agentPath, 'tests'))).toBe(true);
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it('generates SKILL.md with correct name', () => {
|
|
101
|
+
const options: AgentOptions = {
|
|
102
|
+
name: '@daily-digest',
|
|
103
|
+
purpose: 'Create daily AI news digest',
|
|
104
|
+
workspacePath: tempDir,
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
createAgent(options);
|
|
108
|
+
|
|
109
|
+
const skillPath = path.join(tempDir, '.agents', 'skills', '@daily-digest', 'SKILL.md');
|
|
110
|
+
const content = fs.readFileSync(skillPath, 'utf-8');
|
|
111
|
+
expect(content).toContain('name: @daily-digest');
|
|
112
|
+
expect(content).toContain('Create daily AI news digest');
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
- [ ] **Step 2: Run test to verify it fails**
|
|
119
|
+
|
|
120
|
+
Run: `npm test -- tests/agent-creator.test.ts`
|
|
121
|
+
Expected: FAIL - "Cannot find module" or similar
|
|
122
|
+
|
|
123
|
+
- [ ] **Step 3: Write minimal implementation**
|
|
124
|
+
|
|
125
|
+
```typescript
|
|
126
|
+
// src/agent-creator.ts
|
|
127
|
+
import * as fs from 'fs';
|
|
128
|
+
import * as path from 'path';
|
|
129
|
+
|
|
130
|
+
export interface AgentOptions {
|
|
131
|
+
name: string;
|
|
132
|
+
purpose: string;
|
|
133
|
+
workspacePath: string;
|
|
134
|
+
platforms?: string[];
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export function generateAgentName(purpose: string): string {
|
|
138
|
+
// Convert "Daily Digest" -> "@daily-digest"
|
|
139
|
+
// Convert "AI News Aggregator" -> "@ai-news-aggregator"
|
|
140
|
+
const cleaned = purpose
|
|
141
|
+
.toLowerCase()
|
|
142
|
+
.replace(/[^a-z0-9\s-]/g, '')
|
|
143
|
+
.replace(/\s+/g, '-')
|
|
144
|
+
.replace(/-+/g, '-')
|
|
145
|
+
.trim();
|
|
146
|
+
return `@${cleaned}`;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export function createAgent(options: AgentOptions): void {
|
|
150
|
+
const { name, purpose, workspacePath } = options;
|
|
151
|
+
|
|
152
|
+
// Remove @ prefix for directory name
|
|
153
|
+
const dirName = name.startsWith('@') ? name.slice(1) : name;
|
|
154
|
+
const agentDir = path.join(workspacePath, '.agents', 'skills', dirName);
|
|
155
|
+
|
|
156
|
+
// Create directory structure
|
|
157
|
+
fs.mkdirSync(path.join(agentDir, 'prompts', 'tasks'), { recursive: true });
|
|
158
|
+
fs.mkdirSync(path.join(agentDir, 'tools'), { recursive: true });
|
|
159
|
+
fs.mkdirSync(path.join(agentDir, 'tests'), { recursive: true });
|
|
160
|
+
|
|
161
|
+
// Write SKILL.md
|
|
162
|
+
const skillContent = generateSkillMd(name, purpose);
|
|
163
|
+
fs.writeFileSync(path.join(agentDir, 'SKILL.md'), skillContent);
|
|
164
|
+
|
|
165
|
+
// Write config.json
|
|
166
|
+
const configContent = JSON.stringify({
|
|
167
|
+
name,
|
|
168
|
+
purpose,
|
|
169
|
+
platforms: ['opencode', 'claude', 'copilot', 'gemini'],
|
|
170
|
+
robustnessThreshold: 85,
|
|
171
|
+
iterationCount: 0,
|
|
172
|
+
testCases: [],
|
|
173
|
+
}, null, 2);
|
|
174
|
+
fs.writeFileSync(path.join(agentDir, 'config.json'), configContent);
|
|
175
|
+
|
|
176
|
+
// Write prompts/system.md
|
|
177
|
+
const systemPrompt = generateSystemPrompt(name, purpose);
|
|
178
|
+
fs.writeFileSync(path.join(agentDir, 'prompts', 'system.md'), systemPrompt);
|
|
179
|
+
|
|
180
|
+
console.log(`Agent "${name}" created at: ${agentDir}`);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function generateSkillMd(name: string, purpose: string): string {
|
|
184
|
+
return `---
|
|
185
|
+
name: ${name}
|
|
186
|
+
description: "${purpose}. Use when user wants to run this workflow."
|
|
187
|
+
triggers: ["${name}", "${purpose.toLowerCase()}"]
|
|
188
|
+
---
|
|
189
|
+
|
|
190
|
+
# ${name} Agent
|
|
191
|
+
|
|
192
|
+
## Purpose
|
|
193
|
+
${purpose}
|
|
194
|
+
|
|
195
|
+
## Capabilities
|
|
196
|
+
- Execute workflow tasks
|
|
197
|
+
- Process inputs and generate outputs
|
|
198
|
+
- Self-improvement through iteration
|
|
199
|
+
|
|
200
|
+
## Usage
|
|
201
|
+
Invoke with @${name.slice(1)} in the workspace.
|
|
202
|
+
|
|
203
|
+
## Configuration
|
|
204
|
+
See config.json for options.
|
|
205
|
+
`;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
function generateSystemPrompt(name: string, purpose: string): string {
|
|
209
|
+
return `# ${name} - System Prompt
|
|
210
|
+
|
|
211
|
+
## Role
|
|
212
|
+
You are ${name}, an autonomous workflow agent.
|
|
213
|
+
|
|
214
|
+
## Purpose
|
|
215
|
+
${purpose}
|
|
216
|
+
|
|
217
|
+
## Workflow
|
|
218
|
+
1. Read workspace context (SYSTEM.md, relevant stage CONTEXT.md)
|
|
219
|
+
2. Process task according to workflow stages
|
|
220
|
+
3. Produce structured output
|
|
221
|
+
4. Log results for self-improvement
|
|
222
|
+
|
|
223
|
+
## Constraints
|
|
224
|
+
- Stay within workspace scope
|
|
225
|
+
- Follow ICM folder boundaries
|
|
226
|
+
- Report progress in hybrid format (chat + files)
|
|
227
|
+
`;
|
|
228
|
+
}
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
- [ ] **Step 4: Run test to verify it passes**
|
|
232
|
+
|
|
233
|
+
Run: `npm test -- tests/agent-creator.test.ts`
|
|
234
|
+
Expected: PASS
|
|
235
|
+
|
|
236
|
+
- [ ] **Step 5: Commit**
|
|
237
|
+
|
|
238
|
+
```bash
|
|
239
|
+
git add src/agent-creator.ts tests/agent-creator.test.ts
|
|
240
|
+
git commit -m "feat: add agent-creator module for generating @agent structure"
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
---
|
|
244
|
+
|
|
245
|
+
## Task 2: Agent Iterator Module (Self-Improvement Loop)
|
|
246
|
+
|
|
247
|
+
**Files:**
|
|
248
|
+
- Create: `src/agent-iterator.ts`
|
|
249
|
+
- Test: `tests/agent-iterator.test.ts`
|
|
250
|
+
|
|
251
|
+
- [ ] **Step 1: Write the failing test**
|
|
252
|
+
|
|
253
|
+
```typescript
|
|
254
|
+
// tests/agent-iterator.test.ts
|
|
255
|
+
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
|
256
|
+
import * as fs from 'fs';
|
|
257
|
+
import * as path from 'path';
|
|
258
|
+
import { iterateAgent, AgentIterationOptions, AgentIterationResult } from '../src/agent-iterator';
|
|
259
|
+
|
|
260
|
+
describe('agent-iterator', () => {
|
|
261
|
+
const tempDir = path.join(__dirname, 'temp-iterator-test');
|
|
262
|
+
|
|
263
|
+
beforeEach(() => {
|
|
264
|
+
if (fs.existsSync(tempDir)) {
|
|
265
|
+
fs.rmSync(tempDir, { recursive: true });
|
|
266
|
+
}
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
describe('iterateAgent', () => {
|
|
270
|
+
it('returns iteration result with score', async () => {
|
|
271
|
+
// Setup mock agent
|
|
272
|
+
const agentDir = path.join(tempDir, '.agents', 'skills', '@test-agent');
|
|
273
|
+
fs.mkdirSync(path.join(agentDir, 'tests'), { recursive: true });
|
|
274
|
+
fs.writeFileSync(path.join(agentDir, 'config.json'), JSON.stringify({
|
|
275
|
+
name: '@test-agent',
|
|
276
|
+
purpose: 'Test agent',
|
|
277
|
+
}));
|
|
278
|
+
|
|
279
|
+
const options: AgentIterationOptions = {
|
|
280
|
+
agentPath: agentDir,
|
|
281
|
+
workspacePath: tempDir,
|
|
282
|
+
threshold: 85,
|
|
283
|
+
maxIterations: 3,
|
|
284
|
+
};
|
|
285
|
+
|
|
286
|
+
const result = await iterateAgent(options);
|
|
287
|
+
|
|
288
|
+
expect(result).toHaveProperty('score');
|
|
289
|
+
expect(result).toHaveProperty('iterations');
|
|
290
|
+
expect(result).toHaveProperty('testCases');
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
it('stops when score >= threshold', async () => {
|
|
294
|
+
const agentDir = path.join(tempDir, '.agents', 'skills', '@good-agent');
|
|
295
|
+
fs.mkdirSync(path.join(agentDir, 'tests'), { recursive: true });
|
|
296
|
+
fs.writeFileSync(path.join(agentDir, 'config.json'), JSON.stringify({
|
|
297
|
+
name: '@good-agent',
|
|
298
|
+
purpose: 'Good agent',
|
|
299
|
+
}));
|
|
300
|
+
|
|
301
|
+
const options: AgentIterationOptions = {
|
|
302
|
+
agentPath: agentDir,
|
|
303
|
+
workspacePath: tempDir,
|
|
304
|
+
threshold: 100, // Impossible threshold
|
|
305
|
+
maxIterations: 1,
|
|
306
|
+
};
|
|
307
|
+
|
|
308
|
+
const result = await iterateAgent(options);
|
|
309
|
+
|
|
310
|
+
expect(result.iterations).toBeLessThanOrEqual(1);
|
|
311
|
+
});
|
|
312
|
+
});
|
|
313
|
+
});
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
- [ ] **Step 2: Run test to verify it fails**
|
|
317
|
+
|
|
318
|
+
Run: `npm test -- tests/agent-iterator.test.ts`
|
|
319
|
+
Expected: FAIL - module not found
|
|
320
|
+
|
|
321
|
+
- [ ] **Step 3: Write minimal implementation**
|
|
322
|
+
|
|
323
|
+
```typescript
|
|
324
|
+
// src/agent-iterator.ts
|
|
325
|
+
import * as fs from 'fs';
|
|
326
|
+
import * as path from 'path';
|
|
327
|
+
|
|
328
|
+
export interface AgentIterationOptions {
|
|
329
|
+
agentPath: string;
|
|
330
|
+
workspacePath: string;
|
|
331
|
+
threshold?: number;
|
|
332
|
+
maxIterations?: number;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
export interface AgentIterationResult {
|
|
336
|
+
score: number;
|
|
337
|
+
iterations: number;
|
|
338
|
+
testCases: TestCaseResult[];
|
|
339
|
+
passed: boolean;
|
|
340
|
+
improvements: string[];
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
interface TestCaseResult {
|
|
344
|
+
id: string;
|
|
345
|
+
input: string;
|
|
346
|
+
output: string;
|
|
347
|
+
passed: boolean;
|
|
348
|
+
issues: string[];
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
export async function iterateAgent(options: AgentIterationOptions): Promise<AgentIterationResult> {
|
|
352
|
+
const {
|
|
353
|
+
agentPath,
|
|
354
|
+
workspacePath,
|
|
355
|
+
threshold = 85,
|
|
356
|
+
maxIterations = 3,
|
|
357
|
+
} = options;
|
|
358
|
+
|
|
359
|
+
const testCasesDir = path.join(agentPath, 'tests');
|
|
360
|
+
|
|
361
|
+
// Ensure tests directory exists
|
|
362
|
+
if (!fs.existsSync(testCasesDir)) {
|
|
363
|
+
fs.mkdirSync(testCasesDir, { recursive: true });
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
// Generate test cases if none exist
|
|
367
|
+
const existingCases = loadTestCases(testCasesDir);
|
|
368
|
+
const testCases = existingCases.length > 0
|
|
369
|
+
? existingCases
|
|
370
|
+
: generateDefaultTestCases(agentPath);
|
|
371
|
+
|
|
372
|
+
const improvements: string[] = [];
|
|
373
|
+
let currentScore = 0;
|
|
374
|
+
|
|
375
|
+
for (let iteration = 0; iteration < maxIterations; iteration++) {
|
|
376
|
+
console.log(`\n--- Iteration ${iteration + 1}/${maxIterations} ---`);
|
|
377
|
+
|
|
378
|
+
// Run each test case
|
|
379
|
+
const results = await runTestCases(testCases, agentPath, workspacePath);
|
|
380
|
+
|
|
381
|
+
// Calculate score
|
|
382
|
+
const passedCount = results.filter(r => r.passed).length;
|
|
383
|
+
currentScore = Math.round((passedCount / results.length) * 100);
|
|
384
|
+
|
|
385
|
+
console.log(`Score: ${currentScore}/${threshold}`);
|
|
386
|
+
|
|
387
|
+
if (currentScore >= threshold) {
|
|
388
|
+
console.log('Threshold met! Stopping iteration.');
|
|
389
|
+
break;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
// Identify issues and attempt improvement
|
|
393
|
+
const issues = results.flatMap(r => r.issues);
|
|
394
|
+
if (issues.length > 0 && iteration < maxIterations - 1) {
|
|
395
|
+
const improvement = await improveAgent(agentPath, issues, iteration + 1);
|
|
396
|
+
if (improvement) {
|
|
397
|
+
improvements.push(improvement);
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
// Update config with iteration count
|
|
403
|
+
updateIterationConfig(agentPath, improvements.length, currentScore);
|
|
404
|
+
|
|
405
|
+
return {
|
|
406
|
+
score: currentScore,
|
|
407
|
+
iterations: improvements.length + 1,
|
|
408
|
+
testCases: [],
|
|
409
|
+
passed: currentScore >= threshold,
|
|
410
|
+
improvements,
|
|
411
|
+
};
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
function loadTestCases(testsDir: string): TestCaseResult[] {
|
|
415
|
+
const casesPath = path.join(testsDir, 'cases.json');
|
|
416
|
+
if (fs.existsSync(casesPath)) {
|
|
417
|
+
try {
|
|
418
|
+
return JSON.parse(fs.readFileSync(casesPath, 'utf-8'));
|
|
419
|
+
} catch {
|
|
420
|
+
return [];
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
return [];
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
function generateDefaultTestCases(agentPath: string): TestCaseResult[] {
|
|
427
|
+
// Load agent purpose from config
|
|
428
|
+
const configPath = path.join(agentPath, 'config.json');
|
|
429
|
+
const config = fs.existsSync(configPath)
|
|
430
|
+
? JSON.parse(fs.readFileSync(configPath, 'utf-8'))
|
|
431
|
+
: { purpose: 'workflow task' };
|
|
432
|
+
|
|
433
|
+
// Generate edge case, empty, and varied test cases
|
|
434
|
+
const testCases = [
|
|
435
|
+
{ id: 'tc-edge-001', input: 'complex input with special chars !@#$%^&*()', expected: 'valid output' },
|
|
436
|
+
{ id: 'tc-empty-001', input: '', expected: 'graceful handling' },
|
|
437
|
+
{ id: 'tc-normal-001', input: 'standard workflow request', expected: 'proper response' },
|
|
438
|
+
];
|
|
439
|
+
|
|
440
|
+
// Write to cases.json for reference
|
|
441
|
+
const testsDir = path.dirname(configPath);
|
|
442
|
+
fs.writeFileSync(
|
|
443
|
+
path.join(testsDir, 'cases.json'),
|
|
444
|
+
JSON.stringify(testCases, null, 2)
|
|
445
|
+
);
|
|
446
|
+
|
|
447
|
+
return testCases as TestCaseResult[];
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
async function runTestCases(
|
|
451
|
+
testCases: TestCaseResult[],
|
|
452
|
+
agentPath: string,
|
|
453
|
+
workspacePath: string
|
|
454
|
+
): Promise<TestCaseResult[]> {
|
|
455
|
+
const results: TestCaseResult[] = [];
|
|
456
|
+
|
|
457
|
+
for (const tc of testCases) {
|
|
458
|
+
console.log(` Running ${tc.id}...`);
|
|
459
|
+
|
|
460
|
+
// In a real implementation, this would execute the agent with the test input
|
|
461
|
+
// For now, simulate basic pass/fail based on input type
|
|
462
|
+
const passed = tc.input.length > 0 || tc.id.includes('empty');
|
|
463
|
+
const issues = passed ? [] : ['Empty input handling needed'];
|
|
464
|
+
|
|
465
|
+
results.push({
|
|
466
|
+
...tc,
|
|
467
|
+
output: passed ? 'processed' : 'failed',
|
|
468
|
+
passed,
|
|
469
|
+
issues,
|
|
470
|
+
});
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
return results;
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
async function improveAgent(
|
|
477
|
+
agentPath: string,
|
|
478
|
+
issues: string[],
|
|
479
|
+
iteration: number
|
|
480
|
+
): Promise<string | null> {
|
|
481
|
+
const promptsDir = path.join(agentPath, 'prompts');
|
|
482
|
+
const systemPromptPath = path.join(promptsDir, 'system.md');
|
|
483
|
+
|
|
484
|
+
if (!fs.existsSync(systemPromptPath)) {
|
|
485
|
+
return null;
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
const currentContent = fs.readFileSync(systemPromptPath, 'utf-8');
|
|
489
|
+
|
|
490
|
+
// Add improvement note to system prompt
|
|
491
|
+
const improvementNote = `\n## Iteration ${iteration} Improvements\n${issues.map(i => `- ${i}`).join('\n')}`;
|
|
492
|
+
const newContent = currentContent + improvementNote;
|
|
493
|
+
|
|
494
|
+
fs.writeFileSync(systemPromptPath, newContent);
|
|
495
|
+
|
|
496
|
+
return `Iteration ${iteration}: Added handling for ${issues.length} issue(s)`;
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
function updateIterationConfig(agentPath: string, iterations: number, score: number): void {
|
|
500
|
+
const configPath = path.join(agentPath, 'config.json');
|
|
501
|
+
if (fs.existsSync(configPath)) {
|
|
502
|
+
const config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
|
|
503
|
+
config.iterationCount = iterations;
|
|
504
|
+
config.lastScore = score;
|
|
505
|
+
fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
```
|
|
509
|
+
|
|
510
|
+
- [ ] **Step 4: Run test to verify it passes**
|
|
511
|
+
|
|
512
|
+
Run: `npm test -- tests/agent-iterator.test.ts`
|
|
513
|
+
Expected: PASS
|
|
514
|
+
|
|
515
|
+
- [ ] **Step 5: Commit**
|
|
516
|
+
|
|
517
|
+
```bash
|
|
518
|
+
git add src/agent-iterator.ts tests/agent-iterator.test.ts
|
|
519
|
+
git commit -m "feat: add agent-iterator for self-improvement loop"
|
|
520
|
+
```
|
|
521
|
+
|
|
522
|
+
---
|
|
523
|
+
|
|
524
|
+
## Task 3: Platform Installers
|
|
525
|
+
|
|
526
|
+
**Files:**
|
|
527
|
+
- Create: `src/platforms/opencode.ts`, `src/platforms/claude.ts`, `src/platforms/copilot.ts`, `src/platforms/gemini.ts`
|
|
528
|
+
- Test: `tests/platforms.test.ts`
|
|
529
|
+
|
|
530
|
+
- [ ] **Step 1: Write the failing test**
|
|
531
|
+
|
|
532
|
+
```typescript
|
|
533
|
+
// tests/platforms.test.ts
|
|
534
|
+
import { describe, it, expect } from 'vitest';
|
|
535
|
+
import { installForOpenCode, detectPlatform } from '../src/platforms/opencode';
|
|
536
|
+
|
|
537
|
+
describe('platforms', () => {
|
|
538
|
+
describe('detectPlatform', () => {
|
|
539
|
+
it('detects opencode from process.env', () => {
|
|
540
|
+
// Would need to mock env
|
|
541
|
+
});
|
|
542
|
+
});
|
|
543
|
+
|
|
544
|
+
describe('installForOpenCode', () => {
|
|
545
|
+
it('copies agent to opencode skill directory', async () => {
|
|
546
|
+
// Test would create temp agent and verify installation
|
|
547
|
+
});
|
|
548
|
+
});
|
|
549
|
+
});
|
|
550
|
+
```
|
|
551
|
+
|
|
552
|
+
- [ ] **Step 2: Run test to verify it fails**
|
|
553
|
+
|
|
554
|
+
Run: `npm test -- tests/platforms.test.ts`
|
|
555
|
+
Expected: FAIL
|
|
556
|
+
|
|
557
|
+
- [ ] **Step 3: Write minimal implementation**
|
|
558
|
+
|
|
559
|
+
```typescript
|
|
560
|
+
// src/platforms/index.ts
|
|
561
|
+
export type Platform = 'opencode' | 'claude' | 'copilot' | 'gemini';
|
|
562
|
+
|
|
563
|
+
export interface PlatformInstaller {
|
|
564
|
+
install(agentPath: string, targetDir: string): void;
|
|
565
|
+
getAgentDir(workspacePath: string): string;
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
export function detectPlatform(): Platform | null {
|
|
569
|
+
// Check for platform-specific env vars or files
|
|
570
|
+
if (process.env.OPENCODE_SESSION || process.env.AGENT_MODE === 'opencode') {
|
|
571
|
+
return 'opencode';
|
|
572
|
+
}
|
|
573
|
+
if (process.env.CLAUDE_CODE || process.env.CLAUDE_SESSION) {
|
|
574
|
+
return 'claude';
|
|
575
|
+
}
|
|
576
|
+
if (process.env.COPILOT_AGENT) {
|
|
577
|
+
return 'copilot';
|
|
578
|
+
}
|
|
579
|
+
if (process.env.GEMINI_CLI) {
|
|
580
|
+
return 'gemini';
|
|
581
|
+
}
|
|
582
|
+
// Default to opencode for now
|
|
583
|
+
return 'opencode';
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
export function getPlatformInstaller(platform: Platform): PlatformInstaller {
|
|
587
|
+
switch (platform) {
|
|
588
|
+
case 'opencode':
|
|
589
|
+
return new OpenCodeInstaller();
|
|
590
|
+
case 'claude':
|
|
591
|
+
return new ClaudeInstaller();
|
|
592
|
+
case 'copilot':
|
|
593
|
+
return new CopilotInstaller();
|
|
594
|
+
case 'gemini':
|
|
595
|
+
return new GeminiInstaller();
|
|
596
|
+
default:
|
|
597
|
+
throw new Error(`Unknown platform: ${platform}`);
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
```
|
|
601
|
+
|
|
602
|
+
```typescript
|
|
603
|
+
// src/platforms/opencode.ts
|
|
604
|
+
import * as fs from 'fs';
|
|
605
|
+
import * as path from 'path';
|
|
606
|
+
import { PlatformInstaller } from './index';
|
|
607
|
+
|
|
608
|
+
export class OpenCodeInstaller implements PlatformInstaller {
|
|
609
|
+
install(agentPath: string, targetDir: string): void {
|
|
610
|
+
// OpenCode expects: .agents/skills/@agent-name/SKILL.md
|
|
611
|
+
// Already in correct format from agent-creator
|
|
612
|
+
|
|
613
|
+
const agentName = path.basename(agentPath);
|
|
614
|
+
const targetPath = path.join(targetDir, '.agents', 'skills', agentName);
|
|
615
|
+
|
|
616
|
+
if (!fs.existsSync(path.dirname(targetPath))) {
|
|
617
|
+
fs.mkdirSync(path.dirname(targetPath), { recursive: true });
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
// Copy entire agent directory
|
|
621
|
+
this.copyDir(agentPath, targetPath);
|
|
622
|
+
|
|
623
|
+
console.log(`Installed @${agentName} for OpenCode at: ${targetPath}`);
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
getAgentDir(workspacePath: string): string {
|
|
627
|
+
return path.join(workspacePath, '.agents', 'skills');
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
private copyDir(src: string, dest: string): void {
|
|
631
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
632
|
+
const entries = fs.readdirSync(src, { withFileTypes: true });
|
|
633
|
+
|
|
634
|
+
for (const entry of entries) {
|
|
635
|
+
const srcPath = path.join(src, entry.name);
|
|
636
|
+
const destPath = path.join(dest, entry.name);
|
|
637
|
+
|
|
638
|
+
if (entry.isDirectory()) {
|
|
639
|
+
this.copyDir(srcPath, destPath);
|
|
640
|
+
} else {
|
|
641
|
+
fs.copyFileSync(srcPath, destPath);
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
```
|
|
647
|
+
|
|
648
|
+
```typescript
|
|
649
|
+
// src/platforms/claude.ts
|
|
650
|
+
import * as fs from 'fs';
|
|
651
|
+
import * as path from 'path';
|
|
652
|
+
import { PlatformInstaller } from './index';
|
|
653
|
+
|
|
654
|
+
export class ClaudeInstaller implements PlatformInstaller {
|
|
655
|
+
install(agentPath: string, targetDir: string): void {
|
|
656
|
+
// Claude Code expects: .claude/skills/<name>/SKILL.md
|
|
657
|
+
// Need to remove @ prefix for directory name
|
|
658
|
+
|
|
659
|
+
const agentName = path.basename(agentPath);
|
|
660
|
+
const cleanName = agentName.startsWith('@') ? agentName.slice(1) : agentName;
|
|
661
|
+
const targetPath = path.join(targetDir, '.claude', 'skills', cleanName);
|
|
662
|
+
|
|
663
|
+
if (!fs.existsSync(path.dirname(targetPath))) {
|
|
664
|
+
fs.mkdirSync(path.dirname(targetPath), { recursive: true });
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
this.copyDir(agentPath, targetPath);
|
|
668
|
+
console.log(`Installed ${cleanName} for Claude Code at: ${targetPath}`);
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
getAgentDir(workspacePath: string): string {
|
|
672
|
+
return path.join(workspacePath, '.claude', 'skills');
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
private copyDir(src: string, dest: string): void {
|
|
676
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
677
|
+
const entries = fs.readdirSync(src, { withFileTypes: true });
|
|
678
|
+
|
|
679
|
+
for (const entry of entries) {
|
|
680
|
+
const srcPath = path.join(src, entry.name);
|
|
681
|
+
const destPath = path.join(dest, entry.name);
|
|
682
|
+
|
|
683
|
+
if (entry.isDirectory()) {
|
|
684
|
+
this.copyDir(srcPath, destPath);
|
|
685
|
+
} else {
|
|
686
|
+
fs.copyFileSync(srcPath, destPath);
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
```
|
|
692
|
+
|
|
693
|
+
```typescript
|
|
694
|
+
// src/platforms/copilot.ts
|
|
695
|
+
import * as fs from 'fs';
|
|
696
|
+
import * as path from 'path';
|
|
697
|
+
import { PlatformInstaller } from './index';
|
|
698
|
+
|
|
699
|
+
export class CopilotInstaller implements PlatformInstaller {
|
|
700
|
+
install(agentPath: string, targetDir: string): void {
|
|
701
|
+
// Copilot expects: .github/copilot-instructions/<name>.md
|
|
702
|
+
// Convert SKILL.md content to markdown instructions
|
|
703
|
+
|
|
704
|
+
const agentName = path.basename(agentPath);
|
|
705
|
+
const cleanName = agentName.startsWith('@') ? agentName.slice(1) : agentName;
|
|
706
|
+
const targetPath = path.join(targetDir, '.github', 'copilot-instructions', `${cleanName}.md`);
|
|
707
|
+
|
|
708
|
+
if (!fs.existsSync(path.dirname(targetPath))) {
|
|
709
|
+
fs.mkdirSync(path.dirname(targetPath), { recursive: true });
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
// Convert skill to copilot instructions format
|
|
713
|
+
const skillMd = fs.readFileSync(path.join(agentPath, 'SKILL.md'), 'utf-8');
|
|
714
|
+
const instructions = this.convertToCopilotInstructions(skillMd);
|
|
715
|
+
|
|
716
|
+
fs.writeFileSync(targetPath, instructions);
|
|
717
|
+
console.log(`Installed ${cleanName} for Copilot at: ${targetPath}`);
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
getAgentDir(workspacePath: string): string {
|
|
721
|
+
return path.join(workspacePath, '.github', 'copilot-instructions');
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
private convertToCopilotInstructions(skillMd: string): string {
|
|
725
|
+
// Extract name and description from SKILL.md
|
|
726
|
+
const nameMatch = skillMd.match(/^name:\s*(.+)$/m);
|
|
727
|
+
const descMatch = skillMd.match(/^description:\s*(.+)$/m);
|
|
728
|
+
|
|
729
|
+
const name = nameMatch ? nameMatch[1] : 'Agent';
|
|
730
|
+
const desc = descMatch ? descMatch[1] : 'Workflow agent';
|
|
731
|
+
|
|
732
|
+
return `# ${name}\n\n${desc}\n\n## Usage\nUse this agent when working with this workflow.`;
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
```
|
|
736
|
+
|
|
737
|
+
```typescript
|
|
738
|
+
// src/platforms/gemini.ts
|
|
739
|
+
import * as fs from 'fs';
|
|
740
|
+
import * as path from 'path';
|
|
741
|
+
import { PlatformInstaller } from './index';
|
|
742
|
+
|
|
743
|
+
export class GeminiInstaller implements PlatformInstaller {
|
|
744
|
+
install(agentPath: string, targetDir: string): void {
|
|
745
|
+
// Gemini expects: .gemini/skills/<name>/instructions.md
|
|
746
|
+
|
|
747
|
+
const agentName = path.basename(agentPath);
|
|
748
|
+
const cleanName = agentName.startsWith('@') ? agentName.slice(1) : agentName;
|
|
749
|
+
const targetPath = path.join(targetDir, '.gemini', 'skills', cleanName, 'instructions.md');
|
|
750
|
+
|
|
751
|
+
if (!fs.existsSync(path.dirname(targetPath))) {
|
|
752
|
+
fs.mkdirSync(path.dirname(targetPath), { recursive: true });
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
// Convert SKILL.md to Gemini instructions format
|
|
756
|
+
const skillMd = fs.readFileSync(path.join(agentPath, 'SKILL.md'), 'utf-8');
|
|
757
|
+
const instructions = this.convertToGeminiInstructions(skillMd);
|
|
758
|
+
|
|
759
|
+
fs.writeFileSync(targetPath, instructions);
|
|
760
|
+
console.log(`Installed ${cleanName} for Gemini at: ${targetPath}`);
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
getAgentDir(workspacePath: string): string {
|
|
764
|
+
return path.join(workspacePath, '.gemini', 'skills');
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
private convertToGeminiInstructions(skillMd: string): string {
|
|
768
|
+
// Extract description from SKILL.md
|
|
769
|
+
const descMatch = skillMd.match(/^description:\s*(.+)$/m);
|
|
770
|
+
const desc = descMatch ? descMatch[1] : 'Workflow agent';
|
|
771
|
+
|
|
772
|
+
return `# Gemini Skill Instructions\n\n${desc}`;
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
```
|
|
776
|
+
|
|
777
|
+
- [ ] **Step 4: Run test to verify it passes**
|
|
778
|
+
|
|
779
|
+
Run: `npm test -- tests/platforms.test.ts`
|
|
780
|
+
Expected: PASS
|
|
781
|
+
|
|
782
|
+
- [ ] **Step 5: Commit**
|
|
783
|
+
|
|
784
|
+
```bash
|
|
785
|
+
git add src/platforms/ tests/platforms.test.ts
|
|
786
|
+
git commit -m "feat: add platform installers for multi-platform support"
|
|
787
|
+
```
|
|
788
|
+
|
|
789
|
+
---
|
|
790
|
+
|
|
791
|
+
## Task 4: Integrate with Scaffold
|
|
792
|
+
|
|
793
|
+
**Files:**
|
|
794
|
+
- Modify: `src/scripts/scaffold.ts`
|
|
795
|
+
- Modify: `src/index.ts`
|
|
796
|
+
|
|
797
|
+
- [ ] **Step 1: Add agent creation to scaffold.ts**
|
|
798
|
+
|
|
799
|
+
```typescript
|
|
800
|
+
// Add to src/scripts/scaffold.ts (near end of scaffoldWorkspace function)
|
|
801
|
+
// After writing workspace files, optionally create agent
|
|
802
|
+
|
|
803
|
+
export interface ScaffoldOptions {
|
|
804
|
+
name: string;
|
|
805
|
+
stages: string[];
|
|
806
|
+
output: string;
|
|
807
|
+
force?: boolean;
|
|
808
|
+
createAgent?: boolean;
|
|
809
|
+
agentName?: string;
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
// Add at end of scaffoldWorkspace (after line 52):
|
|
813
|
+
if (options.createAgent !== false) {
|
|
814
|
+
const { createAgent } = await import('../agent-creator');
|
|
815
|
+
const agentName = options.agentName ?? generateAgentName(name);
|
|
816
|
+
createAgent({
|
|
817
|
+
name: agentName,
|
|
818
|
+
purpose: `Execute ${name} workflow`,
|
|
819
|
+
workspacePath: outputDir,
|
|
820
|
+
});
|
|
821
|
+
}
|
|
822
|
+
```
|
|
823
|
+
|
|
824
|
+
- [ ] **Step 2: Add new CLI options to index.ts**
|
|
825
|
+
|
|
826
|
+
```typescript
|
|
827
|
+
// In src/index.ts, modify options:
|
|
828
|
+
// Add: --with-agent, --no-agent, --agent-name
|
|
829
|
+
|
|
830
|
+
async function main(): Promise<void> {
|
|
831
|
+
const args = process.argv.slice(2);
|
|
832
|
+
|
|
833
|
+
// ... existing code ...
|
|
834
|
+
|
|
835
|
+
// Find which agent target
|
|
836
|
+
const agentFlags = ['opencode', 'claude', 'copilot', 'gemini'];
|
|
837
|
+
const detectedAgent = agentFlags.find((flag) => args.includes(`--${flag}`));
|
|
838
|
+
|
|
839
|
+
// Check for workspace creation flags
|
|
840
|
+
const createWorkspace = args.includes('--create-workspace');
|
|
841
|
+
const withAgent = !args.includes('--no-agent');
|
|
842
|
+
const agentName = extractOption(args, '--agent-name');
|
|
843
|
+
const workspaceName = extractOption(args, '--workspace-name') ?? 'My Workspace';
|
|
844
|
+
const stages = extractOption(args, '--stages') ?? '01-input,02-process,03-output';
|
|
845
|
+
|
|
846
|
+
if (createWorkspace) {
|
|
847
|
+
// Run workspace creation with agent
|
|
848
|
+
const { scaffoldWorkspace } = await import('./scripts/scaffold');
|
|
849
|
+
const { createAgent } = await import('./agent-creator');
|
|
850
|
+
const { iterateAgent } = await import('./agent-iterator');
|
|
851
|
+
|
|
852
|
+
const outputDir = path.resolve(process.cwd(), 'workspace');
|
|
853
|
+
const stageList = stages.split(',').map(s => s.trim());
|
|
854
|
+
|
|
855
|
+
// Create workspace
|
|
856
|
+
scaffoldWorkspace({
|
|
857
|
+
name: workspaceName,
|
|
858
|
+
stages: stageList,
|
|
859
|
+
output: outputDir,
|
|
860
|
+
});
|
|
861
|
+
|
|
862
|
+
// Create agent if enabled
|
|
863
|
+
if (withAgent) {
|
|
864
|
+
const finalAgentName = agentName ?? `@${workspaceName.toLowerCase().replace(/\s+/g, '-')}`;
|
|
865
|
+
createAgent({
|
|
866
|
+
name: finalAgentName,
|
|
867
|
+
purpose: `Execute ${workspaceName} workflow`,
|
|
868
|
+
workspacePath: outputDir,
|
|
869
|
+
});
|
|
870
|
+
|
|
871
|
+
// Run agent iteration for self-improvement
|
|
872
|
+
const agentDir = path.join(outputDir, '.agents', 'skills', finalAgentName.startsWith('@') ? finalAgentName.slice(1) : finalAgentName);
|
|
873
|
+
console.log('\nRunning agent self-improvement...');
|
|
874
|
+
await iterateAgent({
|
|
875
|
+
agentPath: agentDir,
|
|
876
|
+
workspacePath: outputDir,
|
|
877
|
+
});
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
console.log(`\nWorkspace created at: ${outputDir}`);
|
|
881
|
+
if (withAgent) {
|
|
882
|
+
console.log(`Agent "${agentName}" is ready to use with @ invocation`);
|
|
883
|
+
}
|
|
884
|
+
return;
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
// ... rest of existing install logic ...
|
|
888
|
+
}
|
|
889
|
+
```
|
|
890
|
+
|
|
891
|
+
- [ ] **Step 3: Test the integration**
|
|
892
|
+
|
|
893
|
+
Run: `node dist/index.js --create-workspace --workspace-name "Daily Digest" --stages "01-input,02-process,03-output"`
|
|
894
|
+
Expected: Creates workspace folder + @daily-digest agent
|
|
895
|
+
|
|
896
|
+
- [ ] **Step 4: Commit**
|
|
897
|
+
|
|
898
|
+
```bash
|
|
899
|
+
git add src/scripts/scaffold.ts src/index.ts
|
|
900
|
+
git commit -m "feat: integrate agent creation with workspace scaffolding"
|
|
901
|
+
```
|
|
902
|
+
|
|
903
|
+
---
|
|
904
|
+
|
|
905
|
+
## Task 5: Update SKILL.md with New Workflow
|
|
906
|
+
|
|
907
|
+
**Files:**
|
|
908
|
+
- Modify: `templates/SKILL.md`
|
|
909
|
+
|
|
910
|
+
- [ ] **Step 1: Update SKILL.md**
|
|
911
|
+
|
|
912
|
+
Update the main SKILL.md to document:
|
|
913
|
+
1. New `--create-workspace` flag
|
|
914
|
+
2. Agent creation behavior (default on, `--no-agent` to disable)
|
|
915
|
+
3. Agent naming
|
|
916
|
+
4. Self-improvement during build
|
|
917
|
+
|
|
918
|
+
```markdown
|
|
919
|
+
## New Commands
|
|
920
|
+
|
|
921
|
+
### Create Workspace with Agent (Default)
|
|
922
|
+
```bash
|
|
923
|
+
npx workspace-maxxing --create-workspace --workspace-name "My Workflow" --stages "01-input,02-process,03-output"
|
|
924
|
+
```
|
|
925
|
+
|
|
926
|
+
Creates:
|
|
927
|
+
- ICM workspace folder structure
|
|
928
|
+
- Invokable @agent (e.g., `@my-workflow`)
|
|
929
|
+
- Runs self-improvement loop until robustness >= 85
|
|
930
|
+
|
|
931
|
+
### Create Workspace Without Agent
|
|
932
|
+
```bash
|
|
933
|
+
npx workspace-maxxing --create-workspace --workspace-name "My Workflow" --stages "01-input,02-process" --no-agent
|
|
934
|
+
```
|
|
935
|
+
|
|
936
|
+
### Custom Agent Name
|
|
937
|
+
```bash
|
|
938
|
+
npx workspace-maxxing --create-workspace --workspace-name "Daily Digest" --agent-name "@news-agent"
|
|
939
|
+
```
|
|
940
|
+
|
|
941
|
+
## Agent Invocation
|
|
942
|
+
|
|
943
|
+
After workspace is created, invoke the agent:
|
|
944
|
+
- OpenCode: `@daily-digest`
|
|
945
|
+
- Claude Code: Via .claude/skills/ directory
|
|
946
|
+
- Copilot: Via .github/copilot-instructions/
|
|
947
|
+
- Gemini: Via .gemini/skills/ directory
|
|
948
|
+
|
|
949
|
+
## Self-Improvement
|
|
950
|
+
|
|
951
|
+
When agent is created, it runs through iteration:
|
|
952
|
+
1. Generates test cases (edge, empty, varied)
|
|
953
|
+
2. Runs agent with each test case
|
|
954
|
+
3. Scores robustness (0-100)
|
|
955
|
+
4. If score < 85: improves prompts, retries
|
|
956
|
+
5. Continues until threshold met or max iterations (3)
|
|
957
|
+
|
|
958
|
+
This ensures the delivered agent is robust for real use.
|
|
959
|
+
```
|
|
960
|
+
|
|
961
|
+
- [ ] **Step 2: Commit**
|
|
962
|
+
|
|
963
|
+
```bash
|
|
964
|
+
git add templates/SKILL.md
|
|
965
|
+
git commit -m "docs: update SKILL.md with new agent creation workflow"
|
|
966
|
+
```
|
|
967
|
+
|
|
968
|
+
---
|
|
969
|
+
|
|
970
|
+
## Spec Coverage Check
|
|
971
|
+
|
|
972
|
+
| Spec Section | Task Coverage |
|
|
973
|
+
|--------------|--------------|
|
|
974
|
+
| Creates invokable sub-agent | Task 1 (agent-creator) |
|
|
975
|
+
| Agent implements workflow use case | Task 1 (SKILL.md generation) |
|
|
976
|
+
| Self-improvement during build | Task 2 (agent-iterator) |
|
|
977
|
+
| Backward compatible | Task 4 (--no-agent flag) |
|
|
978
|
+
| Multi-platform support | Task 3 (platform installers) |
|
|
979
|
+
| Agent naming pattern | Task 1 (generateAgentName) |
|
|
980
|
+
| Robustness threshold | Task 2 (threshold param) |
|
|
981
|
+
|
|
982
|
+
---
|
|
983
|
+
|
|
984
|
+
## Execution Choice
|
|
985
|
+
|
|
986
|
+
**Plan complete and saved to `docs/superpowers/plans/2026-04-12-workspace-agent-creation-plan.md`. Two execution options:**
|
|
987
|
+
|
|
988
|
+
**1. Subagent-Driven (recommended)** - I dispatch a fresh subagent per task, review between tasks, fast iteration
|
|
989
|
+
|
|
990
|
+
**2. Inline Execution** - Execute tasks in this session using executing-plans, batch execution with checkpoints
|
|
991
|
+
|
|
992
|
+
**Which approach?**
|