picopilot 0.1.5 → 0.2.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 (126) hide show
  1. package/dist/cli.d.ts.map +1 -1
  2. package/dist/cli.js +205 -17
  3. package/dist/cli.js.map +1 -1
  4. package/dist/commands/audio.d.ts +3 -3
  5. package/dist/commands/audio.d.ts.map +1 -1
  6. package/dist/commands/audio.js +69 -44
  7. package/dist/commands/audio.js.map +1 -1
  8. package/dist/commands/doctor.d.ts +22 -0
  9. package/dist/commands/doctor.d.ts.map +1 -0
  10. package/dist/commands/doctor.js +226 -0
  11. package/dist/commands/doctor.js.map +1 -0
  12. package/dist/commands/export.d.ts +3 -4
  13. package/dist/commands/export.d.ts.map +1 -1
  14. package/dist/commands/export.js +4 -9
  15. package/dist/commands/export.js.map +1 -1
  16. package/dist/commands/gfx.d.ts +2 -2
  17. package/dist/commands/gfx.d.ts.map +1 -1
  18. package/dist/commands/gfx.js +14 -7
  19. package/dist/commands/gfx.js.map +1 -1
  20. package/dist/commands/lint.d.ts +2 -2
  21. package/dist/commands/lint.d.ts.map +1 -1
  22. package/dist/commands/lint.js +3 -2
  23. package/dist/commands/lint.js.map +1 -1
  24. package/dist/commands/minify.d.ts +2 -2
  25. package/dist/commands/minify.d.ts.map +1 -1
  26. package/dist/commands/minify.js +3 -2
  27. package/dist/commands/minify.js.map +1 -1
  28. package/dist/commands/pico8-env.d.ts +112 -0
  29. package/dist/commands/pico8-env.d.ts.map +1 -0
  30. package/dist/commands/pico8-env.js +118 -0
  31. package/dist/commands/pico8-env.js.map +1 -0
  32. package/dist/commands/playtest.d.ts +2 -2
  33. package/dist/commands/playtest.d.ts.map +1 -1
  34. package/dist/commands/playtest.js +4 -9
  35. package/dist/commands/playtest.js.map +1 -1
  36. package/dist/commands/run.d.ts +3 -4
  37. package/dist/commands/run.d.ts.map +1 -1
  38. package/dist/commands/run.js +52 -19
  39. package/dist/commands/run.js.map +1 -1
  40. package/dist/commands/serve.d.ts +2 -2
  41. package/dist/commands/serve.d.ts.map +1 -1
  42. package/dist/commands/serve.js +4 -9
  43. package/dist/commands/serve.js.map +1 -1
  44. package/dist/commands/shrinko-env.d.ts +22 -0
  45. package/dist/commands/shrinko-env.d.ts.map +1 -0
  46. package/dist/commands/shrinko-env.js +15 -0
  47. package/dist/commands/shrinko-env.js.map +1 -0
  48. package/dist/commands/tokens.d.ts +4 -4
  49. package/dist/commands/tokens.d.ts.map +1 -1
  50. package/dist/commands/tokens.js +3 -2
  51. package/dist/commands/tokens.js.map +1 -1
  52. package/dist/commands/verify.d.ts +2 -2
  53. package/dist/commands/verify.d.ts.map +1 -1
  54. package/dist/commands/verify.js +3 -2
  55. package/dist/commands/verify.js.map +1 -1
  56. package/dist/engine/child-env.d.ts +14 -0
  57. package/dist/engine/child-env.d.ts.map +1 -0
  58. package/dist/engine/child-env.js +21 -0
  59. package/dist/engine/child-env.js.map +1 -0
  60. package/dist/engine/pico8/adapter.d.ts +23 -3
  61. package/dist/engine/pico8/adapter.d.ts.map +1 -1
  62. package/dist/engine/pico8/adapter.js.map +1 -1
  63. package/dist/engine/pico8/cleanup.d.ts +16 -0
  64. package/dist/engine/pico8/cleanup.d.ts.map +1 -0
  65. package/dist/engine/pico8/cleanup.js +74 -0
  66. package/dist/engine/pico8/cleanup.js.map +1 -0
  67. package/dist/engine/pico8/display.d.ts +149 -0
  68. package/dist/engine/pico8/display.d.ts.map +1 -0
  69. package/dist/engine/pico8/display.js +311 -0
  70. package/dist/engine/pico8/display.js.map +1 -0
  71. package/dist/engine/pico8/drive.d.ts.map +1 -1
  72. package/dist/engine/pico8/drive.js +28 -2
  73. package/dist/engine/pico8/drive.js.map +1 -1
  74. package/dist/engine/pico8/harness.d.ts +8 -0
  75. package/dist/engine/pico8/harness.d.ts.map +1 -1
  76. package/dist/engine/pico8/harness.js +9 -1
  77. package/dist/engine/pico8/harness.js.map +1 -1
  78. package/dist/engine/pico8/index.d.ts +3 -0
  79. package/dist/engine/pico8/index.d.ts.map +1 -1
  80. package/dist/engine/pico8/index.js +3 -0
  81. package/dist/engine/pico8/index.js.map +1 -1
  82. package/dist/engine/pico8/shell.d.ts +56 -3
  83. package/dist/engine/pico8/shell.d.ts.map +1 -1
  84. package/dist/engine/pico8/shell.js +188 -24
  85. package/dist/engine/pico8/shell.js.map +1 -1
  86. package/dist/engine/shrinko/shell.d.ts +3 -3
  87. package/dist/engine/shrinko/shell.js +3 -3
  88. package/package.json +2 -2
  89. package/src/cli.test.ts +229 -0
  90. package/src/cli.ts +230 -18
  91. package/src/commands/audio.test.ts +64 -1
  92. package/src/commands/audio.ts +86 -57
  93. package/src/commands/doctor.test.ts +149 -0
  94. package/src/commands/doctor.ts +284 -0
  95. package/src/commands/export.ts +9 -13
  96. package/src/commands/gfx.ts +19 -15
  97. package/src/commands/lint.ts +7 -6
  98. package/src/commands/minify.ts +7 -6
  99. package/src/commands/pico8-env.ts +192 -0
  100. package/src/commands/playtest.ts +8 -11
  101. package/src/commands/run.test.ts +110 -2
  102. package/src/commands/run.ts +68 -24
  103. package/src/commands/serve.ts +8 -11
  104. package/src/commands/shrinko-env.test.ts +68 -0
  105. package/src/commands/shrinko-env.ts +40 -0
  106. package/src/commands/tokens.ts +9 -6
  107. package/src/commands/verify.ts +7 -4
  108. package/src/engine/child-env.ts +22 -0
  109. package/src/engine/pico8/adapter.ts +25 -3
  110. package/src/engine/pico8/cleanup.test.ts +28 -0
  111. package/src/engine/pico8/cleanup.ts +76 -0
  112. package/src/engine/pico8/display.test.ts +210 -0
  113. package/src/engine/pico8/display.ts +429 -0
  114. package/src/engine/pico8/drive.test.ts +20 -0
  115. package/src/engine/pico8/drive.ts +25 -2
  116. package/src/engine/pico8/fake-xvfb.test-support.ts +55 -0
  117. package/src/engine/pico8/harness.test.ts +26 -0
  118. package/src/engine/pico8/harness.ts +18 -2
  119. package/src/engine/pico8/index.ts +3 -0
  120. package/src/engine/pico8/shell.test.ts +448 -9
  121. package/src/engine/pico8/shell.ts +255 -26
  122. package/src/engine/pico8/virtual-display.process.test.ts +206 -0
  123. package/src/engine/shrinko/shell.ts +3 -3
  124. package/src/mcp.process.test.ts +219 -0
  125. package/src/skills/picopilot-audio/SKILL.md +4 -8
  126. package/src/skills/picopilot-overview/SKILL.md +9 -1
