This specification is maintained by the AgentRules Working Group. Have enhancements or want to claim maintainership?Submit Specification →
mobilecritical PriorityID: cmp-skiko-render-pass-budget-guardrail

Compose Multiplatform 1.8 Skiko Render-Pass Budget Guardrail

Enforces strict render-pass time budgets across heterogeneous refresh rates (60Hz, 120Hz ProMotion, and high-refresh desktop monitors) in Compose Multiplatform 1.8. Prevents frame-drop cascades and UI thread starvation by eliminating object allocations inside Skiko draw loops and isolating hardware canvas operations into cache-backed layers. Guards against cascading redraw triggers and non-deterministic VSync stalls in cross-platform render pipelines.

Prohibited Anti-Pattern: Unthrottled Intra-Draw Allocations and Direct Canvas Mutations Busting Skiko Frame Budgets

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: Compose Multiplatform 1.8 Skiko Render-Pass Budget Guardrail - Enforces strict render-pass time budgets across heterogeneous refresh rates (60Hz, 120Hz ProMotion, and high-refresh desktop monitors) in Compose Multiplatform 1.8. Prevents frame-drop cascades and UI thread starvation by eliminating object allocations inside Skiko draw loops and isolating hardware canvas operations into cache-backed layers. Guards against cascading redraw triggers and non-deterministic VSync stalls in cross-platform render pipelines.
globs: commonMain/**/*.kt, androidMain/**/*.kt, iosMain/**/*.kt, desktopMain/**/*.kt
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/cmp-skiko-render-pass-budget-guardrail"
---

# Compose Multiplatform 1.8 Skiko Render-Pass Budget Guardrail

> **Severity**: CRITICAL | **Category**: mobile
> **Anti-Pattern Warning**: Unthrottled Intra-Draw Allocations and Direct Canvas Mutations Busting Skiko Frame Budgets

## System Constraints
You are a Principal Engineer enforcing Compose Multiplatform 1.8 Skiko Render-Pass Budget Guardrails. Mandate absolute render-phase determinism across all supported targets (iOS, Android, Desktop, Web). Prevent frame-budget overruns (16.6ms at 60Hz, 8.3ms at 120Hz) by strictly prohibiting allocations in draw phases, enforcing graphicsLayer boundaries, and requiring drawWithCache for vector/path construction.

## Strict Guidelines
- Engineers MUST ALWAYS isolate complex vector paths, shaders, and text measurements inside Modifier.drawWithCache to reuse Skia Native allocations across frames.
- Engineers MUST NOT instantiate Path, Paint, Matrix, ColorFilter, or any heap-allocated drawing objects inside Modifier.drawBehind, Modifier.drawWithContent, or Custom Canvas blocks.
- Code MUST apply Modifier.graphicsLayer to rapidly mutating UI nodes (such as scroll indicators, progress animations, or gesture transforms) to avoid invalidating the root Skiko SkiaLayer render tree.
- Services and view models MUST NOT emit raw continuous touch or scroll events directly to render-invalidating Compose state without explicit frame-rate quantization or structural equality suppression via derivedStateOf.
- Components NEVER execute blocking I/O, synchronous resource decoding, or layout re-measurements within or directly driving the Skiko VSync dispatch loop.

## Bad vs Good Implementations
### Complex Canvas Rendering with Dynamic Paths

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: Instantiating Path and Stroke within the DrawScope creates high-frequency allocations on the Skiko render loop. At 120Hz, Skiko only has 8.33ms total for layout, draw, and GPU submission; allocating ephemeral objects triggers frequent GC pauses and disrupts display pacing.
```kotlin
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Path
import androidx.compose.ui.graphics.drawscope.Stroke

@Composable
fun PerformanceGraph(points: List<Float>, modifier: Modifier = Modifier) {
    // ANTI-PATTERN: Heap-allocating Path, Stroke, and points transformations on every
    // Skiko VSync frame trigger. Causes Skia garbage collection cascades and 120Hz ProMotion drops.
    Canvas(modifier = modifier.fillMaxSize()) {
        val path = Path() // Allocates on EVERY frame
        points.forEachIndexed { index, value ->
            val x = index * (size.width / (points.size - 1))
            val y = size.height - (value * size.height)
            if (index == 0) path.moveTo(x, y) else path.lineTo(x, y)
        }
        drawPath(
            path = path,
            color = Color.Green,
            style = Stroke(width = 4f) // Allocates on EVERY frame
        )
    }
}
```

