@bitmagic/cli 0.1.25 → 0.1.27

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 (36) hide show
  1. package/README.md +22 -0
  2. package/dist/commands/dev.js +4 -0
  3. package/dist/commands/dev.js.map +1 -1
  4. package/dist/commands/forge.js +32 -21
  5. package/dist/commands/forge.js.map +1 -1
  6. package/dist/commands/generate.js +117 -56
  7. package/dist/commands/generate.js.map +1 -1
  8. package/dist/commands/upgrade.js +7 -0
  9. package/dist/commands/upgrade.js.map +1 -1
  10. package/dist/editor/previews.d.ts +23 -0
  11. package/dist/editor/previews.js +108 -0
  12. package/dist/editor/previews.js.map +1 -0
  13. package/dist/editor/server.js +111 -3
  14. package/dist/editor/server.js.map +1 -1
  15. package/dist/editor/shell-page.js +406 -5
  16. package/dist/editor/shell-page.js.map +1 -1
  17. package/dist/project/jobs.d.ts +67 -0
  18. package/dist/project/jobs.js +295 -0
  19. package/dist/project/jobs.js.map +1 -0
  20. package/dist/publish/fingerprint.js +8 -1
  21. package/dist/publish/fingerprint.js.map +1 -1
  22. package/dist/scaffold/claude-settings.d.ts +7 -1
  23. package/dist/scaffold/claude-settings.js +34 -2
  24. package/dist/scaffold/claude-settings.js.map +1 -1
  25. package/dist/scaffold/engine-download.d.ts +10 -5
  26. package/dist/scaffold/engine-download.js +14 -8
  27. package/dist/scaffold/engine-download.js.map +1 -1
  28. package/dist/scaffold/project-files.d.ts +27 -0
  29. package/dist/scaffold/project-files.js +444 -8
  30. package/dist/scaffold/project-files.js.map +1 -1
  31. package/dist/scaffold/project.d.ts +17 -0
  32. package/dist/scaffold/project.js +26 -2
  33. package/dist/scaffold/project.js.map +1 -1
  34. package/dist/scaffold/upgrade-project.js +9 -1
  35. package/dist/scaffold/upgrade-project.js.map +1 -1
  36. package/package.json +1 -1
