summer-engine 3.1.0 → 3.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 (366) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/.claude-plugin/plugin.json +27 -5
  3. package/.codex-plugin/plugin.json +28 -6
  4. package/.cursor-plugin/plugin.json +27 -5
  5. package/.factory-plugin/plugin.json +27 -5
  6. package/.opencode/plugins/summer.js +1 -1
  7. package/CHANGELOG.md +102 -0
  8. package/README.md +18 -3
  9. package/assets/audit/scene_audit.gd +4136 -0
  10. package/assets/seeing/seeing_probe.gd +1873 -0
  11. package/dist/cli/commands/skills.js +20 -2
  12. package/dist/core/api-client.d.ts +9 -1
  13. package/dist/core/api-client.js +21 -4
  14. package/dist/core/capabilities/agent-playbook.js +46 -0
  15. package/dist/core/capabilities/audit/accept.d.ts +55 -0
  16. package/dist/core/capabilities/audit/accept.js +147 -0
  17. package/dist/core/capabilities/audit/args.d.ts +95 -0
  18. package/dist/core/capabilities/audit/args.js +89 -0
  19. package/dist/core/capabilities/audit/audit.d.ts +56 -0
  20. package/dist/core/capabilities/audit/audit.js +287 -0
  21. package/dist/core/capabilities/audit/frame.d.ts +14 -0
  22. package/dist/core/capabilities/audit/frame.js +35 -0
  23. package/dist/core/capabilities/audit/gaps.d.ts +96 -0
  24. package/dist/core/capabilities/audit/gaps.js +257 -0
  25. package/dist/core/capabilities/audit/judge.d.ts +162 -0
  26. package/dist/core/capabilities/audit/judge.js +1134 -0
  27. package/dist/core/capabilities/audit/math.d.ts +110 -0
  28. package/dist/core/capabilities/audit/math.js +263 -0
  29. package/dist/core/capabilities/audit/summary.d.ts +74 -0
  30. package/dist/core/capabilities/audit/summary.js +212 -0
  31. package/dist/core/capabilities/board.d.ts +31 -0
  32. package/dist/core/capabilities/board.js +43 -0
  33. package/dist/core/capabilities/camera-view.d.ts +4 -2
  34. package/dist/core/capabilities/camera-view.js +6 -3
  35. package/dist/core/capabilities/connect-signal.d.ts +85 -0
  36. package/dist/core/capabilities/connect-signal.js +285 -0
  37. package/dist/core/capabilities/engine-fallbacks.d.ts +5 -0
  38. package/dist/core/capabilities/engine-fallbacks.js +5 -0
  39. package/dist/core/capabilities/engine-ops.d.ts +5 -1
  40. package/dist/core/capabilities/engine-ops.js +0 -3
  41. package/dist/core/capabilities/engine-receipt.d.ts +12 -0
  42. package/dist/core/capabilities/engine-receipt.js +26 -0
  43. package/dist/core/capabilities/file-read.d.ts +64 -0
  44. package/dist/core/capabilities/file-read.js +325 -0
  45. package/dist/core/capabilities/game-task-plan.js +4 -2
  46. package/dist/core/capabilities/grep.d.ts +60 -0
  47. package/dist/core/capabilities/grep.js +190 -0
  48. package/dist/core/capabilities/inspect-node.d.ts +56 -0
  49. package/dist/core/capabilities/inspect-node.js +225 -0
  50. package/dist/core/capabilities/inspect-resource.d.ts +61 -0
  51. package/dist/core/capabilities/inspect-resource.js +376 -0
  52. package/dist/core/capabilities/math3d.d.ts +28 -0
  53. package/dist/core/capabilities/math3d.js +88 -0
  54. package/dist/core/capabilities/motion-generation.d.ts +62 -0
  55. package/dist/core/capabilities/motion-generation.js +138 -0
  56. package/dist/core/capabilities/placement-batch.d.ts +102 -0
  57. package/dist/core/capabilities/placement-batch.js +483 -0
  58. package/dist/core/capabilities/placement-math.d.ts +70 -0
  59. package/dist/core/capabilities/placement-math.js +209 -0
  60. package/dist/core/capabilities/placement-script.d.ts +42 -0
  61. package/dist/core/capabilities/placement-script.js +1096 -0
  62. package/dist/core/capabilities/placement.d.ts +485 -0
  63. package/dist/core/capabilities/placement.js +1731 -0
  64. package/dist/core/capabilities/project-context.d.ts +33 -2
  65. package/dist/core/capabilities/project-context.js +87 -4
  66. package/dist/core/capabilities/replace-node.d.ts +91 -0
  67. package/dist/core/capabilities/replace-node.js +423 -0
  68. package/dist/core/capabilities/runtime-control.d.ts +18 -2
  69. package/dist/core/capabilities/runtime-control.js +67 -2
  70. package/dist/core/capabilities/scene-batch.d.ts +63 -0
  71. package/dist/core/capabilities/scene-batch.js +394 -0
  72. package/dist/core/capabilities/scene-readback.d.ts +36 -0
  73. package/dist/core/capabilities/scene-readback.js +54 -0
  74. package/dist/core/capabilities/seeing/args.d.ts +348 -0
  75. package/dist/core/capabilities/seeing/args.js +178 -0
  76. package/dist/core/capabilities/seeing/candidates.d.ts +127 -0
  77. package/dist/core/capabilities/seeing/candidates.js +282 -0
  78. package/dist/core/capabilities/seeing/math.d.ts +134 -0
  79. package/dist/core/capabilities/seeing/math.js +269 -0
  80. package/dist/core/capabilities/seeing/probe.d.ts +62 -0
  81. package/dist/core/capabilities/seeing/probe.js +188 -0
  82. package/dist/core/capabilities/seeing/scoring.d.ts +235 -0
  83. package/dist/core/capabilities/seeing/scoring.js +639 -0
  84. package/dist/core/capabilities/seeing/seeing.d.ts +233 -0
  85. package/dist/core/capabilities/seeing/seeing.js +1341 -0
  86. package/dist/core/capabilities/seeing/shot-store.d.ts +52 -0
  87. package/dist/core/capabilities/seeing/shot-store.js +204 -0
  88. package/dist/core/capabilities/surface-snap-mesh.d.ts +88 -0
  89. package/dist/core/capabilities/surface-snap-mesh.js +425 -0
  90. package/dist/core/capabilities/surface-snap.d.ts +77 -0
  91. package/dist/core/capabilities/surface-snap.js +461 -0
  92. package/dist/core/capabilities/tool-dispatch.js +231 -72
  93. package/dist/core/capabilities/tscn.d.ts +85 -0
  94. package/dist/core/capabilities/tscn.js +391 -0
  95. package/dist/core/capabilities/world-snapshot.d.ts +58 -0
  96. package/dist/core/capabilities/world-snapshot.js +150 -0
  97. package/dist/core/capability-skew.d.ts +5 -5
  98. package/dist/core/capability-skew.js +14 -6
  99. package/dist/core/headless/worker-engine-client.d.ts +1 -1
  100. package/dist/core/headless/worker-engine-client.js +2 -2
  101. package/dist/core/library-read.d.ts +37 -5
  102. package/dist/core/library-read.js +264 -33
  103. package/dist/core/library-search.d.ts +2 -2
  104. package/dist/installer/agent-config.js +5 -3
  105. package/dist/installer/agent-table.d.ts +16 -0
  106. package/dist/installer/agent-table.js +52 -17
  107. package/dist/mcp/server.js +9 -3
  108. package/dist/mcp/tools/asset-tools.js +21 -3
  109. package/dist/mcp/tools/audit-tools.d.ts +23 -0
  110. package/dist/mcp/tools/audit-tools.js +60 -0
  111. package/dist/mcp/tools/debug-tools.js +3 -1
  112. package/dist/mcp/tools/file-tools.js +17 -4
  113. package/dist/mcp/tools/generate-tools.js +74 -66
  114. package/dist/mcp/tools/library-tools.js +2 -0
  115. package/dist/mcp/tools/perception-tools.js +6 -19
  116. package/dist/mcp/tools/placement-tools.d.ts +24 -0
  117. package/dist/mcp/tools/placement-tools.js +91 -0
  118. package/dist/mcp/tools/project-tools.js +18 -15
  119. package/dist/mcp/tools/scene-tools.js +71 -83
  120. package/dist/mcp/tools/seeing-tools.d.ts +24 -0
  121. package/dist/mcp/tools/seeing-tools.js +64 -0
  122. package/dist/mcp/tools/spatial-tools.js +17 -9
  123. package/dist/mcp/tools/visual-tools.js +59 -7
  124. package/gemini-extension.json +26 -4
  125. package/integrations/amp/README.md +1 -1
  126. package/integrations/crush/README.md +1 -1
  127. package/integrations/grok-build/README.md +1 -1
  128. package/integrations/hermes/README.md +1 -1
  129. package/integrations/kimi-code/README.md +1 -1
  130. package/integrations/mistral-vibe/README.md +1 -1
  131. package/integrations/opencode/README.md +1 -1
  132. package/integrations/rovo-dev/README.md +1 -1
  133. package/integrations/vscode-copilot/README.md +1 -1
  134. package/integrations/warp/README.md +1 -1
  135. package/integrations/windsurf/README.md +1 -1
  136. package/library/references/mcp-tools-reference/mcp-tools-reference.md +59 -15
  137. package/library/references/mcp-tools-reference/resource.yaml +1 -1
  138. package/library/references/summer-folder/resource.yaml +1 -1
  139. package/library/references/summer-folder/summer-folder.md +1 -1
  140. package/library/skills/3d-lighting/SKILL.md +1 -1
  141. package/library/skills/README.md +36 -14
  142. package/library/skills/adaptive-music/SKILL.md +1 -1
  143. package/library/skills/agent-playtesting/SKILL.md +1 -1
  144. package/library/skills/ai-characters-in-games/SKILL.md +220 -0
  145. package/library/skills/ai-characters-in-games/resource.yaml +30 -0
  146. package/library/skills/ambient-bed/SKILL.md +1 -1
  147. package/library/skills/animated-loop/SKILL.md +1 -1
  148. package/library/skills/animation-tree/SKILL.md +1 -1
  149. package/library/skills/art-direction/SKILL.md +1 -1
  150. package/library/skills/asset-strategy/SKILL.md +2 -1
  151. package/library/skills/asset-strategy/resource.yaml +2 -1
  152. package/library/skills/audio-direction/SKILL.md +1 -1
  153. package/library/skills/auto-fire-targeting/SKILL.md +1 -1
  154. package/library/skills/brainstorm-game/SKILL.md +1 -1
  155. package/library/skills/brainstorming/SKILL.md +1 -1
  156. package/library/skills/browse-templates/SKILL.md +3 -3
  157. package/library/skills/browse-templates/resource.yaml +1 -1
  158. package/library/skills/camera-rigs/SKILL.md +128 -0
  159. package/library/skills/camera-rigs/resource.yaml +29 -0
  160. package/library/skills/celeste-momentum-platforming/SKILL.md +1 -1
  161. package/library/skills/character-animation-wiring/SKILL.md +1 -1
  162. package/library/skills/character-model/SKILL.md +1 -1
  163. package/library/skills/character-movement/SKILL.md +326 -0
  164. package/library/skills/character-movement/references/default-third-person-controller.gd +201 -0
  165. package/library/skills/character-movement/references/default-third-person-verification-probe.gd +154 -0
  166. package/library/skills/character-movement/references/movement-3d.md +136 -0
  167. package/library/skills/character-movement/references/platformer-feel.md +83 -0
  168. package/library/skills/character-movement/resource.yaml +40 -0
  169. package/library/skills/character-portrait/SKILL.md +1 -1
  170. package/library/skills/cinematic-cutscene/SKILL.md +1 -1
  171. package/library/skills/combat-basics/SKILL.md +159 -0
  172. package/library/skills/combat-basics/references/projectiles-and-aoe.md +100 -0
  173. package/library/skills/combat-basics/resource.yaml +34 -0
  174. package/library/skills/concept-art/SKILL.md +1 -1
  175. package/library/skills/create-asset-sheet/SKILL.md +1 -1
  176. package/library/skills/debug/SKILL.md +1 -1
  177. package/library/skills/debugging-game-feel/SKILL.md +1 -1
  178. package/library/skills/design-level/SKILL.md +1 -1
  179. package/library/skills/design-mechanic/SKILL.md +1 -1
  180. package/library/skills/design-npc/SKILL.md +1 -1
  181. package/library/skills/diagnosing-perf-regressions/SKILL.md +1 -1
  182. package/library/skills/dispatching-parallel-agents/SKILL.md +1 -1
  183. package/library/skills/driving-the-editor-ui/SKILL.md +1 -1
  184. package/library/skills/environment-kit/SKILL.md +1 -1
  185. package/library/skills/export-and-ship/SKILL.md +1 -1
  186. package/library/skills/fabricating-assets/SKILL.md +1 -1
  187. package/library/skills/facial-and-lipsync/SKILL.md +1 -1
  188. package/library/skills/fps-controller/SKILL.md +9 -7
  189. package/library/skills/fps-controller/resource.yaml +4 -1
  190. package/library/skills/game-feel/SKILL.md +1 -1
  191. package/library/skills/gameskill/SKILL.md +1 -1
  192. package/library/skills/gdscript-patterns/SKILL.md +1 -1
  193. package/library/skills/generate-motion/SKILL.md +9 -9
  194. package/library/skills/generate-motion/resource.yaml +2 -1
  195. package/library/skills/godogen-visual-proof-game-generation/SKILL.md +1 -1
  196. package/library/skills/headless-scripting/SKILL.md +1 -1
  197. package/library/skills/in-game-purchases/SKILL.md +254 -0
  198. package/library/skills/in-game-purchases/resource.yaml +29 -0
  199. package/library/skills/instantiate-asset-pack/SKILL.md +1 -1
  200. package/library/skills/investigating-bugs/SKILL.md +1 -1
  201. package/library/skills/lumera-single-image-scene-reconstruction/SKILL.md +1 -1
  202. package/library/skills/make-game/SKILL.md +25 -3
  203. package/library/skills/make-game/references/2d-platformer-polish.md +93 -0
  204. package/library/skills/make-game/references/2d-platformer.md +117 -0
  205. package/library/skills/make-game/references/2d-rpg-content.md +234 -0
  206. package/library/skills/make-game/references/2d-rpg.md +241 -0
  207. package/library/skills/make-game/references/2d-survivors-progression.md +201 -0
  208. package/library/skills/make-game/references/2d-survivors.md +237 -0
  209. package/library/skills/make-game/references/3d-fps-systems.md +216 -0
  210. package/library/skills/make-game/references/3d-fps.md +177 -0
  211. package/library/skills/make-game/references/3d-horror-systems.md +186 -0
  212. package/library/skills/make-game/references/3d-horror.md +201 -0
  213. package/library/skills/make-game/references/3d-third-person-systems.md +220 -0
  214. package/library/skills/make-game/references/3d-third-person.md +215 -0
  215. package/library/skills/make-game/resource.yaml +6 -1
  216. package/library/skills/multiplayer/SKILL.md +150 -0
  217. package/library/skills/multiplayer/resource.yaml +33 -0
  218. package/library/skills/multiplayer-movement/SKILL.md +510 -0
  219. package/library/skills/multiplayer-movement/files.md +501 -0
  220. package/library/skills/multiplayer-movement/resource.yaml +30 -0
  221. package/library/skills/multiplayer-project/SKILL.md +521 -0
  222. package/library/skills/multiplayer-project/files.md +448 -0
  223. package/library/skills/multiplayer-project/resource.yaml +36 -0
  224. package/library/skills/multiplayer-publish/SKILL.md +229 -0
  225. package/library/skills/multiplayer-publish/export-errors.md +89 -0
  226. package/library/skills/multiplayer-publish/resource.yaml +28 -0
  227. package/library/skills/multiplayer-state/SKILL.md +438 -0
  228. package/library/skills/multiplayer-state/files.md +592 -0
  229. package/library/skills/multiplayer-state/resource.yaml +35 -0
  230. package/library/skills/multiplayer-testing/SKILL.md +236 -0
  231. package/library/skills/multiplayer-testing/resource.yaml +39 -0
  232. package/library/skills/music-track/SKILL.md +1 -1
  233. package/library/skills/navigate-summer/SKILL.md +1 -1
  234. package/library/skills/new-project/SKILL.md +1 -1
  235. package/library/skills/organic-model/SKILL.md +1 -1
  236. package/library/skills/pixel-art/SKILL.md +1 -1
  237. package/library/skills/play/SKILL.md +1 -1
  238. package/library/skills/playtesting-a-feature/SKILL.md +1 -1
  239. package/library/skills/procedural-animation/SKILL.md +2 -2
  240. package/library/skills/procedural-animation/resource.yaml +1 -1
  241. package/library/skills/prop-model/SKILL.md +1 -1
  242. package/library/skills/psx-retro-rendering/SKILL.md +1 -1
  243. package/library/skills/realtime-wet-surfaces/SKILL.md +2 -2
  244. package/library/skills/remote-deploy/SKILL.md +1 -1
  245. package/library/skills/retarget/SKILL.md +1 -1
  246. package/library/skills/running-in-the-cloud/SKILL.md +1 -1
  247. package/library/skills/save-load/SKILL.md +156 -0
  248. package/library/skills/save-load/resource.yaml +27 -0
  249. package/library/skills/scene-composition/SKILL.md +1 -1
  250. package/library/skills/scene-hierarchy-design/SKILL.md +1 -1
  251. package/library/skills/scene-scripting/SKILL.md +1 -1
  252. package/library/skills/scene-to-level/SKILL.md +1 -1
  253. package/library/skills/skill-create/SKILL.md +1 -1
  254. package/library/skills/skill-improve/SKILL.md +1 -1
  255. package/library/skills/skill-test/SKILL.md +1 -1
  256. package/library/skills/skintokens-auto-rigging/SKILL.md +1 -1
  257. package/library/skills/skybox-panorama/SKILL.md +1 -1
  258. package/library/skills/sound-effect/SKILL.md +1 -1
  259. package/library/skills/spatial-placement/SKILL.md +134 -3
  260. package/library/skills/spatial-placement/references/kit-placement-tools.md +364 -0
  261. package/library/skills/spatial-placement/resource.yaml +16 -2
  262. package/library/skills/sprite-sheet/SKILL.md +1 -1
  263. package/library/skills/summer-analytics/SKILL.md +147 -0
  264. package/library/skills/summer-analytics/resource.yaml +28 -0
  265. package/library/skills/summer-friends/SKILL.md +226 -0
  266. package/library/skills/summer-friends/resource.yaml +28 -0
  267. package/library/skills/summer-leaderboards/SKILL.md +231 -0
  268. package/library/skills/summer-leaderboards/resource.yaml +30 -0
  269. package/library/skills/summer-match-results/SKILL.md +286 -0
  270. package/library/skills/summer-match-results/resource.yaml +32 -0
  271. package/library/skills/summer-matchmaking/SKILL.md +301 -0
  272. package/library/skills/summer-matchmaking/resource.yaml +32 -0
  273. package/library/skills/summer-parties/SKILL.md +253 -0
  274. package/library/skills/summer-parties/resource.yaml +30 -0
  275. package/library/skills/summer-player-data/SKILL.md +322 -0
  276. package/library/skills/summer-player-data/resource.yaml +30 -0
  277. package/library/skills/summer-store/SKILL.md +271 -0
  278. package/library/skills/summer-store/resource.yaml +29 -0
  279. package/library/skills/summer-world-chat/SKILL.md +195 -0
  280. package/library/skills/summer-world-chat/resource.yaml +30 -0
  281. package/library/skills/summer-world-saves/SKILL.md +284 -0
  282. package/library/skills/summer-world-saves/resource.yaml +29 -0
  283. package/library/skills/text-to-motion/SKILL.md +99 -0
  284. package/library/skills/text-to-motion/prompts-and-controls.md +34 -0
  285. package/library/skills/text-to-motion/resource.yaml +41 -0
  286. package/library/skills/text-to-motion/rigging-for-text-motion.md +54 -0
  287. package/library/skills/tileable-texture/SKILL.md +1 -1
  288. package/library/skills/trailer-shot/SKILL.md +1 -1
  289. package/library/skills/tune-performance/SKILL.md +1 -1
  290. package/library/skills/ui-basics/SKILL.md +10 -1
  291. package/library/skills/ui-graphics/SKILL.md +1 -1
  292. package/library/skills/use-widget-asset/SKILL.md +1 -1
  293. package/library/skills/using-summer/SKILL.md +2 -2
  294. package/library/skills/using-summer/resource.yaml +2 -2
  295. package/library/skills/vehicle-model/SKILL.md +1 -1
  296. package/library/skills/verification-before-completion/SKILL.md +1 -1
  297. package/library/skills/verifying-scenes/SKILL.md +76 -2
  298. package/library/skills/verifying-scenes/resource.yaml +13 -2
  299. package/library/skills/vfx-dissolve/SKILL.md +1 -1
  300. package/library/skills/vfx-fire/SKILL.md +1 -1
  301. package/library/skills/vfx-hit-spark/SKILL.md +1 -1
  302. package/library/skills/vfx-lightning/SKILL.md +1 -1
  303. package/library/skills/vfx-magic-glow/SKILL.md +1 -1
  304. package/library/skills/vfx-muzzle-flash/SKILL.md +1 -1
  305. package/library/skills/vfx-smoke/SKILL.md +1 -1
  306. package/library/skills/vfx-water-ripple/SKILL.md +1 -1
  307. package/library/skills/voice-line/SKILL.md +1 -1
  308. package/library/skills/web-and-touch-input/SKILL.md +38 -0
  309. package/library/skills/web-and-touch-input/resource.yaml +28 -0
  310. package/library/skills/web-compatibility-look/SKILL.md +62 -0
  311. package/library/skills/web-compatibility-look/resource.yaml +30 -0
  312. package/library/skills/world-building-3d/SKILL.md +8 -1
  313. package/library/skills/world-building-3d/references/spatial-tools.md +1 -1
  314. package/library/skills/world-building-3d/resource.yaml +2 -1
  315. package/library/skills/writing-plans/SKILL.md +1 -1
  316. package/library/skills/writing-skills/SKILL.md +1 -1
  317. package/library/templates/3d-lan-multiplayer-starter/resource.yaml +2 -2
  318. package/library/tools/attach-to-surface/resource.yaml +142 -0
  319. package/library/tools/batch/resource.yaml +9 -3
  320. package/library/tools/connect-ports/resource.yaml +120 -0
  321. package/library/tools/connect-signal/resource.yaml +3 -2
  322. package/library/tools/debug-views/resource.yaml +94 -0
  323. package/library/tools/frame-nodes/resource.yaml +104 -0
  324. package/library/tools/frame-shot/resource.yaml +134 -0
  325. package/library/tools/generate-motion/resource.yaml +44 -9
  326. package/library/tools/get-board/resource.yaml +50 -0
  327. package/library/tools/get-project-context/resource.yaml +13 -2
  328. package/library/tools/grep/resource.yaml +77 -0
  329. package/library/tools/inspect-asset/resource.yaml +71 -0
  330. package/library/tools/inspect-node/resource.yaml +9 -2
  331. package/library/tools/inspect-resource/resource.yaml +16 -5
  332. package/library/tools/instantiate-scene/resource.yaml +27 -2
  333. package/library/tools/measure/resource.yaml +96 -0
  334. package/library/tools/place-adjacent/resource.yaml +113 -0
  335. package/library/tools/play/resource.yaml +15 -2
  336. package/library/tools/raycast/resource.yaml +101 -0
  337. package/library/tools/read-file/resource.yaml +36 -2
  338. package/library/tools/read-library/resource.yaml +2 -2
  339. package/library/tools/repeat-along/resource.yaml +129 -0
  340. package/library/tools/replace-node/resource.yaml +11 -5
  341. package/library/tools/scene-audit/resource.yaml +144 -0
  342. package/library/tools/screenshot/resource.yaml +13 -2
  343. package/library/tools/search-assets/resource.yaml +18 -0
  344. package/library/tools/shot-sheet/resource.yaml +110 -0
  345. package/library/tools/snap-to-surface/resource.yaml +4 -1
  346. package/library/tools/world-snapshot/resource.yaml +24 -3
  347. package/library/tools/zoom/resource.yaml +105 -0
  348. package/package.json +1 -1
  349. package/registry/generated/aliases.json +17 -3
  350. package/registry/generated/counts.json +3 -3
  351. package/registry/generated/gemini-extension.json +26 -4
  352. package/registry/generated/index.json +2154 -469
  353. package/registry/generated/marketplace.claude.json +2 -2
  354. package/registry/generated/plugin.claude.json +27 -5
  355. package/registry/generated/plugin.codex.json +28 -6
  356. package/registry/generated/plugin.cursor.json +27 -5
  357. package/registry/generated/plugin.factory.json +27 -5
  358. package/registry/generated/skills-index.md +36 -14
  359. package/registry/generated/skills-registry.json +421 -124
  360. package/registry/generated/templates-registry.json +2 -2
  361. package/library/skills/host-authoritative-state/SKILL.md +0 -332
  362. package/library/skills/host-authoritative-state/resource.yaml +0 -28
  363. package/library/skills/peer-to-peer-multiplayer/SKILL.md +0 -373
  364. package/library/skills/peer-to-peer-multiplayer/resource.yaml +0 -28
  365. package/library/skills/setup-multiplayer/SKILL.md +0 -336
  366. package/library/skills/setup-multiplayer/resource.yaml +0 -28