#### Production Standard (Correct)
> **Standard**: Using drawWithCache isolates path construction so it only executes when sizes or dependencies change. The onDrawBehind block remains completely allocation-free, allowing Skiko to submit draw commands to the underlying Skia canvas well within the 8.33ms budget.
```kotlin
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.Spacer
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.drawWithCache
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Path
import androidx.compose.ui.graphics.drawscope.Stroke

@Composable
fun PerformanceGraph(points: List<Float>, modifier: Modifier = Modifier) {
    // PRODUCTION FIX: Hoist static configuration and leverage drawWithCache.
    // Reconstructs native path geometry ONLY when input dimensions or data change.
    val stroke = remember { Stroke(width = 4f) }

    Spacer(
        modifier = modifier
            .fillMaxSize()
            .drawWithCache {
                val path = Path()
                val stepX = if (points.size > 1) size.width / (points.size - 1) else 0f
                points.forEachIndexed { index, value ->
                    val x = index * stepX
                    val y = size.height - (value * size.height)
                    if (index == 0) path.moveTo(x, y) else path.lineTo(x, y)
                }
                onDrawBehind {
                    drawPath(path = path, color = Color.Green, style = stroke)
                }
            }
    )
}
```

Recommended MCP Servers (mcp-serverlist.com)

Equip agent with system tools to verify code for this stack.

Architectural Specification & Invariant Rationale

Architectural Invariant Design: Compose Multiplatform 1.8 Skiko Render-Pass Budget Guardrail

Compose Multiplatform 1.8 Skiko Render-Pass Budget Guardrail defines an industrial-grade behavioral standard for mobile engineering. Enforces strict render-pass time budgets across heterogeneous refresh rates (60Hz, 120Hz ProMotion, and high-refresh desktop monitors) in Compose Multiplatform 1.8. Prevents frame-drop cascades and UI thread starvation by eliminating object allocations inside Skiko draw loops and isolating hardware canvas operations into cache-backed layers. Guards against cascading redraw triggers and non-deterministic VSync stalls in cross-platform render pipelines. Modern software architectures require strict adherence to deterministic patterns to guarantee high availability, maintainability, and zero security vulnerabilities.

Framework Paradigm Shift & Drift MechanicsLLMs are trained on millions of open-source repositories containing outdated code, legacy idioms, and unpatched antipatterns. When coding assistants generate implementations for this stack, they default to common statistical tokens: Unthrottled Intra-Draw Allocations and Direct Canvas Mutations Busting Skiko Frame Budgets Without an explicit system instruction file, developers spend hours debugging silent failures.
Failure Modes & Production Blast Radius

Hazard Analysis: What Breaks Without This Rule

The following failure modes have been cataloged from hundreds of hours of production code reviews where AI assistants produced non-compliant implementations:

Failure ModeAI Symptom (The Anti-Pattern)SeverityProduction Impact & Remedy
AI Hallucination & Deprecation DriftUnthrottled Intra-Draw Allocations and Direct Canvas Mutations Busting Skiko Frame BudgetsCritical
Violating this industrial standard introduces regression bugs, security risks, and unexpected runtime failures in production.
Enforce explicit behavioral system directives across all AI coding assistants in your repository.
Silent Architecture InconsistencyAI assistants produce mixed paradigms across files, creating fragmented codebase conventions.Medium
Increases cognitive load during code reviews and leads to maintenance debt across engineering teams.
Pin project conventions in .cursor/rules, CLAUDE.md, and AGENTS.md so all team agents follow identical guardrails.
Architectural Directives in Detail

Step-by-Step Production Directives

