summer-engine 3.8.0 → 4.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 (527) hide show
  1. package/.claude-plugin/marketplace.json +2 -13
  2. package/.claude-plugin/plugin.json +24 -22
  3. package/.codex-plugin/plugin.json +18 -22
  4. package/.cursor-plugin/plugin.json +8 -14
  5. package/.factory-plugin/plugin.json +6 -13
  6. package/AGENTS.md +19 -12
  7. package/CHANGELOG.md +133 -0
  8. package/GEMINI.md +3 -3
  9. package/README.md +118 -37
  10. package/assets/icon.png +0 -0
  11. package/commands/start.md +71 -0
  12. package/commands/summer.md +3 -2
  13. package/dist/cli/banner.js +3 -0
  14. package/dist/cli/commands/config.js +3 -2
  15. package/dist/cli/commands/create.js +12 -3
  16. package/dist/cli/commands/list.d.ts +5 -0
  17. package/dist/cli/commands/list.js +30 -13
  18. package/dist/cli/commands/login.d.ts +27 -0
  19. package/dist/cli/commands/login.js +58 -12
  20. package/dist/cli/commands/memory.js +6 -2
  21. package/dist/cli/commands/ops.d.ts +64 -0
  22. package/dist/cli/commands/ops.js +329 -0
  23. package/dist/cli/commands/setup.d.ts +4 -0
  24. package/dist/cli/commands/setup.js +254 -26
  25. package/dist/cli/commands/skills.js +28 -11
  26. package/dist/cli/commands/status.d.ts +26 -0
  27. package/dist/cli/commands/status.js +36 -21
  28. package/dist/cli/index.js +7 -0
  29. package/dist/core/agent-host.d.ts +65 -0
  30. package/dist/core/agent-host.js +193 -0
  31. package/dist/core/capabilities/agent-playbook.d.ts +3 -0
  32. package/dist/core/capabilities/agent-playbook.js +54 -2
  33. package/dist/core/capabilities/apps.d.ts +33 -10
  34. package/dist/core/capabilities/apps.js +25 -12
  35. package/dist/core/capabilities/audit/args.d.ts +6 -6
  36. package/dist/core/capabilities/doctor.d.ts +3 -0
  37. package/dist/core/capabilities/doctor.js +20 -15
  38. package/dist/core/capabilities/fabricate-mesh.d.ts +4 -4
  39. package/dist/core/capabilities/game-task-plan.d.ts +12 -6
  40. package/dist/core/capabilities/game-task-plan.js +80 -5
  41. package/dist/core/capabilities/hdri-import.d.ts +2 -2
  42. package/dist/core/capabilities/motion-generation.d.ts +2 -2
  43. package/dist/core/capabilities/motion-generation.js +2 -2
  44. package/dist/core/capabilities/navigation/open.d.ts +6 -2
  45. package/dist/core/capabilities/navigation/open.js +3 -0
  46. package/dist/core/capabilities/placement.d.ts +23 -23
  47. package/dist/core/capabilities/publish-build.js +2 -0
  48. package/dist/core/capabilities/runtime-control.d.ts +42 -42
  49. package/dist/core/capabilities/scene-script-target.d.ts +17 -0
  50. package/dist/core/capabilities/scene-script-target.js +70 -0
  51. package/dist/core/capabilities/seeing/args.d.ts +16 -16
  52. package/dist/core/capabilities/sfx-choices.d.ts +4 -0
  53. package/dist/core/capabilities/sfx-choices.js +13 -6
  54. package/dist/core/capabilities/tool-dispatch.d.ts +12 -3
  55. package/dist/core/capabilities/tool-dispatch.js +81 -46
  56. package/dist/core/capabilities/ui-control.d.ts +2 -2
  57. package/dist/core/capabilities/world-snapshot.d.ts +4 -4
  58. package/dist/core/embeddings.d.ts +2 -0
  59. package/dist/core/embeddings.js +1 -1
  60. package/dist/core/error-codes.d.ts +62 -0
  61. package/dist/core/error-codes.js +97 -0
  62. package/dist/core/format.d.ts +2 -0
  63. package/dist/core/format.js +2 -1
  64. package/dist/core/hosted-mcp.d.ts +22 -0
  65. package/dist/core/hosted-mcp.js +56 -1
  66. package/dist/core/library-read.js +5 -0
  67. package/dist/core/library-search.d.ts +2 -2
  68. package/dist/core/library-search.js +2 -1
  69. package/dist/core/oauth.js +4 -0
  70. package/dist/core/ops/areas.d.ts +11 -0
  71. package/dist/core/ops/areas.js +24 -0
  72. package/dist/core/ops/catalog.d.ts +45 -0
  73. package/dist/core/ops/catalog.js +157 -0
  74. package/dist/core/ops/cloud.d.ts +64 -0
  75. package/dist/core/ops/cloud.js +198 -0
  76. package/dist/core/ops/contract.d.ts +120 -0
  77. package/dist/core/ops/contract.js +134 -0
  78. package/dist/core/ops/engine-answer.d.ts +25 -0
  79. package/dist/core/ops/engine-answer.js +117 -0
  80. package/dist/core/ops/engine.d.ts +55 -0
  81. package/dist/core/ops/engine.js +649 -0
  82. package/dist/core/ops/public-catalog.d.ts +48 -0
  83. package/dist/core/ops/public-catalog.js +56 -0
  84. package/dist/core/ops/save-files.d.ts +78 -0
  85. package/dist/core/ops/save-files.js +419 -0
  86. package/dist/core/ops/search.d.ts +8 -0
  87. package/dist/core/ops/search.js +187 -0
  88. package/dist/core/skills-registry.d.ts +16 -1
  89. package/dist/core/skills-registry.js +35 -2
  90. package/dist/core/telemetry.d.ts +32 -0
  91. package/dist/core/telemetry.js +38 -10
  92. package/dist/core/tool-profiles.d.ts +25 -0
  93. package/dist/core/tool-profiles.js +41 -0
  94. package/dist/installer/agent-config.d.ts +17 -4
  95. package/dist/installer/agent-config.js +27 -6
  96. package/dist/installer/agent-table.d.ts +12 -0
  97. package/dist/installer/agent-table.js +33 -9
  98. package/dist/installer/cli-permissions.d.ts +65 -0
  99. package/dist/installer/cli-permissions.js +182 -0
  100. package/dist/installer/setup.d.ts +4 -0
  101. package/dist/installer/setup.js +12 -4
  102. package/dist/installer/skills-refresh.d.ts +29 -0
  103. package/dist/installer/skills-refresh.js +261 -0
  104. package/dist/installer/version-check.d.ts +51 -11
  105. package/dist/installer/version-check.js +147 -37
  106. package/dist/mcp/command.js +7 -0
  107. package/dist/mcp/hosted-mount.d.ts +27 -2
  108. package/dist/mcp/hosted-mount.js +53 -23
  109. package/dist/mcp/legacy-toolset.d.ts +27 -0
  110. package/dist/mcp/legacy-toolset.js +43 -0
  111. package/dist/mcp/ops-surface.d.ts +59 -0
  112. package/dist/mcp/ops-surface.js +453 -0
  113. package/dist/mcp/server.d.ts +45 -11
  114. package/dist/mcp/server.js +263 -89
  115. package/dist/mcp/tool-results.d.ts +26 -0
  116. package/dist/mcp/tool-results.js +81 -0
  117. package/dist/mcp/tool-surface.d.ts +65 -0
  118. package/dist/mcp/tool-surface.js +317 -0
  119. package/dist/mcp/tools/app-tools.js +9 -2
  120. package/dist/mcp/tools/asset-tools.js +55 -53
  121. package/dist/mcp/tools/audit-tools.js +21 -21
  122. package/dist/mcp/tools/debug-tools.js +6 -6
  123. package/dist/mcp/tools/fabricate-tools.js +6 -6
  124. package/dist/mcp/tools/generate-tools.js +76 -70
  125. package/dist/mcp/tools/project-tools.d.ts +9 -4
  126. package/dist/mcp/tools/project-tools.js +16 -10
  127. package/dist/mcp/tools/scene-tools.js +12 -23
  128. package/dist/mcp/tools/script-tools.js +9 -5
  129. package/dist/mcp/tools/with-engine.d.ts +6 -0
  130. package/dist/mcp/tools/with-engine.js +19 -0
  131. package/dist/project-memory/agent-instructions.d.ts +47 -0
  132. package/dist/project-memory/agent-instructions.js +226 -0
  133. package/gemini-extension.json +6 -13
  134. package/hooks/pre-commit-doctor.sh +5 -4
  135. package/hooks/session-start.sh +24 -28
  136. package/integrations/README.md +1 -1
  137. package/integrations/claude/README.md +6 -0
  138. package/integrations/claude/manifest-target.json +4 -0
  139. package/integrations/claude-desktop/README.md +1 -1
  140. package/integrations/copilot-jetbrains/README.md +1 -1
  141. package/integrations/gemini/README.md +11 -0
  142. package/integrations/junie/README.md +1 -1
  143. package/integrations/lm-studio/README.md +1 -1
  144. package/integrations/trae/README.md +1 -1
  145. package/integrations/visual-studio/README.md +1 -1
  146. package/integrations/windsurf/README.md +1 -1
  147. package/library/references/mcp-tools-reference/mcp-tools-reference.md +79 -51
  148. package/library/references/mcp-tools-reference/resource.yaml +1 -1
  149. package/library/references/product-map/resource.yaml +2 -2
  150. package/library/skills/3d-lighting/SKILL.md +69 -28
  151. package/library/skills/3d-lighting/resource.yaml +1 -1
  152. package/library/skills/README.md +121 -118
  153. package/library/skills/adaptive-music/SKILL.md +40 -23
  154. package/library/skills/adaptive-music/resource.yaml +1 -1
  155. package/library/skills/agent-playtesting/SKILL.md +23 -1
  156. package/library/skills/agent-playtesting/resource.yaml +1 -1
  157. package/library/skills/ai-characters-in-games/SKILL.md +16 -1
  158. package/library/skills/ai-characters-in-games/resource.yaml +1 -1
  159. package/library/skills/ambient-bed/SKILL.md +38 -13
  160. package/library/skills/ambient-bed/resource.yaml +1 -1
  161. package/library/skills/animated-loop/SKILL.md +60 -32
  162. package/library/skills/animated-loop/resource.yaml +1 -1
  163. package/library/skills/animation-tree/SKILL.md +27 -1
  164. package/library/skills/animation-tree/resource.yaml +1 -1
  165. package/library/skills/art-direction/SKILL.md +17 -3
  166. package/library/skills/art-direction/resource.yaml +1 -1
  167. package/library/skills/asset-strategy/SKILL.md +51 -4
  168. package/library/skills/asset-strategy/resource.yaml +2 -1
  169. package/library/skills/audio-direction/SKILL.md +26 -10
  170. package/library/skills/audio-direction/resource.yaml +1 -1
  171. package/library/skills/auto-fire-targeting/SKILL.md +15 -1
  172. package/library/skills/auto-fire-targeting/resource.yaml +1 -1
  173. package/library/skills/bounded-engine-runs/SKILL.md +1 -1
  174. package/library/skills/bounded-engine-runs/resource.yaml +1 -1
  175. package/library/skills/brainstorm-game/SKILL.md +14 -1
  176. package/library/skills/brainstorm-game/resource.yaml +1 -1
  177. package/library/skills/brainstorming/SKILL.md +1 -1
  178. package/library/skills/brainstorming/resource.yaml +1 -1
  179. package/library/skills/browse-templates/SKILL.md +11 -1
  180. package/library/skills/browse-templates/resource.yaml +1 -1
  181. package/library/skills/camera-rigs/SKILL.md +22 -2
  182. package/library/skills/camera-rigs/resource.yaml +1 -1
  183. package/library/skills/celeste-momentum-platforming/resource.yaml +1 -0
  184. package/library/skills/character-animation-wiring/SKILL.md +28 -4
  185. package/library/skills/character-animation-wiring/resource.yaml +1 -1
  186. package/library/skills/character-model/SKILL.md +83 -47
  187. package/library/skills/character-model/resource.yaml +1 -1
  188. package/library/skills/character-movement/SKILL.md +27 -3
  189. package/library/skills/character-movement/resource.yaml +1 -1
  190. package/library/skills/character-portrait/SKILL.md +39 -19
  191. package/library/skills/character-portrait/resource.yaml +1 -1
  192. package/library/skills/cinematic-cutscene/SKILL.md +79 -46
  193. package/library/skills/cinematic-cutscene/resource.yaml +1 -1
  194. package/library/skills/combat-basics/SKILL.md +20 -1
  195. package/library/skills/combat-basics/resource.yaml +1 -1
  196. package/library/skills/compatibility-renderer-traps/SKILL.md +12 -1
  197. package/library/skills/compatibility-renderer-traps/resource.yaml +1 -1
  198. package/library/skills/concept-art/SKILL.md +29 -12
  199. package/library/skills/concept-art/resource.yaml +1 -1
  200. package/library/skills/concept-to-level/SKILL.md +258 -0
  201. package/library/skills/concept-to-level/references/technical-rules.md +150 -0
  202. package/library/skills/concept-to-level/resource.yaml +44 -0
  203. package/library/skills/create-asset-sheet/SKILL.md +37 -13
  204. package/library/skills/create-asset-sheet/resource.yaml +1 -1
  205. package/library/skills/debug/SKILL.md +34 -2
  206. package/library/skills/debug/resource.yaml +1 -1
  207. package/library/skills/debugging-game-feel/SKILL.md +13 -1
  208. package/library/skills/debugging-game-feel/resource.yaml +1 -1
  209. package/library/skills/design-level/SKILL.md +40 -35
  210. package/library/skills/design-level/resource.yaml +1 -1
  211. package/library/skills/design-mechanic/SKILL.md +18 -1
  212. package/library/skills/design-mechanic/resource.yaml +1 -1
  213. package/library/skills/design-npc/SKILL.md +43 -24
  214. package/library/skills/design-npc/resource.yaml +1 -1
  215. package/library/skills/diagnosing-perf-regressions/SKILL.md +13 -1
  216. package/library/skills/diagnosing-perf-regressions/resource.yaml +1 -1
  217. package/library/skills/driving-the-editor-ui/SKILL.md +24 -1
  218. package/library/skills/driving-the-editor-ui/resource.yaml +1 -1
  219. package/library/skills/environment-kit/SKILL.md +43 -16
  220. package/library/skills/environment-kit/resource.yaml +1 -1
  221. package/library/skills/export-and-ship/SKILL.md +29 -6
  222. package/library/skills/export-and-ship/resource.yaml +1 -1
  223. package/library/skills/fabricating-assets/SKILL.md +30 -7
  224. package/library/skills/fabricating-assets/resource.yaml +3 -3
  225. package/library/skills/facial-and-lipsync/SKILL.md +36 -15
  226. package/library/skills/facial-and-lipsync/resource.yaml +1 -1
  227. package/library/skills/fps-controller/SKILL.md +50 -41
  228. package/library/skills/fps-controller/resource.yaml +1 -1
  229. package/library/skills/game-feel/SKILL.md +34 -8
  230. package/library/skills/game-feel/resource.yaml +1 -1
  231. package/library/skills/gameskill/SKILL.md +15 -4
  232. package/library/skills/gameskill/resource.yaml +1 -1
  233. package/library/skills/gdscript-patterns/SKILL.md +16 -1
  234. package/library/skills/gdscript-patterns/resource.yaml +1 -1
  235. package/library/skills/generate-motion/SKILL.md +51 -21
  236. package/library/skills/generate-motion/resource.yaml +1 -1
  237. package/library/skills/godogen-visual-proof-game-generation/SKILL.md +18 -1
  238. package/library/skills/godogen-visual-proof-game-generation/resource.yaml +1 -0
  239. package/library/skills/grow-analytics/SKILL.md +13 -3
  240. package/library/skills/grow-analytics/resource.yaml +1 -1
  241. package/library/skills/headless-scripting/SKILL.md +14 -1
  242. package/library/skills/headless-scripting/resource.yaml +1 -1
  243. package/library/skills/in-game-purchases/SKILL.md +12 -1
  244. package/library/skills/in-game-purchases/resource.yaml +1 -1
  245. package/library/skills/instantiate-asset-pack/SKILL.md +19 -2
  246. package/library/skills/instantiate-asset-pack/resource.yaml +1 -1
  247. package/library/skills/lumera-single-image-scene-reconstruction/resource.yaml +1 -0
  248. package/library/skills/make-game/SKILL.md +33 -4
  249. package/library/skills/make-game/references/2d-platformer.md +1 -1
  250. package/library/skills/make-game/references/3d-fps.md +1 -1
  251. package/library/skills/make-game/references/3d-horror.md +1 -1
  252. package/library/skills/make-game/references/3d-third-person.md +2 -2
  253. package/library/skills/make-game/resource.yaml +1 -1
  254. package/library/skills/multiplayer/SKILL.md +13 -1
  255. package/library/skills/multiplayer/resource.yaml +1 -1
  256. package/library/skills/multiplayer-movement/SKILL.md +19 -1
  257. package/library/skills/multiplayer-movement/resource.yaml +1 -1
  258. package/library/skills/multiplayer-project/SKILL.md +18 -1
  259. package/library/skills/multiplayer-project/resource.yaml +1 -1
  260. package/library/skills/multiplayer-publish/SKILL.md +25 -7
  261. package/library/skills/multiplayer-publish/resource.yaml +3 -3
  262. package/library/skills/multiplayer-state/SKILL.md +17 -1
  263. package/library/skills/multiplayer-state/resource.yaml +1 -1
  264. package/library/skills/multiplayer-testing/SKILL.md +16 -1
  265. package/library/skills/multiplayer-testing/resource.yaml +1 -1
  266. package/library/skills/music-track/SKILL.md +38 -13
  267. package/library/skills/music-track/resource.yaml +1 -1
  268. package/library/skills/navigate-summer/SKILL.md +26 -9
  269. package/library/skills/navigate-summer/resource.yaml +1 -1
  270. package/library/skills/new-project/SKILL.md +12 -1
  271. package/library/skills/new-project/resource.yaml +1 -1
  272. package/library/skills/organic-model/SKILL.md +48 -18
  273. package/library/skills/organic-model/resource.yaml +1 -1
  274. package/library/skills/pixel-art/SKILL.md +42 -23
  275. package/library/skills/pixel-art/resource.yaml +1 -1
  276. package/library/skills/play/SKILL.md +19 -1
  277. package/library/skills/play/resource.yaml +1 -1
  278. package/library/skills/playtesting-a-feature/SKILL.md +24 -1
  279. package/library/skills/playtesting-a-feature/resource.yaml +1 -1
  280. package/library/skills/procedural-animation/SKILL.md +38 -16
  281. package/library/skills/procedural-animation/resource.yaml +1 -1
  282. package/library/skills/prop-model/SKILL.md +48 -19
  283. package/library/skills/prop-model/resource.yaml +1 -1
  284. package/library/skills/psx-retro-rendering/resource.yaml +1 -0
  285. package/library/skills/publish-your-game/SKILL.md +43 -6
  286. package/library/skills/publish-your-game/resource.yaml +3 -3
  287. package/library/skills/realtime-wet-surfaces/resource.yaml +1 -0
  288. package/library/skills/release-readiness/SKILL.md +13 -1
  289. package/library/skills/release-readiness/resource.yaml +1 -1
  290. package/library/skills/remote-deploy/SKILL.md +15 -1
  291. package/library/skills/remote-deploy/resource.yaml +1 -1
  292. package/library/skills/retarget/SKILL.md +43 -20
  293. package/library/skills/retarget/resource.yaml +1 -1
  294. package/library/skills/running-in-the-cloud/SKILL.md +11 -1
  295. package/library/skills/running-in-the-cloud/resource.yaml +1 -1
  296. package/library/skills/save-load/SKILL.md +16 -1
  297. package/library/skills/save-load/resource.yaml +1 -1
  298. package/library/skills/scene-composition/SKILL.md +18 -1
  299. package/library/skills/scene-composition/resource.yaml +1 -1
  300. package/library/skills/scene-hierarchy-design/SKILL.md +26 -2
  301. package/library/skills/scene-hierarchy-design/resource.yaml +1 -1
  302. package/library/skills/scene-scripting/SKILL.md +96 -636
  303. package/library/skills/scene-scripting/references/ctx-api.md +184 -0
  304. package/library/skills/scene-scripting/references/recipes-2d-ui.md +193 -0
  305. package/library/skills/scene-scripting/references/recipes-3d.md +280 -0
  306. package/library/skills/scene-scripting/resource.yaml +4 -4
  307. package/library/skills/scene-to-level/SKILL.md +24 -2
  308. package/library/skills/scene-to-level/resource.yaml +1 -1
  309. package/library/skills/skill-create/resource.yaml +1 -0
  310. package/library/skills/skill-improve/resource.yaml +1 -0
  311. package/library/skills/skill-test/SKILL.md +12 -2
  312. package/library/skills/skill-test/resource.yaml +1 -0
  313. package/library/skills/skintokens-auto-rigging/resource.yaml +1 -0
  314. package/library/skills/skybox-panorama/SKILL.md +47 -21
  315. package/library/skills/skybox-panorama/resource.yaml +1 -1
  316. package/library/skills/sound-effect/SKILL.md +52 -20
  317. package/library/skills/sound-effect/resource.yaml +1 -1
  318. package/library/skills/spatial-placement/SKILL.md +44 -9
  319. package/library/skills/spatial-placement/resource.yaml +1 -1
  320. package/library/skills/sprite-sheet/SKILL.md +55 -27
  321. package/library/skills/sprite-sheet/resource.yaml +1 -1
  322. package/library/skills/store-art/SKILL.md +14 -3
  323. package/library/skills/store-art/resource.yaml +2 -2
  324. package/library/skills/store-listing/SKILL.md +13 -3
  325. package/library/skills/store-listing/resource.yaml +2 -2
  326. package/library/skills/summer-analytics/SKILL.md +22 -5
  327. package/library/skills/summer-analytics/resource.yaml +2 -2
  328. package/library/skills/summer-apps/SKILL.md +77 -32
  329. package/library/skills/summer-apps/manifest.md +1 -1
  330. package/library/skills/summer-apps/minimal-app.md +7 -7
  331. package/library/skills/summer-apps/resource.yaml +1 -1
  332. package/library/skills/summer-apps/sdk-reference.md +5 -5
  333. package/library/skills/summer-apps-design/SKILL.md +1 -1
  334. package/library/skills/summer-apps-design/resource.yaml +1 -1
  335. package/library/skills/summer-assets/SKILL.md +86 -0
  336. package/library/skills/summer-assets/resource.yaml +34 -0
  337. package/library/skills/summer-cli/SKILL.md +133 -0
  338. package/library/skills/summer-cli/resource.yaml +31 -0
  339. package/library/skills/summer-friends/SKILL.md +14 -0
  340. package/library/skills/summer-leaderboards/SKILL.md +16 -0
  341. package/library/skills/summer-match-results/SKILL.md +17 -0
  342. package/library/skills/summer-matchmaking/SKILL.md +17 -0
  343. package/library/skills/summer-parties/SKILL.md +14 -0
  344. package/library/skills/summer-player-data/SKILL.md +14 -0
  345. package/library/skills/summer-store/SKILL.md +16 -1
  346. package/library/skills/summer-world-chat/SKILL.md +14 -0
  347. package/library/skills/summer-world-saves/SKILL.md +14 -0
  348. package/library/skills/text-to-motion/SKILL.md +45 -23
  349. package/library/skills/text-to-motion/prompts-and-controls.md +5 -5
  350. package/library/skills/text-to-motion/resource.yaml +1 -1
  351. package/library/skills/text-to-motion/rigging-for-text-motion.md +2 -2
  352. package/library/skills/tileable-texture/SKILL.md +37 -15
  353. package/library/skills/tileable-texture/resource.yaml +1 -1
  354. package/library/skills/trailer-shot/SKILL.md +46 -24
  355. package/library/skills/trailer-shot/resource.yaml +1 -1
  356. package/library/skills/tune-performance/SKILL.md +32 -6
  357. package/library/skills/tune-performance/resource.yaml +1 -1
  358. package/library/skills/ui-basics/SKILL.md +55 -36
  359. package/library/skills/ui-basics/resource.yaml +1 -1
  360. package/library/skills/ui-graphics/SKILL.md +64 -38
  361. package/library/skills/ui-graphics/resource.yaml +1 -1
  362. package/library/skills/use-widget-asset/SKILL.md +15 -1
  363. package/library/skills/use-widget-asset/resource.yaml +1 -1
  364. package/library/skills/using-summer/SKILL.md +32 -5
  365. package/library/skills/using-summer/resource.yaml +3 -2
  366. package/library/skills/vehicle-model/SKILL.md +92 -57
  367. package/library/skills/vehicle-model/resource.yaml +1 -1
  368. package/library/skills/verification-before-completion/SKILL.md +1 -1
  369. package/library/skills/verification-before-completion/resource.yaml +1 -1
  370. package/library/skills/verifying-scenes/SKILL.md +31 -2
  371. package/library/skills/verifying-scenes/resource.yaml +1 -1
  372. package/library/skills/vfx-dissolve/SKILL.md +21 -2
  373. package/library/skills/vfx-dissolve/resource.yaml +1 -1
  374. package/library/skills/vfx-fire/SKILL.md +41 -41
  375. package/library/skills/vfx-fire/resource.yaml +1 -1
  376. package/library/skills/vfx-hit-spark/SKILL.md +24 -1
  377. package/library/skills/vfx-hit-spark/resource.yaml +1 -1
  378. package/library/skills/vfx-lightning/SKILL.md +30 -16
  379. package/library/skills/vfx-lightning/resource.yaml +1 -1
  380. package/library/skills/vfx-magic-glow/SKILL.md +46 -32
  381. package/library/skills/vfx-magic-glow/resource.yaml +1 -1
  382. package/library/skills/vfx-muzzle-flash/SKILL.md +43 -35
  383. package/library/skills/vfx-muzzle-flash/resource.yaml +1 -1
  384. package/library/skills/vfx-smoke/SKILL.md +39 -31
  385. package/library/skills/vfx-smoke/resource.yaml +1 -1
  386. package/library/skills/vfx-water-ripple/SKILL.md +35 -31
  387. package/library/skills/vfx-water-ripple/resource.yaml +1 -1
  388. package/library/skills/voice-line/SKILL.md +87 -40
  389. package/library/skills/voice-line/resource.yaml +1 -1
  390. package/library/skills/web-and-touch-input/SKILL.md +20 -1
  391. package/library/skills/web-and-touch-input/resource.yaml +1 -1
  392. package/library/skills/web-compatibility-look/SKILL.md +21 -1
  393. package/library/skills/web-compatibility-look/resource.yaml +1 -1
  394. package/library/skills/world-building-3d/SKILL.md +29 -1
  395. package/library/skills/world-building-3d/resource.yaml +1 -1
  396. package/library/skills/writing-skills/resource.yaml +1 -0
  397. package/library/tools/add-node/GUIDE.md +14 -0
  398. package/library/tools/align-distribute-3d/GUIDE.md +7 -0
  399. package/library/tools/app-call/resource.yaml +1 -1
  400. package/library/tools/app-guide/resource.yaml +2 -2
  401. package/library/tools/app-page/resource.yaml +1 -1
  402. package/library/tools/app-screenshot/resource.yaml +19 -1
  403. package/library/tools/app-tools/resource.yaml +1 -1
  404. package/library/tools/attach-to-surface/GUIDE.md +15 -0
  405. package/library/tools/batch/GUIDE.md +27 -0
  406. package/library/tools/camera-bookmark/GUIDE.md +12 -0
  407. package/library/tools/capture-gameplay/GUIDE.md +3 -0
  408. package/library/tools/capture-gameplay/resource.yaml +3 -3
  409. package/library/tools/check-job/resource.yaml +1 -1
  410. package/library/tools/clear-console/GUIDE.md +3 -0
  411. package/library/tools/connect-ports/GUIDE.md +9 -0
  412. package/library/tools/connect-signal/GUIDE.md +14 -0
  413. package/library/tools/create-debug-report/GUIDE.md +10 -0
  414. package/library/tools/create-scene/GUIDE.md +10 -0
  415. package/library/tools/debug-views/GUIDE.md +7 -0
  416. package/library/tools/enable-plugin/GUIDE.md +3 -0
  417. package/library/tools/export-game/GUIDE.md +3 -0
  418. package/library/tools/export-game/resource.yaml +3 -3
  419. package/library/tools/export-templates/GUIDE.md +3 -0
  420. package/library/tools/fabricate-3d/GUIDE.md +19 -0
  421. package/library/tools/frame-nodes/GUIDE.md +9 -0
  422. package/library/tools/frame-shot/GUIDE.md +9 -0
  423. package/library/tools/game-control/GUIDE.md +9 -0
  424. package/library/tools/game-input/GUIDE.md +9 -0
  425. package/library/tools/game-probe/GUIDE.md +9 -0
  426. package/library/tools/generate-3d/resource.yaml +3 -3
  427. package/library/tools/generate-motion/resource.yaml +2 -2
  428. package/library/tools/get-console/GUIDE.md +9 -0
  429. package/library/tools/get-console/resource.yaml +5 -0
  430. package/library/tools/get-debugger-errors/GUIDE.md +7 -0
  431. package/library/tools/get-debugger-errors/resource.yaml +5 -0
  432. package/library/tools/get-debugger-warnings/GUIDE.md +7 -0
  433. package/library/tools/get-debugger-warnings/resource.yaml +5 -0
  434. package/library/tools/get-diagnostics/GUIDE.md +13 -0
  435. package/library/tools/get-project-context/GUIDE.md +25 -0
  436. package/library/tools/get-runtime-tree/GUIDE.md +7 -0
  437. package/library/tools/get-runtime-tree/resource.yaml +5 -0
  438. package/library/tools/get-scene-tree/GUIDE.md +11 -0
  439. package/library/tools/get-scene-tree/resource.yaml +5 -0
  440. package/library/tools/get-script-errors/GUIDE.md +5 -0
  441. package/library/tools/grep/GUIDE.md +11 -0
  442. package/library/tools/import-asset/GUIDE.md +8 -0
  443. package/library/tools/import-asset-by-id/GUIDE.md +12 -0
  444. package/library/tools/import-from-url/GUIDE.md +10 -0
  445. package/library/tools/import-from-url-batch/GUIDE.md +3 -0
  446. package/library/tools/import-hdri/GUIDE.md +16 -0
  447. package/library/tools/input-map-bind/GUIDE.md +11 -0
  448. package/library/tools/inspect-asset/GUIDE.md +14 -0
  449. package/library/tools/inspect-asset/resource.yaml +5 -0
  450. package/library/tools/inspect-node/GUIDE.md +11 -0
  451. package/library/tools/inspect-node/resource.yaml +5 -0
  452. package/library/tools/inspect-resource/GUIDE.md +7 -0
  453. package/library/tools/inspect-resource/resource.yaml +5 -0
  454. package/library/tools/inspect-runtime-node/GUIDE.md +7 -0
  455. package/library/tools/inspect-runtime-node/resource.yaml +5 -0
  456. package/library/tools/instantiate-scene/GUIDE.md +12 -0
  457. package/library/tools/is-running/GUIDE.md +3 -0
  458. package/library/tools/measure/GUIDE.md +8 -0
  459. package/library/tools/navigation-probe/GUIDE.md +9 -0
  460. package/library/tools/open/resource.yaml +2 -2
  461. package/library/tools/open-main-scene/GUIDE.md +6 -0
  462. package/library/tools/open-scene/GUIDE.md +8 -0
  463. package/library/tools/place-adjacent/GUIDE.md +7 -0
  464. package/library/tools/play/GUIDE.md +13 -0
  465. package/library/tools/project-setting/GUIDE.md +9 -0
  466. package/library/tools/publish-build/resource.yaml +6 -6
  467. package/library/tools/raycast/GUIDE.md +7 -0
  468. package/library/tools/read-file/GUIDE.md +10 -0
  469. package/library/tools/read-library/resource.yaml +5 -0
  470. package/library/tools/recent-events/GUIDE.md +7 -0
  471. package/library/tools/remove-node/GUIDE.md +3 -0
  472. package/library/tools/repeat-along/GUIDE.md +5 -0
  473. package/library/tools/replace-node/GUIDE.md +9 -0
  474. package/library/tools/replace-text/GUIDE.md +5 -0
  475. package/library/tools/run-editor-script/GUIDE.md +16 -0
  476. package/library/tools/run-script/GUIDE.md +30 -0
  477. package/library/tools/run-script/resource.yaml +6 -3
  478. package/library/tools/runtime-animate/GUIDE.md +7 -0
  479. package/library/tools/runtime-call/GUIDE.md +7 -0
  480. package/library/tools/runtime-set/GUIDE.md +9 -0
  481. package/library/tools/runtime-spawn/GUIDE.md +9 -0
  482. package/library/tools/save-scene/GUIDE.md +3 -0
  483. package/library/tools/scene-audit/GUIDE.md +29 -0
  484. package/library/tools/screenshot/GUIDE.md +17 -0
  485. package/library/tools/select-node/GUIDE.md +3 -0
  486. package/library/tools/set-prop/GUIDE.md +23 -0
  487. package/library/tools/set-resource-property/GUIDE.md +8 -0
  488. package/library/tools/shot-sheet/GUIDE.md +7 -0
  489. package/library/tools/snap-to-surface/GUIDE.md +17 -0
  490. package/library/tools/snapshot-diff/GUIDE.md +7 -0
  491. package/library/tools/starcast/GUIDE.md +12 -0
  492. package/library/tools/stop/GUIDE.md +3 -0
  493. package/library/tools/test-placement/GUIDE.md +7 -0
  494. package/library/tools/ui-actions/GUIDE.md +12 -0
  495. package/library/tools/ui-activate/GUIDE.md +11 -0
  496. package/library/tools/ui-screenshot/GUIDE.md +9 -0
  497. package/library/tools/ui-tree/GUIDE.md +10 -0
  498. package/library/tools/wait-for-event/GUIDE.md +11 -0
  499. package/library/tools/world-snapshot/GUIDE.md +9 -0
  500. package/library/tools/write-file/GUIDE.md +5 -0
  501. package/library/tools/zoom/GUIDE.md +5 -0
  502. package/package.json +8 -5
  503. package/registry/generated/counts.json +2 -2
  504. package/registry/generated/gemini-extension.json +6 -13
  505. package/registry/generated/index.json +482 -349
  506. package/registry/generated/marketplace.claude.json +2 -13
  507. package/registry/generated/plugin.claude-directory.json +168 -0
  508. package/registry/generated/plugin.claude.json +24 -22
  509. package/registry/generated/plugin.codex.json +18 -22
  510. package/registry/generated/plugin.cursor.json +8 -14
  511. package/registry/generated/plugin.factory.json +6 -13
  512. package/registry/generated/server.json +43 -0
  513. package/registry/generated/skills-index.md +121 -118
  514. package/registry/generated/skills-registry.json +167 -115
  515. package/registry/operations/fixtures/invalid-deprecated-without-replacement.json +60 -0
  516. package/registry/operations/fixtures/invalid-name.json +60 -0
  517. package/registry/operations/fixtures/invalid-publish-without-owner.json +82 -0
  518. package/registry/operations/fixtures/invalid-spend-without-estimate.json +42 -0
  519. package/registry/operations/fixtures/invalid-unknown-field.json +61 -0
  520. package/registry/operations/fixtures/valid-player-facing.json +82 -0
  521. package/registry/operations/fixtures/valid-read.json +60 -0
  522. package/registry/operations/fixtures/valid-spend.json +43 -0
  523. package/registry/operations/legacy-names.json +1241 -0
  524. package/registry/operations/public-catalog.json +33160 -0
  525. package/registry/schemas/operation.schema.json +318 -0
  526. package/registry/schemas/skill.schema.json +4 -0
  527. package/CLAUDE.md +0 -7
