Skip to content

Commit 094c806

Browse files
UnbreakableMJclaude
andcommitted
skills: add spacecraft-gtk-guidelines and spacecraft-qt-guidelines; Standard §13 → v1.42
Construct had no GUI-toolkit skill. A GTK or Qt request fell back on generic C/C++ advice and lost everything toolkit-specific — GObject reference semantics, GTK's main-thread-only rule, QObject parent-child ownership, the signal/slot lifetime traps — with no steer toward the memory-safe binding layer §3.1 requires. - spacecraft-gtk-guidelines: GTK 4, Rust-first. gtk-rs is the §3.1 memory-safe alternative, so C GTK now requires a filed exemption plus ASLR+CFI. references/Spacecraft_GTK_Rust_Guidelines.md covers GObject subclassing, glib::clone! weak capture against reference cycles, main-thread affinity and the gio::spawn_blocking handoff, GtkAccessible plus the AccessKit boundary for custom-drawn surfaces, @define-color theming, and Flatpak/portal sandboxing. references/Spacecraft_GTK_C_Guidelines.md is a full peer chapter: floating references and g_object_ref_sink, g_autoptr/g_clear_object, GWeakRef over the non-thread-safe g_object_weak_ref, and hardened Meson. - spacecraft-qt-guidelines: Qt 6.8 LTS floor, Rust-first via CXX-Qt 0.9.x with an explicit coverage boundary — custom QWidget painting, QAccessibleInterface, and most non-core modules stay C++. Three references: the CXX-Qt bridge path, the C++ surface (single ownership, deleteLater, context-object connects, worker-object threading, named QMutexLocker), and QML (the JS-GC vs QObject double-ownership crash, qmllint gates, Accessible attached properties). - Standard §13 → v1.42. §13 required Material Design for "all graphical applications", which no GTK or Qt application could satisfy — neither ships a Material component set — so both were unpassable at the §16 audit gate. Rewritten around the requirement that carries the intent: declare exactly one component system and follow it, chosen by platform. Material stays the default where the platform supplies none, so nothing compliant under v1.41 becomes non-compliant. §11 token binding, WCAG 2.2 AA, and §18 supremacy unchanged. §16 bullet and Skill Cross-References updated; description 976/1000 (§5.6). - spacecraft-theme-factory: GTK 4 CSS (@define-color) and Qt QSS/QPalette/ Theme.qml added to Output Targets and the emit-format list; stale v1.39 masthead corrected. Registered in README §2. All four bundles rebuilt. Description cap, REUSE lint, config validation, and the full drift sweep pass. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent 7b2215c commit 094c806

19 files changed

