picopilot 0.1.4 → 0.2.0

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 (172) hide show
  1. package/dist/cli.d.ts.map +1 -1
  2. package/dist/cli.js +111 -16
  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 +61 -44
  7. package/dist/commands/audio.js.map +1 -1
  8. package/dist/commands/cart-includes.d.ts +11 -0
  9. package/dist/commands/cart-includes.d.ts.map +1 -0
  10. package/dist/commands/cart-includes.js +26 -0
  11. package/dist/commands/cart-includes.js.map +1 -0
  12. package/dist/commands/doctor.d.ts +22 -0
  13. package/dist/commands/doctor.d.ts.map +1 -0
  14. package/dist/commands/doctor.js +222 -0
  15. package/dist/commands/doctor.js.map +1 -0
  16. package/dist/commands/export.d.ts +3 -4
  17. package/dist/commands/export.d.ts.map +1 -1
  18. package/dist/commands/export.js +66 -86
  19. package/dist/commands/export.js.map +1 -1
  20. package/dist/commands/gfx.d.ts +2 -2
  21. package/dist/commands/gfx.d.ts.map +1 -1
  22. package/dist/commands/gfx.js +3 -2
  23. package/dist/commands/gfx.js.map +1 -1
  24. package/dist/commands/label-cart.d.ts +72 -0
  25. package/dist/commands/label-cart.d.ts.map +1 -0
  26. package/dist/commands/label-cart.js +228 -0
  27. package/dist/commands/label-cart.js.map +1 -0
  28. package/dist/commands/lint.d.ts +2 -2
  29. package/dist/commands/lint.d.ts.map +1 -1
  30. package/dist/commands/lint.js +3 -2
  31. package/dist/commands/lint.js.map +1 -1
  32. package/dist/commands/minify.d.ts +2 -2
  33. package/dist/commands/minify.d.ts.map +1 -1
  34. package/dist/commands/minify.js +3 -2
  35. package/dist/commands/minify.js.map +1 -1
  36. package/dist/commands/pico8-env.d.ts +76 -0
  37. package/dist/commands/pico8-env.d.ts.map +1 -0
  38. package/dist/commands/pico8-env.js +71 -0
  39. package/dist/commands/pico8-env.js.map +1 -0
  40. package/dist/commands/playtest.d.ts +2 -2
  41. package/dist/commands/playtest.d.ts.map +1 -1
  42. package/dist/commands/playtest.js +6 -32
  43. package/dist/commands/playtest.js.map +1 -1
  44. package/dist/commands/run.d.ts +3 -4
  45. package/dist/commands/run.d.ts.map +1 -1
  46. package/dist/commands/run.js +46 -19
  47. package/dist/commands/run.js.map +1 -1
  48. package/dist/commands/serve.d.ts +2 -2
  49. package/dist/commands/serve.d.ts.map +1 -1
  50. package/dist/commands/serve.js +65 -19
  51. package/dist/commands/serve.js.map +1 -1
  52. package/dist/commands/shrinko-env.d.ts +22 -0
  53. package/dist/commands/shrinko-env.d.ts.map +1 -0
  54. package/dist/commands/shrinko-env.js +15 -0
  55. package/dist/commands/shrinko-env.js.map +1 -0
  56. package/dist/commands/tokens.d.ts +4 -4
  57. package/dist/commands/tokens.d.ts.map +1 -1
  58. package/dist/commands/tokens.js +3 -2
  59. package/dist/commands/tokens.js.map +1 -1
  60. package/dist/commands/verify.d.ts +2 -2
  61. package/dist/commands/verify.d.ts.map +1 -1
  62. package/dist/commands/verify.js +3 -2
  63. package/dist/commands/verify.js.map +1 -1
  64. package/dist/engine/child-env.d.ts +14 -0
  65. package/dist/engine/child-env.d.ts.map +1 -0
  66. package/dist/engine/child-env.js +21 -0
  67. package/dist/engine/child-env.js.map +1 -0
  68. package/dist/engine/gfx/label.d.ts +15 -9
  69. package/dist/engine/gfx/label.d.ts.map +1 -1
  70. package/dist/engine/gfx/label.js +130 -38
  71. package/dist/engine/gfx/label.js.map +1 -1
  72. package/dist/engine/pico8/adapter.d.ts +23 -3
  73. package/dist/engine/pico8/adapter.d.ts.map +1 -1
  74. package/dist/engine/pico8/adapter.js.map +1 -1
  75. package/dist/engine/pico8/cleanup.d.ts +16 -0
  76. package/dist/engine/pico8/cleanup.d.ts.map +1 -0
  77. package/dist/engine/pico8/cleanup.js +74 -0
  78. package/dist/engine/pico8/cleanup.js.map +1 -0
  79. package/dist/engine/pico8/display.d.ts +149 -0
  80. package/dist/engine/pico8/display.d.ts.map +1 -0
  81. package/dist/engine/pico8/display.js +311 -0
  82. package/dist/engine/pico8/display.js.map +1 -0
  83. package/dist/engine/pico8/drive.d.ts.map +1 -1
  84. package/dist/engine/pico8/drive.js +28 -2
  85. package/dist/engine/pico8/drive.js.map +1 -1
  86. package/dist/engine/pico8/harness.d.ts +8 -0
  87. package/dist/engine/pico8/harness.d.ts.map +1 -1
  88. package/dist/engine/pico8/harness.js +9 -1
  89. package/dist/engine/pico8/harness.js.map +1 -1
  90. package/dist/engine/pico8/index.d.ts +3 -0
  91. package/dist/engine/pico8/index.d.ts.map +1 -1
  92. package/dist/engine/pico8/index.js +3 -0
  93. package/dist/engine/pico8/index.js.map +1 -1
  94. package/dist/engine/pico8/session-daemon-entry.d.ts +1 -1
  95. package/dist/engine/pico8/session-daemon-entry.js +1 -1
  96. package/dist/engine/pico8/session-daemon-main.d.ts +1 -1
  97. package/dist/engine/pico8/session-daemon-main.js +1 -1
  98. package/dist/engine/pico8/session-daemon.d.ts +1 -1
  99. package/dist/engine/pico8/session-daemon.d.ts.map +1 -1
  100. package/dist/engine/pico8/session-daemon.js +19 -19
  101. package/dist/engine/pico8/session-daemon.js.map +1 -1
  102. package/dist/engine/pico8/session.d.ts +1 -1
  103. package/dist/engine/pico8/session.js +1 -1
  104. package/dist/engine/pico8/shell.d.ts +56 -3
  105. package/dist/engine/pico8/shell.d.ts.map +1 -1
  106. package/dist/engine/pico8/shell.js +188 -24
  107. package/dist/engine/pico8/shell.js.map +1 -1
  108. package/dist/engine/pico8/supervisor.d.ts +1 -1
  109. package/dist/engine/pico8/supervisor.js +1 -1
  110. package/dist/engine/shrinko/adapter.d.ts +1 -1
  111. package/dist/engine/shrinko/shell.d.ts +3 -3
  112. package/dist/engine/shrinko/shell.js +3 -3
  113. package/package.json +2 -1
  114. package/src/cli.test.ts +188 -0
  115. package/src/cli.ts +122 -16
  116. package/src/commands/audio.test.ts +76 -1
  117. package/src/commands/audio.ts +79 -57
  118. package/src/commands/cart-includes.ts +27 -0
  119. package/src/commands/doctor.test.ts +149 -0
  120. package/src/commands/doctor.ts +280 -0
  121. package/src/commands/export.test.ts +327 -3
  122. package/src/commands/export.ts +81 -99
  123. package/src/commands/gfx.ts +7 -6
  124. package/src/commands/label-cart.ts +304 -0
  125. package/src/commands/lint.test.ts +6 -0
  126. package/src/commands/lint.ts +7 -6
  127. package/src/commands/minify.test.ts +6 -0
  128. package/src/commands/minify.ts +7 -6
  129. package/src/commands/pico8-env.ts +124 -0
  130. package/src/commands/playtest.test.ts +3 -0
  131. package/src/commands/playtest.ts +10 -34
  132. package/src/commands/run.test.ts +116 -2
  133. package/src/commands/run.ts +62 -24
  134. package/src/commands/serve.test.ts +138 -2
  135. package/src/commands/serve.ts +80 -21
  136. package/src/commands/shrinko-env.test.ts +68 -0
  137. package/src/commands/shrinko-env.ts +40 -0
  138. package/src/commands/tokens.test.ts +19 -0
  139. package/src/commands/tokens.ts +9 -6
  140. package/src/commands/verify.test.ts +12 -0
  141. package/src/commands/verify.ts +7 -4
  142. package/src/engine/child-env.ts +22 -0
  143. package/src/engine/gfx/fixtures/pico8-screenshot-384.png +0 -0
  144. package/src/engine/gfx/label.test.ts +467 -1
  145. package/src/engine/gfx/label.ts +147 -41
  146. package/src/engine/pico8/adapter.ts +25 -3
  147. package/src/engine/pico8/cleanup.test.ts +28 -0
  148. package/src/engine/pico8/cleanup.ts +76 -0
  149. package/src/engine/pico8/display.test.ts +210 -0
  150. package/src/engine/pico8/display.ts +429 -0
  151. package/src/engine/pico8/drive.test.ts +20 -0
  152. package/src/engine/pico8/drive.ts +25 -2
  153. package/src/engine/pico8/fake-xvfb.test-support.ts +55 -0
  154. package/src/engine/pico8/harness.test.ts +26 -0
  155. package/src/engine/pico8/harness.ts +18 -2
  156. package/src/engine/pico8/index.ts +3 -0
  157. package/src/engine/pico8/session-daemon-entry.ts +1 -1
  158. package/src/engine/pico8/session-daemon-main.ts +1 -1
  159. package/src/engine/pico8/session-daemon.test.ts +32 -1
  160. package/src/engine/pico8/session-daemon.ts +25 -17
  161. package/src/engine/pico8/session.test.ts +1 -1
  162. package/src/engine/pico8/session.ts +1 -1
  163. package/src/engine/pico8/shell.test.ts +449 -10
  164. package/src/engine/pico8/shell.ts +255 -26
  165. package/src/engine/pico8/supervisor.ts +1 -1
  166. package/src/engine/pico8/virtual-display.process.test.ts +206 -0
  167. package/src/engine/shrinko/adapter.ts +1 -1
  168. package/src/engine/shrinko/shell.ts +3 -3
  169. package/src/engine/skills/skills.test.ts +10 -0
  170. package/src/skills/picopilot-audio/SKILL.md +4 -8
  171. package/src/skills/picopilot-debug/SKILL.md +18 -1
  172. package/src/skills/picopilot-overview/SKILL.md +9 -1