@@ -0,0 +1,295 @@
1
+ /**
2
+ * `.bitmagic/jobs/` — what a running `bitmagic dev` can see of generations it did not start.
3
+ *
4
+ * Every `bitmagic generate`, `forge` and `cover` writes `world.json` exactly once, at the very end,
5
+ * and writes nothing anywhere else while it runs. A `generate skybox` that takes four minutes
6
+ * leaves zero on-disk trace for those four minutes. Since each of those commands is its own
7
+ * process, a `bitmagic dev` in the next window has nothing to read and nothing to show — which is
8
+ * precisely the stretch of time the creator most wants to watch.
9
+ *
10
+ * So each generation announces itself here: one file per job, written on start, updated as its
11
+ * progress lines land, removed when it succeeds.
12
+ *
13
+ * ── Why a file rather than a message to the dev server ───────────────────────────────────────
14
+ *
15
+ * A loopback POST (the trick `bitmagic reload` uses via `dev-handle.ts`) would be lower latency,
16
+ * but it only works when `dev` happened to be running at the moment the generation started, and it
17
+ * survives neither a `dev` restart nor a `dev` opened halfway through a twenty-minute forge. A file
18
+ * is readable by whoever turns up whenever they turn up — including the creator's agent, which can
19
+ * `cat` this directory to see what it has in flight. The dev sidecar watches the directory, so the
20
+ * latency is a filesystem event, not a poll.
21
+ *
22
+ * ── Removed on success, kept on failure ──────────────────────────────────────────────────────
23
+ *
24
+ * A finished asset is in `world.json`, and that IS the completion record — the browser reloads
25
+ * because the file changed, and the asset appears in the panel. A record left behind saying "done"
26
+ * would be a second, staler source of truth for the same fact.
27
+ *
28
+ * A failure is the opposite: nothing else records it. `world.json` is untouched, so the panel would
29
+ * simply show a job vanishing with no asset ever appearing. The record stays, carrying the error.
30
+ *
31
+ * ── Staleness is the reader's problem ────────────────────────────────────────────────────────
32
+ *
33
+ * A SIGKILLed generation never removes its file, so a `running` record is a claim, not a fact. The
34
+ * `pid` is on the record for exactly that: `readJobs` checks liveness and reports a job whose
35
+ * process is gone as failed. This is the rule `game-play-agent/src/mastra/utils/hq-asset-jobs.ts`
36
+ * already arrived at for the web lane's job list, for the same reason.
37
+ *
38
+ * Note the deliberate contrast with `dev-handle.ts`, which records a pid and explicitly declines to
39
+ * check it: there, a stale handle is self-correcting (the reload just fails to connect and says so).
40
+ * Here nothing else would ever notice, so the check earns its keep.
41
+ */
42
+ import * as fs from 'fs';
43
+ import * as path from 'path';
44
+ export const JOBS_DIR = path.join('.bitmagic', 'jobs');
45
+ /** Failed records are kept so the creator can see why nothing appeared — but not forever. */
46
+ const FAILED_RECORD_TTL_MS = 24 * 60 * 60 * 1000;
47
+ export function jobsDirPath(root) {
48
+ return path.join(root, JOBS_DIR);
49
+ }
50
+ function jobPath(root, jobId) {
51
+ return path.join(jobsDirPath(root), `${jobId}.json`);
52
+ }
53
+ /**
54
+ * Ids only have to be unique among the jobs running on one machine at one moment, and they end up
55
+ * in a filename. pid plus a counter plus a short random tail covers concurrent commands without
56
+ * needing a clock the tests would then have to control.
57
+ */
58
+ let sequence = 0;
59
+ function newJobId(kind) {
60
+ sequence += 1;
61
+ return `${kind}-${process.pid}-${sequence}-${Math.random().toString(36).slice(2, 8)}`;
62
+ }
63
+ /**
64
+ * Temp file then rename, the same discipline `forge/local-store.ts` uses: the sidecar watches this
65
+ * directory and will read a record the instant it appears, so a half-written file is a JSON parse
66
+ * error in the dev view rather than a merely-late update.
67
+ */
68
+ function writeRecord(root, record) {
69
+ const file = jobPath(root, record.jobId);
70
+ fs.mkdirSync(path.dirname(file), { recursive: true });
71
+ const temp = `${file}.${process.pid}.tmp`;
72
+ fs.writeFileSync(temp, `${JSON.stringify(record, null, 2)}\n`);
73
+ fs.renameSync(temp, file);
74
+ }
75
+ function isRecord(value) {
76
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
77
+ }
78
+ function parseRecord(raw) {
79
+ let parsed;
80
+ try {
81
+ parsed = JSON.parse(raw);
82
+ }
83
+ catch {
84
+ return null;
85
+ }
86
+ if (!isRecord(parsed))
87
+ return null;
88
+ const { jobId, kind, label, status, message, pid, startedAt, updatedAt } = parsed;
89
+ if (typeof jobId !== 'string' || typeof kind !== 'string' || typeof pid !== 'number')
90
+ return null;
91
+ return {
92
+ jobId,
93
+ kind: kind,
94
+ label: typeof label === 'string' ? label : '',
95
+ ...(typeof parsed.assetId === 'string' ? { assetId: parsed.assetId } : {}),
96
+ status: status === 'failed' ? 'failed' : 'running',
97
+ message: typeof message === 'string' ? message : '',
98
+ pid,
99
+ startedAt: typeof startedAt === 'string' ? startedAt : '',
100
+ updatedAt: typeof updatedAt === 'string' ? updatedAt : '',
101
+ ...(typeof parsed.error === 'string' ? { error: parsed.error } : {}),
102
+ };
103
+ }
104
+ /**
105
+ * Is the process that wrote this record still alive?
106
+ *
107
+ * Signal 0 performs the permission and existence checks without delivering anything. EPERM means
108
+ * the process exists but belongs to someone else — alive, as far as this question goes.
109
+ */
110
+ function isProcessAlive(pid) {
111
+ if (pid <= 0)
112
+ return false;
113
+ try {
114
+ process.kill(pid, 0);
115
+ return true;
116
+ }
117
+ catch (error) {
118
+ return error.code === 'EPERM';
119
+ }
120
+ }
121
+ /**
122
+ * Every job this project knows about, newest first, with dead `running` records reported as
123
+ * failed rather than left spinning in the dev view forever.
124
+ *
125
+ * Unreadable and unparseable files are skipped, not thrown: a record being written right now is a
126
+ * normal thing for a directory that several processes append to, and losing one tick of one job is
127
+ * not worth failing a read that also carries five healthy ones.
128
+ */
129
+ export function readJobs(root) {
130
+ let names;
131
+ try {
132
+ names = fs.readdirSync(jobsDirPath(root));
133
+ }
134
+ catch {
135
+ return [];
136
+ }
137
+ const jobs = [];
138
+ for (const name of names) {
139
+ if (!name.endsWith('.json'))
140
+ continue;
141
+ let raw;
142
+ try {
143
+ raw = fs.readFileSync(path.join(jobsDirPath(root), name), 'utf-8');
144
+ }
145
+ catch {
146
+ continue;
147
+ }
148
+ const record = parseRecord(raw);
149
+ if (record === null)
150
+ continue;
151
+ if (record.status === 'running' && !isProcessAlive(record.pid)) {
152
+ jobs.push({
153
+ ...record,
154
+ status: 'failed',
155
+ error: 'The generation stopped before it finished — its process is gone.',
156
+ });
157
+ continue;
158
+ }
159
+ jobs.push(record);
160
+ }
161
+ return jobs.sort((a, b) => b.startedAt.localeCompare(a.startedAt));
162
+ }
163
+ /**
164
+ * Drop failed records older than a day. Called by `dev` at startup rather than on a timer: this is
165
+ * housekeeping, and the moment someone opens the dev view is the moment a day-old failure stops
166
+ * being worth showing.
167
+ */
168
+ export function pruneJobs(root, now = Date.now()) {
169
+ let names;
170
+ try {
171
+ names = fs.readdirSync(jobsDirPath(root));
172
+ }
173
+ catch {
174
+ return 0;
175
+ }
176
+ let removed = 0;
177
+ for (const name of names) {
178
+ if (!name.endsWith('.json'))
179
+ continue;
180
+ const file = path.join(jobsDirPath(root), name);
181
+ let record = null;
182
+ try {
183
+ record = parseRecord(fs.readFileSync(file, 'utf-8'));
184
+ }
185
+ catch {
186
+ // Fall through: an unreadable record is exactly as useless as an expired one.
187
+ }
188
+ const startedMs = record === null ? 0 : Date.parse(record.startedAt);
189
+ const expired = !Number.isFinite(startedMs) || now - startedMs > FAILED_RECORD_TTL_MS;
190
+ // A live `running` job is never pruned however old it looks — a forge legitimately runs for
191
+ // twenty minutes, and a clock skew must not delete a job that is still working. A `running`
192
+ // record whose process is gone is a failure that never got to say so, and ages out like one.
193
+ if (record !== null && record.status === 'running' && isProcessAlive(record.pid))
194
+ continue;
195
+ if (!expired)
196
+ continue;
197
+ try {
198
+ fs.rmSync(file, { force: true });
199
+ removed += 1;
200
+ }
201
+ catch {
202
+ // A record we cannot delete is a stale file, never a failed startup.
203
+ }
204
+ }
205
+ return removed;
206
+ }
207
+ export function startJob(options) {
208
+ const now = new Date().toISOString();
209
+ const record = {
210
+ jobId: newJobId(options.kind),
211
+ kind: options.kind,
212
+ label: options.label,
213
+ ...(options.assetId === undefined ? {} : { assetId: options.assetId }),
214
+ status: 'running',
215
+ message: 'Starting…',
216
+ pid: process.pid,
217
+ startedAt: now,
218
+ updatedAt: now,
219
+ };
220
+ writeRecord(options.root, record);
221
+ return {
222
+ jobId: record.jobId,
223
+ update: (message) => {
224
+ record.message = message;
225
+ record.updatedAt = new Date().toISOString();
226
+ writeRecord(options.root, record);
227
+ },
228
+ };
229
+ }
230
+ /**
231
+ * Run `body` with its progress recorded for anyone watching.
232
+ *
233
+ * The `log` handed to the body is the caller's own logger with a tap on it, so every line a command
234
+ * already prints also becomes the job's current message. That is deliberate reuse rather than a
235
+ * second progress vocabulary to keep in step — the dev sidecar's in-process HQ job has worked this
236
+ * way since it shipped, and it means a command gains live progress in the dev view without a single
237
+ * new call site inside it.
238
+ *
239
+ * **Never fails the generation it is watching.** Bookkeeping that breaks a paid, minutes-long
240
+ * generation would be a far worse bug than the missing progress line it is trying to provide, so
241
+ * every filesystem error here is swallowed. The body's own errors propagate untouched, after being
242
+ * recorded.
243
+ */
244
+ export async function withJobRecord(options, body) {
245
+ let handle = null;
246
+ try {
247
+ handle = startJob(options);
248
+ }
249
+ catch {
250
+ // See above: no record is a worse dev view, not a failed generation.
251
+ }
252
+ const log = (message) => {
253
+ options.log(message);
254
+ try {
255
+ handle?.update(message);
256
+ }
257
+ catch {
258
+ // Same.
259
+ }
260
+ };
261
+ try {
262
+ const result = await body(log);
263
+ if (handle)
264
+ removeJob(options.root, handle.jobId);
265
+ return result;
266
+ }
267
+ catch (error) {
268
+ if (handle) {
269
+ failJob(options.root, handle.jobId, error instanceof Error ? error.message : String(error));
270
+ }
271
+ throw error;
272
+ }
273
+ }
274
+ /** Success: the asset is in world.json, and that is the record. */
275
+ export function removeJob(root, jobId) {
276
+ try {
277
+ fs.rmSync(jobPath(root, jobId), { force: true });
278
+ }
279
+ catch {
280
+ // A record we cannot delete reads as a dead process on the next poll, which is close enough.
281
+ }
282
+ }
283
+ /** Failure: nothing else records it, so the record stays and carries the reason. */
284
+ export function failJob(root, jobId, error) {
285
+ try {
286
+ const existing = parseRecord(fs.readFileSync(jobPath(root, jobId), 'utf-8'));
287
+ if (existing === null)
288
+ return;
289
+ writeRecord(root, { ...existing, status: 'failed', error, updatedAt: new Date().toISOString() });
290
+ }
291
+ catch {
292
+ // See withJobRecord: bookkeeping never fails the thing it is bookkeeping for.
293
+ }
294
+ }
295
+ //# sourceMappingURL=jobs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jobs.js","sourceRoot":"","sources":["../../src/project/jobs.ts"],"names":[],"mappings":"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"}
@@ -23,6 +23,13 @@ import * as path from 'path';
23
23
  * mechanism, because a false "fresh" ships an unverified bundle while a false "stale" only costs
