summer-engine 3.0.0 → 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +27 -5
- package/.codex-plugin/plugin.json +28 -6
- package/.cursor-plugin/plugin.json +27 -5
- package/.factory-plugin/plugin.json +27 -5
- package/.opencode/plugins/summer.js +1 -1
- package/CHANGELOG.md +120 -0
- package/README.md +22 -7
- package/assets/audit/scene_audit.gd +4136 -0
- package/assets/seeing/seeing_probe.gd +1873 -0
- package/dist/cli/commands/setup.js +6 -19
- package/dist/cli/commands/skills.js +57 -32
- package/dist/core/api-client.d.ts +9 -1
- package/dist/core/api-client.js +21 -4
- package/dist/core/capabilities/agent-playbook.js +46 -0
- package/dist/core/capabilities/audit/accept.d.ts +55 -0
- package/dist/core/capabilities/audit/accept.js +147 -0
- package/dist/core/capabilities/audit/args.d.ts +95 -0
- package/dist/core/capabilities/audit/args.js +89 -0
- package/dist/core/capabilities/audit/audit.d.ts +56 -0
- package/dist/core/capabilities/audit/audit.js +287 -0
- package/dist/core/capabilities/audit/frame.d.ts +14 -0
- package/dist/core/capabilities/audit/frame.js +35 -0
- package/dist/core/capabilities/audit/gaps.d.ts +96 -0
- package/dist/core/capabilities/audit/gaps.js +257 -0
- package/dist/core/capabilities/audit/judge.d.ts +162 -0
- package/dist/core/capabilities/audit/judge.js +1134 -0
- package/dist/core/capabilities/audit/math.d.ts +110 -0
- package/dist/core/capabilities/audit/math.js +263 -0
- package/dist/core/capabilities/audit/summary.d.ts +74 -0
- package/dist/core/capabilities/audit/summary.js +212 -0
- package/dist/core/capabilities/board.d.ts +31 -0
- package/dist/core/capabilities/board.js +43 -0
- package/dist/core/capabilities/camera-view.d.ts +4 -2
- package/dist/core/capabilities/camera-view.js +6 -3
- package/dist/core/capabilities/connect-signal.d.ts +85 -0
- package/dist/core/capabilities/connect-signal.js +285 -0
- package/dist/core/capabilities/engine-fallbacks.d.ts +5 -0
- package/dist/core/capabilities/engine-fallbacks.js +5 -0
- package/dist/core/capabilities/engine-ops.d.ts +5 -1
- package/dist/core/capabilities/engine-ops.js +0 -3
- package/dist/core/capabilities/engine-receipt.d.ts +12 -0
- package/dist/core/capabilities/engine-receipt.js +26 -0
- package/dist/core/capabilities/file-read.d.ts +64 -0
- package/dist/core/capabilities/file-read.js +325 -0
- package/dist/core/capabilities/game-task-plan.js +4 -2
- package/dist/core/capabilities/grep.d.ts +60 -0
- package/dist/core/capabilities/grep.js +190 -0
- package/dist/core/capabilities/inspect-node.d.ts +56 -0
- package/dist/core/capabilities/inspect-node.js +225 -0
- package/dist/core/capabilities/inspect-resource.d.ts +61 -0
- package/dist/core/capabilities/inspect-resource.js +376 -0
- package/dist/core/capabilities/math3d.d.ts +28 -0
- package/dist/core/capabilities/math3d.js +88 -0
- package/dist/core/capabilities/motion-generation.d.ts +62 -0
- package/dist/core/capabilities/motion-generation.js +138 -0
- package/dist/core/capabilities/placement-batch.d.ts +102 -0
- package/dist/core/capabilities/placement-batch.js +483 -0
- package/dist/core/capabilities/placement-math.d.ts +70 -0
- package/dist/core/capabilities/placement-math.js +209 -0
- package/dist/core/capabilities/placement-script.d.ts +42 -0
- package/dist/core/capabilities/placement-script.js +1096 -0
- package/dist/core/capabilities/placement.d.ts +485 -0
- package/dist/core/capabilities/placement.js +1731 -0
- package/dist/core/capabilities/project-context.d.ts +33 -2
- package/dist/core/capabilities/project-context.js +87 -4
- package/dist/core/capabilities/replace-node.d.ts +91 -0
- package/dist/core/capabilities/replace-node.js +423 -0
- package/dist/core/capabilities/runtime-control.d.ts +20 -4
- package/dist/core/capabilities/runtime-control.js +67 -2
- package/dist/core/capabilities/scene-batch.d.ts +63 -0
- package/dist/core/capabilities/scene-batch.js +394 -0
- package/dist/core/capabilities/scene-readback.d.ts +36 -0
- package/dist/core/capabilities/scene-readback.js +54 -0
- package/dist/core/capabilities/seeing/args.d.ts +348 -0
- package/dist/core/capabilities/seeing/args.js +178 -0
- package/dist/core/capabilities/seeing/candidates.d.ts +127 -0
- package/dist/core/capabilities/seeing/candidates.js +282 -0
- package/dist/core/capabilities/seeing/math.d.ts +134 -0
- package/dist/core/capabilities/seeing/math.js +269 -0
- package/dist/core/capabilities/seeing/probe.d.ts +62 -0
- package/dist/core/capabilities/seeing/probe.js +188 -0
- package/dist/core/capabilities/seeing/scoring.d.ts +235 -0
- package/dist/core/capabilities/seeing/scoring.js +639 -0
- package/dist/core/capabilities/seeing/seeing.d.ts +233 -0
- package/dist/core/capabilities/seeing/seeing.js +1341 -0
- package/dist/core/capabilities/seeing/shot-store.d.ts +52 -0
- package/dist/core/capabilities/seeing/shot-store.js +204 -0
- package/dist/core/capabilities/surface-snap-mesh.d.ts +88 -0
- package/dist/core/capabilities/surface-snap-mesh.js +425 -0
- package/dist/core/capabilities/surface-snap.d.ts +77 -0
- package/dist/core/capabilities/surface-snap.js +461 -0
- package/dist/core/capabilities/tool-dispatch.js +231 -72
- package/dist/core/capabilities/tscn.d.ts +85 -0
- package/dist/core/capabilities/tscn.js +391 -0
- package/dist/core/capabilities/world-snapshot.d.ts +58 -0
- package/dist/core/capabilities/world-snapshot.js +150 -0
- package/dist/core/capability-skew.d.ts +5 -5
- package/dist/core/capability-skew.js +14 -6
- package/dist/core/headless/worker-engine-client.d.ts +1 -1
- package/dist/core/headless/worker-engine-client.js +2 -2
- package/dist/core/library-read.d.ts +37 -5
- package/dist/core/library-read.js +264 -33
- package/dist/core/library-search.d.ts +2 -2
- package/dist/core/skills-registry.d.ts +9 -1
- package/dist/core/skills-registry.js +25 -2
- package/dist/installer/agent-config.d.ts +9 -4
- package/dist/installer/agent-config.js +194 -392
- package/dist/installer/agent-table.d.ts +119 -0
- package/dist/installer/agent-table.js +619 -0
- package/dist/installer/setup.js +4 -2
- package/dist/installer/skill-locations.d.ts +8 -17
- package/dist/installer/skill-locations.js +22 -101
- package/dist/installer/version-check.d.ts +5 -1
- package/dist/installer/version-check.js +38 -28
- package/dist/mcp/server.js +9 -3
- package/dist/mcp/tools/asset-tools.js +21 -3
- package/dist/mcp/tools/audit-tools.d.ts +23 -0
- package/dist/mcp/tools/audit-tools.js +60 -0
- package/dist/mcp/tools/debug-tools.js +3 -1
- package/dist/mcp/tools/file-tools.js +17 -4
- package/dist/mcp/tools/generate-tools.js +74 -66
- package/dist/mcp/tools/library-tools.js +2 -0
- package/dist/mcp/tools/perception-tools.js +6 -19
- package/dist/mcp/tools/placement-tools.d.ts +24 -0
- package/dist/mcp/tools/placement-tools.js +91 -0
- package/dist/mcp/tools/project-tools.js +18 -15
- package/dist/mcp/tools/scene-tools.js +71 -83
- package/dist/mcp/tools/seeing-tools.d.ts +24 -0
- package/dist/mcp/tools/seeing-tools.js +64 -0
- package/dist/mcp/tools/spatial-tools.js +17 -9
- package/dist/mcp/tools/visual-tools.js +59 -7
- package/gemini-extension.json +26 -4
- package/integrations/README.md +48 -19
- package/integrations/amp/README.md +12 -0
- package/integrations/amp/manifest-target.json +3 -0
- package/integrations/antigravity/README.md +12 -0
- package/integrations/antigravity/manifest-target.json +3 -0
- package/integrations/claude-desktop/README.md +12 -0
- package/integrations/claude-desktop/manifest-target.json +3 -0
- package/integrations/cline/README.md +8 -9
- package/integrations/cline-cli/README.md +12 -0
- package/integrations/cline-cli/manifest-target.json +3 -0
- package/integrations/copilot-jetbrains/README.md +12 -0
- package/integrations/copilot-jetbrains/manifest-target.json +3 -0
- package/integrations/crush/README.md +12 -0
- package/integrations/crush/manifest-target.json +3 -0
- package/integrations/github-copilot/README.md +8 -8
- package/integrations/goose/README.md +12 -0
- package/integrations/goose/manifest-target.json +3 -0
- package/integrations/grok-build/README.md +12 -0
- package/integrations/grok-build/manifest-target.json +3 -0
- package/integrations/hermes/README.md +12 -0
- package/integrations/hermes/manifest-target.json +3 -0
- package/integrations/junie/README.md +12 -0
- package/integrations/junie/manifest-target.json +3 -0
- package/integrations/kilo-code/README.md +6 -10
- package/integrations/kimi-code/README.md +12 -0
- package/integrations/kimi-code/manifest-target.json +3 -0
- package/integrations/kiro/README.md +12 -0
- package/integrations/kiro/manifest-target.json +3 -0
- package/integrations/lm-studio/README.md +8 -8
- package/integrations/mistral-vibe/README.md +12 -0
- package/integrations/mistral-vibe/manifest-target.json +3 -0
- package/integrations/opencode/README.md +9 -12
- package/integrations/qoder/README.md +12 -0
- package/integrations/qoder/manifest-target.json +3 -0
- package/integrations/qwen-code/README.md +12 -0
- package/integrations/qwen-code/manifest-target.json +3 -0
- package/integrations/roo-code/README.md +8 -7
- package/integrations/rovo-dev/README.md +12 -0
- package/integrations/rovo-dev/manifest-target.json +3 -0
- package/integrations/trae/README.md +12 -0
- package/integrations/trae/manifest-target.json +3 -0
- package/integrations/visual-studio/README.md +12 -0
- package/integrations/visual-studio/manifest-target.json +3 -0
- package/integrations/vscode-copilot/README.md +9 -9
- package/integrations/warp/README.md +12 -0
- package/integrations/warp/manifest-target.json +3 -0
- package/integrations/windsurf/README.md +8 -9
- package/integrations/zed/README.md +12 -0
- package/integrations/zed/manifest-target.json +3 -0
- package/library/references/mcp-tools-reference/mcp-tools-reference.md +59 -15
- package/library/references/mcp-tools-reference/resource.yaml +1 -1
- package/library/references/summer-folder/resource.yaml +1 -1
- package/library/references/summer-folder/summer-folder.md +1 -1
- package/library/skills/3d-lighting/SKILL.md +1 -1
- package/library/skills/README.md +264 -0
- package/library/skills/adaptive-music/SKILL.md +1 -1
- package/library/skills/agent-playtesting/SKILL.md +1 -1
- package/library/skills/ai-characters-in-games/SKILL.md +220 -0
- package/library/skills/ai-characters-in-games/resource.yaml +30 -0
- package/library/skills/ambient-bed/SKILL.md +1 -1
- package/library/skills/animated-loop/SKILL.md +1 -1
- package/library/skills/animation-tree/SKILL.md +1 -1
- package/library/skills/art-direction/SKILL.md +1 -1
- package/library/skills/asset-strategy/SKILL.md +2 -1
- package/library/skills/asset-strategy/resource.yaml +2 -1
- package/library/skills/audio-direction/SKILL.md +1 -1
- package/library/skills/auto-fire-targeting/SKILL.md +1 -1
- package/library/skills/brainstorm-game/SKILL.md +1 -1
- package/library/skills/brainstorming/SKILL.md +1 -1
- package/library/skills/browse-templates/SKILL.md +3 -3
- package/library/skills/browse-templates/resource.yaml +1 -1
- package/library/skills/camera-rigs/SKILL.md +128 -0
- package/library/skills/camera-rigs/resource.yaml +29 -0
- package/library/skills/celeste-momentum-platforming/SKILL.md +1 -1
- package/library/skills/character-animation-wiring/SKILL.md +1 -1
- package/library/skills/character-model/SKILL.md +1 -1
- package/library/skills/character-movement/SKILL.md +326 -0
- package/library/skills/character-movement/references/default-third-person-controller.gd +201 -0
- package/library/skills/character-movement/references/default-third-person-verification-probe.gd +154 -0
- package/library/skills/character-movement/references/movement-3d.md +136 -0
- package/library/skills/character-movement/references/platformer-feel.md +83 -0
- package/library/skills/character-movement/resource.yaml +40 -0
- package/library/skills/character-portrait/SKILL.md +1 -1
- package/library/skills/cinematic-cutscene/SKILL.md +1 -1
- package/library/skills/combat-basics/SKILL.md +159 -0
- package/library/skills/combat-basics/references/projectiles-and-aoe.md +100 -0
- package/library/skills/combat-basics/resource.yaml +34 -0
- package/library/skills/concept-art/SKILL.md +1 -1
- package/library/skills/create-asset-sheet/SKILL.md +1 -1
- package/library/skills/debug/SKILL.md +1 -1
- package/library/skills/debugging-game-feel/SKILL.md +1 -1
- package/library/skills/design-level/SKILL.md +1 -1
- package/library/skills/design-mechanic/SKILL.md +1 -1
- package/library/skills/design-npc/SKILL.md +1 -1
- package/library/skills/diagnosing-perf-regressions/SKILL.md +1 -1
- package/library/skills/dispatching-parallel-agents/SKILL.md +1 -1
- package/library/skills/driving-the-editor-ui/SKILL.md +1 -1
- package/library/skills/environment-kit/SKILL.md +1 -1
- package/library/skills/export-and-ship/SKILL.md +1 -1
- package/library/skills/fabricating-assets/SKILL.md +1 -1
- package/library/skills/facial-and-lipsync/SKILL.md +1 -1
- package/library/skills/fps-controller/SKILL.md +9 -7
- package/library/skills/fps-controller/resource.yaml +4 -1
- package/library/skills/game-feel/SKILL.md +1 -1
- package/library/skills/gameskill/SKILL.md +1 -1
- package/library/skills/gdscript-patterns/SKILL.md +1 -1
- package/library/skills/generate-motion/SKILL.md +9 -9
- package/library/skills/generate-motion/resource.yaml +2 -1
- package/library/skills/godogen-visual-proof-game-generation/SKILL.md +1 -1
- package/library/skills/headless-scripting/SKILL.md +1 -1
- package/library/skills/in-game-purchases/SKILL.md +254 -0
- package/library/skills/in-game-purchases/resource.yaml +29 -0
- package/library/skills/instantiate-asset-pack/SKILL.md +1 -1
- package/library/skills/investigating-bugs/SKILL.md +1 -1
- package/library/skills/lumera-single-image-scene-reconstruction/SKILL.md +1 -1
- package/library/skills/make-game/SKILL.md +25 -3
- package/library/skills/make-game/references/2d-platformer-polish.md +93 -0
- package/library/skills/make-game/references/2d-platformer.md +117 -0
- package/library/skills/make-game/references/2d-rpg-content.md +234 -0
- package/library/skills/make-game/references/2d-rpg.md +241 -0
- package/library/skills/make-game/references/2d-survivors-progression.md +201 -0
- package/library/skills/make-game/references/2d-survivors.md +237 -0
- package/library/skills/make-game/references/3d-fps-systems.md +216 -0
- package/library/skills/make-game/references/3d-fps.md +177 -0
- package/library/skills/make-game/references/3d-horror-systems.md +186 -0
- package/library/skills/make-game/references/3d-horror.md +201 -0
- package/library/skills/make-game/references/3d-third-person-systems.md +220 -0
- package/library/skills/make-game/references/3d-third-person.md +215 -0
- package/library/skills/make-game/resource.yaml +6 -1
- package/library/skills/multiplayer/SKILL.md +150 -0
- package/library/skills/multiplayer/resource.yaml +33 -0
- package/library/skills/multiplayer-movement/SKILL.md +510 -0
- package/library/skills/multiplayer-movement/files.md +501 -0
- package/library/skills/multiplayer-movement/resource.yaml +30 -0
- package/library/skills/multiplayer-project/SKILL.md +521 -0
- package/library/skills/multiplayer-project/files.md +448 -0
- package/library/skills/multiplayer-project/resource.yaml +36 -0
- package/library/skills/multiplayer-publish/SKILL.md +229 -0
- package/library/skills/multiplayer-publish/export-errors.md +89 -0
- package/library/skills/multiplayer-publish/resource.yaml +28 -0
- package/library/skills/multiplayer-state/SKILL.md +438 -0
- package/library/skills/multiplayer-state/files.md +592 -0
- package/library/skills/multiplayer-state/resource.yaml +35 -0
- package/library/skills/multiplayer-testing/SKILL.md +236 -0
- package/library/skills/multiplayer-testing/resource.yaml +39 -0
- package/library/skills/music-track/SKILL.md +1 -1
- package/library/skills/navigate-summer/SKILL.md +1 -1
- package/library/skills/new-project/SKILL.md +1 -1
- package/library/skills/organic-model/SKILL.md +1 -1
- package/library/skills/pixel-art/SKILL.md +1 -1
- package/library/skills/play/SKILL.md +1 -1
- package/library/skills/playtesting-a-feature/SKILL.md +1 -1
- package/library/skills/procedural-animation/SKILL.md +2 -2
- package/library/skills/procedural-animation/resource.yaml +1 -1
- package/library/skills/prop-model/SKILL.md +1 -1
- package/library/skills/psx-retro-rendering/SKILL.md +1 -1
- package/library/skills/realtime-wet-surfaces/SKILL.md +2 -2
- package/library/skills/remote-deploy/SKILL.md +1 -1
- package/library/skills/retarget/SKILL.md +1 -1
- package/library/skills/running-in-the-cloud/SKILL.md +1 -1
- package/library/skills/save-load/SKILL.md +156 -0
- package/library/skills/save-load/resource.yaml +27 -0
- package/library/skills/scene-composition/SKILL.md +1 -1
- package/library/skills/scene-hierarchy-design/SKILL.md +1 -1
- package/library/skills/scene-scripting/SKILL.md +1 -1
- package/library/skills/scene-to-level/SKILL.md +1 -1
- package/library/skills/skill-create/SKILL.md +1 -1
- package/library/skills/skill-improve/SKILL.md +1 -1
- package/library/skills/skill-test/SKILL.md +1 -1
- package/library/skills/skintokens-auto-rigging/SKILL.md +1 -1
- package/library/skills/skybox-panorama/SKILL.md +1 -1
- package/library/skills/sound-effect/SKILL.md +1 -1
- package/library/skills/spatial-placement/SKILL.md +134 -3
- package/library/skills/spatial-placement/references/kit-placement-tools.md +364 -0
- package/library/skills/spatial-placement/resource.yaml +16 -2
- package/library/skills/sprite-sheet/SKILL.md +1 -1
- package/library/skills/summer-analytics/SKILL.md +147 -0
- package/library/skills/summer-analytics/resource.yaml +28 -0
- package/library/skills/summer-friends/SKILL.md +226 -0
- package/library/skills/summer-friends/resource.yaml +28 -0
- package/library/skills/summer-leaderboards/SKILL.md +231 -0
- package/library/skills/summer-leaderboards/resource.yaml +30 -0
- package/library/skills/summer-match-results/SKILL.md +286 -0
- package/library/skills/summer-match-results/resource.yaml +32 -0
- package/library/skills/summer-matchmaking/SKILL.md +301 -0
- package/library/skills/summer-matchmaking/resource.yaml +32 -0
- package/library/skills/summer-parties/SKILL.md +253 -0
- package/library/skills/summer-parties/resource.yaml +30 -0
- package/library/skills/summer-player-data/SKILL.md +322 -0
- package/library/skills/summer-player-data/resource.yaml +30 -0
- package/library/skills/summer-store/SKILL.md +271 -0
- package/library/skills/summer-store/resource.yaml +29 -0
- package/library/skills/summer-world-chat/SKILL.md +195 -0
- package/library/skills/summer-world-chat/resource.yaml +30 -0
- package/library/skills/summer-world-saves/SKILL.md +284 -0
- package/library/skills/summer-world-saves/resource.yaml +29 -0
- package/library/skills/text-to-motion/SKILL.md +99 -0
- package/library/skills/text-to-motion/prompts-and-controls.md +34 -0
- package/library/skills/text-to-motion/resource.yaml +41 -0
- package/library/skills/text-to-motion/rigging-for-text-motion.md +54 -0
- package/library/skills/tileable-texture/SKILL.md +1 -1
- package/library/skills/trailer-shot/SKILL.md +1 -1
- package/library/skills/tune-performance/SKILL.md +1 -1
- package/library/skills/ui-basics/SKILL.md +10 -1
- package/library/skills/ui-graphics/SKILL.md +1 -1
- package/library/skills/use-widget-asset/SKILL.md +1 -1
- package/library/skills/using-summer/SKILL.md +2 -2
- package/library/skills/using-summer/resource.yaml +2 -2
- package/library/skills/vehicle-model/SKILL.md +1 -1
- package/library/skills/verification-before-completion/SKILL.md +1 -1
- package/library/skills/verifying-scenes/SKILL.md +76 -2
- package/library/skills/verifying-scenes/resource.yaml +13 -2
- package/library/skills/vfx-dissolve/SKILL.md +1 -1
- package/library/skills/vfx-fire/SKILL.md +1 -1
- package/library/skills/vfx-hit-spark/SKILL.md +1 -1
- package/library/skills/vfx-lightning/SKILL.md +1 -1
- package/library/skills/vfx-magic-glow/SKILL.md +1 -1
- package/library/skills/vfx-muzzle-flash/SKILL.md +1 -1
- package/library/skills/vfx-smoke/SKILL.md +1 -1
- package/library/skills/vfx-water-ripple/SKILL.md +1 -1
- package/library/skills/voice-line/SKILL.md +1 -1
- package/library/skills/web-and-touch-input/SKILL.md +38 -0
- package/library/skills/web-and-touch-input/resource.yaml +28 -0
- package/library/skills/web-compatibility-look/SKILL.md +62 -0
- package/library/skills/web-compatibility-look/resource.yaml +30 -0
- package/library/skills/world-building-3d/SKILL.md +8 -1
- package/library/skills/world-building-3d/references/spatial-tools.md +1 -1
- package/library/skills/world-building-3d/resource.yaml +2 -1
- package/library/skills/writing-plans/SKILL.md +1 -1
- package/library/skills/writing-skills/SKILL.md +1 -1
- package/library/templates/3d-lan-multiplayer-starter/resource.yaml +2 -2
- package/library/tools/attach-to-surface/resource.yaml +142 -0
- package/library/tools/batch/resource.yaml +9 -3
- package/library/tools/connect-ports/resource.yaml +120 -0
- package/library/tools/connect-signal/resource.yaml +3 -2
- package/library/tools/debug-views/resource.yaml +94 -0
- package/library/tools/frame-nodes/resource.yaml +104 -0
- package/library/tools/frame-shot/resource.yaml +134 -0
- package/library/tools/generate-motion/resource.yaml +44 -9
- package/library/tools/get-board/resource.yaml +50 -0
- package/library/tools/get-project-context/resource.yaml +13 -2
- package/library/tools/grep/resource.yaml +77 -0
- package/library/tools/inspect-asset/resource.yaml +71 -0
- package/library/tools/inspect-node/resource.yaml +9 -2
- package/library/tools/inspect-resource/resource.yaml +16 -5
- package/library/tools/instantiate-scene/resource.yaml +27 -2
- package/library/tools/measure/resource.yaml +96 -0
- package/library/tools/place-adjacent/resource.yaml +113 -0
- package/library/tools/play/resource.yaml +15 -2
- package/library/tools/raycast/resource.yaml +101 -0
- package/library/tools/read-file/resource.yaml +36 -2
- package/library/tools/read-library/resource.yaml +2 -2
- package/library/tools/repeat-along/resource.yaml +129 -0
- package/library/tools/replace-node/resource.yaml +11 -5
- package/library/tools/scene-audit/resource.yaml +144 -0
- package/library/tools/screenshot/resource.yaml +13 -2
- package/library/tools/search-assets/resource.yaml +18 -0
- package/library/tools/shot-sheet/resource.yaml +110 -0
- package/library/tools/snap-to-surface/resource.yaml +4 -1
- package/library/tools/world-snapshot/resource.yaml +24 -3
- package/library/tools/zoom/resource.yaml +105 -0
- package/package.json +3 -3
- package/registry/generated/aliases.json +17 -3
- package/registry/generated/counts.json +3 -3
- package/registry/generated/gemini-extension.json +26 -4
- package/registry/generated/index.json +2154 -469
- package/registry/generated/marketplace.claude.json +2 -2
- package/registry/generated/plugin.claude.json +27 -5
- package/registry/generated/plugin.codex.json +28 -6
- package/registry/generated/plugin.cursor.json +27 -5
- package/registry/generated/plugin.factory.json +27 -5
- package/registry/generated/skills-index.md +264 -0
- package/registry/generated/skills-registry.json +901 -206
- package/registry/generated/templates-registry.json +2 -2
- package/library/skills/host-authoritative-state/SKILL.md +0 -332
- package/library/skills/host-authoritative-state/resource.yaml +0 -28
- package/library/skills/peer-to-peer-multiplayer/SKILL.md +0 -373
- package/library/skills/peer-to-peer-multiplayer/resource.yaml +0 -28
- package/library/skills/setup-multiplayer/SKILL.md +0 -336
- package/library/skills/setup-multiplayer/resource.yaml +0 -28
|
@@ -5,20 +5,7 @@ import { printDoctorResult, runDoctor } from "../../core/capabilities/doctor.js"
|
|
|
5
5
|
import { brandLine, c, sym, tildeify } from "../../core/format.js";
|
|
6
6
|
import { TOOLKIT_VERSION as cliVersion } from "../../core/version.js";
|
|
7
7
|
import { resolveDefaultChannel } from "../../installer/version-check.js";
|
|
8
|
-
|
|
9
|
-
"claude-code": "Claude Code",
|
|
10
|
-
codex: "Codex",
|
|
11
|
-
cursor: "Cursor",
|
|
12
|
-
windsurf: "Devin Desktop (Windsurf)",
|
|
13
|
-
cline: "Cline",
|
|
14
|
-
"roo-code": "Roo Code",
|
|
15
|
-
"kilo-code": "Kilo Code",
|
|
16
|
-
gemini: "Gemini CLI",
|
|
17
|
-
"github-copilot": "GitHub Copilot CLI",
|
|
18
|
-
"vscode-copilot": "GitHub Copilot in VS Code",
|
|
19
|
-
opencode: "OpenCode",
|
|
20
|
-
"lm-studio": "LM Studio",
|
|
21
|
-
};
|
|
8
|
+
import { agentLabel } from "../../installer/agent-table.js";
|
|
22
9
|
export const setupCommand = new Command("setup")
|
|
23
10
|
.description("Configure Summer Engine for an AI agent and run diagnostics")
|
|
24
11
|
.argument("[agent]", `Agent to configure: ${supportedAgents.join(", ")}`)
|
|
@@ -82,15 +69,15 @@ function printSetupResult(config, skills, doctor) {
|
|
|
82
69
|
console.log("");
|
|
83
70
|
console.log(brandLine(cliVersion));
|
|
84
71
|
console.log("");
|
|
85
|
-
const
|
|
72
|
+
const label = agentLabel(config.agent);
|
|
86
73
|
if (config.dryRun) {
|
|
87
|
-
console.log(` ${c.dim("(dry run)")} Would link to ${
|
|
74
|
+
console.log(` ${c.dim("(dry run)")} Would link to ${label} ${c.dim(tildeify(config.path))}`);
|
|
88
75
|
}
|
|
89
76
|
else if (config.wrote) {
|
|
90
|
-
console.log(` ${sym.ok()} Linked to ${c.bold(
|
|
77
|
+
console.log(` ${sym.ok()} Linked to ${c.bold(label)} ${c.dim(tildeify(config.path))}`);
|
|
91
78
|
}
|
|
92
79
|
else {
|
|
93
|
-
console.log(` ${sym.ok()} Already linked to ${c.bold(
|
|
80
|
+
console.log(` ${sym.ok()} Already linked to ${c.bold(label)} ${c.dim(tildeify(config.path))}`);
|
|
94
81
|
}
|
|
95
82
|
if (config.localDev) {
|
|
96
83
|
console.log(` ${c.dim("(local dev)")} MCP server command: ${c.dim(`${config.server.command} ${config.server.args.join(" ")}`)}`);
|
|
@@ -140,7 +127,7 @@ function printSetupResult(config, skills, doctor) {
|
|
|
140
127
|
printDoctorResult(doctor);
|
|
141
128
|
if (doctor.ok && skills.status !== "failed" && !config.dryRun) {
|
|
142
129
|
console.log("");
|
|
143
|
-
console.log(`${c.dim("Try it:")} open ${
|
|
130
|
+
console.log(`${c.dim("Try it:")} open ${label} and ask: ${c.bold("\"add a DirectionalLight3D and Camera3D to my scene\"")}`);
|
|
144
131
|
}
|
|
145
132
|
}
|
|
146
133
|
function parseInstalledSkills(stdout) {
|
|
@@ -8,6 +8,7 @@ import { writeSkillMarker } from "../../installer/version-check.js";
|
|
|
8
8
|
import { pruneRetiredSkills } from "../../installer/legacy-skills.js";
|
|
9
9
|
import { resolveInstallLocation, resolveSkillAgent, resolveSkillScope, } from "../../installer/skill-locations.js";
|
|
10
10
|
import { PACKAGE_ROOT } from "../../core/package-root.js";
|
|
11
|
+
import { agentLabel as tableAgentLabel, agentSpec, agentsSharingSkills, defaultPathContext, isSharedSkillsPath, legacyRuleFiles, legacySkillDirs, } from "../../installer/agent-table.js";
|
|
11
12
|
import { TOOLKIT_VERSION as cliVersion } from "../../core/version.js";
|
|
12
13
|
// Skill files live in library/skills/<slug>/ and are resolved through the
|
|
13
14
|
// generated registry (registry/generated/skills-registry.json).
|
|
@@ -52,32 +53,7 @@ function orDie(parse) {
|
|
|
52
53
|
}
|
|
53
54
|
}
|
|
54
55
|
function agentLabel(agent) {
|
|
55
|
-
|
|
56
|
-
case "claude-code":
|
|
57
|
-
return "Claude Code";
|
|
58
|
-
case "codex":
|
|
59
|
-
return "Codex";
|
|
60
|
-
case "cursor":
|
|
61
|
-
return "Cursor";
|
|
62
|
-
case "windsurf":
|
|
63
|
-
return "Devin Desktop (Windsurf)";
|
|
64
|
-
case "cline":
|
|
65
|
-
return "Cline";
|
|
66
|
-
case "roo-code":
|
|
67
|
-
return "Roo Code";
|
|
68
|
-
case "kilo-code":
|
|
69
|
-
return "Kilo Code";
|
|
70
|
-
case "gemini":
|
|
71
|
-
return "Gemini CLI";
|
|
72
|
-
case "github-copilot":
|
|
73
|
-
return "GitHub Copilot CLI";
|
|
74
|
-
case "vscode-copilot":
|
|
75
|
-
return "GitHub Copilot in VS Code";
|
|
76
|
-
case "opencode":
|
|
77
|
-
return "OpenCode";
|
|
78
|
-
case "summer":
|
|
79
|
-
return "Summer";
|
|
80
|
-
}
|
|
56
|
+
return agent === "summer" ? "Summer" : tableAgentLabel(agent);
|
|
81
57
|
}
|
|
82
58
|
function previewSkippedLine(count) {
|
|
83
59
|
return ` Skipped ${count} preview skill${count === 1 ? "" : "s"} (--stable-only).`;
|
|
@@ -219,11 +195,19 @@ function printInstallSummary(count, agent, scope, location) {
|
|
|
219
195
|
const label = agentLabel(agent);
|
|
220
196
|
const tildeified = tildeify(location.path);
|
|
221
197
|
console.log(`\n${count} skill${count === 1 ? "" : "s"} ready for ${label} (${scope} scope).`);
|
|
198
|
+
const reloadHint = agent === "summer" ? undefined : agentSpec(agent).skills?.reloadHint;
|
|
222
199
|
if (location.kind === "skill-dir") {
|
|
223
200
|
console.log(`${label} can read skills from ${tildeified}/<skill>/SKILL.md`);
|
|
224
|
-
if (
|
|
225
|
-
|
|
201
|
+
if (isSharedSkillsPath(location.path)) {
|
|
202
|
+
const others = agentsSharingSkills(scope, defaultPathContext())
|
|
203
|
+
.map((spec) => spec.label)
|
|
204
|
+
.filter((name) => name !== label);
|
|
205
|
+
if (others.length > 0) {
|
|
206
|
+
console.log(`This is the shared agentskills.io folder; ${others.join(", ")} read it too, so they are covered by this install.`);
|
|
207
|
+
}
|
|
226
208
|
}
|
|
209
|
+
if (reloadHint)
|
|
210
|
+
console.log(reloadHint);
|
|
227
211
|
}
|
|
228
212
|
else if (location.kind === "cursor-rule-dir") {
|
|
229
213
|
console.log(`Cursor rules are in ${tildeified}/summer-<skill>.mdc`);
|
|
@@ -248,17 +232,36 @@ export const skillsCommand = new Command("skills")
|
|
|
248
232
|
skillsCommand
|
|
249
233
|
.command("list")
|
|
250
234
|
.description("List available skills")
|
|
251
|
-
.
|
|
235
|
+
.option("--by-domain", "Group skills by their primary domain (same grouping as library/skills/README.md)")
|
|
236
|
+
.action((opts) => {
|
|
252
237
|
const skills = getBuiltinSkills();
|
|
253
238
|
if (skills.length === 0) {
|
|
254
239
|
console.log("No skills found.");
|
|
255
240
|
return;
|
|
256
241
|
}
|
|
257
|
-
|
|
258
|
-
for (const s of skills) {
|
|
242
|
+
const line = (s) => {
|
|
259
243
|
const badge = s.recommended ? "recommended" : "optional";
|
|
260
244
|
const tag = s.status === "preview" ? "[preview] " : "";
|
|
261
|
-
|
|
245
|
+
return ` ${s.name.padEnd(24)} ${badge.padEnd(11)} ${tag}${s.description}`;
|
|
246
|
+
};
|
|
247
|
+
if (opts.byDomain) {
|
|
248
|
+
const groups = new Map();
|
|
249
|
+
for (const s of skills) {
|
|
250
|
+
const primary = s.domains[0] ?? "uncategorised";
|
|
251
|
+
groups.set(primary, [...(groups.get(primary) ?? []), s]);
|
|
252
|
+
}
|
|
253
|
+
console.log(`${skills.length} skills by primary domain (full index: library/skills/README.md):`);
|
|
254
|
+
for (const domain of [...groups.keys()].sort()) {
|
|
255
|
+
const group = groups.get(domain);
|
|
256
|
+
console.log(`\n${domain} (${group.length})`);
|
|
257
|
+
for (const s of group)
|
|
258
|
+
console.log(line(s));
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
else {
|
|
262
|
+
console.log("Available public skills:\n");
|
|
263
|
+
for (const s of skills)
|
|
264
|
+
console.log(line(s));
|
|
262
265
|
}
|
|
263
266
|
const previewCount = skills.filter((s) => s.status === "preview").length;
|
|
264
267
|
if (previewCount > 0) {
|
|
@@ -307,6 +310,28 @@ skillsCommand
|
|
|
307
310
|
for (const pruned of pruneRetiredSkills(location.path, getSkillRegistry().map((entry) => entry.name))) {
|
|
308
311
|
console.log(` Removed ${pruned.name} -> ${pruned.path} (retired in 3.0.0)`);
|
|
309
312
|
}
|
|
313
|
+
// Agents that moved from generated rule files to SKILL.md skills in 3.1
|
|
314
|
+
// (Cursor, OpenCode): drop the rule files 3.0 wrote so the agent does not
|
|
315
|
+
// load both for the same slug. Only files with Summer's own naming go.
|
|
316
|
+
if (agent !== "summer" && !process.env.SUMMER_SKILLS_DIR) {
|
|
317
|
+
const names = skills.map((skill) => skill.name);
|
|
318
|
+
const legacy = legacyRuleFiles(agentSpec(agent), scope, defaultPathContext(), names) ?? [];
|
|
319
|
+
for (const file of legacy) {
|
|
320
|
+
if (!existsSync(file))
|
|
321
|
+
continue;
|
|
322
|
+
rmSync(file, { force: true });
|
|
323
|
+
console.log(` Removed ${tildeify(file)} (rule file from Summer 3.0; now a skill)`);
|
|
324
|
+
}
|
|
325
|
+
// 3.1.0 wrote skills into each agent's own folder; agents that read
|
|
326
|
+
// the shared ~/.agents/skills now install there. Drop Summer's copies
|
|
327
|
+
// (dirs with a SKILL.md and a library name) from the old folder.
|
|
328
|
+
for (const dir of legacySkillDirs(agentSpec(agent), scope, defaultPathContext(), names) ?? []) {
|
|
329
|
+
if (!existsSync(join(dir, "SKILL.md")))
|
|
330
|
+
continue;
|
|
331
|
+
rmSync(dir, { recursive: true, force: true });
|
|
332
|
+
console.log(` Removed ${tildeify(dir)} (moved to the shared skills folder)`);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
310
335
|
}
|
|
311
336
|
if (name && skills[0]?.status === "preview") {
|
|
312
337
|
console.log(` Note: ${name} is a preview skill — not yet exercised in-engine by the Summer team; its guidance says so.`);
|
|
@@ -96,6 +96,11 @@ export declare class EngineApiClient {
|
|
|
96
96
|
getEngineCapabilities(): EngineCapabilities | undefined;
|
|
97
97
|
/** Engine version string from the last health read, for skew messages. */
|
|
98
98
|
getEngineVersion(): string | undefined;
|
|
99
|
+
/** Absolute project directory: the engine's own report from the last health
|
|
100
|
+
* read (newer engines publish project_path), else the explicit --project
|
|
101
|
+
* selection. Undefined when neither is known. Used for the bounded
|
|
102
|
+
* res://.summer/shots/ folder the seeing tools keep on the local disk. */
|
|
103
|
+
getProjectRoot(): string | undefined;
|
|
99
104
|
/** The projectIdHash this session is bound to (undefined if none was reported
|
|
100
105
|
* at connect — e.g. no project open yet). */
|
|
101
106
|
getBoundProjectIdHash(): string | undefined;
|
|
@@ -168,11 +173,14 @@ export declare class EngineApiClient {
|
|
|
168
173
|
getSceneState(scenePath?: string, options?: {
|
|
169
174
|
depth?: number;
|
|
170
175
|
limit?: number;
|
|
176
|
+
root?: string;
|
|
171
177
|
}): Promise<unknown>;
|
|
172
178
|
getProjectState(prefix?: string): Promise<unknown>;
|
|
173
179
|
getDiagnostics(): Promise<unknown>;
|
|
174
180
|
inspectNode(path: string): Promise<unknown>;
|
|
175
|
-
|
|
181
|
+
/** A resource a node of the edited scene holds (state:resource takes
|
|
182
|
+
* nodePath + property; resource FILES go through the inspect-resource probe). */
|
|
183
|
+
inspectNodeResource(nodePath: string, property: string): Promise<unknown>;
|
|
176
184
|
getScriptErrors(path: string): Promise<unknown>;
|
|
177
185
|
play(scene?: string, determinism?: PlayDeterminism): Promise<unknown>;
|
|
178
186
|
stop(): Promise<unknown>;
|
package/dist/core/api-client.js
CHANGED
|
@@ -6,6 +6,7 @@ import { checkEngineHealth, discoverRegistryConnection, engineNotRunningError, e
|
|
|
6
6
|
import { asRecord, boolFrom, numberFrom, stringFrom } from "./util/json.js";
|
|
7
7
|
import { classifyOpsResponse, pollOpToTerminal, } from "./async-op-lifecycle.js";
|
|
8
8
|
import { pickPlayDeterminism } from "./capabilities/play-determinism.js";
|
|
9
|
+
import { honestSceneReceipt } from "./capabilities/engine-receipt.js";
|
|
9
10
|
function findSnapshotPayload(value) {
|
|
10
11
|
const record = asRecord(value);
|
|
11
12
|
if (!record)
|
|
@@ -180,6 +181,13 @@ export class EngineApiClient {
|
|
|
180
181
|
getEngineVersion() {
|
|
181
182
|
return this.lastHealth?.version;
|
|
182
183
|
}
|
|
184
|
+
/** Absolute project directory: the engine's own report from the last health
|
|
185
|
+
* read (newer engines publish project_path), else the explicit --project
|
|
186
|
+
* selection. Undefined when neither is known. Used for the bounded
|
|
187
|
+
* res://.summer/shots/ folder the seeing tools keep on the local disk. */
|
|
188
|
+
getProjectRoot() {
|
|
189
|
+
return this.lastHealth?.project_path ?? this.selection?.projectPath;
|
|
190
|
+
}
|
|
183
191
|
/** The projectIdHash this session is bound to (undefined if none was reported
|
|
184
192
|
* at connect — e.g. no project open yet). */
|
|
185
193
|
getBoundProjectIdHash() {
|
|
@@ -461,7 +469,9 @@ export class EngineApiClient {
|
|
|
461
469
|
// different project (identity_mismatch, atomic — before any op applies).
|
|
462
470
|
const merged = { ...(options ?? {}), ...this.identityOptions() };
|
|
463
471
|
const body = Object.keys(merged).length ? { ops, options: merged } : { ops };
|
|
464
|
-
|
|
472
|
+
// scenePersistence.persisted only means SaveScene ran; hand it out as
|
|
473
|
+
// `saved` (engine-receipt.ts honestSceneReceipt).
|
|
474
|
+
return honestSceneReceipt(await this._requestQueued("POST", "/api/ops", body, timeoutMs));
|
|
465
475
|
}
|
|
466
476
|
/**
|
|
467
477
|
* Mutation path for MCP file tools. Unlike legacy executeOps callers, this
|
|
@@ -480,13 +490,16 @@ export class EngineApiClient {
|
|
|
480
490
|
return this.request("GET", `/api/state/read-file?${query.toString()}`);
|
|
481
491
|
}
|
|
482
492
|
async getSceneState(scenePath, options) {
|
|
483
|
-
// depth/limit only take effect on targeted (scene=) reads: the engine
|
|
493
|
+
// depth/limit/root only take effect on targeted (scene=) reads: the engine
|
|
484
494
|
// routes those through the live command queue and forwards every query
|
|
485
495
|
// param into StateProvider::scene_state (tool_net_thread.cpp
|
|
486
496
|
// _parse_state_args). An UNtargeted read is answered from a pre-published
|
|
487
497
|
// snapshot built with the defaults (depth 2, limit 200) and its query
|
|
488
498
|
// params are ignored — callers who need depth/limit must pass scenePath
|
|
489
499
|
// (summer_get_scene_tree resolves the current scene path for this).
|
|
500
|
+
// `root` starts the walk at a scene-relative node path; a path the engine
|
|
501
|
+
// cannot resolve falls back to the scene root, so callers compare the
|
|
502
|
+
// returned data.path before trusting a rooted read.
|
|
490
503
|
const parts = [];
|
|
491
504
|
if (scenePath)
|
|
492
505
|
parts.push(`scene=${encodeURIComponent(scenePath)}`);
|
|
@@ -494,6 +507,8 @@ export class EngineApiClient {
|
|
|
494
507
|
parts.push(`depth=${options.depth}`);
|
|
495
508
|
if (options?.limit !== undefined)
|
|
496
509
|
parts.push(`limit=${options.limit}`);
|
|
510
|
+
if (options?.root !== undefined)
|
|
511
|
+
parts.push(`root=${encodeURIComponent(options.root)}`);
|
|
497
512
|
const query = parts.length ? `?${parts.join("&")}` : "";
|
|
498
513
|
return this.request("GET", `/api/state/scene${query}`);
|
|
499
514
|
}
|
|
@@ -513,8 +528,10 @@ export class EngineApiClient {
|
|
|
513
528
|
async inspectNode(path) {
|
|
514
529
|
return this.request("GET", `/api/state/inspector?path=${encodeURIComponent(path)}`);
|
|
515
530
|
}
|
|
516
|
-
|
|
517
|
-
|
|
531
|
+
/** A resource a node of the edited scene holds (state:resource takes
|
|
532
|
+
* nodePath + property; resource FILES go through the inspect-resource probe). */
|
|
533
|
+
async inspectNodeResource(nodePath, property) {
|
|
534
|
+
return this.request("GET", `/api/state/resource?nodePath=${encodeURIComponent(nodePath)}&property=${encodeURIComponent(property)}`);
|
|
518
535
|
}
|
|
519
536
|
async getScriptErrors(path) {
|
|
520
537
|
return this.request("GET", `/api/state/script-errors?path=${encodeURIComponent(path)}`);
|
|
@@ -19,6 +19,14 @@ export function buildAgentPlaybook(options = {}) {
|
|
|
19
19
|
"For lighting, mood, environment, or emissive materials, use summer_screenshot target:'scene' framing:'camera' — it renders through the scene's OWN camera with its REAL WorldEnvironment. The preset framings (iso/top/...) substitute a flat preview environment and CANNOT verify lighting.",
|
|
20
20
|
"When executing multiple batches, screenshot between them — catch the wrong turn at batch 2, not batch 7.",
|
|
21
21
|
"If something looks wrong in the screenshot or the diff, investigate and fix before proceeding. Do not stack more work on a broken base.",
|
|
22
|
+
"A game made from a planning board (the brief gives its project id): read the board with summer_get_board at the start of each build step and compare your screenshot against its images (palette, shapes and proportions, camera angle, composition); fix the biggest difference.",
|
|
23
|
+
],
|
|
24
|
+
// ------------------------------------------------------------------
|
|
25
|
+
// SEEING — judge a 3D environment the way a player and an artist do.
|
|
26
|
+
// ------------------------------------------------------------------
|
|
27
|
+
seeing: [
|
|
28
|
+
"Environment work ('make it beautiful', level dressing, lighting passes): bookmark hero views with summer_frame_shot (establishing / eye_level / low_angle / detail / corridor; walls, or a camera behind a one-sided wall, reject a pose; props frame it), then after every change one summer_shot_sheet of those bookmarks (compare_previous:true for previous / now / difference; only it or update_previous:true replaces a bookmark's baseline), summer_debug_views on the weakest shot (lighting, unshaded, normals, overdraw, wireframe) and summer_zoom (region or mark N) into each problem. summer_frame_nodes fits nodes with the REAL environment. Images come back inline, one grid per call; the verifying-scenes skill carries the loop and the beauty rubric. Preview tools.",
|
|
29
|
+
"Before calling a 3D scene done: summer_scene_audit (read-only, one call, at most 5 KB) lists what a camera may miss — see-through gaps, floor holes, floating or clipping props, facing look items, UV stretch, z-fighting, lights — sorted by severity with the node path, world position, evidence and next tool. Look at every error and look item up close (render:'sheet', or summer_frame_nodes / summer_zoom) and decide facings yourself; the audit never auto-fixes. Preview tool.",
|
|
22
30
|
],
|
|
23
31
|
// ------------------------------------------------------------------
|
|
24
32
|
// LIBRARY FEEDBACK — report how the library entries you used worked out.
|
|
@@ -80,6 +88,28 @@ export function buildAgentPlaybook(options = {}) {
|
|
|
80
88
|
},
|
|
81
89
|
},
|
|
82
90
|
// ------------------------------------------------------------------
|
|
91
|
+
// 3D PLACEMENT — question -> tool. These bounded spatial tools ship
|
|
92
|
+
// today; an agent that never hears of them falls back to hand math.
|
|
93
|
+
// ------------------------------------------------------------------
|
|
94
|
+
placement3d: {
|
|
95
|
+
first: "For any 3D placement (props, kit pieces, walls, ledges, alcoves), call summer_search_library and read skill/spatial-placement (and skill/world-building-3d) before placing. Observe first still applies: snapshot, then place, then verify.",
|
|
96
|
+
questionToTool: [
|
|
97
|
+
"'How big is this kit piece, where is its origin, which side is its back, where are its pipe ends?' -> summer_inspect_asset (measures the file without adding it to a scene). Measure every piece type before placing it; never guess facing.",
|
|
98
|
+
"'Place it at this pose' -> summer_instantiate_scene with position / rotation_degrees (one call per piece). Many pieces -> one summer_batch of InstantiateScene ops carrying position / rotation_degrees, with receipt:'summary'.",
|
|
99
|
+
"'Next module edge to edge, next storey on top' -> summer_place_adjacent. 'Mount it on the wall' -> summer_attach_to_surface (backAxis from summer_inspect_asset). 'Clamps every 0.45 m' -> summer_repeat_along. 'Pipe to pipe' -> summer_connect_ports.",
|
|
100
|
+
"'What surface is in front of this point?' -> summer_raycast. 'Gap or overlap between these two, is the facade front flush?' -> summer_measure.",
|
|
101
|
+
"'What is around it, which side is blocked, is it flush against the wall?' -> summer_starcast (read-only, 26 directional casts from one node's bounds: open|blocked per direction with distance and object, contact-or-overlap, grounded). Call it BEFORE and AFTER placing; pass directionSpace:'local' for rotated pieces, wall gaps and alcoves.",
|
|
102
|
+
"'Will it fit here?' -> summer_test_placement: ghost-test a candidate global pose for overlap and floor gap without moving anything. Use it before committing a pose in a tight or dense spot.",
|
|
103
|
+
"'Seat it on the floor, table or wall' -> summer_snap_to_surface: move along a ray to the first surface at a requested gap (default straight down).",
|
|
104
|
+
"'Line these up / space them evenly' -> summer_align_distribute_3d: align (min/center/max) or equal-space 2-16 pieces along one axis from their visible AABBs.",
|
|
105
|
+
"'Did exactly that change, and does it look right?' -> summer_world_snapshot before + summer_snapshot_diff after, then summer_screenshot.",
|
|
106
|
+
"'What is wrong with this scene, and where?' -> summer_scene_audit after each build stage (save first; it reads the saved file in a private copy, so the tab stays clean): see-through holes in facades, exposed band ends and seams, open duct or pipe ends, floor gaps, floating/sunken/clipping props, facing look items, UV stretch, z-fighting (with the axis to nudge), lights; every check works from geometry, engine data and materials, never names or kit metadata. At most 5 KB, sorted error/warn/look; page with offset, narrow with checks/root/min_severity, render:'sheet' frames the first 6. Frame every error and look item before calling the scene done; accept:[{key, reason}] the look items you judged fine so later audits hide them.",
|
|
107
|
+
"'Can the player get from A to B?' -> summer_navigation_probe (reachability on the scene's navigation map).",
|
|
108
|
+
],
|
|
109
|
+
evidence: "physics evidence comes from colliders; visual_aabb is a broad-phase fallback for mesh-only geometry. Read the evidence field before trusting a contact or a gap.",
|
|
110
|
+
status: "skill/spatial-placement, skill/world-building-3d and summer_starcast / summer_test_placement / summer_snap_to_surface / summer_align_distribute_3d / summer_navigation_probe / summer_world_snapshot / summer_snapshot_diff / summer_inspect_asset / summer_place_adjacent / summer_attach_to_surface / summer_repeat_along / summer_connect_ports / summer_raycast / summer_measure / summer_scene_audit are preview: verify their receipts with a screenshot. An engine build that predates an op answers engine_lacks_op naming the fallback.",
|
|
111
|
+
},
|
|
112
|
+
// ------------------------------------------------------------------
|
|
83
113
|
// PHYSICAL INVARIANTS — hold after EVERY placement/import.
|
|
84
114
|
// ------------------------------------------------------------------
|
|
85
115
|
physicalInvariants: [
|
|
@@ -96,6 +126,15 @@ export function buildAgentPlaybook(options = {}) {
|
|
|
96
126
|
"Engine calls are cheap; YOUR context is not: prefer summer_world_snapshot + summer_snapshot_diff (compact, capped, fingerprinted) over repeated full-tree dumps.",
|
|
97
127
|
],
|
|
98
128
|
// ------------------------------------------------------------------
|
|
129
|
+
// READ IN PARTS — a result too big for the host is a result you never see.
|
|
130
|
+
// ------------------------------------------------------------------
|
|
131
|
+
readingInParts: [
|
|
132
|
+
"summer_get_project_context is compact by default (project, scene path + sceneSummary, health summary, projectMemory, warnings). Add include:['scene_tree'] / ['capabilities'] / ['settings'] only when you need that block; `omitted` names what was left out.",
|
|
133
|
+
"summer_world_snapshot lists at most 200 nodes by default. Read one subtree with path_prefix ('House3', 'Lane2/Props'), narrow with classes and fields (['pos','aabb']), page with offset/next_offset; matched_counts counts the subtree's classes. counts and the snapshot_id diff baseline always cover the whole scene.",
|
|
134
|
+
"summer_inspect_node fields:['transform','global_transform','scene_file_path'] reads where a node is (locally and in the world) and which scene it instances in a few hundred bytes instead of about 5 KB.",
|
|
135
|
+
"Search, then read the part: summer_grep (regex over project files; context_lines, path, glob, max_results) finds the lines; summer_read_file then reads just that part — offset/limit for text (data.window.next_offset continues), json_path / keys / keys_only for JSON (e.g. json_path:'pieces', keys:['wall_*'] on a kit manifest).",
|
|
136
|
+
],
|
|
137
|
+
// ------------------------------------------------------------------
|
|
99
138
|
// Verification ladder (climb only as high as the change demands).
|
|
100
139
|
// ------------------------------------------------------------------
|
|
101
140
|
verificationLadder: {
|
|
@@ -156,6 +195,8 @@ export function buildAgentPlaybook(options = {}) {
|
|
|
156
195
|
"For live scene hierarchy and inspector changes, prefer scene tools. Guarded text writes support .tscn/.tres, and the engine schedules editor reloads after they land.",
|
|
157
196
|
"Write GDScript by default; use C# only if the project already uses it.",
|
|
158
197
|
"Never remove multiple top-level nodes unless the user explicitly requests destructive edits.",
|
|
198
|
+
"summer_snap_to_surface lifts a prop that is sunk into its support and settles it (receipt.recovery); when it still fails, read blocking and next_step in the failure instead of guessing a new position.",
|
|
199
|
+
"To swap one piece for another use summer_replace_node: it keeps parent, index, name, transform and added children, and proves the swap from the saved file. Trust persisted:true only; failure_reason not_persisted means the editor shows a change the file does not hold.",
|
|
159
200
|
"Never change priority: locked .summer memory, voice IDs, canon, or provider bindings without explicit user confirmation.",
|
|
160
201
|
],
|
|
161
202
|
liveEngineFlow: [
|
|
@@ -175,6 +216,11 @@ export function buildAgentPlaybook(options = {}) {
|
|
|
175
216
|
"SimulateInput (drive the RUNNING game — summer_play first): summer_batch ops:[{op:'SimulateInput', type:'action', action:'jump', pressed:true}], sent ALONE as the only op. failure_reason 'not_running' = start the game first; 'unsupported' = the running game build predates the handler — use RunVerification instead.",
|
|
176
217
|
"SINGLE-OP CONTRACT: the engine rejects any multi-op batch containing SaveScene, InstantiateScene, ReplaceNode, SimulateInput, ViewportSnapshot, GameSnapshot, GetRuntimeSceneTree, GetRuntimeNode, the runtime-control ops (SetRuntimeProp, CallRuntimeMethod, SpawnRuntimeScene, FreeRuntimeNode, RuntimeAnimation, RuntimeAnimationTree, GetRuntimeBones, GamePause, GameStep, GameSpeed, SimulateInputScript, InputRecordStart, InputRecordStop, InputReplay, GameProbe), Run*/Import* or Git* ops (failure_reason 'unsupported_transport', nothing executes). summer_batch splits these into sequential requests for you; when composing raw batches keep them as their own call anyway.",
|
|
177
218
|
"WriteFile and ReplaceText are rejected here by design — use summer_write_file / summer_replace_text so project identity, content guards and same-file ordering are enforced.",
|
|
219
|
+
"A raw ReplaceNode with scene is rejected here too: the engine op shows the new scene but saves the OLD scene reference. summer_replace_node does the swap with ops that persist and verifies the saved file (persisted:true, or failure_reason not_persisted).",
|
|
220
|
+
"A raw ConnectSignal is rejected here: the engine connects without CONNECT_PERSIST, so the saved scene never holds it. summer_connect_signal connects with the flag and verifies the [connection] line in the saved file.",
|
|
221
|
+
"ReparentNode in summer_batch keeps the moved node's subtree: the engine op re-owns only the moved node, so the tool re-owns each scene-owned descendant in place and verifies every moved node in the saved file (persisted:true / verified:true, or failure_reason not_persisted).",
|
|
222
|
+
"scenePersistence.saved only says the SaveScene ran. Trust verified:true, which a tool sets only after reading the saved file back.",
|
|
223
|
+
"Searching project files needs no raw op: summer_grep wraps the engine's Grep op and adds context lines and a result cap.",
|
|
178
224
|
"You do not need an engine op to run a shell command: your own host already has a shell. The engine binary that runs project scripts is at OS.get_executable_path() (on macOS, /Applications/Summer.app/Contents/MacOS/Summer); see the summer-cli headless-scripting skill.",
|
|
179
225
|
"These are runtime ops, not scene mutations — the batch undo group is a harmless no-op for them.",
|
|
180
226
|
],
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { type Severity } from "./args.js";
|
|
2
|
+
import type { AuditIssue } from "./judge.js";
|
|
3
|
+
export declare const ACCEPT_FILE: string;
|
|
4
|
+
export declare const ACCEPT_MAX_ENTRIES = 500;
|
|
5
|
+
export declare const ACCEPT_SCORE_CHANGE = 0.25;
|
|
6
|
+
export interface AcceptEntry {
|
|
7
|
+
key: string;
|
|
8
|
+
scene: string;
|
|
9
|
+
reason: string;
|
|
10
|
+
check: string;
|
|
11
|
+
severity: Severity;
|
|
12
|
+
score: number;
|
|
13
|
+
why: string;
|
|
14
|
+
at: string;
|
|
15
|
+
}
|
|
16
|
+
export declare function issueKey(issue: Pick<AuditIssue, "check" | "path" | "pos">): string;
|
|
17
|
+
export declare function validIssueKey(key: string): boolean;
|
|
18
|
+
/** The file's entries (the kernel echoes the parsed file as result.accept). */
|
|
19
|
+
export declare function parseAcceptFile(raw: unknown): AcceptEntry[];
|
|
20
|
+
/** Why an accepted item shows again, or null while it still holds. */
|
|
21
|
+
export declare function staleReason(entry: AcceptEntry, issue: AuditIssue): string | null;
|
|
22
|
+
export interface AcceptOutcome {
|
|
23
|
+
/** The new file content (null: nothing to write). */
|
|
24
|
+
entries: AcceptEntry[] | null;
|
|
25
|
+
added: string[];
|
|
26
|
+
refused: Array<{
|
|
27
|
+
key: string;
|
|
28
|
+
why: string;
|
|
29
|
+
}>;
|
|
30
|
+
}
|
|
31
|
+
/** Merge accept requests for THIS run's issues into the file's entries. */
|
|
32
|
+
export declare function mergeAccepts(existing: readonly AcceptEntry[], requests: ReadonlyArray<{
|
|
33
|
+
key: string;
|
|
34
|
+
reason: string;
|
|
35
|
+
}>, issues: readonly AuditIssue[], scene: string, now?: Date): AcceptOutcome;
|
|
36
|
+
export interface AcceptFilter {
|
|
37
|
+
shown: AuditIssue[];
|
|
38
|
+
accepted: Array<{
|
|
39
|
+
issue: AuditIssue;
|
|
40
|
+
entry: AcceptEntry;
|
|
41
|
+
}>;
|
|
42
|
+
stale: Array<{
|
|
43
|
+
issue: AuditIssue;
|
|
44
|
+
why: string;
|
|
45
|
+
}>;
|
|
46
|
+
}
|
|
47
|
+
/** Split issues into shown and accepted (stale entries show again). */
|
|
48
|
+
export declare function applyAccepts(issues: readonly AuditIssue[], entries: readonly AcceptEntry[], scene: string): AcceptFilter;
|
|
49
|
+
export declare class AcceptStoreError extends Error {
|
|
50
|
+
readonly reason: "no_project" | "unsafe_path";
|
|
51
|
+
constructor(reason: "no_project" | "unsafe_path", message: string);
|
|
52
|
+
}
|
|
53
|
+
/** Write the entries to <project>/.summer/audit-accept.json: refuses symlinks
|
|
54
|
+
* at the folder and the file, writes a temp file and renames it. */
|
|
55
|
+
export declare function writeAcceptFile(projectRoot: string | undefined, entries: readonly AcceptEntry[]): Promise<string>;
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Accepted audit items: res://.summer/audit-accept.json.
|
|
3
|
+
*
|
|
4
|
+
* Without it an agent re-judges the same look items (hidden contact faces,
|
|
5
|
+
* overlapping trim at an inside corner) on every audit. An agent that has
|
|
6
|
+
* looked at an item and judged it fine passes accept: [{key, reason}]; the
|
|
7
|
+
* MCP side writes the entry here (the kernel only reads it, and the audit
|
|
8
|
+
* writes nothing else), and later audits count the item but hide it until
|
|
9
|
+
* its evidence changes materially.
|
|
10
|
+
*
|
|
11
|
+
* - Key: check:path@x,y,z, the world position rounded to 0.1 m (node names
|
|
12
|
+
* never contain ":" or "@"). A moved piece is a new item.
|
|
13
|
+
* - Evidence: the severity and the issue's magnitude (score) when accepted.
|
|
14
|
+
* A higher severity, or a score that moves by more than 25% (and 0.005),
|
|
15
|
+
* makes the entry stale: the item shows again, marked accept_stale.
|
|
16
|
+
* - Errors cannot be accepted. Entries are per scene; the file keeps the
|
|
17
|
+
* newest 500.
|
|
18
|
+
*/
|
|
19
|
+
import { lstat, mkdir, rename, writeFile } from "node:fs/promises";
|
|
20
|
+
import { existsSync } from "node:fs";
|
|
21
|
+
import { isAbsolute, join, resolve } from "node:path";
|
|
22
|
+
import { randomBytes } from "node:crypto";
|
|
23
|
+
import { ISSUE_KEY_PATTERN } from "./args.js";
|
|
24
|
+
export const ACCEPT_FILE = join(".summer", "audit-accept.json");
|
|
25
|
+
export const ACCEPT_MAX_ENTRIES = 500;
|
|
26
|
+
export const ACCEPT_SCORE_CHANGE = 0.25;
|
|
27
|
+
const SEVERITY_RANK = { error: 0, warn: 1, look: 2 };
|
|
28
|
+
const tenth = (n) => (Math.round(n * 10) / 10 || 0).toFixed(1).replace(/\.0$/, "");
|
|
29
|
+
export function issueKey(issue) {
|
|
30
|
+
return `${issue.check}:${issue.path}@${issue.pos.map(tenth).join(",")}`;
|
|
31
|
+
}
|
|
32
|
+
export function validIssueKey(key) {
|
|
33
|
+
return ISSUE_KEY_PATTERN.test(key);
|
|
34
|
+
}
|
|
35
|
+
/** The file's entries (the kernel echoes the parsed file as result.accept). */
|
|
36
|
+
export function parseAcceptFile(raw) {
|
|
37
|
+
const doc = raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {};
|
|
38
|
+
const list = Array.isArray(doc.entries) ? doc.entries : [];
|
|
39
|
+
const out = [];
|
|
40
|
+
for (const e of list.slice(0, ACCEPT_MAX_ENTRIES * 2)) {
|
|
41
|
+
if (!e || typeof e !== "object")
|
|
42
|
+
continue;
|
|
43
|
+
const r = e;
|
|
44
|
+
const severity = r.severity === "warn" || r.severity === "look" ? r.severity : null;
|
|
45
|
+
if (typeof r.key !== "string" || !validIssueKey(r.key) || typeof r.scene !== "string" || !severity)
|
|
46
|
+
continue;
|
|
47
|
+
out.push({
|
|
48
|
+
key: r.key,
|
|
49
|
+
scene: r.scene,
|
|
50
|
+
reason: String(r.reason ?? "").slice(0, 200),
|
|
51
|
+
check: String(r.check ?? r.key.split(":")[0]),
|
|
52
|
+
severity,
|
|
53
|
+
score: typeof r.score === "number" && Number.isFinite(r.score) ? r.score : 0,
|
|
54
|
+
why: String(r.why ?? "").slice(0, 160),
|
|
55
|
+
at: String(r.at ?? ""),
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
return out;
|
|
59
|
+
}
|
|
60
|
+
/** Why an accepted item shows again, or null while it still holds. */
|
|
61
|
+
export function staleReason(entry, issue) {
|
|
62
|
+
if (SEVERITY_RANK[issue.severity] < SEVERITY_RANK[entry.severity])
|
|
63
|
+
return `severity rose from ${entry.severity} to ${issue.severity}`;
|
|
64
|
+
const delta = Math.abs(issue.score - entry.score);
|
|
65
|
+
if (delta > Math.max(ACCEPT_SCORE_CHANGE * Math.abs(entry.score), 0.005)) {
|
|
66
|
+
return `evidence changed: magnitude ${Math.round(entry.score * 1000) / 1000} -> ${Math.round(issue.score * 1000) / 1000}`;
|
|
67
|
+
}
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
/** Merge accept requests for THIS run's issues into the file's entries. */
|
|
71
|
+
export function mergeAccepts(existing, requests, issues, scene, now = new Date()) {
|
|
72
|
+
if (!requests.length)
|
|
73
|
+
return { entries: null, added: [], refused: [] };
|
|
74
|
+
const byKey = new Map(issues.map((i) => [issueKey(i), i]));
|
|
75
|
+
const added = [];
|
|
76
|
+
const refused = [];
|
|
77
|
+
const fresh = [];
|
|
78
|
+
for (const req of requests) {
|
|
79
|
+
const issue = byKey.get(req.key);
|
|
80
|
+
if (!issue) {
|
|
81
|
+
refused.push({ key: req.key, why: "no issue with this key in this audit (keys change when a piece moves 5 cm or more)" });
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
if (issue.severity === "error") {
|
|
85
|
+
refused.push({ key: req.key, why: "errors cannot be accepted: fix it" });
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
fresh.push({ key: req.key, scene, reason: req.reason.trim().slice(0, 200), check: issue.check, severity: issue.severity, score: issue.score, why: issue.why.slice(0, 160), at: now.toISOString() });
|
|
89
|
+
added.push(req.key);
|
|
90
|
+
}
|
|
91
|
+
if (!fresh.length)
|
|
92
|
+
return { entries: null, added, refused };
|
|
93
|
+
const keep = existing.filter((e) => !(e.scene === scene && fresh.some((f) => f.key === e.key)));
|
|
94
|
+
const entries = [...keep, ...fresh].slice(-ACCEPT_MAX_ENTRIES);
|
|
95
|
+
return { entries, added, refused };
|
|
96
|
+
}
|
|
97
|
+
/** Split issues into shown and accepted (stale entries show again). */
|
|
98
|
+
export function applyAccepts(issues, entries, scene) {
|
|
99
|
+
const mine = new Map(entries.filter((e) => e.scene === scene).map((e) => [e.key, e]));
|
|
100
|
+
const shown = [];
|
|
101
|
+
const accepted = [];
|
|
102
|
+
const stale = [];
|
|
103
|
+
for (const issue of issues) {
|
|
104
|
+
const entry = mine.get(issueKey(issue));
|
|
105
|
+
if (!entry || issue.severity === "error") {
|
|
106
|
+
shown.push(issue);
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
const why = staleReason(entry, issue);
|
|
110
|
+
if (why) {
|
|
111
|
+
stale.push({ issue, why });
|
|
112
|
+
shown.push(issue);
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
accepted.push({ issue, entry });
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return { shown, accepted, stale };
|
|
119
|
+
}
|
|
120
|
+
export class AcceptStoreError extends Error {
|
|
121
|
+
reason;
|
|
122
|
+
constructor(reason, message) {
|
|
123
|
+
super(message);
|
|
124
|
+
this.reason = reason;
|
|
125
|
+
this.name = "AcceptStoreError";
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
/** Write the entries to <project>/.summer/audit-accept.json: refuses symlinks
|
|
129
|
+
* at the folder and the file, writes a temp file and renames it. */
|
|
130
|
+
export async function writeAcceptFile(projectRoot, entries) {
|
|
131
|
+
if (!projectRoot || !isAbsolute(projectRoot) || !existsSync(join(projectRoot, "project.godot"))) {
|
|
132
|
+
throw new AcceptStoreError("no_project", "The project folder is not known to this session (no project.godot), so accepted items cannot be saved.");
|
|
133
|
+
}
|
|
134
|
+
const root = resolve(projectRoot);
|
|
135
|
+
const dir = join(root, ".summer");
|
|
136
|
+
await mkdir(dir, { recursive: true });
|
|
137
|
+
const dirInfo = await lstat(dir);
|
|
138
|
+
if (dirInfo.isSymbolicLink() || !dirInfo.isDirectory())
|
|
139
|
+
throw new AcceptStoreError("unsafe_path", `${dir} is not a real folder.`);
|
|
140
|
+
const file = join(root, ACCEPT_FILE);
|
|
141
|
+
if (existsSync(file) && (await lstat(file)).isSymbolicLink())
|
|
142
|
+
throw new AcceptStoreError("unsafe_path", `${file} is a symlink; refusing to write through it.`);
|
|
143
|
+
const tmp = `${file}.${randomBytes(6).toString("hex")}.tmp`;
|
|
144
|
+
await writeFile(tmp, JSON.stringify({ version: 1, note: "summer_scene_audit accepted items (written by accept:[{key, reason}])", entries }, null, 1));
|
|
145
|
+
await rename(tmp, file);
|
|
146
|
+
return file;
|
|
147
|
+
}
|