@@ -0,0 +1,72 @@
1
+ import { type DriveOptions, type Pico8DriveResult } from '../engine/pico8/index.js';
2
+ /**
3
+ * The remedy for both label-image errors (`label-wrong-size`,
4
+ * `label-unsupported-png`): the screenshot `run`/`playtest` already wrote is a
5
+ * valid label as-is, so point at that rather than at an external image tool.
6
+ */
7
+ export declare const LABEL_FIX_CTA: {
8
+ description: string;
9
+ commands: {
10
+ command: string;
11
+ description: string;
12
+ }[];
13
+ };
14
+ /** Where the exported cart's `__label__` came from. */
15
+ export type LabelSource = 'cart' | 'image' | 'frame' | 'none';
16
+ /** A cart ready to hand to PICO-8's export, plus how to tidy up after it. */
17
+ export interface LabeledCart {
18
+ readonly ok: true;
19
+ /** The cart to export: the original, or a labeled throwaway copy. */
20
+ readonly cartPath: string;
21
+ /**
22
+ * Where the label comes from: the cart's own (`cart`), `--label` (`image`),
23
+ * `--label-frame` (`frame`), or nowhere (`none`, the cart stays labelless).
24
+ */
25
+ readonly labelSource: LabelSource;
26
+ /** Removes the throwaway copy (if one was made). Best-effort, idempotent. */
27
+ readonly cleanup: () => void;
28
+ }
29
+ /** A label-preparation failure, shaped for incur's `error({...})`. */
30
+ export interface LabelCartFailure {
31
+ readonly ok: false;
32
+ readonly code: string;
33
+ readonly message: string;
34
+ readonly cta?: {
35
+ description: string;
36
+ commands: {
37
+ command: string;
38
+ description: string;
39
+ }[];
40
+ };
41
+ }
42
+ /** The label flags `export` and `serve` share. */
43
+ export interface LabelOptions {
44
+ /** `--label <png>`: an image (a run/playtest screenshot as-is, or 128x128). */
45
+ readonly label?: string;
46
+ /** `--label-frame <n>`: capture frame `n` of the running cart, no input. */
47
+ readonly labelFrame?: number;
48
+ /** The backstop for the `--label-frame` capture run. */
49
+ readonly backstopMs: number;
50
+ }
51
+ /**
52
+ * The `--label` / `--label-frame` step shared by `export` and `serve` (ADR-0013,
53
+ * ADR-0015, ADR-0016): give a labelless cart a `__label__` (the export splash)
54
+ * without an interactive F7 capture.
55
+ *
56
+ * - `--label <png>`: decode an image (a `run`/`playtest` screenshot as-is, any
57
+ * square integer multiple of 128x128, or any 128x128 PNG).
58
+ * - `--label-frame <n>`: RUN the cart headlessly through the playtest drive
59
+ * harness (ADR-0011) with NO input, advance `n` frames, screenshot that frame,
60
+ * and decode it. Needs PICO-8 (`drive`); an arbitrary cart does not have to
61
+ * cooperate, since the harness owns its frame loop.
62
+ *
63
+ * The two flags are mutually exclusive (`label-flags-conflict`). The user's cart
64
+ * is NEVER mutated: a labeled copy is written NEXT TO it (same dir, so
65
+ * `#include main.lua` still resolves) and the caller exports that, then calls
66
+ * `cleanup()`. A cart that ALREADY has a label wins (the flags are a fallback,
67
+ * not an override): it is returned untouched and nothing is run.
68
+ *
69
+ * @param drive the adapter's `drive`, only called for `--label-frame`.
70
+ */
71
+ export declare function prepareLabeledCart(cartPath: string, options: LabelOptions, drive: (options: DriveOptions) => Promise<Pico8DriveResult>): Promise<LabeledCart | LabelCartFailure>;
72
+ //# sourceMappingURL=label-cart.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"label-cart.d.ts","sourceRoot":"","sources":["../../src/commands/label-cart.ts"],"names":[],"mappings":"AAWA,OAAO,EAGN,KAAK,YAAY,EACjB,KAAK,gBAAgB,EACrB,MAAM,0BAA0B,CAAC;AAGlC;;;;GAIG;AACH,eAAO,MAAM,aAAa;;;;;;CAezB,CAAC;AAEF,uDAAuD;AACvD,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,GAAG,MAAM,CAAC;AAE9D,6EAA6E;AAC7E,MAAM,WAAW,WAAW;IAC3B,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAClB,qEAAqE;IACrE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B;;;OAGG;IACH,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC;IAClC,6EAA6E;IAC7E,QAAQ,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC;CAC7B;AAED,sEAAsE;AACtE,MAAM,WAAW,gBAAgB;IAChC,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IACnB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,GAAG,CAAC,EAAE;QACd,WAAW,EAAE,MAAM,CAAC;QACpB,QAAQ,EAAE;YAAC,OAAO,EAAE,MAAM,CAAC;YAAC,WAAW,EAAE,MAAM,CAAA;SAAC,EAAE,CAAC;KACnD,CAAC;CACF;AAED,kDAAkD;AAClD,MAAM,WAAW,YAAY;IAC5B,+EAA+E;IAC/E,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,4EAA4E;IAC5E,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,wDAAwD;IACxD,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC5B;AAKD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,kBAAkB,CACvC,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,YAAY,EACrB,KAAK,EAAE,CAAC,OAAO,EAAE,YAAY,KAAK,OAAO,CAAC,gBAAgB,CAAC,GACzD,OAAO,CAAC,WAAW,GAAG,gBAAgB,CAAC,CAwGzC"}
@@ -0,0 +1,228 @@
1
+ import { existsSync, mkdtempSync, readFileSync, rmSync, writeFileSync, } from 'node:fs';
2
+ import { tmpdir } from 'node:os';
3
+ import { dirname, isAbsolute, join, resolve } from 'node:path';
4
+ import { Cart, CartParseError } from '../engine/cart/index.js';
5
+ import { labelHexFromPng, LabelError } from '../engine/gfx/index.js';
6
+ import { buildDriveHarness, DriveError, } from '../engine/pico8/index.js';
7
+ import { makeReadInclude } from './cart-includes.js';
8
+ /**
9
+ * The remedy for both label-image errors (`label-wrong-size`,
10
+ * `label-unsupported-png`): the screenshot `run`/`playtest` already wrote is a
11
+ * valid label as-is, so point at that rather than at an external image tool.
12
+ */
13
+ export const LABEL_FIX_CTA = {
14
+ description: 'Pass a picopilot screenshot directly; it is scaled for you (any 128*k square: 128x128, 256x256, 384x384, ...). No image tool needed:',
15
+ commands: [
16
+ {
17
+ command: 'run <cart> --shot-dir shots',
18
+ description: 'Capture a frame (the cart calls extcmd("screen")), then pass shots/<name>.png to --label unchanged.',
19
+ },
20
+ {
21
+ command: 'export <cart> <dest> --label shots/<name>.png',
22
+ description: 'Bake that screenshot in as the label splash (`serve --label` takes it the same way). playtest screenshots work too.',
23
+ },
24
+ ],
25
+ };
26
+ /** The base filename the `--label-frame` capture names its screenshot. */
27
+ const LABEL_FRAME_BASENAME = 'label';
28
+ /**
29
+ * The `--label` / `--label-frame` step shared by `export` and `serve` (ADR-0013,
30
+ * ADR-0015, ADR-0016): give a labelless cart a `__label__` (the export splash)
31
+ * without an interactive F7 capture.
32
+ *
33
+ * - `--label <png>`: decode an image (a `run`/`playtest` screenshot as-is, any
34
+ * square integer multiple of 128x128, or any 128x128 PNG).
35
+ * - `--label-frame <n>`: RUN the cart headlessly through the playtest drive
36
+ * harness (ADR-0011) with NO input, advance `n` frames, screenshot that frame,
37
+ * and decode it. Needs PICO-8 (`drive`); an arbitrary cart does not have to
38
+ * cooperate, since the harness owns its frame loop.
39
+ *
40
+ * The two flags are mutually exclusive (`label-flags-conflict`). The user's cart
41
+ * is NEVER mutated: a labeled copy is written NEXT TO it (same dir, so
42
+ * `#include main.lua` still resolves) and the caller exports that, then calls
43
+ * `cleanup()`. A cart that ALREADY has a label wins (the flags are a fallback,
44
+ * not an override): it is returned untouched and nothing is run.
45
+ *
46
+ * @param drive the adapter's `drive`, only called for `--label-frame`.
47
+ */
48
+ export async function prepareLabeledCart(cartPath, options, drive) {
49
+ const keep = (labelSource) => ({
50
+ ok: true,
51
+ cartPath,
52
+ labelSource,
53
+ cleanup: () => { },
54
+ });
55
+ if (options.label !== undefined && options.labelFrame !== undefined) {
56
+ return {
57
+ ok: false,
58
+ code: 'label-flags-conflict',
59
+ message: 'pass either --label <png> (an image) or --label-frame <n> (capture a frame of the running cart), not both',
60
+ };
61
+ }
62
+ // With no label flag the cart is only read to REPORT `labelSource`; anything
63
+ // odd about it (unreadable, unparseable) is left for PICO-8 to judge, exactly
64
+ // as before the label flags existed.
65
+ const noFlag = options.label === undefined && options.labelFrame === undefined;
66
+ let cart;
67
+ try {
68
+ cart = Cart.parse(readFileSync(cartPath, 'utf8'));
69
+ }
70
+ catch (e) {
71
+ if (noFlag)
72
+ return keep('none');
73
+ if (e instanceof CartParseError) {
74
+ return {
75
+ ok: false,
76
+ code: `cart-${e.code}`,
77
+ message: `could not parse the cart to inject a label: ${e.message}`,
78
+ };
79
+ }
80
+ throw e;
81
+ }
82
+ const existingLabel = cart.getSection('label');
83
+ if (existingLabel !== undefined && existingLabel.trim() !== '') {
84
+ return keep('cart');
85
+ }
86
+ let png;
87
+ let labelSource;
88
+ if (options.label !== undefined) {
89
+ const labelPath = isAbsolute(options.label)
90
+ ? options.label
91
+ : resolve(process.cwd(), options.label);
92
+ if (!existsSync(labelPath)) {
93
+ return {
94
+ ok: false,
95
+ code: 'label-not-found',
96
+ message: `no label image at ${labelPath}`,
97
+ };
98
+ }
99
+ png = readFileSync(labelPath);
100
+ labelSource = 'image';
101
+ }
102
+ else if (options.labelFrame !== undefined) {
103
+ const captured = await captureFrame(cartPath, options.labelFrame, options.backstopMs, drive);
104
+ if (!captured.ok)
105
+ return captured;
106
+ png = captured.png;
107
+ labelSource = 'frame';
108
+ }
109
+ else {
110
+ return keep('none');
111
+ }
112
+ let hex;
113
+ try {
114
+ hex = labelHexFromPng(png);
115
+ }
116
+ catch (e) {
117
+ if (e instanceof LabelError) {
118
+ return {
119
+ ok: false,
120
+ code: `label-${e.code}`,
121
+ message: e.message,
122
+ cta: LABEL_FIX_CTA,
123
+ };
124
+ }
125
+ throw e;
126
+ }
127
+ cart.setSection('label', hex);
128
+ const copy = join(dirname(cartPath), `.picopilot-export-${process.pid}-${Date.now()}.p8`);
129
+ writeFileSync(copy, cart.serialize());
130
+ return {
131
+ ok: true,
132
+ cartPath: copy,
133
+ labelSource,
134
+ cleanup: () => {
135
+ try {
136
+ rmSync(copy, { force: true });
137
+ }
138
+ catch {
139
+ // A leftover dotfile is not fatal.
140
+ }
141
+ },
142
+ };
143
+ }
144
+ /**
145
+ * Runs the cart through the playtest drive harness with NO input for `frame + 1`
146
+ * frames, screenshotting after frame `frame` (0 = the first drawn frame), and
147
+ * returns that PNG. The driven cart and PICO-8's screenshot dir live in a temp
148
+ * dir that is removed before returning.
149
+ */
150
+ async function captureFrame(cartPath, frame, backstopMs, drive) {
151
+ let harness;
152
+ try {
153
+ harness = buildDriveHarness(readFileSync(cartPath, 'utf8'), {
154
+ presses: [],
155
+ frames: frame + 1,
156
+ shotFrames: [frame],
157
+ shotBasename: LABEL_FRAME_BASENAME,
158
+ readInclude: makeReadInclude(cartPath),
159
+ });
160
+ }
161
+ catch (e) {
162
+ if (e instanceof DriveError) {
163
+ return { ok: false, code: e.code, message: e.message };
164
+ }
165
+ throw e;
166
+ }
167
+ const shotDir = mkdtempSync(join(tmpdir(), 'picopilot-label-frame-'));
168
+ try {
169
+ const drivenCart = join(shotDir, 'driven.p8');
170
+ writeFileSync(drivenCart, harness.cartText);
171
+ const result = await drive({
172
+ cartPath: drivenCart,
173
+ shotDir,
174
+ blocks: harness.blocks,
175
+ backstopMs,
176
+ });
177
+ if (!result.ok) {
178
+ return {
179
+ ok: false,
180
+ code: result.reason,
181
+ message: `PICO-8 is not installed, so --label-frame cannot capture a frame. ${result.remedy} (needs: ${result.needs.join(', ')})`,
182
+ };
183
+ }
184
+ const shot = result.value.screenshots[0];
185
+ if (shot === undefined) {
186
+ const { exitReason } = result.value;
187
+ const tail = result.value.printh.trim().split('\n').slice(-5).join('\n');
188
+ const commands = [
189
+ {
190
+ command: 'verify',
191
+ description: 'Run the static gate (tokens + lint + integrity).',
192
+ },
193
+ {
194
+ command: 'playtest start <cart>',
195
+ description: 'Reproduce the SAME no-input frame to look at it: start a paused session (nothing held), then step and shoot.',
196
+ },
197
+ {
198
+ command: `playtest step <id> --frames ${frame + 1}`,
199
+ description: `Advance to frame ${frame}, as --label-frame ${frame} does.`,
200
+ },
201
+ {
202
+ command: 'playtest shot <id>',
203
+ description: 'Screenshot it; if it looks right, pass that PNG with --label <png> (then `playtest stop <id>`).',
204
+ },
205
+ ];
206
+ if (exitReason === 'timeout') {
207
+ commands.push({
208
+ command: `export <cart> --label-frame ${frame} --backstop-ms <more>`,
209
+ description: 'The capture hit the backstop (it runs about one frame per PICO-8 tick): allow more time, or pick an earlier frame.',
210
+ });
211
+ }
212
+ return {
213
+ ok: false,
214
+ code: 'label-frame-not-captured',
215
+ message: `the cart produced no frame ${frame} screenshot (exit: ${exitReason}).${tail === '' ? '' : ` Last output:\n${tail}`}`,
216
+ cta: {
217
+ description: 'The cart did not reach that frame. Check it boots, or look at the frame first:',
218
+ commands,
219
+ },
220
+ };
221
+ }
222
+ return { ok: true, png: readFileSync(shot) };
223
+ }
224
+ finally {
225
+ rmSync(shotDir, { recursive: true, force: true });
226
+ }
227
+ }
228
+ //# sourceMappingURL=label-cart.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"label-cart.js","sourceRoot":"","sources":["../../src/commands/label-cart.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  import { type Cli } from 'incur';
2
- import { type ShrinkoAdapter } from '../engine/shrinko/index.js';
2
+ import { type ShrinkoAdapterFactory } from './shrinko-env.js';
3
3
  /** See {@link import('./tokens.js').ShrinkoAdapterFactory}: lint reuses the same seam. */