24
24
  * one `bitmagic verify`.
25
25
  *
26
+ * `mechanics-plan.md` earns its place the same way, and for a sharper version of the reason: the
27
+ * agent is told to rewrite it after every slice — moving shipped items out of the backlog and
28
+ * re-ranking the rest is the whole point of the file. Left in, the ordinary
29
+ * `bitmagic verify` → update the backlog → `bitmagic publish` sequence exits 3 over prose, which
30
+ * teaches agents to reach for `--force`, the one flag that also waves through a genuinely stale
31
+ * verify. Nothing imports it and `vite.publish.config.js` cannot put prose in the bundle.
32
+ *
26
33
  * `GAME-DESIGN.md` earns its place on the same "no build tool reads it" test: nothing imports it,
27
34
  * `vite.publish.config.js` cannot put prose in the bundle, and it exists to be REWRITTEN as the
28
35
  * game evolves — it is the input `bitmagic cover` reads. Left in, the ordinary
@@ -33,7 +40,7 @@ import * as path from 'path';
33
40
  */
34
41
  const EXCLUDED_DIRS = new Set(['.bitmagic', 'node_modules', 'dist', '.vite-cache', '.git']);
35
42
  /** See EXCLUDED_DIRS: files that can never change what the bundle contains. */
36
- const EXCLUDED_FILES = new Set(['.DS_Store', 'GAME-DESIGN.md']);
43
+ const EXCLUDED_FILES = new Set(['.DS_Store', 'GAME-DESIGN.md', 'mechanics-plan.md']);
37
44
  /**
38
45
  * A relative path as the fingerprint hashes it: always forward-slashed.
39
46
  *
@@ -1 +1 @@
1
- {"version":3,"file":"fingerprint.js","sourceRoot":"","sources":["../../src/publish/fingerprint.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AACpC,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAE7B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,CAAC,WAAW,EAAE,cAAc,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,CAAC,CAAC,CAAC;AAE5F,+EAA+E;AAC/E,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,CAAC,WAAW,EAAE,gBAAgB,CAAC,CAAC,CAAC;AAEhE;;;;;;GAMG;AACH,MAAM,UAAU,WAAW,CAAC,YAAoB,EAAE,MAAc,IAAI,CAAC,GAAG;IACtE,OAAO,YAAY,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC3C,CAAC;AAED,SAAS,IAAI,CAAC,GAAW,EAAE,IAAY,EAAE,GAAa;IACpD,MAAM,OAAO,GAAG,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7D,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;YACxB,IAAI,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC;gBAAE,SAAS;YAC5C,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;QAC9C,CAAC;aAAM,IAAI,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;YAC1B,IAAI,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC;gBAAE,SAAS;YAC7C,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;YAChE,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC;QACjC,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,kBAAkB,CAAC,IAAY;IAC7C,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;IACxB,KAAK,CAAC,IAAI,EAAE,CAAC;IAEb,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;IAClC,KAAK,MAAM,GAAG,IAAI,KAAK,EAAE,CAAC;QACxB,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC;QACtD,IAAI,CAAC,MAAM,CAAC,GAAG,GAAG,IAAI,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAChF,CAAC;IACD,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC5B,CAAC"}
1
+ {"version":3,"file":"fingerprint.js","sourceRoot":"","sources":["../../src/publish/fingerprint.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AACpC,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAE7B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,CAAC,WAAW,EAAE,cAAc,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,CAAC,CAAC,CAAC;AAE5F,+EAA+E;AAC/E,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,CAAC,WAAW,EAAE,gBAAgB,EAAE,mBAAmB,CAAC,CAAC,CAAC;AAErF;;;;;;GAMG;AACH,MAAM,UAAU,WAAW,CAAC,YAAoB,EAAE,MAAc,IAAI,CAAC,GAAG;IACtE,OAAO,YAAY,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC3C,CAAC;AAED,SAAS,IAAI,CAAC,GAAW,EAAE,IAAY,EAAE,GAAa;IACpD,MAAM,OAAO,GAAG,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7D,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;YACxB,IAAI,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC;gBAAE,SAAS;YAC5C,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;QAC9C,CAAC;aAAM,IAAI,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;YAC1B,IAAI,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC;gBAAE,SAAS;YAC7C,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;YAChE,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC;QACjC,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,kBAAkB,CAAC,IAAY;IAC7C,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;IACxB,KAAK,CAAC,IAAI,EAAE,CAAC;IAEb,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;IAClC,KAAK,MAAM,GAAG,IAAI,KAAK,EAAE,CAAC;QACxB,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC;QACtD,IAAI,CAAC,MAAM,CAAC,GAAG,GAAG,IAAI,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAChF,CAAC;IACD,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC5B,CAAC"}
@@ -29,7 +29,13 @@ export interface ReloadHookMerge {
29
29
  /** Present only when `contents` is null *because* the file could not be merged. */
