@bitmagic/cli 0.1.61 → 0.1.62-dev.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.
Files changed (85) hide show
  1. package/README.md +27 -3
  2. package/assets/unity-import/README.md +13 -0
  3. package/assets/unity-import/blender_build.py +462 -0
  4. package/assets/unity-import/build_parts.py +263 -0
  5. package/assets/unity-import/convert_assets.py +193 -0
  6. package/assets/unity-import/fbx_ascii.py +156 -0
  7. package/assets/unity-import/fbx_axis.py +174 -0
  8. package/assets/unity-import/fbx_bounds.py +202 -0
  9. package/assets/unity-import/import_config.py +86 -0
  10. package/assets/unity-import/level_patches.example.json +23 -0
  11. package/assets/unity-import/mesh_walls.py +78 -0
  12. package/assets/unity-import/render_topdown.py +33 -0
  13. package/assets/unity-import/unity-import.example.json +27 -0
  14. package/assets/unity-import/unity_assets.py +114 -0
  15. package/assets/unity-import/unity_colliders2d.py +127 -0
  16. package/assets/unity-import/unity_extract.py +774 -0
  17. package/assets/unity-import/unity_markers.py +249 -0
  18. package/assets/unity-import/unity_renderers.py +279 -0
  19. package/assets/unity-import/write_arena_data.py +198 -0
  20. package/dist/cli.d.ts +12 -0
  21. package/dist/commands/check.js +2 -2
  22. package/dist/commands/check.js.map +1 -1
  23. package/dist/commands/dev.js +4 -4
  24. package/dist/commands/dev.js.map +1 -1
  25. package/dist/commands/forge.js +4 -3
  26. package/dist/commands/forge.js.map +1 -1
  27. package/dist/commands/import.d.ts +4 -0
  28. package/dist/commands/import.js +5 -0
  29. package/dist/commands/import.js.map +1 -1
  30. package/dist/commands/init.d.ts +4 -0
  31. package/dist/commands/init.js +20 -0
  32. package/dist/commands/init.js.map +1 -1
  33. package/dist/commands/upgrade.d.ts +4 -0
  34. package/dist/commands/upgrade.js +31 -5
  35. package/dist/commands/upgrade.js.map +1 -1
  36. package/dist/commands/verify.js +5 -4
  37. package/dist/commands/verify.js.map +1 -1
  38. package/dist/editor/server.js +3 -3
  39. package/dist/editor/shell-page.js +16 -1
  40. package/dist/editor/shell-page.js.map +1 -1
  41. package/dist/editor/watch.d.ts +1 -1
  42. package/dist/editor/watch.js +2 -21
  43. package/dist/editor/watch.js.map +1 -1
  44. package/dist/forge/voxelize-session.d.ts +1 -1
  45. package/dist/forge/voxelize-session.js +4 -32
  46. package/dist/forge/voxelize-session.js.map +1 -1
  47. package/dist/project/context.d.ts +14 -1
  48. package/dist/project/context.js +17 -4
  49. package/dist/project/context.js.map +1 -1
  50. package/dist/project/package-manager.js +2 -2
  51. package/dist/project/package-manager.js.map +1 -1
  52. package/dist/project/spawn-bin.d.ts +69 -0
  53. package/dist/project/spawn-bin.js +96 -0
  54. package/dist/project/spawn-bin.js.map +1 -0
  55. package/dist/publish/bundle.js +3 -3
  56. package/dist/publish/bundle.js.map +1 -1
  57. package/dist/scaffold/agent-targets.d.ts +126 -0
  58. package/dist/scaffold/agent-targets.js +180 -0
  59. package/dist/scaffold/agent-targets.js.map +1 -0
  60. package/dist/scaffold/agents-md.d.ts +4 -1
  61. package/dist/scaffold/agents-md.js +6 -2
  62. package/dist/scaffold/agents-md.js.map +1 -1
  63. package/dist/scaffold/project-files.d.ts +40 -5
  64. package/dist/scaffold/project-files.js +67 -25
  65. package/dist/scaffold/project-files.js.map +1 -1
  66. package/dist/scaffold/project.d.ts +42 -15
  67. package/dist/scaffold/project.js +100 -38
  68. package/dist/scaffold/project.js.map +1 -1
  69. package/dist/scaffold/reference-guidance.d.ts +1 -1
  70. package/dist/scaffold/reference-guidance.js +2 -1
  71. package/dist/scaffold/reference-guidance.js.map +1 -1
  72. package/dist/scaffold/scaffold-run.js +2 -2
  73. package/dist/scaffold/scaffold-run.js.map +1 -1
  74. package/dist/scaffold/skill-files.d.ts +32 -9
  75. package/dist/scaffold/skill-files.js +71 -15
  76. package/dist/scaffold/skill-files.js.map +1 -1
  77. package/dist/scaffold/unity-skill-files.d.ts +30 -0
  78. package/dist/scaffold/unity-skill-files.js +474 -0
  79. package/dist/scaffold/unity-skill-files.js.map +1 -0
  80. package/dist/scaffold/upgrade-project.d.ts +31 -11
  81. package/dist/scaffold/upgrade-project.js +35 -23
  82. package/dist/scaffold/upgrade-project.js.map +1 -1
  83. package/dist/verify/iterate.js +2 -1
  84. package/dist/verify/iterate.js.map +1 -1
  85. package/package.json +4 -4
