diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json index c75259f..34aa46b 100644 --- a/.claude-plugin/plugin.json +++ b/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "compose-expert", - "version": "2.3.0", + "version": "2.3.1", "description": "Compose and Compose Multiplatform expert skill — state, animations, navigation, performance, design-to-code, PR review mode, M3 motion.", "author": { "name": "Adit Lal", diff --git a/.copilot/plugin.yaml b/.copilot/plugin.yaml index 9980e39..61c0a79 100644 --- a/.copilot/plugin.yaml +++ b/.copilot/plugin.yaml @@ -1,5 +1,5 @@ name: compose-expert -version: 2.3.0 +version: 2.3.1 description: > Compose and Compose Multiplatform expert skill — state, animations, navigation, performance, design-to-code, PR review mode, M3 motion. diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c4906b8..124d1b1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,6 +22,9 @@ jobs: - name: Validate plugin manifest schema run: bash scripts/validate-plugin-manifest.sh + - name: Check SKILL.md description length (Codex/Copilot 1024-char cap) + run: bash scripts/check-description-length.sh + - name: Run manifest schema tests run: bats scripts/validate-plugin-manifest.bats diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f2d1b3f..7511500 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -22,6 +22,9 @@ jobs: - name: Validate plugin manifest schema run: bash scripts/validate-plugin-manifest.sh + - name: Check SKILL.md description length (Codex/Copilot 1024-char cap) + run: bash scripts/check-description-length.sh + - name: Assert version consistency run: bash scripts/check-versions.sh "${GITHUB_REF_NAME}" diff --git a/CHANGELOG.md b/CHANGELOG.md index b67fde7..391ac94 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,33 @@ All notable changes to this project will be documented in this file. +## [2.3.1] - 2026-05-03 + +### Fixed + +- **`SKILL.md` `description:` frontmatter no longer exceeds Codex / Copilot + CLI's 1024-character cap** (issue #12). Both hosts rejected the manifest + with `invalid description: exceeds maximum length of 1024 characters`. The + field is now 843 chars; Claude Code continues to load it identically. + +### Changed + +- Long trigger-keyword surface previously packed into the `description:` + field (TV phrases, casual phrasings, Compose Multiplatform symbol lists, + Review Mode triggers) is preserved in a new **`## When this skill applies`** + section in the SKILL.md body. Body content is not subject to the 1024-char + cap, so the keyword surface remains available to Claude after the skill + loads. + +### Added + +- **`scripts/check-description-length.sh`** — a regression check that + asserts the SKILL.md frontmatter `description:` is ≤ 1024 chars. +- Wired the new check into both `.github/workflows/ci.yml` (every PR) and + `.github/workflows/release.yml` (every tag push) so a future regression + fails CI loudly instead of shipping green on Claude Code and breaking + Codex / Copilot installs. + ## [2.3.0] - 2026-05-03 ### Added diff --git a/scripts/check-description-length.sh b/scripts/check-description-length.sh new file mode 100755 index 0000000..209542d --- /dev/null +++ b/scripts/check-description-length.sh @@ -0,0 +1,41 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Asserts the SKILL.md frontmatter `description:` field is <= 1024 characters. +# Codex CLI and Copilot CLI both reject the manifest when this field exceeds +# 1024 characters (see issue #12). Claude Code does not enforce the cap, so +# without this check a regression ships green on Claude and breaks downstream. + +SKILL_FILE="${1:-skills/compose-expert/SKILL.md}" +LIMIT=1024 + +if [[ ! -f "$SKILL_FILE" ]]; then + echo "FAIL: $SKILL_FILE not found" + exit 1 +fi + +# Extract the description: block from the frontmatter (between first two `---`). +# Handles both inline (`description: ...`) and folded (`description: >\n ...`) +# YAML forms. Stops at the next top-level frontmatter key. +desc=$(awk ' + /^---$/ { c++; next } + c == 1 && /^description:/ { + flag = 1 + sub(/^description: */, "") + print + next + } + c == 1 && flag && /^[a-zA-Z_]+:/ { exit } + c == 1 && flag { print } +' "$SKILL_FILE") + +len=${#desc} + +if (( len > LIMIT )); then + echo "FAIL: description is $len chars, exceeds $LIMIT-char Codex/Copilot limit" + echo " file: $SKILL_FILE" + echo " issue: https://github.com/aldefy/compose-skill/issues/12" + exit 1 +fi + +echo "OK: description is $len chars (limit $LIMIT)" diff --git a/scripts/check-versions.bats b/scripts/check-versions.bats index b282d6d..a427cf8 100644 --- a/scripts/check-versions.bats +++ b/scripts/check-versions.bats @@ -4,6 +4,9 @@ setup() { TEST_DIR=$(mktemp -d) cp -R "$BATS_TEST_DIRNAME/.." "$TEST_DIR/repo" cd "$TEST_DIR/repo" + # Read the current version from plugin.json so the test does not rot at + # every release. Tests verify the script's logic, not a fixed version. + CURRENT=$(jq -r .version .claude-plugin/plugin.json) } teardown() { @@ -11,21 +14,21 @@ teardown() { } @test "passes when all five versions match (tag passed as arg)" { - run bash scripts/check-versions.sh v2.1.2 + run bash scripts/check-versions.sh "v${CURRENT}" [ "$status" -eq 0 ] [[ "$output" == *"versions aligned"* ]] } @test "fails when plugin.json version diverges" { - sed -i.bak 's/"version": "2.1.2"/"version": "2.0.1"/' .claude-plugin/plugin.json - run bash scripts/check-versions.sh v2.1.2 + sed -i.bak "s/\"version\": \"${CURRENT}\"/\"version\": \"0.0.1\"/" .claude-plugin/plugin.json + run bash scripts/check-versions.sh "v${CURRENT}" [ "$status" -ne 0 ] [[ "$output" == *"plugin.json"* ]] } @test "fails when SKILL.md frontmatter version diverges" { - sed -i.bak 's/^version: 2.1.2$/version: 2.0.1/' skills/compose-expert/SKILL.md - run bash scripts/check-versions.sh v2.1.2 + sed -i.bak "s/^version: ${CURRENT}$/version: 0.0.1/" skills/compose-expert/SKILL.md + run bash scripts/check-versions.sh "v${CURRENT}" [ "$status" -ne 0 ] [[ "$output" == *"SKILL.md"* ]] } diff --git a/skills/compose-expert/SKILL.md b/skills/compose-expert/SKILL.md index 91e35e8..ea7b45f 100644 --- a/skills/compose-expert/SKILL.md +++ b/skills/compose-expert/SKILL.md @@ -1,27 +1,18 @@ --- name: compose-expert description: > - Compose and Compose Multiplatform expert skill for UI development across Android, Desktop, - iOS, and Web. Guides state management, view composition, animations, navigation, performance, - design-to-code workflows, and production crash patterns. Backed by actual source code analysis - from both androidx/androidx and JetBrains/compose-multiplatform-core. - Use this skill whenever the user mentions Compose, @Composable, remember, LaunchedEffect, - Scaffold, NavHost, MaterialTheme, LazyColumn, Modifier, recomposition, Style, styleable, - MutableStyleState, Compose Multiplatform, CMP, KMP, commonMain, expect, actual, - ComposeUIViewController, Window composable, UIKitView, ComposeViewport, Res.drawable, - Res.string, or any Compose API. Also trigger when the user says "Android UI", "Kotlin UI", - "compose layout", "compose navigation", "compose animation", "material3", "compose styles", - "compose multiplatform", "desktop compose", "iOS compose", "compose web", "design to compose", - "build this UI", "implement this design", "Android TV", "Google TV", "tv-material", - "tv-foundation", "Carousel", "NavigationDrawer", "D-pad", "focus indication", - "10-foot UI", "living room", "tv compose", "review this PR", "review this code", - "check this diff", or any GitHub PR URL (github.com/.*/pull/), - "design system", "component library", "atomic", "reusable component", - "design tokens", "atoms", "molecules", or asks about modern - Kotlin UI development patterns. Even casual mentions like "my compose screen is slow" - or "how do I pass data between screens" or "how do I build a TV app" should trigger this skill. - Also trigger on session_start to auto-detect Compose projects — see references/auto-init.md. -version: 2.3.0 + Compose and Compose Multiplatform expert for UI development across Android, Desktop, + iOS, and Web. Use whenever the user mentions Compose APIs (@Composable, remember, + LaunchedEffect, NavHost, MaterialTheme, LazyColumn, Modifier, recomposition), + Compose Multiplatform (commonMain, expect/actual, Res.*, ComposeUIViewController, + UIKitView, ComposeViewport), Android TV (tv-material, D-pad, focus, Carousel), + Material 3 motion, atomic design systems, design-to-code workflows, Paging 3, or + navigation. Activates Review Mode on GitHub PR URLs and review phrases ("review + this PR", "what's wrong with this"). Auto-detects Compose projects on + session_start. Backed by actual androidx/androidx and JetBrains/compose-multiplatform-core + source receipts. See "## When this skill applies" in SKILL.md for the full trigger + surface. +version: 2.3.1 --- > **Installation notice:** This skill is now distributed as a plugin. @@ -34,6 +25,57 @@ version: 2.3.0 > See [MIGRATION.md](../docs/MIGRATION.md) for Codex and Copilot CLI instructions. > This banner will remain through v2.x and escalate in v3.0. +## When this skill applies + +The frontmatter `description:` is intentionally short to satisfy Codex / Copilot +CLI's 1024-character cap on that field (see issue #12). The full trigger surface +lives here so it stays available to Claude after the skill loads. + +### Compose API mentions +`@Composable`, `remember`, `mutableStateOf`, `derivedStateOf`, `rememberSaveable`, +`LaunchedEffect`, `DisposableEffect`, `SideEffect`, `rememberCoroutineScope`, +`Scaffold`, `NavHost`, `NavController`, `MaterialTheme`, `ColorScheme`, +`Typography`, `LazyColumn`, `LazyRow`, `LazyVerticalGrid`, `HorizontalPager`, +`Modifier`, `Modifier.Node`, `recomposition`, `CompositionLocal`, `Style`, +`styleable`, `MutableStyleState`. + +### Compose Multiplatform / KMP +`Compose Multiplatform`, `CMP`, `KMP`, `commonMain`, `expect`, `actual`, +`ComposeUIViewController`, `Window` composable, `UIKitView`, `ComposeViewport`, +`Res.drawable`, `Res.string`, `SkikoMain`. + +### Android TV +`tv-material`, `tv-foundation`, `Carousel`, `NavigationDrawer` (TV), +`D-pad`, `focus indication`, `FocusRequester` on TV, `10-foot UI`, +`living room`, `tv compose`, `Android TV`, `Google TV`, `leanback migration`. + +### Paging 3 +`PagingSource`, `Pager`, `PagingConfig`, `PagingData`, `LazyPagingItems`, +`collectAsLazyPagingItems`, `RemoteMediator`, `LoadState`, +`asSnapshot`, `TestPager`, `cachedIn`. + +### Design system / design-to-code +`atomic design`, `atoms`, `molecules`, `organisms`, `templates`, +`design tokens`, `design system`, `component library`, `reusable component`, +`Figma to Compose`, `design to compose`, `build this UI`, `implement this design`, +`spec to code`, `redline`. + +### Casual phrasing +"my compose screen is slow", "my recomposition is broken", +"how do I pass data between screens", "how do I build a TV app", +"Android UI", "Kotlin UI", "compose layout", "compose navigation", +"compose animation", "compose styles", "desktop compose", "iOS compose", +"compose web". + +### Review Mode triggers +Any GitHub PR URL matching `github.com/.*/pull/\d+`, or phrases: +"review this PR", "review this diff", "review this code", +"check this code", "check this diff", "what's wrong with this". +On match, follow `references/pr-review.md` exclusively. + +### Session start +Auto-detect Compose projects on `session_start` — see `references/auto-init.md`. + ## Quick Routing Use this table first. Match the user's signal to one reference file and read it before