picopilot 0.0.0 → 0.1.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 (334) hide show
  1. package/LICENSE +661 -0
  2. package/dist/bin.d.ts +3 -0
  3. package/dist/bin.d.ts.map +1 -0
  4. package/dist/bin.js +4 -0
  5. package/dist/bin.js.map +1 -0
  6. package/dist/cli.d.ts +15 -0
  7. package/dist/cli.d.ts.map +1 -0
  8. package/dist/cli.js +59 -0
  9. package/dist/cli.js.map +1 -0
  10. package/dist/commands/audio.d.ts +17 -0
  11. package/dist/commands/audio.d.ts.map +1 -0
  12. package/dist/commands/audio.js +315 -0
  13. package/dist/commands/audio.js.map +1 -0
  14. package/dist/commands/export.d.ts +36 -0
  15. package/dist/commands/export.d.ts.map +1 -0
  16. package/dist/commands/export.js +257 -0
  17. package/dist/commands/export.js.map +1 -0
  18. package/dist/commands/gfx.d.ts +28 -0
  19. package/dist/commands/gfx.d.ts.map +1 -0
  20. package/dist/commands/gfx.js +521 -0
  21. package/dist/commands/gfx.js.map +1 -0
  22. package/dist/commands/init.d.ts +34 -0
  23. package/dist/commands/init.d.ts.map +1 -0
  24. package/dist/commands/init.js +151 -0
  25. package/dist/commands/init.js.map +1 -0
  26. package/dist/commands/lint.d.ts +20 -0
  27. package/dist/commands/lint.d.ts.map +1 -0
  28. package/dist/commands/lint.js +90 -0
  29. package/dist/commands/lint.js.map +1 -0
  30. package/dist/commands/minify.d.ts +20 -0
  31. package/dist/commands/minify.d.ts.map +1 -0
  32. package/dist/commands/minify.js +129 -0
  33. package/dist/commands/minify.js.map +1 -0
  34. package/dist/commands/music.d.ts +13 -0
  35. package/dist/commands/music.d.ts.map +1 -0
  36. package/dist/commands/music.js +241 -0
  37. package/dist/commands/music.js.map +1 -0
  38. package/dist/commands/playtest.d.ts +29 -0
  39. package/dist/commands/playtest.d.ts.map +1 -0
  40. package/dist/commands/playtest.js +631 -0
  41. package/dist/commands/playtest.js.map +1 -0
  42. package/dist/commands/run.d.ts +30 -0
  43. package/dist/commands/run.d.ts.map +1 -0
  44. package/dist/commands/run.js +202 -0
  45. package/dist/commands/run.js.map +1 -0
  46. package/dist/commands/serve.d.ts +50 -0
  47. package/dist/commands/serve.d.ts.map +1 -0
  48. package/dist/commands/serve.js +213 -0
  49. package/dist/commands/serve.js.map +1 -0
  50. package/dist/commands/sfx.d.ts +13 -0
  51. package/dist/commands/sfx.d.ts.map +1 -0
  52. package/dist/commands/sfx.js +254 -0
  53. package/dist/commands/sfx.js.map +1 -0
  54. package/dist/commands/tokens.d.ts +36 -0
  55. package/dist/commands/tokens.d.ts.map +1 -0
  56. package/dist/commands/tokens.js +129 -0
  57. package/dist/commands/tokens.js.map +1 -0
  58. package/dist/commands/verify.d.ts +57 -0
  59. package/dist/commands/verify.d.ts.map +1 -0
  60. package/dist/commands/verify.js +213 -0
  61. package/dist/commands/verify.js.map +1 -0
  62. package/dist/commands/version.d.ts +12 -0
  63. package/dist/commands/version.d.ts.map +1 -0
  64. package/dist/commands/version.js +24 -0
  65. package/dist/commands/version.js.map +1 -0
  66. package/dist/engine/audio/index.d.ts +14 -0
  67. package/dist/engine/audio/index.d.ts.map +1 -0
  68. package/dist/engine/audio/index.js +14 -0
  69. package/dist/engine/audio/index.js.map +1 -0
  70. package/dist/engine/audio/music.d.ts +116 -0
  71. package/dist/engine/audio/music.d.ts.map +1 -0
  72. package/dist/engine/audio/music.js +138 -0
  73. package/dist/engine/audio/music.js.map +1 -0
  74. package/dist/engine/audio/section.d.ts +34 -0
  75. package/dist/engine/audio/section.d.ts.map +1 -0
  76. package/dist/engine/audio/section.js +67 -0
  77. package/dist/engine/audio/section.js.map +1 -0
  78. package/dist/engine/audio/sfx.d.ts +141 -0
  79. package/dist/engine/audio/sfx.d.ts.map +1 -0
  80. package/dist/engine/audio/sfx.js +506 -0
  81. package/dist/engine/audio/sfx.js.map +1 -0
  82. package/dist/engine/cart/cart.d.ts +75 -0
  83. package/dist/engine/cart/cart.d.ts.map +1 -0
  84. package/dist/engine/cart/cart.js +153 -0
  85. package/dist/engine/cart/cart.js.map +1 -0
  86. package/dist/engine/cart/errors.d.ts +29 -0
  87. package/dist/engine/cart/errors.d.ts.map +1 -0
  88. package/dist/engine/cart/errors.js +26 -0
  89. package/dist/engine/cart/errors.js.map +1 -0
  90. package/dist/engine/cart/gfx.d.ts +79 -0
  91. package/dist/engine/cart/gfx.d.ts.map +1 -0
  92. package/dist/engine/cart/gfx.js +171 -0
  93. package/dist/engine/cart/gfx.js.map +1 -0
  94. package/dist/engine/cart/index.d.ts +15 -0
  95. package/dist/engine/cart/index.d.ts.map +1 -0
  96. package/dist/engine/cart/index.js +15 -0
  97. package/dist/engine/cart/index.js.map +1 -0
  98. package/dist/engine/cart/map.d.ts +46 -0
  99. package/dist/engine/cart/map.d.ts.map +1 -0
  100. package/dist/engine/cart/map.js +118 -0
  101. package/dist/engine/cart/map.js.map +1 -0
  102. package/dist/engine/config/config.d.ts +74 -0
  103. package/dist/engine/config/config.d.ts.map +1 -0
  104. package/dist/engine/config/config.js +103 -0
  105. package/dist/engine/config/config.js.map +1 -0
  106. package/dist/engine/config/index.d.ts +7 -0
  107. package/dist/engine/config/index.d.ts.map +1 -0
  108. package/dist/engine/config/index.js +7 -0
  109. package/dist/engine/config/index.js.map +1 -0
  110. package/dist/engine/gfx/grid.d.ts +51 -0
  111. package/dist/engine/gfx/grid.d.ts.map +1 -0
  112. package/dist/engine/gfx/grid.js +116 -0
  113. package/dist/engine/gfx/grid.js.map +1 -0
  114. package/dist/engine/gfx/index.d.ts +17 -0
  115. package/dist/engine/gfx/index.d.ts.map +1 -0
  116. package/dist/engine/gfx/index.js +17 -0
  117. package/dist/engine/gfx/index.js.map +1 -0
  118. package/dist/engine/gfx/label.d.ts +34 -0
  119. package/dist/engine/gfx/label.d.ts.map +1 -0
  120. package/dist/engine/gfx/label.js +190 -0
  121. package/dist/engine/gfx/label.js.map +1 -0
  122. package/dist/engine/gfx/overlap.d.ts +42 -0
  123. package/dist/engine/gfx/overlap.d.ts.map +1 -0
  124. package/dist/engine/gfx/overlap.js +57 -0
  125. package/dist/engine/gfx/overlap.js.map +1 -0
  126. package/dist/engine/gfx/palette.d.ts +29 -0
  127. package/dist/engine/gfx/palette.d.ts.map +1 -0
  128. package/dist/engine/gfx/palette.js +46 -0
  129. package/dist/engine/gfx/palette.js.map +1 -0
  130. package/dist/engine/gfx/png.d.ts +31 -0
  131. package/dist/engine/gfx/png.d.ts.map +1 -0
  132. package/dist/engine/gfx/png.js +165 -0
  133. package/dist/engine/gfx/png.js.map +1 -0
  134. package/dist/engine/gfx/render.d.ts +42 -0
  135. package/dist/engine/gfx/render.d.ts.map +1 -0
  136. package/dist/engine/gfx/render.js +72 -0
  137. package/dist/engine/gfx/render.js.map +1 -0
  138. package/dist/engine/index.d.ts +22 -0
  139. package/dist/engine/index.d.ts.map +1 -0
  140. package/dist/engine/index.js +22 -0
  141. package/dist/engine/index.js.map +1 -0
  142. package/dist/engine/pico8/adapter.d.ts +267 -0
  143. package/dist/engine/pico8/adapter.d.ts.map +1 -0
  144. package/dist/engine/pico8/adapter.js +37 -0
  145. package/dist/engine/pico8/adapter.js.map +1 -0
  146. package/dist/engine/pico8/drive.d.ts +308 -0
  147. package/dist/engine/pico8/drive.d.ts.map +1 -0
  148. package/dist/engine/pico8/drive.js +581 -0
  149. package/dist/engine/pico8/drive.js.map +1 -0
  150. package/dist/engine/pico8/harness.d.ts +146 -0
  151. package/dist/engine/pico8/harness.d.ts.map +1 -0
  152. package/dist/engine/pico8/harness.js +251 -0
  153. package/dist/engine/pico8/harness.js.map +1 -0
  154. package/dist/engine/pico8/index.d.ts +21 -0
  155. package/dist/engine/pico8/index.d.ts.map +1 -0
  156. package/dist/engine/pico8/index.js +21 -0
  157. package/dist/engine/pico8/index.js.map +1 -0
  158. package/dist/engine/pico8/sentinel.d.ts +63 -0
  159. package/dist/engine/pico8/sentinel.d.ts.map +1 -0
  160. package/dist/engine/pico8/sentinel.js +86 -0
  161. package/dist/engine/pico8/sentinel.js.map +1 -0
  162. package/dist/engine/pico8/session-daemon-entry.d.ts +10 -0
  163. package/dist/engine/pico8/session-daemon-entry.d.ts.map +1 -0
  164. package/dist/engine/pico8/session-daemon-entry.js +11 -0
  165. package/dist/engine/pico8/session-daemon-entry.js.map +1 -0
  166. package/dist/engine/pico8/session-daemon-main.d.ts +44 -0
  167. package/dist/engine/pico8/session-daemon-main.d.ts.map +1 -0
  168. package/dist/engine/pico8/session-daemon-main.js +71 -0
  169. package/dist/engine/pico8/session-daemon-main.js.map +1 -0
  170. package/dist/engine/pico8/session-daemon.d.ts +68 -0
  171. package/dist/engine/pico8/session-daemon.d.ts.map +1 -0
  172. package/dist/engine/pico8/session-daemon.js +264 -0
  173. package/dist/engine/pico8/session-daemon.js.map +1 -0
  174. package/dist/engine/pico8/session.d.ts +140 -0
  175. package/dist/engine/pico8/session.d.ts.map +1 -0
  176. package/dist/engine/pico8/session.js +250 -0
  177. package/dist/engine/pico8/session.js.map +1 -0
  178. package/dist/engine/pico8/shell.d.ts +103 -0
  179. package/dist/engine/pico8/shell.d.ts.map +1 -0
  180. package/dist/engine/pico8/shell.js +324 -0
  181. package/dist/engine/pico8/shell.js.map +1 -0
  182. package/dist/engine/pico8/supervisor.d.ts +137 -0
  183. package/dist/engine/pico8/supervisor.d.ts.map +1 -0
  184. package/dist/engine/pico8/supervisor.js +140 -0
  185. package/dist/engine/pico8/supervisor.js.map +1 -0
  186. package/dist/engine/scaffold/index.d.ts +8 -0
  187. package/dist/engine/scaffold/index.d.ts.map +1 -0
  188. package/dist/engine/scaffold/index.js +8 -0
  189. package/dist/engine/scaffold/index.js.map +1 -0
  190. package/dist/engine/scaffold/scaffold.d.ts +49 -0
  191. package/dist/engine/scaffold/scaffold.d.ts.map +1 -0
  192. package/dist/engine/scaffold/scaffold.js +217 -0
  193. package/dist/engine/scaffold/scaffold.js.map +1 -0
  194. package/dist/engine/shrinko/adapter.d.ts +167 -0
  195. package/dist/engine/shrinko/adapter.d.ts.map +1 -0
  196. package/dist/engine/shrinko/adapter.js +107 -0
  197. package/dist/engine/shrinko/adapter.js.map +1 -0
  198. package/dist/engine/shrinko/index.d.ts +13 -0
  199. package/dist/engine/shrinko/index.d.ts.map +1 -0
  200. package/dist/engine/shrinko/index.js +13 -0
  201. package/dist/engine/shrinko/index.js.map +1 -0
  202. package/dist/engine/shrinko/shell.d.ts +69 -0
  203. package/dist/engine/shrinko/shell.d.ts.map +1 -0
  204. package/dist/engine/shrinko/shell.js +156 -0
  205. package/dist/engine/shrinko/shell.js.map +1 -0
  206. package/dist/engine/skills/index.d.ts +8 -0
  207. package/dist/engine/skills/index.d.ts.map +1 -0
  208. package/dist/engine/skills/index.js +8 -0
  209. package/dist/engine/skills/index.js.map +1 -0
  210. package/dist/engine/skills/skills.d.ts +104 -0
  211. package/dist/engine/skills/skills.d.ts.map +1 -0
  212. package/dist/engine/skills/skills.js +149 -0
  213. package/dist/engine/skills/skills.js.map +1 -0
  214. package/dist/index.d.ts +10 -0
  215. package/dist/index.d.ts.map +1 -0
  216. package/dist/index.js +10 -0
  217. package/dist/index.js.map +1 -0
  218. package/dist/version.d.ts +2 -0
  219. package/dist/version.d.ts.map +1 -0
  220. package/dist/version.js +19 -0
  221. package/dist/version.js.map +1 -0
  222. package/package.json +48 -2
  223. package/src/bin.ts +4 -0
  224. package/src/cli.ts +61 -0
  225. package/src/commands/audio.test.ts +280 -0
  226. package/src/commands/audio.ts +410 -0
  227. package/src/commands/export.test.ts +310 -0
  228. package/src/commands/export.ts +316 -0
  229. package/src/commands/gfx-io.test.ts +178 -0
  230. package/src/commands/gfx.test.ts +470 -0
  231. package/src/commands/gfx.ts +645 -0
  232. package/src/commands/init.test.ts +460 -0
  233. package/src/commands/init.ts +193 -0
  234. package/src/commands/lint.test.ts +137 -0
  235. package/src/commands/lint.ts +117 -0
  236. package/src/commands/minify.test.ts +166 -0
  237. package/src/commands/minify.ts +156 -0
  238. package/src/commands/music.test.ts +272 -0
  239. package/src/commands/music.ts +288 -0
  240. package/src/commands/playtest.test.ts +317 -0
  241. package/src/commands/playtest.ts +773 -0
  242. package/src/commands/run.test.ts +238 -0
  243. package/src/commands/run.ts +259 -0
  244. package/src/commands/serve.test.ts +218 -0
  245. package/src/commands/serve.ts +272 -0
  246. package/src/commands/sfx.test.ts +349 -0
  247. package/src/commands/sfx.ts +300 -0
  248. package/src/commands/tokens.test.ts +212 -0
  249. package/src/commands/tokens.ts +168 -0
  250. package/src/commands/verify.test.ts +238 -0
  251. package/src/commands/verify.ts +256 -0
  252. package/src/commands/version.test.ts +70 -0
  253. package/src/commands/version.ts +24 -0
  254. package/src/engine/audio/index.ts +47 -0
  255. package/src/engine/audio/music.test.ts +188 -0
  256. package/src/engine/audio/music.ts +218 -0
  257. package/src/engine/audio/section.test.ts +124 -0
  258. package/src/engine/audio/section.ts +79 -0
  259. package/src/engine/audio/sfx.test.ts +410 -0
  260. package/src/engine/audio/sfx.ts +694 -0
  261. package/src/engine/cart/cart.test.ts +304 -0
  262. package/src/engine/cart/cart.ts +211 -0
  263. package/src/engine/cart/errors.ts +39 -0
  264. package/src/engine/cart/fixtures/crlf.p8 +6 -0
  265. package/src/engine/cart/fixtures/full.p8 +174 -0
  266. package/src/engine/cart/fixtures/header-only.p8 +2 -0
  267. package/src/engine/cart/fixtures/malformed-no-header.p8 +2 -0
  268. package/src/engine/cart/fixtures/minimal.p8 +10 -0
  269. package/src/engine/cart/fixtures/no-trailing-newline.p8 +6 -0
  270. package/src/engine/cart/gfx.ts +195 -0
  271. package/src/engine/cart/index.ts +27 -0
  272. package/src/engine/cart/map.ts +134 -0
  273. package/src/engine/config/config.ts +115 -0
  274. package/src/engine/config/index.ts +12 -0
  275. package/src/engine/gfx/grid.test.ts +128 -0
  276. package/src/engine/gfx/grid.ts +136 -0
  277. package/src/engine/gfx/index.ts +34 -0
  278. package/src/engine/gfx/label.test.ts +105 -0
  279. package/src/engine/gfx/label.ts +229 -0
  280. package/src/engine/gfx/overlap.test.ts +71 -0
  281. package/src/engine/gfx/overlap.ts +66 -0
  282. package/src/engine/gfx/palette.test.ts +35 -0
  283. package/src/engine/gfx/palette.ts +54 -0
  284. package/src/engine/gfx/png.test.ts +111 -0
  285. package/src/engine/gfx/png.ts +196 -0
  286. package/src/engine/gfx/render.test.ts +180 -0
  287. package/src/engine/gfx/render.ts +106 -0
  288. package/src/engine/index.ts +21 -0
  289. package/src/engine/pico8/adapter.ts +303 -0
  290. package/src/engine/pico8/drive.test.ts +415 -0
  291. package/src/engine/pico8/drive.ts +729 -0
  292. package/src/engine/pico8/harness.test.ts +181 -0
  293. package/src/engine/pico8/harness.ts +354 -0
  294. package/src/engine/pico8/index.ts +20 -0
  295. package/src/engine/pico8/sentinel.test.ts +80 -0
  296. package/src/engine/pico8/sentinel.ts +93 -0
  297. package/src/engine/pico8/session-daemon-entry.ts +12 -0
  298. package/src/engine/pico8/session-daemon-main.ts +98 -0
  299. package/src/engine/pico8/session-daemon.test.ts +212 -0
  300. package/src/engine/pico8/session-daemon.ts +306 -0
  301. package/src/engine/pico8/session.test.ts +239 -0
  302. package/src/engine/pico8/session.ts +321 -0
  303. package/src/engine/pico8/shell.test.ts +583 -0
  304. package/src/engine/pico8/shell.ts +412 -0
  305. package/src/engine/pico8/supervisor.test.ts +105 -0
  306. package/src/engine/pico8/supervisor.ts +197 -0
  307. package/src/engine/scaffold/index.ts +15 -0
  308. package/src/engine/scaffold/scaffold.ts +236 -0
  309. package/src/engine/shrinko/adapter.ts +241 -0
  310. package/src/engine/shrinko/fixtures/count-no-compressed.txt +2 -0
  311. package/src/engine/shrinko/fixtures/count-over-budget.txt +3 -0
  312. package/src/engine/shrinko/fixtures/count-under-budget.txt +3 -0
  313. package/src/engine/shrinko/index.ts +33 -0
  314. package/src/engine/shrinko/shell.ts +224 -0
  315. package/src/engine/shrinko/shrinko.test.ts +182 -0
  316. package/src/engine/skills/index.ts +14 -0
  317. package/src/engine/skills/skills.test.ts +376 -0
  318. package/src/engine/skills/skills.ts +205 -0
  319. package/src/index.ts +13 -0
  320. package/src/skills/game-design-reference/SKILL.md +70 -0
  321. package/src/skills/game-jam/SKILL.md +45 -0
  322. package/src/skills/picopilot-art/SKILL.md +62 -0
  323. package/src/skills/picopilot-audio/SKILL.md +194 -0
  324. package/src/skills/picopilot-code/SKILL.md +97 -0
  325. package/src/skills/picopilot-code/reference/README.md +42 -0
  326. package/src/skills/picopilot-code/reference/mode7-racing.md +95 -0
  327. package/src/skills/picopilot-code/reference/platformer.md +119 -0
  328. package/src/skills/picopilot-code/reference/puzzle-grid.md +106 -0
  329. package/src/skills/picopilot-code/reference/rpg-menus-dialog.md +122 -0
  330. package/src/skills/picopilot-code/reference/top-down-adventure.md +117 -0
  331. package/src/skills/picopilot-code/reference/twin-stick-arcade.md +128 -0
  332. package/src/skills/picopilot-debug/SKILL.md +195 -0
  333. package/src/skills/picopilot-overview/SKILL.md +52 -0
  334. package/src/version.ts +22 -0
