teamspec 3.2.0 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/README.md +24 -12
  2. package/bin/teamspec-init.js +2 -2
  3. package/lib/cli.js +653 -99
  4. package/lib/linter.js +823 -1076
  5. package/lib/prompt-generator.js +312 -330
  6. package/lib/structure-loader.js +400 -0
  7. package/package.json +14 -6
  8. package/teamspec-core/FOLDER_STRUCTURE.yml +131 -0
  9. package/teamspec-core/agents/AGENT_BA.md +188 -293
  10. package/teamspec-core/agents/AGENT_BOOTSTRAP.md +197 -102
  11. package/teamspec-core/agents/AGENT_DES.md +9 -8
  12. package/teamspec-core/agents/AGENT_DEV.md +68 -67
  13. package/teamspec-core/agents/AGENT_FA.md +437 -245
  14. package/teamspec-core/agents/AGENT_FIX.md +344 -74
  15. package/teamspec-core/agents/AGENT_PO.md +487 -0
  16. package/teamspec-core/agents/AGENT_QA.md +124 -98
  17. package/teamspec-core/agents/AGENT_SA.md +143 -84
  18. package/teamspec-core/agents/AGENT_SM.md +106 -83
  19. package/teamspec-core/agents/README.md +143 -93
  20. package/teamspec-core/copilot-instructions.md +281 -205
  21. package/teamspec-core/definitions/definition-of-done.md +47 -84
  22. package/teamspec-core/definitions/definition-of-ready.md +35 -60
  23. package/teamspec-core/registry.yml +898 -0
  24. package/teamspec-core/teamspec.yml +44 -28
  25. package/teamspec-core/templates/README.md +5 -5
  26. package/teamspec-core/templates/adr-template.md +19 -17
  27. package/teamspec-core/templates/bai-template.md +125 -0
  28. package/teamspec-core/templates/bug-report-template.md +21 -15
  29. package/teamspec-core/templates/business-analysis-template.md +16 -13
  30. package/teamspec-core/templates/decision-log-template.md +26 -22
  31. package/teamspec-core/templates/dev-plan-template.md +168 -0
  32. package/teamspec-core/templates/epic-template.md +204 -0
  33. package/teamspec-core/templates/feature-increment-template.md +84 -0
  34. package/teamspec-core/templates/feature-template.md +45 -32
  35. package/teamspec-core/templates/increments-index-template.md +53 -0
  36. package/teamspec-core/templates/product-template.yml +44 -0
  37. package/teamspec-core/templates/products-index-template.md +46 -0
  38. package/teamspec-core/templates/project-template.yml +70 -0
  39. package/teamspec-core/templates/ri-template.md +225 -0
  40. package/teamspec-core/templates/rt-template.md +104 -0
  41. package/teamspec-core/templates/sd-template.md +132 -0
  42. package/teamspec-core/templates/sdi-template.md +119 -0
  43. package/teamspec-core/templates/sprint-template.md +17 -15
  44. package/teamspec-core/templates/story-template-v4.md +202 -0
  45. package/teamspec-core/templates/story-template.md +48 -90
  46. package/teamspec-core/templates/ta-template.md +198 -0
  47. package/teamspec-core/templates/tai-template.md +131 -0
  48. package/teamspec-core/templates/tc-template.md +145 -0
  49. package/teamspec-core/templates/testcases-template.md +20 -17
  50. package/extensions/teamspec-0.1.0.vsix +0 -0
  51. package/lib/extension-installer.js +0 -236
@@ -1,321 +1,174 @@
1
1
  /**
2
- * TeamSpec Copilot Command Generator
2
+ * TeamSpec Copilot Prompt Generator
3
3
  *
4
4
  * Generates GitHub Copilot prompt files for all TeamSpec commands.
5
+ * Commands and roles are loaded from registry.yml to ensure consistency.
6
+ *
7
+ * Prompts are kept minimal and reference agent files for detailed guidance.
8
+ *
5
9
  * Usage: teamspec generate-prompts
10
+ * Version: 4.0
6
11
  */
7
12
 