@@ -76,6 +76,25 @@ function vsCodeGlobalStorage(ctx, extensionId, fileName) {
76
76
  }
77
77
  const home = (...parts) => (ctx) => join(ctx.home, ...parts);
78
78
  const project = (...parts) => (ctx) => join(ctx.cwd, ...parts);
79
+ /**
80
+ * The agentskills.io shared folder: `~/.agents/skills` and `<project>/.agents/skills`.
81
+ * Every agent whose docs say it reads this folder installs here, so one
82
+ * install serves them all and "where are the skills" has one answer.
83
+ */
84
+ const SHARED_SKILLS_USER = home(".agents", "skills");
85
+ const SHARED_SKILLS_PROJECT = project(".agents", "skills");
86
+ function sharedSkills(extra = {}) {
87
+ return { kind: "skill-dir", user: SHARED_SKILLS_USER, project: SHARED_SKILLS_PROJECT, ...extra };
88
+ }
89
+ /** True when this location is the shared agentskills.io folder. */
90
+ export function isSharedSkillsPath(path) {
91
+ return /[\\/]\.agents[\\/]skills$/.test(path);
92
+ }
93
+ /** Agents that read the shared folder at the given scope (for the install summary). */
94
+ export function agentsSharingSkills(scope, ctx) {
95
+ const shared = (scope === "user" ? SHARED_SKILLS_USER : SHARED_SKILLS_PROJECT)(ctx);
96
+ return SPECS.filter((spec) => resolveSkillPath(spec, scope, ctx)?.path === shared);
97
+ }
79
98
  /** agentskills.io layout (`<dir>/<skill>/SKILL.md`) under a user dir and a project dir. */