@@ -0,0 +1,69 @@
1
+ import { type CountReport, type LintReport, type MinifyReport, type ShrinkoAdapter, type ShrinkoResult } from './adapter.js';
2
+ /**
3
+ * The result of running one child process: its exit `code` (null when killed by
4
+ * a signal), captured `stdout`/`stderr`, and `spawnError` set when the binary
5
+ * could not be launched AT ALL (ENOENT etc.) rather than launched-and-exited.
6
+ * `spawnError` is how the shell adapter distinguishes "shrinko is not installed"
7
+ * from "shrinko ran and failed".
8
+ */
9
+ export interface ChildResult {
10
+ readonly code: number | null;
11
+ readonly stdout: string;
12
+ readonly stderr: string;
13
+ readonly spawnError: NodeJS.ErrnoException | undefined;
14
+ }
15
+ /**
16
+ * The child-process seam. The real implementation shells out with the CALLER's
17
+ * `env` (so a test overrides the child's `PATH` and nothing else). Tests inject
18
+ * a stub runner to simulate shrinko present/absent WITHOUT ever requiring the
19
+ * real binary, and to assert exactly what argv/env the adapter would spawn.
20
+ */
21
+ export type ChildRunner = (file: string, args: string[], env: NodeJS.ProcessEnv) => Promise<ChildResult>;
22
+ /**
23
+ * The default {@link ChildRunner}: an `execFile` that captures stdout/stderr and
24
+ * NEVER rejects. A failed spawn (ENOENT) becomes `spawnError`; a nonzero exit
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.
29
+ */
30
+ export declare const execFileRunner: ChildRunner;
31
+ /** Options for {@link ShellShrinkoAdapter}. */
32
+ export interface ShellShrinkoOptions {
33
+ /**
34
+ * The environment handed to the child process. The command layer passes the
35
+ * incur-resolved env here; its `PATH` is the isolation lever a test overrides
36
+ * (an empty/`PATH`-less env makes every invocation ENOENT ⇒ shrinko-absent).
37
+ */
38
+ readonly env: NodeJS.ProcessEnv;
39
+ /** The child runner (defaults to {@link execFileRunner}); tests inject a stub. */
40
+ readonly run?: ChildRunner;
41
+ }
42
+ /**
43
+ * The v1 {@link ShrinkoAdapter}: shells out to a user-installed Python
44
+ * `shrinko8` (ADR-0001). It is the ONLY place that knows shrinko is an external
45
+ * process; every command talks to the {@link ShrinkoAdapter} interface, so a
46
+ * future native-TS adapter replaces this class without touching a command.
47
+ *
48
+ * Presence detection and invocation are the SAME act: the adapter tries each
49
+ * {@link SHRINKO_INVOCATIONS} candidate and uses the first that spawns. If every
50
+ * candidate ENOENTs, shrinko is absent and the method returns the structured
51
+ * {@link shrinkoNotFound} value (never a throw, never a hollow success).
52
+ */
53
+ export declare class ShellShrinkoAdapter implements ShrinkoAdapter {
54
+ private readonly env;
55
+ private readonly run;
56
+ constructor(options: ShellShrinkoOptions);
57
+ count(cartPath: string): Promise<ShrinkoResult<CountReport>>;
58
+ lint(cartPath: string): Promise<ShrinkoResult<LintReport>>;
59
+ minify(cartPath: string, outPath: string): Promise<ShrinkoResult<MinifyReport>>;
60
+ exportSpritesheet(cartPath: string, pngPath: string): Promise<ShrinkoResult<void>>;
61
+ importSpritesheet(srcCartPath: string, pngPath: string, outCartPath: string): Promise<ShrinkoResult<void>>;
62
+ /**
63
+ * Runs shrinko with the given trailing args, trying each invocation candidate
64
+ * until one SPAWNS. Returns the {@link ChildResult} of the first candidate
65
+ * that launched, or `undefined` when every candidate ENOENTs (shrinko absent).
66
+ */
67
+ private invoke;
68
+ }
69
+ //# sourceMappingURL=shell.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shell.d.ts","sourceRoot":"","sources":["../../../src/engine/shrinko/shell.ts"],"names":[],"mappings":"AAEA,OAAO,EACN,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,KAAK,YAAY,EAGjB,KAAK,cAAc,EACnB,KAAK,aAAa,EAElB,MAAM,cAAc,CAAC;AAEtB;;;;;;GAMG;AACH,MAAM,WAAW,WAAW;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC,cAAc,GAAG,SAAS,CAAC;CACvD;AAED;;;;;GAKG;AACH,MAAM,MAAM,WAAW,GAAG,CACzB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EAAE,EACd,GAAG,EAAE,MAAM,CAAC,UAAU,KAClB,OAAO,CAAC,WAAW,CAAC,CAAC;AAE1B;;;;;;;GAOG;AACH,eAAO,MAAM,cAAc,EAAE,WAmB1B,CAAC;AAcJ,+CAA+C;AAC/C,MAAM,WAAW,mBAAmB;IACnC;;;;OAIG;IACH,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IAChC,kFAAkF;IAClF,QAAQ,CAAC,GAAG,CAAC,EAAE,WAAW,CAAC;CAC3B;AAED;;;;;;;;;;GAUG;AACH,qBAAa,mBAAoB,YAAW,cAAc;IACzD,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAoB;IACxC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAc;gBAEtB,OAAO,EAAE,mBAAmB;IAKlC,KAAK,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC;IAa5D,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC;IAe1D,MAAM,CACX,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,GACb,OAAO,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC;IAgCjC,iBAAiB,CACtB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,GACb,OAAO,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;IAOzB,iBAAiB,CACtB,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,MAAM,GACjB,OAAO,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;IAgB/B;;;;OAIG;YACW,MAAM;CAapB"}
@@ -0,0 +1,156 @@
1
+ import { execFile } from 'node:child_process';
2
+ import { parseCount, parseLint, shrinkoNotFound, } from './adapter.js';
3
+ /**
4
+ * The default {@link ChildRunner}: an `execFile` that captures stdout/stderr and
5
+ * NEVER rejects. A failed spawn (ENOENT) becomes `spawnError`; a nonzero exit
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.
10
+ */
11
+ export const execFileRunner = (file, args, env) => new Promise((resolve) => {
12
+ execFile(file, args, { env, encoding: 'utf8' }, (error, stdout, stderr) => {
13
+ const err = error;
14
+ resolve({
15
+ // `execFile` sets error.code to the string 'ENOENT' on spawn failure and
16
+ // to the numeric exit code on a nonzero exit; separate the two.
17
+ code: err !== null && typeof err.code === 'number'
18
+ ? err.code
19
+ : err === null
20
+ ? 0
21
+ : null,
22
+ stdout,
23
+ stderr,
24
+ spawnError: err !== null && typeof err.code === 'string' ? err : undefined,
25
+ });
26
+ });
27
+ });
28
+ /**
29
+ * The candidate ways to invoke shrinko, tried in order. First the `shrinko8`
30
+ * entry-point on `PATH`, then `python -m shrinko8` / `python3 -m shrinko8` as
31
+ * fallbacks (the module is `shrinko8`; the pip package is `shrinko`). The first
32
+ * candidate that SPAWNS (does not ENOENT) is the one shrinko is reached through.
33
+ */
34
+ const SHRINKO_INVOCATIONS = [
35
+ ['shrinko8'],
36
+ ['python', '-m', 'shrinko8'],
37
+ ['python3', '-m', 'shrinko8'],
38
+ ];
39
+ /**
40
+ * The v1 {@link ShrinkoAdapter}: shells out to a user-installed Python
41
+ * `shrinko8` (ADR-0001). It is the ONLY place that knows shrinko is an external
42
+ * process; every command talks to the {@link ShrinkoAdapter} interface, so a
43
+ * future native-TS adapter replaces this class without touching a command.
44
+ *
45
+ * Presence detection and invocation are the SAME act: the adapter tries each
46
+ * {@link SHRINKO_INVOCATIONS} candidate and uses the first that spawns. If every
47
+ * candidate ENOENTs, shrinko is absent and the method returns the structured
48
+ * {@link shrinkoNotFound} value (never a throw, never a hollow success).
49
+ */
50
+ export class ShellShrinkoAdapter {
51
+ env;
52
+ run;
53
+ constructor(options) {
54
+ this.env = options.env;
55
+ this.run = options.run ?? execFileRunner;
56
+ }
57
+ async count(cartPath) {
58
+ const outcome = await this.invoke([cartPath, '--count']);
59
+ if (outcome === undefined) {
60
+ return shrinkoNotFound();
61
+ }
62
+ // shrinko prints the count report; some builds send it to stderr, so parse
63
+ // the combined stream. parseCount throws on unparseable output (ShrinkoParseError).
64
+ return {
65
+ ok: true,
66
+ value: parseCount(`${outcome.stdout}\n${outcome.stderr}`),
67
+ };
68
+ }
69
+ async lint(cartPath) {
70
+ // `-l` lints; it exits nonzero (2) WHEN it finds warnings, which is a normal
71
+ // result (findings are data), NOT a spawn failure. Only a spawnError means
72
+ // shrinko is absent, so we key absence off `outcome === undefined`, and parse
73
+ // the warnings regardless of the (0-or-2) exit code.
74
+ const outcome = await this.invoke([cartPath, '-l']);
75
+ if (outcome === undefined) {
76
+ return shrinkoNotFound();
77
+ }
78
+ return {
79
+ ok: true,
80
+ value: parseLint(`${outcome.stdout}\n${outcome.stderr}`),
81
+ };
82
+ }
83
+ async minify(cartPath, outPath) {
84
+ // Count the source first (the "before"): if shrinko is absent, this returns
85
+ // the not-found value and we never write anything.
86
+ const before = await this.count(cartPath);
87
+ if (!before.ok)
88
+ return before;
89
+ // Minify SAFE-only (ADR-0007): the three safe-only knobs keep rename/reorder/
90
+ // builtins behaviour-preserving. Output goes to a SEPARATE cart (outPath).
91
+ const out = await this.invoke([
92
+ cartPath,
93
+ '-m',
94
+ '--rename-safe-only',
95
+ '--reorder-safe-only',
96
+ '--builtins-safe-only',
97
+ outPath,
98
+ ]);
99
+ if (out === undefined)
100
+ return shrinkoNotFound();
101
+ // Count the artifact (the "after"). It exists now, so this is a normal count.
102
+ const after = await this.count(outPath);
103
+ if (!after.ok)
104
+ return after;
105
+ return {
106
+ ok: true,
107
+ value: {
108
+ beforeTokens: before.value.tokens,
109
+ afterTokens: after.value.tokens,
110
+ outPath,
111
+ },
112
+ };
113
+ }
114
+ async exportSpritesheet(cartPath, pngPath) {
115
+ // `<cart> <out.png> -f spritesheet` writes the 128x128 spritesheet PNG.
116
+ const outcome = await this.invoke([cartPath, pngPath, '-f', 'spritesheet']);
117
+ if (outcome === undefined)
118
+ return shrinkoNotFound();
119
+ return { ok: true, value: undefined };
120
+ }
121
+ async importSpritesheet(srcCartPath, pngPath, outCartPath) {
122
+ // `<cart> <out.p8> --merge <png> gfx spritesheet` merges ONLY the gfx section
123
+ // from the PNG into the source cart, preserving code/map/sfx/music. (A plain
124
+ // `-F spritesheet` would drop everything but gfx, wiping the user's code.)
125
+ const outcome = await this.invoke([
126
+ srcCartPath,
127
+ outCartPath,
128
+ '--merge',
129
+ pngPath,
130
+ 'gfx',
131
+ 'spritesheet',
132
+ ]);
133
+ if (outcome === undefined)
134
+ return shrinkoNotFound();
135
+ return { ok: true, value: undefined };
136
+ }
137
+ /**
138
+ * Runs shrinko with the given trailing args, trying each invocation candidate
139
+ * until one SPAWNS. Returns the {@link ChildResult} of the first candidate
140
+ * that launched, or `undefined` when every candidate ENOENTs (shrinko absent).
141
+ */
142
+ async invoke(args) {
143
+ for (const inv of SHRINKO_INVOCATIONS) {
144
+ const [file, ...prefix] = inv;
145
+ const result = await this.run(file, [...prefix, ...args], this.env);
146
+ if (result.spawnError === undefined) {
147
+ return result;
148
+ }
149
+ // ENOENT on this candidate: fall through to the next. Any other spawn
150
+ // error (EACCES etc.) also falls through, so a broken candidate never
151
+ // masks a working one.
152
+ }
153
+ return undefined;
154
+ }
155
+ }
156
+ //# sourceMappingURL=shell.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shell.js","sourceRoot":"","sources":["../../../src/engine/shrinko/shell.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,QAAQ,EAAC,MAAM,oBAAoB,CAAC;AAE5C,OAAO,EAIN,UAAU,EACV,SAAS,EAGT,eAAe,GACf,MAAM,cAAc,CAAC;AA4BtB;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,cAAc,GAAgB,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE,CAC9D,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;IACvB,QAAQ,CAAC,IAAI,EAAE,IAAI,EAAE,EAAC,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE;QACvE,MAAM,GAAG,GAAG,KAAqC,CAAC;QAClD,OAAO,CAAC;YACP,yEAAyE;YACzE,gEAAgE;YAChE,IAAI,EACH,GAAG,KAAK,IAAI,IAAI,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ;gBAC3C,CAAC,CAAC,GAAG,CAAC,IAAI;gBACV,CAAC,CAAC,GAAG,KAAK,IAAI;oBACb,CAAC,CAAC,CAAC;oBACH,CAAC,CAAC,IAAI;YACT,MAAM;YACN,MAAM;YACN,UAAU,EACT,GAAG,KAAK,IAAI,IAAI,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS;SAC/D,CAAC,CAAC;IACJ,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC,CAAC;AAEJ;;;;;GAKG;AACH,MAAM,mBAAmB,GAAmC;IAC3D,CAAC,UAAU,CAAC;IACZ,CAAC,QAAQ,EAAE,IAAI,EAAE,UAAU,CAAC;IAC5B,CAAC,SAAS,EAAE,IAAI,EAAE,UAAU,CAAC;CAC7B,CAAC;AAcF;;;;;;;;;;GAUG;AACH,MAAM,OAAO,mBAAmB;IACd,GAAG,CAAoB;IACvB,GAAG,CAAc;IAElC,YAAY,OAA4B;QACvC,IAAI,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;QACvB,IAAI,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,cAAc,CAAC;IAC1C,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,QAAgB;QAC3B,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC;QACzD,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC3B,OAAO,eAAe,EAAE,CAAC;QAC1B,CAAC;QACD,2EAA2E;QAC3E,oFAAoF;QACpF,OAAO;YACN,EAAE,EAAE,IAAI;YACR,KAAK,EAAE,UAAU,CAAC,GAAG,OAAO,CAAC,MAAM,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC;SACzD,CAAC;IACH,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,QAAgB;QAC1B,6EAA6E;QAC7E,2EAA2E;QAC3E,8EAA8E;QAC9E,qDAAqD;QACrD,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC;QACpD,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC3B,OAAO,eAAe,EAAE,CAAC;QAC1B,CAAC;QACD,OAAO;YACN,EAAE,EAAE,IAAI;YACR,KAAK,EAAE,SAAS,CAAC,GAAG,OAAO,CAAC,MAAM,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC;SACxD,CAAC;IACH,CAAC;IAED,KAAK,CAAC,MAAM,CACX,QAAgB,EAChB,OAAe;QAEf,4EAA4E;QAC5E,mDAAmD;QACnD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QAC1C,IAAI,CAAC,MAAM,CAAC,EAAE;YAAE,OAAO,MAAM,CAAC;QAE9B,8EAA8E;QAC9E,2EAA2E;QAC3E,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC;YAC7B,QAAQ;YACR,IAAI;YACJ,oBAAoB;YACpB,qBAAqB;YACrB,sBAAsB;YACtB,OAAO;SACP,CAAC,CAAC;QACH,IAAI,GAAG,KAAK,SAAS;YAAE,OAAO,eAAe,EAAE,CAAC;QAEhD,8EAA8E;QAC9E,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACxC,IAAI,CAAC,KAAK,CAAC,EAAE;YAAE,OAAO,KAAK,CAAC;QAE5B,OAAO;YACN,EAAE,EAAE,IAAI;YACR,KAAK,EAAE;gBACN,YAAY,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM;gBACjC,WAAW,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM;gBAC/B,OAAO;aACP;SACD,CAAC;IACH,CAAC;IAED,KAAK,CAAC,iBAAiB,CACtB,QAAgB,EAChB,OAAe;QAEf,wEAAwE;QACxE,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,aAAa,CAAC,CAAC,CAAC;QAC5E,IAAI,OAAO,KAAK,SAAS;YAAE,OAAO,eAAe,EAAE,CAAC;QACpD,OAAO,EAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,EAAC,CAAC;IACrC,CAAC;IAED,KAAK,CAAC,iBAAiB,CACtB,WAAmB,EACnB,OAAe,EACf,WAAmB;QAEnB,8EAA8E;QAC9E,6EAA6E;QAC7E,2EAA2E;QAC3E,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC;YACjC,WAAW;YACX,WAAW;YACX,SAAS;YACT,OAAO;YACP,KAAK;YACL,aAAa;SACb,CAAC,CAAC;QACH,IAAI,OAAO,KAAK,SAAS;YAAE,OAAO,eAAe,EAAE,CAAC;QACpD,OAAO,EAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,EAAC,CAAC;IACrC,CAAC;IAED;;;;OAIG;IACK,KAAK,CAAC,MAAM,CAAC,IAAc;QAClC,KAAK,MAAM,GAAG,IAAI,mBAAmB,EAAE,CAAC;YACvC,MAAM,CAAC,IAAI,EAAE,GAAG,MAAM,CAAC,GAAG,GAA4B,CAAC;YACvD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,GAAG,MAAM,EAAE,GAAG,IAAI,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;YACpE,IAAI,MAAM,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;gBACrC,OAAO,MAAM,CAAC;YACf,CAAC;YACD,sEAAsE;YACtE,sEAAsE;YACtE,uBAAuB;QACxB,CAAC;QACD,OAAO,SAAS,CAAC;IAClB,CAAC;CACD"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * The skills-install engine behind `picopilot init --install-skills`, the one
3
+ * picopilot path that writes to a shared/global location. Every install-target
4
+ * knob is a parameter here so tests redirect it to a temp dir and the real agent
5
+ * skill dirs stay byte-untouched. See `skills.ts` for the isolation contract.
6
+ */
7
+ export { installSkills, type InstallSkillsOptions, type InstallSkillsResult, SKILL_NAMES, skillsSourceDir, type WiredAgent, } from './skills.js';
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/engine/skills/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EACN,aAAa,EACb,KAAK,oBAAoB,EACzB,KAAK,mBAAmB,EACxB,WAAW,EACX,eAAe,EACf,KAAK,UAAU,GACf,MAAM,aAAa,CAAC"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * The skills-install engine behind `picopilot init --install-skills`, the one
3
+ * picopilot path that writes to a shared/global location. Every install-target
4
+ * knob is a parameter here so tests redirect it to a temp dir and the real agent
5
+ * skill dirs stay byte-untouched. See `skills.ts` for the isolation contract.
6
+ */
7
+ export { installSkills, SKILL_NAMES, skillsSourceDir, } from './skills.js';
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/engine/skills/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EACN,aAAa,EAGb,WAAW,EACX,eAAe,GAEf,MAAM,aAAa,CAAC"}
@@ -0,0 +1,104 @@
1
+ import { Cli } from 'incur';
2
+ /**
3
+ * The engine behind `picopilot init --install-skills`: the ONE picopilot path
4
+ * that writes to a SHARED/GLOBAL location. incur's `skills add` defaults to a
5
+ * GLOBAL install (into `~/.agents/skills` plus symlinks into detected agent
6
+ * dirs like `~/.claude/skills`), so this module is where the work-contract's
7
+ * shared-write isolation obligation is discharged: every knob that decides the
8
+ * install TARGET (`global`, `cwd`) is a parameter a test can redirect to a temp
9
+ * dir, so installing skills can never pollute the real environment in tests.
10
+ *
11
+ * The install runs IN-PROCESS through incur's `SyncSkills.sync`. NOTE (incur
12
+ * 0.4.10): `SyncSkills.sync` / the `skills add` built-in resolve their target
13
+ * from `os.homedir()` and `process.env` captured AT MODULE LOAD, NOT from the
14
+ * `env` DI you can pass to `cli.serve(argv, { env })`, so overriding the serve
15
+ * env does NOT move the install target. The effective in-process lever is
16
+ * `global: false` + `cwd: <temp dir>`, which installs under `<cwd>/.agents/skills`
17
+ * (and `<cwd>/.claude/skills` etc.) and leaves the real dirs byte-untouched.
18
+ */
19
+ /**
20
+ * The authored picopilot skills (US #20 discipline skills + the game skills),
21
+ * as SKILL.md files under {@link skillsSourceDir}. They load on-demand by
22
+ * concern and carry the hard-won workflow knowledge (the `#include` discipline,
23
+ * the token breakdown, the `gfx render`→look→`gfx set`→fix loop incl. the
24
+ * non-multimodal fallback, composing in picopilot-MML) so an agent gets it
25
+ * without bloating every turn.
26
+ *
27
+ * The GAME skills are a composed pair (grilled design in
28
+ * work/notes/ideas/game-jam-design-skill.md): `game-jam` (model-invoked, the
29
+ * clock+theme discipline) POINTS AT `game-design-reference` (a user-invoked
30
+ * reference body of universal design principles, `disable-model-invocation`, so
31
+ * it costs no per-turn context and is reached only by pointer, not fired on a
32
+ * vague trigger). Both ship engine-packaged here; `game-design-reference`'s
33
+ * CONTENT is engine-agnostic.
34
+ *
35
+ * They ship ALONGSIDE the per-command skills incur auto-generates from the
36
+ * command surface (`sync: { depth: 1 }`), pulled in via an `include` glob; the
37
+ * command surface is still growing, so the named discipline skills are authored
38
+ * rather than tied to a command-group shape that does not exist yet.
39
+ */
40
+ export declare const SKILL_NAMES: readonly ["picopilot-overview", "picopilot-code", "picopilot-art", "picopilot-audio", "picopilot-debug", "game-design-reference", "game-jam"];
41
+ /**
42
+ * Resolves the on-disk directory that holds the authored `picopilot-*` SKILL.md
43
+ * files (`<packageRoot>/src/skills`). The files ship in the npm package (the
44
+ * package `files` includes `src`), so the same path works from the built
45
+ * `dist/` runtime and from `src/` under tsx: we walk up from THIS module to the
46
+ * package root (the nearest ancestor with a `package.json`) and join `src/skills`,
47
+ * rather than a `dist`-relative path that would not exist (SKILL.md is not
48
+ * compiled).
49
+ */
50
+ export declare function skillsSourceDir(): string;
51
+ /** One agent whose skill dir picopilot's install wired up (from incur's result). */
52
+ export interface WiredAgent {
53
+ readonly agent: string;
54
+ readonly path: string;
55
+ readonly mode: string;
56
+ }
57
+ /** The outcome of installing picopilot's skills. */
58
+ export interface InstallSkillsResult {
59
+ /** Canonical install paths (one per skill, under `<base>/.agents/skills`). */
60
+ readonly paths: string[];
61
+ /** Non-universal agents whose dirs were symlinked/copied to the canonical skills. */
62
+ readonly agents: WiredAgent[];
63
+ /** The skill names that were installed. */
64
+ readonly skills: string[];
65
+ }
66
+ /** Options controlling WHERE and HOW picopilot's skills are installed. */
67
+ export interface InstallSkillsOptions {
68
+ /**
69
+ * The picopilot CLI whose command surface the per-command skills are generated
70
+ * from. Its command map (via {@link Cli.toCommands}) is handed to incur.
71
+ */
72
+ readonly cli: Cli.Cli;
73
+ /**
74
+ * Install globally (the real default, into `~/.agents/skills` + detected agent
75
+ * dirs) when true; install project-locally (into `<cwd>/.agents/skills`) when
76
+ * false. This is the shared-write isolation lever: tests pass `false`.
77
+ */
78
+ readonly global: boolean;
79
+ /**
80
+ * The install base for a project-local (`global: false`) install and, when a
81
+ * non-universal agent is detected, the base its symlinks are written under.
82
+ * Ignored for a global install (that goes to the real home). Tests point this
83
+ * at a temp dir.
84
+ */
85
+ readonly cwd?: string;
86
+ /**
87
+ * Override the authored-skills source dir. Defaults to {@link skillsSourceDir}.
88
+ * Exists so a test can prove isolation using its own fixture skills.
89
+ */
90
+ readonly sourceDir?: string;
91
+ }
92
+ /**
93
+ * Installs picopilot's skills (the authored `picopilot-*` discipline skills plus
94
+ * the per-command skills incur generates from the CLI) via incur's
95
+ * `SyncSkills.sync`. This is the real work `init --install-skills` performs.
96
+ *
97
+ * The authored skills are pulled in with an ABSOLUTE `include` glob into
98
+ * {@link skillsSourceDir}, DECOUPLED from `cwd` on purpose: `cwd` selects the
99
+ * install TARGET, the include glob selects the skills SOURCE. That decoupling is
100
+ * what lets a test install to a temp `cwd` while still reading the real authored
101
+ * skills (or its own fixtures), the crux of the isolation contract.
102
+ */
103
+ export declare function installSkills(options: InstallSkillsOptions): Promise<InstallSkillsResult>;
104
+ //# sourceMappingURL=skills.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["../../../src/engine/skills/skills.ts"],"names":[],"mappings":"AAGA,OAAO,EAAC,GAAG,EAAa,MAAM,OAAO,CAAC;AAEtC;;;;;;;;;;;;;;;;GAgBG;AAEH;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,WAAW,+IAQd,CAAC;AAEX;;;;;;;;GAQG;AACH,wBAAgB,eAAe,IAAI,MAAM,CAcxC;AAED,oFAAoF;AACpF,MAAM,WAAW,UAAU;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACtB;AAED,oDAAoD;AACpD,MAAM,WAAW,mBAAmB;IACnC,8EAA8E;IAC9E,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC;IACzB,qFAAqF;IACrF,QAAQ,CAAC,MAAM,EAAE,UAAU,EAAE,CAAC;IAC9B,2CAA2C;IAC3C,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED,0EAA0E;AAC1E,MAAM,WAAW,oBAAoB;IACpC;;;OAGG;IACH,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,CAAC;IACtB;;;;OAIG;IACH,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB;;;;;OAKG;IACH,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,aAAa,CAClC,OAAO,EAAE,oBAAoB,GAC3B,OAAO,CAAC,mBAAmB,CAAC,CA6C9B"}
@@ -0,0 +1,149 @@
1
+ import { cpSync, existsSync, readdirSync } from 'node:fs';
2
+ import { basename, dirname, join } from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+ import { Cli, SyncSkills } from 'incur';
5
+ /**
6
+ * The engine behind `picopilot init --install-skills`: the ONE picopilot path
7
+ * that writes to a SHARED/GLOBAL location. incur's `skills add` defaults to a
8
+ * GLOBAL install (into `~/.agents/skills` plus symlinks into detected agent
9
+ * dirs like `~/.claude/skills`), so this module is where the work-contract's
10
+ * shared-write isolation obligation is discharged: every knob that decides the
11
+ * install TARGET (`global`, `cwd`) is a parameter a test can redirect to a temp
12
+ * dir, so installing skills can never pollute the real environment in tests.
13
+ *
14
+ * The install runs IN-PROCESS through incur's `SyncSkills.sync`. NOTE (incur
15
+ * 0.4.10): `SyncSkills.sync` / the `skills add` built-in resolve their target
16
+ * from `os.homedir()` and `process.env` captured AT MODULE LOAD, NOT from the
17
+ * `env` DI you can pass to `cli.serve(argv, { env })`, so overriding the serve
18
+ * env does NOT move the install target. The effective in-process lever is
19
+ * `global: false` + `cwd: <temp dir>`, which installs under `<cwd>/.agents/skills`
20
+ * (and `<cwd>/.claude/skills` etc.) and leaves the real dirs byte-untouched.
21
+ */
22
+ /**
23
+ * The authored picopilot skills (US #20 discipline skills + the game skills),
24
+ * as SKILL.md files under {@link skillsSourceDir}. They load on-demand by
25
+ * concern and carry the hard-won workflow knowledge (the `#include` discipline,
26
+ * the token breakdown, the `gfx render`→look→`gfx set`→fix loop incl. the
27
+ * non-multimodal fallback, composing in picopilot-MML) so an agent gets it
28
+ * without bloating every turn.
29
+ *
30
+ * The GAME skills are a composed pair (grilled design in
31
+ * work/notes/ideas/game-jam-design-skill.md): `game-jam` (model-invoked, the
32
+ * clock+theme discipline) POINTS AT `game-design-reference` (a user-invoked
33
+ * reference body of universal design principles, `disable-model-invocation`, so
34
+ * it costs no per-turn context and is reached only by pointer, not fired on a
35
+ * vague trigger). Both ship engine-packaged here; `game-design-reference`'s
36
+ * CONTENT is engine-agnostic.
37
+ *
38
+ * They ship ALONGSIDE the per-command skills incur auto-generates from the
39
+ * command surface (`sync: { depth: 1 }`), pulled in via an `include` glob; the
40
+ * command surface is still growing, so the named discipline skills are authored
41
+ * rather than tied to a command-group shape that does not exist yet.
42
+ */
43
+ export const SKILL_NAMES = [
44
+ 'picopilot-overview',
45
+ 'picopilot-code',
46
+ 'picopilot-art',
47
+ 'picopilot-audio',
48
+ 'picopilot-debug',
49
+ 'game-design-reference',
50
+ 'game-jam',
51
+ ];
52
+ /**
53
+ * Resolves the on-disk directory that holds the authored `picopilot-*` SKILL.md
54
+ * files (`<packageRoot>/src/skills`). The files ship in the npm package (the
55
+ * package `files` includes `src`), so the same path works from the built
56
+ * `dist/` runtime and from `src/` under tsx: we walk up from THIS module to the
57
+ * package root (the nearest ancestor with a `package.json`) and join `src/skills`,
58
+ * rather than a `dist`-relative path that would not exist (SKILL.md is not
59
+ * compiled).
60
+ */
61
+ export function skillsSourceDir() {
62
+ let dir = dirname(fileURLToPath(import.meta.url));
63
+ const seen = new Set();
64
+ while (!seen.has(dir)) {
65
+ seen.add(dir);
66
+ if (existsSync(join(dir, 'package.json'))) {
67
+ return join(dir, 'src', 'skills');
68
+ }
69
+ const parent = dirname(dir);
70
+ if (parent === dir)
71
+ break;
72
+ dir = parent;
73
+ }
74
+ // Fallback: two levels up from src/engine/skills is the package root.
75
+ return join(dirname(fileURLToPath(import.meta.url)), '..', '..', 'skills');
76
+ }
77
+ /**
78
+ * Installs picopilot's skills (the authored `picopilot-*` discipline skills plus
79
+ * the per-command skills incur generates from the CLI) via incur's
80
+ * `SyncSkills.sync`. This is the real work `init --install-skills` performs.
81
+ *
82
+ * The authored skills are pulled in with an ABSOLUTE `include` glob into
83
+ * {@link skillsSourceDir}, DECOUPLED from `cwd` on purpose: `cwd` selects the
84
+ * install TARGET, the include glob selects the skills SOURCE. That decoupling is
85
+ * what lets a test install to a temp `cwd` while still reading the real authored
86
+ * skills (or its own fixtures), the crux of the isolation contract.
87
+ */
88
+ export async function installSkills(options) {
89
+ const commands = Cli.toCommands.get(options.cli);
90
+ if (commands === undefined) {
91
+ throw new Error('installSkills: the given CLI has no command map (was it built by Cli.create?)');
92
+ }
93
+ const source = options.sourceDir ?? skillsSourceDir();
94
+ const result = await SyncSkills.sync('picopilot', commands, {
95
+ depth: 1,
96
+ description: 'An agent-first toolchain for PICO-8 game development.',
97
+ global: options.global,
98
+ cwd: options.cwd,
99
+ // Absolute glob → resolves against `source`, independent of `cwd`.
100
+ include: [join(source, '*')],
101
+ });
102
+ // Ship skill RESOURCE files (everything a skill dir carries besides SKILL.md).
103
+ // incur 0.4.10's SyncSkills.sync copies ONLY SKILL.md and drops sibling files
104
+ // (see work/notes/observations/incur-syncskills-drops-skill-resource-files.md),
105
+ // so genre code references under e.g. `picopilot-code/reference/` would never
106
+ // reach the installed skill. We backfill them here: for each installed skill
107
+ // path (canonical + each wired agent), copy the matching source skill's
108
+ // non-SKILL.md contents in. This stays inside the already-isolated installSkills
109
+ // seam, so the shared-write isolation test still governs it, and it becomes a
110
+ // no-op (safe to delete) once incur copies full skill dirs.
111
+ const installPaths = [...result.paths, ...result.agents.map((a) => a.path)];
112
+ for (const installedSkillDir of installPaths) {
113
+ copySkillResources(join(source, basename(installedSkillDir)), installedSkillDir);
114
+ }
115
+ return {
116
+ paths: result.paths,
117
+ agents: result.agents.map((a) => ({
118
+ agent: a.agent,
119
+ path: a.path,
120
+ mode: a.mode,
121
+ })),
122
+ skills: result.skills.map((s) => s.name),
123
+ };
124
+ }
125
+ /**
126
+ * Copies a source skill directory's RESOURCE files (everything except SKILL.md)
127
+ * into an already-installed skill directory. This is the workaround for incur
128
+ * 0.4.10 shipping only SKILL.md (see the observation referenced in installSkills):
129
+ * SKILL.md is left to incur (it is already written and may be transformed), and
130
+ * only the sibling resources are backfilled, recursively, preserving structure.
131
+ *
132
+ * Both the source skill and any resources are optional: a skill with no resource
133
+ * files, or a source dir that does not exist (a command-generated skill with no
134
+ * authored source), is a silent no-op. Nothing here reaches outside `destDir`,
135
+ * which is one of the install paths SyncSkills already chose, so it inherits the
136
+ * shared-write isolation of installSkills (tests redirect those paths to a temp).
137
+ */
138
+ function copySkillResources(sourceSkillDir, destDir) {
139
+ if (!existsSync(sourceSkillDir) || !existsSync(destDir))
140
+ return;
141
+ for (const entry of readdirSync(sourceSkillDir)) {
142
+ if (entry === 'SKILL.md')
143
+ continue; // incur owns the manifest; do not clobber it
144
+ cpSync(join(sourceSkillDir, entry), join(destDir, entry), {
145
+ recursive: true,
146
+ });
147
+ }
148
+ }
149
+ //# sourceMappingURL=skills.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skills.js","sourceRoot":"","sources":["../../../src/engine/skills/skills.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { Cli } from 'incur';
2
+ export { createCli } from './cli.js';
3
+ export { VERSION } from './version.js';
4
+ /**
5
+ * The default CLI instance, exported for `incur gen` (typed CTAs) and for
6
+ * embedding picopilot as a Fetch API handler / MCP server.
7
+ */
8
+ declare const cli: Cli.Cli;
9
+ export default cli;
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,GAAG,EAAC,MAAM,OAAO,CAAC;AAG/B,OAAO,EAAC,SAAS,EAAC,MAAM,UAAU,CAAC;AACnC,OAAO,EAAC,OAAO,EAAC,MAAM,cAAc,CAAC;AAErC;;;GAGG;AACH,QAAA,MAAM,GAAG,EAAE,GAAG,CAAC,GAAiB,CAAC;AAEjC,eAAe,GAAG,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,10 @@
1
+ import { createCli } from './cli.js';
2
+ export { createCli } from './cli.js';
3
+ export { VERSION } from './version.js';
4
+ /**
5
+ * The default CLI instance, exported for `incur gen` (typed CTAs) and for
6
+ * embedding picopilot as a Fetch API handler / MCP server.
7
+ */
8
+ const cli = createCli();
9
+ export default cli;
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,SAAS,EAAC,MAAM,UAAU,CAAC;AAEnC,OAAO,EAAC,SAAS,EAAC,MAAM,UAAU,CAAC;AACnC,OAAO,EAAC,OAAO,EAAC,MAAM,cAAc,CAAC;AAErC;;;GAGG;AACH,MAAM,GAAG,GAAY,SAAS,EAAE,CAAC;AAEjC,eAAe,GAAG,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const VERSION: string;
2
+ //# sourceMappingURL=version.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAqBA,eAAO,MAAM,OAAO,QAAgB,CAAC"}
@@ -0,0 +1,19 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { dirname, join } from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+ /**
5
+ * The installed picopilot version, read from the package manifest at load time.
6
+ *
7
+ * Single source of truth: the version lives only in `package.json`. The manifest
8
+ * sits one level above the compiled module (`dist/version.js` → `package.json`)
9
+ * and one level above the source module (`src/version.ts` → `package.json`), so
10
+ * the same relative lookup works for both the built binary and `tsx` dev runs.
11
+ */
12
+ function readVersion() {
13
+ const here = dirname(fileURLToPath(import.meta.url));
14
+ const manifestPath = join(here, '..', 'package.json');
15
+ const manifest = JSON.parse(readFileSync(manifestPath, 'utf8'));
16
+ return manifest.version ?? '0.0.0';
17
+ }
18
+ export const VERSION = readVersion();
19
+ //# sourceMappingURL=version.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.js","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,YAAY,EAAC,MAAM,SAAS,CAAC;AACrC,OAAO,EAAC,OAAO,EAAE,IAAI,EAAC,MAAM,WAAW,CAAC;AACxC,OAAO,EAAC,aAAa,EAAC,MAAM,UAAU,CAAC;AAEvC;;;;;;;GAOG;AACH,SAAS,WAAW;IACnB,MAAM,IAAI,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IACrD,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,cAAc,CAAC,CAAC;IACtD,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,YAAY,EAAE,MAAM,CAAC,CAE7D,CAAC;IACF,OAAO,QAAQ,CAAC,OAAO,IAAI,OAAO,CAAC;AACpC,CAAC;AAED,MAAM,CAAC,MAAM,OAAO,GAAG,WAAW,EAAE,CAAC"}
package/package.json CHANGED
@@ -1,4 +1,50 @@
1
1
  {
2
2
  "name": "picopilot",
3
- "version": "0.0.0"
4
- }
3
+ "version": "0.1.0",
4
+ "description": "An agent-first toolchain for PICO-8 game development, built on the incur CLI framework.",
5
+ "license": "AGPL-3.0-only",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/wighawag/picopilot.git",
9
+ "directory": "packages/picopilot"
10
+ },
11
+ "homepage": "https://github.com/wighawag/picopilot#readme",
12
+ "bugs": "https://github.com/wighawag/picopilot/issues",
13
+ "type": "module",
14
+ "bin": {
15
+ "picopilot": "./dist/bin.js"
16
+ },
17
+ "main": "./dist/index.js",
18
+ "module": "./dist/index.js",
19
+ "types": "./dist/index.d.ts",
20
+ "exports": {
21
+ ".": {
22
+ "types": "./dist/index.d.ts",
23
+ "default": "./dist/index.js"
24
+ }
25
+ },
26
+ "files": [
27
+ "dist",
28
+ "src"
29
+ ],
30
+ "engines": {
31
+ "node": ">=22"
32
+ },
33
+ "dependencies": {
34
+ "incur": "0.4.10"
35
+ },
36
+ "devDependencies": {
37
+ "@types/node": "22.12.0",
38
+ "as-soon": "^0.1.5",
39
+ "tsx": "4.21.0",
40
+ "typescript": "5.9.3",
41
+ "vitest": "3.2.4"
42
+ },
43
+ "scripts": {
44
+ "build": "tsc -p tsconfig.build.json",
45
+ "dev": "as-soon -w src pnpm build",
46
+ "test": "vitest run",
47
+ "test:watch": "vitest",
48
+ "picopilot": "node --import tsx src/bin.ts"
49
+ }
50
+ }