Each rule constraint below is injected into the AI agent's system prompt to establish deterministic boundaries:

1

Engineers MUST ALWAYS isolate complex vector paths, shaders, and text measurements inside Modifier.drawWithCache to reuse Skia Native allocations across frames.

Engineers MUST ALWAYS isolate complex vector paths, shaders, and text measurements inside Modifier.drawWithCache to reuse Skia Native allocations across frames.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
2

Engineers MUST NOT instantiate Path, Paint, Matrix, ColorFilter, or any heap-allocated drawing objects inside Modifier.drawBehind, Modifier.drawWithContent, or Custom Canvas blocks.

Engineers MUST NOT instantiate Path, Paint, Matrix, ColorFilter, or any heap-allocated drawing objects inside Modifier.drawBehind, Modifier.drawWithContent, or Custom Canvas blocks.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
3

Code MUST apply Modifier.graphicsLayer to rapidly mutating UI nodes (such as scroll indicators, progress animations, or gesture transforms) to avoid invalidating the root Skiko SkiaLayer render tree.

Code MUST apply Modifier.graphicsLayer to rapidly mutating UI nodes (such as scroll indicators, progress animations, or gesture transforms) to avoid invalidating the root Skiko SkiaLayer render tree.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
4

Services and view models MUST NOT emit raw continuous touch or scroll events directly to render-invalidating Compose state without explicit frame-rate quantization or structural equality suppression via derivedStateOf.

Services and view models MUST NOT emit raw continuous touch or scroll events directly to render-invalidating Compose state without explicit frame-rate quantization or structural equality suppression via derivedStateOf.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
5

Components NEVER execute blocking I/O, synchronous resource decoding, or layout re-measurements within or directly driving the Skiko VSync dispatch loop.

Components NEVER execute blocking I/O, synchronous resource decoding, or layout re-measurements within or directly driving the Skiko VSync dispatch loop.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
Technical Questions & Answers

Frequently Asked Technical Questions

Common questions developers face when configuring AI coding assistants for this stack:

Q:Why is Compose Multiplatform 1.8 Skiko Render-Pass Budget Guardrail critical for AI coding assistants?

Enforces strict render-pass time budgets across heterogeneous refresh rates (60Hz, 120Hz ProMotion, and high-refresh desktop monitors) in Compose Multiplatform 1.8. Prevents frame-drop cascades and UI thread starvation by eliminating object allocations inside Skiko draw loops and isolating hardware canvas operations into cache-backed layers. Guards against cascading redraw triggers and non-deterministic VSync stalls in cross-platform render pipelines. Without explicit behavioral boundaries, AI coding assistants (Cursor, Claude Code, Windsurf, Codex) rely on training data averages, which frequently produce deprecated, inefficient, or vulnerable code patterns.

Q:How does adopting this rule prevent AI hallucinations?

This rule explicitly declares what the AI must avoid (Unthrottled Intra-Draw Allocations and Direct Canvas Mutations Busting Skiko Frame Budgets) and prescribes verified positive examples. Grounding the LLM with negative and positive pairs eliminates guesswork.

Q:Which AI coding environments are supported?

This specification is multi-platform compatible: Cursor (.cursor/rules/*.mdc & .cursorrules), Anthropic Claude Code (CLAUDE.md), Windsurf (.windsurfrules), Codex / Cline (AGENTS.md), and GitHub Copilot (.github/copilot-instructions.md).

Q:Can I combine this rule with other technology stacks?

Yes. Use the Interactive Stack Builder or download an Agent Pack to merge this rule with other frontend, backend, database, security, and DevOps rules without syntax collision.

Open Specification · CC BY 4.0·Free for Personal, Team & Commercial In-Repo Use

Citation & Open Source Attribution Guidelines

This specification is licensed under Creative Commons Attribution 4.0 International (CC BY 4.0). You are completely free to adapt and share this rule in your workspace. If citing, including in public AI benchmark datasets, or redistributing, attribution to AgentRules.org is required.

Related MOBILE Rules

View all rules →
1 Rule in Stack

Compose