@torus-engineering/tas-kit 1.12.0 → 1.14.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/.tas/commands/tas-init.md +1 -1
- package/README.md +13 -5
- package/bin/cli.js +1 -1
- package/lib/adapters/antigravity.js +7 -13
- package/lib/adapters/codex.js +8 -14
- package/lib/install.js +183 -40
- package/package.json +2 -2
- package/.tas/README.md +0 -334
|
@@ -4,7 +4,7 @@ Initialize TAS kit for the current project.
|
|
|
4
4
|
|
|
5
5
|
## Actions
|
|
6
6
|
1. Need context from root/tas.yaml. If not exists, copy from .tas/tas-example.yaml to root and ask user to fill required information.
|
|
7
|
-
2. Create directory structure: .tas/templates/, docs/, docs/adr/, docs/epics/, docs/bugs/
|
|
7
|
+
2. Create directory structure: .tas/templates/, docs/, docs/adr/, docs/epics/, docs/bugs/, docs/ref/
|
|
8
8
|
3. Create root/project-status.yaml file with initial state (artifacts, epics, adrs all empty).
|
|
9
9
|
4. Copy default templates to .tas/templates/ if not exist.
|
|
10
10
|
5. If project type is brownfield and codebase_scan_on_init = true:
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# TAS Kit
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
TAS Kit - Turbo Agentic SDLC toolkit for modern AI-first software teams.
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -33,8 +33,8 @@ All code starts from spec. Story.md is "context digest" that has absorbed all in
|
|
|
33
33
|
- When coding: MUST start new session (don't reuse old session that loaded PRD/SAD to avoid Window Context bloat)
|
|
34
34
|
|
|
35
35
|
### Role-Based & Template-Driven
|
|
36
|
-
- 3
|
|
37
|
-
- Separate templates for PRD, SAD, ADR, Epic, Feature, Story per
|
|
36
|
+
- 3 roles: PE (Product Engineer), SE (Software Engineer), DSE (DevOps Engineer)
|
|
37
|
+
- Separate templates for PRD, SAD, ADR, Epic, Feature, Story per team standards
|
|
38
38
|
- Flow configurable via `tas.yaml` file
|
|
39
39
|
|
|
40
40
|
### Azure DevOps Compatible
|
|
@@ -329,6 +329,14 @@ tas.yaml Flow configuration template (edit this for your project)
|
|
|
329
329
|
|
|
330
330
|
---
|
|
331
331
|
|
|
332
|
-
##
|
|
332
|
+
## Changelog
|
|
333
333
|
|
|
334
|
-
|
|
334
|
+
### v1.14.0
|
|
335
|
+
- Support 4 Agentic Coding Platforms: Claude Code, Cursor, Codex, Antigravity
|
|
336
|
+
- Compress kit size — refactor commands, skills, rules to only include what's truly necessary
|
|
337
|
+
- Remove legacy agent and skill files
|
|
338
|
+
|
|
339
|
+
### v1.11.x
|
|
340
|
+
- Drop Claude Code branding from kit artifacts
|
|
341
|
+
- Set real Azure DevOps project_id in config
|
|
342
|
+
- Translate all documentation to English
|
package/bin/cli.js
CHANGED
|
@@ -55,9 +55,9 @@ export async function install({ tasDir, target }) {
|
|
|
55
55
|
console.log(' [ok] .agents/rules/ (from .tas/rules/)');
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
//
|
|
59
|
-
await
|
|
60
|
-
console.log(' [ok]
|
|
58
|
+
// platform index (not root AGENTS.md — that's the template/system prompt)
|
|
59
|
+
await generateReadme(agentsDir);
|
|
60
|
+
console.log(' [ok] .agents/README.md');
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
async function commandToWorkflow(file, agentsDir) {
|
|
@@ -95,7 +95,7 @@ async function convertRules(rulesDir, outDir) {
|
|
|
95
95
|
}
|
|
96
96
|
}
|
|
97
97
|
|
|
98
|
-
async function
|
|
98
|
+
async function generateReadme(agentsDir) {
|
|
99
99
|
const workflowFiles = (await fs.readdir(agentsDir, { withFileTypes: true }))
|
|
100
100
|
.filter(e => e.isFile() && e.name.endsWith('.md'))
|
|
101
101
|
.map(e => `- \`/${e.name.replace('.md', '')}\``);
|
|
@@ -112,10 +112,8 @@ async function generateAgentsMd(agentsDir, target) {
|
|
|
112
112
|
}
|
|
113
113
|
}
|
|
114
114
|
|
|
115
|
-
const
|
|
116
|
-
`#
|
|
117
|
-
``,
|
|
118
|
-
`This project uses TAS Kit — Torus Agentic SDLC Kit.`,
|
|
115
|
+
const readme = [
|
|
116
|
+
`# TAS Kit — Antigravity`,
|
|
119
117
|
``,
|
|
120
118
|
`## Workflows`,
|
|
121
119
|
``,
|
|
@@ -127,11 +125,7 @@ async function generateAgentsMd(agentsDir, target) {
|
|
|
127
125
|
``,
|
|
128
126
|
...skillLines,
|
|
129
127
|
``,
|
|
130
|
-
`## Project Configuration`,
|
|
131
|
-
``,
|
|
132
|
-
`See \`tas.yaml\` for project settings and project instructions file for detailed conventions.`,
|
|
133
|
-
``,
|
|
134
128
|
].join('\n');
|
|
135
129
|
|
|
136
|
-
await fs.writeFile(path.join(
|
|
130
|
+
await fs.writeFile(path.join(agentsDir, 'README.md'), readme);
|
|
137
131
|
}
|
package/lib/adapters/codex.js
CHANGED
|
@@ -52,9 +52,9 @@ export async function install({ tasDir, target }) {
|
|
|
52
52
|
console.log(' [ok] .codex/skills/ (rules)');
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
-
//
|
|
56
|
-
await
|
|
57
|
-
console.log(' [ok]
|
|
55
|
+
// platform index (not root AGENTS.md — that's the template/system prompt)
|
|
56
|
+
await generateReadme(skillsOut, codexDir);
|
|
57
|
+
console.log(' [ok] .codex/README.md');
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
async function commandToSkill(file, skillsOut) {
|
|
@@ -129,7 +129,7 @@ async function rulesToSkills(rulesDir, skillsOut) {
|
|
|
129
129
|
}
|
|
130
130
|
}
|
|
131
131
|
|
|
132
|
-
async function
|
|
132
|
+
async function generateReadme(skillsOut, codexDir) {
|
|
133
133
|
const skillDirs = await fs.readdir(skillsOut, { withFileTypes: true });
|
|
134
134
|
const skillLines = [];
|
|
135
135
|
for (const d of skillDirs.filter(e => e.isDirectory())) {
|
|
@@ -142,22 +142,16 @@ async function generateAgentsMd(skillsOut, target) {
|
|
|
142
142
|
}
|
|
143
143
|
}
|
|
144
144
|
|
|
145
|
-
const
|
|
146
|
-
`#
|
|
147
|
-
``,
|
|
148
|
-
`This project uses TAS Kit — Torus Agentic SDLC Kit.`,
|
|
145
|
+
const readme = [
|
|
146
|
+
`# TAS Kit — Codex`,
|
|
149
147
|
``,
|
|
150
148
|
`## Available Skills`,
|
|
151
149
|
``,
|
|
152
|
-
`Use \`/skills\` to list and invoke skills
|
|
150
|
+
`Use \`/skills\` to list and invoke skills:`,
|
|
153
151
|
``,
|
|
154
152
|
...skillLines,
|
|
155
153
|
``,
|
|
156
|
-
`## Project Configuration`,
|
|
157
|
-
``,
|
|
158
|
-
`See \`tas.yaml\` for project settings and \`CLAUDE.md\` for detailed instructions.`,
|
|
159
|
-
``,
|
|
160
154
|
].join('\n');
|
|
161
155
|
|
|
162
|
-
await fs.writeFile(path.join(
|
|
156
|
+
await fs.writeFile(path.join(codexDir, 'README.md'), readme);
|
|
163
157
|
}
|
package/lib/install.js
CHANGED
|
@@ -10,6 +10,25 @@ const TAS_SRC = path.join(PACKAGE_DIR, '.tas');
|
|
|
10
10
|
const PLATFORMS_FILE = '.tas/platforms.json';
|
|
11
11
|
const require = createRequire(import.meta.url);
|
|
12
12
|
|
|
13
|
+
// ─── Logo ────────────────────────────────────────────────────────────────────
|
|
14
|
+
|
|
15
|
+
function printLogo() {
|
|
16
|
+
const c = '\x1b[36m';
|
|
17
|
+
const d = '\x1b[90m';
|
|
18
|
+
const r = '\x1b[0m';
|
|
19
|
+
const art = [
|
|
20
|
+
` ████████╗ █████╗ ███████╗ ██╗ ██╗ ██╗ ████████╗`,
|
|
21
|
+
` ╚══██╔══╝ ██╔══██╗██╔════╝ ██║ ██╔╝ ██║ ╚══██╔══╝`,
|
|
22
|
+
` ██║ ███████║███████╗ █████╔╝ ██║ ██║ `,
|
|
23
|
+
` ██║ ██╔══██║╚════██║ ██╔═██╗ ██║ ██║ `,
|
|
24
|
+
` ██║ ██║ ██║███████║ ██║ ██╗ ██║ ██║ `,
|
|
25
|
+
` ╚═╝ ╚═╝ ╚═╝╚══════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ `,
|
|
26
|
+
].map(l => c + l + r).join('\n');
|
|
27
|
+
process.stdout.write('\n' + art + '\n' + d + ' Turbo Agentic SDLC Kit' + r + '\n\n');
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// ─── Helpers ─────────────────────────────────────────────────────────────────
|
|
31
|
+
|
|
13
32
|
async function getDeletedFiles() {
|
|
14
33
|
try {
|
|
15
34
|
const manifest = require('./deleted-files.json');
|
|
@@ -57,30 +76,152 @@ async function copyDir(src, dest) {
|
|
|
57
76
|
await fs.cp(src, dest, { recursive: true });
|
|
58
77
|
}
|
|
59
78
|
|
|
79
|
+
const TAS_ROOT_EXCLUDE = new Set([
|
|
80
|
+
'tas-example.yaml',
|
|
81
|
+
'project-status-example.yaml',
|
|
82
|
+
'platforms.json',
|
|
83
|
+
'agents',
|
|
84
|
+
'commands',
|
|
85
|
+
'skills',
|
|
86
|
+
'README.md',
|
|
87
|
+
]);
|
|
88
|
+
|
|
89
|
+
async function copyTasDir(src, dest) {
|
|
90
|
+
await fs.cp(src, dest, {
|
|
91
|
+
recursive: true,
|
|
92
|
+
filter: (srcPath) => !TAS_ROOT_EXCLUDE.has(path.relative(src, srcPath)),
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
async function chmodExecutables(target) {
|
|
97
|
+
const adoPy = path.join(target, '.tas', 'tools', 'tas-ado.py');
|
|
98
|
+
if (await exists(adoPy)) await fs.chmod(adoPy, 0o755);
|
|
99
|
+
|
|
100
|
+
const preCommit = path.join(target, '.tas', 'hooks', 'pre-commit');
|
|
101
|
+
if (await exists(preCommit)) await fs.chmod(preCommit, 0o755);
|
|
102
|
+
|
|
103
|
+
const hooksDir = path.join(target, '.tas', '_platform', 'hooks');
|
|
104
|
+
if (await exists(hooksDir)) {
|
|
105
|
+
const files = await fs.readdir(hooksDir);
|
|
106
|
+
for (const f of files) await fs.chmod(path.join(hooksDir, f), 0o755);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
60
110
|
// ─── Platform selection ───────────────────────────────────────────────────────
|
|
61
111
|
|
|
62
|
-
async function
|
|
63
|
-
if (
|
|
64
|
-
|
|
112
|
+
async function checkboxSelect(title, items, defaultIndexes = [0]) {
|
|
113
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
114
|
+
return fallbackTextSelect(title, items, defaultIndexes);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const selected = new Set(defaultIndexes);
|
|
118
|
+
let cursor = defaultIndexes[0] ?? 0;
|
|
119
|
+
let renderedLines = 0;
|
|
120
|
+
|
|
121
|
+
const clearRendered = () => {
|
|
122
|
+
if (renderedLines > 0) {
|
|
123
|
+
process.stdout.write(`\x1b[${renderedLines}A\x1b[0J`);
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
const render = () => {
|
|
128
|
+
clearRendered();
|
|
129
|
+
const lines = [];
|
|
130
|
+
lines.push(` ${title}`);
|
|
131
|
+
lines.push('');
|
|
132
|
+
for (let i = 0; i < items.length; i++) {
|
|
133
|
+
const mark = selected.has(i) ? '\x1b[32m◉\x1b[0m' : '○';
|
|
134
|
+
const arrow = cursor === i ? '\x1b[36m›\x1b[0m' : ' ';
|
|
135
|
+
const label = cursor === i ? `\x1b[36m${items[i].label}\x1b[0m` : items[i].label;
|
|
136
|
+
const note = items[i].note ? ` \x1b[90m${items[i].note}\x1b[0m` : '';
|
|
137
|
+
lines.push(` ${arrow} ${mark} ${label}${note}`);
|
|
138
|
+
}
|
|
139
|
+
lines.push('');
|
|
140
|
+
lines.push('\x1b[90m ↑↓ navigate space select enter confirm\x1b[0m');
|
|
141
|
+
renderedLines = lines.length;
|
|
142
|
+
process.stdout.write(lines.join('\n') + '\n');
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
return new Promise((resolve) => {
|
|
146
|
+
process.stdout.write('\x1b[?25l');
|
|
147
|
+
process.stdin.setRawMode(true);
|
|
148
|
+
process.stdin.resume();
|
|
149
|
+
process.stdin.setEncoding('utf8');
|
|
150
|
+
|
|
151
|
+
render();
|
|
152
|
+
|
|
153
|
+
const onKey = (key) => {
|
|
154
|
+
if (key === '\x03') {
|
|
155
|
+
finish(null);
|
|
156
|
+
process.exit(0);
|
|
157
|
+
} else if (key === '\x1b[A') {
|
|
158
|
+
cursor = (cursor - 1 + items.length) % items.length;
|
|
159
|
+
render();
|
|
160
|
+
} else if (key === '\x1b[B') {
|
|
161
|
+
cursor = (cursor + 1) % items.length;
|
|
162
|
+
render();
|
|
163
|
+
} else if (key === ' ') {
|
|
164
|
+
if (selected.has(cursor)) selected.delete(cursor);
|
|
165
|
+
else selected.add(cursor);
|
|
166
|
+
render();
|
|
167
|
+
} else if (key === '\r' || key === '\n') {
|
|
168
|
+
const ids = items.filter((_, i) => selected.has(i)).map(it => it.id);
|
|
169
|
+
finish(ids.length > 0 ? ids : [items[cursor].id]);
|
|
170
|
+
}
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
const finish = (result) => {
|
|
174
|
+
process.stdin.removeListener('data', onKey);
|
|
175
|
+
process.stdin.setRawMode(false);
|
|
176
|
+
process.stdin.pause();
|
|
177
|
+
process.stdout.write('\x1b[?25h');
|
|
178
|
+
clearRendered();
|
|
179
|
+
if (result) {
|
|
180
|
+
const labels = result.map(id => items.find(it => it.id === id)?.label || id).join(', ');
|
|
181
|
+
process.stdout.write(` Platforms: \x1b[36m${labels}\x1b[0m\n\n`);
|
|
182
|
+
resolve(result);
|
|
183
|
+
}
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
process.stdin.on('data', onKey);
|
|
187
|
+
});
|
|
188
|
+
}
|
|
65
189
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
190
|
+
async function fallbackTextSelect(title, items, defaultIndexes) {
|
|
191
|
+
console.log(`\n ${title}`);
|
|
192
|
+
items.forEach((item, i) => {
|
|
193
|
+
const def = defaultIndexes.includes(i) ? ' (default)' : '';
|
|
194
|
+
console.log(` [${i + 1}] ${item.label}${def}`);
|
|
70
195
|
});
|
|
71
196
|
console.log('');
|
|
72
197
|
console.log(' Enter numbers comma-separated for multiple platforms.');
|
|
73
|
-
const
|
|
198
|
+
const nums = items.map((_, i) => i + 1).join('/');
|
|
199
|
+
const answer = await ask(` Choose [${nums}] (default: 1): `, '1');
|
|
74
200
|
|
|
75
201
|
const selected = [];
|
|
76
202
|
for (const part of answer.split(',')) {
|
|
77
203
|
const idx = parseInt(part.trim(), 10) - 1;
|
|
78
|
-
if (idx >= 0 && idx <
|
|
79
|
-
const id =
|
|
204
|
+
if (idx >= 0 && idx < items.length) {
|
|
205
|
+
const id = items[idx].id;
|
|
80
206
|
if (!selected.includes(id)) selected.push(id);
|
|
81
207
|
}
|
|
82
208
|
}
|
|
83
|
-
return selected.length > 0 ? selected : [
|
|
209
|
+
return selected.length > 0 ? selected : [items[defaultIndexes[0] ?? 0].id];
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
async function choosePlatforms({ yes, forced }) {
|
|
213
|
+
if (forced && forced.length > 0) return forced;
|
|
214
|
+
if (yes) return ['claude-code'];
|
|
215
|
+
|
|
216
|
+
return checkboxSelect(
|
|
217
|
+
'Agentic Coding Platform(s) to install:',
|
|
218
|
+
PLATFORMS.map(p => ({
|
|
219
|
+
id: p.id,
|
|
220
|
+
label: p.label,
|
|
221
|
+
note: p.id === 'claude-code' ? '(default)' : '',
|
|
222
|
+
})),
|
|
223
|
+
[0],
|
|
224
|
+
);
|
|
84
225
|
}
|
|
85
226
|
|
|
86
227
|
async function savePlatforms(target, platforms) {
|
|
@@ -240,6 +381,7 @@ async function installSecurityHook({ target, mode }) {
|
|
|
240
381
|
// ─── Update ──────────────────────────────────────────────────────────────────
|
|
241
382
|
|
|
242
383
|
export async function update({ directory, yes, securityHook, platforms: forcedPlatforms }) {
|
|
384
|
+
printLogo();
|
|
243
385
|
const target = path.resolve(directory);
|
|
244
386
|
|
|
245
387
|
const tasExists = await exists(path.join(target, '.tas'));
|
|
@@ -249,7 +391,7 @@ export async function update({ directory, yes, securityHook, platforms: forcedPl
|
|
|
249
391
|
process.exit(1);
|
|
250
392
|
}
|
|
251
393
|
|
|
252
|
-
console.log(
|
|
394
|
+
console.log(`Updating TAS Kit in: ${target}\n`);
|
|
253
395
|
|
|
254
396
|
const platforms = forcedPlatforms && forcedPlatforms.length > 0
|
|
255
397
|
? forcedPlatforms
|
|
@@ -270,7 +412,8 @@ export async function update({ directory, yes, securityHook, platforms: forcedPl
|
|
|
270
412
|
|
|
271
413
|
const tasDest = path.join(target, '.tas');
|
|
272
414
|
if (path.resolve(TAS_SRC) !== path.resolve(tasDest)) {
|
|
273
|
-
await
|
|
415
|
+
await copyTasDir(TAS_SRC, tasDest);
|
|
416
|
+
await fs.copyFile(path.join(PACKAGE_DIR, 'README.md'), path.join(tasDest, 'README.md'));
|
|
274
417
|
}
|
|
275
418
|
console.log(' [ok] .tas/ (updated)');
|
|
276
419
|
|
|
@@ -282,7 +425,7 @@ export async function update({ directory, yes, securityHook, platforms: forcedPl
|
|
|
282
425
|
}
|
|
283
426
|
}
|
|
284
427
|
|
|
285
|
-
await runPlatformAdapters(platforms, { tasDir:
|
|
428
|
+
await runPlatformAdapters(platforms, { tasDir: TAS_SRC, target });
|
|
286
429
|
|
|
287
430
|
await savePlatforms(target, platforms);
|
|
288
431
|
|
|
@@ -294,7 +437,8 @@ export async function update({ directory, yes, securityHook, platforms: forcedPl
|
|
|
294
437
|
await installSecurityHook({ target, mode: securityHook });
|
|
295
438
|
}
|
|
296
439
|
|
|
297
|
-
|
|
440
|
+
const configFilename = platforms.includes('claude-code') ? 'CLAUDE.md' : 'AGENTS.md';
|
|
441
|
+
console.log(` [--] ${configFilename}, tas.yaml, project-status.yaml, .env.example — not touched`);
|
|
298
442
|
console.log(`
|
|
299
443
|
TAS Kit updated successfully!
|
|
300
444
|
|
|
@@ -306,11 +450,12 @@ and manually merge changes into your CLAUDE.md and tas.yaml if needed.
|
|
|
306
450
|
// ─── Install ─────────────────────────────────────────────────────────────────
|
|
307
451
|
|
|
308
452
|
export async function install({ directory, yes, securityHook, platforms: forcedPlatforms }) {
|
|
453
|
+
printLogo();
|
|
309
454
|
const target = path.resolve(directory);
|
|
310
455
|
|
|
311
456
|
await fs.mkdir(target, { recursive: true });
|
|
312
457
|
|
|
313
|
-
console.log(
|
|
458
|
+
console.log(`Installing TAS Kit into: ${target}\n`);
|
|
314
459
|
|
|
315
460
|
const tasExists = await exists(path.join(target, '.tas'));
|
|
316
461
|
if (tasExists && !yes) {
|
|
@@ -327,7 +472,8 @@ export async function install({ directory, yes, securityHook, platforms: forcedP
|
|
|
327
472
|
// Copy .tas/ (skip if installing into the package itself)
|
|
328
473
|
const tasDest = path.join(target, '.tas');
|
|
329
474
|
if (path.resolve(TAS_SRC) !== path.resolve(tasDest)) {
|
|
330
|
-
await
|
|
475
|
+
await copyTasDir(TAS_SRC, tasDest);
|
|
476
|
+
await fs.copyFile(path.join(PACKAGE_DIR, 'README.md'), path.join(tasDest, 'README.md'));
|
|
331
477
|
console.log(' [ok] .tas/');
|
|
332
478
|
} else {
|
|
333
479
|
console.log(' [--] .tas/ (source = destination, skipped)');
|
|
@@ -335,16 +481,18 @@ export async function install({ directory, yes, securityHook, platforms: forcedP
|
|
|
335
481
|
|
|
336
482
|
// Platform selection
|
|
337
483
|
const platforms = await choosePlatforms({ yes, forced: forcedPlatforms });
|
|
338
|
-
await runPlatformAdapters(platforms, { tasDir:
|
|
484
|
+
await runPlatformAdapters(platforms, { tasDir: TAS_SRC, target });
|
|
339
485
|
await savePlatforms(target, platforms);
|
|
340
486
|
|
|
341
487
|
// Project config files (first-time only)
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
488
|
+
// Claude Code uses CLAUDE.md; all other platforms use AGENTS.md
|
|
489
|
+
const configFilename = platforms.includes('claude-code') ? 'CLAUDE.md' : 'AGENTS.md';
|
|
490
|
+
const configTarget = path.join(target, configFilename);
|
|
491
|
+
if (!(await exists(configTarget))) {
|
|
492
|
+
await fs.copyFile(path.join(PACKAGE_DIR, '.tas', 'templates', 'AGENTS.md'), configTarget);
|
|
493
|
+
console.log(` [ok] ${configFilename} (from .tas/templates/AGENTS.md)`);
|
|
346
494
|
} else {
|
|
347
|
-
console.log(
|
|
495
|
+
console.log(` [--] ${configFilename} already exists, skipped`);
|
|
348
496
|
}
|
|
349
497
|
|
|
350
498
|
const envExampleTarget = path.join(target, '.env.example');
|
|
@@ -363,6 +511,17 @@ export async function install({ directory, yes, securityHook, platforms: forcedP
|
|
|
363
511
|
console.log(' [--] tas.yaml already exists, skipped');
|
|
364
512
|
}
|
|
365
513
|
|
|
514
|
+
const psYamlTarget = path.join(target, 'project-status.yaml');
|
|
515
|
+
if (!(await exists(psYamlTarget))) {
|
|
516
|
+
const psSrc = path.join(PACKAGE_DIR, '.tas', 'project-status-example.yaml');
|
|
517
|
+
if (await exists(psSrc)) {
|
|
518
|
+
await fs.copyFile(psSrc, psYamlTarget);
|
|
519
|
+
console.log(' [ok] project-status.yaml (from .tas/project-status-example.yaml)');
|
|
520
|
+
}
|
|
521
|
+
} else {
|
|
522
|
+
console.log(' [--] project-status.yaml already exists, skipped');
|
|
523
|
+
}
|
|
524
|
+
|
|
366
525
|
if (process.platform !== 'win32') {
|
|
367
526
|
await chmodExecutables(target);
|
|
368
527
|
}
|
|
@@ -375,7 +534,7 @@ export async function install({ directory, yes, securityHook, platforms: forcedP
|
|
|
375
534
|
TAS Kit installed successfully! (Platforms: ${platformLabels})
|
|
376
535
|
|
|
377
536
|
Next steps:
|
|
378
|
-
1. Edit
|
|
537
|
+
1. Edit ${configFilename.padEnd(10)} — add your project's tech stack and conventions
|
|
379
538
|
2. Edit tas.yaml — set project name, team and ADO config
|
|
380
539
|
3. Create .env — add AZURE_DEVOPS_PAT (see .env.example)
|
|
381
540
|
4. Open your IDE — run /tas-init to initialize your project
|
|
@@ -385,19 +544,3 @@ Docs:
|
|
|
385
544
|
.tas/hooks/README.md — pre-commit security hook details
|
|
386
545
|
`);
|
|
387
546
|
}
|
|
388
|
-
|
|
389
|
-
// ─── Helpers ─────────────────────────────────────────────────────────────────
|
|
390
|
-
|
|
391
|
-
async function chmodExecutables(target) {
|
|
392
|
-
const adoPy = path.join(target, '.tas', 'tools', 'tas-ado.py');
|
|
393
|
-
if (await exists(adoPy)) await fs.chmod(adoPy, 0o755);
|
|
394
|
-
|
|
395
|
-
const preCommit = path.join(target, '.tas', 'hooks', 'pre-commit');
|
|
396
|
-
if (await exists(preCommit)) await fs.chmod(preCommit, 0o755);
|
|
397
|
-
|
|
398
|
-
const hooksDir = path.join(target, '.tas', '_platform', 'hooks');
|
|
399
|
-
if (await exists(hooksDir)) {
|
|
400
|
-
const files = await fs.readdir(hooksDir);
|
|
401
|
-
for (const f of files) await fs.chmod(path.join(hooksDir, f), 0o755);
|
|
402
|
-
}
|
|
403
|
-
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@torus-engineering/tas-kit",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "1.14.0",
|
|
4
|
+
"description": "TAS Kit - Turbo Agentic SDLC toolkit for modern AI-first software teams.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"tas-kit": "bin/cli.js"
|
package/.tas/README.md
DELETED
|
@@ -1,334 +0,0 @@
|
|
|
1
|
-
# TAS Kit
|
|
2
|
-
|
|
3
|
-
**Torus Agentic SDLC Kit** — AI-assisted SDLC toolkit, designed following Spec-Driven Development philosophy and Context-Aware Architecture.
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## Purpose
|
|
8
|
-
|
|
9
|
-
TAS Kit helps software development teams:
|
|
10
|
-
- **Standardize SDLC process** with clear artifacts (PRD, SAD, ADR, Epic, Feature, Story)
|
|
11
|
-
- **Optimize token usage** through Context Layer — invest in design phase, save in code phase
|
|
12
|
-
- **Support multiple workflows**: from solo developer to full team with PE/SE/DSE roles
|
|
13
|
-
- **Automate** with Hybrid and Autonomous agents operating 24/7
|
|
14
|
-
|
|
15
|
-
---
|
|
16
|
-
|
|
17
|
-
## Design Philosophy
|
|
18
|
-
|
|
19
|
-
### Spec-Driven Development
|
|
20
|
-
All code starts from spec. Story.md is "context digest" that has absorbed all information from PRD, SAD, ADR, Feature. Each implementation session only needs to read CLAUDE.md + Story.md — no need to reload all artifacts.
|
|
21
|
-
|
|
22
|
-
### Human-Led, AI-Powered
|
|
23
|
-
- **Human-led**: Architecture decisions, design approval, code review
|
|
24
|
-
- **AI-assisted**: Draft creation, implementation per spec, test execution, bug detection
|
|
25
|
-
|
|
26
|
-
### Dual Mode Operation
|
|
27
|
-
- **Hybrid Mode**: Developer and AI work together in session
|
|
28
|
-
- **Autonomous Mode**: AI automatically develops 24/7, reports results when done
|
|
29
|
-
|
|
30
|
-
### Lightweight & Context-Aware
|
|
31
|
-
- Each skill < 3KB, total kit < 50KB
|
|
32
|
-
- Context Layer: invest tokens in design phase to save many times in code phase
|
|
33
|
-
- When coding: MUST start new session (don't reuse old session that loaded PRD/SAD to avoid Window Context bloat)
|
|
34
|
-
|
|
35
|
-
### Role-Based & Template-Driven
|
|
36
|
-
- 3 actual roles at Torus: PE (Product Engineer), SE (Software Engineer), DSE (DevOps Engineer)
|
|
37
|
-
- Separate templates for PRD, SAD, ADR, Epic, Feature, Story per Torus standards
|
|
38
|
-
- Flow configurable via `tas.yaml` file
|
|
39
|
-
|
|
40
|
-
### Azure DevOps Compatible
|
|
41
|
-
- Markdown output compatible with Azure DevOps Wiki
|
|
42
|
-
- Mermaid diagrams don't use `()` characters (avoid conflict with ADO syntax)
|
|
43
|
-
|
|
44
|
-
---
|
|
45
|
-
|
|
46
|
-
## SDLC Workflow
|
|
47
|
-
|
|
48
|
-
:::mermaid
|
|
49
|
-
graph TD
|
|
50
|
-
subgraph Phase1["Phase 1: Discovery"]
|
|
51
|
-
PRD["/tas-prd"]
|
|
52
|
-
SAD["/tas-sad"]
|
|
53
|
-
ADR["/tas-adr"]
|
|
54
|
-
DESIGN["/tas-design"]
|
|
55
|
-
PRD -->|Product Engineer| PRD_ARTIFACT["PRD.md"]
|
|
56
|
-
PRD_ARTIFACT -->|Software Engineer| SAD
|
|
57
|
-
PRD_ARTIFACT -->|Software Engineer| ADR
|
|
58
|
-
SAD --> SAD_ARTIFACT["SAD.md"]
|
|
59
|
-
ADR --> ADR_ARTIFACT["ADR-XXX.md"]
|
|
60
|
-
PRD_ARTIFACT -->|Product Engineer| DESIGN
|
|
61
|
-
DESIGN --> DESIGN_ARTIFACT["design-spec.md"]
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
subgraph Phase2["Phase 2: Planning"]
|
|
65
|
-
EPIC["/tas-epic"]
|
|
66
|
-
FEATURE["/tas-feature"]
|
|
67
|
-
STORY["/tas-story"]
|
|
68
|
-
PRD_ARTIFACT -->|Product Engineer| EPIC
|
|
69
|
-
EPIC --> EPIC_ARTIFACT["Epic-XXX/"]
|
|
70
|
-
EPIC_ARTIFACT -->|Product Engineer| FEATURE
|
|
71
|
-
FEATURE --> FEATURE_ARTIFACT["Feature-XXX/"]
|
|
72
|
-
SAD_ARTIFACT --> FEATURE
|
|
73
|
-
DESIGN_ARTIFACT --> FEATURE
|
|
74
|
-
FEATURE_ARTIFACT -->|Product Engineer| STORY
|
|
75
|
-
STORY --> STORY_ARTIFACT["Story-XXX.md"]
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
subgraph Phase3["Phase 3: Implementation"]
|
|
79
|
-
PLAN["/tas-plan"]
|
|
80
|
-
DEV["/tas-dev"]
|
|
81
|
-
FIX["/tas-fix"]
|
|
82
|
-
APItest["/tas-apitest"]
|
|
83
|
-
E2E["/tas-e2e"]
|
|
84
|
-
FUNCTEST_WEB["/tas-functest-web"]
|
|
85
|
-
FUNCTEST_MOBILE["/tas-functest-mobile"]
|
|
86
|
-
E2E_WEB["/tas-e2e-web"]
|
|
87
|
-
E2E_MOBILE["/tas-e2e-mobile"]
|
|
88
|
-
BUG["/tas-bug"]
|
|
89
|
-
REVIEW["/tas-review"]
|
|
90
|
-
FUNctest["/tas-functest"]
|
|
91
|
-
STORY_ARTIFACT -->|Software Engineer| PLAN
|
|
92
|
-
PLAN --> STORY_ARTIFACT
|
|
93
|
-
STORY_ARTIFACT -->|AI Agent| DEV
|
|
94
|
-
DEV --> CODE["Source Code"]
|
|
95
|
-
CODE -->|Bug found| FIX
|
|
96
|
-
FIX --> CODE
|
|
97
|
-
CODE -->|Software Engineer| REVIEW
|
|
98
|
-
REVIEW --> REVIEW_ARTIFACT["Code Review Report"]
|
|
99
|
-
STORY_ARTIFACT -->|Software Engineer| APItest
|
|
100
|
-
APItest --> APITEST_ARTIFACT["API Testing Script"]
|
|
101
|
-
FUNCTEST_ARTIFACT -->|Product Engineer| E2E
|
|
102
|
-
E2E --> E2E_ARTIFACT["E2E Test Scenarios"]
|
|
103
|
-
FUNCTEST_ARTIFACT -->|Software Engineer| FUNCTEST_WEB
|
|
104
|
-
FUNCTEST_WEB --> FUNCTEST_WEB_ARTIFACT["Functional Test Web Script"]
|
|
105
|
-
FUNCTEST_ARTIFACT -->|Software Engineer| FUNCTEST_MOBILE
|
|
106
|
-
FUNCTEST_MOBILE --> FUNCTEST_MOBILE_ARTIFACT["Functional Test Mobile Script"]
|
|
107
|
-
FUNCTEST_ARTIFACT -->|Product Engineer| E2E_WEB
|
|
108
|
-
E2E_WEB --> E2E_WEB_ARTIFACT["E2E Web Test Script"]
|
|
109
|
-
FUNCTEST_ARTIFACT -->|Product Engineer| E2E_MOBILE
|
|
110
|
-
E2E_MOBILE --> E2E_MOBILE_ARTIFACT["E2E Mobile Test Script"]
|
|
111
|
-
CODE -->|Bug found| BUG
|
|
112
|
-
BUG --> BUG_ARTIFACT["Bug Report"]
|
|
113
|
-
FEATURE_ARTIFACT -->|Product Engineer| FUNctest
|
|
114
|
-
FUNctest --> FUNCTEST_ARTIFACT["Functional-Testing-Spec-FeatureXXX.md"]
|
|
115
|
-
end
|
|
116
|
-
|
|
117
|
-
subgraph Phase4["Phase 4: Quality & Deploy"]
|
|
118
|
-
SECURITY["/tas-security"]
|
|
119
|
-
PIPELINE["Pipeline / CLI"]
|
|
120
|
-
CODE -->|DevOps Engineer| SECURITY
|
|
121
|
-
SECURITY --> SECURITY_ARTIFACT["Security Report"]
|
|
122
|
-
APITEST_ARTIFACT -->|Product Engineer| PIPELINE
|
|
123
|
-
FUNCTEST_WEB_ARTIFACT --> PIPELINE
|
|
124
|
-
FUNCTEST_MOBILE_ARTIFACT --> PIPELINE
|
|
125
|
-
E2E_WEB_ARTIFACT --> PIPELINE
|
|
126
|
-
E2E_MOBILE_ARTIFACT --> PIPELINE
|
|
127
|
-
PIPELINE --> TEST_REPORT["Test Report"]
|
|
128
|
-
SECURITY_ARTIFACT -->|DevOps Engineer| DEPLOY["Production"]
|
|
129
|
-
TEST_REPORT --> DEPLOY
|
|
130
|
-
end
|
|
131
|
-
|
|
132
|
-
STATUS["/tas-status"] -.->|Track| PRD_ARTIFACT
|
|
133
|
-
STATUS -.->|Track| SAD_ARTIFACT
|
|
134
|
-
STATUS -.->|Track| STORY_ARTIFACT
|
|
135
|
-
STATUS -.->|Track| DEPLOY
|
|
136
|
-
|
|
137
|
-
style PRD_ARTIFACT fill:#e1f5ff
|
|
138
|
-
style SAD_ARTIFACT fill:#fff4e1
|
|
139
|
-
style DESIGN_ARTIFACT fill:#f3e5f5
|
|
140
|
-
style STORY_ARTIFACT fill:#e8f5e9
|
|
141
|
-
style CODE fill:#f3e5f5
|
|
142
|
-
style TEST_REPORT fill:#c8e6c9
|
|
143
|
-
style DEPLOY fill:#c8e6c9
|
|
144
|
-
:::
|
|
145
|
-
|
|
146
|
-
### Phase Summary
|
|
147
|
-
|
|
148
|
-
| Phase | Role | Commands | Artifacts |
|
|
149
|
-
|-------|------|----------|-----------|
|
|
150
|
-
| **Phase 1: Discovery** | PE, SE | `/tas-prd`, `/tas-sad`, `/tas-adr`, `/tas-design` | PRD.md, SAD.md, ADR-XXX.md, design-spec.md |
|
|
151
|
-
| **Phase 2: Planning** | SE | `/tas-epic`, `/tas-feature`, `/tas-story`, `/tas-functest` | Epic-XXX/, Feature-XXX/, Story-XXX.md, Functional-Testing-Spec-FeatureXXX.md |
|
|
152
|
-
| **Phase 3: Implementation** | PE, SE, AI | `/tas-plan`, `/tas-dev`, `/tas-fix`, `/tas-apitest`, `/tas-e2e`, `/tas-functest-web`, `/tas-functest-mobile`, `/tas-e2e-web`, `/tas-e2e-mobile`, `/tas-bug`, `/tas-review` | Plan.md, Source Code, API Testing Script, E2E Test Scenarios, Functional Test Scripts, Bug Report, Code Review Report |
|
|
153
|
-
| **Phase 4: Quality & Deploy** | PE, DSE | `/tas-security`, Pipeline/CLI | Security Report, Test Report, Production |
|
|
154
|
-
|
|
155
|
-
### Phase Details
|
|
156
|
-
|
|
157
|
-
#### Phase 1: Discovery
|
|
158
|
-
- **PE**: Create PRD with `/tas-prd`, create design-spec with `/tas-design`
|
|
159
|
-
- **SE**: Create SAD with `/tas-sad`, create ADR with `/tas-adr`
|
|
160
|
-
|
|
161
|
-
#### Phase 2: Planning
|
|
162
|
-
- **PE**: Breakdown Epic with `/tas-epic`, Feature with `/tas-feature`, Story with `/tas-story`
|
|
163
|
-
|
|
164
|
-
#### Phase 3: Implementation
|
|
165
|
-
- **SE**: Create Plan with `/tas-plan`, Implement with `/tas-dev`, Fix bug with `/tas-fix`
|
|
166
|
-
- **SE**: Review code with `/tas-review`
|
|
167
|
-
- **PE**: Create Functional Testing Spec with `/tas-functest`
|
|
168
|
-
- **SE**: Create API Testing Script with `/tas-apitest`
|
|
169
|
-
- **PE**: Create E2E Test Scenarios with `/tas-e2e`
|
|
170
|
-
- **SE**: Create Functional Test Scripts with `/tas-functest-web`, `/tas-functest-mobile`
|
|
171
|
-
- **PE**: Create E2E Test Scripts with `/tas-e2e-web`, `/tas-e2e-mobile`
|
|
172
|
-
- **PE**: Create Bug Report with `/tas-bug`
|
|
173
|
-
|
|
174
|
-
#### Phase 4: Quality & Deploy
|
|
175
|
-
- **DSE**: Security Review with `/tas-security`
|
|
176
|
-
- **PE**: Run Pipeline/CLI to execute Automation Tests
|
|
177
|
-
- **DSE**: Deploy to Production
|
|
178
|
-
|
|
179
|
-
---
|
|
180
|
-
|
|
181
|
-
## Quick Start
|
|
182
|
-
|
|
183
|
-
```bash
|
|
184
|
-
npx @torus-engineering/tas-kit install
|
|
185
|
-
```
|
|
186
|
-
|
|
187
|
-
### Options
|
|
188
|
-
|
|
189
|
-
```bash
|
|
190
|
-
npx @torus-engineering/tas-kit install --directory /path/to/my-project
|
|
191
|
-
npx @torus-engineering/tas-kit install --yes # skip confirmation prompts
|
|
192
|
-
```
|
|
193
|
-
|
|
194
|
-
---
|
|
195
|
-
|
|
196
|
-
## Important Setup
|
|
197
|
-
|
|
198
|
-
### CLAUDE.md
|
|
199
|
-
|
|
200
|
-
Most important configuration file — Claude reads this file first in every session.
|
|
201
|
-
|
|
202
|
-
**Structure:**
|
|
203
|
-
```markdown
|
|
204
|
-
# Project Name
|
|
205
|
-
|
|
206
|
-
## Tech Stack
|
|
207
|
-
- Backend: .NET / Node.js / Python
|
|
208
|
-
- Frontend: React / Next.js
|
|
209
|
-
- Database: PostgreSQL / MySQL
|
|
210
|
-
- Infrastructure: AWS / Azure
|
|
211
|
-
|
|
212
|
-
## Conventions
|
|
213
|
-
- Coding standards
|
|
214
|
-
- Architecture patterns
|
|
215
|
-
- Testing requirements
|
|
216
|
-
```
|
|
217
|
-
|
|
218
|
-
### tas.yaml
|
|
219
|
-
|
|
220
|
-
Controls TAS Kit flow per project.
|
|
221
|
-
|
|
222
|
-
**Structure:**
|
|
223
|
-
```yaml
|
|
224
|
-
project:
|
|
225
|
-
name: "My Project"
|
|
226
|
-
team: "Team Name"
|
|
227
|
-
|
|
228
|
-
azure_devops:
|
|
229
|
-
enabled: true
|
|
230
|
-
organization: "org"
|
|
231
|
-
project: "project"
|
|
232
|
-
|
|
233
|
-
flow:
|
|
234
|
-
mode: "greenfield" # or "brownfield"
|
|
235
|
-
use_tdd: true
|
|
236
|
-
auto_review: true
|
|
237
|
-
```
|
|
238
|
-
|
|
239
|
-
### project-status.yaml
|
|
240
|
-
|
|
241
|
-
Project status index — automatically updated after each artifact change.
|
|
242
|
-
|
|
243
|
-
**Structure:**
|
|
244
|
-
```yaml
|
|
245
|
-
last_updated: 2025-01-15
|
|
246
|
-
|
|
247
|
-
artifacts:
|
|
248
|
-
prd:
|
|
249
|
-
file: docs/prd.md
|
|
250
|
-
status: Approved
|
|
251
|
-
version: "1.0"
|
|
252
|
-
|
|
253
|
-
epics:
|
|
254
|
-
Epic-001:
|
|
255
|
-
status: Active
|
|
256
|
-
features:
|
|
257
|
-
Feature-001:
|
|
258
|
-
stories:
|
|
259
|
-
Story-001:
|
|
260
|
-
status: In Progress
|
|
261
|
-
```
|
|
262
|
-
|
|
263
|
-
### .env
|
|
264
|
-
|
|
265
|
-
Environment variables for Azure DevOps integration.
|
|
266
|
-
|
|
267
|
-
```bash
|
|
268
|
-
AZURE_DEVOPS_PAT=your_pat_here
|
|
269
|
-
AZURE_DEVOPS_ORG=your_org
|
|
270
|
-
AZURE_DEVOPS_PROJECT=your_project
|
|
271
|
-
```
|
|
272
|
-
|
|
273
|
-
---
|
|
274
|
-
|
|
275
|
-
## What gets installed
|
|
276
|
-
|
|
277
|
-
```
|
|
278
|
-
.claude/
|
|
279
|
-
commands/ 22 slash commands (/tas-*, /ado-*)
|
|
280
|
-
skills/ 3 auto-invoked skills
|
|
281
|
-
agents/ 29 specialized subagents
|
|
282
|
-
.tas/
|
|
283
|
-
templates/ Markdown templates (PRD, SAD, ADR, Epic, Feature, Story...)
|
|
284
|
-
rules/ Coding standards + workflow rules (code-review, story-done, security...)
|
|
285
|
-
tools/ ADO integration script (tas-ado.py)
|
|
286
|
-
CLAUDE.md Project context template (edit this for your project)
|
|
287
|
-
tas.yaml Flow configuration template (edit this for your project)
|
|
288
|
-
.env.example Environment variable template
|
|
289
|
-
```
|
|
290
|
-
|
|
291
|
-
---
|
|
292
|
-
|
|
293
|
-
## Commands Reference
|
|
294
|
-
|
|
295
|
-
| Command | Description | Role |
|
|
296
|
-
|---------|-------------|------|
|
|
297
|
-
| `/tas-init` | Initialize TAS for new project | All |
|
|
298
|
-
| `/tas-status` | Display current project status | All |
|
|
299
|
-
| `/tas-prd` | Create/update Product Requirements Document | PE |
|
|
300
|
-
| `/tas-sad` | Create/update Solution Architecture Document | SE |
|
|
301
|
-
| `/tas-adr` | Create Architecture Decision Record | SE |
|
|
302
|
-
| `/tas-design` | Create Design Specification | SE |
|
|
303
|
-
| `/tas-epic` | Create/update Epic | SE |
|
|
304
|
-
| `/tas-feature` | Create/update Feature | SE |
|
|
305
|
-
| `/tas-story` | Create/update Story | SE |
|
|
306
|
-
| `/tas-functest` | Create Functional Testing Specification | SE |
|
|
307
|
-
| `/tas-spec` | Lightweight spec (solo / prototype) | SE |
|
|
308
|
-
| `/tas-plan` | Create technical implementation plan | SE |
|
|
309
|
-
| `/tas-dev` | Implement story (agentic) | AI |
|
|
310
|
-
| `/tas-fix` | Quick fix without full story flow | SE |
|
|
311
|
-
| `/tas-apitest` | Create API Testing Script automatically | SE |
|
|
312
|
-
| `/tas-e2e` | Create E2E Test Scenarios | PE |
|
|
313
|
-
| `/tas-functest-web` | Create Functional Test Script for Web | SE |
|
|
314
|
-
| `/tas-functest-mobile` | Create Functional Test Script for Mobile | SE |
|
|
315
|
-
| `/tas-e2e-web` | Create E2E Test Script for Web | PE |
|
|
316
|
-
| `/tas-e2e-mobile` | Create E2E Test Script for Mobile | PE |
|
|
317
|
-
| `/tas-bug` | Create Bug Report | PE |
|
|
318
|
-
| `/tas-review` | Code Review with checklist | SE |
|
|
319
|
-
| `/tas-brainstorm` | Brainstorm solutions | All |
|
|
320
|
-
| `/tas-security` | Security Review | DSE |
|
|
321
|
-
| `/ado-*` | Azure DevOps integration | All |
|
|
322
|
-
|
|
323
|
-
---
|
|
324
|
-
|
|
325
|
-
## Requirements
|
|
326
|
-
|
|
327
|
-
- Node.js 18+
|
|
328
|
-
- [Claude Code](https://claude.ai/code)
|
|
329
|
-
|
|
330
|
-
---
|
|
331
|
-
|
|
332
|
-
## Documentation
|
|
333
|
-
|
|
334
|
-
See `.tas/README.md` after install for detailed documentation.
|