sdtk-kit 1.2.0 → 1.3.1
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 -21
- package/README.md +202 -135
- package/bin/sdtk-code.js +6 -6
- package/bin/sdtk-design.js +6 -6
- package/bin/sdtk-ops.js +6 -6
- package/bin/sdtk-spec.js +12 -12
- package/bin/sdtk-wiki.js +6 -6
- package/bin/sdtk.js +99 -0
- package/package.json +65 -60
- package/scripts/install-smoke.js +190 -0
- package/scripts/postinstall.js +43 -40
- package/scripts/unified-init.test.js +292 -0
- package/src/commands/init.js +106 -0
- package/src/lib/unified-init.js +280 -0
package/package.json
CHANGED
|
@@ -1,60 +1,65 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "sdtk-kit",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "Install all five SDTK toolkits in one command. Meta-package for sdtk-spec-kit, sdtk-code-kit, sdtk-ops-kit, sdtk-design-kit, and sdtk-wiki-kit.",
|
|
5
|
-
"type": "commonjs",
|
|
6
|
-
"bin": {
|
|
7
|
-
"sdtk
|
|
8
|
-
"sdtk-
|
|
9
|
-
"sdtk-
|
|
10
|
-
"sdtk-
|
|
11
|
-
"sdtk-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
"
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
"
|
|
25
|
-
"
|
|
26
|
-
"
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
"
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
"
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
"sdtk
|
|
40
|
-
"sdtk-
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
"
|
|
50
|
-
"
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
"
|
|
54
|
-
|
|
55
|
-
"url": "https://github.com/codexsdtk/sdtk-toolkit
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "sdtk-kit",
|
|
3
|
+
"version": "1.3.1",
|
|
4
|
+
"description": "Install all five SDTK toolkits in one command. Meta-package for sdtk-spec-kit, sdtk-code-kit, sdtk-ops-kit, sdtk-design-kit, and sdtk-wiki-kit.",
|
|
5
|
+
"type": "commonjs",
|
|
6
|
+
"bin": {
|
|
7
|
+
"sdtk": "bin/sdtk.js",
|
|
8
|
+
"sdtk-spec": "bin/sdtk-spec.js",
|
|
9
|
+
"sdtk-code": "bin/sdtk-code.js",
|
|
10
|
+
"sdtk-ops": "bin/sdtk-ops.js",
|
|
11
|
+
"sdtk-design": "bin/sdtk-design.js",
|
|
12
|
+
"sdtk-wiki": "bin/sdtk-wiki.js"
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"bin/",
|
|
16
|
+
"src/",
|
|
17
|
+
"scripts/",
|
|
18
|
+
"README.md",
|
|
19
|
+
"LICENSE"
|
|
20
|
+
],
|
|
21
|
+
"scripts": {
|
|
22
|
+
"postinstall": "node scripts/postinstall.js",
|
|
23
|
+
"test": "node scripts/unified-init.test.js",
|
|
24
|
+
"install:smoke:local": "node scripts/install-smoke.js --mode local",
|
|
25
|
+
"install:smoke:published": "node scripts/install-smoke.js --mode published --package sdtk-kit@latest",
|
|
26
|
+
"pack:smoke": "npm pack --dry-run"
|
|
27
|
+
},
|
|
28
|
+
"dependencies": {
|
|
29
|
+
"sdtk-spec-kit": "^0.4.7",
|
|
30
|
+
"sdtk-code-kit": "^0.3.0",
|
|
31
|
+
"sdtk-ops-kit": "^0.2.4",
|
|
32
|
+
"sdtk-design-kit": "^0.3.2",
|
|
33
|
+
"sdtk-wiki-kit": "^0.2.0"
|
|
34
|
+
},
|
|
35
|
+
"engines": {
|
|
36
|
+
"node": ">=18.13.0"
|
|
37
|
+
},
|
|
38
|
+
"keywords": [
|
|
39
|
+
"sdtk",
|
|
40
|
+
"sdtk-kit",
|
|
41
|
+
"sdtk-spec",
|
|
42
|
+
"sdtk-code",
|
|
43
|
+
"sdtk-ops",
|
|
44
|
+
"sdtk-design",
|
|
45
|
+
"sdtk-wiki",
|
|
46
|
+
"cli",
|
|
47
|
+
"toolkit",
|
|
48
|
+
"ai-workflow",
|
|
49
|
+
"solo-founder",
|
|
50
|
+
"mvp"
|
|
51
|
+
],
|
|
52
|
+
"license": "MIT",
|
|
53
|
+
"repository": {
|
|
54
|
+
"type": "git",
|
|
55
|
+
"url": "git+https://github.com/codexsdtk/sdtk-toolkit.git",
|
|
56
|
+
"directory": "products/sdtk-kit/distribution/sdtk-kit"
|
|
57
|
+
},
|
|
58
|
+
"homepage": "https://sdtk.dev",
|
|
59
|
+
"bugs": {
|
|
60
|
+
"url": "https://github.com/codexsdtk/sdtk-toolkit/issues"
|
|
61
|
+
},
|
|
62
|
+
"publishConfig": {
|
|
63
|
+
"access": "public"
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
|
|
4
|
+
const fs = require("fs");
|
|
5
|
+
const os = require("os");
|
|
6
|
+
const path = require("path");
|
|
7
|
+
const { spawnSync } = require("child_process");
|
|
8
|
+
|
|
9
|
+
const PACKAGE_ROOT = path.resolve(__dirname, "..");
|
|
10
|
+
const PACKAGE_JSON = path.join(PACKAGE_ROOT, "package.json");
|
|
11
|
+
const TOOLKITS = Object.freeze([
|
|
12
|
+
{ cli: "sdtk-spec", packageName: "sdtk-spec-kit" },
|
|
13
|
+
{ cli: "sdtk-code", packageName: "sdtk-code-kit" },
|
|
14
|
+
{ cli: "sdtk-ops", packageName: "sdtk-ops-kit" },
|
|
15
|
+
{ cli: "sdtk-design", packageName: "sdtk-design-kit" },
|
|
16
|
+
{ cli: "sdtk-wiki", packageName: "sdtk-wiki-kit" },
|
|
17
|
+
]);
|
|
18
|
+
|
|
19
|
+
function usage() {
|
|
20
|
+
return [
|
|
21
|
+
"Usage:",
|
|
22
|
+
" node scripts/install-smoke.js --mode local [--package ./sdtk-kit-1.2.0.tgz] [--keep-prefix]",
|
|
23
|
+
" node scripts/install-smoke.js --mode published [--package sdtk-kit@latest] [--keep-prefix]",
|
|
24
|
+
"",
|
|
25
|
+
"Modes:",
|
|
26
|
+
" local Packs the local sdtk-kit package when --package is omitted, then installs it into a clean prefix.",
|
|
27
|
+
" published Installs a published package spec, defaulting to sdtk-kit@latest, into a clean prefix.",
|
|
28
|
+
].join("\n");
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function parseArgs(argv) {
|
|
32
|
+
const args = { mode: "local", packageSpec: null, keepPrefix: false };
|
|
33
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
34
|
+
const arg = argv[i];
|
|
35
|
+
if (arg === "--mode") {
|
|
36
|
+
args.mode = argv[++i];
|
|
37
|
+
} else if (arg === "--package") {
|
|
38
|
+
args.packageSpec = argv[++i];
|
|
39
|
+
} else if (arg === "--keep-prefix") {
|
|
40
|
+
args.keepPrefix = true;
|
|
41
|
+
} else if (arg === "--help" || arg === "-h") {
|
|
42
|
+
console.log(usage());
|
|
43
|
+
process.exit(0);
|
|
44
|
+
} else {
|
|
45
|
+
throw new Error(`Unknown argument: ${arg}\n${usage()}`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
if (!new Set(["local", "published"]).has(args.mode)) {
|
|
49
|
+
throw new Error(`Invalid --mode: ${args.mode}\n${usage()}`);
|
|
50
|
+
}
|
|
51
|
+
return args;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function run(command, args, options = {}) {
|
|
55
|
+
const result = spawnSync(command, args, {
|
|
56
|
+
cwd: options.cwd || PACKAGE_ROOT,
|
|
57
|
+
env: options.env || process.env,
|
|
58
|
+
encoding: "utf8",
|
|
59
|
+
shell: options.shell || false,
|
|
60
|
+
});
|
|
61
|
+
if (result.status !== 0) {
|
|
62
|
+
throw new Error([
|
|
63
|
+
`Command failed: ${command} ${args.join(" ")}`,
|
|
64
|
+
`exit=${result.status}`,
|
|
65
|
+
result.stdout ? `stdout:\n${result.stdout}` : "stdout: <empty>",
|
|
66
|
+
result.stderr ? `stderr:\n${result.stderr}` : "stderr: <empty>",
|
|
67
|
+
].join("\n"));
|
|
68
|
+
}
|
|
69
|
+
return result;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function readJson(file) {
|
|
73
|
+
return JSON.parse(fs.readFileSync(file, "utf8"));
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function assertPackageMetadata(packageJson) {
|
|
77
|
+
const missingBins = [];
|
|
78
|
+
const missingDeps = [];
|
|
79
|
+
for (const toolkit of TOOLKITS) {
|
|
80
|
+
if (!packageJson.bin || packageJson.bin[toolkit.cli] !== `bin/${toolkit.cli}.js`) {
|
|
81
|
+
missingBins.push(toolkit.cli);
|
|
82
|
+
}
|
|
83
|
+
if (!packageJson.dependencies || !packageJson.dependencies[toolkit.packageName]) {
|
|
84
|
+
missingDeps.push(toolkit.packageName);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
if (missingBins.length || missingDeps.length) {
|
|
88
|
+
throw new Error(`sdtk-kit metadata is incomplete: missingBins=${missingBins.join(",") || "none"}; missingDeps=${missingDeps.join(",") || "none"}`);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function packLocalPackage() {
|
|
93
|
+
const result = run("npm", ["pack", "--json"], { cwd: PACKAGE_ROOT });
|
|
94
|
+
const entries = JSON.parse(result.stdout);
|
|
95
|
+
if (!Array.isArray(entries) || entries.length !== 1 || !entries[0].filename) {
|
|
96
|
+
throw new Error(`Unexpected npm pack --json output: ${result.stdout}`);
|
|
97
|
+
}
|
|
98
|
+
return path.join(PACKAGE_ROOT, entries[0].filename);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function npmBinPath(prefix, cli) {
|
|
102
|
+
const binDir = path.join(prefix, "node_modules", ".bin");
|
|
103
|
+
const candidates = process.platform === "win32"
|
|
104
|
+
? [path.join(binDir, `${cli}.cmd`), path.join(binDir, `${cli}.ps1`), path.join(binDir, cli)]
|
|
105
|
+
: [path.join(binDir, cli)];
|
|
106
|
+
return candidates.find((candidate) => fs.existsSync(candidate));
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function installedPackageJson(prefix, packageName) {
|
|
110
|
+
const candidates = [
|
|
111
|
+
path.join(prefix, "node_modules", packageName, "package.json"),
|
|
112
|
+
path.join(prefix, "node_modules", "sdtk-kit", "node_modules", packageName, "package.json"),
|
|
113
|
+
];
|
|
114
|
+
const found = candidates.find((candidate) => fs.existsSync(candidate));
|
|
115
|
+
if (!found) {
|
|
116
|
+
throw new Error(`Cannot find installed package.json for ${packageName} under ${prefix}`);
|
|
117
|
+
}
|
|
118
|
+
return readJson(found);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function runCliVersion(binPath) {
|
|
122
|
+
return run(binPath, ["--version"], { shell: process.platform === "win32" });
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function smokeInstall(packageSpec, mode, keepPrefix) {
|
|
126
|
+
const prefix = fs.mkdtempSync(path.join(os.tmpdir(), "sdtk-kit-install-smoke-"));
|
|
127
|
+
let packedTarball = null;
|
|
128
|
+
try {
|
|
129
|
+
const localPackageJson = readJson(PACKAGE_JSON);
|
|
130
|
+
assertPackageMetadata(localPackageJson);
|
|
131
|
+
|
|
132
|
+
let installSpec = packageSpec;
|
|
133
|
+
if (mode === "local" && !installSpec) {
|
|
134
|
+
packedTarball = packLocalPackage();
|
|
135
|
+
installSpec = packedTarball;
|
|
136
|
+
}
|
|
137
|
+
if (mode === "published" && !installSpec) {
|
|
138
|
+
installSpec = "sdtk-kit@latest";
|
|
139
|
+
}
|
|
140
|
+
if (!installSpec) {
|
|
141
|
+
throw new Error("No package spec resolved for install smoke.");
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
console.log(`[sdtk-kit smoke] mode=${mode}`);
|
|
145
|
+
console.log(`[sdtk-kit smoke] prefix=${prefix}`);
|
|
146
|
+
console.log(`[sdtk-kit smoke] install=${installSpec}`);
|
|
147
|
+
run("npm", ["install", "--prefix", prefix, installSpec]);
|
|
148
|
+
|
|
149
|
+
const installedMeta = installedPackageJson(prefix, "sdtk-kit");
|
|
150
|
+
assertPackageMetadata(installedMeta);
|
|
151
|
+
console.log(`[sdtk-kit smoke] installed sdtk-kit ${installedMeta.version}`);
|
|
152
|
+
|
|
153
|
+
for (const toolkit of TOOLKITS) {
|
|
154
|
+
const binPath = npmBinPath(prefix, toolkit.cli);
|
|
155
|
+
if (!binPath) {
|
|
156
|
+
throw new Error(`Missing CLI shim for ${toolkit.cli} in ${path.join(prefix, "node_modules", ".bin")}`);
|
|
157
|
+
}
|
|
158
|
+
const expected = installedPackageJson(prefix, toolkit.packageName).version;
|
|
159
|
+
const result = runCliVersion(binPath);
|
|
160
|
+
const output = `${result.stdout || ""}${result.stderr || ""}`.trim();
|
|
161
|
+
if (!output.includes(expected)) {
|
|
162
|
+
throw new Error(`${toolkit.cli} --version did not include installed ${toolkit.packageName} version ${expected}. Output: ${output}`);
|
|
163
|
+
}
|
|
164
|
+
console.log(`[sdtk-kit smoke] ${toolkit.cli} -> ${output}`);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
console.log("[sdtk-kit smoke] PASS all five CLI shims exist and --version checks passed.");
|
|
168
|
+
} finally {
|
|
169
|
+
if (packedTarball && fs.existsSync(packedTarball)) {
|
|
170
|
+
fs.rmSync(packedTarball, { force: true });
|
|
171
|
+
}
|
|
172
|
+
if (keepPrefix) {
|
|
173
|
+
console.log(`[sdtk-kit smoke] kept prefix: ${prefix}`);
|
|
174
|
+
} else {
|
|
175
|
+
fs.rmSync(prefix, { recursive: true, force: true });
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function main() {
|
|
181
|
+
const args = parseArgs(process.argv.slice(2));
|
|
182
|
+
smokeInstall(args.packageSpec, args.mode, args.keepPrefix);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
try {
|
|
186
|
+
main();
|
|
187
|
+
} catch (error) {
|
|
188
|
+
console.error(`[sdtk-kit smoke] FAIL ${error.message}`);
|
|
189
|
+
process.exit(1);
|
|
190
|
+
}
|
package/scripts/postinstall.js
CHANGED
|
@@ -1,40 +1,43 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
"use strict";
|
|
3
|
-
|
|
4
|
-
// Skip banner in CI environments and headless installs.
|
|
5
|
-
// This avoids noisy output in automated pipelines that install sdtk-kit
|
|
6
|
-
// as a transitive dependency.
|
|
7
|
-
const isCI =
|
|
8
|
-
process.env.CI === "true" ||
|
|
9
|
-
process.env.NODE_ENV === "test" ||
|
|
10
|
-
process.env.npm_config_loglevel === "silent" ||
|
|
11
|
-
process.env.npm_config_loglevel === "error";
|
|
12
|
-
|
|
13
|
-
if (isCI) {
|
|
14
|
-
process.exit(0);
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
const lines = [
|
|
18
|
-
"",
|
|
19
|
-
" ╔══════════════════════════════════════════════════════╗",
|
|
20
|
-
" ║ SDTK — All Five Toolkits Installed ║",
|
|
21
|
-
" ╚══════════════════════════════════════════════════════╝",
|
|
22
|
-
"",
|
|
23
|
-
" You now have all five SDTK CLI tools available:",
|
|
24
|
-
"",
|
|
25
|
-
" sdtk-spec — Spec-first SDLC: PM → BA → ARCH → DEV → QA",
|
|
26
|
-
" sdtk-design — MVP design: idea → prototype → handoff",
|
|
27
|
-
" sdtk-code — Governed coding: handoff → PR with review gates",
|
|
28
|
-
" sdtk-ops — Operations: deploy → smoke → sign-off",
|
|
29
|
-
" sdtk-wiki — Local second brain: your project memory",
|
|
30
|
-
"",
|
|
31
|
-
"
|
|
32
|
-
"",
|
|
33
|
-
" sdtk
|
|
34
|
-
"
|
|
35
|
-
"",
|
|
36
|
-
"
|
|
37
|
-
"",
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
|
|
4
|
+
// Skip banner in CI environments and headless installs.
|
|
5
|
+
// This avoids noisy output in automated pipelines that install sdtk-kit
|
|
6
|
+
// as a transitive dependency.
|
|
7
|
+
const isCI =
|
|
8
|
+
process.env.CI === "true" ||
|
|
9
|
+
process.env.NODE_ENV === "test" ||
|
|
10
|
+
process.env.npm_config_loglevel === "silent" ||
|
|
11
|
+
process.env.npm_config_loglevel === "error";
|
|
12
|
+
|
|
13
|
+
if (isCI) {
|
|
14
|
+
process.exit(0);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const lines = [
|
|
18
|
+
"",
|
|
19
|
+
" ╔══════════════════════════════════════════════════════╗",
|
|
20
|
+
" ║ SDTK — All Five Toolkits Installed ║",
|
|
21
|
+
" ╚══════════════════════════════════════════════════════╝",
|
|
22
|
+
"",
|
|
23
|
+
" You now have all five SDTK CLI tools available:",
|
|
24
|
+
"",
|
|
25
|
+
" sdtk-spec — Spec-first SDLC: PM → BA → ARCH → DEV → QA",
|
|
26
|
+
" sdtk-design — MVP design: idea → prototype → handoff",
|
|
27
|
+
" sdtk-code — Governed coding: handoff → PR with review gates",
|
|
28
|
+
" sdtk-ops — Operations: deploy → smoke → sign-off",
|
|
29
|
+
" sdtk-wiki — Local second brain: your project memory",
|
|
30
|
+
"",
|
|
31
|
+
" Set up the whole suite in one command:",
|
|
32
|
+
"",
|
|
33
|
+
" sdtk init --runtime claude (or --runtime codex)",
|
|
34
|
+
"",
|
|
35
|
+
" Then generate your first feature spec:",
|
|
36
|
+
"",
|
|
37
|
+
" sdtk-spec generate --feature-key <YOUR_FEATURE>",
|
|
38
|
+
"",
|
|
39
|
+
" Docs: https://sdtk.dev",
|
|
40
|
+
"",
|
|
41
|
+
];
|
|
42
|
+
|
|
43
|
+
process.stdout.write(lines.join("\n") + "\n");
|