30
30
  skipped?: string;
31
31
  }
32
- /** The settings a project with no `.claude/settings.json` at all gets. */
32
+ /**
33
+ * The settings a project with no `.claude/settings.json` at all gets.
34
+ *
35
+ * Note the asymmetry with `mergeReloadHook` below: an existing settings file gains the Stop hook
36
+ * and nothing else. Permissions are the creator's own security posture, and adding entries to a
37
+ * file they already own is a different kind of act from seeding one that does not exist yet.
38
+ */
33
39
  export declare function renderClaudeSettings(): string;
34
40
  /**
35
41
  * Add the Stop hook to an existing settings file, preserving everything else in it.
@@ -33,9 +33,41 @@ function stringify(settings) {
33
33
  function reloadMatcher() {
34
34
  return { hooks: [{ type: 'command', command: RELOAD_HOOK_COMMAND }] };
35
35
  }
36
- /** The settings a project with no `.claude/settings.json` at all gets. */
36
+ /**
37
+ * The `bitmagic` commands a new project pre-approves, so the agent is not prompted for them.
38
+ *
39
+ * Every entry is free, local and idempotent, and every one is something AGENTS.md tells the agent
40
+ * to run repeatedly — `check` after each edit, `reload` at the end of each turn, `verify` before
41
+ * declaring anything done. A prompt on those is pure friction.
42
+ *
43
+ * What is deliberately ABSENT is the point of the list. A blanket `Bash(bitmagic:*)` would also
44
+ * cover `generate`, `forge` and `cover`, which spend the creator's sparks, and `publish`, which
45
+ * with `--visibility public` lists their game on bitmagic.ai. The permission prompt is currently
46
+ * the only human gate on that spending — AGENTS.md leans on it explicitly ("Generation costs the
47
+ * creator real money. Do not call these in a loop to explore options"), so widening this list
48
+ * removes a safeguard rather than a nuisance. `upgrade` is out too: it replaces `engine/`
49
+ * wholesale, which the creator should see coming.
50
+ */
51
+ const ALLOWED_COMMANDS = [
52
+ 'Bash(bitmagic check:*)',
53
+ 'Bash(bitmagic dev:*)',
54
+ 'Bash(bitmagic reload:*)',
55
+ 'Bash(bitmagic verify:*)',
56
+ 'Bash(bitmagic build:*)',
57
+ 'Bash(bitmagic whoami:*)',
58
+ ];
59
+ /**
60
+ * The settings a project with no `.claude/settings.json` at all gets.
61
+ *
62
+ * Note the asymmetry with `mergeReloadHook` below: an existing settings file gains the Stop hook
63
+ * and nothing else. Permissions are the creator's own security posture, and adding entries to a
64
+ * file they already own is a different kind of act from seeding one that does not exist yet.
65
+ */
37
66
  export function renderClaudeSettings() {
38
- return stringify({ hooks: { Stop: [reloadMatcher()] } });
67
+ return stringify({
68
+ permissions: { allow: ALLOWED_COMMANDS },
69
+ hooks: { Stop: [reloadMatcher()] },
70
+ });
39
71
  }