80
99
  function skillDirs(user, proj, extra = {}) {
81
100
  return { kind: "skill-dir", user, project: proj, ...extra };
@@ -121,7 +140,7 @@ const SPECS = [
121
140
  projectNote: "Codex only loads project .codex/config.toml from trusted projects.",
122
141
  },
123
142
  restart: "Restart Codex or run /mcp in a new session.",
124
- skills: skillDirs(home(".agents", "skills"), project(".agents", "skills")),
143
+ skills: sharedSkills(),
125
144
  },
126
145
  {
127
146
  id: "cursor",
@@ -132,9 +151,10 @@ const SPECS = [
132
151
  format: "json-stdio",
133
152
  mcp: { user: home(".cursor", "mcp.json"), project: project(".cursor", "mcp.json") },
134
153
  restart: "Restart Cursor and enable the summer-engine MCP server if prompted.",
135
- skills: skillDirs(home(".cursor", "skills"), project(".cursor", "skills"), {
136
- reloadHint: "Cursor loads skills in the next chat. Summer 3.0 and earlier wrote rule files to .cursor/rules; `--force` removes those.",
154
+ skills: sharedSkills({
155
+ reloadHint: "Cursor loads skills in the next chat. Summer 3.0 wrote rule files to .cursor/rules and 3.1.0 wrote .cursor/skills; `--force` removes both.",
137
156
  legacyRules: { user: home(".cursor", "rules"), project: project(".cursor", "rules"), suffix: ".mdc" },
157
+ legacyDirs: { user: home(".cursor", "skills"), project: project(".cursor", "skills") },
138
158
  }),
139
159
  },
140
160
  {
@@ -149,7 +169,7 @@ const SPECS = [
149
169
  project: null,
150
170
  },
151
171
  restart: "Restart Devin Desktop (formerly Windsurf) and refresh MCP servers from the agent settings. Devin's docs say mcp_config.json configures the Cascade agent; for the Devin agent add the server in the app's MCP settings with the same command.",
152
- skills: skillDirs(home(".codeium", "windsurf", "skills"), project(".windsurf", "skills")),
172
+ skills: sharedSkills({ legacyDirs: { user: home(".codeium", "windsurf", "skills"), project: project(".windsurf", "skills") } }),
153
173
  },
154
174
  {
155
175
  id: "antigravity",
@@ -259,7 +279,7 @@ const SPECS = [
259
279
  format: "json-vscode",
260
280
  mcp: { user: (ctx) => join(vsCodeUserDir(ctx), "mcp.json"), project: project(".vscode", "mcp.json") },
261
281
  restart: "Restart VS Code or run MCP: List Servers, then start summer-engine in Copilot Agent mode.",
262
- skills: skillDirs(home(".copilot", "skills"), project(".github", "skills")),
282
+ skills: sharedSkills({ legacyDirs: { user: home(".copilot", "skills"), project: project(".github", "skills") } }),
263
283
  },
264
284
  {
265
285
  id: "visual-studio",
@@ -300,9 +320,10 @@ const SPECS = [
300
320
  project: project("opencode.json"),
301
321
  },
302
322
  restart: "Restart OpenCode so it reloads opencode.json.",
303
- skills: skillDirs((ctx) => join(xdgOrAppData(ctx), "opencode", "skills"), project(".opencode", "skills"), {
304
- reloadHint: "OpenCode loads skills from this folder on the next session. Summer 3.0 and earlier wrote markdown under agents/summer; `--force` removes those.",
323
+ skills: sharedSkills({
324
+ reloadHint: "OpenCode loads skills from this folder on the next session. Summer 3.0 wrote markdown under agents/summer and 3.1.0 wrote opencode/skills; `--force` removes both.",
305
325
  legacyRules: { user: (ctx) => join(xdgOrAppData(ctx), "opencode", "agents", "summer"), project: project(".opencode", "agents", "summer"), suffix: ".md" },
326
+ legacyDirs: { user: (ctx) => join(xdgOrAppData(ctx), "opencode", "skills"), project: project(".opencode", "skills") },
306
327
  }),
307
328
  },
308
329
  {
@@ -317,7 +338,7 @@ const SPECS = [
317
338
  project: null,
318
339
  },
319
340
  restart: "Zed reloads settings.json live; open the Agent panel and check summer-engine under MCP servers.",
320
- skills: skillDirs(home(".agents", "skills"), project(".agents", "skills")),
341
+ skills: sharedSkills(),
321
342
  },
322
343
  {
323
344
  id: "kiro",
@@ -355,8 +376,9 @@ const SPECS = [
355
376
  format: "yaml-hermes",
356
377
  mcp: { user: home(".hermes", "config.yaml"), project: null },
357
378
  restart: "Run /reload-mcp in Hermes Agent (or restart it).",
358
- skills: skillDirs(home(".hermes", "skills"), project(".hermes", "skills"), {
379
+ skills: skillDirs(home(".hermes", "skills"), SHARED_SKILLS_PROJECT, {
359
380
  reloadHint: "Project skills need `hermes skills trust` before Hermes loads them.",
381
+ legacyDirs: { user: home(".hermes", "skills"), project: project(".hermes", "skills") },
360
382
  }),
361
383
  },
362
384
  {
@@ -395,7 +417,7 @@ const SPECS = [
395
417
  format: "json",
396
418
  mcp: { user: home(".kimi-code", "mcp.json"), project: project(".kimi-code", "mcp.json") },
397
419
  restart: "Restart Kimi Code CLI so it reconnects its MCP servers.",
398
- skills: skillDirs(home(".kimi-code", "skills"), project(".kimi-code", "skills")),
420
+ skills: sharedSkills({ legacyDirs: { user: home(".kimi-code", "skills"), project: project(".kimi-code", "skills") } }),
399
421
  },
400
422
  {
401
423
  id: "crush",
@@ -409,7 +431,7 @@ const SPECS = [
409
431
  project: project(".crushrc"),
410
432
  },
411
433
  restart: "Restart Crush so it reloads crushrc.",
412
- skills: skillDirs(home(".config", "crush", "skills"), project(".crush", "skills")),
434
+ skills: sharedSkills({ legacyDirs: { user: home(".config", "crush", "skills"), project: project(".crush", "skills") } }),
413
435
  },
414
436
  {
415
437
  id: "amp",
@@ -420,7 +442,7 @@ const SPECS = [
420
442
  format: "json-amp",
421
443
  mcp: { user: (ctx) => join(xdgOrAppData(ctx), "amp", "settings.json"), project: null },
422
444
  restart: "Restart Amp so it reloads settings.json.",
423
- skills: skillDirs((ctx) => join(xdgOrAppData(ctx), "amp", "skills"), project(".agents", "skills")),
445
+ skills: sharedSkills({ legacyDirs: { user: (ctx) => join(xdgOrAppData(ctx), "amp", "skills"), project: null } }),
424
446
  },
425
447
  {
426
448
  id: "factory",
@@ -431,7 +453,7 @@ const SPECS = [
431
453
  format: "json-stdio",
432
454
  mcp: { user: home(".factory", "mcp.json"), project: project(".factory", "mcp.json") },
433
455
  restart: "Restart droid or run /mcp in the active session.",
434
- skills: skillDirs(home(".factory", "skills"), project(".factory", "skills")),
456
+ skills: sharedSkills({ legacyDirs: { user: home(".factory", "skills"), project: project(".factory", "skills") } }),
435
457
  },
436
458
  {
437
459
  id: "junie",
@@ -454,7 +476,7 @@ const SPECS = [
454
476
  format: "json",
455
477
  mcp: { user: home(".warp", ".mcp.json"), project: project(".warp", ".mcp.json") },
456
478
  restart: "Warp detects the file and spawns the server; check Settings > AI > MCP servers.",
457
- skills: skillDirs(home(".warp", "skills"), project(".warp", "skills")),
479
+ skills: sharedSkills({ legacyDirs: { user: home(".warp", "skills"), project: project(".warp", "skills") } }),
458
480
  },
459
481
  {
460
482
  id: "rovo-dev",
@@ -465,7 +487,7 @@ const SPECS = [
465
487
  format: "json-transport",
466
488
  mcp: { user: home(".rovodev", "mcp.json"), project: null },
467
489
  restart: "Restart Rovo Dev CLI so it reconnects its MCP servers.",
468
- skills: skillDirs(home(".rovodev", "skills"), project(".rovodev", "skills")),
490
+ skills: sharedSkills({ legacyDirs: { user: home(".rovodev", "skills"), project: project(".rovodev", "skills") } }),
469
491
  },
470
492
  {
471
493
  id: "qoder",
@@ -487,7 +509,7 @@ const SPECS = [
487
509
  format: "toml",
488
510
  mcp: { user: home(".grok", "config.toml"), project: project(".grok", "config.toml") },
489
511
  restart: "Restart Grok Build so it reloads config.toml (it also reads ~/.claude.json and .cursor/mcp.json).",
490
- skills: skillDirs(home(".grok", "skills"), project(".grok", "skills")),
512
+ skills: sharedSkills({ legacyDirs: { user: home(".grok", "skills"), project: project(".grok", "skills") } }),
491
513
  },
492
514
  {
493
515
  id: "mistral-vibe",
@@ -498,7 +520,7 @@ const SPECS = [
498
520
  format: "toml-array",
499
521
  mcp: { user: home(".vibe", "config.toml"), project: project(".vibe", "config.toml") },
500
522
  restart: "Restart Vibe so it reloads config.toml.",
501
- skills: skillDirs(home(".vibe", "skills"), project(".vibe", "skills")),
523
+ skills: skillDirs(home(".vibe", "skills"), SHARED_SKILLS_PROJECT, { legacyDirs: { user: home(".vibe", "skills"), project: project(".vibe", "skills") } }),
502
524
  },
503
525
  {
504
526
  id: "lm-studio",
@@ -573,6 +595,19 @@ export function legacyRuleFiles(spec, scope, ctx, skillNames) {
573
595
  const prefix = spec.id === "opencode" ? "" : "summer-";
574
596
  return [...skillNames].map((name) => join(dir, `${prefix}${name}${legacy.suffix}`));
575
597
  }
598
+ /** Skill dirs a Summer 3.1.0 install may have written at this agent's old native location; `null` when it never moved. */
599
+ export function legacySkillDirs(spec, scope, ctx, skillNames) {
600
+ const legacy = spec.skills?.legacyDirs;
601
+ if (!legacy)
602
+ return null;
603
+ const dir = scope === "project" ? (legacy.project ? legacy.project(ctx) : null) : legacy.user(ctx);
604
+ if (!dir)
605
+ return [];
606
+ const current = resolveSkillPath(spec, scope, ctx)?.path;
607
+ if (current === dir)
608
+ return [];
609
+ return [...skillNames].map((name) => join(dir, name));
610
+ }
576
611
  /** Where skills go for an agent with a skills home. */
577
612
  export function resolveSkillPath(spec, scope, ctx) {
578
613
  if (!spec.skills)
@@ -4,10 +4,13 @@ import { EngineApiClient } from "../core/api-client.js";
4
4
  import { registerSceneTools } from "./tools/scene-tools.js";
5
5
  import { registerDebugTools } from "./tools/debug-tools.js";
6
6
  import { registerVisualTools } from "./tools/visual-tools.js";
7
+ import { registerSeeingTools } from "./tools/seeing-tools.js";
8
+ import { registerAuditTools } from "./tools/audit-tools.js";
7
9
  import { WITH_ENGINE_META } from "./tools/with-engine.js";
8
10
  import { registerPlaybookPrompt, registerProjectTools, } from "./tools/project-tools.js";
9
11
  import { registerPerceptionTools } from "./tools/perception-tools.js";
10
12
  import { registerSpatialTools } from "./tools/spatial-tools.js";
13
+ import { registerPlacementTools } from "./tools/placement-tools.js";
11
14
  import { registerScriptTools } from "./tools/script-tools.js";
12
15
  import { registerEventTools } from "./tools/event-tools.js";
13
16
  import { registerFabricateTools } from "./tools/fabricate-tools.js";
@@ -36,10 +39,10 @@ export const getCachedBootDriftNotice = getCachedNotice;
36
39
  * it costs a few hundred tokens once; the full operating guide stays in the
37
40
  * summer_agent_playbook prompt / summer_get_agent_playbook tool.
38
41
  */
39
- export const SUMMER_MCP_INSTRUCTIONS = "Summer Engine MCP. Call summer_get_project_context first: it binds this session to the open project and returns mainScene, projectMemory (GameSoul, template pin) and any capabilitySkewWarning. " +
40
- "Before building or fixing, summer_search_library then summer_read_library the hit — skills, examples and templates live there. " +
42
+ export const SUMMER_MCP_INSTRUCTIONS = "Summer Engine MCP. Call summer_get_project_context first: it binds this session to the open project and returns mainScene, projectMemory (GameSoul, template pin) and any capabilitySkewWarning, compactly. " +
43
+ "Before building or fixing, summer_search_library then summer_read_library the hit: skills, examples, templates live there. " +
41
44
  "After a playthrough read summer_get_diagnostics, not summer_get_console alone (runtime errors live in the debugger). " +
42
- "A uniformly black screenshot means the viewport had not redrawn — recapture before concluding. " +
45
+ "An all-black screenshot means the viewport had not redrawn — recapture before concluding. " +
43
46
  "Report entries you verified in-engine via summer_library_feedback.";
44
47
  /**
45
48
  * Fire-and-forget probe of the npm registry on MCP boot. Caches the result for
@@ -302,6 +305,8 @@ export function createMcpServer() {
302
305
  registerSceneTools(server);
303
306
  registerDebugTools(server);
304
307
  registerVisualTools(server);
308
+ registerSeeingTools(server);
309
+ registerAuditTools(server);
305
310
  registerProjectTools(server);
306
311
  registerFileTools(server);
307
312
  registerAssetTools(server);
@@ -311,6 +316,7 @@ export function createMcpServer() {
311
316
  registerScriptTools(server);
312
317
  registerPerceptionTools(server);
313
318
  registerSpatialTools(server);
319
+ registerPlacementTools(server);
314
320
  registerNavigationTools(server);
315
321
  registerLibraryTools(server);
316
322
  registerEventTools(server);
@@ -23,6 +23,12 @@ async function searchAssetsApi(params) {
23
23
  if (params.source) {
24
24
  searchParams.set("source", params.source);
25
25
  }
26
+ if (params.style)
27
+ searchParams.set("style", params.style);
28
+ if (params.includeCommunity)
29
+ searchParams.set("includeCommunity", "true");
30
+ if (params.preview)
31
+ searchParams.set("contactSheet", "true");
26
32
  const gatewayUrl = await resolveGatewayUrl();
27
33
  const res = await fetch(`${gatewayUrl}/api/mcp/assets?${searchParams}`, {
28
34
  headers: { Authorization: `Bearer ${token}` },
@@ -120,7 +126,10 @@ Sources:
120
126
  - "all" — Search both library and your assets.
121
127
 
122
128
  Uses hybrid search: keywords + semantic similarity. Finds assets by name AND by meaning.
123
- Returns asset names, types, preview URLs, and import-ready file URLs.
129
+ Returns asset names, types, each asset's art style, preview URLs, and import-ready file URLs.
130
+ Keep a game in ONE art direction: pass style (the game's chosen family) so clashing styles are
131
+ left out, and set preview to see the first results as one numbered picture before importing.
132
+ Curated, open-source and Summer packs come first; people's own public generations only with includeCommunity.
124
133
 
125
134
  Cloud tool — works WITHOUT the Summer Engine app open.
126
135
  Requires authentication (so we can attribute usage and apply per-user rate limits): run 'npx -y summer-engine@latest login' first.`, {
@@ -128,8 +137,14 @@ Requires authentication (so we can attribute usage and apply per-user rate limit
128
137
  assetType: z.enum(["2d_image", "animation", "3d_model", "audio", "music", "all"]).default("all").describe("Filter by asset type"),
129
138
  limit: z.number().default(10).describe("Max results (1-20)"),
130
139
  source: z.enum(["library", "my_assets", "all"]).default("library").describe("Where to search: library (public 25k+), my_assets (your generated assets), all"),
131
- }, async ({ query, assetType, limit, source }) => {
132
- const result = await searchAssetsApi({ query, assetType, limit: Math.min(limit, 20), source });
140
+ style: z
141
+ .enum(["realistic", "stylized-lowpoly", "toon", "pixel", "hand-painted", "voxel"])
142
+ .optional()
143
+ .describe("The game's one art direction: clashing styles are left out, matches come first"),
144
+ preview: z.boolean().default(false).describe("Also return one picture of the first 9 results, numbered in order, to see them before importing"),
145
+ includeCommunity: z.boolean().default(false).describe("Also include people's own public AI generations"),
146
+ }, async ({ query, assetType, limit, source, style, preview, includeCommunity }) => {
147
+ const result = await searchAssetsApi({ query, assetType, limit: Math.min(limit, 20), source, style, preview, includeCommunity });
133
148
  if (result.error) {
134
149
  return {
135
150
  content: [
@@ -141,6 +156,7 @@ Requires authentication (so we can attribute usage and apply per-user rate limit
141
156
  isError: true,
142
157
  };
143
158
  }
159
+ const sheet = result.contactSheet?.match(/^data:(image\/[a-z]+);base64,(.+)$/);
144
160
  return {
145
161
  content: [
146
162
  {
@@ -150,8 +166,10 @@ Requires authentication (so we can attribute usage and apply per-user rate limit
150
166
  count: result.count,
151
167
  summary: result.summary,
152
168
  message: result.message,
169
+ ...(sheet ? { preview: "attached: the first results, numbered in this order" } : {}),
153
170
  }, null, 2),
154
171
  },
172
+ ...(sheet ? [{ type: "image", data: sheet[2], mimeType: sheet[1] }] : []),
155
173
  ],
156
174
  };
157
175
  });
@@ -0,0 +1,23 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { type AuditResult } from "../../core/capabilities/audit/audit.js";
3
+ /**
4
+ * summer_scene_audit: one read-only call that walks every node of a 3D scene
5
+ * and lists likely visual and placement problems, so a build agent knows
6
+ * exactly where to look. Implementation and the in-engine kernel:
7
+ * src/core/capabilities/audit/ and assets/audit/scene_audit.gd.
8
+ */
9
+ type ToolResultContent = {
10
+ type: "text";
11
+ text: string;
12
+ } | {
13
+ type: "image";
14
+ data: string;
15
+ mimeType: string;
16
+ };
17
+ type ToolResult = {
18
+ content: ToolResultContent[];
19
+ isError?: boolean;
20
+ };
21
+ export declare function auditContent(result: AuditResult): ToolResult;
22
+ export declare function registerAuditTools(server: McpServer): void;
23
+ export {};
@@ -0,0 +1,60 @@
1
+ import { withEngine } from "./with-engine.js";
2
+ import { sceneAudit } from "../../core/capabilities/audit/audit.js";
3
+ import { sceneAuditShape } from "../../core/capabilities/audit/args.js";
4
+ export function auditContent(result) {
5
+ if (!result.ok) {
6
+ return {
7
+ isError: true,
8
+ content: [
9
+ {
10
+ type: "text",
11
+ text: JSON.stringify({
12
+ ok: false,
13
+ tool: "summer_scene_audit",
14
+ failure_reason: result.failure_reason,
15
+ error: result.error,
16
+ ...(result.hint ? { hint: result.hint } : {}),
17
+ ...(result.detail ? { detail: result.detail } : {}),
18
+ }),
19
+ },
20
+ ],
21
+ };
22
+ }
23
+ const content = [];
24
+ if (result.image)
25
+ content.push({ type: "image", data: result.image.base64, mimeType: result.image.mime || "image/jpeg" });
26
+ content.push({ type: "text", text: JSON.stringify(result.summary) });
27
+ return { content };
28
+ }
29
+ export function registerAuditTools(server) {
30
+ server.tool("summer_scene_audit", `Audit a 3D scene in one fast, read-only call: every node and subnode is walked and likely visual and placement problems come back as a short list, sorted by severity, so you know exactly where to look. Each issue is a flag to LOOK at, never an auto-fix.
31
+
32
+ Checks (each can be picked with checks):
33
+ - through_hole: capped ray grids through every facade line (coplanar wall fronts); clusters of rays that pass the wall AND reach the far side of the building (a door insert narrower than its frame, a missing module, a seam). Walls, structure and inserts close an opening; props do not.
34
+ - exposed_edge: open outline edges of walls and facade members (bands, piers, corner blocks; cached per mesh) that nothing covers within 4-7 mm, seen from walkable space (eye points over open-sky floor cells, flood-filled from the scene's cameras and characters, sight lines not through a building), with a 2-60 cm reveal behind them, or a coplanar sheet continuing within 4 cm (seam) or 35 cm (gap). Warn on band pieces and when depth_step agrees, look otherwise; repeats group per piece type.
35
+ - open_fixture_end: open ends of run pieces (a mesh with two or more open rims of one size: pipe, duct or gutter sections, elbows, tees) that nothing joins within 2.5 cm (sleeve tolerance), seen from walkable space: a missing elbow, coupler, section or end piece (warn). A piece with one rim or rims of different sizes (a cap, a funnel, an outlet) is open by design.
36
+ - depth_step (look): ray rows across each visible facade side at its band levels and every 1.25 m: band recesses and missing runs, seams, modules standing proud, holes with something behind them; a hole next to a through_hole confirms it (warn -> error); runs a door-like opening covers are skipped.
37
+ - floor_gap: down rays over the floor tiles, along their seams, and from each tile edge to a wall within 1 m (bare strips at wall bases), classified by the FIRST surface hit: the void (error); an underlay over the floor's own lower surface such as a drain channel ("covers the floor", warn, not a hole); an underlay through a hole or strip. Areas are the missed rays' own footprints with the strip's size; a tile whose own mesh has holes is one issue for the piece.
38
+ - floating / sunken: support under each prop's footprint; gap over 2 cm, embed over 3 cm, measured against the first surface from above (the tile it is buried in, not the underlay under it); structure and pieces touching a wall well off the ground excluded.
39
+ - interpenetration: each prop's convex hulls against props, walls, structure and inserts; a deepest overlap over 3 cm, then every partner it cuts (up to 3).
40
+ - orientation (look): long props within 1.2 m of a wall more than 15 deg off parallel. It never says which way a piece should face.
41
+ - uv_stretch: per mesh resource, large triangles whose UV-to-world mapping is stretched over 8:1 or collapsed to a line, where an instance shows them (a reveal that inserts normally cover = warn).
42
+ - duplicate: the same scene at the same transform.
43
+ - z_fight: coplanar overlapping faces anywhere, from each mesh's planar face groups: between any two pieces (props, roofs, ledges, side walls, inserts against hosts, decals; opposite-facing only when both are double-sided) and between two surfaces of one mesh (once per mesh), plus the ray samples. Coplanar = a gap under twice the 24-bit depth step at the view distance (the nearest walkable eye point, camera or bookmark; 30 m without one) for the main camera's near/far; ev carries the overlap, gap, tolerance, surfaces, the plane's normal and the axis to nudge (nudge.world, nudge.local: a window can share its head or a jamb with its host, not its front). Warn over 0.05 m2 seen from a viewpoint; the material decides what is demoted to look, with the reason: render_priority, depth or normal offsets, a see-through (alpha) material, no depth test or depth writes.
44
+ - lights: meshes paired with more than the per-object limit of omni or spot lights (Compatibility: 8 each; light cuts off at seams), spot lights with spot_angle_attenuation under 3; shadowed light counts.
45
+ - transform: NaN, negative or non-uniform scale, a piece far out of bounds, and pieces left at the origin: an identity LOCAL transform under an identity parent, touching nothing and not one of a row of siblings (several sharing it warn, one alone is look; a module whose corner is the world origin is placed).
46
+ - resource: missing dependency files, MeshInstance3D without a mesh, surfaces without a material.
47
+
48
+ budget_ms (default 3000) bounds the editor time: each check gets a weighted share of it, and a check past its share stops and is marked counts.<check>.partial (the share it covered), never clean. The three gap detectors (exposed_edge, open_fixture_end, depth_step) run last on the time the other checks leave (band pieces and band rows first); rerun them alone when partial.
49
+
50
+ accept:[{key, reason}] (keys from issues[].key) records look and warn items you judged fine in res://.summer/audit-accept.json (the only file the audit writes); later audits count them (counts.<check>.accepted) but hide them until their evidence changes materially (severity rises, or the measured size moves by over 25%: shown again with accept_stale). Errors cannot be accepted; show_accepted lists them.
51
+
52
+ Returns at most 5 KB of JSON: counts per check, time per check (editor ms), the scene size, and ONE page of issues {n, check, sev (error|warn|look), path, pos (world), why, ev (evidence numbers: sizes, distances, angles, the ray to reproduce), next (the tool to use next), key (for accept)}. Page with offset/limit (next_offset names the next page); filter with checks, root (a subtree) and min_severity. render:"sheet" adds ONE inline image of the page's first 6 issues framed up close from their open side (a camera never behind a wall), each tile labelled #n.
53
+
54
+ Every check works on any scene from geometry, the engine's node and resource data and materials alone: never node or file names, never kit metadata. Each piece's role comes from its shape: see-through cards (every material alpha) are dressing; thin upright sheets are walls (facing their side with more face area); flat slabs whose tops cover their footprint are floors (raised ones with walls under them are roofs, a large one below the rest is the underlay); a piece inside a wall's rectangle that reaches through the wall where it is open is an insert; bands, piers and corner blocks touching a facade wall are structure; the rest are props up to 3.5 m.
55
+
56
+ Read-only: it audits the SAVED file in a private offscreen copy (ScenePreview), so the open tab never becomes unsaved, undo is untouched and nothing is saved (accept writes only its own file). Save the scene first. Failures are structured (failure_reason), never a silent fallback.`, sceneAuditShape, async (args) => withEngine(async (client) => {
57
+ const audit = await sceneAudit(client, args);
58
+ return audit.ok ? { audit } : { audit, failure_reason: audit.failure_reason };
59
+ }, { onResult: (wrapped) => auditContent(wrapped.audit) }));
60
+ }
@@ -200,7 +200,9 @@ After starting, confirm boot with summer_is_running (boot time varies — never
200
200
 
201
201
  DETERMINISTIC RUNS (newer engines): seed / fixed_fps / time_scale pin THIS launch only (nothing is persisted). seed pins the game's GLOBAL RNG (randi/randf/randi_range/randf_range/randfn, Array.shuffle/pick_random) — it does NOT pin RandomNumberGenerator instances, scripts that call randomize(), rand_from_seed, wall-clock reads, or thread/IO/audio timing. fixed_fps decouples scene time from the wall clock so frame-count-derived state lands on the same frame run to run. The result's \`determinism\` block says whether the pins were applied (applied:false carries a reason: already_running, editor_run_args_override, launch_not_started) and restates seed_scope. If the result has NO determinism block although you sent a pin, the engine predates the params and the run is NOT reproducible — the tool says so; do not claim otherwise. Omitting every pin and instance parameter is exactly the v1 launch.
202
202
 
203
- PLAYTEST LAUNCH (engine runtime-control build): instance + mode:'offscreen' spawn a disposable hidden instance (at most 3) that summer_game_probe / summer_game_input / summer_game_control / summer_runtime_* address by name — run two variants side by side for an A/B. deterministic:true (offscreen only) launches with --fixed-fps 60 --summer-seed --audio-driver Dummy and is what lets summer_game_input action:'replay' accept a seed; speed sets the user time scale on session start. The instance result reports session_attached; poll summer_game_control action:'instances' until attached:true before addressing it. Then: probe -> act -> step/probe -> assert (the agent-playtesting skill). Failure reasons: too_many_instances, instance_exists, session_timeout (child never attached — check summer_get_console), unsupported_mode, main_scene_not_configured. A game already running answers playing:true with determinism.applied:false — summer_stop first to apply seed/fixed_fps.`, {
203
+ PLAYTEST LAUNCH (engine runtime-control build): instance + mode:'offscreen' spawn a disposable hidden instance (at most 3) that summer_game_probe / summer_game_input / summer_game_control / summer_runtime_* address by name — run two variants side by side for an A/B. deterministic:true (offscreen only) launches with --fixed-fps 60 --summer-seed --audio-driver Dummy and is what lets summer_game_input action:'replay' accept a seed; speed sets the user time scale on session start. The instance result reports session_attached; poll summer_game_control action:'instances' until attached:true before addressing it. Then: probe -> act -> step/probe -> assert (the agent-playtesting skill). Failure reasons: too_many_instances, instance_exists, session_timeout (child never attached — check summer_get_console), unsupported_mode, main_scene_not_configured. A game already running answers playing:true with determinism.applied:false — summer_stop first to apply seed/fixed_fps.
204
+
205
+ MULTIPLAYER — LOCAL PLAY (Summer multiplayer games; engine with Local Play): players:N starts the game's authority headless plus N clients on this machine, each joining through the game's OWN Summer.client.join(SummerJoinTarget.queue(...)) — no account, login, Docker, CLI or local-only game code. The scenes and queue come from the project's summer.build.json and its WorldDefinition (client_entry_point + the headless_engine component entry_point); queue picks another declared queue — pass queue WITHOUT players to start that queue's minPlayers (a 4-player queue starts 4), or players to choose; spectators adds spectator clients. local_play.warnings flags a roster outside the queue's minPlayers..maxPlayers. The result's local_play block lists every process (label, role, persona) and the port; failure_reason local_play_unavailable says exactly what to declare. Every process attaches to the editor debugger: screenshots, input and summer_game_* go to the FIRST client, the authority's output is in summer_get_console, and summer_stop stops them all. A join for a different queue fails with a message naming both queues. It is not a proof of sign-in, matchmaking or hosted admission (staging). No local_play block although you sent players means the engine predates Local Play and ran ONE client — the tool says so.`, {
204
206
  scene: z.string().optional().describe("Scene to run instead of main scene, e.g. 'res://levels/test_level.tscn'"),
205
207
  ...playGameExtensionSchema,
206
208
  }, async (args) => {
@@ -1,6 +1,8 @@
1
1
  import { z } from "zod";
2
2
  import { withEngine, ToolInputError } from "./with-engine.js";
3
3
  import { occurrenceCount, readTextPayload, safeProjectPath, validSha256, } from "../../core/capabilities/engine-ops.js";
4
+ import { readFileInputShape, readProjectFileWindow } from "../../core/capabilities/file-read.js";
5
+ import { GREP_DEFAULT_MAX_RESULTS, GREP_MAX_RESULTS, grepInputShape, grepProject, } from "../../core/capabilities/grep.js";
4
6
  // MCP clients may issue tool calls concurrently. Keep the complete read->write
5
7
  // transaction ordered for one project file while allowing unrelated files to
6
8
  // proceed in parallel. The tail is always released in `finally`, so a rejected
@@ -32,10 +34,21 @@ async function withFileMutationTurn(projectIdHash, path, fn) {
32
34
  export function registerFileTools(server) {
33
35
  server.tool("summer_read_file", `Read a text file from the engine-bound project and return its full-file sha256 receipt.
34
36
 
35
- Use the returned sha256 as expected_sha256 when overwriting an existing file. Paths must begin with res://.`, {
36
- path: z.string().describe("Project path, e.g. res://scripts/player.gd"),
37
- max_bytes: z.number().int().positive().max(1_000_000).default(200_000),
38
- }, async ({ path, max_bytes }) => withEngine(async (client) => client.readProjectFile(safeProjectPath(path), max_bytes)));
37
+ Use the returned sha256 as expected_sha256 when overwriting an existing file. Paths must begin with res://.
38
+
39
+ READ BIG FILES IN PARTS instead of all at once:
40
+ - offset + limit page the file: lines by default (unit:'bytes' for a byte range on UTF-8 boundaries). The result's data.window gives start_line/end_line, total_lines, next_offset (null at the end) and eof.
41
+ - For JSON: json_path picks one value ('pieces.wall_a', 'items[3]'); keys keeps matching object keys (['wall_*']); keys_only lists key names only. data.json says what matched. offset/limit then page the selection.
42
+ The sha256 always covers the WHOLE file, so a windowed read still guards a later overwrite. Files over 1 MB can be paged only within their first 1 MB.`, readFileInputShape, async (args) => withEngine(async (client) => readProjectFileWindow(client, args)));
43
+ server.tool("summer_grep", `Search project files with a regular expression (ripgrep, through the engine) and get file + line + text per match, optionally with context lines around each.
44
+
45
+ Use it to find things in big files without reading them whole: every '"fits_into"' in a kit manifest, the scenes of a kit (glob '*.tscn'), where a signal handler is defined. Then read exactly the part you need with summer_read_file (offset/limit, or json_path for JSON).
46
+
47
+ - path: a res:// directory or file (default: the whole project; .godot/ and .import/ are never searched).
48
+ - glob: ripgrep --glob filter ('*.gd', '**/*.json', '!addons/**'). Ripgrep skips files ignored by .gitignore unless a glob names them.
49
+ - context_lines (0-10): lines before/after each match, as before[] / after[].
50
+ - max_results (default ${GREP_DEFAULT_MAX_RESULTS}, max ${GREP_MAX_RESULTS}) caps the matches; truncated:true says there were more. Lines are clipped to max_line_chars.
51
+ Case-insensitive unless case_sensitive:true. Read-only.`, grepInputShape, async (args) => withEngine(async (client) => grepProject(client, args)));
39
52
  server.tool("summer_write_file", `Create or safely overwrite a complete text file through the identity-bound engine.
40
53
 
41
54
  For a new file, set create_only:true. For an existing file, first call summer_read_file and pass its sha256 as expected_sha256. Exactly one guard is required; unguarded writes fail closed. Supports scripts, .tscn scenes, .tres resources, JSON, docs, and project config.`, {
@@ -1,5 +1,7 @@
1
1
  import { z } from "zod";
2
+ import { BOARD_ENDPOINT, boardArgsSchema, boardContent, boardQuery } from "../../core/capabilities/board.js";
2
3
  import { imageGenerationArgsSchema } from "../../core/capabilities/image-generation.js";
4
+ import { buildMotionRequestBody, motionErrorHint, motionGenerationArgsSchema, motionJobFailureHint, } from "../../core/capabilities/motion-generation.js";
3
5
  import { writeFile, mkdir } from "fs/promises";
4
6
  import { tmpdir } from "os";
5
7
  import { join } from "path";
@@ -16,6 +18,7 @@ const TOOL_BY_ENDPOINT = {
16
18
  "/api/mcp/generate/motion": "summer_generate_motion",
17
19
  "/api/mcp/generate/slice-asset-sheet": "summer_slice_asset_sheet",
18
20
  "/api/mcp/workflows": "summer_get_studio_workflow",
21
+ [BOARD_ENDPOINT]: "summer_get_board",
19
22
  };
20
23
  // ---------------------------------------------------------------------------
21
24
  // Shared helpers
@@ -253,6 +256,26 @@ handoff that MCP cannot perform automatically; do not pretend that stage ran.`,
253
256
  return successResult(result.data);
254
257
  });
255
258
  // ========================================================================
259
+ // summer_get_board
260
+ // ========================================================================
261
+ server.tool("summer_get_board", `Read the person's approved planning board for this game: the look (palette,
262
+ description, picture), the characters, the place, the first-minute storyboard
263
+ and the cards they picked, with a version that changes when the board does.
264
+
265
+ The look and the picked cards come back as images you can see. Read the board at
266
+ the start of each build step and compare your screenshot against its images
267
+ (palette, shapes and proportions, camera angle, composition); fix the biggest
268
+ difference. Use the picked card pictures as referenceImageUrl for
269
+ summer_generate_image to make sprites and backgrounds in the same look.
270
+
271
+ Cloud tool — runs on Summer's servers and works WITHOUT the Summer Engine app open.
272
+ Requires authentication: run 'npx -y summer-engine@latest login' first.`, boardArgsSchema.shape, async (args) => {
273
+ const result = await mcpGet(BOARD_ENDPOINT, boardQuery(args), 45_000);
274
+ if (result.error)
275
+ return errorResult(result.error, result.data);
276
+ return { content: boardContent(result.data ?? {}) };
277
+ });
278
+ // ========================================================================
256
279
  // summer_generate_image
257
280
  // ========================================================================
258
281
  server.tool("summer_generate_image", `Generate an image using AI models via Summer Engine Studio.
@@ -651,89 +674,74 @@ Requires authentication: run 'npx -y summer-engine@latest login' first.`, {
651
674
  // ========================================================================
652
675
  // summer_generate_motion
653
676
  //
654
- // NOTE (2026-05-10): only the "meshy-library" backend is exposed today.
655
- // The "hunyuan-custom" path exists in the Studio route but has not been
656
- // tested end-to-end on a user's rig (Hunyuan returns a generic skeleton
657
- // FBX that isn't retargeted onto the caller's character). The schema and
658
- // call are kept commented-out below — re-enable by restoring the wider
659
- // zod enum, the prompt/durationSeconds params, the validation branch, and
660
- // the relevant description lines once the path is verified.
677
+ // Backends exposed: "meshy-library" (curated humanoid mocap by name) and
678
+ // "text-to-motion" (Summer-hosted model, any of the caller's own rigs, from
679
+ // text prompts; default-off on the server until enabled, which answers 400
680
+ // backend_unavailable). The Studio route's "hunyuan-custom" stays hidden: it
681
+ // returns a generic skeleton FBX that is not retargeted onto the caller's
682
+ // rig. The shared zod shape + body builder live in
683
+ // core/capabilities/motion-generation.ts so `summer tool generate-motion`
684
+ // validates identically.
661
685
  // ========================================================================
662
- server.tool("summer_generate_motion", `Generate an animation clip for a Meshy-rigged humanoid character via Summer Engine Studio.
663
-
664
- Backend:
665
- - "meshy-library" — picks a clip from a curated mocap set by name (idle, walk,
666
- run, attack_sword, jump, ~70 standard names). Fast (~30s), cheap (~$0.10),
667
- real mocap quality.
686
+ server.tool("summer_generate_motion", `Generate animation clips for a rigged 3D model via Summer Engine Studio.
687
+
688
+ Backends (pick one):
689
+ - "meshy-library" (default) — a curated mocap clip by motionName on a
690
+ Summer-rigged humanoid (rigAssetId from summer_generate_3d with
691
+ options.rig=true). Fast (~30s), cheap (~$0.10), real mocap quality.
692
+ Names that always work: idle, walk, run, jump, attack; anything else must
693
+ be an exact library name.
694
+ - "text-to-motion" — custom 2-second clips (60 frames) from text prompts on
695
+ ANY of your own rigged models: humanoid, animal, creature, cartoon plant,
696
+ prop (GLB/FBX 3d_model, one skinned armature, 5-70 bones). Use it for
697
+ actions the library lacks (nod, bow, shrug, wave with the right arm) and
698
+ for non-humanoid rigs. Pass prompt or prompts (1-8), optional takes (1-4),
699
+ cfgScale (1.5-8, default 3; 5 for clearer gestures), and lockJoints for
700
+ rooted characters (e.g. ["Hips","Spine"] on a plant; never on characters
701
+ that walk). Human-style bone names (Hips, Spine, LeftArm...) animate far
702
+ better, even on non-humans. Jobs take ~1-2 min; result.assets lists one
703
+ animation asset per prompt x take.
704
+
705
+ Each clip (meshy: each motion; text-to-motion: each prompt x take) is billed.
706
+ State the clip list and estimated cost and confirm with the user before
707
+ spending.
668
708
 
669
- Requires a Meshy-rigged humanoid as the target. The 'rigAssetId' must come from
670
- a prior summer_generate_3d call with options.rig=true.
671
-
672
- By default, waits for completion (up to 5 min) and returns the result directly.
673
- Set wait=false to get the jobId immediately and poll manually with summer_check_job.
674
-
675
- Common motion names:
676
- Locomotion: idle, idle_alert, idle_combat, walk, walk_back, run, sprint,
677
- crouch_idle, crouch_walk, jump, jump_loop, jump_land
678
- Combat: attack_sword, attack_punch, attack_kick, attack_bow, attack_cast,
679
- block, dodge_left, dodge_right, hit_react, death
680
- Social: wave, dance, sit_idle
681
-
682
- Cost: ~$0.10 per clip. Confirm with user before spending.
709
+ By default, waits for completion (up to 10 min) and returns the result directly.
710
+ Set wait=false to get the jobId immediately and poll with summer_check_job.
711
+ Import finished clips with summer_import_asset_by_id.
683
712
 
684
- Custom prompt-driven motion is on the roadmap; not yet shipped. For one-off
685
- signature moves not on the curated list, fall back to hand-authoring in the
686
- Summer Engine or importing from Mixamo.
713
+ Errors: backend_unavailable means text-to-motion is not enabled on this server
714
+ yet — use meshy-library for humanoids and do not retry. Job failures starting
715
+ "text_motion:" (no skinned armature, too many/few joints, unknown joint) are
716
+ input problems and are refunded; fix the rig or request instead of retrying.
687
717
 
688
718
  Cloud tool — runs on Summer's servers and works WITHOUT the Summer Engine app open.
689
- Requires authentication: run 'npx -y summer-engine@latest login' first.`, {
690
- rigAssetId: z
691
- .string()
692
- .describe("Asset ID of a rigged character (from summer_generate_3d with options.rig=true)"),
693
- backend: z
694
- .enum(["meshy-library"])
695
- .default("meshy-library")
696
- .describe("Backend: meshy-library (only option today)"),
697
- motionName: z
698
- .string()
699
- .describe("Curated motion name: walk, run, attack_sword, idle, jump, etc."),
700
- // prompt + durationSeconds reserved for the hunyuan-custom backend (not
701
- // shipped yet — see header comment).
702
- wait: z
703
- .boolean()
704
- .default(true)
705
- .describe("Wait for completion (default true, up to 5 min). Set false to get jobId immediately."),
706
- options: z
707
- .record(z.any())
708
- .optional()
709
- .describe("Backend-specific passthrough"),
710
- }, async ({ rigAssetId, backend, motionName, wait, options }) => {
711
- // Client-side validation
712
- if (!motionName) {
713
- return errorResult("motionName is required (e.g. 'walk', 'run', 'attack_sword'). See the tool description for the curated list.");
719
+ Requires authentication: run 'npx -y summer-engine@latest login' first.`, motionGenerationArgsSchema.shape, async (args) => {
720
+ // Client-side validation of the backend-specific rules.
721
+ const built = buildMotionRequestBody(args);
722
+ if ("error" in built) {
723
+ return errorResult(built.error);
714
724
  }
715
- const body = {
716
- rigAssetId,
717
- backend,
718
- motionName,
719
- options,
720
- };
721
- const result = await mcpGenerate("/api/mcp/generate/motion", body);
725
+ const result = await mcpGenerate("/api/mcp/generate/motion", built.body);
722
726
  if (result.error) {
723
- return errorResult(result.error, result.data);
727
+ const hint = motionErrorHint(result.data?.error);
728
+ return errorResult(result.error, hint ? { ...result.data, hint } : result.data);
724
729
  }
725
730
  const jobId = result.data?.jobId;
726
- if (!wait || !jobId) {
731
+ if (!args.wait || !jobId) {
727
732
  return successResult(result.data);
728
733
  }
729
734
  const pollResult = await pollJob(jobId);
730
735
  if (pollResult.error) {
731
- return errorResult(pollResult.error, { ...pollResult.data, jobId });
736
+ const hint = motionJobFailureHint(pollResult.error);
737
+ return errorResult(pollResult.error, { ...pollResult.data, jobId, ...(hint ? { hint } : {}) });
732
738
  }
733
739
  return successResult({
734
740
  ...pollResult.data,
735
741
  jobId,
736
- message: "Motion generation complete. animationAssetId is in result.",
742
+ message: args.backend === "text-to-motion"
743
+ ? "Motion generation complete. result.assets lists one animation asset per prompt x take; import with summer_import_asset_by_id."
744
+ : "Motion generation complete. animationAssetId is in result.",
737
745
  });
738
746
  });
739
747
  }