@@ -1,16 +1,19 @@
1
- import { type DriveOptions, type ExportOptions, type Pico8Adapter, type Pico8DriveResult, type Pico8ExportResult, type Pico8RecordResult, type Pico8Result, type RecordOptions, type RunOptions } from './adapter.js';
1
+ import { type DriveOptions, type ExitReason, type ExportOptions, type Pico8Adapter, type Pico8DriveResult, type Pico8ExportResult, type Pico8RecordResult, type Pico8Result, type RecordOptions, type RunOptions } from './adapter.js';
2
+ import { type DisplayMode, type VirtualDisplayDeps } from './display.js';
2
3
  /**
3
4
  * A spawned PICO-8 process, abstracted so tests inject a fake. `onStdout`
4
5
  * delivers stdout chunks (both `stdout` and `stderr` folded in, since PICO-8's
5
6
  * `printh` and its own lines can land on either); `onClose` fires when the
6
7
  * process exits on its own; `onError` fires on a spawn failure (ENOENT ⇒ PICO-8
7
- * absent). `kill` terminates the process tree (the backstop / sentinel kill).
8
+ * absent). `kill` terminates the process tree (the backstop / sentinel kill),
9
+ * with SIGKILL unless a gentler `signal` is given (the `xvfb-run` fallback is
10
+ * first sent SIGTERM so Xvfb can remove its lock file and socket).
8
11
  */