40
72
  /**
41
73
  * Does this `Stop` group already run our command?
@@ -1 +1 @@
1
- {"version":3,"file":"claude-settings.js","sourceRoot":"","sources":["../../src/scaffold/claude-settings.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"claude-settings.js","sourceRoot":"","sources":["../../src/scaffold/claude-settings.ts"],"names":[],"mappings":"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"}
@@ -15,13 +15,18 @@ export interface DownloadDeps {
15
15
  */
16
16
  export declare function downloadAndVerify(tarballUrl: string, expectedSha256: string, targetPath: string, deps: DownloadDeps): Promise<void>;
17
17
  /**
18
- * The tarball stores three prefixes at different depths — game/src/<root>, game/docs (plus the
19
- * sibling game/sw-cache-buster.js, which shares game/docs's strip depth) and templates — so it
20
- * takes three passes. A single pass cannot express them: `strip` is a fixed depth, and stripping
21
- * 2 would turn game/docs/x.md into a bare x.md.
18
+ * The tarball stores three prefixes at different depths — game/src/<root>, game/agent-docs (plus
19
+ * the sibling game/sw-cache-buster.js, which shares its strip depth) and templates — so it takes
20
+ * three passes. A single pass cannot express them: `strip` is a fixed depth, and stripping 2 would
21
+ * turn game/agent-docs/x.md into a bare x.md.
22
22
  *
23
- * Result: <engineDir>/{engine,types,bundle,debug,editor,genres}, <engineDir>/docs,
23
+ * Result: <engineDir>/{engine,types,bundle,debug,editor,genres}, <engineDir>/agent-docs,
24
24
  * <engineDir>/sw-cache-buster.js, and templates unpacked separately so the scaffolder can read
25
25
  * templates/index.json.
26
+ *
27
+ * `game/docs` is deliberately absent: those are engine-CONTRIBUTOR docs (how to edit the engine),
28
+ * which is noise in a project where engine/ is read-only. Tarballs published before the corpus
29
+ * moved still carry it, and the second pass simply does not match it — an old tarball produces a
30
+ * project without agent-docs rather than a failure. See OPTIONAL_VENDORED_DIRS in project.ts.
26
31
  */