Lines changed: 2171 additions & 8 deletions

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ the rules re-attached to every prompt.
5050
| [`spacecraft-flutterdart-guidelines`](spacecraft-flutterdart-guidelines/) | Type-safe highly-concurrent Flutter & Dart guidance — Sound Null Safety (avoiding `!`), multithreaded isolate task loops (`Isolate.run`), event-loop concurrency, Flutter rendering checks (`const` caching and `RepaintBoundary`), widget testing, and explicit controller disposal. |
5151
| [`spacecraft-gleam-guidelines`](spacecraft-gleam-guidelines/) | Type-safe fault-tolerant Gleam-on-the-BEAM guidance — gleam_otp 1.x typed actors and static/factory supervision, `Subject` message passing, `Result`/`use` error flow, exhaustive `case`, `@external` FFI discipline, gleeunit/qcheck/birdie testing, and the `gleam format --check` / `build --warnings-as-errors` gates. |
5252
| [`spacecraft-golang-guidelines`](spacecraft-golang-guidelines/) | High-performance concurrent Go guidance — goroutines, channels, errgroup, context cancellation, atomics, `sync.Pool`, pprof / race-detector workflow, and memory-safe parallelism patterns. |
53+
| [`spacecraft-gtk-guidelines`](spacecraft-gtk-guidelines/) | Memory-safe GTK 4 desktop guidance, Rust-first — `gtk-rs` GObject subclassing and composite templates, `glib::clone!` weak capture against reference cycles, main-thread affinity with `gio::spawn_blocking` handoff, `GtkAccessible` names and roles plus the AccessKit boundary for custom-drawn surfaces, `@define-color` theming, Flatpak/portal sandboxing, and a full C fallback chapter (`g_autoptr`, floating references, `GWeakRef`). |
5354
| [`spacecraft-java-guidelines`](spacecraft-java-guidelines/) | Type-safe concurrent Java guidance — Virtual Threads (Project Loom), structured concurrency (`StructuredTaskScope`), avoiding thread pinning, garbage collection tuning (Generational ZGC), try-with-resources resource safety, and immutable records. |
5455
| [`spacecraft-kotlin-guidelines`](spacecraft-kotlin-guidelines/) | Type-safe highly-concurrent Kotlin guidance — structured concurrency, `supervisorScope` failure isolation, injected dispatchers (`IO`/`Default`/`Main`), null safety (avoiding `!!`), Exposed ORM transaction boundaries, and functional `Either` error mappers. |
5556
| [`spacecraft-lua-guidelines`](spacecraft-lua-guidelines/) | Expert guidelines for writing memory-safe, high-performance, and concurrent Lua code (targeting Lua 5.1/LuaJIT and Lua 5.4+) — local variables, table performance, metatable-based OOP, coroutine event loops, and LuaCATS. |
@@ -61,6 +62,7 @@ the rules re-attached to every prompt.
6162
| [`spacecraft-nu-guidelines`](spacecraft-nu-guidelines/) | Expert guidelines for writing high-performance, clean, and type-safe Nushell (Nu) script code — structured data pipelines, variables and mutability, custom commands, environment management, and error handling. |
6263
| [`spacecraft-ocamel-guidelines`](spacecraft-ocamel-guidelines/) | Type-safe highly-concurrent OCaml guidance — direct-style I/O fibers via `Eio` and Domainslib task parallelism pools, Saturn lock-free structures, Software Transactional Memory with Kcas, C FFI memory safety (`CAMLparam`/`CAMLlocal`/`CAMLreturn`), and warning-as-errors compilation flags. |
6364
| [`spacecraft-python-guidelines`](spacecraft-python-guidelines/) | Type-safe highly-concurrent Python guidance (targeting Python 3.12+) — strict static typing (`mypy`), boundary validation (`Pydantic v2`), non-blocking asynchronous event loops (`asyncio`), multiprocess CPU scaling (`ProcessPoolExecutor`), memory-optimized slots classes, and Ruff linting rules. |
65+
| [`spacecraft-qt-guidelines`](spacecraft-qt-guidelines/) | Memory-safe Qt 6 desktop guidance, Rust-first — CXX-Qt bridges for logic and QML models with an honest coverage boundary, `QObject` single-ownership discipline, `deleteLater` and context-object connect rules, worker-object threading (never a `QThread` subclass), named `QMutexLocker` guards, `QAccessibleInterface` for custom paint, `QPalette`/QSS theming, and QML↔C++ ownership. |
6466
| [`spacecraft-rust-guidelines`](spacecraft-rust-guidelines/) | High-performance concurrent Rust guidance — concurrency model selection, lock-free synchronisation, memory layout, tooling gates, and unsafe hygiene — plus a distilled idiom layer (`references/idioms.md`, adapted from Apollo's Rust Best Practices, MIT) covering borrowing, clippy discipline, testing, dispatch, and type-state. |
6567
| [`spacecraft-standard-constitution`](spacecraft-standard-constitution/) | Authoritative compliance reference (The Steelbore Standard). |
6668
| [`spacecraft-swift-guidelines`](spacecraft-swift-guidelines/) | Type-safe highly-concurrent Swift guidance (targeting Swift 6.2+) — Swift 6.2 concurrency, explicit `@concurrent` background offloading, isolated conformances, `@MainActor` isolated ViewModels, Swift Testing `@Suite` and `@Test` parameterized checks, and ARC reference cycle safety. |

spacecraft-gtk-guidelines.skill

20.4 KB
Binary file not shown.

spacecraft-gtk-guidelines.zip

20.6 KB
Binary file not shown.

spacecraft-gtk-guidelines/SKILL.md

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
---
2+
name: spacecraft-gtk-guidelines
3+
description: Use for writing memory-safe GTK 4 desktop applications following Spacecraft Software standards, preferring Rust gtk-rs over C. Triggers on any request involving GTK, GTK4, gtk-rs, gtk4-rs, libadwaita, GObject subclassing, glib::clone!, composite templates, GtkApplication, GtkBuilder, Blueprint, GtkAccessible, GNOME HIG, Flatpak, .desktop files, g_autoptr, g_object_ref_sink, floating references, GWeakRef, or GTK main-loop threading. Trigger even when implicit, e.g. "write a GTK window", "port this GTK 3 widget", "run work off the GTK main thread", or "theme a GNOME app". Rust is the default implementation; C GTK requires a documented Standard §3.1 exemption. Do NOT trigger for Qt (use spacecraft-qt-guidelines) or Flutter unless interoperability is explicitly requested. By Mohamed Hammad and Spacecraft Software.
4+
license: GPL-3.0-or-later
5+
maintainer: Mohamed Hammad <Mohamed.Hammad@SpacecraftSoftware.org>
6+
website: https://Construct.SpacecraftSoftware.org/
7+
---
8+
9+
# Spacecraft GTK 4 Guidelines
10+
11+
**Maintainer:** Mohamed Hammad | **Contact:** [Mohamed.Hammad@SpacecraftSoftware.org](mailto:Mohamed.Hammad@SpacecraftSoftware.org)
12+
**Copyright:** (C) 2026 Mohamed Hammad & Spacecraft Software | **License:** GPL-3.0-or-later
13+
**Website:** [https://Construct.SpacecraftSoftware.org/](https://Construct.SpacecraftSoftware.org/)
14+
15+
**You are an expert GTK 4 desktop engineer at Spacecraft Software specializing in memory-safe, accessible, GNOME-native applications built on the `gtk-rs` Rust bindings.** Always follow these rules when writing or reviewing GTK code. Never deviate. This skill is fully compatible with Claude 3.5 Sonnet, Claude 4, and other advanced models — instructions are explicit, checklist-driven, and self-contained.
16+
17+
> [!IMPORTANT]
18+
> **Rust is the default implementation language for GTK 4.** Load `microsoft-rust-guidelines` first for any Rust work — it is the mandatory Rust base and has higher dominance on Rust API and library design. For the C fallback path, `spacecraft-clang-guidelines` has higher dominance on C hardening, bounded flow, and CMake configuration; this skill adds only the GObject-specific layer on top of it.
19+
20+
## Core Philosophy
21+
- **Stability and Safety first (Standard §3 Priority 1).** GTK is a C library with manual reference counting, so the safety boundary is the binding layer. `gtk-rs` **is** the memory-safe-language alternative for GTK: it wraps GObject refcounting in `Drop`, makes the main-thread restriction a `!Send` type error, and eliminates the floating-reference and use-after-unref classes outright. Because that MSL alternative exists, **writing new GTK code in C requires a documented technical exemption plus ASLR and CFI** (§3.1). Rust is the default; C is the justified exception.
22+
- **Then Performance (Priority 2).** GTK renders through GSK on a single main loop. A frame budget of 16.6 ms (60 Hz) or 8.3 ms (120 Hz) is never spent on I/O, parsing, or computation — that work moves off the main thread and results return by channel. Concurrency here is architectural, not retrofitted (§3.2).
23+
- **Main-Thread Affinity is Absolute.** Every GTK and GDK object is main-thread-only. Widgets are never touched from a worker. Workers own data, not widgets, and communicate results back through `async_channel` or `glib::MainContext::spawn_local`.
24+
- **Accessible by Construction (Standard §18).** Every interactive widget carries an explicit accessible name and role before it ships. Decorative widgets are explicitly marked presentational. This is a build requirement, not a polish pass.
25+
26+
## Memory Safety & Ownership
27+
- **Reference cycles are the GTK memory bug.** A widget holding a closure that holds a strong reference back to the widget never drops. In Rust, always capture with `glib::clone!(#[weak] obj, move |…| …)` — the weak upgrade is attempted per invocation and the callback is skipped if the object is gone. Use `#[strong]` only when the closure must genuinely keep the object alive, and justify it in a comment.
28+
- **Signal handlers outlive naive expectations.** A handler connected to a long-lived object (a `GSettings`, an application-level action, a model) keeps its closure alive for that object's lifetime. Store the `SignalHandlerId` and disconnect on teardown, or connect with `connect_*_local` on an object whose lifetime already bounds it.
29+
- **C path — floating references.** A freshly constructed `GInitiallyUnowned` (every widget) carries a *floating* reference. Parenting sinks it. A widget constructed and never parented is **leaked**, not freed — `g_object_unref` on a floating reference does not release it. Sink explicitly with `g_object_ref_sink` when taking ownership outside a container.
30+
- **C path — `g_autoptr` everywhere.** Declare with `g_autoptr(GtkWidget)` / `g_autofree` so scope exit releases. Use `g_clear_object` rather than a bare `g_object_unref` followed by a stale pointer.
31+
- **C path — `GWeakRef`, not `g_object_weak_ref`.** `g_object_weak_ref` and `g_object_add_weak_pointer` are **not thread-safe**: they cannot safely be used from one thread when the final `g_object_unref` may happen on another. `GWeakRef` makes the weak-to-strong upgrade atomic with respect to invalidation. Prefer `g_signal_connect_object` over `g_signal_connect` so the handler dies with the object.
32+
- **Audit every `-sys` crate.** GTK pulls a large `-sys` dependency tree. Run `cargo audit` before adding any of them (§3.3, dependency auditing before third-party inclusion).
33+
34+
## Concurrency vs. Performance Tradeoffs
35+
- **When Concurrency Helps (Do Spawn / Channel):**
36+
- **Blocking I/O off the main loop:** `gio::spawn_blocking` for file, socket, and database work, with the result delivered back through `async_channel`.
37+
- **Main-context async tasks:** `glib::MainContext::spawn_local` for futures that must touch widgets on completion — it runs on the main thread, so the widget update is legal.
38+
- **Long computations on a worker:** `std::thread` or a Rayon pool owning plain data (never widgets), reporting progress by channel so the UI stays responsive.
39+
- **When Concurrency Hurts (Do NOT Touch / Block):**
40+
- **Widgets from a worker thread:** undefined behaviour in C, a compile error in `gtk-rs` because GTK types are `!Send`. Never work around it with `unsafe`.
41+
- **`glib::idle_add` where `idle_add_local` is required:** the `Send` variant may only be used for work that carries no main-thread-only data; the `_local` variants may only be called from the main thread. Mixing them is a latent crash.
42+
- **Blocking the main loop:** any synchronous call over ~5 ms on the main thread drops frames. `.await`-ing a blocking future on the main context blocks it just as hard as a sleep.
43+
- **Per-item thread spawning:** creating a thread per row, per file, or per frame costs more than the work. Use a pool.
44+
45+
## Mandatory Abstraction Choice
46+
Always choose the abstraction corresponding to the task:
47+
- **New GTK 4 application:** Rust with `gtk4` + `libadwaita`. This is the default, no justification needed.
48+
- **Existing C GTK codebase:** `spacecraft-clang-guidelines` hardening plus the GObject rules above, with the §3.1 exemption filed and ASLR + CFI enabled.
49+
- **UI definition:** Blueprint (`.blp`) compiled to `.ui`, or `.ui` directly, loaded as a composite template. Never build large widget trees imperatively.
50+
- **Design system:** libadwaita widgets following the GNOME HIG (Standard §13 admits platform-native design systems for native desktop toolkits).
51+
- **Accessibility bridge:** `GtkAccessible` for toolkit-native widgets; **AccessKit additionally** for any `GtkDrawingArea` or Cairo-painted custom surface (§18.3).
52+
- **Theme:** a named `steelbore` theme emitted as CSS `@define-color` tokens — never hex literals in widget code (§11.1).
53+
- **Packaging:** Flatpak manifest plus a `.desktop` entry and icons; file access through xdg-desktop-portal (§3.3 sandboxing).
54+
55+
## Required Techniques
56+
1. **Weak capture by default:** every closure connected to a widget signal captures with `glib::clone!(#[weak] …)`; `#[strong]` requires a written justification.
57+
2. **Composite templates:** define UI in `.blp`/`.ui` and bind with `#[template_child]`; validate with `gtk4-builder-tool validate` in CI.
58+
3. **Accessible name and role on every interactive widget:** `widget.update_property(&[Property::Label("Rebuild index")])` and `update_role(AccessibleRole::Presentation)` for decoration. Verify with Orca (§18.4).
59+
4. **Off-thread work returns by channel:** `gio::spawn_blocking` or a worker thread plus `async_channel`, consumed by `glib::MainContext::spawn_local`. Widgets are mutated only in the receiving arm.
60+
5. **Theme tokens only:** load `steelbore.css` with `@define-color` bindings; a bare hex literal in widget code or CSS is a §11.1 violation.
61+
6. **Version-gate feature flags:** declare the `gtk4` crate's `v4_10`/`v4_12`/`v4_16`/`v4_18` features explicitly rather than relying on whatever the host GTK provides.
62+
63+
## Build, Tooling & CI (Non-Negotiable)
64+
- **Toolchain floor:** GTK 4.10 minimum (4.18+ for the AccessKit backend on Windows/macOS); `gtk4` crate 0.11.x, Rust 1.83+ (the crate's MSRV); `libadwaita` 0.9.x.
65+
- **Rust gates:** `cargo clippy --all-targets -- -D warnings`, `cargo fmt --check`, `cargo audit`, `cargo test`.
66+
- **UI gates:** `gtk4-builder-tool validate` on every `.ui`; `blueprint-compiler format --check` on every `.blp`.
67+
- **C gates (fallback path):** everything in `spacecraft-clang-guidelines``-Wall -Wextra -Wpedantic -Werror`, ASan/UBSan in Debug, `clang-tidy`. Note every applied and every disabled optimization flag (§3.2), and remember §3.2.1: on NixOS, `-flto` requires `-fuse-ld=mold` (preferred) or `-fuse-ld=bfd`.
68+
- **Accessibility gate:** exercise the built application with Orca before release (§18.4).
69+
70+
## Anti-Patterns (Never Do These)
71+
- Touching any GTK or GDK object from a thread other than the main thread.
72+
- Capturing `self` or a widget strongly in a signal closure without a documented reason — this is the reference-cycle leak.
73+
- Constructing a widget in C and never parenting or `g_object_ref_sink`-ing it.
74+
- Using `g_object_weak_ref` / `g_object_add_weak_pointer` where the last unref may happen on another thread.
75+
- Blocking the main loop with synchronous I/O, parsing, or a `.await` on a blocking future.
76+
- Building large widget trees imperatively instead of with a composite template.
77+
- Shipping an icon-only button with no accessible name — it announces as "button" and nothing else.
78+
- Writing hex color literals into widget code or CSS instead of `steelbore` theme tokens.
79+
- Starting a new GTK project in C without filing the §3.1 exemption.
80+
81+
## Pre-Commit Checklist (Verify Every Time)
82+
- [ ] No GTK or GDK object is accessed off the main thread
83+
- [ ] Every signal closure captures weakly, or documents why it captures strongly
84+
- [ ] `SignalHandlerId`s connected to long-lived objects are disconnected on teardown
85+
- [ ] Blocking work runs on `gio::spawn_blocking` or a worker, returning by channel
86+
- [ ] Every interactive widget has an explicit accessible name and role; decoration is marked presentational
87+
- [ ] Custom-drawn surfaces (`GtkDrawingArea`, Cairo) publish an AccessKit tree
88+
- [ ] All colors come from `steelbore` theme tokens — no hex literals
89+
- [ ] `.ui` files pass `gtk4-builder-tool validate`
90+
- [ ] `cargo clippy -- -D warnings`, `cargo fmt --check`, and `cargo audit` are clean
91+
- [ ] C-path code has its §3.1 exemption filed and ASLR + CFI enabled
92+
- [ ] C-path code uses `g_autoptr`/`g_clear_object` and sinks floating references
93+
- [ ] Applied and disabled compiler flags are both documented (§3.2)
94+
95+
## References & Further Reading
96+
- Load `references/Spacecraft_GTK_Rust_Guidelines.md` for full Rust skeletons (GObject subclassing, `glib::clone!` weak capture, worker-plus-channel threading, accessibility, CSS theming, Flatpak packaging, CI gates).
97+
- Load `references/Spacecraft_GTK_C_Guidelines.md` for the C fallback path (`g_autoptr`, floating references, `GWeakRef`, hardened Meson/CMake).
98+
- Cross-reference `spacecraft-accessibility-support` for the §18 bridge table, activation contract, and audit gates — this skill does not restate them.
99+
- Cross-reference `steelbore-color-palette` for palette values and `spacecraft-theme-factory` for emitting `steelbore.css`. Never retype hex values from memory.
100+
- **Licensing (§4.2):** GTK 4 and libadwaita are `LGPL-2.1-or-later`; the `gtk4`, `glib`, and `libadwaita` Rust bindings are `MIT`. All are compatible with a `GPL-3.0-or-later` project. Preserve upstream notices and ship each distinct license text in `LICENSES/` (§4.3).
101+
- *Further reading* (consulted for background only): the GTK 4 API reference, the gtk4-rs book, the GObject reference manual, and the GNOME Human Interface Guidelines.
102+
103+
When the user requests GTK code or review, activate this skill, apply the checklist, and produce code a senior Spacecraft desktop engineer would ship.

0 commit comments

Comments
 (0)