4
- export type ShrinkoAdapterFactory = (env: NodeJS.ProcessEnv) => ShrinkoAdapter;
4
+ export type { ShrinkoAdapterFactory } from './shrinko-env.js';
5
5
  /**
6
6
  * Registers `picopilot lint` (US #4): surface PICO-8-specific issues (undefined
7
7
  * globals, unused/duplicate locals, and, via the parsed findings, the classic
@@ -1 +1 @@
1
- {"version":3,"file":"lint.d.ts","sourceRoot":"","sources":["../../src/commands/lint.ts"],"names":[],"mappings":"AAEA,OAAO,EAAC,KAAK,GAAG,EAAI,MAAM,OAAO,CAAC;AAClC,OAAO,EACN,KAAK,cAAc,EAEnB,MAAM,4BAA4B,CAAC;AAEpC,0FAA0F;AAC1F,MAAM,MAAM,qBAAqB,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,KAAK,cAAc,CAAC;AAK/E;;;;;;;;;;;;;GAaG;AACH,wBAAgB,YAAY,CAC3B,GAAG,EAAE,GAAG,CAAC,GAAG,EACZ,cAAc,GAAE,qBAA6C,GAC3D,IAAI,CAqFN"}
1
+ {"version":3,"file":"lint.d.ts","sourceRoot":"","sources":["../../src/commands/lint.ts"],"names":[],"mappings":"AAEA,OAAO,EAAC,KAAK,GAAG,EAAI,MAAM,OAAO,CAAC;AAElC,OAAO,EAEN,KAAK,qBAAqB,EAC1B,MAAM,kBAAkB,CAAC;AAE1B,0FAA0F;AAC1F,YAAY,EAAC,qBAAqB,EAAC,MAAM,kBAAkB,CAAC;AAK5D;;;;;;;;;;;;;GAaG;AACH,wBAAgB,YAAY,CAC3B,GAAG,EAAE,GAAG,CAAC,GAAG,EACZ,cAAc,GAAE,qBAA6C,GAC3D,IAAI,CAqFN"}
@@ -1,8 +1,9 @@
1
1
  import { existsSync } from 'node:fs';
2
2
  import { isAbsolute, resolve } from 'node:path';
3
3
  import { z } from 'incur';
4
- import { ShellShrinkoAdapter, } from '../engine/shrinko/index.js';
5
- const defaultAdapterFactory = (env) => new ShellShrinkoAdapter({ env });
4
+ import {} from '../engine/shrinko/index.js';
5
+ import { createShellShrinkoFactory, } from './shrinko-env.js';
6
+ const defaultAdapterFactory = createShellShrinkoFactory();
6
7
  /**
7
8
  * Registers `picopilot lint` (US #4): surface PICO-8-specific issues (undefined
8
9
  * globals, unused/duplicate locals, and, via the parsed findings, the classic
@@ -1 +1 @@
1
- {"version":3,"file":"lint.js","sourceRoot":"","sources":["../../src/commands/lint.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"lint.js","sourceRoot":"","sources":["../../src/commands/lint.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  import { type Cli } from 'incur';
2
- import { type ShrinkoAdapter } from '../engine/shrinko/index.js';
2
+ import { type ShrinkoAdapterFactory } from './shrinko-env.js';
3
3
  /** See {@link import('./tokens.js').ShrinkoAdapterFactory}: minify reuses the same seam. */
