sdd-toolkit 2.0.1 → 2.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/README.md +21 -34
- package/definitions/sdd-coder.yaml +4 -5
- package/definitions/sdd-project.yaml +0 -1
- package/definitions/sdd-requirements.yaml +75 -10
- package/definitions/sdd-review.yaml +4 -5
- package/package.json +1 -1
- package/src/index.js +97 -120
- package/src/lib/agents.js +9 -18
- package/src/lib/docs.js +0 -1
- package/src/lib/messages.js +15 -15
- package/src/lib/transformers.js +40 -26
- package/src/scripts/reset.js +1 -1
- package/templates/requirements.md +23 -0
- package/src/lib/profiles.js +0 -186
- package/templates/guidelines.md +0 -9
package/README.md
CHANGED
|
@@ -190,18 +190,17 @@ Once agents are installed, use these commands in your AI coding assistant:
|
|
|
190
190
|
|
|
191
191
|
After running `sdd-toolkit`, the following structure is created in your project:
|
|
192
192
|
|
|
193
|
-
```
|
|
194
|
-
.sdd-toolkit/
|
|
195
|
-
├── project.md # Project scope and principles
|
|
196
|
-
├── requirements.md # Technical requirements and stack
|
|
197
|
-
├──
|
|
198
|
-
├──
|
|
199
|
-
├──
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
├── logs
|
|
203
|
-
│ ├──
|
|
204
|
-
│ ├── reviews/ # Code review reports
|
|
193
|
+
```
|
|
194
|
+
.sdd-toolkit/
|
|
195
|
+
├── project.md # Project scope and principles
|
|
196
|
+
├── requirements.md # Technical requirements and stack
|
|
197
|
+
├── milestones.md # Development roadmap
|
|
198
|
+
├── task.md # Task execution backlog
|
|
199
|
+
├── features/ # Individual feature specifications
|
|
200
|
+
│ └── [feature-name].md
|
|
201
|
+
├── logs/
|
|
202
|
+
│ ├── executions/ # Task execution logs
|
|
203
|
+
│ ├── reviews/ # Code review reports
|
|
205
204
|
│ └── archive/ # Archived completed work
|
|
206
205
|
└── agents/ # Custom agent definitions (optional overrides)
|
|
207
206
|
```
|
|
@@ -328,19 +327,7 @@ MIT
|
|
|
328
327
|
- Re-run `sdd-toolkit` and ensure you select the correct language during setup (English, Portuguese, or Spanish).
|
|
329
328
|
- Or manually edit the `LANGUAGE_RULES` in your agent files.
|
|
330
329
|
|
|
331
|
-
###
|
|
332
|
-
|
|
333
|
-
**Problem:** Selected stack profile rules are not being used by agents.
|
|
334
|
-
|
|
335
|
-
**Solution:**
|
|
336
|
-
|
|
337
|
-
- The stack profile is only applied during initial installation or upgrade. Run:
|
|
338
|
-
```bash
|
|
339
|
-
sdd-toolkit upgrade
|
|
340
|
-
```
|
|
341
|
-
Ensure you select the same stack profile again.
|
|
342
|
-
|
|
343
|
-
### `.sdd-toolkit/` folder not created
|
|
330
|
+
### `.sdd-toolkit/` folder not created
|
|
344
331
|
|
|
345
332
|
**Problem:** The hidden folder structure is not created after installation.
|
|
346
333
|
|
|
@@ -356,9 +343,9 @@ MIT
|
|
|
356
343
|
|
|
357
344
|
A: Yes! You can install agents for multiple AI tools in the same project. Each tool has its own folder structure (`.roo/`, `.cline/`, `.cursor/`, etc.) and they can coexist without conflicts.
|
|
358
345
|
|
|
359
|
-
**Q: How do I update agents after initial setup?**
|
|
360
|
-
|
|
361
|
-
A: Run `sdd-toolkit upgrade`. This will update all installed agents without requiring you to reconfigure
|
|
346
|
+
**Q: How do I update agents after initial setup?**
|
|
347
|
+
|
|
348
|
+
A: Run `sdd-toolkit upgrade`. This will update all installed agents without requiring you to reconfigure global rules.
|
|
362
349
|
|
|
363
350
|
**Q: Can I customize agent definitions?**
|
|
364
351
|
|
|
@@ -384,10 +371,10 @@ A: Simply delete the `.sdd-toolkit/` folder and any tool-specific folders (`.roo
|
|
|
384
371
|
|
|
385
372
|
A: No, sdd-toolkit only manages documentation and AI agent configurations. It does not track code changes, read your source files, or interfere with version control.
|
|
386
373
|
|
|
387
|
-
**Q:
|
|
388
|
-
|
|
389
|
-
A:
|
|
390
|
-
|
|
391
|
-
**Q: Is this suitable for enterprise projects?**
|
|
374
|
+
**Q: How do I define my tech stack and conventions?**
|
|
375
|
+
|
|
376
|
+
A: Use the Requirements Engineer agent (`/sdd.requirements`) to define your tech stack. The agent will interview you with detailed questions about frontend, backend, database, and infrastructure. Stack-specific conventions can also be added via "Global Rules" during setup or by manually editing `.sdd-toolkit/requirements.md`.
|
|
392
377
|
|
|
393
|
-
|
|
378
|
+
**Q: Is this suitable for enterprise projects?**
|
|
379
|
+
|
|
380
|
+
A: Yes, sdd-toolkit is designed to scale. The `.sdd-toolkit/` folder can be committed to your repository, ensuring all team members use the same agent configurations and follow the same development principles defined in `requirements.md` and `project.md`. Stack-specific conventions are automatically applied via selected profile during agent installation.
|
|
@@ -15,15 +15,14 @@ systemPrompt: |
|
|
|
15
15
|
|
|
16
16
|
# INPUT CONTEXT - LAYERED READING PROTOCOL
|
|
17
17
|
|
|
18
|
-
## L1: Global Context (ALWAYS READ -
|
|
18
|
+
## L1: Global Context (ALWAYS READ - 2 files)
|
|
19
19
|
1. Read `.sdd-toolkit/context.md` (Feature matrix + executive summary)
|
|
20
20
|
2. Read `.sdd-toolkit/requirements.md` (Tech stack + business rules)
|
|
21
|
-
3. Read `.sdd-toolkit/guidelines.md` (Code conventions)
|
|
22
21
|
|
|
23
22
|
## L2: Feature Context (READ IF WORKING ON FEATURE - 3 files)
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
3. Read `.sdd-toolkit/features/[feature-slug]/index.md` (Feature overview)
|
|
24
|
+
4. Read `.sdd-toolkit/features/[feature-slug]/state.md` (Progress + context + files)
|
|
25
|
+
5. Read `.sdd-toolkit/features/[feature-slug]/[MILESTONE].md` (Tasks from Task_ID)
|
|
27
26
|
|
|
28
27
|
## L2.1 Validate Feature Files Existence (BEFORE READING)
|
|
29
28
|
Before reading L2 files, verify that feature structure exists:
|
|
@@ -15,9 +15,48 @@ systemPrompt: |
|
|
|
15
15
|
1. Verify the existence of `.sdd-toolkit/project.md`.
|
|
16
16
|
2. If the project is of type **Formalization (Hybrid)**, ask to see examples of error logs, current database schemas, or existing API documentation to ensure requirements respect the legacy system.
|
|
17
17
|
|
|
18
|
+
## Stack Definition Protocol (New - Enhanced)
|
|
19
|
+
Before generating requirements, check if Tech Stack is already defined in `.sdd-toolkit/requirements.md`:
|
|
20
|
+
|
|
21
|
+
### If Tech Stack is UNDEFINED:
|
|
22
|
+
You MUST interview the user with DETAILED questions (Mode 3 - Stack Interview):
|
|
23
|
+
|
|
24
|
+
#### Frontend Stack:
|
|
25
|
+
1. **Framework:** React, Vue, Angular, Next.js, SvelteKit, Nuxt.js, None
|
|
26
|
+
2. **Styling:** Tailwind CSS, CSS Modules, Styled Components, SCSS, None
|
|
27
|
+
3. **State Management:** Redux, Zustand, Pinia, NgRx, Context API, None
|
|
28
|
+
4. **Testing:** Jest + Testing Library, Vitest, Cypress, Playwright, None
|
|
29
|
+
5. **Build Tool:** Vite, Webpack, Next.js built-in, None
|
|
30
|
+
|
|
31
|
+
#### Backend Stack:
|
|
32
|
+
1. **Language:** JavaScript/Node.js, TypeScript, Python, Go, Java, C#, Rust, Other
|
|
33
|
+
2. **Framework:** Express, NestJS, FastAPI, Django, Spring Boot, .NET, Gin, Fiber, None
|
|
34
|
+
3. **API Style:** RESTful, GraphQL, gRPC, None
|
|
35
|
+
4. **Authentication:** JWT, OAuth 2.0, Session-based, None
|
|
36
|
+
5. **Testing:** Jest, Pytest, Go test, JUnit, NUnit, None
|
|
37
|
+
|
|
38
|
+
#### Database & Storage:
|
|
39
|
+
1. **Primary Database:** PostgreSQL, MySQL, MongoDB, SQLite, Redis, TBD
|
|
40
|
+
2. **ORM:** Prisma, SQLAlchemy, TypeORM, Mongoose, GORM, None
|
|
41
|
+
3. **Migration Tool:** Prisma Migrate, Alembic, Flyway, None
|
|
42
|
+
|
|
43
|
+
#### DevOps & Infrastructure:
|
|
44
|
+
1. **Containerization:** Docker, Podman, None
|
|
45
|
+
2. **CI/CD:** GitHub Actions, GitLab CI, Jenkins, None
|
|
46
|
+
3. **Hosting:** Vercel, Netlify, AWS, Railway, Render, None
|
|
47
|
+
|
|
48
|
+
**Interview Rules:**
|
|
49
|
+
- Ask ONE question at a time
|
|
50
|
+
- Wait for user response before asking next
|
|
51
|
+
- If user answers "TBD" or "None", document as TBD
|
|
52
|
+
- If user answers "Other", ask for clarification
|
|
53
|
+
|
|
54
|
+
### If Tech Stack is ALREADY DEFINED:
|
|
55
|
+
Respect the defined stack and do NOT re-interview the user.
|
|
56
|
+
|
|
18
57
|
## Golden Constraints (Hard Rules)
|
|
19
58
|
* **Scope Fidelity:** If something is not in `project.md`, you cannot create requirements for it. If you notice a gap, ask the user to return to the Project Architect.
|
|
20
|
-
* **Tech Agnostic:** You do not decide if the database is SQL or NoSQL.
|
|
59
|
+
* **Tech Agnostic:** You do not auto-decide if the database is SQL or NoSQL. If tech stack is NOT defined in requirements.md, use Stack Definition Protocol to ask the user. If already defined, respect the defined stack.
|
|
21
60
|
* **Code Prohibition:** You never write code.
|
|
22
61
|
|
|
23
62
|
## Modes of Operation
|
|
@@ -35,37 +74,63 @@ systemPrompt: |
|
|
|
35
74
|
```markdown
|
|
36
75
|
# 📋 Requirements Specification
|
|
37
76
|
|
|
38
|
-
## 1.
|
|
77
|
+
## 1. Tech Stack and Standards (Tech Constraints)
|
|
78
|
+
|
|
79
|
+
### Frontend
|
|
80
|
+
- **Framework:** [React / Vue / Angular / Next.js / SvelteKit / Nuxt.js / None]
|
|
81
|
+
- **Styling:** [Tailwind CSS / CSS Modules / Styled Components / SCSS / None]
|
|
82
|
+
- **State Management:** [Redux / Zustand / Pinia / NgRx / Context API / None]
|
|
83
|
+
- **Testing:** [Jest + Testing Library / Vitest / Cypress / Playwright / None]
|
|
84
|
+
|
|
85
|
+
### Backend
|
|
86
|
+
- **Language:** [JavaScript / TypeScript / Python / Go / Java / C# / Rust]
|
|
87
|
+
- **Framework:** [Express / NestJS / FastAPI / Django / Spring Boot / .NET / None]
|
|
88
|
+
- **API Style:** [RESTful / GraphQL / gRPC / None]
|
|
89
|
+
- **Authentication:** [JWT / OAuth 2.0 / Session-based / None]
|
|
90
|
+
- **Testing:** [Jest / Pytest / Go test / JUnit / NUnit / None]
|
|
91
|
+
|
|
92
|
+
### Database & Storage
|
|
93
|
+
- **Primary Database:** [PostgreSQL / MySQL / MongoDB / SQLite / Redis / TBD]
|
|
94
|
+
- **ORM:** [Prisma / SQLAlchemy / TypeORM / Mongoose / GORM / None]
|
|
95
|
+
- **Migration Tool:** [Prisma Migrate / Alembic / Flyway / None]
|
|
96
|
+
|
|
97
|
+
### DevOps & Infrastructure
|
|
98
|
+
- **Containerization:** [Docker / Podman / None]
|
|
99
|
+
- **CI/CD:** [GitHub Actions / GitLab CI / Jenkins / None]
|
|
100
|
+
- **Hosting:** [Vercel / Netlify / AWS / Railway / Render / None]
|
|
101
|
+
|
|
102
|
+
## 2. Summary and Traceability
|
|
39
103
|
- **Project:** [Project Name]
|
|
40
104
|
- **Based on:** `.sdd-toolkit/project.md` (v.X.Y.Z)
|
|
41
105
|
|
|
42
|
-
##
|
|
106
|
+
## 3. Functional Requirements (FR)
|
|
43
107
|
| ID | Module | Behavior Description | Acceptance Criteria (Checklist) |
|
|
44
108
|
|:---|:---|:---|:---|
|
|
45
109
|
| RF-001 | [Name] | The system must [action] when [trigger]. | - [ ] Criteria 1 <br> - [ ] Criteria 2 |
|
|
46
110
|
|
|
47
|
-
##
|
|
111
|
+
## 4. User Stories (User Perspective)
|
|
48
112
|
- **As** [persona], **I want** [feature] **so that** [business value].
|
|
49
113
|
|
|
50
|
-
##
|
|
114
|
+
## 5. Non-Functional Requirements (NFR)
|
|
51
115
|
- **RNF-001 [Security]:** Technical description of the need.
|
|
52
116
|
- **RNF-002 [Performance]:** E.g.: Response time must not exceed 200ms.
|
|
53
117
|
|
|
54
|
-
##
|
|
118
|
+
## 6. Business Rules (BR) and Validations
|
|
55
119
|
- **RB-001:** [Clear rule, e.g.: "Only over 18s can register"].
|
|
56
120
|
- **RB-002:** [Calculation flow or system states].
|
|
57
121
|
|
|
58
|
-
##
|
|
59
|
-
- **E-001:** If connection drops during upload,
|
|
122
|
+
## 7. Exception Matrix (Edge Cases)
|
|
123
|
+
- **E-001:** If connection drops during upload, system must [behavior].
|
|
60
124
|
|
|
61
|
-
##
|
|
125
|
+
## 8. Rationale and Discarded Items
|
|
62
126
|
- Justification for requirements that seemed necessary but violated scope.
|
|
63
127
|
```
|
|
64
128
|
|
|
65
|
-
rules:
|
|
129
|
+
rules:
|
|
66
130
|
- "**BE SPECIFIC:** If the user did not define a library, **suggest market standard** for the chosen stack (e.g., If React, suggest React Hook Form), but mark as a suggestion."
|
|
67
131
|
- "**UNIQUE IDS:** Keep IDs (FR-XX, BR-XX)."
|
|
68
132
|
- "**TECH FIRST:** The goal of this step is to lock technical decisions so the programmer (Tasks Agent) does not need to \"invent\" architecture."
|
|
133
|
+
- "**STACK FIRST:** If tech stack is NOT defined in requirements.md, use Stack Definition Protocol to interview user before documenting requirements. If already defined, respect the stack and do NOT re-interview."
|
|
69
134
|
- "**FILE OPS:** Save strictly as `.sdd-toolkit/requirements.md`."
|
|
70
135
|
- "**DECISIVENESS:** Max 3 clarifying questions. For non-critical details, make an informed assumption (standard market practice) and document it."
|
|
71
136
|
- "Language Adaptability: Respond in English by default. If the user speaks in another language, mirror their language."
|
|
@@ -24,15 +24,14 @@ systemPrompt: |
|
|
|
24
24
|
|
|
25
25
|
## INPUT CONTEXT & WORKFLOW
|
|
26
26
|
|
|
27
|
-
## L1: Global Context (ALWAYS READ -
|
|
27
|
+
## L1: Global Context (ALWAYS READ - 2 files)
|
|
28
28
|
1. Read `.sdd-toolkit/context.md` (Feature matrix + executive summary)
|
|
29
29
|
2. Read `.sdd-toolkit/requirements.md` (Tech stack + business rules)
|
|
30
|
-
3. Read `.sdd-toolkit/guidelines.md` (Code conventions)
|
|
31
30
|
|
|
32
31
|
## L2: Feature Context (READ IF WORKING ON FEATURE - 3 files)
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
32
|
+
3. Read `.sdd-toolkit/features/[feature-slug]/index.md` (Feature overview)
|
|
33
|
+
4. Read `.sdd-toolkit/features/[feature-slug]/state.md` (Progress + context + files)
|
|
34
|
+
5. Read `.sdd-toolkit/features/[feature-slug]/[MILESTONE].md` (Tasks)
|
|
36
35
|
|
|
37
36
|
## L3: Task Context (READ ON DEMAND)
|
|
38
37
|
7. Read `.sdd-toolkit/logs/executions/[Task_ID].md` (Developer execution log)
|
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -8,7 +8,6 @@ const pc = require('picocolors');
|
|
|
8
8
|
|
|
9
9
|
// Internal Modules
|
|
10
10
|
const { loadAgents } = require('./lib/agents');
|
|
11
|
-
const { STACK_PROFILES } = require('./lib/profiles');
|
|
12
11
|
const { setLocale, t, getLocale } = require('./lib/i18n');
|
|
13
12
|
const {
|
|
14
13
|
toGeminiTOML,
|
|
@@ -20,7 +19,8 @@ const {
|
|
|
20
19
|
toClaudeCommand,
|
|
21
20
|
toPlainSystemPrompt,
|
|
22
21
|
toTraeRules,
|
|
23
|
-
|
|
22
|
+
toOpenCodeSkill,
|
|
23
|
+
toAntigravitySkill
|
|
24
24
|
} = require('./lib/transformers');
|
|
25
25
|
const { generateWorkflowGuide } = require('./lib/docs');
|
|
26
26
|
const { view } = require('./commands/view');
|
|
@@ -72,11 +72,12 @@ async function main() {
|
|
|
72
72
|
if (fs.existsSync(path.join(process.cwd(), '.claude'))) tools.push('claude');
|
|
73
73
|
if (fs.existsSync(path.join(process.cwd(), '.trae'))) tools.push('trae');
|
|
74
74
|
if (fs.existsSync(path.join(process.cwd(), '.kilocode'))) tools.push('kilo');
|
|
75
|
-
if (fs.existsSync(path.join(process.cwd(), '.github'))) tools.push('copilot');
|
|
75
|
+
if (fs.existsSync(path.join(process.cwd(), '.github'))) tools.push('copilot');
|
|
76
76
|
if (fs.existsSync(path.join(process.cwd(), '.roo'))) tools.push('roo');
|
|
77
77
|
if (fs.existsSync(path.join(process.cwd(), '.opencode'))) tools.push('opencode');
|
|
78
78
|
if (fs.existsSync(path.join(process.cwd(), 'prompts'))) tools.push('web');
|
|
79
79
|
|
|
80
|
+
if (fs.existsSync(path.join(process.cwd(), '.antigravity'))) tools.push('antigravity');
|
|
80
81
|
if (tools.length === 0) {
|
|
81
82
|
note(t('UPGRADE.NO_CONFIG'), t('UPGRADE.NO_CONFIG_TITLE'));
|
|
82
83
|
} else {
|
|
@@ -102,24 +103,7 @@ async function main() {
|
|
|
102
103
|
s.stop(pc.red(t('SCAFFOLD.ERROR')));
|
|
103
104
|
}
|
|
104
105
|
|
|
105
|
-
// 2. Feature
|
|
106
|
-
const stackOptions = Object.entries(STACK_PROFILES).map(([key, profile]) => ({
|
|
107
|
-
value: key,
|
|
108
|
-
label: profile.label
|
|
109
|
-
}));
|
|
110
|
-
|
|
111
|
-
const stackProfile = await select({
|
|
112
|
-
message: t('SETUP.STACK_SELECT'),
|
|
113
|
-
options: stackOptions,
|
|
114
|
-
initialValue: 'generic'
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
if (typeof stackProfile === 'symbol') {
|
|
118
|
-
outro(pc.yellow(t('GENERAL.CANCELLED')));
|
|
119
|
-
process.exit(0);
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
// 3. Feature 3: Global Rules
|
|
106
|
+
// 2. Feature 3: Global Rules
|
|
123
107
|
const globalRules = await text({
|
|
124
108
|
message: t('SETUP.GLOBAL_RULES'),
|
|
125
109
|
placeholder: t('SETUP.GLOBAL_RULES_HINT'),
|
|
@@ -145,7 +129,8 @@ async function main() {
|
|
|
145
129
|
{ value: 'kilo', label: t('TOOLS.KILO'), hint: '.kilocode/workflows/*.md' },
|
|
146
130
|
{ value: 'copilot', label: t('TOOLS.COPILOT'), hint: '.github/prompts/*.md' },
|
|
147
131
|
{ value: 'web', label: t('TOOLS.WEB'), hint: 'prompts/*.txt' },
|
|
148
|
-
{ value: 'opencode', label: t('TOOLS.OPENCODE'), hint: '.opencode/
|
|
132
|
+
{ value: 'opencode', label: t('TOOLS.OPENCODE'), hint: '.opencode/skills/*' },
|
|
133
|
+
{ value: 'antigravity', label: t('TOOLS.ANTIGRAVITY'), hint: '.antigravity/skills/*' }
|
|
149
134
|
],
|
|
150
135
|
required: true,
|
|
151
136
|
hint: t('SETUP.TOOL_HINT')
|
|
@@ -161,7 +146,7 @@ async function main() {
|
|
|
161
146
|
process.exit(0);
|
|
162
147
|
}
|
|
163
148
|
|
|
164
|
-
await processAgentsInstallation(tools, {
|
|
149
|
+
await processAgentsInstallation(tools, { globalRules, locale: getLocale() });
|
|
165
150
|
|
|
166
151
|
outro(pc.green(t('SETUP.SUCCESS')));
|
|
167
152
|
}
|
|
@@ -193,17 +178,17 @@ async function processAgentsInstallation(tools, options) {
|
|
|
193
178
|
})
|
|
194
179
|
);
|
|
195
180
|
},
|
|
196
|
-
roo: async (validAgents, options) => {
|
|
197
|
-
const targetDir = path.join(process.cwd(), '.roo', 'commands');
|
|
198
|
-
await fsp.mkdir(targetDir, { recursive: true });
|
|
199
|
-
|
|
200
|
-
await Promise.all(
|
|
201
|
-
validAgents.map((agent) => {
|
|
202
|
-
const md = toOpenCodeAgent(agent, options);
|
|
203
|
-
return fsp.writeFile(path.join(targetDir, `${agent.slug}.md`), md);
|
|
204
|
-
})
|
|
205
|
-
);
|
|
206
|
-
},
|
|
181
|
+
roo: async (validAgents, options) => {
|
|
182
|
+
const targetDir = path.join(process.cwd(), '.roo', 'commands');
|
|
183
|
+
await fsp.mkdir(targetDir, { recursive: true });
|
|
184
|
+
|
|
185
|
+
await Promise.all(
|
|
186
|
+
validAgents.map((agent) => {
|
|
187
|
+
const md = toOpenCodeAgent(agent, options);
|
|
188
|
+
return fsp.writeFile(path.join(targetDir, `${agent.slug}.md`), md);
|
|
189
|
+
})
|
|
190
|
+
);
|
|
191
|
+
},
|
|
207
192
|
cline: async (validAgents, options) => {
|
|
208
193
|
const targetDir = path.join(process.cwd(), '.cline');
|
|
209
194
|
await fsp.mkdir(targetDir, { recursive: true });
|
|
@@ -230,31 +215,31 @@ async function processAgentsInstallation(tools, options) {
|
|
|
230
215
|
})
|
|
231
216
|
);
|
|
232
217
|
},
|
|
233
|
-
claude: async (validAgents, options) => {
|
|
234
|
-
const targetDir = path.join(process.cwd(), '.claude', 'commands', 'agents');
|
|
235
|
-
await fsp.mkdir(targetDir, { recursive: true });
|
|
236
|
-
|
|
237
|
-
await Promise.all(
|
|
238
|
-
validAgents.map((agent) => {
|
|
239
|
-
const md = toClaudeCommand(agent, options);
|
|
240
|
-
return fsp.writeFile(path.join(targetDir, `${agent.slug}.md`), md);
|
|
241
|
-
})
|
|
242
|
-
);
|
|
243
|
-
},
|
|
244
|
-
cursor: async (validAgents, options) => {
|
|
245
|
-
const commandsDir = path.join(process.cwd(), '.cursor', 'commands');
|
|
246
|
-
await fsp.mkdir(commandsDir, { recursive: true });
|
|
247
|
-
|
|
248
|
-
await Promise.all(
|
|
249
|
-
validAgents.map((agent) => {
|
|
250
|
-
const mdc = toCursorMDC(agent, options);
|
|
251
|
-
return fsp.writeFile(path.join(commandsDir, `${agent.slug}.mdc`), mdc);
|
|
252
|
-
})
|
|
253
|
-
);
|
|
254
|
-
},
|
|
255
|
-
kilo: async (validAgents, options) => {
|
|
256
|
-
const targetDir = path.join(process.cwd(), '.kilocode', 'workflows');
|
|
257
|
-
await fsp.mkdir(targetDir, { recursive: true });
|
|
218
|
+
claude: async (validAgents, options) => {
|
|
219
|
+
const targetDir = path.join(process.cwd(), '.claude', 'commands', 'agents');
|
|
220
|
+
await fsp.mkdir(targetDir, { recursive: true });
|
|
221
|
+
|
|
222
|
+
await Promise.all(
|
|
223
|
+
validAgents.map((agent) => {
|
|
224
|
+
const md = toClaudeCommand(agent, options);
|
|
225
|
+
return fsp.writeFile(path.join(targetDir, `${agent.slug}.md`), md);
|
|
226
|
+
})
|
|
227
|
+
);
|
|
228
|
+
},
|
|
229
|
+
cursor: async (validAgents, options) => {
|
|
230
|
+
const commandsDir = path.join(process.cwd(), '.cursor', 'commands');
|
|
231
|
+
await fsp.mkdir(commandsDir, { recursive: true });
|
|
232
|
+
|
|
233
|
+
await Promise.all(
|
|
234
|
+
validAgents.map((agent) => {
|
|
235
|
+
const mdc = toCursorMDC(agent, options);
|
|
236
|
+
return fsp.writeFile(path.join(commandsDir, `${agent.slug}.mdc`), mdc);
|
|
237
|
+
})
|
|
238
|
+
);
|
|
239
|
+
},
|
|
240
|
+
kilo: async (validAgents, options) => {
|
|
241
|
+
const targetDir = path.join(process.cwd(), '.kilocode', 'workflows');
|
|
242
|
+
await fsp.mkdir(targetDir, { recursive: true });
|
|
258
243
|
|
|
259
244
|
await Promise.all(
|
|
260
245
|
validAgents.map((agent) => {
|
|
@@ -263,22 +248,22 @@ async function processAgentsInstallation(tools, options) {
|
|
|
263
248
|
})
|
|
264
249
|
);
|
|
265
250
|
},
|
|
266
|
-
copilot: async (validAgents, options) => {
|
|
267
|
-
const githubDir = path.join(process.cwd(), '.github');
|
|
268
|
-
const promptsDir = path.join(githubDir, 'prompts');
|
|
269
|
-
await fsp.mkdir(promptsDir, { recursive: true });
|
|
270
|
-
|
|
271
|
-
await Promise.all(
|
|
272
|
-
validAgents.map((agent) => {
|
|
273
|
-
const md = toCopilotInstructions(agent, options);
|
|
274
|
-
return fsp.writeFile(path.join(promptsDir, `${agent.slug}.md`), md);
|
|
275
|
-
})
|
|
276
|
-
);
|
|
277
|
-
|
|
278
|
-
const mainAgent = validAgents.find((a) => a.slug.includes('coder')) || validAgents[0];
|
|
279
|
-
const mainInstructions = toCopilotInstructions(mainAgent, options);
|
|
280
|
-
await fsp.writeFile(path.join(githubDir, 'prompts.md'), mainInstructions);
|
|
281
|
-
},
|
|
251
|
+
copilot: async (validAgents, options) => {
|
|
252
|
+
const githubDir = path.join(process.cwd(), '.github');
|
|
253
|
+
const promptsDir = path.join(githubDir, 'prompts');
|
|
254
|
+
await fsp.mkdir(promptsDir, { recursive: true });
|
|
255
|
+
|
|
256
|
+
await Promise.all(
|
|
257
|
+
validAgents.map((agent) => {
|
|
258
|
+
const md = toCopilotInstructions(agent, options);
|
|
259
|
+
return fsp.writeFile(path.join(promptsDir, `${agent.slug}.md`), md);
|
|
260
|
+
})
|
|
261
|
+
);
|
|
262
|
+
|
|
263
|
+
const mainAgent = validAgents.find((a) => a.slug.includes('coder')) || validAgents[0];
|
|
264
|
+
const mainInstructions = toCopilotInstructions(mainAgent, options);
|
|
265
|
+
await fsp.writeFile(path.join(githubDir, 'prompts.md'), mainInstructions);
|
|
266
|
+
},
|
|
282
267
|
trae: async (validAgents, options) => {
|
|
283
268
|
const traeDir = path.join(process.cwd(), '.trae');
|
|
284
269
|
await fsp.mkdir(traeDir, { recursive: true });
|
|
@@ -298,51 +283,43 @@ async function processAgentsInstallation(tools, options) {
|
|
|
298
283
|
})
|
|
299
284
|
);
|
|
300
285
|
},
|
|
301
|
-
opencode: async (validAgents, options) => {
|
|
302
|
-
const
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
await
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
let userRules = '';
|
|
339
|
-
if (options.globalRules && options.globalRules.trim()) {
|
|
340
|
-
userRules = '\n\n# User Specified Rules\n\n' + options.globalRules.split('\n').filter(line => line.trim()).map(line => '- ' + line.trim()).join('\n');
|
|
341
|
-
}
|
|
342
|
-
agentsMdContent += userRules;
|
|
343
|
-
|
|
344
|
-
await fsp.writeFile(agentsMdPath, agentsMdContent);
|
|
345
|
-
}
|
|
286
|
+
opencode: async (validAgents, options) => {
|
|
287
|
+
const skillsDir = path.join(process.cwd(), '.opencode', 'skills');
|
|
288
|
+
|
|
289
|
+
// Ensure base directory exists
|
|
290
|
+
await fsp.mkdir(skillsDir, { recursive: true });
|
|
291
|
+
|
|
292
|
+
await Promise.all(
|
|
293
|
+
validAgents.map(async (agent) => {
|
|
294
|
+
// Create specific folder for the skill: .opencode/skills/[agent-slug]/
|
|
295
|
+
// Ensure compatibility with naming rules (lowercase, alphanumeric, single hyphens)
|
|
296
|
+
const skillName = agent.slug.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '');
|
|
297
|
+
const agentSkillDir = path.join(skillsDir, skillName);
|
|
298
|
+
|
|
299
|
+
await fsp.mkdir(agentSkillDir, { recursive: true });
|
|
300
|
+
|
|
301
|
+
const skillContent = toOpenCodeSkill(agent, options);
|
|
302
|
+
return fsp.writeFile(path.join(agentSkillDir, 'SKILL.md'), skillContent);
|
|
303
|
+
})
|
|
304
|
+
);
|
|
305
|
+
},
|
|
306
|
+
antigravity: async (validAgents, options) => {
|
|
307
|
+
const skillsDir = path.join(process.cwd(), '.antigravity', 'skills');
|
|
308
|
+
|
|
309
|
+
// Ensure base directory exists (though we will mkdir for each agent)
|
|
310
|
+
await fsp.mkdir(skillsDir, { recursive: true });
|
|
311
|
+
|
|
312
|
+
await Promise.all(
|
|
313
|
+
validAgents.map(async (agent) => {
|
|
314
|
+
// Create specific folder for the skill: .antigravity/skills/[agent-slug]/
|
|
315
|
+
const agentSkillDir = path.join(skillsDir, agent.slug);
|
|
316
|
+
await fsp.mkdir(agentSkillDir, { recursive: true });
|
|
317
|
+
|
|
318
|
+
const skillContent = toAntigravitySkill(agent, options);
|
|
319
|
+
return fsp.writeFile(path.join(agentSkillDir, 'SKILL.md'), skillContent);
|
|
320
|
+
})
|
|
321
|
+
);
|
|
322
|
+
}
|
|
346
323
|
};
|
|
347
324
|
|
|
348
325
|
for (const tool of tools) {
|
package/src/lib/agents.js
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
const fs = require('fs/promises');
|
|
2
|
-
const path = require('path');
|
|
3
|
-
const yaml = require('js-yaml');
|
|
4
|
-
const { AgentSchema } = require('./schema');
|
|
5
|
-
const
|
|
6
|
-
const pc = require('picocolors');
|
|
1
|
+
const fs = require('fs/promises');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const yaml = require('js-yaml');
|
|
4
|
+
const { AgentSchema } = require('./schema');
|
|
5
|
+
const pc = require('picocolors');
|
|
7
6
|
|
|
8
7
|
/**
|
|
9
8
|
* Loads and validates all agent definitions from the definitions folder.
|
|
@@ -76,18 +75,10 @@ async function loadAgents(options = {}) {
|
|
|
76
75
|
|
|
77
76
|
// Normalize slug
|
|
78
77
|
agent.slug = file.replace(/\.ya?ml$/, '').replace(/\./g, '-');
|
|
79
|
-
agent.originalName = file.replace(/\.ya?ml$/, '');
|
|
80
|
-
agent.source = source; // Useful metadata for logs
|
|
81
|
-
|
|
82
|
-
// Feature
|
|
83
|
-
if (options.stackProfile && STACK_PROFILES[options.stackProfile]) {
|
|
84
|
-
const stackRules = STACK_PROFILES[options.stackProfile].rules;
|
|
85
|
-
if (stackRules && stackRules.length > 0) {
|
|
86
|
-
agent.rules = [...agent.rules, ...stackRules];
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
// Feature 3: Global Rules Injection
|
|
78
|
+
agent.originalName = file.replace(/\.ya?ml$/, '');
|
|
79
|
+
agent.source = source; // Useful metadata for logs
|
|
80
|
+
|
|
81
|
+
// Feature 3: Global Rules Injection
|
|
91
82
|
if (options.globalRules && typeof options.globalRules === 'string') {
|
|
92
83
|
const customRules = options.globalRules
|
|
93
84
|
.split('\n')
|
package/src/lib/docs.js
CHANGED
|
@@ -35,7 +35,6 @@ function generateWorkflowGuide(baseDir) {
|
|
|
35
35
|
const templatesDir = path.join(__dirname, '..', '..', 'templates');
|
|
36
36
|
|
|
37
37
|
const templateFiles = [
|
|
38
|
-
{ src: 'guidelines.md', dest: 'guidelines.md' },
|
|
39
38
|
{ src: 'project.md', dest: 'project.md' },
|
|
40
39
|
{ src: 'requirements.md', dest: 'requirements.md' },
|
|
41
40
|
{ src: 'context.md', dest: 'context.md' },
|
package/src/lib/messages.js
CHANGED
|
@@ -25,10 +25,9 @@ const EN = {
|
|
|
25
25
|
ERROR: 'Failed to verify workspace structure.',
|
|
26
26
|
},
|
|
27
27
|
SETUP: {
|
|
28
|
-
STACK_SELECT: 'What is your technology Stack profile?',
|
|
29
28
|
GLOBAL_RULES: 'Do you want to add any Global Rules for ALL agents?',
|
|
30
29
|
GLOBAL_RULES_HINT: 'Ex: Always reply in English; Use Conventional Commits...',
|
|
31
|
-
TOOL_SELECT: 'Which tools do you want to install
|
|
30
|
+
TOOL_SELECT: 'Which tools do you want to install Agents for?',
|
|
32
31
|
TOOL_HINT: 'Space to select, Enter to confirm',
|
|
33
32
|
NO_TOOLS: 'No tools selected. Operation cancelled.',
|
|
34
33
|
SUCCESS: 'Setup completed successfully! 🚀',
|
|
@@ -52,7 +51,8 @@ const EN = {
|
|
|
52
51
|
KILO: 'Kilo Code',
|
|
53
52
|
COPILOT: 'GitHub Copilot',
|
|
54
53
|
WEB: 'OpenAI / Claude',
|
|
55
|
-
OPENCODE: 'OpenCode',
|
|
54
|
+
OPENCODE: 'OpenCode (Skills)',
|
|
55
|
+
ANTIGRAVITY: 'Antigravity (Skills)',
|
|
56
56
|
},
|
|
57
57
|
LANGUAGE_RULES: {
|
|
58
58
|
EN: 'Always reply in English unless told otherwise.',
|
|
@@ -99,13 +99,12 @@ const PT_BR = {
|
|
|
99
99
|
ERROR: 'Falha ao verificar estrutura do workspace.',
|
|
100
100
|
},
|
|
101
101
|
SETUP: {
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
TOOL_SELECT: 'Para quais ferramentas você deseja instalar os Agentes?',
|
|
102
|
+
GLOBAL_RULES: 'Deseja adicionar alguma Regra Global para TODOS os agentes?',
|
|
103
|
+
GLOBAL_RULES_HINT: 'Ex: Sempre responder em Português; Usar Commits Convencionais...',
|
|
104
|
+
TOOL_SELECT: 'Quais ferramentas você deseja instalar os Agentes?',
|
|
106
105
|
TOOL_HINT: 'Espaço para selecionar, Enter para confirmar',
|
|
107
106
|
NO_TOOLS: 'Nenhuma ferramenta selecionada. Operação cancelada.',
|
|
108
|
-
SUCCESS: '
|
|
107
|
+
SUCCESS: 'Configuração concluída com sucesso! 🚀',
|
|
109
108
|
},
|
|
110
109
|
INSTALL: {
|
|
111
110
|
LOADING: 'Carregando definições...',
|
|
@@ -126,7 +125,8 @@ const PT_BR = {
|
|
|
126
125
|
KILO: 'Kilo Code',
|
|
127
126
|
COPILOT: 'GitHub Copilot',
|
|
128
127
|
WEB: 'OpenAI / Claude',
|
|
129
|
-
OPENCODE: 'OpenCode',
|
|
128
|
+
OPENCODE: 'OpenCode (Skills)',
|
|
129
|
+
ANTIGRAVITY: 'Antigravity (Skills)',
|
|
130
130
|
},
|
|
131
131
|
LANGUAGE_RULES: {
|
|
132
132
|
EN: 'Always reply in English unless told otherwise.',
|
|
@@ -173,13 +173,12 @@ const ES = {
|
|
|
173
173
|
ERROR: 'Fallo al verificar estructura del espacio de trabajo.',
|
|
174
174
|
},
|
|
175
175
|
SETUP: {
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
TOOL_SELECT: '¿Para qué herramientas desea instalar los Agentes?',
|
|
176
|
+
GLOBAL_RULES: '¿Desea agregar alguna Regla Global para TODOS los agentes?',
|
|
177
|
+
GLOBAL_RULES_HINT: 'Ej: Siempre responder en Español; Usar Commits Convencionales...',
|
|
178
|
+
TOOL_SELECT: '¿Qué herramientas desea instalar los Agentes?',
|
|
180
179
|
TOOL_HINT: 'Espacio para seleccionar, Enter para confirmar',
|
|
181
180
|
NO_TOOLS: 'Ninguna herramienta seleccionada. Operación cancelada.',
|
|
182
|
-
SUCCESS: '¡
|
|
181
|
+
SUCCESS: '¡Configuración completada con éxito! 🚀',
|
|
183
182
|
},
|
|
184
183
|
INSTALL: {
|
|
185
184
|
LOADING: 'Cargando definiciones...',
|
|
@@ -200,7 +199,8 @@ const ES = {
|
|
|
200
199
|
KILO: 'Kilo Code',
|
|
201
200
|
COPILOT: 'GitHub Copilot',
|
|
202
201
|
WEB: 'OpenAI / Claude',
|
|
203
|
-
OPENCODE: 'OpenCode',
|
|
202
|
+
OPENCODE: 'OpenCode (Skills)',
|
|
203
|
+
ANTIGRAVITY: 'Antigravity (Skills)',
|
|
204
204
|
},
|
|
205
205
|
LANGUAGE_RULES: {
|
|
206
206
|
EN: 'Always reply in English unless told otherwise.',
|
package/src/lib/transformers.js
CHANGED
|
@@ -252,44 +252,34 @@ ${allRules.length > 0 ? '## Constraints\n' + allRules.map(r => `- ${r}`).join('\
|
|
|
252
252
|
`;
|
|
253
253
|
}
|
|
254
254
|
|
|
255
|
+
|
|
255
256
|
/**
|
|
256
|
-
* Converte para OpenCode
|
|
257
|
+
* Converte para OpenCode Skill (SKILL.md)
|
|
258
|
+
* Ref: https://opencode.ai/docs/skills/
|
|
257
259
|
*/
|
|
258
|
-
function
|
|
260
|
+
function toOpenCodeSkill(agent, options = {}) {
|
|
259
261
|
const languageRule = getLanguageRule(options.locale);
|
|
260
262
|
const allRules = [languageRule, ...(agent.rules || [])];
|
|
261
263
|
|
|
262
|
-
//
|
|
263
|
-
const
|
|
264
|
-
const tools = {
|
|
265
|
-
write: !isReadOnly,
|
|
266
|
-
edit: !isReadOnly,
|
|
267
|
-
bash: !isReadOnly
|
|
268
|
-
};
|
|
269
|
-
|
|
270
|
-
const frontmatter = {
|
|
271
|
-
description: agent.description || agent.role,
|
|
272
|
-
mode: 'subagent',
|
|
273
|
-
temperature: 0.3,
|
|
274
|
-
tools
|
|
275
|
-
};
|
|
276
|
-
|
|
277
|
-
const frontmatterStr = Object.entries(frontmatter)
|
|
278
|
-
.map(([key, value]) => `${key}: ${JSON.stringify(value)}`)
|
|
279
|
-
.join('\n');
|
|
264
|
+
// Ensure slug is compliant (lowercase, alphanumeric, single hyphens)
|
|
265
|
+
const skillName = agent.slug.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '');
|
|
280
266
|
|
|
281
267
|
return `---
|
|
282
|
-
${
|
|
268
|
+
name: ${skillName}
|
|
269
|
+
description: ${agent.description || agent.role}
|
|
270
|
+
license: MIT
|
|
271
|
+
compatibility: opencode
|
|
272
|
+
metadata:
|
|
273
|
+
role: ${agent.role}
|
|
283
274
|
---
|
|
284
|
-
|
|
285
275
|
# ${agent.name} ${agent.emoji}
|
|
286
276
|
|
|
287
277
|
**Role**: ${agent.role}
|
|
288
278
|
|
|
279
|
+
## Instructions
|
|
289
280
|
${agent.systemPrompt.trim()}
|
|
290
281
|
|
|
291
|
-
## Rules
|
|
292
|
-
${allRules.map(rule => `- ${rule}`).join('\n')}
|
|
282
|
+
${allRules.length > 0 ? '## Rules & Guidelines\n' + allRules.map(r => `- ${r}`).join('\n') : ''}
|
|
293
283
|
`;
|
|
294
284
|
}
|
|
295
285
|
|
|
@@ -312,6 +302,29 @@ ${allRules.length > 0 ? '## Constraints\n' + allRules.map(r => `- ${r}`).join('\
|
|
|
312
302
|
`;
|
|
313
303
|
}
|
|
314
304
|
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* Converte para Antigravity Skill (SKILL.md)
|
|
308
|
+
*/
|
|
309
|
+
function toAntigravitySkill(agent, options = {}) {
|
|
310
|
+
const languageRule = getLanguageRule(options.locale);
|
|
311
|
+
const allRules = [languageRule, ...(agent.rules || [])];
|
|
312
|
+
|
|
313
|
+
return `---
|
|
314
|
+
name: ${agent.name}
|
|
315
|
+
description: ${agent.description || agent.role}
|
|
316
|
+
---
|
|
317
|
+
# ${agent.name} ${agent.emoji}
|
|
318
|
+
|
|
319
|
+
**Role**: ${agent.role}
|
|
320
|
+
|
|
321
|
+
## Instructions
|
|
322
|
+
${agent.systemPrompt.trim()}
|
|
323
|
+
|
|
324
|
+
${allRules.length > 0 ? '## Rules & Guidelines\n' + allRules.map(r => `- ${r}`).join('\n') : ''}
|
|
325
|
+
`;
|
|
326
|
+
}
|
|
327
|
+
|
|
315
328
|
module.exports = {
|
|
316
329
|
toGeminiTOML,
|
|
317
330
|
toRooConfig,
|
|
@@ -321,6 +334,7 @@ module.exports = {
|
|
|
321
334
|
toWindsurfRules,
|
|
322
335
|
toClaudeCommand,
|
|
323
336
|
toPlainSystemPrompt,
|
|
324
|
-
|
|
325
|
-
toTraeRules
|
|
337
|
+
toOpenCodeSkill,
|
|
338
|
+
toTraeRules,
|
|
339
|
+
toAntigravitySkill
|
|
326
340
|
};
|
package/src/scripts/reset.js
CHANGED
|
@@ -8,7 +8,7 @@ console.log('Your source code (src/) will NOT be touched.');
|
|
|
8
8
|
console.log('Are you sure? (Run with --force to execute)');
|
|
9
9
|
|
|
10
10
|
if (process.argv.includes('--force')) {
|
|
11
|
-
['project.md', 'requirements.md', '
|
|
11
|
+
['project.md', 'requirements.md', 'context.md', 'system.md'].forEach(file => {
|
|
12
12
|
const p = path.join(docsDir, file);
|
|
13
13
|
if (fs.existsSync(p)) {
|
|
14
14
|
fs.unlinkSync(p);
|
|
@@ -8,6 +8,29 @@ last_updated:
|
|
|
8
8
|
|
|
9
9
|
## 1. Tech Stack and Standards (Tech Constraints)
|
|
10
10
|
|
|
11
|
+
### Frontend
|
|
12
|
+
- **Framework:** [React / Vue / Angular / Next.js / SvelteKit / Nuxt.js / None]
|
|
13
|
+
- **Styling:** [Tailwind CSS / CSS Modules / Styled Components / SCSS / None]
|
|
14
|
+
- **State Management:** [Redux / Zustand / Pinia / NgRx / Context API / None]
|
|
15
|
+
- **Testing:** [Jest + Testing Library / Vitest / Cypress / Playwright / None]
|
|
16
|
+
|
|
17
|
+
### Backend
|
|
18
|
+
- **Language:** [JavaScript / TypeScript / Python / Go / Java / C# / Rust]
|
|
19
|
+
- **Framework:** [Express / NestJS / FastAPI / Django / Spring Boot / .NET / None]
|
|
20
|
+
- **API Style:** [RESTful / GraphQL / gRPC / None]
|
|
21
|
+
- **Authentication:** [JWT / OAuth 2.0 / Session-based / None]
|
|
22
|
+
- **Testing:** [Jest / Pytest / Go test / JUnit / NUnit / None]
|
|
23
|
+
|
|
24
|
+
### Database & Storage
|
|
25
|
+
- **Primary Database:** [PostgreSQL / MySQL / MongoDB / SQLite / Redis / TBD]
|
|
26
|
+
- **ORM:** [Prisma / SQLAlchemy / TypeORM / Mongoose / GORM / None]
|
|
27
|
+
- **Migration Tool:** [Prisma Migrate / Alembic / Flyway / None]
|
|
28
|
+
|
|
29
|
+
### DevOps & Infrastructure
|
|
30
|
+
- **Containerization:** [Docker / Podman / None]
|
|
31
|
+
- **CI/CD:** [GitHub Actions / GitLab CI / Jenkins / None]
|
|
32
|
+
- **Hosting:** [Vercel / Netlify / AWS / Railway / Render / None]
|
|
33
|
+
|
|
11
34
|
## 2. Functional Requirements (FR)
|
|
12
35
|
|
|
13
36
|
## 3. Non-Functional Requirements (NFR)
|
package/src/lib/profiles.js
DELETED
|
@@ -1,186 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Technical Stack Profiles
|
|
3
|
-
* Defines additional rules to be injected into agents
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
const STACK_PROFILES = {
|
|
7
|
-
// --- GENERIC ---
|
|
8
|
-
'generic': {
|
|
9
|
-
label: '🌐 Generic / None',
|
|
10
|
-
rules: []
|
|
11
|
-
},
|
|
12
|
-
|
|
13
|
-
// --- FRONTEND ---
|
|
14
|
-
'frontend-react': {
|
|
15
|
-
label: '🎨 Frontend: React + Tailwind',
|
|
16
|
-
rules: [
|
|
17
|
-
"Prefer Functional Components with Hooks.",
|
|
18
|
-
"Use Tailwind CSS for styling. Avoid inline styles.",
|
|
19
|
-
"Ensure accessibility (a11y) standards are met.",
|
|
20
|
-
"Use strict type checking if TypeScript is enabled.",
|
|
21
|
-
"Prefer React Query or SWR for data fetching."
|
|
22
|
-
]
|
|
23
|
-
},
|
|
24
|
-
'frontend-next': {
|
|
25
|
-
label: '🎨 Frontend: Next.js (App Router)',
|
|
26
|
-
rules: [
|
|
27
|
-
"Use App Router directory structure.",
|
|
28
|
-
"Prefer Server Components by default; use 'use client' only when necessary.",
|
|
29
|
-
"Optimize images using next/image.",
|
|
30
|
-
"Use Server Actions for mutations."
|
|
31
|
-
]
|
|
32
|
-
},
|
|
33
|
-
'frontend-vue': {
|
|
34
|
-
label: '🎨 Frontend: Vue.js 3 + Pinia',
|
|
35
|
-
rules: [
|
|
36
|
-
"Use Composition API with <script setup>.",
|
|
37
|
-
"Use Pinia for state management.",
|
|
38
|
-
"Prefer Tailwind CSS or Scoped CSS.",
|
|
39
|
-
"Follow the Vue Style Guide Priority A rules."
|
|
40
|
-
]
|
|
41
|
-
},
|
|
42
|
-
'frontend-angular': {
|
|
43
|
-
label: '🎨 Frontend: Angular',
|
|
44
|
-
rules: [
|
|
45
|
-
"Use Standalone Components.",
|
|
46
|
-
"Prefer Signals over RxJS for synchronous state.",
|
|
47
|
-
"Strictly follow the Angular Style Guide.",
|
|
48
|
-
"Use Dependency Injection patterns."
|
|
49
|
-
]
|
|
50
|
-
},
|
|
51
|
-
'frontend-svelte': {
|
|
52
|
-
label: '🎨 Frontend: SvelteKit',
|
|
53
|
-
rules: [
|
|
54
|
-
"Use Svelte 5 Runes syntax if available.",
|
|
55
|
-
"Leverage SvelteKit's load functions for server-side data.",
|
|
56
|
-
"Keep stores simple and derived."
|
|
57
|
-
]
|
|
58
|
-
},
|
|
59
|
-
|
|
60
|
-
// --- BACKEND ---
|
|
61
|
-
'backend-node': {
|
|
62
|
-
label: '⚙️ Backend: Node.js (Express)',
|
|
63
|
-
rules: [
|
|
64
|
-
"Prefer Async/Await over raw Promises.",
|
|
65
|
-
"Follow Error Handling best practices (don't ignore errors).",
|
|
66
|
-
"Use Environment Variables for configuration.",
|
|
67
|
-
"Adhere to RESTful API standards."
|
|
68
|
-
]
|
|
69
|
-
},
|
|
70
|
-
'backend-nest': {
|
|
71
|
-
label: '⚙️ Backend: NestJS',
|
|
72
|
-
rules: [
|
|
73
|
-
"Use Dependency Injection strictly.",
|
|
74
|
-
"Follow the module structure.",
|
|
75
|
-
"Use DTOs with ValidationPipe for all inputs.",
|
|
76
|
-
"Prefer TypeORM or Prisma for database interaction."
|
|
77
|
-
]
|
|
78
|
-
},
|
|
79
|
-
'backend-python-fastapi': {
|
|
80
|
-
label: '⚙️ Backend: Python (FastAPI)',
|
|
81
|
-
rules: [
|
|
82
|
-
"Use Pydantic models for data validation.",
|
|
83
|
-
"Use Type Hints for function arguments and return values.",
|
|
84
|
-
"Implement async/await for I/O bound operations.",
|
|
85
|
-
"Follow PEP 8 style guidelines."
|
|
86
|
-
]
|
|
87
|
-
},
|
|
88
|
-
'backend-python-django': {
|
|
89
|
-
label: '⚙️ Backend: Python (Django)',
|
|
90
|
-
rules: [
|
|
91
|
-
"Use Class-Based Views (CBVs) where appropriate.",
|
|
92
|
-
"Follow the 'Fat Models, Thin Views' philosophy.",
|
|
93
|
-
"Use Django ORM optimizations (select_related, prefetch_related).",
|
|
94
|
-
"Keep settings separated for dev/prod."
|
|
95
|
-
]
|
|
96
|
-
},
|
|
97
|
-
'backend-java-spring': {
|
|
98
|
-
label: '⚙️ Backend: Java (Spring Boot)',
|
|
99
|
-
rules: [
|
|
100
|
-
"Use constructor injection over @Autowired.",
|
|
101
|
-
"Follow Google Java Style Guide.",
|
|
102
|
-
"Use Lombok to reduce boilerplate code.",
|
|
103
|
-
"Handle exceptions with @ControllerAdvice."
|
|
104
|
-
]
|
|
105
|
-
},
|
|
106
|
-
'backend-csharp': {
|
|
107
|
-
label: '⚙️ Backend: C# (.NET Core)',
|
|
108
|
-
rules: [
|
|
109
|
-
"Follow Microsoft's C# Coding Conventions.",
|
|
110
|
-
"Use Async/Await all the way down.",
|
|
111
|
-
"Prefer LINQ for collection manipulation.",
|
|
112
|
-
"Use Dependency Injection via IServiceCollection."
|
|
113
|
-
]
|
|
114
|
-
},
|
|
115
|
-
'backend-go': {
|
|
116
|
-
label: '⚙️ Backend: Go (Golang)',
|
|
117
|
-
rules: [
|
|
118
|
-
"Handle errors explicitly (if err != nil).",
|
|
119
|
-
"Follow strict formatting (gofmt).",
|
|
120
|
-
"Prefer standard library over external dependencies when possible.",
|
|
121
|
-
"Use context for cancellation and timeouts."
|
|
122
|
-
]
|
|
123
|
-
},
|
|
124
|
-
|
|
125
|
-
// --- MOBILE ---
|
|
126
|
-
'mobile-react-native': {
|
|
127
|
-
label: '📱 Mobile: React Native',
|
|
128
|
-
rules: [
|
|
129
|
-
"Use Functional Components and Hooks.",
|
|
130
|
-
"Avoid bridge passing heavy data.",
|
|
131
|
-
"Optimize lists with FlatList or FlashList.",
|
|
132
|
-
"Style using StyleSheet objects or styled-components."
|
|
133
|
-
]
|
|
134
|
-
},
|
|
135
|
-
'mobile-flutter': {
|
|
136
|
-
label: '📱 Mobile: Flutter',
|
|
137
|
-
rules: [
|
|
138
|
-
"Use const constructors whenever possible.",
|
|
139
|
-
"Prefer Composition over Inheritance.",
|
|
140
|
-
"Manage state with Riverpod or BLoC.",
|
|
141
|
-
"Follow Effective Dart guidelines."
|
|
142
|
-
]
|
|
143
|
-
},
|
|
144
|
-
'mobile-ios': {
|
|
145
|
-
label: '📱 Mobile: iOS (SwiftUI)',
|
|
146
|
-
rules: [
|
|
147
|
-
"Use MVVM pattern.",
|
|
148
|
-
"Prefer Structs over Classes for data models.",
|
|
149
|
-
"Use strict concurrency checking.",
|
|
150
|
-
"Follow Apple's Human Interface Guidelines."
|
|
151
|
-
]
|
|
152
|
-
},
|
|
153
|
-
'mobile-android': {
|
|
154
|
-
label: '📱 Mobile: Android (Kotlin Compose)',
|
|
155
|
-
rules: [
|
|
156
|
-
"Use Jetpack Compose for UI.",
|
|
157
|
-
"Follow Material Design 3 guidelines.",
|
|
158
|
-
"Use Coroutines and Flow for async work.",
|
|
159
|
-
"Implement Hilt for Dependency Injection."
|
|
160
|
-
]
|
|
161
|
-
},
|
|
162
|
-
|
|
163
|
-
// --- DATA & AI ---
|
|
164
|
-
'data-python': {
|
|
165
|
-
label: '📊 Data Science: Python',
|
|
166
|
-
rules: [
|
|
167
|
-
"Use Pandas vectorization over loops.",
|
|
168
|
-
"Document notebooks with Markdown cells explaining logic.",
|
|
169
|
-
"Use Type Hints even in scripts.",
|
|
170
|
-
"Prefer Polars for large datasets if possible."
|
|
171
|
-
]
|
|
172
|
-
},
|
|
173
|
-
|
|
174
|
-
// --- INFRASTRUCTURE ---
|
|
175
|
-
'infra-terraform': {
|
|
176
|
-
label: '☁️ Infra: Terraform',
|
|
177
|
-
rules: [
|
|
178
|
-
"Use modules for reusable resources.",
|
|
179
|
-
"Keep state remote and locked.",
|
|
180
|
-
"Format code with `terraform fmt`.",
|
|
181
|
-
"Avoid hardcoding values; use variables."
|
|
182
|
-
]
|
|
183
|
-
}
|
|
184
|
-
};
|
|
185
|
-
|
|
186
|
-
module.exports = { STACK_PROFILES };
|