8
13
  const fs = require('fs');
9
14
  const path = require('path');
15
+ const { loadRegistry, getCommandsFromRegistry } = require('./structure-loader');
16
+
17
+ // =============================================================================
18
+ // ROLE EXTRACTION FROM REGISTRY
19
+ // =============================================================================
10
20
 
11
- // Command definitions from agent system
12
- const COMMANDS = {
13
- ba: {
14
- name: 'Business Analyst',
15
- commands: [
16
- {
17
- name: 'project',
18
- description: 'Create project structure',
19
- prompt: `Execute project creation workflow:
20
- 1. Gather project information (name, ID, stakeholders, goals)
21
- 2. Create project folder structure in projects/{id}/
22
- 3. Generate project.yml with metadata
23
- 4. Create README.md
24
- 5. Initialize folders: features/, stories/backlog/, stories/ready-to-refine/, stories/ready-for-development/, adr/, decisions/, dev-plans/, qa/test-cases/, epics/, sprints/
25
- 6. Create features-index.md and story-ledger.md
26
- Wait for user confirmation before creating files.`
27
- },
28
- {
29
- name: 'epic',
30
- description: 'Define an epic',
31
- prompt: `Execute epic creation workflow:
32
- 1. Identify epic scope and goal
33
- 2. Link to project
34
- 3. Break down into candidate features
35
- 4. Create epic file in epics/ folder
36
- Wait for user confirmation before creating files.`
37
- },
38
- {
39
- name: 'feature',
40
- description: 'Create feature file',
41
- prompt: `Execute feature creation workflow:
42
- 1. Gather feature requirements (purpose, value, scope)
43
- 2. Define personas/actors
44
- 3. Create feature file in features/ folder using F-XXX-name.md format
45
- 4. Update features-index.md
46
- Ensure feature is implementation-agnostic.
47
- Wait for user confirmation before creating files.`
48
- },
49
- {
50
- name: 'decision',
51
- description: 'Log business decision',
52
- prompt: `Log a business decision:
53
- 1. Capture decision context
54
- 2. Document options considered
55
- 3. Record rationale
56
- 4. Link to affected features
57
- 5. Create decision file in decisions/ folder using DECISION-XXX-name.md format`
58
- },
59
- {
60
- name: 'analysis',
61
- description: 'Create business analysis document',
62
- prompt: `Create a business analysis document to describe business processes:
63
-
64
- 1. **Understand the business domain** - Ask about:
65
- - What business problem needs to be analyzed?
66
- - Who are the stakeholders?
67
- - What business processes are involved?
68
-
69
- 2. **Document Current State (As-Is)**
70
- - How do users solve the problem today?
71
- - What are the pain points?
72
- - What processes exist?
73
-
74
- 3. **Define Future State (To-Be)**
75
- - What will the improved workflow look like?
76
- - What business rules apply?
77
- - What are the success metrics?
78
-
79
- 4. **Create business analysis document** using templates/business-analysis-template.md
80
- - Place in analysis/ folder (create if needed)
81
- - Name format: BA-XXX-description.md
82
-
83
- 5. **Link to related artifacts**
84
- - Identify candidate features that will come from this analysis
85
- - Note decisions that need to be made
86
- - Identify risks and constraints
87
-
88
- āš ļø This is a PLANNING artifact - Feature Canon becomes Source of Truth after features are created.`
89
- }
90
- ]
91
- },
92
- fa: {
93
- name: 'Functional Analyst',
94
- commands: [
95
- {
96
- name: 'story',
97
- description: 'Create a new story',
98
- prompt: `Create a story as a DELTA to the Feature Canon:
99
- 1. Identify the linked feature (REQUIRED)
100
- 2. Document BEFORE state (reference Canon)
101
- 3. Document AFTER state (the delta)
102
- 4. Write testable Acceptance Criteria
103
- 5. Mark impact type (Adds/Changes/Fixes/Removes)
104
- 6. Create story in stories/backlog/ using S-XXX-name.md format
105
- NEVER create a story without a feature link.`
106
- },
107
- {
108
- name: 'slice',
109
- description: 'Slice feature into stories',
110
- prompt: `Slice a feature into implementable stories:
111
- 1. Read the Feature Canon entry
112
- 2. Identify discrete behavior changes
113
- 3. Create story deltas for each change
114
- 4. Ensure each story is independently deliverable
115
- 5. Link all stories to the feature
116
- Create files in stories/backlog/`
117
- },
118
- {
119
- name: 'refine',
120
- description: 'Move story to ready-to-refine',
121
- prompt: `Refine a story for development:
122
- 1. Verify feature link exists
123
- 2. Check Before/After delta is clear
124
- 3. Validate ACs are testable
125
- 4. Move file from stories/backlog/ to stories/ready-to-refine/`
126
- },
127
- {
128
- name: 'sync',
129
- description: 'Update Feature Canon after story completion',
130
- prompt: `CRITICAL: Canon sync workflow:
131
- 1. Identify completed story
132
- 2. Check impact type (Adds/Changes Behavior?)
133
- 3. Update Feature Canon sections in features/
134
- 4. Add Change Log entry with story reference
135
- 5. Update story-ledger.md
136
- 6. Verify DoD checkbox is checked
137
- A story CANNOT be Done until Canon is synchronized.`
138
- }
139
- ]
140
- },
141
- arch: {
142
- name: 'Solution Architect',
143
- commands: [
144
- {
145
- name: 'adr',
146
- description: 'Create Architecture Decision Record',
147
- prompt: `Create an ADR:
148
- 1. Identify technical decision
149
- 2. Document context and options
150
- 3. Record decision and rationale
151
- 4. Link to affected features
152
- 5. Create ADR file in adr/ folder using ADR-XXX-name.md format`
153
- }
154
- ]
155
- },
156
- dev: {
157
- name: 'Developer',
158
- commands: [
159
- {
160
- name: 'plan',
161
- description: 'Create development plan',
162
- prompt: `Create a development plan:
163
- 1. Read the story and linked feature
164
- 2. Break down into implementation tasks
165
- 3. Estimate effort for each task
166
- 4. Identify dependencies and risks
167
- 5. Create dev plan in dev-plans/ using story-XXX-tasks.md format`
168
- },
169
- {
170
- name: 'implement',
171
- description: 'Execute implementation',
172
- prompt: `Execute implementation:
173
- 1. Load dev plan
174
- 2. Work through tasks sequentially
175
- 3. Update task completion status
176
- 4. Create/modify code files
177
- 5. Track actual vs estimated effort`
178
- },
179
- {
180
- name: 'ready',
181
- description: 'Move story to ready-for-development',
182
- prompt: `Move story to ready-for-development:
183
- 1. Verify dev plan exists
184
- 2. Check DoR criteria
185
- 3. Move file from stories/ready-to-refine/ to stories/ready-for-development/`
186
- }
187
- ]
188
- },
189
- qa: {
190
- name: 'QA Engineer',
191
- commands: [
192
- {
193
- name: 'test',
194
- description: 'Design test cases',
195
- prompt: `Design test cases:
196
- 1. Read feature specification
197
- 2. Identify test scenarios
198
- 3. Write test cases with steps and expected results
199
- 4. Create test file in qa/test-cases/ using F-XXX-test-cases.md format`
200
- },
201
- {
202
- name: 'bug',
203
- description: 'File bug report',
204
- prompt: `File a bug report:
205
- 1. Capture bug details
206
- 2. Document reproduction steps
207
- 3. Classify severity
208
- 4. Link to affected feature
209
- 5. Create bug file in bugs/ folder`
210
- },
211
- {
212
- name: 'dor-check',
213
- description: 'Validate Definition of Ready',
214
- prompt: `Check Definition of Ready:
215
- 1. Verify feature link exists
216
- 2. Check Before/After delta is clear
217
- 3. Validate ACs are testable
218
- 4. Confirm no TBD/placeholder content
219
- 5. Check estimate is assigned
220
- Report any gaps.`
221
- }
222
- ]
223
- },
224
- sm: {
225
- name: 'Scrum Master',
226
- commands: [
227
- {
228
- name: 'sprint-create',
229
- description: 'Create new sprint',
230
- prompt: `Create new sprint:
231
- 1. Determine sprint number
232
- 2. Create sprint folder: sprints/sprint-N/
233
- 3. Create sprint-goal.md
234
- 4. Update active-sprint.md`
235
- },
236
- {
237
- name: 'sprint-plan',
238
- description: 'Plan sprint backlog',
239
- prompt: `Plan sprint backlog:
240
- 1. Review ready-for-development stories
241
- 2. Calculate team capacity
242
- 3. Select stories for sprint
243
- 4. Move story files to sprints/sprint-N/
244
- 5. Update sprint-goal.md`
245
- },
246
- {
247
- name: 'sprint-status',
248
- description: 'Sprint status report',
249
- prompt: `Generate sprint status:
250
- 1. Count stories by status
251
- 2. Calculate burndown
252
- 3. Identify blockers
253
- 4. Report health metrics`
254
- }
255
- ]
256
- },
257
- utility: {
258
- name: 'Utility',
259
- commands: [
260
- {
261
- name: 'fix',
262
- description: 'Auto-fix linter errors',
263
- prompt: `Auto-fix TeamSpec linter errors:
264
- 1. Run \`teamspec lint\` to identify errors
265
- 2. Review the linter output
266
- 3. Apply fixes for each error category
267
- 4. Re-run linter to verify fixes
268
-
269
- Supports: TS-PROJ, TS-FEAT, TS-STORY, TS-ADR, TS-DEVPLAN, TS-DOD, TS-NAMING rules.`
270
- }
271
- ]
21
+ /**
22
+ * Extract roles from registry.yml
23
+ * @param {Object} registry - Parsed registry object
24
+ * @returns {Object} - Roles keyed by role ID
25
+ */
26
+ function extractRoles(registry) {
27
+ const roles = {};
28
+
29
+ if (registry?.roles) {
30
+ for (const [roleId, roleData] of Object.entries(registry.roles)) {
31
+ roles[roleId] = {
32
+ id: roleId,
33
+ name: roleData.name || roleId,
34
+ agent: `AGENT_${roleId}`,
35
+ owns: roleData.owns || [],
36
+ creates: roleData.creates || [],
37
+ commands: roleData.commands || []
38
+ };
39
+ }
272
40
  }
273
- };
41
+
42
+ return roles;
43
+ }
274
44
 
275
45
  /**
276
- * Map role codes to agent file names
46
+ * Get role info from registry roles
47
+ * @param {Object} roles - Extracted roles
48
+ * @param {string} roleKey - Role key (e.g., 'PO', 'BA')
49
+ * @returns {Object} - Role info with defaults
277
50
  */
278
- const ROLE_TO_AGENT = {
279
- ba: 'AGENT_BA',
280
- fa: 'AGENT_FA',
281
- arch: 'AGENT_SA', // Solution Architect
282
- dev: 'AGENT_DEV',
283
- qa: 'AGENT_QA',
284
- sm: 'AGENT_SM',
285
- utility: 'AGENT_FIX'
286
- };
51
+ function getRoleInfo(roles, roleKey) {
52
+ const key = roleKey?.toUpperCase();
53
+ return roles[key] || {
54
+ id: key || 'ANY',
55
+ name: 'TeamSpec',
56
+ agent: 'AGENT_BOOTSTRAP',
57
+ owns: [],
58
+ creates: [],
59
+ commands: []
60
+ };
61
+ }
62
+
63
+ // =============================================================================
64
+ // COMMAND EXTRACTION FROM REGISTRY
65
+ // =============================================================================
287
66
 
288
67
  /**
289
- * Generate GitHub Copilot prompt file in VS Code format
290
- * Creates minimal prompts that link to the full agent files
291
- * VS Code automatically includes linked Markdown files as context
68
+ * Group commands by role
69
+ * @param {Array} commands - Commands from registry
70
+ * @returns {Object} - Commands grouped by role
292
71
  */
293
- function generatePromptFile(role, command, outputDir) {
294
- // Utility commands use just the command name (e.g., fix.prompt.md, ts:fix)
295
- // Other roles use role-command pattern (e.g., ba-project.prompt.md, ts:ba-project)
296
- const isUtility = role === 'utility';
297
- const filename = isUtility ? `${command.name}.prompt.md` : `${role}-${command.name}.prompt.md`;
72
+ function groupCommandsByRole(commands) {
73
+ const byRole = {};
74
+
75
+ for (const cmd of commands) {
76
+ if (cmd.status === 'REMOVED') continue;
77
+
78
+ const role = cmd.role || 'Any';
79
+ if (!byRole[role]) byRole[role] = [];
80
+ byRole[role].push(cmd);
81
+ }
82
+
83
+ return byRole;
84
+ }
85
+
86
+ // =============================================================================
87
+ // PROMPT FILE GENERATION
88
+ // =============================================================================
89
+
90
+ /**
91
+ * Sanitize a string for use in filenames
92
+ */
93
+ function sanitizeFilename(str) {
94
+ return str
95
+ .replace(/<[^>]+>/g, '') // Remove angle bracket patterns like <role>
96
+ .replace(/[\\/:*?"<>|]/g, '') // Remove Windows-invalid chars
97
+ .replace(/\s+/g, '-') // Replace spaces with dashes
98
+ .replace(/-+/g, '-') // Collapse multiple dashes
99
+ .replace(/^-|-$/g, ''); // Remove leading/trailing dashes
100
+ }
101
+
102
+ /**
103
+ * Parse command invocation to extract role and action
104
+ * @param {string} invocation - Command invocation (e.g., "ts:po product")
105
+ * @returns {Object|null} - Parsed command parts or null if invalid
106
+ */
107
+ function parseInvocation(invocation) {
108
+ const match = invocation.match(/^ts:(\w+)(?:\s+(.+))?$/);
109
+ if (!match) return null;
110
+
111
+ const [, roleOrCmd, action] = match;
112
+
113
+ // Skip commands with placeholders
114
+ if (action && action.includes('<')) return null;
115
+
116
+ return { roleOrCmd, action };
117
+ }
118
+
119
+ /**
120
+ * Generate a clean, minimal GitHub Copilot prompt file
121
+ * The prompt references the agent file for detailed guidance.
122
+ */
123
+ function generatePromptFile(command, outputDir, roles) {
124
+ const parsed = parseInvocation(command.invocation);
125
+ if (!parsed) return null;
126
+
127
+ const { roleOrCmd, action } = parsed;
128
+ const role = getRoleInfo(roles, roleOrCmd);
129
+
130
+ // Determine filename
131
+ let filename, commandName;
132
+ if (action) {
133
+ const sanitizedAction = sanitizeFilename(action);
134
+ filename = `${roleOrCmd}-${sanitizedAction}.prompt.md`;
135
+ commandName = `ts:${roleOrCmd} ${action}`;
136
+ } else {
137
+ filename = `${roleOrCmd}.prompt.md`;
138
+ commandName = `ts:${roleOrCmd}`;
139
+ }
140
+
298
141
  const filepath = path.join(outputDir, filename);
299
- const commandName = isUtility ? `ts:${command.name}` : `ts:${role}-${command.name}`;
300
- const agentFile = ROLE_TO_AGENT[role] || `AGENT_${role.toUpperCase()}`;
301
142
 
302
- // Create minimal prompt that links to the agent file
303
- // VS Code will include the linked file as context automatically
143
+ // Build clean, minimal prompt content
304
144
  const content = `---
305
- name: "${commandName}"
306
- description: "TeamSpec ${COMMANDS[role].name}: ${command.description}"
307
- agent: "agent"
145
+ name: "ts:${filename.replace('.prompt.md', '').replace(/-/g, ' ')}"
146
+ description: "${command.purpose || `${role.name} command`}"
308
147
  ---
309
148
 
310
- # ${command.description}
149
+ # ${command.purpose || `${role.name} - ${action || roleOrCmd}`}
311
150
 
312
- Execute the **${command.name}** workflow as a **${COMMANDS[role].name}**.
151
+ You are acting as **${role.name}**.
313
152
 
314
- See full role instructions: [${agentFile}.md](../../.teamspec/agents/${agentFile}.md)
153
+ ## Command
315
154
 
316
- ## Quick Reference
155
+ \`${commandName}\`
317
156
 
318
- ${command.prompt}
157
+ ## Agent Instructions
158
+
159
+ See full role instructions and command details in:
160
+ - [${role.agent}.md](../../.teamspec/agents/${role.agent}.md)
161
+
162
+ ${command.output ? `## Output
163
+
164
+ ${command.output}
165
+ ` : ''}
166
+ ${command.precondition ? `## Precondition
167
+
168
+ ${command.precondition}
169
+ ` : ''}
170
+ ---
171
+ *Command from registry.yml - TeamSpec 4.0*
319
172
  `;
320
173
 
321
174
  fs.writeFileSync(filepath, content, 'utf-8');
@@ -323,32 +176,86 @@ ${command.prompt}
323
176
  }
324
177
 
325
178
  /**
326
- * Generate all prompt files
179
+ * Generate all prompt files from registry
327
180
  */
328
181
  function generateAllPrompts(targetDir = process.cwd()) {
329
182
  const outputDir = path.join(targetDir, '.github', 'prompts');
330
183
 
331
184
  // Create output directory
332
- if (!fs.existsSync(outputDir)) {
333
- fs.mkdirSync(outputDir, { recursive: true });
334
- }
185
+ fs.mkdirSync(outputDir, { recursive: true });
335
186
 
336
187
  console.log('šŸš€ Generating GitHub Copilot prompt files...\n');
337
188
 
189
+ // Load registry and extract data
190
+ const registry = loadRegistry(targetDir);
191
+ const roles = extractRoles(registry);
192
+ const commands = getCommandsFromRegistry(registry);
193
+ const byRole = groupCommandsByRole(commands);
194
+
338
195
  const generated = [];
196
+ const generatedByRole = {};
197
+
198
+ // Generate prompts for each command
199
+ for (const command of commands) {
200
+ if (command.status === 'REMOVED') continue;
339
201
 
340
- // Generate prompts for each role and command
341
- for (const [role, config] of Object.entries(COMMANDS)) {
342
- console.log(`šŸ“‹ ${config.name}:`);
343
- for (const command of config.commands) {
344
- const filename = generatePromptFile(role, command, outputDir);
202
+ const filename = generatePromptFile(command, outputDir, roles);
203
+ if (filename) {
345
204
  generated.push(filename);
205
+
206
+ // Track by role for summary
207
+ const role = command.role || 'Any';
208
+ if (!generatedByRole[role]) generatedByRole[role] = [];
209
+ generatedByRole[role].push({ filename, command });
210
+ }
211
+ }
212
+
213
+ // Print summary by role
214
+ for (const [roleKey, cmds] of Object.entries(generatedByRole)) {
215
+ const role = getRoleInfo(roles, roleKey);
216
+ console.log(`šŸ“‹ ${role.name}:`);
217
+ for (const { filename } of cmds) {
346
218
  console.log(` āœ“ ${filename}`);
347
219
  }
348
220
  }
349
221
 
350
- // Generate index file
351
- const indexContent = `# TeamSpec Copilot Prompts
222
+ // Generate README index
223
+ generateReadme(outputDir, generatedByRole, roles, registry);
224
+ generated.push('README.md');
225
+
226
+ console.log(`\nāœ… Generated ${generated.length} files in ${outputDir}`);
227
+ console.log('\nšŸ“– See .github/prompts/README.md for usage instructions');
228
+ console.log('šŸ’” In Copilot Chat, type "/" to see available prompts');
229
+
230
+ return generated;
231
+ }
232
+
233
+ /**
234
+ * Generate README index file
235
+ */
236
+ function generateReadme(outputDir, byRole, roles, registry) {
237
+ let pkgVersion = '4.0';
238
+ try {
239
+ const pkg = require('../package.json');
240
+ pkgVersion = pkg.version;
241
+ } catch (e) {
242
+ // Use default
243
+ }
244
+
245
+ const rolesSections = Object.entries(byRole).map(([roleKey, cmds]) => {
246
+ const role = getRoleInfo(roles, roleKey);
247
+ const cmdList = cmds.map(({ filename, command }) => {
248
+ return `- \`/${filename.replace('.prompt.md', '')}\` - ${command.purpose || 'Command'}`;
249
+ }).join('\n');
250
+
251
+ return `
252
+ ### ${role.name}
253
+
254
+ ${cmdList}
255
+ `;
256
+ }).join('\n');
257
+
258
+ const content = `# TeamSpec Copilot Prompts
352
259
 
353
260
  These prompt files provide structured guidance for TeamSpec commands in GitHub Copilot Chat.
354
261
 
@@ -356,50 +263,125 @@ These prompt files provide structured guidance for TeamSpec commands in GitHub C
356
263
 
357
264
  In VS Code, type \`/\` in Copilot Chat to see available prompts. Look for prompts starting with \`ts:\`.
358
265
 
359
- Alternatively, run any prompt directly:
360
- - Press \`Ctrl+Shift+P\` (or \`Cmd+Shift+P\` on Mac)
361
- - Type "Chat: Run Prompt"
362
- - Select a TeamSpec prompt
363
-
364
266
  ## Available Commands
365
267
 
366
- ${Object.entries(COMMANDS).map(([role, config]) => {
367
- const isUtility = role === 'utility';
368
- return `
369
- ### ${config.name}
370
-
371
- ${config.commands.map(cmd => {
372
- const cmdName = isUtility ? `ts:${cmd.name}` : `ts:${role}-${cmd.name}`;
373
- return `- \`/${cmdName}\` - ${cmd.description}`;
374
- }).join('\n')}
375
- `;
376
- }).join('\n')}
268
+ ${rolesSections}
377
269
 
378
270
  ## How It Works
379
271
 
380
272
  1. Type \`/\` in Copilot Chat to see prompts
381
- 2. Select a \`ts:\` prefixed prompt
382
- 3. Copilot provides role-specific guidance
273
+ 2. Select a TeamSpec prompt
274
+ 3. Copilot loads role-specific agent instructions
383
275
  4. Follow the workflow to create artifacts
384
276
 
277
+ ## Command Reference
278
+
279
+ | Command | Role | Purpose |
280
+ |---------|------|---------|
281
+ ${Object.values(byRole).flat().map(({ command }) => {
282
+ const role = getRoleInfo(roles, command.role);
283
+ return `| \`${command.invocation}\` | ${role.name} | ${command.purpose || '-'} |`;
284
+ }).join('\n')}
285
+
385
286
  ---
