summer-engine 2.6.6 → 2.8.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 (168) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +4 -1
  3. package/.codex-plugin/plugin.json +6 -2
  4. package/.cursor-plugin/plugin.json +5 -1
  5. package/.opencode/INSTALL.md +1 -1
  6. package/.opencode/plugins/summer.js +2 -2
  7. package/AGENTS.md +11 -7
  8. package/CHANGELOG.md +40 -0
  9. package/GEMINI.md +9 -7
  10. package/README.md +63 -21
  11. package/_persona/summer/SKILL.md +1 -0
  12. package/assets/autopilot/README.md +51 -0
  13. package/assets/autopilot/autopilot.gd +222 -0
  14. package/assets/autopilot/probe_base.gd +262 -0
  15. package/assets/autopilot/run.sh +78 -0
  16. package/commands/gameskill.md +11 -2
  17. package/commands/summer.md +13 -0
  18. package/dist/bin/summer.js +12 -0
  19. package/dist/commands/config.d.ts +2 -0
  20. package/dist/commands/config.js +53 -0
  21. package/dist/commands/create.d.ts +1 -0
  22. package/dist/commands/create.js +38 -6
  23. package/dist/commands/debug.d.ts +2 -0
  24. package/dist/commands/debug.js +44 -0
  25. package/dist/commands/doctor.js +112 -8
  26. package/dist/commands/list.js +1 -1
  27. package/dist/commands/login.d.ts +19 -0
  28. package/dist/commands/login.js +123 -36
  29. package/dist/commands/logout.js +3 -16
  30. package/dist/commands/logs.d.ts +2 -0
  31. package/dist/commands/logs.js +19 -0
  32. package/dist/commands/mcp.js +7 -2
  33. package/dist/commands/open.js +1 -1
  34. package/dist/commands/publish.d.ts +2 -0
  35. package/dist/commands/publish.js +20 -0
  36. package/dist/commands/releases.d.ts +2 -0
  37. package/dist/commands/releases.js +20 -0
  38. package/dist/commands/run.js +1 -1
  39. package/dist/commands/skills.js +1 -1
  40. package/dist/lib/api-client.d.ts +15 -4
  41. package/dist/lib/api-client.js +138 -13
  42. package/dist/lib/async-op-lifecycle.d.ts +7 -2
  43. package/dist/lib/async-op-lifecycle.js +32 -9
  44. package/dist/lib/auth.d.ts +40 -12
  45. package/dist/lib/auth.js +173 -37
  46. package/dist/lib/cloud/engine-bridge.d.ts +17 -4
  47. package/dist/lib/cloud/engine-bridge.js +32 -6
  48. package/dist/lib/config.d.ts +20 -0
  49. package/dist/lib/config.js +142 -0
  50. package/dist/lib/creator.d.ts +93 -0
  51. package/dist/lib/creator.js +393 -0
  52. package/dist/lib/debug-report.d.ts +50 -0
  53. package/dist/lib/debug-report.js +308 -0
  54. package/dist/lib/engine.d.ts +35 -2
  55. package/dist/lib/engine.js +240 -6
  56. package/dist/lib/game-task-plan.js +4 -4
  57. package/dist/lib/mcp-boot-notice.d.ts +3 -0
  58. package/dist/lib/mcp-boot-notice.js +7 -0
  59. package/dist/lib/mcp-log.d.ts +3 -0
  60. package/dist/lib/mcp-log.js +72 -0
  61. package/dist/lib/public-surface-paths.d.ts +13 -0
  62. package/dist/lib/public-surface-paths.js +42 -0
  63. package/dist/lib/skills-registry.d.ts +33 -1
  64. package/dist/lib/skills-registry.js +55 -0
  65. package/dist/lib/store.d.ts +14 -0
  66. package/dist/lib/store.js +145 -0
  67. package/dist/lib/summer-compatibility.d.ts +6 -0
  68. package/dist/lib/summer-compatibility.js +22 -0
  69. package/dist/mcp/server.d.ts +10 -3
  70. package/dist/mcp/server.js +104 -11
  71. package/dist/mcp/tools/asset-tools.js +33 -12
  72. package/dist/mcp/tools/cloud-tools.js +15 -15
  73. package/dist/mcp/tools/creator-tools.d.ts +2 -0
  74. package/dist/mcp/tools/creator-tools.js +105 -0
  75. package/dist/mcp/tools/debug-tools.js +44 -1
  76. package/dist/mcp/tools/file-tools.d.ts +2 -0
  77. package/dist/mcp/tools/file-tools.js +154 -0
  78. package/dist/mcp/tools/generate-tools.js +159 -11
  79. package/dist/mcp/tools/project-tools.js +37 -27
  80. package/dist/mcp/tools/scene-tools.js +106 -29
  81. package/dist/mcp/tools/visual-tools.js +4 -3
  82. package/dist/mcp/tools/with-engine.js +4 -4
  83. package/hooks/session-start.sh +5 -5
  84. package/package.json +3 -1
  85. package/references/collaborative-protocol.md +50 -0
  86. package/references/gd-style.md +121 -0
  87. package/references/godot-version.md +51 -0
  88. package/references/mcp-tools-reference.md +199 -0
  89. package/references/public-surface-language.md +30 -0
  90. package/references/summer-folder.md +90 -0
  91. package/references/template-registry.md +73 -0
  92. package/skills/2d-assets/character-portrait/SKILL.md +17 -12
  93. package/skills/2d-assets/concept-art/SKILL.md +10 -9
  94. package/skills/2d-assets/create-asset-sheet/SKILL.md +17 -15
  95. package/skills/2d-assets/pixel-art/SKILL.md +36 -20
  96. package/skills/2d-assets/skybox-panorama/SKILL.md +32 -37
  97. package/skills/2d-assets/sprite-sheet/SKILL.md +40 -35
  98. package/skills/2d-assets/tileable-texture/SKILL.md +28 -22
  99. package/skills/2d-assets/ui-graphics/SKILL.md +46 -32
  100. package/skills/2d-assets/use-widget-asset/SKILL.md +8 -6
  101. package/skills/3d-assets/character-model/SKILL.md +34 -19
  102. package/skills/3d-assets/environment-kit/SKILL.md +11 -5
  103. package/skills/3d-assets/organic-model/SKILL.md +8 -5
  104. package/skills/3d-assets/prop-model/SKILL.md +9 -3
  105. package/skills/3d-assets/vehicle-model/SKILL.md +32 -19
  106. package/skills/README.md +1 -1
  107. package/skills/ai-and-npcs/design-npc/SKILL.md +31 -13
  108. package/skills/animation/animation-tree/SKILL.md +39 -15
  109. package/skills/animation/facial-and-lipsync/SKILL.md +25 -8
  110. package/skills/animation/generate-motion/SKILL.md +47 -15
  111. package/skills/animation/procedural-animation/SKILL.md +31 -13
  112. package/skills/animation/retarget/SKILL.md +127 -79
  113. package/skills/audio/adaptive-music/SKILL.md +24 -20
  114. package/skills/audio/ambient-bed/SKILL.md +22 -16
  115. package/skills/audio/audio-direction/SKILL.md +15 -10
  116. package/skills/audio/music-track/SKILL.md +18 -12
  117. package/skills/audio/sound-effect/SKILL.md +17 -12
  118. package/skills/audio/voice-line/SKILL.md +42 -42
  119. package/skills/character-controllers/fps-controller/SKILL.md +26 -16
  120. package/skills/debugging/debug/SKILL.md +74 -20
  121. package/skills/deployment/export-and-ship/SKILL.md +105 -38
  122. package/skills/deployment/remote-deploy/SKILL.md +140 -0
  123. package/skills/gameplay-mechanics/auto-fire-targeting/SKILL.md +26 -1
  124. package/skills/gameplay-mechanics/design-mechanic/SKILL.md +23 -15
  125. package/skills/level-design/design-level/SKILL.md +22 -8
  126. package/skills/level-design/scene-to-level/SKILL.md +13 -7
  127. package/skills/multiplayer-and-networking/host-authoritative-state/SKILL.md +8 -8
  128. package/skills/multiplayer-and-networking/peer-to-peer-multiplayer/SKILL.md +2 -7
  129. package/skills/multiplayer-and-networking/setup-multiplayer/SKILL.md +26 -18
  130. package/skills/performance/tune-performance/SKILL.md +51 -32
  131. package/skills/rendering-and-lighting/3d-lighting/SKILL.md +34 -5
  132. package/skills/rendering-and-lighting/art-direction/SKILL.md +6 -8
  133. package/skills/scene-and-project/brainstorm-game/SKILL.md +7 -9
  134. package/skills/scene-and-project/make-game/SKILL.md +2 -1
  135. package/skills/scene-and-project/play/SKILL.md +10 -4
  136. package/skills/scene-and-project/scene-composition/SKILL.md +21 -8
  137. package/skills/scene-and-project/summer-cloud/SKILL.md +92 -0
  138. package/skills/scripting-patterns/gdscript-patterns/SKILL.md +1 -1
  139. package/skills/ui-and-ux/ui-basics/SKILL.md +16 -7
  140. package/skills/video/animated-loop/SKILL.md +63 -39
  141. package/skills/video/cinematic-cutscene/SKILL.md +66 -30
  142. package/skills/video/trailer-shot/SKILL.md +30 -21
  143. package/skills/visual-effects/_building-blocks/additive-billboard-particles.md +25 -16
  144. package/skills/visual-effects/_building-blocks/trauma-shake-snippet.md +5 -3
  145. package/skills/visual-effects/game-feel/SKILL.md +51 -33
  146. package/skills/visual-effects/recipes/dissolve/SKILL.md +51 -9
  147. package/skills/visual-effects/recipes/fire/SKILL.md +136 -49
  148. package/skills/visual-effects/recipes/hit-spark/SKILL.md +45 -8
  149. package/skills/visual-effects/recipes/lightning/SKILL.md +59 -27
  150. package/skills/visual-effects/recipes/magic-glow/SKILL.md +59 -26
  151. package/skills/visual-effects/recipes/muzzle-flash/SKILL.md +68 -25
  152. package/skills/visual-effects/recipes/smoke/SKILL.md +89 -28
  153. package/skills/visual-effects/recipes/water-ripple/SKILL.md +83 -23
  154. package/skills/workflow/brainstorming/SKILL.md +1 -1
  155. package/skills/workflow/debugging-game-feel/SKILL.md +29 -9
  156. package/skills/workflow/diagnosing-perf-regressions/SKILL.md +46 -21
  157. package/skills/workflow/gameskill/SKILL.md +11 -2
  158. package/skills/workflow/headless-scripting/SKILL.md +407 -0
  159. package/skills/workflow/investigating-bugs/SKILL.md +4 -2
  160. package/skills/workflow/mcpupdate/SKILL.md +9 -9
  161. package/skills/workflow/playtesting-a-feature/SKILL.md +94 -21
  162. package/skills/workflow/skill-create/SKILL.md +7 -7
  163. package/skills/workflow/skill-test/SKILL.md +3 -3
  164. package/skills/workflow/using-summer/SKILL.md +32 -3
  165. package/skills/workflow/verification-before-completion/SKILL.md +2 -0
  166. package/skills/workflow/writing-plans/SKILL.md +7 -7
  167. package/skills/workflow/writing-skills/SKILL.md +7 -5
  168. package/skills/workflow/writing-skills/testing-skills-with-subagents.md +1 -1
