sdtk-kit 1.3.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/README.md CHANGED
@@ -34,22 +34,34 @@ sdtk-spec generate --feature-key MY_FEATURE
34
34
  each toolkit's own, already-shipped `init` in order:
35
35
 
36
36
  ```
37
- sdtk-spec → sdtk-ops → sdtk-code (with --runtime <r>)
38
- sdtk-design → sdtk-wiki (their own non-runtime init)
37
+ sdtk-spec → sdtk-ops → sdtk-code → sdtk-design (with --runtime <r>)
38
+ sdtk-wiki (its own non-runtime init)
39
39
  ```
40
40
 
41
41
  ```bash
42
42
  sdtk init --runtime claude
43
43
  sdtk init --runtime codex --project-path ./my-app
44
+ sdtk init --runtime claude --global # install skills to the user/global home
44
45
  sdtk init --runtime claude --keep-going # continue past a failing toolkit
45
46
  ```
46
47
 
47
- Options: `--runtime <claude|codex>` (required), `--runtime-scope <scope>`,
48
- `--project-path <path>`, `--force`, `--skip-runtime-assets`, `--keep-going`
49
- (default is fail-fast — stop at the first failing toolkit), `--verbose`.
50
- `--runtime`, `--runtime-scope`, and `--skip-runtime-assets` apply to the runtime
51
- toolkits (spec/ops/code); `sdtk-design` and `sdtk-wiki` receive only
52
- `--project-path`, `--force`, and `--verbose`.
48
+ Options: `--runtime <claude|codex>` (required), `--runtime-scope <project|user>`,
49
+ `--global` (shorthand for `--runtime-scope user`), `--project-path <path>`,
50
+ `--force`, `--skip-runtime-assets`, `--keep-going` (default is fail-fast — stop
51
+ at the first failing toolkit), `--verbose`.
52
+
53
+ `--runtime`, `--runtime-scope`, and `--global` apply to the runtime-aware
54
+ toolkits (spec/ops/code **and** sdtk-design), so each places its skills under the
55
+ matching runtime home: `.claude/skills` for claude, `.codex/skills` for codex
56
+ (and `~/.claude/skills` / `~/.codex/skills` for `--global`). `--skip-runtime-assets`
57
+ applies only to spec/ops/code (which own the PowerShell runtime-asset payload).
58
+ `sdtk-wiki` installs no skills and receives only `--project-path`, `--force`,
59
+ and `--verbose`.
60
+
61
+ > Note: claude defaults to **project** scope (`.claude/skills`); codex defaults
62
+ > to **user/global** scope (`~/.codex/skills`), since Codex discovers skills via
63
+ > `CODEX_HOME`. Pass `--runtime-scope project` with codex to get a project-local
64
+ > `.codex/skills` (then launch Codex with `CODEX_HOME=<project>/.codex`).
53
65
 
54
66
  `sdtk init` is a thin orchestrator: it re-implements no init logic, writes no files
55
67
  itself, and runs no PowerShell of its own — every side effect happens inside the
@@ -106,14 +118,14 @@ are the mechanism that puts `sdtk`, `sdtk-spec`, `sdtk-code`, `sdtk-ops`,
106
118
  - **Major version bumps** in any sub-toolkit require a coordinated `sdtk-kit` major-bump and re-publish.
107
119
  - If you need exact version control per toolkit, use standalone packages instead.
108
120
 
109
- Current dependency ranges (as of sdtk-kit v1.3.0):
121
+ Current dependency ranges (as of sdtk-kit v1.3.1):
110
122
 
111
123
  | Package | Version |
112
124
  |------------------|---------|
113
125
  | sdtk-spec-kit | ^0.4.7 |
114
126
  | sdtk-code-kit | ^0.3.0 |
115
127
  | sdtk-ops-kit | ^0.2.4 |
116
- | sdtk-design-kit | ^0.3.0 |
128
+ | sdtk-design-kit | ^0.3.2 |
117
129
  | sdtk-wiki-kit | ^0.2.0 |
118
130
 
119
131
  ## Updating