386
287
 
387
- *Generated by TeamSpec CLI v${require('../package.json').version}*
288
+ *Generated by TeamSpec CLI v${pkgVersion}*
289
+ *Source: registry.yml - TeamSpec ${registry?.version || '4.0'}*
388
290
  `;
389
291
 
390
- fs.writeFileSync(path.join(outputDir, 'README.md'), indexContent, 'utf-8');
391
- generated.push('README.md');
292
+ fs.writeFileSync(path.join(outputDir, 'README.md'), content, 'utf-8');
293
+ }
392
294
 
393
- console.log(`\nāœ… Generated ${generated.length} files in ${outputDir}`);
394
- console.log('\nšŸ“– See .github/prompts/README.md for usage instructions');
395
- console.log('šŸ’” In Copilot Chat, type "/" to see available prompts');
295
+ // =============================================================================
296
+ // BACKWARDS COMPATIBILITY EXPORTS
297
+ // =============================================================================
396
298
 
397
- return generated;
299
+ /**
300
+ * Get all commands for external use
301
+ */
302
+ function getCommands(targetDir = process.cwd()) {
303
+ const registry = loadRegistry(targetDir);
304
+ return getCommandsFromRegistry(registry);
305
+ }
306
+
307
+ /**
308
+ * Get ROLES object (extracted from registry)
309
+ * For backwards compatibility with tests
310
+ */
311
+ function getRolesFromRegistry(targetDir = process.cwd()) {
312
+ const registry = loadRegistry(targetDir);
313
+ return extractRoles(registry);
398
314
  }
399
315
 
316
+ // Legacy ROLES export - now dynamically loaded
317
+ // Kept for backwards compatibility with tests
318
+ const ROLES = (() => {
319
+ try {
320
+ const registry = loadRegistry(process.cwd());
321
+ return extractRoles(registry);
322
+ } catch (e) {
323
+ // Fallback for when registry not available
324
+ return {
325
+ PO: { id: 'PO', name: 'Product Owner', agent: 'AGENT_PO', owns: [], creates: [], commands: [] },
326
+ BA: { id: 'BA', name: 'Business Analyst', agent: 'AGENT_BA', owns: [], creates: [], commands: [] },
327
+ FA: { id: 'FA', name: 'Functional Analyst', agent: 'AGENT_FA', owns: [], creates: [], commands: [] },
328
+ SA: { id: 'SA', name: 'Solution Architect', agent: 'AGENT_SA', owns: [], creates: [], commands: [] },
329
+ DEV: { id: 'DEV', name: 'Developer', agent: 'AGENT_DEV', owns: [], creates: [], commands: [] },
330
+ QA: { id: 'QA', name: 'QA Engineer', agent: 'AGENT_QA', owns: [], creates: [], commands: [] },
331
+ SM: { id: 'SM', name: 'Scrum Master', agent: 'AGENT_SM', owns: [], creates: [], commands: [] },
332
+ DES: { id: 'DES', name: 'Designer', agent: 'AGENT_DES', owns: [], creates: [], commands: [] }
333
+ };
334
+ }
335
+ })();
336
+
337
+ // Legacy COMMANDS export - now dynamically built from registry
338
+ // Kept for backwards compatibility with tests
339
+ const COMMANDS = (() => {
340
+ try {
341
+ const registry = loadRegistry(process.cwd());
342
+ const commands = getCommandsFromRegistry(registry);
343
+ const roles = extractRoles(registry);
344
+ const byRole = groupCommandsByRole(commands);
345
+
346
+ const result = {};
347
+ for (const [roleKey, cmds] of Object.entries(byRole)) {
348
+ const role = getRoleInfo(roles, roleKey);
349
+ const normalizedKey = roleKey.toLowerCase() === 'any' ? 'utility' : roleKey.toLowerCase();
350
+
351
+ result[normalizedKey] = {
352
+ name: role.name,
353
+ commands: cmds.map(cmd => ({
354
+ name: cmd.invocation.replace(/^ts:\w+\s*/, '').trim() || cmd.id.split('.').pop(),
355
+ description: cmd.purpose || '',
356
+ prompt: '' // No longer embedding workflow in prompt
357
+ }))
358
+ };
359
+ }
360
+
361
+ return result;
362
+ } catch (e) {
363
+ // Fallback for when registry not available
364
+ return {
365
+ ba: { name: 'Business Analyst', commands: [] },
366
+ fa: { name: 'Functional Analyst', commands: [] },
367
+ po: { name: 'Product Owner', commands: [] },
368
+ sa: { name: 'Solution Architect', commands: [] },
369
+ dev: { name: 'Developer', commands: [] },
370
+ qa: { name: 'QA Engineer', commands: [] },
371
+ sm: { name: 'Scrum Master', commands: [] },
372
+ utility: { name: 'Utility', commands: [] }
373
+ };
374
+ }
375
+ })();
376
+
400
377
  module.exports = {
401
378
  generateAllPrompts,
402
- COMMANDS
379
+ getCommands,
380
+ getRolesFromRegistry,
381
+ extractRoles,
382
+ groupCommandsByRole,
383
+ COMMANDS,
384
+ ROLES
403
385
  };
404
386
 
405
387
  // CLI execution