@@ -0,0 +1,317 @@
1
+ import { z } from "zod";
2
+ import { loadLibraryIndex } from "../core/library-search.js";
3
+ import { PROFILES, TOOLSETS, parseProfile } from "../core/tool-profiles.js";
4
+ /**
5
+ * The shape of the MCP tool surface: which toolset each tool belongs to, each
6
+ * local tool's annotations, which results are capped, and which calls count
7
+ * as single scene edits. Read by server.ts (registration, results) and, with
8
+ * the profiles in core/tool-profiles.ts, by hosted-mount.ts (which hosted
9
+ * tools a profile mounts).
10
+ *
11
+ * Tool names never change here: a profile only leaves tools out.
12
+ */
13
+ export { TOOLSETS, PROFILES, PROFILE_TOOL_LIMIT } from "../core/tool-profiles.js";
14
+ const LOCAL_TOOLSETS = {
15
+ core: [
16
+ "summer_search_library",
17
+ "summer_read_library",
18
+ "summer_library_feedback",
19
+ "summer_get_agent_playbook",
20
+ "summer_start_game_task",
21
+ "summer_open",
22
+ ],
23
+ assets: [
24
+ "summer_generate_3d",
25
+ "summer_generate_audio",
26
+ "summer_generate_image",
27
+ "summer_generate_motion",
28
+ "summer_generate_sfx_choices",
29
+ "summer_generate_video",
30
+ "summer_check_job",
31
+ "summer_get_choices",
32
+ "summer_slice_asset_sheet",
33
+ "summer_get_studio_workflow",
34
+ "summer_search_assets",
35
+ "summer_list_my_assets",
36
+ "summer_get_asset",
37
+ "summer_get_asset_download_url",
38
+ ],
39
+ ship: ["summer_export_game", "summer_export_templates", "summer_publish_build", "summer_capture_gameplay"],
40
+ ui: ["summer_ui_actions", "summer_ui_activate", "summer_ui_screenshot", "summer_ui_tree"],
41
+ };
42
+ const localToolset = new Map(Object.entries(LOCAL_TOOLSETS).flatMap(([set, names]) => names.map((name) => [name, set])));
43
+ /** Hosted tool names by pattern, first match wins. Unknown names land in `other` (full only). */
44
+ const HOSTED_TOOLSETS = [
45
+ [/^summer_(account|team)$/, "core"],
46
+ [/^summer_(remove_background|update_asset|delete_asset|upload_image_\w+)$/, "assets"],
47
+ [/^summer_tool_\w+$/, "tools"],
48
+ [/^summer_(store_version_(begin_upload|sign_parts|complete)|build_(begin_upload|sign_parts|complete_upload))$/, "uploads"],
49
+ [/^summer_(store_\w+|list_games)$/, "ship"],
50
+ [/^summer_board_\w+$/, "board"],
51
+ [/^summer_grow_\w+$/, "grow"],
52
+ [/^summer_studio_\w+$/, "studio"],
53
+ [/^summer_app_\w+$/, "apps"],
54
+ [/^summer_(build_\w+|make_game|game|game_\w+|list_projects|get_project)$/, "cloud"],
55
+ ];
56
+ /** The toolset a tool belongs to: local tools by the table above, hosted ones by name. */
57
+ export function toolsetOf(name, local) {
58
+ if (local) {
59
+ if (localToolset.has(name))
60
+ return localToolset.get(name);
61
+ return name.startsWith("summer_app_") ? "apps" : "engine";
62
+ }
63
+ if (localToolset.has(name))
64
+ return localToolset.get(name);
65
+ return HOSTED_TOOLSETS.find(([pattern]) => pattern.test(name))?.[1] ?? "other";
66
+ }
67
+ const splitList = (value) => (value ?? "")
68
+ .split(",")
69
+ .map((part) => part.trim().toLowerCase())
70
+ .filter(Boolean);
71
+ /**
72
+ * `summer mcp --profile <p> --toolsets <a,b>` (env SUMMER_PROFILE,
73
+ * SUMMER_TOOLSETS). Without either: the full profile. `--toolsets` alone
74
+ * selects those toolsets plus core; with a profile it adds to it. `all` is
75
+ * every toolset. Unknown names are ignored and reported, never fatal: a
76
+ * typo must not stop an agent's MCP server from starting.
77
+ */
78
+ export function resolveToolSelection(options = {}, env = process.env) {
79
+ const ignored = [];
80
+ const profileName = (options.profile ?? env.SUMMER_PROFILE ?? "").trim().toLowerCase();
81
+ const requested = splitList(options.toolsets ?? env.SUMMER_TOOLSETS);
82
+ const profile = parseProfile(profileName);
83
+ if (profileName && !profile)
84
+ ignored.push(profileName);
85
+ const extra = new Set();
86
+ let all = false;
87
+ for (const name of requested) {
88
+ if (name === "all")
89
+ all = true;
90
+ else if (TOOLSETS.includes(name))
91
+ extra.add(name);
92
+ else
93
+ ignored.push(name);
94
+ }
95
+ if (all || profile === "full" || (profile === null && extra.size === 0)) {
96
+ return { profile: "full", toolsets: null, ignored };
97
+ }
98
+ if (profile === null)
99
+ return { profile: "custom", toolsets: new Set(["core", ...extra]), ignored };
100
+ return { profile, toolsets: new Set([...PROFILES[profile], ...extra]), ignored };
101
+ }
102
+ /** True when the selection keeps this tool. */
103
+ export function selectionIncludes(selection, name, local) {
104
+ return selection.toolsets === null || selection.toolsets.has(toolsetOf(name, local));
105
+ }
106
+ // ── Annotations ──────────────────────────────────────────────────────────────
107
+ /**
108
+ * Local tools carry the registry's five `authority` booleans
109
+ * (library/tools/<slug>/resource.yaml). They say what a tool may touch, not
110
+ * whether it only reads, so a few sets refine them; the result is the MCP
111
+ * effect hints clients use for approvals.
112
+ */
113
+ /** Tools whose only file output is an image or render for the agent; they never change the game. */
114
+ const EVIDENCE_ONLY = new Set([
115
+ "summer_screenshot",
116
+ "summer_debug_views",
117
+ "summer_shot_sheet",
118
+ "summer_zoom",
119
+ "summer_scene_audit",
120
+ "summer_game_probe",
121
+ "summer_capture_gameplay",
122
+ "summer_app_screenshot",
123
+ ]);
124
+ /** Generation on Summer's servers: costs credits, creates new assets. */
125
+ const SPENDS_CREDITS = new Set([
126
+ "summer_generate_3d",
127
+ "summer_generate_audio",
128
+ "summer_generate_image",
129
+ "summer_generate_motion",
130
+ "summer_generate_sfx_choices",
131
+ "summer_generate_video",
132
+ ]);
133
+ /** Network-only tools that change the person's Summer data (the rest of the network tools read). */
134
+ const NETWORK_WRITES = new Set([
135
+ "summer_app_create",
136
+ "summer_app_data",
137
+ "summer_app_page",
138
+ "summer_app_call",
139
+ "summer_app_report_gap",
140
+ "summer_app_update",
141
+ "summer_slice_asset_sheet",
142
+ ]);
143
+ /** Changes that only add something new, or only touch the editor view or the running game. */
144
+ const ADDITIVE_OR_TRANSIENT = new Set([
145
+ "summer_add_node",
146
+ "summer_create_scene",
147
+ "summer_instantiate_scene",
148
+ "summer_connect_signal",
149
+ "summer_input_map_bind",
150
+ "summer_import_asset",
151
+ "summer_import_asset_by_id",
152
+ "summer_import_from_url",
153
+ "summer_import_from_url_batch",
154
+ "summer_import_hdri",
155
+ "summer_repeat_along",
156
+ "summer_fabricate_3d",
157
+ "summer_frame_nodes",
158
+ "summer_frame_shot",
159
+ "summer_save_scene",
160
+ "summer_enable_plugin",
161
+ "summer_export_game",
162
+ "summer_export_templates",
163
+ "summer_create_debug_report",
164
+ "summer_library_feedback",
165
+ "summer_app_create",
166
+ "summer_app_report_gap",
167
+ "summer_app_dock",
168
+ "summer_slice_asset_sheet",
169
+ "summer_open_scene",
170
+ "summer_open_main_scene",
171
+ "summer_select_node",
172
+ "summer_clear_console",
173
+ "summer_play",
174
+ "summer_stop",
175
+ "summer_game_control",
176
+ "summer_game_input",
177
+ "summer_runtime_animate",
178
+ "summer_runtime_call",
179
+ "summer_runtime_set",
180
+ "summer_runtime_spawn",
181
+ ]);
182
+ /** Changes where a second identical call has no further effect. */
183
+ const IDEMPOTENT_WRITES = new Set([
184
+ "summer_set_prop",
185
+ "summer_set_resource_property",
186
+ "summer_project_setting",
187
+ "summer_remove_node",
188
+ "summer_write_file",
189
+ "summer_create_scene",
190
+ "summer_save_scene",
191
+ "summer_open_scene",
192
+ "summer_open_main_scene",
193
+ "summer_select_node",
194
+ "summer_clear_console",
195
+ "summer_stop",
196
+ "summer_enable_plugin",
197
+ "summer_place_adjacent",
198
+ "summer_attach_to_surface",
199
+ "summer_connect_ports",
200
+ "summer_align_distribute_3d",
201
+ "summer_snap_to_surface",
202
+ "summer_camera_bookmark",
203
+ "summer_frame_nodes",
204
+ "summer_runtime_set",
205
+ "summer_export_game",
206
+ "summer_export_templates",
207
+ "summer_app_update",
208
+ "summer_app_dock",
209
+ ]);
210
+ /** Every name the refinement sets mention (a test checks each is a real tool). */
211
+ export const ANNOTATION_REFINEMENTS = new Set([
212
+ ...EVIDENCE_ONLY,
213
+ ...SPENDS_CREDITS,
214
+ ...NETWORK_WRITES,
215
+ ...ADDITIVE_OR_TRANSIENT,
216
+ ...IDEMPOTENT_WRITES,
217
+ ]);
218
+ /** MCP annotations for one local tool from its registry authority. */
219
+ export function annotationsFor(name, authority) {
220
+ const openWorldHint = Boolean(authority.network || authority.publish);
221
+ if (authority.publish) {
222
+ return { readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: true };
223
+ }
224
+ if (SPENDS_CREDITS.has(name)) {
225
+ return { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true };
226
+ }
227
+ const writes = !EVIDENCE_ONLY.has(name) &&
228
+ Boolean(authority.filesystem || authority.editor_mutation || authority.credentials || NETWORK_WRITES.has(name));
229
+ if (!writes) {
230
+ return { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint };
231
+ }
232
+ return {
233
+ readOnlyHint: false,
234
+ destructiveHint: !ADDITIVE_OR_TRANSIENT.has(name),
235
+ idempotentHint: IDEMPOTENT_WRITES.has(name),
236
+ openWorldHint,
237
+ };
238
+ }
239
+ let authorityCache = null;
240
+ /** Registry authority per MCP tool name (registry/generated/index.json). */
241
+ export function registryAuthorities() {
242
+ if (authorityCache)
243
+ return authorityCache;
244
+ const map = new Map();
245
+ try {
246
+ for (const entry of loadLibraryIndex()) {
247
+ if (entry.kind === "tool" && entry.mcp_tool_name && entry.authority)
248
+ map.set(entry.mcp_tool_name, entry.authority);
249
+ }
250
+ }
251
+ catch {
252
+ // A broken install still serves tools; they go out without annotations.
253
+ }
254
+ authorityCache = map;
255
+ return map;
256
+ }
257
+ // ── Output caps ──────────────────────────────────────────────────────────────
258
+ /** Default text cap for tools whose results can be large. */
259
+ export const DEFAULT_MAX_CHARACTERS = 4_000;
260
+ /**
261
+ * Tools whose text results are capped by default, with their default cap.
262
+ * Scene and runtime trees, console and debugger reads, inspect reads and
263
+ * library reads. The scene tree and library reads get more room: a median
264
+ * skill is about 12K characters, and cutting every skill read would double
265
+ * the core search-then-read loop. Writes, job ids and file reads are never
266
+ * capped.
267
+ */
268
+ export const OUTPUT_CAPS = new Map([
269
+ ["summer_get_scene_tree", 8_000],
270
+ ["summer_get_runtime_tree", DEFAULT_MAX_CHARACTERS],
271
+ ["summer_get_console", DEFAULT_MAX_CHARACTERS],
272
+ ["summer_get_debugger_errors", DEFAULT_MAX_CHARACTERS],
273
+ ["summer_get_debugger_warnings", DEFAULT_MAX_CHARACTERS],
274
+ ["summer_inspect_node", DEFAULT_MAX_CHARACTERS],
275
+ ["summer_inspect_resource", DEFAULT_MAX_CHARACTERS],
276
+ ["summer_inspect_runtime_node", DEFAULT_MAX_CHARACTERS],
277
+ ["summer_inspect_asset", DEFAULT_MAX_CHARACTERS],
278
+ ["summer_read_library", 24_000],
279
+ ]);
280
+ /**
281
+ * A capped tool's input shape plus `maxCharacters`. server.ts adds it at
282
+ * registration and strips it before the handler runs; the descriptor parity
283
+ * test applies the same function, so library/tools/<slug>/resource.yaml
284
+ * lists the argument too.
285
+ */
286
+ export function withMaxCharactersArg(name, shape) {
287
+ const cap = OUTPUT_CAPS.get(name);
288
+ if (cap === undefined || "maxCharacters" in shape)
289
+ return shape;
290
+ return {
291
+ ...shape,
292
+ maxCharacters: z
293
+ .number()
294
+ .int()
295
+ .min(500)
296
+ .max(1_000_000)
297
+ .optional()
298
+ .describe(`Most characters of text to return (default ${cap}). A longer result is cut and says so.`),
299
+ };
300
+ }
301
+ // ── Single scene edits ───────────────────────────────────────────────────────
302
+ /** One-change scene tools; a run of them is one summer_run_script. */
303
+ export const SINGLE_EDIT_TOOLS = new Set([
304
+ "summer_set_prop",
305
+ "summer_add_node",
306
+ "summer_remove_node",
307
+ "summer_set_resource_property",
308
+ "summer_instantiate_scene",
309
+ "summer_connect_signal",
310
+ "summer_replace_node",
311
+ ]);
312
+ /** Calls that already batch edits; they end a run of single edits. */
313
+ export const BATCH_EDIT_TOOLS = new Set([
314
+ "summer_run_script",
315
+ "summer_batch",
316
+ "summer_run_editor_script",
317
+ ]);
@@ -19,7 +19,14 @@ function cloud(name, schema, run) {
19
19
  };