package/bin/sdtk.js CHANGED
@@ -28,16 +28,25 @@ function helpText() {
28
28
  " sdtk --version Show versions",
29
29
  "",
30
30
  "init options:",
31
- " --runtime <claude|codex> Required. Runtime to install for spec/ops/code.",
32
- " --runtime-scope <scope> Optional. Forwarded to the runtime toolkits.",
31
+ " --runtime <claude|codex> Required. Runtime for the runtime-aware kits",
32
+ " (spec/ops/code and design place skills under",
33
+ " .claude/skills or .codex/skills accordingly).",
34
+ " --runtime-scope <project|user> Optional. project = repo-local skills dir;",
35
+ " user = global home. Default: claude→project,",
36
+ " codex→user (Codex discovers skills via CODEX_HOME).",
37
+ " --global Shorthand for --runtime-scope user (~/.claude or",
38
+ " ~/.codex). Applies to both runtimes.",
33
39
  " --project-path <path> Optional. Target project directory.",
34
40
  " --force Re-initialise existing assets.",
35
- " --skip-runtime-assets Skip runtime asset install (runtime toolkits).",
41
+ " --skip-runtime-assets Skip PowerShell runtime asset install (spec/ops/code).",
36
42
  " --keep-going Continue past a failing toolkit (default: fail-fast).",
37
43
  " --verbose Verbose per-toolkit output.",
38
44
  "",
39
- "Runs: sdtk-spec → sdtk-ops → sdtk-code (with --runtime) → sdtk-design sdtk-wiki",
40
- "(sdtk-design and sdtk-wiki run their own non-runtime init).",
45
+ "Runs: sdtk-spec → sdtk-ops → sdtk-code → sdtk-design (all with --runtime)",
46
+ " sdtk-wiki (its own non-runtime init; installs no skills).",
47
+ "",
48
+ "Note: for a project-local .codex with codex, pass --runtime-scope project and",
49
+ "launch Codex with CODEX_HOME=<project>/.codex (no native .codex auto-discovery).",
41
50
  "",
42
51
  "Standalone per-toolkit CLIs remain available: sdtk-spec, sdtk-ops, sdtk-code,",
43
52
  "sdtk-design, sdtk-wiki.",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sdtk-kit",
3
- "version": "1.3.0",
3
+ "version": "1.3.1",
4
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
5
  "type": "commonjs",
6
6
  "bin": {
@@ -29,7 +29,7 @@
29
29
  "sdtk-spec-kit": "^0.4.7",
30
30
  "sdtk-code-kit": "^0.3.0",
31
31
  "sdtk-ops-kit": "^0.2.4",
32
- "sdtk-design-kit": "^0.3.0",
32
+ "sdtk-design-kit": "^0.3.2",
33
33
  "sdtk-wiki-kit": "^0.2.0"
34
34
  },
35
35
  "engines": {
@@ -12,9 +12,14 @@ const {
12
12
  TOOLKITS,
13
13
  ToolkitResolveError,
14
14
  } = require("../src/lib/unified-init");
15
+ const { parseFlags, buildOpts } = require("../src/commands/init");
15
16
 
16
- const RUNTIME_KITS = ["sdtk-spec", "sdtk-ops", "sdtk-code"];
17
- const NON_RUNTIME_KITS = ["sdtk-design", "sdtk-wiki"];
17
+ // spec/ops/code own the PowerShell runtime-asset payload (install.ps1) and so
18
+ // also accept --skip-runtime-assets. sdtk-design is runtime-aware (places the
19
+ // design-prototype skill under .claude/.codex) but does NOT take that flag.
20
+ const ASSET_KITS = ["sdtk-spec", "sdtk-ops", "sdtk-code"];
21
+ const RUNTIME_KITS = ["sdtk-spec", "sdtk-ops", "sdtk-code", "sdtk-design"];
22
+ const NON_RUNTIME_KITS = ["sdtk-wiki"];
18
23
 
19
24
  // Build an injected deps object with a recording spawn spy.
20
25
  // `failures` maps toolkit name → exit code to return (default 0).
@@ -95,7 +100,7 @@ test("T3 forwards shared flags to runtime kits; only subset to design/wiki", ()
95
100
  };
96
101
  runUnifiedInit(opts, h.deps);
97
102
 
98
- for (const kit of RUNTIME_KITS) {
103
+ for (const kit of ASSET_KITS) {
99
104
  const argv = argvFor(h.spawnCalls, kit);
100
105
  assert.deepStrictEqual(
101
106
  argv,
@@ -114,6 +119,27 @@ test("T3 forwards shared flags to runtime kits; only subset to design/wiki", ()
114
119
  `${kit} full forward`
115
120
  );
116
121
  }
122
+ // design is runtime-aware (gets --runtime/--runtime-scope) but owns no
123
+ // PowerShell payload, so it must NOT receive --skip-runtime-assets.
124
+ {
125
+ const argv = argvFor(h.spawnCalls, "sdtk-design");
126
+ assert.deepStrictEqual(
127
+ argv,
128
+ [
129
+ "init",
130
+ "--runtime",
131
+ "claude",
132
+ "--runtime-scope",
133
+ "user",
134
+ "--project-path",
135
+ "/tmp/proj",
136
+ "--force",
137
+ "--verbose",
138
+ ],
139
+ "sdtk-design runtime-aware forward (no --skip-runtime-assets)"
140
+ );
141
+ assert.ok(!argv.includes("--skip-runtime-assets"), "design must not get --skip-runtime-assets");
142
+ }
117
143
  for (const kit of NON_RUNTIME_KITS) {
118
144
  const argv = argvFor(h.spawnCalls, kit);
119
145
  assert.deepStrictEqual(
@@ -223,6 +249,30 @@ test("T10 orchestrator uses only injected deps (no real host access)", () => {
223
249
  assert.deepStrictEqual(a, b);
224
250
  });
225
251
 
252
+ // ── T11 — --global shorthand maps to runtime-scope user ─────────────────────
253
+ test("T11 --global parses and maps to runtimeScope=user", () => {
254
+ const flags = parseFlags(["--runtime", "claude", "--global"]);
255
+ assert.strictEqual(flags.global, true);
256
+ const opts = buildOpts(flags);
257
+ assert.strictEqual(opts.runtimeScope, "user");
258
+ });
259
+ test("T11b explicit --runtime-scope wins over --global", () => {
260
+ const opts = buildOpts(parseFlags(["--runtime", "codex", "--global", "--runtime-scope", "project"]));
261
+ assert.strictEqual(opts.runtimeScope, "project");
262
+ });
263
+ test("T11c no scope flag leaves runtimeScope undefined (kits apply their default)", () => {
264
+ const opts = buildOpts(parseFlags(["--runtime", "codex"]));
265
+ assert.strictEqual(opts.runtimeScope, undefined);
266
+ });
267
+ test("T11d --global forwards --runtime-scope user to design (runtime-aware)", () => {
268
+ const h = makeDeps();
269
+ runUnifiedInit(buildOpts(parseFlags(["--runtime", "claude", "--global"])), h.deps);
270
+ assert.deepStrictEqual(
271
+ argvFor(h.spawnCalls, "sdtk-design"),
272
+ ["init", "--runtime", "claude", "--runtime-scope", "user"]
273
+ );
274
+ });
275
+
226
276
  // ── runner ──────────────────────────────────────────────────────────────────
227
277
  let passed = 0;
228
278
  let failed = 0;
@@ -16,6 +16,7 @@ const {
16
16
  const FLAG_DEFS = Object.freeze({
17
17
  runtime: "string",
18
18
  "runtime-scope": "string",
19
+ global: "boolean",
19
20
  "project-path": "string",
20
21
  force: "boolean",
21
22
  "skip-runtime-assets": "boolean",
@@ -57,6 +58,23 @@ function parseFlags(args) {
57
58
  return flags;
58
59
  }
59
60
 
61
+ // Pure flags → orchestrator opts mapping (exported for unit testing).
62
+ // --global is a shorthand for --runtime-scope user (installs skills under the
63
+ // user/global runtime home: ~/.claude/skills or ~/.codex/skills). An explicit
64
+ // --runtime-scope wins if both are supplied.
65
+ function buildOpts(flags) {
66
+ const runtimeScope = flags["runtime-scope"] || (flags.global ? "user" : undefined);
67
+ return {
68
+ runtime: flags.runtime,
69
+ runtimeScope,
70
+ projectPath: flags["project-path"],
71
+ force: Boolean(flags.force),
72
+ skipRuntimeAssets: Boolean(flags["skip-runtime-assets"]),
73
+ keepGoing: Boolean(flags["keep-going"]),
74
+ verbose: Boolean(flags.verbose),
75
+ };
76
+ }
77
+
60
78
  function cmdInit(args) {
61
79
  let flags;
62
80
  try {
@@ -66,15 +84,7 @@ function cmdInit(args) {
66
84
  return 2;
67
85
  }
68
86
 
69
- const opts = {
70
- runtime: flags.runtime,
71
- runtimeScope: flags["runtime-scope"],
72
- projectPath: flags["project-path"],
73
- force: Boolean(flags.force),
74
- skipRuntimeAssets: Boolean(flags["skip-runtime-assets"]),
75
- keepGoing: Boolean(flags["keep-going"]),
76
- verbose: Boolean(flags.verbose),
77
- };
87
+ const opts = buildOpts(flags);
78
88
 
79
89
  const deps = {
80
90
  spawn(binPath, argv) {
@@ -92,4 +102,5 @@ function cmdInit(args) {
92
102
  module.exports = {
93
103
  cmdInit,
94
104
  parseFlags,
105
+ buildOpts,
95
106
  };
@@ -18,14 +18,20 @@ const VALID_RUNTIMES = Object.freeze(["claude", "codex"]);
18
18
  // Ordered target registry. `binName` is the bin key in each kit's package.json
19
19
  // (resolved through its `bin` map at runtime, so a kit renaming its bin file
20
20
  // across a minor version does not break us — see R1 in the implementation plan).
21
- // `acceptsRuntime: false` toolkits run their own non-runtime init and receive
22
- // only the flags they accept (--project-path / --force / --verbose).
21
+ //
22
+ // `acceptsRuntime` toolkits receive --runtime (+ --runtime-scope) so they place
23
+ // their skills under the correct runtime home (.claude vs .codex). Of those,
24
+ // only `installsRuntimeAssets` toolkits (spec/ops/code, which run install.ps1)
25
+ // also accept --skip-runtime-assets. sdtk-design is runtime-aware (it installs
26
+ // the design-prototype skill into the matching skills dir) but does not own the
27
+ // PowerShell runtime-asset payload. sdtk-wiki is not runtime-aware (it installs
28
+ // no skills) and receives only --project-path / --force / --verbose.
23
29
  const TOOLKITS = Object.freeze([
24
- { name: "sdtk-spec", kitPkg: "sdtk-spec-kit", binName: "sdtk-spec", acceptsRuntime: true },
25
- { name: "sdtk-ops", kitPkg: "sdtk-ops-kit", binName: "sdtk-ops", acceptsRuntime: true },
26
- { name: "sdtk-code", kitPkg: "sdtk-code-kit", binName: "sdtk-code", acceptsRuntime: true },
27
- { name: "sdtk-design", kitPkg: "sdtk-design-kit", binName: "sdtk-design", acceptsRuntime: false },
28
- { name: "sdtk-wiki", kitPkg: "sdtk-wiki-kit", binName: "sdtk-wiki", acceptsRuntime: false },
30
+ { name: "sdtk-spec", kitPkg: "sdtk-spec-kit", binName: "sdtk-spec", acceptsRuntime: true, installsRuntimeAssets: true },
31
+ { name: "sdtk-ops", kitPkg: "sdtk-ops-kit", binName: "sdtk-ops", acceptsRuntime: true, installsRuntimeAssets: true },
32
+ { name: "sdtk-code", kitPkg: "sdtk-code-kit", binName: "sdtk-code", acceptsRuntime: true, installsRuntimeAssets: true },
33
+ { name: "sdtk-design", kitPkg: "sdtk-design-kit", binName: "sdtk-design", acceptsRuntime: true, installsRuntimeAssets: false },
34
+ { name: "sdtk-wiki", kitPkg: "sdtk-wiki-kit", binName: "sdtk-wiki", acceptsRuntime: false, installsRuntimeAssets: false },
29
35
  ]);
30
36
 
31
37
  // Mirrors sdtk-{spec,ops,code} scope.js: claude defaults to project, codex to user.
@@ -107,7 +113,7 @@ function buildInitArgs(toolkit, opts) {
107
113
  if (opts.force) {
108
114
  args.push("--force");
109
115
  }
110
- if (toolkit.acceptsRuntime && opts.skipRuntimeAssets) {
116
+ if (toolkit.installsRuntimeAssets && opts.skipRuntimeAssets) {
111
117
  args.push("--skip-runtime-assets");
112
118
  }
113
119
  if (opts.verbose) {