summer-engine 2.3.0 → 2.6.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 +24 -8
- package/.codex-plugin/plugin.json +19 -8
- package/.cursor-plugin/plugin.json +18 -7
- package/.factory-plugin/plugin.json +3 -3
- package/.opencode/INSTALL.md +1 -1
- package/AGENTS.md +6 -4
- package/CHANGELOG.md +46 -7
- package/CLAUDE.md +2 -2
- package/GEMINI.md +5 -6
- package/README.md +116 -109
- package/_persona/summer/SKILL.md +5 -6
- package/commands/gameskill.md +103 -0
- package/dist/bin/summer.js +17 -4
- package/dist/commands/cloud.d.ts +2 -0
- package/dist/commands/cloud.js +80 -0
- package/dist/commands/create.js +2 -0
- package/dist/commands/doctor.js +90 -1
- package/dist/commands/install.d.ts +17 -0
- package/dist/commands/install.js +63 -4
- package/dist/commands/login.js +4 -1
- package/dist/commands/logout.js +1 -1
- package/dist/commands/memory.d.ts +14 -0
- package/dist/commands/memory.js +196 -0
- package/dist/commands/open.js +1 -1
- package/dist/commands/plan.d.ts +2 -0
- package/dist/commands/plan.js +60 -0
- package/dist/commands/run.js +132 -35
- package/dist/commands/setup.js +8 -2
- package/dist/commands/skills.js +90 -6
- package/dist/commands/status.js +3 -0
- package/dist/lib/agent-config.d.ts +2 -2
- package/dist/lib/agent-config.js +134 -7
- package/dist/lib/api-client.d.ts +13 -0
- package/dist/lib/api-client.js +63 -26
- package/dist/lib/async-op-lifecycle.d.ts +60 -0
- package/dist/lib/async-op-lifecycle.js +83 -0
- package/dist/lib/auth.d.ts +2 -0
- package/dist/lib/auth.js +13 -0
- package/dist/lib/cloud/api.d.ts +79 -0
- package/dist/lib/cloud/api.js +107 -0
- package/dist/lib/cloud/apply.d.ts +32 -0
- package/dist/lib/cloud/apply.js +294 -0
- package/dist/lib/cloud/checkpoint.d.ts +26 -0
- package/dist/lib/cloud/checkpoint.js +142 -0
- package/dist/lib/cloud/conflicts.d.ts +55 -0
- package/dist/lib/cloud/conflicts.js +131 -0
- package/dist/lib/cloud/containment.d.ts +8 -0
- package/dist/lib/cloud/containment.js +52 -0
- package/dist/lib/cloud/diff.d.ts +39 -0
- package/dist/lib/cloud/diff.js +138 -0
- package/dist/lib/cloud/engine-bridge.d.ts +21 -0
- package/dist/lib/cloud/engine-bridge.js +105 -0
- package/dist/lib/cloud/hash-cache.d.ts +23 -0
- package/dist/lib/cloud/hash-cache.js +44 -0
- package/dist/lib/cloud/hash.d.ts +10 -0
- package/dist/lib/cloud/hash.js +111 -0
- package/dist/lib/cloud/http.d.ts +17 -0
- package/dist/lib/cloud/http.js +47 -0
- package/dist/lib/cloud/lock-path.d.ts +1 -0
- package/dist/lib/cloud/lock-path.js +5 -0
- package/dist/lib/cloud/lock.d.ts +14 -0
- package/dist/lib/cloud/lock.js +143 -0
- package/dist/lib/cloud/manifest.d.ts +6 -0
- package/dist/lib/cloud/manifest.js +41 -0
- package/dist/lib/cloud/paths.d.ts +20 -0
- package/dist/lib/cloud/paths.js +90 -0
- package/dist/lib/cloud/project-godot-merge.d.ts +32 -0
- package/dist/lib/cloud/project-godot-merge.js +185 -0
- package/dist/lib/cloud/rules.d.ts +39 -0
- package/dist/lib/cloud/rules.js +159 -0
- package/dist/lib/cloud/sync.d.ts +21 -0
- package/dist/lib/cloud/sync.js +518 -0
- package/dist/lib/cloud/transfer.d.ts +23 -0
- package/dist/lib/cloud/transfer.js +184 -0
- package/dist/lib/cloud/types.d.ts +62 -0
- package/dist/lib/cloud/validate-path.d.ts +23 -0
- package/dist/lib/cloud/validate-path.js +103 -0
- package/dist/lib/engine.d.ts +6 -0
- package/dist/lib/engine.js +36 -1
- package/dist/lib/game-task-plan.d.ts +42 -0
- package/dist/lib/game-task-plan.js +376 -0
- package/dist/lib/project-memory.d.ts +33 -0
- package/dist/lib/project-memory.js +220 -0
- package/dist/lib/skills-registry.d.ts +134 -61
- package/dist/lib/skills-registry.js +102 -4
- package/dist/lib/version-check.d.ts +106 -0
- package/dist/lib/version-check.js +338 -0
- package/dist/mcp/server.d.ts +2 -0
- package/dist/mcp/server.js +83 -0
- package/dist/mcp/tools/asset-tools.js +265 -45
- package/dist/mcp/tools/cloud-tools.d.ts +2 -0
- package/dist/mcp/tools/cloud-tools.js +42 -0
- package/dist/mcp/tools/debug-tools.js +32 -2
- package/dist/mcp/tools/generate-tools.js +101 -13
- package/dist/mcp/tools/project-tools.js +76 -21
- package/dist/mcp/tools/with-engine.d.ts +14 -0
- package/dist/mcp/tools/with-engine.js +52 -7
- package/gemini-extension.json +3 -3
- package/hooks/pre-commit-doctor.sh +0 -0
- package/hooks/run-hook.cmd +0 -0
- package/hooks/session-start.sh +0 -0
- package/package.json +20 -7
- package/skills/2d-assets/character-portrait/SKILL.md +1 -1
- package/skills/2d-assets/concept-art/SKILL.md +1 -1
- package/skills/2d-assets/create-asset-sheet/SKILL.md +163 -0
- package/skills/2d-assets/instantiate-asset-pack/SKILL.md +245 -0
- package/skills/2d-assets/pixel-art/SKILL.md +1 -1
- package/skills/2d-assets/skybox-panorama/SKILL.md +1 -1
- package/skills/2d-assets/sprite-sheet/SKILL.md +1 -1
- package/skills/2d-assets/tileable-texture/SKILL.md +1 -1
- package/skills/2d-assets/ui-graphics/SKILL.md +1 -1
- package/skills/2d-assets/use-widget-asset/SKILL.md +217 -0
- package/skills/3d-assets/character-model/SKILL.md +28 -6
- package/skills/3d-assets/environment-kit/SKILL.md +7 -2
- package/skills/3d-assets/organic-model/SKILL.md +5 -4
- package/skills/3d-assets/prop-model/SKILL.md +17 -9
- package/skills/3d-assets/vehicle-model/SKILL.md +5 -4
- package/skills/README.md +37 -30
- package/skills/ai-and-npcs/design-npc/SKILL.md +6 -6
- package/skills/animation/animation-tree/SKILL.md +4 -2
- package/skills/animation/facial-and-lipsync/SKILL.md +1 -1
- package/skills/animation/generate-motion/SKILL.md +26 -5
- package/skills/animation/procedural-animation/SKILL.md +2 -2
- package/skills/asset-pipeline/asset-strategy/SKILL.md +3 -2
- package/skills/audio/adaptive-music/SKILL.md +1 -1
- package/skills/audio/audio-direction/SKILL.md +5 -5
- package/skills/audio/sound-effect/SKILL.md +2 -2
- package/skills/audio/voice-line/SKILL.md +25 -3
- package/skills/character-controllers/fps-controller/SKILL.md +5 -5
- package/skills/debugging/debug/SKILL.md +39 -1
- package/skills/deployment/export-and-ship/SKILL.md +4 -4
- package/skills/gameplay-mechanics/auto-fire-targeting/SKILL.md +170 -0
- package/skills/gameplay-mechanics/design-mechanic/SKILL.md +8 -8
- package/skills/level-design/design-level/SKILL.md +5 -5
- package/skills/level-design/scene-to-level/SKILL.md +125 -0
- package/skills/multiplayer-and-networking/host-authoritative-state/SKILL.md +4 -4
- package/skills/multiplayer-and-networking/peer-to-peer-multiplayer/SKILL.md +4 -4
- package/skills/multiplayer-and-networking/setup-multiplayer/SKILL.md +7 -7
- package/skills/performance/tune-performance/SKILL.md +5 -5
- package/skills/rendering-and-lighting/3d-lighting/SKILL.md +1 -1
- package/skills/rendering-and-lighting/art-direction/SKILL.md +5 -5
- package/skills/scene-and-project/brainstorm-game/SKILL.md +4 -4
- package/skills/scene-and-project/play/SKILL.md +1 -1
- package/skills/scene-and-project/scene-composition/SKILL.md +30 -1
- package/skills/scripting-patterns/gdscript-patterns/SKILL.md +53 -0
- package/skills/ui-and-ux/ui-basics/SKILL.md +1 -1
- package/skills/video/animated-loop/SKILL.md +1 -1
- package/skills/video/cinematic-cutscene/SKILL.md +1 -1
- package/skills/video/trailer-shot/SKILL.md +1 -1
- package/skills/visual-effects/game-feel/SKILL.md +6 -6
- package/skills/workflow/brainstorming/SKILL.md +164 -0
- package/skills/workflow/brainstorming/scripts/frame-template.html +214 -0
- package/skills/workflow/brainstorming/scripts/helper.js +88 -0
- package/skills/workflow/brainstorming/scripts/server.cjs +354 -0
- package/skills/workflow/brainstorming/scripts/start-server.sh +148 -0
- package/skills/workflow/brainstorming/scripts/stop-server.sh +56 -0
- package/skills/workflow/brainstorming/spec-document-reviewer-prompt.md +49 -0
- package/skills/workflow/brainstorming/visual-companion.md +287 -0
- package/skills/workflow/debugging-game-feel/SKILL.md +174 -0
- package/skills/workflow/diagnosing-perf-regressions/SKILL.md +190 -0
- package/skills/workflow/dispatching-parallel-agents/SKILL.md +182 -0
- package/skills/workflow/gameskill/SKILL.md +111 -0
- package/skills/workflow/investigating-bugs/CREATION-LOG.md +119 -0
- package/skills/workflow/investigating-bugs/SKILL.md +296 -0
- package/skills/workflow/investigating-bugs/condition-based-waiting-example.ts +158 -0
- package/skills/workflow/investigating-bugs/condition-based-waiting.md +115 -0
- package/skills/workflow/investigating-bugs/defense-in-depth.md +122 -0
- package/skills/workflow/investigating-bugs/find-polluter.sh +63 -0
- package/skills/workflow/investigating-bugs/root-cause-tracing.md +169 -0
- package/skills/workflow/investigating-bugs/test-academic.md +14 -0
- package/skills/workflow/investigating-bugs/test-pressure-1.md +58 -0
- package/skills/workflow/investigating-bugs/test-pressure-2.md +68 -0
- package/skills/workflow/investigating-bugs/test-pressure-3.md +69 -0
- package/skills/workflow/mcpupdate/SKILL.md +134 -0
- package/skills/workflow/playtesting-a-feature/SKILL.md +173 -0
- package/skills/{_meta → workflow}/skill-create/SKILL.md +32 -22
- package/skills/{_meta → workflow}/skill-improve/SKILL.md +9 -10
- package/skills/{_meta → workflow}/skill-test/SKILL.md +12 -12
- package/skills/{_meta → workflow}/using-summer/SKILL.md +5 -2
- package/skills/workflow/verification-before-completion/SKILL.md +139 -0
- package/skills/workflow/writing-plans/SKILL.md +152 -0
- package/skills/workflow/writing-plans/plan-document-reviewer-prompt.md +49 -0
- package/skills/workflow/writing-skills/SKILL.md +655 -0
- package/skills/workflow/writing-skills/anthropic-best-practices.md +1150 -0
- package/skills/workflow/writing-skills/examples/CLAUDE_MD_TESTING.md +189 -0
- package/skills/workflow/writing-skills/graphviz-conventions.dot +172 -0
- package/skills/workflow/writing-skills/persuasion-principles.md +187 -0
- package/skills/workflow/writing-skills/render-graphs.js +168 -0
- package/skills/workflow/writing-skills/testing-skills-with-subagents.md +384 -0
- package/dist/commands/assets.d.ts +0 -2
- package/dist/commands/assets.js +0 -189
- package/dist/commands/debug.d.ts +0 -2
- package/dist/commands/debug.js +0 -127
- package/dist/commands/doctor.test.js +0 -29
- package/dist/commands/project.d.ts +0 -2
- package/dist/commands/project.js +0 -170
- package/dist/commands/scene.d.ts +0 -2
- package/dist/commands/scene.js +0 -290
- package/dist/lib/agent-config.test.d.ts +0 -1
- package/dist/lib/agent-config.test.js +0 -80
- package/dist/lib/format.test.d.ts +0 -1
- package/dist/lib/format.test.js +0 -36
- package/dist/lib/plugin-manifests.test.d.ts +0 -1
- package/dist/lib/plugin-manifests.test.js +0 -134
- package/dist/lib/with-engine.d.ts +0 -14
- package/dist/lib/with-engine.js +0 -109
- package/skills/_shared/collaborative-protocol.md +0 -50
- package/skills/_shared/gd-style.md +0 -121
- package/skills/_shared/godot-version.md +0 -32
- package/skills/_shared/mcp-tools-reference.md +0 -133
- package/skills/_shared/summer-folder.md +0 -44
- package/skills/_shared/template-registry.md +0 -40
- package/skills/_tests/runner.md +0 -90
- package/skills/_tests/specs/3d-lighting.md +0 -19
- package/skills/_tests/specs/art-direction.md +0 -115
- package/skills/_tests/specs/asset-strategy.md +0 -19
- package/skills/_tests/specs/audio-direction.md +0 -123
- package/skills/_tests/specs/brainstorm-game.md +0 -99
- package/skills/_tests/specs/debug.md +0 -94
- package/skills/_tests/specs/design-level.md +0 -113
- package/skills/_tests/specs/design-mechanic.md +0 -112
- package/skills/_tests/specs/design-npc.md +0 -143
- package/skills/_tests/specs/export-and-ship.md +0 -114
- package/skills/_tests/specs/fps-controller.md +0 -113
- package/skills/_tests/specs/gdscript-patterns.md +0 -19
- package/skills/_tests/specs/host-authoritative-state.md +0 -104
- package/skills/_tests/specs/make-game.md +0 -19
- package/skills/_tests/specs/peer-to-peer-multiplayer.md +0 -99
- package/skills/_tests/specs/play.md +0 -88
- package/skills/_tests/specs/scene-composition.md +0 -19
- package/skills/_tests/specs/setup-multiplayer.md +0 -106
- package/skills/_tests/specs/tune-performance.md +0 -104
- package/skills/_tests/specs/ui-basics.md +0 -19
- package/skills/_tests/specs/vfx.md +0 -116
- package/skills/catalog.yaml +0 -991
- /package/dist/{commands/doctor.test.d.ts → lib/cloud/types.js} +0 -0
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
# Visual Companion Guide
|
|
2
|
+
|
|
3
|
+
Browser-based visual brainstorming companion for showing mockups, diagrams, and options.
|
|
4
|
+
|
|
5
|
+
## When to Use
|
|
6
|
+
|
|
7
|
+
Decide per-question, not per-session. The test: **would the user understand this better by seeing it than reading it?**
|
|
8
|
+
|
|
9
|
+
**Use the browser** when the content itself is visual:
|
|
10
|
+
|
|
11
|
+
- **UI mockups** — wireframes, layouts, navigation structures, component designs
|
|
12
|
+
- **Architecture diagrams** — system components, data flow, relationship maps
|
|
13
|
+
- **Side-by-side visual comparisons** — comparing two layouts, two color schemes, two design directions
|
|
14
|
+
- **Design polish** — when the question is about look and feel, spacing, visual hierarchy
|
|
15
|
+
- **Spatial relationships** — state machines, flowcharts, entity relationships rendered as diagrams
|
|
16
|
+
|
|
17
|
+
**Use the terminal** when the content is text or tabular:
|
|
18
|
+
|
|
19
|
+
- **Requirements and scope questions** — "what does X mean?", "which features are in scope?"
|
|
20
|
+
- **Conceptual A/B/C choices** — picking between approaches described in words
|
|
21
|
+
- **Tradeoff lists** — pros/cons, comparison tables
|
|
22
|
+
- **Technical decisions** — API design, data modeling, architectural approach selection
|
|
23
|
+
- **Clarifying questions** — anything where the answer is words, not a visual preference
|
|
24
|
+
|
|
25
|
+
A question *about* a UI topic is not automatically a visual question. "What kind of wizard do you want?" is conceptual — use the terminal. "Which of these wizard layouts feels right?" is visual — use the browser.
|
|
26
|
+
|
|
27
|
+
## How It Works
|
|
28
|
+
|
|
29
|
+
The server watches a directory for HTML files and serves the newest one to the browser. You write HTML content to `screen_dir`, the user sees it in their browser and can click to select options. Selections are recorded to `state_dir/events` that you read on your next turn.
|
|
30
|
+
|
|
31
|
+
**Content fragments vs full documents:** If your HTML file starts with `<!DOCTYPE` or `<html`, the server serves it as-is (just injects the helper script). Otherwise, the server automatically wraps your content in the frame template — adding the header, CSS theme, selection indicator, and all interactive infrastructure. **Write content fragments by default.** Only write full documents when you need complete control over the page.
|
|
32
|
+
|
|
33
|
+
## Starting a Session
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
# Start server with persistence (mockups saved to project)
|
|
37
|
+
scripts/start-server.sh --project-dir /path/to/project
|
|
38
|
+
|
|
39
|
+
# Returns: {"type":"server-started","port":52341,"url":"http://localhost:52341",
|
|
40
|
+
# "screen_dir":"/path/to/project/.superpowers/brainstorm/12345-1706000000/content",
|
|
41
|
+
# "state_dir":"/path/to/project/.superpowers/brainstorm/12345-1706000000/state"}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Save `screen_dir` and `state_dir` from the response. Tell user to open the URL.
|
|
45
|
+
|
|
46
|
+
**Finding connection info:** The server writes its startup JSON to `$STATE_DIR/server-info`. If you launched the server in the background and didn't capture stdout, read that file to get the URL and port. When using `--project-dir`, check `<project>/.superpowers/brainstorm/` for the session directory.
|
|
47
|
+
|
|
48
|
+
**Note:** Pass the project root as `--project-dir` so mockups persist in `.superpowers/brainstorm/` and survive server restarts. Without it, files go to `/tmp` and get cleaned up. Remind the user to add `.superpowers/` to `.gitignore` if it's not already there.
|
|
49
|
+
|
|
50
|
+
**Launching the server by platform:**
|
|
51
|
+
|
|
52
|
+
**Claude Code (macOS / Linux):**
|
|
53
|
+
```bash
|
|
54
|
+
# Default mode works — the script backgrounds the server itself
|
|
55
|
+
scripts/start-server.sh --project-dir /path/to/project
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
**Claude Code (Windows):**
|
|
59
|
+
```bash
|
|
60
|
+
# Windows auto-detects and uses foreground mode, which blocks the tool call.
|
|
61
|
+
# Use run_in_background: true on the Bash tool call so the server survives
|
|
62
|
+
# across conversation turns.
|
|
63
|
+
scripts/start-server.sh --project-dir /path/to/project
|
|
64
|
+
```
|
|
65
|
+
When calling this via the Bash tool, set `run_in_background: true`. Then read `$STATE_DIR/server-info` on the next turn to get the URL and port.
|
|
66
|
+
|
|
67
|
+
**Codex:**
|
|
68
|
+
```bash
|
|
69
|
+
# Codex reaps background processes. The script auto-detects CODEX_CI and
|
|
70
|
+
# switches to foreground mode. Run it normally — no extra flags needed.
|
|
71
|
+
scripts/start-server.sh --project-dir /path/to/project
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
**Gemini CLI:**
|
|
75
|
+
```bash
|
|
76
|
+
# Use --foreground and set is_background: true on your shell tool call
|
|
77
|
+
# so the process survives across turns
|
|
78
|
+
scripts/start-server.sh --project-dir /path/to/project --foreground
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
**Other environments:** The server must keep running in the background across conversation turns. If your environment reaps detached processes, use `--foreground` and launch the command with your platform's background execution mechanism.
|
|
82
|
+
|
|
83
|
+
If the URL is unreachable from your browser (common in remote/containerized setups), bind a non-loopback host:
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
scripts/start-server.sh \
|
|
87
|
+
--project-dir /path/to/project \
|
|
88
|
+
--host 0.0.0.0 \
|
|
89
|
+
--url-host localhost
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Use `--url-host` to control what hostname is printed in the returned URL JSON.
|
|
93
|
+
|
|
94
|
+
## The Loop
|
|
95
|
+
|
|
96
|
+
1. **Check server is alive**, then **write HTML** to a new file in `screen_dir`:
|
|
97
|
+
- Before each write, check that `$STATE_DIR/server-info` exists. If it doesn't (or `$STATE_DIR/server-stopped` exists), the server has shut down — restart it with `start-server.sh` before continuing. The server auto-exits after 30 minutes of inactivity.
|
|
98
|
+
- Use semantic filenames: `platform.html`, `visual-style.html`, `layout.html`
|
|
99
|
+
- **Never reuse filenames** — each screen gets a fresh file
|
|
100
|
+
- Use Write tool — **never use cat/heredoc** (dumps noise into terminal)
|
|
101
|
+
- Server automatically serves the newest file
|
|
102
|
+
|
|
103
|
+
2. **Tell user what to expect and end your turn:**
|
|
104
|
+
- Remind them of the URL (every step, not just first)
|
|
105
|
+
- Give a brief text summary of what's on screen (e.g., "Showing 3 layout options for the homepage")
|
|
106
|
+
- Ask them to respond in the terminal: "Take a look and let me know what you think. Click to select an option if you'd like."
|
|
107
|
+
|
|
108
|
+
3. **On your next turn** — after the user responds in the terminal:
|
|
109
|
+
- Read `$STATE_DIR/events` if it exists — this contains the user's browser interactions (clicks, selections) as JSON lines
|
|
110
|
+
- Merge with the user's terminal text to get the full picture
|
|
111
|
+
- The terminal message is the primary feedback; `state_dir/events` provides structured interaction data
|
|
112
|
+
|
|
113
|
+
4. **Iterate or advance** — if feedback changes current screen, write a new file (e.g., `layout-v2.html`). Only move to the next question when the current step is validated.
|
|
114
|
+
|
|
115
|
+
5. **Unload when returning to terminal** — when the next step doesn't need the browser (e.g., a clarifying question, a tradeoff discussion), push a waiting screen to clear the stale content:
|
|
116
|
+
|
|
117
|
+
```html
|
|
118
|
+
<!-- filename: waiting.html (or waiting-2.html, etc.) -->
|
|
119
|
+
<div style="display:flex;align-items:center;justify-content:center;min-height:60vh">
|
|
120
|
+
<p class="subtitle">Continuing in terminal...</p>
|
|
121
|
+
</div>
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
This prevents the user from staring at a resolved choice while the conversation has moved on. When the next visual question comes up, push a new content file as usual.
|
|
125
|
+
|
|
126
|
+
6. Repeat until done.
|
|
127
|
+
|
|
128
|
+
## Writing Content Fragments
|
|
129
|
+
|
|
130
|
+
Write just the content that goes inside the page. The server wraps it in the frame template automatically (header, theme CSS, selection indicator, and all interactive infrastructure).
|
|
131
|
+
|
|
132
|
+
**Minimal example:**
|
|
133
|
+
|
|
134
|
+
```html
|
|
135
|
+
<h2>Which layout works better?</h2>
|
|
136
|
+
<p class="subtitle">Consider readability and visual hierarchy</p>
|
|
137
|
+
|
|
138
|
+
<div class="options">
|
|
139
|
+
<div class="option" data-choice="a" onclick="toggleSelect(this)">
|
|
140
|
+
<div class="letter">A</div>
|
|
141
|
+
<div class="content">
|
|
142
|
+
<h3>Single Column</h3>
|
|
143
|
+
<p>Clean, focused reading experience</p>
|
|
144
|
+
</div>
|
|
145
|
+
</div>
|
|
146
|
+
<div class="option" data-choice="b" onclick="toggleSelect(this)">
|
|
147
|
+
<div class="letter">B</div>
|
|
148
|
+
<div class="content">
|
|
149
|
+
<h3>Two Column</h3>
|
|
150
|
+
<p>Sidebar navigation with main content</p>
|
|
151
|
+
</div>
|
|
152
|
+
</div>
|
|
153
|
+
</div>
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
That's it. No `<html>`, no CSS, no `<script>` tags needed. The server provides all of that.
|
|
157
|
+
|
|
158
|
+
## CSS Classes Available
|
|
159
|
+
|
|
160
|
+
The frame template provides these CSS classes for your content:
|
|
161
|
+
|
|
162
|
+
### Options (A/B/C choices)
|
|
163
|
+
|
|
164
|
+
```html
|
|
165
|
+
<div class="options">
|
|
166
|
+
<div class="option" data-choice="a" onclick="toggleSelect(this)">
|
|
167
|
+
<div class="letter">A</div>
|
|
168
|
+
<div class="content">
|
|
169
|
+
<h3>Title</h3>
|
|
170
|
+
<p>Description</p>
|
|
171
|
+
</div>
|
|
172
|
+
</div>
|
|
173
|
+
</div>
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
**Multi-select:** Add `data-multiselect` to the container to let users select multiple options. Each click toggles the item. The indicator bar shows the count.
|
|
177
|
+
|
|
178
|
+
```html
|
|
179
|
+
<div class="options" data-multiselect>
|
|
180
|
+
<!-- same option markup — users can select/deselect multiple -->
|
|
181
|
+
</div>
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### Cards (visual designs)
|
|
185
|
+
|
|
186
|
+
```html
|
|
187
|
+
<div class="cards">
|
|
188
|
+
<div class="card" data-choice="design1" onclick="toggleSelect(this)">
|
|
189
|
+
<div class="card-image"><!-- mockup content --></div>
|
|
190
|
+
<div class="card-body">
|
|
191
|
+
<h3>Name</h3>
|
|
192
|
+
<p>Description</p>
|
|
193
|
+
</div>
|
|
194
|
+
</div>
|
|
195
|
+
</div>
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### Mockup container
|
|
199
|
+
|
|
200
|
+
```html
|
|
201
|
+
<div class="mockup">
|
|
202
|
+
<div class="mockup-header">Preview: Dashboard Layout</div>
|
|
203
|
+
<div class="mockup-body"><!-- your mockup HTML --></div>
|
|
204
|
+
</div>
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### Split view (side-by-side)
|
|
208
|
+
|
|
209
|
+
```html
|
|
210
|
+
<div class="split">
|
|
211
|
+
<div class="mockup"><!-- left --></div>
|
|
212
|
+
<div class="mockup"><!-- right --></div>
|
|
213
|
+
</div>
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
### Pros/Cons
|
|
217
|
+
|
|
218
|
+
```html
|
|
219
|
+
<div class="pros-cons">
|
|
220
|
+
<div class="pros"><h4>Pros</h4><ul><li>Benefit</li></ul></div>
|
|
221
|
+
<div class="cons"><h4>Cons</h4><ul><li>Drawback</li></ul></div>
|
|
222
|
+
</div>
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### Mock elements (wireframe building blocks)
|
|
226
|
+
|
|
227
|
+
```html
|
|
228
|
+
<div class="mock-nav">Logo | Home | About | Contact</div>
|
|
229
|
+
<div style="display: flex;">
|
|
230
|
+
<div class="mock-sidebar">Navigation</div>
|
|
231
|
+
<div class="mock-content">Main content area</div>
|
|
232
|
+
</div>
|
|
233
|
+
<button class="mock-button">Action Button</button>
|
|
234
|
+
<input class="mock-input" placeholder="Input field">
|
|
235
|
+
<div class="placeholder">Placeholder area</div>
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
### Typography and sections
|
|
239
|
+
|
|
240
|
+
- `h2` — page title
|
|
241
|
+
- `h3` — section heading
|
|
242
|
+
- `.subtitle` — secondary text below title
|
|
243
|
+
- `.section` — content block with bottom margin
|
|
244
|
+
- `.label` — small uppercase label text
|
|
245
|
+
|
|
246
|
+
## Browser Events Format
|
|
247
|
+
|
|
248
|
+
When the user clicks options in the browser, their interactions are recorded to `$STATE_DIR/events` (one JSON object per line). The file is cleared automatically when you push a new screen.
|
|
249
|
+
|
|
250
|
+
```jsonl
|
|
251
|
+
{"type":"click","choice":"a","text":"Option A - Simple Layout","timestamp":1706000101}
|
|
252
|
+
{"type":"click","choice":"c","text":"Option C - Complex Grid","timestamp":1706000108}
|
|
253
|
+
{"type":"click","choice":"b","text":"Option B - Hybrid","timestamp":1706000115}
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
The full event stream shows the user's exploration path — they may click multiple options before settling. The last `choice` event is typically the final selection, but the pattern of clicks can reveal hesitation or preferences worth asking about.
|
|
257
|
+
|
|
258
|
+
If `$STATE_DIR/events` doesn't exist, the user didn't interact with the browser — use only their terminal text.
|
|
259
|
+
|
|
260
|
+
## Design Tips
|
|
261
|
+
|
|
262
|
+
- **Scale fidelity to the question** — wireframes for layout, polish for polish questions
|
|
263
|
+
- **Explain the question on each page** — "Which layout feels more professional?" not just "Pick one"
|
|
264
|
+
- **Iterate before advancing** — if feedback changes current screen, write a new version
|
|
265
|
+
- **2-4 options max** per screen
|
|
266
|
+
- **Use real content when it matters** — for a photography portfolio, use actual images (Unsplash). Placeholder content obscures design issues.
|
|
267
|
+
- **Keep mockups simple** — focus on layout and structure, not pixel-perfect design
|
|
268
|
+
|
|
269
|
+
## File Naming
|
|
270
|
+
|
|
271
|
+
- Use semantic names: `platform.html`, `visual-style.html`, `layout.html`
|
|
272
|
+
- Never reuse filenames — each screen must be a new file
|
|
273
|
+
- For iterations: append version suffix like `layout-v2.html`, `layout-v3.html`
|
|
274
|
+
- Server serves newest file by modification time
|
|
275
|
+
|
|
276
|
+
## Cleaning Up
|
|
277
|
+
|
|
278
|
+
```bash
|
|
279
|
+
scripts/stop-server.sh $SESSION_DIR
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
If the session used `--project-dir`, mockup files persist in `.superpowers/brainstorm/` for later reference. Only `/tmp` sessions get deleted on stop.
|
|
283
|
+
|
|
284
|
+
## Reference
|
|
285
|
+
|
|
286
|
+
- Frame template (CSS reference): `scripts/frame-template.html`
|
|
287
|
+
- Helper script (client-side): `scripts/helper.js`
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: debugging-game-feel
|
|
3
|
+
description: Use when a gameplay feature works correctly but feels wrong — floaty jumps, mushy combat, sluggish camera, weightless impacts. Different from logical bug debugging; the bug is subjective and lives in tuning, timing, and feedback layers.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Debugging Game Feel
|
|
7
|
+
|
|
8
|
+
## Overview
|
|
9
|
+
|
|
10
|
+
"Works but feels wrong" is its own debugging discipline. The code is correct. No diagnostic flags it. The unit tests pass. And yet the jump is floaty, the sword has no weight, the camera lags the player, the dash is unsatisfying.
|
|
11
|
+
|
|
12
|
+
**Core principle:** Game-feel bugs are tuning bugs, not logic bugs. Treat them with discipline — isolate one variable, compare to a reference, measure what you can, feel what you can't.
|
|
13
|
+
|
|
14
|
+
This skill is for the diagnostic phase. The polish-and-juice layer (screen shake, hit-stop, particles, sound design) is `summer:visual-effects/game-feel` — go there once you've identified WHICH variable is wrong.
|
|
15
|
+
|
|
16
|
+
## When To Use
|
|
17
|
+
|
|
18
|
+
- The user says: "feels floaty", "feels mushy", "feels off", "feels sluggish", "doesn't feel right", "lacks impact", "lacks weight", "doesn't feel satisfying".
|
|
19
|
+
- The feature passes `summer:playtesting-a-feature` (no errors, golden path runs) but still doesn't feel right.
|
|
20
|
+
- You're tuning movement, combat, camera, or any interaction with frame-level timing.
|
|
21
|
+
|
|
22
|
+
## When NOT To Use
|
|
23
|
+
|
|
24
|
+
- The feature has a **concrete reproducible bug** — go to `summer:investigating-bugs`.
|
|
25
|
+
- The feature **crashes or throws** — go to `summer:debug`.
|
|
26
|
+
- The feature **hasn't been built yet** — design it via `summer:brainstorming` first.
|
|
27
|
+
|
|
28
|
+
## The Iron Law
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
ONE VARIABLE AT A TIME. ALWAYS.
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Game-feel debugging is the place where engineers most often violate this rule, because each variable is a small tweak. "Let me bump acceleration AND friction AND max speed all together" produces a result you cannot reason about. You learn nothing. The bug returns.
|
|
35
|
+
|
|
36
|
+
## The Loop
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
Anchor → Isolate → Tweak one variable → Compare → Decide → Repeat
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### 1. Anchor: name the reference
|
|
43
|
+
|
|
44
|
+
Before touching any value, decide what "right" feels like. Game feel is subjective; without an anchor, you are debugging air.
|
|
45
|
+
|
|
46
|
+
Two ways to anchor:
|
|
47
|
+
|
|
48
|
+
| Anchor type | When to use | Example |
|
|
49
|
+
|---|---|---|
|
|
50
|
+
| **Reference game footage** | The user has a target in mind (Hollow Knight jumps, Dark Souls weight, Hades dashes) | "Match the Hollow Knight jump arc — peak in ~0.25s, fall ~0.35s, terminal velocity around frame 30" |
|
|
51
|
+
| **Internal known-good** | An older build / a sibling feature in the same game already feels right | "The pistol fires snappy. Make the rifle feel as snappy as the pistol minus the recovery frames." |
|
|
52
|
+
|
|
53
|
+
Write the anchor down in one sentence. If the user can't articulate it, ask. "What game does this remind you of when it's working?" is a fast way to extract the reference.
|
|
54
|
+
|
|
55
|
+
### 2. Isolate: name the suspect variable
|
|
56
|
+
|
|
57
|
+
Game-feel bugs almost always live in one of a small set of axes. Pick the most likely one first.
|
|
58
|
+
|
|
59
|
+
| Domain | Common suspect variables |
|
|
60
|
+
|---|---|
|
|
61
|
+
| Jump | gravity, jump velocity, terminal velocity, coyote-time window, jump-buffer window, variable-jump cutoff, apex hang time |
|
|
62
|
+
| Run | acceleration, max speed, friction (ground vs air), deceleration on input release, turn-around speed |
|
|
63
|
+
| Combat hit | hit-stop duration (attacker), hit-stop duration (target), screen shake amplitude + duration, knockback velocity + decay, recovery frames |
|
|
64
|
+
| Camera | follow lag (lerp factor or spring stiffness), lookahead distance, deadzone size, snap-vs-smooth on direction change |
|
|
65
|
+
| Dash | distance, duration, ease curve, cooldown, i-frame window, end-lag |
|
|
66
|
+
| UI feedback | input-to-response frame count, tween duration, easing function, sound onset delay |
|
|
67
|
+
|
|
68
|
+
If you cannot pick one suspect: state the top two, pick the one you think is most likely (say which), tweak it, see if it moved the feel. Do not tweak both.
|
|
69
|
+
|
|
70
|
+
### 3. Tweak one variable
|
|
71
|
+
|
|
72
|
+
- Read the current value via `summer_inspect_node` or open the relevant `.tres` / `.gd` file.
|
|
73
|
+
- Change ONE value. Save.
|
|
74
|
+
- Trigger `summer_play` and walk the feature.
|
|
75
|
+
- Ask: did the feel move toward or away from the anchor?
|
|
76
|
+
|
|
77
|
+
### 4. Compare
|
|
78
|
+
|
|
79
|
+
Two compare modes:
|
|
80
|
+
|
|
81
|
+
**Feel:** subjective. The user (or you, if you have eyes on the screen) reports "warmer" or "colder." This is fine. Most game-feel work is felt, not measured.
|
|
82
|
+
|
|
83
|
+
**Measure:** objective. When the feel is ambiguous, drop down to frame counts.
|
|
84
|
+
|
|
85
|
+
| Question | Measurement |
|
|
86
|
+
|---|---|
|
|
87
|
+
| "Does the jump peak too fast?" | `print` the y-velocity in `_physics_process`, count frames from launch to peak |
|
|
88
|
+
| "Is the camera too laggy?" | `print` `camera.global_position - target.global_position` per frame |
|
|
89
|
+
| "Is the input dead?" | Log input event frame and resulting state-machine transition frame; subtract |
|
|
90
|
+
| "Is the hit-stop too short?" | Log frame at hit + frame at unfreeze |
|
|
91
|
+
|
|
92
|
+
The point of measurement is to ground the conversation in numbers when "feels off" stops being useful. You do not need to measure most tweaks — only the ambiguous ones.
|
|
93
|
+
|
|
94
|
+
### 5. Decide
|
|
95
|
+
|
|
96
|
+
After the tweak:
|
|
97
|
+
|
|
98
|
+
- **Felt closer to the anchor** → commit the change, move to the next suspect variable if the feel still isn't right.
|
|
99
|
+
- **Felt further** → revert the change, pick a different suspect variable.
|
|
100
|
+
- **No change in feel** → revert the change, you tweaked the wrong variable.
|
|
101
|
+
|
|
102
|
+
Never leave a tweak in the codebase that you couldn't tell did anything. It will compound with the next tweak and you will lose the thread.
|
|
103
|
+
|
|
104
|
+
## The Compounding Tweaks Trap
|
|
105
|
+
|
|
106
|
+
The most common failure mode in game-feel work:
|
|
107
|
+
|
|
108
|
+
```
|
|
109
|
+
Jump feels floaty.
|
|
110
|
+
Bump gravity from 980 → 1200. Still floaty.
|
|
111
|
+
Bump it to 1500. A bit better.
|
|
112
|
+
Also reduce jump velocity from 500 → 450.
|
|
113
|
+
Also tweak terminal velocity 1500 → 2000.
|
|
114
|
+
Also add a 3-frame coyote window because why not.
|
|
115
|
+
Now it feels... different. But the dash that used to feel great no longer does.
|
|
116
|
+
Try to undo? You don't remember the starting point.
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
**Antidote:**
|
|
120
|
+
|
|
121
|
+
1. Note the starting values before you begin.
|
|
122
|
+
2. One variable at a time.
|
|
123
|
+
3. After every tweak, ask: anchor closer or farther? If unsure, revert.
|
|
124
|
+
4. Commit small revertible changes — one variable per commit during a feel-tuning session. Easy to bisect.
|
|
125
|
+
|
|
126
|
+
## Feel Principles (Briefly)
|
|
127
|
+
|
|
128
|
+
Game feel rests on three small ideas. Most "feels wrong" bugs trace to one of these being undertuned:
|
|
129
|
+
|
|
130
|
+
| Principle | What it means | What it looks like when broken |
|
|
131
|
+
|---|---|---|
|
|
132
|
+
| **Anticipation** | A small wind-up before a big action | Sword swings feel like they "appear" instead of being thrown |
|
|
133
|
+
| **Follow-through** | The action continues past the input | Player snaps to a stop on input release — feels robotic |
|
|
134
|
+
| **Weight** | Visible cost to changing direction or stopping | Player turns on a dime at full speed — feels weightless |
|
|
135
|
+
|
|
136
|
+
These are diagnostic tools, not lecture material. When the user says "feels weightless," your suspect-variable shortlist is: deceleration on input release, friction, turn-around speed, animation cross-fade time.
|
|
137
|
+
|
|
138
|
+
## Red Flags — STOP
|
|
139
|
+
|
|
140
|
+
| Red flag | Reality |
|
|
141
|
+
|---|---|
|
|
142
|
+
| Tweaking 2+ variables in one play session without reverting between | You will lose the signal. |
|
|
143
|
+
| "Let me just feel it out without an anchor" | You will tune in circles. Name the reference. |
|
|
144
|
+
| "The user said floaty so I'm jacking gravity" | "Floaty" can also mean weak air control, slow terminal velocity, or too-long apex hang. Confirm before tweaking. |
|
|
145
|
+
| Skipping the play step ("I'll just bump the number and trust the feel") | Game feel is felt, not predicted. Play every tweak. |
|
|
146
|
+
| Adding "while I'm here" tweaks to unrelated features | Game feel debugging is a focused activity. Stay on the one feature. |
|
|
147
|
+
| Going to `summer:visual-effects/game-feel` before identifying the broken variable | Juice on top of a broken tuning makes the bug louder. Fix tuning first. |
|
|
148
|
+
| Spending >30 minutes on one variable without progress | The anchor is wrong, or the variable is wrong. Step back, re-anchor. |
|
|
149
|
+
|
|
150
|
+
## Rationalization Prevention
|
|
151
|
+
|
|
152
|
+
| Excuse | Reality |
|
|
153
|
+
|---|---|
|
|
154
|
+
| "It's subjective — I'll just iterate fast" | Fast iteration without isolation is thrashing, not iteration. |
|
|
155
|
+
| "I know game feel, I don't need an anchor" | Even pros anchor. Especially pros anchor. |
|
|
156
|
+
| "Two variables are coupled, I have to tune them together" | Then tune one, ship that delta, tune the other separately. |
|
|
157
|
+
| "The user can't articulate the anchor" | "What game does this remind you of when it works?" — one question, anchor obtained. |
|
|
158
|
+
| "Adding juice will hide the bad tuning" | It won't. It amplifies it. |
|
|
159
|
+
|
|
160
|
+
## When To Escalate
|
|
161
|
+
|
|
162
|
+
After diagnosis pins down which variable(s) are wrong, the tuning is done — but the feature may still want polish. Hand off to:
|
|
163
|
+
|
|
164
|
+
- `summer:visual-effects/game-feel` — for the screen-shake, hit-stop, particle, sound layer once tuning is locked.
|
|
165
|
+
- `summer:debug` — if mid-debug you discover an actual error (signal not firing, node freed) hiding under the feel issue.
|
|
166
|
+
|
|
167
|
+
## The Bottom Line
|
|
168
|
+
|
|
169
|
+
Feel bugs are tuning bugs. Tuning is a one-variable-at-a-time discipline. Anchor to a reference. Tweak one number. Play it. Decide. Repeat.
|
|
170
|
+
|
|
171
|
+
**Related skills:**
|
|
172
|
+
- `summer:investigating-bugs` — for logical bugs with concrete repros, not feel.
|
|
173
|
+
- `summer:playtesting-a-feature` — the playtest discipline this skill plugs into.
|
|
174
|
+
- `summer:debug` — when the feel investigation surfaces an actual error.
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: diagnosing-perf-regressions
|
|
3
|
+
description: Use when frame rate, frame time, or load time has gotten worse since a known-good state — "it used to run at 60, now it's at 30." Focused on finding the cause of a regression, not general performance tuning.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Diagnosing Performance Regressions
|
|
7
|
+
|
|
8
|
+
## Overview
|
|
9
|
+
|
|
10
|
+
There is a difference between "this game is slow" and "this game got slow." This skill is for the second one.
|
|
11
|
+
|
|
12
|
+
**Core principle:** A regression has a cause. The cause is a specific change. Bisect to find the change, then root-cause from there.
|
|
13
|
+
|
|
14
|
+
This skill is **not** general performance tuning. If the game has always run at 30fps and you want to push it to 60, that is `summer:tune-performance` (the domain skill for budget-driven optimization). This skill is the diagnostic — what broke, where, when.
|
|
15
|
+
|
|
16
|
+
## When To Use
|
|
17
|
+
|
|
18
|
+
- "It used to run at 60fps, now it's at 30."
|
|
19
|
+
- "Load time was 3s yesterday, now it's 15s."
|
|
20
|
+
- "Frame stutters started after I added X."
|
|
21
|
+
- "Build went from buttery to choppy and I don't know why."
|
|
22
|
+
|
|
23
|
+
## When NOT To Use
|
|
24
|
+
|
|
25
|
+
- "The game has always been slow, help me speed it up." → `summer:tune-performance`.
|
|
26
|
+
- "I want to know if my game is fast enough to ship." → `summer:tune-performance`.
|
|
27
|
+
- "The game crashes." → `summer:debug`.
|
|
28
|
+
|
|
29
|
+
## The Iron Law
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
NO PERF FIX WITHOUT A KNOWN-GOOD vs KNOWN-BAD MEASUREMENT
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
You cannot fix a regression you have not measured. Eyeballing "feels laggy" is not a measurement. Get a number for the good state and a number for the bad state before touching code.
|
|
36
|
+
|
|
37
|
+
## The Loop
|
|
38
|
+
|
|
39
|
+
```
|
|
40
|
+
Measure now → Find last good → Bisect changes → Match to a cliff → A/B fix → Re-measure
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### 1. Measure now
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
summer_play (on the scene that's slow)
|
|
47
|
+
── wait 5-10 seconds of normal play ──
|
|
48
|
+
summer_get_diagnostics
|
|
49
|
+
summer_get_console
|
|
50
|
+
summer_stop
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
What to capture:
|
|
54
|
+
|
|
55
|
+
| Metric | Source | Why |
|
|
56
|
+
|---|---|---|
|
|
57
|
+
| Avg FPS / frame time | `summer_get_diagnostics` or in-game perf monitor | Headline number |
|
|
58
|
+
| Spike pattern | `summer_get_console` if user has frame-time prints, else in-game monitor | Steady 30 vs intermittent stutters → different causes |
|
|
59
|
+
| Scene complexity | `summer_get_scene_tree` (root counts) | Establishes baseline for instance/body count cliffs |
|
|
60
|
+
|
|
61
|
+
Write the bad-state number down. "Scene `Level3` runs at 31fps avg, drops to 12fps when 5+ enemies are on screen."
|
|
62
|
+
|
|
63
|
+
### 2. Find the last known-good state
|
|
64
|
+
|
|
65
|
+
Ask the user: when did it last run well? Then go to the VCS:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
git log --oneline --since="<last good date>" --until="now"
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
If they can name a commit ("it was fine on Monday's build"), check that out and measure it the same way. You now have:
|
|
72
|
+
|
|
73
|
+
- Known good: commit X, scene `Level3`, 60fps avg.
|
|
74
|
+
- Known bad: HEAD, scene `Level3`, 31fps avg.
|
|
75
|
+
|
|
76
|
+
If they can't name a date: ask for the rough window, list the commits, ask which ones are likely candidates. Do not bisect blind across 200 commits.
|
|
77
|
+
|
|
78
|
+
### 3. Bisect the changes
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
git log --oneline <last-good>..HEAD
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Read the list. Group commits into suspects:
|
|
85
|
+
|
|
86
|
+
| Likely culprit | Why |
|
|
87
|
+
|---|---|
|
|
88
|
+
| Big asset imports (.glb, textures, audio) | GPU memory, draw-call count |
|
|
89
|
+
| New shaders or material changes | Compilation stalls, overdraw, pipeline switches |
|
|
90
|
+
| Scene additions (enemies, props, lights) | Physics-body count, instance count, light count |
|
|
91
|
+
| `_process` / `_physics_process` additions | CPU per-frame cost |
|
|
92
|
+
| Signal connections in tight loops | Hidden per-frame cost |
|
|
93
|
+
| Particle systems | GPU + CPU |
|
|
94
|
+
| `@tool` scripts running in editor | Misleading editor FPS |
|
|
95
|
+
| Resource preload changes | First-use stalls |
|
|
96
|
+
|
|
97
|
+
If a single commit is the obvious suspect (e.g. "Added 200 enemies to spawner"), test it first. Otherwise actually `git bisect` — check out the midpoint, measure FPS, repeat. Don't theorize through it; the bisect is fast and definitive.
|
|
98
|
+
|
|
99
|
+
### 4. Match to one of the four Godot perf cliffs
|
|
100
|
+
|
|
101
|
+
Godot 4.x regressions cluster heavily into four categories. Knowing them shortens diagnosis to minutes.
|
|
102
|
+
|
|
103
|
+
| Cliff | Symptom | How to verify | Common cause |
|
|
104
|
+
|---|---|---|---|
|
|
105
|
+
| **Too many physics bodies** | FPS scales inversely with on-screen actor count, no GPU pressure | Count active `CharacterBody`/`RigidBody`/`Area` nodes; FPS doubles when half are queue_freed | Spawner with no upper cap; bullets/particles using physics bodies; collision layers too broad |
|
|
106
|
+
| **Shader compilation stalls** | First-frame or first-effect-fire stutter, then smooth; only on shipped builds, not editor | Frame-time spike on first cast/shot; clean after; `OS.has_feature("editor")` differences | New shader added; `unique` material not pre-warmed; pipeline cache not built |
|
|
107
|
+
| **GPU instance count / draw calls** | Steady low FPS, scales with what's on screen, no CPU pressure | RenderingServer perf monitors show high draw call count; FPS recovers when camera looks away | Forgot to enable MultiMeshInstance; unique materials per instance breaking instancing; too-detailed LOD0 |
|
|
108
|
+
| **Transparent overdraw** | FPS tanks when looking at smoke, fire, foliage, glass — fine otherwise | Look at the offending region, FPS drops; look away, recovers | New particle effect with large quads; transparent UI over the viewport; fog/volumetrics |
|
|
109
|
+
|
|
110
|
+
If the bad-state symptom matches one row, you have your hypothesis. Verify by reverting just the change you suspect and re-measuring.
|
|
111
|
+
|
|
112
|
+
### 5. A/B with one variable
|
|
113
|
+
|
|
114
|
+
This is the most violated step. Discipline:
|
|
115
|
+
|
|
116
|
+
- **Revert one suspect commit** (or stub the suspect feature behind a flag).
|
|
117
|
+
- Rebuild / reload the scene.
|
|
118
|
+
- Measure FPS the same way you did in step 1.
|
|
119
|
+
- Compare to known-bad. Did it recover?
|
|
120
|
+
|
|
121
|
+
If yes → root cause confirmed. Now decide: fix the change, or accept the perf cost.
|
|
122
|
+
If no → that wasn't it. Restore. Try the next suspect.
|
|
123
|
+
|
|
124
|
+
**Never** revert multiple changes at once during diagnosis. You will not know which one was the cause, and the bug will return on the next merge.
|
|
125
|
+
|
|
126
|
+
### 6. Re-measure after the fix
|
|
127
|
+
|
|
128
|
+
The fix is not done until the same measurement that found the regression returns the good number. Same scene, same play duration, same warm-up.
|
|
129
|
+
|
|
130
|
+
```
|
|
131
|
+
summer_clear_console
|
|
132
|
+
summer_play
|
|
133
|
+
── 5-10 seconds of play ──
|
|
134
|
+
summer_get_diagnostics
|
|
135
|
+
summer_stop
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
State the result with the number: "Reverted the per-frame `get_tree().get_nodes_in_group()` call in `enemy_manager.gd`. Level3 back to 58fps avg." Not "should be faster now."
|
|
139
|
+
|
|
140
|
+
## When To Escalate
|
|
141
|
+
|
|
142
|
+
| Situation | Go to |
|
|
143
|
+
|---|---|
|
|
144
|
+
| Regression confirmed and root cause known, but the fix is "make the feature cheaper" rather than "undo the change" | `summer:tune-performance` for the optimization pass |
|
|
145
|
+
| The regression turns out to be a crash or error in disguise (the slow path is throwing exceptions in a tight loop) | `summer:debug` |
|
|
146
|
+
| The cause is a Godot version change or engine-side regression | Surface to the user; this is not a project-side fix |
|
|
147
|
+
| Bisect lands on a commit that touches 40 files | Subdivide the commit: check out the commit, revert subsets, re-measure |
|
|
148
|
+
|
|
149
|
+
## Red Flags — STOP
|
|
150
|
+
|
|
151
|
+
| Red flag | Reality |
|
|
152
|
+
|---|---|
|
|
153
|
+
| "Just optimize the whole scene" | That's tuning, not regression diagnosis. Find what changed first. |
|
|
154
|
+
| Reverting 3 commits at once to "see if it helps" | You learn nothing. Revert one. |
|
|
155
|
+
| Eyeballing "feels slow" without measuring | You will optimize the wrong thing. Get a number. |
|
|
156
|
+
| Skipping the known-good measurement | Without a baseline, you don't know when you're done. |
|
|
157
|
+
| Reading the slow scene's code top-to-bottom looking for inefficiency | The regression is in what changed, not in what was already there. |
|
|
158
|
+
| Adding caching / pooling / LOD before identifying the cause | These are tuning moves. They can hide the regression instead of fixing it. |
|
|
159
|
+
| Trusting editor FPS as ground truth | Editor runs `@tool` scripts, debug overlays, and a different render pipeline. Measure in a built or `--game` run when possible. |
|
|
160
|
+
| "Maybe it's just a Tuesday thing" | Performance does not regress randomly. There is a cause. |
|
|
161
|
+
|
|
162
|
+
## Rationalization Prevention
|
|
163
|
+
|
|
164
|
+
| Excuse | Reality |
|
|
165
|
+
|---|---|
|
|
166
|
+
| "User wants it fixed now, no time to bisect" | Bisect is 5-15 minutes. Blind optimization can burn a day. |
|
|
167
|
+
| "The slow commit is obvious, no need to A/B" | The "obvious" cause is wrong ~30% of the time. Verify before fixing. |
|
|
168
|
+
| "I'll measure after I fix it" | If you don't have the bad number, you can't prove the fix worked. |
|
|
169
|
+
| "It's probably just Godot" | Engine-side regressions exist but are rare. Suspect your project first. |
|
|
170
|
+
| "Adding a pool / LOD / cache will help anyway" | Premature optimization on the wrong system is wasted work. |
|
|
171
|
+
|
|
172
|
+
## When The Engine Isn't Running
|
|
173
|
+
|
|
174
|
+
If `summer_play` is unavailable:
|
|
175
|
+
|
|
176
|
+
1. Ask the user for an in-game perf overlay screenshot (FPS, frame time, draw call count).
|
|
177
|
+
2. Walk the bisect logically with them: "Run on commit X, tell me the FPS. Run on commit Y, tell me the FPS."
|
|
178
|
+
3. Do not claim a fix is verified from code reading alone.
|
|
179
|
+
|
|
180
|
+
## The Bottom Line
|
|
181
|
+
|
|
182
|
+
A regression is a delta. Diagnose the delta, not the codebase.
|
|
183
|
+
|
|
184
|
+
Measure now. Measure last-good. Bisect what changed. Match to a Godot perf cliff. A/B one variable. Re-measure. Done.
|
|
185
|
+
|
|
186
|
+
**Related skills:**
|
|
187
|
+
- `summer:tune-performance` — for general optimization once the regression is fixed or when no regression exists.
|
|
188
|
+
- `summer:investigating-bugs` — when the slow path turns out to be a logic bug (errors in a tight loop).
|
|
189
|
+
- `summer:debug` — when the perf issue is actually a crash or freeze.
|
|
190
|
+
- `summer:verification-before-completion` — to claim the fix worked, with numbers.
|