27
32
  export declare function extractEngine(tarballPath: string, engineDir: string, templatesDir: string): Promise<void>;
@@ -39,14 +39,19 @@ export async function downloadAndVerify(tarballUrl, expectedSha256, targetPath,
39
39
  fs.writeFileSync(targetPath, body);
40
40
  }
41
41
  /**
42
- * The tarball stores three prefixes at different depths — game/src/<root>, game/docs (plus the
43
- * sibling game/sw-cache-buster.js, which shares game/docs's strip depth) and templates — so it
44
- * takes three passes. A single pass cannot express them: `strip` is a fixed depth, and stripping
45
- * 2 would turn game/docs/x.md into a bare x.md.
42
+ * The tarball stores three prefixes at different depths — game/src/<root>, game/agent-docs (plus
43
+ * the sibling game/sw-cache-buster.js, which shares its strip depth) and templates — so it takes
44
+ * three passes. A single pass cannot express them: `strip` is a fixed depth, and stripping 2 would
45
+ * turn game/agent-docs/x.md into a bare x.md.
46
46
  *
47
- * Result: <engineDir>/{engine,types,bundle,debug,editor,genres}, <engineDir>/docs,
47
+ * Result: <engineDir>/{engine,types,bundle,debug,editor,genres}, <engineDir>/agent-docs,
48
48
  * <engineDir>/sw-cache-buster.js, and templates unpacked separately so the scaffolder can read
49
49
  * templates/index.json.
50
+ *
51
+ * `game/docs` is deliberately absent: those are engine-CONTRIBUTOR docs (how to edit the engine),
52
+ * which is noise in a project where engine/ is read-only. Tarballs published before the corpus
53
+ * moved still carry it, and the second pass simply does not match it — an old tarball produces a
54
+ * project without agent-docs rather than a failure. See OPTIONAL_VENDORED_DIRS in project.ts.
50
55
  */