20
20
  }
21
21
  export function registerAppTools(server) {
22
- server.tool("summer_app_guide", `Read this before building or changing a Summer App (a tool for the person's team inside Summer Studio, live on their assets, game data and engine): when to build one, Layout vs code, the build loop, manifest schema, SDK reference, UI kit, layout format, design rules and four worked examples. section returns one part.\n\n${CLOUD}`, appGuideArgsSchema.shape, cloud("summer_app_guide", appGuideArgsSchema, appGuide));
22
+ server.tool("summer_app_guide", `Read this before building or changing a Summer App (a tool for the person's team inside Summer Studio). Start with the default section overview (when to build one, Layout vs code, the build loop, the rules), then read what the app needs: examples (a complete working app to copy), sdk, manifest, kit, design, layout, types (exact SDK TypeScript types).\n\n${CLOUD}`, appGuideArgsSchema.shape, async (args) => {
23
+ const parsed = appGuideArgsSchema.safeParse(args ?? {});
24
+ if (!parsed.success)
25
+ return result({ ok: false, code: "invalid", error: parsed.error.issues[0]?.message ?? "Invalid arguments" });
26
+ const guide = await appGuide(parsed.data, { request: appsGateway("mcp", "summer_app_guide") });
27
+ // The guide reads as Markdown, not as one escaped JSON line.
28
+ return guide.ok === true && typeof guide.markdown === "string" ? { content: [{ type: "text", text: guide.markdown }] } : result(guide);
29
+ });
23
30
  server.tool("summer_app_list", `The Summer Apps in the person's workspaces: id, name, purpose, folder, status (scratch, kept, archived), version, format.\n\n${CLOUD}`, appListArgsSchema.shape, cloud("summer_app_list", appListArgsSchema, appList));
24
31
  server.tool("summer_app_create", `Create a new scratch Summer App; their open Summer Studio tab opens it. Without workspaceId it goes to the person's team (the one their Studio tab is on, else their latest team, else personal); the result's workspace says which: tell the person. Read summer_app_guide first. format code (index.html + JS/CSS) or layout (a JSON layout of kit nodes for a quick decision UI). Then summer_app_publish.\n\n${CLOUD}`, appCreateArgsSchema.shape, cloud("summer_app_create", appCreateArgsSchema, appCreate));
25
32
  server.tool("summer_app_publish", `Publish a new immutable version of a Summer App: dir (a local folder with index.html at its root) or files [{path, content, encoding}] for code apps, layout for layout apps, plus the manifest. Limits: 10 MB, 300 files, 5 MB per file. The person's Studio tab boots it. An error names the file or rule to fix: fix it and publish again.\n\n${CLOUD}`, appPublishArgsSchema.shape, cloud("summer_app_publish", appPublishArgsSchema, appPublish));
@@ -27,7 +34,7 @@ export function registerAppTools(server) {
27
34
  server.tool("summer_app_update", `Rename a Summer App, change its purpose or folder, or set its status: kept (the team keeps it), archived (hidden from the app list; restore with scratch or kept), scratch. Archive the scratch apps you made that the person did not keep.\n\n${CLOUD}`, appUpdateArgsSchema.shape, cloud("summer_app_update", appUpdateArgsSchema, appUpdate));
28
35
  server.tool("summer_app_events", `Wait for what a Summer App sends you: summer.agent.send events (kind agent), errors in the app (kind error), feedback (kind feedback), agent tool calls (kind tool). Waits up to timeoutSeconds (max ${MAX_APP_EVENTS_WAIT_SECONDS}) for the first event after the cursor; pass the returned cursor as after next time.\n\n${CLOUD}`, appEventsArgsSchema.shape, cloud("summer_app_events", appEventsArgsSchema, appEvents));
29
36
  server.tool("summer_app_page", `Read or use the fields and buttons a Summer App declared while it is open in the person's Studio tab or editor dock: no fill and no press reads the page; fill [{field, value}] and press an action id use it. Critical actions (delete, publish, pay, send) are pressed only by the person. app_not_open when the app is not open.\n\n${CLOUD}`, appPageArgsSchema.shape, cloud("summer_app_page", appPageArgsSchema, appPage));
30
- server.tool("summer_app_screenshot", `See a Summer App without the person: Summer renders its current version (or version) headless with the person's data and returns the picture plus what to fix: console lines, uncaught errors, refused calls, whether the SDK connected and rendered, and the fields, buttons and agent tools it declared. Read-only: writes, sends and paid calls are refused, nothing changes. width 390 for a phone, theme dark, fullPage for the whole scroll; out also saves the PNG. Use it after every publish.\n\n${CLOUD}`, appScreenshotArgsSchema.shape, async (args) => {
37
+ server.tool("summer_app_screenshot", `See a Summer App without the person: Summer renders its current version (or version) headless with the person's data and returns the picture plus what to fix: console lines, uncaught errors, refused calls, whether the SDK connected and rendered, and the fields, buttons and agent tools it declared. Read-only: writes, sends and paid calls are refused, nothing changes. width 390 for a phone, theme dark, fullPage for the whole scroll, steps to click or press something first (a dialog, a second state); out also saves the PNG. It waits until the app's calls settle. Use it after every publish.\n\n${CLOUD}`, appScreenshotArgsSchema.shape, async (args) => {
31
38
  const parsed = appScreenshotArgsSchema.safeParse(args ?? {});
32
39
  if (!parsed.success)
33
40
  return result({ ok: false, code: "invalid", error: parsed.error.issues[0]?.message ?? "Invalid arguments" });
@@ -4,14 +4,15 @@ import { resolveGatewayUrl } from "../../core/config.js";
4
4
  import { getClient } from "../server.js";
5
5
  import { ImportHdriError, importPolyHavenHdri, } from "../../core/capabilities/hdri-import.js";
6
6
  import { importResolvedAsset } from "../../core/capabilities/asset-import.js";
7
+ import { summerRequestHeaders } from "../../core/agent-host.js";
8
+ import { codedFailure, describeNetworkError, EngineNotRunningError, networkDetails, NOT_SIGNED_IN, SIGN_IN_AGAIN_RECOVERY, } from "../../core/error-codes.js";
9
+ import { engineNotRunningResult } from "./with-engine.js";
10
+ /** No Summer account token: the same failure for every asset tool. */
11
+ const notSignedIn = { error: "not_logged_in", message: NOT_SIGNED_IN, code: "not_signed_in" };
7
12
  async function searchAssetsApi(params) {
8
13
  const token = await getAuthToken();
9
- if (!token) {
10
- return {
11
- error: "Not logged in",
12
- message: "Not signed in. The user needs to run this in their terminal:\n npx -y summer-engine@latest login\nOr open: https://www.summerengine.com/login\nAsset search requires a Summer Engine account (free to create).",
13
- };
14
- }
14
+ if (!token)
15
+ return { ...notSignedIn };
15
16
  const searchParams = new URLSearchParams();
16
17
  searchParams.set("query", params.query);
17
18
  if (params.assetType && params.assetType !== "all") {
@@ -30,17 +31,24 @@ async function searchAssetsApi(params) {
30
31
  if (params.preview)
31
32
  searchParams.set("contactSheet", "true");
32
33
  const gatewayUrl = await resolveGatewayUrl();
33
- const res = await fetch(`${gatewayUrl}/api/mcp/assets?${searchParams}`, {
34
- headers: { Authorization: `Bearer ${token}` },
35
- signal: AbortSignal.timeout(15000),
36
- });
34
+ let res;
35
+ try {
36
+ res = await fetch(`${gatewayUrl}/api/mcp/assets?${searchParams}`, {
37
+ headers: { ...summerRequestHeaders({ surface: "mcp" }), Authorization: `Bearer ${token}` },
38
+ signal: AbortSignal.timeout(15000),
39
+ });
40
+ }
41
+ catch (err) {
42
+ return { error: "network_error", message: `Asset request failed: ${describeNetworkError(err)}`, code: "unavailable", ...networkDetails(err) };
43
+ }
37
44
  const data = (await res.json());
38
45
  if (!res.ok) {
39
46
  if (res.status === 401) {
40
47
  return {
41
48
  error: "unauthorized",
42
- message: (data.message || "Auth token expired.") +
43
- " The user needs to re-authenticate:\n npx -y summer-engine@latest login --force",
49
+ message: data.message || "Auth token expired.",
50
+ code: "not_signed_in",
51
+ recovery: SIGN_IN_AGAIN_RECOVERY,
44
52
  };
45
53
  }
46
54
  if (res.status === 429) {
@@ -59,18 +67,19 @@ async function searchAssetsApi(params) {
59
67
  }
60
68
  async function authedGetJson(endpoint, timeoutMs = 15_000) {
61
69
  const token = await getAuthToken();
62
- if (!token) {
63
- return {
64
- status: 401,
65
- error: "not_logged_in",
66
- message: "Not signed in. Run in your terminal:\n npx -y summer-engine@latest login",
67
- };
68
- }
70
+ if (!token)
71
+ return { status: 401, ...notSignedIn };
69
72
  const gatewayUrl = await resolveGatewayUrl();
70
- const res = await fetch(`${gatewayUrl}${endpoint}`, {
71
- headers: { Authorization: `Bearer ${token}` },
72
- signal: AbortSignal.timeout(timeoutMs),
73
- });
73
+ let res;
74
+ try {
75
+ res = await fetch(`${gatewayUrl}${endpoint}`, {
76
+ headers: { ...summerRequestHeaders({ surface: "mcp" }), Authorization: `Bearer ${token}` },
77
+ signal: AbortSignal.timeout(timeoutMs),
78
+ });
79
+ }
80
+ catch (err) {
81
+ return { status: 0, error: "network_error", message: `Asset request failed: ${describeNetworkError(err)}`, code: "unavailable", ...networkDetails(err) };
82
+ }
74
83
  const data = (await res.json());
75
84
  if (!res.ok) {
76
85
  return {
@@ -78,6 +87,7 @@ async function authedGetJson(endpoint, timeoutMs = 15_000) {
78
87
  data,
79
88
  error: data?.error || "request_failed",
80
89
  message: data?.message || "Request failed",
90
+ ...(res.status === 401 ? { code: "not_signed_in", recovery: SIGN_IN_AGAIN_RECOVERY } : {}),
81
91
  };
82
92
  }
83
93
  return { status: res.status, data };
@@ -85,14 +95,14 @@ async function authedGetJson(endpoint, timeoutMs = 15_000) {
85
95
  async function getAssetApi(assetId) {
86
96
  const result = await authedGetJson(`/api/mcp/assets/${encodeURIComponent(assetId)}`);
87
97
  if (result.error) {
88
- return { error: result.error, message: result.message };
98
+ return { error: result.error, message: result.message, code: result.code, recovery: result.recovery, details: result.details };
89
99
  }
90
100
  return { asset: result.data?.asset };
91
101
  }
92
102
  async function getAssetDownloadUrlApi(assetId, role) {
93
103
  const result = await authedGetJson(`/api/mcp/assets/${encodeURIComponent(assetId)}/download-url?role=${encodeURIComponent(role)}`);
94
104
  if (result.error) {
95
- return { error: result.error, message: result.message };
105
+ return { error: result.error, message: result.message, code: result.code, recovery: result.recovery, details: result.details };
96
106
  }
97
107
  return { data: result.data };
98
108
  }
@@ -106,6 +116,14 @@ function jsonSuccess(data) {
106
116
  ],
107
117
  };
108
118
  }
119
+ /** The body of a failed lookup: `{ok:false, code, error, recovery, message}`
120
+ * for the shared failures, else the older `{error, message}`. */
121
+ function failureBody(result, fallback) {
122
+ const message = result.message || fallback.message;
123
+ return result.code
124
+ ? codedFailure(result.code, message, { message, ...(result.details ? { details: result.details } : {}) }, result.recovery)
125
+ : { error: result.error || fallback.error, message };
126
+ }
109
127
  function jsonError(data) {
110
128
  return {
111
129
  content: [
@@ -146,15 +164,7 @@ Requires authentication (so we can attribute usage and apply per-user rate limit
146
164
  }, async ({ query, assetType, limit, source, style, preview, includeCommunity }) => {
147
165
  const result = await searchAssetsApi({ query, assetType, limit: Math.min(limit, 20), source, style, preview, includeCommunity });
148
166
  if (result.error) {
149
- return {
150
- content: [
151
- {
152
- type: "text",
153
- text: JSON.stringify({ error: result.error, message: result.message }, null, 2),
154
- },
155
- ],
156
- isError: true,
157
- };
167
+ return jsonError(failureBody(result, { error: "Search failed", message: "Asset search failed" }));
158
168
  }
159
169
  const sheet = result.contactSheet?.match(/^data:(image\/[a-z]+);base64,(.+)$/);
160
170
  return {
@@ -200,7 +210,7 @@ Cloud tool — works WITHOUT the Summer Engine app open.`, {
200
210
  source: "my_assets",
201
211
  });
202
212
  if (result.error) {
203
- return jsonError({ error: result.error, message: result.message });
213
+ return jsonError(failureBody(result, { error: "List failed", message: "Listing your assets failed" }));
204
214
  }
205
215
  return jsonSuccess({
206
216
  assets: result.assets,
@@ -220,10 +230,7 @@ Cloud tool — works WITHOUT the Summer Engine app open.`, {
220
230
  }, async ({ assetId }) => {
221
231
  const result = await getAssetApi(assetId);
222
232
  if (result.error || !result.asset) {
223
- return jsonError({
224
- error: result.error || "asset_not_found",
225
- message: result.message || "Asset not found.",
226
- });
233
+ return jsonError(failureBody(result, { error: "asset_not_found", message: "Asset not found." }));
227
234
  }
228
235
  return jsonSuccess({ asset: result.asset });
229
236
  });
@@ -242,7 +249,7 @@ Cloud tool — works WITHOUT the Summer Engine app open.`, {
242
249
  }, async ({ assetId, role }) => {
243
250
  const result = await getAssetDownloadUrlApi(assetId, role);
244
251
  if (result.error) {
245
- return jsonError({ error: result.error, message: result.message });
252
+ return jsonError(failureBody(result, { error: "request_failed", message: "Request failed" }));
246
253
  }
247
254
  return jsonSuccess(result.data);
248
255
  });
@@ -276,10 +283,7 @@ itself does not — only this import step does).`, {
276
283
  }, async ({ assetId, path, parent, scenePath, name }) => {
277
284
  const fetched = await getAssetApi(assetId);
278
285
  if (fetched.error || !fetched.asset) {
279
- return jsonError({
280
- error: fetched.error || "asset_not_found",
281
- message: fetched.message || "Asset not found.",
282
- });
286
+ return jsonError(failureBody(fetched, { error: "asset_not_found", message: "Asset not found." }));
283
287
  }
284
288
  try {
285
289
  const imported = await importResolvedAsset(await getClient(), {
@@ -297,6 +301,8 @@ itself does not — only this import step does).`, {
297
301
  });
298
302
  }
299
303
  catch (err) {
304
+ if (err instanceof EngineNotRunningError)
305
+ return engineNotRunningResult(err);
300
306
  const msg = err instanceof Error ? err.message : String(err);
301
307
  return jsonError({
302
308
  error: "import_failed",
@@ -319,15 +325,7 @@ Requires authentication. If the user gets an auth error, they need to run 'npx -
319
325
  }, async ({ query, parent, scenePath, assetType, source }) => {
320
326
  const searchResult = await searchAssetsApi({ query, assetType, limit: 5, source });
321
327
  if (searchResult.error) {
322
- return {
323
- content: [
324
- {
325
- type: "text",
326
- text: JSON.stringify({ error: searchResult.error, message: searchResult.message }, null, 2),
327
- },
328
- ],
329
- isError: true,
330
- };
328
+ return jsonError(failureBody(searchResult, { error: "Search failed", message: "Asset search failed" }));
331
329
  }
332
330
  const assets = searchResult.assets || [];
333
331
  if (assets.length === 0) {
@@ -378,6 +376,8 @@ Requires authentication. If the user gets an auth error, they need to run 'npx -
378
376
  };
379
377
  }
380
378
  catch (err) {
379
+ if (err instanceof EngineNotRunningError)
380
+ return engineNotRunningResult(err);
381
381
  const msg = err instanceof Error ? err.message : String(err);
382
382
  return {
383
383
  content: [
@@ -433,6 +433,8 @@ runs through the engine). No Summer login needed.`, {
433
433
  ...(err.hint ? { hint: err.hint } : {}),
434
434
  });
435
435
  }
436
+ if (err instanceof EngineNotRunningError)
437
+ return engineNotRunningResult(err);
436
438
  const msg = err instanceof Error ? err.message : String(err);
437
439
  return jsonError({
438
440
  error: "hdri_import_failed",
@@ -27,33 +27,33 @@ export function auditContent(result) {
27
27
  return { content };
28
28
  }
29
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.
30
+ server.tool("summer_scene_audit", `Audit a 3D scene in one fast, read-only call: it walks every node and subnode and lists likely visual and placement problems, sorted by severity. Each issue is a flag to LOOK at, never an auto-fix.
31
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.
32
+ Checks (pick with checks; the verifying-scenes skill explains each):
33
+ - through_hole: ray grids through each facade line that pass the wall AND reach the building's far side (an insert narrower than its frame, a missing module). Props do not close an opening.
34
+ - exposed_edge: edges of walls, bands, piers and corner blocks nothing covers within 4-7 mm, seen from walkable space, with a 2-60 cm reveal, a 4 cm seam or a 35 cm gap. Warn on bands or when depth_step agrees, else look.
35
+ - open_fixture_end (warn): open ends of pipe, duct or gutter runs (2+ open rims of one size) nothing joins within 2.5 cm; caps, funnels, outlets are open by design.
36
+ - depth_step (look): ray rows at each facade's band levels and every 1.25 m: recesses, missing runs, seams, proud modules, holes (a hole by a through_hole makes it an error).
37
+ - floor_gap: down rays over tiles, seams and the strip to a wall within 1 m, by FIRST surface hit: the void (error), underlay over the floor's own drain (warn, not a hole), underlay through a hole.
38
+ - floating / sunken: over 2 cm above or 3 cm into the first surface from above; structure and wall-mounted pieces excluded.
39
+ - interpenetration: prop hulls cutting props, walls, structure or inserts over 3 cm, with every partner (up to 3).
40
+ - orientation (look): long props within 1.2 m of a wall over 15 deg off parallel; never says which way to face.
41
+ - uv_stretch: shown triangles with UVs stretched over 8:1 or collapsed.
42
+ - duplicate: same scene, same transform.
43
+ - z_fight: coplanar overlapping faces of two pieces (opposite-facing only if both double-sided) or of one mesh: a gap under twice the 24-bit depth step at the view distance (else 30 m). Warn over 0.05 m2 seen; ev.nudge names the axis to move (world and local). render_priority, depth or normal offsets, alpha, no depth test or writes demote it to look, with the reason.
44
+ - lights: over the per-object omni/spot limit (Compatibility: 8 each), spot_angle_attenuation under 3; shadowed counts.
45
+ - transform: NaN, negative or non-uniform scale, far out of bounds, pieces left at the origin (several = warn, one = look).
46
+ - resource: missing dependencies, a MeshInstance3D without a mesh, surfaces without a material.
47
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.
48
+ budget_ms (default 3000) bounds editor time: each check gets a weighted share; one past it stops, marked counts.<check>.partial (the share covered), never clean. exposed_edge, open_fixture_end and depth_step run last on the time left: rerun them alone when partial.
49
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.
50
+ accept:[{key, reason}] (issues[].key) records look/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 severity rises or the measured size moves over 25% (then accept_stale). Errors cannot be accepted; show_accepted lists them.
51
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.
52
+ Returns at most 5 KB of JSON: counts and editor ms per check, scene size, ONE page of issues {n, check, sev (error|warn|look), path, pos (world), why, ev (evidence numbers, the ray to reproduce), next (the next tool), key}. Page with offset/limit (next_offset); filter with checks, root (subtree), min_severity. render:"sheet" adds ONE image of the page's first 6 issues framed close from their open side, tiles labelled #n.
53
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.
54
+ Every check works from geometry, node and resource data and materials alone: never node or file names, never kit metadata. Each piece's role (dressing, wall, floor, roof, underlay, insert, structure, a prop up to 3.5 m) comes from its shape.
55
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) => {
56
+ Read-only: audits the SAVED file (save first) in a private offscreen copy (ScenePreview): the open tab never becomes unsaved, undo is untouched, nothing is saved. Failures are structured (failure_reason), never a silent fallback.`, sceneAuditShape, async (args) => withEngine(async (client) => {
57
57
  const audit = await sceneAudit(client, args);
58
58
  return audit.ok ? { audit } : { audit, failure_reason: audit.failure_reason };
59
59
  }, { onResult: (wrapped) => auditContent(wrapped.audit) }));