@@ -16,6 +16,15 @@ export interface ProjectMetadata {
16
16
  * documents for `defaultEnvironment`, and the reason this module must not import that table.
17
17
  */
18
18
  environment?: string;
19
+ /**
20
+ * Which agent tools this project is set up for. Absent on projects scaffolded before the field
21
+ * existed, which reads as the always-present set — see scaffold/agent-targets.ts.
22
+ *
23
+ * Typed `string[]` rather than `AgentId[]` for the same reason `environment` is typed `string`:
24
+ * this file is hand-editable, so a narrow type here would be a claim the parser cannot back.
25
+ * `readRecordedAgents` does the narrowing, and reports what it dropped.
26
+ */
27
+ agents?: string[];
19
28
  }
20
29
  export interface ProjectContext {
21
30
  root: string;
@@ -70,5 +79,9 @@ export declare function readProjectGameIdOrNull(startDir?: string): string | und
70
79
  /**
71
80
  * Resolves a tool from the PROJECT's node_modules, never the CLI's. The scaffold pins its own
72
81
  * typescript and vite; running a different copy would type-check against the wrong compiler.
82
+ *
83
+ * Windows gets `<name>.cmd` (or a real `<name>.exe`) rather than the extensionless file, which is
84
+ * a POSIX shell script there and spawns ENOENT. Run whatever this returns through
85
+ * `spawn-bin.ts` — a `.cmd` additionally needs a shell, and that is the one place that knows it.
73
86
  */
74
- export declare function projectBin(root: string, name: string): string;
87
+ export declare function projectBin(root: string, name: string, platform?: string): string;
@@ -20,7 +20,10 @@ const REQUIRED_STRING_FIELDS = [
20
20
  * review found a bare cast let malformed data through unnoticed.
21
21
  */
22
22
  function findMissingField(value) {
23
- return REQUIRED_STRING_FIELDS.find((field) => typeof value[field] !== 'string' || value[field].length === 0);
23
+ return REQUIRED_STRING_FIELDS.find((field) => {
24
+ const entry = value[field];
25
+ return typeof entry !== 'string' || entry.length === 0;
26
+ });
24
27
  }
25
28
  /**
26
29
  * The nearest ancestor of `startDir` (itself included) holding `fileName`, or null at the root.
@@ -141,10 +144,20 @@ export function readProjectGameIdOrNull(startDir = process.cwd()) {
141
144
  /**
142
145
  * Resolves a tool from the PROJECT's node_modules, never the CLI's. The scaffold pins its own
143
146
  * typescript and vite; running a different copy would type-check against the wrong compiler.
147
+ *
148
+ * Windows gets `<name>.cmd` (or a real `<name>.exe`) rather than the extensionless file, which is
149
+ * a POSIX shell script there and spawns ENOENT. Run whatever this returns through
150
+ * `spawn-bin.ts` — a `.cmd` additionally needs a shell, and that is the one place that knows it.
144
151
  */
145
- export function projectBin(root, name) {
146
- const binary = path.join(root, 'node_modules', '.bin', name);
147
- if (!fs.existsSync(binary)) {
152
+ export function projectBin(root, name, platform = process.platform) {
153
+ const dir = path.join(root, 'node_modules', '.bin');
154
+ // Order matters only in the impossible case of both existing; `.cmd` is what every package
155
+ // manager writes for a JS bin, so it is the one to prefer.
156
+ const candidates = platform === 'win32'
157
+ ? [`${name}.cmd`, `${name}.exe`, name]
158
+ : [name];
159
+ const binary = candidates.map((file) => path.join(dir, file)).find((file) => fs.existsSync(file));
160
+ if (binary === undefined) {
148
161
  // Names the project's OWN package manager: telling a pnpm project to run `npm install`
149
162
  // installs the tree under a different linker, and the next build fails on module
150
163
  // resolution instead — a worse failure than the one this message is trying to fix.
@@ -1 +1 @@
1
- {"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/project/context.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/project/context.ts"],"names":[],"mappings":"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"}
@@ -12,9 +12,9 @@
12
12
  * Kept in `project/` rather than inside a command, because both `commands/upgrade.ts` and
13
13
  * `project/context.ts` need it and a command module must not be imported from `project/`.
14
14
  */
15
- import { spawnSync } from 'child_process';
16
15
  import * as fs from 'fs';
17
16
  import * as path from 'path';
17
+ import { spawnPathCommandSync } from './spawn-bin.js';
18
18
  /**
19
19
  * Decide from the project's lockfile. npm is the fallback: it is what ships with Node, so it is
20
20
  * the right guess for a tree with no lockfile at all — one assembled by hand, or one whose
@@ -53,7 +53,7 @@ export function installAllCommand(manager) {
53
53
  return `${manager} install`;
54
54
  }
55
55
  function respondsToVersion(command) {
56
- const result = spawnSync(command, ['--version'], { stdio: 'ignore' });
56
+ const result = spawnPathCommandSync(command, ['--version'], { stdio: 'ignore' });
57
57
  return result.error === undefined && result.status === 0;
58
58
  }
59
59
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"package-manager.js","sourceRoot":"","sources":["../../src/project/package-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAI7B;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,oBAAoB,CAAC,IAAY;IAC/C,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,gBAAgB,CAAC,CAAC;QAAE,OAAO,MAAM,CAAC;IACpE,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;QAAE,OAAO,MAAM,CAAC;IAC/D,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,UAAU,CAAC,OAAuB,EAAE,GAAY,EAAE,KAAe;IAC/E,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC/B,IAAI,OAAO,KAAK,MAAM;QAAE,OAAO,YAAY,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,GAAG,MAAM,EAAE,CAAC;IAC1E,IAAI,OAAO,KAAK,MAAM;QAAE,OAAO,YAAY,GAAG,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,GAAG,MAAM,EAAE,CAAC;IAC/E,OAAO,eAAe,GAAG,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,GAAG,MAAM,EAAE,CAAC;AAC5D,CAAC;AAED,6EAA6E;AAC7E,MAAM,UAAU,iBAAiB,CAAC,OAAuB;IACvD,OAAO,GAAG,OAAO,UAAU,CAAC;AAC9B,CAAC;AAKD,SAAS,iBAAiB,CAAC,OAAe;IACxC,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,EAAE,CAAC,WAAW,CAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;IACtE,OAAO,MAAM,CAAC,KAAK,KAAK,SAAS,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC;AAC3D,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,uBAAuB,CAAC,QAAsB,iBAAiB;IAC7E,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC;AACxC,CAAC"}
1
+ {"version":3,"file":"package-manager.js","sourceRoot":"","sources":["../../src/project/package-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAItD;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,oBAAoB,CAAC,IAAY;IAC/C,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,gBAAgB,CAAC,CAAC;QAAE,OAAO,MAAM,CAAC;IACpE,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;QAAE,OAAO,MAAM,CAAC;IAC/D,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,UAAU,CAAC,OAAuB,EAAE,GAAY,EAAE,KAAe;IAC/E,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC/B,IAAI,OAAO,KAAK,MAAM;QAAE,OAAO,YAAY,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,GAAG,MAAM,EAAE,CAAC;IAC1E,IAAI,OAAO,KAAK,MAAM;QAAE,OAAO,YAAY,GAAG,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,GAAG,MAAM,EAAE,CAAC;IAC/E,OAAO,eAAe,GAAG,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,GAAG,MAAM,EAAE,CAAC;AAC5D,CAAC;AAED,6EAA6E;AAC7E,MAAM,UAAU,iBAAiB,CAAC,OAAuB;IACvD,OAAO,GAAG,OAAO,UAAU,CAAC;AAC9B,CAAC;AAKD,SAAS,iBAAiB,CAAC,OAAe;IACxC,MAAM,MAAM,GAAG,oBAAoB,CAAC,OAAO,EAAE,CAAC,WAAW,CAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;IACjF,OAAO,MAAM,CAAC,KAAK,KAAK,SAAS,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC;AAC3D,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,uBAAuB,CAAC,QAAsB,iBAAiB;IAC7E,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC;AACxC,CAAC"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Running a binary out of the project's `node_modules/.bin` — on Windows as well as POSIX.
3
+ *
4
+ * ── Why this is not just `spawn(bin, args)` ──────────────────────────────────────────────────
5
+ *
6
+ * `node_modules/.bin/tsc` is a POSIX shell script. Windows cannot execute it: every package
7
+ * manager writes a `tsc.cmd` next to it for that platform, and handing the extensionless path to
8
+ * `spawnSync` there fails with ENOENT before tsc is ever reached. `projectBin` picks the right
9
+ * file; this module runs it.
10
+ *
11
+ * Picking the `.cmd` is only half of it. Since the CVE-2024-27980 fix (Node 18.20.2 / 20.12.2),
12
+ * spawning a `.cmd` or `.bat` WITHOUT `shell: true` throws EINVAL — the shell is now mandatory for
13
+ * those, not an alternative to naming them. So on Windows the command and every argument are
14
+ * quoted for `cmd.exe` and the spawn is a shell spawn. `"` needs no escape because Windows forbids
15
+ * it in a path, and our own arguments are flags and paths; a literal `%` in a path can still be
16
+ * eaten by cmd's variable expansion, which has no command-line escape and which no Bitmagic path
17
+ * has ever contained.
18
+ *
19
+ * The shell brings one more consequence, which `stopChild` exists for: the child is `cmd.exe`, and
20
+ * killing it leaves the vite or tsc it launched running — holding `--strictPort` against the next
21
+ * `bitmagic dev`. Windows kills the tree instead.
22
+ *
23
+ * `spawnPathCommandSync` is the same defect one step out: a package manager looked up on PATH is
24
+ * `npm.cmd`/`pnpm.cmd` on Windows, and `spawnSync('pnpm', …)` there fails the same ENOENT way.
25
+ */
26
+ import { spawnSync, type ChildProcess, type SpawnOptions, type SpawnSyncOptions } from 'child_process';
27
+ /** How to hand a `.bin` entry to `child_process` on one platform. */
28
+ export interface BinInvocation {
29
+ command: string;
30
+ args: string[];
31
+ shell: boolean;
32
+ }
33
+ /**
34
+ * Pure, so the Windows shape is testable from any machine — the same split `openerFor` uses.
35
+ *
36
+ * Only `.cmd`/`.bat` take the shell. A `.exe` (some packages ship a real one) and the POSIX
37
+ * extensionless script are executables the OS can launch directly, and routing those through
38
+ * cmd.exe would add the orphaned-child problem for nothing.
39
+ */
40
+ export declare function binInvocation(bin: string, args: readonly string[], platform?: string): BinInvocation;
41
+ /** `spawnSync` for a project binary. Same return value, so callers read `error`/`status` as before. */
42
+ export declare function spawnBinSync(bin: string, args: readonly string[], options: SpawnSyncOptions): ReturnType<typeof spawnSync>;
43
+ /** `spawn` for a project binary. Same `ChildProcess`, but stop it with `stopChild`, not `kill`. */
44
+ export declare function spawnBin(bin: string, args: readonly string[], options: SpawnOptions): ChildProcess;
45
+ /**
46
+ * Stops a child started by `spawnBin`, including anything it started.
47
+ *
48
+ * On Windows that child is the `cmd.exe` wrapper, so `kill` alone would orphan the real server;
49
+ * `taskkill /T` takes the tree.
50
+ *
51
+ * Throws whatever `kill` throws, exactly as the bare `child.kill('SIGTERM')` this replaced did —
52
+ * `killQuietly` in forge/voxelize-session.ts reports that rather than losing the command to it,
53
+ * and swallowing it here would silently take that report away.
54
+ */
55
+ export declare function stopChild(child: ChildProcess, platform?: string): void;
56
+ /**
57
+ * Runs a command looked up on PATH — a package manager, not a project binary.
58
+ *
59
+ * On Windows `npm`, `pnpm` and `yarn` are all `.cmd` shims, and `CreateProcess` (which is what a
60
+ * non-shell spawn ends at) cannot execute a batch file however it was named. cmd.exe resolves the
61
+ * PATHEXT extension itself, so the shell does double duty here: it finds the shim AND it is the
62
+ * `shell: true` the batch file needs anyway.
63
+ *
64
+ * An absolute path is spawned directly. `self-install.ts` runs npm as `process.execPath
65
+ * npm-cli.js` — a real executable with nothing for a shell to add.
66
+ */
67
+ export declare function pathCommandInvocation(command: string, args: readonly string[], platform?: string): BinInvocation;
68
+ /** `spawnSync` for a PATH command. Same return value, so callers read `error`/`status` as before. */
69
+ export declare function spawnPathCommandSync(command: string, args: readonly string[], options: SpawnSyncOptions): ReturnType<typeof spawnSync>;
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Running a binary out of the project's `node_modules/.bin` — on Windows as well as POSIX.
3
+ *
4
+ * ── Why this is not just `spawn(bin, args)` ──────────────────────────────────────────────────
5
+ *
6
+ * `node_modules/.bin/tsc` is a POSIX shell script. Windows cannot execute it: every package
7
+ * manager writes a `tsc.cmd` next to it for that platform, and handing the extensionless path to
8
+ * `spawnSync` there fails with ENOENT before tsc is ever reached. `projectBin` picks the right
9
+ * file; this module runs it.
10
+ *
11
+ * Picking the `.cmd` is only half of it. Since the CVE-2024-27980 fix (Node 18.20.2 / 20.12.2),
12
+ * spawning a `.cmd` or `.bat` WITHOUT `shell: true` throws EINVAL — the shell is now mandatory for
13
+ * those, not an alternative to naming them. So on Windows the command and every argument are
14
+ * quoted for `cmd.exe` and the spawn is a shell spawn. `"` needs no escape because Windows forbids
15
+ * it in a path, and our own arguments are flags and paths; a literal `%` in a path can still be
16
+ * eaten by cmd's variable expansion, which has no command-line escape and which no Bitmagic path
17
+ * has ever contained.
18
+ *
19
+ * The shell brings one more consequence, which `stopChild` exists for: the child is `cmd.exe`, and
20
+ * killing it leaves the vite or tsc it launched running — holding `--strictPort` against the next
21
+ * `bitmagic dev`. Windows kills the tree instead.
22
+ *
23
+ * `spawnPathCommandSync` is the same defect one step out: a package manager looked up on PATH is
24
+ * `npm.cmd`/`pnpm.cmd` on Windows, and `spawnSync('pnpm', …)` there fails the same ENOENT way.
25
+ */
26
+ import { spawn, spawnSync } from 'child_process';
27
+ /** cmd.exe treats everything inside double quotes literally, and a path can never contain one. */
28
+ function quoteForCmd(value) {
29
+ return `"${value}"`;
30
+ }
31
+ /**
32
+ * Pure, so the Windows shape is testable from any machine — the same split `openerFor` uses.
33
+ *
34
+ * Only `.cmd`/`.bat` take the shell. A `.exe` (some packages ship a real one) and the POSIX
35
+ * extensionless script are executables the OS can launch directly, and routing those through
36
+ * cmd.exe would add the orphaned-child problem for nothing.
37
+ */
38
+ export function binInvocation(bin, args, platform = process.platform) {
39
+ const isBatch = /\.(cmd|bat)$/i.test(bin);
40
+ if (platform !== 'win32' || !isBatch)
41
+ return { command: bin, args: [...args], shell: false };
42
+ return { command: quoteForCmd(bin), args: args.map(quoteForCmd), shell: true };
43
+ }
44
+ /** `spawnSync` for a project binary. Same return value, so callers read `error`/`status` as before. */
45
+ export function spawnBinSync(bin, args, options) {
46
+ const invocation = binInvocation(bin, args);
47
+ return spawnSync(invocation.command, invocation.args, { ...options, shell: invocation.shell });
48
+ }
49
+ /** `spawn` for a project binary. Same `ChildProcess`, but stop it with `stopChild`, not `kill`. */
50
+ export function spawnBin(bin, args, options) {
51
+ const invocation = binInvocation(bin, args);
52
+ return spawn(invocation.command, invocation.args, { ...options, shell: invocation.shell });
53
+ }
54
+ /**
55
+ * Stops a child started by `spawnBin`, including anything it started.
56
+ *
57
+ * On Windows that child is the `cmd.exe` wrapper, so `kill` alone would orphan the real server;
58
+ * `taskkill /T` takes the tree.
59
+ *
60
+ * Throws whatever `kill` throws, exactly as the bare `child.kill('SIGTERM')` this replaced did —
61
+ * `killQuietly` in forge/voxelize-session.ts reports that rather than losing the command to it,
62
+ * and swallowing it here would silently take that report away.
63
+ */
64
+ export function stopChild(child, platform = process.platform) {
65
+ if (platform === 'win32' && typeof child.pid === 'number') {
66
+ const killed = spawnSync('taskkill', ['/pid', String(child.pid), '/T', '/F'], { stdio: 'ignore' });
67
+ // Only fall through to `kill` when taskkill itself could not run (missing, or the pid was
68
+ // already reaped). A successful taskkill has nothing left to signal.
69
+ if (!killed.error && killed.status === 0)
70
+ return;
71
+ }
72
+ child.kill('SIGTERM');
73
+ }
74
+ /**
75
+ * Runs a command looked up on PATH — a package manager, not a project binary.
76
+ *
77
+ * On Windows `npm`, `pnpm` and `yarn` are all `.cmd` shims, and `CreateProcess` (which is what a
78
+ * non-shell spawn ends at) cannot execute a batch file however it was named. cmd.exe resolves the
79
+ * PATHEXT extension itself, so the shell does double duty here: it finds the shim AND it is the
80
+ * `shell: true` the batch file needs anyway.
81
+ *
82
+ * An absolute path is spawned directly. `self-install.ts` runs npm as `process.execPath
83
+ * npm-cli.js` — a real executable with nothing for a shell to add.
84
+ */
85
+ export function pathCommandInvocation(command, args, platform = process.platform) {
86
+ const bare = !command.includes('/') && !command.includes('\\');
87
+ if (platform !== 'win32' || !bare)
88
+ return { command, args: [...args], shell: false };
89
+ return { command: quoteForCmd(command), args: args.map(quoteForCmd), shell: true };
90
+ }
91
+ /** `spawnSync` for a PATH command. Same return value, so callers read `error`/`status` as before. */
92
+ export function spawnPathCommandSync(command, args, options) {
93
+ const invocation = pathCommandInvocation(command, args);
94
+ return spawnSync(invocation.command, invocation.args, { ...options, shell: invocation.shell });
95
+ }
96
+ //# sourceMappingURL=spawn-bin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spawn-bin.js","sourceRoot":"","sources":["../../src/project/spawn-bin.ts"],"names":[],"mappings":"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"}
@@ -1,9 +1,9 @@
1
1
  import { createHash } from 'crypto';
2
- import { spawnSync } from 'child_process';
3
2
  import * as fs from 'fs';
4
3
  import * as path from 'path';
5
4
  import { CliError } from '../errors.js';
6
5
  import { projectBin } from '../project/context.js';
6
+ import { spawnBinSync } from '../project/spawn-bin.js';
7
7
  import { computeFingerprint } from './fingerprint.js';
8
8
  /**
9
9
  * The configs the scaffold vendors alongside `engine/`, one per bundle mode.
@@ -82,7 +82,7 @@ export function runBuild(root, engineVersion, options = {}) {
82
82
  'vendor it (your game code is not touched), then build again.', 1);
83
83
  }
84
84
  const tsc = projectBin(root, 'tsc');
85
- const compile = spawnSync(tsc, [], { cwd: root, stdio: 'inherit' });
85
+ const compile = spawnBinSync(tsc, [], { cwd: root, stdio: 'inherit' });
86
86
  if (compile.error)
87
87
  throw new CliError(`Could not run the TypeScript compiler: ${compile.error.message}`, 1);
88
88
  if (compile.status !== 0)
@@ -90,7 +90,7 @@ export function runBuild(root, engineVersion, options = {}) {
90
90
  const { dir, htmlPath } = buildBundlePaths(root);
91
91
  fs.mkdirSync(dir, { recursive: true });
92
92
  const vite = projectBin(root, 'vite');
93
- const bundle = spawnSync(vite, ['build', '--config', configFile, '--outDir', dir, '--emptyOutDir'], {
93
+ const bundle = spawnBinSync(vite, ['build', '--config', configFile, '--outDir', dir, '--emptyOutDir'], {
94
94
  cwd: root,
95
95
  stdio: 'inherit',
96
96
  });
@@ -1 +1 @@
1
- {"version":3,"file":"bundle.js","sourceRoot":"","sources":["../../src/publish/bundle.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"bundle.js","sourceRoot":"","sources":["../../src/publish/bundle.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,126 @@
1
+ /**
2
+ * Which agent tools a project is set up for, and where each one looks for its skills.
3
+ *
4
+ * The GDK is a bring-your-own-agent product, but for most of its life the scaffold wrote to
5
+ * `.claude/skills/` and nothing else — so a creator on Cursor, Codex or Kiro received a directory of
6
+ * skill files their agent never opened, and `bitmagic upgrade`, the only route by which an existing
7
+ * project learns about a new CLI capability, kept refreshing files nobody read.
8
+ *
9
+ * ── Why `.agents/skills/` is unconditional ───────────────────────────────────────────────────────
10
+ *
11
+ * Cursor, Codex, GitHub Copilot, Cline and OpenCode all load `.agents/skills/` by themselves, and
12
+ * all of them read the root `AGENTS.md` this scaffold already writes. So writing that one directory
13
+ * into every project supports five agents with no flag to pass and no environment to sniff — which
14
+ * is the whole point, because neither of the alternatives survives contact:
15
+ *
16
+ * - Detection cannot be built honestly. `../telemetry/command-context.ts` states the policy —
17
+ * an agent gets a marker here only once that marker is verified against the real thing, because
18
+ * a guessed variable never fires and misleads whoever reads the table next — and `CLAUDECODE` is
19
+ * the only marker anyone has verified. An `init` run by Cursor's agent proves nothing, so
20
+ * detection-as-default would silently produce a Cursor-less project.
21
+ * - A required flag cannot be relied on either. The GDK bootstrap that runs `bitmagic init` is
22
+ * read BY the agent, so it could pass its own id — but nothing upgrades an installed copy of
23
+ * that bootstrap (see `agent-plugin/README.md`), so a creator on last month's copy would get
24
+ * nothing, and the failure is silent.
25
+ *
26
+ * What is left for this table is therefore narrow: agents that read a VENDOR directory and nothing
27
+ * else. Claude Code (`.claude/skills/`) is one, and it is unconditional too — every project on disk
28
+ * today has that directory, and an upgrade that stopped writing it would be the first destructive
29
+ * thing the command has ever done. Kiro (`.kiro/skills/`) is the other, and it is the only reason
30
+ * `--agent` exists: an unasked-for `.kiro/` is pure noise in a project that does not use Kiro.
31
+ *
32
+ * ── Why the directory, not the agent, is the unit ────────────────────────────────────────────────
33
+ *
34
+ * Four agents map onto three directories, so every caller works in terms of the deduped set of
35
+ * DIRECTORIES (`skillDirsFor`). Writing per agent instead would put the same files into
36
+ * `.agents/skills/` twice for a creator who named both Cursor and Codex.
37
+ */
38
+ export type AgentId = 'claude-code' | 'cursor' | 'codex' | 'kiro';
39
+ export interface AgentTarget {
40
+ id: AgentId;
41
+ /** How the agent is named in output a creator reads. */
42
+ label: string;
43
+ /**
44
+ * The agent's own skills directory, or absent when it reads `SHARED_SKILLS_DIR` itself — in which
45
+ * case there is nothing to write for it and `--agent <id>` is a no-op we report rather than
46
+ * refuse. Relative to the project root, POSIX-separated.
47
+ */
48
+ skillsDir?: string;
49
+ /** Where this agent reads its startup instructions. Output copy only; nothing branches on it. */
50
+ instructions: string;
51
+ }
52
+ /**
53
+ * The directory every agent following the AGENTS.md / agent-skills convention reads by itself.
54
+ * Written into every project whatever agent scaffolded it — see the file header.
55
+ */
56
+ export declare const SHARED_SKILLS_DIR = ".agents/skills";
57
+ /**
58
+ * Declaration order is output order, so the file set a project receives is a function of WHICH
59
+ * agents were selected and not of how they were typed.
60
+ */
61
+ export declare const AGENT_TARGETS: readonly AgentTarget[];
62
+ export declare const AGENT_IDS: readonly AgentId[];
63
+ /**
64
+ * In every project's set, and not removable.
65
+ *
66
+ * `--agent` adds; it never takes away. Both of the unconditional directories are already on disk in
67
+ * every existing project (`.claude/skills/`) or are what makes five agents work for free
68
+ * (`.agents/skills/`), and `upgrade` has never deleted a file under a skills directory.
69
+ */
70
+ export declare const ALWAYS_AGENTS: readonly AgentId[];
71
+ /**
72
+ * `--agent`'s help text, shared by `init` and `upgrade` so the two cannot describe the same flag
73
+ * differently. It names what the flag is FOR, because the honest answer is "usually nothing": the
74
+ * default already covers every agent but Kiro.
75
+ */
76
+ export declare const AGENT_FLAG_DESCRIPTION: string;
77
+ export declare function isAgentId(value: unknown): value is AgentId;
78
+ export declare function agentTarget(id: AgentId): AgentTarget;
79
+ /** In table order, each agent once. */
80
+ export declare function dedupeAgents(agents: readonly AgentId[]): AgentId[];
81
+ /**
82
+ * "Cursor", "Cursor and Codex", "Cursor, Codex and Kiro" — for a sentence a creator reads, not a
83
+ * list a parser does. Exported because the scaffolded AGENTS.md joins its skills directories the
84
+ * same way, and two hand-written copies of this join is how the two come to punctuate differently.
85
+ */
86
+ export declare function joinWithAnd(items: readonly string[]): string;
87
+ /** The agents named, in table order, as a clause for a sentence a creator reads. */
88
+ export declare function agentLabels(agents: readonly AgentId[]): string;
89
+ /**
90
+ * `--agent kiro,cursor` → `['cursor', 'kiro']`, unioned with the always-present set.
91
+ *
92
+ * Comma-separated rather than a repeatable flag because citty's string args are single-valued. An
93
+ * unknown id is a hard error naming the valid ones: a typo that silently scaffolded the default set
94
+ * would look like the flag working, and the creator would find out when their agent loaded nothing.
95
+ */
96
+ export declare function parseAgentFlag(raw: string | undefined): AgentId[];
97
+ /** The `agents` field of a `bitmagic.json`, keeping only ids this CLI recognises. */
98
+ export declare function readRecordedAgents(value: unknown): AgentId[];
99
+ /** Values in a project's `agents` field that this CLI does not recognise — reported, never fatal. */
100
+ export declare function unrecognisedAgents(value: unknown): string[];
101
+ /**
102
+ * The directories to write, deduped and in a stable order, always starting with the shared one.
103
+ *
104
+ * A duplicate here would double-write a file and list its path twice in `UpgradeResult.replaced`,
105
+ * so the dedupe is load-bearing rather than tidiness: `--agent cursor,codex` names two agents that
106
+ * share a directory.
107
+ */
108
+ export declare function skillDirsFor(agents: readonly AgentId[]): string[];
109
+ /**
110
+ * The directory `AGENTS.md` names when it cross-references a skill.
111
+ *
112
+ * Every project has more than one copy of the shipped skills, but `AGENTS.md` is ONE file at the
113
+ * root read by every agent in the project, so it has to name a single path — and the only honest
114
+ * choice is the one that exists in every project and that most agents load from. Its Layout section
115
+ * names the other copies, so a Claude Code reader still learns where its own loader looks.
116
+ */
117
+ export declare const PRIMARY_SKILLS_DIR = ".agents/skills";
118
+ /**
119
+ * The agents named by `--agent` that this scaffold writes nothing extra for, because the directory
120
+ * and the instructions file they read are already unconditional.
121
+ *
122
+ * Accepting such a flag and explaining it beats refusing one a creator reasonably typed.
123
+ */
124
+ export declare function noOpAgents(agents: readonly AgentId[]): AgentId[];
125
+ /** Which agents load a given skills directory, as a clause for a sentence the creator reads. */
126
+ export declare function describeSkillsDir(dir: string): string;