4
- export type ShrinkoAdapterFactory = (env: NodeJS.ProcessEnv) => ShrinkoAdapter;
4
+ export type { ShrinkoAdapterFactory } from './shrinko-env.js';
5
5
  /**
6
6
  * Registers `picopilot minify` (US #5, ADR-0007): run shrinko8's SAFE
7
7
  * minification and write the result to a SEPARATE artifact (`<name>.min.p8` by
@@ -1 +1 @@
1
- {"version":3,"file":"minify.d.ts","sourceRoot":"","sources":["../../src/commands/minify.ts"],"names":[],"mappings":"AAEA,OAAO,EAAC,KAAK,GAAG,EAAI,MAAM,OAAO,CAAC;AAClC,OAAO,EACN,KAAK,cAAc,EAEnB,MAAM,4BAA4B,CAAC;AAEpC,4FAA4F;AAC5F,MAAM,MAAM,qBAAqB,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,KAAK,cAAc,CAAC;AAoB/E;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,CAC7B,GAAG,EAAE,GAAG,CAAC,GAAG,EACZ,cAAc,GAAE,qBAA6C,GAC3D,IAAI,CA6GN"}
1
+ {"version":3,"file":"minify.d.ts","sourceRoot":"","sources":["../../src/commands/minify.ts"],"names":[],"mappings":"AAEA,OAAO,EAAC,KAAK,GAAG,EAAI,MAAM,OAAO,CAAC;AAElC,OAAO,EAEN,KAAK,qBAAqB,EAC1B,MAAM,kBAAkB,CAAC;AAE1B,4FAA4F;AAC5F,YAAY,EAAC,qBAAqB,EAAC,MAAM,kBAAkB,CAAC;AAoB5D;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,CAC7B,GAAG,EAAE,GAAG,CAAC,GAAG,EACZ,cAAc,GAAE,qBAA6C,GAC3D,IAAI,CA6GN"}
@@ -1,8 +1,9 @@
1
1
  import { existsSync } from 'node:fs';
2
2
  import { dirname, isAbsolute, join, resolve } from 'node:path';
3
3
  import { z } from 'incur';
4
- import { ShellShrinkoAdapter, } from '../engine/shrinko/index.js';
5
- const defaultAdapterFactory = (env) => new ShellShrinkoAdapter({ env });
4
+ import {} from '../engine/shrinko/index.js';
5
+ import { createShellShrinkoFactory, } from './shrinko-env.js';
6
+ const defaultAdapterFactory = createShellShrinkoFactory();
6
7
  /**
7
8
  * Derives the default output path `<name>.min.p8` next to the source cart:
8
9
  * `main.p8` -> `main.min.p8`, `game.p8.png` -> `game.min.p8.png` is NOT the
@@ -1 +1 @@
1
- {"version":3,"file":"minify.js","sourceRoot":"","sources":["../../src/commands/minify.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"minify.js","sourceRoot":"","sources":["../../src/commands/minify.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,76 @@
1
+ import { z } from 'incur';
2
+ import { type DisplayMode, type Pico8Adapter, type SpawnRunner, type VirtualDisplayDeps } from '../engine/pico8/index.js';
3
+ /**
4
+ * The env schema every PICO-8-gated command declares. These are the values
5
+ * picopilot itself RESOLVES (incur reads them from its env source, which tests
6
+ * override); they are NOT the whole child environment. The child gets the
7
+ * parent environment with these overlaid ({@link pico8ChildEnv}), so PICO-8
8
+ * still sees DISPLAY, HOME, XDG_RUNTIME_DIR, SDL_* and the rest.
9
+ */
10
+ export declare const PICO8_ENV: z.ZodObject<{
11
+ PICO8_PATH: z.ZodOptional<z.ZodString>;
12
+ PATH: z.ZodOptional<z.ZodString>;
13
+ }, z.core.$strip>;
14
+ /** What a command knows beyond the env when it builds an adapter. */
15
+ export interface Pico8AdapterContext {
16
+ /** The resolved display mode for `-run` sessions (ADR-0017). */
17
+ readonly display: DisplayMode;
18
+ }
19
+ /**
20
+ * Injects the PICO-8 adapter a command uses. A test passes a stub to drive the
21
+ * sentinel/backstop/absent paths without the paid binary; the default is
22
+ * {@link createShellAdapterFactory}.
23
+ */
24
+ export type Pico8AdapterFactory = (env: NodeJS.ProcessEnv, context?: Pico8AdapterContext) => Pico8Adapter;
25
+ /** Dependencies for {@link createShellAdapterFactory}, injectable for tests. */
26
+ export interface ShellAdapterFactoryDeps {
27
+ /** The parent environment PICO-8 inherits (defaults to `process.env`). */
28
+ readonly parentEnv?: NodeJS.ProcessEnv;
29
+ /** The PICO-8 spawn seam (defaults to the real spawn). */
30
+ readonly spawn?: SpawnRunner;
31
+ /** The virtual-display seam (Xvfb lookup + spawn). */
32
+ readonly virtualDisplay?: VirtualDisplayDeps;
33
+ }
34
+ /**
35
+ * The default adapter factory: the shell adapter over the user's PICO-8, with
36
+ * the child env = parent env + the command's resolved values, and the display
37
+ * mode from the context.
38
+ */
39
+ export declare function createShellAdapterFactory(deps?: ShellAdapterFactoryDeps): Pico8AdapterFactory;
40
+ /**
41
+ * The display mode a command handler sees. The root middleware in `createCli`
42
+ * resolves it (flag > env > config > default) into the `display` var; a command
43
+ * mounted on a bare CLI (some tests) has no var and gets the default.
44
+ */
45
+ export declare function displayModeOf(vars: unknown): DisplayMode;
46
+ /**
47
+ * The `error(...)` payload for a `display-unavailable` result (ADR-0017): the
48
+ * session needs a display, there is none, and no Xvfb is installed to provide a
49
+ * virtual one. The message and CTA name the fix, so the agent never has to
50
+ * discover it by a silent timeout.
51
+ */
52
+ export declare function displayUnavailableError(what: string, result: {
53
+ detail: string;
54
+ remedy: string;
55
+ }): {
56
+ code: "display-unavailable";
57
+ message: string;
58
+ exitCode: number;
59
+ cta: {
60
+ description: string;
61
+ commands: {
62
+ command: string;
63
+ description: string;
64
+ }[];
65
+ };
66
+ };
67
+ /** The `error(...)` payload for a `pico8-not-found` result (the exact remedy + needs). */
68
+ export declare function pico8NotFoundError(result: {
69
+ remedy: string;
70
+ needs: readonly string[];
71
+ }): {
72
+ code: "pico8-not-found";
73
+ message: string;
74
+ exitCode: number;
75
+ };
76
+ //# sourceMappingURL=pico8-env.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pico8-env.d.ts","sourceRoot":"","sources":["../../src/commands/pico8-env.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,CAAC,EAAC,MAAM,OAAO,CAAC;AACxB,OAAO,EAEN,KAAK,WAAW,EAEhB,KAAK,YAAY,EAGjB,KAAK,WAAW,EAChB,KAAK,kBAAkB,EACvB,MAAM,0BAA0B,CAAC;AAElC;;;;;;GAMG;AACH,eAAO,MAAM,SAAS;;;iBAMpB,CAAC;AAEH,qEAAqE;AACrE,MAAM,WAAW,mBAAmB;IACnC,gEAAgE;IAChE,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;CAC9B;AAED;;;;GAIG;AACH,MAAM,MAAM,mBAAmB,GAAG,CACjC,GAAG,EAAE,MAAM,CAAC,UAAU,EACtB,OAAO,CAAC,EAAE,mBAAmB,KACzB,YAAY,CAAC;AAElB,gFAAgF;AAChF,MAAM,WAAW,uBAAuB;IACvC,0EAA0E;IAC1E,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACvC,0DAA0D;IAC1D,QAAQ,CAAC,KAAK,CAAC,EAAE,WAAW,CAAC;IAC7B,sDAAsD;IACtD,QAAQ,CAAC,cAAc,CAAC,EAAE,kBAAkB,CAAC;CAC7C;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CACxC,IAAI,GAAE,uBAA4B,GAChC,mBAAmB,CAWrB;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,OAAO,GAAG,WAAW,CAMxD;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CACtC,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAC;;;;;;;;;;;EAiBxC;AAED,0FAA0F;AAC1F,wBAAgB,kBAAkB,CAAC,MAAM,EAAE;IAC1C,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;CACzB;;;;EAMA"}
@@ -0,0 +1,71 @@
1
+ import { z } from 'incur';
2
+ import { DEFAULT_DISPLAY_MODE, isDisplayMode, pico8ChildEnv, ShellPico8Adapter, } from '../engine/pico8/index.js';
3
+ /**
4
+ * The env schema every PICO-8-gated command declares. These are the values
5
+ * picopilot itself RESOLVES (incur reads them from its env source, which tests
6
+ * override); they are NOT the whole child environment. The child gets the
7
+ * parent environment with these overlaid ({@link pico8ChildEnv}), so PICO-8
8
+ * still sees DISPLAY, HOME, XDG_RUNTIME_DIR, SDL_* and the rest.
9
+ */
10
+ export const PICO8_ENV = z.object({
11
+ PICO8_PATH: z
12
+ .string()
13
+ .optional()
14
+ .describe('Explicit path to the PICO-8 binary (else `pico8` on PATH).'),
15
+ PATH: z.string().optional().describe('Used to locate `pico8`.'),
16
+ });
17
+ /**
18
+ * The default adapter factory: the shell adapter over the user's PICO-8, with
19
+ * the child env = parent env + the command's resolved values, and the display
20
+ * mode from the context.
21
+ */
22
+ export function createShellAdapterFactory(deps = {}) {
23
+ return (env, context) => new ShellPico8Adapter({
24
+ env: pico8ChildEnv(env, deps.parentEnv ?? process.env),
25
+ spawn: deps.spawn,
26
+ display: context?.display ?? DEFAULT_DISPLAY_MODE,
27
+ virtualDisplay: deps.virtualDisplay,
28
+ });
29
+ }
30
+ /**
31
+ * The display mode a command handler sees. The root middleware in `createCli`
32
+ * resolves it (flag > env > config > default) into the `display` var; a command
33
+ * mounted on a bare CLI (some tests) has no var and gets the default.
34
+ */
35
+ export function displayModeOf(vars) {
36
+ const value = vars !== null && typeof vars === 'object'
37
+ ? vars.display
38
+ : undefined;
39
+ return isDisplayMode(value) ? value : DEFAULT_DISPLAY_MODE;
40
+ }
41
+ /**
42
+ * The `error(...)` payload for a `display-unavailable` result (ADR-0017): the
43
+ * session needs a display, there is none, and no Xvfb is installed to provide a
44
+ * virtual one. The message and CTA name the fix, so the agent never has to
45
+ * discover it by a silent timeout.
46
+ */
47
+ export function displayUnavailableError(what, result) {
48
+ return {
49
+ code: 'display-unavailable',
50
+ message: `${what} needs a display (a real audio+video -run session): ${result.detail}. Remedy: ${result.remedy}.`,
51
+ exitCode: 1,
52
+ cta: {
53
+ description: `No display and no Xvfb on this machine. Fix: ${result.remedy}. Then re-run; picopilot starts a private virtual display by itself (--display auto). Check what this machine can do:`,
54
+ commands: [
55
+ {
56
+ command: 'doctor',
57
+ description: 'Report PICO-8, shrinko8 and display capabilities, and which commands are available here.',
58
+ },
59
+ ],
60
+ },
61
+ };
62
+ }
63
+ /** The `error(...)` payload for a `pico8-not-found` result (the exact remedy + needs). */
64
+ export function pico8NotFoundError(result) {
65
+ return {
66
+ code: 'pico8-not-found',
67
+ message: `PICO-8 is not installed. ${result.remedy} (needs: ${result.needs.join(', ')})`,
68
+ exitCode: 1,
69
+ };
70
+ }
71
+ //# sourceMappingURL=pico8-env.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pico8-env.js","sourceRoot":"","sources":["../../src/commands/pico8-env.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,CAAC,EAAC,MAAM,OAAO,CAAC;AACxB,OAAO,EACN,oBAAoB,EAEpB,aAAa,EAEb,aAAa,EACb,iBAAiB,GAGjB,MAAM,0BAA0B,CAAC;AAElC;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,CAAC,MAAM,CAAC;IACjC,UAAU,EAAE,CAAC;SACX,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CAAC,4DAA4D,CAAC;IACxE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,yBAAyB,CAAC;CAC/D,CAAC,CAAC;AA4BH;;;;GAIG;AACH,MAAM,UAAU,yBAAyB,CACxC,OAAgC,EAAE;IAElC,OAAO,CAAC,GAAG,EAAE,OAAO,EAAE,EAAE,CACvB,IAAI,iBAAiB,CAAC;QACrB,GAAG,EAAE,aAAa,CACjB,GAAyC,EACzC,IAAI,CAAC,SAAS,IAAI,OAAO,CAAC,GAAG,CAC7B;QACD,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,OAAO,EAAE,OAAO,EAAE,OAAO,IAAI,oBAAoB;QACjD,cAAc,EAAE,IAAI,CAAC,cAAc;KACnC,CAAC,CAAC;AACL,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,IAAa;IAC1C,MAAM,KAAK,GACV,IAAI,KAAK,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ;QACxC,CAAC,CAAE,IAA4B,CAAC,OAAO;QACvC,CAAC,CAAC,SAAS,CAAC;IACd,OAAO,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,oBAAoB,CAAC;AAC5D,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,uBAAuB,CACtC,IAAY,EACZ,MAAwC;IAExC,OAAO;QACN,IAAI,EAAE,qBAA8B;QACpC,OAAO,EAAE,GAAG,IAAI,uDAAuD,MAAM,CAAC,MAAM,aAAa,MAAM,CAAC,MAAM,GAAG;QACjH,QAAQ,EAAE,CAAC;QACX,GAAG,EAAE;YACJ,WAAW,EAAE,gDAAgD,MAAM,CAAC,MAAM,uHAAuH;YACjM,QAAQ,EAAE;gBACT;oBACC,OAAO,EAAE,QAAQ;oBACjB,WAAW,EACV,0FAA0F;iBAC3F;aACD;SACD;KACD,CAAC;AACH,CAAC;AAED,0FAA0F;AAC1F,MAAM,UAAU,kBAAkB,CAAC,MAGlC;IACA,OAAO;QACN,IAAI,EAAE,iBAA0B;QAChC,OAAO,EAAE,4BAA4B,MAAM,CAAC,MAAM,YAAY,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG;QACxF,QAAQ,EAAE,CAAC;KACX,CAAC;AACH,CAAC"}
@@ -1,12 +1,12 @@
1
1
  import { type Cli } from 'incur';