51
56
  export async function extractEngine(tarballPath, engineDir, templatesDir) {
52
57
  fs.mkdirSync(engineDir, { recursive: true });
@@ -58,14 +63,15 @@ export async function extractEngine(tarballPath, engineDir, templatesDir) {
58
63
  strip: 2,
59
64
  filter: (entryPath) => entryPath.startsWith('game/src/'),
60
65
  });
61
- // game/docs/coordinate-system.md -> <engineDir>/docs/coordinate-system.md
66
+ // game/agent-docs/npc-system.md -> <engineDir>/agent-docs/npc-system.md, and the same for its
67
+ // engine-api/ signature digest and samples/ subdirectories.
62
68
  // game/sw-cache-buster.js -> <engineDir>/sw-cache-buster.js (rides this pass because it needs
63
- // the same strip depth as game/docs/, even though it isn't under game/docs/ itself)
69
+ // the same strip depth as game/agent-docs/, even though it isn't under it)
64
70
  await tar.extract({
65
71
  file: tarballPath,
66
72
  cwd: engineDir,
67
73
  strip: 1,
68
- filter: (entryPath) => entryPath.startsWith('game/docs/') || entryPath === 'game/sw-cache-buster.js',
74
+ filter: (entryPath) => entryPath.startsWith('game/agent-docs/') || entryPath === 'game/sw-cache-buster.js',
69
75
  });