9
12
  export interface Pico8Process {
10
13
  onStdout(cb: (chunk: string) => void): void;
11
14
  onClose(cb: (code: number | null) => void): void;
12
15
  onError(cb: (err: NodeJS.ErrnoException) => void): void;
13
- kill(): void;
16
+ kill(signal?: NodeJS.Signals): void;
14
17
  /**
15
18
  * Writes raw bytes to the process's stdin, for the `drive` transport (the
16
19
  * fixed-size command blocks). Absent/undefined when stdin was detached
@@ -34,6 +37,28 @@ export declare function pico8HomeDir(): string;
34
37
  * land in the CWD. Applied at every spawn site.
35
38
  */
36
39
  export declare function withPico8Home(args: string[]): string[];
40
+ /**
41
+ * The environment PICO-8 is spawned with: the parent env overlaid with the
42
+ * picopilot-resolved values ({@link overlayEnv}). A `-run` session cannot open a
43
+ * window or an audio device without DISPLAY, HOME, XDG_RUNTIME_DIR, SDL_*, ...
44
+ */
45
+ export declare function pico8ChildEnv(resolved: Readonly<Record<string, string | undefined>>, parent: NodeJS.ProcessEnv): NodeJS.ProcessEnv;
46
+ export declare function pico8RuntimeDir(): string;
47
+ /** `env` with a private {@link pico8RuntimeDir} filled in when XDG_RUNTIME_DIR is absent. */
48
+ export declare function withRuntimeDir(env: NodeJS.ProcessEnv): NodeJS.ProcessEnv;
49
+ /** The last lines of PICO-8's `log.txt` in the isolated `-home`, or undefined if absent. */
50
+ export declare function readPico8LogTail(home?: string, lines?: number): string | undefined;
51
+ /**
52
+ * Says WHY a record run produced no WAV, from how it ended. The sentinel is the
53
+ * harness's last act (after `audio_end`), so anything other than a sentinel
54
+ * means the harness never finished; a sentinel with no WAV means `audio_end`
55
+ * saved nothing usable.
56
+ */
57
+ export declare function explainNoWav(exitReason: ExitReason, ctx: {
58
+ backstopMs: number;
59
+ wavDir: string;
60
+ basename: string;
61
+ }): string;
37
62
  export declare const spawnRunner: SpawnRunner;
38
63
  /** The candidate ways to launch PICO-8, tried in order: `PICO8_PATH`, then `pico8` on `PATH`. */
39
64
  export declare function pico8Candidates(env: NodeJS.ProcessEnv): string[];
@@ -43,7 +68,22 @@ export interface ShellPico8Options {
43
68
  readonly env: NodeJS.ProcessEnv;
44
69
  /** The spawn runner (defaults to {@link spawnRunner}); tests inject a fake. */
45
70
  readonly spawn?: SpawnRunner;
71
+ /**
72
+ * The display mode for `-run` sessions (ADR-0017; defaults to `auto`). Only
73
+ * {@link ShellPico8Adapter.record} consults it: the `-x` paths never need a
74
+ * display and never start one.
75
+ */
76
+ readonly display?: DisplayMode;
77
+ /** The virtual-display dependencies (Xvfb lookup + spawn); tests inject fakes. */
78
+ readonly virtualDisplay?: VirtualDisplayDeps;
79
+ /**
80
+ * How long a gracefully-ended run (the `xvfb-run` fallback) gets between
81
+ * SIGTERM and SIGKILL, in ms (default {@link DEFAULT_KILL_GRACE_MS}).
82
+ */
83
+ readonly killGraceMs?: number;
46
84
  }
85
+ /** The default SIGTERM-to-SIGKILL grace for a gracefully-ended run. */
86
+ export declare const DEFAULT_KILL_GRACE_MS = 2000;
47
87
  /**
48
88
  * The v1 {@link Pico8Adapter}: shells out to the user's native `pico8 -x`
49
89
  * (ADR-0006, native path first). It owns the ORCHESTRATION the command should
@@ -57,6 +97,9 @@ export interface ShellPico8Options {
57
97
  export declare class ShellPico8Adapter implements Pico8Adapter {
58
98
  private readonly env;
59
99
  private readonly spawnRun;
100
+ private readonly display;
101
+ private readonly virtualDisplay;
102
+ private readonly killGraceMs;
60
103
  constructor(options: ShellPico8Options);
61
104
  run(options: RunOptions): Promise<Pico8Result>;
62
105
  /**
@@ -90,6 +133,16 @@ export declare class ShellPico8Adapter implements Pico8Adapter {
90
133
  */
91
134
  export(options: ExportOptions): Promise<Pico8ExportResult>;
92
135
  record(options: RecordOptions): Promise<Pico8RecordResult>;
136
+ /**
137
+ * The record session on a private virtual display (ADR-0017): start Xvfb
138
+ * (or fall back to `xvfb-run`), run PICO-8 on it with a dummy SDL audio
139
+ * driver (unless the caller chose one; `audio_rec` captures PICO-8's own
140
+ * mixer, not the device), and ALWAYS stop the display afterwards, however
141
+ * the run ended (sentinel, backstop, crash, spawn failure).
142
+ */
143
+ private recordOnVirtualDisplay;
144
+ /** The record launch itself, natively or under a virtual display's env/wrapper. */
145
+ private recordWith;
93
146
  /**
94
147
  * The shared launch/sentinel-watch/backstop/collect loop behind both
95
148
  * {@link run} and {@link record}. `buildOk` turns the exit reason + captured
@@ -1 +1 @@
1
- {"version":3,"file":"shell.d.ts","sourceRoot":"","sources":["../../../src/engine/pico8/shell.ts"],"names":[],"mappings":"AAUA,OAAO,EACN,KAAK,YAAY,EAGjB,KAAK,aAAa,EAClB,KAAK,YAAY,EAEjB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,EACtB,KAAK,WAAW,EAEhB,KAAK,aAAa,EAClB,KAAK,UAAU,EACf,MAAM,cAAc,CAAC;AAGtB;;;;;;GAMG;AACH,MAAM,WAAW,YAAY;IAC5B,QAAQ,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAAC;IAC5C,OAAO,CAAC,EAAE,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,GAAG,IAAI,CAAC;IACjD,OAAO,CAAC,EAAE,EAAE,CAAC,GAAG,EAAE,MAAM,CAAC,cAAc,KAAK,IAAI,GAAG,IAAI,CAAC;IACxD,IAAI,IAAI,IAAI,CAAC;IACb;;;;OAIG;IACH,UAAU,CAAC,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,CAAC;CACrC;AAED;;;;;;GAMG;AACH,MAAM,MAAM,WAAW,GAAG,CACzB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EAAE,EACd,GAAG,EAAE,MAAM,CAAC,UAAU,EACtB,OAAO,CAAC,EAAE;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAC,KACvB,YAAY,CAAC;AAsBlB,wBAAgB,YAAY,IAAI,MAAM,CAIrC;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAItD;AAED,eAAO,MAAM,WAAW,EAAE,WAsCzB,CAAC;AAEF,iGAAiG;AACjG,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,MAAM,EAAE,CAKhE;AAuDD,6CAA6C;AAC7C,MAAM,WAAW,iBAAiB;IACjC,iFAAiF;IACjF,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IAChC,+EAA+E;IAC/E,QAAQ,CAAC,KAAK,CAAC,EAAE,WAAW,CAAC;CAC7B;AAED;;;;;;;;;GASG;AACH,qBAAa,iBAAkB,YAAW,YAAY;IACrD,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAoB;IACxC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAc;gBAE3B,OAAO,EAAE,iBAAiB;IAKtC,GAAG,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,WAAW,CAAC;IAoB9C;;;;;;;;;;OAUG;IACH;;;;;;;;OAQG;IACH,KAAK,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAmBvD;;;;;;;OAOG;IACH,MAAM,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,iBAAiB,CAAC;IA+B1D,MAAM,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAsB1D;;;;;;;OAOG;IACH,OAAO,CAAC,WAAW;CA0DnB"}
1
+ {"version":3,"file":"shell.d.ts","sourceRoot":"","sources":["../../../src/engine/pico8/shell.ts"],"names":[],"mappings":"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"}
@@ -1,8 +1,11 @@
1
1
  import { spawn } from 'node:child_process';
2
- import { existsSync, mkdirSync, mkdtempSync, readdirSync, statSync, } from 'node:fs';
2
+ import { existsSync, mkdirSync, mkdtempSync, readdirSync, readFileSync, rmSync, statSync, } from 'node:fs';
3
3
  import { tmpdir } from 'node:os';
4
4
  import { join } from 'node:path';
5
5
  import { EXPORT_HTML_NAME, pico8NotFound, RECORD_WAV_BASENAME, } from './adapter.js';
6
+ import { DEFAULT_DISPLAY_MODE, findExecutable, needsVirtualDisplay, startVirtualDisplay, } from './display.js';
7
+ import { overlayEnv } from '../child-env.js';
8
+ import { killOnAbort } from './cleanup.js';
6
9
  import { SentinelWatcher } from './sentinel.js';
7
10
  /**
8
11
  * The default {@link SpawnRunner}: `spawn` with stdin detached (`ignore`) so the
@@ -39,6 +42,63 @@ export function withPico8Home(args) {
39
42
  mkdirSync(home, { recursive: true });
40
43
  return ['-home', home, ...args];
41
44
  }
45
+ /**
46
+ * The environment PICO-8 is spawned with: the parent env overlaid with the
47
+ * picopilot-resolved values ({@link overlayEnv}). A `-run` session cannot open a
48
+ * window or an audio device without DISPLAY, HOME, XDG_RUNTIME_DIR, SDL_*, ...
49
+ */
50
+ export function pico8ChildEnv(resolved, parent) {
51
+ return overlayEnv(resolved, parent);
52
+ }
53
+ /**
54
+ * A private `XDG_RUNTIME_DIR` (mode 0700, one per picopilot process) for a
55
+ * PICO-8 launched without one. SDL logs "XDG_RUNTIME_DIR is invalid or not set"
56
+ * otherwise, which is noise in every headless report.
57
+ */
58
+ let cachedRuntimeDir;
59
+ export function pico8RuntimeDir() {
60
+ if (cachedRuntimeDir !== undefined && existsSync(cachedRuntimeDir)) {
61
+ return cachedRuntimeDir;
62
+ }
63
+ cachedRuntimeDir = mkdtempSync(join(tmpdir(), 'picopilot-xdg-runtime-'));
64
+ return cachedRuntimeDir;
65
+ }
66
+ /** `env` with a private {@link pico8RuntimeDir} filled in when XDG_RUNTIME_DIR is absent. */
67
+ export function withRuntimeDir(env) {
68
+ const current = env.XDG_RUNTIME_DIR;
69
+ if (current !== undefined && current.trim() !== '')
70
+ return env;
71
+ return { ...env, XDG_RUNTIME_DIR: pico8RuntimeDir() };
72
+ }
73
+ /** How many lines of PICO-8's `log.txt` a failed record reports. */
74
+ const LOG_TAIL_LINES = 25;
75
+ /** The last lines of PICO-8's `log.txt` in the isolated `-home`, or undefined if absent. */
76
+ export function readPico8LogTail(home = pico8HomeDir(), lines = LOG_TAIL_LINES) {
77
+ try {
78
+ const text = readFileSync(join(home, 'log.txt'), 'utf8');
79
+ const all = text.trimEnd().split('\n');
80
+ return all.slice(-lines).join('\n');
81
+ }
82
+ catch {
83
+ return undefined;
84
+ }
85
+ }
86
+ /**
87
+ * Says WHY a record run produced no WAV, from how it ended. The sentinel is the
88
+ * harness's last act (after `audio_end`), so anything other than a sentinel
89
+ * means the harness never finished; a sentinel with no WAV means `audio_end`
90
+ * saved nothing usable.
91
+ */
92
+ export function explainNoWav(exitReason, ctx) {
93
+ switch (exitReason) {
94
+ case 'timeout':
95
+ return `the backstop fired after ${ctx.backstopMs}ms before the record harness printed its done-sentinel: the cart never reached audio_end (it failed to load, errored at runtime, or its game loop never ran). See pico8LogTail and printh.`;
96
+ case 'exit':
97
+ return 'PICO-8 exited before the record harness printed its done-sentinel: the cart failed to load or crashed, or PICO-8 itself could not start (e.g. no display or audio device). See pico8LogTail and printh.';
98
+ case 'sentinel':
99
+ return `the record harness reached its done-sentinel but no non-empty ${ctx.basename}.wav was written to ${ctx.wavDir}: audio_end saved nothing usable (an empty 0-frame capture).`;
100
+ }
101
+ }
42
102
  export const spawnRunner = (file, args, env, options) => {
43
103
  // `drive` pipes fixed-size command blocks to stdin; `run`/`record` detach it so
44
104
  // the cart never blocks on console input.
@@ -69,14 +129,14 @@ export const spawnRunner = (file, args, env, options) => {
69
129
  // A closed stdin (the cart exited) is not fatal to the run.
70
130
  }
71
131
  },
72
- kill() {
132
+ kill(signal = 'SIGKILL') {
73
133
  try {
74
134
  // Negative pid kills the process GROUP (detached), so any child dies too.
75
135
  if (child.pid !== undefined)
76
- process.kill(-child.pid, 'SIGKILL');
136
+ process.kill(-child.pid, signal);
77
137
  }
78
138
  catch {
79
- child.kill('SIGKILL'); // fall back to killing just the process
139
+ child.kill(signal); // fall back to killing just the process
80
140
  }
81
141
  },
82
142
  };
@@ -143,6 +203,8 @@ function collectWav(wavDir, basename) {
143
203
  }
144
204
  return path;
145
205
  }