@@ -5,15 +5,30 @@ license: MIT
5
5
  compatibility: [Cursor, Claude Code, Windsurf, Codex]
6
6
  category: animation
7
7
  user-invocable: false
8
- allowed-tools: Read Grep summer_search_assets summer_inspect_resource summer_retarget_motion summer_get_scene_tree summer_set_resource_property summer_save_scene
8
+ allowed-tools: Read Grep summer_search_assets summer_inspect_resource summer_generate_motion summer_get_scene_tree summer_set_resource_property summer_save_scene
9
9
  paths: ["**/*.tscn", "**/*.tres"]
10
10
  ---
11
11
 
12
12
  # Retarget Motion — One Library, Many Characters
13
13
 
14
- Generating a "run" clip costs ~$0.10 and 30s. If you have ten enemies, regenerating ten runs is ten generations of wasted money and clock time when one Meshy retarget call would cost ~$0.05 and take ~10s. Retarget is the right answer the moment a project has more than one rigged humanoid character.
14
+ ## There is no retarget MCP tool. Read this before promising one.
15
15
 
16
- The Meshy retarget pipeline takes a source `animationAssetId` and a target `rigAssetId`, both of which must be **Meshy-rigged humanoids**. It re-projects the animation onto the target's bone hierarchy, preserves timing and root motion, and emits a new `animationAssetId` against the target rig. The source clip is unchanged.
16
+ Summer ships **no** `summer_retarget_motion` tool, and no other MCP tool that
17
+ re-projects an existing animation asset onto a second rig. Verify it yourself:
18
+ `grep -rn 'summer_' tools/summer-cli/src/mcp/tools/*.ts` lists every registered
19
+ tool and there is no retarget entry. Never call one — the MCP server rejects
20
+ unknown tool names outright, and inventing a cost table for it ("$0.05 a clip")
21
+ is worse than saying nothing.
22
+
23
+ Two real paths exist. Pick by whether the target rig is Meshy-rigged.
24
+
25
+ | Situation | Path |
26
+ |---|---|
27
+ | Target is Meshy-rigged and the clip name is on the curated list | Re-run `summer_generate_motion` against the target's `rigAssetId`. Same clip, ~$0.10, ~30s. |
28
+ | Target is not Meshy-rigged, or the clip is hand-authored / Mixamo / bought | In-engine retargeting: `BoneMap` + `SkeletonProfileHumanoid` + `RetargetModifier3D`. No credits, no network, but you configure the bone mapping. |
29
+
30
+ The rest of this skill covers both. The cost math that used to live here assumed a
31
+ retarget API that does not exist; the honest math is below.
17
32
 
