@torus-engineering/tas-kit 1.13.0 → 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/.tas/_platform/claude-code/settings.json +58 -46
- package/.tas/_platform/hooks/code-quality.js +127 -127
- package/.tas/_platform/hooks/session-end.js +111 -111
- package/.tas/agents/architect.md +53 -53
- package/.tas/agents/aws-reviewer.md +71 -71
- package/.tas/agents/build-resolver.md +89 -59
- package/.tas/agents/code-explorer.md +63 -63
- package/.tas/agents/csharp-reviewer.md +62 -62
- package/.tas/agents/database-reviewer.md +73 -73
- package/.tas/agents/doc-updater.md +68 -66
- package/.tas/agents/python-reviewer.md +67 -67
- package/.tas/agents/security-reviewer.md +79 -79
- package/.tas/agents/software-engineer.md +53 -0
- package/.tas/agents/typescript-reviewer.md +65 -65
- package/.tas/commands/ado-create.md +33 -28
- package/.tas/commands/ado-delete.md +26 -22
- package/.tas/commands/ado-get.md +24 -20
- package/.tas/commands/ado-status.md +22 -18
- package/.tas/commands/ado-update.md +31 -27
- package/.tas/commands/tas-adr.md +37 -33
- package/.tas/commands/tas-apitest-plan.md +177 -173
- package/.tas/commands/tas-apitest.md +147 -143
- package/.tas/commands/tas-brainstorm.md +23 -19
- package/.tas/commands/tas-brd.md +50 -0
- package/.tas/commands/tas-bug.md +127 -113
- package/.tas/commands/tas-checklist.md +180 -0
- package/.tas/commands/tas-debug.md +103 -0
- package/.tas/commands/tas-design.md +41 -37
- package/.tas/commands/tas-dev.md +225 -125
- package/.tas/commands/tas-e2e-mobile.md +146 -155
- package/.tas/commands/tas-e2e-web.md +150 -163
- package/.tas/commands/tas-e2e.md +289 -102
- package/.tas/commands/tas-feature.md +181 -47
- package/.tas/commands/tas-fix.md +72 -51
- package/.tas/commands/tas-functest-mobile.md +138 -144
- package/.tas/commands/tas-functest-web.md +176 -192
- package/.tas/commands/tas-functest.md +225 -76
- package/.tas/commands/tas-init.md +22 -17
- package/.tas/commands/tas-master-plan.md +300 -0
- package/.tas/commands/tas-orchestrate.md +159 -0
- package/.tas/commands/tas-plan.md +152 -117
- package/.tas/commands/tas-prd.md +57 -37
- package/.tas/commands/tas-review-pr.md +174 -0
- package/.tas/commands/tas-review.md +115 -113
- package/.tas/commands/tas-sad.md +47 -43
- package/.tas/commands/tas-security.md +91 -87
- package/.tas/commands/tas-spec.md +54 -50
- package/.tas/commands/tas-status.md +25 -16
- package/.tas/project-status-example.yaml +3 -1
- package/.tas/rules/ado-integration.md +67 -65
- package/.tas/rules/common/api-design.md +517 -517
- package/.tas/rules/common/build-debug-loop.md +233 -0
- package/.tas/rules/common/code-review.md +4 -0
- package/.tas/rules/common/feature-done.md +42 -0
- package/.tas/rules/common/post-implementation-review.md +4 -0
- package/.tas/rules/common/project-status.md +33 -16
- package/.tas/rules/common/sad-impact.md +81 -0
- package/.tas/rules/common/tdd.md +104 -89
- package/.tas/rules/csharp/api-testing.md +2 -2
- package/.tas/rules/csharp/torus-core-framework.md +128 -0
- package/.tas/tas-example.yaml +9 -32
- package/.tas/templates/AGENTS.md +13 -0
- package/.tas/templates/API-Test-Spec.md +5 -4
- package/.tas/templates/BRD.md +133 -0
- package/.tas/templates/Bug.md +15 -0
- package/.tas/templates/E2E-Execution-Report.md +8 -8
- package/.tas/templates/E2E-Mobile-Spec.md +6 -8
- package/.tas/templates/E2E-Report.md +2 -2
- package/.tas/templates/E2E-Scenario.md +22 -22
- package/.tas/templates/E2E-Test-Spec.md +274 -0
- package/.tas/templates/E2E-Web-Spec.md +4 -4
- package/.tas/templates/Feature-Technical-Part.md +69 -0
- package/.tas/templates/Feature-Technical-Stack.md +74 -0
- package/.tas/templates/Feature-Technical.md +329 -0
- package/.tas/templates/Feature.md +50 -26
- package/.tas/templates/Func-Test-Script.md +29 -56
- package/.tas/templates/Func-Test-Spec.md +144 -142
- package/.tas/templates/PRD.md +173 -142
- package/.tas/templates/TestChecklist.md +96 -0
- package/.tas/templates/torus-dotnet-bootstrap.md +223 -0
- package/.tas/tools/tas-ado-readme.md +24 -27
- package/.tas/tools/tas-ado.py +328 -25
- package/.tas/tools/tas-github.py +339 -0
- package/README.md +142 -57
- package/bin/cli.js +90 -90
- package/lib/adapters/antigravity.js +131 -131
- package/lib/adapters/claude-code.js +71 -35
- package/lib/adapters/codex.js +157 -157
- package/lib/adapters/cursor.js +80 -80
- package/lib/adapters/index.js +20 -20
- package/lib/adapters/utils.js +81 -81
- package/lib/deleted-files.json +7 -0
- package/lib/install.js +546 -543
- package/package.json +2 -2
- package/.tas/README.md +0 -334
- package/.tas/commands/tas-epic.md +0 -35
- package/.tas/commands/tas-story.md +0 -91
- package/.tas/rules/common/story-done.md +0 -30
- package/.tas/templates/Epic.md +0 -46
- package/.tas/templates/Story.md +0 -90
package/lib/adapters/utils.js
CHANGED
|
@@ -1,81 +1,81 @@
|
|
|
1
|
-
import fs from 'node:fs/promises';
|
|
2
|
-
import path from 'node:path';
|
|
3
|
-
|
|
4
|
-
export async function exists(p) {
|
|
5
|
-
return fs.access(p).then(() => true).catch(() => false);
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
export async function copyDir(src, dest) {
|
|
9
|
-
await fs.cp(src, dest, { recursive: true });
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export async function listFilesRecursive(dir, ext = '') {
|
|
13
|
-
const results = [];
|
|
14
|
-
async function walk(current) {
|
|
15
|
-
const entries = await fs.readdir(current, { withFileTypes: true });
|
|
16
|
-
for (const e of entries) {
|
|
17
|
-
const full = path.join(current, e.name);
|
|
18
|
-
if (e.isDirectory()) await walk(full);
|
|
19
|
-
else if (!ext || e.name.endsWith(ext)) results.push(full);
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
await walk(dir);
|
|
23
|
-
return results;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export function parseFrontmatter(content) {
|
|
27
|
-
if (!content.startsWith('---')) return { frontmatter: {}, body: content };
|
|
28
|
-
const end = content.indexOf('\n---', 3);
|
|
29
|
-
if (end === -1) return { frontmatter: {}, body: content };
|
|
30
|
-
const yaml = content.slice(4, end);
|
|
31
|
-
const body = content.slice(end + 4).trimStart();
|
|
32
|
-
const frontmatter = {};
|
|
33
|
-
for (const line of yaml.split('\n')) {
|
|
34
|
-
const colon = line.indexOf(':');
|
|
35
|
-
if (colon > 0) {
|
|
36
|
-
const key = line.slice(0, colon).trim();
|
|
37
|
-
let val = line.slice(colon + 1).trim();
|
|
38
|
-
// handle multiline: only single-line values here
|
|
39
|
-
val = val.replace(/^["']|["']$/g, '');
|
|
40
|
-
frontmatter[key] = val;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
return { frontmatter, body };
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
// Extract description: first non-empty, non-heading line after the H1
|
|
47
|
-
export function extractDescription(content, fallback = '') {
|
|
48
|
-
const lines = content.split('\n');
|
|
49
|
-
let pastH1 = false;
|
|
50
|
-
for (const line of lines) {
|
|
51
|
-
const trimmed = line.trim();
|
|
52
|
-
if (!pastH1) {
|
|
53
|
-
if (trimmed.startsWith('# ')) pastH1 = true;
|
|
54
|
-
continue;
|
|
55
|
-
}
|
|
56
|
-
if (trimmed && !trimmed.startsWith('#') && !trimmed.startsWith('|') && !trimmed.startsWith('-')) {
|
|
57
|
-
return trimmed.replace(/^Role:\s*/i, '').replace(/\*\*/g, '').slice(0, 150);
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
return fallback;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
// Extract H1 title from markdown
|
|
64
|
-
export function extractH1(content) {
|
|
65
|
-
const match = content.match(/^#\s+(.+)$/m);
|
|
66
|
-
return match ? match[1].trim() : '';
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// Extract command name from first line: "# /tas-dev $ARGUMENTS" → "tas-dev"
|
|
70
|
-
export function extractCommandName(content) {
|
|
71
|
-
const match = content.match(/^#\s+\/(\S+)/);
|
|
72
|
-
return match ? match[1] : '';
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
// Escape a string for use in YAML frontmatter value (single-line)
|
|
76
|
-
export function yamlValue(str) {
|
|
77
|
-
if (/[:#\[\]{},|>&*!'"\\]/.test(str) || str.includes('\n')) {
|
|
78
|
-
return `"${str.replace(/"/g, '\\"')}"`;
|
|
79
|
-
}
|
|
80
|
-
return str;
|
|
81
|
-
}
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
|
|
4
|
+
export async function exists(p) {
|
|
5
|
+
return fs.access(p).then(() => true).catch(() => false);
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export async function copyDir(src, dest) {
|
|
9
|
+
await fs.cp(src, dest, { recursive: true });
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export async function listFilesRecursive(dir, ext = '') {
|
|
13
|
+
const results = [];
|
|
14
|
+
async function walk(current) {
|
|
15
|
+
const entries = await fs.readdir(current, { withFileTypes: true });
|
|
16
|
+
for (const e of entries) {
|
|
17
|
+
const full = path.join(current, e.name);
|
|
18
|
+
if (e.isDirectory()) await walk(full);
|
|
19
|
+
else if (!ext || e.name.endsWith(ext)) results.push(full);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
await walk(dir);
|
|
23
|
+
return results;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function parseFrontmatter(content) {
|
|
27
|
+
if (!content.startsWith('---')) return { frontmatter: {}, body: content };
|
|
28
|
+
const end = content.indexOf('\n---', 3);
|
|
29
|
+
if (end === -1) return { frontmatter: {}, body: content };
|
|
30
|
+
const yaml = content.slice(4, end);
|
|
31
|
+
const body = content.slice(end + 4).trimStart();
|
|
32
|
+
const frontmatter = {};
|
|
33
|
+
for (const line of yaml.split('\n')) {
|
|
34
|
+
const colon = line.indexOf(':');
|
|
35
|
+
if (colon > 0) {
|
|
36
|
+
const key = line.slice(0, colon).trim();
|
|
37
|
+
let val = line.slice(colon + 1).trim();
|
|
38
|
+
// handle multiline: only single-line values here
|
|
39
|
+
val = val.replace(/^["']|["']$/g, '');
|
|
40
|
+
frontmatter[key] = val;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return { frontmatter, body };
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Extract description: first non-empty, non-heading line after the H1
|
|
47
|
+
export function extractDescription(content, fallback = '') {
|
|
48
|
+
const lines = content.split('\n');
|
|
49
|
+
let pastH1 = false;
|
|
50
|
+
for (const line of lines) {
|
|
51
|
+
const trimmed = line.trim();
|
|
52
|
+
if (!pastH1) {
|
|
53
|
+
if (trimmed.startsWith('# ')) pastH1 = true;
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
if (trimmed && !trimmed.startsWith('#') && !trimmed.startsWith('|') && !trimmed.startsWith('-')) {
|
|
57
|
+
return trimmed.replace(/^Role:\s*/i, '').replace(/\*\*/g, '').slice(0, 150);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return fallback;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Extract H1 title from markdown
|
|
64
|
+
export function extractH1(content) {
|
|
65
|
+
const match = content.match(/^#\s+(.+)$/m);
|
|
66
|
+
return match ? match[1].trim() : '';
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Extract command name from first line: "# /tas-dev $ARGUMENTS" → "tas-dev"
|
|
70
|
+
export function extractCommandName(content) {
|
|
71
|
+
const match = content.match(/^#\s+\/(\S+)/);
|
|
72
|
+
return match ? match[1] : '';
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Escape a string for use in YAML frontmatter value (single-line)
|
|
76
|
+
export function yamlValue(str) {
|
|
77
|
+
if (/[:#\[\]{},|>&*!'"\\]/.test(str) || str.includes('\n')) {
|
|
78
|
+
return `"${str.replace(/"/g, '\\"')}"`;
|
|
79
|
+
}
|
|
80
|
+
return str;
|
|
81
|
+
}
|
package/lib/deleted-files.json
CHANGED
|
@@ -131,5 +131,12 @@
|
|
|
131
131
|
".claude/hooks/code-quality.js",
|
|
132
132
|
".claude/hooks/session-end.js",
|
|
133
133
|
".claude/settings.json"
|
|
134
|
+
],
|
|
135
|
+
"2.0.0": [
|
|
136
|
+
".tas/templates/Epic.md",
|
|
137
|
+
".tas/templates/Story.md",
|
|
138
|
+
".tas/commands/tas-epic.md",
|
|
139
|
+
".tas/commands/tas-story.md",
|
|
140
|
+
".tas/rules/common/story-done.md"
|
|
134
141
|
]
|
|
135
142
|
}
|