206
+ /** The default SIGTERM-to-SIGKILL grace for a gracefully-ended run. */
207
+ export const DEFAULT_KILL_GRACE_MS = 2_000;
146
208
  /**
147
209
  * The v1 {@link Pico8Adapter}: shells out to the user's native `pico8 -x`
148
210
  * (ADR-0006, native path first). It owns the ORCHESTRATION the command should
@@ -156,9 +218,15 @@ function collectWav(wavDir, basename) {
156
218
  export class ShellPico8Adapter {
157
219
  env;
158
220
  spawnRun;
221
+ display;
222
+ virtualDisplay;
223
+ killGraceMs;
159
224
  constructor(options) {
225
+ this.killGraceMs = options.killGraceMs ?? DEFAULT_KILL_GRACE_MS;
160
226
  this.env = options.env;
161
227
  this.spawnRun = options.spawn ?? spawnRunner;
228
+ this.display = options.display ?? DEFAULT_DISPLAY_MODE;
229
+ this.virtualDisplay = options.virtualDisplay ?? {};
162
230
  }
163
231
  run(options) {
164
232
  const [file] = pico8Candidates(this.env);
@@ -246,20 +314,80 @@ export class ShellPico8Adapter {
246
314
  });
247
315
  }
248
316
  record(options) {
317
+ if (needsVirtualDisplay(this.display, this.env)) {
318
+ return this.recordOnVirtualDisplay(options);
319
+ }
320
+ return this.recordWith(options, 'native');
321
+ }
322
+ /**
323
+ * The record session on a private virtual display (ADR-0017): start Xvfb
324
+ * (or fall back to `xvfb-run`), run PICO-8 on it with a dummy SDL audio
325
+ * driver (unless the caller chose one; `audio_rec` captures PICO-8's own
326
+ * mixer, not the device), and ALWAYS stop the display afterwards, however
327
+ * the run ended (sentinel, backstop, crash, spawn failure).
328
+ */
329
+ async recordOnVirtualDisplay(options) {
330
+ const [file] = pico8Candidates(this.env);
331
+ // Absent PICO-8 is reported as such BEFORE paying for (or failing on) a
332
+ // display, and wrapped in xvfb-run a missing binary would not ENOENT.
333
+ const find = this.virtualDisplay.find ?? findExecutable;
334
+ if (find(file, this.env) === undefined)
335
+ return pico8NotFound();
336
+ const started = await startVirtualDisplay(this.env, this.virtualDisplay);
337
+ if (!started.ok)
338
+ return started;
339
+ const vd = started.display;
340
+ try {
341
+ const env = { ...this.env, ...vd.env };
342
+ const audioDriver = env.SDL_AUDIODRIVER;
343
+ if (audioDriver === undefined || audioDriver.trim() === '') {
344
+ env.SDL_AUDIODRIVER = 'dummy';
345
+ }
346
+ return await this.recordWith(options, vd.backend, {
347
+ env,
348
+ wrap: (f, a) => vd.wrap(f, a),
349
+ // xvfb-run's Xvfb lives in PICO-8's process group: SIGTERM first so it
350
+ // removes its /tmp/.X<n>-lock and socket (a SIGKILL leaves them behind).
351
+ endGracefully: vd.backend === 'xvfb-run',
352
+ });
353
+ }
354
+ finally {
355
+ await vd.stop();
356
+ }
357
+ }
358
+ /** The record launch itself, natively or under a virtual display's env/wrapper. */
359
+ recordWith(options, display, launch) {
249
360
  const [file] = pico8Candidates(this.env);
250
361
  const basename = options.wavBasename ?? RECORD_WAV_BASENAME;
251
362
  // `-root_path <wavDir>` steers the `audio_end(1)`-to-current-folder WAV into
252
363
  // the isolated temp dir (never ~/Desktop or the carts root). `-run` is a real
253
364
  // A/V session (recording needs audio to capture; `-x` yields an empty WAV).
254
365
  const args = ['-root_path', options.wavDir, '-run', options.cartPath];
255
- return this.orchestrate(file, args, { sentinel: options.sentinel, backstopMs: options.backstopMs }, (exitReason, printh) => ({
256
- ok: true,
257
- value: {
258
- wavPath: collectWav(options.wavDir, basename),
259
- printh,
260
- exitReason,
261
- },
262
- }));
366
+ // The `-home` is shared by every launch in this process: drop the previous
367
+ // log.txt so a failed record never reports another run's log as its own.
368
+ rmSync(join(pico8HomeDir(), 'log.txt'), { force: true });
369
+ return this.orchestrate(file, args, { sentinel: options.sentinel, backstopMs: options.backstopMs }, (exitReason, printh) => {
370
+ const wavPath = collectWav(options.wavDir, basename);
371
+ if (wavPath !== undefined) {
372
+ return { ok: true, value: { wavPath, printh, exitReason, display } };
373
+ }
374
+ const pico8LogTail = readPico8LogTail();
375
+ return {
376
+ ok: true,
377
+ value: {
378
+ wavPath,
379
+ printh,
380
+ exitReason,
381
+ display,
382
+ noWavReason: explainNoWav(exitReason, {
383
+ backstopMs: options.backstopMs,
384
+ wavDir: options.wavDir,
385
+ basename,
386
+ }),
387
+ ...(pico8LogTail !== undefined ? { pico8LogTail } : {}),
388
+ },
389
+ };
390
+ }, launch);
263
391
  }