2
- import { type Pico8Adapter } from '../engine/pico8/index.js';
2
+ import { type Pico8AdapterFactory } from './pico8-env.js';
3
3
  /**
4
4
  * Injects the PICO-8 adapter `playtest` uses (defaults to the shell adapter over
5
5
  * native `pico8 -x`). Mirrors `run`'s `Pico8AdapterFactory` seam: a test passes a
6
6
  * stub to drive the drive-orchestration + the absent path WITHOUT the paid
7
7
  * binary, and to isolate the child `env` (its `PICO8_PATH`/`PATH`).
8
8
  */
9
- export type Pico8AdapterFactory = (env: NodeJS.ProcessEnv) => Pico8Adapter;
9
+ export type { Pico8AdapterFactory } from './pico8-env.js';
10
10
  /**
11
11
  * Registers `picopilot playtest`, the driven-playtest command group (ADR-0011).
12
12
  * The ROOT command (`playtest <cart>`) is the ONE-SHOT driver (US #1-5,7-11): it
@@ -1 +1 @@
1
- {"version":3,"file":"playtest.d.ts","sourceRoot":"","sources":["../../src/commands/playtest.ts"],"names":[],"mappings":"AASA,OAAO,EAAC,KAAK,GAAG,EAAqB,MAAM,OAAO,CAAC;AACnD,OAAO,EAMN,KAAK,YAAY,EAajB,MAAM,0BAA0B,CAAC;AAElC;;;;;GAKG;AACH,MAAM,MAAM,mBAAmB,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,KAAK,YAAY,CAAC;AAiD3E;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,gBAAgB,CAC/B,GAAG,EAAE,GAAG,CAAC,GAAG,EACZ,cAAc,GAAE,mBAA2C,GACzD,IAAI,CAEN"}
1
+ {"version":3,"file":"playtest.d.ts","sourceRoot":"","sources":["../../src/commands/playtest.ts"],"names":[],"mappings":"AASA,OAAO,EAAC,KAAK,GAAG,EAAqB,MAAM,OAAO,CAAC;AAoBnD,OAAO,EAGN,KAAK,mBAAmB,EACxB,MAAM,gBAAgB,CAAC;AAGxB;;;;;GAKG;AACH,YAAY,EAAC,mBAAmB,EAAC,MAAM,gBAAgB,CAAC;AA0BxD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,gBAAgB,CAC/B,GAAG,EAAE,GAAG,CAAC,GAAG,EACZ,cAAc,GAAE,mBAA2C,GACzD,IAAI,CAEN"}