Skip to main content

best-practices-kde

Repo-specific KDE/QML best practices for agentic coding: singleton design systems, property ordering, accessibility, performance (binding loops, delegate recycling), Plasma integration, and D-Bus patterns.

الانتقال إلى التثبيت

معلومات المصدر

المستودع
grahama1970/agent-stack-public
آخر نشاط في المصدر
٢٤ سبتمبر ٢٠٢٦ في ١٥:٥١
لغة SKILL.md المكتشفة
الإنجليزية
النجوم
٠
التفرعات
٠

خيارات التثبيت

يُحدَّد Prompt الذي يراجع المصدر أولًا بشكل افتراضي. يمكنك التبديل إلى أمر مباشر أو تنزيل نسخة محلية.

مراجعة ملفات المصدر

اقرأ SKILL.md وأي ملفات مرافقة يعرضها SkillsMP قبل أن تقرر التثبيت.

مستكشف الملفات
2 ملفات

عرض SKILL.md

SKILL.md
تعليمات المصدر · معاينة للقراءة فقط
name
best-practices-kde
description
Repo-specific KDE/QML best practices for agentic coding: singleton design systems, property ordering, accessibility, performance (binding loops, delegate recycling), Plasma integration, and D-Bus patterns.
triggers
["best practices kde","qml review","kde plasma","plasmoid","dbus pattern"]
license
MIT
metadata
{"language":"qml","qt_versions":["6.x"],"defaults":{"style":{"max_lines_per_file":600,"design_system":"singleton","property_ordering":"required","accessibility":"required"},"performance":{"avoid_binding_loops":true,"delegate_recycling":true,"shader_effects_gpu_only":true},"integration":{"dbus":"required","plasma_hig":"recommended"}}}
provides
["best-practices-kde"]
composes
["task-monitor","agentic-evals"]
disciplines
["engineering-standards","ui-design-engineering"]
# KDE / QML Best Practices (Project Skill) Curated rules for writing and reviewing QML in this repo's KDE surface area (primarily `apps/horus-overlay/`). ## When to Apply Use this skill whenever you: - create or modify `.qml` files - add or change KDE Plasma integration (D-Bus, KWin scripts, global shortcuts) - design plugin UIs for the overlay system - review accessibility or keyboard navigation in QML ## Project Defaults - **Design System:** Use a `pragma Singleton` style object (e.g. `HorusStyle.qml`) — never hard-code colors, sizes, or animation durations - **Property Ordering:** Follow the canonical order (see below) - **Accessibility:** Every interactive element needs `Accessible.name`, `Accessible.role`, and `Accessible.description` - **File Size:** No QML file over **600** lines — extract delegates, sub-components, and style objects - **Effects:** `MultiEffect` / `layer.effect` only when GPU-composited; disable on software renderers ## Property Ordering (within a QML type) ```qml Item { // 1. id id: root // 2. Custom properties (readonly first, then mutable) readonly property string label: "Hello" property int count: 0 // 3. Sizing & geometry width: 200; height: 100 // 4. Anchors / Layout properties anchors.fill: parent Layout.fillWidth: true // 5. Visual properties (color, opacity, radius, clip, z, visible) color: HorusStyle.colors.bg opacity: 1.0 visible: true // 6. Behaviors & Transitions Behavior on opacity { NumberAnimation { duration: HorusStyle.anim.fast } } // 7. Signals signal clicked(string itemId) // 8. Signal handlers (on*) onVisibleChanged: { /* ... */ } // 9. Functions function doSomething() { /* ... */ } // 10. Child items (deepest nesting last) Text { text: root.label } } ``` ## Categories (priority order) 1. Correctness (CRITICAL): `correctness-` 2. Accessibility (HIGH): `a11y-` 3. Performance (HIGH): `perf-` 4. Design System (HIGH): `design-` 5. Integration (MEDIUM): `integration-` 6. Style & Maintainability (MEDIUM): `style-` ## Rules ### `design-singleton-style` **Impact: HIGH** — All colors, spacing, typography, and animation durations MUST come from the singleton design system (`HorusStyle`). Hard-coded hex colors in component files are a violation. ```qml // ❌ BAD color: "#1e293b" font.pixelSize: 14 // ✅ GOOD color: HorusStyle.colors.bgElevated font.pixelSize: HorusStyle.text.bodySize ``` ### `design-token-completeness` **Impact: MEDIUM** — When adding a new visual concept, add the token to `HorusStyle.qml` first, then reference it. Don't add ad-hoc `property color` declarations in leaf components. ### `a11y-interactive-elements` **Impact: HIGH** — Every `Button`, `MouseArea` acting as a button, `TextField`, and `ListView` MUST declare: - `Accessible.name` — concise label - `Accessible.role` — correct semantic role - `Accessible.description` — context for screen readers (optional for obvious elements) ```qml Button { Accessible.name: "Stop recording" Accessible.role: Accessible.Button Accessible.description: "Stops the current voice recording" } ``` ### `a11y-keyboard-navigation` **Impact: HIGH** — All primary flows must be operable via keyboard: - `Tab` / `Shift+Tab` for focus cycling - `Enter` / `Return` for activation - `Escape` for dismissal - Arrow keys within lists (`keyNavigationEnabled: true`) - Visible focus indicators (border or glow on `activeFocus`) ### `perf-binding-loops` **Impact: CRITICAL** — Never create circular property bindings. If the QML engine warns `"Binding loop detected"`, it's a hard error. ```qml // ❌ BAD — width depends on child, child depends on parent width width: childItem.implicitWidth + 20 // ... where childItem has: width: parent.width - 40 // ✅ GOOD — break the loop with explicit sizing or implicitWidth implicitWidth: childItem.implicitWidth + 20 ``` ### `perf-delegate-recycling` **Impact: HIGH** — `ListView` and `GridView` delegates MUST be lightweight: - No `Component.onCompleted` with heavy logic - Prefer model role bindings over imperative JS in delegates - Use `cacheBuffer` for off-screen pre-loading - Set `clip: true` on the view ### `perf-layer-effects` **Impact: MEDIUM** — `layer.enabled` and `MultiEffect` force GPU texture allocation. Guard with a condition: ```qml layer.enabled: someCondition // not always-on layer.effect: MultiEffect { shadowEnabled: true // ... } ``` ### `perf-canvas-repaint` **Impact: MEDIUM** — `Canvas.onPaint` is CPU-bound. Minimize repaints: - Only call `requestPaint()` when data actually changes - Avoid repainting on every frame (use a timer or data-change signal) ### `integration-dbus` **Impact: MEDIUM** — Use D-Bus for communication between the QML frontend and Python backend. Follow patterns: - Register well-known names under `org.openclaw.*` - Use `QDBusConnection::sessionBus()` (not system bus) for user-scope services - Expose properties via D-Bus properties interface for external tooling ### `integration-global-shortcuts` **Impact: MEDIUM** — Register global shortcuts via KGlobalAccel, not raw X11/Wayland grabs. This ensures they appear in System Settings and respect user overrides. ### `style-max-600-lines` **Impact: MEDIUM** — QML files over 600 lines should be decomposed: - Extract reusable delegates into separate `.qml` files - Extract complex sub-layouts into components - Keep the design system singleton as a separate file ### `style-signal-naming` **Impact: LOW** — Signal names should be verb phrases: `clicked`, `toggled`, `dataReceived`. Avoid noun-only signals like `data` or `result`. ### `correctness-null-guards` **Impact: HIGH** — Guard against `undefined` / `null` model data in delegates and dynamic property access: ```qml text: model.title || "" visible: (model.items && model.items.length > 0) || false ``` ## Skill-App Pattern Any skill needing a GUI beyond TUI should launch a **KDE app** matching the Tauri app's design system. This creates **agent accountability** — when the agent says "I trained the voice model," a human opens the same skill's GUI and verifies visually. The GUI is the audit surface that prevents hallucination. ### Convention - **Launch via** `./run.sh gui` — every skill with a GUI exposes this command - **Framework:** PySide6 + QML with `EmbryStyle.qml` design tokens (singleton) - **Tab-based navigation** with `tab-registry.json` (matching the Tauri `tab-registry.json` pattern) - **Keyboard shortcuts** per tab (number keys 1-9 switch tabs) - **EmbryParticles** as universal state indicator (header or sidebar) - **Accessible:** all interactive elements have `Accessible.name` + `Accessible.role` - **Agent-invocable:** `./run.sh gui --tab <id>` opens a specific panel for human review - **Two bridges pattern:** skills with multiple concerns register separate QObject bridges (e.g. `editorBridge` + `guiBridge`), each as a named context property — never merge ### File Layout ``` skill-name/ qml/ SkillNameApp.qml # ApplicationWindow with header, tab bar, StackLayout tab-registry.json # Tab config: groups, shortcuts, voice keywords EmbryStyle.qml # Symlink or copy of the shared design system PageOne.qml # Tab content pages PageTwo.qml app.py # Unified launcher (registers bridges, loads App.qml) run.sh # ./run.sh gui, ./run.sh gui --tab <id> ``` ### Shared Mic Pattern When multiple bridges need mic input, **one bridge owns pw-record** and others read from it via `set_mic_source(owner_bridge)`. This avoids duplicate PipeWire readers. ### Reference Implementation See `voice-lab/` for the canonical example: `VoiceLabApp.qml` with 4 tabs across 2 groups, shared mic meter, two coexisting bridges. ## Quick Reference (house rules) - `design-singleton-style` - `design-token-completeness` - `a11y-interactive-elements` - `a11y-keyboard-navigation` - `perf-binding-loops` - `perf-delegate-recycling` - `perf-layer-effects` - `perf-canvas-repaint` - `integration-dbus` - `integration-global-shortcuts` - `style-max-600-lines` - `style-signal-naming` - `correctness-null-guards`
عرض على GitHub