264
392
  /**
265
393
  * The shared launch/sentinel-watch/backstop/collect loop behind both
@@ -274,16 +402,49 @@ export class ShellPico8Adapter {
274
402
  return new Promise((resolve) => {
275
403
  let settled = false;
276
404
  let backstop;
277
- const proc = this.spawnRun(file, withPico8Home(args), this.env, {
278
- stdin: spawnOpts?.stdin,
279
- });
280
- const finish = (exitReason) => {
405
+ const homeArgs = withPico8Home(args);
406
+ const launch = spawnOpts?.wrap !== undefined
407
+ ? spawnOpts.wrap(file, homeArgs)
408
+ : { file, args: homeArgs };
409
+ const proc = this.spawnRun(launch.file, launch.args, withRuntimeDir(spawnOpts?.env ?? this.env), { stdin: spawnOpts?.stdin });
410
+ // If picopilot itself is stopped mid-run, take PICO-8 down with it.
411
+ const disposeAbort = killOnAbort(() => proc.kill());
412
+ let onClosed;
413
+ /**
414
+ * Ends the run once. `kill` = PICO-8 is still running (sentinel/backstop):
415
+ * SIGKILL its group, or for a graceful end SIGTERM it and resolve when it
416
+ * has closed (SIGKILL after the grace period).
417
+ */
418
+ const finish = (exitReason, kill = false) => {
281
419
  if (settled)
282
420
  return;
283
421
  settled = true;
284
422
  if (backstop !== undefined)
285
423
  clearTimeout(backstop);
286
- resolve(buildOk(exitReason, watcher.text));
424
+ let resolved = false;
425
+ const done = () => {
426
+ if (resolved)
427
+ return;
428
+ resolved = true;
429
+ // Only now: a signal during the graceful wait must still kill PICO-8.
430
+ disposeAbort();
431
+ resolve(buildOk(exitReason, watcher.text));
432
+ };
433
+ if (!kill)
434
+ return done();
435
+ if (spawnOpts?.endGracefully !== true) {
436
+ proc.kill();
437
+ return done();
438
+ }
439
+ proc.kill('SIGTERM');
440
+ const hard = setTimeout(() => {
441
+ proc.kill();
442
+ done();
443
+ }, this.killGraceMs);
444
+ onClosed = () => {
445
+ clearTimeout(hard);
446
+ done();
447
+ };
287
448
  };
288
449
  proc.onError((err) => {
289
450
  // A spawn ENOENT ⇒ PICO-8 is absent (a bad PICO8_PATH surfaces as absence
@@ -293,6 +454,7 @@ export class ShellPico8Adapter {
293
454
  return;
294
455
  if (err.code === 'ENOENT') {
295
456
  settled = true;
457
+ disposeAbort();
296
458
  if (backstop !== undefined)
297
459
  clearTimeout(backstop);
298
460
  resolve(pico8NotFound());
@@ -302,12 +464,15 @@ export class ShellPico8Adapter {
302
464
  }
303
465
  });
304
466
  proc.onStdout((chunk) => {
305
- if (watcher.push(chunk) && !settled) {
306
- proc.kill(); // sentinel matched: end the run promptly
307
- finish('sentinel');
308
- }
467
+ // sentinel matched: end the run promptly
468
+ if (watcher.push(chunk) && !settled)
469
+ finish('sentinel', true);
470
+ });
471
+ proc.onClose(() => {
472
+ if (onClosed !== undefined)
473
+ return onClosed();
474
+ finish('exit'); // PICO-8 exited on its own
309
475
  });
310
- proc.onClose(() => finish('exit')); // PICO-8 exited on its own
311
476
  // For `drive`: write the command blocks to the live stdin now that it is
312
477
  // spawned. A spawn ENOENT resolves via onError before this matters.
313
478
  spawnOpts?.onSpawn?.(proc);
@@ -315,8 +480,7 @@ export class ShellPico8Adapter {
315
480
  backstop = setTimeout(() => {
316
481
  if (settled)
317
482
  return;
318
- proc.kill();
319
- finish('timeout');
483
+ finish('timeout', true);
320
484
  }, opts.backstopMs);
321
485
  });
322
486
  }