70
76
  // templates/index.json -> <templatesDir>/index.json
71
77
  await tar.extract({
@@ -1 +1 @@
1
- {"version":3,"file":"engine-download.js","sourceRoot":"","sources":["../../src/scaffold/engine-download.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"engine-download.js","sourceRoot":"","sources":["../../src/scaffold/engine-download.ts"],"names":[],"mappings":"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"}
@@ -41,6 +41,33 @@ export interface ProjectMetadata {
41
41
  }
42
42
  export declare function renderBitmagicJson(metadata: ProjectMetadata): string;
43
43
  export declare function renderAgentsMd(): string;
44
+ /**
45
+ * `.claude/skills/planning-a-game/SKILL.md` — the slice contract and the mechanic-recipe routing.
46
+ *
47
+ * These are one skill rather than two on purpose: you route to a recipe *in order to* scope slice
48
+ * 1, and slice 1 is the first section of the plan file the recipe tells you to write. Split, the
49
+ * first instruction of each half would be "now invoke the other half" — and the hosted lane already
50
+ * paid for that hop (see game-play-agent's mechanic-recipe-router.ts: the batch's slowest game read
51
+ * the right recipe twice and still shipped with no plan file, because the plan step sat above the
52
+ * table rather than inside it).
53
+ *
54
+ * They are also deliberately NOT in AGENTS.md, which carries only the trigger and a compressed
55
+ * version. `bitmagic upgrade` refreshes AGENTS.md only while it is byte-identical to what the CLI
56
+ * wrote, but overwrites shipped skills unconditionally — so a creator who has customised their
57
+ * AGENTS.md still receives every word of this.
58
+ */
59
+ export declare function renderPlanningSkill(): string;
60
+ /**
61
+ * `.claude/skills/finding-engine-apis/SKILL.md` — the discovery protocol in full.
62
+ *
63
+ * The problem this exists to solve is measured, not hypothetical. game-play-agent's
64
+ * engine-api-digest.ts opens with it: session analysis showed the hosted coding agent spending most
65
+ * of its wall-clock reconstructing the engine's public API through dozens of sequential searches,
66
+ * and one digest lookup replaced several code searches. A scaffolded project had the same 240k
67
+ * lines and none of the digest until the corpus started shipping — so an external agent had no
68
+ * option but the expensive one.
69
+ */
70
+ export declare function renderEngineApiSkill(): string;
44
71
  export declare function renderGenerateSkill(): string;
45
72
  /**
46
73
  * `GAME-DESIGN.md` — the project's design document, and the input `bitmagic cover` builds its