18
33
  ## When to use this skill
19
34
 
@@ -24,149 +39,182 @@ The Meshy retarget pipeline takes a source `animationAssetId` and a target `rigA
24
39
 
25
40
  ## When NOT to use this skill
26
41
 
27
- - Source and target are not both Meshy-rigged humanoids — retarget will fail. Route to `summer:animation/generate-motion` to regenerate, or to `summer:asset-pipeline/asset-strategy` to re-rig.
28
- - Target is a quadruped or non-humanoid (wings-only, mech, blob). Meshy retarget is humanoid-skeleton-locked. Hand-author or regenerate.
29
- - The user wants ONE new clip on ONE character — just call `summer:animation/generate-motion`. Retarget is for fan-out.
42
+ - The user wants ONE new clip on ONE character — just call `summer:animation/generate-motion`.
30
43
  - The user wants to retime, edit, or layer the animation — that's `summer:animation/animation-tree` and the `summer:animation/procedural-animation` additive layers.
44
+ - Target is a quadruped or non-humanoid (wings-only, mech, blob). The curated Meshy
45
+ library is humanoid-only and `SkeletonProfileHumanoid` is a humanoid profile.
46
+ Hand-author instead.
31
47
 
32
- ## The compatibility check (do this BEFORE calling retarget)
33
-
34
- The dominant failure mode is retargeting between rigs that look humanoid but have different bone counts, names, or hierarchies. Meshy auto-rigs use a fixed 52-bone humanoid skeleton — every Meshy rig is interchangeable. Mixamo / VRoid / hand-rigged FBX imports are NOT — even if they're "humanoid", the bone names differ and the retarget call rejects them.
35
-
36
- Before calling `summer_retarget_motion`, verify:
37
-
38
- ```
39
- summer_inspect_resource(<source_rigAssetId>)
40
- summer_inspect_resource(<target_rigAssetId>)
41
- ```
42
-
43
- Both responses should include `rig_provider: "meshy"` and `bone_count: 52`. If either is missing those fields or shows a different provider, **stop**. Tell the user: "Target rig isn't Meshy-rigged — retarget will fail. Either re-rig the target via `summer_generate_3d({ kind: \"image-to-3d\", imageUrl: \"...\", options: { rig: true } })` or regenerate motion directly on it via `summer:animation/generate-motion`. Which?"
44
-
45
- If both are Meshy-rigged but the target's mesh has wildly different proportions (e.g., source is a 1.8m human, target is a 2.5m ogre with arms-down-to-knees), retarget will succeed but the *result* will look wrong — clipping, foot-floating, or limb-twisting. Warn the user before spending: "Proportions differ a lot — retarget will run but you'll likely need procedural foot IK on the result. Continue?" Hand off to `summer:animation/procedural-animation` after.
48
+ ## Path A — regenerate on the target rig (Meshy-rigged targets)
46
49
 
47
- ## Steps
50
+ This is the path for the common case: several characters that all came out of
51
+ `summer_generate_3d(... rig: true)`.
48
52
 
49
- ### 1. Find the source library
53
+ ### 1. Find the source clip names
50
54
 
51
55
  ```
52
- summer_search_assets(query: "<source character>", kind: "animation")
56
+ summer_search_assets(query: "<source character>", assetType: "animation", source: "my_assets")
53
57
  ```
54
58
 
55
- Returns a list of `{ animationAssetId, name, durationSeconds }`. Cache the IDs.
59
+ You want the *names* (`idle`, `walk`, `run`, ...), not the asset IDs — the IDs
60
+ belong to the source rig and cannot be transplanted.
56
61
 
57
62
  ### 2. Find the target rig
58
63
 
59
64
  ```
60
- summer_search_assets(query: "<target character>", kind: "model")
65
+ summer_search_assets(query: "<target character>", assetType: "3d_model", source: "my_assets")
61
66
  ```
62
67
 
63
- Confirm `rigAssetId` is present and Meshy-provider.
68
+ Confirm a `rigAssetId` is present. If it is null the model was never rigged —
69
+ stop and propose `summer_generate_3d({ kind: "image-to-3d", imageUrl: "...", options: { rig: true } })`
70
+ first, or route to `summer:asset-pipeline/asset-strategy`.
64
71
 
65
72
  ### 3. Confirm with user before spending
66
73
 
67
- Always batch-ask. Retargets are cheap individually but $0.05 × 30 clips × 5 enemies = $7.50, which deserves consent.
74
+ Regeneration is a real generation per clip per character. Say the total.
68
75
 
69
- > I'm about to retarget 12 clips (idle, walk, run, attack, ...) from `goblin_rigged` onto `orc_rigged` — about 12 × $0.05 = $0.60, ~2 minutes total. OK?
76
+ > I'm about to generate 12 clips (idle, walk, run, attack, ...) on `orc_rigged` —
77
+ > 12 × ~$0.10 = ~$1.20, a few minutes total. OK?
70
78
 
71
- ### 4. Loop the retarget calls
79
+ ### 4. Loop the generation calls
72
80
 
73
81
  ```
74
- for clip in source_clips:
75
- summer_retarget_motion(
76
- sourceAnimationAssetId: clip.animationAssetId,
77
- targetRigAssetId: <target_rigAssetId>,
78
- name: clip.name // preserve the slot name (idle, walk, run...)
82
+ for name in source_clip_names:
83
+ summer_generate_motion(
84
+ rigAssetId: "<target_rigAssetId>",
85
+ backend: "meshy-library",
86
+ motionName: name // exact curated name — see generate-motion's list
79
87
  )
80
- // returns { animationAssetId, durationSeconds }
88
+ // returns animationAssetId in the job result
81
89
  ```
82
90
 
83
91
  Save the returned IDs as a map `{ name: animationAssetId }` for the target.
84
92
 
85
93
  ### 5. Attach to the target's AnimationPlayer
86
94
 
87
- Same pattern as `summer:animation/generate-motion`: ensure an `AnimationPlayer` child exists, then write each clip into `libraries/default`.
95
+ `summer_set_resource_property` requires the target scene path — it is not optional.
88
96
 
89
97
  ```
90
98
  summer_set_resource_property(
99
+ scenePath: "res://main.tscn",
91
100
  nodePath: "./World/Orc/AnimationPlayer",
92
101
  resourceProperty: "libraries/default",
93
102
  subProperty: "<clip_name>",
94
- value: "<retargeted_animationAssetId>"
103
+ value: "<animationAssetId>"
95
104
  )
96
105
  ```
97
106
 
98
- `summer_save_scene` once at the end, not per clip.
107
+ `summer_save_scene(scenePath: "res://main.tscn")` once at the end, not per clip.
108
+
109
+ ## Path B — in-engine retargeting (non-Meshy rigs, bought or hand-authored clips)
110
+
111
+ The current Summer Engine build ships the retargeting stack that the MCP layer
112
+ does not wrap. Verified
113
+ instantiable on the shipped binary: `BoneMap`, `SkeletonProfileHumanoid`
114
+ (56 bones), `RetargetModifier3D`.
115
+
116
+ The shape:
117
+
118
+ 1. Create a `BoneMap` resource per rig, with `profile` set to a
119
+ `SkeletonProfileHumanoid`. Map each profile bone name to that rig's actual
120
+ bone name. Save as `.tres` — one per distinct skeleton, reused forever.
121
+ 2. On import, set the source `.glb`'s import options to use the source rig's
122
+ `BoneMap` so its animation tracks are expressed against the humanoid profile.
123
+ 3. On the target character, add a `RetargetModifier3D` under the `Skeleton3D`
124
+ and set its `profile` to the same `SkeletonProfileHumanoid`. It re-projects
125
+ the profile-space pose onto the target's bones each frame.
126
+
127
+ This costs no credits and works with any humanoid skeleton, including Mixamo and
128
+ hand-rigged FBX. The cost is the bone-mapping pass: a few minutes per distinct
129
+ skeleton, once.
99
130
 
100
131
  ## Confirmation gates
101
132
 
102
- - **Before any retarget call:** show the full list and total cost.
103
- - **After the first retarget:** preview the result. If it looks wrong, stop the loop and re-evaluate (proportions, T-pose, missing bones).
133
+ - **Before any generation call:** show the full clip list and total cost.
134
+ - **After the first clip:** preview the result. If it looks wrong, stop the loop
135
+ and re-evaluate (proportions, T-pose, missing bones).
104
136
  - **Before saving the scene:** confirm the AnimationPlayer additions you're about to write.
105
137
 
106
138
  ## Reference card
107
139
 
108
- ### When retarget fails — the 5 common causes
109
-
110
- | Symptom | Cause | Fix |
111
- |---|---|---|
112
- | API returns `incompatible_rig` | Target isn't Meshy-rigged | Re-rig target via `summer_generate_3d({ kind: "image-to-3d", options: { rig: true } })` |
113
- | API returns `bone_mismatch` | Source rigged with custom bones (extra wings, etc.) | Strip extras or regenerate motion natively on target |
114
- | Clip plays but limbs twist 180° | T-pose vs A-pose mismatch | Re-rig source from T-pose reference |
115
- | Feet float / clip into ground | Target is much taller/shorter | Apply foot IK — see `summer:animation/procedural-animation` |
116
- | Root motion drifts | Source had baked root translation, target scale differs | Strip root track in AnimationPlayer or scale `playback_speed` |
117
-
118
140
  ### Cost math (decision rule)
119
141
 
120
- | Scenario | Generate fresh | Retarget |
142
+ There is no cheaper "retarget" rate to compare against, so the real decision is
143
+ generate-per-character versus spend the time on a `BoneMap`.
144
+
145
+ | Scenario | Regenerate (Path A) | In-engine BoneMap (Path B) |
121
146
  |---|---|---|
122
- | 1 character, 1 clip | $0.10 | n/a |
123
- | 1 character, 12 clips | $1.20 | n/a |
124
- | 5 characters, same 12 clips | $6.00 (5 × $1.20) | $1.80 ($1.20 + 4 × $0.60 retarget) |
125
- | 30 NPCs, same 8-clip set | $24.00 | $6.40 ($0.80 + 29 × $0.40) |
147
+ | 1 character, 12 clips | ~$1.20 | n/a — nothing to share yet |
148
+ | 5 characters, same 12 clips | ~$6.00 | $0, plus ~1 bone-map pass per distinct skeleton |
149
+ | 30 NPCs sharing one skeleton | ~$36.00 | $0 — same rig, so the clips already play on all of them |
126
150
 
127
- The break-even is two characters. Past that, retarget is always cheaper.
151
+ Note the case that makes most of this moot: **NPCs that share one rig share one
152
+ animation library already.** If the user's 30 enemies are 30 instances of the
153
+ same rigged `.glb`, nothing needs retargeting — instance the scene.
128
154
 
129
155
  ### Pitfalls
130
156
 
131
- - **Not preserving clip names.** If you don't pass `name:` to `summer_retarget_motion`, the target gets clips named `retargeted_001`, `retargeted_002` and your AnimationTree state machine breaks. Always pass the source name.
132
- - **Retargeting one clip at a time interactively.** Batch the loop; each call has a few seconds of overhead. Sequential is fine; parallel via `summer_batch` is faster if the project supports it.
133
- - **Forgetting the source library still owns the clips.** Source character's AnimationPlayer is unchanged. Don't accidentally re-attach the *source* IDs to the target.
134
- - **Retargeting then regenerating "to clean it up".** If retarget produced bad output, the fix is procedural foot IK or a bone-correction modifier — not regeneration. Regeneration only makes sense if the source itself is bad.
135
- - **Mixing Meshy and Mixamo libraries on the same character.** They have different bone-naming conventions; the AnimationPlayer tries to play tracks against bones that don't exist. Pick one rig provider per character and stick with it.
157
+ - **Assuming a retarget tool exists.** It does not. Check the tool list before
158
+ promising a capability; a hallucinated tool name fails the call outright.
159
+ - **Reusing the source `animationAssetId` on the target.** Animation assets are
160
+ bound to the rig they were generated against. Generate against the target's own
161
+ `rigAssetId` (Path A) or go through a `BoneMap` (Path B).
162
+ - **Omitting `scenePath`.** `summer_set_resource_property`, `summer_save_scene`,
163
+ `summer_add_node`, and `summer_set_prop` all take a required `scenePath`.
164
+ - **Mixing Meshy and Mixamo libraries on one character without a BoneMap.** The
165
+ bone-naming conventions differ; the AnimationPlayer plays tracks against bones
166
+ that don't exist. One rig provider per character, or map both through the
167
+ humanoid profile.
168
+ - **Proportion mismatch.** A library authored on a 1.8m humanoid on a 2.5m ogre
169
+ runs, but you get foot-float and limb-twist. Layer foot IK afterwards — see
170
+ `summer:animation/procedural-animation`.
136
171
 
137
172
  ### Quality bar
138
173
 
139
- - Library was originally generated on a 1.8m humanoid → target between 1.5m and 2.2m: retarget is production-ready.
140
- - Target is 2.2m–3m: retarget runs, expect foot-clipping; layer foot IK.
141
- - Target is < 1.5m or has cartoon proportions (big head, short limbs): retarget runs, expect noticeable limb-pop; consider regenerating natively.
174
+ - Library authored on a 1.8m humanoid → target between 1.5m and 2.2m: production-ready.
175
+ - Target 2.2m–3m: expect foot-clipping; layer foot IK.
176
+ - Target < 1.5m or cartoon proportions (big head, short limbs): expect limb-pop.
142
177
 
143
178
  ## Anti-patterns
144
179
 
145
- - Calling `summer_retarget_motion` without first verifying both rigs are Meshy-provider.
146
- - Retargeting from a hand-authored animation library (Mixamo `.fbx`, etc.). The MCP wraps Meshy's retarget, which only accepts Meshy-rig source clips. For external libraries, use Godot's built-in `BoneMap` retargeting in the editor — out of scope for this skill.
147
- - Retargeting on every gameplay session. Retarget once, persist the resulting `animationAssetId`, and reference from the scene file. The asset library survives session restarts.
148
- - Generating motion on each enemy separately because you forgot retarget existed. The first time the project has two rigged characters, point at this skill.
180
+ - Calling a `summer_retarget_motion` / `summer_retarget_*` tool. None exists.
181
+ - Quoting a retarget price. There is no retarget SKU to price.
182
+ - Passing an asset ID to `summer_inspect_resource`. That tool takes a `res://`
183
+ **path** to a resource in the project, not a cloud asset ID. Use
184
+ `summer_get_asset(assetId: ...)` for asset metadata.
185
+ - Generating motion on each enemy separately when they are instances of the same
186
+ rig. Instance the scene; the library comes with it.
149
187
 
150
188
  ## Edge cases
151
189
 
152
- - **Source library uses additive blend tracks.** Additive clips (e.g., a "lean left" overlay) retarget but the additive flag is preserved only on Meshy-native rigs. Verify the `track_type` survived: `summer_inspect_resource(<retargeted_animationAssetId>)`.
153
- - **Source has facial blendshape tracks.** Meshy retarget only handles skeleton. Facial tracks are stripped. Hand off to `summer:animation/facial-and-lipsync` to re-author per character.
154
- - **Target rig was generated months ago and Meshy updated their skeleton schema.** Rare but happens. Symptom: bone-count mismatch even though both rigs are Meshy. Re-rig the target with a fresh `summer_generate_3d({ kind: "image-to-3d", options: { rig: true } })` call.
155
- - **The user wants to retarget *to* the source rig as a sanity test.** Allowed and useful — round-trips should be near-identical.
190
+ - **Source has facial blendshape tracks.** Skeleton retargeting only handles
191
+ bones. Facial tracks do not transfer. Hand off to `summer:animation/facial-and-lipsync`
192
+ to re-author per character.
193
+ - **Target rig is a different Meshy skeleton generation.** Symptom: bone-count
194
+ mismatch even though both are Meshy. Re-rig the target with a fresh
195
+ `summer_generate_3d({ kind: "image-to-3d", options: { rig: true } })` call.
196
+ - **The clip the user wants is not on the curated list.** Path A cannot produce
197
+ it. Either hand-author it, or import a Mixamo clip and take Path B.
156
198
 
157
199
  ## Fallback (no MCP)
158
200
 
159
- Open the source `.glb` in Blender, export the animation, then in Godot 4.5 use the BoneMap-based humanoid retargeting workflow (Project → Tools → Bone Map). Set both source and target as humanoid profile, configure the bone mapping if names differ, save the retargeted clip into the target's `AnimationLibrary`. ~5 minutes per clip vs ~10 seconds via MCP. Documented in the Godot 4.5 character animation docs.
201
+ Path B is the fallback and does not need MCP at all. In Summer Engine: select
202
+ the source `.glb` in the FileSystem dock, open the Import tab, create/assign a
203
+ `BoneMap` with a `SkeletonProfileHumanoid` profile, re-import. On the target
204
+ character add a `RetargetModifier3D` under `Skeleton3D` with the same profile.
205
+ Documented in the Godot 4.x "Retargeting 3D Skeletons" docs.
160
206
 
161
207
  ## Handoff
162
208
 
163
- - After retarget, the wiring is identical to a freshly-generated clip — hand off to `summer:animation/animation-tree` for state-machine integration.
164
- - If retarget produced foot-clipping or hand-pen-through-prop issues, hand off to `summer:animation/procedural-animation` for IK correction.
209
+ - After the clips are on the target, the wiring is identical to a freshly-generated
210
+ clip — hand off to `summer:animation/animation-tree` for state-machine integration.
211
+ - If the result shows foot-clipping or hand-pen-through-prop issues, hand off to
212
+ `summer:animation/procedural-animation` for IK correction.
165
213
  - For NPC behavior driving these clips, hand off to `summer:ai-and-npcs/design-npc`.
166
214
 
167
215
  ## See also
168
216
 
169
- - `summer:animation/generate-motion` — to create the source library.
170
- - `summer:asset-pipeline/asset-strategy` — to ensure all characters are Meshy-rigged before retargeting.
171
- - `summer:animation/animation-tree` — wire the retargeted clips into a state machine.
172
- - `summer:animation/procedural-animation` — fix proportional mismatches with foot IK after retarget.
217
+ - `summer:animation/generate-motion` — the tool that actually produces clips, and the curated name list.
218
+ - `summer:asset-pipeline/asset-strategy` — getting characters rigged in the first place.
219
+ - `summer:animation/animation-tree` — wire the clips into a state machine.
220
+ - `summer:animation/procedural-animation` — fix proportional mismatches with foot IK.
@@ -56,7 +56,7 @@ For 90% of indie games, **horizontal sequencing** is correct. It's cheaper to au
56
56
  ### 3. Confirm stems exist (or generate them)
57
57
 
58
58
  ```
59
- summer_search_assets(query="music", filter={ kind: "audio" })
59
+ summer_search_assets(query="music", assetType="music", source="all")
60
60
  ```
61
61
 
62
62
  You need (typical case):
@@ -100,25 +100,27 @@ For ducking, add a sidechain compressor on the `Music` bus with the `Voice` bus
100
100
  For horizontal sequencing, instantiate one `AudioStreamPlayer` per state, all on the Music bus, all autoplay, all looping, all starting at `-60 dB` except the active state:
101
101
 
102
102
  ```
103
- summer_add_node(parentPath="/root/Game/Music", type="AudioStreamPlayer", name="Calm")
104
- summer_set_prop(path="/root/Game/Music/Calm", property="stream", value="res://audio/music/calm.mp3")
105
- summer_set_prop(path="/root/Game/Music/Calm", property="bus", value="Music")
106
- summer_set_prop(path="/root/Game/Music/Calm", property="volume_db", value=0.0)
107
- summer_set_prop(path="/root/Game/Music/Calm", property="autoplay", value=true)
108
-
109
- summer_add_node(parentPath="/root/Game/Music", type="AudioStreamPlayer", name="Tension")
110
- summer_set_prop(path="/root/Game/Music/Tension", property="stream", value="res://audio/music/tension.mp3")
111
- summer_set_prop(path="/root/Game/Music/Tension", property="bus", value="Music")
112
- summer_set_prop(path="/root/Game/Music/Tension", property="volume_db", value=-60.0)
113
- summer_set_prop(path="/root/Game/Music/Tension", property="autoplay", value=true)
114
-
115
- summer_add_node(parentPath="/root/Game/Music", type="AudioStreamPlayer", name="Combat")
116
- summer_set_prop(path="/root/Game/Music/Combat", property="stream", value="res://audio/music/combat.mp3")
117
- summer_set_prop(path="/root/Game/Music/Combat", property="bus", value="Music")
118
- summer_set_prop(path="/root/Game/Music/Combat", property="volume_db", value=-60.0)
119
- summer_set_prop(path="/root/Game/Music/Combat", property="autoplay", value=true)
103
+ summer_add_node(scenePath="res://main.tscn", parent="./Music", type="AudioStreamPlayer", name="Calm")
104
+ summer_set_prop(scenePath="res://main.tscn", path="./Music/Calm", key="stream", value="res://audio/music/calm.mp3")
105
+ summer_set_prop(scenePath="res://main.tscn", path="./Music/Calm", key="bus", value="Music")
106
+ summer_set_prop(scenePath="res://main.tscn", path="./Music/Calm", key="volume_db", value=0.0)
107
+ summer_set_prop(scenePath="res://main.tscn", path="./Music/Calm", key="autoplay", value=true)
108
+
109
+ summer_add_node(scenePath="res://main.tscn", parent="./Music", type="AudioStreamPlayer", name="Tension")
110
+ summer_set_prop(scenePath="res://main.tscn", path="./Music/Tension", key="stream", value="res://audio/music/tension.mp3")
111
+ summer_set_prop(scenePath="res://main.tscn", path="./Music/Tension", key="bus", value="Music")
112
+ summer_set_prop(scenePath="res://main.tscn", path="./Music/Tension", key="volume_db", value=-60.0)
113
+ summer_set_prop(scenePath="res://main.tscn", path="./Music/Tension", key="autoplay", value=true)
114
+
115
+ summer_add_node(scenePath="res://main.tscn", parent="./Music", type="AudioStreamPlayer", name="Combat")
116
+ summer_set_prop(scenePath="res://main.tscn", path="./Music/Combat", key="stream", value="res://audio/music/combat.mp3")
117
+ summer_set_prop(scenePath="res://main.tscn", path="./Music/Combat", key="bus", value="Music")
118
+ summer_set_prop(scenePath="res://main.tscn", path="./Music/Combat", key="volume_db", value=-60.0)
119
+ summer_set_prop(scenePath="res://main.tscn", path="./Music/Combat", key="autoplay", value=true)
120
120
  ```
121
121
 
122
+ Every scene-mutating tool takes an explicit `scenePath`; node paths are relative to that scene's root (`./`), not absolute `/root/...` runtime paths; and the property argument is named `key`, not `property`.
123
+
122
124
  All three play simultaneously, in sync, but only one is audible. State transitions tween volumes — the music never restarts, only fades.
123
125
 
124
126
  This is why same BPM / same key / same bar length matter: all three are at the same playhead at all times.
@@ -309,7 +311,8 @@ Master
309
311
 
310
312
  ## Fallback (no MCP)
311
313
 
312
- Print the bus layout, the node tree, and the GDScript. User constructs in the Godot editor manually.
314
+ Print the bus layout, node tree, and GDScript. The user constructs it manually
315
+ in Summer Engine.
313
316
 
314
317
  ## Handoff
315
318
 
@@ -323,4 +326,5 @@ Print the bus layout, the node tree, and the GDScript. User constructs in the Go
323
326
  - `audio/audio-direction` — defines the dynamic music plan and bus layout
324
327
  - `audio/music-track` — generates the stems
325
328
  - `audio/voice-line` — the voice bus that triggers ducking
326
- - `references/godot-version.md` — Godot 4.5 AudioServer and Tween API
329
+ - `../../../references/godot-version.md` — Summer compatibility for AudioServer
330
+ and Tween APIs
@@ -17,7 +17,8 @@ An ambient bed is the *air* of a place. Forest at dawn, dungeon corridor, spaces
17
17
 
18
18
  This is **not** music. Use `summer_generate_audio({capability: 'sound_effects'})`, not `{capability: 'music'}`. SFX renders textures; Music renders melody. You want texture.
19
19
 
20
- Generated at 15–22 seconds (the SFX duration ceiling) and looped seamlessly with a Godot loop point and optional crossfade.
20
+ Generated at 15–22 seconds (the SFX duration ceiling) and looped with a Summer
21
+ Engine import loop point and optional crossfade.
21
22
 
22
23
  ## When to use
23
24
 
@@ -102,38 +103,43 @@ If the user wants a busier bed (market, party), still prevent foreground events:
102
103
  ```
103
104
  summer_generate_audio(
104
105
  capability: "sound_effects",
105
- prompt: "forest at dawn, gentle wind through leaves, distant bird calls every 6 seconds, soft creaking branches, no music, no human sound, 22s seamless loop",
106
+ text: "forest at dawn, gentle wind through leaves, distant bird calls every 6 seconds, soft creaking branches, no music, no human sound, 22s seamless loop",
106
107
  durationSeconds: 22
107
108
  )
108
- // Result: { asset: { fileUrl, ... } }
109
109
  // Then: summer_import_from_url(url: "<fileUrl>", path: "res://audio/ambient/forest_dawn.wav")
110
110
  ```
111
111
 
112
+ `sound_effects` reads from **`text`**, not `prompt` — passing `prompt` is a 400 `text_required`. (`prompt` is the `music` capability's field.) The clip comes back as WAV, so a `.wav` target path is correct.
113
+
112
114
  22s is the SFX ceiling. Always generate at the ceiling for ambient — longer cycle means less recognized repetition.
113
115
 
114
116
  If the model returns a clip with a loud event near the start or end (a sudden bird right at 0:00), regenerate. That kills loop seamlessness.
115
117
 
116
- ### 6. Mark the seamless loop in Godot's import dock
118
+ ### 6. Mark the seamless loop in Summer Engine's Import dock
117
119
 
118
120
  This step is what makes the bed sound like a place rather than a 22-second sample.
119
121
 
120
- In the Godot editor, select the `.wav`, open the Import dock:
122
+ WAV and MP3 use **different importers with different option names** — do not copy the MP3 block from `audio/music-track` here. The WAV importer has no `loop` / `loop_offset`; it has an `edit/loop_mode` enum plus sample-frame bounds.
123
+
124
+ In Summer Engine, select the `.wav` and open the Import dock:
121
125
 
122
126
  | Setting | Value |
123
127
  |---|---|
124
- | Loop | On |
125
- | Loop Mode | Forward |
126
- | Loop Begin | 0 (or 0.5 if there's a fade-in artifact) |
128
+ | Edit > Loop Mode | Forward |
129
+ | Edit > Loop Begin | 0 |
130
+ | Edit > Loop End | -1 (end of file) |
127
131
 
128
132
  The `.import` file:
129
133
 
130
134
  ```
131
135
  [params]
132
- loop = true
133
- loop_offset = 0.0
134
- loop_mode = 1
136
+ edit/loop_mode = 2
137
+ edit/loop_begin = 0
138
+ edit/loop_end = -1
135
139
  ```
136
140
 
141
+ `edit/loop_mode` is `0 = Detect From WAV, 1 = Disabled, 2 = Forward, 3 = Ping-Pong, 4 = Backward` — Forward is **2**, not 1. `edit/loop_begin` / `edit/loop_end` are integer sample frames, not seconds; to skip a 0.5 s fade-in artifact at 44.1 kHz set `edit/loop_begin = 22050`.
142
+
137
143
  After changing, click `Reimport`.
138
144
 
139
145
  ### 7. Crossfade-loop pattern for seamlessness
@@ -190,11 +196,11 @@ This eliminates the click and adds variation through phase-overlap (the loop ove
190
196
  For most beds, non-positional is correct (the player is *in* the place; the bed isn't an emitter):
191
197
 
192
198
  ```
193
- summer_add_node(parentPath="/root/Game/Level", type="AudioStreamPlayer", name="AmbientBed")
194
- summer_set_prop(path="/root/Game/Level/AmbientBed", property="stream", value="res://audio/ambient/forest_dawn.wav")
195
- summer_set_prop(path="/root/Game/Level/AmbientBed", property="bus", value="Ambient")
196
- summer_set_prop(path="/root/Game/Level/AmbientBed", property="volume_db", value=-12.0)
197
- summer_set_prop(path="/root/Game/Level/AmbientBed", property="autoplay", value=true)
199
+ summer_add_node(scenePath="res://levels/level_01.tscn", parent="./Level", type="AudioStreamPlayer", name="AmbientBed")
200
+ summer_set_prop(scenePath="res://levels/level_01.tscn", path="./Level/AmbientBed", key="stream", value="res://audio/ambient/forest_dawn.wav")
201
+ summer_set_prop(scenePath="res://levels/level_01.tscn", path="./Level/AmbientBed", key="bus", value="Ambient")
202
+ summer_set_prop(scenePath="res://levels/level_01.tscn", path="./Level/AmbientBed", key="volume_db", value=-12.0)
203
+ summer_set_prop(scenePath="res://levels/level_01.tscn", path="./Level/AmbientBed", key="autoplay", value=true)
198
204
  ```
199
205
 
200
206
  Or attach the script in step 7 to a Node, set its `stream` to the imported audio, and skip the `AudioStreamPlayer` node — the script provides its own.
@@ -139,7 +139,8 @@ Rules:
139
139
 
140
140
  ### 8. Configure the audio bus layout
141
141
 
142
- Real audio in Godot needs a bus layout. Default Godot has Master only — configure the buses now.
142
+ Real audio in Summer Engine needs a bus layout. A new project starts with only
143
+ the Master bus, so configure the remaining buses now.
143
144
 
144
145
  **Preferred (Summer MCP):** Buses are typically in `default_bus_layout.tres`. Modify project setting:
145
146
 
@@ -151,7 +152,8 @@ Ask the user:
151
152
 
152
153
  > May I create `audio/default_bus_layout.tres` with these buses: Master / Music / SFX / UI / Voice / Ambient / Reverb_Small / Reverb_Large / Reverb_Outdoor?
153
154
 
154
- On yes, write the `.tres` directly via `Write` (it's plain Godot resource format the host can produce):
155
+ On yes, write the `.tres` directly via `Write` (it is the engine's plain-text
156
+ resource format):
155
157
 
156
158
  ```
157
159
  Write audio/default_bus_layout.tres
@@ -204,11 +206,13 @@ Ask:
204
206
  If the user wants to start generating, propose 3-5 SFX seeds aligned with the vocabulary. These are starting points, not finals.
205
207
 
206
208
  ```
207
- summer_generate_audio(prompt="soft woody UI click, 80ms, no reverb, neutral pitch", duration=0.1)
208
- summer_generate_audio(prompt="warm major-third coin pickup, 300ms, light reverb", duration=0.3)
209
- summer_generate_audio(prompt="punchy low-mid player damage hit, slight detune, 200ms, no tail", duration=0.2)
209
+ summer_generate_audio(capability="sound_effects", text="soft woody UI click, 80ms, no reverb, neutral pitch", durationSeconds=0.5)
210
+ summer_generate_audio(capability="sound_effects", text="warm major-third coin pickup, 300ms, light reverb", durationSeconds=0.5)
211
+ summer_generate_audio(capability="sound_effects", text="punchy low-mid player damage hit, slight detune, 200ms, no tail", durationSeconds=0.5)
210
212
  ```
211
213
 
214
+ `capability` is required; `sound_effects` reads from `text` (not `prompt`), and the length argument is `durationSeconds` (not `duration`) with a floor of 0.5 s. Ask for the character you want inside the text and let the player only use the front of the clip — you cannot request 80 ms.
215
+
212
216
  Ask first:
213
217
 
214
218
  > May I generate first-pass SFX seeds for UI, pickup, and damage classes? They're starting points, not finals.
@@ -235,11 +239,11 @@ End with:
235
239
  | Pure sine "ding" for pickup | Reads as cheap mobile game. Use a major-third interval with character. |
236
240
  | Same footstep sample for all surfaces | Material-aware footsteps are 80% of the perceived audio quality. |
237
241
  | No master ceiling / true peak | Audio clips on console builds without `-1 dBTP` ceiling. Always set it. |
238
- | Calling SetResourceProperty on inline sub_resources | Silent fail. See `references/mcp-tools-reference.md` § Trap. |
242
+ | Calling SetResourceProperty on inline sub_resources | Silent fail. See `../../../references/mcp-tools-reference.md` § Trap. |
239
243
 
240
244
  ## Collaborative protocol
241
245
 
242
- This skill writes one bible (`.summer/audio-bible.md`), creates a bus layout (`audio/default_bus_layout.tres`), modifies `project.godot`, and may generate audio (metered). Always ask before writing or generating. See `references/collaborative-protocol.md`.
246
+ This skill writes one bible (`.summer/audio-bible.md`), creates a bus layout (`audio/default_bus_layout.tres`), modifies `project.godot`, and may generate audio (metered). Always ask before writing or generating. See `../../../references/collaborative-protocol.md`.
243
247
 
244
248
  ## Want a working starter?
245
249
 
@@ -247,9 +251,10 @@ No template — this is a workflow that produces the bible the rest of the proje
247
251
 
248
252
  ## See also
249
253
 
250
- - `references/collaborative-protocol.md`
251
- - `references/godot-version.md` — Godot 4.5 audio API notes
252
- - `references/mcp-tools-reference.md`
254
+ - `../../../references/collaborative-protocol.md`
255
+ - `../../../references/godot-version.md` — Summer compatibility and
256
+ version-sensitive audio API notes
257
+ - `../../../references/mcp-tools-reference.md`
253
258
  - `scene-and-project/brainstorm-game/SKILL.md` — produces the brief that anchors the bible
254
259
  - `rendering-and-lighting/art-direction/SKILL.md` — the visual counterpart; audio must rhyme with it
255
260
  - `audio/audio-bus-setup/SKILL.md` (NEXT) — implements the bus layout in detail
@@ -13,7 +13,7 @@ paths: ["audio/music/**", "scripts/**", "**/*.tscn"]
13
13
 
14
14
  ## Overview
15
15
 
16
- ElevenLabs Music renders 10–300 seconds of music from a prompt. The output quality depends entirely on prompt specificity: tempo (BPM), key, instrumentation, mood, structural cue. "Epic orchestral" returns generic stock music. "85 BPM, D minor, solo cello and detuned upright piano, sparse, melancholic, no drums, 4/4" returns a usable score for a melancholic exploration scene.
16
+ ElevenLabs Music renders a track from a prompt. Summer clamps the requested length to **3–600 seconds** before sending it, so anything outside that range is silently pulled to the nearest bound. The output quality depends entirely on prompt specificity: tempo (BPM), key, instrumentation, mood, structural cue. "Epic orchestral" returns generic stock music. "85 BPM, D minor, solo cello and detuned upright piano, sparse, melancholic, no drums, 4/4" returns a usable score for a melancholic exploration scene.
17
17
 
18
18
  This skill produces one track aligned with the audio bible's music style and dynamic music plan, then wires it as an `AudioStreamPlayer` on the `Music` bus with a marked loop point if it's a loop, or as a linear cinematic stream if it's a one-shot.
19
19
 
@@ -126,21 +126,26 @@ Show the prompt:
126
126
  > `85 BPM, D minor, 4/4, solo cello and detuned upright piano, sparse, melancholic exploration loop, no drums, gentle reverb, 60s loop`
127
127
  > Duration 60s. Cost: ~12 credits. Generate?
128
128
 
129
+ The `music` capability reads the description from **`prompt`**, not `text` — the mirror image of `sound_effects`. Passing `text` here is a 400 `prompt_required`.
130
+
129
131
  ```
130
132
  summer_generate_audio(
131
133
  capability: "music",
132
134
  prompt: "85 BPM, D minor, 4/4, solo cello and detuned upright piano, sparse, melancholic exploration loop, no drums, gentle reverb, 60s loop",
133
135
  durationSeconds: 60
134
136
  )
135
- // Result: { asset: { fileUrl, ... } }
136
137
  // Then: summer_import_from_url(url: "<fileUrl>", path: "res://audio/music/calm_exploration.mp3")
137
138
  ```
138
139
 
139
- `durationSeconds` range is 10–300.
140
+ `durationSeconds` is clamped to 3–600. Music comes back as MP3 (`audio/mpeg`), so a `.mp3` target path is correct.
141
+
142
+ ### 7. Mark the loop point in Summer Engine
140
143
 
141
- ### 7. Mark the loop point in Godot
144
+ ElevenLabs Music does not return a loop-clean cut. You must mark the loop point
145
+ in Summer Engine's Import dock so playback returns to the loop point on
146
+ completion, not to 0:00.
142
147
 
143
- ElevenLabs Music does not return a loop-clean cut. You must mark the loop point in Godot's import dock so playback returns to the loop point on completion, not to 0:00.
148
+ The MP3 importer exposes exactly five options — `loop`, `loop_offset`, `bpm`, `beat_count`, `bar_beats`. There is **no `loop_mode`** on MP3 or OGG; `loop_mode` belongs to the WAV importer, where it is spelled `edit/loop_mode`.
144
149
 
145
150
  In `audio/music/calm_exploration.mp3.import`:
146
151
 
@@ -148,21 +153,22 @@ In `audio/music/calm_exploration.mp3.import`:
148
153
  [params]
149
154
  loop = true
150
155
  loop_offset = 0.0
151
- loop_mode = 0 # 0=disabled, 1=forward, 2=ping-pong, 3=backward
152
156
  ```
153
157
 
154
- If the start has a fade-in but the body is loopable, set `loop_offset = 4.0` (4 seconds of intro skipped on loop, plays full track first time).
158
+ If the start has a fade-in but the body is loopable, set `loop_offset = 4.0` (4 seconds of intro skipped on loop, plays full track first time). `bpm` + `beat_count` + `bar_beats` are what you set if you want beat-synced transitions later — see `audio/adaptive-music`.
155
159
 
156
160
  For seamless looping, the cleaner option is to ask the model to generate a cell (one bar / one phrase) and concatenate; or generate at 60s and trust the model's structural cue. Crossfade looping in code is the practical fallback (see step 9).
157
161
 
158
162
  ### 8. Wire it as `AudioStreamPlayer` on the `Music` bus
159
163
 
164
+ Every scene-mutating tool takes an explicit `scenePath`, node paths are relative to the scene root (`./`), and the property argument is named `key`, not `property`:
165
+
160
166
  ```
161
- summer_add_node(parentPath="/root/Game", type="AudioStreamPlayer", name="MusicCalm")
162
- summer_set_prop(path="/root/Game/MusicCalm", property="stream", value="res://audio/music/calm_exploration.mp3")
163
- summer_set_prop(path="/root/Game/MusicCalm", property="bus", value="Music")
164
- summer_set_prop(path="/root/Game/MusicCalm", property="volume_db", value=-8.0)
165
- summer_set_prop(path="/root/Game/MusicCalm", property="autoplay", value=true)
167
+ summer_add_node(scenePath="res://main.tscn", parent=".", type="AudioStreamPlayer", name="MusicCalm")
168
+ summer_set_prop(scenePath="res://main.tscn", path="./MusicCalm", key="stream", value="res://audio/music/calm_exploration.mp3")
169
+ summer_set_prop(scenePath="res://main.tscn", path="./MusicCalm", key="bus", value="Music")
170
+ summer_set_prop(scenePath="res://main.tscn", path="./MusicCalm", key="volume_db", value=-8.0)
171
+ summer_set_prop(scenePath="res://main.tscn", path="./MusicCalm", key="autoplay", value=true)
166
172
  ```
167
173
 
168
174
  Music is `AudioStreamPlayer` (not 2D / 3D) — non-positional. The bible's `Music -8 dB` mix sits the music behind SFX where it belongs.