@@ -1 +1 @@
1
- {"version":3,"file":"shell.js","sourceRoot":"","sources":["../../../src/engine/pico8/shell.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"shell.js","sourceRoot":"","sources":["../../../src/engine/pico8/shell.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,KAAK,EAAC,MAAM,oBAAoB,CAAC;AACzC,OAAO,EACN,UAAU,EACV,SAAS,EACT,WAAW,EACX,WAAW,EACX,YAAY,EACZ,MAAM,EACN,QAAQ,GACR,MAAM,SAAS,CAAC;AACjB,OAAO,EAAC,MAAM,EAAC,MAAM,SAAS,CAAC;AAC/B,OAAO,EAAC,IAAI,EAAC,MAAM,WAAW,CAAC;AAC/B,OAAO,EAGN,gBAAgB,EAGhB,aAAa,EAKb,mBAAmB,GAInB,MAAM,cAAc,CAAC;AACtB,OAAO,EACN,oBAAoB,EAEpB,cAAc,EACd,mBAAmB,EACnB,mBAAmB,GAEnB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAC,UAAU,EAAC,MAAM,iBAAiB,CAAC;AAC3C,OAAO,EAAC,WAAW,EAAC,MAAM,cAAc,CAAC;AACzC,OAAO,EAAC,eAAe,EAAC,MAAM,eAAe,CAAC;AAsC9C;;;;;GAKG;AACH;;;;;;;;;;;;GAYG;AACH,IAAI,UAA8B,CAAC;AACnC,MAAM,UAAU,YAAY;IAC3B,IAAI,UAAU,KAAK,SAAS,IAAI,UAAU,CAAC,UAAU,CAAC;QAAE,OAAO,UAAU,CAAC;IAC1E,UAAU,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,uBAAuB,CAAC,CAAC,CAAC;IAClE,OAAO,UAAU,CAAC;AACnB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,IAAc;IAC3C,MAAM,IAAI,GAAG,YAAY,EAAE,CAAC;IAC5B,SAAS,CAAC,IAAI,EAAE,EAAC,SAAS,EAAE,IAAI,EAAC,CAAC,CAAC;IACnC,OAAO,CAAC,OAAO,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC,CAAC;AACjC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAC5B,QAAsD,EACtD,MAAyB;IAEzB,OAAO,UAAU,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;AACrC,CAAC;AAED;;;;GAIG;AACH,IAAI,gBAAoC,CAAC;AACzC,MAAM,UAAU,eAAe;IAC9B,IAAI,gBAAgB,KAAK,SAAS,IAAI,UAAU,CAAC,gBAAgB,CAAC,EAAE,CAAC;QACpE,OAAO,gBAAgB,CAAC;IACzB,CAAC;IACD,gBAAgB,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,wBAAwB,CAAC,CAAC,CAAC;IACzE,OAAO,gBAAgB,CAAC;AACzB,CAAC;AAED,6FAA6F;AAC7F,MAAM,UAAU,cAAc,CAAC,GAAsB;IACpD,MAAM,OAAO,GAAG,GAAG,CAAC,eAAe,CAAC;IACpC,IAAI,OAAO,KAAK,SAAS,IAAI,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE;QAAE,OAAO,GAAG,CAAC;IAC/D,OAAO,EAAC,GAAG,GAAG,EAAE,eAAe,EAAE,eAAe,EAAE,EAAC,CAAC;AACrD,CAAC;AAED,oEAAoE;AACpE,MAAM,cAAc,GAAG,EAAE,CAAC;AAE1B,4FAA4F;AAC5F,MAAM,UAAU,gBAAgB,CAC/B,OAAe,YAAY,EAAE,EAC7B,QAAgB,cAAc;IAE9B,IAAI,CAAC;QACJ,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,EAAE,MAAM,CAAC,CAAC;QACzD,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACvC,OAAO,GAAG,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACrC,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,SAAS,CAAC;IAClB,CAAC;AACF,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAC3B,UAAsB,EACtB,GAA2D;IAE3D,QAAQ,UAAU,EAAE,CAAC;QACpB,KAAK,SAAS;YACb,OAAO,4BAA4B,GAAG,CAAC,UAAU,4LAA4L,CAAC;QAC/O,KAAK,MAAM;YACV,OAAO,yMAAyM,CAAC;QAClN,KAAK,UAAU;YACd,OAAO,iEAAiE,GAAG,CAAC,QAAQ,uBAAuB,GAAG,CAAC,MAAM,8DAA8D,CAAC;IACtL,CAAC;AACF,CAAC;AAED,MAAM,CAAC,MAAM,WAAW,GAAgB,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE;IACpE,gFAAgF;IAChF,0CAA0C;IAC1C,MAAM,KAAK,GAAG,OAAO,EAAE,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC;IAC1D,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE;QAC/B,GAAG;QACH,KAAK,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC;QAC9B,QAAQ,EAAE,IAAI;KACd,CAAC,CAAC;IACH,KAAK,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAClC,KAAK,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAClC,OAAO;QACN,QAAQ,CAAC,EAAE;YACV,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;YAC7B,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QAC9B,CAAC;QACD,OAAO,CAAC,EAAE;YACT,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QACvB,CAAC;QACD,OAAO,CAAC,EAAE;YACT,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,EAAwB,CAAC,CAAC;QAC7C,CAAC;QACD,UAAU,CAAC,KAAK;YACf,IAAI,CAAC;gBACJ,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;YACxC,CAAC;YAAC,MAAM,CAAC;gBACR,4DAA4D;YAC7D,CAAC;QACF,CAAC;QACD,IAAI,CAAC,MAAM,GAAG,SAAS;YACtB,IAAI,CAAC;gBACJ,0EAA0E;gBAC1E,IAAI,KAAK,CAAC,GAAG,KAAK,SAAS;oBAAE,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;YAC/D,CAAC;YAAC,MAAM,CAAC;gBACR,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,wCAAwC;YAC7D,CAAC;QACF,CAAC;KACD,CAAC;AACH,CAAC,CAAC;AAEF,iGAAiG;AACjG,MAAM,UAAU,eAAe,CAAC,GAAsB;IACrD,MAAM,OAAO,GAAG,GAAG,CAAC,UAAU,EAAE,IAAI,EAAE,CAAC;IACvC,OAAO,OAAO,KAAK,SAAS,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;QACjD,CAAC,CAAC,CAAC,OAAO,EAAE,OAAO,CAAC;QACpB,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;AACd,CAAC;AAED;;;;GAIG;AACH,SAAS,kBAAkB,CAAC,MAAc;IACzC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC;QAAE,OAAO,EAAE,CAAC;IACnC,OAAO,WAAW,CAAC,MAAM,CAAC;SACxB,IAAI,EAAE;SACN,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;SAC3B,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE;QACb,IAAI,CAAC;YACJ,OAAO,QAAQ,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;QAC7B,CAAC;QAAC,MAAM,CAAC;YACR,OAAO,KAAK,CAAC;QACd,CAAC;IACF,CAAC,CAAC,CAAC;AACL,CAAC;AAED,sFAAsF;AACtF,SAAS,kBAAkB,CAAC,OAAe;IAC1C,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC;QAAE,OAAO,EAAE,CAAC;IACpC,OAAO,WAAW,CAAC,OAAO,CAAC;SACzB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;SAC/C,IAAI,EAAE;SACN,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC;AAChC,CAAC;AAED;;;;;;GAMG;AACH,SAAS,UAAU,CAAC,MAAc,EAAE,QAAgB;IACnD,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC;QAAE,OAAO,SAAS,CAAC;IAC1C,MAAM,IAAI,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAC7C,CAAC,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,CAChC,CAAC;IACF,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IACxC,MAAM,QAAQ,GAAG,GAAG,QAAQ,MAAM,CAAC;IACnC,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAE,CAAC;IACpE,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,6EAA6E;IAC7E,IAAI,CAAC;QACJ,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,IAAI,EAAE;YAAE,OAAO,SAAS,CAAC;IACjD,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,SAAS,CAAC;IAClB,CAAC;IACD,OAAO,IAAI,CAAC;AACb,CAAC;AAuBD,uEAAuE;AACvE,MAAM,CAAC,MAAM,qBAAqB,GAAG,KAAK,CAAC;AAE3C;;;;;;;;;GASG;AACH,MAAM,OAAO,iBAAiB;IACZ,GAAG,CAAoB;IACvB,QAAQ,CAAc;IACtB,OAAO,CAAc;IACrB,cAAc,CAAqB;IACnC,WAAW,CAAS;IAErC,YAAY,OAA0B;QACrC,IAAI,CAAC,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,qBAAqB,CAAC;QAChE,IAAI,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;QACvB,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,KAAK,IAAI,WAAW,CAAC;QAC7C,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,oBAAoB,CAAC;QACvD,IAAI,CAAC,cAAc,GAAG,OAAO,CAAC,cAAc,IAAI,EAAE,CAAC;IACpD,CAAC;IAED,GAAG,CAAC,OAAmB;QACtB,MAAM,CAAC,IAAI,CAAC,GAAG,eAAe,CAAC,IAAI,CAAC,GAAG,CAA0B,CAAC;QAClE,MAAM,IAAI,GAAG;YACZ,UAAU;YACV,OAAO,CAAC,OAAO;YACf,IAAI;YACJ,OAAO,CAAC,QAAQ;YAChB,8EAA8E;YAC9E,GAAG,CAAC,OAAO,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;SAC7D,CAAC;QACF,OAAO,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC;YACrE,EAAE,EAAE,IAAI;YACR,KAAK,EAAE;gBACN,WAAW,EAAE,kBAAkB,CAAC,OAAO,CAAC,OAAO,CAAC;gBAChD,MAAM;gBACN,UAAU;aACV;SACD,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;;;;;;;;;OAUG;IACH;;;;;;;;OAQG;IACH,KAAK,CAAC,OAAqB;QAC1B,MAAM,CAAC,IAAI,CAAC,GAAG,eAAe,CAAC,IAAI,CAAC,GAAG,CAA0B,CAAC;QAClE,MAAM,IAAI,GAAG,CAAC,UAAU,EAAE,OAAO,CAAC,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;QACnE,OAAO,IAAI,CAAC,WAAW,CACtB,IAAI,EACJ,IAAI,EACJ,EAAC,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,UAAU,EAAE,OAAO,CAAC,UAAU,EAAC,EAC5D,CAAC,UAAU,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC;YACxB,EAAE,EAAE,IAAI;YACR,KAAK,EAAE;gBACN,WAAW,EAAE,kBAAkB,CAAC,OAAO,CAAC,OAAO,CAAC;gBAChD,MAAM;gBACN,UAAU;aACV;SACD,CAAC,EACF,EAAC,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,EAAC,CACnE,CAAC;IACH,CAAC;IAED;;;;;;;OAOG;IACH,MAAM,CAAC,OAAsB;QAC5B,MAAM,CAAC,IAAI,CAAC,GAAG,eAAe,CAAC,IAAI,CAAC,GAAG,CAA0B,CAAC;QAClE,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,gBAAgB,CAAC;QACtD,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QAC/C,6EAA6E;QAC7E,2EAA2E;QAC3E,MAAM,IAAI,GAAG,CAAC,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;QAC1D,OAAO,IAAI,CAAC,WAAW,CACtB,IAAI,EACJ,IAAI;QACJ,0EAA0E;QAC1E,uEAAuE;QACvE,EAAC,UAAU,EAAE,OAAO,CAAC,UAAU,EAAC,EAChC,CAAC,WAAW,EAAE,MAAM,EAAE,EAAE;YACvB,MAAM,KAAK,GAAG,kBAAkB,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YACjD,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;YACxD,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;YACpD,OAAO;gBACN,EAAE,EAAE,IAAI;gBACR,KAAK,EAAE;oBACN,QAAQ;oBACR,MAAM;oBACN,KAAK;oBACL,wEAAwE;oBACxE,YAAY,EAAE,+BAA+B,CAAC,IAAI,CAAC,MAAM,CAAC;iBAC1D;aACD,CAAC;QACH,CAAC,CACD,CAAC;IACH,CAAC;IAED,MAAM,CAAC,OAAsB;QAC5B,IAAI,mBAAmB,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YACjD,OAAO,IAAI,CAAC,sBAAsB,CAAC,OAAO,CAAC,CAAC;QAC7C,CAAC;QACD,OAAO,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IAC3C,CAAC;IAED;;;;;;OAMG;IACK,KAAK,CAAC,sBAAsB,CACnC,OAAsB;QAEtB,MAAM,CAAC,IAAI,CAAC,GAAG,eAAe,CAAC,IAAI,CAAC,GAAG,CAA0B,CAAC;QAClE,wEAAwE;QACxE,sEAAsE;QACtE,MAAM,IAAI,GAAG,IAAI,CAAC,cAAc,CAAC,IAAI,IAAI,cAAc,CAAC;QACxD,IAAI,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,SAAS;YAAE,OAAO,aAAa,EAAE,CAAC;QAE/D,MAAM,OAAO,GAAG,MAAM,mBAAmB,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC;QACzE,IAAI,CAAC,OAAO,CAAC,EAAE;YAAE,OAAO,OAAO,CAAC;QAChC,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC;QAC3B,IAAI,CAAC;YACJ,MAAM,GAAG,GAAsB,EAAC,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC,GAAG,EAAC,CAAC;YACxD,MAAM,WAAW,GAAG,GAAG,CAAC,eAAe,CAAC;YACxC,IAAI,WAAW,KAAK,SAAS,IAAI,WAAW,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;gBAC5D,GAAG,CAAC,eAAe,GAAG,OAAO,CAAC;YAC/B,CAAC;YACD,OAAO,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,EAAE;gBACjD,GAAG;gBACH,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC;gBAC7B,uEAAuE;gBACvE,yEAAyE;gBACzE,aAAa,EAAE,EAAE,CAAC,OAAO,KAAK,UAAU;aACxC,CAAC,CAAC;QACJ,CAAC;gBAAS,CAAC;YACV,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC;QACjB,CAAC;IACF,CAAC;IAED,mFAAmF;IAC3E,UAAU,CACjB,OAAsB,EACtB,OAAgC,EAChC,MAIC;QAED,MAAM,CAAC,IAAI,CAAC,GAAG,eAAe,CAAC,IAAI,CAAC,GAAG,CAA0B,CAAC;QAClE,MAAM,QAAQ,GAAG,OAAO,CAAC,WAAW,IAAI,mBAAmB,CAAC;QAC5D,6EAA6E;QAC7E,8EAA8E;QAC9E,4EAA4E;QAC5E,MAAM,IAAI,GAAG,CAAC,YAAY,EAAE,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;QACtE,2EAA2E;QAC3E,yEAAyE;QACzE,MAAM,CAAC,IAAI,CAAC,YAAY,EAAE,EAAE,SAAS,CAAC,EAAE,EAAC,KAAK,EAAE,IAAI,EAAC,CAAC,CAAC;QACvD,OAAO,IAAI,CAAC,WAAW,CACtB,IAAI,EACJ,IAAI,EACJ,EAAC,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,UAAU,EAAE,OAAO,CAAC,UAAU,EAAC,EAC5D,CAAC,UAAU,EAAE,MAAM,EAAE,EAAE;YACtB,MAAM,OAAO,GAAG,UAAU,CAAC,OAAO,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;YACrD,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;gBAC3B,OAAO,EAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,EAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAC,EAAC,CAAC;YAClE,CAAC;YACD,MAAM,YAAY,GAAG,gBAAgB,EAAE,CAAC;YACxC,OAAO;gBACN,EAAE,EAAE,IAAI;gBACR,KAAK,EAAE;oBACN,OAAO;oBACP,MAAM;oBACN,UAAU;oBACV,OAAO;oBACP,WAAW,EAAE,YAAY,CAAC,UAAU,EAAE;wBACrC,UAAU,EAAE,OAAO,CAAC,UAAU;wBAC9B,MAAM,EAAE,OAAO,CAAC,MAAM;wBACtB,QAAQ;qBACR,CAAC;oBACF,GAAG,CAAC,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,EAAC,YAAY,EAAC,CAAC,CAAC,CAAC,EAAE,CAAC;iBACrD;aACD,CAAC;QACH,CAAC,EACD,MAAM,CACN,CAAC;IACH,CAAC;IAED;;;;;;;OAOG;IACK,WAAW,CAClB,IAAY,EACZ,IAAc,EACd,IAA6C,EAC7C,OAAsD,EACtD,SAYC;QAED,MAAM,OAAO,GAAG,IAAI,eAAe,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAEnD,OAAO,IAAI,OAAO,CAAuC,CAAC,OAAO,EAAE,EAAE;YACpE,IAAI,OAAO,GAAG,KAAK,CAAC;YACpB,IAAI,QAAoC,CAAC;YACzC,MAAM,QAAQ,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;YACrC,MAAM,MAAM,GACX,SAAS,EAAE,IAAI,KAAK,SAAS;gBAC5B,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC;gBAChC,CAAC,CAAC,EAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAC,CAAC;YAC3B,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CACzB,MAAM,CAAC,IAAI,EACX,MAAM,CAAC,IAAI,EACX,cAAc,CAAC,SAAS,EAAE,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,EAC1C,EAAC,KAAK,EAAE,SAAS,EAAE,KAAK,EAAC,CACzB,CAAC;YAEF,oEAAoE;YACpE,MAAM,YAAY,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;YACpD,IAAI,QAAkC,CAAC;YAEvC;;;;eAIG;YACH,MAAM,MAAM,GAAG,CAAC,UAAsB,EAAE,IAAI,GAAG,KAAK,EAAQ,EAAE;gBAC7D,IAAI,OAAO;oBAAE,OAAO;gBACpB,OAAO,GAAG,IAAI,CAAC;gBACf,IAAI,QAAQ,KAAK,SAAS;oBAAE,YAAY,CAAC,QAAQ,CAAC,CAAC;gBACnD,IAAI,QAAQ,GAAG,KAAK,CAAC;gBACrB,MAAM,IAAI,GAAG,GAAG,EAAE;oBACjB,IAAI,QAAQ;wBAAE,OAAO;oBACrB,QAAQ,GAAG,IAAI,CAAC;oBAChB,sEAAsE;oBACtE,YAAY,EAAE,CAAC;oBACf,OAAO,CAAC,OAAO,CAAC,UAAU,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;gBAC5C,CAAC,CAAC;gBACF,IAAI,CAAC,IAAI;oBAAE,OAAO,IAAI,EAAE,CAAC;gBACzB,IAAI,SAAS,EAAE,aAAa,KAAK,IAAI,EAAE,CAAC;oBACvC,IAAI,CAAC,IAAI,EAAE,CAAC;oBACZ,OAAO,IAAI,EAAE,CAAC;gBACf,CAAC;gBACD,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;gBACrB,MAAM,IAAI,GAAG,UAAU,CAAC,GAAG,EAAE;oBAC5B,IAAI,CAAC,IAAI,EAAE,CAAC;oBACZ,IAAI,EAAE,CAAC;gBACR,CAAC,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;gBACrB,QAAQ,GAAG,GAAG,EAAE;oBACf,YAAY,CAAC,IAAI,CAAC,CAAC;oBACnB,IAAI,EAAE,CAAC;gBACR,CAAC,CAAC;YACH,CAAC,CAAC;YAEF,IAAI,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE;gBACpB,0EAA0E;gBAC1E,0EAA0E;gBAC1E,gCAAgC;gBAChC,IAAI,OAAO;oBAAE,OAAO;gBACpB,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;oBAC3B,OAAO,GAAG,IAAI,CAAC;oBACf,YAAY,EAAE,CAAC;oBACf,IAAI,QAAQ,KAAK,SAAS;wBAAE,YAAY,CAAC,QAAQ,CAAC,CAAC;oBACnD,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC;gBAC1B,CAAC;qBAAM,CAAC;oBACP,MAAM,CAAC,MAAM,CAAC,CAAC;gBAChB,CAAC;YACF,CAAC,CAAC,CAAC;YAEH,IAAI,CAAC,QAAQ,CAAC,CAAC,KAAK,EAAE,EAAE;gBACvB,yCAAyC;gBACzC,IAAI,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO;oBAAE,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;YAC/D,CAAC,CAAC,CAAC;YAEH,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE;gBACjB,IAAI,QAAQ,KAAK,SAAS;oBAAE,OAAO,QAAQ,EAAE,CAAC;gBAC9C,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,2BAA2B;YAC5C,CAAC,CAAC,CAAC;YAEH,yEAAyE;YACzE,oEAAoE;YACpE,SAAS,EAAE,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC;YAE3B,+DAA+D;YAC/D,QAAQ,GAAG,UAAU,CAAC,GAAG,EAAE;gBAC1B,IAAI,OAAO;oBAAE,OAAO;gBACpB,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;YACzB,CAAC,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;QACrB,CAAC,CAAC,CAAC;IACJ,CAAC;CACD"}
@@ -23,9 +23,9 @@ export type ChildRunner = (file: string, args: string[], env: NodeJS.ProcessEnv)
23
23
  * The default {@link ChildRunner}: an `execFile` that captures stdout/stderr and
24
24
  * NEVER rejects. A failed spawn (ENOENT) becomes `spawnError`; a nonzero exit
25
25
  * becomes a `code`, so both outcomes are data the adapter maps to a structured
26
- * result. The child inherits ONLY the `env` it is handed (the command layer
27
- * passes the incur-resolved env, whose `PATH` a test can override) so there is
28
- * no ambient-environment leak.
26
+ * result. The child gets exactly the `env` it is handed and reads nothing
27
+ * ambiently; the command layer builds that env as the parent env overlaid with
28
+ * the resolved `PATH` (`commands/shrinko-env.ts`), and a test injects its own.
29
29
  */
30
30
  export declare const execFileRunner: ChildRunner;
31
31
  /** Options for {@link ShellShrinkoAdapter}. */
@@ -4,9 +4,9 @@ import { parseCount, parseLint, shrinkoNotFound, } from './adapter.js';
4
4
  * The default {@link ChildRunner}: an `execFile` that captures stdout/stderr and
5
5
  * NEVER rejects. A failed spawn (ENOENT) becomes `spawnError`; a nonzero exit
6
6
  * becomes a `code`, so both outcomes are data the adapter maps to a structured
7
- * result. The child inherits ONLY the `env` it is handed (the command layer
8
- * passes the incur-resolved env, whose `PATH` a test can override) so there is
9
- * no ambient-environment leak.
7
+ * result. The child gets exactly the `env` it is handed and reads nothing
8
+ * ambiently; the command layer builds that env as the parent env overlaid with
9
+ * the resolved `PATH` (`commands/shrinko-env.ts`), and a test injects its own.
10
10
  */
11
11
  export const execFileRunner = (file, args, env) => new Promise((resolve) => {
12
12
  execFile(file, args, { env, encoding: 'utf8' }, (error, stdout, stderr) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "picopilot",
3
- "version": "0.1.5",
3
+ "version": "0.2.1",
4
4
  "description": "An agent-first toolchain for PICO-8 game development, built on the incur CLI framework.",
5
5
  "license": "AGPL-3.0-only",
6
6
  "repository": {
@@ -31,7 +31,7 @@
31
31
  "node": ">=22"
32
32
  },
33
33
  "dependencies": {
34
- "incur": "0.4.10"
34
+ "incur": "0.7.1"
35
35
  },
36
36
  "devDependencies": {
37
37
  "@types/node": "22.12.0",