change-the-window
Skill33 starsChanged 27 days agoApache-2.0View on GitHub
Work on deck's GPUI window — crates/app. Use before touching view.rs, pane.rs, chart.rs, pill.rs or prose.rs, or when a change makes the window crash, makes a picture vanish, or makes something land in the wrong place. Four mistakes account for nearly every bug this window has had, and three of them abort the process rather than failing.
In this repository4 other files it gives its agents.
- AGENTS.mdAGENTS.md
- change-the-protocolSkill
- change-the-skillSkill
- cut-a-releaseSkill
The file
We split this skill into the rules it gives an agent
4 rules. About 0 are common, 3 are distinctive, and 1 is very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈3
Distinctive · estimate
This author's own choices. Worth a look.
1
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 34
If you see panic_cannot_unwind in a crash report, this is what happened.
- Distinctive: line 58
Before adding a wrapper, ask whether you can hang the position off something already there.
- Distinctive: line 68
If a click is being answered by the wrong element, the order things were added in is the first place to look.
- Distinctive: line 83
Keep the length fixed and vary the contents.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Changing the window
deck-app is GPUI. It has a few sharp edges that do not
announce themselves, and the same four have caused nearly every bug in here.
Never read the window during render
A pane asking the entity that is drawing it is a second borrow of something
already borrowed, and it aborts the process rather than failing. It usually
aborts inside a mouse handler, which is an extern "C" callback that cannot
unwind — so nothing catches it and deck dies.
// This killed every deck with a diagram in it.
let pace = view.upgrade().map_or(Pace::Normal, |deck| deck.read(cx).pace());Everything a pane needs is handed down through Slot — the palette, its share
of the row, the playback speed. Add a field there instead.
Handlers are fine. on_click calling deck.update(...) runs later, when the
borrow has been released. It is only reading during render that is fatal.
If you see panic_cannot_unwind in a crash report, this is what happened.
div() is display: block
This has eaten a diagram twice.
A block div is only as wide as its content and gives its children no height
to fill. So a child asking for size_full gets nothing, and a child that was
being centred stops being centred. Wrapping something in a plain div() to hang
a position off is the exact move that breaks it:
// The drawing inside this had no height and disappeared.
div().relative().child(self.render_drawing(...))
// It needs to be a flex row, and at least as big as the pane.
div()
.relative()
.flex()
.min_w(relative(1.))
.min_h(relative(1.))
.child(self.render_drawing(...))Before adding a wrapper, ask whether you can hang the position off something already there. The flow buttons ended up anchored to the pane itself for exactly this reason.
Bubble-phase handlers run in reverse registration order
An overlay painted after a list answers first, and can call
stop_propagation. Several behaviours here depend on that ordering rather than
on hit-testing, and HitboxBehavior::Normal does not occlude anything.
If a click is being answered by the wrong element, the order things were added in is the first place to look.
A list whose length changes between frames
with_animations keeps the index of the running animation in element state and
indexes the list with it on the next frame. A list that gets shorter between
frames is an index past the end, and deck aborts.
// Two while writing, one when finished. It crashed the moment a deck
// was sealed, because that is when the flag flipped.
if writing { vec![arrive, pulse] } else { vec![arrive] }Keep the length fixed and vary the contents. A zero-length animation with a constant easing is a held frame and asks for nothing further.
Verifying a change
You cannot screenshot the window from a script, and synthetic clicks do not reach it. There is no flag that opens a deck without a person pressing Open, and adding one is not the answer — that was removed on purpose.
So:
D=$(cargo run -q -p deck-app -- new --title "Checking a change" --total 1)
cargo run -q -p deck-app -- group "$D" --say "Here." --ref "src/main.rs:1-10 the change"
cargo run -q -p deck-app -- seal "$D"
cargo run -q -p deck-app -- open "$D"A bar appears. Ask the person you are working with to press Open and say what they see. Do not claim a visual change works because it compiled. If you could not see it, say so.
One thing you can check from a script — that the window survived being opened, which catches the aborts above:
sleep 3 && ps -Ao args | grep -c "[d]eck open $D"Crash reports
macOS writes them, and they name the failure precisely:
F=$(ls -t ~/Library/Logs/DiagnosticReports/deck-*.ips | head -1)The first line is JSON metadata and the rest is a second JSON document. The
faulting thread's frames are usually enough: panic_bounds_check is an index
past the end, panic_cannot_unwind is a borrow inside a handler.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

