teamspec 3.2.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/LICENSE +21 -0
- package/README.md +252 -0
- package/bin/teamspec-init.js +10 -0
- package/extensions/teamspec-0.1.0.vsix +0 -0
- package/lib/cli.js +1174 -0
- package/lib/extension-installer.js +236 -0
- package/lib/linter.js +1184 -0
- package/lib/prompt-generator.js +409 -0
- package/package.json +51 -0
- package/teamspec-core/agents/AGENT_BA.md +486 -0
- package/teamspec-core/agents/AGENT_BOOTSTRAP.md +447 -0
- package/teamspec-core/agents/AGENT_DES.md +623 -0
- package/teamspec-core/agents/AGENT_DEV.md +611 -0
- package/teamspec-core/agents/AGENT_FA.md +736 -0
- package/teamspec-core/agents/AGENT_FEEDBACK.md +202 -0
- package/teamspec-core/agents/AGENT_FIX.md +380 -0
- package/teamspec-core/agents/AGENT_QA.md +756 -0
- package/teamspec-core/agents/AGENT_SA.md +581 -0
- package/teamspec-core/agents/AGENT_SM.md +771 -0
- package/teamspec-core/agents/README.md +383 -0
- package/teamspec-core/context/_schema.yml +222 -0
- package/teamspec-core/copilot-instructions.md +356 -0
- package/teamspec-core/definitions/definition-of-done.md +129 -0
- package/teamspec-core/definitions/definition-of-ready.md +104 -0
- package/teamspec-core/profiles/enterprise.yml +127 -0
- package/teamspec-core/profiles/platform-team.yml +104 -0
- package/teamspec-core/profiles/regulated.yml +97 -0
- package/teamspec-core/profiles/startup.yml +85 -0
- package/teamspec-core/teamspec.yml +69 -0
- package/teamspec-core/templates/README.md +211 -0
- package/teamspec-core/templates/active-sprint-template.md +98 -0
- package/teamspec-core/templates/adr-template.md +194 -0
- package/teamspec-core/templates/bug-report-template.md +188 -0
- package/teamspec-core/templates/business-analysis-template.md +164 -0
- package/teamspec-core/templates/decision-log-template.md +216 -0
- package/teamspec-core/templates/feature-template.md +269 -0
- package/teamspec-core/templates/functional-spec-template.md +161 -0
- package/teamspec-core/templates/refinement-notes-template.md +133 -0
- package/teamspec-core/templates/sprint-goal-template.md +129 -0
- package/teamspec-core/templates/sprint-template.md +175 -0
- package/teamspec-core/templates/sprints-index-template.md +67 -0
- package/teamspec-core/templates/story-template.md +244 -0
- package/teamspec-core/templates/storymap-template.md +204 -0
- package/teamspec-core/templates/testcases-template.md +147 -0
- package/teamspec-core/templates/uat-pack-template.md +161 -0
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TeamSpec Extension Installer
|
|
3
|
+
*
|
|
4
|
+
* Handles installation of the TeamSpec VS Code extension.
|
|
5
|
+
* Used by the CLI during 'teamspec init --ide vscode' flow.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const fs = require('fs');
|
|
9
|
+
const path = require('path');
|
|
10
|
+
const { exec, execSync } = require('child_process');
|
|
11
|
+
|
|
12
|
+
// =============================================================================
|
|
13
|
+
// Constants
|
|
14
|
+
// =============================================================================
|
|
15
|
+
|
|
16
|
+
const EXTENSION_ID = 'teamspec.teamspec';
|
|
17
|
+
const EXTENSION_NAME = 'TeamSpec';
|
|
18
|
+
|
|
19
|
+
// =============================================================================
|
|
20
|
+
// Utilities
|
|
21
|
+
// =============================================================================
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Check if VS Code CLI is available
|
|
25
|
+
*/
|
|
26
|
+
function isVSCodeAvailable() {
|
|
27
|
+
try {
|
|
28
|
+
execSync('code --version', { stdio: 'ignore' });
|
|
29
|
+
return true;
|
|
30
|
+
} catch {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Check if the extension is already installed
|
|
37
|
+
*/
|
|
38
|
+
function isExtensionInstalled() {
|
|
39
|
+
try {
|
|
40
|
+
const result = execSync('code --list-extensions', { encoding: 'utf-8' });
|
|
41
|
+
return result.toLowerCase().includes(EXTENSION_ID.toLowerCase());
|
|
42
|
+
} catch {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Get the path to the bundled VSIX file
|
|
49
|
+
*/
|
|
50
|
+
function getBundledVsixPath() {
|
|
51
|
+
// Check for VSIX in the CLI package
|
|
52
|
+
const packageDir = path.join(__dirname, '..');
|
|
53
|
+
const vsixCandidates = [
|
|
54
|
+
path.join(packageDir, 'extensions', 'teamspec-0.1.0.vsix'),
|
|
55
|
+
path.join(packageDir, 'teamspec-0.1.0.vsix'),
|
|
56
|
+
path.join(__dirname, '..', '..', 'vscode-extension', 'teamspec-0.1.0.vsix'),
|
|
57
|
+
];
|
|
58
|
+
|
|
59
|
+
for (const candidate of vsixCandidates) {
|
|
60
|
+
if (fs.existsSync(candidate)) {
|
|
61
|
+
return candidate;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Install extension from VSIX file
|
|
70
|
+
*/
|
|
71
|
+
function installFromVsix(vsixPath) {
|
|
72
|
+
return new Promise((resolve, reject) => {
|
|
73
|
+
exec(`code --install-extension "${vsixPath}"`, (error, stdout, stderr) => {
|
|
74
|
+
if (error) {
|
|
75
|
+
reject(new Error(`Failed to install extension: ${stderr || error.message}`));
|
|
76
|
+
} else {
|
|
77
|
+
resolve(stdout);
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Install extension from marketplace (future support)
|
|
85
|
+
*/
|
|
86
|
+
function installFromMarketplace() {
|
|
87
|
+
return new Promise((resolve, reject) => {
|
|
88
|
+
exec(`code --install-extension ${EXTENSION_ID}`, (error, stdout, stderr) => {
|
|
89
|
+
if (error) {
|
|
90
|
+
// Marketplace install failed, extension may not be published yet
|
|
91
|
+
reject(new Error(`Failed to install from marketplace: ${stderr || error.message}`));
|
|
92
|
+
} else {
|
|
93
|
+
resolve(stdout);
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// =============================================================================
|
|
100
|
+
// Main Installation Function
|
|
101
|
+
// =============================================================================
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Install the TeamSpec VS Code extension
|
|
105
|
+
*
|
|
106
|
+
* @param {Object} options Installation options
|
|
107
|
+
* @param {boolean} options.force Force reinstall even if already installed
|
|
108
|
+
* @param {string} options.vsixPath Custom path to VSIX file
|
|
109
|
+
* @param {Function} options.onProgress Progress callback
|
|
110
|
+
* @returns {Promise<{success: boolean, message: string}>}
|
|
111
|
+
*/
|
|
112
|
+
async function installExtension(options = {}) {
|
|
113
|
+
const { force = false, vsixPath = null, onProgress = () => {} } = options;
|
|
114
|
+
|
|
115
|
+
// Check VS Code availability
|
|
116
|
+
onProgress('Checking VS Code installation...');
|
|
117
|
+
if (!isVSCodeAvailable()) {
|
|
118
|
+
return {
|
|
119
|
+
success: false,
|
|
120
|
+
message: 'VS Code CLI not found. Please install VS Code and ensure "code" command is in PATH.',
|
|
121
|
+
hint: 'You can add VS Code to PATH via: Command Palette > "Shell Command: Install code command in PATH"'
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Check if already installed
|
|
126
|
+
if (!force && isExtensionInstalled()) {
|
|
127
|
+
return {
|
|
128
|
+
success: true,
|
|
129
|
+
message: 'TeamSpec extension is already installed.',
|
|
130
|
+
alreadyInstalled: true
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Try to find VSIX
|
|
135
|
+
const vsix = vsixPath || getBundledVsixPath();
|
|
136
|
+
|
|
137
|
+
if (vsix) {
|
|
138
|
+
// Install from bundled VSIX
|
|
139
|
+
onProgress(`Installing extension from ${path.basename(vsix)}...`);
|
|
140
|
+
try {
|
|
141
|
+
await installFromVsix(vsix);
|
|
142
|
+
return {
|
|
143
|
+
success: true,
|
|
144
|
+
message: 'TeamSpec extension installed successfully from local package.'
|
|
145
|
+
};
|
|
146
|
+
} catch (error) {
|
|
147
|
+
return {
|
|
148
|
+
success: false,
|
|
149
|
+
message: `Failed to install from VSIX: ${error.message}`,
|
|
150
|
+
error
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
} else {
|
|
154
|
+
// Try marketplace (may not be available yet)
|
|
155
|
+
onProgress('Installing extension from VS Code Marketplace...');
|
|
156
|
+
try {
|
|
157
|
+
await installFromMarketplace();
|
|
158
|
+
return {
|
|
159
|
+
success: true,
|
|
160
|
+
message: 'TeamSpec extension installed successfully from Marketplace.'
|
|
161
|
+
};
|
|
162
|
+
} catch (error) {
|
|
163
|
+
return {
|
|
164
|
+
success: false,
|
|
165
|
+
message: 'Extension not found in Marketplace and no local VSIX available.',
|
|
166
|
+
hint: 'Build the extension with: cd vscode-extension && npm run package',
|
|
167
|
+
error
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Copy extension files to workspace for development/testing
|
|
175
|
+
*/
|
|
176
|
+
function copyExtensionToWorkspace(targetDir, sourceExtensionDir) {
|
|
177
|
+
const vscodeDir = path.join(targetDir, '.vscode');
|
|
178
|
+
fs.mkdirSync(vscodeDir, { recursive: true });
|
|
179
|
+
|
|
180
|
+
// Create a settings.json with TeamSpec recommendations
|
|
181
|
+
const settingsPath = path.join(vscodeDir, 'settings.json');
|
|
182
|
+
let settings = {};
|
|
183
|
+
|
|
184
|
+
if (fs.existsSync(settingsPath)) {
|
|
185
|
+
try {
|
|
186
|
+
settings = JSON.parse(fs.readFileSync(settingsPath, 'utf-8'));
|
|
187
|
+
} catch {
|
|
188
|
+
// Ignore parse errors, start fresh
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// Add TeamSpec settings
|
|
193
|
+
settings['teamspec.enforceGates'] = true;
|
|
194
|
+
settings['files.associations'] = settings['files.associations'] || {};
|
|
195
|
+
settings['files.associations']['*.teamspec'] = 'yaml';
|
|
196
|
+
|
|
197
|
+
fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
|
|
198
|
+
|
|
199
|
+
// Create extensions.json to recommend the extension
|
|
200
|
+
const extensionsPath = path.join(vscodeDir, 'extensions.json');
|
|
201
|
+
const extensions = {
|
|
202
|
+
recommendations: [EXTENSION_ID]
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
if (fs.existsSync(extensionsPath)) {
|
|
206
|
+
try {
|
|
207
|
+
const existing = JSON.parse(fs.readFileSync(extensionsPath, 'utf-8'));
|
|
208
|
+
if (existing.recommendations && !existing.recommendations.includes(EXTENSION_ID)) {
|
|
209
|
+
existing.recommendations.push(EXTENSION_ID);
|
|
210
|
+
}
|
|
211
|
+
extensions.recommendations = existing.recommendations || [EXTENSION_ID];
|
|
212
|
+
} catch {
|
|
213
|
+
// Ignore parse errors
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
fs.writeFileSync(extensionsPath, JSON.stringify(extensions, null, 2));
|
|
218
|
+
|
|
219
|
+
return {
|
|
220
|
+
settingsPath,
|
|
221
|
+
extensionsPath
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// =============================================================================
|
|
226
|
+
// Exports
|
|
227
|
+
// =============================================================================
|
|
228
|
+
|
|
229
|
+
module.exports = {
|
|
230
|
+
installExtension,
|
|
231
|
+
copyExtensionToWorkspace,
|
|
232
|
+
isVSCodeAvailable,
|
|
233
|
+
isExtensionInstalled,
|
|
234
|
+
EXTENSION_ID,
|
|
235
|
+
EXTENSION_NAME
|
|
236
|
+
};
|